Canvas的drawImage()方法是用于在画布上绘制图像的方法。它可以绘制图像、视频的某一帧图像以及其他画布的内容。此外,还可以对绘制的图像进行裁剪,代码如下:
//frameworks/base/graphics/java/android/graphic/Canvas.java
public class Canvas extends BaseCanvas {
public void drawImage(Image image, float x, float y, SamplingOptions sampling) {
nDrawImage(mNativeInstance, image.getNativeInstance(), x, y,
sampling.getNativeDesc(), sampling.getCubicCoeffB(), sampling.getCubicCoeffC());
}
}
调用nDrawImage方法,该方法是一个Native方法,在Canvas.cpp中定义,通过查调用的是Canvas_DrawImage方法:
//external/skia/modules/androidkit/src/Canvas.cpp
void Canvas_DrawImage(JNIEnv* env, jobject, jlong native_instance, jlong native_image,
jfloat x, jfloat y,
jint sampling_desc, jfloat sampling_b, jfloat sampling_c) {
auto* canvas = reinterpret_cast<SkCanvas*>(native_instance);
auto* image = reinterpret_cast<SkImage *>(native_image);
if (canvas && image) {
canvas->drawImage(image, x, y,
androidkit::utils::SamplingOptions(sampling_desc, sampling_b, sampling_c));
}
}
SkCanvas drawImage
调用SkCanvas的drawImage方法:
//external/skia/src/core/SkiaCanvas.cpp
class SK_API SkCanvas {
void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y,
const SkSamplingOptions& sampling, const SkPaint* paint) {
TRACE_EVENT0("skia", TRACE_FUNC);
RETURN_ON_NULL(image);
this->onDrawImage2(image, x, y, sampling, paint);
}
调用SkCanvas的onDrawImage2方法:
//external/skia/include/core/SkCanvas.cpp
class SK_API SkCanvas {
void SkCanvas::onDrawImage2(const SkImage* image, SkScalar x, SkScalar y,
const SkSamplingOptions& sampling, const SkPaint* paint) {
SkPaint realPaint = clean_paint_for_drawImage(paint);
SkRect bounds = SkRect::MakeXYWH(x, y, image->width(), image->height());
if (this->internalQuickReject(bounds, realPaint)) {
return;
}
if (realPaint.getImageFilter() &&
this->canDrawBitmapAsSprite(x, y, image->width(), image->height(), sampling, realPaint) &&
!image_to_color_filter(&realPaint)) {
// Evaluate the image filter directly on the input image and then draw the result, instead
// of first drawing the image to a temporary layer and filtering.
SkBaseDevice* device = this->topDevice();
sk_sp<SkSpecialImage> special;
if ((special = device->makeSpecial(image))) {
sk_sp<SkImageFilter> filter = realPaint.refImageFilter();
realPaint.setImageFilter(nullptr);
// TODO(michaelludwig) - Many filters could probably be evaluated like this even if the
// CTM is not translate-only; the post-transformation of the filtered image by the CTM
// will probably look just as good and not require an extra layer.
// TODO(michaelludwig) - Once image filter implementations can support source images
// with non-(0,0) origins, we can just mark the origin as (x,y) instead of doing a
// pre-concat here.
SkMatrix layerToDevice = device->localToDevice();
layerToDevice.preTranslate(x, y);
SkMatrix deviceToLayer;
if (!layerToDevice.invert(&deviceToLayer)) {
return; // bad ctm, d