Blender  V3.3
blf_glyph.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2009 Blender Foundation. All rights reserved. */
3 
10 #include <math.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <ft2build.h>
16 
17 #include FT_FREETYPE_H
18 #include FT_GLYPH_H
19 #include FT_OUTLINE_H
20 #include FT_BITMAP_H
21 #include FT_ADVANCES_H /* For FT_Get_Advance. */
22 #include FT_MULTIPLE_MASTERS_H /* Variable font support. */
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "DNA_userdef_types.h"
27 #include "DNA_vec_types.h"
28 
29 #include "BLI_listbase.h"
30 #include "BLI_rect.h"
31 #include "BLI_threads.h"
32 
33 #include "BLF_api.h"
34 
35 #include "GPU_capabilities.h"
36 #include "GPU_immediate.h"
37 
38 #include "blf_internal.h"
39 #include "blf_internal_types.h"
40 
41 #include "BLI_math_vector.h"
42 #include "BLI_strict_flags.h"
43 #include "BLI_string_utf8.h"
44 
45 /* -------------------------------------------------------------------- */
52 static FT_Fixed to_16dot16(double val)
53 {
54  return (FT_Fixed)(lround(val * 65536.0));
55 }
56 
59 /* -------------------------------------------------------------------- */
63 static GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
64 {
65  GlyphCacheBLF *gc = (GlyphCacheBLF *)font->cache.first;
66  while (gc) {
67  if (gc->size == size && gc->dpi == dpi && (gc->bold == ((font->flags & BLF_BOLD) != 0)) &&
68  (gc->italic == ((font->flags & BLF_ITALIC) != 0)) &&
69  (gc->char_weight == font->char_weight) && (gc->char_slant == font->char_slant) &&
70  (gc->char_width == font->char_width) && (gc->char_spacing == font->char_spacing)) {
71  return gc;
72  }
73  gc = gc->next;
74  }
75  return NULL;
76 }
77 
79 {
80  GlyphCacheBLF *gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
81 
82  gc->next = NULL;
83  gc->prev = NULL;
84  gc->size = font->size;
85  gc->dpi = font->dpi;
86  gc->bold = ((font->flags & BLF_BOLD) != 0);
87  gc->italic = ((font->flags & BLF_ITALIC) != 0);
88  gc->char_weight = font->char_weight;
89  gc->char_slant = font->char_slant;
90  gc->char_width = font->char_width;
91  gc->char_spacing = font->char_spacing;
92 
93  memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
94  memset(gc->bucket, 0, sizeof(gc->bucket));
95 
96  /* Determine ideal fixed-width size for monospaced output. */
97  FT_UInt gindex = FT_Get_Char_Index(font->face, U'0');
98  if (gindex) {
99  FT_Fixed advance = 0;
100  FT_Get_Advance(font->face, gindex, FT_LOAD_NO_HINTING, &advance);
101  /* Use CSS 'ch unit' width, advance of zero character. */
102  gc->fixed_width = (int)(advance >> 16);
103  }
104  else {
105  /* Font does not contain "0" so use CSS fallback of 1/2 of em. */
106  gc->fixed_width = (int)((font->face->size->metrics.height / 2) >> 6);
107  }
108  if (gc->fixed_width < 1) {
109  gc->fixed_width = 1;
110  }
111 
112  BLI_addhead(&font->cache, gc);
113  return gc;
114 }
115 
117 {
119 
120  GlyphCacheBLF *gc = blf_glyph_cache_find(font, font->size, font->dpi);
121 
122  if (!gc) {
123  gc = blf_glyph_cache_new(font);
124  }
125 
126  return gc;
127 }
128 
130 {
132 }
133 
135 {
136  GlyphBLF *g;
137  for (uint i = 0; i < ARRAY_SIZE(gc->bucket); i++) {
138  while ((g = BLI_pophead(&gc->bucket[i]))) {
139  blf_glyph_free(g);
140  }
141  }
142  if (gc->texture) {
144  }
145  if (gc->bitmap_result) {
147  }
148  MEM_freeN(gc);
149 }
150 
152 {
153  GlyphCacheBLF *gc;
154 
156 
157  while ((gc = BLI_pophead(&font->cache))) {
159  }
160 
162 }
163 
170 {
171  if (charcode < GLYPH_ASCII_TABLE_SIZE) {
172  return gc->glyph_ascii_table[charcode];
173  }
174 
175  GlyphBLF *g = gc->bucket[blf_hash(charcode)].first;
176  while (g) {
177  if (g->c == charcode) {
178  return g;
179  }
180  g = g->next;
181  }
182  return NULL;
183 }
184 
189  FontBLF *font, GlyphCacheBLF *gc, FT_GlyphSlot glyph, uint charcode, FT_UInt glyph_index)
190 {
191  GlyphBLF *g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_get");
192  g->c = charcode;
193  g->idx = glyph_index;
194  g->advance_x = (ft_pix)glyph->advance.x;
195  g->pos[0] = glyph->bitmap_left;
196  g->pos[1] = glyph->bitmap_top;
197  g->dims[0] = (int)glyph->bitmap.width;
198  g->dims[1] = (int)glyph->bitmap.rows;
199  g->pitch = glyph->bitmap.pitch;
200 
201  FT_BBox bbox;
202  FT_Outline_Get_CBox(&(glyph->outline), &bbox);
203  g->box_xmin = (ft_pix)bbox.xMin;
204  g->box_xmax = (ft_pix)bbox.xMax;
205  g->box_ymin = (ft_pix)bbox.yMin;
206  g->box_ymax = (ft_pix)bbox.yMax;
207 
208  /* Used to improve advance when hinting is enabled. */
209  g->lsb_delta = (ft_pix)glyph->lsb_delta;
210  g->rsb_delta = (ft_pix)glyph->rsb_delta;
211 
212  const int buffer_size = (int)(glyph->bitmap.width * glyph->bitmap.rows);
213  if (buffer_size != 0) {
214  if (font->flags & BLF_MONOCHROME) {
215  /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range. */
216  for (int i = 0; i < buffer_size; i++) {
217  glyph->bitmap.buffer[i] = glyph->bitmap.buffer[i] ? 255 : 0;
218  }
219  }
220  g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap");
221  memcpy(g->bitmap, glyph->bitmap.buffer, (size_t)buffer_size);
222  }
223 
224  unsigned int key = blf_hash(g->c);
225  BLI_addhead(&(gc->bucket[key]), g);
226  if (charcode < GLYPH_ASCII_TABLE_SIZE) {
227  gc->glyph_ascii_table[charcode] = g;
228  }
229 
230  return g;
231 }
232 
233 /* This table can be used to find a coverage bit based on a charcode. later we can get default
234  * language and script from codepoint. */
235 
236 typedef struct eUnicodeBlock {
237  unsigned int first;
238  unsigned int last;
239  int coverage_bit; /* 0-122. -1 is N/A. */
240  /* Later we add primary script and language for Harfbuzz, data from
241  * https://en.wikipedia.org/wiki/Unicode_block */
243 
245  /* Must be in ascending order by start of range. */
246  {0x0, 0x7F, 0}, /* Basic Latin. */
247  {0x80, 0xFF, 1}, /* Latin-1 Supplement. */
248  {0x100, 0x17F, 2}, /* Latin Extended-A. */
249  {0x180, 0x24F, 3}, /* Latin Extended-B. */
250  {0x250, 0x2AF, 4}, /* IPA Extensions. */
251  {0x2B0, 0x2FF, 5}, /* Spacing Modifier Letters. */
252  {0x300, 0x36F, 6}, /* Combining Diacritical Marks. */
253  {0x370, 0x3FF, 7}, /* Greek. */
254  {0x400, 0x52F, 9}, /* Cyrillic. */
255  {0x530, 0x58F, 10}, /* Armenian. */
256  {0x590, 0x5FF, 11}, /* Hebrew. */
257  {0x600, 0x6FF, 13}, /* Arabic. */
258  {0x700, 0x74F, 71}, /* Syriac. */
259  {0x750, 0x77F, 13}, /* Arabic Supplement. */
260  {0x780, 0x7BF, 72}, /* Thaana. */
261  {0x7C0, 0x7FF, 14}, /* NKo. */
262  {0x800, 0x83F, -1}, /* Samaritan. */
263  {0x840, 0x85F, -1}, /* Mandaic. */
264  {0x900, 0x97F, 15}, /* Devanagari. */
265  {0x980, 0x9FF, 16}, /* Bengali. */
266  {0xA00, 0xA7F, 17}, /* Gurmukhi. */
267  {0xA80, 0xAFF, 18}, /* Gujarati. */
268  {0xB00, 0xB7F, 19}, /* Oriya. */
269  {0xB80, 0xBFF, 20}, /* Tamil. */
270  {0xC00, 0xC7F, 21}, /* Telugu. */
271  {0xC80, 0xCFF, 22}, /* Kannada. */
272  {0xD00, 0xD7F, 23}, /* Malayalam. */
273  {0xD80, 0xDFF, 73}, /* Sinhala. */
274  {0xE00, 0xE7F, 24}, /* Thai. */
275  {0xE80, 0xEFF, 25}, /* Lao. */
276  {0xF00, 0xFFF, 70}, /* Tibetan. */
277  {0x1000, 0x109F, 74}, /* Myanmar. */
278  {0x10A0, 0x10FF, 26}, /* Georgian. */
279  {0x1100, 0x11FF, 28}, /* Hangul Jamo. */
280  {0x1200, 0x139F, 75}, /* Ethiopic. */
281  {0x13A0, 0x13FF, 76}, /* Cherokee. */
282  {0x1400, 0x167F, 77}, /* Canadian Aboriginal. */
283  {0x1680, 0x169F, 78}, /* Ogham. */
284  {0x16A0, 0x16FF, 79}, /* unic. */
285  {0x1700, 0x171F, 84}, /* Tagalog. */
286  {0x1720, 0x173F, 84}, /* Hanunoo. */
287  {0x1740, 0x175F, 84}, /* Buhid. */
288  {0x1760, 0x177F, 84}, /* Tagbanwa. */
289  {0x1780, 0x17FF, 80}, /* Khmer. */
290  {0x1800, 0x18AF, 81}, /* Mongolian. */
291  {0x1900, 0x194F, 93}, /* Limbu. */
292  {0x1950, 0x197F, 94}, /* Tai Le. */
293  {0x1980, 0x19DF, 95}, /* New Tai Lue". */
294  {0x19E0, 0x19FF, 80}, /* Khmer. */
295  {0x1A00, 0x1A1F, 96}, /* Buginese. */
296  {0x1A20, 0x1AAF, -1}, /* Tai Tham. */
297  {0x1B00, 0x1B7F, 27}, /* Balinese. */
298  {0x1B80, 0x1BBF, 112}, /* Sundanese. */
299  {0x1BC0, 0x1BFF, -1}, /* Batak. */
300  {0x1C00, 0x1C4F, 113}, /* Lepcha. */
301  {0x1C50, 0x1C7F, 114}, /* Ol Chiki. */
302  {0x1D00, 0x1DBF, 4}, /* IPA Extensions. */
303  {0x1DC0, 0x1DFF, 6}, /* Combining Diacritical Marks. */
304  {0x1E00, 0x1EFF, 29}, /* Latin Extended Additional. */
305  {0x1F00, 0x1FFF, 30}, /* Greek Extended. */
306  {0x2000, 0x206F, 31}, /* General Punctuation. */
307  {0x2070, 0x209F, 32}, /* Superscripts And Subscripts. */
308  {0x20A0, 0x20CF, 33}, /* Currency Symbols. */
309  {0x20D0, 0x20FF, 34}, /* Combining Diacritical Marks For Symbols. */
310  {0x2100, 0x214F, 35}, /* Letterlike Symbols. */
311  {0x2150, 0x218F, 36}, /* Number Forms. */
312  {0x2190, 0x21FF, 37}, /* Arrows. */
313  {0x2200, 0x22FF, 38}, /* Mathematical Operators. */
314  {0x2300, 0x23FF, 39}, /* Miscellaneous Technical. */
315  {0x2400, 0x243F, 40}, /* Control Pictures. */
316  {0x2440, 0x245F, 41}, /* Optical Character Recognition. */
317  {0x2460, 0x24FF, 42}, /* Enclosed Alphanumerics. */
318  {0x2500, 0x257F, 43}, /* Box Drawing. */
319  {0x2580, 0x259F, 44}, /* Block Elements. */
320  {0x25A0, 0x25FF, 45}, /* Geometric Shapes. */
321  {0x2600, 0x26FF, 46}, /* Miscellaneous Symbols. */
322  {0x2700, 0x27BF, 47}, /* Dingbats. */
323  {0x27C0, 0x27EF, 38}, /* Mathematical Operators. */
324  {0x27F0, 0x27FF, 37}, /* Arrows. */
325  {0x2800, 0x28FF, 82}, /* Braille. */
326  {0x2900, 0x297F, 37}, /* Arrows. */
327  {0x2980, 0x2AFF, 38}, /* Mathematical Operators. */
328  {0x2B00, 0x2BFF, 37}, /* Arrows. */
329  {0x2C00, 0x2C5F, 97}, /* Glagolitic. */
330  {0x2C60, 0x2C7F, 29}, /* Latin Extended Additional. */
331  {0x2C80, 0x2CFF, 8}, /* Coptic. */
332  {0x2D00, 0x2D2F, 26}, /* Georgian. */
333  {0x2D30, 0x2D7F, 98}, /* Tifinagh. */
334  {0x2D80, 0x2DDF, 75}, /* Ethiopic. */
335  {0x2DE0, 0x2DFF, 9}, /* Cyrillic. */
336  {0x2E00, 0x2E7F, 31}, /* General Punctuation. */
337  {0x2E80, 0x2FFF, 59}, /* CJK Unified Ideographs. */
338  {0x3000, 0x303F, 48}, /* CJK Symbols And Punctuation. */
339  {0x3040, 0x309F, 49}, /* Hiragana. */
340  {0x30A0, 0x30FF, 50}, /* Katakana. */
341  {0x3100, 0x312F, 51}, /* Bopomofo. */
342  {0x3130, 0x318F, 52}, /* Hangul Compatibility Jamo. */
343  {0x3190, 0x319F, 59}, /* CJK Unified Ideographs. */
344  {0x31A0, 0x31BF, 51}, /* Bopomofo. */
345  {0x31C0, 0x31EF, 59}, /* CJK Unified Ideographs. */
346  {0x31F0, 0x31FF, 50}, /* Katakana. */
347  {0x3200, 0x32FF, 54}, /* Enclosed CJK Letters And Months. */
348  {0x3300, 0x33FF, 55}, /* CJK Compatibility. */
349  {0x3400, 0x4DBF, 59}, /* CJK Unified Ideographs. */
350  {0x4DC0, 0x4DFF, 99}, /* Yijing. */
351  {0x4E00, 0x9FFF, 59}, /* CJK Unified Ideographs. */
352  {0xA000, 0xA4CF, 83}, /* Yi. */
353  {0xA4D0, 0xA4FF, -1}, /* Lisu. */
354  {0xA500, 0xA63F, 12}, /* Vai. */
355  {0xA640, 0xA69F, 9}, /* Cyrillic. */
356  {0xA6A0, 0xA6FF, -1}, /* Bamum. */
357  {0xA700, 0xA71F, 5}, /* Spacing Modifier Letters. */
358  {0xA720, 0xA7FF, 29}, /* Latin Extended Additional. */
359  {0xA800, 0xA82F, 100}, /* Syloti Nagri. */
360  {0xA840, 0xA87F, 53}, /* Phags-pa. */
361  {0xA880, 0xA8DF, 115}, /* Saurashtra. */
362  {0xA900, 0xA92F, 116}, /* Kayah Li. */
363  {0xA930, 0xA95F, 117}, /* Rejang. */
364  {0xA960, 0xA97F, 56}, /* Hangul Syllables. */
365  {0xA980, 0xA9DF, -1}, /* Javanese. */
366  {0xA9E0, 0xA9FF, 74}, /* Myanmar. */
367  {0xAA00, 0xAA5F, 118}, /* Cham. */
368  {0xAA60, 0xAA7F, 74}, /* Myanmar. */
369  {0xAA80, 0xAADF, -1}, /* Tai Viet. */
370  {0xAAE0, 0xAAFF, -1}, /* Meetei Mayek. */
371  {0xAB00, 0xAB2F, 75}, /* Ethiopic. */
372  {0xAB70, 0xABBF, 76}, /* Cherokee. */
373  {0xABC0, 0xABFF, -1}, /* Meetei Mayek. */
374  {0xAC00, 0xD7AF, 56}, /* Hangul Syllables. */
375  {0xD800, 0xDFFF, 57}, /* Non-Plane 0. */
376  {0xE000, 0xF6FF, 60}, /* Private Use Area. */
377  {0xE700, 0xEFFF, -1}, /* MS Wingdings. */
378  {0xF000, 0xF8FF, -1}, /* MS Symbols. */
379  {0xF900, 0xFAFF, 61}, /* CJK Compatibility Ideographs. */
380  {0xFB00, 0xFB4F, 62}, /* Alphabetic Presentation Forms. */
381  {0xFB50, 0xFDFF, 63}, /* Arabic Presentation Forms-A. */
382  {0xFE00, 0xFE0F, 91}, /* Variation Selectors. */
383  {0xFE10, 0xFE1F, 65}, /* CJK Compatibility Forms. */
384  {0xFE20, 0xFE2F, 64}, /* Combining Half Marks. */
385  {0xFE30, 0xFE4F, 65}, /* CJK Compatibility Forms. */
386  {0xFE50, 0xFE6F, 66}, /* Small Form Variants. */
387  {0xFE70, 0xFEFF, 67}, /* Arabic Presentation Forms-B. */
388  {0xFF00, 0xFFEF, 68}, /* Half-width And Full-width Forms. */
389  {0xFFF0, 0xFFFF, 69}, /* Specials. */
390  {0x10000, 0x1013F, 101}, /* Linear B. */
391  {0x10140, 0x1018F, 102}, /* Ancient Greek Numbers. */
392  {0x10190, 0x101CF, 119}, /* Ancient Symbols. */
393  {0x101D0, 0x101FF, 120}, /* Phaistos Disc. */
394  {0x10280, 0x1029F, 121}, /* Lycian. */
395  {0x102A0, 0x102DF, 121}, /* Carian. */
396  {0x10300, 0x1032F, 85}, /* Old Italic. */
397  {0x10330, 0x1034F, 86}, /* Gothic. */
398  {0x10350, 0x1037F, -1}, /* Old Permic. */
399  {0x10380, 0x1039F, 103}, /* Ugaritic. */
400  {0x103A0, 0x103DF, 104}, /* Old Persian. */
401  {0x10400, 0x1044F, 87}, /* Deseret. */
402  {0x10450, 0x1047F, 105}, /* Shavian. */
403  {0x10480, 0x104AF, 106}, /* Osmanya. */
404  {0x104B0, 0x104FF, -1}, /* Osage. */
405  {0x10500, 0x1052F, -1}, /* Elbasan. */
406  {0x10530, 0x1056F, -1}, /* Caucasian Albanian. */
407  {0x10570, 0x105BF, -1}, /* Vithkuqi. */
408  {0x10600, 0x1077F, -1}, /* Linear A. */
409  {0x10780, 0x107BF, 3}, /* Latin Extended-B. */
410  {0x10800, 0x1083F, 107}, /* Cypriot Syllabary. */
411  {0x10840, 0x1085F, -1}, /* Imperial Aramaic. */
412  {0x10860, 0x1087F, -1}, /* Palmyrene. */
413  {0x10880, 0x108AF, -1}, /* Nabataean. */
414  {0x108E0, 0x108FF, -1}, /* Hatran. */
415  {0x10900, 0x1091F, 58}, /* Phoenician. */
416  {0x10920, 0x1093F, 121}, /* Lydian. */
417  {0x10980, 0x1099F, -1}, /* Meroitic Hieroglyphs. */
418  {0x109A0, 0x109FF, -1}, /* Meroitic Cursive. */
419  {0x10A00, 0x10A5F, 108}, /* Kharoshthi. */
420  {0x10A60, 0x10A7F, -1}, /* Old South Arabian. */
421  {0x10A80, 0x10A9F, -1}, /* Old North Arabian. */
422  {0x10AC0, 0x10AFF, -1}, /* Manichaean. */
423  {0x10B00, 0x10B3F, -1}, /* Avestan. */
424  {0x10B40, 0x10B5F, -1}, /* Inscriptional Parthian. */
425  {0x10B60, 0x10B7F, -1}, /* Inscriptional Pahlavi. */
426  {0x10B80, 0x10BAF, -1}, /* Psalter Pahlavi. */
427  {0x10C00, 0x10C4F, -1}, /* Old Turkic. */
428  {0x10C80, 0x10CFF, -1}, /* Old Hungarian. */
429  {0x10D00, 0x10D3F, -1}, /* Hanifi Rohingya. */
430  {0x108E0, 0x10E7F, -1}, /* Rumi Numeral Symbols. */
431  {0x10E80, 0x10EBF, -1}, /* Yezidi. */
432  {0x10F00, 0x10F2F, -1}, /* Old Sogdian. */
433  {0x10F30, 0x10F6F, -1}, /* Sogdian. */
434  {0x10F70, 0x10FAF, -1}, /* Old Uyghur. */
435  {0x10FB0, 0x10FDF, -1}, /* Chorasmian. */
436  {0x10FE0, 0x10FFF, -1}, /* Elymaic. */
437  {0x11000, 0x1107F, -1}, /* Brahmi. */
438  {0x11080, 0x110CF, -1}, /* Kaithi. */
439  {0x110D0, 0x110FF, -1}, /* Sora Sompeng. */
440  {0x11100, 0x1114F, -1}, /* Chakma. */
441  {0x11150, 0x1117F, -1}, /* Mahajani. */
442  {0x11180, 0x111DF, -1}, /* Sharada. */
443  {0x111E0, 0x111FF, -1}, /* Sinhala Archaic Numbers. */
444  {0x11200, 0x1124F, -1}, /* Khojki. */
445  {0x11280, 0x112AF, -1}, /* Multani. */
446  {0x112B0, 0x112FF, -1}, /* Khudawadi. */
447  {0x11300, 0x1137F, -1}, /* Grantha. */
448  {0x11400, 0x1147F, -1}, /* Newa. */
449  {0x11480, 0x114DF, -1}, /* Tirhuta. */
450  {0x11580, 0x115FF, -1}, /* Siddham. */
451  {0x11600, 0x1165F, -1}, /* Modi. */
452  {0x11660, 0x1167F, 81}, /* Mongolian. */
453  {0x11680, 0x116CF, -1}, /* Takri. */
454  {0x11700, 0x1174F, -1}, /* Ahom. */
455  {0x11800, 0x1184F, -1}, /* Dogra. */
456  {0x118A0, 0x118FF, -1}, /* Warang Citi. */
457  {0x11900, 0x1195F, -1}, /* Dives Akuru. */
458  {0x119A0, 0x119FF, -1}, /* Nandinagari. */
459  {0x11A00, 0x11A4F, -1}, /* Zanabazar Square. */
460  {0x11A50, 0x11AAF, -1}, /* Soyombo. */
461  {0x11AB0, 0x11ABF, 77}, /* Canadian Aboriginal Syllabics. */
462  {0x11AC0, 0x11AFF, -1}, /* Pau Cin Hau. */
463  {0x11C00, 0x11C6F, -1}, /* Bhaiksuki. */
464  {0x11C70, 0x11CBF, -1}, /* Marchen. */
465  {0x11D00, 0x11D5F, -1}, /* Masaram Gondi. */
466  {0x11D60, 0x11DAF, -1}, /* Gunjala Gondi. */
467  {0x11EE0, 0x11EFF, -1}, /* Makasar. */
468  {0x11FB0, 0x11FBF, -1}, /* Lisu. */
469  {0x11FC0, 0x11FFF, 20}, /* Tamil. */
470  {0x12000, 0x1254F, 110}, /* Cuneiform. */
471  {0x12F90, 0x12FFF, -1}, /* Cypro-Minoan. */
472  {0x13000, 0x1343F, -1}, /* Egyptian Hieroglyphs. */
473  {0x14400, 0x1467F, -1}, /* Anatolian Hieroglyphs. */
474  {0x16800, 0x16A3F, -1}, /* Bamum. */
475  {0x16A40, 0x16A6F, -1}, /* Mro. */
476  {0x16A70, 0x16ACF, -1}, /* Tangsa. */
477  {0x16AD0, 0x16AFF, -1}, /* Bassa Vah. */
478  {0x16B00, 0x16B8F, -1}, /* Pahawh Hmong. */
479  {0x16E40, 0x16E9F, -1}, /* Medefaidrin. */
480  {0x16F00, 0x16F9F, -1}, /* Miao. */
481  {0x16FE0, 0x16FFF, -1}, /* Ideographic Symbols. */
482  {0x17000, 0x18AFF, -1}, /* Tangut. */
483  {0x1B170, 0x1B2FF, -1}, /* Nushu. */
484  {0x1BC00, 0x1BC9F, -1}, /* Duployan. */
485  {0x1D000, 0x1D24F, 88}, /* Musical Symbols. */
486  {0x1D2E0, 0x1D2FF, -1}, /* Mayan Numerals. */
487  {0x1D300, 0x1D35F, 109}, /* Tai Xuan Jing. */
488  {0x1D360, 0x1D37F, 111}, /* Counting Rod Numerals. */
489  {0x1D400, 0x1D7FF, 89}, /* Mathematical Alphanumeric Symbols. */
490  {0x1E2C0, 0x1E2FF, -1}, /* Wancho. */
491  {0x1E800, 0x1E8DF, -1}, /* Mende Kikakui. */
492  {0x1E900, 0x1E95F, -1}, /* Adlam. */
493  {0x1EC70, 0x1ECBF, -1}, /* Indic Siyaq Numbers. */
494  {0x1F000, 0x1F02F, 122}, /* Mahjong Tiles. */
495  {0x1F030, 0x1F09F, 122}, /* Domino Tiles. */
496  {0x1F600, 0x1F64F, -1}, /* Emoticons. */
497  {0x20000, 0x2A6DF, 59}, /* CJK Unified Ideographs. */
498  {0x2F800, 0x2FA1F, 61}, /* CJK Compatibility Ideographs. */
499  {0xE0000, 0xE007F, 92}, /* Tags. */
500  {0xE0100, 0xE01EF, 91}, /* Variation Selectors. */
501  {0xF0000, 0x10FFFD, 90}}; /* Private Use Supplementary. */
502 
503 /* Find a unicode block that a charcode belongs to. */
505 {
506  if (charcode < 0x80) {
507  /* Shortcut to Basic Latin. */
508  return &unicode_blocks[0];
509  }
510 
511  /* Binary search for other blocks. */
512 
513  int min = 0;
514  int max = ARRAY_SIZE(unicode_blocks) - 1;
515  int mid;
516 
517  if (charcode < unicode_blocks[0].first || charcode > unicode_blocks[max].last) {
518  return NULL;
519  }
520 
521  while (max >= min) {
522  mid = (min + max) / 2;
523  if (charcode > unicode_blocks[mid].last) {
524  min = mid + 1;
525  }
526  else if (charcode < unicode_blocks[mid].first) {
527  max = mid - 1;
528  }
529  else {
530  return &unicode_blocks[mid];
531  }
532  }
533 
534  return NULL;
535 }
536 
537 static int blf_charcode_to_coverage_bit(uint charcode)
538 {
539  int coverage_bit = -1;
540  eUnicodeBlock *block = blf_charcode_to_unicode_block(charcode);
541  if (block) {
542  coverage_bit = block->coverage_bit;
543  }
544 
545  if (coverage_bit < 0 && charcode > 0xFFFF) {
546  /* No coverage bit, but OpenType specs v.1.3+ says bit 57 implies that there
547  * are codepoints supported beyond the BMP, so only check fonts with this set. */
548  coverage_bit = 57;
549  }
550 
551  return coverage_bit;
552 }
553 
554 static bool blf_font_has_coverage_bit(FontBLF *font, int coverage_bit)
555 {
556  if (coverage_bit < 0) {
557  return false;
558  }
559  return (font->UnicodeRanges[(uint)coverage_bit >> 5] & (1u << ((uint)coverage_bit % 32)));
560 }
561 
566 static FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode)
567 {
568  FT_UInt glyph_index = FT_Get_Char_Index((*font)->face, charcode);
569  if (glyph_index) {
570  return glyph_index;
571  }
572 
573  /* Not found in main font, so look in the others. */
574  FontBLF *last_resort = NULL;
575  int coverage_bit = blf_charcode_to_coverage_bit(charcode);
576  for (int i = 0; i < BLF_MAX_FONT; i++) {
577  FontBLF *f = global_font[i];
578  if (!f || f == *font || !(f->flags & BLF_DEFAULT)) {
579  continue;
580  }
581 
582  if (f->flags & BLF_LAST_RESORT) {
583  last_resort = f;
584  continue;
585  }
586  if (coverage_bit < 0 || blf_font_has_coverage_bit(f, coverage_bit)) {
587  glyph_index = FT_Get_Char_Index(f->face, charcode);
588  if (glyph_index) {
589  *font = f;
590  return glyph_index;
591  }
592  }
593  }
594 
595  /* Not found in the stack, return from Last Resort if there is one. */
596  if (last_resort) {
597  glyph_index = FT_Get_Char_Index(last_resort->face, charcode);
598  if (glyph_index) {
599  *font = last_resort;
600  return glyph_index;
601  }
602  }
603 
604  return 0;
605 }
606 
610 static FT_GlyphSlot blf_glyph_load(FontBLF *font, FT_UInt glyph_index)
611 {
612  int load_flags;
613 
614  if (font->flags & BLF_MONOCHROME) {
615  load_flags = FT_LOAD_TARGET_MONO;
616  }
617  else {
618  load_flags = FT_LOAD_NO_BITMAP;
619  if (font->flags & BLF_HINTING_NONE) {
620  load_flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
621  }
622  else if (font->flags & BLF_HINTING_SLIGHT) {
623  load_flags |= FT_LOAD_TARGET_LIGHT;
624  }
625  else if (font->flags & BLF_HINTING_FULL) {
626  load_flags |= FT_LOAD_TARGET_NORMAL;
627  }
628  else {
629  /* Default, hinting disabled until FreeType has been upgraded
630  * to give good results on all platforms. */
631  load_flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
632  }
633  }
634 
635  if (FT_Load_Glyph(font->face, glyph_index, load_flags) == FT_Err_Ok) {
636  return font->face->glyph;
637  }
638  return NULL;
639 }
640 
644 static bool blf_glyph_render_bitmap(FontBLF *font, FT_GlyphSlot glyph)
645 {
646  int render_mode;
647 
648  if (font->flags & BLF_MONOCHROME) {
649  render_mode = FT_RENDER_MODE_MONO;
650  }
651  else {
652  render_mode = FT_RENDER_MODE_NORMAL;
653  }
654 
655  /* Render the glyph curves to a bitmap. */
656  FT_Error err = FT_Render_Glyph(glyph, render_mode);
657  if (err != FT_Err_Ok) {
658  return false;
659  }
660 
661  FT_Bitmap tempbitmap;
662 
663  if (font->flags & BLF_MONOCHROME) {
664  /* Convert result from 1 bit per pixel to 8 bit per pixel */
665  /* Accumulate errors for later, fine if not interested beyond "ok vs any error" */
666  FT_Bitmap_New(&tempbitmap);
667 
668  /* Does Blender use Pitch 1 always? It works so far */
669  err += FT_Bitmap_Convert(font->ft_lib, &glyph->bitmap, &tempbitmap, 1);
670  err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &glyph->bitmap);
671  err += FT_Bitmap_Done(font->ft_lib, &tempbitmap);
672  }
673 
674  if (err || glyph->format != FT_GLYPH_FORMAT_BITMAP) {
675  return false;
676  }
677 
678  return true;
679 }
680 
683 /* -------------------------------------------------------------------- */
694 static FT_Var_Axis *blf_var_axis_by_tag(FT_MM_Var *variations, uint tag, int *axis_index)
695 {
696  *axis_index = -1;
697  if (!variations) {
698  return NULL;
699  }
700  for (int i = 0; i < (int)variations->num_axis; i++) {
701  if (variations->axis[i].tag == tag) {
702  *axis_index = i;
703  return &(variations->axis)[i];
704  break;
705  }
706  }
707  return NULL;
708 }
709 
716 static FT_Fixed blf_factor_to_coordinate(FT_Var_Axis *axis, float factor)
717 {
718  FT_Fixed value = axis->def;
719  if (factor > 0) {
720  /* Map 0-1 to axis->def - axis->maximum */
721  value += (FT_Fixed)((double)(axis->maximum - axis->def) * factor);
722  }
723  else if (factor < 0) {
724  /* Map -1-0 to axis->minimum - axis->def */
725  value += (FT_Fixed)((double)(axis->def - axis->minimum) * factor);
726  }
727  return value;
728 }
729 
738  FT_Fixed coords[],
739  uint tag,
740  float factor)
741 {
742  int axis_index;
743  FT_Var_Axis *axis = blf_var_axis_by_tag(font->variations, tag, &axis_index);
744  if (axis && (axis_index < BLF_VARIATIONS_MAX)) {
745  coords[axis_index] = blf_factor_to_coordinate(axis, factor);
746  return true;
747  }
748  return false;
749 }
750 
758 static bool blf_glyph_set_variation_float(FontBLF *font, FT_Fixed coords[], uint tag, float value)
759 {
760  int axis_index;
761  FT_Var_Axis *axis = blf_var_axis_by_tag(font->variations, tag, &axis_index);
762  if (axis && (axis_index < BLF_VARIATIONS_MAX)) {
763  FT_Fixed int_value = to_16dot16(value);
764  CLAMP(int_value, axis->minimum, axis->maximum);
765  coords[axis_index] = int_value;
766  return true;
767  }
768  return false;
769 }
770 
773 /* -------------------------------------------------------------------- */
782 static bool blf_glyph_transform_weight(FT_GlyphSlot glyph, float factor, bool monospaced)
783 {
784  if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
785  /* Fake bold if the font does not have this variable axis. */
786  const FT_Pos average_width = FT_MulFix(glyph->face->units_per_EM,
787  glyph->face->size->metrics.x_scale);
788  FT_Pos change = (FT_Pos)((float)average_width * factor * 0.1f);
789  FT_Outline_EmboldenXY(&glyph->outline, change, change / 2);
790  if (monospaced) {
791  /* Widened fixed-pitch font needs a nudge left. */
792  FT_Outline_Translate(&glyph->outline, change / -2, 0);
793  }
794  else {
795  /* Need to increase advance. */
796  glyph->advance.x += change;
797  glyph->advance.y += change / 2;
798  }
799  return true;
800  }
801  return false;
802 }
803 
811 static bool blf_glyph_transform_slant(FT_GlyphSlot glyph, float factor)
812 {
813  if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
814  FT_Matrix transform = {to_16dot16(1), to_16dot16(factor / 2.0f), 0, to_16dot16(1)};
815  FT_Outline_Transform(&glyph->outline, &transform);
816  return true;
817  }
818  return false;
819 }
820 
826 static bool blf_glyph_transform_width(FT_GlyphSlot glyph, float factor)
827 {
828  if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
829  float scale = (factor * 0.4f) + 1.0f; /* 0.6f - 1.4f */
830  FT_Matrix matrix = {to_16dot16(scale), 0, 0, to_16dot16(1)};
831  FT_Outline_Transform(&glyph->outline, &matrix);
832  glyph->advance.x = (FT_Pos)((double)glyph->advance.x * scale);
833  return true;
834  }
835  return false;
836 }
837 
843 static bool blf_glyph_transform_spacing(FT_GlyphSlot glyph, float factor)
844 {
845  if (glyph->advance.x > 0) {
846  const long int size = glyph->face->size->metrics.height;
847  glyph->advance.x += (FT_Pos)(factor * (float)size / 6.0f);
848  return true;
849  }
850  return false;
851 }
852 
856 static bool blf_glyph_transform_monospace(FT_GlyphSlot glyph, int width)
857 {
858  if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
859  FT_Fixed current = glyph->linearHoriAdvance;
860  FT_Fixed target = width << 16; /* Do math in 16.16 values. */
861  if (target < current) {
862  const FT_Pos embolden = (FT_Pos)((current - target) >> 13);
863  /* Horizontally widen strokes to counteract narrowing. */
864  FT_Outline_EmboldenXY(&glyph->outline, embolden, 0);
865  const float scale = (float)(target - (embolden << 9)) / (float)current;
866  FT_Matrix matrix = {to_16dot16(scale), 0, 0, to_16dot16(1)};
867  FT_Outline_Transform(&glyph->outline, &matrix);
868  }
869  else if (target > current) {
870  /* Center narrow glyphs. */
871  FT_Outline_Translate(&glyph->outline, (FT_Pos)((target - current) >> 11), 0);
872  }
873  glyph->advance.x = width << 6;
874  return true;
875  }
876  return false;
877 }
878 
881 /* -------------------------------------------------------------------- */
888 static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font,
889  FontBLF *glyph_font,
890  FT_UInt glyph_index,
891  uint charcode,
892  int fixed_width)
893 {
894  if (glyph_font != settings_font) {
895  FT_Set_Char_Size(glyph_font->face,
896  0,
897  ((FT_F26Dot6)(settings_font->size)) * 64,
898  settings_font->dpi,
899  settings_font->dpi);
900  glyph_font->size = settings_font->size;
901  glyph_font->dpi = settings_font->dpi;
902  }
903 
904  /* We need to keep track if changes are still needed. */
905  bool weight_done = false;
906  bool slant_done = false;
907  bool width_done = false;
908  bool spacing_done = false;
909 
910  /* 70% of maximum weight results in the same amount of boldness and horizontal
911  * expansion as the bold version `DejaVuSans-Bold.ttf` of our default font.
912  * Worth reevaluating if we change default font. */
913  float weight = (settings_font->flags & BLF_BOLD) ? 0.7f : settings_font->char_weight;
914 
915  /* 37.5% of maximum rightward slant results in 6 degree slope, matching italic
916  * version `DejaVuSans-Oblique.ttf` of our current font. But a nice median when
917  * checking others. Worth reevaluating if we change default font. We could also
918  * narrow the glyph slightly as most italics do, but this one does not. */
919  float slant = (settings_font->flags & BLF_ITALIC) ? 0.375f : settings_font->char_slant;
920 
921  float width = settings_font->char_width;
922  float spacing = settings_font->char_spacing;
923 
924  /* Font variations need to be set before glyph loading. Even if new value is zero. */
925 
926  if (glyph_font->variations) {
927  FT_Fixed coords[BLF_VARIATIONS_MAX];
928  /* Load current design coordinates. */
929  FT_Get_Var_Design_Coordinates(glyph_font->face, BLF_VARIATIONS_MAX, &coords[0]);
930  /* Update design coordinates with new values. */
932  glyph_font, coords, blf_variation_axis_weight, weight);
934  glyph_font, coords, blf_variation_axis_slant, slant);
936  glyph_font, coords, blf_variation_axis_width, width);
937  spacing_done = blf_glyph_set_variation_normalized(
938  glyph_font, coords, blf_variation_axis_spacing, spacing);
939  /* Optical size, if available, is set to current font size. */
941  glyph_font, coords, blf_variation_axis_optsize, settings_font->size);
942  /* Save updated design coordinates. */
943  FT_Set_Var_Design_Coordinates(glyph_font->face, BLF_VARIATIONS_MAX, &coords[0]);
944  }
945 
946  FT_GlyphSlot glyph = blf_glyph_load(glyph_font, glyph_index);
947  if (!glyph) {
948  return NULL;
949  }
950 
951  if ((settings_font->flags & BLF_MONOSPACED) && (settings_font != glyph_font)) {
952  blf_glyph_transform_monospace(glyph, BLI_wcwidth((char32_t)charcode) * fixed_width);
953  }
954 
955  /* Fallback glyph transforms, but only if required and not yet done. */
956 
957  if (weight != 0.0f && !weight_done) {
958  blf_glyph_transform_weight(glyph, weight, glyph->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH);
959  }
960  if (slant != 0.0f && !slant_done) {
962  }
963  if (width != 0.0f && !width_done) {
965  }
966  if (spacing != 0.0f && !spacing_done) {
968  }
969 
970  if (blf_glyph_render_bitmap(glyph_font, glyph)) {
971  return glyph;
972  }
973  return NULL;
974 }
975 
977 {
978  GlyphBLF *g = blf_glyph_cache_find_glyph(gc, charcode);
979  if (g) {
980  return g;
981  }
982 
983  /* Glyph might not come from the initial font. */
984  FontBLF *font_with_glyph = font;
985  FT_UInt glyph_index = blf_glyph_index_from_charcode(&font_with_glyph, charcode);
986 
987  /* Glyphs are dynamically created as needed by font rendering. this means that
988  * to make font rendering thread safe we have to do locking here. note that this
989  * must be a lock for the whole library and not just per font, because the font
990  * renderer uses a shared buffer internally. */
991  BLI_spin_lock(font_with_glyph->ft_lib_mutex);
992 
993  FT_GlyphSlot glyph = blf_glyph_render(
994  font, font_with_glyph, glyph_index, charcode, gc->fixed_width);
995 
996  if (glyph) {
997  /* Save this glyph in the initial font's cache. */
998  g = blf_glyph_cache_add_glyph(font, gc, glyph, charcode, glyph_index);
999  }
1000 
1001  BLI_spin_unlock(font_with_glyph->ft_lib_mutex);
1002  return g;
1003 }
1004 
1006 {
1007  if (g->bitmap) {
1008  MEM_freeN(g->bitmap);
1009  }
1010  MEM_freeN(g);
1011 }
1012 
1015 /* -------------------------------------------------------------------- */
1019 static void blf_glyph_calc_rect(rcti *rect, GlyphBLF *g, const int x, const int y)
1020 {
1021  rect->xmin = x + g->pos[0];
1022  rect->xmax = rect->xmin + g->dims[0];
1023  rect->ymin = y + g->pos[1];
1024  rect->ymax = rect->ymin - g->dims[1];
1025 }
1026 
1027 static void blf_glyph_calc_rect_test(rcti *rect, GlyphBLF *g, const int x, const int y)
1028 {
1029  /* Intentionally check with `g->advance`, because this is the
1030  * width used by BLF_width. This allows that the text slightly
1031  * overlaps the clipping border to achieve better alignment. */
1032  rect->xmin = x;
1033  rect->xmax = rect->xmin + MIN2(ft_pix_to_int(g->advance_x), g->dims[0]);
1034  rect->ymin = y;
1035  rect->ymax = rect->ymin - g->dims[1];
1036 }
1037 
1039  rcti *rect, GlyphBLF *g, const int x, const int y, FontBLF *font)
1040 {
1041  blf_glyph_calc_rect(rect, g, x + font->shadow_x, y + font->shadow_y);
1042 }
1043 
1046 /* -------------------------------------------------------------------- */
1050 static void blf_texture_draw(const unsigned char color[4],
1051  const int glyph_size[2],
1052  const int offset,
1053  const int x1,
1054  const int y1,
1055  const int x2,
1056  const int y2)
1057 {
1058  /* Only one vertex per glyph, geometry shader expand it into a quad. */
1059  /* TODO: Get rid of Geom Shader because it's not optimal AT ALL for the GPU. */
1061  (float)(x1 + g_batch.ofs[0]),
1062  (float)(y1 + g_batch.ofs[1]),
1063  (float)(x2 + g_batch.ofs[0]),
1064  (float)(y2 + g_batch.ofs[1]));
1067  *((int *)GPU_vertbuf_raw_step(&g_batch.offset_step)) = offset;
1068 
1069  g_batch.glyph_len++;
1070  /* Flush cache if it's full. */
1072  blf_batch_draw();
1073  }
1074 }
1075 
1076 static void blf_texture5_draw(const unsigned char color_in[4],
1077  const int glyph_size[2],
1078  const int offset,
1079  const int x1,
1080  const int y1,
1081  const int x2,
1082  const int y2)
1083 {
1084  int glyph_size_flag[2];
1085  /* flag the x and y component signs for 5x5 blurring */
1086  glyph_size_flag[0] = -glyph_size[0];
1087  glyph_size_flag[1] = -glyph_size[1];
1088 
1089  blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2);
1090 }
1091 
1092 static void blf_texture3_draw(const unsigned char color_in[4],
1093  const int glyph_size[2],
1094  const int offset,
1095  const int x1,
1096  const int y1,
1097  const int x2,
1098  const int y2)
1099 {
1100  int glyph_size_flag[2];
1101  /* flag the x component sign for 3x3 blurring */
1102  glyph_size_flag[0] = -glyph_size[0];
1103  glyph_size_flag[1] = glyph_size[1];
1104 
1105  blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2);
1106 }
1107 
1108 void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, const int x, const int y)
1109 {
1110  if ((!g->dims[0]) || (!g->dims[1])) {
1111  return;
1112  }
1113 
1114  if (g->glyph_cache == NULL) {
1115  if (font->tex_size_max == -1) {
1117  }
1118 
1119  g->offset = gc->bitmap_len;
1120 
1121  int buff_size = g->dims[0] * g->dims[1];
1122  int bitmap_len = gc->bitmap_len + buff_size;
1123 
1124  if (bitmap_len > gc->bitmap_len_alloc) {
1125  int w = font->tex_size_max;
1126  int h = bitmap_len / w + 1;
1127 
1128  gc->bitmap_len_alloc = w * h;
1129  gc->bitmap_result = MEM_reallocN(gc->bitmap_result, (size_t)gc->bitmap_len_alloc);
1130 
1131  /* Keep in sync with the texture. */
1132  if (gc->texture) {
1134  }
1135  gc->texture = GPU_texture_create_2d(__func__, w, h, 1, GPU_R8, NULL);
1136 
1137  gc->bitmap_len_landed = 0;
1138  }
1139 
1140  memcpy(&gc->bitmap_result[gc->bitmap_len], g->bitmap, (size_t)buff_size);
1141  gc->bitmap_len = bitmap_len;
1142 
1143  g->glyph_cache = gc;
1144  }
1145 
1146  if (font->flags & BLF_CLIPPING) {
1147  rcti rect_test;
1148  blf_glyph_calc_rect_test(&rect_test, g, x, y);
1149  BLI_rcti_translate(&rect_test, font->pos[0], font->pos[1]);
1150 
1151  if (!BLI_rcti_inside_rcti(&font->clip_rec, &rect_test)) {
1152  return;
1153  }
1154  }
1155 
1156  if (g_batch.glyph_cache != g->glyph_cache) {
1157  blf_batch_draw();
1158  g_batch.glyph_cache = g->glyph_cache;
1159  }
1160 
1161  if (font->flags & BLF_SHADOW) {
1162  rcti rect_ofs;
1163  blf_glyph_calc_rect_shadow(&rect_ofs, g, x, y, font);
1164 
1165  if (font->shadow == 0) {
1167  g->dims,
1168  g->offset,
1169  rect_ofs.xmin,
1170  rect_ofs.ymin,
1171  rect_ofs.xmax,
1172  rect_ofs.ymax);
1173  }
1174  else if (font->shadow <= 4) {
1176  g->dims,
1177  g->offset,
1178  rect_ofs.xmin,
1179  rect_ofs.ymin,
1180  rect_ofs.xmax,
1181  rect_ofs.ymax);
1182  }
1183  else {
1185  g->dims,
1186  g->offset,
1187  rect_ofs.xmin,
1188  rect_ofs.ymin,
1189  rect_ofs.xmax,
1190  rect_ofs.ymax);
1191  }
1192  }
1193 
1194  rcti rect;
1195  blf_glyph_calc_rect(&rect, g, x, y);
1196 
1197 #if BLF_BLUR_ENABLE
1198  switch (font->blur) {
1199  case 3:
1201  font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
1202  break;
1203  case 5:
1205  font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
1206  break;
1207  default:
1209  font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
1210  }
1211 #else
1212  blf_texture_draw(font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
1213 #endif
1214 }
1215 
typedef float(TangentPoint)[2]
@ BLF_ITALIC
Definition: BLF_api.h:347
@ BLF_HINTING_NONE
Definition: BLF_api.h:343
@ BLF_LAST_RESORT
Definition: BLF_api.h:353
@ BLF_MONOSPACED
Definition: BLF_api.h:349
@ BLF_MONOCHROME
Definition: BLF_api.h:342
@ BLF_BOLD
Definition: BLF_api.h:346
@ BLF_HINTING_FULL
Definition: BLF_api.h:345
@ BLF_HINTING_SLIGHT
Definition: BLF_api.h:344
@ BLF_SHADOW
Definition: BLF_api.h:336
@ BLF_CLIPPING
Definition: BLF_api.h:335
@ BLF_DEFAULT
Definition: BLF_api.h:351
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:221
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
MINLINE void copy_v4_fl4(float v[4], float x, float y, float z, float w)
MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4])
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
void BLI_rcti_translate(struct rcti *rect, int x, int y)
Definition: rct.c:559
bool BLI_rcti_inside_rcti(const rcti *rct_a, const rcti *rct_b)
Definition: rct.c:197
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
size_t size_t int BLI_wcwidth(char32_t ucs) ATTR_WARN_UNUSED_RESULT
Definition: string_utf8.c:364
unsigned int uint
Definition: BLI_sys_types.h:67
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:452
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:433
#define ARRAY_SIZE(arr)
#define MIN2(a, b)
int GPU_max_texture_size(void)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:564
GPUTexture * GPU_texture_create_2d(const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:291
@ GPU_R8
Definition: GPU_texture.h:107
GPU_INLINE void * GPU_vertbuf_raw_step(GPUVertBufRaw *a)
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
FontBLF * global_font[BLF_MAX_FONT]
Definition: blf.c:44
BatchBLF g_batch
Definition: blf_font.c:52
void blf_batch_draw(void)
Definition: blf_font.c:229
static GlyphBLF * blf_glyph_cache_find_glyph(GlyphCacheBLF *gc, uint charcode)
Definition: blf_glyph.c:169
static bool blf_glyph_transform_weight(FT_GlyphSlot glyph, float factor, bool monospaced)
Definition: blf_glyph.c:782
static bool blf_font_has_coverage_bit(FontBLF *font, int coverage_bit)
Definition: blf_glyph.c:554
static GlyphCacheBLF * blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
Definition: blf_glyph.c:63
static eUnicodeBlock unicode_blocks[]
Definition: blf_glyph.c:244
static bool blf_glyph_set_variation_normalized(FontBLF *font, FT_Fixed coords[], uint tag, float factor)
Definition: blf_glyph.c:737
static void blf_texture5_draw(const unsigned char color_in[4], const int glyph_size[2], const int offset, const int x1, const int y1, const int x2, const int y2)
Definition: blf_glyph.c:1076
static bool blf_glyph_render_bitmap(FontBLF *font, FT_GlyphSlot glyph)
Definition: blf_glyph.c:644
static bool blf_glyph_transform_spacing(FT_GlyphSlot glyph, float factor)
Definition: blf_glyph.c:843
static void blf_glyph_cache_free(GlyphCacheBLF *gc)
Definition: blf_glyph.c:134
static void blf_texture_draw(const unsigned char color[4], const int glyph_size[2], const int offset, const int x1, const int y1, const int x2, const int y2)
Definition: blf_glyph.c:1050
void blf_glyph_cache_clear(FontBLF *font)
Definition: blf_glyph.c:151
static GlyphBLF * blf_glyph_cache_add_glyph(FontBLF *font, GlyphCacheBLF *gc, FT_GlyphSlot glyph, uint charcode, FT_UInt glyph_index)
Definition: blf_glyph.c:188
static void blf_texture3_draw(const unsigned char color_in[4], const int glyph_size[2], const int offset, const int x1, const int y1, const int x2, const int y2)
Definition: blf_glyph.c:1092
void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, const int x, const int y)
Definition: blf_glyph.c:1108
static void blf_glyph_calc_rect_test(rcti *rect, GlyphBLF *g, const int x, const int y)
Definition: blf_glyph.c:1027
GlyphBLF * blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode)
Definition: blf_glyph.c:976
struct eUnicodeBlock eUnicodeBlock
static int blf_charcode_to_coverage_bit(uint charcode)
Definition: blf_glyph.c:537
static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font, FontBLF *glyph_font, FT_UInt glyph_index, uint charcode, int fixed_width)
Definition: blf_glyph.c:888
static FT_GlyphSlot blf_glyph_load(FontBLF *font, FT_UInt glyph_index)
Definition: blf_glyph.c:610
static FT_Fixed blf_factor_to_coordinate(FT_Var_Axis *axis, float factor)
Definition: blf_glyph.c:716
static FT_Fixed to_16dot16(double val)
Definition: blf_glyph.c:52
static bool blf_glyph_transform_monospace(FT_GlyphSlot glyph, int width)
Definition: blf_glyph.c:856
static void blf_glyph_calc_rect_shadow(rcti *rect, GlyphBLF *g, const int x, const int y, FontBLF *font)
Definition: blf_glyph.c:1038
static GlyphCacheBLF * blf_glyph_cache_new(FontBLF *font)
Definition: blf_glyph.c:78
static void blf_glyph_calc_rect(rcti *rect, GlyphBLF *g, const int x, const int y)
Definition: blf_glyph.c:1019
static bool blf_glyph_set_variation_float(FontBLF *font, FT_Fixed coords[], uint tag, float value)
Definition: blf_glyph.c:758
void blf_glyph_cache_release(FontBLF *font)
Definition: blf_glyph.c:129
static bool blf_glyph_transform_width(FT_GlyphSlot glyph, float factor)
Definition: blf_glyph.c:826
static bool blf_glyph_transform_slant(FT_GlyphSlot glyph, float factor)
Definition: blf_glyph.c:811
GlyphCacheBLF * blf_glyph_cache_acquire(FontBLF *font)
Definition: blf_glyph.c:116
static FT_Var_Axis * blf_var_axis_by_tag(FT_MM_Var *variations, uint tag, int *axis_index)
Definition: blf_glyph.c:694
void blf_glyph_free(GlyphBLF *g)
Definition: blf_glyph.c:1005
static eUnicodeBlock * blf_charcode_to_unicode_block(uint charcode)
Definition: blf_glyph.c:504
static FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode)
Definition: blf_glyph.c:566
#define BLF_MAX_FONT
Definition: blf_internal.h:19
unsigned int blf_hash(unsigned int val)
Definition: blf_util.c:30
#define blf_variation_axis_slant
#define BLF_VARIATIONS_MAX
#define GLYPH_ASCII_TABLE_SIZE
int32_t ft_pix
#define blf_variation_axis_optsize
#define blf_variation_axis_spacing
#define blf_variation_axis_weight
#define BLF_BATCH_DRAW_LEN_MAX
#define blf_variation_axis_width
BLI_INLINE int ft_pix_to_int(ft_pix v)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
flat(Type::VEC4, "color_flat") .no_perspective(Type col offset fragColor glyph
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
#define min(a, b)
Definition: sort.c:35
struct GPUVertBufRaw pos_step col_step offset_step glyph_size_step
struct GlyphCacheBLF * glyph_cache
unsigned int glyph_len
unsigned int dpi
uint UnicodeRanges[4]
SpinLock * glyph_cache_mutex
unsigned char color[4]
float char_spacing
FT_MM_Var * variations
SpinLock * ft_lib_mutex
FT_Library ft_lib
ListBase cache
unsigned char shadow_color[4]
unsigned int dpi
struct GlyphBLF * glyph_ascii_table[GLYPH_ASCII_TABLE_SIZE]
GPUTexture * texture
struct GlyphCacheBLF * next
ListBase bucket[257]
struct GlyphCacheBLF * prev
void * first
Definition: DNA_listBase.h:31
unsigned int last
Definition: blf_glyph.c:238
unsigned int first
Definition: blf_glyph.c:237
int coverage_bit
Definition: blf_glyph.c:239
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
float max
static FT_Error err