1
2 package org.freehep.graphicsio.font;
3
4 import java.awt.Shape;
5 import java.io.IOException;
6 import java.io.OutputStream;
7
8 import org.freehep.graphicsio.QuadToCubicPathConstructor;
9
10
11
12
13
14
15
16 public class CharstringEncoder extends QuadToCubicPathConstructor {
17
18 private static final int LAST_POINT = 0;
19
20 private static final int HORIZONTAL = 1;
21
22 private static final int VERTICAL = 2;
23
24 private static final int BOTH = 3;
25
26 private OutputStream out;
27
28 private int currentX, currentY;
29
30 public CharstringEncoder(OutputStream out) {
31 this.out = out;
32 currentX = currentY = 0;
33 }
34
35 private int writeNumber(double v) throws IOException {
36 int round = (int) Math.round(v);
37 writeNumber(round);
38 return round;
39 }
40
41 private void writeNumber(int v) throws IOException {
42 if ((v >= -107) && (v <= 107)) {
43 out.write(v + 139);
44 } else if ((v >= 108) && (v <= 1131)) {
45 int highByte = (v - 108) / 256;
46 out.write(highByte + 247);
47 out.write(v - 108 - 256 * highByte);
48 } else if ((v >= -1131) && (v <= -108)) {
49 int highByte = (v + 108) / 256;
50 out.write(-highByte + 251);
51 out.write(-(v + 108 - 256 * highByte));
52 } else {
53 out.write(255);
54
55 out.write((v >>> 24) & 0xFF);
56 out.write((v >>> 16) & 0xFF);
57 out.write((v >>> 8) & 0xFF);
58 out.write((v >>> 0) & 0xFF);
59 }
60 }
61
62 protected void writeCommand(int com) throws IOException {
63 if (com >= 31)
64 throw new IOException("Charstring command out of range: " + com);
65 out.write(com);
66 }
67
68 protected void writeExtCommand(int com) throws IOException {
69 out.write(12);
70 out.write(com);
71 }
72
73
74
75 private void writePoint(double x, double y) throws IOException {
76 currentX += writeNumber(x - currentX);
77 currentY += writeNumber(y - currentY);
78 }
79
80 private void writeX(double x) throws IOException {
81 currentX += writeNumber(x - currentX);
82 }
83
84 private void writeY(double y) throws IOException {
85 currentY += writeNumber(y - currentY);
86 }
87
88
89
90 public void startChar(double sidebearing, double width) throws IOException {
91 currentX = writeNumber(sidebearing);
92 writeNumber(width);
93 writeCommand(13);
94 }
95
96 public void endchar() throws IOException {
97 writeCommand(14);
98 }
99
100
101
102 private int to(double x, double y) throws IOException {
103
104
105
106 int rx = (int) Math.round(x);
107 int ry = (int) Math.round(y);
108
109 if (rx == currentX) {
110 if (ry == currentY) {
111 return LAST_POINT;
112 } else {
113 writeY(y);
114 return VERTICAL;
115 }
116 } else if (ry == currentY) {
117 writeX(x);
118 return HORIZONTAL;
119 } else {
120 writePoint(x, y);
121 return BOTH;
122 }
123 }
124
125 public void move(double x, double y) throws IOException {
126 switch (to(x, y)) {
127 case BOTH:
128 writeCommand(21);
129 break;
130 case HORIZONTAL:
131 writeCommand(22);
132 break;
133 case VERTICAL:
134 writeCommand(4);
135 break;
136 case LAST_POINT:
137 break;
138 }
139 super.move(x, y);
140 }
141
142 public void line(double x, double y) throws IOException {
143 switch (to(x, y)) {
144 case BOTH:
145 writeCommand(5);
146 break;
147 case HORIZONTAL:
148 writeCommand(6);
149 break;
150 case VERTICAL:
151 writeCommand(7);
152 break;
153 case LAST_POINT:
154 break;
155 }
156 super.line(x, y);
157 }
158
159 public void cubic(double x1, double y1, double x2, double y2, double x3,
160 double y3) throws IOException {
161 writePoint(x1, y1);
162 writePoint(x2, y2);
163 writePoint(x3, y3);
164 writeCommand(8);
165 super.cubic(x1, y1, x2, y2, x3, y3);
166 }
167
168 public void closePath(double x0, double y0) throws IOException {
169 writeCommand(9);
170 super.closePath(x0, y0);
171 }
172
173 public void drawPath(Shape s) throws IOException {
174 addPath(s);
175 }
176
177 }