SVG NSTextAttachment 文本编码问题

SVG NSTextAttachment text encoding issue

为了能够将 SVG 图像用于从 HTML 创建的属性字符串,我这样做了

func createAttributedString(string: String) -> NSMutableAttributedString {
    let data = string.dataUsingEncoding(NSUTF8StringEncoding)

    let options = [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType,
                   NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding]

    let attributedString = (try! NSMutableAttributedString(
                                    data: data!,
                                    options: options as! [String : AnyObject],
                                    documentAttributes: nil))
    var svgImageAttributes: [NSTextAttachment] = []
    var svgImageRanges: [NSRange] = []
    attributedString.enumerateAttribute("NSAttachment", inRange: NSMakeRange(0, attributedString.length), options: []) { (attribute, range, stop) -> Void in


        if let attribute = attribute as? NSTextAttachment, fileType = attribute.fileType where fileType == "public.svg-image"{
            svgImageAttributes.append(attribute)
            svgImageRanges.append(range)
        }

    }
    let array = Array(zip(svgImageAttributes, svgImageRanges))

    for i in array {
        let (attachment, range) = i
        if let imageData = attachment.fileWrapper?.serializedRepresentation {
            var chapterTextAttachment:ChapterImageTextAttachment!
            if let preferedImageWidth = self.preferedImageWidth{
                chapterTextAttachment = ChapterImageTextAttachment(data: imageData, ofType: attachment.fileType, desiredWidth: preferedImageWidth)

            } else {
                chapterTextAttachment = ChapterImageTextAttachment(data: imageData, ofType: attachment.fileType)
            }
            let string = NSMutableAttributedString(string: attributedString.string.substringWithRange(attributedString.string.rangeFromNSRange(range)!), attributes: ["NSAttachment": chapterTextAttachment])
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.alignment = .Center
            string.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: range)
            attributedString.replaceCharactersInRange(range, withAttributedString: string)
        }
    }
    return attributedString
}

ChapterImageTextAttachment

class ChapterImageTextAttachment: NSTextAttachment {
    let width:CGFloat
    var size: CGSize! {
        set{
            self.bounds = CGRectMake(0,0,newValue.width, newValue.height)
        }

        get{
            return self.bounds.size
        }
    }


    init(data contentData: NSData?, ofType uti: String?, desiredWidth:CGFloat = 320) {
        self.width = desiredWidth
        super.init(data: contentData, ofType: uti)
        if let contentData = contentData {
            let string = String(data: contentData, encoding: NSASCIIStringEncoding)!
            let svgrender = SVGRenderer(string: self.fixSVGString(string))

            let image = svgrender.asImageWithSize(CGSizeMake(self.width,  1000), andScale: UIScreen.mainScreen().scale)
            self.image = image
            self.size = image.size

        }
    }

    override func attachmentBoundsForTextContainer(textContainer: NSTextContainer?, proposedLineFragment lineFrag: CGRect, glyphPosition position: CGPoint, characterIndex charIndex: Int) -> CGRect {
        return CGRectInset(self.bounds, 0, 20)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func fixSVGString(string:String) -> String {
        var result: String?
        if string.hasPrefix("rtfd"){
            let startIndex = string.rangeOfString("<?xml")?.startIndex
            let stopIndex = string.rangeOfString("</svg>")?.endIndex

            result = string.substringWithRange(startIndex! ..< stopIndex!)

        } else {
            result = string
        }
        return result!
    }
}

它有效,但有一个缺陷:非 ASCII 字符被破坏。

最重要的是,HTML 和 SVG 都是 UTF-8 编码的,但是在附件中 class 我必须将 SVG 字符串实例化为 ASCII

let string = String(data: contentData, encoding: NSASCIIStringEncoding)!

否则为零

fixSVGString(_:)删除了一些添加的富文本信息。

如何对 SVG 图像实施 UTF-8 编码?

如果返回的字符串为nil,则表示无法使用UTF-8编码进行转换。事实上,ASCII "worked" 可能只是意味着它按原样获取字节,因此任何非 ASCII 字符都是先前编码所具有的任何字节值,并且这些字符后来会被误解。

所以,很简单,您要转换的数据不是 UTF-8,也不是 ASCII。事实上,您正在寻找 "rtfd" 意味着包装数据可能是 RTF 格式,它将有自己的字符集。 RTF 规范可能有一个 \ansi 指令(我认为代码页 1252)、\mac(Mac OS 罗马)或 \pc(代码页 437)来指定字符集的内容。默认是\ansi。字符集有些混乱。

尝试使用 NSWindowsCP1252StringEncoding,而不是 NSASCIIStringEncoding。或者使用参数为 437 的 CFStringConvertWindowsCodepageToEncoding() 并查看生成的编码是否效果更好。

如果您一开始没有 NSTextAttachment,我会根据数据创建一个 NSAttributedString(使用 NSRTFDTextDocumentType 作为文档类型),然后看看您是否可以在其中找到 NSTextAttachment,并获取数据通过内容 属性.

这样

但是您确实有一个 NSTextAttachment...所以也许它就像获取 NSTextAttachment 的 "contents" 属性 而不是 fileWrapper 的 serializedRepresentation 一样简单。或者只是 return 一个 link?