Merge "Better Minikin integration" into lmp-preview-dev
This commit is contained in:
@@ -821,32 +821,45 @@ public:
|
||||
}
|
||||
|
||||
#ifdef USE_MINIKIN
|
||||
static void drawGlyphsToSkia(SkCanvas* canvas, SkPaint* paint, Layout* layout, float x, float y) {
|
||||
size_t nGlyphs = layout->nGlyphs();
|
||||
uint16_t *glyphs = new uint16_t[nGlyphs];
|
||||
SkPoint *pos = new SkPoint[nGlyphs];
|
||||
SkTypeface *lastFace = NULL;
|
||||
SkTypeface *skFace = NULL;
|
||||
size_t start = 0;
|
||||
class DrawTextFunctor {
|
||||
public:
|
||||
DrawTextFunctor(const Layout& layout, SkCanvas* canvas, jfloat x, jfloat y, SkPaint* paint,
|
||||
uint16_t* glyphs, SkPoint* pos)
|
||||
: layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
|
||||
pos(pos) { }
|
||||
|
||||
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
||||
for (size_t i = 0; i < nGlyphs; i++) {
|
||||
MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
|
||||
skFace = mfs->GetSkTypeface();
|
||||
glyphs[i] = layout->getGlyphId(i);
|
||||
pos[i].fX = x + layout->getX(i);
|
||||
pos[i].fY = y + layout->getY(i);
|
||||
if (i > 0 && skFace != lastFace) {
|
||||
paint->setTypeface(lastFace);
|
||||
canvas->drawPosText(glyphs + start, (i - start) << 1, pos + start, *paint);
|
||||
start = i;
|
||||
void operator()(SkTypeface* t, size_t start, size_t end) {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
glyphs[i] = layout.getGlyphId(i);
|
||||
pos[i].fX = x + layout.getX(i);
|
||||
pos[i].fY = y + layout.getY(i);
|
||||
}
|
||||
lastFace = skFace;
|
||||
}
|
||||
if (skFace != NULL) {
|
||||
paint->setTypeface(skFace);
|
||||
canvas->drawPosText(glyphs + start, (nGlyphs - start) << 1, pos + start, *paint);
|
||||
paint->setTypeface(t);
|
||||
canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
|
||||
}
|
||||
private:
|
||||
const Layout& layout;
|
||||
SkCanvas* canvas;
|
||||
jfloat x;
|
||||
jfloat y;
|
||||
SkPaint* paint;
|
||||
uint16_t* glyphs;
|
||||
SkPoint* pos;
|
||||
};
|
||||
|
||||
static void drawGlyphsToSkia(SkCanvas* canvas, SkPaint* paint, const Layout& layout, float x, float y) {
|
||||
size_t nGlyphs = layout.nGlyphs();
|
||||
uint16_t* glyphs = new uint16_t[nGlyphs];
|
||||
SkPoint* pos = new SkPoint[nGlyphs];
|
||||
|
||||
x += MinikinUtils::xOffsetForTextAlign(paint, layout);
|
||||
SkPaint::Align align = paint->getTextAlign();
|
||||
paint->setTextAlign(SkPaint::kLeft_Align);
|
||||
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
||||
DrawTextFunctor f(layout, canvas, x, y, paint, glyphs, pos);
|
||||
MinikinUtils::forFontRun(layout, f);
|
||||
doDrawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
|
||||
paint->setTextAlign(align);
|
||||
delete[] glyphs;
|
||||
delete[] pos;
|
||||
}
|
||||
@@ -868,7 +881,7 @@ public:
|
||||
Layout layout;
|
||||
MinikinUtils::SetLayoutProperties(&layout, paint, flags, typeface);
|
||||
layout.doLayout(textArray + start, count);
|
||||
drawGlyphsToSkia(canvas, paint, &layout, x, y);
|
||||
drawGlyphsToSkia(canvas, paint, layout, x, y);
|
||||
#else
|
||||
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
|
||||
textArray, start, count, contextCount, flags);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "SkPaint.h"
|
||||
#include "minikin/Layout.h"
|
||||
#include "TypefaceImpl.h"
|
||||
#include "MinikinSkia.h"
|
||||
|
||||
#include "MinikinUtils.h"
|
||||
|
||||
@@ -42,4 +43,18 @@ void MinikinUtils::SetLayoutProperties(Layout* layout, SkPaint* paint, int flags
|
||||
layout->setProperties(css);
|
||||
}
|
||||
|
||||
}
|
||||
float MinikinUtils::xOffsetForTextAlign(SkPaint* paint, const Layout& layout) {
|
||||
switch (paint->getTextAlign()) {
|
||||
case SkPaint::kCenter_Align:
|
||||
return layout.getAdvance() * -0.5f;
|
||||
break;
|
||||
case SkPaint::kRight_Align:
|
||||
return -layout.getAdvance();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,27 @@ class MinikinUtils {
|
||||
public:
|
||||
static void SetLayoutProperties(Layout* layout, SkPaint* paint, int flags,
|
||||
TypefaceImpl* face);
|
||||
static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);
|
||||
|
||||
// f is a functor of type void f(SkTypeface *, size_t start, size_t end);
|
||||
template <typename F>
|
||||
static void forFontRun(const Layout& layout, F& f) {
|
||||
SkTypeface* lastFace = NULL;
|
||||
size_t start = 0;
|
||||
size_t nGlyphs = layout.nGlyphs();
|
||||
for (size_t i = 0; i < nGlyphs; i++) {
|
||||
MinikinFontSkia* mfs = static_cast<MinikinFontSkia*>(layout.getFont(i));
|
||||
SkTypeface* skFace = mfs->GetSkTypeface();
|
||||
if (i > 0 && skFace != lastFace) {
|
||||
f(lastFace, start, i);
|
||||
start = i;
|
||||
}
|
||||
lastFace = skFace;
|
||||
}
|
||||
if (nGlyphs > start) {
|
||||
f(lastFace, start, nGlyphs);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -822,26 +822,83 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
static void getTextPath(JNIEnv* env, SkPaint* paint, const jchar* text, jint count,
|
||||
jint bidiFlags, jfloat x, jfloat y, SkPath *path) {
|
||||
#ifdef USE_MINIKIN
|
||||
class GetTextFunctor {
|
||||
public:
|
||||
GetTextFunctor(const Layout& layout, SkPath* path, jfloat x, jfloat y, SkPaint* paint,
|
||||
uint16_t* glyphs, SkPoint* pos)
|
||||
: layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) {
|
||||
}
|
||||
|
||||
void operator()(SkTypeface* t, size_t start, size_t end) {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
glyphs[i] = layout.getGlyphId(i);
|
||||
pos[i].fX = x + layout.getX(i);
|
||||
pos[i].fY = y + layout.getY(i);
|
||||
}
|
||||
paint->setTypeface(t);
|
||||
if (start == 0) {
|
||||
paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path);
|
||||
} else {
|
||||
paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, &tmpPath);
|
||||
path->addPath(tmpPath);
|
||||
}
|
||||
}
|
||||
private:
|
||||
const Layout& layout;
|
||||
SkPath* path;
|
||||
jfloat x;
|
||||
jfloat y;
|
||||
SkPaint* paint;
|
||||
uint16_t* glyphs;
|
||||
SkPoint* pos;
|
||||
SkPath tmpPath;
|
||||
};
|
||||
#endif
|
||||
|
||||
static void getTextPath(JNIEnv* env, SkPaint* paint, TypefaceImpl* typeface, const jchar* text,
|
||||
jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
|
||||
#ifdef USE_MINIKIN
|
||||
Layout layout;
|
||||
MinikinUtils::SetLayoutProperties(&layout, paint, bidiFlags, typeface);
|
||||
layout.doLayout(text, count);
|
||||
size_t nGlyphs = layout.nGlyphs();
|
||||
uint16_t* glyphs = new uint16_t[nGlyphs];
|
||||
SkPoint* pos = new SkPoint[nGlyphs];
|
||||
|
||||
x += MinikinUtils::xOffsetForTextAlign(paint, layout);
|
||||
SkPaint::Align align = paint->getTextAlign();
|
||||
paint->setTextAlign(SkPaint::kLeft_Align);
|
||||
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
||||
GetTextFunctor f(layout, path, x, y, paint, glyphs, pos);
|
||||
MinikinUtils::forFontRun(layout, f);
|
||||
paint->setTextAlign(align);
|
||||
delete[] glyphs;
|
||||
delete[] pos;
|
||||
#else
|
||||
TextLayout::getTextPath(paint, text, count, bidiFlags, x, y, path);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags,
|
||||
static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle,
|
||||
jlong typefaceHandle, jint bidiFlags,
|
||||
jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
|
||||
const jchar* textArray = env->GetCharArrayElements(text, NULL);
|
||||
getTextPath(env, paint, textArray + index, count, bidiFlags, x, y, path);
|
||||
getTextPath(env, paint, typeface, textArray + index, count, bidiFlags, x, y, path);
|
||||
env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
|
||||
}
|
||||
|
||||
static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags,
|
||||
static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle,
|
||||
jlong typefaceHandle, jint bidiFlags,
|
||||
jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
|
||||
const jchar* textArray = env->GetStringChars(text, NULL);
|
||||
getTextPath(env, paint, textArray + start, end - start, bidiFlags, x, y, path);
|
||||
getTextPath(env, paint, typeface, textArray + start, end - start, bidiFlags, x, y, path);
|
||||
env->ReleaseStringChars(text, textArray);
|
||||
}
|
||||
|
||||
@@ -1035,8 +1092,8 @@ static JNINativeMethod methods[] = {
|
||||
{"native_getTextRunCursor", "(J[CIIIII)I", (void*) SkPaintGlue::getTextRunCursor___C},
|
||||
{"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",
|
||||
(void*) SkPaintGlue::getTextRunCursor__String},
|
||||
{"native_getTextPath","(JI[CIIFFJ)V", (void*) SkPaintGlue::getTextPath___C},
|
||||
{"native_getTextPath","(JILjava/lang/String;IIFFJ)V", (void*) SkPaintGlue::getTextPath__String},
|
||||
{"native_getTextPath","(JJI[CIIFFJ)V", (void*) SkPaintGlue::getTextPath___C},
|
||||
{"native_getTextPath","(JJILjava/lang/String;IIFFJ)V", (void*) SkPaintGlue::getTextPath__String},
|
||||
{"nativeGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V",
|
||||
(void*) SkPaintGlue::getStringBounds },
|
||||
{"nativeGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define LOG_TAG "TextLayoutCache"
|
||||
|
||||
#include <utils/JenkinsHash.h>
|
||||
#include <utils/CallStack.h>
|
||||
|
||||
#include "TextLayoutCache.h"
|
||||
#include "TextLayout.h"
|
||||
@@ -89,6 +90,11 @@ void TextLayoutCache::purgeCaches() {
|
||||
sp<TextLayoutValue> TextLayoutCache::getValue(const SkPaint* paint,
|
||||
const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) {
|
||||
AutoMutex _l(mLock);
|
||||
#ifdef USE_MINIKIN
|
||||
// We want to get rid of all legacy calls in the Minikin case, so log
|
||||
ALOGW("TextLayoutCache being invoked!");
|
||||
CallStack _cs(LOG_TAG);
|
||||
#endif
|
||||
nsecs_t startTime = 0;
|
||||
if (mDebugEnabled) {
|
||||
startTime = systemTime(SYSTEM_TIME_MONOTONIC);
|
||||
|
||||
@@ -632,6 +632,7 @@ static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject claz
|
||||
// Text
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TODO: this is moving to MinikinUtils, remove with USE_MINIKIN ifdef
|
||||
static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) {
|
||||
switch (paint->getTextAlign()) {
|
||||
case SkPaint::kCenter_Align:
|
||||
@@ -647,43 +648,51 @@ static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) {
|
||||
}
|
||||
|
||||
#ifdef USE_MINIKIN
|
||||
|
||||
class RenderTextFunctor {
|
||||
public:
|
||||
RenderTextFunctor(const Layout& layout, OpenGLRenderer* renderer, jfloat x, jfloat y,
|
||||
SkPaint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
|
||||
uirenderer::Rect& bounds)
|
||||
: layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
|
||||
pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
|
||||
void operator()(SkTypeface* t, size_t start, size_t end) {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
glyphs[i] = layout.getGlyphId(i);
|
||||
pos[2 * i] = layout.getX(i);
|
||||
pos[2 * i + 1] = layout.getY(i);
|
||||
}
|
||||
paint->setTypeface(t);
|
||||
size_t glyphsCount = end - start;
|
||||
int bytesCount = glyphsCount * sizeof(jchar);
|
||||
renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
|
||||
x, y, pos + 2 * start, paint, totalAdvance, bounds);
|
||||
}
|
||||
private:
|
||||
const Layout& layout;
|
||||
OpenGLRenderer* renderer;
|
||||
jfloat x;
|
||||
jfloat y;
|
||||
SkPaint* paint;
|
||||
uint16_t* glyphs;
|
||||
float* pos;
|
||||
float totalAdvance;
|
||||
uirenderer::Rect& bounds;
|
||||
};
|
||||
|
||||
static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout,
|
||||
jfloat x, jfloat y, SkPaint* paint) {
|
||||
size_t nGlyphs = layout->nGlyphs();
|
||||
float* pos = new float[nGlyphs * 2];
|
||||
uint16_t* glyphs = new uint16_t[nGlyphs];
|
||||
SkTypeface* lastFace = 0;
|
||||
SkTypeface* skFace = 0;
|
||||
size_t start = 0;
|
||||
MinikinRect b;
|
||||
layout->getBounds(&b);
|
||||
android::uirenderer::Rect bounds(b.mLeft, b.mTop, b.mRight, b.mBottom);
|
||||
bounds.translate(x, y);
|
||||
float totalAdvance = layout->getAdvance();
|
||||
|
||||
for (size_t i = 0; i < nGlyphs; i++) {
|
||||
MinikinFontSkia* mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
|
||||
skFace = mfs->GetSkTypeface();
|
||||
glyphs[i] = layout->getGlyphId(i);
|
||||
pos[2 * i] = layout->getX(i);
|
||||
pos[2 * i + 1] = layout->getY(i);
|
||||
if (i > 0 && skFace != lastFace) {
|
||||
paint->setTypeface(lastFace);
|
||||
size_t glyphsCount = i - start;
|
||||
int bytesCount = glyphsCount * sizeof(jchar);
|
||||
renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
|
||||
x, y, pos + 2 * start, paint, totalAdvance, bounds);
|
||||
start = i;
|
||||
}
|
||||
lastFace = skFace;
|
||||
}
|
||||
if (skFace != NULL) {
|
||||
paint->setTypeface(skFace);
|
||||
size_t glyphsCount = nGlyphs - start;
|
||||
int bytesCount = glyphsCount * sizeof(jchar);
|
||||
renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
|
||||
x, y, pos + 2 * start, paint, totalAdvance, bounds);
|
||||
}
|
||||
RenderTextFunctor f(*layout, renderer, x, y, paint, glyphs, pos, totalAdvance, bounds);
|
||||
MinikinUtils::forFontRun(*layout, f);
|
||||
delete[] glyphs;
|
||||
delete[] pos;
|
||||
}
|
||||
|
||||
@@ -2131,7 +2131,7 @@ public class Paint {
|
||||
if ((index | count) < 0 || index + count > text.length) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
native_getTextPath(mNativePaint, mBidiFlags, text, index, count, x, y,
|
||||
native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, index, count, x, y,
|
||||
path.ni());
|
||||
}
|
||||
|
||||
@@ -2153,7 +2153,7 @@ public class Paint {
|
||||
if ((start | end | (end - start) | (text.length() - end)) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
native_getTextPath(mNativePaint, mBidiFlags, text, start, end, x, y,
|
||||
native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, start, end, x, y,
|
||||
path.ni());
|
||||
}
|
||||
|
||||
@@ -2261,10 +2261,10 @@ public class Paint {
|
||||
private native int native_getTextRunCursor(long native_object, String text,
|
||||
int contextStart, int contextEnd, int flags, int offset, int cursorOpt);
|
||||
|
||||
private static native void native_getTextPath(long native_object, int bidiFlags,
|
||||
char[] text, int index, int count, float x, float y, long path);
|
||||
private static native void native_getTextPath(long native_object, int bidiFlags,
|
||||
String text, int start, int end, float x, float y, long path);
|
||||
private static native void native_getTextPath(long native_object, long native_typeface,
|
||||
int bidiFlags, char[] text, int index, int count, float x, float y, long path);
|
||||
private static native void native_getTextPath(long native_object, long native_typeface,
|
||||
int bidiFlags, String text, int start, int end, float x, float y, long path);
|
||||
private static native void nativeGetStringBounds(long nativePaint,
|
||||
String text, int start, int end, int bidiFlags, Rect bounds);
|
||||
private static native void nativeGetCharArrayBounds(long nativePaint,
|
||||
|
||||
Reference in New Issue
Block a user