[gf] Change logic to load bitmap on demand.

Also load glyphs in the order they appear in the font
file by changing the cmap scheme and implementing a
proper `gf cmap'.
This commit is contained in:
Parth Wazurkar 2018-08-10 00:54:24 +05:30
parent 44d9f10ac8
commit 7ea68ac9f3
3 changed files with 294 additions and 179 deletions

View File

@ -43,9 +43,9 @@
typedef struct GF_CMapRec_
{
FT_CMapRec cmap;
FT_UInt32 bc; /* Beginning Character */
FT_UInt32 ec; /* End Character */
FT_CMapRec cmap;
FT_ULong num_encodings;
GF_Encoding encodings;
} GF_CMapRec, *GF_CMap;
@ -57,8 +57,8 @@
GF_Face face = (GF_Face)FT_CMAP_FACE( cmap );
FT_UNUSED( init_data );
cmap->bc = face->gf_glyph->code_min;
cmap->ec = face->gf_glyph->code_max;
cmap->num_encodings = face->gf_glyph->nencodings;
cmap->encodings = face->gf_glyph->encodings;
return FT_Err_Ok;
}
@ -69,54 +69,98 @@
{
GF_CMap cmap = (GF_CMap)gfcmap;
cmap->bc = 0;
cmap->ec = -1;
cmap->encodings = NULL;
cmap->num_encodings = 0;
}
FT_CALLBACK_DEF( FT_UInt )
gf_cmap_char_index( FT_CMap gfcmap,
FT_UInt32 char_code )
FT_UInt32 charcode )
{
FT_UInt gindex = 0;
GF_CMap cmap = (GF_CMap)gfcmap;
GF_CMap cmap = (GF_CMap)gfcmap;
GF_Encoding encodings = cmap->encodings;
FT_ULong min, max, mid;
FT_UInt result = 0;
char_code -= cmap->bc;
min = 0;
max = cmap->num_encodings;
if ( char_code < cmap->ec - cmap->bc + 1 )
gindex = (FT_UInt)( char_code );
while ( min < max )
{
FT_ULong code;
return gindex;
mid = ( min + max ) >> 1;
code = (FT_ULong)encodings[mid].enc;
if ( charcode == code )
{
result = encodings[mid].glyph;
break;
}
if ( charcode < code )
max = mid;
else
min = mid + 1;
}
return result;
}
FT_CALLBACK_DEF( FT_UInt )
gf_cmap_char_next( FT_CMap gfcmap,
FT_UInt32 *achar_code )
FT_UInt32 *acharcode )
{
GF_CMap cmap = (GF_CMap)gfcmap;
FT_UInt gindex = 0;
FT_UInt32 result = 0;
FT_UInt32 char_code = *achar_code + 1;
GF_CMap cmap = (GF_CMap)gfcmap;
GF_Encoding encodings = cmap->encodings;
FT_ULong min, max, mid;
FT_ULong charcode = *acharcode + 1;
FT_UInt result = 0;
if ( char_code <= cmap->bc )
min = 0;
max = cmap->num_encodings;
while ( min < max )
{
result = cmap->bc;
gindex = 1;
FT_ULong code;
mid = ( min + max ) >> 1;
code = (FT_ULong)encodings[mid].enc;
if ( charcode == code )
{
result = encodings[mid].glyph + 1;
goto Exit;
}
if ( charcode < code )
max = mid;
else
min = mid + 1;
}
charcode = 0;
if ( min < cmap->num_encodings )
{
charcode = (FT_ULong)encodings[min].enc;
result = encodings[min].glyph ;
}
Exit:
if ( charcode > 0xFFFFFFFFUL )
{
FT_TRACE1(( "gf_cmap_char_next: charcode 0x%x > 32bit API" ));
*acharcode = 0;
/* XXX: result should be changed to indicate an overflow error */
}
else
{
char_code -= cmap->bc;
if ( char_code < cmap->ec - cmap->bc + 1 )
{
result = char_code;
gindex = (FT_UInt)( char_code );
}
}
*achar_code = result;
return gindex;
*acharcode = (FT_UInt32)charcode;
return result;
}
@ -163,7 +207,6 @@
FT_Error error = FT_Err_Ok;
FT_Memory memory = FT_FACE_MEMORY( face );
GF_Glyph go=NULL;
FT_UInt16 i,count;
TFM_Service tfm;
@ -197,9 +240,9 @@
face->gf_glyph = go ;
/* sanity check */
if ( !face->gf_glyph->bm_table )
if ( !face->gf_glyph->metrics )
{
FT_TRACE2(( "glyph bitmaps not allocated\n" ));
FT_TRACE2(( "glyph metrics missing\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
@ -230,13 +273,7 @@
*/
gfface->family_name = NULL;
count=0;
for (i = 0; i < 256; i++)
{
if(go->bm_table[i].bitmap != NULL)
count++;
}
gfface->num_glyphs = (FT_Long)count;
gfface->num_glyphs = (FT_Long)face->gf_glyph->nglyphs;
FT_TRACE4(( " number of glyphs: allocated %d\n",gfface->num_glyphs ));
@ -270,15 +307,36 @@
y_res ); ;
}
/* set up charmap */
{
/* FT_Bool unicode_charmap ; */
/* XXX: TO-DO
Currently the unicode_charmap is set to `0'
The functionality of extracting coding scheme
from `xxx' and `yyy' commands will be used to
set the unicode_charmap.
*/
}
/* Charmaps */
{
FT_CharMapRec charmap;
FT_Bool unicode_charmap = 0;
/* Unicode Charmap */
charmap.encoding = FT_ENCODING_UNICODE;
charmap.platform_id = TT_PLATFORM_MICROSOFT;
charmap.encoding_id = TT_MS_ID_UNICODE_CS;
charmap.face = FT_FACE( face );
charmap.encoding = FT_ENCODING_NONE;
/* initial platform/encoding should indicate unset status? */
charmap.platform_id = TT_PLATFORM_APPLE_UNICODE;
charmap.encoding_id = TT_APPLE_ID_DEFAULT;
if( unicode_charmap )
{
/* Unicode Charmap */
charmap.encoding = FT_ENCODING_UNICODE;
charmap.platform_id = TT_PLATFORM_MICROSOFT;
charmap.encoding_id = TT_MS_ID_UNICODE_CS;
}
error = FT_CMap_New( &gf_cmap_class, NULL, &charmap, NULL );
@ -365,10 +423,13 @@
{
GF_Face gf = (GF_Face)FT_SIZE_FACE( size );
FT_Face face = FT_FACE( gf );
FT_Stream stream;
FT_Error error = FT_Err_Ok;
FT_Bitmap* bitmap = &slot->bitmap;
GF_BitmapRec bm;
GF_MetricRec metric;
GF_Glyph go;
FT_ULong bytes;
FT_Byte *bitmp;
go = gf->gf_glyph;
@ -387,7 +448,7 @@
goto Exit;
}
FT_TRACE1(( "GF_Glyph_Load: glyph index %d\n", glyph_index ));
FT_TRACE1(( "GF_Glyph_Load: glyph index %d and charcode is %d\n", glyph_index, go->metrics[glyph_index].code ));
if ( (FT_Int)glyph_index < 0 )
glyph_index = 0;
@ -399,44 +460,36 @@
goto Exit;
}
if ( !go->bm_table )
{
FT_TRACE2(( "invalid bitmap table\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
stream = gf->root.stream;
metric = gf->gf_glyph->metrics[glyph_index];
/* slot, bitmap => freetype, bm => gflib */
bm = gf->gf_glyph->bm_table[glyph_index];
error = gf_read_glyph( stream,
&metric );
bitmap->rows = bm.bbx_height;
bitmap->width = bm.bbx_width;
bitmap->rows = metric.bbx_height;
bitmap->width = metric.bbx_width;
bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
if ( !bm.raster )
{
FT_TRACE2(( "invalid bitmap width\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
bitmap->pitch = (int)bm.raster ;
bitmap->pitch = (int)( metric.raster );
/* note: we don't allocate a new array to hold the bitmap; */
/* we can simply point to it */
ft_glyphslot_set_bitmap( slot, bm.bitmap );
ft_glyphslot_set_bitmap( slot, metric.bitmap );
slot->format = FT_GLYPH_FORMAT_BITMAP;
slot->bitmap_left = bm.off_x ;
slot->bitmap_top = bm.off_y ;
slot->bitmap_left = metric.off_x ;
slot->bitmap_top = metric.off_y ;
slot->metrics.horiAdvance = (FT_Pos) (bm.mv_x ) * 64;
slot->metrics.horiBearingX = (FT_Pos) (bm.off_x ) * 64;
slot->metrics.horiBearingY = (FT_Pos) (bm.bbx_height) * 64;
slot->metrics.horiAdvance = (FT_Pos) ( metric.mv_x ) * 64;
slot->metrics.horiBearingX = (FT_Pos) ( metric.off_x ) * 64;
slot->metrics.horiBearingY = (FT_Pos) ( metric.bbx_height) * 64;
slot->metrics.width = (FT_Pos) ( bitmap->width * 64 );
slot->metrics.height = (FT_Pos) ( bitmap->rows * 64 );
ft_synthesize_vertical_metrics( &slot->metrics, bm.bbx_height * 64 );
ft_synthesize_vertical_metrics( &slot->metrics, metric.bbx_height * 64 );
/* XXX: to do: are there cases that need repadding the bitmap? */
Exit:
return error;

View File

@ -27,25 +27,43 @@
FT_BEGIN_HEADER
/* BitmapRec for GF format specific glyphs */
typedef struct GF_BitmapRec_
typedef struct GF_EncodingRec_
{
FT_Int bbx_width, bbx_height;
FT_Int off_x, off_y;
FT_Int mv_x, mv_y;
FT_Long enc;
FT_UShort glyph;
} GF_EncodingRec, *GF_Encoding;
/* BitmapRec for GF format specific glyphs */
typedef struct GF_MetricRec_
{
FT_Long bbx_width, bbx_height;
FT_Long off_x, off_y;
FT_Long mv_x, mv_y;
FT_Byte *bitmap;
FT_UInt raster;
FT_Long char_offset;
FT_UShort code;
} GF_BitmapRec, *GF_Bitmap;
} GF_MetricRec, *GF_Metric;
typedef struct GF_GlyphRec_
{
FT_UInt code_min, code_max;
GF_Bitmap bm_table;
FT_ULong nmetrics;
GF_Metric metrics;
FT_ULong nglyphs;
FT_ULong nencodings;
GF_Encoding encodings;
FT_Short defaultChar; /* To be checked */
FT_Int ds, hppp, vppp;
FT_Int font_bbx_w, font_bbx_h;
FT_Int font_bbx_xoff, font_bbx_yoff;
FT_Int font_bbx_w, font_bbx_h;
FT_Int font_bbx_xoff, font_bbx_yoff;
FT_Int check_sum;
} GF_GlyphRec, *GF_Glyph;

View File

@ -111,26 +111,116 @@ FT_Byte bit_table[] = {
return v;
}
static int
compare( FT_Long* a,
FT_Long* b )
{
if ( *a < *b )
return -1;
else if ( *a > *b )
return 1;
else
return 0;
}
/**************************************************************************
*
* API.
*
*/
static FT_Error
gf_set_encodings( GF_Glyph go,
FT_Memory memory )
{
FT_Error error;
FT_ULong nencoding;
FT_UInt i, j;
FT_ULong k;
GF_Encoding encoding = NULL;
GF_Metric metric;
FT_Long *tosort;
nencoding = go->nglyphs;
FT_TRACE2(( "gf_set_encodings: Reached here.\n" ));
if ( FT_NEW_ARRAY( metric, go->code_max - go->code_min + 1 ) )
return error;
if ( FT_NEW_ARRAY( encoding, nencoding ) )
return error;
if ( FT_NEW_ARRAY( tosort, nencoding ) )
return error;
FT_TRACE2(( "gf_set_encodings: Allocated sufficient memory.\n" ));
for( i = 0 ; i < 256 ; i++ )
{
if( go->metrics[i].char_offset >= 0 )
tosort[i] = go->metrics[i].char_offset;
}
ft_qsort( (void*)tosort, go->nglyphs, sizeof(FT_Long),
(int(*)(const void*, const void*) )compare );
for( i = 0 ; i < go->nglyphs ; i++ )
{
/* FT_TRACE2(( "tosort[%d]is %ld\n",i,tosort[i] )); */
}
k = 0;
for ( i = 0; i < go->nglyphs; i++ )
{
for ( j = 0; j < 256; j++ )
{
if( go->metrics[j].char_offset == tosort[i] )
break;
}
metric[k].char_offset = go->metrics[j].char_offset;
metric[k].code = go->metrics[j].code;
/* FT_TRACE2(( "metric[%d].char_offset is %ld %ld% ld\n",k,metric[k].char_offset,metric[k].code,k )); */
encoding[k].enc = go->metrics[j].code;
encoding[k].glyph = k;
k++;
}
for( i = 0 ; i < go->nglyphs ; i++ )
{
go->metrics[i].char_offset = metric[i].char_offset;
go->metrics[i].code = metric[i].code;
/* FT_TRACE2(( "Hi I am here go->metrics[%d].char_offset is %ld %ld% ld\n",i,
go->metrics[i].char_offset,go->metrics[i].code,i )); */
}
FT_FREE(metric);
go->nencodings = k;
go->encodings = encoding;
return error;
}
FT_LOCAL_DEF( FT_Error )
gf_read_glyph( FT_Stream stream,
GF_Bitmap bm,
FT_Memory memory )
GF_MetricRec *metrics )
{
FT_Long m, n;
FT_Int paint_sw;
FT_Int instr,inst;
FT_Long min_m, max_m, min_n, max_n, del_m, del_n;
FT_Long w, h, d;
FT_Int m_b, k;
FT_Byte *ptr;
FT_Int k;
/* FT_Int m_b;
FT_Byte *ptr; */
FT_Error error = FT_Err_Ok;
if( FT_STREAM_SEEK( metrics->char_offset ) )
return 0;
FT_TRACE2(( "In gf_read_glyph\n" ));
for ( ; ; )
{
inst = READ_UINT1( stream );
@ -203,19 +293,25 @@ FT_Byte bit_table[] = {
return -1;
}
/* FT_TRACE2(( "w is %ld\n"
"h is %ld\n"
"-min_m is %ld\n"
"max_n is %ld\n\n", w, h, -min_m, max_n ));
*/
/* allocate and build bitmap */
if ((bm->bitmap = (FT_Byte*)malloc(h*((w+7)/8))) == NULL)
if ((metrics->bitmap = (FT_Byte*)malloc(h*((w+7)/8))) == NULL)
{
error = FT_THROW( Invalid_File_Format );
return -1;
}
memset(bm->bitmap, 0, h*((w+7)/8));
bm->raster = (FT_UInt)(w+7)/8;
bm->bbx_width = w;
bm->bbx_height = h;
bm->off_x = -min_m;
bm->off_y = max_n;
memset(metrics->bitmap, 0, h*((w+7)/8));
metrics->raster = (FT_UInt)(w+7)/8;
metrics->bbx_width = w;
metrics->bbx_height = h;
metrics->off_x = -min_m;
metrics->off_y = max_n;
#if 0
bm->mv_x = -min_m;
bm->mv_y = max_n;
@ -256,6 +352,7 @@ FT_Byte bit_table[] = {
}
else
{
/*
ptr = &bm->bitmap[(max_n - n) * bm->raster + (m - min_m)/8];
m_b = (m - min_m) % 8;
while (d > 0)
@ -269,6 +366,7 @@ FT_Byte bit_table[] = {
}
d--;
}
*/
}
paint_sw = 1 - paint_sw;
break;
@ -299,8 +397,6 @@ FT_Byte bit_table[] = {
case GF_NO_OP:
break;
default:
FT_FREE(bm->bitmap);
bm->bitmap = NULL;
error = FT_THROW( Invalid_File_Format );
return -1;
}
@ -315,12 +411,11 @@ FT_Byte bit_table[] = {
GF_Glyph *goptr )
{
GF_Glyph go;
GF_Bitmap bm;
FT_Byte instr, d, pre, id, k, code;
FT_Long ds, check_sum, hppp, vppp;
FT_Long min_m, max_m, min_n, max_n, w;
FT_UInt dx, dy;
FT_Long ptr_post, ptr_p, ptr, optr;
FT_Long ptr_post, ptr_p, ptr;
FT_Int bc, ec, nchars, i;
FT_Error error = FT_Err_Ok;
FT_Memory memory = extmemory; /* needed for FT_NEW */
@ -428,70 +523,29 @@ FT_Byte bit_table[] = {
FT_TRACE5(( "gf_load_font: checksum is %ld\n",check_sum ));
if( ptr_p < 0 ) /* Defined to use ptr_p */
if( ptr_p < 0 )
{
FT_ERROR(( "gf_load_font: invalid pointer in postamble\n" ));
goto Exit;
}
if( check_sum < 0 ) /* Defined to use check_sum */
if( check_sum < 0 )
{
FT_ERROR(( "gf_load_font: invalid check sum value\n" ));
goto Exit;
}
#if 0
gptr = ftell(fp);
#endif
#if 0
/* read min & max char code */
bc = 256;
ec = -1;
for ( ; ; )
{
instr = READ_UINT1(fp);
if (instr == GF_POST_POST)
{
break;
}
else if (instr == GF_CHAR_LOC)
{
code = READ_UINT1(fp);
(void)SKIP_N(fp, 16);
}
else if (instr == GF_CHAR_LOC0)
{
code = READ_UINT1(fp);
(void)SKIP_N(fp, 9);
}
else
{
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
if (code < bc)
bc = code;
if (code > ec)
ec = code;
}
#else
bc = 0;
ec = 255;
#endif
bc = 0;
ec = 255;
nchars = ec - bc + 1;
if( FT_ALLOC(go, sizeof(GF_GlyphRec)) )
goto Exit;
if( FT_ALLOC_MULT(go->bm_table, sizeof(GF_BitmapRec), nchars) )
goto Exit;
FT_TRACE2(( "gf_load_font: Allocated bitmap table\n" ));
for (i = 0; i < nchars; i++)
go->bm_table[i].bitmap = NULL;
FT_TRACE5(( "gf_load_font: Allocated GF_GlyphRec\n" ));
go->check_sum = check_sum;
go->ds = (FT_UInt)ds/(1<<20);
go->hppp = (FT_UInt)hppp/(1<<16);
go->vppp = (FT_UInt)vppp/(1<<16);
@ -502,10 +556,15 @@ FT_Byte bit_table[] = {
go->code_min = bc;
go->code_max = ec;
/* read glyph */
#if 0
fseek(fp, gptr, SEEK_SET);
#endif
go->nglyphs = 0;
if ( FT_NEW_ARRAY( go->metrics, nchars ) )
goto Exit;
FT_TRACE5(( "gf_load_font: Allocated go->metrics array\n" ));
for( i = 0; i < 256 ; i++)
go->metrics[i].char_offset = -1;
for ( ; ; )
{
@ -533,39 +592,27 @@ FT_Byte bit_table[] = {
goto Exit;
}
/*
if( w > max_m) Defined to use w
{
FT_ERROR(( "gf_load_font: invalid width in charloc\n" ));
goto Exit;
}
*/
optr = stream->pos;
if( FT_STREAM_SEEK( ptr ) )
goto Exit;
bm = &go->bm_table[code - bc];
if (gf_read_glyph( stream, bm, memory ) < 0)
goto Exit;
bm->mv_x = dx;
bm->mv_y = dy;
if(FT_STREAM_SEEK( optr ))
goto Exit;
go->metrics[code - bc].mv_x = dx;
go->metrics[code - bc].mv_y = dy;
go->metrics[code - bc].char_offset = (FT_ULong)ptr;
go->metrics[code - bc].code = (FT_UShort)code;
go->nglyphs += 1;
}
error = gf_set_encodings( go, memory );
if( error )
goto Exit;
*goptr = go;
return error;
Exit:
if (go != NULL)
{
if( go->bm_table )
if(go->metrics != NULL)
{
for (i = 0; i < nchars; i++)
FT_FREE(go->bm_table[i].bitmap);
FT_FREE(go->metrics);
}
FT_FREE(go->bm_table);
FT_FREE(go);
}
return error;
@ -577,17 +624,14 @@ FT_Byte bit_table[] = {
{
FT_Memory memory = FT_FACE( face )->memory;
GF_Glyph go = face->gf_glyph;
FT_UInt nchars = FT_FACE( face )->num_glyphs,i;
if ( !go )
return;
if( go->bm_table )
if(go->metrics != NULL)
{
for (i = 0; i < nchars; i++)
FT_FREE(go->bm_table[i].bitmap);
FT_FREE(go->metrics);
}
FT_FREE(go->bm_table);
FT_FREE(go);
}