1 /*
2  * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.java2d.marlin;
27 
28 import sun.awt.geom.PathConsumer2D;
29 import java.awt.geom.AffineTransform;
30 import java.awt.geom.Path2D;
31 
32 final class TransformingPathConsumer2D {
33 
TransformingPathConsumer2D()34     TransformingPathConsumer2D() {
35         // used by RendererContext
36     }
37 
38     // recycled PathConsumer2D instance from transformConsumer()
39     private final Path2DWrapper        wp_Path2DWrapper        = new Path2DWrapper();
40 
wrapPath2d(Path2D.Float p2d)41     PathConsumer2D wrapPath2d(Path2D.Float p2d)
42     {
43         return wp_Path2DWrapper.init(p2d);
44     }
45 
46     // recycled PathConsumer2D instances from transformConsumer()
47     private final TranslateFilter      tx_TranslateFilter      = new TranslateFilter();
48     private final DeltaScaleFilter     tx_DeltaScaleFilter     = new DeltaScaleFilter();
49     private final ScaleFilter          tx_ScaleFilter          = new ScaleFilter();
50     private final DeltaTransformFilter tx_DeltaTransformFilter = new DeltaTransformFilter();
51     private final TransformFilter      tx_TransformFilter      = new TransformFilter();
52 
transformConsumer(PathConsumer2D out, AffineTransform at)53     PathConsumer2D transformConsumer(PathConsumer2D out,
54                                      AffineTransform at)
55     {
56         if (at == null) {
57             return out;
58         }
59         float mxx = (float) at.getScaleX();
60         float mxy = (float) at.getShearX();
61         float mxt = (float) at.getTranslateX();
62         float myx = (float) at.getShearY();
63         float myy = (float) at.getScaleY();
64         float myt = (float) at.getTranslateY();
65         if (mxy == 0f && myx == 0f) {
66             if (mxx == 1f && myy == 1f) {
67                 if (mxt == 0f && myt == 0f) {
68                     return out;
69                 } else {
70                     return tx_TranslateFilter.init(out, mxt, myt);
71                 }
72             } else {
73                 if (mxt == 0f && myt == 0f) {
74                     return tx_DeltaScaleFilter.init(out, mxx, myy);
75                 } else {
76                     return tx_ScaleFilter.init(out, mxx, myy, mxt, myt);
77                 }
78             }
79         } else if (mxt == 0f && myt == 0f) {
80             return tx_DeltaTransformFilter.init(out, mxx, mxy, myx, myy);
81         } else {
82             return tx_TransformFilter.init(out, mxx, mxy, mxt, myx, myy, myt);
83         }
84     }
85 
86     // recycled PathConsumer2D instances from deltaTransformConsumer()
87     private final DeltaScaleFilter     dt_DeltaScaleFilter     = new DeltaScaleFilter();
88     private final DeltaTransformFilter dt_DeltaTransformFilter = new DeltaTransformFilter();
89 
deltaTransformConsumer(PathConsumer2D out, AffineTransform at)90     PathConsumer2D deltaTransformConsumer(PathConsumer2D out,
91                                           AffineTransform at)
92     {
93         if (at == null) {
94             return out;
95         }
96         float mxx = (float) at.getScaleX();
97         float mxy = (float) at.getShearX();
98         float myx = (float) at.getShearY();
99         float myy = (float) at.getScaleY();
100         if (mxy == 0f && myx == 0f) {
101             if (mxx == 1f && myy == 1f) {
102                 return out;
103             } else {
104                 return dt_DeltaScaleFilter.init(out, mxx, myy);
105             }
106         } else {
107             return dt_DeltaTransformFilter.init(out, mxx, mxy, myx, myy);
108         }
109     }
110 
111     // recycled PathConsumer2D instances from inverseDeltaTransformConsumer()
112     private final DeltaScaleFilter     iv_DeltaScaleFilter     = new DeltaScaleFilter();
113     private final DeltaTransformFilter iv_DeltaTransformFilter = new DeltaTransformFilter();
114 
inverseDeltaTransformConsumer(PathConsumer2D out, AffineTransform at)115     PathConsumer2D inverseDeltaTransformConsumer(PathConsumer2D out,
116                                                  AffineTransform at)
117     {
118         if (at == null) {
119             return out;
120         }
121         float mxx = (float) at.getScaleX();
122         float mxy = (float) at.getShearX();
123         float myx = (float) at.getShearY();
124         float myy = (float) at.getScaleY();
125         if (mxy == 0f && myx == 0f) {
126             if (mxx == 1f && myy == 1f) {
127                 return out;
128             } else {
129                 return iv_DeltaScaleFilter.init(out, 1.0f/mxx, 1.0f/myy);
130             }
131         } else {
132             float det = mxx * myy - mxy * myx;
133             return iv_DeltaTransformFilter.init(out,
134                                                 myy / det,
135                                                -mxy / det,
136                                                -myx / det,
137                                                 mxx / det);
138         }
139     }
140 
141     static final class TranslateFilter implements PathConsumer2D {
142         private PathConsumer2D out;
143         private float tx, ty;
144 
TranslateFilter()145         TranslateFilter() {}
146 
init(PathConsumer2D out, float tx, float ty)147         TranslateFilter init(PathConsumer2D out,
148                              float tx, float ty)
149         {
150             this.out = out;
151             this.tx = tx;
152             this.ty = ty;
153             return this; // fluent API
154         }
155 
156         @Override
moveTo(float x0, float y0)157         public void moveTo(float x0, float y0) {
158             out.moveTo(x0 + tx, y0 + ty);
159         }
160 
161         @Override
lineTo(float x1, float y1)162         public void lineTo(float x1, float y1) {
163             out.lineTo(x1 + tx, y1 + ty);
164         }
165 
166         @Override
quadTo(float x1, float y1, float x2, float y2)167         public void quadTo(float x1, float y1,
168                            float x2, float y2)
169         {
170             out.quadTo(x1 + tx, y1 + ty,
171                        x2 + tx, y2 + ty);
172         }
173 
174         @Override
curveTo(float x1, float y1, float x2, float y2, float x3, float y3)175         public void curveTo(float x1, float y1,
176                             float x2, float y2,
177                             float x3, float y3)
178         {
179             out.curveTo(x1 + tx, y1 + ty,
180                         x2 + tx, y2 + ty,
181                         x3 + tx, y3 + ty);
182         }
183 
184         @Override
closePath()185         public void closePath() {
186             out.closePath();
187         }
188 
189         @Override
pathDone()190         public void pathDone() {
191             out.pathDone();
192         }
193 
194         @Override
getNativeConsumer()195         public long getNativeConsumer() {
196             return 0;
197         }
198     }
199 
200     static final class ScaleFilter implements PathConsumer2D {
201         private PathConsumer2D out;
202         private float sx, sy, tx, ty;
203 
ScaleFilter()204         ScaleFilter() {}
205 
init(PathConsumer2D out, float sx, float sy, float tx, float ty)206         ScaleFilter init(PathConsumer2D out,
207                          float sx, float sy,
208                          float tx, float ty)
209         {
210             this.out = out;
211             this.sx = sx;
212             this.sy = sy;
213             this.tx = tx;
214             this.ty = ty;
215             return this; // fluent API
216         }
217 
218         @Override
moveTo(float x0, float y0)219         public void moveTo(float x0, float y0) {
220             out.moveTo(x0 * sx + tx, y0 * sy + ty);
221         }
222 
223         @Override
lineTo(float x1, float y1)224         public void lineTo(float x1, float y1) {
225             out.lineTo(x1 * sx + tx, y1 * sy + ty);
226         }
227 
228         @Override
quadTo(float x1, float y1, float x2, float y2)229         public void quadTo(float x1, float y1,
230                            float x2, float y2)
231         {
232             out.quadTo(x1 * sx + tx, y1 * sy + ty,
233                        x2 * sx + tx, y2 * sy + ty);
234         }
235 
236         @Override
curveTo(float x1, float y1, float x2, float y2, float x3, float y3)237         public void curveTo(float x1, float y1,
238                             float x2, float y2,
239                             float x3, float y3)
240         {
241             out.curveTo(x1 * sx + tx, y1 * sy + ty,
242                         x2 * sx + tx, y2 * sy + ty,
243                         x3 * sx + tx, y3 * sy + ty);
244         }
245 
246         @Override
closePath()247         public void closePath() {
248             out.closePath();
249         }
250 
251         @Override
pathDone()252         public void pathDone() {
253             out.pathDone();
254         }
255 
256         @Override
getNativeConsumer()257         public long getNativeConsumer() {
258             return 0;
259         }
260     }
261 
262     static final class TransformFilter implements PathConsumer2D {
263         private PathConsumer2D out;
264         private float mxx, mxy, mxt, myx, myy, myt;
265 
TransformFilter()266         TransformFilter() {}
267 
init(PathConsumer2D out, float mxx, float mxy, float mxt, float myx, float myy, float myt)268         TransformFilter init(PathConsumer2D out,
269                              float mxx, float mxy, float mxt,
270                              float myx, float myy, float myt)
271         {
272             this.out = out;
273             this.mxx = mxx;
274             this.mxy = mxy;
275             this.mxt = mxt;
276             this.myx = myx;
277             this.myy = myy;
278             this.myt = myt;
279             return this; // fluent API
280         }
281 
282         @Override
moveTo(float x0, float y0)283         public void moveTo(float x0, float y0) {
284             out.moveTo(x0 * mxx + y0 * mxy + mxt,
285                        x0 * myx + y0 * myy + myt);
286         }
287 
288         @Override
lineTo(float x1, float y1)289         public void lineTo(float x1, float y1) {
290             out.lineTo(x1 * mxx + y1 * mxy + mxt,
291                        x1 * myx + y1 * myy + myt);
292         }
293 
294         @Override
quadTo(float x1, float y1, float x2, float y2)295         public void quadTo(float x1, float y1,
296                            float x2, float y2)
297         {
298             out.quadTo(x1 * mxx + y1 * mxy + mxt,
299                        x1 * myx + y1 * myy + myt,
300                        x2 * mxx + y2 * mxy + mxt,
301                        x2 * myx + y2 * myy + myt);
302         }
303 
304         @Override
curveTo(float x1, float y1, float x2, float y2, float x3, float y3)305         public void curveTo(float x1, float y1,
306                             float x2, float y2,
307                             float x3, float y3)
308         {
309             out.curveTo(x1 * mxx + y1 * mxy + mxt,
310                         x1 * myx + y1 * myy + myt,
311                         x2 * mxx + y2 * mxy + mxt,
312                         x2 * myx + y2 * myy + myt,
313                         x3 * mxx + y3 * mxy + mxt,
314                         x3 * myx + y3 * myy + myt);
315         }
316 
317         @Override
closePath()318         public void closePath() {
319             out.closePath();
320         }
321 
322         @Override
pathDone()323         public void pathDone() {
324             out.pathDone();
325         }
326 
327         @Override
getNativeConsumer()328         public long getNativeConsumer() {
329             return 0;
330         }
331     }
332 
333     static final class DeltaScaleFilter implements PathConsumer2D {
334         private PathConsumer2D out;
335         private float sx, sy;
336 
DeltaScaleFilter()337         DeltaScaleFilter() {}
338 
init(PathConsumer2D out, float mxx, float myy)339         DeltaScaleFilter init(PathConsumer2D out,
340                               float mxx, float myy)
341         {
342             this.out = out;
343             sx = mxx;
344             sy = myy;
345             return this; // fluent API
346         }
347 
348         @Override
moveTo(float x0, float y0)349         public void moveTo(float x0, float y0) {
350             out.moveTo(x0 * sx, y0 * sy);
351         }
352 
353         @Override
lineTo(float x1, float y1)354         public void lineTo(float x1, float y1) {
355             out.lineTo(x1 * sx, y1 * sy);
356         }
357 
358         @Override
quadTo(float x1, float y1, float x2, float y2)359         public void quadTo(float x1, float y1,
360                            float x2, float y2)
361         {
362             out.quadTo(x1 * sx, y1 * sy,
363                        x2 * sx, y2 * sy);
364         }
365 
366         @Override
curveTo(float x1, float y1, float x2, float y2, float x3, float y3)367         public void curveTo(float x1, float y1,
368                             float x2, float y2,
369                             float x3, float y3)
370         {
371             out.curveTo(x1 * sx, y1 * sy,
372                         x2 * sx, y2 * sy,
373                         x3 * sx, y3 * sy);
374         }
375 
376         @Override
closePath()377         public void closePath() {
378             out.closePath();
379         }
380 
381         @Override
pathDone()382         public void pathDone() {
383             out.pathDone();
384         }
385 
386         @Override
getNativeConsumer()387         public long getNativeConsumer() {
388             return 0;
389         }
390     }
391 
392     static final class DeltaTransformFilter implements PathConsumer2D {
393         private PathConsumer2D out;
394         private float mxx, mxy, myx, myy;
395 
DeltaTransformFilter()396         DeltaTransformFilter() {}
397 
init(PathConsumer2D out, float mxx, float mxy, float myx, float myy)398         DeltaTransformFilter init(PathConsumer2D out,
399                                   float mxx, float mxy,
400                                   float myx, float myy)
401         {
402             this.out = out;
403             this.mxx = mxx;
404             this.mxy = mxy;
405             this.myx = myx;
406             this.myy = myy;
407             return this; // fluent API
408         }
409 
410         @Override
moveTo(float x0, float y0)411         public void moveTo(float x0, float y0) {
412             out.moveTo(x0 * mxx + y0 * mxy,
413                        x0 * myx + y0 * myy);
414         }
415 
416         @Override
lineTo(float x1, float y1)417         public void lineTo(float x1, float y1) {
418             out.lineTo(x1 * mxx + y1 * mxy,
419                        x1 * myx + y1 * myy);
420         }
421 
422         @Override
quadTo(float x1, float y1, float x2, float y2)423         public void quadTo(float x1, float y1,
424                            float x2, float y2)
425         {
426             out.quadTo(x1 * mxx + y1 * mxy,
427                        x1 * myx + y1 * myy,
428                        x2 * mxx + y2 * mxy,
429                        x2 * myx + y2 * myy);
430         }
431 
432         @Override
curveTo(float x1, float y1, float x2, float y2, float x3, float y3)433         public void curveTo(float x1, float y1,
434                             float x2, float y2,
435                             float x3, float y3)
436         {
437             out.curveTo(x1 * mxx + y1 * mxy,
438                         x1 * myx + y1 * myy,
439                         x2 * mxx + y2 * mxy,
440                         x2 * myx + y2 * myy,
441                         x3 * mxx + y3 * mxy,
442                         x3 * myx + y3 * myy);
443         }
444 
445         @Override
closePath()446         public void closePath() {
447             out.closePath();
448         }
449 
450         @Override
pathDone()451         public void pathDone() {
452             out.pathDone();
453         }
454 
455         @Override
getNativeConsumer()456         public long getNativeConsumer() {
457             return 0;
458         }
459     }
460 
461     static final class Path2DWrapper implements PathConsumer2D {
462         private Path2D.Float p2d;
463 
Path2DWrapper()464         Path2DWrapper() {}
465 
init(Path2D.Float p2d)466         Path2DWrapper init(Path2D.Float p2d) {
467             this.p2d = p2d;
468             return this;
469         }
470 
471         @Override
moveTo(float x0, float y0)472         public void moveTo(float x0, float y0) {
473             p2d.moveTo(x0, y0);
474         }
475 
476         @Override
lineTo(float x1, float y1)477         public void lineTo(float x1, float y1) {
478             p2d.lineTo(x1, y1);
479         }
480 
481         @Override
closePath()482         public void closePath() {
483             p2d.closePath();
484         }
485 
486         @Override
pathDone()487         public void pathDone() {}
488 
489         @Override
curveTo(float x1, float y1, float x2, float y2, float x3, float y3)490         public void curveTo(float x1, float y1,
491                             float x2, float y2,
492                             float x3, float y3)
493         {
494             p2d.curveTo(x1, y1, x2, y2, x3, y3);
495         }
496 
497         @Override
quadTo(float x1, float y1, float x2, float y2)498         public void quadTo(float x1, float y1, float x2, float y2) {
499             p2d.quadTo(x1, y1, x2, y2);
500         }
501 
502         @Override
getNativeConsumer()503         public long getNativeConsumer() {
504             throw new InternalError("Not using a native peer");
505         }
506     }
507 }
508