summaryrefslogtreecommitdiff
path: root/src/FreeType/ftfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/FreeType/ftfuncs.c')
-rw-r--r--src/FreeType/ftfuncs.c3112
1 files changed, 2491 insertions, 621 deletions
diff --git a/src/FreeType/ftfuncs.c b/src/FreeType/ftfuncs.c
index fa58006..d942784 100644
--- a/src/FreeType/ftfuncs.c
+++ b/src/FreeType/ftfuncs.c
@@ -1,6 +1,11 @@
/*
Copyright (c) 1997 by Mark Leisher
-Copyright (c) 1998-2002 by Juliusz Chroboczek
+Copyright (c) 1998-2003 by Juliusz Chroboczek
+Copyright (c) 1998 Go Watanabe, All rights reserved.
+Copyright (c) 1998 Kazushi (Jam) Marukawa, All rights reserved.
+Copyright (c) 1998 Takuya SHIOZAKI, All rights reserved.
+Copyright (c) 1998 X-TrueType Server Project, All rights reserved.
+Copyright (c) 2003 After X-TT Project, All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -21,7 +26,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
-/* $XFree86: xc/lib/font/FreeType/ftfuncs.c,v 1.27 2003/02/13 03:01:45 dawes Exp $ */
+/* $XFree86: xc/lib/font/FreeType/ftfuncs.c,v 1.37 2003/11/20 22:36:35 dawes Exp $ */
#include "fontmisc.h"
@@ -37,16 +42,58 @@ THE SOFTWARE.
#include "fntfilst.h"
#include "fontutil.h"
#include "FSproto.h"
-#include "freetype/freetype.h"
-#include "freetype/ftsizes.h"
-#include "freetype/ttnameid.h"
-#include "freetype/tttables.h"
-#include "freetype/t1tables.h"
-#include "freetype/ftxf86.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_SIZES_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_TYPE1_TABLES_H
+#include FT_XFREE86_H
+#include FT_BBOX_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+#include "ttobjs.h"
+/*
+ * If you want to use FT_Outline_Get_CBox instead of
+ * FT_Outline_Get_BBox, define here.
+ */
+/* #define USE_GET_CBOX */
+#ifdef USE_GET_CBOX
+#include FT_OUTLINE_H
+#endif
#include "fontenc.h"
#include "ft.h"
#include "ftfuncs.h"
+#include "xttcap.h"
+
+/* Work around FreeType bug */
+#define WORK_AROUND_UPM 2048
+
+#ifndef True
+#define True (-1)
+#endif /* True */
+#ifndef False
+#define False (0)
+#endif /* False */
+
+#define FLOOR64(x) ((x) & -64)
+#define CEIL64(x) (((x) + 64 - 1) & -64)
+
+/*
+ * If you want very lazy method(vl=y) AS DEFAULT when
+ * handling large charset, define here.
+ */
+/* #define DEFAULT_VERY_LAZY 1 */ /* Always */
+#define DEFAULT_VERY_LAZY 2 /* Multi-byte only */
+/* #define DEFAULT_VERY_LAZY 256 */ /* Unicode only */
+
+/* Does the XAA accept noSuchChar? */
+/* #define XAA_ACCEPTS_NO_SUCH_CHAR */
+
+#ifdef XAA_ACCEPTS_NO_SUCH_CHAR
+static CharInfoRec noSuchChar = { /* metrics */{0,0,0,0,0,0},
+ /* bits */ NULL };
+#endif
/* The propery names for all the XLFD properties. */
@@ -79,7 +126,7 @@ hash(char *string)
int i;
unsigned u = 0;
for(i = 0; string[i] != '\0'; i++)
- u = (u<<2) + (unsigned char)string[i];
+ u = (u<<5) + (u >> (NUMFACEBUCKETS - 5)) + (unsigned char)string[i];
return u;
}
@@ -99,13 +146,11 @@ iceil(int x, int y)
}
static int
-FreeTypeOpenFace(FTFacePtr *facep, char *fileName)
+FreeTypeOpenFace(FTFacePtr *facep, char *FTFileName, char *realFileName, int faceNumber)
{
FT_Error ftrc;
int bucket;
FTFacePtr face, otherFace;
- char *realFileName;
- int faceNumber;
if (!ftypeInitP) {
ftrc = FT_Init_FreeType(&ftypeLibrary);
@@ -117,11 +162,10 @@ FreeTypeOpenFace(FTFacePtr *facep, char *fileName)
}
/* Try to find a matching face in the hashtable */
- bucket = hash(fileName)%NUMFACEBUCKETS;
+ bucket = hash(FTFileName)%NUMFACEBUCKETS;
otherFace = faceTable[bucket];
while(otherFace) {
- if(strcmp(otherFace->filename, fileName) == 0)
- break;
+ if( strcmp(otherFace->filename, FTFileName) == 0 ) break;
otherFace = otherFace->next;
}
if(otherFace) {
@@ -135,29 +179,30 @@ FreeTypeOpenFace(FTFacePtr *facep, char *fileName)
if(face == NULL) {
return AllocError;
}
+ memset(face, 0, sizeof(FTFaceRec));
- face->filename = (char*)xalloc(strlen(fileName)+1);
+ face->filename = (char*)xalloc(strlen(FTFileName)+1);
if(face->filename == NULL) {
xfree(face);
return AllocError;
}
- strcpy(face->filename, fileName);
+ strcpy(face->filename, FTFileName);
- face->instances = NULL;
- face->active_instance = NULL;
-
- if(FTcheckForTTCName(fileName, &realFileName, &faceNumber)) {
- ftrc = FT_New_Face(ftypeLibrary, realFileName, faceNumber, &face->face);
- xfree(realFileName);
- } else
- ftrc = FT_New_Face(ftypeLibrary, fileName, 0, &face->face);
+ ftrc = FT_New_Face(ftypeLibrary, realFileName, faceNumber, &face->face);
if(ftrc != 0) {
- ErrorF("FreeType: couldn't open face %s: %d\n", fileName, ftrc);
+ ErrorF("FreeType: couldn't open face %s: %d\n", FTFileName, ftrc);
xfree(face->filename);
xfree(face);
- return BadFontPath;
+ return BadFontName;
}
+ face->bitmap = ((face->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0);
+ if(!face->bitmap) {
+ TT_MaxProfile *maxp;
+ maxp = FT_Get_Sfnt_Table(face->face, ft_sfnt_maxp);
+ if(maxp && maxp->maxContours == 0)
+ face->bitmap = 1;
+ }
/* Insert face in hashtable and return it */
face->next = faceTable[bucket];
faceTable[bucket] = face;
@@ -223,19 +268,45 @@ BitmapFormatEqual(FontBitmapFormatPtr f1, FontBitmapFormatPtr f2)
}
static int
+TTCapEqual(struct TTCapInfo *t1, struct TTCapInfo *t2)
+{
+ return
+ t1->autoItalic == t2->autoItalic &&
+ t1->scaleWidth == t2->scaleWidth &&
+ t1->scaleBBoxWidth == t2->scaleBBoxWidth &&
+ t1->scaleBBoxHeight == t2->scaleBBoxHeight &&
+ t1->doubleStrikeShift == t2->doubleStrikeShift &&
+ t1->adjustBBoxWidthByPixel == t2->adjustBBoxWidthByPixel &&
+ t1->adjustLeftSideBearingByPixel == t2->adjustLeftSideBearingByPixel &&
+ t1->adjustRightSideBearingByPixel == t2->adjustRightSideBearingByPixel &&
+ t1->flags == t2->flags &&
+ t1->scaleBitmap == t2->scaleBitmap &&
+ /*
+ If we use forceConstantSpacing,
+ we *MUST* allocate new instance.
+ */
+ t1->forceConstantSpacingEnd < 0 &&
+ t2->forceConstantSpacingEnd < 0;
+}
+
+static int
FTInstanceMatch(FTInstancePtr instance,
- char *fileName, FTNormalisedTransformationPtr trans,
- int charcell, FontBitmapFormatPtr bmfmt)
+ char *FTFileName, FTNormalisedTransformationPtr trans,
+ int spacing, FontBitmapFormatPtr bmfmt,
+ struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags)
{
- if(strcmp(instance->face->filename, fileName) != 0) {
+ if(strcmp(instance->face->filename, FTFileName) != 0) {
return 0;
} else if(!TransEqual(&instance->transformation, trans)) {
return 0;
- } else if((charcell && instance->monospaced != FT_CHARCELL) ||
- (!charcell && instance->monospaced == FT_CHARCELL)) {
+ } else if( spacing != instance->spacing ) {
+ return 0;
+ } else if( load_flags != instance->load_flags ) {
return 0;
} else if(!BitmapFormatEqual(&instance->bmfmt, bmfmt)) {
return 0;
+ } else if(!TTCapEqual(&instance->ttcap, tmp_ttcap)) {
+ return 0;
} else {
return 1;
}
@@ -264,26 +335,56 @@ FreeTypeActivateInstance(FTInstancePtr instance)
}
static int
-FreeTypeOpenInstance(FTInstancePtr *instance_return,
- char *fileName, FTNormalisedTransformationPtr trans,
- int charcell, FontBitmapFormatPtr bmfmt)
+FTFindSize(FT_Face face, FTNormalisedTransformationPtr trans,
+ int *x_return, int *y_return)
+{
+ int tx, ty, x, y;
+ int i, j;
+ int d, dd;
+
+ if(trans->nonIdentity)
+ return BadFontName;
+
+ tx = (int)(trans->scale * trans->xres / 72.0 + 0.5);
+ ty = (int)(trans->scale * trans->yres / 72.0 + 0.5);
+
+ d = 100;
+ j = -1;
+ for(i = 0; i < face->num_fixed_sizes; i++) {
+ x = face->available_sizes[i].width;
+ y = face->available_sizes[i].height;
+ if(ABS(x - tx) <= 1 && ABS(y - ty) <= 1) {
+ dd = ABS(x - tx) * ABS(x - tx) + ABS(y - ty) * ABS(y - ty);
+ if(dd < d) {
+ j = i;
+ d = dd;
+ }
+ }
+ }
+ if(j < 0)
+ return BadFontName;
+
+ *x_return = face->available_sizes[j].width;
+ *y_return = face->available_sizes[j].height;
+ return Successful;
+}
+
+static int
+FreeTypeOpenInstance(FTInstancePtr *instance_return, FTFacePtr face,
+ char *FTFileName, FTNormalisedTransformationPtr trans,
+ int spacing, FontBitmapFormatPtr bmfmt,
+ struct TTCapInfo *tmp_ttcap, FT_Int32 load_flags)
{
FT_Error ftrc;
int xrc;
FTInstancePtr instance, otherInstance;
- FTFacePtr face;
-
- xrc = FreeTypeOpenFace(&face, fileName);
- if(xrc != Successful) {
- return xrc;
- }
/* Search for a matching instance */
for(otherInstance = face->instances;
otherInstance;
otherInstance = otherInstance->next) {
- if(FTInstanceMatch(otherInstance, fileName, trans, charcell, bmfmt))
- break;
+ if(FTInstanceMatch(otherInstance, FTFileName, trans, spacing, bmfmt,
+ tmp_ttcap, load_flags)) break;
}
if(otherInstance) {
MUMBLE("Returning cached instance\n");
@@ -301,31 +402,53 @@ FreeTypeOpenInstance(FTInstancePtr *instance_return,
instance->refcount = 1;
instance->face = face;
- instance->monospaced = charcell?FT_CHARCELL:0;
- instance->charcellMetrics = 0;
- instance->width = 0;
-
+ instance->load_flags = load_flags;
+ instance->spacing = spacing; /* Actual spacing */
+ instance->pixel_size =0;
+ instance->pixel_width_unit_x =0;
+ instance->pixel_width_unit_y =0;
+ instance->charcellMetrics = NULL;
+ instance->averageWidth = 0;
+ instance->rawAverageWidth = 0;
+ instance->forceConstantMetrics = NULL;
+
instance->transformation = *trans;
instance->bmfmt = *bmfmt;
- instance->nglyphs = instance->face->face->num_glyphs;
instance->glyphs = NULL;
instance->available = NULL;
+ if( 0 <= tmp_ttcap->forceConstantSpacingEnd )
+ instance->nglyphs = 2 * instance->face->face->num_glyphs;
+ else
+ instance->nglyphs = instance->face->face->num_glyphs;
+
+ /* Store the TTCap info. */
+ memcpy((char*)&instance->ttcap, (char*)tmp_ttcap,
+ sizeof(struct TTCapInfo));
+
ftrc = FT_New_Size(instance->face->face, &instance->size);
if(ftrc != 0) {
ErrorF("FreeType: couldn't create size object: %d\n", ftrc);
- FreeTypeFreeFace(instance->face);
xfree(instance);
return FTtoXReturnCode(ftrc);
}
FreeTypeActivateInstance(instance);
- ftrc = FT_Set_Char_Size(instance->face->face,
- (int)(trans->scale*(1<<6)+0.5),
- (int)(trans->scale*(1<<6)+0.5),
- trans->xres, trans->yres);
+ if(!face->bitmap) {
+ ftrc = FT_Set_Char_Size(instance->face->face,
+ (int)(trans->scale*(1<<6) + 0.5),
+ (int)(trans->scale*(1<<6) + 0.5),
+ trans->xres, trans->yres);
+ } else {
+ int xsize, ysize;
+ xrc = FTFindSize(face->face, trans, &xsize, &ysize);
+ if(xrc != Successful) {
+ xfree(instance);
+ return xrc;
+ }
+ ftrc = FT_Set_Pixel_Sizes(instance->face->face, xsize, ysize);
+ }
if(ftrc != 0) {
FT_Done_Size(instance->size);
- FreeTypeFreeFace(instance->face);
xfree(instance);
return FTtoXReturnCode(ftrc);
}
@@ -343,6 +466,8 @@ FreeTypeFreeInstance(FTInstancePtr instance)
{
FTInstancePtr otherInstance;
+ if( instance == NULL ) return;
+
if(instance->face->active_instance == instance)
instance->face->active_instance = NULL;
instance->refcount--;
@@ -367,6 +492,9 @@ FreeTypeFreeInstance(FTInstancePtr instance)
if(instance->charcellMetrics) {
xfree(instance->charcellMetrics);
}
+ if(instance->forceConstantMetrics) {
+ xfree(instance->forceConstantMetrics);
+ }
if(instance->glyphs) {
for(i = 0; i < iceil(instance->nglyphs, FONTSEGMENTSIZE); i++) {
if(instance->glyphs[i]) {
@@ -392,11 +520,17 @@ FreeTypeFreeInstance(FTInstancePtr instance)
}
static int
-FreeTypeInstanceFindGlyph(unsigned idx, FTInstancePtr instance,
+FreeTypeInstanceFindGlyph(unsigned idx_in, int flags, FTInstancePtr instance,
CharInfoPtr **glyphs, int ***available,
int *found, int *segmentP, int *offsetP)
{
int segment, offset;
+ unsigned idx = idx_in;
+
+ if( 0 <= instance->ttcap.forceConstantSpacingEnd ){
+ if( (flags & FT_FORCE_CONSTANT_SPACING) )
+ idx += instance->nglyphs / 2 ;
+ }
if(idx > instance->nglyphs) {
*found = 0;
@@ -447,10 +581,9 @@ FreeTypeInstanceFindGlyph(unsigned idx, FTInstancePtr instance,
}
static int
-FreeTypeInstanceGetGlyph(unsigned idx, CharInfoPtr *g, FTInstancePtr instance)
+FreeTypeInstanceGetGlyph(unsigned idx, int flags, CharInfoPtr *g, FTInstancePtr instance)
{
int found, segment, offset;
- FT_Error ftrc;
int xrc;
int ***available;
CharInfoPtr **glyphs;
@@ -458,180 +591,662 @@ FreeTypeInstanceGetGlyph(unsigned idx, CharInfoPtr *g, FTInstancePtr instance)
available = &instance->available;
glyphs = &instance->glyphs;
- xrc = FreeTypeInstanceFindGlyph(idx, instance, glyphs, available,
+ xrc = FreeTypeInstanceFindGlyph(idx, flags, instance, glyphs, available,
&found, &segment, &offset);
if(xrc != Successful)
return xrc;
if(!found || (*available)[segment][offset] == FT_AVAILABLE_NO) {
- *g = 0;
- return Successful;
- } else if((*available)[segment][offset] == FT_AVAILABLE_RASTERISED) {
- *g = &(*glyphs)[segment][offset];
+ *g = NULL;
return Successful;
+ }
+
+ if((*available)[segment][offset] == FT_AVAILABLE_RASTERISED) {
+ *g = &(*glyphs)[segment][offset];
+ return Successful;
}
- /* Tough: need to rasterise a new glyph. */
- FreeTypeActivateInstance(instance);
- ftrc = FT_Load_Glyph(instance->face->face, idx,
- FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
- if(ftrc != 0)
- return FTtoXReturnCode(ftrc);
-
- if(instance->monospaced == FT_CHARCELL &&
- (*available)[segment][offset] == 0)
- memcpy((char*)&(*glyphs)[segment][offset].metrics,
- (char*)instance->charcellMetrics,
- sizeof(xCharInfo));
+ flags |= FT_GET_GLYPH_BOTH;
- xrc = FreeTypeRasteriseGlyph(&(*glyphs)[segment][offset],
- instance, instance->monospaced == FT_CHARCELL);
- if(xrc != Successful)
- return xrc;
- else
+ xrc = FreeTypeRasteriseGlyph(idx, flags,
+ &(*glyphs)[segment][offset], instance,
+ (*available)[segment][offset] >= FT_AVAILABLE_METRICS);
+ if(xrc == Successful) {
(*available)[segment][offset] = FT_AVAILABLE_RASTERISED;
-
- /* Update the width to match the width of the font */
- if(instance->monospaced) {
- if((*available)[segment][offset] >= FT_AVAILABLE_RASTERISED)
- (*glyphs)[segment][offset].metrics.characterWidth = instance->width;
- }
-
- /* return the glyph */
- if((*available)[segment][offset] >= FT_AVAILABLE_RASTERISED)
+ /* return the glyph */
*g = &(*glyphs)[segment][offset];
- else
- *g = 0;
- return Successful;
+ }
+ return xrc;
}
static int
-FreeTypeInstanceGetGlyphMetrics(unsigned idx,
- xCharInfo **metrics, FTInstancePtr instance)
+FreeTypeInstanceGetGlyphMetrics(unsigned idx, int flags,
+ xCharInfo **metrics, FTInstancePtr instance )
{
- CharInfoPtr g;
int xrc;
int found, segment, offset;
- xrc = FreeTypeInstanceFindGlyph(idx, instance,
+ /* Char cell */
+ if(instance->spacing == FT_CHARCELL) {
+ *metrics = instance->charcellMetrics;
+ return Successful;
+ }
+ /* Force constant metrics */
+ if( flags & FT_FORCE_CONSTANT_SPACING) {
+ *metrics = instance->forceConstantMetrics;
+ return Successful;
+ }
+
+ /* Not char cell */
+
+ xrc = FreeTypeInstanceFindGlyph(idx, flags, instance,
&instance->glyphs, &instance->available,
&found, &segment, &offset);
if(xrc != Successful)
return xrc;
-
if(!found) {
- *metrics = 0;
+ *metrics = NULL;
return Successful;
}
-
- if(instance->available[segment][offset] == 0) {
- if(instance->monospaced < FT_CHARCELL) {
- xrc = FreeTypeInstanceGetGlyph(idx, &g, instance);
- if(xrc != Successful)
- return xrc;
- } else {
- memcpy((char*)&instance->glyphs[segment][offset].metrics,
- (char*)instance->charcellMetrics,
- sizeof(xCharInfo));
- instance->available[segment][offset] = FT_AVAILABLE_YES;
- }
+ if( instance->available[segment][offset] == FT_AVAILABLE_NO ) {
+ *metrics = NULL;
+ return Successful;
+ }
+
+ if( instance->available[segment][offset] >= FT_AVAILABLE_METRICS ) {
+ *metrics = &instance->glyphs[segment][offset].metrics;
+ return Successful;
}
- if(instance->available[segment][offset] >= FT_AVAILABLE_YES) {
+ flags |= FT_GET_GLYPH_METRICS_ONLY;
+
+ xrc = FreeTypeRasteriseGlyph(idx, flags,
+ &instance->glyphs[segment][offset],
+ instance, 0);
+ if(xrc == Successful) {
+ instance->available[segment][offset] = FT_AVAILABLE_METRICS;
*metrics = &instance->glyphs[segment][offset].metrics;
- } else
- *metrics = 0;
-
- return Successful;
+ }
+ return xrc;
}
-int
-FreeTypeRasteriseGlyph(CharInfoPtr tgp, FTInstancePtr instance,
- int hasMetrics)
+/*
+ * Pseudo enbolding similar as Microsoft Windows.
+ * It is useful but poor.
+ */
+static void
+ft_make_up_bold_bitmap( char *raster, int bpr, int ht, int ds_mode)
{
-#define TRANSFORM_X(x_value) \
- ((int)floor((((double)(x_value)*(double)instance->transformation.matrix.xx)/\
- (TWO_SIXTEENTH*TWO_SIXTH))+0.5))
-
-#define TRANSFORM_Y(y_value) \
- ((int)floor((((double)(y_value)*(double)instance->transformation.matrix.yy)/\
- (TWO_SIXTEENTH*TWO_SIXTH))+0.5))
+ int x, y;
+ unsigned char *p = (unsigned char *)raster;
+ if ( ds_mode & TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT ) {
+ for (y=0; y<ht; y++) {
+ unsigned char rev_pat=0;
+ unsigned char lsb = 0;
+ for (x=0; x<bpr; x++) {
+ unsigned char tmp = *p<<7;
+ if ( (rev_pat & 0x01) && (*p & 0x80) ) p[-1] &= 0xfe;
+ rev_pat = ~(*p);
+ *p |= (*p>>1) | lsb;
+ *p &= ~(rev_pat & (*p << 1));
+ lsb = tmp;
+ p++;
+ }
+ }
+ }
+ else {
+ for (y=0; y<ht; y++) {
+ unsigned char lsb = 0;
+ for (x=0; x<bpr; x++) {
+ unsigned char tmp = *p<<7;
+ *p |= (*p>>1) | lsb;
+ lsb = tmp;
+ p++;
+ }
+ }
+ }
+}
-#define TRANSFORM_X_RAW(value) \
- ((int)floor((double)(value)/instance->transformation.scale/TWO_SIXTH/(smetrics.x_ppem/72.0)*1000.0+0.5))
+static void
+ft_make_up_italic_bitmap( char *raster, int bpr, int ht, int shift,
+ int h_total, int h_offset, double a_italic)
+{
+ int x, y;
+ unsigned char *p = (unsigned char *)raster;
+ if ( a_italic < 0 ) shift = -shift;
+ for (y=0; y<ht; y++) {
+ unsigned char *tmp_p = p + y*bpr;
+ int tmp_shift = shift * (h_total -1 -(y+h_offset)) / h_total;
+ int tmp_byte_shift;
+ if ( 0 <= tmp_shift ) {
+ tmp_byte_shift = tmp_shift/8;
+ tmp_shift %= 8;
+ if ( tmp_shift ) {
+ for (x=bpr-1;0<=x;x--) {
+ if ( x != bpr-1 )
+ tmp_p[x+1] |= tmp_p[x]<<(8-tmp_shift);
+ tmp_p[x]>>=tmp_shift;
+ }
+ }
+ if ( tmp_byte_shift ) {
+ for (x=bpr-1;0<x;x--) {
+ tmp_p[x] = tmp_p[x-1];
+ }
+ tmp_p[x]=0;
+ }
+ }
+ else {
+ tmp_shift = -tmp_shift;
+ tmp_byte_shift = tmp_shift/8;
+ tmp_shift %= 8;
+ if ( tmp_shift ) {
+ for (x=0;x<bpr;x++) {
+ if ( x != 0 )
+ tmp_p[x-1] |= tmp_p[x]>>(8-tmp_shift);
+ tmp_p[x]<<=tmp_shift;
+ }
+ }
+ if ( tmp_byte_shift ) {
+ for (x=0;x<bpr-1;x++) {
+ tmp_p[x] = tmp_p[x+1];
+ }
+ tmp_p[x]=0;
+ }
+ }
+ }
+}
+
+/*
+ * The very lazy method,
+ * parse the htmx field in TrueType font.
+ */
+
+/* from src/truetype/ttgload.c */
+static void
+tt_get_metrics( TT_HoriHeader* header,
+ FT_UInt idx,
+ FT_Short* bearing,
+ FT_UShort* advance )
+/* Copyright 1996-2001, 2002 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+{
+ TT_LongMetrics longs_m;
+ FT_UShort k = header->number_Of_HMetrics;
+
+ if ( k == 0 ) {
+ *bearing = *advance = 0;
+ return;
+ }
+
+ if ( idx < (FT_UInt)k ) {
+ longs_m = (TT_LongMetrics )header->long_metrics + idx;
+ *bearing = longs_m->bearing;
+ *advance = longs_m->advance;
+ }
+ else {
+ *bearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k];
+ *advance = ((TT_LongMetrics )header->long_metrics)[k - 1].advance;
+ }
+}
+
+static int
+ft_get_very_lazy_bbox( FT_UInt index,
+ FT_Face face,
+ FT_Size size,
+ double slant,
+ FT_Matrix *matrix,
+ FT_BBox *bbox,
+ FT_Long *horiAdvance,
+ FT_Long *vertAdvance)
+{
+ if ( FT_IS_SFNT( face ) ) {
+ TT_Face ttface = (TT_Face)face;
+ FT_Size_Metrics *smetrics = &size->metrics;
+ FT_Short leftBearing = 0;
+ FT_UShort advance = 0;
+ FT_Vector p0, p1, p2, p3;
+
+ /* horizontal */
+ tt_get_metrics(&ttface->horizontal, index,
+ &leftBearing, &advance);
+
+#if 0
+ fprintf(stderr,"x_scale=%f y_scale=%f\n",
+ (double)smetrics->x_scale,(double)smetrics->y_scale);
+#endif
+ bbox->xMax = *horiAdvance =
+ FT_MulFix( advance, smetrics->x_scale );
+ bbox->xMin =
+ FT_MulFix( leftBearing, smetrics->x_scale );
+ /* vertical */
+ bbox->yMin = FT_MulFix( face->bbox.yMin,
+ smetrics->y_scale );
+ bbox->yMax = FT_MulFix( face->bbox.yMax,
+ smetrics->y_scale );
+ /* slant */
+ if( 0 < slant ) {
+ bbox->xMax += slant * bbox->yMax;
+ bbox->xMin += slant * bbox->yMin;
+ }
+ else if( slant < 0 ) {
+ bbox->xMax += slant * bbox->yMin;
+ bbox->xMin += slant * bbox->yMax;
+ }
+
+ *vertAdvance = -1; /* We don't support */
+
+ p0.x = p2.x = bbox->xMin;
+ p1.x = p3.x = bbox->xMax;
+ p0.y = p1.y = bbox->yMin;
+ p2.y = p3.y = bbox->yMax;
+
+ FT_Vector_Transform(&p0, matrix);
+ FT_Vector_Transform(&p1, matrix);
+ FT_Vector_Transform(&p2, matrix);
+ FT_Vector_Transform(&p3, matrix);
+
+#if 0
+ fprintf(stderr,
+ "->(%.1f %.1f) (%.1f %.1f)"
+ " (%.1f %.1f) (%.1f %.1f)\n",
+ p0.x / 64.0, p0.y / 64.0,
+ p1.x / 64.0, p1.y / 64.0,
+ p2.x / 64.0, p2.y / 64.0,
+ p3.x / 64.0, p3.y / 64.0);
+#endif
+ bbox->xMin = MIN(p0.x, MIN(p1.x, MIN(p2.x, p3.x)));
+ bbox->xMax = MAX(p0.x, MAX(p1.x, MAX(p2.x, p3.x)));
+ bbox->yMin = MIN(p0.y, MIN(p1.y, MIN(p2.y, p3.y)));
+ bbox->yMax = MAX(p0.y, MAX(p1.y, MAX(p2.y, p3.y)));
+ return 0; /* Successful */
+ }
+ return -1;
+}
+int
+FreeTypeRasteriseGlyph(unsigned idx, int flags, CharInfoPtr tgp,
+ FTInstancePtr instance, int hasMetrics)
+{
FTFacePtr face;
FT_Bitmap *bitmap;
+ FT_BBox bbox;
+ FT_Long outline_hori_advance;
+ FT_Long outline_vert_advance;
char *raster = NULL;
- FT_Size_Metrics smetrics;
- FT_Glyph_Metrics *metrics;
+ FT_Glyph_Metrics *metrics = NULL;
int wd, ht, bpr; /* width, height, bytes per row */
+ int wd_actual, ht_actual;
+ int ftrc, is_outline, b_shift=0, correct=0;
int dx, dy;
int leftSideBearing, rightSideBearing, characterWidth, rawCharacterWidth,
ascent, descent;
- int i = 0, j;
+ double bbox_center_raw;
face = instance->face;
- smetrics = instance->size->metrics;
FreeTypeActivateInstance(instance);
- metrics = &face->face->glyph->metrics;
bitmap = &face->face->glyph->bitmap;
- if(hasMetrics) {
- wd = tgp->metrics.rightSideBearing - tgp->metrics.leftSideBearing;
- ht = tgp->metrics.ascent + tgp->metrics.descent;
- dx = -tgp->metrics.leftSideBearing +
- TRANSFORM_X(metrics->horiBearingX);
- dy = tgp->metrics.ascent - TRANSFORM_Y(metrics->horiBearingY);
- } else {
- wd = bitmap->width;
- ht = bitmap->rows;
- dx = 0;
- dy = 0;
- /* The X convention is to consider a character with an empty
- * bounding box as undefined. This convention is broken. */
- if(wd <= 0) wd = 1;
- if(ht <= 0) ht = 1;
- }
-
- /* Make sure rounding doesn't cause a crash in memcpy below */
- if(wd < bitmap->width)
- wd = bitmap->width;
- if(ht < bitmap->rows)
- ht = bitmap->rows;
+ if(!tgp) return AllocError;
- bpr = (((wd + (instance->bmfmt.glyph<<3) - 1) >> 3) &
- -instance->bmfmt.glyph);
- if(tgp) {
- raster = (char*)xalloc(ht * bpr);
- if(raster == NULL)
- return AllocError;
- memset(raster, 0, ht * bpr);
+ if( instance->spacing == FT_CHARCELL ) correct=1;
+ else if( flags & FT_FORCE_CONSTANT_SPACING ) correct=1;
+ else if( instance->ttcap.flags & TTCAP_IS_VERY_LAZY ){
+ if( hasMetrics || (!hasMetrics && (flags & FT_GET_GLYPH_METRICS_ONLY)) ){
+ /* If sbit is available, we don't use very lazy method. */
+ /* See TT_Load_Glyph */
+ if( FT_IS_SFNT( face->face ) ) {
+ TT_Size tt_size = (TT_Size)instance->size;
+ if( !( !(instance->load_flags & FT_LOAD_NO_BITMAP)
+ && tt_size->strike_index != 0xFFFFU ) ) correct=1;
+ }
+ }
}
- if(dx == 0 && dy == 0 && bpr == bitmap->pitch) {
- memcpy(raster, bitmap->buffer, bitmap->rows * bitmap->pitch);
- } else if(dx == 0) {
- for(i = MAX(0, -dy); i < bitmap->rows && i + dy < ht; i++)
- memcpy(raster + (i + dy) * bpr,
- bitmap->buffer + i * bitmap->pitch,
- bitmap->pitch);
- } else {
- for(i = MAX(0, -dy); i < bitmap->rows && i + dy < ht; i++) {
- for(j = MAX(0, -dx); j < bitmap->width && j + dx < wd; j++) {
- int set;
- set = (bitmap->buffer[i * bitmap->pitch + j / 8] &
- 1 << (7 - j % 8));
- if(set)
- raster[(i + dy) * bpr + (j + dx) / 8] |=
- 1 << (7 - (j + dx) % 8);
- }
- }
+ /*
+ * PREPARE METRICS
+ */
+
+ if(!hasMetrics) {
+ if( instance->spacing == FT_CHARCELL || flags & FT_GET_DUMMY ){
+ memcpy((char*)&tgp->metrics,
+ (char*)instance->charcellMetrics,
+ sizeof(xCharInfo));
+ }
+ else if( flags & FT_FORCE_CONSTANT_SPACING ) {
+ memcpy((char*)&tgp->metrics,
+ (char*)instance->forceConstantMetrics,
+ sizeof(xCharInfo));
+ }
+ /* mono or prop. */
+ else{
+ int new_width, try_very_lazy=correct;
+ double ratio;
+
+ if( try_very_lazy ) {
+ if( ft_get_very_lazy_bbox( idx, face->face, instance->size,
+ instance->ttcap.vl_slant,
+ &instance->transformation.matrix,
+ &bbox, &outline_hori_advance,
+ &outline_vert_advance ) == 0 ) {
+ goto bbox_ok; /* skip exact calculation */
+ }
+ }
+
+ ftrc = FT_Load_Glyph(instance->face->face, idx,
+ instance->load_flags);
+ metrics = &face->face->glyph->metrics;
+
+ if(ftrc != 0) return FTtoXReturnCode(ftrc);
+
+ if( face->face->glyph->format == FT_GLYPH_FORMAT_BITMAP ) {
+ /* bitmap, embedded bitmap */
+ leftSideBearing = metrics->horiBearingX / 64;
+ rightSideBearing = (metrics->width + metrics->horiBearingX) / 64;
+ bbox_center_raw = (2.0 * metrics->horiBearingX + metrics->width)/2.0/64.0;
+ characterWidth = (int)floor(metrics->horiAdvance
+ * instance->ttcap.scaleBBoxWidth / 64.0 + .5);
+ ascent = metrics->horiBearingY / 64;
+ descent = (metrics->height - metrics->horiBearingY) / 64 ;
+ /* */
+ new_width = characterWidth;
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ new_width += instance->ttcap.doubleStrikeShift;
+ new_width += instance->ttcap.adjustBBoxWidthByPixel;
+ ratio = (double)new_width/characterWidth;
+ characterWidth = new_width;
+ /* adjustment by pixel unit */
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE )
+ rightSideBearing += instance->ttcap.doubleStrikeShift;
+ rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel;
+ leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel;
+ rightSideBearing += instance->ttcap.rsbShiftOfBitmapAutoItalic;
+ leftSideBearing += instance->ttcap.lsbShiftOfBitmapAutoItalic;
+ /* */
+ rawCharacterWidth =
+ (unsigned short)(short)(floor(1000 * metrics->horiAdvance
+ * instance->ttcap.scaleBBoxWidth * ratio / 64.
+ / instance->pixel_size));
+ }
+ else {
+ /* Outline */
+#ifdef USE_GET_CBOX
+ /* Very fast?? */
+ FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
+ ftrc=0; /* FT_Outline_Get_CBox returns nothing. */
+#else
+ /* Calculate exact metrics */
+ ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
+#endif
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ outline_hori_advance = metrics->horiAdvance;
+ outline_vert_advance = metrics->vertAdvance;
+ bbox_ok:
+ descent = CEIL64(-bbox.yMin - 32) / 64;
+ leftSideBearing = FLOOR64(bbox.xMin + 32) / 64;
+ ascent = FLOOR64(bbox.yMax + 32) / 64;
+ rightSideBearing = FLOOR64(bbox.xMax + 32) / 64;
+ bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.;
+ if ( instance->pixel_width_unit_x != 0 )
+ characterWidth =
+ (int)floor( outline_hori_advance
+ * instance->ttcap.scaleBBoxWidth
+ * instance->pixel_width_unit_x / 64. + .5);
+ else {
+ characterWidth =
+ (int)floor( outline_vert_advance
+ * instance->ttcap.scaleBBoxHeight
+ * instance->pixel_width_unit_y / 64. + .5);
+ if(characterWidth <= 0)
+ characterWidth = instance->charcellMetrics->characterWidth;
+ }
+ /* */
+ new_width = characterWidth;
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ new_width += instance->ttcap.doubleStrikeShift;
+ new_width += instance->ttcap.adjustBBoxWidthByPixel;
+ ratio = (double)new_width/characterWidth;
+ characterWidth = new_width;
+ if ( instance->pixel_width_unit_x != 0 )
+ rawCharacterWidth =
+ (unsigned short)(short)(floor(1000 * outline_hori_advance
+ * instance->ttcap.scaleBBoxWidth * ratio
+ * instance->pixel_width_unit_x / 64.));
+ else {
+ rawCharacterWidth =
+ (unsigned short)(short)(floor(1000 * outline_vert_advance
+ * instance->ttcap.scaleBBoxHeight * ratio
+ * instance->pixel_width_unit_y / 64.));
+ if(rawCharacterWidth <= 0)
+ rawCharacterWidth = instance->charcellMetrics->attributes;
+ }
+ /* adjustment by pixel unit */
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE )
+ rightSideBearing += instance->ttcap.doubleStrikeShift;
+ rightSideBearing += instance->ttcap.adjustRightSideBearingByPixel;
+ leftSideBearing += instance->ttcap.adjustLeftSideBearingByPixel;
+ }
+
+ /* Set the glyph metrics. */
+ tgp->metrics.attributes = (unsigned short)((short)rawCharacterWidth);
+ tgp->metrics.leftSideBearing = leftSideBearing;
+ tgp->metrics.rightSideBearing = rightSideBearing;
+ tgp->metrics.characterWidth = characterWidth;
+ tgp->metrics.ascent = ascent;
+ tgp->metrics.descent = descent;
+ /* Update the width to match the width of the font */
+ if( instance->spacing != FT_PROPORTIONAL )
+ tgp->metrics.characterWidth = instance->charcellMetrics->characterWidth;
+ if(instance->ttcap.flags & TTCAP_MONO_CENTER){
+ b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5);
+ tgp->metrics.leftSideBearing += b_shift;
+ tgp->metrics.rightSideBearing += b_shift;
+ }
+ }
+ }
+
+ if( flags & FT_GET_GLYPH_METRICS_ONLY ) return Successful;
+
+ /*
+ * RENDER AND ALLOCATE BUFFER
+ */
+
+ if( flags & FT_GET_DUMMY ) is_outline = -1;
+ else {
+ if( !metrics ) {
+ ftrc = FT_Load_Glyph(instance->face->face, idx,
+ instance->load_flags);
+ metrics = &face->face->glyph->metrics;
+
+ if(ftrc != 0) return FTtoXReturnCode(ftrc);
+ }
+
+ if( face->face->glyph->format != FT_GLYPH_FORMAT_BITMAP ) {
+ ftrc = FT_Render_Glyph(face->face->glyph,FT_RENDER_MODE_MONO);
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ is_outline = 1;
+ }
+ else{
+ is_outline=0;
+ }
+ }
+
+ /* Spacial case */
+ if( (instance->ttcap.flags & TTCAP_MONO_CENTER) && hasMetrics ) {
+ if( is_outline == 1 ){
+ if( correct ){
+ if( ft_get_very_lazy_bbox( idx, face->face, instance->size,
+ instance->ttcap.vl_slant,
+ &instance->transformation.matrix,
+ &bbox, &outline_hori_advance,
+ &outline_vert_advance ) != 0 ){
+ is_outline = -1; /* <- error */
+ }
+ }
+ else {
+#ifdef USE_GET_CBOX
+ FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
+ ftrc=0;
+#else
+ ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
+#endif
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ }
+ bbox_center_raw = (double)(bbox.xMax + bbox.xMin)/2.0/64.;
+ }
+ else if( is_outline == 0 )
+ bbox_center_raw = (2.0 * metrics->horiBearingX + metrics->width)/2.0/64.0;
+ else
+ bbox_center_raw = 0;
+ b_shift = (int)floor((instance->advance/2.0-bbox_center_raw) + .5);
}
+ wd_actual = tgp->metrics.rightSideBearing - tgp->metrics.leftSideBearing;
+ ht_actual = tgp->metrics.ascent + tgp->metrics.descent;
+
+ /* The X convention is to consider a character with an empty
+ * bounding box as undefined. This convention is broken. */
+
+ if(wd_actual <= 0) wd = 1;
+ else wd=wd_actual;
+ if(ht_actual <= 0) ht = 1;
+ else ht=ht_actual;
+
+ bpr = (((wd + (instance->bmfmt.glyph<<3) - 1) >> 3) &
+ -instance->bmfmt.glyph);
+ raster = (char*)xalloc(ht * bpr);
+ if(raster == NULL)
+ return AllocError;
+ memset(raster, 0, ht * bpr);
+
tgp->bits = raster;
+
+ /* If FT_GET_DUMMY is set, we return white space. */
+ if ( is_outline == -1 ) return Successful;
+
+ if ( wd_actual <= 0 || ht_actual <= 0 ) return Successful;
+
+ /*
+ * CALCULATE OFFSET, dx AND dy.
+ */
+
+ dx = face->face->glyph->bitmap_left - tgp->metrics.leftSideBearing;
+ dy = tgp->metrics.ascent - face->face->glyph->bitmap_top;
+
+ if(instance->ttcap.flags & TTCAP_MONO_CENTER)
+ dx += b_shift;
+
+ /* To prevent chipped bitmap, we correct dx and dy if needed. */
+ if( correct && is_outline==1 ){
+ int lsb, rsb, asc, des;
+ int chip_left,chip_right,chip_top,chip_bot;
+#ifdef USE_GET_CBOX
+ FT_Outline_Get_CBox(&face->face->glyph->outline, &bbox);
+ ftrc=0;
+#else
+ ftrc=FT_Outline_Get_BBox(&face->face->glyph->outline, &bbox);
+#endif
+ if( ftrc != 0 ) return FTtoXReturnCode(ftrc);
+ des = CEIL64(-bbox.yMin - 32) / 64;
+ lsb = FLOOR64(bbox.xMin + 32) / 64;
+ asc = FLOOR64(bbox.yMax + 32) / 64;
+ rsb = FLOOR64(bbox.xMax + 32) / 64;
+ rightSideBearing = tgp->metrics.rightSideBearing;
+ leftSideBearing = tgp->metrics.leftSideBearing;
+ if( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE )
+ rightSideBearing -= instance->ttcap.doubleStrikeShift;
+ /* special case */
+ if(instance->ttcap.flags & TTCAP_MONO_CENTER){
+ leftSideBearing -= b_shift;
+ rightSideBearing -= b_shift;
+ }
+ chip_left = lsb - leftSideBearing;
+ chip_right = rightSideBearing - rsb;
+ if( flags & FT_FORCE_CONSTANT_SPACING ){
+ if( instance->ttcap.force_c_adjust_lsb_by_pixel != 0 ||
+ instance->ttcap.force_c_adjust_rsb_by_pixel != 0 ){
+ chip_left=0;
+ chip_right=0;
+ }
+ }
+ else{
+ if( instance->ttcap.adjustRightSideBearingByPixel != 0 ||
+ instance->ttcap.adjustLeftSideBearingByPixel != 0 ){
+ chip_left=0;
+ chip_right=0;
+ }
+ }
+ chip_top = tgp->metrics.ascent - asc;
+ chip_bot = tgp->metrics.descent - des;
+ if( chip_left < 0 && 0 < chip_right ) dx++;
+ else if( chip_right < 0 && 0 < chip_left ) dx--;
+ if( chip_top < 0 && 0 < chip_bot ) dy++;
+ else if( chip_bot < 0 && 0 < chip_top ) dy--;
+ }
+
+ /*
+ * COPY RASTER
+ */
+
+ {
+ int i, j;
+ unsigned char *current_raster;
+ unsigned char *current_buffer;
+ int mod_dx0,mod_dx1;
+ int div_dx;
+ if( 0 <= dx ){
+ div_dx = dx / 8;
+ mod_dx0 = dx % 8;
+ mod_dx1 = 8-mod_dx0;
+ }
+ else{
+ div_dx = dx / 8 -1;
+ mod_dx1 = -dx % 8;
+ mod_dx0 = 8-mod_dx1;
+ }
+ for( i = MAX(0, dy) ; i<ht ; i++ ){
+ int prev_jj,jj;
+ if( bitmap->rows <= i-dy ) break;
+ current_buffer=(unsigned char *)(bitmap->buffer+bitmap->pitch*(i-dy));
+ current_raster=(unsigned char *)(raster+i*bpr);
+ j = MAX(0,div_dx);
+ jj = j-div_dx;
+ prev_jj = jj-1;
+ if( j<bpr ){
+ if( 0 <= prev_jj && prev_jj < bitmap->pitch )
+ current_raster[j]|=current_buffer[prev_jj]<<mod_dx1;
+ if( 0 <= jj && jj < bitmap->pitch ){
+ current_raster[j]|=current_buffer[jj]>>mod_dx0;
+ j++; prev_jj++; jj++;
+ for( ; j<bpr ; j++,prev_jj++,jj++ ){
+ current_raster[j]|=current_buffer[prev_jj]<<mod_dx1;
+ if( bitmap->pitch <= jj ) break;
+ current_raster[j]|=current_buffer[jj]>>mod_dx0;
+ }
+ }
+ }
+ }
+ }
+
+ /* by TTCap */
+ if ( instance->ttcap.flags & TTCAP_DOUBLE_STRIKE ) {
+ int i;
+ for( i=0 ; i < instance->ttcap.doubleStrikeShift ; i++ )
+ ft_make_up_bold_bitmap( raster, bpr, ht, instance->ttcap.flags);
+ }
+ if ( is_outline == 0 &&
+ ( instance->ttcap.lsbShiftOfBitmapAutoItalic != 0 ||
+ instance->ttcap.rsbShiftOfBitmapAutoItalic != 0 ) ) {
+ ft_make_up_italic_bitmap( raster, bpr, ht,
+ - instance->ttcap.lsbShiftOfBitmapAutoItalic
+ + instance->ttcap.rsbShiftOfBitmapAutoItalic,
+ instance->charcellMetrics->ascent
+ + instance->charcellMetrics->descent,
+ instance->charcellMetrics->ascent
+ - tgp->metrics.ascent,
+ instance->ttcap.autoItalic);
+ }
if(instance->bmfmt.bit == LSBFirst) {
BitOrderInvert((unsigned char*)(tgp->bits), ht*bpr);
@@ -651,32 +1266,8 @@ FreeTypeRasteriseGlyph(CharInfoPtr tgp, FTInstancePtr instance,
;
}
}
-
-
- if(!hasMetrics) {
- leftSideBearing = TRANSFORM_X(metrics->horiBearingX);
- rightSideBearing = wd + TRANSFORM_X(metrics->horiBearingX);
-
- characterWidth = TRANSFORM_X(metrics->horiAdvance);
- rawCharacterWidth = TRANSFORM_X_RAW(metrics->horiAdvance);
-
- ascent = TRANSFORM_Y(metrics->horiBearingY);
- descent = ht - TRANSFORM_Y(metrics->horiBearingY);
-
- if(tgp) {
- /* Set the glyph metrics. */
- tgp->metrics.attributes = (unsigned short)((short)rawCharacterWidth);
- tgp->metrics.leftSideBearing = leftSideBearing;
- tgp->metrics.rightSideBearing = rightSideBearing;
- tgp->metrics.characterWidth = characterWidth;
- tgp->metrics.ascent = ascent;
- tgp->metrics.descent = descent;
- }
- }
+
return Successful;
-#undef TRANSFORM_X
-#undef TRANSFORM_Y
-#undef TRANSFORM_X_RAW
}
static void
@@ -725,14 +1316,12 @@ FreeTypeUnloadXFont(FontPtr pFont)
static int
FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
- char *fontname,
- int rawAverageWidth)
+ char *fontname, int rawAverageWidth)
{
int i, j, maxprops;
char *sp, *ep, val[MAXFONTNAMELEN], *vp;
FTFacePtr face;
FTInstancePtr instance;
- FT_Size_Metrics smetrics;
FTNormalisedTransformationPtr trans;
int upm;
TT_OS2 *os2;
@@ -743,9 +1332,12 @@ FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
instance = font->instance;
face = instance->face;
- smetrics = instance->size->metrics;
trans = &instance->transformation;
- upm = face->face->units_per_EM;
+ upm = face->face->units_per_EM;
+ if(upm == 0) {
+ /* Work around FreeType bug */
+ upm = WORK_AROUND_UPM;
+ }
os2 = FT_Get_Sfnt_Table(face->face, ft_sfnt_os2);
post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post);
@@ -841,27 +1433,33 @@ FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
}
}
- info->props[i].name = MakeAtom("RAW_AVERAGE_WIDTH", 17, TRUE);
- info->props[i].value = rawAverageWidth;
- i++;
+ if(!face->bitmap) {
+ info->props[i].name = MakeAtom("RAW_AVERAGE_WIDTH", 17, TRUE);
+ info->props[i].value = rawAverageWidth;
+ i++;
+ }
info->props[i].name = MakeAtom("FONT_ASCENT", 11, TRUE);
info->props[i].value = info->fontAscent;
i++;
- info->props[i].name = MakeAtom("RAW_ASCENT", 15, TRUE);
- info->props[i].value =
- ((double)face->face->ascender/(double)upm*1000.0);
- i++;
+ if(!face->bitmap) {
+ info->props[i].name = MakeAtom("RAW_ASCENT", 15, TRUE);
+ info->props[i].value =
+ ((double)face->face->ascender/(double)upm*1000.0);
+ i++;
+ }
info->props[i].name = MakeAtom("FONT_DESCENT", 12, TRUE);
info->props[i].value = info->fontDescent;
i++;
- info->props[i].name = MakeAtom("RAW_DESCENT", 16, TRUE);
- info->props[i].value =
- -((double)face->face->descender/(double)upm*1000.0);
- i++;
+ if(!face->bitmap) {
+ info->props[i].name = MakeAtom("RAW_DESCENT", 16, TRUE);
+ info->props[i].value =
+ -((double)face->face->descender/(double)upm*1000.0);
+ i++;
+ }
j = FTGetEnglishName(face->face, TT_NAME_ID_COPYRIGHT,
val, MAXFONTNAMELEN);
@@ -915,15 +1513,11 @@ FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
FUnits into pixels. */
#define TRANSFORM_FUNITS_X(xval) \
((int) \
- floor((((double)(xval)/(double)upm) * \
- ((double)trans->matrix.xx/TWO_SIXTEENTH)*(double)smetrics.x_ppem)+\
- 0.5))
+ floor( ((double)(xval)/(double)upm) * (double)vals->pixel_matrix[0] + 0.5 ) )
#define TRANSFORM_FUNITS_Y(yval) \
((int) \
- floor((((double)(yval)/(double)upm) * \
- ((double)trans->matrix.yy/TWO_SIXTEENTH) * (double)smetrics.y_ppem)+\
- 0.5))
+ floor( ((double)(yval)/(double)upm) * (double)vals->pixel_matrix[3] + 0.5 ) )
/* In what follows, we assume the matrix is diagonal. In the rare
case when it is not, the values will be somewhat wrong. */
@@ -958,12 +1552,14 @@ FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
if(post || t1info) {
int underlinePosition, underlineThickness;
+ /* Raw underlineposition counts upwards,
+ but UNDERLINE_POSITION counts downwards. */
if(post) {
- underlinePosition = TRANSFORM_FUNITS_Y(post->underlinePosition);
+ underlinePosition = TRANSFORM_FUNITS_Y(-post->underlinePosition);
underlineThickness = TRANSFORM_FUNITS_Y(post->underlineThickness);
} else {
underlinePosition =
- TRANSFORM_FUNITS_Y(t1info->underline_position);
+ TRANSFORM_FUNITS_Y(-t1info->underline_position);
underlineThickness =
TRANSFORM_FUNITS_Y(t1info->underline_thickness);
}
@@ -975,7 +1571,9 @@ FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
i++;
info->props[i].name = MakeAtom("UNDERLINE_POSITION",18,TRUE);
+
info->props[i].value = underlinePosition;
+
i++;
/* The italic angle is often unreliable for Type 1 fonts */
@@ -1007,16 +1605,16 @@ FreeTypeAddProperties(FTFontPtr font, FontScalablePtr vals, FontInfoPtr info,
}
static int
-FreeTypeFontGetGlyph(unsigned code, CharInfoPtr *g, FTFontPtr font)
+ft_get_index(unsigned code, FTFontPtr font, unsigned *idx)
{
- unsigned idx;
- int i;
/* As a special case, we pass 0 even when it is not in the ranges;
this will allow for the default glyph, which should exist in any
TrueType font. */
+ /* This is not required...
if(code > 0 && font->nranges) {
+ int i;
for(i = 0; i < font->nranges; i++)
if((code >=
font->ranges[i].min_char_low+
@@ -1026,137 +1624,861 @@ FreeTypeFontGetGlyph(unsigned code, CharInfoPtr *g, FTFontPtr font)
(font->ranges[i].max_char_high<<8)))
break;
if(i == font->nranges) {
- *g = 0;
- return Successful;
+ *idx = font->zero_idx;
+ return -1;
}
}
+ */
+ if( font->info ) {
+ if( !( font->info->firstCol <= (code & 0x000ff) &&
+ (code & 0x000ff) <= font->info->lastCol &&
+ font->info->firstRow <= (code >> 8) &&
+ (code >> 8) <= font->info->lastRow ) ) {
+ *idx = font->zero_idx;
+ /* Error: The code has not been parsed in ft_compute_bounds()!
+ We should not return any metrics. */
+ return -1;
+ }
+ }
+
+ *idx = FTRemap(font->instance->face->face, &font->mapping, code);
- idx = FTRemap(font->instance->face->face, &font->mapping, code);
+ return 0;
+}
+
+static int
+FreeTypeFontGetGlyph(unsigned code, int flags, CharInfoPtr *g, FTFontPtr font)
+{
+ unsigned idx;
+ int xrc;
- /* Only pass the default glyph if there is no first index */
- if(idx == 0 &&
- (code != 0 ||
- (font->mapping.mapping &&
- (font->mapping.mapping->encoding->first != 0 ||
- font->mapping.mapping->encoding->first_col != 0)))) {
- *g = 0;
- return Successful;
- } else {
- return FreeTypeInstanceGetGlyph(idx, g, font->instance);
+ if( ft_get_index(code,font,&idx) ) {
+ *g = NULL;
+ flags &= ~FT_FORCE_CONSTANT_SPACING;
+#ifdef XAA_ACCEPTS_NO_SUCH_CHAR
+ /* if( font->instance->spacing != FT_CHARCELL ) */
+ return Successful;
+#endif
+ }
+
+ xrc = FreeTypeInstanceGetGlyph(idx, flags, g, font->instance);
+ if( xrc == Successful && *g != NULL )
+ return Successful;
+ if( font->zero_idx != idx ) {
+ xrc = FreeTypeInstanceGetGlyph(font->zero_idx, flags, g, font->instance);
+ if( xrc == Successful && *g != NULL )
+ return Successful;
}
+ return FreeTypeInstanceGetGlyph(font->zero_idx, flags|FT_GET_DUMMY, g, font->instance);
}
static int
-FreeTypeFontGetGlyphMetrics(unsigned code, xCharInfo **metrics, FTFontPtr font)
+FreeTypeFontGetGlyphMetrics(unsigned code, int flags, xCharInfo **metrics, FTFontPtr font)
{
unsigned idx;
- int i;
+ int xrc;
- /* As a special case, we pass 0 even when it is not in the ranges;
- this will allow for the default glyph, which should exist in any
- TrueType font. */
+ if( flags & FT_FORCE_CONSTANT_SPACING )
+ idx = 0; /* This is ignored in FreeTypeInstanceGetGlyphMetrics */
+ else {
+ if ( ft_get_index(code,font,&idx) ) {
+ /* The code has not been parsed! */
+ *metrics = NULL;
+ flags &= ~FT_FORCE_CONSTANT_SPACING;
+#ifdef XAA_ACCEPTS_NO_SUCH_CHAR
+ /* if( font->instance->spacing != FT_CHARCELL ) */
+ return Successful;
+#endif
+ }
+ }
- if(code>0 && font->nranges) {
- for(i = 0; i < font->nranges; i++)
- if((code >=
- font->ranges[i].min_char_low+
- (font->ranges[i].min_char_high<<8)) &&
- (code <=
- font->ranges[i].max_char_low+(font->ranges[i].max_char_high<<8)))
- break;
- if(i == font->nranges) {
- *metrics = 0;
- return Successful;
- }
+ xrc = FreeTypeInstanceGetGlyphMetrics(idx, flags, metrics, font->instance);
+ if( xrc == Successful && *metrics != NULL )
+ return Successful;
+ if( font->zero_idx != idx ) {
+ xrc = FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags,
+ metrics, font->instance);
+ if( xrc == Successful && *metrics != NULL )
+ return Successful;
}
-
- idx = FTRemap(font->instance->face->face, &font->mapping, code);
-
- if(idx == 0 &&
- (code != 0 ||
- (font->mapping.mapping &&
- (font->mapping.mapping->encoding->first != 0 ||
- font->mapping.mapping->encoding->first_col != 0)))) {
- *metrics = 0;
- return Successful;
- } else {
- return FreeTypeInstanceGetGlyphMetrics(idx, metrics, font->instance);
+ return FreeTypeInstanceGetGlyphMetrics(font->zero_idx, flags|FT_GET_DUMMY, metrics, font->instance);
+}
+
+/*
+ * restrict code range
+ *
+ * boolean for the numeric zone:
+ * results = results & (ranges[0] | ranges[1] | ... ranges[nranges-1])
+ */
+
+static void
+restrict_code_range(unsigned short *refFirstCol,
+ unsigned short *refFirstRow,
+ unsigned short *refLastCol,
+ unsigned short *refLastRow,
+ fsRange const *ranges, int nRanges)
+{
+ if (nRanges) {
+ int minCol = 256, minRow = 256, maxCol = -1, maxRow = -1;
+ fsRange const *r = ranges;
+ int i;
+
+ for (i=0; i<nRanges; i++) {
+ if (r->min_char_high != r->max_char_high) {
+ minCol = 0x00;
+ maxCol = 0xff;
+ } else {
+ if (minCol > r->min_char_low)
+ minCol = r->min_char_low;
+ if (maxCol < r->max_char_low)
+ maxCol = r->max_char_low;
+ }
+ if (minRow > r->min_char_high)
+ minRow = r->min_char_high;
+ if (maxRow < r->max_char_high)
+ maxRow = r->max_char_high;
+ r++;
+ }
+
+ if (minCol > *refLastCol)
+ *refFirstCol = *refLastCol;
+ else if (minCol > *refFirstCol)
+ *refFirstCol = minCol;
+
+ if (maxCol < *refFirstCol)
+ *refLastCol = *refFirstCol;
+ else if (maxCol < *refLastCol)
+ *refLastCol = maxCol;
+
+ if (minRow > *refLastRow) {
+ *refFirstRow = *refLastRow;
+ *refFirstCol = *refLastCol;
+ } else if (minRow > *refFirstRow)
+ *refFirstRow = minRow;
+
+ if (maxRow < *refFirstRow) {
+ *refLastRow = *refFirstRow;
+ *refLastCol = *refFirstCol;
+ } else if (maxRow < *refLastRow)
+ *refLastRow = maxRow;
}
}
+
static int
-FreeTypeFontGetDefaultGlyph(CharInfoPtr *g, FTFontPtr font)
+restrict_code_range_by_str(int count,unsigned short *refFirstCol,
+ unsigned short *refFirstRow,
+ unsigned short *refLastCol,
+ unsigned short *refLastRow,
+ char const *str)
{
- /* Disable default glyph generation if there is a first index */
- if(font->mapping.mapping &&
- (font->mapping.mapping->encoding->first ||
- font->mapping.mapping->encoding->first_col)) {
- *g = 0;
- return Successful;
+ int nRanges = 0;
+ int result = 0;
+ fsRange *ranges = NULL;
+ char const *p, *q;
+
+ p = q = str;
+ for (;;) {
+ int minpoint=0, maxpoint=65535;
+ long val;
+
+ /* skip comma and/or space */
+ while (',' == *p || isspace(*p))
+ p++;
+
+ /* begin point */
+ if ('-' != *p) {
+ val = strtol(p, (char **)&q, 0);
+ if (p == q)
+ /* end or illegal */
+ break;
+ if (val<0 || val>65535) {
+ /* out of zone */
+ break;
+ }
+ minpoint = val;
+ p=q;
+ }
+
+ /* skip space */
+ while (isspace(*p))
+ p++;
+
+ if (',' != *p && '\0' != *p) {
+ /* contiune */
+ if ('-' == *p)
+ /* hyphon */
+ p++;
+ else
+ /* end or illegal */
+ break;
+
+ /* skip space */
+ while (isspace(*p))
+ p++;
+
+ val = strtol(p, (char **)&q, 0);
+ if (p != q) {
+ if (val<0 || val>65535)
+ break;
+ maxpoint = val;
+ } else if (',' != *p && '\0' != *p)
+ /* end or illegal */
+ break;
+ p=q;
+ } else
+ /* comma - single code */
+ maxpoint = minpoint;
+
+ if ( count <= 0 && minpoint>maxpoint ) {
+ int tmp;
+ tmp = minpoint;
+ minpoint = maxpoint;
+ maxpoint = tmp;
+ }
+
+ /* add range */
+#if 0
+ fprintf(stderr, "zone: 0x%04X - 0x%04X\n", minpoint, maxpoint);
+ fflush(stderr);
+#endif
+ nRanges++;
+ ranges = (fsRange *)xrealloc(ranges, nRanges*sizeof(*ranges));
+ if (NULL == ranges)
+ break;
+ {
+ fsRange *r = ranges+nRanges-1;
+
+ r->min_char_low = minpoint & 0xff;
+ r->max_char_low = maxpoint & 0xff;
+ r->min_char_high = (minpoint>>8) & 0xff;
+ r->max_char_high = (maxpoint>>8) & 0xff;
+ }
}
-
- /* Using FreeTypeInstanceGetGlyph(0,...) would cause inconsistencies
- between metrics and glyphs in the unlikely case that 0 is not
- mapped to 0. */
- return FreeTypeFontGetGlyph(0, g, font);
+
+ if (ranges) {
+ if ( count <= 0 ) {
+ restrict_code_range(refFirstCol, refFirstRow, refLastCol, refLastRow,
+ ranges, nRanges);
+ }
+ else {
+ int i;
+ fsRange *r;
+ for ( i=0 ; i<nRanges ; i++ ) {
+ if ( count <= i ) break;
+ r = ranges+i;
+ refFirstCol[i] = r->min_char_low;
+ refLastCol[i] = r->max_char_low;
+ refFirstRow[i] = r->min_char_high;
+ refLastRow[i] = r->max_char_high;
+ }
+ result=i;
+ }
+ xfree(ranges);
+ }
+ return result;
}
-static int
-FreeTypeLoadFont(FTFontPtr *font_return, char *fileName,
- FontScalablePtr vals, FontEntryPtr entry,
- FontBitmapFormatPtr bmfmt)
+/* *face_number and *spacing are initialized but *load_flags is NOT. */
+static int
+FreeTypeSetUpTTCap( char *fileName, FontScalablePtr vals,
+ char **dynStrRealFileName, char **dynStrFTFileName,
+ struct TTCapInfo *ret, int *face_number,
+ FT_Int32 *load_flags, int *spacing, char **dynStrTTCapCodeRange )
{
- int xrc;
- FTFontPtr font;
- FTNormalisedTransformationRec trans;
- int charcell;
-
- font = (FTFontPtr)xalloc(sizeof(FTFontRec));
- if(font == NULL)
+ int result = Successful;
+ SDynPropRecValList listPropRecVal;
+ SPropRecValContainer contRecValue;
+ Bool hinting=True;
+ Bool isEmbeddedBitmap = True;
+ Bool alwaysEmbeddedBitmap = False;
+ int pixel = vals->pixel;
+
+ *dynStrRealFileName=NULL;
+ *dynStrFTFileName=NULL;
+ *dynStrTTCapCodeRange=NULL;
+
+ if (SPropRecValList_new(&listPropRecVal)) {
return AllocError;
+ }
+
+ {
+ int len = strlen(fileName);
+ char *capHead = NULL;
+ {
+ /* font cap */
+ char *p1=NULL, *p2=NULL;
+
+ p1=strrchr(fileName, '/');
+ if ( p1 == NULL ) p1 = fileName;
+ else p1++;
+ if (NULL != (p2=strrchr(p1, ':'))) {
+ /* colon exist in the right side of slash. */
+ int dirLen = p1-fileName;
+ int baseLen = fileName+len - p2 -1;
+
+ *dynStrRealFileName = (char *)xalloc(dirLen+baseLen+1);
+ if( *dynStrRealFileName == NULL ) {
+ result = AllocError;
+ goto quit;
+ }
+ if ( 0 < dirLen )
+ memcpy(*dynStrRealFileName, fileName, dirLen);
+ strcpy(*dynStrRealFileName+dirLen, p2+1);
+ capHead = p1;
+ } else {
+ *dynStrRealFileName = xstrdup(fileName);
+ if( *dynStrRealFileName == NULL ) {
+ result = AllocError;
+ goto quit;
+ }
+ }
+ }
+
+ /* font cap */
+ if (capHead) {
+ if (SPropRecValList_add_by_font_cap(&listPropRecVal,
+ capHead)) {
+ result = BadFontPath;
+ goto quit;
+ }
+ }
+ }
+
+ *face_number=0;
+ *spacing=0;
+ ret->autoItalic=0.0;
+ ret->scaleWidth=1.0;
+ ret->scaleBBoxWidth = 1.0;
+ ret->scaleBBoxHeight = 1.0;
+ ret->doubleStrikeShift = 1;
+ ret->adjustBBoxWidthByPixel = 0;
+ ret->adjustLeftSideBearingByPixel = 0;
+ ret->adjustRightSideBearingByPixel = 0;
+ ret->flags = 0;
+ ret->scaleBitmap = 0.0;
+ ret->forceConstantSpacingBegin = -1;
+ ret->forceConstantSpacingEnd = -1;
+ ret->force_c_representative_metrics_char_code = -2;
+ ret->force_c_scale_b_box_width = 1.0;
+ ret->force_c_scale_b_box_height = 1.0;
+ ret->force_c_adjust_width_by_pixel = 0;
+ ret->force_c_adjust_lsb_by_pixel = 0;
+ ret->force_c_adjust_rsb_by_pixel = 0;
+ ret->force_c_scale_lsb = 0.0;
+ ret->force_c_scale_rsb = 1.0;
+ /* */
+ ret->vl_slant=0;
+ ret->lsbShiftOfBitmapAutoItalic=0;
+ ret->rsbShiftOfBitmapAutoItalic=0;
+ /* face number */
+ {
+ char *beginptr=NULL,*endptr;
+ if ( SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "FaceNumber")) {
+ int lv;
+ beginptr = SPropContainer_value_str(contRecValue);
+ lv=strtol(beginptr, &endptr, 10);
+ if ( *beginptr != '\0' && *endptr == '\0' ) {
+ if ( 0 < lv ) *face_number = lv;
+ }
+ }
+ if( beginptr && 0 < *face_number ) {
+ char *slash;
+ *dynStrFTFileName = /* add -> ':'+strlen0+':'+strlen1+'\0' */
+ (char *)xalloc(1+strlen(beginptr)+1+strlen(*dynStrRealFileName)+1);
+ if( *dynStrFTFileName == NULL ){
+ result = AllocError;
+ goto quit;
+ }
+ **dynStrFTFileName = '\0';
+ slash = strrchr(*dynStrRealFileName,'/');
+ if( slash ) {
+ char *p;
+ strcat(*dynStrFTFileName,*dynStrRealFileName);
+ p = strrchr(*dynStrFTFileName,'/');
+ p[1] = '\0';
+ strcat(*dynStrFTFileName,":");
+ strcat(*dynStrFTFileName,beginptr);
+ strcat(*dynStrFTFileName,":");
+ strcat(*dynStrFTFileName,slash+1);
+ }
+ else{
+ strcat(*dynStrFTFileName,":");
+ strcat(*dynStrFTFileName,beginptr);
+ strcat(*dynStrFTFileName,":");
+ strcat(*dynStrFTFileName,*dynStrRealFileName);
+ }
+ }
+ else{
+ *dynStrFTFileName = (char *)xalloc(strlen(*dynStrRealFileName)+1);
+ if( *dynStrFTFileName == NULL ){
+ result = AllocError;
+ goto quit;
+ }
+ **dynStrFTFileName = '\0';
+ strcat(*dynStrFTFileName,*dynStrRealFileName);
+ }
+ }
+ /*
+ fprintf(stderr,"[Filename:%s]\n",fileName);
+ fprintf(stderr,"[RealFilename:%s]\n",*dynStrRealFileName);
+ fprintf(stderr,"[FTFilename:%s]\n",*dynStrFTFileName);
+ */
+ /* slant control */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "AutoItalic"))
+ ret->autoItalic = SPropContainer_value_dbl(contRecValue);
+ /* hinting control */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "Hinting"))
+ hinting = SPropContainer_value_bool(contRecValue);
+ /* scaling */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ScaleWidth")) {
+ ret->scaleWidth = SPropContainer_value_dbl(contRecValue);
+ if (ret->scaleWidth<=0.0) {
+ fprintf(stderr, "ScaleWitdh needs plus.\n");
+ result = BadFontName;
+ goto quit;
+ }
+ }
+ /* bbox adjustment */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ScaleBBoxWidth")) {
+ /* Scaling to Bounding Box Width */
+ int lv;
+ char *endptr,*beginptr;
+ double v,scaleBBoxWidth=1.0,scaleBBoxHeight=1.0;
+ beginptr = SPropContainer_value_str(contRecValue);
+ do {
+ if ( strlen(beginptr) < 1 ) break;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ scaleBBoxWidth = v;
+ }
+ if ( *endptr != ';' && *endptr != ',' ) break;
+ if ( *endptr == ',' ) {
+ beginptr=endptr+1;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ scaleBBoxHeight = v;
+ }
+ }
+ if ( *endptr != ';' && *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->adjustBBoxWidthByPixel = lv;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->adjustLeftSideBearingByPixel = lv;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->adjustRightSideBearingByPixel = lv;
+ }
+ } while ( 0 );
+ if (scaleBBoxWidth<=0.0) {
+ fprintf(stderr, "ScaleBBoxWitdh needs plus.\n");
+ result = BadFontName;
+ goto quit;
+ }
+ if (scaleBBoxHeight<=0.0) {
+ fprintf(stderr, "ScaleBBoxHeight needs plus.\n");
+ result = BadFontName;
+ goto quit;
+ }
+ ret->scaleBBoxWidth = scaleBBoxWidth;
+ ret->scaleBBoxHeight = scaleBBoxHeight;
+ }
+ /* spacing */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ForceSpacing")) {
+ char *strSpace = SPropContainer_value_str(contRecValue);
+ Bool err = False;
+ if (1 != strlen(strSpace))
+ err = True;
+ else
+ switch (strSpace[0]) {
+ case 'M':
+ ret->flags |= TTCAP_MONO_CENTER;
+ *spacing = 'm';
+ break;
+ case 'm':
+ case 'p':
+ case 'c':
+ *spacing = strSpace[0];
+ break;
+ default:
+ err = True;
+ }
+ if (err) {
+ result = BadFontName;
+ goto quit;
+ }
+ }
+ /* doube striking */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "DoubleStrike")) {
+ /* Set or Reset Auto Bold Flag */
+ char *strDoubleStrike = SPropContainer_value_str(contRecValue);
+ Bool err = False;
+ if ( 0 < strlen(strDoubleStrike) ) {
+ switch (strDoubleStrike[0]) {
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ ret->flags |= TTCAP_DOUBLE_STRIKE;
+ ret->flags |= TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
+ break;
+ case 'y':
+ case 'Y':
+ ret->flags |= TTCAP_DOUBLE_STRIKE;
+ break;
+ case 'n':
+ case 'N':
+ ret->flags &= ~TTCAP_DOUBLE_STRIKE;
+ ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
+ ret->flags &= ~TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH;
+ break;
+ default:
+ err = True;
+ }
+ if ( err != True ) {
+ if ( strDoubleStrike[1] ) {
+ switch (strDoubleStrike[1]) {
+ case 'b':
+ case 'B':
+ case 'p':
+ case 'P':
+ case 'y':
+ case 'Y':
+ ret->flags |= TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH;
+ break;
+ default:
+ break;
+ }
+ }
+ do {
+ char *comma_ptr=strchr(strDoubleStrike,';');
+ if ( !comma_ptr ) comma_ptr=strchr(strDoubleStrike,',');
+ if ( !comma_ptr ) break;
+ if ( comma_ptr[1] ) {
+ char *endptr;
+ int mkboldMaxPixel;
+ mkboldMaxPixel=strtol(comma_ptr+1, &endptr, 10);
+ if ( endptr != comma_ptr+1 && mkboldMaxPixel <= pixel ) {
+ ret->flags &= ~TTCAP_DOUBLE_STRIKE_MKBOLD_EDGE_LEFT;
+ }
+ }
+ comma_ptr=strchr(comma_ptr+1,',');
+ if ( !comma_ptr ) break;
+ if ( comma_ptr[1] ) {
+ char *endptr;
+ int max_pixel;
+ max_pixel=strtol(comma_ptr+1, &endptr, 10);
+ if ( endptr != comma_ptr+1 && max_pixel <= pixel ) {
+ if( ret->flags & TTCAP_DOUBLE_STRIKE )
+ ret->doubleStrikeShift += pixel / max_pixel;
+ }
+ }
+ } while(0);
+ }
+ }
+ else
+ err = True;
+ if (err) {
+ result = BadFontName;
+ goto quit;
+ }
+ }
+ /* very lazy metrics */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "VeryLazyMetrics")){
+ Bool isVeryLazy = SPropContainer_value_bool(contRecValue);
+ ret->flags |= TTCAP_DISABLE_DEFAULT_VERY_LAZY;
+ if( isVeryLazy == True )
+ ret->flags |= TTCAP_IS_VERY_LAZY;
+ else
+ ret->flags &= ~TTCAP_IS_VERY_LAZY;
+ }
+ /* embedded bitmap */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "EmbeddedBitmap")) {
+ char *strEmbeddedBitmap = SPropContainer_value_str(contRecValue);
+ Bool err = False;
+ if ( 1 == strlen(strEmbeddedBitmap) ) {
+ switch (strEmbeddedBitmap[0]) {
+ case 'y':
+ case 'Y':
+ isEmbeddedBitmap = True;
+ alwaysEmbeddedBitmap = True;
+ break;
+ case 'u':
+ case 'U':
+ isEmbeddedBitmap = True;
+ alwaysEmbeddedBitmap = False;
+ break;
+ case 'n':
+ case 'N':
+ isEmbeddedBitmap = False;
+ break;
+ default:
+ err = True;
+ }
+ }
+ else
+ err = True;
+ if (err) {
+ result = BadFontName;
+ goto quit;
+ }
+ }
+ /* scale bitmap */
+ if((ret->flags & TTCAP_IS_VERY_LAZY) &&
+ SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "VeryLazyBitmapWidthScale")) {
+ /* Scaling to Bitmap Bounding Box Width */
+ double scaleBitmapWidth = SPropContainer_value_dbl(contRecValue);
+
+ fprintf(stderr, "Warning: `bs' option is not required in X-TT version 2.\n");
+#if 0
+ if (scaleBitmapWidth<=0.0) {
+ fprintf(stderr, "ScaleBitmapWitdh needs plus.\n");
+ result = BadFontName;
+ goto quit;
+ }
+#endif
+ ret->scaleBitmap = scaleBitmapWidth;
+ }
+ /* restriction of the code range */
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "CodeRange")) {
+ *dynStrTTCapCodeRange = xstrdup(SPropContainer_value_str(contRecValue));
+ if( *dynStrTTCapCodeRange == NULL ) {
+ result = AllocError;
+ goto quit;
+ }
+ }
+ /* forceConstantSpacing{Begin,End} */
+ if ( 1 /* ft->spacing == 'p' */ ){
+ unsigned short first_col=0,last_col=0x00ff;
+ unsigned short first_row=0,last_row=0x00ff;
+ if (SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ForceConstantSpacingCodeRange")) {
+ if ( restrict_code_range_by_str(1,&first_col, &first_row,
+ &last_col, &last_row,
+ SPropContainer_value_str(contRecValue)) == 1 ) {
+ ret->forceConstantSpacingBegin = (int)( first_row<<8 | first_col );
+ ret->forceConstantSpacingEnd = (int)( last_row<<8 | last_col );
+ if ( ret->forceConstantSpacingBegin <= ret->forceConstantSpacingEnd )
+ ret->flags &= ~TTCAP_FORCE_C_OUTSIDE;
+ else ret->flags |= TTCAP_FORCE_C_OUTSIDE;
+ }
+ }
+ }
+ /* */
+ if ( 1 ){
+ unsigned short first_col=0, last_col=0x0ff;
+ unsigned short first_row=0, last_row=0x0ff;
+ if ( SPropRecValList_search_record(&listPropRecVal,
+ &contRecValue,
+ "ForceConstantSpacingMetrics")) {
+ char *strMetrics;
+ strMetrics = SPropContainer_value_str(contRecValue);
+ if ( strMetrics ) {
+ char *comma_ptr,*period_ptr,*semic_ptr;
+ semic_ptr=strchr(strMetrics,';');
+ comma_ptr=strchr(strMetrics,',');
+ period_ptr=strchr(strMetrics,'.');
+ if ( semic_ptr && comma_ptr )
+ if ( semic_ptr < comma_ptr ) comma_ptr=NULL;
+ if ( semic_ptr && period_ptr )
+ if ( semic_ptr < period_ptr ) period_ptr=NULL;
+ if ( !comma_ptr && !period_ptr && strMetrics != semic_ptr ) {
+ if ( restrict_code_range_by_str(1,&first_col, &first_row,
+ &last_col, &last_row,
+ SPropContainer_value_str(contRecValue)) == 1 ) {
+ ret->force_c_representative_metrics_char_code =
+ (int)( first_row<<8 | first_col );
+ }
+ }
+ else {
+ double v;
+ char *endptr,*beginptr=strMetrics;
+ do {
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ ret->force_c_scale_b_box_width = v;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ ret->force_c_scale_lsb = v;
+ ret->flags |= TTCAP_FORCE_C_LSB_FLAG;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ ret->force_c_scale_rsb = v;
+ ret->flags |= TTCAP_FORCE_C_RSB_FLAG;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ v=strtod(beginptr, &endptr);
+ if ( endptr!=beginptr ) {
+ ret->force_c_scale_b_box_height = v;
+ }
+ } while (0);
+ }
+ if ( semic_ptr ) {
+ int lv;
+ char *endptr,*beginptr=semic_ptr+1;
+ do {
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->force_c_adjust_width_by_pixel=lv;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->force_c_adjust_lsb_by_pixel=lv;
+ }
+ if ( *endptr != ',' ) break;
+ beginptr=endptr+1;
+ lv=strtol(beginptr, &endptr, 10);
+ if ( endptr!=beginptr ) {
+ ret->force_c_adjust_rsb_by_pixel=lv;
+ }
+ } while (0);
+ }
+ }
+ }
+ }
+
+ ret->force_c_scale_b_box_width *= ret->scaleBBoxWidth;
+ ret->force_c_scale_b_box_height *= ret->scaleBBoxHeight;
+
+ ret->force_c_scale_b_box_width *= ret->scaleWidth;
+ ret->scaleBBoxWidth *= ret->scaleWidth;
+
+ ret->force_c_adjust_rsb_by_pixel += ret->adjustRightSideBearingByPixel;
+ ret->force_c_adjust_lsb_by_pixel += ret->adjustLeftSideBearingByPixel;
+ /* scaleWidth, scaleBBoxWidth, force_c_scale_b_box_width, force_c_scale_b_box_width */
+
+ /* by TTCap */
+ if( hinting == False ) *load_flags |= FT_LOAD_NO_HINTING;
+ if( isEmbeddedBitmap == False ) *load_flags |= FT_LOAD_NO_BITMAP;
+ if( ret->autoItalic != 0 && alwaysEmbeddedBitmap == False )
+ *load_flags |= FT_LOAD_NO_BITMAP;
+
+ quit:
+ return result;
+}
+
+static int
+ft_get_trans_from_vals( FontScalablePtr vals, FTNormalisedTransformationPtr trans )
+{
/* Compute the transformation matrix. We use floating-point
arithmetic for simplicity */
- trans.xres = vals->x;
- trans.yres = vals->y;
+ trans->xres = vals->x;
+ trans->yres = vals->y;
/* This value cannot be 0. */
- trans.scale = MAX(hypot(vals->point_matrix[0], vals->point_matrix[2]),
- hypot(vals->point_matrix[1], vals->point_matrix[3]));
- trans.nonIdentity = 0;
+ trans->scale = hypot(vals->point_matrix[2], vals->point_matrix[3]);
+ trans->nonIdentity = 0;
/* Try to round stuff. We want approximate zeros to be exact zeros,
and if the elements on the diagonal are approximately equal, we
want them equal. We do this to avoid breaking hinting. */
if(DIFFER(vals->point_matrix[0], vals->point_matrix[3])) {
- trans.nonIdentity = 1;
- trans.matrix.xx =
- (int)((vals->point_matrix[0]*(double)TWO_SIXTEENTH)/trans.scale);
- trans.matrix.yy =
- (int)((vals->point_matrix[3]*(double)TWO_SIXTEENTH)/trans.scale);
+ trans->nonIdentity = 1;
+ trans->matrix.xx =
+ (int)((vals->point_matrix[0]*(double)TWO_SIXTEENTH)/trans->scale);
+ trans->matrix.yy =
+ (int)((vals->point_matrix[3]*(double)TWO_SIXTEENTH)/trans->scale);
} else {
- trans.matrix.xx = trans.matrix.yy =
+ trans->matrix.xx = trans->matrix.yy =
((vals->point_matrix[0] + vals->point_matrix[3])/2*
- (double)TWO_SIXTEENTH)/trans.scale;
+ (double)TWO_SIXTEENTH)/trans->scale;
}
- if(DIFFER0(vals->point_matrix[1], trans.scale)) {
- trans.matrix.yx =
- (int)((vals->point_matrix[1]*(double)TWO_SIXTEENTH)/trans.scale);
- trans.nonIdentity = 1;
+ if(DIFFER0(vals->point_matrix[1], trans->scale)) {
+ trans->matrix.yx =
+ (int)((vals->point_matrix[1]*(double)TWO_SIXTEENTH)/trans->scale);
+ trans->nonIdentity = 1;
} else
- trans.matrix.yx = 0;
+ trans->matrix.yx = 0;
- if(DIFFER0(vals->point_matrix[2], trans.scale)) {
- trans.matrix.xy =
- (int)((vals->point_matrix[2]*(double)TWO_SIXTEENTH)/trans.scale);
- trans.nonIdentity = 1;
+ if(DIFFER0(vals->point_matrix[2], trans->scale)) {
+ trans->matrix.xy =
+ (int)((vals->point_matrix[2]*(double)TWO_SIXTEENTH)/trans->scale);
+ trans->nonIdentity = 1;
} else
- trans.matrix.xy=0;
-
+ trans->matrix.xy=0;
+ return 0;
+}
+
+
+static int
+is_fixed_width(FT_Face face)
+{
+ PS_FontInfoRec t1info_rec;
+ int ftrc;
+
+ if(FT_IS_FIXED_WIDTH(face)) {
+ return 1;
+ }
+
+ ftrc = FT_Get_PS_Font_Info(face, &t1info_rec);
+ if(ftrc == 0 && t1info_rec.is_fixed_pitch) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+FreeTypeLoadFont(FTFontPtr font, FontInfoPtr info, FTFacePtr face,
+ char *FTFileName, FontScalablePtr vals, FontEntryPtr entry,
+ FontBitmapFormatPtr bmfmt, FT_Int32 load_flags,
+ struct TTCapInfo *tmp_ttcap, char *dynStrTTCapCodeRange,
+ int ttcap_spacing )
+{
+ int xrc;
+ FTNormalisedTransformationRec trans;
+ int spacing, actual_spacing, zero_code;
+ long lastCode, firstCode;
+ TT_Postscript *post;
+
+ ft_get_trans_from_vals(vals,&trans);
+
/* Check for charcell in XLFD */
- charcell = 0;
+ spacing = FT_PROPORTIONAL;
if(entry->name.ndashes == 14) {
char *p;
int dashes = 0;
@@ -1167,242 +2489,53 @@ FreeTypeLoadFont(FTFontPtr *font_return, char *fileName,
dashes++;
if(dashes == 11) {
if(p[1]=='c' && p[2]=='-')
- charcell=1;
+ spacing=FT_CHARCELL;
+ else if(p[1]=='m' && p[2]=='-')
+ spacing=FT_MONOSPACED;
break;
}
}
}
}
-
- xrc = FreeTypeOpenInstance(&font->instance,
- fileName, &trans, charcell, bmfmt);
- if(xrc != Successful)
- return xrc;
-
+ /* by TTCap */
+ if( ttcap_spacing != 0 ) {
+ if( ttcap_spacing == 'c' ) spacing=FT_CHARCELL;
+ else if( ttcap_spacing == 'm' ) spacing=FT_MONOSPACED;
+ else spacing=FT_PROPORTIONAL;
+ }
+
+ actual_spacing = spacing;
+ if( spacing == FT_PROPORTIONAL ) {
+ if( is_fixed_width(face->face) )
+ actual_spacing = FT_MONOSPACED;
+ }
+
if(entry->name.ndashes == 14) {
- if(FTPickMapping(entry->name.name, entry->name.length, fileName,
- font->instance->face->face, &font->mapping))
- return BadFontFormat;
+ xrc = FTPickMapping(entry->name.name, entry->name.length, FTFileName,
+ face->face, &font->mapping);
+ if (xrc != Successful)
+ return xrc;
} else {
- if(FTPickMapping(0, 0, fileName,
- font->instance->face->face, &font->mapping))
- return BadFontFormat;
+ xrc = FTPickMapping(0, 0, FTFileName,
+ face->face, &font->mapping);
+ if (xrc != Successful)
+ return xrc;
}
-
font->nranges = vals->nranges;
font->ranges = 0;
if(font->nranges) {
font->ranges = (fsRange*)xalloc(vals->nranges*sizeof(fsRange));
- if(font->ranges == NULL) {
- FreeTypeFreeFont(font);
+ if(font->ranges == NULL)
return AllocError;
- }
memcpy((char*)font->ranges, (char*)vals->ranges,
vals->nranges*sizeof(fsRange));
}
- *font_return = font;
-
- return Successful;
-}
-/* Given a BBox in FUnits, return a transformed BBox in pixels */
-static void
-transformBBox(FTNormalisedTransformationPtr transformation,
- int upm, int x_ppem, int y_ppem,
- int x1, int y1, int x2, int y2,
- int *tx1p, int *ty1p, int *tx2p, int *ty2p)
-{
- double
- xx1, yy1, xx2, yy2,
- tx11, ty11, tx12, ty12, tx21, ty21, tx22, ty22,
- tx1, ty1, tx2, ty2;
-
- /* Convert arguments to EM units */
-
- xx1 = ((double)x1/(double)upm);
- yy1 = ((double)y1/(double)upm);
- xx2 = ((double)x2/(double)upm);
- yy2 = ((double)y2/(double)upm);
-
- /* Apply transformation matrix */
-
- if(!transformation->nonIdentity) {
- tx1 = xx1;
- ty1 = yy1;
- tx2 = xx2;
- ty2 = yy2;
- } else {
- /* Not an identity matrix, need to compute images of all corners */
- tx11 =
- (transformation->matrix.xx/TWO_SIXTEENTH)*xx1 +
- (transformation->matrix.xy/TWO_SIXTEENTH)*yy1;
- ty11 =
- (transformation->matrix.yx/TWO_SIXTEENTH)*xx1 +
- (transformation->matrix.yy/TWO_SIXTEENTH)*yy1;
- tx12 =
- (transformation->matrix.xx/TWO_SIXTEENTH)*xx1 +
- (transformation->matrix.xy/TWO_SIXTEENTH)*yy2;
- ty12 =
- (transformation->matrix.yx/TWO_SIXTEENTH)*xx1 +
- (transformation->matrix.yy/TWO_SIXTEENTH)*yy2;
- tx21 =
- (transformation->matrix.xx/TWO_SIXTEENTH)*xx2 +
- (transformation->matrix.xy/TWO_SIXTEENTH)*yy1;
- ty21 =
- (transformation->matrix.yx/TWO_SIXTEENTH)*xx2 +
- (transformation->matrix.yy/TWO_SIXTEENTH)*yy1;
- tx22 =
- (transformation->matrix.xx/TWO_SIXTEENTH)*xx2 +
- (transformation->matrix.xy/TWO_SIXTEENTH)*yy2;
- ty22 =
- (transformation->matrix.yx/TWO_SIXTEENTH)*xx2 +
- (transformation->matrix.yy/TWO_SIXTEENTH)*yy2;
-
- /* Compute the corners of the new bounding box */
-
- tx1 = MIN(MIN(tx11,tx12),MIN(tx21,tx22));
- ty1 = MIN(MIN(ty11,ty12),MIN(ty21,ty22));
- tx2 = MAX(MAX(tx11,tx12),MAX(tx21,tx22));
- ty2 = MAX(MAX(ty11,ty12),MAX(ty21,ty22));
- }
-
-
- /* Convert to device space */
- *tx1p = (int)floor(tx1*(double)x_ppem);
- *ty1p = (int)floor(ty1*(double)y_ppem);
- *tx2p = (int)ceil(tx2*(double)x_ppem);
- *ty2p = (int)ceil(ty2*(double)y_ppem);
-
- /* Ensure the resulting bounding box is not empty */
- if(*tx1p == *tx2p)
- (*tx2p)++;
- if(*ty1p == *ty2p)
- (*ty2p)++;
-}
-
-static int
-is_fixed_width(FT_Face face)
-{
- PS_FontInfoRec t1info_rec;
- int ftrc;
-
- if(FT_IS_FIXED_WIDTH(face)) {
- return 1;
- }
-
- ftrc = FT_Get_PS_Font_Info(face, &t1info_rec);
- if(ftrc == 0 && t1info_rec.is_fixed_pitch) {
- return 1;
- }
-
- return 0;
-}
-
-/* Do all the real work for OpenFont or FontInfo */
-/* xf->info is only accessed through info, and xf might be null */
-
-static int
-FreeTypeLoadXFont(char *fileName,
- FontScalablePtr vals, FontPtr xf, FontInfoPtr info,
- FontBitmapFormatPtr bmfmt, FontEntryPtr entry)
-{
-#define TRANSFORM_FUNITS_X(xval) \
- ((int) \
- floor((((double)(xval)/(double)upm) * \
- ((double)instance->transformation.matrix.xx/TWO_SIXTEENTH)*(double)smetrics.x_ppem)+0.5))
-#define TRANSFORM_FUNITS_X_DOWN(xval) \
- ((int) \
- floor((((double)(xval)/(double)upm) * \
- ((double)instance->transformation.matrix.xx/TWO_SIXTEENTH)*(double)smetrics.x_ppem)))
-#define TRANSFORM_FUNITS_X_UP(xval) \
- ((int) \
- ceil((((double)(xval)/(double)upm) * \
- ((double)instance->transformation.matrix.xx/TWO_SIXTEENTH)*(double)smetrics.x_ppem)))
-#define TRANSFORM_FUNITS_Y(yval) \
- ((int) \
- floor((((double)(yval)/(double)upm) * \
- ((double)instance->transformation.matrix.yy/TWO_SIXTEENTH)*(double)smetrics.x_ppem)+0.5))
-#define TRANSFORM_FUNITS_Y_DOWN(yval) \
- ((int) \
- floor((((double)(yval)/(double)upm) * \
- ((double)instance->transformation.matrix.yy/TWO_SIXTEENTH) * (double)smetrics.y_ppem)))
-#define TRANSFORM_FUNITS_Y_UP(yval) \
- ((int) \
- ceil((((double)(yval)/(double)upm) * \
- ((double)instance->transformation.matrix.yy/TWO_SIXTEENTH) * (double)smetrics.y_ppem)))
-#define TRANSFORM_FUNITS_RAW(value) \
- ((long) \
- floor(((double)(value)/(double)upm) * 1000.0 + 0.5))
-#define TRANSFORM_FUNITS_RAW_DOWN(value) \
- ((long) \
- floor(((double)(value)/(double)upm) * 1000.0))
-#define TRANSFORM_FUNITS_RAW_UP(value) \
- ((long) \
- ceil(((double)(value)/(double)upm) * 1000.0))
-
-
- FTFontPtr font;
- FTInstancePtr instance;
- FT_Size_Metrics smetrics;
- FTFacePtr face;
- int xrc, i;
- int charcell, constantWidth;
- long rawWidth, rawAverageWidth, aw, code, lastCode, firstCode;
- int upm, minLsb, maxRsb, ascent, descent, width, averageWidth;
-
-
- xrc = FreeTypeLoadFont(&font, fileName, vals, entry, bmfmt);
- if(xrc != Successful)
- return xrc;
-
- instance = font->instance;
- face = instance->face;
- smetrics = instance->size->metrics;
-
- upm = face->face->units_per_EM;
- charcell = (instance->monospaced == FT_CHARCELL);
- constantWidth = charcell || is_fixed_width(face->face);
- if(constantWidth && instance->monospaced == 0)
- instance->monospaced = FT_MONOSPACED;
-
- /* There's no way to get the average width right without rasterising
- all of the glyphs. We make a serious attempt at getting it right
- for monospaced fonts, and try to provide a reasonable
- approximation for others. */
-
- if(constantWidth)
- aw = face->face->max_advance_width;
- else
- aw = face->face->max_advance_width / 2;
-
- if(constantWidth)
- averageWidth = 10*TRANSFORM_FUNITS_X(aw);
- else
- averageWidth = TRANSFORM_FUNITS_X(aw*10L);
- rawAverageWidth = TRANSFORM_FUNITS_RAW(aw*10L);
-
- vals->width = averageWidth;
-
+ zero_code=-1;
if(info) {
- info->fontAscent =
- TRANSFORM_FUNITS_Y(face->face->ascender);
- info->fontDescent =
- -TRANSFORM_FUNITS_Y(face->face->descender);
firstCode = 0;
lastCode = 0xFFFFL;
- if(font->nranges) {
- lastCode = 0;
- /* The ranges information does not have an effect on firstCode,
- as we pass the default glyph at position 0. */
- for(i=0; i<font->nranges; i++) {
- code = font->ranges[i].max_char_low +
- (font->ranges[i].max_char_high<<8);
- if(lastCode < code)
- lastCode = code;
- }
- }
-
if(!font->mapping.mapping ||
font->mapping.mapping->encoding->row_size == 0) {
/* linear indexing */
@@ -1417,6 +2550,7 @@ FreeTypeLoadXFont(char *fileName,
info->firstCol =
(info->firstRow || info->lastRow) ? 0 : (firstCode & 0xFF);
info->lastCol = info->lastRow ? 0xFF : (lastCode & 0xFF);
+ if ( firstCode == 0 ) zero_code=0;
} else {
/* matrix indexing */
info->firstRow = font->mapping.mapping->encoding->first;
@@ -1425,66 +2559,767 @@ FreeTypeLoadXFont(char *fileName,
info->firstCol = font->mapping.mapping->encoding->first_col;
info->lastCol = MIN(font->mapping.mapping->encoding->row_size-1,
lastCode<0x100?lastCode:0xFF);
+ if( info->firstRow == 0 && info->firstCol == 0 ) zero_code=0;
}
/* firstCode and lastCode are not valid in case of a matrix
encoding */
- transformBBox(&instance->transformation, upm,
- smetrics.x_ppem, smetrics.y_ppem,
- charcell? 0 :
- face->face->bbox.xMin,
- face->face->bbox.yMin,
- charcell ?
- face->face->max_advance_width :
- face->face->bbox.xMax,
- face->face->bbox.yMax,
- &minLsb, &descent, &maxRsb, &ascent);
- descent = -descent;
-
- width = TRANSFORM_FUNITS_X(face->face->max_advance_width);
- rawWidth =
- TRANSFORM_FUNITS_RAW(face->face->max_advance_width);
- instance->width = width;
-
- info->constantWidth=constantWidth;
- info->constantMetrics=charcell;
-
- info->minbounds.leftSideBearing = minLsb;
- info->minbounds.rightSideBearing = charcell?maxRsb:minLsb;
- info->minbounds.characterWidth = constantWidth?width:-width;
- info->minbounds.ascent = charcell?ascent:-descent;
- info->minbounds.descent = charcell?descent:-ascent;
- info->minbounds.attributes =
- (unsigned short)(short)(constantWidth?rawWidth:-rawWidth);
-
- info->maxbounds.leftSideBearing = charcell?minLsb:maxRsb;
- info->maxbounds.rightSideBearing = maxRsb;
- info->maxbounds.characterWidth = width;
- info->maxbounds.ascent = ascent;
- info->maxbounds.descent = descent;
- info->maxbounds.attributes = (unsigned short)(short)rawWidth;
-
- if(charcell && instance->charcellMetrics == 0) {
- instance->charcellMetrics = (xCharInfo*)xalloc(sizeof(xCharInfo));
- if(instance->charcellMetrics == 0) {
- FreeTypeFreeFont(font);
- return AllocError;
+ if( dynStrTTCapCodeRange ) {
+ restrict_code_range_by_str(0,&info->firstCol, &info->firstRow,
+ &info->lastCol, &info->lastRow,
+ dynStrTTCapCodeRange);
+ }
+ restrict_code_range(&info->firstCol, &info->firstRow,
+ &info->lastCol, &info->lastRow,
+ font->ranges, font->nranges);
+ }
+ font->info = info;
+
+ /* zero code is frequently used. */
+ if ( zero_code < 0 ) {
+ /* The fontenc should have the information of DefaultCh.
+ But we do not have such a information.
+ So we cannot but set 0. */
+ font->zero_idx = 0;
+ }
+ else
+ font->zero_idx = FTRemap(face->face,
+ &font->mapping, zero_code);
+
+ post = FT_Get_Sfnt_Table(face->face, ft_sfnt_post);
+
+#ifdef DEFAULT_VERY_LAZY
+ if( !( tmp_ttcap->flags & TTCAP_DISABLE_DEFAULT_VERY_LAZY ) )
+ if( DEFAULT_VERY_LAZY <= 1 + info->lastRow - info->firstRow ) {
+ if( post ){
+ tmp_ttcap->flags |= TTCAP_IS_VERY_LAZY;
+ }
+ }
+#endif
+ /* We should always reset. */
+ tmp_ttcap->flags &= ~TTCAP_DISABLE_DEFAULT_VERY_LAZY;
+
+ if ( face->bitmap || actual_spacing == FT_CHARCELL )
+ tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY;
+ /* "vl=y" is available when TrueType or OpenType only */
+ if ( !face->bitmap && !(FT_IS_SFNT( face->face )) )
+ tmp_ttcap->flags &= ~TTCAP_IS_VERY_LAZY;
+
+ if( post ) {
+ if( post->italicAngle != 0 )
+ tmp_ttcap->vl_slant = -sin( (post->italicAngle/1024./5760.)*1.57079632679489661923 );
+ /* fprintf(stderr,"angle=%g(%g)\n",tmp_ttcap->vl_slant,(post->italicAngle/1024./5760.)*90); */
+ }
+
+ xrc = FreeTypeOpenInstance(&font->instance, face,
+ FTFileName, &trans, actual_spacing, bmfmt,
+ tmp_ttcap, load_flags );
+ return xrc;
+}
+
+static void
+adjust_min_max(xCharInfo *minc, xCharInfo *maxc, xCharInfo *tmp)
+{
+#define MINMAX(field,ci) \
+ if (minc->field > (ci)->field) \
+ minc->field = (ci)->field; \
+ if (maxc->field < (ci)->field) \
+ maxc->field = (ci)->field;
+
+ MINMAX(ascent, tmp);
+ MINMAX(descent, tmp);
+ MINMAX(leftSideBearing, tmp);
+ MINMAX(rightSideBearing, tmp);
+ MINMAX(characterWidth, tmp);
+
+ if ((INT16)minc->attributes > (INT16)tmp->attributes)
+ minc->attributes = tmp->attributes;
+ if ((INT16)maxc->attributes < (INT16)tmp->attributes)
+ maxc->attributes = tmp->attributes;
+#undef MINMAX
+}
+
+static void
+ft_compute_bounds(FTFontPtr font, FontInfoPtr pinfo, FontScalablePtr vals )
+{
+ FTInstancePtr instance;
+ int row, col;
+ unsigned int c;
+ xCharInfo minchar, maxchar, *tmpchar = NULL;
+ int overlap, maxOverlap;
+ long swidth = 0;
+ long total_width = 0;
+ int num_cols, num_chars = 0;
+ int flags, skip_ok = 0;
+ int force_c_outside ;
+
+ instance = font->instance;
+ force_c_outside = instance->ttcap.flags & TTCAP_FORCE_C_OUTSIDE;
+
+ minchar.ascent = minchar.descent =
+ minchar.leftSideBearing = minchar.rightSideBearing =
+ minchar.characterWidth = minchar.attributes = 32767;
+ maxchar.ascent = maxchar.descent =
+ maxchar.leftSideBearing = maxchar.rightSideBearing =
+ maxchar.characterWidth = maxchar.attributes = -32767;
+ maxOverlap = -32767;
+
+ /* Parse all glyphs */
+ num_cols = 1 + pinfo->lastCol - pinfo->firstCol;
+ for (row = pinfo->firstRow; row <= pinfo->lastRow; row++) {
+ if ( skip_ok && tmpchar ) {
+ if ( !force_c_outside ) {
+ if ( instance->ttcap.forceConstantSpacingBegin < row<<8
+ && row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) {
+ if (tmpchar->characterWidth) {
+ num_chars += num_cols;
+ swidth += ABS(tmpchar->characterWidth)*num_cols;
+ total_width += tmpchar->characterWidth*num_cols;
+ continue;
+ }
+ }
+ else skip_ok=0;
+ }
+ else { /* for GB18030 proportional */
+ if ( instance->ttcap.forceConstantSpacingBegin < row<<8
+ || row<<8 < (instance->ttcap.forceConstantSpacingEnd & 0x0ff00) ) {
+ if (tmpchar->characterWidth) {
+ num_chars += num_cols;
+ swidth += ABS(tmpchar->characterWidth)*num_cols;
+ total_width += tmpchar->characterWidth*num_cols;
+ continue;
}
- memcpy((char*)instance->charcellMetrics,
- (char*)&info->maxbounds, sizeof(xCharInfo));
+ }
+ else skip_ok=0;
}
+ }
+ for (col = pinfo->firstCol; col <= pinfo->lastCol; col++) {
+ c = row<<8|col;
+ flags=0;
+ if ( !force_c_outside ) {
+ if ( c <= instance->ttcap.forceConstantSpacingEnd
+ && instance->ttcap.forceConstantSpacingBegin <= c )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ }
+ else { /* for GB18030 proportional */
+ if ( c <= instance->ttcap.forceConstantSpacingEnd
+ || instance->ttcap.forceConstantSpacingBegin <= c )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ }
+#if 0
+ fprintf(stderr, "comp_bounds: %x ->", c);
+#endif
+ if ( skip_ok == 0 || flags == 0 ){
+ tmpchar=NULL;
+#if 0
+ fprintf(stderr, "%x\n", c);
+#endif
+ if( FreeTypeFontGetGlyphMetrics(c, flags, &tmpchar, font) != Successful )
+ continue;
+ }
+ if ( !tmpchar ) continue;
+ adjust_min_max(&minchar, &maxchar, tmpchar);
+ overlap = tmpchar->rightSideBearing - tmpchar->characterWidth;
+ if (maxOverlap < overlap)
+ maxOverlap = overlap;
+
+ if (!tmpchar->characterWidth)
+ continue;
+ num_chars++;
+ swidth += ABS(tmpchar->characterWidth);
+ total_width += tmpchar->characterWidth;
+
+ if ( flags & FT_FORCE_CONSTANT_SPACING ) skip_ok=1;
+ }
+ }
+
+#ifndef XAA_ACCEPTS_NO_SUCH_CHAR
+ /* Check code 0 */
+ if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, 0, &tmpchar, font->instance) != Successful || tmpchar == NULL)
+ if( FreeTypeInstanceGetGlyphMetrics(font->zero_idx, FT_GET_DUMMY, &tmpchar, font->instance) != Successful )
+ tmpchar = NULL;
+ if ( tmpchar ) {
+ adjust_min_max(&minchar, &maxchar, tmpchar);
+ overlap = tmpchar->rightSideBearing - tmpchar->characterWidth;
+ if (maxOverlap < overlap)
+ maxOverlap = overlap;
+ }
+#endif
+
+ /* AVERAGE_WIDTH ... 1/10 pixel unit */
+ if (num_chars > 0) {
+ swidth = (swidth * 10.0 + num_chars / 2.0) / num_chars;
+ if (total_width < 0)
+ swidth = -swidth;
+ vals->width = swidth;
+ } else
+ vals->width = 0;
+
+ /*
+ if (char_width.pixel) {
+ maxchar.characterWidth = char_width.pixel;
+ minchar.characterWidth = char_width.pixel;
+ }
+ */
+
+ pinfo->maxbounds = maxchar;
+ pinfo->minbounds = minchar;
+ pinfo->ink_maxbounds = maxchar;
+ pinfo->ink_minbounds = minchar;
+ pinfo->maxOverlap = maxOverlap;
+}
+
+static int
+compute_new_extents( FontScalablePtr vals, double scale, double lsb, double rsb, double desc, double asc,
+ int *lsb_result, int *rsb_result, int *desc_result, int *asc_result )
+{
+#define TRANSFORM_POINT(matrix, x, y, dest) \
+ ((dest)[0] = (matrix)[0] * (x) + (matrix)[2] * (y), \
+ (dest)[1] = (matrix)[1] * (x) + (matrix)[3] * (y))
+
+#define CHECK_EXTENT(lsb, rsb, desc, asc, data) \
+ ((lsb) > (data)[0] ? (lsb) = (data)[0] : 0 , \
+ (rsb) < (data)[0] ? (rsb) = (data)[0] : 0, \
+ (-desc) > (data)[1] ? (desc) = -(data)[1] : 0 , \
+ (asc) < (data)[1] ? (asc) = (data)[1] : 0)
+ double newlsb, newrsb, newdesc, newasc;
+ double point[2];
+
+ /* Compute new extents for this glyph */
+ TRANSFORM_POINT(vals->pixel_matrix, lsb, -desc, point);
+ newlsb = point[0];
+ newrsb = newlsb;
+ newdesc = -point[1];
+ newasc = -newdesc;
+ TRANSFORM_POINT(vals->pixel_matrix, lsb, asc, point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+ TRANSFORM_POINT(vals->pixel_matrix, rsb, -desc, point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+ TRANSFORM_POINT(vals->pixel_matrix, rsb, asc, point);
+ CHECK_EXTENT(newlsb, newrsb, newdesc, newasc, point);
+
+ /* ???: lsb = (int)floor(newlsb * scale); */
+ *lsb_result = (int)floor(newlsb * scale + 0.5);
+ *rsb_result = (int)floor(newrsb * scale + 0.5);
+ *desc_result = (int)ceil(newdesc * scale - 0.5);
+ *asc_result = (int)floor(newasc * scale + 0.5);
+
+ return 0;
+#undef CHECK_EXTENT
+#undef TRANSFORM_POINT
+}
+
+static int
+is_matrix_unit(FontScalablePtr vals)
+{
+ double base_size;
+ FT_Matrix m;
+
+ base_size = hypot(vals->point_matrix[2], vals->point_matrix[3]);
+
+ m.xx = vals->point_matrix[0] / base_size * 65536;
+ m.xy = vals->point_matrix[2] / base_size * 65536;
+ m.yx = vals->point_matrix[1] / base_size * 65536;
+ m.yy = vals->point_matrix[3] / base_size * 65536;
+
+ return (m.xx == 65536) && (m.yx == 0) &&
+ (m.xy == 0) && (m.yy == 65536);
+}
+
+/* Do all the real work for OpenFont or FontInfo */
+/* xf->info is only accessed through info, and xf might be null */
- /* Glyph metrics are accurate */
- info->inkMetrics=1;
+static int
+FreeTypeLoadXFont(char *fileName,
+ FontScalablePtr vals, FontPtr xf, FontInfoPtr info,
+ FontBitmapFormatPtr bmfmt, FontEntryPtr entry)
+{
+ FTFontPtr font = NULL;
+ FTFacePtr face = NULL;
+ FTInstancePtr instance;
+ FT_Size_Metrics *smetrics;
+ int xrc=Successful;
+ int charcell;
+ long rawWidth = 0, rawAverageWidth = 0;
+ int upm, minLsb, maxRsb, ascent, descent, width, averageWidth;
+ double scale, base_width, base_height;
+ Bool orig_is_matrix_unit;
+ int face_number, ttcap_spacing;
+ struct TTCapInfo tmp_ttcap;
+ struct TTCapInfo *ins_ttcap;
+ FT_Int32 load_flags = FT_LOAD_DEFAULT; /* orig: FT_LOAD_RENDER | FT_LOAD_MONOCHROME */
+ char *dynStrRealFileName = NULL; /* foo.ttc */
+ char *dynStrFTFileName = NULL; /* :1:foo.ttc */
+ char *dynStrTTCapCodeRange = NULL;
- memcpy((char *)&info->ink_maxbounds,
- (char *)&info->maxbounds, sizeof(xCharInfo));
- memcpy((char *)&info->ink_minbounds,
- (char *)&info->minbounds, sizeof(xCharInfo));
+ font = (FTFontPtr)xalloc(sizeof(FTFontRec));
+ if(font == NULL) {
+ xrc = AllocError;
+ goto quit;
+ }
+ memset(font, 0, sizeof(FTFontRec));
+
+ xrc = FreeTypeSetUpTTCap(fileName, vals,
+ &dynStrRealFileName, &dynStrFTFileName,
+ &tmp_ttcap, &face_number,
+ &load_flags, &ttcap_spacing,
+ &dynStrTTCapCodeRange);
+ if ( xrc != Successful ) {
+ goto quit;
+ }
- /* XXX - hack */
- info->defaultCh=0;
+ xrc = FreeTypeOpenFace(&face, dynStrFTFileName, dynStrRealFileName, face_number);
+ if(xrc != Successful) {
+ goto quit;
+ }
+
+ if( is_matrix_unit(vals) )
+ orig_is_matrix_unit = True;
+ else {
+ orig_is_matrix_unit = False;
+ /* Turn off EmbeddedBitmap when original matrix is not diagonal. */
+ load_flags |= FT_LOAD_NO_BITMAP;
+ }
+
+ if( face->bitmap ) load_flags &= ~FT_LOAD_NO_BITMAP;
+
+ /* Slant control by TTCap */
+ if(!face->bitmap) {
+ vals->pixel_matrix[2] +=
+ vals->pixel_matrix[0] * tmp_ttcap.autoItalic;
+ vals->point_matrix[2] +=
+ vals->point_matrix[0] * tmp_ttcap.autoItalic;
+ vals->pixel_matrix[3] +=
+ vals->pixel_matrix[1] * tmp_ttcap.autoItalic;
+ vals->point_matrix[3] +=
+ vals->point_matrix[1] * tmp_ttcap.autoItalic;
+ }
+
+ base_width=hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]);
+ base_height=hypot(vals->pixel_matrix[2], vals->pixel_matrix[3]);
+ if(MAX(base_width, base_height) < 1.0 ) {
+ xrc = BadFontName;
+ goto quit;
+ }
+
+ xrc = FreeTypeLoadFont(font, info, face, dynStrFTFileName, vals, entry, bmfmt,
+ load_flags, &tmp_ttcap, dynStrTTCapCodeRange,
+ ttcap_spacing );
+ if(xrc != Successful) {
+ goto quit;
+ }
+
+ instance = font->instance;
+ smetrics = &instance->size->metrics;
+ ins_ttcap = &instance->ttcap;
+
+ upm = face->face->units_per_EM;
+ if(upm == 0) {
+ /* Work around FreeType bug */
+ upm = WORK_AROUND_UPM;
+ }
+ scale = 1.0 / upm;
+
+ charcell = (instance->spacing == FT_CHARCELL);
+
+ if( instance->charcellMetrics == NULL ) {
+
+ /* New instance */
+
+ long force_c_rawWidth = 0;
+ int force_c_lsb,force_c_rsb,force_c_width;
+ double unit_x=0,unit_y=0,advance;
+ CharInfoPtr tmpglyph;
+
+ /*
+ * CALCULATE HEADER'S METRICS
+ */
+
+ /* for OUTLINE fonts */
+ if(!face->bitmap) {
+ int new_width;
+ double ratio,force_c_ratio;
+ double b_width_diagonal;
+ double width_x=0,width_y=0;
+ double force_c_width_x, force_c_rsb_x, force_c_lsb_x;
+ double tmp_rsb,tmp_lsb,tmp_asc,tmp_des;
+ double max_advance_height;
+ tmp_asc = face->face->bbox.yMax;
+ tmp_des = -(face->face->bbox.yMin);
+ if ( tmp_asc < face->face->ascender ) tmp_asc = face->face->ascender;
+ if ( tmp_des < -(face->face->descender) ) tmp_des = -(face->face->descender);
+ tmp_lsb = face->face->bbox.xMin;
+ tmp_rsb = face->face->bbox.xMax;
+ if ( tmp_rsb < face->face->max_advance_width ) tmp_rsb = face->face->max_advance_width;
+ /* apply scaleBBoxWidth */
+ /* we should not ...???
+ tmp_lsb *= ins_ttcap->scaleBBoxWidth;
+ tmp_rsb *= ins_ttcap->scaleBBoxWidth;
+ */
+ /* transform and rescale */
+ compute_new_extents( vals, scale, tmp_lsb, tmp_rsb, tmp_des, tmp_asc,
+ &minLsb, &maxRsb, &descent, &ascent );
+ /* */
+ b_width_diagonal = (tmp_rsb - tmp_lsb) /* face->face->max_advance_width */
+ * vals->pixel_matrix[0] * scale;
+ /* Consider vertical layouts */
+ if( 0 < face->face->max_advance_height )
+ max_advance_height = face->face->max_advance_height;
+ else
+ max_advance_height = tmp_asc + tmp_des;
+ if( vals->pixel_matrix[1] == 0 ){
+ unit_x = fabs(vals->pixel_matrix[0]);
+ unit_y = 0;
+ width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x;
+ }
+ else if( vals->pixel_matrix[3] == 0 ){
+ unit_y = fabs(vals->pixel_matrix[2]);
+ unit_x = 0;
+ width_x = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y;
+ }
+ else{
+ unit_x = fabs(vals->pixel_matrix[0] -
+ vals->pixel_matrix[1]*vals->pixel_matrix[2]/vals->pixel_matrix[3]);
+ unit_y = fabs(vals->pixel_matrix[2] -
+ vals->pixel_matrix[3]*vals->pixel_matrix[0]/vals->pixel_matrix[1]);
+ width_x = face->face->max_advance_width * ins_ttcap->scaleBBoxWidth * unit_x;
+ width_y = max_advance_height * ins_ttcap->scaleBBoxHeight * unit_y;
+ if( width_y < width_x ){
+ width_x = width_y;
+ unit_x = 0;
+ }
+ else{
+ unit_y = 0;
+ }
+ }
+ /* calculate correction ratio */
+ width = (int)floor( (advance = width_x * scale) + 0.5);
+ new_width = width;
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ new_width += ins_ttcap->doubleStrikeShift;
+ new_width += ins_ttcap->adjustBBoxWidthByPixel;
+ ratio = (double)new_width/width;
+ width = new_width;
+ /* force constant */
+ if( unit_x != 0 ) {
+ force_c_width_x = face->face->max_advance_width
+ * ins_ttcap->force_c_scale_b_box_width * unit_x;
+ force_c_lsb_x = face->face->max_advance_width
+ * ins_ttcap->force_c_scale_lsb * unit_x;
+ force_c_rsb_x = face->face->max_advance_width
+ * ins_ttcap->force_c_scale_rsb * unit_x;
+ }
+ else {
+ force_c_width_x = max_advance_height
+ * ins_ttcap->force_c_scale_b_box_height * unit_y;
+ force_c_lsb_x = max_advance_height
+ * ins_ttcap->force_c_scale_lsb * unit_y;
+ force_c_rsb_x = max_advance_height
+ * ins_ttcap->force_c_scale_rsb * unit_y;
+ }
+ /* calculate correction ratio */
+ force_c_width = (int)floor(force_c_width_x * scale + 0.5);
+ new_width = force_c_width;
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ force_c_width += ins_ttcap->doubleStrikeShift;
+ new_width += ins_ttcap->force_c_adjust_width_by_pixel;
+ force_c_ratio = (double)new_width/force_c_width;
+ force_c_width = new_width;
+ /* force_c_lsb, force_c_rsb */
+ if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG )
+ force_c_lsb = (int)floor( force_c_lsb_x * scale + 0.5 );
+ else
+ force_c_lsb = minLsb;
+ if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG )
+ force_c_rsb = (int)floor( force_c_rsb_x * scale + 0.5 );
+ else
+ force_c_rsb = maxRsb;
+ /* calculate shift of BitmapAutoItalic
+ (when diagonal matrix only) */
+ if( orig_is_matrix_unit == True ) {
+ if( ins_ttcap->autoItalic != 0 ) {
+ double ai;
+ int ai_lsb,ai_rsb,ai_total;
+ if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic;
+ else ai = -ins_ttcap->autoItalic;
+ ai_total = (int)( b_width_diagonal * ai + 0.5);
+ ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 );
+ ai_lsb = -(ai_total - ai_rsb);
+ if( 0 < ins_ttcap->autoItalic ) {
+ ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb;
+ ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb;
+ }
+ else {
+ ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb;
+ ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb;
+ }
+ }
+ }
+ /* integer adjustment by TTCap */
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
+ maxRsb += ins_ttcap->doubleStrikeShift;
+ maxRsb += ins_ttcap->adjustRightSideBearingByPixel;
+ minLsb += ins_ttcap->adjustLeftSideBearingByPixel;
+ /* */
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
+ force_c_rsb += ins_ttcap->doubleStrikeShift;
+ force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel;
+ force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel;
+ /* apply to rawWidth */
+ averageWidth = (int)floor(10 * width_x * scale
+ * ratio + 0.5);
+ rawWidth = floor(width_x * scale
+ * ratio * 1000. / base_height + 0.5);
+ rawAverageWidth = floor(width_x * scale * ratio * 10.
+ * 1000. / base_height + 0.5);
+ force_c_rawWidth = floor(force_c_width_x * scale
+ * force_c_ratio * 1000. / base_height + 0.5);
+ /* */
+ }
+ /* for BITMAP fonts [if(face->bitmap)] */
+ else {
+ /* These values differ from actual when outline,
+ so we must use them ONLY FOR BITMAP. */
+ width = (int)floor(smetrics->max_advance * ins_ttcap->scaleBBoxWidth / 64.0 + .5);
+ descent = -smetrics->descender / 64;
+ ascent = smetrics->ascender / 64;
+ /* force constant */
+ force_c_width = (int)floor(smetrics->max_advance
+ * ins_ttcap->force_c_scale_b_box_width / 64.0 + .5);
+ /* Preserve average width for bitmap fonts */
+ if(vals->width != 0)
+ averageWidth = (int)floor(vals->width * ins_ttcap->scaleBBoxWidth +.5);
+ else
+ averageWidth = (int)floor(10.0 * smetrics->max_advance
+ * ins_ttcap->scaleBBoxWidth / 64.0 + .5);
+ rawWidth = 0;
+ rawAverageWidth = 0;
+ force_c_rawWidth = 0;
+ /* We don't consider vertical layouts */
+ advance = (int)floor(smetrics->max_advance / 64.0 +.5);
+ unit_x = vals->pixel_matrix[0];
+ unit_y = 0;
+ /* We can use 'width' only when bitmap.
+ This should not be set when outline. */
+ minLsb = 0;
+ maxRsb = width;
+ /* force constant */
+ if( ins_ttcap->flags & TTCAP_FORCE_C_LSB_FLAG )
+ force_c_lsb = (int)floor(smetrics->max_advance
+ * ins_ttcap->force_c_scale_lsb / 64.0 + .5);
+ else
+ force_c_lsb = minLsb;
+ if( ins_ttcap->flags & TTCAP_FORCE_C_RSB_FLAG )
+ force_c_rsb = (int)floor(smetrics->max_advance
+ * ins_ttcap->force_c_scale_rsb / 64.0 + .5);
+ else
+ force_c_rsb = maxRsb;
+ /* calculate shift of BitmapAutoItalic */
+ if( ins_ttcap->autoItalic != 0 ) {
+ double ai;
+ int ai_lsb,ai_rsb,ai_total;
+ if( 0 < ins_ttcap->autoItalic ) ai=ins_ttcap->autoItalic;
+ else ai = -ins_ttcap->autoItalic;
+ ai_total = (int)( ai * smetrics->max_advance / 64.0 + 0.5);
+ ai_rsb = (int)((double)ai_total * ascent / ( ascent + descent ) + 0.5 );
+ ai_lsb = -(ai_total - ai_rsb);
+ if( 0 < ins_ttcap->autoItalic ) {
+ ins_ttcap->lsbShiftOfBitmapAutoItalic = ai_lsb;
+ ins_ttcap->rsbShiftOfBitmapAutoItalic = ai_rsb;
+ }
+ else {
+ ins_ttcap->lsbShiftOfBitmapAutoItalic = -ai_rsb;
+ ins_ttcap->rsbShiftOfBitmapAutoItalic = -ai_lsb;
+ }
+ }
+ /* integer adjustment by TTCap */
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE_CORRECT_B_BOX_WIDTH )
+ width += ins_ttcap->doubleStrikeShift;
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
+ maxRsb += ins_ttcap->doubleStrikeShift;
+ maxRsb += ins_ttcap->adjustRightSideBearingByPixel;
+ minLsb += ins_ttcap->adjustLeftSideBearingByPixel;
+ /* We have not carried out matrix calculation, so this is done. */
+ maxRsb += ins_ttcap->rsbShiftOfBitmapAutoItalic;
+ minLsb += ins_ttcap->lsbShiftOfBitmapAutoItalic;
+ /* force constant */
+ if( ins_ttcap->flags & TTCAP_DOUBLE_STRIKE )
+ force_c_rsb += ins_ttcap->doubleStrikeShift;
+ force_c_rsb += ins_ttcap->force_c_adjust_rsb_by_pixel;
+ force_c_lsb += ins_ttcap->force_c_adjust_lsb_by_pixel;
+ force_c_rsb += ins_ttcap->rsbShiftOfBitmapAutoItalic;
+ force_c_lsb += ins_ttcap->lsbShiftOfBitmapAutoItalic;
+ }
+
+ /* SET CALCULATED VALUES TO INSTANCE */
+
+ /* Set actual height and cosine */
+ instance->pixel_size = base_height;
+ instance->advance = advance;
+ if ( unit_x != 0 ){
+ instance->pixel_width_unit_x = unit_x/base_height;
+ instance->pixel_width_unit_y = 0;
+ }
+ else{
+ instance->pixel_width_unit_x = 0;
+ instance->pixel_width_unit_y = unit_y/base_height;
+ }
+
+ /* header's metrics */
+ instance->charcellMetrics = (xCharInfo*)xalloc(sizeof(xCharInfo));
+ if(instance->charcellMetrics == NULL) {
+ xrc = AllocError;
+ goto quit;
+ }
+ instance->charcellMetrics->ascent = ascent;
+ instance->charcellMetrics->descent = descent;
+ instance->charcellMetrics->attributes = rawWidth;
+ instance->charcellMetrics->rightSideBearing = maxRsb;
+ instance->charcellMetrics->leftSideBearing = minLsb;
+ instance->charcellMetrics->characterWidth = width;
+ instance->averageWidth = averageWidth;
+ instance->rawAverageWidth = rawAverageWidth;
+
+ /* Check code 0 */
+ if( FreeTypeInstanceGetGlyph(font->zero_idx, 0, &tmpglyph, font->instance) != Successful
+ || tmpglyph == NULL)
+ if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_GET_DUMMY, &tmpglyph, font->instance)
+ != Successful )
+ tmpglyph = NULL;
+ if ( !tmpglyph ) {
+ xrc = AllocError;
+ goto quit;
+ }
+
+ /* FORCE CONSTANT METRICS */
+ if( 0 <= ins_ttcap->forceConstantSpacingEnd ) {
+ xCharInfo *tmpchar = NULL;
+ int c = ins_ttcap->force_c_representative_metrics_char_code;
+ /* header's metrics */
+ if( instance->forceConstantMetrics == NULL ){
+ instance->forceConstantMetrics = (xCharInfo*)xalloc(sizeof(xCharInfo));
+ if(instance->forceConstantMetrics == NULL) {
+ xrc = AllocError;
+ goto quit;
+ }
+ }
+ /* Get Representative Metrics */
+ if ( 0 <= c ) {
+ if( FreeTypeFontGetGlyphMetrics(c, 0, &tmpchar, font) != Successful )
+ tmpchar = NULL;
+ }
+ if ( tmpchar && 0 < tmpchar->characterWidth ) {
+ instance->forceConstantMetrics->leftSideBearing = tmpchar->leftSideBearing;
+ instance->forceConstantMetrics->rightSideBearing = tmpchar->rightSideBearing;
+ instance->forceConstantMetrics->characterWidth = tmpchar->characterWidth;
+ instance->forceConstantMetrics->ascent = tmpchar->ascent;
+ instance->forceConstantMetrics->descent = tmpchar->descent;
+ instance->forceConstantMetrics->attributes = tmpchar->attributes;
+ }
+ else {
+ instance->forceConstantMetrics->leftSideBearing = force_c_lsb;
+ instance->forceConstantMetrics->rightSideBearing = force_c_rsb;
+ instance->forceConstantMetrics->characterWidth = force_c_width;
+ instance->forceConstantMetrics->ascent = ascent;
+ instance->forceConstantMetrics->descent = descent;
+ instance->forceConstantMetrics->attributes = force_c_rawWidth;
+ }
+ /* Check code 0 */
+ if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING,
+ &tmpglyph, font->instance) != Successful
+ || tmpglyph == NULL)
+ if( FreeTypeInstanceGetGlyph(font->zero_idx, FT_FORCE_CONSTANT_SPACING | FT_GET_DUMMY,
+ &tmpglyph, font->instance)
+ != Successful )
+ tmpglyph = NULL;
+ if ( !tmpglyph ) {
+ xrc = AllocError;
+ goto quit;
+ }
+ }
+ }
+ else{
+
+ /*
+ * CACHED VALUES
+ */
+
+ width = instance->charcellMetrics->characterWidth;
+ ascent = instance->charcellMetrics->ascent;
+ descent = instance->charcellMetrics->descent;
+ rawWidth = instance->charcellMetrics->attributes;
+ maxRsb = instance->charcellMetrics->rightSideBearing;
+ minLsb = instance->charcellMetrics->leftSideBearing;
+ averageWidth = instance->averageWidth;
+ rawAverageWidth = instance->rawAverageWidth;
+
+ }
+
+ /*
+ * SET maxbounds, minbounds ...
+ */
+
+ if( !charcell ) { /* NOT CHARCELL */
+ if( info ){
+ /*
+ Calculate all glyphs' metrics.
+ maxbounds.ascent and maxbounds.descent are quite important values
+ for XAA. If ascent/descent of each glyph exceeds
+ maxbounds.ascent/maxbounds.descent, XAA causes SERVER CRASH.
+ Therefore, THIS MUST BE DONE.
+ */
+ ft_compute_bounds(font,info,vals);
+ }
+ }
+ else{ /* CHARCELL */
+
+ /*
+ * SET CALCULATED OR CACHED VARIABLES
+ */
+
+ vals->width = averageWidth;
+
+ if( info ){
+
+ info->maxbounds.leftSideBearing = minLsb;
+ info->maxbounds.rightSideBearing = maxRsb;
+ info->maxbounds.characterWidth = width;
+ info->maxbounds.ascent = ascent;
+ info->maxbounds.descent = descent;
+ info->maxbounds.attributes =
+ (unsigned short)(short)rawWidth;
+
+ info->minbounds = info->maxbounds;
+ }
+ }
+
+ /* set info */
+
+ if( info ){
+ info->fontAscent = ascent;
+ info->fontDescent = descent;
+ /* Glyph metrics are accurate */
+ info->inkMetrics=1;
+
+ memcpy((char *)&info->ink_maxbounds,
+ (char *)&info->maxbounds, sizeof(xCharInfo));
+ memcpy((char *)&info->ink_minbounds,
+ (char *)&info->minbounds, sizeof(xCharInfo));
+
+ /* XXX - hack */
+ info->defaultCh=0;
+
+ /* Set the pInfo flags */
+ /* Properties set by FontComputeInfoAccelerators:
+ pInfo->noOverlap;
+ pInfo->terminalFont;
+ pInfo->constantMetrics;
+ pInfo->constantWidth;
+ pInfo->inkInside;
+ */
+ /* from lib/font/util/fontaccel.c */
+ FontComputeInfoAccelerators(info);
}
if(xf)
@@ -1494,21 +3329,21 @@ FreeTypeLoadXFont(char *fileName,
xrc = FreeTypeAddProperties(font, vals, info, entry->name.name,
rawAverageWidth);
if (xrc != Successful) {
- FreeTypeFreeFont(font);
- return xrc;
+ goto quit;
}
}
- return Successful;
-#undef TRANSFORM_FUNITS_X
-#undef TRANSFORM_FUNITS_X_DOWN
-#undef TRANSFORM_FUNITS_X_UP
-#undef TRANSFORM_FUNITS_Y
-#undef TRANSFORM_FUNITS_Y_DOWN
-#undef TRANSFORM_FUNITS_Y_UP
-#undef TRANSFORM_FUNITS_RAW
-#undef TRANSFORM_FUNITS_RAW_DOWN
-#undef TRANSFORM_FUNITS_RAW_UP
+ quit:
+ if ( dynStrTTCapCodeRange ) xfree(dynStrTTCapCodeRange);
+ if ( dynStrFTFileName ) xfree(dynStrFTFileName);
+ if ( dynStrRealFileName ) xfree(dynStrRealFileName);
+ if ( xrc != Successful ) {
+ if( font ){
+ if( face && font->instance == NULL ) FreeTypeFreeFace(face);
+ FreeTypeFreeFont(font);
+ }
+ }
+ return xrc;
}
/* Routines used by X11 to get info and glyphs from the font. */
@@ -1519,16 +3354,15 @@ FreeTypeGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars,
xCharInfo **metrics)
{
unsigned int code = 0;
+ int flags = 0;
FTFontPtr tf;
+ struct TTCapInfo *ttcap;
xCharInfo **mp, *m;
-
- /* The compiler is supposed to initialise all the fields to 0 */
- static xCharInfo noSuchChar;
-
/* MUMBLE1("Get metrics for %ld characters\n", count);*/
tf = (FTFontPtr)pFont->fontPrivate;
+ ttcap = &tf->instance->ttcap;
mp = metrics;
while (count-- > 0) {
@@ -1541,13 +3375,28 @@ FreeTypeGetMetrics(FontPtr pFont, unsigned long count, unsigned char *chars,
case TwoD16Bit:
code = (*chars++ << 8);
code |= *chars++;
+ /* */
+ if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) {
+ if ( (int)code <= ttcap->forceConstantSpacingEnd
+ && ttcap->forceConstantSpacingBegin <= (int)code )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ else flags=0;
+ }
+ else { /* for GB18030 proportional */
+ if ( (int)code <= ttcap->forceConstantSpacingEnd
+ || ttcap->forceConstantSpacingBegin <= (int)code )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ else flags=0;
+ }
break;
}
- if(FreeTypeFontGetGlyphMetrics(code, &m, tf) == Successful && m!=0) {
+ if(FreeTypeFontGetGlyphMetrics(code, flags, &m, tf) == Successful && m!=NULL) {
*mp++ = m;
- } else
- *mp++ = &noSuchChar;
+ }
+#ifdef XAA_ACCEPTS_NO_SUCH_CHAR
+ else *mp++ = &noSuchChar.metrics;
+#endif
}
*metricCount = mp - metrics;
@@ -1560,11 +3409,14 @@ FreeTypeGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
CharInfoPtr *glyphs)
{
unsigned int code = 0;
+ int flags = 0;
FTFontPtr tf;
CharInfoPtr *gp;
CharInfoPtr g;
+ struct TTCapInfo *ttcap;
tf = (FTFontPtr)pFont->fontPrivate;
+ ttcap = &tf->instance->ttcap;
gp = glyphs;
while (count-- > 0) {
@@ -1575,14 +3427,28 @@ FreeTypeGetGlyphs(FontPtr pFont, unsigned long count, unsigned char *chars,
case Linear16Bit: case TwoD16Bit:
code = *chars++ << 8;
code |= *chars++;
+ /* */
+ if ( !(ttcap->flags & TTCAP_FORCE_C_OUTSIDE) ) {
+ if ( (int)code <= ttcap->forceConstantSpacingEnd
+ && ttcap->forceConstantSpacingBegin <= (int)code )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ else flags=0;
+ }
+ else { /* for GB18030 proportional */
+ if ( (int)code <= ttcap->forceConstantSpacingEnd
+ || ttcap->forceConstantSpacingBegin <= (int)code )
+ flags|=FT_FORCE_CONSTANT_SPACING;
+ else flags=0;
+ }
break;
}
- if(FreeTypeFontGetGlyph(code, &g, tf) == Successful && g!=0) {
+ if(FreeTypeFontGetGlyph(code, flags, &g, tf) == Successful && g!=NULL) {
*gp++ = g;
- } else
- if(FreeTypeFontGetDefaultGlyph(&g, tf) == Successful && g!=0)
- *gp++ = g;
+ }
+#ifdef XAA_ACCEPTS_NO_SUCH_CHAR
+ else *gp++ = &noSuchChar;
+#endif
}
*glyphCount = gp - glyphs;
@@ -1658,13 +3524,6 @@ FreeTypeOpenScalable(FontPathElementPtr fpe, FontPtr *ppFont, int flags,
#endif
MUMBLE("\n");
- /* Reject ridiculously small values. Singular matrices are okay. */
- if(MAX(hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]),
- hypot(vals->pixel_matrix[2], vals->pixel_matrix[3]))
- <1.0)
- return BadFontName;
-
- /* Create an X11 server-side font. */
xf = CreateFontRec();
if (xf == NULL)
return AllocError;
@@ -1674,16 +3533,13 @@ FreeTypeOpenScalable(FontPathElementPtr fpe, FontPtr *ppFont, int flags,
DestroyFontRec(xf);
return xrc;
}
- /* Load the font and fill its info structure. */
xrc = FreeTypeLoadXFont(fileName, vals, xf, &xf->info, &bmfmt, entry);
if(xrc != Successful) {
- /* Free everything up at this level and return the error code. */
MUMBLE1("Error during load: %d\n",xrc);
DestroyFontRec(xf);
return xrc;
}
- /* Set the font and return. */
*ppFont = xf;
return xrc;
@@ -1705,10 +3561,6 @@ FreeTypeGetInfoScalable(FontPathElementPtr fpe, FontInfoPtr info,
#endif
MUMBLE("\n");
- if(MAX(hypot(vals->pixel_matrix[0], vals->pixel_matrix[1]),
- hypot(vals->pixel_matrix[2], vals->pixel_matrix[3])) < 1.0)
- return BadFontName;
-
xrc = FreeTypeSetUpFont(fpe, 0, info, 0, 0, &bmfmt);
if(xrc != Successful) {
return xrc;
@@ -1760,6 +3612,21 @@ static FontRendererRec renderers[] = {
};
static int num_renderers = sizeof(renderers) / sizeof(renderers[0]);
+static FontRendererRec alt_renderers[] = {
+ {".bdf", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".BDF", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".pcf", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+ {".PCF", 4, 0, FreeTypeOpenScalable, 0,
+ FreeTypeGetInfoScalable, 0, CAPABILITIES},
+};
+
+static int num_alt_renderers =
+sizeof(alt_renderers) / sizeof(alt_renderers[0]);
+
+
void
FreeTypeRegisterFontFileFunctions(void)
{
@@ -1767,4 +3634,7 @@ FreeTypeRegisterFontFileFunctions(void)
for (i = 0; i < num_renderers; i++)
FontFileRegisterRenderer(&renderers[i]);
+
+ for (i = 0; i < num_alt_renderers; i++)
+ FontFilePriorityRegisterRenderer(&alt_renderers[i], -10);
}