Make DisplayListRenderer inherit from Canvas, merge JNI
Incrementally unify the upper layers for Skia and HWUI. Remove redundant code from GLES20Canvas.java; instead use inherited mNativeCanvasWrapper and superclass method definitions. Moves some unrelated SkPaint utility functions from Renderer to new utils/PaintUtils. bug: 15672762 Change-Id: I4ddd4214b8e9eeb95289d054ef423f2542bb5fa5
This commit is contained in:
@@ -19,19 +19,13 @@ package android.view;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.CanvasProperty;
|
||||
import android.graphics.DrawFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.NinePatch;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PaintFlagsDrawFilter;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Picture;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.TemporaryBuffer;
|
||||
import android.text.GraphicsOperations;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannedString;
|
||||
@@ -41,14 +35,6 @@ import android.text.TextUtils;
|
||||
* An implementation of Canvas on top of OpenGL ES 2.0.
|
||||
*/
|
||||
class GLES20Canvas extends HardwareCanvas {
|
||||
private final boolean mOpaque;
|
||||
protected long mRenderer;
|
||||
|
||||
// The native renderer will be destroyed when this object dies.
|
||||
// DO NOT overwrite this reference once it is set.
|
||||
@SuppressWarnings({"unused", "FieldCanBeLocal"})
|
||||
private CanvasFinalizer mFinalizer;
|
||||
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
|
||||
@@ -58,8 +44,6 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
private Rect mClipBounds;
|
||||
private RectF mPathBounds;
|
||||
|
||||
private DrawFilter mFilter;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// JNI
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -77,39 +61,10 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
|
||||
// TODO: Merge with GLES20RecordingCanvas
|
||||
protected GLES20Canvas() {
|
||||
mOpaque = false;
|
||||
mRenderer = nCreateDisplayListRenderer();
|
||||
setupFinalizer();
|
||||
}
|
||||
|
||||
private void setupFinalizer() {
|
||||
if (mRenderer == 0) {
|
||||
throw new IllegalStateException("Could not create GLES20Canvas renderer");
|
||||
} else {
|
||||
mFinalizer = new CanvasFinalizer(mRenderer);
|
||||
}
|
||||
super(nCreateDisplayListRenderer());
|
||||
}
|
||||
|
||||
private static native long nCreateDisplayListRenderer();
|
||||
private static native void nResetDisplayListRenderer(long renderer);
|
||||
private static native void nDestroyRenderer(long renderer);
|
||||
|
||||
private static final class CanvasFinalizer {
|
||||
private final long mRenderer;
|
||||
|
||||
public CanvasFinalizer(long renderer) {
|
||||
mRenderer = renderer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
nDestroyRenderer(mRenderer);
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setProperty(String name, String value) {
|
||||
nSetProperty(name, value);
|
||||
@@ -123,7 +78,7 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
|
||||
@Override
|
||||
public boolean isOpaque() {
|
||||
return mOpaque;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -153,7 +108,7 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
* Returns the native OpenGLRenderer object.
|
||||
*/
|
||||
long getRenderer() {
|
||||
return mRenderer;
|
||||
return mNativeCanvasWrapper;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -165,7 +120,7 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
nSetViewport(mRenderer, width, height);
|
||||
nSetViewport(mNativeCanvasWrapper, width, height);
|
||||
}
|
||||
|
||||
private static native void nSetViewport(long renderer,
|
||||
@@ -173,19 +128,19 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
|
||||
@Override
|
||||
public void setHighContrastText(boolean highContrastText) {
|
||||
nSetHighContrastText(mRenderer, highContrastText);
|
||||
nSetHighContrastText(mNativeCanvasWrapper, highContrastText);
|
||||
}
|
||||
|
||||
private static native void nSetHighContrastText(long renderer, boolean highContrastText);
|
||||
|
||||
@Override
|
||||
public void insertReorderBarrier() {
|
||||
nInsertReorderBarrier(mRenderer, true);
|
||||
nInsertReorderBarrier(mNativeCanvasWrapper, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertInorderBarrier() {
|
||||
nInsertReorderBarrier(mRenderer, false);
|
||||
nInsertReorderBarrier(mNativeCanvasWrapper, false);
|
||||
}
|
||||
|
||||
private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
|
||||
@@ -193,20 +148,18 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
@Override
|
||||
public void onPreDraw(Rect dirty) {
|
||||
if (dirty != null) {
|
||||
nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
|
||||
mOpaque);
|
||||
nPrepareDirty(mNativeCanvasWrapper, dirty.left, dirty.top, dirty.right, dirty.bottom);
|
||||
} else {
|
||||
nPrepare(mRenderer, mOpaque);
|
||||
nPrepare(mNativeCanvasWrapper);
|
||||
}
|
||||
}
|
||||
|
||||
private static native void nPrepare(long renderer, boolean opaque);
|
||||
private static native void nPrepareDirty(long renderer, int left, int top, int right, int bottom,
|
||||
boolean opaque);
|
||||
private static native void nPrepare(long renderer);
|
||||
private static native void nPrepareDirty(long renderer, int left, int top, int right, int bottom);
|
||||
|
||||
@Override
|
||||
public void onPostDraw() {
|
||||
nFinish(mRenderer);
|
||||
nFinish(mNativeCanvasWrapper);
|
||||
}
|
||||
|
||||
private static native void nFinish(long renderer);
|
||||
@@ -217,7 +170,7 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
|
||||
@Override
|
||||
public void callDrawGLFunction2(long drawGLFunction) {
|
||||
nCallDrawGLFunction(mRenderer, drawGLFunction);
|
||||
nCallDrawGLFunction(mNativeCanvasWrapper, drawGLFunction);
|
||||
}
|
||||
|
||||
private static native void nCallDrawGLFunction(long renderer, long drawGLFunction);
|
||||
@@ -230,7 +183,7 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
|
||||
@Override
|
||||
public void drawRenderNode(RenderNode renderNode, int flags) {
|
||||
nDrawRenderNode(mRenderer, renderNode.getNativeDisplayList(), flags);
|
||||
nDrawRenderNode(mNativeCanvasWrapper, renderNode.getNativeDisplayList(), flags);
|
||||
}
|
||||
|
||||
private static native void nDrawRenderNode(long renderer, long renderNode,
|
||||
@@ -242,475 +195,42 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
|
||||
void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
|
||||
layer.setLayerPaint(paint);
|
||||
nDrawLayer(mRenderer, layer.getLayerHandle(), x, y);
|
||||
nDrawLayer(mNativeCanvasWrapper, layer.getLayerHandle(), x, y);
|
||||
}
|
||||
|
||||
private static native void nDrawLayer(long renderer, long layer, float x, float y);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Support
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private Rect getInternalClipBounds() {
|
||||
if (mClipBounds == null) mClipBounds = new Rect();
|
||||
return mClipBounds;
|
||||
}
|
||||
|
||||
|
||||
private RectF getPathBounds() {
|
||||
if (mPathBounds == null) mPathBounds = new RectF();
|
||||
return mPathBounds;
|
||||
}
|
||||
|
||||
private float[] getPointStorage() {
|
||||
if (mPoint == null) mPoint = new float[2];
|
||||
return mPoint;
|
||||
}
|
||||
|
||||
private float[] getLineStorage() {
|
||||
if (mLine == null) mLine = new float[4];
|
||||
return mLine;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Clipping
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public boolean clipPath(Path path) {
|
||||
return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clipPath(Path path, Region.Op op) {
|
||||
return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
|
||||
}
|
||||
|
||||
private static native boolean nClipPath(long renderer, long path, int op);
|
||||
|
||||
@Override
|
||||
public boolean clipRect(float left, float top, float right, float bottom) {
|
||||
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
|
||||
}
|
||||
|
||||
private static native boolean nClipRect(long renderer, float left, float top,
|
||||
float right, float bottom, int op);
|
||||
|
||||
@Override
|
||||
public boolean clipRect(float left, float top, float right, float bottom, Region.Op op) {
|
||||
return nClipRect(mRenderer, left, top, right, bottom, op.nativeInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clipRect(int left, int top, int right, int bottom) {
|
||||
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
|
||||
}
|
||||
|
||||
private static native boolean nClipRect(long renderer, int left, int top,
|
||||
int right, int bottom, int op);
|
||||
|
||||
@Override
|
||||
public boolean clipRect(Rect rect) {
|
||||
return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
|
||||
Region.Op.INTERSECT.nativeInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clipRect(Rect rect, Region.Op op) {
|
||||
return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clipRect(RectF rect) {
|
||||
return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
|
||||
Region.Op.INTERSECT.nativeInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clipRect(RectF rect, Region.Op op) {
|
||||
return nClipRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom, op.nativeInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clipRegion(Region region) {
|
||||
return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean clipRegion(Region region, Region.Op op) {
|
||||
return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
|
||||
}
|
||||
|
||||
private static native boolean nClipRegion(long renderer, long region, int op);
|
||||
|
||||
@Override
|
||||
public boolean getClipBounds(Rect bounds) {
|
||||
return nGetClipBounds(mRenderer, bounds);
|
||||
}
|
||||
|
||||
private static native boolean nGetClipBounds(long renderer, Rect bounds);
|
||||
|
||||
@Override
|
||||
public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
|
||||
return nQuickReject(mRenderer, left, top, right, bottom);
|
||||
}
|
||||
|
||||
private static native boolean nQuickReject(long renderer, float left, float top,
|
||||
float right, float bottom);
|
||||
|
||||
@Override
|
||||
public boolean quickReject(Path path, EdgeType type) {
|
||||
RectF pathBounds = getPathBounds();
|
||||
path.computeBounds(pathBounds, true);
|
||||
return nQuickReject(mRenderer, pathBounds.left, pathBounds.top,
|
||||
pathBounds.right, pathBounds.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean quickReject(RectF rect, EdgeType type) {
|
||||
return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Transformations
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void translate(float dx, float dy) {
|
||||
if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
|
||||
}
|
||||
|
||||
private static native void nTranslate(long renderer, float dx, float dy);
|
||||
|
||||
@Override
|
||||
public void skew(float sx, float sy) {
|
||||
nSkew(mRenderer, sx, sy);
|
||||
}
|
||||
|
||||
private static native void nSkew(long renderer, float sx, float sy);
|
||||
|
||||
@Override
|
||||
public void rotate(float degrees) {
|
||||
nRotate(mRenderer, degrees);
|
||||
}
|
||||
|
||||
private static native void nRotate(long renderer, float degrees);
|
||||
|
||||
@Override
|
||||
public void scale(float sx, float sy) {
|
||||
nScale(mRenderer, sx, sy);
|
||||
}
|
||||
|
||||
private static native void nScale(long renderer, float sx, float sy);
|
||||
|
||||
@Override
|
||||
public void setMatrix(Matrix matrix) {
|
||||
nSetMatrix(mRenderer, matrix == null ? 0 : matrix.native_instance);
|
||||
}
|
||||
|
||||
private static native void nSetMatrix(long renderer, long matrix);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void getMatrix(Matrix matrix) {
|
||||
nGetMatrix(mRenderer, matrix.native_instance);
|
||||
}
|
||||
|
||||
private static native void nGetMatrix(long renderer, long matrix);
|
||||
|
||||
@Override
|
||||
public void concat(Matrix matrix) {
|
||||
if (matrix != null) nConcatMatrix(mRenderer, matrix.native_instance);
|
||||
}
|
||||
|
||||
private static native void nConcatMatrix(long renderer, long matrix);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// State management
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public int save() {
|
||||
return nSave(mRenderer, Canvas.CLIP_SAVE_FLAG | Canvas.MATRIX_SAVE_FLAG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int save(int saveFlags) {
|
||||
return nSave(mRenderer, saveFlags);
|
||||
}
|
||||
|
||||
private static native int nSave(long renderer, int flags);
|
||||
|
||||
@Override
|
||||
public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
|
||||
if (bounds != null) {
|
||||
return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
|
||||
}
|
||||
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
return nSaveLayer(mRenderer, nativePaint, saveFlags);
|
||||
}
|
||||
|
||||
private static native int nSaveLayer(long renderer, long paint, int saveFlags);
|
||||
|
||||
@Override
|
||||
public int saveLayer(float left, float top, float right, float bottom, Paint paint,
|
||||
int saveFlags) {
|
||||
if (left < right && top < bottom) {
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
|
||||
}
|
||||
return save(saveFlags);
|
||||
}
|
||||
|
||||
private static native int nSaveLayer(long renderer, float left, float top,
|
||||
float right, float bottom, long paint, int saveFlags);
|
||||
|
||||
@Override
|
||||
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
|
||||
if (bounds != null) {
|
||||
return saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
|
||||
alpha, saveFlags);
|
||||
}
|
||||
return nSaveLayerAlpha(mRenderer, alpha, saveFlags);
|
||||
}
|
||||
|
||||
private static native int nSaveLayerAlpha(long renderer, int alpha, int saveFlags);
|
||||
|
||||
@Override
|
||||
public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
|
||||
int saveFlags) {
|
||||
if (left < right && top < bottom) {
|
||||
return nSaveLayerAlpha(mRenderer, left, top, right, bottom, alpha, saveFlags);
|
||||
}
|
||||
return save(saveFlags);
|
||||
}
|
||||
|
||||
private static native int nSaveLayerAlpha(long renderer, float left, float top, float right,
|
||||
float bottom, int alpha, int saveFlags);
|
||||
|
||||
@Override
|
||||
public void restore() {
|
||||
nRestore(mRenderer);
|
||||
}
|
||||
|
||||
private static native void nRestore(long renderer);
|
||||
|
||||
@Override
|
||||
public void restoreToCount(int saveCount) {
|
||||
nRestoreToCount(mRenderer, saveCount);
|
||||
}
|
||||
|
||||
private static native void nRestoreToCount(long renderer, int saveCount);
|
||||
|
||||
@Override
|
||||
public int getSaveCount() {
|
||||
return nGetSaveCount(mRenderer);
|
||||
}
|
||||
|
||||
private static native int nGetSaveCount(long renderer);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Filtering
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void setDrawFilter(DrawFilter filter) {
|
||||
mFilter = filter;
|
||||
nSetDrawFilter(mRenderer, (filter != null) ? filter.mNativeInt : 0);
|
||||
}
|
||||
|
||||
private static native void nSetDrawFilter(long renderer, long nativeFilter);
|
||||
|
||||
@Override
|
||||
public DrawFilter getDrawFilter() {
|
||||
return mFilter;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Drawing
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, boolean useCenter, Paint paint) {
|
||||
nDrawArc(mRenderer, left, top, right, bottom,
|
||||
startAngle, sweepAngle, useCenter, paint.getNativeInstance());
|
||||
}
|
||||
|
||||
private static native void nDrawArc(long renderer, float left, float top,
|
||||
float right, float bottom, float startAngle, float sweepAngle,
|
||||
boolean useCenter, long paint);
|
||||
|
||||
@Override
|
||||
public void drawARGB(int a, int r, int g, int b) {
|
||||
drawColor((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
|
||||
}
|
||||
|
||||
// TODO: move to Canvas.java
|
||||
@Override
|
||||
public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
|
||||
Bitmap bitmap = patch.getBitmap();
|
||||
throwIfCannotDraw(bitmap);
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
|
||||
nDrawPatch(mNativeCanvasWrapper, bitmap.mNativeBitmap, patch.mNativeChunk,
|
||||
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
|
||||
}
|
||||
|
||||
// TODO: move to Canvas.java
|
||||
@Override
|
||||
public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
|
||||
Bitmap bitmap = patch.getBitmap();
|
||||
throwIfCannotDraw(bitmap);
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
|
||||
nDrawPatch(mNativeCanvasWrapper, bitmap.mNativeBitmap, patch.mNativeChunk,
|
||||
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
|
||||
}
|
||||
|
||||
private static native void nDrawPatch(long renderer, long bitmap, long chunk,
|
||||
float left, float top, float right, float bottom, long paint);
|
||||
|
||||
@Override
|
||||
public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
|
||||
throwIfCannotDraw(bitmap);
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, nativePaint);
|
||||
}
|
||||
|
||||
private static native void nDrawBitmap(long renderer, long bitmap, float left,
|
||||
float top, long paint);
|
||||
|
||||
@Override
|
||||
public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
|
||||
throwIfCannotDraw(bitmap);
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint);
|
||||
}
|
||||
|
||||
private static native void nDrawBitmap(long renderer, long bitmap,
|
||||
long matrix, long paint);
|
||||
|
||||
@Override
|
||||
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
|
||||
throwIfCannotDraw(bitmap);
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
|
||||
int left, top, right, bottom;
|
||||
if (src == null) {
|
||||
left = top = 0;
|
||||
right = bitmap.getWidth();
|
||||
bottom = bitmap.getHeight();
|
||||
} else {
|
||||
left = src.left;
|
||||
right = src.right;
|
||||
top = src.top;
|
||||
bottom = src.bottom;
|
||||
}
|
||||
|
||||
nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
|
||||
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
|
||||
throwIfCannotDraw(bitmap);
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
|
||||
float left, top, right, bottom;
|
||||
if (src == null) {
|
||||
left = top = 0;
|
||||
right = bitmap.getWidth();
|
||||
bottom = bitmap.getHeight();
|
||||
} else {
|
||||
left = src.left;
|
||||
right = src.right;
|
||||
top = src.top;
|
||||
bottom = src.bottom;
|
||||
}
|
||||
|
||||
nDrawBitmap(mRenderer, bitmap.mNativeBitmap, left, top, right, bottom,
|
||||
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
|
||||
}
|
||||
|
||||
private static native void nDrawBitmap(long renderer, long bitmap,
|
||||
float srcLeft, float srcTop, float srcRight, float srcBottom,
|
||||
float left, float top, float right, float bottom, long paint);
|
||||
|
||||
@Override
|
||||
public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
|
||||
int width, int height, boolean hasAlpha, Paint paint) {
|
||||
if (width < 0) {
|
||||
throw new IllegalArgumentException("width must be >= 0");
|
||||
}
|
||||
|
||||
if (height < 0) {
|
||||
throw new IllegalArgumentException("height must be >= 0");
|
||||
}
|
||||
|
||||
if (Math.abs(stride) < width) {
|
||||
throw new IllegalArgumentException("abs(stride) must be >= width");
|
||||
}
|
||||
|
||||
int lastScanline = offset + (height - 1) * stride;
|
||||
int length = colors.length;
|
||||
|
||||
if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
|
||||
(lastScanline + width > length)) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
nDrawBitmap(mRenderer, colors, offset, stride, x, y,
|
||||
width, height, hasAlpha, nativePaint);
|
||||
}
|
||||
|
||||
private static native void nDrawBitmap(long renderer, int[] colors, int offset, int stride,
|
||||
float x, float y, int width, int height, boolean hasAlpha, long nativePaint);
|
||||
|
||||
@Override
|
||||
public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
|
||||
int width, int height, boolean hasAlpha, Paint paint) {
|
||||
drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
|
||||
int vertOffset, int[] colors, int colorOffset, Paint paint) {
|
||||
throwIfCannotDraw(bitmap);
|
||||
if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
if (meshWidth == 0 || meshHeight == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int count = (meshWidth + 1) * (meshHeight + 1);
|
||||
checkRange(verts.length, vertOffset, count * 2);
|
||||
|
||||
if (colors != null) {
|
||||
checkRange(colors.length, colorOffset, count);
|
||||
}
|
||||
|
||||
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
|
||||
nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, meshWidth, meshHeight,
|
||||
verts, vertOffset, colors, colorOffset, nativePaint);
|
||||
}
|
||||
|
||||
private static native void nDrawBitmapMesh(long renderer, long bitmap,
|
||||
int meshWidth, int meshHeight, float[] verts, int vertOffset,
|
||||
int[] colors, int colorOffset, long paint);
|
||||
|
||||
@Override
|
||||
public void drawCircle(float cx, float cy, float radius, Paint paint) {
|
||||
nDrawCircle(mRenderer, cx, cy, radius, paint.getNativeInstance());
|
||||
}
|
||||
|
||||
private static native void nDrawCircle(long renderer, float cx, float cy,
|
||||
float radius, long paint);
|
||||
|
||||
@Override
|
||||
public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
|
||||
CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
|
||||
nDrawCircle(mRenderer, cx.getNativeContainer(), cy.getNativeContainer(),
|
||||
nDrawCircle(mNativeCanvasWrapper, cx.getNativeContainer(), cy.getNativeContainer(),
|
||||
radius.getNativeContainer(), paint.getNativeContainer());
|
||||
}
|
||||
|
||||
@@ -721,7 +241,7 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
public void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
|
||||
CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
|
||||
CanvasProperty<Float> ry, CanvasProperty<Paint> paint) {
|
||||
nDrawRoundRect(mRenderer, left.getNativeContainer(), top.getNativeContainer(),
|
||||
nDrawRoundRect(mNativeCanvasWrapper, left.getNativeContainer(), top.getNativeContainer(),
|
||||
right.getNativeContainer(), bottom.getNativeContainer(),
|
||||
rx.getNativeContainer(), ry.getNativeContainer(),
|
||||
paint.getNativeContainer());
|
||||
@@ -730,73 +250,18 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
private static native void nDrawRoundRect(long renderer, long propLeft, long propTop,
|
||||
long propRight, long propBottom, long propRx, long propRy, long propPaint);
|
||||
|
||||
@Override
|
||||
public void drawColor(int color) {
|
||||
drawColor(color, PorterDuff.Mode.SRC_OVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawColor(int color, PorterDuff.Mode mode) {
|
||||
nDrawColor(mRenderer, color, mode.nativeInt);
|
||||
}
|
||||
|
||||
private static native void nDrawColor(long renderer, int color, int mode);
|
||||
|
||||
@Override
|
||||
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
|
||||
float[] line = getLineStorage();
|
||||
line[0] = startX;
|
||||
line[1] = startY;
|
||||
line[2] = stopX;
|
||||
line[3] = stopY;
|
||||
drawLines(line, 0, 4, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLines(float[] pts, int offset, int count, Paint paint) {
|
||||
if (count < 4) return;
|
||||
|
||||
if ((offset | count) < 0 || offset + count > pts.length) {
|
||||
throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
|
||||
}
|
||||
nDrawLines(mRenderer, pts, offset, count, paint.getNativeInstance());
|
||||
}
|
||||
|
||||
private static native void nDrawLines(long renderer, float[] points,
|
||||
int offset, int count, long paint);
|
||||
|
||||
@Override
|
||||
public void drawLines(float[] pts, Paint paint) {
|
||||
drawLines(pts, 0, pts.length, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOval(float left, float top, float right, float bottom, Paint paint) {
|
||||
nDrawOval(mRenderer, left, top, right, bottom, paint.getNativeInstance());
|
||||
}
|
||||
|
||||
private static native void nDrawOval(long renderer, float left, float top,
|
||||
float right, float bottom, long paint);
|
||||
|
||||
@Override
|
||||
public void drawPaint(Paint paint) {
|
||||
final Rect r = getInternalClipBounds();
|
||||
nGetClipBounds(mRenderer, r);
|
||||
drawRect(r.left, r.top, r.right, r.bottom, paint);
|
||||
}
|
||||
|
||||
// TODO: move this optimization to Canvas.java
|
||||
@Override
|
||||
public void drawPath(Path path, Paint paint) {
|
||||
if (path.isSimplePath) {
|
||||
if (path.rects != null) {
|
||||
nDrawRects(mRenderer, path.rects.mNativeRegion, paint.getNativeInstance());
|
||||
nDrawRects(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
|
||||
}
|
||||
} else {
|
||||
nDrawPath(mRenderer, path.mNativePath, paint.getNativeInstance());
|
||||
super.drawPath(path, paint);
|
||||
}
|
||||
}
|
||||
|
||||
private static native void nDrawPath(long renderer, long path, long paint);
|
||||
private static native void nDrawRects(long renderer, long region, long paint);
|
||||
|
||||
@Override
|
||||
@@ -804,190 +269,4 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
picture.endRecording();
|
||||
// TODO: Implement rendering
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPoint(float x, float y, Paint paint) {
|
||||
float[] point = getPointStorage();
|
||||
point[0] = x;
|
||||
point[1] = y;
|
||||
drawPoints(point, 0, 2, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPoints(float[] pts, Paint paint) {
|
||||
drawPoints(pts, 0, pts.length, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPoints(float[] pts, int offset, int count, Paint paint) {
|
||||
if (count < 2) return;
|
||||
|
||||
nDrawPoints(mRenderer, pts, offset, count, paint.getNativeInstance());
|
||||
}
|
||||
|
||||
private static native void nDrawPoints(long renderer, float[] points,
|
||||
int offset, int count, long paint);
|
||||
|
||||
// Note: drawPosText just uses implementation in Canvas
|
||||
|
||||
@Override
|
||||
public void drawRect(float left, float top, float right, float bottom, Paint paint) {
|
||||
if (left == right || top == bottom) return;
|
||||
nDrawRect(mRenderer, left, top, right, bottom, paint.getNativeInstance());
|
||||
}
|
||||
|
||||
private static native void nDrawRect(long renderer, float left, float top,
|
||||
float right, float bottom, long paint);
|
||||
|
||||
@Override
|
||||
public void drawRect(Rect r, Paint paint) {
|
||||
drawRect(r.left, r.top, r.right, r.bottom, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRect(RectF r, Paint paint) {
|
||||
drawRect(r.left, r.top, r.right, r.bottom, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRGB(int r, int g, int b) {
|
||||
drawColor(0xFF000000 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
|
||||
Paint paint) {
|
||||
nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.getNativeInstance());
|
||||
}
|
||||
|
||||
private static native void nDrawRoundRect(long renderer, float left, float top,
|
||||
float right, float bottom, float rx, float y, long paint);
|
||||
|
||||
@Override
|
||||
public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
|
||||
if ((index | count | (index + count) | (text.length - index - count)) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
nDrawText(mRenderer, text, index, count, x, y,
|
||||
paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
}
|
||||
|
||||
private static native void nDrawText(long renderer, char[] text, int index, int count,
|
||||
float x, float y, int bidiFlags, long paint, long typeface);
|
||||
|
||||
@Override
|
||||
public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
|
||||
if ((start | end | (end - start) | (text.length() - end)) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
if (text instanceof String || text instanceof SpannedString ||
|
||||
text instanceof SpannableString) {
|
||||
nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
|
||||
paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
} else if (text instanceof GraphicsOperations) {
|
||||
((GraphicsOperations) text).drawText(this, start, end, x, y, paint);
|
||||
} else {
|
||||
char[] buf = TemporaryBuffer.obtain(end - start);
|
||||
TextUtils.getChars(text, start, end, buf, 0);
|
||||
nDrawText(mRenderer, buf, 0, end - start, x, y,
|
||||
paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
TemporaryBuffer.recycle(buf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawText(String text, int start, int end, float x, float y, Paint paint) {
|
||||
if ((start | end | (end - start) | (text.length() - end)) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
nDrawText(mRenderer, text, start, end, x, y,
|
||||
paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
}
|
||||
|
||||
private static native void nDrawText(long renderer, String text, int start, int end,
|
||||
float x, float y, int bidiFlags, long paint, long typeface);
|
||||
|
||||
@Override
|
||||
public void drawText(String text, float x, float y, Paint paint) {
|
||||
nDrawText(mRenderer, text, 0, text.length(), x, y,
|
||||
paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
|
||||
float vOffset, Paint paint) {
|
||||
if (index < 0 || index + count > text.length) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
|
||||
paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
}
|
||||
|
||||
private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
|
||||
long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
|
||||
long typeface);
|
||||
|
||||
@Override
|
||||
public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
|
||||
if (text.length() == 0) return;
|
||||
|
||||
nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
|
||||
paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
}
|
||||
|
||||
private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
|
||||
long path, float hOffset, float vOffset, int bidiFlags, long nativePaint,
|
||||
long typeface);
|
||||
|
||||
@Override
|
||||
public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
|
||||
float x, float y, boolean isRtl, Paint paint) {
|
||||
if ((index | count | text.length - index - count) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, isRtl,
|
||||
paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
}
|
||||
|
||||
private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
|
||||
int contextIndex, int contextCount, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
|
||||
|
||||
@Override
|
||||
public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
|
||||
float x, float y, boolean isRtl, Paint paint) {
|
||||
if ((start | end | end - start | text.length() - end) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
if (text instanceof String || text instanceof SpannedString ||
|
||||
text instanceof SpannableString) {
|
||||
nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
|
||||
contextEnd, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
} else if (text instanceof GraphicsOperations) {
|
||||
((GraphicsOperations) text).drawTextRun(this, start, end,
|
||||
contextStart, contextEnd, x, y, isRtl, paint);
|
||||
} else {
|
||||
int contextLen = contextEnd - contextStart;
|
||||
int len = end - start;
|
||||
char[] buf = TemporaryBuffer.obtain(contextLen);
|
||||
TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
|
||||
nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
|
||||
x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
|
||||
TemporaryBuffer.recycle(buf);
|
||||
}
|
||||
}
|
||||
|
||||
private static native void nDrawTextRun(long renderer, String text, int start, int end,
|
||||
int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
|
||||
|
||||
@Override
|
||||
public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
|
||||
float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
|
||||
int indexOffset, int indexCount, Paint paint) {
|
||||
// TODO: Implement
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class GLES20RecordingCanvas extends GLES20Canvas {
|
||||
}
|
||||
|
||||
long finishRecording() {
|
||||
return nFinishRecording(mRenderer);
|
||||
return nFinishRecording(mNativeCanvasWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,6 +29,14 @@ import android.graphics.Rect;
|
||||
*/
|
||||
public abstract class HardwareCanvas extends Canvas {
|
||||
|
||||
/**
|
||||
* Pass a reference to the native renderer to our superclass's
|
||||
* constructor.
|
||||
*/
|
||||
protected HardwareCanvas(long renderer) {
|
||||
super(renderer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHardwareAccelerated() {
|
||||
return true;
|
||||
|
||||
@@ -126,7 +126,8 @@ public:
|
||||
|
||||
virtual void drawText(const uint16_t* text, const float* positions, 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);
|
||||
virtual void drawPosText(const uint16_t* text, const float* positions, int count,
|
||||
int posCount, const SkPaint& paint);
|
||||
virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
|
||||
@@ -686,7 +687,8 @@ void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshH
|
||||
|
||||
void SkiaCanvas::drawText(const uint16_t* text, const float* positions, 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) {
|
||||
// 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.
|
||||
|
||||
@@ -411,9 +411,10 @@ static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitma
|
||||
class DrawTextFunctor {
|
||||
public:
|
||||
DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
|
||||
const SkPaint& paint, float x, float y, MinikinRect& bounds)
|
||||
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) { }
|
||||
x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
|
||||
|
||||
void operator()(size_t start, size_t end) {
|
||||
if (canvas->drawTextAbsolutePos()) {
|
||||
@@ -432,7 +433,8 @@ public:
|
||||
|
||||
size_t glyphCount = end - start;
|
||||
canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
|
||||
bounds.mLeft , bounds.mTop , bounds.mRight , bounds.mBottom);
|
||||
bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
|
||||
totalAdvance);
|
||||
}
|
||||
private:
|
||||
const Layout& layout;
|
||||
@@ -443,6 +445,7 @@ private:
|
||||
float x;
|
||||
float y;
|
||||
MinikinRect& bounds;
|
||||
float totalAdvance;
|
||||
};
|
||||
|
||||
// Same values used by Skia
|
||||
@@ -494,8 +497,11 @@ void drawText(Canvas* canvas, const uint16_t* text, int start, int count, int co
|
||||
|
||||
MinikinRect bounds;
|
||||
layout.getBounds(&bounds);
|
||||
if (!canvas->drawTextAbsolutePos()) {
|
||||
bounds.offset(x, y);
|
||||
}
|
||||
|
||||
DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds);
|
||||
DrawTextFunctor f(layout, canvas, glyphs, pos, paint, x, y, bounds, layout.getAdvance());
|
||||
MinikinUtils::forFontRun(layout, &paint, f);
|
||||
|
||||
drawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
|
||||
|
||||
@@ -24,19 +24,10 @@
|
||||
|
||||
#include <androidfw/ResourceTypes.h>
|
||||
|
||||
#include <private/hwui/DrawGlInfo.h>
|
||||
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include <SkBitmap.h>
|
||||
#include <SkCanvas.h>
|
||||
#include <SkImageInfo.h>
|
||||
#include <SkMatrix.h>
|
||||
#include <SkPorterDuff.h>
|
||||
#include <SkRegion.h>
|
||||
#include <SkScalerContext.h>
|
||||
#include <SkTemplates.h>
|
||||
#include <SkXfermode.h>
|
||||
|
||||
#include <DisplayListRenderer.h>
|
||||
#include <Rect.h>
|
||||
@@ -45,8 +36,6 @@
|
||||
#include <Paint.h>
|
||||
#include <renderthread/RenderProxy.h>
|
||||
|
||||
#include "MinikinUtils.h"
|
||||
|
||||
#include "core_jni_helpers.h"
|
||||
|
||||
namespace android {
|
||||
@@ -63,19 +52,6 @@ static struct {
|
||||
|
||||
static const bool kDebugRenderer = false;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
if (kDebugRenderer) {
|
||||
ALOGD("Destroy DisplayListRenderer");
|
||||
}
|
||||
delete renderer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Setup
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -99,16 +75,15 @@ static void android_view_GLES20Canvas_insertReorderBarrier(JNIEnv* env, jobject
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jboolean opaque) {
|
||||
jlong rendererPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
renderer->prepare(opaque);
|
||||
renderer->prepare();
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jint left, jint top, jint right, jint bottom,
|
||||
jboolean opaque) {
|
||||
jlong rendererPtr, jint left, jint top, jint right, jint bottom) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
renderer->prepareDirty(left, top, right, bottom, opaque);
|
||||
renderer->prepareDirty(left, top, right, bottom);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
|
||||
@@ -159,268 +134,10 @@ static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject c
|
||||
return Caches::getInstance().maxTextureSize;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// State
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererPtr,
|
||||
jint flags) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
return renderer->save(flags);
|
||||
}
|
||||
|
||||
static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
return renderer->getSaveCount();
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
renderer->restore();
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jint saveCount) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
renderer->restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Layers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
|
||||
jlong paintPtr, jint saveFlags) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
|
||||
}
|
||||
|
||||
static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong paintPtr, jint saveFlags) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
|
||||
return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
|
||||
paint, saveFlags);
|
||||
}
|
||||
|
||||
static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
|
||||
jint alpha, jint saveFlags) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
|
||||
}
|
||||
|
||||
static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jint alpha, jint saveFlags) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
|
||||
return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
|
||||
alpha, saveFlags);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Clipping
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
const bool result = renderer->quickRejectConservative(left, top, right, bottom);
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
|
||||
jint op) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
const bool result = renderer->clipRect(left, top, right, bottom,
|
||||
static_cast<SkRegion::Op>(op));
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jint left, jint top, jint right, jint bottom,
|
||||
jint op) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
const bool result = renderer->clipRect(float(left), float(top), float(right),
|
||||
float(bottom),
|
||||
static_cast<SkRegion::Op>(op));
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong pathPtr, jint op) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
|
||||
const bool result = renderer->clipPath(path, static_cast<SkRegion::Op>(op));
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong regionPtr, jint op) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
|
||||
const bool result = renderer->clipRegion(region, static_cast<SkRegion::Op>(op));
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jobject rect) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
|
||||
|
||||
env->CallVoidMethod(rect, gRectClassInfo.set,
|
||||
int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
|
||||
|
||||
return !bounds.isEmpty() ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Transforms
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat dx, jfloat dy) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
renderer->translate(dx, dy);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat degrees) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
renderer->rotate(degrees);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat sx, jfloat sy) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
renderer->scale(sx, sy);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat sx, jfloat sy) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
renderer->skew(sx, sy);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong matrixPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
|
||||
renderer->setMatrix(matrix ? *matrix : SkMatrix::I());
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong matrixPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
|
||||
renderer->getMatrix(matrix);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong matrixPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
|
||||
renderer->concatMatrix(*matrix);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Drawing
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong bitmapPtr, jfloat left, jfloat top, jlong paintPtr) {
|
||||
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
|
||||
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
|
||||
// apply transform directly to canvas, so it affects shaders correctly
|
||||
renderer->save(SkCanvas::kMatrix_SaveFlag);
|
||||
renderer->translate(left, top);
|
||||
renderer->drawBitmap(bitmap, paint);
|
||||
renderer->restore();
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong bitmapPtr,
|
||||
float srcLeft, float srcTop, float srcRight, float srcBottom,
|
||||
float dstLeft, float dstTop, float dstRight, float dstBottom, jlong paintPtr) {
|
||||
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
|
||||
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
|
||||
dstLeft, dstTop, dstRight, dstBottom, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong bitmapPtr, jlong matrixPtr, jlong paintPtr) {
|
||||
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
|
||||
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
|
||||
// apply transform directly to canvas, so it affects shaders correctly
|
||||
renderer->save(SkCanvas::kMatrix_SaveFlag);
|
||||
renderer->concatMatrix(*matrix);
|
||||
renderer->drawBitmap(bitmap, paint);
|
||||
renderer->restore();
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jintArray colors, jint offset, jint stride,
|
||||
jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, jlong paintPtr) {
|
||||
// Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
|
||||
// correct the alphaType to kOpaque_SkAlphaType.
|
||||
const SkImageInfo info = SkImageInfo::Make(width, height,
|
||||
hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
|
||||
kPremul_SkAlphaType);
|
||||
SkBitmap* bitmap = new SkBitmap;
|
||||
if (!bitmap->tryAllocPixels(info)) {
|
||||
delete bitmap;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) {
|
||||
delete bitmap;
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
|
||||
// apply transform directly to canvas, so it affects shaders correctly
|
||||
renderer->save(SkCanvas::kMatrix_SaveFlag);
|
||||
renderer->translate(left, top);
|
||||
renderer->drawBitmapData(bitmap, paint);
|
||||
renderer->restore();
|
||||
|
||||
// Note - bitmap isn't deleted as DisplayListRenderer owns it now
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong bitmapPtr, jint meshWidth, jint meshHeight,
|
||||
jfloatArray vertices, jint offset, jintArray colors, jint colorOffset, jlong paintPtr) {
|
||||
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
|
||||
|
||||
jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
|
||||
jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
|
||||
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
|
||||
|
||||
if (vertices) env->ReleaseFloatArrayElements(vertices, verticesArray, 0);
|
||||
if (colors) env->ReleaseIntArrayElements(colors, colorsArray, 0);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong bitmapPtr, jlong patchPtr,
|
||||
float left, float top, float right, float bottom, jlong paintPtr) {
|
||||
@@ -432,29 +149,6 @@ static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
|
||||
renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jint color, jint modeHandle) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
|
||||
renderer->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
|
||||
jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawRect(left, top, right, bottom, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
|
||||
jfloat rx, jfloat ry, jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawRoundRectProps(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong leftPropPtr, jlong topPropPtr, jlong rightPropPtr,
|
||||
jlong bottomPropPtr, jlong rxPropPtr, jlong ryPropPtr, jlong paintPropPtr) {
|
||||
@@ -469,13 +163,6 @@ static void android_view_GLES20Canvas_drawRoundRectProps(JNIEnv* env, jobject cl
|
||||
renderer->drawRoundRect(leftProp, topProp, rightProp, bottomProp, rxProp, ryProp, paintProp);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawCircle(x, y, radius, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
@@ -486,22 +173,6 @@ static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz
|
||||
renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
|
||||
jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawOval(left, top, right, bottom, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
|
||||
jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
@@ -512,7 +183,7 @@ static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject cla
|
||||
SkRegion::Iterator it(*region);
|
||||
while (!it.done()) {
|
||||
const SkIRect& r = it.rect();
|
||||
renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
|
||||
renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, *paint);
|
||||
it.next();
|
||||
}
|
||||
} else {
|
||||
@@ -532,236 +203,6 @@ static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject cla
|
||||
}
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
jfloat* storage = env->GetFloatArrayElements(points, NULL);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawPoints(storage + offset, count, paint);
|
||||
env->ReleaseFloatArrayElements(points, storage, 0);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong pathPtr, jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawPath(path, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
jfloat* storage = env->GetFloatArrayElements(points, NULL);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
renderer->drawLines(storage + offset, count, paint);
|
||||
env->ReleaseFloatArrayElements(points, storage, 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Draw filters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void android_view_GLES20Canvas_setDrawFilter(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jlong filterPtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
SkDrawFilter* filter = reinterpret_cast<SkDrawFilter*>(filterPtr);
|
||||
renderer->setDrawFilter(filter);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Text
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class RenderTextFunctor {
|
||||
public:
|
||||
RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y,
|
||||
Paint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
|
||||
uirenderer::Rect& bounds)
|
||||
: layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
|
||||
pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
|
||||
void operator()(size_t start, size_t end) {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
glyphs[i] = layout.getGlyphId(i);
|
||||
pos[2 * i] = layout.getX(i);
|
||||
pos[2 * i + 1] = layout.getY(i);
|
||||
}
|
||||
size_t glyphsCount = end - start;
|
||||
int bytesCount = glyphsCount * sizeof(jchar);
|
||||
renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
|
||||
x, y, pos + 2 * start, paint, totalAdvance, bounds);
|
||||
}
|
||||
private:
|
||||
const Layout& layout;
|
||||
DisplayListRenderer* renderer;
|
||||
jfloat x;
|
||||
jfloat y;
|
||||
Paint* paint;
|
||||
uint16_t* glyphs;
|
||||
float* pos;
|
||||
float totalAdvance;
|
||||
uirenderer::Rect& bounds;
|
||||
};
|
||||
|
||||
static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout,
|
||||
jfloat x, jfloat y, Paint* paint) {
|
||||
size_t nGlyphs = layout->nGlyphs();
|
||||
float* pos = new float[nGlyphs * 2];
|
||||
uint16_t* glyphs = new uint16_t[nGlyphs];
|
||||
MinikinRect b;
|
||||
layout->getBounds(&b);
|
||||
android::uirenderer::Rect bounds(b.mLeft, b.mTop, b.mRight, b.mBottom);
|
||||
bounds.translate(x, y);
|
||||
float totalAdvance = layout->getAdvance();
|
||||
|
||||
RenderTextFunctor f(*layout, renderer, x, y, paint, glyphs, pos, totalAdvance, bounds);
|
||||
MinikinUtils::forFontRun(*layout, paint, f);
|
||||
delete[] glyphs;
|
||||
delete[] pos;
|
||||
}
|
||||
|
||||
static void renderText(DisplayListRenderer* renderer, const jchar* text, int count,
|
||||
jfloat x, jfloat y, int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
|
||||
Layout layout;
|
||||
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
|
||||
x += MinikinUtils::xOffsetForTextAlign(paint, layout);
|
||||
renderTextLayout(renderer, &layout, x, y, paint);
|
||||
}
|
||||
|
||||
class RenderTextOnPathFunctor {
|
||||
public:
|
||||
RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
|
||||
float vOffset, Paint* paint, SkPath* path)
|
||||
: layout(layout), renderer(renderer), 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);
|
||||
renderer->drawTextOnPath((const char*) glyphs, sizeof(glyphs), 1, path, x, y, paint);
|
||||
}
|
||||
}
|
||||
private:
|
||||
const Layout& layout;
|
||||
DisplayListRenderer* renderer;
|
||||
float hOffset;
|
||||
float vOffset;
|
||||
Paint* paint;
|
||||
SkPath* path;
|
||||
};
|
||||
|
||||
static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
|
||||
SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, Paint* paint,
|
||||
TypefaceImpl* typeface) {
|
||||
Layout layout;
|
||||
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
|
||||
hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
|
||||
Paint::Align align = paint->getTextAlign();
|
||||
paint->setTextAlign(Paint::kLeft_Align);
|
||||
|
||||
RenderTextOnPathFunctor f(layout, renderer, hOffset, vOffset, paint, path);
|
||||
MinikinUtils::forFontRun(layout, paint, f);
|
||||
paint->setTextAlign(align);
|
||||
}
|
||||
|
||||
static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
|
||||
jint start, jint count, jint contextCount, jfloat x, jfloat y,
|
||||
int bidiFlags, Paint* paint, TypefaceImpl* typeface) {
|
||||
Layout layout;
|
||||
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count, contextCount);
|
||||
x += MinikinUtils::xOffsetForTextAlign(paint, layout);
|
||||
renderTextLayout(renderer, &layout, x, y, paint);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jcharArray text, jint index, jint count,
|
||||
jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
jchar* textArray = env->GetCharArrayElements(text, NULL);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
|
||||
|
||||
renderText(renderer, textArray + index, count, x, y, bidiFlags, paint, typeface);
|
||||
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jstring text, jint start, jint end,
|
||||
jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
const jchar* textArray = env->GetStringChars(text, NULL);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
|
||||
|
||||
renderText(renderer, textArray + start, end - start, x, y, bidiFlags, paint, typeface);
|
||||
env->ReleaseStringChars(text, textArray);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jcharArray text, jint index, jint count,
|
||||
jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
|
||||
jlong typefacePtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
jchar* textArray = env->GetCharArrayElements(text, NULL);
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
|
||||
|
||||
renderTextOnPath(renderer, textArray + index, count, path,
|
||||
hOffset, vOffset, bidiFlags, paint, typeface);
|
||||
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jstring text, jint start, jint end,
|
||||
jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
|
||||
jlong typefacePtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
const jchar* textArray = env->GetStringChars(text, NULL);
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
|
||||
|
||||
renderTextOnPath(renderer, textArray + start, end - start, path,
|
||||
hOffset, vOffset, bidiFlags, paint, typeface);
|
||||
env->ReleaseStringChars(text, textArray);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jcharArray text, jint index, jint count,
|
||||
jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
|
||||
jlong paintPtr, jlong typefacePtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
jchar* textArray = env->GetCharArrayElements(text, NULL);
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
|
||||
|
||||
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
|
||||
renderTextRun(renderer, textArray + contextIndex, index - contextIndex,
|
||||
count, contextCount, x, y, bidiFlags, paint, typeface);
|
||||
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
|
||||
jlong rendererPtr, jstring text, jint start, jint end,
|
||||
jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
|
||||
jlong paintPtr, jlong typefacePtr) {
|
||||
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
|
||||
const jchar* textArray = env->GetStringChars(text, NULL);
|
||||
jint count = end - start;
|
||||
jint contextCount = contextEnd - contextStart;
|
||||
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
|
||||
|
||||
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
|
||||
renderTextRun(renderer, textArray + contextStart, start - contextStart,
|
||||
count, contextCount, x, y, bidiFlags, paint, typeface);
|
||||
env->ReleaseStringChars(text, textArray);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Display lists
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -830,88 +271,29 @@ const char* const kClassPathName = "android/view/GLES20Canvas";
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{ "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable },
|
||||
{ "nDestroyRenderer", "(J)V", (void*) android_view_GLES20Canvas_destroyRenderer },
|
||||
{ "nSetViewport", "(JII)V", (void*) android_view_GLES20Canvas_setViewport },
|
||||
{ "nSetHighContrastText","(JZ)V", (void*) android_view_GLES20Canvas_setHighContrastText },
|
||||
{ "nInsertReorderBarrier","(JZ)V", (void*) android_view_GLES20Canvas_insertReorderBarrier },
|
||||
{ "nPrepare", "(JZ)V", (void*) android_view_GLES20Canvas_prepare },
|
||||
{ "nPrepareDirty", "(JIIIIZ)V", (void*) android_view_GLES20Canvas_prepareDirty },
|
||||
{ "nPrepare", "(J)V", (void*) android_view_GLES20Canvas_prepare },
|
||||
{ "nPrepareDirty", "(JIIII)V", (void*) android_view_GLES20Canvas_prepareDirty },
|
||||
{ "nFinish", "(J)V", (void*) android_view_GLES20Canvas_finish },
|
||||
{ "nSetProperty", "(Ljava/lang/String;Ljava/lang/String;)V",
|
||||
{ "nSetProperty", "(Ljava/lang/String;Ljava/lang/String;)V",
|
||||
(void*) android_view_GLES20Canvas_setProperty },
|
||||
|
||||
{ "nCallDrawGLFunction", "(JJ)V", (void*) android_view_GLES20Canvas_callDrawGLFunction },
|
||||
|
||||
{ "nSave", "(JI)I", (void*) android_view_GLES20Canvas_save },
|
||||
{ "nRestore", "(J)V", (void*) android_view_GLES20Canvas_restore },
|
||||
{ "nRestoreToCount", "(JI)V", (void*) android_view_GLES20Canvas_restoreToCount },
|
||||
{ "nGetSaveCount", "(J)I", (void*) android_view_GLES20Canvas_getSaveCount },
|
||||
{ "nDrawPatch", "(JJJFFFFJ)V", (void*) android_view_GLES20Canvas_drawPatch },
|
||||
|
||||
{ "nSaveLayer", "(JFFFFJI)I", (void*) android_view_GLES20Canvas_saveLayer },
|
||||
{ "nSaveLayer", "(JJI)I", (void*) android_view_GLES20Canvas_saveLayerClip },
|
||||
{ "nSaveLayerAlpha", "(JFFFFII)I", (void*) android_view_GLES20Canvas_saveLayerAlpha },
|
||||
{ "nSaveLayerAlpha", "(JII)I", (void*) android_view_GLES20Canvas_saveLayerAlphaClip },
|
||||
|
||||
{ "nQuickReject", "(JFFFF)Z", (void*) android_view_GLES20Canvas_quickReject },
|
||||
{ "nClipRect", "(JFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
|
||||
{ "nClipRect", "(JIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
|
||||
{ "nClipPath", "(JJI)Z", (void*) android_view_GLES20Canvas_clipPath },
|
||||
{ "nClipRegion", "(JJI)Z", (void*) android_view_GLES20Canvas_clipRegion },
|
||||
|
||||
{ "nTranslate", "(JFF)V", (void*) android_view_GLES20Canvas_translate },
|
||||
{ "nRotate", "(JF)V", (void*) android_view_GLES20Canvas_rotate },
|
||||
{ "nScale", "(JFF)V", (void*) android_view_GLES20Canvas_scale },
|
||||
{ "nSkew", "(JFF)V", (void*) android_view_GLES20Canvas_skew },
|
||||
|
||||
{ "nSetMatrix", "(JJ)V", (void*) android_view_GLES20Canvas_setMatrix },
|
||||
{ "nGetMatrix", "(JJ)V", (void*) android_view_GLES20Canvas_getMatrix },
|
||||
{ "nConcatMatrix", "(JJ)V", (void*) android_view_GLES20Canvas_concatMatrix },
|
||||
|
||||
{ "nDrawBitmap", "(JJFFJ)V", (void*) android_view_GLES20Canvas_drawBitmap },
|
||||
{ "nDrawBitmap", "(JJFFFFFFFFJ)V",(void*) android_view_GLES20Canvas_drawBitmapRect },
|
||||
{ "nDrawBitmap", "(JJJJ)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
|
||||
{ "nDrawBitmap", "(J[IIIFFIIZJ)V", (void*) android_view_GLES20Canvas_drawBitmapData },
|
||||
|
||||
{ "nDrawBitmapMesh", "(JJII[FI[IIJ)V",(void*) android_view_GLES20Canvas_drawBitmapMesh },
|
||||
|
||||
{ "nDrawPatch", "(JJJFFFFJ)V", (void*) android_view_GLES20Canvas_drawPatch },
|
||||
|
||||
{ "nDrawColor", "(JII)V", (void*) android_view_GLES20Canvas_drawColor },
|
||||
{ "nDrawRect", "(JFFFFJ)V", (void*) android_view_GLES20Canvas_drawRect },
|
||||
{ "nDrawRects", "(JJJ)V", (void*) android_view_GLES20Canvas_drawRegionAsRects },
|
||||
{ "nDrawRoundRect", "(JFFFFFFJ)V", (void*) android_view_GLES20Canvas_drawRoundRect },
|
||||
{ "nDrawRoundRect", "(JJJJJJJJ)V", (void*) android_view_GLES20Canvas_drawRoundRectProps },
|
||||
{ "nDrawCircle", "(JFFFJ)V", (void*) android_view_GLES20Canvas_drawCircle },
|
||||
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_GLES20Canvas_drawCircleProps },
|
||||
{ "nDrawOval", "(JFFFFJ)V", (void*) android_view_GLES20Canvas_drawOval },
|
||||
{ "nDrawArc", "(JFFFFFFZJ)V", (void*) android_view_GLES20Canvas_drawArc },
|
||||
{ "nDrawPoints", "(J[FIIJ)V", (void*) android_view_GLES20Canvas_drawPoints },
|
||||
|
||||
{ "nDrawPath", "(JJJ)V", (void*) android_view_GLES20Canvas_drawPath },
|
||||
{ "nDrawLines", "(J[FIIJ)V", (void*) android_view_GLES20Canvas_drawLines },
|
||||
|
||||
{ "nSetDrawFilter", "(JJ)V", (void*) android_view_GLES20Canvas_setDrawFilter },
|
||||
|
||||
{ "nDrawText", "(J[CIIFFIJJ)V", (void*) android_view_GLES20Canvas_drawTextArray },
|
||||
{ "nDrawText", "(JLjava/lang/String;IIFFIJJ)V",
|
||||
(void*) android_view_GLES20Canvas_drawText },
|
||||
|
||||
{ "nDrawTextOnPath", "(J[CIIJFFIJJ)V", (void*) android_view_GLES20Canvas_drawTextArrayOnPath },
|
||||
{ "nDrawTextOnPath", "(JLjava/lang/String;IIJFFIJJ)V",
|
||||
(void*) android_view_GLES20Canvas_drawTextOnPath },
|
||||
|
||||
{ "nDrawTextRun", "(J[CIIIIFFZJJ)V", (void*) android_view_GLES20Canvas_drawTextRunArray },
|
||||
{ "nDrawTextRun", "(JLjava/lang/String;IIIIFFZJJ)V",
|
||||
(void*) android_view_GLES20Canvas_drawTextRun },
|
||||
|
||||
{ "nGetClipBounds", "(JLandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds },
|
||||
|
||||
{ "nFinishRecording", "(J)J", (void*) android_view_GLES20Canvas_finishRecording },
|
||||
{ "nDrawRenderNode", "(JJI)V", (void*) android_view_GLES20Canvas_drawRenderNode },
|
||||
|
||||
{ "nCreateDisplayListRenderer", "()J", (void*) android_view_GLES20Canvas_createDisplayListRenderer },
|
||||
|
||||
{ "nDrawLayer", "(JJFF)V", (void*) android_view_GLES20Canvas_drawLayer },
|
||||
{ "nDrawLayer", "(JJFF)V", (void*) android_view_GLES20Canvas_drawLayer },
|
||||
|
||||
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth },
|
||||
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight },
|
||||
|
||||
@@ -44,8 +44,12 @@ import javax.microedition.khronos.opengles.GL;
|
||||
*/
|
||||
public class Canvas {
|
||||
|
||||
// assigned in constructors or setBitmap, freed in finalizer
|
||||
private long mNativeCanvasWrapper;
|
||||
/**
|
||||
* Should only be assigned in constructors (or setBitmap if software canvas),
|
||||
* freed in finalizer.
|
||||
* @hide
|
||||
*/
|
||||
protected long mNativeCanvasWrapper;
|
||||
|
||||
/** @hide */
|
||||
public long getNativeCanvasWrapper() {
|
||||
@@ -1619,6 +1623,9 @@ public class Canvas {
|
||||
int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
|
||||
@NonNull Paint paint) {
|
||||
checkRange(verts.length, vertOffset, vertexCount);
|
||||
if (isHardwareAccelerated()) {
|
||||
return;
|
||||
}
|
||||
if (texs != null) {
|
||||
checkRange(texs.length, texOffset, vertexCount);
|
||||
}
|
||||
|
||||
@@ -131,15 +131,23 @@ public:
|
||||
const float* vertices, const int* colors, const SkPaint* paint) = 0;
|
||||
|
||||
// Text
|
||||
virtual void drawText(const uint16_t* text, const float* positions, int count,
|
||||
/**
|
||||
* drawText: count is of glyphs
|
||||
* totalAdvance is ignored in software renderering, used by hardware renderer for
|
||||
* text decorations (underlines, strikethroughs).
|
||||
*/
|
||||
virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
|
||||
const SkPaint& paint, float x, float y,
|
||||
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom) = 0;
|
||||
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
|
||||
float totalAdvance) = 0;
|
||||
/** drawPosText: count is of UTF16 characters, posCount is floats (2 * glyphs) */
|
||||
virtual void drawPosText(const uint16_t* text, const float* positions, int count,
|
||||
int posCount, const SkPaint& paint) = 0;
|
||||
/** drawTextOnPath: count is of glyphs */
|
||||
virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
|
||||
float hOffset, float vOffset, const SkPaint& paint) = 0;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Specifies if the positions passed to ::drawText are absolute or relative
|
||||
* to the (x,y) value provided.
|
||||
*
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "RenderState.h"
|
||||
#include "UvMapper.h"
|
||||
#include "utils/LinearAllocator.h"
|
||||
#include "utils/PaintUtils.h"
|
||||
|
||||
// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
|
||||
#define OP_LOGS(s) OP_LOG("%s", (s))
|
||||
@@ -203,7 +204,7 @@ protected:
|
||||
if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
|
||||
return false;
|
||||
}
|
||||
if (Renderer::isBlendedColorFilter(mPaint->getColorFilter())) {
|
||||
if (PaintUtils::isBlendedColorFilter(mPaint->getColorFilter())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "DisplayListOp.h"
|
||||
#include "DisplayListRenderer.h"
|
||||
#include "RenderNode.h"
|
||||
#include "utils/PaintUtils.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
@@ -63,7 +64,7 @@ DisplayListData* DisplayListRenderer::finishRecording() {
|
||||
}
|
||||
|
||||
void DisplayListRenderer::prepareDirty(float left, float top,
|
||||
float right, float bottom, bool opaque) {
|
||||
float right, float bottom) {
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(mDisplayListData,
|
||||
"prepareDirty called a second time during a recording!");
|
||||
@@ -72,7 +73,7 @@ void DisplayListRenderer::prepareDirty(float left, float top,
|
||||
mState.initializeSaveStack(0, 0, mState.getWidth(), mState.getHeight(), Vector3());
|
||||
|
||||
mDeferredBarrierType = kBarrier_InOrder;
|
||||
mState.setDirtyClip(opaque);
|
||||
mState.setDirtyClip(false);
|
||||
mRestoreSaveCount = -1;
|
||||
}
|
||||
|
||||
@@ -94,9 +95,9 @@ void DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
|
||||
mDisplayListData->functors.add(functor);
|
||||
}
|
||||
|
||||
int DisplayListRenderer::save(int flags) {
|
||||
addStateOp(new (alloc()) SaveOp(flags));
|
||||
return mState.save(flags);
|
||||
int DisplayListRenderer::save(SkCanvas::SaveFlags flags) {
|
||||
addStateOp(new (alloc()) SaveOp((int) flags));
|
||||
return mState.save((int) flags);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::restore() {
|
||||
@@ -117,22 +118,21 @@ void DisplayListRenderer::restoreToCount(int saveCount) {
|
||||
}
|
||||
|
||||
int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint, int flags) {
|
||||
const SkPaint* paint, SkCanvas::SaveFlags flags) {
|
||||
// force matrix/clip isolation for layer
|
||||
flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
|
||||
|
||||
paint = refPaint(paint);
|
||||
addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, flags));
|
||||
return mState.save(flags);
|
||||
addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, (int) flags));
|
||||
return mState.save((int) flags);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::translate(float dx, float dy, float dz) {
|
||||
// ignore dz, not used at defer time
|
||||
void DisplayListRenderer::translate(float dx, float dy) {
|
||||
mHasDeferredTranslate = true;
|
||||
mTranslateX += dx;
|
||||
mTranslateY += dy;
|
||||
flushRestoreToCount();
|
||||
mState.translate(dx, dy, dz);
|
||||
mState.translate(dx, dy, 0.0f);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::rotate(float degrees) {
|
||||
@@ -155,11 +155,27 @@ void DisplayListRenderer::setMatrix(const SkMatrix& matrix) {
|
||||
mState.setMatrix(matrix);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::concatMatrix(const SkMatrix& matrix) {
|
||||
void DisplayListRenderer::concat(const SkMatrix& matrix) {
|
||||
addStateOp(new (alloc()) ConcatMatrixOp(matrix));
|
||||
mState.concatMatrix(matrix);
|
||||
}
|
||||
|
||||
bool DisplayListRenderer::getClipBounds(SkRect* outRect) const {
|
||||
Rect bounds = mState.getLocalClipBounds();
|
||||
*outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
|
||||
return !(outRect->isEmpty());
|
||||
}
|
||||
|
||||
bool DisplayListRenderer::quickRejectRect(float left, float top, float right, float bottom) const {
|
||||
return mState.quickRejectConservative(left, top, right, bottom);
|
||||
}
|
||||
|
||||
bool DisplayListRenderer::quickRejectPath(const SkPath& path) const {
|
||||
SkRect bounds = path.getBounds();
|
||||
return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
|
||||
}
|
||||
|
||||
|
||||
bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
|
||||
SkRegion::Op op) {
|
||||
addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
|
||||
@@ -201,23 +217,50 @@ void DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* pain
|
||||
addDrawOp(new (alloc()) DrawBitmapOp(bitmap, paint));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
|
||||
void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float left, float top,
|
||||
const SkPaint* paint) {
|
||||
save(SkCanvas::kMatrix_SaveFlag);
|
||||
translate(left, top);
|
||||
drawBitmap(&bitmap, paint);
|
||||
restore();
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
|
||||
const SkPaint* paint) {
|
||||
if (matrix.isIdentity()) {
|
||||
drawBitmap(&bitmap, paint);
|
||||
} else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))) {
|
||||
// SkMatrix::isScaleTranslate() not available in L
|
||||
SkRect src;
|
||||
SkRect dst;
|
||||
bitmap.getBounds(&src);
|
||||
matrix.mapRect(&dst, src);
|
||||
drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
|
||||
dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
|
||||
} else {
|
||||
save(SkCanvas::kMatrix_SaveFlag);
|
||||
concat(matrix);
|
||||
drawBitmap(&bitmap, paint);
|
||||
restore();
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
|
||||
float srcRight, float srcBottom, float dstLeft, float dstTop,
|
||||
float dstRight, float dstBottom, const SkPaint* paint) {
|
||||
if (srcLeft == 0 && srcTop == 0
|
||||
&& srcRight == bitmap->width() && srcBottom == bitmap->height()
|
||||
&& srcRight == bitmap.width() && srcBottom == bitmap.height()
|
||||
&& (srcBottom - srcTop == dstBottom - dstTop)
|
||||
&& (srcRight - srcLeft == dstRight - dstLeft)) {
|
||||
// transform simple rect to rect drawing case into position bitmap ops, since they merge
|
||||
save(SkCanvas::kMatrix_SaveFlag);
|
||||
translate(dstLeft, dstTop);
|
||||
drawBitmap(bitmap, paint);
|
||||
drawBitmap(&bitmap, paint);
|
||||
restore();
|
||||
} else {
|
||||
bitmap = refBitmap(bitmap);
|
||||
paint = refPaint(paint);
|
||||
|
||||
addDrawOp(new (alloc()) DrawBitmapRectOp(bitmap,
|
||||
addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(&bitmap),
|
||||
srcLeft, srcTop, srcRight, srcBottom,
|
||||
dstLeft, dstTop, dstRight, dstBottom, paint));
|
||||
}
|
||||
@@ -230,16 +273,15 @@ void DisplayListRenderer::drawBitmapData(const SkBitmap* bitmap, const SkPaint*
|
||||
addDrawOp(new (alloc()) DrawBitmapDataOp(bitmap, paint));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
|
||||
void DisplayListRenderer::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
|
||||
const float* vertices, const int* colors, const SkPaint* paint) {
|
||||
int vertexCount = (meshWidth + 1) * (meshHeight + 1);
|
||||
bitmap = refBitmap(bitmap);
|
||||
vertices = refBuffer<float>(vertices, vertexCount * 2); // 2 floats per vertex
|
||||
paint = refPaint(paint);
|
||||
colors = refBuffer<int>(colors, vertexCount); // 1 color per vertex
|
||||
|
||||
addDrawOp(new (alloc()) DrawBitmapMeshOp(bitmap, meshWidth, meshHeight,
|
||||
vertices, colors, paint));
|
||||
addDrawOp(new (alloc()) DrawBitmapMeshOp(refBitmap(&bitmap), meshWidth, meshHeight,
|
||||
vertices, colors, paint));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
|
||||
@@ -255,16 +297,22 @@ void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
|
||||
addDrawOp(new (alloc()) DrawColorOp(color, mode));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawPaint(const SkPaint& paint) {
|
||||
SkRect bounds;
|
||||
if (getClipBounds(&bounds)) {
|
||||
drawRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, paint);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint) {
|
||||
paint = refPaint(paint);
|
||||
addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, paint));
|
||||
const SkPaint& paint) {
|
||||
addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, refPaint(&paint)));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
|
||||
float rx, float ry, const SkPaint* paint) {
|
||||
paint = refPaint(paint);
|
||||
addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, paint));
|
||||
float rx, float ry, const SkPaint& paint) {
|
||||
addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, refPaint(&paint)));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawRoundRect(
|
||||
@@ -283,9 +331,8 @@ void DisplayListRenderer::drawRoundRect(
|
||||
&right->value, &bottom->value, &rx->value, &ry->value, &paint->value));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawCircle(float x, float y, float radius, const SkPaint* paint) {
|
||||
paint = refPaint(paint);
|
||||
addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, paint));
|
||||
void DisplayListRenderer::drawCircle(float x, float y, float radius, const SkPaint& paint) {
|
||||
addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, refPaint(&paint)));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
|
||||
@@ -299,65 +346,56 @@ void DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyP
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint) {
|
||||
paint = refPaint(paint);
|
||||
addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, paint));
|
||||
const SkPaint& paint) {
|
||||
addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, refPaint(&paint)));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
|
||||
if (fabs(sweepAngle) >= 360.0f) {
|
||||
drawOval(left, top, right, bottom, paint);
|
||||
} else {
|
||||
paint = refPaint(paint);
|
||||
addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
|
||||
startAngle, sweepAngle, useCenter, paint));
|
||||
startAngle, sweepAngle, useCenter, refPaint(&paint)));
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
|
||||
path = refPath(path);
|
||||
paint = refPaint(paint);
|
||||
|
||||
addDrawOp(new (alloc()) DrawPathOp(path, paint));
|
||||
void DisplayListRenderer::drawPath(const SkPath& path, const SkPaint& paint) {
|
||||
addDrawOp(new (alloc()) DrawPathOp(refPath(&path), refPaint(&paint)));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
|
||||
void DisplayListRenderer::drawLines(const float* points, int count, const SkPaint& paint) {
|
||||
points = refBuffer<float>(points, count);
|
||||
paint = refPaint(paint);
|
||||
|
||||
addDrawOp(new (alloc()) DrawLinesOp(points, count, paint));
|
||||
addDrawOp(new (alloc()) DrawLinesOp(points, count, refPaint(&paint)));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
|
||||
void DisplayListRenderer::drawPoints(const float* points, int count, const SkPaint& paint) {
|
||||
points = refBuffer<float>(points, count);
|
||||
paint = refPaint(paint);
|
||||
|
||||
addDrawOp(new (alloc()) DrawPointsOp(points, count, paint));
|
||||
addDrawOp(new (alloc()) DrawPointsOp(points, count, refPaint(&paint)));
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
|
||||
const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
|
||||
if (!text || count <= 0) return;
|
||||
void DisplayListRenderer::drawTextOnPath(const uint16_t* glyphs, int count,
|
||||
const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) {
|
||||
if (!glyphs || count <= 0) return;
|
||||
|
||||
text = refText(text, bytesCount);
|
||||
path = refPath(path);
|
||||
paint = refPaint(paint);
|
||||
|
||||
DrawOp* op = new (alloc()) DrawTextOnPathOp(text, bytesCount, count, path,
|
||||
hOffset, vOffset, paint);
|
||||
int bytesCount = 2 * count;
|
||||
DrawOp* op = new (alloc()) DrawTextOnPathOp(refText((const char*) glyphs, bytesCount),
|
||||
bytesCount, count, refPath(&path),
|
||||
hOffset, vOffset, refPaint(&paint));
|
||||
addDrawOp(op);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
|
||||
const float* positions, const SkPaint* paint) {
|
||||
void DisplayListRenderer::drawPosText(const uint16_t* text, const float* positions,
|
||||
int count, int posCount, const SkPaint& paint) {
|
||||
if (!text || count <= 0) return;
|
||||
|
||||
text = refText(text, bytesCount);
|
||||
int bytesCount = 2 * count;
|
||||
positions = refBuffer<float>(positions, count * 2);
|
||||
paint = refPaint(paint);
|
||||
|
||||
DrawOp* op = new (alloc()) DrawPosTextOp(text, bytesCount, count, positions, paint);
|
||||
DrawOp* op = new (alloc()) DrawPosTextOp(refText((const char*) text, bytesCount),
|
||||
bytesCount, count, positions, refPaint(&paint));
|
||||
addDrawOp(op);
|
||||
}
|
||||
|
||||
@@ -371,40 +409,41 @@ static void simplifyPaint(int color, SkPaint* paint) {
|
||||
paint->setLooper(NULL);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
float x, float y, const float* positions, const SkPaint* paint,
|
||||
float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
|
||||
void DisplayListRenderer::drawText(const uint16_t* glyphs, const float* positions,
|
||||
int count, const SkPaint& paint, float x, float y,
|
||||
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
|
||||
float totalAdvance) {
|
||||
|
||||
if (!text || count <= 0 || paintWillNotDrawText(*paint)) return;
|
||||
if (!glyphs || count <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
|
||||
|
||||
text = refText(text, bytesCount);
|
||||
int bytesCount = count * 2;
|
||||
const char* text = refText((const char*) glyphs, bytesCount);
|
||||
positions = refBuffer<float>(positions, count * 2);
|
||||
Rect bounds(boundsLeft, boundsTop, boundsRight, boundsBottom);
|
||||
|
||||
if (CC_UNLIKELY(mHighContrastText)) {
|
||||
// high contrast draw path
|
||||
int color = paint->getColor();
|
||||
int color = paint.getColor();
|
||||
int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
|
||||
bool darken = channelSum < (128 * 3);
|
||||
|
||||
// outline
|
||||
SkPaint* outlinePaint = copyPaint(paint);
|
||||
SkPaint* outlinePaint = copyPaint(&paint);
|
||||
simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, outlinePaint);
|
||||
outlinePaint->setStyle(SkPaint::kStrokeAndFill_Style);
|
||||
addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
|
||||
x, y, positions, outlinePaint, totalAdvance, bounds)); // bounds?
|
||||
|
||||
// inner
|
||||
SkPaint* innerPaint = copyPaint(paint);
|
||||
SkPaint* innerPaint = copyPaint(&paint);
|
||||
simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, innerPaint);
|
||||
innerPaint->setStyle(SkPaint::kFill_Style);
|
||||
addDrawOp(new (alloc()) DrawTextOp(text, bytesCount, count,
|
||||
x, y, positions, innerPaint, totalAdvance, bounds));
|
||||
} else {
|
||||
// standard draw path
|
||||
paint = refPaint(paint);
|
||||
|
||||
DrawOp* op = new (alloc()) DrawTextOp(text, bytesCount, count,
|
||||
x, y, positions, paint, totalAdvance, bounds);
|
||||
x, y, positions, refPaint(&paint), totalAdvance, bounds);
|
||||
addDrawOp(op);
|
||||
}
|
||||
}
|
||||
@@ -477,7 +516,7 @@ size_t DisplayListRenderer::addStateOp(StateOp* op) {
|
||||
size_t DisplayListRenderer::addDrawOp(DrawOp* op) {
|
||||
Rect localBounds;
|
||||
if (op->getLocalBounds(localBounds)) {
|
||||
bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
|
||||
bool rejected = quickRejectRect(localBounds.left, localBounds.top,
|
||||
localBounds.right, localBounds.bottom);
|
||||
op->setQuickRejected(rejected);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <SkTLazy.h>
|
||||
#include <cutils/compiler.h>
|
||||
|
||||
#include <private/graphics/Canvas.h>
|
||||
|
||||
#include "CanvasState.h"
|
||||
#include "DisplayList.h"
|
||||
#include "DisplayListLogBuffer.h"
|
||||
@@ -62,7 +64,7 @@ class StateOp;
|
||||
/**
|
||||
* Records drawing commands in a display list for later playback into an OpenGLRenderer.
|
||||
*/
|
||||
class ANDROID_API DisplayListRenderer: public Renderer, public CanvasStateClient {
|
||||
class ANDROID_API DisplayListRenderer: public Canvas, public CanvasStateClient {
|
||||
public:
|
||||
DisplayListRenderer();
|
||||
virtual ~DisplayListRenderer();
|
||||
@@ -72,126 +74,177 @@ public:
|
||||
DisplayListData* finishRecording();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Frame state operations
|
||||
// HWUI Frame state operations
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void prepareDirty(float left, float top, float right,
|
||||
float bottom, bool opaque) override;
|
||||
virtual void prepare(bool opaque) override {
|
||||
prepareDirty(0.0f, 0.0f, mState.getWidth(), mState.getHeight(), opaque);
|
||||
}
|
||||
virtual bool finish() override;
|
||||
virtual void interrupt();
|
||||
virtual void resume();
|
||||
|
||||
void prepareDirty(float left, float top, float right, float bottom);
|
||||
void prepare() { prepareDirty(0.0f, 0.0f, width(), height()); }
|
||||
bool finish();
|
||||
void interrupt();
|
||||
void resume();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations
|
||||
// HWUI Canvas state operations
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void setViewport(int width, int height) override { mState.setViewport(width, height); }
|
||||
|
||||
// Save (layer)
|
||||
virtual int getSaveCount() const override { return mState.getSaveCount(); }
|
||||
virtual int save(int flags) override;
|
||||
virtual void restore() override;
|
||||
virtual void restoreToCount(int saveCount) override;
|
||||
virtual int saveLayer(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint, int flags) override;
|
||||
void setViewport(int width, int height) { mState.setViewport(width, height); }
|
||||
|
||||
// Matrix
|
||||
virtual void getMatrix(SkMatrix* outMatrix) const override { mState.getMatrix(outMatrix); }
|
||||
|
||||
virtual void translate(float dx, float dy, float dz = 0.0f) override;
|
||||
virtual void rotate(float degrees) override;
|
||||
virtual void scale(float sx, float sy) override;
|
||||
virtual void skew(float sx, float sy) override;
|
||||
|
||||
virtual void setMatrix(const SkMatrix& matrix) override;
|
||||
virtual void concatMatrix(const SkMatrix& matrix) override;
|
||||
|
||||
// Clip
|
||||
virtual bool clipRect(float left, float top, float right, float bottom,
|
||||
SkRegion::Op op) override;
|
||||
virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
|
||||
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
|
||||
|
||||
// Misc
|
||||
virtual void setDrawFilter(SkDrawFilter* filter) override;
|
||||
virtual const Rect& getLocalClipBounds() const override { return mState.getLocalClipBounds(); }
|
||||
const Rect& getRenderTargetClipBounds() const { return mState.getRenderTargetClipBounds(); }
|
||||
virtual bool quickRejectConservative(float left, float top,
|
||||
float right, float bottom) const override {
|
||||
return mState.quickRejectConservative(left, top, right, bottom);
|
||||
}
|
||||
|
||||
bool isCurrentTransformSimple() {
|
||||
return mState.currentTransform()->isSimple();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas draw operations
|
||||
// HWUI Canvas draw operations
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void drawColor(int color, SkXfermode::Mode mode) override;
|
||||
|
||||
// Bitmap-based
|
||||
virtual void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) override;
|
||||
virtual void drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
|
||||
float srcRight, float srcBottom, float dstLeft, float dstTop,
|
||||
float dstRight, float dstBottom, const SkPaint* paint) override;
|
||||
virtual void drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint) override;
|
||||
virtual void drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
|
||||
const float* vertices, const int* colors, const SkPaint* paint) override;
|
||||
virtual void drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
|
||||
float left, float top, float right, float bottom, const SkPaint* paint) override;
|
||||
void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
|
||||
// TODO: move drawBitmapData() to Canvas.h
|
||||
void drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint);
|
||||
// TODO: move drawPatch() to Canvas.h
|
||||
void drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
|
||||
float left, float top, float right, float bottom, const SkPaint* paint);
|
||||
|
||||
// Shapes
|
||||
virtual void drawRect(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint) override;
|
||||
virtual void drawRects(const float* rects, int count, const SkPaint* paint) override;
|
||||
virtual void drawRoundRect(float left, float top, float right, float bottom,
|
||||
float rx, float ry, const SkPaint* paint) override;
|
||||
virtual void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
|
||||
void drawRects(const float* rects, int count, const SkPaint* paint);
|
||||
void drawRoundRect(CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top,
|
||||
CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom,
|
||||
CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry,
|
||||
CanvasPropertyPaint* paint);
|
||||
virtual void drawCircle(float x, float y, float radius, const SkPaint* paint) override;
|
||||
virtual void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
|
||||
void drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
|
||||
CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
|
||||
virtual void drawOval(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint) override;
|
||||
virtual void drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) override;
|
||||
virtual void drawPath(const SkPath* path, const SkPaint* paint) override;
|
||||
virtual void drawLines(const float* points, int count, const SkPaint* paint) override;
|
||||
virtual void drawPoints(const float* points, int count, const SkPaint* paint) override;
|
||||
|
||||
// Text
|
||||
virtual void drawText(const char* text, int bytesCount, int count, float x, float y,
|
||||
const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
|
||||
DrawOpMode drawOpMode = kDrawOpMode_Immediate) override;
|
||||
virtual void drawTextOnPath(const char* text, int bytesCount, int count, const SkPath* path,
|
||||
float hOffset, float vOffset, const SkPaint* paint) override;
|
||||
virtual void drawPosText(const char* text, int bytesCount, int count,
|
||||
const float* positions, const SkPaint* paint) override;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas draw operations - special
|
||||
// HWUI Canvas draw operations - special
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void drawLayer(DeferredLayerUpdater* layerHandle, float x, float y);
|
||||
virtual void drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags) override;
|
||||
void drawLayer(DeferredLayerUpdater* layerHandle, float x, float y);
|
||||
void drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags);
|
||||
|
||||
// TODO: rename for consistency
|
||||
virtual void callDrawGLFunction(Functor* functor, Rect& dirty) override;
|
||||
void callDrawGLFunction(Functor* functor, Rect& dirty);
|
||||
|
||||
void setHighContrastText(bool highContrastText) {
|
||||
mHighContrastText = highContrastText;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CanvasState callbacks
|
||||
// CanvasStateClient interface
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void onViewportInitialized() override { }
|
||||
virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) override { }
|
||||
virtual GLuint onGetTargetFbo() const override { return -1; }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// android/graphics/Canvas interface
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual SkCanvas* getSkCanvas() {
|
||||
LOG_ALWAYS_FATAL("DisplayListRenderer has no SkCanvas");
|
||||
return NULL;
|
||||
}
|
||||
virtual void setBitmap(SkBitmap* bitmap, bool copyState) {
|
||||
LOG_ALWAYS_FATAL("DisplayListRenderer is not backed by a bitmap.");
|
||||
}
|
||||
|
||||
virtual bool isOpaque() { return false; }
|
||||
virtual int width() { return mState.getWidth(); }
|
||||
virtual int height() { return mState.getHeight(); }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// android/graphics/Canvas state operations
|
||||
// ----------------------------------------------------------------------------
|
||||
// Save (layer)
|
||||
virtual int getSaveCount() const { return mState.getSaveCount(); }
|
||||
virtual int save(SkCanvas::SaveFlags flags);
|
||||
virtual void restore();
|
||||
virtual void restoreToCount(int saveCount);
|
||||
|
||||
virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
|
||||
SkCanvas::SaveFlags flags);
|
||||
virtual int saveLayerAlpha(float left, float top, float right, float bottom,
|
||||
int alpha, SkCanvas::SaveFlags flags) {
|
||||
SkPaint paint;
|
||||
paint.setAlpha(alpha);
|
||||
return saveLayer(left, top, right, bottom, &paint, flags);
|
||||
}
|
||||
|
||||
// Matrix
|
||||
virtual void getMatrix(SkMatrix* outMatrix) const { mState.getMatrix(outMatrix); }
|
||||
virtual void setMatrix(const SkMatrix& matrix);
|
||||
|
||||
virtual void concat(const SkMatrix& matrix);
|
||||
virtual void rotate(float degrees);
|
||||
virtual void scale(float sx, float sy);
|
||||
virtual void skew(float sx, float sy);
|
||||
virtual void translate(float dx, float dy);
|
||||
|
||||
// Clip
|
||||
virtual bool getClipBounds(SkRect* outRect) const;
|
||||
virtual bool quickRejectRect(float left, float top, float right, float bottom) const;
|
||||
virtual bool quickRejectPath(const SkPath& path) const;
|
||||
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||
virtual bool clipPath(const SkPath* path, SkRegion::Op op);
|
||||
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
|
||||
|
||||
// Misc
|
||||
virtual SkDrawFilter* getDrawFilter() { return mDrawFilter.get(); }
|
||||
virtual void setDrawFilter(SkDrawFilter* filter);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// android/graphics/Canvas draw operations
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void drawColor(int color, SkXfermode::Mode mode);
|
||||
virtual void drawPaint(const SkPaint& paint);
|
||||
|
||||
// Geometry
|
||||
virtual void drawPoint(float x, float y, const SkPaint& paint) {
|
||||
float points[2] = { x, y };
|
||||
drawPoints(points, 2, paint);
|
||||
}
|
||||
virtual void drawPoints(const float* points, int count, const SkPaint& paint);
|
||||
virtual void drawLine(float startX, float startY, float stopX, float stopY,
|
||||
const SkPaint& paint) {
|
||||
float points[4] = { startX, startY, stopX, stopY };
|
||||
drawLines(points, 4, paint);
|
||||
}
|
||||
virtual void drawLines(const float* points, int count, const SkPaint& paint);
|
||||
virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint);
|
||||
virtual void drawRoundRect(float left, float top, float right, float bottom,
|
||||
float rx, float ry, const SkPaint& paint);
|
||||
virtual void drawCircle(float x, float y, float radius, const SkPaint& paint);
|
||||
virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint);
|
||||
virtual void drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint);
|
||||
virtual void drawPath(const SkPath& path, const SkPaint& paint);
|
||||
virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
|
||||
const float* verts, const float* tex, const int* colors,
|
||||
const uint16_t* indices, int indexCount, const SkPaint& paint)
|
||||
{ LOG_ALWAYS_FATAL("DisplayListRenderer does not support drawVertices()"); }
|
||||
|
||||
// Bitmap-based
|
||||
virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint);
|
||||
virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
|
||||
const SkPaint* paint);
|
||||
virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
|
||||
float srcRight, float srcBottom, float dstLeft, float dstTop,
|
||||
float dstRight, float dstBottom, const SkPaint* paint);
|
||||
virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
|
||||
const float* vertices, const int* colors, const SkPaint* paint);
|
||||
|
||||
// Text
|
||||
virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
|
||||
const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
|
||||
float boundsRight, float boundsBottom, float totalAdvance);
|
||||
virtual void drawPosText(const uint16_t* text, const float* positions, int count,
|
||||
int posCount, const SkPaint& paint);
|
||||
virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
|
||||
float hOffset, float vOffset, const SkPaint& paint);
|
||||
virtual bool drawTextAbsolutePos() const { return false; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
CanvasState mState;
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "Vector.h"
|
||||
#include "VertexBuffer.h"
|
||||
#include "utils/GLUtils.h"
|
||||
#include "utils/PaintUtils.h"
|
||||
#include "utils/TraceUtils.h"
|
||||
|
||||
#if DEBUG_DETAILED_EVENTS
|
||||
@@ -1667,8 +1668,10 @@ void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) {
|
||||
// argb=1,0,0,0
|
||||
accountForClear(mode);
|
||||
// TODO: check shader blending, once we have shader drawing support for layers.
|
||||
bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f ||
|
||||
(mColorSet && mColorA < 1.0f) || isBlendedColorFilter(layer->getColorFilter());
|
||||
bool blend = layer->isBlend()
|
||||
|| getLayerAlpha(layer) < 1.0f
|
||||
|| (mColorSet && mColorA < 1.0f)
|
||||
|| PaintUtils::isBlendedColorFilter(layer->getColorFilter());
|
||||
chooseBlending(blend, mode, mDescription, swapSrcDst);
|
||||
}
|
||||
|
||||
@@ -1679,7 +1682,7 @@ void OpenGLRenderer::setupDrawBlending(const SkPaint* paint, bool blend, bool sw
|
||||
accountForClear(mode);
|
||||
blend |= (mColorSet && mColorA < 1.0f) ||
|
||||
(getShader(paint) && !getShader(paint)->isOpaque()) ||
|
||||
isBlendedColorFilter(getColorFilter(paint));
|
||||
PaintUtils::isBlendedColorFilter(getColorFilter(paint));
|
||||
chooseBlending(blend, mode, mDescription, swapSrcDst);
|
||||
}
|
||||
|
||||
@@ -2476,7 +2479,7 @@ void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bot
|
||||
float rx, float ry, const SkPaint* p) {
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(left, top, right, bottom, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
|| PaintUtils::paintWillNotDraw(*p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2495,7 +2498,7 @@ void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bot
|
||||
void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
|| PaintUtils::paintWillNotDraw(*p)) {
|
||||
return;
|
||||
}
|
||||
if (p->getPathEffect() != nullptr) {
|
||||
@@ -2517,7 +2520,7 @@ void OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
|
||||
const SkPaint* p) {
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(left, top, right, bottom, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
|| PaintUtils::paintWillNotDraw(*p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2540,7 +2543,7 @@ void OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(left, top, right, bottom, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
|| PaintUtils::paintWillNotDraw(*p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2575,7 +2578,7 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
|
||||
const SkPaint* p) {
|
||||
if (mState.currentlyIgnored()
|
||||
|| quickRejectSetupScissor(left, top, right, bottom, p)
|
||||
|| paintWillNotDraw(*p)) {
|
||||
|| PaintUtils::paintWillNotDraw(*p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2657,7 +2660,8 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
|
||||
|
||||
bool OpenGLRenderer::canSkipText(const SkPaint* paint) const {
|
||||
float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * currentSnapshot()->alpha;
|
||||
return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
|
||||
return MathUtils::isZero(alpha)
|
||||
&& PaintUtils::getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "UvMapper.h"
|
||||
#include "Vertex.h"
|
||||
#include "Caches.h"
|
||||
#include "utils/PaintUtils.h"
|
||||
|
||||
class SkShader;
|
||||
|
||||
@@ -274,7 +275,7 @@ public:
|
||||
|
||||
static inline SkXfermode::Mode getXfermodeDirect(const SkPaint* paint) {
|
||||
if (!paint) return SkXfermode::kSrcOver_Mode;
|
||||
return getXfermode(paint->getXfermode());
|
||||
return PaintUtils::getXfermode(paint->getXfermode());
|
||||
}
|
||||
|
||||
static inline int getAlphaDirect(const SkPaint* paint) {
|
||||
|
||||
@@ -57,40 +57,6 @@ class ANDROID_API Renderer {
|
||||
public:
|
||||
virtual ~Renderer() {}
|
||||
|
||||
/**
|
||||
* Safely retrieves the mode from the specified xfermode. If the specified
|
||||
* xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
|
||||
*/
|
||||
static inline SkXfermode::Mode getXfermode(SkXfermode* mode) {
|
||||
SkXfermode::Mode resultMode;
|
||||
if (!SkXfermode::AsMode(mode, &resultMode)) {
|
||||
resultMode = SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
return resultMode;
|
||||
}
|
||||
|
||||
// TODO: move to a method on android:Paint
|
||||
static inline bool paintWillNotDraw(const SkPaint& paint) {
|
||||
return paint.getAlpha() == 0
|
||||
&& !paint.getColorFilter()
|
||||
&& getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
|
||||
// TODO: move to a method on android:Paint
|
||||
static inline bool paintWillNotDrawText(const SkPaint& paint) {
|
||||
return paint.getAlpha() == 0
|
||||
&& paint.getLooper() == nullptr
|
||||
&& !paint.getColorFilter()
|
||||
&& getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
|
||||
static bool isBlendedColorFilter(const SkColorFilter* filter) {
|
||||
if (filter == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Frame state operations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
static DisplayListRenderer* startRecording(RenderNode* node) {
|
||||
DisplayListRenderer* renderer = new DisplayListRenderer();
|
||||
renderer->setViewport(node->getWidth(), node->getHeight());
|
||||
renderer->prepare(false);
|
||||
renderer->prepare();
|
||||
return renderer;
|
||||
}
|
||||
|
||||
|
||||
64
libs/hwui/utils/PaintUtils.h
Normal file
64
libs/hwui/utils/PaintUtils.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 PAINT_UTILS_H
|
||||
#define PAINT_UTILS_H
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class PaintUtils {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Safely retrieves the mode from the specified xfermode. If the specified
|
||||
* xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
|
||||
*/
|
||||
static inline SkXfermode::Mode getXfermode(SkXfermode* mode) {
|
||||
SkXfermode::Mode resultMode;
|
||||
if (!SkXfermode::AsMode(mode, &resultMode)) {
|
||||
resultMode = SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
return resultMode;
|
||||
}
|
||||
|
||||
// TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()?
|
||||
static inline bool paintWillNotDraw(const SkPaint& paint) {
|
||||
return paint.getAlpha() == 0
|
||||
&& !paint.getColorFilter()
|
||||
&& getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
|
||||
// TODO: move to a method on android:Paint? replace with SkPaint::nothingToDraw()?
|
||||
static inline bool paintWillNotDrawText(const SkPaint& paint) {
|
||||
return paint.getAlpha() == 0
|
||||
&& paint.getLooper() == NULL
|
||||
&& !paint.getColorFilter()
|
||||
&& getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
|
||||
}
|
||||
|
||||
static bool isBlendedColorFilter(const SkColorFilter* filter) {
|
||||
if (filter == NULL) {
|
||||
return false;
|
||||
}
|
||||
return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0;
|
||||
}
|
||||
|
||||
}; // class PaintUtils
|
||||
|
||||
} /* namespace uirenderer */
|
||||
} /* namespace android */
|
||||
|
||||
#endif /* PAINT_UTILS_H */
|
||||
Reference in New Issue
Block a user