Merge pull request #10 from gedoor/master

Sys Code
pull/978/head
ag2s20150909 4 years ago committed by GitHub
commit 238df3dc05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/src/main/java/io/legado/app/constant/PreferKey.kt
  2. 6
      app/src/main/java/io/legado/app/help/AppConfig.kt
  3. 294
      app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.java
  4. 13
      app/src/main/java/io/legado/app/service/help/ReadBook.kt
  5. 14
      app/src/main/java/io/legado/app/ui/config/OtherConfigFragment.kt
  6. 5
      app/src/main/java/io/legado/app/ui/main/MainViewModel.kt
  7. 2
      app/src/main/res/values-zh-rHK/strings.xml
  8. 2
      app/src/main/res/values-zh-rTW/strings.xml
  9. 2
      app/src/main/res/values-zh/strings.xml
  10. 2
      app/src/main/res/values/strings.xml
  11. 5
      app/src/main/res/xml/pref_config_other.xml

@ -66,7 +66,7 @@ object PreferKey {
const val importKeepName = "importKeepName" const val importKeepName = "importKeepName"
const val screenOrientation = "screenOrientation" const val screenOrientation = "screenOrientation"
const val syncBookProgress = "syncBookProgress" const val syncBookProgress = "syncBookProgress"
const val preDownload = "preDownload" const val preDownloadNum = "preDownloadNum"
const val autoRefresh = "auto_refresh" const val autoRefresh = "auto_refresh"
const val defaultToRead = "defaultToRead" const val defaultToRead = "defaultToRead"
const val exportCharset = "exportCharset" const val exportCharset = "exportCharset"

@ -184,7 +184,11 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
val syncBookProgress get() = appCtx.getPrefBoolean(PreferKey.syncBookProgress, true) val syncBookProgress get() = appCtx.getPrefBoolean(PreferKey.syncBookProgress, true)
val preDownload get() = appCtx.getPrefBoolean(PreferKey.preDownload, true) var preDownloadNum
get() = appCtx.getPrefInt(PreferKey.preDownloadNum, 10)
set(value) {
appCtx.putPrefInt(PreferKey.preDownloadNum, value)
}
val mediaButtonOnExit get() = appCtx.getPrefBoolean("mediaButtonOnExit", true) val mediaButtonOnExit get() = appCtx.getPrefBoolean("mediaButtonOnExit", true)

@ -147,19 +147,19 @@ public class QueryTTF {
} }
private static class ByteArrayReader { private static class ByteArrayReader {
public int Index; public int index;
public byte[] Buffer; public byte[] buffer;
public ByteArrayReader(byte[] buffer, int index) { public ByteArrayReader(byte[] buffer, int index) {
Buffer = buffer; this.buffer = buffer;
Index = index; this.index = index;
} }
public long ReadUIntX(long len) { public long ReadUIntX(long len) {
long result = 0; long result = 0;
for (long i = 0; i < len; ++i) { for (long i = 0; i < len; ++i) {
result <<= 8; result <<= 8;
result |= Buffer[Index++] & 0xFF; result |= buffer[index++] & 0xFF;
} }
return result; return result;
} }
@ -187,17 +187,17 @@ public class QueryTTF {
public String ReadStrings(int len, Charset charset) { public String ReadStrings(int len, Charset charset) {
byte[] result = len > 0 ? new byte[len] : null; byte[] result = len > 0 ? new byte[len] : null;
for (int i = 0; i < len; ++i) result[i] = Buffer[Index++]; for (int i = 0; i < len; ++i) result[i] = buffer[index++];
return new String(result, charset); return new String(result, charset);
} }
public byte GetByte() { public byte GetByte() {
return Buffer[Index++]; return buffer[index++];
} }
public byte[] GetBytes(int len) { public byte[] GetBytes(int len) {
byte[] result = len > 0 ? new byte[len] : null; byte[] result = len > 0 ? new byte[len] : null;
for (int i = 0; i < len; ++i) result[i] = Buffer[Index++]; for (int i = 0; i < len; ++i) result[i] = buffer[index++];
return result; return result;
} }
@ -214,10 +214,10 @@ public class QueryTTF {
} }
} }
private final ByteArrayReader FontReader; private final ByteArrayReader fontReader;
private final Header fileHeader = new Header(); private final Header fileHeader = new Header();
private final List<Directory> Directorys = new LinkedList<>(); private final List<Directory> directorys = new LinkedList<>();
private final NameLayout Name = new NameLayout(); private final NameLayout name = new NameLayout();
private final HeadLayout head = new HeadLayout(); private final HeadLayout head = new HeadLayout();
private final MaxpLayout maxp = new MaxpLayout(); private final MaxpLayout maxp = new MaxpLayout();
private final List<Integer> loca = new LinkedList<>(); private final List<Integer> loca = new LinkedList<>();
@ -232,10 +232,10 @@ public class QueryTTF {
Pair.of(0, 1) Pair.of(0, 1)
}; };
public final Map<Integer, String> CodeToGlyph = new HashMap<>(); public final Map<Integer, String> codeToGlyph = new HashMap<>();
public final Map<String, Integer> GlyphToCode = new HashMap<>(); public final Map<String, Integer> glyphToCode = new HashMap<>();
private int LimitMix = 0; private int limitMix = 0;
private int LimitMax = 0; private int limitMax = 0;
/** /**
* 构造函数 * 构造函数
@ -243,162 +243,162 @@ public class QueryTTF {
* @param buffer 传入TTF字体二进制数组 * @param buffer 传入TTF字体二进制数组
*/ */
public QueryTTF(byte[] buffer) { public QueryTTF(byte[] buffer) {
FontReader = new ByteArrayReader(buffer, 0); fontReader = new ByteArrayReader(buffer, 0);
// 获取文件头 // 获取文件头
fileHeader.majorVersion = FontReader.ReadUInt16(); fileHeader.majorVersion = fontReader.ReadUInt16();
fileHeader.minorVersion = FontReader.ReadUInt16(); fileHeader.minorVersion = fontReader.ReadUInt16();
fileHeader.numOfTables = FontReader.ReadUInt16(); fileHeader.numOfTables = fontReader.ReadUInt16();
fileHeader.searchRange = FontReader.ReadUInt16(); fileHeader.searchRange = fontReader.ReadUInt16();
fileHeader.entrySelector = FontReader.ReadUInt16(); fileHeader.entrySelector = fontReader.ReadUInt16();
fileHeader.rangeShift = FontReader.ReadUInt16(); fileHeader.rangeShift = fontReader.ReadUInt16();
// 获取目录 // 获取目录
for (int i = 0; i < fileHeader.numOfTables; ++i) { for (int i = 0; i < fileHeader.numOfTables; ++i) {
Directory d = new Directory(); Directory d = new Directory();
d.tag = FontReader.ReadStrings(4, StandardCharsets.US_ASCII); d.tag = fontReader.ReadStrings(4, StandardCharsets.US_ASCII);
d.checkSum = FontReader.ReadUInt32(); d.checkSum = fontReader.ReadUInt32();
d.offset = FontReader.ReadUInt32(); d.offset = fontReader.ReadUInt32();
d.length = FontReader.ReadUInt32(); d.length = fontReader.ReadUInt32();
Directorys.add(d); directorys.add(d);
} }
// 解析表 name (字体信息,包含版权、名称、作者等...) // 解析表 name (字体信息,包含版权、名称、作者等...)
for (Directory Temp : Directorys) { for (Directory Temp : directorys) {
if (Temp.tag.equals("name")) { if (Temp.tag.equals("name")) {
FontReader.Index = Temp.offset; fontReader.index = Temp.offset;
Name.format = FontReader.ReadUInt16(); name.format = fontReader.ReadUInt16();
Name.count = FontReader.ReadUInt16(); name.count = fontReader.ReadUInt16();
Name.stringOffset = FontReader.ReadUInt16(); name.stringOffset = fontReader.ReadUInt16();
for (int i = 0; i < Name.count; ++i) { for (int i = 0; i < name.count; ++i) {
NameRecord record = new NameRecord(); NameRecord record = new NameRecord();
record.platformID = FontReader.ReadUInt16(); record.platformID = fontReader.ReadUInt16();
record.encodingID = FontReader.ReadUInt16(); record.encodingID = fontReader.ReadUInt16();
record.languageID = FontReader.ReadUInt16(); record.languageID = fontReader.ReadUInt16();
record.nameID = FontReader.ReadUInt16(); record.nameID = fontReader.ReadUInt16();
record.length = FontReader.ReadUInt16(); record.length = fontReader.ReadUInt16();
record.offset = FontReader.ReadUInt16(); record.offset = fontReader.ReadUInt16();
Name.records.add(record); name.records.add(record);
} }
} }
} }
// 解析表 head (获取 head.indexToLocFormat) // 解析表 head (获取 head.indexToLocFormat)
for (Directory Temp : Directorys) { for (Directory Temp : directorys) {
if (Temp.tag.equals("head")) { if (Temp.tag.equals("head")) {
FontReader.Index = Temp.offset; fontReader.index = Temp.offset;
head.majorVersion = FontReader.ReadUInt16(); head.majorVersion = fontReader.ReadUInt16();
head.minorVersion = FontReader.ReadUInt16(); head.minorVersion = fontReader.ReadUInt16();
head.fontRevision = FontReader.ReadUInt32(); head.fontRevision = fontReader.ReadUInt32();
head.checkSumAdjustment = FontReader.ReadUInt32(); head.checkSumAdjustment = fontReader.ReadUInt32();
head.magicNumber = FontReader.ReadUInt32(); head.magicNumber = fontReader.ReadUInt32();
head.flags = FontReader.ReadUInt16(); head.flags = fontReader.ReadUInt16();
head.unitsPerEm = FontReader.ReadUInt16(); head.unitsPerEm = fontReader.ReadUInt16();
head.created = FontReader.ReadUInt64(); head.created = fontReader.ReadUInt64();
head.modified = FontReader.ReadUInt64(); head.modified = fontReader.ReadUInt64();
head.xMin = FontReader.ReadInt16(); head.xMin = fontReader.ReadInt16();
head.yMin = FontReader.ReadInt16(); head.yMin = fontReader.ReadInt16();
head.xMax = FontReader.ReadInt16(); head.xMax = fontReader.ReadInt16();
head.yMax = FontReader.ReadInt16(); head.yMax = fontReader.ReadInt16();
head.macStyle = FontReader.ReadUInt16(); head.macStyle = fontReader.ReadUInt16();
head.lowestRecPPEM = FontReader.ReadUInt16(); head.lowestRecPPEM = fontReader.ReadUInt16();
head.fontDirectionHint = FontReader.ReadInt16(); head.fontDirectionHint = fontReader.ReadInt16();
head.indexToLocFormat = FontReader.ReadInt16(); head.indexToLocFormat = fontReader.ReadInt16();
head.glyphDataFormat = FontReader.ReadInt16(); head.glyphDataFormat = fontReader.ReadInt16();
} }
} }
// 解析表 maxp (获取 maxp.numGlyphs) // 解析表 maxp (获取 maxp.numGlyphs)
for (Directory Temp : Directorys) { for (Directory Temp : directorys) {
if (Temp.tag.equals("maxp")) { if (Temp.tag.equals("maxp")) {
FontReader.Index = Temp.offset; fontReader.index = Temp.offset;
maxp.majorVersion = FontReader.ReadUInt16(); maxp.majorVersion = fontReader.ReadUInt16();
maxp.minorVersion = FontReader.ReadUInt16(); maxp.minorVersion = fontReader.ReadUInt16();
maxp.numGlyphs = FontReader.ReadUInt16(); maxp.numGlyphs = fontReader.ReadUInt16();
maxp.maxPoints = FontReader.ReadUInt16(); maxp.maxPoints = fontReader.ReadUInt16();
maxp.maxContours = FontReader.ReadUInt16(); maxp.maxContours = fontReader.ReadUInt16();
maxp.maxCompositePoints = FontReader.ReadUInt16(); maxp.maxCompositePoints = fontReader.ReadUInt16();
maxp.maxCompositeContours = FontReader.ReadUInt16(); maxp.maxCompositeContours = fontReader.ReadUInt16();
maxp.maxZones = FontReader.ReadUInt16(); maxp.maxZones = fontReader.ReadUInt16();
maxp.maxTwilightPoints = FontReader.ReadUInt16(); maxp.maxTwilightPoints = fontReader.ReadUInt16();
maxp.maxStorage = FontReader.ReadUInt16(); maxp.maxStorage = fontReader.ReadUInt16();
maxp.maxFunctionDefs = FontReader.ReadUInt16(); maxp.maxFunctionDefs = fontReader.ReadUInt16();
maxp.maxInstructionDefs = FontReader.ReadUInt16(); maxp.maxInstructionDefs = fontReader.ReadUInt16();
maxp.maxStackElements = FontReader.ReadUInt16(); maxp.maxStackElements = fontReader.ReadUInt16();
maxp.maxSizeOfInstructions = FontReader.ReadUInt16(); maxp.maxSizeOfInstructions = fontReader.ReadUInt16();
maxp.maxComponentElements = FontReader.ReadUInt16(); maxp.maxComponentElements = fontReader.ReadUInt16();
maxp.maxComponentDepth = FontReader.ReadUInt16(); maxp.maxComponentDepth = fontReader.ReadUInt16();
} }
} }
// 解析表 loca (轮廓数据偏移地址表) // 解析表 loca (轮廓数据偏移地址表)
for (Directory Temp : Directorys) { for (Directory Temp : directorys) {
if (Temp.tag.equals("loca")) { if (Temp.tag.equals("loca")) {
FontReader.Index = Temp.offset; fontReader.index = Temp.offset;
int offset = head.indexToLocFormat == 0 ? 2 : 4; int offset = head.indexToLocFormat == 0 ? 2 : 4;
for (long i = 0; i < Temp.length; i += offset) { for (long i = 0; i < Temp.length; i += offset) {
loca.add(offset == 2 ? FontReader.ReadUInt16() << 1 : FontReader.ReadUInt32()); loca.add(offset == 2 ? fontReader.ReadUInt16() << 1 : fontReader.ReadUInt32());
} }
} }
} }
// 解析表 cmap (Unicode编码轮廓索引对照表) // 解析表 cmap (Unicode编码轮廓索引对照表)
for (Directory Temp : Directorys) { for (Directory Temp : directorys) {
if (Temp.tag.equals("cmap")) { if (Temp.tag.equals("cmap")) {
FontReader.Index = Temp.offset; fontReader.index = Temp.offset;
Cmap.version = FontReader.ReadUInt16(); Cmap.version = fontReader.ReadUInt16();
Cmap.numTables = FontReader.ReadUInt16(); Cmap.numTables = fontReader.ReadUInt16();
for (int i = 0; i < Cmap.numTables; ++i) { for (int i = 0; i < Cmap.numTables; ++i) {
CmapRecord record = new CmapRecord(); CmapRecord record = new CmapRecord();
record.platformID = FontReader.ReadUInt16(); record.platformID = fontReader.ReadUInt16();
record.encodingID = FontReader.ReadUInt16(); record.encodingID = fontReader.ReadUInt16();
record.offset = FontReader.ReadUInt32(); record.offset = fontReader.ReadUInt32();
Cmap.records.add(record); Cmap.records.add(record);
} }
for (int i = 0; i < Cmap.numTables; ++i) { for (int i = 0; i < Cmap.numTables; ++i) {
int fmtOffset = Cmap.records.get(i).offset; int fmtOffset = Cmap.records.get(i).offset;
FontReader.Index = Temp.offset + fmtOffset; fontReader.index = Temp.offset + fmtOffset;
int EndIndex = FontReader.Index; int EndIndex = fontReader.index;
int format = FontReader.ReadUInt16(); int format = fontReader.ReadUInt16();
if (Cmap.tables.containsKey(fmtOffset)) continue; if (Cmap.tables.containsKey(fmtOffset)) continue;
if (format == 0) { if (format == 0) {
CmapFormat f = new CmapFormat(); CmapFormat f = new CmapFormat();
f.format = format; f.format = format;
f.length = FontReader.ReadUInt16(); f.length = fontReader.ReadUInt16();
f.language = FontReader.ReadUInt16(); f.language = fontReader.ReadUInt16();
f.glyphIdArray = FontReader.GetBytes(f.length - 6); f.glyphIdArray = fontReader.GetBytes(f.length - 6);
Cmap.tables.put(fmtOffset, f); Cmap.tables.put(fmtOffset, f);
} else if (format == 4) { } else if (format == 4) {
CmapFormat4 f = new CmapFormat4(); CmapFormat4 f = new CmapFormat4();
f.format = format; f.format = format;
f.length = FontReader.ReadUInt16(); f.length = fontReader.ReadUInt16();
f.language = FontReader.ReadUInt16(); f.language = fontReader.ReadUInt16();
f.segCountX2 = FontReader.ReadUInt16(); f.segCountX2 = fontReader.ReadUInt16();
int segCount = f.segCountX2 >> 1; int segCount = f.segCountX2 >> 1;
f.searchRange = FontReader.ReadUInt16(); f.searchRange = fontReader.ReadUInt16();
f.entrySelector = FontReader.ReadUInt16(); f.entrySelector = fontReader.ReadUInt16();
f.rangeShift = FontReader.ReadUInt16(); f.rangeShift = fontReader.ReadUInt16();
f.endCode = FontReader.GetUInt16Array(segCount); f.endCode = fontReader.GetUInt16Array(segCount);
f.reservedPad = FontReader.ReadUInt16(); f.reservedPad = fontReader.ReadUInt16();
f.startCode = FontReader.GetUInt16Array(segCount); f.startCode = fontReader.GetUInt16Array(segCount);
f.idDelta = FontReader.GetInt16Array(segCount); f.idDelta = fontReader.GetInt16Array(segCount);
f.idRangeOffset = FontReader.GetUInt16Array(segCount); f.idRangeOffset = fontReader.GetUInt16Array(segCount);
f.glyphIdArray = FontReader.GetUInt16Array((EndIndex + f.length - FontReader.Index) >> 1); f.glyphIdArray = fontReader.GetUInt16Array((EndIndex + f.length - fontReader.index) >> 1);
Cmap.tables.put(fmtOffset, f); Cmap.tables.put(fmtOffset, f);
} else if (format == 6) { } else if (format == 6) {
CmapFormat6 f = new CmapFormat6(); CmapFormat6 f = new CmapFormat6();
f.format = format; f.format = format;
f.length = FontReader.ReadUInt16(); f.length = fontReader.ReadUInt16();
f.language = FontReader.ReadUInt16(); f.language = fontReader.ReadUInt16();
f.firstCode = FontReader.ReadUInt16(); f.firstCode = fontReader.ReadUInt16();
f.entryCount = FontReader.ReadUInt16(); f.entryCount = fontReader.ReadUInt16();
f.glyphIdArray = FontReader.GetUInt16Array(f.entryCount); f.glyphIdArray = fontReader.GetUInt16Array(f.entryCount);
Cmap.tables.put(fmtOffset, f); Cmap.tables.put(fmtOffset, f);
} else if (format == 12) { } else if (format == 12) {
CmapFormat12 f = new CmapFormat12(); CmapFormat12 f = new CmapFormat12();
f.format = format; f.format = format;
f.reserved = FontReader.ReadUInt16(); f.reserved = fontReader.ReadUInt16();
f.length = FontReader.ReadUInt32(); f.length = fontReader.ReadUInt32();
f.language = FontReader.ReadUInt32(); f.language = fontReader.ReadUInt32();
f.numGroups = FontReader.ReadUInt32(); f.numGroups = fontReader.ReadUInt32();
f.groups = new ArrayList<>(f.numGroups); f.groups = new ArrayList<>(f.numGroups);
for (int n = 0; n < f.numGroups; ++n) { for (int n = 0; n < f.numGroups; ++n) {
f.groups.add(Triple.of(FontReader.ReadUInt32(), FontReader.ReadUInt32(), FontReader.ReadUInt32())); f.groups.add(Triple.of(fontReader.ReadUInt32(), fontReader.ReadUInt32(), fontReader.ReadUInt32()));
} }
Cmap.tables.put(fmtOffset, f); Cmap.tables.put(fmtOffset, f);
} }
@ -406,30 +406,30 @@ public class QueryTTF {
} }
} }
// 解析表 glyf (字体轮廓数据表) // 解析表 glyf (字体轮廓数据表)
for (Directory Temp : Directorys) { for (Directory Temp : directorys) {
if (Temp.tag.equals("glyf")) { if (Temp.tag.equals("glyf")) {
FontReader.Index = Temp.offset; fontReader.index = Temp.offset;
for (int i = 0; i < maxp.numGlyphs; ++i) { for (int i = 0; i < maxp.numGlyphs; ++i) {
FontReader.Index = Temp.offset + loca.get(i); fontReader.index = Temp.offset + loca.get(i);
short numberOfContours = FontReader.ReadInt16(); short numberOfContours = fontReader.ReadInt16();
if (numberOfContours > 0) { if (numberOfContours > 0) {
GlyfLayout g = new GlyfLayout(); GlyfLayout g = new GlyfLayout();
g.numberOfContours = numberOfContours; g.numberOfContours = numberOfContours;
g.xMin = FontReader.ReadInt16(); g.xMin = fontReader.ReadInt16();
g.yMin = FontReader.ReadInt16(); g.yMin = fontReader.ReadInt16();
g.xMax = FontReader.ReadInt16(); g.xMax = fontReader.ReadInt16();
g.yMax = FontReader.ReadInt16(); g.yMax = fontReader.ReadInt16();
g.endPtsOfContours = FontReader.GetUInt16Array(numberOfContours); g.endPtsOfContours = fontReader.GetUInt16Array(numberOfContours);
g.instructionLength = FontReader.ReadUInt16(); g.instructionLength = fontReader.ReadUInt16();
g.instructions = FontReader.GetBytes(g.instructionLength); g.instructions = fontReader.GetBytes(g.instructionLength);
int flagLength = g.endPtsOfContours[g.endPtsOfContours.length - 1] + 1; int flagLength = g.endPtsOfContours[g.endPtsOfContours.length - 1] + 1;
// 获取轮廓点描述标志 // 获取轮廓点描述标志
g.flags = new byte[flagLength]; g.flags = new byte[flagLength];
for (int n = 0; n < flagLength; ++n) { for (int n = 0; n < flagLength; ++n) {
g.flags[n] = FontReader.GetByte(); g.flags[n] = fontReader.GetByte();
if ((g.flags[n] & 0x08) != 0x00) { if ((g.flags[n] & 0x08) != 0x00) {
for (int m = FontReader.ReadUInt8(); m > 0; --m) { for (int m = fontReader.ReadUInt8(); m > 0; --m) {
g.flags[++n] = g.flags[n - 1]; g.flags[++n] = g.flags[n - 1];
} }
} }
@ -439,9 +439,9 @@ public class QueryTTF {
for (int n = 0; n < flagLength; ++n) { for (int n = 0; n < flagLength; ++n) {
short same = (short) ((g.flags[n] & 0x10) != 0 ? 1 : -1); short same = (short) ((g.flags[n] & 0x10) != 0 ? 1 : -1);
if ((g.flags[n] & 0x02) != 0) { if ((g.flags[n] & 0x02) != 0) {
g.xCoordinates[n] = (short) (same * FontReader.ReadUInt8()); g.xCoordinates[n] = (short) (same * fontReader.ReadUInt8());
} else { } else {
g.xCoordinates[n] = same == 1 ? (short) 0 : FontReader.ReadInt16(); g.xCoordinates[n] = same == 1 ? (short) 0 : fontReader.ReadInt16();
} }
} }
// 获取轮廓点描述y轴相对值 // 获取轮廓点描述y轴相对值
@ -449,9 +449,9 @@ public class QueryTTF {
for (int n = 0; n < flagLength; ++n) { for (int n = 0; n < flagLength; ++n) {
short same = (short) ((g.flags[n] & 0x20) != 0 ? 1 : -1); short same = (short) ((g.flags[n] & 0x20) != 0 ? 1 : -1);
if ((g.flags[n] & 0x04) != 0) { if ((g.flags[n] & 0x04) != 0) {
g.yCoordinates[n] = (short) (same * FontReader.ReadUInt8()); g.yCoordinates[n] = (short) (same * fontReader.ReadUInt8());
} else { } else {
g.yCoordinates[n] = same == 1 ? (short) 0 : FontReader.ReadInt16(); g.yCoordinates[n] = same == 1 ? (short) 0 : fontReader.ReadInt16();
} }
} }
// 相对坐标转绝对坐标 // 相对坐标转绝对坐标
@ -478,11 +478,11 @@ public class QueryTTF {
for (short b : glyf.get(gid).xCoordinates) sb.append(b); for (short b : glyf.get(gid).xCoordinates) sb.append(b);
for (short b : glyf.get(gid).yCoordinates) sb.append(b); for (short b : glyf.get(gid).yCoordinates) sb.append(b);
String val = sb.toString(); String val = sb.toString();
if (LimitMix == 0) LimitMix = key; if (limitMix == 0) limitMix = key;
LimitMax = key; limitMax = key;
CodeToGlyph.put(key, val); codeToGlyph.put(key, val);
if (GlyphToCode.containsKey(val)) continue; if (glyphToCode.containsKey(val)) continue;
GlyphToCode.put(val, key); glyphToCode.put(val, key);
} }
} }
@ -493,15 +493,15 @@ public class QueryTTF {
* @return 返回查询结果字符串 * @return 返回查询结果字符串
*/ */
public String getNameById(int nameId) { public String getNameById(int nameId) {
for (Directory Temp : Directorys) { for (Directory Temp : directorys) {
if (!Temp.tag.equals("name")) continue; if (!Temp.tag.equals("name")) continue;
FontReader.Index = Temp.offset; fontReader.index = Temp.offset;
break; break;
} }
for (NameRecord record : Name.records) { for (NameRecord record : name.records) {
if (record.nameID != nameId) continue; if (record.nameID != nameId) continue;
FontReader.Index += Name.stringOffset + record.offset; fontReader.index += name.stringOffset + record.offset;
return FontReader.ReadStrings(record.length, record.platformID == 1 ? StandardCharsets.UTF_8 : StandardCharsets.UTF_16BE); return fontReader.ReadStrings(record.length, record.platformID == 1 ? StandardCharsets.UTF_8 : StandardCharsets.UTF_16BE);
} }
return "error"; return "error";
} }
@ -528,6 +528,7 @@ public class QueryTTF {
int glyfID = 0; int glyfID = 0;
CmapFormat table = Cmap.tables.get(fmtKey); CmapFormat table = Cmap.tables.get(fmtKey);
assert table != null;
int fmt = table.format; int fmt = table.format;
if (fmt == 0) { if (fmt == 0) {
if (code < table.glyphIdArray.length) glyfID = table.glyphIdArray[code] & 0xFF; if (code < table.glyphIdArray.length) glyfID = table.glyphIdArray[code] & 0xFF;
@ -576,7 +577,7 @@ public class QueryTTF {
* @return 返回bool查询结果 * @return 返回bool查询结果
*/ */
public boolean inLimit(char code) { public boolean inLimit(char code) {
return (LimitMix <= code) && (code < LimitMax); return (limitMix <= code) && (code < limitMax);
} }
/** /**
@ -586,7 +587,7 @@ public class QueryTTF {
* @return 返回轮廓数组的String值 * @return 返回轮廓数组的String值
*/ */
public String getGlyfByCode(int key) { public String getGlyfByCode(int key) {
return CodeToGlyph.getOrDefault(key, ""); return codeToGlyph.getOrDefault(key, "");
} }
/** /**
@ -596,6 +597,7 @@ public class QueryTTF {
* @return 返回Unicode十进制值 * @return 返回Unicode十进制值
*/ */
public int getCodeByGlyf(String val) { public int getCodeByGlyf(String val) {
return GlyphToCode.getOrDefault(val, 0); //noinspection ConstantConditions
return glyphToCode.getOrDefault(val, 0);
} }
} }

@ -21,6 +21,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import splitties.init.appCtx import splitties.init.appCtx
import kotlin.math.min
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
@ -137,15 +138,15 @@ object ReadBook {
callBack?.upContent() callBack?.upContent()
} }
loadContent(durChapterIndex.plus(1), upContent, false) loadContent(durChapterIndex.plus(1), upContent, false)
if (AppConfig.preDownload) {
GlobalScope.launch(Dispatchers.IO) { GlobalScope.launch(Dispatchers.IO) {
for (i in 2..9) { val maxChapterIndex =
min(chapterSize - 1, durChapterIndex + AppConfig.preDownloadNum)
for (i in 2..maxChapterIndex) {
delay(1000) delay(1000)
download(durChapterIndex + i) download(durChapterIndex + i)
} }
} }
} }
}
saveRead() saveRead()
callBack?.upView() callBack?.upView()
curPageChanged() curPageChanged()
@ -169,15 +170,15 @@ object ReadBook {
callBack?.upContent() callBack?.upContent()
} }
loadContent(durChapterIndex.minus(1), upContent, false) loadContent(durChapterIndex.minus(1), upContent, false)
if (AppConfig.preDownload) {
GlobalScope.launch(Dispatchers.IO) { GlobalScope.launch(Dispatchers.IO) {
for (i in 2..9) { val maxChapterIndex =
min(chapterSize - 1, durChapterIndex + AppConfig.preDownloadNum)
for (i in 2..maxChapterIndex) {
delay(1000) delay(1000)
download(durChapterIndex - i) download(durChapterIndex - i)
} }
} }
} }
}
saveRead() saveRead()
callBack?.upView() callBack?.upView()
curPageChanged() curPageChanged()

@ -53,6 +53,7 @@ class OtherConfigFragment : BasePreferenceFragment(),
putPrefBoolean(PreferKey.processText, isProcessTextEnabled()) putPrefBoolean(PreferKey.processText, isProcessTextEnabled())
addPreferencesFromResource(R.xml.pref_config_other) addPreferencesFromResource(R.xml.pref_config_other)
upPreferenceSummary(PreferKey.userAgent, AppConfig.userAgent) upPreferenceSummary(PreferKey.userAgent, AppConfig.userAgent)
upPreferenceSummary(PreferKey.preDownloadNum, AppConfig.preDownloadNum.toString())
upPreferenceSummary(PreferKey.threadCount, AppConfig.threadCount.toString()) upPreferenceSummary(PreferKey.threadCount, AppConfig.threadCount.toString())
upPreferenceSummary(PreferKey.webPort, webPort.toString()) upPreferenceSummary(PreferKey.webPort, webPort.toString())
upPreferenceSummary(PreferKey.defaultCover, getPrefString(PreferKey.defaultCover)) upPreferenceSummary(PreferKey.defaultCover, getPrefString(PreferKey.defaultCover))
@ -72,6 +73,14 @@ class OtherConfigFragment : BasePreferenceFragment(),
override fun onPreferenceTreeClick(preference: Preference?): Boolean { override fun onPreferenceTreeClick(preference: Preference?): Boolean {
when (preference?.key) { when (preference?.key) {
PreferKey.userAgent -> showUserAgentDialog() PreferKey.userAgent -> showUserAgentDialog()
PreferKey.preDownloadNum -> NumberPickerDialog(requireContext())
.setTitle(getString(R.string.pre_download))
.setMaxValue(9999)
.setMinValue(1)
.setValue(AppConfig.preDownloadNum)
.show {
AppConfig.preDownloadNum = it
}
PreferKey.threadCount -> NumberPickerDialog(requireContext()) PreferKey.threadCount -> NumberPickerDialog(requireContext())
.setTitle(getString(R.string.threads_num_title)) .setTitle(getString(R.string.threads_num_title))
.setMaxValue(999) .setMaxValue(999)
@ -106,6 +115,9 @@ class OtherConfigFragment : BasePreferenceFragment(),
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
when (key) { when (key) {
PreferKey.preDownloadNum -> {
upPreferenceSummary(key, AppConfig.preDownloadNum.toString())
}
PreferKey.threadCount -> { PreferKey.threadCount -> {
upPreferenceSummary(key, AppConfig.threadCount.toString()) upPreferenceSummary(key, AppConfig.threadCount.toString())
postEvent(PreferKey.threadCount, "") postEvent(PreferKey.threadCount, "")
@ -141,6 +153,8 @@ class OtherConfigFragment : BasePreferenceFragment(),
private fun upPreferenceSummary(preferenceKey: String, value: String?) { private fun upPreferenceSummary(preferenceKey: String, value: String?) {
val preference = findPreference<Preference>(preferenceKey) ?: return val preference = findPreference<Preference>(preferenceKey) ?: return
when (preferenceKey) { when (preferenceKey) {
PreferKey.preDownloadNum -> preference.summary =
getString(R.string.pre_download_s, value)
PreferKey.threadCount -> preference.summary = getString(R.string.threads_num, value) PreferKey.threadCount -> preference.summary = getString(R.string.threads_num, value)
PreferKey.webPort -> preference.summary = getString(R.string.web_port_summary, value) PreferKey.webPort -> preference.summary = getString(R.string.web_port_summary, value)
else -> if (preference is ListPreference) { else -> if (preference is ListPreference) {

@ -84,9 +84,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
appDb.bookDao.update(book) appDb.bookDao.update(book)
appDb.bookChapterDao.delByBook(book.bookUrl) appDb.bookChapterDao.delByBook(book.bookUrl)
appDb.bookChapterDao.insert(*toc.toTypedArray()) appDb.bookChapterDao.insert(*toc.toTypedArray())
if (AppConfig.preDownload) {
cacheBook(webBook, book) cacheBook(webBook, book)
}
}.onError { }.onError {
it.printStackTrace() it.printStackTrace()
}.onFinally { }.onFinally {
@ -114,7 +112,8 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
private fun cacheBook(webBook: WebBook, book: Book) { private fun cacheBook(webBook: WebBook, book: Book) {
execute { execute {
if (book.totalChapterNum > book.durChapterIndex) { if (book.totalChapterNum > book.durChapterIndex) {
val downloadToIndex = min(book.totalChapterNum, book.durChapterIndex.plus(10)) val downloadToIndex =
min(book.totalChapterNum, book.durChapterIndex.plus(AppConfig.preDownloadNum))
for (i in book.durChapterIndex until downloadToIndex) { for (i in book.durChapterIndex until downloadToIndex) {
appDb.bookChapterDao.getChapter(book.bookUrl, i)?.let { chapter -> appDb.bookChapterDao.getChapter(book.bookUrl, i)?.let { chapter ->
if (!BookHelp.hasContent(book, chapter)) { if (!BookHelp.hasContent(book, chapter)) {

@ -800,7 +800,7 @@
<string name="export_bookshelf">导出书单</string> <string name="export_bookshelf">导出书单</string>
<string name="import_bookshelf">导入书单</string> <string name="import_bookshelf">导入书单</string>
<string name="pre_download">预下载</string> <string name="pre_download">预下载</string>
<string name="pre_download_s">预先下载10章正文</string> <string name="pre_download_s">预先下载%s章正文</string>
<string name="sort_enable">启用排序</string> <string name="sort_enable">启用排序</string>
<string name="background_image">背景图片</string> <string name="background_image">背景图片</string>
<string name="export_folder">导出文件夹</string> <string name="export_folder">导出文件夹</string>

@ -804,7 +804,7 @@
<string name="export_bookshelf">匯出書單</string> <string name="export_bookshelf">匯出書單</string>
<string name="import_bookshelf">匯入書單</string> <string name="import_bookshelf">匯入書單</string>
<string name="pre_download">預下載</string> <string name="pre_download">預下載</string>
<string name="pre_download_s">預先下載10章正文</string> <string name="pre_download_s">預先下載%s章正文</string>
<string name="sort_enable">啟用排序</string> <string name="sort_enable">啟用排序</string>
<string name="background_image">背景圖片</string> <string name="background_image">背景圖片</string>
<string name="export_folder">匯出資料夾</string> <string name="export_folder">匯出資料夾</string>

@ -804,7 +804,7 @@
<string name="export_bookshelf">导出书单</string> <string name="export_bookshelf">导出书单</string>
<string name="import_bookshelf">导入书单</string> <string name="import_bookshelf">导入书单</string>
<string name="pre_download">预下载</string> <string name="pre_download">预下载</string>
<string name="pre_download_s">预先下载10章正文</string> <string name="pre_download_s">预先下载%s章正文</string>
<string name="sort_enable">启用排序</string> <string name="sort_enable">启用排序</string>
<string name="background_image">背景图片</string> <string name="background_image">背景图片</string>
<string name="export_folder">导出文件夹</string> <string name="export_folder">导出文件夹</string>

@ -805,7 +805,7 @@
<string name="export_bookshelf">导出书单</string> <string name="export_bookshelf">导出书单</string>
<string name="import_bookshelf">导入书单</string> <string name="import_bookshelf">导入书单</string>
<string name="pre_download">预下载</string> <string name="pre_download">预下载</string>
<string name="pre_download_s">预先下载10章正文</string> <string name="pre_download_s">预先下载%s章正文</string>
<string name="sort_enable">启用排序</string> <string name="sort_enable">启用排序</string>
<string name="background_image">背景图片</string> <string name="background_image">背景图片</string>
<string name="export_folder">导出文件夹</string> <string name="export_folder">导出文件夹</string>

@ -61,9 +61,8 @@
android:title="@string/high_brush_title" android:title="@string/high_brush_title"
android:summary="@string/high_brush_summary" /> android:summary="@string/high_brush_summary" />
<io.legado.app.ui.widget.prefs.SwitchPreference <io.legado.app.ui.widget.prefs.Preference
android:defaultValue="true" android:key="preDownloadNum"
android:key="preDownload"
android:title="@string/pre_download" android:title="@string/pre_download"
android:summary="@string/pre_download_s" /> android:summary="@string/pre_download_s" />

Loading…
Cancel
Save