void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(GlyphBuffer* glyphBuffer) { hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(m_harfbuzzBuffer, 0); hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(m_harfbuzzBuffer, 0); HarfBuzzRun* currentRun = m_harfbuzzRuns.last().get(); unsigned numGlyphs = currentRun->numGlyphs(); float totalAdvance = 0; float nextOffsetX = harfbuzzPositionToFloat(glyphPositions[0].x_offset); float nextOffsetY = -harfbuzzPositionToFloat(glyphPositions[0].y_offset); // HarfBuzz returns the shaping result in visual order. We need not to flip them for RTL. for (size_t i = 0; i < numGlyphs; ++i) { bool runEnd = i + 1 == numGlyphs; uint16_t glyph = glyphInfos[i].codepoint; float offsetX = nextOffsetX; float offsetY = nextOffsetY; float advance = harfbuzzPositionToFloat(glyphPositions[i].x_advance); nextOffsetX = runEnd ? 0 : harfbuzzPositionToFloat(glyphPositions[i + 1].x_offset); nextOffsetY = runEnd ? 0 : -harfbuzzPositionToFloat(glyphPositions[i + 1].y_offset); unsigned currentCharacterIndex = m_startIndexOfCurrentRun + glyphInfos[i].cluster; bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1].cluster; float spacing = isClusterEnd ? m_letterSpacing : 0; if (isClusterEnd && isWordEnd(currentCharacterIndex)) spacing += determineWordBreakSpacing(); if (m_currentFontData->isZeroWidthSpaceGlyph(glyph)) { currentRun->setGlyphAndPositions(i, glyph, 0, 0, 0); if (glyphBuffer) glyphBuffer->add(glyph, m_currentFontData, createGlyphBufferAdvance(0, 0)); continue; } advance += spacing; currentRun->setGlyphAndPositions(i, glyph, totalAdvance + offsetX, offsetY, advance); if (glyphBuffer) { float glyphAdvanceX = advance + nextOffsetX - offsetX; float glyphAdvanceY = nextOffsetY - offsetY; glyphBuffer->add(glyph, m_currentFontData, createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY)); } totalAdvance += advance; } currentRun->setWidth(totalAdvance > 0.0 ? totalAdvance : 0.0); m_totalWidth += currentRun->width(); }
void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb_buffer_t* harfbuzzBuffer) { const SimpleFontData* currentFontData = currentRun->fontData(); hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(harfbuzzBuffer, 0); hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(harfbuzzBuffer, 0); unsigned numGlyphs = currentRun->numGlyphs(); float totalAdvance = 0; // HarfBuzz returns the shaping result in visual order. We need not to flip for RTL. for (size_t i = 0; i < numGlyphs; ++i) { bool runEnd = i + 1 == numGlyphs; uint16_t glyph = glyphInfos[i].codepoint; float offsetX = harfbuzzPositionToFloat(glyphPositions[i].x_offset); float offsetY = -harfbuzzPositionToFloat(glyphPositions[i].y_offset); float advance = harfbuzzPositionToFloat(glyphPositions[i].x_advance); unsigned currentCharacterIndex = currentRun->startIndex() + glyphInfos[i].cluster; bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1].cluster; float spacing = 0; if (isClusterEnd && !Font::treatAsZeroWidthSpace(m_normalizedBuffer[currentCharacterIndex])) spacing += m_letterSpacing; if (isClusterEnd && isWordEnd(currentCharacterIndex)) spacing += determineWordBreakSpacing(); if (currentFontData->isZeroWidthSpaceGlyph(glyph)) { currentRun->setGlyphAndPositions(i, glyph, 0, 0, 0); continue; } advance += spacing; if (m_run.rtl()) { // In RTL, spacing should be added to left side of glyphs. offsetX += spacing; if (!isClusterEnd) offsetX += m_letterSpacing; } currentRun->setGlyphAndPositions(i, glyph, advance, offsetX, offsetY); totalAdvance += advance; } currentRun->setWidth(totalAdvance > 0.0 ? totalAdvance : 0.0); m_totalWidth += currentRun->width(); }