/*
* This function tries to load a small bitmap within a given FTC_SNode.
* Note that it returns a non-zero error code _only_ in the case of
* out-of-memory condition. For all other errors (e.g., corresponding
* to a bad font file), this function will mark the sbit as `unavailable'
* and return a value of 0.
*
* You should also read the comment within the @ftc_snode_compare
* function below to see how out-of-memory is handled during a lookup.
*/
static FT_Error
ftc_snode_load( FTC_SNode snode,
FTC_Manager manager,
FT_UInt gindex,
FT_ULong *asize )
{
FT_Error error;
FTC_GNode gnode = FTC_GNODE( snode );
FTC_Family family = gnode->family;
FT_Memory memory = manager->memory;
FT_Face face;
FTC_SBit sbit;
FTC_SFamilyClass clazz;
if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )
{
FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
return FTC_Err_Invalid_Argument;
}
sbit = snode->sbits + ( gindex - gnode->gindex );
clazz = (FTC_SFamilyClass)family->clazz;
sbit->buffer = 0;
error = clazz->family_load_glyph( family, gindex, manager, &face );
if ( error )
goto BadGlyph;
{
FT_Int temp;
FT_GlyphSlot slot = face->glyph;
FT_Bitmap* bitmap = &slot->bitmap;
FT_Int xadvance, yadvance;
if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
{
FT_ERROR(( "%s: glyph loaded didn't return a bitmap!\n",
"ftc_snode_load" ));
goto BadGlyph;
}
/* Check that our values fit into 8-bit containers! */
/* If this is not the case, our bitmap is too large */
/* and we will leave it as `missing' with sbit.buffer = 0 */
#define CHECK_CHAR( d ) ( temp = (FT_Char)d, temp == d )
#define CHECK_BYTE( d ) ( temp = (FT_Byte)d, temp == d )
/* horizontal advance in pixels */
xadvance = ( slot->advance.x + 32 ) >> 6;
yadvance = ( slot->advance.y + 32 ) >> 6;
if ( !CHECK_BYTE( bitmap->rows ) ||
!CHECK_BYTE( bitmap->width ) ||
!CHECK_CHAR( bitmap->pitch ) ||
!CHECK_CHAR( slot->bitmap_left ) ||
!CHECK_CHAR( slot->bitmap_top ) ||
!CHECK_CHAR( xadvance ) ||
!CHECK_CHAR( yadvance ) )
goto BadGlyph;
sbit->width = (FT_Byte)bitmap->width;
sbit->height = (FT_Byte)bitmap->rows;
sbit->pitch = (FT_Char)bitmap->pitch;
sbit->left = (FT_Char)slot->bitmap_left;
sbit->top = (FT_Char)slot->bitmap_top;
sbit->xadvance = (FT_Char)xadvance;
sbit->yadvance = (FT_Char)yadvance;
sbit->format = (FT_Byte)bitmap->pixel_mode;
sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
/* copy the bitmap into a new buffer -- ignore error */
error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
/* now, compute size */
if ( asize )
*asize = FT_ABS( sbit->pitch ) * sbit->height;
} /* glyph loading successful */
/* ignore the errors that might have occurred -- */
/* we mark unloaded glyphs with `sbit.buffer == 0' */
/* and `width == 255', `height == 0' */
/* */
if ( error && error != FTC_Err_Out_Of_Memory )
{
BadGlyph:
//.........这里部分代码省略.........
static void
t42_parse_encoding( T42_Face face,
T42_Loader loader )
{
T42_Parser parser = &loader->parser;
FT_Byte* cur;
FT_Byte* limit = parser->root.limit;
PSAux_Service psaux = (PSAux_Service)face->psaux;
T1_Skip_Spaces( parser );
cur = parser->root.cursor;
if ( cur >= limit )
{
FT_ERROR(( "t42_parse_encoding: out of bounds\n" ));
parser->root.error = FT_THROW( Invalid_File_Format );
return;
}
/* if we have a number or `[', the encoding is an array, */
/* and we must load it now */
if ( ft_isdigit( *cur ) || *cur == '[' )
{
T1_Encoding encode = &face->type1.encoding;
FT_Int count, n;
PS_Table char_table = &loader->encoding_table;
FT_Memory memory = parser->root.memory;
FT_Error error;
FT_Bool only_immediates = 0;
/* read the number of entries in the encoding; should be 256 */
if ( *cur == '[' )
{
count = 256;
only_immediates = 1;
parser->root.cursor++;
}
else
count = (FT_Int)T1_ToInt( parser );
T1_Skip_Spaces( parser );
if ( parser->root.cursor >= limit )
return;
/* we use a T1_Table to store our charnames */
loader->num_chars = encode->num_chars = count;
if ( FT_NEW_ARRAY( encode->char_index, count ) ||
FT_NEW_ARRAY( encode->char_name, count ) ||
FT_SET_ERROR( psaux->ps_table_funcs->init(
char_table, count, memory ) ) )
{
parser->root.error = error;
return;
}
/* We need to `zero' out encoding_table.elements */
for ( n = 0; n < count; n++ )
{
char* notdef = (char *)".notdef";
(void)T1_Add_Table( char_table, n, notdef, 8 );
}
/* Now we need to read records of the form */
/* */
/* ... charcode /charname ... */
/* */
/* for each entry in our table. */
/* */
/* We simply look for a number followed by an immediate */
/* name. Note that this ignores correctly the sequence */
/* that is often seen in type42 fonts: */
/* */
/* 0 1 255 { 1 index exch /.notdef put } for dup */
/* */
/* used to clean the encoding array before anything else. */
/* */
/* Alternatively, if the array is directly given as */
/* */
/* /Encoding [ ... ] */
/* */
/* we only read immediates. */
n = 0;
T1_Skip_Spaces( parser );
while ( parser->root.cursor < limit )
{
cur = parser->root.cursor;
/* we stop when we encounter `def' or `]' */
if ( *cur == 'd' && cur + 3 < limit )
{
if ( cur[1] == 'e' &&
cur[2] == 'f' &&
t42_is_space( cur[3] ) )
{
//.........这里部分代码省略.........
开发者ID:theqvd,项目名称:vcxsrv,代码行数:101,代码来源:t42parse.c
示例4: t42_parse_charstrings
static void
t42_parse_charstrings( T42_Face face,
T42_Loader loader )
{
T42_Parser parser = &loader->parser;
PS_Table code_table = &loader->charstrings;
PS_Table name_table = &loader->glyph_names;
PS_Table swap_table = &loader->swap_table;
FT_Memory memory = parser->root.memory;
FT_Error error;
PSAux_Service psaux = (PSAux_Service)face->psaux;
FT_Byte* cur;
FT_Byte* limit = parser->root.limit;
FT_Int n;
FT_Int notdef_index = 0;
FT_Byte notdef_found = 0;
T1_Skip_Spaces( parser );
if ( parser->root.cursor >= limit )
{
FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
error = FT_THROW( Invalid_File_Format );
goto Fail;
}
if ( ft_isdigit( *parser->root.cursor ) )
{
loader->num_glyphs = T1_ToInt( parser );
if ( parser->root.error )
return;
if ( loader->num_glyphs < 0 )
{
FT_ERROR(( "t42_parse_encoding: invalid number of glyphs\n" ));
error = FT_THROW( Invalid_File_Format );
goto Fail;
}
}
else if ( *parser->root.cursor == '<' )
{
/* We have `<< ... >>'. Count the number of `/' in the dictionary */
/* to get its size. */
FT_Int count = 0;
T1_Skip_PS_Token( parser );
if ( parser->root.error )
return;
T1_Skip_Spaces( parser );
cur = parser->root.cursor;
while ( parser->root.cursor < limit )
{
if ( *parser->root.cursor == '/' )
count++;
else if ( *parser->root.cursor == '>' )
{
loader->num_glyphs = count;
parser->root.cursor = cur; /* rewind */
break;
}
T1_Skip_PS_Token( parser );
if ( parser->root.error )
return;
T1_Skip_Spaces( parser );
}
}
else
{
FT_ERROR(( "t42_parse_charstrings: invalid token\n" ));
error = FT_THROW( Invalid_File_Format );
goto Fail;
}
if ( parser->root.cursor >= limit )
{
FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
error = FT_THROW( Invalid_File_Format );
goto Fail;
}
/* initialize tables */
error = psaux->ps_table_funcs->init( code_table,
loader->num_glyphs,
memory );
if ( error )
goto Fail;
error = psaux->ps_table_funcs->init( name_table,
loader->num_glyphs,
memory );
if ( error )
goto Fail;
/* Initialize table for swapping index notdef_index and */
/* index 0 names and codes (if necessary). */
//.........这里部分代码省略.........
开发者ID:theqvd,项目名称:vcxsrv,代码行数:101,代码来源:t42parse.c
示例5: cid_load_keyword
static FT_Error
cid_load_keyword( CID_Face face,
CID_Loader* loader,
const T1_Field keyword )
{
FT_Error error;
CID_Parser* parser = &loader->parser;
FT_Byte* object;
void* dummy_object;
CID_FaceInfo cid = &face->cid;
/* if the keyword has a dedicated callback, call it */
if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
{
keyword->reader( (FT_Face)face, parser );
error = parser->root.error;
goto Exit;
}
/* we must now compute the address of our target object */
switch ( keyword->location )
{
case T1_FIELD_LOCATION_CID_INFO:
object = (FT_Byte*)cid;
break;
case T1_FIELD_LOCATION_FONT_INFO:
object = (FT_Byte*)&cid->font_info;
break;
case T1_FIELD_LOCATION_FONT_EXTRA:
object = (FT_Byte*)&face->font_extra;
break;
case T1_FIELD_LOCATION_BBOX:
object = (FT_Byte*)&cid->font_bbox;
break;
default:
{
CID_FaceDict dict;
if ( parser->num_dict < 0 || parser->num_dict >= cid->num_dicts )
{
FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n",
keyword->ident ));
error = FT_THROW( Syntax_Error );
goto Exit;
}
dict = cid->font_dicts + parser->num_dict;
switch ( keyword->location )
{
case T1_FIELD_LOCATION_PRIVATE:
object = (FT_Byte*)&dict->private_dict;
break;
default:
object = (FT_Byte*)dict;
}
}
}
dummy_object = object;
/* now, load the keyword data in the object's field(s) */
if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
keyword->type == T1_FIELD_TYPE_FIXED_ARRAY )
error = cid_parser_load_field_table( &loader->parser, keyword,
&dummy_object );
else
error = cid_parser_load_field( &loader->parser,
keyword, &dummy_object );
Exit:
return error;
}
int vrpn_Tracker_Isotrak::get_report(void)
{
char errmsg[512]; // Error message to send to VRPN
int ret; // Return value from function call to be checked
// The first byte of a binary record has the high order bit set
if (status == vrpn_TRACKER_SYNCING) {
// Try to get a character. If none, just return.
if (vrpn_read_available_characters(serial_fd, buffer, 1) != 1) {
return 0;
}
// The first byte of a record has the high order bit set
if(!(buffer[0] & 0x80)) {
sprintf(errmsg,"While syncing (looking for byte with high order bit set, "
"got '%x')", buffer[0]);
FT_WARNING(errmsg);
vrpn_flush_input_buffer(serial_fd);
return 0;
}
// Got the first byte of a report -- go into TRACKER_PARTIAL mode
// and record that we got one character at this time.
bufcount = 1;
vrpn_gettimeofday(×tamp, NULL);
status = vrpn_TRACKER_PARTIAL;
}
//--------------------------------------------------------------------
// Read as many bytes of this report as we can, storing them
// in the buffer. We keep track of how many have been read so far
// and only try to read the rest. The routine that calls this one
// makes sure we get a full reading often enough (ie, it is responsible
// for doing the watchdog timing to make sure the tracker hasn't simply
// stopped sending characters).
//--------------------------------------------------------------------
ret = vrpn_read_available_characters(serial_fd, &buffer[bufcount],
BINARY_RECORD_SIZE - bufcount);
if (ret == -1) {
FT_ERROR("Error reading report");
status = vrpn_TRACKER_FAIL;
return 0;
}
bufcount += ret;
if (bufcount < BINARY_RECORD_SIZE) { // Not done -- go back for more
return 0;
}
// We now have enough characters for a full report
// Check it to ensure we do not have a high bit set other
// than on the first byte
for(int i=1; i<BINARY_RECORD_SIZE; i++)
{
if (buffer[i] & 0x80) {
status = vrpn_TRACKER_SYNCING;
sprintf(errmsg,"Unexpected sync character in record");
FT_WARNING(errmsg);
//FT_WARNING("Not '0' in record, re-syncing");
vrpn_flush_input_buffer(serial_fd);
return 0;
}
}
// Create a buffer for the decoded message
unsigned char decoded[BINARY_RECORD_SIZE];
int d = 0;
int fullgroups = BINARY_RECORD_SIZE / 8;
// The following decodes the Isotrak binary format. It consists of
// 7 byte values plus an extra byte of the high bit for these
// 7 bytes. First, loop over the 7 byte ranges (8 bytes in binary)
int i;
for(i = 0; i<fullgroups; i++)
{
vrpn_uint8 *group = &buffer[i * 8];
vrpn_uint8 high = buffer[i * 8 + 7];
for(int j=0; j<7; j++)
{
decoded[d] = *group++;
if(high & 1)
decoded[d] |= 0x80;
d++;
high >>= 1;
}
}
// We'll have X bytes left at the end
int left = BINARY_RECORD_SIZE - fullgroups * 8;
vrpn_uint8 *group = &buffer[fullgroups * 8];
vrpn_uint8 high = buffer[fullgroups * 8 + left - 1];
//.........这里部分代码省略.........
void vrpn_Tracker_Isotrak::reset()
{
static int numResets = 0; // How many resets have we tried?
int i,resetLen,ret;
unsigned char reset[10];
char errmsg[512];
//--------------------------------------------------------------------
// This section deals with resetting the tracker to its default state.
// Multiple attempts are made to reset, getting more aggressive each
// time. This section completes when the tracker reports a valid status
// message after the reset has completed.
//--------------------------------------------------------------------
// Send the tracker a string that should reset it. The first time we
// try this, just do the normal 'c' command to put it into polled mode.
// After a few tries with this, use a [return] character, and then use the ^Y to reset.
resetLen = 0;
numResets++;
// We're trying another reset
if (numResets > 1) { // Try to get it out of a query loop if its in one
reset[resetLen++] = (unsigned char) (13); // Return key -> get ready
}
if (numResets > 2) {
reset[resetLen++] = (unsigned char) (25); // Ctrl + Y -> reset the tracker
}
reset[resetLen++] = 'c'; // Put it into polled (not continuous) mode
sprintf(errmsg, "Resetting the tracker (attempt %d)", numResets);
FT_WARNING(errmsg);
for (i = 0; i < resetLen; i++) {
if (vrpn_write_characters(serial_fd, &reset[i], 1) == 1) {
fprintf(stderr,".");
vrpn_SleepMsecs(1000.0*2); // Wait after each character to give it time to respond
} else {
perror("Isotrack: Failed writing to tracker");
status = vrpn_TRACKER_FAIL;
return;
}
}
//XXX Take out the sleep and make it keep spinning quickly
if (numResets > 2) {
vrpn_SleepMsecs(1000.0*20); // Sleep to let the reset happen, if we're doing ^Y
}
fprintf(stderr,"\n");
// Get rid of the characters left over from before the reset
vrpn_flush_input_buffer(serial_fd);
// Make sure that the tracker has stopped sending characters
vrpn_SleepMsecs(1000.0*2);
unsigned char scrap[80];
if ( (ret = vrpn_read_available_characters(serial_fd, scrap, 80)) != 0) {
sprintf(errmsg,"Got >=%d characters after reset",ret);
FT_WARNING(errmsg);
for (i = 0; i < ret; i++) {
if (isprint(scrap[i])) {
fprintf(stderr,"%c",scrap[i]);
} else {
fprintf(stderr,"[0x%02X]",scrap[i]);
}
}
fprintf(stderr, "\n");
vrpn_flush_input_buffer(serial_fd); // Flush what's left
}
// Asking for tracker status
if (vrpn_write_characters(serial_fd, (const unsigned char *) "S", 1) == 1) {
vrpn_SleepMsecs(1000.0*1); // Sleep for a second to let it respond
} else {
perror(" Isotrack write failed");
status = vrpn_TRACKER_FAIL;
return;
}
// Read Status
unsigned char statusmsg[22];
// Attempt to read 21 characters.
ret = vrpn_read_available_characters(serial_fd, statusmsg, 21);
if ( (ret != 21) ) {
fprintf(stderr,
" Got %d of 21 characters for status\n",ret);
FT_ERROR("Bad status report from Isotrack, retrying reset");
return;
}
else if ( (statusmsg[0]!='2') ) {
int i;
statusmsg[sizeof(statusmsg) - 1] = '\0'; // Null-terminate the string
fprintf(stderr, " Isotrack: bad status (");
for (i = 0; i < ret; i++) {
if (isprint(statusmsg[i])) {
//.........这里部分代码省略.........
//.........这里部分代码省略.........
/* Read the number of codes in the range. */
if ( FT_READ_BYTE( nleft ) )
goto Exit;
/* Increment nleft, so we read `nleft + 1' codes/sids. */
nleft++;
/* compute max number of character codes */
if ( (FT_UInt)nleft > encoding->count )
encoding->count = nleft;
/* Fill in the range of codes/sids. */
for ( k = i; k < nleft + i; k++, glyph_code++ )
{
/* Make sure k is not too big. */
if ( k < num_glyphs && glyph_code < 256 )
{
/* Assign code to GID mapping. */
encoding->codes[glyph_code] = (FT_UShort)k;
/* Assign code to SID mapping. */
encoding->sids[glyph_code] = charset->sids[k];
}
}
}
/* simple check; one never knows what can be found in a font */
if ( encoding->count > 256 )
encoding->count = 256;
}
break;
default:
FT_ERROR(( "cff_encoding_load: invalid table format!\n" ));
error = CFF_Err_Invalid_File_Format;
goto Exit;
}
/* Parse supplemental encodings, if any. */
if ( encoding->format & 0x80 )
{
FT_UInt gindex;
/* count supplements */
if ( FT_READ_BYTE( count ) )
goto Exit;
for ( j = 0; j < count; j++ )
{
/* Read supplemental glyph code. */
if ( FT_READ_BYTE( glyph_code ) )
goto Exit;
/* Read the SID associated with this glyph code. */
if ( FT_READ_USHORT( glyph_sid ) )
goto Exit;
/* Assign code to SID mapping. */
encoding->sids[glyph_code] = glyph_sid;
/* First, look up GID which has been assigned to */
/* SID glyph_sid. */
for ( gindex = 0; gindex < num_glyphs; gindex++ )
{
if ( charset->sids[gindex] == glyph_sid )
static FT_Error
cff_charset_load( CFF_Charset charset,
FT_UInt num_glyphs,
FT_Stream stream,
FT_ULong base_offset,
FT_ULong offset,
FT_Bool invert )
{
FT_Memory memory = stream->memory;
FT_Error error = CFF_Err_Ok;
FT_UShort glyph_sid;
/* If the the offset is greater than 2, we have to parse the */
/* charset table. */
if ( offset > 2 )
{
FT_UInt j;
charset->offset = base_offset + offset;
/* Get the format of the table. */
if ( FT_STREAM_SEEK( charset->offset ) ||
FT_READ_BYTE( charset->format ) )
goto Exit;
/* Allocate memory for sids. */
if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
goto Exit;
/* assign the .notdef glyph */
charset->sids[0] = 0;
switch ( charset->format )
{
case 0:
if ( num_glyphs > 0 )
{
if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
goto Exit;
for ( j = 1; j < num_glyphs; j++ )
charset->sids[j] = FT_GET_USHORT();
FT_FRAME_EXIT();
}
break;
case 1:
case 2:
{
FT_UInt nleft;
FT_UInt i;
j = 1;
while ( j < num_glyphs )
{
/* Read the first glyph sid of the range. */
if ( FT_READ_USHORT( glyph_sid ) )
goto Exit;
/* Read the number of glyphs in the range. */
if ( charset->format == 2 )
{
if ( FT_READ_USHORT( nleft ) )
goto Exit;
}
else
{
if ( FT_READ_BYTE( nleft ) )
goto Exit;
}
/* Fill in the range of sids -- `nleft + 1' glyphs. */
for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
charset->sids[j] = glyph_sid;
}
}
break;
default:
FT_ERROR(( "cff_charset_load: invalid table format!\n" ));
error = CFF_Err_Invalid_File_Format;
goto Exit;
}
}
else
{
/* Parse default tables corresponding to offset == 0, 1, or 2. */
/* CFF specification intimates the following: */
/* */
/* In order to use a predefined charset, the following must be */
/* true: The charset constructed for the glyphs in the font's */
/* charstrings dictionary must match the predefined charset in */
/* the first num_glyphs. */
charset->offset = offset; /* record charset type */
//.........这里部分代码省略.........
T1_Get_Private_Dict( T1_Parser parser,
PSAux_Service psaux )
{
FT_Stream stream = parser->stream;
FT_Memory memory = parser->root.memory;
FT_Error error = T1_Err_Ok;
FT_Long size;
if ( parser->in_pfb )
{
/* in the case of the PFB format, the private dictionary can be */
/* made of several segments. We thus first read the number of */
/* segments to compute the total size of the private dictionary */
/* then re-read them into memory. */
FT_Long start_pos = FT_STREAM_POS();
FT_UShort tag;
parser->private_len = 0;
for (;;)
{
error = read_pfb_tag( stream, &tag, &size );
if ( error )
goto Fail;
if ( tag != 0x8002U )
break;
parser->private_len += size;
if ( FT_STREAM_SKIP( size ) )
goto Fail;
}
/* Check that we have a private dictionary there */
/* and allocate private dictionary buffer */
if ( parser->private_len == 0 )
{
FT_ERROR(( "T1_Get_Private_Dict:" ));
FT_ERROR(( " invalid private dictionary section\n" ));
error = T1_Err_Invalid_File_Format;
goto Fail;
}
if ( FT_STREAM_SEEK( start_pos ) ||
FT_ALLOC( parser->private_dict, parser->private_len ) )
goto Fail;
parser->private_len = 0;
for (;;)
{
error = read_pfb_tag( stream, &tag, &size );
if ( error || tag != 0x8002U )
{
error = T1_Err_Ok;
break;
}
if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
size ) )
goto Fail;
parser->private_len += size;
}
}
else
{
/* We have already `loaded' the whole PFA font file into memory; */
/* if this is a memory resource, allocate a new block to hold */
/* the private dict. Otherwise, simply overwrite into the base */
/* dictionary block in the heap. */
/* first of all, look at the `eexec' keyword */
FT_Byte* cur = parser->base_dict;
FT_Byte* limit = cur + parser->base_len;
FT_Byte c;
Again:
for (;;)
{
c = cur[0];
if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
/* newline + 4 chars */
{
if ( cur[1] == 'e' &&
cur[2] == 'x' &&
cur[3] == 'e' &&
cur[4] == 'c' )
break;
}
cur++;
if ( cur >= limit )
{
FT_ERROR(( "T1_Get_Private_Dict:" ));
FT_ERROR(( " could not find `eexec' keyword\n" ));
error = T1_Err_Invalid_File_Format;
goto Exit;
}
//.........这里部分代码省略.........
请发表评论