/* Copyright (C) 2003 Nikolas Zimmermann This file is part of the KDE project This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License aint with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include "Font.h" #include "Tools.h" #include "Converter.h" // Macros #define FT_TRUNC(x) ((x) >> 6) #define FT_TOFLOAT(x) ((x) * (1.0 / 64.0)) #define FT_FROMFLOAT(x) ((int) floor ((x) * 64.0 + 0.5)) using namespace T2P; FontVisualParams::FontVisualParams() { m_size = 0.0; m_slant = 0; m_weight = 0; } FontVisualParams::FontVisualParams(const FontVisualParams &other) { (*this) = other; } FontVisualParams::~FontVisualParams() { } FontVisualParams &FontVisualParams::operator=(const FontVisualParams &other) { m_size = other.m_size; m_slant = other.m_slant; m_weight = other.m_weight; m_fontList = other.m_fontList; return *this; } void FontVisualParams::setWeight(int weight) { m_weight = weight; } int FontVisualParams::weight() const { return m_weight; } void FontVisualParams::setSlant(int slant) { m_slant = slant; } int FontVisualParams::slant() const { return m_slant; } void FontVisualParams::setSize(double size) { m_size = size; } double FontVisualParams::size() const { return m_size; } std::list &FontVisualParams::fontList() { return m_fontList; } // ##### Font::Font(Converter *context) : m_context(context) { m_ready = false; m_fontFace = 0; m_fontParams = 0; } Font::~Font() { // Release font face if(m_ready && m_fontFace) { // FIXME: Debug that! //std::cout << "CALLING DONE FACE " << m_fontFace << std::endl; FT_Done_Face(m_fontFace); } delete m_fontParams; } std::string Font::buildRequest(const FontVisualParams *fontParams, int &id) { // Use FontConfig to locate & select fonts and use // FreeType2 to open them FcPattern *pattern; std::string fileName; pattern = FcPatternBuild(0, FC_WEIGHT, FcTypeInteger, fontParams->weight(), FC_SLANT, FcTypeInteger, fontParams->slant(), FC_SIZE, FcTypeDouble, fontParams->size(), NULL); // Add multiple font names std::list &fontList = const_cast(fontParams)->fontList(); for(std::list::const_iterator it = fontList.begin(); it != fontList.end(); ++it) { std::string string = *it; if(!string.empty()) FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast(string.c_str())); } // Always load vertical layout FcPatternAddBool(pattern, FC_VERTICAL_LAYOUT, true); // Disable hinting FcPatternAddBool(pattern, FC_HINTING, false); // Perform the default font pattern modification operations. FcDefaultSubstitute(pattern); FcConfigSubstitute(FcConfigGetCurrent(), pattern, FcMatchPattern); // Match the pattern! FcResult result; FcPattern *match = FcFontMatch(0, pattern, &result); // Destroy pattern FcPatternDestroy(pattern); // Get index & filename FcChar8 *temp; if(match) { FcPattern *pattern = FcPatternDuplicate(match); // Get index & filename if(FcPatternGetString(pattern, FC_FILE, 0, &temp) != FcResultMatch || FcPatternGetInteger(pattern, FC_INDEX, 0, &id) != FcResultMatch) { std::cout << "Font::buildRequest(), could not load font file for requested font \"" << Tools::joinList('|', fontList) << "\"" << std::endl; return fileName; } fileName = reinterpret_cast(temp); // Kill pattern FcPatternDestroy(pattern); } // Kill pattern FcPatternDestroy(match); return fileName; } bool Font::load(const FontVisualParams *fontParams) { // Build FontConfig request pattern int id = -1; std::string filename = Font::buildRequest(fontParams, id); // Load font directly using FreeType2 std::cout << "Font::load(), loading " << filename << " for requested font \"" << Tools::joinList('|', const_cast(fontParams)->fontList()) << "\"" << std::endl; FT_Error error = FT_New_Face(m_context->library(), filename.c_str(), id, &m_fontFace); if(error) { std::cout << "Font::load(), could not load font. Aborting!" << std::endl; return false; } if(!FT_IS_SCALABLE(m_fontFace)) { std::cout << "Font::load(), font does not contain outlines. Aborting!" << std::endl; FT_Done_Face(m_fontFace); m_fontFace = 0; return false; } // Choose unicode charmap for(int charmap = 0; charmap < m_fontFace->num_charmaps; charmap++) { if(m_fontFace->charmaps[charmap]->encoding == ft_encoding_unicode) { FT_Error error = FT_Set_Charmap(m_fontFace, m_fontFace->charmaps[charmap]); if(error) { std::cout << "Font::load(), unable to select unicode charmap. Aborting!" << std::endl; FT_Done_Face(m_fontFace); m_fontFace = 0; return false; } } } m_fontParams = fontParams; m_fontFile = filename; m_ready = true; return true; } FT_Face &Font::fontFace() { return m_fontFace; } std::string Font::fontFile() const { return m_fontFile; } const FontVisualParams *Font::fontParams() const { return m_fontParams; } // vim:ts=4:noet