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;
    }
}
Пример #4
0
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;
}
Пример #5
0
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);
}
Пример #6
0
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;
    }
}
Пример #7
0
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());
  }
}
Пример #8
0
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;
}
Пример #9
0
 virtual const void *getFontTable(LETag tableTag, size_t &length) const
 {
     length = -1;
     return getFontTable(tableTag);
 }
Пример #10
0
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);
}