12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802 |
- /* ====================================================================
- 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.xwpf.usermodel;
-
- import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.StringReader;
- import java.math.BigDecimal;
- import java.math.BigInteger;
- import java.math.RoundingMode;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
-
- import javax.xml.namespace.QName;
-
- import org.apache.poi.common.usermodel.PictureType;
- import org.apache.poi.ooxml.POIXMLException;
- import org.apache.poi.ooxml.util.DocumentHelper;
- import org.apache.poi.ooxml.util.POIXMLUnits;
- import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
- import org.apache.poi.util.*;
- import org.apache.poi.wp.usermodel.CharacterRun;
- import org.apache.poi.xssf.usermodel.XSSFRelation;
- import org.apache.xmlbeans.*;
- import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;
- import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualPictureProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
- import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
- import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture;
- import org.openxmlformats.schemas.drawingml.x2006.picture.CTPictureNonVisual;
- import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
- import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
- import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STHexColorRGB;
- import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STOnOff1;
- import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STVerticalAlignRun;
- import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
- import org.w3c.dom.Node;
- import org.w3c.dom.NodeList;
- import org.w3c.dom.Text;
- import org.xml.sax.InputSource;
- import org.xml.sax.SAXException;
-
- /**
- * XWPFRun object defines a region of text with a common set of properties
- */
- public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
- private final CTR run;
- private final String pictureText;
- private final IRunBody parent;
- private final List<XWPFPicture> pictures;
-
- /**
- * @param r the CTR bean which holds the run attributes
- * @param p the parent paragraph
- */
- public XWPFRun(CTR r, IRunBody p) {
- this.run = r;
- this.parent = p;
-
- /*
- * reserve already occupied drawing ids, so reserving new ids later will
- * not corrupt the document
- */
- for (CTDrawing ctDrawing : r.getDrawingArray()) {
- for (CTAnchor anchor : ctDrawing.getAnchorArray()) {
- if (anchor.getDocPr() != null) {
- getDocument().getDrawingIdManager().reserve(anchor.getDocPr().getId());
- }
- }
- for (CTInline inline : ctDrawing.getInlineArray()) {
- if (inline.getDocPr() != null) {
- getDocument().getDrawingIdManager().reserve(inline.getDocPr().getId());
- }
- }
- }
-
- // Look for any text in any of our pictures or drawings
- StringBuilder text = new StringBuilder();
- List<XmlObject> pictTextObjs = new ArrayList<>();
- pictTextObjs.addAll(Arrays.asList(r.getPictArray()));
- pictTextObjs.addAll(Arrays.asList(r.getDrawingArray()));
- for (XmlObject o : pictTextObjs) {
- XmlObject[] ts = o.selectPath("declare namespace w='" + XSSFRelation.NS_WORDPROCESSINGML + "' .//w:t");
- for (XmlObject t : ts) {
- NodeList kids = t.getDomNode().getChildNodes();
- for (int n = 0; n < kids.getLength(); n++) {
- if (kids.item(n) instanceof Text) {
- if (text.length() > 0) {
- text.append("\n");
- }
- text.append(kids.item(n).getNodeValue());
- }
- }
- }
- }
- pictureText = text.toString();
-
- // Do we have any embedded pictures?
- // (They're a different CTPicture, under the drawingml namespace)
- pictures = new ArrayList<>();
- for (XmlObject o : pictTextObjs) {
- for (CTPicture pict : getCTPictures(o)) {
- XWPFPicture picture = new XWPFPicture(pict, this);
- pictures.add(picture);
- }
- }
- }
-
- /**
- * @deprecated Use {@link XWPFRun#XWPFRun(CTR, IRunBody)}
- */
- @Deprecated
- public XWPFRun(CTR r, XWPFParagraph p) {
- this(r, (IRunBody) p);
- }
-
- /**
- * Add the xml:spaces="preserve" attribute if the string has leading or trailing white spaces
- *
- * @param xs the string to check
- */
- static void preserveSpaces(XmlString xs) {
- String text = xs.getStringValue();
- if (text != null && text.length() >= 1
- && (Character.isWhitespace(text.charAt(0)) || Character.isWhitespace(text.charAt(text.length()-1)))) {
- try (XmlCursor c = xs.newCursor()) {
- c.toNextToken();
- c.insertAttributeWithValue(new QName("http://www.w3.org/XML/1998/namespace", "space"), "preserve");
- }
- }
- }
-
- private List<CTPicture> getCTPictures(XmlObject o) {
- List<CTPicture> pics = new ArrayList<>();
- XmlObject[] picts = o.selectPath("declare namespace pic='" + CTPicture.type.getName().getNamespaceURI() + "' .//pic:pic");
- for (XmlObject pict : picts) {
- if (pict instanceof XmlAnyTypeImpl) {
- // Pesky XmlBeans bug - see Bugzilla #49934
- try {
- pict = CTPicture.Factory.parse(pict.toString(), DEFAULT_XML_OPTIONS);
- } catch (XmlException e) {
- throw new POIXMLException(e);
- }
- }
- if (pict instanceof CTPicture) {
- pics.add((CTPicture) pict);
- }
- }
- return pics;
- }
-
- /**
- * Get the currently used CTR object
- *
- * @return ctr object
- */
- @Internal
- public CTR getCTR() {
- return run;
- }
-
- /**
- * Get the currently referenced paragraph/SDT object
- *
- * @return current parent
- */
- public IRunBody getParent() {
- return parent;
- }
-
- /**
- * Get the currently referenced paragraph, or null if a SDT object
- *
- * @deprecated use {@link XWPFRun#getParent()} instead
- */
- @Deprecated
- public XWPFParagraph getParagraph() {
- if (parent instanceof XWPFParagraph) {
- return (XWPFParagraph) parent;
- }
- return null;
- }
-
- /**
- * @return The {@link XWPFDocument} instance, this run belongs to, or
- * {@code null} if parent structure (paragraph > document) is not properly set.
- */
- public XWPFDocument getDocument() {
- if (parent != null) {
- return parent.getDocument();
- }
- return null;
- }
-
- /**
- * For isBold, isItalic etc
- */
- private static boolean isCTOnOff(CTOnOff onoff) {
- return !onoff.isSetVal() || POIXMLUnits.parseOnOff(onoff);
- }
-
- /**
- * Get the language tag associated with this run, if any.
- *
- * @return the language tag associated with this run, if any
- */
- public String getLang() {
- CTRPr pr = getRunProperties(false);
- return (pr == null || pr.sizeOfLangArray() == 0) ? null : pr.getLangArray(0).getVal();
- }
-
- /**
- * Set the language tag associated with this run.
- *
- * @param lang the language tag associated with this run
- * @since 4.1.0
- */
- public void setLang(String lang) {
- CTRPr pr = getRunProperties(true);
- CTLanguage ctLang = pr.sizeOfLangArray() > 0 ? pr.getLangArray(0) : pr.addNewLang();
- ctLang.setVal(lang);
- }
-
- /**
- * Whether the bold property shall be applied to all non-complex script
- * characters in the contents of this run when displayed in a document
- *
- * @return {@code true} if the bold property for non-complex scripts is applied
- */
- @Override
- public boolean isBold() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfBArray() > 0 && isCTOnOff(pr.getBArray(0));
- }
-
- /**
- * Whether the bold property shall be applied to the complex
- * characters in the contents of this run when displayed in a document.
- *
- * @return {@code true} if the bold property for complex scripts is applied
- * @since POI 5.2.5
- */
- public boolean isComplexScriptBold() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfBCsArray() > 0 && isCTOnOff(pr.getBCsArray(0));
- }
-
- /**
- * Whether the bold property shall be applied to the non-complex
- * characters in the contents of this run when displayed in a document.
- * <p>
- * This formatting property is a toggle property, which specifies that its
- * behavior differs between its use within a style definition and its use as
- * direct formatting. When used as part of a style definition, setting this
- * property shall toggle the current state of that property as specified up
- * to this point in the hierarchy (i.e. applied to not applied, and vice
- * versa). Setting it to {@code false} (or an equivalent) shall
- * result in the current setting remaining unchanged. However, when used as
- * direct formatting, setting this property to true or false shall set the
- * absolute state of the resulting property.
- * </p>
- * <p>
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then bold shall not be
- * applied to non-complex script characters.
- * </p>
- *
- * @param value {@code true} if the bold property is applied for non-complex characters.
- */
- @Override
- public void setBold(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff bold = pr.sizeOfBArray() > 0 ? pr.getBArray(0) : pr.addNewB();
- bold.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- /**
- * Whether the bold property shall be applied to the complex
- * characters in the contents of this run when displayed in a document.
- * <p>
- * This formatting property is a toggle property, which specifies that its
- * behavior differs between its use within a style definition and its use as
- * direct formatting. When used as part of a style definition, setting this
- * property shall toggle the current state of that property as specified up
- * to this point in the hierarchy (i.e. applied to not applied, and vice
- * versa). Setting it to {@code false} (or an equivalent) shall
- * result in the current setting remaining unchanged. However, when used as
- * direct formatting, setting this property to true or false shall set the
- * absolute state of the resulting property.
- * </p>
- * <p>
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then bold shall not be
- * applied to the complex characters.
- * </p>
- *
- * @param value {@code true} if the bold property is applied for complex characters
- * @since POI 5.2.5
- */
- public void setComplexScriptBold(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff bold = pr.sizeOfBCsArray() > 0 ? pr.getBCsArray(0) : pr.addNewBCs();
- bold.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- /**
- * Get text color. The returned value is a string in the hex form "RRGGBB". This can be <code>null</code>.
- */
- public String getColor() {
- String color = null;
- if (run.isSetRPr()) {
- CTRPr pr = getRunProperties(false);
- if (pr != null && pr.sizeOfColorArray() > 0) {
- CTColor clr = pr.getColorArray(0);
- color = clr.xgetVal().getStringValue();
- }
- }
- return color;
- }
-
- /**
- * Set text color.
- *
- * @param rgbStr - the desired color, in the hex form "RRGGBB".
- */
- public void setColor(String rgbStr) {
- CTRPr pr = getRunProperties(true);
- CTColor color = pr.sizeOfColorArray() > 0 ? pr.getColorArray(0) : pr.addNewColor();
- color.setVal(rgbStr);
- }
-
- /**
- * Return the string content of this text run
- *
- * @return the text of this text run or {@code null} if not set
- */
- public String getText(int pos) {
- return run.sizeOfTArray() == 0 ? null : run.getTArray(pos)
- .getStringValue();
- }
-
- /**
- * Returns text embedded in pictures
- */
- public String getPictureText() {
- return pictureText;
- }
-
- /**
- * Sets the text of this text run
- *
- * @param value the literal text which shall be displayed in the document
- */
- public void setText(String value) {
- setText(value, run.sizeOfTArray());
- }
-
- /**
- * Sets the text of this text run in the
- *
- * @param value the literal text which shall be displayed in the document
- * @param pos - position in the text array (NB: 0 based)
- */
- public void setText(String value, int pos) {
- if (pos > run.sizeOfTArray()) {
- throw new ArrayIndexOutOfBoundsException("Value too large for the parameter position in XWPFRun.setText(String value,int pos)");
- }
- CTText t = (pos < run.sizeOfTArray() && pos >= 0) ? run.getTArray(pos) : run.addNewT();
- t.setStringValue(value);
- preserveSpaces(t);
- }
-
- /**
- * Whether the italic property should be applied to all non-complex script
- * characters in the contents of this run when displayed in a document.
- *
- * @return {@code true} if the italic property is applied for non-complex characters.
- */
- @Override
- public boolean isItalic() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfIArray() > 0 && isCTOnOff(pr.getIArray(0));
- }
-
- /**
- * Whether the italic property should be applied to the complex
- * characters in the contents of this run when displayed in a document.
- *
- * @return {@code true} if the italic property is applied for complex characters.
- * @since POI 5.2.5
- */
- public boolean isComplexScriptItalic() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfICsArray() > 0 && isCTOnOff(pr.getICsArray(0));
- }
-
- /**
- * Whether the italic property shall be applied to the non-complex
- * characters in the contents of this run when displayed in a document.
- * <p>
- * This formatting property is a toggle property, which specifies that its
- * behavior differs between its use within a style definition and its use as
- * direct formatting. When used as part of a style definition, setting this
- * property shall toggle the current state of that property as specified up
- * to this point in the hierarchy (i.e. applied to not applied, and vice
- * versa). Setting it to {@code false} (or an equivalent) shall
- * result in the current setting remaining unchanged. However, when used as
- * direct formatting, setting this property to true or false shall set the
- * absolute state of the resulting property.
- * <p>
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then bold shall not be
- * applied to non-complex script characters.
- *
- * @param value {@code true} if the italic property is applied for non-complex characters.
- */
- @Override
- public void setItalic(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff italic = pr.sizeOfIArray() > 0 ? pr.getIArray(0) : pr.addNewI();
- italic.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- /**
- * Whether the italic property shall be applied to the complex
- * characters in the contents of this run when displayed in a document.
- * <p>
- * This formatting property is a toggle property, which specifies that its
- * behavior differs between its use within a style definition and its use as
- * direct formatting. When used as part of a style definition, setting this
- * property shall toggle the current state of that property as specified up
- * to this point in the hierarchy (i.e. applied to not applied, and vice
- * versa). Setting it to {@code false} (or an equivalent) shall
- * result in the current setting remaining unchanged. However, when used as
- * direct formatting, setting this property to true or false shall set the
- * absolute state of the resulting property.
- * <p>
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then italic shall not be
- * applied to the complex characters.
- *
- * @param value {@code true} if the italic property is applied for complex characters.
- * @since POI 5.2.5
- */
- public void setComplexScriptItalic(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff italic = pr.sizeOfICsArray() > 0 ? pr.getICsArray(0) : pr.addNewICs();
- italic.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- /**
- * Get the underline setting for the run.
- *
- * @return the Underline pattern applied to this run
- * @see UnderlinePatterns
- */
- public UnderlinePatterns getUnderline() {
- UnderlinePatterns value = UnderlinePatterns.NONE;
- CTUnderline underline = getCTUnderline(false);
- if (underline != null) {
- STUnderline.Enum baseValue = underline.getVal();
- if (baseValue != null) {
- value = UnderlinePatterns.valueOf(baseValue.intValue());
- }
- }
- return value;
- }
-
- /**
- * Specifies that the contents of this run should be displayed along with an
- * underline appearing directly below the character height.
- * <p>
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then an underline shall
- * not be applied to the contents of this run.
- * </p>
- *
- * @param value -
- * underline type
- * @see UnderlinePatterns
- */
- public void setUnderline(UnderlinePatterns value) {
- CTUnderline underline = getCTUnderline(true);
- assert(underline != null);
- underline.setVal(STUnderline.Enum.forInt(value.getValue()));
- }
-
- /**
- * Get the CTUnderline for the run.
- * @param create Create a new underline if necessary
- * @return The underline, or null create is false and there is no underline.
- */
- private CTUnderline getCTUnderline(boolean create) {
- CTRPr pr = getRunProperties(true);
- return pr.sizeOfUArray() > 0 ? pr.getUArray(0) : (create ? pr.addNewU() : null);
- }
-
- /**
- * Set the underline color for the run's underline, if any.
- *
- * @param color An RGB color value (e.g, "a0C6F3") or "auto".
- * @since 4.0.0
- */
- public void setUnderlineColor(String color) {
- CTUnderline underline = getCTUnderline(true);
- assert(underline != null);
- SimpleValue svColor;
- if (color.equals("auto")) {
- STHexColorAuto hexColor = STHexColorAuto.Factory.newInstance();
- hexColor.setEnumValue(STHexColorAuto.Enum.forString(color));
- svColor = (SimpleValue) hexColor;
- } else {
- STHexColorRGB rgbColor = STHexColorRGB.Factory.newInstance();
- rgbColor.setStringValue(color);
- svColor = (SimpleValue) rgbColor;
- }
- underline.setColor(svColor);
- }
-
- /**
- * Set the underline theme color for the run's underline, if any.
- *
- * @param themeColor A theme color name (see {@link STThemeColor.Enum}).
- * @since 4.0.0
- */
- public void setUnderlineThemeColor(String themeColor) {
- CTUnderline underline = getCTUnderline(true);
- assert(underline != null);
- STThemeColor.Enum val = STThemeColor.Enum.forString(themeColor);
- if (val != null) {
- underline.setThemeColor(val);
- }
- }
-
- /**
- * Get the underline theme color for the run's underline, if any.
- *
- * @return The {@link STThemeColor.Enum}.
- * @since 4.0.0
- */
- public STThemeColor.Enum getUnderlineThemeColor() {
- CTUnderline underline = getCTUnderline(false);
- STThemeColor.Enum color = STThemeColor.NONE;
- if (underline != null) {
- color = underline.getThemeColor();
- }
- return color;
- }
-
- /**
- * Get the underline color for the run's underline, if any.
- *
- * @return The RGB color value as as a string of hexadecimal digits (e.g., "A0B2F1") or "auto".
- * @since 4.0.0
- */
- public String getUnderlineColor() {
- CTUnderline underline = getCTUnderline(true);
- assert(underline != null);
- String colorName = "auto";
- Object rawValue = underline.getColor();
- if (rawValue != null) {
- if (rawValue instanceof String) {
- colorName = (String)rawValue;
- } else {
- byte[] rgbColor = (byte[])rawValue;
- colorName = HexDump.toHex(rgbColor[0]) + HexDump.toHex(rgbColor[1]) + HexDump.toHex(rgbColor[2]);
- }
- }
- return colorName;
- }
-
- /**
- * Specifies that the contents of this run shall be displayed with a single
- * horizontal line through the center of the line.
- *
- * @return {@code true} if the strike property is applied
- */
- @Override
- public boolean isStrikeThrough() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfStrikeArray() > 0 && isCTOnOff(pr.getStrikeArray(0));
- }
-
- /**
- * Specifies that the contents of this run shall be displayed with a single
- * horizontal line through the center of the line.
- * <p>
- * This formatting property is a toggle property, which specifies that its
- * behaviour differs between its use within a style definition and its use as
- * direct formatting. When used as part of a style definition, setting this
- * property shall toggle the current state of that property as specified up
- * to this point in the hierarchy (i.e. applied to not applied, and vice
- * versa). Setting it to false (or an equivalent) shall result in the
- * current setting remaining unchanged. However, when used as direct
- * formatting, setting this property to true or false shall set the absolute
- * state of the resulting property.
- * </p>
- * <p>
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then strikethrough shall
- * not be applied to the contents of this run.
- * </p>
- *
- * @param value {@code true} if the strike property is applied to
- * this run
- */
- @Override
- public void setStrikeThrough(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff strike = pr.sizeOfStrikeArray() > 0 ? pr.getStrikeArray(0) : pr.addNewStrike();
- strike.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- @Deprecated
- public boolean isStrike() {
- return isStrikeThrough();
- }
-
- @Deprecated
- public void setStrike(boolean value) {
- setStrikeThrough(value);
- }
-
- /**
- * Specifies that the contents of this run shall be displayed with a double
- * horizontal line through the center of the line.
- *
- * @return {@code true} if the double strike property is applied
- */
- @Override
- public boolean isDoubleStrikeThrough() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfDstrikeArray() > 0 && isCTOnOff(pr.getDstrikeArray(0));
- }
-
- /**
- * Specifies that the contents of this run shall be displayed with a
- * double horizontal line through the center of the line.
- *
- * @see #setStrikeThrough(boolean) for the rules about this
- */
- @Override
- public void setDoubleStrikethrough(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff dstrike = pr.sizeOfDstrikeArray() > 0 ? pr.getDstrikeArray(0) : pr.addNewDstrike();
- dstrike.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- @Override
- public boolean isSmallCaps() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfSmallCapsArray() > 0 && isCTOnOff(pr.getSmallCapsArray(0));
- }
-
- @Override
- public void setSmallCaps(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff caps = pr.sizeOfSmallCapsArray() > 0 ? pr.getSmallCapsArray(0) : pr.addNewSmallCaps();
- caps.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- @Override
- public boolean isCapitalized() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfCapsArray() > 0 && isCTOnOff(pr.getCapsArray(0));
- }
-
- @Override
- public void setCapitalized(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff caps = pr.sizeOfCapsArray() > 0 ? pr.getCapsArray(0) : pr.addNewCaps();
- caps.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- @Override
- public boolean isShadowed() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfShadowArray() > 0 && isCTOnOff(pr.getShadowArray(0));
- }
-
- @Override
- public void setShadow(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff shadow = pr.sizeOfShadowArray() > 0 ? pr.getShadowArray(0) : pr.addNewShadow();
- shadow.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- @Override
- public boolean isImprinted() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfImprintArray() > 0 && isCTOnOff(pr.getImprintArray(0));
- }
-
- @Override
- public void setImprinted(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff imprinted = pr.sizeOfImprintArray() > 0 ? pr.getImprintArray(0) : pr.addNewImprint();
- imprinted.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- @Override
- public boolean isEmbossed() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfEmbossArray() > 0 && isCTOnOff(pr.getEmbossArray(0));
- }
-
- @Override
- public void setEmbossed(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff emboss = pr.sizeOfEmbossArray() > 0 ? pr.getEmbossArray(0) : pr.addNewEmboss();
- emboss.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- /**
- * Specifies the alignment which shall be applied to the contents of this
- * run in relation to the default appearance of the run's text. This allows
- * the text to be repositioned as subscript or superscript without altering
- * the font size of the run properties.
- * <p>
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then the text shall not
- * be subscript or superscript relative to the default baseline location for
- * the contents of this run.
- * </p>
- *
- * @param valign Type of vertical align to apply
- * @see VerticalAlign
- */
- public void setSubscript(VerticalAlign valign) {
- CTRPr pr = getRunProperties(true);
- CTVerticalAlignRun ctValign = pr.sizeOfVertAlignArray() > 0 ? pr.getVertAlignArray(0) : pr.addNewVertAlign();
- ctValign.setVal(STVerticalAlignRun.Enum.forInt(valign.getValue()));
- }
-
- @Override
- public int getKerning() {
- CTRPr pr = getRunProperties(false);
- if (pr == null || pr.sizeOfKernArray() == 0) {
- return 0;
- }
- return (int)POIXMLUnits.parseLength(pr.getKernArray(0).xgetVal());
- }
-
- @Override
- public void setKerning(int kern) {
- CTRPr pr = getRunProperties(true);
- CTHpsMeasure kernmes = pr.sizeOfKernArray() > 0 ? pr.getKernArray(0) : pr.addNewKern();
- kernmes.setVal(BigInteger.valueOf(kern));
- }
-
- @Override
- public boolean isHighlighted() {
- CTRPr pr = getRunProperties(false);
- if (pr == null || pr.sizeOfHighlightArray() == 0) {
- return false;
- }
- STHighlightColor.Enum val = pr.getHighlightArray(0).getVal();
- return val != null && val != STHighlightColor.NONE;
- }
- // TODO Provide a wrapper round STHighlightColor, then expose getter/setter
- // for the highlight colour. Ideally also then add to CharacterRun interface
-
- @Override
- public int getCharacterSpacing() {
- CTRPr pr = getRunProperties(false);
- if (pr == null || pr.sizeOfSpacingArray() == 0) {
- return 0;
- }
- return (int)Units.toDXA(POIXMLUnits.parseLength(pr.getSpacingArray(0).xgetVal()));
- }
-
- @Override
- public void setCharacterSpacing(int twips) {
- CTRPr pr = getRunProperties(true);
- CTSignedTwipsMeasure spc = pr.sizeOfSpacingArray() > 0 ? pr.getSpacingArray(0) : pr.addNewSpacing();
- spc.setVal(BigInteger.valueOf(twips));
- }
-
- /**
- * Gets the fonts which shall be used to display the text contents of
- * this run. Specifies a font which shall be used to format all characters
- * in the ASCII range (0 - 127) within the parent run
- *
- * @return a string representing the font family
- */
- public String getFontFamily() {
- return getFontFamily(null);
- }
-
- /**
- * Specifies the fonts which shall be used to display the text contents of
- * this run. Specifies a font which shall be used to format all characters
- * in the ASCII range (0 - 127) within the parent run.
- * <p>
- * Also sets the other font ranges, if they haven't been set before
- *
- * @param fontFamily The font family to apply
- * @see FontCharRange
- */
- public void setFontFamily(String fontFamily) {
- setFontFamily(fontFamily, null);
- }
-
- /**
- * Alias for {@link #getFontFamily()}
- */
- @Override
- public String getFontName() {
- return getFontFamily();
- }
-
- /**
- * Gets the font family for the specified font char range.
- * If fcr is null, the font char range "ascii" is used
- *
- * @param fcr the font char range, defaults to "ansi"
- * @return a string representing the font famil
- */
- public String getFontFamily(FontCharRange fcr) {
- CTRPr pr = getRunProperties(false);
- if (pr == null || pr.sizeOfRFontsArray() == 0) {
- return null;
- }
-
- CTFonts fonts = pr.getRFontsArray(0);
- switch (fcr == null ? FontCharRange.ascii : fcr) {
- default:
- case ascii:
- return fonts.getAscii();
- case cs:
- return fonts.getCs();
- case eastAsia:
- return fonts.getEastAsia();
- case hAnsi:
- return fonts.getHAnsi();
- }
- }
-
- /**
- * Specifies the fonts which shall be used to display the text contents of
- * this run. The default handling for fcr == null is to overwrite the
- * ascii font char range with the given font family and also set all not
- * specified font ranges
- *
- * @param fontFamily The font family to apply
- * @param fcr FontCharRange or null for default handling
- */
- public void setFontFamily(String fontFamily, FontCharRange fcr) {
- CTRPr pr = getRunProperties(true);
- CTFonts fonts = pr.sizeOfRFontsArray() > 0 ? pr.getRFontsArray(0) : pr.addNewRFonts();
-
- if (fcr == null) {
- fonts.setAscii(fontFamily);
- if (!fonts.isSetHAnsi()) {
- fonts.setHAnsi(fontFamily);
- }
- if (!fonts.isSetCs()) {
- fonts.setCs(fontFamily);
- }
- if (!fonts.isSetEastAsia()) {
- fonts.setEastAsia(fontFamily);
- }
- } else {
- switch (fcr) {
- case ascii:
- fonts.setAscii(fontFamily);
- break;
- case cs:
- fonts.setCs(fontFamily);
- break;
- case eastAsia:
- fonts.setEastAsia(fontFamily);
- break;
- case hAnsi:
- fonts.setHAnsi(fontFamily);
- break;
- }
- }
- }
-
- /**
- * Specifies the font size which shall be applied to all non complex script
- * characters in the contents of this run when displayed.
- *
- * @return value representing the font size (non-integer size will be rounded with half rounding up,
- * -1 is returned if size not set)
- * @deprecated use {@link #getFontSizeAsDouble()}
- */
- @Deprecated
- @Removal(version = "6.0.0")
- @Override
- public int getFontSize() {
- BigDecimal bd = getFontSizeAsBigDecimal(0);
- return bd == null ? -1 : bd.intValue();
- }
-
- /**
- * Specifies the font size which shall be applied to the non-complex
- * characters in the contents of this run when displayed.
- *
- * @return value representing the font size (can be null if size not set)
- * @since POI 5.0.0
- */
- @Override
- public Double getFontSizeAsDouble() {
- BigDecimal bd = getFontSizeAsBigDecimal(1);
- return bd == null ? null : bd.doubleValue();
- }
-
- /**
- * Specifies the font size which shall be applied to the complex script
- * characters in the contents of this run when displayed.
- *
- * @return value representing the font size for the complex scripts (can be null if size not set)
- * @since POI 5.2.5
- */
- public Double getComplexScriptFontSizeAsDouble() {
- BigDecimal bd = getComplexScriptFontSizeAsBigDecimal(1);
- return bd == null ? null : bd.doubleValue();
- }
-
-
- private BigDecimal getFontSizeAsBigDecimal(int scale) {
- CTRPr pr = getRunProperties(false);
- return (pr != null && pr.sizeOfSzArray() > 0)
- ? BigDecimal.valueOf(Units.toPoints(POIXMLUnits.parseLength(pr.getSzArray(0).xgetVal()))).divide(BigDecimal.valueOf(4), scale, RoundingMode.HALF_UP)
- : null;
- }
-
- private BigDecimal getComplexScriptFontSizeAsBigDecimal(int scale) {
- CTRPr pr = getRunProperties(false);
- return (pr != null && pr.sizeOfSzCsArray() > 0)
- ? BigDecimal.valueOf(Units.toPoints(POIXMLUnits.parseLength(pr.getSzCsArray(0).xgetVal()))).divide(BigDecimal.valueOf(4), scale, RoundingMode.HALF_UP)
- : null;
- }
-
- /**
- * Specifies the font size which shall be applied to all non complex script
- * characters in the contents of this run when displayed.
- * <p>
- * If this element is not present, the default value is to leave the value
- * applied at previous level in the style hierarchy. If this element is
- * never applied in the style hierarchy, then any appropriate font size may
- * be used for non complex script characters.
- * </p>
- *
- * @param size The font size as number of point measurements.
- * @see #setFontSize(double)
- */
- @Override
- public void setFontSize(int size) {
- BigInteger bint = BigInteger.valueOf(size);
- CTRPr pr = getRunProperties(true);
- CTHpsMeasure ctSize = pr.sizeOfSzArray() > 0 ? pr.getSzArray(0) : pr.addNewSz();
- ctSize.setVal(bint.multiply(BigInteger.valueOf(2)));
- }
-
- /**
- * Specifies the font size which shall be applied to the currently specified complex
- * script characters in the contents of this run when displayed.
- * <p>
- * If this element is not present, the default value is to leave the value
- * applied at previous level in the style hierarchy. If this element is
- * never applied in the style hierarchy, then any appropriate font size may
- * be used for the non-complex characters.
- * </p>
- *
- * @param size The font size as number of point measurements.
- * @see #setComplexScriptFontSize(double)
- * @since POI 5.2.5
- */
- public void setComplexScriptFontSize(int size) {
- CTRPr pr = getRunProperties(true);
- BigInteger bint = BigInteger.valueOf(size);
- CTHpsMeasure ctCsSize = pr.sizeOfSzCsArray() > 0 ? pr.getSzCsArray(0) : pr.addNewSzCs();
- ctCsSize.setVal(bint.multiply(BigInteger.valueOf(2)));
- }
-
- /**
- * Specifies the font size which shall be applied to the currently specified non-complex
- * characters in the contents of this run when displayed.
- *
- * <p>
- * If this element is not present, the default value is to leave the value
- * applied at previous level in the style hierarchy. If this element is
- * never applied in the style hierarchy, then any appropriate font size may
- * be used for non complex script characters.
- * </p>
- *
- * @param size The font size as number of point measurements.
- * @see #setFontSize(int)
- * @since POI 5.0.0
- */
- @Override
- public void setFontSize(double size) {
- BigDecimal bd = BigDecimal.valueOf(size);
- CTRPr pr = getRunProperties(true);
- CTHpsMeasure ctSize = pr.sizeOfSzArray() > 0 ? pr.getSzArray(0) : pr.addNewSz();
- ctSize.setVal(bd.multiply(BigDecimal.valueOf(2)).setScale(0, RoundingMode.HALF_UP).toBigInteger());
- }
-
-
- /**
- * Specifies the font size which shall be applied to the currently specified complex
- * characters in the contents of this run when displayed.
- *
- * <p>
- * If this element is not present, the default value is to leave the value
- * applied at previous level in the style hierarchy. If this element is
- * never applied in the style hierarchy, then any appropriate font size may
- * be used for the non-complex characters.
- * </p>
- *
- * @param size The font size as number of point measurements.
- * @see #setFontSize(int)
- * @since POI 5.2.5
- */
- public void setComplexScriptFontSize(double size) {
- CTRPr pr = getRunProperties(true);
- BigDecimal bd = BigDecimal.valueOf(size);
- CTHpsMeasure ctCsSize = pr.sizeOfSzCsArray() > 0 ? pr.getSzCsArray(0) : pr.addNewSzCs();
- ctCsSize.setVal(bd.multiply(BigDecimal.valueOf(2)).setScale(0, RoundingMode.HALF_UP).toBigInteger());
- }
-
- /**
- * This element specifies the amount by which text shall be raised or
- * lowered for this run in relation to the default baseline of the
- * surrounding non-positioned text. This allows the text to be repositioned
- * without altering the font size of the contents.
- *
- * @return a big integer representing the amount of text shall be "moved"
- */
- public int getTextPosition() {
- CTRPr pr = getRunProperties(false);
- return (pr != null && pr.sizeOfPositionArray() > 0) ? (int)(Units.toPoints(POIXMLUnits.parseLength(pr.getPositionArray(0).xgetVal())) / 2.)
- : -1;
- }
-
- /**
- * This element specifies the amount by which text shall be raised or
- * lowered for this run in relation to the default baseline of the
- * surrounding non-positioned text. This allows the text to be repositioned
- * without altering the font size of the contents.
- * <p>
- * If the val attribute is positive, then the parent run shall be raised
- * above the baseline of the surrounding text by the specified number of
- * half-points. If the val attribute is negative, then the parent run shall
- * be lowered below the baseline of the surrounding text by the specified
- * number of half-points.
- * </p>
- * <p>
- * If this element is not present, the default value is to leave the
- * formatting applied at previous level in the style hierarchy. If this
- * element is never applied in the style hierarchy, then the text shall not
- * be raised or lowered relative to the default baseline location for the
- * contents of this run.
- * </p>
- *
- * @param val Positive values will raise the baseline of the text, negative
- * values will lower it.
- */
- public void setTextPosition(int val) {
- BigInteger bint = new BigInteger(Integer.toString(val));
- CTRPr pr = getRunProperties(true);
- CTSignedHpsMeasure position = pr.sizeOfPositionArray() > 0 ? pr.getPositionArray(0) : pr.addNewPosition();
- position.setVal(bint);
- }
-
- /**
- * Not yet implemented.
- */
- public void removeBreak() {
- // TODO not yet implemented
- }
-
- /**
- * Specifies that a break shall be placed at the current location in the run
- * content.
- * A break is a special character which is used to override the
- * normal line breaking that would be performed based on the normal layout
- * of the document's contents.
- *
- * @see #addCarriageReturn()
- */
- public void addBreak() {
- run.addNewBr();
- }
-
- /**
- * Specifies that a break shall be placed at the current location in the run
- * content.
- * A break is a special character which is used to override the
- * normal line breaking that would be performed based on the normal layout
- * of the document's contents.
- * <p>
- * The behavior of this break character (the
- * location where text shall be restarted after this break) shall be
- * determined by its type values.
- * </p>
- *
- * @see BreakType
- */
- public void addBreak(BreakType type) {
- CTBr br = run.addNewBr();
- br.setType(STBrType.Enum.forInt(type.getValue()));
- }
-
- /**
- * Specifies that a break shall be placed at the current location in the run
- * content. A break is a special character which is used to override the
- * normal line breaking that would be performed based on the normal layout
- * of the document's contents.
- * <p>
- * The behavior of this break character (the
- * location where text shall be restarted after this break) shall be
- * determined by its type (in this case is BreakType.TEXT_WRAPPING as default) and clear attribute values.
- * </p>
- *
- * @see BreakClear
- */
- public void addBreak(BreakClear clear) {
- CTBr br = run.addNewBr();
- br.setType(STBrType.Enum.forInt(BreakType.TEXT_WRAPPING.getValue()));
- br.setClear(STBrClear.Enum.forInt(clear.getValue()));
- }
-
- /**
- * Specifies that a tab shall be placed at the current location in
- * the run content.
- */
- public void addTab() {
- run.addNewTab();
- }
-
- public void removeTab() {
- //TODO
- }
-
- /**
- * Specifies that a carriage return shall be placed at the
- * current location in the run content.
- * A carriage return is used to end the current line of text in
- * Wordprocess.
- * The behavior of a carriage return in run content shall be
- * identical to a break character with null type and clear attributes, which
- * shall end the current line and find the next available line on which to
- * continue.
- * The carriage return character forced the following text to be
- * restarted on the next available line in the document.
- */
- public void addCarriageReturn() {
- run.addNewCr();
- }
-
- public void removeCarriageReturn() {
- //TODO
- }
-
- /**
- * Adds a picture to the run. This method handles
- * attaching the picture data to the overall file.
- *
- * @param pictureData The raw picture data
- * @param pictureType The type of the picture, eg {@link Document#PICTURE_TYPE_JPEG}
- * @param width width in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
- * @param height height in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
- * @throws InvalidFormatException If the format of the picture is not known.
- * @throws IOException If reading the picture-data from the stream fails.
- * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF
- * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF
- * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PICT
- * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_JPEG
- * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PNG
- * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_GIF
- * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB
- * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_SVG
- * @see #addPicture(InputStream, PictureType, String, int, int)
- */
- public XWPFPicture addPicture(InputStream pictureData, int pictureType, String filename, int width, int height)
- throws InvalidFormatException, IOException {
- return addPicture(pictureData, PictureType.findByOoxmlId(pictureType), filename, width, height);
- }
-
- /**
- * Adds a picture to the run. This method handles
- * attaching the picture data to the overall file.
- *
- * @param pictureData The raw picture data
- * @param pictureType The {@link PictureType} of the picture
- * @param width width in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
- * @param height height in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
- * @throws InvalidFormatException If the format of the picture is not known.
- * @throws IOException If reading the picture-data from the stream fails.
- * @since POI 5.2.3
- */
- public XWPFPicture addPicture(InputStream pictureData, PictureType pictureType, String filename, int width, int height)
- throws InvalidFormatException, IOException {
- if (pictureType == null) {
- throw new InvalidFormatException("pictureType is not supported");
- }
- String relationId;
- XWPFPictureData picData;
-
- // Work out what to add the picture to, then add both the
- // picture and the relationship for it
- // TODO Should we have an interface for this sort of thing?
- if (parent.getPart() instanceof XWPFHeaderFooter) {
- XWPFHeaderFooter headerFooter = (XWPFHeaderFooter) parent.getPart();
- relationId = headerFooter.addPictureData(pictureData, pictureType);
- picData = (XWPFPictureData) headerFooter.getRelationById(relationId);
- } else if (parent.getPart() instanceof XWPFComments) {
- XWPFComments comments = (XWPFComments) parent.getPart();
- relationId = comments.addPictureData(pictureData, pictureType);
- picData = (XWPFPictureData) comments.getRelationById(relationId);
- } else {
- @SuppressWarnings("resource")
- XWPFDocument doc = parent.getDocument();
- relationId = doc.addPictureData(pictureData, pictureType);
- picData = (XWPFPictureData) doc.getRelationById(relationId);
- }
-
- // Create the drawing entry for it
- try {
- CTDrawing drawing = run.addNewDrawing();
- CTInline inline = drawing.addNewInline();
-
- // Do the fiddly namespace bits on the inline
- // (We need full control of what goes where and as what)
- String xml =
- "<a:graphic xmlns:a=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
- "<a:graphicData uri=\"" + CTPicture.type.getName().getNamespaceURI() + "\">" +
- "<pic:pic xmlns:pic=\"" + CTPicture.type.getName().getNamespaceURI() + "\" />" +
- "</a:graphicData>" +
- "</a:graphic>";
- InputSource is = new InputSource(new StringReader(xml));
- org.w3c.dom.Document doc = DocumentHelper.readDocument(is);
- inline.set(XmlToken.Factory.parse(doc.getDocumentElement(), DEFAULT_XML_OPTIONS));
-
- // Setup the inline
- inline.setDistT(0);
- inline.setDistR(0);
- inline.setDistB(0);
- inline.setDistL(0);
-
- CTNonVisualDrawingProps docPr = inline.addNewDocPr();
- long id = getParent().getDocument().getDrawingIdManager().reserveNew();
- docPr.setId(id);
- /* This name is not visible in Word 2010 anywhere. */
- docPr.setName("Drawing " + id);
- docPr.setDescr(filename);
-
- CTPositiveSize2D extent = inline.addNewExtent();
- extent.setCx(width);
- extent.setCy(height);
-
- // Grab the picture object
- CTGraphicalObject graphic = inline.getGraphic();
- CTGraphicalObjectData graphicData = graphic.getGraphicData();
- CTPicture pic = getCTPictures(graphicData).get(0);
-
- // Set it up
- CTPictureNonVisual nvPicPr = pic.addNewNvPicPr();
-
- CTNonVisualDrawingProps cNvPr = nvPicPr.addNewCNvPr();
- /* use "0" for the id. See ECM-576, 20.2.2.3 */
- cNvPr.setId(0L);
- /* This name is not visible in Word 2010 anywhere */
- cNvPr.setName("Picture " + id);
- cNvPr.setDescr(filename);
-
- CTNonVisualPictureProperties cNvPicPr = nvPicPr.addNewCNvPicPr();
- cNvPicPr.addNewPicLocks().setNoChangeAspect(true);
-
- CTBlipFillProperties blipFill = pic.addNewBlipFill();
- CTBlip blip = blipFill.addNewBlip();
- blip.setEmbed(parent.getPart().getRelationId(picData));
- blipFill.addNewStretch().addNewFillRect();
-
- CTShapeProperties spPr = pic.addNewSpPr();
- CTTransform2D xfrm = spPr.addNewXfrm();
-
- CTPoint2D off = xfrm.addNewOff();
- off.setX(0);
- off.setY(0);
-
- CTPositiveSize2D ext = xfrm.addNewExt();
- ext.setCx(width);
- ext.setCy(height);
-
- CTPresetGeometry2D prstGeom = spPr.addNewPrstGeom();
- prstGeom.setPrst(STShapeType.RECT);
- prstGeom.addNewAvLst();
-
- // Finish up
- XWPFPicture xwpfPicture = new XWPFPicture(pic, this);
- pictures.add(xwpfPicture);
- return xwpfPicture;
- } catch (XmlException | SAXException e) {
- throw new IllegalStateException(e);
- }
- }
-
- /**
- * this method add chart template into document
- *
- * @param chartRelId relation id of chart in document relation file
- * @since POI 4.0.0
- */
- @Internal
- public CTInline addChart(String chartRelId) throws InvalidFormatException, IOException {
- try {
- CTInline inline = run.addNewDrawing().addNewInline();
-
- //xml part of chart in document
- String xml =
- "<a:graphic xmlns:a=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
- "<a:graphicData uri=\"" + CTChart.type.getName().getNamespaceURI() + "\">" +
- "<c:chart xmlns:c=\"" + CTChart.type.getName().getNamespaceURI() + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" r:id=\"" + chartRelId + "\" />" +
- "</a:graphicData>" +
- "</a:graphic>";
-
- InputSource is = new InputSource(new StringReader(xml));
-
- org.w3c.dom.Document doc = DocumentHelper.readDocument(is);
-
- inline.set(XmlToken.Factory.parse(doc.getDocumentElement(), DEFAULT_XML_OPTIONS));
-
- // Setup the inline with 0 margin
- inline.setDistT(0);
- inline.setDistR(0);
- inline.setDistB(0);
- inline.setDistL(0);
-
- CTNonVisualDrawingProps docPr = inline.addNewDocPr();
- long id = getParent().getDocument().getDrawingIdManager().reserveNew();
- docPr.setId(id);
- //This name is not visible in Word anywhere.
- docPr.setName("chart " + id);
-
- return inline;
- } catch (XmlException | SAXException e) {
- throw new IllegalStateException(e);
- }
- }
-
-
- /**
- * Returns the embedded pictures of the run. These
- * are pictures which reference an external,
- * embedded picture image such as a .png or .jpg
- */
- public List<XWPFPicture> getEmbeddedPictures() {
- return pictures;
- }
-
- /**
- * Set the style ID for the run.
- *
- * @param styleId ID (not name) of the style to set for the run, e.g. "BoldItalic" (not "Bold Italic").
- * @since POI 4.1.1
- */
- public void setStyle(String styleId) {
- CTRPr pr = getCTR().getRPr();
- if (null == pr) {
- pr = getCTR().addNewRPr();
- }
- CTString style = pr.sizeOfRStyleArray() > 0 ? pr.getRStyleArray(0) : pr.addNewRStyle();
- style.setVal(styleId);
- }
-
- /**
- * Return this run's style ID. If this run has no style (no run properties or properties without a style),
- * an empty string is returned.
- *
- * @since 4.1.1
- */
- public String getStyle() {
- CTRPr pr = getCTR().getRPr();
- if (pr == null || pr.sizeOfRStyleArray() <= 0) {
- return "";
- }
- CTString style = pr.getRStyleArray(0);
- return null == style ? "" : style.getVal();
- }
-
-
- /**
- * Returns the string version of the text and the phonetic string
- */
- @Override
- public String toString() {
- String phonetic = getPhonetic();
- if (phonetic.length() > 0) {
- return text() + " (" + phonetic + ")";
- } else {
- return text();
- }
- }
-
- /**
- * Returns the string version of the text, with tabs and
- * carriage returns in place of their xml equivalents.
- */
- @Override
- public String text() {
- StringBuilder text = new StringBuilder(64);
-
- // Grab the text and tabs of the text run
- // Do so in a way that preserves the ordering
- try (XmlCursor c = run.newCursor()) {
- c.selectPath("./*");
- while (c.toNextSelection()) {
- XmlObject o = c.getObject();
- if (o instanceof CTRuby) {
- handleRuby(o, text, false);
- continue;
- }
- _getText(o, text);
- }
- }
- return text.toString();
- }
-
- /**
- * @return the phonetic (ruby) string associated with this run or an empty String if none exists
- */
- public String getPhonetic() {
- StringBuilder text = new StringBuilder(64);
-
- // Grab the text and tabs of the text run
- // Do so in a way that preserves the ordering
- try (XmlCursor c = run.newCursor()) {
- c.selectPath("./*");
- while (c.toNextSelection()) {
- XmlObject o = c.getObject();
- if (o instanceof CTRuby) {
- handleRuby(o, text, true);
- }
- }
- // Any picture text?
- if (pictureText != null && pictureText.length() > 0) {
- text.append("\n").append(pictureText).append("\n");
- }
- }
- return text.toString();
- }
-
- /**
- * @param rubyObj rubyobject
- * @param text buffer to which to append the content
- * @param extractPhonetic extract the phonetic (rt) component or the base component
- */
- private void handleRuby(XmlObject rubyObj, StringBuilder text, boolean extractPhonetic) {
- try (XmlCursor c = rubyObj.newCursor()) {
- //according to the spec, a ruby object
- //has the phonetic (rt) first, then the actual text (base)
- //second.
-
- c.selectPath(".//*");
- boolean inRT = false;
- boolean inBase = false;
- while (c.toNextSelection()) {
- XmlObject o = c.getObject();
- if (o instanceof CTRubyContent) {
- final Node node = o.getDomNode();
- if (XSSFRelation.NS_WORDPROCESSINGML.equals(node.getNamespaceURI())) {
- final String tagName = node.getLocalName();
- if ("rt".equals(tagName)) {
- inRT = true;
- } else if ("rubyBase".equals(tagName)) {
- inRT = false;
- inBase = true;
- }
- }
- } else {
- if (extractPhonetic && inRT) {
- _getText(o, text);
- } else if (!extractPhonetic && inBase) {
- _getText(o, text);
- }
- }
- }
- }
- }
-
- private void _getText(XmlObject o, StringBuilder text) {
-
- if (o instanceof CTText) {
- final Node node = o.getDomNode();
- // Field Codes (w:instrText, defined in spec sec. 17.16.23)
- // come up as instances of CTText, but we don't want them
- // in the normal text output
- if (!("instrText".equals(node.getLocalName()) && XSSFRelation.NS_WORDPROCESSINGML.equals(node.getNamespaceURI()))) {
- String textValue = ((CTText) o).getStringValue();
- if (textValue != null) {
- if (isCapitalized() || isSmallCaps()) {
- textValue = textValue.toUpperCase(LocaleUtil.getUserLocale());
- }
- text.append(textValue);
- }
- }
- }
-
- // Complex type evaluation (currently only for extraction of check boxes)
- if (o instanceof CTFldChar) {
- CTFldChar ctfldChar = ((CTFldChar) o);
- if (ctfldChar.getFldCharType() == STFldCharType.BEGIN) {
- if (ctfldChar.getFfData() != null) {
- for (CTFFCheckBox checkBox : ctfldChar.getFfData().getCheckBoxList()) {
- String textValue = checkBox.getDefault() != null && POIXMLUnits.parseOnOff(checkBox.getDefault().xgetVal()) ?
- "|X|" : "|_|";
- text.append(textValue);
- }
- }
- }
- }
-
- if (o instanceof CTPTab) {
- text.append('\t');
- }
- if (o instanceof CTBr) {
- text.append('\n');
- }
- if (o instanceof CTEmpty) {
- // Some inline text elements get returned not as
- // themselves, but as CTEmpty, owing to some odd
- // definitions around line 5642 of the XSDs
- // This bit works around it, and replicates the above
- // rules for that case
- final Node node = o.getDomNode();
- if (XSSFRelation.NS_WORDPROCESSINGML.equals(node.getNamespaceURI())) {
- switch (node.getLocalName()) {
- case "tab":
- text.append('\t');
- break;
- case "br":
- case "cr":
- text.append('\n');
- break;
- }
- }
- }
- if (o instanceof CTFtnEdnRef) {
- CTFtnEdnRef ftn = (CTFtnEdnRef) o;
- final int i = ftn.getId() == null ? -1 : ftn.getId().intValue();
- String footnoteRef = ftn.getDomNode().getLocalName().equals("footnoteReference") ?
- "[footnoteRef:" + i + "]" : "[endnoteRef:" + i + "]";
- text.append(footnoteRef);
- }
- }
-
- /**
- * @see <a href="http://msdn.microsoft.com/en-us/library/ff533743(v=office.12).aspx">[MS-OI29500] Run Fonts</a>
- */
- public enum FontCharRange {
- ascii /* char 0-127 */,
- cs /* complex symbol */,
- eastAsia /* east asia */,
- hAnsi /* high ansi */
- }
-
- /**
- * Set the text expand/collapse scale value.
- *
- * @param percentage The percentage to expand or compress the text
- * @since 4.0.0
- */
- public void setTextScale(int percentage) {
- CTRPr pr = getRunProperties(true);
- CTTextScale scale = pr.sizeOfWArray() > 0 ? pr.getWArray(0) : pr.addNewW();
- scale.setVal(percentage);
- }
-
- /**
- * Gets the current text scale value.
- *
- * @return Value is an integer percentage
- * @since 4.0.0
- */
- public int getTextScale() {
- CTRPr pr = getRunProperties(false);
- if (pr == null || pr.sizeOfWArray() == 0) {
- return 100;
- }
-
- int value = POIXMLUnits.parsePercent(pr.getWArray(0).xgetVal());
- // 100% scaling, that is, no change. See 17.3.2.43 w (Expanded/Compressed Text)
- return value == 0 ? 100 : value / 1000;
- }
-
- /**
- * Set the highlight color for the run. Silently does nothing of colorName is not a recognized value.
- *
- * @param colorName The name of the color as defined in the ST_HighlightColor simple type ({@link STHighlightColor})
- * @since 4.0.0
- */
- public void setTextHighlightColor(String colorName) {
- CTRPr pr = getRunProperties(true);
- CTHighlight highlight = pr.sizeOfHighlightArray() > 0 ? pr.getHighlightArray(0) : pr.addNewHighlight();
- STHighlightColor color = highlight.xgetVal();
- if (color == null) {
- color = STHighlightColor.Factory.newInstance();
- }
- STHighlightColor.Enum val = STHighlightColor.Enum.forString(colorName);
- if (val != null) {
- color.setStringValue(val.toString());
- highlight.xsetVal(color);
- }
-
- }
-
- /**
- * Gets the highlight color for the run
- *
- * @return {@link STHighlightColor} for the run.
- * @since 4.0.0
- * @deprecated use {@link #getTextHighlightColor()} instead
- */
- @Deprecated
- @Removal(version = "7.0.0")
- public STHighlightColor.Enum getTextHightlightColor() {
- return getTextHighlightColor();
- }
-
- /**
- * Gets the highlight color for the run
- *
- * @return {@link STHighlightColor} for the run. The default is <code>NONE</code>;
- * @since 5.2.3
- */
- public STHighlightColor.Enum getTextHighlightColor() {
- CTRPr pr = getRunProperties(false);
- if (pr == null) {
- return STHighlightColor.NONE;
- }
- CTHighlight highlight = pr.sizeOfHighlightArray() > 0 ? pr.getHighlightArray(0) : pr.addNewHighlight();
- STHighlightColor color = highlight.xgetVal();
- if (color == null) {
- color = STHighlightColor.Factory.newInstance();
- color.setEnumValue(STHighlightColor.NONE);
- }
- return (STHighlightColor.Enum)(color.getEnumValue());
- }
-
- /**
- * Get the vanish (hidden text) value
- *
- * @return True if the run is hidden text.
- * @since 4.0.0
- */
- public boolean isVanish() {
- CTRPr pr = getRunProperties(false);
- return pr != null && pr.sizeOfVanishArray() > 0 && isCTOnOff(pr.getVanishArray(0));
- }
-
- /**
- * The vanish (hidden text) property for the run.
- *
- * @param value Set to true to make the run hidden text.
- * @since 4.0.0
- */
- public void setVanish(boolean value) {
- CTRPr pr = getRunProperties(true);
- CTOnOff vanish = pr.sizeOfVanishArray() > 0 ? pr.getVanishArray(0) : pr.addNewVanish();
- vanish.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
- }
-
- /**
- * Get the vertical alignment value
- *
- * @return {@link STVerticalAlignRun.Enum} value (see 22.9.2.17 ST_VerticalAlignRun (Vertical Positioning Location)).
- * The default is <code>BASELINE</code>.
- * @since 4.0.0
- */
- public STVerticalAlignRun.Enum getVerticalAlignment() {
- CTRPr pr = getRunProperties(false);
- if (pr == null) {
- return STVerticalAlignRun.BASELINE;
- }
- CTVerticalAlignRun vertAlign = pr.sizeOfVertAlignArray() > 0 ? pr.getVertAlignArray(0) : pr.addNewVertAlign();
- STVerticalAlignRun.Enum val = vertAlign.getVal();
- if (val == null) {
- val = STVerticalAlignRun.BASELINE;
- }
- return val;
- }
-
- /**
- * Set the vertical alignment of the run.
- *
- * @param verticalAlignment Vertical alignment value, one of "baseline", "superscript", or "subscript".
- * @since 4.0.0
- */
- public void setVerticalAlignment(String verticalAlignment) {
- CTRPr pr = getRunProperties(true);
- CTVerticalAlignRun vertAlign = pr.sizeOfVertAlignArray() > 0 ? pr.getVertAlignArray(0) : pr.addNewVertAlign();
- STVerticalAlignRun align = vertAlign.xgetVal();
- if (align == null) {
- align = STVerticalAlignRun.Factory.newInstance();
- }
- STVerticalAlignRun.Enum val = STVerticalAlignRun.Enum.forString(verticalAlignment);
- if (val != null) {
- align.setStringValue(val.toString());
- vertAlign.xsetVal(align);
- }
-
-
- }
-
- /**
- * Get the emphasis mark value for the run.
- *
- * @return {@link STEm.Enum} emphasis mark type enumeration. See 17.18.24 ST_Em (Emphasis Mark Type).
- * The default is <code>NONE</code>.
- * @since 4.0.0
- */
- public STEm.Enum getEmphasisMark() {
- CTRPr pr = getRunProperties(false);
- if (pr == null) {
- return STEm.NONE;
- }
- CTEm emphasis = pr.sizeOfEmArray() > 0 ? pr.getEmArray(0) : pr.addNewEm();
-
- STEm.Enum val = emphasis.getVal();
- if (val == null) {
- val = STEm.NONE;
- }
- return val;
- }
-
- /**
- * Set the emphasis mark for the run. The emphasis mark goes above or below the run
- * text.
- *
- * @param markType Emphasis mark type name, e.g., "dot" or "none". See 17.18.24 ST_Em (Emphasis Mark Type)
- * @since 4.0.0
- */
- public void setEmphasisMark(String markType) {
- CTRPr pr = getRunProperties(true);
- CTEm emphasisMark = pr.sizeOfEmArray() > 0 ? pr.getEmArray(0) : pr.addNewEm();
- STEm mark = emphasisMark.xgetVal();
- if (mark == null) {
- mark = STEm.Factory.newInstance();
- }
- STEm.Enum val = STEm.Enum.forString(markType);
- if (val != null) {
- mark.setStringValue(val.toString());
- emphasisMark.xsetVal(mark);
- }
-
-
- }
-
- /**
- * Get the run properties for the run.
- *
- * @param create If true, create the properties, if false, do not.
- * @return The run properties or null if there are no properties and create is false.
- */
- protected CTRPr getRunProperties(boolean create) {
- CTRPr pr = run.isSetRPr() ? run.getRPr() : null;
- if (create && pr == null) {
- pr = run.addNewRPr();
- }
- return pr;
- }
-
- }
|