Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fontimage.cc
Go to the documentation of this file.
1 
18 #include "ion/text/fontimage.h"
19 
20 #include <iterator>
21 #include <vector>
22 
23 #include "base/integral_types.h"
24 #include "ion/base/array2.h"
25 #include "ion/base/invalid.h"
26 #include "ion/base/lockguards.h"
27 #include "ion/base/logging.h"
28 #include "ion/base/serialize.h"
30 #include "ion/gfx/sampler.h"
32 #include "ion/math/utils.h"
33 #include "ion/math/vector.h"
34 #include "ion/text/binpacker.h"
35 #include "ion/text/font.h"
36 #include "ion/text/sdfutils.h"
37 
38 namespace ion {
39 namespace text {
40 
41 namespace {
42 
43 using gfx::Image;
44 using gfx::ImagePtr;
45 using gfx::Sampler;
46 using gfx::SamplerPtr;
47 using gfx::Texture;
48 using gfx::TexturePtr;
49 using math::Point2f;
50 using math::Point2ui;
51 using math::Range2f;
52 using math::Vector2f;
53 using math::Vector2ui;
54 
56 
61 
62 
64 typedef base::Array2<double> SdfGrid;
65 
70 typedef base::AllocMap<GlyphIndex, SdfGrid> SdfGridMap;
71 
73 typedef FontImage::ImageData::TexRectMap TexRectMap;
74 
77 struct ImageDataWrapper {
78  explicit ImageDataWrapper(const base::AllocatorPtr& allocator)
79  : image_data(allocator),
80  packed_area(0),
81  used_area_fraction(0.f) {}
82 
84  FontImage::ImageData image_data;
85 
87  BinPacker bin_packer;
88 
90  size_t packed_area;
91 
94 };
95 
98 struct DeferredUpdate : Texture::SubImage {
99  DeferredUpdate() {}
100 
101  DeferredUpdate(const TexturePtr& texture_in, size_t level_in,
102  const math::Point2ui& offset_in, const ImagePtr& image_in)
103  : Texture::SubImage(level_in, offset_in, image_in),
104  texture(texture_in) {}
105 
108 };
109 
111 
116 
117 
120 static const SdfGridMap BuildSdfGridMap(const Font& font,
121  const GlyphSet& glyph_set,
122  const base::AllocatorPtr& allocator) {
123  SdfGridMap grid_map(allocator);
124  for (auto it = glyph_set.begin(); it != glyph_set.end(); ++it) {
125  const Font::GlyphGrid& glyph_grid = font.GetGlyphGrid(*it);
126  DCHECK(!base::IsInvalidReference(glyph_grid));
128  grid_map[*it] = glyph_grid.pixels;
129  }
130  return grid_map;
131 }
132 
135 static void AddGridsToBinPacker(const SdfGridMap& grids, BinPacker* packer) {
136  for (SdfGridMap::const_iterator it = grids.begin(); it != grids.end(); ++it) {
137  const SdfGrid& grid = it->second;
138  const uint32 width = static_cast<uint32>(grid.GetWidth());
139  const uint32 height = static_cast<uint32>(grid.GetHeight());
140  if (width * height)
141  packer->AddRectangle(it->first, Vector2ui(width, height));
142  }
143 }
144 
146 static size_t ComputeTotalGridArea(const SdfGridMap& grids) {
147  size_t area = 0;
148  for (SdfGridMap::const_iterator it = grids.begin(); it != grids.end(); ++it) {
149  const SdfGrid& grid = it->second;
150  area += grid.GetWidth() * grid.GetHeight();
151  }
152  return area;
153 }
154 
156 static void InsertGrid(const SdfGrid& grid, const Point2ui& bottom_left,
157  SdfGrid* composite_grid) {
158  DCHECK_LE(bottom_left[0] + grid.GetWidth(), composite_grid->GetWidth());
159  DCHECK_LE(bottom_left[1] + grid.GetHeight(), composite_grid->GetHeight());
160 
161  const size_t width = grid.GetWidth();
162  const size_t height = grid.GetHeight();
163  for (size_t y = 0; y < height; ++y) {
164  for (size_t x = 0; x < width; ++x) {
165  composite_grid->Set(x + bottom_left[0], y + bottom_left[1],
166  grid.Get(x, y));
167  }
168  }
169 }
170 
173 static void NormalizeGrid(const double scale_factor, SdfGrid* grid) {
174  const size_t width = grid->GetWidth();
175  const size_t height = grid->GetHeight();
176 
177  for (size_t y = 0; y < height; ++y) {
178  for (size_t x = 0; x < width; ++x) {
180  const double d = scale_factor * grid->Get(x, y);
182  grid->Set(x, y, (math::Clamp(d, -1.0, 1.0) + 1.0) * 0.5);
183  }
184  }
185 }
186 
189 static void NormalizeGridsInMap(size_t sdf_padding, SdfGridMap* grids) {
190  const float scale_factor =
191  sdf_padding ? 1.0f / static_cast<float>(sdf_padding) : 1.0f;
192  for (SdfGridMap::iterator it = grids->begin(); it != grids->end(); ++it)
193  NormalizeGrid(scale_factor, &it->second);
194 }
195 
199 static const SdfGrid CreatePackedGrid(
200  const SdfGridMap& grids, const BinPacker& bin_packer,
201  uint32 width, uint32 height, size_t sdf_padding) {
204  const double initial_value = static_cast<double>(width + height);
205  SdfGrid packed_grid(width, height, initial_value);
206 
207  const std::vector<BinPacker::Rectangle>& rects = bin_packer.GetRectangles();
208  const size_t count = rects.size();
209  for (size_t i = 0; i < count; ++i) {
210  const BinPacker::Rectangle& rect = rects[i];
211  SdfGridMap::const_iterator it =
212  grids.find(static_cast<GlyphIndex>(rect.id));
213  DCHECK(it != grids.end());
214  InsertGrid(it->second, rect.bottom_left, &packed_grid);
215  }
216 
217  const float scale_factor =
218  sdf_padding ? 1.0f / static_cast<float>(sdf_padding) : 1.0f;
219  NormalizeGrid(scale_factor, &packed_grid);
220  return packed_grid;
221 }
222 
229 static const SdfGrid PackIntoMinimalGrid(
230  const SdfGridMap& grids, size_t max_image_size, size_t sdf_padding,
231  BinPacker* bin_packer) {
233  const size_t total_area = ComputeTotalGridArea(grids);
234  DCHECK_GT(total_area, 0U);
235 
238  if (total_area > math::Square(max_image_size))
239  return SdfGrid();
240 
243  const size_t initial_size =
244  math::NextPowerOf2(static_cast<uint32>(math::Sqrt(total_area))) / 2;
245  uint32 image_width = static_cast<uint32>(initial_size);
246  uint32 image_height = image_width;
247  bool double_the_width = true;
248  while (!bin_packer->Pack(Vector2ui(image_width, image_height))) {
252  if (double_the_width)
253  image_width *= 2;
254  else
255  image_height *= 2;
256  double_the_width = !double_the_width;
257  if (image_width > max_image_size || image_height > max_image_size)
258  return SdfGrid();
259  }
260 
261  return CreatePackedGrid(grids, *bin_packer, image_width, image_height,
262  sdf_padding);
263 }
264 
267 static SamplerPtr* CreateSampler() {
268  base::AllocatorPtr allocator =
270  SamplerPtr* sampler_ptr = new SamplerPtr;
271  SamplerPtr sampler(new(allocator)Sampler);
272  *sampler_ptr = sampler;
275  sampler->SetMinFilter(ion::gfx::Sampler::kLinear);
276  sampler->SetMagFilter(ion::gfx::Sampler::kLinear);
277  sampler->SetWrapS(ion::gfx::Sampler::kClampToEdge);
278  sampler->SetWrapT(ion::gfx::Sampler::kClampToEdge);
279  return sampler_ptr;
280 }
281 
284 static TexturePtr CreateTexture(const base::AllocatorPtr& allocator) {
286  CreateSampler());
287  TexturePtr texture(new(allocator) Texture);
288  texture->SetSampler(*sampler);
289  return texture;
290 }
291 
294 static ImagePtr CreateImage(size_t width, size_t height,
295  const base::AllocatorPtr& allocator) {
297  std::vector<uint8> data_buf(width * height);
298 
302  ImagePtr image(new(allocator) Image);
303  image->Set(Image::kLuminance,
304  static_cast<uint32>(width), static_cast<uint32>(height),
305  base::DataContainer::CreateAndCopy<uint8>(
306  &data_buf[0], data_buf.size(), true, allocator));
307  return image;
308 }
309 
312 static void StoreGridInImage(const SdfGrid& grid, const ImagePtr& image) {
313  const size_t width = grid.GetWidth();
314  const size_t height = grid.GetHeight();
315 
317  DCHECK(image->GetData().Get());
318  DCHECK_EQ(image->GetDataSize(), width * height);
319  uint8* data = image->GetData()->GetMutableData<uint8>();
320  DCHECK(data);
321 
323  for (size_t y = 0; y < height; ++y) {
324  for (size_t x = 0; x < width; ++x) {
325  const double d = grid.Get(x, y);
326  data[y * width + x] = static_cast<uint8>(d * 255.0);
327  }
328  }
329 }
330 
333 static const Range2f ComputeTextureRectangle(
334  const BinPacker::Rectangle& rect, const Vector2f& inverse_image_size) {
335  const Point2f min_point(
336  static_cast<float>(rect.bottom_left[0]) * inverse_image_size[0],
337  static_cast<float>(rect.bottom_left[1]) * inverse_image_size[1]);
338  const Vector2f size(static_cast<float>(rect.size[0]) * inverse_image_size[0],
339  static_cast<float>(rect.size[1]) * inverse_image_size[1]);
340  return Range2f::BuildWithSize(min_point, size);
341 }
342 
345 static const TexRectMap ComputeTextureRectangleMap(
346  const Image& image, const BinPacker& bin_packer) {
347  const Vector2f inverse_image_size(
348  1.0f / static_cast<float>(image.GetWidth()),
349  1.0f / static_cast<float>(image.GetHeight()));
350 
352  const std::vector<BinPacker::Rectangle>& rects = bin_packer.GetRectangles();
353  const size_t num_rects = rects.size();
354  TexRectMap texture_rectangle_map(image.GetAllocator());
355  for (size_t i = 0; i < num_rects; ++i) {
356  const BinPacker::Rectangle& rect = rects[i];
357  texture_rectangle_map[static_cast<GlyphIndex>(rect.id)] =
358  ComputeTextureRectangle(rect, inverse_image_size);
359  }
360  return texture_rectangle_map;
361 }
362 
365 static void UpdateImageData(
366  const SdfGridMap& grid_map, const BinPacker& bin_packer, uint32 image_size,
367  size_t sdf_padding, FontImage::ImageData* image_data,
368  const base::AllocatorPtr& allocator) {
369  const SdfGrid packed_grid = CreatePackedGrid(
370  grid_map, bin_packer, image_size, image_size, sdf_padding);
371  DCHECK(packed_grid.GetSize());
372 
374  if (!image_data->texture->HasImage(0U))
375  image_data->texture->SetImage(
376  0U, CreateImage(packed_grid.GetWidth(), packed_grid.GetHeight(),
377  allocator));
378  const ImagePtr& image = image_data->texture->GetImage(0U);
379 
381  StoreGridInImage(packed_grid, image);
382 
384  image_data->texture_rectangle_map =
385  ComputeTextureRectangleMap(*image, bin_packer);
386 }
387 
393 static void StoreSubImages(const SdfGridMap& grids, const BinPacker& bin_packer,
394  const base::AllocatorPtr& alloc,
395  const TexturePtr& texture,
396  base::AllocVector<DeferredUpdate>* updates) {
397  const std::vector<BinPacker::Rectangle>& rects = bin_packer.GetRectangles();
398  const size_t count = rects.size();
399  for (size_t i = 0; i < count; ++i) {
400  const BinPacker::Rectangle& rect = rects[i];
401  const auto& it = grids.find(static_cast<GlyphIndex>(rect.id));
404  if (it != grids.end()) {
405  const SdfGrid& grid = it->second;
406  ImagePtr image = CreateImage(grid.GetWidth(), grid.GetHeight(), alloc);
407  StoreGridInImage(grid, image);
408  if (updates)
409  updates->push_back(
410  DeferredUpdate(texture, 0U, rect.bottom_left, image));
411  else
412  texture->SetSubImage(0U, rect.bottom_left, image);
413  }
414  }
415 }
416 
418 static void SetDifference(const GlyphSet& lhs, const GlyphSet& rhs,
419  GlyphSet* diff) {
420  std::set_difference(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(),
421  std::inserter(*diff, diff->end()));
422 }
423 
424 } // anonymous namespace
425 
427 
432 
433 
435  : texture(CreateTexture(allocator)),
436  glyph_set(allocator),
437  texture_rectangle_map(allocator) {}
438 
440 
445 
446 
447 FontImage::FontImage(Type type, const FontPtr& font, size_t max_image_size)
448  : type_(type), font_(font), max_image_size_(max_image_size) {}
449 
451 
452 bool FontImage::GetTextureCoords(const ImageData& image_data,
453  GlyphIndex glyph_index,
454  math::Range2f* rectangle) {
455  if (base::IsInvalidReference(image_data))
456  return false;
457  const ImageData::TexRectMap::const_iterator it =
458  image_data.texture_rectangle_map.find(glyph_index);
459  if (it == image_data.texture_rectangle_map.end())
460  return false;
461  *rectangle = it->second;
462  return !rectangle->IsEmpty();
463 }
464 
466 
471 
472 
473 StaticFontImage::StaticFontImage(const FontPtr& font, size_t max_image_size,
474  const GlyphSet& glyph_set)
475  : FontImage(kStatic, font, max_image_size),
476  image_data_(
477  InitImageData(font.Get()
478  ? font->GetName() + "_" +
479  base::ValueToString(font->GetSizeInPixels())
480  : "",
481  glyph_set)) {}
482 
483 StaticFontImage::StaticFontImage(const FontPtr& font, size_t max_image_size,
484  const ImageData& image_data)
485  : FontImage(kStatic, font, max_image_size),
486  image_data_(image_data) {}
487 
489 
491  const GlyphSet& glyph_set) {
493  return image_data_;
494 }
495 
496 const FontImage::ImageData StaticFontImage::InitImageData(
497  const std::string& texture_name, const GlyphSet& glyph_set) {
498  const base::AllocatorPtr& allocator = GetAllocator();
499  ImageData image_data(allocator);
500  image_data.texture->SetLabel(texture_name);
501  Font* font = GetFont().Get();
502 
503  if (glyph_set.empty() || !font) {
504  return image_data;
505  }
506 
507  image_data.glyph_set = glyph_set;
508  const base::AllocatorPtr& sta =
510 
512  font->CacheSdfGrids(glyph_set);
513 
515  const SdfGridMap grid_map = BuildSdfGridMap(*font, glyph_set, sta);
516 
518  BinPacker bin_packer;
519  AddGridsToBinPacker(grid_map, &bin_packer);
520 
522  const SdfGrid packed_grid = PackIntoMinimalGrid(
523  grid_map, GetMaxImageSize(), font->GetSdfPadding(), &bin_packer);
524 
526  if (packed_grid.GetSize()) {
528  ImagePtr image =
529  CreateImage(packed_grid.GetWidth(), packed_grid.GetHeight(), allocator);
530  image_data.texture->SetImage(0U, image);
531  StoreGridInImage(packed_grid, image);
532 
534  image_data.texture_rectangle_map =
535  ComputeTextureRectangleMap(*image, bin_packer);
536  }
537 
538  return image_data;
539 }
540 
542 
548 
549 
550 class DynamicFontImage::Helper : public Allocatable {
551  public:
552  Helper() : image_data_wrappers_(*this), deferred_updates_(*this) {}
553 
555  base::AllocVector<ImageDataWrapper>& GetImageDataWrappers() {
556  return image_data_wrappers_;
557  }
558 
560  base::AllocVector<DeferredUpdate>& GetDeferredUpdates() {
561  return deferred_updates_;
562  }
563 
564  private:
566  base::AllocVector<ImageDataWrapper> image_data_wrappers_;
567 
569  base::AllocVector<DeferredUpdate> deferred_updates_;
570 };
571 
573 
578 
579 
580 DynamicFontImage::DynamicFontImage(const FontPtr& font, size_t image_size)
581  : FontImage(kDynamic, font, image_size),
582  helper_(new(GetAllocator()) Helper()),
583  updates_deferred_(false) {}
584 
586 
588  return helper_->GetImageDataWrappers().size();
589 }
590 
592  const base::AllocVector<ImageDataWrapper>& wrappers =
593  helper_->GetImageDataWrappers();
594  return index < wrappers.size() ? wrappers[index].image_data
595  : base::InvalidReference<ImageData>();
596 }
597 
599  const base::AllocVector<ImageDataWrapper>& wrappers =
600  helper_->GetImageDataWrappers();
601  return index < wrappers.size() ? wrappers[index].used_area_fraction : 0.f;
602 }
603 
605  if (updates_deferred_) {
606  base::AllocVector<DeferredUpdate>& updates = helper_->GetDeferredUpdates();
607  base::ReadLock lock(&update_lock_);
608  base::ReadGuard guard(&lock);
609  const size_t count = updates.size();
610  for (size_t i = 0; i < count; ++i) {
611  const DeferredUpdate& di = updates[i];
612  di.texture->SetSubImage(di.level, di.offset, di.image);
613  }
614  updates.clear();
615  }
616 }
617 
619  const GlyphSet& glyph_set) {
620  return GetImageData(FindImageDataIndex(glyph_set));
621 }
622 
624  const GlyphSet& unfiltered_glyph_set) {
626  size_t index = base::kInvalidIndex;
627 
628  if (!GetFont().Get()) {
629  return index;
630  }
631 
633  unfiltered_glyph_set);
634  GetFont()->FilterGlyphs(&glyph_set);
635 
636  if (glyph_set.empty() || (glyph_set.size() == 1 && !(*glyph_set.begin())))
637  return index;
638 
640  GetFont()->CacheSdfGrids(glyph_set);
641 
644 
646  index = FindContainingImageDataIndexPrefiltered(glyph_set);
647 
649  if (index == base::kInvalidIndex) {
650  index = FindImageDataThatFits(glyph_set);
651  }
652 
655  if (index == base::kInvalidIndex) {
656  index = AddImageData(glyph_set);
657  }
658 
659  return index;
660 }
661 
663  const GlyphSet& unfiltered_glyph_set) {
664  if (!GetFont().Get()) {
665  return base::kInvalidIndex;
666  }
668  unfiltered_glyph_set);
669  GetFont()->FilterGlyphs(&glyph_set);
670  return glyph_set.size() ? FindContainingImageDataIndexPrefiltered(glyph_set)
672 }
673 
674 size_t DynamicFontImage::FindContainingImageDataIndexPrefiltered(
675  const GlyphSet& glyph_set) {
676  const base::AllocVector<ImageDataWrapper>& wrappers =
677  helper_->GetImageDataWrappers();
678  const size_t num_wrappers = wrappers.size();
679  for (size_t i = 0; i < num_wrappers; ++i) {
680  if (HasAllGlyphs(wrappers[i].image_data, glyph_set)) return i;
681  const auto& candidate = wrappers[i].image_data.glyph_set;
682  if (std::includes(candidate.cbegin(), candidate.cend(), glyph_set.cbegin(),
683  glyph_set.cend())) {
684  return i;
685  }
686  }
687  return base::kInvalidIndex;
688 }
689 
690 size_t DynamicFontImage::FindImageDataThatFits(const GlyphSet& glyph_set) {
691  DCHECK(GetFont().Get());
692  const Font& font = *GetFont();
693  const uint32 image_size = static_cast<uint32>(GetMaxImageSize());
694  const size_t max_area = math::Square(image_size);
695 
696  base::AllocVector<ImageDataWrapper>& wrappers =
697  helper_->GetImageDataWrappers();
698  const size_t num_wrappers = wrappers.size();
699  for (size_t i = 0; i < num_wrappers; ++i) {
700  ImageDataWrapper& wrapper = wrappers[i];
701  ImageData& image_data = wrapper.image_data;
702  const base::AllocatorPtr& allocator = GetAllocator();
703  const base::AllocatorPtr& sta =
705 
708  GlyphSet missing_glyph_set(GetAllocator());
709  SetDifference(glyph_set, image_data.glyph_set, &missing_glyph_set);
710  DCHECK(!missing_glyph_set.empty());
711  SdfGridMap missing_grid_map = BuildSdfGridMap(font, missing_glyph_set, sta);
712 
715  const size_t added_area = ComputeTotalGridArea(missing_grid_map);
716  if (wrapper.packed_area + added_area > max_area)
717  continue;
718 
721  BinPacker test_bin_packer(wrapper.bin_packer);
722  AddGridsToBinPacker(missing_grid_map, &test_bin_packer);
723 
725  if (test_bin_packer.Pack(Vector2ui(image_size, image_size))) {
727  image_data.glyph_set.insert(missing_glyph_set.begin(),
728  missing_glyph_set.end());
729 
731  wrapper.bin_packer = test_bin_packer;
732 
734  NormalizeGridsInMap(font.GetSdfPadding(), &missing_grid_map);
736  if (updates_deferred_) {
737  base::WriteLock lock(&update_lock_);
738  base::WriteGuard guard(&lock);
739  StoreSubImages(missing_grid_map, test_bin_packer, sta,
740  wrapper.image_data.texture,
741  &helper_->GetDeferredUpdates());
742  } else {
743  StoreSubImages(missing_grid_map, test_bin_packer, sta,
744  wrapper.image_data.texture, NULL);
745  }
747  wrapper.image_data.texture_rectangle_map = ComputeTextureRectangleMap(
748  *wrapper.image_data.texture->GetImage(0U), test_bin_packer);
749 
751  wrapper.packed_area += added_area;
752  wrapper.used_area_fraction +=
753  static_cast<float>(added_area) / static_cast<float>(max_area);
754  return i;
755  }
756  }
757 
759  return base::kInvalidIndex;
760 }
761 
762 size_t DynamicFontImage::AddImageData(const GlyphSet& glyph_set) {
763  const base::AllocatorPtr& allocator = GetAllocator();
764  const base::AllocatorPtr& sta =
766  DCHECK(GetFont().Get());
767  const Font& font = *GetFont();
768 
770  base::AllocVector<ImageDataWrapper>& wrappers =
771  helper_->GetImageDataWrappers();
772  const size_t index = wrappers.size();
773  wrappers.push_back(ImageDataWrapper(allocator));
774  ImageDataWrapper& wrapper = wrappers[index];
775  ImageData& image_data = wrapper.image_data;
776  const std::string texture_name = font.GetName() + "_" +
777  base::ValueToString(font.GetSizeInPixels()) +
778  "_" + base::ValueToString(index);
779  image_data.texture->SetLabel(texture_name);
780 
782  const SdfGridMap grid_map = BuildSdfGridMap(font, glyph_set, sta);
783 
785  AddGridsToBinPacker(grid_map, &wrapper.bin_packer);
786 
788  const uint32 image_size = static_cast<uint32>(GetMaxImageSize());
789  if (wrapper.bin_packer.Pack(Vector2ui(image_size, image_size))) {
790  DCHECK(!wrapper.image_data.texture->HasImage(0U));
791  UpdateImageData(grid_map, wrapper.bin_packer, image_size,
792  font.GetSdfPadding(), &wrapper.image_data, sta);
793 
795  image_data.glyph_set = glyph_set;
796 
798  wrapper.packed_area = ComputeTotalGridArea(grid_map);
799  wrapper.used_area_fraction =
800  static_cast<float>(wrapper.packed_area) /
801  static_cast<float>(math::Square(image_size));
802 
803  return index;
804  }
805 
807  wrappers.pop_back();
808  return base::kInvalidIndex;
809 }
810 
811 } // namespace text
812 } // 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
kShortTerm is used for objects that are very transient in nature, such as scratch memory used to comp...
Definition: allocator.h:36
size_t GetSdfPadding() const
Returns the padding value used when generating SDF glyphs from the font.
Definition: font.h:84
base::ReferentPtr< Image >::Type ImagePtr
Definition: image.h:29
#define ION_DECLARE_SAFE_STATIC_POINTER_WITH_CONSTRUCTOR(type, variable, constructor)
Declare a static non-array pointer and calls a non-default constructor.
std::string type
Definition: printer.cc:353
~FontImage() override
The destructor is protected because all base::Referent classes must have protected or private destruc...
Definition: fontimage.cc:450
std::string text
const size_t kInvalidIndex
kInvalidIndex is a size_t value that is very unlikely to be a valid index.
Definition: invalid.cc:23
#define DCHECK(expr)
Definition: logging.h:331
size_t packed_area
Area (in pixels) of the glyphs already packed into the ImageData.
Definition: fontimage.cc:90
const ImageData & FindImageData(const GlyphSet &glyph_set) override
Implements this function to find an existing ImageData that already contains all of the glyphs (prese...
Definition: fontimage.cc:618
#define DCHECK_GT(val1, val2)
Definition: logging.h:337
size_t FindContainingImageDataIndex(const GlyphSet &glyph_set)
Returns the index of an ImageData instance that contains all of the glyphs (present in the Font) in g...
Definition: fontimage.cc:662
virtual const AllocatorPtr & GetAllocatorForLifetime(AllocationLifetime lifetime) const
Returns the correct Allocator to use to allocate memory with a specific lifetime. ...
Definition: allocator.cc:27
const ImageData & GetImageData(size_t index) const
Returns the indexed ImageData instance, or an invalid reference if the index is out of range...
Definition: fontimage.cc:591
Range< 2, float > Range2f
Definition: range.h:373
float used_area_fraction
Fraction of area used.
Definition: fontimage.cc:93
T Sqrt(const T &val)
Returns the square root of a value.
Definition: utils.h:59
SharedPtr< Allocator > AllocatorPtr
Definition: allocator.h:51
A FontImage contains image and texture coordinate information used to render font glyphs...
Definition: fontimage.h:63
base::ReferentPtr< Sampler >::Type SamplerPtr
Convenience typedef for shared pointer to a Sampler.
const AllocatorPtr & GetAllocatorForLifetime(AllocationLifetime lifetime) const
Convenience function that returns the Allocator to use to allocate an object with a specific lifetime...
Definition: allocatable.h:78
void ProcessDeferredUpdates()
Updates internal texture data with any deferred updates.
Definition: fontimage.cc:604
T * Get() const
Returns a raw pointer to the instance, which may be NULL.
Definition: sharedptr.h:89
ImageData(const base::AllocatorPtr &allocator)
FontImage::ImageData functions.
Definition: fontimage.cc:434
A LockGuard locks a mutex when created, and unlocks it when destroyed.
Definition: lockguards.h:90
std::string ValueToString(const T &val)
ValueToString.
Definition: serialize.h:209
base::AllocSet< GlyphIndex > GlyphSet
Definition: layout.h:47
size_t FindImageDataIndex(const GlyphSet &glyph_set)
This is the same as FindImageData(), but instead returns the index of the ImageData, or kInvalidIndex if unsuccessful.
Definition: fontimage.cc:623
static bool GetTextureCoords(const ImageData &image_data, GlyphIndex glyph_index, math::Range2f *rectangle)
Convenience function that sets rectangle to the texture coordinate rectangle to use for the indexed g...
Definition: fontimage.cc:452
size_t GetMaxImageSize()
Returns the maximum image size passed to the constructor.
Definition: fontimage.h:91
const T Clamp(const T &val, const T &min_val, const T &max_val)
Clamps a value to lie between a minimum and maximum, inclusive.
Definition: utils.h:204
float GetImageDataUsedAreaFraction(size_t index) const
Returns the area covered by glyphs in the indexed ImageData, or 0 if the index is out of range...
Definition: fontimage.cc:598
const Grid & image
The original monochrome image data, as doubles (0 - 1).
Definition: sdfutils.cc:90
Copyright 2016 Google Inc.
uint32 NextPowerOf2(uint32 n)
Returns the next power of 2 greater than or equal to n.
Definition: utils.h:124
int width
#define DCHECK_EQ(val1, val2)
Definition: logging.h:332
TexturePtr texture
The Texture to add sub-image data to.
Definition: fontimage.cc:107
#define DCHECK_LE(val1, val2)
Definition: logging.h:334
FontImage(Type type, const FontPtr &font, size_t max_image_size)
The constructor is passed the type of derived class, the Font to use, and the maximum image size (in ...
Definition: fontimage.cc:447
const T Square(const T &val)
Squares a value.
Definition: utils.h:48
void CacheSdfGrids(const GlyphSet &glyph_set)
Makes sure that the GlyphData for each glyph in glyph_set has an SDF grid cached inside the font...
Definition: font.cc:95
base::AllocMap< GlyphIndex, math::Range2f > TexRectMap
Maps glyph index to a texture coordinate rectangle.
Definition: fontimage.h:78
const FontPtr & GetFont()
Returns the Font passed to the constructor.
Definition: fontimage.h:88
BinPacker bin_packer
BinPacker used to pack glyphs into the FontImage.
Definition: fontimage.cc:87
static bool HasAllGlyphs(const ImageData &image_data, const GlyphSet &glyph_set)
Convenience function that returns true if an ImageData instance contains all glyphs in glyph_set...
Definition: fontimage.h:101
A ReadLock obtains a read lock, but has a similar interface to a Mutex and can be used with a ReadGua...
Definition: readwritelock.h:86
const AllocatorPtr & GetAllocator() const
Returns the Allocator that was used for the instance.
Definition: allocatable.h:68
StaticFontImage(const FontPtr &font, size_t max_image_size, const GlyphSet &glyph_set)
The constructor sets up the single ImageData instance to contain glyphs for all the requested glyphs...
Definition: fontimage.cc:473
kLongTerm is used for objects that have persistent lifetimes, such as managers.
Definition: allocator.h:44
const ImageData & FindImageData(const GlyphSet &glyph_sets) override
Implements this function to return the single ImageData instance, whether or not it contains all the ...
Definition: fontimage.cc:490
FontImage::ImageData image_data
The wrapped ImageData instance.
Definition: fontimage.cc:84
DynamicFontImage(const FontPtr &font, size_t image_size)
The constructor sets up the DynamicFontImage to use the Font.
Definition: fontimage.cc:580
uint64 GlyphIndex
Definition: layout.h:46
Data for each image in the FontImage.
Definition: fontimage.h:71
GenericLockGuard< WriteLock > WriteGuard
Definition: lockguards.h:203
size_t GetImageDataCount() const
Returns the current count of ImageData instances.
Definition: fontimage.cc:587
base::ReferentPtr< Texture >::Type TexturePtr
Convenience typedef for shared pointer to a Texture.
Definition: texture.h:333
static const AllocatorPtr & GetDefaultAllocatorForLifetime(AllocationLifetime lifetime)
Font is a base class for implementation-specific representations of fonts.
Definition: font.h:43