OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success) : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureMask(minimalFeatures), fFeatureMap(featureMap), fFeatureMapCount(featureMapCount), fFeatureOrder(FALSE), fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { static const le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG; static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG; const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag); // todo: switch to more flags and bitfield rather than list of feature tags? switch (typoFlags & ~0x80000000L) { case 0: break; // default case 1: fFeatureMask = kernFeatures; break; case 2: fFeatureMask = ligaFeatures; break; case 3: fFeatureMask = kernAndLigaFeatures; break; default: break; } if (typoFlags & 0x80000000L) { fSubstitutionFilter = new CharSubstitutionFilter(fontInstance); } setScriptAndLanguageTags(); fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag); // JK patch, 2008-05-30 - see Sinhala bug report and LKLUG font // if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) { if (gposTable != NULL && gposTable->coversScript(fScriptTag)) { fGPOSTable = gposTable; } }
void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphStorage &glyphStorage, LEErrorCode &success) { if (LE_FAILURE(success)) { return; } if (chars == NULL || offset < 0 || count < 0) { success = LE_ILLEGAL_ARGUMENT_ERROR; return; } GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable; CanonMarkFilter filter(gdefTable); adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success); if (fTypoFlags & 0x1) { /* kerning enabled */ static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG; KernTable kt(fFontInstance, getFontTable(kernTableTag)); kt.process(glyphStorage); } // default is no adjustments return; }
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable) : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags), fFeatureList(minimalFeatures), fFeatureOrder(NULL), fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { static const le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG; static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG; const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag); // todo: switch to more flags and bitfield rather than list of feature tags? switch (typoFlags) { case 0: break; // default case 1: fFeatureList = kernFeatures; break; case 2: fFeatureList = ligaFeatures; break; case 3: fFeatureList = kernAndLigaFeatures; break; default: break; } setScriptAndLanguageTags(); fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag); if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) { fGPOSTable = gposTable; } }
std::unordered_set<AxisTag> Font::getSupportedAxesLocked() const { const uint32_t fvarTag = MinikinFont::MakeTag('f', 'v', 'a', 'r'); HbBlob fvarTable(getFontTable(typeface.get(), fvarTag)); if (fvarTable.size() == 0) { return std::unordered_set<AxisTag>(); } std::unordered_set<AxisTag> supportedAxes; analyzeAxes(fvarTable.get(), fvarTable.size(), &supportedAxes); return supportedAxes; }
bool FontFamily::analyzeStyle(const std::shared_ptr<MinikinFont>& typeface, int* weight, bool* italic) { std::lock_guard<std::mutex> _l(gMinikinLock); const uint32_t os2Tag = MinikinFont::MakeTag('O', 'S', '/', '2'); HbBlob os2Table(getFontTable(typeface.get(), os2Tag)); if (os2Table.get() == nullptr) return false; return ::minikin::analyzeStyle(os2Table.get(), os2Table.size(), weight, italic); }
static void getFamiliesAndSignatures(const QByteArray &fontData, QFontDatabasePrivate::ApplicationFont *appFont) { const uchar *data = reinterpret_cast<const uchar *>(fontData.constData()); QList<quint32> offsets = getTrueTypeFontOffsets(data); if (offsets.isEmpty()) return; for (int i = 0; i < offsets.count(); ++i) { const uchar *font = data + offsets.at(i); const uchar *table; quint32 length; getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); if (!table) continue; QString name = getEnglishName(table, length); if (name.isEmpty()) continue; appFont->families << name; FONTSIGNATURE signature; getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); if (table && length >= 86) { // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42); signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46); signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50); signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54); signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78); signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82); } else { memset(&signature, 0, sizeof(signature)); } appFont->signatures << signature; } }
void FontFamily::computeCoverage() { std::lock_guard<std::mutex> _l(gMinikinLock); const FontStyle defaultStyle; const MinikinFont* typeface = getClosestMatch(defaultStyle).font; const uint32_t cmapTag = MinikinFont::MakeTag('c', 'm', 'a', 'p'); HbBlob cmapTable(getFontTable(typeface, cmapTag)); if (cmapTable.get() == nullptr) { ALOGE("Could not get cmap table size!\n"); return; } mCoverage = CmapCoverage::getCoverage(cmapTable.get(), cmapTable.size(), &mHasVSTable); for (size_t i = 0; i < mFonts.size(); ++i) { std::unordered_set<AxisTag> supportedAxes = mFonts[i].getSupportedAxesLocked(); mSupportedAxes.insert(supportedAxes.begin(), supportedAxes.end()); } }
void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/, LEGlyphStorage &glyphStorage, LEErrorCode &success) { if (LE_FAILURE(success)) { return; } if (chars == NULL || offset < 0 || count < 0) { success = LE_ILLEGAL_ARGUMENT_ERROR; return; } if (fTypoFlags & 0x1) { /* kerning enabled */ static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG; KernTable kt(fFontInstance, getFontTable(kernTableTag)); kt.process(glyphStorage); } // default is no adjustments return; }
virtual const void *getFontTable(LETag tableTag, size_t &length) const { length = -1; return getFontTable(tableTag); }
void XeTeXFontInst::initialize(const char* pathname, int index, int &status) { TT_Postscript *postTable; TT_OS2* os2Table; FT_Error error; hb_face_t *hbFace; if (!gFreeTypeLibrary) { error = FT_Init_FreeType(&gFreeTypeLibrary); if (error) { fprintf(stderr, "FreeType initialization failed! (%d)\n", error); exit(1); } } error = FT_New_Face(gFreeTypeLibrary, pathname, index, &m_ftFace); if (error) { status = 1; return; } if (!FT_IS_SCALABLE(m_ftFace)) { status = 1; return; } /* for non-sfnt-packaged fonts (presumably Type 1), see if there is an AFM file we can attach */ if (index == 0 && !FT_IS_SFNT(m_ftFace)) { char* afm = xstrdup (xbasename (pathname)); char* p = strrchr (afm, '.'); if (p != NULL && strlen(p) == 4 && tolower(*(p+1)) == 'p' && tolower(*(p+2)) == 'f') strcpy(p, ".afm"); char *fullafm = kpse_find_file (afm, kpse_afm_format, 0); free (afm); if (fullafm) { FT_Attach_File(m_ftFace, fullafm); free (fullafm); } } m_filename = xstrdup(pathname); m_index = index; m_unitsPerEM = m_ftFace->units_per_EM; m_ascent = unitsToPoints(m_ftFace->ascender); m_descent = unitsToPoints(m_ftFace->descender); postTable = (TT_Postscript *) getFontTable(ft_sfnt_post); if (postTable != NULL) { m_italicAngle = Fix2D(postTable->italicAngle); } os2Table = (TT_OS2*) getFontTable(ft_sfnt_os2); if (os2Table) { m_capHeight = unitsToPoints(os2Table->sCapHeight); m_xHeight = unitsToPoints(os2Table->sxHeight); } // Set up HarfBuzz font hbFace = hb_face_create_for_tables(_get_table, m_ftFace, NULL); hb_face_set_index(hbFace, index); hb_face_set_upem(hbFace, m_unitsPerEM); m_hbFont = hb_font_create(hbFace); hb_face_destroy(hbFace); if (hbFontFuncs == NULL) hbFontFuncs = _get_font_funcs(); hb_font_set_funcs(m_hbFont, hbFontFuncs, m_ftFace, NULL); hb_font_set_scale(m_hbFont, m_unitsPerEM, m_unitsPerEM); // We don’t want device tables adjustments hb_font_set_ppem(m_hbFont, 0, 0); return; }
// apply GPOS table, if any void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, LEGlyphStorage &glyphStorage, LEErrorCode &success) { if (LE_FAILURE(success)) { return; } if (chars == NULL || offset < 0 || count < 0) { success = LE_ILLEGAL_ARGUMENT_ERROR; return; } le_int32 glyphCount = glyphStorage.getGlyphCount(); if (glyphCount == 0) { return; } if (fGPOSTable != NULL) { GlyphPositionAdjustments *adjustments = new GlyphPositionAdjustments(glyphCount); le_int32 i; if (adjustments == NULL) { success = LE_MEMORY_ALLOCATION_ERROR; return; } #if 0 // Don't need to do this if we allocate // the adjustments array w/ new... for (i = 0; i < glyphCount; i += 1) { adjustments->setXPlacement(i, 0); adjustments->setYPlacement(i, 0); adjustments->setXAdvance(i, 0); adjustments->setYAdvance(i, 0); adjustments->setBaseOffset(i, -1); } #endif if (fGPOSTable != NULL) { if (fScriptTagV2 != nullScriptTag && fGPOSTable->coversScriptAndLanguage(fScriptTagV2,fLangSysTag)) { fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTagV2, fLangSysTag, fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder); } else { fGPOSTable->process(glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder); } } else if ( fTypoFlags & 0x1 ) { static const le_uint32 kernTableTag = LE_KERN_TABLE_TAG; KernTable kt(fFontInstance, getFontTable(kernTableTag)); kt.process(glyphStorage); } float xAdjust = 0, yAdjust = 0; for (i = 0; i < glyphCount; i += 1) { float xAdvance = adjustments->getXAdvance(i); float yAdvance = adjustments->getYAdvance(i); float xPlacement = 0; float yPlacement = 0; #if 0 // This is where separate kerning adjustments // should get applied. xAdjust += xKerning; yAdjust += yKerning; #endif for (le_int32 base = i; base >= 0; base = adjustments->getBaseOffset(base)) { xPlacement += adjustments->getXPlacement(base); yPlacement += adjustments->getYPlacement(base); } xPlacement = fFontInstance->xUnitsToPoints(xPlacement); yPlacement = fFontInstance->yUnitsToPoints(yPlacement); glyphStorage.adjustPosition(i, xAdjust + xPlacement, -(yAdjust + yPlacement), success); xAdjust += fFontInstance->xUnitsToPoints(xAdvance); yAdjust += fFontInstance->yUnitsToPoints(yAdvance); } glyphStorage.adjustPosition(glyphCount, xAdjust, -yAdjust, success); delete adjustments; } else { // if there was no GPOS table, maybe there's non-OpenType kerning we can use // Google Patch: disable this. Causes problems with Tamil. // Umesh says layout is poor both with and without the change, but // worse with the change. See ocean/imageprocessing/layout_test_unittest.cc // Public ICU ticket for this problem is #7742 // LayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success); } LEGlyphID zwnj = fFontInstance->mapCharToGlyph(0x200C); if (zwnj != 0x0000) { for (le_int32 g = 0; g < glyphCount; g += 1) { LEGlyphID glyph = glyphStorage[g]; if (glyph == zwnj) { glyphStorage[g] = LE_SET_GLYPH(glyph, 0xFFFF); } } } #if 0 // Don't know why this is here... LE_DELETE_ARRAY(fFeatureTags); fFeatureTags = NULL; #endif }
OpenTypeLayoutEngine::OpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success) : LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fFeatureMask(minimalFeatures), fFeatureMap(featureMap), fFeatureMapCount(featureMapCount), fFeatureOrder(FALSE), fGSUBTable(gsubTable), fGDEFTable(NULL), fGPOSTable(NULL), fSubstitutionFilter(NULL) { static const le_uint32 gdefTableTag = LE_GDEF_TABLE_TAG; static const le_uint32 gposTableTag = LE_GPOS_TABLE_TAG; const GlyphPositioningTableHeader *gposTable = (const GlyphPositioningTableHeader *) getFontTable(gposTableTag); switch (typoFlags & (LE_SS01_FEATURE_FLAG | LE_SS02_FEATURE_FLAG | LE_SS03_FEATURE_FLAG | LE_SS04_FEATURE_FLAG | LE_SS05_FEATURE_FLAG | LE_SS06_FEATURE_FLAG | LE_SS07_FEATURE_FLAG)) { case LE_SS01_FEATURE_FLAG: fFeatureMask |= ss01FeatureMask; break; case LE_SS02_FEATURE_FLAG: fFeatureMask |= ss02FeatureMask; break; case LE_SS03_FEATURE_FLAG: fFeatureMask |= ss03FeatureMask; break; case LE_SS04_FEATURE_FLAG: fFeatureMask |= ss04FeatureMask; break; case LE_SS05_FEATURE_FLAG: fFeatureMask |= ss05FeatureMask; break; case LE_SS06_FEATURE_FLAG: fFeatureMask |= ss06FeatureMask; break; case LE_SS07_FEATURE_FLAG: fFeatureMask |= ss07FeatureMask; break; } if (typoFlags & LE_Kerning_FEATURE_FLAG) { fFeatureMask |= (kernFeatureMask | paltFeatureMask); // Convenience. } if (typoFlags & LE_Ligatures_FEATURE_FLAG) { fFeatureMask |= (ligaFeatureMask | cligFeatureMask); // Convenience TODO: should add: .. dligFeatureMask | rligFeatureMask ? } if (typoFlags & LE_CLIG_FEATURE_FLAG) fFeatureMask |= cligFeatureMask; if (typoFlags & LE_DLIG_FEATURE_FLAG) fFeatureMask |= dligFeatureMask; if (typoFlags & LE_HLIG_FEATURE_FLAG) fFeatureMask |= hligFeatureMask; if (typoFlags & LE_LIGA_FEATURE_FLAG) fFeatureMask |= ligaFeatureMask; if (typoFlags & LE_RLIG_FEATURE_FLAG) fFeatureMask |= rligFeatureMask; if (typoFlags & LE_SMCP_FEATURE_FLAG) fFeatureMask |= smcpFeatureMask; if (typoFlags & LE_FRAC_FEATURE_FLAG) fFeatureMask |= fracFeatureMask; if (typoFlags & LE_AFRC_FEATURE_FLAG) fFeatureMask |= afrcFeatureMask; if (typoFlags & LE_ZERO_FEATURE_FLAG) fFeatureMask |= zeroFeatureMask; if (typoFlags & LE_SWSH_FEATURE_FLAG) fFeatureMask |= swshFeatureMask; if (typoFlags & LE_CSWH_FEATURE_FLAG) fFeatureMask |= cswhFeatureMask; if (typoFlags & LE_SALT_FEATURE_FLAG) fFeatureMask |= saltFeatureMask; if (typoFlags & LE_RUBY_FEATURE_FLAG) fFeatureMask |= rubyFeatureMask; if (typoFlags & LE_NALT_FEATURE_FLAG) { // Mutually exclusive with ALL other features. http://www.microsoft.com/typography/otspec/features_ko.htm fFeatureMask = naltFeatureMask; } if (typoFlags & LE_CHAR_FILTER_FEATURE_FLAG) { // This isn't a font feature, but requests a Char Substitution Filter fSubstitutionFilter = new CharSubstitutionFilter(fontInstance); } setScriptAndLanguageTags(); fGDEFTable = (const GlyphDefinitionTableHeader *) getFontTable(gdefTableTag); // JK patch, 2008-05-30 - see Sinhala bug report and LKLUG font // if (gposTable != NULL && gposTable->coversScriptAndLanguage(fScriptTag, fLangSysTag)) { if (gposTable != NULL && gposTable->coversScript(fScriptTag)) { fGPOSTable = gposTable; } }
const void *FontInstanceAdapter::getFontTable(LETag tableTag) const { size_t ignored = 0; return getFontTable(tableTag, ignored); }