123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- /* ====================================================================
- 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.logging.log4j.LogManager;
- import org.apache.logging.log4j.Logger;
-
- 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.Arc2D;
- import java.awt.geom.Area;
- import java.awt.geom.GeneralPath;
- import java.awt.geom.Line2D;
- 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;
-
- /**
- * 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 static final Logger LOG = LogManager.getLogger(EscherGraphics2d.class);
-
- private EscherGraphics _escherGraphics;
- private BufferedImage _img;
- private AffineTransform _trans;
- private Stroke _stroke;
- private Paint _paint;
- private Shape _deviceclip;
-
- /**
- * 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()
- {
- return new EscherGraphics2d(_escherGraphics);
- }
-
- 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
- {
- LOG.atWarn().log("draw not fully supported");
- }
- }
-
- public void drawArc(int x, int y, int width, int height,
- int startAngle, int arcAngle)
- {
- draw(new 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)
- {
- LOG.atWarn().log("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)
- {
- LOG.atWarn().log("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)
- {
- LOG.atWarn().log("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 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)
- {
- LOG.atWarn().log("fill(Shape) not supported");
- }
-
- public void fillArc(int i, int j, int k, int l, int i1, int j1)
- {
- fill(new 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 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 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) {
- final Shape clip = getClip();
- return clip != null ? clip.getBounds() : null;
- }
- 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(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(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);
- }
-
- 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;
- }
-
- }
|