123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- /* ====================================================================
- 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;
- }
- }
|