Merge branch 'gedoor:master' into master

This commit is contained in:
Xwite
2022-04-13 16:14:17 +08:00
committed by GitHub
3 changed files with 92 additions and 41 deletions
@@ -171,18 +171,19 @@ class ContentTextView(context: Context, attrs: AttributeSet?) : View(context, at
book, book,
textChar.charData, textChar.charData,
ReadBook.bookSource, ReadBook.bookSource,
true (textChar.end - textChar.start).toInt(),
)?.let { (lineBottom - lineTop).toInt()
)?.let { bitmap ->
val rectF = if (isImageLine) { val rectF = if (isImageLine) {
RectF(textChar.start, lineTop, textChar.end, lineBottom) RectF(textChar.start, lineTop, textChar.end, lineBottom)
} else { } else {
/*以宽度为基准保持图片的原始比例叠加,当div为负数时,允许高度比字符更高*/ /*以宽度为基准保持图片的原始比例叠加,当div为负数时,允许高度比字符更高*/
val h = (textChar.end - textChar.start) / it.width * it.height val h = (textChar.end - textChar.start) / bitmap.width * bitmap.height
val div = (lineBottom - lineTop - h) / 2 val div = (lineBottom - lineTop - h) / 2
RectF(textChar.start, lineTop + div, textChar.end, lineBottom - div) RectF(textChar.start, lineTop + div, textChar.end, lineBottom - div)
} }
kotlin.runCatching { kotlin.runCatching {
canvas.drawBitmap(it, null, rectF, null) canvas.drawBitmap(bitmap, null, rectF, null)
}.onFailure { e -> }.onFailure { e ->
context.toastOnUi(e.localizedMessage) context.toastOnUi(e.localizedMessage)
} }
@@ -101,7 +101,7 @@ object ChapterProvider {
/** /**
* 获取拆分完的章节数据 * 获取拆分完的章节数据
*/ */
fun getTextChapter( suspend fun getTextChapter(
book: Book, book: Book,
bookChapter: BookChapter, bookChapter: BookChapter,
displayTitle: String, displayTitle: String,
@@ -136,7 +136,6 @@ object ChapterProvider {
while (matcher.find()) { while (matcher.find()) {
matcher.group(1)?.let { src -> matcher.group(1)?.let { src ->
srcList.add(src) srcList.add(src)
ImageProvider.getImage(book, src, ReadBook.bookSource)
matcher.appendReplacement(sb, srcReplaceChar) matcher.appendReplacement(sb, srcReplaceChar)
} }
} }
@@ -200,7 +199,7 @@ object ChapterProvider {
) )
} }
private fun setTypeImage( private suspend fun setTypeImage(
book: Book, book: Book,
src: String, src: String,
x: Int, x: Int,
@@ -209,7 +208,7 @@ object ChapterProvider {
imageStyle: String?, imageStyle: String?,
): Float { ): Float {
var durY = y var durY = y
ImageProvider.getImage(book, src, ReadBook.bookSource)?.let { ImageProvider.getImageSize(book, src, ReadBook.bookSource).let {
if (durY > visibleHeight) { if (durY > visibleHeight) {
textPages.last().height = durY textPages.last().height = durY
textPages.add(TextPage()) textPages.add(TextPage())
@@ -1,6 +1,8 @@
package io.legado.app.ui.book.read.page.provider package io.legado.app.ui.book.read.page.provider
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Size
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.AppLog.putDebug import io.legado.app.constant.AppLog.putDebug
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
@@ -10,59 +12,108 @@ import io.legado.app.help.coroutine.Coroutine
import io.legado.app.help.glide.ImageLoader import io.legado.app.help.glide.ImageLoader
import io.legado.app.model.localBook.EpubFile import io.legado.app.model.localBook.EpubFile
import io.legado.app.utils.FileUtils import io.legado.app.utils.FileUtils
import io.legado.app.utils.BitmapUtils
import io.legado.app.utils.isXml import io.legado.app.utils.isXml
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.suspendCancellableCoroutine
import splitties.init.appCtx import splitties.init.appCtx
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import kotlin.coroutines.resume
object ImageProvider { object ImageProvider {
private val errorBitmap: Bitmap? by lazy { private val errorBitmap: Bitmap by lazy {
BitmapUtils.decodeBitmap( BitmapFactory.decodeResource(appCtx.resources, R.drawable.image_loading_error)
appCtx, }
R.drawable.image_loading_error,
ChapterProvider.visibleWidth, private suspend fun cacheImage(
ChapterProvider.visibleHeight book: Book,
) src: String,
bookSource: BookSource?
): File {
val vFile = BookHelp.getImage(book, src)
if (!vFile.exists()) {
if (book.isEpub()) {
EpubFile.getImage(book, src)?.use { input ->
val newFile = FileUtils.createFileIfNotExist(vFile.absolutePath)
@Suppress("BlockingMethodInNonBlockingContext")
FileOutputStream(newFile).use { output ->
input.copyTo(output)
}
}
} else {
BookHelp.saveImage(bookSource, book, src)
}
}
return vFile
}
suspend fun getImageSize(
book: Book,
src: String,
bookSource: BookSource?
): Size {
val file = cacheImage(book, src, bookSource)
return suspendCancellableCoroutine { block ->
kotlin.runCatching {
ImageLoader.loadBitmap(appCtx, file.absolutePath).submit()
.getSize { width, height ->
block.resume(Size(width, height))
}
}.onFailure {
block.resume(Size(errorBitmap.width, errorBitmap.height))
}
}
} }
fun getImage( fun getImage(
book: Book, book: Book,
src: String, src: String,
bookSource: BookSource?, bookSource: BookSource?,
onUi: Boolean = false, width: Int,
height: Int
): Bitmap? { ): Bitmap? {
val vFile = BookHelp.getImage(book, src) val vFile = runBlocking {
if (!vFile.exists()) { cacheImage(book, src, bookSource)
if (book.isEpub()) { }
EpubFile.getImage(book, src)?.use { input -> return try {
val newFile = FileUtils.createFileIfNotExist(vFile.absolutePath) ImageLoader.loadBitmap(appCtx, vFile.absolutePath)
FileOutputStream(newFile).use { output -> .submit(width, height)
input.copyTo(output) .get()
} } catch (e: Exception) {
} Coroutine.async {
} else if (!onUi) { putDebug("${vFile.absolutePath} 解码失败", e)
runBlocking { if (FileUtils.readText(vFile.absolutePath).isXml()) {
BookHelp.saveImage(bookSource, book, src) putDebug("${vFile.absolutePath}为xml,自动删除")
vFile.delete()
} }
} }
errorBitmap
} }
return try { }
fun getImage(
book: Book,
src: String,
bookSource: BookSource?
): Bitmap? {
val vFile = runBlocking {
cacheImage(book, src, bookSource)
}
return try {
ImageLoader.loadBitmap(appCtx, vFile.absolutePath) ImageLoader.loadBitmap(appCtx, vFile.absolutePath)
.submit(ChapterProvider.visibleWidth,ChapterProvider.visibleHeight) .submit(ChapterProvider.visibleWidth, ChapterProvider.visibleHeight)
.get() .get()
} catch (e: Exception) { } catch (e: Exception) {
Coroutine.async { Coroutine.async {
putDebug("${vFile.absolutePath} 解码失败", e) putDebug("${vFile.absolutePath} 解码失败", e)
if (FileUtils.readText(vFile.absolutePath).isXml()) { if (FileUtils.readText(vFile.absolutePath).isXml()) {
putDebug("${vFile.absolutePath}为xml,自动删除") putDebug("${vFile.absolutePath}为xml,自动删除")
vFile.delete() vFile.delete()
} }
} }
errorBitmap errorBitmap
} }
} }
} }