1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/* 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 <http://www.gnu.org/licenses/>.
*
*/
#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<Stream> reader(_GP(AssetMgr)->OpenAsset(filename));
if (!reader)
return nullptr;
const size_t lenof = reader->GetLength();
std::vector<char> 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
|