28 template <
typename Container,
typename ConstIterator,
typename Iterator>
29 inline const font& basic_glyph_text_content<Container, ConstIterator, Iterator>::font_cache::glyph_font()
const
32 return iCache.begin()->second.second;
33 throw cached_font_not_found();
36 template <
typename Container,
typename ConstIterator,
typename Iterator>
37 inline const font& basic_glyph_text_content<Container, ConstIterator, Iterator>::font_cache::glyph_font(font_id aFontId)
const
39 cache_glyph_font(aFontId);
40 auto existing = iCache.find(aFontId);
41 if (existing != iCache.end())
42 return existing->second.second;
43 throw cached_font_not_found();
46 template <
typename Container,
typename ConstIterator,
typename Iterator>
47 inline const font& basic_glyph_text_content<Container, ConstIterator, Iterator>::font_cache::glyph_font(const_reference aGlyphChar)
const
49 return glyph_font(aGlyphChar.font);
52 template <
typename Container,
typename ConstIterator,
typename Iterator>
53 inline void basic_glyph_text_content<Container, ConstIterator, Iterator>::font_cache::cache_glyph_font(font_id aFontId)
const
55 if (iCache.find(aFontId) == iCache.end())
57 auto& fontService = service<i_font_manager>();
62 template <
typename Container,
typename ConstIterator,
typename Iterator>
63 inline void basic_glyph_text_content<Container, ConstIterator, Iterator>::font_cache::cache_glyph_font(
const font& aFont)
const
65 if (iCache.find(aFont.id()) == iCache.end())
67 auto& fontService = service<i_font_manager>();
68 iCache.emplace(aFont.id(), cache_entry{ neolib::small_cookie_ref_ptr{ fontService, aFont.id() }, aFont });
72 template <
typename Container,
typename ConstIterator,
typename Iterator>
73 inline void basic_glyph_text_content<Container, ConstIterator, Iterator>::font_cache::clear()
78 template <
typename Container,
typename ConstIterator,
typename Iterator>
86 template <
typename Container,
typename ConstIterator,
typename Iterator>
89 iMajorFont{ aFont.
id() },
95 template <
typename Container,
typename ConstIterator,
typename Iterator>
97 container_type{ aOther },
98 iCache{ aOther.iCache },
99 iExtents{ aOther.iExtents },
100 iMajorFont{ aOther.iMajorFont },
101 iBaseline{ aOther.iBaseline }
105 template <
typename Container,
typename ConstIterator,
typename Iterator>
107 container_type{
std::move(aOther) },
108 iCache{
std::move(aOther.iCache) },
109 iExtents{ aOther.iExtents },
110 iMajorFont{ aOther.iMajorFont },
111 iBaseline{ aOther.iBaseline }
115 template <
typename Container,
typename ConstIterator,
typename Iterator>
120 container_type::operator=(aOther);
121 iCache = aOther.iCache;
122 iExtents = aOther.iExtents;
123 iMajorFont = aOther.iMajorFont;
124 iBaseline = aOther.iBaseline;
128 template <
typename Container,
typename ConstIterator,
typename Iterator>
133 container_type::operator=(std::move(aOther));
134 iCache = aOther.iCache;
135 iExtents = aOther.iExtents;
136 iMajorFont = aOther.iMajorFont;
137 iBaseline = aOther.iBaseline;
141 template <
typename Container,
typename ConstIterator,
typename Iterator>
144 aClone = make_ref<self_type>(*
this);
147 template <
typename Container,
typename ConstIterator,
typename Iterator>
150 return container_type::empty();
153 template <
typename Container,
typename ConstIterator,
typename Iterator>
156 return container_type::size();
159 template <
typename Container,
typename ConstIterator,
typename Iterator>
162 if constexpr (std::is_same_v<const_iterator, typename container_type::const_iterator>)
163 return container_type::cbegin();
167 return &*container_type::cbegin();
173 template <
typename Container,
typename ConstIterator,
typename Iterator>
176 if constexpr (std::is_same_v<const_iterator, typename container_type::const_iterator>)
177 return container_type::cend();
187 template <
typename Container,
typename ConstIterator,
typename Iterator>
191 if constexpr (std::is_same_v<iterator, typename container_type::iterator>)
192 return container_type::begin();
196 return &*container_type::begin();
202 template <
typename Container,
typename ConstIterator,
typename Iterator>
206 if constexpr (std::is_same_v<iterator, typename container_type::iterator>)
207 return container_type::end();
217 template <
typename Container,
typename ConstIterator,
typename Iterator>
221 return container_type::back();
224 template <
typename Container,
typename ConstIterator,
typename Iterator>
227 container_type::push_back(aGlyphChar);
231 template <
typename Container,
typename ConstIterator,
typename Iterator>
234 container_type::clear();
239 template <
typename Container,
typename ConstIterator,
typename Iterator>
242 return static_cast<const container_type&
>(*this) ==
static_cast<const container_type&
>(aOther);
245 template <
typename Container,
typename ConstIterator,
typename Iterator>
251 template <
typename Container,
typename ConstIterator,
typename Iterator>
257 template <
typename Container,
typename ConstIterator,
typename Iterator>
261 iExtents = extents(begin(), end());
265 template <
typename Container,
typename ConstIterator,
typename Iterator>
268 return rect{
to_aabb_2d(aGlyphChar.cell.begin(), aGlyphChar.cell.end()) }.extents().ceil();
271 template <
typename Container,
typename ConstIterator,
typename Iterator>
276 auto const& firstGlyph = *aBegin;
277 auto const& lastGlyph = *
std::prev(aEnd);
282 firstGlyph.cell[3] };
283 rect const boundingRect{
to_aabb_2d(quadExtents.begin(), quadExtents.end()) };
284 return boundingRect.extents().ceil();
287 template <
typename Container,
typename ConstIterator,
typename Iterator>
293 template <
typename Container,
typename ConstIterator,
typename Iterator>
296 auto result = align_baselines(begin(), end());
297 iMajorFont = result.majorFont;
298 iBaseline = result.baseline;
302 template <
typename Container,
typename ConstIterator,
typename Iterator>
305 align_baselines_result result = {};
310 for (
auto const& g : std::ranges::subrange(aBegin, aEnd))
312 auto const& gf = glyph_font(g);
314 result.yExtent = std::max(result.yExtent, existingExtents.y);
315 float cy = existingExtents.y +
static_cast<float>(gf.descender());
319 result.majorFont = gf.id();
320 result.baseline = cyMax;
322 yMax = std::max(yMax, existingExtents.y);
327 result.majorFont = major_font().id();
328 result.yExtent =
static_cast<float>(major_font().height());
332 for (
auto& g : std::ranges::subrange(aBegin, aEnd))
334 auto const& gf = glyph_font(g);
336 g.shape +=
vec2f{ 0.0f, cyMax - (existingExtents.y +
static_cast<float>(gf.descender())) };
337 g.cell[2].y = g.cell[1].y + yMax;
338 g.cell[3].y = g.cell[0].y + yMax;
341 scalar const ascender = gf.ascender();
342 scalar const descender = gf.descender();
343 scalar const cy = ascender - descender;
344 scalar const dyLarge = cy / 0.58 * 0.33;
345 scalar const dySmall = dyLarge * 0.5;
348 auto const belowAscenderDelta =
static_cast<float>(dySmall);
349 auto const aboveAscenderDelta =
static_cast<float>(dyLarge);
351 g.shape -=
vec2f{ 0.0f, std::ceil(belowAscenderDelta) };
353 g.shape -=
vec2f{ 0.0f, std::ceil(aboveAscenderDelta) };
357 auto const aboveBaselineDelta = 0.0f;
358 auto const belowBaselineDelta =
static_cast<float>(dyLarge + descender / 0.58);
360 g.shape +=
vec2f{ 0.0f, aboveBaselineDelta };
362 g.shape +=
vec2f{ 0.0f, belowBaselineDelta };
369 template <
typename Container,
typename ConstIterator,
typename Iterator>
372 std::pair<const_iterator, const_iterator> result(aFrom, aFrom);
375 while (result.first != aBegin && !
is_whitespace(*result.first))
379 result.first = aFrom;
380 while (result.first != aBegin && (result.first - 1)->clusters == aFrom->clusters)
382 result.second = result.first;
385 result.second = result.first;
387 while (result.first != aBegin &&
is_whitespace(*(result.first - 1)))
389 while (
is_whitespace(*result.second) && result.second != end())
394 template <
typename Container,
typename ConstIterator,
typename Iterator>
401 template <
typename Container,
typename ConstIterator,
typename Iterator>
407 template <
typename Container,
typename ConstIterator,
typename Iterator>
413 template <
typename Container,
typename ConstIterator,
typename Iterator>
416 return iCache.glyph_font();
419 template <
typename Container,
typename ConstIterator,
typename Iterator>
422 return iCache.glyph_font(aGlyphChar);
425 template <
typename Container,
typename ConstIterator,
typename Iterator>
428 iCache.cache_glyph_font(aFontId);
431 template <
typename Container,
typename ConstIterator,
typename Iterator>
434 iCache.cache_glyph_font(aFont);
437 template <
typename Container,
typename ConstIterator,
typename Iterator>
440 return glyph_font(aGlyphChar).glyph(aGlyphChar);
443 template <
typename Container,
typename ConstIterator,
typename Iterator>
446 iMajorFont = aFont.id();
449 template <
typename Container,
typename ConstIterator,
typename Iterator>
452 return iCache.glyph_font(iMajorFont);
455 template <
typename Container,
typename ConstIterator,
typename Iterator>
461 template <
typename Container,
typename ConstIterator,
typename Iterator>
464 iBaseline = aBaseline;
const_iterator cend() const override
self_type & operator=(const self_type &aOther)
ConstIterator const_iterator
self_type & align_baselines() override
basic_glyph_text_content()
void set_major_font(const font &aFont) override
const i_glyph & glyph(const_reference aGlyphChar) const override
void cache_glyph_font(font_id aFontId) const override
std::pair< const_iterator, const_iterator > word_break(const_iterator aBegin, const_iterator aFrom) const override
void push_back(const_reference aGlyphChar) override
void set_extents(const neogfx::size &aExtents) override
vector< size_type > const & line_breaks() const override
const_iterator cbegin() const override
iterator begin() override
size_type size() const override
const font & glyph_font() const override
bool operator==(const self_type &aOther) const
scalar baseline() const override
void clone(i_ref_ptr< abstract_type > &aClone) const override
neogfx::size extents() const override
bool empty() const override
const font & major_font() const override
container_type const & container() const
void set_baseline(scalar aBaseline) override
bool is_whitespace(glyph_char const &g)
std::array< vec2, 4 > quad_2d
basic_vector< T, D > quad_extents(std::array< basic_vector< T, D >, 4 > const &aQuad)
aabb_2d to_aabb_2d(const vec3 &aOrigin, scalar aSize)
basic_cookie_ref_ptr< small_cookie > small_cookie_ref_ptr
it_type next(it_type it, const typename iterator_traits< it_type >::difference_type distance=1)
iterator_traits< it_type >::difference_type distance(const it_type first, const it_type last)
it_type prev(it_type it, const typename iterator_traits< it_type >::difference_type distance=1)