public final void reset() {
   pathPoints.clear();
   gp.reset();
   bounds.setBounds(0, 0, 0, 0);
   largestCoord = 0;
   needClosePath = false;
 }
  public static GeneralPath createArrowLine(double x0, double y0, double x1, double y1) {

    float theta = (float) Math.atan((double) (y1 - y0) / (double) (x1 - x0));
    float len = (float) Math.sqrt(Math.pow((x1 - x0), 2) + Math.pow((y1 - y0), 2));
    float side = (x1 < x0) ? -1 : 1;

    // Ideally, we should use a fixed distance from the end point,
    // rather than try and calculate a percentage, as that mucks it up
    // for shorter lengths...The easiest way would be to "draw" a
    // circle around the point (x1,y1) and then compute the
    // line-circle intersection point.  I'm too lazy to do the math
    // right now, though...

    GeneralPath gp = new GeneralPath();
    gp.reset();
    gp.moveTo((float) x0, (float) y0);
    gp.lineTo((float) (x0 + ((x1 - x0) * 0.9725f)), (float) (y0 + ((y1 - y0) * 0.9725f)));
    gp.moveTo((float) x1, (float) y1);
    gp.lineTo(
        (float) (x1 - side * ALEN * (float) Math.cos(theta + AANG)),
        (float) (y1 - side * ALEN * (float) Math.sin(theta + AANG)));
    gp.quadTo(
        (float) (x0 + ((x1 - x0) * 0.9725f)),
        (float) (y0 + ((y1 - y0) * 0.9725f)),
        (float) (x1 - side * ALEN * Math.cos(theta - AANG)),
        (float) (y1 - side * ALEN * Math.sin(theta - AANG)));
    gp.closePath();
    return gp;
  }
Esempio n. 3
0
 public void reset() {
   if (path != null) {
     path.reset();
   }
   if (pathNormalizer != null) {
     pathNormalizer.reset();
   }
   drawing = false;
   newLine = false;
   normalizerFinished = false;
   normalizerCounter = 0;
   normalizerX = 10.0;
   normalizerY = 10.0;
   pixX = 0;
   pixY = 0;
   propX = 0.0;
   propY = 0.0;
   lineList.clear();
   repaint();
 }
  private GeneralPath getGeneralPath() {
    if (pathPoints.size() == 0) return gp;

    gp.reset();
    if (largestCoord < MAX_COORD_VALUE) {
      addSimpleSegments();
    } else {
      addClippedSegments();
    }

    // clear pathPoints to free up memory
    pathPoints.clear();

    return gp;
  }
 public void drawPolylines(Graphics2D g2) {
   int i, ipol, npoints, noffs;
   // draw GeneralPath (polyline)
   for (ipol = 0; ipol < numpolys; ipol++) {
     noffs = bufpol[ipol];
     npoints = bufpts[noffs + 1];
     if (npoints > 1) { // was 0, TS on 20.08.'12
       polyline.moveTo(bufpts[noffs + 2], bufpts[noffs + 3]);
       for (i = 1; i < npoints; i++) {
         polyline.lineTo(bufpts[noffs + 2 * i + 2], bufpts[noffs + 2 * i + 3]);
       }
       /* //TS on 20.08.'12
                       if (npoints == 1) {
                           polyline.lineTo(bufpts[noffs+2], bufpts[noffs+3]);
                       }
       */
       g2.setStroke(DatanGraphics.strokes[bufpts[noffs] - 1]);
       g2.setPaint(DatanGraphics.ct[bufpts[noffs]]);
       g2.draw(polyline);
       polyline.reset();
     }
   }
 }
  public void update() {
    super.update();

    // YCTRL could be implemented but then we had to check whether target is above or below source.
    if (target.isLeft()) {
      one = new Point2D.Float(start.x - XCTRL, start.y);
      two = new Point2D.Float(end.x + XCTRL, end.y);
    } else {
      one = new Point2D.Float(start.x + XCTRL, start.y);
      two = new Point2D.Float(end.x - XCTRL, end.y);
    }
    int w = getWidth() / 2 + 1;
    int w2 = w / 2;
    int dy1 = getSourceShift();
    line1.setCurve(
        start.x, start.y + dy1 - w, one.x, one.y + dy1 - w, two.x, two.y - w2, end.x, end.y);
    line2.setCurve(
        end.x, end.y, two.x, two.y + w2, one.x, one.y + dy1 + w, start.x, start.y + dy1 + w);
    graph.reset();
    graph.append(line1, true);
    graph.append(line2, true);
    graph.closePath();
  }
Esempio n. 7
0
  public void routeEdge(Graphics2D g2d, VisualEdge vEdge) {

    Rectangle fromvertexBounds;
    Rectangle tovertexBounds;
    GeneralPath drawPath;
    VisualVertex visualVertexA = vEdge.getVisualVertexA();
    VisualVertex visualVertexB = vEdge.getVisualVertexB();

    drawPath = new GeneralPath();
    ;

    fromvertexBounds = visualVertexA.getBounds();
    tovertexBounds = visualVertexB.getBounds();

    // Make sure to clear the GeneralPath() first. Otherwise, the edge's previous
    // path will be redrawn as well.
    drawPath.reset();

    // Start the line from the center of the vEdgertex
    drawPath.moveTo((float) fromvertexBounds.getCenterX(), (float) fromvertexBounds.getCenterY());
    drawPath.lineTo((float) tovertexBounds.getCenterX(), (float) tovertexBounds.getCenterY());
    vEdge.setShape(new VisualGraphComponentPath(drawPath));
  }
  /** Paints the <tt>visualEdge</tt>. No arrowhead is drawn. */
  public void paint(VisualGraphComponent component, Graphics2D g2d) {
    VisualEdge vEdge = (VisualEdge) component;
    Rectangle fromvertexBounds;
    Rectangle tovertexBounds;
    GeneralPath drawPath;
    VisualVertex visualVertexA = vEdge.getVisualVertexA();
    VisualVertex visualVertexB = vEdge.getVisualVertexB();
    GraphLayoutManager layoutmanager = vEdge.getVisualGraph().getGraphLayoutManager();

    drawPath = vEdge.getGeneralPath();

    // If there is no layoutmanager or there is one but the layout has not
    // been initialised, by default, let us route edges as straight lines.
    if (layoutmanager == null || (layoutmanager != null && !layoutmanager.isInitialized())) {

      fromvertexBounds = visualVertexA.getBounds();
      tovertexBounds = visualVertexB.getBounds();

      // Make sure to clear the GeneralPath() first. Otherwise, the edge's previous
      // path will be redrawn as well.
      drawPath.reset();

      // Start the line from the center of the vEdgertex
      drawPath.moveTo((float) fromvertexBounds.getCenterX(), (float) fromvertexBounds.getCenterY());
      drawPath.lineTo((float) tovertexBounds.getCenterX(), (float) tovertexBounds.getCenterY());
    } else {
      // Let the layout manager determine how the edge will be routed.
      layoutmanager.routeEdge(g2d, vEdge);
    }

    // Draw the line
    g2d.setColor(vEdge.getOutlinecolor());
    g2d.draw(drawPath);

    // Draw the edge label
    this.paintText(vEdge, g2d);
  }
Esempio n. 9
0
  /**
   * Le méthode <code>createShape</code> crée la forme qui sert à visualiser le contour de la zone
   * convexe.
   */
  public void createShape(Rectangle2D allocation) {
    if (boundaryPath0 != null) return;

    if (boundary == null) boundary = convexPolygonalZone.getBoundary();

    if (DEBUG)
      debug(
          "this = "
              + toString()
              + "\n\tboundary = "
              + boundary.toString()
              + "\n\tallocation="
              + allocation.toString());

    if (boundaryPath0 == null) boundaryPath0 = new GeneralPath();
    boundaryPath0.reset();
    if (boundary.subdivisionPoints.size() != 0) {
      // la frontière n'est pas une droite, mais comprend au moins un
      // point de sousdivision.
      boundaryPath1 = null;
      allocationIntersectionPath1 = null;

      PicPoint firstPointInInfinity = null;
      PicPoint secondPointInInfinity = null;
      PicPoint anglePoint = null;
      int i;
      if (boundary.isClosed()) {
        // pas de points à l'infini
        allocationIntersectionPath0 = null;
        allocationIntersectionPath1 = null;

        bounds.setFrameFromDiagonal(
            boundary.subdivisionPoints.get(0), boundary.subdivisionPoints.get(1));
        i = 0;
      } else {
        PointsInInfinity pointsInInfinity = new PointsInInfinity(allocation);
        firstPointInInfinity = pointsInInfinity.get(boundary.halfPlanes.getFirst(), +1);
        boundaryPath0.moveTo(firstPointInInfinity.getX(), firstPointInInfinity.getY());
        secondPointInInfinity = pointsInInfinity.get(boundary.halfPlanes.getLast(), -1);
        anglePoint = pointsInInfinity.getAnglePoint();
        bounds.setFrameFromDiagonal(firstPointInInfinity, secondPointInInfinity);
        i = 1;
      }
      for (PicPoint pt : boundary.subdivisionPoints) {
        if (i == 0) {
          boundaryPath0.moveTo(pt.getX(), pt.getY());
        } else {
          boundaryPath0.lineTo(pt.getX(), pt.getY());
          if (i > 1) bounds.add(pt);
        }
        ++i;
      }
      if (!boundary.isClosed()) {
        boundaryPath0.lineTo(secondPointInInfinity.getX(), secondPointInInfinity.getY());
        if (allocationIntersectionPath0 == null) allocationIntersectionPath0 = new GeneralPath();
        allocationIntersectionPath1 = null;
        allocationIntersectionPath0.reset();
        allocationIntersectionPath0.moveTo(
            firstPointInInfinity.getX(), firstPointInInfinity.getY());
        if (anglePoint != null)
          allocationIntersectionPath0.lineTo(anglePoint.getX(), anglePoint.getY());
        allocationIntersectionPath0.lineTo(
            secondPointInInfinity.getX(), secondPointInInfinity.getY());
      } else boundaryPath0.closePath();
      if (DEBUG) debug("boundaryPath0 = " + boundaryPath0.toString());
    } else if (boundary.halfPlanes.size() > 0) {
      // ici on n'a pas de point de sous-division, donc la zone convexe
      // est soit une bande, soit un demi-plan.
      PointsInInfinity pointsInInfinity0 = new PointsInInfinity(allocation);
      PicPoint firstPointInInfinity0 = pointsInInfinity0.get(boundary.halfPlanes.getFirst(), +1);
      PicPoint secondPointInInfinity0 = pointsInInfinity0.get(boundary.halfPlanes.getFirst(), -1);
      if (boundaryPath0 == null) boundaryPath0 = new GeneralPath();
      boundaryPath0.reset();
      boundaryPath0.moveTo(firstPointInInfinity0.getX(), firstPointInInfinity0.getY());
      boundaryPath0.lineTo(secondPointInInfinity0.getX(), secondPointInInfinity0.getY());

      if (boundary.halfPlanes.size() > 1) {
        // la zone convexe est une bande
        if (boundaryPath1 == null) boundaryPath1 = new GeneralPath();
        boundaryPath1.reset();
        boundaryPath1.moveTo(firstPointInInfinity0.getX(), firstPointInInfinity0.getY());
        PointsInInfinity pointsInInfinity1 = new PointsInInfinity(pointsInInfinity0);

        // Astuce : on prend le complémentaire de l'autre demi-plan de
        // sorte que les points d'angle tournent dans le même sens.
        ConvexPolygonalZone.HalfPlane complementLastHp =
            boundary.halfPlanes.getLast().dirCInverse();

        PicPoint firstPointInInfinity1 = pointsInInfinity1.get(complementLastHp, +1);
        PicPoint secondPointInInfinity1 = pointsInInfinity1.get(complementLastHp, -1);

        /*
         first0  first1	   (0) := boundaryPath0
          x	  (1) x	       (1) := allocationIntersectionPath0
          |		  |	   	   (2) := boundaryPath1
         	   (0)|>   	  |>   	   (3) :=  allocationIntersectionPath1
          |		  |(2)
          x	 (3)  x
        second0   second1

         */
        if (boundaryPath1 == null) boundaryPath1 = new GeneralPath();
        boundaryPath1.reset();
        // on fait trace de `second' vers `first' parce que on a pris
        // le demi plan complémentaire, donc l'ordre est inversé si on
        // veut continuer à tourner dans le même sens.
        boundaryPath1.moveTo(secondPointInInfinity1.getX(), secondPointInInfinity1.getY());
        boundaryPath1.lineTo(firstPointInInfinity1.getX(), firstPointInInfinity1.getY());

        if (allocationIntersectionPath0 == null) allocationIntersectionPath0 = new GeneralPath();
        allocationIntersectionPath0.reset();
        allocationIntersectionPath0.moveTo(
            firstPointInInfinity0.getX(), firstPointInInfinity0.getY());

        if (allocationIntersectionPath1 == null) allocationIntersectionPath1 = new GeneralPath();
        allocationIntersectionPath1.reset();
        // idem, ici il faut partir de `second' et non de `first'
        // toujours pourn la même raison qu'on a pris le demi-plan
        // complémentaire.
        allocationIntersectionPath1.moveTo(
            secondPointInInfinity1.getX(), secondPointInInfinity1.getY());

        PicPoint anglePoint0, anglePoint1;

        anglePoint1 = pointsInInfinity1.getAnglePoint();
        while ((anglePoint0 = pointsInInfinity0.getAnglePoint()) != null) {
          if (anglePoint1 != null && anglePoint0.equals(anglePoint1)) break;
          allocationIntersectionPath0.lineTo(anglePoint0.getX(), anglePoint0.getY());
        }
        allocationIntersectionPath0.lineTo(
            firstPointInInfinity1.getX(), firstPointInInfinity1.getY());

        if (anglePoint1 != null && anglePoint0 != null) {
          for (; ; ) {
            anglePoint0 = pointsInInfinity0.getAnglePoint();
            anglePoint1 = pointsInInfinity1.getAnglePoint();
            if (anglePoint1 == null) break;
            if (anglePoint0 == null) break;
            if (!anglePoint0.equals(anglePoint1)) break;
          }
          while (anglePoint0 != null) {
            allocationIntersectionPath1.lineTo(anglePoint0.getX(), anglePoint0.getY());
            anglePoint0 = pointsInInfinity0.getAnglePoint();
          }
        }

        allocationIntersectionPath1.lineTo(
            secondPointInInfinity0.getX(), secondPointInInfinity0.getY());
      } else {
        // la zone convexe est un demi-plan
        boundaryPath1 = null;
        allocationIntersectionPath1 = null;
        if (allocationIntersectionPath0 == null) allocationIntersectionPath0 = new GeneralPath();
        allocationIntersectionPath0.moveTo(
            firstPointInInfinity0.getX(), firstPointInInfinity0.getY());
        PicPoint anglePoint;
        while ((anglePoint = pointsInInfinity0.getAnglePoint()) != null) {
          allocationIntersectionPath0.lineTo(anglePoint.getX(), anglePoint.getY());
        }
        allocationIntersectionPath0.lineTo(
            secondPointInInfinity0.getX(), secondPointInInfinity0.getY());
      }
    }
  }
 @Override
 public void paint(Graphics g) {
   super.paint(g);
   // added by Markus Hohenwarter, BEGIN
   Graphics2D g2 = (Graphics2D) g;
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
   // added by Markus Hohenwarter, END
   //		 Michael Borcherds 2007-10-13 BEGIN
   //		g2.setColor(getBackground());
   if (getBackground() == Color.LIGHT_GRAY) g2.setColor(Color.LIGHT_GRAY);
   else g2.setColor(Color.WHITE);
   //		 Michael Borcherds 2007-10-13 END
   g2.fillRect(0, 0, getWidth(), getHeight());
   g2.setColor(Color.BLACK);
   g2.drawLine(13, 27, 67, 27);
   g2.drawLine(13, 27, 67, 3);
   arc.setArcByCenter(13, 27, 40, 0, 24, Arc2D.OPEN);
   g2.draw(arc);
   switch (id) {
     case GeoElement.DECORATION_ANGLE_TWO_ARCS:
       arc.setArcByCenter(13, 27, 35, 0, 24, Arc2D.OPEN);
       g2.draw(arc);
       break;
     case GeoElement.DECORATION_ANGLE_THREE_ARCS:
       arc.setArcByCenter(13, 27, 35, 0, 24, Arc2D.OPEN);
       g2.draw(arc);
       arc.setArcByCenter(13, 27, 45, 0, 24, Arc2D.OPEN);
       g2.draw(arc);
       break;
     case GeoElement.DECORATION_ANGLE_ONE_TICK:
       drawTick(Math.toRadians(12));
       g2.draw(tick);
       break;
     case GeoElement.DECORATION_ANGLE_TWO_TICKS:
       drawTick(Math.toRadians(9.6));
       g2.draw(tick);
       drawTick(Math.toRadians(14.4));
       g2.draw(tick);
       break;
     case GeoElement.DECORATION_ANGLE_THREE_TICKS:
       drawTick(Math.toRadians(12));
       g2.draw(tick);
       drawTick(Math.toRadians(7));
       g2.draw(tick);
       drawTick(Math.toRadians(16));
       g2.draw(tick);
       break;
       //			 Michael Borcherds 2007-11-19 BEGIN
     case GeoElement.DECORATION_ANGLE_ARROW_ANTICLOCKWISE:
       polygon.reset();
       polygon.moveTo(56, 15);
       polygon.lineTo(48, 19);
       polygon.lineTo(50, 10);
       polygon.lineTo(56, 15);
       polygon.closePath();
       g2.fill(polygon);
       break;
     case GeoElement.DECORATION_ANGLE_ARROW_CLOCKWISE:
       polygon.reset();
       polygon.moveTo(54, 27);
       polygon.lineTo(48, 20);
       polygon.lineTo(56, 18);
       polygon.lineTo(54, 27);
       polygon.closePath();
       g2.fill(polygon);
       break;
       //			 Michael Borcherds 2007-11-19 END
   }
 }
  @Override
  public void paint(Graphics g) {
    super.paint(g);
    Graphics2D g2 = (Graphics2D) g;
    GGraphics2DD.setAntialiasing(g2);

    // g2.setColor(getBackground());
    if (getBackground() == Color.LIGHT_GRAY) {
      g2.setColor(Color.LIGHT_GRAY);
    } else {
      g2.setColor(Color.WHITE);
    }

    g2.fillRect(0, 0, getWidth(), getHeight());
    g2.setColor(Color.BLACK);
    g2.drawLine(13, 27, 67, 27);
    g2.drawLine(13, 27, 67, 3);
    arc.setArcByCenter(13, 27, 40, 0, 24, Arc2D.OPEN);
    g2.draw(arc);
    switch (id) {
      case GeoElement.DECORATION_ANGLE_TWO_ARCS:
        arc.setArcByCenter(13, 27, 35, 0, 24, Arc2D.OPEN);
        g2.draw(arc);
        break;
      case GeoElement.DECORATION_ANGLE_THREE_ARCS:
        arc.setArcByCenter(13, 27, 35, 0, 24, Arc2D.OPEN);
        g2.draw(arc);
        arc.setArcByCenter(13, 27, 45, 0, 24, Arc2D.OPEN);
        g2.draw(arc);
        break;
      case GeoElement.DECORATION_ANGLE_ONE_TICK:
        drawTick(Math.toRadians(12));
        g2.draw(tick);
        break;
      case GeoElement.DECORATION_ANGLE_TWO_TICKS:
        drawTick(Math.toRadians(9.6));
        g2.draw(tick);
        drawTick(Math.toRadians(14.4));
        g2.draw(tick);
        break;
      case GeoElement.DECORATION_ANGLE_THREE_TICKS:
        drawTick(Math.toRadians(12));
        g2.draw(tick);
        drawTick(Math.toRadians(7));
        g2.draw(tick);
        drawTick(Math.toRadians(16));
        g2.draw(tick);
        break;
      case GeoElement.DECORATION_ANGLE_ARROW_ANTICLOCKWISE:
        polygon.reset();
        polygon.moveTo(56, 15);
        polygon.lineTo(48, 19);
        polygon.lineTo(50, 10);
        polygon.lineTo(56, 15);
        polygon.closePath();
        g2.fill(polygon);
        break;
      case GeoElement.DECORATION_ANGLE_ARROW_CLOCKWISE:
        polygon.reset();
        polygon.moveTo(54, 27);
        polygon.lineTo(48, 20);
        polygon.lineTo(56, 18);
        polygon.lineTo(54, 27);
        polygon.closePath();
        g2.fill(polygon);
        break;
    }
  }
Esempio n. 12
0
  public void run() {
    Thread me = Thread.currentThread();
    while (getSize().width <= 0) {
      try {
        anim.sleep(500);
      } catch (InterruptedException e) {
        return;
      }
    }

    Graphics2D g2d = null;
    Graphics2D BufferG2D = null;
    Graphics2D ScreenG2D = null;
    BasicStroke solid = new BasicStroke(9.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 9.0f);
    GeneralPath gp = new GeneralPath(GeneralPath.WIND_NON_ZERO);
    int rule = AlphaComposite.SRC_OVER;
    AlphaComposite opaque = AlphaComposite.SrcOver;
    AlphaComposite blend = AlphaComposite.getInstance(rule, 0.9f);
    AlphaComposite set = AlphaComposite.Src;
    int frame = 0;
    int frametmp = 0;
    Dimension oldSize = getSize();
    Shape clippath = null;
    while (anim == me) {
      Dimension size = getSize();
      if (size.width != oldSize.width || size.height != oldSize.height) {
        img = null;
        clippath = null;
        if (BufferG2D != null) {
          BufferG2D.dispose();
          BufferG2D = null;
        }
        if (ScreenG2D != null) {
          ScreenG2D.dispose();
          ScreenG2D = null;
        }
      }
      oldSize = size;

      if (img == null) {
        img = (BufferedImage) createImage(size.width, size.height);
      }

      if (BufferG2D == null) {
        BufferG2D = img.createGraphics();
        BufferG2D.setRenderingHint(
            RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT);
        BufferG2D.setClip(clippath);
      }
      g2d = BufferG2D;

      float[] ctrlpts;
      for (int i = 0; i < animpts.length; i += 2) {
        animate(animpts, deltas, i + 0, size.width);
        animate(animpts, deltas, i + 1, size.height);
      }
      ctrlpts = animpts;
      int len = ctrlpts.length;
      gp.reset();
      int dir = 0;
      float prevx = ctrlpts[len - 2];
      float prevy = ctrlpts[len - 1];
      float curx = ctrlpts[0];
      float cury = ctrlpts[1];
      float midx = (curx + prevx) / 2.0f;
      float midy = (cury + prevy) / 2.0f;
      gp.moveTo(midx, midy);
      for (int i = 2; i <= ctrlpts.length; i += 2) {
        float x1 = (midx + curx) / 2.0f;
        float y1 = (midy + cury) / 2.0f;
        prevx = curx;
        prevy = cury;
        if (i < ctrlpts.length) {
          curx = ctrlpts[i + 0];
          cury = ctrlpts[i + 1];
        } else {
          curx = ctrlpts[0];
          cury = ctrlpts[1];
        }
        midx = (curx + prevx) / 2.0f;
        midy = (cury + prevy) / 2.0f;
        float x2 = (prevx + midx) / 2.0f;
        float y2 = (prevy + midy) / 2.0f;
        gp.curveTo(x1, y1, x2, y2, midx, midy);
      }
      gp.closePath();

      g2d.setComposite(set);
      g2d.setBackground(backgroundColor);
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);

      if (bgChanged || bounds == null) {
        bounds = new Rectangle(0, 0, getWidth(), getHeight());
        bgChanged = false;
      }
      // g2d.clearRect(bounds.x-5, bounds.y-5, bounds.x + bounds.width + 5, bounds.y + bounds.height
      // + 5);
      g2d.clearRect(0, 0, getWidth(), getHeight());

      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2d.setColor(outerColor);
      g2d.setComposite(opaque);
      g2d.setStroke(solid);
      g2d.draw(gp);
      g2d.setPaint(gradient);

      if (!bgChanged) {
        bounds = gp.getBounds();
      } else {
        bounds = new Rectangle(0, 0, getWidth(), getHeight());
        bgChanged = false;
      }
      gradient =
          new GradientPaint(
              bounds.x,
              bounds.y,
              gradientColorA,
              bounds.x + bounds.width,
              bounds.y + bounds.height,
              gradientColorB,
              true);
      g2d.setComposite(blend);
      g2d.fill(gp);

      if (g2d == BufferG2D) {
        repaint();
      }
      ++frame;
      Thread.yield();
    }
    if (g2d != null) {
      g2d.dispose();
    }
  }