KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > codec > postscript > PAContext


1 /*
2  * Copyright 1998 by Sun Microsystems, Inc.,
3  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
4  * All rights reserved.
5  *
6  * This software is the confidential and proprietary information
7  * of Sun Microsystems, Inc. ("Confidential Information"). You
8  * shall not disclose such Confidential Information and shall use
9  * it only in accordance with the terms of the license agreement
10  * you entered into with Sun.
11  */

12
13 package com.lowagie.text.pdf.codec.postscript;
14
15 import java.lang.*;
16 import java.lang.reflect.*;
17 import java.util.*;
18 import java.io.*;
19 import java.awt.*;
20 import java.awt.geom.*;
21 import java.awt.color.*;
22 import java.awt.font.*;
23
24 public class PAContext
25     extends Object {
26
27   public PAPencil pencil;
28   public Stack dictionaries;
29   public Stack operands;
30   public PAEngine engine;
31   PAParser poorscript = null;
32   protected Random randomNumberGenerator;
33
34   protected Object lastUnknownIdentifier;
35
36   public PAContext(Component component) {
37     this(new PAPencil(component));
38   }
39
40   public PAContext(Graphics2D g, Dimension size) {
41     this(new PAPencil(g, size));
42   }
43
44   public PAContext(PAPencil pencil) {
45     super();
46     this.pencil = pencil;
47     this.dictionaries = new Stack();
48     this.operands = new Stack();
49     this.engine = new PAEngine(this);
50     this.dictionaries.push(this.constructSystemDict());
51     this.dictionaries.push(this.constructGlobalDict());
52     this.dictionaries.push(new HashMap());
53     this.randomNumberGenerator = new Random();
54     this.lastUnknownIdentifier = null;
55   }
56
57   public void draw(InputStream inputStream) throws PainterException {
58     try {
59
60         poorscript = new PAParser(inputStream);
61
62       poorscript.parse(this);
63      // pencil.graphics.dispose();
64
}
65     catch (ParseException e) {
66       e.printStackTrace();
67       throw new PainterException(e.toString());
68     }
69   }
70
71   public Object getLastUnknownIdentifier() {
72     return this.lastUnknownIdentifier;
73   }
74
75   public double[] popNumberOperands(int n) throws PainterException {
76     double[] result = new double[n];
77     Object objectValue;
78     double doubleValue;
79
80     for (int i = n - 1; i >= 0; i--) {
81       try {
82         objectValue = this.operands.pop();
83       }
84       catch (EmptyStackException e) {
85         throw new PainterException("Operand stack is empty");
86       }
87       if (objectValue instanceof Number) {
88         doubleValue = ( (Number) objectValue).doubleValue();
89       }
90       else {
91         throw new PainterException("Number expected on operand stack");
92       }
93       result[i] = doubleValue;
94     }
95     return result;
96   }
97
98   public Object[] popOperands(int n) throws PainterException {
99     Object[] result = new Object[n];
100     Object objectValue;
101
102     for (int i = n - 1; i >= 0; i--) {
103       try {
104         objectValue = this.operands.pop();
105       }
106       catch (EmptyStackException e) {
107         throw new PainterException("Operand stack is empty");
108       }
109       result[i] = objectValue;
110     }
111     return result;
112   }
113
114   public Object peekOperand() throws PainterException {
115     Object objectValue;
116
117     try {
118       objectValue = this.operands.peek();
119     }
120     catch (EmptyStackException e) {
121       throw new PainterException("Operand stack is empty");
122     }
123     return objectValue;
124   }
125
126   public Object findIdentifier(Object identifier) {
127     Object result = null;
128     int i, n;
129
130     n = this.dictionaries.size();
131     i = n - 1;
132     while (i >= 0 && result == null) {
133       HashMap dictionary = (HashMap)this.dictionaries.elementAt(i);
134       result = dictionary.get(identifier);
135       i--;
136     }
137     if (result == null) {
138       this.lastUnknownIdentifier = identifier;
139     }
140     return result;
141   }
142
143   public Object findDictionary(Object identifier) {
144     Object result = null;
145     HashMap dictionary = null;
146     int i, n;
147
148     n = this.dictionaries.size();
149     i = n - 1;
150     while (i >= 0 && result == null) {
151       dictionary = (HashMap)this.dictionaries.elementAt(i);
152       result = dictionary.get(identifier);
153       i--;
154     }
155     if (result == null) {
156       return result;
157     }
158     else {
159       return dictionary;
160     }
161   }
162
163   public void collectArray() throws PainterException {
164     ArrayList result;
165     Object objectValue;
166     int i, n;
167     boolean found = false;
168
169     n = this.operands.size();
170     for (i = n - 1; i >= 0; i--) {
171       objectValue = this.operands.elementAt(i);
172       if (objectValue instanceof PAToken &&
173           ( (PAToken) objectValue).type == PAToken.START_ARRAY) {
174         found = true;
175         break;
176       }
177     }
178     if (!found) {
179       throw new PainterException("No array was started");
180     }
181     result = new ArrayList(n - i - 1);
182     for (int j = 0; j < n - i - 1; j++) {
183       result.add(null);
184     }
185     for (int j = n - 1; j > i; j--) {
186       try {
187         objectValue = this.operands.pop();
188       }
189       catch (EmptyStackException e) {
190         throw new PainterException("Operand stack is empty");
191       }
192       result.set(j - i - 1, objectValue);
193     }
194     try {
195       this.operands.pop(); // the start array mark itself
196
}
197     catch (EmptyStackException e) {
198       throw new PainterException("Operand stack is empty");
199     }
200     this.operands.push(result);
201   }
202
203   protected HashMap constructGlobalDict() {
204     HashMap globalDict = new HashMap();
205
206     return globalDict;
207   }
208
209   protected HashMap constructSystemDict() {
210     HashMap systemDict = new HashMap();
211
212     // newpath
213
systemDict.put("newpath", new PACommand() {
214       public void execute(PAContext context) throws PainterException {
215         context.pencil.newpath();
216       }
217     });
218
219     // moveto
220
systemDict.put("moveto", new PACommand() {
221       public void execute(PAContext context) throws PainterException {
222         double data[];
223
224         data = context.popNumberOperands(2);
225         context.pencil.moveto(data[0], data[1]);
226       }
227     });
228
229     // rmoveto
230
systemDict.put("rmoveto", new PACommand() {
231       public void execute(PAContext context) throws PainterException {
232         double data[];
233
234         data = context.popNumberOperands(2);
235         context.pencil.rmoveto(data[0], data[1]);
236       }
237     });
238
239     // lineto
240
systemDict.put("lineto", new PACommand() {
241       public void execute(PAContext context) throws PainterException {
242         double data[];
243
244         data = context.popNumberOperands(2);
245         context.pencil.lineto(data[0], data[1]);
246       }
247     });
248
249     // rlineto
250
systemDict.put("rlineto", new PACommand() {
251       public void execute(PAContext context) throws PainterException {
252         double data[];
253
254         data = context.popNumberOperands(2);
255         context.pencil.rlineto(data[0], data[1]);
256       }
257     });
258
259     // arc
260
systemDict.put("arc", new PACommand() {
261       public void execute(PAContext context) throws PainterException {
262         double data[];
263
264         data = context.popNumberOperands(5);
265         context.pencil.arc(data[0], data[1], data[2], data[3], data[4]);
266       }
267     });
268
269     // arcn
270
systemDict.put("arcn", new PACommand() {
271       public void execute(PAContext context) throws PainterException {
272         double data[];
273
274         data = context.popNumberOperands(5);
275         context.pencil.arcn(data[0], data[1], data[2], data[3], data[4]);
276       }
277     });
278
279     // curveto
280
systemDict.put("curveto", new PACommand() {
281       public void execute(PAContext context) throws PainterException {
282         double data[];
283
284         data = context.popNumberOperands(6);
285         context.pencil.curveto(data[0], data[1], data[2], data[3], data[4],
286                                data[5]);
287       }
288     });
289
290     // rcurveto
291
systemDict.put("rcurveto", new PACommand() {
292       public void execute(PAContext context) throws PainterException {
293         double data[];
294
295         data = context.popNumberOperands(6);
296         context.pencil.rcurveto(data[0], data[1], data[2], data[3], data[4],
297                                 data[5]);
298       }
299     });
300
301     // closepath
302
systemDict.put("closepath", new PACommand() {
303       public void execute(PAContext context) throws PainterException {
304         context.pencil.closepath();
305       }
306     });
307
308     // gsave
309
systemDict.put("gsave", new PACommand() {
310       public void execute(PAContext context) throws PainterException {
311         context.pencil.gsave();
312       }
313     });
314
315     // grestore
316
systemDict.put("grestore", new PACommand() {
317       public void execute(PAContext context) throws PainterException {
318         context.pencil.grestore();
319       }
320     });
321
322     // translate
323
systemDict.put("translate", new PACommand() {
324       public void execute(PAContext context) throws PainterException {
325         if (context.peekOperand() instanceof Number) {
326           double data[];
327           AffineTransform at = new AffineTransform();
328           AffineTransform ctm = context.pencil.graphics.getTransform();
329
330           data = context.popNumberOperands(2);
331           at.translate(data[0], data[1]);
332           ctm.concatenate(at);
333           context.pencil.graphics.setTransform(ctm);
334         }
335         else {
336           Object data[];
337
338           data = context.popOperands(3);
339           if (! (data[0] instanceof Number)) {
340             throw new PainterException("wrong arguments");
341           }
342           if (! (data[1] instanceof Number)) {
343             throw new PainterException("wrong arguments");
344           }
345           if (! (data[2] instanceof ArrayList)) {
346             throw new PainterException("wrong arguments");
347           }
348
349           ArrayList array = (ArrayList) data[2];
350
351           if (! (array.size() == 6)) {
352             throw new PainterException("wrong arguments");
353           }
354
355           AffineTransform at = new AffineTransform();
356
357           at.translate( ( (Number) data[0]).doubleValue(),
358                        ( (Number) data[1]).doubleValue());
359
360           double[] entries = new double[6];
361
362           at.getMatrix(entries);
363
364           for (int i = 0; i < 6; i++) {
365             array.set(i, new Double(entries[i]));
366           }
367           context.operands.push(array);
368         }
369       }
370     });
371
372     // rotate
373
systemDict.put("rotate", new PACommand() {
374       public void execute(PAContext context) throws PainterException {
375         if (context.peekOperand() instanceof Number) {
376           double data[];
377           AffineTransform at = new AffineTransform();
378           AffineTransform ctm = context.pencil.graphics.getTransform();
379
380           data = context.popNumberOperands(1);
381           at.rotate(data[0] * Math.PI / 180.0d);
382           ctm.concatenate(at);
383           context.pencil.graphics.setTransform(ctm);
384         }
385         else {
386           Object data[];
387           AffineTransform at = new AffineTransform();
388
389           data = context.popOperands(2);
390           if (! (data[0] instanceof Number)) {
391             throw new PainterException("wrong arguments");
392           }
393           if (! (data[1] instanceof ArrayList)) {
394             throw new PainterException("wrong arguments");
395           }
396
397           ArrayList array = (ArrayList) data[1];
398
399           if (! (array.size() == 6)) {
400             throw new PainterException("wrong arguments");
401           }
402
403           at.rotate( ( (Number) data[0]).doubleValue());
404
405           double[] entries = new double[6];
406
407           at.getMatrix(entries);
408
409           for (int i = 0; i < 6; i++) {
410             array.set(i, new Double(entries[i]));
411           }
412           context.operands.push(array);
413         }
414       }
415     });
416
417     // scale
418
systemDict.put("scale", new PACommand() {
419       public void execute(PAContext context) throws PainterException {
420         if (context.peekOperand() instanceof Number) {
421           double data[];
422           AffineTransform at = new AffineTransform();
423           AffineTransform ctm = context.pencil.graphics.getTransform();
424
425           data = context.popNumberOperands(2);
426           at.scale(data[0], data[1]);
427           ctm.concatenate(at);
428           context.pencil.graphics.setTransform(ctm);
429         }
430         else {
431           Object data[];
432
433           data = context.popOperands(3);
434           if (! (data[0] instanceof Number)) {
435             throw new PainterException("wrong arguments");
436           }
437           if (! (data[1] instanceof Number)) {
438             throw new PainterException("wrong arguments");
439           }
440           if (! (data[2] instanceof ArrayList)) {
441             throw new PainterException("wrong arguments");
442           }
443
444           ArrayList array = (ArrayList) data[2];
445
446           double[] entries = new double[6];
447
448           if (! (array.size() == 6)) {
449             throw new PainterException("wrong arguments");
450           }
451
452           entries[0] = ( (Number) data[0]).doubleValue();
453           entries[1] = 0.0d;
454           entries[2] = 0.0d;
455           entries[3] = ( (Number) data[1]).doubleValue();
456           entries[4] = 0.0d;
457           entries[5] = 0.0d;
458
459           for (int i = 0; i < 6; i++) {
460             array.set(i, new Double(entries[i]));
461           }
462           context.operands.push(array);
463         }
464       }
465     });
466
467     // stroke
468
systemDict.put("stroke", new PACommand() {
469       public void execute(PAContext context) throws PainterException {
470         context.pencil.stroke();
471       }
472     });
473
474     // fill
475
systemDict.put("fill", new PACommand() {
476       public void execute(PAContext context) throws PainterException {
477         context.pencil.fill();
478       }
479     });
480
481     // eofill
482
systemDict.put("eofill", new PACommand() {
483       public void execute(PAContext context) throws PainterException {
484         context.pencil.eofill();
485       }
486     });
487
488     // show
489
systemDict.put("show", new PACommand() {
490       public void execute(PAContext context) throws PainterException {
491         Object data[];
492
493         data = context.popOperands(1);
494         if (! (data[0] instanceof String)) {
495           throw new PainterException("wrong arguments");
496         }
497         context.pencil.show( (String) data[0]);
498       }
499     });
500
501     // stringwidth
502
systemDict.put("stringwidth", new PACommand() {
503       public void execute(PAContext context) throws PainterException {
504         Object data[];
505         float[] result;
506         Font font;
507
508         data = context.popOperands(1);
509         if (! (data[0] instanceof String)) {
510           throw new PainterException("wrong arguments");
511         }
512         font = context.pencil.graphics.getFont();
513         Rectangle2D rect = font.getStringBounds( (String) data[0],
514                                                 context.pencil.graphics.
515                                                 getFontRenderContext());
516         context.operands.push(new Float(rect.getWidth()));
517         context.operands.push(new Float(rect.getHeight()));
518       }
519     });
520
521     // showpage
522
systemDict.put("showpage", new PACommand() {
523       public void execute(PAContext context) throws PainterException {
524         context.pencil.showpage();
525       }
526     });
527
528     // findfont
529
systemDict.put("findfont", new PACommand() {
530       public void execute(PAContext context) throws PainterException {
531         Object data[];
532         PAToken patoken;
533         data = context.popOperands(1);
534         if (! (data[0] instanceof PAToken)) {
535           throw new PainterException("wrong arguments");
536         }
537         patoken = (PAToken) data[0];
538         if (! (patoken.type == PAToken.KEY)) {
539           throw new PainterException("wrong arguments");
540         }
541         context.operands.push(context.pencil.findFont( (String) patoken.value));
542       }
543     });
544
545     // scalefont
546
systemDict.put("scalefont", new PACommand() {
547       public void execute(PAContext context) throws PainterException {
548         Object data[];
549         data = context.popOperands(2);
550         if (! (data[0] instanceof Font)) {
551           throw new PainterException("wrong arguments");
552         }
553         if (! (data[1] instanceof Number)) {
554           throw new PainterException("wrong arguments");
555         }
556         context.operands.push( ( (Font) data[0]).deriveFont( ( (Number) data[1]).
557             floatValue()));
558       }
559     });
560
561     // setfont
562
systemDict.put("setfont", new PACommand() {
563       public void execute(PAContext context) throws PainterException {
564         Object data[];
565         data = context.popOperands(1);
566         if (! (data[0] instanceof Font)) {
567           throw new PainterException("wrong arguments");
568         }
569         context.pencil.graphics.setFont( (Font) data[0]);
570       }
571     });
572
573     // def
574
systemDict.put("def", new PACommand() {
575       public void execute(PAContext context) throws PainterException {
576         Object data[];
577         PAToken patoken;
578         data = context.popOperands(2);
579         if (! (data[0] instanceof PAToken)) {
580           throw new PainterException("wrong arguments");
581         }
582         patoken = (PAToken) data[0];
583         if (! (patoken.type == PAToken.KEY)) {
584           throw new PainterException("wrong arguments");
585         }
586         try {
587           ( (HashMap) context.dictionaries.peek()).put(patoken.value, data[1]);
588         }
589         catch (EmptyStackException e) {
590           throw new PainterException(e.toString());
591         }
592       }
593     });
594
595     // bind
596
systemDict.put("bind", new PACommand() {
597       public void execute(PAContext context) throws PainterException {
598         Object data[];
599         PAToken patoken;
600         data = context.popOperands(1);
601         if (! (data[0] instanceof PAToken)) {
602           throw new PainterException("wrong arguments");
603         }
604         patoken = (PAToken) data[0];
605         if (! (patoken.type == PAToken.PROCEDURE)) {
606           throw new PainterException("wrong arguments");
607         }
608         context.engine.bindProcedure(patoken);
609         context.operands.push(patoken);
610       }
611     });
612
613     // mul
614
systemDict.put("mul", new PACommand() {
615       public void execute(PAContext context) throws PainterException {
616         double data[];
617
618         data = context.popNumberOperands(2);
619         context.operands.push(new Double(data[0] * data[1]));
620       }
621     });
622
623     // div
624
systemDict.put("div", new PACommand() {
625       public void execute(PAContext context) throws PainterException {
626         double data[];
627
628         data = context.popNumberOperands(2);
629         context.operands.push(new Double(data[0] / data[1]));
630       }
631     });
632
633     // mod
634
systemDict.put("mod", new PACommand() {
635       public void execute(PAContext context) throws PainterException {
636         double data[];
637
638         data = context.popNumberOperands(2);
639         int a, b, m;
640         a = (int) data[0];
641         b = (int) data[1];
642         m = a % b;
643         context.operands.push(new Integer(m));
644       }
645     });
646
647     // add
648
systemDict.put("add", new PACommand() {
649       public void execute(PAContext context) throws PainterException {
650         double data[];
651
652         data = context.popNumberOperands(2);
653         context.operands.push(new Double(data[0] + data[1]));
654       }
655     });
656
657     // neg
658
systemDict.put("neg", new PACommand() {
659       public void execute(PAContext context) throws PainterException {
660         double data[];
661
662         data = context.popNumberOperands(1);
663         context.operands.push(new Double( -data[0]));
664       }
665     });
666
667     // sub
668
systemDict.put("sub", new PACommand() {
669       public void execute(PAContext context) throws PainterException {
670         double data[];
671
672         data = context.popNumberOperands(2);
673         context.operands.push(new Double(data[0] - data[1]));
674       }
675     });
676
677     // atan
678
systemDict.put("atan", new PACommand() {
679       public void execute(PAContext context) throws PainterException {
680         double data[];
681
682         data = context.popNumberOperands(2);
683         context.operands.push(new Double(Math.atan2(data[0], data[1])));
684       }
685     });
686
687     // sin
688
systemDict.put("sin", new PACommand() {
689       public void execute(PAContext context) throws PainterException {
690         double data[];
691
692         data = context.popNumberOperands(1);
693         context.operands.push(new Double(Math.sin(data[0] * Math.PI / 180.0)));
694       }
695     });
696
697     // cos
698
systemDict.put("cos", new PACommand() {
699       public void execute(PAContext context) throws PainterException {
700         double data[];
701
702         data = context.popNumberOperands(1);
703         context.operands.push(new Double(Math.cos(data[0] * Math.PI / 180.0)));
704       }
705     });
706
707     // sqrt
708
systemDict.put("sqrt", new PACommand() {
709       public void execute(PAContext context) throws PainterException {
710         double data[];
711
712         data = context.popNumberOperands(1);
713         context.operands.push(new Double(Math.sqrt(data[0])));
714       }
715     });
716
717     // exch
718
systemDict.put("exch", new PACommand() {
719       public void execute(PAContext context) throws PainterException {
720         Object data[];
721
722         data = context.popOperands(2);
723         context.operands.push(data[1]);
724         context.operands.push(data[0]);
725       }
726     });
727
728     // dup
729
systemDict.put("dup", new PACommand() {
730       public void execute(PAContext context) throws PainterException {
731         Object data[];
732
733         data = context.popOperands(1);
734         context.operands.push(data[0]);
735         context.operands.push(data[0]);
736       }
737     });
738
739     // roll
740
systemDict.put("roll", new PACommand() {
741       public void execute(PAContext context) throws PainterException {
742         Object data[];
743         Object rollData[];
744
745         data = context.popOperands(2);
746         if (! (data[0] instanceof Number)) {
747           throw new PainterException("wrong arguments");
748         }
749         if (! (data[1] instanceof Number)) {
750           throw new PainterException("wrong arguments");
751         }
752         int numberOfElements, numberOfPositions, i;
753
754         numberOfElements = ( (Number) data[0]).intValue();
755         numberOfPositions = ( (Number) data[1]).intValue();
756
757         if (numberOfPositions == 0 || numberOfElements <= 0) {
758           return;
759         }
760
761         rollData = context.popOperands(numberOfElements);
762
763         if (numberOfPositions < 0) {
764           numberOfPositions = -numberOfPositions;
765           numberOfPositions = numberOfPositions % numberOfElements;
766
767           // downward roll
768
for (i = numberOfPositions; i < numberOfElements; i++) {
769             context.operands.push(rollData[i]);
770           }
771           for (i = 0; i < numberOfPositions; i++) {
772             context.operands.push(rollData[i]);
773           }
774         }
775         else {
776           numberOfPositions = numberOfPositions % numberOfElements;
777
778           // upward roll
779
for (i = numberOfElements - numberOfPositions; i < numberOfElements;
780                i++) {
781             context.operands.push(rollData[i]);
782           }
783           for (i = 0; i < numberOfElements - numberOfPositions; i++) {
784             context.operands.push(rollData[i]);
785           }
786         }
787       }
788     });
789
790     // pop
791
systemDict.put("pop", new PACommand() {
792       public void execute(PAContext context) throws PainterException {
793         context.popOperands(1);
794       }
795     });
796
797     // index
798
systemDict.put("index", new PACommand() {
799       public void execute(PAContext context) throws PainterException {
800         Object data[];
801         data = context.popOperands(1);
802         if (! (data[0] instanceof Number)) {
803           throw new PainterException("wrong arguments");
804