Skip to content

Commit 0d24e8b

Browse files
committed
Remove no-longer-relevant abstraction
1 parent 50f3442 commit 0d24e8b

File tree

5 files changed

+54
-89
lines changed

5 files changed

+54
-89
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.simplemobiletools.draw.pro.extensions
2+
3+
fun <K, V> LinkedHashMap<K, V>.removeFirst(): Pair<K, V> {
4+
val key = keys.first()
5+
val value = values.first()
6+
remove(key)
7+
return key to value
8+
}
9+
10+
fun <K, V> LinkedHashMap<K, V>.removeLast(): Pair<K, V> {
11+
val key = keys.last()
12+
val value = values.last()
13+
remove(key)
14+
return key to value
15+
}
16+
17+
fun <K, V> LinkedHashMap<K, V>.removeLastOrNull(): Pair<K?, V?> {
18+
val key = keys.lastOrNull()
19+
val value = values.lastOrNull()
20+
remove(key)
21+
return key to value
22+
}

app/src/main/kotlin/com/simplemobiletools/draw/pro/models/CanvasOp.kt

Lines changed: 0 additions & 15 deletions
This file was deleted.

app/src/main/kotlin/com/simplemobiletools/draw/pro/models/MyParcelable.kt

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,27 @@ import android.os.Parcelable
55
import android.view.View
66

77
internal class MyParcelable : View.BaseSavedState {
8-
var operations = ArrayList<CanvasOp>()
8+
var operations = LinkedHashMap<MyPath, PaintOptions>()
99

1010
constructor(superState: Parcelable) : super(superState)
1111

1212
constructor(parcel: Parcel) : super(parcel) {
1313
val size = parcel.readInt()
1414
for (i in 0 until size) {
15-
val serializable = parcel.readSerializable()
16-
if (serializable is MyPath) {
17-
val paintOptions = PaintOptions(parcel.readInt(), parcel.readFloat(), parcel.readInt() == 1)
18-
val operation = CanvasOp.PathOp(serializable, paintOptions)
19-
operations.add(operation)
20-
}
15+
val key = parcel.readSerializable() as MyPath
16+
val paintOptions = PaintOptions(parcel.readInt(), parcel.readFloat(), parcel.readInt() == 1)
17+
operations[key] = paintOptions
2118
}
2219
}
2320

2421
override fun writeToParcel(out: Parcel, flags: Int) {
2522
super.writeToParcel(out, flags)
2623
out.writeInt(operations.size)
27-
for (operation in operations) {
28-
if (operation is CanvasOp.PathOp) {
29-
val path = operation.path
30-
val paintOptions = operation.paintOptions
31-
out.writeSerializable(path)
32-
out.writeInt(paintOptions.color)
33-
out.writeFloat(paintOptions.strokeWidth)
34-
out.writeInt(if (paintOptions.isEraser) 1 else 0)
35-
}
24+
for ((path, paintOptions) in operations) {
25+
out.writeSerializable(path)
26+
out.writeInt(paintOptions.color)
27+
out.writeFloat(paintOptions.strokeWidth)
28+
out.writeInt(if (paintOptions.isEraser) 1 else 0)
3629
}
3730
}
3831

app/src/main/kotlin/com/simplemobiletools/draw/pro/models/Svg.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ object Svg {
7373
path.readObject(it.data, activity)
7474
val options = PaintOptions(it.color, it.strokeWidth, it.isEraser)
7575

76-
canvas.addPath(path, options)
76+
canvas.addOperation(path, options)
7777
}
7878
}
7979

app/src/main/kotlin/com/simplemobiletools/draw/pro/views/MyCanvas.kt

Lines changed: 22 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ import com.bumptech.glide.request.RequestOptions
1616
import com.simplemobiletools.commons.extensions.toast
1717
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
1818
import com.simplemobiletools.draw.pro.R
19-
import com.simplemobiletools.draw.pro.extensions.contains
20-
import com.simplemobiletools.draw.pro.extensions.vectorFloodFill
19+
import com.simplemobiletools.draw.pro.extensions.*
2120
import com.simplemobiletools.draw.pro.interfaces.CanvasListener
22-
import com.simplemobiletools.draw.pro.models.CanvasOp
2321
import com.simplemobiletools.draw.pro.models.MyParcelable
2422
import com.simplemobiletools.draw.pro.models.MyPath
2523
import com.simplemobiletools.draw.pro.models.PaintOptions
@@ -31,17 +29,16 @@ import kotlin.math.min
3129
class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
3230
private val MIN_ERASER_WIDTH = 20f
3331
private val MAX_HISTORY_COUNT = 1000
34-
private val BITMAP_MAX_HISTORY_COUNT = 60
35-
private val FLOOD_FILL_TOLERANCE = 2
32+
private val FLOOD_FILL_TOLERANCE = 10
3633

3734
private val mScaledTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
3835

39-
private var mOperations = ArrayList<CanvasOp>()
36+
private var mOperations = LinkedHashMap<MyPath, PaintOptions>()
4037
var mBackgroundBitmap: Bitmap? = null
4138
var mListener: CanvasListener? = null
4239

43-
private var mUndoneOperations = ArrayList<CanvasOp>()
44-
private var mLastOperations = ArrayList<CanvasOp>()
40+
private var mUndoneOperations = LinkedHashMap<MyPath, PaintOptions>()
41+
private var mLastOperations = LinkedHashMap<MyPath, PaintOptions>()
4542
private var mLastBackgroundBitmap: Bitmap? = null
4643

4744
private var mPaint = Paint()
@@ -222,19 +219,9 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
222219
}
223220

224221
if (mOperations.isNotEmpty()) {
225-
val bitmapOps = mOperations.filterIsInstance<CanvasOp.BitmapOp>()
226-
val bitmapOp = bitmapOps.lastOrNull()
227-
if (bitmapOp != null) {
228-
canvas.drawBitmap(bitmapOp.bitmap, 0f, 0f, null)
229-
}
230-
231-
// only perform path ops after last bitmap op as any previous path operations are already visible due to the bitmap op
232-
val startIndex = if (bitmapOp != null) mOperations.indexOf(bitmapOp) else 0
233-
val endIndex = mOperations.lastIndex
234-
val pathOps = mOperations.slice(startIndex..endIndex).filterIsInstance<CanvasOp.PathOp>()
235-
for (pathOp in pathOps) {
236-
changePaint(pathOp.paintOptions)
237-
canvas.drawPath(pathOp.path, mPaint)
222+
for ((path, paintOptions) in mOperations) {
223+
changePaint(paintOptions)
224+
canvas.drawPath(path, mPaint)
238225
}
239226
}
240227

@@ -245,7 +232,7 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
245232

246233
fun undo() {
247234
if (mOperations.isEmpty() && mLastOperations.isNotEmpty()) {
248-
mOperations = mLastOperations.clone() as ArrayList<CanvasOp>
235+
mOperations = mLastOperations.clone() as LinkedHashMap<MyPath, PaintOptions>
249236
mBackgroundBitmap = mLastBackgroundBitmap
250237
mLastOperations.clear()
251238
updateUndoVisibility()
@@ -254,17 +241,19 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
254241
}
255242

256243
if (mOperations.isNotEmpty()) {
257-
val lastOp = mOperations.removeLast()
258-
mUndoneOperations.add(lastOp)
244+
val (path, paintOptions) = mOperations.removeLastOrNull()
245+
if (paintOptions != null && path != null) {
246+
mUndoneOperations[path] = paintOptions
247+
}
259248
invalidate()
260249
}
261250
updateUndoRedoVisibility()
262251
}
263252

264253
fun redo() {
265254
if (mUndoneOperations.isNotEmpty()) {
266-
val undoneOperation = mUndoneOperations.removeLast()
267-
addOperation(undoneOperation)
255+
val (path, paintOptions) = mUndoneOperations.removeLast()
256+
addOperation(path, paintOptions)
268257
invalidate()
269258
}
270259
updateUndoRedoVisibility()
@@ -327,12 +316,6 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
327316
}
328317
}
329318

330-
fun addPath(path: MyPath, options: PaintOptions) {
331-
val pathOp = CanvasOp.PathOp(path, options)
332-
mOperations.add(pathOp)
333-
updateUndoVisibility()
334-
}
335-
336319
private fun changePaint(paintOptions: PaintOptions) {
337320
mPaint.color = if (paintOptions.isEraser) mBackgroundColor else paintOptions.color
338321
mPaint.strokeWidth = paintOptions.strokeWidth
@@ -342,7 +325,7 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
342325
}
343326

344327
fun clearCanvas() {
345-
mLastOperations = mOperations.clone() as ArrayList<CanvasOp>
328+
mLastOperations = mOperations.clone() as LinkedHashMap<MyPath, PaintOptions>
346329
mLastBackgroundBitmap = mBackgroundBitmap
347330
mBackgroundBitmap = null
348331
mPath.reset()
@@ -399,7 +382,7 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
399382
ensureBackgroundThread {
400383
val path = bitmap.vectorFloodFill(color = color, x = touchedX, y = touchedY, tolerance = FLOOD_FILL_TOLERANCE)
401384
val paintOpts = PaintOptions(color = color, strokeWidth = 4f)
402-
addOperation(CanvasOp.PathOp(path, paintOpts))
385+
addOperation(path, paintOpts)
403386
post { invalidate() }
404387
}
405388
}
@@ -414,37 +397,19 @@ class MyCanvas(context: Context, attrs: AttributeSet) : View(context, attrs) {
414397
mPath.lineTo(mCurX + 1, mCurY + 2)
415398
mPath.lineTo(mCurX + 1, mCurY)
416399
}
417-
addOperation(CanvasOp.PathOp(mPath, mPaintOptions))
400+
addOperation(mPath, mPaintOptions)
418401
}
419402

420-
private fun addOperation(operation: CanvasOp) {
421-
mOperations.add(operation)
403+
fun addOperation(path: MyPath, paintOptions: PaintOptions) {
404+
mOperations[path] = paintOptions
422405

423406
// maybe free up some memory
424407
while (mOperations.size > MAX_HISTORY_COUNT) {
425-
val item = mOperations.removeFirst()
426-
if (item is CanvasOp.BitmapOp) {
427-
item.bitmap.recycle()
428-
}
429-
}
430-
431-
val ops = mOperations.filterIsInstance<CanvasOp.BitmapOp>()
432-
if (ops.size > BITMAP_MAX_HISTORY_COUNT) {
433-
val start = ops.lastIndex - BITMAP_MAX_HISTORY_COUNT
434-
val bitmapOp = ops.slice(start..ops.lastIndex).first()
435-
436-
val startIndex = mOperations.indexOf(bitmapOp)
437-
mOperations = mOperations.slice(startIndex..mOperations.lastIndex) as ArrayList<CanvasOp>
408+
mOperations.removeFirst()
438409
}
439410
}
440411

441-
fun getPathsMap(): Map<MyPath, PaintOptions> {
442-
val pathOps = mOperations
443-
.filterIsInstance<CanvasOp.PathOp>()
444-
.map { it.path to it.paintOptions }
445-
.toTypedArray()
446-
return mapOf(*pathOps)
447-
}
412+
fun getPathsMap() = mOperations
448413

449414
fun getDrawingHashCode(): Long {
450415
return if (mOperations.isEmpty()) {

0 commit comments

Comments
 (0)