Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. /*
  2. * ====================================================================
  3. * Licensed to the Apache Software Foundation (ASF) under one or more
  4. * contributor license agreements. See the NOTICE file distributed with
  5. * this work for additional information regarding copyright ownership.
  6. * The ASF licenses this file to You under the Apache License, Version 2.0
  7. * (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. * ====================================================================
  18. */
  19. package org.apache.poi.xslf.usermodel;
  20. import java.awt.Color;
  21. import java.awt.geom.Rectangle2D;
  22. import javax.xml.stream.XMLStreamException;
  23. import javax.xml.stream.XMLStreamReader;
  24. import org.apache.poi.openxml4j.opc.PackagePart;
  25. import org.apache.poi.sl.draw.geom.CustomGeometry;
  26. import org.apache.poi.sl.draw.geom.Guide;
  27. import org.apache.poi.sl.draw.geom.PresetGeometries;
  28. import org.apache.poi.sl.usermodel.FillStyle;
  29. import org.apache.poi.sl.usermodel.LineDecoration;
  30. import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
  31. import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
  32. import org.apache.poi.sl.usermodel.PaintStyle;
  33. import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
  34. import org.apache.poi.sl.usermodel.ShapeType;
  35. import org.apache.poi.sl.usermodel.SimpleShape;
  36. import org.apache.poi.sl.usermodel.StrokeStyle;
  37. import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
  38. import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
  39. import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
  40. import org.apache.poi.util.Beta;
  41. import org.apache.poi.util.Units;
  42. import org.apache.poi.xslf.model.PropertyFetcher;
  43. import org.apache.xmlbeans.XmlObject;
  44. import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles;
  45. import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
  46. import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
  47. import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
  48. import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
  49. import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
  50. import org.openxmlformats.schemas.drawingml.x2006.main.CTLineStyleList;
  51. import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
  52. import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
  53. import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
  54. import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
  55. import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties;
  56. import org.openxmlformats.schemas.drawingml.x2006.main.CTSRgbColor;
  57. import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
  58. import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
  59. import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
  60. import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
  61. import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
  62. import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
  63. import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
  64. import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;
  65. import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
  66. import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
  67. import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
  68. import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;
  69. import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
  70. import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
  71. import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
  72. /**
  73. * Represents a single (non-group) shape in a .pptx slide show
  74. *
  75. * @author Yegor Kozlov
  76. */
  77. @Beta
  78. public abstract class XSLFSimpleShape extends XSLFShape
  79. implements SimpleShape<XSLFShape,XSLFTextParagraph> {
  80. private static CTOuterShadowEffect NO_SHADOW = CTOuterShadowEffect.Factory.newInstance();
  81. /* package */XSLFSimpleShape(XmlObject shape, XSLFSheet sheet) {
  82. super(shape,sheet);
  83. }
  84. @Override
  85. public void setShapeType(ShapeType type) {
  86. STShapeType.Enum geom = STShapeType.Enum.forInt(type.ooxmlId);
  87. getSpPr().getPrstGeom().setPrst(geom);
  88. }
  89. @Override
  90. public ShapeType getShapeType(){
  91. STShapeType.Enum geom = getSpPr().getPrstGeom().getPrst();
  92. return ShapeType.forId(geom.intValue(), true);
  93. }
  94. protected CTTransform2D getSafeXfrm() {
  95. CTTransform2D xfrm = getXfrm();
  96. return (xfrm == null ? getSpPr().addNewXfrm() : xfrm);
  97. }
  98. protected CTTransform2D getXfrm() {
  99. PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>() {
  100. public boolean fetch(XSLFShape shape) {
  101. CTShapeProperties pr = shape.getSpPr();
  102. if (pr.isSetXfrm()) {
  103. setValue(pr.getXfrm());
  104. return true;
  105. }
  106. return false;
  107. }
  108. };
  109. fetchShapeProperty(fetcher);
  110. return fetcher.getValue();
  111. }
  112. @Override
  113. public Rectangle2D getAnchor() {
  114. CTTransform2D xfrm = getXfrm();
  115. CTPoint2D off = xfrm.getOff();
  116. double x = Units.toPoints(off.getX());
  117. double y = Units.toPoints(off.getY());
  118. CTPositiveSize2D ext = xfrm.getExt();
  119. double cx = Units.toPoints(ext.getCx());
  120. double cy = Units.toPoints(ext.getCy());
  121. return new Rectangle2D.Double(x, y, cx, cy);
  122. }
  123. @Override
  124. public void setAnchor(Rectangle2D anchor) {
  125. CTTransform2D xfrm = getSafeXfrm();
  126. CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
  127. long x = Units.toEMU(anchor.getX());
  128. long y = Units.toEMU(anchor.getY());
  129. off.setX(x);
  130. off.setY(y);
  131. CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm
  132. .addNewExt();
  133. long cx = Units.toEMU(anchor.getWidth());
  134. long cy = Units.toEMU(anchor.getHeight());
  135. ext.setCx(cx);
  136. ext.setCy(cy);
  137. }
  138. @Override
  139. public void setRotation(double theta) {
  140. getSafeXfrm().setRot((int) (theta * 60000));
  141. }
  142. @Override
  143. public double getRotation() {
  144. CTTransform2D xfrm = getXfrm();
  145. return (xfrm == null || !xfrm.isSetRot()) ? 0 : (xfrm.getRot() / 60000.d);
  146. }
  147. @Override
  148. public void setFlipHorizontal(boolean flip) {
  149. getSafeXfrm().setFlipH(flip);
  150. }
  151. @Override
  152. public void setFlipVertical(boolean flip) {
  153. getSafeXfrm().setFlipV(flip);
  154. }
  155. @Override
  156. public boolean getFlipHorizontal() {
  157. CTTransform2D xfrm = getXfrm();
  158. return (xfrm == null || !xfrm.isSetFlipH()) ? false : getXfrm().getFlipH();
  159. }
  160. @Override
  161. public boolean getFlipVertical() {
  162. CTTransform2D xfrm = getXfrm();
  163. return (xfrm == null || !xfrm.isSetFlipV()) ? false : getXfrm().getFlipV();
  164. }
  165. /**
  166. * Get default line properties defined in the theme (if any).
  167. * Used internally to resolve shape properties.
  168. *
  169. * @return line propeties from the theme of null
  170. */
  171. CTLineProperties getDefaultLineProperties() {
  172. CTShapeStyle style = getSpStyle();
  173. if (style == null) return null;
  174. CTStyleMatrixReference lnRef = style.getLnRef();
  175. if (lnRef == null) return null;
  176. // 1-based index of a line style within the style matrix
  177. int idx = (int)lnRef.getIdx();
  178. XSLFTheme theme = getSheet().getTheme();
  179. if (theme == null) return null;
  180. CTBaseStyles styles = theme.getXmlObject().getThemeElements();
  181. if (styles == null) return null;
  182. CTStyleMatrix styleMatrix = styles.getFmtScheme();
  183. if (styleMatrix == null) return null;
  184. CTLineStyleList lineStyles = styleMatrix.getLnStyleLst();
  185. if (lineStyles == null || lineStyles.sizeOfLnArray() < idx) return null;
  186. return lineStyles.getLnArray(idx - 1);
  187. }
  188. /**
  189. * @param color the color to paint the shape outline.
  190. * A <code>null</code> value turns off the shape outline.
  191. */
  192. public void setLineColor(Color color) {
  193. CTShapeProperties spPr = getSpPr();
  194. if (color == null) {
  195. if (spPr.isSetLn() && spPr.getLn().isSetSolidFill())
  196. spPr.getLn().unsetSolidFill();
  197. } else {
  198. CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr
  199. .addNewLn();
  200. CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
  201. rgb.setVal(new byte[]{(byte) color.getRed(),
  202. (byte) color.getGreen(), (byte) color.getBlue()});
  203. CTSolidColorFillProperties fill = ln.isSetSolidFill() ? ln
  204. .getSolidFill() : ln.addNewSolidFill();
  205. fill.setSrgbClr(rgb);
  206. if(fill.isSetHslClr()) fill.unsetHslClr();
  207. if(fill.isSetPrstClr()) fill.unsetPrstClr();
  208. if(fill.isSetSchemeClr()) fill.unsetSchemeClr();
  209. if(fill.isSetScrgbClr()) fill.unsetScrgbClr();
  210. if(fill.isSetSysClr()) fill.unsetSysClr();
  211. }
  212. }
  213. /**
  214. *
  215. * @return the color of the shape outline or <code>null</code>
  216. * if outline is turned off
  217. */
  218. public Color getLineColor() {
  219. PaintStyle ps = getLinePaint();
  220. if (ps instanceof SolidPaint) {
  221. return ((SolidPaint)ps).getSolidColor().getColor();
  222. }
  223. return null;
  224. }
  225. protected PaintStyle getLinePaint() {
  226. PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
  227. public boolean fetch(XSLFShape shape) {
  228. CTLineProperties spPr = shape.getSpPr().getLn();
  229. if (spPr != null) {
  230. if (spPr.isSetNoFill()) {
  231. setValue(null); // use it as 'nofill' value
  232. return true;
  233. }
  234. PaintStyle paint = null;
  235. PackagePart pp = getSheet().getPackagePart();
  236. for (XmlObject obj : spPr.selectPath("*")) {
  237. paint = selectPaint(obj, null, pp);
  238. if (paint != null) {
  239. setValue(paint);
  240. return true;
  241. }
  242. }
  243. CTShapeStyle style = shape.getSpStyle();
  244. if (style != null) {
  245. paint = selectPaint(style.getLnRef());
  246. if (paint != null) {
  247. setValue(paint);
  248. return true;
  249. }
  250. }
  251. }
  252. return false;
  253. }
  254. };
  255. fetchShapeProperty(fetcher);
  256. PaintStyle paint = fetcher.getValue();
  257. if (paint != null) return paint;
  258. // line color was not found, check if it is defined in the theme
  259. CTShapeStyle style = getSpStyle();
  260. if (style == null) return null;
  261. // get a reference to a line style within the style matrix.
  262. CTStyleMatrixReference lnRef = style.getLnRef();
  263. int idx = (int)lnRef.getIdx();
  264. CTSchemeColor phClr = lnRef.getSchemeClr();
  265. if(idx > 0){
  266. XSLFTheme theme = getSheet().getTheme();
  267. XmlObject lnProps = theme.getXmlObject().
  268. getThemeElements().getFmtScheme().getLnStyleLst().selectPath("*")[idx - 1];
  269. paint = getPaint(lnProps, phClr);
  270. }
  271. return paint;
  272. }
  273. /**
  274. *
  275. * @param width line width in points. <code>0</code> means no line
  276. */
  277. public void setLineWidth(double width) {
  278. CTShapeProperties spPr = getSpPr();
  279. if (width == 0.) {
  280. if (spPr.isSetLn() && spPr.getLn().isSetW())
  281. spPr.getLn().unsetW();
  282. } else {
  283. CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr
  284. .addNewLn();
  285. ln.setW(Units.toEMU(width));
  286. }
  287. }
  288. /**
  289. * @return line width in points. <code>0</code> means no line.
  290. */
  291. public double getLineWidth() {
  292. PropertyFetcher<Double> fetcher = new PropertyFetcher<Double>() {
  293. public boolean fetch(XSLFShape shape) {
  294. CTShapeProperties spPr = shape.getSpPr();
  295. CTLineProperties ln = spPr.getLn();
  296. if (ln != null) {
  297. if (ln.isSetNoFill()) {
  298. setValue(0.);
  299. return true;
  300. }
  301. if (ln.isSetW()) {
  302. setValue(Units.toPoints(ln.getW()));
  303. return true;
  304. }
  305. }
  306. return false;
  307. }
  308. };
  309. fetchShapeProperty(fetcher);
  310. double lineWidth = 0;
  311. if (fetcher.getValue() == null) {
  312. CTLineProperties defaultLn = getDefaultLineProperties();
  313. if (defaultLn != null) {
  314. if (defaultLn.isSetW()) lineWidth = Units.toPoints(defaultLn.getW());
  315. }
  316. } else {
  317. lineWidth = fetcher.getValue();
  318. }
  319. return lineWidth;
  320. }
  321. /**
  322. * @param compound set the line compound style
  323. */
  324. public void setLineCompound(LineCompound compound) {
  325. CTShapeProperties spPr = getSpPr();
  326. if (compound == null) {
  327. if (spPr.isSetLn() && spPr.getLn().isSetCmpd())
  328. spPr.getLn().unsetCmpd();
  329. } else {
  330. CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();
  331. STCompoundLine.Enum xCmpd;
  332. switch (compound) {
  333. default:
  334. case SINGLE:
  335. xCmpd = STCompoundLine.SNG;
  336. break;
  337. case DOUBLE:
  338. xCmpd = STCompoundLine.DBL;
  339. break;
  340. case THICK_THIN:
  341. xCmpd = STCompoundLine.THICK_THIN;
  342. break;
  343. case THIN_THICK:
  344. xCmpd = STCompoundLine.THIN_THICK;
  345. break;
  346. case TRIPLE:
  347. xCmpd = STCompoundLine.TRI;
  348. break;
  349. }
  350. ln.setCmpd(xCmpd);
  351. }
  352. }
  353. /**
  354. * @return the line compound
  355. */
  356. public LineCompound getLineCompound() {
  357. PropertyFetcher<Integer> fetcher = new PropertyFetcher<Integer>() {
  358. public boolean fetch(XSLFShape shape) {
  359. CTShapeProperties spPr = shape.getSpPr();
  360. CTLineProperties ln = spPr.getLn();
  361. if (ln != null) {
  362. STCompoundLine.Enum stCmpd = ln.getCmpd();
  363. if (stCmpd != null) {
  364. setValue(stCmpd.intValue());
  365. return true;
  366. }
  367. }
  368. return false;
  369. }
  370. };
  371. fetchShapeProperty(fetcher);
  372. Integer cmpd = fetcher.getValue();
  373. if (cmpd == null) {
  374. CTLineProperties defaultLn = getDefaultLineProperties();
  375. if (defaultLn != null) {
  376. STCompoundLine.Enum stCmpd = defaultLn.getCmpd();
  377. if (stCmpd != null) {
  378. cmpd = stCmpd.intValue();
  379. }
  380. }
  381. }
  382. if (cmpd == null) return null;
  383. switch (cmpd) {
  384. default:
  385. case STCompoundLine.INT_SNG:
  386. return LineCompound.SINGLE;
  387. case STCompoundLine.INT_DBL:
  388. return LineCompound.DOUBLE;
  389. case STCompoundLine.INT_THICK_THIN:
  390. return LineCompound.THICK_THIN;
  391. case STCompoundLine.INT_THIN_THICK:
  392. return LineCompound.THIN_THICK;
  393. case STCompoundLine.INT_TRI:
  394. return LineCompound.TRIPLE;
  395. }
  396. }
  397. /**
  398. *
  399. * @param dash a preset line dashing scheme to stroke thr shape outline
  400. */
  401. public void setLineDash(LineDash dash) {
  402. CTShapeProperties spPr = getSpPr();
  403. if (dash == null) {
  404. if (spPr.isSetLn() && spPr.getLn().isSetPrstDash())
  405. spPr.getLn().unsetPrstDash();
  406. } else {
  407. CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr.addNewLn();
  408. CTPresetLineDashProperties ldp = ln.isSetPrstDash() ? ln.getPrstDash() : ln.addNewPrstDash();
  409. ldp.setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));
  410. }
  411. }
  412. /**
  413. * @return a preset line dashing scheme to stroke thr shape outline
  414. */
  415. public LineDash getLineDash() {
  416. PropertyFetcher<LineDash> fetcher = new PropertyFetcher<LineDash>() {
  417. public boolean fetch(XSLFShape shape) {
  418. CTShapeProperties spPr = shape.getSpPr();
  419. CTLineProperties ln = spPr.getLn();
  420. if (ln != null) {
  421. CTPresetLineDashProperties ctDash = ln.getPrstDash();
  422. if (ctDash != null) {
  423. setValue(LineDash.fromOoxmlId(ctDash.getVal().intValue()));
  424. return true;
  425. }
  426. }
  427. return false;
  428. }
  429. };
  430. fetchShapeProperty(fetcher);
  431. LineDash dash = fetcher.getValue();
  432. if (dash == null) {
  433. CTLineProperties defaultLn = getDefaultLineProperties();
  434. if (defaultLn != null) {
  435. CTPresetLineDashProperties ctDash = defaultLn.getPrstDash();
  436. if (ctDash != null) {
  437. dash = LineDash.fromOoxmlId(ctDash.getVal().intValue());
  438. }
  439. }
  440. }
  441. return dash;
  442. }
  443. /**
  444. *
  445. * @param cap the line end cap style
  446. */
  447. public void setLineCap(LineCap cap) {
  448. CTShapeProperties spPr = getSpPr();
  449. if (cap == null) {
  450. if (spPr.isSetLn() && spPr.getLn().isSetCap())
  451. spPr.getLn().unsetCap();
  452. } else {
  453. CTLineProperties ln = spPr.isSetLn() ? spPr.getLn() : spPr
  454. .addNewLn();
  455. ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId));
  456. }
  457. }
  458. /**
  459. *
  460. * @return the line end cap style
  461. */
  462. public LineCap getLineCap() {
  463. PropertyFetcher<LineCap> fetcher = new PropertyFetcher<LineCap>() {
  464. public boolean fetch(XSLFShape shape) {
  465. CTShapeProperties spPr = shape.getSpPr();
  466. CTLineProperties ln = spPr.getLn();
  467. if (ln != null) {
  468. STLineCap.Enum stCap = ln.getCap();
  469. if (stCap != null) {
  470. setValue(LineCap.fromOoxmlId(stCap.intValue()));
  471. return true;
  472. }
  473. }
  474. return false;
  475. }
  476. };
  477. fetchShapeProperty(fetcher);
  478. LineCap cap = fetcher.getValue();
  479. if (cap == null) {
  480. CTLineProperties defaultLn = getDefaultLineProperties();
  481. if (defaultLn != null) {
  482. STLineCap.Enum stCap = defaultLn.getCap();
  483. if (stCap != null) {
  484. cap = LineCap.fromOoxmlId(stCap.intValue());
  485. }
  486. }
  487. }
  488. return cap;
  489. }
  490. @Override
  491. public void setFillColor(Color color) {
  492. CTShapeProperties spPr = getSpPr();
  493. if (color == null) {
  494. if (spPr.isSetSolidFill()) spPr.unsetSolidFill();
  495. if (!spPr.isSetNoFill()) spPr.addNewNoFill();
  496. } else {
  497. if (spPr.isSetNoFill()) spPr.unsetNoFill();
  498. CTSolidColorFillProperties fill = spPr.isSetSolidFill() ? spPr
  499. .getSolidFill() : spPr.addNewSolidFill();
  500. CTSRgbColor rgb = CTSRgbColor.Factory.newInstance();
  501. rgb.setVal(new byte[]{(byte) color.getRed(),
  502. (byte) color.getGreen(), (byte) color.getBlue()});
  503. fill.setSrgbClr(rgb);
  504. if(fill.isSetHslClr()) fill.unsetHslClr();
  505. if(fill.isSetPrstClr()) fill.unsetPrstClr();
  506. if(fill.isSetSchemeClr()) fill.unsetSchemeClr();
  507. if(fill.isSetScrgbClr()) fill.unsetScrgbClr();
  508. if(fill.isSetSysClr()) fill.unsetSysClr();
  509. }
  510. }
  511. @Override
  512. public Color getFillColor() {
  513. PaintStyle ps = getFillPaint();
  514. if (ps instanceof SolidPaint) {
  515. return ((SolidPaint)ps).getSolidColor().getColor();
  516. }
  517. return null;
  518. }
  519. /**
  520. * @return shadow of this shape or null if shadow is disabled
  521. */
  522. public XSLFShadow getShadow() {
  523. PropertyFetcher<CTOuterShadowEffect> fetcher = new PropertyFetcher<CTOuterShadowEffect>() {
  524. public boolean fetch(XSLFShape shape) {
  525. CTShapeProperties spPr = shape.getSpPr();
  526. if (spPr.isSetEffectLst()) {
  527. CTOuterShadowEffect obj = spPr.getEffectLst().getOuterShdw();
  528. setValue(obj == null ? NO_SHADOW : obj);
  529. return true;
  530. }
  531. return false;
  532. }
  533. };
  534. fetchShapeProperty(fetcher);
  535. CTOuterShadowEffect obj = fetcher.getValue();
  536. if (obj == null) {
  537. // fill color was not found, check if it is defined in the theme
  538. CTShapeStyle style = getSpStyle();
  539. if (style != null) {
  540. // 1-based index of a shadow style within the style matrix
  541. int idx = (int) style.getEffectRef().getIdx();
  542. if(idx != 0) {
  543. CTStyleMatrix styleMatrix = getSheet().getTheme().getXmlObject().getThemeElements().getFmtScheme();
  544. CTEffectStyleItem ef = styleMatrix.getEffectStyleLst().getEffectStyleArray(idx - 1);
  545. obj = ef.getEffectLst().getOuterShdw();
  546. }
  547. }
  548. }
  549. return (obj == null || obj == NO_SHADOW) ? null : new XSLFShadow(obj, this);
  550. }
  551. /**
  552. *
  553. * @return definition of the shape geometry
  554. */
  555. public CustomGeometry getGeometry(){
  556. CTShapeProperties spPr = getSpPr();
  557. CustomGeometry geom;
  558. PresetGeometries dict = PresetGeometries.getInstance();
  559. if(spPr.isSetPrstGeom()){
  560. String name = spPr.getPrstGeom().getPrst().toString();
  561. geom = dict.get(name);
  562. if(geom == null) {
  563. throw new IllegalStateException("Unknown shape geometry: " + name + ", available geometries are: " + dict.keySet());
  564. }
  565. } else if (spPr.isSetCustGeom()){
  566. XMLStreamReader staxReader = spPr.getCustGeom().newXMLStreamReader();
  567. geom = PresetGeometries.convertCustomGeometry(staxReader);
  568. try { staxReader.close(); }
  569. catch (XMLStreamException e) {}
  570. } else {
  571. geom = dict.get("rect");
  572. }
  573. return geom;
  574. }
  575. @Override
  576. void copy(XSLFShape sh){
  577. super.copy(sh);
  578. XSLFSimpleShape s = (XSLFSimpleShape)sh;
  579. Color srsSolidFill = s.getFillColor();
  580. Color tgtSoliFill = getFillColor();
  581. if(srsSolidFill != null && !srsSolidFill.equals(tgtSoliFill)){
  582. setFillColor(srsSolidFill);
  583. }
  584. if(getSpPr().isSetBlipFill()){
  585. CTBlip blip = getSpPr().getBlipFill().getBlip();
  586. String blipId = blip.getEmbed();
  587. String relId = getSheet().importBlip(blipId, s.getSheet().getPackagePart());
  588. blip.setEmbed(relId);
  589. }
  590. Color srcLineColor = s.getLineColor();
  591. Color tgtLineColor = getLineColor();
  592. if(srcLineColor != null && !srcLineColor.equals(tgtLineColor)) {
  593. setLineColor(srcLineColor);
  594. }
  595. double srcLineWidth = s.getLineWidth();
  596. double tgtLineWidth = getLineWidth();
  597. if(srcLineWidth != tgtLineWidth) {
  598. setLineWidth(srcLineWidth);
  599. }
  600. LineDash srcLineDash = s.getLineDash();
  601. LineDash tgtLineDash = getLineDash();
  602. if(srcLineDash != null && srcLineDash != tgtLineDash) {
  603. setLineDash(srcLineDash);
  604. }
  605. LineCap srcLineCap = s.getLineCap();
  606. LineCap tgtLineCap = getLineCap();
  607. if(srcLineCap != null && srcLineCap != tgtLineCap) {
  608. setLineCap(srcLineCap);
  609. }
  610. }
  611. /**
  612. * Specifies the line end decoration, such as a triangle or arrowhead.
  613. */
  614. public void setLineHeadDecoration(DecorationShape style) {
  615. CTLineProperties ln = getSpPr().getLn();
  616. CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();
  617. if (style == null) {
  618. if (lnEnd.isSetType()) lnEnd.unsetType();
  619. } else {
  620. lnEnd.setType(STLineEndType.Enum.forInt(style.ooxmlId));
  621. }
  622. }
  623. public DecorationShape getLineHeadDecoration() {
  624. CTLineProperties ln = getSpPr().getLn();
  625. if (ln == null || !ln.isSetHeadEnd()) return DecorationShape.NONE;
  626. STLineEndType.Enum end = ln.getHeadEnd().getType();
  627. return end == null ? DecorationShape.NONE : DecorationShape.fromOoxmlId(end.intValue());
  628. }
  629. /**
  630. * specifies decorations which can be added to the head of a line.
  631. */
  632. public void setLineHeadWidth(DecorationSize style) {
  633. CTLineProperties ln = getSpPr().getLn();
  634. CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();
  635. if (style == null) {
  636. if (lnEnd.isSetW()) lnEnd.unsetW();
  637. } else {
  638. lnEnd.setW(STLineEndWidth.Enum.forInt(style.ooxmlId));
  639. }
  640. }
  641. public DecorationSize getLineHeadWidth() {
  642. CTLineProperties ln = getSpPr().getLn();
  643. if (ln == null || !ln.isSetHeadEnd()) return DecorationSize.MEDIUM;
  644. STLineEndWidth.Enum w = ln.getHeadEnd().getW();
  645. return w == null ? DecorationSize.MEDIUM : DecorationSize.fromOoxmlId(w.intValue());
  646. }
  647. /**
  648. * Specifies the line end width in relation to the line width.
  649. */
  650. public void setLineHeadLength(DecorationSize style) {
  651. CTLineProperties ln = getSpPr().getLn();
  652. CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();
  653. if (style == null) {
  654. if (lnEnd.isSetLen()) lnEnd.unsetLen();
  655. } else {
  656. lnEnd.setLen(STLineEndLength.Enum.forInt(style.ooxmlId));
  657. }
  658. }
  659. public DecorationSize getLineHeadLength() {
  660. CTLineProperties ln = getSpPr().getLn();
  661. if (ln == null || !ln.isSetHeadEnd()) return DecorationSize.MEDIUM;
  662. STLineEndLength.Enum len = ln.getHeadEnd().getLen();
  663. return len == null ? DecorationSize.MEDIUM : DecorationSize.fromOoxmlId(len.intValue());
  664. }
  665. /**
  666. * Specifies the line end decoration, such as a triangle or arrowhead.
  667. */
  668. public void setLineTailDecoration(DecorationShape style) {
  669. CTLineProperties ln = getSpPr().getLn();
  670. CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
  671. if (style == null) {
  672. if (lnEnd.isSetType()) lnEnd.unsetType();
  673. } else {
  674. lnEnd.setType(STLineEndType.Enum.forInt(style.ooxmlId));
  675. }
  676. }
  677. public DecorationShape getLineTailDecoration() {
  678. CTLineProperties ln = getSpPr().getLn();
  679. if (ln == null || !ln.isSetTailEnd()) return DecorationShape.NONE;
  680. STLineEndType.Enum end = ln.getTailEnd().getType();
  681. return end == null ? DecorationShape.NONE : DecorationShape.fromOoxmlId(end.intValue());
  682. }
  683. /**
  684. * specifies decorations which can be added to the tail of a line.
  685. */
  686. public void setLineTailWidth(DecorationSize style) {
  687. CTLineProperties ln = getSpPr().getLn();
  688. CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
  689. if (style == null) {
  690. if (lnEnd.isSetW()) lnEnd.unsetW();
  691. } else {
  692. lnEnd.setW(STLineEndWidth.Enum.forInt(style.ooxmlId));
  693. }
  694. }
  695. public DecorationSize getLineTailWidth() {
  696. CTLineProperties ln = getSpPr().getLn();
  697. if (ln == null || !ln.isSetTailEnd()) return DecorationSize.MEDIUM;
  698. STLineEndWidth.Enum w = ln.getTailEnd().getW();
  699. return w == null ? DecorationSize.MEDIUM : DecorationSize.fromOoxmlId(w.intValue());
  700. }
  701. /**
  702. * Specifies the line end width in relation to the line width.
  703. */
  704. public void setLineTailLength(DecorationSize style) {
  705. CTLineProperties ln = getSpPr().getLn();
  706. CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
  707. if (style == null) {
  708. if (lnEnd.isSetLen()) lnEnd.unsetLen();
  709. } else {
  710. lnEnd.setLen(STLineEndLength.Enum.forInt(style.ooxmlId));
  711. }
  712. }
  713. public DecorationSize getLineTailLength() {
  714. CTLineProperties ln = getSpPr().getLn();
  715. if (ln == null || !ln.isSetTailEnd()) return DecorationSize.MEDIUM;
  716. STLineEndLength.Enum len = ln.getTailEnd().getLen();
  717. return len == null ? DecorationSize.MEDIUM : DecorationSize.fromOoxmlId(len.intValue());
  718. }
  719. public boolean isPlaceholder() {
  720. CTPlaceholder ph = getCTPlaceholder();
  721. return ph != null;
  722. }
  723. @SuppressWarnings("deprecation")
  724. public Guide getAdjustValue(String name) {
  725. CTPresetGeometry2D prst = getSpPr().getPrstGeom();
  726. if (prst.isSetAvLst()) {
  727. for (CTGeomGuide g : prst.getAvLst().getGdArray()) {
  728. if (g.getName().equals(name)) {
  729. return new Guide(g.getName(), g.getFmla());
  730. }
  731. }
  732. }
  733. return null;
  734. }
  735. public LineDecoration getLineDecoration() {
  736. return new LineDecoration() {
  737. public DecorationShape getHeadShape() {
  738. return getLineHeadDecoration();
  739. }
  740. public DecorationSize getHeadWidth() {
  741. return getLineHeadWidth();
  742. }
  743. public DecorationSize getHeadLength() {
  744. return getLineHeadLength();
  745. }
  746. public DecorationShape getTailShape() {
  747. return getLineTailDecoration();
  748. }
  749. public DecorationSize getTailWidth() {
  750. return getLineTailWidth();
  751. }
  752. public DecorationSize getTailLength() {
  753. return getLineTailLength();
  754. }
  755. };
  756. }
  757. /**
  758. * fetch shape fill as a java.awt.Paint
  759. *
  760. * @return either Color or GradientPaint or TexturePaint or null
  761. */
  762. public FillStyle getFillStyle() {
  763. return new FillStyle() {
  764. public PaintStyle getPaint() {
  765. return XSLFSimpleShape.this.getFillPaint();
  766. }
  767. };
  768. }
  769. public StrokeStyle getStrokeStyle() {
  770. return new StrokeStyle() {
  771. public PaintStyle getPaint() {
  772. return XSLFSimpleShape.this.getLinePaint();
  773. }
  774. public LineCap getLineCap() {
  775. return XSLFSimpleShape.this.getLineCap();
  776. }
  777. public LineDash getLineDash() {
  778. return XSLFSimpleShape.this.getLineDash();
  779. }
  780. public double getLineWidth() {
  781. return XSLFSimpleShape.this.getLineWidth();
  782. }
  783. public LineCompound getLineCompound() {
  784. return XSLFSimpleShape.this.getLineCompound();
  785. }
  786. };
  787. }
  788. @Override
  789. public void setStrokeStyle(Object... styles) {
  790. if (styles.length == 0) {
  791. // remove stroke
  792. setLineColor(null);
  793. return;
  794. }
  795. // TODO: handle PaintStyle
  796. for (Object st : styles) {
  797. if (st instanceof Number) {
  798. setLineWidth(((Number)st).doubleValue());
  799. } else if (st instanceof LineCap) {
  800. setLineCap((LineCap)st);
  801. } else if (st instanceof LineDash) {
  802. setLineDash((LineDash)st);
  803. } else if (st instanceof LineCompound) {
  804. setLineCompound((LineCompound)st);
  805. } else if (st instanceof Color) {
  806. setLineColor((Color)st);
  807. }
  808. }
  809. }
  810. }