Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
coretextfont.mm
Go to the documentation of this file.
1 
18 #include "ion/text/coretextfont.h"
19 
20 // Though functionally very similar, the objective-c font object on Mac is
21 // NSFont and on iOS is UIFont, and they are found in different headers.
22 #if defined(ION_PLATFORM_MAC)
23 #import <AppKit/AppKit.h>
24 
25 typedef NSFont OBJC_FONT;
26 
27 #else // defined(ION_PLATFORM_MAC)
28 #import <CoreText/CoreText.h>
29 #import <UIKit/UIKit.h>
30 
31 typedef UIFont OBJC_FONT;
32 
33 #endif // defined(ION_PLATFORM_MAC)
34 
35 #include "ion/math/matrix.h"
36 #include "ion/math/rangeutils.h"
37 #include "ion/text/layout.h"
38 
39 namespace ion {
40 namespace text {
41 
42 namespace {
43 
44 using math::Matrix2d;
45 using math::Point2d;
46 using math::Point2f;
47 using math::Point3d;
48 using math::Point3f;
49 using math::Range2d;
50 using math::Range2f;
51 using math::Vector2d;
52 using math::Vector2f;
53 
54 // The width and height of the rectangular area in which CoreText is asked to
55 // layout the incoming text. This needs to be larger than any expected output
56 // layout, so that CoreText won't wrap or clip its results.
57 static const CGFloat kPathSizePixels = 10000;
58 
59 // This is the transform that takes CoreText glyph coordinates and converts them
60 // into those that can be used in ion::text::Layout::Glyph::Quads.
61 struct Transform {
62  Vector2d translation;
63  Vector2d scale;
64 };
65 
66 // Calculates the transform that should be applied to glyph locations due to
67 // the input |options|, and for the given CoreText line data.
68 static Transform CalculateLayoutOptionsTransform(
69  CFArrayRef lines,
70  CFIndex line_count,
71  const CGPoint* line_origins,
72  const LayoutOptions& options,
73  const Font* font) {
74  // Work out the range enclosing the bounds of all the lines.
75  math::Range2d line_bounds_range;
76  for (CFIndex line_index = 0; line_index < line_count; ++line_index) {
77  CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(lines, line_index);
78  CGRect line_bounds = CTLineGetBoundsWithOptions(
79  line, kCTLineBoundsUseGlyphPathBounds);
80  line_bounds.origin.x += line_origins[line_index].x;
81  line_bounds.origin.y += line_origins[line_index].y;
82  line_bounds_range.ExtendByPoint(Point2d(CGRectGetMinX(line_bounds),
83  CGRectGetMinY(line_bounds)));
84  line_bounds_range.ExtendByPoint(Point2d(CGRectGetMaxX(line_bounds),
85  CGRectGetMaxY(line_bounds)));
86  }
87 
88  // The height as it should be considered for transformation isn't the bounds
89  // of the lines as calculated above, which take into account the presence or
90  // absence of descenders and ascenders in the text. It's a simpler calculation
91  // as follows.
92  const double rect_height =
93  font->GetFontMetrics().line_advance_height * (line_count - 1) + font->GetSizeInPixels();
94 
95  // Compute the scale based on the text size in pixels and LayoutOptions::target_size. If one of
96  // the target size dimensions is 0, use the other dimension's scale.
97  Vector2d scale_for_target_size;
98  if (options.target_size[0] == 0.0f) {
99  DCHECK_GT(options.target_size[1], 0.0f);
100  const double s = options.target_size[1] / rect_height;
101  scale_for_target_size.Set(s, s);
102  } else if (options.target_size[1] == 0.0f) {
103  DCHECK_GT(options.target_size[0], 0.0f);
104  const double s = options.target_size[0] / line_bounds_range.GetSize()[0];
105  scale_for_target_size.Set(s, s);
106  } else {
107  scale_for_target_size.Set(options.target_size[0] / line_bounds_range.GetSize()[0],
108  options.target_size[1] / rect_height);
109  }
110 
111  // Calculate the translation needed to align the text relative to the origin rather than where
112  // CoreText placed it within the CGPath.
113  Vector2d translation_for_path;
114  if (line_count) {
115  // Horizontal alignment has been done by CoreText within the path that it
116  // was passed. All that remains is to center it around the origin rather
117  // than the edges of the path rectangle.
118  switch (options.horizontal_alignment) {
119  case kAlignLeft:
120  translation_for_path[0] = 0;
121  break;
122  case kAlignHCenter:
123  translation_for_path[0] = -kPathSizePixels * 0.5;
124  break;
125  case kAlignRight:
126  translation_for_path[0] = -kPathSizePixels;
127  break;
128  }
129 
130  // Center vertically as required.
131  switch (options.vertical_alignment) {
132  case kAlignTop:
133  translation_for_path[1] = -line_bounds_range.GetMaxPoint()[1];
134  break;
135  case kAlignVCenter:
136  translation_for_path[1] =
137  -(line_bounds_range.GetMinPoint()[1] + line_bounds_range.GetMaxPoint()[1]) * 0.5;
138  break;
139  case kAlignBaseline:
140  translation_for_path[1] = -line_origins[0].y;
141  break;
142  case kAlignBottom:
143  translation_for_path[1] = -line_bounds_range.GetMinPoint()[1];
144  break;
145  }
146  }
147 
148  // Combine scale_for_target_size, translation_for_path and LayoutOptions::target_point.
149  Transform result;
150  result.scale = scale_for_target_size;
151  result.translation[0] =
152  translation_for_path[0] * scale_for_target_size[0] + options.target_point[0];
153  result.translation[1] =
154  translation_for_path[1] * scale_for_target_size[1] + options.target_point[1];
155  return result;
156 }
157 
158 // Builds a Layout::Quad in the XY plane for |rect|.
159 static const Layout::Quad BuildXyQuad(const Range2d& rect) {
160  const Point2f& min(rect.GetMinPoint());
161  const Point2f& max(rect.GetMaxPoint());
162  return Layout::Quad(Point3f(min[0], min[1], 0.0f),
163  Point3f(max[0], min[1], 0.0f),
164  Point3f(max[0], max[1], 0.0f),
165  Point3f(min[0], max[1], 0.0f));
166 }
167 
168 // Applies |transform| to |point|.
169 static Point2d ApplyTransform(const Transform& transform,
170  const Point2d& point) {
171  return Point2d(point[0] * transform.scale[0] + transform.translation[0],
172  point[1] * transform.scale[1] + transform.translation[1]);
173 }
174 
175 // Because CoreTextFonts may render glyphs from more than one CTFont, the
176 // GlyphIndex passed to the rest of Ion must combine both the CoreText CGGlyph
177 // and some representation of what CoreText font the glyph comes from. These
178 // following functions map between GlyphIndex, CGGlyph and a uint16 font index.
179 // This first function combines a |glyph| and |font_index| to create a
180 // GlyphIndex.
181 static GlyphIndex CGGlyphFontIndexToGlyphIndex(CGGlyph glyph,
182  uint16 font_index) {
183  ION_STATIC_ASSERT(sizeof(CGGlyph) <= sizeof(uint16),
184  "CGGlyph size too large for bit-packing operation.");
185  ION_STATIC_ASSERT(sizeof(CGGlyph) + sizeof(uint16) <= sizeof(GlyphIndex),
186  "CGGlyph and uint16 too large to pack into GlyphIndex.");
187  return static_cast<GlyphIndex>(glyph) | (static_cast<GlyphIndex>(font_index) << 16);
188 }
189 
190 // Extracts the system CGGlyph from an ion::text::GlyphIndex.
191 static CGGlyph GlyphIndexToCGGlyph(GlyphIndex glyph_index) {
192  return static_cast<CGGlyph>(glyph_index);
193 }
194 
195 // Extracts the font index from an ion::text::GlyphIndex.
196 static uint16 GlyphIndexToFontIndex(GlyphIndex glyph_index) {
197  return static_cast<uint16>(glyph_index >> 16);
198 }
199 
200 // Adds a glyph to the |layout|. Glyphs contained in CTLines have a rectangular
201 // |bounds|, a |position| relative to their containing CTLine and the CTLine has
202 // an origin |line_origin| relative to the whole text being rendered. This
203 // method also applies the |sdf_padding| as necessary.
204 static void AddGlyphToLayout(CGGlyph glyph,
205  uint16 font_index,
206  const Transform& transform,
207  const CGRect& bounds,
208  const CGPoint& position,
209  const CGPoint& line_origin,
210  float sdf_padding,
211  Layout* layout) {
212  // Ignore characters (e.g., newlines) represented by zero-size glyphs.
213  if (bounds.size.width * bounds.size.height == 0.0)
214  return;
215 
216  const Point2d glyph_min(CGRectGetMinX(bounds) + position.x + line_origin.x,
217  CGRectGetMinY(bounds) + position.y + line_origin.y);
218  const Point2d glyph_max(CGRectGetMaxX(bounds) + position.x + line_origin.x,
219  CGRectGetMaxY(bounds) + position.y + line_origin.y);
220 
221  Range2d transformed_glyph(ApplyTransform(transform, glyph_min),
222  ApplyTransform(transform, glyph_max));
223  const Range2f tight_bounds(Point2f(transformed_glyph.GetMinPoint()),
224  Point2f(transformed_glyph.GetMaxPoint()));
225 
226  // Scale nonuniformly about the Quad center to compensate for the padding.
227  if (sdf_padding != 0) {
228  const double padding = 2.0 * sdf_padding;
229  const Vector2d scale(
230  (CGRectGetWidth(bounds) + padding) / CGRectGetWidth(bounds),
231  (CGRectGetHeight(bounds) + padding) / CGRectGetHeight(bounds));
232  transformed_glyph = math::ScaleRangeNonUniformly(transformed_glyph, scale);
233  }
234 
235  const Vector2f offset(float(CGRectGetMinX(bounds) * transform.scale[0]),
236  float(CGRectGetMinY(bounds) * transform.scale[1]));
237 
238  CHECK(layout->AddGlyph(
239  Layout::Glyph(CGGlyphFontIndexToGlyphIndex(glyph, font_index),
240  BuildXyQuad(transformed_glyph),
241  tight_bounds,
242  offset)));
243 }
244 
245 } // anonymous namespace
246 
247 //-----------------------------------------------------------------------------
248 //
249 // Helper class. The only reason for this class is to avoid having either a
250 // CTFontRef exposed in coretextfont.h, or an awkward cast from (for example)
251 // a void * member of CoreTextFont. Given that the class exists, however, it
252 // implements all non-trivial functionality of CoreTextFont.
253 //
254 //-----------------------------------------------------------------------------
255 
256 class CoreTextFont::Helper {
257  public:
258  Helper(const CoreTextFont& owning_font, const void* data, size_t data_size);
259  ~Helper();
260 
261  // For the given string, return its layout rendered with the current font.
262  CTFrameRef CreateFrame(const std::string& text,
263  HorizontalAlignment horizontal_alignment,
264  float line_spacing) const;
265 
266  // The following methods correspond directly to CoreTextFont methods, see
267  // comments in the base Font class.
268  const Font::FontMetrics GetFontMetrics(size_t size_in_pixels) const;
269  bool LoadGlyphGrid(GlyphIndex glyph_index, GlyphGrid* glyph_grid);
271  const Layout BuildLayout(const std::string& text, const LayoutOptions& options, const Font* font);
272  std::string GetCTFontName() const;
273  void AddFallbackFont(const FontPtr& fallback);
274 
275  private:
276  // A thread-safe bi-directional mapping is maintained here between uint16 font
277  // indices and CTFonts.
278  uint16 FontToFontIndex(CTFontRef font);
279  CTFontRef FontIndexToFont(uint16 glyph_index);
280 
281  typedef base::AllocMap<CTFontRef, uint16> FontToIndexMap;
282  typedef base::AllocMap<uint16, CTFontRef> IndexToFontMap;
283 
284  FontToIndexMap font_to_index_map_;
285  IndexToFontMap index_to_font_map_;
286  // Guards all font<->index data fields above.
287  port::Mutex mutex_;
288 
289  CTFontRef coretext_font_;
290  CGPathRef path_;
291 };
292 
293 CoreTextFont::Helper::Helper(const CoreTextFont& owning_font,
294  const void* data, size_t data_size)
295  : font_to_index_map_(owning_font.GetAllocator()),
296  index_to_font_map_(owning_font.GetAllocator()),
297  path_(CGPathCreateWithRect(
298  CGRectMake(0, 0, kPathSizePixels, kPathSizePixels),
299  &CGAffineTransformIdentity)) {
300  const size_t size_in_pixels = owning_font.GetSizeInPixels();
301  if (data && data_size) {
302  CGDataProviderRef data_provider =
303  CGDataProviderCreateWithData(NULL, data, data_size, NULL);
304  CGFontRef cg_font = CGFontCreateWithDataProvider(data_provider);
305  coretext_font_ =
306  CTFontCreateWithGraphicsFont(cg_font, size_in_pixels, NULL, NULL);
307  CFRelease(cg_font);
308  CFRelease(data_provider);
309  } else {
310  CFStringRef name_ref = CFStringCreateWithCString(
311  NULL, owning_font.GetName().c_str(), kCFStringEncodingUTF8);
312  coretext_font_ = CTFontCreateWithName(name_ref, size_in_pixels, NULL);
313  CFRelease(name_ref);
314  }
315 }
316 
317 CoreTextFont::Helper::~Helper() {
318  CFRelease(coretext_font_);
319  CFRelease(path_);
320 
321  for (auto it = font_to_index_map_.begin(); it != font_to_index_map_.end(); ++it) {
322  CFRelease(it->first);
323  }
324 }
325 
326 CTFrameRef CoreTextFont::Helper::CreateFrame(
327  const std::string& text, HorizontalAlignment horizontal_alignment, float line_spacing) const {
328  // Create a CFAttributedString from |string|, with the current font.
329  CFStringRef cf_string = CFStringCreateWithBytes(
330  NULL, reinterpret_cast<const UInt8 *>(text.data()), text.size(),
331  kCFStringEncodingUTF8, false);
332  if (!cf_string) {
333  LOG(ERROR) << "CreateFrame failed on: " << text;
334  return NULL;
335  }
336  NSMutableParagraphStyle* paragraph_style =
337  [[NSMutableParagraphStyle alloc] init];
338  paragraph_style.lineHeightMultiple = line_spacing;
339 #if defined(ION_PLATFORM_MAC)
340  switch (horizontal_alignment) {
341  case kAlignLeft:
342  paragraph_style.alignment = NSLeftTextAlignment;
343  break;
344  case kAlignHCenter:
345  paragraph_style.alignment = NSCenterTextAlignment;
346  break;
347  case kAlignRight:
348  paragraph_style.alignment = NSRightTextAlignment;
349  break;
350  }
351 #else // defined(ION_PLATFORM_MAC)
352  switch (horizontal_alignment) {
353  case kAlignLeft:
354  paragraph_style.alignment = NSTextAlignmentLeft;
355  break;
356  case kAlignHCenter:
357  paragraph_style.alignment = NSTextAlignmentCenter;
358  break;
359  case kAlignRight:
360  paragraph_style.alignment = NSTextAlignmentRight;
361  break;
362  }
363 #endif // defined(ION_PLATFORM_MAC)
364  NSDictionary* attributes =
365  @{ NSFontAttributeName: (__bridge OBJC_FONT *)coretext_font_,
366  NSParagraphStyleAttributeName: paragraph_style };
367 
368  CFAttributedStringRef attrString =
369  CFAttributedStringCreate(NULL, cf_string, (CFDictionaryRef)attributes);
370  CFRelease(cf_string);
371 
372  // Create a CTFrame; this is the step that lays out the glyphs.
373  CTFramesetterRef framesetter =
374  CTFramesetterCreateWithAttributedString(attrString);
375  CFRelease(attrString);
376  CTFrameRef frame = CTFramesetterCreateFrame(
377  framesetter, CFRangeMake(0, 0), path_, NULL);
378  CFRelease(framesetter);
379  return frame;
380 }
381 
382 const Font::FontMetrics CoreTextFont::Helper::GetFontMetrics(
383  size_t size_in_pixels) const {
384  FontMetrics metrics;
385 
386  // Calculation of font metrics as per http://goo.gl/MleUbS.
387  // TODO(bug): This has just been copied from the above link, so should
388  // be verified more; it may apply only to Mac.
389  CGFloat ascent = CTFontGetAscent(coretext_font_);
390  CGFloat descent = CTFontGetDescent(coretext_font_);
391  CGFloat leading = CTFontGetLeading(coretext_font_);
392 
393  if (leading < 0)
394  leading = 0;
395 
396  leading = static_cast<CGFloat>(floor(leading + 0.5));
397  metrics.line_advance_height =
398  static_cast<float>(floor(ascent + 0.5) + floor(descent + 0.5) + leading);
399  return metrics;
400 }
401 
402 bool CoreTextFont::Helper::LoadGlyphGrid(GlyphIndex glyph_index,
403  GlyphGrid* glyph_grid) {
404  CGGlyph glyph = GlyphIndexToCGGlyph(glyph_index);
405  CGRect bounds;
406  CTFontRef font = FontIndexToFont(GlyphIndexToFontIndex(glyph_index));
407  CTFontGetBoundingRectsForGlyphs(
408  font, kCTFontDefaultOrientation, &glyph, &bounds, 1);
409  const size_t pixel_width = static_cast<size_t>(ceil(CGRectGetWidth(bounds)));
410  const size_t pixel_height =
411  static_cast<size_t>(ceil(CGRectGetHeight(bounds)));
412 
413  if (pixel_width != 0 && pixel_height != 0) {
414  // Render the glyph.
415 
416  // Create a CGContext backed by an array of bytes.
417  std::unique_ptr<uint8[]> bitmapData(new uint8[pixel_height * pixel_width]);
418  memset(bitmapData.get(), 0, pixel_height * pixel_width);
419  CGContextRef cg_context = CGBitmapContextCreate(
420  bitmapData.get(), pixel_width, pixel_height,
421  8, pixel_width, NULL, kCGImageAlphaOnly);
422  CGContextSetTextMatrix(cg_context, CGAffineTransformIdentity);
423 
424  // Render the glyph into the above CGContext.
425  CGPoint point = CGPointMake(-CGRectGetMinX(bounds), -CGRectGetMinY(bounds));
426  CTFontDrawGlyphs(font, &glyph, &point, 1, cg_context);
427 
428  // Inspect the array of bytes to calculate the contents of the GlyphData's
429  // grid.
430  static const double kScale = 1.0 / 255.0;
431  glyph_grid->pixels = base::Array2<double>(pixel_width, pixel_height);
432  for (size_t x = 0; x < pixel_width; x++) {
433  for (size_t y = 0; y < pixel_height; y++) {
434  glyph_grid->pixels.Set(
435  x, y, (double)bitmapData[x + y * pixel_width] * kScale);
436  }
437  }
438 
439  CGContextRelease(cg_context);
440  }
441  return true;
442 }
443 
444 GlyphIndex CoreTextFont::Helper::GetDefaultGlyphForChar(CharIndex char_index) {
445  // Note that this only supports 16-bit unicode and also uses
446  // CTFontGetGlyphsForCharacters which does not provide font fallback.
447  // However, this should be sufficient for its use as documented in the base
448  // class.
449  CGGlyph glyph;
450  unichar un = (unichar)char_index;
451  uint16 font_index = FontToFontIndex(coretext_font_);
452  return CTFontGetGlyphsForCharacters(coretext_font_, &un, &glyph, 1) ?
453  CGGlyphFontIndexToGlyphIndex(glyph, font_index) : 0;
454 }
455 
456 const Layout CoreTextFont::Helper::BuildLayout(const std::string& text,
457  const LayoutOptions& options,
458  const Font* font) {
459  CTFrameRef frame = CreateFrame(text, options.horizontal_alignment, options.line_spacing);
460  Layout layout;
461  if (frame == nil) {
462  return layout;
463  }
464  CFArrayRef lines = CTFrameGetLines(frame);
465  const CFIndex line_count = CFArrayGetCount(lines);
466  std::unique_ptr<CGPoint[]> line_origins(new CGPoint[line_count]);
467  CTFrameGetLineOrigins(frame, CFRangeMake(0, line_count), line_origins.get());
468 
469  Transform layout_options_transform = CalculateLayoutOptionsTransform(
470  lines, line_count, line_origins.get(), options, font);
471  layout.SetLineAdvanceHeight(
472  font->GetFontMetrics().line_advance_height *
473  static_cast<float>(layout_options_transform.scale[1]) *
474  options.line_spacing);
475 
476  for (CFIndex line_index = 0; line_index < line_count; ++line_index) {
477  CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(lines, line_index);
478  CFArrayRef runs = CTLineGetGlyphRuns(line);
479 
480  const CFIndex run_count = CFArrayGetCount(runs);
481  for (CFIndex run_index = 0; run_index < run_count; ++run_index) {
482  CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex(runs, run_index);
483 
484  // Check if this run is the correct font.
485  NSDictionary* run_attributes = (NSDictionary*)CTRunGetAttributes(run);
486  CTFontRef run_font =
487  (__bridge CTFontRef)[run_attributes objectForKey:NSFontAttributeName];
488  uint16 font_index = FontToFontIndex(run_font);
489 
490  const CFIndex glyph_count = CTRunGetGlyphCount(run);
491 
492  std::unique_ptr<CGPoint[]> positions(new CGPoint[glyph_count]);
493  CTRunGetPositions(run, CFRangeMake(0, glyph_count), positions.get());
494 
495  std::unique_ptr<CGGlyph[]> glyphs(new CGGlyph[glyph_count]);
496  CTRunGetGlyphs(run, CFRangeMake(0, glyph_count), glyphs.get());
497 
498  std::unique_ptr<CGRect[]> bounds(new CGRect[glyph_count]);
499  CTFontGetBoundingRectsForGlyphs(run_font, kCTFontDefaultOrientation,
500  glyphs.get(), bounds.get(), glyph_count);
501 
502  for (CFIndex glyph_index = 0; glyph_index < glyph_count; ++glyph_index) {
503  AddGlyphToLayout(glyphs[glyph_index],
504  font_index,
505  layout_options_transform,
506  bounds[glyph_index],
507  positions[glyph_index],
508  line_origins[line_index],
509  font->GetSdfPadding(),
510  &layout);
511  }
512  }
513  }
514  CFRelease(frame);
515 
516  return layout;
517 }
518 
519 std::string CoreTextFont::Helper::GetCTFontName() const {
520  return [CFBridgingRelease(CTFontCopyFullName(coretext_font_)) UTF8String];
521 }
522 
523 uint16 CoreTextFont::Helper::FontToFontIndex(CTFontRef font) {
524  base::LockGuard guard(&mutex_);
525  auto existing = font_to_index_map_.find(font);
526  if (existing == font_to_index_map_.end()) {
527  // It is assumed that there would never be enough fallback fonts mapped to
528  // cause font_index to overflow a uint16.
529  CHECK_LT(font_to_index_map_.size(), kuint16max);
530  uint16 font_index = static_cast<uint16>(font_to_index_map_.size());
531  font_to_index_map_[font] = font_index;
532  index_to_font_map_[font_index] = font;
533  CFRetain((CTFontRef)font);
534  return font_index;
535  }
536  return existing->second;
537 }
538 
539 CTFontRef CoreTextFont::Helper::FontIndexToFont(uint16 font_index) {
540  base::LockGuard guard(&mutex_);
541  return index_to_font_map_[font_index];
542 }
543 
544 void CoreTextFont::Helper::AddFallbackFont(const FontPtr& fallback) {
545  LOG(WARNING) << "Fallback support for CoreTextFont is not implemented";
546 }
547 
548 //-----------------------------------------------------------------------------
549 //
550 // CoreTextFont functions.
551 //
552 //-----------------------------------------------------------------------------
553 
554 CoreTextFont::CoreTextFont(
555  const std::string& name, size_t size_in_pixels, size_t sdf_padding,
556  const void* data, size_t data_size)
557  : Font(name, size_in_pixels, sdf_padding),
558  helper_(new Helper(*this, data, data_size)) {
559  SetFontMetrics(helper_->GetFontMetrics(size_in_pixels));
560 }
561 
563 
565  GlyphGrid* glyph_grid) const {
566  return helper_->LoadGlyphGrid(glyph_index, glyph_grid);
567 }
568 
570  return helper_->GetDefaultGlyphForChar(char_index);
571 }
572 
573 const Layout CoreTextFont::BuildLayout(const std::string& text,
574  const LayoutOptions& options) const {
575  return helper_->BuildLayout(text, options, this);
576 }
577 
578 std::string CoreTextFont::GetCTFontName() const {
579  return helper_->GetCTFontName();
580 }
581 
582 void CoreTextFont::AddFallbackFont(const FontPtr& fallback) {
583  helper_->AddFallbackFont(fallback);
584 }
585 
586 #undef OBJC_FONT
587 
588 } // namespace text
589 } // namespace ion
#define CHECK(expr)
Definition: logging.h:323
void SetFontMetrics(const FontMetrics &metrics)
Sets FontMetrics. SetFontMetrics() should only ever be called once.
Definition: font.cc:89
bool LoadGlyphGrid(GlyphIndex glyph_index, GlyphGrid *glyph_grid) const override
Called by GetGlyphGrid() for missing glyphs.
Matrix< 2, double > Matrix2d
Definition: matrix.h:368
std::string text
GenericLockGuard< port::Mutex > LockGuard
Convenient typedefs for ion::port::Mutex.
Definition: lockguards.h:192
Range< 2, double > Range2d
Definition: range.h:374
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
Definition: logging.h:216
#define DCHECK_GT(val1, val2)
Definition: logging.h:337
uint32 offset
Range< 2, float > Range2f
Definition: range.h:373
GlyphIndex GetDefaultGlyphForChar(CharIndex char_index) const override
Font overrides.
uint32 CharIndex
Typedef for a Unicode index of a character.
Definition: font.h:35
This struct defines parameters affecting layout of a single text string when passed to BuildLayout()...
Definition: layout.h:101
#define CHECK_LT(val1, val2)
Definition: logging.h:327
Point3f position
Definition: shapeutils.cc:67
const Layout BuildLayout(const std::string &text, const LayoutOptions &options) const override
Creates a layout as specified by options for a given single- or multi- line string text...
Vector2d translation
Definition: coretextfont.mm:62
base::ReferentPtr< Font >::Type FontPtr
Definition: font.h:38
size_t line_count
std::string name
Definition: printer.cc:324
const FontMetrics & GetFontMetrics() const
Returns the FontMetrics for the font.
Definition: font.h:87
A Layout instance specifies how glyphs are arranged to form text.
Definition: layout.h:127
UIFont OBJC_FONT
Copyright 2016 Google Inc.
Definition: coretextfont.mm:31
std::string GetCTFontName() const
Returns the name of the backing system font.
HorizontalAlignment
Alignment enums.
Definition: layout.h:54
#define ION_STATIC_ASSERT(expr, message)
Copyright 2016 Google Inc.
Definition: static_assert.h:35
CoreTextFont(const std::string &name, size_t size_in_pixels, size_t sdf_padding, const void *data, size_t data_size)
Constructs an instance using the given name.
port::Mutex mutex_
Protects shared access to the Allocator and FT_Library.
Vector2d scale
Definition: coretextfont.mm:63
uint64 GlyphIndex
Definition: layout.h:46
A grid representing a rendered glyph, with each grid pixel representing pixel coverage in the range (...
Definition: font.h:48
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
Definition: sharedptr.h:60
void AddFallbackFont(const FontPtr &fallback) override
Causes this font to use the font fallback as a fallback if a requested glyph is not found...
const Range< Dimension, T > ScaleRangeNonUniformly(const Range< Dimension, T > &r, const Vector< Dimension, T > scale_factors)
Returns a Range that is the input Range scaled nonuniformly about its center by the given per-dimensi...
Definition: rangeutils.h:123
Font(const std::string &name, size_t size_in_pixels, size_t sdf_padding)
The constructor is protected because this is an abstract base class.
Definition: font.cc:41
Font is a base class for implementation-specific representations of fonts.
Definition: font.h:43