Merge "Add support for partial invalidates in WebView Bug #3461349" into honeycomb-mr1

This commit is contained in:
Romain Guy
2011-03-07 22:40:27 -08:00
committed by Android (Google) Code Review
16 changed files with 98 additions and 281 deletions

View File

@@ -245,11 +245,12 @@ class GLES20Canvas extends HardwareCanvas {
private static native void nDestroyDisplayList(int displayList);
@Override
public boolean drawDisplayList(DisplayList displayList) {
return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
public boolean drawDisplayList(DisplayList displayList, Rect dirty) {
return nDrawDisplayList(mRenderer,
((GLES20DisplayList) displayList).mNativeDisplayList, dirty);
}
private static native boolean nDrawDisplayList(int renderer, int displayList);
private static native boolean nDrawDisplayList(int renderer, int displayList, Rect dirty);
///////////////////////////////////////////////////////////////////////////
// Hardware layer

View File

@@ -53,8 +53,13 @@ public abstract class HardwareCanvas extends Canvas {
* Draws the specified display list onto this canvas.
*
* @param displayList The display list to replay.
* @param dirty The dirty region to redraw in the next pass, matters only
* if this method returns true, can be null.
*
* @return True if the content of the display list requires another
* drawing pass (invalidate()), false otherwise
*/
abstract boolean drawDisplayList(DisplayList displayList);
abstract boolean drawDisplayList(DisplayList displayList, Rect dirty);
/**
* Draws the specified layer onto this canvas.

View File

@@ -269,7 +269,7 @@ public abstract class HardwareRenderer {
static EGLDisplay sEglDisplay;
static EGLConfig sEglConfig;
private static Thread sEglThread;
private static Thread sEglThread;
EGLSurface mEglSurface;
@@ -284,6 +284,8 @@ public abstract class HardwareRenderer {
final boolean mTranslucent;
private boolean mDestroyed;
private final Rect mRedrawClip = new Rect();
GlRenderer(int glVersion, boolean translucent) {
mGlVersion = glVersion;
@@ -606,8 +608,13 @@ public abstract class HardwareRenderer {
DisplayList displayList = view.getDisplayList();
if (displayList != null) {
if (canvas.drawDisplayList(displayList)) {
view.invalidate();
if (canvas.drawDisplayList(displayList, mRedrawClip)) {
if (mRedrawClip.isEmpty()) {
view.invalidate();
} else {
view.getParent().invalidateChild(view, mRedrawClip);
}
mRedrawClip.setEmpty();
}
} else {
// Shouldn't reach here
@@ -646,8 +653,8 @@ public abstract class HardwareRenderer {
private int checkCurrent() {
// TODO: Don't check the current context when we have one per UI thread
// TODO: Use a threadlocal flag to know whether the surface has changed
if (sEgl.eglGetCurrentContext() != sEglContext ||
sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW) != mEglSurface) {
if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
fallback(true);
Log.e(LOG_TAG, "eglMakeCurrent failed " +

View File

@@ -2585,7 +2585,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
} else {
child.mPrivateFlags &= ~DIRTY_MASK;
((HardwareCanvas) canvas).drawDisplayList(displayList);
((HardwareCanvas) canvas).drawDisplayList(displayList, null);
}
}
} else if (cache != null) {

View File

@@ -351,7 +351,8 @@ public class WebView extends AbsoluteLayout
private ZoomManager mZoomManager;
private Rect mGLRectViewport = new Rect();
private final Rect mGLRectViewport = new Rect();
private final Rect mViewRectViewport = new Rect();
private boolean mGLViewportEmpty = false;
/**
@@ -4152,7 +4153,7 @@ public class WebView extends AbsoluteLayout
if (canvas.isHardwareAccelerated()) {
int functor = nativeGetDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
getScale(), extras);
mGLViewportEmpty ? null : mViewRectViewport, getScale(), extras);
((HardwareCanvas) canvas).callDrawGLFunction(functor);
} else {
DrawFilter df = null;
@@ -5258,6 +5259,7 @@ public class WebView extends AbsoluteLayout
// Then need to invert the Y axis, just for GL
View rootView = getRootView();
int rootViewHeight = rootView.getHeight();
mViewRectViewport.set(mGLRectViewport);
int savedWebViewBottom = mGLRectViewport.bottom;
mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeight();
mGLRectViewport.top = rootViewHeight - savedWebViewBottom;
@@ -5265,7 +5267,8 @@ public class WebView extends AbsoluteLayout
} else {
mGLViewportEmpty = true;
}
nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport);
nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
mGLViewportEmpty ? null : mViewRectViewport);
}
/**
@@ -8531,8 +8534,9 @@ public class WebView extends AbsoluteLayout
boolean splitIfNeeded);
private native void nativeDumpDisplayTree(String urlOrNull);
private native boolean nativeEvaluateLayersAnimations();
private native int nativeGetDrawGLFunction(Rect rect, float scale, int extras);
private native void nativeUpdateDrawGLFunction(Rect rect);
private native int nativeGetDrawGLFunction(Rect rect, Rect viewRect,
float scale, int extras);
private native void nativeUpdateDrawGLFunction(Rect rect, Rect viewRect);
private native boolean nativeDrawGL(Rect rect, float scale, int extras);
private native void nativeExtendSelection(int x, int y);
private native int nativeFindAll(String findLower, String findUpper,

View File

@@ -35,7 +35,6 @@
#include <DisplayListRenderer.h>
#include <LayerRenderer.h>
#include <OpenGLDebugRenderer.h>
#include <OpenGLRenderer.h>
#include <SkiaShader.h>
#include <SkiaColorFilter.h>
@@ -60,7 +59,6 @@ using namespace uirenderer;
// Debug
#define DEBUG_RENDERER 0
#define PROFILE_RENDERER 0
// Debug
#if DEBUG_RENDERER
@@ -99,11 +97,7 @@ static jboolean android_view_GLES20Canvas_preserveBackBuffer(JNIEnv* env, jobjec
static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
RENDERER_LOGD("Create OpenGLRenderer");
#if PROFILE_RENDERER
return new OpenGLDebugRenderer;
#else
return new OpenGLRenderer;
#endif
}
static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
@@ -139,7 +133,8 @@ static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
static bool android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, Functor *functor) {
return renderer->callDrawGLFunction(functor);
android::uirenderer::Rect dirty;
return renderer->callDrawGLFunction(functor, dirty);
}
// ----------------------------------------------------------------------------
@@ -503,8 +498,14 @@ static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
}
static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList) {
return renderer->drawDisplayList(displayList);
jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList, jobject dirty) {
android::uirenderer::Rect bounds;
bool redraw = renderer->drawDisplayList(displayList, bounds);
if (redraw && dirty != NULL) {
env->CallVoidMethod(dirty, gRectClassInfo.set,
int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
}
return redraw;
}
// ----------------------------------------------------------------------------
@@ -663,7 +664,8 @@ static JNINativeMethod gMethods[] = {
{ "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList },
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
{ "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer },
{ "nDrawDisplayList", "(II)Z", (void*) android_view_GLES20Canvas_drawDisplayList },
{ "nDrawDisplayList", "(IILandroid/graphics/Rect;)Z",
(void*) android_view_GLES20Canvas_drawDisplayList },
{ "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt },
{ "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume },

View File

@@ -26,6 +26,7 @@ public:
Functor() {}
virtual ~Functor() {}
virtual status_t operator ()() { return true; }
virtual status_t operator ()(float* data, uint32_t len) { return true; }
};
}; // namespace android

View File

@@ -15,7 +15,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
LayerCache.cpp \
LayerRenderer.cpp \
Matrix.cpp \
OpenGLDebugRenderer.cpp \
OpenGLRenderer.cpp \
Patch.cpp \
PatchCache.cpp \

View File

@@ -166,7 +166,7 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
void DisplayList::init() {
}
bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) {
bool needsInvalidate = false;
TextContainer text;
mReader.rewind();
@@ -189,7 +189,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
case DrawGLFunction: {
Functor *functor = (Functor *) getInt();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
needsInvalidate |= renderer.callDrawGLFunction(functor);
needsInvalidate |= renderer.callDrawGLFunction(functor, dirty);
}
break;
case Save: {
@@ -287,7 +287,7 @@ bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
DisplayList* displayList = getDisplayList();
DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op],
displayList, level + 1);
needsInvalidate |= renderer.drawDisplayList(displayList, level + 1);
needsInvalidate |= renderer.drawDisplayList(displayList, dirty, level + 1);
}
break;
case DrawLayer: {
@@ -589,7 +589,8 @@ void DisplayListRenderer::interrupt() {
void DisplayListRenderer::resume() {
}
bool DisplayListRenderer::callDrawGLFunction(Functor *functor) {
bool DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
// Ignore dirty during recording, it matters only when we replay
addOp(DisplayList::DrawGLFunction);
addInt((int) functor);
return false; // No invalidate needed at record-time
@@ -673,7 +674,9 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot
return OpenGLRenderer::clipRect(left, top, right, bottom, op);
}
bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
// dirty is an out parameter and should not be recorded,
// it matters only when replaying the display list
addOp(DisplayList::DrawDisplayList);
addDisplayList(displayList);
return false;

View File

@@ -103,7 +103,7 @@ public:
void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
bool replay(OpenGLRenderer& renderer, uint32_t level = 0);
bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
private:
void init();
@@ -214,7 +214,7 @@ public:
void prepareDirty(float left, float top, float right, float bottom, bool opaque);
void finish();
bool callDrawGLFunction(Functor *functor);
bool callDrawGLFunction(Functor *functor, Rect& dirty);
void interrupt();
void resume();
@@ -238,7 +238,7 @@ public:
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);

View File

@@ -1,156 +0,0 @@
/*
* Copyright (C) 2010 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.
*/
#define LOG_TAG "OpenGLRenderer"
#include <utils/StopWatch.h>
#include "OpenGLDebugRenderer.h"
namespace android {
namespace uirenderer {
void OpenGLDebugRenderer::prepareDirty(float left, float top,
float right, float bottom, bool opaque) {
mPrimitivesCount = 0;
LOGD("========= Frame start =========");
OpenGLRenderer::prepareDirty(left, top, right, bottom, opaque);
}
void OpenGLDebugRenderer::finish() {
LOGD("========= Frame end =========");
LOGD("Primitives draw count = %d", mPrimitivesCount);
OpenGLRenderer::finish();
}
void OpenGLDebugRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
mPrimitivesCount++;
StopWatch w("composeLayer");
return OpenGLRenderer::composeLayer(current, previous);
}
int OpenGLDebugRenderer::saveLayer(float left, float top, float right, float bottom,
SkPaint* p, int flags) {
mPrimitivesCount++;
StopWatch w("saveLayer");
return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
}
bool OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
mPrimitivesCount++;
StopWatch w("drawDisplayList");
return OpenGLRenderer::drawDisplayList(displayList);
}
void OpenGLDebugRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawLayer");
OpenGLRenderer::drawLayer(layer, x, y, paint);
}
void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawBitmap");
OpenGLRenderer::drawBitmap(bitmap, left, top, paint);
}
void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawBitmapMatrix");
OpenGLRenderer::drawBitmap(bitmap, matrix, paint);
}
void OpenGLDebugRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawBitmapRect");
OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, paint);
}
void OpenGLDebugRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
float left, float top, float right, float bottom, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawPatch");
OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, colors, width, height, numColors,
left, top, right, bottom, paint);
}
void OpenGLDebugRenderer::drawColor(int color, SkXfermode::Mode mode) {
mPrimitivesCount++;
StopWatch w("drawColor");
OpenGLRenderer::drawColor(color, mode);
}
void OpenGLDebugRenderer::drawRect(float left, float top, float right, float bottom,
SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawRect");
OpenGLRenderer::drawRect(left, top, right, bottom, paint);
}
void OpenGLDebugRenderer::drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawRoundRect");
OpenGLRenderer::drawRoundRect(left, top, right, bottom, rx, ry, paint);
}
void OpenGLDebugRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawCircle");
OpenGLRenderer::drawCircle(x, y, radius, paint);
}
void OpenGLDebugRenderer::drawOval(float left, float top, float right, float bottom,
SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawOval");
OpenGLRenderer::drawOval(left, top, right, bottom, paint);
}
void OpenGLDebugRenderer::drawArc(float left, float top, float right, float bottom,
float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawArc");
OpenGLRenderer::drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
}
void OpenGLDebugRenderer::drawPath(SkPath* path, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawPath");
OpenGLRenderer::drawPath(path, paint);
}
void OpenGLDebugRenderer::drawLines(float* points, int count, SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawLines");
OpenGLRenderer::drawLines(points, count, paint);
}
void OpenGLDebugRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
SkPaint* paint) {
mPrimitivesCount++;
StopWatch w("drawText");
OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint);
}
}; // namespace uirenderer
}; // namespace android

View File

@@ -1,77 +0,0 @@
/*
* Copyright (C) 2010 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.
*/
#ifndef ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
#define ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H
#include "OpenGLRenderer.h"
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Renderer
///////////////////////////////////////////////////////////////////////////////
class OpenGLDebugRenderer: public OpenGLRenderer {
public:
OpenGLDebugRenderer(): mPrimitivesCount(0) {
}
~OpenGLDebugRenderer() {
}
void prepareDirty(float left, float top, float right, float bottom, bool opaque);
void finish();
int saveLayer(float left, float top, float right, float bottom,
SkPaint* p, int flags);
bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, SkPaint* paint);
void drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
float left, float top, float right, float bottom, SkPaint* paint);
void drawColor(int color, SkXfermode::Mode mode);
void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
void drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, SkPaint* paint);
void drawCircle(float x, float y, float radius, SkPaint* paint);
void drawOval(float left, float top, float right, float bottom, SkPaint* paint);
void drawArc(float left, float top, float right, float bottom,
float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
void drawPath(SkPath* path, SkPaint* paint);
void drawLines(float* points, int count, SkPaint* paint);
void drawText(const char* text, int bytesCount, int count, float x, float y,
SkPaint* paint);
protected:
void composeLayer(sp<Snapshot> current, sp<Snapshot> previous);
private:
uint32_t mPrimitivesCount;
}; // class OpenGLDebugRenderer
}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_HWUI_OPENGL_DEBUG_RENDERER_H

View File

@@ -210,7 +210,7 @@ void OpenGLRenderer::resume() {
glBlendEquation(GL_FUNC_ADD);
}
bool OpenGLRenderer::callDrawGLFunction(Functor *functor) {
bool OpenGLRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
interrupt();
if (mDirtyClip) {
setScissorFromClip();
@@ -226,9 +226,16 @@ bool OpenGLRenderer::callDrawGLFunction(Functor *functor) {
}
#endif
status_t result = (*functor)();
float bounds[4];
status_t result = (*functor)(&bounds[0], 4);
if (result != 0) {
Rect localDirty(bounds[0], bounds[1], bounds[2], bounds[3]);
dirty.unionWith(localDirty);
}
resume();
return (result == 0) ? false : true;
return result != 0;
}
///////////////////////////////////////////////////////////////////////////////
@@ -1057,11 +1064,11 @@ void OpenGLRenderer::finishDrawTexture() {
// Drawing
///////////////////////////////////////////////////////////////////////////////
bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level) {
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
// will be performed by the display list itself
if (displayList) {
return displayList->replay(*this, level);
return displayList->replay(*this, dirty, level);
}
return false;
}
@@ -1522,7 +1529,6 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
break;
}
// TODO: Handle paint->getTextScaleX()
const float oldX = x;
const float oldY = y;
const bool pureTranslate = mSnapshot->transform->isPureTranslate();

View File

@@ -70,7 +70,7 @@ public:
virtual void interrupt();
virtual void resume();
virtual bool callDrawGLFunction(Functor *functor);
virtual bool callDrawGLFunction(Functor *functor, Rect& dirty);
int getSaveCount() const;
virtual int save(int flags);
@@ -96,7 +96,7 @@ public:
bool quickReject(float left, float top, float right, float bottom);
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
virtual bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
virtual bool drawDisplayList(DisplayList* displayList, Rect& dirty, uint32_t level = 0);
virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);

View File

@@ -42,6 +42,17 @@ struct ShadowText {
textSize = paint->getTextSize();
typeface = paint->getTypeface();
flags = 0;
if (paint->isFakeBoldText()) {
flags |= Font::kFakeBold;
}
const float skewX = paint->getTextSkewX();
italicStyle = *(uint32_t*) &skewX;
const float scaleXFloat = paint->getTextScaleX();
scaleX = *(uint32_t*) &scaleXFloat;
}
~ShadowText() {
@@ -51,6 +62,9 @@ struct ShadowText {
uint32_t len;
float textSize;
SkTypeface* typeface;
uint32_t flags;
uint32_t italicStyle;
uint32_t scaleX;
const char16_t* text;
String16 str;
@@ -65,7 +79,13 @@ struct ShadowText {
LTE_INT(radius) {
LTE_FLOAT(textSize) {
LTE_INT(typeface) {
return strncmp16(text, rhs.text, len >> 1) < 0;
LTE_INT(flags) {
LTE_INT(italicStyle) {
LTE_INT(scaleX) {
return strncmp16(text, rhs.text, len >> 1) < 0;
}
}
}
}
}
}

View File

@@ -58,10 +58,12 @@ public class TextActivity extends Activity {
mScaledPaint = new Paint();
mScaledPaint.setAntiAlias(true);
mScaledPaint.setTextSize(16.0f);
mScaledPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff00ff00);
mSkewPaint = new Paint();
mSkewPaint.setAntiAlias(true);
mSkewPaint.setTextSize(16.0f);
mSkewPaint.setTextSize(16.0f);
mSkewPaint.setShadowLayer(3.0f, 3.0f, 3.0f, 0xff000000);
}
@Override
@@ -106,11 +108,11 @@ public class TextActivity extends Activity {
mStrikePaint.setUnderlineText(true);
mSkewPaint.setTextSkewX(-0.25f);
canvas.drawText("Hello OpenGL renderer!", 680, 200, mSkewPaint);
canvas.drawText("Hello OpenGL renderer!", 980, 200, mSkewPaint);
mSkewPaint.setTextSkewX(0.5f);
canvas.drawText("Hello OpenGL renderer!", 680, 230, mSkewPaint);
canvas.drawText("Hello OpenGL renderer!", 980, 230, mSkewPaint);
mSkewPaint.setTextSkewX(0.0f);
canvas.drawText("Hello OpenGL renderer!", 680, 260, mSkewPaint);
canvas.drawText("Hello OpenGL renderer!", 980, 260, mSkewPaint);
mScaledPaint.setTextScaleX(0.5f);
canvas.drawText("Hello OpenGL renderer!", 500, 200, mScaledPaint);
@@ -125,4 +127,4 @@ public class TextActivity extends Activity {
canvas.restore();
}
}
}
}