fd8e53e5f08a33c09c36f1f6c4b69a66eb374358
[framework/uifw/xorg/lib/libxfont.git] / src / FreeType / ftfuncs.c
1 /*
2 Copyright (c) 1997 by Mark Leisher
3 Copyright (c) 1998-2003 by Juliusz Chroboczek
4 Copyright (c) 1998 Go Watanabe, All rights reserved.
5 Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved.
6 Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved.
7 Copyright (c) 1998 X-TrueType Server Project, All rights reserved.
8 Copyright (c) 2003-2004 After X-TT Project, All rights reserved.
9
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 THE SOFTWARE.
27 */
28
29 #ifdef HAVE_CONFIG_H
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
43 #include FT_SIZES_H
44 #include FT_TRUETYPE_IDS_H
45 #include FT_TRUETYPE_TABLES_H
46 #include FT_TYPE1_TABLES_H
47 #include FT_XFREE86_H
48 #include FT_BBOX_H
49 #include FT_TRUETYPE_TAGS_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
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_UPM 2048
66
67 #ifndef True
68 #define True (-1)
69 #endif /* True */
70 #ifndef False
71 #define False (0)
72 #endif /* False */
73
74 #define FLOOR64(x) ((x) & -64)
75 #define CEIL64(x) (((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_LAZY 2             /* Multi-byte only */
83 /* #define DEFAULT_VERY_LAZY 256 */     /* Unicode only */
84
85 /* Does the X accept noSuchChar? */
86 #define X_ACCEPTS_NO_SUCH_CHAR
87 /* Does the XAA accept NULL noSuchChar.bits?(dangerous) */
88 /* #define XAA_ACCEPTS_NULL_BITS */
89
90 #ifdef X_ACCEPTS_NO_SUCH_CHAR
91 static CharInfoRec noSuchChar = { /* metrics */{0,0,0,0,0,0},
92                                   /* bits */   NULL };
93 #endif
94
95 /* The propery names for all the XLFD properties. */
96
97 static char *xlfd_props[] = {
98     "FOUNDRY",
99     "FAMILY_NAME",
100     "WEIGHT_NAME",
101     "SLANT",
102     "SETWIDTH_NAME",
103     "ADD_STYLE_NAME",
104     "PIXEL_SIZE",
105     "POINT_SIZE",
106     "RESOLUTION_X",
107     "RESOLUTION_Y",
108     "SPACING",
109     "AVERAGE_WIDTH",
110     "CHARSET_REGISTRY",
111     "CHARSET_ENCODING",
112 };
113
114
115 /* read 2-byte value from a SFNT table */
116 static FT_UShort
117 sfnt_get_ushort( FT_Face     face,
118                  FT_ULong    table_tag,
119                  FT_ULong    table_offset )
120 {
121   FT_Byte    buff[2];
122   FT_ULong   len = sizeof(buff);
123   FT_UShort  result = 0;
124
125   if ( !FT_Load_Sfnt_Table( face, table_tag, table_offset, buff, &len ) );
126     result = (FT_UShort)( (buff[0] << 8) | buff[1] );
127
128   return result;
129 }
130
131 #define  sfnt_get_short(f,t,o)  ((FT_Short)sfnt_get_ushort((f),(t),(o)))
132
133
134 static int ftypeInitP = 0;      /* is the engine initialised? */
135 FT_Library ftypeLibrary;
136
137 static FTFacePtr faceTable[NUMFACEBUCKETS];
138
139 static unsigned
140 hash(char *string)
141 {
142     int i;
143     unsigned u = 0;
144     for(i = 0; string[i] != '\0'; i++)
145         u = (u<<5) + (u >> (NUMFACEBUCKETS - 5)) + (unsigned char)string[i];
146     return u;
147 }
148
149 static int
150 ifloor(int x, int y)
151 {
152     if(x >= 0)
153         return x/y;
154     else
155         return x/y - 1;
156 }
157
158 static int
159 iceil(int x, int y)
160 {
161     return ifloor(x + y - 1, y);
162 }
163   
164 static int
165 FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber)
166 {
167     FT_Error ftrc;
168     int bucket;
169     FTFacePtr face, otherFace;
170
171     if (!ftypeInitP) {
172         ftrc = FT_Init_FreeType(&ftypeLibrary);
173         if (ftrc != 0) {
174             ErrorF("FreeType: error initializing ftypeEngine: %d\n", ftrc);
175             return AllocError;
176         }
177         ftypeInitP = 1;
178     }
179
180     /* Try to find a matching face in the hashtable */
181     bucket = hash(FTFileName)%NUMFACEBUCKETS;
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 Successful;
191     }
192
193     /* No cached match; need to make a new one */
194     face = calloc(1, sizeof(FTFaceRec));
195     if (face == NULL) {
196         return AllocError;
197     }
198
199     face->filename = strdup(FTFileName);
200     if (face->filename == NULL) {
201         free(face);
202         return AllocError;
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 BadFontName;
211     }
212
213     face->bitmap = ((face->face->face_flags & FT_FACE_FLAG_SCALABLE) == 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, 34 );
223
224     /* Insert face in hashtable and return it */
225     face->next = faceTable[bucket];
226     faceTable[bucket] = face;
227     *facep = face;
228     return Successful;
229 }
230
231 static void
232 FreeTypeFreeFace(FTFacePtr face)
233 {
234     int bucket;
235     FTFacePtr otherFace;
236
237     if(!face->instances) {
238         bucket = hash(face->filename) % NUMFACEBUCKETS;
239         if(faceTable[bucket] == face)
240             faceTable[bucket] = face->next;
241         else {
242             otherFace = faceTable[bucket];
243             while(otherFace) {
244                 if(otherFace->next == face)
245                     break;
246                 otherFace = otherFace->next;
247             }
248             if(otherFace && otherFace->next)
249                 otherFace->next = otherFace->next->next;
250             else
251                 ErrorF("FreeType: freeing unknown face\n");
252         }
253         MUMBLE("Closing face: %s\n", face->filename);
254         FT_Done_Face(face->face);
255         free(face->filename);
256         free(face);
257     }
258 }
259
260 static int
261 TransEqual(FTNormalisedTransformationPtr t1, FTNormalisedTransformationPtr t2)
262 {
263     if(t1->scale != t2->scale)
264         return 0;
265     else if(t1->xres != t2->xres || t1->yres != t2->yres)
266         return 0;
267     else if(t1->nonIdentity != t2->nonIdentity)
268         return 0;
269     else if(t1->nonIdentity && t2->nonIdentity) {
270         return 
271             t1->matrix.xx == t2->matrix.xx &&
272             t1->matrix.yx == t2->matrix.yx &&
273             t1->matrix.yy == t2->matrix.yy &&
274             t1->matrix.xy == t2->matrix.xy;
275     } else
276         return 1;
277 }
278
279 static int
280 BitmapFormatEqual(FontBitmapFormatPtr f1, FontBitmapFormatPtr f2)
281 {
282     return
283         f1->bit == f2->bit &&
284         f1->byte == f2->byte &&
285         f1->glyph == f2->glyph;
286 }
287
288 static int
289 TTCapEqual(struct TTCapInfo *t1, struct TTCapInfo *t2)
290 {
291     return
292         t1->autoItalic == t2->autoItalic &&
293         t1->scaleWidth == t2->scaleWidth &&
294         t1->scaleBBoxWidth == t2->scaleBBoxWidth &&
295         t1->scaleBBoxHeight == t2->scaleBBoxHeight &&
296         t1->doubleStrikeShift == t2->doubleStrikeShift &&
297         t1->adjustBBoxWidthByPixel == t2->adjustBBoxWidthByPixel &&
298         t1->adjustLeftSideBearingByPixel == t2->adjustLeftSideBearingByPixel &&
299         t1->adjustRightSideBearingByPixel == t2->adjustRightSideBearingByPixel &&
300         t1->flags == t2->flags &&
301         t1->scaleBitmap == t2->scaleBitmap &&
302         /*
303           If we use forceConstantSpacing, 
304           we *MUST* allocate new instance.
305         */
306         t1->forceConstantSpacingEnd < 0 &&
307         t2->forceConstantSpacingEnd < 0;
308 }
309
310 static int
311 FTInstanceMatch(FTInstancePtr instance,
312                 char *FTFileName, FTNormalisedTransformationPtr trans,
313                 int spacing, FontBitmapFormatPtr bmfmt,
314                 struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags) 
315 {
316     if(strcmp(instance->face->filename, FTFileName) != 0) {
317         return 0;
318     } else if(!TransEqual(&instance->transformation, trans)) {
319         return 0;
320     } else if( spacing != instance->spacing ) {
321         return 0;
322     } else if( load_flags != instance->load_flags ) {
323         return 0;
324     } else if(!BitmapFormatEqual(&instance->bmfmt, bmfmt)) {
325         return 0;
326     } else if(!TTCapEqual(&instance->ttcap, tmp_ttcap)) {
327         return 0;
328     } else {
329         return 1;
330     }
331 }
332
333 static int
334 FreeTypeActivateInstance(FTInstancePtr instance)
335 {
336     FT_Error ftrc;
337     if(instance->face->active_instance == instance)
338         return Successful;
339
340     ftrc = FT_Activate_Size(instance->size);
341     if(ftrc != 0) {
342         instance->face->active_instance = NULL;
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 Successful;
353 }
354
355 static int
356 FTFindSize(FT_Face face, FTNormalisedTransformationPtr trans,
357            int *x_return, int *y_return)
358 {
359     int tx, ty, x, y;
360     int i, j;
361     int d, dd;
362
363     if(trans->nonIdentity)
364         return BadFontName;
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) <= 1 && ABS(y - ty) <= 1) {
375             dd = ABS(x - tx) * ABS(x - tx) + ABS(y - ty) * ABS(y - ty);
376             if(dd < d) {
377                 j = i;
378                 d = dd;
379             }
380         }            
381     }
382     if(j < 0)
383         return BadFontName;
384
385     *x_return = face->available_sizes[j].width;
386     *y_return = face->available_sizes[j].height;
387     return Successful;
388 }
389
390 static int
391 FreeTypeOpenInstance(FTInstancePtr *instance_return, FTFacePtr face,
392                      char *FTFileName, FTNormalisedTransformationPtr trans,
393                      int spacing, FontBitmapFormatPtr bmfmt,
394                      struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags)
395 {
396     FT_Error ftrc;
397     int xrc;
398     FTInstancePtr instance, otherInstance;
399
400     /* Search for a matching instance */
401     for(otherInstance = face->instances;
402         otherInstance;
403         otherInstance = otherInstance->next) {
404         if(FTInstanceMatch(otherInstance, FTFileName, trans, spacing, bmfmt,
405                            tmp_ttcap, load_flags)) break;
406     }
407     if(otherInstance) {
408         MUMBLE("Returning cached instance\n");
409         otherInstance->refcount++;
410         *instance_return = otherInstance;
411         return Successful;
412     }
413
414     /* None matching found */
415     instance = malloc(sizeof(FTInstanceRec));
416     if(instance == NULL) {
417         return AllocError;
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;
429     instance->averageWidth = 0;
430     instance->rawAverageWidth = 0;
431     instance->forceConstantMetrics = NULL;
432
433     instance->transformation = *trans;
434     instance->bmfmt = *bmfmt;
435     instance->glyphs = NULL;
436     instance->available = NULL;
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 != Successful) {
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 ) ) {
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 );
485         tt_dim_y = FLOOR64( ( tt_char_height * trans->yres + 36 ) / 72 + 32 );
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) && tt_dim_y == FLOOR64(sz->y_ppem + 32) )
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 Successful;
536 }
537
538 static void
539 FreeTypeFreeInstance(FTInstancePtr instance)
540 {
541     FTInstancePtr otherInstance;
542
543     if( instance == NULL ) return;
544
545     if(instance->face->active_instance == instance)
546         instance->face->active_instance = NULL;
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, FONTSEGMENTSIZE); i++) {
574                 if(instance->glyphs[i]) {
575                     for(j = 0; j < FONTSEGMENTSIZE; j++) {
576                         if(instance->available[i][j] == 
577                            FT_AVAILABLE_RASTERISED)
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, FONTSEGMENTSIZE); i++) {
587                 if(instance->available[i])
588                     free(instance->available[i]);
589             }
590             free(instance->available);
591         }
592         free(instance);
593     }
594 }
595
596 static int
597 FreeTypeInstanceFindGlyph(unsigned idx_in, int flags, FTInstancePtr instance,
598                           CharInfoPtr **glyphs, int ***available,
599                           int *found, int *segmentP, int *offsetP)
600 {
601     int segment, offset;
602     unsigned idx = idx_in;
603
604     if( 0 <= instance->ttcap.forceConstantSpacingEnd ){
605         if( (flags & FT_FORCE_CONSTANT_SPACING) )
606             idx += instance->nglyphs / 2 ;
607     }
608
609     if(idx > instance->nglyphs) {
610         *found = 0;
611         return Successful;
612     }
613   
614     if(*available == NULL) {
615         *available = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE),
616                             sizeof(int *));
617         if(*available == NULL)
618             return AllocError;
619     }
620
621     segment = ifloor(idx, FONTSEGMENTSIZE);
622     offset = idx - segment * FONTSEGMENTSIZE;
623
624     if((*available)[segment] == NULL) {
625         (*available)[segment] = calloc(FONTSEGMENTSIZE, sizeof(int *));
626         if((*available)[segment] == NULL)
627             return AllocError;
628     }
629
630     if(*glyphs == NULL) {
631         *glyphs = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE),
632                          sizeof(CharInfoPtr));
633         if(*glyphs == NULL)
634             return AllocError;
635     }
636
637     if((*glyphs)[segment] == NULL) {
638         (*glyphs)[segment] = malloc(sizeof(CharInfoRec) * FONTSEGMENTSIZE);
639         if((*glyphs)[segment] == NULL)
640             return AllocError;
641     }
642
643     *found = 1;
644     *segmentP = segment;
645     *offsetP = offset;
646     return Successful;
647 }
648
649 static int
650 FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance)
651 {
652     int found, segment, offset;
653     int xrc;
654     int ***available;
655     CharInfoPtr **glyphs;
656     
657     available = &instance->available;
658     glyphs = &instance->glyphs;
659
660     xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, glyphs, available,
661                                     &found, &segment, &offset);
662     if(xrc != Successful)
663         return xrc;
664
665     if(!found || (*available)[segment][offset] == FT_AVAILABLE_NO) {
666         *g = NULL;
667         return Successful;
668     } 
669
670     if((*available)[segment][offset] == FT_AVAILABLE_RASTERISED) {
671         *g = &(*glyphs)[segment][offset];
672         return Successful;
673     }
674     
675     flags |= FT_GET_GLYPH_BOTH;
676
677     xrc = FreeTypeRasteriseGlyph(idx, flags, 
678                                  &(*glyphs)[segment][offset], instance, 
679                                  (*available)[segment][offset] >= FT_AVAILABLE_METRICS);
680     if(xrc != Successful && (*available)[segment][offset] >= FT_AVAILABLE_METRICS) {
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_DUMMY,
684                                      &(*glyphs)[segment][offset], instance,
685                                      (*available)[segment][offset] >= FT_AVAILABLE_METRICS);
686     }
687     if(xrc == Successful) {
688         (*available)[segment][offset] = FT_AVAILABLE_RASTERISED;
689         /* return the glyph */
690         *g = &(*glyphs)[segment][offset];
691     }
692     return xrc;
693 }
694
695 static int
696 FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags,
697                                 xCharInfo **metrics, FTInstancePtr instance )
698 {
699     int xrc;
700     int found, segment, offset;
701     
702     /* Char cell */
703     if(instance->spacing == FT_CHARCELL) {
704         *metrics = instance->charcellMetrics;
705         return Successful;
706     }
707     /* Force constant metrics  */
708     if( flags & FT_FORCE_CONSTANT_SPACING) {
709         *metrics = instance->forceConstantMetrics;
710         return Successful;
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 != Successful)
719         return xrc;
720     if(!found) {
721         *metrics = NULL;
722         return Successful;
723     }
724     if( instance->available[segment][offset] == FT_AVAILABLE_NO ) {
725         *metrics = NULL;
726         return Successful;
727     } 
728
729     if( instance->available[segment][offset] >= FT_AVAILABLE_METRICS ) {
730         *metrics = &instance->glyphs[segment][offset].metrics;
731         return Successful;
732     }
733     
734     flags |= FT_GET_GLYPH_METRICS_ONLY;
735
736     xrc = FreeTypeRasteriseGlyph(idx, flags, 
737                                  &instance->glyphs[segment][offset],
738                                  instance, 0);
739     if(xrc == Successful) {
740         instance->available[segment][offset] = FT_AVAILABLE_METRICS;
741         *metrics = &instance->glyphs[segment][offset].metrics;
742     }
743     return xrc;
744 }
745     
746 /*
747  * Pseudo enbolding similar as Microsoft Windows.
748  * It is useful but poor.
749  */
750 static void
751 ft_make_up_bold_bitmap( char *raster, int bpr, int ht, int ds_mode)
752 {
753     int x, y;
754     unsigned char *p = (unsigned char *)raster;
755     if ( ds_mode & TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT ) {
756         for (y=0; y<ht; y++) {
757             unsigned char rev_pat=0;
758             unsigned char lsb = 0;
759             for (x=0; x<bpr; x++) {
760                 unsigned char tmp = *p<<7;
761                 if ( (rev_pat & 0x01) && (*p & 0x80) ) p[-1] &= 0xfe;
762                 rev_pat = ~(*p);
763                 *p |= (*p>>1) | lsb;
764                 *p &= ~(rev_pat & (*p << 1));
765                 lsb = tmp;
766                 p++;
767             }
768         }
769     }
770     else {
771         for (y=0; y<ht; y++) {
772             unsigned char lsb = 0;
773             for (x=0; x<bpr; x++) {
774                 unsigned char tmp = *p<<7;
775                 *p |= (*p>>1) | lsb;
776                 lsb = tmp;
777                 p++;
778             }
779         }
780     }
781 }
782
783 static void
784 ft_make_up_italic_bitmap( char *raster, int bpr, int ht, int shift,
785                           int h_total, int h_offset, double a_italic)
786 {
787     int x, y;
788     unsigned char *p = (unsigned char *)raster;
789     if ( a_italic < 0 ) shift = -shift;
790     for (y=0; y<ht; y++) {
791         unsigned char *tmp_p = p + y*bpr;
792         int tmp_shift = shift * (h_total -1 -(y+h_offset)) / h_total;
793         int tmp_byte_shift;
794         if ( 0 <= tmp_shift ) {
795             tmp_byte_shift = tmp_shift/8;
796             tmp_shift %= 8;
797             if ( tmp_shift ) {
798                 for (x=bpr-1;0<=x;x--) {
799                     if ( x != bpr-1 ) 
800                         tmp_p[x+1] |= tmp_p[x]<<(8-tmp_shift);
801                     tmp_p[x]>>=tmp_shift;
802                 }
803             }
804             if ( tmp_byte_shift ) {
805                 for (x=bpr-1;0<x;x--) {
806                     tmp_p[x] = tmp_p[x-1];
807                 }
808                 tmp_p[x]=0;
809             }
810         }
811         else {
812             tmp_shift = -tmp_shift;
813             tmp_byte_shift = tmp_shift/8;
814             tmp_shift %= 8;
815             if ( tmp_shift ) {
816                 for (x=0;x<bpr;x++) {
817                     if ( x != 0 ) 
818                         tmp_p[x-1] |= tmp_p[x]>>(8-tmp_shift);
819                     tmp_p[x]<<=tmp_shift;
820                 }
821             }
822             if ( tmp_byte_shift ) {
823                 for (x=0;x<bpr-1;x++) {
824                     tmp_p[x] = tmp_p[x+1];
825                 }
826                 tmp_p[x]=0;
827             }
828         }
829     }
830 }
831
832 /*
833  * The very lazy method,
834  * parse the htmx field in TrueType font.
835  */
836
837 static void
838 tt_get_metrics( FT_Face         face,
839                 FT_UInt         idx,
840                 FT_UInt         num_hmetrics,
841                 FT_Short*       bearing,
842                 FT_UShort*      advance )
843 {
844    /* read the metrics directly from the horizontal header, we
845     * parse the SFNT table directly through the standard FreeType API.
846     * this works with any version of the library and doesn't need to
847     * peek at its internals. Maybe a bit less
848     */
849     FT_UInt  count  = num_hmetrics;
850     FT_ULong length = 0;
851     FT_ULong offset = 0;
852     FT_Error error;
853
854     error = FT_Load_Sfnt_Table( face, TTAG_hmtx, 0, NULL, &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, offset );
872             *bearing = sfnt_get_short ( face, TTAG_hmtx, 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, 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 );
891     }
892     }
893 }
894
895 static int                   
896 ft_get_very_lazy_bbox( FT_UInt index,
897                        FT_Face face,
898                        FT_Size size,
899                        FT_UInt num_hmetrics,
900                        double slant,
901                        FT_Matrix *matrix,
902                        FT_BBox *bbox,
903                        FT_Long *horiAdvance,
904                        FT_Long *vertAdvance)
905 {
906     if ( FT_IS_SFNT( face ) ) {
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(stderr,"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(stderr,
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)));
961         bbox->xMax = MAX(p0.x, MAX(p1.x, MAX(p2.x, p3.x)));
962         bbox->yMin = MIN(p0.y, MIN(p1.y, MIN(p2.y, p3.y)));
963         bbox->yMax = MAX(p0.y, MAX(p1.y, MAX(p2.y, p3.y)));
964         return 0;       /* Successful */
965     }
966     return -1;
967 }
968
969 static FT_Error
970 FT_Do_SBit_Metrics( FT_Face ft_face, FT_Size ft_size, FT_ULong strike_index,
971                     FT_UShort glyph_index, FT_Glyph_Metrics *metrics_return,
972                     int *sbitchk_incomplete_but_exist )
973 {
974 #if 1
975     if ( strike_index != 0xFFFFU && ft_face->available_sizes != NULL )
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_ONLY );
984         if ( !error )
985         {
986           if ( metrics_return != NULL )
987             *metrics_return = ft_face->glyph->metrics;
988
989           return 0;
990         }
991       }
992     }
993     return -1;
994 #elif (FREETYPE_VERSION >= 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 ) )
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 ) 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, stream, 0 );
1031     if ( error )
1032       error = face->goto_table( face, TTAG_bdat, 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 ) ) return -1;
1063     face = (TT_Face)ft_face;
1064     sfnt = (SFNT_Service)face->sfnt;
1065     if ( strike_index != 0xFFFFU && sfnt->load_sbits ) {
1066         if ( sbitchk_incomplete_but_exist ) *sbitchk_incomplete_but_exist=1;
1067     }
1068     return -1;
1069 #endif
1070 }
1071
1072 int
1073 FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp,
1074                        FTInstancePtr instance, int hasMetrics)
1075 {
1076     FTFacePtr face;
1077     FT_BBox bbox;
1078     FT_Long outline_hori_advance, outline_vert_advance;
1079     FT_Glyph_Metrics sbit_metrics;
1080     FT_Glyph_Metrics *bitmap_metrics=NULL, *metrics = NULL;
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 AllocError;
1096
1097     /*
1098      * PREPARE METRICS
1099      */
1100
1101     if(!hasMetrics) {
1102         if( instance->spacing == FT_CHARCELL || flags & FT_GET_DUMMY ){
1103             memcpy((char*)&tgp->metrics, 
1104                    (char*)instance->charcellMetrics,
1105                    sizeof(xCharInfo));
1106         }
1107         else if( flags & FT_FORCE_CONSTANT_SPACING ) {
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_BITMAP) ) {
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 ) {
1125                 if ( sbitchk_incomplete_but_exist==0 && (instance->ttcap.flags & TTCAP_IS_VERY_LAZY) ) {
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_WIDTH )
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_STRIKE )
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) / 64;
1189                 leftSideBearing  = FLOOR64(bbox.xMin + 32) / 64;
1190                 ascent   = FLOOR64(bbox.yMax + 32) / 64;
1191                 rightSideBearing = FLOOR64(bbox.xMax + 32) / 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_WIDTH )
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_STRIKE )
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_PROPORTIONAL )
1242                 tgp->metrics.characterWidth = instance->charcellMetrics->characterWidth;
1243             if(instance->ttcap.flags & TTCAP_MONO_CENTER){
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_ONLY ) return Successful;
1252
1253     /*
1254      * CHECK THE NECESSITY OF BITMAP POSITION'S CORRECTION
1255      */
1256
1257     correct=0;
1258     if( instance->spacing == FT_CHARCELL ) correct=1;
1259     else if( flags & FT_FORCE_CONSTANT_SPACING ) correct=1;
1260     else{
1261         int sbit_available=0;
1262         sbitchk_incomplete_but_exist=0;
1263         if( !(instance->load_flags & FT_LOAD_NO_BITMAP) ) {
1264             if( FT_Do_SBit_Metrics(face->face,instance->size,
1265                                    instance->strike_index,idx,NULL,
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_LAZY) ) {
1272                 if( FT_IS_SFNT(face->face) ) correct=1;
1273             }
1274         }
1275     }
1276
1277     /*
1278      * RENDER AND ALLOCATE BUFFER
1279      */
1280
1281     if( flags & FT_GET_DUMMY ) 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 );
1300             bbox.yMax = CEIL64 ( bbox.yMax );
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_CENTER) && 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) 
1364         return AllocError;
1365
1366     tgp->bits = raster;
1367
1368     /* If FT_GET_DUMMY is set, we return white space. */
1369     if ( is_outline == -1 ) return Successful;
1370
1371     if ( wd_actual <= 0 || ht_actual <= 0 ) return Successful;
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_CENTER)
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) / 64;
1395         lsb = FLOOR64(bbox.xMin + 32) / 64;
1396         asc = FLOOR64(bbox.yMax + 32) / 64;
1397         rsb = FLOOR64(bbox.xMax + 32) / 64;
1398         rightSideBearing = tgp->metrics.rightSideBearing;
1399         leftSideBearing  = tgp->metrics.leftSideBearing;
1400         if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE )
1401             rightSideBearing -= instance->ttcap.doubleStrikeShift;
1402         /* special case */
1403         if(instance->ttcap.flags & TTCAP_MONO_CENTER){
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_SPACING ){
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) ; 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);
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_STRIKE ) {
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 == LSBFirst) {
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 Successful;
1516 }
1517
1518 static void
1519 FreeTypeFreeFont(FTFontPtr font)
1520 {
1521     FreeTypeFreeInstance(font->instance);
1522     if(font->ranges)
1523         free(font->ranges);
1524     if(font->dummy_char.bits)
1525         free(font->dummy_char.bits);
1526     free(font);
1527 }
1528
1529 /* Free a font.  If freeProps is 0, don't free the properties. */
1530
1531 static void
1532 FreeTypeFreeXFont(FontPtr pFont, int freeProps)
1533 {
1534     FTFontPtr tf;
1535     
1536     if(pFont) {
1537         if((tf = (FTFontPtr)pFont->fontPrivate)) {
1538             FreeTypeFreeFont(tf);
1539         }
1540         if(freeProps && pFont->info.nprops>0) {
1541             free(pFont->info.isStringProp);
1542             free(pFont->info.props);
1543         }
1544         DestroyFontRec(pFont);
1545     }
1546 }
1547
1548
1549 /* Unload a font */
1550
1551 static void
1552 FreeTypeUnloadXFont(FontPtr pFont)
1553 {
1554     MUMBLE("Unloading\n");
1555     FreeTypeFreeXFont(pFont, 1);
1556 }
1557
1558 /* Add the font properties, including the Font name, the XLFD
1559    properties, some strings from the font, and various typographical
1560    data.  We only provide data readily available in the tables in the
1561    font for now, altough FIGURE_WIDTH would be a good idea as it is
1562    used by Xaw. */
1563
1564 static int
1565 FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info, 
1566                       char *fontname, int rawAverageWidth, Bool font_properties)
1567 {
1568     int i, j, maxprops;
1569     char *sp, *ep, val[MAXFONTNAMELEN], *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_UPM;
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;
1596
1597     if(t1info) {
1598         os2 = NULL;
1599         post = NULL;
1600     }
1601
1602     info->nprops = 0;           /* in case we abort */
1603   
1604     strcpy(val, fontname);
1605     if(FontParseXLFDName(val, vals, FONT_XLFD_REPLACE_VALUE)) {
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)
1624         return AllocError;
1625     
1626     info->isStringProp = malloc(maxprops);
1627     if(info->isStringProp == NULL) {
1628         free(info->props);
1629         return AllocError;
1630     }
1631
1632     memset((char *)info->isStringProp, 0, maxprops);
1633
1634     i = 0;
1635
1636     info->props[i].name = MakeAtom("FONT", 4, TRUE);
1637     info->props[i].value = MakeAtom(val, strlen(val), TRUE);
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]), TRUE);
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, TRUE);
1678                 info->isStringProp[i] = 1;
1679                 i++;
1680             }
1681             sp = ++ep;
1682         }
1683     }
1684
1685     info->props[i].name = MakeAtom("RAW_PIXEL_SIZE", 14, TRUE);
1686     info->props[i].value = 1000;
1687     i++;
1688
1689     info->props[i].name = MakeAtom("RAW_POINT_SIZE", 14, TRUE);
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, TRUE);
1695         info->props[i].value = rawAverageWidth;
1696         i++;
1697     }
1698
1699     if ( font_properties ) {
1700         info->props[i].name = MakeAtom("FONT_ASCENT", 11, TRUE);
1701         info->props[i].value = info->fontAscent;
1702         i++;
1703     }
1704
1705     if(!face->bitmap) {
1706         info->props[i].name = MakeAtom("RAW_ASCENT", 10, TRUE);
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, TRUE);
1714         info->props[i].value = info->fontDescent;
1715         i++;
1716     }
1717
1718     if(!face->bitmap) {
1719         info->props[i].name = MakeAtom("RAW_DESCENT", 11, TRUE);
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_COPYRIGHT,
1726                          val, MAXFONTNAMELEN);
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, TRUE);
1736         info->props[i].value = MakeAtom(vp, j, TRUE);
1737         info->isStringProp[i] = 1;
1738         i++;
1739     }
1740     
1741     j = FTGetEnglishName(face->face, TT_NAME_ID_FULL_NAME,
1742                          val, MAXFONTNAMELEN);
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, TRUE);
1752         info->props[i].value = MakeAtom(vp, j, TRUE);
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_NAME,
1765                          val, MAXFONTNAMELEN);
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, TRUE);
1776         info->props[i].value = MakeAtom(vp, j, TRUE);
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,TRUE);
1796         info->props[i].value = 
1797             TRANSFORM_FUNITS_Y(os2->ySubscriptYSize);
1798         i++;
1799         info->props[i].name = MakeAtom("SUBSCRIPT_X",11,TRUE);
1800         info->props[i].value = 
1801             TRANSFORM_FUNITS_X(os2->ySubscriptXOffset);
1802         i++;
1803         info->props[i].name = MakeAtom("SUBSCRIPT_Y",11,TRUE);
1804         info->props[i].value = 
1805             TRANSFORM_FUNITS_Y(os2->ySubscriptYOffset);
1806         i++;
1807         info->props[i].name = MakeAtom("SUPERSCRIPT_SIZE",16,TRUE);
1808         info->props[i].value = 
1809             TRANSFORM_FUNITS_Y(os2->ySuperscriptYSize);
1810         i++;
1811         info->props[i].name = MakeAtom("SUPERSCRIPT_X",13,TRUE);
1812         info->props[i].value = 
1813             TRANSFORM_FUNITS_X(os2->ySuperscriptXOffset);
1814         i++;
1815         info->props[i].name = MakeAtom("SUPERSCRIPT_Y",13,TRUE);
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,TRUE);
1839         info->props[i].value = underlineThickness;
1840         i++;
1841
1842         info->props[i].name = MakeAtom("UNDERLINE_POSITION",18,TRUE);
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,TRUE);
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, TRUE);
1862     vp = (char *)FT_Get_X11_Font_Format(face->face);
1863     info->props[i].value = MakeAtom(vp, strlen(vp), TRUE);
1864     info->isStringProp[i] = 1;
1865     i++;
1866     
1867     info->props[i].name  = MakeAtom("RASTERIZER_NAME", 15, TRUE);
1868     info->props[i].value = MakeAtom("FreeType", 10, TRUE);
1869     info->isStringProp[i] = 1;
1870     i++;
1871     
1872     info->nprops = i;
1873     return Successful;
1874 }
1875
1876 static int
1877 ft_get_index(unsigned code, FTFontPtr font, unsigned *idx)
1878 {
1879     
1880     /* As a special case, we pass 0 even when it is not in the ranges;
1881        this will allow for the default glyph, which should exist in any
1882        TrueType font. */
1883     
1884     /* This is not required...
1885     if(code > 0 && font->nranges) {
1886         int i;
1887         for(i = 0; i < font->nranges; i++)
1888             if((code >= 
1889                 font->ranges[i].min_char_low+
1890                 (font->ranges[i].min_char_high<<8)) &&
1891                (code <=
1892                 font->ranges[i].max_char_low + 
1893                 (font->ranges[i].max_char_high<<8)))
1894                 break;
1895         if(i == font->nranges) {
1896             *idx = font->zero_idx;
1897             return -1;
1898         }
1899     }
1900     */
1901     if( font->info ) {
1902         if( !( font->info->firstCol <= (code & 0x000ff) &&
1903                (code & 0x000ff) <= font->info->lastCol &&
1904                font->info->firstRow <= (code >> 8) &&
1905                (code >> 8) <= font->info->lastRow ) ) {
1906             *idx = font->zero_idx;
1907             /* Error: The code has not been parsed in ft_compute_bounds()!
1908                We should not return any metrics. */
1909             return -1;
1910         }
1911     }
1912
1913     *idx = FTRemap(font->instance->face->face, &font->mapping, code);
1914     
1915     return 0;
1916 }
1917
1918 static int
1919 FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font)
1920 {
1921     unsigned idx = 0;
1922     int xrc;
1923     
1924 #ifdef X_ACCEPTS_NO_SUCH_CHAR
1925     if( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) {
1926         *g = NULL;
1927         flags &= ~FT_FORCE_CONSTANT_SPACING;
1928         /* if( font->instance->spacing != FT_CHARCELL ) */
1929         return Successful;
1930     }
1931 #else
1932     if( ft_get_index(code,font,&idx) ) {
1933         /* The code has not been parsed! */
1934         *g = NULL;
1935         flags &= ~FT_FORCE_CONSTANT_SPACING;
1936     }
1937 #endif
1938
1939     xrc = FreeTypeInstanceGetGlyph(idx, flags, g, font->instance);
1940     if( xrc == Successful && *g != NULL )
1941         return Successful;
1942     if( font->zero_idx != idx ) {
1943         xrc = FreeTypeInstanceGetGlyph(font->zero_idx, flags, g, font->instance);
1944         if( xrc == Successful && *g != NULL )
1945             return Successful;
1946     }
1947     return FreeTypeInstanceGetGlyph(font->zero_idx, flags|FT_GET_DUMMY, g, font->instance);
1948 }
1949
1950 static int
1951 FreeTypeFontGetGlyphMetrics(unsigned code, int flags, xCharInfo **metrics, FTFontPtr font)
1952 {
1953     unsigned idx = 0;
1954     int xrc;
1955
1956 #ifdef X_ACCEPTS_NO_SUCH_CHAR
1957     if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) {
1958         *metrics = NULL;
1959         flags &= ~FT_FORCE_CONSTANT_SPACING;
1960         /* if( font->instance->spacing != FT_CHARCELL ) */
1961         return Successful;
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;
1967         flags &= ~FT_FORCE_CONSTANT_SPACING;
1968     }
1969 #endif
1970
1971     xrc = FreeTypeInstanceGetGlyphMetrics(idx, flags, metrics, font->instance);
1972     if( xrc == Successful && *metrics != NULL )
1973         return Successful;
1974     if( font->zero_idx != idx ) {
1975         xrc = FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags, 
1976                                               metrics, font->instance);
1977         if( xrc == Successful && *metrics != NULL )
1978             return Successful;
1979     }
1980     return FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags|FT_GET_DUMMY, metrics, font->instance);
1981 }
1982
1983 /*
1984  * restrict code range
1985  *
1986  * boolean for the numeric zone:
1987  *   results = results & (ranges[0] | ranges[1] | ... ranges[nranges-1])
1988  */
1989
1990 static void
1991 restrict_code_range(unsigned short *refFirstCol,
1992                     unsigned short *refFirstRow,
1993                     unsigned short *refLastCol,
1994                     unsigned short *refLastRow,
1995                     fsRange const *ranges, int nRanges)
1996 {
1997     if (nRanges) {
1998         int minCol = 256, minRow = 256, maxCol = -1, maxRow = -1;
1999         fsRange const *r = ranges;
2000         int i;
2001
2002         for (i=0; i<nRanges; i++) {
2003             if (r->min_char_high != r->max_char_high) {
2004                 minCol = 0x00;
2005                 maxCol = 0xff;
2006             } else {
2007                 if (minCol > r->min_char_low)
2008                     minCol = r->min_char_low;
2009                 if (maxCol < r->max_char_low)
2010                     maxCol = r->max_char_low;
2011             }
2012             if (minRow > r->min_char_high)
2013                 minRow = r->min_char_high;
2014             if (maxRow < r->max_char_high)
2015                 maxRow = r->max_char_high;
2016             r++;
2017         }
2018
2019         if (minCol > *refLastCol)
2020             *refFirstCol = *refLastCol;
2021         else if (minCol > *refFirstCol)
2022             *refFirstCol = minCol;
2023
2024         if (maxCol < *refFirstCol)
2025             *refLastCol = *refFirstCol;
2026         else if (maxCol < *refLastCol)
2027             *refLastCol = maxCol;
2028
2029         if (minRow > *refLastRow) {
2030             *refFirstRow = *refLastRow;
2031             *refFirstCol = *refLastCol;
2032         } else if (minRow > *refFirstRow)
2033             *refFirstRow = minRow;
2034
2035         if (maxRow < *refFirstRow) {
2036             *refLastRow = *refFirstRow;
2037             *refLastCol = *refFirstCol;
2038         } else if (maxRow < *refLastRow)
2039             *refLastRow = maxRow;
2040     }
2041 }
2042
2043
2044 static int
2045 restrict_code_range_by_str(int count,unsigned short *refFirstCol,
2046                            unsigned short *refFirstRow,
2047                            unsigned short *refLastCol,
2048                            unsigned short *refLastRow,
2049                            char const *str)
2050 {
2051     int nRanges = 0;
2052     int result = 0;
2053     fsRange *ranges = NULL;
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))
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))
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))
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(stderr, "zone: 0x%04X - 0x%04X\n", minpoint, maxpoint);
2119         fflush(stderr);
2120 #endif
2121         nRanges++;
2122         ranges = realloc(ranges, nRanges*sizeof(*ranges));
2123         if (NULL == ranges)
2124             break;
2125         {
2126             fsRange *r = ranges+nRanges-1;
2127
2128             r->min_char_low = minpoint & 0xff;
2129             r->max_char_low = maxpoint & 0xff;
2130             r->min_char_high = (minpoint>>8) & 0xff;
2131             r->max_char_high = (maxpoint>>8) & 0xff;
2132         }
2133     }
2134
2135     if (ranges) {
2136         if ( count <= 0 ) {
2137             restrict_code_range(refFirstCol, refFirstRow, refLastCol, refLastRow,
2138                                 ranges, nRanges);
2139         }
2140         else {
2141             int i;
2142             fsRange *r;
2143             for ( i=0 ; i<nRanges ; i++ ) {
2144                 if ( count <= i ) break;
2145                 r = ranges+i;
2146                 refFirstCol[i] = r->min_char_low;
2147                 refLastCol[i] = r->max_char_low;
2148                 refFirstRow[i] = r->min_char_high;
2149                 refLastRow[i] = r->max_char_high;
2150             }
2151             result=i;
2152         }
2153         free(ranges);
2154     }
2155     return result;
2156 }
2157
2158 /* *face_number and *spacing are initialized but *load_flags is NOT. */
2159 static int 
2160 FreeTypeSetUpTTCap( char *fileName, FontScalablePtr vals,
2161                     char **dynStrRealFileName, char **dynStrFTFileName,
2162                     struct TTCapInfo *ret, int *face_number, FT_Int32 *load_flags,
2163                     int *spacing, Bool *font_properties, char **dynStrTTCapCodeRange )
2164 {
2165     int result = Successful;
2166     SDynPropRecValList listPropRecVal;
2167     SPropRecValContainer contRecValue;
2168     Bool hinting=True;
2169     Bool isEmbeddedBitmap = True;
2170     Bool alwaysEmbeddedBitmap = False;
2171     int pixel = vals->pixel;
2172
2173     *font_properties=True;
2174     *dynStrRealFileName=NULL;
2175     *dynStrFTFileName=NULL;
2176     *dynStrTTCapCodeRange=NULL;
2177
2178     if (SPropRecValList_new(&listPropRecVal)) {
2179         return AllocError;
2180     }
2181
2182     {
2183         int len = strlen(fileName);
2184         char *capHead = NULL;
2185         {
2186             /* font cap */
2187             char *p1=NULL, *p2=NULL;
2188             
2189             p1=strrchr(fileName, '/');
2190             if ( p1 == NULL ) p1 = fileName;
2191             else p1++;
2192             if (NULL != (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 ) {
2199                     result = AllocError;
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);
2208                 if( *dynStrRealFileName == NULL ) {
2209                     result = AllocError;
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 = BadFontPath;
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,*endptr;
2254         if ( SPropRecValList_search_record(&listPropRecVal,
2255                                        &contRecValue,
2256                                        "FaceNumber")) {
2257             int lv;
2258             beginptr = SPropContainer_value_str(contRecValue);
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 ){
2269                 result = AllocError;
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 ){
2294                 result = AllocError;
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);
2311     /* hinting control */
2312     if (SPropRecValList_search_record(&listPropRecVal,
2313                                       &contRecValue,
2314                                       "Hinting"))
2315         hinting = SPropContainer_value_bool(contRecValue);
2316     /* scaling */
2317     if (SPropRecValList_search_record(&listPropRecVal,
2318                                       &contRecValue,
2319                                       "ScaleWidth")) {
2320         ret->scaleWidth = SPropContainer_value_dbl(contRecValue);
2321         if (ret->scaleWidth<=0.0) {
2322             fprintf(stderr, "ScaleWitdh needs plus.\n");
2323             result = BadFontName;
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);
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(stderr, "ScaleBBoxWitdh needs plus.\n");
2371             result = BadFontName;
2372             goto quit;
2373         }
2374         if (scaleBBoxHeight<=0.0) {
2375             fprintf(stderr, "ScaleBBoxHeight needs plus.\n");
2376             result = BadFontName;
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);
2387         Bool err = False;
2388         if (1 != strlen(strSpace))
2389             err = True;
2390         else
2391             switch (strSpace[0]) {
2392             case 'M':
2393                 ret->flags |= TTCAP_MONO_CENTER;
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;
2403             }
2404         if (err) {
2405             result = BadFontName;
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);
2415         Bool err = False;
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_STRIKE;
2423                 ret->flags |= TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
2424                 break;
2425             case 'y':
2426             case 'Y':
2427                 ret->flags |= TTCAP_DOUBLE_STRIKE;
2428                 break;
2429             case 'n':
2430             case 'N':
2431                 ret->flags &= ~TTCAP_DOUBLE_STRIKE;
2432                 ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
2433                 ret->flags &= ~TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH;
2434                 break;
2435             default:
2436                 err = True;
2437             }
2438             if ( err != True ) {
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_WIDTH;
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_LEFT;
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_STRIKE )
2473                             ret->doubleStrikeShift += pixel / max_pixel;
2474                         }
2475                     }
2476                 } while(0);
2477             }
2478         }
2479         else
2480             err = True;
2481         if (err) {
2482             result = BadFontName;
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);
2491         ret->flags |= TTCAP_DISABLE_DEFAULT_VERY_LAZY;
2492         if( isVeryLazy == True )
2493             ret->flags |= TTCAP_IS_VERY_LAZY;
2494         else
2495             ret->flags &= ~TTCAP_IS_VERY_LAZY;
2496     }
2497     /* embedded bitmap */
2498     if (SPropRecValList_search_record(&listPropRecVal,
2499                                       &contRecValue,
2500                                       "EmbeddedBitmap")) {
2501         char *strEmbeddedBitmap = SPropContainer_value_str(contRecValue);
2502         Bool err = False;
2503         if ( 1 == strlen(strEmbeddedBitmap) ) {
2504             switch (strEmbeddedBitmap[0]) {
2505             case 'y':
2506             case 'Y':
2507                 isEmbeddedBitmap = True;
2508                 alwaysEmbeddedBitmap = True;
2509                 break;
2510             case 'u':
2511             case 'U':
2512                 isEmbeddedBitmap = True;
2513                 alwaysEmbeddedBitmap = False;
2514                 break;
2515             case 'n':
2516             case 'N':
2517                 isEmbeddedBitmap = False;
2518                 break;
2519             default:
2520                 err = True;
2521             }
2522         }
2523         else
2524             err = True;
2525         if (err) {
2526             result = BadFontName;
2527             goto quit;
2528         }
2529     }
2530     /* scale bitmap */
2531     if((ret->flags & TTCAP_IS_VERY_LAZY) &&
2532        SPropRecValList_search_record(&listPropRecVal,
2533                                      &contRecValue,
2534                                      "VeryLazyBitmapWidthScale")) {
2535         /* Scaling to Bitmap Bounding Box Width */
2536         double scaleBitmapWidth = SPropContainer_value_dbl(contRecValue);
2537
2538         fprintf(stderr, "Warning: `bs' option is not required in X-TT version 2.\n");
2539 #if 0
2540         if (scaleBitmapWidth<=0.0) {
2541             fprintf(stderr, "ScaleBitmapWitdh needs plus.\n");
2542             result = BadFontName;
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));
2553         if( *dynStrTTCapCodeRange == NULL ) {
2554             result = AllocError;
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)) == 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_OUTSIDE;
2572               else ret->flags |= TTCAP_FORCE_C_OUTSIDE;
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);
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;
2592                 if ( semic_ptr && period_ptr ) 
2593                     if ( semic_ptr < period_ptr ) period_ptr=NULL;
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)) == 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_FLAG;
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_FLAG;
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);
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 ) *load_flags |= FT_LOAD_NO_HINTING;
2678     if( isEmbeddedBitmap == False ) *load_flags |= FT_LOAD_NO_BITMAP;
2679     if( ret->autoItalic != 0 && alwaysEmbeddedBitmap == False )
2680         *load_flags |= FT_LOAD_NO_BITMAP;
2681
2682  quit:
2683     return result;
2684 }
2685
2686 static int
2687 ft_get_trans_from_vals( FontScalablePtr vals, FTNormalisedTransformationPtr trans )
2688 {
2689     /* Compute the transformation matrix.  We use floating-point
2690        arithmetic for simplicity */
2691     
2692     trans->xres = vals->x;
2693     trans->yres = vals->y;
2694     
2695     /* This value cannot be 0. */
2696     trans->scale = hypot(vals->point_matrix[2], vals->point_matrix[3]);
2697     trans->nonIdentity = 0;
2698     
2699     /* Try to round stuff.  We want approximate zeros to be exact zeros,
2700        and if the elements on the diagonal are approximately equal, we
2701        want them equal.  We do this to avoid breaking hinting. */
2702     if(DIFFER(vals->point_matrix[0], vals->point_matrix[3])) {
2703         trans->nonIdentity = 1;
2704         trans->matrix.xx =
2705             (int)((vals->point_matrix[0]*(double)TWO_SIXTEENTH)/trans->scale);
2706         trans->matrix.yy =
2707             (int)((vals->point_matrix[3]*(double)TWO_SIXTEENTH)/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)/trans->scale;
2712     }
2713     
2714     if(DIFFER0(vals->point_matrix[1], trans->scale)) {
2715         trans->matrix.yx =
2716             (int)((vals->point_matrix[1]*(double)TWO_SIXTEENTH)/trans->scale);
2717         trans->nonIdentity = 1;
2718     } else
2719         trans->matrix.yx = 0;
2720     
2721     if(DIFFER0(vals->point_matrix[2], trans->scale)) {
2722         trans->matrix.xy =
2723             (int)((vals->point_matrix[2]*(double)TWO_SIXTEENTH)/trans->scale);
2724         trans->nonIdentity = 1;
2725     } else
2726         trans->matrix.xy=0;
2727     return 0;
2728 }
2729
2730
2731 static int
2732 is_fixed_width(FT_Face face)
2733 {
2734     PS_FontInfoRec t1info_rec;
2735     int ftrc;
2736
2737     if(FT_IS_FIXED_WIDTH(face)) {
2738         return 1;
2739     }
2740
2741     ftrc = FT_Get_PS_Font_Info(face, &t1info_rec);
2742     if(ftrc == 0 && t1info_rec.is_fixed_pitch) {
2743         return 1;
2744     }
2745
2746     return 0;
2747 }
2748
2749 static int
2750 FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face,
2751                  char *FTFileName, FontScalablePtr vals, FontEntryPtr entry,
2752                  FontBitmapFormatPtr bmfmt, FT_Int32 load_flags, 
2753                  struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange,
2754                  int ttcap_spacing )
2755 {
2756     int xrc;
2757     FTNormalisedTransformationRec trans;
2758     int spacing, actual_spacing, zero_code;
2759     long  lastCode, firstCode;
2760     TT_Postscript *post;
2761
2762     ft_get_trans_from_vals(vals,&trans);
2763
2764     /* Check for charcell in XLFD */
2765     spacing = FT_PROPORTIONAL;
2766     if(entry->name.ndashes == 14) {
2767         char *p;
2768         int dashes = 0;
2769         for(p = entry->name.name; 
2770             p <= entry->name.name + entry->name.length - 2;
2771             p++) {
2772             if(*p == '-') {
2773                 dashes++;
2774                 if(dashes == 11) {
2775                     if(p[1]=='c' && p[2]=='-')
2776                         spacing=FT_CHARCELL;
2777                     else if(p[1]=='m' && p[2]=='-')
2778                         spacing=FT_MONOSPACED;
2779                     break;
2780                 }
2781             }
2782         }
2783     }
2784     /* by TTCap  */
2785     if( ttcap_spacing != 0 ) {
2786         if( ttcap_spacing == 'c' ) spacing=FT_CHARCELL;
2787         else if( ttcap_spacing == 'm' ) spacing=FT_MONOSPACED;
2788         else spacing=FT_PROPORTIONAL;
2789     }
2790
2791     actual_spacing = spacing;
2792     if( spacing == FT_PROPORTIONAL ) {
2793         if( is_fixed_width(face->face) )
2794             actual_spacing = FT_MONOSPACED;
2795     }
2796
2797     if(entry->name.ndashes == 14) {
2798         xrc = FTPickMapping(entry->name.name, entry->name.length, FTFileName,
2799                             face->face, &font->mapping);
2800         if (xrc != Successful)
2801             return xrc;
2802     } else {
2803         xrc = FTPickMapping(0, 0, FTFileName, 
2804                             face->face, &font->mapping);
2805         if (xrc != Successful)
2806             return xrc;
2807     }
2808     
2809     font->nranges = vals->nranges;
2810     font->ranges = 0;
2811     if(font->nranges) {
2812         font->ranges = malloc(vals->nranges*sizeof(fsRange));
2813         if(font->ranges == NULL) 
2814             return AllocError;
2815         memcpy((char*)font->ranges, (char*)vals->ranges,
2816                vals->nranges*sizeof(fsRange));
2817     }
2818
2819     zero_code=-1;
2820     if(info) {
2821         firstCode = 0;
2822         lastCode = 0xFFFFL;
2823         if(!font->mapping.mapping || 
2824            font->mapping.mapping->encoding->row_size == 0) {
2825             /* linear indexing */
2826             lastCode=MIN(lastCode,
2827                          font->mapping.mapping ?
2828                          font->mapping.mapping->encoding->size-1 :
2829                          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,
2842                                 lastCode/0x100);
2843             info->firstCol = font->mapping.mapping->encoding->first_col;
2844             info->lastCol = MIN(font->mapping.mapping->encoding->row_size-1, 
2845                                 lastCode<0x100?lastCode:0xFF);
2846             if( info->firstRow == 0 && info->firstCol == 0 ) zero_code=0;
2847         }
2848
2849         /* firstCode and lastCode are not valid in case of a matrix
2850            encoding */
2851
2852         if( dynStrTTCapCodeRange ) {
2853             restrict_code_range_by_str(0,&info->firstCol, &info->firstRow,
2854                                        &info->lastCol, &info->lastRow,
2855                                        dynStrTTCapCodeRange);
2856         }
2857         restrict_code_range(&info->firstCol, &info->firstRow,
2858                             &info->lastCol, &info->lastRow,
2859                             font->ranges, font->nranges);
2860     }
2861     font->info = info;
2862
2863     /* zero code is frequently used. */
2864     if ( zero_code < 0 ) {
2865         /* The fontenc should have the information of DefaultCh.
2866            But we do not have such a information.
2867            So we cannot but set 0. */
2868         font->zero_idx = 0;
2869     }
2870     else
2871         font->zero_idx = FTRemap(face->face, 
2872                                  &font->mapping, zero_code);
2873
2874     post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post);
2875
2876 #ifdef DEFAULT_VERY_LAZY
2877     if( !( tmp_ttcap->flags & TTCAP_DISABLE_DEFAULT_VERY_LAZY ) )
2878         if( DEFAULT_VERY_LAZY <= 1 + info->lastRow - info->firstRow ) {
2879             if( post ){
2880                 tmp_ttcap->flags |= TTCAP_IS_VERY_LAZY;
2881             }
2882         }
2883 #endif
2884     /* We should always reset. */
2885     tmp_ttcap->flags &= ~TTCAP_DISABLE_DEFAULT_VERY_LAZY;
2886
2887     if ( face->bitmap || actual_spacing == FT_CHARCELL )
2888         tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY;
2889     /* "vl=y" is available when TrueType or OpenType only */
2890     if ( !face->bitmap && !(FT_IS_SFNT( face->face )) )
2891         tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY;
2892
2893     if( post ) {
2894         if( post->italicAngle != 0 )
2895             tmp_ttcap->vl_slant = -sin( (post->italicAngle/1024./5760.)*1.57079632679489661923 );
2896         /* fprintf(stderr,"angle=%g(%g)\n",tmp_ttcap->vl_slant,(post->italicAngle/1024./5760.)*90); */
2897     }
2898
2899     xrc = FreeTypeOpenInstance(&font->instance, face,
2900                                FTFileName, &trans, actual_spacing, bmfmt,
2901                                tmp_ttcap, load_flags );
2902     return xrc;
2903 }
2904
2905 static void
2906 adjust_min_max(xCharInfo *minc, xCharInfo *maxc, xCharInfo *tmp)
2907 {
2908 #define MINMAX(field,ci) \
2909     if (minc->field > (ci)->field) \
2910     minc->field = (ci)->field; \
2911     if (maxc->field < (ci)->field) \
2912     maxc->field = (ci)->field;
2913
2914     MINMAX(ascent, tmp);
2915     MINMAX(descent, tmp);
2916     MINMAX(leftSideBearing, tmp);
2917     MINMAX(rightSideBearing, tmp);
2918     MINMAX(characterWidth, tmp);
2919
2920     if ((INT16)minc->attributes > (INT16)tmp->attributes)
2921         minc->attributes = tmp->attributes;
2922     if ((INT16)maxc->attributes < (INT16)tmp->attributes)
2923         maxc->attributes = tmp->attributes;
2924 #undef  MINMAX
2925 }
2926
2927 static void
2928 ft_compute_bounds(FTFontPtr font, FontInfoPtr pinfo, FontScalablePtr vals )
2929 {
2930     FTInstancePtr instance;
2931     int row, col;
2932     unsigned int c;
2933     xCharInfo minchar, maxchar, *tmpchar = NULL;
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_OUTSIDE;
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)*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)*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_SPACING;
2988           }
2989           else {        /* for GB18030 proportional */
2990               if ( c <= instance->ttcap.forceConstantSpacingEnd 
2991                    || instance->ttcap.forceConstantSpacingBegin <= c )
2992                   flags|=FT_FORCE_CONSTANT_SPACING;
2993           }
2994 #if 0
2995           fprintf(stderr, "comp_bounds: %x ->", c);
2996 #endif
2997           if ( skip_ok == 0 || flags == 0 ){
2998               tmpchar=NULL;
2999 #if 0
3000               fprintf(stderr, "%x\n", c);
3001 #endif
3002               if( FreeTypeFontGetGlyphMetrics(c, flags, &tmpchar, font) != Successful )
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);
3015           total_width += tmpchar->characterWidth;
3016           
3017           if ( flags & FT_FORCE_CONSTANT_SPACING ) 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) != Successful || tmpchar == NULL)
3024         if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, FT_GET_DUMMY, &tmpchar, font->instance) != Successful )
3025             tmpchar = NULL;
3026     if ( tmpchar ) {
3027         adjust_min_max(&minchar, &maxchar, tmpchar);
3028         overlap = tmpchar->rightSideBearing - tmpchar->characterWidth;
3029         if (maxOverlap < overlap)
3030             maxOverlap = overlap;
3031     }
3032 #endif
3033
3034     /* AVERAGE_WIDTH ... 1/10 pixel unit */
3035     if (num_chars > 0) {
3036         swidth = (swidth * 10.0 + num_chars / 2.0) / num_chars;
3037         if (total_width < 0)
3038             swidth = -swidth;
3039         vals->width = swidth;
3040     } else
3041         vals->width = 0;
3042
3043     /*
3044     if (char_width.pixel) {
3045         maxchar.characterWidth = char_width.pixel;
3046         minchar.characterWidth = char_width.pixel;
3047     }
3048     */
3049
3050     pinfo->maxbounds     = maxchar;
3051     pinfo->minbounds     = minchar;
3052     pinfo->ink_maxbounds = maxchar;
3053     pinfo->ink_minbounds = minchar;
3054     pinfo->maxOverlap    = maxOverlap;
3055 }
3056
3057 static int
3058 compute_new_extents( FontScalablePtr vals, double scale, double lsb, double rsb, double desc, double asc,
3059                      int *lsb_result, int *rsb_result, int *desc_result, int *asc_result )
3060 {
3061 #define TRANSFORM_POINT(matrix, x, y, dest) \
3062     ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \
3063      (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y))
3064
3065 #define CHECK_EXTENT(lsb, rsb, desc, asc, data) \
3066     ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \
3067      (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \
3068      (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \
3069      (asc) < (data)[1] ? (asc) = (data)[1] : 0)
3070     double newlsb, newrsb, newdesc, newasc;
3071     double point[2];
3072
3073     /* Compute new extents for this glyph */
3074     TRANSFORM_POINT(vals->pixel_matrix, lsb, -desc, point);
3075     newlsb  = point[0];
3076     newrsb  = newlsb;
3077     newdesc = -point[1];
3078     newasc  = -newdesc;
3079     TRANSFORM_POINT(vals->pixel_matrix, lsb, asc, point);
3080     CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
3081     TRANSFORM_POINT(vals->pixel_matrix, rsb, -desc, point);
3082     CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
3083     TRANSFORM_POINT(vals->pixel_matrix, rsb, asc, point);
3084     CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
3085
3086     /* ???: lsb = (int)floor(newlsb * scale); */
3087     *lsb_result   = (int)floor(newlsb * scale + 0.5);
3088     *rsb_result   = (int)floor(newrsb * scale + 0.5);
3089     *desc_result  = (int)ceil(newdesc * scale - 0.5);
3090     *asc_result   = (int)floor(newasc * scale + 0.5);
3091
3092     return 0;
3093 #undef CHECK_EXTENT
3094 #undef TRANSFORM_POINT
3095 }
3096
3097 static int
3098 is_matrix_unit(FontScalablePtr vals)
3099 {
3100     double base_size;
3101     FT_Matrix m;
3102
3103     base_size = hypot(vals->point_matrix[2], vals->point_matrix[3]);
3104
3105     m.xx = vals->point_matrix[0] / base_size * 65536;
3106     m.xy = vals->point_matrix[2] / base_size * 65536;
3107     m.yx = vals->point_matrix[1] / base_size * 65536;
3108     m.yy = vals->point_matrix[3] / base_size * 65536;
3109
3110     return (m.xx == 65536) && (m.yx == 0) && 
3111            (m.xy == 0) && (m.yy == 65536);
3112 }
3113
3114 /* Do all the real work for OpenFont or FontInfo */
3115 /* xf->info is only accessed through info, and xf might be null */
3116
3117 static int
3118 FreeTypeLoadXFont(char *fileName, 
3119                   FontScalablePtr vals, FontPtr xf, FontInfoPtr info,
3120                   FontBitmapFormatPtr bmfmt, FontEntryPtr entry)
3121 {
3122     FTFontPtr font = NULL;
3123     FTFacePtr face = NULL;
3124     FTInstancePtr instance;
3125     FT_Size_Metrics *smetrics;
3126     int xrc=Successful;
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_DEFAULT;      /* orig: FT_LOAD_RENDER | FT_LOAD_MONOCHROME */
3136     char *dynStrRealFileName   = NULL;  /* foo.ttc */
3137     char *dynStrFTFileName     = NULL;  /* :1:foo.ttc */
3138     char *dynStrTTCapCodeRange = NULL;
3139
3140     font = calloc(1, sizeof(FTFontRec));
3141     if(font == NULL) {
3142         xrc = AllocError;
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 != Successful ) {
3152         goto quit;
3153     }
3154
3155     xrc = FreeTypeOpenFace(&face, dynStrFTFileName, dynStrRealFileName, face_number);
3156     if(xrc != Successful) {
3157         goto quit;
3158     }
3159
3160     if( is_matrix_unit(vals) )
3161         orig_is_matrix_unit = True;
3162     else {
3163         orig_is_matrix_unit = False;
3164         /* Turn off EmbeddedBitmap when original matrix is not diagonal. */
3165         load_flags |= FT_LOAD_NO_BITMAP;
3166     }
3167
3168     if( face->bitmap ) load_flags &= ~FT_LOAD_NO_BITMAP;
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) < 1.0 ) {
3185         xrc = BadFontName;
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 != Successful) {
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_UPM;
3204     }
3205     scale = 1.0 / upm;
3206
3207     charcell = (instance->spacing == FT_CHARCELL);
3208
3209     if( instance->charcellMetrics == NULL ) {
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_WIDTH )
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_WIDTH )
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_FLAG )
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_FLAG )
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 ) {
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_STRIKE )
3340                 maxRsb += ins_ttcap->doubleStrikeShift;
3341             maxRsb += ins_ttcap->adjustRightSideBearingByPixel;
3342             minLsb += ins_ttcap->adjustLeftSideBearingByPixel;
3343             /* */
3344             if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
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_FLAG )
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_FLAG )
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_WIDTH )
3417                 width += ins_ttcap->doubleStrikeShift;
3418             if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
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_STRIKE )
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) {
3451             xrc = AllocError;
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) != Successful
3465             || tmpglyph == NULL)
3466             if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_GET_DUMMY, &tmpglyph, font->instance)
3467                 != Successful )
3468                 tmpglyph = NULL;
3469         if ( !tmpglyph ) {
3470             xrc = AllocError;
3471             goto quit;
3472         }
3473
3474         /* FORCE CONSTANT METRICS */
3475         if( 0 <= ins_ttcap->forceConstantSpacingEnd ) {
3476             xCharInfo *tmpchar = NULL;
3477             int c = ins_ttcap->force_c_representative_metrics_char_code;
3478             /* header's metrics */
3479             if( instance->forceConstantMetrics == NULL ){
3480                 instance->forceConstantMetrics = malloc(sizeof(xCharInfo));
3481                 if(instance->forceConstantMetrics == NULL) {
3482                     xrc = AllocError;
3483                     goto quit;
3484                 }
3485             }
3486             /* Get Representative Metrics */
3487             if ( 0 <= c ) {
3488                 if( FreeTypeFontGetGlyphMetrics(c, 0, &tmpchar, font) != Successful )
3489                     tmpchar = NULL;
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_SPACING, 
3509                                          &tmpglyph, font->instance) != Successful
3510                 || tmpglyph == NULL)
3511                 if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING | FT_GET_DUMMY,
3512                                              &tmpglyph, font->instance)
3513                     != Successful )
3514                     tmpglyph = NULL;
3515             if ( !tmpglyph ) {
3516                 xrc = AllocError;
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 != Successful) {
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 != Successful ) {
3624         if( font ){
3625             if( face && font->instance == NULL ) FreeTypeFreeFace(face);
3626             FreeTypeFreeFont(font);
3627         }
3628     }
3629     return xrc;
3630 }
3631
3632 /* Routines used by X11 to get info and glyphs from the font. */
3633
3634 static int
3635 FreeTypeGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars,
3636                    FontEncoding charEncoding, unsigned long *metricCount,
3637                    xCharInfo **metrics)
3638 {
3639     unsigned int code = 0;
3640     int flags = 0;
3641     FTFontPtr tf;
3642     struct TTCapInfo *ttcap;
3643     xCharInfo **mp, *m;
3644
3645     /*  MUMBLE("Get metrics for %ld characters\n", count);*/
3646
3647     tf = (FTFontPtr)pFont->fontPrivate;
3648     ttcap = &tf->instance->ttcap;
3649     mp = metrics;
3650
3651     while (count-- > 0) {
3652         switch (charEncoding) {
3653         case Linear8Bit: 
3654         case TwoD8Bit:
3655             code = *chars++;
3656             break;
3657         case Linear16Bit: 
3658         case TwoD16Bit:
3659             code = (*chars++ << 8);
3660             code |= *chars++;
3661             /* */
3662             if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) {
3663                 if ( (int)code <= ttcap->forceConstantSpacingEnd 
3664                      && ttcap->forceConstantSpacingBegin <= (int)code )
3665                     flags|=FT_FORCE_CONSTANT_SPACING;
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_SPACING;
3672                 else flags=0;
3673             }
3674             break;
3675         }
3676
3677         if(FreeTypeFontGetGlyphMetrics(code, flags, &m, tf) == Successful && m!=NULL) {
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 Successful;
3687 }
3688
3689 static int
3690 FreeTypeGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
3691                   FontEncoding charEncoding, unsigned long *glyphCount,
3692                   CharInfoPtr *glyphs)
3693 {
3694     unsigned int code = 0;
3695     int flags = 0;
3696     FTFontPtr tf;
3697     CharInfoPtr *gp;
3698     CharInfoPtr g;
3699     struct TTCapInfo *ttcap;
3700
3701     tf = (FTFontPtr)pFont->fontPrivate;
3702     ttcap = &tf->instance->ttcap;
3703     gp = glyphs;
3704
3705     while (count-- > 0) {
3706         switch (charEncoding) {
3707         case Linear8Bit: case TwoD8Bit:
3708             code = *chars++;
3709             break;
3710         case Linear16Bit: case TwoD16Bit:
3711             code = *chars++ << 8; 
3712             code |= *chars++;
3713             /* */
3714             if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) {
3715                 if ( (int)code <= ttcap->forceConstantSpacingEnd 
3716                      && ttcap->forceConstantSpacingBegin <= (int)code )
3717                     flags|=FT_FORCE_CONSTANT_SPACING;
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_SPACING;
3724                 else flags=0;
3725             }
3726             break;
3727         }
3728       
3729         if(FreeTypeFontGetGlyph(code, flags, &g, tf) == Successful && g!=NULL) {
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;
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 Successful;
3764 }
3765
3766 static int
3767 FreeTypeSetUpFont(FontPathElementPtr fpe, FontPtr xf, FontInfoPtr info, 
3768                   fsBitmapFormat format, fsBitmapFormatMask fmask,
3769                   FontBitmapFormatPtr bmfmt)
3770 {
3771     int xrc;
3772     int image;
3773
3774     /* Get the default bitmap format information for this X installation.
3775        Also update it for the client if running in the font server. */
3776     FontDefaultFormat(&bmfmt->bit, &bmfmt->byte, &bmfmt->glyph, &bmfmt->scan);
3777     if ((xrc = CheckFSFormat(format, fmask, &bmfmt->bit, &bmfmt->byte,
3778                              &bmfmt->scan, &bmfmt->glyph,
3779                              &image)) != Successful) {
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 = LeftToRight; /* 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 Successful;
3815 }
3816
3817 /* Functions exported by the backend */
3818
3819 static int
3820 FreeTypeOpenScalable(FontPathElementPtr fpe, FontPtr *ppFont, int flags,
3821                      FontEntryPtr entry, char *fileName, FontScalablePtr vals,
3822                      fsBitmapFormat format, fsBitmapFormatMask fmask,
3823                      FontPtr non_cachable_font)
3824 {
3825     int xrc;
3826     FontPtr xf;
3827     FontBitmapFormatRec bmfmt;
3828
3829     MUMBLE("Open Scalable %s, XLFD=%s\n",fileName, entry->name.length ? entry->name.name : "");
3830
3831     xf = CreateFontRec();
3832     if (xf == NULL)
3833         return AllocError;
3834
3835     xrc = FreeTypeSetUpFont(fpe, xf, &xf->info, format, fmask, &bmfmt);
3836     if(xrc != Successful) {
3837         DestroyFontRec(xf);
3838         return xrc;
3839     }
3840     xrc = FreeTypeLoadXFont(fileName, vals, xf, &xf->info, &bmfmt, entry);
3841     if(xrc != Successful) {
3842         MUMBLE("Error during load: %d\n",xrc);
3843         DestroyFontRec(xf);
3844         return xrc;
3845     }
3846
3847     *ppFont = xf;
3848
3849     return xrc;
3850 }
3851
3852 /* Routine to get requested font info. */
3853
3854 static int
3855 FreeTypeGetInfoScalable(FontPathElementPtr fpe, FontInfoPtr info,
3856                         FontEntryPtr entry, FontNamePtr fontName,
3857                         char *fileName, FontScalablePtr vals)
3858 {
3859     int xrc;
3860     FontBitmapFormatRec bmfmt;
3861
3862     MUMBLE("Get info, XLFD=%s\n", entry->name.length ? entry->name.name : "");
3863
3864     xrc = FreeTypeSetUpFont(fpe, 0, info, 0, 0, &bmfmt);
3865     if(xrc != Successful) {
3866         return xrc;
3867     }
3868
3869     bmfmt.glyph <<= 3;
3870
3871     xrc = FreeTypeLoadXFont(fileName, vals, 0, info, &bmfmt, entry);
3872     if(xrc != Successful) {
3873         MUMBLE("Error during load: %d\n", xrc);
3874         return xrc;
3875     }
3876
3877     return Successful;
3878 }
3879
3880 /* Renderer registration. */
3881
3882 /* Set the capabilities of this renderer. */
3883 #define CAPABILITIES (CAP_CHARSUBSETTING | CAP_MATRIX)
3884
3885 /* Set it up so file names with either upper or lower case can be
3886    loaded.  We don't support compressed fonts. */
3887 static FontRendererRec renderers[] = {
3888     {".ttf", 4, 0, FreeTypeOpenScalable, 0,
3889      FreeTypeGetInfoScalable, 0, CAPABILITIES},
3890     {".ttc", 4, 0, FreeTypeOpenScalable, 0,
3891      FreeTypeGetInfoScalable, 0, CAPABILITIES},
3892     {".otf", 4, 0, FreeTypeOpenScalable, 0,
3893      FreeTypeGetInfoScalable, 0, CAPABILITIES},
3894     {".otc", 4, 0, FreeTypeOpenScalable, 0,
3895      FreeTypeGetInfoScalable, 0, CAPABILITIES},
3896     {".pfa", 4, 0, FreeTypeOpenScalable, 0,
3897      FreeTypeGetInfoScalable, 0, CAPABILITIES},
3898     {".pfb", 4, 0, FreeTypeOpenScalable, 0,
3899      FreeTypeGetInfoScalable, 0, CAPABILITIES},
3900 };
3901 static int num_renderers = sizeof(renderers) / sizeof(renderers[0]);
3902
3903 static FontRendererRec alt_renderers[] = {
3904     {".bdf", 4, 0, FreeTypeOpenScalable, 0,
3905      FreeTypeGetInfoScalable, 0, CAPABILITIES},
3906     {".pcf", 4, 0, FreeTypeOpenScalable, 0,
3907      FreeTypeGetInfoScalable, 0, CAPABILITIES},
3908 };
3909
3910 static int num_alt_renderers =  
3911 sizeof(alt_renderers) / sizeof(alt_renderers[0]);
3912     
3913
3914 void
3915 FreeTypeRegisterFontFileFunctions(void)
3916 {
3917     int i;
3918
3919     for (i = 0; i < num_renderers; i++)
3920         FontFileRegisterRenderer(&renderers[i]);
3921
3922     for (i = 0; i < num_alt_renderers; i++)
3923         FontFilePriorityRegisterRenderer(&alt_renderers[i], -10);
3924 }