Ejemplo n.º 1
0
static void
xps_load_sfnt_cmap(xps_font_t *font)
{
    byte *cmapdata;
    int offset, length;
    int nsubtables;

    offset = xps_find_sfnt_table(font, "cmap", &length);
    if (offset < 0 || length < 4)
    {
        gs_warn("cannot find cmap table");
        return;
    }

    cmapdata = font->data + offset;

    nsubtables = u16(cmapdata + 2);
    if (nsubtables < 0 || length < 4 + nsubtables * 8)
    {
        gs_warn("cannot find cmap sub-tables");
        return;
    }

    font->cmaptable = offset;
    font->cmapsubcount = nsubtables;
    font->cmapsubtable = 0;
}
Ejemplo n.º 2
0
static int
xps_true_callback_glyph_name(gs_font *pfont, gs_glyph glyph, gs_const_string *pstr)
{
    /* This function is copied verbatim from plfont.c */

    int table_length;
    int table_offset;

    ulong format;
    uint numGlyphs;
    uint glyph_name_index;
    const byte *postp; /* post table pointer */

    /* guess if the font type is not truetype */
    if ( pfont->FontType != ft_TrueType )
    {
        glyph -= 29;
        if ( glyph >= 0 && glyph < 258 )
        {
            pstr->data = (byte*) pl_mac_names[glyph];
            pstr->size = strlen((char*)pstr->data);
            return 0;
        }
        else
        {
            return gs_throw1(-1, "glyph index %lu out of range", (ulong)glyph);
        }
    }

    table_offset = xps_find_sfnt_table((xps_font_t*)pfont->client_data, "post", &table_length);

    /* no post table */
    if (table_offset < 0)
        return gs_throw(-1, "no post table");

    /* this shoudn't happen but... */
    if ( table_length == 0 )
        return gs_throw(-1, "zero-size post table");

    ((gs_font_type42 *)pfont)->data.string_proc((gs_font_type42 *)pfont,
                                                table_offset, table_length, &postp);
    format = u32(postp);

    /* Format 1.0 (mac encoding) is a simple table see the TT spec.
     * We don't implement this because we don't see it in practice.
     * Format 2.5 is deprecated.
     * Format 3.0 means that there is no post data in the font file.
     * We see this a lot but can't do much about it.
     * The only format we support is 2.0.
     */
    if ( format != 0x20000 )
    {
        /* Invent a name if we don't know the table format. */
        char buf[32];
        sprintf(buf, "glyph%d", (int)glyph);
        pstr->data = (byte*)buf;
        pstr->size = strlen((char*)pstr->data);
        return 0;
    }

    /* skip over the post header */
    numGlyphs = u16(postp + 32);
    if ( glyph < 0 || glyph > numGlyphs - 1)
    {
        return gs_throw1(-1, "glyph index %lu out of range", (ulong)glyph);
    }

    /* glyph name index starts at post + 34 each entry is 2 bytes */
    glyph_name_index = u16(postp + 34 + (glyph * 2));

    /* this shouldn't happen */
    if ( glyph_name_index < 0 && glyph_name_index > 0x7fff )
        return gs_throw(-1, "post table format error");

    /* mac easy */
    if ( glyph_name_index < 258 )
    {
        // dprintf2("glyph name (mac) %d = %s\n", glyph, pl_mac_names[glyph_name_index]);
        pstr->data = (byte*) pl_mac_names[glyph_name_index];
        pstr->size = strlen((char*)pstr->data);
        return 0;
    }

    /* not mac */
    else
    {
        byte *mydata;

        /* and here's the tricky part */
        const byte *pascal_stringp = postp + 34 + (numGlyphs * 2);

        /* 0 - 257 lives in the mac table above */
        glyph_name_index -= 258;

        /* The string we want is the index'th pascal string,
         * so we "hop" to each length byte "index" times. */
        while (glyph_name_index > 0)
        {
            pascal_stringp += ((int)(*pascal_stringp)+1);
            glyph_name_index--;
        }

        /* length byte */
        pstr->size = (int)(*pascal_stringp);

        /* + 1 is for the length byte */
        pstr->data = pascal_stringp + 1;

        /* sanity check */
        if ( pstr->data + pstr->size > postp + table_length || pstr->data - 1 < postp)
            return gs_throw(-1, "data out of range");

        /* sigh - we have to allocate a copy of the data - by the
         * time a high level device makes use of it the font data
         * may be freed. This is a necessary leak. */
        mydata = gs_alloc_bytes(pfont->memory, pstr->size + 1, "glyph to name");
        if ( mydata == 0 )
            return -1;
        memcpy(mydata, pascal_stringp + 1, pstr->size);
        pstr->data = mydata;

        mydata[pstr->size] = 0;

        return 0;
    }
}
Ejemplo n.º 3
0
void
xps_measure_font_glyph(xps_context_t *ctx, xps_font_t *font, int gid, xps_glyph_metrics_t *mtx)
{

    int head, format, loca, glyf;
    int ofs, len;
    int idx, i, n;
    int hadv, vadv, vorg;
    int vtop, ymax, desc;
    int scale;

    /* some insane defaults */

    scale = 1000; /* units-per-em */
    hadv = 500;
    vadv = -1000;
    vorg = 1000;

    /*
     * Horizontal metrics are easy.
     */

    ofs = xps_find_sfnt_table(font, "hhea", &len);
    if (ofs < 0 || len < 2 * 18)
    {
        gs_warn("hhea table is too short");
        return;
    }

    vorg = s16(font->data + ofs + 4); /* ascender is default vorg */
    desc = s16(font->data + ofs + 6); /* descender */
    if (desc < 0)
        desc = -desc;
    n = u16(font->data + ofs + 17 * 2);

    ofs = xps_find_sfnt_table(font, "hmtx", &len);
    if (ofs < 0)
    {
        gs_warn("cannot find hmtx table");
        return;
    }

    idx = gid;
    if (idx > n - 1)
        idx = n - 1;

    hadv = u16(font->data + ofs + idx * 4);
    vadv = 0;

    /*
     * Vertical metrics are hairy (with missing tables).
     */

    head = xps_find_sfnt_table(font, "head", &len);
    if (head > 0)
    {
        scale = u16(font->data + head + 18); /* units per em */
    }

    ofs = xps_find_sfnt_table(font, "OS/2", &len);
    if (ofs > 0 && len > 70)
    {
        vorg = s16(font->data + ofs + 68); /* sTypoAscender */
        desc = s16(font->data + ofs + 70); /* sTypoDescender */
        if (desc < 0)
            desc = -desc;
    }

    ofs = xps_find_sfnt_table(font, "vhea", &len);
    if (ofs > 0 && len >= 2 * 18)
    {
        n = u16(font->data + ofs + 17 * 2);

        ofs = xps_find_sfnt_table(font, "vmtx", &len);
        if (ofs < 0)
        {
            gs_warn("cannot find vmtx table");
            return;
        }

        idx = gid;
        if (idx > n - 1)
            idx = n - 1;

        vadv = u16(font->data + ofs + idx * 4);
        vtop = u16(font->data + ofs + idx * 4 + 2);

        glyf = xps_find_sfnt_table(font, "glyf", &len);
        loca = xps_find_sfnt_table(font, "loca", &len);
        if (head > 0 && glyf > 0 && loca > 0)
        {
            format = u16(font->data + head + 50); /* indexToLocaFormat */

            if (format == 0)
                ofs = u16(font->data + loca + gid * 2) * 2;
            else
                ofs = u32(font->data + loca + gid * 4);

            ymax = u16(font->data + glyf + ofs + 8); /* yMax */

            vorg = ymax + vtop;
        }
    }

    ofs = xps_find_sfnt_table(font, "VORG", &len);
    if (ofs > 0)
    {
        vorg = u16(font->data + ofs + 6);
        n = u16(font->data + ofs + 6);
        for (i = 0; i < n; i++)
        {
            if (u16(font->data + ofs + 8 + 4 * i) == gid)
            {
                vorg = s16(font->data + ofs + 8 + 4 * i + 2);
                break;
            }
        }
    }

    if (vadv == 0)
        vadv = vorg + desc;

    mtx->hadv = hadv / (float) scale;
    mtx->vadv = vadv / (float) scale;
    mtx->vorg = vorg / (float) scale;
}
Ejemplo n.º 4
0
/*
 * Get the windows truetype font file name - position 4 in the name table.
 */
void
xps_load_sfnt_name(xps_font_t *font, char *namep)
{
    byte *namedata;
    int offset, length;
    int format, count, stringoffset;
    int found;
    int i, k;

    found = 0;
    strcpy(namep, "Unknown");

    offset = xps_find_sfnt_table(font, "name", &length);
    if (offset < 0 || length < 6)
    {
        gs_warn("cannot find name table");
        return;
    }

    namedata = font->data + offset;

    format = u16(namedata + 0);
    count = u16(namedata + 2);
    stringoffset = u16(namedata + 4);

    if (length < 6 + (count * 12))
    {
        gs_warn("name table too short");
        return;
    }

    for (i = 0; i < count; i++)
    {
        byte *record = namedata + 6 + i * 12;
        int pid = u16(record + 0);
        int eid = u16(record + 2);
        int langid = u16(record + 4);
        int nameid = u16(record + 6);
        length = u16(record + 8);
        offset = u16(record + 10);

        /* Full font name or postscript name */
        if (nameid == 4 || nameid == 6)
        {
            if (pid == 1 && eid == 0 && langid == 0) /* mac roman, english */
            {
                if (found < 3)
                {
                    memcpy(namep, namedata + stringoffset + offset, length);
                    namep[length] = 0;
                    found = 3;
                }
            }

            if (pid == 3 && eid == 1 && langid == 0x409) /* windows unicode ucs-2, US */
            {
                if (found < 2)
                {
                    unsigned char *s = namedata + stringoffset + offset;
                    int n = length / 2;
                    for (k = 0; k < n; k ++)
                    {
                        int c = u16(s + k * 2);
                        namep[k] = isprint(c) ? c : '?';
                    }
                    namep[k] = 0;
                    found = 2;
                }
            }

            if (pid == 3 && eid == 10 && langid == 0x409) /* windows unicode ucs-4, US */
            {
                if (found < 1)
                {
                    unsigned char *s = namedata + stringoffset + offset;
                    int n = length / 4;
                    for (k = 0; k < n; k ++)
                    {
                        int c = u32(s + k * 4);
                        namep[k] = isprint(c) ? c : '?';
                    }
                    namep[k] = 0;
                    found = 1;
                }
            }
        }
    }
}