Class MeshGradient

  • All Implemented Interfaces:
    java.awt.Paint, java.awt.Transparency

    public class MeshGradient
    extends java.lang.Object
    implements java.awt.Paint

    A MeshGradient is a "Coons Patch Array" based shading pattern, which can be used to give photorealistic shading to a fill. It's used the same way a MultipleGradientPaint would be, and while it is necessarily complicated, it is defined using exactly the same conceptual approach as the meshgradient which we hope will be added to SVG some time after SVG 2.0. Here's an example:

     MeshGradient.Builder b = new MeshGradient.Builder();
     // Add first patch
     GeneralPath p = new GeneralPath();
     p.moveTo(50, 50);                            // initial point of first patch positions the shape
     p.curveTo(75, 25, 125, 75, 150, 50);         // top edge
     p.curveTo(175, 75, 125, 125, 150, 150);      // right edge
     p.curveTo(125, 175, 75, 125, 50, 150);       // bottom edge
     p.curveTo(25, 125, 75, 75, 50, 50);          // left edge, back to start
     b.addFirst(p, Color.blue, Color.magenta, Color.red, Color.magenta);
    
     // Add second patch, to the right of the first one. Needs top, right and bottom edge.
     p = new GeneralPath();
     p.moveTo(0, 0);                              // top-left corner, will be adjusted to match previous patch
     p.curveTo(25, -25, 75, 25, 100, 0);          // top edge
     p.curveTo(125, 25, 75, 75, 100, 100);        // right idge
     p.curveTo(75, 125, 25, 75, 0, 100);          // bottom edge
     b.addNext(p, Color.blue, Color.magenta);
    
     b.nextRow();
    
     // Add third patch, below the first one. Needs right, bottom and left edge.
     p = new GeneralPath();
     p.moveTo(100, 0);                            // top-right corner, will be adjusted to match previous patch
     p.curveTo(125, 25, 75, 75, 100, 100);        // right edge
     p.curveTo(75, 125, 25, 75, 0, 100);          // bottom edge
     p.curveTo(-25, 75, 25, 25, 0, 0);            // left edge
     b.addNext(p, Color.magenta, Color.blue);
    
     // Add fourth patch, to right of previous one. Only needs two edges.
     p = new GeneralPath();
     p.moveTo(100, 0);                            // top-right corner, will be adjusted to match previous patch
     p.curveTo(125, 25, 75, 75, 100, 100);        // right edge
     p.curveTo(75, 125, 25, 75, 0, 100);          // bottom edge
     b.addNext(p, Color.blue);
    
     Paint paint = b.createMeshGradient();        // Complete! Now just treat it as a paint
     PDFStyle style = new PDFStyle();
     style.setFillColor(paint);
     page.setStyle(style);
     page.drawShape(new Rectangle(0, 0, 595, 842));
     

    The first patch is added at the logical top-left corner of the gradient, then further patches are added on the same row until a call to MeshGradient.Builder.nextRow(). The rows are build up with shapes and when done, the final MeshGradient is retrieved by calling MeshGradient.Builder.createMeshGradient()

    This is identical to the SVG example below, which is taken from the SVG specification. Coordinates in the Java GeneralPath class are absolute, but they result in identical coordinates in the SVG path below.

     
      
       
        
        
        
        
       
       
        
        
        
        
       
        
        
       
        
         
        
        
       
       
        
         
        
        
       
      
     
     

    Finally, although this class implements Paint, it cannot currently be used outside as a general paint and will only work when used in PDF. And of course, remember that all coordinates are in PDF space so are measured from the bottom-left.

    Since:
    2.23.1
    • Field Summary

      • Fields inherited from interface java.awt.Transparency

        BITMASK, OPAQUE, TRANSLUCENT
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      java.awt.PaintContext createContext​(java.awt.image.ColorModel cm, java.awt.Rectangle deviceBounds, java.awt.geom.Rectangle2D userBounds, java.awt.geom.AffineTransform xform, java.awt.RenderingHints hints)
      This class is not suitable for use with the AWT so this method throws an UnsupportedOperationException
      java.awt.Color getColor​(int x, int y, int z)
      Retrieve an individual Color from the mesh array.
      int getColumns()
      Get the number of columns in this mesh array
      java.awt.geom.Point2D getPoint​(int x, int y, int z, java.awt.geom.Point2D point)
      Retrieve an individual point from the mesh array.
      int getRows()
      Get the number of rows in this mesh array
      java.awt.geom.AffineTransform getTransform()
      Return the AffineTransform on this gradient, as set by setTransform(java.awt.geom.AffineTransform)
      int getTransparency()  
      void setTransform​(java.awt.geom.AffineTransform transform)
      Set the AffineTransform on this gradient
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • setTransform

        public void setTransform​(java.awt.geom.AffineTransform transform)
        Set the AffineTransform on this gradient
        Since:
        2.23.3
      • getTransparency

        public int getTransparency()
        Specified by:
        getTransparency in interface java.awt.Transparency
      • getColumns

        public int getColumns()
        Get the number of columns in this mesh array
      • getRows

        public int getRows()
        Get the number of rows in this mesh array
      • getPoint

        public java.awt.geom.Point2D getPoint​(int x,
                                              int y,
                                              int z,
                                              java.awt.geom.Point2D point)
        Retrieve an individual point from the mesh array. Points are numbered clockwise, with the bottom-left corner at index 0, the two control points for the left edge and index 1 and 2, the top-left corner at index 3, and so on around to 11.
        Parameters:
        x - the column of the patch to retrieve, from 0..getColumns()
        y - the row of the patch to retrieve, from 0..getColumns()
        z - the index of the point to retrive, from 0..11
        point - the Point2D object to populate (may be null to create a new Point2D)
        Returns:
        the requested Point.
      • getColor

        public java.awt.Color getColor​(int x,
                                       int y,
                                       int z)
        Retrieve an individual Color from the mesh array. Colors are numbered clockwise, with the bottom-left corner at index 0
        Parameters:
        x - the column of the patch to retrieve, from 0..getColumns()
        y - the row of the patch to retrieve, from 0..getColumns()
        z - the index of the Color to retrive, from 0..3
        Returns:
        the requested Color.
      • createContext

        public java.awt.PaintContext createContext​(java.awt.image.ColorModel cm,
                                                   java.awt.Rectangle deviceBounds,
                                                   java.awt.geom.Rectangle2D userBounds,
                                                   java.awt.geom.AffineTransform xform,
                                                   java.awt.RenderingHints hints)
        This class is not suitable for use with the AWT so this method throws an UnsupportedOperationException
        Specified by:
        createContext in interface java.awt.Paint
        Throws:
        java.lang.UnsupportedOperationException