Welcome to mirror list, hosted at ThFree Co, Russian Federation.

text_engine.h « software_renderer - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2b8dd59f8b8054078a51fef6a0d2d6143d30fa88 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#pragma once
#ifndef __ML__TEXT_ENGINE_H__
#define __ML__TEXT_ENGINE_H__

#include <string>
#include <stdexcept>
#include <map>
#include <vector>
#include <iostream>

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_STROKER_H

#include "point.h"
#include "rect.h"

#include "base/string_utils.hpp"

#include "std/utility.hpp"

namespace ml
{
class text_engine;

class face
{
  double m_height;
  double m_ascender;
  double m_descender;
  std::string m_face_name;
  size_t m_face_size;
  FT_Face m_face;
  bool m_flip_y;

  typedef std::map<FT_UInt, FT_Glyph> glyph_cache_type;

  ml::text_engine & m_engine;
  glyph_cache_type m_glyph_cache;

public:
  face();
  //		~face() {} // TODO: clear cache before exit

  bool flip_y() const { return m_flip_y; }
  void flip_y(bool f) { m_flip_y = f; }

  face(ml::text_engine & e, std::string const & name, size_t size);
  inline std::string const & face_name() const { return m_face_name; }
  inline size_t face_size() const { return m_face_size; }
  FT_Glyph glyph(unsigned int code, unsigned int prev_code = 0, ml::point_d * kerning = NULL);
  inline double ascender() const { return m_ascender; }
  inline double descender() const { return m_descender; }
  inline double height() const { return m_height; }
};

struct text_engine_exception : public std::runtime_error
{
  explicit text_engine_exception(std::string const & s) : std::runtime_error(s) {}
};

class text_renderer
{
protected:
  bool m_outline;

public:
  text_renderer() {}
  virtual void operator()(ml::point_d const & pt, size_t width, size_t height,
                          unsigned char const * data)
  {
  }
  bool outline() const { return m_outline; }
  void outline(bool f) { m_outline = f; }
  virtual double outlinewidth() const { return 0; }
};

class text_options
{
  bool m_flip_y;
  ml::point_d m_offset;
  size_t m_horizontal_align;
  size_t m_vertical_align;
  float m_linegap;
  float m_ascender;

public:
  explicit text_options(face const & f)
      : m_flip_y(f.flip_y()),
        m_offset(0, 0),
        m_horizontal_align(0),
        m_vertical_align(0),
        m_linegap(f.height()),
        m_ascender(f.ascender())
  {
  }

  bool flip_y() const { return m_flip_y; }
  bool flip_y(bool flip) { return (m_flip_y = flip); }

  ml::point_d const & offset() const { return m_offset; }
  ml::point_d const & offset(ml::point_d const & p) { return (m_offset = p); }

  size_t horizontal_align() const { return m_horizontal_align; }
  size_t horizontal_align(size_t v) { return m_horizontal_align = v; }

  size_t vertical_align() const { return m_vertical_align; }
  size_t vertical_align(size_t v) { return m_vertical_align = v; }

  float linegap() const { return m_linegap; }
  float linegap(float v) { return m_linegap = v; }

  float ascender() const { return m_ascender; }
  float ascender(float v) { return m_ascender = v; }
};

class text
{
public:
  class symbol_holder
  {
  public:
    ml::rect_d m_bounds;
    float advance;
    ml::point_d pt;
    float angle;
    unsigned int charcode;

    symbol_holder() : advance(0), angle(0.0), charcode(0) {}
    explicit symbol_holder(unsigned int code) : advance(0), angle(0.0), charcode(code) {}
    ml::rect_d const & bounds() const { return m_bounds; }
  };

  typedef symbol_holder symbol_type;
  typedef std::vector<symbol_type> text_type;

protected:
  struct string_range
  {
    size_t begin;
    size_t end;
    string_range() : begin(0), end(0) {}
    string_range(size_t b, size_t e) : begin(b), end(e) {}
  };

  typedef std::vector<string_range> string_array_type;

  text_type m_text;
  string_array_type m_string_array;
  ml::rect_d m_bounds;

public:
  enum text_align_e
  {
    align_center = 0,
    align_left = 1,
    align_right = 4,
    align_top = 8,
    align_bottom = 16
  };

  text() {}
  explicit text(strings::UniString const & src) { set_text(src); }

  void swap(text & t)
  {
    m_text.swap(t.m_text);
    m_string_array.swap(t.m_string_array);
    m_bounds = t.m_bounds;
  }

  void set_text(strings::UniString const & src);

  ml::rect_d const & calc_bounds(ml::face & face, double outlinewidth = 0);

  ml::rect_d const & bounds() const { return m_bounds; }

  bool is_intersect_with(ml::text const & t) const;
  bool is_intersect_with(ml::rect_d const & r) const;

  bool empty() const { return m_string_array.empty(); }

  void render(ml::face & face, text_renderer & renderer) const;
  void apply_font(ml::face & face, double symbol_space = 0.0);
  void warp(std::vector<ml::point_d> const & path, ml::text_options const & options);

  text_type const & symbols() const { return m_text; }

protected:
  bool is_whitespace(unsigned int ch) const;
  double string_width(text::string_range const & r) const;
  ml::rect_d const & calc_bounds(ml::face & face, symbol_holder & sym, double outlinewidth = 0);
  void render(ml::face & face, symbol_holder const & sym, text_renderer & renderer) const;
  void warp_text_line(string_range const & text_line, std::vector<ml::point_d> const & path,
                      ml::point_d & shift, bool flip);
};

class text_engine
{
  typedef std::map<std::string, FT_Face> face_map_type;
  typedef std::map<pair<size_t, size_t>, face> face_cache_type;
  FT_Library m_library;
  face_map_type m_faces;
  FT_Face m_current_face;
  face_cache_type m_cache;

  text_engine & select_face(std::string const & face_name);
  text_engine & set_size(size_t height, size_t width = 0);

public:
  ml::face & get_face(size_t font_key, std::string const & name, size_t size);
  FT_Face current_face() { return m_current_face; }

  text_engine & load_face(std::string const & face_name, std::string const & face_path);
  text_engine & load_face(std::string const & face_name, char const * face_data,
                          size_t face_data_size);
  text_engine();
  //        ~text_engine() {} // TODO: destroy all faces before exit
};

}  // namespace ml

#endif  // __ML__TEXT_ENGINE_H__