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:
Tom Hudson
2014-12-09 15:03:44 -05:00
committed by Chris Craik
parent c82be5f27f
commit 8dfaa49042
16 changed files with 406 additions and 1586 deletions

View File

@@ -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
}
}

View File

@@ -56,7 +56,7 @@ class GLES20RecordingCanvas extends GLES20Canvas {
}
long finishRecording() {
return nFinishRecording(mRenderer);
return nFinishRecording(mNativeCanvasWrapper);
}
@Override

View File

@@ -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;

View File

@@ -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.

View File

@@ -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);

View File

@@ -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 },

View File

@@ -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);
}

View File

@@ -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.
*

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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
// ----------------------------------------------------------------------------

View File

@@ -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;
}

View 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 */