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 34 TransformingPathConsumer2D() { 35 // used by RendererContext 36 } 37 38 // recycled PathConsumer2D instance from transformConsumer() 39 private final Path2DWrapper wp_Path2DWrapper = new Path2DWrapper(); 40 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 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 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 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 145 TranslateFilter() {} 146 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 157 public void moveTo(float x0, float y0) { 158 out.moveTo(x0 + tx, y0 + ty); 159 } 160 161 @Override 162 public void lineTo(float x1, float y1) { 163 out.lineTo(x1 + tx, y1 + ty); 164 } 165 166 @Override 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 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 185 public void closePath() { 186 out.closePath(); 187 } 188 189 @Override 190 public void pathDone() { 191 out.pathDone(); 192 } 193 194 @Override 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 204 ScaleFilter() {} 205 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 219 public void moveTo(float x0, float y0) { 220 out.moveTo(x0 * sx + tx, y0 * sy + ty); 221 } 222 223 @Override 224 public void lineTo(float x1, float y1) { 225 out.lineTo(x1 * sx + tx, y1 * sy + ty); 226 } 227 228 @Override 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 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 247 public void closePath() { 248 out.closePath(); 249 } 250 251 @Override 252 public void pathDone() { 253 out.pathDone(); 254 } 255 256 @Override 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 266 TransformFilter() {} 267 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 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 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 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 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 318 public void closePath() { 319 out.closePath(); 320 } 321 322 @Override 323 public void pathDone() { 324 out.pathDone(); 325 } 326 327 @Override 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 337 DeltaScaleFilter() {} 338 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 349 public void moveTo(float x0, float y0) { 350 out.moveTo(x0 * sx, y0 * sy); 351 } 352 353 @Override 354 public void lineTo(float x1, float y1) { 355 out.lineTo(x1 * sx, y1 * sy); 356 } 357 358 @Override 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 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 377 public void closePath() { 378 out.closePath(); 379 } 380 381 @Override 382 public void pathDone() { 383 out.pathDone(); 384 } 385 386 @Override 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 396 DeltaTransformFilter() {} 397 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 411 public void moveTo(float x0, float y0) { 412 out.moveTo(x0 * mxx + y0 * mxy, 413 x0 * myx + y0 * myy); 414 } 415 416 @Override 417 public void lineTo(float x1, float y1) { 418 out.lineTo(x1 * mxx + y1 * mxy, 419 x1 * myx + y1 * myy); 420 } 421 422 @Override 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 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 446 public void closePath() { 447 out.closePath(); 448 } 449 450 @Override 451 public void pathDone() { 452 out.pathDone(); 453 } 454 455 @Override 456 public long getNativeConsumer() { 457 return 0; 458 } 459 } 460 461 static final class Path2DWrapper implements PathConsumer2D { 462 private Path2D.Float p2d; 463 464 Path2DWrapper() {} 465 466 Path2DWrapper init(Path2D.Float p2d) { 467 this.p2d = p2d; 468 return this; 469 } 470 471 @Override 472 public void moveTo(float x0, float y0) { 473 p2d.moveTo(x0, y0); 474 } 475 476 @Override 477 public void lineTo(float x1, float y1) { 478 p2d.lineTo(x1, y1); 479 } 480 481 @Override 482 public void closePath() { 483 p2d.closePath(); 484 } 485 486 @Override 487 public void pathDone() {} 488 489 @Override 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 498 public void quadTo(float x1, float y1, float x2, float y2) { 499 p2d.quadTo(x1, y1, x2, y2); 500 } 501 502 @Override 503 public long getNativeConsumer() { 504 throw new InternalError("Not using a native peer"); 505 } 506 } 507 }