GLVis  v4.2
Accurate and flexible finite element visualization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
font.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-443271.
4 //
5 // This file is part of the GLVis visualization tool and library. For more
6 // information and source code availability see https://glvis.org.
7 //
8 // GLVis is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #include <vector>
13 
14 #include "font.hpp"
15 #include "aux_vis.hpp"
16 
17 struct vert_tex2d
18 {
19  float x, y;
20  float u, v;
21 
22  vert_tex2d(float x, float y, float u, float v)
23  : x(x), y(y), u(u), v(v) { }
24 };
25 
26 
27 const int font_scale = 64;
28 bool GlVisFont::LoadFont(const std::string& path, int font_index, int font_size)
29 {
30  if (!init)
31  {
32  return false;
33  }
34  if (font_init)
35  {
36  glDeleteTextures(1, &font_tex);
37  FT_Done_Face(face);
38  font_init = false;
39  }
40  if (FT_New_Face(library, path.c_str(), font_index, &face))
41  {
42  cout << "GlVisFont::LoadFont(): Cannot open font file: " << path << endl;
43  return false;
44  }
45  face_has_kerning = FT_HAS_KERNING(face);
46  int ppi_w, ppi_h;
47  GetAppWindow()->getDpi(ppi_w, ppi_h);
48  const bool use_fixed_ppi_h = true;
49  if (use_fixed_ppi_h)
50  {
51  double ratio = double(ppi_w)/ppi_h;
52  ppi_h = GetAppWindow()->isHighDpi() ? 192 : 96;
53  ppi_w = ratio*ppi_h + 0.5;
54 #ifdef GLVIS_DEBUG
55  cout << "Fonts use fixed ppi: " << ppi_w << " x " << ppi_h << endl;
56 #endif
57  }
58  if (FT_Set_Char_Size(face, 0, font_size*font_scale, ppi_w, ppi_h))
59  {
60  cout << "GlVisFont::LoadFont(): Cannot set font height: " << font_size
61  << " pts" << endl;
62  FT_Done_Face(face);
63  return false;
64  }
65 #ifdef GLVIS_DEBUG
66  cout << "Loaded font: " << path << ", index: " << font_index
67  << ", height: " << font_size << endl;
68 #endif
69 
70  // generate atlas
71  size_t w = 0, h = 0;
72  for (int c = 32; c < 128; c++)
73  {
74  if (FT_Load_Char(face, c, FT_LOAD_RENDER))
75  {
76  cout << "GlVisFont::LoadFont(): Cannot load glyph: " << (char) c << endl;
77  continue;
78  }
79  w += face->glyph->bitmap.width + 2;
80  if (h < size_t(face->glyph->bitmap.rows))
81  {
82  h = face->glyph->bitmap.rows;
83  }
84  }
85  tex_w = w;
86  tex_h = h + 2;
87 
88 #ifdef GLVIS_DEBUG
89  cout << "GlVisFont::LoadFont(): font texture dimensions are ("
90  << tex_w << ", " << tex_h << ")" << endl;
91 #endif
92 
93  glGenTextures(1, &font_tex);
94 
95  glActiveTexture(GL_TEXTURE0 + 1);
96  glBindTexture(GL_TEXTURE_2D, font_tex);
97  std::vector<uint8_t> zeros(tex_w * tex_h, 0);
98  GLenum alpha_internal_fmt = alpha_channel == GL_RED ? GL_R8 : GL_ALPHA;
99  glTexImage2D(GL_TEXTURE_2D, 0, alpha_internal_fmt, tex_w, tex_h, 0,
100  alpha_channel,
101  GL_UNSIGNED_BYTE, zeros.data());
102 
103  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
104  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
105 
106  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
107  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
108 
109  int x = 0;
110  for (int c = 32; c < 128; c++)
111  {
112  if (FT_Load_Char(face, c, FT_LOAD_RENDER))
113  {
114  cout << "GlVisFont::LoadFont(): Cannot load glyph: " << (char) c << endl;
115  continue;
116  }
117  FT_GlyphSlot glyph_slot = face->glyph;
118  glTexSubImage2D(GL_TEXTURE_2D,
119  0,
120  x + 1, 1,
121  glyph_slot->bitmap.width,
122  glyph_slot->bitmap.rows,
123  alpha_channel,
124  GL_UNSIGNED_BYTE,
125  glyph_slot->bitmap.buffer);
126  // To improve the rendering quality in some cases, we can utilize the
127  // 'lsb_delta' and 'rsb_delta' fields in 'glyph_slot'. These will need to
128  // be stored in the GlVisFont::glyph struct and used in the method
129  // bufferToDevice() of class CoreGLDevice and class FFGLDevice.
130  font_chars[c] =
131  {
132  (unsigned)(glyph_slot->bitmap.width + 2),
133  (unsigned)(glyph_slot->bitmap.rows + 2),
134  glyph_slot->bitmap_left,
135  glyph_slot->bitmap_top,
136  glyph_slot->advance.x / 64.f,
137  glyph_slot->advance.y / 64.f,
138  x / (float) w
139  };
140  x += glyph_slot->bitmap.width + 2;
141  }
142  font_init = true;
143  // glEnable(GL_TEXTURE_2D);
144  glActiveTexture(GL_TEXTURE0);
145  return true;
146 }
147 
148 void GlVisFont::getObjectSize(const std::string& text, int& w, int& h)
149 {
150  float pen_x = 0.f, pen_y = 0.f;
151  char prev_c = '\0';
152  int min_x = INT_MAX, max_x = INT_MIN;
153  int min_y = INT_MAX, max_y = INT_MIN;
154  for (char c : text)
155  {
156  const glyph &g = GetTexChar(c);
157  if (!g.w || !g.h) { continue; }
158  pen_x += GetKerning(prev_c, c);
159  // note: both g.w and g.h include padding of 2
160  // note: the x-direction bounds are not pixel-tight (include bear_x/adv_x)
161  // note: the y-direction bounds are pixel-tight
162  min_x = std::min(min_x, (int)floorf(pen_x));
163  max_x = std::max(max_x, (int)ceilf (pen_x + g.adv_x));
164  min_y = std::min(min_y, (int)floorf(pen_y + g.bear_y - (g.h - 2)));
165  max_y = std::max(max_y, (int)ceilf (pen_y + g.bear_y));
166  pen_x += g.adv_x;
167  pen_y += g.adv_y;
168  prev_c = c;
169  }
170  w = max_x - min_x;
171  h = max_y - min_y;
172 }
int32_t bear_y
Definition: font.hpp:32
float adv_x
Definition: font.hpp:33
float GetKerning(char cprev, char c)
Definition: font.hpp:82
bool isHighDpi() const
This property is set by createWindow().
Definition: sdl.hpp:224
SdlWindow * GetAppWindow()
Definition: aux_vis.cpp:58
uint32_t h
Definition: font.hpp:31
void getObjectSize(const std::string &text, int &w, int &h)
Get the width and height of the bounding box containing the rendered text.
Definition: font.cpp:148
const glyph & GetTexChar(char c) const
Definition: font.hpp:54
float adv_y
Definition: font.hpp:33
uint32_t w
Definition: font.hpp:31
bool LoadFont(const std::string &path, int font_index, int font_size)
Definition: font.cpp:28
void getDpi(int &wdpi, int &hdpi)
Definition: sdl.cpp:568
const int font_scale
Definition: font.cpp:27
int font_size
Definition: aux_vis.cpp:1641