\r
package org.apache.poi.sl.draw;\r
\r
-import static org.apache.poi.sl.usermodel.PaintStyle.TRANSPARENT_PAINT;\r
-\r
-import java.awt.*;\r
+import java.awt.Color;\r
+import java.awt.Graphics2D;\r
+import java.awt.LinearGradientPaint;\r
import java.awt.MultipleGradientPaint.ColorSpaceType;\r
import java.awt.MultipleGradientPaint.CycleMethod;\r
-import java.awt.geom.*;\r
+import java.awt.Paint;\r
+import java.awt.RadialGradientPaint;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Point2D;\r
+import java.awt.geom.Rectangle2D;\r
import java.io.IOException;\r
import java.io.InputStream;\r
\r
-import org.apache.poi.sl.usermodel.*;\r
+import org.apache.poi.sl.usermodel.ColorStyle;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;\r
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;\r
+import org.apache.poi.sl.usermodel.PlaceableShape;\r
import org.apache.poi.util.POILogFactory;\r
import org.apache.poi.util.POILogger;\r
\r
\r
/**\r
- * This class handles color transformations\r
+ * This class handles color transformations.\r
* \r
* @see <a href="https://tips4java.wordpress.com/2009/07/05/hsl-color/">HSL code taken from Java Tips Weblog</a>\r
*/\r
this.shape = shape;\r
}\r
\r
- public static SolidPaint createSolidPaint(final Color color) {\r
- return new SolidPaint() {\r
- public ColorStyle getSolidColor() {\r
- return new ColorStyle(){\r
+ private static class SimpleSolidPaint implements SolidPaint {\r
+ private final ColorStyle solidColor;\r
+\r
+ SimpleSolidPaint(final Color color) {\r
+ if (color == null) {\r
+ throw new NullPointerException("Color needs to be specified");\r
+ }\r
+ this.solidColor = new ColorStyle(){\r
public Color getColor() { return color; }\r
public int getAlpha() { return -1; }\r
+ public int getHueOff() { return -1; }\r
+ public int getHueMod() { return -1; }\r
+ public int getSatOff() { return -1; }\r
+ public int getSatMod() { return -1; }\r
public int getLumOff() { return -1; }\r
public int getLumMod() { return -1; }\r
public int getShade() { return -1; }\r
public int getTint() { return -1; }\r
};\r
+ }\r
+\r
+ SimpleSolidPaint(ColorStyle color) {\r
+ if (color == null) {\r
+ throw new NullPointerException("Color needs to be specified");\r
}\r
- };\r
+ this.solidColor = color;\r
+ }\r
+ \r
+ public ColorStyle getSolidColor() {\r
+ return solidColor;\r
+ }\r
+ }\r
+ \r
+ public static SolidPaint createSolidPaint(final Color color) {\r
+ return (color == null) ? null : new SimpleSolidPaint(color);\r
+ }\r
+ \r
+ public static SolidPaint createSolidPaint(final ColorStyle color) {\r
+ return (color == null) ? null : new SimpleSolidPaint(color);\r
}\r
\r
public Paint getPaint(Graphics2D graphics, PaintStyle paint) {\r
\r
protected Paint getTexturePaint(TexturePaint fill, Graphics2D graphics) {\r
InputStream is = fill.getImageData();\r
- if (is == null) return TRANSPARENT_PAINT.getSolidColor().getColor();\r
+ if (is == null) return null;\r
assert(graphics != null);\r
\r
ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER);\r
if (renderer == null) renderer = new ImageRenderer();\r
\r
try {\r
- renderer.loadImage(fill.getImageData(), fill.getContentType());\r
+ renderer.loadImage(is, fill.getContentType());\r
+ is.close();\r
} catch (IOException e) {\r
LOG.log(POILogger.ERROR, "Can't load image data - using transparent color", e);\r
- return TRANSPARENT_PAINT.getSolidColor().getColor();\r
+ return null;\r
}\r
\r
int alpha = fill.getAlpha();\r
- if (alpha != -1) {\r
+ if (0 <= alpha && alpha < 100000) {\r
renderer.setAlpha(alpha/100000.f);\r
}\r
\r
- Dimension dim = renderer.getDimension();\r
- Rectangle2D textAnchor = new Rectangle2D.Double(0, 0, dim.getWidth(), dim.getHeight());\r
+ Rectangle2D textAnchor = shape.getAnchor();\r
Paint paint = new java.awt.TexturePaint(renderer.getImage(), textAnchor);\r
\r
return paint;\r
\r
/**\r
* Convert color transformations in {@link ColorStyle} to a {@link Color} instance\r
+ * \r
+ * @see <a href="https://msdn.microsoft.com/en-us/library/dd560821%28v=office.12%29.aspx">Using Office Open XML to Customize Document Formatting in the 2007 Office System</a>\r
+ * @see <a href="https://social.msdn.microsoft.com/Forums/office/en-US/040e0a1f-dbfe-4ce5-826b-38b4b6f6d3f7/saturation-modulation-satmod">saturation modulation (satMod)</a>\r
+ * @see <a href="http://stackoverflow.com/questions/6754127/office-open-xml-satmod-results-in-more-than-100-saturation">Office Open XML satMod results in more than 100% saturation</a>\r
*/\r
public static Color applyColorTransform(ColorStyle color){\r
+ // TODO: The colors don't match 100% the results of Powerpoint, maybe because we still\r
+ // operate in sRGB and not scRGB ... work in progress ...\r
+\r
Color result = color.getColor();\r
+ if (result == null) return null;\r
\r
- if (result == null || color.getAlpha() == 100) {\r
- return TRANSPARENT_PAINT.getSolidColor().getColor();\r
- }\r
- \r
- result = applyAlpha(result, color);\r
- result = applyLuminance(result, color);\r
- result = applyShade(result, color);\r
- result = applyTint(result, color);\r
+ double alpha = getAlpha(result, color);\r
+ double hsl[] = RGB2HSL(result); // values are in the range [0..100] (usually ...)\r
+ applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff());\r
+ applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff());\r
+ applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff());\r
+ applyShade(hsl, color);\r
+ applyTint(hsl, color);\r
\r
+ result = HSL2RGB(hsl[0], hsl[1], hsl[2], alpha);\r
+ \r
return result;\r
}\r
\r
- protected static Color applyAlpha(Color c, ColorStyle fc) {\r
- int alpha = c.getAlpha();\r
- return (alpha == 255) ? c : new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); \r
+ private static double getAlpha(Color c, ColorStyle fc) {\r
+ double alpha = c.getAlpha()/255d;\r
+ int fcAlpha = fc.getAlpha();\r
+ if (fcAlpha != -1) {\r
+ alpha *= fcAlpha/100000d;\r
+ }\r
+ return Math.min(1, Math.max(0, alpha));\r
}\r
\r
/**\r
- * Apply lumMod / lumOff adjustments\r
- *\r
- * @param c the color to modify\r
- * @param fc the color style containing the lumMod / lumOff adjustments\r
- * @return modified color\r
+ * Apply the modulation and offset adjustments to the given HSL part\r
+ * \r
+ * Example for lumMod/lumOff:\r
+ * The lumMod value is the percent luminance. A lumMod value of "60000",\r
+ * is 60% of the luminance of the original color.\r
+ * When the color is a shade of the original theme color, the lumMod\r
+ * attribute is the only one of the tags shown here that appears.\r
+ * The <a:lumOff> tag appears after the <a:lumMod> tag when the color is a\r
+ * tint of the original. The lumOff value always equals 1-lumMod, which is used in the tint calculation\r
+ * \r
+ * Despite having different ways to display the tint and shade percentages,\r
+ * all of the programs use the same method to calculate the resulting color.\r
+ * Convert the original RGB value to HSL ... and then adjust the luminance (L)\r
+ * with one of the following equations before converting the HSL value back to RGB.\r
+ * (The % tint in the following equations refers to the tint, themetint, themeshade,\r
+ * or lumMod values, as applicable.)\r
+ * \r
+ * @param hsl the hsl values\r
+ * @param hslPart the hsl part to modify [0..2]\r
+ * @param mod the modulation adjustment\r
+ * @param off the offset adjustment\r
+ * @return the modified hsl value\r
* \r
- * @see <a href="https://msdn.microsoft.com/en-us/library/dd560821%28v=office.12%29.aspx">Using Office Open XML to Customize Document Formatting in the 2007 Office System</a>\r
*/\r
- protected static Color applyLuminance(Color c, ColorStyle fc) {\r
- int lumMod = fc.getLumMod();\r
- if (lumMod == -1) lumMod = 100000;\r
-\r
- int lumOff = fc.getLumOff();\r
- if (lumOff == -1) lumOff = 0;\r
- \r
- if (lumMod == 100000 && lumOff == 0) return c;\r
-\r
- // The lumMod value is the percent luminance. A lumMod value of "60000",\r
- // is 60% of the luminance of the original color.\r
- // When the color is a shade of the original theme color, the lumMod\r
- // attribute is the only one of the tags shown here that appears.\r
- // The <a:lumOff> tag appears after the <a:lumMod> tag when the color is a\r
- // tint of the original. The lumOff value always equals 1-lumMod, which is used in the tint calculation\r
- //\r
- // Despite having different ways to display the tint and shade percentages,\r
- // all of the programs use the same method to calculate the resulting color.\r
- // Convert the original RGB value to HSL ... and then adjust the luminance (L)\r
- // with one of the following equations before converting the HSL value back to RGB.\r
- // (The % tint in the following equations refers to the tint, themetint, themeshade,\r
- // or lumMod values, as applicable.)\r
- //\r
- // For a shade, the equation is luminance * %tint.\r
- //\r
- // For a tint, the equation is luminance * %tint + (1-%tint).\r
- // (Note that 1-%tint is equal to the lumOff value in DrawingML.)\r
- \r
- double fLumOff = lumOff / 100000d;\r
- double fLumMod = lumMod / 100000d;\r
- \r
- double hsl[] = RGB2HSL(c);\r
- hsl[2] = hsl[2]*fLumMod+fLumOff;\r
-\r
- Color c2 = HSL2RGB(hsl[0], hsl[1], hsl[2], c.getAlpha()/255d);\r
- return c2;\r
+ private static void applyHslModOff(double hsl[], int hslPart, int mod, int off) {\r
+ if (mod == -1) mod = 100000;\r
+ if (off == -1) off = 0;\r
+ if (!(mod == 100000 && off == 0)) {\r
+ double fOff = off / 1000d;\r
+ double fMod = mod / 100000d;\r
+ hsl[hslPart] = hsl[hslPart]*fMod+fOff;\r
+ }\r
}\r
\r
/**\r
- * This algorithm returns result different from PowerPoint.\r
- * TODO: revisit and improve\r
+ * Apply the shade\r
+ * \r
+ * For a shade, the equation is luminance * %tint.\r
*/\r
- protected static Color applyShade(Color c, ColorStyle fc) {\r
+ private static void applyShade(double hsl[], ColorStyle fc) {\r
int shade = fc.getShade();\r
- if (shade == -1) return c;\r
+ if (shade == -1) return;\r
\r
- float fshade = shade / 100000.f;\r
-\r
- float red = c.getRed() * fshade;\r
- float green = c.getGreen() * fshade;\r
- float blue = c.getGreen() * fshade;\r
+ double fshade = shade / 100000.d;\r
\r
- return new Color(Math.round(red), Math.round(green), Math.round(blue), c.getAlpha());\r
+ hsl[2] *= fshade;\r
}\r
\r
/**\r
- * This algorithm returns result different from PowerPoint.\r
- * TODO: revisit and improve\r
+ * Apply the tint\r
+ * \r
+ * For a tint, the equation is luminance * %tint + (1-%tint).\r
+ * (Note that 1-%tint is equal to the lumOff value in DrawingML.)\r
*/\r
- protected static Color applyTint(Color c, ColorStyle fc) {\r
+ private static void applyTint(double hsl[], ColorStyle fc) {\r
int tint = fc.getTint();\r
- if (tint == -1) return c;\r
+ if (tint == -1) return;\r
\r
- float ftint = tint / 100000.f;\r
-\r
- float red = ftint * c.getRed() + (1.f - ftint) * 255.f;\r
- float green = ftint * c.getGreen() + (1.f - ftint) * 255.f;\r
- float blue = ftint * c.getBlue() + (1.f - ftint) * 255.f;\r
+ double ftint = tint / 100000.f;\r
\r
- return new Color(Math.round(red), Math.round(green), Math.round(blue), c.getAlpha());\r
+ hsl[2] = hsl[2] * ftint + (100 - ftint*100.);\r
}\r
\r
\r
\r
@Override\r
public void draw(Graphics2D graphics) {\r
-// RenderableShape rShape = new RenderableShape(this);\r
-// rShape.render(graphics);\r
-\r
DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(shape);\r
Paint fill = drawPaint.getPaint(graphics, shape.getFillStyle().getPaint());\r
Paint line = drawPaint.getPaint(graphics, shape.getStrokeStyle().getPaint());\r
\r
package org.apache.poi.sl.draw;\r
\r
-import java.awt.Color;\r
import java.awt.Graphics2D;\r
-import java.awt.font.*;\r
+import java.awt.Paint;\r
+import java.awt.font.FontRenderContext;\r
+import java.awt.font.LineBreakMeasurer;\r
+import java.awt.font.TextAttribute;\r
+import java.awt.font.TextLayout;\r
import java.awt.geom.Rectangle2D;\r
-import java.text.*;\r
+import java.text.AttributedCharacterIterator;\r
import java.text.AttributedCharacterIterator.Attribute;\r
-import java.util.*;\r
-\r
-import org.apache.poi.sl.usermodel.*;\r
+import java.text.AttributedString;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.apache.poi.sl.usermodel.AutoNumberingScheme;\r
+import org.apache.poi.sl.usermodel.Insets2D;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
+import org.apache.poi.sl.usermodel.PlaceableShape;\r
+import org.apache.poi.sl.usermodel.Shape;\r
+import org.apache.poi.sl.usermodel.ShapeContainer;\r
+import org.apache.poi.sl.usermodel.TextParagraph;\r
import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle;\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
+import org.apache.poi.sl.usermodel.TextRun;\r
import org.apache.poi.sl.usermodel.TextRun.TextCap;\r
+import org.apache.poi.sl.usermodel.TextShape;\r
import org.apache.poi.util.Units;\r
\r
public class DrawTextParagraph<T extends TextRun> implements Drawable {\r
public void draw(Graphics2D graphics){\r
if (lines.isEmpty()) return;\r
\r
- Insets2D insets = paragraph.getParentShape().getInsets();\r
- double leftInset = insets.left;\r
- double rightInset = insets.right;\r
double penY = y;\r
\r
boolean firstLine = true;\r
Double leftMargin = paragraph.getLeftMargin();\r
if (leftMargin == null) {\r
// if the marL attribute is omitted, then a value of 347663 is implied\r
- leftMargin = Units.toPoints(347663*(indentLevel+1));\r
+ leftMargin = Units.toPoints(347663*indentLevel);\r
}\r
Double indent = paragraph.getIndent();\r
if (indent == null) {\r
indent = Units.toPoints(347663*indentLevel);\r
}\r
+ if (paragraph.getClass().getName().contains("HSLF")) {\r
+ // special handling for HSLF\r
+ indent -= leftMargin;\r
+ }\r
+ \r
Double rightMargin = paragraph.getRightMargin();\r
if (rightMargin == null) {\r
rightMargin = 0d;\r
}\r
\r
if (bullet != null){\r
- bullet.setPosition(x + indent, penY);\r
+ bullet.setPosition(x+leftMargin+indent, penY);\r
bullet.draw(graphics);\r
// don't let text overlay the bullet and advance by the bullet width\r
double bulletWidth = bullet.getLayout().getAdvance() + 1;\r
- penX = x + Math.max(leftMargin, indent+bulletWidth);\r
+ penX = x + Math.max(leftMargin, leftMargin+indent+bulletWidth);\r
} else {\r
- penX = x + indent;\r
+ penX = x + leftMargin;\r
}\r
} else {\r
penX = x + leftMargin;\r
}\r
\r
Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape());\r
+ // Insets are already applied on DrawTextShape.drawContent\r
+ // but (outer) anchor need to be adjusted\r
+ Insets2D insets = paragraph.getParentShape().getInsets();\r
+ double leftInset = insets.left;\r
+ double rightInset = insets.right;\r
\r
TextAlign ta = paragraph.getTextAlign();\r
if (ta == null) ta = TextAlign.LEFT;\r
switch (ta) {\r
case CENTER:\r
- penX += (anchor.getWidth() - leftMargin - line.getWidth() - leftInset - rightInset) / 2;\r
+ penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset - leftMargin) / 2;\r
break;\r
case RIGHT:\r
penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset);\r
if (buFont == null) buFont = paragraph.getDefaultFontFamily();\r
assert(buFont != null);\r
\r
- Color buColor = bulletStyle.getBulletFontColor();\r
- if (buColor == null) buColor = (Color)firstLineAttr.getAttribute(TextAttribute.FOREGROUND);\r
+ PlaceableShape ps = getParagraphShape();\r
+ PaintStyle fgPaintStyle = bulletStyle.getBulletFontColor();\r
+ Paint fgPaint;\r
+ if (fgPaintStyle == null) {\r
+ fgPaint = (Paint)firstLineAttr.getAttribute(TextAttribute.FOREGROUND);\r
+ } else {\r
+ fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle);\r
+ }\r
\r
float fontSize = (Float)firstLineAttr.getAttribute(TextAttribute.SIZE);\r
Double buSz = bulletStyle.getBulletFontSize();\r
\r
\r
AttributedString str = new AttributedString(buCharacter);\r
- str.addAttribute(TextAttribute.FOREGROUND, buColor);\r
+ str.addAttribute(TextAttribute.FOREGROUND, fgPaint);\r
str.addAttribute(TextAttribute.FAMILY, buFont);\r
str.addAttribute(TextAttribute.SIZE, fontSize);\r
\r
this.endIndex = endIndex;\r
}\r
}\r
+ \r
+ /**\r
+ * Helper method for paint style relative to bounds, e.g. gradient paint\r
+ */\r
+ private PlaceableShape getParagraphShape() {\r
+ PlaceableShape ps = new PlaceableShape(){\r
+ public ShapeContainer<? extends Shape> getParent() { return null; }\r
+ public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); }\r
+ public void setAnchor(Rectangle2D anchor) {}\r
+ public double getRotation() { return 0; }\r
+ public void setRotation(double theta) {}\r
+ public void setFlipHorizontal(boolean flip) {}\r
+ public void setFlipVertical(boolean flip) {}\r
+ public boolean getFlipHorizontal() { return false; }\r
+ public boolean getFlipVertical() { return false; }\r
+ };\r
+ return ps;\r
+ }\r
\r
protected AttributedString getAttributedString(Graphics2D graphics, StringBuilder text){\r
List<AttributedStringData> attList = new ArrayList<AttributedStringData>();\r
if (text == null) text = new StringBuilder();\r
\r
+ PlaceableShape ps = getParagraphShape();\r
+ \r
DrawFontManager fontHandler = (DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER);\r
\r
for (TextRun run : paragraph){\r
text.append(runText);\r
int endIndex = text.length();\r
\r
- Color fgColor = run.getFontColor();\r
- if (fgColor == null) fgColor = Color.BLACK;\r
- attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgColor, beginIndex, endIndex));\r
+ PaintStyle fgPaintStyle = run.getFontColor();\r
+ Paint fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle);\r
+ attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgPaint, beginIndex, endIndex));\r
\r
// user can pass an custom object to convert fonts\r
String fontFamily = run.getFontFamily();\r
*/\r
public double drawParagraphs(Graphics2D graphics, double x, double y) {\r
DrawFactory fact = DrawFactory.getInstance(graphics);\r
- Insets2D shapePadding = shape.getInsets();\r
\r
double y0 = y;\r
Iterator<? extends TextParagraph<? extends TextRun>> paragraphs = shape.iterator();\r
int getAlpha();\r
\r
/**\r
- * the luminance shift as expressed by a percentage relative to the input color\r
+ * the hue shift as expressed by a percentage relative to the input color.\r
+ * Be aware that OOXML also returns values greater than 100%\r
+ * \r
+ * @return hue shift in percents in the range [0..100000] (usually ...)\r
+ * or -1 if the value is not set\r
+ */\r
+ int getHueOff();\r
+ \r
+ /**\r
+ * the hue as expressed by a percentage relative to the input color.\r
+ * Be aware that OOXML also returns values greater than 100%\r
+ * \r
+ * @return hue in percents in the range [0..100000] (usually ...)\r
+ * or -1 if the value is not set\r
+ */\r
+ int getHueMod();\r
+ \r
+ /**\r
+ * the saturation shift as expressed by a percentage relative to the input color.\r
+ * Be aware that OOXML also returns values greater than 100%\r
+ * \r
+ * @return saturation shift in percents in the range [0..100000] (usually ...)\r
+ * or -1 if the value is not set\r
+ */\r
+ int getSatOff();\r
+ \r
+ /**\r
+ * the saturation as expressed by a percentage relative to the input color.\r
+ * Be aware that OOXML also returns values greater than 100%\r
+ * \r
+ * @return saturation in percents in the range [0..100000] (usually ...)\r
+ * or -1 if the value is not set\r
+ */\r
+ int getSatMod();\r
+ \r
+ /**\r
+ * the luminance shift as expressed by a percentage relative to the input color.\r
+ * Be aware that OOXML also returns values greater than 100%\r
*\r
- * @return luminance shift in percents in the range [0..100000]\r
+ * @return luminance shift in percents in the range [0..100000] (usually ...)\r
* or -1 if the value is not set\r
*/\r
int getLumOff();\r
\r
/**\r
- * the luminance as expressed by a percentage relative to the input color\r
+ * the luminance as expressed by a percentage relative to the input color.\r
+ * Be aware that OOXML also returns values greater than 100%.\r
*\r
- * @return luminance in percents in the range [0..100000]\r
+ * @return luminance in percents in the range [0..100000] (usually ...)\r
* or -1 if the value is not set\r
*/\r
int getLumMod();\r
/**\r
* specifies a darker version of its input color.\r
* A 10% shade is 10% of the input color combined with 90% black.\r
+ * Be aware that OOXML also returns values greater than 100%.\r
* \r
- * @return the value of the shade specified as percents in the range [0..100000]\r
+ * @return the value of the shade specified as percents in the range [0..100000] (usually ...)\r
* with 0% indicating minimal shade and 100% indicating maximum\r
* or -1 if the value is not set\r
*/\r
/**\r
* specifies a lighter version of its input color.\r
* A 10% tint is 10% of the input color combined with 90% white.\r
+ * Be aware that OOXML also returns values greater than 100%\r
*\r
- * @return the value of the tint specified as percents in the range [0..100000]\r
+ * @return the value of the tint specified as percents in the range [0..100000] (usually ...)\r
* with 0% indicating minimal tint and 100% indicating maximum\r
* or -1 if the value is not set\r
*/\r
package org.apache.poi.sl.usermodel;
-import java.awt.Color;
import java.io.InputStream;
-import org.apache.poi.sl.draw.DrawPaint;
-
public interface PaintStyle {
+
public interface SolidPaint extends PaintStyle {
ColorStyle getSolidColor();
}
*/
int getAlpha();
}
-
- SolidPaint TRANSPARENT_PAINT = DrawPaint.createSolidPaint(new Color(0xFF, 0xFF, 0xFF, 0));
}
package org.apache.poi.sl.usermodel;
public interface Slide<T extends Shape, SS extends SlideShow, N extends Notes<T,SS>> extends Sheet<T, SS> {
- N getNotes();
- void setNotes(N notes);
+ N getNotes();
+ void setNotes(N notes);
- boolean getFollowMasterBackground();
- void setFollowMasterBackground(boolean follow);
+ boolean getFollowMasterBackground();
+ void setFollowMasterBackground(boolean follow);
- boolean getFollowMasterColourScheme();
- void setFollowMasterColourScheme(boolean follow);
+ boolean getFollowMasterColourScheme();
+ void setFollowMasterColourScheme(boolean follow);
- boolean getFollowMasterObjects();
- void setFollowMasterObjects(boolean follow);
+ boolean getFollowMasterObjects();
+ void setFollowMasterObjects(boolean follow);
+
+ /**
+ * @return the 1-based slide no.
+ */
+ int getSlideNumber();
+
+ /**
+ * @return title of this slide or null if title is not set
+ */
+ String getTitle();
- /**
- * @return the 1-based slide no.
- */
- int getSlideNumber();
}
import java.io.IOException;
import java.util.List;
-import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
public interface SlideShow {
import java.awt.Color;\r
\r
\r
+\r
public interface TextParagraph<T extends TextRun> extends Iterable<T> {\r
\r
/**\r
* @return the bullet point font size\r
*/\r
Double getBulletFontSize();\r
- Color getBulletFontColor();\r
+\r
+ /**\r
+ * Convenience function to set a solid color\r
+ */\r
+ void setBulletFontColor(Color color);\r
+ \r
+ void setBulletFontColor(PaintStyle color);\r
+\r
+ /**\r
+ *\r
+ * @return the color of bullet characters within a given paragraph.\r
+ * A {@code null} value means to use the text font color.\r
+ */\r
+ PaintStyle getBulletFontColor();\r
\r
AutoNumberingScheme getAutoNumberingScheme();\r
/**\r
import java.awt.Color;
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+
/**
* Some text.
*/
TextCap getTextCap();
- Color getFontColor();
- void setFontColor(Color color);
+ /**
+ * Returns the font color.
+ * This usually returns a {@link SolidPaint}, but but also other classes are possible
+ *
+ * @return the font color/paint
+ *
+ * @see org.apache.poi.sl.draw.DrawPaint#getPaint(java.awt.Graphics2D, PaintStyle)
+ * @see SolidPaint#getSolidColor()
+ * @see org.apache.poi.sl.draw.DrawPaint#applyColorTransform(ColorStyle)
+ */
+ PaintStyle getFontColor();
+
+ /**
+ * Sets the (solid) font color - convenience function
+ *
+ * @param color the color
+ */
+ void setFontColor(Color color);
+
+ /**
+ * Sets the font color
+ *
+ * @param color the color
+ *
+ * @see org.apache.poi.sl.draw.DrawPaint#createSolidPaint(Color)
+ */
+ void setFontColor(PaintStyle color);
/**
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.sl;\r
+\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.PushbackInputStream;\r
+import java.security.GeneralSecurityException;\r
+\r
+import org.apache.poi.EmptyFileException;\r
+import org.apache.poi.EncryptedDocumentException;\r
+import org.apache.poi.POIXMLDocument;\r
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;\r
+import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;\r
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
+import org.apache.poi.openxml4j.opc.OPCPackage;\r
+import org.apache.poi.openxml4j.opc.PackageAccess;\r
+import org.apache.poi.poifs.crypt.Decryptor;\r
+import org.apache.poi.poifs.crypt.EncryptionInfo;\r
+import org.apache.poi.poifs.filesystem.DirectoryNode;\r
+import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;\r
+import org.apache.poi.poifs.filesystem.OfficeXmlFileException;\r
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;\r
+import org.apache.poi.sl.usermodel.SlideShow;\r
+import org.apache.poi.util.IOUtils;\r
+import org.apache.poi.xslf.usermodel.XMLSlideShow;\r
+\r
+public class SlideShowFactory {\r
+ /**\r
+ * Creates a HSLFSlideShow from the given POIFSFileSystem\r
+ * <p>Note that in order to properly release resources the\r
+ * SlideShow should be closed after use.\r
+ */\r
+ public static SlideShow create(POIFSFileSystem fs) throws IOException {\r
+ return new HSLFSlideShow(fs);\r
+ }\r
+\r
+ /**\r
+ * Creates a HSLFSlideShow from the given NPOIFSFileSystem\r
+ * <p>Note that in order to properly release resources the\r
+ * SlideShow should be closed after use.\r
+ */\r
+ public static SlideShow create(NPOIFSFileSystem fs) throws IOException {\r
+ try {\r
+ return create(fs, null);\r
+ } catch (InvalidFormatException e) {\r
+ // Special case of OOXML-in-POIFS which is broken\r
+ throw new IOException(e);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Creates a SlideShow from the given NPOIFSFileSystem, which may\r
+ * be password protected\r
+ *\r
+ * @param fs The {@link NPOIFSFileSystem} to read the document from\r
+ * @param password The password that should be used or null if no password is necessary.\r
+ *\r
+ * @return The created SlideShow\r
+ *\r
+ * @throws IOException if an error occurs while reading the data\r
+ * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow}\r
+ */\r
+ private static SlideShow create(NPOIFSFileSystem fs, String password) throws IOException, InvalidFormatException {\r
+ DirectoryNode root = fs.getRoot();\r
+\r
+ // Encrypted OOXML files go inside OLE2 containers, is this one?\r
+ if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {\r
+ EncryptionInfo info = new EncryptionInfo(fs);\r
+ Decryptor d = Decryptor.getInstance(info);\r
+\r
+ boolean passwordCorrect = false;\r
+ InputStream stream = null;\r
+ try {\r
+ if (password != null && d.verifyPassword(password)) {\r
+ passwordCorrect = true;\r
+ }\r
+ if (!passwordCorrect && d.verifyPassword(Decryptor.DEFAULT_PASSWORD)) {\r
+ passwordCorrect = true;\r
+ }\r
+ if (passwordCorrect) {\r
+ stream = d.getDataStream(root);\r
+ }\r
+ } catch (GeneralSecurityException e) {\r
+ throw new IOException(e);\r
+ }\r
+\r
+ if (! passwordCorrect) {\r
+ if (password != null)\r
+ throw new EncryptedDocumentException("Password incorrect");\r
+ else\r
+ throw new EncryptedDocumentException("The supplied spreadsheet is protected, but no password was supplied");\r
+ }\r
+\r
+ OPCPackage pkg = OPCPackage.open(stream);\r
+ return create(pkg);\r
+ }\r
+\r
+ // If we get here, it isn't an encrypted PPTX file\r
+ // So, treat it as a regular HSLF PPT one\r
+ if (password != null) {\r
+ Biff8EncryptionKey.setCurrentUserPassword(password);\r
+ }\r
+ SlideShow wb = new HSLFSlideShow(root);\r
+ Biff8EncryptionKey.setCurrentUserPassword(null);\r
+ return wb;\r
+ }\r
+\r
+ /**\r
+ * Creates a XMLSlideShow from the given OOXML Package\r
+ *\r
+ * <p>Note that in order to properly release resources the\r
+ * SlideShow should be closed after use.</p>\r
+ *\r
+ * @param pkg The {@link OPCPackage} opened for reading data.\r
+ *\r
+ * @return The created SlideShow\r
+ *\r
+ * @throws IOException if an error occurs while reading the data\r
+ */\r
+ public static SlideShow create(OPCPackage pkg) throws IOException {\r
+ return new XMLSlideShow(pkg);\r
+ }\r
+\r
+ /**\r
+ * Creates the appropriate HSLFSlideShow / XMLSlideShow from\r
+ * the given InputStream.\r
+ *\r
+ * <p>Your input stream MUST either support mark/reset, or\r
+ * be wrapped as a {@link PushbackInputStream}! Note that\r
+ * using an {@link InputStream} has a higher memory footprint\r
+ * than using a {@link File}.</p>\r
+ *\r
+ * <p>Note that in order to properly release resources the\r
+ * SlideShow should be closed after use. Note also that loading\r
+ * from an InputStream requires more memory than loading\r
+ * from a File, so prefer {@link #create(File)} where possible.\r
+ *\r
+ * @param inp The {@link InputStream} to read data from.\r
+ *\r
+ * @return The created SlideShow\r
+ *\r
+ * @throws IOException if an error occurs while reading the data\r
+ * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow}\r
+ * @throws EncryptedDocumentException If the SlideShow given is password protected\r
+ */\r
+ public static SlideShow create(InputStream inp) throws IOException, InvalidFormatException, EncryptedDocumentException {\r
+ return create(inp, null);\r
+ }\r
+\r
+ /**\r
+ * Creates the appropriate HSLFSlideShow / XMLSlideShow from\r
+ * the given InputStream, which may be password protected.\r
+ * <p>Your input stream MUST either support mark/reset, or\r
+ * be wrapped as a {@link PushbackInputStream}! Note that\r
+ * using an {@link InputStream} has a higher memory footprint\r
+ * than using a {@link File}.</p>\r
+ *\r
+ * <p>Note that in order to properly release resources the\r
+ * SlideShow should be closed after use. Note also that loading\r
+ * from an InputStream requires more memory than loading\r
+ * from a File, so prefer {@link #create(File)} where possible.</p>\r
+ *\r
+ * @param inp The {@link InputStream} to read data from.\r
+ * @param password The password that should be used or null if no password is necessary.\r
+ *\r
+ * @return The created SlideShow\r
+ *\r
+ * @throws IOException if an error occurs while reading the data\r
+ * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow}\r
+ * @throws EncryptedDocumentException If the wrong password is given for a protected file\r
+ * @throws EmptyFileException If an empty stream is given\r
+ */\r
+ public static SlideShow create(InputStream inp, String password) throws IOException, InvalidFormatException, EncryptedDocumentException {\r
+ // If clearly doesn't do mark/reset, wrap up\r
+ if (! inp.markSupported()) {\r
+ inp = new PushbackInputStream(inp, 8);\r
+ }\r
+\r
+ // Ensure that there is at least some data there\r
+ byte[] header8 = IOUtils.peekFirst8Bytes(inp);\r
+\r
+ // Try to create\r
+ if (NPOIFSFileSystem.hasPOIFSHeader(header8)) {\r
+ NPOIFSFileSystem fs = new NPOIFSFileSystem(inp);\r
+ return create(fs, password);\r
+ }\r
+ if (POIXMLDocument.hasOOXMLHeader(inp)) {\r
+ return new XMLSlideShow(OPCPackage.open(inp));\r
+ }\r
+ throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream");\r
+ }\r
+\r
+ /**\r
+ * Creates the appropriate HSLFSlideShow / XMLSlideShow from\r
+ * the given File, which must exist and be readable.\r
+ * <p>Note that in order to properly release resources the\r
+ * SlideShow should be closed after use.\r
+ *\r
+ * @param file The file to read data from.\r
+ *\r
+ * @return The created SlideShow\r
+ *\r
+ * @throws IOException if an error occurs while reading the data\r
+ * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow}\r
+ * @throws EncryptedDocumentException If the SlideShow given is password protected\r
+ */\r
+ public static SlideShow create(File file) throws IOException, InvalidFormatException, EncryptedDocumentException {\r
+ return create(file, null);\r
+ }\r
+\r
+ /**\r
+ * Creates the appropriate HSLFSlideShow / XMLSlideShow from\r
+ * the given File, which must exist and be readable, and\r
+ * may be password protected\r
+ * <p>Note that in order to properly release resources the\r
+ * SlideShow should be closed after use.\r
+ *\r
+ * @param file The file to read data from.\r
+ * @param password The password that should be used or null if no password is necessary.\r
+ *\r
+ * @return The created SlideShow\r
+ *\r
+ * @throws IOException if an error occurs while reading the data\r
+ * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow}\r
+ * @throws EncryptedDocumentException If the wrong password is given for a protected file\r
+ * @throws EmptyFileException If an empty stream is given\r
+ */\r
+ public static SlideShow create(File file, String password) throws IOException, InvalidFormatException, EncryptedDocumentException {\r
+ return create(file, password, false);\r
+ }\r
+\r
+ /**\r
+ * Creates the appropriate HSLFSlideShow / XMLSlideShow from\r
+ * the given File, which must exist and be readable, and\r
+ * may be password protected\r
+ * <p>Note that in order to properly release resources the\r
+ * SlideShow should be closed after use.\r
+ *\r
+ * @param file The file to read data from.\r
+ * @param password The password that should be used or null if no password is necessary.\r
+ * @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back\r
+ * changes when the document is closed.\r
+ *\r
+ * @return The created SlideShow\r
+ *\r
+ * @throws IOException if an error occurs while reading the data\r
+ * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow}\r
+ * @throws EncryptedDocumentException If the wrong password is given for a protected file\r
+ * @throws EmptyFileException If an empty stream is given\r
+ */\r
+ public static SlideShow create(File file, String password, boolean readOnly) throws IOException, InvalidFormatException, EncryptedDocumentException {\r
+ if (! file.exists()) {\r
+ throw new FileNotFoundException(file.toString());\r
+ }\r
+\r
+ try {\r
+ NPOIFSFileSystem fs = new NPOIFSFileSystem(file, readOnly);\r
+ return create(fs, password);\r
+ } catch(OfficeXmlFileException e) {\r
+ // opening as .ppt failed => try opening as .pptx\r
+ OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE);\r
+ try {\r
+ return new XMLSlideShow(pkg);\r
+// } catch (IOException ioe) {\r
+// // ensure that file handles are closed (use revert() to not re-write the file)\r
+// pkg.revert();\r
+// //pkg.close();\r
+//\r
+// // rethrow exception\r
+// throw ioe;\r
+ } catch (IllegalArgumentException ioe) {\r
+ // ensure that file handles are closed (use revert() to not re-write the file)\r
+ pkg.revert();\r
+ //pkg.close();\r
+\r
+ // rethrow exception\r
+ throw ioe;\r
+ }\r
+ }\r
+ }\r
+}\r
* @author Yegor Kozlov\r
*/\r
public abstract class CharacterPropertyFetcher<T> extends ParagraphPropertyFetcher<T> {\r
- public boolean isFetchingFromMaster = false;\r
-\r
public CharacterPropertyFetcher(int level) {\r
super(level);\r
}\r
return getRawValue("alpha");\r
}\r
\r
+ public int getHueOff() {\r
+ return getRawValue("hueOff");\r
+ }\r
+\r
+ public int getHueMod() {\r
+ return getRawValue("hueMod");\r
+ }\r
+\r
+ public int getSatOff() {\r
+ return getRawValue("satOff");\r
+ }\r
+\r
+ public int getSatMod() {\r
+ return getRawValue("satMod");\r
+ }\r
+\r
public int getLumOff() {\r
return getRawValue("lumOff");\r
}\r
XmlObject[] cNvPr = sheet.getSpTree().selectPath(\r
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr");\r
for(XmlObject o : cNvPr) {\r
- CTNonVisualDrawingProps p = (CTNonVisualDrawingProps)o;\r
- _shapeId = (int)Math.max(_shapeId, p.getId());\r
+ // powerpoint generates AlternateContent elements which cNvPr elements aren't recognized\r
+ // ignore them for now\r
+ if (o instanceof CTNonVisualDrawingProps) {\r
+ CTNonVisualDrawingProps p = (CTNonVisualDrawingProps)o;\r
+ _shapeId = (int)Math.max(_shapeId, p.getId());\r
+ }\r
}\r
}\r
\r
import java.awt.geom.Rectangle2D;\r
\r
import org.apache.poi.sl.draw.DrawPaint;\r
-import org.apache.poi.sl.usermodel.ColorStyle;\r
-import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
import org.apache.poi.sl.usermodel.Shadow;\r
import org.apache.poi.util.Units;\r
*/\r
public Color getFillColor() {\r
SolidPaint ps = getFillStyle();\r
- if (ps == PaintStyle.TRANSPARENT_PAINT) return null;\r
+ if (ps == null) return null;\r
Color col = DrawPaint.applyColorTransform(ps.getSolidColor());\r
return col;\r
}\r
public SolidPaint getFillStyle() {\r
XSLFTheme theme = getSheet().getTheme();\r
CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();\r
- if(ct == null) return PaintStyle.TRANSPARENT_PAINT;\r
+ if(ct == null) return null;\r
\r
CTSchemeColor phClr = ct.getSchemeClr();\r
final XSLFColor xc = new XSLFColor(ct, theme, phClr);\r
- return new SolidPaint(){\r
- public ColorStyle getSolidColor() {\r
- return xc.getColorStyle();\r
- }\r
- };\r
+ return DrawPaint.createSolidPaint(xc.getColorStyle());\r
}\r
}
\ No newline at end of file
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
import org.apache.poi.openxml4j.opc.PackagePart;\r
import org.apache.poi.openxml4j.opc.PackageRelationship;\r
+import org.apache.poi.sl.draw.DrawPaint;\r
import org.apache.poi.sl.usermodel.ColorStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;\r
-import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;\r
import org.apache.poi.sl.usermodel.PlaceableShape;\r
import org.apache.poi.sl.usermodel.Shape;\r
import org.apache.poi.util.Internal;\r
import org.apache.poi.xslf.model.PropertyFetcher;\r
import org.apache.xmlbeans.XmlObject;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientStop;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNoFillProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STPathShadeType;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties;\r
try {\r
pr = shape.getSpPr();\r
if (((CTShapeProperties)pr).isSetNoFill()) {\r
- setValue(PaintStyle.TRANSPARENT_PAINT);\r
+ setValue(null);\r
return true;\r
} \r
} catch (IllegalStateException e) {}\r
}\r
}\r
\r
- if (pr == null) {\r
- setValue(PaintStyle.TRANSPARENT_PAINT);\r
- return true;\r
- }\r
+ if (pr == null) return false;\r
\r
PaintStyle paint = null;\r
+ PackagePart pp = getSheet().getPackagePart();\r
for (XmlObject obj : pr.selectPath("*")) {\r
- paint = selectPaint(obj, null, getSheet().getPackagePart());\r
- if (paint != null) break;\r
+ paint = selectPaint(obj, null, pp);\r
+ if (paint != null) {\r
+ setValue(paint);\r
+ return true;\r
+ };\r
}\r
\r
- if (paint == null) return false;\r
- \r
- setValue(paint);\r
- return true;\r
+ return false;\r
}\r
};\r
fetchShapeProperty(fetcher);\r
}\r
paint = selectPaint(fillRef);\r
\r
- return paint == null ? PaintStyle.TRANSPARENT_PAINT : paint;\r
+ return paint;\r
}\r
\r
protected CTBackgroundProperties getBgPr() {\r
paint = selectPaint(obj, phClr, pp);\r
if(paint != null) break;\r
}\r
- return paint == null ? PaintStyle.TRANSPARENT_PAINT : paint;\r
- } \r
+ return paint;\r
+ }\r
\r
/**\r
* Convert shape fill into java.awt.Paint. The result is either Color or\r
*/\r
protected PaintStyle selectPaint(XmlObject obj, final CTSchemeColor phClr, final PackagePart parentPart) {\r
if (obj instanceof CTNoFillProperties) {\r
- return PaintStyle.TRANSPARENT_PAINT;\r
+ return null;\r
} else if (obj instanceof CTSolidColorFillProperties) {\r
- return selectPaint((CTSolidColorFillProperties)obj, phClr, parentPart);\r
+ return selectPaint((CTSolidColorFillProperties)obj, phClr);\r
} else if (obj instanceof CTBlipFillProperties) {\r
- return selectPaint((CTBlipFillProperties)obj, phClr, parentPart);\r
+ return selectPaint((CTBlipFillProperties)obj, parentPart);\r
} else if (obj instanceof CTGradientFillProperties) {\r
- return selectPaint((CTGradientFillProperties) obj, phClr, parentPart);\r
+ return selectPaint((CTGradientFillProperties) obj, phClr);\r
} else if (obj instanceof CTStyleMatrixReference) {\r
return selectPaint((CTStyleMatrixReference)obj);\r
} else {\r
}\r
}\r
\r
- protected PaintStyle selectPaint(final CTSolidColorFillProperties solidFill, final CTSchemeColor phClr, final PackagePart parentPart) {\r
+ protected PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr) {\r
final XSLFTheme theme = getSheet().getTheme();\r
+ if (phClr == null && solidFill.isSetSchemeClr()) {\r
+ phClr = solidFill.getSchemeClr();\r
+ }\r
final XSLFColor c = new XSLFColor(solidFill, theme, phClr);\r
- return new SolidPaint() {\r
- public ColorStyle getSolidColor() {\r
- return c.getColorStyle();\r
- }\r
- };\r
+ return DrawPaint.createSolidPaint(c.getColorStyle());\r
}\r
\r
- protected PaintStyle selectPaint(final CTBlipFillProperties blipFill, final CTSchemeColor phClr, final PackagePart parentPart) {\r
+ protected PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) {\r
final CTBlip blip = blipFill.getBlip();\r
return new TexturePaint() {\r
private PackagePart getPart() {\r
public int getAlpha() {\r
return (blip.sizeOfAlphaModFixArray() > 0)\r
? blip.getAlphaModFixArray(0).getAmt()\r
- : 0;\r
+ : 100000;\r
}\r
}; \r
}\r
\r
- protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, final CTSchemeColor phClr, final PackagePart parentPart) {\r
+ protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr) {\r
\r
@SuppressWarnings("deprecation")\r
final CTGradientStop[] gs = gradFill.getGsLst().getGsArray();\r
\r
int i=0;\r
for (CTGradientStop cgs : gs) {\r
- cs[i] = new XSLFColor(cgs, theme, phClr).getColorStyle();\r
+ CTSchemeColor phClrCgs = phClr;\r
+ if (phClrCgs == null && cgs.isSetSchemeClr()) {\r
+ phClrCgs = cgs.getSchemeClr();\r
+ }\r
+ cs[i] = new XSLFColor(cgs, theme, phClrCgs).getColorStyle();\r
fractions[i] = cgs.getPos() / 100000.f;\r
i++;\r
}\r
\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.apache.poi.sl.usermodel.PaintStyle.TRANSPARENT_PAINT;\r
-\r
import java.awt.Color;\r
import java.awt.geom.Rectangle2D;\r
\r
import org.apache.poi.sl.draw.geom.CustomGeometry;\r
import org.apache.poi.sl.draw.geom.Guide;\r
import org.apache.poi.sl.draw.geom.PresetGeometries;\r
-import org.apache.poi.sl.usermodel.*;\r
+import org.apache.poi.sl.usermodel.FillStyle;\r
+import org.apache.poi.sl.usermodel.LineDecoration;\r
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;\r
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
+import org.apache.poi.sl.usermodel.ShapeType;\r
+import org.apache.poi.sl.usermodel.SimpleShape;\r
+import org.apache.poi.sl.usermodel.StrokeStyle;\r
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;\r
import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;\r
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;\r
*/\r
public Color getLineColor() {\r
PaintStyle ps = getLinePaint();\r
- if (ps == null || ps == TRANSPARENT_PAINT) return null;\r
if (ps instanceof SolidPaint) {\r
return ((SolidPaint)ps).getSolidColor().getColor();\r
}\r
CTLineProperties spPr = shape.getSpPr().getLn();\r
if (spPr != null) {\r
if (spPr.isSetNoFill()) {\r
- setValue(TRANSPARENT_PAINT); // use it as 'nofill' value\r
+ setValue(null); // use it as 'nofill' value\r
return true;\r
}\r
\r
\r
// line color was not found, check if it is defined in the theme\r
CTShapeStyle style = getSpStyle();\r
- if (style == null) return TRANSPARENT_PAINT;\r
+ if (style == null) return null;\r
\r
// get a reference to a line style within the style matrix.\r
CTStyleMatrixReference lnRef = style.getLnRef();\r
paint = getPaint(lnProps, phClr);\r
}\r
\r
- return paint == null ? TRANSPARENT_PAINT : paint;\r
+ return paint;\r
}\r
\r
/**\r
*/\r
public Color getFillColor() {\r
PaintStyle ps = getFillPaint();\r
- if (ps == null || ps == TRANSPARENT_PAINT) return null;\r
if (ps instanceof SolidPaint) {\r
return ((SolidPaint)ps).getSolidColor().getColor();\r
}\r
return _notes;
}
- /**
- *
- * @return title of this slide or empty string if title is not set
- */
+ @Override
public String getTitle(){
XSLFTextShape txt = getTextShapeByType(Placeholder.TITLE);
- return txt == null ? "" : txt.getText();
+ return txt == null ? null : txt.getText();
}
@Override
import java.util.Iterator;\r
import java.util.List;\r
\r
+import org.apache.poi.sl.draw.DrawPaint;\r
import org.apache.poi.sl.usermodel.AutoNumberingScheme;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
import org.apache.poi.sl.usermodel.TextParagraph;\r
import org.apache.poi.util.Beta;\r
import org.apache.poi.util.Internal;\r
* @return the color of bullet characters within a given paragraph.\r
* A <code>null</code> value means to use the text font color.\r
*/\r
- public Color getBulletFontColor(){\r
+ public PaintStyle getBulletFontColor(){\r
final XSLFTheme theme = getParentShape().getSheet().getTheme();\r
ParagraphPropertyFetcher<Color> fetcher = new ParagraphPropertyFetcher<Color>(getIndentLevel()){\r
public boolean fetch(CTTextParagraphProperties props){\r
}\r
};\r
fetchParagraphProperty(fetcher);\r
- return fetcher.getValue();\r
+ Color col = fetcher.getValue();\r
+ return (col == null) ? null : DrawPaint.createSolidPaint(col);\r
}\r
\r
+ public void setBulletFontColor(Color color) {\r
+ setBulletFontColor(DrawPaint.createSolidPaint(color));\r
+ }\r
+ \r
+ \r
/**\r
* Set the color to be used on bullet characters within a given paragraph.\r
*\r
* @param color the bullet color\r
*/\r
- public void setBulletFontColor(Color color){\r
+ public void setBulletFontColor(PaintStyle color) {\r
+ if (!(color instanceof SolidPaint)) {\r
+ throw new IllegalArgumentException("Currently XSLF only supports SolidPaint");\r
+ }\r
+\r
+ // TODO: implement setting bullet color to null\r
+ SolidPaint sp = (SolidPaint)color;\r
+ Color col = DrawPaint.applyColorTransform(sp.getSolidColor());\r
+ \r
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
CTColor c = pr.isSetBuClr() ? pr.getBuClr() : pr.addNewBuClr();\r
CTSRgbColor clr = c.isSetSrgbClr() ? c.getSrgbClr() : c.addNewSrgbClr();\r
- clr.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()});\r
+ clr.setVal(new byte[]{(byte) col.getRed(), (byte) col.getGreen(), (byte) col.getBlue()});\r
}\r
\r
/**\r
XSLFSheet masterSheet = _shape.getSheet();\r
for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) {\r
masterSheet = m;\r
-\r
XmlObject xo = masterSheet.getXmlObject();\r
for (String xpath : xpaths) {\r
XmlObject[] o = xo.selectPath(xpath);\r
\r
private <T> boolean fetchParagraphProperty(ParagraphPropertyFetcher<T> visitor){\r
boolean ok = false;\r
-\r
+ XSLFTextShape shape = getParentShape();\r
+ XSLFSheet sheet = shape.getSheet();\r
+ \r
if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr());\r
+ if (ok) return true;\r
\r
- if(!ok) {\r
- XSLFTextShape shape = getParentShape();\r
- ok = shape.fetchShapeProperty(visitor);\r
- if(!ok){\r
- CTPlaceholder ph = shape.getCTPlaceholder();\r
- if(ph == null){\r
- // if it is a plain text box then take defaults from presentation.xml\r
- XMLSlideShow ppt = getParentShape().getSheet().getSlideShow();\r
- CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel());\r
- if(themeProps != null) ok = visitor.fetch(themeProps);\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
- }\r
- }\r
+ ok = shape.fetchShapeProperty(visitor);\r
+ if (ok) return true;\r
+ \r
+ \r
+ CTPlaceholder ph = shape.getCTPlaceholder();\r
+ if(ph == null){\r
+ // if it is a plain text box then take defaults from presentation.xml\r
+ XMLSlideShow ppt = sheet.getSlideShow();\r
+ CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel());\r
+ if (themeProps != null) ok = visitor.fetch(themeProps);\r
}\r
+ if (ok) return true;\r
+\r
+ // defaults for placeholders are defined in the slide master\r
+ CTTextParagraphProperties defaultProps = getDefaultMasterStyle();\r
+ // TODO: determine master shape\r
+ if(defaultProps != null) ok = visitor.fetch(defaultProps);\r
+ if (ok) return true;\r
\r
- return ok;\r
+ return false;\r
}\r
\r
+ @SuppressWarnings("deprecation")\r
void copy(XSLFTextParagraph other){\r
if (other == this) return;\r
\r
if(buChar != null && !buChar.equals(getBulletCharacter())){\r
setBulletCharacter(buChar);\r
}\r
- Color buColor = other.getBulletFontColor();\r
+ PaintStyle buColor = other.getBulletFontColor();\r
if(buColor != null && !buColor.equals(getBulletFontColor())){\r
setBulletFontColor(buColor);\r
}\r
}\r
\r
@Override\r
- public Color getBulletFontColor() {\r
+ public PaintStyle getBulletFontColor() {\r
return XSLFTextParagraph.this.getBulletFontColor();\r
}\r
\r
+ @Override\r
+ public void setBulletFontColor(Color color) {\r
+ setBulletFontColor(DrawPaint.createSolidPaint(color));\r
+ }\r
+\r
+ @Override\r
+ public void setBulletFontColor(PaintStyle color) {\r
+ XSLFTextParagraph.this.setBulletFontColor(color);\r
+ }\r
+ \r
@Override\r
public AutoNumberingScheme getAutoNumberingScheme() {\r
return XSLFTextParagraph.this.getAutoNumberingScheme();\r
\r
import java.awt.Color;\r
\r
+import org.apache.poi.sl.draw.DrawPaint;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
import org.apache.poi.sl.usermodel.TextRun;\r
import org.apache.poi.util.Beta;\r
import org.apache.poi.xslf.model.CharacterPropertyFetcher;\r
\r
@Override\r
public void setFontColor(Color color) {\r
+ setFontColor(DrawPaint.createSolidPaint(color));\r
+ }\r
+ \r
+ @Override\r
+ public void setFontColor(PaintStyle color) {\r
+ if (!(color instanceof SolidPaint)) {\r
+ throw new IllegalArgumentException("Currently only SolidPaint is supported!");\r
+ }\r
+ SolidPaint sp = (SolidPaint)color;\r
+ \r
CTTextCharacterProperties rPr = getRPr();\r
CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill();\r
CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr();\r
- clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()});\r
+ Color c = DrawPaint.applyColorTransform(sp.getSolidColor());\r
+ clr.setVal(new byte[]{(byte)c.getRed(), (byte)c.getGreen(), (byte)c.getBlue()});\r
\r
if(fill.isSetHslClr()) fill.unsetHslClr();\r
if(fill.isSetPrstClr()) fill.unsetPrstClr();\r
}\r
\r
@Override\r
- public Color getFontColor(){\r
- final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();\r
- CTShapeStyle style = _p.getParentShape().getSpStyle();\r
- final CTSchemeColor phClr = style == null ? null : style.getFontRef().getSchemeClr();\r
-\r
- CharacterPropertyFetcher<Color> fetcher = new CharacterPropertyFetcher<Color>(_p.getIndentLevel()){\r
+ public PaintStyle getFontColor(){\r
+ CharacterPropertyFetcher<PaintStyle> fetcher = new CharacterPropertyFetcher<PaintStyle>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
- CTSolidColorFillProperties solidFill = props.getSolidFill();\r
- if(solidFill != null) {\r
- boolean useCtxColor =\r
- (solidFill.isSetSchemeClr() && solidFill.getSchemeClr().getVal() == STSchemeColorVal.PH_CLR)\r
- || isFetchingFromMaster;\r
- Color c = new XSLFColor(solidFill, theme, useCtxColor ? phClr : null).getColor();\r
- setValue(c);\r
+ XSLFShape shape = _p.getParentShape();\r
+ CTShapeStyle style = shape.getSpStyle();\r
+ CTSchemeColor phClr = null;\r
+ if (style != null && style.getFontRef() != null) {\r
+ phClr = style.getFontRef().getSchemeClr();\r
+ }\r
+\r
+ PaintStyle ps = shape.getPaint(props, phClr);\r
+ if (ps != null) {\r
+ setValue(ps);\r
return true;\r
}\r
+ \r
return false;\r
}\r
};\r
}\r
\r
public byte getPitchAndFamily(){\r
- final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();\r
+ // final XSLFTheme theme = _p.getParentShape().getSheet().getTheme();\r
\r
CharacterPropertyFetcher<Byte> visitor = new CharacterPropertyFetcher<Byte>(_p.getIndentLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
}\r
\r
private boolean fetchCharacterProperty(CharacterPropertyFetcher<?> fetcher){\r
+ XSLFTextShape shape = _p.getParentShape();\r
+ XSLFSheet sheet = shape.getSheet();\r
boolean ok = false;\r
\r
- if(_r.isSetRPr()) ok = fetcher.fetch(getRPr());\r
-\r
- if(!ok) {\r
- XSLFTextShape shape = _p.getParentShape();\r
- ok = shape.fetchShapeProperty(fetcher);\r
- if(!ok){\r
- CTPlaceholder ph = shape.getCTPlaceholder();\r
- if(ph == null){\r
- // if it is a plain text box then take defaults from presentation.xml\r
- XMLSlideShow ppt = shape.getSheet().getSlideShow();\r
- CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel());\r
- if(themeProps != null) {\r
- fetcher.isFetchingFromMaster = true;\r
- ok = fetcher.fetch(themeProps);\r
- }\r
- }\r
- if (!ok) {\r
- CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle();\r
- if(defaultProps != null) {\r
- fetcher.isFetchingFromMaster = true;\r
- ok = fetcher.fetch(defaultProps);\r
- }\r
- }\r
+ if (_r.isSetRPr()) ok = fetcher.fetch(getRPr());\r
+ if (ok) return true;\r
+ \r
+ ok = shape.fetchShapeProperty(fetcher);\r
+ if (ok) return true;\r
+ \r
+ CTPlaceholder ph = shape.getCTPlaceholder();\r
+ if (ph == null){\r
+ // if it is a plain text box then take defaults from presentation.xml\r
+ XMLSlideShow ppt = sheet.getSlideShow();\r
+ CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel());\r
+ if (themeProps != null) {\r
+ // TODO: determine master shape\r
+ ok = fetcher.fetch(themeProps);\r
}\r
}\r
+ if (ok) return true;\r
+\r
+ CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle();\r
+ if(defaultProps != null) {\r
+ // TODO: determine master shape\r
+ ok = fetcher.fetch(defaultProps);\r
+ }\r
+ if (ok) return true;\r
\r
- return ok;\r
+ return false;\r
}\r
\r
void copy(XSLFTextRun r){\r
setFontFamily(srcFontFamily);\r
}\r
\r
- Color srcFontColor = r.getFontColor();\r
+ PaintStyle srcFontColor = r.getFontColor();\r
if(srcFontColor != null && !srcFontColor.equals(getFontColor())){\r
setFontColor(srcFontColor);\r
}\r
\r
package org.apache.poi.xslf.util;\r
\r
-import org.apache.poi.openxml4j.opc.OPCPackage;\r
-import org.apache.poi.xslf.usermodel.XMLSlideShow;\r
-import org.apache.poi.xslf.usermodel.XSLFSlide;\r
-\r
-import javax.imageio.ImageIO;\r
-\r
-import java.awt.Color;\r
import java.awt.Dimension;\r
import java.awt.Graphics2D;\r
import java.awt.RenderingHints;\r
import java.awt.image.BufferedImage;\r
-import java.io.FileOutputStream;\r
+import java.io.File;\r
+import java.util.HashMap;\r
import java.util.List;\r
+import java.util.Map;\r
+\r
+import javax.imageio.ImageIO;\r
+\r
+import org.apache.poi.sl.SlideShowFactory;\r
+import org.apache.poi.sl.draw.Drawable;\r
+import org.apache.poi.sl.usermodel.Slide;\r
+import org.apache.poi.sl.usermodel.SlideShow;\r
+import org.apache.poi.util.JvmBugs;\r
\r
/**\r
* An utulity to convert slides of a .pptx slide show to a PNG image\r
*/\r
public class PPTX2PNG {\r
\r
- static void usage(){\r
- System.out.println("Usage: PPTX2PNG [options] <pptx file>");\r
- System.out.println("Options:");\r
- System.out.println(" -scale <float> scale factor");\r
- System.out.println(" -slide <integer> 1-based index of a slide to render");\r
+ static void usage(String error){\r
+ String msg =\r
+ "Usage: PPTX2PNG [options] <ppt or pptx file>\n" +\r
+ (error == null ? "" : ("Error: "+error+"\n")) +\r
+ "Options:\n" +\r
+ " -scale <float> scale factor\n" +\r
+ " -slide <integer> 1-based index of a slide to render\n" +\r
+ " -format <type> png,gif,jpg (,null for testing)" +\r
+ " -outdir <dir> output directory, defaults to origin of the ppt/pptx file" +\r
+ " -quite do not write to console (for normal processing)";\r
+\r
+ System.out.println(msg);\r
+ // no System.exit here, as we also run in junit tests!\r
}\r
\r
public static void main(String[] args) throws Exception {\r
if (args.length == 0) {\r
- usage();\r
+ usage(null);\r
return;\r
}\r
\r
int slidenum = -1;\r
float scale = 1;\r
- String file = null;\r
+ File file = null;\r
+ String format = "png";\r
+ File outdir = null;\r
+ boolean quite = false;\r
\r
for (int i = 0; i < args.length; i++) {\r
if (args[i].startsWith("-")) {\r
scale = Float.parseFloat(args[++i]);\r
} else if ("-slide".equals(args[i])) {\r
slidenum = Integer.parseInt(args[++i]);\r
+ } else if ("-format".equals(args[i])) {\r
+ format = args[++i];\r
+ } else if ("-outdir".equals(args[i])) {\r
+ outdir = new File(args[++i]);\r
+ } else if ("-quite".equals(args[i])) {\r
+ quite = true;\r
}\r
} else {\r
- file = args[i];\r
+ file = new File(args[i]);\r
}\r
}\r
\r
- if(file == null){\r
- usage();\r
+ if (file == null || !file.exists()) {\r
+ usage("File not specified or it doesn't exist");\r
+ return;\r
+ }\r
+\r
+ if (outdir == null) {\r
+ outdir = file.getParentFile();\r
+ }\r
+ \r
+ if (outdir == null || !outdir.exists() || !outdir.isDirectory()) {\r
+ usage("Output directory doesn't exist");\r
return;\r
}\r
\r
- System.out.println("Processing " + file);\r
- XMLSlideShow ppt = new XMLSlideShow(OPCPackage.open(file));\r
+ if (scale < 0) {\r
+ usage("Invalid scale given");\r
+ return;\r
+ }\r
+ \r
+ if (format == null || !format.matches("^(png|gif|jpg|null)$")) {\r
+ usage("Invalid format given");\r
+ return;\r
+ }\r
+ \r
+ if (!quite) {\r
+ System.out.println("Processing " + file);\r
+ }\r
+ SlideShow ss = SlideShowFactory.create(file, null, true);\r
+ List<? extends Slide<?,?,?>> slides = ss.getSlides();\r
\r
- Dimension pgsize = ppt.getPageSize();\r
+ \r
+ if (slidenum < -1 || slidenum == 0 || slidenum > slides.size()) {\r
+ usage("slidenum must be either -1 (for all) or within range: [1.."+slides.size()+"] for "+file);\r
+ return;\r
+ }\r
+ \r
+ Dimension pgsize = ss.getPageSize();\r
int width = (int) (pgsize.width * scale);\r
int height = (int) (pgsize.height * scale);\r
\r
- List<XSLFSlide> slide = ppt.getSlides();\r
- for (int i = 0; i < slide.size(); i++) {\r
- if (slidenum != -1 && slidenum != (i + 1)) continue;\r
-\r
- String title = slide.get(i).getTitle();\r
- System.out.println("Rendering slide " + (i + 1) + (title == null ? "" : ": " + title));\r
-\r
- BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\r
- Graphics2D graphics = img.createGraphics();\r
-\r
- // default rendering options\r
- graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
- graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);\r
- graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);\r
- graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);\r
-\r
- graphics.setColor(Color.white);\r
- graphics.clearRect(0, 0, width, height);\r
-\r
- graphics.scale(scale, scale);\r
-\r
- // draw stuff\r
- slide.get(i).draw(graphics);\r
+ int slideNo=1;\r
+ for(Slide<?,?,?> slide : slides) {\r
+ if (slidenum == -1 || slideNo == slidenum) {\r
+ String title = slide.getTitle();\r
+ if (!quite) {\r
+ System.out.println("Rendering slide " + slideNo + (title == null ? "" : ": " + title));\r
+ }\r
\r
- // save the result\r
- int sep = file.lastIndexOf(".");\r
- String fname = file.substring(0, sep == -1 ? file.length() : sep) + "-" + (i + 1) +".png";\r
- FileOutputStream out = new FileOutputStream(fname);\r
- ImageIO.write(img, "png", out);\r
- out.close();\r
+ BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);\r
+ Graphics2D graphics = img.createGraphics();\r
+ fixFonts(graphics);\r
+ \r
+ // default rendering options\r
+ graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+ graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);\r
+ graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);\r
+ graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);\r
+\r
+ graphics.scale(scale, scale);\r
+\r
+ // draw stuff\r
+ slide.draw(graphics);\r
+\r
+ // save the result\r
+ if (!"null".equals(format)) {\r
+ String outname = file.getName().replaceFirst(".pptx?", "");\r
+ outname = String.format("%1$s-%2$04d.%3$s", outname, slideNo, format);\r
+ File outfile = new File(outdir, outname);\r
+ ImageIO.write(img, format, outfile);\r
+ }\r
+ } \r
+ slideNo++;\r
}\r
- System.out.println("Done");\r
+ \r
+ if (!quite) {\r
+ System.out.println("Done");\r
+ }\r
+ }\r
+\r
+ @SuppressWarnings("unchecked")\r
+ private static void fixFonts(Graphics2D graphics) {\r
+ if (!JvmBugs.hasLineBreakMeasurerBug()) return;\r
+ Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);\r
+ if (fontMap == null) fontMap = new HashMap<String,String>();\r
+ fontMap.put("Calibri", "Lucida Sans");\r
+ fontMap.put("Cambria", "Lucida Bright");\r
+ graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); \r
}\r
}\r
\r
package org.apache.poi.xslf.usermodel;\r
\r
-import java.awt.Dimension;\r
-import java.awt.Graphics2D;\r
-import java.awt.image.BufferedImage;\r
+import java.io.File;\r
import java.lang.reflect.Field;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
\r
-import org.apache.poi.sl.draw.Drawable;\r
-import org.apache.poi.util.JvmBugs;\r
-import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.apache.poi.POIDataSamples;\r
+import org.apache.poi.xslf.util.PPTX2PNG;\r
import org.junit.AfterClass;\r
import org.junit.BeforeClass;\r
import org.junit.Test;\r
@BeforeClass\r
public static void activateJaxpDebug() {\r
jaxpDebugEnable = setDebugFld(true);\r
-// setXmlInputFactory();\r
}\r
\r
@AfterClass\r
return false;\r
}\r
}\r
-\r
-// private static void setXmlInputFactory() {\r
-// String propName = "javax.xml.stream.XMLInputFactory";\r
-// String propVal = "com.sun.xml.internal.stream.XMLInputFactoryImpl";\r
-// try {\r
-// Class.forName(propVal);\r
-// System.setProperty(propName, propVal);\r
-// } catch (Exception e){\r
-// // ignore\r
-// }\r
-// }\r
- \r
\r
@Test\r
public void render() throws Exception {\r
- String[] testFiles = {"backgrounds.pptx","layouts.pptx", "sample.pptx", "shapes.pptx", "themes.pptx",};\r
+ POIDataSamples samples = POIDataSamples.getSlideShowInstance();\r
+\r
+ String[] testFiles = {"alterman_security.ppt","alterman_security.pptx","KEY02.pptx","themes.pptx","backgrounds.pptx","layouts.pptx", "sample.pptx", "shapes.pptx",};\r
+ String[] args = {\r
+ "-format", "null", // png,gif,jpg or null for test\r
+ "-slide", "-1", // -1 for all\r
+ "-outdir", new File("build/tmp/").getCanonicalPath(),\r
+ "-quite",\r
+ "dummyfile"\r
+ };\r
for(String sampleFile : testFiles){\r
+ args[args.length-1] = samples.getFile(sampleFile).getCanonicalPath();\r
try {\r
- XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument(sampleFile);\r
- Dimension pg = pptx.getPageSize();\r
- //int slideNo=1;\r
- for(XSLFSlide slide : pptx.getSlides()){\r
- BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_ARGB);\r
- Graphics2D graphics = img.createGraphics();\r
- fixFonts(graphics);\r
- slide.draw(graphics);\r
- // ImageIO.write(img, "PNG", new File("build/tmp/"+sampleFile.replaceFirst(".pptx?", "-")+slideNo+".png"));\r
- //slideNo++;\r
- }\r
+ PPTX2PNG.main(args);\r
} catch (IllegalStateException e) {\r
throw new IllegalStateException("While reading file " + sampleFile, e);\r
}\r
}\r
}\r
- \r
- @SuppressWarnings("unchecked")\r
- private void fixFonts(Graphics2D graphics) {\r
- if (!JvmBugs.hasLineBreakMeasurerBug()) return;\r
- Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);\r
- if (fontMap == null) fontMap = new HashMap<String,String>();\r
- fontMap.put("Calibri", "Lucida Sans");\r
- fontMap.put("Cambria", "Lucida Bright");\r
- graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); \r
- }\r
}\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.*;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertTrue;\r
+import static org.junit.Assert.fail;\r
\r
import java.awt.Color;\r
import java.io.IOException;\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.*;\r
+import static org.apache.poi.sl.TestCommonSL.sameColor;\r
+import static org.junit.Assert.assertArrayEquals;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertTrue;\r
\r
import java.awt.Color;\r
+import java.io.IOException;\r
import java.util.List;\r
\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
}\r
\r
@Test\r
- public void testCreateSlide(){\r
+ public void testCreateSlide() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
assertEquals(0, ppt.getSlides().size());\r
\r
assertFalse(slide.getFollowMasterGraphics());\r
slide.setFollowMasterGraphics(true);\r
assertTrue(slide.getFollowMasterGraphics());\r
+ \r
+ ppt.close();\r
}\r
\r
@Test\r
- public void testImportContent(){\r
+ public void testImportContent() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
\r
XMLSlideShow src = XSLFTestDataSamples.openSampleDocument("themes.pptx");\r
assertEquals(40.0, r1.getFontSize(), 0);\r
assertTrue(r1.isBold());\r
assertTrue(r1.isItalic());\r
- assertEquals(new Color(148, 198, 0), r1.getFontColor());\r
+ assertTrue(sameColor(new Color(148, 198, 0), r1.getFontColor()));\r
assertNull(sh1.getFillColor());\r
assertNull(sh1.getLineColor());\r
\r
assertEquals(18.0, r2.getFontSize(), 0);\r
assertFalse(r2.isBold());\r
assertFalse(r2.isItalic());\r
- assertEquals(Color.white, r2.getFontColor());\r
+ assertTrue(sameColor(Color.white, r2.getFontColor()));\r
assertEquals(new Color(148, 198, 0), sh2.getFillColor());\r
assertEquals(new Color(148, 198, 0), sh2.getLineColor()); // slightly different from PowerPoint!\r
\r
//assertEquals(32.4.0, r3.getFontSize());\r
assertTrue(r3.isBold());\r
assertTrue(r3.isItalic());\r
- assertEquals(new Color(148, 198, 0), r3.getFontColor());\r
+ assertTrue(sameColor(new Color(148, 198, 0), r3.getFontColor()));\r
assertNull(sh3.getFillColor());\r
assertNull(sh3.getLineColor());\r
\r
XSLFPictureShape sh4 = (XSLFPictureShape)shapes2.get(1);\r
XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides().get(4).getShapes().get(1);\r
assertArrayEquals(sh4.getPictureData().getData(), srcPic.getPictureData().getData());\r
+ \r
+ ppt.close();\r
}\r
\r
@Test\r
- public void testMergeSlides(){\r
+ public void testMergeSlides() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
String[] pptx = {"shapes.pptx", "themes.pptx", "layouts.pptx", "backgrounds.pptx"};\r
\r
}\r
}\r
assertEquals(30, ppt.getSlides().size());\r
+ \r
+ ppt.close();\r
} \r
}
\ No newline at end of file
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.*;\r
-\r
-import java.awt.*;\r
+import static org.apache.poi.sl.TestCommonSL.sameColor;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertTrue;\r
+\r
+import java.awt.Color;\r
+import java.awt.Graphics2D;\r
+import java.awt.Rectangle;\r
import java.awt.geom.Rectangle2D;\r
import java.awt.image.BufferedImage;\r
+import java.io.IOException;\r
import java.util.List;\r
\r
import org.apache.poi.sl.draw.DrawTextFragment;\r
import org.apache.poi.sl.draw.DrawTextParagraph;\r
import org.apache.poi.sl.usermodel.AutoNumberingScheme;\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
-import org.apache.poi.util.POILogFactory;\r
-import org.apache.poi.util.POILogger;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
import org.junit.Assume;\r
import org.junit.Test;\r
* @author Yegor Kozlov\r
*/\r
public class TestXSLFTextParagraph {\r
- private static POILogger _logger = POILogFactory.getLogger(XSLFTextParagraph.class);\r
+ // private static POILogger _logger = POILogFactory.getLogger(XSLFTextParagraph.class);\r
\r
static class DrawTextParagraphProxy extends DrawTextParagraph<XSLFTextRun> {\r
DrawTextParagraphProxy(XSLFTextParagraph p) {\r
}\r
\r
@Test\r
- public void testWrappingWidth() throws Exception {\r
+ public void testWrappingWidth() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
XSLFTextShape sh = slide.createAutoShape();\r
expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin;\r
assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 \r
assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0);\r
+ \r
+ ppt.close();\r
}\r
\r
/**\r
* This test requires that the Arial font is available and will run only on windows\r
*/\r
@Test\r
- public void testBreakLines(){\r
+ public void testBreakLines() throws IOException {\r
String os = System.getProperty("os.name");\r
Assume.assumeTrue("Skipping testBreakLines(), it is executed only on Windows machines", (os != null && os.contains("Windows")));\r
\r
// the first line is at least two times higher than the second\r
assertTrue(lines.get(0).getHeight() > lines.get(1).getHeight()*2);\r
\r
+ ppt.close();\r
}\r
\r
@Test\r
- public void testThemeInheritance(){\r
+ public void testThemeInheritance() throws IOException {\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("prProps.pptx");\r
List<XSLFShape> shapes = ppt.getSlides().get(0).getShapes();\r
XSLFTextShape sh1 = (XSLFTextShape)shapes.get(0);\r
XSLFTextShape sh3 = (XSLFTextShape)shapes.get(2);\r
assertEquals("Foundation", sh3.getText());\r
assertEquals(TextAlign.CENTER, sh3.getTextParagraphs().get(0).getTextAlign());\r
+ ppt.close();\r
}\r
\r
@Test\r
- public void testParagraphProperties(){\r
+ public void testParagraphProperties() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
XSLFTextShape sh = slide.createAutoShape();\r
\r
assertEquals(null, p.getBulletFontColor());\r
p.setBulletFontColor(Color.red);\r
- assertEquals(Color.red, p.getBulletFontColor());\r
+ assertTrue(sameColor(Color.red, p.getBulletFontColor()));\r
\r
assertNull(p.getBulletFontSize());\r
p.setBulletFontSize(200.);\r
\r
assertEquals(72.0, p.getDefaultTabSize(), 0);\r
\r
+ ppt.close();\r
}\r
\r
- @Test\r
- public void testLineBreak(){\r
+ @Test(expected = IllegalStateException.class)\r
+ public void testLineBreak() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
- XSLFSlide slide = ppt.createSlide();\r
- XSLFTextShape sh = slide.createAutoShape();\r
-\r
- XSLFTextParagraph p = sh.addNewTextParagraph();\r
- XSLFTextRun r1 = p.addNewTextRun();\r
- r1.setText("Hello,");\r
- XSLFTextRun r2 = p.addLineBreak();\r
- assertEquals("\n", r2.getRawText());\r
- r2.setFontSize(10.0);\r
- assertEquals(10.0, r2.getFontSize(), 0);\r
- XSLFTextRun r3 = p.addNewTextRun();\r
- r3.setText("World!");\r
- r3.setFontSize(20.0);\r
- XSLFTextRun r4 = p.addLineBreak();\r
- assertEquals(20.0, r4.getFontSize(), 0);\r
-\r
- assertEquals("Hello,\nWorld!\n",sh.getText());\r
-\r
try {\r
+ XSLFSlide slide = ppt.createSlide();\r
+ XSLFTextShape sh = slide.createAutoShape();\r
+ \r
+ XSLFTextParagraph p = sh.addNewTextParagraph();\r
+ XSLFTextRun r1 = p.addNewTextRun();\r
+ r1.setText("Hello,");\r
+ XSLFTextRun r2 = p.addLineBreak();\r
+ assertEquals("\n", r2.getRawText());\r
+ r2.setFontSize(10.0);\r
+ assertEquals(10.0, r2.getFontSize(), 0);\r
+ XSLFTextRun r3 = p.addNewTextRun();\r
+ r3.setText("World!");\r
+ r3.setFontSize(20.0);\r
+ XSLFTextRun r4 = p.addLineBreak();\r
+ assertEquals(20.0, r4.getFontSize(), 0);\r
+ \r
+ assertEquals("Hello,\nWorld!\n",sh.getText());\r
+\r
+ // "You cannot change text of a line break, it is always '\\n'"\r
r2.setText("aaa");\r
- fail("Expected IllegalStateException");\r
- } catch (IllegalStateException e){\r
- assertEquals("You cannot change text of a line break, it is always '\\n'", e.getMessage());\r
+ } finally {\r
+ ppt.close();\r
}\r
}\r
}\r
*/\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.apache.poi.sl.TestCommonSL.sameColor;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertTrue;\r
\r
-import java.awt.*;\r
+import java.awt.Color;\r
+import java.io.IOException;\r
+\r
+import org.junit.Test;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFTextRun extends TestCase {\r
+public class TestXSLFTextRun {\r
\r
- public void testRunProperties(){\r
+ @Test\r
+ public void testRunProperties() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
XSLFTextShape sh = slide.createAutoShape();\r
XSLFTextRun r = sh.addNewTextParagraph().addNewTextRun();\r
assertEquals("en-US", r.getRPr().getLang());\r
\r
- assertEquals(0., r.getCharacterSpacing());\r
+ assertEquals(0., r.getCharacterSpacing(), 0);\r
r.setCharacterSpacing(3);\r
- assertEquals(3., r.getCharacterSpacing());\r
+ assertEquals(3., r.getCharacterSpacing(), 0);\r
r.setCharacterSpacing(-3);\r
- assertEquals(-3., r.getCharacterSpacing());\r
+ assertEquals(-3., r.getCharacterSpacing(), 0);\r
r.setCharacterSpacing(0);\r
- assertEquals(0., r.getCharacterSpacing());\r
+ assertEquals(0., r.getCharacterSpacing(), 0);\r
assertFalse(r.getRPr().isSetSpc());\r
\r
- assertEquals(Color.black, r.getFontColor());\r
+ assertTrue(sameColor(Color.black, r.getFontColor()));\r
r.setFontColor(Color.red);\r
- assertEquals(Color.red, r.getFontColor());\r
+ assertTrue(sameColor(Color.red, r.getFontColor()));\r
\r
assertEquals("Calibri", r.getFontFamily());\r
r.setFontFamily("Arial");\r
assertEquals("Arial", r.getFontFamily());\r
\r
- assertEquals(18.0, r.getFontSize());\r
+ assertEquals(18.0, r.getFontSize(), 0);\r
r.setFontSize(13.0);\r
- assertEquals(13.0, r.getFontSize());\r
+ assertEquals(13.0, r.getFontSize(), 0);\r
\r
assertEquals(false, r.isSuperscript());\r
r.setSuperscript(true);\r
assertEquals(true, r.isSubscript());\r
r.setSubscript(false);\r
assertEquals(false, r.isSubscript());\r
+ \r
+ ppt.close();\r
}\r
}\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.*;\r
+import static org.apache.poi.sl.TestCommonSL.sameColor;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertNull;\r
+import static org.junit.Assert.assertSame;\r
+import static org.junit.Assert.assertTrue;\r
\r
import java.awt.Color;\r
+import java.io.IOException;\r
import java.util.List;\r
\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
import org.apache.poi.sl.usermodel.VerticalAlignment;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
import org.junit.Test;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;\r
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;\r
\r
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals("Calibri", r1.getFontFamily());\r
assertEquals(44.0, r1.getFontSize(), 0);\r
- assertEquals(Color.black, r1.getFontColor());\r
+ assertTrue(sameColor(Color.black, r1.getFontColor()));\r
\r
XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
CTPlaceholder ph2 = shape2.getCTPlaceholder();\r
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals("Calibri", r1.getFontFamily());\r
assertEquals(44.0, r1.getFontSize(), 0);\r
- assertEquals(Color.black, r1.getFontColor());\r
+ assertTrue(sameColor(Color.black, r1.getFontColor()));\r
\r
XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
CTPlaceholder ph2 = shape2.getCTPlaceholder();\r
assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
assertEquals(40.0, r1.getFontSize(), 0);\r
- assertEquals(Color.black, r1.getFontColor());\r
+ assertTrue(sameColor(Color.black, r1.getFontColor()));\r
assertTrue(r1.isBold());\r
assertFalse(r1.isItalic());\r
assertFalse(r1.isUnderlined());\r
assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
assertEquals(44.0, r1.getFontSize(), 0);\r
- assertEquals(Color.black, r1.getFontColor());\r
+ assertTrue(sameColor(Color.black, r1.getFontColor()));\r
\r
XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
CTPlaceholder ph2 = shape2.getCTPlaceholder();\r
assertEquals(0, pr5.getParentParagraph().getIndentLevel());\r
assertEquals("Right", pr5.getRawText());\r
assertEquals("Calibri", pr5.getFontFamily());\r
- assertEquals(Color.black, pr5.getFontColor());\r
+ assertTrue(sameColor(Color.black, pr5.getFontColor()));\r
}\r
\r
@SuppressWarnings("unused")\r
assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
assertEquals(44.0, r1.getFontSize(), 0);\r
- assertEquals(Color.black, r1.getFontColor());\r
+ assertTrue(sameColor(Color.black, r1.getFontColor()));\r
assertFalse(r1.isBold());\r
\r
XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
assertEquals(20.0, r1.getFontSize(), 0);\r
- assertEquals(Color.black, r1.getFontColor());\r
+ assertTrue(sameColor(Color.black, r1.getFontColor()));\r
assertTrue(r1.isBold());\r
\r
XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
assertEquals("Calibri", r1.getFontFamily());\r
assertEquals(12.0, r1.getFontSize(), 0);\r
// TODO calculation of tint is incorrect\r
- assertEquals(new Color(64,64,64), r1.getFontColor());\r
+ assertTrue(sameColor(new Color(64,64,64), r1.getFontColor()));\r
\r
XSLFTextShape dt = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_DT);\r
assertEquals("Friday, October 21, 2011", dt.getText());\r
}\r
\r
@Test\r
- public void testTitleStyles(){\r
+ public void testTitleStyles() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
\r
XSLFSlideMaster master = ppt.getSlideMasters().get(0);\r
assertEquals("Calibri", textRun.getFontFamily());\r
lv5PPr.setAlgn(STTextAlignType.CTR);\r
assertEquals(TextAlign.CENTER, paragraph.getTextAlign());\r
+ \r
+ ppt.close();\r
}\r
\r
@Test\r
- public void testBodyStyles(){\r
+ public void testBodyStyles() throws IOException {\r
XMLSlideShow ppt = new XMLSlideShow();\r
\r
XSLFSlideMaster master = ppt.getSlideMasters().get(0);\r
assertEquals("Calibri", r3.getFontFamily());\r
lv3PPr.setAlgn(STTextAlignType.CTR);\r
assertEquals(TextAlign.CENTER, p3.getTextAlign());\r
-\r
+ \r
+ ppt.close();\r
}\r
-\r
}
\ No newline at end of file
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
+import static org.apache.poi.sl.TestCommonSL.sameColor;\r
import static org.junit.Assert.*;\r
\r
import java.awt.Color;\r
\r
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 3");\r
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);\r
- assertEquals(Color.white, run1.getFontColor());\r
+ assertTrue(sameColor(Color.white, run1.getFontColor()));\r
assertEquals(new Color(79, 129, 189), sh1.getFillColor());\r
assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill\r
\r
\r
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 4");\r
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);\r
- assertEquals(Color.white, run1.getFontColor());\r
+ assertTrue(sameColor(Color.white, run1.getFontColor()));\r
assertEquals(new Color(148, 198, 0), sh1.getFillColor());\r
assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill\r
\r
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 3");\r
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);\r
- assertEquals(new Color(148, 198, 0), run2.getFontColor());\r
+ assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor()));\r
assertNull(sh2.getFillColor()); // no fill\r
\r
assertTrue(slide.getSlideLayout().getFollowMasterGraphics());\r
\r
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 1");\r
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);\r
- assertEquals(new Color(148, 198, 0), run2.getFontColor());\r
+ assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor()));\r
assertNull(sh2.getFillColor()); // no fill\r
// font size is 40pt and scale factor is 90%\r
assertEquals(36.0, run2.getFontSize(), 0);\r
\r
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Subtitle 3");\r
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);\r
- assertEquals(new Color(66, 66, 66), run1.getFontColor());\r
+ assertTrue(sameColor(new Color(66, 66, 66), run1.getFontColor()));\r
assertNull(sh1.getFillColor()); // no fill\r
\r
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 2");\r
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);\r
- assertEquals(new Color(148, 198, 0), run2.getFontColor());\r
+ assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor()));\r
assertNull(sh2.getFillColor()); // no fill\r
\r
assertFalse(slide.getSlideLayout().getFollowMasterGraphics());\r
\r
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Title 3");\r
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);\r
- assertEquals(Color.white, run1.getFontColor());\r
+ assertTrue(sameColor(Color.white, run1.getFontColor()));\r
assertNull(sh1.getFillColor()); // no fill\r
\r
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Subtitle 4");\r
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);\r
- assertEquals(Color.white, run2.getFontColor());\r
+ assertTrue(sameColor(Color.white, run2.getFontColor()));\r
assertNull(sh2.getFillColor()); // no fill\r
}\r
}\r
package org.apache.poi.hslf.model;
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherOptRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.hslf.usermodel.HSLFGroupShape;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
+import org.apache.poi.hslf.usermodel.HSLFTextShape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
*
* @author Yegor Kozlov
*/
-public final class Line extends HSLFSimpleShape {
+public final class Line extends HSLFTextShape implements org.apache.poi.sl.usermodel.Line<HSLFTextParagraph> {
public Line(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
super(escherRecord, parent);
}
return _escherContainer;
}
- /**
- * Sets the orientation of the line, if inverse is false, then line goes
- * from top-left to bottom-right, otherwise use inverse equals true
- *
- * @param inverse the orientation of the line
- */
- public void setInverse(boolean inverse) {
- setShapeType(inverse ? ShapeType.LINE_INV : ShapeType.LINE);
- }
-
- /**
- * Gets the orientation of the line, if inverse is false, then line goes
- * from top-left to bottom-right, otherwise inverse equals true
- *
- * @return inverse the orientation of the line
- */
- public boolean isInverse() {
- return (getShapeType() == ShapeType.LINE_INV);
- }
+// /**
+// * Sets the orientation of the line, if inverse is false, then line goes
+// * from top-left to bottom-right, otherwise use inverse equals true
+// *
+// * @param inverse the orientation of the line
+// */
+// public void setInverse(boolean inverse) {
+// setShapeType(inverse ? ShapeType.LINE_INV : ShapeType.LINE);
+// }
+//
+// /**
+// * Gets the orientation of the line, if inverse is false, then line goes
+// * from top-left to bottom-right, otherwise inverse equals true
+// *
+// * @return inverse the orientation of the line
+// */
+// public boolean isInverse() {
+// return (getShapeType() == ShapeType.LINE_INV);
+// }
}
package org.apache.poi.hslf.model;
-import java.awt.*;
-import java.awt.font.*;
-import java.awt.geom.*;
-import java.awt.image.*;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Paint;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.Toolkit;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Arc2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.text.AttributedCharacterIterator;
import java.util.Map;
import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.hslf.usermodel.HSLFFreeformShape;
+import org.apache.poi.hslf.usermodel.HSLFGroupShape;
+import org.apache.poi.hslf.usermodel.HSLFSimpleShape;
+import org.apache.poi.hslf.usermodel.HSLFTextBox;
+import org.apache.poi.hslf.usermodel.HSLFTextRun;
+import org.apache.poi.sl.draw.DrawPaint;
import org.apache.poi.sl.usermodel.StrokeStyle;
import org.apache.poi.sl.usermodel.VerticalAlignment;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
rt.setFontSize((double)_font.getSize());
rt.setFontFamily(_font.getFamily());
- if (getColor() != null) rt.setFontColor(getColor());
+ if (getColor() != null) rt.setFontColor(DrawPaint.createSolidPaint(getColor()));
if (_font.isBold()) rt.setBold(true);
if (_font.isItalic()) rt.setItalic(true);
import java.io.InputStream;
import java.util.List;
-import org.apache.poi.ddf.*;
+import org.apache.poi.ddf.EscherBSERecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherOptRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.hslf.record.Document;
-import org.apache.poi.sl.usermodel.*;
-import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+import org.apache.poi.sl.draw.DrawPaint;
+import org.apache.poi.sl.usermodel.FillStyle;
+import org.apache.poi.sl.usermodel.PaintStyle;
import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
return new FillStyle() {
public PaintStyle getPaint() {
switch (getFillType()) {
- case FILL_SOLID: {
- return new SolidPaint() {
- public ColorStyle getSolidColor() {
- return new ColorStyle() {
- public Color getColor() { return getForegroundColor(); }
- public int getAlpha() { return -1; }
- public int getLumOff() { return -1; }
- public int getLumMod() { return -1; }
- public int getShade() { return -1; }
- public int getTint() { return -1; }
- };
- }
- };
- }
+ case FILL_SOLID:
+ return DrawPaint.createSolidPaint(getForegroundColor());
case FILL_PICTURE: {
final HSLFPictureData pd = getPictureData();
if (pd == null) break;
logger.log(POILogger.WARN, "unsuported fill type: " + getFillType());
break;
}
- return PaintStyle.TRANSPARENT_PAINT;
+ return null;
}
};
}
// Complex Accesser methods follow
/**
- * Return title of this slide or <code>null</code> if the slide does not have title.
* <p>
* The title is a run of text of type <code>TextHeaderAtom.CENTER_TITLE_TYPE</code> or
* <code>TextHeaderAtom.TITLE_TYPE</code>
* </p>
*
* @see TextHeaderAtom
- *
- * @return title of this slide
*/
+ @Override
public String getTitle(){
for (List<HSLFTextParagraph> tp : getTextParagraphs()) {
if (tp.isEmpty()) continue;
this(new HSLFSlideShowImpl(inputStream));
}
+ /**
+ * Constructs a Powerpoint document from an POIFSFileSystem.
+ */
+ public HSLFSlideShow(POIFSFileSystem inputStream) throws IOException {
+ this(new HSLFSlideShowImpl(inputStream));
+ }
+
+ /**
+ * Constructs a Powerpoint document from an DirectoryNode.
+ */
+ public HSLFSlideShow(DirectoryNode root) throws IOException {
+ this(new HSLFSlideShowImpl(root));
+ }
+
/**
* Use the PersistPtrHolder entries to figure out what is the "most recent"
* version of all the core records (Document, Notes, Slide etc), and save a
import org.apache.poi.hslf.model.textproperties.*;\r
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;\r
import org.apache.poi.hslf.record.*;\r
+import org.apache.poi.sl.draw.DrawPaint;\r
import org.apache.poi.sl.usermodel.AutoNumberingScheme;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
import org.apache.poi.sl.usermodel.TextParagraph;\r
import org.apache.poi.util.*;\r
\r
}\r
\r
@Override\r
- public Color getBulletFontColor() {\r
- return HSLFTextParagraph.this.getBulletColor();\r
+ public void setBulletFontColor(Color color) {\r
+ setBulletFontColor(DrawPaint.createSolidPaint(color));\r
+ }\r
+ \r
+ @Override\r
+ public void setBulletFontColor(PaintStyle color) {\r
+ if (!(color instanceof SolidPaint)) {\r
+ throw new IllegalArgumentException("HSLF only supports SolidPaint");\r
+ }\r
+ SolidPaint sp = (SolidPaint)color;\r
+ Color col = DrawPaint.applyColorTransform(sp.getSolidColor());\r
+ HSLFTextParagraph.this.setBulletColor(col);\r
+ }\r
+ \r
+ @Override\r
+ public PaintStyle getBulletFontColor() {\r
+ Color col = HSLFTextParagraph.this.getBulletColor();\r
+ return DrawPaint.createSolidPaint(col);\r
}\r
\r
@Override\r
TextProp tp = getPropVal(_paragraphStyle, "bullet.color", this);\r
if (tp == null) {\r
// if bullet color is undefined, return color of first run\r
- return (_runs.isEmpty()) ? null : _runs.get(0).getFontColor();\r
+ if (_runs.isEmpty()) return null;\r
+ SolidPaint sp = _runs.get(0).getFontColor();\r
+ return DrawPaint.applyColorTransform(sp.getSolidColor());\r
}\r
\r
return getColorFromColorIndexStruct(tp.getValue(), _sheet);\r
import java.awt.Color;
-import org.apache.poi.hslf.model.textproperties.*;
+import org.apache.poi.hslf.model.textproperties.BitMaskTextProp;
+import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp;
+import org.apache.poi.hslf.model.textproperties.TextProp;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
+import org.apache.poi.sl.draw.DrawPaint;
+import org.apache.poi.sl.usermodel.PaintStyle;
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
}
/**
- * @return font color as RGB value
- * @see java.awt.Color
+ * @return font color as PaintStyle
*/
- public Color getFontColor() {
+ @Override
+ public SolidPaint getFontColor() {
TextProp tp = getPropVal(characterStyle, "font.color", parentParagraph);
- return (tp == null) ? null
- : HSLFTextParagraph.getColorFromColorIndexStruct(tp.getValue(), parentParagraph.getSheet());
+ if (tp == null) return null;
+ Color color = HSLFTextParagraph.getColorFromColorIndexStruct(tp.getValue(), parentParagraph.getSheet());
+ SolidPaint ps = DrawPaint.createSolidPaint(color);
+ return ps;
}
/**
setCharTextPropVal("font.color", bgr);
}
- /**
- * Sets color of the text, as a java.awt.Color
- */
- public void setFontColor(Color color) {
+
+ @Override
+ public void setFontColor(Color color) {
+ setFontColor(DrawPaint.createSolidPaint(color));
+ }
+
+ @Override
+ public void setFontColor(PaintStyle color) {
+ if (!(color instanceof SolidPaint)) {
+ throw new IllegalArgumentException("HSLF only supports solid paint");
+ }
// In PowerPont RGB bytes are swapped, as BGR
- int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB();
+ SolidPaint sp = (SolidPaint)color;
+ Color c = DrawPaint.applyColorTransform(sp.getSolidColor());
+ int rgb = new Color(c.getBlue(), c.getGreen(), c.getRed(), 254).getRGB();
setFontColor(rgb);
}
package org.apache.poi.hslf.model;
+import static org.apache.poi.sl.TestCommonSL.sameColor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
import org.apache.poi.hslf.usermodel.HSLFTextRun;
import org.apache.poi.hslf.usermodel.HSLFTextShape;
+import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
-import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.junit.Before;
import org.junit.Test;
List<HSLFTextParagraph> para = tb.getTextParagraphs();
HSLFTextRun tr = para.get(0).getTextRuns().get(0);
assertEquals("para 1 run 1. ", tr.getRawText());
- assertEquals(Color.black, tr.getFontColor());
+ assertTrue(sameColor(Color.black, tr.getFontColor()));
tr = para.get(0).getTextRuns().get(1);
assertEquals("para 1 run 2.\r", tr.getRawText());
- assertEquals(Color.red, tr.getFontColor());
+ assertTrue(sameColor(Color.red, tr.getFontColor()));
tr = para.get(1).getTextRuns().get(0);
assertEquals("para 2 run 1. ", tr.getRawText());
- assertEquals(Color.yellow, tr.getFontColor());
+ assertTrue(sameColor(Color.yellow, tr.getFontColor()));
tr = para.get(1).getTextRuns().get(1);
assertEquals("para 2 run 2. para 2 run 3.", tr.getRawText());
- assertEquals(Color.black, tr.getFontColor());
+ assertTrue(sameColor(Color.black, tr.getFontColor()));
assertTrue(tr.isStrikethrough());
}
assertTrue(rt.isItalic());
assertFalse(rt.isUnderlined());
assertEquals("Arial", rt.getFontFamily());
- assertEquals(Color.red, rt.getFontColor());
+ assertTrue(sameColor(Color.red, rt.getFontColor()));
// Serialize and read again
ByteArrayOutputStream out = new ByteArrayOutputStream();
assertTrue(rt.isItalic());
assertFalse(rt.isUnderlined());
assertEquals("Arial", rt.getFontFamily());
- assertEquals(Color.red, rt.getFontColor());
+ assertTrue(sameColor(Color.red, rt.getFontColor()));
}
/**
package org.apache.poi.hslf.usermodel;
-import static org.junit.Assert.*;
+import static org.apache.poi.sl.TestCommonSL.sameColor;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import java.awt.Color;
-import java.io.*;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.util.List;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
-import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.TextBytesAtom;
+import org.apache.poi.hslf.record.TextCharsAtom;
+import org.apache.poi.hslf.record.TextHeaderAtom;
import org.junit.Before;
import org.junit.Test;
List<HSLFTextParagraph> run = tx.getTextParagraphs();
HSLFTextRun rt = run.get(0).getTextRuns().get(0);
assertTrue(rt.isBold());
- assertEquals(rt.getFontColor(), Color.RED);
+ assertTrue(sameColor(Color.RED, rt.getFontColor()));
}
}
}
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.sl;\r
+\r
+import java.awt.Color;\r
+\r
+import org.apache.poi.sl.draw.DrawPaint;\r
+import org.apache.poi.sl.usermodel.PaintStyle;\r
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
+import org.junit.Ignore;\r
+\r
+/**\r
+ * Currently only contains helper methods\r
+ */\r
+@Ignore\r
+public class TestCommonSL {\r
+\r
+ public static boolean sameColor(Color colorExpected, PaintStyle paintActual) {\r
+ if (!(paintActual instanceof SolidPaint)) return false;\r
+ Color thisC = DrawPaint.applyColorTransform(((SolidPaint)paintActual).getSolidColor());\r
+ return thisC.equals(colorExpected);\r
+ }\r
+\r
+}\r