/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "ags/shared/font/ttf_font_renderer.h" #include "ags/lib/alfont/alfont.h" #include "ags/shared/core/platform.h" #include "ags/shared/ac/game_version.h" #include "ags/globals.h" #include "ags/shared/core/asset_manager.h" #include "ags/shared/util/stream.h" #include "ags/shared/ac/game_struct_defines.h" #include "ags/shared/font/fonts.h" namespace AGS3 { using namespace AGS::Shared; // ***** TTF RENDERER ***** void TTFFontRenderer::AdjustYCoordinateForFont(int *ycoord, int /*fontNumber*/) { // TTF fonts already have space at the top, so try to remove the gap // TODO: adding -1 was here before (check the comment above), // but how universal is this "space at the top"? // Also, why is this function used only in one case of text rendering? // Review this after we upgrade the font library. ycoord[0]--; } void TTFFontRenderer::EnsureTextValidForFont(char * /*text*/, int /*fontNumber*/) { // do nothing, TTF can handle all characters } int TTFFontRenderer::GetTextWidth(const char *text, int fontNumber) { return alfont_text_length(_fontData[fontNumber].AlFont, text); } int TTFFontRenderer::GetTextHeight(const char * /*text*/, int fontNumber) { return alfont_get_font_real_height(_fontData[fontNumber].AlFont); } void TTFFontRenderer::RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) { if (y > destination->cb) // optimisation return; // Y - 1 because it seems to get drawn down a bit if ((ShouldAntiAliasText()) && (bitmap_color_depth(destination) > 8)) alfont_textout_aa(destination, _fontData[fontNumber].AlFont, text, x, y - 1, colour); else alfont_textout(destination, _fontData[fontNumber].AlFont, text, x, y - 1, colour); } bool TTFFontRenderer::LoadFromDisk(int fontNumber, int fontSize) { return LoadFromDiskEx(fontNumber, fontSize, nullptr, nullptr, nullptr); } bool TTFFontRenderer::IsBitmapFont() { return false; } static int GetAlfontFlags(int load_mode) { int flags = ALFONT_FLG_FORCE_RESIZE | ALFONT_FLG_SELECT_NOMINAL_SZ; // Compatibility: font ascender is always adjusted to the formal font's height; // EXCEPTION: not if it's a game made before AGS 3.4.1 with TTF anti-aliasing // (the reason is uncertain, but this is to emulate old engine's behavior). if (((load_mode & FFLG_ASCENDERFIXUP) != 0) && !(ShouldAntiAliasText() && (_G(loaded_game_file_version) < kGameVersion_341))) flags |= ALFONT_FLG_ASCENDER_EQ_HEIGHT; // Precalculate real glyphs extent (will make loading fonts relatively slower) flags |= ALFONT_FLG_PRECALC_MAX_CBOX; return flags; } // Loads a TTF font of a certain size static ALFONT_FONT *LoadTTF(const String &filename, int fontSize, int alfont_flags) { std::unique_ptr reader(_GP(AssetMgr)->OpenAsset(filename)); if (!reader) return nullptr; const size_t lenof = reader->GetLength(); std::vector buf; buf.resize(lenof); reader->Read(&buf.front(), lenof); reader.reset(); ALFONT_FONT *alfptr = alfont_load_font_from_mem(&buf.front(), lenof); if (!alfptr) return nullptr; alfont_set_font_size_ex(alfptr, fontSize, alfont_flags); return alfptr; } // Fill the FontMetrics struct from the given ALFONT static void FillMetrics(ALFONT_FONT *alfptr, FontMetrics *metrics) { metrics->NominalHeight = alfont_get_font_height(alfptr); metrics->RealHeight = alfont_get_font_real_height(alfptr); metrics->CompatHeight = metrics->NominalHeight; // just set to default here alfont_get_font_real_vextent(alfptr, &metrics->VExtent.first, &metrics->VExtent.second); // fixup vextent to be *not less* than realheight metrics->VExtent.first = std::min(0, metrics->VExtent.first); metrics->VExtent.second = std::max(metrics->RealHeight, metrics->VExtent.second); } bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize, String *src_filename, const FontRenderParams *params, FontMetrics *metrics) { String filename = String::FromFormat("agsfnt%d.ttf", fontNumber); if (fontSize <= 0) fontSize = 8; // compatibility fix assert(params); FontRenderParams f_params = params ? *params : FontRenderParams(); if (f_params.SizeMultiplier > 1) fontSize *= f_params.SizeMultiplier; ALFONT_FONT *alfptr = LoadTTF(filename, fontSize, GetAlfontFlags(f_params.LoadMode)); if (!alfptr) return false; _fontData[fontNumber].AlFont = alfptr; _fontData[fontNumber].Params = f_params; if (src_filename) *src_filename = filename; if (metrics) FillMetrics(alfptr, metrics); return true; } const char *TTFFontRenderer::GetFontName(int fontNumber) { return alfont_get_name(_fontData[fontNumber].AlFont); } int TTFFontRenderer::GetFontHeight(int fontNumber) { return alfont_get_font_real_height(_fontData[fontNumber].AlFont); } void TTFFontRenderer::GetFontMetrics(int fontNumber, FontMetrics *metrics) { FillMetrics(_fontData[fontNumber].AlFont, metrics); } void TTFFontRenderer::AdjustFontForAntiAlias(int fontNumber, bool /*aa_mode*/) { if (_G(loaded_game_file_version) < kGameVersion_341) { ALFONT_FONT *alfptr = _fontData[fontNumber].AlFont; const FontRenderParams ¶ms = _fontData[fontNumber].Params; int old_height = alfont_get_font_height(alfptr); alfont_set_font_size_ex(alfptr, old_height, GetAlfontFlags(params.LoadMode)); } } void TTFFontRenderer::FreeMemory(int fontNumber) { alfont_destroy_font(_fontData[fontNumber].AlFont); _fontData.erase(fontNumber); } bool TTFFontRenderer::MeasureFontOfPointSize(const String &filename, int size_pt, FontMetrics *metrics) { ALFONT_FONT *alfptr = LoadTTF(filename, size_pt, ALFONT_FLG_FORCE_RESIZE | ALFONT_FLG_SELECT_NOMINAL_SZ); if (!alfptr) return false; FillMetrics(alfptr, metrics); alfont_destroy_font(alfptr); return true; } bool TTFFontRenderer::MeasureFontOfPixelHeight(const String &filename, int pixel_height, FontMetrics *metrics) { ALFONT_FONT *alfptr = LoadTTF(filename, pixel_height, ALFONT_FLG_FORCE_RESIZE); if (!alfptr) return false; FillMetrics(alfptr, metrics); alfont_destroy_font(alfptr); return true; } } // namespace AGS3