You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

XWPFRun.java 68KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.xwpf.usermodel;
  16. import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
  17. import java.io.IOException;
  18. import java.io.InputStream;
  19. import java.io.StringReader;
  20. import java.math.BigDecimal;
  21. import java.math.BigInteger;
  22. import java.math.RoundingMode;
  23. import java.util.ArrayList;
  24. import java.util.Arrays;
  25. import java.util.List;
  26. import javax.xml.namespace.QName;
  27. import org.apache.poi.common.usermodel.PictureType;
  28. import org.apache.poi.ooxml.POIXMLException;
  29. import org.apache.poi.ooxml.util.DocumentHelper;
  30. import org.apache.poi.ooxml.util.POIXMLUnits;
  31. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  32. import org.apache.poi.util.*;
  33. import org.apache.poi.wp.usermodel.CharacterRun;
  34. import org.apache.poi.xssf.usermodel.XSSFRelation;
  35. import org.apache.xmlbeans.*;
  36. import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;
  37. import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
  38. import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
  39. import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
  40. import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
  41. import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;
  42. import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
  43. import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualPictureProperties;
  44. import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
  45. import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
  46. import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
  47. import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
  48. import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
  49. import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
  50. import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture;
  51. import org.openxmlformats.schemas.drawingml.x2006.picture.CTPictureNonVisual;
  52. import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
  53. import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
  54. import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STHexColorRGB;
  55. import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STOnOff1;
  56. import org.openxmlformats.schemas.officeDocument.x2006.sharedTypes.STVerticalAlignRun;
  57. import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
  58. import org.w3c.dom.Node;
  59. import org.w3c.dom.NodeList;
  60. import org.w3c.dom.Text;
  61. import org.xml.sax.InputSource;
  62. import org.xml.sax.SAXException;
  63. /**
  64. * XWPFRun object defines a region of text with a common set of properties
  65. */
  66. public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
  67. private final CTR run;
  68. private final String pictureText;
  69. private final IRunBody parent;
  70. private final List<XWPFPicture> pictures;
  71. /**
  72. * @param r the CTR bean which holds the run attributes
  73. * @param p the parent paragraph
  74. */
  75. public XWPFRun(CTR r, IRunBody p) {
  76. this.run = r;
  77. this.parent = p;
  78. /*
  79. * reserve already occupied drawing ids, so reserving new ids later will
  80. * not corrupt the document
  81. */
  82. for (CTDrawing ctDrawing : r.getDrawingArray()) {
  83. for (CTAnchor anchor : ctDrawing.getAnchorArray()) {
  84. if (anchor.getDocPr() != null) {
  85. getDocument().getDrawingIdManager().reserve(anchor.getDocPr().getId());
  86. }
  87. }
  88. for (CTInline inline : ctDrawing.getInlineArray()) {
  89. if (inline.getDocPr() != null) {
  90. getDocument().getDrawingIdManager().reserve(inline.getDocPr().getId());
  91. }
  92. }
  93. }
  94. // Look for any text in any of our pictures or drawings
  95. StringBuilder text = new StringBuilder();
  96. List<XmlObject> pictTextObjs = new ArrayList<>();
  97. pictTextObjs.addAll(Arrays.asList(r.getPictArray()));
  98. pictTextObjs.addAll(Arrays.asList(r.getDrawingArray()));
  99. for (XmlObject o : pictTextObjs) {
  100. XmlObject[] ts = o.selectPath("declare namespace w='" + XSSFRelation.NS_WORDPROCESSINGML + "' .//w:t");
  101. for (XmlObject t : ts) {
  102. NodeList kids = t.getDomNode().getChildNodes();
  103. for (int n = 0; n < kids.getLength(); n++) {
  104. if (kids.item(n) instanceof Text) {
  105. if (text.length() > 0) {
  106. text.append("\n");
  107. }
  108. text.append(kids.item(n).getNodeValue());
  109. }
  110. }
  111. }
  112. }
  113. pictureText = text.toString();
  114. // Do we have any embedded pictures?
  115. // (They're a different CTPicture, under the drawingml namespace)
  116. pictures = new ArrayList<>();
  117. for (XmlObject o : pictTextObjs) {
  118. for (CTPicture pict : getCTPictures(o)) {
  119. XWPFPicture picture = new XWPFPicture(pict, this);
  120. pictures.add(picture);
  121. }
  122. }
  123. }
  124. /**
  125. * @deprecated Use {@link XWPFRun#XWPFRun(CTR, IRunBody)}
  126. */
  127. @Deprecated
  128. public XWPFRun(CTR r, XWPFParagraph p) {
  129. this(r, (IRunBody) p);
  130. }
  131. /**
  132. * Add the xml:spaces="preserve" attribute if the string has leading or trailing white spaces
  133. *
  134. * @param xs the string to check
  135. */
  136. static void preserveSpaces(XmlString xs) {
  137. String text = xs.getStringValue();
  138. if (text != null && text.length() >= 1
  139. && (Character.isWhitespace(text.charAt(0)) || Character.isWhitespace(text.charAt(text.length()-1)))) {
  140. try (XmlCursor c = xs.newCursor()) {
  141. c.toNextToken();
  142. c.insertAttributeWithValue(new QName("http://www.w3.org/XML/1998/namespace", "space"), "preserve");
  143. }
  144. }
  145. }
  146. private List<CTPicture> getCTPictures(XmlObject o) {
  147. List<CTPicture> pics = new ArrayList<>();
  148. XmlObject[] picts = o.selectPath("declare namespace pic='" + CTPicture.type.getName().getNamespaceURI() + "' .//pic:pic");
  149. for (XmlObject pict : picts) {
  150. if (pict instanceof XmlAnyTypeImpl) {
  151. // Pesky XmlBeans bug - see Bugzilla #49934
  152. try {
  153. pict = CTPicture.Factory.parse(pict.toString(), DEFAULT_XML_OPTIONS);
  154. } catch (XmlException e) {
  155. throw new POIXMLException(e);
  156. }
  157. }
  158. if (pict instanceof CTPicture) {
  159. pics.add((CTPicture) pict);
  160. }
  161. }
  162. return pics;
  163. }
  164. /**
  165. * Get the currently used CTR object
  166. *
  167. * @return ctr object
  168. */
  169. @Internal
  170. public CTR getCTR() {
  171. return run;
  172. }
  173. /**
  174. * Get the currently referenced paragraph/SDT object
  175. *
  176. * @return current parent
  177. */
  178. public IRunBody getParent() {
  179. return parent;
  180. }
  181. /**
  182. * Get the currently referenced paragraph, or null if a SDT object
  183. *
  184. * @deprecated use {@link XWPFRun#getParent()} instead
  185. */
  186. @Deprecated
  187. public XWPFParagraph getParagraph() {
  188. if (parent instanceof XWPFParagraph) {
  189. return (XWPFParagraph) parent;
  190. }
  191. return null;
  192. }
  193. /**
  194. * @return The {@link XWPFDocument} instance, this run belongs to, or
  195. * {@code null} if parent structure (paragraph &gt; document) is not properly set.
  196. */
  197. public XWPFDocument getDocument() {
  198. if (parent != null) {
  199. return parent.getDocument();
  200. }
  201. return null;
  202. }
  203. /**
  204. * For isBold, isItalic etc
  205. */
  206. private static boolean isCTOnOff(CTOnOff onoff) {
  207. return !onoff.isSetVal() || POIXMLUnits.parseOnOff(onoff);
  208. }
  209. /**
  210. * Get the language tag associated with this run, if any.
  211. *
  212. * @return the language tag associated with this run, if any
  213. */
  214. public String getLang() {
  215. CTRPr pr = getRunProperties(false);
  216. return (pr == null || pr.sizeOfLangArray() == 0) ? null : pr.getLangArray(0).getVal();
  217. }
  218. /**
  219. * Set the language tag associated with this run.
  220. *
  221. * @param lang the language tag associated with this run
  222. * @since 4.1.0
  223. */
  224. public void setLang(String lang) {
  225. CTRPr pr = getRunProperties(true);
  226. CTLanguage ctLang = pr.sizeOfLangArray() > 0 ? pr.getLangArray(0) : pr.addNewLang();
  227. ctLang.setVal(lang);
  228. }
  229. /**
  230. * Whether the bold property shall be applied to all non-complex script
  231. * characters in the contents of this run when displayed in a document
  232. *
  233. * @return {@code true} if the bold property for non-complex scripts is applied
  234. */
  235. @Override
  236. public boolean isBold() {
  237. CTRPr pr = getRunProperties(false);
  238. return pr != null && pr.sizeOfBArray() > 0 && isCTOnOff(pr.getBArray(0));
  239. }
  240. /**
  241. * Whether the bold property shall be applied to the complex
  242. * characters in the contents of this run when displayed in a document.
  243. *
  244. * @return {@code true} if the bold property for complex scripts is applied
  245. * @since POI 5.2.5
  246. */
  247. public boolean isComplexScriptBold() {
  248. CTRPr pr = getRunProperties(false);
  249. return pr != null && pr.sizeOfBCsArray() > 0 && isCTOnOff(pr.getBCsArray(0));
  250. }
  251. /**
  252. * Whether the bold property shall be applied to the non-complex
  253. * characters in the contents of this run when displayed in a document.
  254. * <p>
  255. * This formatting property is a toggle property, which specifies that its
  256. * behavior differs between its use within a style definition and its use as
  257. * direct formatting. When used as part of a style definition, setting this
  258. * property shall toggle the current state of that property as specified up
  259. * to this point in the hierarchy (i.e. applied to not applied, and vice
  260. * versa). Setting it to {@code false} (or an equivalent) shall
  261. * result in the current setting remaining unchanged. However, when used as
  262. * direct formatting, setting this property to true or false shall set the
  263. * absolute state of the resulting property.
  264. * </p>
  265. * <p>
  266. * If this element is not present, the default value is to leave the
  267. * formatting applied at previous level in the style hierarchy. If this
  268. * element is never applied in the style hierarchy, then bold shall not be
  269. * applied to non-complex script characters.
  270. * </p>
  271. *
  272. * @param value {@code true} if the bold property is applied for non-complex characters.
  273. */
  274. @Override
  275. public void setBold(boolean value) {
  276. CTRPr pr = getRunProperties(true);
  277. CTOnOff bold = pr.sizeOfBArray() > 0 ? pr.getBArray(0) : pr.addNewB();
  278. bold.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  279. }
  280. /**
  281. * Whether the bold property shall be applied to the complex
  282. * characters in the contents of this run when displayed in a document.
  283. * <p>
  284. * This formatting property is a toggle property, which specifies that its
  285. * behavior differs between its use within a style definition and its use as
  286. * direct formatting. When used as part of a style definition, setting this
  287. * property shall toggle the current state of that property as specified up
  288. * to this point in the hierarchy (i.e. applied to not applied, and vice
  289. * versa). Setting it to {@code false} (or an equivalent) shall
  290. * result in the current setting remaining unchanged. However, when used as
  291. * direct formatting, setting this property to true or false shall set the
  292. * absolute state of the resulting property.
  293. * </p>
  294. * <p>
  295. * If this element is not present, the default value is to leave the
  296. * formatting applied at previous level in the style hierarchy. If this
  297. * element is never applied in the style hierarchy, then bold shall not be
  298. * applied to the complex characters.
  299. * </p>
  300. *
  301. * @param value {@code true} if the bold property is applied for complex characters
  302. * @since POI 5.2.5
  303. */
  304. public void setComplexScriptBold(boolean value) {
  305. CTRPr pr = getRunProperties(true);
  306. CTOnOff bold = pr.sizeOfBCsArray() > 0 ? pr.getBCsArray(0) : pr.addNewBCs();
  307. bold.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  308. }
  309. /**
  310. * Get text color. The returned value is a string in the hex form "RRGGBB". This can be <code>null</code>.
  311. */
  312. public String getColor() {
  313. String color = null;
  314. if (run.isSetRPr()) {
  315. CTRPr pr = getRunProperties(false);
  316. if (pr != null && pr.sizeOfColorArray() > 0) {
  317. CTColor clr = pr.getColorArray(0);
  318. color = clr.xgetVal().getStringValue();
  319. }
  320. }
  321. return color;
  322. }
  323. /**
  324. * Set text color.
  325. *
  326. * @param rgbStr - the desired color, in the hex form "RRGGBB".
  327. */
  328. public void setColor(String rgbStr) {
  329. CTRPr pr = getRunProperties(true);
  330. CTColor color = pr.sizeOfColorArray() > 0 ? pr.getColorArray(0) : pr.addNewColor();
  331. color.setVal(rgbStr);
  332. }
  333. /**
  334. * Return the string content of this text run
  335. *
  336. * @return the text of this text run or {@code null} if not set
  337. */
  338. public String getText(int pos) {
  339. return run.sizeOfTArray() == 0 ? null : run.getTArray(pos)
  340. .getStringValue();
  341. }
  342. /**
  343. * Returns text embedded in pictures
  344. */
  345. public String getPictureText() {
  346. return pictureText;
  347. }
  348. /**
  349. * Sets the text of this text run
  350. *
  351. * @param value the literal text which shall be displayed in the document
  352. */
  353. public void setText(String value) {
  354. setText(value, run.sizeOfTArray());
  355. }
  356. /**
  357. * Sets the text of this text run in the
  358. *
  359. * @param value the literal text which shall be displayed in the document
  360. * @param pos - position in the text array (NB: 0 based)
  361. */
  362. public void setText(String value, int pos) {
  363. if (pos > run.sizeOfTArray()) {
  364. throw new ArrayIndexOutOfBoundsException("Value too large for the parameter position in XWPFRun.setText(String value,int pos)");
  365. }
  366. CTText t = (pos < run.sizeOfTArray() && pos >= 0) ? run.getTArray(pos) : run.addNewT();
  367. t.setStringValue(value);
  368. preserveSpaces(t);
  369. }
  370. /**
  371. * Whether the italic property should be applied to all non-complex script
  372. * characters in the contents of this run when displayed in a document.
  373. *
  374. * @return {@code true} if the italic property is applied for non-complex characters.
  375. */
  376. @Override
  377. public boolean isItalic() {
  378. CTRPr pr = getRunProperties(false);
  379. return pr != null && pr.sizeOfIArray() > 0 && isCTOnOff(pr.getIArray(0));
  380. }
  381. /**
  382. * Whether the italic property should be applied to the complex
  383. * characters in the contents of this run when displayed in a document.
  384. *
  385. * @return {@code true} if the italic property is applied for complex characters.
  386. * @since POI 5.2.5
  387. */
  388. public boolean isComplexScriptItalic() {
  389. CTRPr pr = getRunProperties(false);
  390. return pr != null && pr.sizeOfICsArray() > 0 && isCTOnOff(pr.getICsArray(0));
  391. }
  392. /**
  393. * Whether the italic property shall be applied to the non-complex
  394. * characters in the contents of this run when displayed in a document.
  395. * <p>
  396. * This formatting property is a toggle property, which specifies that its
  397. * behavior differs between its use within a style definition and its use as
  398. * direct formatting. When used as part of a style definition, setting this
  399. * property shall toggle the current state of that property as specified up
  400. * to this point in the hierarchy (i.e. applied to not applied, and vice
  401. * versa). Setting it to {@code false} (or an equivalent) shall
  402. * result in the current setting remaining unchanged. However, when used as
  403. * direct formatting, setting this property to true or false shall set the
  404. * absolute state of the resulting property.
  405. * <p>
  406. * If this element is not present, the default value is to leave the
  407. * formatting applied at previous level in the style hierarchy. If this
  408. * element is never applied in the style hierarchy, then bold shall not be
  409. * applied to non-complex script characters.
  410. *
  411. * @param value {@code true} if the italic property is applied for non-complex characters.
  412. */
  413. @Override
  414. public void setItalic(boolean value) {
  415. CTRPr pr = getRunProperties(true);
  416. CTOnOff italic = pr.sizeOfIArray() > 0 ? pr.getIArray(0) : pr.addNewI();
  417. italic.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  418. }
  419. /**
  420. * Whether the italic property shall be applied to the complex
  421. * characters in the contents of this run when displayed in a document.
  422. * <p>
  423. * This formatting property is a toggle property, which specifies that its
  424. * behavior differs between its use within a style definition and its use as
  425. * direct formatting. When used as part of a style definition, setting this
  426. * property shall toggle the current state of that property as specified up
  427. * to this point in the hierarchy (i.e. applied to not applied, and vice
  428. * versa). Setting it to {@code false} (or an equivalent) shall
  429. * result in the current setting remaining unchanged. However, when used as
  430. * direct formatting, setting this property to true or false shall set the
  431. * absolute state of the resulting property.
  432. * <p>
  433. * If this element is not present, the default value is to leave the
  434. * formatting applied at previous level in the style hierarchy. If this
  435. * element is never applied in the style hierarchy, then italic shall not be
  436. * applied to the complex characters.
  437. *
  438. * @param value {@code true} if the italic property is applied for complex characters.
  439. * @since POI 5.2.5
  440. */
  441. public void setComplexScriptItalic(boolean value) {
  442. CTRPr pr = getRunProperties(true);
  443. CTOnOff italic = pr.sizeOfICsArray() > 0 ? pr.getICsArray(0) : pr.addNewICs();
  444. italic.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  445. }
  446. /**
  447. * Get the underline setting for the run.
  448. *
  449. * @return the Underline pattern applied to this run
  450. * @see UnderlinePatterns
  451. */
  452. public UnderlinePatterns getUnderline() {
  453. UnderlinePatterns value = UnderlinePatterns.NONE;
  454. CTUnderline underline = getCTUnderline(false);
  455. if (underline != null) {
  456. STUnderline.Enum baseValue = underline.getVal();
  457. if (baseValue != null) {
  458. value = UnderlinePatterns.valueOf(baseValue.intValue());
  459. }
  460. }
  461. return value;
  462. }
  463. /**
  464. * Specifies that the contents of this run should be displayed along with an
  465. * underline appearing directly below the character height.
  466. * <p>
  467. * If this element is not present, the default value is to leave the
  468. * formatting applied at previous level in the style hierarchy. If this
  469. * element is never applied in the style hierarchy, then an underline shall
  470. * not be applied to the contents of this run.
  471. * </p>
  472. *
  473. * @param value -
  474. * underline type
  475. * @see UnderlinePatterns
  476. */
  477. public void setUnderline(UnderlinePatterns value) {
  478. CTUnderline underline = getCTUnderline(true);
  479. assert(underline != null);
  480. underline.setVal(STUnderline.Enum.forInt(value.getValue()));
  481. }
  482. /**
  483. * Get the CTUnderline for the run.
  484. * @param create Create a new underline if necessary
  485. * @return The underline, or null create is false and there is no underline.
  486. */
  487. private CTUnderline getCTUnderline(boolean create) {
  488. CTRPr pr = getRunProperties(true);
  489. return pr.sizeOfUArray() > 0 ? pr.getUArray(0) : (create ? pr.addNewU() : null);
  490. }
  491. /**
  492. * Set the underline color for the run's underline, if any.
  493. *
  494. * @param color An RGB color value (e.g, "a0C6F3") or "auto".
  495. * @since 4.0.0
  496. */
  497. public void setUnderlineColor(String color) {
  498. CTUnderline underline = getCTUnderline(true);
  499. assert(underline != null);
  500. SimpleValue svColor;
  501. if (color.equals("auto")) {
  502. STHexColorAuto hexColor = STHexColorAuto.Factory.newInstance();
  503. hexColor.setEnumValue(STHexColorAuto.Enum.forString(color));
  504. svColor = (SimpleValue) hexColor;
  505. } else {
  506. STHexColorRGB rgbColor = STHexColorRGB.Factory.newInstance();
  507. rgbColor.setStringValue(color);
  508. svColor = (SimpleValue) rgbColor;
  509. }
  510. underline.setColor(svColor);
  511. }
  512. /**
  513. * Set the underline theme color for the run's underline, if any.
  514. *
  515. * @param themeColor A theme color name (see {@link STThemeColor.Enum}).
  516. * @since 4.0.0
  517. */
  518. public void setUnderlineThemeColor(String themeColor) {
  519. CTUnderline underline = getCTUnderline(true);
  520. assert(underline != null);
  521. STThemeColor.Enum val = STThemeColor.Enum.forString(themeColor);
  522. if (val != null) {
  523. underline.setThemeColor(val);
  524. }
  525. }
  526. /**
  527. * Get the underline theme color for the run's underline, if any.
  528. *
  529. * @return The {@link STThemeColor.Enum}.
  530. * @since 4.0.0
  531. */
  532. public STThemeColor.Enum getUnderlineThemeColor() {
  533. CTUnderline underline = getCTUnderline(false);
  534. STThemeColor.Enum color = STThemeColor.NONE;
  535. if (underline != null) {
  536. color = underline.getThemeColor();
  537. }
  538. return color;
  539. }
  540. /**
  541. * Get the underline color for the run's underline, if any.
  542. *
  543. * @return The RGB color value as as a string of hexadecimal digits (e.g., "A0B2F1") or "auto".
  544. * @since 4.0.0
  545. */
  546. public String getUnderlineColor() {
  547. CTUnderline underline = getCTUnderline(true);
  548. assert(underline != null);
  549. String colorName = "auto";
  550. Object rawValue = underline.getColor();
  551. if (rawValue != null) {
  552. if (rawValue instanceof String) {
  553. colorName = (String)rawValue;
  554. } else {
  555. byte[] rgbColor = (byte[])rawValue;
  556. colorName = HexDump.toHex(rgbColor[0]) + HexDump.toHex(rgbColor[1]) + HexDump.toHex(rgbColor[2]);
  557. }
  558. }
  559. return colorName;
  560. }
  561. /**
  562. * Specifies that the contents of this run shall be displayed with a single
  563. * horizontal line through the center of the line.
  564. *
  565. * @return {@code true} if the strike property is applied
  566. */
  567. @Override
  568. public boolean isStrikeThrough() {
  569. CTRPr pr = getRunProperties(false);
  570. return pr != null && pr.sizeOfStrikeArray() > 0 && isCTOnOff(pr.getStrikeArray(0));
  571. }
  572. /**
  573. * Specifies that the contents of this run shall be displayed with a single
  574. * horizontal line through the center of the line.
  575. * <p>
  576. * This formatting property is a toggle property, which specifies that its
  577. * behaviour differs between its use within a style definition and its use as
  578. * direct formatting. When used as part of a style definition, setting this
  579. * property shall toggle the current state of that property as specified up
  580. * to this point in the hierarchy (i.e. applied to not applied, and vice
  581. * versa). Setting it to false (or an equivalent) shall result in the
  582. * current setting remaining unchanged. However, when used as direct
  583. * formatting, setting this property to true or false shall set the absolute
  584. * state of the resulting property.
  585. * </p>
  586. * <p>
  587. * If this element is not present, the default value is to leave the
  588. * formatting applied at previous level in the style hierarchy. If this
  589. * element is never applied in the style hierarchy, then strikethrough shall
  590. * not be applied to the contents of this run.
  591. * </p>
  592. *
  593. * @param value {@code true} if the strike property is applied to
  594. * this run
  595. */
  596. @Override
  597. public void setStrikeThrough(boolean value) {
  598. CTRPr pr = getRunProperties(true);
  599. CTOnOff strike = pr.sizeOfStrikeArray() > 0 ? pr.getStrikeArray(0) : pr.addNewStrike();
  600. strike.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  601. }
  602. @Deprecated
  603. public boolean isStrike() {
  604. return isStrikeThrough();
  605. }
  606. @Deprecated
  607. public void setStrike(boolean value) {
  608. setStrikeThrough(value);
  609. }
  610. /**
  611. * Specifies that the contents of this run shall be displayed with a double
  612. * horizontal line through the center of the line.
  613. *
  614. * @return {@code true} if the double strike property is applied
  615. */
  616. @Override
  617. public boolean isDoubleStrikeThrough() {
  618. CTRPr pr = getRunProperties(false);
  619. return pr != null && pr.sizeOfDstrikeArray() > 0 && isCTOnOff(pr.getDstrikeArray(0));
  620. }
  621. /**
  622. * Specifies that the contents of this run shall be displayed with a
  623. * double horizontal line through the center of the line.
  624. *
  625. * @see #setStrikeThrough(boolean) for the rules about this
  626. */
  627. @Override
  628. public void setDoubleStrikethrough(boolean value) {
  629. CTRPr pr = getRunProperties(true);
  630. CTOnOff dstrike = pr.sizeOfDstrikeArray() > 0 ? pr.getDstrikeArray(0) : pr.addNewDstrike();
  631. dstrike.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  632. }
  633. @Override
  634. public boolean isSmallCaps() {
  635. CTRPr pr = getRunProperties(false);
  636. return pr != null && pr.sizeOfSmallCapsArray() > 0 && isCTOnOff(pr.getSmallCapsArray(0));
  637. }
  638. @Override
  639. public void setSmallCaps(boolean value) {
  640. CTRPr pr = getRunProperties(true);
  641. CTOnOff caps = pr.sizeOfSmallCapsArray() > 0 ? pr.getSmallCapsArray(0) : pr.addNewSmallCaps();
  642. caps.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  643. }
  644. @Override
  645. public boolean isCapitalized() {
  646. CTRPr pr = getRunProperties(false);
  647. return pr != null && pr.sizeOfCapsArray() > 0 && isCTOnOff(pr.getCapsArray(0));
  648. }
  649. @Override
  650. public void setCapitalized(boolean value) {
  651. CTRPr pr = getRunProperties(true);
  652. CTOnOff caps = pr.sizeOfCapsArray() > 0 ? pr.getCapsArray(0) : pr.addNewCaps();
  653. caps.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  654. }
  655. @Override
  656. public boolean isShadowed() {
  657. CTRPr pr = getRunProperties(false);
  658. return pr != null && pr.sizeOfShadowArray() > 0 && isCTOnOff(pr.getShadowArray(0));
  659. }
  660. @Override
  661. public void setShadow(boolean value) {
  662. CTRPr pr = getRunProperties(true);
  663. CTOnOff shadow = pr.sizeOfShadowArray() > 0 ? pr.getShadowArray(0) : pr.addNewShadow();
  664. shadow.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  665. }
  666. @Override
  667. public boolean isImprinted() {
  668. CTRPr pr = getRunProperties(false);
  669. return pr != null && pr.sizeOfImprintArray() > 0 && isCTOnOff(pr.getImprintArray(0));
  670. }
  671. @Override
  672. public void setImprinted(boolean value) {
  673. CTRPr pr = getRunProperties(true);
  674. CTOnOff imprinted = pr.sizeOfImprintArray() > 0 ? pr.getImprintArray(0) : pr.addNewImprint();
  675. imprinted.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  676. }
  677. @Override
  678. public boolean isEmbossed() {
  679. CTRPr pr = getRunProperties(false);
  680. return pr != null && pr.sizeOfEmbossArray() > 0 && isCTOnOff(pr.getEmbossArray(0));
  681. }
  682. @Override
  683. public void setEmbossed(boolean value) {
  684. CTRPr pr = getRunProperties(true);
  685. CTOnOff emboss = pr.sizeOfEmbossArray() > 0 ? pr.getEmbossArray(0) : pr.addNewEmboss();
  686. emboss.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  687. }
  688. /**
  689. * Specifies the alignment which shall be applied to the contents of this
  690. * run in relation to the default appearance of the run's text. This allows
  691. * the text to be repositioned as subscript or superscript without altering
  692. * the font size of the run properties.
  693. * <p>
  694. * If this element is not present, the default value is to leave the
  695. * formatting applied at previous level in the style hierarchy. If this
  696. * element is never applied in the style hierarchy, then the text shall not
  697. * be subscript or superscript relative to the default baseline location for
  698. * the contents of this run.
  699. * </p>
  700. *
  701. * @param valign Type of vertical align to apply
  702. * @see VerticalAlign
  703. */
  704. public void setSubscript(VerticalAlign valign) {
  705. CTRPr pr = getRunProperties(true);
  706. CTVerticalAlignRun ctValign = pr.sizeOfVertAlignArray() > 0 ? pr.getVertAlignArray(0) : pr.addNewVertAlign();
  707. ctValign.setVal(STVerticalAlignRun.Enum.forInt(valign.getValue()));
  708. }
  709. @Override
  710. public int getKerning() {
  711. CTRPr pr = getRunProperties(false);
  712. if (pr == null || pr.sizeOfKernArray() == 0) {
  713. return 0;
  714. }
  715. return (int)POIXMLUnits.parseLength(pr.getKernArray(0).xgetVal());
  716. }
  717. @Override
  718. public void setKerning(int kern) {
  719. CTRPr pr = getRunProperties(true);
  720. CTHpsMeasure kernmes = pr.sizeOfKernArray() > 0 ? pr.getKernArray(0) : pr.addNewKern();
  721. kernmes.setVal(BigInteger.valueOf(kern));
  722. }
  723. @Override
  724. public boolean isHighlighted() {
  725. CTRPr pr = getRunProperties(false);
  726. if (pr == null || pr.sizeOfHighlightArray() == 0) {
  727. return false;
  728. }
  729. STHighlightColor.Enum val = pr.getHighlightArray(0).getVal();
  730. return val != null && val != STHighlightColor.NONE;
  731. }
  732. // TODO Provide a wrapper round STHighlightColor, then expose getter/setter
  733. // for the highlight colour. Ideally also then add to CharacterRun interface
  734. @Override
  735. public int getCharacterSpacing() {
  736. CTRPr pr = getRunProperties(false);
  737. if (pr == null || pr.sizeOfSpacingArray() == 0) {
  738. return 0;
  739. }
  740. return (int)Units.toDXA(POIXMLUnits.parseLength(pr.getSpacingArray(0).xgetVal()));
  741. }
  742. @Override
  743. public void setCharacterSpacing(int twips) {
  744. CTRPr pr = getRunProperties(true);
  745. CTSignedTwipsMeasure spc = pr.sizeOfSpacingArray() > 0 ? pr.getSpacingArray(0) : pr.addNewSpacing();
  746. spc.setVal(BigInteger.valueOf(twips));
  747. }
  748. /**
  749. * Gets the fonts which shall be used to display the text contents of
  750. * this run. Specifies a font which shall be used to format all characters
  751. * in the ASCII range (0 - 127) within the parent run
  752. *
  753. * @return a string representing the font family
  754. */
  755. public String getFontFamily() {
  756. return getFontFamily(null);
  757. }
  758. /**
  759. * Specifies the fonts which shall be used to display the text contents of
  760. * this run. Specifies a font which shall be used to format all characters
  761. * in the ASCII range (0 - 127) within the parent run.
  762. * <p>
  763. * Also sets the other font ranges, if they haven't been set before
  764. *
  765. * @param fontFamily The font family to apply
  766. * @see FontCharRange
  767. */
  768. public void setFontFamily(String fontFamily) {
  769. setFontFamily(fontFamily, null);
  770. }
  771. /**
  772. * Alias for {@link #getFontFamily()}
  773. */
  774. @Override
  775. public String getFontName() {
  776. return getFontFamily();
  777. }
  778. /**
  779. * Gets the font family for the specified font char range.
  780. * If fcr is null, the font char range "ascii" is used
  781. *
  782. * @param fcr the font char range, defaults to "ansi"
  783. * @return a string representing the font famil
  784. */
  785. public String getFontFamily(FontCharRange fcr) {
  786. CTRPr pr = getRunProperties(false);
  787. if (pr == null || pr.sizeOfRFontsArray() == 0) {
  788. return null;
  789. }
  790. CTFonts fonts = pr.getRFontsArray(0);
  791. switch (fcr == null ? FontCharRange.ascii : fcr) {
  792. default:
  793. case ascii:
  794. return fonts.getAscii();
  795. case cs:
  796. return fonts.getCs();
  797. case eastAsia:
  798. return fonts.getEastAsia();
  799. case hAnsi:
  800. return fonts.getHAnsi();
  801. }
  802. }
  803. /**
  804. * Specifies the fonts which shall be used to display the text contents of
  805. * this run. The default handling for fcr == null is to overwrite the
  806. * ascii font char range with the given font family and also set all not
  807. * specified font ranges
  808. *
  809. * @param fontFamily The font family to apply
  810. * @param fcr FontCharRange or null for default handling
  811. */
  812. public void setFontFamily(String fontFamily, FontCharRange fcr) {
  813. CTRPr pr = getRunProperties(true);
  814. CTFonts fonts = pr.sizeOfRFontsArray() > 0 ? pr.getRFontsArray(0) : pr.addNewRFonts();
  815. if (fcr == null) {
  816. fonts.setAscii(fontFamily);
  817. if (!fonts.isSetHAnsi()) {
  818. fonts.setHAnsi(fontFamily);
  819. }
  820. if (!fonts.isSetCs()) {
  821. fonts.setCs(fontFamily);
  822. }
  823. if (!fonts.isSetEastAsia()) {
  824. fonts.setEastAsia(fontFamily);
  825. }
  826. } else {
  827. switch (fcr) {
  828. case ascii:
  829. fonts.setAscii(fontFamily);
  830. break;
  831. case cs:
  832. fonts.setCs(fontFamily);
  833. break;
  834. case eastAsia:
  835. fonts.setEastAsia(fontFamily);
  836. break;
  837. case hAnsi:
  838. fonts.setHAnsi(fontFamily);
  839. break;
  840. }
  841. }
  842. }
  843. /**
  844. * Specifies the font size which shall be applied to all non complex script
  845. * characters in the contents of this run when displayed.
  846. *
  847. * @return value representing the font size (non-integer size will be rounded with half rounding up,
  848. * -1 is returned if size not set)
  849. * @deprecated use {@link #getFontSizeAsDouble()}
  850. */
  851. @Deprecated
  852. @Removal(version = "6.0.0")
  853. @Override
  854. public int getFontSize() {
  855. BigDecimal bd = getFontSizeAsBigDecimal(0);
  856. return bd == null ? -1 : bd.intValue();
  857. }
  858. /**
  859. * Specifies the font size which shall be applied to the non-complex
  860. * characters in the contents of this run when displayed.
  861. *
  862. * @return value representing the font size (can be null if size not set)
  863. * @since POI 5.0.0
  864. */
  865. @Override
  866. public Double getFontSizeAsDouble() {
  867. BigDecimal bd = getFontSizeAsBigDecimal(1);
  868. return bd == null ? null : bd.doubleValue();
  869. }
  870. /**
  871. * Specifies the font size which shall be applied to the complex script
  872. * characters in the contents of this run when displayed.
  873. *
  874. * @return value representing the font size for the complex scripts (can be null if size not set)
  875. * @since POI 5.2.5
  876. */
  877. public Double getComplexScriptFontSizeAsDouble() {
  878. BigDecimal bd = getComplexScriptFontSizeAsBigDecimal(1);
  879. return bd == null ? null : bd.doubleValue();
  880. }
  881. private BigDecimal getFontSizeAsBigDecimal(int scale) {
  882. CTRPr pr = getRunProperties(false);
  883. return (pr != null && pr.sizeOfSzArray() > 0)
  884. ? BigDecimal.valueOf(Units.toPoints(POIXMLUnits.parseLength(pr.getSzArray(0).xgetVal()))).divide(BigDecimal.valueOf(4), scale, RoundingMode.HALF_UP)
  885. : null;
  886. }
  887. private BigDecimal getComplexScriptFontSizeAsBigDecimal(int scale) {
  888. CTRPr pr = getRunProperties(false);
  889. return (pr != null && pr.sizeOfSzCsArray() > 0)
  890. ? BigDecimal.valueOf(Units.toPoints(POIXMLUnits.parseLength(pr.getSzCsArray(0).xgetVal()))).divide(BigDecimal.valueOf(4), scale, RoundingMode.HALF_UP)
  891. : null;
  892. }
  893. /**
  894. * Specifies the font size which shall be applied to all non complex script
  895. * characters in the contents of this run when displayed.
  896. * <p>
  897. * If this element is not present, the default value is to leave the value
  898. * applied at previous level in the style hierarchy. If this element is
  899. * never applied in the style hierarchy, then any appropriate font size may
  900. * be used for non complex script characters.
  901. * </p>
  902. *
  903. * @param size The font size as number of point measurements.
  904. * @see #setFontSize(double)
  905. */
  906. @Override
  907. public void setFontSize(int size) {
  908. BigInteger bint = BigInteger.valueOf(size);
  909. CTRPr pr = getRunProperties(true);
  910. CTHpsMeasure ctSize = pr.sizeOfSzArray() > 0 ? pr.getSzArray(0) : pr.addNewSz();
  911. ctSize.setVal(bint.multiply(BigInteger.valueOf(2)));
  912. }
  913. /**
  914. * Specifies the font size which shall be applied to the currently specified complex
  915. * script characters in the contents of this run when displayed.
  916. * <p>
  917. * If this element is not present, the default value is to leave the value
  918. * applied at previous level in the style hierarchy. If this element is
  919. * never applied in the style hierarchy, then any appropriate font size may
  920. * be used for the non-complex characters.
  921. * </p>
  922. *
  923. * @param size The font size as number of point measurements.
  924. * @see #setComplexScriptFontSize(double)
  925. * @since POI 5.2.5
  926. */
  927. public void setComplexScriptFontSize(int size) {
  928. CTRPr pr = getRunProperties(true);
  929. BigInteger bint = BigInteger.valueOf(size);
  930. CTHpsMeasure ctCsSize = pr.sizeOfSzCsArray() > 0 ? pr.getSzCsArray(0) : pr.addNewSzCs();
  931. ctCsSize.setVal(bint.multiply(BigInteger.valueOf(2)));
  932. }
  933. /**
  934. * Specifies the font size which shall be applied to the currently specified non-complex
  935. * characters in the contents of this run when displayed.
  936. *
  937. * <p>
  938. * If this element is not present, the default value is to leave the value
  939. * applied at previous level in the style hierarchy. If this element is
  940. * never applied in the style hierarchy, then any appropriate font size may
  941. * be used for non complex script characters.
  942. * </p>
  943. *
  944. * @param size The font size as number of point measurements.
  945. * @see #setFontSize(int)
  946. * @since POI 5.0.0
  947. */
  948. @Override
  949. public void setFontSize(double size) {
  950. BigDecimal bd = BigDecimal.valueOf(size);
  951. CTRPr pr = getRunProperties(true);
  952. CTHpsMeasure ctSize = pr.sizeOfSzArray() > 0 ? pr.getSzArray(0) : pr.addNewSz();
  953. ctSize.setVal(bd.multiply(BigDecimal.valueOf(2)).setScale(0, RoundingMode.HALF_UP).toBigInteger());
  954. }
  955. /**
  956. * Specifies the font size which shall be applied to the currently specified complex
  957. * characters in the contents of this run when displayed.
  958. *
  959. * <p>
  960. * If this element is not present, the default value is to leave the value
  961. * applied at previous level in the style hierarchy. If this element is
  962. * never applied in the style hierarchy, then any appropriate font size may
  963. * be used for the non-complex characters.
  964. * </p>
  965. *
  966. * @param size The font size as number of point measurements.
  967. * @see #setFontSize(int)
  968. * @since POI 5.2.5
  969. */
  970. public void setComplexScriptFontSize(double size) {
  971. CTRPr pr = getRunProperties(true);
  972. BigDecimal bd = BigDecimal.valueOf(size);
  973. CTHpsMeasure ctCsSize = pr.sizeOfSzCsArray() > 0 ? pr.getSzCsArray(0) : pr.addNewSzCs();
  974. ctCsSize.setVal(bd.multiply(BigDecimal.valueOf(2)).setScale(0, RoundingMode.HALF_UP).toBigInteger());
  975. }
  976. /**
  977. * This element specifies the amount by which text shall be raised or
  978. * lowered for this run in relation to the default baseline of the
  979. * surrounding non-positioned text. This allows the text to be repositioned
  980. * without altering the font size of the contents.
  981. *
  982. * @return a big integer representing the amount of text shall be "moved"
  983. */
  984. public int getTextPosition() {
  985. CTRPr pr = getRunProperties(false);
  986. return (pr != null && pr.sizeOfPositionArray() > 0) ? (int)(Units.toPoints(POIXMLUnits.parseLength(pr.getPositionArray(0).xgetVal())) / 2.)
  987. : -1;
  988. }
  989. /**
  990. * This element specifies the amount by which text shall be raised or
  991. * lowered for this run in relation to the default baseline of the
  992. * surrounding non-positioned text. This allows the text to be repositioned
  993. * without altering the font size of the contents.
  994. * <p>
  995. * If the val attribute is positive, then the parent run shall be raised
  996. * above the baseline of the surrounding text by the specified number of
  997. * half-points. If the val attribute is negative, then the parent run shall
  998. * be lowered below the baseline of the surrounding text by the specified
  999. * number of half-points.
  1000. * </p>
  1001. * <p>
  1002. * If this element is not present, the default value is to leave the
  1003. * formatting applied at previous level in the style hierarchy. If this
  1004. * element is never applied in the style hierarchy, then the text shall not
  1005. * be raised or lowered relative to the default baseline location for the
  1006. * contents of this run.
  1007. * </p>
  1008. *
  1009. * @param val Positive values will raise the baseline of the text, negative
  1010. * values will lower it.
  1011. */
  1012. public void setTextPosition(int val) {
  1013. BigInteger bint = new BigInteger(Integer.toString(val));
  1014. CTRPr pr = getRunProperties(true);
  1015. CTSignedHpsMeasure position = pr.sizeOfPositionArray() > 0 ? pr.getPositionArray(0) : pr.addNewPosition();
  1016. position.setVal(bint);
  1017. }
  1018. /**
  1019. * Not yet implemented.
  1020. */
  1021. public void removeBreak() {
  1022. // TODO not yet implemented
  1023. }
  1024. /**
  1025. * Specifies that a break shall be placed at the current location in the run
  1026. * content.
  1027. * A break is a special character which is used to override the
  1028. * normal line breaking that would be performed based on the normal layout
  1029. * of the document's contents.
  1030. *
  1031. * @see #addCarriageReturn()
  1032. */
  1033. public void addBreak() {
  1034. run.addNewBr();
  1035. }
  1036. /**
  1037. * Specifies that a break shall be placed at the current location in the run
  1038. * content.
  1039. * A break is a special character which is used to override the
  1040. * normal line breaking that would be performed based on the normal layout
  1041. * of the document's contents.
  1042. * <p>
  1043. * The behavior of this break character (the
  1044. * location where text shall be restarted after this break) shall be
  1045. * determined by its type values.
  1046. * </p>
  1047. *
  1048. * @see BreakType
  1049. */
  1050. public void addBreak(BreakType type) {
  1051. CTBr br = run.addNewBr();
  1052. br.setType(STBrType.Enum.forInt(type.getValue()));
  1053. }
  1054. /**
  1055. * Specifies that a break shall be placed at the current location in the run
  1056. * content. A break is a special character which is used to override the
  1057. * normal line breaking that would be performed based on the normal layout
  1058. * of the document's contents.
  1059. * <p>
  1060. * The behavior of this break character (the
  1061. * location where text shall be restarted after this break) shall be
  1062. * determined by its type (in this case is BreakType.TEXT_WRAPPING as default) and clear attribute values.
  1063. * </p>
  1064. *
  1065. * @see BreakClear
  1066. */
  1067. public void addBreak(BreakClear clear) {
  1068. CTBr br = run.addNewBr();
  1069. br.setType(STBrType.Enum.forInt(BreakType.TEXT_WRAPPING.getValue()));
  1070. br.setClear(STBrClear.Enum.forInt(clear.getValue()));
  1071. }
  1072. /**
  1073. * Specifies that a tab shall be placed at the current location in
  1074. * the run content.
  1075. */
  1076. public void addTab() {
  1077. run.addNewTab();
  1078. }
  1079. public void removeTab() {
  1080. //TODO
  1081. }
  1082. /**
  1083. * Specifies that a carriage return shall be placed at the
  1084. * current location in the run content.
  1085. * A carriage return is used to end the current line of text in
  1086. * Wordprocess.
  1087. * The behavior of a carriage return in run content shall be
  1088. * identical to a break character with null type and clear attributes, which
  1089. * shall end the current line and find the next available line on which to
  1090. * continue.
  1091. * The carriage return character forced the following text to be
  1092. * restarted on the next available line in the document.
  1093. */
  1094. public void addCarriageReturn() {
  1095. run.addNewCr();
  1096. }
  1097. public void removeCarriageReturn() {
  1098. //TODO
  1099. }
  1100. /**
  1101. * Adds a picture to the run. This method handles
  1102. * attaching the picture data to the overall file.
  1103. *
  1104. * @param pictureData The raw picture data
  1105. * @param pictureType The type of the picture, eg {@link Document#PICTURE_TYPE_JPEG}
  1106. * @param width width in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
  1107. * @param height height in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
  1108. * @throws InvalidFormatException If the format of the picture is not known.
  1109. * @throws IOException If reading the picture-data from the stream fails.
  1110. * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF
  1111. * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF
  1112. * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PICT
  1113. * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_JPEG
  1114. * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PNG
  1115. * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_GIF
  1116. * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB
  1117. * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_SVG
  1118. * @see #addPicture(InputStream, PictureType, String, int, int)
  1119. */
  1120. public XWPFPicture addPicture(InputStream pictureData, int pictureType, String filename, int width, int height)
  1121. throws InvalidFormatException, IOException {
  1122. return addPicture(pictureData, PictureType.findByOoxmlId(pictureType), filename, width, height);
  1123. }
  1124. /**
  1125. * Adds a picture to the run. This method handles
  1126. * attaching the picture data to the overall file.
  1127. *
  1128. * @param pictureData The raw picture data
  1129. * @param pictureType The {@link PictureType} of the picture
  1130. * @param width width in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
  1131. * @param height height in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
  1132. * @throws InvalidFormatException If the format of the picture is not known.
  1133. * @throws IOException If reading the picture-data from the stream fails.
  1134. * @since POI 5.2.3
  1135. */
  1136. public XWPFPicture addPicture(InputStream pictureData, PictureType pictureType, String filename, int width, int height)
  1137. throws InvalidFormatException, IOException {
  1138. if (pictureType == null) {
  1139. throw new InvalidFormatException("pictureType is not supported");
  1140. }
  1141. String relationId;
  1142. XWPFPictureData picData;
  1143. // Work out what to add the picture to, then add both the
  1144. // picture and the relationship for it
  1145. // TODO Should we have an interface for this sort of thing?
  1146. if (parent.getPart() instanceof XWPFHeaderFooter) {
  1147. XWPFHeaderFooter headerFooter = (XWPFHeaderFooter) parent.getPart();
  1148. relationId = headerFooter.addPictureData(pictureData, pictureType);
  1149. picData = (XWPFPictureData) headerFooter.getRelationById(relationId);
  1150. } else if (parent.getPart() instanceof XWPFComments) {
  1151. XWPFComments comments = (XWPFComments) parent.getPart();
  1152. relationId = comments.addPictureData(pictureData, pictureType);
  1153. picData = (XWPFPictureData) comments.getRelationById(relationId);
  1154. } else {
  1155. @SuppressWarnings("resource")
  1156. XWPFDocument doc = parent.getDocument();
  1157. relationId = doc.addPictureData(pictureData, pictureType);
  1158. picData = (XWPFPictureData) doc.getRelationById(relationId);
  1159. }
  1160. // Create the drawing entry for it
  1161. try {
  1162. CTDrawing drawing = run.addNewDrawing();
  1163. CTInline inline = drawing.addNewInline();
  1164. // Do the fiddly namespace bits on the inline
  1165. // (We need full control of what goes where and as what)
  1166. String xml =
  1167. "<a:graphic xmlns:a=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
  1168. "<a:graphicData uri=\"" + CTPicture.type.getName().getNamespaceURI() + "\">" +
  1169. "<pic:pic xmlns:pic=\"" + CTPicture.type.getName().getNamespaceURI() + "\" />" +
  1170. "</a:graphicData>" +
  1171. "</a:graphic>";
  1172. InputSource is = new InputSource(new StringReader(xml));
  1173. org.w3c.dom.Document doc = DocumentHelper.readDocument(is);
  1174. inline.set(XmlToken.Factory.parse(doc.getDocumentElement(), DEFAULT_XML_OPTIONS));
  1175. // Setup the inline
  1176. inline.setDistT(0);
  1177. inline.setDistR(0);
  1178. inline.setDistB(0);
  1179. inline.setDistL(0);
  1180. CTNonVisualDrawingProps docPr = inline.addNewDocPr();
  1181. long id = getParent().getDocument().getDrawingIdManager().reserveNew();
  1182. docPr.setId(id);
  1183. /* This name is not visible in Word 2010 anywhere. */
  1184. docPr.setName("Drawing " + id);
  1185. docPr.setDescr(filename);
  1186. CTPositiveSize2D extent = inline.addNewExtent();
  1187. extent.setCx(width);
  1188. extent.setCy(height);
  1189. // Grab the picture object
  1190. CTGraphicalObject graphic = inline.getGraphic();
  1191. CTGraphicalObjectData graphicData = graphic.getGraphicData();
  1192. CTPicture pic = getCTPictures(graphicData).get(0);
  1193. // Set it up
  1194. CTPictureNonVisual nvPicPr = pic.addNewNvPicPr();
  1195. CTNonVisualDrawingProps cNvPr = nvPicPr.addNewCNvPr();
  1196. /* use "0" for the id. See ECM-576, 20.2.2.3 */
  1197. cNvPr.setId(0L);
  1198. /* This name is not visible in Word 2010 anywhere */
  1199. cNvPr.setName("Picture " + id);
  1200. cNvPr.setDescr(filename);
  1201. CTNonVisualPictureProperties cNvPicPr = nvPicPr.addNewCNvPicPr();
  1202. cNvPicPr.addNewPicLocks().setNoChangeAspect(true);
  1203. CTBlipFillProperties blipFill = pic.addNewBlipFill();
  1204. CTBlip blip = blipFill.addNewBlip();
  1205. blip.setEmbed(parent.getPart().getRelationId(picData));
  1206. blipFill.addNewStretch().addNewFillRect();
  1207. CTShapeProperties spPr = pic.addNewSpPr();
  1208. CTTransform2D xfrm = spPr.addNewXfrm();
  1209. CTPoint2D off = xfrm.addNewOff();
  1210. off.setX(0);
  1211. off.setY(0);
  1212. CTPositiveSize2D ext = xfrm.addNewExt();
  1213. ext.setCx(width);
  1214. ext.setCy(height);
  1215. CTPresetGeometry2D prstGeom = spPr.addNewPrstGeom();
  1216. prstGeom.setPrst(STShapeType.RECT);
  1217. prstGeom.addNewAvLst();
  1218. // Finish up
  1219. XWPFPicture xwpfPicture = new XWPFPicture(pic, this);
  1220. pictures.add(xwpfPicture);
  1221. return xwpfPicture;
  1222. } catch (XmlException | SAXException e) {
  1223. throw new IllegalStateException(e);
  1224. }
  1225. }
  1226. /**
  1227. * this method add chart template into document
  1228. *
  1229. * @param chartRelId relation id of chart in document relation file
  1230. * @since POI 4.0.0
  1231. */
  1232. @Internal
  1233. public CTInline addChart(String chartRelId) throws InvalidFormatException, IOException {
  1234. try {
  1235. CTInline inline = run.addNewDrawing().addNewInline();
  1236. //xml part of chart in document
  1237. String xml =
  1238. "<a:graphic xmlns:a=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
  1239. "<a:graphicData uri=\"" + CTChart.type.getName().getNamespaceURI() + "\">" +
  1240. "<c:chart xmlns:c=\"" + CTChart.type.getName().getNamespaceURI() + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\" r:id=\"" + chartRelId + "\" />" +
  1241. "</a:graphicData>" +
  1242. "</a:graphic>";
  1243. InputSource is = new InputSource(new StringReader(xml));
  1244. org.w3c.dom.Document doc = DocumentHelper.readDocument(is);
  1245. inline.set(XmlToken.Factory.parse(doc.getDocumentElement(), DEFAULT_XML_OPTIONS));
  1246. // Setup the inline with 0 margin
  1247. inline.setDistT(0);
  1248. inline.setDistR(0);
  1249. inline.setDistB(0);
  1250. inline.setDistL(0);
  1251. CTNonVisualDrawingProps docPr = inline.addNewDocPr();
  1252. long id = getParent().getDocument().getDrawingIdManager().reserveNew();
  1253. docPr.setId(id);
  1254. //This name is not visible in Word anywhere.
  1255. docPr.setName("chart " + id);
  1256. return inline;
  1257. } catch (XmlException | SAXException e) {
  1258. throw new IllegalStateException(e);
  1259. }
  1260. }
  1261. /**
  1262. * Returns the embedded pictures of the run. These
  1263. * are pictures which reference an external,
  1264. * embedded picture image such as a .png or .jpg
  1265. */
  1266. public List<XWPFPicture> getEmbeddedPictures() {
  1267. return pictures;
  1268. }
  1269. /**
  1270. * Set the style ID for the run.
  1271. *
  1272. * @param styleId ID (not name) of the style to set for the run, e.g. "BoldItalic" (not "Bold Italic").
  1273. * @since POI 4.1.1
  1274. */
  1275. public void setStyle(String styleId) {
  1276. CTRPr pr = getCTR().getRPr();
  1277. if (null == pr) {
  1278. pr = getCTR().addNewRPr();
  1279. }
  1280. CTString style = pr.sizeOfRStyleArray() > 0 ? pr.getRStyleArray(0) : pr.addNewRStyle();
  1281. style.setVal(styleId);
  1282. }
  1283. /**
  1284. * Return this run's style ID. If this run has no style (no run properties or properties without a style),
  1285. * an empty string is returned.
  1286. *
  1287. * @since 4.1.1
  1288. */
  1289. public String getStyle() {
  1290. CTRPr pr = getCTR().getRPr();
  1291. if (pr == null || pr.sizeOfRStyleArray() <= 0) {
  1292. return "";
  1293. }
  1294. CTString style = pr.getRStyleArray(0);
  1295. return null == style ? "" : style.getVal();
  1296. }
  1297. /**
  1298. * Returns the string version of the text and the phonetic string
  1299. */
  1300. @Override
  1301. public String toString() {
  1302. String phonetic = getPhonetic();
  1303. if (phonetic.length() > 0) {
  1304. return text() + " (" + phonetic + ")";
  1305. } else {
  1306. return text();
  1307. }
  1308. }
  1309. /**
  1310. * Returns the string version of the text, with tabs and
  1311. * carriage returns in place of their xml equivalents.
  1312. */
  1313. @Override
  1314. public String text() {
  1315. StringBuilder text = new StringBuilder(64);
  1316. // Grab the text and tabs of the text run
  1317. // Do so in a way that preserves the ordering
  1318. try (XmlCursor c = run.newCursor()) {
  1319. c.selectPath("./*");
  1320. while (c.toNextSelection()) {
  1321. XmlObject o = c.getObject();
  1322. if (o instanceof CTRuby) {
  1323. handleRuby(o, text, false);
  1324. continue;
  1325. }
  1326. _getText(o, text);
  1327. }
  1328. }
  1329. return text.toString();
  1330. }
  1331. /**
  1332. * @return the phonetic (ruby) string associated with this run or an empty String if none exists
  1333. */
  1334. public String getPhonetic() {
  1335. StringBuilder text = new StringBuilder(64);
  1336. // Grab the text and tabs of the text run
  1337. // Do so in a way that preserves the ordering
  1338. try (XmlCursor c = run.newCursor()) {
  1339. c.selectPath("./*");
  1340. while (c.toNextSelection()) {
  1341. XmlObject o = c.getObject();
  1342. if (o instanceof CTRuby) {
  1343. handleRuby(o, text, true);
  1344. }
  1345. }
  1346. // Any picture text?
  1347. if (pictureText != null && pictureText.length() > 0) {
  1348. text.append("\n").append(pictureText).append("\n");
  1349. }
  1350. }
  1351. return text.toString();
  1352. }
  1353. /**
  1354. * @param rubyObj rubyobject
  1355. * @param text buffer to which to append the content
  1356. * @param extractPhonetic extract the phonetic (rt) component or the base component
  1357. */
  1358. private void handleRuby(XmlObject rubyObj, StringBuilder text, boolean extractPhonetic) {
  1359. try (XmlCursor c = rubyObj.newCursor()) {
  1360. //according to the spec, a ruby object
  1361. //has the phonetic (rt) first, then the actual text (base)
  1362. //second.
  1363. c.selectPath(".//*");
  1364. boolean inRT = false;
  1365. boolean inBase = false;
  1366. while (c.toNextSelection()) {
  1367. XmlObject o = c.getObject();
  1368. if (o instanceof CTRubyContent) {
  1369. final Node node = o.getDomNode();
  1370. if (XSSFRelation.NS_WORDPROCESSINGML.equals(node.getNamespaceURI())) {
  1371. final String tagName = node.getLocalName();
  1372. if ("rt".equals(tagName)) {
  1373. inRT = true;
  1374. } else if ("rubyBase".equals(tagName)) {
  1375. inRT = false;
  1376. inBase = true;
  1377. }
  1378. }
  1379. } else {
  1380. if (extractPhonetic && inRT) {
  1381. _getText(o, text);
  1382. } else if (!extractPhonetic && inBase) {
  1383. _getText(o, text);
  1384. }
  1385. }
  1386. }
  1387. }
  1388. }
  1389. private void _getText(XmlObject o, StringBuilder text) {
  1390. if (o instanceof CTText) {
  1391. final Node node = o.getDomNode();
  1392. // Field Codes (w:instrText, defined in spec sec. 17.16.23)
  1393. // come up as instances of CTText, but we don't want them
  1394. // in the normal text output
  1395. if (!("instrText".equals(node.getLocalName()) && XSSFRelation.NS_WORDPROCESSINGML.equals(node.getNamespaceURI()))) {
  1396. String textValue = ((CTText) o).getStringValue();
  1397. if (textValue != null) {
  1398. if (isCapitalized() || isSmallCaps()) {
  1399. textValue = textValue.toUpperCase(LocaleUtil.getUserLocale());
  1400. }
  1401. text.append(textValue);
  1402. }
  1403. }
  1404. }
  1405. // Complex type evaluation (currently only for extraction of check boxes)
  1406. if (o instanceof CTFldChar) {
  1407. CTFldChar ctfldChar = ((CTFldChar) o);
  1408. if (ctfldChar.getFldCharType() == STFldCharType.BEGIN) {
  1409. if (ctfldChar.getFfData() != null) {
  1410. for (CTFFCheckBox checkBox : ctfldChar.getFfData().getCheckBoxList()) {
  1411. String textValue = checkBox.getDefault() != null && POIXMLUnits.parseOnOff(checkBox.getDefault().xgetVal()) ?
  1412. "|X|" : "|_|";
  1413. text.append(textValue);
  1414. }
  1415. }
  1416. }
  1417. }
  1418. if (o instanceof CTPTab) {
  1419. text.append('\t');
  1420. }
  1421. if (o instanceof CTBr) {
  1422. text.append('\n');
  1423. }
  1424. if (o instanceof CTEmpty) {
  1425. // Some inline text elements get returned not as
  1426. // themselves, but as CTEmpty, owing to some odd
  1427. // definitions around line 5642 of the XSDs
  1428. // This bit works around it, and replicates the above
  1429. // rules for that case
  1430. final Node node = o.getDomNode();
  1431. if (XSSFRelation.NS_WORDPROCESSINGML.equals(node.getNamespaceURI())) {
  1432. switch (node.getLocalName()) {
  1433. case "tab":
  1434. text.append('\t');
  1435. break;
  1436. case "br":
  1437. case "cr":
  1438. text.append('\n');
  1439. break;
  1440. }
  1441. }
  1442. }
  1443. if (o instanceof CTFtnEdnRef) {
  1444. CTFtnEdnRef ftn = (CTFtnEdnRef) o;
  1445. final int i = ftn.getId() == null ? -1 : ftn.getId().intValue();
  1446. String footnoteRef = ftn.getDomNode().getLocalName().equals("footnoteReference") ?
  1447. "[footnoteRef:" + i + "]" : "[endnoteRef:" + i + "]";
  1448. text.append(footnoteRef);
  1449. }
  1450. }
  1451. /**
  1452. * @see <a href="http://msdn.microsoft.com/en-us/library/ff533743(v=office.12).aspx">[MS-OI29500] Run Fonts</a>
  1453. */
  1454. public enum FontCharRange {
  1455. ascii /* char 0-127 */,
  1456. cs /* complex symbol */,
  1457. eastAsia /* east asia */,
  1458. hAnsi /* high ansi */
  1459. }
  1460. /**
  1461. * Set the text expand/collapse scale value.
  1462. *
  1463. * @param percentage The percentage to expand or compress the text
  1464. * @since 4.0.0
  1465. */
  1466. public void setTextScale(int percentage) {
  1467. CTRPr pr = getRunProperties(true);
  1468. CTTextScale scale = pr.sizeOfWArray() > 0 ? pr.getWArray(0) : pr.addNewW();
  1469. scale.setVal(percentage);
  1470. }
  1471. /**
  1472. * Gets the current text scale value.
  1473. *
  1474. * @return Value is an integer percentage
  1475. * @since 4.0.0
  1476. */
  1477. public int getTextScale() {
  1478. CTRPr pr = getRunProperties(false);
  1479. if (pr == null || pr.sizeOfWArray() == 0) {
  1480. return 100;
  1481. }
  1482. int value = POIXMLUnits.parsePercent(pr.getWArray(0).xgetVal());
  1483. // 100% scaling, that is, no change. See 17.3.2.43 w (Expanded/Compressed Text)
  1484. return value == 0 ? 100 : value / 1000;
  1485. }
  1486. /**
  1487. * Set the highlight color for the run. Silently does nothing of colorName is not a recognized value.
  1488. *
  1489. * @param colorName The name of the color as defined in the ST_HighlightColor simple type ({@link STHighlightColor})
  1490. * @since 4.0.0
  1491. */
  1492. public void setTextHighlightColor(String colorName) {
  1493. CTRPr pr = getRunProperties(true);
  1494. CTHighlight highlight = pr.sizeOfHighlightArray() > 0 ? pr.getHighlightArray(0) : pr.addNewHighlight();
  1495. STHighlightColor color = highlight.xgetVal();
  1496. if (color == null) {
  1497. color = STHighlightColor.Factory.newInstance();
  1498. }
  1499. STHighlightColor.Enum val = STHighlightColor.Enum.forString(colorName);
  1500. if (val != null) {
  1501. color.setStringValue(val.toString());
  1502. highlight.xsetVal(color);
  1503. }
  1504. }
  1505. /**
  1506. * Gets the highlight color for the run
  1507. *
  1508. * @return {@link STHighlightColor} for the run.
  1509. * @since 4.0.0
  1510. * @deprecated use {@link #getTextHighlightColor()} instead
  1511. */
  1512. @Deprecated
  1513. @Removal(version = "7.0.0")
  1514. public STHighlightColor.Enum getTextHightlightColor() {
  1515. return getTextHighlightColor();
  1516. }
  1517. /**
  1518. * Gets the highlight color for the run
  1519. *
  1520. * @return {@link STHighlightColor} for the run. The default is <code>NONE</code>;
  1521. * @since 5.2.3
  1522. */
  1523. public STHighlightColor.Enum getTextHighlightColor() {
  1524. CTRPr pr = getRunProperties(false);
  1525. if (pr == null) {
  1526. return STHighlightColor.NONE;
  1527. }
  1528. CTHighlight highlight = pr.sizeOfHighlightArray() > 0 ? pr.getHighlightArray(0) : pr.addNewHighlight();
  1529. STHighlightColor color = highlight.xgetVal();
  1530. if (color == null) {
  1531. color = STHighlightColor.Factory.newInstance();
  1532. color.setEnumValue(STHighlightColor.NONE);
  1533. }
  1534. return (STHighlightColor.Enum)(color.getEnumValue());
  1535. }
  1536. /**
  1537. * Get the vanish (hidden text) value
  1538. *
  1539. * @return True if the run is hidden text.
  1540. * @since 4.0.0
  1541. */
  1542. public boolean isVanish() {
  1543. CTRPr pr = getRunProperties(false);
  1544. return pr != null && pr.sizeOfVanishArray() > 0 && isCTOnOff(pr.getVanishArray(0));
  1545. }
  1546. /**
  1547. * The vanish (hidden text) property for the run.
  1548. *
  1549. * @param value Set to true to make the run hidden text.
  1550. * @since 4.0.0
  1551. */
  1552. public void setVanish(boolean value) {
  1553. CTRPr pr = getRunProperties(true);
  1554. CTOnOff vanish = pr.sizeOfVanishArray() > 0 ? pr.getVanishArray(0) : pr.addNewVanish();
  1555. vanish.setVal(value ? STOnOff1.ON : STOnOff1.OFF);
  1556. }
  1557. /**
  1558. * Get the vertical alignment value
  1559. *
  1560. * @return {@link STVerticalAlignRun.Enum} value (see 22.9.2.17 ST_VerticalAlignRun (Vertical Positioning Location)).
  1561. * The default is <code>BASELINE</code>.
  1562. * @since 4.0.0
  1563. */
  1564. public STVerticalAlignRun.Enum getVerticalAlignment() {
  1565. CTRPr pr = getRunProperties(false);
  1566. if (pr == null) {
  1567. return STVerticalAlignRun.BASELINE;
  1568. }
  1569. CTVerticalAlignRun vertAlign = pr.sizeOfVertAlignArray() > 0 ? pr.getVertAlignArray(0) : pr.addNewVertAlign();
  1570. STVerticalAlignRun.Enum val = vertAlign.getVal();
  1571. if (val == null) {
  1572. val = STVerticalAlignRun.BASELINE;
  1573. }
  1574. return val;
  1575. }
  1576. /**
  1577. * Set the vertical alignment of the run.
  1578. *
  1579. * @param verticalAlignment Vertical alignment value, one of "baseline", "superscript", or "subscript".
  1580. * @since 4.0.0
  1581. */
  1582. public void setVerticalAlignment(String verticalAlignment) {
  1583. CTRPr pr = getRunProperties(true);
  1584. CTVerticalAlignRun vertAlign = pr.sizeOfVertAlignArray() > 0 ? pr.getVertAlignArray(0) : pr.addNewVertAlign();
  1585. STVerticalAlignRun align = vertAlign.xgetVal();
  1586. if (align == null) {
  1587. align = STVerticalAlignRun.Factory.newInstance();
  1588. }
  1589. STVerticalAlignRun.Enum val = STVerticalAlignRun.Enum.forString(verticalAlignment);
  1590. if (val != null) {
  1591. align.setStringValue(val.toString());
  1592. vertAlign.xsetVal(align);
  1593. }
  1594. }
  1595. /**
  1596. * Get the emphasis mark value for the run.
  1597. *
  1598. * @return {@link STEm.Enum} emphasis mark type enumeration. See 17.18.24 ST_Em (Emphasis Mark Type).
  1599. * The default is <code>NONE</code>.
  1600. * @since 4.0.0
  1601. */
  1602. public STEm.Enum getEmphasisMark() {
  1603. CTRPr pr = getRunProperties(false);
  1604. if (pr == null) {
  1605. return STEm.NONE;
  1606. }
  1607. CTEm emphasis = pr.sizeOfEmArray() > 0 ? pr.getEmArray(0) : pr.addNewEm();
  1608. STEm.Enum val = emphasis.getVal();
  1609. if (val == null) {
  1610. val = STEm.NONE;
  1611. }
  1612. return val;
  1613. }
  1614. /**
  1615. * Set the emphasis mark for the run. The emphasis mark goes above or below the run
  1616. * text.
  1617. *
  1618. * @param markType Emphasis mark type name, e.g., "dot" or "none". See 17.18.24 ST_Em (Emphasis Mark Type)
  1619. * @since 4.0.0
  1620. */
  1621. public void setEmphasisMark(String markType) {
  1622. CTRPr pr = getRunProperties(true);
  1623. CTEm emphasisMark = pr.sizeOfEmArray() > 0 ? pr.getEmArray(0) : pr.addNewEm();
  1624. STEm mark = emphasisMark.xgetVal();
  1625. if (mark == null) {
  1626. mark = STEm.Factory.newInstance();
  1627. }
  1628. STEm.Enum val = STEm.Enum.forString(markType);
  1629. if (val != null) {
  1630. mark.setStringValue(val.toString());
  1631. emphasisMark.xsetVal(mark);
  1632. }
  1633. }
  1634. /**
  1635. * Get the run properties for the run.
  1636. *
  1637. * @param create If true, create the properties, if false, do not.
  1638. * @return The run properties or null if there are no properties and create is false.
  1639. */
  1640. protected CTRPr getRunProperties(boolean create) {
  1641. CTRPr pr = run.isSetRPr() ? run.getRPr() : null;
  1642. if (create && pr == null) {
  1643. pr = run.addNewRPr();
  1644. }
  1645. return pr;
  1646. }
  1647. }