| Index: third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp
|
| diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp
|
| index 692c0a21c302bd354a4d127d421f1b79a0e5d9db..538bef547b051ae81a0f814a82c80cf3a93502ed 100644
|
| --- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp
|
| +++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp
|
| @@ -32,9 +32,7 @@
|
| #include "platform/fonts/shaping/ShapeResult.h"
|
|
|
| #include "platform/fonts/Font.h"
|
| -#include "platform/fonts/GlyphBuffer.h"
|
| #include "platform/fonts/shaping/ShapeResultInlineHeaders.h"
|
| -#include "platform/text/TextBreakIterator.h"
|
|
|
| namespace blink {
|
|
|
| @@ -130,334 +128,6 @@ ShapeResult::~ShapeResult()
|
| {
|
| }
|
|
|
| -static inline void addGlyphToBuffer(GlyphBuffer* glyphBuffer, float advance,
|
| - hb_direction_t direction, const SimpleFontData* fontData,
|
| - const HarfBuzzRunGlyphData& glyphData)
|
| -{
|
| - FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction)
|
| - ? FloatPoint(advance, 0)
|
| - : FloatPoint(0, advance);
|
| - glyphBuffer->add(glyphData.glyph, fontData, startOffset + glyphData.offset);
|
| -}
|
| -
|
| -template<TextDirection direction>
|
| -float ShapeResult::fillGlyphBufferForRun(GlyphBuffer* glyphBuffer,
|
| - const RunInfo* run, float initialAdvance, unsigned from, unsigned to,
|
| - unsigned runOffset)
|
| -{
|
| - if (!run)
|
| - return 0;
|
| - float advanceSoFar = initialAdvance;
|
| - const unsigned numGlyphs = run->m_glyphData.size();
|
| - for (unsigned i = 0; i < numGlyphs; ++i) {
|
| - const HarfBuzzRunGlyphData& glyphData = run->m_glyphData[i];
|
| - uint16_t currentCharacterIndex = run->m_startIndex +
|
| - glyphData.characterIndex + runOffset;
|
| - if ((direction == RTL && currentCharacterIndex >= to)
|
| - || (direction == LTR && currentCharacterIndex < from)) {
|
| - advanceSoFar += glyphData.advance;
|
| - } else if ((direction == RTL && currentCharacterIndex >= from)
|
| - || (direction == LTR && currentCharacterIndex < to)) {
|
| - addGlyphToBuffer(glyphBuffer, advanceSoFar, run->m_direction,
|
| - run->m_fontData.get(), glyphData);
|
| - advanceSoFar += glyphData.advance;
|
| - }
|
| - }
|
| - return advanceSoFar - initialAdvance;
|
| -}
|
| -
|
| -static inline unsigned countGraphemesInCluster(const UChar* str,
|
| - unsigned strLength, uint16_t startIndex, uint16_t endIndex)
|
| -{
|
| - if (startIndex > endIndex) {
|
| - uint16_t tempIndex = startIndex;
|
| - startIndex = endIndex;
|
| - endIndex = tempIndex;
|
| - }
|
| - uint16_t length = endIndex - startIndex;
|
| - ASSERT(static_cast<unsigned>(startIndex + length) <= strLength);
|
| - TextBreakIterator* cursorPosIterator = cursorMovementIterator(&str[startIndex], length);
|
| -
|
| - int cursorPos = cursorPosIterator->current();
|
| - int numGraphemes = -1;
|
| - while (0 <= cursorPos) {
|
| - cursorPos = cursorPosIterator->next();
|
| - numGraphemes++;
|
| - }
|
| - return std::max(0, numGraphemes);
|
| -}
|
| -
|
| -static inline void addEmphasisMark(GlyphBuffer* buffer,
|
| - const GlyphData* emphasisData, FloatPoint glyphCenter,
|
| - float midGlyphOffset)
|
| -{
|
| - ASSERT(buffer);
|
| - ASSERT(emphasisData);
|
| -
|
| - const SimpleFontData* emphasisFontData = emphasisData->fontData;
|
| - ASSERT(emphasisFontData);
|
| -
|
| - bool isVertical = emphasisFontData->platformData().isVerticalAnyUpright()
|
| - && emphasisFontData->verticalData();
|
| -
|
| - if (!isVertical) {
|
| - buffer->add(emphasisData->glyph, emphasisFontData,
|
| - midGlyphOffset - glyphCenter.x());
|
| - } else {
|
| - buffer->add(emphasisData->glyph, emphasisFontData,
|
| - FloatPoint(-glyphCenter.x(), midGlyphOffset - glyphCenter.y()));
|
| - }
|
| -}
|
| -
|
| -float ShapeResult::fillGlyphBufferForTextEmphasisRun(GlyphBuffer* glyphBuffer,
|
| - const RunInfo* run, const TextRun& textRun, const GlyphData* emphasisData,
|
| - float initialAdvance, unsigned from, unsigned to, unsigned runOffset)
|
| -{
|
| - if (!run)
|
| - return 0;
|
| -
|
| - unsigned graphemesInCluster = 1;
|
| - float clusterAdvance = 0;
|
| -
|
| - FloatPoint glyphCenter = emphasisData->fontData->
|
| - boundsForGlyph(emphasisData->glyph).center();
|
| -
|
| - TextDirection direction = textRun.direction();
|
| -
|
| - // A "cluster" in this context means a cluster as it is used by HarfBuzz:
|
| - // The minimal group of characters and corresponding glyphs, that cannot be broken
|
| - // down further from a text shaping point of view.
|
| - // A cluster can contain multiple glyphs and grapheme clusters, with mutually
|
| - // overlapping boundaries. Below we count grapheme clusters per HarfBuzz clusters,
|
| - // then linearly split the sum of corresponding glyph advances by the number of
|
| - // grapheme clusters in order to find positions for emphasis mark drawing.
|
| - uint16_t clusterStart = static_cast<uint16_t>(direction == RTL
|
| - ? run->m_startIndex + run->m_numCharacters + runOffset
|
| - : run->glyphToCharacterIndex(0) + runOffset);
|
| -
|
| - float advanceSoFar = initialAdvance;
|
| - const unsigned numGlyphs = run->m_glyphData.size();
|
| - for (unsigned i = 0; i < numGlyphs; ++i) {
|
| - const HarfBuzzRunGlyphData& glyphData = run->m_glyphData[i];
|
| - uint16_t currentCharacterIndex = run->m_startIndex + glyphData.characterIndex + runOffset;
|
| - bool isRunEnd = (i + 1 == numGlyphs);
|
| - bool isClusterEnd = isRunEnd || (run->glyphToCharacterIndex(i + 1) + runOffset != currentCharacterIndex);
|
| -
|
| - if ((direction == RTL && currentCharacterIndex >= to) || (direction != RTL && currentCharacterIndex < from)) {
|
| - advanceSoFar += glyphData.advance;
|
| - direction == RTL ? --clusterStart : ++clusterStart;
|
| - continue;
|
| - }
|
| -
|
| - clusterAdvance += glyphData.advance;
|
| -
|
| - if (textRun.is8Bit()) {
|
| - float glyphAdvanceX = glyphData.advance;
|
| - if (Character::canReceiveTextEmphasis(textRun[currentCharacterIndex])) {
|
| - addEmphasisMark(glyphBuffer, emphasisData, glyphCenter, advanceSoFar + glyphAdvanceX / 2);
|
| - }
|
| - advanceSoFar += glyphAdvanceX;
|
| - } else if (isClusterEnd) {
|
| - uint16_t clusterEnd;
|
| - if (direction == RTL)
|
| - clusterEnd = currentCharacterIndex;
|
| - else
|
| - clusterEnd = static_cast<uint16_t>(isRunEnd ? run->m_startIndex + run->m_numCharacters + runOffset : run->glyphToCharacterIndex(i + 1) + runOffset);
|
| -
|
| - graphemesInCluster = countGraphemesInCluster(textRun.characters16(), textRun.charactersLength(), clusterStart, clusterEnd);
|
| - if (!graphemesInCluster || !clusterAdvance)
|
| - continue;
|
| -
|
| - float glyphAdvanceX = clusterAdvance / graphemesInCluster;
|
| - for (unsigned j = 0; j < graphemesInCluster; ++j) {
|
| - // Do not put emphasis marks on space, separator, and control characters.
|
| - if (Character::canReceiveTextEmphasis(textRun[currentCharacterIndex]))
|
| - addEmphasisMark(glyphBuffer, emphasisData, glyphCenter, advanceSoFar + glyphAdvanceX / 2);
|
| - advanceSoFar += glyphAdvanceX;
|
| - }
|
| - clusterStart = clusterEnd;
|
| - clusterAdvance = 0;
|
| - }
|
| - }
|
| - return advanceSoFar - initialAdvance;
|
| -}
|
| -
|
| -float ShapeResult::fillFastHorizontalGlyphBuffer(const ShapeResultBuffer& resultsBuffer,
|
| - GlyphBuffer* glyphBuffer, TextDirection dir)
|
| -{
|
| - ASSERT(!resultsBuffer.hasVerticalOffsets());
|
| -
|
| - const auto& results = resultsBuffer.results();
|
| - float advance = 0;
|
| -
|
| - for (unsigned i = 0; i < results.size(); ++i) {
|
| - const auto& wordResult =
|
| - isLeftToRightDirection(dir) ? results[i] : results[results.size() - 1 - i];
|
| - ASSERT(!wordResult->hasVerticalOffsets());
|
| -
|
| - for (const auto& run : wordResult->m_runs) {
|
| - ASSERT(run);
|
| - ASSERT(HB_DIRECTION_IS_HORIZONTAL(run->m_direction));
|
| -
|
| - for (const auto& glyphData : run->m_glyphData) {
|
| - ASSERT(!glyphData.offset.height());
|
| -
|
| - glyphBuffer->add(glyphData.glyph, run->m_fontData.get(),
|
| - advance + glyphData.offset.width());
|
| - advance += glyphData.advance;
|
| - }
|
| - }
|
| - }
|
| -
|
| - ASSERT(!glyphBuffer->hasVerticalOffsets());
|
| -
|
| - return advance;
|
| -}
|
| -
|
| -float ShapeResult::fillGlyphBuffer(const ShapeResultBuffer& resultsBuffer,
|
| - GlyphBuffer* glyphBuffer, const TextRun& textRun,
|
| - unsigned from, unsigned to)
|
| -{
|
| - // Fast path: full run with no vertical offsets
|
| - if (!from && to == static_cast<unsigned>(textRun.length()) && !resultsBuffer.hasVerticalOffsets())
|
| - return fillFastHorizontalGlyphBuffer(resultsBuffer, glyphBuffer, textRun.direction());
|
| -
|
| - const auto& results = resultsBuffer.results();
|
| - float advance = 0;
|
| -
|
| - if (textRun.rtl()) {
|
| - unsigned wordOffset = textRun.length();
|
| - for (unsigned j = 0; j < results.size(); j++) {
|
| - unsigned resolvedIndex = results.size() - 1 - j;
|
| - const RefPtr<ShapeResult>& wordResult = results[resolvedIndex];
|
| - for (unsigned i = 0; i < wordResult->m_runs.size(); i++) {
|
| - advance += wordResult->fillGlyphBufferForRun<RTL>(glyphBuffer,
|
| - wordResult->m_runs[i].get(), advance, from, to,
|
| - wordOffset - wordResult->numCharacters());
|
| - }
|
| - wordOffset -= wordResult->numCharacters();
|
| - }
|
| - } else {
|
| - unsigned wordOffset = 0;
|
| - for (unsigned j = 0; j < results.size(); j++) {
|
| - const RefPtr<ShapeResult>& wordResult = results[j];
|
| - for (unsigned i = 0; i < wordResult->m_runs.size(); i++) {
|
| - advance += wordResult->fillGlyphBufferForRun<LTR>(glyphBuffer,
|
| - wordResult->m_runs[i].get(), advance, from, to, wordOffset);
|
| - }
|
| - wordOffset += wordResult->numCharacters();
|
| - }
|
| - }
|
| -
|
| - return advance;
|
| -}
|
| -
|
| -float ShapeResult::fillGlyphBufferForTextEmphasis(const ShapeResultBuffer& resultsBuffer,
|
| - GlyphBuffer* glyphBuffer, const TextRun& textRun, const GlyphData* emphasisData,
|
| - unsigned from, unsigned to)
|
| -{
|
| - const auto& results = resultsBuffer.results();
|
| - float advance = 0;
|
| - unsigned wordOffset = textRun.rtl() ? textRun.length() : 0;
|
| -
|
| - for (unsigned j = 0; j < results.size(); j++) {
|
| - unsigned resolvedIndex = textRun.rtl() ? results.size() - 1 - j : j;
|
| - const RefPtr<ShapeResult>& wordResult = results[resolvedIndex];
|
| - for (unsigned i = 0; i < wordResult->m_runs.size(); i++) {
|
| - unsigned resolvedOffset = wordOffset -
|
| - (textRun.rtl() ? wordResult->numCharacters() : 0);
|
| - advance += wordResult->fillGlyphBufferForTextEmphasisRun(
|
| - glyphBuffer, wordResult->m_runs[i].get(), textRun, emphasisData,
|
| - advance, from, to, resolvedOffset);
|
| - }
|
| - wordOffset += wordResult->numCharacters() * (textRun.rtl() ? -1 : 1);
|
| - }
|
| -
|
| - return advance;
|
| -}
|
| -
|
| -FloatRect ShapeResult::selectionRect(const ShapeResultBuffer& resultsBuffer,
|
| - TextDirection direction, float totalWidth, const FloatPoint& point,
|
| - int height, unsigned absoluteFrom, unsigned absoluteTo)
|
| -{
|
| - const auto& results = resultsBuffer.results();
|
| - float currentX = 0;
|
| - float fromX = 0;
|
| - float toX = 0;
|
| - bool foundFromX = false;
|
| - bool foundToX = false;
|
| -
|
| - if (direction == RTL)
|
| - currentX = totalWidth;
|
| -
|
| - // The absoluteFrom and absoluteTo arguments represent the start/end offset
|
| - // for the entire run, from/to are continuously updated to be relative to
|
| - // the current word (ShapeResult instance).
|
| - int from = absoluteFrom;
|
| - int to = absoluteTo;
|
| -
|
| - unsigned totalNumCharacters = 0;
|
| - for (unsigned j = 0; j < results.size(); j++) {
|
| - const RefPtr<ShapeResult> result = results[j];
|
| - if (direction == RTL) {
|
| - // Convert logical offsets to visual offsets, because results are in
|
| - // logical order while runs are in visual order.
|
| - if (!foundFromX && from >= 0 && static_cast<unsigned>(from) < result->numCharacters())
|
| - from = result->numCharacters() - from - 1;
|
| - if (!foundToX && to >= 0 && static_cast<unsigned>(to) < result->numCharacters())
|
| - to = result->numCharacters() - to - 1;
|
| - currentX -= result->width();
|
| - }
|
| - for (unsigned i = 0; i < result->m_runs.size(); i++) {
|
| - if (!result->m_runs[i])
|
| - continue;
|
| - ASSERT((direction == RTL) == result->m_runs[i]->rtl());
|
| - int numCharacters = result->m_runs[i]->m_numCharacters;
|
| - if (!foundFromX && from >= 0 && from < numCharacters) {
|
| - fromX = result->m_runs[i]->xPositionForVisualOffset(from) + currentX;
|
| - foundFromX = true;
|
| - } else {
|
| - from -= numCharacters;
|
| - }
|
| -
|
| - if (!foundToX && to >= 0 && to < numCharacters) {
|
| - toX = result->m_runs[i]->xPositionForVisualOffset(to) + currentX;
|
| - foundToX = true;
|
| - } else {
|
| - to -= numCharacters;
|
| - }
|
| -
|
| - if (foundFromX && foundToX)
|
| - break;
|
| - currentX += result->m_runs[i]->m_width;
|
| - }
|
| - if (direction == RTL)
|
| - currentX -= result->width();
|
| - totalNumCharacters += result->numCharacters();
|
| - }
|
| -
|
| - // The position in question might be just after the text.
|
| - if (!foundFromX && absoluteFrom == totalNumCharacters) {
|
| - fromX = direction == RTL ? 0 : totalWidth;
|
| - foundFromX = true;
|
| - }
|
| - if (!foundToX && absoluteTo == totalNumCharacters) {
|
| - toX = direction == RTL ? 0 : totalWidth;
|
| - foundToX = true;
|
| - }
|
| - if (!foundFromX)
|
| - fromX = 0;
|
| - if (!foundToX)
|
| - toX = direction == RTL ? 0 : totalWidth;
|
| -
|
| - // None of our runs is part of the selection, possibly invalid arguments.
|
| - if (!foundToX && !foundFromX)
|
| - fromX = toX = 0;
|
| - if (fromX < toX)
|
| - return FloatRect(point.x() + fromX, point.y(), toX - fromX, height);
|
| - return FloatRect(point.x() + toX, point.y(), fromX - toX, height);
|
| -}
|
| -
|
| size_t ShapeResult::byteSize()
|
| {
|
| size_t selfByteSize = sizeof(this);
|
| @@ -467,41 +137,7 @@ size_t ShapeResult::byteSize()
|
| return selfByteSize;
|
| }
|
|
|
| -int ShapeResult::offsetForPosition(const ShapeResultBuffer& resultsBuffer,
|
| - const TextRun& run, float targetX)
|
| -{
|
| - const auto& results = resultsBuffer.results();
|
| - unsigned totalOffset;
|
| - if (run.rtl()) {
|
| - totalOffset = run.length();
|
| - for (unsigned i = results.size(); i; --i) {
|
| - const RefPtr<ShapeResult>& wordResult = results[i - 1];
|
| - if (!wordResult)
|
| - continue;
|
| - totalOffset -= wordResult->numCharacters();
|
| - if (targetX >= 0 && targetX <= wordResult->width()) {
|
| - int offsetForWord = wordResult->offsetForPosition(targetX);
|
| - return totalOffset + offsetForWord;
|
| - }
|
| - targetX -= wordResult->width();
|
| - }
|
| - } else {
|
| - totalOffset = 0;
|
| - for (const auto& wordResult : results) {
|
| - if (!wordResult)
|
| - continue;
|
| - int offsetForWord = wordResult->offsetForPosition(targetX);
|
| - ASSERT(offsetForWord >= 0);
|
| - totalOffset += offsetForWord;
|
| - if (targetX >= 0 && targetX <= wordResult->width())
|
| - return totalOffset;
|
| - targetX -= wordResult->width();
|
| - }
|
| - }
|
| - return totalOffset;
|
| -}
|
| -
|
| -int ShapeResult::offsetForPosition(float targetX)
|
| +int ShapeResult::offsetForPosition(float targetX) const
|
| {
|
| int charactersSoFar = 0;
|
| float currentX = 0;
|
|
|