| Index: Source/platform/fonts/GlyphBuffer.h
|
| diff --git a/Source/platform/fonts/GlyphBuffer.h b/Source/platform/fonts/GlyphBuffer.h
|
| index 9ccd92ab1c360e70a8bd603f02ea2b9397178215..50cccb86a3a8dc9025a34e55b335eee5744e1ad5 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,127 @@ 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;
|
| + }
|
| +
|
| + // Depending on the GlyphBuffer-wide positioning mode, this either points to an array of
|
| + // x-only offsets for horizontal positioning ([x1, x2, ... xn]), or interleaved x,y offsets
|
| + // for full positioning ([x1, y1, x2, y2, ... xn, yn]).
|
| + 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
|
| {
|
| - return m_advances[index];
|
| + ASSERT(index < size());
|
| + return hasVerticalOffsets() ? m_offsets[index * 2] : m_offsets[index];
|
| +
|
| }
|
|
|
| - void add(Glyph glyph, const SimpleFontData* font, float width)
|
| + float yOffsetAt(unsigned index) const
|
| {
|
| - // should not mix offset/advance-only glyphs
|
| - ASSERT(!hasOffsets());
|
| + ASSERT(index < size());
|
| + ASSERT(hasVerticalOffsets());
|
| + return m_offsets[index * 2 + 1];
|
| + }
|
| +
|
| + void add(Glyph glyph, const SimpleFontData* font, float x)
|
| + {
|
| + // 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;
|
| +
|
| + // Glyph positioning: either x-only offsets, or interleaved x,y offsets
|
| + // (depending on the buffer-wide positioning mode). This matches the
|
| + // glyph positioning format used by Skia.
|
| + Vector<float, 2048> m_offsets;
|
| };
|
|
|
| } // namespace blink
|
|
|