Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
freetypefont.cc
Go to the documentation of this file.
1 
18 #include "ion/text/freetypefont.h"
19 
20 #include <ft2build.h>
21 #include FT_FREETYPE_H
22 #include FT_GLYPH_H
23 #include FT_MODULE_H
24 #include FT_SYSTEM_H
25 #include FT_TRUETYPE_TABLES_H
26 
27 #include <algorithm>
28 #include <cstring> // For memcpy().
29 #include <memory>
30 #include <mutex> // NOLINT(build/c++11): only using std::call_once, not mutex.
31 #include <unordered_map>
32 #include <vector>
33 
34 #include "ion/base/allocator.h"
35 #include "ion/base/datacontainer.h"
36 #include "ion/base/lockguards.h"
37 #include "ion/base/logging.h"
39 #include "ion/port/fileutils.h"
41 #include "ion/port/mutex.h"
43 #include "ion/text/layout.h"
44 #if defined(ION_USE_ICU)
45 #include "third_party/icu/icu4c/source/common/unicode/udata.h"
46 #include "third_party/iculehb/src/src/LEFontInstance.h"
47 #include "third_party/iculx_hb/include/layout/ParagraphLayout.h"
48 #endif // ION_USE_ICU
49 
50 namespace ion {
51 namespace text {
52 
53 namespace {
54 
55 using math::Vector2f;
56 
58 typedef std::vector<math::Point2f> ControlPoints;
59 
62 static bool IsSizeValid(const Vector2f& target_size) {
63  const float width = target_size[0];
64  const float height = target_size[1];
65  return width >= 0.0f && height >= 0.0f && (width > 0.0f || height > 0.0f);
66 }
67 
69 
75 
76 
77 class FreeTypeManager {
78  public:
79  explicit FreeTypeManager(const base::AllocatorPtr& allocator);
80  ~FreeTypeManager();
81 
84  static FreeTypeManager* GetManagerForAllocator(
85  const base::AllocatorPtr& allocator) {
88  typedef std::unordered_map<base::Allocator*,
89  std::unique_ptr<FreeTypeManager>>
90  FreeTypeManagerMap;
91  ION_DECLARE_SAFE_STATIC_POINTER(FreeTypeManagerMap, map);
93 
96  base::AllocatorPtr allocator_to_use =
97  allocator.Get()
98  ? allocator
101 
102  ion::base::LockGuard lock(mutex);
103  auto it = map->find(allocator_to_use.Get());
104  if (it == map->end()) {
105  auto man = new FreeTypeManager(allocator);
106  (*map)[allocator_to_use.Get()] = std::unique_ptr<FreeTypeManager>(man);
107  return man;
108  }
109  return it->second.get();
110  }
111 
115  FT_Face InitFont(const void* data, size_t data_size,
116  bool simulate_library_failure);
117 
119  bool LoadGlyph(FT_Face face, uint32 glyph_index);
120 
122  void FreeFont(FT_Face face);
123 
124  private:
127  static void* Allocate(FT_Memory mem, long size); // NOLINT
128  static void Free(FT_Memory mem, void* ptr);
129  static void* Realloc(FT_Memory mem, long cur_size, long new_size, // NOLINT
130  void* ptr);
131 
133  static const base::AllocatorPtr& GetAllocator(FT_Memory mem) {
134  DCHECK(mem);
135  DCHECK(mem->user);
136  FreeTypeManager* mgr = static_cast<FreeTypeManager*>(mem->user);
137  DCHECK(mgr->mutex_.IsLocked());
138  DCHECK(mgr->allocator_.Get());
139  return mgr->allocator_;
140  }
141 
145  FT_MemoryRec_ ft_mem_;
147  FT_Library ft_lib_;
149  port::Mutex mutex_;
150 };
151 
152 FreeTypeManager::FreeTypeManager(const base::AllocatorPtr& allocator)
153  : allocator_(allocator), ft_lib_(NULL) {
154  ft_mem_.user = this;
155  ft_mem_.alloc = Allocate;
156  ft_mem_.free = Free;
157  ft_mem_.realloc = Realloc;
158 
159  base::LockGuard guard(&mutex_);
160  FT_New_Library(&ft_mem_, &ft_lib_);
161  if (ft_lib_) FT_Add_Default_Modules(ft_lib_);
162 }
163 
164 FreeTypeManager::~FreeTypeManager() {
165  base::LockGuard guard(&mutex_);
166  if (ft_lib_) FT_Done_Library(ft_lib_);
167 }
168 
169 FT_Face FreeTypeManager::InitFont(const void* data, size_t data_size,
170  bool simulate_library_failure) {
171  FT_Face face = NULL;
172  base::LockGuard guard(&mutex_);
173  if (FT_Library lib = simulate_library_failure ? NULL : ft_lib_) {
174  if (!FT_New_Memory_Face(lib, reinterpret_cast<const FT_Byte*>(data),
175  static_cast<FT_Long>(data_size), 0, &face)) {
176  DCHECK(face);
177  } else {
178  LOG(ERROR) << "Could not read the FreeType font data";
179  face = NULL;
180  }
181  } else {
182  LOG(ERROR) << "Could not initialize the FreeType library";
183  }
184  return face;
185 }
186 
187 void FreeTypeManager::FreeFont(FT_Face face) {
188  if (face) {
189  base::LockGuard guard(&mutex_);
190  FT_Done_Face(face);
191  }
192 }
193 
194 bool FreeTypeManager::LoadGlyph(FT_Face face, uint32 glyph_index) {
195  base::LockGuard guard(&mutex_);
196  const FT_Error result = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER);
197  return result == 0;
198 }
199 
200 void* FreeTypeManager::Allocate(FT_Memory mem, long size) { // NOLINT
201  return GetAllocator(mem)->AllocateMemory(size);
202 }
203 
204 void FreeTypeManager::Free(FT_Memory mem, void* ptr) {
205  GetAllocator(mem)->DeallocateMemory(ptr);
206 }
207 
208 void* FreeTypeManager::Realloc(FT_Memory mem, long cur_size, // NOLINT
209  long new_size, void* ptr) { // NOLINT
210  const base::AllocatorPtr& allocator = GetAllocator(mem);
211  void* new_ptr = allocator->AllocateMemory(new_size);
212  memcpy(new_ptr, ptr, cur_size);
213  allocator->DeallocateMemory(ptr);
214  return new_ptr;
215 }
216 
218 
223 
224 
226 static float ToPixels(FT_Pos v26_6) {
227  static const float kToPixels = 1.0f / 64.0f;
228  return kToPixels * static_cast<float>(v26_6);
229 }
230 
232 static const FreeTypeFont::GlyphMetrics GlyphToMetrics(
233  const FT_GlyphSlot& glyph) {
234  FreeTypeFont::GlyphMetrics metrics;
236  metrics.size.Set(ToPixels(glyph->metrics.width),
237  ToPixels(glyph->metrics.height));
238  metrics.bitmap_offset.Set(static_cast<float>(glyph->bitmap_left),
239  static_cast<float>(glyph->bitmap_top));
240  metrics.advance.Set(ToPixels(glyph->advance.x), ToPixels(glyph->advance.y));
241  return metrics;
242 }
243 
245 static void GlyphToControlPoints(const FT_GlyphSlot& glyph,
246  ControlPoints* control_points) {
247  DCHECK_EQ(control_points->size(), 0U);
248  if (glyph->format != FT_GLYPH_FORMAT_OUTLINE) return;
249  const FT_Outline& outline = glyph->outline;
250  control_points->reserve(outline.n_points);
251  for (int16 i = 0; i < outline.n_points; ++i) {
252  control_points->push_back(math::Point2f(ToPixels(outline.points[i].x),
253  ToPixels(outline.points[i].y)));
254  }
255 }
256 
258 static const Font::GlyphGrid GlyphToGrid(const FT_GlyphSlot& glyph) {
259  const FT_Bitmap bitmap = glyph->bitmap;
260  const size_t width = bitmap.width;
261  const size_t height = bitmap.rows;
262  const size_t pitch = bitmap.pitch;
263 
264  Font::GlyphGrid grid(width, height);
265  for (size_t y = 0; y < height; ++y) {
266  for (size_t x = 0; x < width; ++x) {
267  grid.pixels.Set(
268  x, y, static_cast<double>(bitmap.buffer[y * pitch + x]) / 255.0);
269  }
270  }
271  return grid;
272 }
273 
278 
280 static uint32 GlyphIndexToGlyphId(const GlyphIndex glyph) {
281  return static_cast<uint32>(glyph & 0xFFFFFFFF);
282 }
283 
285 static uint32 GlyphIndexToFaceId(const GlyphIndex glyph) {
286  return static_cast<uint32>(glyph >> 32);
287 }
288 
290 static GlyphIndex BuildGlyphIndex(uint32 glyph, uint32 face) {
291  return static_cast<GlyphIndex>(glyph) | (static_cast<GlyphIndex>(face) << 32);
292 }
293 
294 } // anonymous namespace
295 
297 
305 
306 
307 class FreeTypeFont::Helper
308 #if defined(ION_USE_ICU)
309  : public icu::LEFontInstance
310 #endif
311 {
312  public:
314  struct GlyphMetaData : public Allocatable {
316  bool IsZeroSize() const { return metrics.IsZeroSize(); }
317 
319  GlyphMetrics metrics;
321  ControlPoints control_points;
322  };
323 
325  explicit Helper(FreeTypeFont* owning_font)
326  : glyph_metadata_map_(owning_font->GetAllocator()),
327  owning_font_(owning_font),
328  allocator_(owning_font_->GetAllocator()),
329 #if defined(ION_USE_ICU)
330  font_tables_(allocator_),
331 #endif // ION_USE_ICU
332  ft_face_(NULL),
333  manager_(FreeTypeManager::GetManagerForAllocator(allocator_)) {
334  }
335  ~Helper() { FreeFont(); }
336 
340  bool Init(const void* data, size_t data_size, bool simulate_library_failure);
341 
346  bool LoadGlyph(GlyphIndex glyph_index, GlyphMetaData* glyph_meta,
347  Font::GlyphGrid* glyph_grid) const;
348 
350  const FontMetrics GetFontMetrics() const;
351 
353  const math::Vector2f GetKerning(CharIndex char_index0,
354  CharIndex char_index1) const;
355 
356  GlyphIndex GetDefaultGlyphForChar(CharIndex char_index) const;
357 
361  const GlyphMetaData& GetGlyphMetaData(GlyphIndex glyph_index) const;
362 
364  void FreeFont();
365 
369  void AddFallbackFace(const std::weak_ptr<Helper>& fallback);
370 
371 #if defined(ION_USE_ICU)
372  const void* getFontTable(LETag tableTag, size_t& length) const override;
374  le_int32 getUnitsPerEM() const override;
375  LEGlyphID mapCharToGlyph(LEUnicode32 ch) const override;
376  void getGlyphAdvance(LEGlyphID glyph, LEPoint& advance) const override;
377  le_bool getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber,
378  LEPoint& point) const override;
379  float getXPixelsPerEm() const override;
380  float getYPixelsPerEm() const override;
381  float getScaleFactorX() const override;
382  float getScaleFactorY() const override;
383  le_int32 getAscent() const override;
384  le_int32 getDescent() const override;
385  le_int32 getLeading() const override;
386 
387  const icu::LEFontInstance* GetFace(uint32 index) const;
388  GlyphIndex GlyphIndexForICUFont(const icu::LEFontInstance* icu_font,
389  int32 glyph_id) const;
390 #endif
391 
392  private:
395  void SetFontSizeLocked() const;
396 
399  uint32 GetGlyphForChar(CharIndex char_index) const;
400 
405  bool GetKerningNoFallback(CharIndex char_index0, CharIndex char_index1,
406  math::Vector2f* kern) const;
407 
410  const math::Vector2f GetKerningLocked(CharIndex char_index0,
411  CharIndex char_index1) const;
412 
414  bool LoadGlyphLocked(GlyphIndex glyph_index, GlyphMetaData* glyph_meta,
415  Font::GlyphGrid* glyph_grid) const;
416 
418  bool LoadGlyphLockedNoFallback(GlyphIndex glyph_index,
419  GlyphMetaData* glyph_meta,
420  Font::GlyphGrid* glyph_grid) const;
421 
423  typedef base::AllocMap<GlyphIndex, GlyphMetaData> GlyphMetaDataMap;
424 
429  mutable GlyphMetaDataMap glyph_metadata_map_;
430 
431  FreeTypeFont* owning_font_;
433 #if defined(ION_USE_ICU)
434  mutable base::AllocMap<LETag, std::pair<base::DataContainerPtr, size_t>>
436  font_tables_;
437 #endif
438  FT_Face ft_face_;
439  std::vector<std::weak_ptr<Helper>> fallback_helpers_;
440  FreeTypeManager* manager_;
441  mutable port::Mutex mutex_;
442 };
443 
444 bool FreeTypeFont::Helper::Init(const void* data, size_t data_size,
445  bool simulate_library_failure) {
446  DCHECK(!ft_face_);
447  base::LockGuard guard(&mutex_);
448  ft_face_ = manager_->InitFont(data, data_size, simulate_library_failure);
449  if (!ft_face_) {
450  LOG(ERROR) << "Could not read the FreeType font data.";
451  }
452  return ft_face_;
453 }
454 
455 bool FreeTypeFont::Helper::LoadGlyph(GlyphIndex glyph_index,
456  GlyphMetaData* glyph_meta,
457  Font::GlyphGrid* glyph_grid) const {
458  base::LockGuard guard(&mutex_);
459  return LoadGlyphLocked(glyph_index, glyph_meta, glyph_grid);
460 }
461 
462 bool FreeTypeFont::Helper::LoadGlyphLocked(GlyphIndex glyph_index,
463  GlyphMetaData* glyph_meta,
464  Font::GlyphGrid* glyph_grid) const {
465  uint32 face_id = GlyphIndexToFaceId(glyph_index);
466  if (face_id == 0) {
467  return LoadGlyphLockedNoFallback(glyph_index, glyph_meta, glyph_grid);
468  } else {
469  if (auto helper = fallback_helpers_[face_id - 1].lock()) {
470  base::LockGuard guard(&helper->mutex_);
471  return helper->LoadGlyphLockedNoFallback(glyph_index, glyph_meta,
472  glyph_grid);
473  } else {
474  return false;
475  }
476  }
477 }
478 
479 bool FreeTypeFont::Helper::LoadGlyphLockedNoFallback(
480  GlyphIndex glyph_index, GlyphMetaData* glyph_meta,
481  Font::GlyphGrid* glyph_grid) const {
482  DCHECK(ft_face_);
483 
485  SetFontSizeLocked();
486 
488  if (!manager_->LoadGlyph(ft_face_, GlyphIndexToGlyphId(glyph_index))) {
489  return false;
490  }
491 
493  if (glyph_meta) {
494  glyph_meta->metrics = GlyphToMetrics(ft_face_->glyph);
495  GlyphToControlPoints(ft_face_->glyph, &glyph_meta->control_points);
496  }
497  if (glyph_grid) {
498  *glyph_grid = GlyphToGrid(ft_face_->glyph);
499  }
500  return true;
501 }
502 
503 void FreeTypeFont::Helper::SetFontSizeLocked() const {
506  const size_t size_in_pixels = owning_font_->GetSizeInPixels();
507  if (FT_IS_SCALABLE(ft_face_)) {
508  FT_Set_Pixel_Sizes(ft_face_, static_cast<FT_UInt>(size_in_pixels),
509  static_cast<FT_UInt>(size_in_pixels));
510  } else { // Must be fixed size (bitmap) font.
511  DCHECK(ft_face_->num_fixed_sizes);
512  int closest_face = 0; // Index of bitmap-strike closest to size_in_pixels.
513  size_t closest_size = 0xFFFFFFFF;
514  for (int i = 0; i < ft_face_->num_fixed_sizes; ++i) {
515  FT_Select_Size(ft_face_, i);
516  const size_t size_difference =
517  abs(static_cast<int>(ft_face_->size->metrics.y_ppem) -
518  static_cast<int>(size_in_pixels));
519  if (size_difference < closest_size) {
520  closest_size = size_difference;
521  closest_face = i;
522  }
523  }
524  FT_Select_Size(ft_face_, closest_face);
525  }
526 }
527 
528 const Font::FontMetrics FreeTypeFont::Helper::GetFontMetrics() const {
529  base::LockGuard guard(&mutex_);
530  FontMetrics metrics;
531  SetFontSizeLocked();
532  metrics.line_advance_height =
533  static_cast<float>(ft_face_->size->metrics.height / 64);
534  return metrics;
535 }
536 
537 const math::Vector2f FreeTypeFont::Helper::GetKerning(
538  CharIndex char_index0, CharIndex char_index1) const {
539  math::Vector2f retval = math::Vector2f::Zero();
540  if (GetKerningNoFallback(char_index0, char_index1, &retval)) {
541  return retval;
542  }
543 
544  for (auto& fallback_helper : fallback_helpers_) {
545  auto fallback = fallback_helper.lock();
546  if (fallback &&
547  fallback->GetKerningNoFallback(char_index0, char_index1, &retval)) {
548  return retval;
549  }
550  }
551  return retval;
552 }
553 
554 bool FreeTypeFont::Helper::GetKerningNoFallback(CharIndex char_index0,
555  CharIndex char_index1,
556  math::Vector2f* kern) const {
557  const uint32 idx0 = GetGlyphForChar(char_index0);
558  const uint32 idx1 = GetGlyphForChar(char_index1);
559  base::LockGuard guard(&mutex_);
560  if (idx0 != 0 && idx1 != 0) {
562  *kern = GetKerningLocked(char_index0, char_index1);
563  return true;
564  } else if (idx0 != 0 || idx1 != 0) {
566  *kern = math::Vector2f::Zero();
567  return true;
568  }
569  return false;
570 }
571 
572 const math::Vector2f FreeTypeFont::Helper::GetKerningLocked(
573  CharIndex char_index0, CharIndex char_index1) const {
574  math::Vector2f kerning(0.f, 0.f);
575  FT_Vector ft_kerning;
576  if (ft_face_ && FT_HAS_KERNING(ft_face_) &&
577  !FT_Get_Kerning(ft_face_, static_cast<FT_UInt>(char_index0),
578  static_cast<FT_UInt>(char_index1), FT_KERNING_DEFAULT,
579  &ft_kerning)) {
581  kerning.Set(ToPixels(ft_kerning.x), ToPixels(ft_kerning.y));
582  }
583  return kerning;
584 }
585 
586 uint32 FreeTypeFont::Helper::GetGlyphForChar(CharIndex char_index) const {
587  base::LockGuard guard(&mutex_);
588  return FT_Get_Char_Index(ft_face_, char_index);
589 }
590 
591 GlyphIndex FreeTypeFont::Helper::GetDefaultGlyphForChar(
592  CharIndex char_index) const {
593  uint32 idx = GetGlyphForChar(char_index);
594  if (idx != 0) {
595  return BuildGlyphIndex(idx, 0);
596  }
597  for (uint32 i = 0; i < fallback_helpers_.size(); ++i) {
598  if (auto helper = fallback_helpers_[i].lock()) {
599  idx = helper->GetGlyphForChar(char_index);
600  if (idx != 0) {
601  return BuildGlyphIndex(idx, i + 1);
602  }
603  }
604  }
607  return BuildGlyphIndex(GetGlyphForChar(static_cast<CharIndex>(0xfffd)), 0);
608 }
609 
610 const FreeTypeFont::Helper::GlyphMetaData&
611 FreeTypeFont::Helper::GetGlyphMetaData(GlyphIndex glyph_index) const {
612  base::LockGuard guard(&mutex_);
613  if (!glyph_index) {
614  return base::InvalidReference<GlyphMetaData>();
615  }
616  const auto& it = glyph_metadata_map_.find(glyph_index);
617  if (it == glyph_metadata_map_.end()) {
618  GlyphMetaData glyph_meta;
619  if (LoadGlyphLocked(glyph_index, &glyph_meta, NULL)) {
620  return glyph_metadata_map_[glyph_index] = glyph_meta;
621  }
622  return base::InvalidReference<GlyphMetaData>();
623  }
624  return it->second;
625 }
626 
627 void FreeTypeFont::Helper::FreeFont() {
628  base::LockGuard guard(&mutex_);
629  if (ft_face_) {
630  manager_->FreeFont(ft_face_);
631  ft_face_ = NULL;
632  }
633 }
634 
635 void FreeTypeFont::Helper::AddFallbackFace(
636  const std::weak_ptr<Helper>& fallback) {
637  auto locked_fallback = fallback.lock();
638  if (!locked_fallback || locked_fallback.get() == this) {
639  return;
640  }
641  base::LockGuard guard(&mutex_);
642  fallback_helpers_.push_back(fallback);
643 }
644 
645 #if defined(ION_USE_ICU)
646 const void* FreeTypeFont::Helper::getFontTable(LETag tableTag,
647  size_t& length) const {
648  auto it = font_tables_.find(tableTag);
649  if (it == font_tables_.end()) {
650  FT_ULong table_size = 0;
651  FT_Error error =
652  FT_Load_Sfnt_Table(ft_face_, tableTag, 0, NULL, &table_size);
654  if (!error && error != FT_Err_Table_Missing) {
656  base::DataContainer::CreateOverAllocated<FT_Byte>(table_size, NULL,
657  allocator_);
658  error = FT_Load_Sfnt_Table(ft_face_, tableTag, 0,
659  table->GetMutableData<FT_Byte>(), &table_size);
660  DCHECK_EQ(error, 0);
661  auto inserted = font_tables_.insert(
662  std::make_pair(tableTag, std::make_pair(table, table_size)));
663  DCHECK(inserted.second);
664  it = inserted.first;
665  }
666  }
667  if (it == font_tables_.end()) {
668  length = 0;
669  return NULL;
670  }
671  length = it->second.second;
672  return it->second.first->GetMutableData<uint8>();
673 }
674 
675 le_int32 FreeTypeFont::Helper::getUnitsPerEM() const {
676  return ft_face_->units_per_EM;
677 }
678 
679 LEGlyphID FreeTypeFont::Helper::mapCharToGlyph(LEUnicode32 ch) const {
680  return FT_Get_Char_Index(ft_face_, ch);
681 }
682 
683 static void SetLEPointToZero(LEPoint* point) {
684  point->fX = 0.f;
685  point->fY = 0.f;
686 }
687 
688 void FreeTypeFont::Helper::getGlyphAdvance(LEGlyphID glyph,
689  LEPoint& advance) const {
690  const GlyphMetaData& data = GetGlyphMetaData(glyph);
691  if (base::IsInvalidReference(data)) return SetLEPointToZero(&advance);
692  const FreeTypeFont::GlyphMetrics& metrics = data.metrics;
693  advance.fX = metrics.advance[0];
694  advance.fY = metrics.advance[1];
695 }
696 
697 le_bool FreeTypeFont::Helper::getGlyphPoint(LEGlyphID glyph,
698  le_int32 pointNumber,
699  LEPoint& point) const {
700  const GlyphMetaData& data = GetGlyphMetaData(glyph);
701  if (base::IsInvalidReference(data)) {
702  SetLEPointToZero(&point);
703  return false;
704  }
705  const ControlPoints& control_points = data.control_points;
706  if (static_cast<size_t>(pointNumber) < control_points.size()) {
707  point.fX = control_points[pointNumber][0];
708  point.fY = control_points[pointNumber][1];
709  return true;
710  }
711  return false;
712 }
713 
714 float FreeTypeFont::Helper::getXPixelsPerEm() const {
715  return ft_face_->size->metrics.x_ppem;
716 }
717 
718 float FreeTypeFont::Helper::getYPixelsPerEm() const {
719  return ft_face_->size->metrics.y_ppem;
720 }
721 
722 float FreeTypeFont::Helper::getScaleFactorX() const {
724  static const float k16_16ToFloat = 1.0f / 65536.0f;
725  return static_cast<float>(ft_face_->size->metrics.x_scale) * k16_16ToFloat;
726 }
727 
728 float FreeTypeFont::Helper::getScaleFactorY() const {
730  static const float k16_16ToFloat = 1.0f / 65536.0f;
731  return static_cast<float>(ft_face_->size->metrics.y_scale) * k16_16ToFloat;
732 }
733 
734 le_int32 FreeTypeFont::Helper::getAscent() const {
735  return static_cast<le_int32>(
736  FT_MulFix(ft_face_->ascender,
737  static_cast<FT_Int32>(ft_face_->size->metrics.y_scale)) /
738  64);
739 }
740 
741 le_int32 FreeTypeFont::Helper::getDescent() const {
742  return -static_cast<le_int32>(
743  FT_MulFix(ft_face_->descender, ft_face_->size->metrics.y_scale) / 64);
744 }
745 
746 le_int32 FreeTypeFont::Helper::getLeading() const {
747  return static_cast<le_int32>(
748  FT_MulFix(ft_face_->height,
749  static_cast<FT_Int32>(ft_face_->size->metrics.y_scale)) /
750  64);
751 }
752 
753 const icu::LEFontInstance* FreeTypeFont::Helper::GetFace(uint32 index) const {
754  if (index == 0) {
755  return this;
756  }
757  auto helper = fallback_helpers_[index - 1].lock();
758  if (helper) {
759  return helper.get();
760  }
761  return nullptr;
762 }
763 
764 GlyphIndex FreeTypeFont::Helper::GlyphIndexForICUFont(
765  const icu::LEFontInstance* icu_font, int32 glyph_id) const {
766  for (uint32 i = 0, n = static_cast<uint32>(fallback_helpers_.size()); i <= n;
767  ++i) {
768  if (icu_font == GetFace(i)) {
769  return BuildGlyphIndex(glyph_id, i);
770  }
771  }
772  return BuildGlyphIndex(glyph_id, 0);
773 }
774 
775 #endif // ION_USE_ICU
776 
778 
783 
784 
785 FreeTypeFont::FreeTypeFont(const std::string& name, size_t size_in_pixels,
786  size_t sdf_padding, const void* data,
787  size_t data_size)
788  : Font(name, size_in_pixels, sdf_padding), helper_(new Helper(this)) {
790  if (helper_->Init(data, data_size, false)) {
791  SetFontMetrics(helper_->GetFontMetrics());
792  }
793 }
794 
795 FreeTypeFont::FreeTypeFont(const std::string& name, size_t size_in_pixels,
796  size_t sdf_padding)
797  : Font(name, size_in_pixels, sdf_padding), helper_(new Helper(this)) {
799  helper_->Init(NULL, 0U, true);
800 }
801 
803 
805  GlyphGrid* glyph_grid) const {
806  return helper_->LoadGlyph(glyph_index, NULL, glyph_grid);
807 }
808 
809 const math::Vector2f FreeTypeFont::GetKerning(CharIndex char_index0,
810  CharIndex char_index1) const {
811  return helper_->GetKerning(char_index0, char_index1);
812 }
813 
814 #if defined(ION_USE_ICU)
815 void FreeTypeFont::GetFontRunsForText(icu::UnicodeString chars,
816  iculx::FontRuns* runs) const {
817  uint32 current_face = GlyphIndexToFaceId(GetDefaultGlyphForChar(chars[0]));
818  for (int i = 1; i < chars.length(); ++i) {
819  uint32 this_face = GlyphIndexToFaceId(GetDefaultGlyphForChar(chars[i]));
820  if (this_face != current_face) {
821  runs->add(helper_->GetFace(current_face), i);
822  current_face = this_face;
823  }
824  }
825  runs->add(helper_->GetFace(current_face), chars.length());
826  return;
827 }
828 
829 GlyphIndex FreeTypeFont::GlyphIndexForICUFont(
830  const icu::LEFontInstance* icu_font, int32 glyph_id) const {
831  return helper_->GlyphIndexForICUFont(icu_font, glyph_id);
832 }
833 #endif // ION_USE_ICU
834 
836  return helper_->GetDefaultGlyphForChar(char_index);
837 }
838 
839 const Layout FreeTypeFont::BuildLayout(const std::string& text,
840  const LayoutOptions& options) const {
841  if (text.empty() || !IsSizeValid(options.target_size)) return Layout();
842 
843  const Lines lines = base::SplitString(text, "\n");
844 
846  const TextSize text_size = ComputeTextSize(*this, options, lines);
847 
850  const FreeTypeFontTransformData transform_data =
851  ComputeTransformData(*this, options, text_size);
852 
854 #if defined(ION_USE_ICU)
855  bool use_icu = true;
856 #else // ION_USE_ICU
857  bool use_icu = false;
858 #endif // ION_USE_ICU
859 
860  return LayOutText(*this, use_icu, lines, transform_data);
861 }
862 
863 void FreeTypeFont::AddFallbackFont(const FontPtr& fallback) {
864  helper_->AddFallbackFace(std::weak_ptr<Helper>(
865  reinterpret_cast<FreeTypeFont*>(fallback.Get())->helper_));
866 }
867 
869  GlyphIndex glyph_index) const {
870  if (!glyph_index) {
871  return base::InvalidReference<FreeTypeFont::GlyphMetrics>();
872  }
873  const auto& meta = helper_->GetGlyphMetaData(glyph_index);
874  if (base::IsInvalidReference(meta)) {
875  return base::InvalidReference<FreeTypeFont::GlyphMetrics>();
876  }
877  return meta.metrics;
878 }
879 
880 } // namespace text
881 } // namespace ion
bool IsInvalidReference(const T &value)
IsInvalidReference() returns true if a passed const reference of type T has an address of InvalidRefe...
Definition: invalid.h:41
std::vector< std::string > Lines
Lines of text from a single string (usually split on ' ').
#define ION_DECLARE_SAFE_STATIC_POINTER(type, variable)
Declare a static non-array pointer and calls a default constructor.
const FreeTypeFontTransformData ComputeTransformData(const Font &font, const LayoutOptions &options, const TextSize &text_size)
Sets the scale and translation fields of the LayoutData instance with the scale and translation requi...
base::AllocatorPtr allocator_
The Allocator for the FreeTypeManager and all its Fonts.
GlyphIndex GetDefaultGlyphForChar(CharIndex char_index) const override
Font overrides.
void SetFontMetrics(const FontMetrics &metrics)
Sets FontMetrics. SetFontMetrics() should only ever be called once.
Definition: font.cc:89
const Layout LayOutText(const FreeTypeFont &font, bool use_icu, const Lines &lines, const FreeTypeFontTransformData &transform_data)
Returns a Layout populated by glyphs representing lines of text.
void AddFallbackFont(const FontPtr &fallback) override
Causes this font to use the font fallback as a fallback if a requested glyph is not found...
std::string text
FT_MemoryRec_ ft_mem_
Sets up FreeType to use an Ion Allocator to manage memory.
FT_Library ft_lib_
The shared FT_Library instance.
#define DCHECK(expr)
Definition: logging.h:331
GenericLockGuard< port::Mutex > LockGuard
Convenient typedefs for ion::port::Mutex.
Definition: lockguards.h:192
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
Definition: logging.h:216
bool LoadGlyphGrid(GlyphIndex glyph_index, GlyphGrid *glyph_grid) const override
Override Font::LoadGlyphGrid to load glyphs on demand.
Table table
Definition: printer.cc:333
std::vector< std::string > ION_API SplitString(const std::string &str, const std::string &delimiters)
Splits a string into a vector of substrings, given a set of delimiter characters (expressed as a stri...
Definition: stringutils.cc:187
uint32 CharIndex
Typedef for a Unicode index of a character.
Definition: font.h:35
uint32 length
This struct defines parameters affecting layout of a single text string when passed to BuildLayout()...
Definition: layout.h:101
SharedPtr< Allocator > AllocatorPtr
Definition: allocator.h:51
T * Get() const
Returns a raw pointer to the instance, which may be NULL.
Definition: sharedptr.h:89
A LockGuard locks a mutex when created, and unlocks it when destroyed.
Definition: lockguards.h:90
const math::Vector2f GetKerning(CharIndex char_index0, CharIndex char_index1) const
Returns the delta that should be made to relative positioning of characters beyond the metrics above...
std::string name
Definition: printer.cc:324
~FreeTypeFont() override
The destructor is private because all base::Referent classes must have protected or private destructo...
const TextSize ComputeTextSize(const FreeTypeFont &font, const LayoutOptions &options, const Lines &lines)
Computes the size of text and returns it as a TextSize instance.
Copyright 2016 Google Inc.
math::Vector2f target_size
Target width and height of the text rectangle. (Default: 0 in x, 1 in y)
Definition: layout.h:112
A Layout instance specifies how glyphs are arranged to form text.
Definition: layout.h:127
int width
#define DCHECK_EQ(val1, val2)
Definition: logging.h:332
FreeTypeFont(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.
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...
TextSize contains information about the size of multi-line text.
base::ReferentPtr< DataContainer >::Type DataContainerPtr
Definition: datacontainer.h:38
port::Mutex mutex_
Protects shared access to the Allocator and FT_Library.
kLongTerm is used for objects that have persistent lifetimes, such as managers.
Definition: allocator.h:44
uint64 GlyphIndex
Definition: layout.h:46
This struct represents the metrics for a single glyph.
Definition: freetypefont.h:40
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
This contains the values needed to transform glyph rectangles into the correct coordinates.
A Mutex is used to ensure that only one thread or process can access a block of code at one time...
Definition: mutex.h:34
static const AllocatorPtr & GetDefaultAllocatorForLifetime(AllocationLifetime lifetime)
const GlyphMetrics & GetGlyphMetrics(GlyphIndex glyph_index) const
Returns the GlyphMetrics for a glyph.
Font is a base class for implementation-specific representations of fonts.
Definition: font.h:43