25#pragma warning( push )
26#pragma warning( disable: 4459 )
28#include <boost/multi_array.hpp>
104 if (std::holds_alternative<color>(aEffectColor))
105 return std::get<color>(aEffectColor);
106 else if (std::holds_alternative<gradient>(aEffectColor))
107 return std::get<gradient>(aEffectColor);
115 using color_or_gradient::color_or_gradient;
121 using color_or_gradient::operator=;
130 if (std::holds_alternative<color>(*
this))
131 return std::get<color>(*this).alpha();
137 if (std::holds_alternative<color>(*
this))
138 return std::get<color>(*this).
with_alpha(aAlpha);
139 if (std::holds_alternative<gradient>(*
this))
140 return std::get<gradient>(*this).with_combined_alpha(aAlpha);
148 return std::holds_alternative<color>(lhs) && std::get<color>(lhs) == rhs;
153 return std::holds_alternative<color>(rhs) && std::get<color>(rhs) == lhs;
158 return !std::holds_alternative<color>(lhs) || std::get<color>(lhs) != rhs;
163 return !std::holds_alternative<color>(rhs) && std::get<color>(rhs) != lhs;
168 return std::holds_alternative<gradient>(lhs) && std::get<gradient>(lhs) == rhs;
173 return std::holds_alternative<gradient>(rhs) && std::get<gradient>(rhs) == lhs;
178 return !std::holds_alternative<gradient>(lhs) || std::get<gradient>(lhs) != rhs;
183 return !std::holds_alternative<gradient>(rhs) && std::get<gradient>(rhs) != lhs;
209 typedef text_effect abstract_type;
211 typedef double auxiliary_parameter;
212 typedef optional<auxiliary_parameter> optional_auxiliary_parameter;
218 text_effect(text_effect_type aType,
const text_color& aColor,
const optional_dimension& aWidth = {},
const optional_vec3& aOffset = {},
const optional_auxiliary_parameter& aAux1 = {},
bool aIgnoreEmoji =
false) :
219 iType{ aType }, iColor{ aColor }, iWidth{ aWidth }, iAux1{ aAux1 }, iIgnoreEmoji{ aIgnoreEmoji }
223 text_effect& operator=(
const text_effect& aOther)
227 iType = aOther.iType;
228 iColor = aOther.iColor;
229 iWidth = aOther.iWidth;
230 iOffset = aOther.iOffset;
231 iAux1 = aOther.iAux1;
232 iIgnoreEmoji = aOther.iIgnoreEmoji;
236 bool operator==(
const text_effect& that)
const noexcept
238 return std::forward_as_tuple(iType, iColor, iWidth, iOffset, iAux1, iIgnoreEmoji) ==
239 std::forward_as_tuple(that.iType, that.iColor, that.iWidth, that.iOffset, that.iAux1, that.iIgnoreEmoji);
241 auto operator<=>(
const text_effect& that)
const noexcept
243 return std::forward_as_tuple(iType, iColor, iWidth, iOffset, iAux1, iIgnoreEmoji) <=>
244 std::forward_as_tuple(that.iType, that.iColor, that.iWidth, that.iOffset, that.iAux1, that.iIgnoreEmoji);
251 void set_type(text_effect_type aType)
255 text_color
color()
const
261 case text_effect_type::Shadow:
267 void set_color(text_color
const& aColor)
273 if (iWidth != std::nullopt)
277 case text_effect_type::None:
280 case text_effect_type::Outline:
282 case text_effect_type::Glow:
283 case text_effect_type::Shadow:
287 void set_width(optional_dimension
const& aWidth)
293 if (iOffset != std::nullopt)
297 case text_effect_type::None:
300 case text_effect_type::Outline:
301 return { -width(), -width() };
302 case text_effect_type::Glow:
304 case text_effect_type::Shadow:
305 return { std::max(1.0, width() / 2.0), std::max(1.0, width() / 2.0) };
308 void set_offset(vec3
const& aOffset)
314 if (iAux1 != std::nullopt)
318 case text_effect_type::None:
321 case text_effect_type::Outline:
323 case text_effect_type::Glow:
324 case text_effect_type::Shadow:
328 void set_aux1(
double aAux1)
332 bool ignore_emoji()
const
336 void set_ignore_emoji(
bool aIgnore)
338 iIgnoreEmoji = aIgnore;
340 text_effect with_alpha(color::component aAlpha)
const
342 return text_effect{ iType, iColor.with_alpha(aAlpha), iWidth, iOffset, iAux1, iIgnoreEmoji };
344 text_effect with_alpha(
double aAlpha)
const
346 return with_alpha(
static_cast<color::component
>(aAlpha * 255));
353 optional_auxiliary_parameter iAux1;
359 template <
typename Elem,
typename Traits>
360 inline std::basic_ostream<Elem, Traits>&
operator<<(std::basic_ostream<Elem, Traits>& aStream,
const text_effect& aEffect)
363 aStream << aEffect.type();
365 aStream << aEffect.color();
367 aStream << aEffect.width();
369 aStream << aEffect.offset();
371 aStream << aEffect.aux1();
373 aStream << aEffect.ignore_emoji();
378 template <
typename Elem,
typename Traits>
379 inline std::basic_istream<Elem, Traits>&
operator>>(std::basic_istream<Elem, Traits>& aStream, text_effect& aEffect)
381 auto previousImbued = aStream.getloc();
386 aEffect.set_type(type);
389 aEffect.set_color(
color);
392 aEffect.set_width(width);
395 aEffect.set_offset(offset);
398 aEffect.set_aux1(aux1);
400 aStream >> ignoreEmoji;
401 aEffect.set_ignore_emoji(ignoreEmoji);
402 aStream.imbue(previousImbued);
409 struct no_paper : std::logic_error { no_paper() :
std::logic_error(
"neogfx::text_format::no_paper") {} };
410 struct no_effect : std::logic_error { no_effect() :
std::logic_error(
"neogfx::text_format::no_effect") {} };
412 typedef text_format abstract_type;
415 iSmartUnderline{ false },
416 iIgnoreEmoji{ true },
417 iOnlyCalculateEffect{ false },
418 iBeingFiltered{ false }
421 text_format(text_format
const& aOther) :
423 iPaper{ aOther.iPaper },
424 iSmartUnderline{ aOther.iSmartUnderline },
425 iIgnoreEmoji{ aOther.iIgnoreEmoji },
426 iEffect{ aOther.iEffect },
427 iOnlyCalculateEffect{ aOther.iOnlyCalculateEffect },
428 iBeingFiltered{ aOther.iBeingFiltered }
431 template <
typename InkType,
typename PaperType>
432 text_format(InkType
const& aInk, PaperType
const& aPaper, optional_text_effect
const& aEffect) :
435 iSmartUnderline{ false },
436 iIgnoreEmoji{ true },
438 iOnlyCalculateEffect{ false },
439 iBeingFiltered{ false }
442 template <
typename InkType,
typename PaperType>
443 text_format(InkType
const& aInk, PaperType
const& aPaper, text_effect
const& aEffect) :
446 iSmartUnderline{ false },
447 iIgnoreEmoji{ true },
449 iOnlyCalculateEffect{ false },
450 iBeingFiltered{ false }
453 template <
typename InkType>
454 text_format(InkType
const& aInk, optional_text_effect
const& aEffect) :
456 iSmartUnderline{ false },
457 iIgnoreEmoji{ true },
459 iOnlyCalculateEffect{ false },
460 iBeingFiltered{ false }
463 template <
typename InkType>
464 text_format(InkType
const& aInk, text_effect
const& aEffect) :
466 iSmartUnderline{ false },
467 iIgnoreEmoji{ true },
469 iOnlyCalculateEffect{ false },
470 iBeingFiltered{ false }
473 template <
typename InkType,
typename PaperType>
474 text_format(InkType
const& aInk, PaperType
const& aPaper) :
477 iSmartUnderline{ false },
478 iIgnoreEmoji{ true },
479 iOnlyCalculateEffect{ false },
480 iBeingFiltered{ false }
483 template <
typename InkType>
484 text_format(InkType
const& aInk) :
486 iSmartUnderline{ false },
487 iIgnoreEmoji{ true },
488 iOnlyCalculateEffect{ false },
489 iBeingFiltered{ false }
493 bool operator==(text_format
const& aRhs)
const noexcept
495 return std::forward_as_tuple(ink(), paper(), smart_underline(), ignore_emoji(), effect()) ==
496 std::forward_as_tuple(aRhs.ink(), aRhs.paper(), aRhs.smart_underline(), aRhs.ignore_emoji(), aRhs.effect());
498 auto operator<=>(text_format
const& aRhs)
const noexcept
500 return std::forward_as_tuple(ink(), paper(), smart_underline(), ignore_emoji(), effect()) <=>
501 std::forward_as_tuple(aRhs.ink(), aRhs.paper(), aRhs.smart_underline(), aRhs.ignore_emoji(), aRhs.effect());
504 text_color
const& ink()
const
508 void set_ink(text_color
const& aInk)
516 void set_paper(optional_text_color
const& aPaper)
520 bool smart_underline()
const
522 return iSmartUnderline;
524 void set_smart_underline(
bool aSmartUnderline)
526 iSmartUnderline = aSmartUnderline;
528 bool ignore_emoji()
const
532 void set_ignore_emoji(
bool aIgnore)
534 iIgnoreEmoji = aIgnore;
536 optional_text_effect
const& effect()
const
540 optional_text_effect& effect()
544 void set_effect(optional_text_effect
const& aEffect)
548 bool only_calculate_effect()
const
550 return iOnlyCalculateEffect;
552 bool being_filtered()
const
554 return iBeingFiltered;
557 text_format with_ink(text_color
const& aInk)
const
559 return text_format{ aInk, iPaper, iEffect }.with_smart_underline(smart_underline()).with_emoji_ignored(ignore_emoji());
561 text_format with_paper(optional_text_color
const& aPaper)
const
563 return text_format{ iInk, aPaper, iEffect }.with_smart_underline(smart_underline()).with_emoji_ignored(ignore_emoji());
565 text_format with_smart_underline(
bool aSmartUnderline)
const
568 result.set_smart_underline(aSmartUnderline);
571 text_format with_emoji_ignored(
bool aIgnored)
const
574 result.set_ignore_emoji(aIgnored);
577 text_format with_effect(optional_text_effect
const& aEffect)
const
579 return text_format{ iInk, iPaper, aEffect }.with_smart_underline(smart_underline()).with_emoji_ignored(ignore_emoji());
581 text_format with_alpha(color::component aAlpha)
const
584 iInk.with_alpha(aAlpha),
585 iPaper != std::nullopt ?
588 iEffect != std::nullopt ?
589 iEffect->with_alpha(aAlpha) :
590 optional_text_effect{} }.with_smart_underline(smart_underline()).with_emoji_ignored(ignore_emoji());
592 text_format with_alpha(
double aAlpha)
const
594 return with_alpha(
static_cast<color::component
>(aAlpha * 255));
596 text_format with_only_effect_calculation()
const
599 copy.iOnlyCalculateEffect =
true;
602 text_format as_being_filtered()
const
605 copy.iBeingFiltered =
true;
611 bool iSmartUnderline;
613 optional_text_effect iEffect;
614 bool iOnlyCalculateEffect;
620 template <
typename Elem,
typename Traits>
621 inline std::basic_ostream<Elem, Traits>&
operator<<(std::basic_ostream<Elem, Traits>& aStream,
const text_format& aTextFormat)
624 aStream << aTextFormat.ink();
626 aStream << aTextFormat.paper();
628 aStream << aTextFormat.effect();
630 aStream << aTextFormat.smart_underline();
632 aStream << aTextFormat.ignore_emoji();
637 template <
typename Elem,
typename Traits>
638 inline std::basic_istream<Elem, Traits>&
operator>>(std::basic_istream<Elem, Traits>& aStream, text_format& aTextFormat)
640 auto previousImbued = aStream.getloc();
645 aTextFormat.set_ink(ink);
648 aTextFormat.set_paper(temp);
649 optional_text_effect textEffect;
650 aStream >> textEffect;
651 aTextFormat.set_effect(textEffect);
653 aStream >> smartUnderline;
654 aTextFormat.set_smart_underline(smartUnderline);
656 aStream >> ignoreEmoji;
657 aTextFormat.set_ignore_emoji(ignoreEmoji);
658 aStream.imbue(previousImbued);
667 struct text_format_span
669 std::ptrdiff_t start;
671 text_format attributes;
674 class text_format_spans
682 text_format_spans(text_format_span
const& aSpan) :
691 void add(std::ptrdiff_t aGlyphTextIndex, text_format
const& aTextFormat)
693 if (iSpans.empty() || iSpans.back().attributes != aTextFormat)
694 iSpans.emplace_back(aGlyphTextIndex, aGlyphTextIndex + 1, aTextFormat);
696 iSpans.back().end = aGlyphTextIndex + 1;
698 template <
typename... Args>
699 void add(std::ptrdiff_t aGlyphtTextIndex, Args&&... aArgs)
701 text_format
const attributes{ std::forward<Args>(aArgs)... };
702 add(aGlyphtTextIndex, attributes);
705 spans::const_iterator begin()
const
707 return iSpans.begin();
709 spans::const_iterator end()
const
717 class paragraph_format
720 using self_type = paragraph_format;
721 using abstract_type = self_type;
723 paragraph_format() {}
724 paragraph_format(paragraph_format
const& aOther) {}
726 auto operator<=>(self_type
const&)
const =
default;
return_type with_alpha(view_component aAlpha) const
text_color with_alpha(color::component aAlpha) const
text_color(color_or_gradient const &aOther)
text_color & operator=(color_or_gradient const &aOther)
color::component alpha() const
self_type & operator=(T const &aOther)
#define end_declare_enum(enumName)
#define declare_enum_string(enumName, enumEnumerator)
#define begin_declare_enum(enumName)
#define define_setting_type(T)
std::basic_ostream< Elem, Traits > & operator<<(std::basic_ostream< Elem, Traits > &aStream, const basic_point< T > &aPoint)
bool operator!=(color_or_gradient const &lhs, color const &rhs) noexcept
default_geometry_value_type dimension
std::basic_istream< Elem, Traits > & operator>>(std::basic_istream< Elem, Traits > &aStream, basic_point< T > &aPoint)
brush to_brush(const color_or_gradient &aEffectColor)
bool operator==(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
optional< dimension > optional_dimension
neolib::variant< color, gradient, texture, std::pair< texture, rect >, sub_texture, std::pair< sub_texture, rect > > brush
std::partial_ordering operator<=>(const gradient &aLhs, const gradient &aRhs)
neolib::optional< text_color > optional_text_color
optional< vec3 > optional_vec3