示例#1
0
HRESULT opentype_get_font_table(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_TYPE type, UINT32 font_index, UINT32 tag,
    const void **table_data, void **table_context, UINT32 *table_size, BOOL *found)
{
    HRESULT hr;
    TTC_SFNT_V1 *font_header = NULL;
    void *sfnt_context;
    TT_TableRecord *table_record = NULL;
    void *table_record_context;
    int table_count, table_offset = 0;
    int i;

    if (found) *found = FALSE;
    if (table_size) *table_size = 0;

    if (type == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
        const TTC_Header_V1 *ttc_header;
        void * ttc_context;
        hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&ttc_header, 0, sizeof(*ttc_header), &ttc_context);
        if (SUCCEEDED(hr)) {
            table_offset = GET_BE_DWORD(ttc_header->OffsetTable[0]);
            if (font_index >= GET_BE_DWORD(ttc_header->numFonts))
                hr = E_INVALIDARG;
            else
                hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&font_header, table_offset, sizeof(*font_header), &sfnt_context);
            IDWriteFontFileStream_ReleaseFileFragment(stream, ttc_context);
        }
    }
    else
        hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&font_header, 0, sizeof(*font_header), &sfnt_context);

    if (FAILED(hr))
        return hr;

    table_count = GET_BE_WORD(font_header->numTables);
    table_offset += sizeof(*font_header);
    for (i = 0; i < table_count; i++)
    {
        hr = IDWriteFontFileStream_ReadFileFragment(stream, (const void**)&table_record, table_offset, sizeof(*table_record), &table_record_context);
        if (FAILED(hr))
            break;
        if (DWRITE_MAKE_OPENTYPE_TAG(table_record->tag[0], table_record->tag[1], table_record->tag[2], table_record->tag[3]) == tag)
            break;
        IDWriteFontFileStream_ReleaseFileFragment(stream, table_record_context);
        table_offset += sizeof(*table_record);
    }

    IDWriteFontFileStream_ReleaseFileFragment(stream, sfnt_context);
    if (SUCCEEDED(hr) && i < table_count)
    {
        int offset = GET_BE_DWORD(table_record->offset);
        int length = GET_BE_DWORD(table_record->length);
        IDWriteFontFileStream_ReleaseFileFragment(stream, table_record_context);

        if (found) *found = TRUE;
        if (table_size) *table_size = length;
        hr = IDWriteFontFileStream_ReadFileFragment(stream, table_data, offset, length, table_context);
    }

    return hr;
}
示例#2
0
void opentype_get_font_properties(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_TYPE type, UINT32 index,
    struct dwrite_font_props *props)
{
    void *os2_context, *head_context;
    const TT_OS2_V2 *tt_os2;
    const TT_HEAD *tt_head;

    opentype_get_font_table(stream, type, index, MS_OS2_TAG,  (const void**)&tt_os2, &os2_context, NULL, NULL);
    opentype_get_font_table(stream, type, index, MS_HEAD_TAG, (const void**)&tt_head, &head_context, NULL, NULL);

    /* default stretch, weight and style to normal */
    props->stretch = DWRITE_FONT_STRETCH_NORMAL;
    props->weight = DWRITE_FONT_WEIGHT_NORMAL;
    props->style = DWRITE_FONT_STYLE_NORMAL;
    memset(&props->panose, 0, sizeof(props->panose));

    /* DWRITE_FONT_STRETCH enumeration values directly match font data values */
    if (tt_os2) {
        if (GET_BE_WORD(tt_os2->usWidthClass) <= DWRITE_FONT_STRETCH_ULTRA_EXPANDED)
            props->stretch = GET_BE_WORD(tt_os2->usWidthClass);

        props->weight = GET_BE_WORD(tt_os2->usWeightClass);
        memcpy(&props->panose, &tt_os2->panose, sizeof(props->panose));

        TRACE("stretch=%d, weight=%d\n", props->stretch, props->weight);
    }

    if (tt_head) {
        USHORT macStyle = GET_BE_WORD(tt_head->macStyle);
        if (macStyle & 0x0002)
            props->style = DWRITE_FONT_STYLE_ITALIC;
    }

    if (tt_os2)
        IDWriteFontFileStream_ReleaseFileFragment(stream, os2_context);
    if (tt_head)
        IDWriteFontFileStream_ReleaseFileFragment(stream, head_context);
}
示例#3
0
HRESULT opentype_analyze_font(IDWriteFontFileStream *stream, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported)
{
    /* TODO: Do font validation */
    DWRITE_FONT_FACE_TYPE face;
    const void *font_data;
    const char* tag;
    void *context;
    HRESULT hr;

    hr = IDWriteFontFileStream_ReadFileFragment(stream, &font_data, 0, sizeof(TTC_Header_V1), &context);
    if (FAILED(hr))
        return hr;

    tag = font_data;
    *file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN;
    face = DWRITE_FONT_FACE_TYPE_UNKNOWN;
    *font_count = 0;

    if (DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3]) == MS_TTCF_TAG)
    {
        const TTC_Header_V1 *header = font_data;
        *font_count = GET_BE_DWORD(header->numFonts);
        *file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE_COLLECTION;
        face = DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION;
    }
    else if (GET_BE_DWORD(*(DWORD*)font_data) == 0x10000)
    {
        *font_count = 1;
        *file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE;
        face = DWRITE_FONT_FACE_TYPE_TRUETYPE;
    }
    else if (DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3]) == MS_OTTO_TAG)
    {
        *file_type = DWRITE_FONT_FILE_TYPE_CFF;
        face = DWRITE_FONT_FACE_TYPE_CFF;
    }

    if (face_type)
        *face_type = face;

    *supported = is_face_type_supported(face);

    IDWriteFontFileStream_ReleaseFileFragment(stream, context);
    return S_OK;
}
示例#4
0
void opentype_get_font_metrics(IDWriteFontFileStream *stream, DWRITE_FONT_FACE_TYPE face_type, UINT32 face_index,
    DWRITE_FONT_METRICS1 *metrics, DWRITE_CARET_METRICS *caret)
{
    void *os2_context, *head_context, *post_context, *hhea_context;
    const TT_OS2_V2 *tt_os2;
    const TT_HEAD *tt_head;
    const TT_POST *tt_post;
    const TT_HHEA *tt_hhea;

    memset(metrics, 0, sizeof(*metrics));

    opentype_get_font_table(stream, face_type, face_index, MS_OS2_TAG,  (const void**)&tt_os2, &os2_context, NULL, NULL);
    opentype_get_font_table(stream, face_type, face_index, MS_HEAD_TAG, (const void**)&tt_head, &head_context, NULL, NULL);
    opentype_get_font_table(stream, face_type, face_index, MS_POST_TAG, (const void**)&tt_post, &post_context, NULL, NULL);
    opentype_get_font_table(stream, face_type, face_index, MS_HHEA_TAG, (const void**)&tt_hhea, &hhea_context, NULL, NULL);

    if (tt_head) {
        metrics->designUnitsPerEm = GET_BE_WORD(tt_head->unitsPerEm);
        metrics->glyphBoxLeft = GET_BE_WORD(tt_head->xMin);
        metrics->glyphBoxTop = GET_BE_WORD(tt_head->yMax);
        metrics->glyphBoxRight = GET_BE_WORD(tt_head->xMax);
        metrics->glyphBoxBottom = GET_BE_WORD(tt_head->yMin);
    }

    if (caret) {
        if (tt_hhea) {
            caret->slopeRise = GET_BE_WORD(tt_hhea->caretSlopeRise);
            caret->slopeRun = GET_BE_WORD(tt_hhea->caretSlopeRun);
            caret->offset = GET_BE_WORD(tt_hhea->caretOffset);
        }
        else {
            caret->slopeRise = 0;
            caret->slopeRun = 0;
            caret->offset = 0;
        }
    }

    if (tt_os2) {
        USHORT version = GET_BE_WORD(tt_os2->version);

        metrics->ascent  = GET_BE_WORD(tt_os2->usWinAscent);
        metrics->descent = GET_BE_WORD(tt_os2->usWinDescent);

        /* line gap is estimated using two sets of ascender/descender values and 'hhea' line gap */
        if (tt_hhea) {
            SHORT descender = (SHORT)GET_BE_WORD(tt_hhea->descender);
            INT32 linegap;

            linegap = GET_BE_WORD(tt_hhea->ascender) + abs(descender) + GET_BE_WORD(tt_hhea->linegap) -
                metrics->ascent - metrics->descent;
            metrics->lineGap = linegap > 0 ? linegap : 0;
        }

        metrics->strikethroughPosition  = GET_BE_WORD(tt_os2->yStrikeoutPosition);
        metrics->strikethroughThickness = GET_BE_WORD(tt_os2->yStrikeoutSize);
        metrics->subscriptPositionX = GET_BE_WORD(tt_os2->ySubscriptXOffset);
        /* Y offset is stored as positive offset below baseline */
        metrics->subscriptPositionY = -GET_BE_WORD(tt_os2->ySubscriptYOffset);
        metrics->subscriptSizeX = GET_BE_WORD(tt_os2->ySubscriptXSize);
        metrics->subscriptSizeY = GET_BE_WORD(tt_os2->ySubscriptYSize);
        metrics->superscriptPositionX = GET_BE_WORD(tt_os2->ySuperscriptXOffset);
        metrics->superscriptPositionY = GET_BE_WORD(tt_os2->ySuperscriptYOffset);
        metrics->superscriptSizeX = GET_BE_WORD(tt_os2->ySuperscriptXSize);
        metrics->superscriptSizeY = GET_BE_WORD(tt_os2->ySuperscriptYSize);

        /* version 2 fields */
        if (version >= 2) {
            metrics->capHeight = GET_BE_WORD(tt_os2->sCapHeight);
            metrics->xHeight   = GET_BE_WORD(tt_os2->sxHeight);
        }

        /* version 4 fields */
        if (version >= 4) {
            if (GET_BE_WORD(tt_os2->fsSelection) & OS2_FSSELECTION_USE_TYPO_METRICS) {
                SHORT descent = GET_BE_WORD(tt_os2->sTypoDescender);
                metrics->ascent = GET_BE_WORD(tt_os2->sTypoAscender);
                metrics->descent = descent < 0 ? -descent : 0;
                metrics->lineGap = GET_BE_WORD(tt_os2->sTypoLineGap);
                metrics->hasTypographicMetrics = TRUE;
            }
        }
    }

    if (tt_post) {
        metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition);
        metrics->underlineThickness = GET_BE_WORD(tt_post->underlineThickness);
    }

    /* estimate missing metrics */
    if (metrics->xHeight == 0)
        metrics->xHeight = metrics->designUnitsPerEm / 2;
    if (metrics->capHeight == 0)
        metrics->capHeight = metrics->designUnitsPerEm * 7 / 10;

    if (tt_os2)
        IDWriteFontFileStream_ReleaseFileFragment(stream, os2_context);
    if (tt_head)
        IDWriteFontFileStream_ReleaseFileFragment(stream, head_context);
    if (tt_post)
        IDWriteFontFileStream_ReleaseFileFragment(stream, post_context);
    if (tt_hhea)
        IDWriteFontFileStream_ReleaseFileFragment(stream, hhea_context);
}