Browse Source

Text: initial support for line height in AbstractFont.

Got finally pissed with the requirement of setting AbstractFont::_size
manually and took this as opportunity to rework the internal plugin API
in a better way. Bumped the interface version, as this is binary
incompatible. MagnumFont doesn't support lineHeight yet.
pull/34/head
Vladimír Vondruš 13 years ago
parent
commit
858c9787f0
  1. 33
      src/Plugins/MagnumFont/MagnumFont.cpp
  2. 8
      src/Plugins/MagnumFont/MagnumFont.h
  3. 2
      src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp
  4. 13
      src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp
  5. 33
      src/Text/AbstractFont.cpp
  6. 42
      src/Text/AbstractFont.h
  7. 3
      src/Text/Test/AbstractFontTest.cpp

33
src/Plugins/MagnumFont/MagnumFont.cpp

@ -67,11 +67,11 @@ auto MagnumFont::doFeatures() const -> Features { return Feature::OpenData|Featu
bool MagnumFont::doIsOpened() const { return _opened; }
void MagnumFont::doOpenData(const std::vector<std::pair<std::string, Containers::ArrayReference<const unsigned char>>>& data, const Float) {
std::pair<Float, Float> MagnumFont::doOpenData(const std::vector<std::pair<std::string, Containers::ArrayReference<const unsigned char>>>& data, const Float) {
/* We need just the configuration file and image file */
if(data.size() != 2) {
Error() << "Text::MagnumFont::openData(): wanted two files, got" << data.size();
return;
return {};
}
/* Open the configuration file */
@ -79,51 +79,51 @@ void MagnumFont::doOpenData(const std::vector<std::pair<std::string, Containers:
Utility::Configuration conf(in, Utility::Configuration::Flag::SkipComments);
if(!conf.isValid() || conf.isEmpty()) {
Error() << "Text::MagnumFont::openData(): cannot open file" << data[0].first;
return;
return {};
}
/* Check version */
if(conf.value<UnsignedInt>("version") != 1) {
Error() << "Text::MagnumFont::openData(): unsupported file version, expected 1 but got"
<< conf.value<UnsignedInt>("version");
return;
return {};
}
/* Check that we have also the image file */
if(conf.value("image") != data[1].first) {
Error() << "Text::MagnumFont::openData(): expected file"
<< conf.value("image") << "but got" << data[1].first;
return;
return {};
}
/* Open and load image file */
Trade::TgaImporter importer;
if(!importer.openData(data[1].second)) {
Error() << "Text::MagnumFont::openData(): cannot open image file";
return;
return {};
}
std::optional<Trade::ImageData2D> image = importer.image2D(0);
if(!image) {
Error() << "Text::MagnumFont::openData(): cannot load image file";
return;
return {};
}
openInternal(std::move(conf), std::move(*image));
return openInternal(std::move(conf), std::move(*image));
}
void MagnumFont::doOpenFile(const std::string& filename, Float) {
std::pair<Float, Float> MagnumFont::doOpenFile(const std::string& filename, Float) {
/* Open the configuration file */
Utility::Configuration conf(filename, Utility::Configuration::Flag::ReadOnly|Utility::Configuration::Flag::SkipComments);
if(!conf.isValid() || conf.isEmpty()) {
Error() << "Text::MagnumFont::openFile(): cannot open file" << filename << conf.isValid();
return;
return {};
}
/* Check version */
if(conf.value<UnsignedInt>("version") != 1) {
Error() << "Text::MagnumFont::openFile(): unsupported file version, expected 1 but got"
<< conf.value<UnsignedInt>("version");
return;
return {};
}
/* Open and load image file */
@ -131,21 +131,20 @@ void MagnumFont::doOpenFile(const std::string& filename, Float) {
Trade::TgaImporter importer;
if(!importer.openFile(imageFilename)) {
Error() << "Text::MagnumFont::openFile(): cannot open image file" << imageFilename;
return;
return {};
}
std::optional<Trade::ImageData2D> image = importer.image2D(0);
if(!image) {
Error() << "Text::MagnumFont::openFile(): cannot load image file";
return;
return {};
}
openInternal(std::move(conf), std::move(*image));
return openInternal(std::move(conf), std::move(*image));
}
void MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image) {
std::pair<Float, Float> MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&& image) {
/* Everything okay, save the data internally */
_opened = new Data{std::move(conf), std::move(image), {}, {}};
_size = _opened->conf.value<Float>("fontSize");
/* Glyph advances */
const std::vector<Utility::ConfigurationGroup*> glyphs = _opened->conf.groups("glyph");
@ -160,6 +159,8 @@ void MagnumFont::openInternal(Utility::Configuration&& conf, Trade::ImageData2D&
CORRADE_INTERNAL_ASSERT(glyphId < _opened->glyphAdvance.size());
_opened->glyphId.emplace(c->value<char32_t>("unicode"), glyphId);
}
return {_opened->conf.value<Float>("fontSize"), 0};
}
void MagnumFont::doClose() {

8
src/Plugins/MagnumFont/MagnumFont.h

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

2
src/Plugins/MagnumFont/pluginRegistrationMagnumFont.cpp

@ -25,4 +25,4 @@
#include "MagnumFont/MagnumFont.h"
CORRADE_PLUGIN_REGISTER(MagnumFont, Magnum::Text::MagnumFont,
"cz.mosra.magnum.Text.AbstractFont/0.2.1")
"cz.mosra.magnum.Text.AbstractFont/0.2.2")

13
src/Plugins/MagnumFontConverter/Test/MagnumFontConverterTest.cpp

@ -60,11 +60,15 @@ void MagnumFontConverterTest::exportFont() {
/* Fake font with fake cache */
class FakeFont: public Text::AbstractFont {
public:
explicit FakeFont() { _size = 16.0f; }
explicit FakeFont(): _opened(false) {}
private:
void doClose() {}
bool doIsOpened() const { return true; }
void doClose() { _opened = false; }
bool doIsOpened() const { return _opened; }
std::pair<Float, Float> doOpenFile(const std::string&, Float) {
_opened = true;
return {16.0f, 0};
}
Features doFeatures() const { return {}; }
std::unique_ptr<AbstractLayouter> doLayout(const GlyphCache&, Float, const std::string&) { return nullptr; }
@ -86,7 +90,10 @@ void MagnumFontConverterTest::exportFont() {
CORRADE_ASSERT_UNREACHABLE();
}
bool _opened;
} font;
font.openFile({}, {});
/* Create fake cache */
MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::texture_rg);

33
src/Text/AbstractFont.cpp

@ -34,7 +34,7 @@ namespace Magnum { namespace Text {
AbstractFont::AbstractFont(): _size(0.0f) {}
AbstractFont::AbstractFont(PluginManager::AbstractManager* manager, std::string plugin): AbstractPlugin(manager, std::move(plugin)), _size(0.0f) {}
AbstractFont::AbstractFont(PluginManager::AbstractManager* manager, std::string plugin): AbstractPlugin(manager, std::move(plugin)), _size(0.0f), _lineHeight(0.0f) {}
bool AbstractFont::openData(const std::vector<std::pair<std::string, Containers::ArrayReference<const unsigned char>>>& data, const Float size) {
CORRADE_ASSERT(features() & Feature::OpenData,
@ -43,18 +43,19 @@ bool AbstractFont::openData(const std::vector<std::pair<std::string, Containers:
"Text::AbstractFont::openData(): no data passed", false);
close();
doOpenData(data, size);
std::tie(_size, _lineHeight) = doOpenData(data, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f));
return isOpened();
}
void AbstractFont::doOpenData(const std::vector<std::pair<std::string, Containers::ArrayReference<const unsigned char>>>& data, const Float size) {
std::pair<Float, Float> AbstractFont::doOpenData(const std::vector<std::pair<std::string, Containers::ArrayReference<const unsigned char>>>& data, const Float size) {
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,
"Text::AbstractFont::openData(): expected just one file for single-file format", );
"Text::AbstractFont::openData(): expected just one file for single-file format", {});
close();
doOpenSingleData(data[0].second, size);
return doOpenSingleData(data[0].second, size);
}
bool AbstractFont::openSingleData(const Containers::ArrayReference<const unsigned char> data, const Float size) {
@ -64,29 +65,31 @@ bool AbstractFont::openSingleData(const Containers::ArrayReference<const unsigne
"Text::AbstractFont::openSingleData(): the format is not single-file", false);
close();
doOpenSingleData(data, size);
std::tie(_size, _lineHeight) = doOpenSingleData(data, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f));
return isOpened();
}
void AbstractFont::doOpenSingleData(Containers::ArrayReference<const unsigned char>, Float) {
CORRADE_ASSERT(false, "Text::AbstractFont::openSingleData(): feature advertised but not implemented", );
std::pair<Float, Float> AbstractFont::doOpenSingleData(Containers::ArrayReference<const unsigned char>, Float) {
CORRADE_ASSERT(false, "Text::AbstractFont::openSingleData(): feature advertised but not implemented", {});
}
bool AbstractFont::openFile(const std::string& filename, const Float size) {
close();
doOpenFile(filename, size);
std::tie(_size, _lineHeight) = doOpenFile(filename, size);
CORRADE_INTERNAL_ASSERT(isOpened() || (_size == 0.0f && _lineHeight == 0.0f));
return isOpened();
}
void AbstractFont::doOpenFile(const std::string& filename, const Float size) {
std::pair<Float, Float> AbstractFont::doOpenFile(const std::string& filename, const Float size) {
CORRADE_ASSERT(features() & Feature::OpenData && !(features() & Feature::MultiFile),
"Text::AbstractFont::openFile(): not implemented", );
"Text::AbstractFont::openFile(): not implemented", {});
/* Open file */
std::ifstream in(filename.data(), std::ios::binary);
if(!in.good()) {
Error() << "Trade::AbstractFont::openFile(): cannot open file" << filename;
return;
return {};
}
/* Create array to hold file contents */
@ -98,12 +101,14 @@ void AbstractFont::doOpenFile(const std::string& filename, const Float size) {
in.read(reinterpret_cast<char*>(data.begin()), data.size());
in.close();
doOpenSingleData(data, size);
return doOpenSingleData(data, size);
}
void AbstractFont::close() {
if(isOpened()) {
doClose();
_size = 0.0f;
_lineHeight = 0.0f;
CORRADE_INTERNAL_ASSERT(!isOpened());
}
}

42
src/Text/AbstractFont.h

@ -67,7 +67,7 @@ checked by the implementation:
there is any file opened.
*/
class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.1")
CORRADE_PLUGIN_INTERFACE("cz.mosra.magnum.Text.AbstractFont/0.2.2")
public:
/**
@ -150,6 +150,9 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
/** @brief Font size */
Float size() const { return _size; }
/** @brief Line height */
Float lineHeight() const { return _lineHeight; }
/**
* @brief Glyph ID for given character
*
@ -199,13 +202,6 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
*/
std::unique_ptr<AbstractLayouter> layout(const GlyphCache& cache, Float size, const std::string& text);
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#else
protected:
#endif
Float _size;
#ifdef DOXYGEN_GENERATING_OUTPUT
protected:
#else
@ -220,22 +216,29 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
/**
* @brief Implementation for @ref openData()
*
* If the plugin doesn't have @ref Feature::MultiFile, default
* implementation calls @ref doOpenSingleData().
* Return size and line height of opened font on successful opening,
* zeros otherwise. If the plugin doesn't have @ref Feature::MultiFile,
* default implementation calls @ref doOpenSingleData().
*/
virtual void doOpenData(const std::vector<std::pair<std::string, Containers::ArrayReference<const unsigned char>>>& data, Float size);
virtual std::pair<Float, Float> doOpenData(const std::vector<std::pair<std::string, Containers::ArrayReference<const unsigned char>>>& data, Float size);
/** @brief Implementation for @ref openSingleData() */
virtual void doOpenSingleData(Containers::ArrayReference<const unsigned char> data, Float size);
/**
* @brief Implementation for @ref openSingleData()
*
* Return size and line height of opened font on successful opening,
* zeros otherwise.
*/
virtual std::pair<Float, Float> doOpenSingleData(Containers::ArrayReference<const unsigned char> data, Float size);
/**
* @brief Implementation for @ref openFile()
*
* 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 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.
*/
virtual void doOpenFile(const std::string& filename, Float size);
virtual std::pair<Float, Float> doOpenFile(const std::string& filename, Float size);
/** @brief Implementation for @ref close() */
virtual void doClose() = 0;
@ -266,6 +269,11 @@ class MAGNUM_TEXT_EXPORT AbstractFont: public PluginManager::AbstractPlugin {
/** @brief Implementation for @ref layout() */
virtual std::unique_ptr<AbstractLayouter> doLayout(const GlyphCache& cache, Float size, const std::string& text) = 0;
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#endif
Float _size, _lineHeight;
};
CORRADE_ENUMSET_OPERATORS(AbstractFont::Features)

3
src/Text/Test/AbstractFontTest.cpp

@ -55,8 +55,9 @@ class SingleDataFont: public Text::AbstractFont {
bool doIsOpened() const override { return opened; }
void doClose() override {}
void doOpenSingleData(const Containers::ArrayReference<const unsigned char> data, Float) override {
std::pair<Float, Float> doOpenSingleData(const Containers::ArrayReference<const unsigned char> data, Float) override {
opened = (data.size() == 1 && data[0] == 0xa5);
return {};
}
UnsignedInt doGlyphId(char32_t) override { return 0; }

Loading…
Cancel
Save