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 PathStore extends PathSink implements PathSource {
029:
030: private static final int DEFAULT_INITIAL_CAPACITY = 1000;
031:
032: // M - moveTo II
033: // m - rel moveTo ss
034: // n - rel moveTo bb
035:
036: // H - horiz moveTo I
037: // h - rel horiz moveTo s
038: // i - rel horiz moveTo b
039:
040: // V - vert moveTo I
041: // v - rel vert moveTo s
042: // w - rel vert moveTo b
043:
044: // L - abs lineTo II
045: // l - rel lineTo ss
046: // k - rel lineTo bb
047:
048: // Q - abs quadTo IIII
049: // q - rel quadTo ssss
050: // r - rel quadTo bbbb
051:
052: // T - abs short quadTo II
053: // t - rel short quadTo ss
054: // u - rel short quadTo bb
055:
056: // C - abs cubicTo IIIIII
057: // c - rel cubicTo ssssss
058: // d - rel cubicTo bbbbbb
059:
060: // S - abs short cubicTo IIII
061: // s - rel short cubicTo ssss
062: // p - rel short cubicTo bbbb
063:
064: // z - close
065: // Z - close and end
066:
067: static final byte MOVE_TO = (byte) 'M';
068: static final byte LINE_JOIN = (byte) 'J';
069: static final byte ABS_LINE_TO = (byte) 'L';
070: static final byte REL_LINE_TO_SHORT = (byte) 'l';
071: static final byte ABS_QUAD_TO = (byte) 'Q';
072: static final byte REL_QUAD_TO_SHORT = (byte) 'q';
073: static final byte CUBIC_TO = (byte) 'C';
074: static final byte CLOSE = (byte) 'z';
075: static final byte END = (byte) 'E';
076:
077: int numSegments = 0;
078:
079: int[] pathData;
080: int dindex = 0;
081:
082: byte[] pathTypes;
083: int tindex = 0;
084:
085: int x0, y0, sx0, sy0, xp, yp;
086:
087: public PathStore() {
088: this (DEFAULT_INITIAL_CAPACITY);
089: }
090:
091: public PathStore(int initialCapacity) {
092: this .pathData = new int[initialCapacity];
093: this .pathTypes = new byte[initialCapacity];
094: }
095:
096: private void ensureCapacity(int elements) {
097: if (dindex + elements > pathData.length) {
098: int[] newPathData = new int[pathData.length + 512];
099: System.arraycopy(pathData, 0, newPathData, 0,
100: pathData.length);
101: this .pathData = newPathData;
102: }
103:
104: if (tindex + 1 > pathTypes.length) {
105: byte[] newPathTypes = new byte[pathTypes.length + 512];
106: System.arraycopy(pathTypes, 0, newPathTypes, 0,
107: pathTypes.length);
108: this .pathTypes = newPathTypes;
109: }
110: }
111:
112: private static boolean isShort(int x) {
113: return x >= -32768 && x <= 32767;
114: }
115:
116: public void moveTo(int x0, int y0) {
117: ensureCapacity(2);
118: pathTypes[tindex++] = MOVE_TO;
119: pathData[dindex++] = x0;
120: pathData[dindex++] = y0;
121:
122: this .sx0 = this .x0 = x0;
123: this .sy0 = this .y0 = y0;
124: }
125:
126: private int packShorts(int hi, int lo) {
127: return (hi << 16) | (lo & 0xffff);
128: }
129:
130: public void lineJoin() {
131: ensureCapacity(0);
132: pathTypes[tindex++] = LINE_JOIN;
133: }
134:
135: public void lineTo(int x1, int y1) {
136: int dx = x1 - x0;
137: int dy = y1 - y0;
138: if (isShort(dx) && isShort(dy)) {
139: ensureCapacity(1);
140: pathTypes[tindex++] = REL_LINE_TO_SHORT;
141: pathData[dindex++] = packShorts(dx, dy);
142: } else {
143: ensureCapacity(2);
144: pathTypes[tindex++] = ABS_LINE_TO;
145: pathData[dindex++] = x1;
146: pathData[dindex++] = y1;
147: }
148:
149: this .x0 = x1;
150: this .y0 = y1;
151: }
152:
153: public void quadTo(int x1, int y1, int x2, int y2) {
154: int dx1 = x1 - x0;
155: int dy1 = y1 - y0;
156: int dx2 = x2 - x0;
157: int dy2 = y2 - y0;
158:
159: if (isShort(dx1) && isShort(dy1) && isShort(dx2)
160: && isShort(dy2)) {
161: ensureCapacity(2);
162: pathTypes[tindex++] = REL_QUAD_TO_SHORT;
163: pathData[dindex++] = packShorts(dx1, dy1);
164: pathData[dindex++] = packShorts(dx2, dy2);
165: } else {
166: ensureCapacity(4);
167: pathTypes[tindex++] = ABS_QUAD_TO;
168: pathData[dindex++] = x1;
169: pathData[dindex++] = y1;
170: pathData[dindex++] = x2;
171: pathData[dindex++] = y2;
172: }
173:
174: this .xp = x1;
175: this .yp = y1;
176: this .x0 = x2;
177: this .y0 = y2;
178: }
179:
180: public void cubicTo(int x1, int y1, int x2, int y2, int x3, int y3) {
181: ensureCapacity(6);
182: pathTypes[tindex++] = CUBIC_TO;
183: pathData[dindex++] = x1;
184: pathData[dindex++] = y1;
185: pathData[dindex++] = x2;
186: pathData[dindex++] = y2;
187: pathData[dindex++] = x3;
188: pathData[dindex++] = y3;
189:
190: this .x0 = x3;
191: this .y0 = y3;
192: }
193:
194: public void close() {
195: ensureCapacity(0);
196: pathTypes[tindex++] = CLOSE;
197:
198: this .x0 = sx0;
199: this .y0 = sy0;
200: }
201:
202: public void end() {
203: ensureCapacity(0);
204: pathTypes[tindex++] = END;
205:
206: this .x0 = 0;
207: this .y0 = 0;
208: }
209:
210: public void produce(PathSink consumer) {
211: int tidx = 0;
212: int didx = 0;
213: int x0 = 0, y0 = 0, sx0 = 0, sy0 = 0;
214:
215: while (tidx < tindex) {
216: switch (pathTypes[tidx++]) {
217: case MOVE_TO:
218: sx0 = x0 = pathData[didx++];
219: sy0 = y0 = pathData[didx++];
220: consumer.moveTo(x0, y0);
221: break;
222:
223: case LINE_JOIN:
224: consumer.lineJoin();
225: break;
226:
227: case ABS_LINE_TO:
228: consumer.lineTo(x0 = pathData[didx++],
229: y0 = pathData[didx++]);
230: break;
231:
232: case REL_LINE_TO_SHORT:
233: int dxdy = pathData[didx++];
234: x0 += dxdy >> 16;
235: y0 += (dxdy << 16) >> 16;
236: consumer.lineTo(x0, y0);
237: break;
238:
239: case ABS_QUAD_TO:
240: consumer.quadTo(pathData[didx++], pathData[didx++],
241: x0 = pathData[didx++], y0 = pathData[didx++]);
242: break;
243:
244: case REL_QUAD_TO_SHORT:
245: int dxdy1 = pathData[didx++];
246: int dxdy2 = pathData[didx++];
247: int x1 = x0 + (dxdy1 >> 16);
248: int y1 = y0 + ((dxdy1 << 16) >> 16);
249: int x2 = x0 + (dxdy2 >> 16);
250: int y2 = y0 + ((dxdy2 << 16) >> 16);
251: consumer.quadTo(x1, y1, x2, y2);
252: x0 = x2;
253: y0 = y2;
254: break;
255:
256: case CUBIC_TO:
257: consumer.cubicTo(pathData[didx++], pathData[didx++],
258: pathData[didx++], pathData[didx++],
259: x0 = pathData[didx++], y0 = pathData[didx++]);
260: break;
261:
262: case CLOSE:
263: consumer.close();
264: x0 = sx0;
265: y0 = sy0;
266: break;
267:
268: case END:
269: consumer.end();
270: x0 = 0;
271: y0 = 0;
272: break;
273: }
274: }
275: }
276: }
|