/* This file is part of Zutty. * Copyright (C) 2020 Tom Szilagyi * * 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. * * See the file LICENSE for the full license. */ #pragma once #include #include FT_FREETYPE_H #include #include #include #include namespace zutty { class Font { public: enum Overlay_ { Overlay }; enum DoubleWidth_ { DoubleWidth }; /* Load a primary font, determining the atlas geometry and setting up * a mapping from unicode code points to atlas grid positions. */ explicit Font (const std::string& filename); /* Load an alternate font based on an already loaded primary font, * conforming to the same atlas geometry (incl. position mapping) * and starting with a copy of the atlas texture data. * * It is an error if the alternate font has different geometry. * Any code point not having a glyph in the alternate font will * have the glyph of the primary font (if any) in its atlas. * Any code point not having a glyph in the primary font will be * discarded. */ Font (const std::string& filename, const Font& priFont, Overlay_); /* Load a double-width font based on an already loaded primary font. * A double-width font is less tightly coupled to the primary, * but its glyph size has to match (double width, equal height). * The font will have its own independent atlas geometry. * * Only code points that are considered double-width by wcwidth () * will be loaded. */ Font (const std::string& filename, const Font& priFont, DoubleWidth_); ~Font () = default; uint16_t getPx () const { return px; }; uint16_t getPy () const { return py; }; uint16_t getBaseline () const { return baseline; }; uint16_t getNx () const { return nx; }; uint16_t getNy () const { return ny; }; float getUlTop () const { return ulTop; }; float getUlThick () const { return ulThick; }; const std::vector & getAtlas () const { return atlasBuf; }; const uint8_t* getAtlasData () const { return atlasBuf.data (); }; struct AtlasPos { uint8_t x = 0; uint8_t y = 0; }; using AtlasMap = std::map ; const AtlasMap& getAtlasMap () const { return atlasMap; }; private: std::string filename; bool overlay = false; bool dwidth = false; uint16_t px = 0; // glyph width in pixels uint16_t py = 0; // glyph height in pixels uint16_t baseline = 0; // number of pixels above baseline float ulTop = 0; // underline top from glyph top in pixels float ulThick = 0; // underline thickness in pixels uint16_t nx = 0; // number of glyphs in atlas texture per row uint16_t ny = 0; // number of rows in atlas texture std::vector atlasBuf; // loaded atlas data AtlasMap atlasMap; // unicode -> atlas position /* Start with 1 so as to leave a blank glyph at (0,0). * That blank will get referenced for any out-of-bounds text position * lookup in the shader, and guarantees that no fractional glyphs will * be shown at the right and bottom edges. * Also, any glyph mapping lookup that results in (0,0) means that the * character code does not exist in the atlas. */ uint16_t atlas_seq = 1; int loadSkipCount = 0; /* Load font from glyph bitmaps rasterized by FreeType. * Store the bitmaps into an atlas bitmap stored in atlasBuf. */ bool isLoadableChar (FT_ULong c); void load (); void loadFixed (const FT_Face& face); void loadScaled (const FT_Face& face); void loadFace (const FT_Face& face, FT_ULong c); void loadFace (const FT_Face& face, FT_ULong c, const AtlasPos& apos); }; } // namespace zutty