add support for CBDT and embedded bitmaps in truetype fonts

This commit is contained in:
nulano 2020-03-29 10:31:10 +02:00
parent 82a28d12e2
commit 9151da162c
5 changed files with 86 additions and 45 deletions

View File

@ -105,6 +105,10 @@ jobs:
- name: Build dependencies / WebP
if: steps.build-cache.outputs.cache-hit != 'true'
run: "& winbuild\\build\\build_dep_libwebp.cmd"
# for FreeType CBDT font support
- name: Build dependencies / libpng
if: steps.build-cache.outputs.cache-hit != 'true'
run: "& winbuild\\build\\build_dep_libpng.cmd"
- name: Build dependencies / FreeType
if: steps.build-cache.outputs.cache-hit != 'true'
run: "& winbuild\\build\\build_dep_freetype.cmd"

View File

@ -26,6 +26,7 @@ def test_similar():
im_outline = im_bitmap.copy()
draw_bitmap = ImageDraw.Draw(im_bitmap)
draw_outline = ImageDraw.Draw(im_outline)
draw_outline.fontmode = "1" # disable anti-aliasing to match bitmap font
# Metrics are different on the bitmap and TTF fonts,
# more so on some platforms and versions of FreeType than others.

View File

@ -352,7 +352,7 @@ Methods
.. versionadded:: 6.2.0
:param embedded_color: Whether to use embedded color info in COLR and CPAL tables.
:param embedded_color: Whether to use font embedded color glyphs (COLR or CBDT).
.. versionadded:: 8.0.0
@ -413,7 +413,7 @@ Methods
.. versionadded:: 6.2.0
:param embedded_color: Whether to use embedded color info in COLR and CPAL tables.
:param embedded_color: Whether to use font embedded color glyphs (COLR or CBDT).
.. versionadded:: 8.0.0

View File

@ -564,7 +564,7 @@ text_layout_fallback(PyObject* string, FontObject* self, const char* dir, PyObje
return 0;
}
load_flags = FT_LOAD_NO_BITMAP;
load_flags = FT_LOAD_DEFAULT;
if (mask) {
load_flags |= FT_LOAD_TARGET_MONO;
}
@ -663,10 +663,7 @@ font_getsize(FontObject* self, PyObject* args)
return NULL;
}
/* Note: bitmap fonts within ttf fonts do not work, see #891/pr#960
* Yifu Yu<root@jackyyf.com>, 2014-10-15
*/
load_flags = FT_LOAD_NO_BITMAP;
load_flags = FT_LOAD_DEFAULT;
if (mask) {
load_flags |= FT_LOAD_TARGET_MONO;
}
@ -903,9 +900,7 @@ font_render(FontObject* self, PyObject* args)
}
im = (Imaging) id;
/* Note: bitmap fonts within ttf fonts do not work, see #891/pr#960 */
load_flags = FT_LOAD_NO_BITMAP;
load_flags = FT_LOAD_DEFAULT;
if (mask) {
load_flags |= FT_LOAD_TARGET_MONO;
}
@ -1000,12 +995,16 @@ font_render(FontObject* self, PyObject* args)
/* clip glyph bitmap height to target image bounds */
if (yy >= 0 && yy < im->ysize) {
// blend this glyph into the buffer
unsigned char* target;
if (color) {
/* target[RGB] returns the color, target[A] returns the mask */
/* target bands get split again in ImageDraw.text */
unsigned char *target = im->image[yy] + xx * 4;
target = im->image[yy] + xx * 4;
} else {
target = im->image8[yy] + xx;
}
#ifdef FT_LOAD_COLOR
if (bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
if (color && bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
// paste color glyph
int k;
for (k = x0; k < x1; k++) {
@ -1019,9 +1018,10 @@ font_render(FontObject* self, PyObject* args)
}
} else
#endif
{ // pixel_mode should be FT_PIXEL_MODE_GRAY
// fill with ink
// handle 8bpp separately for performance
if (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
int k;
if (color) {
for (k = x0; k < x1; k++) {
if (target[k * 4 + 3] < source[k]) {
target[k * 4 + 0] = (unsigned char) (foreground_ink);
@ -1030,30 +1030,50 @@ font_render(FontObject* self, PyObject* args)
target[k * 4 + 3] = source[k];
}
}
}
} else {
unsigned char *target = im->image8[yy] + xx;
if (mask) {
// use monochrome mask (on palette images, etc)
int j, k, m = 128;
for (j = k = 0; j < x1; j++) {
if (j >= x0 && (source[k] & m)) {
target[j] = 255;
}
if (!(m >>= 1)) {
m = 128;
k++;
}
}
} else {
// use antialiased rendering
int k;
for (k = x0; k < x1; k++) {
if (target[k] < source[k]) {
target[k] = source[k];
}
}
}
} else {
int k, v, m, a, b;
switch (bitmap.pixel_mode) {
case FT_PIXEL_MODE_MONO:
a = 3;
b = 7;
m = 0x80;
break;
case FT_PIXEL_MODE_GRAY2:
a = 2;
b = 3;
m = 0xC0;
break;
case FT_PIXEL_MODE_GRAY4:
a = 1;
b = 1;
m = 0xF0;
break;
default:
PyErr_SetString(PyExc_IOError, "unsupported bitmap pixel mode");
return NULL;
}
for (k = x0; k < x1; k++) {
v = CLIP8(255 * ((source[k >> a] << (k & b)) & m) / m);
if (color) {
if (target[k * 4 + 3] < v) {
target[k * 4 + 0] = (unsigned char) foreground_ink;
target[k * 4 + 1] = (unsigned char) (foreground_ink >> 8);
target[k * 4 + 2] = (unsigned char) (foreground_ink >> 16);
target[k * 4 + 3] = v;
}
} else {
if (target[k] < v) {
target[k] = v;
}
}
}
}
}
source += bitmap.pitch;

View File

@ -169,6 +169,20 @@ deps = {
],
"libs": [r"output\release-static\{architecture}\lib\*.lib"],
},
"libpng": {
"url": SF_MIRROR + "/project/libpng/libpng16/1.6.37/lpng1637.zip",
"filename": "lpng1637.zip",
"dir": "lpng1637",
"build": [
# lint: do not inline
cmd_cmake(("-DPNG_SHARED:BOOL=OFF", "-DPNG_TESTS:BOOL=OFF")),
cmd_nmake(target="clean"),
cmd_nmake(),
cmd_copy("libpng16_static.lib", "libpng16.lib"),
],
"headers": [r"png*.h"],
"libs": [r"libpng16.lib"],
},
"freetype": {
"url": "https://download.savannah.gnu.org/releases/freetype/freetype-2.10.2.tar.gz", # noqa: E501
"filename": "freetype-2.10.2.tar.gz",
@ -181,8 +195,10 @@ deps = {
'<PropertyGroup Label="Globals">': '<PropertyGroup Label="Globals">\n <WindowsTargetPlatformVersion>$(WindowsSDKVersion)</WindowsTargetPlatformVersion>', # noqa: E501
},
r"builds\windows\vc2010\freetype.user.props": {
"<UserDefines></UserDefines>": "<UserDefines>FT_CONFIG_OPTION_USE_HARFBUZZ</UserDefines>", # noqa: E501
"<UserIncludeDirectories></UserIncludeDirectories>": r"<UserIncludeDirectories>{dir_harfbuzz}\src</UserIncludeDirectories>", # noqa: E501
"<UserDefines></UserDefines>": "<UserDefines>FT_CONFIG_OPTION_SYSTEM_ZLIB;FT_CONFIG_OPTION_USE_PNG;FT_CONFIG_OPTION_USE_HARFBUZZ</UserDefines>", # noqa: E501
"<UserIncludeDirectories></UserIncludeDirectories>": r"<UserIncludeDirectories>{dir_harfbuzz}\src;{inc_dir}</UserIncludeDirectories>", # noqa: E501
"<UserLibraryDirectories></UserLibraryDirectories>": "<UserLibraryDirectories>{lib_dir}</UserLibraryDirectories>", # noqa: E501
"<UserDependencies></UserDependencies>": "<UserDependencies>zlib.lib;libpng16.lib</UserDependencies>", # noqa: E501
},
r"src/autofit/afshaper.c": {
# link against harfbuzz.lib once it becomes available