diff --git a/app/build.gradle b/app/build.gradle index f99250810..f1ad1c604 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -82,11 +82,7 @@ afterEvaluate { } dependencies { //noinspection GradleDependency - // TODO: change bac -// implementation('com.github.KotatsuApp:kotatsu-parsers:078b59b1e2') { -// exclude group: 'org.json', module: 'json' -// } - implementation('com.github.AwkwardPeak7:kotatsu-parsers:d7d42465de') { + implementation('com.github.KotatsuApp:kotatsu-parsers:350bc0ad58') { exclude group: 'org.json', module: 'json' } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/BitmapImpl.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/BitmapImpl.kt deleted file mode 100644 index b55e8333d..000000000 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/BitmapImpl.kt +++ /dev/null @@ -1,48 +0,0 @@ -package org.koitharu.kotatsu.core.parser - -import android.graphics.Canvas -import android.graphics.Bitmap as AndroidBitmap -import android.graphics.Rect as AndroidRect -import org.koitharu.kotatsu.parsers.bitmap.Bitmap -import org.koitharu.kotatsu.parsers.bitmap.Rect - -class BitmapImpl private constructor() : Bitmap { - - lateinit var androidBitmap: AndroidBitmap - - private lateinit var canvas: Canvas - - override val height: Int - get() = androidBitmap.height - - override val width: Int - get() = androidBitmap.width - - override fun drawBitmap(sourceBitmap: Bitmap, src: Rect, dst: Rect) { - val androidSourceBitmap = (sourceBitmap as BitmapImpl).androidBitmap - - canvas.drawBitmap(androidSourceBitmap, src.toAndroidRect(), dst.toAndroidRect(), null) - } - - companion object { - fun create(width: Int, height: Int): Bitmap { - val instance = BitmapImpl() - instance.androidBitmap = AndroidBitmap.createBitmap(width, height, AndroidBitmap.Config.ARGB_8888) - instance.canvas = Canvas(instance.androidBitmap) - - return instance - } - - fun create(bitmap: AndroidBitmap): Bitmap { - val instance = BitmapImpl() - instance.androidBitmap = bitmap.copy(AndroidBitmap.Config.ARGB_8888, true) - instance.canvas = Canvas(instance.androidBitmap) - - return instance - } - } -} - -private fun Rect.toAndroidRect(): AndroidRect { - return AndroidRect(left, top, right, bottom) -} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/BitmapWrapper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/BitmapWrapper.kt new file mode 100644 index 000000000..13d429091 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/BitmapWrapper.kt @@ -0,0 +1,43 @@ +package org.koitharu.kotatsu.core.parser + +import android.graphics.Canvas +import org.koitharu.kotatsu.parsers.bitmap.Bitmap +import org.koitharu.kotatsu.parsers.bitmap.Rect +import java.io.OutputStream +import android.graphics.Bitmap as AndroidBitmap +import android.graphics.Rect as AndroidRect + +class BitmapWrapper private constructor( + private val androidBitmap: AndroidBitmap, +) : Bitmap { + + private val canvas by lazy { Canvas(androidBitmap) } // is not always used, so initialized lazily + + override val height: Int + get() = androidBitmap.height + + override val width: Int + get() = androidBitmap.width + + override fun drawBitmap(sourceBitmap: Bitmap, src: Rect, dst: Rect) { + val androidSourceBitmap = (sourceBitmap as BitmapWrapper).androidBitmap + canvas.drawBitmap(androidSourceBitmap, src.toAndroidRect(), dst.toAndroidRect(), null) + } + + fun compressTo(output: OutputStream) { + androidBitmap.compress(AndroidBitmap.CompressFormat.PNG, 100, output) + } + + companion object { + + fun create(width: Int, height: Int): Bitmap = BitmapWrapper( + AndroidBitmap.createBitmap(width, height, AndroidBitmap.Config.ARGB_8888), + ) + + fun create(bitmap: AndroidBitmap): Bitmap = BitmapWrapper( + if (bitmap.isMutable) bitmap else bitmap.copy(AndroidBitmap.Config.ARGB_8888, true), + ) + + private fun Rect.toAndroidRect() = AndroidRect(left, top, right, bottom) + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt index bfb8b8eae..a4fe4fa25 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/MangaLoaderContextImpl.kt @@ -1,6 +1,5 @@ package org.koitharu.kotatsu.core.parser -import android.graphics.Bitmap as AndroidBitmap import android.annotation.SuppressLint import android.content.Context import android.graphics.BitmapFactory @@ -22,6 +21,7 @@ import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.prefs.SourceSettings import org.koitharu.kotatsu.core.util.ext.configureForParser import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug +import org.koitharu.kotatsu.core.util.ext.requireBody import org.koitharu.kotatsu.core.util.ext.sanitizeHeaderValue import org.koitharu.kotatsu.core.util.ext.toList import org.koitharu.kotatsu.parsers.MangaLoaderContext @@ -76,17 +76,16 @@ class MangaLoaderContextImpl @Inject constructor( } override fun redrawImageResponse(response: Response, redraw: (image: Bitmap) -> Bitmap): Response { - val image = requireNotNull(response.body) { - "Response is null" - }.byteStream() + val image = response.requireBody().byteStream() - val bitmap = BitmapFactory.decodeStream(image) - val result = redraw(BitmapImpl.create(bitmap)) as BitmapImpl + val opts = BitmapFactory.Options() + opts.inMutable = true + val bitmap = BitmapFactory.decodeStream(image, null, opts) ?: error("Cannot decode bitmap") + val result = redraw(BitmapWrapper.create(bitmap)) as BitmapWrapper - val body = Buffer().run { - result.androidBitmap.compress(AndroidBitmap.CompressFormat.JPEG, 90, outputStream()) - asResponseBody("image/jpeg".toMediaType()) - } + val body = Buffer().also { + result.compressTo(it.outputStream()) + }.asResponseBody("image/jpeg".toMediaType()) return response.newBuilder() .body(body) @@ -94,7 +93,7 @@ class MangaLoaderContextImpl @Inject constructor( } override fun createBitmap(width: Int, height: Int): Bitmap { - return BitmapImpl.create(width, height) + return BitmapWrapper.create(width, height) } @MainThread diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt index 0a0c41e40..fcdfefe96 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/parser/favicon/FaviconFetcher.kt @@ -150,10 +150,6 @@ class FaviconFetcher( return if (networkResponse != null) DataSource.NETWORK else DataSource.DISK } - private fun Response.requireBody(): ResponseBody { - return checkNotNull(body) { "response body == null" } - } - private fun Size.toCacheKey() = buildString { append(width.toString()) append('x') diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Http.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Http.kt index a95e7508b..018d594e1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Http.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Http.kt @@ -1,13 +1,12 @@ package org.koitharu.kotatsu.core.util.ext import okhttp3.Cookie -import okhttp3.Headers import okhttp3.HttpUrl import okhttp3.MediaType.Companion.toMediaType import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.Response +import okhttp3.ResponseBody import okhttp3.internal.closeQuietly -import okhttp3.internal.isSensitiveHeader import okio.IOException import org.json.JSONObject import org.jsoup.HttpStatusException @@ -42,6 +41,8 @@ fun Response.ensureSuccess() = apply { } } +fun Response.requireBody(): ResponseBody = checkNotNull(body) { "Response body is null" } + fun Cookie.newBuilder(): Cookie.Builder = Cookie.Builder().also { c -> c.name(name) c.value(value)