Package writer2latex.latex.style

Source Code of writer2latex.latex.style.CharStyleConverter

/************************************************************************
*
*  CharStyleConverter.java
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public
*  License version 2.1, as published by the Free Software Foundation.
*
*  This library 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
*  Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public
*  License along with this library; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
*  MA  02111-1307  USA
*
*  Copyright: 2002-2004 by Henrik Just
*
*  All Rights Reserved.
*
*  Version 0.3.3g (2004-11-11)
*
*/

package writer2latex.latex.style;

import java.util.Hashtable;

import writer2latex.util.*;
import writer2latex.office.*;
import writer2latex.latex.Context;
import writer2latex.latex.LaTeXDocumentPortion;
import writer2latex.latex.ConverterPalette;

/** This class creates LaTeX code from OOo character formatting
   Character formatting in OOo includes font, font effects/decorations and color.
   In addition it includes language/country information, this is however handled
   by the class <code>writer2latex.latex.style.I18n</code>
*/
public class CharStyleConverter extends StyleConverter {

    // Cache of converted font declarations
    private Hashtable fontDecls = new Hashtable();
 
    // Which formatting should we export?
    private boolean bUseColor;
    private boolean bIgnoreHardFontsize;
    private boolean bIgnoreFontsize;
    private boolean bIgnoreFont;
    private boolean bIgnoreAll;
    private boolean bUseUlem;
    // Do we need actually use ulem.sty or \textsubscript?
    private boolean bNeedUlem = false;
    private boolean bNeedSubscript = false;

    /** <p>Constructs a new <code>CharStyleConverter</code>.</p>
     */
    public CharStyleConverter(WriterStyleCollection wsc, Config config, ConverterPalette palette) {
        super(wsc,config,palette);

        bUseColor = config.useColor();
        bUseUlem = config.useUlem();

        // No character formatting at all:
        bIgnoreAll = config.formatting()==Config.IGNORE_ALL;
        // No font family or size:
        bIgnoreFont = config.formatting()<=Config.IGNORE_MOST;
        // No fontsize:
        bIgnoreFontsize = config.formatting()<=Config.CONVERT_BASIC;
        // No hard fontsize
        bIgnoreHardFontsize = config.formatting()<=Config.CONVERT_MOST;
    }
 
    public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) {
        if (bUseColor) {
            pack.append("\\usepackage{color}").nl();
        }
        if (bNeedUlem) {
            pack.append("\\usepackage[normalem]{ulem}").nl();
        }
        if (bNeedSubscript) {
            decl.append("\\newcommand\\textsubscript[1]{\\ensuremath{{}_{\\text{#1}}}}").nl();
        }
        if (!styleNames.isEmpty()) {
            decl.append("% Text styles").nl().append(declarations);
        }
    }

    /** <p>Use a text style in LaTeX.</p>
     @param <code>sName</code> the name of the text style
     *  @param <code>ba</code> a <code>BeforeAfter</code> to put code into
     */
    public void applyTextStyle(String sName, BeforeAfter ba, Context context) {
        if (sName==null || bIgnoreAll) { return; }

        // Style already converted?
        if (styleMap.contains(sName)) {
            ba.add(styleMap.getBefore(sName),styleMap.getAfter(sName));
            context.updateFormattingFromStyle(wsc.getTextStyle(sName));
            // it's verbatim if specified as sich in the configuration
            StyleMap sm = config.getTextStyleMap();
            context.setVerbatim(sm.contains(sName) && sm.getVerbatim(sName));
            return;
        }

        // The style may already be declared in the configuration:
        StyleMap sm = config.getTextStyleMap();
        if (sm.contains(sName)) {
            styleMap.put(sName,sm.getBefore(sName),sm.getAfter(sName));
            applyTextStyle(sName,ba,context);
            return;
        }
   
        // Get the style, if it exists:
        StyleWithProperties style = wsc.getTextStyle(sName);
        if (style==null) {
            styleMap.put(sName,"","");
            applyTextStyle(sName,ba,context);
            return;
        }

        // Convert automatic style 
        if (style.isAutomatic()) {
            palette.getI18n().applyLanguage(style,false,true,ba);
            applyFont(style,false,true,ba,context);
            applyFontEffects(style,true,ba);
            context.updateFormattingFromStyle(wsc.getTextStyle(sName));
            return;     
        }

        // Convert soft style:
        // This must be converted relative to a blank context!
        BeforeAfter baText = new BeforeAfter();
        palette.getI18n().applyLanguage(style,false,true,baText);
        applyFont(style,false,true,baText,new Context());
        applyFontEffects(style,true,baText);
        // declare the text style (\newcommand)
        String sTeXName = styleNames.getExportName(sName);
        styleMap.put(sName,"\\textstyle"+sTeXName+"{","}");
        declarations.append("\\newcommand\\textstyle")
            .append(sTeXName).append("[1]{")
            .append(baText.getBefore()).append("#1").append(baText.getAfter())
            .append("}").nl();
        applyTextStyle(sName,ba,context);
    }
 
    // Get the font name from a char style
    public String getFontName(String sStyleName) {
        StyleWithProperties style = wsc.getTextStyle(sStyleName);
        if (style==null) { return null; }
        String sName = style.getProperty(XMLString.STYLE_FONT_NAME);
        if (sName==null) { return null; }
        FontDeclaration fd = wsc.getFontDeclaration(sName);
        if (fd==null) { return null; }
        return fd.getProperty(XMLString.FO_FONT_FAMILY);
    }

    /** <p>Apply hard character formatting (no inheritance).</p>
     <p>This is used in sections and {foot|end}notes</p>
     @param <code>style</code> the style to use
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to
     */
    public void applyHardCharFormatting(StyleWithProperties style, BeforeAfter ba) {
        palette.getI18n().applyLanguage(style,true,false,ba);
        applyFont(style,true,false,ba,new Context());
        if (!ba.isEmpty()) { ba.add(" ",""); }
    }

    /** <p>Apply all font attributes (family, series, shape, size and color).</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bDecl</code> true if declaration form is required
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    public void applyFont(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
        // Note: if bDecl is true, nothing will be put in the "after" part of ba.
        if (style==null) { return; }
        applyNfssSize(style,bDecl,bInherit,ba,context);
        applyNfssFamily(style,bDecl,bInherit,ba,context);
        applyNfssSeries(style,bDecl,bInherit,ba,context);
        applyNfssShape(style,bDecl,bInherit,ba,context);
        applyColor(style,bDecl,bInherit,ba,context);
    }
 
    /** <p>Reset to normal font, size and color.</p>
     @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    public void applyNormalFont(BeforeAfter ba) {
        if (bUseColor) {
            ba.add("\\normalfont\\normalsize\\normalcolor","");
        }
        else {
            ba.add("\\normalfont\\normalsize","");
        }
    }

    /** <p>Apply default font attributes (family, series, shape, size and color).</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>ldp</code> the <code>LaTeXDocumentPortion</code> to add LaTeX code to.
     */
    public void applyDefaultFont(StyleWithProperties style, LaTeXDocumentPortion ldp) {
        if (style==null) { return; }

        String s = convertFontDeclaration(style.getProperty(XMLString.STYLE_FONT_NAME));
        if (s!=null){
            ldp.append("\\renewcommand\\familydefault{\\")
               .append(s).append("default}").nl();
        } // TODO: Else read props directly from the style

        s = nfssSeries(style.getProperty(XMLString.FO_FONT_WEIGHT));
        if (s!=null) {
            ldp.append("\\renewcommand\\seriesdefault{\\")
               .append(s).append("default}").nl();
        }

        s = nfssShape(style.getProperty(XMLString.FO_FONT_VARIANT),
                             style.getProperty(XMLString.FO_FONT_STYLE));
        if (s!=null) {
            ldp.append("\\renewcommand\\shapedefault{\\")
               .append(s).append("default}").nl();
        }
      
        if (bUseColor) {
            s = color(style.getProperty(XMLString.FO_COLOR));
            if (s!=null) {
                ldp.append("\\renewcommand\\normalcolor{\\color")
                   .append(s).append("}").nl();
            }
        }
    }
 
    /** <p>Apply font effects (position, underline, crossout, change case.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    public void applyFontEffects(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
        if (style==null) { return; }
        applyTextPosition(style, bInherit, ba);
        applyUnderline(style, bInherit, ba);
        applyCrossout(style, bInherit, ba);
        applyChangeCase(style, bInherit, ba);
    }

    /** <p>Apply font color.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bDecl</code> true if declaration form is required
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    public void applyColor(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
        // Note: if bDecl is true, nothing will be put in the "after" part of ba.
        if (style==null || !bUseColor || bIgnoreAll) { return; }
        String sColor = color(style.getProperty(XMLString.FO_COLOR,bInherit));
        if (sColor==null) { return; }
        if (sColor.equals(color(context.getFontColor()))) { return; }
        if (bDecl) { ba.add("\\color"+sColor,""); }
        else { ba.add("\\textcolor"+sColor+"{","}"); }
    }
 
    /** <p>Apply a specific font color.</p>
     @param <code>sColor</code> the rgb color to use
     *  @param <code>bDecl</code> true if declaration form is required
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    public void applyThisColor(String sColor, boolean bDecl, BeforeAfter ba) {
        // Note: if bDecl is true, nothing will be put in the "after" part of ba.
        if (sColor==null || !bUseColor || bIgnoreAll) { return; }
        String s = color(sColor);
        if (s==null) { return; }
        if (bDecl) { ba.add("\\color"+s,""); }
        else { ba.add("\\textcolor"+s+"{","}"); }
    }

    // Remaining methods are private

    /** <p>Apply font family.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bDecl</code> true if declaration form is required
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    private void applyNfssFamily(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
        // Note: if bDecl is true, nothing will be put in the "after" part of ba.
        if (style==null || bIgnoreFont) { return; }
        String sFontName=style.getProperty(XMLString.STYLE_FONT_NAME,bInherit);
        if (sFontName!=null){
            String sFamily = convertFontDeclaration(sFontName);
            if (sFamily==null) { return; }
            if (sFamily.equals(convertFontDeclaration(context.getFontName()))) { return; }
            if (bDecl) { ba.add("\\"+sFamily+"family",""); }
            else { ba.add("\\text"+sFamily+"{","}"); }
        } // TODO: Else read props directly from the style
    }

    /** <p>Apply font series.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bDecl</code> true if declaration form is required
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    private void applyNfssSeries(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
        // Note: if bDecl is true, nothing will be put in the "after" part of ba.
        if (style==null) { return; }
        if (bIgnoreAll) { return; }
        String sSeries = nfssSeries(style.getProperty(XMLString.FO_FONT_WEIGHT,bInherit));
        if (sSeries==null) { return; }
        if (sSeries.equals(nfssSeries(context.getFontWeight()))) { return; }
        if (bDecl) { ba.add("\\"+sSeries+"series",""); }
        else { ba.add("\\text"+sSeries+"{","}"); }
    }

    /** <p>Apply font shape.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bDecl</code> true if declaration form is required
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    private void applyNfssShape(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
        // Note: if bDecl is true, nothing will be put in the "after" part of ba.
        if (style==null) { return; }
        if (bIgnoreAll) { return; }
        String sShape = nfssShape(style.getProperty(XMLString.FO_FONT_VARIANT, bInherit),
                                  style.getProperty(XMLString.FO_FONT_STYLE, bInherit));
        if (sShape==null) { return; }
        if (sShape.equals(nfssShape(context.getFontVariant(),context.getFontStyle()))) { return; }
        if (bDecl) { ba.add("\\"+sShape+"shape",""); }
        else { ba.add("\\text"+sShape+"{","}"); }
    }
       
    /** <p>Apply font size.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bDecl</code> true if declaration form is required
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    private void applyNfssSize(StyleWithProperties style, boolean bDecl, boolean bInherit, BeforeAfter ba, Context context) {
        // Note: if bDecl is true, nothing will be put in the "after" part of ba.
        if (style==null|| bIgnoreFontsize || (bIgnoreHardFontsize && style.isAutomatic())) { return; }
        if (style.getProperty(XMLString.FO_FONT_SIZE, bInherit)==null) { return; }
        String sSize = nfssSize(style.getAbsoluteProperty(XMLString.FO_FONT_SIZE));
        if (sSize==null) { return; }
        if (sSize.equals(nfssSize(context.getFontSize()))) { return; }
        if (bDecl) { ba.add(sSize,""); }
        else { ba.add("{"+sSize+" ","}"); }
    }

    // Remaining methods are not context-sensitive

    /** <p>Apply text position.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    private void applyTextPosition(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
        if (style==null) { return; }
        if (bIgnoreAll) { return; }
        String s = textPosition(style.getProperty(XMLString.STYLE_TEXT_POSITION, bInherit));
        if (s!=null) { ba.add(s+"{","}"); }
    }
 
    /** <p>Apply text underline.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    private void applyUnderline(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
        if (style==null || !bUseUlem) { return; }
        if (bIgnoreAll) { return; }
        String s = underline(style.getProperty(XMLString.STYLE_TEXT_UNDERLINE, bInherit));
        if (s!=null) { bNeedUlem = true; ba.add(s+"{","}"); }
    }

    /** <p>Apply text crossout.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    private void applyCrossout(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
        if (style==null || !bUseUlem) { return; }
        if (bIgnoreAll) { return; }
        String s = crossout(style.getProperty(XMLString.STYLE_TEXT_CROSSING_OUT, bInherit));
        if (s!=null) { bNeedUlem = true; ba.add(s+"{","}"); }
    }

    /** <p>Apply change case.</p>
     @param <code>style</code> the OOo style to read attributesfrom
     *  @param <code>bInherit</code> true if inherited properties should be used
     *  @param <code>ba</code> the <code>BeforeAfter</code> to add LaTeX code to.
     */
    private void applyChangeCase(StyleWithProperties style, boolean bInherit, BeforeAfter ba) {
        if (style==null) { return; }
        if (bIgnoreAll) { return; }
        String s = changeCase(style.getProperty(XMLString.FO_TEXT_TRANSFORM));
        if (s!=null) { ba.add(s+"{","}"); }
    }

    /** <p>Convert font declarations to LaTeX.</p>
     <p>It returns a generic LaTeX font family (rm, tt, sf).</p>
     <p>It returns null if the font declaration doesn't exist.</p>
     @return <code>String</code> with a LaTeX generic fontfamily
     *  @param  <code>sName</code> the name of the font declaration
     */
    private String convertFontDeclaration(String sName) {
        FontDeclaration fd = wsc.getFontDeclaration(sName);
        if (fd==null) { return null; }
        if (!fontDecls.containsKey(sName)) {
            String sFontFamily = fd.getProperty(XMLString.FO_FONT_FAMILY);
            String sFontPitch = fd.getProperty(XMLString.STYLE_FONT_PITCH);
            String sFontFamilyGeneric = fd.getProperty(XMLString.STYLE_FONT_FAMILY_GENERIC);     
            fontDecls.put(sName,nfssFamily(sFontFamily,sFontFamilyGeneric,sFontPitch));
        }
        return (String) fontDecls.get(sName);
    }

    // The remaining methods are static helpers to convert single style properties

    // Font change. These methods return the declaration form if the paramater
    // bDecl is true, and otherwise the command form
   
    private static final String nfssFamily(String sFontFamily, String sFontFamilyGeneric,
                                   String sFontPitch){
        // Note: Defaults to rm
        // TODO: What about decorative, script, system?
        if ("fixed".equals(sFontPitch)) return "tt";
        else if ("modern".equals(sFontFamilyGeneric)) return "tt";
        else if ("swiss".equals(sFontFamilyGeneric)) return "sf";
        else return "rm";
    }
   
    private static final String nfssSeries(String sFontWeight){
        if (sFontWeight==null) return null;
        if ("bold".equals(sFontWeight)) return "bf";
        else return "md";
    }
   
    private static final String nfssShape(String sFontVariant, String sFontStyle){
        if (sFontVariant==null && sFontStyle==null) return null;
        if ("small-caps".equals(sFontVariant)) return "sc";
        else if ("italic".equals(sFontStyle)) return "it";
        else if ("oblique".equals(sFontStyle)) return "sl";
        else return "up";
    }
   
    private static final String nfssSize(String sFontSize){
        if (sFontSize==null) return null;
        return "\\fontsize{"+sFontSize+"}{"+Misc.multiply("120%",sFontSize)+"}\\selectfont";
    }
   
    private static final String color(String sColor){
        if ("#000000".equalsIgnoreCase(sColor)) { return "{black}"; }
        else if ("#ff0000".equalsIgnoreCase(sColor)) { return "{red}"; }
        else if ("#00ff00".equalsIgnoreCase(sColor)) { return "{green}"; }
        else if ("#0000ff".equalsIgnoreCase(sColor)) { return "{blue}"; }
        else if ("#ffff00".equalsIgnoreCase(sColor)) { return "{yellow}"; }
        else if ("#ff00ff".equalsIgnoreCase(sColor)) { return "{magenta}"; }
        else if ("#00ffff".equalsIgnoreCase(sColor)) { return "{cyan}"; }
        //no white, since we don't have background colors:
        //else if ("#ffffff".equalsIgnoreCase(sColor)) { return "{white}"; }
        else {
            float sRed, sGreen, sBlue;
            if (sColor==null || sColor.length()!=7) return null;
            sRed=(float)Misc.getIntegerFromHex(sColor.substring(1,3),0)/255;
            sGreen=(float)Misc.getIntegerFromHex(sColor.substring(3,5),0)/255;
            sBlue=(float)Misc.getIntegerFromHex(sColor.substring(5,7),0)/255;
            // avoid very bright colors (since we don't have background colors):
            if (sRed+sGreen+sBlue>2.7) { return "{black}"; }
            else { return "[rgb]{"+sRed+","+sGreen+","+sBlue+"}"; }
        }
    }
   
    // other character formatting
       
    private final String textPosition(String sTextPosition){
        if (sTextPosition==null) return null;
        if (sTextPosition.startsWith("super")) return "\\textsuperscript";
        if (sTextPosition.startsWith("sub") || sTextPosition.startsWith("-")) {
            bNeedSubscript = true;
            return "\\textsubscript";
        }
        if (sTextPosition.startsWith("0%")) return null;
        return "\\textsuperscript";
    }
   
    private static final String underline(String sUnderline) {
        if (sUnderline==null) { return null; }
        if (sUnderline.equals("none")) { return null; }
        if (sUnderline.indexOf("wave")>=0) { return "\\uwave"; }
        return "\\uline";
    }
 
    private static final String crossout(String sCrossout) {
        if (sCrossout==null) { return null; }
        if (sCrossout.equals("X")) { return "\\xout"; }
        if (sCrossout.equals("slash")) { return "\\xout"; }
        return "\\sout";
    }
 
    private static final String changeCase(String sTextTransform){
        if ("lowercase".equals(sTextTransform)) return "\\MakeLowercase";
        if ("uppercase".equals(sTextTransform)) return "\\MakeUppercase";
        return null;
    }
   
}
TOP

Related Classes of writer2latex.latex.style.CharStyleConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.