summaryrefslogtreecommitdiff
path: root/src/mbgl/text/glyph.hpp
blob: f3f28828ef674a8813ef8fe2be0c5bf68df811fb (plain)
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
#pragma once

#include <mbgl/text/glyph_range.hpp>
#include <mbgl/util/bitmask_operations.hpp>
#include <mbgl/util/font_stack.hpp>
#include <mbgl/util/rect.hpp>
#include <mbgl/util/traits.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/immutable.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/util.hpp>

#include <cstdint>
#include <vector>
#include <string>
#include <map>
#include <set>

namespace mbgl {

using GlyphID = char16_t;
using GlyphIDs = std::set<GlyphID>;

// Note: this only works for the BMP
GlyphRange getGlyphRange(GlyphID glyph);

struct GlyphMetrics {
    uint32_t width = 0;
    uint32_t height = 0;
    int32_t left = 0;
    int32_t top = 0;
    uint32_t advance = 0;
};

inline bool operator==(const GlyphMetrics& lhs, const GlyphMetrics& rhs) {
    return lhs.width == rhs.width &&
        lhs.height == rhs.height &&
        lhs.left == rhs.left &&
        lhs.top == rhs.top &&
        lhs.advance == rhs.advance;
}

class Glyph {
public:
    // We're using this value throughout the Mapbox GL ecosystem. If this is different, the glyphs
    // also need to be reencoded.
    static constexpr const uint8_t borderSize = 3;

    GlyphID id = 0;

    // A signed distance field of the glyph with a border (see above).
    AlphaImage bitmap;

    // Glyph metrics
    GlyphMetrics metrics;
};

using Glyphs = std::map<GlyphID, optional<Immutable<Glyph>>>;
using GlyphMap = std::map<FontStackHash, Glyphs>;

class PositionedGlyph {
public:
    explicit PositionedGlyph(GlyphID glyph_,
                             float x_,
                             float y_,
                             bool vertical_,
                             FontStackHash font_,
                             float scale_,
                             Rect<uint16_t> rect_,
                             GlyphMetrics metrics_,
                             optional<std::string> imageID_,
                             std::size_t sectionIndex_ = 0)
        : glyph(glyph_),
          x(x_),
          y(y_),
          vertical(vertical_),
          font(font_),
          scale(scale_),
          rect(std::move(rect_)),
          metrics(std::move(metrics_)),
          imageID(std::move(imageID_)),
          sectionIndex(sectionIndex_) {}

    GlyphID glyph = 0;
    float x = 0;
    float y = 0;
    bool vertical = false;
    FontStackHash font = 0;
    float scale = 0.0;
    Rect<uint16_t> rect;
    GlyphMetrics metrics;
    optional<std::string> imageID;
    // Maps positioned glyph to TaggedString section
    std::size_t sectionIndex;
};

enum class WritingModeType : uint8_t;

struct PositionedLine {
    std::vector<PositionedGlyph> positionedGlyphs;
    float lineOffset = 0.0;
};

class Shaping {
    public:
    Shaping() = default;
    explicit Shaping(float x, float y, WritingModeType writingMode_)
        : top(y), bottom(y), left(x), right(x), writingMode(writingMode_) {}
    std::vector<PositionedLine> positionedLines;
    float top = 0;
    float bottom = 0;
    float left = 0;
    float right = 0;
    WritingModeType writingMode;
    explicit operator bool() const {
        return std::any_of(positionedLines.begin(), positionedLines.end(), [](const auto& line) {
            return !line.positionedGlyphs.empty();
        });
    }
    // The y offset *should* be part of the font metadata.
    static constexpr int32_t yOffset = -17;
    bool verticalizable = false;
    bool iconsInText = false;
};

enum class WritingModeType : uint8_t {
    None = 0,
    Horizontal = 1 << 0,
    Vertical = 1 << 1,
};

using GlyphDependencies = std::map<FontStack, GlyphIDs>;
using GlyphRangeDependencies = std::map<FontStack, std::unordered_set<GlyphRange>>;

} // end namespace mbgl