Example #1
0
/*
** This is the central routine of this section.
*/
void ttfont_CharStrings(TTStreamWriter& stream, struct TTFONT *font, std::vector<int>& glyph_ids)
    {
    Fixed post_format;

    /* The 'post' table format number. */
    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");

    /* 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));

            tt_type3_charproc(stream, font, *i);

            stream.putline("}_d");      /* "} bind def" */
            }
        }

    stream.putline("end readonly def");
    } /* end of ttfont_CharStrings() */
Example #2
0
/*-----------------------------------------------------------
** Create the optional "FontInfo" sub-dictionary.
-----------------------------------------------------------*/
void ttfont_FontInfo(TTStreamWriter& stream, struct TTFONT *font)
{
    Fixed ItalicAngle;

    /* We create a sub dictionary named "FontInfo" where we */
    /* store information which though it is not used by the */
    /* interpreter, is useful to some programs which will */
    /* be printing with the font. */
    stream.putline("/FontInfo 10 dict dup begin");

    /* These names come from the TrueType font's "name" table. */
    stream.printf("/FamilyName (%s) def\n",font->FamilyName);
    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 : "");
    }

    /* This information is not quite correct. */
    stream.printf("/Weight (%s) def\n",font->Style);

    /* Some fonts have this as "version". */
    stream.printf("/Version (%s) def\n",font->Version);

    /* Some information from the "post" table. */
    ItalicAngle = getFixed( font->post_table + 4 );
    stream.printf("/ItalicAngle %d.%d def\n",ItalicAngle.whole,ItalicAngle.fraction);
    stream.printf("/isFixedPitch %s def\n", getULONG( font->post_table + 12 ) ? "true" : "false" );
    stream.printf("/UnderlinePosition %d def\n", (int)getFWord( font->post_table + 8 ) );
    stream.printf("/UnderlineThickness %d def\n", (int)getFWord( font->post_table + 10 ) );
    stream.putline("end readonly def");
} /* end of ttfont_FontInfo() */
Example #3
0
/*-------------------------------------------------------------
** Define the encoding array for this font.
** 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, 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() */
Example #4
0
/*
** Here is the routine which ties it all together.
**
** Create the array called "sfnts" which
** holds the actual TrueType data.
*/
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"
    } ;

    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. */
    int diff;
    ULONG nextoffset;
    int count;                  /* How many `important' tables did we find? */

    ptr = font->offset_table + 12;
    nextoffset=0;
    count=0;

    /*
    ** Find the tables we want and store there vital
    ** statistics in tables[].
    */
    for (x=0; x < 9; x++ )
    {
        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);

    } /* end of for loop which passes over the table directory */

    /* Begin the sfnts array. */
    sfnts_start(stream);

    /* Generate the offset table header */
    /* Start by copying the TrueType version number. */
    ptr = font->offset_table;
    for (x=0; x < 4; x++)
    {
        sfnts_pputBYTE( stream,  *(ptr++) );
    }

    /* Now, generate those silly numTables numbers. */
    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 */
    }
#ifdef DEBUG_TRUETYPE
    else
    {
        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;
        }

        /* 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 );

        /* Offset */
        sfnts_pputULONG( stream, tables[x].newoffset + 12 + (count * 16) );

        /* 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;
        }

#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");
            }

            /* 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 );

            /* 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);
            }
        }

        /* 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 */

    /* Close the array. */
    sfnts_end_string(stream);
    stream.putline("]def");
} /* end of ttfont_sfnts() */
Example #5
0
/*---------------------------------------------------------------------
** Write the header for a PostScript font.
---------------------------------------------------------------------*/
void ttfont_header(TTStreamWriter& stream, struct TTFONT *font)
{
    int VMMin;
    int VMMax;

    /*
    ** To show that it is a TrueType font in PostScript format,
    ** we will begin the file with a specific string.
    ** This string also indicates the version of the TrueType
    ** specification on which the font is based and the
    ** font manufacturer's revision number for the font.
    */
    if ( font->target_type == PS_TYPE_42 ||
            font->target_type == PS_TYPE_42_3_HYBRID)
    {
        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 */

    /* We will make the title the name of the font. */
    stream.printf("%%%%Title: %s\n",font->FullName);

    /* If there is a Copyright notice, put it here too. */
    if ( font->Copyright != (char*)NULL )
    {
        stream.printf("%%%%Copyright: %s\n",font->Copyright);
    }

    /* We created this file. */
    if ( font->target_type == PS_TYPE_42 )
    {
        stream.putline("%%Creator: Converted from TrueType to type 42 by PPR");
    }
    else if (font->target_type == PS_TYPE_42_3_HYBRID)
    {
        stream.putline("%%Creator: Converted from TypeType to type 42/type 3 hybrid by PPR");
    }
    else
    {
        stream.putline("%%Creator: Converted from TrueType to type 3 by PPR");
    }

    /* If VM usage information is available, print it. */
    if ( font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID)
    {
        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_42)
    {
        stream.putline("15 dict begin");
    }
    else
    {
        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");
    }

    stream.printf("/FontName /%s def\n",font->PostName);
    stream.putline("/PaintType 0 def");

    if (font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID)
    {
        stream.putline("/FontMatrix[1 0 0 1 0 0]def");
    }
    else
    {
        stream.putline("/FontMatrix[.001 0 0 .001 0 0]def");
    }

    stream.printf("/FontBBox[%d %d %d %d]def\n",font->llx-1,font->lly-1,font->urx,font->ury);
    if (font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID)
    {
        stream.printf("/FontType 42 def\n", font->target_type );
    }
    else
    {
        stream.printf("/FontType 3 def\n", font->target_type );
    }
} /* end of ttfont_header() */
Example #6
0
/*----------------------------------------------------------------
** Emmit the code to finish up the dictionary and turn
** it into a font.
----------------------------------------------------------------*/
void ttfont_trailer(TTStreamWriter& stream, struct TTFONT *font)
{
    /* If we are generating a type 3 font, we need to provide */
    /* a BuildGlyph and BuildChar proceedures. */
    if (font->target_type == PS_TYPE_3 ||
        font->target_type == PS_TYPE_42_3_HYBRID)
    {
        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.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");

        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 */
    /* it doesn't, we will hope that the Apple TrueType rasterizer */
    /* has been loaded and we will adjust the font accordingly. */
    /* I found out how to do this by examining a TrueType font */
    /* generated by a Macintosh.  That is where the TrueType interpreter */
    /* setup instructions and part of BuildGlyph came from. */
    if (font->target_type == PS_TYPE_42 ||
        font->target_type == PS_TYPE_42_3_HYBRID)
    {
        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 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");

        /* 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");

        /* 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 */

        /* 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 */

        /* 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}");

        /* Is a TrueType character index, let the rasterizer at it. */
        stream.putline("    {TrueDict begin /bander load cvlit exch TrueState render end}");

        stream.putline("    ifelse");

        /* 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");

        /* 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"); */
} /* end of ttfont_trailer() */