View Javadoc
1   package nl.tudelft.simulation.dsol.web.animation;
2   
3   import java.awt.AlphaComposite;
4   import java.awt.BasicStroke;
5   import java.awt.Canvas;
6   import java.awt.Color;
7   import java.awt.Composite;
8   import java.awt.Font;
9   import java.awt.FontMetrics;
10  import java.awt.Graphics;
11  import java.awt.Graphics2D;
12  import java.awt.GraphicsConfiguration;
13  import java.awt.Image;
14  import java.awt.Paint;
15  import java.awt.Rectangle;
16  import java.awt.RenderingHints;
17  import java.awt.RenderingHints.Key;
18  import java.awt.Shape;
19  import java.awt.Stroke;
20  import java.awt.font.FontRenderContext;
21  import java.awt.font.GlyphVector;
22  import java.awt.geom.AffineTransform;
23  import java.awt.geom.Ellipse2D;
24  import java.awt.geom.Line2D;
25  import java.awt.geom.Path2D;
26  import java.awt.geom.PathIterator;
27  import java.awt.geom.Rectangle2D;
28  import java.awt.image.BufferedImage;
29  import java.awt.image.BufferedImageOp;
30  import java.awt.image.ImageObserver;
31  import java.awt.image.RenderedImage;
32  import java.awt.image.renderable.RenderableImage;
33  import java.text.AttributedCharacterIterator;
34  import java.util.LinkedHashMap;
35  import java.util.Map;
36  
37  import org.djutils.logger.CategoryLogger;
38  
39  import nl.javel.gisbeans.geom.SerializableGeneralPath;
40  import nl.tudelft.simulation.dsol.logger.Cat;
41  
42  /**
43   * HTMLGraphics.java. <br>
44   * <br>
45   * Copyright (c) 2003-2020 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
46   * for project information <a href="https://www.simulation.tudelft.nl/" target="_blank">www.simulation.tudelft.nl</a>. The
47   * source code and binary code of this software is proprietary information of Delft University of Technology.
48   * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
49   */
50  public class HTMLGraphics2D extends Graphics2D
51  {
52      /** the current color of the background for drawing. */
53      Color background = Color.WHITE;
54  
55      /** the current drawing color. */
56      Color color = Color.BLACK;
57  
58      /** the current font. */
59      Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 10);
60  
61      /** the drawing canvas. */
62      Canvas canvas = new Canvas();
63  
64      /** the cached current font properties. */
65      FontMetrics fontMetrics = this.canvas.getFontMetrics(this.font);
66  
67      /** the current paint. */
68      Paint paint = Color.BLACK;
69  
70      /** the current stroke. */
71      Stroke stroke = new BasicStroke();
72  
73      /** TODO: the current rendering hints. */
74      RenderingHints renderingHints = new RenderingHints(new LinkedHashMap<Key, Object>());
75  
76      /** the current affine transform. */
77      AffineTransform affineTransform = new AffineTransform();
78  
79      /** TODO: the current composite. What is that? */
80      Composite composite = AlphaComposite.Clear;
81  
82      /** the commands to send over the channel to the HTML5 code. */
83      StringBuffer commands = new StringBuffer();
84  
85      /**
86       * Clear the commands and put the start tag in.
87       */
88      public void clearCommand()
89      {
90          this.commands = new StringBuffer();
91          this.commands.append("<animate>\n");
92      }
93  
94      /**
95       * Close the commands and put the end tag in.
96       * @return the current set of commands
97       */
98      public String closeAndGetCommands()
99      {
100         this.commands.append("</animate>\n");
101         return this.commands.toString();
102     }
103 
104     /**
105      * Add a draw command.
106      * @param drawCommand String; the tag for the draw command
107      * @param params Object...; the params for the draw command
108      */
109     protected void addDraw(String drawCommand, Object... params)
110     {
111         this.commands.append("<draw>" + drawCommand);
112         for (Object param : params)
113         {
114             this.commands.append("," + param.toString());
115         }
116         this.commands.append("</draw>\n");
117     }
118 
119     /**
120      * add AffineTransform to the command.
121      */
122     protected void addAffineTransform()
123     {
124         this.commands.append(",");
125         this.commands.append(this.affineTransform.getScaleX());
126         this.commands.append(",");
127         this.commands.append(this.affineTransform.getShearY());
128         this.commands.append(",");
129         this.commands.append(this.affineTransform.getShearX());
130         this.commands.append(",");
131         this.commands.append(this.affineTransform.getScaleY());
132         this.commands.append(",");
133         this.commands.append(this.affineTransform.getTranslateX());
134         this.commands.append(",");
135         this.commands.append(this.affineTransform.getTranslateY());
136     }
137 
138     /**
139      * add Color to the command.
140      * @param c Color; the color
141      */
142     protected void addColor(Color c)
143     {
144         this.commands.append(",");
145         this.commands.append(c.getRed());
146         this.commands.append(",");
147         this.commands.append(c.getGreen());
148         this.commands.append(",");
149         this.commands.append(c.getBlue());
150         this.commands.append(",");
151         this.commands.append(c.getAlpha());
152         this.commands.append(",");
153         this.commands.append(c.getTransparency());
154     }
155 
156     /**
157      * add font data to the command, font-name, font-size, bold/italic/plain.
158      */
159     protected void addFontData()
160     {
161         this.commands.append(",");
162         String javaFontName = this.font.getFontName().toLowerCase();
163         String htmlFontName;
164         if (javaFontName.contains("arial") || javaFontName.contains("helvetica") || javaFontName.contains("verdana")
165                 || javaFontName.contains("tahoma") || javaFontName.contains("segoe") || javaFontName.contains("sans"))
166             htmlFontName = "sans-serif";
167         else if (javaFontName.contains("times") || javaFontName.contains("cambria") || javaFontName.contains("georgia")
168                 || javaFontName.contains("serif"))
169             htmlFontName = "serif";
170         else if (javaFontName.contains("courier") || javaFontName.contains("consol") || javaFontName.contains("mono"))
171             htmlFontName = "monospace";
172         else
173             htmlFontName = "sans-serif";
174         this.commands.append(htmlFontName);
175         this.commands.append(",");
176         this.commands.append(this.font.getSize2D());
177         this.commands.append(",");
178         if (this.font.isBold())
179             this.commands.append("bold");
180         else if (this.font.isItalic())
181             this.commands.append("italic");
182         else
183             this.commands.append("plain");
184     }
185 
186     /**
187      * Add fill command, transform.m11(h-scale), transform.m12(h-skew), transform.m21(v-skew), transform.m22(v-scale),
188      * transform.dx(h-translate), transform.dy(v-translate), color.r, color.g, color.b, color.alpha, color.transparency,
189      * params...
190      * @param fillCommand String; the tag to use
191      * @param params Object...; the params to send
192      */
193     protected void addTransformFill(String fillCommand, Object... params)
194     {
195         this.commands.append("<transformFill>" + fillCommand);
196         addAffineTransform();
197         if (this.paint instanceof Color)
198             addColor((Color) this.paint);
199         else
200             addColor(this.color);
201         for (Object param : params)
202         {
203             this.commands.append("," + param.toString());
204         }
205         this.commands.append("</transformFill>\n");
206     }
207 
208     /**
209      * Add command, transform.m11(h-scale), transform.m12(h-skew), transform.m21(v-skew), transform.m22(v-scale),
210      * transform.dx(h-translate), transform.dy(v-translate), linecolor.r, linecolor.g, linecolor.b, linecolor.alpha,
211      * linecolor.transparency, line-width, params...
212      * @param drawCommand String; the tag to use
213      * @param params Object...; the params
214      */
215     protected void addTransformDraw(String drawCommand, Object... params)
216     {
217         this.commands.append("<transformDraw>" + drawCommand);
218         addAffineTransform();
219         if (this.paint instanceof Color)
220             addColor((Color) this.paint);
221         else
222             addColor(this.color);
223         if (this.stroke instanceof BasicStroke)
224             this.commands.append("," + ((BasicStroke) this.stroke).getLineWidth());
225         else
226             this.commands.append(", 0.1");
227         for (Object param : params)
228         {
229             this.commands.append("," + param.toString());
230         }
231         this.commands.append("</transformDraw>\n");
232     }
233 
234     /**
235      * adds a float array to the command.
236      * @param array float[]; the array
237      * @param length int; the number of points from the array to write
238      */
239     private void addFloatArray(final float[] array, final int length)
240     {
241         for (int i = 0; i < length; i++)
242         {
243             this.commands.append(", " + array[i]);
244         }
245     }
246 
247     /**
248      * adds a double array to the command.
249      * @param array double[]; the array
250      * @param length int; the number of points from the array to write
251      */
252     private void addDoubleArray(final double[] array, final int length)
253     {
254         for (int i = 0; i < length; i++)
255         {
256             this.commands.append(", " + array[i]);
257         }
258     }
259 
260     /**
261      * Add a path2D to the command. In case of fill:<br>
262      * FILL, transform.m11(h-scale), transform.m12(h-skew), transform.m21(v-skew), transform.m22(v-scale),
263      * transform.dx(h-translate), transform.dy(v-translate), fillcolor.r, fillcolor.g, fillcolor.b, fillcolor.alpha,
264      * fillcolor.transparency, winding_rule[WIND_EVEN_ODD/WIND_NON_ZERO], COMMAND, coords, COMMAND, coords, ... <br>
265      * In case of draw:<br>
266      * DRAW, transform.m11(h-scale), transform.m12(h-skew), transform.m21(v-skew), transform.m22(v-scale),
267      * transform.dx(h-translate), transform.dy(v-translate), strokecolor.r, strokecolor.g, strokecolor.b, strokecolor.alpha,
268      * strokecolor.transparency, line_width, COMMAND, coords, COMMAND, coords, ... <br>
269      * where command can be one of the following:<br>
270      * - CLOSE, followed by no coordinates<br>
271      * - CUBICTO, followed by 3 coordinates (6 numbers)<br>
272      * - LINETO, followed by 1 coordinate (2 numbers)<br>
273      * - MOVETO, followed by 1 coordinate (2 numbers)<br>
274      * - QUADTO, followed by 2 coordinates (4 numbers)<br>
275      * @param path Path2D.Float; the path to draw
276      * @param fill boolean;
277      */
278     protected void addTransformPathFloat(Path2D.Float path, boolean fill)
279     {
280         if (fill)
281             this.commands.append("<transformPath>FILL");
282         else
283             this.commands.append("<transformPath>DRAW");
284         addAffineTransform();
285         addColor(this.color);
286         if (fill)
287         {
288             if (path.getWindingRule() == Path2D.WIND_EVEN_ODD)
289                 this.commands.append(",WIND_EVEN_ODD");
290             else
291                 this.commands.append(",WIND_NON_ZERO");
292         }
293         else
294         {
295             if (this.stroke instanceof BasicStroke)
296                 this.commands.append("," + ((BasicStroke) this.stroke).getLineWidth());
297             else
298                 this.commands.append(", 0.1");
299         }
300         float[] coords = new float[6];
301         PathIterator i = path.getPathIterator(null);
302         while (!i.isDone())
303         {
304             int segment = i.currentSegment(coords);
305             switch (segment)
306             {
307                 case PathIterator.SEG_CLOSE:
308                     this.commands.append(",CLOSE");
309                     break;
310                 case PathIterator.SEG_CUBICTO:
311                     this.commands.append(",CUBICTO");
312                     addFloatArray(coords, 6);
313                     break;
314                 case PathIterator.SEG_LINETO:
315                     this.commands.append(",LINETO");
316                     addFloatArray(coords, 2);
317                     break;
318                 case PathIterator.SEG_MOVETO:
319                     this.commands.append(",MOVETO");
320                     addFloatArray(coords, 2);
321                     break;
322                 case PathIterator.SEG_QUADTO:
323                     this.commands.append(",QUADTO");
324                     addFloatArray(coords, 4);
325                     break;
326                 default:
327                     throw new RuntimeException("unkown segment");
328             }
329             i.next();
330         }
331             this.commands.append("</transformPath>\n");
332     }
333 
334     /**
335      * Add a path2D to the command. In case of fill:<br>
336      * FILL, transform.m11(h-scale), transform.m12(h-skew), transform.m21(v-skew), transform.m22(v-scale),
337      * transform.dx(h-translate), transform.dy(v-translate), fillcolor.r, fillcolor.g, fillcolor.b, fillcolor.alpha,
338      * fillcolor.transparency, winding_rule[WIND_EVEN_ODD/WIND_NON_ZERO], COMMAND, coords, COMMAND, coords, ... <br>
339      * In case of draw:<br>
340      * DRAW, transform.m11(h-scale), transform.m12(h-skew), transform.m21(v-skew), transform.m22(v-scale),
341      * transform.dx(h-translate), transform.dy(v-translate), strokecolor.r, strokecolor.g, strokecolor.b, strokecolor.alpha,
342      * strokecolor.transparency, line_width, COMMAND, coords, COMMAND, coords, ... <br>
343      * where command can be one of the following:<br>
344      * - CLOSE, followed by no coordinates<br>
345      * - CUBICTO, followed by 3 coordinates (6 numbers)<br>
346      * - LINETO, followed by 1 coordinate (2 numbers)<br>
347      * - MOVETO, followed by 1 coordinate (2 numbers)<br>
348      * - QUADTO, followed by 2 coordinates (4 numbers)<br>
349      * @param path Path2D.Double; the path to draw
350      * @param fill boolean;
351      */
352     protected void addTransformPathDouble(Path2D.Double path, boolean fill)
353     {
354         if (fill)
355             this.commands.append("<transformPath>FILL");
356         else
357             this.commands.append("<transformPath>DRAW");
358         addAffineTransform();
359         addColor(this.color);
360         if (fill)
361         {
362             if (path.getWindingRule() == Path2D.WIND_EVEN_ODD)
363                 this.commands.append(",WIND_EVEN_ODD");
364             else
365                 this.commands.append(",WIND_NON_ZERO");
366         }
367         else
368         {
369             if (this.stroke instanceof BasicStroke)
370                 this.commands.append("," + ((BasicStroke) this.stroke).getLineWidth());
371             else
372                 this.commands.append(", 0.1");
373         }
374         double[] coords = new double[6];
375         PathIterator i = path.getPathIterator(null);
376         while (!i.isDone())
377         {
378             int segment = i.currentSegment(coords);
379             switch (segment)
380             {
381                 case PathIterator.SEG_CLOSE:
382                     this.commands.append(",CLOSE");
383                     break;
384                 case PathIterator.SEG_CUBICTO:
385                     this.commands.append(",CUBICTO");
386                     addDoubleArray(coords, 6);
387                     break;
388                 case PathIterator.SEG_LINETO:
389                     this.commands.append(",LINETO");
390                     addDoubleArray(coords, 2);
391                     break;
392                 case PathIterator.SEG_MOVETO:
393                     this.commands.append(",MOVETO");
394                     addDoubleArray(coords, 2);
395                     break;
396                 case PathIterator.SEG_QUADTO:
397                     this.commands.append(",QUADTO");
398                     addDoubleArray(coords, 4);
399                     break;
400                 default:
401                     throw new RuntimeException("unkown segment");
402             }
403             i.next();
404         }
405         this.commands.append("</transformPath>\n");
406     }
407 
408     /**
409      * Add string, 0=command, 1=transform.m11(h-scale), 2=transform.m12(h-skew), 3=transform.m21(v-skew),
410      * 4=transform.m22(v-scale), 5=transform.dx(h-translate), 6=transform.dy(v-translate), 7=color.r, 8=color.g, 9=color.b,
411      * 10=color.alpha, 11=color.transparency, 12=fontname, 13=fontsize, 14=fontstyle(normal/italic/bold), 15=x, 16=y, 17=text.
412      * @param drawCommand String; the tag to use
413      * @param params Object...; the params
414      */
415     protected void addTransformText(String drawCommand, Object... params)
416     {
417         this.commands.append("<transformText>" + drawCommand);
418         addAffineTransform();
419         addColor(this.color);
420         addFontData();
421         for (Object param : params)
422         {
423             this.commands.append("," + param.toString());
424         }
425         this.commands.append("</transformText>\n");
426     }
427 
428     /** {@inheritDoc} */
429     @Override
430     public void draw(Shape shape)
431     {
432         drawFillShape(shape, false);
433     }
434 
435     /**
436      * Draw or fill a shape.
437      * @param shape Shape; the shape
438      * @param fill boolean; filled or not
439      */
440     protected void drawFillShape(Shape shape, boolean fill)
441     {
442         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.draw(shape: {})", shape.getClass().getSimpleName());
443         if (shape instanceof Ellipse2D.Double)
444         {
445             Ellipse2D.Double ellipse = (Ellipse2D.Double) shape;
446             if (fill)
447                 addTransformFill("fillOval", ellipse.getCenterX(), ellipse.getCenterY(), ellipse.width / 2.0,
448                         ellipse.height / 2.0);
449             else
450                 addTransformDraw("drawOval", ellipse.getCenterX(), ellipse.getCenterY(), ellipse.width / 2.0,
451                         ellipse.height / 2.0);
452         }
453         else if (shape instanceof Ellipse2D.Float)
454         {
455             Ellipse2D.Float ellipse = (Ellipse2D.Float) shape;
456             if (fill)
457                 addTransformFill("fillOval", ellipse.getCenterX(), ellipse.getCenterY(), ellipse.width / 2.0,
458                         ellipse.height / 2.0);
459             else
460                 addTransformDraw("drawOval", ellipse.getCenterX(), ellipse.getCenterY(), ellipse.width / 2.0,
461                         ellipse.height / 2.0);
462         }
463         else if (shape instanceof Line2D.Double)
464         {
465             Line2D.Double line = (Line2D.Double) shape;
466             addTransformDraw("drawLine", line.x1, line.y1, line.x2, line.y2);
467         }
468         else if (shape instanceof Line2D.Float)
469         {
470             Line2D.Float line = (Line2D.Float) shape;
471             addTransformDraw("drawLine", line.x1, line.y1, line.x2, line.y2);
472         }
473         else if (shape instanceof Rectangle2D.Double)
474         {
475             Rectangle2D.Double rect = (Rectangle2D.Double) shape;
476             if (fill)
477                 addTransformFill("fillRect", rect.x, rect.y, rect.width, rect.height);
478             else
479                 addTransformDraw("drawRect", rect.x, rect.y, rect.width, rect.height);
480         }
481         else if (shape instanceof Rectangle2D.Float)
482         {
483             Rectangle2D.Float rect = (Rectangle2D.Float) shape;
484             if (fill)
485                 addTransformFill("fillRect", rect.x, rect.y, rect.width, rect.height);
486             else
487                 addTransformDraw("drawRect", rect.x, rect.y, rect.width, rect.height);
488         }
489         else if (shape instanceof SerializableGeneralPath)
490         {
491             SerializableGeneralPath sgp = (SerializableGeneralPath) shape;
492             Path2D.Float path = sgp.getGeneralPath();
493             addTransformPathFloat(path, fill);
494         }
495         else if (shape instanceof Path2D.Float)
496         {
497             Path2D.Float path = (Path2D.Float) shape;
498             addTransformPathFloat(path, fill);
499         }
500         else if (shape instanceof Path2D.Double)
501         {
502             Path2D.Double path = (Path2D.Double) shape;
503             addTransformPathDouble(path, fill);
504         }
505 
506     }
507 
508     /** {@inheritDoc} */
509     @Override
510     public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
511     {
512         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawImage()");
513         return true;
514     }
515 
516     /** {@inheritDoc} */
517     @Override
518     public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y)
519     {
520         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawImage()");
521     }
522 
523     /** {@inheritDoc} */
524     @Override
525     public void drawRenderedImage(RenderedImage img, AffineTransform xform)
526     {
527         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawRenderedImage()");
528     }
529 
530     /** {@inheritDoc} */
531     @Override
532     public void drawRenderableImage(RenderableImage img, AffineTransform xform)
533     {
534         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawRenderableImage()");
535     }
536 
537     /** {@inheritDoc} */
538     @Override
539     public void drawString(String str, int x, int y)
540     {
541         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawString()");
542         addTransformText("drawString", x, y, str);
543     }
544 
545     /** {@inheritDoc} */
546     @Override
547     public void drawString(String str, float x, float y)
548     {
549         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawString()");
550         addTransformText("drawString", x, y, str);
551     }
552 
553     /** {@inheritDoc} */
554     @Override
555     public void drawString(AttributedCharacterIterator iterator, int x, int y)
556     {
557         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawString()");
558     }
559 
560     /** {@inheritDoc} */
561     @Override
562     public void drawString(AttributedCharacterIterator iterator, float x, float y)
563     {
564         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawString()");
565     }
566 
567     /** {@inheritDoc} */
568     @Override
569     public void drawGlyphVector(GlyphVector g, float x, float y)
570     {
571         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawGlyphVector()");
572     }
573 
574     /** {@inheritDoc} */
575     @Override
576     public void fill(Shape shape)
577     {
578         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.fill()");
579         drawFillShape(shape, true);
580     }
581 
582     /** {@inheritDoc} */
583     @Override
584     public boolean hit(Rectangle rect, Shape s, boolean onStroke)
585     {
586         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.hit()");
587         return false;
588     }
589 
590     /** {@inheritDoc} */
591     @Override
592     public GraphicsConfiguration getDeviceConfiguration()
593     {
594         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getDeviceConfiguration()");
595         return null;
596     }
597 
598     /** {@inheritDoc} */
599     @Override
600     public void setComposite(Composite comp)
601     {
602         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setComposite()");
603     }
604 
605     /** {@inheritDoc} */
606     @Override
607     public void setPaint(Paint paint)
608     {
609         this.paint = paint;
610         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setPaint()");
611     }
612 
613     /** {@inheritDoc} */
614     @Override
615     public void setStroke(Stroke s)
616     {
617         this.stroke = s;
618         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setStroke()");
619     }
620 
621     /** {@inheritDoc} */
622     @Override
623     public void setRenderingHint(Key hintKey, Object hintValue)
624     {
625         this.renderingHints.put(hintKey, hintValue);
626         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setRenderingHint()");
627     }
628 
629     /** {@inheritDoc} */
630     @Override
631     public Object getRenderingHint(Key hintKey)
632     {
633         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getRenderingHint()");
634         return this.renderingHints.get(hintKey);
635     }
636 
637     /** {@inheritDoc} */
638     @Override
639     public void setRenderingHints(Map<?, ?> hints)
640     {
641         this.renderingHints.clear();
642         this.renderingHints.putAll(hints);
643         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setRenderingHints()");
644     }
645 
646     /** {@inheritDoc} */
647     @Override
648     public void addRenderingHints(Map<?, ?> hints)
649     {
650         this.renderingHints.putAll(hints);
651         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.addRenderingHints()");
652     }
653 
654     /** {@inheritDoc} */
655     @Override
656     public RenderingHints getRenderingHints()
657     {
658         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getRenderingHints()");
659         return this.renderingHints;
660     }
661 
662     /** {@inheritDoc} */
663     @Override
664     public void translate(int x, int y)
665     {
666         this.affineTransform.translate(x, y);
667         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.translate()");
668     }
669 
670     /** {@inheritDoc} */
671     @Override
672     public void translate(double tx, double ty)
673     {
674         this.affineTransform.translate(tx, ty);
675         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.translate()");
676     }
677 
678     /** {@inheritDoc} */
679     @Override
680     public void rotate(double theta)
681     {
682         this.affineTransform.rotate(theta);
683         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.rotate()");
684     }
685 
686     /** {@inheritDoc} */
687     @Override
688     public void rotate(double theta, double x, double y)
689     {
690         this.affineTransform.rotate(theta, x, y);
691         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.rotate()");
692     }
693 
694     /** {@inheritDoc} */
695     @Override
696     public void scale(double sx, double sy)
697     {
698         this.affineTransform.scale(sx, sy);
699         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.scale()");
700     }
701 
702     /** {@inheritDoc} */
703     @Override
704     public void shear(double shx, double shy)
705     {
706         this.affineTransform.shear(shx, shy);
707         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.shear()");
708     }
709 
710     /** {@inheritDoc} */
711     @Override
712     public void transform(AffineTransform Tx)
713     {
714         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.transform()");
715     }
716 
717     /** {@inheritDoc} */
718     @Override
719     public void setTransform(AffineTransform Tx)
720     {
721         this.affineTransform = (AffineTransform) Tx.clone();
722         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setTransform()");
723     }
724 
725     /** {@inheritDoc} */
726     @Override
727     public AffineTransform getTransform()
728     {
729         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getTransform()");
730         return this.affineTransform;
731     }
732 
733     /** {@inheritDoc} */
734     @Override
735     public Paint getPaint()
736     {
737         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getPaint()");
738         return this.paint;
739     }
740 
741     /** {@inheritDoc} */
742     @Override
743     public Composite getComposite()
744     {
745         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getComposite()");
746         return this.composite;
747     }
748 
749     /** {@inheritDoc} */
750     @Override
751     public void setBackground(Color color)
752     {
753         this.background = color;
754         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setBackground()");
755     }
756 
757     /** {@inheritDoc} */
758     @Override
759     public Color getBackground()
760     {
761         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getBackground()");
762         return this.background;
763     }
764 
765     /** {@inheritDoc} */
766     @Override
767     public Stroke getStroke()
768     {
769         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getStroke()");
770         return this.stroke;
771     }
772 
773     /** {@inheritDoc} */
774     @Override
775     public void clip(Shape s)
776     {
777         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.clip()");
778     }
779 
780     /** {@inheritDoc} */
781     @Override
782     public FontRenderContext getFontRenderContext()
783     {
784         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getFontRenderContext()");
785         return new FontRenderContext(this.affineTransform, true, true);
786     }
787 
788     /** {@inheritDoc} */
789     @Override
790     public Graphics create()
791     {
792         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.create()");
793         return new HTMLGraphics2D(); // TODO: clone
794     }
795 
796     /** {@inheritDoc} */
797     @Override
798     public Color getColor()
799     {
800         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getColor()");
801         return this.color;
802     }
803 
804     /** {@inheritDoc} */
805     @Override
806     public void setColor(Color c)
807     {
808         this.color = c;
809         this.paint = c; // TODO see how difference between paint and color should be handled
810         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setColor()");
811     }
812 
813     /** {@inheritDoc} */
814     @Override
815     public void setPaintMode()
816     {
817         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setPaintMode()");
818     }
819 
820     /** {@inheritDoc} */
821     @Override
822     public void setXORMode(Color c1)
823     {
824         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setXORMode()");
825     }
826 
827     /** {@inheritDoc} */
828     @Override
829     public Font getFont()
830     {
831         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getFont()");
832         return this.font;
833     }
834 
835     /** {@inheritDoc} */
836     @Override
837     public void setFont(Font font)
838     {
839         this.font = font;
840         this.fontMetrics = this.canvas.getFontMetrics(this.font);
841         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setFont()");
842     }
843 
844     /** {@inheritDoc} */
845     @Override
846     public FontMetrics getFontMetrics(Font f)
847     {
848         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getFontMetrics()");
849         return this.fontMetrics;
850     }
851 
852     /** {@inheritDoc} */
853     @Override
854     public Rectangle getClipBounds()
855     {
856         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getClipBounds()");
857         return null;
858     }
859 
860     /** {@inheritDoc} */
861     @Override
862     public void clipRect(int x, int y, int width, int height)
863     {
864         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.clipRect()");
865     }
866 
867     /** {@inheritDoc} */
868     @Override
869     public void setClip(int x, int y, int width, int height)
870     {
871         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setClip()");
872     }
873 
874     /** {@inheritDoc} */
875     @Override
876     public Shape getClip()
877     {
878         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.getClip()");
879         return null;
880     }
881 
882     /** {@inheritDoc} */
883     @Override
884     public void setClip(Shape clip)
885     {
886         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.setClip()");
887     }
888 
889     /** {@inheritDoc} */
890     @Override
891     public void copyArea(int x, int y, int width, int height, int dx, int dy)
892     {
893         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.copyArea()");
894     }
895 
896     /** {@inheritDoc} */
897     @Override
898     public void drawLine(int x1, int y1, int x2, int y2)
899     {
900         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawLine()");
901         addTransformDraw("drawLine", x1, y1, x2, y2);
902     }
903 
904     /** {@inheritDoc} */
905     @Override
906     public void fillRect(int x, int y, int width, int height)
907     {
908         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.fillRect()");
909         addTransformFill("fillRect", x, y, width, height);
910     }
911 
912     /** {@inheritDoc} */
913     @Override
914     public void clearRect(int x, int y, int width, int height)
915     {
916         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.clearRect()");
917         addTransformDraw("clearRect", x, y, width, height);
918     }
919 
920     /** {@inheritDoc} */
921     @Override
922     public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)
923     {
924         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawRoundRect()");
925     }
926 
927     /** {@inheritDoc} */
928     @Override
929     public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)
930     {
931         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.fillRoundRect()");
932     }
933 
934     /** {@inheritDoc} */
935     @Override
936     public void drawOval(int x, int y, int width, int height)
937     {
938         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawOval()");
939         addTransformDraw("drawOval", x, y, width, height);
940     }
941 
942     /** {@inheritDoc} */
943     @Override
944     public void fillOval(int x, int y, int width, int height)
945     {
946         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.fillOval()");
947         addTransformFill("fillOval", x, y, width, height);
948     }
949 
950     /** {@inheritDoc} */
951     @Override
952     public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
953     {
954         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawArc()");
955     }
956 
957     /** {@inheritDoc} */
958     @Override
959     public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle)
960     {
961         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.fillArc()");
962     }
963 
964     /** {@inheritDoc} */
965     @Override
966     public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
967     {
968         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.fillPolyline()");
969     }
970 
971     /** {@inheritDoc} */
972     @Override
973     public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
974     {
975         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawPolygon()");
976     }
977 
978     /** {@inheritDoc} */
979     @Override
980     public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
981     {
982         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.fillPolygon()");
983     }
984 
985     /** {@inheritDoc} */
986     @Override
987     public boolean drawImage(Image img, int x, int y, ImageObserver observer)
988     {
989         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawImage()");
990         return false;
991     }
992 
993     /** {@inheritDoc} */
994     @Override
995     public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer)
996     {
997         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawImage()");
998         return false;
999     }
1000 
1001     /** {@inheritDoc} */
1002     @Override
1003     public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer)
1004     {
1005         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawImage()");
1006         return false;
1007     }
1008 
1009     /** {@inheritDoc} */
1010     @Override
1011     public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer)
1012     {
1013         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawImage()");
1014         return false;
1015     }
1016 
1017     /** {@inheritDoc} */
1018     @Override
1019     public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2,
1020             ImageObserver observer)
1021     {
1022         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawImage()");
1023         return false;
1024     }
1025 
1026     /** {@inheritDoc} */
1027     @Override
1028     public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor,
1029             ImageObserver observer)
1030     {
1031         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.drawImage()");
1032         return false;
1033     }
1034 
1035     /** {@inheritDoc} */
1036     @Override
1037     public void dispose()
1038     {
1039         CategoryLogger.filter(Cat.WEB).trace("HTMLGraphics2D.dispose()");
1040     }
1041 
1042 }