@@ -23,16 +23,45 @@ actual open class QRCodeGraphics actual constructor(
23
23
val height : Int ,
24
24
) {
25
25
companion object {
26
- val AVAILABLE_FORMATS : Array <String > = CompressFormat .values() .map { it.name }.toTypedArray()
26
+ val AVAILABLE_FORMATS : Array <String > = CompressFormat .entries .map { it.name }.toTypedArray()
27
27
}
28
28
29
29
protected fun createCanvas (image : Bitmap ) = Canvas (image)
30
30
31
+ /* * [Bitmap] being used for the drawing operations. */
31
32
private var image: Bitmap = Bitmap .createBitmap(width, height, ARGB_8888 )
33
+
34
+ /* * [Canvas] that handles the presenting. */
32
35
private var canvas: Canvas = createCanvas(image)
36
+
37
+ /* * Cache of [Paint] objects being used. Just to try and use the least amount of CPU/memory possible. */
33
38
private val paintCache = mutableMapOf<Int , Paint >()
39
+
40
+ /* * Whether any drawing operations were done or not. */
34
41
private var changed: Boolean = false
35
42
43
+ /* * Whether the user set the value of [canvas]. */
44
+ private var customCanvas = false
45
+ private var customCanvasOffsetX: Int = 0
46
+ private var customCanvasOffsetY: Int = 0
47
+
48
+ /* *
49
+ * Allows this object to draw directly to a user specified [Canvas].
50
+ *
51
+ * It'll invoke [Canvas.setBitmap] with the [Bitmap] being used to draw.
52
+ *
53
+ * @see image
54
+ */
55
+ fun useCustomCanvas (canvas : Canvas , offsetX : Int = 0, offsetY : Int = 0): QRCodeGraphics {
56
+ customCanvas = true
57
+ this .canvas = canvas
58
+ this .canvas.setBitmap(image)
59
+ customCanvasOffsetX = offsetX
60
+ customCanvasOffsetY = offsetY
61
+
62
+ return this
63
+ }
64
+
36
65
/* *
37
66
* Keeps a simple color cache. The default style is [FILL].
38
67
*/
@@ -48,8 +77,13 @@ actual open class QRCodeGraphics actual constructor(
48
77
}
49
78
}
50
79
51
- protected fun rect (x : Int , y : Int , w : Int , h : Int ): RectF =
52
- RectF (x.toFloat(), y.toFloat(), (x + w).toFloat(), (y + h).toFloat())
80
+ protected fun buildRectF (x : Int , y : Int , w : Int , h : Int ): RectF =
81
+ RectF (
82
+ (x + customCanvasOffsetX).toFloat(),
83
+ (y + customCanvasOffsetY).toFloat(),
84
+ (x + w + customCanvasOffsetX).toFloat(),
85
+ (y + h + customCanvasOffsetY).toFloat(),
86
+ )
53
87
54
88
/* * Returns `true` if **any** drawing was performed */
55
89
actual open fun changed () = changed
@@ -59,7 +93,12 @@ actual open class QRCodeGraphics actual constructor(
59
93
if (changed) {
60
94
changed = false
61
95
image = Bitmap .createBitmap(width, height, ARGB_8888 )
62
- canvas = createCanvas(image)
96
+
97
+ if (! customCanvas) {
98
+ canvas = createCanvas(image)
99
+ } else {
100
+ this .canvas.setBitmap(image)
101
+ }
63
102
}
64
103
}
65
104
@@ -106,7 +145,7 @@ actual open class QRCodeGraphics actual constructor(
106
145
private fun toCompressFormat (format : String ) =
107
146
try {
108
147
CompressFormat .valueOf(format.uppercase())
109
- } catch (e : Throwable ) {
148
+ } catch (_ : Throwable ) {
110
149
PNG
111
150
}
112
151
@@ -116,7 +155,6 @@ actual open class QRCodeGraphics actual constructor(
116
155
* @see CompressFormat
117
156
* @see CompressFormat.PNG
118
157
* @see CompressFormat.JPEG
119
- * @see CompressFormat.WEBP
120
158
*/
121
159
actual open fun availableFormats (): Array <String > = AVAILABLE_FORMATS
122
160
@@ -126,24 +164,37 @@ actual open class QRCodeGraphics actual constructor(
126
164
/* * Draw a straight line from point `(x1,y1)` to `(x2,y2)`. */
127
165
actual open fun drawLine (x1 : Int , y1 : Int , x2 : Int , y2 : Int , color : Int , thickness : Double ) {
128
166
canvas.drawLine(
129
- x1 .toFloat(),
130
- y1 .toFloat(),
131
- x2 .toFloat(),
132
- y2 .toFloat(),
167
+ (x1 + customCanvasOffsetX) .toFloat(),
168
+ (y1 + customCanvasOffsetY) .toFloat(),
169
+ (x2 + customCanvasOffsetX) .toFloat(),
170
+ (y2 + customCanvasOffsetY) .toFloat(),
133
171
paintFromCache(color, STROKE , thickness),
134
172
)
135
173
}
136
174
137
175
/* * Draw the edges of a rectangle starting at point `(x,y)` and having `width` by `height`. */
138
176
actual open fun drawRect (x : Int , y : Int , width : Int , height : Int , color : Int , thickness : Double ) {
139
177
val halfThickness = (thickness / 2.0 ).roundToInt()
140
- val rect = Rect (x + halfThickness, y + halfThickness, x + width - halfThickness, y + height - halfThickness)
178
+ val rect = Rect (
179
+ x + halfThickness + customCanvasOffsetX,
180
+ y + halfThickness + customCanvasOffsetY,
181
+ x + width - halfThickness + customCanvasOffsetX,
182
+ y + height - halfThickness + customCanvasOffsetY,
183
+ )
141
184
canvas.drawRect(rect, paintFromCache(color, STROKE , thickness))
142
185
}
143
186
144
187
/* * Fills the rectangle starting at point `(x,y)` and having `width` by `height`. */
145
188
actual open fun fillRect (x : Int , y : Int , width : Int , height : Int , color : Int ) {
146
- canvas.drawRect(Rect (x, y, x + width, y + height), paintFromCache(color))
189
+ canvas.drawRect(
190
+ Rect (
191
+ x + customCanvasOffsetX,
192
+ y + customCanvasOffsetY,
193
+ x + width + customCanvasOffsetX,
194
+ y + height + customCanvasOffsetY,
195
+ ),
196
+ paintFromCache(color),
197
+ )
147
198
}
148
199
149
200
/* * Fill the whole area of this canvas with the specified [color]. */
@@ -184,7 +235,7 @@ actual open class QRCodeGraphics actual constructor(
184
235
val halfThickness = (thickness / 2.0 ).roundToInt()
185
236
186
237
canvas.drawRoundRect(
187
- rect (x + halfThickness, y + halfThickness, width - halfThickness * 2 , height - halfThickness * 2 ),
238
+ buildRectF (x + halfThickness, y + halfThickness, width - halfThickness * 2 , height - halfThickness * 2 ),
188
239
borderRadius.toFloat(),
189
240
borderRadius.toFloat(),
190
241
paintFromCache(color, STROKE , thickness),
@@ -214,7 +265,7 @@ actual open class QRCodeGraphics actual constructor(
214
265
*/
215
266
actual open fun fillRoundRect (x : Int , y : Int , width : Int , height : Int , borderRadius : Int , color : Int ) {
216
267
canvas.drawRoundRect(
217
- rect (x, y, width, height),
268
+ buildRectF (x, y, width, height),
218
269
borderRadius.toFloat(),
219
270
borderRadius.toFloat(),
220
271
paintFromCache(color),
@@ -226,7 +277,7 @@ actual open class QRCodeGraphics actual constructor(
226
277
*/
227
278
actual fun drawEllipse (x : Int , y : Int , width : Int , height : Int , color : Int , thickness : Double ) {
228
279
canvas.drawOval(
229
- rect (x, y, width, height),
280
+ buildRectF (x, y, width, height),
230
281
paintFromCache(color, STROKE , thickness),
231
282
)
232
283
}
@@ -237,7 +288,7 @@ actual open class QRCodeGraphics actual constructor(
237
288
*/
238
289
actual fun fillEllipse (x : Int , y : Int , width : Int , height : Int , color : Int ) {
239
290
canvas.drawOval(
240
- rect (x, y, width, height),
291
+ buildRectF (x, y, width, height),
241
292
paintFromCache(color),
242
293
)
243
294
}
@@ -246,12 +297,15 @@ actual open class QRCodeGraphics actual constructor(
246
297
* Reads the specified image from [rawData] and draws it at `(x,y)`
247
298
*/
248
299
actual fun drawImage (rawData : ByteArray? , x : Int , y : Int ) {
249
- if (rawData != null && rawData.isNotEmpty()) {
300
+ if (rawData != null && rawData.isNotEmpty()) { // NOSONAR
250
301
val imgBitmap = BitmapFactory .decodeByteArray(rawData, 0 , rawData.size)
251
302
drawImage(imgBitmap, x, y)
252
303
}
253
304
}
254
305
306
+ /* *
307
+ * Draws a [Bitmap] at the specified `(x,y)`
308
+ */
255
309
open fun drawImage (img : Bitmap , x : Int , y : Int ) {
256
310
changed = true
257
311
canvas.drawBitmap(img, x.toFloat(), y.toFloat(), null )
0 commit comments