@ -0,0 +1,239 @@ | |||||
/* | |||||
* 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_GEOM_RECT_PACK_HPP | |||||
#define ANTKEEPER_GEOM_RECT_PACK_HPP | |||||
#include "geom/rect.hpp" | |||||
namespace geom { | |||||
/** | |||||
* Node used in 2D rectangle packing. | |||||
* | |||||
* @see geom::rect_pack | |||||
*/ | |||||
template <class T> | |||||
struct rect_pack_node | |||||
{ | |||||
/// Scalar type. | |||||
typedef T scalar_type; | |||||
/// Rect type. | |||||
typedef rect<T> rect_type; | |||||
/// Creates a rect pack node. | |||||
rect_pack_node(); | |||||
/// Destroys a rect pack node and its children. | |||||
~rect_pack_node(); | |||||
/// Pointers to the two children of the node, if any. | |||||
rect_pack_node* children[2]; | |||||
/// Bounds of the node. | |||||
rect_type bounds; | |||||
/// `true` if the node is occupied, `false` otherwise. | |||||
bool occupied; | |||||
}; | |||||
template <class T> | |||||
rect_pack_node<T>::rect_pack_node(): | |||||
bounds{T(0), T(0), T(0), T(0)}, | |||||
occupied(false) | |||||
{ | |||||
children[0] = nullptr; | |||||
children[1] = nullptr; | |||||
} | |||||
template <class T> | |||||
rect_pack_node<T>::~rect_pack_node() | |||||
{ | |||||
delete children[0]; | |||||
delete children[1]; | |||||
} | |||||
/** | |||||
* Packs 2D rectangles. | |||||
* | |||||
* @see geom::rect_pack_node | |||||
* | |||||
* @see http://www.blackpawn.com/texts/lightmaps/ | |||||
*/ | |||||
template <class T> | |||||
class rect_pack | |||||
{ | |||||
public: | |||||
/// Scalar type. | |||||
typedef T scalar_type; | |||||
/// Node type. | |||||
typedef rect_pack_node<T> node_type; | |||||
/** | |||||
* Creates a rect pack and sets the bounds of the root node. | |||||
* | |||||
* @param w Width of the root node. | |||||
* @param h Height of the root node. | |||||
*/ | |||||
rect_pack(scalar_type w, scalar_type h); | |||||
/** | |||||
* Creates an empty rect pack. | |||||
*/ | |||||
rect_pack(); | |||||
/** | |||||
* Clears the pack and resizes the root node bounds. | |||||
* | |||||
* @param w New width of the root node. | |||||
* @param h New height of the root node. | |||||
* | |||||
* @see rect_pack::clear() | |||||
*/ | |||||
void resize(scalar_type w, scalar_type h); | |||||
/// Clear the pack, deallocating all nodes. | |||||
void clear(); | |||||
/** | |||||
* Packs a rect into the rect pack. | |||||
* | |||||
* @param w Width of the rect. | |||||
* @param h Height of the rect. | |||||
* @return Pointer to the node in which the rect was packed, or `nullptr` if the rect could not be packed. | |||||
*/ | |||||
const node_type* pack(scalar_type w, scalar_type h); | |||||
/// Returns a reference to the root node. | |||||
const node_type& get_root() const; | |||||
private: | |||||
static node_type* insert(node_type& parent, scalar_type w, scalar_type h); | |||||
static void free(); | |||||
node_type root; | |||||
}; | |||||
template <class T> | |||||
rect_pack<T>::rect_pack(scalar_type w, scalar_type h) | |||||
{ | |||||
root.bounds = {T(0), T(0), w, h}; | |||||
} | |||||
template <class T> | |||||
rect_pack<T>::rect_pack(): | |||||
rect_pack(0, 0) | |||||
{} | |||||
template <class T> | |||||
void rect_pack<T>::resize(scalar_type w, scalar_type h) | |||||
{ | |||||
clear(); | |||||
root.bounds = {T(0), T(0), w, h}; | |||||
} | |||||
template <class T> | |||||
void rect_pack<T>::clear() | |||||
{ | |||||
delete root.children[0]; | |||||
delete root.children[1]; | |||||
root.children[0] = nullptr; | |||||
root.children[1] = nullptr; | |||||
root.occupied = false; | |||||
} | |||||
template <class T> | |||||
const typename rect_pack<T>::node_type* rect_pack<T>::pack(scalar_type w, scalar_type h) | |||||
{ | |||||
return insert(root, w, h); | |||||
} | |||||
template <class T> | |||||
inline const typename rect_pack<T>::node_type& rect_pack<T>::get_root() const | |||||
{ | |||||
return root; | |||||
} | |||||
template <class T> | |||||
typename rect_pack<T>::node_type* rect_pack<T>::insert(node_type& node, scalar_type w, scalar_type h) | |||||
{ | |||||
// If not a leaf node | |||||
if (node.children[0] && node.children[1]) | |||||
{ | |||||
// Attempt to insert into first child | |||||
node_type* result = insert(*node.children[0], w, h); | |||||
if (result) | |||||
return result; | |||||
// Cannot fit in first child, attempt to insert into second child | |||||
return insert(*node.children[1], w, h); | |||||
} | |||||
// Abort if node occupied | |||||
if (node.occupied) | |||||
return nullptr; | |||||
// Determine node dimensions | |||||
scalar_type node_w = node.bounds.max.x - node.bounds.min.x; | |||||
scalar_type node_h = node.bounds.max.y - node.bounds.min.y; | |||||
// Check if rect is larger than node | |||||
if (w > node_w || h > node_h) | |||||
return nullptr; | |||||
// Check for a perfect fit | |||||
if (w == node_w && h == node_h) | |||||
{ | |||||
node.occupied = true; | |||||
return &node; | |||||
} | |||||
// Split the node | |||||
node.children[0] = new node_type(); | |||||
node.children[1] = new node_type(); | |||||
// Determine split direction | |||||
scalar_type dw = node_w - w; | |||||
scalar_type dh = node_h - h; | |||||
if (dw > dh) | |||||
{ | |||||
node.children[0]->bounds.min = node.bounds.min; | |||||
node.children[0]->bounds.max = {node.bounds.min.x + w, node.bounds.max.y}; | |||||
node.children[1]->bounds.min = {node.bounds.min.x + w, node.bounds.min.y}; | |||||
node.children[1]->bounds.max = {node.bounds.max}; | |||||
} | |||||
else | |||||
{ | |||||
node.children[0]->bounds.min = node.bounds.min; | |||||
node.children[0]->bounds.max = {node.bounds.max.x, node.bounds.min.y + h}; | |||||
node.children[1]->bounds.min = {node.bounds.min.x, node.bounds.min.y + h}; | |||||
node.children[1]->bounds.max = {node.bounds.max}; | |||||
} | |||||
// Insert into first child | |||||
return insert(*node.children[0], w, h); | |||||
} | |||||
} // namespace geom | |||||
#endif // ANTKEEPER_GEOM_RECT_PACK_HPP |
@ -0,0 +1,219 @@ | |||||
/* | |||||
* 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/bitmap-font.hpp" | |||||
#include "geom/rect-pack.hpp" | |||||
#include <stdexcept> | |||||
namespace type { | |||||
bitmap_font::bitmap_font(const font_metrics& metrics): | |||||
font(metrics) | |||||
{} | |||||
bitmap_font::bitmap_font() | |||||
{} | |||||
bool bitmap_font::contains(char32_t code) const | |||||
{ | |||||
return glyphs.count(code) != 0; | |||||
} | |||||
void bitmap_font::insert(char32_t code, const bitmap_glyph& glyph) | |||||
{ | |||||
glyphs[code] = glyph; | |||||
} | |||||
void bitmap_font::remove(char32_t code) | |||||
{ | |||||
if (auto it = glyphs.find(code); it != glyphs.end()) | |||||
glyphs.erase(it); | |||||
} | |||||
void bitmap_font::clear() | |||||
{ | |||||
glyphs.clear(); | |||||
} | |||||
bool bitmap_font::pack(bool resize) | |||||
{ | |||||
// Returns the smallest power of two that is not smaller than @p x. | |||||
auto ceil2 = [](unsigned int x) -> unsigned int | |||||
{ | |||||
if (x <= 1) | |||||
return 1; | |||||
unsigned int y = 2; | |||||
--x; | |||||
while (x >>= 1) | |||||
y <<= 1; | |||||
return y; | |||||
}; | |||||
// Calculate initial size of the font bitmap | |||||
unsigned int bitmap_w; | |||||
unsigned int bitmap_h; | |||||
if (resize) | |||||
{ | |||||
// Find the maximum glyph dimensions | |||||
unsigned int max_glyph_w = 0; | |||||
unsigned int max_glyph_h = 0; | |||||
for (auto it = glyphs.begin(); it != glyphs.end(); ++it) | |||||
{ | |||||
max_glyph_w = std::max(max_glyph_w, it->second.bitmap.get_width()); | |||||
max_glyph_h = std::max(max_glyph_h, it->second.bitmap.get_height()); | |||||
} | |||||
// Find minimum power of two dimensions that can accommodate maximum glyph dimensions | |||||
bitmap_w = ceil2(max_glyph_w); | |||||
bitmap_h = ceil2(max_glyph_h); | |||||
} | |||||
else | |||||
{ | |||||
bitmap_w = bitmap.get_width(); | |||||
bitmap_h = bitmap.get_height(); | |||||
} | |||||
bool packed = false; | |||||
geom::rect_pack<unsigned int> glyph_pack(bitmap_w, bitmap_h); | |||||
std::unordered_map<char32_t, const typename geom::rect_pack<unsigned int>::node_type*> glyph_map; | |||||
while (!packed) | |||||
{ | |||||
// For each glyph | |||||
for (auto it = glyphs.begin(); it != glyphs.end(); ++it) | |||||
{ | |||||
// Attempt to pack glyph bitmap | |||||
const auto* node = glyph_pack.pack(it->second.bitmap.get_width(), it->second.bitmap.get_height()); | |||||
// Abort if packing failed | |||||
if (!node) | |||||
break; | |||||
// Map pack node to glyph character code | |||||
glyph_map[it->first] = node; | |||||
} | |||||
// Check if not all glyphs were packed | |||||
if (glyph_map.size() != glyphs.size()) | |||||
{ | |||||
if (!resize) | |||||
{ | |||||
// No resize, packing failed | |||||
packed = false; | |||||
break; | |||||
} | |||||
// Clear glyph map | |||||
glyph_map.clear(); | |||||
// Clear glyph pack | |||||
glyph_pack.clear(); | |||||
// Resize glyph pack | |||||
if (bitmap_w > bitmap_h) | |||||
bitmap_h = ceil2(++bitmap_h); | |||||
else | |||||
bitmap_w = ceil2(++bitmap_w); | |||||
glyph_pack.resize(bitmap_w, bitmap_h); | |||||
} | |||||
else | |||||
{ | |||||
packed = true; | |||||
} | |||||
} | |||||
// Copy glyph bitmaps into font bitmap | |||||
if (packed) | |||||
{ | |||||
// Resize font bitmap | |||||
bitmap.resize(bitmap_w, bitmap_h); | |||||
// For each glyph | |||||
for (auto it = glyphs.begin(); it != glyphs.end(); ++it) | |||||
{ | |||||
// Find rect pack node corresponding to the glyph | |||||
const auto* node = glyph_map[it->first]; | |||||
// Copy glyph bitmap data into font bitmap | |||||
image& glyph_bitmap = it->second.bitmap; | |||||
bitmap.copy(glyph_bitmap, glyph_bitmap.get_width(), glyph_bitmap.get_height(), 0, 0, node->bounds.min.x, node->bounds.min.y); | |||||
// Record coordinates of glyph bitmap within font bitmap | |||||
it->second.position = {node->bounds.min.x, node->bounds.min.y}; | |||||
// Clear glyph bitmap data | |||||
glyph_bitmap.resize(0, 0); | |||||
} | |||||
} | |||||
return packed; | |||||
} | |||||
void bitmap_font::unpack(bool resize) | |||||
{ | |||||
for (auto it = glyphs.begin(); it != glyphs.end(); ++it) | |||||
{ | |||||
bitmap_glyph& glyph = it->second; | |||||
// Get glyph dimensions | |||||
unsigned int glyph_width = static_cast<unsigned int>(glyph.metrics.width + 0.5f); | |||||
unsigned int glyph_height = static_cast<unsigned int>(glyph.metrics.height + 0.5f); | |||||
// Reformat glyph bitmap if necessary | |||||
if (!glyph.bitmap.compatible(bitmap)) | |||||
glyph.bitmap.format(bitmap.get_component_size(), bitmap.get_channel_count()); | |||||
// Resize glyph bitmap if necessary | |||||
if (glyph.bitmap.get_width() != glyph_width || glyph.bitmap.get_height() != glyph_height) | |||||
glyph.bitmap.resize(glyph_width, glyph_height); | |||||
// Copy pixel data from font bitmap to glyph bitmap | |||||
glyph.bitmap.copy(bitmap, glyph_width, glyph_height, glyph.position.x, glyph.position.y); | |||||
} | |||||
// Free font bitmap pixel data | |||||
if (resize) | |||||
{ | |||||
bitmap.resize(0, 0); | |||||
} | |||||
} | |||||
const glyph_metrics& bitmap_font::get_glyph_metrics(char32_t code) const | |||||
{ | |||||
if (auto it = glyphs.find(code); it != glyphs.end()) | |||||
return it->second.metrics; | |||||
throw std::invalid_argument("Cannot fetch metrics of unknown bitmap glyph"); | |||||
} | |||||
const bitmap_glyph& bitmap_font::get_glyph(char32_t code) const | |||||
{ | |||||
if (auto it = glyphs.find(code); it != glyphs.end()) | |||||
return it->second; | |||||
throw std::invalid_argument("Cannot get unknown bitmap glyph"); | |||||
} | |||||
bitmap_glyph& bitmap_font::get_glyph(char32_t code) | |||||
{ | |||||
if (auto it = glyphs.find(code); it != glyphs.end()) | |||||
return it->second; | |||||
throw std::invalid_argument("Cannot get unknown bitmap glyph"); | |||||
} | |||||
} // namespace type |
@ -0,0 +1,151 @@ | |||||
/* | |||||
* 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_BITMAP_FONT_HPP | |||||
#define ANTKEEPER_TYPE_BITMAP_FONT_HPP | |||||
#include "type/font.hpp" | |||||
#include "type/bitmap-glyph.hpp" | |||||
#include "resources/image.hpp" | |||||
#include <unordered_map> | |||||
namespace type { | |||||
/** | |||||
* Raster font in which glyphs are stored as arrays of pixels. | |||||
* | |||||
* @see type::font | |||||
* @see type::font_metrics | |||||
* @see type::bitmap_glyph | |||||
* @see image | |||||
*/ | |||||
class bitmap_font: public font | |||||
{ | |||||
public: | |||||
/** | |||||
* Creates a bitmap font and sets its metrics. | |||||
* | |||||
* @param metrics Metrics describing the font. | |||||
*/ | |||||
bitmap_font(const font_metrics& metrics); | |||||
/// Creates an empty bitmap font. | |||||
bitmap_font(); | |||||
/// Destroys a bitmap font. | |||||
virtual ~bitmap_font() = default; | |||||
/// @copydoc font::contains(char32_t) const | |||||
virtual bool contains(char32_t code) const; | |||||
/** | |||||
* Inserts a glyph into the font. | |||||
* | |||||
* @param code UTF-32 character code of the glyph to insert. | |||||
* @param glyph Bitmap glyph data. | |||||
*/ | |||||
void insert(char32_t code, const bitmap_glyph& glyph); | |||||
/** | |||||
* Removes a glyph from the font. | |||||
* | |||||
* @param code UTF-32 character code of the glyph to remove. | |||||
*/ | |||||
void remove(char32_t code); | |||||
/** | |||||
* Removes all glyphs from the font. | |||||
*/ | |||||
void clear(); | |||||
/** | |||||
* Packs all glyph bitmaps into the font bitmap. | |||||
* | |||||
* @param resize Automatically resize the font bitmap to contain all glyphs. Bitmap size will start at the closest power of two to the largest glyph, then its dimensions will increase to the next power of two until its large enough that all glyphs can be contained. | |||||
* @return `true` if all glyphs were successfully packed, `false` otherwise. | |||||
* | |||||
* @except std::runtime_error Glyph bitmap format doesn't match font bitmap format. | |||||
* @except std::runtime_error Not enough space in font bitmap to pack glyph. | |||||
*/ | |||||
bool pack(bool resize = true); | |||||
/** | |||||
* Unpacks all glyph bitmaps from the font bitmap. | |||||
* | |||||
* @param resize Automatically resizes the font bitmap to zero. | |||||
*/ | |||||
void unpack(bool resize = true); | |||||
/// Returns a reference to the bitmap containing glyph pixel data. | |||||
const image& get_bitmap() const; | |||||
/// @copydoc bitmap_font::get_bitmap() const | |||||
image& get_bitmap(); | |||||
/** | |||||
* @copydoc font::get_glyph_metrics(char32_t) const | |||||
* | |||||
* @except std::invalid_argument Cannot fetch metrics of unknown bitmap glyph | |||||
*/ | |||||
virtual const glyph_metrics& get_glyph_metrics(char32_t code) const; | |||||
/** | |||||
* Returns a reference to the glyph corresponding to a UTF-32 character code. | |||||
* | |||||
* @param code UTF-32 character code of a glyph. | |||||
* @return Reference to the corresponding glyph. | |||||
* | |||||
* @except std::invalid_argument Cannot get unknown bitmap glyph | |||||
*/ | |||||
const bitmap_glyph& get_glyph(char32_t code) const; | |||||
/// @copydoc bitmap_font::get_glyph(char32_t) const | |||||
bitmap_glyph& get_glyph(char32_t code); | |||||
/** | |||||
* Returns a reference to the glyph corresponding to a UTF-32 character code, performing an insertion if such glyph does not already exist. | |||||
* | |||||
* @param code UTF-32 character code of a glyph. | |||||
* @return Reference to the corresponding glyph. | |||||
*/ | |||||
bitmap_glyph& operator[](char32_t code); | |||||
private: | |||||
std::unordered_map<char32_t, bitmap_glyph> glyphs; | |||||
image bitmap; | |||||
}; | |||||
inline const image& bitmap_font::get_bitmap() const | |||||
{ | |||||
return bitmap; | |||||
} | |||||
inline image& bitmap_font::get_bitmap() | |||||
{ | |||||
return bitmap; | |||||
} | |||||
inline bitmap_glyph& bitmap_font::operator[](char32_t code) | |||||
{ | |||||
return glyphs[code]; | |||||
} | |||||
} // namespace type | |||||
#endif // ANTKEEPER_TYPE_BITMAP_FONT_HPP |
@ -0,0 +1,48 @@ | |||||
/* | |||||
* 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_BITMAP_GLYPH_HPP | |||||
#define ANTKEEPER_TYPE_BITMAP_GLYPH_HPP | |||||
#include "resources/image.hpp" | |||||
#include "type/glyph-metrics.hpp" | |||||
#include "utility/fundamental-types.hpp" | |||||
namespace type { | |||||
/** | |||||
* Single glyph in a bitmap font. | |||||
* | |||||
* @see type::bitmap_font | |||||
*/ | |||||
struct bitmap_glyph | |||||
{ | |||||
/// Metrics describing the glyph. | |||||
glyph_metrics metrics; | |||||
/// Bitmap representing the glyph. | |||||
image bitmap; | |||||
/// Position of the packed glyph bitmap within the font bitmap. | |||||
uint2 position; | |||||
}; | |||||
} // namespace type | |||||
#endif // ANTKEEPER_TYPE_BITMAP_GLYPH_HPP |
@ -0,0 +1,51 @@ | |||||
/* | |||||
* 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_FONT_METRICS_HPP | |||||
#define ANTKEEPER_TYPE_FONT_METRICS_HPP | |||||
namespace type { | |||||
/** | |||||
* Metrics describing properties of a font. | |||||
*/ | |||||
struct font_metrics | |||||
{ | |||||
/// Positive distance from the baseline to the highest or upper grid coordinate. | |||||
float ascent; | |||||
/// Negative distance from the baseline to the lowest grid coordinate. | |||||
float descent; | |||||
/// Distance that must be placed between two lines of text. | |||||
float linegap; | |||||
/// Baseline-to-baseline distance, computed as ascent - descent + linegap`. | |||||
float linespace; | |||||
/// Vertical position of an underline. | |||||
float underline_position; | |||||
/// Thickness of an underline. | |||||
float underline_thickness; | |||||
}; | |||||
} // namespace type | |||||
#endif // ANTKEEPER_TYPE_FONT_METRICS_HPP |
@ -0,0 +1,48 @@ | |||||
/* | |||||
* 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_GLYPH_METRICS_HPP | |||||
#define ANTKEEPER_TYPE_GLYPH_METRICS_HPP | |||||
namespace type { | |||||
/** | |||||
* Metrics describing properties of a glyph. | |||||
*/ | |||||
struct glyph_metrics | |||||
{ | |||||
/// Horizontal extent of the glyph. | |||||
float width; | |||||
/// Vertical extent of the glyph. | |||||
float height; | |||||
/// Horizontal distance from the pen position to the glyph's left edge. | |||||
float bearing_left; | |||||
/// 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. | |||||
float advance; | |||||
}; | |||||
} // namespace type | |||||
#endif // ANTKEEPER_TYPE_GLYPH_METRICS_HPP |
@ -0,0 +1,33 @@ | |||||
/* | |||||
* 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_KERNING_TABLE_HPP | |||||
#define ANTKEEPER_TYPE_KERNING_TABLE_HPP | |||||
#include "utility/fundamental-types.hpp" | |||||
#include <unordered_map> | |||||
namespace type { | |||||
/// Table containing kerning offsets for pairs of glyphs. | |||||
typedef std::unordered_map<char32_t, std::unordered_map<char32_t, float2>> kerning_table; | |||||
} // namespace type | |||||
#endif // ANTKEEPER_TYPE_KERNING_TABLE_HPP |
@ -0,0 +1,52 @@ | |||||
/* | |||||
* 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_TYPEFACE_HPP | |||||
#define ANTKEEPER_TYPE_TYPEFACE_HPP | |||||
namespace type { | |||||
enum class typeface_style | |||||
{ | |||||
normal, | |||||
italic, | |||||
oblique | |||||
}; | |||||
/** | |||||
* Variant a typeface family, with a specific style and weight. A typeface corresponds to a single digital font file. | |||||
* | |||||
* @see type::font | |||||
*/ | |||||
class typeface | |||||
{ | |||||
public: | |||||
typeface(typeface_style style, int weight); | |||||
typeface_style get_style() const; | |||||
int get_weight() const; | |||||
private: | |||||
typeface_style style; | |||||
int weight; | |||||
}; | |||||
} // namespace type | |||||
#endif // ANTKEEPER_TYPE_TYPEFACE_HPP |