diff --git a/Sources/RDReaderView/EPUBTextRendering/Typesetter/RDEPUBAttachmentNormalizer.swift b/Sources/RDReaderView/EPUBTextRendering/Typesetter/RDEPUBAttachmentNormalizer.swift index 8486512..ffae4bf 100644 --- a/Sources/RDReaderView/EPUBTextRendering/Typesetter/RDEPUBAttachmentNormalizer.swift +++ b/Sources/RDReaderView/EPUBTextRendering/Typesetter/RDEPUBAttachmentNormalizer.swift @@ -136,8 +136,11 @@ struct RDEPUBAttachmentNormalizer { private static func isFootnoteAttachment(_ attachment: DTTextAttachment) -> Bool { let lowercasedClasses = ((attachment.attributes["class"] as? String) ?? "").lowercased() + if lowercasedClasses.contains("qqreader-footnote") { + return true + } let altText = attachment.attributes["alt"] as? String - return lowercasedClasses.contains("qqreader-footnote") || hasFootnoteAltText(altText) + return hasFootnoteAltText(altText) && isFootnoteSizedImage(attachment.originalSize) } private static func isCoverAttachment(_ attachment: DTTextAttachment) -> Bool { @@ -224,10 +227,31 @@ struct RDEPUBAttachmentNormalizer { } let label = fileAttachment.accessibilityLabel let lowercasedLabel = (label ?? "").lowercased() - return lowercasedLabel.contains("qqreader-footnote") || hasFootnoteAltText(label) + if lowercasedLabel.contains("qqreader-footnote") { + return true + } + let imageSize = fileAttachment.image?.size ?? fileAttachment.bounds.size + return hasFootnoteAltText(label) && isFootnoteSizedImage(imageSize) } + // Footnote images without the qqreader-footnote class are recognized by their + // alt text carrying the note body. Short alts ("logo", "图1") are ordinary + // accessibility descriptions, and note markers are small inline icons, so both + // conditions must hold before an image is shrunk to footnote size. + private static let minimumFootnoteAltTextLength = 8 + + private static let maximumFootnoteImageDimension: CGFloat = 50 + private static func hasFootnoteAltText(_ text: String?) -> Bool { - text?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false + guard let trimmed = text?.trimmingCharacters(in: .whitespacesAndNewlines) else { + return false + } + return trimmed.count >= minimumFootnoteAltTextLength + } + + private static func isFootnoteSizedImage(_ size: CGSize) -> Bool { + guard size.width > 0, size.height > 0 else { return false } + return size.width <= maximumFootnoteImageDimension + && size.height <= maximumFootnoteImageDimension } }