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

org.apache.poi.xslf.usermodel.XSLFTextRun Maven / Gradle / Ivy

There is a newer version: 5.2.5
Show newest version
/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */
package org.apache.poi.xslf.usermodel;

import java.awt.Color;

import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.util.Beta;
import org.apache.poi.xslf.model.CharacterPropertyFetcher;
import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink;
import org.openxmlformats.schemas.drawingml.x2006.main.CTRegularTextRun;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextFont;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextNormalAutofit;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;

/**
 * Represents a run of text within the containing text body. The run element is the
 * lowest level text separation mechanism within a text body.
 */
@Beta
public class XSLFTextRun implements TextRun {
    private final CTRegularTextRun _r;
    private final XSLFTextParagraph _p;

    protected XSLFTextRun(CTRegularTextRun r, XSLFTextParagraph p){
        _r = r;
        _p = p;
    }

    XSLFTextParagraph getParentParagraph(){
        return _p;
    }

    public String getRawText(){
        return _r.getT();
    }

    String getRenderableText(){
        String txt = _r.getT();
        TextCap cap = getTextCap();
        StringBuffer buf = new StringBuffer();
        for(int i = 0; i < txt.length(); i++) {
            char c = txt.charAt(i);
            if(c == '\t') {
                // TODO: finish support for tabs
                buf.append("  ");
            } else {
                switch (cap){
                    case ALL:
                        buf.append(Character.toUpperCase(c));
                        break;
                    case SMALL:
                        buf.append(Character.toLowerCase(c));
                        break;
                    default:
                        buf.append(c);
                }
            }
        }

        return buf.toString();
    }

    public void setText(String text){
        _r.setT(text);
    }

    public CTRegularTextRun getXmlObject(){
        return _r;
    }

    @Override
    public void setFontColor(Color color) {
        setFontColor(DrawPaint.createSolidPaint(color));
    }
    
    @Override
    public void setFontColor(PaintStyle color) {
        if (!(color instanceof SolidPaint)) {
            throw new IllegalArgumentException("Currently only SolidPaint is supported!");
        }
        SolidPaint sp = (SolidPaint)color;
        Color c = DrawPaint.applyColorTransform(sp.getSolidColor());
        
        CTTextCharacterProperties rPr = getRPr(true);
        CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();
        
        XSLFColor col = new XSLFColor(fill, getParentParagraph().getParentShape().getSheet().getTheme(), fill.getSchemeClr());
        col.setColor(c);
    }

    @Override
    public PaintStyle getFontColor(){
        CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){
            public boolean fetch(CTTextCharacterProperties props){
                if (props == null) {
                    return false;
                }
                
                XSLFShape shape = _p.getParentShape();
                CTShapeStyle style = shape.getSpStyle();
                CTSchemeColor phClr = null;
                if (style != null && style.getFontRef() != null) {
                    phClr = style.getFontRef().getSchemeClr();
                }

                XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props);
                XSLFSheet sheet = shape.getSheet();
                PackagePart pp = sheet.getPackagePart();
                XSLFTheme theme = sheet.getTheme();
                PaintStyle ps = XSLFShape.selectPaint(fp, phClr, pp, theme);
                
                if (ps != null)  {
                    setValue(ps);
                    return true;
                }
                
                return false;
            }
        };
        fetchCharacterProperty(fetcher);
        return fetcher.getValue();
    }

    @Override
    public void setFontSize(Double fontSize){
        CTTextCharacterProperties rPr = getRPr(true);
        if(fontSize == null) {
            if (rPr.isSetSz()) rPr.unsetSz();
        } else {
            if (fontSize < 1.0) {
                throw new IllegalArgumentException("Minimum font size is 1pt but was " + fontSize);
            }

            rPr.setSz((int)(100*fontSize));
        }
    }

    @Override
    public Double getFontSize(){
        double scale = 1;
        CTTextNormalAutofit afit = getParentParagraph().getParentShape().getTextBodyPr().getNormAutofit();
        if(afit != null) scale = (double)afit.getFontScale() / 100000;

        CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){
            public boolean fetch(CTTextCharacterProperties props){
                if (props != null && props.isSetSz()) {
                    setValue(props.getSz()*0.01);
                    return true;
                }
                return false;
            }
        };
        fetchCharacterProperty(fetcher);
        return fetcher.getValue() == null ? null : fetcher.getValue()*scale;
    }

    /**
     *
     * @return the spacing between characters within a text run,
     * If this attribute is omitted than a value of 0 or no adjustment is assumed.
     */
    public double getCharacterSpacing(){

        CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){
            public boolean fetch(CTTextCharacterProperties props){
                if (props != null && props.isSetSpc()) {
                    setValue(props.getSpc()*0.01);
                    return true;
                }
                return false;
            }
        };
        fetchCharacterProperty(fetcher);
        return fetcher.getValue() == null ? 0 : fetcher.getValue();
    }

    /**
     * Set the spacing between characters within a text run.
     * 

* The spacing is specified in points. Positive values will cause the text to expand, * negative values to condense. *

* * @param spc character spacing in points. */ public void setCharacterSpacing(double spc){ CTTextCharacterProperties rPr = getRPr(true); if(spc == 0.0) { if(rPr.isSetSpc()) rPr.unsetSpc(); } else { rPr.setSpc((int)(100*spc)); } } @Override public void setFontFamily(String typeface){ setFontFamily(typeface, (byte)-1, (byte)-1, false); } public void setFontFamily(String typeface, byte charset, byte pictAndFamily, boolean isSymbol){ CTTextCharacterProperties rPr = getRPr(true); if(typeface == null){ if(rPr.isSetLatin()) rPr.unsetLatin(); if(rPr.isSetCs()) rPr.unsetCs(); if(rPr.isSetSym()) rPr.unsetSym(); } else { if(isSymbol){ CTTextFont font = rPr.isSetSym() ? rPr.getSym() : rPr.addNewSym(); font.setTypeface(typeface); } else { CTTextFont latin = rPr.isSetLatin() ? rPr.getLatin() : rPr.addNewLatin(); latin.setTypeface(typeface); if(charset != -1) latin.setCharset(charset); if(pictAndFamily != -1) latin.setPitchFamily(pictAndFamily); } } } @Override public String getFontFamily(){ final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); CharacterPropertyFetcher visitor = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if (props != null) { CTTextFont font = props.getLatin(); if (font != null) { String typeface = font.getTypeface(); if("+mj-lt".equals(typeface)) { typeface = theme.getMajorFont(); } else if ("+mn-lt".equals(typeface)){ typeface = theme.getMinorFont(); } setValue(typeface); return true; } } return false; } }; fetchCharacterProperty(visitor); return visitor.getValue(); } public byte getPitchAndFamily(){ // final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); CharacterPropertyFetcher visitor = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if (props != null) { CTTextFont font = props.getLatin(); if (font != null) { setValue(font.getPitchFamily()); return true; } } return false; } }; fetchCharacterProperty(visitor); return visitor.getValue() == null ? 0 : visitor.getValue(); } @Override public void setStrikethrough(boolean strike) { getRPr(true).setStrike(strike ? STTextStrikeType.SNG_STRIKE : STTextStrikeType.NO_STRIKE); } @Override public boolean isStrikethrough() { CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if(props != null && props.isSetStrike()) { setValue(props.getStrike() != STTextStrikeType.NO_STRIKE); return true; } return false; } }; fetchCharacterProperty(fetcher); return fetcher.getValue() == null ? false : fetcher.getValue(); } @Override public boolean isSuperscript() { CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if (props != null && props.isSetBaseline()) { setValue(props.getBaseline() > 0); return true; } return false; } }; fetchCharacterProperty(fetcher); return fetcher.getValue() == null ? false : fetcher.getValue(); } /** * Set the baseline for both the superscript and subscript fonts. *

* The size is specified using a percentage. * Positive values indicate superscript, negative values indicate subscript. *

* * @param baselineOffset */ public void setBaselineOffset(double baselineOffset){ getRPr(true).setBaseline((int) baselineOffset * 1000); } /** * Set whether the text in this run is formatted as superscript. * Default base line offset is 30% * * @see #setBaselineOffset(double) */ public void setSuperscript(boolean flag){ setBaselineOffset(flag ? 30. : 0.); } /** * Set whether the text in this run is formatted as subscript. * Default base line offset is -25%. * * @see #setBaselineOffset(double) */ public void setSubscript(boolean flag){ setBaselineOffset(flag ? -25.0 : 0.); } @Override public boolean isSubscript() { CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if (props != null && props.isSetBaseline()) { setValue(props.getBaseline() < 0); return true; } return false; } }; fetchCharacterProperty(fetcher); return fetcher.getValue() == null ? false : fetcher.getValue(); } /** * @return whether a run of text will be formatted as a superscript text. Default is false. */ public TextCap getTextCap() { CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if (props != null && props.isSetCap()) { int idx = props.getCap().intValue() - 1; setValue(TextCap.values()[idx]); return true; } return false; } }; fetchCharacterProperty(fetcher); return fetcher.getValue() == null ? TextCap.NONE : fetcher.getValue(); } @Override public void setBold(boolean bold){ getRPr(true).setB(bold); } @Override public boolean isBold(){ CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if (props != null && props.isSetB()) { setValue(props.getB()); return true; } return false; } }; fetchCharacterProperty(fetcher); return fetcher.getValue() == null ? false : fetcher.getValue(); } @Override public void setItalic(boolean italic){ getRPr(true).setI(italic); } @Override public boolean isItalic(){ CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if (props != null && props.isSetI()) { setValue(props.getI()); return true; } return false; } }; fetchCharacterProperty(fetcher); return fetcher.getValue() == null ? false : fetcher.getValue(); } @Override public void setUnderlined(boolean underline) { getRPr(true).setU(underline ? STTextUnderlineType.SNG : STTextUnderlineType.NONE); } @Override public boolean isUnderlined(){ CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ if (props != null && props.isSetU()) { setValue(props.getU() != STTextUnderlineType.NONE); return true; } return false; } }; fetchCharacterProperty(fetcher); return fetcher.getValue() == null ? false : fetcher.getValue(); } /** * Return the character properties * * @param create if true, create an empty character properties object if it doesn't exist * @return the character properties or null if create was false and the properties haven't exist */ protected CTTextCharacterProperties getRPr(boolean create) { if (_r.isSetRPr()) { return _r.getRPr(); } else if (create) { return _r.addNewRPr(); } else { return null; } } @Override public String toString(){ return "[" + getClass() + "]" + getRawText(); } @Override public XSLFHyperlink createHyperlink(){ XSLFHyperlink hl = getHyperlink(); if (hl == null) { hl = new XSLFHyperlink(_r.getRPr().addNewHlinkClick(), _p.getParentShape().getSheet()); } return hl; } @Override public XSLFHyperlink getHyperlink(){ CTTextCharacterProperties rPr = _r.getRPr(); if (rPr == null) { return null; } CTHyperlink hl = rPr.getHlinkClick(); if (hl == null) { return null; } return new XSLFHyperlink(hl, _p.getParentShape().getSheet()); } private boolean fetchCharacterProperty(CharacterPropertyFetcher fetcher){ XSLFTextShape shape = _p.getParentShape(); XSLFSheet sheet = shape.getSheet(); boolean ok = false; if (_r.isSetRPr()) ok = fetcher.fetch(getRPr(false)); if (ok) return true; ok = shape.fetchShapeProperty(fetcher); if (ok) return true; CTPlaceholder ph = shape.getCTPlaceholder(); if (ph == null){ // if it is a plain text box then take defaults from presentation.xml @SuppressWarnings("resource") XMLSlideShow ppt = sheet.getSlideShow(); CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel()); if (themeProps != null) { // TODO: determine master shape ok = fetcher.fetch(themeProps); } } if (ok) return true; CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle(); if(defaultProps != null) { // TODO: determine master shape ok = fetcher.fetch(defaultProps); } if (ok) return true; return false; } void copy(XSLFTextRun r){ String srcFontFamily = r.getFontFamily(); if(srcFontFamily != null && !srcFontFamily.equals(getFontFamily())){ setFontFamily(srcFontFamily); } PaintStyle srcFontColor = r.getFontColor(); if(srcFontColor != null && !srcFontColor.equals(getFontColor())){ setFontColor(srcFontColor); } double srcFontSize = r.getFontSize(); if(srcFontSize != getFontSize()){ setFontSize(srcFontSize); } boolean bold = r.isBold(); if(bold != isBold()) setBold(bold); boolean italic = r.isItalic(); if(italic != isItalic()) setItalic(italic); boolean underline = r.isUnderlined(); if(underline != isUnderlined()) setUnderlined(underline); boolean strike = r.isStrikethrough(); if(strike != isStrikethrough()) setStrikethrough(strike); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy