diff --git a/src/Magnum/Text/AbstractShaper.cpp b/src/Magnum/Text/AbstractShaper.cpp index 9c11276a2..e50160194 100644 --- a/src/Magnum/Text/AbstractShaper.cpp +++ b/src/Magnum/Text/AbstractShaper.cpp @@ -29,6 +29,7 @@ #include #include "Magnum/Text/Direction.h" +#include "Magnum/Text/Feature.h" #include "Magnum/Text/Script.h" namespace Magnum { namespace Text { diff --git a/src/Magnum/Text/AbstractShaper.h b/src/Magnum/Text/AbstractShaper.h index 3de26838e..dfdc9cb23 100644 --- a/src/Magnum/Text/AbstractShaper.h +++ b/src/Magnum/Text/AbstractShaper.h @@ -26,7 +26,7 @@ */ /** @file - * @brief Class @ref Magnum::Text::AbstractShaper, @ref Magnum::Text::FeatureRange + * @brief Class @ref Magnum::Text::AbstractShaper * @m_since_latest */ @@ -39,69 +39,6 @@ namespace Magnum { namespace Text { -/** -@brief OpenType feature for a text range -@m_since_latest - -@see @ref AbstractShaper::shape() -*/ -class FeatureRange { - public: - /** - * @brief Constructor - * @param feature Feature to control - * @param begin Beginning byte in the input text - * @param end (One byte after) the end byte in the input text - * @param value Feature value to set - */ - constexpr /*implicit*/ FeatureRange(Feature feature, UnsignedInt begin, UnsignedInt end, UnsignedInt value = true): _feature{feature}, _value{value}, _begin{begin}, _end{end} {} - - /** - * @brief Construct for the whole text - * - * Equivalent to calling @ref FeatureRange(Feature, UnsignedInt, UnsignedInt, UnsignedInt) - * with @p begin set to @cpp 0 @ce and @p end to @cpp 0xffffffffu @ce. - */ - constexpr /*implicit*/ FeatureRange(Feature feature, UnsignedInt value = true): _feature{feature}, _value{value}, _begin{0}, _end{~UnsignedInt{}} {} - - /** @brief Feature to control */ - constexpr Feature feature() const { return _feature; } - - /** - * @brief Whether to enable the feature - * - * Returns @cpp false @ce if @ref value() is @cpp 0 @ce, @cpp true @ce - * otherwise. - */ - constexpr bool isEnabled() const { return _value; } - - /** @brief Feature value to set */ - constexpr UnsignedInt value() const { return _value; } - - /** - * @brief Beginning byte in the input text - * - * If the feature is set for the whole text, this is @cpp 0 @ce. - */ - constexpr UnsignedInt begin() const { return _begin; } - - /** - * @brief (One byte after) the end byte in the input text - * - * If the feature is set for the whole text, this is - * @cpp 0xffffffffu @ce. - */ - constexpr UnsignedInt end() const { return _end; } - - private: - friend AbstractShaper; - - Feature _feature; - UnsignedInt _value; - UnsignedInt _begin; - UnsignedInt _end; -}; - /** @brief Base for text shapers @m_since_latest diff --git a/src/Magnum/Text/Feature.h b/src/Magnum/Text/Feature.h index af3a8c2f3..b2d94ff19 100644 --- a/src/Magnum/Text/Feature.h +++ b/src/Magnum/Text/Feature.h @@ -26,17 +26,81 @@ */ /** @file - * @brief Enum @ref Magnum::Text::Feature, function @ref Magnum::Text::feature() + * @brief Class @ref Magnum::Text::FeatureRange, enum @ref Magnum::Text::Feature, function @ref Magnum::Text::feature() * @m_since_latest */ #include #include "Magnum/Magnum.h" +#include "Magnum/Text/Text.h" #include "Magnum/Text/visibility.h" namespace Magnum { namespace Text { +/** +@brief OpenType feature for a text range +@m_since_latest + +@see @ref AbstractShaper::shape() +*/ +class FeatureRange { + public: + /** + * @brief Constructor + * @param feature Feature to control + * @param begin Beginning byte in the input text + * @param end (One byte after) the end byte in the input text + * @param value Feature value to set + */ + constexpr /*implicit*/ FeatureRange(Feature feature, UnsignedInt begin, UnsignedInt end, UnsignedInt value = true): _feature{feature}, _value{value}, _begin{begin}, _end{end} {} + + /** + * @brief Construct for the whole text + * + * Equivalent to calling @ref FeatureRange(Feature, UnsignedInt, UnsignedInt, UnsignedInt) + * with @p begin set to @cpp 0 @ce and @p end to @cpp 0xffffffffu @ce. + */ + constexpr /*implicit*/ FeatureRange(Feature feature, UnsignedInt value = true): _feature{feature}, _value{value}, _begin{0}, _end{~UnsignedInt{}} {} + + /** @brief Feature to control */ + constexpr Feature feature() const { return _feature; } + + /** + * @brief Whether to enable the feature + * + * Returns @cpp false @ce if @ref value() is @cpp 0 @ce, @cpp true @ce + * otherwise. + */ + constexpr bool isEnabled() const { return _value; } + + /** @brief Feature value to set */ + constexpr UnsignedInt value() const { return _value; } + + /** + * @brief Beginning byte in the input text + * + * If the feature is set for the whole text, this is @cpp 0 @ce. + */ + constexpr UnsignedInt begin() const { return _begin; } + + /** + * @brief (One byte after) the end byte in the input text + * + * If the feature is set for the whole text, this is + * @cpp 0xffffffffu @ce. + */ + constexpr UnsignedInt end() const { return _end; } + + private: + friend AbstractShaper; + + Feature _feature; + UnsignedInt _value; + UnsignedInt _begin; + UnsignedInt _end; +}; + /** @brief OpenType typographic feature @m_since_latest diff --git a/src/Magnum/Text/Test/AbstractShaperTest.cpp b/src/Magnum/Text/Test/AbstractShaperTest.cpp index 2d353254e..e582f9eb7 100644 --- a/src/Magnum/Text/Test/AbstractShaperTest.cpp +++ b/src/Magnum/Text/Test/AbstractShaperTest.cpp @@ -42,9 +42,6 @@ namespace Magnum { namespace Text { namespace Test { namespace { struct AbstractShaperTest: TestSuite::Tester { explicit AbstractShaperTest(); - void featureRangeConstruct(); - void featureRangeConstructBeginEnd(); - void construct(); void constructCopy(); void constructMove(); @@ -72,10 +69,7 @@ struct AbstractShaperTest: TestSuite::Tester { }; AbstractShaperTest::AbstractShaperTest() { - addTests({&AbstractShaperTest::featureRangeConstruct, - &AbstractShaperTest::featureRangeConstructBeginEnd, - - &AbstractShaperTest::construct, + addTests({&AbstractShaperTest::construct, &AbstractShaperTest::constructCopy, &AbstractShaperTest::constructMove, @@ -100,82 +94,6 @@ AbstractShaperTest::AbstractShaperTest() { &AbstractShaperTest::glyphsIntoInvalidViewSizes}); } -void AbstractShaperTest::featureRangeConstruct() { - FeatureRange a{Feature::Kerning}; - FeatureRange b{Feature::StandardLigatures, false}; - FeatureRange c{Feature::AccessAllAlternates, 13}; - CORRADE_COMPARE(a.feature(), Feature::Kerning); - CORRADE_COMPARE(b.feature(), Feature::StandardLigatures); - CORRADE_COMPARE(c.feature(), Feature::AccessAllAlternates); - CORRADE_VERIFY(a.isEnabled()); - CORRADE_VERIFY(!b.isEnabled()); - CORRADE_COMPARE(a.value(), 1); - CORRADE_COMPARE(b.value(), 0); - CORRADE_COMPARE(c.value(), 13); - CORRADE_COMPARE(a.begin(), 0); - CORRADE_COMPARE(b.begin(), 0); - CORRADE_COMPARE(c.begin(), 0); - CORRADE_COMPARE(a.end(), ~UnsignedInt{}); - CORRADE_COMPARE(b.end(), ~UnsignedInt{}); - CORRADE_COMPARE(c.end(), ~UnsignedInt{}); - - constexpr FeatureRange ca{Feature::Kerning}; - constexpr FeatureRange cb{Feature::StandardLigatures, false}; - constexpr FeatureRange cc{Feature::AccessAllAlternates, 13}; - CORRADE_COMPARE(ca.feature(), Feature::Kerning); - CORRADE_COMPARE(cb.feature(), Feature::StandardLigatures); - CORRADE_COMPARE(cc.feature(), Feature::AccessAllAlternates); - CORRADE_VERIFY(ca.isEnabled()); - CORRADE_VERIFY(!cb.isEnabled()); - CORRADE_COMPARE(ca.value(), 1); - CORRADE_COMPARE(cb.value(), 0); - CORRADE_COMPARE(cc.value(), 13); - CORRADE_COMPARE(ca.begin(), 0); - CORRADE_COMPARE(cb.begin(), 0); - CORRADE_COMPARE(cc.begin(), 0); - CORRADE_COMPARE(ca.end(), ~UnsignedInt{}); - CORRADE_COMPARE(cb.end(), ~UnsignedInt{}); - CORRADE_COMPARE(cc.end(), ~UnsignedInt{}); -} - -void AbstractShaperTest::featureRangeConstructBeginEnd() { - FeatureRange a{Feature::Kerning, 7, 26}; - FeatureRange b{Feature::StandardLigatures, 7, 26, false}; - FeatureRange c{Feature::AccessAllAlternates, 7, 26, 13}; - CORRADE_COMPARE(a.feature(), Feature::Kerning); - CORRADE_COMPARE(b.feature(), Feature::StandardLigatures); - CORRADE_COMPARE(c.feature(), Feature::AccessAllAlternates); - CORRADE_VERIFY(a.isEnabled()); - CORRADE_VERIFY(!b.isEnabled()); - CORRADE_COMPARE(a.value(), 1); - CORRADE_COMPARE(b.value(), 0); - CORRADE_COMPARE(c.value(), 13); - CORRADE_COMPARE(a.begin(), 7); - CORRADE_COMPARE(b.begin(), 7); - CORRADE_COMPARE(c.begin(), 7); - CORRADE_COMPARE(a.end(), 26); - CORRADE_COMPARE(b.end(), 26); - CORRADE_COMPARE(c.end(), 26); - - constexpr FeatureRange ca{Feature::Kerning, 7, 26}; - constexpr FeatureRange cb{Feature::StandardLigatures, 7, 26, false}; - constexpr FeatureRange cc{Feature::AccessAllAlternates, 7, 26, 13}; - CORRADE_COMPARE(ca.feature(), Feature::Kerning); - CORRADE_COMPARE(cb.feature(), Feature::StandardLigatures); - CORRADE_COMPARE(cc.feature(), Feature::AccessAllAlternates); - CORRADE_VERIFY(ca.isEnabled()); - CORRADE_VERIFY(!cb.isEnabled()); - CORRADE_COMPARE(ca.value(), 1); - CORRADE_COMPARE(cb.value(), 0); - CORRADE_COMPARE(cc.value(), 13); - CORRADE_COMPARE(ca.begin(), 7); - CORRADE_COMPARE(cb.begin(), 7); - CORRADE_COMPARE(cc.begin(), 7); - CORRADE_COMPARE(ca.end(), 26); - CORRADE_COMPARE(cb.end(), 26); - CORRADE_COMPARE(cc.end(), 26); -} - AbstractFont& FakeFont = *reinterpret_cast(std::size_t{0xdeadbeef}); struct DummyShaper: AbstractShaper { diff --git a/src/Magnum/Text/Test/FeatureTest.cpp b/src/Magnum/Text/Test/FeatureTest.cpp index d8b700d4e..9fe429ef3 100644 --- a/src/Magnum/Text/Test/FeatureTest.cpp +++ b/src/Magnum/Text/Test/FeatureTest.cpp @@ -35,6 +35,9 @@ namespace Magnum { namespace Text { namespace Test { namespace { struct FeatureTest: TestSuite::Tester { explicit FeatureTest(); + void rangeConstruct(); + void rangeConstructBeginEnd(); + void debug(); void fromFourCC(); @@ -43,13 +46,92 @@ struct FeatureTest: TestSuite::Tester { }; FeatureTest::FeatureTest() { - addTests({&FeatureTest::debug, + addTests({&FeatureTest::rangeConstruct, + &FeatureTest::rangeConstructBeginEnd, + + &FeatureTest::debug, &FeatureTest::fromFourCC, &FeatureTest::fromString, &FeatureTest::fromStringInvalid}); } +void FeatureTest::rangeConstruct() { + FeatureRange a{Feature::Kerning}; + FeatureRange b{Feature::StandardLigatures, false}; + FeatureRange c{Feature::AccessAllAlternates, 13}; + CORRADE_COMPARE(a.feature(), Feature::Kerning); + CORRADE_COMPARE(b.feature(), Feature::StandardLigatures); + CORRADE_COMPARE(c.feature(), Feature::AccessAllAlternates); + CORRADE_VERIFY(a.isEnabled()); + CORRADE_VERIFY(!b.isEnabled()); + CORRADE_COMPARE(a.value(), 1); + CORRADE_COMPARE(b.value(), 0); + CORRADE_COMPARE(c.value(), 13); + CORRADE_COMPARE(a.begin(), 0); + CORRADE_COMPARE(b.begin(), 0); + CORRADE_COMPARE(c.begin(), 0); + CORRADE_COMPARE(a.end(), ~UnsignedInt{}); + CORRADE_COMPARE(b.end(), ~UnsignedInt{}); + CORRADE_COMPARE(c.end(), ~UnsignedInt{}); + + constexpr FeatureRange ca{Feature::Kerning}; + constexpr FeatureRange cb{Feature::StandardLigatures, false}; + constexpr FeatureRange cc{Feature::AccessAllAlternates, 13}; + CORRADE_COMPARE(ca.feature(), Feature::Kerning); + CORRADE_COMPARE(cb.feature(), Feature::StandardLigatures); + CORRADE_COMPARE(cc.feature(), Feature::AccessAllAlternates); + CORRADE_VERIFY(ca.isEnabled()); + CORRADE_VERIFY(!cb.isEnabled()); + CORRADE_COMPARE(ca.value(), 1); + CORRADE_COMPARE(cb.value(), 0); + CORRADE_COMPARE(cc.value(), 13); + CORRADE_COMPARE(ca.begin(), 0); + CORRADE_COMPARE(cb.begin(), 0); + CORRADE_COMPARE(cc.begin(), 0); + CORRADE_COMPARE(ca.end(), ~UnsignedInt{}); + CORRADE_COMPARE(cb.end(), ~UnsignedInt{}); + CORRADE_COMPARE(cc.end(), ~UnsignedInt{}); +} + +void FeatureTest::rangeConstructBeginEnd() { + FeatureRange a{Feature::Kerning, 7, 26}; + FeatureRange b{Feature::StandardLigatures, 7, 26, false}; + FeatureRange c{Feature::AccessAllAlternates, 7, 26, 13}; + CORRADE_COMPARE(a.feature(), Feature::Kerning); + CORRADE_COMPARE(b.feature(), Feature::StandardLigatures); + CORRADE_COMPARE(c.feature(), Feature::AccessAllAlternates); + CORRADE_VERIFY(a.isEnabled()); + CORRADE_VERIFY(!b.isEnabled()); + CORRADE_COMPARE(a.value(), 1); + CORRADE_COMPARE(b.value(), 0); + CORRADE_COMPARE(c.value(), 13); + CORRADE_COMPARE(a.begin(), 7); + CORRADE_COMPARE(b.begin(), 7); + CORRADE_COMPARE(c.begin(), 7); + CORRADE_COMPARE(a.end(), 26); + CORRADE_COMPARE(b.end(), 26); + CORRADE_COMPARE(c.end(), 26); + + constexpr FeatureRange ca{Feature::Kerning, 7, 26}; + constexpr FeatureRange cb{Feature::StandardLigatures, 7, 26, false}; + constexpr FeatureRange cc{Feature::AccessAllAlternates, 7, 26, 13}; + CORRADE_COMPARE(ca.feature(), Feature::Kerning); + CORRADE_COMPARE(cb.feature(), Feature::StandardLigatures); + CORRADE_COMPARE(cc.feature(), Feature::AccessAllAlternates); + CORRADE_VERIFY(ca.isEnabled()); + CORRADE_VERIFY(!cb.isEnabled()); + CORRADE_COMPARE(ca.value(), 1); + CORRADE_COMPARE(cb.value(), 0); + CORRADE_COMPARE(cc.value(), 13); + CORRADE_COMPARE(ca.begin(), 7); + CORRADE_COMPARE(cb.begin(), 7); + CORRADE_COMPARE(cc.begin(), 7); + CORRADE_COMPARE(ca.end(), 26); + CORRADE_COMPARE(cb.end(), 26); + CORRADE_COMPARE(cc.end(), 26); +} + void FeatureTest::debug() { std::ostringstream out; Debug{&out} << Feature::StandardLigatures << Text::feature('m', 'a', '\xab', 'g');