#pragma region CPL License
/*
Nuclex Engine
Copyright (C) 2002-2008 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#pragma endregion
#include "Nuclex/Text/TextServer.h"
#include "Nuclex/Text/FontCodec.h"
#include "Nuclex/Support/Exception.h"
namespace Nuclex { namespace Text {
// ------------------------------------------------------------------------------------------- //
namespace {
/// Enumerates a list of font codecs
class InternalFontCodecEnumerator : public TextServer::CodecEnumerator {
/// Map of codecs keyed by their names
private: typedef std::map > CodecMap;
/// Initializes a new FontCodecEnumerator
/// Codecs that will be enumerated by the new enumerator
public: InternalFontCodecEnumerator(const CodecMap &Codecs) :
m_Codecs(Codecs),
m_CodecIt(Codecs.end()),
m_CodecEnd(Codecs.end()) {}
/// Releases all memory owned by a FontCodecEnumerator
public: virtual ~InternalFontCodecEnumerator() {}
//
// CodecEnumerator implementation
//
/// Advances to the next entry in the enumeration
///
/// True if there was a next entry, false if the end of the enumerator was reached
///
public: bool next() {
if(m_CodecIt == m_CodecEnd)
m_CodecIt = m_Codecs.begin();
else
++m_CodecIt;
return (m_CodecIt != m_CodecEnd);
}
/// Gets the font codec at the enumerator's current position
/// The font codec at the enumerator's current position
public: const shared_ptr &get() const { return m_CodecIt->second; }
/// Map containing the codecs being enumerated
///
/// This is an internal implementation that directly references the map of codecs
/// from the text server for efficiency and simplicity.
///
private: const CodecMap &m_Codecs;
/// STL iterator pointing to the enumerator's current codec
private: CodecMap::const_iterator m_CodecIt;
/// STL iterator pointing to the end of the codec map
private: CodecMap::const_iterator m_CodecEnd;
};
} // anonymous namespace
// ------------------------------------------------------------------------------------------- //
namespace {
/// Enumerates over a list of fonts
class InternalFontEnumerator : public TextServer::FontEnumerator {
/// Maps a series of fonts by their names
private: typedef std::map > FontMap;
/// Initializes a new font enumerator
/// Map containing the fonts to enumerate
public: InternalFontEnumerator(const FontMap &Fonts) :
m_Fonts(Fonts),
m_FontIt(Fonts.begin()),
m_FontEnd(Fonts.end()) {}
/// Releases all memory owned by a font enumerator
public: virtual ~InternalFontEnumerator() {}
//
// FontEnumerator implementation
//
/// Advance the enumerator to the next entry
///
/// True if there was a next entry, false if the end of the enumerator was reached
///
public: bool next() {
if(m_FontIt == m_FontEnd)
m_FontIt = m_Fonts.begin();
else
++m_FontIt;
return (m_FontIt != m_FontEnd);
}
/// Gets the font at the enumerator's current position
/// The font at the enumerator's current position
const shared_ptr &get() const { return m_FontIt->second; }
/// Map containing the fonts being enumerated
///
/// This is an internal implementation that directly references the map of fonts
/// from the text server for efficiency and simplicity.
///
private: const FontMap &m_Fonts;
/// STL iterator pointing to the enumerator's current font
private: FontMap::const_iterator m_FontIt;
/// STL iterator pointing to the end of the font map
private: FontMap::const_iterator m_FontEnd;
};
} // namespace
// ------------------------------------------------------------------------------------------- //
const shared_ptr &TextServer::getCodec(const string &sName) const {
CodecMap::const_iterator CodecIt = m_Codecs.find(sName);
if(CodecIt == m_Codecs.end()) {
throw ItemNotFoundException(
"Nuclex::Text::TextServer::getCodec()",
string("Font codec not found: '") + sName + "'"
);
}
return CodecIt->second;
}
// ------------------------------------------------------------------------------------------- //
void TextServer::addCodec(const string &sName, const shared_ptr &spCodec) {
CodecMap::iterator CodecIt = m_Codecs.find(sName);
if(CodecIt != m_Codecs.end())
CodecIt->second = spCodec;
else
m_Codecs.insert(CodecMap::value_type(sName, spCodec));
}
// ------------------------------------------------------------------------------------------- //
void TextServer::removeCodec(const string &sName) {
CodecMap::iterator CodecIt = m_Codecs.find(sName);
if(CodecIt == m_Codecs.end()) {
throw ItemNotFoundException(
"Nuclex::Text::TextServer::removeCodec()",
string("Font codec not found: '") + sName + "'"
);
}
m_Codecs.erase(CodecIt);
}
// ------------------------------------------------------------------------------------------- //
void TextServer::clearCodecs() {
m_Codecs.clear();
}
// ------------------------------------------------------------------------------------------- //
shared_ptr TextServer::enumCodecs() const {
return shared_ptr(
new InternalFontCodecEnumerator(m_Codecs)
);
}
// ------------------------------------------------------------------------------------------- //
shared_ptr TextServer::loadFont(
const shared_ptr &spSource,
const string &sExtension,
size_t nSize
) const {
CodecMap::const_iterator CodecEnd = m_Codecs.end();
for(
CodecMap::const_iterator CodecIt = m_Codecs.begin();
CodecIt != CodecEnd;
CodecIt++
) {
if(CodecIt->second->canLoadFont(spSource, sExtension)) {
return CodecIt->second->loadFont(spSource, sExtension, nSize);
}
}
throw UnsupportedFontFormatException(
"Nuclex::Text::TextServer::loadFont()", "Unsupported font file format"
);
}
// ------------------------------------------------------------------------------------------- //
const shared_ptr &TextServer::getFont(const string &sName) const {
FontMap::const_iterator FontIt = m_Fonts.find(sName);
if(FontIt == m_Fonts.end()) {
throw ItemNotFoundException(
"Nuclex::Text::TextServer::getFont()",
string("Font not found: '") + sName + "'"
);
}
return FontIt->second;
}
// ------------------------------------------------------------------------------------------- //
void TextServer::addFont(const string &sName, const shared_ptr &spFont) {
FontMap::iterator FontIt = m_Fonts.find(sName);
if(FontIt != m_Fonts.end())
FontIt->second = spFont;
else
m_Fonts.insert(FontMap::value_type(sName, spFont));
}
// ------------------------------------------------------------------------------------------- //
void TextServer::removeFont(const string &sName) {
FontMap::iterator FontIt = m_Fonts.find(sName);
if(FontIt == m_Fonts.end()) {
throw ItemNotFoundException(
"Nuclex::Text::TextServer::removeFont()",
string("Font not found: '") + sName + "'"
);
}
m_Fonts.erase(FontIt);
}
// ------------------------------------------------------------------------------------------- //
void TextServer::clearFonts() {
m_Fonts.clear();
}
// ------------------------------------------------------------------------------------------- //
shared_ptr TextServer::enumFonts() const {
return shared_ptr(
new InternalFontEnumerator(m_Fonts)
);
}
// ------------------------------------------------------------------------------------------- //
}} // namespace Nuclex::Text