Merge "Reland: Move text logic from jni to hwui level" into nyc-dev

am: d8e91f6

* commit 'd8e91f65ae038a5223d6efd4ca4e382c7764bd4e':
  Reland: Move text logic from jni to hwui level
This commit is contained in:
sergeyv
2016-03-22 00:18:37 +00:00
committed by android-build-merger
54 changed files with 450 additions and 361 deletions

View File

@@ -117,13 +117,10 @@ LOCAL_SRC_FILES:= \
android/graphics/Interpolator.cpp \ android/graphics/Interpolator.cpp \
android/graphics/MaskFilter.cpp \ android/graphics/MaskFilter.cpp \
android/graphics/Matrix.cpp \ android/graphics/Matrix.cpp \
android/graphics/MinikinSkia.cpp \
android/graphics/MinikinUtils.cpp \
android/graphics/Movie.cpp \ android/graphics/Movie.cpp \
android/graphics/NinePatch.cpp \ android/graphics/NinePatch.cpp \
android/graphics/NinePatchPeeker.cpp \ android/graphics/NinePatchPeeker.cpp \
android/graphics/Paint.cpp \ android/graphics/Paint.cpp \
android/graphics/PaintImpl.cpp \
android/graphics/Path.cpp \ android/graphics/Path.cpp \
android/graphics/PathMeasure.cpp \ android/graphics/PathMeasure.cpp \
android/graphics/PathEffect.cpp \ android/graphics/PathEffect.cpp \
@@ -135,7 +132,6 @@ LOCAL_SRC_FILES:= \
android/graphics/Shader.cpp \ android/graphics/Shader.cpp \
android/graphics/SurfaceTexture.cpp \ android/graphics/SurfaceTexture.cpp \
android/graphics/Typeface.cpp \ android/graphics/Typeface.cpp \
android/graphics/TypefaceImpl.cpp \
android/graphics/Utils.cpp \ android/graphics/Utils.cpp \
android/graphics/Xfermode.cpp \ android/graphics/Xfermode.cpp \
android/graphics/YuvToJpegEncoder.cpp \ android/graphics/YuvToJpegEncoder.cpp \

View File

@@ -1,7 +1,6 @@
#define LOG_TAG "Bitmap" #define LOG_TAG "Bitmap"
#include "Bitmap.h" #include "Bitmap.h"
#include "Paint.h"
#include "SkBitmap.h" #include "SkBitmap.h"
#include "SkPixelRef.h" #include "SkPixelRef.h"
#include "SkImageEncoder.h" #include "SkImageEncoder.h"
@@ -18,6 +17,7 @@
#include "android_nio_utils.h" #include "android_nio_utils.h"
#include "CreateJavaOutputStreamAdaptor.h" #include "CreateJavaOutputStreamAdaptor.h"
#include <Caches.h> #include <Caches.h>
#include <hwui/Paint.h>
#include "core_jni_helpers.h" #include "core_jni_helpers.h"

View File

@@ -3,8 +3,8 @@
#include "SkCamera.h" #include "SkCamera.h"
#include "Canvas.h"
#include "GraphicsJNI.h" #include "GraphicsJNI.h"
#include <hwui/Canvas.h>
static jfieldID gNativeInstanceFieldID; static jfieldID gNativeInstanceFieldID;

View File

@@ -16,9 +16,9 @@
#include "jni.h" #include "jni.h"
#include "GraphicsJNI.h" #include "GraphicsJNI.h"
#include "Paint.h"
#include <core_jni_helpers.h> #include <core_jni_helpers.h>
#include <hwui/Paint.h>
#include <utils/RefBase.h> #include <utils/RefBase.h>
#include <CanvasProperty.h> #include <CanvasProperty.h>

View File

@@ -31,9 +31,9 @@
#include <androidfw/AssetManager.h> #include <androidfw/AssetManager.h>
#include "Utils.h" #include "Utils.h"
#include "TypefaceImpl.h" #include <hwui/MinikinSkia.h>
#include <hwui/TypefaceImpl.h>
#include <minikin/FontFamily.h> #include <minikin/FontFamily.h>
#include "MinikinSkia.h"
#include <memory> #include <memory>

View File

@@ -7,13 +7,13 @@
#include "JNIHelp.h" #include "JNIHelp.h"
#include "GraphicsJNI.h" #include "GraphicsJNI.h"
#include "Canvas.h"
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkDevice.h" #include "SkDevice.h"
#include "SkMath.h" #include "SkMath.h"
#include "SkRegion.h" #include "SkRegion.h"
#include <android_runtime/AndroidRuntime.h> #include <android_runtime/AndroidRuntime.h>
#include <cutils/ashmem.h> #include <cutils/ashmem.h>
#include <hwui/Canvas.h>
#include <Caches.h> #include <Caches.h>
#include <TextureCache.h> #include <TextureCache.h>

View File

@@ -11,8 +11,8 @@
#include "SkPoint.h" #include "SkPoint.h"
#include "SkRect.h" #include "SkRect.h"
#include "SkImageDecoder.h" #include "SkImageDecoder.h"
#include <Canvas.h>
#include <jni.h> #include <jni.h>
#include <hwui/Canvas.h>
class SkBitmapRegionDecoder; class SkBitmapRegionDecoder;
class SkCanvas; class SkCanvas;

View File

@@ -1,7 +1,5 @@
#include "Canvas.h"
#include "CreateJavaOutputStreamAdaptor.h" #include "CreateJavaOutputStreamAdaptor.h"
#include "GraphicsJNI.h" #include "GraphicsJNI.h"
#include "Paint.h"
#include "ScopedLocalRef.h" #include "ScopedLocalRef.h"
#include "SkFrontBufferedStream.h" #include "SkFrontBufferedStream.h"
#include "SkMovie.h" #include "SkMovie.h"
@@ -12,6 +10,8 @@
#include <androidfw/Asset.h> #include <androidfw/Asset.h>
#include <androidfw/ResourceTypes.h> #include <androidfw/ResourceTypes.h>
#include <hwui/Canvas.h>
#include <hwui/Paint.h>
#include <jni.h> #include <jni.h>
#include <netinet/in.h> #include <netinet/in.h>

View File

@@ -19,12 +19,12 @@
#define LOG_NDEBUG 1 #define LOG_NDEBUG 1
#include <androidfw/ResourceTypes.h> #include <androidfw/ResourceTypes.h>
#include <hwui/Canvas.h>
#include <hwui/Paint.h>
#include <utils/Log.h> #include <utils/Log.h>
#include <ResourceCache.h> #include <ResourceCache.h>
#include "Paint.h"
#include "Canvas.h"
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkRegion.h" #include "SkRegion.h"
#include "GraphicsJNI.h" #include "GraphicsJNI.h"

View File

@@ -37,13 +37,13 @@
#include "unicode/ushape.h" #include "unicode/ushape.h"
#include "utils/Blur.h" #include "utils/Blur.h"
#include <hwui/MinikinSkia.h>
#include <hwui/MinikinUtils.h>
#include <hwui/Paint.h>
#include <hwui/TypefaceImpl.h>
#include <minikin/GraphemeBreak.h> #include <minikin/GraphemeBreak.h>
#include <minikin/Measurement.h> #include <minikin/Measurement.h>
#include <unicode/utf16.h> #include <unicode/utf16.h>
#include "MinikinSkia.h"
#include "MinikinUtils.h"
#include "Paint.h"
#include "TypefaceImpl.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>

View File

@@ -14,11 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
#include "Canvas.h"
#include "Picture.h" #include "Picture.h"
#include "SkStream.h" #include "SkStream.h"
#include <memory> #include <memory>
#include <hwui/Canvas.h>
namespace android { namespace android {

View File

@@ -22,10 +22,11 @@
#include "jni.h" #include "jni.h"
#include "GraphicsJNI.h" #include "GraphicsJNI.h"
#include "Paint.h"
#include "SkLayerRasterizer.h" #include "SkLayerRasterizer.h"
#include "core_jni_helpers.h" #include "core_jni_helpers.h"
#include <hwui/Paint.h>
// Rasterizer.java holds a pointer (jlong) to this guy // Rasterizer.java holds a pointer (jlong) to this guy
class NativeRasterizer { class NativeRasterizer {
public: public:

View File

@@ -20,9 +20,9 @@
#include "GraphicsJNI.h" #include "GraphicsJNI.h"
#include "ScopedPrimitiveArray.h" #include "ScopedPrimitiveArray.h"
#include "SkTypeface.h" #include "SkTypeface.h"
#include "TypefaceImpl.h"
#include <android_runtime/android_util_AssetManager.h> #include <android_runtime/android_util_AssetManager.h>
#include <androidfw/AssetManager.h> #include <androidfw/AssetManager.h>
#include <hwui/TypefaceImpl.h>
using namespace android; using namespace android;
@@ -58,7 +58,12 @@ static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) {
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) { static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) {
ScopedLongArrayRO families(env, familyArray); ScopedLongArrayRO families(env, familyArray);
return reinterpret_cast<jlong>(TypefaceImpl_createFromFamilies(families.get(), families.size())); std::vector<FontFamily*> familyVec;
for (size_t i = 0; i < families.size(); i++) {
FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
familyVec.push_back(family);
}
return reinterpret_cast<jlong>(TypefaceImpl_createFromFamilies(familyVec));
} }
static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) { static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {

View File

@@ -19,7 +19,6 @@
#include "core_jni_helpers.h" #include "core_jni_helpers.h"
#include <vector> #include <vector>
#include "Canvas.h"
#include "CreateJavaOutputStreamAdaptor.h" #include "CreateJavaOutputStreamAdaptor.h"
#include "SkDocument.h" #include "SkDocument.h"
@@ -28,6 +27,8 @@
#include "SkStream.h" #include "SkStream.h"
#include "SkRect.h" #include "SkRect.h"
#include <hwui/Canvas.h>
namespace android { namespace android {
struct PageRecord { struct PageRecord {

View File

@@ -19,15 +19,14 @@
#include "core_jni_helpers.h" #include "core_jni_helpers.h"
#include <androidfw/ResourceTypes.h> #include <androidfw/ResourceTypes.h>
#include <Canvas.h> #include <hwui/Canvas.h>
#include <hwui/Paint.h>
#include <hwui/TypefaceImpl.h>
#include <minikin/Layout.h>
#include "Bitmap.h" #include "Bitmap.h"
#include "SkDrawFilter.h" #include "SkDrawFilter.h"
#include "SkGraphics.h" #include "SkGraphics.h"
#include "Paint.h"
#include "TypefaceImpl.h"
#include "MinikinUtils.h"
namespace android { namespace android {
@@ -475,111 +474,13 @@ static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbi
vertA.ptr(), colorA.ptr(), paint); vertA.ptr(), colorA.ptr(), paint);
} }
static void simplifyPaint(int color, SkPaint* paint) {
paint->setColor(color);
paint->setShader(nullptr);
paint->setColorFilter(nullptr);
paint->setLooper(nullptr);
paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
paint->setStrokeJoin(SkPaint::kRound_Join);
paint->setLooper(nullptr);
}
class DrawTextFunctor {
public:
DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
const SkPaint& paint, float x, float y, MinikinRect& bounds,
float totalAdvance)
: layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
void operator()(size_t start, size_t end) {
if (canvas->drawTextAbsolutePos()) {
for (size_t i = start; i < end; i++) {
glyphs[i] = layout.getGlyphId(i);
pos[2 * i] = x + layout.getX(i);
pos[2 * i + 1] = y + layout.getY(i);
}
} else {
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);
}
}
size_t glyphCount = end - start;
if (CC_UNLIKELY(canvas->isHighContrastText() && paint.getAlpha() != 0)) {
// high contrast draw path
int color = paint.getColor();
int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
bool darken = channelSum < (128 * 3);
// outline
SkPaint outlinePaint(paint);
simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
// inner
SkPaint innerPaint(paint);
simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
innerPaint.setStyle(SkPaint::kFill_Style);
canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
} else {
// standard draw path
canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
totalAdvance);
}
}
private:
const Layout& layout;
Canvas* canvas;
uint16_t* glyphs;
float* pos;
const SkPaint& paint;
float x;
float y;
MinikinRect& bounds;
float totalAdvance;
};
void drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
// minikin may modify the original paint
Paint paint(origPaint);
Layout layout;
MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
size_t nGlyphs = layout.nGlyphs();
std::unique_ptr<uint16_t[]> glyphs(new uint16_t[nGlyphs]);
std::unique_ptr<float[]> pos(new float[nGlyphs * 2]);
x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
MinikinRect bounds;
layout.getBounds(&bounds);
if (!canvas->drawTextAbsolutePos()) {
bounds.offset(x, y);
}
DrawTextFunctor f(layout, canvas, glyphs.get(), pos.get(),
paint, x, y, bounds, layout.getAdvance());
MinikinUtils::forFontRun(layout, &paint, f);
}
static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
jint index, jint count, jfloat x, jfloat y, jint bidiFlags, jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
jlong paintHandle, jlong typefaceHandle) { jlong paintHandle, jlong typefaceHandle) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle); Paint* paint = reinterpret_cast<Paint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
jchar* jchars = env->GetCharArrayElements(text, NULL); jchar* jchars = env->GetCharArrayElements(text, NULL);
drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y, get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y,
bidiFlags, *paint, typeface); bidiFlags, *paint, typeface);
env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
} }
@@ -591,7 +492,7 @@ static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring tex
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const int count = end - start; const int count = end - start;
const jchar* jchars = env->GetStringChars(text, NULL); const jchar* jchars = env->GetStringChars(text, NULL);
drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y, get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y,
bidiFlags, *paint, typeface); bidiFlags, *paint, typeface);
env->ReleaseStringChars(text, jchars); env->ReleaseStringChars(text, jchars);
} }
@@ -604,7 +505,7 @@ static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArra
const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
jchar* jchars = env->GetCharArrayElements(text, NULL); jchar* jchars = env->GetCharArrayElements(text, NULL);
drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count, get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count,
contextCount, x, y, bidiFlags, *paint, typeface); contextCount, x, y, bidiFlags, *paint, typeface);
env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
} }
@@ -620,53 +521,11 @@ static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstr
jint count = end - start; jint count = end - start;
jint contextCount = contextEnd - contextStart; jint contextCount = contextEnd - contextStart;
const jchar* jchars = env->GetStringChars(text, NULL); const jchar* jchars = env->GetStringChars(text, NULL);
drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count, get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count,
contextCount, x, y, bidiFlags, *paint, typeface); contextCount, x, y, bidiFlags, *paint, typeface);
env->ReleaseStringChars(text, jchars); env->ReleaseStringChars(text, jchars);
} }
class DrawTextOnPathFunctor {
public:
DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
float vOffset, const Paint& paint, const SkPath& path)
: layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
paint(paint), path(path) {
}
void operator()(size_t start, size_t end) {
uint16_t glyphs[1];
for (size_t i = start; i < end; i++) {
glyphs[0] = layout.getGlyphId(i);
float x = hOffset + layout.getX(i);
float y = vOffset + layout.getY(i);
canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
}
}
private:
const Layout& layout;
Canvas* canvas;
float hOffset;
float vOffset;
const Paint& paint;
const SkPath& path;
};
static void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
const SkPath& path, float hOffset, float vOffset,
const Paint& paint, TypefaceImpl* typeface) {
Paint paintCopy(paint);
Layout layout;
MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
// Set align to left for drawing, as we don't want individual
// glyphs centered or right-aligned; the offset above takes
// care of all alignment.
paintCopy.setTextAlign(Paint::kLeft_Align);
DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
MinikinUtils::forFontRun(layout, &paintCopy, f);
}
static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
jint index, jint count, jlong pathHandle, jfloat hOffset, jint index, jint count, jlong pathHandle, jfloat hOffset,
jfloat vOffset, jint bidiFlags, jlong paintHandle, jfloat vOffset, jint bidiFlags, jlong paintHandle,
@@ -677,7 +536,7 @@ static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharA
jchar* jchars = env->GetCharArrayElements(text, NULL); jchar* jchars = env->GetCharArrayElements(text, NULL);
drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path, get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count, bidiFlags, *path,
hOffset, vOffset, *paint, typeface); hOffset, vOffset, *paint, typeface);
env->ReleaseCharArrayElements(text, jchars, 0); env->ReleaseCharArrayElements(text, jchars, 0);
@@ -693,7 +552,7 @@ static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstri
const jchar* jchars = env->GetStringChars(text, NULL); const jchar* jchars = env->GetStringChars(text, NULL);
int count = env->GetStringLength(text); int count = env->GetStringLength(text);
drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path, get_canvas(canvasHandle)->drawTextOnPath(jchars, count, bidiFlags, *path,
hOffset, vOffset, *paint, typeface); hOffset, vOffset, *paint, typeface);
env->ReleaseStringChars(text, jchars); env->ReleaseStringChars(text, jchars);

View File

@@ -19,9 +19,10 @@
#include "core_jni_helpers.h" #include "core_jni_helpers.h"
#include "log/log.h" #include "log/log.h"
#include "Paint.h"
#include "VectorDrawable.h" #include "VectorDrawable.h"
#include <hwui/Paint.h>
namespace android { namespace android {
using namespace uirenderer; using namespace uirenderer;
using namespace uirenderer::VectorDrawable; using namespace uirenderer::VectorDrawable;

View File

@@ -32,10 +32,12 @@
#include "SkPaint.h" #include "SkPaint.h"
#include "SkTypeface.h" #include "SkTypeface.h"
#include "MinikinSkia.h" #include <hwui/MinikinSkia.h>
#include "MinikinUtils.h" #include <hwui/MinikinUtils.h>
#include "Paint.h" #include <hwui/Paint.h>
#include "minikin/LineBreaker.h" #include <minikin/FontCollection.h>
#include <minikin/LineBreaker.h>
#include <minikin/MinikinFont.h>
namespace android { namespace android {

View File

@@ -28,11 +28,11 @@
#include <SkRegion.h> #include <SkRegion.h>
#include <Canvas.h>
#include <Rect.h> #include <Rect.h>
#include <RenderNode.h> #include <RenderNode.h>
#include <CanvasProperty.h> #include <CanvasProperty.h>
#include <Paint.h> #include <hwui/Canvas.h>
#include <hwui/Paint.h>
#include <renderthread/RenderProxy.h> #include <renderthread/RenderProxy.h>
#include "core_jni_helpers.h" #include "core_jni_helpers.h"

View File

@@ -24,8 +24,8 @@
#include <android_runtime/android_graphics_SurfaceTexture.h> #include <android_runtime/android_graphics_SurfaceTexture.h>
#include <gui/GLConsumer.h> #include <gui/GLConsumer.h>
#include <hwui/Paint.h>
#include <Paint.h>
#include <SkBitmap.h> #include <SkBitmap.h>
#include <SkCanvas.h> #include <SkCanvas.h>
#include <SkMatrix.h> #include <SkMatrix.h>

View File

@@ -30,7 +30,7 @@
#include <RenderNode.h> #include <RenderNode.h>
#include <renderthread/CanvasContext.h> #include <renderthread/CanvasContext.h>
#include <TreeInfo.h> #include <TreeInfo.h>
#include <Paint.h> #include <hwui/Paint.h>
#include "core_jni_helpers.h" #include "core_jni_helpers.h"

View File

@@ -12,6 +12,11 @@ HWUI_ENABLE_OPENGL_VALIDATION := true
hwui_src_files := \ hwui_src_files := \
font/CacheTexture.cpp \ font/CacheTexture.cpp \
font/Font.cpp \ font/Font.cpp \
hwui/Canvas.cpp \
hwui/MinikinSkia.cpp \
hwui/MinikinUtils.cpp \
hwui/PaintImpl.cpp \
hwui/TypefaceImpl.cpp \
renderstate/Blend.cpp \ renderstate/Blend.cpp \
renderstate/MeshState.cpp \ renderstate/MeshState.cpp \
renderstate/OffscreenBufferPool.cpp \ renderstate/OffscreenBufferPool.cpp \
@@ -41,7 +46,6 @@ hwui_src_files := \
AnimatorManager.cpp \ AnimatorManager.cpp \
AssetAtlas.cpp \ AssetAtlas.cpp \
Caches.cpp \ Caches.cpp \
Canvas.cpp \
CanvasState.cpp \ CanvasState.cpp \
ClipArea.cpp \ ClipArea.cpp \
DamageAccumulator.cpp \ DamageAccumulator.cpp \
@@ -143,7 +147,9 @@ endef
hwui_c_includes += \ hwui_c_includes += \
external/skia/include/private \ external/skia/include/private \
external/skia/src/core external/skia/src/core \
external/harfbuzz_ng/src \
external/freetype/include
ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT)) ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
hwui_cflags += -DANDROID_ENABLE_RENDERSCRIPT hwui_cflags += -DANDROID_ENABLE_RENDERSCRIPT

View File

@@ -1,66 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Canvas.h"
#include "DisplayListCanvas.h"
#include "RecordingCanvas.h"
#include <SkDrawFilter.h>
namespace android {
Canvas* Canvas::create_recording_canvas(int width, int height) {
#if HWUI_NEW_OPS
return new uirenderer::RecordingCanvas(width, height);
#else
return new uirenderer::DisplayListCanvas(width, height);
#endif
}
void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
uint32_t flags;
SkDrawFilter* drawFilter = getDrawFilter();
if (drawFilter) {
SkPaint paintCopy(paint);
drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
flags = paintCopy.getFlags();
} else {
flags = paint.getFlags();
}
if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
// Same values used by Skia
const float kStdStrikeThru_Offset = (-6.0f / 21.0f);
const float kStdUnderline_Offset = (1.0f / 9.0f);
const float kStdUnderline_Thickness = (1.0f / 18.0f);
SkScalar left = x;
SkScalar right = x + length;
float textSize = paint.getTextSize();
float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
if (flags & SkPaint::kUnderlineText_Flag) {
SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
drawRect(left, top, right, bottom, paint);
}
if (flags & SkPaint::kStrikeThruText_Flag) {
SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
drawRect(left, top, right, bottom, paint);
}
}
}
} // namespace android

View File

@@ -14,8 +14,8 @@
* limitations under the License. * limitations under the License.
*/ */
#include "Canvas.h"
#include "CanvasState.h" #include "CanvasState.h"
#include "hwui/Canvas.h"
#include "utils/MathUtils.h" #include "utils/MathUtils.h"
namespace android { namespace android {

View File

@@ -418,7 +418,7 @@ void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
addDrawOp(new (alloc()) DrawVectorDrawableOp(tree)); addDrawOp(new (alloc()) DrawVectorDrawableOp(tree));
} }
void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count, void DisplayListCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int count,
const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) { const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) {
if (!glyphs || count <= 0) return; if (!glyphs || count <= 0) return;
@@ -429,7 +429,7 @@ void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count,
addDrawOp(op); addDrawOp(op);
} }
void DisplayListCanvas::drawText(const uint16_t* glyphs, const float* positions, void DisplayListCanvas::drawGlyphs(const uint16_t* glyphs, const float* positions,
int count, const SkPaint& paint, float x, float y, int count, const SkPaint& paint, float x, float y,
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
float totalAdvance) { float totalAdvance) {

View File

@@ -17,12 +17,12 @@
#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H #ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H #define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
#include "Canvas.h"
#include "CanvasState.h" #include "CanvasState.h"
#include "DisplayList.h" #include "DisplayList.h"
#include "RenderNode.h" #include "RenderNode.h"
#include "ResourceCache.h" #include "ResourceCache.h"
#include "SkiaCanvasProxy.h" #include "SkiaCanvasProxy.h"
#include "hwui/Canvas.h"
#include "utils/Macros.h" #include "utils/Macros.h"
#include <SkDrawFilter.h> #include <SkDrawFilter.h>
@@ -209,10 +209,10 @@ public:
virtual void drawVectorDrawable(VectorDrawableRoot* tree) override; virtual void drawVectorDrawable(VectorDrawableRoot* tree) override;
// Text // Text
virtual void drawText(const uint16_t* glyphs, const float* positions, int count, virtual void drawGlyphs(const uint16_t* glyphs, const float* positions, int count,
const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop, const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
float boundsRight, float boundsBottom, float totalAdvance) override; float boundsRight, float boundsBottom, float totalAdvance) override;
virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) override; float hOffset, float vOffset, const SkPaint& paint) override;
virtual bool drawTextAbsolutePos() const override { return false; } virtual bool drawTextAbsolutePos() const override { return false; }

View File

@@ -16,11 +16,11 @@
#include "FrameBuilder.h" #include "FrameBuilder.h"
#include "Canvas.h"
#include "LayerUpdateQueue.h" #include "LayerUpdateQueue.h"
#include "RenderNode.h" #include "RenderNode.h"
#include "VectorDrawable.h" #include "VectorDrawable.h"
#include "renderstate/OffscreenBufferPool.h" #include "renderstate/OffscreenBufferPool.h"
#include "hwui/Canvas.h"
#include "utils/FatVector.h" #include "utils/FatVector.h"
#include "utils/PaintUtils.h" #include "utils/PaintUtils.h"
#include "utils/TraceUtils.h" #include "utils/TraceUtils.h"

View File

@@ -17,7 +17,6 @@
#include <GpuMemoryTracker.h> #include <GpuMemoryTracker.h>
#include "OpenGLRenderer.h" #include "OpenGLRenderer.h"
#include "Canvas.h"
#include "DeferredDisplayList.h" #include "DeferredDisplayList.h"
#include "GammaFontRenderer.h" #include "GammaFontRenderer.h"
#include "Glop.h" #include "Glop.h"
@@ -32,6 +31,7 @@
#include "SkiaShader.h" #include "SkiaShader.h"
#include "Vector.h" #include "Vector.h"
#include "VertexBuffer.h" #include "VertexBuffer.h"
#include "hwui/Canvas.h"
#include "utils/GLUtils.h" #include "utils/GLUtils.h"
#include "utils/PaintUtils.h" #include "utils/PaintUtils.h"
#include "utils/TraceUtils.h" #include "utils/TraceUtils.h"

View File

@@ -514,7 +514,7 @@ void RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_p
} }
// Text // Text
void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int glyphCount, void RecordingCanvas::drawGlyphs(const uint16_t* glyphs, const float* positions, int glyphCount,
const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop, const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
float boundsRight, float boundsBottom, float totalAdvance) { float boundsRight, float boundsBottom, float totalAdvance) {
if (!glyphs || !positions || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return; if (!glyphs || !positions || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
@@ -530,7 +530,7 @@ void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, i
drawTextDecorations(x, y, totalAdvance, paint); drawTextDecorations(x, y, totalAdvance, paint);
} }
void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path, void RecordingCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) { float hOffset, float vOffset, const SkPaint& paint) {
if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return; if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
glyphs = refBuffer<glyph_t>(glyphs, glyphCount); glyphs = refBuffer<glyph_t>(glyphs, glyphCount);

View File

@@ -17,12 +17,12 @@
#ifndef ANDROID_HWUI_RECORDING_CANVAS_H #ifndef ANDROID_HWUI_RECORDING_CANVAS_H
#define ANDROID_HWUI_RECORDING_CANVAS_H #define ANDROID_HWUI_RECORDING_CANVAS_H
#include "Canvas.h"
#include "CanvasState.h" #include "CanvasState.h"
#include "DisplayList.h" #include "DisplayList.h"
#include "ResourceCache.h" #include "ResourceCache.h"
#include "SkiaCanvasProxy.h" #include "SkiaCanvasProxy.h"
#include "Snapshot.h" #include "Snapshot.h"
#include "hwui/Canvas.h"
#include "utils/LinearAllocator.h" #include "utils/LinearAllocator.h"
#include "utils/Macros.h" #include "utils/Macros.h"
#include "utils/NinePatch.h" #include "utils/NinePatch.h"
@@ -191,10 +191,10 @@ public:
const SkPaint* paint) override; const SkPaint* paint) override;
// Text // Text
virtual void drawText(const uint16_t* glyphs, const float* positions, int glyphCount, virtual void drawGlyphs(const uint16_t* glyphs, const float* positions, int glyphCount,
const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop, const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
float boundsRight, float boundsBottom, float totalAdvance) override; float boundsRight, float boundsBottom, float totalAdvance) override;
virtual void drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path, virtual void drawGlyphsOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) override; float hOffset, float vOffset, const SkPaint& paint) override;
virtual bool drawTextAbsolutePos() const override { return false; } virtual bool drawTextAbsolutePos() const override { return false; }

View File

@@ -23,9 +23,9 @@
#include <SkPath.h> #include <SkPath.h>
#include <SkPathOps.h> #include <SkPathOps.h>
#include "Canvas.h"
#include "Matrix.h" #include "Matrix.h"
#include "OpenGLRenderer.h" #include "OpenGLRenderer.h"
#include "hwui/Canvas.h"
#include "utils/MathUtils.h" #include "utils/MathUtils.h"
namespace android { namespace android {

View File

@@ -14,10 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
#include "Canvas.h"
#include "CanvasProperty.h" #include "CanvasProperty.h"
#include "Layer.h" #include "Layer.h"
#include "RenderNode.h" #include "RenderNode.h"
#include "hwui/Canvas.h"
#include <SkCanvas.h> #include <SkCanvas.h>
#include <SkClipStack.h> #include <SkClipStack.h>
@@ -147,11 +147,11 @@ public:
float dstLeft, float dstTop, float dstRight, float dstBottom, float dstLeft, float dstTop, float dstRight, float dstBottom,
const SkPaint* paint) override; const SkPaint* paint) override;
virtual void drawText(const uint16_t* text, const float* positions, int count, virtual void drawGlyphs(const uint16_t* text, const float* positions, int count,
const SkPaint& paint, float x, float y, const SkPaint& paint, float x, float y,
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
float totalAdvance) override; float totalAdvance) override;
virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) override; float hOffset, float vOffset, const SkPaint& paint) override;
virtual bool drawTextAbsolutePos() const override { return true; } virtual bool drawTextAbsolutePos() const override { return true; }
@@ -757,7 +757,7 @@ void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
// Canvas draw operations: Text // Canvas draw operations: Text
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void SkiaCanvas::drawText(const uint16_t* text, const float* positions, int count, void SkiaCanvas::drawGlyphs(const uint16_t* text, const float* positions, int count,
const SkPaint& paint, float x, float y, const SkPaint& paint, float x, float y,
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
float totalAdvance) { float totalAdvance) {
@@ -772,7 +772,7 @@ void SkiaCanvas::drawText(const uint16_t* text, const float* positions, int coun
drawTextDecorations(x, y, totalAdvance, paint); drawTextDecorations(x, y, totalAdvance, paint);
} }
void SkiaCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, void SkiaCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) { float hOffset, float vOffset, const SkPaint& paint) {
mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint); mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint);
} }

View File

@@ -290,7 +290,7 @@ void SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x
} }
static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats"); static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
mCanvas->drawText(glyphs.glyphIDs, &pointStorage[0].fX, glyphs.count, glyphs.paint, mCanvas->drawGlyphs(glyphs.glyphIDs, &pointStorage[0].fX, glyphs.count, glyphs.paint,
x, y, bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0); x, y, bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
} }
@@ -326,7 +326,7 @@ void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const S
bounds.offset(x, y); bounds.offset(x, y);
static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats"); static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
mCanvas->drawText(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y, mCanvas->drawGlyphs(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y,
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0); bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
} }
@@ -344,7 +344,7 @@ void SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, cons
const SkMatrix* matrix, const SkPaint& origPaint) { const SkMatrix* matrix, const SkPaint& origPaint) {
// convert to glyphIDs if necessary // convert to glyphIDs if necessary
GlyphIDConverter glyphs(text, byteLength, origPaint); GlyphIDConverter glyphs(text, byteLength, origPaint);
mCanvas->drawTextOnPath(glyphs.glyphIDs, glyphs.count, path, 0, 0, glyphs.paint); mCanvas->drawGlyphsOnPath(glyphs.glyphIDs, glyphs.count, path, 0, 0, glyphs.paint);
} }
void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,

View File

@@ -20,7 +20,7 @@
#include <cutils/compiler.h> #include <cutils/compiler.h>
#include <SkCanvas.h> #include <SkCanvas.h>
#include "Canvas.h" #include "hwui/Canvas.h"
namespace android { namespace android {
namespace uirenderer { namespace uirenderer {

View File

@@ -16,7 +16,7 @@
#include "Snapshot.h" #include "Snapshot.h"
#include "Canvas.h" #include "hwui/Canvas.h"
namespace android { namespace android {
namespace uirenderer { namespace uirenderer {

View File

@@ -17,7 +17,7 @@
#ifndef ANDROID_HWUI_VPATH_H #ifndef ANDROID_HWUI_VPATH_H
#define ANDROID_HWUI_VPATH_H #define ANDROID_HWUI_VPATH_H
#include "Canvas.h" #include "hwui/Canvas.h"
#include <SkBitmap.h> #include <SkBitmap.h>
#include <SkColor.h> #include <SkColor.h>

220
libs/hwui/hwui/Canvas.cpp Normal file
View File

@@ -0,0 +1,220 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Canvas.h"
#include "DisplayListCanvas.h"
#include "RecordingCanvas.h"
#include "MinikinUtils.h"
#include "Paint.h"
#include "TypefaceImpl.h"
#include <SkDrawFilter.h>
namespace android {
Canvas* Canvas::create_recording_canvas(int width, int height) {
#if HWUI_NEW_OPS
return new uirenderer::RecordingCanvas(width, height);
#else
return new uirenderer::DisplayListCanvas(width, height);
#endif
}
void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
uint32_t flags;
SkDrawFilter* drawFilter = getDrawFilter();
if (drawFilter) {
SkPaint paintCopy(paint);
drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
flags = paintCopy.getFlags();
} else {
flags = paint.getFlags();
}
if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
// Same values used by Skia
const float kStdStrikeThru_Offset = (-6.0f / 21.0f);
const float kStdUnderline_Offset = (1.0f / 9.0f);
const float kStdUnderline_Thickness = (1.0f / 18.0f);
SkScalar left = x;
SkScalar right = x + length;
float textSize = paint.getTextSize();
float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
if (flags & SkPaint::kUnderlineText_Flag) {
SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
drawRect(left, top, right, bottom, paint);
}
if (flags & SkPaint::kStrikeThruText_Flag) {
SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
drawRect(left, top, right, bottom, paint);
}
}
}
static void simplifyPaint(int color, SkPaint* paint) {
paint->setColor(color);
paint->setShader(nullptr);
paint->setColorFilter(nullptr);
paint->setLooper(nullptr);
paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
paint->setStrokeJoin(SkPaint::kRound_Join);
paint->setLooper(nullptr);
}
class DrawTextFunctor {
public:
DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
const SkPaint& paint, float x, float y, MinikinRect& bounds, float totalAdvance)
: layout(layout)
, canvas(canvas)
, glyphs(glyphs)
, pos(pos)
, paint(paint)
, x(x)
, y(y)
, bounds(bounds)
, totalAdvance(totalAdvance) {
}
void operator()(size_t start, size_t end) {
if (canvas->drawTextAbsolutePos()) {
for (size_t i = start; i < end; i++) {
glyphs[i] = layout.getGlyphId(i);
pos[2 * i] = x + layout.getX(i);
pos[2 * i + 1] = y + layout.getY(i);
}
} else {
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);
}
}
size_t glyphCount = end - start;
if (CC_UNLIKELY(canvas->isHighContrastText() && paint.getAlpha() != 0)) {
// high contrast draw path
int color = paint.getColor();
int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
bool darken = channelSum < (128 * 3);
// outline
SkPaint outlinePaint(paint);
simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
canvas->drawGlyphs(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
// inner
SkPaint innerPaint(paint);
simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
innerPaint.setStyle(SkPaint::kFill_Style);
canvas->drawGlyphs(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
} else {
// standard draw path
canvas->drawGlyphs(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
}
}
private:
const Layout& layout;
Canvas* canvas;
uint16_t* glyphs;
float* pos;
const SkPaint& paint;
float x;
float y;
MinikinRect& bounds;
float totalAdvance;
};
void Canvas::drawText(const uint16_t* text, int start, int count, int contextCount,
float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
// minikin may modify the original paint
Paint paint(origPaint);
Layout layout;
MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
size_t nGlyphs = layout.nGlyphs();
std::unique_ptr<uint16_t[]> glyphs(new uint16_t[nGlyphs]);
std::unique_ptr<float[]> pos(new float[nGlyphs * 2]);
x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
MinikinRect bounds;
layout.getBounds(&bounds);
if (!drawTextAbsolutePos()) {
bounds.offset(x, y);
}
DrawTextFunctor f(layout, this, glyphs.get(), pos.get(),
paint, x, y, bounds, layout.getAdvance());
MinikinUtils::forFontRun(layout, &paint, f);
}
class DrawTextOnPathFunctor {
public:
DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
float vOffset, const Paint& paint, const SkPath& path)
: layout(layout)
, canvas(canvas)
, hOffset(hOffset)
, vOffset(vOffset)
, paint(paint)
, path(path) {
}
void operator()(size_t start, size_t end) {
uint16_t glyphs[1];
for (size_t i = start; i < end; i++) {
glyphs[0] = layout.getGlyphId(i);
float x = hOffset + layout.getX(i);
float y = vOffset + layout.getY(i);
canvas->drawGlyphsOnPath(glyphs, 1, path, x, y, paint);
}
}
private:
const Layout& layout;
Canvas* canvas;
float hOffset;
float vOffset;
const Paint& paint;
const SkPath& path;
};
void Canvas::drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
float hOffset, float vOffset, const Paint& paint, TypefaceImpl* typeface) {
Paint paintCopy(paint);
Layout layout;
MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
// Set align to left for drawing, as we don't want individual
// glyphs centered or right-aligned; the offset above takes
// care of all alignment.
paintCopy.setTextAlign(Paint::kLeft_Align);
DrawTextOnPathFunctor f(layout, this, hOffset, vOffset, paintCopy, path);
MinikinUtils::forFontRun(layout, &paintCopy, f);
}
} // namespace android

View File

@@ -59,6 +59,9 @@ class Tree;
}; };
typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
class Paint;
struct TypefaceImpl;
class ANDROID_API Canvas { class ANDROID_API Canvas {
public: public:
virtual ~Canvas() {}; virtual ~Canvas() {};
@@ -207,12 +210,12 @@ public:
* drawText: count is of glyphs * drawText: count is of glyphs
* totalAdvance: used to define width of text decorations (underlines, strikethroughs). * totalAdvance: used to define width of text decorations (underlines, strikethroughs).
*/ */
virtual void drawText(const uint16_t* glyphs, const float* positions, int count, virtual void drawGlyphs(const uint16_t* glyphs, const float* positions, int count,
const SkPaint& paint, float x, float y, const SkPaint& paint, float x, float y,
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom, float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
float totalAdvance) = 0; float totalAdvance) = 0;
/** drawTextOnPath: count is of glyphs */ /** drawTextOnPath: count is of glyphs */
virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) = 0; float hOffset, float vOffset, const SkPaint& paint) = 0;
/** /**
@@ -229,6 +232,16 @@ public:
*/ */
virtual void drawVectorDrawable(VectorDrawableRoot* tree); virtual void drawVectorDrawable(VectorDrawableRoot* tree);
/**
* Converts utf16 text to glyphs, calculating position and boundary,
* and delegating the final draw to virtual drawGlyphs method.
*/
void drawText(const uint16_t* text, int start, int count, int contextCount,
float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface);
void drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
float hOffset, float vOffset, const Paint& paint, TypefaceImpl* typeface);
protected: protected:
void drawTextDecorations(float x, float y, float length, const SkPaint& paint); void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
}; };

View File

@@ -14,14 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
#include <SkTypeface.h>
#include <SkPaint.h>
#define LOG_TAG "Minikin"
#include <cutils/log.h>
#include "MinikinSkia.h" #include "MinikinSkia.h"
#include <SkPaint.h>
#include <SkTypeface.h>
#include <cutils/log.h>
namespace android { namespace android {
MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) : MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) :

View File

@@ -17,11 +17,15 @@
#ifndef _ANDROID_GRAPHICS_MINIKIN_SKIA_H_ #ifndef _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
#define _ANDROID_GRAPHICS_MINIKIN_SKIA_H_ #define _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
#include <cutils/compiler.h>
#include <minikin/MinikinFont.h> #include <minikin/MinikinFont.h>
class SkPaint;
class SkTypeface;
namespace android { namespace android {
class MinikinFontSkia : public MinikinFont { class ANDROID_API MinikinFontSkia : public MinikinFont {
public: public:
// Note: this takes ownership of the reference (will unref on dtor) // Note: this takes ownership of the reference (will unref on dtor)
explicit MinikinFontSkia(SkTypeface *typeface); explicit MinikinFontSkia(SkTypeface *typeface);

View File

@@ -13,16 +13,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "MinikinUtils.h"
#define LOG_TAG "Minikin"
#include <cutils/log.h>
#include <string>
#include "SkPathMeasure.h"
#include "Paint.h" #include "Paint.h"
#include "SkPathMeasure.h"
#include "TypefaceImpl.h" #include "TypefaceImpl.h"
#include "MinikinUtils.h" #include <cutils/log.h>
#include <string>
namespace android { namespace android {

View File

@@ -24,6 +24,7 @@
#ifndef _ANDROID_GRAPHICS_MINIKIN_UTILS_H_ #ifndef _ANDROID_GRAPHICS_MINIKIN_UTILS_H_
#define _ANDROID_GRAPHICS_MINIKIN_UTILS_H_ #define _ANDROID_GRAPHICS_MINIKIN_UTILS_H_
#include <cutils/compiler.h>
#include <minikin/Layout.h> #include <minikin/Layout.h>
#include "Paint.h" #include "Paint.h"
#include "MinikinSkia.h" #include "MinikinSkia.h"
@@ -33,24 +34,24 @@ namespace android {
class MinikinUtils { class MinikinUtils {
public: public:
static FontStyle prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont, ANDROID_API static FontStyle prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
const Paint* paint, TypefaceImpl* typeface); const Paint* paint, TypefaceImpl* typeface);
static void doLayout(Layout* layout, const Paint* paint, int bidiFlags, ANDROID_API static void doLayout(Layout* layout, const Paint* paint, int bidiFlags,
TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count, TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize); size_t bufSize);
static float measureText(const Paint* paint, int bidiFlags, TypefaceImpl* typeface, ANDROID_API static float measureText(const Paint* paint, int bidiFlags, TypefaceImpl* typeface,
const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances); const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances);
static bool hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs); ANDROID_API static bool hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs);
static float xOffsetForTextAlign(Paint* paint, const Layout& layout); ANDROID_API static float xOffsetForTextAlign(Paint* paint, const Layout& layout);
static float hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path); ANDROID_API static float hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path);
// f is a functor of type void f(size_t start, size_t end); // f is a functor of type void f(size_t start, size_t end);
template <typename F> template <typename F>
static void forFontRun(const Layout& layout, Paint* paint, F& f) { ANDROID_API static void forFontRun(const Layout& layout, Paint* paint, F& f) {
float saveSkewX = paint->getTextSkewX(); float saveSkewX = paint->getTextSkewX();
bool savefakeBold = paint->isFakeBoldText(); bool savefakeBold = paint->isFakeBoldText();
MinikinFont* curFont = NULL; MinikinFont* curFont = NULL;

View File

@@ -17,6 +17,8 @@
#ifndef ANDROID_GRAPHICS_PAINT_H_ #ifndef ANDROID_GRAPHICS_PAINT_H_
#define ANDROID_GRAPHICS_PAINT_H_ #define ANDROID_GRAPHICS_PAINT_H_
#include <cutils/compiler.h>
#include <SkPaint.h> #include <SkPaint.h>
#include <string> #include <string>
@@ -24,7 +26,7 @@
namespace android { namespace android {
class Paint : public SkPaint { class ANDROID_API Paint : public SkPaint {
public: public:
Paint(); Paint();
Paint(const Paint& paint); Paint(const Paint& paint);
@@ -45,7 +47,7 @@ public:
return mLetterSpacing; return mLetterSpacing;
} }
void setFontFeatureSettings(const std::string &fontFeatureSettings) { void setFontFeatureSettings(const std::string& fontFeatureSettings) {
mFontFeatureSettings = fontFeatureSettings; mFontFeatureSettings = fontFeatureSettings;
} }

View File

@@ -15,10 +15,6 @@
*/ */
#include "Paint.h" #include "Paint.h"
#include <SkPaint.h>
#define LOG_TAG "Paint"
#include <cutils/log.h>
namespace android { namespace android {

View File

@@ -20,21 +20,16 @@
* being, that choice is hidden under the USE_MINIKIN compile-time flag. * being, that choice is hidden under the USE_MINIKIN compile-time flag.
*/ */
#define LOG_TAG "TypefaceImpl" #include "TypefaceImpl.h"
#include "jni.h" // for jlong, remove when being passed proper type
#include "MinikinSkia.h"
#include "SkTypeface.h" #include "SkTypeface.h"
#include "SkPaint.h"
#include <vector>
#include <minikin/FontCollection.h> #include <minikin/FontCollection.h>
#include <minikin/FontFamily.h> #include <minikin/FontFamily.h>
#include <minikin/Layout.h> #include <minikin/Layout.h>
#include "SkPaint.h" #include <utils/Log.h>
#include "MinikinSkia.h"
#include "TypefaceImpl.h"
#include "Utils.h"
namespace android { namespace android {
@@ -133,15 +128,10 @@ TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) {
return result; return result;
} }
TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) { TypefaceImpl* TypefaceImpl_createFromFamilies(const std::vector<FontFamily*>& families) {
std::vector<FontFamily *>familyVec;
for (size_t i = 0; i < size; i++) {
FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
familyVec.push_back(family);
}
TypefaceImpl* result = new TypefaceImpl; TypefaceImpl* result = new TypefaceImpl;
result->fFontCollection = new FontCollection(familyVec); result->fFontCollection = new FontCollection(families);
if (size == 0) { if (families.empty()) {
ALOGW("createFromFamilies creating empty collection"); ALOGW("createFromFamilies creating empty collection");
result->fSkiaStyle = SkTypeface::kNormal; result->fSkiaStyle = SkTypeface::kNormal;
} else { } else {

View File

@@ -18,15 +18,15 @@
#ifndef _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_ #ifndef _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
#define _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_ #define _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
#include "jni.h" // for jlong, eventually remove
#include "SkTypeface.h" #include "SkTypeface.h"
#include <androidfw/AssetManager.h>
#include <cutils/compiler.h>
#include <minikin/FontCollection.h> #include <minikin/FontCollection.h>
#include <vector>
namespace android { namespace android {
struct TypefaceImpl { struct ANDROID_API TypefaceImpl {
FontCollection *fFontCollection; FontCollection *fFontCollection;
// style used for constructing and querying Typeface objects // style used for constructing and querying Typeface objects
@@ -44,21 +44,19 @@ struct TypefaceImpl {
// is just a pointer to SkTypeface, in the non-USE_MINIKIN case. // is just a pointer to SkTypeface, in the non-USE_MINIKIN case.
// TODO: when #ifdef USE_MINIKIN is removed, move to member functions. // TODO: when #ifdef USE_MINIKIN is removed, move to member functions.
TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src); ANDROID_API TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src);
TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style); ANDROID_API TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style);
TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int baseweight); ANDROID_API TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int baseweight);
// When we remove the USE_MINIKIN ifdef, probably a good idea to move the casting ANDROID_API TypefaceImpl* TypefaceImpl_createFromFamilies(const std::vector<FontFamily*>& families);
// (from jlong to FontFamily*) to the caller in Typeface.cpp.
TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size);
void TypefaceImpl_unref(TypefaceImpl* face); ANDROID_API void TypefaceImpl_unref(TypefaceImpl* face);
int TypefaceImpl_getStyle(TypefaceImpl* face); ANDROID_API int TypefaceImpl_getStyle(TypefaceImpl* face);
void TypefaceImpl_setDefault(TypefaceImpl* face); ANDROID_API void TypefaceImpl_setDefault(TypefaceImpl* face);
} }

View File

@@ -21,8 +21,11 @@ LOCAL_SHARED_LIBRARIES += \
libskia \ libskia \
libui \ libui \
libgui \ libgui \
libprotobuf-cpp-lite libprotobuf-cpp-lite \
libharfbuzz_ng \
libft2 \
libminikin
ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT)) ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
LOCAL_SHARED_LIBRARIES += libRS libRScpp LOCAL_SHARED_LIBRARIES += libRS libRScpp
endif endif

View File

@@ -19,7 +19,6 @@
#include "AnimationContext.h" #include "AnimationContext.h"
#include "Caches.h" #include "Caches.h"
#include "Canvas.h"
#include "DeferredLayerUpdater.h" #include "DeferredLayerUpdater.h"
#include "EglManager.h" #include "EglManager.h"
#include "LayerUpdateQueue.h" #include "LayerUpdateQueue.h"
@@ -27,6 +26,7 @@
#include "OpenGLRenderer.h" #include "OpenGLRenderer.h"
#include "Properties.h" #include "Properties.h"
#include "RenderThread.h" #include "RenderThread.h"
#include "hwui/Canvas.h"
#include "renderstate/RenderState.h" #include "renderstate/RenderState.h"
#include "renderstate/Stencil.h" #include "renderstate/Stencil.h"
#include "protos/hwui.pb.h" #include "protos/hwui.pb.h"

View File

@@ -87,7 +87,7 @@ void TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text,
*outTotalAdvance = totalAdvance; *outTotalAdvance = totalAdvance;
} }
void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text, void TestUtils::drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, float x, float y) { const SkPaint& paint, float x, float y) {
// drawing text requires GlyphID TextEncoding (which JNI layer would have done) // drawing text requires GlyphID TextEncoding (which JNI layer would have done)
LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding, LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding,
@@ -113,11 +113,11 @@ void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
// Force left alignment, since alignment offset is already baked in // Force left alignment, since alignment offset is already baked in
SkPaint alignPaintCopy(paint); SkPaint alignPaintCopy(paint);
alignPaintCopy.setTextAlign(SkPaint::kLeft_Align); alignPaintCopy.setTextAlign(SkPaint::kLeft_Align);
canvas->drawText(glyphs.data(), positions.data(), glyphs.size(), alignPaintCopy, x, y, canvas->drawGlyphs(glyphs.data(), positions.data(), glyphs.size(), alignPaintCopy, x, y,
bounds.left, bounds.top, bounds.right, bounds.bottom, totalAdvance); bounds.left, bounds.top, bounds.right, bounds.bottom, totalAdvance);
} }
void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text, void TestUtils::drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, const SkPath& path) { const SkPaint& paint, const SkPath& path) {
// drawing text requires GlyphID TextEncoding (which JNI layer would have done) // drawing text requires GlyphID TextEncoding (which JNI layer would have done)
LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding, LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding,
@@ -130,7 +130,7 @@ void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
SkUnichar unichar = SkUTF8_NextUnichar(&text); SkUnichar unichar = SkUTF8_NextUnichar(&text);
glyphs.push_back(autoCache.getCache()->unicharToGlyph(unichar)); glyphs.push_back(autoCache.getCache()->unicharToGlyph(unichar));
} }
canvas->drawTextOnPath(glyphs.data(), glyphs.size(), path, 0, 0, paint); canvas->drawGlyphsOnPath(glyphs.data(), glyphs.size(), path, 0, 0, paint);
} }
void TestUtils::TestTask::run() { void TestUtils::TestTask::run() {
@@ -143,5 +143,13 @@ void TestUtils::TestTask::run() {
renderState.onGLContextDestroyed(); renderState.onGLContextDestroyed();
} }
std::unique_ptr<uint16_t[]> TestUtils::utf8ToUtf16(const char* str) {
const size_t strLen = strlen(str);
const ssize_t utf16Len = utf8_to_utf16_length((uint8_t*) str, strLen);
std::unique_ptr<uint16_t[]> dst(new uint16_t[utf16Len + 1]);
utf8_to_utf16((uint8_t*) str, strLen, (char16_t*) dst.get());
return dst;
}
} /* namespace uirenderer */ } /* namespace uirenderer */
} /* namespace android */ } /* namespace android */

View File

@@ -207,12 +207,14 @@ public:
std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions, std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions,
float* outTotalAdvance, Rect* outBounds); float* outTotalAdvance, Rect* outBounds);
static void drawTextToCanvas(TestCanvas* canvas, const char* text, static void drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, float x, float y); const SkPaint& paint, float x, float y);
static void drawTextToCanvas(TestCanvas* canvas, const char* text, static void drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, const SkPath& path); const SkPaint& paint, const SkPath& path);
static std::unique_ptr<uint16_t[]> utf8ToUtf16(const char* str);
private: private:
static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) { static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
node->syncProperties(); node->syncProperties();

View File

@@ -136,9 +136,9 @@ private:
textPaint.setAntiAlias(true); textPaint.setAntiAlias(true);
char buf[256]; char buf[256];
snprintf(buf, sizeof(buf), "This card is #%d", cardId); snprintf(buf, sizeof(buf), "This card is #%d", cardId);
TestUtils::drawTextToCanvas(&canvas, buf, textPaint, cardHeight, dp(25)); TestUtils::drawUtf8ToCanvas(&canvas, buf, textPaint, cardHeight, dp(25));
textPaint.setTextSize(dp(15)); textPaint.setTextSize(dp(15));
TestUtils::drawTextToCanvas(&canvas, "This is some more text on the card", textPaint, TestUtils::drawUtf8ToCanvas(&canvas, "This is some more text on the card", textPaint,
cardHeight, dp(45)); cardHeight, dp(45));
canvas.drawBitmap(createRandomCharIcon(), dp(10), dp(10), nullptr); canvas.drawBitmap(createRandomCharIcon(), dp(10), dp(10), nullptr);

View File

@@ -39,14 +39,14 @@ public:
paint.setColor(Color::Black); paint.setColor(Color::Black);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
TestUtils::drawTextToCanvas(&canvas, "Test string", paint, 400, i * 100); TestUtils::drawUtf8ToCanvas(&canvas, "Test string", paint, 400, i * 100);
} }
SkPath path; SkPath path;
path.addOval(SkRect::MakeLTRB(100, 100, 300, 300)); path.addOval(SkRect::MakeLTRB(100, 100, 300, 300));
paint.setColor(Color::Blue_500); paint.setColor(Color::Blue_500);
TestUtils::drawTextToCanvas(&canvas, "This is a neat circle of text!", paint, path); TestUtils::drawUtf8ToCanvas(&canvas, "This is a neat circle of text!", paint, path);
}); });
canvas.drawRenderNode(card.get()); canvas.drawRenderNode(card.get());
} }

View File

@@ -16,9 +16,9 @@
#include "CanvasState.h" #include "CanvasState.h"
#include "Canvas.h"
#include "Matrix.h" #include "Matrix.h"
#include "Rect.h" #include "Rect.h"
#include "hwui/Canvas.h"
#include "utils/LinearAllocator.h" #include "utils/LinearAllocator.h"
#include <gtest/gtest.h> #include <gtest/gtest.h>

View File

@@ -274,8 +274,8 @@ TEST(FrameBuilder, textMerging) {
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setAntiAlias(true); paint.setAntiAlias(true);
paint.setTextSize(50); paint.setTextSize(50);
TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped
TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
}); });
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
@@ -305,7 +305,7 @@ TEST(FrameBuilder, textStrikethrough) {
textPaint.setStrikeThruText(true); textPaint.setStrikeThruText(true);
textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
for (int i = 0; i < LOOPS; i++) { for (int i = 0; i < LOOPS; i++) {
TestUtils::drawTextToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
} }
}); });
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000, FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000,
@@ -361,7 +361,7 @@ TEST(FrameBuilder, textStyle) {
// They'll get merged, but with // They'll get merged, but with
for (auto style : styles) { for (auto style : styles) {
paint.setStyle(style); paint.setStyle(style);
TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
} }
}); });
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,

View File

@@ -18,6 +18,8 @@
#include <RecordedOp.h> #include <RecordedOp.h>
#include <RecordingCanvas.h> #include <RecordingCanvas.h>
#include <hwui/Paint.h>
#include <minikin/Layout.h>
#include <tests/common/TestUtils.h> #include <tests/common/TestUtils.h>
#include <utils/Color.h> #include <utils/Color.h>
@@ -131,13 +133,13 @@ TEST(RecordingCanvas, drawRoundRect) {
<< "Non-rounded rects should be converted"; << "Non-rounded rects should be converted";
} }
TEST(RecordingCanvas, drawText) { TEST(RecordingCanvas, drawGlyphs) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) { auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
SkPaint paint; SkPaint paint;
paint.setAntiAlias(true); paint.setAntiAlias(true);
paint.setTextSize(20); paint.setTextSize(20);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25); TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
}); });
int count = 0; int count = 0;
@@ -152,7 +154,7 @@ TEST(RecordingCanvas, drawText) {
ASSERT_EQ(1, count); ASSERT_EQ(1, count);
} }
TEST(RecordingCanvas, drawText_strikeThruAndUnderline) { TEST(RecordingCanvas, drawGlyphs_strikeThruAndUnderline) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) { auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
SkPaint paint; SkPaint paint;
paint.setAntiAlias(true); paint.setAntiAlias(true);
@@ -162,7 +164,7 @@ TEST(RecordingCanvas, drawText_strikeThruAndUnderline) {
for (int j = 0; j < 2; j++) { for (int j = 0; j < 2; j++) {
paint.setUnderlineText(i != 0); paint.setUnderlineText(i != 0);
paint.setStrikeThruText(j != 0); paint.setStrikeThruText(j != 0);
TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25); TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
} }
} }
}); });
@@ -184,18 +186,18 @@ TEST(RecordingCanvas, drawText_strikeThruAndUnderline) {
EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough
} }
TEST(RecordingCanvas, drawText_forceAlignLeft) { TEST(RecordingCanvas, drawGlyphs_forceAlignLeft) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) { auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
SkPaint paint; SkPaint paint;
paint.setAntiAlias(true); paint.setAntiAlias(true);
paint.setTextSize(20); paint.setTextSize(20);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setTextAlign(SkPaint::kLeft_Align); paint.setTextAlign(SkPaint::kLeft_Align);
TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25); TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
paint.setTextAlign(SkPaint::kCenter_Align); paint.setTextAlign(SkPaint::kCenter_Align);
TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25); TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
paint.setTextAlign(SkPaint::kRight_Align); paint.setTextAlign(SkPaint::kRight_Align);
TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25); TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
}); });
int count = 0; int count = 0;
@@ -576,7 +578,7 @@ TEST(RecordingCanvas, refPaint) {
canvas.drawRect(0, 0, 200, 10, paint); canvas.drawRect(0, 0, 200, 10, paint);
SkPaint paintCopy(paint); SkPaint paintCopy(paint);
canvas.drawRect(0, 10, 200, 20, paintCopy); canvas.drawRect(0, 10, 200, 20, paintCopy);
TestUtils::drawTextToCanvas(&canvas, "helloworld", paint, 50, 25); TestUtils::drawUtf8ToCanvas(&canvas, "helloworld", paint, 50, 25);
// only here do we use different paint ptr // only here do we use different paint ptr
paint.setColor(SK_ColorRED); paint.setColor(SK_ColorRED);
@@ -597,5 +599,54 @@ TEST(RecordingCanvas, refPaint) {
EXPECT_NE(&paint, ops[3]->paint); EXPECT_NE(&paint, ops[3]->paint);
} }
TEST(RecordingCanvas, drawText) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
Paint paint;
paint.setAntiAlias(true);
paint.setTextSize(20);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
std::unique_ptr<uint16_t[]> dst = TestUtils::utf8ToUtf16("HELLO");
canvas.drawText(dst.get(), 0, 5, 5, 25, 25, kBidi_Force_LTR, paint, NULL);
});
int count = 0;
playbackOps(*dl, [&count](const RecordedOp& op) {
count++;
ASSERT_EQ(RecordedOpId::TextOp, op.opId);
EXPECT_EQ(nullptr, op.localClip);
EXPECT_TRUE(op.localMatrix.isIdentity());
EXPECT_TRUE(op.unmappedBounds.getHeight() >= 10);
EXPECT_TRUE(op.unmappedBounds.getWidth() >= 25);
});
ASSERT_EQ(1, count);
}
TEST(RecordingCanvas, drawTextInHighContrast) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
canvas.setHighContrastText(true);
Paint paint;
paint.setColor(SK_ColorWHITE);
paint.setAntiAlias(true);
paint.setTextSize(20);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
std::unique_ptr<uint16_t[]> dst = TestUtils::utf8ToUtf16("HELLO");
canvas.drawText(dst.get(), 0, 5, 5, 25, 25, kBidi_Force_LTR, paint, NULL);
});
int count = 0;
playbackOps(*dl, [&count](const RecordedOp& op) {
ASSERT_EQ(RecordedOpId::TextOp, op.opId);
if (count++ == 0) {
EXPECT_EQ(SK_ColorBLACK, op.paint->getColor());
EXPECT_EQ(SkPaint::kStrokeAndFill_Style, op.paint->getStyle());
} else {
EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
EXPECT_EQ(SkPaint::kFill_Style, op.paint->getStyle());
}
});
ASSERT_EQ(2, count);
}
} // namespace uirenderer } // namespace uirenderer
} // namespace android } // namespace android