summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2011-06-01 14:52:00 -0700
committerRomain Guy <romainguy@google.com>2011-06-01 14:55:42 -0700
commit726aeba80ffc6778a9bc3e0ee957b8d644183505 (patch)
tree2a270831f12cfa6dd69a07e9068c76c3b737754e /libs/hwui
parentf09ef51889f75289b041f9e9f949b7b82ed5b686 (diff)
downloadframeworks_base-726aeba80ffc6778a9bc3e0ee957b8d644183505.zip
frameworks_base-726aeba80ffc6778a9bc3e0ee957b8d644183505.tar.gz
frameworks_base-726aeba80ffc6778a9bc3e0ee957b8d644183505.tar.bz2
Add support to OpenGLRendere to draw BiDi text.
Bug #4350336 Change-Id: I1cf31693f7ca9653fa3a41b5b91c27ef288d680f
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/DisplayListRenderer.cpp1
-rw-r--r--libs/hwui/FontRenderer.cpp43
-rw-r--r--libs/hwui/FontRenderer.h61
-rw-r--r--libs/hwui/OpenGLRenderer.cpp22
-rw-r--r--libs/hwui/OpenGLRenderer.h2
-rw-r--r--libs/hwui/Properties.h3
-rw-r--r--libs/hwui/TextDropShadowCache.h1
7 files changed, 84 insertions, 49 deletions
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index f8582d8..afab26a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -1151,6 +1151,7 @@ void DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
float x, float y, SkPaint* paint) {
+ if (count <= 0) return;
addOp(DisplayList::DrawText);
addText(text, bytesCount);
addInt(count);
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 1ca0a19..9bf3de8 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -35,6 +35,7 @@ namespace uirenderer {
#define DEFAULT_TEXT_CACHE_WIDTH 1024
#define DEFAULT_TEXT_CACHE_HEIGHT 256
+// We should query these values from the GL context
#define MAX_TEXT_CACHE_WIDTH 2048
#define MAX_TEXT_CACHE_HEIGHT 2048
@@ -58,8 +59,7 @@ Font::~Font() {
}
for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
- CachedGlyphInfo* glyph = mCachedGlyphs.valueAt(i);
- delete glyph;
+ delete mCachedGlyphs.valueAt(i);
}
}
@@ -134,48 +134,49 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
}
-Font::CachedGlyphInfo* Font::getCachedUTFChar(SkPaint* paint, int32_t utfChar) {
+Font::CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
CachedGlyphInfo* cachedGlyph = NULL;
- ssize_t index = mCachedGlyphs.indexOfKey(utfChar);
+ ssize_t index = mCachedGlyphs.indexOfKey(textUnit);
if (index >= 0) {
cachedGlyph = mCachedGlyphs.valueAt(index);
} else {
- cachedGlyph = cacheGlyph(paint, utfChar);
+ cachedGlyph = cacheGlyph(paint, textUnit);
}
// Is the glyph still in texture cache?
if (!cachedGlyph->mIsValid) {
- const SkGlyph& skiaGlyph = paint->getUnicharMetrics(utfChar);
+ const SkGlyph& skiaGlyph = GET_METRICS(paint, textUnit);
updateGlyphCache(paint, skiaGlyph, cachedGlyph);
}
return cachedGlyph;
}
-void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
int numGlyphs, int x, int y, uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH) {
if (bitmap != NULL && bitmapW > 0 && bitmapH > 0) {
- renderUTF(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
+ render(paint, text, start, len, numGlyphs, x, y, BITMAP, bitmap,
bitmapW, bitmapH, NULL);
} else {
- renderUTF(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL, 0, 0, NULL);
+ render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
+ 0, 0, NULL);
}
}
-void Font::measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
int numGlyphs, Rect *bounds) {
if (bounds == NULL) {
LOGE("No return rectangle provided to measure text");
return;
}
bounds->set(1e6, -1e6, -1e6, 1e6);
- renderUTF(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds);
+ render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds);
}
#define SkAutoKern_AdjustF(prev, next) (((next) - (prev) + 32) >> 6 << 16)
-void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
uint32_t bitmapW, uint32_t bitmapH,Rect *bounds) {
if (numGlyphs == 0 || text == NULL || len == 0) {
@@ -195,14 +196,14 @@ void Font::renderUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t
text += start;
while (glyphsLeft > 0) {
- int32_t utfChar = SkUTF16_NextUnichar((const uint16_t**) &text);
+ glyph_t glyph = GET_GLYPH(text);
// Reached the end of the string
- if (utfChar < 0) {
+ if (IS_END_OF_STRING(glyph)) {
break;
}
- CachedGlyphInfo* cachedGlyph = getCachedUTFChar(paint, utfChar);
+ CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
penX += SkAutoKern_AdjustF(prevRsbDelta, cachedGlyph->mLsbDelta);
prevRsbDelta = cachedGlyph->mRsbDelta;
@@ -268,11 +269,11 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
mState->mUploadTexture = true;
}
-Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, int32_t glyph) {
+Font::CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph) {
CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
mCachedGlyphs.add(glyph, newGlyph);
- const SkGlyph& skiaGlyph = paint->getUnicharMetrics(glyph);
+ const SkGlyph& skiaGlyph = GET_METRICS(paint, glyph);
newGlyph->mGlyphIndex = skiaGlyph.fID;
newGlyph->mIsValid = false;
@@ -672,7 +673,7 @@ void FontRenderer::precacheLatin(SkPaint* paint) {
uint32_t remainingCapacity = getRemainingCacheCapacity();
uint32_t precacheIdx = 0;
while (remainingCapacity > 25 && precacheIdx < mLatinPrecache.size()) {
- mCurrentFont->getCachedUTFChar(paint, (int32_t) mLatinPrecache[precacheIdx]);
+ mCurrentFont->getCachedGlyph(paint, (int32_t) mLatinPrecache[precacheIdx]);
remainingCapacity = getRemainingCacheCapacity();
precacheIdx ++;
}
@@ -714,7 +715,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
}
Rect bounds;
- mCurrentFont->measureUTF(paint, text, startIndex, len, numGlyphs, &bounds);
+ mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds);
uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius;
uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius;
uint8_t* dataBuffer = new uint8_t[paddedWidth * paddedHeight];
@@ -725,7 +726,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch
int penX = radius - bounds.left;
int penY = radius - bounds.bottom;
- mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, penX, penY,
+ mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY,
dataBuffer, paddedWidth, paddedHeight);
blurImage(dataBuffer, paddedWidth, paddedHeight, radius);
@@ -755,7 +756,7 @@ bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text
mDrawn = false;
mBounds = bounds;
mClip = clip;
- mCurrentFont->renderUTF(paint, text, startIndex, len, numGlyphs, x, y);
+ mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y);
mBounds = NULL;
if (mCurrentQuadIndex != 0) {
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 95f714f..24ed6fa 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -33,8 +33,32 @@
namespace android {
namespace uirenderer {
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+#if RENDER_TEXT_AS_GLYPHS
+ typedef uint16_t glyph_t;
+ #define GET_METRICS(paint, glyph) paint->getGlyphMetrics(glyph)
+ #define GET_GLYPH(text) nextGlyph((const uint16_t**) &text)
+ #define IS_END_OF_STRING(glyph) false
+#else
+ typedef SkUnichar glyph_t;
+ #define GET_METRICS(paint, glyph) paint->getUnicharMetrics(glyph)
+ #define GET_GLYPH(text) SkUTF16_NextUnichar((const uint16_t**) &text)
+ #define IS_END_OF_STRING(glyph) glyph < 0
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Declarations
+///////////////////////////////////////////////////////////////////////////////
+
class FontRenderer;
+///////////////////////////////////////////////////////////////////////////////
+// Font
+///////////////////////////////////////////////////////////////////////////////
+
/**
* Represents a font, defined by a Skia font id and a font size. A font is used
* to generate glyphs and cache them in the FontState.
@@ -51,9 +75,9 @@ public:
* Renders the specified string of text.
* If bitmap is specified, it will be used as the render target
*/
- void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
- int numGlyphs, int x, int y,
- uint8_t *bitmap = NULL, uint32_t bitmapW = 0, uint32_t bitmapH = 0);
+ void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+ int numGlyphs, int x, int y, uint8_t *bitmap = NULL,
+ uint32_t bitmapW = 0, uint32_t bitmapH = 0);
/**
* Creates a new font associated with the specified font state.
*/
@@ -69,13 +93,12 @@ protected:
MEASURE,
};
- void renderUTF(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
- int numGlyphs, int x, int y, RenderMode mode,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
- Rect *bounds);
+ void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+ int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
+ uint32_t bitmapW, uint32_t bitmapH, Rect *bounds);
- void measureUTF(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
- int numGlyphs, Rect *bounds);
+ void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+ int numGlyphs, Rect *bounds);
struct CachedGlyphInfo {
// Has the cache been invalidated?
@@ -107,18 +130,26 @@ protected:
Font(FontRenderer* state, uint32_t fontId, float fontSize, int flags, uint32_t italicStyle,
uint32_t scaleX);
- DefaultKeyedVector<int32_t, CachedGlyphInfo*> mCachedGlyphs;
+ // Cache of glyphs
+ DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
void invalidateTextureCache();
- CachedGlyphInfo* cacheGlyph(SkPaint* paint, int32_t glyph);
+ CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo *glyph);
void measureCachedGlyph(CachedGlyphInfo *glyph, int x, int y, Rect *bounds);
void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y);
void drawCachedGlyph(CachedGlyphInfo *glyph, int x, int y,
- uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
+ uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH);
- CachedGlyphInfo* getCachedUTFChar(SkPaint* paint, int32_t utfChar);
+ CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit);
+
+ static glyph_t nextGlyph(const uint16_t** srcPtr) {
+ const uint16_t* src = *srcPtr;
+ glyph_t g = *src++;
+ *srcPtr = src;
+ return g;
+ }
FontRenderer* mState;
uint32_t mFontId;
@@ -128,6 +159,10 @@ protected:
uint32_t mScaleX;
};
+///////////////////////////////////////////////////////////////////////////////
+// Renderer
+///////////////////////////////////////////////////////////////////////////////
+
class FontRenderer {
public:
FontRenderer();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 6243b01..45f4a42 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2073,11 +2073,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
drawTextDecorations(text, bytesCount, length, oldX, oldY, paint);
}
-void OpenGLRenderer::drawGlyphs(const char* glyphs, int index, int count, float x, float y,
- SkPaint* paint) {
- // TODO
-}
-
void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
if (mSnapshot->isIgnored()) return;
@@ -2230,14 +2225,19 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
// Handle underline and strike-through
uint32_t flags = paint->getFlags();
if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+ SkPaint paintCopy(*paint);
+#if RENDER_TEXT_AS_GLYPHS
+ paintCopy.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+#endif
+
float underlineWidth = length;
// If length is > 0.0f, we already measured the text for the text alignment
if (length <= 0.0f) {
- underlineWidth = paint->measureText(text, bytesCount);
+ underlineWidth = paintCopy.measureText(text, bytesCount);
}
float offsetX = 0;
- switch (paint->getTextAlign()) {
+ switch (paintCopy.getTextAlign()) {
case SkPaint::kCenter_Align:
offsetX = underlineWidth * 0.5f;
break;
@@ -2249,8 +2249,7 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
}
if (underlineWidth > 0.0f) {
- const float textSize = paint->getTextSize();
- // TODO: Support stroke width < 1.0f when we have AA lines
+ const float textSize = paintCopy.getTextSize();
const float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
const float left = x - offsetX;
@@ -2280,10 +2279,9 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float
points[currentPoint++] = top;
}
- SkPaint linesPaint(*paint);
- linesPaint.setStrokeWidth(strokeWidth);
+ paintCopy.setStrokeWidth(strokeWidth);
- drawLines(&points[0], pointsCount, &linesPaint);
+ drawLines(&points[0], pointsCount, &paintCopy);
}
}
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index e2dbba0..549d6e9 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -123,8 +123,6 @@ public:
virtual void drawPoints(float* points, int count, SkPaint* paint);
virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
SkPaint* paint);
- virtual void drawGlyphs(const char* glyphs, int index, int count, float x, float y,
- SkPaint* paint);
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 2d8b6f3..7c10518 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -28,6 +28,9 @@
// If turned on, layers drawn inside FBOs are optimized with regions
#define RENDER_LAYERS_AS_REGIONS 1
+// If turned on, text is interpreted as glyphs instead of UTF-16
+#define RENDER_TEXT_AS_GLYPHS 1
+
/**
* Debug level for app developers.
*/
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index d46686d..28dba13 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -73,7 +73,6 @@ struct ShadowText {
text = str.string();
}
- // TODO: Should take into account fake bold and text skew
bool operator<(const ShadowText& rhs) const {
LTE_INT(len) {
LTE_INT(radius) {