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