123

118 阅读1分钟
if (0 == currIndex) {
    dstPaint.xfermode = clearMode // 清除模式
    if (this::dstCanvas.isInitialized) {
        dstCanvas.drawPaint(dstPaint)
    }
    srcPaint.xfermode = clearMode
    if (this::srcCanvas.isInitialized) {
        srcCanvas.drawPaint(srcPaint)
    }
    if (this::finalCanvas.isInitialized) {
        finalCanvas.drawPaint(dstPaint)
    }
}

val xTmp = measuredWidth / SVG_STROKE_WIDTH // 缩放比例
val yTmp = measuredHeight / SVG_STROKE_HEIGHT

val restore = canvas.save()
// 1. 沿着 y 轴旋转
// 2. 将 View 下移自身高度,注意汉字上下有边,一般为字体高度的 1/8
// 3. 按控件大小等比缩放汉字,注意默认(0, 0)左下缩,现在要求左上缩
canvas.scale(1F, -1F)
canvas.translate(0F, -SVG_STROKE_HEIGHT * 7 / 8) // -1024 + 1024/8
canvas.scale(xTmp, yTmp, 0F, SVG_STROKE_HEIGHT * 7 / 8) // 1024 - 1024/8
for (stroke in strokePaths) {
    canvas.drawPath(stroke, strokePaint)
}
canvas.restoreToCount(restore)

val w = measuredWidth
val h = measuredHeight
val layer = canvas.saveLayer(0F, 0F, w.toFloat(), h.toFloat(), null)
// 目标Bitmap
if (dstBmp == null) {
    dstBmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444)
    dstCanvas = Canvas(dstBmp)
}
dstPaint.xfermode = srcMode
val c1 = dstCanvas.save()
dstCanvas.scale(1F, -1F)
dstCanvas.translate(0F, -SVG_STROKE_HEIGHT * 7 / 8)
dstCanvas.scale(xTmp, yTmp, 0F, SVG_STROKE_HEIGHT * 7 / 8)
for (i in strokePaths.size - 1 downTo 0) { // 进度内的 stroke path
    if (i <= currIndex && currIndex < strokePaths.size) {
        dstCanvas.drawPath(strokePaths[i], dstPaint)
    }
}
dstCanvas.restoreToCount(c1)
dstPaint.xfermode = null
if (dstBmp?.isRecycled == true) {
    return
}
canvas.drawBitmap(dstBmp, 0F, 0F, medianPaint)
// 在两者相交的地方绘制源图像
medianPaint.xfermode = porterDuffXfermode

// src bitmap
if (srcBmp == null) {
    srcBmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444)
    srcCanvas = Canvas(srcBmp)
}
srcPaint.xfermode = srcMode // 只保留 srcBmp 的 alpha 和 color ,所以绘制出来只有源图

val c2 = srcCanvas.save()
srcCanvas.scale(1F, -1F)
srcCanvas.translate(0F, -SVG_STROKE_HEIGHT * 7 / 8)
srcCanvas.scale(xTmp, yTmp, 0F, SVG_STROKE_HEIGHT * 7 / 8)
if (medianMeasures.isNotEmpty()) {
    if (startAnima) {
        drawBackbonePointCircle(currIndex * 2, 20F)
        if (progress > 0.99) {
            drawBackbonePointCircle(currIndex * 2 + 1, 30F)
        }
    }
    tempPath.reset()
    val m = medianMeasures[currIndex]
    m.getSegment(0F, m.length * progress, tempPath, true)
    srcCanvas.drawPath(tempPath, srcPaint)
}
srcCanvas.restoreToCount(c2)
srcPaint.xfermode = null
if (finalBmp == null) {
    finalBmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444)
    finalCanvas = Canvas(finalBmp)
}
val c3 = finalCanvas.save()
finalCanvas.scale(1F, -1F)
finalCanvas.translate(0F, -SVG_STROKE_HEIGHT * 7 / 8)
finalCanvas.scale(xTmp, yTmp, 0F, SVG_STROKE_HEIGHT * 7 / 8)
for (i in strokePaths.size - 1 downTo 0) { // 进度内的 stroke path
    if (i <= currIndex && currIndex < strokePaths.size) {
        finalCanvas.drawPath(strokePaths[i], dstPaint)
    }
}
finalCanvas.restoreToCount(c3)
srcCanvas.drawBitmap(finalBmp, 0F, 0F, medianPaint)
canvas.drawBitmap(srcBmp, 0F, 0F, medianPaint)
medianPaint.xfermode = null

canvas.restoreToCount(layer)
```
```