public Raster getRaster(int x, int y, int w, int h) {
        WritableRaster raster =
          getColorModel().createCompatibleWritableRaster(w, h);

        int span = (int) radius * ACCURACY;
        int[][] interp = new int[span][4];
        int prev = 0;
        for (int i = 1; i < count; i++) {
          int c0 = color[i-1];
          int c1 = color[i];
          int last = (int) (offset[i] * (span - 1));
          for (int j = prev; j <= last; j++) {
            float btwn = PApplet.norm(j, prev, last);
            interp[j][0] = (int) PApplet.lerp((c0 >> 16) & 0xff, (c1 >> 16) & 0xff, btwn);
            interp[j][1] = (int) PApplet.lerp((c0 >> 8) & 0xff, (c1 >> 8) & 0xff, btwn);
            interp[j][2] = (int) PApplet.lerp(c0 & 0xff, c1 & 0xff, btwn);
            interp[j][3] = (int) (PApplet.lerp((c0 >> 24) & 0xff, (c1 >> 24) & 0xff, btwn) * opacity);
          }
          prev = last;
        }

        int[] data = new int[w * h * 4];
        int index = 0;
        for (int j = 0; j < h; j++) {
          for (int i = 0; i < w; i++) {
            float distance = PApplet.dist(cx, cy, x + i, y + j);
            int which = PApplet.min((int) (distance * ACCURACY), interp.length-1);

            data[index++] = interp[which][0];
            data[index++] = interp[which][1];
            data[index++] = interp[which][2];
            data[index++] = interp[which][3];
          }
        }
        raster.setPixels(0, 0, w, h, data);

        return raster;
      }
    }
  }


  protected Paint calcGradientPaint(Gradient gradient) {
    if (gradient instanceof LinearGradient) {
      LinearGradient grad = (LinearGradient) gradient;
      return new LinearGradientPaint(grad.x1, grad.y1, grad.x2, grad.y2,
                                     grad.offset, grad.color, grad.count,
                                     opacity);

    } else if (gradient instanceof RadialGradient) {
      RadialGradient grad = (RadialGradient) gradient;
      return new RadialGradientPaint(grad.cx, grad.cy, grad.r,
                                     grad.offset, grad.color, grad.count,
                                     opacity);
    }
    return null;
  }


//  protected Paint calcGradientPaint(Gradient gradient,
//                                    float x1, float y1, float x2, float y2) {
//    if (gradient instanceof LinearGradient) {
//      LinearGradient grad = (LinearGradient) gradient;
//      return new LinearGradientPaint(x1, y1, x2, y2,
//                                     grad.offset, grad.color, grad.count,
//                                     opacity);
//    }
//    throw new RuntimeException("Not a linear gradient.");
//  }


//  protected Paint calcGradientPaint(Gradient gradient,
//                                    float cx, float cy, float r) {
//    if (gradient instanceof RadialGradient) {
//      RadialGradient grad = (RadialGradient) gradient;
//      return new RadialGradientPaint(cx, cy, r,
//                                     grad.offset, grad.color, grad.count,
//                                     opacity);
//    }
//    throw new RuntimeException("Not a radial gradient.");
//  }


  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


  protected void styles(PGraphics g) {
    super.styles(g);

    if (g instanceof PGraphicsJava2D) {
      PGraphicsJava2D p2d = (PGraphicsJava2D) g;

      if (strokeGradient != null) {
        p2d.strokeGradient = true;
        p2d.strokeGradientObject = strokeGradientPaint;
      } else {
        // need to shut off, in case parent object has a gradient applied
        //p2d.strokeGradient = false;
      }
      if (fillGradient != null) {
        p2d.fillGradient = true;
        p2d.fillGradientObject = fillGradientPaint;
      } else {
        // need to shut off, in case parent object has a gradient applied
        //p2d.fillGradient = false;
      }
    }
  }


  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


  //public void drawImpl(PGraphics g) {
  // do nothing
  //}


  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .


  /**
   * Get a particular element based on its SVG ID. When editing SVG by hand,
   * this is the id="" tag on any SVG element. When editing from Illustrator,
   * these IDs can be edited by expanding the layers palette. The names used
   * in the layers palette, both for the layers or the shapes and groups
   * beneath them can be used here.
   * <PRE>
   * // This code grabs "Layer 3" and the shapes beneath it.
   * SVG layer3 = svg.getChild("Layer 3");
   * </PRE>
   */
  public PShape getChild(String name) {
    PShape found = super.getChild(name);
    if (found == null) {
      // Otherwise try with underscores instead of spaces
      // (this is how Illustrator handles spaces in the layer names).
      found = super.getChild(name.replace(' ', '_'));
    }
    // Set bounding box based on the parent bounding box
    if (found != null) {
//      found.x = this.x;
//      found.y = this.y;
      found.width = this.width;
      found.height = this.height;
    }