Revision: 8122 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8122&view=rev Author: mdboom Date: 2010-02-09 13:04:44 +0000 (Tue, 09 Feb 2010)
Log Message: ----------- Use a custom encoding containing all of the used glyphs when writing out a Postscript Type 3 font. This resolves a bug when converting Ps output containing non-standard characters (such as the minus sign) to Pdf using ps2pdf/gs 8.7 or later. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py trunk/matplotlib/ttconv/pprdrv_tt.cpp Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2010-02-08 17:50:27 UTC (rev 8121) +++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py 2010-02-09 13:04:44 UTC (rev 8122) @@ -396,7 +396,7 @@ imagecmd = "false 3 colorimage" return h, w, bits, imagecmd - + def draw_image(self, gc, x, y, im, dx=None, dy=None, transform=None): """ Draw the Image instance into the current axes; x is the @@ -1110,6 +1110,14 @@ for c in chars: gind = cmap.get(c) or 0 glyph_ids.append(gind) + + fonttype = rcParams['ps.fonttype'] + + # Can not use more than 255 characters from a + # single font for Type 3 + if len(glyph_ids) > 255: + fonttype = 42 + # The ttf to ps (subsetting) support doesn't work for # OpenType fonts that are Postscript inside (like the # STIX fonts). This will simply turn that off to avoid @@ -1118,7 +1126,7 @@ raise RuntimeError("OpenType CFF fonts can not be saved using the internal Postscript backend at this time.\nConsider using the Cairo backend.") else: fonttype = rcParams['ps.fonttype'] - convert_ttf_to_ps(font_filename, fh, rcParams['ps.fonttype'], glyph_ids) + convert_ttf_to_ps(font_filename, fh, fonttype, glyph_ids) print >>fh, "end" print >>fh, "%%EndProlog" @@ -1394,7 +1402,7 @@ """ paper_option = "-sPAPERSIZE=%s" % ptype - + psfile = tmpfile + '.ps' outfile = tmpfile + '.output' dpi = rcParams['ps.distiller.res'] @@ -1436,7 +1444,7 @@ if eps: paper_option = "-dEPSCrop" else: paper_option = "-sPAPERSIZE=%s" % ptype - + command = 'ps2pdf -dAutoFilterColorImages=false \ -sColorImageFilter=FlateEncode %s "%s" "%s" > "%s"'% \ (paper_option, tmpfile, pdffile, outfile) Modified: trunk/matplotlib/ttconv/pprdrv_tt.cpp =================================================================== --- trunk/matplotlib/ttconv/pprdrv_tt.cpp 2010-02-08 17:50:27 UTC (rev 8121) +++ trunk/matplotlib/ttconv/pprdrv_tt.cpp 2010-02-09 13:04:44 UTC (rev 8122) @@ -58,10 +58,10 @@ ULONG val=0; for(x=0; x<4; x++) - { - val *= 0x100; - val += p[x]; - } + { + val *= 0x100; + val += p[x]; + } return val; } /* end of ftohULONG() */ @@ -75,10 +75,10 @@ USHORT val=0; for(x=0; x<2; x++) - { - val *= 0x100; - val += p[x]; - } + { + val *= 0x100; + val += p[x]; + } return val; } /* end of getUSHORT() */ @@ -120,38 +120,38 @@ ptr = font->offset_table + 12; x=0; while(TRUE) - { - if( strncmp((const char*)ptr,name,4) == 0 ) - { - ULONG offset,length; - BYTE *table; + { + if( strncmp((const char*)ptr,name,4) == 0 ) + { + ULONG offset,length; + BYTE *table; - offset = getULONG( ptr + 8 ); - length = getULONG( ptr + 12 ); - table = (BYTE*)calloc( sizeof(BYTE), length ); + offset = getULONG( ptr + 8 ); + length = getULONG( ptr + 12 ); + table = (BYTE*)calloc( sizeof(BYTE), length ); - try { + try { #ifdef DEBUG_TRUETYPE - debug("Loading table \"%s\" from offset %d, %d bytes",name,offset,length); + debug("Loading table \"%s\" from offset %d, %d bytes",name,offset,length); #endif - if( fseek( font->file, (long)offset, SEEK_SET ) ) - throw TTException("TrueType font may be corrupt (reason 3)"); + if( fseek( font->file, (long)offset, SEEK_SET ) ) + throw TTException("TrueType font may be corrupt (reason 3)"); - if( fread(table,sizeof(BYTE),length,font->file) != (sizeof(BYTE) * length)) - throw TTException("TrueType font may be corrupt (reason 4)"); - } catch (TTException& ) { - free(table); - throw; - } - return table; - } + if( fread(table,sizeof(BYTE),length,font->file) != (sizeof(BYTE) * length)) + throw TTException("TrueType font may be corrupt (reason 4)"); + } catch (TTException& ) { + free(table); + throw; + } + return table; + } - x++; - ptr += 16; - if(x == font->numTables) - throw TTException("TrueType font is missing table"); - } + x++; + ptr += 16; + if(x == font->numTables) + throw TTException("TrueType font is missing table"); + } } /* end of GetTable() */ @@ -165,12 +165,12 @@ void Read_name(struct TTFONT *font) { BYTE *table_ptr,*ptr2; - int numrecords; /* Number of strings in this table */ - BYTE *strings; /* pointer to start of string storage */ + int numrecords; /* Number of strings in this table */ + BYTE *strings; /* pointer to start of string storage */ int x; - int platform,encoding; /* Current platform id, encoding id, */ - int language,nameid; /* language id, name id, */ - int offset,length; /* offset and length of string. */ + int platform,encoding; /* Current platform id, encoding id, */ + int language,nameid; /* language id, name id, */ + int offset,length; /* offset and length of string. */ #ifdef DEBUG_TRUETYPE debug("Read_name()"); @@ -192,136 +192,136 @@ } font->Copyright = font->Trademark = (char*)NULL; - table_ptr = GetTable(font, "name"); /* pointer to table */ + table_ptr = GetTable(font, "name"); /* pointer to table */ try { - numrecords = getUSHORT( table_ptr + 2 ); /* number of names */ - strings = table_ptr + getUSHORT( table_ptr + 4 ); /* start of string storage */ + numrecords = getUSHORT( table_ptr + 2 ); /* number of names */ + strings = table_ptr + getUSHORT( table_ptr + 4 ); /* start of string storage */ ptr2 = table_ptr + 6; for(x=0; x < numrecords; x++,ptr2+=12) - { - platform = getUSHORT(ptr2); - encoding = getUSHORT(ptr2+2); - language = getUSHORT(ptr2+4); - nameid = getUSHORT(ptr2+6); - length = getUSHORT(ptr2+8); - offset = getUSHORT(ptr2+10); + { + platform = getUSHORT(ptr2); + encoding = getUSHORT(ptr2+2); + language = getUSHORT(ptr2+4); + nameid = getUSHORT(ptr2+6); + length = getUSHORT(ptr2+8); + offset = getUSHORT(ptr2+10); #ifdef DEBUG_TRUETYPE - debug("platform %d, encoding %d, language 0x%x, name %d, offset %d, length %d", - platform,encoding,language,nameid,offset,length); + debug("platform %d, encoding %d, language 0x%x, name %d, offset %d, length %d", + platform,encoding,language,nameid,offset,length); #endif - /* Copyright notice */ - if( platform == 1 && nameid == 0 ) - { - font->Copyright = (char*)calloc(sizeof(char),length+1); - strncpy(font->Copyright,(const char*)strings+offset,length); - font->Copyright[length]=(char)NULL; - replace_newlines_with_spaces(font->Copyright); + /* Copyright notice */ + if( platform == 1 && nameid == 0 ) + { + font->Copyright = (char*)calloc(sizeof(char),length+1); + strncpy(font->Copyright,(const char*)strings+offset,length); + font->Copyright[length]=(char)NULL; + replace_newlines_with_spaces(font->Copyright); #ifdef DEBUG_TRUETYPE - debug("font->Copyright=\"%s\"",font->Copyright); + debug("font->Copyright=\"%s\"",font->Copyright); #endif - continue; - } + continue; + } - /* Font Family name */ - if( platform == 1 && nameid == 1 ) - { - free(font->FamilyName); - font->FamilyName = (char*)calloc(sizeof(char),length+1); - strncpy(font->FamilyName,(const char*)strings+offset,length); - font->FamilyName[length]=(char)NULL; - replace_newlines_with_spaces(font->FamilyName); + /* Font Family name */ + if( platform == 1 && nameid == 1 ) + { + free(font->FamilyName); + font->FamilyName = (char*)calloc(sizeof(char),length+1); + strncpy(font->FamilyName,(const char*)strings+offset,length); + font->FamilyName[length]=(char)NULL; + replace_newlines_with_spaces(font->FamilyName); #ifdef DEBUG_TRUETYPE - debug("font->FamilyName=\"%s\"",font->FamilyName); + debug("font->FamilyName=\"%s\"",font->FamilyName); #endif - continue; - } + continue; + } - /* Font Family name */ - if( platform == 1 && nameid == 2 ) - { - free(font->Style); - font->Style = (char*)calloc(sizeof(char),length+1); - strncpy(font->Style,(const char*)strings+offset,length); - font->Style[length]=(char)NULL; - replace_newlines_with_spaces(font->Style); + /* Font Family name */ + if( platform == 1 && nameid == 2 ) + { + free(font->Style); + font->Style = (char*)calloc(sizeof(char),length+1); + strncpy(font->Style,(const char*)strings+offset,length); + font->Style[length]=(char)NULL; + replace_newlines_with_spaces(font->Style); #ifdef DEBUG_TRUETYPE - debug("font->Style=\"%s\"",font->Style); + debug("font->Style=\"%s\"",font->Style); #endif - continue; - } + continue; + } - /* Full Font name */ - if( platform == 1 && nameid == 4 ) - { - free(font->FullName); - font->FullName = (char*)calloc(sizeof(char),length+1); - strncpy(font->FullName,(const char*)strings+offset,length); - font->FullName[length]=(char)NULL; - replace_newlines_with_spaces(font->FullName); + /* Full Font name */ + if( platform == 1 && nameid == 4 ) + { + free(font->FullName); + font->FullName = (char*)calloc(sizeof(char),length+1); + strncpy(font->FullName,(const char*)strings+offset,length); + font->FullName[length]=(char)NULL; + replace_newlines_with_spaces(font->FullName); #ifdef DEBUG_TRUETYPE - debug("font->FullName=\"%s\"",font->FullName); + debug("font->FullName=\"%s\"",font->FullName); #endif - continue; - } + continue; + } - /* Version string */ - if( platform == 1 && nameid == 5 ) - { - free(font->Version); - font->Version = (char*)calloc(sizeof(char),length+1); - strncpy(font->Version,(const char*)strings+offset,length); - font->Version[length]=(char)NULL; - replace_newlines_with_spaces(font->Version); + /* Version string */ + if( platform == 1 && nameid == 5 ) + { + free(font->Version); + font->Version = (char*)calloc(sizeof(char),length+1); + strncpy(font->Version,(const char*)strings+offset,length); + font->Version[length]=(char)NULL; + replace_newlines_with_spaces(font->Version); #ifdef DEBUG_TRUETYPE - debug("font->Version=\"%s\"",font->Version); + debug("font->Version=\"%s\"",font->Version); #endif - continue; - } + continue; + } - /* PostScript name */ - if( platform == 1 && nameid == 6 ) - { - free(font->PostName); - font->PostName = (char*)calloc(sizeof(char),length+1); - strncpy(font->PostName,(const char*)strings+offset,length); - font->PostName[length]=(char)NULL; - replace_newlines_with_spaces(font->PostName); + /* PostScript name */ + if( platform == 1 && nameid == 6 ) + { + free(font->PostName); + font->PostName = (char*)calloc(sizeof(char),length+1); + strncpy(font->PostName,(const char*)strings+offset,length); + font->PostName[length]=(char)NULL; + replace_newlines_with_spaces(font->PostName); #ifdef DEBUG_TRUETYPE - debug("font->PostName=\"%s\"",font->PostName); + debug("font->PostName=\"%s\"",font->PostName); #endif - continue; - } + continue; + } - /* Trademark string */ - if( platform == 1 && nameid == 7 ) - { - font->Trademark = (char*)calloc(sizeof(char),length+1); - strncpy(font->Trademark,(const char*)strings+offset,length); - font->Trademark[length]=(char)NULL; - replace_newlines_with_spaces(font->Trademark); + /* Trademark string */ + if( platform == 1 && nameid == 7 ) + { + font->Trademark = (char*)calloc(sizeof(char),length+1); + strncpy(font->Trademark,(const char*)strings+offset,length); + font->Trademark[length]=(char)NULL; + replace_newlines_with_spaces(font->Trademark); #ifdef DEBUG_TRUETYPE - debug("font->Trademark=\"%s\"",font->Trademark); + debug("font->Trademark=\"%s\"",font->Trademark); #endif - continue; - } + continue; + } - } + } } catch (TTException& ) { free(table_ptr); throw; @@ -346,17 +346,17 @@ ** font manufacturer's revision number for the font. */ if( font->target_type == PS_TYPE_42 ) - { - stream.printf("%%!PS-TrueTypeFont-%d.%d-%d.%d\n", - font->TTVersion.whole, font->TTVersion.fraction, - font->MfrRevision.whole, font->MfrRevision.fraction); - } + { + stream.printf("%%!PS-TrueTypeFont-%d.%d-%d.%d\n", + font->TTVersion.whole, font->TTVersion.fraction, + font->MfrRevision.whole, font->MfrRevision.fraction); + } /* If it is not a Type 42 font, we will use a different format. */ else - { - stream.putline("%!PS-Adobe-3.0 Resource-Font"); - } /* See RBIIp 641 */ + { + stream.putline("%!PS-Adobe-3.0 Resource-Font"); + } /* See RBIIp 641 */ /* We will make the title the name of the font. */ stream.printf("%%%%Title: %s\n",font->FullName); @@ -367,46 +367,46 @@ /* We created this file. */ if( font->target_type == PS_TYPE_42 ) - stream.putline("%%Creator: Converted from TrueType to type 42 by PPR"); + stream.putline("%%Creator: Converted from TrueType to type 42 by PPR"); else - stream.putline("%%Creator: Converted from TrueType by PPR"); + stream.putline("%%Creator: Converted from TrueType by PPR"); /* If VM usage information is available, print it. */ if( font->target_type == PS_TYPE_42 ) - { - VMMin = (int)getULONG( font->post_table + 16 ); - VMMax = (int)getULONG( font->post_table + 20 ); - if( VMMin > 0 && VMMax > 0 ) - stream.printf("%%%%VMUsage: %d %d\n",VMMin,VMMax); - } + { + VMMin = (int)getULONG( font->post_table + 16 ); + VMMax = (int)getULONG( font->post_table + 20 ); + if( VMMin > 0 && VMMax > 0 ) + stream.printf("%%%%VMUsage: %d %d\n",VMMin,VMMax); + } /* Start the dictionary which will eventually */ /* become the font. */ if( font->target_type != PS_TYPE_3 ) - { - stream.putline("15 dict begin"); - } + { + stream.putline("15 dict begin"); + } else - { - stream.putline("25 dict begin"); + { + stream.putline("25 dict begin"); - /* Type 3 fonts will need some subroutines here. */ - stream.putline("/_d{bind def}bind def"); - stream.putline("/_m{moveto}_d"); - stream.putline("/_l{lineto}_d"); - stream.putline("/_cl{closepath eofill}_d"); - stream.putline("/_c{curveto}_d"); - stream.putline("/_sc{7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse}_d"); - stream.putline("/_e{exec}_d"); - } + /* Type 3 fonts will need some subroutines here. */ + stream.putline("/_d{bind def}bind def"); + stream.putline("/_m{moveto}_d"); + stream.putline("/_l{lineto}_d"); + stream.putline("/_cl{closepath eofill}_d"); + stream.putline("/_c{curveto}_d"); + stream.putline("/_sc{7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse}_d"); + stream.putline("/_e{exec}_d"); + } stream.printf("/FontName /%s def\n",font->PostName); stream.putline("/PaintType 0 def"); if(font->target_type == PS_TYPE_42) - stream.putline("/FontMatrix[1 0 0 1 0 0]def"); + stream.putline("/FontMatrix[1 0 0 1 0 0]def"); else - stream.putline("/FontMatrix[.001 0 0 .001 0 0]def"); + stream.putline("/FontMatrix[.001 0 0 .001 0 0]def"); stream.printf("/FontBBox[%d %d %d %d]def\n",font->llx,font->lly,font->urx,font->ury); stream.printf("/FontType %d def\n", font->target_type ); @@ -414,11 +414,25 @@ /*------------------------------------------------------------- ** Define the encoding array for this font. -** It seems best to just use "Standard". +** Since we don't really want to deal with converting all of +** the possible font encodings in the wild to a standard PS +** one, we just explicitly create one for each font. -------------------------------------------------------------*/ -void ttfont_encoding(TTStreamWriter& stream) +void ttfont_encoding(TTStreamWriter& stream, struct TTFONT *font, std::vector<int>& glyph_ids, font_type_enum target_type) { - stream.putline("/Encoding StandardEncoding def"); + if (target_type == PS_TYPE_3) { + stream.printf("/Encoding [ "); + + for (std::vector<int>::const_iterator i = glyph_ids.begin(); + i != glyph_ids.end(); ++i) { + const char* name = ttfont_CharStrings_getname(font, *i); + stream.printf("/%s ", name); + } + + stream.printf("] def\n"); + } else { + stream.putline("/Encoding StandardEncoding def"); + } } /* end of ttfont_encoding() */ /*----------------------------------------------------------- @@ -439,13 +453,13 @@ stream.printf("/FullName (%s) def\n",font->FullName); if( font->Copyright != (char*)NULL || font->Trademark != (char*)NULL ) - { - stream.printf("/Notice (%s", - font->Copyright != (char*)NULL ? font->Copyright : ""); - stream.printf("%s%s) def\n", - font->Trademark != (char*)NULL ? " " : "", - font->Trademark != (char*)NULL ? font->Trademark : ""); - } + { + stream.printf("/Notice (%s", + font->Copyright != (char*)NULL ? font->Copyright : ""); + stream.printf("%s%s) def\n", + font->Trademark != (char*)NULL ? " " : "", + font->Trademark != (char*)NULL ? font->Trademark : ""); + } /* This information is not quite correct. */ stream.printf("/Weight (%s) def\n",font->Style); @@ -494,12 +508,12 @@ static const char hexdigits[]="0123456789ABCDEF"; if(!in_string) - { - stream.put_char('<'); - string_len=0; - line_len++; - in_string=TRUE; - } + { + stream.put_char('<'); + string_len=0; + line_len++; + in_string=TRUE; + } stream.put_char( hexdigits[ n / 16 ] ); stream.put_char( hexdigits[ n % 16 ] ); @@ -507,10 +521,10 @@ line_len+=2; if(line_len > 70) - { - stream.put_char('\n'); - line_len=0; - } + { + stream.put_char('\n'); + line_len=0; + } } /* end of sfnts_pputBYTE() */ @@ -553,17 +567,17 @@ void sfnts_end_string(TTStreamWriter& stream) { if(in_string) - { - string_len=0; /* fool sfnts_pputBYTE() */ + { + string_len=0; /* fool sfnts_pputBYTE() */ - #ifdef DEBUG_TRUETYPE_INLINE - puts("\n% dummy byte:\n"); - #endif + #ifdef DEBUG_TRUETYPE_INLINE + puts("\n% dummy byte:\n"); + #endif - sfnts_pputBYTE(stream, 0); /* extra byte for pre-2013 compatibility */ - stream.put_char('>'); - line_len++; - } + sfnts_pputBYTE(stream, 0); /* extra byte for pre-2013 compatibility */ + stream.put_char('>'); + line_len++; + } in_string=FALSE; } /* end of sfnts_end_string() */ @@ -589,7 +603,7 @@ ULONG off; ULONG length; int c; - ULONG total=0; /* running total of bytes written to table */ + ULONG total=0; /* running total of bytes written to table */ int x; #ifdef DEBUG_TRUETYPE @@ -604,58 +618,58 @@ /* Copy the glyphs one by one */ for(x=0; x < font->numGlyphs; x++) - { - /* Read the glyph offset from the index-to-location table. */ - if(font->indexToLocFormat == 0) - { - off = getUSHORT( font->loca_table + (x * 2) ); - off *= 2; - length = getUSHORT( font->loca_table + ((x+1) * 2) ); - length *= 2; - length -= off; - } - else - { - off = getULONG( font->loca_table + (x * 4) ); - length = getULONG( font->loca_table + ((x+1) * 4) ); - length -= off; - } + { + /* Read the glyph offset from the index-to-location table. */ + if(font->indexToLocFormat == 0) + { + off = getUSHORT( font->loca_table + (x * 2) ); + off *= 2; + length = getUSHORT( font->loca_table + ((x+1) * 2) ); + length *= 2; + length -= off; + } + else + { + off = getULONG( font->loca_table + (x * 4) ); + length = getULONG( font->loca_table + ((x+1) * 4) ); + length -= off; + } - #ifdef DEBUG_TRUETYPE - debug("glyph length=%d",(int)length); - #endif + #ifdef DEBUG_TRUETYPE + debug("glyph length=%d",(int)length); + #endif - /* Start new string if necessary. */ - sfnts_new_table( stream, (int)length ); + /* Start new string if necessary. */ + sfnts_new_table( stream, (int)length ); - /* - ** Make sure the glyph is padded out to a - ** two byte boundary. - */ - if( length % 2 ) - throw TTException("TrueType font contains a 'glyf' table without 2 byte padding"); + /* + ** Make sure the glyph is padded out to a + ** two byte boundary. + */ + if( length % 2 ) + throw TTException("TrueType font contains a 'glyf' table without 2 byte padding"); - /* Copy the bytes of the glyph. */ - while( length-- ) - { - if( (c = fgetc(font->file)) == EOF ) - throw TTException("TrueType font may be corrupt (reason 6)"); + /* Copy the bytes of the glyph. */ + while( length-- ) + { + if( (c = fgetc(font->file)) == EOF ) + throw TTException("TrueType font may be corrupt (reason 6)"); - sfnts_pputBYTE(stream, c); - total++; /* add to running total */ - } + sfnts_pputBYTE(stream, c); + total++; /* add to running total */ + } - } + } free(font->loca_table); font->loca_table = NULL; /* Pad out to full length from table directory */ while( total < correct_total_length ) - { - sfnts_pputBYTE(stream, 0); - total++; - } + { + sfnts_pputBYTE(stream, 0); + total++; + } } /* end of sfnts_glyf_table() */ @@ -667,32 +681,32 @@ */ void ttfont_sfnts(TTStreamWriter& stream, struct TTFONT *font) { - static const char *table_names[] = /* The names of all tables */ - { /* which it is worth while */ - "cvt ", /* to include in a Type 42 */ - "fpgm", /* PostScript font. */ - "glyf", - "head", - "hhea", - "hmtx", - "loca", - "maxp", - "prep" - } ; + static const char *table_names[] = /* The names of all tables */ + { /* which it is worth while */ + "cvt ", /* to include in a Type 42 */ + "fpgm", /* PostScript font. */ + "glyf", + "head", + "hhea", + "hmtx", + "loca", + "maxp", + "prep" + } ; - struct { /* The location of each of */ - ULONG oldoffset; /* the above tables. */ - ULONG newoffset; - ULONG length; - ULONG checksum; - } tables[9]; + struct { /* The location of each of */ + ULONG oldoffset; /* the above tables. */ + ULONG newoffset; + ULONG length; + ULONG checksum; + } tables[9]; - BYTE *ptr; /* A pointer into the origional table directory. */ - ULONG x,y; /* General use loop countes. */ - int c; /* Input character. */ + BYTE *ptr; /* A pointer into the origional table directory. */ + ULONG x,y; /* General use loop countes. */ + int c; /* Input character. */ int diff; ULONG nextoffset; - int count; /* How many `important' tables did we find? */ + int count; /* How many `important' tables did we find? */ ptr = font->offset_table + 12; nextoffset=0; @@ -703,32 +717,32 @@ ** statistics in tables[]. */ for(x=0; x < 9; x++ ) - { - do { - diff = strncmp( (char*)ptr, table_names[x], 4 ); + { + do { + diff = strncmp( (char*)ptr, table_names[x], 4 ); - if( diff > 0 ) /* If we are past it. */ - { - tables[x].length = 0; - diff = 0; - } - else if( diff < 0 ) /* If we haven't hit it yet. */ - { - ptr += 16; - } - else if( diff == 0 ) /* Here it is! */ - { - tables[x].newoffset = nextoffset; - tables[x].checksum = getULONG( ptr + 4 ); - tables[x].oldoffset = getULONG( ptr + 8 ); - tables[x].length = getULONG( ptr + 12 ); - nextoffset += ( ((tables[x].length + 3) / 4) * 4 ); - count++; - ptr += 16; - } - } while(diff != 0); + if( diff > 0 ) /* If we are past it. */ + { + tables[x].length = 0; + diff = 0; + } + else if( diff < 0 ) /* If we haven't hit it yet. */ + { + ptr += 16; + } + else if( diff == 0 ) /* Here it is! */ + { + tables[x].newoffset = nextoffset; + tables[x].checksum = getULONG( ptr + 4 ); + tables[x].oldoffset = getULONG( ptr + 8 ); + tables[x].length = getULONG( ptr + 12 ); + nextoffset += ( ((tables[x].length + 3) / 4) * 4 ); + count++; + ptr += 16; + } + } while(diff != 0); - } /* end of for loop which passes over the table directory */ + } /* end of for loop which passes over the table directory */ /* Begin the sfnts array. */ sfnts_start(stream); @@ -737,95 +751,95 @@ /* Start by copying the TrueType version number. */ ptr = font->offset_table; for(x=0; x < 4; x++) - { - sfnts_pputBYTE( stream, *(ptr++) ); - } + { + sfnts_pputBYTE( stream, *(ptr++) ); + } /* Now, generate those silly numTables numbers. */ - sfnts_pputUSHORT(stream, count); /* number of tables */ + sfnts_pputUSHORT(stream, count); /* number of tables */ if( count == 9 ) - { - sfnts_pputUSHORT(stream, 7); /* searchRange */ - sfnts_pputUSHORT(stream, 3); /* entrySelector */ - sfnts_pputUSHORT(stream, 81); /* rangeShift */ - } + { + sfnts_pputUSHORT(stream, 7); /* searchRange */ + sfnts_pputUSHORT(stream, 3); /* entrySelector */ + sfnts_pputUSHORT(stream, 81); /* rangeShift */ + } #ifdef DEBUG_TRUETYPE else - { - debug("only %d tables selected",count); - } + { + debug("only %d tables selected",count); + } #endif /* Now, emmit the table directory. */ for(x=0; x < 9; x++) - { - if( tables[x].length == 0 ) /* Skip missing tables */ - continue; + { + if( tables[x].length == 0 ) /* Skip missing tables */ + continue; - /* Name */ - sfnts_pputBYTE( stream, table_names[x][0] ); - sfnts_pputBYTE( stream, table_names[x][1] ); - sfnts_pputBYTE( stream, table_names[x][2] ); - sfnts_pputBYTE( stream, table_names[x][3] ); + /* Name */ + sfnts_pputBYTE( stream, table_names[x][0] ); + sfnts_pputBYTE( stream, table_names[x][1] ); + sfnts_pputBYTE( stream, table_names[x][2] ); + sfnts_pputBYTE( stream, table_names[x][3] ); - /* Checksum */ - sfnts_pputULONG( stream, tables[x].checksum ); + /* Checksum */ + sfnts_pputULONG( stream, tables[x].checksum ); - /* Offset */ - sfnts_pputULONG( stream, tables[x].newoffset + 12 + (count * 16) ); + /* Offset */ + sfnts_pputULONG( stream, tables[x].newoffset + 12 + (count * 16) ); - /* Length */ - sfnts_pputULONG( stream, tables[x].length ); - } + /* Length */ + sfnts_pputULONG( stream, tables[x].length ); + } /* Now, send the tables */ for(x=0; x < 9; x++) - { - if( tables[x].length == 0 ) /* skip tables that aren't there */ - continue; + { + if( tables[x].length == 0 ) /* skip tables that aren't there */ + continue; - #ifdef DEBUG_TRUETYPE - debug("emmiting table '%s'",table_names[x]); - #endif + #ifdef DEBUG_TRUETYPE + debug("emmiting table '%s'",table_names[x]); + #endif - /* 'glyf' table gets special treatment */ - if( strcmp(table_names[x],"glyf")==0 ) - { - sfnts_glyf_table(stream,font,tables[x].oldoffset,tables[x].length); - } - else /* Other tables may not exceed */ - { /* 65535 bytes in length. */ - if( tables[x].length > 65535 ) - throw TTException("TrueType font has a table which is too long"); + /* 'glyf' table gets special treatment */ + if( strcmp(table_names[x],"glyf")==0 ) + { + sfnts_glyf_table(stream,font,tables[x].oldoffset,tables[x].length); + } + else /* Other tables may not exceed */ + { /* 65535 bytes in length. */ + if( tables[x].length > 65535 ) + throw TTException("TrueType font has a table which is too long"); - /* Start new string if necessary. */ - sfnts_new_table(stream, tables[x].length); + /* Start new string if necessary. */ + sfnts_new_table(stream, tables[x].length); - /* Seek to proper position in the file. */ - fseek( font->file, tables[x].oldoffset, SEEK_SET ); + /* Seek to proper position in the file. */ + fseek( font->file, tables[x].oldoffset, SEEK_SET ); - /* Copy the bytes of the table. */ - for( y=0; y < tables[x].length; y++ ) - { - if( (c = fgetc(font->file)) == EOF ) - throw TTException("TrueType font may be corrupt (reason 7)"); + /* Copy the bytes of the table. */ + for( y=0; y < tables[x].length; y++ ) + { + if( (c = fgetc(font->file)) == EOF ) + throw TTException("TrueType font may be corrupt (reason 7)"); - sfnts_pputBYTE(stream, c); - } - } + sfnts_pputBYTE(stream, c); + } + } - /* Padd it out to a four byte boundary. */ - y=tables[x].length; - while( (y % 4) != 0 ) - { - sfnts_pputBYTE(stream, 0); - y++; - #ifdef DEBUG_TRUETYPE_INLINE - puts("\n% pad byte:\n"); - #endif - } + /* Padd it out to a four byte boundary. */ + y=tables[x].length; + while( (y % 4) != 0 ) + { + sfnts_pputBYTE(stream, 0); + y++; + #ifdef DEBUG_TRUETYPE_INLINE + puts("\n% pad byte:\n"); + #endif + } - } /* End of loop for all tables */ + } /* End of loop for all tables */ /* Close the array. */ sfnts_end_string(stream); @@ -893,32 +907,32 @@ GlyphIndex = (int)getUSHORT( font->post_table + 34 + (charindex * 2) ); - if( GlyphIndex <= 257 ) /* If a standard Apple name, */ - { - return Apple_CharStrings[GlyphIndex]; - } - else /* Otherwise, use one */ - { /* of the pascal strings. */ - GlyphIndex -= 258; + if( GlyphIndex <= 257 ) /* If a standard Apple name, */ + { + return Apple_CharStrings[GlyphIndex]; + } + else /* Otherwise, use one */ + { /* of the pascal strings. */ + GlyphIndex -= 258; - /* Set pointer to start of Pascal strings. */ - ptr = (char*)(font->post_table + 34 + (font->numGlyphs * 2)); + /* Set pointer to start of Pascal strings. */ + ptr = (char*)(font->post_table + 34 + (font->numGlyphs * 2)); - len = (ULONG)*(ptr++); /* Step thru the strings */ - while(GlyphIndex--) /* until we get to the one */ - { /* that we want. */ - ptr += len; - len = (ULONG)*(ptr++); - } + len = (ULONG)*(ptr++); /* Step thru the strings */ + while(GlyphIndex--) /* until we get to the one */ + { /* that we want. */ + ptr += len; + len = (ULONG)*(ptr++); + } - if( len >= sizeof(temp) ) - throw TTException("TrueType font file contains a very long PostScript name"); + if( len >= sizeof(temp) ) + throw TTException("TrueType font file contains a very long PostScript name"); - strncpy(temp,ptr,len); /* Copy the pascal string into */ - temp[len]=(char)NULL; /* a buffer and make it ASCIIz. */ + strncpy(temp,ptr,len); /* Copy the pascal string into */ + temp[len]=(char)NULL; /* a buffer and make it ASCIIz. */ - return temp; - } + return temp; + } } /* end of ttfont_CharStrings_getname() */ /* @@ -932,28 +946,28 @@ post_format = getFixed( font->post_table ); if( post_format.whole != 2 || post_format.fraction != 0 ) - throw TTException("TrueType fontdoes not have a format 2.0 'post' table"); + throw TTException("TrueType fontdoes not have a format 2.0 'post' table"); /* Emmit the start of the PostScript code to define the dictionary. */ stream.printf("/CharStrings %d dict dup begin\n", glyph_ids.size()); /* Emmit one key-value pair for each glyph. */ for(std::vector<int>::const_iterator i = glyph_ids.begin(); - i != glyph_ids.end(); ++i) - { - if(font->target_type == PS_TYPE_42) /* type 42 */ - { - stream.printf("/%s %d def\n",ttfont_CharStrings_getname(font, *i), *i); - } - else /* type 3 */ - { - stream.printf("/%s{",ttfont_CharStrings_getname(font, *i)); + i != glyph_ids.end(); ++i) + { + if(font->target_type == PS_TYPE_42) /* type 42 */ + { + stream.printf("/%s %d def\n",ttfont_CharStrings_getname(font, *i), *i); + } + else /* type 3 */ + { + stream.printf("/%s{",ttfont_CharStrings_getname(font, *i)); - tt_type3_charproc(stream, font, *i); + tt_type3_charproc(stream, font, *i); - stream.putline("}_d"); /* "} bind def" */ - } - } + stream.putline("}_d"); /* "} bind def" */ + } + } stream.putline("end readonly def"); } /* end of ttfont_CharStrings() */ @@ -967,27 +981,27 @@ /* If we are generating a type 3 font, we need to provide */ /* a BuildGlyph and BuildChar proceedures. */ if( font->target_type == PS_TYPE_3 ) - { - stream.put_char('\n'); + { + stream.put_char('\n'); - stream.putline("/BuildGlyph"); - stream.putline(" {exch begin"); /* start font dictionary */ - stream.putline(" CharStrings exch"); - stream.putline(" 2 copy known not{pop /.notdef}if"); - stream.putline(" true 3 1 roll get exec"); - stream.putline(" end}_d"); + stream.putline("/BuildGlyph"); + stream.putline(" {exch begin"); /* start font dictionary */ + stream.putline(" CharStrings exch"); + stream.putline(" 2 copy known not{pop /.notdef}if"); + stream.putline(" true 3 1 roll get exec"); + stream.putline(" end}_d"); - stream.put_char('\n'); + stream.put_char('\n'); - /* This proceedure is for compatiblity with */ - /* level 1 interpreters. */ - stream.putline("/BuildChar {"); - stream.putline(" 1 index /Encoding get exch get"); - stream.putline(" 1 index /BuildGlyph get exec"); - stream.putline("}_d"); + /* This proceedure is for compatiblity with */ + /* level 1 interpreters. */ + stream.putline("/BuildChar {"); + stream.putline(" 1 index /Encoding get exch get"); + stream.putline(" 1 index /BuildGlyph get exec"); + stream.putline("}_d"); - stream.put_char('\n'); - } + stream.put_char('\n'); + } /* If we are generating a type 42 font, we need to check to see */ /* if this PostScript interpreter understands type 42 fonts. If */ @@ -997,90 +1011,90 @@ /* generated by a Macintosh. That is where the TrueType interpreter */ /* setup instructions and part of BuildGlyph came from. */ else if( font->target_type == PS_TYPE_42 ) - { - stream.put_char('\n'); + { + stream.put_char('\n'); - /* If we have no "resourcestatus" command, or FontType 42 */ - /* is unknown, leave "true" on the stack. */ - stream.putline("systemdict/resourcestatus known"); - stream.putline(" {42 /FontType resourcestatus"); - stream.putline(" {pop pop false}{true}ifelse}"); - stream.putline(" {true}ifelse"); + /* If we have no "resourcestatus" command, or FontType 42 */ + /* is unknown, leave "true" on the stack. */ + stream.putline("systemdict/resourcestatus known"); + stream.putline(" {42 /FontType resourcestatus"); + stream.putline(" {pop pop false}{true}ifelse}"); + stream.putline(" {true}ifelse"); - /* If true, execute code to produce an error message if */ - /* we can't find Apple's TrueDict in VM. */ - stream.putline("{/TrueDict where{pop}{(%%[ Error: no TrueType rasterizer ]%%)= flush}ifelse"); + /* If true, execute code to produce an error message if */ + /* we can't find Apple's TrueDict in VM. */ + stream.putline("{/TrueDict where{pop}{(%%[ Error: no TrueType rasterizer ]%%)= flush}ifelse"); - /* Since we are expected to use Apple's TrueDict TrueType */ - /* reasterizer, change the font type to 3. */ - stream.putline("/FontType 3 def"); + /* Since we are expected to use Apple's TrueDict TrueType */ + /* reasterizer, change the font type to 3. */ + stream.putline("/FontType 3 def"); - /* Define a string to hold the state of the Apple */ - /* TrueType interpreter. */ - stream.putline(" /TrueState 271 string def"); + /* Define a string to hold the state of the Apple */ + /* TrueType interpreter. */ + stream.putline(" /TrueState 271 string def"); - /* It looks like we get information about the resolution */ - /* of the printer and store it in the TrueState string. */ - stream.putline(" TrueDict begin sfnts save"); - stream.putline(" 72 0 matrix defaultmatrix dtransform dup"); - stream.putline(" mul exch dup mul add sqrt cvi 0 72 matrix"); - stream.putline(" defaultmatrix dtransform dup mul exch dup"); - stream.putline(" mul add sqrt cvi 3 -1 roll restore"); - stream.putline(" TrueState initer end"); + /* It looks like we get information about the resolution */ + /* of the printer and store it in the TrueState string. */ + stream.putline(" TrueDict begin sfnts save"); + stream.putline(" 72 0 matrix defaultmatrix dtransform dup"); + stream.putline(" mul exch dup mul add sqrt cvi 0 72 matrix"); + stream.putline(" defaultmatrix dtransform dup mul exch dup"); + stream.putline(" mul add sqrt cvi 3 -1 roll restore"); + stream.putline(" TrueState initer end"); - /* This BuildGlyph procedure will look the name up in the */ - /* CharStrings array, and then check to see if what it gets */ - /* is a procedure. If it is, it executes it, otherwise, it */ - /* lets the TrueType rasterizer loose on it. */ + /* This BuildGlyph procedure will look the name up in the */ + /* CharStrings array, and then check to see if what it gets */ + /* is a procedure. If it is, it executes it, otherwise, it */ + /* lets the TrueType rasterizer loose on it. */ - /* When this proceedure is executed the stack contains */ - /* the font dictionary and the character name. We */ - /* exchange arguments and move the dictionary to the */ - /* dictionary stack. */ - stream.putline(" /BuildGlyph{exch begin"); - /* stack: charname */ + /* When this proceedure is executed the stack contains */ + /* the font dictionary and the character name. We */ + /* exchange arguments and move the dictionary to the */ + /* dictionary stack. */ + stream.putline(" /BuildGlyph{exch begin"); + /* stack: charname */ - /* Put two copies of CharStrings on the stack and consume */ - /* one testing to see if the charname is defined in it, */ - /* leave the answer on the stack. */ - stream.putline(" CharStrings dup 2 index known"); - /* stack: charname CharStrings bool */ + /* Put two copies of CharStrings on the stack and consume */ + /* one testing to see if the charname is defined in it, */ + /* leave the answer on the stack. */ + stream.putline(" CharStrings dup 2 index known"); + /* stack: charname CharStrings bool */ - /* Exchange the CharStrings dictionary and the charname, */ - /* but if the answer was false, replace the character name */ - /* with ".notdef". */ - stream.putline(" {exch}{exch pop /.notdef}ifelse"); - /* stack: CharStrings charname */ + /* Exchange the CharStrings dictionary and the charname, */ + /* but if the answer was false, replace the character name */ + /* with ".notdef". */ + stream.putline(" {exch}{exch pop /.notdef}ifelse"); + /* stack: CharStrings charname */ - /* Get the value from the CharStrings dictionary and see */ - /* if it is executable. */ - stream.putline(" get dup xcheck"); - /* stack: CharStrings_entry */ + /* Get the value from the CharStrings dictionary and see */ + /* if it is executable. */ + stream.putline(" get dup xcheck"); + /* stack: CharStrings_entry */ - /* If is a proceedure. Execute according to RBIIp 277-278. */ - stream.putline(" {currentdict systemdict begin begin exec end end}"); + /* If is a proceedure. Execute according to RBIIp 277-278. */ + stream.putline(" {currentdict systemdict begin begin exec end end}"); - /* Is a TrueType character index, let the rasterizer at it. */ - stream.putline(" {TrueDict begin /bander load cvlit exch TrueState render end}"); + /* Is a TrueType character index, let the rasterizer at it. */ + stream.putline(" {TrueDict begin /bander load cvlit exch TrueState render end}"); - stream.putline(" ifelse"); + stream.putline(" ifelse"); - /* Pop the font's dictionary off the stack. */ - stream.putline(" end}bind def"); + /* Pop the font's dictionary off the stack. */ + stream.putline(" end}bind def"); - /* This is the level 1 compatibility BuildChar procedure. */ - /* See RBIIp 281. */ - stream.putline(" /BuildChar{"); - stream.putline(" 1 index /Encoding get exch get"); - stream.putline(" 1 index /BuildGlyph get exec"); - stream.putline(" }bind def"); + /* This is the level 1 compatibility BuildChar procedure. */ + /* See RBIIp 281. */ + stream.putline(" /BuildChar{"); + stream.putline(" 1 index /Encoding get exch get"); + stream.putline(" 1 index /BuildGlyph get exec"); + stream.putline(" }bind def"); - /* Here we close the condition which is true */ - /* if the printer has no built-in TrueType */ - /* rasterizer. */ - stream.putline("}if"); - stream.put_char('\n'); - } /* end of if Type 42 not understood. */ + /* Here we close the condition which is true */ + /* if the printer has no built-in TrueType */ + /* rasterizer. */ + stream.putline("}if"); + stream.put_char('\n'); + } /* end of if Type 42 not understood. */ stream.putline("FontName currentdict end definefont pop"); /* stream.putline("%%EOF"); */ @@ -1102,7 +1116,7 @@ /* Open the font file */ if( (font.file = fopen(filename,"rb")) == (FILE*)NULL ) - throw TTException("Failed to open TrueType font"); + throw TTException("Failed to open TrueType font"); /* Allocate space for the unvarying part of the offset table. */ assert(font.offset_table == NULL); @@ -1110,7 +1124,7 @@ /* Read the first part of the offset table. */ if( fread( font.offset_table, sizeof(BYTE), 12, font.file ) != 12 ) - throw TTException("TrueType font may be corrupt (reason 1)"); + throw TTException("TrueType font may be corrupt (reason 1)"); /* Determine how many directory entries there are. */ font.numTables = getUSHORT( font.offset_table + 4 ); @@ -1123,7 +1137,7 @@ /* Read the rest of the table directory. */ if( fread( font.offset_table + 12, sizeof(BYTE), (font.numTables*16), font.file ) != (font.numTables*16) ) - throw TTException("TrueType font may be corrupt (reason 2)"); + throw TTException("TrueType font may be corrupt (reason 2)"); /* Extract information from the "Offset" table. */ font.TTVersion = getFixed( font.offset_table ); @@ -1131,21 +1145,21 @@ /* Load the "head" table and extract information from it. */ ptr = GetTable(&font, "head"); try { - font.MfrRevision = getFixed( ptr + 4 ); /* font revision number */ + font.MfrRevision = getFixed( ptr + 4 ); /* font revision number */ font.unitsPerEm = getUSHORT( ptr + 18 ); font.HUPM = font.unitsPerEm / 2; #ifdef DEBUG_TRUETYPE debug("unitsPerEm=%d",(int)font.unitsPerEm); #endif - font.llx = topost2( getFWord( ptr + 36 ) ); /* bounding box info */ + font.llx = topost2( getFWord( ptr + 36 ) ); /* bounding box info */ font.lly = topost2( getFWord( ptr + 38 ) ); font.urx = topost2( getFWord( ptr + 40 ) ); font.ury = topost2( getFWord( ptr + 42 ) ); - font.indexToLocFormat = getSHORT( ptr + 50 ); /* size of 'loca' data */ + font.indexToLocFormat = getSHORT( ptr + 50 ); /* size of 'loca' data */ if(font.indexToLocFormat != 0 && font.indexToLocFormat != 1) - throw TTException("TrueType font is unusable because indexToLocFormat != 0"); + throw TTException("TrueType font is unusable because indexToLocFormat != 0"); if( getSHORT(ptr+52) != 0 ) - throw TTException("TrueType font is unusable because glyphDataFormat != 0"); + throw TTException("TrueType font is unusable because glyphDataFormat != 0"); } catch (TTException& ) { free(ptr); throw; @@ -1164,34 +1178,34 @@ /* have the 'loca' and 'glyf' tables arround while */ /* we are generating the CharStrings. */ if(font.target_type == PS_TYPE_3 || font.target_type == PDF_TYPE_3) - { - BYTE *ptr; /* We need only one value */ - ptr = GetTable(&font, "hhea"); - font.numberOfHMetrics = getUSHORT(ptr + 34); - free(ptr); + { + BYTE *ptr; /* We need only one value */ + ptr = GetTable(&font, "hhea"); + font.numberOfHMetrics = getUSHORT(ptr + 34); + free(ptr); - assert(font.loca_table == NULL); - font.loca_table = GetTable(&font,"loca"); - assert(font.glyf_table == NULL); - font.glyf_table = GetTable(&font,"glyf"); - assert(font.hmtx_table == NULL); - font.hmtx_table = GetTable(&font,"hmtx"); + assert(font.loca_table == NULL); + font.loca_table = GetTable(&font,"loca"); + assert(font.glyf_table == NULL); + font.glyf_table = GetTable(&font,"glyf"); + assert(font.hmtx_table == NULL); + font.hmtx_table = GetTable(&font,"hmtx"); } if (glyph_ids.size() == 0) { - glyph_ids.clear(); - glyph_ids.reserve(font.numGlyphs); - for (int x = 0; x < font.numGlyphs; ++x) { - glyph_ids.push_back(x); - } + glyph_ids.clear(); + glyph_ids.reserve(font.numGlyphs); + for (int x = 0; x < font.numGlyphs; ++x) { + glyph_ids.push_back(x); + } } else if (font.target_type == PS_TYPE_3) { - ttfont_add_glyph_dependencies(&font, glyph_ids); + ttfont_add_glyph_dependencies(&font, glyph_ids); } } /* end of insert_ttfont() */ void insert_ttfont(const char *filename, TTStreamWriter& stream, - font_type_enum target_type, std::vector<int>& glyph_ids) + font_type_enum target_type, std::vector<int>& glyph_ids) { struct TTFONT font; @@ -1201,7 +1215,7 @@ ttfont_header(stream, &font); /* Define the encoding. */ - ttfont_encoding(stream); + ttfont_encoding(stream, &font, glyph_ids, target_type); /* Insert FontInfo dictionary. */ ttfont_FontInfo(stream, &font); @@ -1224,10 +1238,10 @@ public: void write(const char* a) { - oss << a; + oss << a; } std::string str() { - return oss.str(); + return oss.str(); } }; @@ -1237,11 +1251,11 @@ read_font(filename, PDF_TYPE_3, glyph_ids, font); for (std::vector<int>::const_iterator i = glyph_ids.begin(); - i != glyph_ids.end(); ++i) { - StringStreamWriter writer; - tt_type3_charproc(writer, &font, *i); - const char* name = ttfont_CharStrings_getname(&font, *i); - dict.add_pair(name, writer.str().c_str()); + i != glyph_ids.end(); ++i) { + StringStreamWriter writer; + tt_type3_charproc(writer, &font, *i); + const char* name = ttfont_CharStrings_getname(&font, *i); + dict.add_pair(name, writer.str().c_str()); } } @@ -1263,7 +1277,7 @@ TTFONT::~TTFONT() { if (file) - fclose(file); + fclose(file); free(PostName); free(FullName); free(FamilyName); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ The Planet: dedicated and managed hosting, cloud storage, colocation Stay online with enterprise data centers and the best network in the business Choose flexible plans and management services without long-term contracts Personal 24x7 support from experience hosting pros just a phone call away. http://p.sf.net/sfu/theplanet-com _______________________________________________ Matplotlib-checkins mailing list Matplotlib-checkins@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins