1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.ui.text.android
18 
19 import android.graphics.Bitmap
20 import android.graphics.BlendMode
21 import android.graphics.Canvas
22 import android.graphics.DrawFilter
23 import android.graphics.Matrix
24 import android.graphics.NinePatch
25 import android.graphics.Paint
26 import android.graphics.Path
27 import android.graphics.Picture
28 import android.graphics.PorterDuff
29 import android.graphics.Rect
30 import android.graphics.RectF
31 import android.graphics.Region
32 import android.graphics.RenderNode
33 import android.graphics.fonts.Font
34 import android.graphics.text.MeasuredText
35 import android.os.Build
36 import androidx.annotation.RequiresApi
37 
38 /**
39  * This is a wrapper around Android Canvas that we get from
40  * androidx.compose.ui.graphics.Canvas#nativeCanvas. This implementation delegates all methods to
41  * the original nativeCanvas apart from `getClipBounds(Rect)`
42  */
43 @Suppress("DEPRECATION")
44 internal class TextAndroidCanvas : Canvas() {
45     /** Original canvas object to which this class delegates its method calls */
46     private lateinit var nativeCanvas: Canvas
47 
setCanvasnull48     fun setCanvas(canvas: Canvas) {
49         nativeCanvas = canvas
50     }
51 
52     /**
53      * By overriding this methods we allow android.text.Layout to draw all lines that would
54      * otherwise be cut due to Layout's internal drawing logic.
55      */
getClipBoundsnull56     override fun getClipBounds(bounds: Rect): Boolean {
57         val result = nativeCanvas.getClipBounds(bounds)
58         if (result) {
59             val currentWidth = bounds.width()
60             bounds.set(0, 0, currentWidth, Int.MAX_VALUE)
61         }
62         return result
63     }
64 
setBitmapnull65     override fun setBitmap(bitmap: Bitmap?) {
66         nativeCanvas.setBitmap(bitmap)
67     }
68 
69     @RequiresApi(Build.VERSION_CODES.Q)
enableZnull70     override fun enableZ() {
71         CanvasCompatQ.enableZ(nativeCanvas)
72     }
73 
74     @RequiresApi(Build.VERSION_CODES.Q)
disableZnull75     override fun disableZ() {
76         CanvasCompatQ.disableZ(nativeCanvas)
77     }
78 
isOpaquenull79     override fun isOpaque(): Boolean {
80         return nativeCanvas.isOpaque
81     }
82 
getWidthnull83     override fun getWidth(): Int {
84         return nativeCanvas.width
85     }
86 
getHeightnull87     override fun getHeight(): Int {
88         return nativeCanvas.getHeight()
89     }
90 
getDensitynull91     override fun getDensity(): Int {
92         return nativeCanvas.density
93     }
94 
setDensitynull95     override fun setDensity(density: Int) {
96         nativeCanvas.density = density
97     }
98 
getMaximumBitmapWidthnull99     override fun getMaximumBitmapWidth(): Int {
100         return nativeCanvas.maximumBitmapWidth
101     }
102 
getMaximumBitmapHeightnull103     override fun getMaximumBitmapHeight(): Int {
104         return nativeCanvas.maximumBitmapHeight
105     }
106 
savenull107     override fun save(): Int {
108         return nativeCanvas.save()
109     }
110 
111     @Deprecated("Deprecated in Java")
saveLayernull112     override fun saveLayer(bounds: RectF?, paint: Paint?, saveFlags: Int): Int {
113         return nativeCanvas.saveLayer(bounds, paint, saveFlags)
114     }
115 
saveLayernull116     override fun saveLayer(bounds: RectF?, paint: Paint?): Int {
117         return nativeCanvas.saveLayer(bounds, paint)
118     }
119 
120     @Deprecated("Deprecated in Java")
saveLayernull121     override fun saveLayer(
122         left: Float,
123         top: Float,
124         right: Float,
125         bottom: Float,
126         paint: Paint?,
127         saveFlags: Int
128     ): Int {
129         return nativeCanvas.saveLayer(left, top, right, bottom, paint, saveFlags)
130     }
131 
saveLayernull132     override fun saveLayer(
133         left: Float,
134         top: Float,
135         right: Float,
136         bottom: Float,
137         paint: Paint?
138     ): Int {
139         return nativeCanvas.saveLayer(left, top, right, bottom, paint)
140     }
141 
142     @Deprecated("Deprecated in Java")
saveLayerAlphanull143     override fun saveLayerAlpha(bounds: RectF?, alpha: Int, saveFlags: Int): Int {
144         return nativeCanvas.saveLayerAlpha(bounds, alpha, saveFlags)
145     }
146 
saveLayerAlphanull147     override fun saveLayerAlpha(bounds: RectF?, alpha: Int): Int {
148         return nativeCanvas.saveLayerAlpha(bounds, alpha)
149     }
150 
151     @Deprecated("Deprecated in Java")
saveLayerAlphanull152     override fun saveLayerAlpha(
153         left: Float,
154         top: Float,
155         right: Float,
156         bottom: Float,
157         alpha: Int,
158         saveFlags: Int
159     ): Int {
160         return nativeCanvas.saveLayerAlpha(left, top, right, bottom, alpha, saveFlags)
161     }
162 
saveLayerAlphanull163     override fun saveLayerAlpha(
164         left: Float,
165         top: Float,
166         right: Float,
167         bottom: Float,
168         alpha: Int
169     ): Int {
170         return nativeCanvas.saveLayerAlpha(left, top, right, bottom, alpha)
171     }
172 
restorenull173     override fun restore() {
174         nativeCanvas.restore()
175     }
176 
getSaveCountnull177     override fun getSaveCount(): Int {
178         return nativeCanvas.saveCount
179     }
180 
restoreToCountnull181     override fun restoreToCount(saveCount: Int) {
182         nativeCanvas.restoreToCount(saveCount)
183     }
184 
translatenull185     override fun translate(dx: Float, dy: Float) {
186         nativeCanvas.translate(dx, dy)
187     }
188 
scalenull189     override fun scale(sx: Float, sy: Float) {
190         nativeCanvas.scale(sx, sy)
191     }
192 
rotatenull193     override fun rotate(degrees: Float) {
194         nativeCanvas.rotate(degrees)
195     }
196 
skewnull197     override fun skew(sx: Float, sy: Float) {
198         nativeCanvas.skew(sx, sy)
199     }
200 
concatnull201     override fun concat(matrix: Matrix?) {
202         nativeCanvas.concat(matrix)
203     }
204 
setMatrixnull205     override fun setMatrix(matrix: Matrix?) {
206         nativeCanvas.setMatrix(matrix)
207     }
208 
209     @Deprecated("Deprecated in Java")
getMatrixnull210     override fun getMatrix(ctm: Matrix) {
211         nativeCanvas.getMatrix(ctm)
212     }
213 
214     @Deprecated("Deprecated in Java")
clipRectnull215     override fun clipRect(rect: RectF, op: Region.Op): Boolean {
216         return nativeCanvas.clipRect(rect, op)
217     }
218 
219     @Deprecated("Deprecated in Java")
clipRectnull220     override fun clipRect(rect: Rect, op: Region.Op): Boolean {
221         return nativeCanvas.clipRect(rect, op)
222     }
223 
clipRectnull224     override fun clipRect(rect: RectF): Boolean {
225         return nativeCanvas.clipRect(rect)
226     }
227 
clipRectnull228     override fun clipRect(rect: Rect): Boolean {
229         return nativeCanvas.clipRect(rect)
230     }
231 
232     @Deprecated("Deprecated in Java")
clipRectnull233     override fun clipRect(
234         left: Float,
235         top: Float,
236         right: Float,
237         bottom: Float,
238         op: Region.Op
239     ): Boolean {
240         return nativeCanvas.clipRect(left, top, right, bottom, op)
241     }
242 
clipRectnull243     override fun clipRect(left: Float, top: Float, right: Float, bottom: Float): Boolean {
244         return nativeCanvas.clipRect(left, top, right, bottom)
245     }
246 
clipRectnull247     override fun clipRect(left: Int, top: Int, right: Int, bottom: Int): Boolean {
248         return nativeCanvas.clipRect(left, top, right, bottom)
249     }
250 
251     @RequiresApi(Build.VERSION_CODES.O)
clipOutRectnull252     override fun clipOutRect(rect: RectF): Boolean {
253         return CanvasCompatO.clipOutRect(nativeCanvas, rect)
254     }
255 
256     @RequiresApi(Build.VERSION_CODES.O)
clipOutRectnull257     override fun clipOutRect(rect: Rect): Boolean {
258         return CanvasCompatO.clipOutRect(nativeCanvas, rect)
259     }
260 
261     @RequiresApi(Build.VERSION_CODES.O)
clipOutRectnull262     override fun clipOutRect(left: Float, top: Float, right: Float, bottom: Float): Boolean {
263         return CanvasCompatO.clipOutRect(nativeCanvas, left, top, right, bottom)
264     }
265 
266     @RequiresApi(Build.VERSION_CODES.O)
clipOutRectnull267     override fun clipOutRect(left: Int, top: Int, right: Int, bottom: Int): Boolean {
268         return CanvasCompatO.clipOutRect(nativeCanvas, left, top, right, bottom)
269     }
270 
271     @Deprecated("Deprecated in Java")
clipPathnull272     override fun clipPath(path: Path, op: Region.Op): Boolean {
273         return nativeCanvas.clipPath(path, op)
274     }
275 
clipPathnull276     override fun clipPath(path: Path): Boolean {
277         return nativeCanvas.clipPath(path)
278     }
279 
280     @RequiresApi(Build.VERSION_CODES.O)
clipOutPathnull281     override fun clipOutPath(path: Path): Boolean {
282         return CanvasCompatO.clipOutPath(nativeCanvas, path)
283     }
284 
getDrawFilternull285     override fun getDrawFilter() = nativeCanvas.drawFilter
286 
287     override fun setDrawFilter(filter: DrawFilter?) {
288         nativeCanvas.drawFilter = filter
289     }
290 
291     @Deprecated("Deprecated in Java")
quickRejectnull292     override fun quickReject(rect: RectF, type: EdgeType): Boolean {
293         return nativeCanvas.quickReject(rect, type)
294     }
295 
296     @RequiresApi(Build.VERSION_CODES.R)
quickRejectnull297     override fun quickReject(rect: RectF): Boolean {
298         return CanvasCompatR.quickReject(nativeCanvas, rect)
299     }
300 
301     @Deprecated("Deprecated in Java")
quickRejectnull302     override fun quickReject(path: Path, type: EdgeType): Boolean {
303         return nativeCanvas.quickReject(path, type)
304     }
305 
306     @RequiresApi(Build.VERSION_CODES.R)
quickRejectnull307     override fun quickReject(path: Path): Boolean {
308         return CanvasCompatR.quickReject(nativeCanvas, path)
309     }
310 
311     @Deprecated("Deprecated in Java")
quickRejectnull312     override fun quickReject(
313         left: Float,
314         top: Float,
315         right: Float,
316         bottom: Float,
317         type: EdgeType
318     ): Boolean {
319         return nativeCanvas.quickReject(left, top, right, bottom, type)
320     }
321 
322     @RequiresApi(Build.VERSION_CODES.R)
quickRejectnull323     override fun quickReject(left: Float, top: Float, right: Float, bottom: Float): Boolean {
324         return CanvasCompatR.quickReject(nativeCanvas, left, top, right, bottom)
325     }
326 
drawPicturenull327     override fun drawPicture(picture: Picture) {
328         nativeCanvas.drawPicture(picture)
329     }
330 
drawPicturenull331     override fun drawPicture(picture: Picture, dst: RectF) {
332         nativeCanvas.drawPicture(picture, dst)
333     }
334 
drawPicturenull335     override fun drawPicture(picture: Picture, dst: Rect) {
336         nativeCanvas.drawPicture(picture, dst)
337     }
338 
drawArcnull339     override fun drawArc(
340         oval: RectF,
341         startAngle: Float,
342         sweepAngle: Float,
343         useCenter: Boolean,
344         paint: Paint
345     ) {
346         nativeCanvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint)
347     }
348 
drawArcnull349     override fun drawArc(
350         left: Float,
351         top: Float,
352         right: Float,
353         bottom: Float,
354         startAngle: Float,
355         sweepAngle: Float,
356         useCenter: Boolean,
357         paint: Paint
358     ) {
359         nativeCanvas.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint)
360     }
361 
drawARGBnull362     override fun drawARGB(a: Int, r: Int, g: Int, b: Int) {
363         nativeCanvas.drawARGB(a, r, g, b)
364     }
365 
drawBitmapnull366     override fun drawBitmap(bitmap: Bitmap, left: Float, top: Float, paint: Paint?) {
367         nativeCanvas.drawBitmap(bitmap, left, top, paint)
368     }
369 
drawBitmapnull370     override fun drawBitmap(bitmap: Bitmap, src: Rect?, dst: RectF, paint: Paint?) {
371         nativeCanvas.drawBitmap(bitmap, src, dst, paint)
372     }
373 
drawBitmapnull374     override fun drawBitmap(bitmap: Bitmap, src: Rect?, dst: Rect, paint: Paint?) {
375         nativeCanvas.drawBitmap(bitmap, src, dst, paint)
376     }
377 
378     @Deprecated("Deprecated in Java")
drawBitmapnull379     override fun drawBitmap(
380         colors: IntArray,
381         offset: Int,
382         stride: Int,
383         x: Float,
384         y: Float,
385         width: Int,
386         height: Int,
387         hasAlpha: Boolean,
388         paint: Paint?
389     ) {
390         nativeCanvas.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint)
391     }
392 
393     @Deprecated("Deprecated in Java")
drawBitmapnull394     override fun drawBitmap(
395         colors: IntArray,
396         offset: Int,
397         stride: Int,
398         x: Int,
399         y: Int,
400         width: Int,
401         height: Int,
402         hasAlpha: Boolean,
403         paint: Paint?
404     ) {
405         nativeCanvas.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint)
406     }
407 
drawBitmapnull408     override fun drawBitmap(bitmap: Bitmap, matrix: Matrix, paint: Paint?) {
409         nativeCanvas.drawBitmap(bitmap, matrix, paint)
410     }
411 
drawBitmapMeshnull412     override fun drawBitmapMesh(
413         bitmap: Bitmap,
414         meshWidth: Int,
415         meshHeight: Int,
416         verts: FloatArray,
417         vertOffset: Int,
418         colors: IntArray?,
419         colorOffset: Int,
420         paint: Paint?
421     ) {
422         nativeCanvas.drawBitmapMesh(
423             bitmap,
424             meshWidth,
425             meshHeight,
426             verts,
427             vertOffset,
428             colors,
429             colorOffset,
430             paint
431         )
432     }
433 
drawCirclenull434     override fun drawCircle(cx: Float, cy: Float, radius: Float, paint: Paint) {
435         nativeCanvas.drawCircle(cx, cy, radius, paint)
436     }
437 
drawColornull438     override fun drawColor(color: Int) {
439         nativeCanvas.drawColor(color)
440     }
441 
442     @RequiresApi(Build.VERSION_CODES.Q)
drawColornull443     override fun drawColor(color: Long) {
444         CanvasCompatQ.drawColor(nativeCanvas, color)
445     }
446 
drawColornull447     override fun drawColor(color: Int, mode: PorterDuff.Mode) {
448         nativeCanvas.drawColor(color, mode)
449     }
450 
451     @RequiresApi(Build.VERSION_CODES.Q)
drawColornull452     override fun drawColor(color: Int, mode: BlendMode) {
453         CanvasCompatQ.drawColor(nativeCanvas, color, mode)
454     }
455 
456     @RequiresApi(Build.VERSION_CODES.Q)
drawColornull457     override fun drawColor(color: Long, mode: BlendMode) {
458         CanvasCompatQ.drawColor(nativeCanvas, color, mode)
459     }
460 
drawLinenull461     override fun drawLine(startX: Float, startY: Float, stopX: Float, stopY: Float, paint: Paint) {
462         nativeCanvas.drawLine(startX, startY, stopX, stopY, paint)
463     }
464 
drawLinesnull465     override fun drawLines(pts: FloatArray, offset: Int, count: Int, paint: Paint) {
466         nativeCanvas.drawLines(pts, offset, count, paint)
467     }
468 
drawLinesnull469     override fun drawLines(pts: FloatArray, paint: Paint) {
470         nativeCanvas.drawLines(pts, paint)
471     }
472 
drawOvalnull473     override fun drawOval(oval: RectF, paint: Paint) {
474         nativeCanvas.drawOval(oval, paint)
475     }
476 
drawOvalnull477     override fun drawOval(left: Float, top: Float, right: Float, bottom: Float, paint: Paint) {
478         nativeCanvas.drawOval(left, top, right, bottom, paint)
479     }
480 
drawPaintnull481     override fun drawPaint(paint: Paint) {
482         nativeCanvas.drawPaint(paint)
483     }
484 
485     @RequiresApi(Build.VERSION_CODES.S)
drawPatchnull486     override fun drawPatch(patch: NinePatch, dst: Rect, paint: Paint?) {
487         CanvasCompatS.drawPatch(nativeCanvas, patch, dst, paint)
488     }
489 
490     @RequiresApi(Build.VERSION_CODES.S)
drawPatchnull491     override fun drawPatch(patch: NinePatch, dst: RectF, paint: Paint?) {
492         CanvasCompatS.drawPatch(nativeCanvas, patch, dst, paint)
493     }
494 
drawPathnull495     override fun drawPath(path: Path, paint: Paint) {
496         nativeCanvas.drawPath(path, paint)
497     }
498 
drawPointnull499     override fun drawPoint(x: Float, y: Float, paint: Paint) {
500         nativeCanvas.drawPoint(x, y, paint)
501     }
502 
drawPointsnull503     override fun drawPoints(pts: FloatArray?, offset: Int, count: Int, paint: Paint) {
504         nativeCanvas.drawPoints(pts, offset, count, paint)
505     }
506 
drawPointsnull507     override fun drawPoints(pts: FloatArray, paint: Paint) {
508         nativeCanvas.drawPoints(pts, paint)
509     }
510 
511     @Deprecated("Deprecated in Java")
drawPosTextnull512     override fun drawPosText(
513         text: CharArray,
514         index: Int,
515         count: Int,
516         pos: FloatArray,
517         paint: Paint
518     ) {
519         nativeCanvas.drawPosText(text, index, count, pos, paint)
520     }
521 
522     @Deprecated("Deprecated in Java")
drawPosTextnull523     override fun drawPosText(text: String, pos: FloatArray, paint: Paint) {
524         nativeCanvas.drawPosText(text, pos, paint)
525     }
526 
drawRectnull527     override fun drawRect(rect: RectF, paint: Paint) {
528         nativeCanvas.drawRect(rect, paint)
529     }
530 
drawRectnull531     override fun drawRect(r: Rect, paint: Paint) {
532         nativeCanvas.drawRect(r, paint)
533     }
534 
drawRectnull535     override fun drawRect(left: Float, top: Float, right: Float, bottom: Float, paint: Paint) {
536         nativeCanvas.drawRect(left, top, right, bottom, paint)
537     }
538 
drawRGBnull539     override fun drawRGB(r: Int, g: Int, b: Int) {
540         nativeCanvas.drawRGB(r, g, b)
541     }
542 
drawRoundRectnull543     override fun drawRoundRect(rect: RectF, rx: Float, ry: Float, paint: Paint) {
544         nativeCanvas.drawRoundRect(rect, rx, ry, paint)
545     }
546 
drawRoundRectnull547     override fun drawRoundRect(
548         left: Float,
549         top: Float,
550         right: Float,
551         bottom: Float,
552         rx: Float,
553         ry: Float,
554         paint: Paint
555     ) {
556         nativeCanvas.drawRoundRect(left, top, right, bottom, rx, ry, paint)
557     }
558 
559     @RequiresApi(Build.VERSION_CODES.Q)
drawDoubleRoundRectnull560     override fun drawDoubleRoundRect(
561         outer: RectF,
562         outerRx: Float,
563         outerRy: Float,
564         inner: RectF,
565         innerRx: Float,
566         innerRy: Float,
567         paint: Paint
568     ) {
569         CanvasCompatQ.drawDoubleRoundRect(
570             nativeCanvas,
571             outer,
572             outerRx,
573             outerRy,
574             inner,
575             innerRx,
576             innerRy,
577             paint
578         )
579     }
580 
581     @RequiresApi(Build.VERSION_CODES.Q)
drawDoubleRoundRectnull582     override fun drawDoubleRoundRect(
583         outer: RectF,
584         outerRadii: FloatArray,
585         inner: RectF,
586         innerRadii: FloatArray,
587         paint: Paint
588     ) {
589         CanvasCompatQ.drawDoubleRoundRect(nativeCanvas, outer, outerRadii, inner, innerRadii, paint)
590     }
591 
592     @RequiresApi(Build.VERSION_CODES.S)
drawGlyphsnull593     override fun drawGlyphs(
594         glyphIds: IntArray,
595         glyphIdOffset: Int,
596         positions: FloatArray,
597         positionOffset: Int,
598         glyphCount: Int,
599         font: Font,
600         paint: Paint
601     ) {
602         CanvasCompatS.drawGlyphs(
603             nativeCanvas,
604             glyphIds,
605             glyphIdOffset,
606             positions,
607             positionOffset,
608             glyphCount,
609             font,
610             paint
611         )
612     }
613 
drawTextnull614     override fun drawText(
615         text: CharArray,
616         index: Int,
617         count: Int,
618         x: Float,
619         y: Float,
620         paint: Paint
621     ) {
622         nativeCanvas.drawText(text, index, count, x, y, paint)
623     }
624 
drawTextnull625     override fun drawText(text: String, x: Float, y: Float, paint: Paint) {
626         nativeCanvas.drawText(text, x, y, paint)
627     }
628 
drawTextnull629     override fun drawText(text: String, start: Int, end: Int, x: Float, y: Float, paint: Paint) {
630         nativeCanvas.drawText(text, start, end, x, y, paint)
631     }
632 
drawTextnull633     override fun drawText(
634         text: CharSequence,
635         start: Int,
636         end: Int,
637         x: Float,
638         y: Float,
639         paint: Paint
640     ) {
641         nativeCanvas.drawText(text, start, end, x, y, paint)
642     }
643 
drawTextOnPathnull644     override fun drawTextOnPath(
645         text: CharArray,
646         index: Int,
647         count: Int,
648         path: Path,
649         hOffset: Float,
650         vOffset: Float,
651         paint: Paint
652     ) {
653         nativeCanvas.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint)
654     }
655 
drawTextOnPathnull656     override fun drawTextOnPath(
657         text: String,
658         path: Path,
659         hOffset: Float,
660         vOffset: Float,
661         paint: Paint
662     ) {
663         nativeCanvas.drawTextOnPath(text, path, hOffset, vOffset, paint)
664     }
665 
666     @RequiresApi(Build.VERSION_CODES.M)
drawTextRunnull667     override fun drawTextRun(
668         text: CharArray,
669         index: Int,
670         count: Int,
671         contextIndex: Int,
672         contextCount: Int,
673         x: Float,
674         y: Float,
675         isRtl: Boolean,
676         paint: Paint
677     ) {
678         CanvasCompatM.drawTextRun(
679             nativeCanvas,
680             text,
681             index,
682             count,
683             contextIndex,
684             contextCount,
685             x,
686             y,
687             isRtl,
688             paint
689         )
690     }
691 
692     @RequiresApi(Build.VERSION_CODES.M)
drawTextRunnull693     override fun drawTextRun(
694         text: CharSequence,
695         start: Int,
696         end: Int,
697         contextStart: Int,
698         contextEnd: Int,
699         x: Float,
700         y: Float,
701         isRtl: Boolean,
702         paint: Paint
703     ) {
704         CanvasCompatM.drawTextRun(
705             nativeCanvas,
706             text,
707             start,
708             end,
709             contextStart,
710             contextEnd,
711             x,
712             y,
713             isRtl,
714             paint
715         )
716     }
717 
718     @RequiresApi(Build.VERSION_CODES.Q)
drawTextRunnull719     override fun drawTextRun(
720         text: MeasuredText,
721         start: Int,
722         end: Int,
723         contextStart: Int,
724         contextEnd: Int,
725         x: Float,
726         y: Float,
727         isRtl: Boolean,
728         paint: Paint
729     ) {
730         CanvasCompatQ.drawTextRun(
731             nativeCanvas,
732             text,
733             start,
734             end,
735             contextStart,
736             contextEnd,
737             x,
738             y,
739             isRtl,
740             paint
741         )
742     }
743 
drawVerticesnull744     override fun drawVertices(
745         mode: VertexMode,
746         vertexCount: Int,
747         verts: FloatArray,
748         vertOffset: Int,
749         texs: FloatArray?,
750         texOffset: Int,
751         colors: IntArray?,
752         colorOffset: Int,
753         indices: ShortArray?,
754         indexOffset: Int,
755         indexCount: Int,
756         paint: Paint
757     ) {
758         nativeCanvas.drawVertices(
759             mode,
760             vertexCount,
761             verts,
762             vertOffset,
763             texs,
764             texOffset,
765             colors,
766             colorOffset,
767             indices,
768             indexOffset,
769             indexCount,
770             paint
771         )
772     }
773 
774     @RequiresApi(Build.VERSION_CODES.Q)
drawRenderNodenull775     override fun drawRenderNode(renderNode: RenderNode) {
776         CanvasCompatQ.drawRenderNode(nativeCanvas, renderNode)
777     }
778 }
779 
780 @RequiresApi(Build.VERSION_CODES.M)
781 private object CanvasCompatM {
782 
drawTextRunnull783     fun drawTextRun(
784         canvas: Canvas,
785         text: CharArray,
786         index: Int,
787         count: Int,
788         contextIndex: Int,
789         contextCount: Int,
790         x: Float,
791         y: Float,
792         isRtl: Boolean,
793         paint: Paint
794     ) {
795         canvas.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint)
796     }
797 
drawTextRunnull798     fun drawTextRun(
799         canvas: Canvas,
800         text: CharSequence,
801         start: Int,
802         end: Int,
803         contextStart: Int,
804         contextEnd: Int,
805         x: Float,
806         y: Float,
807         isRtl: Boolean,
808         paint: Paint
809     ) {
810         canvas.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint)
811     }
812 }
813 
814 @RequiresApi(Build.VERSION_CODES.O)
815 private object CanvasCompatO {
816 
clipOutRectnull817     fun clipOutRect(canvas: Canvas, rect: RectF): Boolean {
818         return canvas.clipOutRect(rect)
819     }
820 
clipOutRectnull821     fun clipOutRect(canvas: Canvas, rect: Rect): Boolean {
822         return canvas.clipOutRect(rect)
823     }
824 
clipOutRectnull825     fun clipOutRect(canvas: Canvas, left: Float, top: Float, right: Float, bottom: Float): Boolean {
826         return canvas.clipOutRect(left, top, right, bottom)
827     }
828 
clipOutRectnull829     fun clipOutRect(canvas: Canvas, left: Int, top: Int, right: Int, bottom: Int): Boolean {
830         return canvas.clipOutRect(left, top, right, bottom)
831     }
832 
clipOutPathnull833     fun clipOutPath(canvas: Canvas, path: Path): Boolean {
834         return canvas.clipOutPath(path)
835     }
836 }
837 
838 @RequiresApi(Build.VERSION_CODES.Q)
839 private object CanvasCompatQ {
840 
enableZnull841     fun enableZ(canvas: Canvas) {
842         canvas.enableZ()
843     }
844 
disableZnull845     fun disableZ(canvas: Canvas) {
846         canvas.disableZ()
847     }
848 
drawColornull849     fun drawColor(canvas: Canvas, color: Long) {
850         canvas.drawColor(color)
851     }
852 
drawColornull853     fun drawColor(canvas: Canvas, color: Int, mode: BlendMode) {
854         canvas.drawColor(color, mode)
855     }
856 
drawColornull857     fun drawColor(canvas: Canvas, color: Long, mode: BlendMode) {
858         canvas.drawColor(color, mode)
859     }
860 
drawDoubleRoundRectnull861     fun drawDoubleRoundRect(
862         canvas: Canvas,
863         outer: RectF,
864         outerRx: Float,
865         outerRy: Float,
866         inner: RectF,
867         innerRx: Float,
868         innerRy: Float,
869         paint: Paint
870     ) {
871         canvas.drawDoubleRoundRect(outer, outerRx, outerRy, inner, innerRx, innerRy, paint)
872     }
873 
drawDoubleRoundRectnull874     fun drawDoubleRoundRect(
875         canvas: Canvas,
876         outer: RectF,
877         outerRadii: FloatArray,
878         inner: RectF,
879         innerRadii: FloatArray,
880         paint: Paint
881     ) {
882         canvas.drawDoubleRoundRect(outer, outerRadii, inner, innerRadii, paint)
883     }
884 
drawTextRunnull885     fun drawTextRun(
886         canvas: Canvas,
887         text: MeasuredText,
888         start: Int,
889         end: Int,
890         contextStart: Int,
891         contextEnd: Int,
892         x: Float,
893         y: Float,
894         isRtl: Boolean,
895         paint: Paint
896     ) {
897         canvas.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint)
898     }
899 
drawRenderNodenull900     fun drawRenderNode(canvas: Canvas, renderNode: RenderNode) {
901         canvas.drawRenderNode(renderNode)
902     }
903 }
904 
905 @RequiresApi(Build.VERSION_CODES.R)
906 private object CanvasCompatR {
907 
quickRejectnull908     fun quickReject(canvas: Canvas, rect: RectF): Boolean {
909         return canvas.quickReject(rect)
910     }
911 
quickRejectnull912     fun quickReject(canvas: Canvas, path: Path): Boolean {
913         return canvas.quickReject(path)
914     }
915 
quickRejectnull916     fun quickReject(canvas: Canvas, left: Float, top: Float, right: Float, bottom: Float): Boolean {
917         return canvas.quickReject(left, top, right, bottom)
918     }
919 }
920 
921 @RequiresApi(Build.VERSION_CODES.S)
922 private object CanvasCompatS {
drawPatchnull923     fun drawPatch(canvas: Canvas, patch: NinePatch, dst: Rect, paint: Paint?) {
924         canvas.drawPatch(patch, dst, paint)
925     }
926 
drawPatchnull927     fun drawPatch(canvas: Canvas, patch: NinePatch, dst: RectF, paint: Paint?) {
928         canvas.drawPatch(patch, dst, paint)
929     }
930 
drawGlyphsnull931     fun drawGlyphs(
932         canvas: Canvas,
933         glyphIds: IntArray,
934         glyphIdOffset: Int,
935         positions: FloatArray,
936         positionOffset: Int,
937         glyphCount: Int,
938         font: Font,
939         paint: Paint
940     ) {
941         canvas.drawGlyphs(
942             glyphIds,
943             glyphIdOffset,
944             positions,
945             positionOffset,
946             glyphCount,
947             font,
948             paint
949         )
950     }
951 }
952