mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 02:36:17 +03:00
add option to statically link fribidi, version info
This commit is contained in:
parent
9e5fc136b9
commit
5cd688fc82
90
setup.py
90
setup.py
|
@ -267,7 +267,7 @@ class pil_build_ext(build_ext):
|
||||||
"jpeg",
|
"jpeg",
|
||||||
"tiff",
|
"tiff",
|
||||||
"freetype",
|
"freetype",
|
||||||
"harfbuzz",
|
"raqm",
|
||||||
"lcms",
|
"lcms",
|
||||||
"webp",
|
"webp",
|
||||||
"webpmux",
|
"webpmux",
|
||||||
|
@ -277,6 +277,7 @@ class pil_build_ext(build_ext):
|
||||||
]
|
]
|
||||||
|
|
||||||
required = {"jpeg", "zlib"}
|
required = {"jpeg", "zlib"}
|
||||||
|
system = set()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
for f in self.features:
|
for f in self.features:
|
||||||
|
@ -288,6 +289,9 @@ class pil_build_ext(build_ext):
|
||||||
def want(self, feat):
|
def want(self, feat):
|
||||||
return getattr(self, feat) is None
|
return getattr(self, feat) is None
|
||||||
|
|
||||||
|
def want_system(self, feat):
|
||||||
|
return feat in self.system
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
yield from self.features
|
yield from self.features
|
||||||
|
|
||||||
|
@ -297,6 +301,10 @@ class pil_build_ext(build_ext):
|
||||||
build_ext.user_options
|
build_ext.user_options
|
||||||
+ [(f"disable-{x}", None, f"Disable support for {x}") for x in feature]
|
+ [(f"disable-{x}", None, f"Disable support for {x}") for x in feature]
|
||||||
+ [(f"enable-{x}", None, f"Enable support for {x}") for x in feature]
|
+ [(f"enable-{x}", None, f"Enable support for {x}") for x in feature]
|
||||||
|
+ [
|
||||||
|
(f"system-{x}", None, f"Use system version of {x}")
|
||||||
|
for x in ("raqm", "fribidi")
|
||||||
|
]
|
||||||
+ [
|
+ [
|
||||||
("disable-platform-guessing", None, "Disable platform guessing on Linux"),
|
("disable-platform-guessing", None, "Disable platform guessing on Linux"),
|
||||||
("debug", None, "Debug logging"),
|
("debug", None, "Debug logging"),
|
||||||
|
@ -311,6 +319,8 @@ class pil_build_ext(build_ext):
|
||||||
for x in self.feature:
|
for x in self.feature:
|
||||||
setattr(self, f"disable_{x}", None)
|
setattr(self, f"disable_{x}", None)
|
||||||
setattr(self, f"enable_{x}", None)
|
setattr(self, f"enable_{x}", None)
|
||||||
|
for x in ("raqm", "fribidi"):
|
||||||
|
setattr(self, f"system_{x}", None)
|
||||||
|
|
||||||
def finalize_options(self):
|
def finalize_options(self):
|
||||||
build_ext.finalize_options(self)
|
build_ext.finalize_options(self)
|
||||||
|
@ -335,18 +345,40 @@ class pil_build_ext(build_ext):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Conflicting options: --enable-{x} and --disable-{x}"
|
f"Conflicting options: --enable-{x} and --disable-{x}"
|
||||||
)
|
)
|
||||||
|
if x == "freetype":
|
||||||
|
_dbg("--disable-freetype implies --disable-raqm")
|
||||||
|
if getattr(self, "enable_raqm"):
|
||||||
|
raise ValueError(
|
||||||
|
"Conflicting options: --enable-raqm and --disable-freetype"
|
||||||
|
)
|
||||||
|
setattr(self, "disable_raqm", True)
|
||||||
if getattr(self, f"enable_{x}"):
|
if getattr(self, f"enable_{x}"):
|
||||||
_dbg("Requiring %s", x)
|
_dbg("Requiring %s", x)
|
||||||
self.feature.required.add(x)
|
self.feature.required.add(x)
|
||||||
|
if x == "raqm":
|
||||||
|
_dbg("--enable-raqm implies --enable-freetype")
|
||||||
|
self.feature.required.add("freetype")
|
||||||
|
for x in ("raqm", "fribidi"):
|
||||||
|
if getattr(self, f"system_{x}"):
|
||||||
|
if getattr(self, f"disable_raqm"):
|
||||||
|
raise ValueError(
|
||||||
|
f"Conflicting options: --system-{x} and --disable-raqm"
|
||||||
|
)
|
||||||
|
if x == "fribidi" and getattr(self, f"system_raqm"):
|
||||||
|
raise ValueError(
|
||||||
|
f"Conflicting options: --system-{x} and --system-raqm"
|
||||||
|
)
|
||||||
|
_dbg("Using system version of %s", x)
|
||||||
|
self.feature.system.add(x)
|
||||||
|
|
||||||
def _update_extension(self, name, libraries, define_macros=None, include_dirs=None):
|
def _update_extension(self, name, libraries, define_macros=None, sources=None):
|
||||||
for extension in self.extensions:
|
for extension in self.extensions:
|
||||||
if extension.name == name:
|
if extension.name == name:
|
||||||
extension.libraries += libraries
|
extension.libraries += libraries
|
||||||
if define_macros is not None:
|
if define_macros is not None:
|
||||||
extension.define_macros += define_macros
|
extension.define_macros += define_macros
|
||||||
if include_dirs is not None:
|
if sources is not None:
|
||||||
extension.include_dirs += include_dirs
|
extension.sources += sources
|
||||||
break
|
break
|
||||||
|
|
||||||
def _remove_extension(self, name):
|
def _remove_extension(self, name):
|
||||||
|
@ -657,11 +689,27 @@ class pil_build_ext(build_ext):
|
||||||
if subdir:
|
if subdir:
|
||||||
_add_directory(self.compiler.include_dirs, subdir, 0)
|
_add_directory(self.compiler.include_dirs, subdir, 0)
|
||||||
|
|
||||||
if feature.want("harfbuzz"):
|
if feature.want("raqm"):
|
||||||
_dbg("Looking for harfbuzz")
|
if feature.want_system("raqm"): # want system Raqm
|
||||||
if _find_include_file(self, "hb-version.h"):
|
_dbg("Looking for Raqm")
|
||||||
|
if _find_include_file(self, "raqm.h"):
|
||||||
|
if _find_library_file(self, "raqm"):
|
||||||
|
feature.harfbuzz = "raqm"
|
||||||
|
elif _find_library_file(self, "libraqm"):
|
||||||
|
feature.harfbuzz = "libraqm"
|
||||||
|
else: # want to build Raqm
|
||||||
|
_dbg("Looking for HarfBuzz")
|
||||||
|
if _find_include_file(self, "hb.h"):
|
||||||
if _find_library_file(self, "harfbuzz"):
|
if _find_library_file(self, "harfbuzz"):
|
||||||
feature.harfbuzz = "harfbuzz"
|
feature.harfbuzz = "harfbuzz"
|
||||||
|
if feature.harfbuzz:
|
||||||
|
if feature.want_system("fribidi"): # want system FriBiDi
|
||||||
|
_dbg("Looking for FriBiDi")
|
||||||
|
if _find_include_file(self, "fribidi.h"):
|
||||||
|
if _find_library_file(self, "fribidi"):
|
||||||
|
feature.harfbuzz = "fribidi"
|
||||||
|
else: # want to build FriBiDi shim
|
||||||
|
feature.raqm = True
|
||||||
|
|
||||||
if feature.want("lcms"):
|
if feature.want("lcms"):
|
||||||
_dbg("Looking for lcms")
|
_dbg("Looking for lcms")
|
||||||
|
@ -758,9 +806,25 @@ class pil_build_ext(build_ext):
|
||||||
# additional libraries
|
# additional libraries
|
||||||
|
|
||||||
if feature.freetype:
|
if feature.freetype:
|
||||||
|
srcs = []
|
||||||
libs = ["freetype"]
|
libs = ["freetype"]
|
||||||
defs = []
|
defs = []
|
||||||
self._update_extension("PIL._imagingft", libs, defs)
|
if feature.raqm:
|
||||||
|
if feature.want_system("raqm"): # using system Raqm
|
||||||
|
defs.append(("HAVE_RAQM", None))
|
||||||
|
defs.append(("HAVE_RAQM_SYSTEM", None))
|
||||||
|
libs.append(feature.raqm)
|
||||||
|
else: # building Raqm
|
||||||
|
defs.append(("HAVE_RAQM", None))
|
||||||
|
srcs.append("src/thirdparty/raqm/raqm.c")
|
||||||
|
libs.append(feature.harfbuzz)
|
||||||
|
if feature.want_system("fribidi"): # using system FriBiDi
|
||||||
|
defs.append(("HAVE_FRIBIDI_SYSTEM", None))
|
||||||
|
libs.append(feature.fribidi)
|
||||||
|
else: # building our FriBiDi shim
|
||||||
|
srcs.append("src/thirdparty/fribidi-shim/fribidi.c")
|
||||||
|
self._update_extension("PIL._imagingft", libs, defs, srcs)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self._remove_extension("PIL._imagingft")
|
self._remove_extension("PIL._imagingft")
|
||||||
|
|
||||||
|
@ -814,6 +878,7 @@ class pil_build_ext(build_ext):
|
||||||
(feature.imagequant, "LIBIMAGEQUANT"),
|
(feature.imagequant, "LIBIMAGEQUANT"),
|
||||||
(feature.tiff, "LIBTIFF"),
|
(feature.tiff, "LIBTIFF"),
|
||||||
(feature.freetype, "FREETYPE2"),
|
(feature.freetype, "FREETYPE2"),
|
||||||
|
(feature.raqm, "RAQM (Text shaping)"), # TODO!!!
|
||||||
(feature.lcms, "LITTLECMS2"),
|
(feature.lcms, "LITTLECMS2"),
|
||||||
(feature.webp, "WEBP"),
|
(feature.webp, "WEBP"),
|
||||||
(feature.webpmux, "WEBPMUX"),
|
(feature.webpmux, "WEBPMUX"),
|
||||||
|
@ -857,14 +922,7 @@ for src_file in _LIB_IMAGING:
|
||||||
files.append(os.path.join("src/libImaging", src_file + ".c"))
|
files.append(os.path.join("src/libImaging", src_file + ".c"))
|
||||||
ext_modules = [
|
ext_modules = [
|
||||||
Extension("PIL._imaging", files),
|
Extension("PIL._imaging", files),
|
||||||
Extension(
|
Extension("PIL._imagingft", ["src/_imagingft.c"]),
|
||||||
"PIL._imagingft",
|
|
||||||
[
|
|
||||||
"src/_imagingft.c",
|
|
||||||
"src/thirdparty/raqm/raqm.c",
|
|
||||||
"src/thirdparty/fribidi-shim/fribidi.c",
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Extension("PIL._imagingcms", ["src/_imagingcms.c"]),
|
Extension("PIL._imagingcms", ["src/_imagingcms.c"]),
|
||||||
Extension("PIL._webp", ["src/_webp.c"]),
|
Extension("PIL._webp", ["src/_webp.c"]),
|
||||||
Extension("PIL._imagingtk", ["src/_imagingtk.c", "src/Tk/tkImaging.c"]),
|
Extension("PIL._imagingtk", ["src/_imagingtk.c", "src/Tk/tkImaging.c"]),
|
||||||
|
|
|
@ -118,6 +118,8 @@ features = {
|
||||||
"webp_mux": ("PIL._webp", "HAVE_WEBPMUX", None),
|
"webp_mux": ("PIL._webp", "HAVE_WEBPMUX", None),
|
||||||
"transp_webp": ("PIL._webp", "HAVE_TRANSPARENCY", None),
|
"transp_webp": ("PIL._webp", "HAVE_TRANSPARENCY", None),
|
||||||
"raqm": ("PIL._imagingft", "HAVE_RAQM", "raqm_version"),
|
"raqm": ("PIL._imagingft", "HAVE_RAQM", "raqm_version"),
|
||||||
|
"fribidi": ("PIL._imagingft", "HAVE_FRIBIDI", "fribidi_version"),
|
||||||
|
"harfbuzz": ("PIL._imagingft", "HAVE_HARFBUZZ", "harfbuzz_version"),
|
||||||
"libjpeg_turbo": ("PIL._imaging", "HAVE_LIBJPEGTURBO", "libjpeg_turbo_version"),
|
"libjpeg_turbo": ("PIL._imaging", "HAVE_LIBJPEGTURBO", "libjpeg_turbo_version"),
|
||||||
"libimagequant": ("PIL._imaging", "HAVE_LIBIMAGEQUANT", "imagequant_version"),
|
"libimagequant": ("PIL._imaging", "HAVE_LIBIMAGEQUANT", "imagequant_version"),
|
||||||
"xcb": ("PIL._imaging", "HAVE_XCB", None),
|
"xcb": ("PIL._imaging", "HAVE_XCB", None),
|
||||||
|
@ -274,6 +276,11 @@ def pilinfo(out=None, supported_formats=True):
|
||||||
# this check is also in src/_imagingcms.c:setup_module()
|
# this check is also in src/_imagingcms.c:setup_module()
|
||||||
version_static = tuple(int(x) for x in v.split(".")) < (2, 7)
|
version_static = tuple(int(x) for x in v.split(".")) < (2, 7)
|
||||||
t = "compiled for" if version_static else "loaded"
|
t = "compiled for" if version_static else "loaded"
|
||||||
|
if name == "raqm":
|
||||||
|
for f in ("fribidi", "harfbuzz"):
|
||||||
|
v2 = version_feature(f)
|
||||||
|
if v2 is not None:
|
||||||
|
v += f", {f} {v2}"
|
||||||
print("---", feature, "support ok,", t, v, file=out)
|
print("---", feature, "support ok,", t, v, file=out)
|
||||||
else:
|
else:
|
||||||
print("---", feature, "support ok", file=out)
|
print("---", feature, "support ok", file=out)
|
||||||
|
|
|
@ -52,8 +52,21 @@
|
||||||
} \
|
} \
|
||||||
;
|
;
|
||||||
|
|
||||||
|
#ifdef HAVE_RAQM
|
||||||
|
# ifdef HAVE_RAQM_SYSTEM
|
||||||
|
# include <raqm.h>
|
||||||
|
# else
|
||||||
# include "thirdparty/raqm/raqm.h"
|
# include "thirdparty/raqm/raqm.h"
|
||||||
|
# ifdef HAVE_FRIBIDI_SYSTEM
|
||||||
|
# include <fribidi.h>
|
||||||
|
# else
|
||||||
# include "thirdparty/fribidi-shim/fribidi.h"
|
# include "thirdparty/fribidi-shim/fribidi.h"
|
||||||
|
# include <hb.h>
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int have_raqm = 0;
|
||||||
|
|
||||||
#define LAYOUT_FALLBACK 0
|
#define LAYOUT_FALLBACK 0
|
||||||
#define LAYOUT_RAQM 1
|
#define LAYOUT_RAQM 1
|
||||||
|
@ -101,11 +114,6 @@ geterror(int code) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
setraqm(void) {
|
|
||||||
return load_fribidi();
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
getfont(PyObject *self_, PyObject *args, PyObject *kw) {
|
getfont(PyObject *self_, PyObject *args, PyObject *kw) {
|
||||||
/* create a font object from a file name and a size (in pixels) */
|
/* create a font object from a file name and a size (in pixels) */
|
||||||
|
@ -474,7 +482,7 @@ text_layout(
|
||||||
int color) {
|
int color) {
|
||||||
size_t count;
|
size_t count;
|
||||||
|
|
||||||
if (p_fribidi && self->layout_engine == LAYOUT_RAQM) {
|
if (have_raqm && self->layout_engine == LAYOUT_RAQM) {
|
||||||
count = text_layout_raqm(
|
count = text_layout_raqm(
|
||||||
string, self, dir, features, lang, glyph_info, mask, color);
|
string, self, dir, features, lang, glyph_info, mask, color);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1357,15 +1365,51 @@ setup_module(PyObject *m) {
|
||||||
v = PyUnicode_FromFormat("%d.%d.%d", major, minor, patch);
|
v = PyUnicode_FromFormat("%d.%d.%d", major, minor, patch);
|
||||||
PyDict_SetItemString(d, "freetype2_version", v);
|
PyDict_SetItemString(d, "freetype2_version", v);
|
||||||
|
|
||||||
setraqm();
|
#ifdef HAVE_RAQM
|
||||||
v = PyBool_FromLong(!!p_fribidi);
|
#ifdef HAVE_FRIBIDI_SYSTEM
|
||||||
PyDict_SetItemString(d, "HAVE_RAQM", v);
|
have_raqm = 1;
|
||||||
// if (p_raqm.version_string) {
|
#else
|
||||||
PyDict_SetItemString(
|
load_fribidi();
|
||||||
d, "raqm_version", PyUnicode_FromString(raqm_version_string()));
|
have_raqm = !!p_fribidi;
|
||||||
// };
|
#endif
|
||||||
|
#else
|
||||||
|
have_raqm = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* if we have Raqm, we have all three (but possibly no version info) */
|
||||||
|
v = PyBool_FromLong(have_raqm);
|
||||||
|
PyDict_SetItemString(d, "HAVE_RAQM", v);
|
||||||
PyDict_SetItemString(d, "HAVE_FRIBIDI", v);
|
PyDict_SetItemString(d, "HAVE_FRIBIDI", v);
|
||||||
|
PyDict_SetItemString(d, "HAVE_HARFBUZZ", v);
|
||||||
|
if (have_raqm) {
|
||||||
|
const char *a, *b;
|
||||||
|
#ifdef RAQM_VERSION_MAJOR
|
||||||
|
v = PyUnicode_FromString(raqm_version_string());
|
||||||
|
#else
|
||||||
|
v = Py_None;
|
||||||
|
#endif
|
||||||
|
PyDict_SetItemString(d, "raqm_version", v);
|
||||||
|
|
||||||
|
#ifdef FRIBIDI_MAJOR_VERSION
|
||||||
|
a = strchr(fribidi_version_info, '1');
|
||||||
|
b = strchr(fribidi_version_info, '\n');
|
||||||
|
if (a && b) {
|
||||||
|
v = PyUnicode_FromStringAndSize(a, b - a);
|
||||||
|
} else {
|
||||||
|
v = Py_None;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
v = Py_None;
|
||||||
|
#endif
|
||||||
|
PyDict_SetItemString(d, "fribidi_version", v);
|
||||||
|
|
||||||
|
#ifdef HB_VERSION_STRING
|
||||||
|
v = PyUnicode_FromString(hb_version_string());
|
||||||
|
#else
|
||||||
|
v = Py_None;
|
||||||
|
#endif
|
||||||
|
PyDict_SetItemString(d, "harfbuzz_version", v);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
6
src/thirdparty/fribidi-shim/fribidi.c
vendored
6
src/thirdparty/fribidi-shim/fribidi.c
vendored
|
@ -51,13 +51,15 @@ int load_fribidi(void) {
|
||||||
LOAD_FUNCTION(fribidi_charset_to_unicode);
|
LOAD_FUNCTION(fribidi_charset_to_unicode);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if (dlerror() || error) {
|
fribidi_version_info = *(const char**)dlsym(p_fribidi, "fribidi_version_info");
|
||||||
|
if (dlerror() || error || (fribidi_version_info == NULL)) {
|
||||||
dlclose(p_fribidi);
|
dlclose(p_fribidi);
|
||||||
p_fribidi = NULL;
|
p_fribidi = NULL;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (error) {
|
fribidi_version_info = *(const char**)GetProcAddress(p_fribidi, "fribidi_version_info");
|
||||||
|
if (error || (fribidi_version_info == NULL)) {
|
||||||
FreeLibrary(p_fribidi);
|
FreeLibrary(p_fribidi);
|
||||||
p_fribidi = NULL;
|
p_fribidi = NULL;
|
||||||
return 2;
|
return 2;
|
||||||
|
|
5
src/thirdparty/fribidi-shim/fribidi.h
vendored
5
src/thirdparty/fribidi-shim/fribidi.h
vendored
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
#define FRIBIDI_MAJOR_VERSION 1
|
||||||
|
|
||||||
/* fribidi-types.h */
|
/* fribidi-types.h */
|
||||||
|
|
||||||
# if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
|
# if defined (_SVR4) || defined (SVR4) || defined (__OpenBSD__) || \
|
||||||
|
@ -93,6 +95,9 @@ FRIBIDI_FUNC(FriBidiStrIndex, fribidi_charset_to_unicode,
|
||||||
|
|
||||||
#undef FRIBIDI_FUNC
|
#undef FRIBIDI_FUNC
|
||||||
|
|
||||||
|
/* constant, not a function */
|
||||||
|
FRIBIDI_ENTRY const char *fribidi_version_info;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* shim */
|
/* shim */
|
||||||
|
|
8
src/thirdparty/raqm/raqm.c
vendored
8
src/thirdparty/raqm/raqm.c
vendored
|
@ -30,16 +30,20 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_SYSTEM
|
||||||
|
#include <fribidi.h>
|
||||||
|
#else
|
||||||
#include "../fribidi-shim/fribidi.h"
|
#include "../fribidi-shim/fribidi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <hb.h>
|
#include <hb.h>
|
||||||
#include <hb-ft.h>
|
#include <hb-ft.h>
|
||||||
|
|
||||||
#include "raqm.h"
|
#include "raqm.h"
|
||||||
|
|
||||||
//#if FRIBIDI_MAJOR_VERSION >= 1
|
#if FRIBIDI_MAJOR_VERSION >= 1
|
||||||
#define USE_FRIBIDI_EX_API
|
#define USE_FRIBIDI_EX_API
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:raqm
|
* SECTION:raqm
|
||||||
|
|
Loading…
Reference in New Issue
Block a user