- /* ====================================================================
- 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.hslf.usermodel;
-
- import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.getPropVal;
-
- import java.awt.Color;
-
- import org.apache.poi.hslf.exceptions.HSLFException;
- import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
- import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
- import org.apache.poi.hslf.model.textproperties.TextProp;
- import org.apache.poi.hslf.model.textproperties.TextPropCollection;
- import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
- import org.apache.poi.hslf.record.ExHyperlink;
- import org.apache.poi.hslf.record.InteractiveInfo;
- import org.apache.poi.hslf.record.InteractiveInfoAtom;
- import org.apache.poi.hslf.record.Record;
- 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.Internal;
- import org.apache.poi.util.POILogFactory;
- import org.apache.poi.util.POILogger;
-
-
- /**
- * Represents a run of text, all with the same style
- *
- */
- public final class HSLFTextRun implements TextRun {
- protected POILogger logger = POILogFactory.getLogger(this.getClass());
-
- /** The TextRun we belong to */
- private HSLFTextParagraph parentParagraph;
- private String _runText = "";
- private String _fontFamily;
- private int hyperlinkId = -1;
-
- /**
- * Our paragraph and character style.
- * Note - we may share these styles with other RichTextRuns
- */
- private TextPropCollection characterStyle = new TextPropCollection(1, TextPropType.character);
-
- /**
- * Create a new wrapper around a rich text string
- * @param parentParagraph the parent paragraph
- */
- public HSLFTextRun(HSLFTextParagraph parentParagraph) {
- this.parentParagraph = parentParagraph;
- }
-
- public TextPropCollection getCharacterStyle() {
- return characterStyle;
- }
-
- public void setCharacterStyle(TextPropCollection characterStyle) {
- this.characterStyle.copy(characterStyle);
- this.characterStyle.updateTextSize(_runText.length());
- }
-
- /**
- * Setting a master style reference
- *
- * @param characterStyle the master style reference
- *
- * @since POI 3.14-Beta1
- */
- @Internal
- /* package */ void setMasterStyleReference(TextPropCollection characterStyle) {
- this.characterStyle = characterStyle;
- }
-
-
- /**
- * Supply the SlideShow we belong to
- */
- public void updateSheet() {
- if (_fontFamily != null) {
- setFontFamily(_fontFamily);
- _fontFamily = null;
- }
- }
-
- /**
- * Get the length of the text
- */
- public int getLength() {
- return _runText.length();
- }
-
- /**
- * Fetch the text, in raw storage form
- */
- public String getRawText() {
- return _runText;
- }
-
- /**
- * Change the text
- */
- public void setText(String text) {
- if (text == null) {
- throw new HSLFException("text must not be null");
- }
- String newText = HSLFTextParagraph.toInternalString(text);
- if (!newText.equals(_runText)) {
- _runText = newText;
- if (HSLFSlideShow.getLoadSavePhase() == HSLFSlideShow.LoadSavePhase.LOADED) {
- parentParagraph.setDirty();
- }
- }
- }
-
- // --------------- Internal helpers on rich text properties -------
-
- /**
- * Fetch the value of the given flag in the CharFlagsTextProp.
- * Returns false if the CharFlagsTextProp isn't present, since the
- * text property won't be set if there's no CharFlagsTextProp.
- */
- private boolean isCharFlagsTextPropVal(int index) {
- return getFlag(index);
- }
-
- protected boolean getFlag(int index) {
- if (characterStyle == null) return false;
-
- BitMaskTextProp prop = (BitMaskTextProp)characterStyle.findByName(CharFlagsTextProp.NAME);
-
- if (prop == null || !prop.getSubPropMatches()[index]) {
- int txtype = parentParagraph.getRunType();
- HSLFSheet sheet = parentParagraph.getSheet();
- if (sheet != null) {
- HSLFMasterSheet master = sheet.getMasterSheet();
- if (master != null){
- prop = (BitMaskTextProp)master.getStyleAttribute(txtype, parentParagraph.getIndentLevel(), CharFlagsTextProp.NAME, true);
- }
- } else {
- logger.log(POILogger.WARN, "MasterSheet is not available");
- }
- }
-
- return prop == null ? false : prop.getSubValue(index);
- }
-
- /**
- * Set the value of the given flag in the CharFlagsTextProp, adding
- * it if required.
- */
- private void setCharFlagsTextPropVal(int index, boolean value) {
- // TODO: check if paragraph/chars can be handled the same ...
- if (getFlag(index) != value) {
- setFlag(index, value);
- parentParagraph.setDirty();
- }
- }
-
- /**
- * Sets the value of the given Paragraph TextProp, add if required
- * @param propName The name of the Paragraph TextProp
- * @param val The value to set for the TextProp
- */
- public void setCharTextPropVal(String propName, Integer val) {
- HSLFTextParagraph.setPropVal(characterStyle, propName, val);
- parentParagraph.setDirty();
- }
-
-
- // --------------- Friendly getters / setters on rich text properties -------
-
- @Override
- public boolean isBold() {
- return isCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX);
- }
-
- @Override
- public void setBold(boolean bold) {
- setCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX, bold);
- }
-
- @Override
- public boolean isItalic() {
- return isCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX);
- }
-
- @Override
- public void setItalic(boolean italic) {
- setCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX, italic);
- }
-
- @Override
- public boolean isUnderlined() {
- return isCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX);
- }
-
- @Override
- public void setUnderlined(boolean underlined) {
- setCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX, underlined);
- }
-
- /**
- * Does the text have a shadow?
- */
- public boolean isShadowed() {
- return isCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX);
- }
-
- /**
- * Does the text have a shadow?
- */
- public void setShadowed(boolean flag) {
- setCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX, flag);
- }
-
- /**
- * Is this text embossed?
- */
- public boolean isEmbossed() {
- return isCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX);
- }
-
- /**
- * Is this text embossed?
- */
- public void setEmbossed(boolean flag) {
- setCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX, flag);
- }
-
- @Override
- public boolean isStrikethrough() {
- return isCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX);
- }
-
- @Override
- public void setStrikethrough(boolean flag) {
- setCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX, flag);
- }
-
- /**
- * Gets the subscript/superscript option
- *
- * @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript
- */
- public int getSuperscript() {
- TextProp tp = getPropVal(characterStyle, "superscript", parentParagraph);
- return tp == null ? 0 : tp.getValue();
- }
-
- /**
- * Sets the subscript/superscript option
- *
- * @param val the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript
- */
- public void setSuperscript(int val) {
- setCharTextPropVal("superscript", val);
- }
-
- @Override
- public Double getFontSize() {
- TextProp tp = getPropVal(characterStyle, "font.size", parentParagraph);
- return tp == null ? null : (double)tp.getValue();
- }
-
-
- @Override
- public void setFontSize(Double fontSize) {
- Integer iFontSize = (fontSize == null) ? null : fontSize.intValue();
- setCharTextPropVal("font.size", iFontSize);
- }
-
- /**
- * Gets the font index
- */
- public int getFontIndex() {
- TextProp tp = getPropVal(characterStyle, "font.index", parentParagraph);
- return tp == null ? -1 : tp.getValue();
- }
-
- /**
- * Sets the font index
- */
- public void setFontIndex(int idx) {
- setCharTextPropVal("font.index", idx);
- }
-
- @Override
- public void setFontFamily(String fontFamily) {
- HSLFSheet sheet = parentParagraph.getSheet();
- @SuppressWarnings("resource")
- HSLFSlideShow slideShow = (sheet == null) ? null : sheet.getSlideShow();
- if (sheet == null || slideShow == null) {
- //we can't set font since slideshow is not assigned yet
- _fontFamily = fontFamily;
- return;
- }
- // Get the index for this font (adding if needed)
- Integer fontIdx = (fontFamily == null) ? null : slideShow.getFontCollection().addFont(fontFamily);
- setCharTextPropVal("font.index", fontIdx);
- }
-
- @Override
- public String getFontFamily() {
- HSLFSheet sheet = parentParagraph.getSheet();
- @SuppressWarnings("resource")
- HSLFSlideShow slideShow = (sheet == null) ? null : sheet.getSlideShow();
- if (sheet == null || slideShow == null) {
- return _fontFamily;
- }
- TextProp tp = getPropVal(characterStyle, "font.index,asian.font.index,ansi.font.index,symbol.font.index", parentParagraph);
- if (tp == null) { return null; }
- return slideShow.getFontCollection().getFontWithId(tp.getValue());
- }
-
- /**
- * @return font color as PaintStyle
- */
- @Override
- public SolidPaint getFontColor() {
- TextProp tp = getPropVal(characterStyle, "font.color", parentParagraph);
- if (tp == null) return null;
- Color color = HSLFTextParagraph.getColorFromColorIndexStruct(tp.getValue(), parentParagraph.getSheet());
- SolidPaint ps = DrawPaint.createSolidPaint(color);
- return ps;
- }
-
- /**
- * Sets color of the text, as a int bgr.
- * (PowerPoint stores as BlueGreenRed, not the more
- * usual RedGreenBlue)
- * @see java.awt.Color
- */
- public void setFontColor(int bgr) {
- setCharTextPropVal("font.color", bgr);
- }
-
-
- @Override
- public void setFontColor(Color color) {
- setFontColor(DrawPaint.createSolidPaint(color));
- }
-
- @Override
- public void setFontColor(PaintStyle color) {
- if (!(color instanceof SolidPaint)) {
- throw new IllegalArgumentException("HSLF only supports solid paint");
- }
- // In PowerPont RGB bytes are swapped, as BGR
- SolidPaint sp = (SolidPaint)color;
- Color c = DrawPaint.applyColorTransform(sp.getSolidColor());
- int rgb = new Color(c.getBlue(), c.getGreen(), c.getRed(), 254).getRGB();
- setFontColor(rgb);
- }
-
- protected void setFlag(int index, boolean value) {
- BitMaskTextProp prop = (BitMaskTextProp)characterStyle.addWithName(CharFlagsTextProp.NAME);
- prop.setSubValue(value, index);
- }
-
- public HSLFTextParagraph getTextParagraph() {
- return parentParagraph;
- }
-
- public TextCap getTextCap() {
- return TextCap.NONE;
- }
-
- @Override
- public boolean isSubscript() {
- return getSuperscript() < 0;
- }
-
- @Override
- public boolean isSuperscript() {
- return getSuperscript() > 0;
- }
-
- public byte getPitchAndFamily() {
- return 0;
- }
-
- /**
- * Sets the associated hyperlink id - currently this is only used while parsing and
- * can't be used for update a ppt
- *
- * @param hyperlink the id or -1 to unset it
- */
- public void setHyperlinkId(int hyperlinkId) {
- this.hyperlinkId = hyperlinkId;
- }
-
- /**
- * Returns the associated hyperlink id
- *
- * @return the hyperlink id
- */
- public int getHyperlinkId() {
- return hyperlinkId;
- }
-
-
- @Override
- public HSLFHyperlink getHyperlink() {
- if (hyperlinkId == -1) {
- return null;
- }
-
- ExHyperlink linkRecord = parentParagraph.getSheet().getSlideShow().getDocumentRecord().getExObjList().get(hyperlinkId);
- if (linkRecord == null) {
- return null;
- }
-
- InteractiveInfoAtom info = null;
- for (Record r : parentParagraph.getRecords()) {
- if (r instanceof InteractiveInfo) {
- InteractiveInfo ii = (InteractiveInfo)r;
- InteractiveInfoAtom iia = ii.getInteractiveInfoAtom();
- if (iia.getHyperlinkID() == hyperlinkId) {
- info = iia;
- break;
- }
- }
- }
- if (info == null) {
- return null;
- }
-
- // TODO: check previous/next sibling runs for same hyperlink id and return the whole string length
- int startIdx = parentParagraph.getStartIdxOfTextRun(this);
-
- HSLFHyperlink link = new HSLFHyperlink();
- link.setId(hyperlinkId);
- link.setType(info.getAction());
- link.setLabel(linkRecord.getLinkTitle());
- link.setAddress(linkRecord.getLinkURL());
- link.setStartIndex(startIdx);
- link.setEndIndex(startIdx+getLength());
-
- return link;
- }
- }
|