HRESULT analyze_opentype_font(const void* font_data, UINT32* font_count, DWRITE_FONT_FILE_TYPE *file_type, DWRITE_FONT_FACE_TYPE *face_type, BOOL *supported) { /* TODO: Do font validation */ const char* tag = font_data; *supported = FALSE; *file_type = DWRITE_FONT_FILE_TYPE_UNKNOWN; if (face_type) *face_type = 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; if (face_type) *face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION; *supported = TRUE; } else if (GET_BE_DWORD(*(DWORD*)font_data) == 0x10000) { *font_count = 1; *file_type = DWRITE_FONT_FILE_TYPE_TRUETYPE; if (face_type) *face_type = DWRITE_FONT_FACE_TYPE_TRUETYPE; *supported = TRUE; } else if (DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3]) == MS_OTTO_TAG) { *file_type = DWRITE_FONT_FILE_TYPE_CFF; } return S_OK; }
static DWORD shape_select_script(const struct scriptshaping_cache *cache, DWORD kind, const DWORD *scripts, unsigned int *script_index) { static const DWORD fallback_scripts[] = { DWRITE_MAKE_OPENTYPE_TAG('D','F','L','T'), DWRITE_MAKE_OPENTYPE_TAG('d','f','l','t'), DWRITE_MAKE_OPENTYPE_TAG('l','a','t','n'), 0, }; DWORD script; /* Passed scripts in ascending priority. */ while (*scripts) { if ((script = opentype_layout_find_script(cache, kind, *scripts, script_index))) return script; scripts++; } /* 'DFLT' -> 'dflt' -> 'latn' */ scripts = fallback_scripts; while (*scripts) { if ((script = opentype_layout_find_script(cache, kind, *scripts, script_index))) return script; scripts++; } return 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; }
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; }
static inline const OT_LangSys *opentype_get_langsys(const OT_Script *script, UINT32 languagetag) { UINT16 j; for (j = 0; j < GET_BE_WORD(script->LangSysCount); j++) { const char *tag = script->LangSysRecord[j].LangSysTag; if (languagetag == DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3])) return (OT_LangSys*)((BYTE*)script + GET_BE_WORD(script->LangSysRecord[j].LangSys)); } return NULL; }
static inline const OT_Script *opentype_get_script(const OT_ScriptList *scriptlist, UINT32 scripttag) { UINT16 j; for (j = 0; j < GET_BE_WORD(scriptlist->ScriptCount); j++) { const char *tag = scriptlist->ScriptRecord[j].ScriptTag; if (scripttag == DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3])) return (OT_Script*)((BYTE*)scriptlist + GET_BE_WORD(scriptlist->ScriptRecord[j].Script)); } return NULL; }
static DWORD shape_select_language(const struct scriptshaping_cache *cache, DWORD kind, unsigned int script_index, DWORD language, unsigned int *language_index) { /* Specified language -> 'dflt'. */ if ((language = opentype_layout_find_language(cache, kind, language, script_index, language_index))) return language; if ((language = opentype_layout_find_language(cache, kind, DWRITE_MAKE_OPENTYPE_TAG('d','f','l','t'), script_index, language_index))) return language; return 0; }
static uiForEach addToTypography(const uiOpenTypeFeatures *otf, char a, char b, char c, char d, uint32_t value, void *data) { IDWriteTypography *dt = (IDWriteTypography *) data; DWRITE_FONT_FEATURE dff; HRESULT hr; ZeroMemory(&dff, sizeof (DWRITE_FONT_FEATURE)); // yes, the cast here is necessary (the compiler will complain otherwise)... dff.nameTag = (DWRITE_FONT_FEATURE_TAG) DWRITE_MAKE_OPENTYPE_TAG(a, b, c, d); dff.parameter = (UINT32) value; hr = dt->AddFontFeature(dff); if (hr != S_OK) logHRESULT(L"error adding OpenType feature to IDWriteTypography", hr); return uiForEachContinue; }
static void opentype_add_font_features(const GPOS_GSUB_Header *header, const OT_LangSys *langsys, UINT32 max_tagcount, UINT32 *count, DWRITE_FONT_FEATURE_TAG *tags) { const OT_FeatureList *features = (const OT_FeatureList*)((const BYTE*)header + GET_BE_WORD(header->FeatureList)); UINT16 j; for (j = 0; j < GET_BE_WORD(langsys->FeatureCount); j++) { const OT_FeatureRecord *feature = &features->FeatureRecord[langsys->FeatureIndex[j]]; const char *tag = feature->FeatureTag; if (*count < max_tagcount) tags[*count] = DWRITE_MAKE_OPENTYPE_TAG(tag[0], tag[1], tag[2], tag[3]); (*count)++; } }
void gfxDWriteFont::ComputeMetrics() { DWRITE_FONT_METRICS fontMetrics; mFontFace->GetMetrics(&fontMetrics); if (mStyle.sizeAdjust != 0.0) { gfxFloat aspect = (gfxFloat)fontMetrics.xHeight / fontMetrics.designUnitsPerEm; mAdjustedSize = mStyle.GetAdjustedSize(aspect); } else { mAdjustedSize = mStyle.size; } mMetrics.xHeight = ((gfxFloat)fontMetrics.xHeight / fontMetrics.designUnitsPerEm) * mAdjustedSize; mMetrics.maxAscent = ceil(((gfxFloat)fontMetrics.ascent / fontMetrics.designUnitsPerEm) * mAdjustedSize); mMetrics.maxDescent = ceil(((gfxFloat)fontMetrics.descent / fontMetrics.designUnitsPerEm) * mAdjustedSize); mMetrics.maxHeight = mMetrics.maxAscent + mMetrics.maxDescent; mMetrics.emHeight = mAdjustedSize; mMetrics.emAscent = mMetrics.emHeight * mMetrics.maxAscent / mMetrics.maxHeight; mMetrics.emDescent = mMetrics.emHeight - mMetrics.emAscent; mMetrics.maxAdvance = mAdjustedSize; // try to get the true maxAdvance value from 'hhea' PRUint8 *tableData; PRUint32 len; void *tableContext = NULL; BOOL exists; HRESULT hr = mFontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('h', 'h', 'e', 'a'), (const void**)&tableData, &len, &tableContext, &exists); if (SUCCEEDED(hr)) { if (exists && len >= sizeof(mozilla::HheaTable)) { const mozilla::HheaTable* hhea = reinterpret_cast<const mozilla::HheaTable*>(tableData); mMetrics.maxAdvance = ((gfxFloat)PRUint16(hhea->advanceWidthMax) / fontMetrics.designUnitsPerEm) * mAdjustedSize; } mFontFace->ReleaseFontTable(tableContext); } mMetrics.internalLeading = ceil(((gfxFloat)(fontMetrics.ascent + fontMetrics.descent - fontMetrics.designUnitsPerEm) / fontMetrics.designUnitsPerEm) * mAdjustedSize); mMetrics.externalLeading = ceil(((gfxFloat)fontMetrics.lineGap / fontMetrics.designUnitsPerEm) * mAdjustedSize); UINT16 glyph = (PRUint16)GetSpaceGlyph(); DWRITE_GLYPH_METRICS metrics; mFontFace->GetDesignGlyphMetrics(&glyph, 1, &metrics); mMetrics.spaceWidth = ((gfxFloat)metrics.advanceWidth / fontMetrics.designUnitsPerEm) * mAdjustedSize; // try to get aveCharWidth from the OS/2 table, fall back to measuring 'x' // if the table is not available mMetrics.aveCharWidth = 0; hr = mFontFace->TryGetFontTable(DWRITE_MAKE_OPENTYPE_TAG('O', 'S', '/', '2'), (const void**)&tableData, &len, &tableContext, &exists); if (SUCCEEDED(hr)) { if (exists && len >= 4) { // Not checking against sizeof(mozilla::OS2Table) here because older // versions of the table have different sizes; we only need the first // two 16-bit fields here. const mozilla::OS2Table* os2 = reinterpret_cast<const mozilla::OS2Table*>(tableData); mMetrics.aveCharWidth = ((gfxFloat)PRInt16(os2->xAvgCharWidth) / fontMetrics.designUnitsPerEm) * mAdjustedSize; } mFontFace->ReleaseFontTable(tableContext); } UINT32 ucs; if (mMetrics.aveCharWidth < 1) { ucs = L'x'; if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph)) && SUCCEEDED(mFontFace->GetDesignGlyphMetrics(&glyph, 1, &metrics))) { mMetrics.aveCharWidth = ((gfxFloat)metrics.advanceWidth / fontMetrics.designUnitsPerEm) * mAdjustedSize; } else { // Let's just assume the X is square. mMetrics.aveCharWidth = ((gfxFloat)fontMetrics.xHeight / fontMetrics.designUnitsPerEm) * mAdjustedSize; } } ucs = L'0'; if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph)) && SUCCEEDED(mFontFace->GetDesignGlyphMetrics(&glyph, 1, &metrics))) { mMetrics.zeroOrAveCharWidth = ((gfxFloat)metrics.advanceWidth / fontMetrics.designUnitsPerEm) * mAdjustedSize; } else { mMetrics.zeroOrAveCharWidth = mMetrics.aveCharWidth; } mMetrics.underlineOffset = ((gfxFloat)fontMetrics.underlinePosition / fontMetrics.designUnitsPerEm) * mAdjustedSize; mMetrics.underlineSize = ((gfxFloat)fontMetrics.underlineThickness / fontMetrics.designUnitsPerEm) * mAdjustedSize; mMetrics.strikeoutOffset = ((gfxFloat)fontMetrics.strikethroughPosition / fontMetrics.designUnitsPerEm) * mAdjustedSize; mMetrics.strikeoutSize = ((gfxFloat)fontMetrics.strikethroughThickness / fontMetrics.designUnitsPerEm) * mAdjustedSize; mMetrics.superscriptOffset = 0; mMetrics.subscriptOffset = 0; mFUnitsConvFactor = GetAdjustedSize() / fontMetrics.designUnitsPerEm; SanitizeMetrics(&mMetrics, GetFontEntry()->mIsBadUnderlineFont); #if 0 printf("Font: %p (%s) size: %f\n", this, NS_ConvertUTF16toUTF8(GetName()).get(), mStyle.size); printf(" emHeight: %f emAscent: %f emDescent: %f\n", mMetrics.emHeight, mMetrics.emAscent, mMetrics.emDescent); printf(" maxAscent: %f maxDescent: %f maxAdvance: %f\n", mMetrics.maxAscent, mMetrics.maxDescent, mMetrics.maxAdvance); printf(" internalLeading: %f externalLeading: %f\n", mMetrics.internalLeading, mMetrics.externalLeading); printf(" spaceWidth: %f aveCharWidth: %f zeroOrAve: %f xHeight: %f\n", mMetrics.spaceWidth, mMetrics.aveCharWidth, mMetrics.zeroOrAveCharWidth, mMetrics.xHeight); printf(" uOff: %f uSize: %f stOff: %f stSize: %f supOff: %f subOff: %f\n", mMetrics.underlineOffset, mMetrics.underlineSize, mMetrics.strikeoutOffset, mMetrics.strikeoutSize, mMetrics.superscriptOffset, mMetrics.subscriptOffset); #endif }
void add(char a, char b, char c, char d, LONG value) { this->tags.push_back((OPENTYPE_TAG) DWRITE_MAKE_OPENTYPE_TAG(a, b, c, d)); this->values.push_back(value); }