Source Code Cross Referenced for Stroker.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) 


001:        /*
002:         * 
003:         * Copyright  1990-2007 Sun Microsystems, Inc. All Rights Reserved. 
004:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER 
005:         *  
006:         * This program is free software; you can redistribute it and/or 
007:         * modify it under the terms of the GNU General Public License version 
008:         * 2 only, as published by the Free Software Foundation. 
009:         *  
010:         * This program is distributed in the hope that it will be useful, but 
011:         * WITHOUT ANY WARRANTY; without even the implied warranty of 
012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
013:         * General Public License version 2 for more details (a copy is 
014:         * included at /legal/license.txt). 
015:         *  
016:         * You should have received a copy of the GNU General Public License 
017:         * version 2 along with this work; if not, write to the Free Software 
018:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 
019:         * 02110-1301 USA 
020:         *  
021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 
022:         * Clara, CA 95054 or visit www.sun.com if you need additional 
023:         * information or have any questions.
024:         */
025:
026:        package com.sun.pisces;
027:
028:        public class Stroker extends LineSink {
029:
030:            private static final int MOVE_TO = 0;
031:            private static final int LINE_TO = 1;
032:            private static final int CLOSE = 2;
033:
034:            /**
035:             * Constant value for join style.
036:             */
037:            public static final int JOIN_MITER = 0;
038:
039:            /**
040:             * Constant value for join style.
041:             */
042:            public static final int JOIN_ROUND = 1;
043:
044:            /**
045:             * Constant value for join style.
046:             */
047:            public static final int JOIN_BEVEL = 2;
048:
049:            /**
050:             * Constant value for end cap style.
051:             */
052:            public static final int CAP_BUTT = 0;
053:
054:            /**
055:             * Constant value for end cap style.
056:             */
057:            public static final int CAP_ROUND = 1;
058:
059:            /**
060:             * Constant value for end cap style.
061:             */
062:            public static final int CAP_SQUARE = 2;
063:
064:            LineSink output;
065:
066:            int lineWidth;
067:            int capStyle;
068:            int joinStyle;
069:            int miterLimit;
070:
071:            Transform4 transform;
072:            int m00, m01;
073:            int m10, m11;
074:
075:            int lineWidth2;
076:            long scaledLineWidth2;
077:
078:            // For any pen offset (pen_dx, pen_dy) that does not depend on
079:            // the line orientation, the pen should be transformed so that:
080:            //
081:            // pen_dx' = m00*pen_dx + m01*pen_dy
082:            // pen_dy' = m10*pen_dx + m11*pen_dy
083:            //
084:            // For a round pen, this means:
085:            //
086:            // pen_dx(r, theta) = r*cos(theta)
087:            // pen_dy(r, theta) = r*sin(theta)
088:            //
089:            // pen_dx'(r, theta) = r*(m00*cos(theta) + m01*sin(theta))
090:            // pen_dy'(r, theta) = r*(m10*cos(theta) + m11*sin(theta))
091:            int numPenSegments;
092:            int[] pen_dx;
093:            int[] pen_dy;
094:            boolean[] penIncluded;
095:            int[] join;
096:
097:            int[] offset = new int[2];
098:            int[] reverse = new int[100];
099:            int[] miter = new int[2];
100:            long miterLimitSq;
101:
102:            int prev;
103:            int rindex;
104:            boolean started;
105:            boolean lineToOrigin;
106:            boolean joinToOrigin;
107:
108:            int sx0, sy0, sx1, sy1, x0, y0, x1, y1;
109:            int mx0, my0, mx1, my1, omx, omy;
110:            int lx0, ly0, lx1, ly1, lx0p, ly0p, px0, py0;
111:
112:            double m00_2_m01_2;
113:            double m10_2_m11_2;
114:            double m00_m10_m01_m11;
115:
116:            /**
117:             * Empty constructor.  <code>setOutput</code> and
118:             * <code>setParameters</code> must be called prior to calling any
119:             * other methods.
120:             */
121:            public Stroker() {
122:            }
123:
124:            /**
125:             * Constructs a <code>Stroker</code>.
126:             *
127:             * @param output an output <code>LineSink</code>.
128:             * @param lineWidth the desired line width in pixels, in S15.16
129:             * format.
130:             * @param capStyle the desired end cap style, one of
131:             * <code>CAP_BUTT</code>, <code>CAP_ROUND</code> or
132:             * <code>CAP_SQUARE</code>.
133:             * @param joinStyle the desired line join style, one of
134:             * <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
135:             * <code>JOIN_BEVEL</code>.
136:             * @param miterLimit the desired miter limit, in S15.16 format.
137:             * @param transform a <code>Transform4</code> object indicating
138:             * the transform that has been previously applied to all incoming
139:             * coordinates.  This is required in order to produce consistently
140:             * shaped end caps and joins.
141:             */
142:            public Stroker(LineSink output, int lineWidth, int capStyle,
143:                    int joinStyle, int miterLimit, Transform4 transform) {
144:                setOutput(output);
145:                setParameters(lineWidth, capStyle, joinStyle, miterLimit,
146:                        transform);
147:            }
148:
149:            /**
150:             * Sets the output <code>LineSink</code> of this
151:             * <code>Stroker</code>.
152:             *
153:             * @param output an output <code>LineSink</code>.
154:             */
155:            public void setOutput(LineSink output) {
156:                this .output = output;
157:            }
158:
159:            /**
160:             * Sets the parameters of this <code>Stroker</code>.
161:             * @param lineWidth the desired line width in pixels, in S15.16
162:             * format.
163:             * @param capStyle the desired end cap style, one of
164:             * <code>CAP_BUTT</code>, <code>CAP_ROUND</code> or
165:             * <code>CAP_SQUARE</code>.
166:             * @param joinStyle the desired line join style, one of
167:             * <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
168:             * <code>JOIN_BEVEL</code>.
169:             * @param miterLimit the desired miter limit, in S15.16 format.
170:             * @param transform a <code>Transform4</code> object indicating
171:             * the transform that has been previously applied to all incoming
172:             * coordinates.  This is required in order to produce consistently
173:             * shaped end caps and joins.
174:             */
175:            public void setParameters(int lineWidth, int capStyle,
176:                    int joinStyle, int miterLimit, Transform4 transform) {
177:                this .lineWidth = lineWidth;
178:                this .lineWidth2 = lineWidth >> 1;
179:                this .scaledLineWidth2 = (long) transform.m00 * lineWidth2;
180:                this .capStyle = capStyle;
181:                this .joinStyle = joinStyle;
182:                this .miterLimit = miterLimit;
183:
184:                this .transform = transform;
185:                this .m00 = transform.m00;
186:                this .m01 = transform.m01;
187:                this .m10 = transform.m10;
188:                this .m11 = transform.m11;
189:
190:                this .m00_2_m01_2 = (double) m00 * m00 + (double) m01 * m01;
191:                this .m10_2_m11_2 = (double) m10 * m10 + (double) m11 * m11;
192:                this .m00_m10_m01_m11 = (double) m00 * m10 + (double) m01 * m11;
193:
194:                double dm00 = m00 / 65536.0;
195:                double dm01 = m01 / 65536.0;
196:                double dm10 = m10 / 65536.0;
197:                double dm11 = m11 / 65536.0;
198:                double determinant = dm00 * dm11 - dm01 * dm10;
199:
200:                if (joinStyle == JOIN_MITER) {
201:                    double limit = (miterLimit / 65536.0)
202:                            * (lineWidth2 / 65536.0) * determinant;
203:                    double limitSq = limit * limit;
204:                    this .miterLimitSq = (long) (limitSq * 65536.0 * 65536.0);
205:                }
206:
207:                this .numPenSegments = (int) (3.14159f * lineWidth / 65536.0f);
208:                if (pen_dx == null || pen_dx.length < numPenSegments) {
209:                    this .pen_dx = new int[numPenSegments];
210:                    this .pen_dy = new int[numPenSegments];
211:                    this .penIncluded = new boolean[numPenSegments];
212:                    this .join = new int[2 * numPenSegments];
213:                }
214:
215:                for (int i = 0; i < numPenSegments; i++) {
216:                    double r = lineWidth / 2.0;
217:                    double theta = (double) i * 2.0 * Math.PI / numPenSegments;
218:
219:                    double cos = Math.cos(theta);
220:                    double sin = Math.sin(theta);
221:                    pen_dx[i] = (int) (r * (dm00 * cos + dm01 * sin));
222:                    pen_dy[i] = (int) (r * (dm10 * cos + dm11 * sin));
223:                }
224:
225:                prev = CLOSE;
226:                rindex = 0;
227:                started = false;
228:                lineToOrigin = false;
229:            }
230:
231:            private void computeOffset(int x0, int y0, int x1, int y1, int[] m) {
232:                long lx = (long) x1 - (long) x0;
233:                long ly = (long) y1 - (long) y0;
234:
235:                int dx, dy;
236:                if (m00 > 0 && m00 == m11 && m01 == 0 & m10 == 0) {
237:                    long ilen = PiscesMath.hypot(lx, ly);
238:                    if (ilen == 0) {
239:                        dx = dy = 0;
240:                    } else {
241:                        dx = (int) ((ly * scaledLineWidth2) / ilen >> 16);
242:                        dy = (int) (-(lx * scaledLineWidth2) / ilen >> 16);
243:                    }
244:                } else {
245:                    double dlx = x1 - x0;
246:                    double dly = y1 - y0;
247:                    double det = (double) m00 * m11 - (double) m01 * m10;
248:                    int sdet = (det > 0) ? 1 : -1;
249:                    double a = dly * m00 - dlx * m10;
250:                    double b = dly * m01 - dlx * m11;
251:                    double dh = PiscesMath.hypot(a, b);
252:                    double div = sdet * lineWidth2 / (65536.0 * dh);
253:                    double ddx = dly * m00_2_m01_2 - dlx * m00_m10_m01_m11;
254:                    double ddy = dly * m00_m10_m01_m11 - dlx * m10_2_m11_2;
255:                    dx = (int) (ddx * div);
256:                    dy = (int) (ddy * div);
257:                }
258:
259:                m[0] = dx;
260:                m[1] = dy;
261:            }
262:
263:            private void ensureCapacity(int newrindex) {
264:                if (reverse.length < newrindex) {
265:                    int[] tmp = new int[Math.max(newrindex,
266:                            6 * reverse.length / 5)];
267:                    System.arraycopy(reverse, 0, tmp, 0, rindex);
268:                    this .reverse = tmp;
269:                }
270:            }
271:
272:            private boolean isCCW(int x0, int y0, int x1, int y1, int x2, int y2) {
273:                int dx0 = x1 - x0;
274:                int dy0 = y1 - y0;
275:                int dx1 = x2 - x1;
276:                int dy1 = y2 - y1;
277:                return (long) dx0 * dy1 < (long) dy0 * dx1;
278:            }
279:
280:            private boolean side(int x, int y, int x0, int y0, int x1, int y1) {
281:                long lx = x;
282:                long ly = y;
283:                long lx0 = x0;
284:                long ly0 = y0;
285:                long lx1 = x1;
286:                long ly1 = y1;
287:
288:                return (ly0 - ly1) * lx + (lx1 - lx0) * ly
289:                        + (lx0 * ly1 - lx1 * ly0) > 0;
290:            }
291:
292:            private int computeRoundJoin(int cx, int cy, int xa, int ya,
293:                    int xb, int yb, int side, boolean flip, int[] join) {
294:                int px, py;
295:                int ncoords = 0;
296:
297:                boolean centerSide;
298:                if (side == 0) {
299:                    centerSide = side(cx, cy, xa, ya, xb, yb);
300:                } else {
301:                    centerSide = (side == 1) ? true : false;
302:                }
303:                for (int i = 0; i < numPenSegments; i++) {
304:                    px = cx + pen_dx[i];
305:                    py = cy + pen_dy[i];
306:
307:                    boolean penSide = side(px, py, xa, ya, xb, yb);
308:                    if (penSide != centerSide) {
309:                        penIncluded[i] = true;
310:                    } else {
311:                        penIncluded[i] = false;
312:                    }
313:                }
314:
315:                int start = -1, end = -1;
316:                for (int i = 0; i < numPenSegments; i++) {
317:                    if (penIncluded[i]
318:                            && !penIncluded[(i + numPenSegments - 1)
319:                                    % numPenSegments]) {
320:                        start = i;
321:                    }
322:                    if (penIncluded[i]
323:                            && !penIncluded[(i + 1) % numPenSegments]) {
324:                        end = i;
325:                    }
326:                }
327:
328:                if (end < start) {
329:                    end += numPenSegments;
330:                }
331:
332:                if (start != -1 && end != -1) {
333:                    long dxa = cx + pen_dx[start] - xa;
334:                    long dya = cy + pen_dy[start] - ya;
335:                    long dxb = cx + pen_dx[start] - xb;
336:                    long dyb = cy + pen_dy[start] - yb;
337:
338:                    boolean rev = (dxa * dxa + dya * dya > dxb * dxb + dyb
339:                            * dyb);
340:                    int i = rev ? end : start;
341:                    int incr = rev ? -1 : 1;
342:                    while (true) {
343:                        int idx = i % numPenSegments;
344:                        px = cx + pen_dx[idx];
345:                        py = cy + pen_dy[idx];
346:                        join[ncoords++] = px;
347:                        join[ncoords++] = py;
348:                        if (i == (rev ? start : end)) {
349:                            break;
350:                        }
351:                        i += incr;
352:                    }
353:                }
354:
355:                return ncoords / 2;
356:            }
357:
358:            private static final long ROUND_JOIN_THRESHOLD = 1000L;
359:            private static final long ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000L;
360:
361:            private void drawRoundJoin(int x, int y, int omx, int omy, int mx,
362:                    int my, int side, boolean flip, boolean rev, long threshold) {
363:                if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
364:                    return;
365:                }
366:
367:                long domx = (long) omx - mx;
368:                long domy = (long) omy - my;
369:                long len = domx * domx + domy * domy;
370:                if (len < threshold) {
371:                    return;
372:                }
373:
374:                if (rev) {
375:                    omx = -omx;
376:                    omy = -omy;
377:                    mx = -mx;
378:                    my = -my;
379:                }
380:
381:                int bx0 = x + omx;
382:                int by0 = y + omy;
383:                int bx1 = x + mx;
384:                int by1 = y + my;
385:
386:                int npoints = computeRoundJoin(x, y, bx0, by0, bx1, by1, side,
387:                        flip, join);
388:                for (int i = 0; i < npoints; i++) {
389:                    emitLineTo(join[2 * i], join[2 * i + 1], rev);
390:                }
391:            }
392:
393:            // Return the intersection point of the lines (ix0, iy0) -> (ix1, iy1)
394:            // and (ix0p, iy0p) -> (ix1p, iy1p) in m[0] and m[1]
395:            private void computeMiter(int ix0, int iy0, int ix1, int iy1,
396:                    int ix0p, int iy0p, int ix1p, int iy1p, int[] m) {
397:                long x0 = ix0;
398:                long y0 = iy0;
399:                long x1 = ix1;
400:                long y1 = iy1;
401:
402:                long x0p = ix0p;
403:                long y0p = iy0p;
404:                long x1p = ix1p;
405:                long y1p = iy1p;
406:
407:                long x10 = x1 - x0;
408:                long y10 = y1 - y0;
409:                long x10p = x1p - x0p;
410:                long y10p = y1p - y0p;
411:
412:                long den = (x10 * y10p - x10p * y10) >> 16;
413:                if (den == 0) {
414:                    m[0] = ix0;
415:                    m[1] = iy0;
416:                    return;
417:                }
418:
419:                long t = (x1p * (y0 - y0p) - x0 * y10p + x0p * (y1p - y0)) >> 16;
420:                m[0] = (int) (x0 + (t * x10) / den);
421:                m[1] = (int) (y0 + (t * y10) / den);
422:            }
423:
424:            private void drawMiter(int px0, int py0, int x0, int y0, int x1,
425:                    int y1, int omx, int omy, int mx, int my, boolean rev) {
426:                if (mx == omx && my == omy) {
427:                    return;
428:                }
429:                if (px0 == x0 && py0 == y0) {
430:                    return;
431:                }
432:                if (x0 == x1 && y0 == y1) {
433:                    return;
434:                }
435:
436:                if (rev) {
437:                    omx = -omx;
438:                    omy = -omy;
439:                    mx = -mx;
440:                    my = -my;
441:                }
442:
443:                computeMiter(px0 + omx, py0 + omy, x0 + omx, y0 + omy, x0 + mx,
444:                        y0 + my, x1 + mx, y1 + my, miter);
445:
446:                // Compute miter length in untransformed coordinates
447:                long dx = (long) miter[0] - x0;
448:                long dy = (long) miter[1] - y0;
449:                long a = (dy * m00 - dx * m10) >> 16;
450:                long b = (dy * m01 - dx * m11) >> 16;
451:                long lenSq = a * a + b * b;
452:
453:                if (lenSq < miterLimitSq) {
454:                    emitLineTo(miter[0], miter[1], rev);
455:                }
456:            }
457:
458:            public void moveTo(int x0, int y0) {
459:                // System.out.println("Stroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
460:
461:                if (lineToOrigin) {
462:                    // not closing the path, do the previous lineTo
463:                    lineToImpl(sx0, sy0, joinToOrigin);
464:                    lineToOrigin = false;
465:                }
466:
467:                if (prev == LINE_TO) {
468:                    finish();
469:                }
470:
471:                this .sx0 = this .x0 = x0;
472:                this .sy0 = this .y0 = y0;
473:                this .rindex = 0;
474:                this .started = false;
475:                this .joinSegment = false;
476:                this .prev = MOVE_TO;
477:            }
478:
479:            boolean joinSegment = false;
480:
481:            public void lineJoin() {
482:                // System.out.println("Stroker.lineJoin()");
483:                this .joinSegment = true;
484:            }
485:
486:            public void lineTo(int x1, int y1) {
487:                // System.out.println("Stroker.lineTo(" + x1/65536.0 + ", " + y1/65536.0 + ")");
488:
489:                if (lineToOrigin) {
490:                    if (x1 == sx0 && y1 == sy0) {
491:                        // staying in the starting point
492:                        return;
493:                    }
494:
495:                    // not closing the path, do the previous lineTo   
496:                    lineToImpl(sx0, sy0, joinToOrigin);
497:                    lineToOrigin = false;
498:                } else if (x1 == x0 && y1 == y0) {
499:                    return;
500:                } else if (x1 == sx0 && y1 == sy0) {
501:                    lineToOrigin = true;
502:                    joinToOrigin = joinSegment;
503:                    joinSegment = false;
504:                    return;
505:                }
506:
507:                lineToImpl(x1, y1, joinSegment);
508:                joinSegment = false;
509:            }
510:
511:            private void lineToImpl(int x1, int y1, boolean joinSegment) {
512:                computeOffset(x0, y0, x1, y1, offset);
513:                int mx = offset[0];
514:                int my = offset[1];
515:
516:                if (!started) {
517:                    emitMoveTo(x0 + mx, y0 + my);
518:                    this .sx1 = x1;
519:                    this .sy1 = y1;
520:                    this .mx0 = mx;
521:                    this .my0 = my;
522:                    started = true;
523:                } else {
524:                    boolean ccw = isCCW(px0, py0, x0, y0, x1, y1);
525:                    if (joinSegment) {
526:                        if (joinStyle == JOIN_MITER) {
527:                            drawMiter(px0, py0, x0, y0, x1, y1, omx, omy, mx,
528:                                    my, ccw);
529:                        } else if (joinStyle == JOIN_ROUND) {
530:                            drawRoundJoin(x0, y0, omx, omy, mx, my, 0, false,
531:                                    ccw, ROUND_JOIN_THRESHOLD);
532:                        }
533:                    } else {
534:                        // Draw internal joins as round
535:                        drawRoundJoin(x0, y0, omx, omy, mx, my, 0, false, ccw,
536:                                ROUND_JOIN_INTERNAL_THRESHOLD);
537:                    }
538:
539:                    emitLineTo(x0, y0, !ccw);
540:                }
541:
542:                emitLineTo(x0 + mx, y0 + my, false);
543:                emitLineTo(x1 + mx, y1 + my, false);
544:
545:                emitLineTo(x0 - mx, y0 - my, true);
546:                emitLineTo(x1 - mx, y1 - my, true);
547:
548:                lx0 = x1 + mx;
549:                ly0 = y1 + my;
550:                lx0p = x1 - mx;
551:                ly0p = y1 - my;
552:                lx1 = x1;
553:                ly1 = y1;
554:
555:                this .omx = mx;
556:                this .omy = my;
557:                this .px0 = x0;
558:                this .py0 = y0;
559:                this .x0 = x1;
560:                this .y0 = y1;
561:                this .prev = LINE_TO;
562:            }
563:
564:            public void close() {
565:                // System.out.println("Stroker.close()");
566:
567:                if (lineToOrigin) {
568:                    // ignore the previous lineTo
569:                    lineToOrigin = false;
570:                }
571:
572:                if (!started) {
573:                    finish();
574:                    return;
575:                }
576:
577:                computeOffset(x0, y0, sx0, sy0, offset);
578:                int mx = offset[0];
579:                int my = offset[1];
580:
581:                // Draw penultimate join
582:                boolean ccw = isCCW(px0, py0, x0, y0, sx0, sy0);
583:                if (joinSegment) {
584:                    if (joinStyle == JOIN_MITER) {
585:                        drawMiter(px0, py0, x0, y0, sx0, sy0, omx, omy, mx, my,
586:                                ccw);
587:                    } else if (joinStyle == JOIN_ROUND) {
588:                        drawRoundJoin(x0, y0, omx, omy, mx, my, 0, false, ccw,
589:                                ROUND_JOIN_THRESHOLD);
590:                    }
591:                } else {
592:                    // Draw internal joins as round
593:                    drawRoundJoin(x0, y0, omx, omy, mx, my, 0, false, ccw,
594:                            ROUND_JOIN_INTERNAL_THRESHOLD);
595:                }
596:
597:                emitLineTo(x0 + mx, y0 + my);
598:                emitLineTo(sx0 + mx, sy0 + my);
599:
600:                ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1);
601:
602:                // Draw final join on the outside
603:                if (!ccw) {
604:                    if (joinStyle == JOIN_MITER) {
605:                        drawMiter(x0, y0, sx0, sy0, sx1, sy1, mx, my, mx0, my0,
606:                                false);
607:                    } else if (joinStyle == JOIN_ROUND) {
608:                        drawRoundJoin(sx0, sy0, mx, my, mx0, my0, 0, false,
609:                                false, ROUND_JOIN_THRESHOLD);
610:                    }
611:                }
612:
613:                emitLineTo(sx0 + mx0, sy0 + my0);
614:                emitLineTo(sx0 - mx0, sy0 - my0); // same as reverse[0], reverse[1]
615:
616:                // Draw final join on the inside
617:                if (ccw) {
618:                    if (joinStyle == JOIN_MITER) {
619:                        drawMiter(x0, y0, sx0, sy0, sx1, sy1, -mx, -my, -mx0,
620:                                -my0, false);
621:                    } else if (joinStyle == JOIN_ROUND) {
622:                        drawRoundJoin(sx0, sy0, -mx, -my, -mx0, -my0, 0, true,
623:                                false, ROUND_JOIN_THRESHOLD);
624:                    }
625:                }
626:
627:                emitLineTo(sx0 - mx, sy0 - my);
628:                emitLineTo(x0 - mx, y0 - my);
629:                for (int i = rindex - 2; i >= 0; i -= 2) {
630:                    emitLineTo(reverse[i], reverse[i + 1]);
631:                }
632:
633:                this .joinSegment = false;
634:                this .prev = CLOSE;
635:                emitClose();
636:            }
637:
638:            public void end() {
639:                // System.out.println("Stroker.end()");
640:
641:                if (lineToOrigin) {
642:                    // not closing the path, do the previous lineTo
643:                    lineToImpl(sx0, sy0, joinToOrigin);
644:                    lineToOrigin = false;
645:                }
646:
647:                if (prev == LINE_TO) {
648:                    finish();
649:                }
650:
651:                output.end();
652:                this .joinSegment = false;
653:                this .prev = MOVE_TO;
654:            }
655:
656:            long lineLength(long ldx, long ldy) {
657:                long ldet = ((long) m00 * m11 - (long) m01 * m10) >> 16;
658:                long la = ((long) ldy * m00 - (long) ldx * m10) / ldet;
659:                long lb = ((long) ldy * m01 - (long) ldx * m11) / ldet;
660:                long llen = (int) PiscesMath.hypot(la, lb);
661:                return llen;
662:            }
663:
664:            private void finish() {
665:                if (capStyle == CAP_ROUND) {
666:                    drawRoundJoin(x0, y0, omx, omy, -omx, -omy, 1, false,
667:                            false, ROUND_JOIN_THRESHOLD);
668:                } else if (capStyle == CAP_SQUARE) {
669:                    long ldx = (long) (px0 - x0);
670:                    long ldy = (long) (py0 - y0);
671:                    long llen = lineLength(ldx, ldy);
672:                    long s = (long) lineWidth2 * 65536 / llen;
673:
674:                    int capx = x0 - (int) (ldx * s >> 16);
675:                    int capy = y0 - (int) (ldy * s >> 16);
676:
677:                    emitLineTo(capx + omx, capy + omy);
678:                    emitLineTo(capx - omx, capy - omy);
679:                }
680:
681:                for (int i = rindex - 2; i >= 0; i -= 2) {
682:                    emitLineTo(reverse[i], reverse[i + 1]);
683:                }
684:
685:                if (capStyle == CAP_ROUND) {
686:                    drawRoundJoin(sx0, sy0, -mx0, -my0, mx0, my0, 1, false,
687:                            false, ROUND_JOIN_THRESHOLD);
688:                } else if (capStyle == CAP_SQUARE) {
689:                    long ldx = (long) (sx1 - sx0);
690:                    long ldy = (long) (sy1 - sy0);
691:                    long llen = lineLength(ldx, ldy);
692:                    long s = (long) lineWidth2 * 65536 / llen;
693:
694:                    int capx = sx0 - (int) (ldx * s >> 16);
695:                    int capy = sy0 - (int) (ldy * s >> 16);
696:
697:                    emitLineTo(capx - mx0, capy - my0);
698:                    emitLineTo(capx + mx0, capy + my0);
699:                }
700:
701:                emitClose();
702:                this .joinSegment = false;
703:            }
704:
705:            private void emitMoveTo(int x0, int y0) {
706:                // System.out.println("Stroker.emitMoveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
707:                output.moveTo(x0, y0);
708:            }
709:
710:            private void emitLineTo(int x1, int y1) {
711:                // System.out.println("Stroker.emitLineTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
712:                output.lineTo(x1, y1);
713:            }
714:
715:            private void emitLineTo(int x1, int y1, boolean rev) {
716:                if (rev) {
717:                    ensureCapacity(rindex + 2);
718:                    reverse[rindex++] = x1;
719:                    reverse[rindex++] = y1;
720:                } else {
721:                    emitLineTo(x1, y1);
722:                }
723:            }
724:
725:            private void emitClose() {
726:                // System.out.println("Stroker.emitClose()");
727:                output.close();
728:            }
729:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.