src/java.desktop/share/classes/sun/java2d/marlin/DHelpers.java
changeset 48284 fd7fbc929001
parent 47216 71c04702a3d5
child 49496 1ea202af7a97
equal deleted inserted replaced
48283:da1b57b17101 48284:fd7fbc929001
    24  */
    24  */
    25 
    25 
    26 package sun.java2d.marlin;
    26 package sun.java2d.marlin;
    27 
    27 
    28 import static java.lang.Math.PI;
    28 import static java.lang.Math.PI;
    29 import static java.lang.Math.cos;
    29 import java.util.Arrays;
    30 import static java.lang.Math.sqrt;
    30 import sun.java2d.marlin.stats.Histogram;
    31 import static java.lang.Math.cbrt;
    31 import sun.java2d.marlin.stats.StatLong;
    32 import static java.lang.Math.acos;
       
    33 
    32 
    34 final class DHelpers implements MarlinConst {
    33 final class DHelpers implements MarlinConst {
    35 
    34 
    36     private DHelpers() {
    35     private DHelpers() {
    37         throw new Error("This is a non instantiable class");
    36         throw new Error("This is a non instantiable class");
   113         double D = q * q + cb_p;
   112         double D = q * q + cb_p;
   114 
   113 
   115         int num;
   114         int num;
   116         if (D < 0.0d) {
   115         if (D < 0.0d) {
   117             // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method
   116             // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method
   118             final double phi = (1.0d/3.0d) * acos(-q / sqrt(-cb_p));
   117             final double phi = (1.0d/3.0d) * Math.acos(-q / Math.sqrt(-cb_p));
   119             final double t = 2.0d * sqrt(-p);
   118             final double t = 2.0d * Math.sqrt(-p);
   120 
   119 
   121             pts[ off+0 ] = ( t * cos(phi));
   120             pts[ off+0 ] = ( t * Math.cos(phi));
   122             pts[ off+1 ] = (-t * cos(phi + (PI / 3.0d)));
   121             pts[ off+1 ] = (-t * Math.cos(phi + (PI / 3.0d)));
   123             pts[ off+2 ] = (-t * cos(phi - (PI / 3.0d)));
   122             pts[ off+2 ] = (-t * Math.cos(phi - (PI / 3.0d)));
   124             num = 3;
   123             num = 3;
   125         } else {
   124         } else {
   126             final double sqrt_D = sqrt(D);
   125             final double sqrt_D = Math.sqrt(D);
   127             final double u = cbrt(sqrt_D - q);
   126             final double u =   Math.cbrt(sqrt_D - q);
   128             final double v = - cbrt(sqrt_D + q);
   127             final double v = - Math.cbrt(sqrt_D + q);
   129 
   128 
   130             pts[ off ] = (u + v);
   129             pts[ off ] = (u + v);
   131             num = 1;
   130             num = 1;
   132 
   131 
   133             if (within(D, 0.0d, 1e-8d)) {
   132             if (within(D, 0.0d, 1e-8d)) {
   167             if (nums[i] >= a && nums[i] < b) {
   166             if (nums[i] >= a && nums[i] < b) {
   168                 nums[ret++] = nums[i];
   167                 nums[ret++] = nums[i];
   169             }
   168             }
   170         }
   169         }
   171         return ret;
   170         return ret;
   172     }
       
   173 
       
   174     static double polyLineLength(double[] poly, final int off, final int nCoords) {
       
   175         assert nCoords % 2 == 0 && poly.length >= off + nCoords : "";
       
   176         double acc = 0.0d;
       
   177         for (int i = off + 2; i < off + nCoords; i += 2) {
       
   178             acc += linelen(poly[i], poly[i+1], poly[i-2], poly[i-1]);
       
   179         }
       
   180         return acc;
       
   181     }
   171     }
   182 
   172 
   183     static double linelen(double x1, double y1, double x2, double y2) {
   173     static double linelen(double x1, double y1, double x2, double y2) {
   184         final double dx = x2 - x1;
   174         final double dx = x2 - x1;
   185         final double dy = y2 - y1;
   175         final double dy = y2 - y1;
   431         case 6:
   421         case 6:
   432             subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff);
   422             subdivideQuadAt(t, src, srcoff, left, leftoff, right, rightoff);
   433             return;
   423             return;
   434         }
   424         }
   435     }
   425     }
       
   426 
       
   427     // From sun.java2d.loops.GeneralRenderer:
       
   428 
       
   429     static int outcode(final double x, final double y,
       
   430                        final double[] clipRect)
       
   431     {
       
   432         int code;
       
   433         if (y < clipRect[0]) {
       
   434             code = OUTCODE_TOP;
       
   435         } else if (y >= clipRect[1]) {
       
   436             code = OUTCODE_BOTTOM;
       
   437         } else {
       
   438             code = 0;
       
   439         }
       
   440         if (x < clipRect[2]) {
       
   441             code |= OUTCODE_LEFT;
       
   442         } else if (x >= clipRect[3]) {
       
   443             code |= OUTCODE_RIGHT;
       
   444         }
       
   445         return code;
       
   446     }
       
   447 
       
   448     // a stack of polynomial curves where each curve shares endpoints with
       
   449     // adjacent ones.
       
   450     static final class PolyStack {
       
   451         private static final byte TYPE_LINETO  = (byte) 0;
       
   452         private static final byte TYPE_QUADTO  = (byte) 1;
       
   453         private static final byte TYPE_CUBICTO = (byte) 2;
       
   454 
       
   455         // curves capacity = edges count (8192) = edges x 2 (coords)
       
   456         private static final int INITIAL_CURVES_COUNT = INITIAL_EDGES_COUNT << 1;
       
   457 
       
   458         // types capacity = edges count (4096)
       
   459         private static final int INITIAL_TYPES_COUNT = INITIAL_EDGES_COUNT;
       
   460 
       
   461         double[] curves;
       
   462         int end;
       
   463         byte[] curveTypes;
       
   464         int numCurves;
       
   465 
       
   466         // curves ref (dirty)
       
   467         final DoubleArrayCache.Reference curves_ref;
       
   468         // curveTypes ref (dirty)
       
   469         final ByteArrayCache.Reference curveTypes_ref;
       
   470 
       
   471         // used marks (stats only)
       
   472         int curveTypesUseMark;
       
   473         int curvesUseMark;
       
   474 
       
   475         private final StatLong stat_polystack_types;
       
   476         private final StatLong stat_polystack_curves;
       
   477         private final Histogram hist_polystack_curves;
       
   478         private final StatLong stat_array_polystack_curves;
       
   479         private final StatLong stat_array_polystack_curveTypes;
       
   480 
       
   481         PolyStack(final DRendererContext rdrCtx) {
       
   482             this(rdrCtx, null, null, null, null, null);
       
   483         }
       
   484 
       
   485         PolyStack(final DRendererContext rdrCtx,
       
   486                   final StatLong stat_polystack_types,
       
   487                   final StatLong stat_polystack_curves,
       
   488                   final Histogram hist_polystack_curves,
       
   489                   final StatLong stat_array_polystack_curves,
       
   490                   final StatLong stat_array_polystack_curveTypes)
       
   491         {
       
   492             curves_ref = rdrCtx.newDirtyDoubleArrayRef(INITIAL_CURVES_COUNT); // 32K
       
   493             curves     = curves_ref.initial;
       
   494 
       
   495             curveTypes_ref = rdrCtx.newDirtyByteArrayRef(INITIAL_TYPES_COUNT); // 4K
       
   496             curveTypes     = curveTypes_ref.initial;
       
   497             numCurves = 0;
       
   498             end = 0;
       
   499 
       
   500             if (DO_STATS) {
       
   501                 curveTypesUseMark = 0;
       
   502                 curvesUseMark = 0;
       
   503             }
       
   504             this.stat_polystack_types = stat_polystack_types;
       
   505             this.stat_polystack_curves = stat_polystack_curves;
       
   506             this.hist_polystack_curves = hist_polystack_curves;
       
   507             this.stat_array_polystack_curves = stat_array_polystack_curves;
       
   508             this.stat_array_polystack_curveTypes = stat_array_polystack_curveTypes;
       
   509         }
       
   510 
       
   511         /**
       
   512          * Disposes this PolyStack:
       
   513          * clean up before reusing this instance
       
   514          */
       
   515         void dispose() {
       
   516             end = 0;
       
   517             numCurves = 0;
       
   518 
       
   519             if (DO_STATS) {
       
   520                 stat_polystack_types.add(curveTypesUseMark);
       
   521                 stat_polystack_curves.add(curvesUseMark);
       
   522                 hist_polystack_curves.add(curvesUseMark);
       
   523 
       
   524                 // reset marks
       
   525                 curveTypesUseMark = 0;
       
   526                 curvesUseMark = 0;
       
   527             }
       
   528 
       
   529             // Return arrays:
       
   530             // curves and curveTypes are kept dirty
       
   531             curves     = curves_ref.putArray(curves);
       
   532             curveTypes = curveTypes_ref.putArray(curveTypes);
       
   533         }
       
   534 
       
   535         private void ensureSpace(final int n) {
       
   536             // use substraction to avoid integer overflow:
       
   537             if (curves.length - end < n) {
       
   538                 if (DO_STATS) {
       
   539                     stat_array_polystack_curves.add(end + n);
       
   540                 }
       
   541                 curves = curves_ref.widenArray(curves, end, end + n);
       
   542             }
       
   543             if (curveTypes.length <= numCurves) {
       
   544                 if (DO_STATS) {
       
   545                     stat_array_polystack_curveTypes.add(numCurves + 1);
       
   546                 }
       
   547                 curveTypes = curveTypes_ref.widenArray(curveTypes,
       
   548                                                        numCurves,
       
   549                                                        numCurves + 1);
       
   550             }
       
   551         }
       
   552 
       
   553         void pushCubic(double x0, double y0,
       
   554                        double x1, double y1,
       
   555                        double x2, double y2)
       
   556         {
       
   557             ensureSpace(6);
       
   558             curveTypes[numCurves++] = TYPE_CUBICTO;
       
   559             // we reverse the coordinate order to make popping easier
       
   560             final double[] _curves = curves;
       
   561             int e = end;
       
   562             _curves[e++] = x2;    _curves[e++] = y2;
       
   563             _curves[e++] = x1;    _curves[e++] = y1;
       
   564             _curves[e++] = x0;    _curves[e++] = y0;
       
   565             end = e;
       
   566         }
       
   567 
       
   568         void pushQuad(double x0, double y0,
       
   569                       double x1, double y1)
       
   570         {
       
   571             ensureSpace(4);
       
   572             curveTypes[numCurves++] = TYPE_QUADTO;
       
   573             final double[] _curves = curves;
       
   574             int e = end;
       
   575             _curves[e++] = x1;    _curves[e++] = y1;
       
   576             _curves[e++] = x0;    _curves[e++] = y0;
       
   577             end = e;
       
   578         }
       
   579 
       
   580         void pushLine(double x, double y) {
       
   581             ensureSpace(2);
       
   582             curveTypes[numCurves++] = TYPE_LINETO;
       
   583             curves[end++] = x;    curves[end++] = y;
       
   584         }
       
   585 
       
   586         void pullAll(final DPathConsumer2D io) {
       
   587             final int nc = numCurves;
       
   588             if (nc == 0) {
       
   589                 return;
       
   590             }
       
   591             if (DO_STATS) {
       
   592                 // update used marks:
       
   593                 if (numCurves > curveTypesUseMark) {
       
   594                     curveTypesUseMark = numCurves;
       
   595                 }
       
   596                 if (end > curvesUseMark) {
       
   597                     curvesUseMark = end;
       
   598                 }
       
   599             }
       
   600             final byte[]  _curveTypes = curveTypes;
       
   601             final double[] _curves = curves;
       
   602             int e = 0;
       
   603 
       
   604             for (int i = 0; i < nc; i++) {
       
   605                 switch(_curveTypes[i]) {
       
   606                 case TYPE_LINETO:
       
   607                     io.lineTo(_curves[e], _curves[e+1]);
       
   608                     e += 2;
       
   609                     continue;
       
   610                 case TYPE_QUADTO:
       
   611                     io.quadTo(_curves[e+0], _curves[e+1],
       
   612                               _curves[e+2], _curves[e+3]);
       
   613                     e += 4;
       
   614                     continue;
       
   615                 case TYPE_CUBICTO:
       
   616                     io.curveTo(_curves[e+0], _curves[e+1],
       
   617                                _curves[e+2], _curves[e+3],
       
   618                                _curves[e+4], _curves[e+5]);
       
   619                     e += 6;
       
   620                     continue;
       
   621                 default:
       
   622                 }
       
   623             }
       
   624             numCurves = 0;
       
   625             end = 0;
       
   626         }
       
   627 
       
   628         void popAll(final DPathConsumer2D io) {
       
   629             int nc = numCurves;
       
   630             if (nc == 0) {
       
   631                 return;
       
   632             }
       
   633             if (DO_STATS) {
       
   634                 // update used marks:
       
   635                 if (numCurves > curveTypesUseMark) {
       
   636                     curveTypesUseMark = numCurves;
       
   637                 }
       
   638                 if (end > curvesUseMark) {
       
   639                     curvesUseMark = end;
       
   640                 }
       
   641             }
       
   642             final byte[]  _curveTypes = curveTypes;
       
   643             final double[] _curves = curves;
       
   644             int e  = end;
       
   645 
       
   646             while (nc != 0) {
       
   647                 switch(_curveTypes[--nc]) {
       
   648                 case TYPE_LINETO:
       
   649                     e -= 2;
       
   650                     io.lineTo(_curves[e], _curves[e+1]);
       
   651                     continue;
       
   652                 case TYPE_QUADTO:
       
   653                     e -= 4;
       
   654                     io.quadTo(_curves[e+0], _curves[e+1],
       
   655                               _curves[e+2], _curves[e+3]);
       
   656                     continue;
       
   657                 case TYPE_CUBICTO:
       
   658                     e -= 6;
       
   659                     io.curveTo(_curves[e+0], _curves[e+1],
       
   660                                _curves[e+2], _curves[e+3],
       
   661                                _curves[e+4], _curves[e+5]);
       
   662                     continue;
       
   663                 default:
       
   664                 }
       
   665             }
       
   666             numCurves = 0;
       
   667             end = 0;
       
   668         }
       
   669 
       
   670         @Override
       
   671         public String toString() {
       
   672             String ret = "";
       
   673             int nc = numCurves;
       
   674             int last = end;
       
   675             int len;
       
   676             while (nc != 0) {
       
   677                 switch(curveTypes[--nc]) {
       
   678                 case TYPE_LINETO:
       
   679                     len = 2;
       
   680                     ret += "line: ";
       
   681                     break;
       
   682                 case TYPE_QUADTO:
       
   683                     len = 4;
       
   684                     ret += "quad: ";
       
   685                     break;
       
   686                 case TYPE_CUBICTO:
       
   687                     len = 6;
       
   688                     ret += "cubic: ";
       
   689                     break;
       
   690                 default:
       
   691                     len = 0;
       
   692                 }
       
   693                 last -= len;
       
   694                 ret += Arrays.toString(Arrays.copyOfRange(curves, last, last+len))
       
   695                                        + "\n";
       
   696             }
       
   697             return ret;
       
   698         }
       
   699     }
       
   700 
       
   701     // a stack of integer indices
       
   702     static final class IndexStack {
       
   703 
       
   704         // integer capacity = edges count / 4 ~ 1024
       
   705         private static final int INITIAL_COUNT = INITIAL_EDGES_COUNT >> 2;
       
   706 
       
   707         private int end;
       
   708         private int[] indices;
       
   709 
       
   710         // indices ref (dirty)
       
   711         private final IntArrayCache.Reference indices_ref;
       
   712 
       
   713         // used marks (stats only)
       
   714         private int indicesUseMark;
       
   715 
       
   716         private final StatLong stat_idxstack_indices;
       
   717         private final Histogram hist_idxstack_indices;
       
   718         private final StatLong stat_array_idxstack_indices;
       
   719 
       
   720         IndexStack(final DRendererContext rdrCtx) {
       
   721             this(rdrCtx, null, null, null);
       
   722         }
       
   723 
       
   724         IndexStack(final DRendererContext rdrCtx,
       
   725                    final StatLong stat_idxstack_indices,
       
   726                    final Histogram hist_idxstack_indices,
       
   727                    final StatLong stat_array_idxstack_indices)
       
   728         {
       
   729             indices_ref = rdrCtx.newDirtyIntArrayRef(INITIAL_COUNT); // 4K
       
   730             indices     = indices_ref.initial;
       
   731             end = 0;
       
   732 
       
   733             if (DO_STATS) {
       
   734                 indicesUseMark = 0;
       
   735             }
       
   736             this.stat_idxstack_indices = stat_idxstack_indices;
       
   737             this.hist_idxstack_indices = hist_idxstack_indices;
       
   738             this.stat_array_idxstack_indices = stat_array_idxstack_indices;
       
   739         }
       
   740 
       
   741         /**
       
   742          * Disposes this PolyStack:
       
   743          * clean up before reusing this instance
       
   744          */
       
   745         void dispose() {
       
   746             end = 0;
       
   747 
       
   748             if (DO_STATS) {
       
   749                 stat_idxstack_indices.add(indicesUseMark);
       
   750                 hist_idxstack_indices.add(indicesUseMark);
       
   751 
       
   752                 // reset marks
       
   753                 indicesUseMark = 0;
       
   754             }
       
   755 
       
   756             // Return arrays:
       
   757             // values is kept dirty
       
   758             indices = indices_ref.putArray(indices);
       
   759         }
       
   760 
       
   761         boolean isEmpty() {
       
   762             return (end == 0);
       
   763         }
       
   764 
       
   765         void reset() {
       
   766             end = 0;
       
   767         }
       
   768 
       
   769         void push(final int v) {
       
   770             // remove redundant values (reverse order):
       
   771             int[] _values = indices;
       
   772             final int nc = end;
       
   773             if (nc != 0) {
       
   774                 if (_values[nc - 1] == v) {
       
   775                     // remove both duplicated values:
       
   776                     end--;
       
   777                     return;
       
   778                 }
       
   779             }
       
   780             if (_values.length <= nc) {
       
   781                 if (DO_STATS) {
       
   782                     stat_array_idxstack_indices.add(nc + 1);
       
   783                 }
       
   784                 indices = _values = indices_ref.widenArray(_values, nc, nc + 1);
       
   785             }
       
   786             _values[end++] = v;
       
   787 
       
   788             if (DO_STATS) {
       
   789                 // update used marks:
       
   790                 if (end > indicesUseMark) {
       
   791                     indicesUseMark = end;
       
   792                 }
       
   793             }
       
   794         }
       
   795 
       
   796         void pullAll(final double[] points, final DPathConsumer2D io) {
       
   797             final int nc = end;
       
   798             if (nc == 0) {
       
   799                 return;
       
   800             }
       
   801             final int[] _values = indices;
       
   802 
       
   803             for (int i = 0, j; i < nc; i++) {
       
   804                 j = _values[i] << 1;
       
   805                 io.lineTo(points[j], points[j + 1]);
       
   806             }
       
   807             end = 0;
       
   808         }
       
   809     }
   436 }
   810 }