mirror of
https://github.com/gedoor/legado.git
synced 2024-07-04 23:36:56 +08:00
Compare commits
7 Commits
814d5ddf64
...
f132e92772
Author | SHA1 | Date | |
---|---|---|---|
|
f132e92772 | ||
|
576a370da1 | ||
|
d6c2b5eceb | ||
|
da7093214f | ||
|
dc9ce168c1 | ||
|
0337e465de | ||
|
d1af37e04b |
|
@ -802,8 +802,9 @@ interface JsExtensions : JsEncodeUtils {
|
||||||
if (errorQueryTTF.isBlankUnicode(oldCode)) {
|
if (errorQueryTTF.isBlankUnicode(oldCode)) {
|
||||||
return@forEachIndexed
|
return@forEachIndexed
|
||||||
}
|
}
|
||||||
val glyf = errorQueryTTF.getGlyfByUnicode(oldCode)
|
|
||||||
// 删除轮廓数据不存在的字符
|
// 删除轮廓数据不存在的字符
|
||||||
|
var glyf = errorQueryTTF.getGlyfByUnicode(oldCode) // 轮廓数据不存在
|
||||||
|
if (errorQueryTTF.getGlyfIdByUnicode(oldCode) == 0) glyf = null; // 轮廓数据指向保留索引0
|
||||||
if (filter && (glyf == null)) {
|
if (filter && (glyf == null)) {
|
||||||
contentArray[index] = ""
|
contentArray[index] = ""
|
||||||
return@forEachIndexed
|
return@forEachIndexed
|
||||||
|
|
|
@ -188,7 +188,6 @@ class ContentProcessor private constructor(
|
||||||
mContent = mContent.replace('\u00A0', ' ')
|
mContent = mContent.replace('\u00A0', ' ')
|
||||||
}
|
}
|
||||||
val contents = arrayListOf<String>()
|
val contents = arrayListOf<String>()
|
||||||
val paragraphIndent = ReadBookConfig.paragraphIndent
|
|
||||||
mContent.split("\n").forEach { str ->
|
mContent.split("\n").forEach { str ->
|
||||||
val paragraph = str.trim {
|
val paragraph = str.trim {
|
||||||
it.code <= 0x20 || it == ' '
|
it.code <= 0x20 || it == ' '
|
||||||
|
@ -197,14 +196,10 @@ class ContentProcessor private constructor(
|
||||||
if (contents.isEmpty() && includeTitle) {
|
if (contents.isEmpty() && includeTitle) {
|
||||||
contents.add(paragraph)
|
contents.add(paragraph)
|
||||||
} else {
|
} else {
|
||||||
contents.add("$paragraphIndent$paragraph")
|
contents.add("${ReadBookConfig.paragraphIndent}$paragraph")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (contents.isEmpty()) {
|
|
||||||
contents.add("${paragraphIndent}加载正文失败")
|
|
||||||
contents.add("${paragraphIndent}内容处理后为空")
|
|
||||||
}
|
|
||||||
return BookContent(sameTitleRemoved, contents, effectiveReplaceRules)
|
return BookContent(sameTitleRemoved, contents, effectiveReplaceRules)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -648,6 +648,8 @@ public class QueryTTF {
|
||||||
var reader = new BufferReader(buffer, dataTable.offset);
|
var reader = new BufferReader(buffer, dataTable.offset);
|
||||||
if (head.indexToLocFormat == 0) {
|
if (head.indexToLocFormat == 0) {
|
||||||
loca = reader.ReadUInt16Array(dataTable.length / 2);
|
loca = reader.ReadUInt16Array(dataTable.length / 2);
|
||||||
|
// 当loca表数据长度为Uint16时,需要翻倍
|
||||||
|
for (var i = 0; i < loca.length; i++) loca[i] *= 2;
|
||||||
} else {
|
} else {
|
||||||
loca = reader.ReadInt32Array(dataTable.length / 4);
|
loca = reader.ReadInt32Array(dataTable.length / 4);
|
||||||
}
|
}
|
||||||
|
@ -712,7 +714,7 @@ public class QueryTTF {
|
||||||
if (idRangeOffset == 0) {
|
if (idRangeOffset == 0) {
|
||||||
unicodeToGlyphId.put(unicode, (unicode + idDelta) & 0xFFFF);
|
unicodeToGlyphId.put(unicode, (unicode + idDelta) & 0xFFFF);
|
||||||
} else {
|
} else {
|
||||||
int gIndex = (idRangeOffset / 2) + unicode - unicodeInclusive + segmentIndex;
|
int gIndex = (idRangeOffset / 2) + unicode - unicodeInclusive + segmentIndex - segCount;
|
||||||
unicodeToGlyphId.put(unicode, gIndex < glyphIdArrayLength ? f.glyphIdArray[gIndex] + idDelta : 0);
|
unicodeToGlyphId.put(unicode, gIndex < glyphIdArrayLength ? f.glyphIdArray[gIndex] + idDelta : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -771,21 +773,24 @@ public class QueryTTF {
|
||||||
var dataTable = directorys.get("glyf");
|
var dataTable = directorys.get("glyf");
|
||||||
assert dataTable != null;
|
assert dataTable != null;
|
||||||
int glyfCount = maxp.numGlyphs;
|
int glyfCount = maxp.numGlyphs;
|
||||||
glyfArray = new GlyfLayout[glyfCount + 1]; // 创建容器时,多创建一个作为保留区
|
glyfArray = new GlyfLayout[glyfCount]; // 创建字形容器
|
||||||
|
|
||||||
var reader = new BufferReader(buffer, 0);
|
var reader = new BufferReader(buffer, 0);
|
||||||
for (int index = 1; index <= glyfCount; index++) {
|
for (int index = 0; index < glyfCount; index++) {
|
||||||
if (loca[index - 1] == loca[index]) continue; // 当前loca与下一个loca相同,表示这个字形不存在
|
if (loca[index] == loca[index + 1]) continue; // 当前loca与下一个loca相同,表示这个字形不存在
|
||||||
int offset = dataTable.offset + loca[index - 1];
|
int offset = dataTable.offset + loca[index];
|
||||||
// 读GlyphHeaders
|
// 读GlyphHeaders
|
||||||
var glyph = new GlyfLayout();
|
var glyph = new GlyfLayout();
|
||||||
reader.position(offset);
|
reader.position(offset);
|
||||||
glyph.numberOfContours = reader.ReadInt16();
|
glyph.numberOfContours = reader.ReadInt16();
|
||||||
|
if (glyph.numberOfContours > maxp.maxContours) continue; // 如果字形轮廓数大于非复合字形中包含的最大轮廓数,则说明该字形无效。
|
||||||
glyph.xMin = reader.ReadInt16();
|
glyph.xMin = reader.ReadInt16();
|
||||||
glyph.yMin = reader.ReadInt16();
|
glyph.yMin = reader.ReadInt16();
|
||||||
glyph.xMax = reader.ReadInt16();
|
glyph.xMax = reader.ReadInt16();
|
||||||
glyph.yMax = reader.ReadInt16();
|
glyph.yMax = reader.ReadInt16();
|
||||||
|
|
||||||
|
// 轮廓数为0时,不需要解析轮廓数据
|
||||||
|
if (glyph.numberOfContours == 0) continue;
|
||||||
// 读Glyph轮廓数据
|
// 读Glyph轮廓数据
|
||||||
if (glyph.numberOfContours > 0) {
|
if (glyph.numberOfContours > 0) {
|
||||||
// 简单轮廓
|
// 简单轮廓
|
||||||
|
@ -888,7 +893,7 @@ public class QueryTTF {
|
||||||
if ((glyphTableComponent.flags & 0x20) == 0) break;
|
if ((glyphTableComponent.flags & 0x20) == 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glyfArray[index] = glyph; // 根据文档 glyfId=0 作为保留区使用,这里赋值从索引1开始
|
glyfArray[index] = glyph;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,7 +919,15 @@ public class QueryTTF {
|
||||||
// 复合字形
|
// 复合字形
|
||||||
LinkedList<String> glyphIdList = new LinkedList<>();
|
LinkedList<String> glyphIdList = new LinkedList<>();
|
||||||
for (var g : glyph.glyphComponent) {
|
for (var g : glyph.glyphComponent) {
|
||||||
glyphIdList.add(String.valueOf(g.glyphIndex));
|
glyphIdList.add("{" +
|
||||||
|
"flags:" + g.flags + "," +
|
||||||
|
"glyphIndex:" + g.glyphIndex + "," +
|
||||||
|
"arg1:" + g.argument1 + "," +
|
||||||
|
"arg2:" + g.argument2 + "," +
|
||||||
|
"xScale:" + g.xScale + "," +
|
||||||
|
"scale01:" + g.scale01 + "," +
|
||||||
|
"scale10:" + g.scale10 + "," +
|
||||||
|
"yScale:" + g.yScale + "}");
|
||||||
}
|
}
|
||||||
glyphString = "[" + String.join(",", glyphIdList) + "]";
|
glyphString = "[" + String.join(",", glyphIdList) + "]";
|
||||||
}
|
}
|
||||||
|
@ -960,10 +973,11 @@ public class QueryTTF {
|
||||||
int glyfArrayLength = glyfArray.length;
|
int glyfArrayLength = glyfArray.length;
|
||||||
for (var item : unicodeToGlyphId.entrySet()) {
|
for (var item : unicodeToGlyphId.entrySet()) {
|
||||||
int key = item.getKey();
|
int key = item.getKey();
|
||||||
int val = item.getValue() + 1; // glyphArray已根据TTF文档将索引0作为保留位,这里从1开始索引
|
int val = item.getValue();
|
||||||
if (val >= glyfArrayLength) continue;
|
if (val >= glyfArrayLength) continue;
|
||||||
String glyfString = getGlyfById(val);
|
String glyfString = getGlyfById(val);
|
||||||
unicodeToGlyph.put(key, glyfString);
|
unicodeToGlyph.put(key, glyfString);
|
||||||
|
if (glyfString == null) continue; // null 不能用作hashmap的key
|
||||||
glyphToUnicode.put(glyfString, key);
|
glyphToUnicode.put(glyfString, key);
|
||||||
}
|
}
|
||||||
// Log.i("QueryTTF", "字体处理完成");
|
// Log.i("QueryTTF", "字体处理完成");
|
||||||
|
@ -981,8 +995,8 @@ public class QueryTTF {
|
||||||
*/
|
*/
|
||||||
public int getGlyfIdByUnicode(int unicode) {
|
public int getGlyfIdByUnicode(int unicode) {
|
||||||
var result = unicodeToGlyphId.get(unicode);
|
var result = unicodeToGlyphId.get(unicode);
|
||||||
if (result == null) return 0;
|
if (result == null) return 0; // 如果找不到Unicode对应的轮廓索引,就返回默认值0
|
||||||
return result + 1; // 根据TTF文档,轮廓索引的定义从1开始
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1003,7 +1017,7 @@ public class QueryTTF {
|
||||||
*/
|
*/
|
||||||
public int getUnicodeByGlyf(String glyph) {
|
public int getUnicodeByGlyf(String glyph) {
|
||||||
var result = glyphToUnicode.get(glyph);
|
var result = glyphToUnicode.get(glyph);
|
||||||
if (result == null) return 0;
|
if (result == null) return 0; // 如果轮廓数据找不到对应的Unicode,就返回默认值0
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ abstract class BaseReadAloudService : BaseService(),
|
||||||
}
|
}
|
||||||
nowSpeak = textChapter.getParagraphNum(readAloudNumber + 1, readAloudByPage) - 1
|
nowSpeak = textChapter.getParagraphNum(readAloudNumber + 1, readAloudByPage) - 1
|
||||||
if (!readAloudByPage && startPos == 0 && !toLast) {
|
if (!readAloudByPage && startPos == 0 && !toLast) {
|
||||||
pos = page.lines.first().chapterPosition -
|
pos = page.chapterPosition -
|
||||||
textChapter.paragraphs[nowSpeak].chapterPosition
|
textChapter.paragraphs[nowSpeak].chapterPosition
|
||||||
}
|
}
|
||||||
if (toLast) {
|
if (toLast) {
|
||||||
|
@ -226,7 +226,7 @@ abstract class BaseReadAloudService : BaseService(),
|
||||||
readAloudNumber = textChapter.getLastParagraphPosition()
|
readAloudNumber = textChapter.getLastParagraphPosition()
|
||||||
nowSpeak = contentList.lastIndex
|
nowSpeak = contentList.lastIndex
|
||||||
if (page.paragraphs.size == 1) {
|
if (page.paragraphs.size == 1) {
|
||||||
pos = page.lines.first().chapterPosition -
|
pos = page.chapterPosition -
|
||||||
textChapter.paragraphs[nowSpeak].chapterPosition
|
textChapter.paragraphs[nowSpeak].chapterPosition
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ data class TextChapter(
|
||||||
*/
|
*/
|
||||||
fun getReadLength(pageIndex: Int): Int {
|
fun getReadLength(pageIndex: Int): Int {
|
||||||
if (pageIndex < 0) return 0
|
if (pageIndex < 0) return 0
|
||||||
return pages[min(pageIndex, lastIndex)].lines.first().chapterPosition
|
return pages[min(pageIndex, lastIndex)].chapterPosition
|
||||||
/*
|
/*
|
||||||
var length = 0
|
var length = 0
|
||||||
val maxIndex = min(pageIndex, pages.size)
|
val maxIndex = min(pageIndex, pages.size)
|
||||||
|
@ -224,14 +224,13 @@ data class TextChapter(
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
val bIndex = pages.fastBinarySearchBy(charIndex, 0, pageSize) {
|
val bIndex = pages.fastBinarySearchBy(charIndex, 0, pageSize) {
|
||||||
it.lines.first().chapterPosition
|
it.chapterPosition
|
||||||
}
|
}
|
||||||
val index = abs(bIndex + 1) - 1
|
val index = abs(bIndex + 1) - 1
|
||||||
// 判断是否已经排版到 charIndex ,没有则返回 -1
|
// 判断是否已经排版到 charIndex ,没有则返回 -1
|
||||||
if (!isCompleted && index == pageSize - 1) {
|
if (!isCompleted && index == pageSize - 1) {
|
||||||
val page = pages[index]
|
val page = pages[index]
|
||||||
val line = page.lines.first()
|
val pageEndPos = page.chapterPosition + page.charSize
|
||||||
val pageEndPos = line.chapterPosition + page.charSize
|
|
||||||
if (charIndex > pageEndPos) {
|
if (charIndex > pageEndPos) {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ data class TextPage(
|
||||||
val lines: List<TextLine> get() = textLines
|
val lines: List<TextLine> get() = textLines
|
||||||
val lineSize: Int get() = textLines.size
|
val lineSize: Int get() = textLines.size
|
||||||
val charSize: Int get() = text.length.coerceAtLeast(1)
|
val charSize: Int get() = text.length.coerceAtLeast(1)
|
||||||
|
val chapterPosition: Int get() = textLines.first().chapterPosition
|
||||||
val searchResult = hashSetOf<TextColumn>()
|
val searchResult = hashSetOf<TextColumn>()
|
||||||
var isMsgPage: Boolean = false
|
var isMsgPage: Boolean = false
|
||||||
var canvasRecorder = CanvasRecorderFactory.create(true)
|
var canvasRecorder = CanvasRecorderFactory.create(true)
|
||||||
|
|
|
@ -177,7 +177,7 @@ class TextChapterLayout(
|
||||||
val contents = bookContent.textList
|
val contents = bookContent.textList
|
||||||
var absStartX = paddingLeft
|
var absStartX = paddingLeft
|
||||||
var durY = 0f
|
var durY = 0f
|
||||||
if (ReadBookConfig.titleMode != 2 || bookChapter.isVolume) {
|
if (ReadBookConfig.titleMode != 2 || bookChapter.isVolume || contents.isEmpty()) {
|
||||||
//标题非隐藏
|
//标题非隐藏
|
||||||
displayTitle.splitNotBlank("\n").forEach { text ->
|
displayTitle.splitNotBlank("\n").forEach { text ->
|
||||||
setTypeText(
|
setTypeText(
|
||||||
|
|
|
@ -38,7 +38,7 @@ quickChineseTransfer = "0.2.13"
|
||||||
room = "2.6.1"
|
room = "2.6.1"
|
||||||
splitties = "3.0.0"
|
splitties = "3.0.0"
|
||||||
|
|
||||||
activity = "1.8.2"
|
activity = "1.9.0"
|
||||||
kotlinxSerialization = "1.6.3"
|
kotlinxSerialization = "1.6.3"
|
||||||
swiperefreshlayout = "1.1.0"
|
swiperefreshlayout = "1.1.0"
|
||||||
viewpager2 = "1.0.0"
|
viewpager2 = "1.0.0"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user