am 994bfa4b: am 61cc70a2: am 521830a7: Merge "Separate Canvas JNI code from the implementation." into lmp-dev
* commit '994bfa4b469186ffe08b7303ee9e56722c7dd576': Separate Canvas JNI code from the implementation.
This commit is contained in:
@ -90,12 +90,12 @@ LOCAL_SRC_FILES:= \
|
||||
android_util_Process.cpp \
|
||||
android_util_StringBlock.cpp \
|
||||
android_util_XmlBlock.cpp \
|
||||
android_graphics_Canvas.cpp \
|
||||
android_graphics_Picture.cpp \
|
||||
android/graphics/AutoDecodeCancel.cpp \
|
||||
android/graphics/Bitmap.cpp \
|
||||
android/graphics/BitmapFactory.cpp \
|
||||
android/graphics/Camera.cpp \
|
||||
android/graphics/Canvas.cpp \
|
||||
android/graphics/CanvasProperty.cpp \
|
||||
android/graphics/ColorFilter.cpp \
|
||||
android/graphics/DrawFilter.cpp \
|
||||
@ -122,6 +122,7 @@ LOCAL_SRC_FILES:= \
|
||||
android/graphics/Rasterizer.cpp \
|
||||
android/graphics/Region.cpp \
|
||||
android/graphics/Shader.cpp \
|
||||
android/graphics/SkiaCanvas.cpp \
|
||||
android/graphics/SurfaceTexture.cpp \
|
||||
android/graphics/Typeface.cpp \
|
||||
android/graphics/TypefaceImpl.cpp \
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "SkCamera.h"
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "GraphicsJNI.h"
|
||||
|
||||
static jfieldID gNativeInstanceFieldID;
|
||||
@ -95,10 +96,10 @@ static void Camera_getMatrix(JNIEnv* env, jobject obj, jlong matrixHandle) {
|
||||
}
|
||||
|
||||
static void Camera_applyToCanvas(JNIEnv* env, jobject obj, jlong canvasHandle) {
|
||||
SkCanvas* native_canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
|
||||
SkCanvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
|
||||
jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
|
||||
Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
|
||||
v->applyToCanvas((SkCanvas*)native_canvas);
|
||||
v->applyToCanvas(canvas);
|
||||
}
|
||||
|
||||
static jfloat Camera_dotWithNormal(JNIEnv* env, jobject obj,
|
||||
|
File diff suppressed because it is too large
Load Diff
137
core/jni/android/graphics/Canvas.h
Normal file
137
core/jni/android/graphics/Canvas.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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 ANDROID_GRAPHICS_CANVAS_H
|
||||
#define ANDROID_GRAPHICS_CANVAS_H
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkMatrix.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
// TODO: move this further up the stack so that all interaction with minikin
|
||||
// happens prior to calling into this interface
|
||||
class TypefaceImpl;
|
||||
|
||||
class Canvas {
|
||||
public:
|
||||
virtual ~Canvas() {};
|
||||
|
||||
static Canvas* create_canvas(SkBitmap* bitmap);
|
||||
static Canvas* create_canvas(SkCanvas* skiaCanvas);
|
||||
|
||||
// TODO: enable HWUI to either create similar canvas wrapper or subclass
|
||||
// directly from Canvas
|
||||
//static Canvas* create_canvas(uirenderer::Renderer* renderer);
|
||||
|
||||
// TODO: this is a temporary affordance until all necessary logic can be
|
||||
// moved within this interface! Further, the return value should
|
||||
// NOT be unref'd and is valid until this canvas is destroyed or a
|
||||
// new bitmap is set.
|
||||
virtual SkCanvas* getSkCanvas() = 0;
|
||||
|
||||
virtual void setBitmap(SkBitmap* bitmap, bool copyState) = 0;
|
||||
|
||||
virtual bool isOpaque() = 0;
|
||||
virtual int width() = 0;
|
||||
virtual int height() = 0;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations
|
||||
// ----------------------------------------------------------------------------
|
||||
// Save (layer)
|
||||
virtual int getSaveCount() const = 0;
|
||||
virtual int save(SkCanvas::SaveFlags flags) = 0;
|
||||
virtual void restore() = 0;
|
||||
virtual void restoreToCount(int saveCount) = 0;
|
||||
|
||||
virtual int saveLayer(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint, SkCanvas::SaveFlags flags) = 0;
|
||||
virtual int saveLayerAlpha(float left, float top, float right, float bottom,
|
||||
int alpha, SkCanvas::SaveFlags flags) = 0;
|
||||
|
||||
// Matrix
|
||||
virtual void getMatrix(SkMatrix* outMatrix) const = 0;
|
||||
virtual void setMatrix(const SkMatrix& matrix) = 0;
|
||||
|
||||
virtual void concat(const SkMatrix& matrix) = 0;
|
||||
virtual void rotate(float degrees) = 0;
|
||||
virtual void scale(float sx, float sy) = 0;
|
||||
virtual void skew(float sx, float sy) = 0;
|
||||
virtual void translate(float dx, float dy) = 0;
|
||||
|
||||
// clip
|
||||
virtual bool getClipBounds(SkRect* outRect) const = 0;
|
||||
virtual bool quickRejectRect(float left, float top, float right, float bottom) const = 0;
|
||||
virtual bool quickRejectPath(const SkPath& path) const = 0;
|
||||
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) = 0;
|
||||
virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0;
|
||||
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
|
||||
|
||||
// filters
|
||||
virtual void setDrawFilter(SkDrawFilter* drawFilter) = 0;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas draw operations
|
||||
// ----------------------------------------------------------------------------
|
||||
virtual void drawColor(int color, SkXfermode::Mode mode) = 0;
|
||||
virtual void drawPaint(const SkPaint& paint) = 0;
|
||||
|
||||
// Geometry
|
||||
virtual void drawPoint(float x, float y, const SkPaint& paint) = 0;
|
||||
virtual void drawPoints(const float* points, int count, const SkPaint& paint) = 0;
|
||||
virtual void drawLine(float startX, float startY, float stopX, float stopY,
|
||||
const SkPaint& paint) = 0;
|
||||
virtual void drawLines(const float* points, int count, const SkPaint& paint) = 0;
|
||||
virtual void drawRect(float left, float top, float right, float bottom,
|
||||
const SkPaint& paint) = 0;
|
||||
virtual void drawRoundRect(float left, float top, float right, float bottom,
|
||||
float rx, float ry, const SkPaint& paint) = 0;
|
||||
virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) = 0;
|
||||
virtual void drawOval(float left, float top, float right, float bottom,
|
||||
const SkPaint& paint) = 0;
|
||||
virtual void drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) = 0;
|
||||
virtual void drawPath(const SkPath& path, const SkPaint& paint) = 0;
|
||||
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) = 0;
|
||||
|
||||
// Bitmap-based
|
||||
virtual void drawBitmap(const SkBitmap& bitmap, float left, float top,
|
||||
const SkPaint* paint) = 0;
|
||||
virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
|
||||
const SkPaint* paint) = 0;
|
||||
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) = 0;
|
||||
virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
|
||||
const float* vertices, const int* colors, const SkPaint* paint) = 0;
|
||||
|
||||
// Text
|
||||
virtual void drawText(const uint16_t* text, int start, int count, int contextCount,
|
||||
float x, float y, int bidiFlags, const SkPaint& paint,
|
||||
TypefaceImpl* typeface) = 0;
|
||||
virtual void drawPosText(const uint16_t* text, const float* positions, int count,
|
||||
int posCount, const SkPaint& paint) = 0;
|
||||
virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
|
||||
float hOffset, float vOffset, const SkPaint& paint) = 0;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
#endif // ANDROID_GRAPHICS_CANVAS_H
|
@ -4,6 +4,7 @@
|
||||
#include "JNIHelp.h"
|
||||
#include "GraphicsJNI.h"
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkDevice.h"
|
||||
#include "SkMath.h"
|
||||
@ -364,7 +365,7 @@ SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) {
|
||||
SkASSERT(canvas);
|
||||
SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
|
||||
jlong canvasHandle = env->GetLongField(canvas, gCanvas_nativeInstanceID);
|
||||
SkCanvas* c = getNativeCanvas(canvasHandle);
|
||||
SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
|
||||
SkASSERT(c);
|
||||
return c;
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ public:
|
||||
static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
|
||||
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
|
||||
|
||||
static SkCanvas* getNativeCanvas(jlong nativeHandle);
|
||||
static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas);
|
||||
static SkPaint* getNativePaint(JNIEnv*, jobject paint);
|
||||
static android::TypefaceImpl* getNativeTypeface(JNIEnv*, jobject paint);
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <Caches.h>
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkRegion.h"
|
||||
#include "GraphicsJNI.h"
|
||||
@ -119,7 +120,7 @@ public:
|
||||
static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF,
|
||||
jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
|
||||
jint destDensity, jint srcDensity) {
|
||||
SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
|
||||
SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
|
||||
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
@ -138,7 +139,7 @@ public:
|
||||
static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect,
|
||||
jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
|
||||
jint destDensity, jint srcDensity) {
|
||||
SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
|
||||
SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
|
||||
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
|
@ -14,9 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "Picture.h"
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkStream.h"
|
||||
|
||||
namespace android {
|
||||
@ -36,12 +36,13 @@ Picture::Picture(const Picture* src) {
|
||||
}
|
||||
}
|
||||
|
||||
SkCanvas* Picture::beginRecording(int width, int height) {
|
||||
Canvas* Picture::beginRecording(int width, int height) {
|
||||
mPicture.reset(NULL);
|
||||
mRecorder.reset(new SkPictureRecorder);
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
return mRecorder->beginRecording(width, height, NULL, 0);
|
||||
SkCanvas* canvas = mRecorder->beginRecording(width, height, NULL, 0);
|
||||
return Canvas::create_canvas(canvas);
|
||||
}
|
||||
|
||||
void Picture::endRecording() {
|
||||
@ -93,14 +94,14 @@ void Picture::serialize(SkWStream* stream) const {
|
||||
}
|
||||
}
|
||||
|
||||
void Picture::draw(SkCanvas* canvas) {
|
||||
void Picture::draw(Canvas* canvas) {
|
||||
if (NULL != mRecorder.get()) {
|
||||
this->endRecording();
|
||||
SkASSERT(NULL != mPicture.get());
|
||||
}
|
||||
if (NULL != mPicture.get()) {
|
||||
// TODO: remove this const_cast once pictures are immutable
|
||||
const_cast<SkPicture*>(mPicture.get())->draw(canvas);
|
||||
const_cast<SkPicture*>(mPicture.get())->draw(canvas->getSkCanvas());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,14 +22,13 @@
|
||||
#include "SkRefCnt.h"
|
||||
#include "SkTemplates.h"
|
||||
|
||||
class SkCanvas;
|
||||
class SkPicture;
|
||||
class SkPictureRecorder;
|
||||
class SkStream;
|
||||
class SkWStream;
|
||||
|
||||
namespace android {
|
||||
|
||||
class Canvas;
|
||||
|
||||
// Skia's SkPicture class has been split into an SkPictureRecorder
|
||||
// and an SkPicture. AndroidPicture recreates the functionality
|
||||
// of the old SkPicture interface by flip-flopping between the two
|
||||
@ -38,7 +37,7 @@ class Picture {
|
||||
public:
|
||||
explicit Picture(const Picture* src = NULL);
|
||||
|
||||
SkCanvas* beginRecording(int width, int height);
|
||||
Canvas* beginRecording(int width, int height);
|
||||
|
||||
void endRecording();
|
||||
|
||||
@ -50,7 +49,7 @@ public:
|
||||
|
||||
void serialize(SkWStream* stream) const;
|
||||
|
||||
void draw(SkCanvas* canvas);
|
||||
void draw(Canvas* canvas);
|
||||
|
||||
private:
|
||||
int mWidth;
|
||||
|
773
core/jni/android/graphics/SkiaCanvas.cpp
Normal file
773
core/jni/android/graphics/SkiaCanvas.cpp
Normal file
@ -0,0 +1,773 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "Canvas.h"
|
||||
#include "GraphicsJNI.h"
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkClipStack.h"
|
||||
#include "SkDevice.h"
|
||||
#include "SkDeque.h"
|
||||
#include "SkDrawFilter.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkPorterDuff.h"
|
||||
#include "SkShader.h"
|
||||
#include "SkTArray.h"
|
||||
#include "SkTemplates.h"
|
||||
|
||||
#include <minikin/Layout.h>
|
||||
#include "MinikinSkia.h"
|
||||
#include "MinikinUtils.h"
|
||||
|
||||
#include "TypefaceImpl.h"
|
||||
|
||||
#include "unicode/ubidi.h"
|
||||
#include "unicode/ushape.h"
|
||||
|
||||
#include <utils/Log.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
// Holds an SkCanvas reference plus additional native data.
|
||||
class SkiaCanvas : public Canvas {
|
||||
public:
|
||||
SkiaCanvas(SkBitmap* bitmap);
|
||||
|
||||
SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {
|
||||
SkASSERT(canvas);
|
||||
}
|
||||
|
||||
virtual SkCanvas* getSkCanvas() {
|
||||
return mCanvas.get();
|
||||
}
|
||||
|
||||
virtual void setBitmap(SkBitmap* bitmap, bool copyState);
|
||||
|
||||
virtual bool isOpaque();
|
||||
virtual int width();
|
||||
virtual int height();
|
||||
|
||||
virtual int getSaveCount() const;
|
||||
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);
|
||||
|
||||
virtual void getMatrix(SkMatrix* outMatrix) const;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
virtual void setDrawFilter(SkDrawFilter* drawFilter);
|
||||
|
||||
virtual void drawColor(int color, SkXfermode::Mode mode);
|
||||
virtual void drawPaint(const SkPaint& paint);
|
||||
|
||||
virtual void drawPoint(float x, float y, const SkPaint& 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);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
virtual void drawText(const uint16_t* text, int start, int count, int contextCount,
|
||||
float x, float y, int bidiFlags, const SkPaint& paint, TypefaceImpl* typeface);
|
||||
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);
|
||||
|
||||
private:
|
||||
struct SaveRec {
|
||||
int saveCount;
|
||||
SkCanvas::SaveFlags saveFlags;
|
||||
};
|
||||
|
||||
void recordPartialSave(SkCanvas::SaveFlags flags);
|
||||
void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount);
|
||||
void applyClips(const SkTArray<SkClipStack::Element>& clips);
|
||||
|
||||
void drawPoints(const float* points, int count, const SkPaint& paint,
|
||||
SkCanvas::PointMode mode);
|
||||
void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
|
||||
|
||||
SkAutoTUnref<SkCanvas> mCanvas;
|
||||
SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
|
||||
};
|
||||
|
||||
// Construct an SkCanvas from the bitmap.
|
||||
static SkCanvas* createCanvas(SkBitmap* bitmap) {
|
||||
if (bitmap) {
|
||||
return SkNEW_ARGS(SkCanvas, (*bitmap));
|
||||
}
|
||||
|
||||
// Create an empty bitmap device to prevent callers from crashing
|
||||
// if they attempt to draw into this canvas.
|
||||
SkBitmap emptyBitmap;
|
||||
return new SkCanvas(emptyBitmap);
|
||||
}
|
||||
|
||||
Canvas* Canvas::create_canvas(SkBitmap* bitmap) {
|
||||
return new SkiaCanvas(bitmap);
|
||||
}
|
||||
|
||||
Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) {
|
||||
return new SkiaCanvas(skiaCanvas);
|
||||
}
|
||||
|
||||
SkiaCanvas::SkiaCanvas(SkBitmap* bitmap) {
|
||||
mCanvas.reset(createCanvas(bitmap));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations: Replace Bitmap
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class ClipCopier : public SkCanvas::ClipVisitor {
|
||||
public:
|
||||
ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
|
||||
|
||||
virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
|
||||
m_dstCanvas->clipRect(rect, op, antialias);
|
||||
}
|
||||
virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
|
||||
m_dstCanvas->clipRRect(rrect, op, antialias);
|
||||
}
|
||||
virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
|
||||
m_dstCanvas->clipPath(path, op, antialias);
|
||||
}
|
||||
|
||||
private:
|
||||
SkCanvas* m_dstCanvas;
|
||||
};
|
||||
|
||||
void SkiaCanvas::setBitmap(SkBitmap* bitmap, bool copyState) {
|
||||
SkCanvas* newCanvas = createCanvas(bitmap);
|
||||
SkASSERT(newCanvas);
|
||||
|
||||
if (copyState) {
|
||||
// Copy the canvas matrix & clip state.
|
||||
newCanvas->setMatrix(mCanvas->getTotalMatrix());
|
||||
if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) {
|
||||
ClipCopier copier(newCanvas);
|
||||
mCanvas->replayClips(&copier);
|
||||
}
|
||||
}
|
||||
|
||||
// unrefs the existing canvas
|
||||
mCanvas.reset(newCanvas);
|
||||
|
||||
// clean up the old save stack
|
||||
mSaveStack.reset(NULL);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool SkiaCanvas::isOpaque() {
|
||||
return mCanvas->getDevice()->accessBitmap(false).isOpaque();
|
||||
}
|
||||
|
||||
int SkiaCanvas::width() {
|
||||
return mCanvas->getBaseLayerSize().width();
|
||||
}
|
||||
|
||||
int SkiaCanvas::height() {
|
||||
return mCanvas->getBaseLayerSize().height();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations: Save (layer)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int SkiaCanvas::getSaveCount() const {
|
||||
return mCanvas->getSaveCount();
|
||||
}
|
||||
|
||||
int SkiaCanvas::save(SkCanvas::SaveFlags flags) {
|
||||
int count = mCanvas->save();
|
||||
recordPartialSave(flags);
|
||||
return count;
|
||||
}
|
||||
|
||||
void SkiaCanvas::restore() {
|
||||
const SaveRec* rec = (NULL == mSaveStack.get())
|
||||
? NULL
|
||||
: static_cast<SaveRec*>(mSaveStack->back());
|
||||
int currentSaveCount = mCanvas->getSaveCount() - 1;
|
||||
SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount);
|
||||
|
||||
if (NULL == rec || rec->saveCount != currentSaveCount) {
|
||||
// Fast path - no record for this frame.
|
||||
mCanvas->restore();
|
||||
return;
|
||||
}
|
||||
|
||||
bool preserveMatrix = !(rec->saveFlags & SkCanvas::kMatrix_SaveFlag);
|
||||
bool preserveClip = !(rec->saveFlags & SkCanvas::kClip_SaveFlag);
|
||||
|
||||
SkMatrix savedMatrix;
|
||||
if (preserveMatrix) {
|
||||
savedMatrix = mCanvas->getTotalMatrix();
|
||||
}
|
||||
|
||||
SkTArray<SkClipStack::Element> savedClips;
|
||||
if (preserveClip) {
|
||||
saveClipsForFrame(savedClips, currentSaveCount);
|
||||
}
|
||||
|
||||
mCanvas->restore();
|
||||
|
||||
if (preserveMatrix) {
|
||||
mCanvas->setMatrix(savedMatrix);
|
||||
}
|
||||
|
||||
if (preserveClip && !savedClips.empty()) {
|
||||
applyClips(savedClips);
|
||||
}
|
||||
|
||||
mSaveStack->pop_back();
|
||||
}
|
||||
|
||||
void SkiaCanvas::restoreToCount(int restoreCount) {
|
||||
while (mCanvas->getSaveCount() > restoreCount) {
|
||||
this->restore();
|
||||
}
|
||||
}
|
||||
|
||||
int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
|
||||
const SkPaint* paint, SkCanvas::SaveFlags flags) {
|
||||
SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
int count = mCanvas->saveLayer(&bounds, paint, flags | SkCanvas::kMatrixClip_SaveFlag);
|
||||
recordPartialSave(flags);
|
||||
return count;
|
||||
}
|
||||
|
||||
int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
|
||||
int alpha, SkCanvas::SaveFlags flags) {
|
||||
SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
int count = mCanvas->saveLayerAlpha(&bounds, alpha, flags | SkCanvas::kMatrixClip_SaveFlag);
|
||||
recordPartialSave(flags);
|
||||
return count;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// functions to emulate legacy SaveFlags (i.e. independent matrix/clip flags)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void SkiaCanvas::recordPartialSave(SkCanvas::SaveFlags flags) {
|
||||
// A partial save is a save operation which doesn't capture the full canvas state.
|
||||
// (either kMatrix_SaveFlags or kClip_SaveFlag is missing).
|
||||
|
||||
// Mask-out non canvas state bits.
|
||||
flags = static_cast<SkCanvas::SaveFlags>(flags & SkCanvas::kMatrixClip_SaveFlag);
|
||||
|
||||
if (SkCanvas::kMatrixClip_SaveFlag == flags) {
|
||||
// not a partial save.
|
||||
return;
|
||||
}
|
||||
|
||||
if (NULL == mSaveStack.get()) {
|
||||
mSaveStack.reset(SkNEW_ARGS(SkDeque, (sizeof(struct SaveRec), 8)));
|
||||
}
|
||||
|
||||
SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
|
||||
// Store the save counter in the SkClipStack domain.
|
||||
// (0-based, equal to the number of save ops on the stack).
|
||||
rec->saveCount = mCanvas->getSaveCount() - 1;
|
||||
rec->saveFlags = flags;
|
||||
}
|
||||
|
||||
void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount) {
|
||||
SkClipStack::Iter clipIterator(*mCanvas->getClipStack(),
|
||||
SkClipStack::Iter::kTop_IterStart);
|
||||
while (const SkClipStack::Element* elem = clipIterator.next()) {
|
||||
if (elem->getSaveCount() < frameSaveCount) {
|
||||
// done with the current frame.
|
||||
break;
|
||||
}
|
||||
SkASSERT(elem->getSaveCount() == frameSaveCount);
|
||||
clips.push_back(*elem);
|
||||
}
|
||||
}
|
||||
|
||||
void SkiaCanvas::applyClips(const SkTArray<SkClipStack::Element>& clips) {
|
||||
ClipCopier clipCopier(mCanvas);
|
||||
|
||||
// The clip stack stores clips in device space.
|
||||
SkMatrix origMatrix = mCanvas->getTotalMatrix();
|
||||
mCanvas->resetMatrix();
|
||||
|
||||
// We pushed the clips in reverse order.
|
||||
for (int i = clips.count() - 1; i >= 0; --i) {
|
||||
clips[i].replay(&clipCopier);
|
||||
}
|
||||
|
||||
mCanvas->setMatrix(origMatrix);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations: Matrix
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void SkiaCanvas::getMatrix(SkMatrix* outMatrix) const {
|
||||
*outMatrix = mCanvas->getTotalMatrix();
|
||||
}
|
||||
|
||||
void SkiaCanvas::setMatrix(const SkMatrix& matrix) {
|
||||
mCanvas->setMatrix(matrix);
|
||||
}
|
||||
|
||||
void SkiaCanvas::concat(const SkMatrix& matrix) {
|
||||
mCanvas->concat(matrix);
|
||||
}
|
||||
|
||||
void SkiaCanvas::rotate(float degrees) {
|
||||
mCanvas->rotate(degrees);
|
||||
}
|
||||
|
||||
void SkiaCanvas::scale(float sx, float sy) {
|
||||
mCanvas->scale(sx, sy);
|
||||
}
|
||||
|
||||
void SkiaCanvas::skew(float sx, float sy) {
|
||||
mCanvas->skew(sx, sy);
|
||||
}
|
||||
|
||||
void SkiaCanvas::translate(float dx, float dy) {
|
||||
mCanvas->translate(dx, dy);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations: Clips
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This function is a mirror of SkCanvas::getClipBounds except that it does
|
||||
// not outset the edge of the clip to account for anti-aliasing. There is
|
||||
// a skia bug to investigate pushing this logic into back into skia.
|
||||
// (see https://code.google.com/p/skia/issues/detail?id=1303)
|
||||
bool SkiaCanvas::getClipBounds(SkRect* outRect) const {
|
||||
SkIRect ibounds;
|
||||
if (!mCanvas->getClipDeviceBounds(&ibounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkMatrix inverse;
|
||||
// if we can't invert the CTM, we can't return local clip bounds
|
||||
if (!mCanvas->getTotalMatrix().invert(&inverse)) {
|
||||
if (outRect) {
|
||||
outRect->setEmpty();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NULL != outRect) {
|
||||
SkRect r = SkRect::Make(ibounds);
|
||||
inverse.mapRect(outRect, r);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkiaCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
|
||||
SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
return mCanvas->quickReject(bounds);
|
||||
}
|
||||
|
||||
bool SkiaCanvas::quickRejectPath(const SkPath& path) const {
|
||||
return mCanvas->quickReject(path);
|
||||
}
|
||||
|
||||
bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
|
||||
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
mCanvas->clipRect(rect, op);
|
||||
return mCanvas->isClipEmpty();
|
||||
}
|
||||
|
||||
bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
|
||||
mCanvas->clipPath(*path, op);
|
||||
return mCanvas->isClipEmpty();
|
||||
}
|
||||
|
||||
bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
|
||||
SkPath rgnPath;
|
||||
if (region->getBoundaryPath(&rgnPath)) {
|
||||
// The region is specified in device space.
|
||||
SkMatrix savedMatrix = mCanvas->getTotalMatrix();
|
||||
mCanvas->resetMatrix();
|
||||
mCanvas->clipPath(rgnPath, op);
|
||||
mCanvas->setMatrix(savedMatrix);
|
||||
} else {
|
||||
mCanvas->clipRect(SkRect::MakeEmpty(), op);
|
||||
}
|
||||
return mCanvas->isClipEmpty();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas state operations: Filters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) {
|
||||
mCanvas->setDrawFilter(drawFilter);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas draw operations
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void SkiaCanvas::drawColor(int color, SkXfermode::Mode mode) {
|
||||
mCanvas->drawColor(color, mode);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawPaint(const SkPaint& paint) {
|
||||
mCanvas->drawPaint(paint);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas draw operations: Geometry
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint,
|
||||
SkCanvas::PointMode mode) {
|
||||
// convert the floats into SkPoints
|
||||
count >>= 1; // now it is the number of points
|
||||
SkAutoSTMalloc<32, SkPoint> storage(count);
|
||||
SkPoint* pts = storage.get();
|
||||
for (int i = 0; i < count; i++) {
|
||||
pts[i].set(points[0], points[1]);
|
||||
points += 2;
|
||||
}
|
||||
mCanvas->drawPoints(mode, count, pts, paint);
|
||||
}
|
||||
|
||||
|
||||
void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
|
||||
mCanvas->drawPoint(x, y, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
|
||||
this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
|
||||
const SkPaint& paint) {
|
||||
mCanvas->drawLine(startX, startY, stopX, stopY, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
|
||||
this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
|
||||
const SkPaint& paint) {
|
||||
mCanvas->drawRectCoords(left, top, right, bottom, paint);
|
||||
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
|
||||
float rx, float ry, const SkPaint& paint) {
|
||||
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
mCanvas->drawRoundRect(rect, rx, ry, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
|
||||
mCanvas->drawCircle(x, y, radius, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
|
||||
SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
mCanvas->drawOval(oval, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawArc(float left, float top, float right, float bottom,
|
||||
float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
|
||||
SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
|
||||
mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
|
||||
mCanvas->drawPath(path, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
|
||||
const float* verts, const float* texs, const int* colors,
|
||||
const uint16_t* indices, int indexCount, const SkPaint& paint) {
|
||||
#ifndef SK_SCALAR_IS_FLOAT
|
||||
SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
|
||||
#endif
|
||||
const int ptCount = vertexCount >> 1;
|
||||
mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs,
|
||||
(SkColor*)colors, NULL, indices, indexCount, paint);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas draw operations: Bitmaps
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
|
||||
mCanvas->drawBitmap(bitmap, left, top, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
|
||||
mCanvas->drawBitmapMatrix(bitmap, matrix, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
|
||||
float srcRight, float srcBottom, float dstLeft, float dstTop,
|
||||
float dstRight, float dstBottom, const SkPaint* paint) {
|
||||
SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
|
||||
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
|
||||
mCanvas->drawBitmapRectToRect(bitmap, &srcRect, dstRect, paint);
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
|
||||
const float* vertices, const int* colors, const SkPaint* paint) {
|
||||
|
||||
const int ptCount = (meshWidth + 1) * (meshHeight + 1);
|
||||
const int indexCount = meshWidth * meshHeight * 6;
|
||||
|
||||
/* Our temp storage holds 2 or 3 arrays.
|
||||
texture points [ptCount * sizeof(SkPoint)]
|
||||
optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
|
||||
copy to convert from float to fixed
|
||||
indices [ptCount * sizeof(uint16_t)]
|
||||
*/
|
||||
ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
|
||||
storageSize += indexCount * sizeof(uint16_t); // indices[]
|
||||
|
||||
|
||||
#ifndef SK_SCALAR_IS_FLOAT
|
||||
SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
|
||||
#endif
|
||||
SkAutoMalloc storage(storageSize);
|
||||
SkPoint* texs = (SkPoint*)storage.get();
|
||||
uint16_t* indices = (uint16_t*)(texs + ptCount);
|
||||
|
||||
// cons up texture coordinates and indices
|
||||
{
|
||||
const SkScalar w = SkIntToScalar(bitmap.width());
|
||||
const SkScalar h = SkIntToScalar(bitmap.height());
|
||||
const SkScalar dx = w / meshWidth;
|
||||
const SkScalar dy = h / meshHeight;
|
||||
|
||||
SkPoint* texsPtr = texs;
|
||||
SkScalar y = 0;
|
||||
for (int i = 0; i <= meshHeight; i++) {
|
||||
if (i == meshHeight) {
|
||||
y = h; // to ensure numerically we hit h exactly
|
||||
}
|
||||
SkScalar x = 0;
|
||||
for (int j = 0; j < meshWidth; j++) {
|
||||
texsPtr->set(x, y);
|
||||
texsPtr += 1;
|
||||
x += dx;
|
||||
}
|
||||
texsPtr->set(w, y);
|
||||
texsPtr += 1;
|
||||
y += dy;
|
||||
}
|
||||
SkASSERT(texsPtr - texs == ptCount);
|
||||
}
|
||||
|
||||
// cons up indices
|
||||
{
|
||||
uint16_t* indexPtr = indices;
|
||||
int index = 0;
|
||||
for (int i = 0; i < meshHeight; i++) {
|
||||
for (int j = 0; j < meshWidth; j++) {
|
||||
// lower-left triangle
|
||||
*indexPtr++ = index;
|
||||
*indexPtr++ = index + meshWidth + 1;
|
||||
*indexPtr++ = index + meshWidth + 2;
|
||||
// upper-right triangle
|
||||
*indexPtr++ = index;
|
||||
*indexPtr++ = index + meshWidth + 2;
|
||||
*indexPtr++ = index + 1;
|
||||
// bump to the next cell
|
||||
index += 1;
|
||||
}
|
||||
// bump to the next row
|
||||
index += 1;
|
||||
}
|
||||
SkASSERT(indexPtr - indices == indexCount);
|
||||
SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
|
||||
}
|
||||
|
||||
// double-check that we have legal indices
|
||||
#ifdef SK_DEBUG
|
||||
{
|
||||
for (int i = 0; i < indexCount; i++) {
|
||||
SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// cons-up a shader for the bitmap
|
||||
SkPaint tmpPaint;
|
||||
if (paint) {
|
||||
tmpPaint = *paint;
|
||||
}
|
||||
SkShader* shader = SkShader::CreateBitmapShader(bitmap,
|
||||
SkShader::kClamp_TileMode,
|
||||
SkShader::kClamp_TileMode);
|
||||
SkSafeUnref(tmpPaint.setShader(shader));
|
||||
|
||||
mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices,
|
||||
texs, (const SkColor*)colors, NULL, indices,
|
||||
indexCount, tmpPaint);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Canvas draw operations: Text
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class DrawTextFunctor {
|
||||
public:
|
||||
DrawTextFunctor(const Layout& layout, SkCanvas* canvas, float x, float y, SkPaint* paint,
|
||||
uint16_t* glyphs, SkPoint* pos)
|
||||
: layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
|
||||
pos(pos) { }
|
||||
|
||||
void operator()(size_t start, size_t end) {
|
||||
for (size_t i = start; i < end; i++) {
|
||||
glyphs[i] = layout.getGlyphId(i);
|
||||
pos[i].fX = x + layout.getX(i);
|
||||
pos[i].fY = y + layout.getY(i);
|
||||
}
|
||||
canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
|
||||
}
|
||||
private:
|
||||
const Layout& layout;
|
||||
SkCanvas* canvas;
|
||||
float x;
|
||||
float y;
|
||||
SkPaint* paint;
|
||||
uint16_t* glyphs;
|
||||
SkPoint* pos;
|
||||
};
|
||||
|
||||
void SkiaCanvas::drawText(const uint16_t* text, int start, int count, int contextCount,
|
||||
float x, float y, int bidiFlags, const SkPaint& paint, TypefaceImpl* typeface) {
|
||||
Layout layout;
|
||||
std::string css = MinikinUtils::setLayoutProperties(&layout, &paint, bidiFlags, typeface);
|
||||
layout.doLayout(text, start, count, contextCount, css);
|
||||
|
||||
size_t nGlyphs = layout.nGlyphs();
|
||||
uint16_t* glyphs = new uint16_t[nGlyphs];
|
||||
SkPoint* pos = new SkPoint[nGlyphs];
|
||||
|
||||
SkPaint paintCopy(paint);
|
||||
x += MinikinUtils::xOffsetForTextAlign(&paintCopy, layout);
|
||||
paintCopy.setTextAlign(SkPaint::kLeft_Align);
|
||||
paintCopy.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
||||
|
||||
DrawTextFunctor f(layout, mCanvas, x, y, &paintCopy, glyphs, pos);
|
||||
MinikinUtils::forFontRun(layout, &paintCopy, f);
|
||||
drawTextDecorations(x, y, layout.getAdvance(), paintCopy);
|
||||
|
||||
delete[] glyphs;
|
||||
delete[] pos;
|
||||
}
|
||||
|
||||
// Same values used by Skia
|
||||
#define kStdStrikeThru_Offset (-6.0f / 21.0f)
|
||||
#define kStdUnderline_Offset (1.0f / 9.0f)
|
||||
#define kStdUnderline_Thickness (1.0f / 18.0f)
|
||||
|
||||
void SkiaCanvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
|
||||
uint32_t flags;
|
||||
SkDrawFilter* drawFilter = mCanvas->getDrawFilter();
|
||||
if (drawFilter) {
|
||||
SkPaint paintCopy(paint);
|
||||
drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
|
||||
flags = paintCopy.getFlags();
|
||||
} else {
|
||||
flags = paint.getFlags();
|
||||
}
|
||||
if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
|
||||
SkScalar left = x;
|
||||
SkScalar right = x + length;
|
||||
float textSize = paint.getTextSize();
|
||||
float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
|
||||
if (flags & SkPaint::kUnderlineText_Flag) {
|
||||
SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
|
||||
SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
|
||||
mCanvas->drawRectCoords(left, top, right, bottom, paint);
|
||||
}
|
||||
if (flags & SkPaint::kStrikeThruText_Flag) {
|
||||
SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
|
||||
SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
|
||||
mCanvas->drawRectCoords(left, top, right, bottom, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawPosText(const uint16_t* text, const float* positions, int count, int posCount,
|
||||
const SkPaint& paint) {
|
||||
SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
|
||||
int indx;
|
||||
for (indx = 0; indx < posCount; indx++) {
|
||||
posPtr[indx].fX = positions[indx << 1];
|
||||
posPtr[indx].fY = positions[(indx << 1) + 1];
|
||||
}
|
||||
|
||||
SkPaint paintCopy(paint);
|
||||
paintCopy.setTextEncoding(SkPaint::kUTF16_TextEncoding);
|
||||
mCanvas->drawPosText(text, count, posPtr, paintCopy);
|
||||
|
||||
delete[] posPtr;
|
||||
}
|
||||
|
||||
void SkiaCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
|
||||
float hOffset, float vOffset, const SkPaint& paint) {
|
||||
mCanvas->drawTextOnPathHV(glyphs, count, path, hOffset, vOffset, paint);
|
||||
}
|
||||
|
||||
} // namespace android
|
@ -19,9 +19,9 @@
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <vector>
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "CreateJavaOutputStreamAdaptor.h"
|
||||
|
||||
#include "SkCanvas.h"
|
||||
#include "SkDocument.h"
|
||||
#include "SkPicture.h"
|
||||
#include "SkPictureRecorder.h"
|
||||
@ -132,8 +132,9 @@ static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr,
|
||||
jint pageWidth, jint pageHeight,
|
||||
jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
|
||||
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
|
||||
return reinterpret_cast<jlong>(document->startPage(pageWidth, pageHeight,
|
||||
contentLeft, contentTop, contentRight, contentBottom));
|
||||
SkCanvas* canvas = document->startPage(pageWidth, pageHeight,
|
||||
contentLeft, contentTop, contentRight, contentBottom);
|
||||
return reinterpret_cast<jlong>(Canvas::create_canvas(canvas));
|
||||
}
|
||||
|
||||
static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
|
||||
|
647
core/jni/android_graphics_Canvas.cpp
Normal file
647
core/jni/android_graphics_Canvas.cpp
Normal file
@ -0,0 +1,647 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "jni.h"
|
||||
#include "GraphicsJNI.h"
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
|
||||
#include "Canvas.h"
|
||||
#include "SkGraphics.h"
|
||||
#include "SkPorterDuff.h"
|
||||
#include "TypefaceImpl.h"
|
||||
|
||||
#include <minikin/Layout.h>
|
||||
#include "MinikinSkia.h"
|
||||
#include "MinikinUtils.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
namespace CanvasJNI {
|
||||
|
||||
static Canvas* get_canvas(jlong canvasHandle) {
|
||||
return reinterpret_cast<Canvas*>(canvasHandle);
|
||||
}
|
||||
|
||||
static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
|
||||
delete get_canvas(canvasHandle);
|
||||
}
|
||||
|
||||
// Native wrapper constructor used by Canvas(Bitmap)
|
||||
static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
|
||||
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
|
||||
}
|
||||
|
||||
// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
|
||||
// optionally copying canvas matrix & clip state.
|
||||
static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
|
||||
jboolean copyState) {
|
||||
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
get_canvas(canvasHandle)->setBitmap(bitmap, copyState);
|
||||
}
|
||||
|
||||
static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
|
||||
return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
|
||||
return static_cast<jint>(get_canvas(canvasHandle)->width());
|
||||
}
|
||||
|
||||
static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
|
||||
return static_cast<jint>(get_canvas(canvasHandle)->height());
|
||||
}
|
||||
|
||||
static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
|
||||
return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
|
||||
}
|
||||
|
||||
static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
|
||||
SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
|
||||
return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
|
||||
}
|
||||
|
||||
static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
|
||||
jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
|
||||
return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
|
||||
}
|
||||
|
||||
static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
|
||||
jfloat r, jfloat b, jint alpha, jint flagsHandle) {
|
||||
SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
|
||||
return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
|
||||
}
|
||||
|
||||
static void restore(JNIEnv* env, jobject, jlong canvasHandle) {
|
||||
Canvas* canvas = get_canvas(canvasHandle);
|
||||
if (canvas->getSaveCount() <= 1) { // cannot restore anymore
|
||||
doThrowISE(env, "Underflow in restore");
|
||||
return;
|
||||
}
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount) {
|
||||
Canvas* canvas = get_canvas(canvasHandle);
|
||||
if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
|
||||
doThrowIAE(env, "Underflow in restoreToCount");
|
||||
return;
|
||||
}
|
||||
canvas->restoreToCount(restoreCount);
|
||||
}
|
||||
|
||||
static void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
|
||||
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
|
||||
get_canvas(canvasHandle)->getMatrix(matrix);
|
||||
}
|
||||
|
||||
static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
|
||||
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
|
||||
get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
|
||||
}
|
||||
|
||||
static void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
|
||||
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
|
||||
get_canvas(canvasHandle)->concat(*matrix);
|
||||
}
|
||||
|
||||
static void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
|
||||
get_canvas(canvasHandle)->rotate(degrees);
|
||||
}
|
||||
|
||||
static void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
|
||||
get_canvas(canvasHandle)->scale(sx, sy);
|
||||
}
|
||||
|
||||
static void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
|
||||
get_canvas(canvasHandle)->skew(sx, sy);
|
||||
}
|
||||
|
||||
static void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
|
||||
get_canvas(canvasHandle)->translate(dx, dy);
|
||||
}
|
||||
|
||||
static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
|
||||
SkRect r;
|
||||
SkIRect ir;
|
||||
bool result = get_canvas(canvasHandle)->getClipBounds(&r);
|
||||
|
||||
if (!result) {
|
||||
r.setEmpty();
|
||||
}
|
||||
r.round(&ir);
|
||||
|
||||
(void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
|
||||
jfloat left, jfloat top, jfloat right, jfloat bottom) {
|
||||
bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
|
||||
bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
|
||||
return result ? JNI_TRUE : JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
|
||||
jfloat r, jfloat b, jint opHandle) {
|
||||
SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
|
||||
bool emptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
|
||||
return emptyClip ? JNI_FALSE : JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
|
||||
jint opHandle) {
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
|
||||
SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
|
||||
bool emptyClip = get_canvas(canvasHandle)->clipPath(path, op);
|
||||
return emptyClip ? JNI_FALSE : JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
|
||||
jint opHandle) {
|
||||
SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
|
||||
SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
|
||||
bool emptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
|
||||
return emptyClip ? JNI_FALSE : JNI_TRUE;
|
||||
}
|
||||
|
||||
static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
|
||||
SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
|
||||
get_canvas(canvasHandle)->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
|
||||
}
|
||||
|
||||
static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawPaint(*paint);
|
||||
}
|
||||
|
||||
static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
|
||||
jlong paintHandle) {
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawPoint(x, y, *paint);
|
||||
}
|
||||
|
||||
static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
|
||||
jint offset, jint count, jlong paintHandle) {
|
||||
NPE_CHECK_RETURN_VOID(env, jptsArray);
|
||||
AutoJavaFloatArray autoPts(env, jptsArray);
|
||||
float* floats = autoPts.ptr();
|
||||
const int length = autoPts.length();
|
||||
|
||||
if ((offset | count) < 0 || offset + count > length) {
|
||||
doThrowAIOOBE(env);
|
||||
return;
|
||||
}
|
||||
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
|
||||
}
|
||||
|
||||
static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
|
||||
jfloat stopX, jfloat stopY, jlong paintHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
|
||||
}
|
||||
|
||||
static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
|
||||
jint offset, jint count, jlong paintHandle) {
|
||||
NPE_CHECK_RETURN_VOID(env, jptsArray);
|
||||
AutoJavaFloatArray autoPts(env, jptsArray);
|
||||
float* floats = autoPts.ptr();
|
||||
const int length = autoPts.length();
|
||||
|
||||
if ((offset | count) < 0 || offset + count > length) {
|
||||
doThrowAIOOBE(env);
|
||||
return;
|
||||
}
|
||||
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
|
||||
}
|
||||
|
||||
static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
|
||||
jfloat right, jfloat bottom, jlong paintHandle) {
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
|
||||
}
|
||||
|
||||
static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
|
||||
jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
|
||||
}
|
||||
|
||||
static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
|
||||
jfloat radius, jlong paintHandle) {
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
|
||||
}
|
||||
|
||||
static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
|
||||
jfloat right, jfloat bottom, jlong paintHandle) {
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
|
||||
}
|
||||
|
||||
static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
|
||||
jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
|
||||
jboolean useCenter, jlong paintHandle) {
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
|
||||
useCenter, *paint);
|
||||
}
|
||||
|
||||
static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
|
||||
jlong paintHandle) {
|
||||
const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawPath(*path, *paint);
|
||||
}
|
||||
|
||||
static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
|
||||
jint modeHandle, jint vertexCount,
|
||||
jfloatArray jverts, jint vertIndex,
|
||||
jfloatArray jtexs, jint texIndex,
|
||||
jintArray jcolors, jint colorIndex,
|
||||
jshortArray jindices, jint indexIndex,
|
||||
jint indexCount, jlong paintHandle) {
|
||||
AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
|
||||
AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
|
||||
AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
|
||||
AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
|
||||
|
||||
const float* verts = vertA.ptr() + vertIndex;
|
||||
const float* texs = texA.ptr() + vertIndex;
|
||||
const int* colors = NULL;
|
||||
const uint16_t* indices = NULL;
|
||||
|
||||
if (jcolors != NULL) {
|
||||
colors = colorA.ptr() + colorIndex;
|
||||
}
|
||||
if (jindices != NULL) {
|
||||
indices = (const uint16_t*)(indexA.ptr() + indexIndex);
|
||||
}
|
||||
|
||||
SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
|
||||
indices, indexCount, *paint);
|
||||
}
|
||||
|
||||
static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jlong bitmapHandle,
|
||||
jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
|
||||
jint screenDensity, jint bitmapDensity) {
|
||||
Canvas* canvas = get_canvas(canvasHandle);
|
||||
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
|
||||
if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
|
||||
if (screenDensity != 0 && screenDensity != bitmapDensity) {
|
||||
SkPaint filteredPaint;
|
||||
if (paint) {
|
||||
filteredPaint = *paint;
|
||||
}
|
||||
filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
|
||||
canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
|
||||
} else {
|
||||
canvas->drawBitmap(*bitmap, left, top, paint);
|
||||
}
|
||||
} else {
|
||||
canvas->save(SkCanvas::kMatrixClip_SaveFlag);
|
||||
SkScalar scale = canvasDensity / (float)bitmapDensity;
|
||||
canvas->translate(left, top);
|
||||
canvas->scale(scale, scale);
|
||||
|
||||
SkPaint filteredPaint;
|
||||
if (paint) {
|
||||
filteredPaint = *paint;
|
||||
}
|
||||
filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
|
||||
|
||||
canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
|
||||
canvas->restore();
|
||||
}
|
||||
}
|
||||
|
||||
static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
|
||||
jlong matrixHandle, jlong paintHandle) {
|
||||
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawBitmap(*bitmap, *matrix, paint);
|
||||
}
|
||||
|
||||
static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
|
||||
float srcLeft, float srcTop, float srcRight, float srcBottom,
|
||||
float dstLeft, float dstTop, float dstRight, float dstBottom,
|
||||
jlong paintHandle, jint screenDensity, jint bitmapDensity) {
|
||||
Canvas* canvas = get_canvas(canvasHandle);
|
||||
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
|
||||
if (screenDensity != 0 && screenDensity != bitmapDensity) {
|
||||
SkPaint filteredPaint;
|
||||
if (paint) {
|
||||
filteredPaint = *paint;
|
||||
}
|
||||
filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
|
||||
canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
|
||||
dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
|
||||
} else {
|
||||
canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
|
||||
dstLeft, dstTop, dstRight, dstBottom, paint);
|
||||
}
|
||||
}
|
||||
|
||||
static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
|
||||
jintArray jcolors, jint offset, jint stride,
|
||||
jfloat x, jfloat y, jint width, jint height,
|
||||
jboolean hasAlpha, jlong paintHandle) {
|
||||
// Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
|
||||
// correct the alphaType to kOpaque_SkAlphaType.
|
||||
SkImageInfo info = SkImageInfo::Make(width, height,
|
||||
hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
|
||||
kPremul_SkAlphaType);
|
||||
SkBitmap bitmap;
|
||||
if (!bitmap.allocPixels(info)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
|
||||
}
|
||||
|
||||
static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
|
||||
jint meshWidth, jint meshHeight, jfloatArray jverts,
|
||||
jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
|
||||
const int ptCount = (meshWidth + 1) * (meshHeight + 1);
|
||||
AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
|
||||
AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
|
||||
|
||||
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
|
||||
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
get_canvas(canvasHandle)->drawBitmapMesh(*bitmap, meshWidth, meshHeight,
|
||||
vertA.ptr(), colorA.ptr(), paint);
|
||||
}
|
||||
|
||||
static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
|
||||
jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
|
||||
jlong paintHandle, jlong typefaceHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
jchar* jchars = env->GetCharArrayElements(text, NULL);
|
||||
get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y,
|
||||
bidiFlags, *paint, typeface);
|
||||
env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
|
||||
}
|
||||
|
||||
static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
|
||||
jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
|
||||
jlong paintHandle, jlong typefaceHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
const int count = end - start;
|
||||
const jchar* jchars = env->GetStringChars(text, NULL);
|
||||
get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y,
|
||||
bidiFlags, *paint, typeface);
|
||||
env->ReleaseStringChars(text, jchars);
|
||||
}
|
||||
|
||||
static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
|
||||
jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
|
||||
jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
|
||||
const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
|
||||
jchar* jchars = env->GetCharArrayElements(text, NULL);
|
||||
get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count,
|
||||
contextCount, x, y, bidiFlags, *paint, typeface);
|
||||
env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
|
||||
}
|
||||
|
||||
static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
|
||||
jint start, jint end, jint contextStart, jint contextEnd,
|
||||
jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
|
||||
jlong typefaceHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
|
||||
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
|
||||
jint count = end - start;
|
||||
jint contextCount = contextEnd - contextStart;
|
||||
const jchar* jchars = env->GetStringChars(text, NULL);
|
||||
get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count,
|
||||
contextCount, x, y, bidiFlags, *paint, typeface);
|
||||
env->ReleaseStringChars(text, jchars);
|
||||
}
|
||||
|
||||
static void drawPosTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
|
||||
jint index, jint count, jfloatArray pos, jlong paintHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
jchar* jchars = text ? env->GetCharArrayElements(text, NULL) : NULL;
|
||||
float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
|
||||
int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
|
||||
|
||||
get_canvas(canvasHandle)->drawPosText(jchars + index, posArray, count << 1, posCount, *paint);
|
||||
|
||||
if (text) {
|
||||
env->ReleaseCharArrayElements(text, jchars, 0);
|
||||
}
|
||||
if (pos) {
|
||||
env->ReleaseFloatArrayElements(pos, posArray, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void drawPosTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
|
||||
jfloatArray pos, jlong paintHandle) {
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
const jchar* jchars = text ? env->GetStringChars(text, NULL) : NULL;
|
||||
int byteLength = text ? env->GetStringLength(text) : 0;
|
||||
float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
|
||||
int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
|
||||
|
||||
get_canvas(canvasHandle)->drawPosText(jchars , posArray, byteLength << 1, posCount, *paint);
|
||||
|
||||
if (text) {
|
||||
env->ReleaseStringChars(text, jchars);
|
||||
}
|
||||
if (pos) {
|
||||
env->ReleaseFloatArrayElements(pos, posArray, 0);
|
||||
}
|
||||
}
|
||||
|
||||
class DrawTextOnPathFunctor {
|
||||
public:
|
||||
DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
|
||||
float vOffset, const SkPaint& paint, const SkPath& path)
|
||||
: layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
|
||||
paint(paint), path(path) {
|
||||
}
|
||||
void operator()(size_t start, size_t end) {
|
||||
uint16_t glyphs[1];
|
||||
for (size_t i = start; i < end; i++) {
|
||||
glyphs[0] = layout.getGlyphId(i);
|
||||
float x = hOffset + layout.getX(i);
|
||||
float y = vOffset + layout.getY(i);
|
||||
canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
|
||||
}
|
||||
}
|
||||
private:
|
||||
const Layout& layout;
|
||||
Canvas* canvas;
|
||||
float hOffset;
|
||||
float vOffset;
|
||||
const SkPaint& paint;
|
||||
const SkPath& path;
|
||||
};
|
||||
|
||||
static void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
|
||||
const SkPath& path, float hOffset, float vOffset,
|
||||
const SkPaint& paint, TypefaceImpl* typeface) {
|
||||
SkPaint paintCopy(paint);
|
||||
Layout layout;
|
||||
std::string css = MinikinUtils::setLayoutProperties(&layout, &paintCopy, bidiFlags, typeface);
|
||||
layout.doLayout(text, 0, count, count, css);
|
||||
hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
|
||||
|
||||
// Set align to left for drawing, as we don't want individual
|
||||
// glyphs centered or right-aligned; the offset above takes
|
||||
// care of all alignment.
|
||||
paintCopy.setTextAlign(SkPaint::kLeft_Align);
|
||||
|
||||
DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
|
||||
MinikinUtils::forFontRun(layout, &paintCopy, f);
|
||||
}
|
||||
|
||||
static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
|
||||
jint index, jint count, jlong pathHandle, jfloat hOffset,
|
||||
jfloat vOffset, jint bidiFlags, jlong paintHandle,
|
||||
jlong typefaceHandle) {
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
|
||||
jchar* jchars = env->GetCharArrayElements(text, NULL);
|
||||
|
||||
drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
|
||||
hOffset, vOffset, *paint, typeface);
|
||||
|
||||
env->ReleaseCharArrayElements(text, jchars, 0);
|
||||
}
|
||||
|
||||
static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
|
||||
jlong pathHandle, jfloat hOffset, jfloat vOffset,
|
||||
jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
|
||||
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
|
||||
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
|
||||
const jchar* jchars = env->GetStringChars(text, NULL);
|
||||
int count = env->GetStringLength(text);
|
||||
|
||||
drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
|
||||
hOffset, vOffset, *paint, typeface);
|
||||
|
||||
env->ReleaseStringChars(text, jchars);
|
||||
}
|
||||
|
||||
static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
|
||||
get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
|
||||
}
|
||||
|
||||
static void freeCaches(JNIEnv* env, jobject) {
|
||||
SkGraphics::PurgeFontCache();
|
||||
}
|
||||
|
||||
static void freeTextLayoutCaches(JNIEnv* env, jobject) {
|
||||
Layout::purgeCaches();
|
||||
}
|
||||
|
||||
}; // namespace CanvasJNI
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
|
||||
{"initRaster", "(J)J", (void*) CanvasJNI::initRaster},
|
||||
{"native_setBitmap", "(JJZ)V", (void*) CanvasJNI::setBitmap},
|
||||
{"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
|
||||
{"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
|
||||
{"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
|
||||
{"native_save","(JI)I", (void*) CanvasJNI::save},
|
||||
{"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
|
||||
{"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
|
||||
{"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
|
||||
{"native_restore","(J)V", (void*) CanvasJNI::restore},
|
||||
{"native_restoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
|
||||
{"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
|
||||
{"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
|
||||
{"native_concat","(JJ)V", (void*) CanvasJNI::concat},
|
||||
{"native_rotate","(JF)V", (void*) CanvasJNI::rotate},
|
||||
{"native_scale","(JFF)V", (void*) CanvasJNI::scale},
|
||||
{"native_skew","(JFF)V", (void*) CanvasJNI::skew},
|
||||
{"native_translate","(JFF)V", (void*) CanvasJNI::translate},
|
||||
{"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
|
||||
{"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
|
||||
{"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
|
||||
{"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
|
||||
{"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
|
||||
{"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
|
||||
{"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor},
|
||||
{"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
|
||||
{"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
|
||||
{"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
|
||||
{"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
|
||||
{"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
|
||||
{"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
|
||||
{"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
|
||||
{"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
|
||||
{"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
|
||||
{"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
|
||||
{"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
|
||||
{"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
|
||||
{"native_drawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap},
|
||||
{"nativeDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
|
||||
{"native_drawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
|
||||
{"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
|
||||
{"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
|
||||
{"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
|
||||
{"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
|
||||
{"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
|
||||
{"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
|
||||
{"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
|
||||
{"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
|
||||
{"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
|
||||
{"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
|
||||
{"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
|
||||
};
|
||||
|
||||
int register_android_graphics_Canvas(JNIEnv* env) {
|
||||
return AndroidRuntime::registerNativeMethods(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
|
||||
}
|
||||
|
||||
}; // namespace android
|
@ -51,7 +51,7 @@ static void android_graphics_Picture_killPicture(JNIEnv* env, jobject, jlong pic
|
||||
|
||||
static void android_graphics_Picture_draw(JNIEnv* env, jobject, jlong canvasHandle,
|
||||
jlong pictureHandle) {
|
||||
SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
|
||||
Canvas* canvas = reinterpret_cast<Canvas*>(canvasHandle);
|
||||
Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
|
||||
SkASSERT(canvas);
|
||||
SkASSERT(picture);
|
||||
@ -84,12 +84,7 @@ static jint android_graphics_Picture_getHeight(JNIEnv* env, jobject, jlong pictu
|
||||
static jlong android_graphics_Picture_beginRecording(JNIEnv* env, jobject, jlong pictHandle,
|
||||
jint w, jint h) {
|
||||
Picture* pict = reinterpret_cast<Picture*>(pictHandle);
|
||||
// beginRecording does not ref its return value, it just returns it.
|
||||
SkCanvas* canvas = pict->beginRecording(w, h);
|
||||
// the java side will wrap this guy in a Canvas.java, which will call
|
||||
// unref in its finalizer, so we have to ref it here, so that both that
|
||||
// Canvas.java and our picture can both be owners
|
||||
canvas->ref();
|
||||
Canvas* canvas = pict->beginRecording(w, h);
|
||||
return reinterpret_cast<jlong>(canvas);
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ public class Canvas {
|
||||
if (nativeCanvas == 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
mNativeCanvasWrapper = initCanvas(nativeCanvas);
|
||||
mNativeCanvasWrapper = nativeCanvas;
|
||||
mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper);
|
||||
mDensity = Bitmap.getDefaultDensity();
|
||||
}
|
||||
@ -924,7 +924,7 @@ public class Canvas {
|
||||
* @param b blue component (0..255) of the color to draw onto the canvas
|
||||
*/
|
||||
public void drawRGB(int r, int g, int b) {
|
||||
native_drawRGB(mNativeCanvasWrapper, r, g, b);
|
||||
drawColor(Color.rgb(r, g, b));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -937,7 +937,7 @@ public class Canvas {
|
||||
* @param b blue component (0..255) of the color to draw onto the canvas
|
||||
*/
|
||||
public void drawARGB(int a, int r, int g, int b) {
|
||||
native_drawARGB(mNativeCanvasWrapper, a, r, g, b);
|
||||
drawColor(Color.argb(a, r, g, b));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -947,7 +947,7 @@ public class Canvas {
|
||||
* @param color the color to draw onto the canvas
|
||||
*/
|
||||
public void drawColor(int color) {
|
||||
native_drawColor(mNativeCanvasWrapper, color);
|
||||
native_drawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1301,13 +1301,28 @@ public class Canvas {
|
||||
*/
|
||||
public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
|
||||
@Nullable Paint paint) {
|
||||
if (dst == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
throwIfCannotDraw(bitmap);
|
||||
native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), src, dst,
|
||||
paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
|
||||
}
|
||||
if (dst == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
throwIfCannotDraw(bitmap);
|
||||
final long nativePaint = paint == null ? 0 : paint.mNativePaint;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top, right, bottom,
|
||||
dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
|
||||
bitmap.mDensity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the specified bitmap, scaling/translating automatically to fill
|
||||
@ -1337,8 +1352,23 @@ public class Canvas {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
throwIfCannotDraw(bitmap);
|
||||
native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), src, dst,
|
||||
paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
|
||||
final long nativePaint = paint == null ? 0 : paint.mNativePaint;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top, right, bottom,
|
||||
dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
|
||||
bitmap.mDensity);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1866,7 +1896,6 @@ public class Canvas {
|
||||
public static native void freeTextLayoutCaches();
|
||||
|
||||
private static native long initRaster(long nativeBitmapOrZero);
|
||||
private static native long initCanvas(long canvasHandle);
|
||||
private static native void native_setBitmap(long canvasHandle,
|
||||
long bitmapHandle,
|
||||
boolean copyState);
|
||||
@ -1919,11 +1948,6 @@ public class Canvas {
|
||||
private static native boolean native_quickReject(long nativeCanvas,
|
||||
float left, float top,
|
||||
float right, float bottom);
|
||||
private static native void native_drawRGB(long nativeCanvas, int r, int g,
|
||||
int b);
|
||||
private static native void native_drawARGB(long nativeCanvas, int a, int r,
|
||||
int g, int b);
|
||||
private static native void native_drawColor(long nativeCanvas, int color);
|
||||
private static native void native_drawColor(long nativeCanvas, int color,
|
||||
int mode);
|
||||
private static native void native_drawPaint(long nativeCanvas,
|
||||
@ -1965,16 +1989,9 @@ public class Canvas {
|
||||
int screenDensity,
|
||||
int bitmapDensity);
|
||||
private native void native_drawBitmap(long nativeCanvas, long nativeBitmap,
|
||||
Rect src, RectF dst,
|
||||
long nativePaintOrZero,
|
||||
int screenDensity,
|
||||
int bitmapDensity);
|
||||
private static native void native_drawBitmap(long nativeCanvas,
|
||||
long nativeBitmap,
|
||||
Rect src, Rect dst,
|
||||
long nativePaintOrZero,
|
||||
int screenDensity,
|
||||
int bitmapDensity);
|
||||
float srcLeft, float srcTop, float srcRight, float srcBottom,
|
||||
float dstLeft, float dstTop, float dstRight, float dstBottom,
|
||||
long nativePaintOrZero, int screenDensity, int bitmapDensity);
|
||||
private static native void native_drawBitmap(long nativeCanvas, int[] colors,
|
||||
int offset, int stride, float x,
|
||||
float y, int width, int height,
|
||||
|
Reference in New Issue
Block a user