aboutsummaryrefslogtreecommitdiff
path: root/source/30-game/Font.hpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-11-25 17:28:07 -0800
committerrtk0c <[email protected]>2022-11-25 17:28:07 -0800
commitf3269a49c474ffe4d382c3d60826ad1cfbb7cdc4 (patch)
treebf7854505e9dae60c84e64764589c240339c3a41 /source/30-game/Font.hpp
parenta0ddfdbcbc6336685362343518770f7bdefd10fe (diff)
Changeset: 93 Branch comment: [] Port font and UTF-8 string utilities from p6503master-ui-framework
Diffstat (limited to 'source/30-game/Font.hpp')
-rw-r--r--source/30-game/Font.hpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/source/30-game/Font.hpp b/source/30-game/Font.hpp
new file mode 100644
index 0000000..cc64c0c
--- /dev/null
+++ b/source/30-game/Font.hpp
@@ -0,0 +1,131 @@
+#pragma once
+
+#include "Color.hpp"
+#include "CommonVertexIndex.hpp"
+#include "RcPtr.hpp"
+
+#include <glad/glad.h>
+#include <cstddef>
+#include <cstdint>
+#include <glm/glm.hpp>
+#include <memory>
+#include <span>
+#include <string_view>
+#include <vector>
+
+enum class FontType {
+ Regular,
+ Italic,
+ Bold,
+ BoldItalic,
+};
+
+struct GlyphVariant {
+ int horizontalAdvance;
+ float x0, y0;
+ float x1, y1;
+ float u0, v0;
+ float u1, v1;
+};
+
+// TODO optimize for memory when most glyphs don't have a non-regular variant
+// such as CJK characters rarely use bold or italics
+struct GlyphInfo {
+ char32_t codepoint;
+ GlyphVariant regular;
+ GlyphVariant italic;
+ GlyphVariant bold;
+ GlyphVariant boldItalic;
+};
+
+class Font : public RefCounted {
+public:
+ static const char32_t* GetGlyphRangesDefault();
+ static const char32_t* GetGlyphRangesKorean();
+ static const char32_t* GetGlyphRangesJapanese();
+ static const char32_t* GetGlyphRangesChineseFull();
+ static const char32_t* GetGlyphRangesChineseSimplifiedCommon();
+ static const char32_t* GetGlyphRangesCyrillic();
+ static const char32_t* GetGlyphRangesThai();
+ static const char32_t* GetGlyphRangesVietnamese();
+
+private:
+ std::vector<GlyphInfo> mGlyphs;
+ std::vector<int> mGlyphLookup;
+ RcPtr<Texture> mAtlas;
+ float mFontHeight;
+ int mFallbackGlyphIdx;
+
+public:
+ struct LoadingCandidate {
+ // No std::string_view here because iostreams only support null termianted string
+ const char* ttfPath;
+ const char32_t* glyphRange;
+ FontType type = FontType::Regular;
+ };
+
+ Font() = default;
+ Font(const Font&) = delete;
+ Font& operator=(const Font&) = delete;
+ Font(Font&&) = default;
+ Font& operator=(Font&&) = default;
+
+ enum ErrorCode {
+ EC_Success,
+ EC_FileIOFailed,
+ EC_FontLoadingFailed,
+ };
+ struct InitResult {
+ ErrorCode errorCode;
+ int failedItemIdx;
+ };
+
+ /// Initialize this font object from a list of ttf files. Each ttf covers a range of unicode characters,
+ /// and a specific font type, which are combined together into an atlas texture.
+ ///
+ /// \see FontType
+ /// \see Font::LoadingCandidate
+ InitResult Init(std::span<LoadingCandidate> candidates, float fontHeight, char32_t fallbackCodepoint = '?', int oversampleH = 1, int oversampleV = 1);
+
+ float GetFontHeight() const;
+ int HorizontalAdvance(char32_t c, FontType type = FontType::Regular) const;
+ int HorizontalAdvance(std::string_view str, FontType type = FontType::Regular) const;
+
+ int GetGlyphCount() const;
+ const GlyphInfo& GetFallbackGlyph() const;
+
+ /// Find the glyph corresponding to the given codepoint. If none is present, return the fallback glyph
+ /// specified in Init().
+ const GlyphInfo& FindGlyphFallback(char32_t codepoint) const;
+ /// Find the glyph corresponding to the given codepoint. If none is present, `nullptr` is returned.
+ const GlyphInfo* FindGlyph(char32_t codepoint) const;
+
+ struct DrawTargetPointer {
+ // Draw target info
+ Vertex_PTC* vertices;
+ uint32_t* indices;
+ uint32_t initialVertexIdx;
+
+ // Text info
+ glm::vec3 pos;
+ FontType type = FontType::Regular;
+ RgbaColor color = RgbaColor{};
+
+ // Output info, written to by DrawTo()
+ int glyphsRendered;
+ float horizontalAdvance;
+ };
+
+ /// Populate the target with quads, with first character's origin at `pos` and every vertex colored `color`.
+ /// User must allocate enough space for all characers beforehand (one way is to reserve the # of bytes).
+ /// Suitable for raw array allocations or something like PodVector<T> that doesn't do zero-initialization on
+ /// resize.
+ ///
+ /// \see Font::DrawTargetPointer
+ void DrawTo(std::string_view text, DrawTargetPointer& t) const;
+ void DrawTo(std::u32string_view text, DrawTargetPointer& t) const;
+
+ /// OpenGL texture containing the font atlas. Format is in GL_RED because we don't need the other channels, due to the
+ /// font atlas being black and white (in other words, opacity only).
+ const Texture& GetGlyphAtlas() const;
+};