1
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
17
18
19
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
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
91 os.println("fill");
92 os.println("\t\t} def");
93 os.println();
94 }
95
96
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
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
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
138
139
140 }
141
142
143 protected void closeIncludeFont() throws IOException {
144 this.writeBuildProcs();
145
146 }
147
148
149
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
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
182
183
184
185 protected void openGlyphs() throws IOException {
186
187
188 os.println("\t/CharProcs " + (getNODefinedChars() + 1) + " dict def");
189 os.println("\tCharProcs begin");
190
191 os.println("\t\t\t%define Glyph dictionary and start filling");
192 }
193
194
195 protected void closeGlyphs() throws IOException {
196
197 os.print("\tend");
198 os.println("\t\t\t\t% close glyph dict. ");
199 }
200
201
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 }