Browse Source

Text: introduce font ascent and descent.

It required some ABI-incompatible changes so I bumped the font and
font converter plugin interface strings to avoid crashes at runtime.
pull/183/head^2
Vladimír Vondruš 10 years ago
parent
commit
66e17608e6
  1. 30
      src/Magnum/Text/AbstractFont.cpp
  2. 83
      src/Magnum/Text/AbstractFont.h
  3. 4
      src/Magnum/Text/AbstractFontConverter.h
  4. 2
      src/Magnum/Text/Test/AbstractFontTest.cpp
  5. 6
      src/Magnum/Text/Test/RendererGLTest.cpp
  6. 11
      src/MagnumPlugins/MagnumFont/MagnumFont.cpp
  7. 6
      src/MagnumPlugins/MagnumFont/MagnumFont.h
  8. 2
      src/MagnumPlugins/MagnumFont/Test/MagnumFontGLTest.cpp
  9. 2
      src/MagnumPlugins/MagnumFont/Test/font.conf
  10. 2
      src/MagnumPlugins/MagnumFont/pluginRegistration.cpp
  11. 2
      src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp
  12. 4
      src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp
  13. 2
      src/MagnumPlugins/MagnumFontConverter/pluginRegistration.cpp

30
src/Magnum/Text/AbstractFont.cpp

@ -45,12 +45,16 @@ bool AbstractFont::openData(const std::vector<std::pair<std::string, Containers:
"Text::AbstractFont::openData(): no data passed", false); "Text::AbstractFont::openData(): no data passed", false);
close(); close();
std::tie(_size, _lineHeight) = doOpenData(data, size); const Metrics metrics = doOpenData(data, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f)); _size = metrics.size;
_ascent = metrics.ascent;
_descent = metrics.descent;
_lineHeight = metrics.lineHeight;
CORRADE_INTERNAL_ASSERT(isOpened() || (!_size && !_ascent && !_descent && !_lineHeight));
return isOpened(); return isOpened();
} }
std::pair<Float, Float> AbstractFont::doOpenData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, const Float size) { auto AbstractFont::doOpenData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, const Float size) -> Metrics {
CORRADE_ASSERT(!(features() & Feature::MultiFile), CORRADE_ASSERT(!(features() & Feature::MultiFile),
"Text::AbstractFont::openData(): feature advertised but not implemented", {}); "Text::AbstractFont::openData(): feature advertised but not implemented", {});
CORRADE_ASSERT(data.size() == 1, CORRADE_ASSERT(data.size() == 1,
@ -67,24 +71,32 @@ bool AbstractFont::openSingleData(const Containers::ArrayView<const char> data,
"Text::AbstractFont::openSingleData(): the format is not single-file", false); "Text::AbstractFont::openSingleData(): the format is not single-file", false);
close(); close();
std::tie(_size, _lineHeight) = doOpenSingleData(data, size); const Metrics metrics = doOpenSingleData(data, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f)); _size = metrics.size;
_ascent = metrics.ascent;
_descent = metrics.descent;
_lineHeight = metrics.lineHeight;
CORRADE_INTERNAL_ASSERT(isOpened() || (!_size && !_ascent && !_descent && !_lineHeight));
return isOpened(); return isOpened();
} }
std::pair<Float, Float> AbstractFont::doOpenSingleData(Containers::ArrayView<const char>, Float) { auto AbstractFont::doOpenSingleData(Containers::ArrayView<const char>, Float) -> Metrics {
CORRADE_ASSERT(false, "Text::AbstractFont::openSingleData(): feature advertised but not implemented", {}); CORRADE_ASSERT(false, "Text::AbstractFont::openSingleData(): feature advertised but not implemented", {});
return {}; return {};
} }
bool AbstractFont::openFile(const std::string& filename, const Float size) { bool AbstractFont::openFile(const std::string& filename, const Float size) {
close(); close();
std::tie(_size, _lineHeight) = doOpenFile(filename, size); const Metrics metrics = doOpenFile(filename, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f)); _size = metrics.size;
_ascent = metrics.ascent;
_descent = metrics.descent;
_lineHeight = metrics.lineHeight;
CORRADE_INTERNAL_ASSERT(isOpened() || (!_size && !_ascent && !_descent && !_lineHeight));
return isOpened(); return isOpened();
} }
std::pair<Float, Float> AbstractFont::doOpenFile(const std::string& filename, const Float size) { auto AbstractFont::doOpenFile(const std::string& filename, const Float size) -> Metrics {
CORRADE_ASSERT(features() & Feature::OpenData && !(features() & Feature::MultiFile), CORRADE_ASSERT(features() & Feature::OpenData && !(features() & Feature::MultiFile),
"Text::AbstractFont::openFile(): not implemented", {}); "Text::AbstractFont::openFile(): not implemented", {});

83
src/Magnum/Text/AbstractFont.h

@ -72,10 +72,10 @@ checked by the implementation:
- All `do*()` implementations working on opened file are called only if - All `do*()` implementations working on opened file are called only if
there is any file opened. there is any file opened.
Plugin interface string is `"cz.mosra.magnum.Text.AbstractFont/0.2.3"`. Plugin interface string is `"cz.mosra.magnum.Text.AbstractFont/0.2.4"`.
*/ */
class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin { class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.3") CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.4")
public: public:
/** /**
@ -158,16 +158,33 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
/** /**
* @brief Font size * @brief Font size
* *
* Returns scale in which @ref lineHeight() and @ref glyphAdvance() is * Returns scale in which @ref lineHeight(), @ref ascent(),
* returned. * @ref descent() and @ref glyphAdvance() is returned.
*/ */
Float size() const { return _size; } Float size() const { return _size; }
/**
* @brief Font ascent
*
* Distance from baseline to top, scaled to font size. Positive value.
* @see @ref size(), @ref descent(), @ref lineHeight()
*/
Float ascent() const { return _ascent; }
/**
* @brief Font descent
*
* Distance from baseline to bottom, scalled to font size. Negative
* value.
* @see @ref size(), @ref ascent(), @ref lineHeight()
*/
Float descent() const { return _descent; }
/** /**
* @brief Line height * @brief Line height
* *
* Returns line height scaled to font size. * Returns line height scaled to font size.
* @see @ref size() * @see @ref size(), @ref ascent(), @ref descent()
*/ */
Float lineHeight() const { return _lineHeight; } Float lineHeight() const { return _lineHeight; }
@ -225,6 +242,38 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
*/ */
std::unique_ptr<AbstractLayouter> layout(const GlyphCache& cache, Float size, const std::string& text); std::unique_ptr<AbstractLayouter> layout(const GlyphCache& cache, Float size, const std::string& text);
protected:
/**
* @brief Font metrics
*
* @see @ref doOpenFile(), @ref doOpenData(), @ref doOpenSingleData()
*/
struct Metrics {
/**
* Font size
* @see @ref size()
*/
Float size;
/**
* Font ascent
* @see @ref ascent()
*/
Float ascent;
/**
* Font descent
* @see @ref descent()
*/
Float descent;
/**
* Line height
* @see @ref lineHeight()
*/
Float lineHeight;
};
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
protected: protected:
#else #else
@ -239,29 +288,29 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
/** /**
* @brief Implementation for @ref openData() * @brief Implementation for @ref openData()
* *
* Return size and line height of opened font on successful opening, * Return metrics of opened font on successful opening, zeros
* zeros otherwise. If the plugin doesn't have @ref Feature::MultiFile, * otherwise. If the plugin doesn't have @ref Feature::MultiFile,
* default implementation calls @ref doOpenSingleData(). * default implementation calls @ref doOpenSingleData().
*/ */
virtual std::pair<Float, Float> doOpenData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, Float size); virtual Metrics doOpenData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, Float size);
/** /**
* @brief Implementation for @ref openSingleData() * @brief Implementation for @ref openSingleData()
* *
* Return size and line height of opened font on successful opening, * Return metrics of opened font on successful opening, zeros
* zeros otherwise. * otherwise.
*/ */
virtual std::pair<Float, Float> doOpenSingleData(Containers::ArrayView<const char> data, Float size); virtual Metrics doOpenSingleData(Containers::ArrayView<const char> data, Float size);
/** /**
* @brief Implementation for @ref openFile() * @brief Implementation for @ref openFile()
* *
* Return size and line height of opened font on successful opening, * Return metrics of opened font on successful opening, zeros
* zeros otherwise. If @ref Feature::OpenData is supported and the * otherwise. If @ref Feature::OpenData is supported and the plugin
* plugin doesn't have @ref Feature::MultiFile, default implementation * doesn't have @ref Feature::MultiFile, default implementation opens
* opens the file and calls @ref doOpenSingleData() with its contents. * the file and calls @ref doOpenSingleData() with its contents.
*/ */
virtual std::pair<Float, Float> doOpenFile(const std::string& filename, Float size); virtual Metrics doOpenFile(const std::string& filename, Float size);
/** @brief Implementation for @ref close() */ /** @brief Implementation for @ref close() */
virtual void doClose() = 0; virtual void doClose() = 0;
@ -289,7 +338,7 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
private: private:
#endif #endif
Float _size, _lineHeight; Float _size, _ascent, _descent, _lineHeight;
}; };
CORRADE_ENUMSET_OPERATORS(AbstractFont::Features) CORRADE_ENUMSET_OPERATORS(AbstractFont::Features)

4
src/Magnum/Text/AbstractFontConverter.h

@ -68,10 +68,10 @@ checked by the implementation:
- Function `doImport*FromData()` is called only if there is at least one data - Function `doImport*FromData()` is called only if there is at least one data
array passed. array passed.
Plugin interface string is `"cz.mosra.magnum.Text.AbstractFontConverter/0.1.1"`. Plugin interface string is `"cz.mosra.magnum.Text.AbstractFontConverter/0.1.2"`.
*/ */
class MAGNUM_TEXT_EXPORT AbstractFontConverter: public PluginManager::AbstractPlugin { class MAGNUM_TEXT_EXPORT AbstractFontConverter: public PluginManager::AbstractPlugin {
CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFontConverter/0.1.1") CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFontConverter/0.1.2")
public: public:
/** /**

2
src/Magnum/Text/Test/AbstractFontTest.cpp

@ -56,7 +56,7 @@ class SingleDataFont: public Text::AbstractFont {
bool doIsOpened() const override { return opened; } bool doIsOpened() const override { return opened; }
void doClose() override {} void doClose() override {}
std::pair<Float, Float> doOpenSingleData(const Containers::ArrayView<const char> data, Float) override { Metrics doOpenSingleData(const Containers::ArrayView<const char> data, Float) override {
opened = (data.size() == 1 && data[0] == '\xa5'); opened = (data.size() == 1 && data[0] == '\xa5');
return {}; return {};
} }

6
src/Magnum/Text/Test/RendererGLTest.cpp

@ -344,9 +344,9 @@ void RendererGLTest::multiline() {
bool doIsOpened() const override { return _opened; } bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; } void doClose() override { _opened = false; }
std::pair<Float, Float> doOpenFile(const std::string&, Float) override { Metrics doOpenFile(const std::string&, Float) override {
_opened = true; _opened = true;
return {0.5f, 0.75f}; return {0.5f, 0.45f, -0.25f, 0.75f};
} }
UnsignedInt doGlyphId(char32_t) override { return 0; } UnsignedInt doGlyphId(char32_t) override { return 0; }
@ -370,6 +370,8 @@ void RendererGLTest::multiline() {
/* We're rendering text at 2.0f size and the font is scaled to 0.3f, so the /* We're rendering text at 2.0f size and the font is scaled to 0.3f, so the
line advance should be 0.75f*2.0f/0.5f = 3.0f */ line advance should be 0.75f*2.0f/0.5f = 3.0f */
CORRADE_COMPARE(font.size(), 0.5f); CORRADE_COMPARE(font.size(), 0.5f);
CORRADE_COMPARE(font.ascent(), 0.45f);
CORRADE_COMPARE(font.descent(), -0.25f);
CORRADE_COMPARE(font.lineHeight(), 0.75f); CORRADE_COMPARE(font.lineHeight(), 0.75f);
/* Bounds */ /* Bounds */

11
src/MagnumPlugins/MagnumFont/MagnumFont.cpp

@ -68,7 +68,7 @@ auto MagnumFont::doFeatures() const -> Features { return Feature::OpenData|Featu
bool MagnumFont::doIsOpened() const { return _opened; } bool MagnumFont::doIsOpened() const { return _opened; }
std::pair<Float, Float> MagnumFont::doOpenData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, const Float) { auto MagnumFont::doOpenData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, const Float) -> Metrics {
/* We need just the configuration file and image file */ /* We need just the configuration file and image file */
if(data.size() != 2) { if(data.size() != 2) {
Error() << "Text::MagnumFont::openData(): wanted two files, got" << data.size(); Error() << "Text::MagnumFont::openData(): wanted two files, got" << data.size();
@ -112,7 +112,7 @@ std::pair<Float, Float> MagnumFont::doOpenData(const std::vector<std::pair<std::
return openInternal(std::move(conf), std::move(*image)); return openInternal(std::move(conf), std::move(*image));
} }
std::pair<Float, Float> MagnumFont::doOpenFile(const std::string& filename, Float) { auto MagnumFont::doOpenFile(const std::string& filename, Float) -> Metrics {
/* Open the configuration file */ /* Open the configuration file */
Utility::Configuration conf(filename, Utility::Configuration::Flag::ReadOnly|Utility::Configuration::Flag::SkipComments); Utility::Configuration conf(filename, Utility::Configuration::Flag::ReadOnly|Utility::Configuration::Flag::SkipComments);
if(!conf.isValid() || conf.isEmpty()) { if(!conf.isValid() || conf.isEmpty()) {
@ -143,7 +143,7 @@ std::pair<Float, Float> MagnumFont::doOpenFile(const std::string& filename, Floa
return openInternal(std::move(conf), std::move(*image)); return openInternal(std::move(conf), std::move(*image));
} }
std::pair<Float, Float> MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image) { auto MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image) -> Metrics {
/* Everything okay, save the data internally */ /* Everything okay, save the data internally */
_opened = new Data{std::move(conf), std::move(image), std::unordered_map<char32_t, UnsignedInt>{}, {}}; _opened = new Data{std::move(conf), std::move(image), std::unordered_map<char32_t, UnsignedInt>{}, {}};
@ -161,7 +161,10 @@ std::pair<Float, Float> MagnumFont::openInternal(Utility::Configuration&& conf,
_opened->glyphId.emplace(c->value<char32_t>("unicode"), glyphId); _opened->glyphId.emplace(c->value<char32_t>("unicode"), glyphId);
} }
return {_opened->conf.value<Float>("fontSize"), _opened->conf.value<Float>("lineHeight")}; return {_opened->conf.value<Float>("fontSize"),
_opened->conf.value<Float>("ascent"),
_opened->conf.value<Float>("descent"),
_opened->conf.value<Float>("lineHeight")};
} }
void MagnumFont::doClose() { void MagnumFont::doClose() {

6
src/MagnumPlugins/MagnumFont/MagnumFont.h

@ -120,9 +120,9 @@ class MagnumFont: public AbstractFont {
bool doIsOpened() const override; bool doIsOpened() const override;
std::pair<Float, Float> doOpenData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, Float) override; Metrics doOpenData(const std::vector<std::pair<std::string, Containers::ArrayView<const char>>>& data, Float) override;
std::pair<Float, Float> doOpenFile(const std::string& filename, Float) override; Metrics doOpenFile(const std::string& filename, Float) override;
void doClose() override; void doClose() override;
@ -134,7 +134,7 @@ class MagnumFont: public AbstractFont {
std::unique_ptr<AbstractLayouter> doLayout(const GlyphCache& cache, Float size, const std::string& text) override; std::unique_ptr<AbstractLayouter> doLayout(const GlyphCache& cache, Float size, const std::string& text) override;
std::pair<Float, Float> openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image); Metrics openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image);
Data* _opened; Data* _opened;
}; };

2
src/MagnumPlugins/MagnumFont/Test/MagnumFontGLTest.cpp

@ -52,6 +52,8 @@ void MagnumFontGLTest::properties() {
MagnumFont font; MagnumFont font;
CORRADE_VERIFY(font.openFile(Utility::Directory::join(MAGNUMFONT_TEST_DIR, "font.conf"), 0.0f)); CORRADE_VERIFY(font.openFile(Utility::Directory::join(MAGNUMFONT_TEST_DIR, "font.conf"), 0.0f));
CORRADE_COMPARE(font.size(), 16.0f); CORRADE_COMPARE(font.size(), 16.0f);
CORRADE_COMPARE(font.ascent(), 25.0f);
CORRADE_COMPARE(font.descent(), -10.0f);
CORRADE_COMPARE(font.lineHeight(), 39.7333f); CORRADE_COMPARE(font.lineHeight(), 39.7333f);
CORRADE_COMPARE(font.glyphAdvance(font.glyphId(U'W')), Vector2(23.0f, 0.0f)); CORRADE_COMPARE(font.glyphAdvance(font.glyphId(U'W')), Vector2(23.0f, 0.0f));
} }

2
src/MagnumPlugins/MagnumFont/Test/font.conf

@ -3,6 +3,8 @@ image=font.tga
originalImageSize=1536 1536 originalImageSize=1536 1536
padding=24 24 padding=24 24
fontSize=16 fontSize=16
ascent=25
descent=-10
lineHeight=39.7333 lineHeight=39.7333
[char] [char]
unicode=57 unicode=57

2
src/MagnumPlugins/MagnumFont/pluginRegistration.cpp

@ -26,4 +26,4 @@
#include "MagnumPlugins/MagnumFont/MagnumFont.h" #include "MagnumPlugins/MagnumFont/MagnumFont.h"
CORRADE_PLUGIN_REGISTER(MagnumFont, Magnum::Text::MagnumFont, CORRADE_PLUGIN_REGISTER(MagnumFont, Magnum::Text::MagnumFont,
"cz.mosra.magnum.Text.AbstractFont/0.2.3") "cz.mosra.magnum.Text.AbstractFont/0.2.4")

2
src/MagnumPlugins/MagnumFontConverter/MagnumFontConverter.cpp

@ -53,6 +53,8 @@ std::vector<std::pair<std::string, Containers::Array<char>>> MagnumFontConverter
configuration.setValue("originalImageSize", cache.textureSize()); configuration.setValue("originalImageSize", cache.textureSize());
configuration.setValue("padding", cache.padding()); configuration.setValue("padding", cache.padding());
configuration.setValue("fontSize", font.size()); configuration.setValue("fontSize", font.size());
configuration.setValue("ascent", font.ascent());
configuration.setValue("descent", font.descent());
configuration.setValue("lineHeight", font.lineHeight()); configuration.setValue("lineHeight", font.lineHeight());
/* Compress glyph IDs so the glyphs are in consecutive array, glyph 0 /* Compress glyph IDs so the glyphs are in consecutive array, glyph 0

4
src/MagnumPlugins/MagnumFontConverter/Test/MagnumFontConverterGLTest.cpp

@ -65,9 +65,9 @@ void MagnumFontConverterGLTest::exportFont() {
private: private:
void doClose() { _opened = false; } void doClose() { _opened = false; }
bool doIsOpened() const { return _opened; } bool doIsOpened() const { return _opened; }
std::pair<Float, Float> doOpenFile(const std::string&, Float) { Metrics doOpenFile(const std::string&, Float) {
_opened = true; _opened = true;
return {16.0f, 39.7333f}; return {16.0f, 25.0f, -10.0f, 39.7333f};
} }
Features doFeatures() const { return {}; } Features doFeatures() const { return {}; }
std::unique_ptr<AbstractLayouter> doLayout(const GlyphCache&, Float, const std::string&) { return nullptr; } std::unique_ptr<AbstractLayouter> doLayout(const GlyphCache&, Float, const std::string&) { return nullptr; }

2
src/MagnumPlugins/MagnumFontConverter/pluginRegistration.cpp

@ -26,4 +26,4 @@
#include "MagnumPlugins/MagnumFontConverter/MagnumFontConverter.h" #include "MagnumPlugins/MagnumFontConverter/MagnumFontConverter.h"
CORRADE_PLUGIN_REGISTER(MagnumFontConverter, Magnum::Text::MagnumFontConverter, CORRADE_PLUGIN_REGISTER(MagnumFontConverter, Magnum::Text::MagnumFontConverter,
"cz.mosra.magnum.Text.AbstractFontConverter/0.1.1") "cz.mosra.magnum.Text.AbstractFontConverter/0.1.2")

Loading…
Cancel
Save