File: | FreeType/ftfuncs.c |
Location: | line 2878, column 31 |
Description: | Access to field 'lastRow' results in a dereference of a null pointer (loaded from variable 'info') |
1 | /* | ||
2 | Copyright (c) 1997 by Mark Leisher | ||
3 | Copyright (c) 1998-2003 by Juliusz Chroboczek | ||
4 | Copyright (c) 1998 Go Watanabe, All rights reserved. | ||
5 | Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved. | ||
6 | Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved. | ||
7 | Copyright (c) 1998 X-TrueType Server Project, All rights reserved. | ||
8 | Copyright (c) 2003-2004 After X-TT Project, All rights reserved. | ||
9 | |||
10 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
11 | of this software and associated documentation files (the "Software"), to deal | ||
12 | in the Software without restriction, including without limitation the rights | ||
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
14 | copies of the Software, and to permit persons to whom the Software is | ||
15 | furnished to do so, subject to the following conditions: | ||
16 | |||
17 | The above copyright notice and this permission notice shall be included in | ||
18 | all copies or substantial portions of the Software. | ||
19 | |||
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
26 | THE SOFTWARE. | ||
27 | */ | ||
28 | |||
29 | #ifdef HAVE_CONFIG_H1 | ||
30 | #include <config.h> | ||
31 | #endif | ||
32 | #include <X11/fonts/fontmisc.h> | ||
33 | |||
34 | #include <string.h> | ||
35 | #include <math.h> | ||
36 | #include <ctype.h> | ||
37 | |||
38 | #include <X11/fonts/fntfilst.h> | ||
39 | #include <X11/fonts/fontutil.h> | ||
40 | #include <X11/fonts/FSproto.h> | ||
41 | #include <ft2build.h> | ||
42 | #include FT_FREETYPE_H<freetype/freetype.h> | ||
43 | #include FT_SIZES_H<freetype/ftsizes.h> | ||
44 | #include FT_TRUETYPE_IDS_H<freetype/ttnameid.h> | ||
45 | #include FT_TRUETYPE_TABLES_H<freetype/tttables.h> | ||
46 | #include FT_TYPE1_TABLES_H<freetype/t1tables.h> | ||
47 | #include FT_XFREE86_H<freetype/ftxf86.h> | ||
48 | #include FT_BBOX_H<freetype/ftbbox.h> | ||
49 | #include FT_TRUETYPE_TAGS_H<freetype/tttags.h> | ||
50 | /* | ||
51 | * If you want to use FT_Outline_Get_CBox instead of | ||
52 | * FT_Outline_Get_BBox, define here. | ||
53 | */ | ||
54 | /* #define USE_GET_CBOX */ | ||
55 | #ifdef USE_GET_CBOX | ||
56 | #include FT_OUTLINE_H<freetype/ftoutln.h> | ||
57 | #endif | ||
58 | |||
59 | #include <X11/fonts/fontenc.h> | ||
60 | #include "ft.h" | ||
61 | #include "ftfuncs.h" | ||
62 | #include "xttcap.h" | ||
63 | |||
64 | /* Work around FreeType bug */ | ||
65 | #define WORK_AROUND_UPM2048 2048 | ||
66 | |||
67 | #ifndef True(-1) | ||
68 | #define True(-1) (-1) | ||
69 | #endif /* True */ | ||
70 | #ifndef False(0) | ||
71 | #define False(0) (0) | ||
72 | #endif /* False */ | ||
73 | |||
74 | #define FLOOR64(x)((x) & -64) ((x) & -64) | ||
75 | #define CEIL64(x)(((x) + 64 - 1) & -64) (((x) + 64 - 1) & -64) | ||
76 | |||
77 | /* | ||
78 | * If you want very lazy method(vl=y) AS DEFAULT when | ||
79 | * handling large charset, define here. | ||
80 | */ | ||
81 | /* #define DEFAULT_VERY_LAZY 1 */ /* Always */ | ||
82 | #define DEFAULT_VERY_LAZY2 2 /* Multi-byte only */ | ||
83 | /* #define DEFAULT_VERY_LAZY 256 */ /* Unicode only */ | ||
84 | |||
85 | /* Does the X accept noSuchChar? */ | ||
86 | #define X_ACCEPTS_NO_SUCH_CHAR | ||
87 | /* Does the XAA accept NULL noSuchChar.bits?(dangerous) */ | ||
88 | /* #define XAA_ACCEPTS_NULL_BITS */ | ||
89 | |||
90 | #ifdef X_ACCEPTS_NO_SUCH_CHAR | ||
91 | static CharInfoRec noSuchChar = { /* metrics */{0,0,0,0,0,0}, | ||
92 | /* bits */ NULL((void*)0) }; | ||
93 | #endif | ||
94 | |||
95 | /* The propery names for all the XLFD properties. */ | ||
96 | |||
97 | static const char *xlfd_props[] = { | ||
98 | "FOUNDRY", | ||
99 | "FAMILY_NAME", | ||
100 | "WEIGHT_NAME", | ||
101 | "SLANT", | ||
102 | "SETWIDTH_NAME", | ||
103 | "ADD_STYLE_NAME", | ||
104 | "PIXEL_SIZE", | ||
105 | "POINT_SIZE", | ||
106 | "RESOLUTION_X", | ||
107 | "RESOLUTION_Y", | ||
108 | "SPACING", | ||
109 | "AVERAGE_WIDTH", | ||
110 | "CHARSET_REGISTRY", | ||
111 | "CHARSET_ENCODING", | ||
112 | }; | ||
113 | |||
114 | |||
115 | /* read 2-byte value from a SFNT table */ | ||
116 | static FT_UShort | ||
117 | sfnt_get_ushort( FT_Face face, | ||
118 | FT_ULong table_tag, | ||
119 | FT_ULong table_offset ) | ||
120 | { | ||
121 | FT_Byte buff[2]; | ||
122 | FT_ULong len = sizeof(buff); | ||
123 | FT_UShort result = 0; | ||
124 | |||
125 | if ( !FT_Load_Sfnt_Table( face, table_tag, table_offset, buff, &len ) ) | ||
126 | result = (FT_UShort)( (buff[0] << 8) | buff[1] ); | ||
127 | |||
128 | return result; | ||
129 | } | ||
130 | |||
131 | #define sfnt_get_short(f,t,o)((FT_Short)sfnt_get_ushort((f),(t),(o))) ((FT_Short)sfnt_get_ushort((f),(t),(o))) | ||
132 | |||
133 | |||
134 | static int ftypeInitP = 0; /* is the engine initialised? */ | ||
135 | FT_Library ftypeLibrary; | ||
136 | |||
137 | static FTFacePtr faceTable[NUMFACEBUCKETS32]; | ||
138 | |||
139 | static unsigned | ||
140 | hash(char *string) | ||
141 | { | ||
142 | int i; | ||
143 | unsigned u = 0; | ||
144 | for(i = 0; string[i] != '\0'; i++) | ||
145 | u = (u<<5) + (u >> (NUMFACEBUCKETS32 - 5)) + (unsigned char)string[i]; | ||
146 | return u; | ||
147 | } | ||
148 | |||
149 | static int | ||
150 | ifloor(int x, int y) | ||
151 | { | ||
152 | if(x >= 0) | ||
153 | return x/y; | ||
154 | else | ||
155 | return x/y - 1; | ||
156 | } | ||
157 | |||
158 | static int | ||
159 | iceil(int x, int y) | ||
160 | { | ||
161 | return ifloor(x + y - 1, y); | ||
162 | } | ||
163 | |||
164 | static int | ||
165 | FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber) | ||
166 | { | ||
167 | FT_Error ftrc; | ||
168 | int bucket; | ||
169 | FTFacePtr face, otherFace; | ||
170 | |||
171 | if (!ftypeInitP) { | ||
172 | ftrc = FT_Init_FreeType(&ftypeLibrary); | ||
173 | if (ftrc != 0) { | ||
174 | ErrorF("FreeType: error initializing ftypeEngine: %d\n", ftrc); | ||
175 | return AllocError80; | ||
176 | } | ||
177 | ftypeInitP = 1; | ||
178 | } | ||
179 | |||
180 | /* Try to find a matching face in the hashtable */ | ||
181 | bucket = hash(FTFileName)%NUMFACEBUCKETS32; | ||
182 | otherFace = faceTable[bucket]; | ||
183 | while(otherFace) { | ||
184 | if( strcmp(otherFace->filename, FTFileName) == 0 ) break; | ||
185 | otherFace = otherFace->next; | ||
186 | } | ||
187 | if(otherFace) { | ||
188 | MUMBLE("Returning cached face: %s\n", otherFace->filename); | ||
189 | *facep = otherFace; | ||
190 | return Successful85; | ||
191 | } | ||
192 | |||
193 | /* No cached match; need to make a new one */ | ||
194 | face = calloc(1, sizeof(FTFaceRec)); | ||
195 | if (face == NULL((void*)0)) { | ||
196 | return AllocError80; | ||
197 | } | ||
198 | |||
199 | face->filename = strdup(FTFileName); | ||
200 | if (face->filename == NULL((void*)0)) { | ||
201 | free(face); | ||
202 | return AllocError80; | ||
203 | } | ||
204 | |||
205 | ftrc = FT_New_Face(ftypeLibrary, realFileName, faceNumber, &face->face); | ||
206 | if(ftrc != 0) { | ||
207 | ErrorF("FreeType: couldn't open face %s: %d\n", FTFileName, ftrc); | ||
208 | free(face->filename); | ||
209 | free(face); | ||
210 | return BadFontName83; | ||
211 | } | ||
212 | |||
213 | face->bitmap = ((face->face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 )) == 0); | ||
214 | if(!face->bitmap) { | ||
215 | TT_MaxProfile *maxp; | ||
216 | maxp = FT_Get_Sfnt_Table(face->face, ft_sfnt_maxp); | ||
217 | if(maxp && maxp->maxContours == 0) | ||
218 | face->bitmap = 1; | ||
219 | } | ||
220 | |||
221 | face->num_hmetrics = (FT_UInt) sfnt_get_ushort( face->face, | ||
222 | TTAG_hhea(FT_Tag) ( ( (FT_ULong)'h' << 24 ) | ( (FT_ULong)'h' << 16 ) | ( (FT_ULong)'e' << 8 ) | (FT_ULong)'a' ), 34 ); | ||
223 | |||
224 | /* Insert face in hashtable and return it */ | ||
225 | face->next = faceTable[bucket]; | ||
226 | faceTable[bucket] = face; | ||
227 | *facep = face; | ||
228 | return Successful85; | ||
229 | } | ||
230 | |||
231 | static void | ||
232 | FreeTypeFreeFace(FTFacePtr face) | ||
233 | { | ||
234 | int bucket; | ||
235 | FTFacePtr otherFace; | ||
236 | |||
237 | if(!face->instances) { | ||
238 | bucket = hash(face->filename) % NUMFACEBUCKETS32; | ||
239 | if(faceTable[bucket] == face) | ||
240 | faceTable[bucket] = face->next; | ||
241 | else { | ||
242 | otherFace = faceTable[bucket]; | ||
243 | while(otherFace) { | ||
244 | if(otherFace->next == face) | ||
245 | break; | ||
246 | otherFace = otherFace->next; | ||
247 | } | ||
248 | if(otherFace && otherFace->next) | ||
249 | otherFace->next = otherFace->next->next; | ||
250 | else | ||
251 | ErrorF("FreeType: freeing unknown face\n"); | ||
252 | } | ||
253 | MUMBLE("Closing face: %s\n", face->filename); | ||
254 | FT_Done_Face(face->face); | ||
255 | free(face->filename); | ||
256 | free(face); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | static int | ||
261 | TransEqual(FTNormalisedTransformationPtr t1, FTNormalisedTransformationPtr t2) | ||
262 | { | ||
263 | if(t1->scale != t2->scale) | ||
264 | return 0; | ||
265 | else if(t1->xres != t2->xres || t1->yres != t2->yres) | ||
266 | return 0; | ||
267 | else if(t1->nonIdentity != t2->nonIdentity) | ||
268 | return 0; | ||
269 | else if(t1->nonIdentity && t2->nonIdentity) { | ||
270 | return | ||
271 | t1->matrix.xx == t2->matrix.xx && | ||
272 | t1->matrix.yx == t2->matrix.yx && | ||
273 | t1->matrix.yy == t2->matrix.yy && | ||
274 | t1->matrix.xy == t2->matrix.xy; | ||
275 | } else | ||
276 | return 1; | ||
277 | } | ||
278 | |||
279 | static int | ||
280 | BitmapFormatEqual(FontBitmapFormatPtr f1, FontBitmapFormatPtr f2) | ||
281 | { | ||
282 | return | ||
283 | f1->bit == f2->bit && | ||
284 | f1->byte == f2->byte && | ||
285 | f1->glyph == f2->glyph; | ||
286 | } | ||
287 | |||
288 | static int | ||
289 | TTCapEqual(struct TTCapInfo *t1, struct TTCapInfo *t2) | ||
290 | { | ||
291 | return | ||
292 | t1->autoItalic == t2->autoItalic && | ||
293 | t1->scaleWidth == t2->scaleWidth && | ||
294 | t1->scaleBBoxWidth == t2->scaleBBoxWidth && | ||
295 | t1->scaleBBoxHeight == t2->scaleBBoxHeight && | ||
296 | t1->doubleStrikeShift == t2->doubleStrikeShift && | ||
297 | t1->adjustBBoxWidthByPixel == t2->adjustBBoxWidthByPixel && | ||
298 | t1->adjustLeftSideBearingByPixel == t2->adjustLeftSideBearingByPixel && | ||
299 | t1->adjustRightSideBearingByPixel == t2->adjustRightSideBearingByPixel && | ||
300 | t1->flags == t2->flags && | ||
301 | t1->scaleBitmap == t2->scaleBitmap && | ||
302 | /* | ||
303 | If we use forceConstantSpacing, | ||
304 | we *MUST* allocate new instance. | ||
305 | */ | ||
306 | t1->forceConstantSpacingEnd < 0 && | ||
307 | t2->forceConstantSpacingEnd < 0; | ||
308 | } | ||
309 | |||
310 | static int | ||
311 | FTInstanceMatch(FTInstancePtr instance, | ||
312 | char *FTFileName, FTNormalisedTransformationPtr trans, | ||
313 | int spacing, FontBitmapFormatPtr bmfmt, | ||
314 | struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags) | ||
315 | { | ||
316 | if(strcmp(instance->face->filename, FTFileName) != 0) { | ||
317 | return 0; | ||
318 | } else if(!TransEqual(&instance->transformation, trans)) { | ||
319 | return 0; | ||
320 | } else if( spacing != instance->spacing ) { | ||
321 | return 0; | ||
322 | } else if( load_flags != instance->load_flags ) { | ||
323 | return 0; | ||
324 | } else if(!BitmapFormatEqual(&instance->bmfmt, bmfmt)) { | ||
325 | return 0; | ||
326 | } else if(!TTCapEqual(&instance->ttcap, tmp_ttcap)) { | ||
327 | return 0; | ||
328 | } else { | ||
329 | return 1; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static int | ||
334 | FreeTypeActivateInstance(FTInstancePtr instance) | ||
335 | { | ||
336 | FT_Error ftrc; | ||
337 | if(instance->face->active_instance == instance) | ||
338 | return Successful85; | ||
339 | |||
340 | ftrc = FT_Activate_Size(instance->size); | ||
341 | if(ftrc != 0) { | ||
342 | instance->face->active_instance = NULL((void*)0); | ||
343 | ErrorF("FreeType: couldn't activate instance: %d\n", ftrc); | ||
344 | return FTtoXReturnCode(ftrc); | ||
345 | } | ||
346 | FT_Set_Transform(instance->face->face, | ||
347 | instance->transformation.nonIdentity ? | ||
348 | &instance->transformation.matrix : 0, | ||
349 | 0); | ||
350 | |||
351 | instance->face->active_instance = instance; | ||
352 | return Successful85; | ||
353 | } | ||
354 | |||
355 | static int | ||
356 | FTFindSize(FT_Face face, FTNormalisedTransformationPtr trans, | ||
357 | int *x_return, int *y_return) | ||
358 | { | ||
359 | int tx, ty, x, y; | ||
360 | int i, j; | ||
361 | int d, dd; | ||
362 | |||
363 | if(trans->nonIdentity) | ||
364 | return BadFontName83; | ||
365 | |||
366 | tx = (int)(trans->scale * trans->xres / 72.0 + 0.5); | ||
367 | ty = (int)(trans->scale * trans->yres / 72.0 + 0.5); | ||
368 | |||
369 | d = 100; | ||
370 | j = -1; | ||
371 | for(i = 0; i < face->num_fixed_sizes; i++) { | ||
372 | x = face->available_sizes[i].width; | ||
373 | y = face->available_sizes[i].height; | ||
374 | if(ABS(x - tx)((x - tx) >= 0 ? (x - tx) : -(x - tx)) <= 1 && ABS(y - ty)((y - ty) >= 0 ? (y - ty) : -(y - ty)) <= 1) { | ||
375 | dd = ABS(x - tx)((x - tx) >= 0 ? (x - tx) : -(x - tx)) * ABS(x - tx)((x - tx) >= 0 ? (x - tx) : -(x - tx)) + ABS(y - ty)((y - ty) >= 0 ? (y - ty) : -(y - ty)) * ABS(y - ty)((y - ty) >= 0 ? (y - ty) : -(y - ty)); | ||
376 | if(dd < d) { | ||
377 | j = i; | ||
378 | d = dd; | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | if(j < 0) | ||
383 | return BadFontName83; | ||
384 | |||
385 | *x_return = face->available_sizes[j].width; | ||
386 | *y_return = face->available_sizes[j].height; | ||
387 | return Successful85; | ||
388 | } | ||
389 | |||
390 | static int | ||
391 | FreeTypeOpenInstance(FTInstancePtr *instance_return, FTFacePtr face, | ||
392 | char *FTFileName, FTNormalisedTransformationPtr trans, | ||
393 | int spacing, FontBitmapFormatPtr bmfmt, | ||
394 | struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags) | ||
395 | { | ||
396 | FT_Error ftrc; | ||
397 | int xrc; | ||
398 | FTInstancePtr instance, otherInstance; | ||
399 | |||
400 | /* Search for a matching instance */ | ||
401 | for(otherInstance = face->instances; | ||
402 | otherInstance; | ||
403 | otherInstance = otherInstance->next) { | ||
404 | if(FTInstanceMatch(otherInstance, FTFileName, trans, spacing, bmfmt, | ||
405 | tmp_ttcap, load_flags)) break; | ||
406 | } | ||
407 | if(otherInstance) { | ||
408 | MUMBLE("Returning cached instance\n"); | ||
409 | otherInstance->refcount++; | ||
410 | *instance_return = otherInstance; | ||
411 | return Successful85; | ||
412 | } | ||
413 | |||
414 | /* None matching found */ | ||
415 | instance = malloc(sizeof(FTInstanceRec)); | ||
416 | if(instance == NULL((void*)0)) { | ||
417 | return AllocError80; | ||
418 | } | ||
419 | |||
420 | instance->refcount = 1; | ||
421 | instance->face = face; | ||
422 | |||
423 | instance->load_flags = load_flags; | ||
424 | instance->spacing = spacing; /* Actual spacing */ | ||
425 | instance->pixel_size =0; | ||
426 | instance->pixel_width_unit_x =0; | ||
427 | instance->pixel_width_unit_y =0; | ||
428 | instance->charcellMetrics = NULL((void*)0); | ||
429 | instance->averageWidth = 0; | ||
430 | instance->rawAverageWidth = 0; | ||
431 | instance->forceConstantMetrics = NULL((void*)0); | ||
432 | |||
433 | instance->transformation = *trans; | ||
434 | instance->bmfmt = *bmfmt; | ||
435 | instance->glyphs = NULL((void*)0); | ||
436 | instance->available = NULL((void*)0); | ||
437 | |||
438 | if( 0 <= tmp_ttcap->forceConstantSpacingEnd ) | ||
439 | instance->nglyphs = 2 * instance->face->face->num_glyphs; | ||
440 | else | ||
441 | instance->nglyphs = instance->face->face->num_glyphs; | ||
442 | |||
443 | /* Store the TTCap info. */ | ||
444 | memcpy((char*)&instance->ttcap, (char*)tmp_ttcap, | ||
445 | sizeof(struct TTCapInfo)); | ||
446 | |||
447 | ftrc = FT_New_Size(instance->face->face, &instance->size); | ||
448 | if(ftrc != 0) { | ||
449 | ErrorF("FreeType: couldn't create size object: %d\n", ftrc); | ||
450 | free(instance); | ||
451 | return FTtoXReturnCode(ftrc); | ||
452 | } | ||
453 | FreeTypeActivateInstance(instance); | ||
454 | if(!face->bitmap) { | ||
455 | ftrc = FT_Set_Char_Size(instance->face->face, | ||
456 | (int)(trans->scale*(1<<6) + 0.5), | ||
457 | (int)(trans->scale*(1<<6) + 0.5), | ||
458 | trans->xres, trans->yres); | ||
459 | } else { | ||
460 | int xsize, ysize; | ||
461 | xrc = FTFindSize(face->face, trans, &xsize, &ysize); | ||
462 | if(xrc != Successful85) { | ||
463 | free(instance); | ||
464 | return xrc; | ||
465 | } | ||
466 | ftrc = FT_Set_Pixel_Sizes(instance->face->face, xsize, ysize); | ||
467 | } | ||
468 | if(ftrc != 0) { | ||
469 | FT_Done_Size(instance->size); | ||
470 | free(instance); | ||
471 | return FTtoXReturnCode(ftrc); | ||
472 | } | ||
473 | |||
474 | if( FT_IS_SFNT( face->face )( face->face->face_flags & ( 1L << 3 ) ) ) { | ||
475 | #if 1 | ||
476 | FT_F26Dot6 tt_char_width, tt_char_height, tt_dim_x, tt_dim_y; | ||
477 | FT_UInt nn; | ||
478 | |||
479 | instance->strike_index=0xFFFFU; | ||
480 | |||
481 | tt_char_width = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5); | ||
482 | tt_char_height = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5); | ||
483 | |||
484 | tt_dim_x = FLOOR64( ( tt_char_width * trans->xres + 36 ) / 72 + 32 )((( tt_char_width * trans->xres + 36 ) / 72 + 32) & -64 ); | ||
485 | tt_dim_y = FLOOR64( ( tt_char_height * trans->yres + 36 ) / 72 + 32 )((( tt_char_height * trans->yres + 36 ) / 72 + 32) & - 64); | ||
486 | |||
487 | if ( tt_dim_x && !tt_dim_y ) | ||
488 | tt_dim_y = tt_dim_x; | ||
489 | else if ( !tt_dim_x && tt_dim_y ) | ||
490 | tt_dim_x = tt_dim_y; | ||
491 | |||
492 | for ( nn = 0; nn < face->face->num_fixed_sizes; nn++ ) | ||
493 | { | ||
494 | FT_Bitmap_Size* sz = &face->face->available_sizes[nn]; | ||
495 | |||
496 | if ( tt_dim_x == FLOOR64(sz->x_ppem + 32)((sz->x_ppem + 32) & -64) && tt_dim_y == FLOOR64(sz->y_ppem + 32)((sz->y_ppem + 32) & -64) ) | ||
497 | { | ||
498 | instance->strike_index = nn; | ||
499 | break; | ||
500 | } | ||
501 | } | ||
502 | #else | ||
503 | /* See Set_Char_Sizes() in ttdriver.c */ | ||
504 | FT_Error err; | ||
505 | TT_Face tt_face; | ||
506 | FT_Long tt_dim_x, tt_dim_y; | ||
507 | FT_UShort tt_x_ppem, tt_y_ppem; | ||
508 | FT_F26Dot6 tt_char_width, tt_char_height; | ||
509 | SFNT_Service sfnt; | ||
510 | tt_face=(TT_Face)face->face; | ||
511 | tt_char_width = (int)(trans->scale*(1<<6) + 0.5); | ||
512 | tt_char_height = (int)(trans->scale*(1<<6) + 0.5); | ||
513 | if ( ( tt_face->header.Flags & 8 ) != 0 ) { | ||
514 | tt_dim_x = ( ( tt_char_width * trans->xres + (36+32*72) ) / 72 ) & -64; | ||
515 | tt_dim_y = ( ( tt_char_height * trans->yres + (36+32*72) ) / 72 ) & -64; | ||
516 | } | ||
517 | else{ | ||
518 | tt_dim_x = ( ( tt_char_width * trans->xres + 36 ) / 72 ); | ||
519 | tt_dim_y = ( ( tt_char_height * trans->yres + 36 ) / 72 ); | ||
520 | } | ||
521 | tt_x_ppem = (FT_UShort)( tt_dim_x >> 6 ); | ||
522 | tt_y_ppem = (FT_UShort)( tt_dim_y >> 6 ); | ||
523 | /* See Reset_SBit_Size() in ttobjs.c */ | ||
524 | sfnt = (SFNT_Service)tt_face->sfnt; | ||
525 | err = sfnt->set_sbit_strike(tt_face,tt_x_ppem,tt_y_ppem,&instance->strike_index); | ||
526 | if ( err ) instance->strike_index=0xFFFFU; | ||
527 | #endif | ||
528 | } | ||
529 | |||
530 | /* maintain a linked list of instances */ | ||
531 | instance->next = instance->face->instances; | ||
532 | instance->face->instances = instance; | ||
533 | |||
534 | *instance_return = instance; | ||
535 | return Successful85; | ||
536 | } | ||
537 | |||
538 | static void | ||
539 | FreeTypeFreeInstance(FTInstancePtr instance) | ||
540 | { | ||
541 | FTInstancePtr otherInstance; | ||
542 | |||
543 | if( instance == NULL((void*)0) ) return; | ||
544 | |||
545 | if(instance->face->active_instance == instance) | ||
546 | instance->face->active_instance = NULL((void*)0); | ||
547 | instance->refcount--; | ||
548 | if(instance->refcount <= 0) { | ||
549 | int i,j; | ||
550 | |||
551 | if(instance->face->instances == instance) | ||
552 | instance->face->instances = instance->next; | ||
553 | else { | ||
554 | for(otherInstance = instance->face->instances; | ||
555 | otherInstance; | ||
556 | otherInstance = otherInstance->next) | ||
557 | if(otherInstance->next == instance) { | ||
558 | otherInstance->next = instance->next; | ||
559 | break; | ||
560 | } | ||
561 | } | ||
562 | |||
563 | FT_Done_Size(instance->size); | ||
564 | FreeTypeFreeFace(instance->face); | ||
565 | |||
566 | if(instance->charcellMetrics) { | ||
567 | free(instance->charcellMetrics); | ||
568 | } | ||
569 | if(instance->forceConstantMetrics) { | ||
570 | free(instance->forceConstantMetrics); | ||
571 | } | ||
572 | if(instance->glyphs) { | ||
573 | for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE16); i++) { | ||
574 | if(instance->glyphs[i]) { | ||
575 | for(j = 0; j < FONTSEGMENTSIZE16; j++) { | ||
576 | if(instance->available[i][j] == | ||
577 | FT_AVAILABLE_RASTERISED3) | ||
578 | free(instance->glyphs[i][j].bits); | ||
579 | } | ||
580 | free(instance->glyphs[i]); | ||
581 | } | ||
582 | } | ||
583 | free(instance->glyphs); | ||
584 | } | ||
585 | if(instance->available) { | ||
586 | for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE16); i++) { | ||
587 | if(instance->available[i]) | ||
588 | free(instance->available[i]); | ||
589 | } | ||
590 | free(instance->available); | ||
591 | } | ||
592 | free(instance); | ||
593 | } | ||
594 | } | ||
595 | |||
596 | static int | ||
597 | FreeTypeInstanceFindGlyph(unsigned idx_in, int flags, FTInstancePtr instance, | ||
598 | CharInfoPtr **glyphs, int ***available, | ||
599 | int *found, int *segmentP, int *offsetP) | ||
600 | { | ||
601 | int segment, offset; | ||
602 | unsigned idx = idx_in; | ||
603 | |||
604 | if( 0 <= instance->ttcap.forceConstantSpacingEnd ){ | ||
605 | if( (flags & FT_FORCE_CONSTANT_SPACING0x08) ) | ||
606 | idx += instance->nglyphs / 2 ; | ||
607 | } | ||
608 | |||
609 | if(idx > instance->nglyphs) { | ||
610 | *found = 0; | ||
611 | return Successful85; | ||
612 | } | ||
613 | |||
614 | if(*available == NULL((void*)0)) { | ||
615 | *available = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE16), | ||
616 | sizeof(int *)); | ||
617 | if(*available == NULL((void*)0)) | ||
618 | return AllocError80; | ||
619 | } | ||
620 | |||
621 | segment = ifloor(idx, FONTSEGMENTSIZE16); | ||
622 | offset = idx - segment * FONTSEGMENTSIZE16; | ||
623 | |||
624 | if((*available)[segment] == NULL((void*)0)) { | ||
625 | (*available)[segment] = calloc(FONTSEGMENTSIZE16, sizeof(int *)); | ||
626 | if((*available)[segment] == NULL((void*)0)) | ||
627 | return AllocError80; | ||
628 | } | ||
629 | |||
630 | if(*glyphs == NULL((void*)0)) { | ||
631 | *glyphs = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE16), | ||
632 | sizeof(CharInfoPtr)); | ||
633 | if(*glyphs == NULL((void*)0)) | ||
634 | return AllocError80; | ||
635 | } | ||
636 | |||
637 | if((*glyphs)[segment] == NULL((void*)0)) { | ||
638 | (*glyphs)[segment] = malloc(sizeof(CharInfoRec) * FONTSEGMENTSIZE16); | ||
639 | if((*glyphs)[segment] == NULL((void*)0)) | ||
640 | return AllocError80; | ||
641 | } | ||
642 | |||
643 | *found = 1; | ||
644 | *segmentP = segment; | ||
645 | *offsetP = offset; | ||
646 | return Successful85; | ||
647 | } | ||
648 | |||
649 | static int | ||
650 | FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance) | ||
651 | { | ||
652 | int found, segment, offset; | ||
653 | int xrc; | ||
654 | int ***available; | ||
655 | CharInfoPtr **glyphs; | ||
656 | |||
657 | available = &instance->available; | ||
658 | glyphs = &instance->glyphs; | ||
659 | |||
660 | xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, glyphs, available, | ||
661 | &found, &segment, &offset); | ||
662 | if(xrc != Successful85) | ||
663 | return xrc; | ||
664 | |||
665 | if(!found || (*available)[segment][offset] == FT_AVAILABLE_NO1) { | ||
666 | *g = NULL((void*)0); | ||
667 | return Successful85; | ||
668 | } | ||
669 | |||
670 | if((*available)[segment][offset] == FT_AVAILABLE_RASTERISED3) { | ||
671 | *g = &(*glyphs)[segment][offset]; | ||
672 | return Successful85; | ||
673 | } | ||
674 | |||
675 | flags |= FT_GET_GLYPH_BOTH0x01; | ||
676 | |||
677 | xrc = FreeTypeRasteriseGlyph(idx, flags, | ||
678 | &(*glyphs)[segment][offset], instance, | ||
679 | (*available)[segment][offset] >= FT_AVAILABLE_METRICS2); | ||
680 | if(xrc != Successful85 && (*available)[segment][offset] >= FT_AVAILABLE_METRICS2) { | ||
681 | ErrorF("Warning: FreeTypeRasteriseGlyph() returns an error,\n"); | ||
682 | ErrorF("\tso the backend tries to set a white space.\n"); | ||
683 | xrc = FreeTypeRasteriseGlyph(idx, flags | FT_GET_DUMMY0x04, | ||
684 | &(*glyphs)[segment][offset], instance, | ||
685 | (*available)[segment][offset] >= FT_AVAILABLE_METRICS2); | ||
686 | } | ||
687 | if(xrc == Successful85) { | ||
688 | (*available)[segment][offset] = FT_AVAILABLE_RASTERISED3; | ||
689 | /* return the glyph */ | ||
690 | *g = &(*glyphs)[segment][offset]; | ||
691 | } | ||
692 | return xrc; | ||
693 | } | ||
694 | |||
695 | static int | ||
696 | FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags, | ||
697 | xCharInfo **metrics, FTInstancePtr instance ) | ||
698 | { | ||
699 | int xrc; | ||
700 | int found, segment, offset; | ||
701 | |||
702 | /* Char cell */ | ||
703 | if(instance->spacing == FT_CHARCELL2) { | ||
704 | *metrics = instance->charcellMetrics; | ||
705 | return Successful85; | ||
706 | } | ||
707 | /* Force constant metrics */ | ||
708 | if( flags & FT_FORCE_CONSTANT_SPACING0x08) { | ||
709 | *metrics = instance->forceConstantMetrics; | ||
710 | return Successful85; | ||
711 | } | ||
712 | |||
713 | /* Not char cell */ | ||
714 | |||
715 | xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, | ||
716 | &instance->glyphs, &instance->available, | ||
717 | &found, &segment, &offset); | ||
718 | if(xrc != Successful85) | ||
719 | return xrc; | ||
720 | if(!found) { | ||
721 | *metrics = NULL((void*)0); | ||
722 | return Successful85; | ||
723 | } | ||
724 | if( instance->available[segment][offset] == FT_AVAILABLE_NO1 ) { | ||
725 | *metrics = NULL((void*)0); | ||
726 | return Successful85; | ||
727 | } | ||
728 | |||
729 | if( instance->available[segment][offset] >= FT_AVAILABLE_METRICS2 ) { | ||
730 | *metrics = &instance->glyphs[segment][offset].metrics; | ||
731 | return Successful85; | ||
732 | } | ||
733 | |||
734 | flags |= FT_GET_GLYPH_METRICS_ONLY0x02; | ||
735 | |||
736 | xrc = FreeTypeRasteriseGlyph(idx, flags, | ||
737 | &instance->glyphs[segment][offset], | ||
738 | instance, 0); | ||
739 | if(xrc == Successful85) { | ||
740 | instance->available[segment][offset] = FT_AVAILABLE_METRICS2; | ||
741 | *metrics = &instance->glyphs[segment][offset].metrics; | ||
742 | } | ||
743 | return xrc; | ||
744 | } | ||
745 | |||
746 | /* | ||
747 | * Pseudo enbolding similar as Microsoft Windows. | ||
748 | * It is useful but poor. | ||
749 | */ | ||
750 | static void | ||
751 | ft_make_up_bold_bitmap( char *raster, int bpr, int ht, int ds_mode) | ||
752 | { | ||
753 | int x, y; | ||
754 | unsigned char *p = (unsigned char *)raster; | ||
755 | if ( ds_mode & TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT0x0002 ) { | ||
756 | for (y=0; y<ht; y++) { | ||
757 | unsigned char rev_pat=0; | ||
758 | unsigned char lsb = 0; | ||
759 | for (x=0; x<bpr; x++) { | ||
760 | unsigned char tmp = *p<<7; | ||
761 | if ( (rev_pat & 0x01) && (*p & 0x80) ) p[-1] &= 0xfe; | ||
762 | rev_pat = ~(*p); | ||
763 | *p |= (*p>>1) | lsb; | ||
764 | *p &= ~(rev_pat & (*p << 1)); | ||
765 | lsb = tmp; | ||
766 | p++; | ||
767 | } | ||
768 | } | ||
769 | } | ||
770 | else { | ||
771 | for (y=0; y<ht; y++) { | ||
772 | unsigned char lsb = 0; | ||
773 | for (x=0; x<bpr; x++) { | ||
774 | unsigned char tmp = *p<<7; | ||
775 | *p |= (*p>>1) | lsb; | ||
776 | lsb = tmp; | ||
777 | p++; | ||
778 | } | ||
779 | } | ||
780 | } | ||
781 | } | ||
782 | |||
783 | static void | ||
784 | ft_make_up_italic_bitmap( char *raster, int bpr, int ht, int shift, | ||
785 | int h_total, int h_offset, double a_italic) | ||
786 | { | ||
787 | int x, y; | ||
788 | unsigned char *p = (unsigned char *)raster; | ||
789 | if ( a_italic < 0 ) shift = -shift; | ||
790 | for (y=0; y<ht; y++) { | ||
791 | unsigned char *tmp_p = p + y*bpr; | ||
792 | int tmp_shift = shift * (h_total -1 -(y+h_offset)) / h_total; | ||
793 | int tmp_byte_shift; | ||
794 | if ( 0 <= tmp_shift ) { | ||
795 | tmp_byte_shift = tmp_shift/8; | ||
796 | tmp_shift %= 8; | ||
797 | if ( tmp_shift ) { | ||
798 | for (x=bpr-1;0<=x;x--) { | ||
799 | if ( x != bpr-1 ) | ||
800 | tmp_p[x+1] |= tmp_p[x]<<(8-tmp_shift); | ||
801 | tmp_p[x]>>=tmp_shift; | ||
802 | } | ||
803 | } | ||
804 | if ( tmp_byte_shift ) { | ||
805 | for (x=bpr-1;0<x;x--) { | ||
806 | tmp_p[x] = tmp_p[x-1]; | ||
807 | } | ||
808 | tmp_p[x]=0; | ||
809 | } | ||
810 | } | ||
811 | else { | ||
812 | tmp_shift = -tmp_shift; | ||
813 | tmp_byte_shift = tmp_shift/8; | ||
814 | tmp_shift %= 8; | ||
815 | if ( tmp_shift ) { | ||
816 | for (x=0;x<bpr;x++) { | ||
817 | if ( x != 0 ) | ||
818 | tmp_p[x-1] |= tmp_p[x]>>(8-tmp_shift); | ||
819 | tmp_p[x]<<=tmp_shift; | ||
820 | } | ||
821 | } | ||
822 | if ( tmp_byte_shift ) { | ||
823 | for (x=0;x<bpr-1;x++) { | ||
824 | tmp_p[x] = tmp_p[x+1]; | ||
825 | } | ||
826 | tmp_p[x]=0; | ||
827 | } | ||
828 | } | ||
829 | } | ||
830 | } | ||
831 | |||
832 | /* | ||
833 | * The very lazy method, | ||
834 | * parse the htmx field in TrueType font. | ||
835 | */ | ||
836 | |||
837 | static void | ||
838 | tt_get_metrics( FT_Face face, | ||
839 | FT_UInt idx, | ||
840 | FT_UInt num_hmetrics, | ||
841 | FT_Short* bearing, | ||
842 | FT_UShort* advance ) | ||
843 | { | ||
844 | /* read the metrics directly from the horizontal header, we | ||
845 | * parse the SFNT table directly through the standard FreeType API. | ||
846 | * this works with any version of the library and doesn't need to | ||
847 | * peek at its internals. Maybe a bit less | ||
848 | */ | ||
849 | FT_UInt count = num_hmetrics; | ||
850 | FT_ULong length = 0; | ||
851 | FT_ULong offset = 0; | ||
852 | FT_Error error; | ||
853 | |||
854 | error = FT_Load_Sfnt_Table( face, TTAG_hmtx(FT_Tag) ( ( (FT_ULong)'h' << 24 ) | ( (FT_ULong)'m' << 16 ) | ( (FT_ULong)'t' << 8 ) | (FT_ULong)'x' ), 0, NULL((void*)0), &length ); | ||
855 | |||
856 | if ( count == 0 || error ) | ||
857 | { | ||
858 | *advance = 0; | ||
859 | *bearing = 0; | ||
860 | } | ||
861 | else if ( idx < count ) | ||
862 | { | ||
863 | offset = idx * 4L; | ||
864 | if ( offset + 4 > length ) | ||
865 | { | ||
866 | *advance = 0; | ||
867 | *bearing = 0; | ||
868 | } | ||
869 | else | ||
870 | { | ||
871 | *advance = sfnt_get_ushort( face, TTAG_hmtx(FT_Tag) ( ( (FT_ULong)'h' << 24 ) | ( (FT_ULong)'m' << 16 ) | ( (FT_ULong)'t' << 8 ) | (FT_ULong)'x' ), offset ); | ||
872 | *bearing = sfnt_get_short ( face, TTAG_hmtx, offset+2 )((FT_Short)sfnt_get_ushort((face),((FT_Tag) ( ( (FT_ULong)'h' << 24 ) | ( (FT_ULong)'m' << 16 ) | ( (FT_ULong) 't' << 8 ) | (FT_ULong)'x' )),(offset+2))); | ||
873 | } | ||
874 | } | ||
875 | else | ||
876 | { | ||
877 | offset = 4L * (count - 1); | ||
878 | if ( offset + 4 > length ) | ||
879 | { | ||
880 | *advance = 0; | ||
881 | *bearing = 0; | ||
882 | } | ||
883 | else | ||
884 | { | ||
885 | *advance = sfnt_get_ushort ( face, TTAG_hmtx(FT_Tag) ( ( (FT_ULong)'h' << 24 ) | ( (FT_ULong)'m' << 16 ) | ( (FT_ULong)'t' << 8 ) | (FT_ULong)'x' ), offset ); | ||
886 | offset += 4 + 2 * ( idx - count ); | ||
887 | if ( offset + 2 > length) | ||
888 | *bearing = 0; | ||
889 | else | ||
890 | *bearing = sfnt_get_short ( face, TTAG_hmtx, offset )((FT_Short)sfnt_get_ushort((face),((FT_Tag) ( ( (FT_ULong)'h' << 24 ) | ( (FT_ULong)'m' << 16 ) | ( (FT_ULong) 't' << 8 ) | (FT_ULong)'x' )),(offset))); | ||
891 | } | ||
892 | } | ||
893 | } | ||
894 | |||
895 | static int | ||
896 | ft_get_very_lazy_bbox( FT_UInt index, | ||
897 | FT_Face face, | ||
898 | FT_Size size, | ||
899 | FT_UInt num_hmetrics, | ||
900 | double slant, | ||
901 | FT_Matrix *matrix, | ||
902 | FT_BBox *bbox, | ||
903 | FT_Long *horiAdvance, | ||
904 | FT_Long *vertAdvance) | ||
905 | { | ||
906 | if ( FT_IS_SFNT( face )( face->face_flags & ( 1L << 3 ) ) ) { | ||
907 | FT_Size_Metrics *smetrics = &size->metrics; | ||
908 | FT_Short leftBearing = 0; | ||
909 | FT_UShort advance = 0; | ||
910 | FT_Vector p0, p1, p2, p3; | ||
911 | |||
912 | /* horizontal */ | ||
913 | tt_get_metrics( face, index, num_hmetrics, | ||
914 | &leftBearing, &advance ); | ||
915 | |||
916 | #if 0 | ||
917 | fprintf(stderrstderr,"x_scale=%f y_scale=%f\n", | ||
918 | (double)smetrics->x_scale,(double)smetrics->y_scale); | ||
919 | #endif | ||
920 | bbox->xMax = *horiAdvance = | ||
921 | FT_MulFix( advance, smetrics->x_scale ); | ||
922 | bbox->xMin = | ||
923 | FT_MulFix( leftBearing, smetrics->x_scale ); | ||
924 | /* vertical */ | ||
925 | bbox->yMin = FT_MulFix( face->bbox.yMin, | ||
926 | smetrics->y_scale ); | ||
927 | bbox->yMax = FT_MulFix( face->bbox.yMax, | ||
928 | smetrics->y_scale ); | ||
929 | /* slant */ | ||
930 | if( 0 < slant ) { | ||
931 | bbox->xMax += slant * bbox->yMax; | ||
932 | bbox->xMin += slant * bbox->yMin; | ||
933 | } | ||
934 | else if( slant < 0 ) { | ||
935 | bbox->xMax += slant * bbox->yMin; | ||
936 | bbox->xMin += slant * bbox->yMax; | ||
937 | } | ||
938 | |||
939 | *vertAdvance = -1; /* We don't support */ | ||
940 | |||
941 | p0.x = p2.x = bbox->xMin; | ||
942 | p1.x = p3.x = bbox->xMax; | ||
943 | p0.y = p1.y = bbox->yMin; | ||
944 | p2.y = p3.y = bbox->yMax; | ||
945 | |||
946 | FT_Vector_Transform(&p0, matrix); | ||
947 | FT_Vector_Transform(&p1, matrix); | ||
948 | FT_Vector_Transform(&p2, matrix); | ||
949 | FT_Vector_Transform(&p3, matrix); | ||
950 | |||
951 | #if 0 | ||
952 | fprintf(stderrstderr, | ||
953 | "->(%.1f %.1f) (%.1f %.1f)" | ||
954 | " (%.1f %.1f) (%.1f %.1f)\n", | ||
955 | p0.x / 64.0, p0.y / 64.0, | ||
956 | p1.x / 64.0, p1.y / 64.0, | ||
957 | p2.x / 64.0, p2.y / 64.0, | ||
958 | p3.x / 64.0, p3.y / 64.0); | ||
959 | #endif | ||
960 | bbox->xMin = MIN(p0.x, MIN(p1.x, MIN(p2.x, p3.x)))((p0.x) < (((p1.x) < (((p2.x) < (p3.x) ? (p2.x) : (p3 .x))) ? (p1.x) : (((p2.x) < (p3.x) ? (p2.x) : (p3.x))))) ? (p0.x) : (((p1.x) < (((p2.x) < (p3.x) ? (p2.x) : (p3.x ))) ? (p1.x) : (((p2.x) < (p3.x) ? (p2.x) : (p3.x)))))); | ||
961 | bbox->xMax = MAX(p0.x, MAX(p1.x, MAX(p2.x, p3.x)))((p0.x) > (((p1.x) > (((p2.x) > (p3.x) ? (p2.x) : (p3 .x))) ? (p1.x) : (((p2.x) > (p3.x) ? (p2.x) : (p3.x))))) ? (p0.x) : (((p1.x) > (((p2.x) > (p3.x) ? (p2.x) : (p3.x ))) ? (p1.x) : (((p2.x) > (p3.x) ? (p2.x) : (p3.x)))))); | ||
962 | bbox->yMin = MIN(p0.y, MIN(p1.y, MIN(p2.y, p3.y)))((p0.y) < (((p1.y) < (((p2.y) < (p3.y) ? (p2.y) : (p3 .y))) ? (p1.y) : (((p2.y) < (p3.y) ? (p2.y) : (p3.y))))) ? (p0.y) : (((p1.y) < (((p2.y) < (p3.y) ? (p2.y) : (p3.y ))) ? (p1.y) : (((p2.y) < (p3.y) ? (p2.y) : (p3.y)))))); | ||
963 | bbox->yMax = MAX(p0.y, MAX(p1.y, MAX(p2.y, p3.y)))((p0.y) > (((p1.y) > (((p2.y) > (p3.y) ? (p2.y) : (p3 .y))) ? (p1.y) : (((p2.y) > (p3.y) ? (p2.y) : (p3.y))))) ? (p0.y) : (((p1.y) > (((p2.y) > (p3.y) ? (p2.y) : (p3.y ))) ? (p1.y) : (((p2.y) > (p3.y) ? (p2.y) : (p3.y)))))); | ||
964 | return 0; /* Successful */ | ||
965 | } | ||
966 | return -1; | ||
967 | } | ||
968 | |||
969 | static FT_Error | ||
970 | FT_Do_SBit_Metrics( FT_Face ft_face, FT_Size ft_size, FT_ULong strike_index, | ||
971 | FT_UShort glyph_index, FT_Glyph_Metrics *metrics_return, | ||
972 | int *sbitchk_incomplete_but_exist ) | ||
973 | { | ||
974 | #if 1 | ||
975 | if ( strike_index != 0xFFFFU && ft_face->available_sizes != NULL((void*)0) ) | ||
976 | { | ||
977 | FT_Error error; | ||
978 | FT_Bitmap_Size* sz = &ft_face->available_sizes[strike_index]; | ||
979 | |||
980 | error = FT_Set_Pixel_Sizes( ft_face, sz->x_ppem/64, sz->y_ppem/64 ); | ||
981 | if ( !error ) | ||
982 | { | ||
983 | error = FT_Load_Glyph( ft_face, glyph_index, FT_LOAD_SBITS_ONLY0x4000 ); | ||
984 | if ( !error ) | ||
985 | { | ||
986 | if ( metrics_return != NULL((void*)0) ) | ||
987 | *metrics_return = ft_face->glyph->metrics; | ||
988 | |||
989 | return 0; | ||
990 | } | ||
991 | } | ||
992 | } | ||
993 | return -1; | ||
994 | #elif (FREETYPE_VERSION(2 * 1000000 + 4 * 1000 + 4) >= 2001008) | ||
995 | SFNT_Service sfnt; | ||
996 | TT_Face face; | ||
997 | FT_Error error; | ||
998 | FT_Stream stream; | ||
999 | TT_SBit_Strike strike; | ||
1000 | TT_SBit_Range range; | ||
1001 | TT_SBit_MetricsRec elem_metrics; | ||
1002 | FT_ULong ebdt_pos; | ||
1003 | FT_ULong glyph_offset; | ||
1004 | ; | ||
1005 | |||
1006 | if ( ! FT_IS_SFNT( ft_face )( ft_face->face_flags & ( 1L << 3 ) ) ) | ||
1007 | { | ||
1008 | error=-1; | ||
1009 | goto Exit; | ||
1010 | } | ||
1011 | |||
1012 | face = (TT_Face)ft_face; | ||
1013 | sfnt = (SFNT_Service)face->sfnt; | ||
1014 | |||
1015 | if (strike_index != 0xFFFFU && sfnt && sfnt->find_sbit_image && | ||
1016 | sfnt->load_sbits) { | ||
1017 | /* Check whether there is a glyph sbit for the current index */ | ||
1018 | error = sfnt->find_sbit_image( face, glyph_index, strike_index, | ||
1019 | &range, &strike, &glyph_offset ); | ||
1020 | } | ||
1021 | else error=-1; | ||
1022 | if ( error ) goto Exit; | ||
1023 | |||
1024 | if ( metrics_return == NULL((void*)0) ) goto Exit; | ||
1025 | |||
1026 | stream = face->root.stream; | ||
1027 | |||
1028 | /* now, find the location of the `EBDT' table in */ | ||
1029 | /* the font file */ | ||
1030 | error = face->goto_table( face, TTAG_EBDT(FT_Tag) ( ( (FT_ULong)'E' << 24 ) | ( (FT_ULong)'B' << 16 ) | ( (FT_ULong)'D' << 8 ) | (FT_ULong)'T' ), stream, 0 ); | ||
1031 | if ( error ) | ||
1032 | error = face->goto_table( face, TTAG_bdat(FT_Tag) ( ( (FT_ULong)'b' << 24 ) | ( (FT_ULong)'d' << 16 ) | ( (FT_ULong)'a' << 8 ) | (FT_ULong)'t' ), stream, 0 ); | ||
1033 | if (error) | ||
1034 | goto Exit; | ||
1035 | |||
1036 | ebdt_pos = FT_STREAM_POS(); | ||
1037 | |||
1038 | /* place stream at beginning of glyph data and read metrics */ | ||
1039 | if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) ) | ||
1040 | goto Exit; | ||
1041 | |||
1042 | error = sfnt->load_sbit_metrics( stream, range, &elem_metrics ); | ||
1043 | if ( error ) | ||
1044 | goto Exit; | ||
1045 | |||
1046 | metrics_return->width = (FT_Pos)elem_metrics.width << 6; | ||
1047 | metrics_return->height = (FT_Pos)elem_metrics.height << 6; | ||
1048 | |||
1049 | metrics_return->horiBearingX = (FT_Pos)elem_metrics.horiBearingX << 6; | ||
1050 | metrics_return->horiBearingY = (FT_Pos)elem_metrics.horiBearingY << 6; | ||
1051 | metrics_return->horiAdvance = (FT_Pos)elem_metrics.horiAdvance << 6; | ||
1052 | |||
1053 | metrics_return->vertBearingX = (FT_Pos)elem_metrics.vertBearingX << 6; | ||
1054 | metrics_return->vertBearingY = (FT_Pos)elem_metrics.vertBearingY << 6; | ||
1055 | metrics_return->vertAdvance = (FT_Pos)elem_metrics.vertAdvance << 6; | ||
1056 | |||
1057 | Exit: | ||
1058 | return error; | ||
1059 | #else /* if (FREETYPE_VERSION < 2001008) */ | ||
1060 | TT_Face face; | ||
1061 | SFNT_Service sfnt; | ||
1062 | if ( ! FT_IS_SFNT( ft_face )( ft_face->face_flags & ( 1L << 3 ) ) ) return -1; | ||
1063 | face = (TT_Face)ft_face; | ||
1064 | sfnt = (SFNT_Service)face->sfnt; | ||
1065 | if ( strike_index != 0xFFFFU && sfnt->load_sbits ) { | ||
1066 | if ( sbitchk_incomplete_but_exist ) *sbitchk_incomplete_but_exist=1; | ||
1067 | } | ||
1068 | return -1; | ||
1069 | #endif | ||
1070 | } | ||
1071 | |||
1072 | int | ||
1073 | FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp, | ||
1074 | FTInstancePtr instance, int hasMetrics) | ||
1075 | { | ||
1076 | FTFacePtr face; | ||
1077 | FT_BBox bbox; | ||
1078 | FT_Long outline_hori_advance, outline_vert_advance; | ||
1079 | FT_Glyph_Metrics sbit_metrics; | ||
1080 | FT_Glyph_Metrics *bitmap_metrics=NULL((void*)0), *metrics = NULL((void*)0); | ||
1081 | char *raster; | ||
1082 | int wd, ht, bpr; /* width, height, bytes per row */ | ||
1083 | int wd_actual, ht_actual; | ||
1084 | int ftrc, is_outline, correct, b_shift=0; | ||
1085 | int dx, dy; | ||
1086 | int leftSideBearing, rightSideBearing, characterWidth, rawCharacterWidth, | ||
1087 | ascent, descent; | ||
1088 | int sbitchk_incomplete_but_exist; | ||
1089 | double bbox_center_raw; | ||
1090 | |||
1091 | face = instance->face; | ||
1092 | |||
1093 | FreeTypeActivateInstance(instance); | ||
1094 | |||
1095 | if(!tgp) return AllocError80; | ||
1096 | |||
1097 | /* | ||
1098 | * PREPARE METRICS | ||
1099 | */ | ||
1100 | |||
1101 | if(!hasMetrics) { | ||
1102 | if( instance->spacing == FT_CHARCELL2 || flags & FT_GET_DUMMY0x04 ){ | ||
1103 | memcpy((char*)&tgp->metrics, | ||
1104 | (char*)instance->charcellMetrics, | ||
1105 | sizeof(xCharInfo)); | ||
1106 | } | ||
1107 | else if( flags & FT_FORCE_CONSTANT_SPACING0x08 ) { | ||
1108 | memcpy((char*)&tgp->metrics, | ||
1109 | (char*)instance->forceConstantMetrics, | ||
1110 | sizeof(xCharInfo)); | ||
1111 | } | ||
1112 | /* mono or prop. */ | ||
1113 | else{ | ||
1114 | int new_width; | ||
1115 | double ratio; | ||
1116 | |||
1117 | sbitchk_incomplete_but_exist=0; | ||
1118 | if( ! (instance->load_flags & FT_LOAD_NO_BITMAP0x8) ) { | ||
1119 | if( FT_Do_SBit_Metrics(face->face,instance->size,instance->strike_index, | ||
1120 | idx,&sbit_metrics,&sbitchk_incomplete_but_exist)==0 ) { | ||
1121 | bitmap_metrics = &sbit_metrics; | ||
1122 | } | ||
1123 | } | ||
1124 | if( bitmap_metrics == NULL((void*)0) ) { | ||
1125 | if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY0x0010) ) { | ||
1126 | if( ft_get_very_lazy_bbox( idx, face->face, instance->size, | ||
1127 | face->num_hmetrics, | ||
1128 | instance->ttcap.vl_slant, | ||
1129 | &instance->transformation.matrix, | ||
1130 | &bbox, &outline_hori_advance, | ||
1131 | &outline_vert_advance ) == 0 ) { | ||
1132 | goto bbox_ok; /* skip exact calculation */ | ||
1133 | } | ||
1134 | } | ||
1135 | ftrc = FT_Load_Glyph(instance->face->face, idx, | ||
1136 | instance->load_flags); | ||
1137 | if(ftrc != 0) return FTtoXReturnCode(ftrc); | ||
1138 | metrics = &face->face->glyph->metrics; | ||
1139 | if( face->face->glyph->format == FT_GLYPH_FORMAT_BITMAP ) { | ||
1140 | bitmap_metrics = metrics; | ||
1141 | } | ||
1142 | } | ||
1143 | |||
1144 | if( bitmap_metrics ) { | ||
1145 | FT_Pos factor; | ||
1146 | |||
1147 | leftSideBearing = bitmap_metrics->horiBearingX / 64; | ||
1148 | rightSideBearing = (bitmap_metrics->width + bitmap_metrics->horiBearingX) / 64; | ||
1149 | bbox_center_raw = (2.0 * bitmap_metrics->horiBearingX + bitmap_metrics->width)/2.0/64.0; | ||
1150 | characterWidth = (int)floor(bitmap_metrics->horiAdvance | ||
1151 | * instance->ttcap.scaleBBoxWidth / 64.0 + .5); | ||
1152 | ascent = bitmap_metrics->horiBearingY / 64; | ||
1153 | descent = (bitmap_metrics->height - bitmap_metrics->horiBearingY) / 64 ; | ||
1154 | /* */ | ||
1155 | new_width = characterWidth; | ||
1156 | if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH0x0008 ) | ||
1157 | new_width += instance->ttcap.doubleStrikeShift; | ||
1158 | new_width += instance->ttcap.adjustBBoxWidthByPixel; | ||
1159 | ratio = (double)new_width/characterWidth; | ||
1160 | characterWidth = new_width; | ||
1161 | /* adjustment by pixel unit */ | ||
1162 | if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE0x0001 ) | ||
1163 | rightSideBearing += instance->ttcap.doubleStrikeShift; | ||
1164 | rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel; | ||
1165 | leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel; | ||
1166 | rightSideBearing += instance->ttcap.rsbShiftOfBitmapAutoItalic; | ||
1167 | leftSideBearing += instance->ttcap.lsbShiftOfBitmapAutoItalic; | ||
1168 | /* */ | ||
1169 | factor = bitmap_metrics->horiAdvance; | ||
1170 | rawCharacterWidth = (unsigned short)(short)(floor(1000 * factor | ||
1171 | * instance->ttcap.scaleBBoxWidth * ratio / 64. | ||
1172 | / instance->pixel_size)); | ||
1173 | } | ||
1174 | else { | ||
1175 | /* Outline */ | ||
1176 | #ifdef USE_GET_CBOX | ||
1177 | /* Very fast?? */ | ||
1178 | FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); | ||
1179 | ftrc=0; /* FT_Outline_Get_CBox returns nothing. */ | ||
1180 | #else | ||
1181 | /* Calculate exact metrics */ | ||
1182 | ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); | ||
1183 | #endif | ||
1184 | if( ftrc != 0 ) return FTtoXReturnCode(ftrc); | ||
1185 | outline_hori_advance = metrics->horiAdvance; | ||
1186 | outline_vert_advance = metrics->vertAdvance; | ||
1187 | bbox_ok: | ||
1188 | descent = CEIL64(-bbox.yMin - 32)(((-bbox.yMin - 32) + 64 - 1) & -64) / 64; | ||
1189 | leftSideBearing = FLOOR64(bbox.xMin + 32)((bbox.xMin + 32) & -64) / 64; | ||
1190 | ascent = FLOOR64(bbox.yMax + 32)((bbox.yMax + 32) & -64) / 64; | ||
1191 | rightSideBearing = FLOOR64(bbox.xMax + 32)((bbox.xMax + 32) & -64) / 64; | ||
1192 | bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.; | ||
1193 | if ( instance->pixel_width_unit_x != 0 ) | ||
1194 | characterWidth = | ||
1195 | (int)floor( outline_hori_advance | ||
1196 | * instance->ttcap.scaleBBoxWidth | ||
1197 | * instance->pixel_width_unit_x / 64. + .5); | ||
1198 | else { | ||
1199 | characterWidth = | ||
1200 | (int)floor( outline_vert_advance | ||
1201 | * instance->ttcap.scaleBBoxHeight | ||
1202 | * instance->pixel_width_unit_y / 64. + .5); | ||
1203 | if(characterWidth <= 0) | ||
1204 | characterWidth = instance->charcellMetrics->characterWidth; | ||
1205 | } | ||
1206 | /* */ | ||
1207 | new_width = characterWidth; | ||
1208 | if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH0x0008 ) | ||
1209 | new_width += instance->ttcap.doubleStrikeShift; | ||
1210 | new_width += instance->ttcap.adjustBBoxWidthByPixel; | ||
1211 | ratio = (double)new_width/characterWidth; | ||
1212 | characterWidth = new_width; | ||
1213 | if ( instance->pixel_width_unit_x != 0 ) | ||
1214 | rawCharacterWidth = | ||
1215 | (unsigned short)(short)(floor(1000 * outline_hori_advance | ||
1216 | * instance->ttcap.scaleBBoxWidth * ratio | ||
1217 | * instance->pixel_width_unit_x / 64.)); | ||
1218 | else { | ||
1219 | rawCharacterWidth = | ||
1220 | (unsigned short)(short)(floor(1000 * outline_vert_advance | ||
1221 | * instance->ttcap.scaleBBoxHeight * ratio | ||
1222 | * instance->pixel_width_unit_y / 64.)); | ||
1223 | if(rawCharacterWidth <= 0) | ||
1224 | rawCharacterWidth = instance->charcellMetrics->attributes; | ||
1225 | } | ||
1226 | /* adjustment by pixel unit */ | ||
1227 | if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE0x0001 ) | ||
1228 | rightSideBearing += instance->ttcap.doubleStrikeShift; | ||
1229 | rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel; | ||
1230 | leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel; | ||
1231 | } | ||
1232 | |||
1233 | /* Set the glyph metrics. */ | ||
1234 | tgp->metrics.attributes = (unsigned short)((short)rawCharacterWidth); | ||
1235 | tgp->metrics.leftSideBearing = leftSideBearing; | ||
1236 | tgp->metrics.rightSideBearing = rightSideBearing; | ||
1237 | tgp->metrics.characterWidth = characterWidth; | ||
1238 | tgp->metrics.ascent = ascent; | ||
1239 | tgp->metrics.descent = descent; | ||
1240 | /* Update the width to match the width of the font */ | ||
1241 | if( instance->spacing != FT_PROPORTIONAL0 ) | ||
1242 | tgp->metrics.characterWidth = instance->charcellMetrics->characterWidth; | ||
1243 | if(instance->ttcap.flags & TTCAP_MONO_CENTER0x0800){ | ||
1244 | b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5); | ||
1245 | tgp->metrics.leftSideBearing += b_shift; | ||
1246 | tgp->metrics.rightSideBearing += b_shift; | ||
1247 | } | ||
1248 | } | ||
1249 | } | ||
1250 | |||
1251 | if( flags & FT_GET_GLYPH_METRICS_ONLY0x02 ) return Successful85; | ||
1252 | |||
1253 | /* | ||
1254 | * CHECK THE NECESSITY OF BITMAP POSITION'S CORRECTION | ||
1255 | */ | ||
1256 | |||
1257 | correct=0; | ||
1258 | if( instance->spacing == FT_CHARCELL2 ) correct=1; | ||
1259 | else if( flags & FT_FORCE_CONSTANT_SPACING0x08 ) correct=1; | ||
1260 | else{ | ||
1261 | int sbit_available=0; | ||
1262 | sbitchk_incomplete_but_exist=0; | ||
1263 | if( !(instance->load_flags & FT_LOAD_NO_BITMAP0x8) ) { | ||
1264 | if( FT_Do_SBit_Metrics(face->face,instance->size, | ||
1265 | instance->strike_index,idx,NULL((void*)0), | ||
1266 | &sbitchk_incomplete_but_exist)==0 ) { | ||
1267 | sbit_available=1; | ||
1268 | } | ||
1269 | } | ||
1270 | if( sbit_available == 0 ) { | ||
1271 | if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY0x0010) ) { | ||
1272 | if( FT_IS_SFNT(face->face)( face->face->face_flags & ( 1L << 3 ) ) ) correct=1; | ||
1273 | } | ||
1274 | } | ||
1275 | } | ||
1276 | |||
1277 | /* | ||
1278 | * RENDER AND ALLOCATE BUFFER | ||
1279 | */ | ||
1280 | |||
1281 | if( flags & FT_GET_DUMMY0x04 ) is_outline = -1; | ||
1282 | else { | ||
1283 | if( !metrics ) { | ||
1284 | ftrc = FT_Load_Glyph(instance->face->face, idx, | ||
1285 | instance->load_flags); | ||
1286 | metrics = &face->face->glyph->metrics; | ||
1287 | |||
1288 | if(ftrc != 0) return FTtoXReturnCode(ftrc); | ||
1289 | } | ||
1290 | |||
1291 | if( face->face->glyph->format != FT_GLYPH_FORMAT_BITMAP ) { | ||
1292 | #ifdef USE_GET_CBOX | ||
1293 | FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); | ||
1294 | ftrc = 0; | ||
1295 | #else | ||
1296 | ftrc = FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); | ||
1297 | #endif | ||
1298 | if( ftrc != 0 ) return FTtoXReturnCode(ftrc); | ||
1299 | bbox.yMin = FLOOR64( bbox.yMin )((bbox.yMin) & -64); | ||
1300 | bbox.yMax = CEIL64 ( bbox.yMax )(((bbox.yMax) + 64 - 1) & -64); | ||
1301 | ht_actual = ( bbox.yMax - bbox.yMin ) >> 6; | ||
1302 | /* FreeType think a glyph with 0 height control box is invalid. | ||
1303 | * So just let X to create a empty bitmap instead. */ | ||
1304 | if ( ht_actual == 0 ) | ||
1305 | is_outline = -1; | ||
1306 | else | ||
1307 | { | ||
1308 | ftrc = FT_Render_Glyph(face->face->glyph,FT_RENDER_MODE_MONO); | ||
1309 | if( ftrc != 0 ) return FTtoXReturnCode(ftrc); | ||
1310 | is_outline = 1; | ||
1311 | } | ||
1312 | } | ||
1313 | else{ | ||
1314 | is_outline=0; | ||
1315 | } | ||
1316 | } | ||
1317 | |||
1318 | /* Spacial case */ | ||
1319 | if( (instance->ttcap.flags & TTCAP_MONO_CENTER0x0800) && hasMetrics ) { | ||
1320 | if( is_outline == 1 ){ | ||
1321 | if( correct ){ | ||
1322 | if( ft_get_very_lazy_bbox( idx, face->face, instance->size, | ||
1323 | face->num_hmetrics, | ||
1324 | instance->ttcap.vl_slant, | ||
1325 | &instance->transformation.matrix, | ||
1326 | &bbox, &outline_hori_advance, | ||
1327 | &outline_vert_advance ) != 0 ){ | ||
1328 | is_outline = -1; /* <- error */ | ||
1329 | } | ||
1330 | } | ||
1331 | else { | ||
1332 | #ifdef USE_GET_CBOX | ||
1333 | FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); | ||
1334 | ftrc=0; | ||
1335 | #else | ||
1336 | ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); | ||
1337 | #endif | ||
1338 | if( ftrc != 0 ) return FTtoXReturnCode(ftrc); | ||
1339 | } | ||
1340 | bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.; | ||
1341 | } | ||
1342 | else if( is_outline == 0 ) | ||
1343 | bbox_center_raw = (2.0 * metrics->horiBearingX + metrics->width)/2.0/64.0; | ||
1344 | else | ||
1345 | bbox_center_raw = 0; | ||
1346 | b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5); | ||
1347 | } | ||
1348 | |||
1349 | wd_actual = tgp->metrics.rightSideBearing - tgp->metrics.leftSideBearing; | ||
1350 | ht_actual = tgp->metrics.ascent + tgp->metrics.descent; | ||
1351 | |||
1352 | /* The X convention is to consider a character with an empty | ||
1353 | * bounding box as undefined. This convention is broken. */ | ||
1354 | |||
1355 | if(wd_actual <= 0) wd = 1; | ||
1356 | else wd=wd_actual; | ||
1357 | if(ht_actual <= 0) ht = 1; | ||
1358 | else ht=ht_actual; | ||
1359 | |||
1360 | bpr = (((wd + (instance->bmfmt.glyph<<3) - 1) >> 3) & | ||
1361 | -instance->bmfmt.glyph); | ||
1362 | raster = calloc(1, ht * bpr); | ||
1363 | if(raster == NULL((void*)0)) | ||
1364 | return AllocError80; | ||
1365 | |||
1366 | tgp->bits = raster; | ||
1367 | |||
1368 | /* If FT_GET_DUMMY is set, we return white space. */ | ||
1369 | if ( is_outline == -1 ) return Successful85; | ||
1370 | |||
1371 | if ( wd_actual <= 0 || ht_actual <= 0 ) return Successful85; | ||
1372 | |||
1373 | /* | ||
1374 | * CALCULATE OFFSET, dx AND dy. | ||
1375 | */ | ||
1376 | |||
1377 | dx = face->face->glyph->bitmap_left - tgp->metrics.leftSideBearing; | ||
1378 | dy = tgp->metrics.ascent - face->face->glyph->bitmap_top; | ||
1379 | |||
1380 | if(instance->ttcap.flags & TTCAP_MONO_CENTER0x0800) | ||
1381 | dx += b_shift; | ||
1382 | |||
1383 | /* To prevent chipped bitmap, we correct dx and dy if needed. */ | ||
1384 | if( correct && is_outline==1 ){ | ||
1385 | int lsb, rsb, asc, des; | ||
1386 | int chip_left,chip_right,chip_top,chip_bot; | ||
1387 | #ifdef USE_GET_CBOX | ||
1388 | FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox); | ||
1389 | ftrc=0; | ||
1390 | #else | ||
1391 | ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox); | ||
1392 | #endif | ||
1393 | if( ftrc != 0 ) return FTtoXReturnCode(ftrc); | ||
1394 | des = CEIL64(-bbox.yMin - 32)(((-bbox.yMin - 32) + 64 - 1) & -64) / 64; | ||
1395 | lsb = FLOOR64(bbox.xMin + 32)((bbox.xMin + 32) & -64) / 64; | ||
1396 | asc = FLOOR64(bbox.yMax + 32)((bbox.yMax + 32) & -64) / 64; | ||
1397 | rsb = FLOOR64(bbox.xMax + 32)((bbox.xMax + 32) & -64) / 64; | ||
1398 | rightSideBearing = tgp->metrics.rightSideBearing; | ||
1399 | leftSideBearing = tgp->metrics.leftSideBearing; | ||
1400 | if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE0x0001 ) | ||
1401 | rightSideBearing -= instance->ttcap.doubleStrikeShift; | ||
1402 | /* special case */ | ||
1403 | if(instance->ttcap.flags & TTCAP_MONO_CENTER0x0800){ | ||
1404 | leftSideBearing -= b_shift; | ||
1405 | rightSideBearing -= b_shift; | ||
1406 | } | ||
1407 | chip_left = lsb - leftSideBearing; | ||
1408 | chip_right = rightSideBearing - rsb; | ||
1409 | if( flags & FT_FORCE_CONSTANT_SPACING0x08 ){ | ||
1410 | if( instance->ttcap.force_c_adjust_lsb_by_pixel != 0 || | ||
1411 | instance->ttcap.force_c_adjust_rsb_by_pixel != 0 ){ | ||
1412 | chip_left=0; | ||
1413 | chip_right=0; | ||
1414 | } | ||
1415 | } | ||
1416 | else{ | ||
1417 | if( instance->ttcap.adjustRightSideBearingByPixel != 0 || | ||
1418 | instance->ttcap.adjustLeftSideBearingByPixel != 0 ){ | ||
1419 | chip_left=0; | ||
1420 | chip_right=0; | ||
1421 | } | ||
1422 | } | ||
1423 | chip_top = tgp->metrics.ascent - asc; | ||
1424 | chip_bot = tgp->metrics.descent - des; | ||
1425 | if( chip_left < 0 && 0 < chip_right ) dx++; | ||
1426 | else if( chip_right < 0 && 0 < chip_left ) dx--; | ||
1427 | if( chip_top < 0 && 0 < chip_bot ) dy++; | ||
1428 | else if( chip_bot < 0 && 0 < chip_top ) dy--; | ||
1429 | } | ||
1430 | |||
1431 | /* | ||
1432 | * COPY RASTER | ||
1433 | */ | ||
1434 | |||
1435 | { | ||
1436 | FT_Bitmap *bitmap; | ||
1437 | int i, j; | ||
1438 | unsigned char *current_raster; | ||
1439 | unsigned char *current_buffer; | ||
1440 | int mod_dx0,mod_dx1; | ||
1441 | int div_dx; | ||
1442 | bitmap = &face->face->glyph->bitmap; | ||
1443 | if( 0 <= dx ){ | ||
1444 | div_dx = dx / 8; | ||
1445 | mod_dx0 = dx % 8; | ||
1446 | mod_dx1 = 8-mod_dx0; | ||
1447 | } | ||
1448 | else{ | ||
1449 | div_dx = dx / 8 -1; | ||
1450 | mod_dx1 = -dx % 8; | ||
1451 | mod_dx0 = 8-mod_dx1; | ||
1452 | } | ||
1453 | for( i = MAX(0, dy)((0) > (dy) ? (0) : (dy)) ; i<ht ; i++ ){ | ||
1454 | int prev_jj,jj; | ||
1455 | if( bitmap->rows <= i-dy ) break; | ||
1456 | current_buffer=(unsigned char *)(bitmap->buffer+bitmap->pitch*(i-dy)); | ||
1457 | current_raster=(unsigned char *)(raster+i*bpr); | ||
1458 | j = MAX(0,div_dx)((0) > (div_dx) ? (0) : (div_dx)); | ||
1459 | jj = j-div_dx; | ||
1460 | prev_jj = jj-1; | ||
1461 | if( j<bpr ){ | ||
1462 | if( 0 <= prev_jj && prev_jj < bitmap->pitch ) | ||
1463 | current_raster[j]|=current_buffer[prev_jj]<<mod_dx1; | ||
1464 | if( 0 <= jj && jj < bitmap->pitch ){ | ||
1465 | current_raster[j]|=current_buffer[jj]>>mod_dx0; | ||
1466 | j++; prev_jj++; jj++; | ||
1467 | for( ; j<bpr ; j++,prev_jj++,jj++ ){ | ||
1468 | current_raster[j]|=current_buffer[prev_jj]<<mod_dx1; | ||
1469 | if( bitmap->pitch <= jj ) break; | ||
1470 | current_raster[j]|=current_buffer[jj]>>mod_dx0; | ||
1471 | } | ||
1472 | } | ||
1473 | } | ||
1474 | } | ||
1475 | } | ||
1476 | |||
1477 | /* by TTCap */ | ||
1478 | if ( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE0x0001 ) { | ||
1479 | int i; | ||
1480 | for( i=0 ; i < instance->ttcap.doubleStrikeShift ; i++ ) | ||
1481 | ft_make_up_bold_bitmap( raster, bpr, ht, instance->ttcap.flags); | ||
1482 | } | ||
1483 | if ( is_outline == 0 && | ||
1484 | ( instance->ttcap.lsbShiftOfBitmapAutoItalic != 0 || | ||
1485 | instance->ttcap.rsbShiftOfBitmapAutoItalic != 0 ) ) { | ||
1486 | ft_make_up_italic_bitmap( raster, bpr, ht, | ||
1487 | - instance->ttcap.lsbShiftOfBitmapAutoItalic | ||
1488 | + instance->ttcap.rsbShiftOfBitmapAutoItalic, | ||
1489 | instance->charcellMetrics->ascent | ||
1490 | + instance->charcellMetrics->descent, | ||
1491 | instance->charcellMetrics->ascent | ||
1492 | - tgp->metrics.ascent, | ||
1493 | instance->ttcap.autoItalic); | ||
1494 | } | ||
1495 | |||
1496 | if(instance->bmfmt.bit == LSBFirst0) { | ||
1497 | BitOrderInvert((unsigned char*)(tgp->bits), ht*bpr); | ||
1498 | } | ||
1499 | |||
1500 | if(instance->bmfmt.byte != instance->bmfmt.bit) { | ||
1501 | switch(instance->bmfmt.scan) { | ||
1502 | case 1: | ||
1503 | break; | ||
1504 | case 2: | ||
1505 | TwoByteSwap((unsigned char*)(tgp->bits), ht*bpr); | ||
1506 | break; | ||
1507 | case 4: | ||
1508 | FourByteSwap((unsigned char*)(tgp->bits), ht*bpr); | ||
1509 | break; | ||
1510 | default: | ||
1511 | ; | ||
1512 | } | ||
1513 | } | ||
1514 | |||
1515 | return Successful85; | ||
1516 | } | ||
1517 | |||
1518 | static void | ||
1519 | FreeTypeFreeFont(FTFontPtr font) | ||
1520 | { | ||
1521 | FreeTypeFreeInstance(font->instance); | ||
1522 | if(font->ranges) | ||
1523 | free(font->ranges); | ||
1524 | if(font->dummy_char.bits) | ||
1525 | free(font->dummy_char.bits); | ||
1526 | free(font); | ||
1527 | } | ||
1528 | |||
1529 | /* Free a font. If freeProps is 0, don't free the properties. */ | ||
1530 | |||
1531 | static void | ||
1532 | FreeTypeFreeXFont(FontPtr pFont, int freeProps) | ||
1533 | { | ||
1534 | FTFontPtr tf; | ||
1535 | |||
1536 | if(pFont) { | ||
1537 | if((tf = (FTFontPtr)pFont->fontPrivate)) { | ||
1538 | FreeTypeFreeFont(tf); | ||
1539 | } | ||
1540 | if(freeProps && pFont->info.nprops>0) { | ||
1541 | free(pFont->info.isStringProp); | ||
1542 | free(pFont->info.props); | ||
1543 | } | ||
1544 | DestroyFontRec(pFont); | ||
1545 | } | ||
1546 | } | ||
1547 | |||
1548 | |||
1549 | /* Unload a font */ | ||
1550 | |||
1551 | static void | ||
1552 | FreeTypeUnloadXFont(FontPtr pFont) | ||
1553 | { | ||
1554 | MUMBLE("Unloading\n"); | ||
1555 | FreeTypeFreeXFont(pFont, 1); | ||
1556 | } | ||
1557 | |||
1558 | /* Add the font properties, including the Font name, the XLFD | ||
1559 | properties, some strings from the font, and various typographical | ||
1560 | data. We only provide data readily available in the tables in the | ||
1561 | font for now, altough FIGURE_WIDTH would be a good idea as it is | ||
1562 | used by Xaw. */ | ||
1563 | |||
1564 | static int | ||
1565 | FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info, | ||
1566 | char *fontname, int rawAverageWidth, Bool font_properties) | ||
1567 | { | ||
1568 | int i, j, maxprops; | ||
1569 | char *sp, *ep, val[MAXFONTNAMELEN1024], *vp; | ||
1570 | FTFacePtr face; | ||
1571 | FTInstancePtr instance; | ||
1572 | FTNormalisedTransformationPtr trans; | ||
1573 | int upm; | ||
1574 | TT_OS2 *os2; | ||
1575 | TT_Postscript *post; | ||
1576 | PS_FontInfoRec t1info_rec, *t1info; | ||
1577 | int xlfdProps = 0; | ||
1578 | int ftrc; | ||
1579 | |||
1580 | instance = font->instance; | ||
1581 | face = instance->face; | ||
1582 | trans = &instance->transformation; | ||
1583 | upm = face->face->units_per_EM; | ||
1584 | if(upm == 0) { | ||
1585 | /* Work around FreeType bug */ | ||
1586 | upm = WORK_AROUND_UPM2048; | ||
1587 | } | ||
1588 | |||
1589 | os2 = FT_Get_Sfnt_Table(face->face, ft_sfnt_os2); | ||
1590 | post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post); | ||
1591 | ftrc = FT_Get_PS_Font_Info(face->face, &t1info_rec); | ||
1592 | if(ftrc == 0) | ||
1593 | t1info = &t1info_rec; | ||
1594 | else | ||
1595 | t1info = NULL((void*)0); | ||
1596 | |||
1597 | if(t1info) { | ||
1598 | os2 = NULL((void*)0); | ||
1599 | post = NULL((void*)0); | ||
1600 | } | ||
1601 | |||
1602 | info->nprops = 0; /* in case we abort */ | ||
1603 | |||
1604 | strcpy(val, fontname); | ||
1605 | if(FontParseXLFDName(val, vals, FONT_XLFD_REPLACE_VALUE3)) { | ||
1606 | xlfdProps = 1; | ||
1607 | } else { | ||
1608 | MUMBLE("Couldn't parse XLFD\n"); | ||
1609 | xlfdProps = 0; | ||
1610 | } | ||
1611 | |||
1612 | maxprops= | ||
1613 | 1 + /* NAME */ | ||
1614 | (xlfdProps ? 14 : 0) + /* from XLFD */ | ||
1615 | 5 + | ||
1616 | ( !face->bitmap ? 3 : 0 ) + /* raw_av,raw_asc,raw_dec */ | ||
1617 | ( font_properties ? 2 : 0 ) + /* asc,dec */ | ||
1618 | ( (font_properties && os2) ? 6 : 0 ) + | ||
1619 | ( (font_properties && (post || t1info)) ? 3 : 0 ) + | ||
1620 | 2; /* type */ | ||
1621 | |||
1622 | info->props = malloc(maxprops * sizeof(FontPropRec)); | ||
1623 | if(info->props == NULL((void*)0)) | ||
1624 | return AllocError80; | ||
1625 | |||
1626 | info->isStringProp = malloc(maxprops); | ||
1627 | if(info->isStringProp == NULL((void*)0)) { | ||
1628 | free(info->props); | ||
1629 | return AllocError80; | ||
1630 | } | ||
1631 | |||
1632 | memset((char *)info->isStringProp, 0, maxprops); | ||
1633 | |||
1634 | i = 0; | ||
1635 | |||
1636 | info->props[i].name = MakeAtom("FONT", 4, TRUE1); | ||
1637 | info->props[i].value = MakeAtom(val, strlen(val), TRUE1); | ||
1638 | info->isStringProp[i] = 1; | ||
1639 | i++; | ||
1640 | |||
1641 | if(*val && *(sp = val + 1)) { | ||
1642 | for (j = 0, sp = val + 1; j < 14; j++) { | ||
1643 | if (j == 13) | ||
1644 | /* Handle the case of the final field containing a subset | ||
1645 | specification. */ | ||
1646 | for (ep = sp; *ep && *ep != '['; ep++); | ||
1647 | else | ||
1648 | for (ep = sp; *ep && *ep != '-'; ep++); | ||
1649 | |||
1650 | info->props[i].name = | ||
1651 | MakeAtom(xlfd_props[j], strlen(xlfd_props[j]), TRUE1); | ||
1652 | |||
1653 | switch(j) { | ||
1654 | case 6: /* pixel size */ | ||
1655 | info->props[i].value = | ||
1656 | (int)(fabs(vals->pixel_matrix[3]) + 0.5); | ||
1657 | i++; | ||
1658 | break; | ||
1659 | case 7: /* point size */ | ||
1660 | info->props[i].value = | ||
1661 | (int)(fabs(vals->point_matrix[3])*10.0 + 0.5); | ||
1662 | i++; | ||
1663 | break; | ||
1664 | case 8: /* resolution x */ | ||
1665 | info->props[i].value = vals->x; | ||
1666 | i++; | ||
1667 | break; | ||
1668 | case 9: /* resolution y */ | ||
1669 | info->props[i].value = vals->y; | ||
1670 | i++; | ||
1671 | break; | ||
1672 | case 11: /* average width */ | ||
1673 | info->props[i].value = vals->width; | ||
1674 | i++; | ||
1675 | break; | ||
1676 | default: /* a string */ | ||
1677 | info->props[i].value = MakeAtom(sp, ep - sp, TRUE1); | ||
1678 | info->isStringProp[i] = 1; | ||
1679 | i++; | ||
1680 | } | ||
1681 | sp = ++ep; | ||
1682 | } | ||
1683 | } | ||
1684 | |||
1685 | info->props[i].name = MakeAtom("RAW_PIXEL_SIZE", 14, TRUE1); | ||
1686 | info->props[i].value = 1000; | ||
1687 | i++; | ||
1688 | |||
1689 | info->props[i].name = MakeAtom("RAW_POINT_SIZE", 14, TRUE1); | ||
1690 | info->props[i].value = (long)(72270.0 / (double)vals->y + .5); | ||
1691 | i++; | ||
1692 | |||
1693 | if(!face->bitmap) { | ||
1694 | info->props[i].name = MakeAtom("RAW_AVERAGE_WIDTH", 17, TRUE1); | ||
1695 | info->props[i].value = rawAverageWidth; | ||
1696 | i++; | ||
1697 | } | ||
1698 | |||
1699 | if ( font_properties ) { | ||
1700 | info->props[i].name = MakeAtom("FONT_ASCENT", 11, TRUE1); | ||
1701 | info->props[i].value = info->fontAscent; | ||
1702 | i++; | ||
1703 | } | ||
1704 | |||
1705 | if(!face->bitmap) { | ||
1706 | info->props[i].name = MakeAtom("RAW_ASCENT", 10, TRUE1); | ||
1707 | info->props[i].value = | ||
1708 | ((double)face->face->ascender/(double)upm*1000.0); | ||
1709 | i++; | ||
1710 | } | ||
1711 | |||
1712 | if ( font_properties ) { | ||
1713 | info->props[i].name = MakeAtom("FONT_DESCENT", 12, TRUE1); | ||
1714 | info->props[i].value = info->fontDescent; | ||
1715 | i++; | ||
1716 | } | ||
1717 | |||
1718 | if(!face->bitmap) { | ||
1719 | info->props[i].name = MakeAtom("RAW_DESCENT", 11, TRUE1); | ||
1720 | info->props[i].value = | ||
1721 | -((double)face->face->descender/(double)upm*1000.0); | ||
1722 | i++; | ||
1723 | } | ||
1724 | |||
1725 | j = FTGetEnglishName(face->face, TT_NAME_ID_COPYRIGHT0, | ||
1726 | val, MAXFONTNAMELEN1024); | ||
1727 | vp = val; | ||
1728 | if (j < 0) { | ||
1729 | if(t1info && t1info->notice) { | ||
1730 | vp = t1info->notice; | ||
1731 | j = strlen(vp); | ||
1732 | } | ||
1733 | } | ||
1734 | if(j > 0) { | ||
1735 | info->props[i].name = MakeAtom("COPYRIGHT", 9, TRUE1); | ||
1736 | info->props[i].value = MakeAtom(vp, j, TRUE1); | ||
1737 | info->isStringProp[i] = 1; | ||
1738 | i++; | ||
1739 | } | ||
1740 | |||
1741 | j = FTGetEnglishName(face->face, TT_NAME_ID_FULL_NAME4, | ||
1742 | val, MAXFONTNAMELEN1024); | ||
1743 | vp = val; | ||
1744 | if (j < 0) { | ||
1745 | if(t1info && t1info->full_name) { | ||
1746 | vp = t1info->full_name; | ||
1747 | j = strlen(vp); | ||
1748 | } | ||
1749 | } | ||
1750 | if(j > 0) { | ||
1751 | info->props[i].name = MakeAtom("FACE_NAME", 9, TRUE1); | ||
1752 | info->props[i].value = MakeAtom(vp, j, TRUE1); | ||
1753 | info->isStringProp[i] = 1; | ||
1754 | i++; | ||
1755 | } | ||
1756 | |||
1757 | vp = (char *)FT_Get_Postscript_Name(face->face); | ||
1758 | if (vp) { | ||
1759 | j = strlen(vp); | ||
1760 | } else { | ||
1761 | j = -1; | ||
1762 | } | ||
1763 | if (j < 0) { | ||
1764 | j = FTGetEnglishName(face->face, TT_NAME_ID_PS_NAME6, | ||
1765 | val, MAXFONTNAMELEN1024); | ||
1766 | vp = val; | ||
1767 | } | ||
1768 | if (j < 0) { | ||
1769 | if(t1info && t1info->full_name) { | ||
1770 | vp = t1info->full_name; | ||
1771 | j = strlen(vp); | ||
1772 | } | ||
1773 | } | ||
1774 | if(j > 0) { | ||
1775 | info->props[i].name = MakeAtom("_ADOBE_POSTSCRIPT_FONTNAME", 26, TRUE1); | ||
1776 | info->props[i].value = MakeAtom(vp, j, TRUE1); | ||
1777 | info->isStringProp[i] = 1; | ||
1778 | i++; | ||
1779 | } | ||
1780 | |||
1781 | /* These macros handle the case of a diagonal matrix. They convert | ||
1782 | FUnits into pixels. */ | ||
1783 | #define TRANSFORM_FUNITS_X(xval) \ | ||
1784 | ((int) \ | ||
1785 | floor( ((double)(xval)/(double)upm) * (double)vals->pixel_matrix[0] + 0.5 ) ) | ||
1786 | |||
1787 | #define TRANSFORM_FUNITS_Y(yval) \ | ||
1788 | ((int) \ | ||
1789 | floor( ((double)(yval)/(double)upm) * (double)vals->pixel_matrix[3] + 0.5 ) ) | ||
1790 | |||
1791 | /* In what follows, we assume the matrix is diagonal. In the rare | ||
1792 | case when it is not, the values will be somewhat wrong. */ | ||
1793 | |||
1794 | if( font_properties && os2 ) { | ||
1795 | info->props[i].name = MakeAtom("SUBSCRIPT_SIZE",14,TRUE1); | ||
1796 | info->props[i].value = | ||
1797 | TRANSFORM_FUNITS_Y(os2->ySubscriptYSize); | ||
1798 | i++; | ||
1799 | info->props[i].name = MakeAtom("SUBSCRIPT_X",11,TRUE1); | ||
1800 | info->props[i].value = | ||
1801 | TRANSFORM_FUNITS_X(os2->ySubscriptXOffset); | ||
1802 | i++; | ||
1803 | info->props[i].name = MakeAtom("SUBSCRIPT_Y",11,TRUE1); | ||
1804 | info->props[i].value = | ||
1805 | TRANSFORM_FUNITS_Y(os2->ySubscriptYOffset); | ||
1806 | i++; | ||
1807 | info->props[i].name = MakeAtom("SUPERSCRIPT_SIZE",16,TRUE1); | ||
1808 | info->props[i].value = | ||
1809 | TRANSFORM_FUNITS_Y(os2->ySuperscriptYSize); | ||
1810 | i++; | ||
1811 | info->props[i].name = MakeAtom("SUPERSCRIPT_X",13,TRUE1); | ||
1812 | info->props[i].value = | ||
1813 | TRANSFORM_FUNITS_X(os2->ySuperscriptXOffset); | ||
1814 | i++; | ||
1815 | info->props[i].name = MakeAtom("SUPERSCRIPT_Y",13,TRUE1); | ||
1816 | info->props[i].value = | ||
1817 | TRANSFORM_FUNITS_Y(os2->ySuperscriptYOffset); | ||
1818 | i++; | ||
1819 | } | ||
1820 | |||
1821 | if( font_properties && (post || t1info) ) { | ||
1822 | int underlinePosition, underlineThickness; | ||
1823 | |||
1824 | /* Raw underlineposition counts upwards, | ||
1825 | but UNDERLINE_POSITION counts downwards. */ | ||
1826 | if(post) { | ||
1827 | underlinePosition = TRANSFORM_FUNITS_Y(-post->underlinePosition); | ||
1828 | underlineThickness = TRANSFORM_FUNITS_Y(post->underlineThickness); | ||
1829 | } else { | ||
1830 | underlinePosition = | ||
1831 | TRANSFORM_FUNITS_Y(-t1info->underline_position); | ||
1832 | underlineThickness = | ||
1833 | TRANSFORM_FUNITS_Y(t1info->underline_thickness); | ||
1834 | } | ||
1835 | if(underlineThickness <= 0) | ||
1836 | underlineThickness = 1; | ||
1837 | |||
1838 | info->props[i].name = MakeAtom("UNDERLINE_THICKNESS",19,TRUE1); | ||
1839 | info->props[i].value = underlineThickness; | ||
1840 | i++; | ||
1841 | |||
1842 | info->props[i].name = MakeAtom("UNDERLINE_POSITION",18,TRUE1); | ||
1843 | |||
1844 | info->props[i].value = underlinePosition; | ||
1845 | |||
1846 | i++; | ||
1847 | |||
1848 | /* The italic angle is often unreliable for Type 1 fonts */ | ||
1849 | if(post && trans->matrix.xx == trans->matrix.yy) { | ||
1850 | info->props[i].name = MakeAtom("ITALIC_ANGLE",12,TRUE1); | ||
1851 | info->props[i].value = | ||
1852 | /* Convert from TT_Fixed to | ||
1853 | 64th of a degree counterclockwise from 3 o'clock */ | ||
1854 | 90*64+(post->italicAngle >> 10); | ||
1855 | i++; | ||
1856 | } | ||
1857 | #undef TRANSFORM_FUNITS_X | ||
1858 | #undef TRANSFORM_FUNITS_Y | ||
1859 | } | ||
1860 | |||
1861 | info->props[i].name = MakeAtom("FONT_TYPE", 9, TRUE1); | ||
1862 | vp = (char *)FT_Get_X11_Font_Format(face->face); | ||
1863 | info->props[i].value = MakeAtom(vp, strlen(vp), TRUE1); | ||
1864 | info->isStringProp[i] = 1; | ||
1865 | i++; | ||
1866 | |||
1867 | info->props[i].name = MakeAtom("RASTERIZER_NAME", 15, TRUE1); | ||
1868 | info->props[i].value = MakeAtom("FreeType", 10, TRUE1); | ||
1869 | info->isStringProp[i] = 1; | ||
1870 | i++; | ||
1871 | |||
1872 | info->nprops = i; | ||
1873 | return Successful85; | ||
1874 | } | ||
1875 | |||
1876 | static int | ||
1877 | ft_get_index(unsigned code, FTFontPtr font, unsigned *idx) | ||
1878 | { | ||
1879 | |||
1880 | /* As a special case, we pass 0 even when it is not in the ranges; | ||
1881 | this will allow for the default glyph, which should exist in any | ||
1882 | TrueType font. */ | ||
1883 | |||
1884 | /* This is not required... | ||
1885 | if(code > 0 && font->nranges) { | ||
1886 | int i; | ||
1887 | for(i = 0; i < font->nranges; i++) | ||
1888 | if((code >= | ||
1889 | font->ranges[i].min_char_low+ | ||
1890 | (font->ranges[i].min_char_high<<8)) && | ||
1891 | (code <= | ||
1892 | font->ranges[i].max_char_low + | ||
1893 | (font->ranges[i].max_char_high<<8))) | ||
1894 | break; | ||
1895 | if(i == font->nranges) { | ||
1896 | *idx = font->zero_idx; | ||
1897 | return -1; | ||
1898 | } | ||
1899 | } | ||
1900 | */ | ||
1901 | if( font->info ) { | ||
1902 | if( !( font->info->firstCol <= (code & 0x000ff) && | ||
1903 | (code & 0x000ff) <= font->info->lastCol && | ||
1904 | font->info->firstRow <= (code >> 8) && | ||
1905 | (code >> 8) <= font->info->lastRow ) ) { | ||
1906 | *idx = font->zero_idx; | ||
1907 | /* Error: The code has not been parsed in ft_compute_bounds()! | ||
1908 | We should not return any metrics. */ | ||
1909 | return -1; | ||
1910 | } | ||
1911 | } | ||
1912 | |||
1913 | *idx = FTRemap(font->instance->face->face, &font->mapping, code); | ||
1914 | |||
1915 | return 0; | ||
1916 | } | ||
1917 | |||
1918 | static int | ||
1919 | FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font) | ||
1920 | { | ||
1921 | unsigned idx = 0; | ||
1922 | int xrc; | ||
1923 | |||
1924 | #ifdef X_ACCEPTS_NO_SUCH_CHAR | ||
1925 | if( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { | ||
1926 | *g = NULL((void*)0); | ||
1927 | flags &= ~FT_FORCE_CONSTANT_SPACING0x08; | ||
1928 | /* if( font->instance->spacing != FT_CHARCELL ) */ | ||
1929 | return Successful85; | ||
1930 | } | ||
1931 | #else | ||
1932 | if( ft_get_index(code,font,&idx) ) { | ||
1933 | /* The code has not been parsed! */ | ||
1934 | *g = NULL((void*)0); | ||
1935 | flags &= ~FT_FORCE_CONSTANT_SPACING0x08; | ||
1936 | } | ||
1937 | #endif | ||
1938 | |||
1939 | xrc = FreeTypeInstanceGetGlyph(idx, flags, g, font->instance); | ||
1940 | if( xrc == Successful85 && *g != NULL((void*)0) ) | ||
1941 | return Successful85; | ||
1942 | if( font->zero_idx != idx ) { | ||
1943 | xrc = FreeTypeInstanceGetGlyph(font->zero_idx, flags, g, font->instance); | ||
1944 | if( xrc == Successful85 && *g != NULL((void*)0) ) | ||
1945 | return Successful85; | ||
1946 | } | ||
1947 | return FreeTypeInstanceGetGlyph(font->zero_idx, flags|FT_GET_DUMMY0x04, g, font->instance); | ||
1948 | } | ||
1949 | |||
1950 | static int | ||
1951 | FreeTypeFontGetGlyphMetrics(unsigned code, int flags, xCharInfo **metrics, FTFontPtr font) | ||
1952 | { | ||
1953 | unsigned idx = 0; | ||
1954 | int xrc; | ||
1955 | |||
1956 | #ifdef X_ACCEPTS_NO_SUCH_CHAR | ||
1957 | if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { | ||
1958 | *metrics = NULL((void*)0); | ||
1959 | flags &= ~FT_FORCE_CONSTANT_SPACING0x08; | ||
1960 | /* if( font->instance->spacing != FT_CHARCELL ) */ | ||
1961 | return Successful85; | ||
1962 | } | ||
1963 | #else | ||
1964 | if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) { | ||
1965 | /* The code has not been parsed! */ | ||
1966 | *metrics = NULL((void*)0); | ||
1967 | flags &= ~FT_FORCE_CONSTANT_SPACING0x08; | ||
1968 | } | ||
1969 | #endif | ||
1970 | |||
1971 | xrc = FreeTypeInstanceGetGlyphMetrics(idx, flags, metrics, font->instance); | ||
1972 | if( xrc == Successful85 && *metrics != NULL((void*)0) ) | ||
1973 | return Successful85; | ||
1974 | if( font->zero_idx != idx ) { | ||
1975 | xrc = FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags, | ||
1976 | metrics, font->instance); | ||
1977 | if( xrc == Successful85 && *metrics != NULL((void*)0) ) | ||
1978 | return Successful85; | ||
1979 | } | ||
1980 | return FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags|FT_GET_DUMMY0x04, metrics, font->instance); | ||
1981 | } | ||
1982 | |||
1983 | /* | ||
1984 | * restrict code range | ||
1985 | * | ||
1986 | * boolean for the numeric zone: | ||
1987 | * results = results & (ranges[0] | ranges[1] | ... ranges[nranges-1]) | ||
1988 | */ | ||
1989 | |||
1990 | static void | ||
1991 | restrict_code_range(unsigned short *refFirstCol, | ||
1992 | unsigned short *refFirstRow, | ||
1993 | unsigned short *refLastCol, | ||
1994 | unsigned short *refLastRow, | ||
1995 | fsRange const *ranges, int nRanges) | ||
1996 | { | ||
1997 | if (nRanges) { | ||
1998 | int minCol = 256, minRow = 256, maxCol = -1, maxRow = -1; | ||
1999 | fsRange const *r = ranges; | ||
2000 | int i; | ||
2001 | |||
2002 | for (i=0; i<nRanges; i++) { | ||
2003 | if (r->min_char_high != r->max_char_high) { | ||
2004 | minCol = 0x00; | ||
2005 | maxCol = 0xff; | ||
2006 | } else { | ||
2007 | if (minCol > r->min_char_low) | ||
2008 | minCol = r->min_char_low; | ||
2009 | if (maxCol < r->max_char_low) | ||
2010 | maxCol = r->max_char_low; | ||
2011 | } | ||
2012 | if (minRow > r->min_char_high) | ||
2013 | minRow = r->min_char_high; | ||
2014 | if (maxRow < r->max_char_high) | ||
2015 | maxRow = r->max_char_high; | ||
2016 | r++; | ||
2017 | } | ||
2018 | |||
2019 | if (minCol > *refLastCol) | ||
2020 | *refFirstCol = *refLastCol; | ||
2021 | else if (minCol > *refFirstCol) | ||
2022 | *refFirstCol = minCol; | ||
2023 | |||
2024 | if (maxCol < *refFirstCol) | ||
2025 | *refLastCol = *refFirstCol; | ||
2026 | else if (maxCol < *refLastCol) | ||
2027 | *refLastCol = maxCol; | ||
2028 | |||
2029 | if (minRow > *refLastRow) { | ||
2030 | *refFirstRow = *refLastRow; | ||
2031 | *refFirstCol = *refLastCol; | ||
2032 | } else if (minRow > *refFirstRow) | ||
2033 | *refFirstRow = minRow; | ||
2034 | |||
2035 | if (maxRow < *refFirstRow) { | ||
2036 | *refLastRow = *refFirstRow; | ||
2037 | *refLastCol = *refFirstCol; | ||
2038 | } else if (maxRow < *refLastRow) | ||
2039 | *refLastRow = maxRow; | ||
2040 | } | ||
2041 | } | ||
2042 | |||
2043 | |||
2044 | static int | ||
2045 | restrict_code_range_by_str(int count,unsigned short *refFirstCol, | ||
2046 | unsigned short *refFirstRow, | ||
2047 | unsigned short *refLastCol, | ||
2048 | unsigned short *refLastRow, | ||
2049 | char const *str) | ||
2050 | { | ||
2051 | int nRanges = 0; | ||
2052 | int result = 0; | ||
2053 | fsRange *ranges = NULL((void*)0); | ||
2054 | char const *p, *q; | ||
2055 | |||
2056 | p = q = str; | ||
2057 | for (;;) { | ||
2058 | int minpoint=0, maxpoint=65535; | ||
2059 | long val; | ||
2060 | |||
2061 | /* skip comma and/or space */ | ||
2062 | while (',' == *p || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace)) | ||
2063 | p++; | ||
2064 | |||
2065 | /* begin point */ | ||
2066 | if ('-' != *p) { | ||
2067 | val = strtol(p, (char **)&q, 0); | ||
2068 | if (p == q) | ||
2069 | /* end or illegal */ | ||
2070 | break; | ||
2071 | if (val<0 || val>65535) { | ||
2072 | /* out of zone */ | ||
2073 | break; | ||
2074 | } | ||
2075 | minpoint = val; | ||
2076 | p=q; | ||
2077 | } | ||
2078 | |||
2079 | /* skip space */ | ||
2080 | while (isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace)) | ||
2081 | p++; | ||
2082 | |||
2083 | if (',' != *p && '\0' != *p) { | ||
2084 | /* contiune */ | ||
2085 | if ('-' == *p) | ||
2086 | /* hyphon */ | ||
2087 | p++; | ||
2088 | else | ||
2089 | /* end or illegal */ | ||
2090 | break; | ||
2091 | |||
2092 | /* skip space */ | ||
2093 | while (isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int) _ISspace)) | ||
2094 | p++; | ||
2095 | |||
2096 | val = strtol(p, (char **)&q, 0); | ||
2097 | if (p != q) { | ||
2098 | if (val<0 || val>65535) | ||
2099 | break; | ||
2100 | maxpoint = val; | ||
2101 | } else if (',' != *p && '\0' != *p) | ||
2102 | /* end or illegal */ | ||
2103 | break; | ||
2104 | p=q; | ||
2105 | } else | ||
2106 | /* comma - single code */ | ||
2107 | maxpoint = minpoint; | ||
2108 | |||
2109 | if ( count <= 0 && minpoint>maxpoint ) { | ||
2110 | int tmp; | ||
2111 | tmp = minpoint; | ||
2112 | minpoint = maxpoint; | ||
2113 | maxpoint = tmp; | ||
2114 | } | ||
2115 | |||
2116 | /* add range */ | ||
2117 | #if 0 | ||
2118 | fprintf(stderrstderr, "zone: 0x%04X - 0x%04X\n", minpoint, maxpoint); | ||
2119 | fflush(stderrstderr); | ||
2120 | #endif | ||
2121 | nRanges++; | ||
2122 | ranges = realloc(ranges, nRanges*sizeof(*ranges)); | ||
2123 | if (NULL((void*)0) == ranges) | ||
2124 | break; | ||
2125 | { | ||
2126 | fsRange *r = ranges+nRanges-1; | ||
2127 | |||
2128 | r->min_char_low = minpoint & 0xff; | ||
2129 | r->max_char_low = maxpoint & 0xff; | ||
2130 | r->min_char_high = (minpoint>>8) & 0xff; | ||
2131 | r->max_char_high = (maxpoint>>8) & 0xff; | ||
2132 | } | ||
2133 | } | ||
2134 | |||
2135 | if (ranges) { | ||
2136 | if ( count <= 0 ) { | ||
2137 | restrict_code_range(refFirstCol, refFirstRow, refLastCol, refLastRow, | ||
2138 | ranges, nRanges); | ||
2139 | } | ||
2140 | else { | ||
2141 | int i; | ||
2142 | fsRange *r; | ||
2143 | for ( i=0 ; i<nRanges ; i++ ) { | ||
2144 | if ( count <= i ) break; | ||
2145 | r = ranges+i; | ||
2146 | refFirstCol[i] = r->min_char_low; | ||
2147 | refLastCol[i] = r->max_char_low; | ||
2148 | refFirstRow[i] = r->min_char_high; | ||
2149 | refLastRow[i] = r->max_char_high; | ||
2150 | } | ||
2151 | result=i; | ||
2152 | } | ||
2153 | free(ranges); | ||
2154 | } | ||
2155 | return result; | ||
2156 | } | ||
2157 | |||
2158 | /* *face_number and *spacing are initialized but *load_flags is NOT. */ | ||
2159 | static int | ||
2160 | FreeTypeSetUpTTCap( char *fileName, FontScalablePtr vals, | ||
2161 | char **dynStrRealFileName, char **dynStrFTFileName, | ||
2162 | struct TTCapInfo *ret, int *face_number, FT_Int32 *load_flags, | ||
2163 | int *spacing, Bool *font_properties, char **dynStrTTCapCodeRange ) | ||
2164 | { | ||
2165 | int result = Successful85; | ||
2166 | SDynPropRecValList listPropRecVal; | ||
2167 | SPropRecValContainer contRecValue; | ||
2168 | Bool hinting=True(-1); | ||
2169 | Bool isEmbeddedBitmap = True(-1); | ||
2170 | Bool alwaysEmbeddedBitmap = False(0); | ||
2171 | int pixel = vals->pixel; | ||
2172 | |||
2173 | *font_properties=True(-1); | ||
2174 | *dynStrRealFileName=NULL((void*)0); | ||
2175 | *dynStrFTFileName=NULL((void*)0); | ||
2176 | *dynStrTTCapCodeRange=NULL((void*)0); | ||
2177 | |||
2178 | if (SPropRecValList_new(&listPropRecVal)) { | ||
2179 | return AllocError80; | ||
2180 | } | ||
2181 | |||
2182 | { | ||
2183 | int len = strlen(fileName); | ||
2184 | char *capHead = NULL((void*)0); | ||
2185 | { | ||
2186 | /* font cap */ | ||
2187 | char *p1=NULL((void*)0), *p2=NULL((void*)0); | ||
2188 | |||
2189 | p1=strrchr(fileName, '/'); | ||
2190 | if ( p1 == NULL((void*)0) ) p1 = fileName; | ||
2191 | else p1++; | ||
2192 | if (NULL((void*)0) != (p2=strrchr(p1, ':'))) { | ||
2193 | /* colon exist in the right side of slash. */ | ||
2194 | int dirLen = p1-fileName; | ||
2195 | int baseLen = fileName+len - p2 -1; | ||
2196 | |||
2197 | *dynStrRealFileName = malloc(dirLen+baseLen+1); | ||
2198 | if( *dynStrRealFileName == NULL((void*)0) ) { | ||
2199 | result = AllocError80; | ||
2200 | goto quit; | ||
2201 | } | ||
2202 | if ( 0 < dirLen ) | ||
2203 | memcpy(*dynStrRealFileName, fileName, dirLen); | ||
2204 | strcpy(*dynStrRealFileName+dirLen, p2+1); | ||
2205 | capHead = p1; | ||
2206 | } else { | ||
2207 | *dynStrRealFileName = xstrdup(fileName)XttXstrdup((char const*)fileName); | ||
2208 | if( *dynStrRealFileName == NULL((void*)0) ) { | ||
2209 | result = AllocError80; | ||
2210 | goto quit; | ||
2211 | } | ||
2212 | } | ||
2213 | } | ||
2214 | |||
2215 | /* font cap */ | ||
2216 | if (capHead) { | ||
2217 | if (SPropRecValList_add_by_font_cap(&listPropRecVal, | ||
2218 | capHead)) { | ||
2219 | result = BadFontPath86; | ||
2220 | goto quit; | ||
2221 | } | ||
2222 | } | ||
2223 | } | ||
2224 | |||
2225 | *face_number=0; | ||
2226 | *spacing=0; | ||
2227 | ret->autoItalic=0.0; | ||
2228 | ret->scaleWidth=1.0; | ||
2229 | ret->scaleBBoxWidth = 1.0; | ||
2230 | ret->scaleBBoxHeight = 1.0; | ||
2231 | ret->doubleStrikeShift = 1; | ||
2232 | ret->adjustBBoxWidthByPixel = 0; | ||
2233 | ret->adjustLeftSideBearingByPixel = 0; | ||
2234 | ret->adjustRightSideBearingByPixel = 0; | ||
2235 | ret->flags = 0; | ||
2236 | ret->scaleBitmap = 0.0; | ||
2237 | ret->forceConstantSpacingBegin = -1; | ||
2238 | ret->forceConstantSpacingEnd = -1; | ||
2239 | ret->force_c_representative_metrics_char_code = -2; | ||
2240 | ret->force_c_scale_b_box_width = 1.0; | ||
2241 | ret->force_c_scale_b_box_height = 1.0; | ||
2242 | ret->force_c_adjust_width_by_pixel = 0; | ||
2243 | ret->force_c_adjust_lsb_by_pixel = 0; | ||
2244 | ret->force_c_adjust_rsb_by_pixel = 0; | ||
2245 | ret->force_c_scale_lsb = 0.0; | ||
2246 | ret->force_c_scale_rsb = 1.0; | ||
2247 | /* */ | ||
2248 | ret->vl_slant=0; | ||
2249 | ret->lsbShiftOfBitmapAutoItalic=0; | ||
2250 | ret->rsbShiftOfBitmapAutoItalic=0; | ||
2251 | /* face number */ | ||
2252 | { | ||
2253 | char *beginptr=NULL((void*)0),*endptr; | ||
2254 | if ( SPropRecValList_search_record(&listPropRecVal, | ||
2255 | &contRecValue, | ||
2256 | "FaceNumber")) { | ||
2257 | int lv; | ||
2258 | beginptr = SPropContainer_value_str(contRecValue)((contRecValue)->uValue.dynStringValue); | ||
2259 | lv=strtol(beginptr, &endptr, 10); | ||
2260 | if ( *beginptr != '\0' && *endptr == '\0' ) { | ||
2261 | if ( 0 < lv ) *face_number = lv; | ||
2262 | } | ||
2263 | } | ||
2264 | if( beginptr && 0 < *face_number ) { | ||
2265 | char *slash; | ||
2266 | *dynStrFTFileName = /* add -> ':'+strlen0+':'+strlen1+'\0' */ | ||
2267 | malloc(1+strlen(beginptr)+1+strlen(*dynStrRealFileName)+1); | ||
2268 | if( *dynStrFTFileName == NULL((void*)0) ){ | ||
2269 | result = AllocError80; | ||
2270 | goto quit; | ||
2271 | } | ||
2272 | **dynStrFTFileName = '\0'; | ||
2273 | slash = strrchr(*dynStrRealFileName,'/'); | ||
2274 | if( slash ) { | ||
2275 | char *p; | ||
2276 | strcat(*dynStrFTFileName,*dynStrRealFileName); | ||
2277 | p = strrchr(*dynStrFTFileName,'/'); | ||
2278 | p[1] = '\0'; | ||
2279 | strcat(*dynStrFTFileName,":"); | ||
2280 | strcat(*dynStrFTFileName,beginptr); | ||
2281 | strcat(*dynStrFTFileName,":"); | ||
2282 | strcat(*dynStrFTFileName,slash+1); | ||
2283 | } | ||
2284 | else{ | ||
2285 | strcat(*dynStrFTFileName,":"); | ||
2286 | strcat(*dynStrFTFileName,beginptr); | ||
2287 | strcat(*dynStrFTFileName,":"); | ||
2288 | strcat(*dynStrFTFileName,*dynStrRealFileName); | ||
2289 | } | ||
2290 | } | ||
2291 | else{ | ||
2292 | *dynStrFTFileName = malloc(strlen(*dynStrRealFileName)+1); | ||
2293 | if( *dynStrFTFileName == NULL((void*)0) ){ | ||
2294 | result = AllocError80; | ||
2295 | goto quit; | ||
2296 | } | ||
2297 | **dynStrFTFileName = '\0'; | ||
2298 | strcat(*dynStrFTFileName,*dynStrRealFileName); | ||
2299 | } | ||
2300 | } | ||
2301 | /* | ||
2302 | fprintf(stderr,"[Filename:%s]\n",fileName); | ||
2303 | fprintf(stderr,"[RealFilename:%s]\n",*dynStrRealFileName); | ||
2304 | fprintf(stderr,"[FTFilename:%s]\n",*dynStrFTFileName); | ||
2305 | */ | ||
2306 | /* slant control */ | ||
2307 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2308 | &contRecValue, | ||
2309 | "AutoItalic")) | ||
2310 | ret->autoItalic = SPropContainer_value_dbl(contRecValue)((contRecValue)->uValue.doubleValue); | ||
2311 | /* hinting control */ | ||
2312 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2313 | &contRecValue, | ||
2314 | "Hinting")) | ||
2315 | hinting = SPropContainer_value_bool(contRecValue)((contRecValue)->uValue.boolValue); | ||
2316 | /* scaling */ | ||
2317 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2318 | &contRecValue, | ||
2319 | "ScaleWidth")) { | ||
2320 | ret->scaleWidth = SPropContainer_value_dbl(contRecValue)((contRecValue)->uValue.doubleValue); | ||
2321 | if (ret->scaleWidth<=0.0) { | ||
2322 | fprintf(stderrstderr, "ScaleWitdh needs plus.\n"); | ||
2323 | result = BadFontName83; | ||
2324 | goto quit; | ||
2325 | } | ||
2326 | } | ||
2327 | /* bbox adjustment */ | ||
2328 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2329 | &contRecValue, | ||
2330 | "ScaleBBoxWidth")) { | ||
2331 | /* Scaling to Bounding Box Width */ | ||
2332 | int lv; | ||
2333 | char *endptr,*beginptr; | ||
2334 | double v,scaleBBoxWidth=1.0,scaleBBoxHeight=1.0; | ||
2335 | beginptr = SPropContainer_value_str(contRecValue)((contRecValue)->uValue.dynStringValue); | ||
2336 | do { | ||
2337 | if ( strlen(beginptr) < 1 ) break; | ||
2338 | v=strtod(beginptr, &endptr); | ||
2339 | if ( endptr!=beginptr ) { | ||
2340 | scaleBBoxWidth = v; | ||
2341 | } | ||
2342 | if ( *endptr != ';' && *endptr != ',' ) break; | ||
2343 | if ( *endptr == ',' ) { | ||
2344 | beginptr=endptr+1; | ||
2345 | v=strtod(beginptr, &endptr); | ||
2346 | if ( endptr!=beginptr ) { | ||
2347 | scaleBBoxHeight = v; | ||
2348 | } | ||
2349 | } | ||
2350 | if ( *endptr != ';' && *endptr != ',' ) break; | ||
2351 | beginptr=endptr+1; | ||
2352 | lv=strtol(beginptr, &endptr, 10); | ||
2353 | if ( endptr!=beginptr ) { | ||
2354 | ret->adjustBBoxWidthByPixel = lv; | ||
2355 | } | ||
2356 | if ( *endptr != ',' ) break; | ||
2357 | beginptr=endptr+1; | ||
2358 | lv=strtol(beginptr, &endptr, 10); | ||
2359 | if ( endptr!=beginptr ) { | ||
2360 | ret->adjustLeftSideBearingByPixel = lv; | ||
2361 | } | ||
2362 | if ( *endptr != ',' ) break; | ||
2363 | beginptr=endptr+1; | ||
2364 | lv=strtol(beginptr, &endptr, 10); | ||
2365 | if ( endptr!=beginptr ) { | ||
2366 | ret->adjustRightSideBearingByPixel = lv; | ||
2367 | } | ||
2368 | } while ( 0 ); | ||
2369 | if (scaleBBoxWidth<=0.0) { | ||
2370 | fprintf(stderrstderr, "ScaleBBoxWitdh needs plus.\n"); | ||
2371 | result = BadFontName83; | ||
2372 | goto quit; | ||
2373 | } | ||
2374 | if (scaleBBoxHeight<=0.0) { | ||
2375 | fprintf(stderrstderr, "ScaleBBoxHeight needs plus.\n"); | ||
2376 | result = BadFontName83; | ||
2377 | goto quit; | ||
2378 | } | ||
2379 | ret->scaleBBoxWidth = scaleBBoxWidth; | ||
2380 | ret->scaleBBoxHeight = scaleBBoxHeight; | ||
2381 | } | ||
2382 | /* spacing */ | ||
2383 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2384 | &contRecValue, | ||
2385 | "ForceSpacing")) { | ||
2386 | char *strSpace = SPropContainer_value_str(contRecValue)((contRecValue)->uValue.dynStringValue); | ||
2387 | Bool err = False(0); | ||
2388 | if (1 != strlen(strSpace)) | ||
2389 | err = True(-1); | ||
2390 | else | ||
2391 | switch (strSpace[0]) { | ||
2392 | case 'M': | ||
2393 | ret->flags |= TTCAP_MONO_CENTER0x0800; | ||
2394 | *spacing = 'm'; | ||
2395 | break; | ||
2396 | case 'm': | ||
2397 | case 'p': | ||
2398 | case 'c': | ||
2399 | *spacing = strSpace[0]; | ||
2400 | break; | ||
2401 | default: | ||
2402 | err = True(-1); | ||
2403 | } | ||
2404 | if (err) { | ||
2405 | result = BadFontName83; | ||
2406 | goto quit; | ||
2407 | } | ||
2408 | } | ||
2409 | /* doube striking */ | ||
2410 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2411 | &contRecValue, | ||
2412 | "DoubleStrike")) { | ||
2413 | /* Set or Reset Auto Bold Flag */ | ||
2414 | char *strDoubleStrike = SPropContainer_value_str(contRecValue)((contRecValue)->uValue.dynStringValue); | ||
2415 | Bool err = False(0); | ||
2416 | if ( 0 < strlen(strDoubleStrike) ) { | ||
2417 | switch (strDoubleStrike[0]) { | ||
2418 | case 'm': | ||
2419 | case 'M': | ||
2420 | case 'l': | ||
2421 | case 'L': | ||
2422 | ret->flags |= TTCAP_DOUBLE_STRIKE0x0001; | ||
2423 | ret->flags |= TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT0x0002; | ||
2424 | break; | ||
2425 | case 'y': | ||
2426 | case 'Y': | ||
2427 | ret->flags |= TTCAP_DOUBLE_STRIKE0x0001; | ||
2428 | break; | ||
2429 | case 'n': | ||
2430 | case 'N': | ||
2431 | ret->flags &= ~TTCAP_DOUBLE_STRIKE0x0001; | ||
2432 | ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT0x0002; | ||
2433 | ret->flags &= ~TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH0x0008; | ||
2434 | break; | ||
2435 | default: | ||
2436 | err = True(-1); | ||
2437 | } | ||
2438 | if ( err != True(-1) ) { | ||
2439 | if ( strDoubleStrike[1] ) { | ||
2440 | switch (strDoubleStrike[1]) { | ||
2441 | case 'b': | ||
2442 | case 'B': | ||
2443 | case 'p': | ||
2444 | case 'P': | ||
2445 | case 'y': | ||
2446 | case 'Y': | ||
2447 | ret->flags |= TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH0x0008; | ||
2448 | break; | ||
2449 | default: | ||
2450 | break; | ||
2451 | } | ||
2452 | } | ||
2453 | do { | ||
2454 | char *comma_ptr=strchr(strDoubleStrike,';'); | ||
2455 | if ( !comma_ptr ) comma_ptr=strchr(strDoubleStrike,','); | ||
2456 | if ( !comma_ptr ) break; | ||
2457 | if ( comma_ptr[1] ) { | ||
2458 | char *endptr; | ||
2459 | int mkboldMaxPixel; | ||
2460 | mkboldMaxPixel=strtol(comma_ptr+1, &endptr, 10); | ||
2461 | if ( endptr != comma_ptr+1 && mkboldMaxPixel <= pixel ) { | ||
2462 | ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT0x0002; | ||
2463 | } | ||
2464 | } | ||
2465 | comma_ptr=strchr(comma_ptr+1,','); | ||
2466 | if ( !comma_ptr ) break; | ||
2467 | if ( comma_ptr[1] ) { | ||
2468 | char *endptr; | ||
2469 | int max_pixel; | ||
2470 | max_pixel=strtol(comma_ptr+1, &endptr, 10); | ||
2471 | if ( endptr != comma_ptr+1 && max_pixel <= pixel ) { | ||
2472 | if( ret->flags & TTCAP_DOUBLE_STRIKE0x0001 ) | ||
2473 | ret->doubleStrikeShift += pixel / max_pixel; | ||
2474 | } | ||
2475 | } | ||
2476 | } while(0); | ||
2477 | } | ||
2478 | } | ||
2479 | else | ||
2480 | err = True(-1); | ||
2481 | if (err) { | ||
2482 | result = BadFontName83; | ||
2483 | goto quit; | ||
2484 | } | ||
2485 | } | ||
2486 | /* very lazy metrics */ | ||
2487 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2488 | &contRecValue, | ||
2489 | "VeryLazyMetrics")){ | ||
2490 | Bool isVeryLazy = SPropContainer_value_bool(contRecValue)((contRecValue)->uValue.boolValue); | ||
2491 | ret->flags |= TTCAP_DISABLE_DEFAULT_VERY_LAZY0x0020; | ||
2492 | if( isVeryLazy == True(-1) ) | ||
2493 | ret->flags |= TTCAP_IS_VERY_LAZY0x0010; | ||
2494 | else | ||
2495 | ret->flags &= ~TTCAP_IS_VERY_LAZY0x0010; | ||
2496 | } | ||
2497 | /* embedded bitmap */ | ||
2498 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2499 | &contRecValue, | ||
2500 | "EmbeddedBitmap")) { | ||
2501 | char *strEmbeddedBitmap = SPropContainer_value_str(contRecValue)((contRecValue)->uValue.dynStringValue); | ||
2502 | Bool err = False(0); | ||
2503 | if ( 1 == strlen(strEmbeddedBitmap) ) { | ||
2504 | switch (strEmbeddedBitmap[0]) { | ||
2505 | case 'y': | ||
2506 | case 'Y': | ||
2507 | isEmbeddedBitmap = True(-1); | ||
2508 | alwaysEmbeddedBitmap = True(-1); | ||
2509 | break; | ||
2510 | case 'u': | ||
2511 | case 'U': | ||
2512 | isEmbeddedBitmap = True(-1); | ||
2513 | alwaysEmbeddedBitmap = False(0); | ||
2514 | break; | ||
2515 | case 'n': | ||
2516 | case 'N': | ||
2517 | isEmbeddedBitmap = False(0); | ||
2518 | break; | ||
2519 | default: | ||
2520 | err = True(-1); | ||
2521 | } | ||
2522 | } | ||
2523 | else | ||
2524 | err = True(-1); | ||
2525 | if (err) { | ||
2526 | result = BadFontName83; | ||
2527 | goto quit; | ||
2528 | } | ||
2529 | } | ||
2530 | /* scale bitmap */ | ||
2531 | if((ret->flags & TTCAP_IS_VERY_LAZY0x0010) && | ||
2532 | SPropRecValList_search_record(&listPropRecVal, | ||
2533 | &contRecValue, | ||
2534 | "VeryLazyBitmapWidthScale")) { | ||
2535 | /* Scaling to Bitmap Bounding Box Width */ | ||
2536 | double scaleBitmapWidth = SPropContainer_value_dbl(contRecValue)((contRecValue)->uValue.doubleValue); | ||
2537 | |||
2538 | fprintf(stderrstderr, "Warning: `bs' option is not required in X-TT version 2.\n"); | ||
2539 | #if 0 | ||
2540 | if (scaleBitmapWidth<=0.0) { | ||
2541 | fprintf(stderrstderr, "ScaleBitmapWitdh needs plus.\n"); | ||
2542 | result = BadFontName83; | ||
2543 | goto quit; | ||
2544 | } | ||
2545 | #endif | ||
2546 | ret->scaleBitmap = scaleBitmapWidth; | ||
2547 | } | ||
2548 | /* restriction of the code range */ | ||
2549 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2550 | &contRecValue, | ||
2551 | "CodeRange")) { | ||
2552 | *dynStrTTCapCodeRange = xstrdup(SPropContainer_value_str(contRecValue))XttXstrdup((char const*)((contRecValue)->uValue.dynStringValue )); | ||
2553 | if( *dynStrTTCapCodeRange == NULL((void*)0) ) { | ||
2554 | result = AllocError80; | ||
2555 | goto quit; | ||
2556 | } | ||
2557 | } | ||
2558 | /* forceConstantSpacing{Begin,End} */ | ||
2559 | if ( 1 /* ft->spacing == 'p' */ ){ | ||
2560 | unsigned short first_col=0,last_col=0x00ff; | ||
2561 | unsigned short first_row=0,last_row=0x00ff; | ||
2562 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2563 | &contRecValue, | ||
2564 | "ForceConstantSpacingCodeRange")) { | ||
2565 | if ( restrict_code_range_by_str(1,&first_col, &first_row, | ||
2566 | &last_col, &last_row, | ||
2567 | SPropContainer_value_str(contRecValue)((contRecValue)->uValue.dynStringValue)) == 1 ) { | ||
2568 | ret->forceConstantSpacingBegin = (int)( first_row<<8 | first_col ); | ||
2569 | ret->forceConstantSpacingEnd = (int)( last_row<<8 | last_col ); | ||
2570 | if ( ret->forceConstantSpacingBegin <= ret->forceConstantSpacingEnd ) | ||
2571 | ret->flags &= ~TTCAP_FORCE_C_OUTSIDE0x0400; | ||
2572 | else ret->flags |= TTCAP_FORCE_C_OUTSIDE0x0400; | ||
2573 | } | ||
2574 | } | ||
2575 | } | ||
2576 | /* */ | ||
2577 | if ( 1 ){ | ||
2578 | unsigned short first_col=0, last_col=0x0ff; | ||
2579 | unsigned short first_row=0, last_row=0x0ff; | ||
2580 | if ( SPropRecValList_search_record(&listPropRecVal, | ||
2581 | &contRecValue, | ||
2582 | "ForceConstantSpacingMetrics")) { | ||
2583 | char *strMetrics; | ||
2584 | strMetrics = SPropContainer_value_str(contRecValue)((contRecValue)->uValue.dynStringValue); | ||
2585 | if ( strMetrics ) { | ||
2586 | char *comma_ptr,*period_ptr,*semic_ptr; | ||
2587 | semic_ptr=strchr(strMetrics,';'); | ||
2588 | comma_ptr=strchr(strMetrics,','); | ||
2589 | period_ptr=strchr(strMetrics,'.'); | ||
2590 | if ( semic_ptr && comma_ptr ) | ||
2591 | if ( semic_ptr < comma_ptr ) comma_ptr=NULL((void*)0); | ||
2592 | if ( semic_ptr && period_ptr ) | ||
2593 | if ( semic_ptr < period_ptr ) period_ptr=NULL((void*)0); | ||
2594 | if ( !comma_ptr && !period_ptr && strMetrics != semic_ptr ) { | ||
2595 | if ( restrict_code_range_by_str(1,&first_col, &first_row, | ||
2596 | &last_col, &last_row, | ||
2597 | SPropContainer_value_str(contRecValue)((contRecValue)->uValue.dynStringValue)) == 1 ) { | ||
2598 | ret->force_c_representative_metrics_char_code = | ||
2599 | (int)( first_row<<8 | first_col ); | ||
2600 | } | ||
2601 | } | ||
2602 | else { | ||
2603 | double v; | ||
2604 | char *endptr,*beginptr=strMetrics; | ||
2605 | do { | ||
2606 | v=strtod(beginptr, &endptr); | ||
2607 | if ( endptr!=beginptr ) { | ||
2608 | ret->force_c_scale_b_box_width = v; | ||
2609 | } | ||
2610 | if ( *endptr != ',' ) break; | ||
2611 | beginptr=endptr+1; | ||
2612 | v=strtod(beginptr, &endptr); | ||
2613 | if ( endptr!=beginptr ) { | ||
2614 | ret->force_c_scale_lsb = v; | ||
2615 | ret->flags |= TTCAP_FORCE_C_LSB_FLAG0x0100; | ||
2616 | } | ||
2617 | if ( *endptr != ',' ) break; | ||
2618 | beginptr=endptr+1; | ||
2619 | v=strtod(beginptr, &endptr); | ||
2620 | if ( endptr!=beginptr ) { | ||
2621 | ret->force_c_scale_rsb = v; | ||
2622 | ret->flags |= TTCAP_FORCE_C_RSB_FLAG0x0200; | ||
2623 | } | ||
2624 | if ( *endptr != ',' ) break; | ||
2625 | beginptr=endptr+1; | ||
2626 | v=strtod(beginptr, &endptr); | ||
2627 | if ( endptr!=beginptr ) { | ||
2628 | ret->force_c_scale_b_box_height = v; | ||
2629 | } | ||
2630 | } while (0); | ||
2631 | } | ||
2632 | if ( semic_ptr ) { | ||
2633 | int lv; | ||
2634 | char *endptr,*beginptr=semic_ptr+1; | ||
2635 | do { | ||
2636 | lv=strtol(beginptr, &endptr, 10); | ||
2637 | if ( endptr!=beginptr ) { | ||
2638 | ret->force_c_adjust_width_by_pixel=lv; | ||
2639 | } | ||
2640 | if ( *endptr != ',' ) break; | ||
2641 | beginptr=endptr+1; | ||
2642 | lv=strtol(beginptr, &endptr, 10); | ||
2643 | if ( endptr!=beginptr ) { | ||
2644 | ret->force_c_adjust_lsb_by_pixel=lv; | ||
2645 | } | ||
2646 | if ( *endptr != ',' ) break; | ||
2647 | beginptr=endptr+1; | ||
2648 | lv=strtol(beginptr, &endptr, 10); | ||
2649 | if ( endptr!=beginptr ) { | ||
2650 | ret->force_c_adjust_rsb_by_pixel=lv; | ||
2651 | } | ||
2652 | } while (0); | ||
2653 | } | ||
2654 | } | ||
2655 | } | ||
2656 | } | ||
2657 | |||
2658 | if (SPropRecValList_search_record(&listPropRecVal, | ||
2659 | &contRecValue, | ||
2660 | "FontProperties")) { | ||
2661 | /* Set or Reset the Flag of FontProperties */ | ||
2662 | *font_properties=SPropContainer_value_bool(contRecValue)((contRecValue)->uValue.boolValue); | ||
2663 | } | ||
2664 | |||
2665 | ret->force_c_scale_b_box_width *= ret->scaleBBoxWidth; | ||
2666 | ret->force_c_scale_b_box_height *= ret->scaleBBoxHeight; | ||
2667 | |||
2668 | ret->force_c_scale_b_box_width *= ret->scaleWidth; | ||
2669 | ret->scaleBBoxWidth *= ret->scaleWidth; | ||
2670 | |||
2671 | ret->force_c_adjust_rsb_by_pixel += ret->adjustRightSideBearingByPixel; | ||
2672 | ret->force_c_adjust_lsb_by_pixel += ret->adjustLeftSideBearingByPixel; | ||
2673 | |||
2674 | /* scaleWidth, scaleBBoxWidth, force_c_scale_b_box_width, force_c_scale_b_box_width */ | ||
2675 | |||
2676 | /* by TTCap */ | ||
2677 | if( hinting == False(0) ) *load_flags |= FT_LOAD_NO_HINTING0x2; | ||
2678 | if( isEmbeddedBitmap == False(0) ) *load_flags |= FT_LOAD_NO_BITMAP0x8; | ||
2679 | if( ret->autoItalic != 0 && alwaysEmbeddedBitmap == False(0) ) | ||
2680 | *load_flags |= FT_LOAD_NO_BITMAP0x8; | ||
2681 | |||
2682 | quit: | ||
2683 | return result; | ||
2684 | } | ||
2685 | |||
2686 | static int | ||
2687 | ft_get_trans_from_vals( FontScalablePtr vals, FTNormalisedTransformationPtr trans ) | ||
2688 | { | ||
2689 | /* Compute the transformation matrix. We use floating-point | ||
2690 | arithmetic for simplicity */ | ||
2691 | |||
2692 | trans->xres = vals->x; | ||
2693 | trans->yres = vals->y; | ||
2694 | |||
2695 | /* This value cannot be 0. */ | ||
2696 | trans->scale = hypot(vals->point_matrix[2], vals->point_matrix[3]); | ||
2697 | trans->nonIdentity = 0; | ||
2698 | |||
2699 | /* Try to round stuff. We want approximate zeros to be exact zeros, | ||
2700 | and if the elements on the diagonal are approximately equal, we | ||
2701 | want them equal. We do this to avoid breaking hinting. */ | ||
2702 | if(DIFFER(vals->point_matrix[0], vals->point_matrix[3])(fabs((vals->point_matrix[0])-(vals->point_matrix[3]))>= ((double)0.001)*fabs(vals->point_matrix[0]))) { | ||
2703 | trans->nonIdentity = 1; | ||
2704 | trans->matrix.xx = | ||
2705 | (int)((vals->point_matrix[0]*(double)TWO_SIXTEENTH((double)(1<<16)))/trans->scale); | ||
2706 | trans->matrix.yy = | ||
2707 | (int)((vals->point_matrix[3]*(double)TWO_SIXTEENTH((double)(1<<16)))/trans->scale); | ||
2708 | } else { | ||
2709 | trans->matrix.xx = trans->matrix.yy = | ||
2710 | ((vals->point_matrix[0] + vals->point_matrix[3])/2* | ||
2711 | (double)TWO_SIXTEENTH((double)(1<<16)))/trans->scale; | ||
2712 | } | ||
2713 | |||
2714 | if(DIFFER0(vals->point_matrix[1], trans->scale)(fabs(vals->point_matrix[1])>=((double)0.001)*fabs(trans ->scale))) { | ||
2715 | trans->matrix.yx = | ||
2716 | (int)((vals->point_matrix[1]*(double)TWO_SIXTEENTH((double)(1<<16)))/trans->scale); | ||
2717 | trans->nonIdentity = 1; | ||
2718 | } else | ||
2719 | trans->matrix.yx = 0; | ||
2720 | |||
2721 | if(DIFFER0(vals->point_matrix[2], trans->scale)(fabs(vals->point_matrix[2])>=((double)0.001)*fabs(trans ->scale))) { | ||
2722 | trans->matrix.xy = | ||
2723 | (int)((vals->point_matrix[2]*(double)TWO_SIXTEENTH((double)(1<<16)))/trans->scale); | ||
2724 | trans->nonIdentity = 1; | ||
2725 | } else | ||
2726 | trans->matrix.xy=0; | ||
2727 | return 0; | ||
2728 | } | ||
2729 | |||
2730 | |||
2731 | static int | ||
2732 | is_fixed_width(FT_Face face) | ||
2733 | { | ||
2734 | PS_FontInfoRec t1info_rec; | ||
2735 | int ftrc; | ||
2736 | |||
2737 | if(FT_IS_FIXED_WIDTH(face)( face->face_flags & ( 1L << 2 ) )) { | ||
2738 | return 1; | ||
2739 | } | ||
2740 | |||
2741 | ftrc = FT_Get_PS_Font_Info(face, &t1info_rec); | ||
2742 | if(ftrc == 0 && t1info_rec.is_fixed_pitch) { | ||
2743 | return 1; | ||
2744 | } | ||
2745 | |||
2746 | return 0; | ||
2747 | } | ||
2748 | |||
2749 | static int | ||
2750 | FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face, | ||
2751 | char *FTFileName, FontScalablePtr vals, FontEntryPtr entry, | ||
2752 | FontBitmapFormatPtr bmfmt, FT_Int32 load_flags, | ||
2753 | struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange, | ||
2754 | int ttcap_spacing ) | ||
2755 | { | ||
2756 | int xrc; | ||
2757 | FTNormalisedTransformationRec trans; | ||
2758 | int spacing, actual_spacing, zero_code; | ||
2759 | long lastCode, firstCode; | ||
2760 | TT_Postscript *post; | ||
2761 | |||
2762 | ft_get_trans_from_vals(vals,&trans); | ||
2763 | |||
2764 | /* Check for charcell in XLFD */ | ||
2765 | spacing = FT_PROPORTIONAL0; | ||
2766 | if(entry->name.ndashes == 14) { | ||
| |||
2767 | char *p; | ||
2768 | int dashes = 0; | ||
2769 | for(p = entry->name.name; | ||
2770 | p <= entry->name.name + entry->name.length - 2; | ||
2771 | p++) { | ||
2772 | if(*p == '-') { | ||
2773 | dashes++; | ||
2774 | if(dashes == 11) { | ||
2775 | if(p[1]=='c' && p[2]=='-') | ||
2776 | spacing=FT_CHARCELL2; | ||
2777 | else if(p[1]=='m' && p[2]=='-') | ||
2778 | spacing=FT_MONOSPACED1; | ||
2779 | break; | ||
2780 | } | ||
2781 | } | ||
2782 | } | ||
2783 | } | ||
2784 | /* by TTCap */ | ||
2785 | if( ttcap_spacing != 0 ) { | ||
| |||
| |||
2786 | if( ttcap_spacing == 'c' ) spacing=FT_CHARCELL2; | ||
2787 | else if( ttcap_spacing == 'm' ) spacing=FT_MONOSPACED1; | ||
2788 | else spacing=FT_PROPORTIONAL0; | ||
2789 | } | ||
2790 | |||
2791 | actual_spacing = spacing; | ||
2792 | if( spacing == FT_PROPORTIONAL0 ) { | ||
| |||
2793 | if( is_fixed_width(face->face) ) | ||
| |||
2794 | actual_spacing = FT_MONOSPACED1; | ||
2795 | } | ||
2796 | |||
2797 | if(entry->name.ndashes == 14) { | ||
| |||
2798 | xrc = FTPickMapping(entry->name.name, entry->name.length, FTFileName, | ||
2799 | face->face, &font->mapping); | ||
2800 | if (xrc != Successful85) | ||
2801 | return xrc; | ||
2802 | } else { | ||
2803 | xrc = FTPickMapping(0, 0, FTFileName, | ||
2804 | face->face, &font->mapping); | ||
2805 | if (xrc != Successful85) | ||
| |||
| |||
2806 | return xrc; | ||
2807 | } | ||
2808 | |||
2809 | font->nranges = vals->nranges; | ||
2810 | font->ranges = 0; | ||
2811 | if(font->nranges) { | ||
| |||
2812 | font->ranges = malloc(vals->nranges*sizeof(fsRange)); | ||
2813 | if(font->ranges == NULL((void*)0)) | ||
2814 | return AllocError80; | ||
2815 | memcpy((char*)font->ranges, (char*)vals->ranges, | ||
2816 | vals->nranges*sizeof(fsRange)); | ||
2817 | } | ||
2818 | |||
2819 | zero_code=-1; | ||
2820 | if(info) { | ||
| |||
| |||
2821 | firstCode = 0; | ||
2822 | lastCode = 0xFFFFL; | ||
2823 | if(!font->mapping.mapping || | ||
2824 | font->mapping.mapping->encoding->row_size == 0) { | ||
2825 | /* linear indexing */ | ||
2826 | lastCode=MIN(lastCode,((lastCode) < (font->mapping.mapping ? font->mapping .mapping->encoding->size-1 : 0xFF) ? (lastCode) : (font ->mapping.mapping ? font->mapping.mapping->encoding-> size-1 : 0xFF)) | ||
2827 | font->mapping.mapping ?((lastCode) < (font->mapping.mapping ? font->mapping .mapping->encoding->size-1 : 0xFF) ? (lastCode) : (font ->mapping.mapping ? font->mapping.mapping->encoding-> size-1 : 0xFF)) | ||
2828 | font->mapping.mapping->encoding->size-1 :((lastCode) < (font->mapping.mapping ? font->mapping .mapping->encoding->size-1 : 0xFF) ? (lastCode) : (font ->mapping.mapping ? font->mapping.mapping->encoding-> size-1 : 0xFF)) | ||
2829 | 0xFF)((lastCode) < (font->mapping.mapping ? font->mapping .mapping->encoding->size-1 : 0xFF) ? (lastCode) : (font ->mapping.mapping ? font->mapping.mapping->encoding-> size-1 : 0xFF)); | ||
2830 | if(font->mapping.mapping && font->mapping.mapping->encoding->first) | ||
2831 | firstCode = font->mapping.mapping->encoding->first; | ||
2832 | info->firstRow = firstCode/0x100; | ||
2833 | info->lastRow = lastCode/0x100; | ||
2834 | info->firstCol = | ||
2835 | (info->firstRow || info->lastRow) ? 0 : (firstCode & 0xFF); | ||
2836 | info->lastCol = info->lastRow ? 0xFF : (lastCode & 0xFF); | ||
2837 | if ( firstCode == 0 ) zero_code=0; | ||
2838 | } else { | ||
2839 | /* matrix indexing */ | ||
2840 | info->firstRow = font->mapping.mapping->encoding->first; | ||
2841 | info->lastRow = MIN(font->mapping.mapping->encoding->size-1,((font->mapping.mapping->encoding->size-1) < (lastCode /0x100) ? (font->mapping.mapping->encoding->size-1) : (lastCode/0x100)) | ||
2842 | lastCode/0x100)((font->mapping.mapping->encoding->size-1) < (lastCode /0x100) ? (font->mapping.mapping->encoding->size-1) : (lastCode/0x100)); | ||
2843 | info->firstCol = font->mapping.mapping->encoding->first_col; | ||
2844 | info->lastCol = MIN(font->mapping.mapping->encoding->row_size-1,((font->mapping.mapping->encoding->row_size-1) < ( lastCode<0x100?lastCode:0xFF) ? (font->mapping.mapping-> encoding->row_size-1) : (lastCode<0x100?lastCode:0xFF)) | ||
2845 | lastCode<0x100?lastCode:0xFF)((font->mapping.mapping->encoding->row_size-1) < ( lastCode<0x100?lastCode:0xFF) ? (font->mapping.mapping-> encoding->row_size-1) : (lastCode<0x100?lastCode:0xFF)); | ||
2846 | if( info->firstRow == 0 && info->firstCol == 0 ) zero_code=0; | ||
2847 | } | ||
2848 | |||
2849 | /* firstCode and lastCode are not valid in case of a matrix | ||
2850 | encoding */ | ||
2851 | |||
2852 | if( dynStrTTCapCodeRange ) { | ||
2853 | restrict_code_range_by_str(0,&info->firstCol, &info->firstRow, | ||
2854 | &info->lastCol, &info->lastRow, | ||
2855 | dynStrTTCapCodeRange); | ||
2856 | } | ||
2857 | restrict_code_range(&info->firstCol, &info->firstRow, | ||
2858 | &info->lastCol, &info->lastRow, | ||
2859 | font->ranges, font->nranges); | ||
2860 | } | ||
2861 | font->info = info; | ||
2862 | |||
2863 | /* zero code is frequently used. */ | ||
2864 | if ( zero_code < 0 ) { | ||
| |||
2865 | /* The fontenc should have the information of DefaultCh. | ||
2866 | But we do not have such a information. | ||
2867 | So we cannot but set 0. */ | ||
2868 | font->zero_idx = 0; | ||
2869 | } | ||
2870 | else | ||
2871 | font->zero_idx = FTRemap(face->face, | ||
2872 | &font->mapping, zero_code); | ||
2873 | |||
2874 | post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post); | ||
2875 | |||
2876 | #ifdef DEFAULT_VERY_LAZY2 | ||
2877 | if( !( tmp_ttcap->flags & TTCAP_DISABLE_DEFAULT_VERY_LAZY0x0020 ) ) | ||
| |||
2878 | if( DEFAULT_VERY_LAZY2 <= 1 + info->lastRow - info->firstRow ) { | ||
| |||
2879 | if( post ){ | ||
2880 | tmp_ttcap->flags |= TTCAP_IS_VERY_LAZY0x0010; | ||
2881 | } | ||
2882 | } | ||
2883 | #endif | ||
2884 | /* We should always reset. */ | ||
2885 | tmp_ttcap->flags &= ~TTCAP_DISABLE_DEFAULT_VERY_LAZY0x0020; | ||
2886 | |||
2887 | if ( face->bitmap || actual_spacing == FT_CHARCELL2 ) | ||
2888 | tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY0x0010; | ||
2889 | /* "vl=y" is available when TrueType or OpenType only */ | ||
2890 | if ( !face->bitmap && !(FT_IS_SFNT( face->face )( face->face->face_flags & ( 1L << 3 ) )) ) | ||
2891 | tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY0x0010; | ||
2892 | |||
2893 | if( post ) { | ||
2894 | if( post->italicAngle != 0 ) | ||
2895 | tmp_ttcap->vl_slant = -sin( (post->italicAngle/1024./5760.)*1.57079632679489661923 ); | ||
2896 | /* fprintf(stderr,"angle=%g(%g)\n",tmp_ttcap->vl_slant,(post->italicAngle/1024./5760.)*90); */ | ||
2897 | } | ||
2898 | |||
2899 | xrc = FreeTypeOpenInstance(&font->instance, face, | ||
2900 | FTFileName, &trans, actual_spacing, bmfmt, | ||
2901 | tmp_ttcap, load_flags ); | ||
2902 | return xrc; | ||
2903 | } | ||
2904 | |||
2905 | static void | ||
2906 | adjust_min_max(xCharInfo *minc, xCharInfo *maxc, xCharInfo *tmp) | ||
2907 | { | ||
2908 | #define MINMAX(field,ci) \ | ||
2909 | if (minc->field > (ci)->field) \ | ||
2910 | minc->field = (ci)->field; \ | ||
2911 | if (maxc->field < (ci)->field) \ | ||
2912 | maxc->field = (ci)->field; | ||
2913 | |||
2914 | MINMAX(ascent, tmp); | ||
2915 | MINMAX(descent, tmp); | ||
2916 | MINMAX(leftSideBearing, tmp); | ||
2917 | MINMAX(rightSideBearing, tmp); | ||
2918 | MINMAX(characterWidth, tmp); | ||
2919 | |||
2920 | if ((INT16)minc->attributes > (INT16)tmp->attributes) | ||
2921 | minc->attributes = tmp->attributes; | ||
2922 | if ((INT16)maxc->attributes < (INT16)tmp->attributes) | ||
2923 | maxc->attributes = tmp->attributes; | ||
2924 | #undef MINMAX | ||
2925 | } | ||
2926 | |||
2927 | static void | ||
2928 | ft_compute_bounds(FTFontPtr font, FontInfoPtr pinfo, FontScalablePtr vals ) | ||
2929 | { | ||
2930 | FTInstancePtr instance; | ||
2931 | int row, col; | ||
2932 | unsigned int c; | ||
2933 | xCharInfo minchar, maxchar, *tmpchar = NULL((void*)0); | ||
2934 | int overlap, maxOverlap; | ||
2935 | long swidth = 0; | ||
2936 | long total_width = 0; | ||
2937 | int num_cols, num_chars = 0; | ||
2938 | int flags, skip_ok = 0; | ||
2939 | int force_c_outside ; | ||
2940 | |||
2941 | instance = font->instance; | ||
2942 | force_c_outside = instance->ttcap.flags & TTCAP_FORCE_C_OUTSIDE0x0400; | ||
2943 | |||
2944 | minchar.ascent = minchar.descent = | ||
2945 | minchar.leftSideBearing = minchar.rightSideBearing = | ||
2946 | minchar.characterWidth = minchar.attributes = 32767; | ||
2947 | maxchar.ascent = maxchar.descent = | ||
2948 | maxchar.leftSideBearing = maxchar.rightSideBearing = | ||
2949 | maxchar.characterWidth = maxchar.attributes = -32767; | ||
2950 | maxOverlap = -32767; | ||
2951 | |||
2952 | /* Parse all glyphs */ | ||
2953 | num_cols = 1 + pinfo->lastCol - pinfo->firstCol; | ||
2954 | for (row = pinfo->firstRow; row <= pinfo->lastRow; row++) { | ||
2955 | if ( skip_ok && tmpchar ) { | ||
2956 | if ( !force_c_outside ) { | ||
2957 | if ( instance->ttcap.forceConstantSpacingBegin < row<<8 | ||
2958 | && row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) { | ||
2959 | if (tmpchar->characterWidth) { | ||
2960 | num_chars += num_cols; | ||
2961 | swidth += ABS(tmpchar->characterWidth)((tmpchar->characterWidth) >= 0 ? (tmpchar->characterWidth ) : -(tmpchar->characterWidth))*num_cols; | ||
2962 | total_width += tmpchar->characterWidth*num_cols; | ||
2963 | continue; | ||
2964 | } | ||
2965 | } | ||
2966 | else skip_ok=0; | ||
2967 | } | ||
2968 | else { /* for GB18030 proportional */ | ||
2969 | if ( instance->ttcap.forceConstantSpacingBegin < row<<8 | ||
2970 | || row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) { | ||
2971 | if (tmpchar->characterWidth) { | ||
2972 | num_chars += num_cols; | ||
2973 | swidth += ABS(tmpchar->characterWidth)((tmpchar->characterWidth) >= 0 ? (tmpchar->characterWidth ) : -(tmpchar->characterWidth))*num_cols; | ||
2974 | total_width += tmpchar->characterWidth*num_cols; | ||
2975 | continue; | ||
2976 | } | ||
2977 | } | ||
2978 | else skip_ok=0; | ||
2979 | } | ||
2980 | } | ||
2981 | for (col = pinfo->firstCol; col <= pinfo->lastCol; col++) { | ||
2982 | c = row<<8|col; | ||
2983 | flags=0; | ||
2984 | if ( !force_c_outside ) { | ||
2985 | if ( c <= instance->ttcap.forceConstantSpacingEnd | ||
2986 | && instance->ttcap.forceConstantSpacingBegin <= c ) | ||
2987 | flags|=FT_FORCE_CONSTANT_SPACING0x08; | ||
2988 | } | ||
2989 | else { /* for GB18030 proportional */ | ||
2990 | if ( c <= instance->ttcap.forceConstantSpacingEnd | ||
2991 | || instance->ttcap.forceConstantSpacingBegin <= c ) | ||
2992 | flags|=FT_FORCE_CONSTANT_SPACING0x08; | ||
2993 | } | ||
2994 | #if 0 | ||
2995 | fprintf(stderrstderr, "comp_bounds: %x ->", c); | ||
2996 | #endif | ||
2997 | if ( skip_ok == 0 || flags == 0 ){ | ||
2998 | tmpchar=NULL((void*)0); | ||
2999 | #if 0 | ||
3000 | fprintf(stderrstderr, "%x\n", c); | ||
3001 | #endif | ||
3002 | if( FreeTypeFontGetGlyphMetrics(c, flags, &tmpchar, font) != Successful85 ) | ||
3003 | continue; | ||
3004 | } | ||
3005 | if ( !tmpchar ) continue; | ||
3006 | adjust_min_max(&minchar, &maxchar, tmpchar); | ||
3007 | overlap = tmpchar->rightSideBearing - tmpchar->characterWidth; | ||
3008 | if (maxOverlap < overlap) | ||
3009 | maxOverlap = overlap; | ||
3010 | |||
3011 | if (!tmpchar->characterWidth) | ||
3012 | continue; | ||
3013 | num_chars++; | ||
3014 | swidth += ABS(tmpchar->characterWidth)((tmpchar->characterWidth) >= 0 ? (tmpchar->characterWidth ) : -(tmpchar->characterWidth)); | ||
3015 | total_width += tmpchar->characterWidth; | ||
3016 | |||
3017 | if ( flags & FT_FORCE_CONSTANT_SPACING0x08 ) skip_ok=1; | ||
3018 | } | ||
3019 | } | ||
3020 | |||
3021 | #ifndef X_ACCEPTS_NO_SUCH_CHAR | ||
3022 | /* Check code 0 */ | ||
3023 | if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, 0, &tmpchar, font->instance) != Successful85 || tmpchar == NULL((void*)0)) | ||
3024 | if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, FT_GET_DUMMY0x04, &tmpchar, font->instance) != Successful85 ) | ||
3025 | tmpchar = NULL((void*)0); | ||
3026 | if ( tmpchar ) { | ||
3027 | adjust_min_max(&minchar, &maxchar, tmpchar); | ||
3028 | overlap = tmpchar->rightSideBearing - tmpchar->characterWidth; | ||
3029 | if (maxOverlap < overlap) | ||
3030 | maxOverlap = overlap; | ||
3031 | } | ||
3032 | #endif | ||
3033 | |||
3034 | /* AVERAGE_WIDTH ... 1/10 pixel unit */ | ||
3035 | if (num_chars > 0) { | ||
3036 | swidth = (swidth * 10.0 + num_chars / 2.0) / num_chars; | ||
3037 | if (total_width < 0) | ||
3038 | swidth = -swidth; | ||
3039 | vals->width = swidth; | ||
3040 | } else | ||
3041 | vals->width = 0; | ||
3042 | |||
3043 | /* | ||
3044 | if (char_width.pixel) { | ||
3045 | maxchar.characterWidth = char_width.pixel; | ||
3046 | minchar.characterWidth = char_width.pixel; | ||
3047 | } | ||
3048 | */ | ||
3049 | |||
3050 | pinfo->maxbounds = maxchar; | ||
3051 | pinfo->minbounds = minchar; | ||
3052 | pinfo->ink_maxbounds = maxchar; | ||
3053 | pinfo->ink_minbounds = minchar; | ||
3054 | pinfo->maxOverlap = maxOverlap; | ||
3055 | } | ||
3056 | |||
3057 | static int | ||
3058 | compute_new_extents( FontScalablePtr vals, double scale, double lsb, double rsb, double desc, double asc, | ||
3059 | int *lsb_result, int *rsb_result, int *desc_result, int *asc_result ) | ||
3060 | { | ||
3061 | #define TRANSFORM_POINT(matrix, x, y, dest) \ | ||
3062 | ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \ | ||
3063 | (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y)) | ||
3064 | |||
3065 | #define CHECK_EXTENT(lsb, rsb, desc, asc, data) \ | ||
3066 | ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \ | ||
3067 | (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \ | ||
3068 | (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \ | ||
3069 | (asc) < (data)[1] ? (asc) = (data)[1] : 0) | ||
3070 | double newlsb, newrsb, newdesc, newasc; | ||
3071 | double point[2]; | ||
3072 | |||
3073 | /* Compute new extents for this glyph */ | ||
3074 | TRANSFORM_POINT(vals->pixel_matrix, lsb, -desc, point); | ||
3075 | newlsb = point[0]; | ||
3076 | newrsb = newlsb; | ||
3077 | newdesc = -point[1]; | ||
3078 | newasc = -newdesc; | ||
3079 | TRANSFORM_POINT(vals->pixel_matrix, lsb, asc, point); | ||
3080 | CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); | ||
3081 | TRANSFORM_POINT(vals->pixel_matrix, rsb, -desc, point); | ||
3082 | CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); | ||
3083 | TRANSFORM_POINT(vals->pixel_matrix, rsb, asc, point); | ||
3084 | CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point); | ||
3085 | |||
3086 | /* ???: lsb = (int)floor(newlsb * scale); */ | ||
3087 | *lsb_result = (int)floor(newlsb * scale + 0.5); | ||
3088 | *rsb_result = (int)floor(newrsb * scale + 0.5); | ||
3089 | *desc_result = (int)ceil(newdesc * scale - 0.5); | ||
3090 | *asc_result = (int)floor(newasc * scale + 0.5); | ||
3091 | |||
3092 | return 0; | ||
3093 | #undef CHECK_EXTENT | ||
3094 | #undef TRANSFORM_POINT | ||
3095 | } | ||
3096 | |||
3097 | static int | ||
3098 | is_matrix_unit(FontScalablePtr vals) | ||
3099 | { | ||
3100 | double base_size; | ||
3101 | FT_Matrix m; | ||
3102 | |||
3103 | base_size = hypot(vals->point_matrix[2], vals->point_matrix[3]); | ||
3104 | |||
3105 | m.xx = vals->point_matrix[0] / base_size * 65536; | ||
3106 | m.xy = vals->point_matrix[2] / base_size * 65536; | ||
3107 | m.yx = vals->point_matrix[1] / base_size * 65536; | ||
3108 | m.yy = vals->point_matrix[3] / base_size * 65536; | ||
3109 | |||
3110 | return (m.xx == 65536) && (m.yx == 0) && | ||
3111 | (m.xy == 0) && (m.yy == 65536); | ||
3112 | } | ||
3113 | |||
3114 | /* Do all the real work for OpenFont or FontInfo */ | ||
3115 | /* xf->info is only accessed through info, and xf might be null */ | ||
3116 | |||
3117 | static int | ||
3118 | FreeTypeLoadXFont(char *fileName, | ||
3119 | FontScalablePtr vals, FontPtr xf, FontInfoPtr info, | ||
3120 | FontBitmapFormatPtr bmfmt, FontEntryPtr entry) | ||
3121 | { | ||
3122 | FTFontPtr font = NULL((void*)0); | ||
3123 | FTFacePtr face = NULL((void*)0); | ||
3124 | FTInstancePtr instance; | ||
3125 | FT_Size_Metrics *smetrics; | ||
3126 | int xrc=Successful85; | ||
3127 | int charcell; | ||
3128 | long rawWidth = 0, rawAverageWidth = 0; | ||
3129 | int upm, minLsb, maxRsb, ascent, descent, width, averageWidth; | ||
3130 | double scale, base_width, base_height; | ||
3131 | Bool orig_is_matrix_unit, font_properties; | ||
3132 | int face_number, ttcap_spacing; | ||
3133 | struct TTCapInfo tmp_ttcap; | ||
3134 | struct TTCapInfo *ins_ttcap; | ||
3135 | FT_Int32 load_flags = FT_LOAD_DEFAULT0x0; /* orig: FT_LOAD_RENDER | FT_LOAD_MONOCHROME */ | ||
3136 | char *dynStrRealFileName = NULL((void*)0); /* foo.ttc */ | ||
3137 | char *dynStrFTFileName = NULL((void*)0); /* :1:foo.ttc */ | ||
3138 | char *dynStrTTCapCodeRange = NULL((void*)0); | ||
3139 | |||
3140 | font = calloc(1, sizeof(FTFontRec)); | ||
3141 | if(font == NULL((void*)0)) { | ||
3142 | xrc = AllocError80; | ||
3143 | goto quit; | ||
3144 | } | ||
3145 | |||
3146 | xrc = FreeTypeSetUpTTCap(fileName, vals, | ||
3147 | &dynStrRealFileName, &dynStrFTFileName, | ||
3148 | &tmp_ttcap, &face_number, | ||
3149 | &load_flags, &ttcap_spacing, | ||
3150 | &font_properties, &dynStrTTCapCodeRange); | ||
3151 | if ( xrc != Successful85 ) { | ||
3152 | goto quit; | ||
3153 | } | ||
3154 | |||
3155 | xrc = FreeTypeOpenFace(&face, dynStrFTFileName, dynStrRealFileName, face_number); | ||
3156 | if(xrc != Successful85) { | ||
3157 | goto quit; | ||
3158 | } | ||
3159 | |||
3160 | if( is_matrix_unit(vals) ) | ||
3161 | orig_is_matrix_unit = True(-1); | ||
3162 | else { | ||
3163 | orig_is_matrix_unit = False(0); | ||
3164 | /* Turn off EmbeddedBitmap when original matrix is not diagonal. */ | ||
3165 | load_flags |= FT_LOAD_NO_BITMAP0x8; | ||
3166 | } | ||
3167 | |||
3168 | if( face->bitmap ) load_flags &= ~FT_LOAD_NO_BITMAP0x8; | ||
3169 | |||
3170 | /* Slant control by TTCap */ | ||
3171 | if(!face->bitmap) { | ||
3172 | vals->pixel_matrix[2] += | ||
3173 | vals->pixel_matrix[0] * tmp_ttcap.autoItalic; | ||
3174 | vals->point_matrix[2] += | ||
3175 | vals->point_matrix[0] * tmp_ttcap.autoItalic; | ||
3176 | vals->pixel_matrix[3] += | ||
3177 | vals->pixel_matrix[1] * tmp_ttcap.autoItalic; | ||
3178 | vals->point_matrix[3] += | ||
3179 | vals->point_matrix[1] * tmp_ttcap.autoItalic; | ||
3180 | } | ||
3181 | |||
3182 | base_width=hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]); | ||
3183 | base_height=hypot(vals->pixel_matrix[2], vals->pixel_matrix[3]); | ||
3184 | if(MAX(base_width, base_height)((base_width) > (base_height) ? (base_width) : (base_height )) < 1.0 ) { | ||
3185 | xrc = BadFontName83; | ||
3186 | goto quit; | ||
3187 | } | ||
3188 | |||
3189 | xrc = FreeTypeLoadFont(font, info, face, dynStrFTFileName, vals, entry, bmfmt, | ||
3190 | load_flags, &tmp_ttcap, dynStrTTCapCodeRange, | ||
3191 | ttcap_spacing ); | ||
3192 | if(xrc != Successful85) { | ||
3193 | goto quit; | ||
3194 | } | ||
3195 | |||
3196 | instance = font->instance; | ||
3197 | smetrics = &instance->size->metrics; | ||
3198 | ins_ttcap = &instance->ttcap; | ||
3199 | |||
3200 | upm = face->face->units_per_EM; | ||
3201 | if(upm == 0) { | ||
3202 | /* Work around FreeType bug */ | ||
3203 | upm = WORK_AROUND_UPM2048; | ||
3204 | } | ||
3205 | scale = 1.0 / upm; | ||
3206 | |||
3207 | charcell = (instance->spacing == FT_CHARCELL2); | ||
3208 | |||
3209 | if( instance->charcellMetrics == NULL((void*)0) ) { | ||
3210 | |||
3211 | /* New instance */ | ||
3212 | |||
3213 | long force_c_rawWidth = 0; | ||
3214 | int force_c_lsb,force_c_rsb,force_c_width; | ||
3215 | double unit_x=0,unit_y=0,advance; | ||
3216 | CharInfoPtr tmpglyph; | ||
3217 | |||
3218 | /* | ||
3219 | * CALCULATE HEADER'S METRICS | ||
3220 | */ | ||
3221 | |||
3222 | /* for OUTLINE fonts */ | ||
3223 | if(!face->bitmap) { | ||
3224 | int new_width; | ||
3225 | double ratio,force_c_ratio; | ||
3226 | double width_x=0,width_y=0; | ||
3227 | double force_c_width_x, force_c_rsb_x, force_c_lsb_x; | ||
3228 | double tmp_rsb,tmp_lsb,tmp_asc,tmp_des; | ||
3229 | double max_advance_height; | ||
3230 | tmp_asc = face->face->bbox.yMax; | ||
3231 | tmp_des = -(face->face->bbox.yMin); | ||
3232 | if ( tmp_asc < face->face->ascender ) tmp_asc = face->face->ascender; | ||
3233 | if ( tmp_des < -(face->face->descender) ) tmp_des = -(face->face->descender); | ||
3234 | tmp_lsb = face->face->bbox.xMin; | ||
3235 | tmp_rsb = face->face->bbox.xMax; | ||
3236 | if ( tmp_rsb < face->face->max_advance_width ) tmp_rsb = face->face->max_advance_width; | ||
3237 | /* apply scaleBBoxWidth */ | ||
3238 | /* we should not ...??? */ | ||
3239 | tmp_lsb *= ins_ttcap->scaleBBoxWidth; | ||
3240 | tmp_rsb *= ins_ttcap->scaleBBoxWidth; | ||
3241 | /* transform and rescale */ | ||
3242 | compute_new_extents( vals, scale, tmp_lsb, tmp_rsb, tmp_des, tmp_asc, | ||
3243 | &minLsb, &maxRsb, &descent, &ascent ); | ||
3244 | /* */ | ||
3245 | /* Consider vertical layouts */ | ||
3246 | if( 0 < face->face->max_advance_height ) | ||
3247 | max_advance_height = face->face->max_advance_height; | ||
3248 | else | ||
3249 | max_advance_height = tmp_asc + tmp_des; | ||
3250 | if( vals->pixel_matrix[1] == 0 ){ | ||
3251 | unit_x = fabs(vals->pixel_matrix[0]); | ||
3252 | unit_y = 0; | ||
3253 | width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x; | ||
3254 | } | ||
3255 | else if( vals->pixel_matrix[3] == 0 ){ | ||
3256 | unit_y = fabs(vals->pixel_matrix[2]); | ||
3257 | unit_x = 0; | ||
3258 | width_x = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y; | ||
3259 | } | ||
3260 | else{ | ||
3261 | unit_x = fabs(vals->pixel_matrix[0] - | ||
3262 | vals->pixel_matrix[1]*vals->pixel_matrix[2]/vals->pixel_matrix[3]); | ||
3263 | unit_y = fabs(vals->pixel_matrix[2] - | ||
3264 | vals->pixel_matrix[3]*vals->pixel_matrix[0]/vals->pixel_matrix[1]); | ||
3265 | width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x; | ||
3266 | width_y = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y; | ||
3267 | if( width_y < width_x ){ | ||
3268 | width_x = width_y; | ||
3269 | unit_x = 0; | ||
3270 | } | ||
3271 | else{ | ||
3272 | unit_y = 0; | ||
3273 | } | ||
3274 | } | ||
3275 | /* calculate correction ratio */ | ||
3276 | width = (int)floor( (advance = width_x * scale) + 0.5); | ||
3277 | new_width = width; | ||
3278 | if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH0x0008 ) | ||
3279 | new_width += ins_ttcap->doubleStrikeShift; | ||
3280 | new_width += ins_ttcap->adjustBBoxWidthByPixel; | ||
3281 | ratio = (double)new_width/width; | ||
3282 | width = new_width; | ||
3283 | /* force constant */ | ||
3284 | if( unit_x != 0 ) { | ||
3285 | force_c_width_x = face->face->max_advance_width | ||
3286 | * ins_ttcap->force_c_scale_b_box_width * unit_x; | ||
3287 | force_c_lsb_x = face->face->max_advance_width | ||
3288 | * ins_ttcap->force_c_scale_lsb * unit_x; | ||
3289 | force_c_rsb_x = face->face->max_advance_width | ||
3290 | * ins_ttcap->force_c_scale_rsb * unit_x; | ||
3291 | } | ||
3292 | else { | ||
3293 | force_c_width_x = max_advance_height | ||
3294 | * ins_ttcap->force_c_scale_b_box_height * unit_y; | ||
3295 | force_c_lsb_x = max_advance_height | ||
3296 | * ins_ttcap->force_c_scale_lsb * unit_y; | ||
3297 | force_c_rsb_x = max_advance_height | ||
3298 | * ins_ttcap->force_c_scale_rsb * unit_y; | ||
3299 | } | ||
3300 | /* calculate correction ratio */ | ||
3301 | force_c_width = (int)floor(force_c_width_x * scale + 0.5); | ||
3302 | new_width = force_c_width; | ||
3303 | if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH0x0008 ) | ||
3304 | force_c_width += ins_ttcap->doubleStrikeShift; | ||
3305 | new_width += ins_ttcap->force_c_adjust_width_by_pixel; | ||
3306 | force_c_ratio = (double)new_width/force_c_width; | ||
3307 | force_c_width = new_width; | ||
3308 | /* force_c_lsb, force_c_rsb */ | ||
3309 | if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG0x0100 ) | ||
3310 | force_c_lsb = (int)floor( force_c_lsb_x * scale + 0.5 ); | ||
3311 | else | ||
3312 | force_c_lsb = minLsb; | ||
3313 | if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG0x0200 ) | ||
3314 | force_c_rsb = (int)floor( force_c_rsb_x * scale + 0.5 ); | ||
3315 | else | ||
3316 | force_c_rsb = maxRsb; | ||
3317 | /* calculate shift of BitmapAutoItalic | ||
3318 | (when diagonal matrix only) */ | ||
3319 | if( orig_is_matrix_unit == True(-1) ) { | ||
3320 | if( ins_ttcap->autoItalic != 0 ) { | ||
3321 | double ai; | ||
3322 | int ai_lsb,ai_rsb,ai_total; | ||
3323 | if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic; | ||
3324 | else ai = -ins_ttcap->autoItalic; | ||
3325 | ai_total = (int)( (ascent+descent) * ai + 0.5); | ||
3326 | ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 ); | ||
3327 | ai_lsb = -(ai_total - ai_rsb); | ||
3328 | if( 0 < ins_ttcap->autoItalic ) { | ||
3329 | ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb; | ||
3330 | ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb; | ||
3331 | } | ||
3332 | else { | ||
3333 | ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb; | ||
3334 | ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb; | ||
3335 | } | ||
3336 | } | ||
3337 | } | ||
3338 | /* integer adjustment by TTCap */ | ||
3339 | if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE0x0001 ) | ||
3340 | maxRsb += ins_ttcap->doubleStrikeShift; | ||
3341 | maxRsb += ins_ttcap->adjustRightSideBearingByPixel; | ||
3342 | minLsb += ins_ttcap->adjustLeftSideBearingByPixel; | ||
3343 | /* */ | ||
3344 | if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE0x0001 ) | ||
3345 | force_c_rsb += ins_ttcap->doubleStrikeShift; | ||
3346 | force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel; | ||
3347 | force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel; | ||
3348 | /* apply to rawWidth */ | ||
3349 | averageWidth = (int)floor(10 * width_x * scale | ||
3350 | * ratio + 0.5); | ||
3351 | rawWidth = floor(width_x * scale | ||
3352 | * ratio * 1000. / base_height + 0.5); | ||
3353 | rawAverageWidth = floor(width_x * scale * ratio * 10. | ||
3354 | * 1000. / base_height + 0.5); | ||
3355 | force_c_rawWidth = floor(force_c_width_x * scale | ||
3356 | * force_c_ratio * 1000. / base_height + 0.5); | ||
3357 | /* */ | ||
3358 | } | ||
3359 | /* for BITMAP fonts [if(face->bitmap)] */ | ||
3360 | else { | ||
3361 | /* These values differ from actual when outline, | ||
3362 | so we must use them ONLY FOR BITMAP. */ | ||
3363 | width = (int)floor(smetrics->max_advance * ins_ttcap->scaleBBoxWidth / 64.0 + .5); | ||
3364 | descent = -smetrics->descender / 64; | ||
3365 | ascent = smetrics->ascender / 64; | ||
3366 | /* force constant */ | ||
3367 | force_c_width = (int)floor(smetrics->max_advance | ||
3368 | * ins_ttcap->force_c_scale_b_box_width / 64.0 + .5); | ||
3369 | /* Preserve average width for bitmap fonts */ | ||
3370 | if(vals->width != 0) | ||
3371 | averageWidth = (int)floor(vals->width * ins_ttcap->scaleBBoxWidth +.5); | ||
3372 | else | ||
3373 | averageWidth = (int)floor(10.0 * smetrics->max_advance | ||
3374 | * ins_ttcap->scaleBBoxWidth / 64.0 + .5); | ||
3375 | rawWidth = 0; | ||
3376 | rawAverageWidth = 0; | ||
3377 | force_c_rawWidth = 0; | ||
3378 | /* We don't consider vertical layouts */ | ||
3379 | advance = (int)floor(smetrics->max_advance / 64.0 +.5); | ||
3380 | unit_x = vals->pixel_matrix[0]; | ||
3381 | unit_y = 0; | ||
3382 | /* We can use 'width' only when bitmap. | ||
3383 | This should not be set when outline. */ | ||
3384 | minLsb = 0; | ||
3385 | maxRsb = width; | ||
3386 | /* force constant */ | ||
3387 | if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG0x0100 ) | ||
3388 | force_c_lsb = (int)floor(smetrics->max_advance | ||
3389 | * ins_ttcap->force_c_scale_lsb / 64.0 + .5); | ||
3390 | else | ||
3391 | force_c_lsb = minLsb; | ||
3392 | if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG0x0200 ) | ||
3393 | force_c_rsb = (int)floor(smetrics->max_advance | ||
3394 | * ins_ttcap->force_c_scale_rsb / 64.0 + .5); | ||
3395 | else | ||
3396 | force_c_rsb = maxRsb; | ||
3397 | /* calculate shift of BitmapAutoItalic */ | ||
3398 | if( ins_ttcap->autoItalic != 0 ) { | ||
3399 | double ai; | ||
3400 | int ai_lsb,ai_rsb,ai_total; | ||
3401 | if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic; | ||
3402 | else ai = -ins_ttcap->autoItalic; | ||
3403 | ai_total = (int)( (ascent+descent) * ai + 0.5); | ||
3404 | ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 ); | ||
3405 | ai_lsb = -(ai_total - ai_rsb); | ||
3406 | if( 0 < ins_ttcap->autoItalic ) { | ||
3407 | ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb; | ||
3408 | ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb; | ||
3409 | } | ||
3410 | else { | ||
3411 | ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb; | ||
3412 | ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb; | ||
3413 | } | ||
3414 | } | ||
3415 | /* integer adjustment by TTCap */ | ||
3416 | if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH0x0008 ) | ||
3417 | width += ins_ttcap->doubleStrikeShift; | ||
3418 | if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE0x0001 ) | ||
3419 | maxRsb += ins_ttcap->doubleStrikeShift; | ||
3420 | maxRsb += ins_ttcap->adjustRightSideBearingByPixel; | ||
3421 | minLsb += ins_ttcap->adjustLeftSideBearingByPixel; | ||
3422 | /* We have not carried out matrix calculation, so this is done. */ | ||
3423 | maxRsb += ins_ttcap->rsbShiftOfBitmapAutoItalic; | ||
3424 | minLsb += ins_ttcap->lsbShiftOfBitmapAutoItalic; | ||
3425 | /* force constant */ | ||
3426 | if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE0x0001 ) | ||
3427 | force_c_rsb += ins_ttcap->doubleStrikeShift; | ||
3428 | force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel; | ||
3429 | force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel; | ||
3430 | force_c_rsb += ins_ttcap->rsbShiftOfBitmapAutoItalic; | ||
3431 | force_c_lsb += ins_ttcap->lsbShiftOfBitmapAutoItalic; | ||
3432 | } | ||
3433 | |||
3434 | /* SET CALCULATED VALUES TO INSTANCE */ | ||
3435 | |||
3436 | /* Set actual height and cosine */ | ||
3437 | instance->pixel_size = base_height; | ||
3438 | instance->advance = advance; | ||
3439 | if ( unit_x != 0 ){ | ||
3440 | instance->pixel_width_unit_x = unit_x/base_height; | ||
3441 | instance->pixel_width_unit_y = 0; | ||
3442 | } | ||
3443 | else{ | ||
3444 | instance->pixel_width_unit_x = 0; | ||
3445 | instance->pixel_width_unit_y = unit_y/base_height; | ||
3446 | } | ||
3447 | |||
3448 | /* header's metrics */ | ||
3449 | instance->charcellMetrics = malloc(sizeof(xCharInfo)); | ||
3450 | if(instance->charcellMetrics == NULL((void*)0)) { | ||
3451 | xrc = AllocError80; | ||
3452 | goto quit; | ||
3453 | } | ||
3454 | instance->charcellMetrics->ascent = ascent; | ||
3455 | instance->charcellMetrics->descent = descent; | ||
3456 | instance->charcellMetrics->attributes = rawWidth; | ||
3457 | instance->charcellMetrics->rightSideBearing = maxRsb; | ||
3458 | instance->charcellMetrics->leftSideBearing = minLsb; | ||
3459 | instance->charcellMetrics->characterWidth = width; | ||
3460 | instance->averageWidth = averageWidth; | ||
3461 | instance->rawAverageWidth = rawAverageWidth; | ||
3462 | |||
3463 | /* Check code 0 */ | ||
3464 | if( FreeTypeInstanceGetGlyph(font->zero_idx, 0, &tmpglyph, font->instance) != Successful85 | ||
3465 | || tmpglyph == NULL((void*)0)) | ||
3466 | if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_GET_DUMMY0x04, &tmpglyph, font->instance) | ||
3467 | != Successful85 ) | ||
3468 | tmpglyph = NULL((void*)0); | ||
3469 | if ( !tmpglyph ) { | ||
3470 | xrc = AllocError80; | ||
3471 | goto quit; | ||
3472 | } | ||
3473 | |||
3474 | /* FORCE CONSTANT METRICS */ | ||
3475 | if( 0 <= ins_ttcap->forceConstantSpacingEnd ) { | ||
3476 | xCharInfo *tmpchar = NULL((void*)0); | ||
3477 | int c = ins_ttcap->force_c_representative_metrics_char_code; | ||
3478 | /* header's metrics */ | ||
3479 | if( instance->forceConstantMetrics == NULL((void*)0) ){ | ||
3480 | instance->forceConstantMetrics = malloc(sizeof(xCharInfo)); | ||
3481 | if(instance->forceConstantMetrics == NULL((void*)0)) { | ||
3482 | xrc = AllocError80; | ||
3483 | goto quit; | ||
3484 | } | ||
3485 | } | ||
3486 | /* Get Representative Metrics */ | ||
3487 | if ( 0 <= c ) { | ||
3488 | if( FreeTypeFontGetGlyphMetrics(c, 0, &tmpchar, font) != Successful85 ) | ||
3489 | tmpchar = NULL((void*)0); | ||
3490 | } | ||
3491 | if ( tmpchar && 0 < tmpchar->characterWidth ) { | ||
3492 | instance->forceConstantMetrics->leftSideBearing = tmpchar->leftSideBearing; | ||
3493 | instance->forceConstantMetrics->rightSideBearing = tmpchar->rightSideBearing; | ||
3494 | instance->forceConstantMetrics->characterWidth = tmpchar->characterWidth; | ||
3495 | instance->forceConstantMetrics->ascent = tmpchar->ascent; | ||
3496 | instance->forceConstantMetrics->descent = tmpchar->descent; | ||
3497 | instance->forceConstantMetrics->attributes = tmpchar->attributes; | ||
3498 | } | ||
3499 | else { | ||
3500 | instance->forceConstantMetrics->leftSideBearing = force_c_lsb; | ||
3501 | instance->forceConstantMetrics->rightSideBearing = force_c_rsb; | ||
3502 | instance->forceConstantMetrics->characterWidth = force_c_width; | ||
3503 | instance->forceConstantMetrics->ascent = ascent; | ||
3504 | instance->forceConstantMetrics->descent = descent; | ||
3505 | instance->forceConstantMetrics->attributes = force_c_rawWidth; | ||
3506 | } | ||
3507 | /* Check code 0 */ | ||
3508 | if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING0x08, | ||
3509 | &tmpglyph, font->instance) != Successful85 | ||
3510 | || tmpglyph == NULL((void*)0)) | ||
3511 | if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING0x08 | FT_GET_DUMMY0x04, | ||
3512 | &tmpglyph, font->instance) | ||
3513 | != Successful85 ) | ||
3514 | tmpglyph = NULL((void*)0); | ||
3515 | if ( !tmpglyph ) { | ||
3516 | xrc = AllocError80; | ||
3517 | goto quit; | ||
3518 | } | ||
3519 | } | ||
3520 | } | ||
3521 | else{ | ||
3522 | |||
3523 | /* | ||
3524 | * CACHED VALUES | ||
3525 | */ | ||
3526 | |||
3527 | width = instance->charcellMetrics->characterWidth; | ||
3528 | ascent = instance->charcellMetrics->ascent; | ||
3529 | descent = instance->charcellMetrics->descent; | ||
3530 | rawWidth = instance->charcellMetrics->attributes; | ||
3531 | maxRsb = instance->charcellMetrics->rightSideBearing; | ||
3532 | minLsb = instance->charcellMetrics->leftSideBearing; | ||
3533 | averageWidth = instance->averageWidth; | ||
3534 | rawAverageWidth = instance->rawAverageWidth; | ||
3535 | |||
3536 | } | ||
3537 | |||
3538 | /* | ||
3539 | * SET maxbounds, minbounds ... | ||
3540 | */ | ||
3541 | |||
3542 | if( !charcell ) { /* NOT CHARCELL */ | ||
3543 | if( info ){ | ||
3544 | /* | ||
3545 | Calculate all glyphs' metrics. | ||
3546 | maxbounds.ascent and maxbounds.descent are quite important values | ||
3547 | for XAA. If ascent/descent of each glyph exceeds | ||
3548 | maxbounds.ascent/maxbounds.descent, XAA causes SERVER CRASH. | ||
3549 | Therefore, THIS MUST BE DONE. | ||
3550 | */ | ||
3551 | ft_compute_bounds(font,info,vals); | ||
3552 | } | ||
3553 | } | ||
3554 | else{ /* CHARCELL */ | ||
3555 | |||
3556 | /* | ||
3557 | * SET CALCULATED OR CACHED VARIABLES | ||
3558 | */ | ||
3559 | |||
3560 | vals->width = averageWidth; | ||
3561 | |||
3562 | if( info ){ | ||
3563 | |||
3564 | info->maxbounds.leftSideBearing = minLsb; | ||
3565 | info->maxbounds.rightSideBearing = maxRsb; | ||
3566 | info->maxbounds.characterWidth = width; | ||
3567 | info->maxbounds.ascent = ascent; | ||
3568 | info->maxbounds.descent = descent; | ||
3569 | info->maxbounds.attributes = | ||
3570 | (unsigned short)(short)rawWidth; | ||
3571 | |||
3572 | info->minbounds = info->maxbounds; | ||
3573 | } | ||
3574 | } | ||
3575 | |||
3576 | /* set info */ | ||
3577 | |||
3578 | if( info ){ | ||
3579 | /* | ||
3580 | info->fontAscent = ascent; | ||
3581 | info->fontDescent = descent; | ||
3582 | */ | ||
3583 | info->fontAscent = info->maxbounds.ascent; | ||
3584 | info->fontDescent = info->maxbounds.descent; | ||
3585 | /* Glyph metrics are accurate */ | ||
3586 | info->inkMetrics=1; | ||
3587 | |||
3588 | memcpy((char *)&info->ink_maxbounds, | ||
3589 | (char *)&info->maxbounds, sizeof(xCharInfo)); | ||
3590 | memcpy((char *)&info->ink_minbounds, | ||
3591 | (char *)&info->minbounds, sizeof(xCharInfo)); | ||
3592 | |||
3593 | /* XXX - hack */ | ||
3594 | info->defaultCh=0; | ||
3595 | |||
3596 | /* Set the pInfo flags */ | ||
3597 | /* Properties set by FontComputeInfoAccelerators: | ||
3598 | pInfo->noOverlap; | ||
3599 | pInfo->terminalFont; | ||
3600 | pInfo->constantMetrics; | ||
3601 | pInfo->constantWidth; | ||
3602 | pInfo->inkInside; | ||
3603 | */ | ||
3604 | /* from lib/font/util/fontaccel.c */ | ||
3605 | FontComputeInfoAccelerators(info); | ||
3606 | } | ||
3607 | |||
3608 | if(xf) | ||
3609 | xf->fontPrivate = (void*)font; | ||
3610 | |||
3611 | if(info) { | ||
3612 | xrc = FreeTypeAddProperties(font, vals, info, entry->name.name, | ||
3613 | rawAverageWidth, font_properties); | ||
3614 | if (xrc != Successful85) { | ||
3615 | goto quit; | ||
3616 | } | ||
3617 | } | ||
3618 | |||
3619 | quit: | ||
3620 | if ( dynStrTTCapCodeRange ) free(dynStrTTCapCodeRange); | ||
3621 | if ( dynStrFTFileName ) free(dynStrFTFileName); | ||
3622 | if ( dynStrRealFileName ) free(dynStrRealFileName); | ||
3623 | if ( xrc != Successful85 ) { | ||
3624 | if( font ){ | ||
3625 | if( face && font->instance == NULL((void*)0) ) FreeTypeFreeFace(face); | ||
3626 | FreeTypeFreeFont(font); | ||
3627 | } | ||
3628 | } | ||
3629 | return xrc; | ||
3630 | } | ||
3631 | |||
3632 | /* Routines used by X11 to get info and glyphs from the font. */ | ||
3633 | |||
3634 | static int | ||
3635 | FreeTypeGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars, | ||
3636 | FontEncoding charEncoding, unsigned long *metricCount, | ||
3637 | xCharInfo **metrics) | ||
3638 | { | ||
3639 | unsigned int code = 0; | ||
3640 | int flags = 0; | ||
3641 | FTFontPtr tf; | ||
3642 | struct TTCapInfo *ttcap; | ||
3643 | xCharInfo **mp, *m; | ||
3644 | |||
3645 | /* MUMBLE("Get metrics for %ld characters\n", count);*/ | ||
3646 | |||
3647 | tf = (FTFontPtr)pFont->fontPrivate; | ||
3648 | ttcap = &tf->instance->ttcap; | ||
3649 | mp = metrics; | ||
3650 | |||
3651 | while (count-- > 0) { | ||
3652 | switch (charEncoding) { | ||
3653 | case Linear8Bit: | ||
3654 | case TwoD8Bit: | ||
3655 | code = *chars++; | ||
3656 | break; | ||
3657 | case Linear16Bit: | ||
3658 | case TwoD16Bit: | ||
3659 | code = (*chars++ << 8); | ||
3660 | code |= *chars++; | ||
3661 | /* */ | ||
3662 | if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE0x0400) ) { | ||
3663 | if ( (int)code <= ttcap->forceConstantSpacingEnd | ||
3664 | && ttcap->forceConstantSpacingBegin <= (int)code ) | ||
3665 | flags|=FT_FORCE_CONSTANT_SPACING0x08; | ||
3666 | else flags=0; | ||
3667 | } | ||
3668 | else { /* for GB18030 proportional */ | ||
3669 | if ( (int)code <= ttcap->forceConstantSpacingEnd | ||
3670 | || ttcap->forceConstantSpacingBegin <= (int)code ) | ||
3671 | flags|=FT_FORCE_CONSTANT_SPACING0x08; | ||
3672 | else flags=0; | ||
3673 | } | ||
3674 | break; | ||
3675 | } | ||
3676 | |||
3677 | if(FreeTypeFontGetGlyphMetrics(code, flags, &m, tf) == Successful85 && m!=NULL((void*)0)) { | ||
3678 | *mp++ = m; | ||
3679 | } | ||
3680 | #ifdef X_ACCEPTS_NO_SUCH_CHAR | ||
3681 | else *mp++ = &noSuchChar.metrics; | ||
3682 | #endif | ||
3683 | } | ||
3684 | |||
3685 | *metricCount = mp - metrics; | ||
3686 | return Successful85; | ||
3687 | } | ||
3688 | |||
3689 | static int | ||
3690 | FreeTypeGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars, | ||
3691 | FontEncoding charEncoding, unsigned long *glyphCount, | ||
3692 | CharInfoPtr *glyphs) | ||
3693 | { | ||
3694 | unsigned int code = 0; | ||
3695 | int flags = 0; | ||
3696 | FTFontPtr tf; | ||
3697 | CharInfoPtr *gp; | ||
3698 | CharInfoPtr g; | ||
3699 | struct TTCapInfo *ttcap; | ||
3700 | |||
3701 | tf = (FTFontPtr)pFont->fontPrivate; | ||
3702 | ttcap = &tf->instance->ttcap; | ||
3703 | gp = glyphs; | ||
3704 | |||
3705 | while (count-- > 0) { | ||
3706 | switch (charEncoding) { | ||
3707 | case Linear8Bit: case TwoD8Bit: | ||
3708 | code = *chars++; | ||
3709 | break; | ||
3710 | case Linear16Bit: case TwoD16Bit: | ||
3711 | code = *chars++ << 8; | ||
3712 | code |= *chars++; | ||
3713 | /* */ | ||
3714 | if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE0x0400) ) { | ||
3715 | if ( (int)code <= ttcap->forceConstantSpacingEnd | ||
3716 | && ttcap->forceConstantSpacingBegin <= (int)code ) | ||
3717 | flags|=FT_FORCE_CONSTANT_SPACING0x08; | ||
3718 | else flags=0; | ||
3719 | } | ||
3720 | else { /* for GB18030 proportional */ | ||
3721 | if ( (int)code <= ttcap->forceConstantSpacingEnd | ||
3722 | || ttcap->forceConstantSpacingBegin <= (int)code ) | ||
3723 | flags|=FT_FORCE_CONSTANT_SPACING0x08; | ||
3724 | else flags=0; | ||
3725 | } | ||
3726 | break; | ||
3727 | } | ||
3728 | |||
3729 | if(FreeTypeFontGetGlyph(code, flags, &g, tf) == Successful85 && g!=NULL((void*)0)) { | ||
3730 | *gp++ = g; | ||
3731 | } | ||
3732 | #ifdef X_ACCEPTS_NO_SUCH_CHAR | ||
3733 | else { | ||
3734 | #ifdef XAA_ACCEPTS_NULL_BITS | ||
3735 | *gp++ = &noSuchChar; | ||
3736 | #else | ||
3737 | if ( tf->dummy_char.bits ) { | ||
3738 | *gp++ = &tf->dummy_char; | ||
3739 | } | ||
3740 | else { | ||
3741 | char *raster = NULL((void*)0); | ||
3742 | int wd_actual, ht_actual, wd, ht, bpr; | ||
3743 | wd_actual = tf->info->maxbounds.rightSideBearing - tf->info->maxbounds.leftSideBearing; | ||
3744 | ht_actual = tf->info->maxbounds.ascent + tf->info->maxbounds.descent; | ||
3745 | if(wd_actual <= 0) wd = 1; | ||
3746 | else wd=wd_actual; | ||
3747 | if(ht_actual <= 0) ht = 1; | ||
3748 | else ht=ht_actual; | ||
3749 | bpr = (((wd + (tf->instance->bmfmt.glyph<<3) - 1) >> 3) & | ||
3750 | -tf->instance->bmfmt.glyph); | ||
3751 | raster = calloc(1, ht * bpr); | ||
3752 | if(raster) { | ||
3753 | tf->dummy_char.bits = raster; | ||
3754 | *gp++ = &tf->dummy_char; | ||
3755 | } | ||
3756 | } | ||
3757 | #endif | ||
3758 | } | ||
3759 | #endif | ||
3760 | } | ||
3761 | |||
3762 | *glyphCount = gp - glyphs; | ||
3763 | return Successful85; | ||
3764 | } | ||
3765 | |||
3766 | static int | ||
3767 | FreeTypeSetUpFont(FontPathElementPtr fpe, FontPtr xf, FontInfoPtr info, | ||
3768 | fsBitmapFormat format, fsBitmapFormatMask fmask, | ||
3769 | FontBitmapFormatPtr bmfmt) | ||
3770 | { | ||
3771 | int xrc; | ||
3772 | int image; | ||
3773 | |||
3774 | /* Get the default bitmap format information for this X installation. | ||
3775 | Also update it for the client if running in the font server. */ | ||
3776 | FontDefaultFormat(&bmfmt->bit, &bmfmt->byte, &bmfmt->glyph, &bmfmt->scan); | ||
3777 | if ((xrc = CheckFSFormat(format, fmask, &bmfmt->bit, &bmfmt->byte, | ||
3778 | &bmfmt->scan, &bmfmt->glyph, | ||
3779 | &image)) != Successful85) { | ||
3780 | MUMBLE("Aborting after checking FS format: %d\n", xrc); | ||
3781 | return xrc; | ||
3782 | } | ||
3783 | |||
3784 | if(xf) { | ||
3785 | xf->refcnt = 0; | ||
3786 | xf->bit = bmfmt->bit; | ||
3787 | xf->byte = bmfmt->byte; | ||
3788 | xf->glyph = bmfmt->glyph; | ||
3789 | xf->scan = bmfmt->scan; | ||
3790 | xf->format = format; | ||
3791 | xf->get_glyphs = FreeTypeGetGlyphs; | ||
3792 | xf->get_metrics = FreeTypeGetMetrics; | ||
3793 | xf->unload_font = FreeTypeUnloadXFont; | ||
3794 | xf->unload_glyphs = 0; | ||
3795 | xf->fpe = fpe; | ||
3796 | xf->svrPrivate = 0; | ||
3797 | xf->fontPrivate = 0; /* we'll set it later */ | ||
3798 | xf->fpePrivate = 0; | ||
3799 | } | ||
3800 | |||
3801 | info->defaultCh = 0; | ||
3802 | info->noOverlap = 0; /* not updated */ | ||
3803 | info->terminalFont = 0; /* not updated */ | ||
3804 | info->constantMetrics = 0; /* we'll set it later */ | ||
3805 | info->constantWidth = 0; /* we'll set it later */ | ||
3806 | info->inkInside = 1; | ||
3807 | info->inkMetrics = 1; | ||
3808 | info->allExist=0; /* not updated */ | ||
3809 | info->drawDirection = LeftToRight0; /* we'll set it later */ | ||
3810 | info->cachable = 1; /* we don't do licensing */ | ||
3811 | info->anamorphic = 0; /* can hinting lead to anamorphic scaling? */ | ||
3812 | info->maxOverlap = 0; /* we'll set it later. */ | ||
3813 | info->pad = 0; /* ??? */ | ||
3814 | return Successful85; | ||
3815 | } | ||
3816 | |||
3817 | /* Functions exported by the backend */ | ||
3818 | |||
3819 | static int | ||
3820 | FreeTypeOpenScalable(FontPathElementPtr fpe, FontPtr *ppFont, int flags, | ||
3821 | FontEntryPtr entry, char *fileName, FontScalablePtr vals, | ||
3822 | fsBitmapFormat format, fsBitmapFormatMask fmask, | ||
3823 | FontPtr non_cachable_font) | ||
3824 | { | ||
3825 | int xrc; | ||
3826 | FontPtr xf; | ||
3827 | FontBitmapFormatRec bmfmt; | ||
3828 | |||
3829 | MUMBLE("Open Scalable %s, XLFD=%s\n",fileName, entry->name.length ? entry->name.name : ""); | ||
3830 | |||
3831 | xf = CreateFontRec(); | ||
3832 | if (xf == NULL((void*)0)) | ||
3833 | return AllocError80; | ||
3834 | |||
3835 | xrc = FreeTypeSetUpFont(fpe, xf, &xf->info, format, fmask, &bmfmt); | ||
3836 | if(xrc != Successful85) { | ||
3837 | DestroyFontRec(xf); | ||
3838 | return xrc; | ||
3839 | } | ||
3840 | xrc = FreeTypeLoadXFont(fileName, vals, xf, &xf->info, &bmfmt, entry); | ||
3841 | if(xrc != Successful85) { | ||
3842 | MUMBLE("Error during load: %d\n",xrc); | ||
3843 | DestroyFontRec(xf); | ||
3844 | return xrc; | ||
3845 | } | ||
3846 | |||
3847 | *ppFont = xf; | ||
3848 | |||
3849 | return xrc; | ||
3850 | } | ||
3851 | |||
3852 | /* Routine to get requested font info. */ | ||
3853 | |||
3854 | static int | ||
3855 | FreeTypeGetInfoScalable(FontPathElementPtr fpe, FontInfoPtr info, | ||
3856 | FontEntryPtr entry, FontNamePtr fontName, | ||
3857 | char *fileName, FontScalablePtr vals) | ||
3858 | { | ||
3859 | int xrc; | ||
3860 | FontBitmapFormatRec bmfmt; | ||
3861 | |||
3862 | MUMBLE("Get info, XLFD=%s\n", entry->name.length ? entry->name.name : ""); | ||
3863 | |||
3864 | xrc = FreeTypeSetUpFont(fpe, 0, info, 0, 0, &bmfmt); | ||
3865 | if(xrc != Successful85) { | ||
3866 | return xrc; | ||
3867 | } | ||
3868 | |||
3869 | bmfmt.glyph <<= 3; | ||
3870 | |||
3871 | xrc = FreeTypeLoadXFont(fileName, vals, 0, info, &bmfmt, entry); | ||
3872 | if(xrc != Successful85) { | ||
3873 | MUMBLE("Error during load: %d\n", xrc); | ||
3874 | return xrc; | ||
3875 | } | ||
3876 | |||
3877 | return Successful85; | ||
3878 | } | ||
3879 | |||
3880 | /* Renderer registration. */ | ||
3881 | |||
3882 | /* Set the capabilities of this renderer. */ | ||
3883 | #define CAPABILITIES(0x2 | 0x1) (CAP_CHARSUBSETTING0x2 | CAP_MATRIX0x1) | ||
3884 | |||
3885 | /* Set it up so file names with either upper or lower case can be | ||
3886 | loaded. We don't support compressed fonts. */ | ||
3887 | static FontRendererRec renderers[] = { | ||
3888 | {".ttf", 4, 0, FreeTypeOpenScalable, 0, | ||
3889 | FreeTypeGetInfoScalable, 0, CAPABILITIES(0x2 | 0x1)}, | ||
3890 | {".ttc", 4, 0, FreeTypeOpenScalable, 0, | ||
3891 | FreeTypeGetInfoScalable, 0, CAPABILITIES(0x2 | 0x1)}, | ||
3892 | {".otf", 4, 0, FreeTypeOpenScalable, 0, | ||
3893 | FreeTypeGetInfoScalable, 0, CAPABILITIES(0x2 | 0x1)}, | ||
3894 | {".otc", 4, 0, FreeTypeOpenScalable, 0, | ||
3895 | FreeTypeGetInfoScalable, 0, CAPABILITIES(0x2 | 0x1)}, | ||
3896 | {".pfa", 4, 0, FreeTypeOpenScalable, 0, | ||
3897 | FreeTypeGetInfoScalable, 0, CAPABILITIES(0x2 | 0x1)}, | ||
3898 | {".pfb", 4, 0, FreeTypeOpenScalable, 0, | ||
3899 | FreeTypeGetInfoScalable, 0, CAPABILITIES(0x2 | 0x1)}, | ||
3900 | }; | ||
3901 | static int num_renderers = sizeof(renderers) / sizeof(renderers[0]); | ||
3902 | |||
3903 | static FontRendererRec alt_renderers[] = { | ||
3904 | {".bdf", 4, 0, FreeTypeOpenScalable, 0, | ||
3905 | FreeTypeGetInfoScalable, 0, CAPABILITIES(0x2 | 0x1)}, | ||
3906 | {".pcf", 4, 0, FreeTypeOpenScalable, 0, | ||
3907 | FreeTypeGetInfoScalable, 0, CAPABILITIES(0x2 | 0x1)}, | ||
3908 | }; | ||
3909 | |||
3910 | static int num_alt_renderers = | ||
3911 | sizeof(alt_renderers) / sizeof(alt_renderers[0]); | ||
3912 | |||
3913 | |||
3914 | void | ||
3915 | FreeTypeRegisterFontFileFunctions(void) | ||
3916 | { | ||
3917 | int i; | ||
3918 | |||
3919 | for (i = 0; i < num_renderers; i++) | ||
3920 | FontFileRegisterRenderer(&renderers[i]); | ||
3921 | |||
3922 | for (i = 0; i < num_alt_renderers; i++) | ||
3923 | FontFilePriorityRegisterRenderer(&alt_renderers[i], -10); | ||
3924 | } |