      - parameter offset: 行頭オフセット。指定しない場合は `getOffset()` で算出したものを使用する
      - returns: (現在行にはいる文字数, ぶらさがるかどうか)
      */
-    private func getSuggestedLineCount(offset: CGFloat? = nil) -> (Int, Bool) {
+    private func getSuggestedLineCount(offset: CGFloat? = nil) -> (Int, Bool, Bool) {
         let lineWidth: CGFloat = self.width + (offset ?? self.getOffset())
-        var currentLineCount = CTTypesetterSuggestLineBreak(self.typesetter, self.location, Double(lineWidth))
+        var currentLineCount = CTTypesetterSuggestClusterBreak(self.typesetter, self.location, Double(lineWidth))
         var range = self.getCurrentLineRange(currentLineCount)
-        var didBurasagari = false
-
-        //
-        // ぶらさがり処理を適用する。句読点等は行頭１文字目に来ないので、現在行の文字列の実質的な幅が、
-        // 挿入可能な幅よりも 1.25 文字分 (1文字+約物0.25文字分) 開いていれば、
-        // ぶらさがり処理を適用できるとし 2 文字分を現在行のカウントに加算する。
-        //
-        // 例:
-        // ┌─────────┐
-        // │ぶら下り処理によ　│
-        // │り、行末が開かなく│
-        // └─────────┘
-        //　　↓
-        // ┌─────────┐
-        // │ぶら下り処理により、
-        // │行末が開かなくなる。
-        // └─────────┘
-        //
-        // TODO: textInsets を指定しない場合はぶらさがり処理させないようにする
-        //
-        if range.location + range.length + 2 <= self.length {  // 2文字加算しても全体の文字数に収まるか
-            let tmpTail = self.attributedText.attributedSubstringFromRange(NSMakeRange(range.location + range.length + 1, 1)).string  // 次の行の2文字目
+        var (didBurasagari, didOikomi) = (false, false)
+        if range.location + range.length + 1 <= self.length {  // 1文字加算しても全体の文字数に収まるか
+            let tmpTail = self.attributedText.attributedSubstringFromRange(NSMakeRange(range.location + range.length, 1)).string  // 次の行の2文字目
             if kCharactersCanBurasagari.contains(tmpTail) {
-                let textWidth = self.attributedText.attributedSubstringFromRange(range).size().width
-                if (lineWidth - textWidth) >= (self.fontSize * (1 + kCharacterHaveRightSpaceRatio)) {  // 1文字 + 句読点幅ぶんあれば
-                    range = NSMakeRange(range.location, range.length + 2)
-                    currentLineCount = range.length
-                    didBurasagari = true
-                }
-            }
-        }
-        return (currentLineCount, didBurasagari)
+                range = NSMakeRange(range.location, range.length + 1)
+                currentLineCount = range.length
+                didBurasagari = true
+            } else if kCharactersCanOikomi.contains(tmpTail) {
+                range = NSMakeRange(range.location, range.length + 1)
+                currentLineCount = range.length
+                didOikomi = true
+            }
+        }
+        return (currentLineCount, didBurasagari, didOikomi)
     }
 
     /**


            self.goToNextLinePosition()
            var offset = self.getOffset()
            let (currentLineCount, burasagari) = self.getSuggestedLineCount(offset)
            var range = self.getCurrentLineRange(currentLineCount)

            let overflow = self.isOverflow(currentLineCount)

]
private let kCharactersCanBurasagari = [
    "、", "。", "，", "．"
]
private let kCharactersCanOikomi = [
    "」", "』", "】", "》", "〉", "〕", "｝", "）", "］",
]
private let kCharacterHaveRightSpaceRatio: CGFloat = 0.25  // 右半分が空白な文字の、fontSize における実質的な幅の割合
let kCGFloatHuge: CGFloat = pow(2, 12)
