diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.kt b/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.kt index 02fcb2e3e..710fdbe16 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.kt @@ -9,6 +9,7 @@ import kotlin.experimental.and * @see 获取详情 * @see 基于Javascript的TTF解析器 */ +@ExperimentalUnsignedTypes class QueryTTF(var Font: ByteArray) : JsExtensions { private class Header { var majorVersion: UShort = 0u @@ -95,7 +96,7 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { var offset: UInt = 0u } - private class CmapFormat0 { + private class CmapFormat0 { var format: UShort = 0u var length: UShort = 0u var language: UShort = 0u @@ -152,12 +153,12 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { private class ByteArrayReader(var Buffer: ByteArray, var Index: Int) { fun ReadUIntX(len: Long): ULong { - var result: ULong = 0u; + var result: ULong = 0u for (i in 0 until len) { - result.shl(8); + result.shl(8) result = result or Buffer[Index++].toULong() } - return result; + return result } fun ReadUInt64(): ULong { @@ -203,7 +204,7 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { for (i in 0 until len) { result[i] = Buffer[Index++] } - return result; + return result } fun GetUInt16Array(len: Int): ArrayList { @@ -212,7 +213,7 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { for (i in 0 until len) { result[i] = ReadUInt16() } - return result; + return result } fun GetInt16Array(len: Int): ArrayList { @@ -221,7 +222,7 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { for (i in 0 until len) { result[i] = ReadInt16() } - return result; + return result } } @@ -240,15 +241,15 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { FontReader = ByteArrayReader(Font, 0) // 获取文件头 fileHeader.majorVersion = FontReader.ReadUInt16() - fileHeader.minorVersion = FontReader.ReadUInt16(); - fileHeader.numOfTables = FontReader.ReadUInt16(); - fileHeader.searchRange = FontReader.ReadUInt16(); - fileHeader.entrySelector = FontReader.ReadUInt16(); - fileHeader.rangeShift = FontReader.ReadUInt16(); + fileHeader.minorVersion = FontReader.ReadUInt16() + fileHeader.numOfTables = FontReader.ReadUInt16() + fileHeader.searchRange = FontReader.ReadUInt16() + fileHeader.entrySelector = FontReader.ReadUInt16() + fileHeader.rangeShift = FontReader.ReadUInt16() // 获取目录 for (i in 0 until fileHeader.numOfTables.toInt()) { val tag = FontReader.ReadStrings(4, Charsets.US_ASCII) - val t = Directory(); + val t = Directory() t.tag = tag t.checkSum = FontReader.ReadUInt32() t.offset = FontReader.ReadUInt32() @@ -258,10 +259,10 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { // 解析表 name (字体信息,包含版权、名称、作者等...) for (Temp in directorys) { if (Temp.tag == "name") { - FontReader.Index = Temp.offset.toInt(); - name.format = FontReader.ReadUInt16(); - name.count = FontReader.ReadUInt16(); - name.stringOffset = FontReader.ReadUInt16(); + FontReader.Index = Temp.offset.toInt() + name.format = FontReader.ReadUInt16() + name.count = FontReader.ReadUInt16() + name.stringOffset = FontReader.ReadUInt16() for (i in 0 until name.count.toInt()) { val record = NameRecord() @@ -271,54 +272,54 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { record.nameID = FontReader.ReadUInt16() record.length = FontReader.ReadUInt16() record.offset = FontReader.ReadUInt16() - name.records.add(record); + name.records.add(record) } } } // 解析表 head (获取 head.indexToLocFormat) for (Temp in directorys) { if (Temp.tag == "head") { - FontReader.Index = Temp.offset.toInt(); - head.majorVersion = FontReader.ReadUInt16(); - head.minorVersion = FontReader.ReadUInt16(); - head.fontRevision = FontReader.ReadUInt32(); - head.checkSumAdjustment = FontReader.ReadUInt32(); - head.magicNumber = FontReader.ReadUInt32(); - head.flags = FontReader.ReadUInt16(); - head.unitsPerEm = FontReader.ReadUInt16(); - head.created = FontReader.ReadUInt64(); - head.modified = FontReader.ReadUInt64(); - head.xMin = FontReader.ReadInt16(); - head.yMin = FontReader.ReadInt16(); - head.xMax = FontReader.ReadInt16(); - head.yMax = FontReader.ReadInt16(); - head.macStyle = FontReader.ReadUInt16(); - head.lowestRecPPEM = FontReader.ReadUInt16(); - head.fontDirectionHint = FontReader.ReadInt16(); - head.indexToLocFormat = FontReader.ReadInt16(); - head.glyphDataFormat = FontReader.ReadInt16(); + FontReader.Index = Temp.offset.toInt() + head.majorVersion = FontReader.ReadUInt16() + head.minorVersion = FontReader.ReadUInt16() + head.fontRevision = FontReader.ReadUInt32() + head.checkSumAdjustment = FontReader.ReadUInt32() + head.magicNumber = FontReader.ReadUInt32() + head.flags = FontReader.ReadUInt16() + head.unitsPerEm = FontReader.ReadUInt16() + head.created = FontReader.ReadUInt64() + head.modified = FontReader.ReadUInt64() + head.xMin = FontReader.ReadInt16() + head.yMin = FontReader.ReadInt16() + head.xMax = FontReader.ReadInt16() + head.yMax = FontReader.ReadInt16() + head.macStyle = FontReader.ReadUInt16() + head.lowestRecPPEM = FontReader.ReadUInt16() + head.fontDirectionHint = FontReader.ReadInt16() + head.indexToLocFormat = FontReader.ReadInt16() + head.glyphDataFormat = FontReader.ReadInt16() } } // 解析表 maxp (获取 maxp.numGlyphs) for (Temp in directorys) { if (Temp.tag == "maxp") { - FontReader.Index = Temp.offset.toInt(); - maxp.majorVersion = FontReader.ReadUInt16(); - maxp.minorVersion = FontReader.ReadUInt16(); - maxp.numGlyphs = FontReader.ReadUInt16(); - maxp.maxPoints = FontReader.ReadUInt16(); - maxp.maxContours = FontReader.ReadUInt16(); - maxp.maxCompositePoints = FontReader.ReadUInt16(); - maxp.maxCompositeContours = FontReader.ReadUInt16(); - maxp.maxZones = FontReader.ReadUInt16(); - maxp.maxTwilightPoints = FontReader.ReadUInt16(); - maxp.maxStorage = FontReader.ReadUInt16(); - maxp.maxFunctionDefs = FontReader.ReadUInt16(); - maxp.maxInstructionDefs = FontReader.ReadUInt16(); - maxp.maxStackElements = FontReader.ReadUInt16(); - maxp.maxSizeOfInstructions = FontReader.ReadUInt16(); - maxp.maxComponentElements = FontReader.ReadUInt16(); - maxp.maxComponentDepth = FontReader.ReadUInt16(); + FontReader.Index = Temp.offset.toInt() + maxp.majorVersion = FontReader.ReadUInt16() + maxp.minorVersion = FontReader.ReadUInt16() + maxp.numGlyphs = FontReader.ReadUInt16() + maxp.maxPoints = FontReader.ReadUInt16() + maxp.maxContours = FontReader.ReadUInt16() + maxp.maxCompositePoints = FontReader.ReadUInt16() + maxp.maxCompositeContours = FontReader.ReadUInt16() + maxp.maxZones = FontReader.ReadUInt16() + maxp.maxTwilightPoints = FontReader.ReadUInt16() + maxp.maxStorage = FontReader.ReadUInt16() + maxp.maxFunctionDefs = FontReader.ReadUInt16() + maxp.maxInstructionDefs = FontReader.ReadUInt16() + maxp.maxStackElements = FontReader.ReadUInt16() + maxp.maxSizeOfInstructions = FontReader.ReadUInt16() + maxp.maxComponentElements = FontReader.ReadUInt16() + maxp.maxComponentDepth = FontReader.ReadUInt16() } } // 解析表 loca (轮廓数据偏移地址表) @@ -348,13 +349,13 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { cmap.records.add(record) } for (i in 0 until cmap.numTables.toInt()) { - val fmtOffset = cmap.records[i].offset; - FontReader.Index = (Temp.offset + fmtOffset).toInt(); - val EndIndex = FontReader.Index; + val fmtOffset = cmap.records[i].offset + FontReader.Index = (Temp.offset + fmtOffset).toInt() + val EndIndex = FontReader.Index - val format = FontReader.ReadUInt16(); + val format = FontReader.ReadUInt16() - if (cmap.tables.contains(fmtOffset.toInt())) continue; + if (cmap.tables.contains(fmtOffset.toInt())) continue when { format.equals(0) -> { val fmt = CmapFormat0() @@ -395,10 +396,10 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { format.equals(12) -> { val fmt = CmapFormat12() fmt.format = format - fmt.reserved = FontReader.ReadUInt16(); - fmt.length = FontReader.ReadUInt32(); - fmt.language = FontReader.ReadUInt32(); - fmt.numGroups = FontReader.ReadUInt32(); + fmt.reserved = FontReader.ReadUInt16() + fmt.length = FontReader.ReadUInt32() + fmt.language = FontReader.ReadUInt32() + fmt.numGroups = FontReader.ReadUInt32() for (n in 0 until fmt.numGroups.toLong()) { fmt.groups.add(Triple(FontReader.ReadUInt32(), FontReader.ReadUInt32(), FontReader.ReadUInt32())) } @@ -430,7 +431,7 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { g.flags = ArrayList(flagLength) var n = 0 while (n < flagLength) { - g.flags[n] = FontReader.GetByte(); + g.flags[n] = FontReader.GetByte() if ((g.flags[n].and(0x08)).toInt() != 0x00) { for (m in FontReader.GetByte() downTo 1) { g.flags[++n] = g.flags[n - 1] @@ -462,12 +463,12 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { // 相对坐标转绝对坐标 (因不绘制字体,这里用不上) for(m in 1 until flagLength) { - g.xCoordinates[m] = (g.xCoordinates[m] + g.xCoordinates[m - 1]).toShort(); - g.yCoordinates[m] = (g.yCoordinates[m] + g.yCoordinates[m - 1]).toShort(); + g.xCoordinates[m] = (g.xCoordinates[m] + g.xCoordinates[m - 1]).toShort() + g.yCoordinates[m] = (g.yCoordinates[m] + g.yCoordinates[m - 1]).toShort() } */ - glyf.add(g); + glyf.add(g) } else { // 复合字体暂未使用 } @@ -478,12 +479,12 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { // 建立Unicode&Glyf映射表 for (i in 0..130000) { val gid = GetGlyfIndex(i).toInt() - if (gid == 0) continue; + if (gid == 0) continue if (unicodeMap.containsKey(gid)) continue val thisGlyf = ArrayList() thisGlyf.addAll(glyf[gid].xCoordinates) thisGlyf.addAll(glyf[gid].yCoordinates) - unicodeMap[i] = thisGlyf; + unicodeMap[i] = thisGlyf } } @@ -494,76 +495,78 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { */ fun GetNameById(nameId: Int = 1): String { for (Temp in directorys) { - if (Temp.tag != "name") continue; - FontReader.Index = Temp.offset.toInt(); - break; + if (Temp.tag != "name") continue + FontReader.Index = Temp.offset.toInt() + break } for (record in name.records) { - if (record.nameID.toInt() != nameId) continue; - FontReader.Index = FontReader.Index + (name.stringOffset + record.offset).toInt(); - return FontReader.ReadStrings(record.length.toInt(), if (record.platformID.toInt() == 1) Charsets.UTF_8 else Charsets.UTF_16BE); + if (record.nameID.toInt() != nameId) continue + FontReader.Index = FontReader.Index + (name.stringOffset + record.offset).toInt() + return FontReader.ReadStrings(record.length.toInt(), if (record.platformID.toInt() == 1) Charsets.UTF_8 else Charsets.UTF_16BE) } - return "error"; + return "error" } var pps = arrayListOf>(Pair(3u, 10u), Pair(0u, 4u), Pair(3u, 1u), Pair(1u, 0u), Pair(0u, 3u), Pair(0u, 1u)) + /** * 使用Unicode值查找轮廓索引 */ private fun GetGlyfIndex(code: Int): Long { - var fmtKey: UInt = 0u; - for (record in cmap.records) { - for (item in pps) { + if (code == 0) return 0 + var fmtKey: UInt = 0u + for (item in pps) { + for (record in cmap.records) { if ((item.first == record.platformID) && (item.second == record.encodingID)) { - fmtKey = record.offset; - break; + fmtKey = record.offset + break } } - if (fmtKey > 0u) break; + if (fmtKey > 0u) break } - if (fmtKey == 0u) return 0; + if (fmtKey == 0u) return 0 - var glyfID: Long = 0; + var glyfID: Long = 0 if (cmap.tables[fmtKey] is CmapFormat0) { val tab = cmap.tables[fmtKey] as CmapFormat0 - if (code >= tab.glyphIdArray.size) glyfID = 0; - else glyfID = tab.glyphIdArray[code].toLong(); + if (code >= tab.glyphIdArray.size) glyfID = 0 + else glyfID = tab.glyphIdArray[code].toLong() } else if (cmap.tables[fmtKey] is CmapFormat4) { val tab = cmap.tables[fmtKey] as CmapFormat4 - if (code > tab.endCode.last().toInt()) return 0; + if (code > tab.endCode.last().toInt()) return 0 // 二分法查找数值索引 var start = 0 var middle: Int - var end = tab.endCode.size - 1; - while (start + 1 != end) { - middle = (start + end) / 2; - if (tab.endCode[middle] <= code.toUInt()) start = middle; - else end = middle; + var end = tab.endCode.size - 1 + while (start + 1 < end) { + middle = (start + end) / 2 + if (tab.endCode[middle] <= code.toUInt()) start = middle + else end = middle } - if (tab.endCode[start] < code.toUInt()) ++start; - if (code.toUInt() < tab.startCode[start]) return 0; + if (tab.endCode[start] < code.toUInt()) ++start + if (code.toUInt() < tab.startCode[start]) return 0 glyfID = if (tab.idRangeOffset[start].toInt() != 0) { - tab.glyphIdArray[code - tab.startCode[start].toInt() + (tab.idRangeOffset[start].toInt() / 2) - (tab.idRangeOffset.size - start)].toLong(); - } else (code + tab.idDelta[start]).toLong(); + tab.glyphIdArray[code - tab.startCode[start].toInt() + (tab.idRangeOffset[start].toInt() / 2) - (tab.idRangeOffset.size - start)].toLong() + } else (code + tab.idDelta[start]).toLong() glyfID = glyfID.and(0xFFFF) } else if (cmap.tables[fmtKey] is CmapFormat6) { val tab = cmap.tables[fmtKey] as CmapFormat6 - val index = code - tab.firstCode.toInt(); + val index = code - tab.firstCode.toInt() glyfID = if (index < 0 || index >= tab.glyphIdArray.size) 0 else tab.glyphIdArray[index].toLong() } else if (cmap.tables[fmtKey] is CmapFormat12) { - val tab = (cmap.tables[fmtKey] as CmapFormat12); - if (code > tab.groups.last().second.toInt()) return 0; + val tab = (cmap.tables[fmtKey] as CmapFormat12) + if (code > tab.groups.last().second.toInt()) return 0 // 二分法查找数值索引 var start = 0 var middle: Int - var end = tab.groups.size - 1; - while (start + 1 != end) { - middle = (start + end) / 2; - if (tab.groups[middle].first.toInt() <= code) start = middle; - else end = middle; + var end = tab.groups.size - 1 + while (start + 1 < end) { + middle = (start + end) / 2 + if (tab.groups[middle].first.toInt() <= code) start = middle + else end = middle } if (tab.groups[start].first.toInt() <= code && code <= tab.groups[start].second.toInt()) { - glyfID = (tab.groups[start].third.toInt() + code - tab.groups[start].first.toInt()).toLong(); + glyfID = (tab.groups[start].third.toInt() + code - tab.groups[start].first.toInt()).toLong() } } return glyfID @@ -572,31 +575,28 @@ class QueryTTF(var Font: ByteArray) : JsExtensions { /** * 使用轮廓数据获取Unicode值 */ - public fun GetCodeByGlyf(inputGlyf:List): Int { - var unicodeVal = 0; - if(inputGlyf.isEmpty()) return 0; - for(g in unicodeMap) - { - if (inputGlyf.size != g.value.size) continue; - var isFound = true; - for(i in inputGlyf.indices) - { + public fun GetCodeByGlyf(inputGlyf: List): Int { + var unicodeVal = 0 + if (inputGlyf.isEmpty()) return 0 + for (g in unicodeMap) { + if (inputGlyf.size != g.value.size) continue + var isFound = true + for (i in inputGlyf.indices) { if (inputGlyf[i] != g.value[i]) { - isFound = false; - break; + isFound = false + break } } - if (isFound) unicodeVal = g.key; + if (isFound) unicodeVal = g.key } - return unicodeVal; + return unicodeVal } /** * 使用Unicode值获取轮廓数据 */ - public fun GetGlyfByCode(code:Int): ArrayList - { - if(code <= 0) return ArrayList() + public fun GetGlyfByCode(code: Int): ArrayList { + if (code <= 0) return ArrayList() return unicodeMap.getOrDefault(code, ArrayList()) } } \ No newline at end of file