当前位置:   article > 正文

Android UI底层绘制原理

Android UI底层绘制原理

自定义View继承自View类,需要重写onDraw方法,通过canvas和paint进行绘制

  1. @Override
  2. protected void onDraw(Canvas canvas) {
  3. super.onDraw(canvas);
  4. canvas.drawLine();
  5. }

 

  1. public void drawLine(float startX, float startY, float stopX, float stopY,
  2. @NonNull Paint paint) {
  3. super.drawLine(startX, startY, stopX, stopY, paint);
  4. }

 framework/base/graphics/java/android/graphics/BaseCanvas.java

  1. public void drawLine(float startX, float startY, float stopX, float stopY,
  2. @NonNull Paint paint) {
  3. throwIfHasHwFeaturesInSwMode(paint);
  4. nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
  5. }
  1. private static native void nDrawLine(long nativeCanvas, float startX, float startY, float stopX,
  2. float stopY, long nativePaint);

framework/base/libs/hwui/jni/android_graphics_Canvas.cpp

  1. // If called from Canvas these are regular JNI
  2. // If called from DisplayListCanvas they are @FastNative
  3. static const JNINativeMethod gDrawMethods[] = {
  4. {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
  5. {"nDrawColor","(JJJI)V", (void*) CanvasJNI::drawColorLong},
  6. {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
  7. {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
  8. {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
  9. {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
  1. static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
  2. jfloat stopX, jfloat stopY, jlong paintHandle) {
  3. Paint* paint = reinterpret_cast<Paint*>(paintHandle);
  4. get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
  5. }
  1. static Canvas* get_canvas(jlong canvasHandle) {
  2. return reinterpret_cast<Canvas*>(canvasHandle);
  3. }

framework/base/libs/hwui/hwui/Canvas.cpp

  1. virtual void drawLine(float startX, float startY, float stopX, float stopY,
  2. const Paint& paint) = 0;

frameworks\base\libs\hwui\SkiaCanvas.cpp

  1. void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
  2. const Paint& paint) {
  3. applyLooper(&paint,
  4. [&](const SkPaint& p) { mCanvas->drawLine(startX, startY, stopX, stopY, p); });
  5. }
  1. void applyLooper(const Paint* paint, Proc proc, void (*preFilter)(SkPaint&) = nullptr) {
  2. BlurDrawLooper* looper = paint ? paint->getLooper() : nullptr;
  3. Paint pnt = paint ? *paint : Paint();
  4. if (preFilter) {
  5. preFilter(pnt);
  6. }
  7. this->onFilterPaint(pnt);
  8. if (looper) {
  9. looper->apply(pnt, [&](SkPoint offset, const Paint& modifiedPaint) {
  10. mCanvas->save();
  11. mCanvas->translate(offset.fX, offset.fY);
  12. proc(modifiedPaint);
  13. mCanvas->restore();
  14. });
  15. } else {
  16. proc(pnt);
  17. }
  18. }

external/skia/src/core/SkCanvas.cpp

  1. void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
  2. SkPoint pts[2];
  3. pts[0].set(x0, y0);
  4. pts[1].set(x1, y1);
  5. this->drawPoints(kLines_PointMode, 2, pts, paint);
  6. }
  1. void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
  2. TRACE_EVENT0("skia", TRACE_FUNC);
  3. this->onDrawPoints(mode, count, pts, paint);
  4. }
  1. void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
  2. const SkPaint& paint) {
  3. if ((long)count <= 0 || paint.nothingToDraw()) {
  4. return;
  5. }
  6. SkASSERT(pts != nullptr);
  7. SkRect bounds;
  8. // Compute bounds from points (common for drawing a single line)
  9. if (count == 2) {
  10. bounds.set(pts[0], pts[1]);
  11. } else {
  12. bounds.setBounds(pts, SkToInt(count));
  13. }
  14. // Enforce paint style matches implicit behavior of drawPoints
  15. SkPaint strokePaint = paint;
  16. strokePaint.setStyle(SkPaint::kStroke_Style);
  17. if (this->internalQuickReject(bounds, strokePaint)) {
  18. return;
  19. }
  20. auto layer = this->aboutToDraw(this, strokePaint, &bounds);
  21. if (layer) {
  22. this->topDevice()->drawPoints(mode, count, pts, layer->paint());
  23. }
  24. }

external\skia\src\core\SkDevice.h

  1. virtual void drawPaint(const SkPaint& paint) = 0;
  2. virtual void drawPoints(SkCanvas::PointMode mode, size_t count,
  3. const SkPoint[], const SkPaint& paint) = 0;

external\skia\src\gpu\v1\Device.cpp

  1. void Device::drawPaint(const SkPaint& paint) {
  2. ASSERT_SINGLE_OWNER
  3. GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPaint", fContext.get());
  4. GrPaint grPaint;
  5. if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
  6. this->asMatrixProvider(), &grPaint)) {
  7. return;
  8. }
  9. fSurfaceDrawContext->drawPaint(this->clip(), std::move(grPaint), this->localToDevice());
  10. }
  11. void Device::drawPoints(SkCanvas::PointMode mode,
  12. size_t count,
  13. const SkPoint pts[],
  14. const SkPaint& paint) {
  15. ASSERT_SINGLE_OWNER
  16. GR_CREATE_TRACE_MARKER_CONTEXT("skgpu::v1::Device", "drawPoints", fContext.get());
  17. SkScalar width = paint.getStrokeWidth();
  18. if (width < 0) {
  19. return;
  20. }
  21. GrAA aa = fSurfaceDrawContext->chooseAA(paint);
  22. if (count == 2 && mode == SkCanvas::kLines_PointMode) {
  23. if (paint.getPathEffect()) {
  24. // Probably a dashed line. Draw as a path.
  25. GrPaint grPaint;
  26. if (SkPaintToGrPaint(this->recordingContext(),
  27. fSurfaceDrawContext->colorInfo(),
  28. paint,
  29. this->asMatrixProvider(),
  30. &grPaint)) {
  31. SkPath path;
  32. path.setIsVolatile(true);
  33. path.moveTo(pts[0]);
  34. path.lineTo(pts[1]);
  35. fSurfaceDrawContext->drawPath(this->clip(),
  36. std::move(grPaint),
  37. aa,
  38. this->localToDevice(),
  39. path,
  40. GrStyle(paint, SkPaint::kStroke_Style));
  41. }
  42. return;
  43. }
  44. if (!paint.getMaskFilter() &&
  45. paint.getStrokeWidth() > 0 && // drawStrokedLine doesn't support hairlines.
  46. paint.getStrokeCap() != SkPaint::kRound_Cap) { // drawStrokedLine doesn't do round caps.
  47. // Simple stroked line. Bypass path rendering.
  48. GrPaint grPaint;
  49. if (SkPaintToGrPaint(this->recordingContext(),
  50. fSurfaceDrawContext->colorInfo(),
  51. paint,
  52. this->asMatrixProvider(),
  53. &grPaint)) {
  54. fSurfaceDrawContext->drawStrokedLine(this->clip(),
  55. std::move(grPaint),
  56. aa,
  57. this->localToDevice(),
  58. pts,
  59. SkStrokeRec(paint, SkPaint::kStroke_Style));
  60. }
  61. return;
  62. }
  63. }
  64. SkScalar scales[2];
  65. bool isHairline = (0 == width) ||
  66. (1 == width && this->localToDevice().getMinMaxScales(scales) &&
  67. SkScalarNearlyEqual(scales[0], 1.f) && SkScalarNearlyEqual(scales[1], 1.f));
  68. // we only handle non-coverage-aa hairlines and paints without path effects or mask filters,
  69. // else we let the SkDraw call our drawPath()
  70. if (!isHairline ||
  71. paint.getPathEffect() ||
  72. paint.getMaskFilter() ||
  73. fSurfaceDrawContext->chooseAAType(aa) == GrAAType::kCoverage) {
  74. SkRasterClip rc(this->devClipBounds());
  75. SkDraw draw;
  76. draw.fDst = SkPixmap(SkImageInfo::MakeUnknown(this->width(), this->height()), nullptr, 0);
  77. draw.fMatrixProvider = this;
  78. draw.fRC = &rc;
  79. draw.drawPoints(mode, count, pts, paint, this);
  80. return;
  81. }
  82. GrPrimitiveType primitiveType = point_mode_to_primitive_type(mode);
  83. const SkMatrixProvider* matrixProvider = this;
  84. GrPaint grPaint;
  85. if (!SkPaintToGrPaint(this->recordingContext(), fSurfaceDrawContext->colorInfo(), paint,
  86. *matrixProvider, &grPaint)) {
  87. return;
  88. }
  89. static constexpr SkVertices::VertexMode kIgnoredMode = SkVertices::kTriangles_VertexMode;
  90. sk_sp<SkVertices> vertices = SkVertices::MakeCopy(kIgnoredMode, SkToS32(count), pts, nullptr,
  91. nullptr);
  92. fSurfaceDrawContext->drawVertices(this->clip(), std::move(grPaint), *matrixProvider,
  93. std::move(vertices), &primitiveType);
  94. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/481867
推荐阅读
相关标签
  

闽ICP备14008679号