/*
* This source file is part of RmlUi, the HTML/CSS Interface Middleware
*
* For the latest information, see http://github.com/mikke89/RmlUi
*
* Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
* Copyright (c) 2019 The RmlUi Team, and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
#include "precompiled.h"
#ifndef RMLUI_NO_FONT_INTERFACE_DEFAULT
#include "FontFaceHandle.h"
#include "FontFaceLayer.h"
#include
#include "../TextureLayout.h"
namespace Rml {
namespace Core {
BitmapFont::FontFaceHandle::FontFaceHandle()
{
bm_face = nullptr;
texture_width = 0;
texture_height = 0;
}
BitmapFont::FontFaceHandle::~FontFaceHandle()
{
}
// Initialises the handle so it is able to render text.
bool BitmapFont::FontFaceHandle::Initialise(BitmapFontDefinitions *_bm_face, const String& _charset, int _size)
{
bm_face = _bm_face;
size = _size;
line_height = _size;
texture_width = bm_face->CommonCharactersInfo.ScaleWidth;
texture_height = bm_face->CommonCharactersInfo.ScaleHeight;
raw_charset = _charset;
// Construct proper path to texture
URL fnt_source = bm_face->Face.Source;
URL bitmap_source = bm_face->Face.BitmapSource;
if(bitmap_source.GetPath().empty())
{
texture_source = fnt_source.GetPath() + bitmap_source.GetFileName();
if(!bitmap_source.GetExtension().empty())
{
texture_source += "." + bitmap_source.GetExtension();
}
}
else
{
texture_source = bitmap_source.GetPathedFileName();
}
if (!UnicodeRange::BuildList(charset, raw_charset))
{
Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.c_str());
return false;
}
// Construct the list of the characters specified by the charset.
for (size_t i = 0; i < charset.size(); ++i)
BuildGlyphMap(bm_face, charset[i]);
// Generate the metrics for the handle.
GenerateMetrics(bm_face);
// Generate the default layer and layer configuration.
base_layer = GenerateLayer(nullptr);
layer_configurations.push_back(LayerConfiguration());
layer_configurations.back().push_back(base_layer);
return true;
}
void BitmapFont::FontFaceHandle::GenerateMetrics(BitmapFontDefinitions *bm_face)
{
line_height = bm_face->CommonCharactersInfo.LineHeight;
baseline = bm_face->CommonCharactersInfo.BaseLine;
underline_position = (float)line_height - bm_face->CommonCharactersInfo.BaseLine;
baseline += int( underline_position / 1.6f );
underline_thickness = 1.0f;
average_advance = 0;
for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
average_advance += i->advance;
// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
average_advance = Math::RealToInteger((float) average_advance / (glyphs.size() * 0.9f));
// Determine the x-height of this font face.
word x = (word) 'x';
int index = bm_face->BM_Helper_GetCharacterTableIndex( x );// FT_Get_Char_Index(ft_face, x);
if ( index >= 0)
x_height = bm_face->CharactersInfo[ index ].Height;
else
x_height = 0;
}
void BitmapFont::FontFaceHandle::BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range)
{
glyphs.resize(unicode_range.max_codepoint + 1);
for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code)
{
int index = bm_face->BM_Helper_GetCharacterTableIndex( character_code );
if ( index < 0 )
{
continue;
}
FontGlyph glyph;
glyph.character = character_code;
BuildGlyph(glyph, &bm_face->CharactersInfo[ index ] );
glyphs[character_code] = glyph;
}
}
void BitmapFont::FontFaceHandle::BuildGlyph(FontGlyph& glyph, CharacterInfo *bm_glyph)
{
// Set the glyph's dimensions.
glyph.dimensions.x = bm_glyph->Width;
glyph.dimensions.y = bm_glyph->Height;
// Set the glyph's bearing.
glyph.bearing.x = bm_glyph->XOffset;
glyph.bearing.y = bm_glyph->YOffset;
// Set the glyph's advance.
glyph.advance = bm_glyph->Advance;
// Set the glyph's bitmap position.
glyph.bitmap_dimensions.x = bm_glyph->X;
glyph.bitmap_dimensions.y = bm_glyph->Y;
glyph.bitmap_data = nullptr;
}
int BitmapFont::FontFaceHandle::GetKerning(word lhs, word rhs) const
{
if( bm_face != nullptr)
{
return bm_face->BM_Helper_GetXKerning(lhs, rhs);
}
return 0;
}
Rml::Core::FontFaceLayer* BitmapFont::FontFaceHandle::CreateNewLayer()
{
return new BitmapFont::FontFaceLayer();
}
}
}
#endif