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.
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:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
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
32 #include <X11/fonts/fontmisc.h>
38 #include <X11/fonts/fntfilst.h>
39 #include <X11/fonts/fontutil.h>
40 #include <X11/fonts/FSproto.h>
42 #include FT_FREETYPE_H
44 #include FT_TRUETYPE_IDS_H
45 #include FT_TRUETYPE_TABLES_H
46 #include FT_TYPE1_TABLES_H
49 #include FT_TRUETYPE_TAGS_H
51 * If you want to use FT_Outline_Get_CBox instead of
52 * FT_Outline_Get_BBox, define here.
54 /* #define USE_GET_CBOX */
59 #include <X11/fonts/fontenc.h>
64 /* Work around FreeType bug */
65 #define WORK_AROUND_UPM 2048
74 #define FLOOR64(x) ((x) & -64)
75 #define CEIL64(x) (((x) + 64 - 1) & -64)
78 * If you want very lazy method(vl=y) AS DEFAULT when
79 * handling large charset, define here.
81 /* #define DEFAULT_VERY_LAZY 1 */ /* Always */
82 #define DEFAULT_VERY_LAZY 2 /* Multi-byte only */
83 /* #define DEFAULT_VERY_LAZY 256 */ /* Unicode only */
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 */
90 #ifdef X_ACCEPTS_NO_SUCH_CHAR
91 static CharInfoRec noSuchChar = { /* metrics */{0,0,0,0,0,0},
95 /* The propery names for all the XLFD properties. */
97 static const char *xlfd_props[] = {
115 /* read 2-byte value from a SFNT table */
117 sfnt_get_ushort( FT_Face face,
119 FT_ULong table_offset )
122 FT_ULong len = sizeof(buff);
123 FT_UShort result = 0;
125 if ( !FT_Load_Sfnt_Table( face, table_tag, table_offset, buff, &len ) )
126 result = (FT_UShort)( (buff[0] << 8) | buff[1] );
131 #define sfnt_get_short(f,t,o) ((FT_Short)sfnt_get_ushort((f),(t),(o)))
134 static int ftypeInitP = 0; /* is the engine initialised? */
135 FT_Library ftypeLibrary;
137 static FTFacePtr faceTable[NUMFACEBUCKETS];
144 for(i = 0; string[i] != '\0'; i++)
145 u = (u<<5) + (u >> (NUMFACEBUCKETS - 5)) + (unsigned char)string[i];
161 return ifloor(x + y - 1, y);
165 FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber)
169 FTFacePtr face, otherFace;
172 ftrc = FT_Init_FreeType(&ftypeLibrary);
174 ErrorF("FreeType: error initializing ftypeEngine: %d\n", ftrc);
180 /* Try to find a matching face in the hashtable */
181 bucket = hash(FTFileName)%NUMFACEBUCKETS;
182 otherFace = faceTable[bucket];
184 if( strcmp(otherFace->filename, FTFileName) == 0 ) break;
185 otherFace = otherFace->next;
188 MUMBLE("Returning cached face: %s\n", otherFace->filename);
193 /* No cached match; need to make a new one */
194 face = calloc(1, sizeof(FTFaceRec));
199 face->filename = strdup(FTFileName);
200 if (face->filename == NULL) {
205 ftrc = FT_New_Face(ftypeLibrary, realFileName, faceNumber, &face->face);
207 ErrorF("FreeType: couldn't open face %s: %d\n", FTFileName, ftrc);
208 free(face->filename);
213 face->bitmap = ((face->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
216 maxp = FT_Get_Sfnt_Table(face->face, ft_sfnt_maxp);
217 if(maxp && maxp->maxContours == 0)
221 face->num_hmetrics = (FT_UInt) sfnt_get_ushort( face->face,
224 /* Insert face in hashtable and return it */
225 face->next = faceTable[bucket];
226 faceTable[bucket] = face;
232 FreeTypeFreeFace(FTFacePtr face)
237 if(!face->instances) {
238 bucket = hash(face->filename) % NUMFACEBUCKETS;
239 if(faceTable[bucket] == face)
240 faceTable[bucket] = face->next;
242 otherFace = faceTable[bucket];
244 if(otherFace->next == face)
246 otherFace = otherFace->next;
248 if(otherFace && otherFace->next)
249 otherFace->next = otherFace->next->next;
251 ErrorF("FreeType: freeing unknown face\n");
253 MUMBLE("Closing face: %s\n", face->filename);
254 FT_Done_Face(face->face);
255 free(face->filename);
261 TransEqual(FTNormalisedTransformationPtr t1, FTNormalisedTransformationPtr t2)
263 if(t1->scale != t2->scale)
265 else if(t1->xres != t2->xres || t1->yres != t2->yres)
267 else if(t1->nonIdentity != t2->nonIdentity)
269 else if(t1->nonIdentity && t2->nonIdentity) {
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;
280 BitmapFormatEqual(FontBitmapFormatPtr f1, FontBitmapFormatPtr f2)
283 f1->bit == f2->bit &&
284 f1->byte == f2->byte &&
285 f1->glyph == f2->glyph;
289 TTCapEqual(struct TTCapInfo *t1, struct TTCapInfo *t2)
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 &&
303 If we use forceConstantSpacing,
304 we *MUST* allocate new instance.
306 t1->forceConstantSpacingEnd < 0 &&
307 t2->forceConstantSpacingEnd < 0;
311 FTInstanceMatch(FTInstancePtr instance,
312 char *FTFileName, FTNormalisedTransformationPtr trans,
313 int spacing, FontBitmapFormatPtr bmfmt,
314 struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags)
316 if(strcmp(instance->face->filename, FTFileName) != 0) {
318 } else if(!TransEqual(&instance->transformation, trans)) {
320 } else if( spacing != instance->spacing ) {
322 } else if( load_flags != instance->load_flags ) {
324 } else if(!BitmapFormatEqual(&instance->bmfmt, bmfmt)) {
326 } else if(!TTCapEqual(&instance->ttcap, tmp_ttcap)) {
334 FreeTypeActivateInstance(FTInstancePtr instance)
337 if(instance->face->active_instance == instance)
340 ftrc = FT_Activate_Size(instance->size);
342 instance->face->active_instance = NULL;
343 ErrorF("FreeType: couldn't activate instance: %d\n", ftrc);
344 return FTtoXReturnCode(ftrc);
346 FT_Set_Transform(instance->face->face,
347 instance->transformation.nonIdentity ?
348 &instance->transformation.matrix : 0,
351 instance->face->active_instance = instance;
356 FTFindSize(FT_Face face, FTNormalisedTransformationPtr trans,
357 int *x_return, int *y_return)
363 if(trans->nonIdentity)
366 tx = (int)(trans->scale * trans->xres / 72.0 + 0.5);
367 ty = (int)(trans->scale * trans->yres / 72.0 + 0.5);
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);
385 *x_return = face->available_sizes[j].width;
386 *y_return = face->available_sizes[j].height;
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)
398 FTInstancePtr instance, otherInstance;
400 /* Search for a matching instance */
401 for(otherInstance = face->instances;
403 otherInstance = otherInstance->next) {
404 if(FTInstanceMatch(otherInstance, FTFileName, trans, spacing, bmfmt,
405 tmp_ttcap, load_flags)) break;
408 MUMBLE("Returning cached instance\n");
409 otherInstance->refcount++;
410 *instance_return = otherInstance;
414 /* None matching found */
415 instance = malloc(sizeof(FTInstanceRec));
416 if(instance == NULL) {
420 instance->refcount = 1;
421 instance->face = face;
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;
433 instance->transformation = *trans;
434 instance->bmfmt = *bmfmt;
435 instance->glyphs = NULL;
436 instance->available = NULL;
438 if( 0 <= tmp_ttcap->forceConstantSpacingEnd )
439 instance->nglyphs = 2 * instance->face->face->num_glyphs;
441 instance->nglyphs = instance->face->face->num_glyphs;
443 /* Store the TTCap info. */
444 memcpy((char*)&instance->ttcap, (char*)tmp_ttcap,
445 sizeof(struct TTCapInfo));
447 ftrc = FT_New_Size(instance->face->face, &instance->size);
449 ErrorF("FreeType: couldn't create size object: %d\n", ftrc);
451 return FTtoXReturnCode(ftrc);
453 FreeTypeActivateInstance(instance);
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);
461 xrc = FTFindSize(face->face, trans, &xsize, &ysize);
462 if(xrc != Successful) {
466 ftrc = FT_Set_Pixel_Sizes(instance->face->face, xsize, ysize);
469 FT_Done_Size(instance->size);
471 return FTtoXReturnCode(ftrc);
474 if( FT_IS_SFNT( face->face ) ) {
476 FT_F26Dot6 tt_char_width, tt_char_height, tt_dim_x, tt_dim_y;
479 instance->strike_index=0xFFFFU;
481 tt_char_width = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5);
482 tt_char_height = (FT_F26Dot6)(trans->scale*(1<<6) + 0.5);
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 );
487 if ( tt_dim_x && !tt_dim_y )
489 else if ( !tt_dim_x && tt_dim_y )
492 for ( nn = 0; nn < face->face->num_fixed_sizes; nn++ )
494 FT_Bitmap_Size* sz = &face->face->available_sizes[nn];
496 if ( tt_dim_x == FLOOR64(sz->x_ppem + 32) && tt_dim_y == FLOOR64(sz->y_ppem + 32) )
498 instance->strike_index = nn;
503 /* See Set_Char_Sizes() in ttdriver.c */
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;
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;
518 tt_dim_x = ( ( tt_char_width * trans->xres + 36 ) / 72 );
519 tt_dim_y = ( ( tt_char_height * trans->yres + 36 ) / 72 );
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;
530 /* maintain a linked list of instances */
531 instance->next = instance->face->instances;
532 instance->face->instances = instance;
534 *instance_return = instance;
539 FreeTypeFreeInstance(FTInstancePtr instance)
541 FTInstancePtr otherInstance;
543 if( instance == NULL ) return;
545 if(instance->face->active_instance == instance)
546 instance->face->active_instance = NULL;
547 instance->refcount--;
548 if(instance->refcount <= 0) {
551 if(instance->face->instances == instance)
552 instance->face->instances = instance->next;
554 for(otherInstance = instance->face->instances;
556 otherInstance = otherInstance->next)
557 if(otherInstance->next == instance) {
558 otherInstance->next = instance->next;
563 FT_Done_Size(instance->size);
564 FreeTypeFreeFace(instance->face);
566 if(instance->charcellMetrics) {
567 free(instance->charcellMetrics);
569 if(instance->forceConstantMetrics) {
570 free(instance->forceConstantMetrics);
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);
580 free(instance->glyphs[i]);
583 free(instance->glyphs);
585 if(instance->available) {
586 for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE); i++) {
587 if(instance->available[i])
588 free(instance->available[i]);
590 free(instance->available);
597 FreeTypeInstanceFindGlyph(unsigned idx_in, int flags, FTInstancePtr instance,
598 CharInfoPtr **glyphs, int ***available,
599 int *found, int *segmentP, int *offsetP)
602 unsigned idx = idx_in;
604 if( 0 <= instance->ttcap.forceConstantSpacingEnd ){
605 if( (flags & FT_FORCE_CONSTANT_SPACING) )
606 idx += instance->nglyphs / 2 ;
609 if(idx > instance->nglyphs) {
614 if(*available == NULL) {
615 *available = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE),
617 if(*available == NULL)
621 segment = ifloor(idx, FONTSEGMENTSIZE);
622 offset = idx - segment * FONTSEGMENTSIZE;
624 if((*available)[segment] == NULL) {
625 (*available)[segment] = calloc(FONTSEGMENTSIZE, sizeof(int *));
626 if((*available)[segment] == NULL)
630 if(*glyphs == NULL) {
631 *glyphs = calloc(iceil(instance->nglyphs, FONTSEGMENTSIZE),
632 sizeof(CharInfoPtr));
637 if((*glyphs)[segment] == NULL) {
638 (*glyphs)[segment] = malloc(sizeof(CharInfoRec) * FONTSEGMENTSIZE);
639 if((*glyphs)[segment] == NULL)
650 FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance)
652 int found, segment, offset;
655 CharInfoPtr **glyphs;
657 available = &instance->available;
658 glyphs = &instance->glyphs;
660 xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, glyphs, available,
661 &found, &segment, &offset);
662 if(xrc != Successful)
665 if(!found || (*available)[segment][offset] == FT_AVAILABLE_NO) {
670 if((*available)[segment][offset] == FT_AVAILABLE_RASTERISED) {
671 *g = &(*glyphs)[segment][offset];
675 flags |= FT_GET_GLYPH_BOTH;
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);
687 if(xrc == Successful) {
688 (*available)[segment][offset] = FT_AVAILABLE_RASTERISED;
689 /* return the glyph */
690 *g = &(*glyphs)[segment][offset];
696 FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags,
697 xCharInfo **metrics, FTInstancePtr instance )
700 int found, segment, offset;
703 if(instance->spacing == FT_CHARCELL) {
704 *metrics = instance->charcellMetrics;
707 /* Force constant metrics */
708 if( flags & FT_FORCE_CONSTANT_SPACING) {
709 *metrics = instance->forceConstantMetrics;
715 xrc = FreeTypeInstanceFindGlyph(idx, flags, instance,
716 &instance->glyphs, &instance->available,
717 &found, &segment, &offset);
718 if(xrc != Successful)
724 if( instance->available[segment][offset] == FT_AVAILABLE_NO ) {
729 if( instance->available[segment][offset] >= FT_AVAILABLE_METRICS ) {
730 *metrics = &instance->glyphs[segment][offset].metrics;
734 flags |= FT_GET_GLYPH_METRICS_ONLY;
736 xrc = FreeTypeRasteriseGlyph(idx, flags,
737 &instance->glyphs[segment][offset],
739 if(xrc == Successful) {
740 instance->available[segment][offset] = FT_AVAILABLE_METRICS;
741 *metrics = &instance->glyphs[segment][offset].metrics;
747 * Pseudo enbolding similar as Microsoft Windows.
748 * It is useful but poor.
751 ft_make_up_bold_bitmap( char *raster, int bpr, int ht, int ds_mode)
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;
764 *p &= ~(rev_pat & (*p << 1));
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;
784 ft_make_up_italic_bitmap( char *raster, int bpr, int ht, int shift,
785 int h_total, int h_offset, double a_italic)
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;
794 if ( 0 <= tmp_shift ) {
795 tmp_byte_shift = tmp_shift/8;
798 for (x=bpr-1;0<=x;x--) {
800 tmp_p[x+1] |= tmp_p[x]<<(8-tmp_shift);
801 tmp_p[x]>>=tmp_shift;
804 if ( tmp_byte_shift ) {
805 for (x=bpr-1;0<x;x--) {
806 tmp_p[x] = tmp_p[x-1];
812 tmp_shift = -tmp_shift;
813 tmp_byte_shift = tmp_shift/8;
816 for (x=0;x<bpr;x++) {
818 tmp_p[x-1] |= tmp_p[x]>>(8-tmp_shift);
819 tmp_p[x]<<=tmp_shift;
822 if ( tmp_byte_shift ) {
823 for (x=0;x<bpr-1;x++) {
824 tmp_p[x] = tmp_p[x+1];
833 * The very lazy method,
834 * parse the htmx field in TrueType font.
838 tt_get_metrics( FT_Face face,
840 FT_UInt num_hmetrics,
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
849 FT_UInt count = num_hmetrics;
854 error = FT_Load_Sfnt_Table( face, TTAG_hmtx, 0, NULL, &length );
856 if ( count == 0 || error )
861 else if ( idx < count )
864 if ( offset + 4 > length )
871 *advance = sfnt_get_ushort( face, TTAG_hmtx, offset );
872 *bearing = sfnt_get_short ( face, TTAG_hmtx, offset+2 );
877 offset = 4L * (count - 1);
878 if ( offset + 4 > length )
885 *advance = sfnt_get_ushort ( face, TTAG_hmtx, offset );
886 offset += 4 + 2 * ( idx - count );
887 if ( offset + 2 > length)
890 *bearing = sfnt_get_short ( face, TTAG_hmtx, offset );
896 ft_get_very_lazy_bbox( FT_UInt index,
899 FT_UInt num_hmetrics,
903 FT_Long *horiAdvance,
904 FT_Long *vertAdvance)
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;
913 tt_get_metrics( face, index, num_hmetrics,
914 &leftBearing, &advance );
917 fprintf(stderr,"x_scale=%f y_scale=%f\n",
918 (double)smetrics->x_scale,(double)smetrics->y_scale);
920 bbox->xMax = *horiAdvance =
921 FT_MulFix( advance, smetrics->x_scale );
923 FT_MulFix( leftBearing, smetrics->x_scale );
925 bbox->yMin = FT_MulFix( face->bbox.yMin,
927 bbox->yMax = FT_MulFix( face->bbox.yMax,
931 bbox->xMax += slant * bbox->yMax;
932 bbox->xMin += slant * bbox->yMin;
934 else if( slant < 0 ) {
935 bbox->xMax += slant * bbox->yMin;
936 bbox->xMin += slant * bbox->yMax;
939 *vertAdvance = -1; /* We don't support */
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;
946 FT_Vector_Transform(&p0, matrix);
947 FT_Vector_Transform(&p1, matrix);
948 FT_Vector_Transform(&p2, matrix);
949 FT_Vector_Transform(&p3, matrix);
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);
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 */
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 )
975 if ( strike_index != 0xFFFFU && ft_face->available_sizes != NULL )
978 FT_Bitmap_Size* sz = &ft_face->available_sizes[strike_index];
980 error = FT_Set_Pixel_Sizes( ft_face, sz->x_ppem/64, sz->y_ppem/64 );
983 error = FT_Load_Glyph( ft_face, glyph_index, FT_LOAD_SBITS_ONLY );
986 if ( metrics_return != NULL )
987 *metrics_return = ft_face->glyph->metrics;
994 #elif (FREETYPE_VERSION >= 2001008)
999 TT_SBit_Strike strike;
1000 TT_SBit_Range range;
1001 TT_SBit_MetricsRec elem_metrics;
1003 FT_ULong glyph_offset;
1006 if ( ! FT_IS_SFNT( ft_face ) )
1012 face = (TT_Face)ft_face;
1013 sfnt = (SFNT_Service)face->sfnt;
1015 if (strike_index != 0xFFFFU && sfnt && sfnt->find_sbit_image &&
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 );
1022 if ( error ) goto Exit;
1024 if ( metrics_return == NULL ) goto Exit;
1026 stream = face->root.stream;
1028 /* now, find the location of the `EBDT' table in */
1030 error = face->goto_table( face, TTAG_EBDT, stream, 0 );
1032 error = face->goto_table( face, TTAG_bdat, stream, 0 );
1036 ebdt_pos = FT_STREAM_POS();
1038 /* place stream at beginning of glyph data and read metrics */
1039 if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )
1042 error = sfnt->load_sbit_metrics( stream, range, &elem_metrics );
1046 metrics_return->width = (FT_Pos)elem_metrics.width << 6;
1047 metrics_return->height = (FT_Pos)elem_metrics.height << 6;
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;
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;
1059 #else /* if (FREETYPE_VERSION < 2001008) */
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;
1073 FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp,
1074 FTInstancePtr instance, int hasMetrics)
1078 FT_Long outline_hori_advance, outline_vert_advance;
1079 FT_Glyph_Metrics sbit_metrics;
1080 FT_Glyph_Metrics *bitmap_metrics=NULL, *metrics = NULL;
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;
1086 int leftSideBearing, rightSideBearing, characterWidth, rawCharacterWidth,
1088 int sbitchk_incomplete_but_exist;
1089 double bbox_center_raw;
1091 face = instance->face;
1093 FreeTypeActivateInstance(instance);
1095 if(!tgp) return AllocError;
1102 if( instance->spacing == FT_CHARCELL || flags & FT_GET_DUMMY ){
1103 memcpy((char*)&tgp->metrics,
1104 (char*)instance->charcellMetrics,
1107 else if( flags & FT_FORCE_CONSTANT_SPACING ) {
1108 memcpy((char*)&tgp->metrics,
1109 (char*)instance->forceConstantMetrics,
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;
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,
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 */
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;
1144 if( bitmap_metrics ) {
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 ;
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;
1169 factor = bitmap_metrics->horiAdvance;
1170 rawCharacterWidth = (unsigned short)(short)(floor(1000 * factor
1171 * instance->ttcap.scaleBBoxWidth * ratio / 64.
1172 / instance->pixel_size));
1178 FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
1179 ftrc=0; /* FT_Outline_Get_CBox returns nothing. */
1181 /* Calculate exact metrics */
1182 ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
1184 if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
1185 outline_hori_advance = metrics->horiAdvance;
1186 outline_vert_advance = metrics->vertAdvance;
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 )
1195 (int)floor( outline_hori_advance
1196 * instance->ttcap.scaleBBoxWidth
1197 * instance->pixel_width_unit_x / 64. + .5);
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;
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 )
1215 (unsigned short)(short)(floor(1000 * outline_hori_advance
1216 * instance->ttcap.scaleBBoxWidth * ratio
1217 * instance->pixel_width_unit_x / 64.));
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;
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;
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;
1251 if( flags & FT_GET_GLYPH_METRICS_ONLY ) return Successful;
1254 * CHECK THE NECESSITY OF BITMAP POSITION'S CORRECTION
1258 if( instance->spacing == FT_CHARCELL ) correct=1;
1259 else if( flags & FT_FORCE_CONSTANT_SPACING ) correct=1;
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 ) {
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;
1278 * RENDER AND ALLOCATE BUFFER
1281 if( flags & FT_GET_DUMMY ) is_outline = -1;
1284 ftrc = FT_Load_Glyph(instance->face->face, idx,
1285 instance->load_flags);
1286 metrics = &face->face->glyph->metrics;
1288 if(ftrc != 0) return FTtoXReturnCode(ftrc);
1291 if( face->face->glyph->format != FT_GLYPH_FORMAT_BITMAP ) {
1293 FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
1296 ftrc = FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
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 )
1308 ftrc = FT_Render_Glyph(face->face->glyph,FT_RENDER_MODE_MONO);
1309 if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
1319 if( (instance->ttcap.flags & TTCAP_MONO_CENTER) && hasMetrics ) {
1320 if( is_outline == 1 ){
1322 if( ft_get_very_lazy_bbox( idx, face->face, instance->size,
1324 instance->ttcap.vl_slant,
1325 &instance->transformation.matrix,
1326 &bbox, &outline_hori_advance,
1327 &outline_vert_advance ) != 0 ){
1328 is_outline = -1; /* <- error */
1333 FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
1336 ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
1338 if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
1340 bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.;
1342 else if( is_outline == 0 )
1343 bbox_center_raw = (2.0 * metrics->horiBearingX + metrics->width)/2.0/64.0;
1345 bbox_center_raw = 0;
1346 b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5);
1349 wd_actual = tgp->metrics.rightSideBearing - tgp->metrics.leftSideBearing;
1350 ht_actual = tgp->metrics.ascent + tgp->metrics.descent;
1352 /* The X convention is to consider a character with an empty
1353 * bounding box as undefined. This convention is broken. */
1355 if(wd_actual <= 0) wd = 1;
1357 if(ht_actual <= 0) ht = 1;
1360 bpr = (((wd + (instance->bmfmt.glyph<<3) - 1) >> 3) &
1361 -instance->bmfmt.glyph);
1362 raster = calloc(1, ht * bpr);
1368 /* If FT_GET_DUMMY is set, we return white space. */
1369 if ( is_outline == -1 ) return Successful;
1371 if ( wd_actual <= 0 || ht_actual <= 0 ) return Successful;
1374 * CALCULATE OFFSET, dx AND dy.
1377 dx = face->face->glyph->bitmap_left - tgp->metrics.leftSideBearing;
1378 dy = tgp->metrics.ascent - face->face->glyph->bitmap_top;
1380 if(instance->ttcap.flags & TTCAP_MONO_CENTER)
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;
1388 FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
1391 ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
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;
1403 if(instance->ttcap.flags & TTCAP_MONO_CENTER){
1404 leftSideBearing -= b_shift;
1405 rightSideBearing -= b_shift;
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 ){
1417 if( instance->ttcap.adjustRightSideBearingByPixel != 0 ||
1418 instance->ttcap.adjustLeftSideBearingByPixel != 0 ){
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--;
1438 unsigned char *current_raster;
1439 unsigned char *current_buffer;
1440 int mod_dx0,mod_dx1;
1442 bitmap = &face->face->glyph->bitmap;
1446 mod_dx1 = 8-mod_dx0;
1451 mod_dx0 = 8-mod_dx1;
1453 for( i = MAX(0, dy) ; i<ht ; i++ ){
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);
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;
1478 if ( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) {
1480 for( i=0 ; i < instance->ttcap.doubleStrikeShift ; i++ )
1481 ft_make_up_bold_bitmap( raster, bpr, ht, instance->ttcap.flags);
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);
1496 if(instance->bmfmt.bit == LSBFirst) {
1497 BitOrderInvert((unsigned char*)(tgp->bits), ht*bpr);
1500 if(instance->bmfmt.byte != instance->bmfmt.bit) {
1501 switch(instance->bmfmt.scan) {
1505 TwoByteSwap((unsigned char*)(tgp->bits), ht*bpr);
1508 FourByteSwap((unsigned char*)(tgp->bits), ht*bpr);
1519 FreeTypeFreeFont(FTFontPtr font)
1521 FreeTypeFreeInstance(font->instance);
1524 if(font->dummy_char.bits)
1525 free(font->dummy_char.bits);
1529 /* Free a font. If freeProps is 0, don't free the properties. */
1532 FreeTypeFreeXFont(FontPtr pFont, int freeProps)
1537 if((tf = (FTFontPtr)pFont->fontPrivate)) {
1538 FreeTypeFreeFont(tf);
1540 if(freeProps && pFont->info.nprops>0) {
1541 free(pFont->info.isStringProp);
1542 free(pFont->info.props);
1544 DestroyFontRec(pFont);
1552 FreeTypeUnloadXFont(FontPtr pFont)
1554 MUMBLE("Unloading\n");
1555 FreeTypeFreeXFont(pFont, 1);
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
1565 FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
1566 char *fontname, int rawAverageWidth, Bool font_properties)
1569 char *sp, *ep, val[MAXFONTNAMELEN], *vp;
1571 FTInstancePtr instance;
1572 FTNormalisedTransformationPtr trans;
1575 TT_Postscript *post;
1576 PS_FontInfoRec t1info_rec, *t1info;
1580 instance = font->instance;
1581 face = instance->face;
1582 trans = &instance->transformation;
1583 upm = face->face->units_per_EM;
1585 /* Work around FreeType bug */
1586 upm = WORK_AROUND_UPM;
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);
1593 t1info = &t1info_rec;
1602 info->nprops = 0; /* in case we abort */
1604 strcpy(val, fontname);
1605 if(FontParseXLFDName(val, vals, FONT_XLFD_REPLACE_VALUE)) {
1608 MUMBLE("Couldn't parse XLFD\n");
1614 (xlfdProps ? 14 : 0) + /* from XLFD */
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 ) +
1622 info->props = malloc(maxprops * sizeof(FontPropRec));
1623 if(info->props == NULL)
1626 info->isStringProp = malloc(maxprops);
1627 if(info->isStringProp == NULL) {
1632 memset((char *)info->isStringProp, 0, maxprops);
1636 info->props[i].name = MakeAtom("FONT", 4, TRUE);
1637 info->props[i].value = MakeAtom(val, strlen(val), TRUE);
1638 info->isStringProp[i] = 1;
1641 if(*val && *(sp = val + 1)) {
1642 for (j = 0, sp = val + 1; j < 14; j++) {
1644 /* Handle the case of the final field containing a subset
1646 for (ep = sp; *ep && *ep != '['; ep++);
1648 for (ep = sp; *ep && *ep != '-'; ep++);
1650 info->props[i].name =
1651 MakeAtom(xlfd_props[j], strlen(xlfd_props[j]), TRUE);
1654 case 6: /* pixel size */
1655 info->props[i].value =
1656 (int)(fabs(vals->pixel_matrix[3]) + 0.5);
1659 case 7: /* point size */
1660 info->props[i].value =
1661 (int)(fabs(vals->point_matrix[3])*10.0 + 0.5);
1664 case 8: /* resolution x */
1665 info->props[i].value = vals->x;
1668 case 9: /* resolution y */
1669 info->props[i].value = vals->y;
1672 case 11: /* average width */
1673 info->props[i].value = vals->width;
1676 default: /* a string */
1677 info->props[i].value = MakeAtom(sp, ep - sp, TRUE);
1678 info->isStringProp[i] = 1;
1685 info->props[i].name = MakeAtom("RAW_PIXEL_SIZE", 14, TRUE);
1686 info->props[i].value = 1000;
1689 info->props[i].name = MakeAtom("RAW_POINT_SIZE", 14, TRUE);
1690 info->props[i].value = (long)(72270.0 / (double)vals->y + .5);
1694 info->props[i].name = MakeAtom("RAW_AVERAGE_WIDTH", 17, TRUE);
1695 info->props[i].value = rawAverageWidth;
1699 if ( font_properties ) {
1700 info->props[i].name = MakeAtom("FONT_ASCENT", 11, TRUE);
1701 info->props[i].value = info->fontAscent;
1706 info->props[i].name = MakeAtom("RAW_ASCENT", 10, TRUE);
1707 info->props[i].value =
1708 ((double)face->face->ascender/(double)upm*1000.0);
1712 if ( font_properties ) {
1713 info->props[i].name = MakeAtom("FONT_DESCENT", 12, TRUE);
1714 info->props[i].value = info->fontDescent;
1719 info->props[i].name = MakeAtom("RAW_DESCENT", 11, TRUE);
1720 info->props[i].value =
1721 -((double)face->face->descender/(double)upm*1000.0);
1725 j = FTGetEnglishName(face->face, TT_NAME_ID_COPYRIGHT,
1726 val, MAXFONTNAMELEN);
1729 if(t1info && t1info->notice) {
1730 vp = t1info->notice;
1735 info->props[i].name = MakeAtom("COPYRIGHT", 9, TRUE);
1736 info->props[i].value = MakeAtom(vp, j, TRUE);
1737 info->isStringProp[i] = 1;
1741 j = FTGetEnglishName(face->face, TT_NAME_ID_FULL_NAME,
1742 val, MAXFONTNAMELEN);
1745 if(t1info && t1info->full_name) {
1746 vp = t1info->full_name;
1751 info->props[i].name = MakeAtom("FACE_NAME", 9, TRUE);
1752 info->props[i].value = MakeAtom(vp, j, TRUE);
1753 info->isStringProp[i] = 1;
1757 vp = (char *)FT_Get_Postscript_Name(face->face);
1764 j = FTGetEnglishName(face->face, TT_NAME_ID_PS_NAME,
1765 val, MAXFONTNAMELEN);
1769 if(t1info && t1info->full_name) {
1770 vp = t1info->full_name;
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;
1781 /* These macros handle the case of a diagonal matrix. They convert
1782 FUnits into pixels. */
1783 #define TRANSFORM_FUNITS_X(xval) \
1785 floor( ((double)(xval)/(double)upm) * (double)vals->pixel_matrix[0] + 0.5 ) )
1787 #define TRANSFORM_FUNITS_Y(yval) \
1789 floor( ((double)(yval)/(double)upm) * (double)vals->pixel_matrix[3] + 0.5 ) )
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. */
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);
1799 info->props[i].name = MakeAtom("SUBSCRIPT_X",11,TRUE);
1800 info->props[i].value =
1801 TRANSFORM_FUNITS_X(os2->ySubscriptXOffset);
1803 info->props[i].name = MakeAtom("SUBSCRIPT_Y",11,TRUE);
1804 info->props[i].value =
1805 TRANSFORM_FUNITS_Y(os2->ySubscriptYOffset);
1807 info->props[i].name = MakeAtom("SUPERSCRIPT_SIZE",16,TRUE);
1808 info->props[i].value =
1809 TRANSFORM_FUNITS_Y(os2->ySuperscriptYSize);
1811 info->props[i].name = MakeAtom("SUPERSCRIPT_X",13,TRUE);
1812 info->props[i].value =
1813 TRANSFORM_FUNITS_X(os2->ySuperscriptXOffset);
1815 info->props[i].name = MakeAtom("SUPERSCRIPT_Y",13,TRUE);
1816 info->props[i].value =
1817 TRANSFORM_FUNITS_Y(os2->ySuperscriptYOffset);
1821 if( font_properties && (post || t1info) ) {
1822 int underlinePosition, underlineThickness;
1824 /* Raw underlineposition counts upwards,
1825 but UNDERLINE_POSITION counts downwards. */
1827 underlinePosition = TRANSFORM_FUNITS_Y(-post->underlinePosition);
1828 underlineThickness = TRANSFORM_FUNITS_Y(post->underlineThickness);
1831 TRANSFORM_FUNITS_Y(-t1info->underline_position);
1832 underlineThickness =
1833 TRANSFORM_FUNITS_Y(t1info->underline_thickness);
1835 if(underlineThickness <= 0)
1836 underlineThickness = 1;
1838 info->props[i].name = MakeAtom("UNDERLINE_THICKNESS",19,TRUE);
1839 info->props[i].value = underlineThickness;
1842 info->props[i].name = MakeAtom("UNDERLINE_POSITION",18,TRUE);
1844 info->props[i].value = underlinePosition;
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);
1857 #undef TRANSFORM_FUNITS_X
1858 #undef TRANSFORM_FUNITS_Y
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;
1867 info->props[i].name = MakeAtom("RASTERIZER_NAME", 15, TRUE);
1868 info->props[i].value = MakeAtom("FreeType", 10, TRUE);
1869 info->isStringProp[i] = 1;
1877 ft_get_index(unsigned code, FTFontPtr font, unsigned *idx)
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
1884 /* This is not required...
1885 if(code > 0 && font->nranges) {
1887 for(i = 0; i < font->nranges; i++)
1889 font->ranges[i].min_char_low+
1890 (font->ranges[i].min_char_high<<8)) &&
1892 font->ranges[i].max_char_low +
1893 (font->ranges[i].max_char_high<<8)))
1895 if(i == font->nranges) {
1896 *idx = font->zero_idx;
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. */
1913 *idx = FTRemap(font->instance->face->face, &font->mapping, code);
1919 FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font)
1924 #ifdef X_ACCEPTS_NO_SUCH_CHAR
1925 if( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) {
1927 flags &= ~FT_FORCE_CONSTANT_SPACING;
1928 /* if( font->instance->spacing != FT_CHARCELL ) */
1932 if( ft_get_index(code,font,&idx) ) {
1933 /* The code has not been parsed! */
1935 flags &= ~FT_FORCE_CONSTANT_SPACING;
1939 xrc = FreeTypeInstanceGetGlyph(idx, flags, g, font->instance);
1940 if( xrc == Successful && *g != NULL )
1942 if( font->zero_idx != idx ) {
1943 xrc = FreeTypeInstanceGetGlyph(font->zero_idx, flags, g, font->instance);
1944 if( xrc == Successful && *g != NULL )
1947 return FreeTypeInstanceGetGlyph(font->zero_idx, flags|FT_GET_DUMMY, g, font->instance);
1951 FreeTypeFontGetGlyphMetrics(unsigned code, int flags, xCharInfo **metrics, FTFontPtr font)
1956 #ifdef X_ACCEPTS_NO_SUCH_CHAR
1957 if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) {
1959 flags &= ~FT_FORCE_CONSTANT_SPACING;
1960 /* if( font->instance->spacing != FT_CHARCELL ) */
1964 if ( ft_get_index(code,font,&idx) || idx == 0 || idx == font->zero_idx ) {
1965 /* The code has not been parsed! */
1967 flags &= ~FT_FORCE_CONSTANT_SPACING;
1971 xrc = FreeTypeInstanceGetGlyphMetrics(idx, flags, metrics, font->instance);
1972 if( xrc == Successful && *metrics != NULL )
1974 if( font->zero_idx != idx ) {
1975 xrc = FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags,
1976 metrics, font->instance);
1977 if( xrc == Successful && *metrics != NULL )
1980 return FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags|FT_GET_DUMMY, metrics, font->instance);
1984 * restrict code range
1986 * boolean for the numeric zone:
1987 * results = results & (ranges[0] | ranges[1] | ... ranges[nranges-1])
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)
1998 int minCol = 256, minRow = 256, maxCol = -1, maxRow = -1;
1999 fsRange const *r = ranges;
2002 for (i=0; i<nRanges; i++) {
2003 if (r->min_char_high != r->max_char_high) {
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;
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;
2019 if (minCol > *refLastCol)
2020 *refFirstCol = *refLastCol;
2021 else if (minCol > *refFirstCol)
2022 *refFirstCol = minCol;
2024 if (maxCol < *refFirstCol)
2025 *refLastCol = *refFirstCol;
2026 else if (maxCol < *refLastCol)
2027 *refLastCol = maxCol;
2029 if (minRow > *refLastRow) {
2030 *refFirstRow = *refLastRow;
2031 *refFirstCol = *refLastCol;
2032 } else if (minRow > *refFirstRow)
2033 *refFirstRow = minRow;
2035 if (maxRow < *refFirstRow) {
2036 *refLastRow = *refFirstRow;
2037 *refLastCol = *refFirstCol;
2038 } else if (maxRow < *refLastRow)
2039 *refLastRow = maxRow;
2045 restrict_code_range_by_str(int count,unsigned short *refFirstCol,
2046 unsigned short *refFirstRow,
2047 unsigned short *refLastCol,
2048 unsigned short *refLastRow,
2053 fsRange *ranges = NULL;
2058 int minpoint=0, maxpoint=65535;
2061 /* skip comma and/or space */
2062 while (',' == *p || isspace(*p))
2067 val = strtol(p, (char **)&q, 0);
2069 /* end or illegal */
2071 if (val<0 || val>65535) {
2083 if (',' != *p && '\0' != *p) {
2089 /* end or illegal */
2096 val = strtol(p, (char **)&q, 0);
2098 if (val<0 || val>65535)
2101 } else if (',' != *p && '\0' != *p)
2102 /* end or illegal */
2106 /* comma - single code */
2107 maxpoint = minpoint;
2109 if ( count <= 0 && minpoint>maxpoint ) {
2112 minpoint = maxpoint;
2118 fprintf(stderr, "zone: 0x%04X - 0x%04X\n", minpoint, maxpoint);
2122 ranges = realloc(ranges, nRanges*sizeof(*ranges));
2126 fsRange *r = ranges+nRanges-1;
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;
2137 restrict_code_range(refFirstCol, refFirstRow, refLastCol, refLastRow,
2143 for ( i=0 ; i<nRanges ; i++ ) {
2144 if ( count <= i ) break;
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;
2158 /* *face_number and *spacing are initialized but *load_flags is NOT. */
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 )
2165 int result = Successful;
2166 SDynPropRecValList listPropRecVal;
2167 SPropRecValContainer contRecValue;
2169 Bool isEmbeddedBitmap = True;
2170 Bool alwaysEmbeddedBitmap = False;
2171 int pixel = vals->pixel;
2173 *font_properties=True;
2174 *dynStrRealFileName=NULL;
2175 *dynStrFTFileName=NULL;
2176 *dynStrTTCapCodeRange=NULL;
2178 if (SPropRecValList_new(&listPropRecVal)) {
2183 int len = strlen(fileName);
2184 char *capHead = NULL;
2187 char *p1=NULL, *p2=NULL;
2189 p1=strrchr(fileName, '/');
2190 if ( p1 == NULL ) p1 = fileName;
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;
2197 *dynStrRealFileName = malloc(dirLen+baseLen+1);
2198 if( *dynStrRealFileName == NULL ) {
2199 result = AllocError;
2203 memcpy(*dynStrRealFileName, fileName, dirLen);
2204 strcpy(*dynStrRealFileName+dirLen, p2+1);
2207 *dynStrRealFileName = xstrdup(fileName);
2208 if( *dynStrRealFileName == NULL ) {
2209 result = AllocError;
2217 if (SPropRecValList_add_by_font_cap(&listPropRecVal,
2219 result = BadFontPath;
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;
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;
2249 ret->lsbShiftOfBitmapAutoItalic=0;
2250 ret->rsbShiftOfBitmapAutoItalic=0;
2253 char *beginptr=NULL,*endptr;
2254 if ( SPropRecValList_search_record(&listPropRecVal,
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;
2264 if( beginptr && 0 < *face_number ) {
2266 *dynStrFTFileName = /* add -> ':'+strlen0+':'+strlen1+'\0' */
2267 malloc(1+strlen(beginptr)+1+strlen(*dynStrRealFileName)+1);
2268 if( *dynStrFTFileName == NULL ){
2269 result = AllocError;
2272 **dynStrFTFileName = '\0';
2273 slash = strrchr(*dynStrRealFileName,'/');
2276 strcat(*dynStrFTFileName,*dynStrRealFileName);
2277 p = strrchr(*dynStrFTFileName,'/');
2279 strcat(*dynStrFTFileName,":");
2280 strcat(*dynStrFTFileName,beginptr);
2281 strcat(*dynStrFTFileName,":");
2282 strcat(*dynStrFTFileName,slash+1);
2285 strcat(*dynStrFTFileName,":");
2286 strcat(*dynStrFTFileName,beginptr);
2287 strcat(*dynStrFTFileName,":");
2288 strcat(*dynStrFTFileName,*dynStrRealFileName);
2292 *dynStrFTFileName = malloc(strlen(*dynStrRealFileName)+1);
2293 if( *dynStrFTFileName == NULL ){
2294 result = AllocError;
2297 **dynStrFTFileName = '\0';
2298 strcat(*dynStrFTFileName,*dynStrRealFileName);
2302 fprintf(stderr,"[Filename:%s]\n",fileName);
2303 fprintf(stderr,"[RealFilename:%s]\n",*dynStrRealFileName);
2304 fprintf(stderr,"[FTFilename:%s]\n",*dynStrFTFileName);
2307 if (SPropRecValList_search_record(&listPropRecVal,
2310 ret->autoItalic = SPropContainer_value_dbl(contRecValue);
2311 /* hinting control */
2312 if (SPropRecValList_search_record(&listPropRecVal,
2315 hinting = SPropContainer_value_bool(contRecValue);
2317 if (SPropRecValList_search_record(&listPropRecVal,
2320 ret->scaleWidth = SPropContainer_value_dbl(contRecValue);
2321 if (ret->scaleWidth<=0.0) {
2322 fprintf(stderr, "ScaleWitdh needs plus.\n");
2323 result = BadFontName;
2327 /* bbox adjustment */
2328 if (SPropRecValList_search_record(&listPropRecVal,
2330 "ScaleBBoxWidth")) {
2331 /* Scaling to Bounding Box Width */
2333 char *endptr,*beginptr;
2334 double v,scaleBBoxWidth=1.0,scaleBBoxHeight=1.0;
2335 beginptr = SPropContainer_value_str(contRecValue);
2337 if ( strlen(beginptr) < 1 ) break;
2338 v=strtod(beginptr, &endptr);
2339 if ( endptr!=beginptr ) {
2342 if ( *endptr != ';' && *endptr != ',' ) break;
2343 if ( *endptr == ',' ) {
2345 v=strtod(beginptr, &endptr);
2346 if ( endptr!=beginptr ) {
2347 scaleBBoxHeight = v;
2350 if ( *endptr != ';' && *endptr != ',' ) break;
2352 lv=strtol(beginptr, &endptr, 10);
2353 if ( endptr!=beginptr ) {
2354 ret->adjustBBoxWidthByPixel = lv;
2356 if ( *endptr != ',' ) break;
2358 lv=strtol(beginptr, &endptr, 10);
2359 if ( endptr!=beginptr ) {
2360 ret->adjustLeftSideBearingByPixel = lv;
2362 if ( *endptr != ',' ) break;
2364 lv=strtol(beginptr, &endptr, 10);
2365 if ( endptr!=beginptr ) {
2366 ret->adjustRightSideBearingByPixel = lv;
2369 if (scaleBBoxWidth<=0.0) {
2370 fprintf(stderr, "ScaleBBoxWitdh needs plus.\n");
2371 result = BadFontName;
2374 if (scaleBBoxHeight<=0.0) {
2375 fprintf(stderr, "ScaleBBoxHeight needs plus.\n");
2376 result = BadFontName;
2379 ret->scaleBBoxWidth = scaleBBoxWidth;
2380 ret->scaleBBoxHeight = scaleBBoxHeight;
2383 if (SPropRecValList_search_record(&listPropRecVal,
2386 char *strSpace = SPropContainer_value_str(contRecValue);
2388 if (1 != strlen(strSpace))
2391 switch (strSpace[0]) {
2393 ret->flags |= TTCAP_MONO_CENTER;
2399 *spacing = strSpace[0];
2405 result = BadFontName;
2409 /* doube striking */
2410 if (SPropRecValList_search_record(&listPropRecVal,
2413 /* Set or Reset Auto Bold Flag */
2414 char *strDoubleStrike = SPropContainer_value_str(contRecValue);
2416 if ( 0 < strlen(strDoubleStrike) ) {
2417 switch (strDoubleStrike[0]) {
2422 ret->flags |= TTCAP_DOUBLE_STRIKE;
2423 ret->flags |= TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
2427 ret->flags |= TTCAP_DOUBLE_STRIKE;
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;
2438 if ( err != True ) {
2439 if ( strDoubleStrike[1] ) {
2440 switch (strDoubleStrike[1]) {
2447 ret->flags |= TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH;
2454 char *comma_ptr=strchr(strDoubleStrike,';');
2455 if ( !comma_ptr ) comma_ptr=strchr(strDoubleStrike,',');
2456 if ( !comma_ptr ) break;
2457 if ( comma_ptr[1] ) {
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;
2465 comma_ptr=strchr(comma_ptr+1,',');
2466 if ( !comma_ptr ) break;
2467 if ( comma_ptr[1] ) {
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;
2482 result = BadFontName;
2486 /* very lazy metrics */
2487 if (SPropRecValList_search_record(&listPropRecVal,
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;
2495 ret->flags &= ~TTCAP_IS_VERY_LAZY;
2497 /* embedded bitmap */
2498 if (SPropRecValList_search_record(&listPropRecVal,
2500 "EmbeddedBitmap")) {
2501 char *strEmbeddedBitmap = SPropContainer_value_str(contRecValue);
2503 if ( 1 == strlen(strEmbeddedBitmap) ) {
2504 switch (strEmbeddedBitmap[0]) {
2507 isEmbeddedBitmap = True;
2508 alwaysEmbeddedBitmap = True;
2512 isEmbeddedBitmap = True;
2513 alwaysEmbeddedBitmap = False;
2517 isEmbeddedBitmap = False;
2526 result = BadFontName;
2531 if((ret->flags & TTCAP_IS_VERY_LAZY) &&
2532 SPropRecValList_search_record(&listPropRecVal,
2534 "VeryLazyBitmapWidthScale")) {
2535 /* Scaling to Bitmap Bounding Box Width */
2536 double scaleBitmapWidth = SPropContainer_value_dbl(contRecValue);
2538 fprintf(stderr, "Warning: `bs' option is not required in X-TT version 2.\n");
2540 if (scaleBitmapWidth<=0.0) {
2541 fprintf(stderr, "ScaleBitmapWitdh needs plus.\n");
2542 result = BadFontName;
2546 ret->scaleBitmap = scaleBitmapWidth;
2548 /* restriction of the code range */
2549 if (SPropRecValList_search_record(&listPropRecVal,
2552 *dynStrTTCapCodeRange = xstrdup(SPropContainer_value_str(contRecValue));
2553 if( *dynStrTTCapCodeRange == NULL ) {
2554 result = AllocError;
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,
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;
2578 unsigned short first_col=0, last_col=0x0ff;
2579 unsigned short first_row=0, last_row=0x0ff;
2580 if ( SPropRecValList_search_record(&listPropRecVal,
2582 "ForceConstantSpacingMetrics")) {
2584 strMetrics = SPropContainer_value_str(contRecValue);
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 );
2604 char *endptr,*beginptr=strMetrics;
2606 v=strtod(beginptr, &endptr);
2607 if ( endptr!=beginptr ) {
2608 ret->force_c_scale_b_box_width = v;
2610 if ( *endptr != ',' ) break;
2612 v=strtod(beginptr, &endptr);
2613 if ( endptr!=beginptr ) {
2614 ret->force_c_scale_lsb = v;
2615 ret->flags |= TTCAP_FORCE_C_LSB_FLAG;
2617 if ( *endptr != ',' ) break;
2619 v=strtod(beginptr, &endptr);
2620 if ( endptr!=beginptr ) {
2621 ret->force_c_scale_rsb = v;
2622 ret->flags |= TTCAP_FORCE_C_RSB_FLAG;
2624 if ( *endptr != ',' ) break;
2626 v=strtod(beginptr, &endptr);
2627 if ( endptr!=beginptr ) {
2628 ret->force_c_scale_b_box_height = v;
2634 char *endptr,*beginptr=semic_ptr+1;
2636 lv=strtol(beginptr, &endptr, 10);
2637 if ( endptr!=beginptr ) {
2638 ret->force_c_adjust_width_by_pixel=lv;
2640 if ( *endptr != ',' ) break;
2642 lv=strtol(beginptr, &endptr, 10);
2643 if ( endptr!=beginptr ) {
2644 ret->force_c_adjust_lsb_by_pixel=lv;
2646 if ( *endptr != ',' ) break;
2648 lv=strtol(beginptr, &endptr, 10);
2649 if ( endptr!=beginptr ) {
2650 ret->force_c_adjust_rsb_by_pixel=lv;
2658 if (SPropRecValList_search_record(&listPropRecVal,
2660 "FontProperties")) {
2661 /* Set or Reset the Flag of FontProperties */
2662 *font_properties=SPropContainer_value_bool(contRecValue);
2665 ret->force_c_scale_b_box_width *= ret->scaleBBoxWidth;
2666 ret->force_c_scale_b_box_height *= ret->scaleBBoxHeight;
2668 ret->force_c_scale_b_box_width *= ret->scaleWidth;
2669 ret->scaleBBoxWidth *= ret->scaleWidth;
2671 ret->force_c_adjust_rsb_by_pixel += ret->adjustRightSideBearingByPixel;
2672 ret->force_c_adjust_lsb_by_pixel += ret->adjustLeftSideBearingByPixel;
2674 /* scaleWidth, scaleBBoxWidth, force_c_scale_b_box_width, force_c_scale_b_box_width */
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;
2687 ft_get_trans_from_vals( FontScalablePtr vals, FTNormalisedTransformationPtr trans )
2689 /* Compute the transformation matrix. We use floating-point
2690 arithmetic for simplicity */
2692 trans->xres = vals->x;
2693 trans->yres = vals->y;
2695 /* This value cannot be 0. */
2696 trans->scale = hypot(vals->point_matrix[2], vals->point_matrix[3]);
2697 trans->nonIdentity = 0;
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;
2705 (int)((vals->point_matrix[0]*(double)TWO_SIXTEENTH)/trans->scale);
2707 (int)((vals->point_matrix[3]*(double)TWO_SIXTEENTH)/trans->scale);
2709 trans->matrix.xx = trans->matrix.yy =
2710 ((vals->point_matrix[0] + vals->point_matrix[3])/2*
2711 (double)TWO_SIXTEENTH)/trans->scale;
2714 if(DIFFER0(vals->point_matrix[1], trans->scale)) {
2716 (int)((vals->point_matrix[1]*(double)TWO_SIXTEENTH)/trans->scale);
2717 trans->nonIdentity = 1;
2719 trans->matrix.yx = 0;
2721 if(DIFFER0(vals->point_matrix[2], trans->scale)) {
2723 (int)((vals->point_matrix[2]*(double)TWO_SIXTEENTH)/trans->scale);
2724 trans->nonIdentity = 1;
2732 is_fixed_width(FT_Face face)
2734 PS_FontInfoRec t1info_rec;
2737 if(FT_IS_FIXED_WIDTH(face)) {
2741 ftrc = FT_Get_PS_Font_Info(face, &t1info_rec);
2742 if(ftrc == 0 && t1info_rec.is_fixed_pitch) {
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,
2757 FTNormalisedTransformationRec trans;
2758 int spacing, actual_spacing, zero_code;
2759 long lastCode, firstCode;
2760 TT_Postscript *post;
2762 ft_get_trans_from_vals(vals,&trans);
2764 /* Check for charcell in XLFD */
2765 spacing = FT_PROPORTIONAL;
2766 if(entry->name.ndashes == 14) {
2769 for(p = entry->name.name;
2770 p <= entry->name.name + entry->name.length - 2;
2775 if(p[1]=='c' && p[2]=='-')
2776 spacing=FT_CHARCELL;
2777 else if(p[1]=='m' && p[2]=='-')
2778 spacing=FT_MONOSPACED;
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;
2791 actual_spacing = spacing;
2792 if( spacing == FT_PROPORTIONAL ) {
2793 if( is_fixed_width(face->face) )
2794 actual_spacing = FT_MONOSPACED;
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)
2803 xrc = FTPickMapping(0, 0, FTFileName,
2804 face->face, &font->mapping);
2805 if (xrc != Successful)
2809 font->nranges = vals->nranges;
2812 font->ranges = malloc(vals->nranges*sizeof(fsRange));
2813 if(font->ranges == NULL)
2815 memcpy((char*)font->ranges, (char*)vals->ranges,
2816 vals->nranges*sizeof(fsRange));
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 :
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;
2835 (info->firstRow || info->lastRow) ? 0 : (firstCode & 0xFF);
2836 info->lastCol = info->lastRow ? 0xFF : (lastCode & 0xFF);
2837 if ( firstCode == 0 ) zero_code=0;
2839 /* matrix indexing */
2840 info->firstRow = font->mapping.mapping->encoding->first;
2841 info->lastRow = MIN(font->mapping.mapping->encoding->size-1,
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;
2849 /* firstCode and lastCode are not valid in case of a matrix
2852 if( dynStrTTCapCodeRange ) {
2853 restrict_code_range_by_str(0,&info->firstCol, &info->firstRow,
2854 &info->lastCol, &info->lastRow,
2855 dynStrTTCapCodeRange);
2857 restrict_code_range(&info->firstCol, &info->firstRow,
2858 &info->lastCol, &info->lastRow,
2859 font->ranges, font->nranges);
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. */
2871 font->zero_idx = FTRemap(face->face,
2872 &font->mapping, zero_code);
2874 post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post);
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 ) {
2880 tmp_ttcap->flags |= TTCAP_IS_VERY_LAZY;
2884 /* We should always reset. */
2885 tmp_ttcap->flags &= ~TTCAP_DISABLE_DEFAULT_VERY_LAZY;
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;
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); */
2899 xrc = FreeTypeOpenInstance(&font->instance, face,
2900 FTFileName, &trans, actual_spacing, bmfmt,
2901 tmp_ttcap, load_flags );
2906 adjust_min_max(xCharInfo *minc, xCharInfo *maxc, xCharInfo *tmp)
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;
2914 MINMAX(ascent, tmp);
2915 MINMAX(descent, tmp);
2916 MINMAX(leftSideBearing, tmp);
2917 MINMAX(rightSideBearing, tmp);
2918 MINMAX(characterWidth, tmp);
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;
2928 ft_compute_bounds(FTFontPtr font, FontInfoPtr pinfo, FontScalablePtr vals )
2930 FTInstancePtr instance;
2933 xCharInfo minchar, maxchar, *tmpchar = NULL;
2934 int overlap, maxOverlap;
2936 long total_width = 0;
2937 int num_cols, num_chars = 0;
2938 int flags, skip_ok = 0;
2939 int force_c_outside ;
2941 instance = font->instance;
2942 force_c_outside = instance->ttcap.flags & TTCAP_FORCE_C_OUTSIDE;
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;
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;
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;
2981 for (col = pinfo->firstCol; col <= pinfo->lastCol; col++) {
2984 if ( !force_c_outside ) {
2985 if ( c <= instance->ttcap.forceConstantSpacingEnd
2986 && instance->ttcap.forceConstantSpacingBegin <= c )
2987 flags|=FT_FORCE_CONSTANT_SPACING;
2989 else { /* for GB18030 proportional */
2990 if ( c <= instance->ttcap.forceConstantSpacingEnd
2991 || instance->ttcap.forceConstantSpacingBegin <= c )
2992 flags|=FT_FORCE_CONSTANT_SPACING;
2995 fprintf(stderr, "comp_bounds: %x ->", c);
2997 if ( skip_ok == 0 || flags == 0 ){
3000 fprintf(stderr, "%x\n", c);
3002 if( FreeTypeFontGetGlyphMetrics(c, flags, &tmpchar, font) != Successful )
3005 if ( !tmpchar ) continue;
3006 adjust_min_max(&minchar, &maxchar, tmpchar);
3007 overlap = tmpchar->rightSideBearing - tmpchar->characterWidth;
3008 if (maxOverlap < overlap)
3009 maxOverlap = overlap;
3011 if (!tmpchar->characterWidth)
3014 swidth += ABS(tmpchar->characterWidth);
3015 total_width += tmpchar->characterWidth;
3017 if ( flags & FT_FORCE_CONSTANT_SPACING ) skip_ok=1;
3021 #ifndef X_ACCEPTS_NO_SUCH_CHAR
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 )
3027 adjust_min_max(&minchar, &maxchar, tmpchar);
3028 overlap = tmpchar->rightSideBearing - tmpchar->characterWidth;
3029 if (maxOverlap < overlap)
3030 maxOverlap = overlap;
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)
3039 vals->width = swidth;
3044 if (char_width.pixel) {
3045 maxchar.characterWidth = char_width.pixel;
3046 minchar.characterWidth = char_width.pixel;
3050 pinfo->maxbounds = maxchar;
3051 pinfo->minbounds = minchar;
3052 pinfo->ink_maxbounds = maxchar;
3053 pinfo->ink_minbounds = minchar;
3054 pinfo->maxOverlap = maxOverlap;
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 )
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))
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;
3073 /* Compute new extents for this glyph */
3074 TRANSFORM_POINT(vals->pixel_matrix, lsb, -desc, point);
3077 newdesc = -point[1];
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);
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);
3094 #undef TRANSFORM_POINT
3098 is_matrix_unit(FontScalablePtr vals)
3103 base_size = hypot(vals->point_matrix[2], vals->point_matrix[3]);
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;
3110 return (m.xx == 65536) && (m.yx == 0) &&
3111 (m.xy == 0) && (m.yy == 65536);
3114 /* Do all the real work for OpenFont or FontInfo */
3115 /* xf->info is only accessed through info, and xf might be null */
3118 FreeTypeLoadXFont(char *fileName,
3119 FontScalablePtr vals, FontPtr xf, FontInfoPtr info,
3120 FontBitmapFormatPtr bmfmt, FontEntryPtr entry)
3122 FTFontPtr font = NULL;
3123 FTFacePtr face = NULL;
3124 FTInstancePtr instance;
3125 FT_Size_Metrics *smetrics;
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;
3140 font = calloc(1, sizeof(FTFontRec));
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 ) {
3155 xrc = FreeTypeOpenFace(&face, dynStrFTFileName, dynStrRealFileName, face_number);
3156 if(xrc != Successful) {
3160 if( is_matrix_unit(vals) )
3161 orig_is_matrix_unit = True;
3163 orig_is_matrix_unit = False;
3164 /* Turn off EmbeddedBitmap when original matrix is not diagonal. */
3165 load_flags |= FT_LOAD_NO_BITMAP;
3168 if( face->bitmap ) load_flags &= ~FT_LOAD_NO_BITMAP;
3170 /* Slant control by TTCap */
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;
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 ) {
3189 xrc = FreeTypeLoadFont(font, info, face, dynStrFTFileName, vals, entry, bmfmt,
3190 load_flags, &tmp_ttcap, dynStrTTCapCodeRange,
3192 if(xrc != Successful) {
3196 instance = font->instance;
3197 smetrics = &instance->size->metrics;
3198 ins_ttcap = &instance->ttcap;
3200 upm = face->face->units_per_EM;
3202 /* Work around FreeType bug */
3203 upm = WORK_AROUND_UPM;
3207 charcell = (instance->spacing == FT_CHARCELL);
3209 if( instance->charcellMetrics == NULL ) {
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;
3219 * CALCULATE HEADER'S METRICS
3222 /* for OUTLINE fonts */
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 );
3245 /* Consider vertical layouts */
3246 if( 0 < face->face->max_advance_height )
3247 max_advance_height = face->face->max_advance_height;
3249 max_advance_height = tmp_asc + tmp_des;
3250 if( vals->pixel_matrix[1] == 0 ){
3251 unit_x = fabs(vals->pixel_matrix[0]);
3253 width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x;
3255 else if( vals->pixel_matrix[3] == 0 ){
3256 unit_y = fabs(vals->pixel_matrix[2]);
3258 width_x = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y;
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 ){
3275 /* calculate correction ratio */
3276 width = (int)floor( (advance = width_x * scale) + 0.5);
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;
3283 /* force constant */
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;
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;
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 );
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 );
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 ) {
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;
3333 ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb;
3334 ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb;
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;
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
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);
3359 /* for BITMAP fonts [if(face->bitmap)] */
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);
3373 averageWidth = (int)floor(10.0 * smetrics->max_advance
3374 * ins_ttcap->scaleBBoxWidth / 64.0 + .5);
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];
3382 /* We can use 'width' only when bitmap.
3383 This should not be set when outline. */
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);
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);
3396 force_c_rsb = maxRsb;
3397 /* calculate shift of BitmapAutoItalic */
3398 if( ins_ttcap->autoItalic != 0 ) {
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;
3411 ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb;
3412 ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb;
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;
3434 /* SET CALCULATED VALUES TO INSTANCE */
3436 /* Set actual height and cosine */
3437 instance->pixel_size = base_height;
3438 instance->advance = advance;
3440 instance->pixel_width_unit_x = unit_x/base_height;
3441 instance->pixel_width_unit_y = 0;
3444 instance->pixel_width_unit_x = 0;
3445 instance->pixel_width_unit_y = unit_y/base_height;
3448 /* header's metrics */
3449 instance->charcellMetrics = malloc(sizeof(xCharInfo));
3450 if(instance->charcellMetrics == NULL) {
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;
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)
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) {
3486 /* Get Representative Metrics */
3488 if( FreeTypeFontGetGlyphMetrics(c, 0, &tmpchar, font) != Successful )
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;
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;
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)
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;
3539 * SET maxbounds, minbounds ...
3542 if( !charcell ) { /* NOT CHARCELL */
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.
3551 ft_compute_bounds(font,info,vals);
3554 else{ /* CHARCELL */
3557 * SET CALCULATED OR CACHED VARIABLES
3560 vals->width = averageWidth;
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;
3572 info->minbounds = info->maxbounds;
3580 info->fontAscent = ascent;
3581 info->fontDescent = descent;
3583 info->fontAscent = info->maxbounds.ascent;
3584 info->fontDescent = info->maxbounds.descent;
3585 /* Glyph metrics are accurate */
3588 memcpy((char *)&info->ink_maxbounds,
3589 (char *)&info->maxbounds, sizeof(xCharInfo));
3590 memcpy((char *)&info->ink_minbounds,
3591 (char *)&info->minbounds, sizeof(xCharInfo));
3596 /* Set the pInfo flags */
3597 /* Properties set by FontComputeInfoAccelerators:
3599 pInfo->terminalFont;
3600 pInfo->constantMetrics;
3601 pInfo->constantWidth;
3604 /* from lib/font/util/fontaccel.c */
3605 FontComputeInfoAccelerators(info);
3609 xf->fontPrivate = (void*)font;
3612 xrc = FreeTypeAddProperties(font, vals, info, entry->name.name,
3613 rawAverageWidth, font_properties);
3614 if (xrc != Successful) {
3620 if ( dynStrTTCapCodeRange ) free(dynStrTTCapCodeRange);
3621 if ( dynStrFTFileName ) free(dynStrFTFileName);
3622 if ( dynStrRealFileName ) free(dynStrRealFileName);
3623 if ( xrc != Successful ) {
3625 if( face && font->instance == NULL ) FreeTypeFreeFace(face);
3626 FreeTypeFreeFont(font);
3632 /* Routines used by X11 to get info and glyphs from the font. */
3635 FreeTypeGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars,
3636 FontEncoding charEncoding, unsigned long *metricCount,
3637 xCharInfo **metrics)
3639 unsigned int code = 0;
3642 struct TTCapInfo *ttcap;
3645 /* MUMBLE("Get metrics for %ld characters\n", count);*/
3647 tf = (FTFontPtr)pFont->fontPrivate;
3648 ttcap = &tf->instance->ttcap;
3651 while (count-- > 0) {
3652 switch (charEncoding) {
3659 code = (*chars++ << 8);
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;
3668 else { /* for GB18030 proportional */
3669 if ( (int)code <= ttcap->forceConstantSpacingEnd
3670 || ttcap->forceConstantSpacingBegin <= (int)code )
3671 flags|=FT_FORCE_CONSTANT_SPACING;
3677 if(FreeTypeFontGetGlyphMetrics(code, flags, &m, tf) == Successful && m!=NULL) {
3680 #ifdef X_ACCEPTS_NO_SUCH_CHAR
3681 else *mp++ = &noSuchChar.metrics;
3685 *metricCount = mp - metrics;
3690 FreeTypeGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
3691 FontEncoding charEncoding, unsigned long *glyphCount,
3692 CharInfoPtr *glyphs)
3694 unsigned int code = 0;
3699 struct TTCapInfo *ttcap;
3701 tf = (FTFontPtr)pFont->fontPrivate;
3702 ttcap = &tf->instance->ttcap;
3705 while (count-- > 0) {
3706 switch (charEncoding) {
3707 case Linear8Bit: case TwoD8Bit:
3710 case Linear16Bit: case TwoD16Bit:
3711 code = *chars++ << 8;
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;
3720 else { /* for GB18030 proportional */
3721 if ( (int)code <= ttcap->forceConstantSpacingEnd
3722 || ttcap->forceConstantSpacingBegin <= (int)code )
3723 flags|=FT_FORCE_CONSTANT_SPACING;
3729 if(FreeTypeFontGetGlyph(code, flags, &g, tf) == Successful && g!=NULL) {
3732 #ifdef X_ACCEPTS_NO_SUCH_CHAR
3734 #ifdef XAA_ACCEPTS_NULL_BITS
3735 *gp++ = &noSuchChar;
3737 if ( tf->dummy_char.bits ) {
3738 *gp++ = &tf->dummy_char;
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;
3747 if(ht_actual <= 0) ht = 1;
3749 bpr = (((wd + (tf->instance->bmfmt.glyph<<3) - 1) >> 3) &
3750 -tf->instance->bmfmt.glyph);
3751 raster = calloc(1, ht * bpr);
3753 tf->dummy_char.bits = raster;
3754 *gp++ = &tf->dummy_char;
3762 *glyphCount = gp - glyphs;
3767 FreeTypeSetUpFont(FontPathElementPtr fpe, FontPtr xf, FontInfoPtr info,
3768 fsBitmapFormat format, fsBitmapFormatMask fmask,
3769 FontBitmapFormatPtr bmfmt)
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);
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;
3797 xf->fontPrivate = 0; /* we'll set it later */
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; /* ??? */
3817 /* Functions exported by the backend */
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)
3827 FontBitmapFormatRec bmfmt;
3829 MUMBLE("Open Scalable %s, XLFD=%s\n",fileName, entry->name.length ? entry->name.name : "");
3831 xf = CreateFontRec();
3835 xrc = FreeTypeSetUpFont(fpe, xf, &xf->info, format, fmask, &bmfmt);
3836 if(xrc != Successful) {
3840 xrc = FreeTypeLoadXFont(fileName, vals, xf, &xf->info, &bmfmt, entry);
3841 if(xrc != Successful) {
3842 MUMBLE("Error during load: %d\n",xrc);
3852 /* Routine to get requested font info. */
3855 FreeTypeGetInfoScalable(FontPathElementPtr fpe, FontInfoPtr info,
3856 FontEntryPtr entry, FontNamePtr fontName,
3857 char *fileName, FontScalablePtr vals)
3860 FontBitmapFormatRec bmfmt;
3862 MUMBLE("Get info, XLFD=%s\n", entry->name.length ? entry->name.name : "");
3864 xrc = FreeTypeSetUpFont(fpe, 0, info, 0, 0, &bmfmt);
3865 if(xrc != Successful) {
3871 xrc = FreeTypeLoadXFont(fileName, vals, 0, info, &bmfmt, entry);
3872 if(xrc != Successful) {
3873 MUMBLE("Error during load: %d\n", xrc);
3880 /* Renderer registration. */
3882 /* Set the capabilities of this renderer. */
3883 #define CAPABILITIES (CAP_CHARSUBSETTING | CAP_MATRIX)
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},
3901 static int num_renderers = sizeof(renderers) / sizeof(renderers[0]);
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},
3910 static int num_alt_renderers =
3911 sizeof(alt_renderers) / sizeof(alt_renderers[0]);
3915 FreeTypeRegisterFontFileFunctions(void)
3919 for (i = 0; i < num_renderers; i++)
3920 FontFileRegisterRenderer(&renderers[i]);
3922 for (i = 0; i < num_alt_renderers; i++)
3923 FontFilePriorityRegisterRenderer(&alt_renderers[i], -10);