Bug Summary

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')

Annotated Source Code

1/*
2Copyright (c) 1997 by Mark Leisher
3Copyright (c) 1998-2003 by Juliusz Chroboczek
4Copyright (c) 1998 Go Watanabe, All rights reserved.
5Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved.
6Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved.
7Copyright (c) 1998 X-TrueType Server Project, All rights reserved.
8Copyright (c) 2003-2004 After X-TT Project, All rights reserved.
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files (the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions:
16
17The above copyright notice and this permission notice shall be included in
18all copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26THE 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
91static 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
97static 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 */
116static FT_UShort
117sfnt_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
134static int ftypeInitP = 0; /* is the engine initialised? */
135FT_Library ftypeLibrary;
136
137static FTFacePtr faceTable[NUMFACEBUCKETS32];
138
139static unsigned
140hash(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
149static int
150ifloor(int x, int y)
151{
152 if(x >= 0)
153 return x/y;
154 else
155 return x/y - 1;
156}
157
158static int
159iceil(int x, int y)
160{
161 return ifloor(x + y - 1, y);
162}
163
164static int
165FreeTypeOpenFace(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
231static void
232FreeTypeFreeFace(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
260static int
261TransEqual(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
279static int
280BitmapFormatEqual(FontBitmapFormatPtr f1, FontBitmapFormatPtr f2)
281{
282 return
283 f1->bit == f2->bit &&
284 f1->byte == f2->byte &&
285 f1->glyph == f2->glyph;
286}
287
288static int
289TTCapEqual(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
310static int
311FTInstanceMatch(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
333static int
334FreeTypeActivateInstance(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
355static int
356FTFindSize(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
390static int
391FreeTypeOpenInstance(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
538static void
539FreeTypeFreeInstance(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
596static int
597FreeTypeInstanceFindGlyph(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
649static int
650FreeTypeInstanceGetGlyph(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
695static int
696FreeTypeInstanceGetGlyphMetrics(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 */
750static void
751ft_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
783static void
784ft_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
837static void
838tt_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
895static int
896ft_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
969static FT_Error
970FT_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
1072int
1073FreeTypeRasteriseGlyph(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
1518static void
1519FreeTypeFreeFont(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
1531static void
1532FreeTypeFreeXFont(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
1551static void
1552FreeTypeUnloadXFont(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
1564static int
1565FreeTypeAddProperties(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
1876static int
1877ft_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
1918static int
1919FreeTypeFontGetGlyph(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
1950static int
1951FreeTypeFontGetGlyphMetrics(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
1990static void
1991restrict_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
2044static int
2045restrict_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. */
2159static int
2160FreeTypeSetUpTTCap( 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
2686static int
2687ft_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
2731static int
2732is_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
2749static int
2750FreeTypeLoadFont(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) {
1
Taking false branch
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 ) {
2
Assuming 'ttcap_spacing' is equal to 0
3
Taking false branch
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 ) {
4
Taking true branch
2793 if( is_fixed_width(face->face) )
5
Taking false branch
2794 actual_spacing = FT_MONOSPACED1;
2795 }
2796
2797 if(entry->name.ndashes == 14) {
6
Taking false branch
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)
7
Assuming 'xrc' is equal to 85
8
Taking false branch
2806 return xrc;
2807 }
2808
2809 font->nranges = vals->nranges;
2810 font->ranges = 0;
2811 if(font->nranges) {
9
Taking false branch
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) {
10
Assuming 'info' is null
11
Taking false branch
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 ) {
12
Taking true branch
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 ) )
13
Taking true branch
2878 if( DEFAULT_VERY_LAZY2 <= 1 + info->lastRow - info->firstRow ) {
14
Access to field 'lastRow' results in a dereference of a null pointer (loaded from variable 'info')
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
2905static void
2906adjust_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
2927static void
2928ft_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
3057static int
3058compute_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
3097static int
3098is_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
3117static int
3118FreeTypeLoadXFont(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
3634static int
3635FreeTypeGetMetrics(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
3689static int
3690FreeTypeGetGlyphs(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
3766static int
3767FreeTypeSetUpFont(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
3819static int
3820FreeTypeOpenScalable(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
3854static int
3855FreeTypeGetInfoScalable(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. */
3887static 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};
3901static int num_renderers = sizeof(renderers) / sizeof(renderers[0]);
3902
3903static 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
3910static int num_alt_renderers =
3911sizeof(alt_renderers) / sizeof(alt_renderers[0]);
3912
3913
3914void
3915FreeTypeRegisterFontFileFunctions(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}