diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/android/FontAndroid.cpp')
-rw-r--r-- | Source/WebCore/platform/graphics/android/FontAndroid.cpp | 91 |
1 files changed, 59 insertions, 32 deletions
diff --git a/Source/WebCore/platform/graphics/android/FontAndroid.cpp b/Source/WebCore/platform/graphics/android/FontAndroid.cpp index 0a8c0c1..ef7740c 100644 --- a/Source/WebCore/platform/graphics/android/FontAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/FontAndroid.cpp @@ -52,6 +52,7 @@ #include <wtf/OwnPtr.h> #include <wtf/PassOwnArrayPtr.h> #include <wtf/PassOwnPtr.h> +#include <wtf/unicode/CharacterNames.h> #include <wtf/unicode/Unicode.h> #endif @@ -379,7 +380,7 @@ static int truncateFixedPointToInteger(HB_Fixed value) // can call |reset| to start over again. class TextRunWalker { public: - TextRunWalker(const TextRun&, unsigned, const Font*); + TextRunWalker(const TextRun&, int, int, const Font*); ~TextRunWalker(); bool isWordBreak(unsigned, bool); @@ -425,10 +426,10 @@ public: // Return the length of the array returned by |glyphs| unsigned length() const { return m_item.num_glyphs; } - // Return the x offset for each of the glyphs. Note that this is translated + // Return the offset for each of the glyphs. Note that this is translated // by the current x offset and that the x offset is updated for each script // run. - const SkScalar* xPositions() const { return m_xPositions; } + const SkPoint* positions() const { return m_positions; } // Get the advances (widths) for each glyph. const HB_Fixed* advances() const { return m_item.advances; } @@ -472,7 +473,7 @@ private: void createGlyphArrays(int); void resetGlyphArrays(); void shapeGlyphs(); - void setGlyphXPositions(bool); + void setGlyphPositions(bool); static void normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar* destination, int length); @@ -485,10 +486,11 @@ private: const Font* const m_font; HB_ShaperItem m_item; uint16_t* m_glyphs16; // A vector of 16-bit glyph ids. - SkScalar* m_xPositions; // A vector of x positions for each glyph. + SkPoint* m_positions; // A vector of positions for each glyph. ssize_t m_indexOfNextScriptRun; // Indexes the script run in |m_run|. - const unsigned m_startingX; // Offset in pixels of the first script run. - unsigned m_offsetX; // Offset in pixels to the start of the next script run. + const int m_startingX; // Offset in pixels of the first script run. + const int m_startingY; // Offset in pixels of the first script run. + int m_offsetX; // Offset in pixels to the start of the next script run. unsigned m_pixelWidth; // Width (in px) of the current script run. unsigned m_numCodePoints; // Code points in current script run. unsigned m_glyphsArrayCapacity; // Current size of all the Harfbuzz arrays. @@ -519,9 +521,10 @@ const char* TextRunWalker::paths[] = { "/system/fonts/DroidSansThai.ttf" }; -TextRunWalker::TextRunWalker(const TextRun& run, unsigned startingX, const Font* font) +TextRunWalker::TextRunWalker(const TextRun& run, int startingX, int startingY, const Font* font) : m_font(font) , m_startingX(startingX) + , m_startingY(startingY) , m_offsetX(m_startingX) , m_run(getNormalizedTextRun(run, m_normalizedRun, m_normalizedBuffer)) , m_iterateBackwards(m_run.rtl()) @@ -650,7 +653,7 @@ bool TextRunWalker::nextScriptRun() setupFontForScriptRun(); shapeGlyphs(); - setGlyphXPositions(rtl()); + setGlyphPositions(rtl()); return true; } @@ -737,6 +740,16 @@ void TextRunWalker::setupFontForScriptRun() } m_item.face = complexPlatformData->harfbuzzFace(); m_item.font->userData = const_cast<FontPlatformData*>(complexPlatformData); + + int size = complexPlatformData->size(); + m_item.font->x_ppem = size; + m_item.font->y_ppem = size; + // x_ and y_scale are the conversion factors from font design space (fEmSize) to 1/64th of device pixels in 16.16 format. + const int devicePixelFraction = 64; + const int multiplyFor16Dot16 = 1 << 16; + int scale = devicePixelFraction * size * multiplyFor16Dot16 / complexPlatformData->emSizeInFontUnits(); + m_item.font->x_scale = scale; + m_item.font->y_scale = scale; } HB_FontRec* TextRunWalker::allocHarfbuzzFont() @@ -745,13 +758,6 @@ HB_FontRec* TextRunWalker::allocHarfbuzzFont() memset(font, 0, sizeof(HB_FontRec)); font->klass = &harfbuzzSkiaClass; font->userData = 0; - // The values which harfbuzzSkiaClass returns are already scaled to - // pixel units, so we just set all these to one to disable further - // scaling. - font->x_ppem = 1; - font->y_ppem = 1; - font->x_scale = 1; - font->y_scale = 1; return font; } @@ -763,7 +769,7 @@ void TextRunWalker::deleteGlyphArrays() delete[] m_item.advances; delete[] m_item.offsets; delete[] m_glyphs16; - delete[] m_xPositions; + delete[] m_positions; } void TextRunWalker::createGlyphArrays(int size) @@ -774,7 +780,7 @@ void TextRunWalker::createGlyphArrays(int size) m_item.offsets = new HB_FixedPoint[size]; m_glyphs16 = new uint16_t[size]; - m_xPositions = new SkScalar[size]; + m_positions = new SkPoint[size]; m_item.num_glyphs = size; m_glyphsArrayCapacity = size; // Save the GlyphArrays size. @@ -790,7 +796,7 @@ void TextRunWalker::resetGlyphArrays() memset(m_item.advances, 0, size * sizeof(m_item.advances[0])); memset(m_item.offsets, 0, size * sizeof(m_item.offsets[0])); memset(m_glyphs16, 0, size * sizeof(m_glyphs16[0])); - memset(m_xPositions, 0, size * sizeof(m_xPositions[0])); + memset(m_positions, 0, size * sizeof(m_positions[0])); } void TextRunWalker::shapeGlyphs() @@ -810,7 +816,7 @@ void TextRunWalker::shapeGlyphs() } } -void TextRunWalker::setGlyphXPositions(bool isRTL) +void TextRunWalker::setGlyphPositions(bool isRTL) { int position = 0; // logClustersIndex indexes logClusters for the first (or last when @@ -825,7 +831,9 @@ void TextRunWalker::setGlyphXPositions(bool isRTL) int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; m_glyphs16[i] = m_item.glyphs[i]; - m_xPositions[i] = SkIntToScalar(m_offsetX + position); + int offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); + int offsetY = truncateFixedPointToInteger(m_item.offsets[i].y); + m_positions[i].set(SkIntToScalar(m_offsetX + position) + offsetX, m_startingY + offsetY); int advance = truncateFixedPointToInteger(m_item.advances[i]); // The first half of the conjunction works around the case where @@ -846,6 +854,21 @@ void TextRunWalker::setGlyphXPositions(bool isRTL) } } + // ZeroWidthJoiners and ZeroWidthNonJoiners should be stripped by + // Harfbuzz, but aren't. Check for zwj and zwnj and replace with a + // zero width space. We get the glyph data for space instead of + // zeroWidthSpace because the latter was seen to render with an + // unexpected code point (the symbol for a cloud). Since the standard + // space is in page zero and since we've also confirmed that there is + // no advance on this glyph, that should be ok. + if (0 == m_item.advances[i]) { + const HB_UChar16 c = m_item.string[m_item.item.pos + logClustersIndex]; + if ((c == zeroWidthJoiner) || (c == zeroWidthNonJoiner)) { + static Glyph spaceGlyph = m_font->glyphDataForCharacter(space, false).glyph; + m_glyphs16[i] = spaceGlyph; + } + } + // TODO We would like to add m_letterSpacing after each cluster, but I // don't know where the cluster information is. This is typically // fine for Roman languages, but breaks more complex languages @@ -878,10 +901,14 @@ void TextRunWalker::normalizeSpacesAndMirrorChars(const UChar* source, bool rtl, UChar32 character; int nextPosition = position; U16_NEXT(source, nextPosition, length, character); + if (Font::treatAsSpace(character)) - character = ' '; + character = space; + else if (Font::treatAsZeroWidthSpaceInComplexScript(character)) + character = zeroWidthSpace; else if (rtl) character = u_charMirror(character); + U16_APPEND(destination, position, length, character, error); ASSERT(!error); position = nextPosition; @@ -947,7 +974,7 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, { int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1; - TextRunWalker walker(run, 0, this); + TextRunWalker walker(run, 0, 0, this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); // Base will point to the x offset for the current script run. Note that, in @@ -974,14 +1001,14 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, // find which glyph this code-point contributed to and find its x // position. int glyph = walker.logClusters()[from]; - fromX = base + walker.xPositions()[glyph]; + fromX = base + walker.positions()[glyph].x(); fromAdvance = walker.advances()[glyph]; } else from -= numCodePoints; if (toX == -1 && to < numCodePoints) { int glyph = walker.logClusters()[to]; - toX = base + walker.xPositions()[glyph]; + toX = base + walker.positions()[glyph].x(); toAdvance = walker.advances()[glyph]; } else to -= numCodePoints; @@ -1028,7 +1055,7 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, SkCanvas* canvas = gc->platformContext()->mCanvas; bool haveMultipleLayers = isCanvasMultiLayered(canvas); - TextRunWalker walker(run, point.x(), this); + TextRunWalker walker(run, point.x(), point.y(), this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); walker.setPadding(run.expansion()); @@ -1036,14 +1063,14 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, if (fill) { walker.fontPlatformDataForScriptRun()->setupPaint(&fillPaint); adjustTextRenderMode(&fillPaint, haveMultipleLayers); - canvas->drawPosTextH(walker.glyphs(), walker.length() << 1, - walker.xPositions(), point.y(), fillPaint); + canvas->drawPosText(walker.glyphs(), walker.length() << 1, + walker.positions(), fillPaint); } if (stroke) { walker.fontPlatformDataForScriptRun()->setupPaint(&strokePaint); adjustTextRenderMode(&strokePaint, haveMultipleLayers); - canvas->drawPosTextH(walker.glyphs(), walker.length() << 1, - walker.xPositions(), point.y(), strokePaint); + canvas->drawPosText(walker.glyphs(), walker.length() << 1, + walker.positions(), strokePaint); } } } @@ -1051,7 +1078,7 @@ void Font::drawComplexText(GraphicsContext* gc, TextRun const& run, float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const { - TextRunWalker walker(run, 0, this); + TextRunWalker walker(run, 0, 0, this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); return walker.widthOfFullRun(); } @@ -1083,7 +1110,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float x, { // (Mac code ignores includePartialGlyphs, and they don't know what it's // supposed to do, so we just ignore it as well.) - TextRunWalker walker(run, 0, this); + TextRunWalker walker(run, 0, 0, this); walker.setWordAndLetterSpacing(wordSpacing(), letterSpacing()); // If this is RTL text, the first glyph from the left is actually the last |