Skip to content

Instantly share code, notes, and snippets.

@quesera2
Last active May 1, 2018 04:59
Show Gist options
  • Save quesera2/34089e43984fb5c1c15258788719d90f to your computer and use it in GitHub Desktop.
Save quesera2/34089e43984fb5c1c15258788719d90f to your computer and use it in GitHub Desktop.
名詠式 in Swift4

これイズ何?

ルビを振る の名詠式を Swift4 で書いたもの。

  • 行頭約物をちゃんと処理したい
  • 連続したダッシュは仮想ボディではなくて字面体でくっついてるように見せたい
  • Keinez は斜体が正しいはずなので直したい

みたいな思いがあったのですが、このリビジョンでは正規表現を extension を使わない方法に変えたので、上の辺りはまったく未処理です。

Unmanaged の使い方が毎回よく分からなくなりますね。

import UIKit
let text = """
「まさか、|後罪《クライム》の|触媒《カタリスト》を〈|讃来歌《オラトリオ》〉無しで?」
 |教師《きょうし》たちの|狼狽《ろうばい》した声が次々と上がる。
 ……なんでだろう。何を驚いているんだろう。
 ただ|普通《ふつう》に、この|触媒《カタリスト》を使って|名詠門《チャネル》を開かせただけなのに。
 そう言えば、何を|詠《よ》ぼう。
 自分の一番好きな花でいいかな。
 どんな|宝石《ほうせき》より|素敵《すてき》な、わたしの大好きな|緋色《ひいろ》の花。
 ――『|Keinez《赤》』――
 そして、少女の口ずさんだその後に――
"""
@IBDesignable class View: UIView {
lazy var textAttributes: [NSAttributedStringKey: Any] = {
let style = NSMutableParagraphStyle()
style.minimumLineHeight = 24
style.maximumLineHeight = 24
return [.font: UIFont(name: "HiraMinProN-W3", size: 18.0)!,
.verticalGlyphForm: true,
.paragraphStyle: style]
}()
var attributedText: NSAttributedString {
let workingAttributedText = NSMutableAttributedString(string: text, attributes: textAttributes)
// 名前付き正規表現は iOS11+ じゃないと無理です
let rubyRegex = try! NSRegularExpression(pattern: "|(?<string>.+?)《(?<ruby>.+?)》", options: [])
for result in rubyRegex.matches(in: text, options: [], range: NSRange(location: 0, length: text.count)).reversed() {
guard
let stringRange = Range(result.range(withName: "string"), in: text),
let rubyRange = Range(result.range(withName: "ruby"), in: text)
else {
continue
}
let string = String(text[stringRange])
let ruby = String(text[rubyRange])
workingAttributedText.replaceCharacters(in: result.range,
with: createRuby(string: string, ruby: ruby))
}
return workingAttributedText
}
private func createRuby(string: String, ruby: String) -> NSAttributedString {
var unmanage = Unmanaged.passRetained(ruby as CFString)
defer { unmanage.release() }
var text: [Unmanaged<CFString>?] = [unmanage, .none, .none, .none]
let annotation = CTRubyAnnotationCreate(.auto, .auto, 0.5, &text)
let attributedString = NSMutableAttributedString(string: string,
attributes: [kCTRubyAnnotationAttributeName as NSAttributedStringKey: annotation])
attributedString.addAttributes(textAttributes, range: NSRange(location: 0, length: string.count))
return attributedString
}
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.setFillColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
context.addRect(rect)
context.fillPath()
context.rotate(by: CGFloat.pi / 2)
context.scaleBy(x: 1.0, y: -1.0)
let framesetter = CTFramesetterCreateWithAttributedString(attributedText)
let path = CGPath(rect: CGRect(x: 0.0, y: 0.0, width: rect.height, height: rect.width), transform: nil)
let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, nil)
CTFrameDraw(frame, context)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment