*/\r
public Paint selectPaint(Graphics2D graphics, XmlObject obj, CTSchemeColor phClr, PackagePart parentPart) {\r
XSLFTheme theme = _shape.getSheet().getTheme();\r
- Rectangle2D anchor = _shape.getAnchor();\r
\r
Paint paint = null;\r
if (obj instanceof CTNoFillProperties) {\r
paint = createTexturePaint(blipFill, graphics, parentPart);\r
}\r
else if (obj instanceof CTGradientFillProperties) {\r
+ Rectangle2D anchor = getAnchor(graphics);\r
CTGradientFillProperties gradFill = (CTGradientFillProperties) obj;\r
if (gradFill.isSetLin()) {\r
paint = createLinearGradientPaint(graphics, gradFill, anchor, theme, phClr);\r
\r
float lineWidth = (float) _shape.getLineWidth();\r
if(lineWidth == 0.0f) lineWidth = 0.25f; // Both PowerPoint and OOo draw zero-length lines as 0.25pt\r
- Number fontScale = (Number)graphics.getRenderingHint(XSLFRenderingHint.GROUP_SCALE);\r
- if(fontScale != null) lineWidth *= fontScale.floatValue();\r
\r
LineDash lineDash = _shape.getLineDash();\r
float[] dash = null;\r
}\r
\r
public void render(Graphics2D graphics){\r
- Collection<Outline> elems = computeOutlines();\r
+ Collection<Outline> elems = computeOutlines(graphics);\r
\r
// shadow\r
XSLFShadow shadow = _shape.getShadow();\r
}\r
}\r
\r
- private Collection<Outline> computeOutlines() {\r
+ private Collection<Outline> computeOutlines(Graphics2D graphics) {\r
\r
Collection<Outline> lst = new ArrayList<Outline>();\r
CustomGeometry geom = _shape.getGeometry();\r
return lst;\r
}\r
\r
- Rectangle2D anchor = _shape.getAnchor();\r
+ Rectangle2D anchor = getAnchor(graphics);\r
for (Path p : geom) {\r
\r
double w = p.getW() == -1 ? anchor.getWidth() * Units.EMU_PER_POINT : p.getW();\r
return lst;\r
}\r
\r
+ public Rectangle2D getAnchor(Graphics2D graphics) {\r
+ Rectangle2D anchor = _shape.getAnchor();\r
+ if(graphics == null) {\r
+ return anchor;\r
+ }\r
+\r
+ AffineTransform tx = (AffineTransform)graphics.getRenderingHint(XSLFRenderingHint.GROUP_TRANSFORM);\r
+ if(tx != null) {\r
+ anchor = tx.createTransformedShape(anchor).getBounds2D();\r
+ }\r
+ return anchor;\r
+ } \r
}\r
// anchor of this group relative to the parent shape\r
Rectangle2D exterior = getAnchor();\r
\r
- graphics.translate(exterior.getX(), exterior.getY());\r
- double scaleX = exterior.getWidth() / interior.getWidth();\r
- double scaleY = exterior.getHeight() / interior.getHeight();\r
+ AffineTransform tx = (AffineTransform)graphics.getRenderingHint(XSLFRenderingHint.GROUP_TRANSFORM);\r
+ AffineTransform tx0 = new AffineTransform(tx);\r
\r
- // group transform scales shapes but not fonts\r
- Number prevFontScale = (Number)graphics.getRenderingHint(XSLFRenderingHint.GROUP_SCALE);\r
- graphics.setRenderingHint(XSLFRenderingHint.GROUP_SCALE, Math.abs(1/scaleY));\r
+ double scaleX = interior.getWidth() == 0. ? 1.0 : exterior.getWidth() / interior.getWidth();\r
+ double scaleY = interior.getHeight() == 0. ? 1.0 : exterior.getHeight() / interior.getHeight();\r
\r
- graphics.scale(scaleX, scaleY);\r
- graphics.translate(-interior.getX(), -interior.getY());\r
+ tx.translate(exterior.getX(), exterior.getY());\r
+ tx.scale(scaleX, scaleY);\r
+ tx.translate(-interior.getX(), -interior.getY());\r
\r
for (XSLFShape shape : getShapes()) {\r
// remember the initial transform and restore it after we are done with the drawing\r
graphics.setRenderingHint(XSLFRenderingHint.GRESTORE, true);\r
}\r
\r
- graphics.setRenderingHint(XSLFRenderingHint.GROUP_SCALE, prevFontScale);\r
+ graphics.setRenderingHint(XSLFRenderingHint.GROUP_TRANSFORM, tx0);\r
\r
}\r
\r
Rectangle2D anchor) {\r
try {\r
BufferedImage img = ImageIO.read(data.getPackagePart().getInputStream());\r
- Number groupScale = (Number)graphics.getRenderingHint(XSLFRenderingHint.GROUP_SCALE);\r
- if(groupScale != null) {\r
- double sx = anchor.getWidth()/img.getWidth();\r
- double sy = anchor.getHeight()/img.getHeight();\r
- double tx = anchor.getX();\r
- double ty = anchor.getY();\r
- AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ;\r
- graphics.drawRenderedImage(img, at);\r
- } else {\r
- graphics.drawImage(img,\r
- (int) anchor.getX(), (int) anchor.getY(),\r
- (int) anchor.getWidth(), (int) anchor.getHeight(), null);\r
- }\r
+ double sx = anchor.getWidth()/img.getWidth();\r
+ double sy = anchor.getHeight()/img.getHeight();\r
+ double tx = anchor.getX();\r
+ double ty = anchor.getY();\r
+ AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ;\r
+\r
+ graphics.drawRenderedImage(img, at);\r
+\r
return true;\r
} catch (Exception e) {\r
return false;\r
==================================================================== */
package org.apache.poi.xslf.usermodel;
+import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Beta;
}
@Override
- public XSLFSheet getMasterSheet() {
+ public XSLFNotesMaster getMasterSheet() {
+ for (POIXMLDocumentPart p : getRelations()) {
+ if (p instanceof XSLFNotesMaster){
+ return (XSLFNotesMaster)p;
+ }
+ }
return null;
}
}
XSLFImageRendener renderer = (XSLFImageRendener)graphics.getRenderingHint(XSLFRenderingHint.IMAGE_RENDERER);\r
if(renderer == null) renderer = new XSLFImageRendener();\r
\r
- renderer.drawImage(graphics, data, getAnchor());\r
+ RenderableShape rShape = new RenderableShape(this);\r
+ Rectangle2D anchor = rShape.getAnchor(graphics);\r
+\r
+ renderer.drawImage(graphics, data, anchor);\r
}\r
\r
\r
public static final int TEXT_AS_SHAPES = 2;\r
\r
@Internal\r
- static final XSLFRenderingHint GROUP_SCALE = new XSLFRenderingHint(5);\r
+ static final XSLFRenderingHint GROUP_TRANSFORM = new XSLFRenderingHint(5);\r
\r
/**\r
* Use this object to resolve unknown / missing fonts when rendering slides\r
import org.apache.xmlbeans.XmlObject;\r
\r
import java.awt.Graphics2D;\r
+import java.awt.geom.AffineTransform;\r
import java.awt.geom.Rectangle2D;\r
\r
/**\r
*/\r
protected void applyTransform(Graphics2D graphics) {\r
Rectangle2D anchor = getAnchor();\r
+ AffineTransform tx = (AffineTransform)graphics.getRenderingHint(XSLFRenderingHint.GROUP_TRANSFORM);\r
+ if(tx != null) {\r
+ anchor = tx.createTransformedShape(anchor).getBounds2D();\r
+ }\r
\r
// rotation\r
double rotation = getRotation();\r
XSLFSheet master = getMasterSheet();
if(getFollowMasterGraphics() && master != null) master.draw(graphics);
+ graphics.setRenderingHint(XSLFRenderingHint.GROUP_TRANSFORM, new AffineTransform());
for(XSLFShape shape : getShapeList()) {
if(!canDraw(shape)) continue;
Color lineColor = getLineColor();\r
if(lineColor != null) {\r
graphics.setPaint(lineColor);\r
- for(Outline o : getDecorationOutlines()){\r
+ for(Outline o : getDecorationOutlines(graphics)){\r
if(o.getPath().isFilled()){\r
graphics.fill(o.getOutline());\r
}\r
return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1];\r
}\r
\r
- Outline getTailDecoration() {\r
+ Outline getTailDecoration(Graphics2D graphics) {\r
LineEndLength tailLength = getLineTailLength();\r
LineEndWidth tailWidth = getLineTailWidth();\r
\r
double lineWidth = Math.max(2.5, getLineWidth());\r
\r
- Rectangle2D anchor = getAnchor();\r
+ Rectangle2D anchor = new RenderableShape(this).getAnchor(graphics);\r
double x2 = anchor.getX() + anchor.getWidth(),\r
y2 = anchor.getY() + anchor.getHeight();\r
\r
return shape == null ? null : new Outline(shape, p);\r
}\r
\r
- Outline getHeadDecoration() {\r
+ Outline getHeadDecoration(Graphics2D graphics) {\r
LineEndLength headLength = getLineHeadLength();\r
LineEndWidth headWidth = getLineHeadWidth();\r
\r
double lineWidth = Math.max(2.5, getLineWidth());\r
- Rectangle2D anchor = getAnchor();\r
+\r
+ Rectangle2D anchor = new RenderableShape(this).getAnchor(graphics);\r
double x1 = anchor.getX(),\r
y1 = anchor.getY();\r
\r
return shape == null ? null : new Outline(shape, p);\r
}\r
\r
- private List<Outline> getDecorationOutlines(){\r
+ private List<Outline> getDecorationOutlines(Graphics2D graphics){\r
List<Outline> lst = new ArrayList<Outline>();\r
\r
- Outline head = getHeadDecoration();\r
+ Outline head = getHeadDecoration(graphics);\r
if(head != null) lst.add(head);\r
\r
- Outline tail = getTailDecoration();\r
+ Outline tail = getTailDecoration(graphics);\r
if(tail != null) lst.add(tail);\r
return lst;\r
}\r
\r
package org.apache.poi.xslf.usermodel;\r
\r
+import org.apache.poi.POIXMLException;\r
import org.apache.poi.util.Internal;\r
import org.apache.poi.util.Units;\r
import org.apache.xmlbeans.XmlCursor;\r
+import org.apache.xmlbeans.XmlException;\r
import org.apache.xmlbeans.XmlObject;\r
+import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;\r
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTDTable;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTable;\r
/*package*/ XSLFTable(CTGraphicalObjectFrame shape, XSLFSheet sheet){\r
super(shape, sheet);\r
\r
- for(XmlObject obj : shape.getGraphic().getGraphicData().selectPath("*")){\r
- if(obj instanceof CTTable){\r
- _table = (CTTable)obj;\r
+ XmlObject[] rs = shape.getGraphic().getGraphicData()\r
+ .selectPath("declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' ./a:tbl");\r
+ if (rs.length == 0) {\r
+ throw new IllegalStateException("a:tbl element was not found in\n " + shape.getGraphic().getGraphicData());\r
+ }\r
+\r
+ // Pesky XmlBeans bug - see Bugzilla #49934\r
+ // it never happens when using the full ooxml-schemas jar but may happen with the abridged poi-ooxml-schemas\r
+ if(rs[0] instanceof XmlAnyTypeImpl){\r
+ try {\r
+ rs[0] = CTTable.Factory.parse(rs[0].toString());\r
+ }catch (XmlException e){\r
+ throw new POIXMLException(e);\r
}\r
}\r
- if(_table == null) throw new IllegalStateException("CTTable element was not found");\r
\r
+ _table = (CTTable) rs[0];\r
_rows = new ArrayList<XSLFTableRow>(_table.sizeOfTrArray());\r
for(CTTableRow row : _table.getTrList()) _rows.add(new XSLFTableRow(row, this));\r
}\r
*\r
* @return wrapping width in points\r
*/\r
- double getWrappingWidth(boolean firstLine){\r
+ double getWrappingWidth(boolean firstLine, Graphics2D graphics){\r
// internal margins for the text box\r
double leftInset = _shape.getLeftInset();\r
double rightInset = _shape.getRightInset();\r
\r
- Rectangle2D anchor = _shape.getAnchor();\r
+ RenderableShape rShape = new RenderableShape(_shape);\r
+ Rectangle2D anchor = rShape.getAnchor(graphics);\r
\r
double leftMargin = getLeftMargin();\r
double indent = getIndent();\r
public double draw(Graphics2D graphics, double x, double y){\r
double leftInset = _shape.getLeftInset();\r
double rightInset = _shape.getRightInset();\r
- Rectangle2D anchor = _shape.getAnchor();\r
+ RenderableShape rShape = new RenderableShape(_shape);\r
+ Rectangle2D anchor = rShape.getAnchor(graphics);\r
double penY = y;\r
\r
double leftMargin = getLeftMargin();\r
string.addAttribute(TextAttribute.FAMILY, fontFamily, startIndex, endIndex);\r
\r
float fontSz = (float)run.getFontSize();\r
- Number fontScale = (Number)graphics.getRenderingHint(XSLFRenderingHint.GROUP_SCALE);\r
- if(fontScale != null) fontSz *= fontScale.floatValue();\r
-\r
string.addAttribute(TextAttribute.SIZE, fontSz , startIndex, endIndex);\r
+\r
if(run.isBold()) {\r
string.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIndex, endIndex);\r
}\r
for (;;) {\r
int startIndex = measurer.getPosition();\r
\r
- double wrappingWidth = getWrappingWidth(_lines.size() == 0) + 1; // add a pixel to compensate rounding errors\r
+ double wrappingWidth = getWrappingWidth(_lines.size() == 0, graphics) + 1; // add a pixel to compensate rounding errors\r
// shape width can be smaller that the sum of insets (this was proved by a test file)\r
if(wrappingWidth < 0) wrappingWidth = 1;\r
\r
CTTextParagraphProperties getDefaultMasterStyle(){\r
CTPlaceholder ph = _shape.getCTPlaceholder();\r
String defaultStyleSelector;\r
- switch(ph.getType().intValue()){\r
- case STPlaceholderType.INT_TITLE:\r
- case STPlaceholderType.INT_CTR_TITLE:\r
- defaultStyleSelector = "titleStyle";\r
- break;\r
- case STPlaceholderType.INT_FTR:\r
- case STPlaceholderType.INT_SLD_NUM:\r
- case STPlaceholderType.INT_DT:\r
- defaultStyleSelector = "otherStyle";\r
- break;\r
- default:\r
- defaultStyleSelector = "bodyStyle";\r
- break;\r
+ if(ph == null) defaultStyleSelector = "otherStyle"; // no placeholder means plain text box\r
+ else {\r
+ switch(ph.getType().intValue()){\r
+ case STPlaceholderType.INT_TITLE:\r
+ case STPlaceholderType.INT_CTR_TITLE:\r
+ defaultStyleSelector = "titleStyle";\r
+ break;\r
+ case STPlaceholderType.INT_FTR:\r
+ case STPlaceholderType.INT_SLD_NUM:\r
+ case STPlaceholderType.INT_DT:\r
+ defaultStyleSelector = "otherStyle";\r
+ break;\r
+ default:\r
+ defaultStyleSelector = "bodyStyle";\r
+ break;\r
+ }\r
}\r
-\r
int level = getLevel();\r
\r
// wind up and find the root master sheet which must be slide master\r
XMLSlideShow ppt = getParentShape().getSheet().getSlideShow();\r
CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getLevel());\r
if(themeProps != null) ok = visitor.fetch(themeProps);\r
- } else {\r
+ }\r
+\r
+ if(!ok){\r
// defaults for placeholders are defined in the slide master\r
CTTextParagraphProperties defaultProps = getDefaultMasterStyle();\r
if(defaultProps != null) ok = visitor.fetch(defaultProps);\r
fetcher.isFetchingFromMaster = true;\r
ok = fetcher.fetch(themeProps);\r
}\r
- } else {\r
- // defaults for placeholders are defined in the slide master\r
+ }\r
+ if (!ok) {\r
CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle();\r
if(defaultProps != null) {\r
fetcher.isFetchingFromMaster = true;\r
public void drawContent(Graphics2D graphics) {
breakText(graphics);
- Rectangle2D anchor = getAnchor();
+ RenderableShape rShape = new RenderableShape(this);
+ Rectangle2D anchor = rShape.getAnchor(graphics);
double x = anchor.getX() + getLeftInset();
double y = anchor.getY();
pPr.getLatin().setTypeface("Arial");\r
assertEquals(9.0, r.getFontSize());\r
assertEquals("Arial", r.getFontFamily());\r
+\r
+ // unset font size in presentation.xml. The value should be taken from master slide\r
+ // from /p:sldMaster/p:txStyles/p:otherStyle/a:lvl1pPr/a:defRPr\r
+ ppt.getCTPresentation().getDefaultTextStyle().getLvl1PPr().getDefRPr().unsetSz();\r
+ pPr = slide.getSlideMaster().getXmlObject().getTxStyles().getOtherStyle().getLvl1PPr().getDefRPr();\r
+ assertEquals(1800, pPr.getSz());\r
+ assertEquals(18.0, r.getFontSize());\r
+ pPr.setSz(2000);\r
+ assertEquals(20.0, r.getFontSize());\r
+\r
+ pPr.unsetSz(); // Should never be\r
+ assertEquals(-1.0, r.getFontSize());\r
+\r
}\r
}
\ No newline at end of file
// Case 1: bullet=false, leftMargin=0, indent=0.\r
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;\r
assertEquals(285.6, expectedWidth); // 300 - 7.2 - 7.2 - 0\r
- assertEquals(expectedWidth, p.getWrappingWidth(true));\r
- assertEquals(expectedWidth, p.getWrappingWidth(false));\r
+ assertEquals(expectedWidth, p.getWrappingWidth(true, null));\r
+ assertEquals(expectedWidth, p.getWrappingWidth(false, null));\r
\r
p.setLeftMargin(36); // 0.5"\r
leftMargin = p.getLeftMargin();\r
assertEquals(36.0, leftMargin);\r
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;\r
assertEquals(249.6, expectedWidth, 1E-5); // 300 - 7.2 - 7.2 - 36\r
- assertEquals(expectedWidth, p.getWrappingWidth(true));\r
- assertEquals(expectedWidth, p.getWrappingWidth(false));\r
+ assertEquals(expectedWidth, p.getWrappingWidth(true, null));\r
+ assertEquals(expectedWidth, p.getWrappingWidth(false, null));\r
\r
// increase insets, the wrapping width should get smaller\r
sh.setLeftInset(10);\r
assertEquals(10.0, rightInset);\r
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;\r
assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36\r
- assertEquals(expectedWidth, p.getWrappingWidth(true));\r
- assertEquals(expectedWidth, p.getWrappingWidth(false));\r
+ assertEquals(expectedWidth, p.getWrappingWidth(true, null));\r
+ assertEquals(expectedWidth, p.getWrappingWidth(false, null));\r
\r
// set a positive indent of a 0.5 inch. This means "First Line" indentation:\r
// |<--- indent -->|Here goes first line of the text\r
assertEquals(36.0, indent);\r
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin - indent;\r
assertEquals(208.0, expectedWidth); // 300 - 10 - 10 - 36 - 6.4\r
- assertEquals(expectedWidth, p.getWrappingWidth(true)); // first line is indented\r
+ assertEquals(expectedWidth, p.getWrappingWidth(true, null)); // first line is indented\r
// other lines are not indented\r
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;\r
assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36\r
- assertEquals(expectedWidth, p.getWrappingWidth(false));\r
+ assertEquals(expectedWidth, p.getWrappingWidth(false, null));\r
\r
// set a negative indent of a 1 inch. This means "Hanging" indentation:\r
// Here goes first line of the text\r
assertEquals(-72.0, indent);\r
expectedWidth = anchor.getWidth() - leftInset - rightInset;\r
assertEquals(280.0, expectedWidth); // 300 - 10 - 10 \r
- assertEquals(expectedWidth, p.getWrappingWidth(true)); // first line is NOT indented\r
+ assertEquals(expectedWidth, p.getWrappingWidth(true, null)); // first line is NOT indented\r
// other lines are indented by leftMargin (the value of indent is not used)\r
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;\r
assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36 \r
- assertEquals(expectedWidth, p.getWrappingWidth(false));\r
+ assertEquals(expectedWidth, p.getWrappingWidth(false, null));\r
}\r
\r
/**\r