123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655 |
- /*
- * ====================================================================
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ====================================================================
- */
-
- package org.apache.poi.xslf.usermodel;
-
- import java.awt.Graphics2D;
- import java.awt.geom.Rectangle2D;
- import java.util.Locale;
-
- import javax.xml.namespace.QName;
- import javax.xml.stream.XMLStreamReader;
-
- import com.microsoft.schemas.compatibility.AlternateContentDocument;
- import com.microsoft.schemas.compatibility.AlternateContentDocument.AlternateContent;
- import org.apache.poi.openxml4j.opc.PackagePart;
- import org.apache.poi.sl.draw.DrawFactory;
- import org.apache.poi.sl.draw.DrawPaint;
- import org.apache.poi.sl.usermodel.MasterSheet;
- import org.apache.poi.sl.usermodel.PaintStyle;
- import org.apache.poi.sl.usermodel.PlaceableShape;
- import org.apache.poi.sl.usermodel.Placeholder;
- import org.apache.poi.sl.usermodel.PlaceholderDetails;
- import org.apache.poi.sl.usermodel.Shape;
- import org.apache.poi.sl.usermodel.SimpleShape;
- import org.apache.poi.util.Beta;
- import org.apache.poi.util.Internal;
- import org.apache.poi.xslf.model.PropertyFetcher;
- import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
- import org.apache.xmlbeans.XmlCursor;
- import org.apache.xmlbeans.XmlException;
- import org.apache.xmlbeans.XmlObject;
- import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
- import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
- import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
- import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
-
- /**
- * Base super-class class for all shapes in PresentationML
- */
- @Beta
- public abstract class XSLFShape implements Shape<XSLFShape,XSLFTextParagraph> {
-
- @Internal
- public interface ReparseFactory<T extends XmlObject> {
- T parse(XMLStreamReader reader) throws XmlException;
- }
-
- static final String DML_NS = "http://schemas.openxmlformats.org/drawingml/2006/main";
- static final String PML_NS = "http://schemas.openxmlformats.org/presentationml/2006/main";
- private static final String MC_NS = "http://schemas.openxmlformats.org/markup-compatibility/2006";
- private static final String MAC_DML_NS = "http://schemas.microsoft.com/office/mac/drawingml/2008/main";
-
- private static final QName ALTERNATE_CONTENT_TAG = new QName(MC_NS, "AlternateContent");
-
- private static final QName[] NV_CONTAINER = {
- new QName(PML_NS, "nvSpPr"),
- new QName(PML_NS, "nvCxnSpPr"),
- new QName(PML_NS, "nvGrpSpPr"),
- new QName(PML_NS, "nvPicPr"),
- new QName(PML_NS, "nvGraphicFramePr")
- };
-
- private static final QName[] CNV_PROPS = {
- new QName(PML_NS, "cNvPr")
- };
-
- private static final String OSGI_ERROR =
- "Schemas (*.xsb) for <CLASS> can't be loaded - usually this happens when OSGI " +
- "loading is used and the thread context classloader has no reference to " +
- "the xmlbeans classes - please either verify if the <XSB>.xsb is on the " +
- "classpath or alternatively try to use the full ooxml-schemas-x.x.jar";
-
- private final XmlObject _shape;
- private final XSLFSheet _sheet;
- private XSLFShapeContainer _parent;
-
- private CTShapeStyle _spStyle;
- private CTNonVisualDrawingProps _nvPr;
-
- protected XSLFShape(XmlObject shape, XSLFSheet sheet) {
- _shape = shape;
- _sheet = sheet;
- }
-
- /**
- * @return the xml bean holding this shape's data
- */
- public final XmlObject getXmlObject() {
- // it's final because the xslf inheritance hierarchy is not necessary the same as
- // the (not existing) xmlbeans hierarchy and subclasses shouldn't narrow it's return value
- return _shape;
- }
-
- @Override
- public XSLFSheet getSheet() {
- return _sheet;
- }
-
- @Override
- public String getShapeName() {
- CTNonVisualDrawingProps nonVisualDrawingProps = getCNvPr();
- return nonVisualDrawingProps == null ? null : nonVisualDrawingProps.getName();
- }
-
- @Override
- public int getShapeId() {
- CTNonVisualDrawingProps nonVisualDrawingProps = getCNvPr();
- if (nonVisualDrawingProps == null) {
- throw new IllegalStateException("no underlying shape exists");
- }
- return Math.toIntExact(nonVisualDrawingProps.getId());
- }
-
- /**
- * Set the contents of this shape to be a copy of the source shape.
- * This method is called recursively for each shape when merging slides
- *
- * @param sh the source shape
- * @see org.apache.poi.xslf.usermodel.XSLFSlide#importContent(XSLFSheet)
- */
- @Internal
- void copy(XSLFShape sh) {
- if (!getClass().isInstance(sh)) {
- throw new IllegalArgumentException(
- "Can't copy " + sh.getClass().getSimpleName() + " into " + getClass().getSimpleName());
- }
-
- if (this instanceof PlaceableShape) {
- PlaceableShape<?,?> ps = (PlaceableShape<?,?>)this;
- ps.setAnchor(sh.getAnchor());
- }
-
-
- }
-
- public void setParent(XSLFShapeContainer parent) {
- this._parent = parent;
- }
-
- @Override
- public XSLFShapeContainer getParent() {
- return this._parent;
- }
-
- protected PaintStyle getFillPaint() {
- final XSLFTheme theme = getSheet().getTheme();
- final boolean hasPlaceholder = getPlaceholder() != null;
-
- PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
- @Override
- public boolean fetch(XSLFShape shape) {
- PackagePart pp = shape.getSheet().getPackagePart();
- if (shape instanceof XSLFPictureShape) {
- CTPicture pic = (CTPicture)shape.getXmlObject();
- if (pic.getBlipFill() != null) {
- setValue(selectPaint(pic.getBlipFill(), pp, null, theme));
- return true;
- }
- }
-
- XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(shape.getShapeProperties());
- if (fp == null) {
- return false;
- }
-
- if (fp.isSetNoFill()) {
- setValue(null);
- return true;
- }
-
- PaintStyle paint = selectPaint(fp, null, pp, theme, hasPlaceholder);
- if (paint != null) {
- setValue(paint);
- return true;
- }
-
- CTShapeStyle style = shape.getSpStyle();
- if (style != null) {
- fp = XSLFPropertiesDelegate.getFillDelegate(style.getFillRef());
- paint = selectPaint(fp, null, pp, theme, hasPlaceholder);
- }
- if (paint != null) {
- setValue(paint);
- return true;
- }
-
-
- return false;
- }
- };
- fetchShapeProperty(fetcher);
-
- return fetcher.getValue();
- }
-
- @SuppressWarnings("unused")
- protected CTBackgroundProperties getBgPr() {
- return getChild(CTBackgroundProperties.class, PML_NS, "bgPr");
- }
-
- @SuppressWarnings("unused")
- protected CTStyleMatrixReference getBgRef() {
- return getChild(CTStyleMatrixReference.class, PML_NS, "bgRef");
- }
-
- protected CTGroupShapeProperties getGrpSpPr() {
- return getChild(CTGroupShapeProperties.class, PML_NS, "grpSpPr");
- }
-
- protected CTNonVisualDrawingProps getCNvPr() {
- try {
- if (_nvPr == null) {
- _nvPr = selectProperty(CTNonVisualDrawingProps.class, null, NV_CONTAINER, CNV_PROPS);
- }
- return _nvPr;
- } catch (XmlException e) {
- return null;
- }
- }
-
- @SuppressWarnings("WeakerAccess")
- protected CTShapeStyle getSpStyle() {
- if (_spStyle == null) {
- _spStyle = getChild(CTShapeStyle.class, PML_NS, "style");
- }
- return _spStyle;
- }
-
- /**
- * Return direct child objects of this shape
- *
- * @param childClass the class to cast the properties to
- * @param namespace the namespace - usually it is {@code "http://schemas.openxmlformats.org/presentationml/2006/main"}
- * @param nodename the node name, without prefix
- * @return the properties object or null if it can't be found
- */
- @SuppressWarnings({"unchecked", "WeakerAccess", "unused", "SameParameterValue"})
- protected <T extends XmlObject> T getChild(Class<T> childClass, String namespace, String nodename) {
- XmlCursor cur = getXmlObject().newCursor();
- T child = null;
- if (cur.toChild(namespace, nodename)) {
- child = (T)cur.getObject();
- }
- if (cur.toChild(XSLFRelation.NS_DRAWINGML, nodename)) {
- child = (T)cur.getObject();
- }
- cur.dispose();
- return child;
- }
-
- public boolean isPlaceholder() {
- return getPlaceholderDetails().getCTPlaceholder(false) != null;
- }
-
- /**
- * @see PlaceholderDetails#getPlaceholder()
- */
- public Placeholder getPlaceholder() {
- return getPlaceholderDetails().getPlaceholder();
- }
-
- /**
- * @see PlaceholderDetails#setPlaceholder(Placeholder)
- */
- public void setPlaceholder(final Placeholder placeholder) {
- getPlaceholderDetails().setPlaceholder(placeholder);
- }
-
- /**
- * @see SimpleShape#getPlaceholderDetails()
- */
- @SuppressWarnings("WeakerAccess")
- public XSLFPlaceholderDetails getPlaceholderDetails() {
- return new XSLFPlaceholderDetails(this);
- }
-
- /**
- * As there's no xmlbeans hierarchy, but XSLF works with subclassing, not all
- * child classes work with a {@link CTShape} object, but often contain the same
- * properties. This method is the generalized form of selecting and casting those
- * properties.
- *
- * @param resultClass the requested result class
- * @param xquery the simple (xmlbean) xpath expression to the property
- * @return the xml object at the xpath location, or null if not found
- */
- @SuppressWarnings({"unchecked", "WeakerAccess"})
- protected <T extends XmlObject> T selectProperty(Class<T> resultClass, String xquery) {
- XmlObject[] rs = getXmlObject().selectPath(xquery);
- if (rs.length == 0) {
- return null;
- }
- return (resultClass.isInstance(rs[0])) ? (T)rs[0] : null;
- }
-
- /**
- * Internal code - API may change any time!
- * <p>
- * The {@link #selectProperty(Class, String)} xquery method has some performance penalties,
- * which can be workaround by using {@link XmlCursor}. This method also takes into account
- * that {@code AlternateContent} tags can occur anywhere on the given path.
- * <p>
- * It returns the first element found - the search order is:
- * <ul>
- * <li>searching for a direct child</li>
- * <li>searching for a AlternateContent.Choice child</li>
- * <li>searching for a AlternateContent.Fallback child</li>
- * </ul>
- * Currently POI OOXML is based on the first edition of the ECMA 376 schema, which doesn't
- * allow AlternateContent tags to show up everywhere. The factory flag is
- * a workaround to process files based on a later edition. But it comes with the drawback:
- * any change on the returned XmlObject aren't saved back to the underlying document -
- * so it's a non updatable clone. If factory is null, a XmlException is
- * thrown if the AlternateContent is not allowed by the surrounding element or if the
- * extracted object is of the generic type XmlAnyTypeImpl.
- *
- * @param resultClass the requested result class
- * @param factory a factory parse method reference to allow reparsing of elements
- * extracted from AlternateContent elements. Usually the enclosing XmlBeans type needs to be used
- * to parse the stream
- * @param path the elements path, each array must contain at least 1 QName,
- * but can contain additional alternative tags
- * @return the xml object at the path location, or null if not found
- *
- * @throws XmlException If factory is null, a XmlException is
- * thrown if the AlternateContent is not allowed by the surrounding element or if the
- * extracted object is of the generic type XmlAnyTypeImpl.
- *
- * @since POI 4.1.2
- */
- @SuppressWarnings("unchecked")
- @Internal
- public <T extends XmlObject> T selectProperty(Class<T> resultClass, ReparseFactory<T> factory, QName[]... path)
- throws XmlException {
- XmlObject xo = getXmlObject();
- XmlCursor cur = xo.newCursor();
- XmlCursor innerCur = null;
- try {
- innerCur = selectProperty(cur, path, 0, factory != null, false);
- if (innerCur == null) {
- return null;
- }
-
- // Pesky XmlBeans bug - see Bugzilla #49934
- // it never happens when using the full ooxml-schemas jar but may happen with the abridged poi-ooxml-schemas
- xo = innerCur.getObject();
- if (xo instanceof XmlAnyTypeImpl) {
- String errorTxt = OSGI_ERROR
- .replace("<CLASS>", resultClass.getSimpleName())
- .replace("<XSB>", resultClass.getSimpleName().toLowerCase(Locale.ROOT)+"*");
- if (factory == null) {
- throw new XmlException(errorTxt);
- } else {
- xo = factory.parse(innerCur.newXMLStreamReader());
- }
- }
-
- return (T)xo;
- } finally {
- cur.dispose();
- if (innerCur != null) {
- innerCur.dispose();
- }
- }
- }
-
- private XmlCursor selectProperty(final XmlCursor cur, final QName[][] path, final int offset, final boolean reparseAlternate, final boolean isAlternate)
- throws XmlException {
- // first try the direct children
- for (QName qn : path[offset]) {
- if (cur.toChild(qn)) {
- if (offset == path.length-1) {
- return cur;
- }
- cur.push();
- XmlCursor innerCur = selectProperty(cur, path, offset+1, reparseAlternate, false);
- if (innerCur != null) {
- return innerCur;
- }
- cur.pop();
- }
- }
- // if we were called inside an alternate content handling don't look for alternates again
- if (isAlternate || !cur.toChild(ALTERNATE_CONTENT_TAG)) {
- return null;
- }
-
- // otherwise check first the choice then the fallback content
- XmlObject xo = cur.getObject();
- AlternateContent alterCont;
- if (xo instanceof AlternateContent) {
- alterCont = (AlternateContent)xo;
- } else {
- // Pesky XmlBeans bug - see Bugzilla #49934
- // it never happens when using the full ooxml-schemas jar but may happen with the abridged poi-ooxml-schemas
- if (!reparseAlternate) {
- throw new XmlException(OSGI_ERROR
- .replace("<CLASS>", "AlternateContent")
- .replace("<XSB>", "alternatecontentelement")
- );
- }
- try {
- AlternateContentDocument acd = AlternateContentDocument.Factory.parse(cur.newXMLStreamReader());
- alterCont = acd.getAlternateContent();
- } catch (XmlException e) {
- throw new XmlException("unable to parse AlternateContent element", e);
- }
- }
-
- final int choices = alterCont.sizeOfChoiceArray();
- for (int i=0; i<choices; i++) {
- // TODO: check [Requires] attribute of [Choice] element, if we can handle the content
- AlternateContent.Choice choice = alterCont.getChoiceArray(i);
- XmlCursor cCur = choice.newCursor();
- XmlCursor innerCur = null;
- try {
- String requiresNS = cCur.namespaceForPrefix(choice.getRequires());
- if (MAC_DML_NS.equalsIgnoreCase(requiresNS)) {
- // Mac DML usually contains PDFs ...
- continue;
- }
- innerCur = selectProperty(cCur, path, offset, reparseAlternate, true);
- if (innerCur != null) {
- return innerCur;
- }
- } finally {
- if (innerCur != cCur) {
- cCur.dispose();
- }
- }
- }
-
- if (!alterCont.isSetFallback()) {
- return null;
- }
-
- XmlCursor fCur = alterCont.getFallback().newCursor();
- XmlCursor innerCur = null;
- try {
- innerCur = selectProperty(fCur, path, offset, reparseAlternate, true);
- return innerCur;
- } finally {
- if (innerCur != fCur) {
- fCur.dispose();
- }
- }
- }
-
-
- /**
- * Walk up the inheritance tree and fetch shape properties.<p>
- *
- * The following order of inheritance is assumed:<p>
- * <ol>
- * <li>slide
- * <li>slideLayout
- * <li>slideMaster
- * </ol>
- *
- * Currently themes and their defaults aren't correctly handled
- *
- * @param visitor the object that collects the desired property
- * @return true if the property was fetched
- */
- @SuppressWarnings("WeakerAccess")
- @Internal
- public boolean fetchShapeProperty(PropertyFetcher<?> visitor) {
- // try shape properties in slide
- if (visitor.fetch(this)) {
- return true;
- }
-
- final CTPlaceholder ph = getPlaceholderDetails().getCTPlaceholder(false);
- if (ph == null) {
- return false;
- }
- MasterSheet<XSLFShape,XSLFTextParagraph> sm = getSheet().getMasterSheet();
-
- // try slide layout
- if (sm instanceof XSLFSlideLayout) {
- XSLFSlideLayout slideLayout = (XSLFSlideLayout)sm;
- XSLFSimpleShape placeholderShape = slideLayout.getPlaceholder(ph);
- if (placeholderShape != null && visitor.fetch(placeholderShape)) {
- return true;
- }
- sm = slideLayout.getMasterSheet();
- }
-
- // try slide master
- if (sm instanceof XSLFSlideMaster) {
- XSLFSlideMaster master = (XSLFSlideMaster)sm;
- int textType = getPlaceholderType(ph);
- XSLFSimpleShape masterShape = master.getPlaceholderByType(textType);
- return masterShape != null && visitor.fetch(masterShape);
- }
-
- return false;
- }
-
- private static int getPlaceholderType(CTPlaceholder ph) {
- if ( !ph.isSetType()) {
- return STPlaceholderType.INT_BODY;
- }
-
- switch (ph.getType().intValue()) {
- case STPlaceholderType.INT_TITLE:
- case STPlaceholderType.INT_CTR_TITLE:
- return STPlaceholderType.INT_TITLE;
- case STPlaceholderType.INT_FTR:
- case STPlaceholderType.INT_SLD_NUM:
- case STPlaceholderType.INT_DT:
- return ph.getType().intValue();
- default:
- return STPlaceholderType.INT_BODY;
- }
- }
-
- /**
- * Convert shape fill into java.awt.Paint. The result is either Color or
- * TexturePaint or GradientPaint or null
- *
- * @param fp a properties handler specific to the underlying shape properties
- * @param phClr context color
- * @param parentPart the parent package part. Any external references (images, etc.) are resolved relative to it.
- * @param theme the theme for the shape/sheet
- *
- * @return the applied Paint or null if none was applied
- */
- @SuppressWarnings("WeakerAccess")
- protected PaintStyle selectPaint(XSLFFillProperties fp, final CTSchemeColor phClr, final PackagePart parentPart, final XSLFTheme theme, boolean hasPlaceholder) {
- if (fp == null || fp.isSetNoFill()) {
- return null;
- } else if (fp.isSetSolidFill()) {
- return selectPaint(fp.getSolidFill(), phClr, theme);
- } else if (fp.isSetBlipFill()) {
- return selectPaint(fp.getBlipFill(), parentPart, phClr, theme);
- } else if (fp.isSetGradFill()) {
- return selectPaint(fp.getGradFill(), phClr, theme);
- } else if (fp.isSetMatrixStyle()) {
- return selectPaint(fp.getMatrixStyle(), theme, fp.isLineStyle(), hasPlaceholder);
- } else if (phClr != null) {
- return selectPaint(phClr, theme);
- } else {
- return null;
- }
- }
-
- protected PaintStyle selectPaint(CTSchemeColor phClr, final XSLFTheme theme) {
- final XSLFColor c = new XSLFColor(null, theme, phClr, _sheet);
- return DrawPaint.createSolidPaint(c.getColorStyle());
- }
-
- @SuppressWarnings("WeakerAccess")
- protected PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr, final XSLFTheme theme) {
- CTSchemeColor nestedPhClr = solidFill.getSchemeClr();
- boolean useNested = nestedPhClr != null && nestedPhClr.getVal() != null && !STSchemeColorVal.PH_CLR.equals(nestedPhClr.getVal());
- final XSLFColor c = new XSLFColor(solidFill, theme, useNested ? nestedPhClr : phClr, _sheet);
- return DrawPaint.createSolidPaint(c.getColorStyle());
- }
-
- @SuppressWarnings("WeakerAccess")
- protected PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart, CTSchemeColor phClr, final XSLFTheme theme) {
- return new XSLFTexturePaint(blipFill, parentPart, phClr, theme, _sheet);
- }
-
- @SuppressWarnings("WeakerAccess")
- protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr, final XSLFTheme theme) {
- return new XSLFGradientPaint(gradFill, phClr, theme, _sheet);
- }
-
- @SuppressWarnings("WeakerAccess")
- protected PaintStyle selectPaint(CTStyleMatrixReference fillRef, final XSLFTheme theme, boolean isLineStyle, boolean hasPlaceholder) {
- if (fillRef == null) {
- return null;
- }
-
- // The idx attribute refers to the index of a fill style or
- // background fill style within the presentation's style matrix, defined by the fmtScheme element.
- // value of 0 or 1000 indicates no background,
- // values 1-999 refer to the index of a fill style within the fillStyleLst element
- // values 1001 and above refer to the index of a background fill style within the bgFillStyleLst element.
- long idx = fillRef.getIdx();
- CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme();
- final XmlObject styleLst;
- long childIdx;
- if (idx >= 1 && idx <= 999) {
- childIdx = idx-1;
- styleLst = (isLineStyle) ? matrix.getLnStyleLst() : matrix.getFillStyleLst();
- } else if (idx >= 1001 ){
- childIdx = idx - 1001;
- styleLst = matrix.getBgFillStyleLst();
- } else {
- return null;
- }
- XmlCursor cur = styleLst.newCursor();
- XSLFFillProperties fp = null;
- if (cur.toChild(Math.toIntExact(childIdx))) {
- fp = XSLFPropertiesDelegate.getFillDelegate(cur.getObject());
- }
- cur.dispose();
-
- CTSchemeColor phClr = fillRef.getSchemeClr();
- PaintStyle res = selectPaint(fp, phClr, theme.getPackagePart(), theme, hasPlaceholder);
- // check for empty placeholder value
- // see http://officeopenxml.com/prSlide-color.php - "Color Placeholders within Themes"
- if (res != null || hasPlaceholder) {
- return res;
- }
- XSLFColor col = new XSLFColor(fillRef, theme, phClr, _sheet);
- return DrawPaint.createSolidPaint(col.getColorStyle());
- }
-
- @Override
- public void draw(Graphics2D graphics, Rectangle2D bounds) {
- DrawFactory.getInstance(graphics).drawShape(graphics, this, bounds);
- }
-
- /**
- * Return the shape specific (visual) properties
- *
- * @return the shape specific properties
- */
- protected XmlObject getShapeProperties() {
- return getChild(CTShapeProperties.class, PML_NS, "spPr");
- }
- }
|