| @@ -1,514 +1,485 @@ | | | @@ -1,514 +1,485 @@ |
1 | /* | | 1 | /* |
2 | Copyright (c) 2002-2003 by Juliusz Chroboczek | | 2 | Copyright (c) 2002-2003 by Juliusz Chroboczek |
3 | | | 3 | |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy | | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | of this software and associated documentation files (the "Software"), to deal | | 5 | of this software and associated documentation files (the "Software"), to deal |
6 | in the Software without restriction, including without limitation the rights | | 6 | in the Software without restriction, including without limitation the rights |
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | | 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
8 | copies of the Software, and to permit persons to whom the Software is | | 8 | copies of the Software, and to permit persons to whom the Software is |
9 | furnished to do so, subject to the following conditions: | | 9 | furnished to do so, subject to the following conditions: |
10 | | | 10 | |
11 | The above copyright notice and this permission notice shall be included in | | 11 | The above copyright notice and this permission notice shall be included in |
12 | all copies or substantial portions of the Software. | | 12 | all copies or substantial portions of the Software. |
13 | | | 13 | |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | | 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | | 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | | 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | | 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | | 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
20 | THE SOFTWARE. | | 20 | THE SOFTWARE. |
21 | */ | | 21 | */ |
22 | /* $XFree86: xc/programs/fonttosfnt/struct.c,v 1.3 2003/10/24 20:38:11 tsi Exp $ */ | | 22 | /* $XFree86: xc/programs/fonttosfnt/struct.c,v 1.3 2003/10/24 20:38:11 tsi Exp $ */ |
23 | | | 23 | |
24 | #include <stdlib.h> | | 24 | #include <stdlib.h> |
25 | #include <stdio.h> | | 25 | #include <stdio.h> |
26 | #include <ft2build.h> | | 26 | #include <ft2build.h> |
27 | #include FT_FREETYPE_H | | 27 | #include FT_FREETYPE_H |
28 | #include "fonttosfnt.h" | | 28 | #include "fonttosfnt.h" |
29 | | | 29 | |
30 | FontPtr | | 30 | FontPtr |
31 | makeFont(void) | | 31 | makeFont(void) |
32 | { | | 32 | { |
33 | FontPtr font; | | 33 | FontPtr font; |
34 | | | 34 | |
35 | font = malloc(sizeof(FontRec)); | | 35 | font = malloc(sizeof(FontRec)); |
36 | if(font == NULL) | | 36 | if(font == NULL) |
37 | return NULL; | | 37 | return NULL; |
38 | | | 38 | |
39 | font->numNames = 0; | | 39 | font->numNames = 0; |
40 | font->names = NULL; | | 40 | font->names = NULL; |
41 | font->flags = 0; | | 41 | font->flags = 0; |
42 | font->weight = 500; | | 42 | font->weight = 500; |
43 | font->width = 5; | | 43 | font->width = 5; |
44 | font->italicAngle = 0; | | 44 | font->italicAngle = 0; |
45 | font->underlinePosition = - TWO_SIXTEENTH; | | 45 | font->pxMetrics.height = UNDEF; |
46 | font->underlineThickness = TWO_SIXTEENTH; | | 46 | font->pxMetrics.maxX = UNDEF; |
| | | 47 | font->pxMetrics.minX = UNDEF; |
| | | 48 | font->pxMetrics.maxY = UNDEF; |
| | | 49 | font->pxMetrics.minY = UNDEF; |
| | | 50 | font->pxMetrics.xHeight = UNDEF; |
| | | 51 | font->pxMetrics.capHeight = UNDEF; |
| | | 52 | font->pxMetrics.maxAwidth = UNDEF; |
| | | 53 | font->pxMetrics.awidth = UNDEF; |
| | | 54 | font->pxMetrics.ascent = UNDEF; |
| | | 55 | font->pxMetrics.descent = UNDEF; |
| | | 56 | font->pxMetrics.underlinePosition = UNDEF; |
| | | 57 | font->pxMetrics.underlineThickness = UNDEF; |
| | | 58 | font->metrics.height = UNDEF; |
| | | 59 | font->metrics.maxX = UNDEF; |
| | | 60 | font->metrics.minX = UNDEF; |
| | | 61 | font->metrics.maxY = UNDEF; |
| | | 62 | font->metrics.minY = UNDEF; |
| | | 63 | font->metrics.xHeight = UNDEF; |
| | | 64 | font->metrics.capHeight = UNDEF; |
| | | 65 | font->metrics.maxAwidth = UNDEF; |
| | | 66 | font->metrics.awidth = UNDEF; |
| | | 67 | font->metrics.ascent = UNDEF; |
| | | 68 | font->metrics.descent = UNDEF; |
| | | 69 | font->metrics.underlinePosition = UNDEF; |
| | | 70 | font->metrics.underlineThickness = UNDEF; |
47 | font->foundry = makeName("UNKN"); | | 71 | font->foundry = makeName("UNKN"); |
48 | font->strikes = NULL; | | 72 | font->strikes = NULL; |
49 | return font; | | 73 | return font; |
50 | } | | 74 | } |
51 | | | 75 | |
52 | StrikePtr | | 76 | StrikePtr |
53 | makeStrike(FontPtr font, int sizeX, int sizeY) | | 77 | makeStrike(FontPtr font, int sizeX, int sizeY) |
54 | { | | 78 | { |
55 | StrikePtr strike, last_strike; | | 79 | StrikePtr strike, last_strike; |
56 | | | 80 | |
57 | strike = font->strikes; | | 81 | strike = font->strikes; |
58 | last_strike = NULL; | | 82 | last_strike = NULL; |
59 | while(strike) { | | 83 | while(strike) { |
60 | if(strike->sizeX == sizeX && strike->sizeY == sizeY) | | 84 | if(strike->sizeX == sizeX && strike->sizeY == sizeY) |
61 | return strike; | | 85 | return strike; |
62 | last_strike = strike; | | 86 | last_strike = strike; |
63 | strike = strike->next; | | 87 | strike = strike->next; |
64 | } | | 88 | } |
65 | | | 89 | |
66 | strike = malloc(sizeof(StrikeRec)); | | 90 | strike = malloc(sizeof(StrikeRec)); |
67 | if(strike == NULL) | | 91 | if(strike == NULL) |
68 | return NULL; | | 92 | return NULL; |
69 | strike->sizeX = sizeX; | | 93 | strike->sizeX = sizeX; |
70 | strike->sizeY = sizeY; | | 94 | strike->sizeY = sizeY; |
71 | strike->bitmaps = | | 95 | strike->bitmaps = |
72 | calloc(FONT_CODES / FONT_SEGMENT_SIZE, sizeof(BitmapPtr*)); | | 96 | calloc(FONT_CODES / FONT_SEGMENT_SIZE, sizeof(BitmapPtr*)); |
73 | if(strike->bitmaps == NULL) { | | 97 | if(strike->bitmaps == NULL) { |
74 | free(strike); | | 98 | free(strike); |
75 | return NULL; | | 99 | return NULL; |
76 | } | | 100 | } |
77 | strike->numSbits = 0; | | 101 | strike->numSbits = 0; |
78 | strike->next = NULL; | | 102 | strike->next = NULL; |
79 | strike->bitmapSizeTableLocation = 0xDEADFACE; | | 103 | strike->bitmapSizeTableLocation = 0xDEADFACE; |
80 | strike->indexSubTables = NULL; | | 104 | strike->indexSubTables = NULL; |
81 | if(last_strike) | | 105 | if(last_strike) |
82 | last_strike->next = strike; | | 106 | last_strike->next = strike; |
83 | else | | 107 | else |
84 | font->strikes = strike; | | 108 | font->strikes = strike; |
85 | return strike; | | 109 | return strike; |
86 | } | | 110 | } |
87 | | | 111 | |
88 | BitmapPtr | | 112 | BitmapPtr |
89 | makeBitmap(StrikePtr strike, int code, | | 113 | makeBitmap(StrikePtr strike, int code, |
90 | int advanceWidth, int horiBearingX, int horiBearingY, | | 114 | int advanceWidth, int horiBearingX, int horiBearingY, |
91 | int width, int height, int stride, unsigned char *raster, int crop) | | 115 | int width, int height, int stride, unsigned char *raster, int crop) |
92 | { | | 116 | { |
93 | BitmapPtr bitmap; | | 117 | BitmapPtr bitmap; |
94 | int i, j, x, y; | | 118 | int i, j, x, y; |
95 | int dx, dy, new_width, new_height; | | 119 | int dx, dy, new_width, new_height; |
96 | | | 120 | |
97 | bitmap = malloc(sizeof(BitmapRec)); | | 121 | bitmap = malloc(sizeof(BitmapRec)); |
98 | if(bitmap == NULL) | | 122 | if(bitmap == NULL) |
99 | return NULL; | | 123 | return NULL; |
100 | | | 124 | |
101 | bitmap->index = -1; | | 125 | bitmap->index = -1; |
102 | bitmap->width = 0; | | 126 | bitmap->width = 0; |
103 | bitmap->height = 0; | | 127 | bitmap->height = 0; |
104 | bitmap->stride = 0; | | 128 | bitmap->stride = 0; |
105 | bitmap->raster = NULL; | | 129 | bitmap->raster = NULL; |
106 | bitmap->location = 0xDEADFACE; | | 130 | bitmap->location = 0xDEADFACE; |
107 | | | 131 | |
108 | i = code / FONT_SEGMENT_SIZE; | | 132 | i = code / FONT_SEGMENT_SIZE; |
109 | j = code % FONT_SEGMENT_SIZE; | | 133 | j = code % FONT_SEGMENT_SIZE; |
110 | | | 134 | |
111 | if(strike->bitmaps[i] == NULL) { | | 135 | if(strike->bitmaps[i] == NULL) { |
112 | strike->bitmaps[i] = calloc(FONT_SEGMENT_SIZE, sizeof(BitmapPtr)); | | 136 | strike->bitmaps[i] = calloc(FONT_SEGMENT_SIZE, sizeof(BitmapPtr)); |
113 | } | | 137 | } |
114 | if(strike->bitmaps[i] == NULL) { | | 138 | if(strike->bitmaps[i] == NULL) { |
115 | free(bitmap); | | 139 | free(bitmap); |
116 | return NULL; | | 140 | return NULL; |
117 | } | | 141 | } |
118 | if(strike->bitmaps[i][j] != NULL) { | | 142 | if(strike->bitmaps[i][j] != NULL) { |
119 | if(verbose_flag) | | 143 | if(verbose_flag) |
120 | fprintf(stderr, "Duplicate bitmap %d.\n", code); | | 144 | fprintf(stderr, "Duplicate bitmap %d.\n", code); |
121 | free(bitmap); | | 145 | free(bitmap); |
122 | return strike->bitmaps[i][j]; | | 146 | return strike->bitmaps[i][j]; |
123 | } | | 147 | } |
124 | | | 148 | |
125 | dx = 0; | | 149 | dx = 0; |
126 | dy = 0; | | 150 | dy = 0; |
127 | new_width = width; | | 151 | new_width = width; |
128 | new_height = height; | | 152 | new_height = height; |
129 | | | 153 | |
130 | if(crop) { | | 154 | if(crop) { |
131 | int empty; | | 155 | int empty; |
132 | while(new_width > 0) { | | 156 | while(new_width > 0) { |
133 | empty = 1; | | 157 | empty = 1; |
134 | x = new_width - 1; | | 158 | x = new_width - 1; |
135 | for(y = 0; y < new_height; y++) { | | 159 | for(y = 0; y < new_height; y++) { |
136 | if(BITREF(raster, stride, x + dx, y + dy)) { | | 160 | if(BITREF(raster, stride, x + dx, y + dy)) { |
137 | empty = 0; | | 161 | empty = 0; |
138 | break; | | 162 | break; |
139 | } | | 163 | } |
140 | } | | 164 | } |
141 | if(empty) | | 165 | if(empty) |
142 | new_width--; | | 166 | new_width--; |
143 | else | | 167 | else |
144 | break; | | 168 | break; |
145 | } | | 169 | } |
146 | while(new_height > 0) { | | 170 | while(new_height > 0) { |
147 | empty = 1; | | 171 | empty = 1; |
148 | y = new_height - 1; | | 172 | y = new_height - 1; |
149 | for(x = 0; x < new_width; x++) { | | 173 | for(x = 0; x < new_width; x++) { |
150 | if(BITREF(raster, stride, x + dx, y + dy)) { | | 174 | if(BITREF(raster, stride, x + dx, y + dy)) { |
151 | empty = 0; | | 175 | empty = 0; |
152 | break; | | 176 | break; |
153 | } | | 177 | } |
154 | } | | 178 | } |
155 | if(empty) | | 179 | if(empty) |
156 | new_height--; | | 180 | new_height--; |
157 | else | | 181 | else |
158 | break; | | 182 | break; |
159 | } | | 183 | } |
160 | while(new_width > 0) { | | 184 | while(new_width > 0) { |
161 | empty = 1; | | 185 | empty = 1; |
162 | x = 0; | | 186 | x = 0; |
163 | for(y = 0; y < new_height; y++) { | | 187 | for(y = 0; y < new_height; y++) { |
164 | if(BITREF(raster, stride, x + dx, y + dy)) { | | 188 | if(BITREF(raster, stride, x + dx, y + dy)) { |
165 | empty = 0; | | 189 | empty = 0; |
166 | break; | | 190 | break; |
167 | } | | 191 | } |
168 | } | | 192 | } |
169 | if(empty) { | | 193 | if(empty) { |
170 | dx++; | | 194 | dx++; |
171 | new_width--; | | 195 | new_width--; |
172 | } else | | 196 | } else |
173 | break; | | 197 | break; |
174 | } | | 198 | } |
175 | while(new_height > 0) { | | 199 | while(new_height > 0) { |
176 | empty = 1; | | 200 | empty = 1; |
177 | y = 0; | | 201 | y = 0; |
178 | for(x = 0; x < new_width; x++) { | | 202 | for(x = 0; x < new_width; x++) { |
179 | if(BITREF(raster, stride, x + dx, y + dy)) { | | 203 | if(BITREF(raster, stride, x + dx, y + dy)) { |
180 | empty = 0; | | 204 | empty = 0; |
181 | break; | | 205 | break; |
182 | } | | 206 | } |
183 | } | | 207 | } |
184 | if(empty) { | | 208 | if(empty) { |
185 | dy++; | | 209 | dy++; |
186 | new_height--; | | 210 | new_height--; |
187 | } else | | 211 | } else |
188 | break; | | 212 | break; |
189 | } | | 213 | } |
190 | } | | 214 | } |
191 | | | 215 | |
192 | | | 216 | |
193 | bitmap->advanceWidth = advanceWidth; | | 217 | bitmap->advanceWidth = advanceWidth; |
194 | bitmap->horiBearingX = horiBearingX + dx; | | 218 | bitmap->horiBearingX = horiBearingX + dx; |
195 | bitmap->horiBearingY = horiBearingY - dy; | | 219 | bitmap->horiBearingY = horiBearingY - dy; |
196 | bitmap->width = new_width; | | 220 | bitmap->width = new_width; |
197 | bitmap->height = new_height; | | 221 | bitmap->height = new_height; |
198 | bitmap->stride = (new_width + 7) / 8; | | 222 | bitmap->stride = (new_width + 7) / 8; |
199 | | | 223 | |
200 | bitmap->raster = malloc(bitmap->height * bitmap->stride); | | 224 | bitmap->raster = malloc(bitmap->height * bitmap->stride); |
201 | if(bitmap->raster == NULL) { | | 225 | if(bitmap->raster == NULL) { |
202 | free(bitmap); | | 226 | free(bitmap); |
203 | return NULL; | | 227 | return NULL; |
204 | } | | 228 | } |
205 | memset(bitmap->raster, 0, bitmap->height * bitmap->stride); | | 229 | memset(bitmap->raster, 0, bitmap->height * bitmap->stride); |
206 | for(y = 0; y < new_height; y++) { | | 230 | for(y = 0; y < new_height; y++) { |
207 | for(x = 0; x < new_width; x++) { | | 231 | for(x = 0; x < new_width; x++) { |
208 | if(BITREF(raster, stride, x + dx, y + dy)) | | 232 | if(BITREF(raster, stride, x + dx, y + dy)) |
209 | bitmap->raster[y * bitmap->stride + x / 8] |= | | 233 | bitmap->raster[y * bitmap->stride + x / 8] |= |
210 | 1 << (7 - (x % 8)); | | 234 | 1 << (7 - (x % 8)); |
211 | } | | 235 | } |
212 | } | | 236 | } |
213 | strike->bitmaps[i][j] = bitmap; | | 237 | strike->bitmaps[i][j] = bitmap; |
214 | strike->numSbits++; | | 238 | strike->numSbits++; |
215 | | | 239 | |
216 | return bitmap; | | 240 | return bitmap; |
217 | } | | 241 | } |
218 | | | 242 | |
219 | IndexSubTablePtr | | 243 | IndexSubTablePtr |
220 | makeIndexSubTables(StrikePtr strike, CmapPtr cmap) | | 244 | makeIndexSubTables(StrikePtr strike, CmapPtr cmap) |
221 | { | | 245 | { |
222 | IndexSubTablePtr table, first, last; | | 246 | IndexSubTablePtr table, first, last; |
223 | BitmapPtr bitmap0, bitmap; | | 247 | BitmapPtr bitmap0, bitmap; |
224 | int index, n; | | 248 | int index, n; |
225 | | | 249 | |
226 | first = NULL; | | 250 | first = NULL; |
227 | last = NULL; | | 251 | last = NULL; |
228 | | | 252 | |
229 | /* Assuming that we're writing bit-aligned data, small metrics | | 253 | /* Assuming that we're writing bit-aligned data, small metrics |
230 | and short offsets, a constant metrics segment saves 5 bytes | | 254 | and short offsets, a constant metrics segment saves 5 bytes |
231 | per glyph in the EBDT table, and 2 bytes per glyph in the EBLC | | 255 | per glyph in the EBDT table, and 2 bytes per glyph in the EBLC |
232 | table. On the other hand, the overhead for a supplementary | | 256 | table. On the other hand, the overhead for a supplementary |
233 | type 2 indexSubTable is 8 bytes for the indexSubTableArray | | 257 | type 2 indexSubTable is 8 bytes for the indexSubTableArray |
234 | entry and 20 bytes for the subtable itself. It's worth | | 258 | entry and 20 bytes for the subtable itself. It's worth |
235 | splitting at 5 glyphs. There's no analogue of a type 2 | | 259 | splitting at 5 glyphs. There's no analogue of a type 2 |
236 | indexSubTable with byte-aligned data, so we don't bother | | 260 | indexSubTable with byte-aligned data, so we don't bother |
237 | splitting when byte-aligning. */ | | 261 | splitting when byte-aligning. */ |
238 | index = 0; | | 262 | index = 0; |
239 | while(index < 0xFFFF) { | | 263 | while(index < 0xFFFF) { |
240 | int constantMetrics = 1; | | 264 | int constantMetrics = 1; |
241 | bitmap0 = strikeBitmapIndex(strike, cmap, index); | | 265 | bitmap0 = strikeBitmapIndex(strike, cmap, index); |
242 | if(bitmap0 == NULL) { | | 266 | if(bitmap0 == NULL) { |
243 | index++; | | 267 | index++; |
244 | continue; | | 268 | continue; |
245 | } | | 269 | } |
246 | n = 1; | | 270 | n = 1; |
247 | while((bitmap = strikeBitmapIndex(strike, cmap, index + n)) != NULL) { | | 271 | while((bitmap = strikeBitmapIndex(strike, cmap, index + n)) != NULL) { |
248 | if(constantMetrics) { | | 272 | if(constantMetrics) { |
249 | if(!SAME_METRICS(bitmap0, bitmap)) { | | 273 | if(!SAME_METRICS(bitmap0, bitmap)) { |
250 | if(bit_aligned_flag && n >= 4) | | 274 | if(bit_aligned_flag && n >= 4) |
251 | break; | | 275 | break; |
252 | else | | 276 | else |
253 | constantMetrics = 0; | | 277 | constantMetrics = 0; |
254 | } | | 278 | } |
255 | } else if(bit_aligned_flag) { | | 279 | } else if(bit_aligned_flag) { |
256 | BitmapPtr b1 = strikeBitmapIndex(strike, cmap, index + n + 1); | | 280 | BitmapPtr b1 = strikeBitmapIndex(strike, cmap, index + n + 1); |
257 | BitmapPtr b2 = strikeBitmapIndex(strike, cmap, index + n + 2); | | 281 | BitmapPtr b2 = strikeBitmapIndex(strike, cmap, index + n + 2); |
258 | BitmapPtr b3 = strikeBitmapIndex(strike, cmap, index + n + 3); | | 282 | BitmapPtr b3 = strikeBitmapIndex(strike, cmap, index + n + 3); |
259 | BitmapPtr b4 = strikeBitmapIndex(strike, cmap, index + n + 4); | | 283 | BitmapPtr b4 = strikeBitmapIndex(strike, cmap, index + n + 4); |
260 | if(b1 && b2 && b3 && b4 && | | 284 | if(b1 && b2 && b3 && b4 && |
261 | SAME_METRICS(bitmap, b1) && | | 285 | SAME_METRICS(bitmap, b1) && |
262 | SAME_METRICS(bitmap, b2) && | | 286 | SAME_METRICS(bitmap, b2) && |
263 | SAME_METRICS(bitmap, b3) && | | 287 | SAME_METRICS(bitmap, b3) && |
264 | SAME_METRICS(bitmap, b4)) { | | 288 | SAME_METRICS(bitmap, b4)) { |
265 | break; | | 289 | break; |
266 | } | | 290 | } |
267 | } | | 291 | } |
268 | n++; | | 292 | n++; |
269 | } | | 293 | } |
270 | if(n <= 1) | | 294 | if(n <= 1) |
271 | constantMetrics = 0; | | 295 | constantMetrics = 0; |
272 | | | 296 | |
273 | table = malloc(sizeof(IndexSubTableRec)); | | 297 | table = malloc(sizeof(IndexSubTableRec)); |
274 | table->firstGlyphIndex = index; | | 298 | table->firstGlyphIndex = index; |
275 | table->lastGlyphIndex = index + n - 1; | | 299 | table->lastGlyphIndex = index + n - 1; |
276 | table->constantMetrics = constantMetrics; | | 300 | table->constantMetrics = constantMetrics; |
277 | table->location = 0xDEADFACE; | | 301 | table->location = 0xDEADFACE; |
278 | table->lastLocation = 0xDEADFACE; | | 302 | table->lastLocation = 0xDEADFACE; |
279 | table->next = NULL; | | 303 | table->next = NULL; |
280 | | | 304 | |
281 | if(first == NULL) { | | 305 | if(first == NULL) { |
282 | first = table; | | 306 | first = table; |
283 | last = table; | | 307 | last = table; |
284 | } else { | | 308 | } else { |
285 | last->next = table; | | 309 | last->next = table; |
286 | last = table; | | 310 | last = table; |
287 | } | | 311 | } |
288 | index += n; | | 312 | index += n; |
289 | } | | 313 | } |
290 | return first; | | 314 | return first; |
291 | } | | 315 | } |
292 | | | 316 | |
293 | int | | 317 | int |
294 | fontIndex(FontPtr font, int code) | | 318 | fontIndex(FontPtr font, int code) |
295 | { | | 319 | { |
296 | StrikePtr strike; | | 320 | StrikePtr strike; |
297 | BitmapPtr bitmap; | | 321 | BitmapPtr bitmap; |
298 | | | 322 | |
299 | if(code == 0) | | 323 | if(code == 0) |
300 | return 0; | | 324 | return 0; |
301 | strike = font->strikes; | | 325 | strike = font->strikes; |
302 | while(strike) { | | 326 | while(strike) { |
303 | bitmap = STRIKE_BITMAP(strike, code); | | 327 | bitmap = STRIKE_BITMAP(strike, code); |
304 | if(bitmap) | | 328 | if(bitmap) |
305 | return bitmap->index; | | 329 | return bitmap->index; |
306 | strike = strike->next; | | 330 | strike = strike->next; |
307 | } | | 331 | } |
308 | return -1; | | 332 | return -1; |
309 | } | | 333 | } |
310 | | | 334 | |
311 | CmapPtr | | 335 | CmapPtr |
312 | makeCmap(FontPtr font) | | 336 | makeCmap(FontPtr font) |
313 | { | | 337 | { |
314 | CmapPtr cmap_head = NULL; | | 338 | CmapPtr cmap_head = NULL; |
315 | CmapPtr cmap_last = NULL; | | 339 | CmapPtr cmap_last = NULL; |
316 | CmapPtr cmap; | | 340 | CmapPtr cmap; |
317 | int code, i, index, maxindex = 0; | | 341 | int code, i, index, maxindex = 0; |
318 | | | 342 | |
319 | code = 0; | | 343 | code = 0; |
320 | while(code < FONT_CODES) { | | 344 | while(code < FONT_CODES) { |
321 | index = fontIndex(font, code); | | 345 | index = fontIndex(font, code); |
322 | if(index < 0) { | | 346 | if(index < 0) { |
323 | code++; | | 347 | code++; |
324 | continue; | | 348 | continue; |
325 | } | | 349 | } |
326 | i = 1; | | 350 | i = 1; |
327 | while(code + i < FONT_CODES && | | 351 | while(code + i < FONT_CODES && |
328 | fontIndex(font, code + i) == index + i) { | | 352 | fontIndex(font, code + i) == index + i) { |
329 | i++; | | 353 | i++; |
330 | } | | 354 | } |
331 | cmap = malloc(sizeof(CmapRec)); | | 355 | cmap = malloc(sizeof(CmapRec)); |
332 | if(cmap == NULL) | | 356 | if(cmap == NULL) |
333 | return NULL; | | 357 | return NULL; |
334 | cmap->startCode = code; | | 358 | cmap->startCode = code; |
335 | cmap->endCode = code + i - 1; | | 359 | cmap->endCode = code + i - 1; |
336 | cmap->index = index; | | 360 | cmap->index = index; |
337 | cmap->next = NULL; | | 361 | cmap->next = NULL; |
338 | cmap->maxindex = 0; | | 362 | cmap->maxindex = 0; |
339 | if(maxindex < index + i - 1) | | 363 | if(maxindex < index + i - 1) |
340 | maxindex = index + i - 1; | | 364 | maxindex = index + i - 1; |
341 | if(cmap_head == NULL) | | 365 | if(cmap_head == NULL) |
342 | cmap_head = cmap; | | 366 | cmap_head = cmap; |
343 | else | | 367 | else |
344 | cmap_last->next = cmap; | | 368 | cmap_last->next = cmap; |
345 | cmap_last = cmap; | | 369 | cmap_last = cmap; |
346 | | | 370 | |
347 | code += i; | | 371 | code += i; |
348 | } | | 372 | } |
349 | cmap_head->maxindex = maxindex; | | 373 | cmap_head->maxindex = maxindex; |
350 | cmap_head->inverse = calloc(maxindex + 1, sizeof(int)); | | 374 | cmap_head->inverse = calloc(maxindex + 1, sizeof(int)); |
351 | cmap = cmap_head; | | 375 | cmap = cmap_head; |
352 | while(cmap) { | | 376 | while(cmap) { |
353 | for(i = cmap->index; | | 377 | for(i = cmap->index; |
354 | i <= cmap->endCode - cmap->startCode + cmap->index; i++) { | | 378 | i <= cmap->endCode - cmap->startCode + cmap->index; i++) { |
355 | cmap_head->inverse[i] = | | 379 | cmap_head->inverse[i] = |
356 | i - cmap->index + cmap->startCode; | | 380 | i - cmap->index + cmap->startCode; |
357 | } | | 381 | } |
358 | cmap = cmap->next; | | 382 | cmap = cmap->next; |
359 | } | | 383 | } |
360 | | | 384 | |
361 | return cmap_head; | | 385 | return cmap_head; |
362 | } | | 386 | } |
363 | | | 387 | |
364 | int | | 388 | int |
365 | findIndex(CmapPtr cmap_head, int code) | | 389 | findIndex(CmapPtr cmap_head, int code) |
366 | { | | 390 | { |
367 | CmapPtr cmap; | | 391 | CmapPtr cmap; |
368 | cmap = cmap_head; | | 392 | cmap = cmap_head; |
369 | while(cmap) { | | 393 | while(cmap) { |
370 | if(cmap->endCode > code) | | 394 | if(cmap->endCode > code) |
371 | return -1; | | 395 | return -1; |
372 | if(cmap->startCode <= code) | | 396 | if(cmap->startCode <= code) |
373 | return cmap->index + code - cmap->startCode; | | 397 | return cmap->index + code - cmap->startCode; |
374 | cmap = cmap->next; | | 398 | cmap = cmap->next; |
375 | } | | 399 | } |
376 | return -1; | | 400 | return -1; |
377 | } | | 401 | } |
378 | | | 402 | |
379 | int | | 403 | int |
380 | findCode(CmapPtr cmap_head, int index) | | 404 | findCode(CmapPtr cmap_head, int index) |
381 | { | | 405 | { |
382 | if(index < 0 || index > cmap_head->maxindex) | | 406 | if(index < 0 || index > cmap_head->maxindex) |
383 | return -1; | | 407 | return -1; |
384 | return cmap_head->inverse[index]; | | 408 | return cmap_head->inverse[index]; |
385 | | | 409 | |
386 | } | | 410 | } |
387 | | | 411 | |
388 | int | | 412 | int |
389 | maxIndex(CmapPtr cmap_head) | | 413 | maxIndex(CmapPtr cmap_head) |
390 | { | | 414 | { |
391 | return cmap_head->maxindex; | | 415 | return cmap_head->maxindex; |
392 | } | | 416 | } |
393 | | | 417 | |
394 | BitmapPtr | | 418 | BitmapPtr |
395 | strikeBitmapIndex(StrikePtr strike, CmapPtr cmap, int index) | | 419 | strikeBitmapIndex(StrikePtr strike, CmapPtr cmap, int index) |
396 | { | | 420 | { |
397 | int code = findCode(cmap, index); | | 421 | int code = findCode(cmap, index); |
398 | if(code < 0) | | 422 | if(code < 0) |
399 | return NULL; | | 423 | return NULL; |
400 | | | 424 | |
401 | return STRIKE_BITMAP(strike, code); | | 425 | return STRIKE_BITMAP(strike, code); |
402 | } | | 426 | } |
403 | | | 427 | |
404 | void | | 428 | int |
405 | strikeMetrics(StrikePtr strike, | | 429 | strikeMaxWidth(StrikePtr strike) |
406 | int *width_max_return, | | | |
407 | int *x_min_return, int *y_min_return, | | | |
408 | int *x_max_return, int *y_max_return) | | | |
409 | { | | 430 | { |
410 | BitmapPtr bitmap; | | 431 | BitmapPtr bitmap; |
411 | int i; | | 432 | int i; |
412 | int width_max = 0; | | 433 | int width_max = 0; |
413 | int x_min = 10000; | | | |
414 | int y_min = 10000; | | | |
415 | int x_max = -10000; | | | |
416 | int y_max = -10000; | | | |
417 | | | 434 | |
418 | for(i = 0; i < FONT_CODES; i++) { | | 435 | for(i = 0; i < FONT_CODES; i++) { |
419 | bitmap = STRIKE_BITMAP(strike, i); | | 436 | bitmap = STRIKE_BITMAP(strike, i); |
420 | if(!bitmap) | | 437 | if(!bitmap) |
421 | continue; | | 438 | continue; |
422 | if(bitmap->advanceWidth > width_max) | | 439 | if(bitmap->advanceWidth > width_max) |
423 | width_max = bitmap->advanceWidth; | | 440 | width_max = bitmap->advanceWidth; |
424 | if(bitmap->horiBearingX < x_min) | | | |
425 | x_min = bitmap->horiBearingX; | | | |
426 | if(bitmap->horiBearingY > y_max) | | | |
427 | y_max = bitmap->horiBearingY; | | | |
428 | if(bitmap->horiBearingX + bitmap->width > x_max) | | | |
429 | x_max = bitmap->horiBearingX + bitmap->width; | | | |
430 | if(bitmap->horiBearingY - bitmap->height < y_min) | | | |
431 | y_min = bitmap->horiBearingY - bitmap->height; | | | |
432 | } | | 441 | } |
433 | | | 442 | |
434 | if(width_max_return) *width_max_return = width_max; | | 443 | return width_max; |
435 | if(x_min_return) *x_min_return = x_min; | | | |
436 | if(y_min_return) *y_min_return = y_min; | | | |
437 | if(x_max_return) *x_max_return = x_max; | | | |
438 | if(y_max_return) *y_max_return = y_max; | | | |
439 | } | | 444 | } |
440 | | | 445 | |
441 | int | | 446 | int |
442 | glyphMetrics(FontPtr font, int code, | | 447 | glyphMetrics(FontPtr font, int code, |
443 | int *width_return, | | 448 | int *width_return, |
444 | int *x_min_return, int *y_min_return, | | 449 | int *x_min_return, int *y_min_return, |
445 | int *x_max_return, int *y_max_return) | | 450 | int *x_max_return, int *y_max_return) |
446 | { | | 451 | { |
447 | StrikePtr strike; | | 452 | StrikePtr strike; |
448 | BitmapPtr bitmap; | | 453 | BitmapPtr bitmap; |
449 | | | 454 | |
450 | strike = font->strikes; | | 455 | strike = font->strikes; |
451 | while(strike) { | | 456 | while(strike) { |
452 | bitmap = STRIKE_BITMAP(strike, code); | | 457 | bitmap = STRIKE_BITMAP(strike, code); |
453 | if(bitmap) { | | 458 | if(bitmap) { |
454 | if(width_return) | | 459 | if(width_return) |
455 | *width_return = | | 460 | *width_return = |
456 | (((float)bitmap->advanceWidth + 0.5) / strike->sizeX) * | | 461 | (((float)bitmap->advanceWidth) / strike->sizeX) * |
457 | TWO_SIXTEENTH; | | 462 | TWO_SIXTEENTH; |
458 | if(x_min_return) | | 463 | if(x_min_return) |
459 | *x_min_return = | | 464 | *x_min_return = |
460 | ((float)bitmap->horiBearingX / strike->sizeX) * | | 465 | ((float)bitmap->horiBearingX / strike->sizeX) * |
461 | TWO_SIXTEENTH; | | 466 | TWO_SIXTEENTH; |
462 | if(y_min_return) | | 467 | if(y_min_return) |
463 | *y_min_return = | | 468 | *y_min_return = |
464 | (((float)bitmap->horiBearingY - bitmap->height) | | 469 | (((float)bitmap->horiBearingY - bitmap->height) |
465 | / strike->sizeY) * TWO_SIXTEENTH; | | 470 | / strike->sizeY) * TWO_SIXTEENTH; |
466 | /* For the following two, 0.9 instead of 0.5 might make | | | |
467 | more sense. However, using different rounding rules | | | |
468 | for x_max and awidth causes problems for detecting | | | |
469 | charcell fonts. */ | | | |
470 | if(x_max_return) | | 471 | if(x_max_return) |
471 | *x_max_return = | | 472 | *x_max_return = |
472 | (((float)bitmap->horiBearingX + bitmap->width + 0.5) | | 473 | (((float)bitmap->horiBearingX + bitmap->width) |
473 | / strike->sizeX) * TWO_SIXTEENTH; | | 474 | / strike->sizeX) * TWO_SIXTEENTH; |
474 | if(y_max_return) | | 475 | if(y_max_return) |
475 | *y_max_return = | | 476 | *y_max_return = |
476 | (((float)bitmap->horiBearingY + 0.5) / strike->sizeY) * | | 477 | (((float)bitmap->horiBearingY) / strike->sizeY) * |
477 | TWO_SIXTEENTH; | | 478 | TWO_SIXTEENTH; |
478 | return 1; | | 479 | return 1; |
479 | } | | 480 | } |
480 | strike = strike->next; | | 481 | strike = strike->next; |
481 | } | | 482 | } |
482 | | | 483 | |
483 | return -1; | | 484 | return -1; |
484 | } | | 485 | } |
485 | | | | |
486 | void | | | |
487 | fontMetrics(FontPtr font, | | | |
488 | int *max_awidth_return, | | | |
489 | int *min_x_return, int *min_y_return, | | | |
490 | int *max_x_return, int *max_y_return) | | | |
491 | { | | | |
492 | int i, rc; | | | |
493 | int max_awidth = 0; | | | |
494 | int min_x = 10000 * 65536, min_y = 10000 * 65536; | | | |
495 | int max_x = -10000 * 65536, max_y = -10000 * 65536; | | | |
496 | for(i = 0; i < FONT_CODES; i++) { | | | |
497 | int awidth, x0, y0, x1, y1; | | | |
498 | rc = glyphMetrics(font, i, &awidth, &x0, &y0, &x1, &y1); | | | |
499 | if(rc < 0) | | | |
500 | continue; | | | |
501 | if(awidth > max_awidth) | | | |
502 | max_awidth = awidth; | | | |
503 | if(x0 < min_x) min_x = x0; | | | |
504 | if(y0 < min_y) min_y = y0; | | | |
505 | if(x1 > max_x) max_x = x1; | | | |
506 | if(y1 > max_y) max_y = y1; | | | |
507 | } | | | |
508 | if(max_awidth_return) *max_awidth_return = max_awidth; | | | |
509 | if(min_x_return) *min_x_return = min_x; | | | |
510 | if(min_y_return) *min_y_return = min_y; | | | |
511 | if(max_x_return) *max_x_return = max_x; | | | |
512 | if(max_y_return) *max_y_return = max_y; | | | |
513 | } | | | |
514 | | | | |