SVG Pattern Paint

A discussion forum for JFreeSVG (a fast, lightweight, SVG generator for the Java platform).

SVG Pattern Paint

Postby remiohead » Mon Jan 27, 2014 11:56 pm

I wrote this class to add some basic geometric pattern paint support (we use such paints with JFreeChart). It uses SVGGraphics2D own paint methods to construct the pattern definition. Please feel free to incorporate it or parts of it or just the idea into any future version.

Code: Select all
public class SVGPatternPaint
   implements    Paint {
   
   private final int width;
   private final int height;
   private final PatternPainter painter;

   public SVGPatternPaint(
         final int width,
         final int height,
         final PatternPainter painter) {
      this.width = width;
      this.height = height;
      this.painter = painter;
   }
   
   public void writeSvg(
         final String id,
         final SVGGraphics2D g2,
         final StringBuilder sb) {
      sb.append("<pattern ")
         .append("id=\""+id+"\" ")
         .append("width=\""+this.width+"\" ")
         .append("height=\""+this.height+"\" ")
         .append("patternUnits=\"userSpaceOnUse\" ")
         .append(">");
      this.painter.paintPattern(g2);
      sb.append("</pattern>");
   }
   
   @Override
   public int getTransparency() {
      return 0;
   }

   @Override
   public PaintContext createContext(ColorModel cm, Rectangle deviceBounds,
         Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) {
      return new PaintContext() {
         @Override
         public void dispose() {}

         @Override
         public ColorModel getColorModel() {
            return ColorModel.getRGBdefault();
         }

         @Override
         public Raster getRaster(int x, int y, int w, int h) {
            return getColorModel().createCompatibleWritableRaster(w, h);
         }
      };
   }
   
   public static interface PatternPainter {
      void paintPattern(Graphics2D g2);
   }
remiohead
 
Posts: 201
Joined: Fri Oct 02, 2009 3:53 pm

Re: SVG Pattern Paint

Postby david.gilbert » Sun Feb 02, 2014 4:47 pm

Thanks, this looks like a great idea. I presume you must have added some extra code to the setPaint() method in SVGGraphics2D to register the pattern paint instance, and some code in getSVGElement() to write the pattern definitions to SVG.

I'm thinking the paintPattern(Graphics2D) method in the PatternPainter interface could also take width and height arguments so that it knows the bounds that it should be working with. And also, I guess this implementation won't show any pattern when rendering to the screen, only for SVG...I will take a look at the Paint interface to see if there is some way to make it work on screen. Or did I miss something maybe?
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Ask your company to buy the JFreeChart Developer Guide
:idea: Check out other products sold by my company Object Refinery Limited
david.gilbert
JFreeChart Project Leader
 
Posts: 11623
Joined: Fri Mar 14, 2003 10:29 am

Re: SVG Pattern Paint

Postby remiohead » Fri Feb 07, 2014 3:27 pm

Extending from TexturePaint addresses the screen issue somewhat. This is the class I'm using in my app.

Code: Select all
public interface SVGPaint extends Paint {
   
   public void writeSvg(
         final String id,
         final SVGGraphics2D g2,
         final StringBuilder sb);
}


Code: Select all
public class SVGTexturePaint
   extends      TexturePaint
   implements    SVGPaint {
   
   private final int width;
   private final int height;
   private final TexturePainter painter;
   
   public SVGTexturePaint(
         final BufferedImage txtr,
         final Rectangle2D anchor,
         final TexturePainter painter) {
      super(txtr, anchor);
      this.width = txtr.getWidth();
      this.height = txtr.getHeight();
      this.painter = painter;
   }
   
   @Override
   public void writeSvg(
         final String id,
         final SVGGraphics2D g2,
         final StringBuilder sb) {
      sb.append("<pattern ")
         .append("id=\""+id+"\" ")
         .append("width=\""+this.width+"\" ")
         .append("height=\""+this.height+"\" ")
         .append("patternUnits=\"userSpaceOnUse\" ")
         .append(">");
      this.painter.paintTexture(g2,
            this.width,
            this.height);
      sb.append("</pattern>");
   }
   
   public int getWidth() {
      return width;
   }

   public int getHeight() {
      return height;
   }


   public TexturePainter getPainter() {
      return painter;
   }

   public static interface TexturePainter {
      void paintTexture(
            final Graphics2D g2,
            final int width,
            final int height);
   }
}


In set paint:

Code: Select all
else if(paint instanceof SVGPaint) {
           SVGPaint tp = (SVGPaint)paint;
             int count = this.patternPaints.keySet().size();
          String id = "tp"+count;
          this.elementIDs.add(id);
          this.patternPaints.put(id, tp);
          this.texturePaintRef = id;
        }


And finally in getSVGElement:

Code: Select all
        for(String key : this.patternPaints.keySet()) {
           final StringBuilder saved = this.sb;
           try {
              this.sb = defs;
              this.patternPaints.get(key).writeSvg(
                    key, this, defs);
           } finally {
              this.sb = saved;
           }
        }
remiohead
 
Posts: 201
Joined: Fri Oct 02, 2009 3:53 pm

Re: SVG Pattern Paint

Postby david.gilbert » Tue Feb 25, 2014 5:49 pm

I need to spend a bit more time on this to make sure the reuse of the same SVGGraphics2D instance to generate the pattern is going to be safe. I will leave it out for the 1.7 release and come back to it later.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Ask your company to buy the JFreeChart Developer Guide
:idea: Check out other products sold by my company Object Refinery Limited
david.gilbert
JFreeChart Project Leader
 
Posts: 11623
Joined: Fri Mar 14, 2003 10:29 am


Return to JFreeSVG

Who is online

Users browsing this forum: No registered users and 1 guest