diff options
| -rw-r--r-- | core/jni/android/graphics/Canvas.cpp | 63 | ||||
| -rw-r--r-- | core/jni/android/graphics/MinikinUtils.cpp | 17 | ||||
| -rw-r--r-- | core/jni/android/graphics/MinikinUtils.h | 21 | ||||
| -rw-r--r-- | core/jni/android/graphics/Paint.cpp | 73 | ||||
| -rw-r--r-- | core/jni/android/graphics/TextLayoutCache.cpp | 6 | ||||
| -rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 61 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Paint.java | 12 |
7 files changed, 187 insertions, 66 deletions
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index f7acbd7..ec935cc 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -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; - - 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; + 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) { } + + 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); diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp index 79381ad..597160b 100644 --- a/core/jni/android/graphics/MinikinUtils.cpp +++ b/core/jni/android/graphics/MinikinUtils.cpp @@ -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); } -}
\ No newline at end of file +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; +} + +} diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h index 42f5e2f..f85074c 100644 --- a/core/jni/android/graphics/MinikinUtils.h +++ b/core/jni/android/graphics/MinikinUtils.h @@ -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 diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index 8418162..4642cfd 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -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", diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index 9279758..495d08a 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -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); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index c5dd06f..820da17 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -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; } diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 92cfd6b..f97add8 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -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, |
