Index: third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp |
diff --git a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp |
similarity index 53% |
copy from third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp |
copy to third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp |
index 692c0a21c302bd354a4d127d421f1b79a0e5d9db..f59d23008d2565c51e43a9a4617875ec13c0495f 100644 |
--- a/third_party/WebKit/Source/platform/fonts/shaping/ShapeResult.cpp |
+++ b/third_party/WebKit/Source/platform/fonts/shaping/ShapeResultBuffer.cpp |
@@ -1,148 +1,78 @@ |
-/* |
- * Copyright (c) 2012 Google Inc. All rights reserved. |
- * Copyright (C) 2013 BlackBerry Limited. All rights reserved. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions are |
- * met: |
- * |
- * * Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * * Redistributions in binary form must reproduce the above |
- * copyright notice, this list of conditions and the following disclaimer |
- * in the documentation and/or other materials provided with the |
- * distribution. |
- * * Neither the name of Google Inc. nor the names of its |
- * contributors may be used to endorse or promote products derived from |
- * this software without specific prior written permission. |
- * |
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-#include "platform/fonts/shaping/ShapeResult.h" |
- |
-#include "platform/fonts/Font.h" |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "platform/fonts/shaping/ShapeResultBuffer.h" |
+ |
+#include "platform/fonts/Character.h" |
#include "platform/fonts/GlyphBuffer.h" |
+#include "platform/fonts/SimpleFontData.h" |
#include "platform/fonts/shaping/ShapeResultInlineHeaders.h" |
+#include "platform/geometry/FloatPoint.h" |
#include "platform/text/TextBreakIterator.h" |
+#include "platform/text/TextDirection.h" |
namespace blink { |
-float ShapeResult::RunInfo::xPositionForVisualOffset(unsigned offset) const |
-{ |
- ASSERT(offset < m_numCharacters); |
- if (rtl()) |
- offset = m_numCharacters - offset - 1; |
- return xPositionForOffset(offset); |
-} |
+namespace { |
-float ShapeResult::RunInfo::xPositionForOffset(unsigned offset) const |
+inline void addGlyphToBuffer(GlyphBuffer* glyphBuffer, float advance, hb_direction_t direction, |
+ const SimpleFontData* fontData, const HarfBuzzRunGlyphData& glyphData) |
{ |
- ASSERT(offset <= m_numCharacters); |
- const unsigned numGlyphs = m_glyphData.size(); |
- unsigned glyphIndex = 0; |
- float position = 0; |
- if (rtl()) { |
- while (glyphIndex < numGlyphs && m_glyphData[glyphIndex].characterIndex > offset) { |
- position += m_glyphData[glyphIndex].advance; |
- ++glyphIndex; |
- } |
- // For RTL, we need to return the right side boundary of the character. |
- // Add advance of glyphs which are part of the character. |
- while (glyphIndex < numGlyphs - 1 && m_glyphData[glyphIndex].characterIndex == m_glyphData[glyphIndex + 1].characterIndex) { |
- position += m_glyphData[glyphIndex].advance; |
- ++glyphIndex; |
- } |
- position += m_glyphData[glyphIndex].advance; |
- } else { |
- while (glyphIndex < numGlyphs && m_glyphData[glyphIndex].characterIndex < offset) { |
- position += m_glyphData[glyphIndex].advance; |
- ++glyphIndex; |
- } |
- } |
- return position; |
+ FloatPoint startOffset = HB_DIRECTION_IS_HORIZONTAL(direction) |
+ ? FloatPoint(advance, 0) |
+ : FloatPoint(0, advance); |
+ glyphBuffer->add(glyphData.glyph, fontData, startOffset + glyphData.offset); |
} |
-int ShapeResult::RunInfo::characterIndexForXPosition(float targetX) const |
+inline void addEmphasisMark(GlyphBuffer* buffer, |
+ const GlyphData* emphasisData, FloatPoint glyphCenter, |
+ float midGlyphOffset) |
{ |
- ASSERT(targetX <= m_width); |
- const unsigned numGlyphs = m_glyphData.size(); |
- float currentX = 0; |
- float currentAdvance = m_glyphData[0].advance; |
- unsigned glyphIndex = 0; |
- |
- // Sum up advances that belong to the first character. |
- while (glyphIndex < numGlyphs - 1 && m_glyphData[glyphIndex].characterIndex == m_glyphData[glyphIndex + 1].characterIndex) |
- currentAdvance += m_glyphData[++glyphIndex].advance; |
- currentAdvance = currentAdvance / 2.0; |
- if (targetX <= currentAdvance) |
- return rtl() ? m_numCharacters : 0; |
- |
- currentX = currentAdvance; |
- ++glyphIndex; |
- while (glyphIndex < numGlyphs) { |
- unsigned prevCharacterIndex = m_glyphData[glyphIndex - 1].characterIndex; |
- float prevAdvance = currentAdvance; |
- currentAdvance = m_glyphData[glyphIndex].advance; |
- while (glyphIndex < numGlyphs - 1 && m_glyphData[glyphIndex].characterIndex == m_glyphData[glyphIndex + 1].characterIndex) |
- currentAdvance += m_glyphData[++glyphIndex].advance; |
- currentAdvance = currentAdvance / 2.0; |
- float nextX = currentX + prevAdvance + currentAdvance; |
- if (currentX <= targetX && targetX <= nextX) |
- return rtl() ? prevCharacterIndex : m_glyphData[glyphIndex].characterIndex; |
- currentX = nextX; |
- ++glyphIndex; |
- } |
+ ASSERT(buffer); |
+ ASSERT(emphasisData); |
- return rtl() ? 0 : m_numCharacters; |
-} |
+ const SimpleFontData* emphasisFontData = emphasisData->fontData; |
+ ASSERT(emphasisFontData); |
-void ShapeResult::RunInfo::setGlyphAndPositions(unsigned index, |
- uint16_t glyphId, float advance, float offsetX, float offsetY) |
-{ |
- HarfBuzzRunGlyphData& data = m_glyphData[index]; |
- data.glyph = glyphId; |
- data.advance = advance; |
- data.offset = FloatSize(offsetX, offsetY); |
-} |
+ bool isVertical = emphasisFontData->platformData().isVerticalAnyUpright() |
+ && emphasisFontData->verticalData(); |
-ShapeResult::ShapeResult(const Font* font, unsigned numCharacters, TextDirection direction) |
- : m_width(0) |
- , m_primaryFont(const_cast<SimpleFontData*>(font->primaryFont())) |
- , m_numCharacters(numCharacters) |
- , m_numGlyphs(0) |
- , m_direction(direction) |
- , m_hasVerticalOffsets(0) |
-{ |
+ if (!isVertical) { |
+ buffer->add(emphasisData->glyph, emphasisFontData, |
+ midGlyphOffset - glyphCenter.x()); |
+ } else { |
+ buffer->add(emphasisData->glyph, emphasisFontData, |
+ FloatPoint(-glyphCenter.x(), midGlyphOffset - glyphCenter.y())); |
+ } |
} |
-ShapeResult::~ShapeResult() |
+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); |
-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); |
+ int cursorPos = cursorPosIterator->current(); |
+ int numGraphemes = -1; |
+ while (0 <= cursorPos) { |
+ cursorPos = cursorPosIterator->next(); |
+ numGraphemes++; |
+ } |
+ return std::max(0, numGraphemes); |
} |
+} // anonymous namespace |
+ |
template<TextDirection direction> |
-float ShapeResult::fillGlyphBufferForRun(GlyphBuffer* glyphBuffer, |
- const RunInfo* run, float initialAdvance, unsigned from, unsigned to, |
+float ShapeResultBuffer::fillGlyphBufferForRun(GlyphBuffer* glyphBuffer, |
+ const ShapeResult::RunInfo* run, float initialAdvance, unsigned from, unsigned to, |
unsigned runOffset) |
{ |
if (!run) |
@@ -166,51 +96,8 @@ float ShapeResult::fillGlyphBufferForRun(GlyphBuffer* glyphBuffer, |
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 ShapeResultBuffer::fillGlyphBufferForTextEmphasisRun(GlyphBuffer* glyphBuffer, |
+ const ShapeResult::RunInfo* run, const TextRun& textRun, const GlyphData* emphasisData, |
float initialAdvance, unsigned from, unsigned to, unsigned runOffset) |
{ |
if (!run) |
@@ -282,17 +169,16 @@ float ShapeResult::fillGlyphBufferForTextEmphasisRun(GlyphBuffer* glyphBuffer, |
return advanceSoFar - initialAdvance; |
} |
-float ShapeResult::fillFastHorizontalGlyphBuffer(const ShapeResultBuffer& resultsBuffer, |
- GlyphBuffer* glyphBuffer, TextDirection dir) |
+float ShapeResultBuffer::fillFastHorizontalGlyphBuffer(GlyphBuffer* glyphBuffer, |
+ TextDirection dir) const |
{ |
- ASSERT(!resultsBuffer.hasVerticalOffsets()); |
+ ASSERT(!hasVerticalOffsets()); |
- const auto& results = resultsBuffer.results(); |
float advance = 0; |
- for (unsigned i = 0; i < results.size(); ++i) { |
+ for (unsigned i = 0; i < m_results.size(); ++i) { |
const auto& wordResult = |
- isLeftToRightDirection(dir) ? results[i] : results[results.size() - 1 - i]; |
+ isLeftToRightDirection(dir) ? m_results[i] : m_results[m_results.size() - 1 - i]; |
ASSERT(!wordResult->hasVerticalOffsets()); |
for (const auto& run : wordResult->m_runs) { |
@@ -314,24 +200,22 @@ float ShapeResult::fillFastHorizontalGlyphBuffer(const ShapeResultBuffer& result |
return advance; |
} |
-float ShapeResult::fillGlyphBuffer(const ShapeResultBuffer& resultsBuffer, |
- GlyphBuffer* glyphBuffer, const TextRun& textRun, |
- unsigned from, unsigned to) |
+float ShapeResultBuffer::fillGlyphBuffer(GlyphBuffer* glyphBuffer, const TextRun& textRun, |
+ unsigned from, unsigned to) const |
{ |
// Fast path: full run with no vertical offsets |
- if (!from && to == static_cast<unsigned>(textRun.length()) && !resultsBuffer.hasVerticalOffsets()) |
- return fillFastHorizontalGlyphBuffer(resultsBuffer, glyphBuffer, textRun.direction()); |
+ if (!from && to == static_cast<unsigned>(textRun.length()) && !hasVerticalOffsets()) |
+ return fillFastHorizontalGlyphBuffer(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 j = 0; j < m_results.size(); j++) { |
+ unsigned resolvedIndex = m_results.size() - 1 - j; |
+ const RefPtr<ShapeResult>& wordResult = m_results[resolvedIndex]; |
for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { |
- advance += wordResult->fillGlyphBufferForRun<RTL>(glyphBuffer, |
+ advance += fillGlyphBufferForRun<RTL>(glyphBuffer, |
wordResult->m_runs[i].get(), advance, from, to, |
wordOffset - wordResult->numCharacters()); |
} |
@@ -339,10 +223,10 @@ float ShapeResult::fillGlyphBuffer(const ShapeResultBuffer& resultsBuffer, |
} |
} else { |
unsigned wordOffset = 0; |
- for (unsigned j = 0; j < results.size(); j++) { |
- const RefPtr<ShapeResult>& wordResult = results[j]; |
+ for (unsigned j = 0; j < m_results.size(); j++) { |
+ const RefPtr<ShapeResult>& wordResult = m_results[j]; |
for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { |
- advance += wordResult->fillGlyphBufferForRun<LTR>(glyphBuffer, |
+ advance += fillGlyphBufferForRun<LTR>(glyphBuffer, |
wordResult->m_runs[i].get(), advance, from, to, wordOffset); |
} |
wordOffset += wordResult->numCharacters(); |
@@ -352,21 +236,19 @@ float ShapeResult::fillGlyphBuffer(const ShapeResultBuffer& resultsBuffer, |
return advance; |
} |
-float ShapeResult::fillGlyphBufferForTextEmphasis(const ShapeResultBuffer& resultsBuffer, |
- GlyphBuffer* glyphBuffer, const TextRun& textRun, const GlyphData* emphasisData, |
- unsigned from, unsigned to) |
+float ShapeResultBuffer::fillGlyphBufferForTextEmphasis(GlyphBuffer* glyphBuffer, |
+ const TextRun& textRun, const GlyphData* emphasisData, unsigned from, unsigned to) const |
{ |
- 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 j = 0; j < m_results.size(); j++) { |
+ unsigned resolvedIndex = textRun.rtl() ? m_results.size() - 1 - j : j; |
+ const RefPtr<ShapeResult>& wordResult = m_results[resolvedIndex]; |
for (unsigned i = 0; i < wordResult->m_runs.size(); i++) { |
unsigned resolvedOffset = wordOffset - |
(textRun.rtl() ? wordResult->numCharacters() : 0); |
- advance += wordResult->fillGlyphBufferForTextEmphasisRun( |
+ advance += fillGlyphBufferForTextEmphasisRun( |
glyphBuffer, wordResult->m_runs[i].get(), textRun, emphasisData, |
advance, from, to, resolvedOffset); |
} |
@@ -376,11 +258,9 @@ float ShapeResult::fillGlyphBufferForTextEmphasis(const ShapeResultBuffer& resul |
return advance; |
} |
-FloatRect ShapeResult::selectionRect(const ShapeResultBuffer& resultsBuffer, |
- TextDirection direction, float totalWidth, const FloatPoint& point, |
- int height, unsigned absoluteFrom, unsigned absoluteTo) |
+FloatRect ShapeResultBuffer::selectionRect(TextDirection direction, float totalWidth, |
+ const FloatPoint& point, int height, unsigned absoluteFrom, unsigned absoluteTo) const |
{ |
- const auto& results = resultsBuffer.results(); |
float currentX = 0; |
float fromX = 0; |
float toX = 0; |
@@ -397,8 +277,8 @@ FloatRect ShapeResult::selectionRect(const ShapeResultBuffer& resultsBuffer, |
int to = absoluteTo; |
unsigned totalNumCharacters = 0; |
- for (unsigned j = 0; j < results.size(); j++) { |
- const RefPtr<ShapeResult> result = results[j]; |
+ for (unsigned j = 0; j < m_results.size(); j++) { |
+ const RefPtr<ShapeResult> result = m_results[j]; |
if (direction == RTL) { |
// Convert logical offsets to visual offsets, because results are in |
// logical order while runs are in visual order. |
@@ -458,24 +338,13 @@ FloatRect ShapeResult::selectionRect(const ShapeResultBuffer& resultsBuffer, |
return FloatRect(point.x() + toX, point.y(), fromX - toX, height); |
} |
-size_t ShapeResult::byteSize() |
+int ShapeResultBuffer::offsetForPosition(const TextRun& run, float targetX) const |
{ |
- size_t selfByteSize = sizeof(this); |
- for (unsigned i = 0; i < m_runs.size(); ++i) { |
- selfByteSize += m_runs[i]->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]; |
+ for (unsigned i = m_results.size(); i; --i) { |
+ const RefPtr<ShapeResult>& wordResult = m_results[i - 1]; |
if (!wordResult) |
continue; |
totalOffset -= wordResult->numCharacters(); |
@@ -487,7 +356,7 @@ int ShapeResult::offsetForPosition(const ShapeResultBuffer& resultsBuffer, |
} |
} else { |
totalOffset = 0; |
- for (const auto& wordResult : results) { |
+ for (const auto& wordResult : m_results) { |
if (!wordResult) |
continue; |
int offsetForWord = wordResult->offsetForPosition(targetX); |
@@ -501,54 +370,4 @@ int ShapeResult::offsetForPosition(const ShapeResultBuffer& resultsBuffer, |
return totalOffset; |
} |
-int ShapeResult::offsetForPosition(float targetX) |
-{ |
- int charactersSoFar = 0; |
- float currentX = 0; |
- |
- if (m_direction == RTL) { |
- charactersSoFar = m_numCharacters; |
- for (unsigned i = 0; i < m_runs.size(); ++i) { |
- if (!m_runs[i]) |
- continue; |
- charactersSoFar -= m_runs[i]->m_numCharacters; |
- float nextX = currentX + m_runs[i]->m_width; |
- float offsetForRun = targetX - currentX; |
- if (offsetForRun >= 0 && offsetForRun <= m_runs[i]->m_width) { |
- // The x value in question is within this script run. |
- const unsigned index = m_runs[i]->characterIndexForXPosition(offsetForRun); |
- return charactersSoFar + index; |
- } |
- currentX = nextX; |
- } |
- } else { |
- for (unsigned i = 0; i < m_runs.size(); ++i) { |
- if (!m_runs[i]) |
- continue; |
- float nextX = currentX + m_runs[i]->m_width; |
- float offsetForRun = targetX - currentX; |
- if (offsetForRun >= 0 && offsetForRun <= m_runs[i]->m_width) { |
- const unsigned index = m_runs[i]->characterIndexForXPosition(offsetForRun); |
- return charactersSoFar + index; |
- } |
- charactersSoFar += m_runs[i]->m_numCharacters; |
- currentX = nextX; |
- } |
- } |
- |
- return charactersSoFar; |
-} |
- |
-void ShapeResult::fallbackFonts(HashSet<const SimpleFontData*>* fallback) const |
-{ |
- ASSERT(fallback); |
- ASSERT(m_primaryFont); |
- for (unsigned i = 0; i < m_runs.size(); ++i) { |
- if (m_runs[i] && m_runs[i]->m_fontData != m_primaryFont |
- && !m_runs[i]->m_fontData->isTextOrientationFallbackOf(m_primaryFont.get())) { |
- fallback->add(m_runs[i]->m_fontData.get()); |
- } |
- } |
-} |
- |
} // namespace blink |