/*
** Write a BYTE as a hexadecimal value as part of the sfnts array.
*/
void sfnts_pputBYTE(TTStreamWriter& stream, BYTE n)
{
    static const char hexdigits[]="0123456789ABCDEF";

    if (!in_string)
    {
        stream.put_char('<');
        string_len=0;
        line_len++;
        in_string=TRUE;
    }

    stream.put_char( hexdigits[ n / 16 ] );
    stream.put_char( hexdigits[ n % 16 ] );
    string_len++;
    line_len+=2;

    if (line_len > 70)
    {
        stream.put_char('\n');
        line_len=0;
    }

} /* end of sfnts_pputBYTE() */
/*
** This is called whenever it is
** necessary to end a string in the sfnts array.
**
** (The array must be broken into strings which are
** no longer than 64K characters.)
*/
void sfnts_end_string(TTStreamWriter& stream)
{
    if (in_string)
    {
        string_len=0;           /* fool sfnts_pputBYTE() */

#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++;
    }
    in_string=FALSE;
} /* end of sfnts_end_string() */
/*
** This routine is used to break the character
** procedure up into a number of smaller
** procedures.  This is necessary so as not to
** overflow the stack on certain level 1 interpreters.
**
** Prepare to push another item onto the stack,
** starting a new proceedure if necessary.
**
** Not all the stack depth calculations in this routine
** are perfectly accurate, but they do the job.
*/
void GlyphToType3::stack(TTStreamWriter& stream, int new_elem)
{
    if ( !pdf_mode && num_pts > 25 )                    /* Only do something of we will */
    {
        /* have a log of points. */
        if (stack_depth == 0)
        {
            stream.put_char('{');
            stack_depth=1;
        }

        stack_depth += new_elem;                /* Account for what we propose to add */

        if (stack_depth > 100)
        {
            stream.puts("}_e{");
            stack_depth = 3 + new_elem; /* A rough estimate */
        }
    }
} /* end of stack() */
/*----------------------------------------------------------------
** 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() */