Index: Source/platform/fonts/GlyphBuffer.h |
diff --git a/Source/platform/fonts/GlyphBuffer.h b/Source/platform/fonts/GlyphBuffer.h |
index 9ccd92ab1c360e70a8bd603f02ea2b9397178215..606a5f5b88160958b16b7764b104754d706119f5 100644 |
--- a/Source/platform/fonts/GlyphBuffer.h |
+++ b/Source/platform/fonts/GlyphBuffer.h |
@@ -31,7 +31,7 @@ |
#define GlyphBuffer_h |
#include "platform/fonts/Glyph.h" |
-#include "platform/geometry/FloatSize.h" |
+#include "platform/geometry/FloatPoint.h" |
#include "platform/heap/Heap.h" |
#include "wtf/Vector.h" |
@@ -43,68 +43,120 @@ class GlyphBuffer { |
STACK_ALLOCATED(); |
public: |
bool isEmpty() const { return m_fontData.isEmpty(); } |
- bool hasOffsets() const { return !m_offsets.isEmpty(); } |
- unsigned size() const { return m_fontData.size(); } |
+ unsigned size() const |
+ { |
+ ASSERT(m_fontData.size() == m_glyphs.size()); |
+ ASSERT(m_fontData.size() == m_offsets.size() || 2 * m_fontData.size() == m_offsets.size()); |
+ return m_fontData.size(); |
+ } |
+ |
+ bool hasVerticalOffsets() const |
+ { |
+ // We exclusively store either horizontal/x-only ofssets -- in which case m_offsets.size == size, |
+ // or vertical/xy offsets -- in which case m_offsets.size == size * 2. |
+ return size() != m_offsets.size(); |
+ } |
- const Glyph* glyphs(unsigned from) const { return m_glyphs.data() + from; } |
- const float* advances(unsigned from) const { return m_advances.data() + from; } |
- const FloatSize* offsets(unsigned from) const { return m_offsets.data() + from; } |
+ const Glyph* glyphs(unsigned from) const |
+ { |
+ ASSERT(from < size()); |
+ return m_glyphs.data() + from; |
+ } |
+ |
+ const float* offsets(unsigned from) const |
+ { |
+ ASSERT(from < size()); |
+ return m_offsets.data() + (hasVerticalOffsets() ? from * 2 : from); |
+ } |
const SimpleFontData* fontDataAt(unsigned index) const |
{ |
+ ASSERT(index < size()); |
return m_fontData[index]; |
} |
Glyph glyphAt(unsigned index) const |
{ |
+ ASSERT(index < size()); |
return m_glyphs[index]; |
} |
- float advanceAt(unsigned index) const |
+ float xOffsetAt(unsigned index) const |
+ { |
+ ASSERT(index < size()); |
+ return hasVerticalOffsets() ? m_offsets[index * 2] : m_offsets[index]; |
+ |
+ } |
+ |
+ float yOffsetAt(unsigned index) const |
{ |
- return m_advances[index]; |
+ ASSERT(index < size()); |
+ ASSERT(hasVerticalOffsets()); |
+ return m_offsets[index * 2 + 1]; |
} |
- void add(Glyph glyph, const SimpleFontData* font, float width) |
+ void add(Glyph glyph, const SimpleFontData* font, float x) |
{ |
- // should not mix offset/advance-only glyphs |
- ASSERT(!hasOffsets()); |
+ // cannot mix x-only/xy offsets |
+ ASSERT(!hasVerticalOffsets()); |
m_fontData.append(font); |
m_glyphs.append(glyph); |
- m_advances.append(width); |
+ m_offsets.append(x); |
} |
- void add(Glyph glyph, const SimpleFontData* font, const FloatSize& offset, float advance) |
+ void add(Glyph glyph, const SimpleFontData* font, const FloatPoint& offset) |
{ |
- // should not mix offset/advance-only glyphs |
- ASSERT(size() == m_offsets.size()); |
+ // cannot mix x-only/xy offsets |
+ ASSERT(isEmpty() || hasVerticalOffsets()); |
m_fontData.append(font); |
m_glyphs.append(glyph); |
- m_offsets.append(offset); |
- m_advances.append(advance); |
+ m_offsets.append(offset.x()); |
+ m_offsets.append(offset.y()); |
} |
- void reverse() |
+ void reverseForSimpleRTL(float afterOffset, float totalWidth) |
{ |
+ ASSERT(!hasVerticalOffsets()); |
+ |
+ if (isEmpty()) |
+ return; |
+ |
m_fontData.reverse(); |
m_glyphs.reverse(); |
- m_advances.reverse(); |
- } |
- void expandLastAdvance(float width) |
- { |
- ASSERT(!isEmpty()); |
- float& lastAdvance = m_advances.last(); |
- lastAdvance += width; |
+ // | .. [X0 X1 .. Xn] .. | |
+ // ^ ^ ^ |
+ // 0 afterOffset totalWidth |
+ // |
+ // The input buffer is shaped using RTL advances, but since the right edge is unknown at |
+ // that time, offsets are computed as if the advances were LTR. This method performs the |
+ // required adjustments by reconstructing advances and positioning offsets in an RTL |
+ // progression. |
+ |
+ // FIXME: we should get rid of this (idea: store negative offsets while shaping, |
+ // and adjust the initial advance accordingly -> should yield correctly positioned |
+ // RTL glyphs without any post-shape munging). |
+ ASSERT_WITH_SECURITY_IMPLICATION(!m_offsets.isEmpty()); |
+ float x = totalWidth - m_offsets[0]; |
+ for (unsigned i = 0; i + 1 < m_offsets.size(); ++i) { |
+ float advance = m_offsets[i + 1] - m_offsets[i]; |
+ ASSERT(advance >= 0); |
+ x -= advance; |
+ m_offsets[i] = x; |
+ } |
+ float lastAdvance = afterOffset - m_offsets.last(); |
+ ASSERT(lastAdvance >= 0); |
+ m_offsets.last() = x - lastAdvance; |
+ |
+ m_offsets.reverse(); |
} |
protected: |
Vector<const SimpleFontData*, 2048> m_fontData; |
Vector<Glyph, 2048> m_glyphs; |
- Vector<float, 2048> m_advances; |
- Vector<FloatSize, 1024> m_offsets; |
+ Vector<float, 2048> m_offsets; |
}; |
} // namespace blink |