Source Code Cross Referenced for Renderer.java in  » 6.0-JDK-Modules » j2me » com » sun » pisces » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » j2me » com.sun.pisces 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * 
0003:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved. 
0004:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER 
0005:         *  
0006:         * This program is free software; you can redistribute it and/or 
0007:         * modify it under the terms of the GNU General Public License version 
0008:         * 2 only, as published by the Free Software Foundation. 
0009:         *  
0010:         * This program is distributed in the hope that it will be useful, but 
0011:         * WITHOUT ANY WARRANTY; without even the implied warranty of 
0012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
0013:         * General Public License version 2 for more details (a copy is 
0014:         * included at /legal/license.txt). 
0015:         *  
0016:         * You should have received a copy of the GNU General Public License 
0017:         * version 2 along with this work; if not, write to the Free Software 
0018:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 
0019:         * 02110-1301 USA 
0020:         *  
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 
0022:         * Clara, CA 95054 or visit www.sun.com if you need additional 
0023:         * information or have any questions.
0024:         */
0025:
0026:        package com.sun.pisces;
0027:
0028:        public class Renderer extends RendererBase {
0029:
0030:            // Initial edge list size
0031:            // IMPL_NOTE - restore size after growth
0032:            public static final int INITIAL_EDGES = 1000;
0033:
0034:            // Recommended maximum scratchpad sizes.  The arrays will grow
0035:            // larger if needed, but when finished() is called they will be released
0036:            // if they have grown larger than these sizes.
0037:            public static final int DEFAULT_INDICES_SIZE = 8192;
0038:            public static final int DEFAULT_CROSSINGS_SIZE = 32 * 1024;
0039:
0040:            public static final int NUM_ALPHA_ROWS = 8;
0041:
0042:            // Antialiasing
0043:            private int SUBPIXEL_LG_POSITIONS_X;
0044:            private int SUBPIXEL_LG_POSITIONS_Y;
0045:            private int SUBPIXEL_MASK_X;
0046:            private int SUBPIXEL_MASK_Y;
0047:            private int SUBPIXEL_POSITIONS_X;
0048:            private int SUBPIXEL_POSITIONS_Y;
0049:            private int MAX_AA_ALPHA;
0050:            private int MAX_AA_ALPHA_DENOM;
0051:            private int HALF_MAX_AA_ALPHA_DENOM;
0052:            private int XSHIFT;
0053:            private int YSHIFT;
0054:            private int YSTEP;
0055:            private int HYSTEP;
0056:            private int YMASK;
0057:
0058:            private static final int MIN_QUAD_OPT_WIDTH = 100 << 16;
0059:
0060:            // Cache to store RLE-encoded coverage mask of the current primitive
0061:            PiscesCache cache = null;
0062:
0063:            // Bounds of the drawing region, at S15.16 precsion
0064:            private int boundsMinX, boundsMinY, boundsMaxX, boundsMaxY;
0065:
0066:            // Bounds of the current primitive, at subsample precision
0067:            private int rasterMinX, rasterMaxX, rasterMinY, rasterMaxY;
0068:
0069:            // Pixel bounding box for current primitive
0070:            private int bboxX0, bboxY0, bboxX1, bboxY1;
0071:
0072:            // Current winding rule
0073:            private int windingRule = WIND_NON_ZERO;
0074:
0075:            // Current drawing position, i.e., final point of last segment
0076:            private int x0, y0;
0077:
0078:            // Position of most recent 'moveTo' command
0079:            private int sx0, sy0;
0080:
0081:            // Buffer to be filled with one row's worth of alpha values
0082:            private byte[] rowAA = null; // needs to be short if 16x16 subsampling
0083:
0084:            private int[] paintBuffer = null;
0085:            private int paintBufferOffset;
0086:            private int paintBufferStride;
0087:
0088:            // Image information
0089:            private int width, height;
0090:
0091:            private Object imageData;
0092:            private int imageOffset;
0093:            private int imageScanlineStride;
0094:            private int imagePixelStride;
0095:
0096:            private static final int PAINT_FLAT_COLOR = 0;
0097:            private static final int PAINT_LINEAR_GRADIENT = 1;
0098:            private static final int PAINT_RADIAL_GRADIENT = 2;
0099:            private static final int PAINT_TEXTURE = 3;
0100:
0101:            private int paintMode = PAINT_FLAT_COLOR;
0102:            private int cred, cgreen, cblue, calpha;
0103:            Paint paint;
0104:
0105:            // Map from [0, MAX_AA_ALPHA] to [0, 256]
0106:            // Used to normalize alpha processing to 8 bits
0107:            private int[] alphaMap = new int[16 * 16 + 1];
0108:
0109:            private int compositeRule = Blit.COMPOSITE_SRC_OVER;
0110:
0111:            // Track the number of vertical extrema of the incoming edge list
0112:            // in order to determine the maximum number of crossings of a
0113:            // scanline
0114:            private int firstOrientation = 0;
0115:            private int lastOrientation = 0;
0116:            private int flips = 0;
0117:
0118:            // Parameters for emitRow
0119:            private int rowAAOffset;
0120:            private int rowNum;
0121:            private int alphaWidth;
0122:            private int[] minTouched = new int[NUM_ALPHA_ROWS];
0123:            private int[] maxTouched = new int[NUM_ALPHA_ROWS];
0124:            private int[] rowOffsets = new int[NUM_ALPHA_ROWS];
0125:            private int currX, currY;
0126:            private int currImageOffset;
0127:
0128:            public Renderer(Object imageData, int width, int height,
0129:                    int imageOffset, int imageScanlineStride,
0130:                    int imagePixelStride, int imageType) {
0131:                super (imageType);
0132:                this .imageData = imageData;
0133:                this .width = width;
0134:                this .height = height;
0135:                this .imageOffset = imageOffset;
0136:                this .imageScanlineStride = imageScanlineStride;
0137:                this .imagePixelStride = imagePixelStride;
0138:                this .imageType = imageType;
0139:
0140:                setAntialiasing(DEFAULT_SUBPIXEL_LG_POSITIONS_X,
0141:                        DEFAULT_SUBPIXEL_LG_POSITIONS_Y);
0142:            }
0143:
0144:            public void setImageData(Object imageData, int imageOffset,
0145:                    int imageScanlineStride, int imagePixelStride) {
0146:                this .imageData = imageData;
0147:                this .imageOffset = imageOffset;
0148:                this .imageScanlineStride = imageScanlineStride;
0149:                this .imagePixelStride = imagePixelStride;
0150:            }
0151:
0152:            // Create a lookup table indexed from 0 to MAX_AA_ALPHA, inclusive,
0153:            // containing normalized values for (index*alpha).  Normalization
0154:            // maps a value from 0 to MAX_AA_ALPHA*alpha into the range 0 to 256.
0155:            private void createAlphaMap(int alpha) {
0156:                for (int i = 0; i <= MAX_AA_ALPHA; i++) {
0157:                    alphaMap[i] = (256 * i * alpha + HALF_MAX_AA_ALPHA_DENOM)
0158:                            / MAX_AA_ALPHA_DENOM;
0159:                }
0160:            }
0161:
0162:            public void setAntialiasing(int subpixelLgPositionsX,
0163:                    int subpixelLgPositionsY) {
0164:                this .SUBPIXEL_LG_POSITIONS_X = subpixelLgPositionsX;
0165:                this .SUBPIXEL_LG_POSITIONS_Y = subpixelLgPositionsY;
0166:
0167:                this .SUBPIXEL_MASK_X = (1 << (SUBPIXEL_LG_POSITIONS_X)) - 1;
0168:                this .SUBPIXEL_MASK_Y = (1 << (SUBPIXEL_LG_POSITIONS_Y)) - 1;
0169:                this .SUBPIXEL_POSITIONS_X = 1 << (SUBPIXEL_LG_POSITIONS_X);
0170:                this .SUBPIXEL_POSITIONS_Y = 1 << (SUBPIXEL_LG_POSITIONS_Y);
0171:                this .MAX_AA_ALPHA = (SUBPIXEL_POSITIONS_X * SUBPIXEL_POSITIONS_Y);
0172:                this .MAX_AA_ALPHA_DENOM = 255 * MAX_AA_ALPHA;
0173:                this .HALF_MAX_AA_ALPHA_DENOM = MAX_AA_ALPHA_DENOM / 2;
0174:                this .XSHIFT = 16 - SUBPIXEL_LG_POSITIONS_X;
0175:                this .YSHIFT = 16 - SUBPIXEL_LG_POSITIONS_Y;
0176:                this .YSTEP = 1 << YSHIFT;
0177:                this .HYSTEP = 1 << (YSHIFT - 1);
0178:                this .YMASK = ~(YSTEP - 1);
0179:
0180:                createAlphaMap(this .calpha);
0181:            }
0182:
0183:            public int getSubpixelLgPositionsX() {
0184:                return SUBPIXEL_LG_POSITIONS_X;
0185:            }
0186:
0187:            public int getSubpixelLgPositionsY() {
0188:                return SUBPIXEL_LG_POSITIONS_Y;
0189:            }
0190:
0191:            public void setColor(int red, int green, int blue, int alpha) {
0192:                if (imageType == TYPE_INT_RGB || imageType == TYPE_INT_ARGB
0193:                        || imageType == TYPE_BYTE_GRAY) {
0194:                    this .cred = red;
0195:                    this .cgreen = green;
0196:                    this .cblue = blue;
0197:                } else if (imageType == TYPE_USHORT_565_RGB) {
0198:                    this .cred = Blit.convert8To5[red];
0199:                    this .cgreen = Blit.convert8To6[green];
0200:                    this .cblue = Blit.convert8To5[blue];
0201:                }
0202:
0203:                this .calpha = alpha;
0204:                createAlphaMap(calpha);
0205:
0206:                this .paint = null;
0207:                this .paintMode = PAINT_FLAT_COLOR;
0208:            }
0209:
0210:            public void setPaint(Paint paint) {
0211:                this .paint = paint;
0212:                createAlphaMap(255);
0213:
0214:                if (paint instanceof  LinearGradient) {
0215:                    this .paintMode = PAINT_LINEAR_GRADIENT;
0216:                } else if (paint instanceof  RadialGradient) {
0217:                    this .paintMode = PAINT_RADIAL_GRADIENT;
0218:                } else if (paint instanceof  Texture) {
0219:                    this .paintMode = PAINT_TEXTURE;
0220:                } else {
0221:                    throw new IllegalArgumentException("Unknown paint type!");
0222:                }
0223:            }
0224:
0225:            public void beginRendering(int boundsX, int boundsY,
0226:                    int boundsWidth, int boundsHeight, int windingRule) {
0227:                lastOrientation = 0;
0228:                flips = 0;
0229:
0230:                resetEdges();
0231:
0232:                this .boundsMinX = boundsX << 16;
0233:                this .boundsMinY = boundsY << 16;
0234:                this .boundsMaxX = (boundsX + boundsWidth) << 16;
0235:                this .boundsMaxY = (boundsY + boundsHeight) << 16;
0236:                this .windingRule = windingRule;
0237:
0238:                this .bboxX0 = boundsX;
0239:                this .bboxY0 = boundsY;
0240:                this .bboxX1 = boundsX + boundsWidth;
0241:                this .bboxY1 = boundsY + boundsHeight;
0242:            }
0243:
0244:            public void moveTo(int x0, int y0) {
0245:                // System.out.println("Renderer: moveTo " + x0/65536.0 + " " + y0/65536.0);
0246:                this .sx0 = this .x0 = x0;
0247:                this .sy0 = this .y0 = y0;
0248:                this .lastOrientation = 0;
0249:            }
0250:
0251:            public void lineJoin() {
0252:                // System.out.println("Renderer: lineJoin");
0253:                // do nothing
0254:            }
0255:
0256:            public void lineTo(int x1, int y1) {
0257:                // System.out.println("Renderer: lineTo " + x1/65536.0 + " " + y1/65536.0);
0258:
0259:                // Ignore horizontal lines
0260:                // Next line will count flip
0261:                if (y0 == y1) {
0262:                    this .x0 = x1;
0263:                    return;
0264:                }
0265:
0266:                int orientation = (y0 < y1) ? 1 : -1;
0267:                if (lastOrientation == 0) {
0268:                    firstOrientation = orientation;
0269:                } else if (orientation != lastOrientation) {
0270:                    ++flips;
0271:                }
0272:                lastOrientation = orientation;
0273:
0274:                // Bias Y by 1 ULP so endpoints never lie on a scanline
0275:                addEdge(x0, y0 | 0x1, x1, y1 | 0x1);
0276:
0277:                this .x0 = x1;
0278:                this .y0 = y1;
0279:            }
0280:
0281:            public void close() {
0282:                // System.out.println("Renderer: close");
0283:
0284:                int orientation = lastOrientation;
0285:                if (y0 != sy0) {
0286:                    orientation = (y0 < sy0) ? 1 : -1;
0287:                }
0288:                if (orientation != firstOrientation) {
0289:                    ++flips;
0290:                }
0291:                lineTo(sx0, sy0);
0292:            }
0293:
0294:            public void end() {
0295:                // System.out.println("Renderer: end");
0296:                // do nothing
0297:            }
0298:
0299:            // Scan convert a single edge
0300:            private void computeCrossingsForEdge(int index, int boundsMinY,
0301:                    int boundsMaxY) {
0302:                int iy0 = edges[index + 1];
0303:                int iy1 = edges[index + 3];
0304:
0305:                // Clip to valid Y range
0306:                int clipy0 = (iy0 > boundsMinY) ? iy0 : boundsMinY;
0307:                int clipy1 = (iy1 < boundsMaxY) ? iy1 : boundsMaxY;
0308:
0309:                int minY = ((clipy0 + HYSTEP) & YMASK) + HYSTEP;
0310:                int maxY = ((clipy1 - HYSTEP) & YMASK) + HYSTEP;
0311:
0312:                // IMPL_NOTE - If line falls outside the valid X range, could
0313:                // draw a vertical line instead
0314:
0315:                // Exit if no scanlines are crossed
0316:                if (minY > maxY) {
0317:                    return;
0318:                }
0319:
0320:                // Scan convert line using a DDA approach
0321:
0322:                int ix0 = edges[index];
0323:                int ix1 = edges[index + 2];
0324:                int dx = ix1 - ix0;
0325:                int dy = iy1 - iy0;
0326:
0327:                // Compute first crossing point at y = minY
0328:                int orientation = edges[index + 4];
0329:                int y = minY;
0330:                long lx = (long) (y - iy0) * dx / dy + ix0;
0331:                addCrossing(y >> YSHIFT, (int) (lx >> XSHIFT), orientation);
0332:
0333:                // Advance y to next scanline, exit if past endpoint
0334:                y += YSTEP;
0335:                if (y > maxY) {
0336:                    return;
0337:                }
0338:
0339:                // Compute xstep only if additional scanlines are crossed
0340:                // For each scanline, add xstep to lx and YSTEP to y and
0341:                // emit the new crossing
0342:                long xstep = ((long) YSTEP * dx) / dy;
0343:                for (; y <= maxY; y += YSTEP) {
0344:                    lx += xstep;
0345:                    addCrossing(y >> YSHIFT, (int) (lx >> XSHIFT), orientation);
0346:                }
0347:            }
0348:
0349:            private void computeBounds() {
0350:                rasterMinX = crossingMinX & ~SUBPIXEL_MASK_X;
0351:                rasterMaxX = crossingMaxX | SUBPIXEL_MASK_X;
0352:                rasterMinY = crossingMinY & ~SUBPIXEL_MASK_Y;
0353:                rasterMaxY = crossingMaxY | SUBPIXEL_MASK_Y;
0354:
0355:                // If nothing was drawn, we have:
0356:                // minX = Integer.MAX_VALUE and maxX = Integer.MIN_VALUE
0357:                // so nothing to render
0358:                if (rasterMinX > rasterMaxX || rasterMinY > rasterMaxY) {
0359:                    rasterMinX = 0;
0360:                    rasterMaxX = -1;
0361:                    rasterMinY = 0;
0362:                    rasterMaxY = -1;
0363:                    return;
0364:                }
0365:
0366:                if (rasterMinX < boundsMinX >> XSHIFT) {
0367:                    rasterMinX = boundsMinX >> XSHIFT;
0368:                }
0369:                if (rasterMinY < boundsMinY >> YSHIFT) {
0370:                    rasterMinY = boundsMinY >> YSHIFT;
0371:                }
0372:                if (rasterMaxX > boundsMaxX >> XSHIFT) {
0373:                    rasterMaxX = boundsMaxX >> XSHIFT;
0374:                }
0375:                if (rasterMaxY > boundsMaxY >> YSHIFT) {
0376:                    rasterMaxY = boundsMaxY >> YSHIFT;
0377:                }
0378:            }
0379:
0380:            private int clamp(int x, int min, int max) {
0381:                if (x < min) {
0382:                    return min;
0383:                } else if (x > max) {
0384:                    return max;
0385:                }
0386:                return x;
0387:            }
0388:
0389:            private void _endRendering() {
0390:                if (flips == 0) {
0391:                    bboxX0 = bboxY0 = 0;
0392:                    bboxX1 = bboxY1 = -1;
0393:                    return;
0394:                }
0395:
0396:                // Special case for filling a single rect with a flat, opaque color
0397:                if (paintMode == PAINT_FLAT_COLOR && calpha == 255
0398:                        && edgeIdx == 10 && edges[0] == edges[2]
0399:                        && edges[1] == edges[6] && edges[3] == edges[8]
0400:                        && edges[5] == edges[7]
0401:                        && Math.abs(edges[0] - edges[5]) > MIN_QUAD_OPT_WIDTH) {
0402:
0403:                    int x0 = edges[0] >> XSHIFT;
0404:                    int y0 = edges[1] >> YSHIFT;
0405:                    int x1 = edges[5] >> XSHIFT;
0406:                    int y1 = edges[3] >> YSHIFT;
0407:
0408:                    if (x0 > x1) {
0409:                        int tmp = x0;
0410:                        x0 = x1;
0411:                        x1 = tmp;
0412:                    }
0413:                    if (y0 > y1) {
0414:                        int tmp = y0;
0415:                        y0 = y1;
0416:                        y1 = tmp;
0417:                    }
0418:
0419:                    int bMinX = this .boundsMinX >> XSHIFT;
0420:                    int bMinY = this .boundsMinY >> YSHIFT;
0421:                    int bMaxX = this .boundsMaxX >> XSHIFT;
0422:                    int bMaxY = this .boundsMaxY >> YSHIFT;
0423:
0424:                    // Clip to image bounds in supersampled coordinates
0425:                    x0 = clamp(x0, bMinX, bMaxX);
0426:                    x1 = clamp(x1, bMinX, bMaxX);
0427:                    y0 = clamp(y0, bMinY, bMaxY);
0428:                    y1 = clamp(y1, bMinY, bMaxY);
0429:
0430:                    Blit.fillRectSrcOver(this , imageData, imageType,
0431:                            imageOffset, imageScanlineStride, imagePixelStride,
0432:                            width, height, x0, y0, x1, y1, cred, cgreen, cblue);
0433:
0434:                    bboxX0 = x0 >> SUBPIXEL_LG_POSITIONS_X;
0435:                    bboxY0 = y0 >> SUBPIXEL_LG_POSITIONS_Y;
0436:                    bboxX1 = (x1 + SUBPIXEL_POSITIONS_X - 1) >> SUBPIXEL_LG_POSITIONS_X;
0437:                    bboxY1 = (y1 + SUBPIXEL_POSITIONS_Y - 1) >> SUBPIXEL_LG_POSITIONS_Y;
0438:
0439:                    return;
0440:                }
0441:
0442:                int minY = (edgeMinY > boundsMinY) ? edgeMinY : boundsMinY;
0443:                int maxY = (edgeMaxY < boundsMaxY) ? edgeMaxY : boundsMaxY;
0444:
0445:                // Check for empty intersection of primitive with the drawing area
0446:                if (minY > maxY) {
0447:                    bboxX0 = bboxY0 = 0;
0448:                    bboxX1 = bboxY1 = -1;
0449:                    return;
0450:                }
0451:
0452:                // Compute Y extent in subpixel coordinates
0453:                int iminY = (minY >> YSHIFT) & ~SUBPIXEL_MASK_Y;
0454:                int imaxY = (maxY >> YSHIFT) | SUBPIXEL_MASK_Y;
0455:                int yextent = (imaxY - iminY) + 1;
0456:
0457:                // Maximum number of crossings 
0458:                int size = flips * yextent;
0459:
0460:                int bmax = (boundsMaxY >> YSHIFT) - 1;
0461:                if (imaxY > bmax) {
0462:                    imaxY = bmax;
0463:                }
0464:
0465:                // Initialize X bounds, will be refined for each strip
0466:                bboxX0 = Integer.MAX_VALUE;
0467:                bboxX1 = Integer.MIN_VALUE;
0468:
0469:                // Set Y bounds
0470:                bboxY0 = iminY >> SUBPIXEL_LG_POSITIONS_Y;
0471:                bboxY1 = (imaxY + SUBPIXEL_POSITIONS_Y - 1) >> SUBPIXEL_LG_POSITIONS_Y;
0472:
0473:                // Compute number of rows that can be processing using
0474:                // a crossings table no larger than DEFAULT_CROSSINGS_SIZE.
0475:                // However, we must process at least one row, so we grow the table
0476:                // temporarily if needed.  This would require an object with a
0477:                // huge number of flips.
0478:                int rows = DEFAULT_CROSSINGS_SIZE
0479:                        / (flips * SUBPIXEL_POSITIONS_Y);
0480:                rows = Math.min(rows, yextent);
0481:                rows = Math.max(rows, 1);
0482:                for (int i = iminY; i <= imaxY; i += rows
0483:                        * SUBPIXEL_POSITIONS_Y) {
0484:                    // Compute index of last scanline to be processed in this pass
0485:                    int last = Math.min(i + rows * SUBPIXEL_POSITIONS_Y - 1,
0486:                            imaxY);
0487:                    setCrossingsExtents(i, last, flips);
0488:
0489:                    int bminY = i << YSHIFT;
0490:                    int bmaxY = (last << YSHIFT) | ~YMASK;
0491:
0492:                    // Process edges from the edge list
0493:                    int maxIdx = edgeIdx;
0494:                    for (int index = 0; index < maxIdx; index += 5) {
0495:                        // Test y1 < min:
0496:                        //
0497:                        // If edge lies entirely above current strip,
0498:                        // discard it
0499:                        if (edges[index + 3] < bminY) {
0500:                            // Overwrite the edge with the last edge
0501:                            edgeIdx -= 5;
0502:                            int fidx = edgeIdx;
0503:                            int tidx = index;
0504:                            edges[tidx++] = edges[fidx++];
0505:                            edges[tidx++] = edges[fidx++];
0506:                            edges[tidx++] = edges[fidx++];
0507:                            edges[tidx++] = edges[fidx++];
0508:                            edges[tidx] = edges[fidx];
0509:
0510:                            maxIdx -= 5;
0511:                            index -= 5;
0512:                            continue;
0513:                        }
0514:
0515:                        // Test y0 > max:
0516:                        //
0517:                        // If edge lies entirely below current strip,
0518:                        // skip it for now
0519:                        if (edges[index + 1] > bmaxY) {
0520:                            continue;
0521:                        }
0522:
0523:                        computeCrossingsForEdge(index, bminY, bmaxY);
0524:                    }
0525:
0526:                    computeBounds();
0527:                    if (rasterMaxX < rasterMinX) {
0528:                        continue;
0529:                    }
0530:
0531:                    bboxX0 = Math.min(bboxX0,
0532:                            rasterMinX >> SUBPIXEL_LG_POSITIONS_X);
0533:                    bboxX1 = Math
0534:                            .max(
0535:                                    bboxX1,
0536:                                    (rasterMaxX + SUBPIXEL_POSITIONS_X - 1) >> SUBPIXEL_LG_POSITIONS_X);
0537:                    renderStrip();
0538:                }
0539:
0540:                // Free up any unusually large scratchpad memory used by the
0541:                // preceding primitive
0542:                crossingListFinished();
0543:            }
0544:
0545:            public void endRendering() {
0546:                _endRendering();
0547:
0548:                // If a cache is present, store the bounding box in it as well
0549:                if (cache != null) {
0550:                    cache.bboxX0 = bboxX0;
0551:                    cache.bboxY0 = bboxY0;
0552:                    cache.bboxX1 = bboxX1;
0553:                    cache.bboxY1 = bboxY1;
0554:
0555:                    cache.isValid = true;
0556:                }
0557:            }
0558:
0559:            public void getBoundingBox(int[] bbox) {
0560:                bbox[0] = bboxX0;
0561:                bbox[1] = bboxY0;
0562:                bbox[2] = bboxX1 - bboxX0;
0563:                bbox[3] = bboxY1 - bboxY0;
0564:            }
0565:
0566:            private void renderStrip() {
0567:                // Grow rowAA according to the raster width
0568:                int width = (rasterMaxX - rasterMinX + 1) >> SUBPIXEL_LG_POSITIONS_X;
0569:                alphaWidth = width;
0570:
0571:                // Allocate one extra entry in rowAA to avoid a conditional in
0572:                // the rendering loop
0573:                int bufLen = NUM_ALPHA_ROWS * width + 1;
0574:                if (this .rowAA == null || this .rowAA.length < bufLen) {
0575:                    this .rowAA = new byte[bufLen];
0576:
0577:                    this .paintBuffer = new int[bufLen];
0578:                    this .paintBufferOffset = 0;
0579:                    this .paintBufferStride = width;
0580:                }
0581:
0582:                // Mask to determine the relevant bit of the crossing sum
0583:                // 0x1 if EVEN_ODD, all bits if NON_ZERO
0584:                int mask = (windingRule == WIND_EVEN_ODD) ? 0x1 : ~0x0;
0585:
0586:                int y = 0;
0587:                int prevY = rasterMinY - 1;
0588:
0589:                this .currY = rasterMinY >> SUBPIXEL_LG_POSITIONS_Y;
0590:                this .currX = rasterMinX >> SUBPIXEL_LG_POSITIONS_X;
0591:                this .currImageOffset = imageOffset + currY
0592:                        * imageScanlineStride + currX * imagePixelStride;
0593:                this .rowAAOffset = 0;
0594:                this .rowNum = 0;
0595:
0596:                int minX = Integer.MAX_VALUE;
0597:                int maxX = Integer.MIN_VALUE;
0598:
0599:                iterateCrossings();
0600:                while (hasMoreCrossingRows()) {
0601:                    y = crossingY;
0602:
0603:                    // Emit any skipped rows
0604:                    for (int j = prevY + 1; j < y; j++) {
0605:                        if (((j & SUBPIXEL_MASK_Y) == SUBPIXEL_MASK_Y)
0606:                                || (j == rasterMaxY)) {
0607:                            emitRow(0, -1, false);
0608:                        }
0609:                    }
0610:                    prevY = y;
0611:
0612:                    if (crossingRowIndex < crossingRowCount) {
0613:                        int lx = crossings[crossingRowOffset + crossingRowIndex];
0614:                        lx >>= 1;
0615:                        int hx = crossings[crossingRowOffset + crossingRowCount
0616:                                - 1];
0617:                        hx >>= 1;
0618:                        int x0 = lx > rasterMinX ? lx : rasterMinX;
0619:                        int x1 = hx < rasterMaxX ? hx : rasterMaxX;
0620:                        x0 -= rasterMinX;
0621:                        x1 -= rasterMinX;
0622:
0623:                        minX = Math.min(minX, x0 >> SUBPIXEL_LG_POSITIONS_X);
0624:                        maxX = Math.max(maxX, x1 >> SUBPIXEL_LG_POSITIONS_X);
0625:                    }
0626:
0627:                    int sum = 0;
0628:                    int prev = rasterMinX;
0629:                    while (crossingRowIndex < crossingRowCount) {
0630:                        int crxo = crossings[crossingRowOffset
0631:                                + crossingRowIndex];
0632:                        crossingRowIndex++;
0633:
0634:                        int crx = crxo >> 1;
0635:                        int crorientation = ((crxo & 0x1) == 0x1) ? 1 : -1;
0636:
0637:                        if ((sum & mask) != 0) {
0638:                            // Clip to active X range, if x1 < x0 loop will
0639:                            // have no effect
0640:                            int x0 = prev > rasterMinX ? prev : rasterMinX;
0641:                            int x1 = crx < rasterMaxX ? crx : rasterMaxX;
0642:
0643:                            // Empty spans
0644:                            if (x1 > x0) {
0645:                                x0 -= rasterMinX;
0646:                                x1 -= rasterMinX;
0647:
0648:                                // Accumulate alpha, equivalent to:
0649:                                //   for (int x = x0; x < x1; x++) {
0650:                                //       ++rowAA[x >> SUBPIXEL_LG_POSITIONS_X];
0651:                                //   }
0652:                                //
0653:                                // In the middle of the span, we can update a full
0654:                                // pixel at a time (i.e., SUBPIXEL_POSITIONS_X
0655:                                // subpixels)
0656:
0657:                                int x = x0 >> SUBPIXEL_LG_POSITIONS_X;
0658:                                int xmaxm1 = (x1 - 1) >> SUBPIXEL_LG_POSITIONS_X;
0659:                                if (x == xmaxm1) {
0660:                                    // Start and end in same pixel
0661:                                    rowAA[x + rowAAOffset] += x1 - x0;
0662:                                } else {
0663:                                    // Start and end in different pixels
0664:                                    rowAA[x++ + rowAAOffset] += SUBPIXEL_POSITIONS_X
0665:                                            - (x0 & SUBPIXEL_MASK_X);
0666:                                    int xmax = x1 >> SUBPIXEL_LG_POSITIONS_X;
0667:                                    while (x < xmax) {
0668:                                        rowAA[x++ + rowAAOffset] += SUBPIXEL_POSITIONS_X;
0669:                                    }
0670:                                    // Note - at this point it is possible that
0671:                                    // x == width, which implies that
0672:                                    // x1 & SUBPIXEL_MASK_X == 0.  We allocate
0673:                                    // one extra entry in rowAA so this
0674:                                    // assignment will be harmless.  The alternative
0675:                                    // is an extra conditional here, or some other
0676:                                    // scheme to deal with the last pixel better.
0677:                                    rowAA[x + rowAAOffset] += x1
0678:                                            & SUBPIXEL_MASK_X;
0679:                                }
0680:                            }
0681:                        }
0682:                        sum += crorientation;
0683:                        prev = crx;
0684:                    }
0685:
0686:                    // Every SUBPIXEL_POSITIONS rows, output an antialiased row
0687:                    if (((y & SUBPIXEL_MASK_Y) == SUBPIXEL_MASK_Y)
0688:                            || (y == rasterMaxY)) {
0689:                        emitRow(minX, maxX, false);
0690:                        minX = Integer.MAX_VALUE;
0691:                        maxX = Integer.MIN_VALUE;
0692:                    }
0693:                }
0694:
0695:                // Emit final row
0696:                for (int j = prevY + 1; j <= rasterMaxY; j++) {
0697:                    if (((j & SUBPIXEL_MASK_Y) == SUBPIXEL_MASK_Y)
0698:                            || (j == rasterMaxY)) {
0699:                        emitRow(minX, maxX, false);
0700:                        minX = Integer.MAX_VALUE;
0701:                        maxX = Integer.MIN_VALUE;
0702:                    }
0703:                }
0704:
0705:                // Emit last bunch of rows
0706:                if (rowAAOffset != 0) {
0707:                    emitRow(minX, maxX, true);
0708:                }
0709:            }
0710:
0711:            private void clearAlpha(byte[] alpha, int alphaOffset, int width,
0712:                    int height, int[] minTouched, int[] maxTouched,
0713:                    int[] rowOffsets) {
0714:                for (int j = 0; j < height; j++) {
0715:                    int minX = minTouched[j];
0716:                    int maxX = maxTouched[j];
0717:                    if (maxX >= minX) {
0718:                        int w = maxX - minX + 1;
0719:                        if (w + minX > width) {
0720:                            w = width - minX;
0721:                        }
0722:
0723:                        int aidx = alphaOffset + rowOffsets[j] + minX;
0724:                        for (int i = 0; i < w; i++, aidx++) {
0725:                            alpha[aidx] = (byte) 0;
0726:                        }
0727:                    }
0728:                }
0729:            }
0730:
0731:            private void emitRow(int minX, int maxX, boolean forceOutput) {
0732:                // Copy rowAA data into the cache if one is present
0733:                if (cache != null) {
0734:                    if (cache.alphaWidth == 0) {
0735:                        cache.alphaWidth = alphaWidth;
0736:                    } else {
0737:                        if (alphaWidth != cache.alphaWidth) {
0738:                            throw new IllegalStateException(
0739:                                    "alphaWidth changed!");
0740:                        }
0741:                    }
0742:
0743:                    int len = -1;
0744:                    int dstIdx = cache.alphaRLELength;
0745:                    if (maxX >= minX) {
0746:                        int srcIdx = rowAAOffset + minX;
0747:                        len = maxX - minX + 1;
0748:
0749:                        // Perform run-length encoding
0750:                        // and store results in the cache
0751:                        byte startVal = rowAA[srcIdx];
0752:                        int runLen = 1;
0753:                        for (int x = 1; x < len; x++) {
0754:                            byte nextVal = rowAA[srcIdx + x];
0755:                            if (nextVal == startVal && runLen < 255) {
0756:                                ++runLen;
0757:                            } else {
0758:                                cache.addRLERun(startVal, runLen);
0759:
0760:                                runLen = 1;
0761:                                startVal = nextVal;
0762:                            }
0763:                        }
0764:                        if (runLen > 0) {
0765:                            cache.addRLERun(startVal, runLen);
0766:                        }
0767:                        cache.addRLERun((byte) 0, 0);
0768:                    }
0769:
0770:                    cache.addRow(minX, dstIdx);
0771:                }
0772:
0773:                // Record values for later blitting
0774:
0775:                this .minTouched[rowNum] = minX;
0776:                this .maxTouched[rowNum] = maxX;
0777:                this .rowOffsets[rowNum] = rowAAOffset;
0778:
0779:                rowAAOffset += alphaWidth;
0780:                rowNum++;
0781:                if (forceOutput || rowNum == NUM_ALPHA_ROWS) {
0782:                    emitRows(rowNum);
0783:                    clearAlpha(rowAA, 0, alphaWidth, rowNum, minTouched,
0784:                            maxTouched, rowOffsets);
0785:
0786:                    currY += rowNum;
0787:                    currImageOffset += rowNum * imageScanlineStride;
0788:                    rowAAOffset = 0;
0789:                    rowNum = 0;
0790:                }
0791:            }
0792:
0793:            private void emitRows(int alphaHeight) {
0794:                if (paintMode == PAINT_FLAT_COLOR) {
0795:                    Blit.blit(imageData, imageType, currImageOffset,
0796:                            imageScanlineStride, imagePixelStride, rowAA, 0,
0797:                            alphaWidth, alphaHeight, minTouched, maxTouched,
0798:                            rowOffsets, compositeRule, cred, cgreen, cblue,
0799:                            calpha, alphaMap);
0800:                } else {
0801:                    paint.paint(currX, currY, alphaWidth, alphaHeight,
0802:                            minTouched, maxTouched, paintBuffer,
0803:                            paintBufferOffset, paintBufferStride);
0804:
0805:                    Blit.blit(imageData, imageType, currImageOffset,
0806:                            imageScanlineStride, imagePixelStride, rowAA, 0,
0807:                            alphaWidth, alphaHeight, minTouched, maxTouched,
0808:                            rowOffsets, compositeRule, paintBuffer,
0809:                            paintBufferOffset, paintBufferStride, alphaMap);
0810:                }
0811:            }
0812:
0813:            public void setCache(PiscesCache cache) {
0814:                this .cache = cache;
0815:            }
0816:
0817:            public void renderFromCache(PiscesCache cache) {
0818:                this .alphaWidth = cache.alphaWidth;
0819:                int alphaHeight = cache.alphaHeight;
0820:
0821:                int bufLen = NUM_ALPHA_ROWS * alphaWidth;
0822:                if (this .rowAA == null || this .rowAA.length < bufLen) {
0823:                    this .rowAA = new byte[bufLen];
0824:                }
0825:
0826:                // Decode run-length encoded alpha mask data
0827:                // The data for row j begins at cache.rowOffsetsRLE[j]
0828:                // and is encoded as a set of 2-byte pairs (val, runLen)
0829:                // terminated by a (0, 0) pair.
0830:
0831:                int currX = cache.bboxX0;
0832:                int currY = cache.bboxY0;
0833:                currImageOffset = imageOffset + currY * imageScanlineStride
0834:                        + currX * imagePixelStride;
0835:
0836:                int idx = 0;
0837:                for (int j = 0; j < alphaHeight; j++) {
0838:                    int jj = j & (NUM_ALPHA_ROWS - 1);
0839:
0840:                    rowOffsets[jj] = idx - cache.minTouched[j];
0841:
0842:                    int pos = cache.rowOffsetsRLE[j];
0843:                    int len = 0;
0844:
0845:                    while (true) {
0846:                        byte val = cache.rowAARLE[pos];
0847:                        int runLen = cache.rowAARLE[pos + 1] & 0xff;
0848:                        if (runLen == 0) {
0849:                            break;
0850:                        }
0851:                        for (int i = 0; i < runLen; i++) {
0852:                            rowAA[idx++] = val;
0853:                        }
0854:                        len += runLen;
0855:                        pos += 2;
0856:                    }
0857:
0858:                    minTouched[jj] = cache.minTouched[j];
0859:                    if (len == 0) {
0860:                        // Empty rows have minX = Integer.MAX_VALUE,
0861:                        // maxX = Integer.MIN_VALUE
0862:                        maxTouched[jj] = Integer.MIN_VALUE;
0863:                    } else {
0864:                        maxTouched[jj] = cache.minTouched[j] + len - 1;
0865:                    }
0866:
0867:                    // Perform blitting after NUM_ALPHA_ROWS rows have
0868:                    // been decoded, or when we reach the last row
0869:                    if ((jj == NUM_ALPHA_ROWS - 1) || (j == alphaHeight - 1)) {
0870:                        emitRows(jj + 1);
0871:                        currImageOffset += (jj + 1) * imageScanlineStride;
0872:                        idx = 0;
0873:                    }
0874:
0875:                }
0876:
0877:                // Update the bounding box for possible retrieval via getBoundingBox
0878:                this .bboxX0 = cache.bboxX0;
0879:                this .bboxY0 = cache.bboxY0;
0880:                this .bboxX1 = cache.bboxX1;
0881:                this .bboxY1 = cache.bboxY1;
0882:            }
0883:
0884:            // Edge list data
0885:
0886:            private int[] edges = new int[5 * INITIAL_EDGES];
0887:            private int edgeIdx = 0;
0888:            private int edgeMinY = Integer.MAX_VALUE;
0889:            private int edgeMaxY = Integer.MIN_VALUE;
0890:
0891:            private void addEdge(int x0, int y0, int x1, int y1) {
0892:                int newLen = edgeIdx + 5;
0893:                if (edges.length < newLen) {
0894:                    int[] tmp = new int[Math
0895:                            .max(11 * edges.length / 10, newLen)];
0896:                    System.arraycopy(edges, 0, tmp, 0, edgeIdx);
0897:                    this .edges = tmp;
0898:                }
0899:
0900:                int orientation = 1;
0901:                if (y0 > y1) {
0902:                    int tmp = y0;
0903:                    y0 = y1;
0904:                    y1 = tmp;
0905:
0906:                    orientation = -1;
0907:                }
0908:
0909:                // Skip edges that don't cross a subsampled scanline
0910:                int eminY = ((y0 + HYSTEP) & YMASK);
0911:                int emaxY = ((y1 - HYSTEP) & YMASK);
0912:                if (eminY > emaxY) {
0913:                    return;
0914:                }
0915:
0916:                if (orientation == -1) {
0917:                    int tmp = x0;
0918:                    x0 = x1;
0919:                    x1 = tmp;
0920:                }
0921:
0922:                edges[edgeIdx++] = x0;
0923:                edges[edgeIdx++] = y0;
0924:                edges[edgeIdx++] = x1;
0925:                edges[edgeIdx++] = y1;
0926:                edges[edgeIdx++] = orientation;
0927:
0928:                // Update Y bounds of primitive
0929:                if (y0 < edgeMinY) {
0930:                    edgeMinY = y0;
0931:                }
0932:                if (y1 > edgeMaxY) {
0933:                    edgeMaxY = y1;
0934:                }
0935:            }
0936:
0937:            private void resetEdges() {
0938:                this .edgeIdx = 0;
0939:                this .edgeMinY = Integer.MAX_VALUE;
0940:                this .edgeMaxY = Integer.MIN_VALUE;
0941:            }
0942:
0943:            // Crossing list data
0944:
0945:            private int[] crossingIndices;
0946:            private int[] crossings;
0947:            private int crossingMinY;
0948:            private int crossingMaxY;
0949:            private int crossingMinX = Integer.MAX_VALUE;
0950:            private int crossingMaxX = Integer.MIN_VALUE;
0951:            private int crossingMaxXEntries;
0952:            private int numCrossings = 0;
0953:            private boolean crossingsSorted = false;
0954:
0955:            private int crossingY;
0956:            private int crossingRowCount;
0957:            private int crossingRowOffset;
0958:            private int crossingRowIndex;
0959:
0960:            private void setCrossingsExtents(int minY, int maxY, int maxXEntries) {
0961:                int yextent = maxY - minY + 1;
0962:
0963:                // Grow indices array as needed
0964:                if (crossingIndices == null || crossingIndices.length < yextent) {
0965:                    this .crossingIndices = new int[Math.max(yextent,
0966:                            DEFAULT_INDICES_SIZE)];
0967:                }
0968:                // Grow crossings array as needed
0969:                if (crossings == null
0970:                        || crossings.length < yextent * maxXEntries) {
0971:                    this .crossings = new int[Math.max(yextent * maxXEntries,
0972:                            DEFAULT_CROSSINGS_SIZE)];
0973:                }
0974:                this .crossingMinY = minY;
0975:                this .crossingMaxY = maxY;
0976:                this .crossingMaxXEntries = maxXEntries;
0977:                resetCrossings();
0978:            }
0979:
0980:            private void resetCrossings() {
0981:                int yextent = crossingMaxY - crossingMinY + 1;
0982:                int start = 0;
0983:                for (int i = 0; i < yextent; i++) {
0984:                    crossingIndices[i] = start;
0985:                    start += crossingMaxXEntries;
0986:                }
0987:                crossingMinX = Integer.MAX_VALUE;
0988:                crossingMaxX = Integer.MIN_VALUE;
0989:                numCrossings = 0;
0990:                crossingsSorted = false;
0991:            }
0992:
0993:            // Free sorting arrays if larger than maximum size
0994:            private void crossingListFinished() {
0995:                if (crossings.length > DEFAULT_CROSSINGS_SIZE) {
0996:                    crossings = new int[DEFAULT_CROSSINGS_SIZE];
0997:                }
0998:                if (crossingIndices.length > DEFAULT_INDICES_SIZE) {
0999:                    crossingIndices = new int[DEFAULT_INDICES_SIZE];
1000:                }
1001:            }
1002:
1003:            private void sortCrossings(int[] x, int off, int len) {
1004:                for (int i = off + 1; i < off + len; i++) {
1005:                    int j = i;
1006:                    int xj = x[j];
1007:                    int xjm1;
1008:
1009:                    while (j > off && (xjm1 = x[j - 1]) > xj) {
1010:                        x[j] = xjm1;
1011:                        x[j - 1] = xj;
1012:                        j--;
1013:                    }
1014:                }
1015:            }
1016:
1017:            private void sortCrossings() {
1018:                int start = 0;
1019:                for (int i = 0; i <= crossingMaxY - crossingMinY; i++) {
1020:                    sortCrossings(crossings, start, crossingIndices[i] - start);
1021:                    start += crossingMaxXEntries;
1022:                }
1023:            }
1024:
1025:            private void addCrossing(int y, int x, int orientation) {
1026:                if (x < crossingMinX) {
1027:                    crossingMinX = x;
1028:                }
1029:                if (x > crossingMaxX) {
1030:                    crossingMaxX = x;
1031:                }
1032:
1033:                int index = crossingIndices[y - crossingMinY]++;
1034:                x <<= 1;
1035:                crossings[index] = (orientation == 1) ? (x | 0x1) : x;
1036:
1037:                ++numCrossings;
1038:            }
1039:
1040:            private void iterateCrossings() {
1041:                if (!crossingsSorted) {
1042:                    sortCrossings();
1043:                    crossingsSorted = true;
1044:                }
1045:                crossingY = crossingMinY - 1;
1046:                crossingRowOffset = -crossingMaxXEntries;
1047:            }
1048:
1049:            private boolean hasMoreCrossingRows() {
1050:                if (++crossingY <= crossingMaxY) {
1051:                    crossingRowOffset += crossingMaxXEntries;
1052:                    int y = crossingY - crossingMinY;
1053:                    crossingRowCount = crossingIndices[y] - y
1054:                            * crossingMaxXEntries;
1055:                    crossingRowIndex = 0;
1056:                    return true;
1057:                } else {
1058:                    return false;
1059:                }
1060:            }
1061:
1062:            public void clearRect(int x, int y, int w, int h) {
1063:                Blit.clearRect(imageData, imageType, imageOffset,
1064:                        imageScanlineStride, imagePixelStride, x, y, w, h,
1065:                        calpha, cred, cgreen, cblue);
1066:            }
1067:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.