Canvas的drawLine方法用于画线,参数一起始点的x轴位置,参数二起始点的y轴位置,参数三终点的x轴水平位置,参数四y轴垂直位置,最后一个参数为Paint 画刷对象,代码如下:
//frameworks/base/graphics/java/android/graphic/Canvas.java
public class Canvas extends BaseCanvas {
public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint) {
super.drawLine(startX, startY, stopX, stopY, paint);
}
}
调用Canvas的父类BaseCanvas的drawLine方法:
//frameworks/base/graphics/java/android/graphic/BaseCanvas.java
public abstract class BaseCanvas {}
public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint) {
throwIfHasHwFeaturesInSwMode(paint);
nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
}
}
drawLine
调用nDrawLine方法,nDrawLine方法是Native方法,在android_graphics_Canvas.cpp中实现,下面分别进行分析:
//framework/base/libs/hwui/jni/android_graphics_Canvas.cpp
static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
jfloat stopX, jfloat stopY, jlong paintHandle) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
}
调用get_canvas取得Canvas:
//framework/base/libs/hwui/jni/android_graphics_Canvas.cpp
static Canvas* get_canvas(jlong canvasHandle) {
return reinterpret_cast<Canvas*>(canvasHandle);
}
SkiaCanvas drawLine
SkiaCanvas继承于Canvas,因此调用SkiaCanvas的drawLine方法,SkiaCanvas的drawLine功能是用于在画布上绘制直线的方法。通过传入两个点的坐标,可以绘制出一条连接这两个点的直线。在绘制直线之前,可以设置线条的粗细和颜色等属性
//frameworks/base/libs/hwui/SkiaCanvas.cpp
class SkiaCanvas : public Canvas {
SkCanvas* mCanvas;
void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
const Paint& paint) {
applyLooper(&paint,
[&](const SkPaint& p) { mCanvas->drawLine(startX, startY, stopX, stopY, p); });
}
}
SkCanvas drawLine
调用mCanvas(SkCanvas)的drawLine方法:
//external/skia/include/core/SkCanvas.cpp
class SK_API SkCanvas {
void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
SkPoint pts[2];
pts[0].set(x0, y0);
pts[1].set(x1, y1);
this->drawPoints(kLines_PointMode, 2, pts, paint);
}
}
调用SkCanvas的drawPoints方法:
//external/skia/include/core/SkCanvas.cpp
class SK_API SkCanvas {
void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
TRACE_EVENT0("skia", TRACE_FUNC);
this->onDrawPoints(mode, count, pts, paint);
}
}
调用SkCanvas的onDrawPoints方法:
//external/skia/include/core/SkCanvas.cpp
class SK_API SkCanvas {
void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
const SkPaint& paint) {
if ((long)count <= 0 || paint.nothingToDraw()) {
return;
}
SkASSERT(pts != nullptr);
SkRect bounds;
// Compute bounds from points (common for drawing a single line)
if (count == 2) {
bounds.set(pts[0], pts[1]);
} else {
bounds.setBounds(pts, SkToInt(count));
}
// Enforce paint style matches implicit behavior of drawPoints
SkPaint strokePaint = paint;
strokePaint.setStyle(SkPaint::kStroke_Style);
if (this->internalQuickReject(bounds, strokePaint)) {
return;
}
auto layer = this->aboutToDraw(this, strokePaint, &bounds);
if (layer) {
this->topDevice()->drawPoints(mode, count, pts, layer->paint());
}
}
}
调用SkCanvas的topDevice方法,返回SkBaseDevice对象:
//external/skia/include/core/SkCanvas.cpp
SkBaseDevice* SkCanvas::topDevice() const {
SkASSERT(fMCRec->fDevice);
return fMCRec->fDevice;
}