View Javadoc

1   // Copyright 2001-2005 FreeHEP
2   package org.freehep.graphicsio.ps;
3   
4   import java.awt.Shape;
5   import java.awt.font.FontRenderContext;
6   import java.awt.font.GlyphMetrics;
7   import java.awt.geom.PathIterator;
8   import java.awt.geom.Rectangle2D;
9   import java.io.IOException;
10  import java.io.PrintStream;
11  
12  import org.freehep.graphics2d.font.CharTable;
13  import org.freehep.graphicsio.font.FontEmbedder;
14  
15  /**
16   * Type 3 Font Embedder class for Postscript.
17   * 
18   * @author Sami Kama
19   * @version $Id: PSFontEmbedder.java 8584 2006-08-10 23:06:37Z duns $
20   */
21  public class PSFontEmbedder extends FontEmbedder {
22  
23      protected int dictSize = 9;
24  
25      protected PrintStream os;
26  
27      private PSPathConstructor pc;
28  
29      public PSFontEmbedder(FontRenderContext context, PrintStream os) {
30          super(context);
31          this.os = os;
32          pc = new PSPathConstructor(os, false, true);
33      }
34  
35      /**
36       * Writes Glyph definition of given glyph.
37       */
38      protected void writeGlyph(String unicodeName, Shape glyph,
39              GlyphMetrics glyphMetrics) throws IOException {
40  
41          double[] points = new double[6];
42          double[] lastMove = new double[2];
43          double[] lastPoint = new double[2];
44          double[] controlPoint = new double[4];
45  
46          PathIterator pIter = glyph.getPathIterator(null);
47          os.println("\t/" + unicodeName);
48          os.println("\t\t{");
49  
50          while (!pIter.isDone()) {
51              switch (pIter.currentSegment(points)) {
52              case PathIterator.SEG_MOVETO:
53                  pc.move(points[0], points[1]);
54                  lastMove[0] = lastPoint[0] = points[0];
55                  lastMove[1] = lastPoint[1] = points[1];
56                  break;
57  
58              case PathIterator.SEG_LINETO:
59                  pc.line(points[0], points[1]);
60                  lastPoint[0] = points[0];
61                  lastPoint[1] = points[1];
62                  break;
63  
64              case PathIterator.SEG_QUADTO:
65                  controlPoint[0] = points[0] + (lastPoint[0] - points[0]) / 3.;
66                  controlPoint[1] = points[1] + (lastPoint[1] - points[1]) / 3.;
67                  controlPoint[2] = points[0] + (points[2] - points[0]) / 3.;
68                  controlPoint[3] = points[1] + (points[3] - points[1]) / 3.;
69                  pc.cubic(controlPoint[0], controlPoint[1], controlPoint[2],
70                          controlPoint[3], points[2], points[3]);
71                  lastPoint[0] = points[2];
72                  lastPoint[1] = points[3];
73                  break;
74  
75              case PathIterator.SEG_CUBICTO:
76                  pc.cubic(points[0], points[1], points[2], points[3], points[4],
77                          points[5]);
78                  lastPoint[0] = points[4];
79                  lastPoint[1] = points[5];
80                  break;
81  
82              case PathIterator.SEG_CLOSE:
83                  pc.closePath(lastMove[0], lastMove[1]);
84                  lastPoint[0] = 0.;
85                  lastPoint[1] = 0.;
86                  break;
87              }
88              pIter.next();
89          }
90          // System.out.println("done once");
91          os.println("fill");
92          os.println("\t\t} def");
93          os.println();
94      }
95  
96      /** writes metric dictionary for the font. */
97  
98      protected void writeWidths(double[] widths) throws IOException {
99          os.println("\t/Metrics " + (getNODefinedChars() + 1) + " dict def");
100         os.println("\t\tMetrics begin");
101         os.println("\t\t/" + NOTDEF + " " + (int) getUndefinedWidth() + " def");
102         for (int i = 1; i < 256; i++) {
103             if (getCharName(i) != null) {
104                 os.println("\t\t/" + getCharName(i) + " " + widths[i] + " def");
105             }
106 
107         }
108         os.println("\tend");
109     }
110 
111     /** writes encoding array. */
112 
113     protected void writeEncoding(CharTable charTable) throws IOException {
114         os.println("\t/Encoding 256 array def");
115         os.println("\t\t\t0 1 255 {Encoding exch /.notdef put}for");
116         for (int i = 1; i < 256; i++) {
117             String name = charTable.toName(i);
118             if (name != null) {
119                 os.println("\t\tEncoding " + i + " /" + name + " put");
120             }
121         }
122     }
123 
124     /** Writes initial parts of the font dictionary. */
125     protected void openIncludeFont() throws IOException {
126         Rectangle2D boundingBox = getFontBBox();
127         double llx = boundingBox.getX();
128         double lly = -boundingBox.getY() - boundingBox.getHeight();
129         double urx = boundingBox.getX() + boundingBox.getWidth();
130         double ury = -boundingBox.getY();
131         os.println("9 dict begin");
132         os.println("/FontType 3 def");
133         os.println("/FontMatrix [" + (1 / FONT_SIZE) + " 0 0 "
134                 + (1 / FONT_SIZE) + " 0 0]def");
135         os.println("/FontBBox [" + (int) llx + " " + (int) lly + " "
136                 + (int) urx + " " + (int) ury + " ] def");
137         // os.println("\t /"+getFontName()+" "+(getNODefinedChars()+1)+" dict
138         // def");
139 
140     }
141 
142     /** Closes font dictionary. */
143     protected void closeIncludeFont() throws IOException {
144         this.writeBuildProcs();
145 
146     }
147 
148     /*
149      * Writes <tt>BuildGlyph</tt> and <tt>BuildChar</tt> procedures of font.
150      */
151     protected void writeBuildProcs() throws IOException {
152         Rectangle2D boundingBox = getFontBBox();
153         double llx = boundingBox.getX();
154         double lly = -boundingBox.getY() - boundingBox.getHeight();
155         double urx = boundingBox.getX() + boundingBox.getWidth();
156         double ury = -boundingBox.getY();
157 
158         os.println("\t/BuildGlyph");
159         os.println("\t\t{ 2 copy exch /Metrics get exch ");
160         os.println("\t\t\t2 copy known {get}{pop pop " + getUndefinedWidth()
161                 + "} ifelse");
162         os.println("\t\t\t0");
163         os.println("\t\t\t" + (int) llx + " " + (int) lly + " " + (int) urx
164                 + " " + (int) ury);
165         os.println("\t\t\tsetcachedevice");
166         // ????? os.println("\t\t\texch /"+getFontName()+" get exch");
167         os.println("\t\t\texch /CharProcs get exch");
168         os.println("\t\t\t2 copy known not");
169         os.println("\t\t\t\t\t{pop /.notdef}");
170         os.println("\t\t\t\tif");
171         os.println("\t\t\tget exec");
172         os.println("\t\t} bind def");
173         os.println();
174         os.println("\t/BuildChar");
175         os.println("\t\t{ 1 index /Encoding get exch get");
176         os.println("\t\t  1 index /BuildGlyph get exec");
177         os.println("\t  } bind def");
178     }
179 
180     /**
181      * Writes necessary commands to find <tt>Glyphs</tt> dictionary from font
182      * dictionary and puts it on the stack, opens dictionary to write glyph
183      * definitions.
184      */
185     protected void openGlyphs() throws IOException {
186         // ??????? os.println("\t/"+getFontName()+" "+(getNODefinedChars()+1)+"
187         // dict def");
188         os.println("\t/CharProcs " + (getNODefinedChars() + 1) + " dict def");
189         os.println("\tCharProcs begin");
190         // os.print("dup /"+getFontName()+" get begin");
191         os.println("\t\t\t%define Glyph dictionary and start filling");
192     }
193 
194     /** Closes Glyphs dictionary. */
195     protected void closeGlyphs() throws IOException {
196 
197         os.print("\tend");
198         os.println("\t\t\t\t% close glyph dict. ");
199     }
200 
201     /** Closes font dictionary. */
202     protected void closeEmbedFont() throws IOException {
203         os.print("\tcurrentdict");
204         os.println("\t\t\t% actually put dict on the stack");
205         os.print("\tend");
206         os.println("\t\t\t% close the dictionary now");
207         os.println("\t/" + getFontName() + " exch definefont pop");
208         os.flush();
209     }
210 
211 }