From 4c34d7ead53c9a58a0f809161fda0e5eeb69f39c Mon Sep 17 00:00:00 2001 From: ekibun Date: Fri, 12 Aug 2022 23:12:31 +0800 Subject: [PATCH] 1. do not obfuscate Serializable class 2. fix stitch drawing --- app/build.gradle | 16 ++- app/proguard-rules.pro | 3 +- app/src/main/java/soko/ekibun/stitch/App.kt | 7 + .../java/soko/ekibun/stitch/CaptureService.kt | 5 +- .../java/soko/ekibun/stitch/EditActivity.kt | 130 ++++++++++-------- .../main/java/soko/ekibun/stitch/EditView.kt | 23 ++-- .../main/java/soko/ekibun/stitch/Stitch.kt | 41 +++--- app/src/main/res/layout/activity_edit.xml | 7 +- build.gradle | 2 +- 9 files changed, 135 insertions(+), 99 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c737f6c..055fa7f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,13 +12,25 @@ static def gitVersionTag() { def cmd = 'git describe --tags' def version = cmd.execute().text.trim() + def patternVersion = "^(v\\d+\\.\\d+)(\\.(\\d+))?" + def matchVersion = version =~ patternVersion + + def versionPref = version + def versionSub = 0 + if (matchVersion) { + versionPref = matchVersion[0][1] + if (matchVersion[0][3]) { + versionSub = Integer.parseInt(matchVersion[0][3]) + } + } + def pattern = "-(\\d+)-g" def matcher = version =~ pattern if (matcher) { - version = version.substring(0, matcher.start()) + "." + matcher[0][1] + version = versionPref + "." + (Integer.parseInt(matcher[0][1]) + versionSub) } else { - version = version + ".0" + version = versionPref + "." + versionSub } return version diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..c1b5103 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -18,4 +18,5 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile +-keep class * implements java.io.Serializable { *; } \ No newline at end of file diff --git a/app/src/main/java/soko/ekibun/stitch/App.kt b/app/src/main/java/soko/ekibun/stitch/App.kt index 9242c4e..dcc9a2d 100644 --- a/app/src/main/java/soko/ekibun/stitch/App.kt +++ b/app/src/main/java/soko/ekibun/stitch/App.kt @@ -15,6 +15,11 @@ class App : Application() { override fun onCreate() { super.onCreate() app = this + val dataVersion = sp.getInt("dataVersion", 0) + if (dataVersion != DATA_VERSION) { + clearProjects() + sp.edit().putInt("dataVersion", DATA_VERSION).apply() + } } val dataDirPath: String by lazy { @@ -22,6 +27,8 @@ class App : Application() { } companion object { + const val DATA_VERSION = 1 + private lateinit var app: App val bitmapCache get() = app.bitmapCache var captureProject: String? = null diff --git a/app/src/main/java/soko/ekibun/stitch/CaptureService.kt b/app/src/main/java/soko/ekibun/stitch/CaptureService.kt index 0680412..3d44ccd 100644 --- a/app/src/main/java/soko/ekibun/stitch/CaptureService.kt +++ b/app/src/main/java/soko/ekibun/stitch/CaptureService.kt @@ -23,8 +23,9 @@ class CaptureService : Service() { val key = App.bitmapCache.saveBitmap(projectKey, bmp) val info = Stitch.StitchInfo(key, bmp.width, bmp.height) val project = App.getProject(projectKey) - project.updateUndo(screenCapture) - project.stitchInfo.add(info) + project.updateUndo(screenCapture) { + project.stitchInfo.add(info) + } notification.updateText(project.stitchInfo.size) } diff --git a/app/src/main/java/soko/ekibun/stitch/EditActivity.kt b/app/src/main/java/soko/ekibun/stitch/EditActivity.kt index 8b3bd47..e5139df 100644 --- a/app/src/main/java/soko/ekibun/stitch/EditActivity.kt +++ b/app/src/main/java/soko/ekibun/stitch/EditActivity.kt @@ -292,33 +292,34 @@ class EditActivity : Activity() { progress.setMessage(getString(R.string.alert_computing, done, project.selected.size)) progress.show() MainScope().launch(Dispatchers.IO) { - project.updateUndo() - project.stitchInfo.reduceOrNull { acc, it -> - if (progress.isShowing && project.selected.contains(it.imageKey)) { - Stitch.combine(homo, diff, acc, it)?.let { data -> - if (progress.isShowing) { - it.dx = data.dx - it.dy = data.dy - it.drot = data.drot - it.dscale = data.dscale + project.updateUndo { + project.stitchInfo.reduceOrNull { acc, it -> + if (progress.isShowing && project.selected.contains(it.imageKey)) { + Stitch.combine(homo, diff, acc, it)?.let { data -> + if (progress.isShowing) { + it.dx = data.dx + it.dy = data.dy + it.drot = data.drot + it.dscale = data.dscale + } } - } - ++done - runOnUiThread { - progress.setMessage( - getString( - R.string.alert_computing, - done, - project.selected.size + ++done + runOnUiThread { + progress.setMessage( + getString( + R.string.alert_computing, + done, + project.selected.size + ) ) - ) + } } + it + } + runOnUiThread { + updateSelectInfo() + progress.cancel() } - it - } - runOnUiThread { - updateSelectInfo() - progress.cancel() } } } @@ -396,24 +397,25 @@ class EditActivity : Activity() { Toast.makeText(this, R.string.please_select_swap, Toast.LENGTH_SHORT).show() return@setOnClickListener } - project.updateUndo() - val (i, j) = project.selected.map { project.stitchInfo.indexOfFirst { info -> info.imageKey == it } } - if (i < 0 || j < 0) return@setOnClickListener - val a = project.stitchInfo[i] - val b = project.stitchInfo.set(j, a) - project.stitchInfo[i] = b - val adx = a.dx - val ady = a.dy - val adr = a.drot - val ads = a.dscale - a.dx = b.dx - a.dy = b.dy - a.drot = b.drot - a.dscale = b.dscale - b.dx = adx - b.dy = ady - b.drot = adr - b.dscale = ads + project.updateUndo { + val (i, j) = project.selected.map { project.stitchInfo.indexOfFirst { info -> info.imageKey == it } } + if (i < 0 || j < 0) return@updateUndo + val a = project.stitchInfo[i] + val b = project.stitchInfo.set(j, a) + project.stitchInfo[i] = b + val adx = a.dx + val ady = a.dy + val adr = a.drot + val ads = a.dscale + a.dx = b.dx + a.dy = b.dy + a.drot = b.drot + a.dscale = b.dscale + b.dx = adx + b.dy = ady + b.drot = adr + b.dscale = ads + } updateSelectInfo() } findViewById(R.id.menu_remove).setOnClickListener { @@ -425,9 +427,10 @@ class EditActivity : Activity() { .setMessage(getString(R.string.alert_delete, project.selected.size)) .setNegativeButton(R.string.alert_cancel) { _, _ -> } .setPositiveButton(R.string.alert_ok) { _: DialogInterface, _: Int -> - project.updateUndo() - project.stitchInfo.removeAll { project.selected.contains(it.imageKey) } - project.selected.clear() + project.updateUndo { + project.stitchInfo.removeAll { project.selected.contains(it.imageKey) } + project.selected.clear() + } updateSelectInfo() }.show() } @@ -472,47 +475,52 @@ class EditActivity : Activity() { } findViewById(R.id.menu_auto_stitch).setOnClickListener { stitch( - findViewById(R.id.switch_homography).isChecked, - findViewById(R.id.switch_diff).isChecked + findViewById(R.id.switch_homography).isChecked, + findViewById(R.id.switch_diff).isChecked ) } numberA.doAfterTextChanged { if (!numberA.isFocused) return@doAfterTextChanged val newNum = it?.toString()?.toFloatOrNull() ?: return@doAfterTextChanged - project.updateUndo(numberA) - setNumber(newNum) + project.updateUndo(numberA) { + setNumber(newNum) + } updateSeekbar() invalidateView() } numberB.doAfterTextChanged { if (!numberB.isFocused) return@doAfterTextChanged val newNum = it?.toString()?.toFloatOrNull() ?: return@doAfterTextChanged - project.updateUndo(numberB) - setNumber(null, newNum) + project.updateUndo(numberB) { + setNumber(null, newNum) + } updateSeekbar() invalidateView() } numberInc.setOnClickListener { val newNum = (numberA.text.toString().toFloatOrNull() ?: 0f) + 10.0.pow(-(selectItems[selectIndex]?.first ?: 0).toDouble()).toFloat() - project.updateUndo(numberInc) + project.updateUndo(numberInc) { + setNumber(newNum) + } updateNumberView(newNum) - setNumber(newNum) updateSeekbar() invalidateView() } numberDec.setOnClickListener { val newNum = (numberA.text.toString().toFloatOrNull() ?: 0f) - 10.0.pow(-(selectItems[selectIndex]?.first ?: 0).toDouble()).toFloat() - project.updateUndo(numberDec) + project.updateUndo(numberDec) { + setNumber(newNum) + } updateNumberView(newNum) - setNumber(newNum) updateSeekbar() invalidateView() } seekbar.onRangeChange = { a, b -> - project.updateUndo(seekbar) - setNumber(a, b, true) + project.updateUndo(seekbar) { + setNumber(a, b, true) + } updateNumber() invalidateView() } @@ -546,12 +554,14 @@ class EditActivity : Activity() { val count: Int = clipData.itemCount for (i in 0 until count) { - project.updateUndo(data) - addImage(clipData.getItemAt(i).uri) + project.updateUndo(data) { + addImage(clipData.getItemAt(i).uri) + } } } else data?.data?.let { path -> - project.updateUndo(data) - addImage(path) + project.updateUndo(data) { + addImage(path) + } } runOnUiThread { if (requestCode == REQUEST_IMPORT_NEW) { diff --git a/app/src/main/java/soko/ekibun/stitch/EditView.kt b/app/src/main/java/soko/ekibun/stitch/EditView.kt index 6889841..6aac732 100644 --- a/app/src/main/java/soko/ekibun/stitch/EditView.kt +++ b/app/src/main/java/soko/ekibun/stitch/EditView.kt @@ -362,20 +362,21 @@ class EditView(context: Context, attrs: AttributeSet?) : SurfaceView(context, at val x = (event.getX(index) - transX) / scale - downOffsetX val y = (event.getY(index) - transY) / scale - downOffsetY if (abs(initialTouchX - event.x) > 10 || abs(initialTouchY - event.y) > 10) { - if (!dragging) project?.updateUndo() dragging = true } if (dragging) { - val ddx = x - touching.cx - val ddy = y - touching.cy - val cos = cos((touching.rot - touching.drot) * Math.PI / 180).toFloat() - val sin = sin((touching.rot - touching.drot) * Math.PI / 180).toFloat() - val scale = - if (touching.dscale == 0f) 0f else touching.scale / touching.dscale - touching.dx = - touching.dx + if (scale == 0f) 0f else (ddx * cos + ddy * sin) / scale - touching.dy = - touching.dy + if (scale == 0f) 0f else (-ddx * sin + ddy * cos) / scale + project?.updateUndo(touching) { + val ddx = x - touching.cx + val ddy = y - touching.cy + val cos = cos((touching.rot - touching.drot) * Math.PI / 180).toFloat() + val sin = sin((touching.rot - touching.drot) * Math.PI / 180).toFloat() + val scale = + if (touching.dscale == 0f) 0f else touching.scale / touching.dscale + touching.dx = + touching.dx + if (scale == 0f) 0f else (ddx * cos + ddy * sin) / scale + touching.dy = + touching.dy + if (scale == 0f) 0f else (-ddx * sin + ddy * cos) / scale + } (context as? EditActivity)?.updateSelectInfo() } } else { diff --git a/app/src/main/java/soko/ekibun/stitch/Stitch.kt b/app/src/main/java/soko/ekibun/stitch/Stitch.kt index e8bccda..9efd955 100644 --- a/app/src/main/java/soko/ekibun/stitch/Stitch.kt +++ b/app/src/main/java/soko/ekibun/stitch/Stitch.kt @@ -49,30 +49,33 @@ object Stitch { undoTag = null } - fun updateUndo(tag: Any? = System.currentTimeMillis()) { - if (tag == null || tag == undoTag) return - undoTag = tag - selectedBak.clear() - selectedBak.addAll(selected) - stitchInfoBak.clear() - stitchInfoBak.addAll(stitchInfo.map { - it.clone() - }) + fun updateUndo(tag: Any? = System.currentTimeMillis(), runBeforeSave: () -> Unit) { + if (tag != null && tag != undoTag) { + undoTag = tag + selectedBak.clear() + selectedBak.addAll(selected) + stitchInfoBak.clear() + stitchInfoBak.addAll(stitchInfo.map { + it.clone() + }) + } + runBeforeSave() save() } private fun save() { @Suppress("BlockingMethodInNonBlockingContext") MainScope().launch(App.dispatcherIO) { + val info = stitchInfo.toList() if (!file.exists()) { - if (stitchInfo.isNotEmpty()) file.parentFile?.mkdirs() + if (info.isNotEmpty()) file.parentFile?.mkdirs() else return@launch } val os = ObjectOutputStream(file.outputStream()) - val size = stitchInfo.size + val size = info.size os.writeInt(size) for (i in 0 until size) { - os.writeObject(stitchInfo[i]) + os.writeObject(info[i]) } os.close() } @@ -153,17 +156,17 @@ object Stitch { } lastPoints = points - minV = max(minV, minO) / mag2 - maxV = min(maxV, maxO) / mag2 + minV = max(minV, minO) + maxV = max(minV, min(maxV, maxO)) val va = maxV - (maxV - minV) * it.a - val vb = maxV - (maxV - minV) * it.b * (1 + 1e-5f) + val vb = maxV - (maxV - minV) * it.b - 0.01f * sqrt(mag2) it.shader = LinearGradient( - cx - (dx * cos + dy * sin) * va, - cy - (-dx * sin + dy * cos) * va, - cx - (dx * cos + dy * sin) * vb, - cy - (-dx * sin + dy * cos) * vb, + cx - (dx * cos + dy * sin) * va / mag2, + cy - (-dx * sin + dy * cos) * va / mag2, + cx - (dx * cos + dy * sin) * vb / mag2, + cy - (-dx * sin + dy * cos) * vb / mag2, Color.TRANSPARENT, Color.WHITE, Shader.TileMode.CLAMP diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml index 488a0e9..32414d1 100644 --- a/app/src/main/res/layout/activity_edit.xml +++ b/app/src/main/res/layout/activity_edit.xml @@ -4,7 +4,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:background="?android:colorBackground" + android:background="#1000" tools:ignore="UnusedAttribute,ContentDescription,LabelFor"> - - diff --git a/build.gradle b/build.gradle index 234e793..262ec89 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.2.1' + classpath 'com.android.tools.build:gradle:7.2.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10" } }