diff --git a/src/java/org/apache/poi/ddf/EscherProperties.java b/src/java/org/apache/poi/ddf/EscherProperties.java index 7e52fea44e..096a20c574 100644 --- a/src/java/org/apache/poi/ddf/EscherProperties.java +++ b/src/java/org/apache/poi/ddf/EscherProperties.java @@ -186,6 +186,10 @@ public final class EscherProperties { public static final short LINESTYLE__HITLINETEST = 509; public static final short LINESTYLE__LINEFILLSHAPE = 510; public static final short LINESTYLE__NOLINEDRAWDASH = 511; + public static final short LINESTYLE__NOLINEDRAWDASH_LEFT = 0x057F; + public static final short LINESTYLE__NOLINEDRAWDASH_TOP = 0x05BF; + public static final short LINESTYLE__NOLINEDRAWDASH_BOTTOM = 0x063F; + public static final short LINESTYLE__NOLINEDRAWDASH_RIGHT = 0x05FF; public static final short SHADOWSTYLE__TYPE = 512; public static final short SHADOWSTYLE__COLOR = 513; public static final short SHADOWSTYLE__HIGHLIGHT = 514; @@ -488,6 +492,10 @@ public final class EscherProperties { addProp(m, LINESTYLE__HITLINETEST, "linestyle.hitlinetest"); addProp(m, LINESTYLE__LINEFILLSHAPE, "linestyle.linefillshape"); addProp(m, LINESTYLE__NOLINEDRAWDASH, "linestyle.nolinedrawdash", EscherPropertyMetaData.TYPE_BOOLEAN); + addProp(m, LINESTYLE__NOLINEDRAWDASH_LEFT, "linestyle.nolinedrawdash.left", EscherPropertyMetaData.TYPE_BOOLEAN); + addProp(m, LINESTYLE__NOLINEDRAWDASH_TOP, "linestyle.nolinedrawdash.top", EscherPropertyMetaData.TYPE_BOOLEAN); + addProp(m, LINESTYLE__NOLINEDRAWDASH_BOTTOM, "linestyle.nolinedrawdash.bottom", EscherPropertyMetaData.TYPE_BOOLEAN); + addProp(m, LINESTYLE__NOLINEDRAWDASH_RIGHT, "linestyle.nolinedrawdash.right", EscherPropertyMetaData.TYPE_BOOLEAN); addProp(m, SHADOWSTYLE__TYPE, "shadowstyle.type"); addProp(m, SHADOWSTYLE__COLOR, "shadowstyle.color", EscherPropertyMetaData.TYPE_RGB); addProp(m, SHADOWSTYLE__HIGHLIGHT, "shadowstyle.highlight"); diff --git a/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java b/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java new file mode 100644 index 0000000000..5099246e60 --- /dev/null +++ b/src/java/org/apache/poi/sl/draw/BitmapImageRenderer.java @@ -0,0 +1,142 @@ +/* ==================================================================== + 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.draw; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.RescaleOp; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * For now this class renders only images supported by the javax.imageio.ImageIO framework. + **/ +public class BitmapImageRenderer implements ImageRenderer { + private final static POILogger LOG = POILogFactory.getLogger(ImageRenderer.class); + + protected BufferedImage img; + + @Override + public void loadImage(InputStream data, String contentType) throws IOException { + img = convertBufferedImage(ImageIO.read(data), contentType); + } + + @Override + public void loadImage(byte data[], String contentType) throws IOException { + img = convertBufferedImage(ImageIO.read(new ByteArrayInputStream(data)), contentType); + } + + /** + * Add alpha channel to buffered image + */ + private static BufferedImage convertBufferedImage(BufferedImage img, String contentType) { + if (img == null) { + LOG.log(POILogger.WARN, "Content-type: "+contentType+" is not support. Image ignored."); + return null; + } + + BufferedImage bi = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics g = bi.getGraphics(); + g.drawImage(img, 0, 0, null); + g.dispose(); + return bi; + } + + + /** + * @return the buffered image + */ + public BufferedImage getImage() { + return img; + } + + @Override + public Dimension getDimension() { + return (img == null) + ? new Dimension(0,0) + : new Dimension(img.getWidth(),img.getHeight()); + } + + @Override + public void setAlpha(double alpha) { + if (img == null) return; + + Dimension dim = getDimension(); + BufferedImage newImg = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g = newImg.createGraphics(); + RescaleOp op = new RescaleOp(new float[]{1.0f, 1.0f, 1.0f, (float)alpha}, new float[]{0,0,0,0}, null); + g.drawImage(img, op, 0, 0); + g.dispose(); + + img = newImg; + } + + + @Override + public boolean drawImage( + Graphics2D graphics, + Rectangle2D anchor) { + return drawImage(graphics, anchor, null); + } + + @Override + public boolean drawImage( + Graphics2D graphics, + Rectangle2D anchor, + Insets clip) { + if (img == null) return false; + + boolean isClipped = true; + if (clip == null) { + isClipped = false; + clip = new Insets(0,0,0,0); + } + + int iw = img.getWidth(); + int ih = img.getHeight(); + + + double cw = (100000-clip.left-clip.right) / 100000.0; + double ch = (100000-clip.top-clip.bottom) / 100000.0; + double sx = anchor.getWidth()/(iw*cw); + double sy = anchor.getHeight()/(ih*ch); + double tx = anchor.getX()-(iw*sx*clip.left/100000.0); + double ty = anchor.getY()-(ih*sy*clip.top/100000.0); + + AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ; + + Shape clipOld = graphics.getClip(); + if (isClipped) graphics.clip(anchor.getBounds2D()); + graphics.drawRenderedImage(img, at); + graphics.setClip(clipOld); + + return true; + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawFactory.java b/src/java/org/apache/poi/sl/draw/DrawFactory.java index 19d3476470..971feae185 100644 --- a/src/java/org/apache/poi/sl/draw/DrawFactory.java +++ b/src/java/org/apache/poi/sl/draw/DrawFactory.java @@ -26,6 +26,7 @@ import java.text.AttributedString; import org.apache.poi.sl.usermodel.Background; import org.apache.poi.sl.usermodel.ConnectorShape; import org.apache.poi.sl.usermodel.FreeformShape; +import org.apache.poi.sl.usermodel.GraphicalFrame; import org.apache.poi.sl.usermodel.GroupShape; import org.apache.poi.sl.usermodel.MasterSheet; import org.apache.poi.sl.usermodel.PictureShape; @@ -87,6 +88,8 @@ public class DrawFactory { return getDrawable((GroupShape,?>)shape); } else if (shape instanceof PictureShape) { return getDrawable((PictureShape,?>)shape); + } else if (shape instanceof GraphicalFrame) { + return getDrawable((GraphicalFrame,?>)shape); } else if (shape instanceof Background) { return getDrawable((Background,?>)shape); } else if (shape instanceof ConnectorShape) { @@ -144,6 +147,10 @@ public class DrawFactory { return new DrawPictureShape(shape); } + public DrawGraphicalFrame getDrawable(GraphicalFrame,?> shape) { + return new DrawGraphicalFrame(shape); + } + public DrawTextParagraph getDrawable(TextParagraph,?,?> paragraph) { return new DrawTextParagraph(paragraph); } diff --git a/src/java/org/apache/poi/sl/draw/DrawGraphicalFrame.java b/src/java/org/apache/poi/sl/draw/DrawGraphicalFrame.java new file mode 100644 index 0000000000..c4b75f19d7 --- /dev/null +++ b/src/java/org/apache/poi/sl/draw/DrawGraphicalFrame.java @@ -0,0 +1,40 @@ +/* ==================================================================== + 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.draw; + +import java.awt.Graphics2D; + +import org.apache.poi.sl.usermodel.GraphicalFrame; +import org.apache.poi.sl.usermodel.PictureShape; + + +public class DrawGraphicalFrame extends DrawShape { + + public DrawGraphicalFrame(GraphicalFrame,?> shape) { + super(shape); + } + + public void draw(Graphics2D context) { + PictureShape,?> ps = ((GraphicalFrame,?>)getShape()).getFallbackPicture(); + if (ps == null) { + return; + } + DrawPictureShape dps = DrawFactory.getInstance(context).getDrawable(ps); + dps.draw(context); + } +} diff --git a/src/java/org/apache/poi/sl/draw/DrawPaint.java b/src/java/org/apache/poi/sl/draw/DrawPaint.java index 7aed90811f..94001fd88c 100644 --- a/src/java/org/apache/poi/sl/draw/DrawPaint.java +++ b/src/java/org/apache/poi/sl/draw/DrawPaint.java @@ -130,8 +130,7 @@ public class DrawPaint { if (is == null) return null; assert(graphics != null); - ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER); - if (renderer == null) renderer = new ImageRenderer(); + ImageRenderer renderer = DrawPictureShape.getImageRenderer(graphics, fill.getContentType()); try { renderer.loadImage(is, fill.getContentType()); diff --git a/src/java/org/apache/poi/sl/draw/DrawPictureShape.java b/src/java/org/apache/poi/sl/draw/DrawPictureShape.java index 5976dbeaef..9721660580 100644 --- a/src/java/org/apache/poi/sl/draw/DrawPictureShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawPictureShape.java @@ -24,11 +24,17 @@ import java.awt.geom.Rectangle2D; import java.io.IOException; import org.apache.poi.sl.usermodel.PictureData; +import org.apache.poi.sl.usermodel.PictureData.PictureType; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; import org.apache.poi.sl.usermodel.PictureShape; import org.apache.poi.sl.usermodel.RectAlign; public class DrawPictureShape extends DrawSimpleShape { + private static final POILogger LOG = POILogFactory.getLogger(DrawPictureShape.class); + private static final String WMF_IMAGE_RENDERER = "org.apache.poi.hwmf.draw.HwmfSLImageRenderer"; + public DrawPictureShape(PictureShape,?> shape) { super(shape); } @@ -38,14 +44,11 @@ public class DrawPictureShape extends DrawSimpleShape { PictureData data = getShape().getPictureData(); if(data == null) return; - ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER); - if (renderer == null) renderer = new ImageRenderer(); - Rectangle2D anchor = getAnchor(graphics, getShape()); - Insets insets = getShape().getClipping(); try { + ImageRenderer renderer = getImageRenderer(graphics, data.getContentType()); renderer.loadImage(data.getData(), data.getContentType()); renderer.drawImage(graphics, anchor, insets); } catch (IOException e) { @@ -54,6 +57,34 @@ public class DrawPictureShape extends DrawSimpleShape { } } + /** + * Returns an ImageRenderer for the PictureData + * + * @param graphics + * @return + */ + public static ImageRenderer getImageRenderer(Graphics2D graphics, String contentType) { + ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER); + if (renderer != null) { + return renderer; + } + + if (PictureType.WMF.contentType.equals(contentType)) { + try { + @SuppressWarnings("unchecked") + Class extends ImageRenderer> irc = (Class extends ImageRenderer>) + Thread.currentThread().getContextClassLoader().loadClass(WMF_IMAGE_RENDERER); + return irc.newInstance(); + } catch (Exception e) { + // WMF image renderer is not on the classpath, continuing with BitmapRenderer + // although this doesn't make much sense ... + LOG.log(POILogger.ERROR, "WMF image renderer is not on the classpath - include poi-scratchpad jar!", e); + } + } + + return new BitmapImageRenderer(); + } + @Override protected PictureShape,?> getShape() { return (PictureShape,?>)shape; diff --git a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java index cdc665a617..aa03f8a53b 100644 --- a/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java +++ b/src/java/org/apache/poi/sl/draw/DrawSimpleShape.java @@ -98,6 +98,7 @@ public class DrawSimpleShape extends DrawShape { // then stroke the shape outline if(line != null) { graphics.setPaint(line); + graphics.setStroke(stroke); for(Outline o : elems){ if(o.getPath().isStroked()){ java.awt.Shape s = o.getOutline(); diff --git a/src/java/org/apache/poi/sl/draw/ImageRenderer.java b/src/java/org/apache/poi/sl/draw/ImageRenderer.java index ae8eccf98b..fed5d078cc 100644 --- a/src/java/org/apache/poi/sl/draw/ImageRenderer.java +++ b/src/java/org/apache/poi/sl/draw/ImageRenderer.java @@ -31,13 +31,12 @@ import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; /** - * For now this class renders only images supported by the javax.imageio.ImageIO - * framework. Subclasses can override this class to support other formats, for + * Classes can implement this interfaces to support other formats, for * example, use Apache Batik to render WMF, PICT can be rendered using Apple QuickTime API for Java: * *
*
- * public class MyImageRendener extends ImageRendener {
+ * public class MyImageRendener implements ImageRendener {
* InputStream data;
*
* public boolean drawImage(Graphics2D graphics,Rectangle2D anchor,Insets clip) {
@@ -79,127 +78,49 @@ import org.apache.poi.util.POILogger;
*
*
*/
-public class ImageRenderer {
- private final static POILogger LOG = POILogFactory.getLogger(ImageRenderer.class);
-
- protected BufferedImage img;
-
+public interface ImageRenderer {
/**
* Load and buffer the image
*
* @param data the raw image stream
* @param contentType the content type
*/
- public void loadImage(InputStream data, String contentType) throws IOException {
- img = convertBufferedImage(ImageIO.read(data), contentType);
- }
+ void loadImage(InputStream data, String contentType) throws IOException;
/**
* Load and buffer the image
*
- * @param data the raw image stream
+ * @param data the raw image bytes
* @param contentType the content type
*/
- public void loadImage(byte data[], String contentType) throws IOException {
- img = convertBufferedImage(ImageIO.read(new ByteArrayInputStream(data)), contentType);
- }
-
- /**
- * Add alpha channel to buffered image
- */
- private static BufferedImage convertBufferedImage(BufferedImage img, String contentType) {
- if (img == null) {
- LOG.log(POILogger.WARN, "Content-type: "+contentType+" is not support. Image ignored.");
- return null;
- }
-
- BufferedImage bi = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
- Graphics g = bi.getGraphics();
- g.drawImage(img, 0, 0, null);
- g.dispose();
- return bi;
- }
-
-
- /**
- * @return the buffered image
- */
- public BufferedImage getImage() {
- return img;
- }
+ void loadImage(byte data[], String contentType) throws IOException;
/**
* @return the dimension of the buffered image
*/
- public Dimension getDimension() {
- return (img == null)
- ? new Dimension(0,0)
- : new Dimension(img.getWidth(),img.getHeight());
- }
+ Dimension getDimension();
/**
* @param alpha the alpha [0..1] to be added to the image (possibly already containing an alpha channel)
*/
- public void setAlpha(double alpha) {
- if (img == null) return;
-
- Dimension dim = getDimension();
- BufferedImage newImg = new BufferedImage((int)dim.getWidth(), (int)dim.getHeight(), BufferedImage.TYPE_INT_ARGB);
- Graphics2D g = newImg.createGraphics();
- RescaleOp op = new RescaleOp(new float[]{1.0f, 1.0f, 1.0f, (float)alpha}, new float[]{0,0,0,0}, null);
- g.drawImage(img, op, 0, 0);
- g.dispose();
-
- img = newImg;
- }
+ void setAlpha(double alpha);
+ /**
+ * @return the image as buffered image
+ */
+ BufferedImage getImage();
+
+ /**
+ * Render picture data into the supplied graphics
+ *
+ * @return true if the picture data was successfully rendered
+ */
+ boolean drawImage(Graphics2D graphics, Rectangle2D anchor);
/**
* Render picture data into the supplied graphics
*
* @return true if the picture data was successfully rendered
*/
- public boolean drawImage(
- Graphics2D graphics,
- Rectangle2D anchor) {
- return drawImage(graphics, anchor, null);
- }
-
- /**
- * Render picture data into the supplied graphics
- *
- * @return true if the picture data was successfully rendered
- */
- public boolean drawImage(
- Graphics2D graphics,
- Rectangle2D anchor,
- Insets clip) {
- if (img == null) return false;
-
- boolean isClipped = true;
- if (clip == null) {
- isClipped = false;
- clip = new Insets(0,0,0,0);
- }
-
- int iw = img.getWidth();
- int ih = img.getHeight();
-
-
- double cw = (100000-clip.left-clip.right) / 100000.0;
- double ch = (100000-clip.top-clip.bottom) / 100000.0;
- double sx = anchor.getWidth()/(iw*cw);
- double sy = anchor.getHeight()/(ih*ch);
- double tx = anchor.getX()-(iw*sx*clip.left/100000.0);
- double ty = anchor.getY()-(ih*sy*clip.top/100000.0);
-
- AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ;
-
- Shape clipOld = graphics.getClip();
- if (isClipped) graphics.clip(anchor.getBounds2D());
- graphics.drawRenderedImage(img, at);
- graphics.setClip(clipOld);
-
- return true;
- }
-}
+ boolean drawImage(Graphics2D graphics, Rectangle2D anchor, Insets clip);
+}
\ No newline at end of file
diff --git a/src/java/org/apache/poi/sl/usermodel/GraphicalFrame.java b/src/java/org/apache/poi/sl/usermodel/GraphicalFrame.java
new file mode 100644
index 0000000000..20621efedf
--- /dev/null
+++ b/src/java/org/apache/poi/sl/usermodel/GraphicalFrame.java
@@ -0,0 +1,29 @@
+/* ====================================================================
+ 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.usermodel;
+
+public interface GraphicalFrame<
+ S extends Shape