23#include FT_MULTIPLE_MASTERS_H
46# include "nanosvgrast.h"
48# include "svg_icons.h"
58#define BLF_GAMMA_CORRECT_GLYPHS
69 return (FT_Fixed)lround(val * 65536.0);
77 return float(value) / 65536.0f;
88 for (
const std::unique_ptr<GlyphCacheBLF> &gc : font->
cache) {
102 std::unique_ptr<GlyphCacheBLF> gc = std::make_unique<GlyphCacheBLF>();
104 gc->size = font->
size;
116 if (gindex && font->
face) {
117 FT_Fixed advance = 0;
118 FT_Get_Advance(font->
face, gindex, FT_LOAD_NO_HINTING, &advance);
120 gc->fixed_width =
int(advance >> 16);
124 gc->fixed_width =
int((font->
ft_size->metrics.height / 2) >> 6);
126 if (gc->fixed_width < 1) {
155 this->
glyphs.clear_and_shrink();
181 if (
ptr !=
nullptr) {
187#ifdef BLF_GAMMA_CORRECT_GLYPHS
203 static const uchar gamma[256] = {
204 0, 5, 9, 11, 14, 16, 19, 21, 23, 25, 26, 28, 30, 32, 34, 35, 37, 38,
205 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64,
206 65, 66, 67, 69, 70, 71, 72, 73, 75, 76, 77, 78, 79, 80, 82, 83, 84, 85,
207 86, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
208 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
209 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139,
210 140, 141, 142, 143, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155,
211 156, 157, 157, 158, 159, 160, 161, 162, 163, 163, 164, 165, 166, 167, 168, 168, 169, 170,
212 171, 172, 173, 173, 174, 175, 176, 177, 178, 178, 179, 180, 181, 182, 182, 183, 184, 185,
213 186, 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 194, 195, 196, 197, 198, 198, 199,
214 200, 201, 201, 202, 203, 204, 205, 205, 206, 207, 208, 208, 209, 210, 211, 211, 212, 213,
215 214, 214, 215, 216, 217, 217, 218, 219, 220, 220, 221, 222, 223, 223, 224, 225, 226, 226,
216 227, 228, 229, 229, 230, 231, 231, 232, 233, 234, 234, 235, 236, 237, 237, 238, 239, 239,
217 240, 241, 242, 242, 243, 244, 244, 245, 246, 247, 247, 248, 249, 249, 250, 251, 251, 252,
230 std::unique_ptr<GlyphBLF> g = std::make_unique<GlyphBLF>();
232 g->idx = glyph_index;
233 g->advance_x = (
ft_pix)glyph->advance.x;
234 g->subpixel = subpixel;
237 FT_Outline_Get_CBox(&(glyph->outline), &bbox);
238 g->box_xmin = (
ft_pix)bbox.xMin;
239 g->box_xmax = (
ft_pix)bbox.xMax;
240 g->box_ymin = (
ft_pix)bbox.yMin;
241 g->box_ymax = (
ft_pix)bbox.yMax;
244 g->lsb_delta = (
ft_pix)glyph->lsb_delta;
245 g->rsb_delta = (
ft_pix)glyph->rsb_delta;
247 if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
249 g->pos[0] = glyph->bitmap_left;
250 g->pos[1] = glyph->bitmap_top;
251 g->dims[0] =
int(glyph->bitmap.width);
252 g->dims[1] =
int(glyph->bitmap.rows);
253 g->pitch = glyph->bitmap.pitch;
256 switch (glyph->bitmap.pixel_mode) {
257 case FT_PIXEL_MODE_LCD:
261 case FT_PIXEL_MODE_LCD_V:
266 case FT_PIXEL_MODE_BGRA:
271 const int buffer_size = g->dims[0] * g->dims[1] * g->num_channels;
272 g->bitmap =
static_cast<uchar *
>(
MEM_mallocN(
size_t(buffer_size),
"glyph bitmap"));
274 if (
ELEM(glyph->bitmap.pixel_mode,
277 FT_PIXEL_MODE_GRAY4))
280 const char scale = char(255 / (glyph->bitmap.num_grays - 1));
281 for (
int i = 0; i < buffer_size; i++) {
282#ifdef BLF_GAMMA_CORRECT_GLYPHS
286 g->bitmap[i] = glyph->bitmap.buffer[i] * scale;
290 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
292 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
293 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
294 size_t offs_in = (
y * size_t(glyph->bitmap.pitch)) + (
x *
size_t(g->num_channels));
295 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
296 (
x *
size_t(g->num_channels));
297 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + 2];
298 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + 1];
299 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in + 0];
303 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) {
305 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
306 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
307 size_t offs_in = (
y * size_t(glyph->bitmap.pitch) * size_t(g->num_channels)) +
x;
308 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
309 (
x *
size_t(g->num_channels));
310 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in];
311 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + size_t(glyph->bitmap.pitch)];
312 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + size_t(glyph->bitmap.pitch) +
313 size_t(glyph->bitmap.pitch)];
317 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
319 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
320 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
321 size_t offs_in = (
y * size_t(g->pitch)) + (
x *
size_t(g->num_channels));
322 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
323 (
x *
size_t(g->num_channels));
324 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + 2];
325 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + 1];
326 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in + 0];
327 g->bitmap[offs_out + 3] = glyph->bitmap.buffer[offs_in + 3];
332 memcpy(g->bitmap, glyph->bitmap.buffer,
size_t(buffer_size));
347 std::unique_ptr<GlyphBLF> g = std::make_unique<GlyphBLF>();
361 std::string svg_source = blf_get_icon_svg(
int(charcode) -
BLF_ICON_OFFSET);
362 if (edit_source_cb) {
363 edit_source_cb(svg_source);
366 NSVGimage *
image = nsvgParse(svg_source.data(),
"px", 96.0f);
368 if (
image ==
nullptr) {
372 if (
image->width == 0 ||
image->height == 0) {
377 NSVGrasterizer *rast = nsvgCreateRasterizer();
378 if (rast ==
nullptr) {
383 float scale = (gc->
size / 1600.0f);
390 nsvgRasterize(rast,
image, 0.0f, 0.0f, scale, render_bmp.
data(), dest_w, dest_h, dest_w * 4);
391 nsvgDeleteRasterizer(rast);
394 const int offset_x = std::max(
int(round((gc->
size - (
image->width * scale)) / 2.0f)),
395 int(-100.0f * scale));
397 const int offset_y = std::max(
int(
ceil((gc->
size +
float(dest_h)) / 2.0f)),
398 dest_h -
int(100.0f * scale));
402 std::unique_ptr<GlyphBLF> g = std::make_unique<GlyphBLF>();
405 g->advance_x = dest_w * 64;
408 g->box_xmax = dest_w * 64;
410 g->box_ymax = dest_h * 64;
413 g->pos[0] = offset_x;
414 g->pos[1] = offset_y;
418 g->num_channels =
color ? 4 : 1;
420 const int buffer_size = g->dims[0] * g->dims[1] * g->num_channels;
421 g->bitmap =
static_cast<uchar *
>(
MEM_mallocN(
size_t(buffer_size),
"glyph bitmap"));
424 memcpy(g->bitmap, render_bmp.
data(),
size_t(buffer_size));
433 (
float(render_bmp[
int64_t(offs_in + 3)]) / 255.0f));
495 {0x1000, 0x109F, 74},
496 {0x10A0, 0x10FF, 26},
497 {0x1100, 0x11FF, 28},
498 {0x1200, 0x139F, 75},
499 {0x13A0, 0x13FF, 76},
500 {0x1400, 0x167F, 77},
501 {0x1680, 0x169F, 78},
502 {0x16A0, 0x16FF, 79},
503 {0x1700, 0x171F, 84},
504 {0x1720, 0x173F, 84},
505 {0x1740, 0x175F, 84},
506 {0x1760, 0x177F, 84},
507 {0x1780, 0x17FF, 80},
508 {0x1800, 0x18AF, 81},
509 {0x1900, 0x194F, 93},
510 {0x1950, 0x197F, 94},
511 {0x1980, 0x19DF, 95},
512 {0x19E0, 0x19FF, 80},
513 {0x1A00, 0x1A1F, 96},
514 {0x1A20, 0x1AAF, -1},
515 {0x1B00, 0x1B7F, 27},
516 {0x1B80, 0x1BBF, 112},
517 {0x1BC0, 0x1BFF, -1},
518 {0x1C00, 0x1C4F, 113},
519 {0x1C50, 0x1C7F, 114},
522 {0x1E00, 0x1EFF, 29},
523 {0x1F00, 0x1FFF, 30},
524 {0x2000, 0x206F, 31},
525 {0x2070, 0x209F, 32},
526 {0x20A0, 0x20CF, 33},
527 {0x20D0, 0x20FF, 34},
528 {0x2100, 0x214F, 35},
529 {0x2150, 0x218F, 36},
530 {0x2190, 0x21FF, 37},
531 {0x2200, 0x22FF, 38},
532 {0x2300, 0x23FF, 39},
533 {0x2400, 0x243F, 40},
534 {0x2440, 0x245F, 41},
535 {0x2460, 0x24FF, 42},
536 {0x2500, 0x257F, 43},
537 {0x2580, 0x259F, 44},
538 {0x25A0, 0x25FF, 45},
539 {0x2600, 0x26FF, 46},
540 {0x2700, 0x27BF, 47},
541 {0x27C0, 0x27EF, 38},
542 {0x27F0, 0x27FF, 37},
543 {0x2800, 0x28FF, 82},
544 {0x2900, 0x297F, 37},
545 {0x2980, 0x2AFF, 38},
546 {0x2B00, 0x2BFF, 37},
547 {0x2C00, 0x2C5F, 97},
548 {0x2C60, 0x2C7F, 29},
550 {0x2D00, 0x2D2F, 26},
551 {0x2D30, 0x2D7F, 98},
552 {0x2D80, 0x2DDF, 75},
554 {0x2E00, 0x2E7F, 31},
555 {0x2E80, 0x2FFF, 59},
556 {0x3000, 0x303F, 48},
557 {0x3040, 0x309F, 49},
558 {0x30A0, 0x30FF, 50},
559 {0x3100, 0x312F, 51},
560 {0x3130, 0x318F, 52},
561 {0x3190, 0x319F, 59},
562 {0x31A0, 0x31BF, 51},
563 {0x31C0, 0x31EF, 59},
564 {0x31F0, 0x31FF, 50},
565 {0x3200, 0x32FF, 54},
566 {0x3300, 0x33FF, 55},
567 {0x3400, 0x4DBF, 59},
568 {0x4DC0, 0x4DFF, 99},
569 {0x4E00, 0x9FFF, 59},
570 {0xA000, 0xA4CF, 83},
571 {0xA4D0, 0xA4FF, -1},
572 {0xA500, 0xA63F, 12},
574 {0xA6A0, 0xA6FF, -1},
576 {0xA720, 0xA7FF, 29},
577 {0xA800, 0xA82F, 100},
578 {0xA840, 0xA87F, 53},
579 {0xA880, 0xA8DF, 115},
580 {0xA900, 0xA92F, 116},
581 {0xA930, 0xA95F, 117},
582 {0xA960, 0xA97F, 56},
583 {0xA980, 0xA9DF, -1},
584 {0xA9E0, 0xA9FF, 74},
585 {0xAA00, 0xAA5F, 118},
586 {0xAA60, 0xAA7F, 74},
587 {0xAA80, 0xAADF, -1},
588 {0xAAE0, 0xAAFF, -1},
589 {0xAB00, 0xAB2F, 75},
590 {0xAB70, 0xABBF, 76},
591 {0xABC0, 0xABFF, -1},
592 {0xAC00, 0xD7AF, 56},
593 {0xD800, 0xDFFF, 57},
594 {0xE000, 0xF6FF, 60},
595 {0xE700, 0xEFFF, -1},
596 {0xF000, 0xF8FF, -1},
597 {0xF900, 0xFAFF, 61},
598 {0xFB00, 0xFB4F, 62},
599 {0xFB50, 0xFDFF, 63},
600 {0xFE00, 0xFE0F, 91},
601 {0xFE10, 0xFE1F, 65},
602 {0xFE20, 0xFE2F, 64},
603 {0xFE30, 0xFE4F, 65},
604 {0xFE50, 0xFE6F, 66},
605 {0xFE70, 0xFEFF, 67},
606 {0xFF00, 0xFFEF, 68},
607 {0xFFF0, 0xFFFF, 69},
608 {0x10000, 0x1013F, 101},
609 {0x10140, 0x1018F, 102},
610 {0x10190, 0x101CF, 119},
611 {0x101D0, 0x101FF, 120},
612 {0x10280, 0x1029F, 121},
613 {0x102A0, 0x102DF, 121},
614 {0x10300, 0x1032F, 85},
615 {0x10330, 0x1034F, 86},
616 {0x10350, 0x1037F, -1},
617 {0x10380, 0x1039F, 103},
618 {0x103A0, 0x103DF, 104},
619 {0x10400, 0x1044F, 87},
620 {0x10450, 0x1047F, 105},
621 {0x10480, 0x104AF, 106},
622 {0x104B0, 0x104FF, -1},
623 {0x10500, 0x1052F, -1},
624 {0x10530, 0x1056F, -1},
625 {0x10570, 0x105BF, -1},
626 {0x10600, 0x1077F, -1},
627 {0x10780, 0x107BF, 3},
628 {0x10800, 0x1083F, 107},
629 {0x10840, 0x1085F, -1},
630 {0x10860, 0x1087F, -1},
631 {0x10880, 0x108AF, -1},
632 {0x108E0, 0x108FF, -1},
633 {0x10900, 0x1091F, 58},
634 {0x10920, 0x1093F, 121},
635 {0x10980, 0x1099F, -1},
636 {0x109A0, 0x109FF, -1},
637 {0x10A00, 0x10A5F, 108},
638 {0x10A60, 0x10A7F, -1},
639 {0x10A80, 0x10A9F, -1},
640 {0x10AC0, 0x10AFF, -1},
641 {0x10B00, 0x10B3F, -1},
642 {0x10B40, 0x10B5F, -1},
643 {0x10B60, 0x10B7F, -1},
644 {0x10B80, 0x10BAF, -1},
645 {0x10C00, 0x10C4F, -1},
646 {0x10C80, 0x10CFF, -1},
647 {0x10D00, 0x10D3F, -1},
648 {0x108E0, 0x10E7F, -1},
649 {0x10E80, 0x10EBF, -1},
650 {0x10F00, 0x10F2F, -1},
651 {0x10F30, 0x10F6F, -1},
652 {0x10F70, 0x10FAF, -1},
653 {0x10FB0, 0x10FDF, -1},
654 {0x10FE0, 0x10FFF, -1},
655 {0x11000, 0x1107F, -1},
656 {0x11080, 0x110CF, -1},
657 {0x110D0, 0x110FF, -1},
658 {0x11100, 0x1114F, -1},
659 {0x11150, 0x1117F, -1},
660 {0x11180, 0x111DF, -1},
661 {0x111E0, 0x111FF, -1},
662 {0x11200, 0x1124F, -1},
663 {0x11280, 0x112AF, -1},
664 {0x112B0, 0x112FF, -1},
665 {0x11300, 0x1137F, -1},
666 {0x11400, 0x1147F, -1},
667 {0x11480, 0x114DF, -1},
668 {0x11580, 0x115FF, -1},
669 {0x11600, 0x1165F, -1},
670 {0x11660, 0x1167F, 81},
671 {0x11680, 0x116CF, -1},
672 {0x11700, 0x1174F, -1},
673 {0x11800, 0x1184F, -1},
674 {0x118A0, 0x118FF, -1},
675 {0x11900, 0x1195F, -1},
676 {0x119A0, 0x119FF, -1},
677 {0x11A00, 0x11A4F, -1},
678 {0x11A50, 0x11AAF, -1},
679 {0x11AB0, 0x11ABF, 77},
680 {0x11AC0, 0x11AFF, -1},
681 {0x11C00, 0x11C6F, -1},
682 {0x11C70, 0x11CBF, -1},
683 {0x11D00, 0x11D5F, -1},
684 {0x11D60, 0x11DAF, -1},
685 {0x11EE0, 0x11EFF, -1},
686 {0x11FB0, 0x11FBF, -1},
687 {0x11FC0, 0x11FFF, 20},
688 {0x12000, 0x1254F, 110},
689 {0x12F90, 0x12FFF, -1},
690 {0x13000, 0x1343F, -1},
691 {0x14400, 0x1467F, -1},
692 {0x16800, 0x16A3F, -1},
693 {0x16A40, 0x16A6F, -1},
694 {0x16A70, 0x16ACF, -1},
695 {0x16AD0, 0x16AFF, -1},
696 {0x16B00, 0x16B8F, -1},
697 {0x16E40, 0x16E9F, -1},
698 {0x16F00, 0x16F9F, -1},
699 {0x16FE0, 0x16FFF, -1},
700 {0x17000, 0x18AFF, -1},
701 {0x1B170, 0x1B2FF, -1},
702 {0x1BC00, 0x1BC9F, -1},
703 {0x1D000, 0x1D24F, 88},
704 {0x1D2E0, 0x1D2FF, -1},
705 {0x1D300, 0x1D35F, 109},
706 {0x1D360, 0x1D37F, 111},
707 {0x1D400, 0x1D7FF, 89},
708 {0x1E2C0, 0x1E2FF, -1},
709 {0x1E800, 0x1E8DF, -1},
710 {0x1E900, 0x1E95F, -1},
711 {0x1EC70, 0x1ECBF, -1},
712 {0x1F000, 0x1F02F, 122},
713 {0x1F030, 0x1F09F, 122},
714 {0x1F600, 0x1F64F, -1},
715 {0x20000, 0x2A6DF, 59},
716 {0x2F800, 0x2FA1F, 61},
717 {0xE0000, 0xE007F, 92},
718 {0xE0100, 0xE01EF, 91},
719 {0xF0000, 0x10FFFD, 90}};
726 if (charcode < 0x80) {
741 const int mid = (
min +
max) / 2;
758 int coverage_bit = -1;
764 if (coverage_bit < 0 && charcode > 0xFFFF) {
775 if (coverage_bit < 0) {
835 FontBLF *last_resort =
nullptr;
855 printf(
"Unicode character U+%04X not found in loaded fonts. \n", charcode);
884 load_flags = FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP;
887 load_flags = FT_LOAD_TARGET_MONO;
890 load_flags = FT_LOAD_NO_BITMAP;
892 load_flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
895 load_flags |= FT_LOAD_TARGET_LIGHT;
898 load_flags |= FT_LOAD_TARGET_NORMAL;
902 load_flags |= FT_LOAD_TARGET_LIGHT;
906 if (!outline_only && FT_HAS_COLOR(font->
face)) {
907 load_flags |= FT_LOAD_COLOR;
910 if (FT_Load_Glyph(font->
face, glyph_index, load_flags) == FT_Err_Ok) {
911 return font->
face->glyph;
930 render_mode = FT_RENDER_MODE_MONO;
933 render_mode = FT_RENDER_MODE_LIGHT;
936 render_mode = FT_RENDER_MODE_NORMAL;
940 FT_Error err = FT_Render_Glyph(glyph, FT_Render_Mode(render_mode));
941 if (err != FT_Err_Ok) {
945 if (
ELEM(glyph->bitmap.pixel_mode, FT_PIXEL_MODE_MONO, FT_PIXEL_MODE_GRAY2, FT_PIXEL_MODE_GRAY4))
948 FT_Bitmap tempbitmap;
949 FT_Bitmap_New(&tempbitmap);
952 err += FT_Bitmap_Convert(font->
ft_lib, &glyph->bitmap, &tempbitmap, 1);
953 err += FT_Bitmap_Copy(font->
ft_lib, &tempbitmap, &glyph->bitmap);
954 err += FT_Bitmap_Done(font->
ft_lib, &tempbitmap);
957 return (err == FT_Err_Ok);
981 for (
int i = 0; i <
int(variations->num_axis); i++) {
982 if (variations->axis[i].tag == tag) {
984 return &(variations->axis)[i];
1002 FT_Fixed value = axis->def;
1005 value += (FT_Fixed)(
double(axis->maximum - axis->def) * factor);
1007 else if (factor < 0) {
1009 value += (FT_Fixed)(
double(axis->def - axis->minimum) * factor);
1056 CLAMP(int_value, axis->minimum, axis->maximum);
1057 coords[axis_index] = int_value;
1073 float current_weight,
1074 float target_weight)
1076 float value = target_weight;
1080 return current_weight;
1092 float current_degrees,
1093 float target_degrees)
1095 float value = -target_degrees;
1099 return current_degrees;
1111 float current_width,
1114 float value = target_width * 100.0f;
1116 return value / 100.0f;
1118 return current_width;
1130 float current_spacing,
1131 float target_spacing)
1133 float value = target_spacing;
1137 return current_spacing;
1151 float value = points;
1169 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
1171 const FT_Pos average_width = font->
ft_size->metrics.height;
1172 float factor = width * 0.000225f;
1173 FT_Pos change = (FT_Pos)(
float(average_width) * factor);
1174 FT_Outline_EmboldenXY(&glyph->outline, change, 0);
1177 FT_Outline_Translate(&glyph->outline, change / -2, 0);
1181 glyph->advance.x += change / 2;
1196 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
1198 FT_Outline_Transform(&glyph->outline, &
transform);
1199 if (degrees < 0.0f) {
1202 const FT_Pos average_width = font->
ft_size->metrics.height;
1203 FT_Pos change = (FT_Pos)(
float(average_width) * degrees * -0.01f);
1204 FT_Outline_Translate(&glyph->outline, change, 0);
1219 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
1220 float scale = factor + 1.0f;
1222 FT_Outline_Transform(&glyph->outline, &matrix);
1223 glyph->advance.x = (FT_Pos)(
double(glyph->advance.x) * scale);
1237 if (glyph->advance.x > 0) {
1239 const long int size = font->
ft_size->metrics.height;
1240 glyph->advance.x += (FT_Pos)(factor *
float(
size) / 6.0f);
1253 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
1254 FT_Fixed current = glyph->linearHoriAdvance;
1255 FT_Fixed target = FT_Fixed(width) << 16;
1256 if (target < current) {
1257 const FT_Pos embolden = (FT_Pos)((current - target) >> 13);
1259 FT_Outline_EmboldenXY(&glyph->outline, embolden, 0);
1260 const float scale =
float(target - (embolden << 9)) /
float(current);
1262 FT_Outline_Transform(&glyph->outline, &matrix);
1264 else if (target > current) {
1266 FT_Outline_Translate(&glyph->outline, (FT_Pos)((target - current) >> 11), 0);
1268 glyph->advance.x = width << 6;
1285 FT_UInt glyph_index,
1291 if (glyph_font != settings_font) {
1306 weight_target = std::min(weight_target + 300.0f, 900.0f);
1308 float slant_target = settings_font->
char_slant;
1310 slant_target = std::min(slant_target + 8.0f, 15.0f);
1312 float width_target = settings_font->
char_width;
1333 FT_GlyphSlot glyph =
blf_glyph_load(glyph_font, glyph_index, outline_only);
1347 if (weight != weight_target) {
1350 if (slant != slant_target) {
1353 if (width != width_target) {
1356 if (spacing != spacing_target) {
1364 FT_Outline_Translate(&glyph->outline, (FT_Pos)subpixel, 0);
1380 FontBLF *font_with_glyph = font;
1388 font, font_with_glyph, glyph_index, charcode, subpixel, gc->
fixed_width,
false);
1398#ifndef WITH_HEADLESS
1412#ifdef BLF_SUBPIXEL_AA
1509 if ((!g->
dims[0]) || (!g->
dims[1])) {
1525 int h = bitmap_len /
w + 1;
1680 const float eps = 0.0001f;
1681 const float eps_sq =
eps *
eps;
1685 int j, k,
l, l_first = 0;
1691 int *onpoints =
static_cast<int *
>(
1692 MEM_callocN(
size_t(ftoutline.n_contours) *
sizeof(
int),
"onpoints"));
1695 for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
1696 const int n = ftoutline.contours[j] - contour_prev;
1697 contour_prev = ftoutline.contours[j];
1699 for (k = 0; k < n; k++) {
1700 l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
1705 if (ftoutline.tags[
l] == FT_Curve_Tag_On) {
1710 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1711 if (ftoutline.tags[
l] == FT_Curve_Tag_Conic &&
1712 ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
1721 for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
1722 const int n = ftoutline.contours[j] - contour_prev;
1723 contour_prev = ftoutline.contours[j];
1732 nu->
pntsu = onpoints[j];
1738 for (k = 0; k < n; k++) {
1739 l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
1746 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1747 if (ftoutline.tags[
l] == FT_Curve_Tag_Conic &&
1748 ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
1750 dx =
float(ftoutline.points[
l].x + ftoutline.points[l_next].x) * scale / 2.0f;
1751 dy =
float(ftoutline.points[
l].y + ftoutline.points[l_next].y) * scale / 2.0f;
1754 bezt->
vec[0][0] = (dx + (2.0f *
float(ftoutline.points[
l].x)) * scale) / 3.0f;
1755 bezt->
vec[0][1] = (dy + (2.0f *
float(ftoutline.points[
l].y)) * scale) / 3.0f;
1758 bezt->
vec[1][0] = dx;
1759 bezt->
vec[1][1] = dy;
1762 bezt->
vec[2][0] = (dx + (2.0f *
float(ftoutline.points[l_next].x)) * scale) / 3.0f;
1763 bezt->
vec[2][1] = (dy + (2.0f *
float(ftoutline.points[l_next].y)) * scale) / 3.0f;
1772 if (ftoutline.tags[
l] == FT_Curve_Tag_On) {
1773 const int l_prev = (k > 0) ? (
l - 1) : ftoutline.contours[j];
1774 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1777 if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) {
1778 bezt->
vec[0][0] =
float(ftoutline.points[l_prev].x) * scale;
1779 bezt->
vec[0][1] =
float(ftoutline.points[l_prev].y) * scale;
1782 else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) {
1783 bezt->
vec[0][0] = (
float(ftoutline.points[
l].x) +
1784 (2.0f *
float(ftoutline.points[l_prev].x))) *
1786 bezt->
vec[0][1] = (
float(ftoutline.points[
l].y) +
1787 (2.0f *
float(ftoutline.points[l_prev].y))) *
1792 bezt->
vec[0][0] =
float(ftoutline.points[
l].x) * scale -
1793 (
float(ftoutline.points[
l].x) -
float(ftoutline.points[l_prev].x)) *
1795 bezt->
vec[0][1] =
float(ftoutline.points[
l].y) * scale -
1796 (
float(ftoutline.points[
l].y) -
float(ftoutline.points[l_prev].y)) *
1802 bezt->
vec[1][0] =
float(ftoutline.points[
l].x) * scale;
1803 bezt->
vec[1][1] =
float(ftoutline.points[
l].y) * scale;
1806 if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) {
1807 bezt->
vec[2][0] =
float(ftoutline.points[l_next].x) * scale;
1808 bezt->
vec[2][1] =
float(ftoutline.points[l_next].y) * scale;
1811 else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
1812 bezt->
vec[2][0] = (
float(ftoutline.points[
l].x) +
1813 (2.0f *
float(ftoutline.points[l_next].x))) *
1815 bezt->
vec[2][1] = (
float(ftoutline.points[
l].y) +
1816 (2.0f *
float(ftoutline.points[l_next].y))) *
1821 bezt->
vec[2][0] =
float(ftoutline.points[
l].x) * scale -
1822 (
float(ftoutline.points[
l].x) -
float(ftoutline.points[l_next].x)) *
1824 bezt->
vec[2][1] =
float(ftoutline.points[
l].y) * scale -
1825 (
float(ftoutline.points[
l].y) -
float(ftoutline.points[l_next].y)) *
1838 (0.001f * 0.001f)) &&
1860 FontBLF *font_with_glyph = font;
1867 FT_GlyphSlot glyph =
blf_glyph_render(font, font_with_glyph, glyph_index, charcode, 0, 0,
true);
1869 if (font != font_with_glyph) {
1873 double ratio =
float(font->
face->units_per_EM) /
float(font_with_glyph->
face->units_per_EM);
1875 FT_Outline_Transform(&glyph->outline, &
transform);
1876 glyph->advance.x =
int(
float(glyph->advance.x) * ratio);
1877 glyph->metrics.horiAdvance =
int(
float(glyph->metrics.horiAdvance) * ratio);
1891 return float(glyph->advance.x) * scale;
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE float max_ff(float a, float b)
MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3])
float dist_squared_to_line_v2(const float p[2], const float l1[2], const float l2[2])
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
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)
bool BLI_rcti_inside_rcti(const rcti *rct_a, const rcti *rct_b)
size_t size_t int BLI_wcwidth_or_error(char32_t ucs) ATTR_WARN_UNUSED_RESULT
int GPU_max_texture_size()
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
@ GPU_TEXTURE_USAGE_SHADER_READ
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 Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves 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 Invert a color
FontBLF * global_font[BLF_MAX_FONT]
bool blf_ensure_face(FontBLF *font)
void blf_ensure_size(FontBLF *font)
bool blf_font_size(FontBLF *font, float size)
uint blf_get_char_index(FontBLF *font, uint charcode)
static float blf_glyph_set_variation_spacing(const FontBLF *font, FT_Fixed coords[], float current_spacing, float target_spacing)
static GlyphBLF * blf_glyph_cache_find_glyph(const GlyphCacheBLF *gc, uint charcode, uint8_t subpixel)
static FT_GlyphSlot blf_glyph_render(FontBLF *settings_font, FontBLF *glyph_font, FT_UInt glyph_index, uint charcode, uint8_t subpixel, int fixed_width, bool outline_only)
static float blf_glyph_set_variation_width(const FontBLF *font, FT_Fixed coords[], float current_width, float target_width)
static bool blf_glyph_set_variation_optical_size(const FontBLF *font, FT_Fixed coords[], const float points)
static float blf_glyph_set_variation_weight(const FontBLF *font, FT_Fixed coords[], float current_weight, float target_weight)
static bool blf_glyph_render_bitmap(FontBLF *font, FT_GlyphSlot glyph)
static bool blf_glyph_transform_spacing(FT_GlyphSlot glyph, float factor)
void blf_glyph_cache_clear(FontBLF *font)
GlyphCacheBLF * blf_glyph_cache_acquire(FontBLF *font)
static void blf_glyph_calc_rect(const GlyphBLF *g, const int x, const int y, rcti *r_rect)
static float from_16dot16(FT_Fixed value)
float blf_character_to_curves(FontBLF *font, uint unicode, ListBase *nurbsbase, const float scale)
static FT_GlyphSlot blf_glyphslot_ensure_outline(FontBLF *font, const uint charcode)
static FT_GlyphSlot blf_glyph_load(FontBLF *font, FT_UInt glyph_index, bool outline_only)
static const UnicodeBlock * blf_charcode_to_unicode_block(const uint charcode)
static void blf_texture_draw(const GlyphBLF *g, const uchar color[4], const FontShadowType shadow, const int x1, const int y1, const int x2, const int y2)
void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, const int x, const int y)
static GlyphBLF * blf_glyph_cache_add_glyph(GlyphCacheBLF *gc, FT_GlyphSlot glyph, uint charcode, FT_UInt glyph_index, uint8_t subpixel)
static bool blf_font_has_coverage_bit(const FontBLF *font, int coverage_bit)
static int blf_charcode_to_coverage_bit(uint charcode)
static uchar blf_glyph_gamma(uchar c)
static const FT_Var_Axis * blf_var_axis_by_tag(const FT_MM_Var *variations, const uint32_t tag, int *r_axis_index)
static GlyphCacheBLF * blf_glyph_cache_find(const FontBLF *font)
static void blf_glyph_to_curves(const FT_Outline &ftoutline, ListBase *nurbsbase, const float scale)
static void blf_glyph_calc_rect_shadow(const GlyphBLF *g, const int x, const int y, const FontBLF *font, rcti *r_rect)
static FT_Fixed to_16dot16(double val)
static bool blf_glyph_transform_monospace(FT_GlyphSlot glyph, int width)
static const UnicodeBlock unicode_blocks[]
static bool blf_glyph_transform_weight(FT_GlyphSlot glyph, float width, bool monospaced)
GlyphBLF * blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int32_t pen_x)
static GlyphCacheBLF * blf_glyph_cache_new(FontBLF *font)
static void blf_glyph_calc_rect_test(const GlyphBLF *g, const int x, const int y, rcti *r_rect)
void blf_glyph_cache_release(FontBLF *font)
static bool blf_glyph_set_variation_float(const FontBLF *font, FT_Fixed coords[], uint32_t tag, float *value)
static bool blf_glyph_transform_slant(FT_GlyphSlot glyph, float degrees)
static float blf_glyph_set_variation_slant(const FontBLF *font, FT_Fixed coords[], float current_degrees, float target_degrees)
GlyphBLF * blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, const uint charcode, uint8_t subpixel)
static bool blf_glyph_transform_width(FT_GlyphSlot glyph, float factor)
static GlyphBLF * blf_glyph_cache_add_svg(GlyphCacheBLF *gc, uint charcode, bool color, blender::FunctionRef< void(std::string &)> edit_source_cb=nullptr)
static GlyphBLF * blf_glyph_cache_add_blank(GlyphCacheBLF *gc, uint charcode)
static FT_Fixed blf_factor_to_coordinate(const FT_Var_Axis *axis, const float factor)
static bool blf_glyph_set_variation_normalized(const FontBLF *font, FT_Fixed coords[], const uint32_t tag, const float factor)
GlyphBLF * blf_glyph_ensure_icon(GlyphCacheBLF *gc, const uint icon_id, bool color, blender::FunctionRef< void(std::string &)> edit_source_cb)
static FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode)
#define BLF_VARIATIONS_MAX
#define BLF_VARIATION_AXIS_SLANT
#define BLF_VARIATION_AXIS_OPTSIZE
#define BLF_VARIATION_AXIS_WIDTH
#define BLF_VARIATION_AXIS_WEIGHT
#define BLF_VARIATION_AXIS_SPACING
#define BLF_BATCH_DRAW_LEN_MAX
int ft_pix_to_int(ft_pix v)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
bool add(const Key &key, const Value &value)
const Value * lookup_ptr_as(const ForwardKey &key) const
void append(const T &value)
const T & last(const int64_t n=0) const
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
ccl_device_inline float3 ceil(const float3 a)
blender::Vector< std::unique_ptr< GlyphCacheBLF > > cache
std::mutex glyph_cache_mutex
unsigned char shadow_color[4]
GlyphCacheBLF * glyph_cache
blender::Map< GlyphCacheKey, std::unique_ptr< GlyphBLF > > glyphs
ccl_device_inline int abs(int x)