summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/android/FontAndroid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/android/FontAndroid.cpp')
-rw-r--r--Source/WebCore/platform/graphics/android/FontAndroid.cpp91
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