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 const FT_GlyphSlot glyph,
228 const FT_UInt glyph_index,
229 const uint8_t subpixel)
231 std::unique_ptr<GlyphBLF> g = std::make_unique<GlyphBLF>();
233 g->idx = glyph_index;
234 g->advance_x = (
ft_pix)glyph->advance.x;
235 g->subpixel = subpixel;
238 FT_Outline_Get_CBox(&(glyph->outline), &bbox);
239 g->box_xmin = (
ft_pix)bbox.xMin;
240 g->box_xmax = (
ft_pix)bbox.xMax;
241 g->box_ymin = (
ft_pix)bbox.yMin;
242 g->box_ymax = (
ft_pix)bbox.yMax;
245 g->lsb_delta = (
ft_pix)glyph->lsb_delta;
246 g->rsb_delta = (
ft_pix)glyph->rsb_delta;
248 if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
250 g->pos[0] = glyph->bitmap_left;
251 g->pos[1] = glyph->bitmap_top;
252 g->dims[0] = int(glyph->bitmap.width);
253 g->dims[1] = int(glyph->bitmap.rows);
254 g->pitch = glyph->bitmap.pitch;
257 switch (glyph->bitmap.pixel_mode) {
258 case FT_PIXEL_MODE_LCD:
262 case FT_PIXEL_MODE_LCD_V:
267 case FT_PIXEL_MODE_BGRA:
272 const int buffer_size = g->dims[0] * g->dims[1] * g->num_channels;
275 if (
ELEM(glyph->bitmap.pixel_mode,
278 FT_PIXEL_MODE_GRAY4))
281 const char scale = char(255 / (glyph->bitmap.num_grays - 1));
282 for (
int i = 0;
i < buffer_size;
i++) {
283#ifdef BLF_GAMMA_CORRECT_GLYPHS
287 g->bitmap[
i] = glyph->bitmap.buffer[
i] * scale;
291 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
293 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
294 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
295 size_t offs_in = (
y * size_t(glyph->bitmap.pitch)) + (
x *
size_t(g->num_channels));
296 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
297 (
x *
size_t(g->num_channels));
298 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + 2];
299 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + 1];
300 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in + 0];
304 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) {
306 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
307 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
308 size_t offs_in = (
y * size_t(glyph->bitmap.pitch) * size_t(g->num_channels)) +
x;
309 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
310 (
x *
size_t(g->num_channels));
311 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in];
312 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + size_t(glyph->bitmap.pitch)];
313 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + size_t(glyph->bitmap.pitch) +
314 size_t(glyph->bitmap.pitch)];
318 else if (glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
320 for (
size_t y = 0;
y < size_t(g->dims[1]);
y++) {
321 for (
size_t x = 0;
x < size_t(g->dims[0]);
x++) {
322 size_t offs_in = (
y * size_t(g->pitch)) + (
x *
size_t(g->num_channels));
323 size_t offs_out = (
y * size_t(g->dims[0]) * size_t(g->num_channels)) +
324 (
x *
size_t(g->num_channels));
325 g->bitmap[offs_out + 0] = glyph->bitmap.buffer[offs_in + 2];
326 g->bitmap[offs_out + 1] = glyph->bitmap.buffer[offs_in + 1];
327 g->bitmap[offs_out + 2] = glyph->bitmap.buffer[offs_in + 0];
328 g->bitmap[offs_out + 3] = glyph->bitmap.buffer[offs_in + 3];
333 memcpy(g->bitmap, glyph->bitmap.buffer,
size_t(buffer_size));
362 std::string svg_source = blf_get_icon_svg(
int(charcode) -
BLF_ICON_OFFSET);
363 if (edit_source_cb) {
364 edit_source_cb(svg_source);
367 NSVGimage *image = nsvgParse(svg_source.data(),
"px", 96.0f);
369 if (image ==
nullptr) {
373 if (image->width == 0 || image->height == 0) {
378 NSVGrasterizer *rast = nsvgCreateRasterizer();
379 if (rast ==
nullptr) {
384 float scale = (gc->
size / 1600.0f);
385 const int dest_w = int(
ceil(image->width * scale));
386 const int dest_h = int(
ceil(image->height * scale));
387 scale =
float(dest_w) / image->width;
391 nsvgRasterize(rast, image, 0.0f, 0.0f, scale, render_bmp.
data(), dest_w, dest_h, dest_w * 4);
392 nsvgDeleteRasterizer(rast);
395 const int offset_x = std::max(
int(
round((gc->
size - (image->width * scale)) / 2.0f)),
396 int(-100.0f * scale));
398 const int offset_y = std::max(
int(
ceil((gc->
size +
float(dest_h)) / 2.0f)),
399 dest_h -
int(100.0f * scale));
403 std::unique_ptr<GlyphBLF> g = std::make_unique<GlyphBLF>();
406 g->advance_x = dest_w * 64;
409 g->box_xmax = dest_w * 64;
411 g->box_ymax = dest_h * 64;
414 g->pos[0] = offset_x;
415 g->pos[1] = offset_y;
419 g->num_channels = color ? 4 : 1;
421 const int buffer_size = g->dims[0] * g->dims[1] * g->num_channels;
425 memcpy(g->bitmap, render_bmp.
data(),
size_t(buffer_size));
434 (
float(render_bmp[
int64_t(offs_in + 3)]) / 255.0f));
1258 FT_UInt glyph_index,
1264 if (glyph_font != settings_font) {
1279 weight_target = std::min(weight_target + 300.0f, 900.0f);
1281 float slant_target = settings_font->
char_slant;
1283 slant_target = std::min(slant_target + 8.0f, 15.0f);
1285 float width_target = settings_font->
char_width;
1306 FT_GlyphSlot glyph =
blf_glyph_load(glyph_font, glyph_index, outline_only);
1320 if (weight != weight_target) {
1323 if (slant != slant_target) {
1326 if (width != width_target) {
1329 if (spacing != spacing_target) {
1337 FT_Outline_Translate(&glyph->outline, (FT_Pos)subpixel, 0);
1671 const float eps = 0.0001f;
1672 const float eps_sq =
eps *
eps;
1676 int j, k,
l, l_first = 0;
1685 for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
1686 const int n = ftoutline.contours[j] - contour_prev;
1687 contour_prev = ftoutline.contours[j];
1689 for (k = 0; k < n; k++) {
1690 l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
1695 if (ftoutline.tags[
l] == FT_Curve_Tag_On) {
1700 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1701 if (ftoutline.tags[
l] == FT_Curve_Tag_Conic &&
1702 ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
1711 for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
1712 const int n = ftoutline.contours[j] - contour_prev;
1713 contour_prev = ftoutline.contours[j];
1721 nu->
pntsu = onpoints[j];
1727 for (k = 0; k < n; k++) {
1728 l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
1735 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1736 if (ftoutline.tags[
l] == FT_Curve_Tag_Conic &&
1737 ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
1739 dx =
float(ftoutline.points[
l].x + ftoutline.points[l_next].x) * scale / 2.0f;
1740 dy =
float(ftoutline.points[
l].y + ftoutline.points[l_next].y) * scale / 2.0f;
1743 bezt->
vec[0][0] = (dx + (2.0f *
float(ftoutline.points[
l].x)) * scale) / 3.0f;
1744 bezt->
vec[0][1] = (dy + (2.0f *
float(ftoutline.points[
l].y)) * scale) / 3.0f;
1747 bezt->
vec[1][0] = dx;
1748 bezt->
vec[1][1] = dy;
1751 bezt->
vec[2][0] = (dx + (2.0f *
float(ftoutline.points[l_next].x)) * scale) / 3.0f;
1752 bezt->
vec[2][1] = (dy + (2.0f *
float(ftoutline.points[l_next].y)) * scale) / 3.0f;
1761 if (ftoutline.tags[
l] == FT_Curve_Tag_On) {
1762 const int l_prev = (k > 0) ? (
l - 1) : ftoutline.contours[j];
1763 const int l_next = (k < n - 1) ? (
l + 1) : l_first;
1766 if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) {
1767 bezt->
vec[0][0] =
float(ftoutline.points[l_prev].x) * scale;
1768 bezt->
vec[0][1] =
float(ftoutline.points[l_prev].y) * scale;
1771 else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) {
1772 bezt->
vec[0][0] = (
float(ftoutline.points[
l].x) +
1773 (2.0f *
float(ftoutline.points[l_prev].x))) *
1775 bezt->
vec[0][1] = (
float(ftoutline.points[
l].y) +
1776 (2.0f *
float(ftoutline.points[l_prev].y))) *
1781 bezt->
vec[0][0] =
float(ftoutline.points[
l].x) * scale -
1782 (
float(ftoutline.points[
l].x) -
float(ftoutline.points[l_prev].x)) *
1784 bezt->
vec[0][1] =
float(ftoutline.points[
l].y) * scale -
1785 (
float(ftoutline.points[
l].y) -
float(ftoutline.points[l_prev].y)) *
1791 bezt->
vec[1][0] =
float(ftoutline.points[
l].x) * scale;
1792 bezt->
vec[1][1] =
float(ftoutline.points[
l].y) * scale;
1795 if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) {
1796 bezt->
vec[2][0] =
float(ftoutline.points[l_next].x) * scale;
1797 bezt->
vec[2][1] =
float(ftoutline.points[l_next].y) * scale;
1800 else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
1801 bezt->
vec[2][0] = (
float(ftoutline.points[
l].x) +
1802 (2.0f *
float(ftoutline.points[l_next].x))) *
1804 bezt->
vec[2][1] = (
float(ftoutline.points[
l].y) +
1805 (2.0f *
float(ftoutline.points[l_next].y))) *
1810 bezt->
vec[2][0] =
float(ftoutline.points[
l].x) * scale -
1811 (
float(ftoutline.points[
l].x) -
float(ftoutline.points[l_next].x)) *
1813 bezt->
vec[2][1] =
float(ftoutline.points[
l].y) * scale -
1814 (
float(ftoutline.points[
l].y) -
float(ftoutline.points[l_next].y)) *
1827 (0.001f * 0.001f)) &&
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)