2017-05-03 9 views
1

NSViewのキャンバスにテキストを描画しようとしています。私は3行のテキストを書いて、それを超えて無視する必要があります。 String.draw(in:withAttributes)は、指定された矩形で完璧に見えるでしょう。私のコードは次のようになります調整なしNSViewでの書き出し

func renderText(_ string:String, x:Double, y:Double, numberOfLines: Int, withColor color:Color) -> Double { 
    let font = NSFont.boldSystemFont(ofSize: 11) 
    let lineHeight = Double(font.ascender + abs(font.descender) + font.leading) 
    let textHeight = lineHeight * Double(numberOfLines) + font.leading // three lines 
    let textRect = NSRect(x: x, y: y, width: 190, height: textHeight) 
    string.draw(in: textRect, withAttributes: [NSFontAttributeName: font, NSForegroundColorAttributeName: color]) 
    return textHeight 
} 

renderText("Lorem ipsum...", x: 100, y: 100, numberOfLines: 3, withColor: NSColor.white) 

、私はレンダリングされたテキストの2つだけの行を取得:

enter image description here

を私はこれらのガイドラインに従っています:https://developer.apple.com/library/content/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html#//apple_ref/doc/uid/TP40009459-CH5-SW18

私は何かが足りないのですか?

+0

それはですアプリケーションのiOS版では、同じコード(UIFontで)がうまく動作しているように思われ、3行を示しています。 –

答えて

2

最終的に、テキストは、Cocoaのテキストアーキテクチャを構成するクラスを呼び出すことで画面に表示されるため、これらのクラスから直接行の高さに関する情報を取得することは理にかなっています。以下のコードでは、NSLayoutManagerインスタンスを作成し、そのタイプセッターの動作プロパティを、関数drawInRect:withAttributes:によって作成された機械によって最終的に使用されるタイプセッターの値と一致するように設定しました。レイアウトマネージャのdefaultLineHeightメソッドを呼び出すと、その後の高さの値が表示されます。

lazy var layoutManager: NSLayoutManager = { 
    var layoutManager = NSLayoutManager() 
    layoutManager.typesetterBehavior = .behavior_10_2_WithCompatibility 
    return layoutManager 
}() 

func renderText(_ string:String, x:Double, y:Double, numberOfLines: Int, withColor color:NSColor) -> Double { 
    let font = NSFont.boldSystemFont(ofSize: 11) 
    let textHeight = Double(layoutManager.defaultLineHeight(for: font)) * Double(numberOfLines) 
    let textRect = NSRect(x: x, y: y, width: 190, height: textHeight) 
    string.draw(in: textRect, withAttributes: [NSFontAttributeName: font, NSForegroundColorAttributeName: color]) 
    return textHeight 
} 
+0

それは完全に動作します。ありがとうございました! :) –

1

私はtextHeightに小さなデルタを追加しようとします.Doublesは完全に正確です。

+0

3行目を表示させるために、約4ポイント( 'textHeight = ... + 4')を追加する必要があります。これは大きな違いです。lineHeightの計算が正しいかどうかを知りたいと思います。 iOS版のアプリでは、+ 4調整のない同じコードがiOSシミュレータで動作しているようです。 –

+1

あなたはテキストを正確な書体の境界に書いていますが、システムは文字を見やすくするために画面のプレゼンテーションのためにテキストのサイズを調整することがあります(例えば、ベクトルフォントの代わりにスクリーンフォントを使用します)。厳密なタイポグラフィ境界を使用すると、境界外になるアセンダまたはディセンダを持つ文字に問題が発生することもあります。たとえば、 "A-リング"文字や重大なアクセントのある大文字のEなどです。特定のコンテキストのテキストの高さを測定できるルーチンを見つけ出す必要があります...私の後ろのマシンから私の脳を詰めてそれを思い出すことができるかどうかがわかります。 –

+2

boundingRectWithSize:options:context:(NSAttributedString)とboundingRectWithSize:options:attributes:context:(NSStringの場合) –

2

あなたは、正確な印刷上の境界にあなたの文章を書いているが、システムは(ベクトルフォント用のために、例えば代替スクリーンフォント)テキストを読みやすくするために、画面上のプレゼンテーションのためのテキストのサイズを調整することができます。厳密なタイポグラフィ境界を使用すると、境界外になるアセンダまたはディセンダを持つ文字に問題が発生することもあります。たとえば、 "A-リング"文字や重大なアクセントのある大文字のEなどです。オプション:コンテキスト:それは私に描画されることCGContextのルールを使用してテキストの範囲を検索するに

はboundingRectWithSizeを示唆(NSAttributedString用)とboundingRectWithSize:オプション:属性:コンテキストを:(NSStringのために)