Browse Source

Add FreeType implementation of the typeface class, add FreeType typeface loader. Closes #4.

master
C. J. Howard 2 years ago
parent
commit
d09de68cd8
12 changed files with 526 additions and 83 deletions
  1. +3
    -1
      CMakeLists.txt
  2. +1
    -0
      src/game/bootloader.cpp
  3. +2
    -0
      src/game/context.hpp
  4. +56
    -74
      src/game/states/loading.cpp
  5. +1
    -1
      src/resources/json-loader.cpp
  6. +56
    -0
      src/resources/typeface-loader.cpp
  7. +6
    -0
      src/type/font-metrics.hpp
  8. +164
    -0
      src/type/freetype/typeface.cpp
  9. +80
    -0
      src/type/freetype/typeface.hpp
  10. +11
    -6
      src/type/glyph-metrics.hpp
  11. +44
    -0
      src/type/typeface.cpp
  12. +102
    -1
      src/type/typeface.hpp

+ 3
- 1
CMakeLists.txt View File

@ -14,6 +14,7 @@ find_package(OpenGL REQUIRED)
find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2-static SDL2::SDL2main CONFIG) find_package(SDL2 REQUIRED COMPONENTS SDL2::SDL2-static SDL2::SDL2main CONFIG)
find_package(OpenAL REQUIRED CONFIG) find_package(OpenAL REQUIRED CONFIG)
find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib") find_library(physfs REQUIRED NAMES physfs-static PATHS "${CMAKE_PREFIX_PATH}/lib")
find_package(freetype REQUIRED CONFIG)
# Determine dependencies # Determine dependencies
set(STATIC_LIBS set(STATIC_LIBS
@ -24,7 +25,8 @@ set(STATIC_LIBS
SDL2::SDL2-static SDL2::SDL2-static
SDL2::SDL2main SDL2::SDL2main
OpenAL::OpenAL OpenAL::OpenAL
${physfs})
${physfs}
freetype)
set(SHARED_LIBS set(SHARED_LIBS
${OPENGL_gl_LIBRARY}) ${OPENGL_gl_LIBRARY})

+ 1
- 0
src/game/bootloader.cpp View File

@ -346,6 +346,7 @@ void setup_resources(game::context* ctx)
ctx->resource_manager->include("/behaviors/"); ctx->resource_manager->include("/behaviors/");
ctx->resource_manager->include("/controls/"); ctx->resource_manager->include("/controls/");
ctx->resource_manager->include("/localization/"); ctx->resource_manager->include("/localization/");
ctx->resource_manager->include("/localization/fonts/");
ctx->resource_manager->include("/biomes/"); ctx->resource_manager->include("/biomes/");
ctx->resource_manager->include("/traits/"); ctx->resource_manager->include("/traits/");
ctx->resource_manager->include("/"); ctx->resource_manager->include("/");

+ 2
- 0
src/game/context.hpp View File

@ -44,6 +44,7 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "resources/json.hpp" #include "resources/json.hpp"
#include "type/typeface.hpp"
// Forward declarations // Forward declarations
class animator; class animator;
@ -139,6 +140,7 @@ struct context
string_table* string_table; string_table* string_table;
string_table_map string_table_map; string_table_map string_table_map;
std::unordered_map<std::string, std::string>* strings; std::unordered_map<std::string, std::string>* strings;
std::unordered_map<std::string, type::typeface*> typefaces;
// Framebuffers // Framebuffers
gl::framebuffer* shadow_map_framebuffer; gl::framebuffer* shadow_map_framebuffer;

+ 56
- 74
src/game/states/loading.cpp View File

@ -52,7 +52,6 @@
#include "utility/timestamp.hpp" #include "utility/timestamp.hpp"
#include "type/type.hpp" #include "type/type.hpp"
#include <stb/stb_image_write.h> #include <stb/stb_image_write.h>
#include <stb/stb_truetype.h>
namespace game { namespace game {
namespace state { namespace state {
@ -61,6 +60,8 @@ namespace loading {
/// Loads control profile and calibrates gamepads /// Loads control profile and calibrates gamepads
static void load_controls(game::context* ctx); static void load_controls(game::context* ctx);
static void load_fonts(game::context* ctx);
/// Creates the universe and solar system. /// Creates the universe and solar system.
static void cosmogenesis(game::context* ctx); static void cosmogenesis(game::context* ctx);
@ -93,6 +94,18 @@ void enter(game::context* ctx)
} }
ctx->logger->pop_task(EXIT_SUCCESS); ctx->logger->pop_task(EXIT_SUCCESS);
// Load fonts
ctx->logger->push_task("Loading fonts");
try
{
load_fonts(ctx);
}
catch (...)
{
ctx->logger->pop_task(EXIT_FAILURE);
}
ctx->logger->pop_task(EXIT_SUCCESS);
// Create universe // Create universe
ctx->logger->push_task("Creating the universe"); ctx->logger->push_task("Creating the universe");
try try
@ -121,79 +134,6 @@ void enter(game::context* ctx)
next_state.exit = std::bind(game::state::splash::exit, ctx); next_state.exit = std::bind(game::state::splash::exit, ctx);
} }
type::bitmap_font font;
image& font_bitmap = font.get_bitmap();
font_bitmap.format(sizeof(unsigned char), 1);
std::ifstream font_file(ctx->config_path + "Vollkorn-Regular.ttf", std::ios::binary | std::ios::ate);
std::streamsize size = font_file.tellg();
font_file.seekg(0, std::ios::beg);
std::vector<unsigned char> font_buffer(size);
if (!font_file.read((char*)font_buffer.data(), size))
{
ctx->logger->error("Failed to read font file");
}
// stb_truetype
{
stbtt_fontinfo font_info;
if (!stbtt_InitFont(&font_info, font_buffer.data(), 0))
{
ctx->logger->error("stb init font failed");
}
const float font_size = 64.0f;
const float scale = stbtt_ScaleForPixelHeight(&font_info, font_size);
int ascent = 0;
int descent = 0;
int linegap = 0;
stbtt_GetFontVMetrics(&font_info, &ascent, &descent, &linegap);
float scaled_ascent = static_cast<float>(ascent) * scale;
float scaled_descent = static_cast<float>(descent) * scale;
float scaled_linegap = static_cast<float>(linegap) * scale;
type::unicode::block block = type::unicode::block::basic_latin;
for (int c = block.first; c <= block.last; ++c)
{
int glyph_index = stbtt_FindGlyphIndex(&font_info, c);
if (!glyph_index)
continue;
type::bitmap_glyph& glyph = font[static_cast<char32_t>(c)];
int advance_width = 0;
int left_side_bearing = 0;
stbtt_GetGlyphHMetrics(&font_info, glyph_index, &advance_width, &left_side_bearing);
int min_x;
int min_y;
int max_x;
int max_y;
stbtt_GetGlyphBitmapBox(&font_info, glyph_index, scale, scale, &min_x, &min_y, &max_x, &max_y);
int glyph_width = max_x - min_x;
int glyph_height = max_y - min_y;
glyph.metrics.width = static_cast<float>(glyph_width);
glyph.metrics.height = static_cast<float>(glyph_height);
glyph.metrics.bearing_left = static_cast<float>(left_side_bearing) * scale;
glyph.metrics.bearing_top = 0.0f;
glyph.metrics.advance = static_cast<float>(advance_width) * scale;
glyph.bitmap.format(sizeof(unsigned char), 1);
glyph.bitmap.resize(glyph_width, glyph_height);
stbtt_MakeGlyphBitmap(&font_info, (unsigned char*)glyph.bitmap.get_pixels(), glyph_width, glyph_height, glyph_width, scale, scale, glyph_index);
}
}
font.pack();
std::string bitmap_path = ctx->config_path + "bitmap-font.png";
stbi_flip_vertically_on_write(0);
stbi_write_png(bitmap_path.c_str(), font_bitmap.get_width(), font_bitmap.get_height(), font_bitmap.get_channel_count(), font_bitmap.get_pixels(), font_bitmap.get_width() * font_bitmap.get_channel_count());
// Queue next game state // Queue next game state
ctx->app->queue_state(next_state); ctx->app->queue_state(next_state);
} }
@ -287,6 +227,48 @@ void load_controls(game::context* ctx)
ctx->controls["menu_right"]->set_activation_threshold(menu_activation_threshold); ctx->controls["menu_right"]->set_activation_threshold(menu_activation_threshold);
} }
void load_fonts(game::context* ctx)
{
// Load typefaces
if (auto it = ctx->strings->find("font_serif"); it != ctx->strings->end())
ctx->typefaces["serif"] = ctx->resource_manager->load<type::typeface>(it->second);
if (auto it = ctx->strings->find("font_sans_serif"); it != ctx->strings->end())
ctx->typefaces["sans_serif"] = ctx->resource_manager->load<type::typeface>(it->second);
if (auto it = ctx->strings->find("font_monospace"); it != ctx->strings->end())
ctx->typefaces["monospace"] = ctx->resource_manager->load<type::typeface>(it->second);
// Build bitmap fonts
if (auto it = ctx->typefaces.find("serif"); it != ctx->typefaces.end())
{
type::typeface* typeface = it->second;
type::bitmap_font font;
const float size = 48.0f;
if (type::font_metrics metrics; typeface->get_metrics(size, metrics))
font.set_font_metrics(metrics);
image& font_bitmap = font.get_bitmap();
font_bitmap.format(sizeof(unsigned char), 1);
type::unicode::block block = type::unicode::block::basic_latin;
for (char32_t code = block.first; code <= block.last; ++code)
{
if (!typeface->has_glyph(code))
continue;
type::bitmap_glyph& glyph = font[code];
typeface->get_metrics(size, code, glyph.metrics);
typeface->get_bitmap(size, code, glyph.bitmap);
}
font.pack();
std::string bitmap_path = ctx->config_path + "bitmap-font-serif.png";
stbi_flip_vertically_on_write(0);
stbi_write_png(bitmap_path.c_str(), font_bitmap.get_width(), font_bitmap.get_height(), font_bitmap.get_channel_count(), font_bitmap.get_pixels(), font_bitmap.get_width() * font_bitmap.get_channel_count());
}
}
void cosmogenesis(game::context* ctx) void cosmogenesis(game::context* ctx)
{ {
// Init time // Init time

+ 1
- 1
src/resources/json-loader.cpp View File

@ -26,7 +26,7 @@ template <>
json* resource_loader<json>::load(resource_manager* resource_manager, PHYSFS_File* file) json* resource_loader<json>::load(resource_manager* resource_manager, PHYSFS_File* file)
{ {
// Read file into buffer // Read file into buffer
std::size_t size = static_cast<int>(PHYSFS_fileLength(file));
std::size_t size = static_cast<std::size_t>(PHYSFS_fileLength(file));
std::string buffer; std::string buffer;
buffer.resize(size); buffer.resize(size);
PHYSFS_readBytes(file, &buffer[0], size); PHYSFS_readBytes(file, &buffer[0], size);

+ 56
- 0
src/resources/typeface-loader.cpp View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code 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.
*
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resource-loader.hpp"
#include "type/freetype/typeface.hpp"
#include <stdexcept>
#include <physfs.h>
#include <ft2build.h>
#include FT_FREETYPE_H
template <>
type::typeface* resource_loader<type::typeface>::load(resource_manager* resource_manager, PHYSFS_File* file)
{
FT_Error error = 0;
// Init FreeType library object
FT_Library library;
error = FT_Init_FreeType(&library);
if (error)
{
throw std::runtime_error("Failed to init FreeType library (error code " + std::to_string(error) + ")");
}
// Read file into buffer
std::size_t size = static_cast<std::size_t>(PHYSFS_fileLength(file));
unsigned char* buffer = new unsigned char[size];
PHYSFS_readBytes(file, buffer, size);
// Load FreeType face from buffer
FT_Face face;
error = FT_New_Memory_Face(library, buffer, size, 0, &face);
if (error)
{
delete[] buffer;
FT_Done_FreeType(library);
throw std::runtime_error("Failed to load FreeType face (error code " + std::to_string(error) + ")");
}
return new type::freetype::typeface(library, face, buffer);
}

+ 6
- 0
src/type/font-metrics.hpp View File

@ -44,6 +44,12 @@ struct font_metrics
/// Thickness of an underline. /// Thickness of an underline.
float underline_thickness; float underline_thickness;
/// Maximum advance with for all glyphs, for horizontal layouts.
float max_horizontal_advance;
/// Maximum advance height for all glyphs, for vertical layouts.
float max_vertical_advance;
}; };
} // namespace type } // namespace type

+ 164
- 0
src/type/freetype/typeface.cpp View File

@ -0,0 +1,164 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code 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.
*
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "type/freetype/typeface.hpp"
#include <stdexcept>
#include <string>
namespace type {
namespace freetype {
typeface::typeface(FT_Library library, FT_Face face, unsigned char* buffer):
library(library),
face(face),
buffer(buffer),
height(-1.0f)
{}
typeface::~typeface()
{
FT_Done_Face(face);
delete[] buffer;
FT_Done_FreeType(library);
}
bool typeface::has_kerning() const
{
return FT_HAS_KERNING(face);
}
bool typeface::has_glyph(char32_t code) const
{
return FT_Get_Char_Index(face, static_cast<FT_ULong>(code)) != 0;
}
bool typeface::get_metrics(float height, font_metrics& metrics) const
{
// Set font size
set_face_pixel_size(height);
// Get font metrics
metrics.ascent = face->size->metrics.ascender / 64.0f;
metrics.descent = face->size->metrics.descender / 64.0f;
metrics.linegap = face->size->metrics.height / 64.0f;
metrics.linespace = metrics.ascent - metrics.descent + metrics.linegap;
metrics.underline_position = FT_MulFix(face->underline_position, face->size->metrics.y_scale) / 64.0f;
metrics.underline_thickness = FT_MulFix(face->underline_thickness, face->size->metrics.y_scale) / 64.0f;
metrics.max_horizontal_advance = face->size->metrics.max_advance / 64.0f;
metrics.max_vertical_advance = FT_MulFix(face->max_advance_height, face->size->metrics.y_scale) / 64.0f;
return true;
}
bool typeface::get_metrics(float height, char32_t code, glyph_metrics& metrics) const
{
// Set font size
set_face_pixel_size(height);
// Get index of glyph
FT_UInt glyph_index = FT_Get_Char_Index(face, static_cast<FT_ULong>(code));
// Load glyph and render bitmap
FT_Error error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error)
{
throw std::runtime_error("FreeType failed to load glyph (error code " + std::to_string(error) + ")");
}
// Get glyph metrics
metrics.width = face->glyph->metrics.width / 64.0f;
metrics.height = face->glyph->metrics.height / 64.0f;
metrics.horizontal_bearing.x = face->glyph->metrics.horiBearingX / 64.0f;
metrics.horizontal_bearing.y = face->glyph->metrics.horiBearingY / 64.0f;
metrics.vertical_bearing.x = face->glyph->metrics.vertBearingX / 64.0f;
metrics.vertical_bearing.y = face->glyph->metrics.vertBearingY / 64.0f;
metrics.horizontal_advance = face->glyph->metrics.horiAdvance / 64.0f;
metrics.vertical_advance = face->glyph->metrics.vertAdvance / 64.0f;
return true;
}
bool typeface::get_bitmap(float height, char32_t code, image& bitmap) const
{
// Set font size
set_face_pixel_size(height);
// Get index of glyph
FT_UInt glyph_index = FT_Get_Char_Index(face, static_cast<FT_ULong>(code));
// Load glyph and render bitmap
FT_Error error = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER | FT_LOAD_TARGET_(FT_RENDER_MODE_NORMAL));
if (error)
{
throw std::runtime_error("FreeType failed to load glyph (error code " + std::to_string(error) + ")");
}
// Format and resize bitmap
bitmap.resize(0, 0);
bitmap.format(sizeof(unsigned char), 1);
bitmap.resize(face->glyph->bitmap.width, face->glyph->bitmap.rows);
// Copy glyph bitmap data in bitmap
std::memcpy(bitmap.get_pixels(), face->glyph->bitmap.buffer, bitmap.get_size());
return true;
}
bool typeface::get_kerning(float height, char32_t first, char32_t second, float2& offset) const
{
// Check if typeface has kerning information
if (!has_kerning())
return false;
// Set font size
set_face_pixel_size(height);
// Get indices of the two glyphs
FT_UInt first_index = FT_Get_Char_Index(face, static_cast<FT_ULong>(first));
FT_UInt second_index = FT_Get_Char_Index(face, static_cast<FT_ULong>(second));
// Get kerning vector
FT_Vector kerning;
FT_Error error = FT_Get_Kerning(face, first_index, second_index, FT_KERNING_DEFAULT, &kerning);
if (error)
{
throw std::runtime_error("FreeType failed to get kerning vector (error code " + std::to_string(error) + ")");
}
offset = float2{static_cast<float>(kerning.x), static_cast<float>(kerning.y)} / 64.0f;
return true;
}
void typeface::set_face_pixel_size(float height) const
{
if (this->height == height)
return;
FT_Error error = FT_Set_Pixel_Sizes(face, 0, static_cast<FT_UInt>(height));
if (error)
{
throw std::runtime_error("FreeType failed to set face size (error code " + std::to_string(error) + ")");
}
this->height = height;
}
} // namespace freetype
} // namespace type

+ 80
- 0
src/type/freetype/typeface.hpp View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code 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.
*
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_TYPE_FREETYPE_TYPEFACE_HPP
#define ANTKEEPER_TYPE_FREETYPE_TYPEFACE_HPP
#include "type/typeface.hpp"
#include <ft2build.h>
#include FT_FREETYPE_H
namespace type {
namespace freetype {
/**
* Typeface implementation using the FreeType library.
*
* @see type::typeface
*/
class typeface: public type::typeface
{
public:
/**
* Creates a FreeType typeface.
*
* @param library Pointer to a FreeType library instance.
* @param face Pointer to the FreeType object instance.
* @param buffer Pointer to file buffer containing FreeType face data.
*/
typeface(FT_Library library, FT_Face face, unsigned char* buffer);
/// Destroys a FreeType typeface.
virtual ~typeface();
/// @copydoc type::typeface::has_kerning() const
virtual bool has_kerning() const;
/// @copydoc type::typeface::has_glyph(char32_t) const
virtual bool has_glyph(char32_t code) const;
/// @copydoc type::typeface::get_metrics(float, font_metrics&) const
virtual bool get_metrics(float height, font_metrics& metrics) const;
/// @copydoc type::typeface::get_metrics(float, char32_t, glyph_metrics&) const
virtual bool get_metrics(float height, char32_t code, glyph_metrics& metrics) const;
/// @copydoc type::typeface::get_bitmap(float, char32_t, image&) const
virtual bool get_bitmap(float height, char32_t code, image& bitmap) const;
/// @copydoc type::typeface::get_kerning(float, char32_t, char32_t, float2&) const
virtual bool get_kerning(float height, char32_t first, char32_t second, float2& offset) const;
private:
void set_face_pixel_size(float height) const;
FT_Library library;
FT_Face face;
unsigned char* buffer;
mutable float height;
};
} // namespace freetype
} // namespace type
#endif // ANTKEEPER_TYPE_FREETYPE_TYPEFACE_HPP

+ 11
- 6
src/type/glyph-metrics.hpp View File

@ -20,6 +20,8 @@
#ifndef ANTKEEPER_TYPE_GLYPH_METRICS_HPP #ifndef ANTKEEPER_TYPE_GLYPH_METRICS_HPP
#define ANTKEEPER_TYPE_GLYPH_METRICS_HPP #define ANTKEEPER_TYPE_GLYPH_METRICS_HPP
#include "utility/fundamental-types.hpp"
namespace type { namespace type {
/** /**
@ -33,14 +35,17 @@ struct glyph_metrics
/// Vertical extent of the glyph. /// Vertical extent of the glyph.
float height; float height;
/// Horizontal distance from the pen position to the glyph's left edge.
float bearing_left;
/// Offset from the pen position to the glyph's top-left edge, in horizontal layouts.
float2 horizontal_bearing;
/// Offset from the pen position to the glph's top-left edge, in vertical layouts.
float2 vertical_bearing;
/// Vertical distance from the baseline to the glyph's top edge.
float bearing_top;
/// Distance to move the pen position after the glyph has been rendered, in horizontal layouts.
float horizontal_advance;
/// Distance to move the pen position after the glyph has been rendered.
float advance;
/// Distance to move the pen position after the glyph has been rendered, in vertical layouts.
float vertical_advance;
}; };
} // namespace type } // namespace type

+ 44
- 0
src/type/typeface.cpp View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code 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.
*
* Antkeeper source code 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 Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "type/typeface.hpp"
namespace type {
typeface::typeface(typeface_style style, int weight):
style(style),
weight(weight)
{}
typeface::typeface():
style(typeface_style::normal),
weight(400)
{}
void typeface::set_style(typeface_style style)
{
this->style = style;
}
void typeface::set_weight(int weight)
{
this->weight = weight;
}
} // namespace type

+ 102
- 1
src/type/typeface.hpp View File

@ -20,33 +20,134 @@
#ifndef ANTKEEPER_TYPE_TYPEFACE_HPP #ifndef ANTKEEPER_TYPE_TYPEFACE_HPP
#define ANTKEEPER_TYPE_TYPEFACE_HPP #define ANTKEEPER_TYPE_TYPEFACE_HPP
#include "type/font-metrics.hpp"
#include "type/glyph-metrics.hpp"
#include "resources/image.hpp"
#include "utility/fundamental-types.hpp"
namespace type { namespace type {
/// Emumerates typeface styles.
enum class typeface_style enum class typeface_style
{ {
/// Normal typeface style.
normal, normal,
/// Italic typeface style.
italic, italic,
/// Oblique typeface style.
oblique oblique
}; };
/** /**
* Variant a typeface family, with a specific style and weight. A typeface corresponds to a single digital font file.
* Abstract base class for a typeface, which corresponds to a single digital font file.
* *
* @see type::font * @see type::font
*/ */
class typeface class typeface
{ {
public: public:
/**
* Creates a typeface, setting its style and weight.
*
* @param style Typeface style.
* @param weight Typeface weight.
*/
typeface(typeface_style style, int weight); typeface(typeface_style style, int weight);
/// Creates an empty typeface.
typeface();
/// Destroys a typeface.
virtual ~typeface() = default;
/**
* Sets the style of the typeface.
*
* @param style Typeface style.
*/
void set_style(typeface_style style);
/**
* Sets the weight of the typeface.
*
* @param weight Typeface weight.
*/
void set_weight(int weight);
/// Returns the style of the typeface.
typeface_style get_style() const; typeface_style get_style() const;
/// Returns the weight of the typeface.
int get_weight() const; int get_weight() const;
/// Returns `true` if the typeface contains kerning information, `false` otherwise.
virtual bool has_kerning() const = 0;
/**
* Returns `true` if the typeface contains a glyph, `false` otherwise.
*
* @param code UTF-32 character code of a glyph.
* @return `true` if the typeface contains the glyph, `false` otherwise.
*/
virtual bool has_glyph(char32_t code) const = 0;
/**
* Gets metrics for a font of the specified size.
*
* @param[in] height Height of the font, in pixels.
* @param[out] metrics Font metrics.
* @return `true` if font metrics were returned, `false` otherwise.
*/
virtual bool get_metrics(float height, font_metrics& metrics) const = 0;
/**
* Gets metrics for a glyph in a font of the specified size.
*
* @param[in] height Height of the font, in pixels.
* @param[in] code UTF-32 character code of a glyph.
* @param[out] metrics Glyph metrics.
* @return `true` if glyph metrics were returned, `false` otherwise.
*/
virtual bool get_metrics(float height, char32_t code, glyph_metrics& metrics) const = 0;
/**
* Gets a bitmap of a glyph in a font of the specified size.
*
* @param[in] height Height of the font, in pixels.
* @param[in] code UTF-32 character code of a glyph.
* @param[out] bitmap Glyph bitmap data.
* @return `true` if glyph bitmap data was returned, `false` otherwise.
*/
virtual bool get_bitmap(float height, char32_t code, image& bitmap) const = 0;
/**
* Gets the kerning offset for a pair of glyphs.
*
* @param[in] height Height of the font, in pixels.
* @param[in] first UTF-32 character code of the first glyph.
* @param[in] second UTF-32 character code of the second glyph.
* @param[out] offset Kerning offset.
* @return `true` if a kerning offset was returned, `false` otherwise.
*/
virtual bool get_kerning(float height, char32_t first, char32_t second, float2& offset) const = 0;
private: private:
typeface_style style; typeface_style style;
int weight; int weight;
}; };
inline typeface_style typeface::get_style() const
{
return style;
}
inline int typeface::get_weight() const
{
return weight;
}
} // namespace type } // namespace type
#endif // ANTKEEPER_TYPE_TYPEFACE_HPP #endif // ANTKEEPER_TYPE_TYPEFACE_HPP

Loading…
Cancel
Save