All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylesDocument Maven / Gradle / Ivy

There is a newer version: 2.0.6
Show newest version
/**
 * Copyright (C) 2011-2015 The XDocReport Team 
 *
 * All rights reserved.
 *
 * Permission is hereby granted, free  of charge, to any person obtaining
 * a  copy  of this  software  and  associated  documentation files  (the
 * "Software"), to  deal in  the Software without  restriction, including
 * without limitation  the rights to  use, copy, modify,  merge, publish,
 * distribute,  sublicense, and/or sell  copies of  the Software,  and to
 * permit persons to whom the Software  is furnished to do so, subject to
 * the following conditions:
 *
 * The  above  copyright  notice  and  this permission  notice  shall  be
 * included in all copies or substantial portions of the Software.
 *
 * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
 * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
 * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package fr.opensagres.poi.xwpf.converter.xhtml.internal.styles;

import static fr.opensagres.poi.xwpf.converter.xhtml.internal.XHTMLConstants.P_ELEMENT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.XHTMLConstants.SPAN_ELEMENT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.XHTMLConstants.TABLE_ELEMENT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.XHTMLConstants.TD_ELEMENT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.XHTMLConstants.TR_ELEMENT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.BACKGROUND_COLOR;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.COLOR;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.FONT_FAMILY;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.FONT_SIZE;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.FONT_STYLE;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.FONT_STYLE_ITALIC;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.FONT_WEIGHT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.FONT_WEIGHT_BOLD;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.HEIGHT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.MARGIN_LEFT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.MARGIN_RIGHT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.MARGIN_BOTTOM;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.MARGIN_TOP;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.MIN_HEIGHT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.TEXT_ALIGN;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.TEXT_ALIGN_CENTER;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.TEXT_ALIGN_JUSTIFIED;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.TEXT_ALIGN_LEFT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.TEXT_ALIGN_RIGHT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.TEXT_DECORATION;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.TEXT_DECORATION_UNDERLINE;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.TEXT_INDENT;
import static fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylePropertyConstants.WIDTH;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPrBase;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTextDirection;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTrPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTextDirection;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

import fr.opensagres.poi.xwpf.converter.core.Color;
import fr.opensagres.poi.xwpf.converter.core.TableHeight;
import fr.opensagres.poi.xwpf.converter.core.TableWidth;
import fr.opensagres.poi.xwpf.converter.core.styles.XWPFStylesDocument;
import fr.opensagres.poi.xwpf.converter.core.utils.StringUtils;
import fr.opensagres.poi.xwpf.converter.core.utils.XWPFUtils;
import fr.opensagres.poi.xwpf.converter.xhtml.internal.XHTMLConstants;
import fr.opensagres.poi.xwpf.converter.xhtml.internal.utils.SAXHelper;

public class CSSStylesDocument
    extends XWPFStylesDocument
{

    private static final String CR = "\n";

    private static final String PT_UNIT = "pt";

    private static final Object PERCENT_UNIT = "%";

    private List cssStyles;

    private final boolean ignoreStylesIfUnused;

    private final Integer indent;

    public CSSStylesDocument( XWPFDocument document, boolean ignoreStylesIfUnused, Integer indent )
        throws XmlException, IOException
    {
        super( document, false );
        this.ignoreStylesIfUnused = ignoreStylesIfUnused;
        this.indent = indent;
        this.initialize();
    }

    @Override
    protected void initialize()
        throws XmlException, IOException
    {
        // default paragraph
        CSSStyle defaultPStyle = new CSSStyle( P_ELEMENT, null );
        defaultPStyle.addProperty( MARGIN_TOP, "0pt" );
        defaultPStyle.addProperty( MARGIN_BOTTOM, "1pt" );
        getCSSStyles().add( defaultPStyle );

        super.initialize();
    }

    @Override
    protected void visitStyle( CTStyle style, boolean defaultStyle )
    {
        String styleId = style.getStyleId();
        if ( StringUtils.isNotEmpty( styleId ) )
        {
            String className = getClassName( styleId );
            visitStyle( className, style.getPPr(), defaultStyle );
            visitStyle( className, style.getRPr(), defaultStyle );
            visitStyle( className, style.getTblPr(), defaultStyle );
            visitStyle( className, style.getTrPr(), defaultStyle );
            visitStyle( className, style.getTcPr(), defaultStyle );
        }
    }

    // -------------------------------- Paragraph styles

    /**
     * @param className
     * @param pPr
     * @param defaultStyle
     */
    private void visitStyle( String className, CTPPr pPr, boolean defaultStyle )
    {
        CSSStyle style = createCSSStyle( pPr, className );
        if ( style != null )
        {
            getCSSStyles().add( style );
        }
    }

    public CSSStyle createCSSStyle( CTPPr pPr )
    {
        return createCSSStyle( pPr, null );
    }

    public CSSStyle createCSSStyle( CTPPr pPr, String className )
    {
        if ( pPr != null )
        {
            String tagName = P_ELEMENT;
            CSSStyle style = ignoreStylesIfUnused ? null : getOrCreateStyle( null, tagName, className );
            
            // indentation left
            Float indentationLeft = super.getIndentationLeft( pPr );
            if ( indentationLeft != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( MARGIN_LEFT, getValueAsPoint( indentationLeft ) );
            }
            // indentation right
            Float indentationRight = super.getIndentationRight( pPr );
            if ( indentationRight != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( MARGIN_RIGHT, getValueAsPoint( indentationRight ) );
            }
            // indentation first line
            Float indentationFirstLine = super.getIndentationFirstLine( pPr );
            if ( indentationFirstLine != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( TEXT_INDENT, getValueAsPoint( indentationFirstLine ) );
            }

            // Aligment
            ParagraphAlignment alignment = super.getParagraphAlignment( pPr );
            if ( alignment != null )
            {
                switch ( alignment )
                {
                    case LEFT:
                        style = getOrCreateStyle( style, tagName, className );
                        style.addProperty( TEXT_ALIGN, TEXT_ALIGN_LEFT );
                        break;
                    case RIGHT:
                        style = getOrCreateStyle( style, tagName, className );
                        style.addProperty( TEXT_ALIGN, TEXT_ALIGN_RIGHT );
                        break;
                    case CENTER:
                        style = getOrCreateStyle( style, tagName, className );
                        style.addProperty( TEXT_ALIGN, TEXT_ALIGN_CENTER );
                        break;

                    case BOTH:
                        style = getOrCreateStyle( style, tagName, className );
                        style.addProperty( TEXT_ALIGN, TEXT_ALIGN_JUSTIFIED );
                        break;
                }
            }
            // Margin bottom/top
            Float spacingBefore = super.getSpacingBefore( pPr );
            if ( spacingBefore != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( MARGIN_TOP, getValueAsPoint( spacingBefore ) );
            }
            Float spacingAfter = super.getSpacingAfter( pPr );
            if ( spacingAfter != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( MARGIN_BOTTOM, getValueAsPoint( spacingAfter ) );
            }
            // Background color
            Color backgroundColor = super.getBackgroundColor( pPr );
            if ( backgroundColor != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( BACKGROUND_COLOR, XWPFUtils.toHexString( backgroundColor ) );
            }
            return style;
        }
        return null;
    }

    // -------------------------------- Run styles

    private void visitStyle( String className, CTRPr rPr, boolean defaultStyle )
    {

        CSSStyle style = createCSSStyle( rPr, className );
        if ( style != null )
        {
            getCSSStyles().add( style );
        }
    }

    public CSSStyle createCSSStyle( CTRPr rPr )
    {
        return createCSSStyle( rPr, null );
    }

    public CSSStyle createCSSStyle( CTRPr rPr, String className )
    {
        if ( rPr != null )
        {
            String tagName = SPAN_ELEMENT;
            CSSStyle style = ignoreStylesIfUnused ? null : getOrCreateStyle( null, tagName, className );

            // Font family
            String fontFamily = super.getFontFamilyAscii( rPr );
            if ( StringUtils.isNotEmpty( fontFamily ) )
            {
                fontFamily = new StringBuilder( "'" ).append( fontFamily ).append( "'" ).toString();
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( FONT_FAMILY, fontFamily );
            }
            // Font size
            Float fontSize = super.getFontSize( rPr );
            if ( fontSize != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( FONT_SIZE, getValueAsPoint( fontSize ) );
            }
            // Font Bold
            Boolean bold = super.getFontStyleBold( rPr );
            if ( bold != null && bold )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( FONT_WEIGHT, FONT_WEIGHT_BOLD );
            }
            // Font Italic
            Boolean italic = super.getFontStyleItalic( rPr );
            if ( italic != null && italic )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( FONT_STYLE, FONT_STYLE_ITALIC );
            }
            // Font color
            Color fontColor = super.getFontColor( rPr );
            if ( fontColor != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( COLOR, XWPFUtils.toHexString( fontColor ) );
            }
            // Underlines
            UnderlinePatterns underlinePatterns = super.getUnderline( rPr );
            if ( underlinePatterns != null )
            {
                switch ( underlinePatterns )
                {
                    case SINGLE:
                        style = getOrCreateStyle( style, tagName, className );
                        style.addProperty( TEXT_DECORATION, TEXT_DECORATION_UNDERLINE );
                        break;
                    default:
                        break;
                }
            }
            // Background color
            Color backgroundColor = super.getBackgroundColor( rPr );
            if ( backgroundColor != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( BACKGROUND_COLOR, XWPFUtils.toHexString( backgroundColor ) );
            }
            return style;
        }
        return null;
    }

    // -------------------------------- Table styles

    /**
     * @param className
     * @param tblPr
     * @param defaultStyle
     */
    private void visitStyle( String className, CTTblPrBase tblPr, boolean defaultStyle )
    {
        CSSStyle style = createCSSStyle( tblPr, className );
        if ( style != null )
        {
            getCSSStyles().add( style );
        }
    }

    public CSSStyle createCSSStyle( CTTblPrBase tblPr )
    {
        return createCSSStyle( tblPr, null );
    }

    public CSSStyle createCSSStyle( CTTblPrBase tblPr, String className )
    {
        if ( tblPr != null )
        {
            String tagName = TABLE_ELEMENT;
            CSSStyle style = ignoreStylesIfUnused ? null : getOrCreateStyle( null, tagName, className );

            TableWidth tableWidth = super.getTableWidth( tblPr );
            if ( tableWidth != null && tableWidth.width > 0 )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( WIDTH, getStyleWidth( tableWidth ) );
            }

            return style;
        }
        return null;
    }

    private String getStyleWidth( TableWidth tableWidth )
    {
        return tableWidth.percentUnit ? getValueAsPercent( tableWidth.width ) : getValueAsPoint( tableWidth.width );
    }

    // -------------------------------- Table row styles

    /**
     * @param className
     * @param trPr
     * @param defaultStyle
     */
    private void visitStyle( String className, CTTrPr trPr, boolean defaultStyle )
    {
        CSSStyle style = createCSSStyle( trPr, className );
        if ( style != null )
        {
            getCSSStyles().add( style );
        }
    }

    public CSSStyle createCSSStyle( CTTrPr trPr )
    {
        return createCSSStyle( trPr, null );
    }

    public CSSStyle createCSSStyle( CTTrPr trPr, String className )
    {
        if ( trPr != null )
        {
            String tagName = TR_ELEMENT;
            CSSStyle style = ignoreStylesIfUnused ? null : getOrCreateStyle( null, tagName, className );

            // min-height / height
            TableHeight tableHeight = super.getTableRowHeight( trPr );
            if ( tableHeight != null )
            {
                if ( tableHeight.minimum )
                {
                    style = getOrCreateStyle( style, tagName, className );
                    style.addProperty( MIN_HEIGHT, getValueAsPoint( tableHeight.height ) );
                }
                else
                {
                    style = getOrCreateStyle( style, tagName, className );
                    style.addProperty( HEIGHT, getValueAsPoint( tableHeight.height ) );
                }
            }
            return style;
        }
        return null;
    }

    // -------------------------------- Table cell styles

    /**
     * @param className
     * @param tcPr
     * @param defaultStyle
     */
    private void visitStyle( String className, CTTcPr tcPr, boolean defaultStyle )
    {
        CSSStyle style = createCSSStyle( tcPr, className );
        if ( style != null )
        {
            getCSSStyles().add( style );
        }
    }

    public CSSStyle createCSSStyle( CTTcPr tcPr )
    {
        return createCSSStyle( tcPr, null );
    }

    public CSSStyle createCSSStyle( CTTcPr tcPr, String className )
    {
        if ( tcPr != null )
        {
            String tagName = TD_ELEMENT;
            CSSStyle style = ignoreStylesIfUnused ? null : getOrCreateStyle( null, tagName, className );

            // cell width
            TableWidth cellWidth = super.getTableCellWith( tcPr );
            if ( cellWidth != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( WIDTH, getStyleWidth( cellWidth ) );
            }
            // background color
            Color backgroundColor = super.getTableCellBackgroundColor( tcPr );
            if ( backgroundColor != null )
            {
                style = getOrCreateStyle( style, tagName, className );
                style.addProperty( BACKGROUND_COLOR, XWPFUtils.toHexString( backgroundColor ) );
            }
            CTTextDirection direction = super.getTextDirection( tcPr );
            if ( direction != null )
            {
                // see http://www.css3maker.com/text-rotation.html
                int dir = direction.getVal().intValue();
                switch ( dir )
                {
                    case STTextDirection.INT_BT_LR:
                        style = getOrCreateStyle( style, tagName, className );
                        style.addProperty( "-webkit-transform", "rotate(270deg)" );
                        style.addProperty( "-moz-transform", "rotate(270deg)" );
                        style.addProperty( "-o-transform", "rotate(270deg)" );
                        style.addProperty( "writing-mode", "bt-lr" ); // For IE
                        break;
                    case STTextDirection.INT_TB_RL:
                        style = getOrCreateStyle( style, tagName, className );
                        style.addProperty( "-webkit-transform", "rotate(90deg)" );
                        style.addProperty( "-moz-transform", "rotate(90deg)" );
                        style.addProperty( "-o-transform", "rotate(90deg)" );                        
                        style.addProperty( "writing-mode", "tb-rl" ); // For IE
                        break;
                }
            }
            return style;
        }
        return null;
    }

    public List getCSSStyles()
    {
        if ( cssStyles == null )
        {
            cssStyles = new ArrayList();
        }
        return cssStyles;
    }

    public void save( ContentHandler contentHandler )
        throws SAXException
    {
        List cssStyles = getCSSStyles();
        if ( ignoreStylesIfUnused && cssStyles.size() < 1 )
        {
            return;
        }

        SAXHelper.startElement( contentHandler, XHTMLConstants.STYLE_ELEMENT, null );
        for ( CSSStyle style : cssStyles )
        {
            if ( indent != null )
            {
                SAXHelper.characters( contentHandler, CR );
            }
            style.save( contentHandler );
        }
        SAXHelper.endElement( contentHandler, XHTMLConstants.STYLE_ELEMENT );
    }

    public String getValueAsPoint( float value )
    {
        return new StringBuilder( String.valueOf( value ) ).append( PT_UNIT ).toString();
    }

    private String getValueAsPercent( float value )
    {
        return new StringBuilder( String.valueOf( value ) ).append( PERCENT_UNIT ).toString();
    }

    public String getClassNames( String styleID )
    {
        if ( StringUtils.isEmpty( styleID ) )
        {
            return null;
        }
        StringBuilder classNames = new StringBuilder( getClassName( styleID ) );
        CTStyle style = super.getStyle( styleID );
        while ( style != null )
        {
            style = super.getStyle( style.getBasedOn() );
            if ( style != null )
            {
                classNames.insert( 0, getClassName( style.getStyleId(), true ) );
            }
        }

        return classNames.toString();
    }

    private String getClassName( String styleId )
    {
        return getClassName( styleId, false );
    }

    private String getClassName( String styleId, boolean spaceAfter )
    {
        StringBuilder className = new StringBuilder();
        char firstChar = styleId.charAt( 0 );
        if ( Character.isDigit( firstChar ) )
        {
            // class name must not started with a number (Chrome doesn't works with that).
            className.append( 'X' ).toString();
        }
        if ( spaceAfter )
        {
            return className.append( styleId ).append( ' ' ).toString();
        }
        return className.append( styleId ).toString();
    }

    private CSSStyle getOrCreateStyle( CSSStyle style, String tagName, String className )
    {
        if ( style != null )
        {
            return style;
        }
        return new CSSStyle( tagName, className );
    }

    // private String () {
    // // see http://www.css3maker.com/text-rotation.html
    // -webkit-transform: rotate(90deg);
    // -moz-transform: rotate(90deg);
    // -ms-transform: matrix(1.239,-0.124,-0.547,0.843,0,0);
    // -o-transform: matrix(1.239,-0.124,-0.547,0.843,0,0);
    // transform: matrix(1.239,-0.124,-0.547,0.843,0,0);
    // }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy