1 /* 2 * Copyright (c) 2009, 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 com.sun.prism.impl; 27 28 import com.sun.glass.ui.Screen; 29 import com.sun.javafx.geom.Ellipse2D; 30 import com.sun.javafx.geom.Line2D; 31 import com.sun.javafx.geom.RectBounds; 32 import com.sun.javafx.geom.Rectangle; 33 import com.sun.javafx.geom.RoundRectangle2D; 34 import com.sun.javafx.geom.Shape; 35 import com.sun.javafx.geom.transform.Affine3D; 36 import com.sun.javafx.geom.transform.BaseTransform; 37 import com.sun.javafx.sg.prism.NGCamera; 38 import com.sun.javafx.sg.prism.NodePath; 39 import com.sun.prism.BasicStroke; 40 import com.sun.prism.CompositeMode; 41 import com.sun.prism.PixelFormat; 42 import com.sun.prism.RectShadowGraphics; 43 import com.sun.prism.RenderTarget; 44 import com.sun.prism.ResourceFactory; 45 import com.sun.prism.Texture; 46 import com.sun.prism.paint.Color; 47 import com.sun.prism.paint.Paint; 48 49 public abstract class BaseGraphics implements RectShadowGraphics { 50 51 private static final BasicStroke DEFAULT_STROKE = 52 new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f); 53 private static final Paint DEFAULT_PAINT = Color.WHITE; 54 55 protected static final RoundRectangle2D scratchRRect = new RoundRectangle2D(); 56 protected static final Ellipse2D scratchEllipse = new Ellipse2D(); 57 protected static final Line2D scratchLine = new Line2D(); 58 protected static final BaseTransform IDENT = BaseTransform.IDENTITY_TRANSFORM; 59 60 // TODO: initialize transform lazily to avoid creating garbage... (RT-27422) 61 private final Affine3D transform3D = new Affine3D(); 62 private NGCamera camera = NGCamera.INSTANCE; 63 private RectBounds devClipRect; 64 private RectBounds finalClipRect; 65 protected RectBounds nodeBounds = null; 66 private Rectangle clipRect; 67 private int clipRectIndex; 68 private boolean hasPreCullingBits = false; 69 private float extraAlpha = 1f; 70 private CompositeMode compMode; 71 private boolean antialiasedShape = true; 72 private boolean depthBuffer = false; 73 private boolean depthTest = false; 74 protected Paint paint = DEFAULT_PAINT; 75 protected BasicStroke stroke = DEFAULT_STROKE; 76 77 protected boolean isSimpleTranslate = true; 78 protected float transX; 79 protected float transY; 80 81 private final BaseContext context; 82 private final RenderTarget renderTarget; 83 private boolean state3D = false; 84 private float pixelScale = 1.0f; 85 86 protected BaseGraphics(BaseContext context, RenderTarget target) { 87 this.context = context; 88 this.renderTarget = target; 89 devClipRect = new RectBounds(0, 0, 90 target.getContentWidth(), 91 target.getContentHeight()); 92 finalClipRect = new RectBounds(devClipRect); 93 compMode = CompositeMode.SRC_OVER; 94 if (context != null) { 95 // RT-27422 96 // TODO: Ideally we wouldn't need this step here and would 97 // instead call some method prior to making any OpenGL calls 98 // to ensure that there is a current context. We're getting 99 // closer to that ideal in that we call validate*Op() before 100 // every graphics operation (which in turn calls the 101 // setRenderTarget() method), but there are still some cases 102 // remaining where this doesn't happen (e.g. texture creation). 103 // So for the time being this blanket call to setRenderTarget() 104 // is better than nothing... 105 context.setRenderTarget(this); 106 } 107 } 108 109 protected NGCamera getCamera() { 110 return camera; 111 } 112 113 public RenderTarget getRenderTarget() { 114 return renderTarget; 115 } 116 117 @Override 118 public void setState3D(boolean flag) { 119 this.state3D = flag; 120 } 121 122 @Override 123 public boolean isState3D() { 124 return state3D; 125 } 126 127 public Screen getAssociatedScreen() { 128 return context.getAssociatedScreen(); 129 } 130 131 public ResourceFactory getResourceFactory() { 132 return context.getResourceFactory(); 133 } 134 135 public BaseTransform getTransformNoClone() { 136 return transform3D; 137 } 138 139 public void setTransform(BaseTransform transform) { 140 if (transform == null) { 141 transform3D.setToIdentity(); 142 } else { 143 transform3D.setTransform(transform); 144 } 145 validateTransformAndPaint(); 146 } 147 148 public void setTransform(double m00, double m10, 149 double m01, double m11, 150 double m02, double m12) 151 { 152 transform3D.setTransform(m00, m10, m01, m11, m02, m12); 153 validateTransformAndPaint(); 154 } 155 156 public void setTransform3D(double mxx, double mxy, double mxz, double mxt, 157 double myx, double myy, double myz, double myt, 158 double mzx, double mzy, double mzz, double mzt) 159 { 160 transform3D.setTransform(mxx, mxy, mxz, mxt, 161 myx, myy, myz, myt, 162 mzx, mzy, mzz, mzt); 163 validateTransformAndPaint(); 164 } 165 166 public void transform(BaseTransform transform) { 167 transform3D.concatenate(transform); 168 validateTransformAndPaint(); 169 } 170 171 public void translate(float tx, float ty) { 172 if (tx != 0f || ty != 0f) { 173 transform3D.translate(tx, ty); 174 validateTransformAndPaint(); 175 } 176 } 177 178 public void translate(float tx, float ty, float tz) { 179 if (tx != 0f || ty != 0f || tz != 0f) { 180 transform3D.translate(tx, ty, tz); 181 validateTransformAndPaint(); 182 } 183 } 184 185 public void scale(float sx, float sy) { 186 if (sx != 1f || sy != 1f) { 187 transform3D.scale(sx, sy); 188 validateTransformAndPaint(); 189 } 190 } 191 192 public void scale(float sx, float sy, float sz) { 193 if (sx != 1f || sy != 1f || sz != 1f) { 194 transform3D.scale(sx, sy, sz); 195 validateTransformAndPaint(); 196 } 197 } 198 199 public void setClipRectIndex(int index) { 200 this.clipRectIndex = index; 201 } 202 public int getClipRectIndex() { 203 return this.clipRectIndex; 204 } 205 206 public void setHasPreCullingBits(boolean hasBits) { 207 this.hasPreCullingBits = hasBits; 208 } 209 210 public boolean hasPreCullingBits() { 211 return hasPreCullingBits; 212 } 213 214 private NodePath renderRoot; 215 @Override 216 public final void setRenderRoot(NodePath root) { 217 this.renderRoot = root; 218 } 219 220 @Override 221 public final NodePath getRenderRoot() { 222 return renderRoot; 223 } 224 225 private void validateTransformAndPaint() { 226 if (transform3D.isTranslateOrIdentity() && 227 paint.getType() == Paint.Type.COLOR) 228 { 229 // RT-27422 230 // TODO: we could probably extend this to include 231 // proportional paints in addition to simple colors... 232 isSimpleTranslate = true; 233 transX = (float)transform3D.getMxt(); 234 transY = (float)transform3D.getMyt(); 235 } else { 236 isSimpleTranslate = false; 237 transX = 0f; 238 transY = 0f; 239 } 240 } 241 242 public NGCamera getCameraNoClone() { 243 return camera; 244 } 245 246 public void setDepthTest(boolean depthTest) { 247 this.depthTest = depthTest; 248 } 249 250 public boolean isDepthTest() { 251 return depthTest; 252 } 253 254 public void setDepthBuffer(boolean depthBuffer) { 255 this.depthBuffer = depthBuffer; 256 } 257 258 public boolean isDepthBuffer() { 259 return depthBuffer; 260 } 261 262 // If true use fragment shader that does alpha testing (i.e. discard if alpha == 0.0) 263 // Currently it is required when depth testing is in use. 264 public boolean isAlphaTestShader() { 265 return (PrismSettings.forceAlphaTestShader || (isDepthTest() && isDepthBuffer())); 266 } 267 268 public void setAntialiasedShape(boolean aa) { 269 antialiasedShape = aa; 270 } 271 272 public boolean isAntialiasedShape() { 273 return antialiasedShape; 274 } 275 276 @Override 277 public void setPixelScaleFactor(float pixelScale) { 278 this.pixelScale = pixelScale; 279 } 280 281 @Override 282 public float getPixelScaleFactor() { 283 return pixelScale; 284 } 285 286 public void setCamera(NGCamera camera) { 287 this.camera = camera; 288 } 289 290 public Rectangle getClipRect() { 291 return (clipRect != null) ? new Rectangle(clipRect) : null; 292 } 293 294 public Rectangle getClipRectNoClone() { 295 return clipRect; 296 } 297 298 public RectBounds getFinalClipNoClone() { 299 return finalClipRect; 300 } 301 302 public void setClipRect(Rectangle clipRect) { 303 this.finalClipRect.setBounds(devClipRect); 304 if (clipRect == null) { 305 this.clipRect = null; 306 } else { 307 this.clipRect = new Rectangle(clipRect); 308 this.finalClipRect.intersectWith(clipRect); 309 } 310 } 311 312 public float getExtraAlpha() { 313 return extraAlpha; 314 } 315 316 public void setExtraAlpha(float extraAlpha) { 317 this.extraAlpha = extraAlpha; 318 } 319 320 public CompositeMode getCompositeMode() { 321 return compMode; 322 } 323 324 public void setCompositeMode(CompositeMode compMode) { 325 this.compMode = compMode; 326 } 327 328 public Paint getPaint() { 329 return paint; 330 } 331 332 public void setPaint(Paint paint) { 333 this.paint = paint; 334 validateTransformAndPaint(); 335 } 336 337 public BasicStroke getStroke() { 338 return stroke; 339 } 340 341 public void setStroke(BasicStroke stroke) { 342 this.stroke = stroke; 343 } 344 345 public void clear() { 346 clear(Color.TRANSPARENT); 347 } 348 349 protected abstract void renderShape(Shape shape, BasicStroke stroke, 350 float bx, float by, float bw, float bh); 351 352 public void fill(Shape shape) { 353 float bx = 0f, by = 0f, bw = 0f, bh = 0f; 354 if (paint.isProportional()) { 355 if (nodeBounds != null) { 356 bx = nodeBounds.getMinX(); 357 by = nodeBounds.getMinY(); 358 bw = nodeBounds.getWidth(); 359 bh = nodeBounds.getHeight(); 360 } else { 361 float[] bbox = { 362 Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 363 Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 364 }; 365 Shape.accumulate(bbox, shape, BaseTransform.IDENTITY_TRANSFORM); 366 bx = bbox[0]; 367 by = bbox[1]; 368 bw = bbox[2] - bx; 369 bh = bbox[3] - by; 370 } 371 } 372 renderShape(shape, null, bx, by, bw, bh); 373 } 374 375 public void draw(Shape shape) { 376 float bx = 0f, by = 0f, bw = 0f, bh = 0f; 377 if (paint.isProportional()) { 378 if (nodeBounds != null) { 379 bx = nodeBounds.getMinX(); 380 by = nodeBounds.getMinY(); 381 bw = nodeBounds.getWidth(); 382 bh = nodeBounds.getHeight(); 383 } else { 384 float[] bbox = { 385 Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, 386 Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY, 387 }; 388 Shape.accumulate(bbox, shape, BaseTransform.IDENTITY_TRANSFORM); 389 bx = bbox[0]; 390 by = bbox[1]; 391 bw = bbox[2] - bx; 392 bh = bbox[3] - by; 393 } 394 } 395 renderShape(shape, stroke, bx, by, bw, bh); 396 } 397 398 @Override 399 public void drawTexture(Texture tex, float x, float y, float w, float h) { 400 drawTexture(tex, 401 x, y, x+w, y+h, 402 0, 0, w, h); 403 } 404 405 @Override 406 public void drawTexture(Texture tex, 407 float dx1, float dy1, float dx2, float dy2, 408 float sx1, float sy1, float sx2, float sy2) 409 { 410 BaseTransform xform = isSimpleTranslate ? IDENT : getTransformNoClone(); 411 PixelFormat format = tex.getPixelFormat(); 412 if (format == PixelFormat.BYTE_ALPHA) { 413 // Note that we treat this as a paint operation, using the 414 // given texture as the alpha mask; perhaps it would be better 415 // to treat this as a separate operation from drawTexture(), but 416 // overloading drawTexture() seems like an equally valid option. 417 context.validatePaintOp(this, xform, tex, dx1, dy1, dx2-dx1, dy2-dy1); 418 } else { 419 context.validateTextureOp(this, xform, tex, format); 420 } 421 if (isSimpleTranslate) { 422 // The validatePaintOp bounds above needed to use the original 423 // coordinates (prior to any translation below) for relative 424 // paint processing. 425 dx1 += transX; 426 dy1 += transY; 427 dx2 += transX; 428 dy2 += transY; 429 } 430 431 float pw = tex.getPhysicalWidth(); 432 float ph = tex.getPhysicalHeight(); 433 float cx1 = tex.getContentX(); 434 float cy1 = tex.getContentY(); 435 float tx1 = (cx1 + sx1) / pw; 436 float ty1 = (cy1 + sy1) / ph; 437 float tx2 = (cx1 + sx2) / pw; 438 float ty2 = (cy1 + sy2) / ph; 439 440 VertexBuffer vb = context.getVertexBuffer(); 441 if (context.isSuperShaderEnabled()) { 442 vb.addSuperQuad(dx1, dy1, dx2, dy2, tx1, ty1, tx2, ty2, false); 443 } else { 444 vb.addQuad(dx1, dy1, dx2, dy2, tx1, ty1, tx2, ty2); 445 } 446 } 447 448 @Override 449 public void drawTexture3SliceH(Texture tex, 450 float dx1, float dy1, float dx2, float dy2, 451 float sx1, float sy1, float sx2, float sy2, 452 float dh1, float dh2, float sh1, float sh2) 453 { 454 BaseTransform xform = isSimpleTranslate ? IDENT : getTransformNoClone(); 455 PixelFormat format = tex.getPixelFormat(); 456 if (format == PixelFormat.BYTE_ALPHA) { 457 // Note that we treat this as a paint operation, using the 458 // given texture as the alpha mask; perhaps it would be better 459 // to treat this as a separate operation from drawTexture(), but 460 // overloading drawTexture() seems like an equally valid option. 461 context.validatePaintOp(this, xform, tex, dx1, dy1, dx2-dx1, dy2-dy1); 462 } else { 463 context.validateTextureOp(this, xform, tex, format); 464 } 465 if (isSimpleTranslate) { 466 // The validatePaintOp bounds above needed to use the original 467 // coordinates (prior to any translation below) for relative 468 // paint processing. 469 dx1 += transX; 470 dy1 += transY; 471 dx2 += transX; 472 dy2 += transY; 473 dh1 += transX; 474 // dv1 += transY; 475 dh2 += transX; 476 // dv2 += transY; 477 } 478 479 float pw = tex.getPhysicalWidth(); 480 float ph = tex.getPhysicalHeight(); 481 float cx1 = tex.getContentX(); 482 float cy1 = tex.getContentY(); 483 float tx1 = (cx1 + sx1) / pw; 484 float ty1 = (cy1 + sy1) / ph; 485 float tx2 = (cx1 + sx2) / pw; 486 float ty2 = (cy1 + sy2) / ph; 487 float th1 = (cx1 + sh1) / pw; 488 // float tv1 = (cy1 + sv1) / ph; 489 float th2 = (cx1 + sh2) / pw; 490 // float tv2 = (cy1 + sv2) / ph; 491 492 VertexBuffer vb = context.getVertexBuffer(); 493 if (context.isSuperShaderEnabled()) { 494 vb.addSuperQuad(dx1, dy1, dh1, dy2, tx1, ty1, th1, ty2, false); 495 vb.addSuperQuad(dh1, dy1, dh2, dy2, th1, ty1, th2, ty2, false); 496 vb.addSuperQuad(dh2, dy1, dx2, dy2, th2, ty1, tx2, ty2, false); 497 } else { 498 vb.addQuad(dx1, dy1, dh1, dy2, tx1, ty1, th1, ty2); 499 vb.addQuad(dh1, dy1, dh2, dy2, th1, ty1, th2, ty2); 500 vb.addQuad(dh2, dy1, dx2, dy2, th2, ty1, tx2, ty2); 501 } 502 } 503 504 @Override 505 public void drawTexture3SliceV(Texture tex, 506 float dx1, float dy1, float dx2, float dy2, 507 float sx1, float sy1, float sx2, float sy2, 508 float dv1, float dv2, float sv1, float sv2) 509 { 510 BaseTransform xform = isSimpleTranslate ? IDENT : getTransformNoClone(); 511 PixelFormat format = tex.getPixelFormat(); 512 if (format == PixelFormat.BYTE_ALPHA) { 513 // Note that we treat this as a paint operation, using the 514 // given texture as the alpha mask; perhaps it would be better 515 // to treat this as a separate operation from drawTexture(), but 516 // overloading drawTexture() seems like an equally valid option. 517 context.validatePaintOp(this, xform, tex, dx1, dy1, dx2-dx1, dy2-dy1); 518 } else { 519 context.validateTextureOp(this, xform, tex, format); 520 } 521 if (isSimpleTranslate) { 522 // The validatePaintOp bounds above needed to use the original 523 // coordinates (prior to any translation below) for relative 524 // paint processing. 525 dx1 += transX; 526 dy1 += transY; 527 dx2 += transX; 528 dy2 += transY; 529 // dh1 += transX; 530 dv1 += transY; 531 // dh2 += transX; 532 dv2 += transY; 533 } 534 535 float pw = tex.getPhysicalWidth(); 536 float ph = tex.getPhysicalHeight(); 537 float cx1 = tex.getContentX(); 538 float cy1 = tex.getContentY(); 539 float tx1 = (cx1 + sx1) / pw; 540 float ty1 = (cy1 + sy1) / ph; 541 float tx2 = (cx1 + sx2) / pw; 542 float ty2 = (cy1 + sy2) / ph; 543 // float th1 = (cx1 + sh1) / pw; 544 float tv1 = (cy1 + sv1) / ph; 545 // float th2 = (cx1 + sh2) / pw; 546 float tv2 = (cy1 + sv2) / ph; 547 548 VertexBuffer vb = context.getVertexBuffer(); 549 if (context.isSuperShaderEnabled()) { 550 vb.addSuperQuad(dx1, dy1, dx2, dv1, tx1, ty1, tx2, tv1, false); 551 vb.addSuperQuad(dx1, dv1, dx2, dv2, tx1, tv1, tx2, tv2, false); 552 vb.addSuperQuad(dx1, dv2, dx2, dy2, tx1, tv2, tx2, ty2, false); 553 } else { 554 vb.addQuad(dx1, dy1, dx2, dv1, tx1, ty1, tx2, tv1); 555 vb.addQuad(dx1, dv1, dx2, dv2, tx1, tv1, tx2, tv2); 556 vb.addQuad(dx1, dv2, dx2, dy2, tx1, tv2, tx2, ty2); 557 } 558 } 559 560 @Override 561 public void drawTexture9Slice(Texture tex, 562 float dx1, float dy1, float dx2, float dy2, 563 float sx1, float sy1, float sx2, float sy2, 564 float dh1, float dv1, float dh2, float dv2, 565 float sh1, float sv1, float sh2, float sv2) 566 { 567 BaseTransform xform = isSimpleTranslate ? IDENT : getTransformNoClone(); 568 PixelFormat format = tex.getPixelFormat(); 569 if (format == PixelFormat.BYTE_ALPHA) { 570 // Note that we treat this as a paint operation, using the 571 // given texture as the alpha mask; perhaps it would be better 572 // to treat this as a separate operation from drawTexture(), but 573 // overloading drawTexture() seems like an equally valid option. 574 context.validatePaintOp(this, xform, tex, dx1, dy1, dx2-dx1, dy2-dy1); 575 } else { 576 context.validateTextureOp(this, xform, tex, format); 577 } 578 if (isSimpleTranslate) { 579 // The validatePaintOp bounds above needed to use the original 580 // coordinates (prior to any translation below) for relative 581 // paint processing. 582 dx1 += transX; 583 dy1 += transY; 584 dx2 += transX; 585 dy2 += transY; 586 dh1 += transX; 587 dv1 += transY; 588 dh2 += transX; 589 dv2 += transY; 590 } 591 592 float pw = tex.getPhysicalWidth(); 593 float ph = tex.getPhysicalHeight(); 594 float cx1 = tex.getContentX(); 595 float cy1 = tex.getContentY(); 596 float tx1 = (cx1 + sx1) / pw; 597 float ty1 = (cy1 + sy1) / ph; 598 float tx2 = (cx1 + sx2) / pw; 599 float ty2 = (cy1 + sy2) / ph; 600 float th1 = (cx1 + sh1) / pw; 601 float tv1 = (cy1 + sv1) / ph; 602 float th2 = (cx1 + sh2) / pw; 603 float tv2 = (cy1 + sv2) / ph; 604 605 VertexBuffer vb = context.getVertexBuffer(); 606 if (context.isSuperShaderEnabled()) { 607 vb.addSuperQuad(dx1, dy1, dh1, dv1, tx1, ty1, th1, tv1, false); 608 vb.addSuperQuad(dh1, dy1, dh2, dv1, th1, ty1, th2, tv1, false); 609 vb.addSuperQuad(dh2, dy1, dx2, dv1, th2, ty1, tx2, tv1, false); 610 611 vb.addSuperQuad(dx1, dv1, dh1, dv2, tx1, tv1, th1, tv2, false); 612 vb.addSuperQuad(dh1, dv1, dh2, dv2, th1, tv1, th2, tv2, false); 613 vb.addSuperQuad(dh2, dv1, dx2, dv2, th2, tv1, tx2, tv2, false); 614 615 vb.addSuperQuad(dx1, dv2, dh1, dy2, tx1, tv2, th1, ty2, false); 616 vb.addSuperQuad(dh1, dv2, dh2, dy2, th1, tv2, th2, ty2, false); 617 vb.addSuperQuad(dh2, dv2, dx2, dy2, th2, tv2, tx2, ty2, false); 618 } else { 619 vb.addQuad(dx1, dy1, dh1, dv1, tx1, ty1, th1, tv1); 620 vb.addQuad(dh1, dy1, dh2, dv1, th1, ty1, th2, tv1); 621 vb.addQuad(dh2, dy1, dx2, dv1, th2, ty1, tx2, tv1); 622 623 vb.addQuad(dx1, dv1, dh1, dv2, tx1, tv1, th1, tv2); 624 vb.addQuad(dh1, dv1, dh2, dv2, th1, tv1, th2, tv2); 625 vb.addQuad(dh2, dv1, dx2, dv2, th2, tv1, tx2, tv2); 626 627 vb.addQuad(dx1, dv2, dh1, dy2, tx1, tv2, th1, ty2); 628 vb.addQuad(dh1, dv2, dh2, dy2, th1, tv2, th2, ty2); 629 vb.addQuad(dh2, dv2, dx2, dy2, th2, tv2, tx2, ty2); 630 } 631 } 632 633 public void drawTextureVO(Texture tex, 634 float topopacity, float botopacity, 635 float dx1, float dy1, float dx2, float dy2, 636 float sx1, float sy1, float sx2, float sy2) 637 { 638 BaseTransform xform = isSimpleTranslate ? IDENT : getTransformNoClone(); 639 PixelFormat format = tex.getPixelFormat(); 640 if (format == PixelFormat.BYTE_ALPHA) { 641 // Note that we treat this as a paint operation, using the 642 // given texture as the alpha mask; perhaps it would be better 643 // to treat this as a separate operation from drawTexture(), but 644 // overloading drawTexture() seems like an equally valid option. 645 context.validatePaintOp(this, xform, tex, dx1, dy1, dx2-dx1, dy2-dy1); 646 } else { 647 context.validateTextureOp(this, xform, tex, format); 648 } 649 if (isSimpleTranslate) { 650 // The validatePaintOp bounds above needed to use the original 651 // coordinates (prior to any translation below) for relative 652 // paint processing. 653 dx1 += transX; 654 dy1 += transY; 655 dx2 += transX; 656 dy2 += transY; 657 } 658 659 float tw = tex.getPhysicalWidth(); 660 float th = tex.getPhysicalHeight(); 661 float cx1 = tex.getContentX(); 662 float cy1 = tex.getContentY(); 663 float tx1 = (cx1 + sx1) / tw; 664 float ty1 = (cy1 + sy1) / th; 665 float tx2 = (cx1 + sx2) / tw; 666 float ty2 = (cy1 + sy2) / th; 667 668 VertexBuffer vb = context.getVertexBuffer(); 669 if (topopacity == 1f && botopacity == 1f) { 670 vb.addQuad(dx1, dy1, dx2, dy2, 671 tx1, ty1, tx2, ty2); 672 } else { 673 topopacity *= getExtraAlpha(); 674 botopacity *= getExtraAlpha(); 675 vb.addQuadVO(topopacity, botopacity, 676 dx1, dy1, dx2, dy2, 677 tx1, ty1, tx2, ty2); 678 } 679 } 680 681 public void drawTextureRaw(Texture tex, 682 float dx1, float dy1, float dx2, float dy2, 683 float tx1, float ty1, float tx2, float ty2) 684 { 685 // Capture the original bounds (prior to any translation below), 686 // which will be needed in the mask case. 687 // NOTE: note that we currently assume (here and throughout this 688 // method) that dx1<=dx2 and dy1<=dy2; the scenegraph does not rely 689 // on flipping behavior, but this method will need to be fixed if 690 // that assumption becomes invalid... 691 float bx = dx1; 692 float by = dy1; 693 float bw = dx2 - dx1; 694 float bh = dy2 - dy1; 695 696 // The following is safe; this method does not mutate the transform 697 BaseTransform xform = getTransformNoClone(); 698 if (isSimpleTranslate) { 699 xform = IDENT; 700 dx1 += transX; 701 dy1 += transY; 702 dx2 += transX; 703 dy2 += transY; 704 } 705 706 PixelFormat format = tex.getPixelFormat(); 707 if (format == PixelFormat.BYTE_ALPHA) { 708 // Note that we treat this as a paint operation, using the 709 // given texture as the alpha mask; perhaps it would be better 710 // to treat this as a separate operation from drawTexture(), but 711 // overloading drawTexture() seems like an equally valid option. 712 context.validatePaintOp(this, xform, tex, bx, by, bw, bh); 713 } else { 714 context.validateTextureOp(this, xform, tex, format); 715 } 716 717 VertexBuffer vb = context.getVertexBuffer(); 718 vb.addQuad(dx1, dy1, dx2, dy2, 719 tx1, ty1, tx2, ty2); 720 } 721 722 public void drawMappedTextureRaw(Texture tex, 723 float dx1, float dy1, float dx2, float dy2, 724 float tx11, float ty11, float tx21, float ty21, 725 float tx12, float ty12, float tx22, float ty22) 726 { 727 // Capture the original bounds (prior to any translation below), 728 // which will be needed in the mask case. 729 // NOTE: note that we currently assume (here and throughout this 730 // method) that dx1<=dx2 and dy1<=dy2; the scenegraph does not rely 731 // on flipping behavior, but this method will need to be fixed if 732 // that assumption becomes invalid... 733 float bx = dx1; 734 float by = dy1; 735 float bw = dx2 - dx1; 736 float bh = dy2 - dy1; 737 738 // The following is safe; this method does not mutate the transform 739 BaseTransform xform = getTransformNoClone(); 740 if (isSimpleTranslate) { 741 xform = IDENT; 742 dx1 += transX; 743 dy1 += transY; 744 dx2 += transX; 745 dy2 += transY; 746 } 747 748 PixelFormat format = tex.getPixelFormat(); 749 if (format == PixelFormat.BYTE_ALPHA) { 750 // Note that we treat this as a paint operation, using the 751 // given texture as the alpha mask; perhaps it would be better 752 // to treat this as a separate operation from drawTexture(), but 753 // overloading drawTexture() seems like an equally valid option. 754 context.validatePaintOp(this, xform, tex, bx, by, bw, bh); 755 } else { 756 context.validateTextureOp(this, xform, tex, format); 757 } 758 759 VertexBuffer vb = context.getVertexBuffer(); 760 vb.addMappedQuad(dx1, dy1, dx2, dy2, 761 tx11, ty11, tx21, ty21, 762 tx12, ty12, tx22, ty22); 763 } 764 765 }