diff --git a/src/java/org/apache/poi/sl/draw/DrawPaint.java b/src/java/org/apache/poi/sl/draw/DrawPaint.java index 26a94ed34..2221c2f2f 100644 --- a/src/java/org/apache/poi/sl/draw/DrawPaint.java +++ b/src/java/org/apache/poi/sl/draw/DrawPaint.java @@ -17,25 +17,31 @@ package org.apache.poi.sl.draw; -import static org.apache.poi.sl.usermodel.PaintStyle.TRANSPARENT_PAINT; - -import java.awt.*; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; import java.awt.MultipleGradientPaint.ColorSpaceType; import java.awt.MultipleGradientPaint.CycleMethod; -import java.awt.geom.*; +import java.awt.Paint; +import java.awt.RadialGradientPaint; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.InputStream; -import org.apache.poi.sl.usermodel.*; +import org.apache.poi.sl.usermodel.ColorStyle; +import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; +import org.apache.poi.sl.usermodel.PlaceableShape; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; /** - * This class handles color transformations + * This class handles color transformations. * * @see HSL code taken from Java Tips Weblog */ @@ -50,19 +56,45 @@ public class DrawPaint { this.shape = shape; } - public static SolidPaint createSolidPaint(final Color color) { - return new SolidPaint() { - public ColorStyle getSolidColor() { - return new ColorStyle(){ + private static class SimpleSolidPaint implements SolidPaint { + private final ColorStyle solidColor; + + SimpleSolidPaint(final Color color) { + if (color == null) { + throw new NullPointerException("Color needs to be specified"); + } + this.solidColor = new ColorStyle(){ public Color getColor() { return color; } public int getAlpha() { return -1; } + public int getHueOff() { return -1; } + public int getHueMod() { return -1; } + public int getSatOff() { return -1; } + public int getSatMod() { return -1; } public int getLumOff() { return -1; } public int getLumMod() { return -1; } public int getShade() { return -1; } public int getTint() { return -1; } }; + } + + SimpleSolidPaint(ColorStyle color) { + if (color == null) { + throw new NullPointerException("Color needs to be specified"); } - }; + this.solidColor = color; + } + + public ColorStyle getSolidColor() { + return solidColor; + } + } + + public static SolidPaint createSolidPaint(final Color color) { + return (color == null) ? null : new SimpleSolidPaint(color); + } + + public static SolidPaint createSolidPaint(final ColorStyle color) { + return (color == null) ? null : new SimpleSolidPaint(color); } public Paint getPaint(Graphics2D graphics, PaintStyle paint) { @@ -95,26 +127,26 @@ public class DrawPaint { protected Paint getTexturePaint(TexturePaint fill, Graphics2D graphics) { InputStream is = fill.getImageData(); - if (is == null) return TRANSPARENT_PAINT.getSolidColor().getColor(); + if (is == null) return null; assert(graphics != null); ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER); if (renderer == null) renderer = new ImageRenderer(); try { - renderer.loadImage(fill.getImageData(), fill.getContentType()); + renderer.loadImage(is, fill.getContentType()); + is.close(); } catch (IOException e) { LOG.log(POILogger.ERROR, "Can't load image data - using transparent color", e); - return TRANSPARENT_PAINT.getSolidColor().getColor(); + return null; } int alpha = fill.getAlpha(); - if (alpha != -1) { + if (0 <= alpha && alpha < 100000) { renderer.setAlpha(alpha/100000.f); } - Dimension dim = renderer.getDimension(); - Rectangle2D textAnchor = new Rectangle2D.Double(0, 0, dim.getWidth(), dim.getHeight()); + Rectangle2D textAnchor = shape.getAnchor(); Paint paint = new java.awt.TexturePaint(renderer.getImage(), textAnchor); return paint; @@ -122,106 +154,102 @@ public class DrawPaint { /** * Convert color transformations in {@link ColorStyle} to a {@link Color} instance + * + * @see Using Office Open XML to Customize Document Formatting in the 2007 Office System + * @see saturation modulation (satMod) + * @see Office Open XML satMod results in more than 100% saturation */ public static Color applyColorTransform(ColorStyle color){ + // TODO: The colors don't match 100% the results of Powerpoint, maybe because we still + // operate in sRGB and not scRGB ... work in progress ... + Color result = color.getColor(); + if (result == null) return null; - if (result == null || color.getAlpha() == 100) { - return TRANSPARENT_PAINT.getSolidColor().getColor(); - } + double alpha = getAlpha(result, color); + double hsl[] = RGB2HSL(result); // values are in the range [0..100] (usually ...) + applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff()); + applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff()); + applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff()); + applyShade(hsl, color); + applyTint(hsl, color); + + result = HSL2RGB(hsl[0], hsl[1], hsl[2], alpha); - result = applyAlpha(result, color); - result = applyLuminance(result, color); - result = applyShade(result, color); - result = applyTint(result, color); - return result; } - protected static Color applyAlpha(Color c, ColorStyle fc) { - int alpha = c.getAlpha(); - return (alpha == 255) ? c : new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); + private static double getAlpha(Color c, ColorStyle fc) { + double alpha = c.getAlpha()/255d; + int fcAlpha = fc.getAlpha(); + if (fcAlpha != -1) { + alpha *= fcAlpha/100000d; + } + return Math.min(1, Math.max(0, alpha)); } /** - * Apply lumMod / lumOff adjustments - * - * @param c the color to modify - * @param fc the color style containing the lumMod / lumOff adjustments - * @return modified color + * Apply the modulation and offset adjustments to the given HSL part + * + * Example for lumMod/lumOff: + * The lumMod value is the percent luminance. A lumMod value of "60000", + * is 60% of the luminance of the original color. + * When the color is a shade of the original theme color, the lumMod + * attribute is the only one of the tags shown here that appears. + * The tag appears after the tag when the color is a + * tint of the original. The lumOff value always equals 1-lumMod, which is used in the tint calculation + * + * Despite having different ways to display the tint and shade percentages, + * all of the programs use the same method to calculate the resulting color. + * Convert the original RGB value to HSL ... and then adjust the luminance (L) + * with one of the following equations before converting the HSL value back to RGB. + * (The % tint in the following equations refers to the tint, themetint, themeshade, + * or lumMod values, as applicable.) + * + * @param hsl the hsl values + * @param hslPart the hsl part to modify [0..2] + * @param mod the modulation adjustment + * @param off the offset adjustment + * @return the modified hsl value * - * @see Using Office Open XML to Customize Document Formatting in the 2007 Office System */ - protected static Color applyLuminance(Color c, ColorStyle fc) { - int lumMod = fc.getLumMod(); - if (lumMod == -1) lumMod = 100000; - - int lumOff = fc.getLumOff(); - if (lumOff == -1) lumOff = 0; - - if (lumMod == 100000 && lumOff == 0) return c; - - // The lumMod value is the percent luminance. A lumMod value of "60000", - // is 60% of the luminance of the original color. - // When the color is a shade of the original theme color, the lumMod - // attribute is the only one of the tags shown here that appears. - // The tag appears after the tag when the color is a - // tint of the original. The lumOff value always equals 1-lumMod, which is used in the tint calculation - // - // Despite having different ways to display the tint and shade percentages, - // all of the programs use the same method to calculate the resulting color. - // Convert the original RGB value to HSL ... and then adjust the luminance (L) - // with one of the following equations before converting the HSL value back to RGB. - // (The % tint in the following equations refers to the tint, themetint, themeshade, - // or lumMod values, as applicable.) - // - // For a shade, the equation is luminance * %tint. - // - // For a tint, the equation is luminance * %tint + (1-%tint). - // (Note that 1-%tint is equal to the lumOff value in DrawingML.) - - double fLumOff = lumOff / 100000d; - double fLumMod = lumMod / 100000d; - - double hsl[] = RGB2HSL(c); - hsl[2] = hsl[2]*fLumMod+fLumOff; - - Color c2 = HSL2RGB(hsl[0], hsl[1], hsl[2], c.getAlpha()/255d); - return c2; + private static void applyHslModOff(double hsl[], int hslPart, int mod, int off) { + if (mod == -1) mod = 100000; + if (off == -1) off = 0; + if (!(mod == 100000 && off == 0)) { + double fOff = off / 1000d; + double fMod = mod / 100000d; + hsl[hslPart] = hsl[hslPart]*fMod+fOff; + } } /** - * This algorithm returns result different from PowerPoint. - * TODO: revisit and improve + * Apply the shade + * + * For a shade, the equation is luminance * %tint. */ - protected static Color applyShade(Color c, ColorStyle fc) { + private static void applyShade(double hsl[], ColorStyle fc) { int shade = fc.getShade(); - if (shade == -1) return c; + if (shade == -1) return; - float fshade = shade / 100000.f; - - float red = c.getRed() * fshade; - float green = c.getGreen() * fshade; - float blue = c.getGreen() * fshade; + double fshade = shade / 100000.d; - return new Color(Math.round(red), Math.round(green), Math.round(blue), c.getAlpha()); + hsl[2] *= fshade; } /** - * This algorithm returns result different from PowerPoint. - * TODO: revisit and improve + * Apply the tint + * + * For a tint, the equation is luminance * %tint + (1-%tint). + * (Note that 1-%tint is equal to the lumOff value in DrawingML.) */ - protected static Color applyTint(Color c, ColorStyle fc) { + private static void applyTint(double hsl[], ColorStyle fc) { int tint = fc.getTint(); - if (tint == -1) return c; + if (tint == -1) return; - float ftint = tint / 100000.f; + double ftint = tint / 100000.f; - float red = ftint * c.getRed() + (1.f - ftint) * 255.f; - float green = ftint * c.getGreen() + (1.f - ftint) * 255.f; - float blue = ftint * c.getBlue() + (1.f - ftint) * 255.f; - - return new Color(Math.round(red), Math.round(green), Math.round(blue), c.getAlpha()); + hsl[2] = hsl[2] * ftint + (100 - ftint*100.); } diff --git a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java index d62b93006..8ffc57e60 100644 --- a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java @@ -47,9 +47,6 @@ public class DrawSimpleShape extends DrawShape { @Override public void draw(Graphics2D graphics) { -// RenderableShape rShape = new RenderableShape(this); -// rShape.render(graphics); - DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(shape); Paint fill = drawPaint.getPaint(graphics, shape.getFillStyle().getPaint()); Paint line = drawPaint.getPaint(graphics, shape.getStrokeStyle().getPaint()); diff --git a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java index e4ce1d760..1a40372be 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextParagraph.java @@ -17,18 +17,32 @@ package org.apache.poi.sl.draw; -import java.awt.Color; import java.awt.Graphics2D; -import java.awt.font.*; +import java.awt.Paint; +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; import java.awt.geom.Rectangle2D; -import java.text.*; +import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator.Attribute; -import java.util.*; +import java.text.AttributedString; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; -import org.apache.poi.sl.usermodel.*; +import org.apache.poi.sl.usermodel.AutoNumberingScheme; +import org.apache.poi.sl.usermodel.Insets2D; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PlaceableShape; +import org.apache.poi.sl.usermodel.Shape; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.sl.usermodel.TextParagraph.BulletStyle; import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; +import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.sl.usermodel.TextRun.TextCap; +import org.apache.poi.sl.usermodel.TextShape; import org.apache.poi.util.Units; public class DrawTextParagraph implements Drawable { @@ -69,9 +83,6 @@ public class DrawTextParagraph implements Drawable { public void draw(Graphics2D graphics){ if (lines.isEmpty()) return; - Insets2D insets = paragraph.getParentShape().getInsets(); - double leftInset = insets.left; - double rightInset = insets.right; double penY = y; boolean firstLine = true; @@ -79,12 +90,17 @@ public class DrawTextParagraph implements Drawable { Double leftMargin = paragraph.getLeftMargin(); if (leftMargin == null) { // if the marL attribute is omitted, then a value of 347663 is implied - leftMargin = Units.toPoints(347663*(indentLevel+1)); + leftMargin = Units.toPoints(347663*indentLevel); } Double indent = paragraph.getIndent(); if (indent == null) { indent = Units.toPoints(347663*indentLevel); } + if (paragraph.getClass().getName().contains("HSLF")) { + // special handling for HSLF + indent -= leftMargin; + } + Double rightMargin = paragraph.getRightMargin(); if (rightMargin == null) { rightMargin = 0d; @@ -104,25 +120,30 @@ public class DrawTextParagraph implements Drawable { } if (bullet != null){ - bullet.setPosition(x + indent, penY); + bullet.setPosition(x+leftMargin+indent, penY); bullet.draw(graphics); // don't let text overlay the bullet and advance by the bullet width double bulletWidth = bullet.getLayout().getAdvance() + 1; - penX = x + Math.max(leftMargin, indent+bulletWidth); + penX = x + Math.max(leftMargin, leftMargin+indent+bulletWidth); } else { - penX = x + indent; + penX = x + leftMargin; } } else { penX = x + leftMargin; } Rectangle2D anchor = DrawShape.getAnchor(graphics, paragraph.getParentShape()); + // Insets are already applied on DrawTextShape.drawContent + // but (outer) anchor need to be adjusted + Insets2D insets = paragraph.getParentShape().getInsets(); + double leftInset = insets.left; + double rightInset = insets.right; TextAlign ta = paragraph.getTextAlign(); if (ta == null) ta = TextAlign.LEFT; switch (ta) { case CENTER: - penX += (anchor.getWidth() - leftMargin - line.getWidth() - leftInset - rightInset) / 2; + penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset - leftMargin) / 2; break; case RIGHT: penX += (anchor.getWidth() - line.getWidth() - leftInset - rightInset); @@ -245,8 +266,14 @@ public class DrawTextParagraph implements Drawable { if (buFont == null) buFont = paragraph.getDefaultFontFamily(); assert(buFont != null); - Color buColor = bulletStyle.getBulletFontColor(); - if (buColor == null) buColor = (Color)firstLineAttr.getAttribute(TextAttribute.FOREGROUND); + PlaceableShape ps = getParagraphShape(); + PaintStyle fgPaintStyle = bulletStyle.getBulletFontColor(); + Paint fgPaint; + if (fgPaintStyle == null) { + fgPaint = (Paint)firstLineAttr.getAttribute(TextAttribute.FOREGROUND); + } else { + fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle); + } float fontSize = (Float)firstLineAttr.getAttribute(TextAttribute.SIZE); Double buSz = bulletStyle.getBulletFontSize(); @@ -256,7 +283,7 @@ public class DrawTextParagraph implements Drawable { AttributedString str = new AttributedString(buCharacter); - str.addAttribute(TextAttribute.FOREGROUND, buColor); + str.addAttribute(TextAttribute.FOREGROUND, fgPaint); str.addAttribute(TextAttribute.FAMILY, buFont); str.addAttribute(TextAttribute.SIZE, fontSize); @@ -382,11 +409,31 @@ public class DrawTextParagraph implements Drawable { this.endIndex = endIndex; } } + + /** + * Helper method for paint style relative to bounds, e.g. gradient paint + */ + private PlaceableShape getParagraphShape() { + PlaceableShape ps = new PlaceableShape(){ + public ShapeContainer getParent() { return null; } + public Rectangle2D getAnchor() { return paragraph.getParentShape().getAnchor(); } + public void setAnchor(Rectangle2D anchor) {} + public double getRotation() { return 0; } + public void setRotation(double theta) {} + public void setFlipHorizontal(boolean flip) {} + public void setFlipVertical(boolean flip) {} + public boolean getFlipHorizontal() { return false; } + public boolean getFlipVertical() { return false; } + }; + return ps; + } protected AttributedString getAttributedString(Graphics2D graphics, StringBuilder text){ List attList = new ArrayList(); if (text == null) text = new StringBuilder(); + PlaceableShape ps = getParagraphShape(); + DrawFontManager fontHandler = (DrawFontManager)graphics.getRenderingHint(Drawable.FONT_HANDLER); for (TextRun run : paragraph){ @@ -398,9 +445,9 @@ public class DrawTextParagraph implements Drawable { text.append(runText); int endIndex = text.length(); - Color fgColor = run.getFontColor(); - if (fgColor == null) fgColor = Color.BLACK; - attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgColor, beginIndex, endIndex)); + PaintStyle fgPaintStyle = run.getFontColor(); + Paint fgPaint = new DrawPaint(ps).getPaint(graphics, fgPaintStyle); + attList.add(new AttributedStringData(TextAttribute.FOREGROUND, fgPaint, beginIndex, endIndex)); // user can pass an custom object to convert fonts String fontFamily = run.getFontFamily(); diff --git a/src/java/org/apache/poi/sl/draw/DrawTextShape.java b/src/java/org/apache/poi/sl/draw/DrawTextShape.java index 3be880ec0..36896ba68 100644 --- a/src/java/org/apache/poi/sl/draw/DrawTextShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawTextShape.java @@ -102,7 +102,6 @@ public class DrawTextShape> paragraphs = shape.iterator(); diff --git a/src/java/org/apache/poi/sl/usermodel/ColorStyle.java b/src/java/org/apache/poi/sl/usermodel/ColorStyle.java index 9be847b36..fba7f5eae 100644 --- a/src/java/org/apache/poi/sl/usermodel/ColorStyle.java +++ b/src/java/org/apache/poi/sl/usermodel/ColorStyle.java @@ -32,17 +32,55 @@ public interface ColorStyle { int getAlpha(); /** - * the luminance shift as expressed by a percentage relative to the input color + * the hue shift as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return hue shift in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getHueOff(); + + /** + * the hue as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return hue in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getHueMod(); + + /** + * the saturation shift as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return saturation shift in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getSatOff(); + + /** + * the saturation as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% + * + * @return saturation in percents in the range [0..100000] (usually ...) + * or -1 if the value is not set + */ + int getSatMod(); + + /** + * the luminance shift as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100% * - * @return luminance shift in percents in the range [0..100000] + * @return luminance shift in percents in the range [0..100000] (usually ...) * or -1 if the value is not set */ int getLumOff(); /** - * the luminance as expressed by a percentage relative to the input color + * the luminance as expressed by a percentage relative to the input color. + * Be aware that OOXML also returns values greater than 100%. * - * @return luminance in percents in the range [0..100000] + * @return luminance in percents in the range [0..100000] (usually ...) * or -1 if the value is not set */ int getLumMod(); @@ -50,8 +88,9 @@ public interface ColorStyle { /** * specifies a darker version of its input color. * A 10% shade is 10% of the input color combined with 90% black. + * Be aware that OOXML also returns values greater than 100%. * - * @return the value of the shade specified as percents in the range [0..100000] + * @return the value of the shade specified as percents in the range [0..100000] (usually ...) * with 0% indicating minimal shade and 100% indicating maximum * or -1 if the value is not set */ @@ -60,8 +99,9 @@ public interface ColorStyle { /** * specifies a lighter version of its input color. * A 10% tint is 10% of the input color combined with 90% white. + * Be aware that OOXML also returns values greater than 100% * - * @return the value of the tint specified as percents in the range [0..100000] + * @return the value of the tint specified as percents in the range [0..100000] (usually ...) * with 0% indicating minimal tint and 100% indicating maximum * or -1 if the value is not set */ diff --git a/src/java/org/apache/poi/sl/usermodel/PaintStyle.java b/src/java/org/apache/poi/sl/usermodel/PaintStyle.java index 255120169..25651043b 100644 --- a/src/java/org/apache/poi/sl/usermodel/PaintStyle.java +++ b/src/java/org/apache/poi/sl/usermodel/PaintStyle.java @@ -17,14 +17,12 @@ 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(); } @@ -58,6 +56,4 @@ public interface PaintStyle { */ int getAlpha(); } - - SolidPaint TRANSPARENT_PAINT = DrawPaint.createSolidPaint(new Color(0xFF, 0xFF, 0xFF, 0)); } diff --git a/src/java/org/apache/poi/sl/usermodel/Slide.java b/src/java/org/apache/poi/sl/usermodel/Slide.java index 7b238de17..b992a5e3c 100644 --- a/src/java/org/apache/poi/sl/usermodel/Slide.java +++ b/src/java/org/apache/poi/sl/usermodel/Slide.java @@ -18,20 +18,26 @@ package org.apache.poi.sl.usermodel; public interface Slide> extends Sheet { - 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(); } diff --git a/src/java/org/apache/poi/sl/usermodel/SlideShow.java b/src/java/org/apache/poi/sl/usermodel/SlideShow.java index 5ced5b21e..e8f442821 100644 --- a/src/java/org/apache/poi/sl/usermodel/SlideShow.java +++ b/src/java/org/apache/poi/sl/usermodel/SlideShow.java @@ -21,7 +21,6 @@ import java.awt.Dimension; 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 { diff --git a/src/java/org/apache/poi/sl/usermodel/TextParagraph.java b/src/java/org/apache/poi/sl/usermodel/TextParagraph.java index 0b2eb062c..97296bb0b 100644 --- a/src/java/org/apache/poi/sl/usermodel/TextParagraph.java +++ b/src/java/org/apache/poi/sl/usermodel/TextParagraph.java @@ -20,6 +20,7 @@ package org.apache.poi.sl.usermodel; import java.awt.Color; + public interface TextParagraph extends Iterable { /** @@ -113,7 +114,20 @@ public interface TextParagraph extends Iterable { * @return the bullet point font size */ Double getBulletFontSize(); - Color getBulletFontColor(); + + /** + * Convenience function to set a solid color + */ + void setBulletFontColor(Color color); + + void setBulletFontColor(PaintStyle color); + + /** + * + * @return the color of bullet characters within a given paragraph. + * A {@code null} value means to use the text font color. + */ + PaintStyle getBulletFontColor(); AutoNumberingScheme getAutoNumberingScheme(); /** diff --git a/src/java/org/apache/poi/sl/usermodel/TextRun.java b/src/java/org/apache/poi/sl/usermodel/TextRun.java index 946bfc321..ff76a98e0 100644 --- a/src/java/org/apache/poi/sl/usermodel/TextRun.java +++ b/src/java/org/apache/poi/sl/usermodel/TextRun.java @@ -19,6 +19,8 @@ package org.apache.poi.sl.usermodel; import java.awt.Color; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; + /** * Some text. */ @@ -34,8 +36,33 @@ public interface TextRun { 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); /** diff --git a/src/ooxml/java/org/apache/poi/sl/SlideShowFactory.java b/src/ooxml/java/org/apache/poi/sl/SlideShowFactory.java new file mode 100644 index 000000000..19446c98c --- /dev/null +++ b/src/ooxml/java/org/apache/poi/sl/SlideShowFactory.java @@ -0,0 +1,298 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.sl; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.PushbackInputStream; +import java.security.GeneralSecurityException; + +import org.apache.poi.EmptyFileException; +import org.apache.poi.EncryptedDocumentException; +import org.apache.poi.POIXMLDocument; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.crypt.EncryptionInfo; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.OfficeXmlFileException; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.util.IOUtils; +import org.apache.poi.xslf.usermodel.XMLSlideShow; + +public class SlideShowFactory { + /** + * Creates a HSLFSlideShow from the given POIFSFileSystem + *

Note that in order to properly release resources the + * SlideShow should be closed after use. + */ + public static SlideShow create(POIFSFileSystem fs) throws IOException { + return new HSLFSlideShow(fs); + } + + /** + * Creates a HSLFSlideShow from the given NPOIFSFileSystem + *

Note that in order to properly release resources the + * SlideShow should be closed after use. + */ + public static SlideShow create(NPOIFSFileSystem fs) throws IOException { + try { + return create(fs, null); + } catch (InvalidFormatException e) { + // Special case of OOXML-in-POIFS which is broken + throw new IOException(e); + } + } + + /** + * Creates a SlideShow from the given NPOIFSFileSystem, which may + * be password protected + * + * @param fs The {@link NPOIFSFileSystem} to read the document from + * @param password The password that should be used or null if no password is necessary. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow} + */ + private static SlideShow create(NPOIFSFileSystem fs, String password) throws IOException, InvalidFormatException { + DirectoryNode root = fs.getRoot(); + + // Encrypted OOXML files go inside OLE2 containers, is this one? + if (root.hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) { + EncryptionInfo info = new EncryptionInfo(fs); + Decryptor d = Decryptor.getInstance(info); + + boolean passwordCorrect = false; + InputStream stream = null; + try { + if (password != null && d.verifyPassword(password)) { + passwordCorrect = true; + } + if (!passwordCorrect && d.verifyPassword(Decryptor.DEFAULT_PASSWORD)) { + passwordCorrect = true; + } + if (passwordCorrect) { + stream = d.getDataStream(root); + } + } catch (GeneralSecurityException e) { + throw new IOException(e); + } + + if (! passwordCorrect) { + if (password != null) + throw new EncryptedDocumentException("Password incorrect"); + else + throw new EncryptedDocumentException("The supplied spreadsheet is protected, but no password was supplied"); + } + + OPCPackage pkg = OPCPackage.open(stream); + return create(pkg); + } + + // If we get here, it isn't an encrypted PPTX file + // So, treat it as a regular HSLF PPT one + if (password != null) { + Biff8EncryptionKey.setCurrentUserPassword(password); + } + SlideShow wb = new HSLFSlideShow(root); + Biff8EncryptionKey.setCurrentUserPassword(null); + return wb; + } + + /** + * Creates a XMLSlideShow from the given OOXML Package + * + *

Note that in order to properly release resources the + * SlideShow should be closed after use.

+ * + * @param pkg The {@link OPCPackage} opened for reading data. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + */ + public static SlideShow create(OPCPackage pkg) throws IOException { + return new XMLSlideShow(pkg); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given InputStream. + * + *

Your input stream MUST either support mark/reset, or + * be wrapped as a {@link PushbackInputStream}! Note that + * using an {@link InputStream} has a higher memory footprint + * than using a {@link File}.

+ * + *

Note that in order to properly release resources the + * SlideShow should be closed after use. Note also that loading + * from an InputStream requires more memory than loading + * from a File, so prefer {@link #create(File)} where possible. + * + * @param inp The {@link InputStream} to read data from. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow} + * @throws EncryptedDocumentException If the SlideShow given is password protected + */ + public static SlideShow create(InputStream inp) throws IOException, InvalidFormatException, EncryptedDocumentException { + return create(inp, null); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given InputStream, which may be password protected. + *

Your input stream MUST either support mark/reset, or + * be wrapped as a {@link PushbackInputStream}! Note that + * using an {@link InputStream} has a higher memory footprint + * than using a {@link File}.

+ * + *

Note that in order to properly release resources the + * SlideShow should be closed after use. Note also that loading + * from an InputStream requires more memory than loading + * from a File, so prefer {@link #create(File)} where possible.

+ * + * @param inp The {@link InputStream} to read data from. + * @param password The password that should be used or null if no password is necessary. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow} + * @throws EncryptedDocumentException If the wrong password is given for a protected file + * @throws EmptyFileException If an empty stream is given + */ + public static SlideShow create(InputStream inp, String password) throws IOException, InvalidFormatException, EncryptedDocumentException { + // If clearly doesn't do mark/reset, wrap up + if (! inp.markSupported()) { + inp = new PushbackInputStream(inp, 8); + } + + // Ensure that there is at least some data there + byte[] header8 = IOUtils.peekFirst8Bytes(inp); + + // Try to create + if (NPOIFSFileSystem.hasPOIFSHeader(header8)) { + NPOIFSFileSystem fs = new NPOIFSFileSystem(inp); + return create(fs, password); + } + if (POIXMLDocument.hasOOXMLHeader(inp)) { + return new XMLSlideShow(OPCPackage.open(inp)); + } + throw new IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable. + *

Note that in order to properly release resources the + * SlideShow should be closed after use. + * + * @param file The file to read data from. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow} + * @throws EncryptedDocumentException If the SlideShow given is password protected + */ + public static SlideShow create(File file) throws IOException, InvalidFormatException, EncryptedDocumentException { + return create(file, null); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable, and + * may be password protected + *

Note that in order to properly release resources the + * SlideShow should be closed after use. + * + * @param file The file to read data from. + * @param password The password that should be used or null if no password is necessary. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow} + * @throws EncryptedDocumentException If the wrong password is given for a protected file + * @throws EmptyFileException If an empty stream is given + */ + public static SlideShow create(File file, String password) throws IOException, InvalidFormatException, EncryptedDocumentException { + return create(file, password, false); + } + + /** + * Creates the appropriate HSLFSlideShow / XMLSlideShow from + * the given File, which must exist and be readable, and + * may be password protected + *

Note that in order to properly release resources the + * SlideShow should be closed after use. + * + * @param file The file to read data from. + * @param password The password that should be used or null if no password is necessary. + * @param readOnly If the SlideShow should be opened in read-only mode to avoid writing back + * changes when the document is closed. + * + * @return The created SlideShow + * + * @throws IOException if an error occurs while reading the data + * @throws InvalidFormatException if the contents of the file cannot be parsed into a {@link SlideShow} + * @throws EncryptedDocumentException If the wrong password is given for a protected file + * @throws EmptyFileException If an empty stream is given + */ + public static SlideShow create(File file, String password, boolean readOnly) throws IOException, InvalidFormatException, EncryptedDocumentException { + if (! file.exists()) { + throw new FileNotFoundException(file.toString()); + } + + try { + NPOIFSFileSystem fs = new NPOIFSFileSystem(file, readOnly); + return create(fs, password); + } catch(OfficeXmlFileException e) { + // opening as .ppt failed => try opening as .pptx + OPCPackage pkg = OPCPackage.open(file, readOnly ? PackageAccess.READ : PackageAccess.READ_WRITE); + try { + return new XMLSlideShow(pkg); +// } catch (IOException ioe) { +// // ensure that file handles are closed (use revert() to not re-write the file) +// pkg.revert(); +// //pkg.close(); +// +// // rethrow exception +// throw ioe; + } catch (IllegalArgumentException ioe) { + // ensure that file handles are closed (use revert() to not re-write the file) + pkg.revert(); + //pkg.close(); + + // rethrow exception + throw ioe; + } + } + } +} diff --git a/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java b/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java index ced941ccb..c20f94259 100644 --- a/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java +++ b/src/ooxml/java/org/apache/poi/xslf/model/CharacterPropertyFetcher.java @@ -27,8 +27,6 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties * @author Yegor Kozlov */ public abstract class CharacterPropertyFetcher extends ParagraphPropertyFetcher { - public boolean isFetchingFromMaster = false; - public CharacterPropertyFetcher(int level) { super(level); } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java index 09e05d964..67a41faec 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFColor.java @@ -78,6 +78,22 @@ public class XSLFColor { return getRawValue("alpha"); } + public int getHueOff() { + return getRawValue("hueOff"); + } + + public int getHueMod() { + return getRawValue("hueMod"); + } + + public int getSatOff() { + return getRawValue("satOff"); + } + + public int getSatMod() { + return getRawValue("satMod"); + } + public int getLumOff() { return getRawValue("lumOff"); } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java index c3b0b1a51..f312145b9 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java @@ -44,8 +44,12 @@ public class XSLFDrawing { XmlObject[] cNvPr = sheet.getSpTree().selectPath( "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:cNvPr"); for(XmlObject o : cNvPr) { - CTNonVisualDrawingProps p = (CTNonVisualDrawingProps)o; - _shapeId = (int)Math.max(_shapeId, p.getId()); + // powerpoint generates AlternateContent elements which cNvPr elements aren't recognized + // ignore them for now + if (o instanceof CTNonVisualDrawingProps) { + CTNonVisualDrawingProps p = (CTNonVisualDrawingProps)o; + _shapeId = (int)Math.max(_shapeId, p.getId()); + } } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java index 85e85b6a4..fd42bc2d7 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java @@ -21,8 +21,6 @@ import java.awt.Color; import java.awt.geom.Rectangle2D; import org.apache.poi.sl.draw.DrawPaint; -import org.apache.poi.sl.usermodel.ColorStyle; -import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.Shadow; import org.apache.poi.util.Units; @@ -90,7 +88,7 @@ public class XSLFShadow extends XSLFShape implements Shadow { */ public Color getFillColor() { SolidPaint ps = getFillStyle(); - if (ps == PaintStyle.TRANSPARENT_PAINT) return null; + if (ps == null) return null; Color col = DrawPaint.applyColorTransform(ps.getSolidColor()); return col; } @@ -99,14 +97,10 @@ public class XSLFShadow extends XSLFShape implements Shadow { public SolidPaint getFillStyle() { XSLFTheme theme = getSheet().getTheme(); CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); - if(ct == null) return PaintStyle.TRANSPARENT_PAINT; + if(ct == null) return null; CTSchemeColor phClr = ct.getSchemeClr(); final XSLFColor xc = new XSLFColor(ct, theme, phClr); - return new SolidPaint(){ - public ColorStyle getSolidColor() { - return xc.getColorStyle(); - } - }; + return DrawPaint.createSolidPaint(xc.getColorStyle()); } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index 3ea1d3a7c..d0c512382 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -27,10 +27,10 @@ import java.util.Comparator; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.usermodel.ColorStyle; import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; -import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; import org.apache.poi.sl.usermodel.PlaceableShape; import org.apache.poi.sl.usermodel.Shape; @@ -38,7 +38,20 @@ import org.apache.poi.util.Beta; import org.apache.poi.util.Internal; import org.apache.poi.xslf.model.PropertyFetcher; import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; +import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGradientStop; +import org.openxmlformats.schemas.drawingml.x2006.main.CTGroupShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNoFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle; +import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; +import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference; +import org.openxmlformats.schemas.drawingml.x2006.main.STPathShadeType; import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; import org.openxmlformats.schemas.presentationml.x2006.main.CTBackground; import org.openxmlformats.schemas.presentationml.x2006.main.CTBackgroundProperties; @@ -139,7 +152,7 @@ public abstract class XSLFShape implements Shape { try { pr = shape.getSpPr(); if (((CTShapeProperties)pr).isSetNoFill()) { - setValue(PaintStyle.TRANSPARENT_PAINT); + setValue(null); return true; } } catch (IllegalStateException e) {} @@ -156,21 +169,19 @@ public abstract class XSLFShape implements Shape { } } - if (pr == null) { - setValue(PaintStyle.TRANSPARENT_PAINT); - return true; - } + if (pr == null) return false; PaintStyle paint = null; + PackagePart pp = getSheet().getPackagePart(); for (XmlObject obj : pr.selectPath("*")) { - paint = selectPaint(obj, null, getSheet().getPackagePart()); - if (paint != null) break; + paint = selectPaint(obj, null, pp); + if (paint != null) { + setValue(paint); + return true; + }; } - if (paint == null) return false; - - setValue(paint); - return true; + return false; } }; fetchShapeProperty(fetcher); @@ -190,7 +201,7 @@ public abstract class XSLFShape implements Shape { } paint = selectPaint(fillRef); - return paint == null ? PaintStyle.TRANSPARENT_PAINT : paint; + return paint; } protected CTBackgroundProperties getBgPr() { @@ -347,8 +358,8 @@ public abstract class XSLFShape implements Shape { paint = selectPaint(obj, phClr, pp); if(paint != null) break; } - return paint == null ? PaintStyle.TRANSPARENT_PAINT : paint; - } + return paint; + } /** * Convert shape fill into java.awt.Paint. The result is either Color or @@ -371,13 +382,13 @@ public abstract class XSLFShape implements Shape { */ protected PaintStyle selectPaint(XmlObject obj, final CTSchemeColor phClr, final PackagePart parentPart) { if (obj instanceof CTNoFillProperties) { - return PaintStyle.TRANSPARENT_PAINT; + return null; } else if (obj instanceof CTSolidColorFillProperties) { - return selectPaint((CTSolidColorFillProperties)obj, phClr, parentPart); + return selectPaint((CTSolidColorFillProperties)obj, phClr); } else if (obj instanceof CTBlipFillProperties) { - return selectPaint((CTBlipFillProperties)obj, phClr, parentPart); + return selectPaint((CTBlipFillProperties)obj, parentPart); } else if (obj instanceof CTGradientFillProperties) { - return selectPaint((CTGradientFillProperties) obj, phClr, parentPart); + return selectPaint((CTGradientFillProperties) obj, phClr); } else if (obj instanceof CTStyleMatrixReference) { return selectPaint((CTStyleMatrixReference)obj); } else { @@ -385,17 +396,16 @@ public abstract class XSLFShape implements Shape { } } - protected PaintStyle selectPaint(final CTSolidColorFillProperties solidFill, final CTSchemeColor phClr, final PackagePart parentPart) { + protected PaintStyle selectPaint(CTSolidColorFillProperties solidFill, CTSchemeColor phClr) { final XSLFTheme theme = getSheet().getTheme(); + if (phClr == null && solidFill.isSetSchemeClr()) { + phClr = solidFill.getSchemeClr(); + } final XSLFColor c = new XSLFColor(solidFill, theme, phClr); - return new SolidPaint() { - public ColorStyle getSolidColor() { - return c.getColorStyle(); - } - }; + return DrawPaint.createSolidPaint(c.getColorStyle()); } - protected PaintStyle selectPaint(final CTBlipFillProperties blipFill, final CTSchemeColor phClr, final PackagePart parentPart) { + protected PaintStyle selectPaint(final CTBlipFillProperties blipFill, final PackagePart parentPart) { final CTBlip blip = blipFill.getBlip(); return new TexturePaint() { private PackagePart getPart() { @@ -424,12 +434,12 @@ public abstract class XSLFShape implements Shape { public int getAlpha() { return (blip.sizeOfAlphaModFixArray() > 0) ? blip.getAlphaModFixArray(0).getAmt() - : 0; + : 100000; } }; } - protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, final CTSchemeColor phClr, final PackagePart parentPart) { + protected PaintStyle selectPaint(final CTGradientFillProperties gradFill, CTSchemeColor phClr) { @SuppressWarnings("deprecation") final CTGradientStop[] gs = gradFill.getGsLst().getGsArray(); @@ -448,7 +458,11 @@ public abstract class XSLFShape implements Shape { int i=0; for (CTGradientStop cgs : gs) { - cs[i] = new XSLFColor(cgs, theme, phClr).getColorStyle(); + CTSchemeColor phClrCgs = phClr; + if (phClrCgs == null && cgs.isSetSchemeClr()) { + phClrCgs = cgs.getSchemeClr(); + } + cs[i] = new XSLFColor(cgs, theme, phClrCgs).getColorStyle(); fractions[i] = cgs.getPos() / 100000.f; i++; } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java index bd29667c8..3b0874876 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java @@ -19,8 +19,6 @@ package org.apache.poi.xslf.usermodel; -import static org.apache.poi.sl.usermodel.PaintStyle.TRANSPARENT_PAINT; - import java.awt.Color; import java.awt.geom.Rectangle2D; @@ -31,10 +29,15 @@ import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.sl.draw.geom.CustomGeometry; import org.apache.poi.sl.draw.geom.Guide; import org.apache.poi.sl.draw.geom.PresetGeometries; -import org.apache.poi.sl.usermodel.*; +import org.apache.poi.sl.usermodel.FillStyle; +import org.apache.poi.sl.usermodel.LineDecoration; import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape; import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; +import org.apache.poi.sl.usermodel.PaintStyle; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.ShapeType; +import org.apache.poi.sl.usermodel.SimpleShape; +import org.apache.poi.sl.usermodel.StrokeStyle; import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; @@ -219,7 +222,6 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { */ public Color getLineColor() { PaintStyle ps = getLinePaint(); - if (ps == null || ps == TRANSPARENT_PAINT) return null; if (ps instanceof SolidPaint) { return ((SolidPaint)ps).getSolidColor().getColor(); } @@ -232,7 +234,7 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { CTLineProperties spPr = shape.getSpPr().getLn(); if (spPr != null) { if (spPr.isSetNoFill()) { - setValue(TRANSPARENT_PAINT); // use it as 'nofill' value + setValue(null); // use it as 'nofill' value return true; } @@ -266,7 +268,7 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { // line color was not found, check if it is defined in the theme CTShapeStyle style = getSpStyle(); - if (style == null) return TRANSPARENT_PAINT; + if (style == null) return null; // get a reference to a line style within the style matrix. CTStyleMatrixReference lnRef = style.getLnRef(); @@ -279,7 +281,7 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { paint = getPaint(lnProps, phClr); } - return paint == null ? TRANSPARENT_PAINT : paint; + return paint; } /** @@ -524,7 +526,6 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { */ public Color getFillColor() { PaintStyle ps = getFillPaint(); - if (ps == null || ps == TRANSPARENT_PAINT) return null; if (ps instanceof SolidPaint) { return ((SolidPaint)ps).getSolidColor().getColor(); } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java index 83024ee2e..83453573c 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java @@ -168,13 +168,10 @@ public final class XSLFSlide extends XSLFSheet implements Slide { * @return the color of bullet characters within a given paragraph. * A null value means to use the text font color. */ - public Color getBulletFontColor(){ + public PaintStyle getBulletFontColor(){ final XSLFTheme theme = getParentShape().getSheet().getTheme(); ParagraphPropertyFetcher fetcher = new ParagraphPropertyFetcher(getIndentLevel()){ public boolean fetch(CTTextParagraphProperties props){ @@ -277,19 +280,33 @@ public class XSLFTextParagraph implements TextParagraph { } }; fetchParagraphProperty(fetcher); - return fetcher.getValue(); + Color col = fetcher.getValue(); + return (col == null) ? null : DrawPaint.createSolidPaint(col); } + public void setBulletFontColor(Color color) { + setBulletFontColor(DrawPaint.createSolidPaint(color)); + } + + /** * Set the color to be used on bullet characters within a given paragraph. * * @param color the bullet color */ - public void setBulletFontColor(Color color){ + public void setBulletFontColor(PaintStyle color) { + if (!(color instanceof SolidPaint)) { + throw new IllegalArgumentException("Currently XSLF only supports SolidPaint"); + } + + // TODO: implement setting bullet color to null + SolidPaint sp = (SolidPaint)color; + Color col = DrawPaint.applyColorTransform(sp.getSolidColor()); + CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr(); CTColor c = pr.isSetBuClr() ? pr.getBuClr() : pr.addNewBuClr(); CTSRgbColor clr = c.isSetSrgbClr() ? c.getSrgbClr() : c.addNewSrgbClr(); - clr.setVal(new byte[]{(byte) color.getRed(), (byte) color.getGreen(), (byte) color.getBlue()}); + clr.setVal(new byte[]{(byte) col.getRed(), (byte) col.getGreen(), (byte) col.getBlue()}); } /** @@ -729,7 +746,6 @@ public class XSLFTextParagraph implements TextParagraph { XSLFSheet masterSheet = _shape.getSheet(); for (XSLFSheet m = masterSheet; m != null; m = (XSLFSheet)m.getMasterSheet()) { masterSheet = m; - XmlObject xo = masterSheet.getXmlObject(); for (String xpath : xpaths) { XmlObject[] o = xo.selectPath(xpath); @@ -767,32 +783,35 @@ public class XSLFTextParagraph implements TextParagraph { private boolean fetchParagraphProperty(ParagraphPropertyFetcher visitor){ boolean ok = false; - + XSLFTextShape shape = getParentShape(); + XSLFSheet sheet = shape.getSheet(); + if(_p.isSetPPr()) ok = visitor.fetch(_p.getPPr()); + if (ok) return true; - if(!ok) { - XSLFTextShape shape = getParentShape(); - ok = shape.fetchShapeProperty(visitor); - if(!ok){ - CTPlaceholder ph = shape.getCTPlaceholder(); - if(ph == null){ - // if it is a plain text box then take defaults from presentation.xml - XMLSlideShow ppt = getParentShape().getSheet().getSlideShow(); - CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel()); - if(themeProps != null) ok = visitor.fetch(themeProps); - } - - if(!ok){ - // defaults for placeholders are defined in the slide master - CTTextParagraphProperties defaultProps = getDefaultMasterStyle(); - if(defaultProps != null) ok = visitor.fetch(defaultProps); - } - } + ok = shape.fetchShapeProperty(visitor); + if (ok) return true; + + + CTPlaceholder ph = shape.getCTPlaceholder(); + if(ph == null){ + // if it is a plain text box then take defaults from presentation.xml + XMLSlideShow ppt = sheet.getSlideShow(); + CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(getIndentLevel()); + if (themeProps != null) ok = visitor.fetch(themeProps); } + if (ok) return true; - return ok; + // defaults for placeholders are defined in the slide master + CTTextParagraphProperties defaultProps = getDefaultMasterStyle(); + // TODO: determine master shape + if(defaultProps != null) ok = visitor.fetch(defaultProps); + if (ok) return true; + + return false; } + @SuppressWarnings("deprecation") void copy(XSLFTextParagraph other){ if (other == this) return; @@ -848,7 +867,7 @@ public class XSLFTextParagraph implements TextParagraph { if(buChar != null && !buChar.equals(getBulletCharacter())){ setBulletCharacter(buChar); } - Color buColor = other.getBulletFontColor(); + PaintStyle buColor = other.getBulletFontColor(); if(buColor != null && !buColor.equals(getBulletFontColor())){ setBulletFontColor(buColor); } @@ -920,10 +939,20 @@ public class XSLFTextParagraph implements TextParagraph { } @Override - public Color getBulletFontColor() { + public PaintStyle getBulletFontColor() { return XSLFTextParagraph.this.getBulletFontColor(); } + @Override + public void setBulletFontColor(Color color) { + setBulletFontColor(DrawPaint.createSolidPaint(color)); + } + + @Override + public void setBulletFontColor(PaintStyle color) { + XSLFTextParagraph.this.setBulletFontColor(color); + } + @Override public AutoNumberingScheme getAutoNumberingScheme() { return XSLFTextParagraph.this.getAutoNumberingScheme(); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java index 7a5c78b19..fd0f44d75 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextRun.java @@ -18,6 +18,9 @@ package org.apache.poi.xslf.usermodel; import java.awt.Color; +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.Beta; import org.apache.poi.xslf.model.CharacterPropertyFetcher; @@ -84,10 +87,21 @@ public class XSLFTextRun implements TextRun { @Override public void setFontColor(Color color) { + setFontColor(DrawPaint.createSolidPaint(color)); + } + + @Override + public void setFontColor(PaintStyle color) { + if (!(color instanceof SolidPaint)) { + throw new IllegalArgumentException("Currently only SolidPaint is supported!"); + } + SolidPaint sp = (SolidPaint)color; + CTTextCharacterProperties rPr = getRPr(); CTSolidColorFillProperties fill = rPr.isSetSolidFill() ? rPr.getSolidFill() : rPr.addNewSolidFill(); CTSRgbColor clr = fill.isSetSrgbClr() ? fill.getSrgbClr() : fill.addNewSrgbClr(); - clr.setVal(new byte[]{(byte)color.getRed(), (byte)color.getGreen(), (byte)color.getBlue()}); + Color c = DrawPaint.applyColorTransform(sp.getSolidColor()); + clr.setVal(new byte[]{(byte)c.getRed(), (byte)c.getGreen(), (byte)c.getBlue()}); if(fill.isSetHslClr()) fill.unsetHslClr(); if(fill.isSetPrstClr()) fill.unsetPrstClr(); @@ -98,22 +112,22 @@ public class XSLFTextRun implements TextRun { } @Override - public Color getFontColor(){ - final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); - CTShapeStyle style = _p.getParentShape().getSpStyle(); - final CTSchemeColor phClr = style == null ? null : style.getFontRef().getSchemeClr(); - - CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ + public PaintStyle getFontColor(){ + CharacterPropertyFetcher fetcher = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ - CTSolidColorFillProperties solidFill = props.getSolidFill(); - if(solidFill != null) { - boolean useCtxColor = - (solidFill.isSetSchemeClr() && solidFill.getSchemeClr().getVal() == STSchemeColorVal.PH_CLR) - || isFetchingFromMaster; - Color c = new XSLFColor(solidFill, theme, useCtxColor ? phClr : null).getColor(); - setValue(c); + XSLFShape shape = _p.getParentShape(); + CTShapeStyle style = shape.getSpStyle(); + CTSchemeColor phClr = null; + if (style != null && style.getFontRef() != null) { + phClr = style.getFontRef().getSchemeClr(); + } + + PaintStyle ps = shape.getPaint(props, phClr); + if (ps != null) { + setValue(ps); return true; } + return false; } }; @@ -250,7 +264,7 @@ public class XSLFTextRun implements TextRun { } public byte getPitchAndFamily(){ - final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); + // final XSLFTheme theme = _p.getParentShape().getSheet().getTheme(); CharacterPropertyFetcher visitor = new CharacterPropertyFetcher(_p.getIndentLevel()){ public boolean fetch(CTTextCharacterProperties props){ @@ -474,35 +488,36 @@ public class XSLFTextRun implements TextRun { } private boolean fetchCharacterProperty(CharacterPropertyFetcher fetcher){ + XSLFTextShape shape = _p.getParentShape(); + XSLFSheet sheet = shape.getSheet(); boolean ok = false; - if(_r.isSetRPr()) ok = fetcher.fetch(getRPr()); - - if(!ok) { - XSLFTextShape shape = _p.getParentShape(); - ok = shape.fetchShapeProperty(fetcher); - if(!ok){ - CTPlaceholder ph = shape.getCTPlaceholder(); - if(ph == null){ - // if it is a plain text box then take defaults from presentation.xml - XMLSlideShow ppt = shape.getSheet().getSlideShow(); - CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel()); - if(themeProps != null) { - fetcher.isFetchingFromMaster = true; - ok = fetcher.fetch(themeProps); - } - } - if (!ok) { - CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle(); - if(defaultProps != null) { - fetcher.isFetchingFromMaster = true; - ok = fetcher.fetch(defaultProps); - } - } + if (_r.isSetRPr()) ok = fetcher.fetch(getRPr()); + if (ok) return true; + + ok = shape.fetchShapeProperty(fetcher); + if (ok) return true; + + CTPlaceholder ph = shape.getCTPlaceholder(); + if (ph == null){ + // if it is a plain text box then take defaults from presentation.xml + XMLSlideShow ppt = sheet.getSlideShow(); + CTTextParagraphProperties themeProps = ppt.getDefaultParagraphStyle(_p.getIndentLevel()); + if (themeProps != null) { + // TODO: determine master shape + ok = fetcher.fetch(themeProps); } } + if (ok) return true; - return ok; + CTTextParagraphProperties defaultProps = _p.getDefaultMasterStyle(); + if(defaultProps != null) { + // TODO: determine master shape + ok = fetcher.fetch(defaultProps); + } + if (ok) return true; + + return false; } void copy(XSLFTextRun r){ @@ -511,7 +526,7 @@ public class XSLFTextRun implements TextRun { setFontFamily(srcFontFamily); } - Color srcFontColor = r.getFontColor(); + PaintStyle srcFontColor = r.getFontColor(); if(srcFontColor != null && !srcFontColor.equals(getFontColor())){ setFontColor(srcFontColor); } diff --git a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java index 400c637ca..43fefedf5 100644 --- a/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java +++ b/src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java @@ -19,19 +19,22 @@ package org.apache.poi.xslf.util; -import org.apache.poi.openxml4j.opc.OPCPackage; -import org.apache.poi.xslf.usermodel.XMLSlideShow; -import org.apache.poi.xslf.usermodel.XSLFSlide; - -import javax.imageio.ImageIO; - -import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; -import java.io.FileOutputStream; +import java.io.File; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import javax.imageio.ImageIO; + +import org.apache.poi.sl.SlideShowFactory; +import org.apache.poi.sl.draw.Drawable; +import org.apache.poi.sl.usermodel.Slide; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.util.JvmBugs; /** * An utulity to convert slides of a .pptx slide show to a PNG image @@ -40,22 +43,33 @@ import java.util.List; */ public class PPTX2PNG { - static void usage(){ - System.out.println("Usage: PPTX2PNG [options] "); - System.out.println("Options:"); - System.out.println(" -scale scale factor"); - System.out.println(" -slide 1-based index of a slide to render"); + static void usage(String error){ + String msg = + "Usage: PPTX2PNG [options] \n" + + (error == null ? "" : ("Error: "+error+"\n")) + + "Options:\n" + + " -scale scale factor\n" + + " -slide 1-based index of a slide to render\n" + + " -format png,gif,jpg (,null for testing)" + + " -outdir

output directory, defaults to origin of the ppt/pptx file" + + " -quite do not write to console (for normal processing)"; + + System.out.println(msg); + // no System.exit here, as we also run in junit tests! } public static void main(String[] args) throws Exception { if (args.length == 0) { - usage(); + usage(null); return; } int slidenum = -1; float scale = 1; - String file = null; + File file = null; + String format = "png"; + File outdir = null; + boolean quite = false; for (int i = 0; i < args.length; i++) { if (args[i].startsWith("-")) { @@ -63,55 +77,104 @@ public class PPTX2PNG { scale = Float.parseFloat(args[++i]); } else if ("-slide".equals(args[i])) { slidenum = Integer.parseInt(args[++i]); + } else if ("-format".equals(args[i])) { + format = args[++i]; + } else if ("-outdir".equals(args[i])) { + outdir = new File(args[++i]); + } else if ("-quite".equals(args[i])) { + quite = true; } } else { - file = args[i]; + file = new File(args[i]); } } - if(file == null){ - usage(); + if (file == null || !file.exists()) { + usage("File not specified or it doesn't exist"); return; } - System.out.println("Processing " + file); - XMLSlideShow ppt = new XMLSlideShow(OPCPackage.open(file)); + if (outdir == null) { + outdir = file.getParentFile(); + } + + if (outdir == null || !outdir.exists() || !outdir.isDirectory()) { + usage("Output directory doesn't exist"); + return; + } - Dimension pgsize = ppt.getPageSize(); + if (scale < 0) { + usage("Invalid scale given"); + return; + } + + if (format == null || !format.matches("^(png|gif|jpg|null)$")) { + usage("Invalid format given"); + return; + } + + if (!quite) { + System.out.println("Processing " + file); + } + SlideShow ss = SlideShowFactory.create(file, null, true); + List> slides = ss.getSlides(); + + + if (slidenum < -1 || slidenum == 0 || slidenum > slides.size()) { + usage("slidenum must be either -1 (for all) or within range: [1.."+slides.size()+"] for "+file); + return; + } + + Dimension pgsize = ss.getPageSize(); int width = (int) (pgsize.width * scale); int height = (int) (pgsize.height * scale); - List slide = ppt.getSlides(); - for (int i = 0; i < slide.size(); i++) { - if (slidenum != -1 && slidenum != (i + 1)) continue; + int slideNo=1; + for(Slide slide : slides) { + if (slidenum == -1 || slideNo == slidenum) { + String title = slide.getTitle(); + if (!quite) { + System.out.println("Rendering slide " + slideNo + (title == null ? "" : ": " + title)); + } - String title = slide.get(i).getTitle(); - System.out.println("Rendering slide " + (i + 1) + (title == null ? "" : ": " + title)); + BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = img.createGraphics(); + fixFonts(graphics); + + // default rendering options + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); - BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - Graphics2D graphics = img.createGraphics(); + graphics.scale(scale, scale); - // default rendering options - graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); - graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + // draw stuff + slide.draw(graphics); - graphics.setColor(Color.white); - graphics.clearRect(0, 0, width, height); - - graphics.scale(scale, scale); - - // draw stuff - slide.get(i).draw(graphics); - - // save the result - int sep = file.lastIndexOf("."); - String fname = file.substring(0, sep == -1 ? file.length() : sep) + "-" + (i + 1) +".png"; - FileOutputStream out = new FileOutputStream(fname); - ImageIO.write(img, "png", out); - out.close(); + // save the result + if (!"null".equals(format)) { + String outname = file.getName().replaceFirst(".pptx?", ""); + outname = String.format("%1$s-%2$04d.%3$s", outname, slideNo, format); + File outfile = new File(outdir, outname); + ImageIO.write(img, format, outfile); + } + } + slideNo++; } - System.out.println("Done"); + + if (!quite) { + System.out.println("Done"); + } + } + + @SuppressWarnings("unchecked") + private static void fixFonts(Graphics2D graphics) { + if (!JvmBugs.hasLineBreakMeasurerBug()) return; + Map fontMap = (Map)graphics.getRenderingHint(Drawable.FONT_MAP); + if (fontMap == null) fontMap = new HashMap(); + fontMap.put("Calibri", "Lucida Sans"); + fontMap.put("Cambria", "Lucida Bright"); + graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); } } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java index a0a937aee..2c72f0a44 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java @@ -19,16 +19,11 @@ package org.apache.poi.xslf.usermodel; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; +import java.io.File; import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import org.apache.poi.sl.draw.Drawable; -import org.apache.poi.util.JvmBugs; -import org.apache.poi.xslf.XSLFTestDataSamples; +import org.apache.poi.POIDataSamples; +import org.apache.poi.xslf.util.PPTX2PNG; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; @@ -44,7 +39,6 @@ public class TestPPTX2PNG { @BeforeClass public static void activateJaxpDebug() { jaxpDebugEnable = setDebugFld(true); -// setXmlInputFactory(); } @AfterClass @@ -66,48 +60,26 @@ public class TestPPTX2PNG { return false; } } - -// private static void setXmlInputFactory() { -// String propName = "javax.xml.stream.XMLInputFactory"; -// String propVal = "com.sun.xml.internal.stream.XMLInputFactoryImpl"; -// try { -// Class.forName(propVal); -// System.setProperty(propName, propVal); -// } catch (Exception e){ -// // ignore -// } -// } - @Test public void render() throws Exception { - String[] testFiles = {"backgrounds.pptx","layouts.pptx", "sample.pptx", "shapes.pptx", "themes.pptx",}; + POIDataSamples samples = POIDataSamples.getSlideShowInstance(); + + String[] testFiles = {"alterman_security.ppt","alterman_security.pptx","KEY02.pptx","themes.pptx","backgrounds.pptx","layouts.pptx", "sample.pptx", "shapes.pptx",}; + String[] args = { + "-format", "null", // png,gif,jpg or null for test + "-slide", "-1", // -1 for all + "-outdir", new File("build/tmp/").getCanonicalPath(), + "-quite", + "dummyfile" + }; for(String sampleFile : testFiles){ + args[args.length-1] = samples.getFile(sampleFile).getCanonicalPath(); try { - XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument(sampleFile); - Dimension pg = pptx.getPageSize(); - //int slideNo=1; - for(XSLFSlide slide : pptx.getSlides()){ - BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_ARGB); - Graphics2D graphics = img.createGraphics(); - fixFonts(graphics); - slide.draw(graphics); - // ImageIO.write(img, "PNG", new File("build/tmp/"+sampleFile.replaceFirst(".pptx?", "-")+slideNo+".png")); - //slideNo++; - } + PPTX2PNG.main(args); } catch (IllegalStateException e) { throw new IllegalStateException("While reading file " + sampleFile, e); } } } - - @SuppressWarnings("unchecked") - private void fixFonts(Graphics2D graphics) { - if (!JvmBugs.hasLineBreakMeasurerBug()) return; - Map fontMap = (Map)graphics.getRenderingHint(Drawable.FONT_MAP); - if (fontMap == null) fontMap = new HashMap(); - fontMap.put("Calibri", "Lucida Sans"); - fontMap.put("Cambria", "Lucida Bright"); - graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); - } } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java index 6088eeee7..db2c9833f 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java @@ -16,7 +16,12 @@ ==================================================================== */ package org.apache.poi.xslf.usermodel; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.awt.Color; import java.io.IOException; diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java index 3314855c7..691d9941a 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java @@ -16,9 +16,15 @@ ==================================================================== */ package org.apache.poi.xslf.usermodel; -import static org.junit.Assert.*; +import static org.apache.poi.sl.TestCommonSL.sameColor; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import java.awt.Color; +import java.io.IOException; import java.util.List; import org.apache.poi.xslf.XSLFTestDataSamples; @@ -98,7 +104,7 @@ public class TestXSLFSlide { } @Test - public void testCreateSlide(){ + public void testCreateSlide() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); assertEquals(0, ppt.getSlides().size()); @@ -108,10 +114,12 @@ public class TestXSLFSlide { assertFalse(slide.getFollowMasterGraphics()); slide.setFollowMasterGraphics(true); assertTrue(slide.getFollowMasterGraphics()); + + ppt.close(); } @Test - public void testImportContent(){ + public void testImportContent() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); XMLSlideShow src = XSLFTestDataSamples.openSampleDocument("themes.pptx"); @@ -128,7 +136,7 @@ public class TestXSLFSlide { assertEquals(40.0, r1.getFontSize(), 0); assertTrue(r1.isBold()); assertTrue(r1.isItalic()); - assertEquals(new Color(148, 198, 0), r1.getFontColor()); + assertTrue(sameColor(new Color(148, 198, 0), r1.getFontColor())); assertNull(sh1.getFillColor()); assertNull(sh1.getLineColor()); @@ -141,7 +149,7 @@ public class TestXSLFSlide { assertEquals(18.0, r2.getFontSize(), 0); assertFalse(r2.isBold()); assertFalse(r2.isItalic()); - assertEquals(Color.white, r2.getFontColor()); + assertTrue(sameColor(Color.white, r2.getFontColor())); assertEquals(new Color(148, 198, 0), sh2.getFillColor()); assertEquals(new Color(148, 198, 0), sh2.getLineColor()); // slightly different from PowerPoint! @@ -157,17 +165,19 @@ public class TestXSLFSlide { //assertEquals(32.4.0, r3.getFontSize()); assertTrue(r3.isBold()); assertTrue(r3.isItalic()); - assertEquals(new Color(148, 198, 0), r3.getFontColor()); + assertTrue(sameColor(new Color(148, 198, 0), r3.getFontColor())); assertNull(sh3.getFillColor()); assertNull(sh3.getLineColor()); XSLFPictureShape sh4 = (XSLFPictureShape)shapes2.get(1); XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides().get(4).getShapes().get(1); assertArrayEquals(sh4.getPictureData().getData(), srcPic.getPictureData().getData()); + + ppt.close(); } @Test - public void testMergeSlides(){ + public void testMergeSlides() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); String[] pptx = {"shapes.pptx", "themes.pptx", "layouts.pptx", "backgrounds.pptx"}; @@ -179,5 +189,7 @@ public class TestXSLFSlide { } } assertEquals(30, ppt.getSlides().size()); + + ppt.close(); } } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java index e71cf2419..1ad525011 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java @@ -16,19 +16,24 @@ ==================================================================== */ package org.apache.poi.xslf.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.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -import java.awt.*; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import java.io.IOException; import java.util.List; import org.apache.poi.sl.draw.DrawTextFragment; import org.apache.poi.sl.draw.DrawTextParagraph; import org.apache.poi.sl.usermodel.AutoNumberingScheme; import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; import org.apache.poi.xslf.XSLFTestDataSamples; import org.junit.Assume; import org.junit.Test; @@ -37,7 +42,7 @@ import org.junit.Test; * @author Yegor Kozlov */ public class TestXSLFTextParagraph { - private static POILogger _logger = POILogFactory.getLogger(XSLFTextParagraph.class); + // private static POILogger _logger = POILogFactory.getLogger(XSLFTextParagraph.class); static class DrawTextParagraphProxy extends DrawTextParagraph { DrawTextParagraphProxy(XSLFTextParagraph p) { @@ -58,7 +63,7 @@ public class TestXSLFTextParagraph { } @Test - public void testWrappingWidth() throws Exception { + public void testWrappingWidth() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); XSLFTextShape sh = slide.createAutoShape(); @@ -142,6 +147,8 @@ public class TestXSLFTextParagraph { expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); + + ppt.close(); } /** @@ -149,7 +156,7 @@ public class TestXSLFTextParagraph { * This test requires that the Arial font is available and will run only on windows */ @Test - public void testBreakLines(){ + public void testBreakLines() throws IOException { String os = System.getProperty("os.name"); Assume.assumeTrue("Skipping testBreakLines(), it is executed only on Windows machines", (os != null && os.contains("Windows"))); @@ -237,10 +244,11 @@ public class TestXSLFTextParagraph { // the first line is at least two times higher than the second assertTrue(lines.get(0).getHeight() > lines.get(1).getHeight()*2); + ppt.close(); } @Test - public void testThemeInheritance(){ + public void testThemeInheritance() throws IOException { XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("prProps.pptx"); List shapes = ppt.getSlides().get(0).getShapes(); XSLFTextShape sh1 = (XSLFTextShape)shapes.get(0); @@ -252,10 +260,11 @@ public class TestXSLFTextParagraph { XSLFTextShape sh3 = (XSLFTextShape)shapes.get(2); assertEquals("Foundation", sh3.getText()); assertEquals(TextAlign.CENTER, sh3.getTextParagraphs().get(0).getTextAlign()); + ppt.close(); } @Test - public void testParagraphProperties(){ + public void testParagraphProperties() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); XSLFTextShape sh = slide.createAutoShape(); @@ -275,7 +284,7 @@ public class TestXSLFTextParagraph { assertEquals(null, p.getBulletFontColor()); p.setBulletFontColor(Color.red); - assertEquals(Color.red, p.getBulletFontColor()); + assertTrue(sameColor(Color.red, p.getBulletFontColor())); assertNull(p.getBulletFontSize()); p.setBulletFontSize(200.); @@ -342,34 +351,35 @@ public class TestXSLFTextParagraph { assertEquals(72.0, p.getDefaultTabSize(), 0); + ppt.close(); } - @Test - public void testLineBreak(){ + @Test(expected = IllegalStateException.class) + public void testLineBreak() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); - XSLFSlide slide = ppt.createSlide(); - XSLFTextShape sh = slide.createAutoShape(); - - XSLFTextParagraph p = sh.addNewTextParagraph(); - XSLFTextRun r1 = p.addNewTextRun(); - r1.setText("Hello,"); - XSLFTextRun r2 = p.addLineBreak(); - assertEquals("\n", r2.getRawText()); - r2.setFontSize(10.0); - assertEquals(10.0, r2.getFontSize(), 0); - XSLFTextRun r3 = p.addNewTextRun(); - r3.setText("World!"); - r3.setFontSize(20.0); - XSLFTextRun r4 = p.addLineBreak(); - assertEquals(20.0, r4.getFontSize(), 0); - - assertEquals("Hello,\nWorld!\n",sh.getText()); - try { + XSLFSlide slide = ppt.createSlide(); + XSLFTextShape sh = slide.createAutoShape(); + + XSLFTextParagraph p = sh.addNewTextParagraph(); + XSLFTextRun r1 = p.addNewTextRun(); + r1.setText("Hello,"); + XSLFTextRun r2 = p.addLineBreak(); + assertEquals("\n", r2.getRawText()); + r2.setFontSize(10.0); + assertEquals(10.0, r2.getFontSize(), 0); + XSLFTextRun r3 = p.addNewTextRun(); + r3.setText("World!"); + r3.setFontSize(20.0); + XSLFTextRun r4 = p.addLineBreak(); + assertEquals(20.0, r4.getFontSize(), 0); + + assertEquals("Hello,\nWorld!\n",sh.getText()); + + // "You cannot change text of a line break, it is always '\\n'" r2.setText("aaa"); - fail("Expected IllegalStateException"); - } catch (IllegalStateException e){ - assertEquals("You cannot change text of a line break, it is always '\\n'", e.getMessage()); + } finally { + ppt.close(); } } } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java index eb7553ecc..a3d2c50e8 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextRun.java @@ -18,16 +18,23 @@ */ package org.apache.poi.xslf.usermodel; -import junit.framework.TestCase; +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.assertTrue; -import java.awt.*; +import java.awt.Color; +import java.io.IOException; + +import org.junit.Test; /** * @author Yegor Kozlov */ -public class TestXSLFTextRun extends TestCase { +public class TestXSLFTextRun { - public void testRunProperties(){ + @Test + public void testRunProperties() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); XSLFTextShape sh = slide.createAutoShape(); @@ -35,26 +42,26 @@ public class TestXSLFTextRun extends TestCase { XSLFTextRun r = sh.addNewTextParagraph().addNewTextRun(); assertEquals("en-US", r.getRPr().getLang()); - assertEquals(0., r.getCharacterSpacing()); + assertEquals(0., r.getCharacterSpacing(), 0); r.setCharacterSpacing(3); - assertEquals(3., r.getCharacterSpacing()); + assertEquals(3., r.getCharacterSpacing(), 0); r.setCharacterSpacing(-3); - assertEquals(-3., r.getCharacterSpacing()); + assertEquals(-3., r.getCharacterSpacing(), 0); r.setCharacterSpacing(0); - assertEquals(0., r.getCharacterSpacing()); + assertEquals(0., r.getCharacterSpacing(), 0); assertFalse(r.getRPr().isSetSpc()); - assertEquals(Color.black, r.getFontColor()); + assertTrue(sameColor(Color.black, r.getFontColor())); r.setFontColor(Color.red); - assertEquals(Color.red, r.getFontColor()); + assertTrue(sameColor(Color.red, r.getFontColor())); assertEquals("Calibri", r.getFontFamily()); r.setFontFamily("Arial"); assertEquals("Arial", r.getFontFamily()); - assertEquals(18.0, r.getFontSize()); + assertEquals(18.0, r.getFontSize(), 0); r.setFontSize(13.0); - assertEquals(13.0, r.getFontSize()); + assertEquals(13.0, r.getFontSize(), 0); assertEquals(false, r.isSuperscript()); r.setSuperscript(true); @@ -67,5 +74,7 @@ public class TestXSLFTextRun extends TestCase { assertEquals(true, r.isSubscript()); r.setSubscript(false); assertEquals(false, r.isSubscript()); + + ppt.close(); } } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java index de0d1a36a..e0c4f9dd9 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java @@ -16,16 +16,26 @@ ==================================================================== */ package org.apache.poi.xslf.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.assertFalse; +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.IOException; import java.util.List; import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.xslf.XSLFTestDataSamples; import org.junit.Test; -import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; +import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; @@ -82,7 +92,7 @@ public class TestXSLFTextShape { XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); assertEquals("Calibri", r1.getFontFamily()); assertEquals(44.0, r1.getFontSize(), 0); - assertEquals(Color.black, r1.getFontColor()); + assertTrue(sameColor(Color.black, r1.getFontColor())); XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); CTPlaceholder ph2 = shape2.getCTPlaceholder(); @@ -151,7 +161,7 @@ public class TestXSLFTextShape { XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0); assertEquals("Calibri", r1.getFontFamily()); assertEquals(44.0, r1.getFontSize(), 0); - assertEquals(Color.black, r1.getFontColor()); + assertTrue(sameColor(Color.black, r1.getFontColor())); XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); CTPlaceholder ph2 = shape2.getCTPlaceholder(); @@ -262,7 +272,7 @@ public class TestXSLFTextShape { assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign()); assertEquals("Calibri", r1.getFontFamily()); assertEquals(40.0, r1.getFontSize(), 0); - assertEquals(Color.black, r1.getFontColor()); + assertTrue(sameColor(Color.black, r1.getFontColor())); assertTrue(r1.isBold()); assertFalse(r1.isItalic()); assertFalse(r1.isUnderlined()); @@ -336,7 +346,7 @@ public class TestXSLFTextShape { assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign()); assertEquals("Calibri", r1.getFontFamily()); assertEquals(44.0, r1.getFontSize(), 0); - assertEquals(Color.black, r1.getFontColor()); + assertTrue(sameColor(Color.black, r1.getFontColor())); XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); CTPlaceholder ph2 = shape2.getCTPlaceholder(); @@ -404,7 +414,7 @@ public class TestXSLFTextShape { assertEquals(0, pr5.getParentParagraph().getIndentLevel()); assertEquals("Right", pr5.getRawText()); assertEquals("Calibri", pr5.getFontFamily()); - assertEquals(Color.black, pr5.getFontColor()); + assertTrue(sameColor(Color.black, pr5.getFontColor())); } @SuppressWarnings("unused") @@ -444,7 +454,7 @@ public class TestXSLFTextShape { assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign()); assertEquals("Calibri", r1.getFontFamily()); assertEquals(44.0, r1.getFontSize(), 0); - assertEquals(Color.black, r1.getFontColor()); + assertTrue(sameColor(Color.black, r1.getFontColor())); assertFalse(r1.isBold()); XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); @@ -517,7 +527,7 @@ public class TestXSLFTextShape { assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign()); assertEquals("Calibri", r1.getFontFamily()); assertEquals(20.0, r1.getFontSize(), 0); - assertEquals(Color.black, r1.getFontColor()); + assertTrue(sameColor(Color.black, r1.getFontColor())); assertTrue(r1.isBold()); XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1); @@ -605,7 +615,7 @@ public class TestXSLFTextShape { assertEquals("Calibri", r1.getFontFamily()); assertEquals(12.0, r1.getFontSize(), 0); // TODO calculation of tint is incorrect - assertEquals(new Color(64,64,64), r1.getFontColor()); + assertTrue(sameColor(new Color(64,64,64), r1.getFontColor())); XSLFTextShape dt = (XSLFTextShape)slide.getPlaceholderByType(STPlaceholderType.INT_DT); assertEquals("Friday, October 21, 2011", dt.getText()); @@ -615,7 +625,7 @@ public class TestXSLFTextShape { } @Test - public void testTitleStyles(){ + public void testTitleStyles() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); XSLFSlideMaster master = ppt.getSlideMasters().get(0); @@ -693,10 +703,12 @@ public class TestXSLFTextShape { assertEquals("Calibri", textRun.getFontFamily()); lv5PPr.setAlgn(STTextAlignType.CTR); assertEquals(TextAlign.CENTER, paragraph.getTextAlign()); + + ppt.close(); } @Test - public void testBodyStyles(){ + public void testBodyStyles() throws IOException { XMLSlideShow ppt = new XMLSlideShow(); XSLFSlideMaster master = ppt.getSlideMasters().get(0); @@ -895,7 +907,7 @@ public class TestXSLFTextShape { assertEquals("Calibri", r3.getFontFamily()); lv3PPr.setAlgn(STTextAlignType.CTR); assertEquals(TextAlign.CENTER, p3.getTextAlign()); - + + ppt.close(); } - } \ No newline at end of file diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java index f928124c4..ee95e771d 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTheme.java @@ -16,6 +16,7 @@ ==================================================================== */ package org.apache.poi.xslf.usermodel; +import static org.apache.poi.sl.TestCommonSL.sameColor; import static org.junit.Assert.*; import java.awt.Color; @@ -66,7 +67,7 @@ public class TestXSLFTheme { XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 3"); XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(Color.white, run1.getFontColor()); + assertTrue(sameColor(Color.white, run1.getFontColor())); assertEquals(new Color(79, 129, 189), sh1.getFillColor()); assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill @@ -89,13 +90,13 @@ public class TestXSLFTheme { XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 4"); XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(Color.white, run1.getFontColor()); + assertTrue(sameColor(Color.white, run1.getFontColor())); assertEquals(new Color(148, 198, 0), sh1.getFillColor()); assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 3"); XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(new Color(148, 198, 0), run2.getFontColor()); + assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); assertNull(sh2.getFillColor()); // no fill assertTrue(slide.getSlideLayout().getFollowMasterGraphics()); @@ -107,7 +108,7 @@ public class TestXSLFTheme { XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 1"); XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(new Color(148, 198, 0), run2.getFontColor()); + assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); assertNull(sh2.getFillColor()); // no fill // font size is 40pt and scale factor is 90% assertEquals(36.0, run2.getFontSize(), 0); @@ -119,12 +120,12 @@ public class TestXSLFTheme { XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Subtitle 3"); XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(new Color(66, 66, 66), run1.getFontColor()); + assertTrue(sameColor(new Color(66, 66, 66), run1.getFontColor())); assertNull(sh1.getFillColor()); // no fill XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 2"); XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(new Color(148, 198, 0), run2.getFontColor()); + assertTrue(sameColor(new Color(148, 198, 0), run2.getFontColor())); assertNull(sh2.getFillColor()); // no fill assertFalse(slide.getSlideLayout().getFollowMasterGraphics()); @@ -154,12 +155,12 @@ public class TestXSLFTheme { XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Title 3"); XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(Color.white, run1.getFontColor()); + assertTrue(sameColor(Color.white, run1.getFontColor())); assertNull(sh1.getFillColor()); // no fill XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Subtitle 4"); XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0); - assertEquals(Color.white, run2.getFontColor()); + assertTrue(sameColor(Color.white, run2.getFontColor())); assertNull(sh2.getFillColor()); // no fill } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java index 67b12be8b..c71395980 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java @@ -17,8 +17,14 @@ 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; @@ -27,7 +33,7 @@ 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 { public Line(EscherContainerRecord escherRecord, ShapeContainer parent){ super(escherRecord, parent); } @@ -64,23 +70,23 @@ public final class Line extends HSLFSimpleShape { 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); +// } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java index 3b22227b9..02cb9154f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java @@ -18,19 +18,49 @@ 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; @@ -259,7 +289,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable { 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); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java index 77cb18e21..e0b056714 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java @@ -22,10 +22,16 @@ import java.io.ByteArrayInputStream; 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; @@ -113,20 +119,8 @@ public final class HSLFFill { 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; @@ -149,7 +143,7 @@ public final class HSLFFill { logger.log(POILogger.WARN, "unsuported fill type: " + getFillType()); break; } - return PaintStyle.TRANSPARENT_PAINT; + return null; } }; } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java index 8feee2312..bbffdc5e1 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java @@ -188,16 +188,14 @@ public final class HSLFSlide extends HSLFSheet implements Slidenull if the slide does not have title. *

* The title is a run of text of type TextHeaderAtom.CENTER_TITLE_TYPE or * TextHeaderAtom.TITLE_TYPE *

* * @see TextHeaderAtom - * - * @return title of this slide */ + @Override public String getTitle(){ for (List tp : getTextParagraphs()) { if (tp.isEmpty()) continue; diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java index 9f4d31198..86604bf09 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java @@ -132,6 +132,20 @@ public final class HSLFSlideShow implements SlideShow { 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 diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java index 0dc8de65f..529d73316 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java @@ -27,7 +27,10 @@ import org.apache.poi.hslf.model.PPFont; import org.apache.poi.hslf.model.textproperties.*; import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType; import org.apache.poi.hslf.record.*; +import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.usermodel.AutoNumberingScheme; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.TextParagraph; import org.apache.poi.util.*; @@ -403,8 +406,24 @@ public final class HSLFTextParagraph implements TextParagraph { } @Override - public Color getBulletFontColor() { - return HSLFTextParagraph.this.getBulletColor(); + public void setBulletFontColor(Color color) { + setBulletFontColor(DrawPaint.createSolidPaint(color)); + } + + @Override + public void setBulletFontColor(PaintStyle color) { + if (!(color instanceof SolidPaint)) { + throw new IllegalArgumentException("HSLF only supports SolidPaint"); + } + SolidPaint sp = (SolidPaint)color; + Color col = DrawPaint.applyColorTransform(sp.getSolidColor()); + HSLFTextParagraph.this.setBulletColor(col); + } + + @Override + public PaintStyle getBulletFontColor() { + Color col = HSLFTextParagraph.this.getBulletColor(); + return DrawPaint.createSolidPaint(col); } @Override @@ -497,7 +516,9 @@ public final class HSLFTextParagraph implements TextParagraph { TextProp tp = getPropVal(_paragraphStyle, "bullet.color", this); if (tp == null) { // if bullet color is undefined, return color of first run - return (_runs.isEmpty()) ? null : _runs.get(0).getFontColor(); + if (_runs.isEmpty()) return null; + SolidPaint sp = _runs.get(0).getFontColor(); + return DrawPaint.applyColorTransform(sp.getSolidColor()); } return getColorFromColorIndexStruct(tp.getValue(), _sheet); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java index 08565e3da..fbb908c1c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java @@ -21,8 +21,14 @@ import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.getPropVal; 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; @@ -315,13 +321,15 @@ public final class HSLFTextRun implements TextRun { } /** - * @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; } /** @@ -334,12 +342,21 @@ public final class HSLFTextRun implements TextRun { 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); } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java index ed9ca3819..8141650fe 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java @@ -17,6 +17,7 @@ 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; @@ -53,9 +54,9 @@ import org.apache.poi.hslf.usermodel.HSLFTextBox; 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; @@ -189,16 +190,16 @@ public final class TestShapes { List 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()); } @@ -235,7 +236,7 @@ public final class TestShapes { 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(); @@ -255,7 +256,7 @@ public final class TestShapes { assertTrue(rt.isItalic()); assertFalse(rt.isUnderlined()); assertEquals("Arial", rt.getFontFamily()); - assertEquals(Color.red, rt.getFontColor()); + assertTrue(sameColor(Color.red, rt.getFontColor())); } /** diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java index aa0c307f9..1cbf238de 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java @@ -17,15 +17,26 @@ 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; @@ -539,7 +550,7 @@ public final class TestTextRun { List 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())); } } } diff --git a/src/testcases/org/apache/poi/sl/TestCommonSL.java b/src/testcases/org/apache/poi/sl/TestCommonSL.java new file mode 100644 index 000000000..ab27ca42e --- /dev/null +++ b/src/testcases/org/apache/poi/sl/TestCommonSL.java @@ -0,0 +1,38 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.sl; + +import java.awt.Color; + +import org.apache.poi.sl.draw.DrawPaint; +import org.apache.poi.sl.usermodel.PaintStyle; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.junit.Ignore; + +/** + * Currently only contains helper methods + */ +@Ignore +public class TestCommonSL { + + public static boolean sameColor(Color colorExpected, PaintStyle paintActual) { + if (!(paintActual instanceof SolidPaint)) return false; + Color thisC = DrawPaint.applyColorTransform(((SolidPaint)paintActual).getSolidColor()); + return thisC.equals(colorExpected); + } + +} diff --git a/test-data/slideshow/KEY02.pptx b/test-data/slideshow/KEY02.pptx new file mode 100644 index 000000000..142c6dd27 Binary files /dev/null and b/test-data/slideshow/KEY02.pptx differ diff --git a/test-data/slideshow/alterman_security.pptx b/test-data/slideshow/alterman_security.pptx new file mode 100644 index 000000000..e9869b9c2 Binary files /dev/null and b/test-data/slideshow/alterman_security.pptx differ diff --git a/test-data/slideshow/alterman_security2.pptx b/test-data/slideshow/alterman_security2.pptx deleted file mode 100644 index 132922864..000000000 Binary files a/test-data/slideshow/alterman_security2.pptx and /dev/null differ