Beispiel #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() */
Beispiel #2
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)
{
    if (target_type == PS_TYPE_3 || target_type == PS_TYPE_42_3_HYBRID)
    {
        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() */
Beispiel #3
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() */
/*
** Emit a PostScript "curveto" command, assuming the current point
** is (x0, y0), the control point of a quadratic spline is (x1, y1),
** and the endpoint is (x2, y2). Note that this requires a conversion,
** since PostScript splines are cubic.
*/
void GlyphToType3::PSCurveto(TTStreamWriter& stream,
                             FWord x0, FWord y0,
                             FWord x1, FWord y1,
                             FWord x2, FWord y2)
{
    double sx[3], sy[3], cx[3], cy[3];

    sx[0] = x0;
    sy[0] = y0;
    sx[1] = x1;
    sy[1] = y1;
    sx[2] = x2;
    sy[2] = y2;
    cx[0] = (2*sx[1]+sx[0])/3;
    cy[0] = (2*sy[1]+sy[0])/3;
    cx[1] = (sx[2]+2*sx[1])/3;
    cy[1] = (sy[2]+2*sy[1])/3;
    cx[2] = sx[2];
    cy[2] = sy[2];
    stream.printf("%d %d %d %d %d %d %s\n",
                  (int)cx[0], (int)cy[0], (int)cx[1], (int)cy[1],
                  (int)cx[2], (int)cy[2], pdf_mode ? "c" : "_c");
}
GlyphToType3::GlyphToType3(TTStreamWriter& stream, struct TTFONT *font, int charindex, bool embedded /* = false */)
{
    BYTE *glyph;

    tt_flags = NULL;
    xcoor = NULL;
    ycoor = NULL;
    epts_ctr = NULL;
    area_ctr = NULL;
    check_ctr = NULL;
    ctrset = NULL;
    stack_depth = 0;
    pdf_mode = font->target_type < 0;

    /* Get a pointer to the data. */
    glyph = find_glyph_data( font, charindex );

    /* If the character is blank, it has no bounding box, */
    /* otherwise read the bounding box. */
    if ( glyph == (BYTE*)NULL )
    {
        llx=lly=urx=ury=0;      /* A blank char has an all zero BoundingBox */
        num_ctr=0;              /* Set this for later if()s */
    }
    else
    {
        /* Read the number of contours. */
        num_ctr = getSHORT(glyph);

        /* Read PostScript bounding box. */
        llx = getFWord(glyph + 2);
        lly = getFWord(glyph + 4);
        urx = getFWord(glyph + 6);
        ury = getFWord(glyph + 8);

        /* Advance the pointer. */
        glyph += 10;
    }

    /* If it is a simple character, load its data. */
    if (num_ctr > 0)
    {
        load_char(font, glyph);
    }
    else
    {
        num_pts=0;
    }

    /* Consult the horizontal metrics table to determine */
    /* the character width. */
    if ( charindex < font->numberOfHMetrics )
    {
        advance_width = getuFWord( font->hmtx_table + (charindex * 4) );
    }
    else
    {
        advance_width = getuFWord( font->hmtx_table + ((font->numberOfHMetrics-1) * 4) );
    }

    /* Execute setcachedevice in order to inform the font machinery */
    /* of the character bounding box and advance width. */
    stack(stream, 7);
    if (pdf_mode)
    {
        if (!embedded) {
            stream.printf("%d 0 %d %d %d %d d1\n",
                          topost(advance_width),
                          topost(llx), topost(lly), topost(urx), topost(ury) );
        }
    }
    else if (font->target_type == PS_TYPE_42_3_HYBRID)
    {
        stream.printf("pop gsave .001 .001 scale %d 0 %d %d %d %d setcachedevice\n",
                      topost(advance_width),
                      topost(llx), topost(lly), topost(urx), topost(ury) );
    }
    else
    {
        stream.printf("%d 0 %d %d %d %d _sc\n",
                      topost(advance_width),
                      topost(llx), topost(lly), topost(urx), topost(ury) );
    }

    /* If it is a simple glyph, convert it, */
    /* otherwise, close the stack business. */
    if ( num_ctr > 0 )          /* simple */
    {
        PSConvert(stream);
    }
    else if ( num_ctr < 0 )     /* composite */
    {
        do_composite(stream, font, glyph);
    }

    if (font->target_type == PS_TYPE_42_3_HYBRID)
    {
        stream.printf("\ngrestore\n");
    }

    stack_end(stream);
}
/*
** Emmit PostScript code for a composite character.
*/
void GlyphToType3::do_composite(TTStreamWriter& stream, struct TTFONT *font, BYTE *glyph)
{
    USHORT flags;
    USHORT glyphIndex;
    int arg1;
    int arg2;
    USHORT xscale;
    USHORT yscale;
    USHORT scale01;
    USHORT scale10;

    /* Once around this loop for each component. */
    do
    {
        flags = getUSHORT(glyph);       /* read the flags word */
        glyph += 2;

        glyphIndex = getUSHORT(glyph);  /* read the glyphindex word */
        glyph += 2;

        if (flags & ARG_1_AND_2_ARE_WORDS)
        {
            /* The tt spec. seems to say these are signed. */
            arg1 = getSHORT(glyph);
            glyph += 2;
            arg2 = getSHORT(glyph);
            glyph += 2;
        }
        else                    /* The tt spec. does not clearly indicate */
        {
            /* whether these values are signed or not. */
            arg1 = *(signed char *)(glyph++);
            arg2 = *(signed char *)(glyph++);
        }

        if (flags & WE_HAVE_A_SCALE)
        {
            xscale = yscale = getUSHORT(glyph);
            glyph += 2;
            scale01 = scale10 = 0;
        }
        else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
        {
            xscale = getUSHORT(glyph);
            glyph += 2;
            yscale = getUSHORT(glyph);
            glyph += 2;
            scale01 = scale10 = 0;
        }
        else if (flags & WE_HAVE_A_TWO_BY_TWO)
        {
            xscale = getUSHORT(glyph);
            glyph += 2;
            scale01 = getUSHORT(glyph);
            glyph += 2;
            scale10 = getUSHORT(glyph);
            glyph += 2;
            yscale = getUSHORT(glyph);
            glyph += 2;
        }
        else
        {
            xscale = yscale = scale01 = scale10 = 0;
        }

        /* Debugging */
#ifdef DEBUG_TRUETYPE
        stream.printf("%% flags=%d, arg1=%d, arg2=%d, xscale=%d, yscale=%d, scale01=%d, scale10=%d\n",
                      (int)flags,arg1,arg2,(int)xscale,(int)yscale,(int)scale01,(int)scale10);
#endif

        if (pdf_mode)
        {
            if ( flags & ARGS_ARE_XY_VALUES )
            {
                /* We should have been able to use 'Do' to reference the
                   subglyph here.  However, that doesn't seem to work with
                   xpdf or gs (only acrobat), so instead, this just includes
                   the subglyph here inline. */
                stream.printf("q 1 0 0 1 %d %d cm\n", topost(arg1), topost(arg2));
            }
            else
            {
                stream.printf("%% unimplemented shift, arg1=%d, arg2=%d\n",arg1,arg2);
            }
            GlyphToType3(stream, font, glyphIndex, true);
            if ( flags & ARGS_ARE_XY_VALUES )
            {
                stream.printf("\nQ\n");
            }
        }
        else
        {
            /* If we have an (X,Y) shif and it is non-zero, */
            /* translate the coordinate system. */
            if ( flags & ARGS_ARE_XY_VALUES )
            {
                if ( arg1 != 0 || arg2 != 0 )
                    stream.printf("gsave %d %d translate\n", topost(arg1), topost(arg2) );
            }
            else
            {
                stream.printf("%% unimplemented shift, arg1=%d, arg2=%d\n",arg1,arg2);
            }

            /* Invoke the CharStrings procedure to print the component. */
            stream.printf("false CharStrings /%s get exec\n",
                          ttfont_CharStrings_getname(font,glyphIndex));

            /* If we translated the coordinate system, */
            /* put it back the way it was. */
            if ( flags & ARGS_ARE_XY_VALUES && (arg1 != 0 || arg2 != 0) )
            {
                stream.puts("grestore ");
            }
        }

    }
    while (flags & MORE_COMPONENTS);

} /* end of do_composite() */
void GlyphToType3::PSLineto(TTStreamWriter& stream, int x, int y)
{
    stream.printf(pdf_mode ? "%d %d l\n" : "%d %d _l\n",
                  x, y);
}
Beispiel #8
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() */