001: /**
002: * Page.java
003: *
004: Copyright (c) 2007, Innovatics Inc.
005:
006: All rights reserved.
007:
008: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
009:
010: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
011: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
012:
013: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
014: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
015: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
016: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
017: CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
018: EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
019: PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
020: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
021: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
022: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
023: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
024: */package com.pdfjet;
025:
026: import java.lang.*;
027: import java.io.*;
028: import java.text.*;
029: import java.util.*;
030: import java.util.zip.*;
031:
032: //>>>>pdfjet {
033: public class Page {
034:
035: protected ByteArrayOutputStream buf = null;
036: protected String writingMode = "1 0 0 1 ";
037: protected int renderingMode = 0;
038: protected double width = 0.0;
039: protected double height = 0.0;
040: protected List<Annotation> annots = null;
041: protected PDF pdf = null;
042:
043: private double[] pen_color = { 0.0, 0.0, 0.0 };
044: private double[] brush_color = { 0.0, 0.0, 0.0 };
045: private double pen_width = 0.0;
046: private String line_pattern = "[] 0";
047:
048: public Page(PDF pdf, double[] pageSize) throws Exception {
049: this .pdf = pdf;
050: annots = new ArrayList<Annotation>();
051: width = pageSize[0];
052: height = pageSize[1];
053: buf = new ByteArrayOutputStream(8192);
054: pdf.pages.add(this );
055: }
056:
057: protected void drawLine(double x1, double y1, double x2, double y2)
058: throws IOException {
059: moveTo(x1, y1);
060: lineTo(x2, y2);
061: strokePath();
062: }
063:
064: protected void drawString(Font font, String str, double x, double y)
065: throws IOException {
066: pdf.append(buf, "BT\n");
067: pdf.append(buf, "/F");
068: pdf.append(buf, font.objNumber);
069: pdf.append(buf, ' ');
070: pdf.append(buf, font.size);
071: pdf.append(buf, " Tf\n");
072: if (renderingMode != 0) {
073: pdf.append(buf, renderingMode);
074: pdf.append(buf, " Tr\n");
075: }
076: pdf.append(buf, writingMode);
077: pdf.append(buf, x);
078: pdf.append(buf, ' ');
079: pdf.append(buf, height - y);
080: pdf.append(buf, " Tm\n");
081: pdf.addText(buf, str, font);
082: pdf.append(buf, "ET\n");
083: }
084:
085: /**
086: * Set color for stroking operations
087: */
088: protected void setPenColor(double r, double g, double b)
089: throws IOException {
090: if (pen_color[0] == r && pen_color[1] == g && pen_color[2] == b) {
091: return;
092: } else {
093: pen_color[0] = r;
094: pen_color[1] = g;
095: pen_color[2] = b;
096: }
097: pdf.append(buf, r);
098: pdf.append(buf, ' ');
099: pdf.append(buf, g);
100: pdf.append(buf, ' ');
101: pdf.append(buf, b);
102: pdf.append(buf, " RG\n");
103: }
104:
105: /**
106: * Set color for nonstroking operations
107: */
108: protected void setBrushColor(double r, double g, double b)
109: throws IOException {
110: if (brush_color[0] == r && brush_color[1] == g
111: && brush_color[2] == b) {
112: return;
113: } else {
114: brush_color[0] = r;
115: brush_color[1] = g;
116: brush_color[2] = b;
117: }
118: pdf.append(buf, r);
119: pdf.append(buf, ' ');
120: pdf.append(buf, g);
121: pdf.append(buf, ' ');
122: pdf.append(buf, b);
123: pdf.append(buf, " rg\n");
124: }
125:
126: protected void setDefaultLineWidth() throws IOException {
127: pdf.append(buf, 0.0);
128: pdf.append(buf, " w\n");
129: }
130:
131: protected void setLinePattern(String pattern) throws IOException {
132: if (pattern.equals(line_pattern)) {
133: return;
134: } else {
135: line_pattern = pattern;
136: }
137: if (pattern.startsWith("[")) {
138: pdf.append(buf, pattern);
139: } else {
140: int dash = 0;
141: int space = 0;
142: for (int i = 0; i < pattern.length(); i++) {
143: if (pattern.charAt(i) == '-') {
144: dash++;
145: } else {
146: space++;
147: }
148: }
149: if (dash == 0 || space == 0) {
150: pdf.append(buf, "[] 0");
151: } else {
152: pdf.append(buf, "[" + dash / 2 + " " + space / 2
153: + "] 0");
154: }
155: }
156: pdf.append(buf, " d\n");
157: }
158:
159: protected void setDefaultLinePattern() throws IOException {
160: pdf.append(buf, "[] 0");
161: pdf.append(buf, " d\n");
162: }
163:
164: protected void setPenWidth(double width) throws IOException {
165: if (width == pen_width) {
166: return;
167: } else {
168: pen_width = width;
169: }
170: pdf.append(buf, width);
171: pdf.append(buf, " w\n");
172: }
173:
174: protected void moveTo(double x, double y) throws IOException {
175: pdf.append(buf, x);
176: pdf.append(buf, ' ');
177: pdf.append(buf, height - y);
178: pdf.append(buf, " m\n");
179: }
180:
181: protected void lineTo(double x, double y) throws IOException {
182: pdf.append(buf, x);
183: pdf.append(buf, ' ');
184: pdf.append(buf, height - y);
185: pdf.append(buf, " l\n");
186: }
187:
188: protected void closePath() throws IOException {
189: pdf.append(buf, "h\n");
190: }
191:
192: protected void strokePath() throws IOException {
193: pdf.append(buf, "S\n");
194: }
195:
196: protected void fillPath() throws IOException {
197: pdf.append(buf, "f\n");
198: }
199:
200: protected void drawPath(List<Point> list, char operand)
201: throws Exception {
202: if (list.size() < 2) {
203: throw new Exception(
204: "The Path object must contain at least 2 points");
205: }
206: Point point = list.get(0);
207: moveTo(point.x, point.y);
208: int numOfCurvePoints = 0;
209: for (int i = 1; i < list.size(); i++) {
210: point = list.get(i);
211: if (point.isCurvePoint) {
212: pdf.append(buf, point.x);
213: pdf.append(buf, ' ');
214: pdf.append(buf, height - point.y);
215: if (numOfCurvePoints < 2) {
216: pdf.append(buf, ' ');
217: numOfCurvePoints++;
218: } else {
219: pdf.append(buf, " c\n");
220: numOfCurvePoints = 0;
221: }
222: } else {
223: lineTo(point.x, point.y);
224: }
225: }
226: if (numOfCurvePoints != 0) {
227: throw new Exception(
228: "Invalid number of curve points in the Path object");
229: }
230: pdf.append(buf, operand);
231: pdf.append(buf, '\n');
232: }
233:
234: protected void drawBezierCurve(List<Point> list, char operand)
235: throws IOException {
236: Point point = list.get(0);
237: moveTo(point.x, point.y);
238: for (int i = 1; i < list.size(); i++) {
239: point = list.get(i);
240: pdf.append(buf, point.x);
241: pdf.append(buf, ' ');
242: pdf.append(buf, height - point.y);
243: if (i % 3 == 0) {
244: pdf.append(buf, " c\n");
245: } else {
246: pdf.append(buf, ' ');
247: }
248: }
249:
250: pdf.append(buf, operand);
251: pdf.append(buf, '\n');
252: }
253:
254: protected void drawCircle(double x, double y, double r, char operand)
255: throws Exception {
256: List<Point> list = new ArrayList<Point>();
257:
258: Point point = new Point();
259: point.x = x;
260: point.y = y - r;
261: list.add(point); // Starting point
262:
263: point = new Point();
264: point.x = x + 0.55 * r;
265: point.y = y - r;
266: list.add(point);
267: point = new Point();
268: point.x = x + r;
269: point.y = y - 0.55 * r;
270: list.add(point);
271: point = new Point();
272: point.x = x + r;
273: point.y = y;
274: list.add(point);
275:
276: point = new Point();
277: point.x = x + r;
278: point.y = y + 0.55 * r;
279: list.add(point);
280: point = new Point();
281: point.x = x + 0.55 * r;
282: point.y = y + r;
283: list.add(point);
284: point = new Point();
285: point.x = x;
286: point.y = y + r;
287: list.add(point);
288:
289: point = new Point();
290: point.x = x - 0.55 * r;
291: point.y = y + r;
292: list.add(point);
293: point = new Point();
294: point.x = x - r;
295: point.y = y + 0.55 * r;
296: list.add(point);
297: point = new Point();
298: point.x = x - r;
299: point.y = y;
300: list.add(point);
301:
302: point = new Point();
303: point.x = x - r;
304: point.y = y - 0.55 * r;
305: list.add(point);
306: point = new Point();
307: point.x = x - 0.55 * r;
308: point.y = y - r;
309: list.add(point);
310: point = new Point();
311: point.x = x;
312: point.y = y - r;
313: list.add(point);
314:
315: drawBezierCurve(list, operand);
316: }
317:
318: protected void drawPoint(Point p) throws Exception {
319: if (p.shape == Point.INVISIBLE)
320: return;
321:
322: List<Point> list = null;
323: Point point = null;
324:
325: if (p.shape == Point.CIRCLE) {
326: if (p.fill_shape) {
327: drawCircle(p.x, p.y, p.r, 'f');
328: } else {
329: drawCircle(p.x, p.y, p.r, 'S');
330: }
331: } else if (p.shape == Point.DIAMOND) {
332: list = new ArrayList<Point>();
333: point = new Point();
334: point.x = p.x;
335: point.y = p.y - p.r;
336: list.add(point);
337: point = new Point();
338: point.x = p.x + p.r;
339: point.y = p.y;
340: list.add(point);
341: point = new Point();
342: point.x = p.x;
343: point.y = p.y + p.r;
344: list.add(point);
345: point = new Point();
346: point.x = p.x - p.r;
347: point.y = p.y;
348: list.add(point);
349: if (p.fill_shape) {
350: drawPath(list, 'f');
351: } else {
352: drawPath(list, 's');
353: }
354: } else if (p.shape == Point.BOX) {
355: list = new ArrayList<Point>();
356: point = new Point();
357: point.x = p.x - p.r;
358: point.y = p.y - p.r;
359: list.add(point);
360: point = new Point();
361: point.x = p.x + p.r;
362: point.y = p.y - p.r;
363: list.add(point);
364: point = new Point();
365: point.x = p.x + p.r;
366: point.y = p.y + p.r;
367: list.add(point);
368: point = new Point();
369: point.x = p.x - p.r;
370: point.y = p.y + p.r;
371: list.add(point);
372: if (p.fill_shape) {
373: drawPath(list, 'f');
374: } else {
375: drawPath(list, 's');
376: }
377: } else if (p.shape == Point.PLUS) {
378: drawLine(p.x - p.r, p.y, p.x + p.r, p.y);
379: drawLine(p.x, p.y - p.r, p.x, p.y + p.r);
380: } else if (p.shape == Point.UP_ARROW) {
381: list = new ArrayList<Point>();
382: point = new Point();
383: point.x = p.x;
384: point.y = p.y - p.r;
385: list.add(point);
386: point = new Point();
387: point.x = p.x + p.r;
388: point.y = p.y + p.r;
389: list.add(point);
390: point = new Point();
391: point.x = p.x - p.r;
392: point.y = p.y + p.r;
393: list.add(point);
394: if (p.fill_shape) {
395: drawPath(list, 'f');
396: } else {
397: drawPath(list, 's');
398: }
399: } else if (p.shape == Point.DOWN_ARROW) {
400: list = new ArrayList<Point>();
401: point = new Point();
402: point.x = p.x - p.r;
403: point.y = p.y - p.r;
404: list.add(point);
405: point = new Point();
406: point.x = p.x + p.r;
407: point.y = p.y - p.r;
408: list.add(point);
409: point = new Point();
410: point.x = p.x;
411: point.y = p.y + p.r;
412: list.add(point);
413: if (p.fill_shape) {
414: drawPath(list, 'f');
415: } else {
416: drawPath(list, 's');
417: }
418: } else if (p.shape == Point.LEFT_ARROW) {
419: list = new ArrayList<Point>();
420: point = new Point();
421: point.x = p.x + p.r;
422: point.y = p.y + p.r;
423: list.add(point);
424: point = new Point();
425: point.x = p.x - p.r;
426: point.y = p.y;
427: list.add(point);
428: point = new Point();
429: point.x = p.x + p.r;
430: point.y = p.y - p.r;
431: list.add(point);
432: if (p.fill_shape) {
433: drawPath(list, 'f');
434: } else {
435: drawPath(list, 's');
436: }
437: } else if (p.shape == Point.RIGHT_ARROW) {
438: list = new ArrayList<Point>();
439: point = new Point();
440: point.x = p.x - p.r;
441: point.y = p.y - p.r;
442: list.add(point);
443: point = new Point();
444: point.x = p.x + p.r;
445: point.y = p.y;
446: list.add(point);
447: point = new Point();
448: point.x = p.x - p.r;
449: point.y = p.y + p.r;
450: list.add(point);
451: if (p.fill_shape) {
452: drawPath(list, 'f');
453: } else {
454: drawPath(list, 's');
455: }
456: } else if (p.shape == Point.H_DASH) {
457: drawLine(p.x - p.r, p.y, p.x + p.r, p.y);
458: } else if (p.shape == Point.V_DASH) {
459: drawLine(p.x, p.y - p.r, p.x, p.y + p.r);
460: } else if (p.shape == Point.X_MARK) {
461: drawLine(p.x - p.r, p.y - p.r, p.x + p.r, p.y + p.r);
462: drawLine(p.x - p.r, p.y + p.r, p.x + p.r, p.y - p.r);
463: } else if (p.shape == Point.MULTIPLY) {
464: drawLine(p.x - p.r, p.y - p.r, p.x + p.r, p.y + p.r);
465: drawLine(p.x - p.r, p.y + p.r, p.x + p.r, p.y - p.r);
466: drawLine(p.x - p.r, p.y, p.x + p.r, p.y);
467: drawLine(p.x, p.y - p.r, p.x, p.y + p.r);
468: } else if (p.shape == Point.STAR) {
469: double angle = Math.PI / 10;
470: double sin18 = Math.sin(angle);
471: double cos18 = Math.cos(angle);
472: double a = p.r * cos18;
473: double b = p.r * sin18;
474: double c = 2 * a * sin18;
475: double d = 2 * a * cos18 - p.r;
476: list = new ArrayList<Point>();
477: point = new Point();
478: point.x = p.x;
479: point.y = p.y - p.r;
480: list.add(point);
481: point = new Point();
482: point.x = p.x + c;
483: point.y = p.y + d;
484: list.add(point);
485: point = new Point();
486: point.x = p.x - a;
487: point.y = p.y - b;
488: list.add(point);
489: point = new Point();
490: point.x = p.x + a;
491: point.y = p.y - b;
492: list.add(point);
493: point = new Point();
494: point.x = p.x - c;
495: point.y = p.y + d;
496: list.add(point);
497: if (p.fill_shape) {
498: drawPath(list, 'f');
499: } else {
500: drawPath(list, 's');
501: }
502: }
503: }
504:
505: protected void setTextRenderingMode(int mode) throws Exception {
506: if (mode == 0 || mode == 1 || mode == 2 || mode == 3
507: || mode == 4 || mode == 5 || mode == 6 || mode == 7) {
508: this .renderingMode = mode;
509: } else {
510: throw new Exception("Invalid text rendering mode: " + mode);
511: }
512: }
513:
514: protected void setTextDirection(int degrees) throws Exception {
515: if (degrees > 360)
516: degrees %= 360;
517: if (degrees == 0) {
518: writingMode = "1 0 0 1 ";
519: } else if (degrees == 90) {
520: writingMode = "0 1 -1 0 ";
521: } else if (degrees == 180) {
522: writingMode = "-1 0 0 -1 ";
523: } else if (degrees == 270) {
524: writingMode = "0 -1 1 0 ";
525: } else if (degrees == 360) {
526: writingMode = "1 0 0 1 ";
527: } else {
528: double sinOfAngle = Math.sin(degrees * (Math.PI / 180));
529: double cosOfAngle = Math.cos(degrees * (Math.PI / 180));
530: StringBuilder sb = new StringBuilder();
531: sb.append(cosOfAngle);
532: sb.append(' ');
533: sb.append(sinOfAngle);
534: sb.append(' ');
535: sb.append(-sinOfAngle);
536: sb.append(' ');
537: sb.append(cosOfAngle);
538: sb.append(' ');
539: writingMode = sb.toString();
540: }
541: }
542:
543: } // End of Page.java
544: //>>>>}
|