title: Core Text: Simplest accurate means of getting text bounds?
body: <h3>Question:</h3>
  
  <p>What is the simplest accurate means of getting the bounds for a given line of text, using Core Text?</p>
  
  <h3>Problem:</h3>
  
  <p>I have tried multiple techniques, but am getting inconsistent results.</p>
  
  <h3>Context:</h3>
  
  <p>I have been trying to figure out how to find the actual bounds of what is for now, a single line of text.</p>
  
  <p>The Core Text documentation is at best incomplete on what the frame, line, and run level routines return, stating that they return the "actual" bounds, when they in fact disagree (at least on the frame level), and don't return the actual bounds for the specific string, but appear to return a size larger than the font size would predict.</p>
  
  <p>However, when I get the bounds on individual glyphs, I do see differences between different characters, suggesting to me that this is the only accurate method (iterating through all glyphs, finding the effective union of them all).</p>
  
  <p>I have written some tests in a playground file, am I missing something obvious?  My final goal (that partly / mostly works) is to have a custom CALayer that takes an attributed string, and scales it to fill the entire bounds.  This then plays nicely with auto layout, in that I can create a label that scales with my layout, as desired.</p>
  
  <p>My playground snippet is below, note the values generated on the right column.</p>
  
  <pre><code>// Playground - noun: a place where people can play
  
  import UIKit
  import CoreText
  import QuartzCore
  
  print("start")
  
  
  
  let f = UIFont.systemFontOfSize(12)
  let t = NSAttributedString(string: "A", attributes: [NSFontAttributeName:f])
  let line = CTLineCreateWithAttributedString(t)
  var ascent:CGFloat = 0, descent:CGFloat = 0, leading:CGFloat = 0
  CTLineGetTypographicBounds(line, &amp;ascent, &amp;descent, &amp;leading)
  ascent
  descent
  ascent + descent
  leading
  
  let boundingSize = CGSizeMake(CGFloat.max, CGFloat.max)
  let fs = CTFramesetterCreateWithAttributedString(t)
  let frameSize = CTFramesetterSuggestFrameSizeWithConstraints(fs, CFRangeMake(0, t.length),
      nil, boundingSize, nil)
  frameSize
  let lineWidth = frameSize.width
  let lineHeight = frameSize.height
  
  
  // for each run
  let runs = CTLineGetGlyphRuns(line) as [AnyObject] as! [CTRun]
  for (runIndex, run) in runs.enumerate() {
  
      // get font
      let attributes = CTRunGetAttributes(run) as NSDictionary as! [String:AnyObject]
      let runFont:CTFont = attributes[kCTFontAttributeName as String] as! CTFont
  
      // get glyphs for current run
      let glyphCount = CTRunGetGlyphCount(run)
      let range = CFRangeMake(0, glyphCount)
      var glyphs = Array&lt;CGGlyph&gt;(count: glyphCount, repeatedValue: CGGlyph())
      var positions = [CGPoint](count: glyphCount, repeatedValue: CGPointZero)
      CTRunGetGlyphs(run, range, &amp;glyphs)
      CTRunGetPositions(run, range, &amp;positions)
  
      let runWidth = CTRunGetTypographicBounds(run, range, &amp;ascent, &amp;descent, &amp;leading)
      runWidth
  
      ascent
      descent
      leading
  
      // for each glyph in run
      for (glyphInRun, var glyph) in glyphs.enumerate() {
  
          let glyphFrame = withUnsafePointer(&amp;glyph) { pointer -&gt; CGRect in
              return CTFontGetBoundingRectsForGlyphs(runFont, .Default, pointer, nil, 1) }
          glyphFrame.size
      }
  }
  
  
  
  print("done")
  </code></pre>
  
  <p>Thanks!</p>