Source Code Cross Referenced for BasicStroke.java in  » Apache-Harmony-Java-SE » java-package » java » awt » 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 » Apache Harmony Java SE » java package » java.awt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  Licensed to the Apache Software Foundation (ASF) under one or more
0003:         *  contributor license agreements.  See the NOTICE file distributed with
0004:         *  this work for additional information regarding copyright ownership.
0005:         *  The ASF licenses this file to You under the Apache License, Version 2.0
0006:         *  (the "License"); you may not use this file except in compliance with
0007:         *  the License.  You may obtain a copy of the License at
0008:         *
0009:         *     http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         *  Unless required by applicable law or agreed to in writing, software
0012:         *  distributed under the License is distributed on an "AS IS" BASIS,
0013:         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         *  See the License for the specific language governing permissions and
0015:         *  limitations under the License.
0016:         */
0017:        /**
0018:         * @author Denis M. Kishenko
0019:         * @version $Revision$
0020:         */package java.awt;
0021:
0022:        import java.awt.geom.GeneralPath;
0023:        import java.awt.geom.PathIterator;
0024:
0025:        import org.apache.harmony.awt.internal.nls.Messages;
0026:        import org.apache.harmony.misc.HashCode;
0027:
0028:        public class BasicStroke implements  Stroke {
0029:
0030:            public static final int CAP_BUTT = 0;
0031:            public static final int CAP_ROUND = 1;
0032:            public static final int CAP_SQUARE = 2;
0033:
0034:            public static final int JOIN_MITER = 0;
0035:            public static final int JOIN_ROUND = 1;
0036:            public static final int JOIN_BEVEL = 2;
0037:
0038:            /**
0039:             * Constants for calculating 
0040:             */
0041:            static final int MAX_LEVEL = 20; // Maximal deepness of curve subdivision
0042:            static final double CURVE_DELTA = 2.0; // Width tolerance
0043:            static final double CORNER_ANGLE = 4.0; // Minimum corner angel
0044:            static final double CORNER_ZERO = 0.01; // Zero angle
0045:            static final double CUBIC_ARC = 4.0 / 3.0 * (Math.sqrt(2.0) - 1);
0046:
0047:            /**
0048:             * Stroke width
0049:             */
0050:            float width;
0051:
0052:            /**
0053:             * Stroke cap type
0054:             */
0055:            int cap;
0056:
0057:            /**
0058:             * Stroke join type
0059:             */
0060:            int join;
0061:
0062:            /**
0063:             * Stroke miter limit
0064:             */
0065:            float miterLimit;
0066:
0067:            /**
0068:             * Stroke dashes array
0069:             */
0070:            float dash[];
0071:
0072:            /**
0073:             * Stroke dash phase
0074:             */
0075:            float dashPhase;
0076:
0077:            /**
0078:             * The temporary pre-calculated values
0079:             */
0080:            double curveDelta;
0081:            double cornerDelta;
0082:            double zeroDelta;
0083:
0084:            double w2;
0085:            double fmx, fmy;
0086:            double scx, scy, smx, smy;
0087:            double mx, my, cx, cy;
0088:
0089:            /**
0090:             * The temporary indicators
0091:             */
0092:            boolean isMove;
0093:            boolean isFirst;
0094:            boolean checkMove;
0095:
0096:            /**
0097:             * The temporary and destination work paths
0098:             */
0099:            BufferedPath dst, lp, rp, sp;
0100:
0101:            /**
0102:             * Stroke dasher class 
0103:             */
0104:            Dasher dasher;
0105:
0106:            public BasicStroke() {
0107:                this (1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
0108:            }
0109:
0110:            public BasicStroke(float width, int cap, int join,
0111:                    float miterLimit, float[] dash, float dashPhase) {
0112:                if (width < 0.0f) {
0113:                    // awt.133=Negative width
0114:                    throw new IllegalArgumentException(Messages
0115:                            .getString("awt.133")); //$NON-NLS-1$
0116:                }
0117:                if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) {
0118:                    // awt.134=Illegal cap
0119:                    throw new IllegalArgumentException(Messages
0120:                            .getString("awt.134")); //$NON-NLS-1$
0121:                }
0122:                if (join != JOIN_MITER && join != JOIN_ROUND
0123:                        && join != JOIN_BEVEL) {
0124:                    // awt.135=Illegal join
0125:                    throw new IllegalArgumentException(Messages
0126:                            .getString("awt.135")); //$NON-NLS-1$
0127:                }
0128:                if (join == JOIN_MITER && miterLimit < 1.0f) {
0129:                    // awt.136=miterLimit less than 1.0f
0130:                    throw new IllegalArgumentException(Messages
0131:                            .getString("awt.136")); //$NON-NLS-1$
0132:                }
0133:                if (dash != null) {
0134:                    if (dashPhase < 0.0f) {
0135:                        // awt.137=Negative dashPhase
0136:                        throw new IllegalArgumentException(Messages
0137:                                .getString("awt.137")); //$NON-NLS-1$
0138:                    }
0139:                    if (dash.length == 0) {
0140:                        // awt.138=Zero dash length
0141:                        throw new IllegalArgumentException(Messages
0142:                                .getString("awt.138")); //$NON-NLS-1$
0143:                    }
0144:                    ZERO: {
0145:                        for (int i = 0; i < dash.length; i++) {
0146:                            if (dash[i] < 0.0) {
0147:                                // awt.139=Negative dash[{0}]
0148:                                throw new IllegalArgumentException(Messages
0149:                                        .getString("awt.139", i)); //$NON-NLS-1$
0150:                            }
0151:                            if (dash[i] > 0.0) {
0152:                                break ZERO;
0153:                            }
0154:                        }
0155:                        // awt.13A=All dash lengths zero
0156:                        throw new IllegalArgumentException(Messages
0157:                                .getString("awt.13A")); //$NON-NLS-1$
0158:                    }
0159:                }
0160:                this .width = width;
0161:                this .cap = cap;
0162:                this .join = join;
0163:                this .miterLimit = miterLimit;
0164:                this .dash = dash;
0165:                this .dashPhase = dashPhase;
0166:            }
0167:
0168:            public BasicStroke(float width, int cap, int join, float miterLimit) {
0169:                this (width, cap, join, miterLimit, null, 0.0f);
0170:            }
0171:
0172:            public BasicStroke(float width, int cap, int join) {
0173:                this (width, cap, join, 10.0f, null, 0.0f);
0174:            }
0175:
0176:            public BasicStroke(float width) {
0177:                this (width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
0178:            }
0179:
0180:            public float getLineWidth() {
0181:                return width;
0182:            }
0183:
0184:            public int getEndCap() {
0185:                return cap;
0186:            }
0187:
0188:            public int getLineJoin() {
0189:                return join;
0190:            }
0191:
0192:            public float getMiterLimit() {
0193:                return miterLimit;
0194:            }
0195:
0196:            public float[] getDashArray() {
0197:                return dash;
0198:            }
0199:
0200:            public float getDashPhase() {
0201:                return dashPhase;
0202:            }
0203:
0204:            @Override
0205:            public int hashCode() {
0206:                HashCode hash = new HashCode();
0207:                hash.append(width);
0208:                hash.append(cap);
0209:                hash.append(join);
0210:                hash.append(miterLimit);
0211:                if (dash != null) {
0212:                    hash.append(dashPhase);
0213:                    for (float element : dash) {
0214:                        hash.append(element);
0215:                    }
0216:                }
0217:                return hash.hashCode();
0218:            }
0219:
0220:            @Override
0221:            public boolean equals(Object obj) {
0222:                if (obj == this ) {
0223:                    return true;
0224:                }
0225:                if (obj instanceof  BasicStroke) {
0226:                    BasicStroke bs = (BasicStroke) obj;
0227:                    return bs.width == width && bs.cap == cap
0228:                            && bs.join == join && bs.miterLimit == miterLimit
0229:                            && bs.dashPhase == dashPhase
0230:                            && java.util.Arrays.equals(bs.dash, dash);
0231:                }
0232:                return false;
0233:            }
0234:
0235:            /**
0236:             * Calculates allowable curve derivation 
0237:             */
0238:            double getCurveDelta(double width) {
0239:                double a = width + CURVE_DELTA;
0240:                double cos = 1.0 - 2.0 * width * width / (a * a);
0241:                double sin = Math.sqrt(1.0 - cos * cos);
0242:                return Math.abs(sin / cos);
0243:            }
0244:
0245:            /**
0246:             * Calculates value to detect small angle 
0247:             */
0248:            double getCornerDelta(double width) {
0249:                return width * width * Math.sin(Math.PI * CORNER_ANGLE / 180.0);
0250:            }
0251:
0252:            /**
0253:             * Calculates value to detect zero angle 
0254:             */
0255:            double getZeroDelta(double width) {
0256:                return width * width * Math.sin(Math.PI * CORNER_ZERO / 180.0);
0257:            }
0258:
0259:            public Shape createStrokedShape(Shape s) {
0260:                w2 = width / 2.0;
0261:                curveDelta = getCurveDelta(w2);
0262:                cornerDelta = getCornerDelta(w2);
0263:                zeroDelta = getZeroDelta(w2);
0264:
0265:                dst = new BufferedPath();
0266:                lp = new BufferedPath();
0267:                rp = new BufferedPath();
0268:
0269:                if (dash == null) {
0270:                    createSolidShape(s.getPathIterator(null));
0271:                } else {
0272:                    createDashedShape(s.getPathIterator(null));
0273:                }
0274:
0275:                return dst.createGeneralPath();
0276:            }
0277:
0278:            /**
0279:             * Generates solid stroked shape without dash
0280:             * @param p - the PathIterator of source shape
0281:             */
0282:            void createSolidShape(PathIterator p) {
0283:                double coords[] = new double[6];
0284:                mx = my = cx = cy = 0.0;
0285:                isMove = false;
0286:                isFirst = false;
0287:                checkMove = true;
0288:                boolean isClosed = true;
0289:
0290:                while (!p.isDone()) {
0291:                    switch (p.currentSegment(coords)) {
0292:                    case PathIterator.SEG_MOVETO:
0293:                        if (!isClosed) {
0294:                            closeSolidShape();
0295:                        }
0296:                        rp.clean();
0297:                        mx = cx = coords[0];
0298:                        my = cy = coords[1];
0299:                        isMove = true;
0300:                        isClosed = false;
0301:                        break;
0302:                    case PathIterator.SEG_LINETO:
0303:                        addLine(cx, cy, cx = coords[0], cy = coords[1], true);
0304:                        break;
0305:                    case PathIterator.SEG_QUADTO:
0306:                        addQuad(cx, cy, coords[0], coords[1], cx = coords[2],
0307:                                cy = coords[3]);
0308:                        break;
0309:                    case PathIterator.SEG_CUBICTO:
0310:                        addCubic(cx, cy, coords[0], coords[1], coords[2],
0311:                                coords[3], cx = coords[4], cy = coords[5]);
0312:                        break;
0313:                    case PathIterator.SEG_CLOSE:
0314:                        addLine(cx, cy, mx, my, false);
0315:                        addJoin(lp, mx, my, lp.xMove, lp.yMove, true);
0316:                        addJoin(rp, mx, my, rp.xMove, rp.yMove, false);
0317:                        lp.closePath();
0318:                        rp.closePath();
0319:                        lp.appendReverse(rp);
0320:                        isClosed = true;
0321:                        break;
0322:                    }
0323:                    p.next();
0324:                }
0325:                if (!isClosed) {
0326:                    closeSolidShape();
0327:                }
0328:
0329:                dst = lp;
0330:            }
0331:
0332:            /**
0333:             * Closes solid shape path
0334:             */
0335:            void closeSolidShape() {
0336:                addCap(lp, cx, cy, rp.xLast, rp.yLast);
0337:                lp.combine(rp);
0338:                addCap(lp, mx, my, lp.xMove, lp.yMove);
0339:                lp.closePath();
0340:            }
0341:
0342:            /**
0343:             * Generates dashed stroked shape
0344:             * @param p - the PathIterator of source shape
0345:             */
0346:            void createDashedShape(PathIterator p) {
0347:                double coords[] = new double[6];
0348:                mx = my = cx = cy = 0.0;
0349:                smx = smy = scx = scy = 0.0;
0350:                isMove = false;
0351:                checkMove = false;
0352:                boolean isClosed = true;
0353:
0354:                while (!p.isDone()) {
0355:                    switch (p.currentSegment(coords)) {
0356:                    case PathIterator.SEG_MOVETO:
0357:
0358:                        if (!isClosed) {
0359:                            closeDashedShape();
0360:                        }
0361:
0362:                        dasher = new Dasher(dash, dashPhase);
0363:                        lp.clean();
0364:                        rp.clean();
0365:                        sp = null;
0366:                        isFirst = true;
0367:                        isMove = true;
0368:                        isClosed = false;
0369:                        mx = cx = coords[0];
0370:                        my = cy = coords[1];
0371:                        break;
0372:                    case PathIterator.SEG_LINETO:
0373:                        addDashLine(cx, cy, cx = coords[0], cy = coords[1]);
0374:                        break;
0375:                    case PathIterator.SEG_QUADTO:
0376:                        addDashQuad(cx, cy, coords[0], coords[1],
0377:                                cx = coords[2], cy = coords[3]);
0378:                        break;
0379:                    case PathIterator.SEG_CUBICTO:
0380:                        addDashCubic(cx, cy, coords[0], coords[1], coords[2],
0381:                                coords[3], cx = coords[4], cy = coords[5]);
0382:                        break;
0383:                    case PathIterator.SEG_CLOSE:
0384:                        addDashLine(cx, cy, cx = mx, cy = my);
0385:
0386:                        if (dasher.isConnected()) {
0387:                            // Connect current and head segments
0388:                            addJoin(lp, fmx, fmy, sp.xMove, sp.yMove, true);
0389:                            lp.join(sp);
0390:                            addJoin(lp, fmx, fmy, rp.xLast, rp.yLast, true);
0391:                            lp.combine(rp);
0392:                            addCap(lp, smx, smy, lp.xMove, lp.yMove);
0393:                            lp.closePath();
0394:                            dst.append(lp);
0395:                            sp = null;
0396:                        } else {
0397:                            closeDashedShape();
0398:                        }
0399:
0400:                        isClosed = true;
0401:                        break;
0402:                    }
0403:                    p.next();
0404:                }
0405:
0406:                if (!isClosed) {
0407:                    closeDashedShape();
0408:                }
0409:
0410:            }
0411:
0412:            /**
0413:             * Closes dashed shape path
0414:             */
0415:            void closeDashedShape() {
0416:                // Add head segment
0417:                if (sp != null) {
0418:                    addCap(sp, fmx, fmy, sp.xMove, sp.yMove);
0419:                    sp.closePath();
0420:                    dst.append(sp);
0421:                }
0422:                if (lp.typeSize > 0) {
0423:                    // Close current segment
0424:                    if (!dasher.isClosed()) {
0425:                        addCap(lp, scx, scy, rp.xLast, rp.yLast);
0426:                        lp.combine(rp);
0427:                        addCap(lp, smx, smy, lp.xMove, lp.yMove);
0428:                        lp.closePath();
0429:                    }
0430:                    dst.append(lp);
0431:                }
0432:            }
0433:
0434:            /**
0435:             * Adds cap to the work path 
0436:             * @param p - the BufferedPath object of work path
0437:             * @param x0 - the x coordinate of the source path 
0438:             * @param y0 - the y coordinate on the source path
0439:             * @param x2 - the x coordinate of the next point on the work path 
0440:             * @param y2 - the y coordinate of the next point on the work path
0441:             */
0442:            void addCap(BufferedPath p, double x0, double y0, double x2,
0443:                    double y2) {
0444:                double x1 = p.xLast;
0445:                double y1 = p.yLast;
0446:                double x10 = x1 - x0;
0447:                double y10 = y1 - y0;
0448:                double x20 = x2 - x0;
0449:                double y20 = y2 - y0;
0450:
0451:                switch (cap) {
0452:                case CAP_BUTT:
0453:                    p.lineTo(x2, y2);
0454:                    break;
0455:                case CAP_ROUND:
0456:                    double mx = x10 * CUBIC_ARC;
0457:                    double my = y10 * CUBIC_ARC;
0458:
0459:                    double x3 = x0 + y10;
0460:                    double y3 = y0 - x10;
0461:
0462:                    x10 *= CUBIC_ARC;
0463:                    y10 *= CUBIC_ARC;
0464:                    x20 *= CUBIC_ARC;
0465:                    y20 *= CUBIC_ARC;
0466:
0467:                    p.cubicTo(x1 + y10, y1 - x10, x3 + mx, y3 + my, x3, y3);
0468:                    p.cubicTo(x3 - mx, y3 - my, x2 - y20, y2 + x20, x2, y2);
0469:                    break;
0470:                case CAP_SQUARE:
0471:                    p.lineTo(x1 + y10, y1 - x10);
0472:                    p.lineTo(x2 - y20, y2 + x20);
0473:                    p.lineTo(x2, y2);
0474:                    break;
0475:                }
0476:            }
0477:
0478:            /**
0479:             * Adds bevel and miter join to the work path 
0480:             * @param p - the BufferedPath object of work path
0481:             * @param x0 - the x coordinate of the source path 
0482:             * @param y0 - the y coordinate on the source path
0483:             * @param x2 - the x coordinate of the next point on the work path 
0484:             * @param y2 - the y coordinate of the next point on the work path
0485:             * @param isLeft - the orientation of work path, true if work path lies to the left from source path, false otherwise 
0486:             */
0487:            void addJoin(BufferedPath p, double x0, double y0, double x2,
0488:                    double y2, boolean isLeft) {
0489:                double x1 = p.xLast;
0490:                double y1 = p.yLast;
0491:                double x10 = x1 - x0;
0492:                double y10 = y1 - y0;
0493:                double x20 = x2 - x0;
0494:                double y20 = y2 - y0;
0495:                double sin0 = x10 * y20 - y10 * x20;
0496:
0497:                // Small corner
0498:                if (-cornerDelta < sin0 && sin0 < cornerDelta) {
0499:                    double cos0 = x10 * x20 + y10 * y20;
0500:                    if (cos0 > 0.0) {
0501:                        // if zero corner do nothing
0502:                        if (-zeroDelta > sin0 || sin0 > zeroDelta) {
0503:                            double x3 = x0 + w2 * w2 * (y20 - y10) / sin0;
0504:                            double y3 = y0 + w2 * w2 * (x10 - x20) / sin0;
0505:                            p.setLast(x3, y3);
0506:                        }
0507:                        return;
0508:                    }
0509:                    // Zero corner
0510:                    if (-zeroDelta < sin0 && sin0 < zeroDelta) {
0511:                        p.lineTo(x2, y2);
0512:                    }
0513:                    return;
0514:                }
0515:
0516:                if (isLeft ^ (sin0 < 0.0)) {
0517:                    // Twisted corner
0518:                    p.lineTo(x0, y0);
0519:                    p.lineTo(x2, y2);
0520:                } else {
0521:                    switch (join) {
0522:                    case JOIN_BEVEL:
0523:                        p.lineTo(x2, y2);
0524:                        break;
0525:                    case JOIN_MITER:
0526:                        double s1 = x1 * x10 + y1 * y10;
0527:                        double s2 = x2 * x20 + y2 * y20;
0528:                        double x3 = (s1 * y20 - s2 * y10) / sin0;
0529:                        double y3 = (s2 * x10 - s1 * x20) / sin0;
0530:                        double x30 = x3 - x0;
0531:                        double y30 = y3 - y0;
0532:                        double miterLength = Math.sqrt(x30 * x30 + y30 * y30);
0533:                        if (miterLength < miterLimit * w2) {
0534:                            p.lineTo(x3, y3);
0535:                        }
0536:                        p.lineTo(x2, y2);
0537:                        break;
0538:                    case JOIN_ROUND:
0539:                        addRoundJoin(p, x0, y0, x2, y2, isLeft);
0540:                        break;
0541:                    }
0542:                }
0543:            }
0544:
0545:            /**
0546:             * Adds round join to the work path 
0547:             * @param p - the BufferedPath object of work path
0548:             * @param x0 - the x coordinate of the source path 
0549:             * @param y0 - the y coordinate on the source path
0550:             * @param x2 - the x coordinate of the next point on the work path 
0551:             * @param y2 - the y coordinate of the next point on the work path
0552:             * @param isLeft - the orientation of work path, true if work path lies to the left from source path, false otherwise 
0553:             */
0554:            void addRoundJoin(BufferedPath p, double x0, double y0, double x2,
0555:                    double y2, boolean isLeft) {
0556:                double x1 = p.xLast;
0557:                double y1 = p.yLast;
0558:                double x10 = x1 - x0;
0559:                double y10 = y1 - y0;
0560:                double x20 = x2 - x0;
0561:                double y20 = y2 - y0;
0562:
0563:                double x30 = x10 + x20;
0564:                double y30 = y10 + y20;
0565:
0566:                double l30 = Math.sqrt(x30 * x30 + y30 * y30);
0567:
0568:                if (l30 < 1E-5) {
0569:                    p.lineTo(x2, y2);
0570:                    return;
0571:                }
0572:
0573:                double w = w2 / l30;
0574:
0575:                x30 *= w;
0576:                y30 *= w;
0577:
0578:                double x3 = x0 + x30;
0579:                double y3 = y0 + y30;
0580:
0581:                double cos = x10 * x20 + y10 * y20;
0582:                double a = Math.acos(cos / (w2 * w2));
0583:                if (cos >= 0.0) {
0584:                    double k = 4.0 / 3.0 * Math.tan(a / 4.0);
0585:                    if (isLeft) {
0586:                        k = -k;
0587:                    }
0588:
0589:                    x10 *= k;
0590:                    y10 *= k;
0591:                    x20 *= k;
0592:                    y20 *= k;
0593:
0594:                    p.cubicTo(x1 - y10, y1 + x10, x2 + y20, y2 - x20, x2, y2);
0595:                } else {
0596:                    double k = 4.0 / 3.0 * Math.tan(a / 8.0);
0597:                    if (isLeft) {
0598:                        k = -k;
0599:                    }
0600:
0601:                    x10 *= k;
0602:                    y10 *= k;
0603:                    x20 *= k;
0604:                    y20 *= k;
0605:                    x30 *= k;
0606:                    y30 *= k;
0607:
0608:                    p.cubicTo(x1 - y10, y1 + x10, x3 + y30, y3 - x30, x3, y3);
0609:                    p.cubicTo(x3 - y30, y3 + x30, x2 + y20, y2 - x20, x2, y2);
0610:                }
0611:
0612:            }
0613:
0614:            /**
0615:             * Adds solid line segment to the work path
0616:             * @param x1 - the x coordinate of the start line point
0617:             * @param y1 - the y coordinate of the start line point
0618:             * @param x2 - the x coordinate of the end line point
0619:             * @param y2 - the y coordinate of the end line point
0620:             * @param zero - if true it's allowable to add zero length line segment
0621:             */
0622:            void addLine(double x1, double y1, double x2, double y2,
0623:                    boolean zero) {
0624:                double dx = x2 - x1;
0625:                double dy = y2 - y1;
0626:
0627:                if (dx == 0.0 && dy == 0.0) {
0628:                    if (!zero) {
0629:                        return;
0630:                    }
0631:                    dx = w2;
0632:                    dy = 0;
0633:                } else {
0634:                    double w = w2 / Math.sqrt(dx * dx + dy * dy);
0635:                    dx *= w;
0636:                    dy *= w;
0637:                }
0638:
0639:                double lx1 = x1 - dy;
0640:                double ly1 = y1 + dx;
0641:                double rx1 = x1 + dy;
0642:                double ry1 = y1 - dx;
0643:
0644:                if (checkMove) {
0645:                    if (isMove) {
0646:                        isMove = false;
0647:                        lp.moveTo(lx1, ly1);
0648:                        rp.moveTo(rx1, ry1);
0649:                    } else {
0650:                        addJoin(lp, x1, y1, lx1, ly1, true);
0651:                        addJoin(rp, x1, y1, rx1, ry1, false);
0652:                    }
0653:                }
0654:
0655:                lp.lineTo(x2 - dy, y2 + dx);
0656:                rp.lineTo(x2 + dy, y2 - dx);
0657:            }
0658:
0659:            /**
0660:             * Adds solid quad segment to the work path
0661:             * @param x1 - the x coordinate of the first control point
0662:             * @param y1 - the y coordinate of the first control point
0663:             * @param x2 - the x coordinate of the second control point
0664:             * @param y2 - the y coordinate of the second control point
0665:             * @param x3 - the x coordinate of the third control point
0666:             * @param y3 - the y coordinate of the third control point
0667:             */
0668:            void addQuad(double x1, double y1, double x2, double y2, double x3,
0669:                    double y3) {
0670:                double x21 = x2 - x1;
0671:                double y21 = y2 - y1;
0672:                double x23 = x2 - x3;
0673:                double y23 = y2 - y3;
0674:
0675:                double l21 = Math.sqrt(x21 * x21 + y21 * y21);
0676:                double l23 = Math.sqrt(x23 * x23 + y23 * y23);
0677:
0678:                if (l21 == 0.0 && l23 == 0.0) {
0679:                    addLine(x1, y1, x3, y3, false);
0680:                    return;
0681:                }
0682:
0683:                if (l21 == 0.0) {
0684:                    addLine(x2, y2, x3, y3, false);
0685:                    return;
0686:                }
0687:
0688:                if (l23 == 0.0) {
0689:                    addLine(x1, y1, x2, y2, false);
0690:                    return;
0691:                }
0692:
0693:                double w;
0694:                w = w2 / l21;
0695:                double mx1 = -y21 * w;
0696:                double my1 = x21 * w;
0697:                w = w2 / l23;
0698:                double mx3 = y23 * w;
0699:                double my3 = -x23 * w;
0700:
0701:                double lx1 = x1 + mx1;
0702:                double ly1 = y1 + my1;
0703:                double rx1 = x1 - mx1;
0704:                double ry1 = y1 - my1;
0705:
0706:                if (checkMove) {
0707:                    if (isMove) {
0708:                        isMove = false;
0709:                        lp.moveTo(lx1, ly1);
0710:                        rp.moveTo(rx1, ry1);
0711:                    } else {
0712:                        addJoin(lp, x1, y1, lx1, ly1, true);
0713:                        addJoin(rp, x1, y1, rx1, ry1, false);
0714:                    }
0715:                }
0716:
0717:                if (x21 * y23 - y21 * x23 == 0.0) {
0718:                    // On line curve
0719:                    if (x21 * x23 + y21 * y23 > 0.0) {
0720:                        // Twisted curve
0721:                        if (l21 == l23) {
0722:                            double px = x1 + (x21 + x23) / 4.0;
0723:                            double py = y1 + (y21 + y23) / 4.0;
0724:                            lp.lineTo(px + mx1, py + my1);
0725:                            rp.lineTo(px - mx1, py - my1);
0726:                            lp.lineTo(px - mx1, py - my1);
0727:                            rp.lineTo(px + mx1, py + my1);
0728:                            lp.lineTo(x3 - mx1, y3 - my1);
0729:                            rp.lineTo(x3 + mx1, y3 + my1);
0730:                        } else {
0731:                            double px1, py1;
0732:                            double k = l21 / (l21 + l23);
0733:                            double px = x1 + (x21 + x23) * k * k;
0734:                            double py = y1 + (y21 + y23) * k * k;
0735:                            px1 = (x1 + px) / 2.0;
0736:                            py1 = (y1 + py) / 2.0;
0737:                            lp.quadTo(px1 + mx1, py1 + my1, px + mx1, py + my1);
0738:                            rp.quadTo(px1 - mx1, py1 - my1, px - mx1, py - my1);
0739:                            lp.lineTo(px - mx1, py - my1);
0740:                            rp.lineTo(px + mx1, py + my1);
0741:                            px1 = (x3 + px) / 2.0;
0742:                            py1 = (y3 + py) / 2.0;
0743:                            lp.quadTo(px1 - mx1, py1 - my1, x3 - mx1, y3 - my1);
0744:                            rp.quadTo(px1 + mx1, py1 + my1, x3 + mx1, y3 + my1);
0745:                        }
0746:                    } else {
0747:                        // Simple curve
0748:                        lp.quadTo(x2 + mx1, y2 + my1, x3 + mx3, y3 + my3);
0749:                        rp.quadTo(x2 - mx1, y2 - my1, x3 - mx3, y3 - my3);
0750:                    }
0751:                } else {
0752:                    addSubQuad(x1, y1, x2, y2, x3, y3, 0);
0753:                }
0754:            }
0755:
0756:            /**
0757:             * Subdivides solid quad curve to make outline for source quad segment and adds it to work path
0758:             * @param x1 - the x coordinate of the first control point
0759:             * @param y1 - the y coordinate of the first control point
0760:             * @param x2 - the x coordinate of the second control point
0761:             * @param y2 - the y coordinate of the second control point
0762:             * @param x3 - the x coordinate of the third control point
0763:             * @param y3 - the y coordinate of the third control point
0764:             * @param level - the maximum level of subdivision deepness
0765:             */
0766:            void addSubQuad(double x1, double y1, double x2, double y2,
0767:                    double x3, double y3, int level) {
0768:                double x21 = x2 - x1;
0769:                double y21 = y2 - y1;
0770:                double x23 = x2 - x3;
0771:                double y23 = y2 - y3;
0772:
0773:                double cos = x21 * x23 + y21 * y23;
0774:                double sin = x21 * y23 - y21 * x23;
0775:
0776:                if (level < MAX_LEVEL
0777:                        && (cos >= 0.0 || (Math.abs(sin / cos) > curveDelta))) {
0778:                    double c1x = (x2 + x1) / 2.0;
0779:                    double c1y = (y2 + y1) / 2.0;
0780:                    double c2x = (x2 + x3) / 2.0;
0781:                    double c2y = (y2 + y3) / 2.0;
0782:                    double c3x = (c1x + c2x) / 2.0;
0783:                    double c3y = (c1y + c2y) / 2.0;
0784:                    addSubQuad(x1, y1, c1x, c1y, c3x, c3y, level + 1);
0785:                    addSubQuad(c3x, c3y, c2x, c2y, x3, y3, level + 1);
0786:                } else {
0787:                    double w;
0788:                    double l21 = Math.sqrt(x21 * x21 + y21 * y21);
0789:                    double l23 = Math.sqrt(x23 * x23 + y23 * y23);
0790:                    w = w2 / sin;
0791:                    double mx2 = (x21 * l23 + x23 * l21) * w;
0792:                    double my2 = (y21 * l23 + y23 * l21) * w;
0793:                    w = w2 / l23;
0794:                    double mx3 = y23 * w;
0795:                    double my3 = -x23 * w;
0796:                    lp.quadTo(x2 + mx2, y2 + my2, x3 + mx3, y3 + my3);
0797:                    rp.quadTo(x2 - mx2, y2 - my2, x3 - mx3, y3 - my3);
0798:                }
0799:            }
0800:
0801:            /**
0802:             * Adds solid cubic segment to the work path
0803:             * @param x1 - the x coordinate of the first control point
0804:             * @param y1 - the y coordinate of the first control point
0805:             * @param x2 - the x coordinate of the second control point
0806:             * @param y2 - the y coordinate of the second control point
0807:             * @param x3 - the x coordinate of the third control point
0808:             * @param y3 - the y coordinate of the third control point
0809:             * @param x4 - the x coordinate of the fours control point
0810:             * @param y4 - the y coordinate of the fours control point
0811:             */
0812:            void addCubic(double x1, double y1, double x2, double y2,
0813:                    double x3, double y3, double x4, double y4) {
0814:                double x12 = x1 - x2;
0815:                double y12 = y1 - y2;
0816:                double x23 = x2 - x3;
0817:                double y23 = y2 - y3;
0818:                double x34 = x3 - x4;
0819:                double y34 = y3 - y4;
0820:
0821:                double l12 = Math.sqrt(x12 * x12 + y12 * y12);
0822:                double l23 = Math.sqrt(x23 * x23 + y23 * y23);
0823:                double l34 = Math.sqrt(x34 * x34 + y34 * y34);
0824:
0825:                // All edges are zero
0826:                if (l12 == 0.0 && l23 == 0.0 && l34 == 0.0) {
0827:                    addLine(x1, y1, x4, y4, false);
0828:                    return;
0829:                }
0830:
0831:                // One zero edge
0832:                if (l12 == 0.0 && l23 == 0.0) {
0833:                    addLine(x3, y3, x4, y4, false);
0834:                    return;
0835:                }
0836:
0837:                if (l23 == 0.0 && l34 == 0.0) {
0838:                    addLine(x1, y1, x2, y2, false);
0839:                    return;
0840:                }
0841:
0842:                if (l12 == 0.0 && l34 == 0.0) {
0843:                    addLine(x2, y2, x3, y3, false);
0844:                    return;
0845:                }
0846:
0847:                double w, mx1, my1, mx4, my4;
0848:                boolean onLine;
0849:
0850:                if (l12 == 0.0) {
0851:                    w = w2 / l23;
0852:                    mx1 = y23 * w;
0853:                    my1 = -x23 * w;
0854:                    w = w2 / l34;
0855:                    mx4 = y34 * w;
0856:                    my4 = -x34 * w;
0857:                    onLine = -x23 * y34 + y23 * x34 == 0.0; // sin3
0858:                } else if (l34 == 0.0) {
0859:                    w = w2 / l12;
0860:                    mx1 = y12 * w;
0861:                    my1 = -x12 * w;
0862:                    w = w2 / l23;
0863:                    mx4 = y23 * w;
0864:                    my4 = -x23 * w;
0865:                    onLine = -x12 * y23 + y12 * x23 == 0.0; // sin2
0866:                } else {
0867:                    w = w2 / l12;
0868:                    mx1 = y12 * w;
0869:                    my1 = -x12 * w;
0870:                    w = w2 / l34;
0871:                    mx4 = y34 * w;
0872:                    my4 = -x34 * w;
0873:                    if (l23 == 0.0) {
0874:                        onLine = -x12 * y34 + y12 * x34 == 0.0;
0875:                    } else {
0876:                        onLine = -x12 * y34 + y12 * x34 == 0.0
0877:                                && -x12 * y23 + y12 * x23 == 0.0 && // sin2
0878:                                -x23 * y34 + y23 * x34 == 0.0; // sin3
0879:                    }
0880:                }
0881:
0882:                double lx1 = x1 + mx1;
0883:                double ly1 = y1 + my1;
0884:                double rx1 = x1 - mx1;
0885:                double ry1 = y1 - my1;
0886:
0887:                if (checkMove) {
0888:                    if (isMove) {
0889:                        isMove = false;
0890:                        lp.moveTo(lx1, ly1);
0891:                        rp.moveTo(rx1, ry1);
0892:                    } else {
0893:                        addJoin(lp, x1, y1, lx1, ly1, true);
0894:                        addJoin(rp, x1, y1, rx1, ry1, false);
0895:                    }
0896:                }
0897:
0898:                if (onLine) {
0899:                    if ((x1 == x2 && y1 < y2) || x1 < x2) {
0900:                        l12 = -l12;
0901:                    }
0902:                    if ((x2 == x3 && y2 < y3) || x2 < x3) {
0903:                        l23 = -l23;
0904:                    }
0905:                    if ((x3 == x4 && y3 < y4) || x3 < x4) {
0906:                        l34 = -l34;
0907:                    }
0908:                    double d = l23 * l23 - l12 * l34;
0909:                    double roots[] = new double[3];
0910:                    int rc = 0;
0911:                    if (d == 0.0) {
0912:                        double t = (l12 - l23) / (l12 + l34 - l23 - l23);
0913:                        if (0.0 < t && t < 1.0) {
0914:                            roots[rc++] = t;
0915:                        }
0916:                    } else if (d > 0.0) {
0917:                        d = Math.sqrt(d);
0918:                        double z = l12 + l34 - l23 - l23;
0919:                        double t;
0920:                        t = (l12 - l23 + d) / z;
0921:                        if (0.0 < t && t < 1.0) {
0922:                            roots[rc++] = t;
0923:                        }
0924:                        t = (l12 - l23 - d) / z;
0925:                        if (0.0 < t && t < 1.0) {
0926:                            roots[rc++] = t;
0927:                        }
0928:                    }
0929:
0930:                    if (rc > 0) {
0931:                        // Sort roots
0932:                        if (rc == 2 && roots[0] > roots[1]) {
0933:                            double tmp = roots[0];
0934:                            roots[0] = roots[1];
0935:                            roots[1] = tmp;
0936:                        }
0937:                        roots[rc++] = 1.0;
0938:
0939:                        double ax = -x34 - x12 + x23 + x23;
0940:                        double ay = -y34 - y12 + y23 + y23;
0941:                        double bx = 3.0 * (-x23 + x12);
0942:                        double by = 3.0 * (-y23 + y12);
0943:                        double cx = 3.0 * (-x12);
0944:                        double cy = 3.0 * (-y12);
0945:                        double xPrev = x1;
0946:                        double yPrev = y1;
0947:                        for (int i = 0; i < rc; i++) {
0948:                            double t = roots[i];
0949:                            double px = t * (t * (t * ax + bx) + cx) + x1;
0950:                            double py = t * (t * (t * ay + by) + cy) + y1;
0951:                            double px1 = (xPrev + px) / 2.0;
0952:                            double py1 = (yPrev + py) / 2.0;
0953:                            lp.cubicTo(px1 + mx1, py1 + my1, px1 + mx1, py1
0954:                                    + my1, px + mx1, py + my1);
0955:                            rp.cubicTo(px1 - mx1, py1 - my1, px1 - mx1, py1
0956:                                    - my1, px - mx1, py - my1);
0957:                            if (i < rc - 1) {
0958:                                lp.lineTo(px - mx1, py - my1);
0959:                                rp.lineTo(px + mx1, py + my1);
0960:                            }
0961:                            xPrev = px;
0962:                            yPrev = py;
0963:                            mx1 = -mx1;
0964:                            my1 = -my1;
0965:                        }
0966:                    } else {
0967:                        lp.cubicTo(x2 + mx1, y2 + my1, x3 + mx4, y3 + my4, x4
0968:                                + mx4, y4 + my4);
0969:                        rp.cubicTo(x2 - mx1, y2 - my1, x3 - mx4, y3 - my4, x4
0970:                                - mx4, y4 - my4);
0971:                    }
0972:                } else {
0973:                    addSubCubic(x1, y1, x2, y2, x3, y3, x4, y4, 0);
0974:                }
0975:            }
0976:
0977:            /**
0978:             * Subdivides solid cubic curve to make outline for source quad segment and adds it to work path
0979:             * @param x1 - the x coordinate of the first control point
0980:             * @param y1 - the y coordinate of the first control point
0981:             * @param x2 - the x coordinate of the second control point
0982:             * @param y2 - the y coordinate of the second control point
0983:             * @param x3 - the x coordinate of the third control point
0984:             * @param y3 - the y coordinate of the third control point
0985:             * @param x4 - the x coordinate of the fours control point
0986:             * @param y4 - the y coordinate of the fours control point
0987:             * @param level - the maximum level of subdivision deepness
0988:             */
0989:            void addSubCubic(double x1, double y1, double x2, double y2,
0990:                    double x3, double y3, double x4, double y4, int level) {
0991:                double x12 = x1 - x2;
0992:                double y12 = y1 - y2;
0993:                double x23 = x2 - x3;
0994:                double y23 = y2 - y3;
0995:                double x34 = x3 - x4;
0996:                double y34 = y3 - y4;
0997:
0998:                double cos2 = -x12 * x23 - y12 * y23;
0999:                double cos3 = -x23 * x34 - y23 * y34;
1000:                double sin2 = -x12 * y23 + y12 * x23;
1001:                double sin3 = -x23 * y34 + y23 * x34;
1002:                double sin0 = -x12 * y34 + y12 * x34;
1003:                double cos0 = -x12 * x34 - y12 * y34;
1004:
1005:                if (level < MAX_LEVEL
1006:                        && (sin2 != 0.0 || sin3 != 0.0 || sin0 != 0.0)
1007:                        && (cos2 >= 0.0 || cos3 >= 0.0 || cos0 >= 0.0
1008:                                || (Math.abs(sin2 / cos2) > curveDelta)
1009:                                || (Math.abs(sin3 / cos3) > curveDelta) || (Math
1010:                                .abs(sin0 / cos0) > curveDelta))) {
1011:                    double cx = (x2 + x3) / 2.0;
1012:                    double cy = (y2 + y3) / 2.0;
1013:                    double lx2 = (x2 + x1) / 2.0;
1014:                    double ly2 = (y2 + y1) / 2.0;
1015:                    double rx3 = (x3 + x4) / 2.0;
1016:                    double ry3 = (y3 + y4) / 2.0;
1017:                    double lx3 = (cx + lx2) / 2.0;
1018:                    double ly3 = (cy + ly2) / 2.0;
1019:                    double rx2 = (cx + rx3) / 2.0;
1020:                    double ry2 = (cy + ry3) / 2.0;
1021:                    cx = (lx3 + rx2) / 2.0;
1022:                    cy = (ly3 + ry2) / 2.0;
1023:                    addSubCubic(x1, y1, lx2, ly2, lx3, ly3, cx, cy, level + 1);
1024:                    addSubCubic(cx, cy, rx2, ry2, rx3, ry3, x4, y4, level + 1);
1025:                } else {
1026:                    double w, mx1, my1, mx2, my2, mx3, my3, mx4, my4;
1027:                    double l12 = Math.sqrt(x12 * x12 + y12 * y12);
1028:                    double l23 = Math.sqrt(x23 * x23 + y23 * y23);
1029:                    double l34 = Math.sqrt(x34 * x34 + y34 * y34);
1030:
1031:                    if (l12 == 0.0) {
1032:                        w = w2 / l23;
1033:                        mx1 = y23 * w;
1034:                        my1 = -x23 * w;
1035:                        w = w2 / l34;
1036:                        mx4 = y34 * w;
1037:                        my4 = -x34 * w;
1038:                    } else if (l34 == 0.0) {
1039:                        w = w2 / l12;
1040:                        mx1 = y12 * w;
1041:                        my1 = -x12 * w;
1042:                        w = w2 / l23;
1043:                        mx4 = y23 * w;
1044:                        my4 = -x23 * w;
1045:                    } else {
1046:                        // Common case
1047:                        w = w2 / l12;
1048:                        mx1 = y12 * w;
1049:                        my1 = -x12 * w;
1050:                        w = w2 / l34;
1051:                        mx4 = y34 * w;
1052:                        my4 = -x34 * w;
1053:                    }
1054:
1055:                    if (sin2 == 0.0) {
1056:                        mx2 = mx1;
1057:                        my2 = my1;
1058:                    } else {
1059:                        w = w2 / sin2;
1060:                        mx2 = -(x12 * l23 - x23 * l12) * w;
1061:                        my2 = -(y12 * l23 - y23 * l12) * w;
1062:                    }
1063:                    if (sin3 == 0.0) {
1064:                        mx3 = mx4;
1065:                        my3 = my4;
1066:                    } else {
1067:                        w = w2 / sin3;
1068:                        mx3 = -(x23 * l34 - x34 * l23) * w;
1069:                        my3 = -(y23 * l34 - y34 * l23) * w;
1070:                    }
1071:
1072:                    lp.cubicTo(x2 + mx2, y2 + my2, x3 + mx3, y3 + my3,
1073:                            x4 + mx4, y4 + my4);
1074:                    rp.cubicTo(x2 - mx2, y2 - my2, x3 - mx3, y3 - my3,
1075:                            x4 - mx4, y4 - my4);
1076:                }
1077:            }
1078:
1079:            /**
1080:             * Adds dashed line segment to the work path
1081:             * @param x1 - the x coordinate of the start line point
1082:             * @param y1 - the y coordinate of the start line point
1083:             * @param x2 - the x coordinate of the end line point
1084:             * @param y2 - the y coordinate of the end line point
1085:             */
1086:            void addDashLine(double x1, double y1, double x2, double y2) {
1087:                double x21 = x2 - x1;
1088:                double y21 = y2 - y1;
1089:
1090:                double l21 = Math.sqrt(x21 * x21 + y21 * y21);
1091:
1092:                if (l21 == 0.0) {
1093:                    return;
1094:                }
1095:
1096:                double px1, py1;
1097:                px1 = py1 = 0.0;
1098:                double w = w2 / l21;
1099:                double mx = -y21 * w;
1100:                double my = x21 * w;
1101:
1102:                dasher.init(new DashIterator.Line(l21));
1103:
1104:                while (!dasher.eof()) {
1105:                    double t = dasher.getValue();
1106:                    scx = x1 + t * x21;
1107:                    scy = y1 + t * y21;
1108:
1109:                    if (dasher.isOpen()) {
1110:                        px1 = scx;
1111:                        py1 = scy;
1112:                        double lx1 = px1 + mx;
1113:                        double ly1 = py1 + my;
1114:                        double rx1 = px1 - mx;
1115:                        double ry1 = py1 - my;
1116:                        if (isMove) {
1117:                            isMove = false;
1118:                            smx = px1;
1119:                            smy = py1;
1120:                            rp.clean();
1121:                            lp.moveTo(lx1, ly1);
1122:                            rp.moveTo(rx1, ry1);
1123:                        } else {
1124:                            addJoin(lp, x1, y1, lx1, ly1, true);
1125:                            addJoin(rp, x1, y1, rx1, ry1, false);
1126:                        }
1127:                    } else if (dasher.isContinue()) {
1128:                        double px2 = scx;
1129:                        double py2 = scy;
1130:                        lp.lineTo(px2 + mx, py2 + my);
1131:                        rp.lineTo(px2 - mx, py2 - my);
1132:                        if (dasher.close) {
1133:                            addCap(lp, px2, py2, rp.xLast, rp.yLast);
1134:                            lp.combine(rp);
1135:                            if (isFirst) {
1136:                                isFirst = false;
1137:                                fmx = smx;
1138:                                fmy = smy;
1139:                                sp = lp;
1140:                                lp = new BufferedPath();
1141:                            } else {
1142:                                addCap(lp, smx, smy, lp.xMove, lp.yMove);
1143:                                lp.closePath();
1144:                            }
1145:                            isMove = true;
1146:                        }
1147:                    }
1148:
1149:                    dasher.next();
1150:                }
1151:            }
1152:
1153:            /**
1154:             * Adds dashed quad segment to the work path
1155:             * @param x1 - the x coordinate of the first control point
1156:             * @param y1 - the y coordinate of the first control point
1157:             * @param x2 - the x coordinate of the second control point
1158:             * @param y2 - the y coordinate of the second control point
1159:             * @param x3 - the x coordinate of the third control point
1160:             * @param y3 - the y coordinate of the third control point
1161:             */
1162:            void addDashQuad(double x1, double y1, double x2, double y2,
1163:                    double x3, double y3) {
1164:
1165:                double x21 = x2 - x1;
1166:                double y21 = y2 - y1;
1167:                double x23 = x2 - x3;
1168:                double y23 = y2 - y3;
1169:
1170:                double l21 = Math.sqrt(x21 * x21 + y21 * y21);
1171:                double l23 = Math.sqrt(x23 * x23 + y23 * y23);
1172:
1173:                if (l21 == 0.0 && l23 == 0.0) {
1174:                    return;
1175:                }
1176:
1177:                if (l21 == 0.0) {
1178:                    addDashLine(x2, y2, x3, y3);
1179:                    return;
1180:                }
1181:
1182:                if (l23 == 0.0) {
1183:                    addDashLine(x1, y1, x2, y2);
1184:                    return;
1185:                }
1186:
1187:                double ax = x1 + x3 - x2 - x2;
1188:                double ay = y1 + y3 - y2 - y2;
1189:                double bx = x2 - x1;
1190:                double by = y2 - y1;
1191:                double cx = x1;
1192:                double cy = y1;
1193:
1194:                double px1, py1, dx1, dy1;
1195:                px1 = py1 = dx1 = dy1 = 0.0;
1196:                double prev = 0.0;
1197:
1198:                dasher.init(new DashIterator.Quad(x1, y1, x2, y2, x3, y3));
1199:
1200:                while (!dasher.eof()) {
1201:                    double t = dasher.getValue();
1202:                    double dx = t * ax + bx;
1203:                    double dy = t * ay + by;
1204:                    scx = t * (dx + bx) + cx; // t^2 * ax + 2.0 * t * bx + cx
1205:                    scy = t * (dy + by) + cy; // t^2 * ay + 2.0 * t * by + cy
1206:                    if (dasher.isOpen()) {
1207:                        px1 = scx;
1208:                        py1 = scy;
1209:                        dx1 = dx;
1210:                        dy1 = dy;
1211:                        double w = w2 / Math.sqrt(dx1 * dx1 + dy1 * dy1);
1212:                        double mx1 = -dy1 * w;
1213:                        double my1 = dx1 * w;
1214:                        double lx1 = px1 + mx1;
1215:                        double ly1 = py1 + my1;
1216:                        double rx1 = px1 - mx1;
1217:                        double ry1 = py1 - my1;
1218:                        if (isMove) {
1219:                            isMove = false;
1220:                            smx = px1;
1221:                            smy = py1;
1222:                            rp.clean();
1223:                            lp.moveTo(lx1, ly1);
1224:                            rp.moveTo(rx1, ry1);
1225:                        } else {
1226:                            addJoin(lp, x1, y1, lx1, ly1, true);
1227:                            addJoin(rp, x1, y1, rx1, ry1, false);
1228:                        }
1229:                    } else if (dasher.isContinue()) {
1230:                        double px3 = scx;
1231:                        double py3 = scy;
1232:                        double sx = x2 - x23 * prev;
1233:                        double sy = y2 - y23 * prev;
1234:                        double t2 = (t - prev) / (1 - prev);
1235:                        double px2 = px1 + (sx - px1) * t2;
1236:                        double py2 = py1 + (sy - py1) * t2;
1237:
1238:                        addQuad(px1, py1, px2, py2, px3, py3);
1239:                        if (dasher.isClosed()) {
1240:                            addCap(lp, px3, py3, rp.xLast, rp.yLast);
1241:                            lp.combine(rp);
1242:                            if (isFirst) {
1243:                                isFirst = false;
1244:                                fmx = smx;
1245:                                fmy = smy;
1246:                                sp = lp;
1247:                                lp = new BufferedPath();
1248:                            } else {
1249:                                addCap(lp, smx, smy, lp.xMove, lp.yMove);
1250:                                lp.closePath();
1251:                            }
1252:                            isMove = true;
1253:                        }
1254:                    }
1255:
1256:                    prev = t;
1257:                    dasher.next();
1258:                }
1259:            }
1260:
1261:            /**
1262:             * Adds dashed cubic segment to the work path
1263:             * @param x1 - the x coordinate of the first control point
1264:             * @param y1 - the y coordinate of the first control point
1265:             * @param x2 - the x coordinate of the second control point
1266:             * @param y2 - the y coordinate of the second control point
1267:             * @param x3 - the x coordinate of the third control point
1268:             * @param y3 - the y coordinate of the third control point
1269:             * @param x4 - the x coordinate of the fours control point
1270:             * @param y4 - the y coordinate of the fours control point
1271:             */
1272:            void addDashCubic(double x1, double y1, double x2, double y2,
1273:                    double x3, double y3, double x4, double y4) {
1274:
1275:                double x12 = x1 - x2;
1276:                double y12 = y1 - y2;
1277:                double x23 = x2 - x3;
1278:                double y23 = y2 - y3;
1279:                double x34 = x3 - x4;
1280:                double y34 = y3 - y4;
1281:
1282:                double l12 = Math.sqrt(x12 * x12 + y12 * y12);
1283:                double l23 = Math.sqrt(x23 * x23 + y23 * y23);
1284:                double l34 = Math.sqrt(x34 * x34 + y34 * y34);
1285:
1286:                // All edges are zero
1287:                if (l12 == 0.0 && l23 == 0.0 && l34 == 0.0) {
1288:                    // NOTHING
1289:                    return;
1290:                }
1291:
1292:                // One zero edge
1293:                if (l12 == 0.0 && l23 == 0.0) {
1294:                    addDashLine(x3, y3, x4, y4);
1295:                    return;
1296:                }
1297:
1298:                if (l23 == 0.0 && l34 == 0.0) {
1299:                    addDashLine(x1, y1, x2, y2);
1300:                    return;
1301:                }
1302:
1303:                if (l12 == 0.0 && l34 == 0.0) {
1304:                    addDashLine(x2, y2, x3, y3);
1305:                    return;
1306:                }
1307:
1308:                double ax = x4 - x1 + 3.0 * (x2 - x3);
1309:                double ay = y4 - y1 + 3.0 * (y2 - y3);
1310:                double bx = 3.0 * (x1 + x3 - x2 - x2);
1311:                double by = 3.0 * (y1 + y3 - y2 - y2);
1312:                double cx = 3.0 * (x2 - x1);
1313:                double cy = 3.0 * (y2 - y1);
1314:                double dx = x1;
1315:                double dy = y1;
1316:
1317:                double px1 = 0.0;
1318:                double py1 = 0.0;
1319:                double prev = 0.0;
1320:
1321:                dasher.init(new DashIterator.Cubic(x1, y1, x2, y2, x3, y3, x4,
1322:                        y4));
1323:
1324:                while (!dasher.eof()) {
1325:
1326:                    double t = dasher.getValue();
1327:                    scx = t * (t * (t * ax + bx) + cx) + dx;
1328:                    scy = t * (t * (t * ay + by) + cy) + dy;
1329:                    if (dasher.isOpen()) {
1330:                        px1 = scx;
1331:                        py1 = scy;
1332:                        double dx1 = t * (t * (ax + ax + ax) + bx + bx) + cx;
1333:                        double dy1 = t * (t * (ay + ay + ay) + by + by) + cy;
1334:                        double w = w2 / Math.sqrt(dx1 * dx1 + dy1 * dy1);
1335:                        double mx1 = -dy1 * w;
1336:                        double my1 = dx1 * w;
1337:                        double lx1 = px1 + mx1;
1338:                        double ly1 = py1 + my1;
1339:                        double rx1 = px1 - mx1;
1340:                        double ry1 = py1 - my1;
1341:                        if (isMove) {
1342:                            isMove = false;
1343:                            smx = px1;
1344:                            smy = py1;
1345:                            rp.clean();
1346:                            lp.moveTo(lx1, ly1);
1347:                            rp.moveTo(rx1, ry1);
1348:                        } else {
1349:                            addJoin(lp, x1, y1, lx1, ly1, true);
1350:                            addJoin(rp, x1, y1, rx1, ry1, false);
1351:                        }
1352:                    } else if (dasher.isContinue()) {
1353:                        double sx1 = x2 - x23 * prev;
1354:                        double sy1 = y2 - y23 * prev;
1355:                        double sx2 = x3 - x34 * prev;
1356:                        double sy2 = y3 - y34 * prev;
1357:                        double sx3 = sx1 + (sx2 - sx1) * prev;
1358:                        double sy3 = sy1 + (sy2 - sy1) * prev;
1359:                        double t2 = (t - prev) / (1 - prev);
1360:                        double sx4 = sx3 + (sx2 - sx3) * t2;
1361:                        double sy4 = sy3 + (sy2 - sy3) * t2;
1362:
1363:                        double px4 = scx;
1364:                        double py4 = scy;
1365:                        double px2 = px1 + (sx3 - px1) * t2;
1366:                        double py2 = py1 + (sy3 - py1) * t2;
1367:                        double px3 = px2 + (sx4 - px2) * t2;
1368:                        double py3 = py2 + (sy4 - py2) * t2;
1369:
1370:                        addCubic(px1, py1, px2, py2, px3, py3, px4, py4);
1371:                        if (dasher.isClosed()) {
1372:                            addCap(lp, px4, py4, rp.xLast, rp.yLast);
1373:                            lp.combine(rp);
1374:                            if (isFirst) {
1375:                                isFirst = false;
1376:                                fmx = smx;
1377:                                fmy = smy;
1378:                                sp = lp;
1379:                                lp = new BufferedPath();
1380:                            } else {
1381:                                addCap(lp, smx, smy, lp.xMove, lp.yMove);
1382:                                lp.closePath();
1383:                            }
1384:                            isMove = true;
1385:                        }
1386:                    }
1387:
1388:                    prev = t;
1389:                    dasher.next();
1390:                }
1391:            }
1392:
1393:            /**
1394:             *  Dasher class provides dashing for particular dash style
1395:             */
1396:            class Dasher {
1397:
1398:                double pos;
1399:                boolean close, visible, first;
1400:                float dash[];
1401:                float phase;
1402:                int index;
1403:                DashIterator iter;
1404:
1405:                Dasher(float dash[], float phase) {
1406:                    this .dash = dash;
1407:                    this .phase = phase;
1408:                    index = 0;
1409:                    pos = phase;
1410:                    visible = true;
1411:                    while (pos >= dash[index]) {
1412:                        visible = !visible;
1413:                        pos -= dash[index];
1414:                        index = (index + 1) % dash.length;
1415:                    }
1416:                    pos = -pos;
1417:                    first = visible;
1418:                }
1419:
1420:                void init(DashIterator iter) {
1421:                    this .iter = iter;
1422:                    close = true;
1423:                }
1424:
1425:                boolean isOpen() {
1426:                    return visible && pos < iter.length;
1427:                }
1428:
1429:                boolean isContinue() {
1430:                    return !visible && pos > 0;
1431:                }
1432:
1433:                boolean isClosed() {
1434:                    return close;
1435:                }
1436:
1437:                boolean isConnected() {
1438:                    return first && !close;
1439:                }
1440:
1441:                boolean eof() {
1442:                    if (!close) {
1443:                        pos -= iter.length;
1444:                        return true;
1445:                    }
1446:                    if (pos >= iter.length) {
1447:                        if (visible) {
1448:                            pos -= iter.length;
1449:                            return true;
1450:                        }
1451:                        close = pos == iter.length;
1452:                    }
1453:                    return false;
1454:                }
1455:
1456:                void next() {
1457:                    if (close) {
1458:                        pos += dash[index];
1459:                        index = (index + 1) % dash.length;
1460:                    } else {
1461:                        // Go back
1462:                        index = (index + dash.length - 1) % dash.length;
1463:                        pos -= dash[index];
1464:                    }
1465:                    visible = !visible;
1466:                }
1467:
1468:                double getValue() {
1469:                    double t = iter.getNext(pos);
1470:                    return t < 0 ? 0 : (t > 1 ? 1 : t);
1471:                }
1472:
1473:            }
1474:
1475:            /**
1476:             * DashIterator class provides dashing for particular segment type  
1477:             */
1478:            static abstract class DashIterator {
1479:
1480:                static final double FLATNESS = 1.0;
1481:
1482:                static class Line extends DashIterator {
1483:
1484:                    Line(double len) {
1485:                        length = len;
1486:                    }
1487:
1488:                    @Override
1489:                    double getNext(double dashPos) {
1490:                        return dashPos / length;
1491:                    }
1492:
1493:                }
1494:
1495:                static class Quad extends DashIterator {
1496:
1497:                    int valSize;
1498:                    int valPos;
1499:                    double curLen;
1500:                    double prevLen;
1501:                    double lastLen;
1502:                    double[] values;
1503:                    double step;
1504:
1505:                    Quad(double x1, double y1, double x2, double y2, double x3,
1506:                            double y3) {
1507:
1508:                        double nx = x1 + x3 - x2 - x2;
1509:                        double ny = y1 + y3 - y2 - y2;
1510:
1511:                        int n = (int) (1 + Math.sqrt(0.75
1512:                                * (Math.abs(nx) + Math.abs(ny)) * FLATNESS));
1513:                        step = 1.0 / n;
1514:
1515:                        double ax = x1 + x3 - x2 - x2;
1516:                        double ay = y1 + y3 - y2 - y2;
1517:                        double bx = 2.0 * (x2 - x1);
1518:                        double by = 2.0 * (y2 - y1);
1519:
1520:                        double dx1 = step * (step * ax + bx);
1521:                        double dy1 = step * (step * ay + by);
1522:                        double dx2 = step * (step * ax * 2.0);
1523:                        double dy2 = step * (step * ay * 2.0);
1524:                        double vx = x1;
1525:                        double vy = y1;
1526:
1527:                        valSize = n;
1528:                        values = new double[valSize];
1529:                        double pvx = vx;
1530:                        double pvy = vy;
1531:                        length = 0.0;
1532:                        for (int i = 0; i < n; i++) {
1533:                            vx += dx1;
1534:                            vy += dy1;
1535:                            dx1 += dx2;
1536:                            dy1 += dy2;
1537:                            double lx = vx - pvx;
1538:                            double ly = vy - pvy;
1539:                            values[i] = Math.sqrt(lx * lx + ly * ly);
1540:                            length += values[i];
1541:                            pvx = vx;
1542:                            pvy = vy;
1543:                        }
1544:
1545:                        valPos = 0;
1546:                        curLen = 0.0;
1547:                        prevLen = 0.0;
1548:                    }
1549:
1550:                    @Override
1551:                    double getNext(double dashPos) {
1552:                        double t = 2.0;
1553:                        while (curLen <= dashPos && valPos < valSize) {
1554:                            prevLen = curLen;
1555:                            curLen += lastLen = values[valPos++];
1556:                        }
1557:                        if (curLen > dashPos) {
1558:                            t = (valPos - 1 + (dashPos - prevLen) / lastLen)
1559:                                    * step;
1560:                        }
1561:                        return t;
1562:                    }
1563:
1564:                }
1565:
1566:                static class Cubic extends DashIterator {
1567:
1568:                    int valSize;
1569:                    int valPos;
1570:                    double curLen;
1571:                    double prevLen;
1572:                    double lastLen;
1573:                    double[] values;
1574:                    double step;
1575:
1576:                    Cubic(double x1, double y1, double x2, double y2,
1577:                            double x3, double y3, double x4, double y4) {
1578:
1579:                        double nx1 = x1 + x3 - x2 - x2;
1580:                        double ny1 = y1 + y3 - y2 - y2;
1581:                        double nx2 = x2 + x4 - x3 - x3;
1582:                        double ny2 = y2 + y4 - y3 - y3;
1583:
1584:                        double max = Math.max(Math.abs(nx1) + Math.abs(ny1),
1585:                                Math.abs(nx2) + Math.abs(ny2));
1586:                        int n = (int) (1 + Math.sqrt(0.75 * max) * FLATNESS);
1587:                        step = 1.0 / n;
1588:
1589:                        double ax = x4 - x1 + 3.0 * (x2 - x3);
1590:                        double ay = y4 - y1 + 3.0 * (y2 - y3);
1591:                        double bx = 3.0 * (x1 + x3 - x2 - x2);
1592:                        double by = 3.0 * (y1 + y3 - y2 - y2);
1593:                        double cx = 3.0 * (x2 - x1);
1594:                        double cy = 3.0 * (y2 - y1);
1595:
1596:                        double dx1 = step * (step * (step * ax + bx) + cx);
1597:                        double dy1 = step * (step * (step * ay + by) + cy);
1598:                        double dx2 = step
1599:                                * (step * (step * ax * 6.0 + bx * 2.0));
1600:                        double dy2 = step
1601:                                * (step * (step * ay * 6.0 + by * 2.0));
1602:                        double dx3 = step * (step * (step * ax * 6.0));
1603:                        double dy3 = step * (step * (step * ay * 6.0));
1604:                        double vx = x1;
1605:                        double vy = y1;
1606:
1607:                        valSize = n;
1608:                        values = new double[valSize];
1609:                        double pvx = vx;
1610:                        double pvy = vy;
1611:                        length = 0.0;
1612:                        for (int i = 0; i < n; i++) {
1613:                            vx += dx1;
1614:                            vy += dy1;
1615:                            dx1 += dx2;
1616:                            dy1 += dy2;
1617:                            dx2 += dx3;
1618:                            dy2 += dy3;
1619:                            double lx = vx - pvx;
1620:                            double ly = vy - pvy;
1621:                            values[i] = Math.sqrt(lx * lx + ly * ly);
1622:                            length += values[i];
1623:                            pvx = vx;
1624:                            pvy = vy;
1625:                        }
1626:
1627:                        valPos = 0;
1628:                        curLen = 0.0;
1629:                        prevLen = 0.0;
1630:                    }
1631:
1632:                    @Override
1633:                    double getNext(double dashPos) {
1634:                        double t = 2.0;
1635:                        while (curLen <= dashPos && valPos < valSize) {
1636:                            prevLen = curLen;
1637:                            curLen += lastLen = values[valPos++];
1638:                        }
1639:                        if (curLen > dashPos) {
1640:                            t = (valPos - 1 + (dashPos - prevLen) / lastLen)
1641:                                    * step;
1642:                        }
1643:                        return t;
1644:                    }
1645:
1646:                }
1647:
1648:                double length;
1649:
1650:                abstract double getNext(double dashPos);
1651:
1652:            }
1653:
1654:            /**
1655:             * BufferedPath class provides work path storing and processing
1656:             */
1657:            static class BufferedPath {
1658:
1659:                private static final int bufCapacity = 10;
1660:
1661:                static int pointShift[] = { 2, // MOVETO
1662:                        2, // LINETO
1663:                        4, // QUADTO
1664:                        6, // CUBICTO
1665:                        0 }; // CLOSE
1666:
1667:                byte[] types;
1668:                float[] points;
1669:                int typeSize;
1670:                int pointSize;
1671:
1672:                float xLast;
1673:                float yLast;
1674:                float xMove;
1675:                float yMove;
1676:
1677:                public BufferedPath() {
1678:                    types = new byte[bufCapacity];
1679:                    points = new float[bufCapacity * 2];
1680:                }
1681:
1682:                void checkBuf(int typeCount, int pointCount) {
1683:                    if (typeSize + typeCount > types.length) {
1684:                        byte tmp[] = new byte[typeSize
1685:                                + Math.max(bufCapacity, typeCount)];
1686:                        System.arraycopy(types, 0, tmp, 0, typeSize);
1687:                        types = tmp;
1688:                    }
1689:                    if (pointSize + pointCount > points.length) {
1690:                        float tmp[] = new float[pointSize
1691:                                + Math.max(bufCapacity * 2, pointCount)];
1692:                        System.arraycopy(points, 0, tmp, 0, pointSize);
1693:                        points = tmp;
1694:                    }
1695:                }
1696:
1697:                boolean isEmpty() {
1698:                    return typeSize == 0;
1699:                }
1700:
1701:                void clean() {
1702:                    typeSize = 0;
1703:                    pointSize = 0;
1704:                }
1705:
1706:                void moveTo(double x, double y) {
1707:                    checkBuf(1, 2);
1708:                    types[typeSize++] = PathIterator.SEG_MOVETO;
1709:                    points[pointSize++] = xMove = (float) x;
1710:                    points[pointSize++] = yMove = (float) y;
1711:                }
1712:
1713:                void lineTo(double x, double y) {
1714:                    checkBuf(1, 2);
1715:                    types[typeSize++] = PathIterator.SEG_LINETO;
1716:                    points[pointSize++] = xLast = (float) x;
1717:                    points[pointSize++] = yLast = (float) y;
1718:                }
1719:
1720:                void quadTo(double x1, double y1, double x2, double y2) {
1721:                    checkBuf(1, 4);
1722:                    types[typeSize++] = PathIterator.SEG_QUADTO;
1723:                    points[pointSize++] = (float) x1;
1724:                    points[pointSize++] = (float) y1;
1725:                    points[pointSize++] = xLast = (float) x2;
1726:                    points[pointSize++] = yLast = (float) y2;
1727:                }
1728:
1729:                void cubicTo(double x1, double y1, double x2, double y2,
1730:                        double x3, double y3) {
1731:                    checkBuf(1, 6);
1732:                    types[typeSize++] = PathIterator.SEG_CUBICTO;
1733:                    points[pointSize++] = (float) x1;
1734:                    points[pointSize++] = (float) y1;
1735:                    points[pointSize++] = (float) x2;
1736:                    points[pointSize++] = (float) y2;
1737:                    points[pointSize++] = xLast = (float) x3;
1738:                    points[pointSize++] = yLast = (float) y3;
1739:                }
1740:
1741:                void closePath() {
1742:                    checkBuf(1, 0);
1743:                    types[typeSize++] = PathIterator.SEG_CLOSE;
1744:                }
1745:
1746:                void setLast(double x, double y) {
1747:                    points[pointSize - 2] = xLast = (float) x;
1748:                    points[pointSize - 1] = yLast = (float) y;
1749:                }
1750:
1751:                void append(BufferedPath p) {
1752:                    checkBuf(p.typeSize, p.pointSize);
1753:                    System.arraycopy(p.points, 0, points, pointSize,
1754:                            p.pointSize);
1755:                    System.arraycopy(p.types, 0, types, typeSize, p.typeSize);
1756:                    pointSize += p.pointSize;
1757:                    typeSize += p.typeSize;
1758:                    xLast = points[pointSize - 2];
1759:                    yLast = points[pointSize - 1];
1760:                }
1761:
1762:                void appendReverse(BufferedPath p) {
1763:                    checkBuf(p.typeSize, p.pointSize);
1764:                    // Skip last point, beacause it's the first point of the second path
1765:                    for (int i = p.pointSize - 2; i >= 0; i -= 2) {
1766:                        points[pointSize++] = p.points[i + 0];
1767:                        points[pointSize++] = p.points[i + 1];
1768:                    }
1769:                    // Skip first type, beacuse it's always MOVETO
1770:                    int closeIndex = 0;
1771:                    for (int i = p.typeSize - 1; i >= 0; i--) {
1772:                        byte type = p.types[i];
1773:                        if (type == PathIterator.SEG_MOVETO) {
1774:                            types[closeIndex] = PathIterator.SEG_MOVETO;
1775:                            types[typeSize++] = PathIterator.SEG_CLOSE;
1776:                        } else {
1777:                            if (type == PathIterator.SEG_CLOSE) {
1778:                                closeIndex = typeSize;
1779:                            }
1780:                            types[typeSize++] = type;
1781:                        }
1782:                    }
1783:                    xLast = points[pointSize - 2];
1784:                    yLast = points[pointSize - 1];
1785:                }
1786:
1787:                void join(BufferedPath p) {
1788:                    // Skip MOVETO
1789:                    checkBuf(p.typeSize - 1, p.pointSize - 2);
1790:                    System.arraycopy(p.points, 2, points, pointSize,
1791:                            p.pointSize - 2);
1792:                    System.arraycopy(p.types, 1, types, typeSize,
1793:                            p.typeSize - 1);
1794:                    pointSize += p.pointSize - 2;
1795:                    typeSize += p.typeSize - 1;
1796:                    xLast = points[pointSize - 2];
1797:                    yLast = points[pointSize - 1];
1798:                }
1799:
1800:                void combine(BufferedPath p) {
1801:                    checkBuf(p.typeSize - 1, p.pointSize - 2);
1802:                    // Skip last point, beacause it's the first point of the second path
1803:                    for (int i = p.pointSize - 4; i >= 0; i -= 2) {
1804:                        points[pointSize++] = p.points[i + 0];
1805:                        points[pointSize++] = p.points[i + 1];
1806:                    }
1807:                    // Skip first type, beacuse it's always MOVETO
1808:                    for (int i = p.typeSize - 1; i >= 1; i--) {
1809:                        types[typeSize++] = p.types[i];
1810:                    }
1811:                    xLast = points[pointSize - 2];
1812:                    yLast = points[pointSize - 1];
1813:                }
1814:
1815:                GeneralPath createGeneralPath() {
1816:                    GeneralPath p = new GeneralPath();
1817:                    int j = 0;
1818:                    for (int i = 0; i < typeSize; i++) {
1819:                        int type = types[i];
1820:                        switch (type) {
1821:                        case PathIterator.SEG_MOVETO:
1822:                            p.moveTo(points[j], points[j + 1]);
1823:                            break;
1824:                        case PathIterator.SEG_LINETO:
1825:                            p.lineTo(points[j], points[j + 1]);
1826:                            break;
1827:                        case PathIterator.SEG_QUADTO:
1828:                            p.quadTo(points[j], points[j + 1], points[j + 2],
1829:                                    points[j + 3]);
1830:                            break;
1831:                        case PathIterator.SEG_CUBICTO:
1832:                            p
1833:                                    .curveTo(points[j], points[j + 1],
1834:                                            points[j + 2], points[j + 3],
1835:                                            points[j + 4], points[j + 5]);
1836:                            break;
1837:                        case PathIterator.SEG_CLOSE:
1838:                            p.closePath();
1839:                            break;
1840:                        }
1841:                        j += pointShift[type];
1842:                    }
1843:                    return p;
1844:                }
1845:
1846:            }
1847:
1848:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.