fr.opensagres.poi.xwpf.converter.xhtml.internal.styles.CSSStylesDocument Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apache-poi-ooxml Show documentation
Show all versions of apache-poi-ooxml Show documentation
The Apache Commons Codec package contains simple encoder and decoders for
various formats such as Base64 and Hexadecimal. In addition to these
widely used encoders and decoders, the codec package also maintains a
collection of phonetic encoding utilities.
/**
* 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);
// }
}