201 static const uchar gamma[256] = {
202 0, 5, 9, 11, 14, 16, 19, 21, 23, 25, 26, 28, 30, 32, 34, 35, 37, 38,
203 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64,
204 65, 66, 67, 69, 70, 71, 72, 73, 75, 76, 77, 78, 79, 80, 82, 83, 84, 85,
205 86, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
206 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122,
207 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139,
208 140, 141, 142, 143, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155,
209 156, 157, 157, 158, 159, 160, 161, 162, 163, 163, 164, 165, 166, 167, 168, 168, 169, 170,
210 171, 172, 173, 173, 174, 175, 176, 177, 178, 178, 179, 180, 181, 182, 182, 183, 184, 185,
211 186, 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 194, 195, 196, 197, 198, 198, 199,
212 200, 201, 201, 202, 203, 204, 205, 205, 206, 207, 208, 208, 209, 210, 211, 211, 212, 213,
213 214, 214, 215, 216, 217, 217, 218, 219, 220, 220, 221, 222, 223, 223, 224, 225, 226, 226,
214 227, 228, 229, 229, 230, 231, 231, 232, 233, 234, 234, 235, 236, 237, 237, 238, 239, 239,
215 240, 241, 242, 242, 243, 244, 244, 245, 246, 247, 247, 248, 249, 249, 250, 251, 251, 252,
226 GlyphCacheBLF *gc, FT_GlyphSlot glyph,
uint charcode, FT_UInt glyph_index, uint8_t subpixel)
228 std::unique_ptr<GlyphBLF> g = std::make_unique<GlyphBLF>();
230 g->idx = glyph_index;
231 g->advance_x = (
ft_pix)glyph->advance.x;
232 g->subpixel = subpixel;
235 FT_Outline_Get_CBox(&(glyph->outline), &bbox);
236 g->box_xmin = (
ft_pix)bbox.xMin;
237 g->box_xmax = (
ft_pix)bbox.xMax;
238 g->box_ymin = (
ft_pix)bbox.yMin;
239 g->box_ymax = (
ft_pix)bbox.yMax;
242 g->lsb_delta = (
ft_pix)glyph->lsb_delta;
243 g->rsb_delta = (
ft_pix)glyph->rsb_delta;
245 if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
247 g->pos[0] = glyph->bitmap_left;
248 g->pos[1] = glyph->bitmap_top;
249 g->dims[0] = int(glyph->bitmap.width);
250 g->dims[1] = int(glyph->bitmap.rows);
251 g->pitch = glyph->bitmap.pitch;
254 switch (glyph->bitmap.pixel_mode) {
255 case FT_PIXEL_MODE_LCD:
259 case FT_PIXEL_MODE_LCD_V:
264 case FT_PIXEL_MODE_BGRA:
269 const int buffer_size = g->dims[0] * g->dims[1] * g->num_channels;
272 if (
ELEM(glyph->bitmap.pixel_mode,
275 FT_PIXEL_MODE_GRAY4))
278 const char scale = char(255 / (glyph->bitmap.num_grays - 1));
279 for (
int i = 0;
i < buffer_size;
i++) {
280#ifdef BLF_GAMMA_CORRECT_GLYPHS
284 g->bitmap[
i] = glyph->bitmap.buffer[
i] * scale;
288 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
290 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
291 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
292 size_t offs_in = (
y * size_t(glyph->bitmap.pitch)) + (
x *
size_t(g->num_channels));
293 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
294 (
x *
size_t(g->num_channels));
295 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + 2];
296 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + 1];
297 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in + 0];
301 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) {
303 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
304 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
305 size_t offs_in = (
y * size_t(glyph->bitmap.pitch) * size_t(g->num_channels)) +
x;
306 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
307 (
x *
size_t(g->num_channels));
308 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in];
309 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + size_t(glyph->bitmap.pitch)];
310 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + size_t(glyph->bitmap.pitch) +
311 size_t(glyph->bitmap.pitch)];
315 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
317 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
318 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
319 size_t offs_in = (
y * size_t(g->pitch)) + (
x *
size_t(g->num_channels));
320 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
321 (
x *
size_t(g->num_channels));
322 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + 2];
323 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + 1];
324 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in + 0];
325 g->bitmap[offs_out + 3] = glyph->bitmap.buffer[offs_in + 3];
330 memcpy(g->bitmap, glyph->bitmap.buffer,
size_t(buffer_size));
359 std::string svg_source = blf_get_icon_svg(
int(charcode) -
BLF_ICON_OFFSET);
360 if (edit_source_cb) {
361 edit_source_cb(svg_source);
364 NSVGimage *image = nsvgParse(svg_source.data(),
"px", 96.0f);
366 if (image ==
nullptr) {
370 if (image->width == 0 || image->height == 0) {
375 NSVGrasterizer *rast = nsvgCreateRasterizer();
376 if (rast ==
nullptr) {
381 float scale = (gc->
size / 1600.0f);
382 const int dest_w = int(
ceil(image->width * scale));
383 const int dest_h = int(
ceil(image->height * scale));
384 scale = float(dest_w) / image->width;
388 nsvgRasterize(rast, image, 0.0f, 0.0f, scale, render_bmp.
data(), dest_w, dest_h, dest_w * 4);
389 nsvgDeleteRasterizer(rast);
392 const int offset_x = std::max(
int(
round((gc->
size - (image->width * scale)) / 2.0f)),
393 int(-100.0f * scale));
395 const int offset_y = std::max(
int(
ceil((gc->
size +
float(dest_h)) / 2.0f)),
396 dest_h -
int(100.0f * scale));
400 std::unique_ptr<GlyphBLF> g = std::make_unique<GlyphBLF>();
403 g->advance_x = dest_w * 64;
406 g->box_xmax = dest_w * 64;
408 g->box_ymax = dest_h * 64;
411 g->pos[0] = offset_x;
412 g->pos[1] = offset_y;
416 g->num_channels = color ? 4 : 1;
418 const int buffer_size = g->dims[0] * g->dims[1] * g->num_channels;
422 memcpy(g->bitmap, render_bmp.
data(),
size_t(buffer_size));
431 (
float(render_bmp[
int64_t(offs_in + 3)]) / 255.0f));
1265 FT_UInt glyph_index,
1271 if (glyph_font != settings_font) {
1284 float weight_target = float(settings_font->
char_weight);
1286 weight_target = std::min(weight_target + 300.0f, 900.0f);
1288 float slant_target = settings_font->
char_slant;
1290 slant_target = std::min(slant_target + 8.0f, 15.0f);
1292 float width_target = settings_font->
char_width;
1313 FT_GlyphSlot glyph =
blf_glyph_load(glyph_font, glyph_index, outline_only);
1327 if (weight != weight_target) {
1330 if (slant != slant_target) {
1333 if (width != width_target) {
1336 if (spacing != spacing_target) {
1344 FT_Outline_Translate(&glyph->outline, (FT_Pos)subpixel, 0);
1670 const float eps = 0.0001f;
1671 const float eps_sq =
eps *
eps;
1675 int j, k,
l, l_first = 0;
1684 for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
1685 const int n = ftoutline.contours[j] - contour_prev;
1686 contour_prev = ftoutline.contours[j];
1688 for (k = 0; k < n; k++) {
1689 l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
1694 if (ftoutline.tags[
l] == FT_Curve_Tag_On) {
1699 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1700 if (ftoutline.tags[
l] == FT_Curve_Tag_Conic &&
1701 ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
1710 for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
1711 const int n = ftoutline.contours[j] - contour_prev;
1712 contour_prev = ftoutline.contours[j];
1720 nu->
pntsu = onpoints[j];
1726 for (k = 0; k < n; k++) {
1727 l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
1734 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1735 if (ftoutline.tags[
l] == FT_Curve_Tag_Conic &&
1736 ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
1738 dx = float(ftoutline.points[
l].x + ftoutline.points[l_next].x) * scale / 2.0f;
1739 dy = float(ftoutline.points[
l].y + ftoutline.points[l_next].y) * scale / 2.0f;
1742 bezt->
vec[0][0] = (dx + (2.0f * float(ftoutline.points[
l].x)) * scale) / 3.0f;
1743 bezt->
vec[0][1] = (dy + (2.0f * float(ftoutline.points[
l].y)) * scale) / 3.0f;
1746 bezt->
vec[1][0] = dx;
1747 bezt->
vec[1][1] = dy;
1750 bezt->
vec[2][0] = (dx + (2.0f * float(ftoutline.points[l_next].x)) * scale) / 3.0f;
1751 bezt->
vec[2][1] = (dy + (2.0f * float(ftoutline.points[l_next].y)) * scale) / 3.0f;
1760 if (ftoutline.tags[
l] == FT_Curve_Tag_On) {
1761 const int l_prev = (k > 0) ? (
l - 1) : ftoutline.contours[j];
1762 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1765 if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) {
1766 bezt->
vec[0][0] = float(ftoutline.points[l_prev].x) * scale;
1767 bezt->
vec[0][1] = float(ftoutline.points[l_prev].y) * scale;
1770 else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) {
1771 bezt->
vec[0][0] = (float(ftoutline.points[
l].x) +
1772 (2.0f * float(ftoutline.points[l_prev].x))) *
1774 bezt->
vec[0][1] = (float(ftoutline.points[
l].y) +
1775 (2.0f * float(ftoutline.points[l_prev].y))) *
1780 bezt->
vec[0][0] = float(ftoutline.points[
l].x) * scale -
1781 (float(ftoutline.points[
l].x) - float(ftoutline.points[l_prev].x)) *
1783 bezt->
vec[0][1] = float(ftoutline.points[
l].y) * scale -
1784 (float(ftoutline.points[
l].y) - float(ftoutline.points[l_prev].y)) *
1790 bezt->
vec[1][0] = float(ftoutline.points[
l].x) * scale;
1791 bezt->
vec[1][1] = float(ftoutline.points[
l].y) * scale;
1794 if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) {
1795 bezt->
vec[2][0] = float(ftoutline.points[l_next].x) * scale;
1796 bezt->
vec[2][1] = float(ftoutline.points[l_next].y) * scale;
1799 else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
1800 bezt->
vec[2][0] = (float(ftoutline.points[
l].x) +
1801 (2.0f * float(ftoutline.points[l_next].x))) *
1803 bezt->
vec[2][1] = (float(ftoutline.points[
l].y) +
1804 (2.0f * float(ftoutline.points[l_next].y))) *
1809 bezt->
vec[2][0] = float(ftoutline.points[
l].x) * scale -
1810 (float(ftoutline.points[
l].x) - float(ftoutline.points[l_next].x)) *
1812 bezt->
vec[2][1] = float(ftoutline.points[
l].y) * scale -
1813 (float(ftoutline.points[
l].y) - float(ftoutline.points[l_next].y)) *
1826 (0.001f * 0.001f)) &&
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)