/************************************************************************ * * StyleConverter.java * * Copyright: 2002-2015 by Henrik Just * * This file is part of Writer2LaTeX. * * Writer2LaTeX is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Writer2LaTeX is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Writer2LaTeX. If not, see . * * Version 1.6 (2015-06-15) * */ package writer2latex.xhtml.style; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import writer2latex.office.*; import writer2latex.util.*; import writer2latex.xhtml.Converter; import writer2latex.xhtml.Parser; import writer2latex.xhtml.StyleInfo; import writer2latex.xhtml.XhtmlConfig; /** This class converts OpenDocument styles to CSS2 styles. * Note that some elements in OpenDocument has attributes that also maps to CSS2 properties. * Example: the width of a text box. * Also note, that some OpenDocument style properties cannot be mapped to CSS2 without creating an additional inline element. * The class uses one helper class per OpenDocument style family (paragraph, frame etc.) */ public class StyleParser extends Parser { // Helpers for text styles private TextStyleParser textSc; private ParStyleParser parSc; private HeadingStyleParser headingSc; private ListStyleFamilyParser listSc; private SectionStyleParser sectionSc; // Helpers for table styles private TableStyleParser tableSc; private RowStyleParser rowSc; private CellStyleParser cellSc; // Helpers for drawing styles private FrameStyleParser frameSc; private PresentationStyleParser presentationSc; // Helper for page styles private PageStyleParser pageSc; /** Create a new StyleConverter * * @param ofr the office reader used to access the source document * @param config the configuration to use * @param converter the main converter * @param nType the XHTML type */ public StyleParser(OfficeReader ofr, XhtmlConfig config, Converter converter, int nType) { super(ofr,config,converter); // Create the helpers textSc = new TextStyleParser(ofr,config,converter,nType); parSc = new ParStyleParser(ofr,config,converter,nType); headingSc = new HeadingStyleParser(ofr,config,converter,nType); listSc = new ListStyleFamilyParser(ofr,config,converter,nType); sectionSc = new SectionStyleParser(ofr,config,converter,nType); tableSc = new TableStyleParser(ofr,config,converter,nType); rowSc = new RowStyleParser(ofr,config,converter,nType); cellSc = new CellStyleParser(ofr,config,converter,nType); frameSc = new FrameStyleParser(ofr,config,converter,nType); presentationSc = new PresentationStyleParser(ofr,config,converter,nType); pageSc = new PageStyleParser(ofr,config,converter,nType); } // Accessor methods for helpers: We need to override the style helper accessors public TextStyleParser getTextSc() { return textSc; } public ParStyleParser getParSc() { return parSc; } public HeadingStyleParser getHeadingSc() { return headingSc; } public ListStyleFamilyParser getListSc() { return listSc; } public SectionStyleParser getSectionSc() { return sectionSc; } public TableStyleParser getTableSc() { return tableSc; } public RowStyleParser getRowSc() { return rowSc; } public CellStyleParser getCellSc() { return cellSc; } public FrameStyleParser getFrameSc() { return frameSc; } public PresentationStyleParser getPresentationSc() { return presentationSc; } public PageStyleParser getPageSc() { return pageSc; } /** Apply the default language of the source document on an XHTML element * * @param node the XHTML element */ public void applyDefaultLanguage(Element node) { StyleWithProperties style = getDefaultStyle(); if (style!=null) { StyleInfo info = new StyleInfo(); StyleFamilyParser.applyLang(style,info); applyStyle(info,node); } } /** Export style information as a string of plain CSS code * * @param bIndent true if the CSS code should be indented * @return the CSS code */ public String allStyleSelectors(boolean bIndent) { String sIndent = bIndent ? " " : ""; StringBuilder buf = new StringBuilder(); exportDefaultStyle(buf,sIndent); // Export declarations from helpers // For OpenDocument documents created with OOo only some will generate content: // Text documents: text, par, list, frame // Spreadsheet documents: cell // Presentation documents: frame, presentation, page buf.append(textSc.getStyleSelectors(sIndent)); buf.append(parSc.getStyleSelectors(sIndent)); buf.append(headingSc.getStyleSelectors(sIndent)); buf.append(listSc.getStyleSelectors(sIndent)); buf.append(sectionSc.getStyleSelectors(sIndent)); buf.append(cellSc.getStyleSelectors(sIndent)); buf.append(tableSc.getStyleSelectors(sIndent)); buf.append(rowSc.getStyleSelectors(sIndent)); buf.append(frameSc.getStyleSelectors(sIndent)); buf.append(presentationSc.getStyleSelectors(sIndent)); buf.append(pageSc.getStyleSelectors(sIndent)); return buf.toString(); } /** Export style information as an XHTML style element * * @param htmlDOM the XHTML DOM to which the generated element belongs * @return the style element */ public Node getStyleSelectors(Document htmlDOM) { String styleSelectors = allStyleSelectors(config.prettyPrint()); // Create node if (styleSelectors.length()>0) { Element styleElement = htmlDOM.createElement("style"); styleElement.setAttribute("media","all"); styleElement.setAttribute("type","text/css"); styleElement.appendChild(htmlDOM.createTextNode(config.prettyPrint() ? "\n" : " ")); styleElement.appendChild(htmlDOM.createTextNode(styleSelectors)); if (config.prettyPrint()) { styleElement.appendChild(htmlDOM.createTextNode(" ")); } return styleElement; } else { return null; } } // Private helper methods private void exportDefaultStyle(StringBuilder buf, String sIndent) { // Export default style if (config.xhtmlCustomStylesheet().length()==0 && (config.xhtmlFormatting()==XhtmlConfig.CONVERT_ALL || config.xhtmlFormatting()==XhtmlConfig.IGNORE_HARD)) { CSVList props = new CSVList(";"); // Default paragraph/cell/frame style is applied to the body element StyleWithProperties defaultStyle = getDefaultStyle(); if (defaultStyle!=null) { // text properties only! getTextSc().cssTextCommon(defaultStyle,props,true); if (config.useDefaultFont() && config.defaultFontName().length()>0) { props.addValue("font-family", "'"+config.defaultFontName()+"'"); } } // For text documents (XHTML only), also set maximum width if (ofr.isText() && !converter.isOPS()) { String sMaxWidth = config.getMaxWidth().trim(); if (sMaxWidth.length()>0) { props.addValue("max-width", sMaxWidth); props.addValue("margin-left","auto"); props.addValue("margin-right","auto"); } } // Apply properties to body if (!props.isEmpty()) { buf.append(sIndent) .append("body {").append(props.toString()).append("}").append(config.prettyPrint() ? "\n" : " "); } } } private StyleWithProperties getDefaultStyle() { if (ofr.isSpreadsheet()) return ofr.getDefaultCellStyle(); else if (ofr.isPresentation()) return ofr.getDefaultFrameStyle(); else return ofr.getDefaultParStyle(); } }