modules/graphics/src/main/java/javafx/scene/canvas/GraphicsContext.java

Print this page




 220             ctx.setLineJoin(linejoin);
 221             ctx.setMiterLimit(miterlimit);
 222             GrowableDataBuffer buf = ctx.getBuffer();
 223             while (ctx.curState.numClipPaths > numClipPaths) {
 224                 ctx.curState.numClipPaths--;
 225                 ctx.clipStack.removeLast();
 226                 buf.putByte(NGCanvas.POP_CLIP);
 227             }
 228             ctx.setFillRule(fillRule);
 229             ctx.setFont(font);
 230             ctx.setTextAlign(textalign);
 231             ctx.setTextBaseline(textbaseline);
 232             ctx.setEffect(effect);
 233         }
 234     }
 235 
 236     private GrowableDataBuffer getBuffer() {
 237         return theCanvas.getBuffer();
 238     }
 239 
 240     private static float coords[] = new float[6];
 241     private static final byte pgtype[] = {
 242         NGCanvas.MOVETO,
 243         NGCanvas.LINETO,
 244         NGCanvas.QUADTO,
 245         NGCanvas.CUBICTO,
 246         NGCanvas.CLOSEPATH,
 247     };
 248     private static final int numsegs[] = { 2, 2, 4, 6, 0, };
 249 
 250     private void markPathDirty() {
 251         pathDirty = true;
 252     }
 253 
 254     private void writePath(byte command) {
 255         updateTransform();
 256         GrowableDataBuffer buf = getBuffer();
 257         if (pathDirty) {
 258             buf.putByte(NGCanvas.PATHSTART);
 259             PathIterator pi = path.getPathIterator(null);
 260             while (!pi.isDone()) {


 568 
 569     /**
 570      * Scales the current transform by x, y.
 571      * @param x value to scale in the x axis.
 572      * @param y value to scale in the y axis.
 573      */
 574     public void scale(double x, double y) {
 575         curState.transform.scale(x, y);
 576         txdirty = true;
 577     }
 578 
 579     /**
 580      * Rotates the current transform in degrees.
 581      * @param degrees value in degrees to rotate the current transform.
 582      */
 583     public void rotate(double degrees) {
 584         curState.transform.rotate(Math.toRadians(degrees));
 585         txdirty = true;
 586     }
 587 
 588     private static Affine2D scratchTX = new Affine2D();
 589     /**
 590      * Concatenates the input with the current transform.
 591      * 
 592      * @param mxx - the X coordinate scaling element of the 3x4 matrix
 593      * @param myx - the Y coordinate shearing element of the 3x4 matrix
 594      * @param mxy - the X coordinate shearing element of the 3x4 matrix
 595      * @param myy - the Y coordinate scaling element of the 3x4 matrix
 596      * @param mxt - the X coordinate translation element of the 3x4 matrix
 597      * @param myt - the Y coordinate translation element of the 3x4 matrix
 598      */
 599     public void transform(double mxx, double myx,
 600                           double mxy, double myy,
 601                           double mxt, double myt)
 602     {
 603         scratchTX.setTransform(mxx, myx,
 604                                mxy, myy,
 605                                mxt, myt);
 606         curState.transform.concatenate(scratchTX);
 607         txdirty = true;
 608     }
 609     
 610     /**
 611      * Concatenates the input with the current transform. Only 2D transforms are
 612      * supported. The only values used are the X and Y scaling, translation, and
 613      * shearing components of a transform. A {@code null} value is treated as identity.
 614      * 
 615      * @param xform The affine to be concatenated with the current transform or null.
 616      */
 617     public void transform(Affine xform) {
 618         if (xform == null) return;
 619         scratchTX.setTransform(xform.getMxx(), xform.getMyx(),
 620                                xform.getMxy(), xform.getMyy(),
 621                                xform.getTx(), xform.getTy());
 622         curState.transform.concatenate(scratchTX);
 623         txdirty = true;
 624     }
 625 
 626     /**
 627      * Sets the current transform.
 628      * @param mxx - the X coordinate scaling element of the 3x4 matrix
 629      * @param myx - the Y coordinate shearing element of the 3x4 matrix
 630      * @param mxy - the X coordinate shearing element of the 3x4 matrix
 631      * @param myy - the Y coordinate scaling element of the 3x4 matrix
 632      * @param mxt - the X coordinate translation element of the 3x4 matrix
 633      * @param myt - the Y coordinate translation element of the 3x4 matrix 
 634      */
 635     public void setTransform(double mxx, double myx,
 636                              double mxy, double myy,
 637                              double mxt, double myt)
 638     {
 639         curState.transform.setTransform(mxx, myx,
 640                                         mxy, myy,
 641                                         mxt, myt);
 642         txdirty = true;


 703      * @param alpha value in the range {@code 0.0-1.0}. The value is clamped if it is 
 704      * out of range.
 705      */
 706     public void setGlobalAlpha(double alpha) {
 707         if (curState.globalAlpha != alpha) {
 708             curState.globalAlpha = alpha;
 709             alpha = (alpha > 1.0) ? 1.0 : (alpha < 0.0) ? 0.0 : alpha;
 710             writeParam(alpha, NGCanvas.GLOBAL_ALPHA);
 711         }
 712     }
 713     
 714     /**
 715      * Gets the current global alpha.
 716      * 
 717      * @return the current global alpha. 
 718      */
 719     public double getGlobalAlpha() {
 720         return curState.globalAlpha;
 721     }
 722     
 723     private static Blend TMP_BLEND = new Blend(BlendMode.SRC_OVER); 
 724     /**
 725      * Sets the global blend mode.
 726      * A {@code null} value will be ignored and the current value will remain unchanged.
 727      * 
 728      * @param op the {@code BlendMode} that will be set or null.
 729      */
 730     public void setGlobalBlendMode(BlendMode op) {
 731         if (op != null && op != curState.blendop) {
 732             GrowableDataBuffer buf = getBuffer();           
 733             curState.blendop = op; 
 734             TMP_BLEND.setMode(op);
 735             TMP_BLEND.impl_sync();
 736             buf.putByte(NGCanvas.COMP_MODE);
 737             buf.putObject(((com.sun.scenario.effect.Blend)TMP_BLEND.impl_getImpl()).getMode());
 738         }
 739     }
 740     
 741     /**
 742      * Gets the global blend mode.
 743      * 
 744      * @return the global {@code BlendMode} of the current state.
 745      */
 746     public BlendMode getGlobalBlendMode() {
 747         return curState.blendop;
 748     }
 749 
 750     /**
 751      * Sets the current fill attribute. This method affects the paint used for any
 752      * method with "fill" in it. For Example, fillRect(...), fillOval(...).
 753      * A {@code null} value will be ignored and the current value will remain unchanged.
 754      * 
 755      * @param p The {@code Paint} to be used as the fill {@code Paint} or null.
 756      */
 757     public void setFill(Paint p) {


1324             double cosqtrarc = Math.sqrt((1.0 + coshalfarc) / 2.0);
1325             double cv = 4.0 / 3.0 * sinqtrarc / (1.0 + cosqtrarc);
1326             if (ccw) cv = -cv;
1327             double midratio = radius / Math.sqrt(lenratioden);
1328             double midarcx = cx + (x1 - mx) * midratio;
1329             double midarcy = cy + (y1 - my) * midratio;
1330             double cpx0 = tx0 - cv * (ty0 - cy);
1331             double cpy0 = ty0 + cv * (tx0 - cx);
1332             double cpx1 = midarcx + cv * (midarcy - cy);
1333             double cpy1 = midarcy - cv * (midarcx - cx);
1334             bezierCurveTo(cpx0, cpy0, cpx1, cpy1, midarcx, midarcy);
1335             cpx0 = midarcx - cv * (midarcy - cy);
1336             cpy0 = midarcy + cv * (midarcx - cx);
1337             cpx1 = tx1 + cv * (ty1 - cy);
1338             cpy1 = ty1 - cv * (tx1 - cx);
1339             bezierCurveTo(cpx0, cpy0, cpx1, cpy1, tx1, ty1);
1340         }
1341         return true;
1342     }
1343 
1344     private static final Arc2D TEMP_ARC = new Arc2D();
1345     /**
1346      * Adds path elements to the current path to make an arc that uses Euclidean
1347      * degrees. This Euclidean orientation sweeps from East to North, then West,
1348      * then South, then back to East. 
1349      *
1350      * @param centerX the center x position of the arc.
1351      * @param centerY the center y position of the arc.
1352      * @param radiusX the x radius of the arc.
1353      * @param radiusY the y radius of the arc.
1354      * @param startAngle the starting angle of the arc in the range {@code 0-360.0}
1355      * @param length  the length of the baseline of the arc.
1356      */
1357     public void arc(double centerX, double centerY,
1358                     double radiusX, double radiusY,
1359                     double startAngle, double length)
1360     {
1361         TEMP_ARC.setArc((float)(centerX - radiusX), // x
1362                         (float)(centerY - radiusY), // y
1363                         (float)(radiusX * 2.0), // w
1364                         (float)(radiusY * 2.0), // h
1365                         (float)startAngle,
1366                         (float)length,
1367                         Arc2D.OPEN);
1368         path.append(TEMP_ARC.getPathIterator(curState.transform), true);
1369         markPathDirty();
1370     }
1371 
1372     /**
1373      * Adds path elements to the current path to make a rectangle.
1374      * 
1375      * @param x x position of the upper left corner of the rectangle.
1376      * @param y y position of the upper left corner of the rectangle.
1377      * @param w width of the rectangle.
1378      * @param h height of the rectangle.
1379      */
1380     public void rect(double x, double y, double w, double h) {
1381         coords[0] = (float) x;
1382         coords[1] = (float) y;
1383         coords[2] = (float) w;
1384         coords[3] = (float) 0;
1385         coords[4] = (float) 0;
1386         coords[5] = (float) h;
1387         curState.transform.deltaTransform(coords, 0, coords, 0, 3);
1388         float x0 = coords[0] + (float) curState.transform.getMxt();




 220             ctx.setLineJoin(linejoin);
 221             ctx.setMiterLimit(miterlimit);
 222             GrowableDataBuffer buf = ctx.getBuffer();
 223             while (ctx.curState.numClipPaths > numClipPaths) {
 224                 ctx.curState.numClipPaths--;
 225                 ctx.clipStack.removeLast();
 226                 buf.putByte(NGCanvas.POP_CLIP);
 227             }
 228             ctx.setFillRule(fillRule);
 229             ctx.setFont(font);
 230             ctx.setTextAlign(textalign);
 231             ctx.setTextBaseline(textbaseline);
 232             ctx.setEffect(effect);
 233         }
 234     }
 235 
 236     private GrowableDataBuffer getBuffer() {
 237         return theCanvas.getBuffer();
 238     }
 239 
 240     private float coords[] = new float[6];
 241     private static final byte pgtype[] = {
 242         NGCanvas.MOVETO,
 243         NGCanvas.LINETO,
 244         NGCanvas.QUADTO,
 245         NGCanvas.CUBICTO,
 246         NGCanvas.CLOSEPATH,
 247     };
 248     private static final int numsegs[] = { 2, 2, 4, 6, 0, };
 249 
 250     private void markPathDirty() {
 251         pathDirty = true;
 252     }
 253 
 254     private void writePath(byte command) {
 255         updateTransform();
 256         GrowableDataBuffer buf = getBuffer();
 257         if (pathDirty) {
 258             buf.putByte(NGCanvas.PATHSTART);
 259             PathIterator pi = path.getPathIterator(null);
 260             while (!pi.isDone()) {


 568 
 569     /**
 570      * Scales the current transform by x, y.
 571      * @param x value to scale in the x axis.
 572      * @param y value to scale in the y axis.
 573      */
 574     public void scale(double x, double y) {
 575         curState.transform.scale(x, y);
 576         txdirty = true;
 577     }
 578 
 579     /**
 580      * Rotates the current transform in degrees.
 581      * @param degrees value in degrees to rotate the current transform.
 582      */
 583     public void rotate(double degrees) {
 584         curState.transform.rotate(Math.toRadians(degrees));
 585         txdirty = true;
 586     }
 587 

 588     /**
 589      * Concatenates the input with the current transform.
 590      * 
 591      * @param mxx - the X coordinate scaling element of the 3x4 matrix
 592      * @param myx - the Y coordinate shearing element of the 3x4 matrix
 593      * @param mxy - the X coordinate shearing element of the 3x4 matrix
 594      * @param myy - the Y coordinate scaling element of the 3x4 matrix
 595      * @param mxt - the X coordinate translation element of the 3x4 matrix
 596      * @param myt - the Y coordinate translation element of the 3x4 matrix
 597      */
 598     public void transform(double mxx, double myx,
 599                           double mxy, double myy,
 600                           double mxt, double myt)
 601     {
 602         curState.transform.concatenate(mxx, mxy, mxt,
 603                                        myx, myy, myt);


 604         txdirty = true;
 605     }
 606     
 607     /**
 608      * Concatenates the input with the current transform. Only 2D transforms are
 609      * supported. The only values used are the X and Y scaling, translation, and
 610      * shearing components of a transform. A {@code null} value is treated as identity.
 611      * 
 612      * @param xform The affine to be concatenated with the current transform or null.
 613      */
 614     public void transform(Affine xform) {
 615         if (xform == null) return;
 616         curState.transform.concatenate(xform.getMxx(), xform.getMxy(), xform.getTx(),
 617                                        xform.getMyx(), xform.getMyy(), xform.getTy());


 618         txdirty = true;
 619     }
 620 
 621     /**
 622      * Sets the current transform.
 623      * @param mxx - the X coordinate scaling element of the 3x4 matrix
 624      * @param myx - the Y coordinate shearing element of the 3x4 matrix
 625      * @param mxy - the X coordinate shearing element of the 3x4 matrix
 626      * @param myy - the Y coordinate scaling element of the 3x4 matrix
 627      * @param mxt - the X coordinate translation element of the 3x4 matrix
 628      * @param myt - the Y coordinate translation element of the 3x4 matrix 
 629      */
 630     public void setTransform(double mxx, double myx,
 631                              double mxy, double myy,
 632                              double mxt, double myt)
 633     {
 634         curState.transform.setTransform(mxx, myx,
 635                                         mxy, myy,
 636                                         mxt, myt);
 637         txdirty = true;


 698      * @param alpha value in the range {@code 0.0-1.0}. The value is clamped if it is 
 699      * out of range.
 700      */
 701     public void setGlobalAlpha(double alpha) {
 702         if (curState.globalAlpha != alpha) {
 703             curState.globalAlpha = alpha;
 704             alpha = (alpha > 1.0) ? 1.0 : (alpha < 0.0) ? 0.0 : alpha;
 705             writeParam(alpha, NGCanvas.GLOBAL_ALPHA);
 706         }
 707     }
 708     
 709     /**
 710      * Gets the current global alpha.
 711      * 
 712      * @return the current global alpha. 
 713      */
 714     public double getGlobalAlpha() {
 715         return curState.globalAlpha;
 716     }
 717 

 718     /**
 719      * Sets the global blend mode.
 720      * A {@code null} value will be ignored and the current value will remain unchanged.
 721      * 
 722      * @param op the {@code BlendMode} that will be set or null.
 723      */
 724     public void setGlobalBlendMode(BlendMode op) {
 725         if (op != null && op != curState.blendop) {
 726             GrowableDataBuffer buf = getBuffer();           
 727             curState.blendop = op; 


 728             buf.putByte(NGCanvas.COMP_MODE);
 729             buf.putObject(Blend.impl_getToolkitMode(op));
 730         }
 731     }
 732     
 733     /**
 734      * Gets the global blend mode.
 735      * 
 736      * @return the global {@code BlendMode} of the current state.
 737      */
 738     public BlendMode getGlobalBlendMode() {
 739         return curState.blendop;
 740     }
 741 
 742     /**
 743      * Sets the current fill attribute. This method affects the paint used for any
 744      * method with "fill" in it. For Example, fillRect(...), fillOval(...).
 745      * A {@code null} value will be ignored and the current value will remain unchanged.
 746      * 
 747      * @param p The {@code Paint} to be used as the fill {@code Paint} or null.
 748      */
 749     public void setFill(Paint p) {


1316             double cosqtrarc = Math.sqrt((1.0 + coshalfarc) / 2.0);
1317             double cv = 4.0 / 3.0 * sinqtrarc / (1.0 + cosqtrarc);
1318             if (ccw) cv = -cv;
1319             double midratio = radius / Math.sqrt(lenratioden);
1320             double midarcx = cx + (x1 - mx) * midratio;
1321             double midarcy = cy + (y1 - my) * midratio;
1322             double cpx0 = tx0 - cv * (ty0 - cy);
1323             double cpy0 = ty0 + cv * (tx0 - cx);
1324             double cpx1 = midarcx + cv * (midarcy - cy);
1325             double cpy1 = midarcy - cv * (midarcx - cx);
1326             bezierCurveTo(cpx0, cpy0, cpx1, cpy1, midarcx, midarcy);
1327             cpx0 = midarcx - cv * (midarcy - cy);
1328             cpy0 = midarcy + cv * (midarcx - cx);
1329             cpx1 = tx1 + cv * (ty1 - cy);
1330             cpy1 = ty1 - cv * (tx1 - cx);
1331             bezierCurveTo(cpx0, cpy0, cpx1, cpy1, tx1, ty1);
1332         }
1333         return true;
1334     }
1335 

1336     /**
1337      * Adds path elements to the current path to make an arc that uses Euclidean
1338      * degrees. This Euclidean orientation sweeps from East to North, then West,
1339      * then South, then back to East. 
1340      *
1341      * @param centerX the center x position of the arc.
1342      * @param centerY the center y position of the arc.
1343      * @param radiusX the x radius of the arc.
1344      * @param radiusY the y radius of the arc.
1345      * @param startAngle the starting angle of the arc in the range {@code 0-360.0}
1346      * @param length  the length of the baseline of the arc.
1347      */
1348     public void arc(double centerX, double centerY,
1349                     double radiusX, double radiusY,
1350                     double startAngle, double length)
1351     {
1352         Arc2D arc = new Arc2D((float) (centerX - radiusX), // x
1353                               (float) (centerY - radiusY), // y
1354                               (float) (radiusX * 2.0), // w
1355                               (float) (radiusY * 2.0), // h
1356                               (float) startAngle,
1357                               (float) length,
1358                               Arc2D.OPEN);
1359         path.append(arc.getPathIterator(curState.transform), true);
1360         markPathDirty();
1361     }
1362 
1363     /**
1364      * Adds path elements to the current path to make a rectangle.
1365      * 
1366      * @param x x position of the upper left corner of the rectangle.
1367      * @param y y position of the upper left corner of the rectangle.
1368      * @param w width of the rectangle.
1369      * @param h height of the rectangle.
1370      */
1371     public void rect(double x, double y, double w, double h) {
1372         coords[0] = (float) x;
1373         coords[1] = (float) y;
1374         coords[2] = (float) w;
1375         coords[3] = (float) 0;
1376         coords[4] = (float) 0;
1377         coords[5] = (float) h;
1378         curState.transform.deltaTransform(coords, 0, coords, 0, 3);
1379         float x0 = coords[0] + (float) curState.transform.getMxt();