Пример #1
0
inline bool HarfBuzzShaper::shapeRange(hb_buffer_t* harfBuzzBuffer,
    unsigned startIndex,
    unsigned numCharacters,
    const SimpleFontData* currentFont,
    PassRefPtr<UnicodeRangeSet> currentFontRangeSet,
    UScriptCode currentRunScript,
    hb_language_t language)
{
    const FontPlatformData* platformData = &(currentFont->platformData());
    HarfBuzzFace* face = platformData->harfBuzzFace();
    if (!face) {
        DLOG(ERROR) << "Could not create HarfBuzzFace from FontPlatformData.";
        return false;
    }

    hb_buffer_set_language(harfBuzzBuffer, language);
    hb_buffer_set_script(harfBuzzBuffer, ICUScriptToHBScript(currentRunScript));
    hb_buffer_set_direction(harfBuzzBuffer, TextDirectionToHBDirection(m_textRun.direction(),
        m_font->getFontDescription().orientation(), currentFont));

    hb_font_t* hbFont = face->getScaledFont(currentFontRangeSet);
    hb_shape(hbFont, harfBuzzBuffer, m_features.isEmpty() ? 0 : m_features.data(), m_features.size());

    return true;
}
Пример #2
0
bool FontPlatformData::hasSpaceInLigaturesOrKerning(
    TypesettingFeatures features) const {
  HarfBuzzFace* hbFace = harfBuzzFace();
  if (!hbFace)
    return false;

  hb_font_t* font = hbFace->getScaledFont();
  ASSERT(font);
  hb_face_t* face = hb_font_get_face(font);
  ASSERT(face);

  hb_codepoint_t space;
  // If the space glyph isn't present in the font then each space character
  // will be rendering using a fallback font, which grantees that it cannot
  // affect the shape of the preceding word.
  if (!hb_font_get_glyph(font, spaceCharacter, 0, &space))
    return false;

  if (!hb_ot_layout_has_substitution(face) &&
      !hb_ot_layout_has_positioning(face)) {
    return false;
  }

  bool foundSpaceInTable = false;
  hb_set_t* glyphs = hb_set_create();
  if (features & Kerning)
    foundSpaceInTable = tableHasSpace(face, glyphs, HB_OT_TAG_GPOS, space);
  if (!foundSpaceInTable && (features & Ligatures))
    foundSpaceInTable = tableHasSpace(face, glyphs, HB_OT_TAG_GSUB, space);

  hb_set_destroy(glyphs);

  return foundSpaceInTable;
}
Пример #3
0
bool HarfBuzzShaper::shapeHarfBuzzRuns(bool shouldSetDirection)
{
    HarfBuzzScopedPtr<hb_buffer_t> harfBuzzBuffer(hb_buffer_create(), hb_buffer_destroy);

    hb_buffer_set_unicode_funcs(harfBuzzBuffer.get(), hb_icu_get_unicode_funcs());

    for (unsigned i = 0; i < m_harfBuzzRuns.size(); ++i) {
        unsigned runIndex = m_run.rtl() ? m_harfBuzzRuns.size() - i - 1 : i;
        HarfBuzzRun* currentRun = m_harfBuzzRuns[runIndex].get();
        const SimpleFontData* currentFontData = currentRun->fontData();
        if (currentFontData->isSVGFont())
            return false;

        hb_buffer_set_script(harfBuzzBuffer.get(), currentRun->script());
        if (shouldSetDirection)
            hb_buffer_set_direction(harfBuzzBuffer.get(), currentRun->rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR);
        else
            // Leaving direction to HarfBuzz to guess is *really* bad, but will do for now.
            hb_buffer_guess_segment_properties(harfBuzzBuffer.get());

        // Add a space as pre-context to the buffer. This prevents showing dotted-circle
        // for combining marks at the beginning of runs.
        static const uint16_t preContext = ' ';
        hb_buffer_add_utf16(harfBuzzBuffer.get(), &preContext, 1, 1, 0);

        if (m_font->isSmallCaps() && u_islower(m_normalizedBuffer[currentRun->startIndex()])) {
            String upperText = String(m_normalizedBuffer.get() + currentRun->startIndex(), currentRun->numCharacters());
            upperText.makeUpper();
            currentFontData = m_font->glyphDataForCharacter(upperText[0], false, SmallCapsVariant).fontData;
            hb_buffer_add_utf16(harfBuzzBuffer.get(), upperText.characters(), currentRun->numCharacters(), 0, currentRun->numCharacters());
        } else
            hb_buffer_add_utf16(harfBuzzBuffer.get(), m_normalizedBuffer.get() + currentRun->startIndex(), currentRun->numCharacters(), 0, currentRun->numCharacters());

        FontPlatformData* platformData = const_cast<FontPlatformData*>(&currentFontData->platformData());
        HarfBuzzFace* face = platformData->harfBuzzFace();
        if (!face)
            return false;

        if (m_font->fontDescription().orientation() == Vertical)
            face->setScriptForVerticalGlyphSubstitution(harfBuzzBuffer.get());

        HarfBuzzScopedPtr<hb_font_t> harfBuzzFont(face->createFont(), hb_font_destroy);

        hb_shape(harfBuzzFont.get(), harfBuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size());

        currentRun->applyShapeResult(harfBuzzBuffer.get());
        setGlyphPositionsForHarfBuzzRun(currentRun, harfBuzzBuffer.get());

        hb_buffer_reset(harfBuzzBuffer.get());
    }

    return true;
}
Пример #4
0
bool HarfBuzzShaper::shapeHarfBuzzRun()
{
    FontPlatformData* platformData = const_cast<FontPlatformData*>(&m_currentFontData->platformData());
    HarfBuzzFace* face = platformData->harfbuzzFace();
    if (!face)
        return false;
    hb_font_t* harfbuzzFont = face->createFont();
    hb_shape(harfbuzzFont, m_harfbuzzBuffer, m_features.size() > 0 ? m_features.data() : 0, m_features.size());
    hb_font_destroy(harfbuzzFont);
    m_harfbuzzRuns.append(HarfBuzzRun::create(m_numCharactersOfCurrentRun, m_run.direction(), m_harfbuzzBuffer));
    return true;
}