Add Chromium-only Blender WebEngine parity work
This commit is contained in:
1226
blender-5.2.0/source/blender/blenfont/intern/blf.cc
Normal file
1226
blender-5.2.0/source/blender/blenfont/intern/blf.cc
Normal file
File diff suppressed because it is too large
Load Diff
63
blender-5.2.0/source/blender/blenfont/intern/blf_default.cc
Normal file
63
blender-5.2.0/source/blender/blenfont/intern/blf_default.cc
Normal file
@@ -0,0 +1,63 @@
|
||||
/* SPDX-FileCopyrightText: 2009 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup blf
|
||||
*
|
||||
* Default API, that uses Blender's user preferences for the default size.
|
||||
*/
|
||||
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BLI_assert.h"
|
||||
|
||||
#include "BLF_api.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* call BLF_default_set first! */
|
||||
#define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1)
|
||||
|
||||
/* Default size and dpi, for BLF_draw_default. */
|
||||
static int global_font_default = -1;
|
||||
/* Keep in sync with `UI_DEFAULT_TEXT_POINTS` */
|
||||
static float global_font_size = 11.0f;
|
||||
|
||||
void BLF_default_size(const float size)
|
||||
{
|
||||
global_font_size = size;
|
||||
}
|
||||
|
||||
void BLF_default_set(const int fontid)
|
||||
{
|
||||
if ((fontid == -1) || BLF_is_loaded_id(fontid)) {
|
||||
global_font_default = fontid;
|
||||
}
|
||||
}
|
||||
|
||||
int BLF_default()
|
||||
{
|
||||
ASSERT_DEFAULT_SET;
|
||||
return global_font_default;
|
||||
}
|
||||
|
||||
int BLF_set_default()
|
||||
{
|
||||
ASSERT_DEFAULT_SET;
|
||||
|
||||
BLF_size(global_font_default, global_font_size * UI_SCALE_FAC);
|
||||
|
||||
return global_font_default;
|
||||
}
|
||||
|
||||
void BLF_draw_default(
|
||||
const float x, const float y, const float z, const char *str, const size_t str_len)
|
||||
{
|
||||
ASSERT_DEFAULT_SET;
|
||||
BLF_size(global_font_default, global_font_size * UI_SCALE_FAC);
|
||||
BLF_position(global_font_default, x, y, z);
|
||||
BLF_draw(global_font_default, str, str_len);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
61
blender-5.2.0/source/blender/blenfont/intern/blf_dir.cc
Normal file
61
blender-5.2.0/source/blender/blenfont/intern/blf_dir.cc
Normal file
@@ -0,0 +1,61 @@
|
||||
/* SPDX-FileCopyrightText: 2009 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup blf
|
||||
*
|
||||
* Manage search paths for font files.
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <ft2build.h>
|
||||
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "blf_internal.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
char *blf_dir_metrics_search(const char *filepath)
|
||||
{
|
||||
char *mfile;
|
||||
char *s;
|
||||
|
||||
mfile = BLI_strdup(filepath);
|
||||
s = strrchr(mfile, '.');
|
||||
if (s) {
|
||||
if (BLI_strnlen(s, 4) < 4) {
|
||||
MEM_delete(mfile);
|
||||
return nullptr;
|
||||
}
|
||||
s++;
|
||||
s[0] = 'a';
|
||||
s[1] = 'f';
|
||||
s[2] = 'm';
|
||||
|
||||
/* First check `.afm`. */
|
||||
if (BLI_exists(mfile)) {
|
||||
return mfile;
|
||||
}
|
||||
|
||||
/* And now check `.pfm`. */
|
||||
s[0] = 'p';
|
||||
|
||||
if (BLI_exists(mfile)) {
|
||||
return mfile;
|
||||
}
|
||||
}
|
||||
MEM_delete(mfile);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
2350
blender-5.2.0/source/blender/blenfont/intern/blf_font.cc
Normal file
2350
blender-5.2.0/source/blender/blenfont/intern/blf_font.cc
Normal file
File diff suppressed because it is too large
Load Diff
103
blender-5.2.0/source/blender/blenfont/intern/blf_font_default.cc
Normal file
103
blender-5.2.0/source/blender/blenfont/intern/blf_font_default.cc
Normal file
@@ -0,0 +1,103 @@
|
||||
/* SPDX-FileCopyrightText: 2011 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup blf
|
||||
*
|
||||
* API for loading default font files.
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "BLF_api.hh"
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_path_utils.hh"
|
||||
|
||||
#include "BKE_appdir.hh"
|
||||
|
||||
#ifdef WIN32
|
||||
# include "BLI_winstuff.h"
|
||||
#endif
|
||||
|
||||
namespace blender {
|
||||
|
||||
static int blf_load_font_default(const char *filename, const bool unique)
|
||||
{
|
||||
const std::optional<std::string> dir = BKE_appdir_folder_id(BLENDER_DATAFILES,
|
||||
BLF_DATAFILES_FONTS_DIR);
|
||||
if (!dir.has_value()) {
|
||||
fprintf(stderr,
|
||||
"%s: 'fonts' data path not found for '%s', will not be able to display text\n",
|
||||
__func__,
|
||||
filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char filepath[FILE_MAX];
|
||||
BLI_path_join(filepath, sizeof(filepath), dir->c_str(), filename);
|
||||
|
||||
return (unique) ? BLF_load_unique(filepath) : BLF_load(filepath);
|
||||
}
|
||||
|
||||
int BLF_load_default(const bool unique)
|
||||
{
|
||||
int font_id = blf_load_font_default(BLF_DEFAULT_PROPORTIONAL_FONT, unique);
|
||||
BLF_enable(font_id, BLF_DEFAULT);
|
||||
return font_id;
|
||||
}
|
||||
|
||||
int BLF_load_mono_default(const bool unique)
|
||||
{
|
||||
int font_id = blf_load_font_default(BLF_DEFAULT_MONOSPACED_FONT, unique);
|
||||
BLF_enable(font_id, BLF_MONOSPACED | BLF_DEFAULT);
|
||||
return font_id;
|
||||
}
|
||||
|
||||
static void blf_load_datafiles_dir()
|
||||
{
|
||||
const char *datafiles_fonts_dir = BLF_DATAFILES_FONTS_DIR SEP_STR;
|
||||
const std::optional<std::string> path = BKE_appdir_folder_id(BLENDER_DATAFILES,
|
||||
datafiles_fonts_dir);
|
||||
if (!path.has_value()) {
|
||||
fprintf(stderr, "Font data directory \"%s\" could not be detected!\n", datafiles_fonts_dir);
|
||||
return;
|
||||
}
|
||||
|
||||
direntry *file_list;
|
||||
uint file_list_num = BLI_filelist_dir_contents(path->c_str(), &file_list);
|
||||
for (int i = 0; i < file_list_num; i++) {
|
||||
if (S_ISDIR(file_list[i].s.st_mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *filepath = file_list[i].path;
|
||||
if (!BLI_path_extension_check_n(filepath, ".ttf", ".otf", ".woff", ".woff2", nullptr)) {
|
||||
continue;
|
||||
}
|
||||
if (BLF_is_loaded(filepath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Attempt to load the font. */
|
||||
int font_id = BLF_load(filepath);
|
||||
if (font_id == -1) {
|
||||
fprintf(stderr, "Unable to load font: %s\n", filepath);
|
||||
continue;
|
||||
}
|
||||
|
||||
BLF_enable(font_id, BLF_DEFAULT);
|
||||
}
|
||||
BLI_filelist_free(file_list, file_list_num);
|
||||
}
|
||||
|
||||
void BLF_load_font_stack()
|
||||
{
|
||||
/* Load these if not already, might have been replaced by user custom. */
|
||||
BLF_load_default(false);
|
||||
BLF_load_mono_default(false);
|
||||
blf_load_datafiles_dir();
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,128 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup blf
|
||||
*
|
||||
* Workaround for win32 which needs to use BLI_fopen to access files.
|
||||
*
|
||||
* defines #FT_New_Face__win32_compat, a drop-in replacement for \a #FT_New_Face.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
# include <ft2build.h>
|
||||
# include FT_FREETYPE_H
|
||||
|
||||
# include "MEM_guardedalloc.h"
|
||||
|
||||
# include "BLI_fileops.h"
|
||||
# include "BLI_utildefines.h"
|
||||
|
||||
# include "blf_internal.hh"
|
||||
|
||||
/* internal freetype defines */
|
||||
# define STREAM_FILE(stream) static_cast<FILE *>(stream->descriptor.pointer)
|
||||
# define FT_THROW(e) -1
|
||||
|
||||
using namespace blender;
|
||||
|
||||
static void ft_ansi_stream_close(FT_Stream stream)
|
||||
{
|
||||
fclose(STREAM_FILE(stream));
|
||||
|
||||
stream->descriptor.pointer = nullptr;
|
||||
stream->size = 0;
|
||||
stream->base = 0;
|
||||
|
||||
/* WARNING: this works but be careful!
|
||||
* Checked freetype sources, there isn't any access after closing. */
|
||||
MEM_delete(stream);
|
||||
}
|
||||
|
||||
static ulong ft_ansi_stream_io(FT_Stream stream, ulong offset, uchar *buffer, ulong count)
|
||||
{
|
||||
|
||||
if (!count && offset > stream->size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
FILE *file = STREAM_FILE(stream);
|
||||
|
||||
if (stream->pos != offset) {
|
||||
BLI_fseek(file, offset, SEEK_SET);
|
||||
}
|
||||
|
||||
return fread(buffer, 1, count, file);
|
||||
}
|
||||
|
||||
static FT_Error FT_Stream_Open__win32_compat(FT_Stream stream, const char *filepathname)
|
||||
{
|
||||
BLI_assert(stream);
|
||||
|
||||
stream->descriptor.pointer = nullptr;
|
||||
stream->pathname.pointer = (char *)filepathname;
|
||||
stream->base = 0;
|
||||
stream->pos = 0;
|
||||
stream->read = nullptr;
|
||||
stream->close = nullptr;
|
||||
|
||||
FILE *file = BLI_fopen(filepathname, "rb");
|
||||
if (!file) {
|
||||
fprintf(stderr,
|
||||
"FT_Stream_Open: "
|
||||
"could not open '%s'\n",
|
||||
filepathname);
|
||||
return FT_THROW(Cannot_Open_Resource);
|
||||
}
|
||||
|
||||
BLI_fseek(file, 0LL, SEEK_END);
|
||||
stream->size = ftell(file);
|
||||
if (!stream->size) {
|
||||
fprintf(stderr,
|
||||
"FT_Stream_Open: "
|
||||
"opened '%s' but zero-sized\n",
|
||||
filepathname);
|
||||
fclose(file);
|
||||
return FT_THROW(Cannot_Open_Stream);
|
||||
}
|
||||
|
||||
BLI_fseek(file, 0LL, SEEK_SET);
|
||||
|
||||
stream->descriptor.pointer = file;
|
||||
stream->read = ft_ansi_stream_io;
|
||||
stream->close = ft_ansi_stream_close;
|
||||
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
FT_Error FT_New_Face__win32_compat(FT_Library library,
|
||||
const char *pathname,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface)
|
||||
{
|
||||
FT_Error err;
|
||||
FT_Open_Args open;
|
||||
FT_Stream stream = static_cast<FT_Stream>(MEM_new_zeroed(sizeof(*stream), __func__));
|
||||
|
||||
open.flags = FT_OPEN_STREAM;
|
||||
open.stream = stream;
|
||||
|
||||
stream->pathname.pointer = (void *)pathname;
|
||||
|
||||
err = FT_Stream_Open__win32_compat(stream, pathname);
|
||||
if (err) {
|
||||
MEM_delete(stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = FT_Open_Face(library, &open, face_index, aface);
|
||||
/* no need to free 'stream', its handled by FT_Open_Face if an error occurs */
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
1590
blender-5.2.0/source/blender/blenfont/intern/blf_glyph.cc
Normal file
1590
blender-5.2.0/source/blender/blenfont/intern/blf_glyph.cc
Normal file
File diff suppressed because it is too large
Load Diff
407
blender-5.2.0/source/blender/blenfont/intern/blf_glyph_curves.cc
Normal file
407
blender-5.2.0/source/blender/blenfont/intern/blf_glyph_curves.cc
Normal file
@@ -0,0 +1,407 @@
|
||||
/* SPDX-FileCopyrightText: 2009 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup blf
|
||||
*
|
||||
* Glyph conversion, from FreeType to curves.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <ft2build.h>
|
||||
|
||||
#include FT_OUTLINE_H
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_geom.h"
|
||||
|
||||
#include "BLF_api.hh"
|
||||
|
||||
#include "DNA_curve_types.h"
|
||||
|
||||
#include "blf_internal.hh"
|
||||
#include "blf_internal_types.hh"
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Internal Utilities
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Convert a floating point value to a FreeType 16.16 fixed point value.
|
||||
*/
|
||||
static FT_Fixed to_16dot16(const double val)
|
||||
{
|
||||
return FT_Fixed(lround(val * 65536.0));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Convert Glyph to Curves
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* from: http://www.freetype.org/freetype2/docs/glyphs/glyphs-6.html#section-1
|
||||
*
|
||||
* Vectorial representation of FreeType glyphs
|
||||
*
|
||||
* The source format of outlines is a collection of closed paths called "contours". Each contour is
|
||||
* made of a series of line segments and bezier arcs. Depending on the file format, these can be
|
||||
* second-order or third-order polynomials. The former are also called quadratic or conic arcs, and
|
||||
* they come from the TrueType format. The latter are called cubic arcs and mostly come from the
|
||||
* Type1 format.
|
||||
*
|
||||
* Each arc is described through a series of start, end and control points.
|
||||
* Each point of the outline has a specific tag which indicates whether it is
|
||||
* used to describe a line segment or an arc.
|
||||
* The following rules are applied to decompose the contour's points into segments and arcs :
|
||||
*
|
||||
* # two successive "on" points indicate a line segment joining them.
|
||||
*
|
||||
* # one conic "off" point midst two "on" points indicates a conic bezier arc,
|
||||
* the "off" point being the control point, and the "on" ones the start and end points.
|
||||
*
|
||||
* # Two successive cubic "off" points midst two "on" points indicate a cubic bezier arc.
|
||||
* There must be exactly two cubic control points and two on points for each cubic arc
|
||||
* (using a single cubic "off" point between two "on" points is forbidden, for example).
|
||||
*
|
||||
* # finally, two successive conic "off" points forces the rasterizer to create
|
||||
* (during the scan-line conversion process exclusively) a virtual "on" point midst them,
|
||||
* at their exact middle.
|
||||
* This greatly facilitates the definition of successive conic bezier arcs.
|
||||
* Moreover, it's the way outlines are described in the TrueType specification.
|
||||
*
|
||||
* Note that it is possible to mix conic and cubic arcs in a single contour, even though no current
|
||||
* font driver produces such outlines.
|
||||
*
|
||||
* <pre>
|
||||
* * # on
|
||||
* * off
|
||||
* __---__
|
||||
* #-__ _-- -_
|
||||
* --__ _- -
|
||||
* --__ # \
|
||||
* --__ #
|
||||
* -#
|
||||
* Two "on" points
|
||||
* Two "on" points and one "conic" point
|
||||
* between them
|
||||
* *
|
||||
* # __ Two "on" points with two "conic"
|
||||
* \ - - points between them. The point
|
||||
* \ / \ marked '0' is the middle of the
|
||||
* - 0 \ "off" points, and is a 'virtual'
|
||||
* -_ _- # "on" point where the curve passes.
|
||||
* -- It does not appear in the point
|
||||
* list.
|
||||
* *
|
||||
* * # on
|
||||
* * * off
|
||||
* __---__
|
||||
* _-- -_
|
||||
* _- -
|
||||
* # \
|
||||
* #
|
||||
*
|
||||
* Two "on" points
|
||||
* and two "cubic" point
|
||||
* between them
|
||||
* </pre>
|
||||
*
|
||||
* Each glyphs original outline points are located on a grid of indivisible units.
|
||||
* The points are stored in the font file as 16-bit integer grid coordinates,
|
||||
* with the grid origin's being at (0, 0); they thus range from -16384 to 16383.
|
||||
*
|
||||
* Convert conic to bezier arcs:
|
||||
* Conic P0 P1 P2
|
||||
* Bezier B0 B1 B2 B3
|
||||
* B0=P0
|
||||
* B1=(P0+2*P1)/3
|
||||
* B2=(P2+2*P1)/3
|
||||
* B3=P2
|
||||
*/
|
||||
|
||||
static void blf_glyph_to_curves(const FT_Outline &ftoutline,
|
||||
ListBaseT<Nurb> *nurbsbase,
|
||||
const float scale)
|
||||
{
|
||||
const float eps = 0.0001f;
|
||||
const float eps_sq = eps * eps;
|
||||
Nurb *nu;
|
||||
BezTriple *bezt;
|
||||
float dx, dy;
|
||||
int j, k, l, l_first = 0;
|
||||
|
||||
/* initialize as -1 to add 1 on first loop each time */
|
||||
int contour_prev;
|
||||
|
||||
/* Start converting the FT data */
|
||||
int *onpoints = MEM_new_array_zeroed<int>(size_t(ftoutline.n_contours), "onpoints");
|
||||
|
||||
/* Get number of on-curve points for bezier-triples (including conic virtual on-points). */
|
||||
for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
|
||||
const int n = ftoutline.contours[j] - contour_prev;
|
||||
contour_prev = ftoutline.contours[j];
|
||||
|
||||
for (k = 0; k < n; k++) {
|
||||
l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
|
||||
if (k == 0) {
|
||||
l_first = l;
|
||||
}
|
||||
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_On) {
|
||||
onpoints[j]++;
|
||||
}
|
||||
|
||||
{
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
|
||||
ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
|
||||
{
|
||||
onpoints[j]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* contour loop, bezier & conic styles merged */
|
||||
for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
|
||||
const int n = ftoutline.contours[j] - contour_prev;
|
||||
contour_prev = ftoutline.contours[j];
|
||||
|
||||
/* add new curve */
|
||||
nu = MEM_new<Nurb>("objfnt_nurb");
|
||||
bezt = MEM_new_array_zeroed<BezTriple>(size_t(onpoints[j]), "objfnt_bezt");
|
||||
BLI_addtail(nurbsbase, nu);
|
||||
|
||||
nu->type = CU_BEZIER;
|
||||
nu->pntsu = onpoints[j];
|
||||
nu->resolu = 8;
|
||||
nu->flagu = CU_NURB_CYCLIC;
|
||||
nu->bezt = bezt;
|
||||
|
||||
/* individual curve loop, start-end */
|
||||
for (k = 0; k < n; k++) {
|
||||
l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
|
||||
if (k == 0) {
|
||||
l_first = l;
|
||||
}
|
||||
|
||||
/* virtual conic on-curve points */
|
||||
{
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
|
||||
ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
|
||||
{
|
||||
dx = float(ftoutline.points[l].x + ftoutline.points[l_next].x) * scale / 2.0f;
|
||||
dy = float(ftoutline.points[l].y + ftoutline.points[l_next].y) * scale / 2.0f;
|
||||
|
||||
/* left handle */
|
||||
bezt->vec[0][0] = (dx + (2.0f * float(ftoutline.points[l].x)) * scale) / 3.0f;
|
||||
bezt->vec[0][1] = (dy + (2.0f * float(ftoutline.points[l].y)) * scale) / 3.0f;
|
||||
|
||||
/* midpoint (virtual on-curve point) */
|
||||
bezt->vec[1][0] = dx;
|
||||
bezt->vec[1][1] = dy;
|
||||
|
||||
/* right handle */
|
||||
bezt->vec[2][0] = (dx + (2.0f * float(ftoutline.points[l_next].x)) * scale) / 3.0f;
|
||||
bezt->vec[2][1] = (dy + (2.0f * float(ftoutline.points[l_next].y)) * scale) / 3.0f;
|
||||
|
||||
bezt->h1 = bezt->h2 = HD_ALIGN;
|
||||
bezt->radius = 1.0f;
|
||||
bezt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* on-curve points */
|
||||
if (ftoutline.tags[l] == FT_Curve_Tag_On) {
|
||||
const int l_prev = (k > 0) ? (l - 1) : ftoutline.contours[j];
|
||||
const int l_next = (k < n - 1) ? (l + 1) : l_first;
|
||||
|
||||
/* left handle */
|
||||
if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) {
|
||||
bezt->vec[0][0] = float(ftoutline.points[l_prev].x) * scale;
|
||||
bezt->vec[0][1] = float(ftoutline.points[l_prev].y) * scale;
|
||||
bezt->h1 = HD_FREE;
|
||||
}
|
||||
else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) {
|
||||
bezt->vec[0][0] = (float(ftoutline.points[l].x) +
|
||||
(2.0f * float(ftoutline.points[l_prev].x))) *
|
||||
scale / 3.0f;
|
||||
bezt->vec[0][1] = (float(ftoutline.points[l].y) +
|
||||
(2.0f * float(ftoutline.points[l_prev].y))) *
|
||||
scale / 3.0f;
|
||||
bezt->h1 = HD_FREE;
|
||||
}
|
||||
else {
|
||||
bezt->vec[0][0] = float(ftoutline.points[l].x) * scale -
|
||||
(float(ftoutline.points[l].x) - float(ftoutline.points[l_prev].x)) *
|
||||
scale / 3.0f;
|
||||
bezt->vec[0][1] = float(ftoutline.points[l].y) * scale -
|
||||
(float(ftoutline.points[l].y) - float(ftoutline.points[l_prev].y)) *
|
||||
scale / 3.0f;
|
||||
bezt->h1 = HD_VECT;
|
||||
}
|
||||
|
||||
/* midpoint (on-curve point) */
|
||||
bezt->vec[1][0] = float(ftoutline.points[l].x) * scale;
|
||||
bezt->vec[1][1] = float(ftoutline.points[l].y) * scale;
|
||||
|
||||
/* right handle */
|
||||
if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) {
|
||||
bezt->vec[2][0] = float(ftoutline.points[l_next].x) * scale;
|
||||
bezt->vec[2][1] = float(ftoutline.points[l_next].y) * scale;
|
||||
bezt->h2 = HD_FREE;
|
||||
}
|
||||
else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
|
||||
bezt->vec[2][0] = (float(ftoutline.points[l].x) +
|
||||
(2.0f * float(ftoutline.points[l_next].x))) *
|
||||
scale / 3.0f;
|
||||
bezt->vec[2][1] = (float(ftoutline.points[l].y) +
|
||||
(2.0f * float(ftoutline.points[l_next].y))) *
|
||||
scale / 3.0f;
|
||||
bezt->h2 = HD_FREE;
|
||||
}
|
||||
else {
|
||||
bezt->vec[2][0] = float(ftoutline.points[l].x) * scale -
|
||||
(float(ftoutline.points[l].x) - float(ftoutline.points[l_next].x)) *
|
||||
scale / 3.0f;
|
||||
bezt->vec[2][1] = float(ftoutline.points[l].y) * scale -
|
||||
(float(ftoutline.points[l].y) - float(ftoutline.points[l_next].y)) *
|
||||
scale / 3.0f;
|
||||
bezt->h2 = HD_VECT;
|
||||
}
|
||||
|
||||
/* get the handles that are aligned, tricky...
|
||||
* - check if one of them is a vector handle.
|
||||
* - dist_squared_to_line_v2, check if the three beztriple points are on one line
|
||||
* - len_squared_v2v2, see if there's a distance between the three points
|
||||
* - len_squared_v2v2 again, to check the angle between the handles
|
||||
*/
|
||||
if ((bezt->h1 != HD_VECT && bezt->h2 != HD_VECT) &&
|
||||
(dist_squared_to_line_v2(bezt->vec[0], bezt->vec[1], bezt->vec[2]) <
|
||||
(0.001f * 0.001f)) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[1]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > eps_sq) &&
|
||||
(len_squared_v2v2(bezt->vec[0], bezt->vec[2]) >
|
||||
max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]),
|
||||
len_squared_v2v2(bezt->vec[1], bezt->vec[2]))))
|
||||
{
|
||||
bezt->h1 = bezt->h2 = HD_ALIGN;
|
||||
}
|
||||
bezt->radius = 1.0f;
|
||||
bezt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MEM_delete(onpoints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale all fields of a glyph metrics by the ratio `num / den`,
|
||||
* useful when converting between two different EM units.
|
||||
*
|
||||
* \param m: Glyph metrics to rescale in-place.
|
||||
* \param num: Destination face's `units_per_EM` (the face we're converting *to*).
|
||||
* \param den: Source face's `units_per_EM` (the face the glyph was loaded *from*).
|
||||
*/
|
||||
static void blf_glyph_metrics_scale(FT_Glyph_Metrics &m, const FT_Long num, const FT_Long den)
|
||||
{
|
||||
m.width = FT_MulDiv(m.width, num, den);
|
||||
m.height = FT_MulDiv(m.height, num, den);
|
||||
m.horiBearingX = FT_MulDiv(m.horiBearingX, num, den);
|
||||
m.horiBearingY = FT_MulDiv(m.horiBearingY, num, den);
|
||||
m.horiAdvance = FT_MulDiv(m.horiAdvance, num, den);
|
||||
m.vertBearingX = FT_MulDiv(m.vertBearingX, num, den);
|
||||
m.vertBearingY = FT_MulDiv(m.vertBearingY, num, den);
|
||||
m.vertAdvance = FT_MulDiv(m.vertAdvance, num, den);
|
||||
}
|
||||
|
||||
static FT_GlyphSlot blf_glyphslot_ensure_outline(FontBLF *font, uint charcode, bool use_fallback)
|
||||
{
|
||||
if (charcode < 32) {
|
||||
if (ELEM(charcode, 0x10, 0x13)) {
|
||||
/* Do not render line feed or carriage return. #134972. */
|
||||
return nullptr;
|
||||
}
|
||||
/* Other C0 controls (U+0000 - U+001F) can show as space. #135421. */
|
||||
/* TODO: Return all but TAB as ".notdef" character when we have our own. */
|
||||
charcode = ' ';
|
||||
}
|
||||
|
||||
/* Glyph might not come from the initial font. */
|
||||
FontBLF *font_with_glyph = font;
|
||||
FT_UInt glyph_index = use_fallback ? blf_glyph_index_from_charcode(&font_with_glyph, charcode) :
|
||||
blf_get_char_index(font_with_glyph, charcode);
|
||||
|
||||
if (!glyph_index) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!blf_ensure_face(font_with_glyph)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FT_GlyphSlot glyph = blf_glyph_render_outline(font, font_with_glyph, glyph_index, charcode, 0);
|
||||
|
||||
if (font != font_with_glyph) {
|
||||
if (!blf_ensure_face(font)) {
|
||||
return nullptr;
|
||||
}
|
||||
const FT_Long num = FT_Long(font->face->units_per_EM);
|
||||
const FT_Long den = FT_Long(font_with_glyph->face->units_per_EM);
|
||||
const double ratio = double(num) / double(den);
|
||||
const FT_Matrix transform = {to_16dot16(ratio), 0, 0, to_16dot16(ratio)};
|
||||
FT_Outline_Transform(&glyph->outline, &transform);
|
||||
glyph->advance.x = FT_Pos(double(glyph->advance.x) * ratio);
|
||||
blf_glyph_metrics_scale(glyph->metrics, num, den);
|
||||
}
|
||||
|
||||
return glyph;
|
||||
}
|
||||
|
||||
bool blf_character_to_curves(FontBLF *font,
|
||||
uint unicode,
|
||||
ListBaseT<Nurb> *nurbsbase,
|
||||
const float scale,
|
||||
bool use_fallback,
|
||||
float *r_advance,
|
||||
rctf *r_bounds)
|
||||
{
|
||||
FT_GlyphSlot glyph = blf_glyphslot_ensure_outline(font, unicode, use_fallback);
|
||||
if (!glyph) {
|
||||
*r_advance = 0.0f;
|
||||
*r_bounds = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
return false;
|
||||
}
|
||||
|
||||
blf_glyph_to_curves(glyph->outline, nurbsbase, scale);
|
||||
*r_advance = float(glyph->advance.x) * scale;
|
||||
|
||||
const FT_Glyph_Metrics &m = glyph->metrics;
|
||||
r_bounds->xmin = float(m.horiBearingX) * scale;
|
||||
r_bounds->xmax = float(m.horiBearingX + m.width) * scale;
|
||||
r_bounds->ymin = float(m.horiBearingY - m.height) * scale;
|
||||
r_bounds->ymax = float(m.horiBearingY) * scale;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
251
blender-5.2.0/source/blender/blenfont/intern/blf_internal.hh
Normal file
251
blender-5.2.0/source/blender/blenfont/intern/blf_internal.hh
Normal file
@@ -0,0 +1,251 @@
|
||||
/* SPDX-FileCopyrightText: 2009 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup blf
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_array.hh"
|
||||
#include "BLI_bounds_types.hh"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct FontBLF;
|
||||
struct GlyphBLF;
|
||||
struct GlyphCacheBLF;
|
||||
struct Nurb;
|
||||
struct ResultBLF;
|
||||
struct rcti;
|
||||
struct rctf;
|
||||
enum class BLFWrapMode;
|
||||
|
||||
/**
|
||||
* Max number of FontBLFs in memory. Take care that every font has a glyph cache per size/dpi,
|
||||
* so we don't need load the same font with different size, just load one and call #BLF_size.
|
||||
*/
|
||||
#define BLF_MAX_FONT 64
|
||||
|
||||
/**
|
||||
* If enabled, glyphs positions are on 64ths of a pixel. Disabled, they are on whole pixels.
|
||||
*/
|
||||
#define BLF_SUBPIXEL_POSITION
|
||||
|
||||
/**
|
||||
* If enabled, glyphs are rendered at multiple horizontal subpixel positions.
|
||||
*/
|
||||
#define BLF_SUBPIXEL_AA
|
||||
|
||||
/** Maximum number of opened FT_Face objects managed by cache. 0 is default of 2. */
|
||||
#define BLF_CACHE_MAX_FACES 8
|
||||
/** Maximum number of opened FT_Size objects managed by cache. 0 is default of 4 */
|
||||
#define BLF_CACHE_MAX_SIZES 16
|
||||
/** Maximum number of bytes to use for cached data nodes. 0 is default of 200,000. */
|
||||
#define BLF_CACHE_BYTES 0x100000
|
||||
|
||||
/**
|
||||
* Offset from icon id to Unicode Supplementary Private Use Area-B,
|
||||
* added with Unicode 2.0. 65,536 code-points at U+100000..U+10FFFF.
|
||||
*/
|
||||
#define BLF_ICON_OFFSET 0x100000L
|
||||
|
||||
/**
|
||||
* We assume square pixels at a fixed DPI of 72, scaling only the size. Therefore
|
||||
* font size = points = pixels, i.e. a size of 20 will result in a 20-pixel EM square.
|
||||
* Although we could use the actual monitor DPI instead, we would then have to scale
|
||||
* the size to cancel that out. Other libraries like Skia use this same fixed value.
|
||||
*/
|
||||
#define BLF_DPI 72
|
||||
|
||||
/** Font array. */
|
||||
extern FontBLF *global_font[BLF_MAX_FONT];
|
||||
|
||||
void blf_batch_draw_begin(FontBLF *font);
|
||||
void blf_batch_draw();
|
||||
|
||||
/**
|
||||
* Some font have additional file with metrics information,
|
||||
* in general, the extension of the file is: `.afm` or `.pfm`
|
||||
*/
|
||||
char *blf_dir_metrics_search(const char *filepath);
|
||||
|
||||
int blf_font_init();
|
||||
void blf_font_exit();
|
||||
|
||||
/**
|
||||
* Return glyph id from char-code.
|
||||
*/
|
||||
uint blf_get_char_index(FontBLF *font, uint charcode);
|
||||
|
||||
/**
|
||||
* Create an FT_Face for this font if not already existing.
|
||||
*/
|
||||
bool blf_ensure_face(FontBLF *font);
|
||||
void blf_ensure_size(FontBLF *font);
|
||||
|
||||
void blf_draw_buffer__start(FontBLF *font);
|
||||
void blf_draw_buffer__end();
|
||||
|
||||
FontBLF *blf_font_new_from_filepath(const char *filepath);
|
||||
FontBLF *blf_font_new_from_mem(const char *mem_name, const unsigned char *mem, size_t mem_size);
|
||||
void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, size_t mem_size);
|
||||
|
||||
/**
|
||||
* Change font's output size. Returns true if successful in changing the size.
|
||||
*/
|
||||
bool blf_font_size(FontBLF *font, float size);
|
||||
|
||||
void blf_font_draw(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
void blf_font_draw__wrap(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
|
||||
/**
|
||||
* \param outline_alpha: Alpha value between 0 and 1.
|
||||
*/
|
||||
void blf_draw_svg_icon(FontBLF *font,
|
||||
uint icon_id,
|
||||
float size,
|
||||
const float color[4] = nullptr,
|
||||
float outline_alpha = 1.0f,
|
||||
bool multicolor = false,
|
||||
FunctionRef<void(std::string &)> edit_source_cb = nullptr);
|
||||
|
||||
Array<uchar> blf_svg_icon_bitmap(FontBLF *font,
|
||||
uint icon_id,
|
||||
float size,
|
||||
int *r_width,
|
||||
int *r_height,
|
||||
bool multicolor = false,
|
||||
FunctionRef<void(std::string &)> edit_source_cb = nullptr);
|
||||
|
||||
Vector<StringRef> blf_font_string_wrap(FontBLF *font,
|
||||
StringRef str,
|
||||
int max_pixel_width,
|
||||
BLFWrapMode mode);
|
||||
|
||||
/**
|
||||
* Use fixed column width, but an UTF8 character may occupy multiple columns.
|
||||
*/
|
||||
int blf_font_draw_mono(
|
||||
FontBLF *font, const char *str, size_t str_len, int cwidth, int tab_columns);
|
||||
void blf_font_draw_buffer(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
void blf_font_draw_buffer__wrap(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
size_t blf_font_width_to_strlen(
|
||||
FontBLF *font, const char *str, size_t str_len, int width, int *r_width);
|
||||
size_t blf_font_width_to_rstrlen(
|
||||
FontBLF *font, const char *str, size_t str_len, int width, int *r_width);
|
||||
void blf_font_boundbox(
|
||||
FontBLF *font, const char *str, size_t str_len, rcti *r_box, ResultBLF *r_info);
|
||||
void blf_font_boundbox__wrap(
|
||||
FontBLF *font, const char *str, size_t str_len, rcti *r_box, ResultBLF *r_info);
|
||||
void blf_font_width_and_height(FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
float *r_width,
|
||||
float *r_height,
|
||||
ResultBLF *r_info);
|
||||
float blf_font_width(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
float blf_font_height(FontBLF *font, const char *str, size_t str_len, ResultBLF *r_info);
|
||||
float blf_font_fixed_width(FontBLF *font);
|
||||
int blf_font_glyph_advance(FontBLF *font, const char *str);
|
||||
int blf_font_height_max(FontBLF *font);
|
||||
int blf_font_width_max(FontBLF *font);
|
||||
int blf_font_descender(FontBLF *font);
|
||||
int blf_font_ascender(FontBLF *font);
|
||||
bool blf_font_bounds_max(FontBLF *font, rctf *r_bounds);
|
||||
|
||||
char *blf_display_name(FontBLF *font);
|
||||
|
||||
void blf_font_boundbox_foreach_glyph(
|
||||
FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
bool (*user_fn)(const char *str, size_t str_step_ofs, const rcti *bounds, void *user_data),
|
||||
void *user_data);
|
||||
|
||||
void blf_font_info_foreach_glyph(
|
||||
FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
FunctionRef<void(int index, size_t byte_offset, int byte_len, int advance_x)> callback);
|
||||
|
||||
size_t blf_str_offset_from_cursor_position(FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
int location_x);
|
||||
|
||||
void blf_str_offset_to_glyph_bounds(FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_offset,
|
||||
rcti *r_glyph_bounds);
|
||||
|
||||
Vector<Bounds<int>> blf_str_selection_boxes(
|
||||
FontBLF *font, const char *str, size_t str_len, size_t sel_start, size_t sel_length);
|
||||
|
||||
int blf_str_offset_to_cursor(
|
||||
FontBLF *font, const char *str, size_t str_len, size_t str_offset, int cursor_width);
|
||||
|
||||
void blf_font_free(FontBLF *font);
|
||||
|
||||
GlyphCacheBLF *blf_glyph_cache_acquire(FontBLF *font);
|
||||
void blf_glyph_cache_release(FontBLF *font);
|
||||
void blf_glyph_cache_clear(FontBLF *font);
|
||||
|
||||
/**
|
||||
* Create (or load from cache) a fully-rendered bitmap glyph.
|
||||
*/
|
||||
GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode, uint8_t subpixel = 0);
|
||||
|
||||
#ifdef BLF_SUBPIXEL_AA
|
||||
GlyphBLF *blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int32_t pen_x);
|
||||
#endif
|
||||
|
||||
GlyphBLF *blf_glyph_ensure_icon(GlyphCacheBLF *gc,
|
||||
uint icon_id,
|
||||
bool color = false,
|
||||
FunctionRef<void(std::string &)> edit_source_cb = nullptr);
|
||||
|
||||
/* blf_glyph.cc */
|
||||
void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int x, int y);
|
||||
|
||||
#ifdef FT_FREETYPE_H
|
||||
FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode);
|
||||
FT_GlyphSlot blf_glyph_render_outline(FontBLF *settings_font,
|
||||
FontBLF *glyph_font,
|
||||
FT_UInt glyph_index,
|
||||
uint charcode,
|
||||
int fixed_width);
|
||||
#endif
|
||||
|
||||
/* blf_glyph_curves.cc */
|
||||
|
||||
/**
|
||||
* Convert a character's outlines into curves.
|
||||
* \return success if the character was found and converted.
|
||||
*/
|
||||
bool blf_character_to_curves(FontBLF *font,
|
||||
unsigned int unicode,
|
||||
ListBaseT<Nurb> *nurbsbase,
|
||||
const float scale,
|
||||
bool use_fallback,
|
||||
float *r_advance,
|
||||
rctf *r_bounds);
|
||||
|
||||
} // namespace blender
|
||||
|
||||
#ifdef WIN32
|
||||
/* `blf_font_win32_compat.cc` */
|
||||
|
||||
# ifdef FT_FREETYPE_H
|
||||
extern FT_Error FT_New_Face__win32_compat(FT_Library library,
|
||||
const char *pathname,
|
||||
FT_Long face_index,
|
||||
FT_Face *aface);
|
||||
# endif
|
||||
#endif
|
||||
@@ -0,0 +1,420 @@
|
||||
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup blf
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
|
||||
#include "DNA_vec_types.h"
|
||||
|
||||
#include "BLF_api.hh"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_mutex.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "GPU_shader_shared.hh"
|
||||
#include "GPU_storage_buffer.hh"
|
||||
#include "GPU_texture.hh"
|
||||
|
||||
#include <ft2build.h>
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct FontBLF;
|
||||
struct GlyphCacheBLF;
|
||||
struct GlyphBLF;
|
||||
|
||||
namespace gpu {
|
||||
class Batch;
|
||||
class VertBuf;
|
||||
} // namespace gpu
|
||||
struct GPUVertBufRaw;
|
||||
|
||||
namespace ocio {
|
||||
class ColorSpace;
|
||||
} // namespace ocio
|
||||
using ColorSpace = ocio::ColorSpace;
|
||||
|
||||
#include FT_MULTIPLE_MASTERS_H /* Variable font support. */
|
||||
|
||||
/** Maximum variation axes per font. */
|
||||
#define BLF_VARIATIONS_MAX 16
|
||||
|
||||
#define MAKE_DVAR_TAG(a, b, c, d) \
|
||||
((uint32_t(a) << 24u) | (uint32_t(b) << 16u) | (uint32_t(c) << 8u) | (uint32_t(d)))
|
||||
|
||||
#define BLF_VARIATION_AXIS_WEIGHT MAKE_DVAR_TAG('w', 'g', 'h', 't') /* `wght` weight axis. */
|
||||
#define BLF_VARIATION_AXIS_SLANT MAKE_DVAR_TAG('s', 'l', 'n', 't') /* `slnt` slant axis. */
|
||||
#define BLF_VARIATION_AXIS_WIDTH MAKE_DVAR_TAG('w', 'd', 't', 'h') /* `wdth` width axis. */
|
||||
#define BLF_VARIATION_AXIS_SPACING MAKE_DVAR_TAG('s', 'p', 'a', 'c') /* `spac` spacing axis. */
|
||||
#define BLF_VARIATION_AXIS_OPTSIZE MAKE_DVAR_TAG('o', 'p', 's', 'z') /* `opsz` optical size. */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Sub-Pixel Offset & Utilities
|
||||
*
|
||||
* Free-type uses fixed point precision for sub-pixel offsets.
|
||||
* Utility functions here avoid exposing the details in the BLF API.
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* This is an internal type that represents sub-pixel positioning,
|
||||
* users of this type are to use `ft_pix_*` functions to keep scaling/rounding in one place.
|
||||
*/
|
||||
using ft_pix = int32_t;
|
||||
|
||||
/* Macros copied from `include/freetype/internal/ftobjs.h`. */
|
||||
|
||||
#define FT_PIX_FLOOR(x) ((x) & ~63)
|
||||
#define FT_PIX_ROUND(x) FT_PIX_FLOOR((x) + 32)
|
||||
#define FT_PIX_CEIL(x) ((x) + 63)
|
||||
|
||||
inline int ft_pix_to_int(ft_pix v)
|
||||
{
|
||||
return int(v >> 6);
|
||||
}
|
||||
|
||||
inline int ft_pix_to_int_floor(ft_pix v)
|
||||
{
|
||||
return int(v >> 6); /* No need for explicit floor as the bits are removed when shifting. */
|
||||
}
|
||||
|
||||
inline int ft_pix_to_int_ceil(ft_pix v)
|
||||
{
|
||||
return (FT_PIX_CEIL(v) >> 6);
|
||||
}
|
||||
|
||||
inline ft_pix ft_pix_from_int(int v)
|
||||
{
|
||||
return v * 64;
|
||||
}
|
||||
|
||||
inline ft_pix ft_pix_from_float(float v)
|
||||
{
|
||||
return lroundf(v * 64.0f);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
#define BLF_BATCH_DRAW_LEN_MAX 128 /* in glyph */
|
||||
|
||||
/** Number of characters in #KerningCacheBLF.table. */
|
||||
#define KERNING_CACHE_TABLE_SIZE 128
|
||||
|
||||
/** A value in the kerning cache that indicates it is not yet set. */
|
||||
#define KERNING_ENTRY_UNSET INT_MAX
|
||||
|
||||
struct BatchBLF {
|
||||
/** Can only batch glyph from the same font. */
|
||||
FontBLF *font;
|
||||
gpu::Batch *batch;
|
||||
gpu::StorageBuf *glyph_buf;
|
||||
int glyph_len;
|
||||
/** Copy of `font->pos`. */
|
||||
int ofs[2];
|
||||
/** Previous call `modelmatrix`. */
|
||||
float mat[4][4];
|
||||
bool enabled, active, simple_shader;
|
||||
GlyphCacheBLF *glyph_cache;
|
||||
|
||||
GlyphQuad glyph_data[BLF_BATCH_DRAW_LEN_MAX];
|
||||
};
|
||||
|
||||
extern BatchBLF g_batch;
|
||||
|
||||
struct KerningCacheBLF {
|
||||
/**
|
||||
* Cache a ASCII glyph pairs. Only store the x offset we are interested in,
|
||||
* instead of the full #FT_Vector since it's not used for drawing at the moment.
|
||||
*/
|
||||
int ascii_table[KERNING_CACHE_TABLE_SIZE][KERNING_CACHE_TABLE_SIZE];
|
||||
};
|
||||
|
||||
struct GlyphCacheKey {
|
||||
uint charcode;
|
||||
uint8_t subpixel;
|
||||
friend bool operator==(const GlyphCacheKey &a, const GlyphCacheKey &b)
|
||||
{
|
||||
return a.charcode == b.charcode && a.subpixel == b.subpixel;
|
||||
}
|
||||
uint64_t hash() const
|
||||
{
|
||||
return get_default_hash(charcode, subpixel);
|
||||
}
|
||||
};
|
||||
|
||||
struct GlyphCacheBLF {
|
||||
/** Font size. */
|
||||
float size;
|
||||
|
||||
int char_weight;
|
||||
float char_slant;
|
||||
float char_width;
|
||||
float char_spacing;
|
||||
|
||||
bool bold;
|
||||
bool italic;
|
||||
|
||||
/** Column width when printing monospaced. */
|
||||
int fixed_width;
|
||||
|
||||
/** The glyphs. */
|
||||
Map<GlyphCacheKey, std::unique_ptr<GlyphBLF>> glyphs;
|
||||
|
||||
/** Texture array, to draw the glyphs. */
|
||||
gpu::Texture *texture;
|
||||
char *bitmap_result;
|
||||
int bitmap_len;
|
||||
int bitmap_len_landed;
|
||||
int bitmap_len_alloc;
|
||||
|
||||
~GlyphCacheBLF();
|
||||
};
|
||||
|
||||
struct GlyphBLF {
|
||||
/** The character, as UTF32. */
|
||||
unsigned int c;
|
||||
|
||||
/** Freetype2 index, to speed-up the search. */
|
||||
FT_UInt idx;
|
||||
|
||||
/** Glyph bounding-box. */
|
||||
ft_pix box_xmin;
|
||||
ft_pix box_xmax;
|
||||
ft_pix box_ymin;
|
||||
ft_pix box_ymax;
|
||||
|
||||
ft_pix advance_x;
|
||||
uint8_t subpixel;
|
||||
|
||||
/** The difference in bearings when hinting is active, zero otherwise. */
|
||||
ft_pix lsb_delta;
|
||||
ft_pix rsb_delta;
|
||||
|
||||
/** Position inside the texture where this glyph is store. */
|
||||
int offset;
|
||||
|
||||
/**
|
||||
* Bitmap data, from freetype. Take care that this
|
||||
* can be NULL.
|
||||
*/
|
||||
unsigned char *bitmap;
|
||||
|
||||
/** Glyph width and height. */
|
||||
int dims[2];
|
||||
int pitch;
|
||||
int num_channels;
|
||||
|
||||
/**
|
||||
* X and Y bearing of the glyph.
|
||||
* The X bearing is from the origin to the glyph left bounding-box edge.
|
||||
* The Y bearing is from the baseline to the top of the glyph edge.
|
||||
*/
|
||||
int pos[2];
|
||||
|
||||
GlyphCacheBLF *glyph_cache;
|
||||
|
||||
~GlyphBLF();
|
||||
};
|
||||
|
||||
struct FontBufInfoBLF {
|
||||
/** For draw to buffer, always set this to NULL after finish! */
|
||||
float *fbuf;
|
||||
|
||||
/** The same but unsigned char. */
|
||||
unsigned char *cbuf;
|
||||
|
||||
/** Buffer size, keep signed so comparisons with negative values work. */
|
||||
int dims[2];
|
||||
|
||||
/** The number of channels in the buffer. Can be either 1 or 4 for grayscale and color buffers
|
||||
* respectively. The red channel of the color is used in case of a grayscale buffer. */
|
||||
int channel_count;
|
||||
|
||||
/** Color-space of the byte buffer (float is scene linear). */
|
||||
const ColorSpace *colorspace;
|
||||
|
||||
/** The color, the alphas is get from the glyph! (color is sRGB space). The red channel of the
|
||||
* color is used in case of a grayscale buffer. */
|
||||
float col_init[4];
|
||||
/** Cached conversion from 'col_init'. */
|
||||
unsigned char col_char[4];
|
||||
float col_float[4];
|
||||
};
|
||||
|
||||
struct FontMetrics {
|
||||
/** Indicate that these values have been properly loaded. */
|
||||
bool valid;
|
||||
/** This font's default weight, 100-900, 400 is normal. */
|
||||
short weight;
|
||||
/** This font's default width, 1 is normal, 2 is twice as wide. */
|
||||
float width;
|
||||
/** This font's slant in clockwise degrees, 0 being upright. */
|
||||
float slant;
|
||||
/** This font's default spacing, 1 is normal. */
|
||||
float spacing;
|
||||
|
||||
/** Number of font units in an EM square. 2048, 1024, 1000 are typical. */
|
||||
short units_per_EM; /* */
|
||||
/** Design classification from OS/2 sFamilyClass. */
|
||||
short family_class;
|
||||
/** Style classification from OS/2 fsSelection. */
|
||||
short selection_flags;
|
||||
/** Total number of glyphs in the font. */
|
||||
int num_glyphs;
|
||||
/** Minimum Unicode index, typically 0x0020. */
|
||||
short first_charindex;
|
||||
/** Maximum Unicode index, or 0xFFFF if greater than. */
|
||||
short last_charindex;
|
||||
|
||||
/**
|
||||
* Positive number of font units from baseline to top of typical capitals. Can be slightly more
|
||||
* than cap height when head serifs, terminals, or apexes extend above cap line. */
|
||||
short ascender;
|
||||
/** Negative (!) number of font units from baseline to bottom of letters like `gjpqy`. */
|
||||
short descender;
|
||||
/** Positive number of font units between consecutive baselines. */
|
||||
short line_height;
|
||||
/** Font units from baseline to lowercase mean line, typically to top of "x". */
|
||||
short x_height;
|
||||
/** Font units from baseline to top of capital letters, specifically "H". */
|
||||
short cap_height;
|
||||
/** Ratio width to height of lowercase "O". Reliable indication of font proportion. */
|
||||
float o_proportion;
|
||||
/** Font unit maximum horizontal advance for all glyphs in font. Can help with wrapping. */
|
||||
short max_advance_width;
|
||||
/** As above but only for vertical layout fonts, otherwise is set to line_height value. */
|
||||
short max_advance_height;
|
||||
|
||||
/** Negative (!) number of font units below baseline to center (!) of underlining stem. */
|
||||
short underline_position;
|
||||
/** thickness of the underline in font units. */
|
||||
short underline_thickness;
|
||||
/** Positive number of font units above baseline to the top (!) of strikeout stroke. */
|
||||
short strikeout_position;
|
||||
/** thickness of the strikeout line in font units. */
|
||||
short strikeout_thickness;
|
||||
/** EM size font units of recommended subscript letters. */
|
||||
short subscript_size;
|
||||
/** Horizontal offset before first subscript character, typically 0. */
|
||||
short subscript_xoffset;
|
||||
/** Positive number of font units above baseline for subscript characters. */
|
||||
short subscript_yoffset;
|
||||
/** EM size font units of recommended superscript letters. */
|
||||
short superscript_size;
|
||||
/** Horizontal offset before first superscript character, typically 0. */
|
||||
short superscript_xoffset;
|
||||
/** Positive (!) number of font units below baseline for subscript characters. */
|
||||
short superscript_yoffset;
|
||||
};
|
||||
|
||||
struct FontBLF {
|
||||
/** The full path to font file or NULL when from memory. */
|
||||
char *filepath;
|
||||
|
||||
/** Pointer to in-memory font, or NULL when from a file. */
|
||||
const void *mem;
|
||||
size_t mem_size;
|
||||
/** Handle for in-memory fonts to avoid loading them multiple times. */
|
||||
char *mem_name;
|
||||
|
||||
/**
|
||||
* Copied from the SFNT OS/2 table. Bit flags for unicode blocks and ranges
|
||||
* considered "functional". Cached here because face might not always exist.
|
||||
* See: https://docs.microsoft.com/en-us/typography/opentype/spec/os2#ur
|
||||
*/
|
||||
uint unicode_ranges[4];
|
||||
|
||||
/** Number of references to this font object. When it reaches zero, font is unloaded. */
|
||||
std::atomic<uint32_t> reference_count;
|
||||
|
||||
/** Aspect ratio or scale. */
|
||||
float aspect[3];
|
||||
|
||||
/** Initial position for draw the text. */
|
||||
int pos[3];
|
||||
|
||||
/** Angle in radians. */
|
||||
float angle;
|
||||
|
||||
/** Shadow type. */
|
||||
FontShadowType shadow;
|
||||
|
||||
/** And shadow offset. */
|
||||
int shadow_x;
|
||||
int shadow_y;
|
||||
|
||||
/** Shadow color. */
|
||||
unsigned char shadow_color[4];
|
||||
|
||||
/** Main text color. */
|
||||
unsigned char color[4];
|
||||
|
||||
/** Clipping rectangle. */
|
||||
rcti clip_rec;
|
||||
|
||||
/** The width to wrap the text, see #BLF_WORD_WRAP. */
|
||||
int wrap_width;
|
||||
BLFWrapMode wrap_mode;
|
||||
|
||||
/** Font size. */
|
||||
float size;
|
||||
|
||||
/** Axes data for Adobe MM, TrueType GX, or OpenType variation fonts. */
|
||||
FT_MM_Var *variations;
|
||||
|
||||
/* Character variations. */
|
||||
|
||||
/** Wight in range: 100 - 900, 400 = normal. */
|
||||
int char_weight;
|
||||
/** Slant in clockwise degrees. 0.0 = upright. */
|
||||
float char_slant;
|
||||
/** Factor of normal character width. 1.0 = normal. */
|
||||
float char_width;
|
||||
/** Factor of normal character spacing. 0.0 = normal. */
|
||||
float char_spacing;
|
||||
|
||||
/** Max texture size. */
|
||||
int tex_size_max;
|
||||
|
||||
/** Font options. */
|
||||
FontFlags flags;
|
||||
|
||||
/**
|
||||
* List of glyph caches (#GlyphCacheBLF) for this font for size, DPI, bold, italic.
|
||||
* Use `blf_glyph_cache_acquire(font)` and `blf_glyph_cache_release(font)` to access cache!
|
||||
*/
|
||||
Vector<std::unique_ptr<GlyphCacheBLF>> cache;
|
||||
|
||||
/** Cache of unscaled kerning values. Will be NULL if font does not have kerning. */
|
||||
KerningCacheBLF *kerning_cache;
|
||||
|
||||
/** Freetype2 lib handle. */
|
||||
FT_Library ft_lib;
|
||||
|
||||
/** Freetype2 face. */
|
||||
FT_Face face;
|
||||
|
||||
/** Point to face->size or to cache's size. */
|
||||
FT_Size ft_size;
|
||||
|
||||
/** Copy of the font->face->face_flags, in case we don't have a face loaded. */
|
||||
FT_Long face_flags;
|
||||
|
||||
/** Details about the font's design and style and sizes (in un-sized font units). */
|
||||
FontMetrics metrics;
|
||||
|
||||
/** Data for buffer usage (drawing into a texture buffer) */
|
||||
FontBufInfoBLF buf_info;
|
||||
|
||||
/** Mutex lock for glyph cache. */
|
||||
Mutex glyph_cache_mutex;
|
||||
};
|
||||
|
||||
} // namespace blender
|
||||
425
blender-5.2.0/source/blender/blenfont/intern/blf_thumbs.cc
Normal file
425
blender-5.2.0/source/blender/blenfont/intern/blf_thumbs.cc
Normal file
@@ -0,0 +1,425 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup blf
|
||||
*
|
||||
* Utility function to generate font preview images.
|
||||
*
|
||||
* Isolate since this needs to be called by #ImBuf code (bad level call).
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <ft2build.h>
|
||||
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_ADVANCES_H /* For FT_Get_Advance */
|
||||
#include FT_TRUETYPE_IDS_H /* Code-point coverage constants. */
|
||||
#include FT_TRUETYPE_TABLES_H /* For TT_OS2 */
|
||||
|
||||
#include "BLI_math_bits.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "blf_internal_types.hh"
|
||||
|
||||
#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* Maximum length of text sample in char32_t, including null terminator. */
|
||||
#define BLF_SAMPLE_LEN 5
|
||||
|
||||
struct UnicodeSample {
|
||||
char32_t sample[BLF_SAMPLE_LEN];
|
||||
int field; /* 'OS/2' table ulUnicodeRangeX field (1-4). */
|
||||
FT_ULong mask; /* 'OS/2' table ulUnicodeRangeX bit mask. */
|
||||
};
|
||||
|
||||
/* The seemingly arbitrary order that follows is to help quickly find the most-likely designed
|
||||
* intent of the font. Many feature-specific fonts contain Latin, Greek, & Coptic characters so
|
||||
* those need to be checked last. */
|
||||
static const UnicodeSample unicode_samples[] = {
|
||||
/* Chinese, Japanese, Korean, ordered specific to general. */
|
||||
{U"\ud55c\uad6d\uc5b4", 2, TT_UCR_HANGUL}, /* 한국어 */
|
||||
{U"\u3042\u30a2\u4e9c", 2, TT_UCR_HIRAGANA}, /* あア亜 */
|
||||
{U"\u30a2\u30a4\u4e9c", 2, TT_UCR_KATAKANA}, /* アイ亜 */
|
||||
{U"\u1956\u195b\u1966", 3, TT_UCR_TAI_LE}, /* ᥖᥛᥦ */
|
||||
{U"\u3105\u3106\u3107", 2, TT_UCR_BOPOMOFO}, /* ㄅㄆㄇ */
|
||||
{U"\ua840\ua841\ua85d", 2, TT_UCR_PHAGSPA}, /* ꡀꡁꡝ */
|
||||
{U"\u5e03\u4e01\u4f53", 2, TT_UCR_CJK_UNIFIED_IDEOGRAPHS}, /* 布丁体 */
|
||||
/* Languages in the BMP with a coverage bit. */
|
||||
{U"\u05d0\u05da\u05e4", 1, TT_UCR_HEBREW},
|
||||
{U"\ua500\ua502\ua549", 1, TT_UCR_VAI},
|
||||
{U"\ufee6\ufef4\ufeb3", 1, TT_UCR_ARABIC},
|
||||
{U"\u07C1\u07C2\u07C3", 1, TT_UCR_NKO},
|
||||
{U"\u0905\u093f\u092a", 1, TT_UCR_DEVANAGARI},
|
||||
{U"\u0986\u0987\u098c", 1, TT_UCR_BENGALI},
|
||||
{U"\u0a05\u0a16\u0a30", 1, TT_UCR_GURMUKHI},
|
||||
{U"\u0aaa\u0aaf\u0ab8", 1, TT_UCR_GUJARATI},
|
||||
{U"\u0b2a\u0b30\u0b37", 1, TT_UCR_ORIYA},
|
||||
{U"\u0b85\u0b88\u0b8f", 1, TT_UCR_TAMIL},
|
||||
{U"\u0c05\u0c0c\u0c36", 1, TT_UCR_TELUGU},
|
||||
{U"\u0c85\u0c87\u0c8e", 1, TT_UCR_KANNADA},
|
||||
{U"\u0d05\u0d09\u0d3d", 1, TT_UCR_MALAYALAM},
|
||||
{U"\u0e05\u0e06\u0e07", 1, TT_UCR_THAI},
|
||||
{U"\u0e81\u0e82\u0e84", 1, TT_UCR_LAO},
|
||||
{U"\u10a0\u10a1\u10a2", 1, TT_UCR_GEORGIAN},
|
||||
{U"\u1B05\u1B07\u1B09", 1, TT_UCR_BALINESE},
|
||||
{U"\u0f00\u0f04\u0f08", 3, TT_UCR_TIBETAN},
|
||||
{U"\u0710\u0717\u071c", 3, TT_UCR_SYRIAC},
|
||||
{U"\u0784\u0783\u0798", 3, TT_UCR_THAANA},
|
||||
{U"\u0d85\u0d89\u0daf", 3, TT_UCR_SINHALA},
|
||||
{U"\u1000\u1001\u1014", 3, TT_UCR_MYANMAR},
|
||||
{U"\u1202\u1207\u1250", 3, TT_UCR_ETHIOPIC},
|
||||
{U"\u13a3\u13a4\u13a8", 3, TT_UCR_CHEROKEE},
|
||||
{U"\u1401\u144d\u156e", 3, TT_UCR_CANADIAN_ABORIGINAL_SYLLABICS},
|
||||
{U"\u1681\u1687\u168b", 3, TT_UCR_OGHAM},
|
||||
{U"\u16A0\u16A4\u16AA", 3, TT_UCR_RUNIC},
|
||||
{U"\u1780\u1781\u1783", 3, TT_UCR_KHMER},
|
||||
{U"\u1820\u1826\u1845", 3, TT_UCR_MONGOLIAN},
|
||||
{U"\ua188\ua320\ua4bf", 3, TT_UCR_YI},
|
||||
{U"\u1900\u1901\u1902", 3, TT_UCR_LIMBU},
|
||||
{U"\u1950\u1951\u1952", 3, TT_UCR_TAI_LE},
|
||||
{U"\u1980\u1982\u1986", 3, FT_ULong(TT_UCR_NEW_TAI_LUE)},
|
||||
{U"\u1A00\u1A01\u1A02", 4, TT_UCR_BUGINESE},
|
||||
{U"\u2c01\u2c05\u2c0c", 4, TT_UCR_GLAGOLITIC},
|
||||
{U"\u2d31\u2d33\u2d37", 4, TT_UCR_TIFINAGH},
|
||||
{U"\u2d31\u2d33\u2d37", 4, TT_UCR_YIJING},
|
||||
{U"\u1B83\u1B84\u1B88", 4, TT_UCR_SUNDANESE},
|
||||
{U"\u1C00\u1C01\u1C02", 4, TT_UCR_LEPCHA},
|
||||
{U"\u1C50\u1C51\u1C52", 4, TT_UCR_OL_CHIKI},
|
||||
{U"\uA800\uA801\uA805", 4, TT_UCR_SYLOTI_NAGRI},
|
||||
{U"\uA882\uA88a\uA892", 4, TT_UCR_SAURASHTRA},
|
||||
{U"\uA901\uA902\uA904", 4, TT_UCR_KAYAH_LI},
|
||||
{U"\uA930\uA932\uA943", 4, TT_UCR_REJANG},
|
||||
{U"\uaa00\uaa02\uaa05", 4, TT_UCR_CHAM},
|
||||
/* Indexed languages in the Supplementary Multilingual Plane. */
|
||||
{U"\U00010000\U00010001\U00010002", 4, TT_UCR_LINEAR_B},
|
||||
{U"\U00010300\U00010301\U00010302", 3, TT_UCR_OLD_ITALIC},
|
||||
{U"\U00010330\U00010331\U00010332", 3, TT_UCR_GOTHIC},
|
||||
{U"\U00010380\U00010381\U00010382", 4, TT_UCR_UGARITIC},
|
||||
{U"\U000103A0\U000103A1\U000103A2", 4, TT_UCR_OLD_PERSIAN},
|
||||
{U"\U00010400\U00010401\U00010402", 3, TT_UCR_DESERET},
|
||||
{U"\U00010450\U00010451\U00010452", 4, TT_UCR_SHAVIAN},
|
||||
{U"\U00010480\U00010481\U00010482", 4, TT_UCR_OSMANYA},
|
||||
{U"\U00010800\U00010803\U00010805", 4, TT_UCR_CYPRIOT_SYLLABARY},
|
||||
{U"\U00010900\U00010901\U00010902", 2, TT_UCR_PHOENICIAN},
|
||||
{U"\U00010A10\U00010A11\U00010A12", 4, TT_UCR_KHAROSHTHI},
|
||||
{U"\U00012000\U00012001\U00012002", 4, TT_UCR_CUNEIFORM},
|
||||
/* Philippine languages use a single OS2 coverage bit. */
|
||||
{U"\u1700\u1701\u1702", 3, TT_UCR_PHILIPPINE}, /* Tagalog */
|
||||
{U"\u1720\u1721\u1722", 3, TT_UCR_PHILIPPINE}, /* Hanunoo */
|
||||
{U"\u1740\u1741\u1742", 3, TT_UCR_PHILIPPINE}, /* Buhid */
|
||||
{U"\u1760\u1761\u1762", 3, TT_UCR_PHILIPPINE}, /* Tagbanwa */
|
||||
/* Anatolian languages use a single OS2 coverage bit. */
|
||||
{U"\U000102A3\U000102A8\U000102CB", 4, TT_UCR_OLD_ANATOLIAN}, /* Carian */
|
||||
{U"\U00010280\U00010281\U00010282", 4, TT_UCR_OLD_ANATOLIAN}, /* Lycian */
|
||||
{U"\U00010920\U00010921\U00010922", 4, TT_UCR_OLD_ANATOLIAN}, /* Lydian */
|
||||
/* Symbol blocks. */
|
||||
{U"\U0001f600\U0001f638", 0, 0}, /* Emoticons 😀😸 */
|
||||
{U"\uf021\uf022\uf023", 0, 0}, /* MS Symbols */
|
||||
{U"\u280f\u2815\u283f", 3, TT_UCR_BRAILLE},
|
||||
{U"\U0001D11e\U0001D161\U0001D130", 3, TT_UCR_MUSICAL_SYMBOLS},
|
||||
{U"\u2700\u2708\u2709", 2, TT_UCR_DINGBATS},
|
||||
{U"\u2600\u2601\u2602", 2, TT_UCR_MISCELLANEOUS_SYMBOLS},
|
||||
{U"\ue000\ue001\ue002", 2, TT_UCR_PRIVATE_USE},
|
||||
{U"\ue702\ue703\ue704", 2, TT_UCR_PRIVATE_USE},
|
||||
{U"\U000F0001\U000F0002\U000F0003", 2, TT_UCR_PRIVATE_USE_SUPPLEMENTARY},
|
||||
/* Languages in the Supplementary Multilingual Plane. */
|
||||
{U"\U00010350\U00010352\U00010353", 2, TT_UCR_NON_PLANE_0}, /* Old Permic */
|
||||
{U"\U000104B0\U000104B6\U000104B8", 2, TT_UCR_NON_PLANE_0}, /* Osage */
|
||||
{U"\U00010500\U00010501\U00010502", 2, TT_UCR_NON_PLANE_0}, /* Elbasan */
|
||||
{U"\U00010530\U00010531\U00010532", 2, TT_UCR_NON_PLANE_0}, /* Caucasian Albanian */
|
||||
{U"\U00010600\U00010601\U00010602", 2, TT_UCR_NON_PLANE_0}, /* Linear A */
|
||||
{U"\U00010840\U00010841\U00010842", 2, TT_UCR_NON_PLANE_0}, /* Imperial Aramaic */
|
||||
{U"\U00010860\U00010861\U00010862", 2, TT_UCR_NON_PLANE_0}, /* Palmyrene */
|
||||
{U"\U00010880\U00010881\U00010882", 2, TT_UCR_NON_PLANE_0}, /* Nabataean */
|
||||
{U"\U000108E0\U000108E3\U000108E4", 2, TT_UCR_NON_PLANE_0}, /* Hatran */
|
||||
{U"\U00010980\U00010983\U00010989", 2, TT_UCR_NON_PLANE_0}, /* Meroitic Hieroglyphs */
|
||||
{U"\U000109A0\U000109A1\U000109A2", 2, TT_UCR_NON_PLANE_0}, /* Meroitic Cursive */
|
||||
{U"\U00010A60\U00010A61\U00010A62", 2, TT_UCR_NON_PLANE_0}, /* Old South Arabian */
|
||||
{U"\U00010A80\U00010A81\U00010A82", 2, TT_UCR_NON_PLANE_0}, /* Old North Arabian */
|
||||
{U"\U00010ac0\U00010ac3\U00010ac6", 2, TT_UCR_NON_PLANE_0}, /* Manichaean */
|
||||
{U"\U00010B00\U00010B04\U00010B08", 2, TT_UCR_NON_PLANE_0}, /* Avestan */
|
||||
{U"\U00010B40\U00010B41\U00010B42", 2, TT_UCR_NON_PLANE_0}, /* Inscriptional Parthian */
|
||||
{U"\U00010B60\U00010B61\U00010B62", 2, TT_UCR_NON_PLANE_0}, /* Inscriptional Pahlavi */
|
||||
{U"\U00010B80\U00010B84\U00010B87", 2, TT_UCR_NON_PLANE_0}, /* Psalter Pahlavi */
|
||||
{U"\U00010C00\U00010C01\U00010C02", 2, TT_UCR_NON_PLANE_0}, /* Old Turkic */
|
||||
{U"\U00010C80\U00010C81\U00010C82", 2, TT_UCR_NON_PLANE_0}, /* Old Hungarian */
|
||||
{U"\U00010D00\U00010D07\U00010D0D", 2, TT_UCR_NON_PLANE_0}, /* Hanifi Rohingya */
|
||||
{U"\U00010E80\U00010E81\U00010E82", 2, TT_UCR_NON_PLANE_0}, /* Yezidi */
|
||||
{U"\U00010F00\U00010F01\U00010F02", 2, TT_UCR_NON_PLANE_0}, /* Old Sogdian */
|
||||
{U"\U00010F30\U00010F32\U00010F34", 2, TT_UCR_NON_PLANE_0}, /* Sogdian */
|
||||
{U"\U00010F70\U00010F71\U00010F72", 2, TT_UCR_NON_PLANE_0}, /* Old Uyghur */
|
||||
{U"\U00010FB0\U00010FB1\U00010FB2", 2, TT_UCR_NON_PLANE_0}, /* Chorasmian */
|
||||
{U"\U00010FE0\U00010FE1\U00010FE2", 2, TT_UCR_NON_PLANE_0}, /* Elymaic */
|
||||
{U"\U00011003\U00011004\U00011005", 2, TT_UCR_NON_PLANE_0}, /* Brahmi */
|
||||
{U"\U00011083\U00011085\U00011087", 2, TT_UCR_NON_PLANE_0}, /* Kaithi */
|
||||
{U"\U000110D0\U000110D1\U000110D2", 2, TT_UCR_NON_PLANE_0}, /* Sora Sompeng */
|
||||
{U"\U00011103\U00011104\U00011105", 2, TT_UCR_NON_PLANE_0}, /* Chakma */
|
||||
{U"\U00011150\U00011151\U00011152", 2, TT_UCR_NON_PLANE_0}, /* Mahajani */
|
||||
{U"\U00011183\U00011185\U0001118b", 2, TT_UCR_NON_PLANE_0}, /* Sharada */
|
||||
{U"\U00011200\U00011201\U00011202", 2, TT_UCR_NON_PLANE_0}, /* Khojki */
|
||||
{U"\U00011280\U00011281\U00011282", 2, TT_UCR_NON_PLANE_0}, /* Multani */
|
||||
{U"\U000112B0\U000112B2\U000112B4", 2, TT_UCR_NON_PLANE_0}, /* Khudawadi */
|
||||
{U"\U00011305\U00011309\U0001130b", 2, TT_UCR_NON_PLANE_0}, /* Grantha */
|
||||
{U"\U00011400\U00011404\U00011409", 2, TT_UCR_NON_PLANE_0}, /* Newa */
|
||||
{U"\U00011480\U00011481\U00011482", 2, TT_UCR_NON_PLANE_0}, /* Tirhuta */
|
||||
{U"\U00011580\U00011582\U00011589", 2, TT_UCR_NON_PLANE_0}, /* Siddham */
|
||||
{U"\U00011600\U00011604\U00011609", 2, TT_UCR_NON_PLANE_0}, /* Modi */
|
||||
{U"\U00011680\U00011682\U0001168A", 2, TT_UCR_NON_PLANE_0}, /* Takri */
|
||||
{U"\U00011700\U00011701\U00011702", 2, TT_UCR_NON_PLANE_0}, /* Ahom */
|
||||
{U"\U00011800\U00011801\U00011802", 2, TT_UCR_NON_PLANE_0}, /* Dogri */
|
||||
{U"\U000118A0\U000118A1\U000118AA", 2, TT_UCR_NON_PLANE_0}, /* Warang Citi */
|
||||
{U"\U00011900\U00011901\U00011902", 2, TT_UCR_NON_PLANE_0}, /* Dives Akuru */
|
||||
{U"\U00011A00\U00011A10\U00011A15", 2, TT_UCR_NON_PLANE_0}, /* Zanabazar Square */
|
||||
{U"\U00011A50\U00011A5C\U00011A6B", 2, TT_UCR_NON_PLANE_0}, /* Soyombo */
|
||||
{U"\U00011AC0\U00011AC1\U00011AC2", 2, TT_UCR_NON_PLANE_0}, /* Pau Cin Hau */
|
||||
{U"\U00011C00\U00011C01\U00011C02", 2, TT_UCR_NON_PLANE_0}, /* Bhaiksuki */
|
||||
{U"\U00011C70\U00011C71\U00011C72", 2, TT_UCR_NON_PLANE_0}, /* Marchen */
|
||||
{U"\U00011D00\U00011D02\U00011D08", 2, TT_UCR_NON_PLANE_0}, /* Masaram Gondi */
|
||||
{U"\U00011D60\U00011D62\U00011D6c", 2, TT_UCR_NON_PLANE_0}, /* Gunjala Gondi */
|
||||
{U"\U00011FC1\U00011FC2\U00011FC8", 2, TT_UCR_NON_PLANE_0}, /* Tamil Supplement */
|
||||
{U"\U00012F90\U00012F91\U00012F92", 2, TT_UCR_NON_PLANE_0}, /* Cypro-Minoan */
|
||||
{U"\U00013000\U00013076\U0001307f", 2, TT_UCR_NON_PLANE_0}, /* Egyptian Hieroglyphs */
|
||||
{U"\U00014400\U00014409\U00014447", 2, TT_UCR_NON_PLANE_0}, /* Anatolian Hieroglyphs */
|
||||
{U"\U00016A40\U00016A41\U00016A42", 2, TT_UCR_NON_PLANE_0}, /* Mro */
|
||||
{U"\U00016A70\U00016A71\U00016A72", 2, TT_UCR_NON_PLANE_0}, /* Tangsa */
|
||||
{U"\U00016AD0\U00016AD2\U00016ADA", 2, TT_UCR_NON_PLANE_0}, /* Bassa Vah */
|
||||
{U"\U00016B00\U00016B01\U00016B02", 2, TT_UCR_NON_PLANE_0}, /* Pahawh Hmong */
|
||||
{U"\U00016F01\U00016F05\U00016F09", 2, TT_UCR_NON_PLANE_0}, /* Miao */
|
||||
{U"\U0001BC19\U0001BC1f\U0001BC0e", 2, TT_UCR_NON_PLANE_0}, /* Duployan */
|
||||
{U"\U0001D2E0\U0001D2E6\U0001D2f3", 2, TT_UCR_NON_PLANE_0}, /* Mayan Numerals */
|
||||
{U"\U0001E800\U0001E80A\U0001E80F", 2, TT_UCR_NON_PLANE_0}, /* Mende Kikakui */
|
||||
{U"\U0001E900\U0001E902\U0001E907", 2, TT_UCR_NON_PLANE_0}, /* Adlam */
|
||||
{U"\U0001E2C0\U0001E2C2\U0001E2C7", 2, TT_UCR_NON_PLANE_0}, /* Wancho */
|
||||
{U"\U0001EC71\U0001EC72\U0001EC73", 2, TT_UCR_NON_PLANE_0}, /* Indic Siyaq Numbers */
|
||||
/* Basic Multilingual Plane but are not indexed with an OS2 coverage bit. */
|
||||
{U"\u0638\u0630\u0633", 0, 0}, /* Urdu */
|
||||
{U"\u0800\u0801\u0802", 0, 0}, /* Samaritan */
|
||||
{U"\u0841\u0842\u084c", 0, 0}, /* Mandaic */
|
||||
{U"\u1A20\u1A21\u1A22", 0, 0}, /* Tai Tham */
|
||||
{U"\u1BC0\u1BC1\u1BC2", 0, 0}, /* Batak */
|
||||
{U"\uA4EF\uA4E8\uA4ED", 0, 0}, /* Lisu */
|
||||
{U"\uA6A0\uA6A1\uA6A2", 0, 0}, /* Bamum */
|
||||
{U"\ua983\ua984\ua98d", 0, 0}, /* Javanese */
|
||||
{U"\uaa80\uaa81\uaa82", 0, 0}, /* Tai Viet */
|
||||
{U"\uABC0\uABC1\uABC2", 0, 0}, /* Meetei Mayek */
|
||||
/* Near the end since many fonts contain these. */
|
||||
{U"\u03e2\u03e4\u03e8", 1, TT_UCR_COPTIC},
|
||||
{U"\u1f08\u03a6\u03a8", 1, TT_UCR_GREEK},
|
||||
{U"\u0518\u0409\u040f", 1, TT_UCR_CYRILLIC},
|
||||
{U"\u0533\u0537\u0539", 1, TT_UCR_ARMENIAN},
|
||||
};
|
||||
|
||||
static const char32_t *blf_get_sample_text(const FT_Face face)
|
||||
{
|
||||
/* First check for fonts with MS Symbol character map. */
|
||||
if (face->charmap->encoding == FT_ENCODING_MS_SYMBOL) {
|
||||
/* Many of these have characters starting from F020. */
|
||||
if (FT_Get_Char_Index(face, U'\uf041') != 0) {
|
||||
return U"\uf041\uf044\uf048";
|
||||
}
|
||||
if (FT_Get_Char_Index(face, U'\uf030') != 0) {
|
||||
return U"\uf030\uf031\uf032";
|
||||
}
|
||||
return U"ADH";
|
||||
}
|
||||
|
||||
const char32_t *def = U"Aabg";
|
||||
const char32_t *sample = def;
|
||||
|
||||
/* Fonts too old to have a Unicode character map. */
|
||||
if (face->charmap->encoding != FT_ENCODING_UNICODE) {
|
||||
return def;
|
||||
}
|
||||
|
||||
/* TrueType table with bits to quickly test most Unicode block coverage. */
|
||||
TT_OS2 *os2_table = static_cast<TT_OS2 *>(FT_Get_Sfnt_Table(face, FT_SFNT_OS2));
|
||||
if (!os2_table) {
|
||||
return def;
|
||||
}
|
||||
|
||||
/* Detect "Last resort" fonts. They have everything, except the last 5 bits. */
|
||||
if (os2_table->ulUnicodeRange1 == 0xffffffffU && os2_table->ulUnicodeRange2 == 0xffffffffU &&
|
||||
os2_table->ulUnicodeRange3 == 0xffffffffU && os2_table->ulUnicodeRange4 >= 0x7FFFFFFU)
|
||||
{
|
||||
return U"\xE000\xFFFF";
|
||||
}
|
||||
|
||||
int language_count = count_bits_i(uint(os2_table->ulUnicodeRange1)) +
|
||||
count_bits_i(uint(os2_table->ulUnicodeRange2)) +
|
||||
count_bits_i(uint(os2_table->ulUnicodeRange3)) +
|
||||
count_bits_i(uint(os2_table->ulUnicodeRange4));
|
||||
|
||||
/* Use OS/2 Table code page range bits to differentiate between (combined) CJK fonts.
|
||||
* See https://learn.microsoft.com/en-us/typography/opentype/spec/os2#cpr */
|
||||
FT_ULong codepages = os2_table->ulCodePageRange1;
|
||||
if (codepages & (1 << 19) || codepages & (1 << 21)) {
|
||||
return U"\ud55c\uad6d\uc5b4"; /* 한국어 Korean. */
|
||||
}
|
||||
if (codepages & (1 << 20)) {
|
||||
return U"\u7E41\u9AD4\u5B57"; /* 繁體字 Traditional Chinese. */
|
||||
}
|
||||
if (codepages & (1 << 17) && !(codepages & (1 << 18))) {
|
||||
return U"\u65E5\u672C\u8A9E"; /* 日本語 Japanese. */
|
||||
}
|
||||
if (codepages & (1 << 18) && !(codepages & (1 << 17))) {
|
||||
return U"\u7B80\u4F53\u5B57"; /* 简体字 Simplified Chinese. */
|
||||
}
|
||||
|
||||
for (uint i = 0; i < ARRAY_SIZE(unicode_samples); ++i) {
|
||||
const UnicodeSample *s = &unicode_samples[i];
|
||||
if (os2_table && s->field && s->mask) {
|
||||
/* OS/2 Table contains 4 contiguous integers of script coverage bit flags. */
|
||||
const FT_ULong *unicode_range = &os2_table->ulUnicodeRange1;
|
||||
const int index = (s->field - 1);
|
||||
BLI_assert(index < 4);
|
||||
if (!(unicode_range[index] & s->mask)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (FT_Get_Char_Index(face, s->sample[0]) != 0) {
|
||||
sample = s->sample;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool has_latin = (os2_table && (os2_table->ulUnicodeRange1 & TT_UCR_BASIC_LATIN) &&
|
||||
(FT_Get_Char_Index(face, U'A') != 0));
|
||||
bool has_cjk = (os2_table && (os2_table->ulUnicodeRange2 & TT_UCR_CJK_UNIFIED_IDEOGRAPHS));
|
||||
|
||||
if (has_latin && ((has_cjk && language_count > 40) || (!has_cjk && language_count > 5))) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
||||
bool BLF_thumb_preview(
|
||||
const char *filepath, uchar *buf, const int w, const int h, const int /*channels*/)
|
||||
{
|
||||
/* Use own FT_Library and direct FreeType calls as this is called from multiple threads. */
|
||||
FT_Library ft_lib = nullptr;
|
||||
if (FT_Init_FreeType(&ft_lib) != FT_Err_Ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_Face face;
|
||||
if (FT_New_Face(ft_lib, filepath, 0, &face) != FT_Err_Ok) {
|
||||
FT_Done_FreeType(ft_lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_Error err = FT_Select_Charmap(face, FT_ENCODING_UNICODE);
|
||||
if (err) {
|
||||
err = FT_Select_Charmap(face, FT_ENCODING_MS_SYMBOL);
|
||||
}
|
||||
if (err) {
|
||||
err = FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN);
|
||||
}
|
||||
if (err && face->num_charmaps > 0) {
|
||||
err = FT_Select_Charmap(face, face->charmaps[0]->encoding);
|
||||
}
|
||||
if (err != FT_Err_Ok) {
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft_lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char32_t *codepoints = blf_get_sample_text(face);
|
||||
uint glyph_ids[BLF_SAMPLE_LEN] = {0};
|
||||
|
||||
/* A large initial font size for measuring. Nothing will be rendered this size. */
|
||||
if (FT_Set_Char_Size(face, w * 64, 0, 72, 72) != FT_Err_Ok) {
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft_lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Approximate length of the sample. Uses only advances, ignores bearings. */
|
||||
int width = 0;
|
||||
for (uint i = 0; i < BLF_SAMPLE_LEN && codepoints[i]; i++) {
|
||||
glyph_ids[i] = FT_Get_Char_Index(face, codepoints[i]);
|
||||
/* If sample glyph is not found, use another. */
|
||||
if (!glyph_ids[i]) {
|
||||
glyph_ids[i] = uint(face->num_glyphs / (BLF_SAMPLE_LEN + 1)) * (i + 1);
|
||||
}
|
||||
/* Get advance without loading the glyph. */
|
||||
FT_Fixed advance;
|
||||
FT_Get_Advance(face, glyph_ids[i], FT_LOAD_NO_HINTING, &advance);
|
||||
/* Advance is returned in 16.16 format, so divide by 65536 for pixels. */
|
||||
width += int(advance >> 16);
|
||||
}
|
||||
|
||||
int height = ft_pix_to_int(ft_pix(face->size->metrics.ascender) -
|
||||
ft_pix(face->size->metrics.descender));
|
||||
width = std::max(width, height);
|
||||
|
||||
/* Fill up to 96% horizontally or vertically. */
|
||||
float font_size = std::min({float(w),
|
||||
(float(w) * 0.96f / float(width) * float(w)),
|
||||
float(h) * 0.96f / float(height) * float(h)});
|
||||
|
||||
if (font_size < 1 || FT_Set_Char_Size(face, int(font_size * 64.0f), 0, 72, 72) != FT_Err_Ok) {
|
||||
/* Sizing can fail, but very rarely. */
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft_lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Horizontally center, line up baselines vertically. */
|
||||
int left = int((float(w) - (float(width) * (font_size / float(w)))) / 2.0f);
|
||||
int top = int(float(h) * 0.7f);
|
||||
|
||||
/* Print out to buffer. */
|
||||
|
||||
FT_Pos advance_x = 0;
|
||||
int glyph_count = 0; /* How many are successfully loaded and rendered. */
|
||||
|
||||
for (int i = 0; i < BLF_SAMPLE_LEN && glyph_ids[i]; i++) {
|
||||
if (FT_Load_Glyph(face, glyph_ids[i], FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING) != FT_Err_Ok)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL) != FT_Err_Ok ||
|
||||
face->glyph->format != FT_GLYPH_FORMAT_BITMAP)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
glyph_count++;
|
||||
|
||||
for (int y = 0; y < int(face->glyph->bitmap.rows); y++) {
|
||||
int dest_row = (h - y - 1 + int(face->glyph->bitmap_top) - top);
|
||||
if (dest_row >= 0 && dest_row < h) {
|
||||
for (int x = 0; x < int(face->glyph->bitmap.width); x++) {
|
||||
int dest_col = (x + ft_pix_to_int(ft_pix(advance_x)) + face->glyph->bitmap_left + left);
|
||||
if (dest_col >= 0 && dest_col < w) {
|
||||
uchar *source = &face->glyph->bitmap.buffer[y * int(face->glyph->bitmap.width) + x];
|
||||
uchar *dest = &buf[dest_row * w * 4 + (dest_col * 4 + 3)];
|
||||
*dest = uchar(std::min((uint(*dest) + uint(*source)), 255u));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
advance_x += face->glyph->advance.x;
|
||||
}
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft_lib);
|
||||
|
||||
/* Return success if we printed at least one glyph. */
|
||||
return glyph_count > 0;
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
Reference in New Issue
Block a user