Merge "Preliminary Support for region clipping"

This commit is contained in:
Romain Guy
2013-01-15 10:24:46 -08:00
committed by Android (Google) Code Review
10 changed files with 206 additions and 59 deletions

View File

@@ -433,20 +433,16 @@ class GLES20Canvas extends HardwareCanvas {
@Override @Override
public boolean clipPath(Path path) { public boolean clipPath(Path path) {
// TODO: Implement return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
path.computeBounds(mPathBounds, true);
return nClipRect(mRenderer, mPathBounds.left, mPathBounds.top,
mPathBounds.right, mPathBounds.bottom, Region.Op.INTERSECT.nativeInt);
} }
@Override @Override
public boolean clipPath(Path path, Region.Op op) { public boolean clipPath(Path path, Region.Op op) {
// TODO: Implement return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
path.computeBounds(mPathBounds, true);
return nClipRect(mRenderer, mPathBounds.left, mPathBounds.top,
mPathBounds.right, mPathBounds.bottom, op.nativeInt);
} }
private static native boolean nClipPath(int renderer, int path, int op);
@Override @Override
public boolean clipRect(float left, float top, float right, float bottom) { public boolean clipRect(float left, float top, float right, float bottom) {
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
@@ -465,8 +461,8 @@ class GLES20Canvas extends HardwareCanvas {
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt); return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
} }
private static native boolean nClipRect(int renderer, int left, int top, int right, int bottom, private static native boolean nClipRect(int renderer, int left, int top,
int op); int right, int bottom, int op);
@Override @Override
public boolean clipRect(Rect rect) { public boolean clipRect(Rect rect) {
@@ -492,20 +488,16 @@ class GLES20Canvas extends HardwareCanvas {
@Override @Override
public boolean clipRegion(Region region) { public boolean clipRegion(Region region) {
// TODO: Implement return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
region.getBounds(mClipBounds);
return nClipRect(mRenderer, mClipBounds.left, mClipBounds.top,
mClipBounds.right, mClipBounds.bottom, Region.Op.INTERSECT.nativeInt);
} }
@Override @Override
public boolean clipRegion(Region region, Region.Op op) { public boolean clipRegion(Region region, Region.Op op) {
// TODO: Implement return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
region.getBounds(mClipBounds);
return nClipRect(mRenderer, mClipBounds.left, mClipBounds.top,
mClipBounds.right, mClipBounds.bottom, op.nativeInt);
} }
private static native boolean nClipRegion(int renderer, int region, int op);
@Override @Override
public boolean getClipBounds(Rect bounds) { public boolean getClipBounds(Rect bounds) {
return nGetClipBounds(mRenderer, bounds); return nGetClipBounds(mRenderer, bounds);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2010 The Android Open Source Project * Copyright (C) 2013 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
package android.view; package android.view;
import android.content.ComponentCallbacks2; import android.content.ComponentCallbacks2;
@@ -173,6 +172,17 @@ public abstract class HardwareRenderer {
*/ */
public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw"; public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw";
/**
* Turn on to allow region clipping (see
* {@link android.graphics.Canvas#clipPath(android.graphics.Path)} and
* {@link android.graphics.Canvas#clipRegion(android.graphics.Region)}.
*
* When this option is turned on a stencil buffer is always required.
* If this option is off a stencil buffer is only created when the overdraw
* debugging mode is turned on.
*/
private static final boolean REGION_CLIPPING_ENABLED = false;
/** /**
* A process can set this flag to false to prevent the use of hardware * A process can set this flag to false to prevent the use of hardware
* rendering. * rendering.
@@ -876,10 +886,12 @@ public abstract class HardwareRenderer {
changed = true; changed = true;
mShowOverdraw = value; mShowOverdraw = value;
if (surface != null && isEnabled()) { if (!REGION_CLIPPING_ENABLED) {
if (validate()) { if (surface != null && isEnabled()) {
sEglConfig = loadEglConfig(); if (validate()) {
invalidate(surface); sEglConfig = loadEglConfig();
invalidate(surface);
}
} }
} }
} }
@@ -1752,6 +1764,11 @@ public abstract class HardwareRenderer {
@Override @Override
int[] getConfig(boolean dirtyRegions) { int[] getConfig(boolean dirtyRegions) {
//noinspection PointlessBooleanExpression
final int stencilSize = mShowOverdraw || REGION_CLIPPING_ENABLED ?
GLES20Canvas.getStencilSize() : 0;
final int swapBehavior = dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
return new int[] { return new int[] {
EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT, EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
EGL_RED_SIZE, 8, EGL_RED_SIZE, 8,
@@ -1760,10 +1777,8 @@ public abstract class HardwareRenderer {
EGL_ALPHA_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0, EGL_DEPTH_SIZE, 0,
EGL_CONFIG_CAVEAT, EGL_NONE, EGL_CONFIG_CAVEAT, EGL_NONE,
// TODO: Find a better way to choose the stencil size EGL_STENCIL_SIZE, stencilSize,
EGL_STENCIL_SIZE, mShowOverdraw ? GLES20Canvas.getStencilSize() : 0, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
(dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
EGL_NONE EGL_NONE
}; };
} }

View File

@@ -275,6 +275,16 @@ static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
return renderer->clipRect(float(left), float(top), float(right), float(bottom), op); return renderer->clipRect(float(left), float(top), float(right), float(bottom), op);
} }
static bool android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, SkPath* path, SkRegion::Op op) {
return renderer->clipPath(path, op);
}
static bool android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, SkRegion* region, SkRegion::Op op) {
return renderer->clipRegion(region, op);
}
static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz, static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, jobject rect) { OpenGLRenderer* renderer, jobject rect) {
const android::uirenderer::Rect& bounds(renderer->getClipBounds()); const android::uirenderer::Rect& bounds(renderer->getClipBounds());
@@ -961,6 +971,8 @@ static JNINativeMethod gMethods[] = {
{ "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject }, { "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
{ "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF }, { "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
{ "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect }, { "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
{ "nClipPath", "(III)Z", (void*) android_view_GLES20Canvas_clipPath },
{ "nClipRegion", "(III)Z", (void*) android_view_GLES20Canvas_clipRegion },
{ "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate }, { "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate },
{ "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate }, { "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate },

View File

@@ -35,6 +35,9 @@
// Turn on to enable layers debugging when rendered as regions // Turn on to enable layers debugging when rendered as regions
#define DEBUG_LAYERS_AS_REGIONS 0 #define DEBUG_LAYERS_AS_REGIONS 0
// Turn on to enable debugging when the clip is not a rect
#define DEBUG_CLIP_REGIONS 0
// Turn on to display debug info about vertex/fragment shaders // Turn on to display debug info about vertex/fragment shaders
#define DEBUG_PROGRAMS 0 #define DEBUG_PROGRAMS 0

View File

@@ -44,6 +44,8 @@ const char* DisplayList::OP_NAMES[] = {
"SetMatrix", "SetMatrix",
"ConcatMatrix", "ConcatMatrix",
"ClipRect", "ClipRect",
"ClipPath",
"ClipRegion",
"DrawDisplayList", "DrawDisplayList",
"DrawLayer", "DrawLayer",
"DrawBitmap", "DrawBitmap",
@@ -166,6 +168,10 @@ void DisplayList::clearResources() {
delete mPaints.itemAt(i); delete mPaints.itemAt(i);
} }
for (size_t i = 0; i < mRegions.size(); i++) {
delete mRegions.itemAt(i);
}
for (size_t i = 0; i < mPaths.size(); i++) { for (size_t i = 0; i < mPaths.size(); i++) {
SkPath* path = mPaths.itemAt(i); SkPath* path = mPaths.itemAt(i);
caches.pathCache.remove(path); caches.pathCache.remove(path);
@@ -182,6 +188,7 @@ void DisplayList::clearResources() {
mShaders.clear(); mShaders.clear();
mSourcePaths.clear(); mSourcePaths.clear();
mPaints.clear(); mPaints.clear();
mRegions.clear();
mPaths.clear(); mPaths.clear();
mMatrices.clear(); mMatrices.clear();
mLayers.clear(); mLayers.clear();
@@ -259,20 +266,10 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
caches.resourceCache.unlock(); caches.resourceCache.unlock();
const Vector<SkPaint*>& paints = recorder.getPaints(); mPaints.appendVector(recorder.getPaints());
for (size_t i = 0; i < paints.size(); i++) { mRegions.appendVector(recorder.getRegions());
mPaints.add(paints.itemAt(i)); mPaths.appendVector(recorder.getPaths());
} mMatrices.appendVector(recorder.getMatrices());
const Vector<SkPath*>& paths = recorder.getPaths();
for (size_t i = 0; i < paths.size(); i++) {
mPaths.add(paths.itemAt(i));
}
const Vector<SkMatrix*>& matrices = recorder.getMatrices();
for (size_t i = 0; i < matrices.size(); i++) {
mMatrices.add(matrices.itemAt(i));
}
} }
void DisplayList::init() { void DisplayList::init() {
@@ -429,6 +426,18 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
f1, f2, f3, f4, regionOp); f1, f2, f3, f4, regionOp);
} }
break; break;
case ClipPath: {
SkPath* path = getPath();
int regionOp = getInt();
ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
}
break;
case ClipRegion: {
SkRegion* region = getRegion();
int regionOp = getInt();
ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
}
break;
case DrawDisplayList: { case DrawDisplayList: {
DisplayList* displayList = getDisplayList(); DisplayList* displayList = getDisplayList();
int32_t flags = getInt(); int32_t flags = getInt();
@@ -1031,6 +1040,20 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp); renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
} }
break; break;
case ClipPath: {
SkPath* path = getPath();
int32_t regionOp = getInt();
DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
renderer.clipPath(path, (SkRegion::Op) regionOp);
}
break;
case ClipRegion: {
SkRegion* region = getRegion();
int32_t regionOp = getInt();
DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
renderer.clipRegion(region, (SkRegion::Op) regionOp);
}
break;
case DrawDisplayList: { case DrawDisplayList: {
DisplayList* displayList = getDisplayList(); DisplayList* displayList = getDisplayList();
int32_t flags = getInt(); int32_t flags = getInt();
@@ -1415,6 +1438,9 @@ void DisplayListRenderer::reset() {
mPaints.clear(); mPaints.clear();
mPaintMap.clear(); mPaintMap.clear();
mRegions.clear();
mRegionMap.clear();
mPaths.clear(); mPaths.clear();
mPathMap.clear(); mPathMap.clear();
@@ -1571,6 +1597,20 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot
return OpenGLRenderer::clipRect(left, top, right, bottom, op); return OpenGLRenderer::clipRect(left, top, right, bottom, op);
} }
bool DisplayListRenderer::clipPath(SkPath* path, SkRegion::Op op) {
addOp(DisplayList::ClipPath);
addPath(path);
addInt(op);
return OpenGLRenderer::clipPath(path, op);
}
bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
addOp(DisplayList::ClipRegion);
addRegion(region);
addInt(op);
return OpenGLRenderer::clipRegion(region, op);
}
status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList, status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
Rect& dirty, int32_t flags, uint32_t level) { Rect& dirty, int32_t flags, uint32_t level) {
// dirty is an out parameter and should not be recorded, // dirty is an out parameter and should not be recorded,

View File

@@ -85,6 +85,8 @@ public:
SetMatrix, SetMatrix,
ConcatMatrix, ConcatMatrix,
ClipRect, ClipRect,
ClipPath,
ClipRegion,
// Drawing operations // Drawing operations
DrawDisplayList, DrawDisplayList,
DrawLayer, DrawLayer,
@@ -457,6 +459,10 @@ private:
return (SkPath*) getInt(); return (SkPath*) getInt();
} }
SkRegion* getRegion() {
return (SkRegion*) getInt();
}
SkPaint* getPaint(OpenGLRenderer& renderer) { SkPaint* getPaint(OpenGLRenderer& renderer) {
return renderer.filterPaint((SkPaint*) getInt()); return renderer.filterPaint((SkPaint*) getInt());
} }
@@ -496,6 +502,7 @@ private:
Vector<SkPaint*> mPaints; Vector<SkPaint*> mPaints;
Vector<SkPath*> mPaths; Vector<SkPath*> mPaths;
SortedVector<SkPath*> mSourcePaths; SortedVector<SkPath*> mSourcePaths;
Vector<SkRegion*> mRegions;
Vector<SkMatrix*> mMatrices; Vector<SkMatrix*> mMatrices;
Vector<SkiaShader*> mShaders; Vector<SkiaShader*> mShaders;
Vector<Layer*> mLayers; Vector<Layer*> mLayers;
@@ -577,6 +584,8 @@ public:
virtual void concatMatrix(SkMatrix* matrix); virtual void concatMatrix(SkMatrix* matrix);
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
virtual bool clipPath(SkPath* path, SkRegion::Op op);
virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags, virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
uint32_t level = 0); uint32_t level = 0);
@@ -657,6 +666,10 @@ public:
return mSourcePaths; return mSourcePaths;
} }
const Vector<SkRegion*>& getRegions() const {
return mRegions;
}
const Vector<Layer*>& getLayers() const { const Vector<Layer*>& getLayers() const {
return mLayers; return mLayers;
} }
@@ -802,6 +815,26 @@ private:
return paintCopy; return paintCopy;
} }
inline SkRegion* addRegion(SkRegion* region) {
if (!region) {
addInt((int) NULL);
return region;
}
SkRegion* regionCopy = mRegionMap.valueFor(region);
// TODO: Add generation ID to SkRegion
if (regionCopy == NULL) {
regionCopy = new SkRegion(*region);
// replaceValueFor() performs an add if the entry doesn't exist
mRegionMap.replaceValueFor(region, regionCopy);
mRegions.add(regionCopy);
}
addInt((int) regionCopy);
return regionCopy;
}
inline void addDisplayList(DisplayList* displayList) { inline void addDisplayList(DisplayList* displayList) {
// TODO: To be safe, the display list should be ref-counted in the // TODO: To be safe, the display list should be ref-counted in the
// resources cache, but we rely on the caller (UI toolkit) to // resources cache, but we rely on the caller (UI toolkit) to
@@ -876,6 +909,9 @@ private:
SortedVector<SkPath*> mSourcePaths; SortedVector<SkPath*> mSourcePaths;
Vector<SkRegion*> mRegions;
DefaultKeyedVector<SkRegion*, SkRegion*> mRegionMap;
Vector<SkiaShader*> mShaders; Vector<SkiaShader*> mShaders;
DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap; DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;

View File

@@ -1288,10 +1288,38 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom,
bool clipped = mSnapshot->clip(left, top, right, bottom, op); bool clipped = mSnapshot->clip(left, top, right, bottom, op);
if (clipped) { if (clipped) {
dirtyClip(); dirtyClip();
#if DEBUG_CLIP_REGIONS
if (!isDeferred() && mSnapshot->clipRegion && !mSnapshot->clipRegion->isRect()) {
int count = 0;
Vector<float> rects;
SkRegion::Iterator it(*mSnapshot->clipRegion);
while (!it.done()) {
const SkIRect& r = it.rect();
rects.push(r.fLeft);
rects.push(r.fTop);
rects.push(r.fRight);
rects.push(r.fBottom);
count++;
it.next();
}
drawColorRects(rects.array(), count, 0x7f00ff00, SkXfermode::kSrcOver_Mode, true);
}
#endif
} }
return !mSnapshot->clipRect->isEmpty(); return !mSnapshot->clipRect->isEmpty();
} }
bool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) {
const SkRect& bounds = path->getBounds();
return clipRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, op);
}
bool OpenGLRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
const SkIRect& bounds = region->getBounds();
return clipRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, op);
}
Rect* OpenGLRenderer::getClipRect() { Rect* OpenGLRenderer::getClipRect() {
return mSnapshot->clipRect; return mSnapshot->clipRect;
} }
@@ -3046,6 +3074,19 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
return DrawGlInfo::kStatusDone; return DrawGlInfo::kStatusDone;
} }
int color = paint->getColor();
// If a shader is set, preserve only the alpha
if (mShader) {
color |= 0x00ffffff;
}
SkXfermode::Mode mode = getXfermode(paint->getXfermode());
return drawColorRects(rects, count, color, mode);
}
status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color,
SkXfermode::Mode mode, bool ignoreTransform) {
float left = FLT_MAX; float left = FLT_MAX;
float top = FLT_MAX; float top = FLT_MAX;
float right = FLT_MIN; float right = FLT_MIN;
@@ -3081,13 +3122,6 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
if (count == 0) return DrawGlInfo::kStatusDone; if (count == 0) return DrawGlInfo::kStatusDone;
int color = paint->getColor();
// If a shader is set, preserve only the alpha
if (mShader) {
color |= 0x00ffffff;
}
SkXfermode::Mode mode = getXfermode(paint->getXfermode());
setupDraw(); setupDraw();
setupDrawNoTexture(); setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
@@ -3096,7 +3130,7 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
setupDrawBlending(mode); setupDrawBlending(mode);
setupDrawProgram(); setupDrawProgram();
setupDrawDirtyRegionsDisabled(); setupDrawDirtyRegionsDisabled();
setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f); setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f, ignoreTransform, true);
setupDrawColorUniforms(); setupDrawColorUniforms();
setupDrawShaderUniforms(); setupDrawShaderUniforms();
setupDrawColorFilterUniforms(); setupDrawColorFilterUniforms();

View File

@@ -164,6 +164,8 @@ public:
ANDROID_API bool quickReject(float left, float top, float right, float bottom); ANDROID_API bool quickReject(float left, float top, float right, float bottom);
bool quickRejectNoScissor(float left, float top, float right, float bottom); bool quickRejectNoScissor(float left, float top, float right, float bottom);
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
virtual bool clipPath(SkPath* path, SkRegion::Op op);
virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
virtual Rect* getClipRect(); virtual Rect* getClipRect();
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags, virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
@@ -498,7 +500,8 @@ private:
/** /**
* Draws a colored rectangle with the specified color. The specified coordinates * Draws a colored rectangle with the specified color. The specified coordinates
* are transformed by the current snapshot's transform matrix. * are transformed by the current snapshot's transform matrix unless specified
* otherwise.
* *
* @param left The left coordinate of the rectangle * @param left The left coordinate of the rectangle
* @param top The top coordinate of the rectangle * @param top The top coordinate of the rectangle
@@ -511,6 +514,20 @@ private:
void drawColorRect(float left, float top, float right, float bottom, void drawColorRect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode, bool ignoreTransform = false); int color, SkXfermode::Mode mode, bool ignoreTransform = false);
/**
* Draws a series of colored rectangles with the specified color. The specified
* coordinates are transformed by the current snapshot's transform matrix unless
* specified otherwise.
*
* @param rects A list of rectangles, 4 floats (left, top, right, bottom)
* per rectangle
* @param color The rectangles' ARGB color, defined as a packed 32 bits word
* @param mode The Skia xfermode to use
* @param ignoreTransform True if the current transform should be ignored
*/
status_t drawColorRects(const float* rects, int count, int color,
SkXfermode::Mode mode, bool ignoreTransform = false);
/** /**
* Draws the shape represented by the specified path texture. * Draws the shape represented by the specified path texture.
* This method invokes drawPathTexture() but takes into account * This method invokes drawPathTexture() but takes into account

View File

@@ -130,6 +130,7 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
switch (op) { switch (op) {
case SkRegion::kIntersect_Op: { case SkRegion::kIntersect_Op: {
if (CC_UNLIKELY(clipRegion)) { if (CC_UNLIKELY(clipRegion)) {
ensureClipRegion();
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op); clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
} else { } else {
clipped = clipRect->intersect(r); clipped = clipRect->intersect(r);
@@ -142,6 +143,7 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
} }
case SkRegion::kUnion_Op: { case SkRegion::kUnion_Op: {
if (CC_UNLIKELY(clipRegion)) { if (CC_UNLIKELY(clipRegion)) {
ensureClipRegion();
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op); clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
} else { } else {
clipped = clipRect->unionWith(r); clipped = clipRect->unionWith(r);

View File

@@ -18,13 +18,7 @@ package com.android.test.hwui;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Region; import android.graphics.Region;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
@@ -50,8 +44,10 @@ public class ClipRegionActivity extends Activity {
canvas.save(); canvas.save();
canvas.clipRect(100.0f, 100.0f, getWidth() - 100.0f, getHeight() - 100.0f, canvas.clipRect(100.0f, 100.0f, getWidth() - 100.0f, getHeight() - 100.0f,
Region.Op.DIFFERENCE); Region.Op.DIFFERENCE);
canvas.drawARGB(255, 255, 0, 0); canvas.drawARGB(128, 255, 0, 0);
canvas.restore(); canvas.restore();
invalidate();
} }
} }
} }