private void fillCanvasWithHole(
      Canvas canvas, ColorChangeTask task, float radius, boolean transparent) {
    if (transparent) return;

    float scale = radius / GRADIENT_RADIUS;

    mMatrix.reset();
    mMatrix.postScale(scale, scale, task.x, task.y);
    RadialGradient shader = getShader(task);
    shader.setLocalMatrix(mMatrix);
    mShaderPaint.setShader(shader);
    canvas.drawRect(getBounds(), mShaderPaint);
  }
  private boolean setRippleEffect(float x, float y, float radius) {
    if (mRipplePoint.x != x || mRipplePoint.y != y || mRippleRadius != radius) {
      mRipplePoint.set(x, y);
      mRippleRadius = radius;
      radius = mRippleRadius / GRADIENT_RADIUS;
      mMatrix.reset();
      mMatrix.postTranslate(x, y);
      mMatrix.postScale(radius, radius, x, y);
      mInShader.setLocalMatrix(mMatrix);
      if (mOutShader != null) mOutShader.setLocalMatrix(mMatrix);

      return true;
    }

    return false;
  }
 protected void onBoundsChange(Rect bounds) {
   super.onBoundsChange(bounds);
   float centerX = this.mRect.centerX();
   float centerY = (this.mRect.centerY() * DefaultRetryPolicy.DEFAULT_BACKOFF_MULT) / 0.7f;
   float centerX2 = this.mRect.centerX() * 1.3f;
   int[] iArr = new int[3];
   iArr[2] = 2130706432;
   RadialGradient vignette =
       new RadialGradient(
           centerX,
           centerY,
           centerX2,
           iArr,
           new float[] {0.0f, 0.7f, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT},
           TileMode.CLAMP);
   Matrix oval = new Matrix();
   oval.setScale(DefaultRetryPolicy.DEFAULT_BACKOFF_MULT, 0.7f);
   vignette.setLocalMatrix(oval);
   this.paint.setShader(new ComposeShader(this.bitmapShader, vignette, Mode.SRC_OVER));
 }
  @Override
  protected void onBoundsChange(Rect bounds) {
    super.onBoundsChange(bounds);

    rectF.set(margin, margin, bounds.width() - margin, bounds.height() - margin);
    if (USE_VIGNETTE) {
      RadialGradient vignette =
          new RadialGradient(
              rectF.centerX(),
              rectF.centerY() * 1.0f / 0.7f,
              rectF.centerX() * 1.3f,
              new int[] {0, 0, 0x7f000000},
              new float[] {0.0f, 0.7f, 1.0f},
              Shader.TileMode.CLAMP);

      Matrix oval = new Matrix();
      oval.setScale(1.0f, 0.7f);
      vignette.setLocalMatrix(oval);

      paint.setShader(new ComposeShader(bitmapShader, vignette, PorterDuff.Mode.SRC_OVER));
    }
  }
 @Override
 public void endElement(String namespaceURI, String localName, String qName)
     throws SAXException {
   if (localName.equals("svg")) {
     picture.endRecording();
   } else if (localName.equals("linearGradient")) {
     if (gradient.id != null) {
       if (gradient.xlink != null) {
         Gradient parent = gradientRefMap.get(gradient.xlink);
         if (parent != null) {
           gradient = parent.createChild(gradient);
         }
       }
       int[] colors = new int[gradient.colors.size()];
       for (int i = 0; i < colors.length; i++) {
         colors[i] = gradient.colors.get(i);
       }
       float[] positions = new float[gradient.positions.size()];
       for (int i = 0; i < positions.length; i++) {
         positions[i] = gradient.positions.get(i);
       }
       LinearGradient g =
           new LinearGradient(
               gradient.x1,
               gradient.y1,
               gradient.x2,
               gradient.y2,
               colors,
               positions,
               Shader.TileMode.CLAMP);
       if (gradient.matrix != null) {
         g.setLocalMatrix(gradient.matrix);
       }
       gradientMap.put(gradient.id, g);
       gradientRefMap.put(gradient.id, gradient);
     }
   } else if (localName.equals("radialGradient")) {
     if (gradient.id != null) {
       if (gradient.xlink != null) {
         Gradient parent = gradientRefMap.get(gradient.xlink);
         if (parent != null) {
           gradient = parent.createChild(gradient);
         }
       }
       int[] colors = new int[gradient.colors.size()];
       for (int i = 0; i < colors.length; i++) {
         colors[i] = gradient.colors.get(i);
       }
       float[] positions = new float[gradient.positions.size()];
       for (int i = 0; i < positions.length; i++) {
         positions[i] = gradient.positions.get(i);
       }
       if (gradient.xlink != null) {
         Gradient parent = gradientRefMap.get(gradient.xlink);
         if (parent != null) {
           gradient = parent.createChild(gradient);
         }
       }
       RadialGradient g =
           new RadialGradient(
               gradient.x,
               gradient.y,
               gradient.radius,
               colors,
               positions,
               Shader.TileMode.CLAMP);
       if (gradient.matrix != null) {
         g.setLocalMatrix(gradient.matrix);
       }
       gradientMap.put(gradient.id, g);
       gradientRefMap.put(gradient.id, gradient);
     }
   } else if (localName.equals("g")) {
     if (boundsMode) {
       boundsMode = false;
     }
     // Break out of hidden mode
     if (hidden) {
       hiddenLevel--;
       // Util.debug("Hidden down: " + hiddenLevel);
       if (hiddenLevel == 0) {
         hidden = false;
       }
     }
     // Clear gradient map
     gradientMap.clear();
     popTransform();
   }
 }