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);
close();
std::tie(_size, _lineHeight) = doOpenData(data, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f));
const Metrics metrics = doOpenData(data, size);
_size = metrics.size;
_ascent = metrics.ascent;
_descent = metrics.descent;
_lineHeight = metrics.lineHeight;
CORRADE_INTERNAL_ASSERT(isOpened() || (!_size && !_ascent && !_descent && !_lineHeight));
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),
"Text::AbstractFont::openData(): feature advertised but not implemented", {});
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);
close();
std::tie(_size, _lineHeight) = doOpenSingleData(data, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f));
const Metrics metrics = doOpenSingleData(data, size);
_size = metrics.size;
_ascent = metrics.ascent;
_descent = metrics.descent;
_lineHeight = metrics.lineHeight;
CORRADE_INTERNAL_ASSERT(isOpened() || (!_size && !_ascent && !_descent && !_lineHeight));
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", {});
return {};
}
bool AbstractFont::openFile(const std::string& filename, const Float size) {
close();
std::tie(_size, _lineHeight) = doOpenFile(filename, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f));
const Metrics metrics = doOpenFile(filename, size);
_size = metrics.size;
_ascent = metrics.ascent;
_descent = metrics.descent;
_lineHeight = metrics.lineHeight;
CORRADE_INTERNAL_ASSERT(isOpened() || (!_size && !_ascent && !_descent && !_lineHeight));
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),
"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
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 {
CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.3")
CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.4")
public:
/**
@ -158,16 +158,33 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
/**
* @brief Font size
*
* Returns scale in which @ref lineHeight() and @ref glyphAdvance() is
* returned.
* Returns scale in which @ref lineHeight(), @ref ascent(),
* @ref descent() and @ref glyphAdvance() is returned.
*/
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
*
* Returns line height scaled to font size.
* @see @ref size()
* @see @ref size(), @ref ascent(), @ref descent()
*/
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);
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
protected:
#else
@ -239,29 +288,29 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
/**
* @brief Implementation for @ref openData()
*
* Return size and line height of opened font on successful opening,
* zeros otherwise. If the plugin doesn't have @ref Feature::MultiFile,
* Return metrics of opened font on successful opening, zeros
* otherwise. If the plugin doesn't have @ref Feature::MultiFile,
* 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()
*
* Return size and line height of opened font on successful opening,
* zeros otherwise.
* Return metrics of opened font on successful opening, zeros
* 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()
*
* Return size and line height of opened font on successful opening,
* zeros otherwise. If @ref Feature::OpenData is supported and the
* plugin doesn't have @ref Feature::MultiFile, default implementation
* opens the file and calls @ref doOpenSingleData() with its contents.
* Return metrics of opened font on successful opening, zeros
* otherwise. If @ref Feature::OpenData is supported and the plugin
* doesn't have @ref Feature::MultiFile, default implementation opens
* 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() */
virtual void doClose() = 0;
@ -289,7 +338,7 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#endif
Float _size, _lineHeight;
Float _size, _ascent, _descent, _lineHeight;
};
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
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 {
CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFontConverter/0.1.1")
CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFontConverter/0.1.2")
public:
/**

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

@ -56,7 +56,7 @@ class SingleDataFont: public Text::AbstractFont {
bool doIsOpened() const override { return opened; }
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');
return {};
}

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

@ -344,9 +344,9 @@ void RendererGLTest::multiline() {
bool doIsOpened() const override { return _opened; }
void doClose() override { _opened = false; }
std::pair<Float, Float> doOpenFile(const std::string&, Float) override {
Metrics doOpenFile(const std::string&, Float) override {
_opened = true;
return {0.5f, 0.75f};
return {0.5f, 0.45f, -0.25f, 0.75f};
}
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
line advance should be 0.75f*2.0f/0.5f = 3.0f */
CORRADE_COMPARE(font.size(), 0.5f);
CORRADE_COMPARE(font.ascent(), 0.45f);
CORRADE_COMPARE(font.descent(), -0.25f);
CORRADE_COMPARE(font.lineHeight(), 0.75f);
/* 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; }
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 */
if(data.size() != 2) {
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));
}
std::pair<Float, Float> MagnumFont::doOpenFile(const std::string& filename, Float) {
auto MagnumFont::doOpenFile(const std::string& filename, Float) -> Metrics {
/* Open the configuration file */
Utility::Configuration conf(filename, Utility::Configuration::Flag::ReadOnly|Utility::Configuration::Flag::SkipComments);
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));
}
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 */
_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);
}
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() {

6
src/MagnumPlugins/MagnumFont/MagnumFont.h

@ -120,9 +120,9 @@ class MagnumFont: public AbstractFont {
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;
@ -134,7 +134,7 @@ class MagnumFont: public AbstractFont {
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;
};

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

@ -52,6 +52,8 @@ void MagnumFontGLTest::properties() {
MagnumFont font;
CORRADE_VERIFY(font.openFile(Utility::Directory::join(MAGNUMFONT_TEST_DIR, "font.conf"), 0.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.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
padding=24 24
fontSize=16
ascent=25
descent=-10
lineHeight=39.7333
[char]
unicode=57

2
src/MagnumPlugins/MagnumFont/pluginRegistration.cpp

@ -26,4 +26,4 @@
#include "MagnumPlugins/MagnumFont/MagnumFont.h"
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("padding", cache.padding());
configuration.setValue("fontSize", font.size());
configuration.setValue("ascent", font.ascent());
configuration.setValue("descent", font.descent());
configuration.setValue("lineHeight", font.lineHeight());
/* 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:
void doClose() { _opened = false; }
bool doIsOpened() const { return _opened; }
std::pair<Float, Float> doOpenFile(const std::string&, Float) {
Metrics doOpenFile(const std::string&, Float) {
_opened = true;
return {16.0f, 39.7333f};
return {16.0f, 25.0f, -10.0f, 39.7333f};
}
Features doFeatures() const { return {}; }
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"
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