001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hssf.usermodel;
019:
020: import org.apache.poi.util.POILogFactory;
021: import org.apache.poi.util.POILogger;
022:
023: import java.awt.*;
024: import java.awt.font.FontRenderContext;
025: import java.awt.font.GlyphVector;
026: import java.awt.font.TextLayout;
027: import java.awt.geom.AffineTransform;
028: import java.awt.geom.Area;
029: import java.awt.geom.GeneralPath;
030: import java.awt.geom.Line2D;
031: import java.awt.image.BufferedImage;
032: import java.awt.image.BufferedImageOp;
033: import java.awt.image.ImageObserver;
034: import java.awt.image.RenderedImage;
035: import java.awt.image.renderable.RenderableImage;
036: import java.text.AttributedCharacterIterator;
037: import java.util.Map;
038:
039: /**
040: * Translates Graphics2d calls into escher calls. The translation is lossy so
041: * many features are not supported and some just aren't implemented yet. If
042: * in doubt test the specific calls you wish to make. Graphics calls are
043: * always drawn into an EscherGroup so one will need to be created.
044: * <p>
045: * <b>Important:</b>
046: * <blockquote>
047: * One important concept worth considering is that of font size. One of the
048: * difficulties in converting Graphics calls into escher drawing calls is that
049: * Excel does not have the concept of absolute pixel positions. It measures
050: * it's cell widths in 'characters' and the cell heights in points.
051: * Unfortunately it's not defined exactly what a type of character it's
052: * measuring. Presumably this is due to the fact that the Excel will be
053: * using different fonts on different platforms or even within the same
054: * platform.
055: * <p>
056: * Because of this constraint you have to calculate the verticalPointsPerPixel.
057: * This the amount the font should be scaled by when
058: * you issue commands such as drawString(). A good way to calculate this
059: * is to use the follow formula:
060: * <p>
061: * <pre>
062: * multipler = groupHeightInPoints / heightOfGroup
063: * </pre>
064: * <p>
065: * The height of the group is calculated fairly simply by calculating the
066: * difference between the y coordinates of the bounding box of the shape. The
067: * height of the group can be calculated by using a convenience called
068: * <code>HSSFClientAnchor.getAnchorHeightInPoints()</code>.
069: * </blockquote>
070: *
071: * @author Glen Stampoultzis (glens at apache.org)
072: */
073: public class EscherGraphics2d extends Graphics2D {
074: private EscherGraphics escherGraphics;
075: private BufferedImage img;
076: private AffineTransform trans;
077: private Stroke stroke;
078: private Paint paint;
079: private Shape deviceclip;
080: private POILogger logger = POILogFactory.getLogger(getClass());
081:
082: /**
083: * Constructs one escher graphics object from an escher graphics object.
084: *
085: * @param escherGraphics the original EscherGraphics2d object to copy
086: */
087: public EscherGraphics2d(EscherGraphics escherGraphics) {
088: this .escherGraphics = escherGraphics;
089: setImg(new BufferedImage(1, 1, 2));
090: setColor(Color.black);
091: }
092:
093: public void addRenderingHints(Map map) {
094: getG2D().addRenderingHints(map);
095: }
096:
097: public void clearRect(int i, int j, int k, int l) {
098: Paint paint1 = getPaint();
099: setColor(getBackground());
100: fillRect(i, j, k, l);
101: setPaint(paint1);
102: }
103:
104: public void clip(Shape shape) {
105: if (getDeviceclip() != null) {
106: Area area = new Area(getClip());
107: if (shape != null)
108: area.intersect(new Area(shape));
109: shape = area;
110: }
111: setClip(shape);
112: }
113:
114: public void clipRect(int x, int y, int width, int height) {
115: clip(new Rectangle(x, y, width, height));
116: }
117:
118: public void copyArea(int x, int y, int width, int height, int dx,
119: int dy) {
120: getG2D().copyArea(x, y, width, height, dx, dy);
121: }
122:
123: public Graphics create() {
124: EscherGraphics2d g2d = new EscherGraphics2d(escherGraphics);
125: return g2d;
126: }
127:
128: public void dispose() {
129: getEscherGraphics().dispose();
130: getG2D().dispose();
131: getImg().flush();
132: }
133:
134: public void draw(Shape shape) {
135: if (shape instanceof Line2D) {
136: Line2D shape2d = (Line2D) shape;
137:
138: int width = 0;
139: if (stroke != null && stroke instanceof BasicStroke) {
140: width = (int) ((BasicStroke) stroke).getLineWidth() * 12700;
141: }
142:
143: drawLine((int) shape2d.getX1(), (int) shape2d.getY1(),
144: (int) shape2d.getX2(), (int) shape2d.getY2(), width);
145: } else {
146: if (logger.check(POILogger.WARN))
147: logger.log(POILogger.WARN, "draw not fully supported");
148: }
149: }
150:
151: public void drawArc(int x, int y, int width, int height,
152: int startAngle, int arcAngle) {
153: draw(new java.awt.geom.Arc2D.Float(x, y, width, height,
154: startAngle, arcAngle, 0));
155: }
156:
157: public void drawGlyphVector(GlyphVector g, float x, float y) {
158: fill(g.getOutline(x, y));
159: }
160:
161: public boolean drawImage(Image image, int dx1, int dy1, int dx2,
162: int dy2, int sx1, int sy1, int sx2, int sy2, Color bgColor,
163: ImageObserver imageobserver) {
164: if (logger.check(POILogger.WARN))
165: logger.log(POILogger.WARN, "drawImage() not supported");
166: return true;
167: }
168:
169: public boolean drawImage(Image image, int dx1, int dy1, int dx2,
170: int dy2, int sx1, int sy1, int sx2, int sy2,
171: ImageObserver imageobserver) {
172: if (logger.check(POILogger.WARN))
173: logger.log(POILogger.WARN, "drawImage() not supported");
174: return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
175: null, imageobserver);
176: }
177:
178: public boolean drawImage(Image image, int dx1, int dy1, int dx2,
179: int dy2, Color bgColor, ImageObserver imageobserver) {
180: if (logger.check(POILogger.WARN))
181: logger.log(POILogger.WARN, "drawImage() not supported");
182: return true;
183: }
184:
185: public boolean drawImage(Image img, int x, int y, int width,
186: int height, ImageObserver observer) {
187: return drawImage(img, x, y, width, height, null, observer);
188: }
189:
190: public boolean drawImage(Image image, int x, int y, Color bgColor,
191: ImageObserver imageobserver) {
192: return drawImage(image, x, y, image.getWidth(imageobserver),
193: image.getHeight(imageobserver), bgColor, imageobserver);
194: }
195:
196: public boolean drawImage(Image image, int x, int y,
197: ImageObserver imageobserver) {
198: return drawImage(image, x, y, image.getWidth(imageobserver),
199: image.getHeight(imageobserver), imageobserver);
200: }
201:
202: public boolean drawImage(Image image,
203: AffineTransform affinetransform, ImageObserver imageobserver) {
204: AffineTransform affinetransform1 = (AffineTransform) getTrans()
205: .clone();
206: getTrans().concatenate(affinetransform);
207: drawImage(image, 0, 0, imageobserver);
208: setTrans(affinetransform1);
209: return true;
210: }
211:
212: public void drawImage(BufferedImage bufferedimage,
213: BufferedImageOp op, int x, int y) {
214: BufferedImage img = op.filter(bufferedimage, null);
215: drawImage(((Image) (img)), new AffineTransform(1.0F, 0.0F,
216: 0.0F, 1.0F, x, y), null);
217: }
218:
219: public void drawLine(int x1, int y1, int x2, int y2, int width) {
220: getEscherGraphics().drawLine(x1, y1, x2, y2, width);
221: }
222:
223: public void drawLine(int x1, int y1, int x2, int y2) {
224: int width = 0;
225: if (stroke != null && stroke instanceof BasicStroke) {
226: width = (int) ((BasicStroke) stroke).getLineWidth() * 12700;
227: }
228: getEscherGraphics().drawLine(x1, y1, x2, y2, width);
229: // draw(new GeneralPath(new java.awt.geom.Line2D.Float(x1, y1, x2, y2)));
230: }
231:
232: public void drawOval(int x, int y, int width, int height) {
233: getEscherGraphics().drawOval(x, y, width, height);
234: // draw(new java.awt.geom.Ellipse2D.Float(x, y, width, height));
235: }
236:
237: public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {
238: getEscherGraphics().drawPolygon(xPoints, yPoints, nPoints);
239: }
240:
241: public void drawPolyline(int xPoints[], int yPoints[], int nPoints) {
242: if (nPoints > 0) {
243: GeneralPath generalpath = new GeneralPath();
244: generalpath.moveTo(xPoints[0], yPoints[0]);
245: for (int j = 1; j < nPoints; j++)
246: generalpath.lineTo(xPoints[j], yPoints[j]);
247:
248: draw(generalpath);
249: }
250: }
251:
252: public void drawRect(int x, int y, int width, int height) {
253: escherGraphics.drawRect(x, y, width, height);
254: }
255:
256: public void drawRenderableImage(RenderableImage renderableimage,
257: AffineTransform affinetransform) {
258: drawRenderedImage(renderableimage.createDefaultRendering(),
259: affinetransform);
260: }
261:
262: public void drawRenderedImage(RenderedImage renderedimage,
263: AffineTransform affinetransform) {
264: BufferedImage bufferedimage = new BufferedImage(renderedimage
265: .getColorModel(), renderedimage.getData()
266: .createCompatibleWritableRaster(), false, null);
267: bufferedimage.setData(renderedimage.getData());
268: drawImage(bufferedimage, affinetransform, null);
269: }
270:
271: public void drawRoundRect(int i, int j, int k, int l, int i1, int j1) {
272: draw(new java.awt.geom.RoundRectangle2D.Float(i, j, k, l, i1,
273: j1));
274: }
275:
276: public void drawString(String string, float x, float y) {
277: getEscherGraphics().drawString(string, (int) x, (int) y);
278: }
279:
280: public void drawString(String string, int x, int y) {
281: getEscherGraphics().drawString(string, x, y);
282: }
283:
284: public void drawString(
285: AttributedCharacterIterator attributedcharacteriterator,
286: float x, float y) {
287: TextLayout textlayout = new TextLayout(
288: attributedcharacteriterator, getFontRenderContext());
289: Paint paint1 = getPaint();
290: setColor(getColor());
291: fill(textlayout.getOutline(AffineTransform
292: .getTranslateInstance(x, y)));
293: setPaint(paint1);
294: }
295:
296: public void drawString(
297: AttributedCharacterIterator attributedcharacteriterator,
298: int x, int y) {
299: drawString(attributedcharacteriterator, x, y);
300: }
301:
302: public void fill(Shape shape) {
303: if (logger.check(POILogger.WARN))
304: logger.log(POILogger.WARN, "fill(Shape) not supported");
305: }
306:
307: public void fillArc(int i, int j, int k, int l, int i1, int j1) {
308: fill(new java.awt.geom.Arc2D.Float(i, j, k, l, i1, j1, 2));
309: }
310:
311: public void fillOval(int x, int y, int width, int height) {
312: escherGraphics.fillOval(x, y, width, height);
313: }
314:
315: /**
316: * Fills a (closed) polygon, as defined by a pair of arrays, which
317: * hold the <i>x</i> and <i>y</i> coordinates.
318: * <p>
319: * This draws the polygon, with <code>nPoint</code> line segments.
320: * The first <code>nPoint - 1</code> line segments are
321: * drawn between sequential points
322: * (<code>xPoints[i],yPoints[i],xPoints[i+1],yPoints[i+1]</code>).
323: * The final line segment is a closing one, from the last point to
324: * the first (assuming they are different).
325: * <p>
326: * The area inside of the polygon is defined by using an
327: * even-odd fill rule (also known as the alternating rule), and
328: * the area inside of it is filled.
329: * @param xPoints array of the <code>x</code> coordinates.
330: * @param yPoints array of the <code>y</code> coordinates.
331: * @param nPoints the total number of points in the polygon.
332: * @see java.awt.Graphics#drawPolygon(int[], int[], int)
333: */
334: public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {
335: escherGraphics.fillPolygon(xPoints, yPoints, nPoints);
336: }
337:
338: public void fillRect(int x, int y, int width, int height) {
339: getEscherGraphics().fillRect(x, y, width, height);
340: }
341:
342: public void fillRoundRect(int x, int y, int width, int height,
343: int arcWidth, int arcHeight) {
344: fill(new java.awt.geom.RoundRectangle2D.Float(x, y, width,
345: height, arcWidth, arcHeight));
346: }
347:
348: public Color getBackground() {
349: return getEscherGraphics().getBackground();
350: }
351:
352: public Shape getClip() {
353: try {
354: return getTrans().createInverse().createTransformedShape(
355: getDeviceclip());
356: } catch (Exception _ex) {
357: return null;
358: }
359: }
360:
361: public Rectangle getClipBounds() {
362: if (getDeviceclip() != null)
363: return getClip().getBounds();
364: else
365: return null;
366: }
367:
368: public Color getColor() {
369: return escherGraphics.getColor();
370: }
371:
372: public Composite getComposite() {
373: return getG2D().getComposite();
374: }
375:
376: public GraphicsConfiguration getDeviceConfiguration() {
377: return getG2D().getDeviceConfiguration();
378: }
379:
380: public Font getFont() {
381: return getEscherGraphics().getFont();
382: }
383:
384: public FontMetrics getFontMetrics(Font font) {
385: return getEscherGraphics().getFontMetrics(font);
386: }
387:
388: public FontRenderContext getFontRenderContext() {
389: getG2D().setTransform(getTrans());
390: return getG2D().getFontRenderContext();
391: }
392:
393: public Paint getPaint() {
394: return paint;
395: }
396:
397: public Object getRenderingHint(java.awt.RenderingHints.Key key) {
398: return getG2D().getRenderingHint(key);
399: }
400:
401: public RenderingHints getRenderingHints() {
402: return getG2D().getRenderingHints();
403: }
404:
405: public Stroke getStroke() {
406: return stroke;
407: }
408:
409: public AffineTransform getTransform() {
410: return (AffineTransform) getTrans().clone();
411: }
412:
413: public boolean hit(Rectangle rectangle, Shape shape, boolean flag) {
414: getG2D().setTransform(getTrans());
415: getG2D().setStroke(getStroke());
416: getG2D().setClip(getClip());
417: return getG2D().hit(rectangle, shape, flag);
418: }
419:
420: public void rotate(double d) {
421: getTrans().rotate(d);
422: }
423:
424: public void rotate(double d, double d1, double d2) {
425: getTrans().rotate(d, d1, d2);
426: }
427:
428: public void scale(double d, double d1) {
429: getTrans().scale(d, d1);
430: }
431:
432: public void setBackground(Color c) {
433: getEscherGraphics().setBackground(c);
434: }
435:
436: public void setClip(int i, int j, int k, int l) {
437: setClip(((Shape) (new Rectangle(i, j, k, l))));
438: }
439:
440: public void setClip(Shape shape) {
441: setDeviceclip(getTrans().createTransformedShape(shape));
442: }
443:
444: public void setColor(Color c) {
445: escherGraphics.setColor(c);
446: }
447:
448: public void setComposite(Composite composite) {
449: getG2D().setComposite(composite);
450: }
451:
452: public void setFont(Font font) {
453: getEscherGraphics().setFont(font);
454: }
455:
456: public void setPaint(Paint paint1) {
457: if (paint1 != null) {
458: paint = paint1;
459: if (paint1 instanceof Color)
460: setColor((Color) paint1);
461: }
462: }
463:
464: public void setPaintMode() {
465: getEscherGraphics().setPaintMode();
466: }
467:
468: public void setRenderingHint(java.awt.RenderingHints.Key key,
469: Object obj) {
470: getG2D().setRenderingHint(key, obj);
471: }
472:
473: public void setRenderingHints(Map map) {
474: getG2D().setRenderingHints(map);
475: }
476:
477: public void setStroke(Stroke s) {
478: stroke = s;
479: }
480:
481: public void setTransform(AffineTransform affinetransform) {
482: setTrans((AffineTransform) affinetransform.clone());
483: }
484:
485: public void setXORMode(Color color1) {
486: getEscherGraphics().setXORMode(color1);
487: }
488:
489: public void shear(double d, double d1) {
490: getTrans().shear(d, d1);
491: }
492:
493: public void transform(AffineTransform affinetransform) {
494: getTrans().concatenate(affinetransform);
495: }
496:
497: // Image transformImage(Image image, Rectangle rectangle, Rectangle rectangle1, ImageObserver imageobserver, Color color1)
498: // {
499: // logger.log(POILogger.WARN,"transformImage() not supported");
500: // return null;
501: // }
502: //
503: // Image transformImage(Image image, int ai[], Rectangle rectangle, ImageObserver imageobserver, Color color1)
504: // {
505: // logger.log(POILogger.WARN,"transformImage() not supported");
506: // return null;
507: // }
508:
509: public void translate(double d, double d1) {
510: getTrans().translate(d, d1);
511: }
512:
513: public void translate(int i, int j) {
514: getTrans().translate(i, j);
515: }
516:
517: private EscherGraphics getEscherGraphics() {
518: return escherGraphics;
519: }
520:
521: private BufferedImage getImg() {
522: return img;
523: }
524:
525: private void setImg(BufferedImage img) {
526: this .img = img;
527: }
528:
529: private Graphics2D getG2D() {
530: return (Graphics2D) img.getGraphics();
531: }
532:
533: private AffineTransform getTrans() {
534: return trans;
535: }
536:
537: private void setTrans(AffineTransform trans) {
538: this .trans = trans;
539: }
540:
541: private Shape getDeviceclip() {
542: return deviceclip;
543: }
544:
545: private void setDeviceclip(Shape deviceclip) {
546: this.deviceclip = deviceclip;
547: }
548:
549: }
|