Showing the changes to java/pkg/sun/java2d/pipe/BufferedRenderPipe.java (1 of 18352 files). Show all
Unified · Split
| @@ -0,0 +1,601 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2005, 2008, 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.pipe; | ||
| 27 | |||
| 28 | import java.awt.BasicStroke; | ||
| 29 | import java.awt.Polygon; | ||
| 30 | import java.awt.Shape; | ||
| 31 | import java.awt.geom.AffineTransform; | ||
| 32 | import java.awt.geom.Arc2D; | ||
| 33 | import java.awt.geom.Ellipse2D; | ||
| 34 | import java.awt.geom.Path2D; | ||
| 35 | import java.awt.geom.IllegalPathStateException; | ||
| 36 | import java.awt.geom.PathIterator; | ||
| 37 | import java.awt.geom.Rectangle2D; | ||
| 38 | import java.awt.geom.RoundRectangle2D; | ||
| 39 | import sun.java2d.SunGraphics2D; | ||
| 40 | import sun.java2d.loops.ProcessPath; | ||
| 41 | import static sun.java2d.pipe.BufferedOpCodes.*; | ||
| 42 | |||
| 43 | /** | ||
| 44 | * Base class for enqueuing rendering operations in a single-threaded | ||
| 45 | * rendering environment. Instead of each operation being rendered | ||
| 46 | * immediately by the underlying graphics library, the operation will be | ||
| 47 | * added to the provided RenderQueue, which will be processed at a later | ||
| 48 | * time by a single thread. | ||
| 49 | * | ||
| 50 | * This class provides implementations of drawLine(), drawRect(), drawPoly(), | ||
| 51 | * fillRect(), draw(Shape), and fill(Shape), which are useful for a | ||
| 52 | * hardware-accelerated renderer. The other draw*() and fill*() methods | ||
| 53 | * simply delegate to draw(Shape) and fill(Shape), respectively. | ||
| 54 | */ | ||
| 55 | public abstract class BufferedRenderPipe | ||
| 56 | implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe, ParallelogramPipe | ||
| 57 | { | ||
| 58 | ParallelogramPipe aapgrampipe = new AAParallelogramPipe(); | ||
| 59 | |||
| 60 | static final int BYTES_PER_POLY_POINT = 8; | ||
| 61 | static final int BYTES_PER_SCANLINE = 12; | ||
| 62 | static final int BYTES_PER_SPAN = 16; | ||
| 63 | |||
| 64 | protected RenderQueue rq; | ||
| 65 | protected RenderBuffer buf; | ||
| 66 | private BufferedDrawHandler drawHandler; | ||
| 67 | |||
| 68 | public BufferedRenderPipe(RenderQueue rq) { | ||
| 69 | this.rq = rq; | ||
| 70 | this.buf = rq.getBuffer(); | ||
| 71 | this.drawHandler = new BufferedDrawHandler(); | ||
| 72 | } | ||
| 73 | |||
| 74 | public ParallelogramPipe getAAParallelogramPipe() { | ||
| 75 | return aapgrampipe; | ||
| 76 | } | ||
| 77 | |||
| 78 | /** | ||
| 79 | * Validates the state in the provided SunGraphics2D object and sets up | ||
| 80 | * any special resources for this operation (e.g. enabling gradient | ||
| 81 | * shading). | ||
| 82 | */ | ||
| 83 | protected abstract void validateContext(SunGraphics2D sg2d); | ||
| 84 | protected abstract void validateContextAA(SunGraphics2D sg2d); | ||
| 85 | |||
| 86 | public void drawLine(SunGraphics2D sg2d, | ||
| 87 | int x1, int y1, int x2, int y2) | ||
| 88 | { | ||
| 89 | int transx = sg2d.transX; | ||
| 90 | int transy = sg2d.transY; | ||
| 91 | rq.lock(); | ||
| 92 | try { | ||
| 93 | validateContext(sg2d); | ||
| 94 | rq.ensureCapacity(20); | ||
| 95 | buf.putInt(DRAW_LINE); | ||
| 96 | buf.putInt(x1 + transx); | ||
| 97 | buf.putInt(y1 + transy); | ||
| 98 | buf.putInt(x2 + transx); | ||
| 99 | buf.putInt(y2 + transy); | ||
| 100 | } finally { | ||
| 101 | rq.unlock(); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | public void drawRect(SunGraphics2D sg2d, | ||
| 106 | int x, int y, int width, int height) | ||
| 107 | { | ||
| 108 | rq.lock(); | ||
| 109 | try { | ||
| 110 | validateContext(sg2d); | ||
| 111 | rq.ensureCapacity(20); | ||
| 112 | buf.putInt(DRAW_RECT); | ||
| 113 | buf.putInt(x + sg2d.transX); | ||
| 114 | buf.putInt(y + sg2d.transY); | ||
| 115 | buf.putInt(width); | ||
| 116 | buf.putInt(height); | ||
| 117 | } finally { | ||
| 118 | rq.unlock(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | public void fillRect(SunGraphics2D sg2d, | ||
| 123 | int x, int y, int width, int height) | ||
| 124 | { | ||
| 125 | rq.lock(); | ||
| 126 | try { | ||
| 127 | validateContext(sg2d); | ||
| 128 | rq.ensureCapacity(20); | ||
| 129 | buf.putInt(FILL_RECT); | ||
| 130 | buf.putInt(x + sg2d.transX); | ||
| 131 | buf.putInt(y + sg2d.transY); | ||
| 132 | buf.putInt(width); | ||
| 133 | buf.putInt(height); | ||
| 134 | } finally { | ||
| 135 | rq.unlock(); | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | public void drawRoundRect(SunGraphics2D sg2d, | ||
| 140 | int x, int y, int width, int height, | ||
| 141 | int arcWidth, int arcHeight) | ||
| 142 | { | ||
| 143 | draw(sg2d, new RoundRectangle2D.Float(x, y, width, height, | ||
| 144 | arcWidth, arcHeight)); | ||
| 145 | } | ||
| 146 | |||
| 147 | public void fillRoundRect(SunGraphics2D sg2d, | ||
| 148 | int x, int y, int width, int height, | ||
| 149 | int arcWidth, int arcHeight) | ||
| 150 | { | ||
| 151 | fill(sg2d, new RoundRectangle2D.Float(x, y, width, height, | ||
| 152 | arcWidth, arcHeight)); | ||
| 153 | } | ||
| 154 | |||
| 155 | public void drawOval(SunGraphics2D sg2d, | ||
| 156 | int x, int y, int width, int height) | ||
| 157 | { | ||
| 158 | draw(sg2d, new Ellipse2D.Float(x, y, width, height)); | ||
| 159 | } | ||
| 160 | |||
| 161 | public void fillOval(SunGraphics2D sg2d, | ||
| 162 | int x, int y, int width, int height) | ||
| 163 | { | ||
| 164 | fill(sg2d, new Ellipse2D.Float(x, y, width, height)); | ||
| 165 | } | ||
| 166 | |||
| 167 | public void drawArc(SunGraphics2D sg2d, | ||
| 168 | int x, int y, int width, int height, | ||
| 169 | int startAngle, int arcAngle) | ||
| 170 | { | ||
| 171 | draw(sg2d, new Arc2D.Float(x, y, width, height, | ||
| 172 | startAngle, arcAngle, | ||
| 173 | Arc2D.OPEN)); | ||
| 174 | } | ||
| 175 | |||
| 176 | public void fillArc(SunGraphics2D sg2d, | ||
| 177 | int x, int y, int width, int height, | ||
| 178 | int startAngle, int arcAngle) | ||
| 179 | { | ||
| 180 | fill(sg2d, new Arc2D.Float(x, y, width, height, | ||
| 181 | startAngle, arcAngle, | ||
| 182 | Arc2D.PIE)); | ||
| 183 | } | ||
| 184 | |||
| 185 | protected void drawPoly(final SunGraphics2D sg2d, | ||
| 186 | final int[] xPoints, final int[] yPoints, | ||
| 187 | final int nPoints, final boolean isClosed) | ||
| 188 | { | ||
| 189 | if (xPoints == null || yPoints == null) { | ||
| 190 | throw new NullPointerException("coordinate array"); | ||
| 191 | } | ||
| 192 | if (xPoints.length < nPoints || yPoints.length < nPoints) { | ||
| 193 | throw new ArrayIndexOutOfBoundsException("coordinate array"); | ||
| 194 | } | ||
| 195 | |||
| 196 | if (nPoints < 2) { | ||
| 197 | // render nothing | ||
| 198 | return; | ||
| 199 | } else if (nPoints == 2 && !isClosed) { | ||
| 200 | // render a simple line | ||
| 201 | drawLine(sg2d, xPoints[0], yPoints[0], xPoints[1], yPoints[1]); | ||
| 202 | return; | ||
| 203 | } | ||
| 204 | |||
| 205 | rq.lock(); | ||
| 206 | try { | ||
| 207 | validateContext(sg2d); | ||
| 208 | |||
| 209 | int pointBytesRequired = nPoints * BYTES_PER_POLY_POINT; | ||
| 210 | int totalBytesRequired = 20 + pointBytesRequired; | ||
| 211 | |||
| 212 | if (totalBytesRequired <= buf.capacity()) { | ||
| 213 | if (totalBytesRequired > buf.remaining()) { | ||
| 214 | // process the queue first and then enqueue the points | ||
| 215 | rq.flushNow(); | ||
| 216 | } | ||
| 217 | buf.putInt(DRAW_POLY); | ||
| 218 | // enqueue parameters | ||
| 219 | buf.putInt(nPoints); | ||
| 220 | buf.putInt(isClosed ? 1 : 0); | ||
| 221 | buf.putInt(sg2d.transX); | ||
| 222 | buf.putInt(sg2d.transY); | ||
| 223 | // enqueue the points | ||
| 224 | buf.put(xPoints, 0, nPoints); | ||
| 225 | buf.put(yPoints, 0, nPoints); | ||
| 226 | } else { | ||
| 227 | // queue is too small to accomodate all points; perform the | ||
| 228 | // operation directly on the queue flushing thread | ||
| 229 | rq.flushAndInvokeNow(new Runnable() { | ||
| 230 | public void run() { | ||
| 231 | drawPoly(xPoints, yPoints, | ||
| 232 | nPoints, isClosed, | ||
| 233 | sg2d.transX, sg2d.transY); | ||
| 234 | } | ||
| 235 | }); | ||
| 236 | } | ||
| 237 | } finally { | ||
| 238 | rq.unlock(); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | protected abstract void drawPoly(int[] xPoints, int[] yPoints, | ||
| 243 | int nPoints, boolean isClosed, | ||
| 244 | int transX, int transY); | ||
| 245 | |||
| 246 | public void drawPolyline(SunGraphics2D sg2d, | ||
| 247 | int[] xPoints, int[] yPoints, | ||
| 248 | int nPoints) | ||
| 249 | { | ||
| 250 | drawPoly(sg2d, xPoints, yPoints, nPoints, false); | ||
| 251 | } | ||
| 252 | |||
| 253 | public void drawPolygon(SunGraphics2D sg2d, | ||
| 254 | int[] xPoints, int[] yPoints, | ||
| 255 | int nPoints) | ||
| 256 | { | ||
| 257 | drawPoly(sg2d, xPoints, yPoints, nPoints, true); | ||
| 258 | } | ||
| 259 | |||
| 260 | public void fillPolygon(SunGraphics2D sg2d, | ||
| 261 | int[] xPoints, int[] yPoints, | ||
| 262 | int nPoints) | ||
| 263 | { | ||
| 264 | fill(sg2d, new Polygon(xPoints, yPoints, nPoints)); | ||
| 265 | } | ||
| 266 | |||
| 267 | private class BufferedDrawHandler | ||
| 268 | extends ProcessPath.DrawHandler | ||
| 269 | { | ||
| 270 | BufferedDrawHandler() { | ||
| 271 | // these are bogus values; the caller will use validate() | ||
| 272 | // to ensure that they are set properly prior to each usage | ||
| 273 | super(0, 0, 0, 0); | ||
| 274 | } | ||
| 275 | |||
| 276 | /** | ||
| 277 | * This method needs to be called prior to each draw/fillPath() | ||
| 278 | * operation to ensure the clip bounds are up to date. | ||
| 279 | */ | ||
| 280 | void validate(SunGraphics2D sg2d) { | ||
| 281 | Region clip = sg2d.getCompClip(); | ||
| 282 | setBounds(clip.getLoX(), clip.getLoY(), | ||
| 283 | clip.getHiX(), clip.getHiY(), | ||
| 284 | sg2d.strokeHint); | ||
| 285 | } | ||
| 286 | |||
| 287 | /** | ||
| 288 | * drawPath() support... | ||
| 289 | */ | ||
| 290 | |||
| 291 | public void drawLine(int x1, int y1, int x2, int y2) { | ||
| 292 | // assert rq.lock.isHeldByCurrentThread(); | ||
| 293 | rq.ensureCapacity(20); | ||
| 294 | buf.putInt(DRAW_LINE); | ||
| 295 | buf.putInt(x1); | ||
| 296 | buf.putInt(y1); | ||
| 297 | buf.putInt(x2); | ||
| 298 | buf.putInt(y2); | ||
| 299 | } | ||
| 300 | |||
| 301 | public void drawPixel(int x, int y) { | ||
| 302 | // assert rq.lock.isHeldByCurrentThread(); | ||
| 303 | rq.ensureCapacity(12); | ||
| 304 | buf.putInt(DRAW_PIXEL); | ||
| 305 | buf.putInt(x); | ||
| 306 | buf.putInt(y); | ||
| 307 | } | ||
| 308 | |||
| 309 | /** | ||
| 310 | * fillPath() support... | ||
| 311 | */ | ||
| 312 | |||
| 313 | private int scanlineCount; | ||
| 314 | private int scanlineCountIndex; | ||
| 315 | private int remainingScanlines; | ||
| 316 | |||
| 317 | private void resetFillPath() { | ||
| 318 | buf.putInt(DRAW_SCANLINES); | ||
| 319 | scanlineCountIndex = buf.position(); | ||
| 320 | buf.putInt(0); | ||
| 321 | scanlineCount = 0; | ||
| 322 | remainingScanlines = buf.remaining() / BYTES_PER_SCANLINE; | ||
| 323 | } | ||
| 324 | |||
| 325 | private void updateScanlineCount() { | ||
| 326 | buf.putInt(scanlineCountIndex, scanlineCount); | ||
| 327 | } | ||
| 328 | |||
| 329 | /** | ||
| 330 | * Called from fillPath() to indicate that we are about to | ||
| 331 | * start issuing drawScanline() calls. | ||
| 332 | */ | ||
| 333 | public void startFillPath() { | ||
| 334 | rq.ensureCapacity(20); // to ensure room for at least a scanline | ||
| 335 | resetFillPath(); | ||
| 336 | } | ||
| 337 | |||
| 338 | public void drawScanline(int x1, int x2, int y) { | ||
| 339 | if (remainingScanlines == 0) { | ||
| 340 | updateScanlineCount(); | ||
| 341 | rq.flushNow(); | ||
| 342 | resetFillPath(); | ||
| 343 | } | ||
| 344 | buf.putInt(x1); | ||
| 345 | buf.putInt(x2); | ||
| 346 | buf.putInt(y); | ||
| 347 | scanlineCount++; | ||
| 348 | remainingScanlines--; | ||
| 349 | } | ||
| 350 | |||
| 351 | /** | ||
| 352 | * Called from fillPath() to indicate that we are done | ||
| 353 | * issuing drawScanline() calls. | ||
| 354 | */ | ||
| 355 | public void endFillPath() { | ||
| 356 | updateScanlineCount(); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | protected void drawPath(SunGraphics2D sg2d, | ||
| 361 | Path2D.Float p2df, int transx, int transy) | ||
| 362 | { | ||
| 363 | rq.lock(); | ||
| 364 | try { | ||
| 365 | validateContext(sg2d); | ||
| 366 | drawHandler.validate(sg2d); | ||
| 367 | ProcessPath.drawPath(drawHandler, p2df, transx, transy); | ||
| 368 | } finally { | ||
| 369 | rq.unlock(); | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 373 | protected void fillPath(SunGraphics2D sg2d, | ||
| 374 | Path2D.Float p2df, int transx, int transy) | ||
| 375 | { | ||
| 376 | rq.lock(); | ||
| 377 | try { | ||
| 378 | validateContext(sg2d); | ||
| 379 | drawHandler.validate(sg2d); | ||
| 380 | drawHandler.startFillPath(); | ||
| 381 | ProcessPath.fillPath(drawHandler, p2df, transx, transy); | ||
| 382 | drawHandler.endFillPath(); | ||
| 383 | } finally { | ||
| 384 | rq.unlock(); | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | private native int fillSpans(RenderQueue rq, long buf, | ||
| 389 | int pos, int limit, | ||
| 390 | SpanIterator si, long iterator, | ||
| 391 | int transx, int transy); | ||
| 392 | |||
| 393 | protected void fillSpans(SunGraphics2D sg2d, SpanIterator si, | ||
| 394 | int transx, int transy) | ||
| 395 | { | ||
| 396 | rq.lock(); | ||
| 397 | try { | ||
| 398 | validateContext(sg2d); | ||
| 399 | rq.ensureCapacity(24); // so that we have room for at least a span | ||
| 400 | int newpos = fillSpans(rq, buf.getAddress(), | ||
| 401 | buf.position(), buf.capacity(), | ||
| 402 | si, si.getNativeIterator(), | ||
| 403 | transx, transy); | ||
| 404 | buf.position(newpos); | ||
| 405 | } finally { | ||
| 406 | rq.unlock(); | ||
| 407 | } | ||
| 408 | } | ||
| 409 | |||
| 410 | public void fillParallelogram(SunGraphics2D sg2d, | ||
| 411 | double ux1, double uy1, | ||
| 412 | double ux2, double uy2, | ||
| 413 | double x, double y, | ||
| 414 | double dx1, double dy1, | ||
| 415 | double dx2, double dy2) | ||
| 416 | { | ||
| 417 | rq.lock(); | ||
| 418 | try { | ||
| 419 | validateContext(sg2d); | ||
| 420 | rq.ensureCapacity(28); | ||
| 421 | buf.putInt(FILL_PARALLELOGRAM); | ||
| 422 | buf.putFloat((float) x); | ||
| 423 | buf.putFloat((float) y); | ||
| 424 | buf.putFloat((float) dx1); | ||
| 425 | buf.putFloat((float) dy1); | ||
| 426 | buf.putFloat((float) dx2); | ||
| 427 | buf.putFloat((float) dy2); | ||
| 428 | } finally { | ||
| 429 | rq.unlock(); | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | public void drawParallelogram(SunGraphics2D sg2d, | ||
| 434 | double ux1, double uy1, | ||
| 435 | double ux2, double uy2, | ||
| 436 | double x, double y, | ||
| 437 | double dx1, double dy1, | ||
| 438 | double dx2, double dy2, | ||
| 439 | double lw1, double lw2) | ||
| 440 | { | ||
| 441 | rq.lock(); | ||
| 442 | try { | ||
| 443 | validateContext(sg2d); | ||
| 444 | rq.ensureCapacity(36); | ||
| 445 | buf.putInt(DRAW_PARALLELOGRAM); | ||
| 446 | buf.putFloat((float) x); | ||
| 447 | buf.putFloat((float) y); | ||
| 448 | buf.putFloat((float) dx1); | ||
| 449 | buf.putFloat((float) dy1); | ||
| 450 | buf.putFloat((float) dx2); | ||
| 451 | buf.putFloat((float) dy2); | ||
| 452 | buf.putFloat((float) lw1); | ||
| 453 | buf.putFloat((float) lw2); | ||
| 454 | } finally { | ||
| 455 | rq.unlock(); | ||
| 456 | } | ||
| 457 | } | ||
| 458 | |||
| 459 | private class AAParallelogramPipe implements ParallelogramPipe { | ||
| 460 | public void fillParallelogram(SunGraphics2D sg2d, | ||
| 461 | double ux1, double uy1, | ||
| 462 | double ux2, double uy2, | ||
| 463 | double x, double y, | ||
| 464 | double dx1, double dy1, | ||
| 465 | double dx2, double dy2) | ||
| 466 | { | ||
| 467 | rq.lock(); | ||
| 468 | try { | ||
| 469 | validateContextAA(sg2d); | ||
| 470 | rq.ensureCapacity(28); | ||
| 471 | buf.putInt(FILL_AAPARALLELOGRAM); | ||
| 472 | buf.putFloat((float) x); | ||
| 473 | buf.putFloat((float) y); | ||
| 474 | buf.putFloat((float) dx1); | ||
| 475 | buf.putFloat((float) dy1); | ||
| 476 | buf.putFloat((float) dx2); | ||
| 477 | buf.putFloat((float) dy2); | ||
| 478 | } finally { | ||
| 479 | rq.unlock(); | ||
| 480 | } | ||
| 481 | } | ||
| 482 | |||
| 483 | public void drawParallelogram(SunGraphics2D sg2d, | ||
| 484 | double ux1, double uy1, | ||
| 485 | double ux2, double uy2, | ||
| 486 | double x, double y, | ||
| 487 | double dx1, double dy1, | ||
| 488 | double dx2, double dy2, | ||
| 489 | double lw1, double lw2) | ||
| 490 | { | ||
| 491 | rq.lock(); | ||
| 492 | try { | ||
| 493 | validateContextAA(sg2d); | ||
| 494 | rq.ensureCapacity(36); | ||
| 495 | buf.putInt(DRAW_AAPARALLELOGRAM); | ||
| 496 | buf.putFloat((float) x); | ||
| 497 | buf.putFloat((float) y); | ||
| 498 | buf.putFloat((float) dx1); | ||
| 499 | buf.putFloat((float) dy1); | ||
| 500 | buf.putFloat((float) dx2); | ||
| 501 | buf.putFloat((float) dy2); | ||
| 502 | buf.putFloat((float) lw1); | ||
| 503 | buf.putFloat((float) lw2); | ||
| 504 | } finally { | ||
| 505 | rq.unlock(); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | } | ||
| 509 | |||
| 510 | public void draw(SunGraphics2D sg2d, Shape s) { | ||
| 511 | if (sg2d.strokeState == sg2d.STROKE_THIN) { | ||
| 512 | if (s instanceof Polygon) { | ||
| 513 | if (sg2d.transformState < sg2d.TRANSFORM_TRANSLATESCALE) { | ||
| 514 | Polygon p = (Polygon)s; | ||
| 515 | drawPolygon(sg2d, p.xpoints, p.ypoints, p.npoints); | ||
| 516 | return; | ||
| 517 | } | ||
| 518 | } | ||
| 519 | Path2D.Float p2df; | ||
| 520 | int transx, transy; | ||
| 521 | if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) { | ||
| 522 | if (s instanceof Path2D.Float) { | ||
| 523 | p2df = (Path2D.Float)s; | ||
| 524 | } else { | ||
| 525 | p2df = new Path2D.Float(s); | ||
| 526 | } | ||
| 527 | transx = sg2d.transX; | ||
| 528 | transy = sg2d.transY; | ||
| 529 | } else { | ||
| 530 | p2df = new Path2D.Float(s, sg2d.transform); | ||
| 531 | transx = 0; | ||
| 532 | transy = 0; | ||
| 533 | } | ||
| 534 | drawPath(sg2d, p2df, transx, transy); | ||
| 535 | } else if (sg2d.strokeState < sg2d.STROKE_CUSTOM) { | ||
| 536 | ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s); | ||
| 537 | try { | ||
| 538 | fillSpans(sg2d, si, 0, 0); | ||
| 539 | } finally { | ||
| 540 | si.dispose(); | ||
| 541 | } | ||
| 542 | } else { | ||
| 543 | fill(sg2d, sg2d.stroke.createStrokedShape(s)); | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | public void fill(SunGraphics2D sg2d, Shape s) { | ||
| 548 | int transx, transy; | ||
| 549 | |||
| 550 | if (sg2d.strokeState == sg2d.STROKE_THIN) { | ||
| 551 | // Here we are able to use fillPath() for | ||
| 552 | // high-quality fills. | ||
| 553 | Path2D.Float p2df; | ||
| 554 | if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) { | ||
| 555 | if (s instanceof Path2D.Float) { | ||
| 556 | p2df = (Path2D.Float)s; | ||
| 557 | } else { | ||
| 558 | p2df = new Path2D.Float(s); | ||
| 559 | } | ||
| 560 | transx = sg2d.transX; | ||
| 561 | transy = sg2d.transY; | ||
| 562 | } else { | ||
| 563 | p2df = new Path2D.Float(s, sg2d.transform); | ||
| 564 | transx = 0; | ||
| 565 | transy = 0; | ||
| 566 | } | ||
| 567 | fillPath(sg2d, p2df, transx, transy); | ||
| 568 | return; | ||
| 569 | } | ||
| 570 | |||
| 571 | AffineTransform at; | ||
| 572 | if (sg2d.transformState <= sg2d.TRANSFORM_INT_TRANSLATE) { | ||
| 573 | // Transform (translation) will be done by FillSpans (we could | ||
| 574 | // delegate to fillPolygon() here, but most hardware accelerated | ||
| 575 | // libraries cannot handle non-convex polygons, so we will use | ||
| 576 | // the FillSpans approach by default) | ||
| 577 | at = null; | ||
| 578 | transx = sg2d.transX; | ||
| 579 | transy = sg2d.transY; | ||
| 580 | } else { | ||
| 581 | // Transform will be done by the PathIterator | ||
| 582 | at = sg2d.transform; | ||
| 583 | transx = transy = 0; | ||
| 584 | } | ||
| 585 | |||
| 586 | ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d); | ||
| 587 | try { | ||
| 588 | // Subtract transx/y from the SSI clip to match the | ||
| 589 | // (potentially untranslated) geometry fed to it | ||
| 590 | Region clip = sg2d.getCompClip(); | ||
| 591 | ssi.setOutputAreaXYXY(clip.getLoX() - transx, | ||
| 592 | clip.getLoY() - transy, | ||
| 593 | clip.getHiX() - transx, | ||
| 594 | clip.getHiY() - transy); | ||
| 595 | ssi.appendPath(s.getPathIterator(at)); | ||
| 596 | fillSpans(sg2d, ssi, transx, transy); | ||
| 597 | } finally { | ||
| 598 | ssi.dispose(); | ||
| 599 | } | ||
| 600 | } | ||
| 601 | } | ||