| /* ==================================================================== |
| 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.hssf.usermodel; |
| |
| import org.apache.poi.util.POILogFactory; |
| import org.apache.poi.util.POILogger; |
| |
| import java.awt.*; |
| import java.awt.font.FontRenderContext; |
| import java.awt.font.GlyphVector; |
| import java.awt.font.TextLayout; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.Area; |
| import java.awt.geom.GeneralPath; |
| import java.awt.geom.Line2D; |
| 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; |
| |
| /** |
| * Translates Graphics2d calls into escher calls. The translation is lossy so |
| * many features are not supported and some just aren't implemented yet. If |
| * in doubt test the specific calls you wish to make. Graphics calls are |
| * always drawn into an EscherGroup so one will need to be created. |
| * <p> |
| * <b>Important:</b> |
| * <blockquote> |
| * One important concept worth considering is that of font size. One of the |
| * difficulties in converting Graphics calls into escher drawing calls is that |
| * Excel does not have the concept of absolute pixel positions. It measures |
| * it's cell widths in 'characters' and the cell heights in points. |
| * Unfortunately it's not defined exactly what a type of character it's |
| * measuring. Presumably this is due to the fact that the Excel will be |
| * using different fonts on different platforms or even within the same |
| * platform. |
| * <p> |
| * Because of this constraint you have to calculate the verticalPointsPerPixel. |
| * This the amount the font should be scaled by when |
| * you issue commands such as drawString(). A good way to calculate this |
| * is to use the follow formula: |
| * <p> |
| * <pre> |
| * multipler = groupHeightInPoints / heightOfGroup |
| * </pre> |
| * <p> |
| * The height of the group is calculated fairly simply by calculating the |
| * difference between the y coordinates of the bounding box of the shape. The |
| * height of the group can be calculated by using a convenience called |
| * <code>HSSFClientAnchor.getAnchorHeightInPoints()</code>. |
| * </blockquote> |
| */ |
| public final class EscherGraphics2d extends Graphics2D { |
| private EscherGraphics _escherGraphics; |
| private BufferedImage _img; |
| private AffineTransform _trans; |
| private Stroke _stroke; |
| private Paint _paint; |
| private Shape _deviceclip; |
| private POILogger logger = POILogFactory.getLogger(getClass()); |
| |
| /** |
| * Constructs one escher graphics object from an escher graphics object. |
| * |
| * @param escherGraphics the original EscherGraphics2d object to copy |
| */ |
| public EscherGraphics2d(EscherGraphics escherGraphics) |
| { |
| this._escherGraphics = escherGraphics; |
| setImg( new BufferedImage(1, 1, 2) ); |
| setColor(Color.black); |
| } |
| |
| public void addRenderingHints(Map<?, ?> map) |
| { |
| getG2D().addRenderingHints(map); |
| } |
| |
| public void clearRect(int i, int j, int k, int l) |
| { |
| Paint paint1 = getPaint(); |
| setColor(getBackground()); |
| fillRect(i, j, k, l); |
| setPaint(paint1); |
| } |
| |
| public void clip(Shape shape) |
| { |
| if(getDeviceclip() != null) |
| { |
| Area area = new Area(getClip()); |
| if(shape != null) |
| area.intersect(new Area(shape)); |
| shape = area; |
| } |
| setClip(shape); |
| } |
| |
| public void clipRect(int x, int y, int width, int height) |
| { |
| clip(new Rectangle(x,y,width,height)); |
| } |
| |
| public void copyArea(int x, int y, int width, int height, |
| int dx, int dy) |
| { |
| getG2D().copyArea(x,y,width,height,dx,dy); |
| } |
| |
| public Graphics create() |
| { |
| EscherGraphics2d g2d = new EscherGraphics2d(_escherGraphics); |
| return g2d; |
| } |
| |
| public void dispose() |
| { |
| getEscherGraphics().dispose(); |
| getG2D().dispose(); |
| getImg().flush(); |
| } |
| |
| public void draw(Shape shape) |
| { |
| if (shape instanceof Line2D) |
| { |
| Line2D shape2d = (Line2D) shape; |
| |
| int width = 0; |
| if (_stroke != null && _stroke instanceof BasicStroke) { |
| width = (int) ((BasicStroke)_stroke).getLineWidth() * 12700; |
| } |
| |
| drawLine((int)shape2d.getX1(), (int)shape2d.getY1(), (int)shape2d.getX2(), (int)shape2d.getY2(), width); |
| } |
| else |
| { |
| if (logger.check(POILogger.WARN)) |
| logger.log(POILogger.WARN, "draw not fully supported"); |
| } |
| } |
| |
| public void drawArc(int x, int y, int width, int height, |
| int startAngle, int arcAngle) |
| { |
| draw(new java.awt.geom.Arc2D.Float(x, y, width, height, startAngle, arcAngle, 0)); |
| } |
| |
| public void drawGlyphVector(GlyphVector g, float x, float y) |
| { |
| fill(g.getOutline(x, y)); |
| } |
| |
| public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, |
| int sx2, int sy2, Color bgColor, ImageObserver imageobserver) |
| { |
| if (logger.check( POILogger.WARN )) |
| logger.log(POILogger.WARN,"drawImage() not supported"); |
| return true; |
| } |
| |
| public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, |
| int sx2, int sy2, ImageObserver imageobserver) |
| { |
| if (logger.check( POILogger.WARN )) |
| logger.log(POILogger.WARN,"drawImage() not supported"); |
| return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, imageobserver); |
| } |
| public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2, Color bgColor, ImageObserver imageobserver) |
| { |
| if (logger.check( POILogger.WARN )) |
| logger.log(POILogger.WARN,"drawImage() not supported"); |
| return true; |
| } |
| |
| public boolean drawImage(Image img, int x, int y, |
| int width, int height, |
| ImageObserver observer) |
| { |
| return drawImage(img, x,y,width,height, null, observer); |
| } |
| |
| public boolean drawImage(Image image, int x, int y, Color bgColor, ImageObserver imageobserver) |
| { |
| return drawImage(image, x, y, image.getWidth(imageobserver), image.getHeight(imageobserver), bgColor, imageobserver); |
| } |
| |
| public boolean drawImage(Image image, int x, int y, ImageObserver imageobserver) |
| { |
| return drawImage(image, x, y, image.getWidth(imageobserver), image.getHeight(imageobserver), imageobserver); |
| } |
| |
| public boolean drawImage(Image image, AffineTransform affinetransform, ImageObserver imageobserver) |
| { |
| AffineTransform affinetransform1 = (AffineTransform)getTrans().clone(); |
| getTrans().concatenate(affinetransform); |
| drawImage(image, 0, 0, imageobserver); |
| setTrans( affinetransform1 ); |
| return true; |
| } |
| |
| public void drawImage(BufferedImage bufferedimage, BufferedImageOp op, int x, int y) |
| { |
| BufferedImage img = op.filter(bufferedimage, null); |
| drawImage(img, new AffineTransform(1.0F, 0.0F, 0.0F, 1.0F, x, y), null); |
| } |
| |
| public void drawLine(int x1, int y1, int x2, int y2, int width) |
| { |
| getEscherGraphics().drawLine(x1,y1,x2,y2, width); |
| } |
| |
| public void drawLine(int x1, int y1, int x2, int y2) |
| { |
| int width = 0; |
| if (_stroke != null && _stroke instanceof BasicStroke) { |
| width = (int) ((BasicStroke)_stroke).getLineWidth() * 12700; |
| } |
| getEscherGraphics().drawLine(x1,y1,x2,y2, width); |
| // draw(new GeneralPath(new java.awt.geom.Line2D.Float(x1, y1, x2, y2))); |
| } |
| |
| public void drawOval(int x, int y, int width, int height) |
| { |
| getEscherGraphics().drawOval(x,y,width,height); |
| // draw(new java.awt.geom.Ellipse2D.Float(x, y, width, height)); |
| } |
| |
| public void drawPolygon(int xPoints[], int yPoints[], |
| int nPoints) |
| { |
| getEscherGraphics().drawPolygon(xPoints, yPoints, nPoints); |
| } |
| |
| public void drawPolyline(int xPoints[], int yPoints[], int nPoints) |
| { |
| if(nPoints > 0) |
| { |
| GeneralPath generalpath = new GeneralPath(); |
| generalpath.moveTo(xPoints[0], yPoints[0]); |
| for(int j = 1; j < nPoints; j++) |
| generalpath.lineTo(xPoints[j], yPoints[j]); |
| |
| draw(generalpath); |
| } |
| } |
| |
| public void drawRect(int x, int y, int width, int height) |
| { |
| _escherGraphics.drawRect(x,y,width,height); |
| } |
| |
| public void drawRenderableImage(RenderableImage renderableimage, AffineTransform affinetransform) |
| { |
| drawRenderedImage(renderableimage.createDefaultRendering(), affinetransform); |
| } |
| |
| public void drawRenderedImage(RenderedImage renderedimage, AffineTransform affinetransform) |
| { |
| BufferedImage bufferedimage = new BufferedImage(renderedimage.getColorModel(), renderedimage.getData().createCompatibleWritableRaster(), false, null); |
| bufferedimage.setData(renderedimage.getData()); |
| drawImage(bufferedimage, affinetransform, null); |
| } |
| |
| public void drawRoundRect(int i, int j, int k, int l, int i1, int j1) |
| { |
| draw(new java.awt.geom.RoundRectangle2D.Float(i, j, k, l, i1, j1)); |
| } |
| |
| public void drawString(String string, float x, float y) |
| { |
| getEscherGraphics().drawString(string, (int)x, (int)y); |
| } |
| |
| public void drawString(String string, int x, int y) |
| { |
| getEscherGraphics().drawString(string, x, y); |
| } |
| |
| public void drawString(AttributedCharacterIterator attributedcharacteriterator, float x, float y) |
| { |
| TextLayout textlayout = new TextLayout(attributedcharacteriterator, getFontRenderContext()); |
| Paint paint1 = getPaint(); |
| setColor(getColor()); |
| fill(textlayout.getOutline(AffineTransform.getTranslateInstance(x, y))); |
| setPaint(paint1); |
| } |
| |
| public void drawString(AttributedCharacterIterator attributedcharacteriterator, int x, int y) |
| { |
| getEscherGraphics().drawString(attributedcharacteriterator, x, y); |
| } |
| |
| public void fill(Shape shape) |
| { |
| if (logger.check( POILogger.WARN )) |
| logger.log(POILogger.WARN,"fill(Shape) not supported"); |
| } |
| |
| public void fillArc(int i, int j, int k, int l, int i1, int j1) |
| { |
| fill(new java.awt.geom.Arc2D.Float(i, j, k, l, i1, j1, 2)); |
| } |
| |
| public void fillOval(int x, int y, int width, int height) |
| { |
| _escherGraphics.fillOval(x,y,width,height); |
| } |
| |
| /** |
| * Fills a (closed) polygon, as defined by a pair of arrays, which |
| * hold the <i>x</i> and <i>y</i> coordinates. |
| * <p> |
| * This draws the polygon, with <code>nPoint</code> line segments. |
| * The first <code>nPoint - 1</code> line segments are |
| * drawn between sequential points |
| * (<code>xPoints[i],yPoints[i],xPoints[i+1],yPoints[i+1]</code>). |
| * The final line segment is a closing one, from the last point to |
| * the first (assuming they are different). |
| * <p> |
| * The area inside of the polygon is defined by using an |
| * even-odd fill rule (also known as the alternating rule), and |
| * the area inside of it is filled. |
| * @param xPoints array of the <code>x</code> coordinates. |
| * @param yPoints array of the <code>y</code> coordinates. |
| * @param nPoints the total number of points in the polygon. |
| * @see java.awt.Graphics#drawPolygon(int[], int[], int) |
| */ |
| public void fillPolygon(int xPoints[], int yPoints[], int nPoints) |
| { |
| _escherGraphics.fillPolygon(xPoints, yPoints, nPoints); |
| } |
| |
| public void fillRect(int x, int y, int width, int height) |
| { |
| getEscherGraphics().fillRect(x,y,width,height); |
| } |
| |
| public void fillRoundRect(int x, int y, int width, int height, |
| int arcWidth, int arcHeight) |
| { |
| fill(new java.awt.geom.RoundRectangle2D.Float(x, y, width, height, arcWidth, arcHeight)); |
| } |
| |
| public Color getBackground() |
| { |
| return getEscherGraphics().getBackground(); |
| } |
| |
| public Shape getClip() |
| { |
| try |
| { |
| return getTrans().createInverse().createTransformedShape(getDeviceclip()); |
| } |
| catch(Exception _ex) |
| { |
| return null; |
| } |
| } |
| |
| public Rectangle getClipBounds() |
| { |
| if(getDeviceclip() != null) { |
| return getClip().getBounds(); |
| } |
| return null; |
| } |
| |
| public Color getColor() |
| { |
| return _escherGraphics.getColor(); |
| } |
| |
| public Composite getComposite() |
| { |
| return getG2D().getComposite(); |
| } |
| |
| public GraphicsConfiguration getDeviceConfiguration() |
| { |
| return getG2D().getDeviceConfiguration(); |
| } |
| |
| public Font getFont() |
| { |
| return getEscherGraphics().getFont(); |
| } |
| |
| public FontMetrics getFontMetrics(Font font) |
| { |
| return getEscherGraphics().getFontMetrics(font); |
| } |
| |
| public FontRenderContext getFontRenderContext() |
| { |
| getG2D().setTransform(getTrans()); |
| return getG2D().getFontRenderContext(); |
| } |
| |
| public Paint getPaint() |
| { |
| return _paint; |
| } |
| |
| public Object getRenderingHint(java.awt.RenderingHints.Key key) |
| { |
| return getG2D().getRenderingHint(key); |
| } |
| |
| public RenderingHints getRenderingHints() |
| { |
| return getG2D().getRenderingHints(); |
| } |
| |
| public Stroke getStroke() |
| { |
| return _stroke; |
| } |
| |
| public AffineTransform getTransform() |
| { |
| return (AffineTransform)getTrans().clone(); |
| } |
| |
| public boolean hit(Rectangle rectangle, Shape shape, boolean flag) |
| { |
| getG2D().setTransform(getTrans()); |
| getG2D().setStroke(getStroke()); |
| getG2D().setClip(getClip()); |
| return getG2D().hit(rectangle, shape, flag); |
| } |
| |
| public void rotate(double d) |
| { |
| getTrans().rotate(d); |
| } |
| |
| public void rotate(double d, double d1, double d2) |
| { |
| getTrans().rotate(d, d1, d2); |
| } |
| |
| public void scale(double d, double d1) |
| { |
| getTrans().scale(d, d1); |
| } |
| |
| public void setBackground(Color c) |
| { |
| getEscherGraphics().setBackground(c); |
| } |
| |
| public void setClip(int i, int j, int k, int l) |
| { |
| setClip(new Rectangle(i, j, k, l)); |
| } |
| |
| public void setClip(Shape shape) |
| { |
| setDeviceclip( getTrans().createTransformedShape(shape) ); |
| } |
| |
| public void setColor(Color c) |
| { |
| _escherGraphics.setColor(c); |
| } |
| |
| public void setComposite(Composite composite) |
| { |
| getG2D().setComposite(composite); |
| } |
| |
| public void setFont(Font font) |
| { |
| getEscherGraphics().setFont(font); |
| } |
| |
| public void setPaint(Paint paint1) |
| { |
| if(paint1 != null) |
| { |
| _paint = paint1; |
| if(paint1 instanceof Color) |
| setColor( (Color)paint1 ); |
| } |
| } |
| |
| public void setPaintMode() |
| { |
| getEscherGraphics().setPaintMode(); |
| } |
| |
| public void setRenderingHint(java.awt.RenderingHints.Key key, Object obj) |
| { |
| getG2D().setRenderingHint(key, obj); |
| } |
| |
| public void setRenderingHints(Map<?, ?> map) |
| { |
| getG2D().setRenderingHints(map); |
| } |
| |
| public void setStroke(Stroke s) |
| { |
| _stroke = s; |
| } |
| |
| public void setTransform(AffineTransform affinetransform) |
| { |
| setTrans( (AffineTransform)affinetransform.clone() ); |
| } |
| |
| public void setXORMode(Color color1) |
| { |
| getEscherGraphics().setXORMode(color1); |
| } |
| |
| public void shear(double d, double d1) |
| { |
| getTrans().shear(d, d1); |
| } |
| |
| public void transform(AffineTransform affinetransform) |
| { |
| getTrans().concatenate(affinetransform); |
| } |
| |
| // Image transformImage(Image image, Rectangle rectangle, Rectangle rectangle1, ImageObserver imageobserver, Color color1) |
| // { |
| // logger.log(POILogger.WARN,"transformImage() not supported"); |
| // return null; |
| // } |
| // |
| // Image transformImage(Image image, int ai[], Rectangle rectangle, ImageObserver imageobserver, Color color1) |
| // { |
| // logger.log(POILogger.WARN,"transformImage() not supported"); |
| // return null; |
| // } |
| |
| public void translate(double d, double d1) |
| { |
| getTrans().translate(d, d1); |
| } |
| |
| public void translate(int i, int j) |
| { |
| getTrans().translate(i, j); |
| } |
| |
| private EscherGraphics getEscherGraphics() |
| { |
| return _escherGraphics; |
| } |
| |
| private BufferedImage getImg() |
| { |
| return _img; |
| } |
| |
| private void setImg( BufferedImage img ) |
| { |
| this._img = img; |
| } |
| |
| private Graphics2D getG2D() |
| { |
| return (Graphics2D) _img.getGraphics(); |
| } |
| |
| private AffineTransform getTrans() |
| { |
| return _trans; |
| } |
| |
| private void setTrans( AffineTransform trans ) |
| { |
| this._trans = trans; |
| } |
| |
| private Shape getDeviceclip() |
| { |
| return _deviceclip; |
| } |
| |
| private void setDeviceclip( Shape deviceclip ) |
| { |
| this._deviceclip = deviceclip; |
| } |
| |
| } |