mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 01:16:16 +03:00
Merge branch 'python-pillow:main' into eps_plugin_perf
This commit is contained in:
commit
89bdcfe835
8
.github/workflows/test-mingw.yml
vendored
8
.github/workflows/test-mingw.yml
vendored
|
@ -5,7 +5,7 @@ on: [push, pull_request, workflow_dispatch]
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
@ -49,7 +49,6 @@ jobs:
|
||||||
${{ matrix.package }}-python3-numpy \
|
${{ matrix.package }}-python3-numpy \
|
||||||
${{ matrix.package }}-python3-olefile \
|
${{ matrix.package }}-python3-olefile \
|
||||||
${{ matrix.package }}-python3-pip \
|
${{ matrix.package }}-python3-pip \
|
||||||
${{ matrix.package }}-python-pyqt6 \
|
|
||||||
${{ matrix.package }}-python3-setuptools \
|
${{ matrix.package }}-python3-setuptools \
|
||||||
${{ matrix.package }}-freetype \
|
${{ matrix.package }}-freetype \
|
||||||
${{ matrix.package }}-gcc \
|
${{ matrix.package }}-gcc \
|
||||||
|
@ -63,6 +62,11 @@ jobs:
|
||||||
${{ matrix.package }}-openjpeg2 \
|
${{ matrix.package }}-openjpeg2 \
|
||||||
subversion
|
subversion
|
||||||
|
|
||||||
|
if [ ${{ matrix.package }} == "mingw-w64-x86_64" ]; then
|
||||||
|
pacman -S --noconfirm \
|
||||||
|
${{ matrix.package }}-python-pyqt6
|
||||||
|
fi
|
||||||
|
|
||||||
python3 -m pip install pyroma pytest pytest-cov pytest-timeout
|
python3 -m pip install pyroma pytest pytest-cov pytest-timeout
|
||||||
|
|
||||||
pushd depends && ./install_extra_test_images.sh && popd
|
pushd depends && ./install_extra_test_images.sh && popd
|
||||||
|
|
|
@ -5,6 +5,9 @@ Changelog (Pillow)
|
||||||
9.5.0 (unreleased)
|
9.5.0 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- Raise ValueError for BoxBlur filter with negative radius #6874
|
||||||
|
[hugovk, radarhere]
|
||||||
|
|
||||||
- Support arbitrary number of loaded modules on Windows #6761
|
- Support arbitrary number of loaded modules on Windows #6761
|
||||||
[javidcf, radarhere, nulano]
|
[javidcf, radarhere, nulano]
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ from .helper import assert_image_equal, hopper
|
||||||
ImageFilter.ModeFilter,
|
ImageFilter.ModeFilter,
|
||||||
ImageFilter.GaussianBlur,
|
ImageFilter.GaussianBlur,
|
||||||
ImageFilter.GaussianBlur(5),
|
ImageFilter.GaussianBlur(5),
|
||||||
|
ImageFilter.BoxBlur(0),
|
||||||
ImageFilter.BoxBlur(5),
|
ImageFilter.BoxBlur(5),
|
||||||
ImageFilter.UnsharpMask,
|
ImageFilter.UnsharpMask,
|
||||||
ImageFilter.UnsharpMask(10),
|
ImageFilter.UnsharpMask(10),
|
||||||
|
@ -173,3 +174,14 @@ def test_consistency_5x5(mode):
|
||||||
Image.merge(mode, source[: len(mode)]).filter(kernel),
|
Image.merge(mode, source[: len(mode)]).filter(kernel),
|
||||||
Image.merge(mode, reference[: len(mode)]),
|
Image.merge(mode, reference[: len(mode)]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_box_blur_filter():
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
ImageFilter.BoxBlur(-2)
|
||||||
|
|
||||||
|
im = hopper()
|
||||||
|
box_blur_filter = ImageFilter.BoxBlur(2)
|
||||||
|
box_blur_filter.radius = -2
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
im.filter(box_blur_filter)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# install raqm
|
# install raqm
|
||||||
|
|
||||||
|
|
||||||
archive=libraqm-0.9.0
|
archive=libraqm-0.10.0
|
||||||
|
|
||||||
./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/main/$archive.tar.gz
|
./download-and-extract.sh $archive https://raw.githubusercontent.com/python-pillow/pillow-depends/main/$archive.tar.gz
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,10 @@ Pillow for enterprise is available via the Tidelift Subscription. `Learn more <h
|
||||||
:target: https://fosstodon.org/@pillow
|
:target: https://fosstodon.org/@pillow
|
||||||
:alt: Follow on https://fosstodon.org/@pillow
|
:alt: Follow on https://fosstodon.org/@pillow
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<link rel="me" href="https://fosstodon.org/@pillow">
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
========
|
========
|
||||||
|
|
||||||
|
|
|
@ -478,13 +478,13 @@ These platforms have been reported to work at the versions mentioned.
|
||||||
| Operating system | | Tested Python | | Latest tested | | Tested |
|
| Operating system | | Tested Python | | Latest tested | | Tested |
|
||||||
| | | versions | | Pillow version | | processors |
|
| | | versions | | Pillow version | | processors |
|
||||||
+==================================+===========================+==================+==============+
|
+==================================+===========================+==================+==============+
|
||||||
| macOS 13 Ventura | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.3.0 |arm |
|
| macOS 13 Ventura | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.4.0 |arm |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+---------------------------+------------------+--------------+
|
||||||
| macOS 12 Big Sur | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.3.0 |arm |
|
| macOS 12 Big Sur | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.3.0 |arm |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+---------------------------+------------------+--------------+
|
||||||
| macOS 11 Big Sur | 3.7, 3.8, 3.9, 3.10 | 8.4.0 |arm |
|
| macOS 11 Big Sur | 3.7, 3.8, 3.9, 3.10 | 8.4.0 |arm |
|
||||||
| +---------------------------+------------------+--------------+
|
| +---------------------------+------------------+--------------+
|
||||||
| | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.3.0 |x86-64 |
|
| | 3.7, 3.8, 3.9, 3.10, 3.11 | 9.4.0 |x86-64 |
|
||||||
| +---------------------------+------------------+ |
|
| +---------------------------+------------------+ |
|
||||||
| | 3.6 | 8.4.0 | |
|
| | 3.6 | 8.4.0 | |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+---------------------------+------------------+--------------+
|
||||||
|
|
|
@ -183,6 +183,9 @@ class BoxBlur(MultibandFilter):
|
||||||
name = "BoxBlur"
|
name = "BoxBlur"
|
||||||
|
|
||||||
def __init__(self, radius):
|
def __init__(self, radius):
|
||||||
|
if radius < 0:
|
||||||
|
msg = "radius must be >= 0"
|
||||||
|
raise ValueError(msg)
|
||||||
self.radius = radius
|
self.radius = radius
|
||||||
|
|
||||||
def filter(self, image):
|
def filter(self, image):
|
||||||
|
|
|
@ -237,6 +237,9 @@ ImagingBoxBlur(Imaging imOut, Imaging imIn, float radius, int n) {
|
||||||
if (n < 1) {
|
if (n < 1) {
|
||||||
return ImagingError_ValueError("number of passes must be greater than zero");
|
return ImagingError_ValueError("number of passes must be greater than zero");
|
||||||
}
|
}
|
||||||
|
if (radius < 0) {
|
||||||
|
return ImagingError_ValueError("radius must be >= 0");
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(imIn->mode, imOut->mode) || imIn->type != imOut->type ||
|
if (strcmp(imIn->mode, imOut->mode) || imIn->type != imOut->type ||
|
||||||
imIn->bands != imOut->bands || imIn->xsize != imOut->xsize ||
|
imIn->bands != imOut->bands || imIn->xsize != imOut->xsize ||
|
||||||
|
|
4
src/thirdparty/raqm/README.md
vendored
4
src/thirdparty/raqm/README.md
vendored
|
@ -11,7 +11,7 @@ It currently provides bidirectional text support (using [FriBiDi][1] or
|
||||||
As a result, Raqm can support most writing systems covered by Unicode.
|
As a result, Raqm can support most writing systems covered by Unicode.
|
||||||
|
|
||||||
The documentation can be accessed on the web at:
|
The documentation can be accessed on the web at:
|
||||||
> http://host-oman.github.io/libraqm/
|
> https://host-oman.github.io/libraqm/
|
||||||
|
|
||||||
Raqm (Arabic: رَقْم) is writing, also number or digit and the Arabic word for
|
Raqm (Arabic: رَقْم) is writing, also number or digit and the Arabic word for
|
||||||
digital (رَقَمِيّ) shares the same root, so it is a play on “digital writing”.
|
digital (رَقَمِيّ) shares the same root, so it is a play on “digital writing”.
|
||||||
|
@ -81,5 +81,5 @@ The following projects have patches to support complex text layout using Raqm:
|
||||||
[1]: https://github.com/fribidi/fribidi
|
[1]: https://github.com/fribidi/fribidi
|
||||||
[2]: https://github.com/Tehreer/SheenBidi
|
[2]: https://github.com/Tehreer/SheenBidi
|
||||||
[3]: https://github.com/harfbuzz/harfbuzz
|
[3]: https://github.com/harfbuzz/harfbuzz
|
||||||
[4]: https://freetype.org/
|
[4]: https://www.freetype.org
|
||||||
[5]: https://www.gtk.org/gtk-doc
|
[5]: https://www.gtk.org/gtk-doc
|
||||||
|
|
4
src/thirdparty/raqm/raqm-version.h
vendored
4
src/thirdparty/raqm/raqm-version.h
vendored
|
@ -32,10 +32,10 @@
|
||||||
#define _RAQM_VERSION_H_
|
#define _RAQM_VERSION_H_
|
||||||
|
|
||||||
#define RAQM_VERSION_MAJOR 0
|
#define RAQM_VERSION_MAJOR 0
|
||||||
#define RAQM_VERSION_MINOR 9
|
#define RAQM_VERSION_MINOR 10
|
||||||
#define RAQM_VERSION_MICRO 0
|
#define RAQM_VERSION_MICRO 0
|
||||||
|
|
||||||
#define RAQM_VERSION_STRING "0.9.0"
|
#define RAQM_VERSION_STRING "0.10.0"
|
||||||
|
|
||||||
#define RAQM_VERSION_ATLEAST(major,minor,micro) \
|
#define RAQM_VERSION_ATLEAST(major,minor,micro) \
|
||||||
((major)*10000+(minor)*100+(micro) <= \
|
((major)*10000+(minor)*100+(micro) <= \
|
||||||
|
|
554
src/thirdparty/raqm/raqm.c
vendored
554
src/thirdparty/raqm/raqm.c
vendored
|
@ -171,19 +171,23 @@
|
||||||
typedef FriBidiLevel _raqm_bidi_level_t;
|
typedef FriBidiLevel _raqm_bidi_level_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
FT_Face ftface;
|
FT_Face ftface;
|
||||||
int ftloadflags;
|
int ftloadflags;
|
||||||
hb_language_t lang;
|
hb_language_t lang;
|
||||||
hb_script_t script;
|
hb_script_t script;
|
||||||
|
int spacing_after;
|
||||||
} _raqm_text_info;
|
} _raqm_text_info;
|
||||||
|
|
||||||
typedef struct _raqm_run raqm_run_t;
|
typedef struct _raqm_run raqm_run_t;
|
||||||
|
|
||||||
struct _raqm {
|
struct _raqm
|
||||||
|
{
|
||||||
int ref_count;
|
int ref_count;
|
||||||
|
|
||||||
uint32_t *text;
|
uint32_t *text;
|
||||||
|
uint16_t *text_utf16;
|
||||||
char *text_utf8;
|
char *text_utf8;
|
||||||
size_t text_len;
|
size_t text_len;
|
||||||
size_t text_capacity_bytes;
|
size_t text_capacity_bytes;
|
||||||
|
@ -205,7 +209,8 @@ struct _raqm {
|
||||||
int invisible_glyph;
|
int invisible_glyph;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _raqm_run {
|
struct _raqm_run
|
||||||
|
{
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|
||||||
|
@ -217,9 +222,13 @@ struct _raqm_run {
|
||||||
raqm_run_t *next;
|
raqm_run_t *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t
|
static size_t
|
||||||
_raqm_u8_to_u32_index (raqm_t *rq,
|
_raqm_encoding_to_u32_index (raqm_t *rq,
|
||||||
uint32_t index);
|
size_t index);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_raqm_allowed_grapheme_boundary (hb_codepoint_t l_char,
|
||||||
|
hb_codepoint_t r_char);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_raqm_init_text_info (raqm_t *rq)
|
_raqm_init_text_info (raqm_t *rq)
|
||||||
|
@ -231,6 +240,7 @@ _raqm_init_text_info (raqm_t *rq)
|
||||||
rq->text_info[i].ftloadflags = -1;
|
rq->text_info[i].ftloadflags = -1;
|
||||||
rq->text_info[i].lang = default_lang;
|
rq->text_info[i].lang = default_lang;
|
||||||
rq->text_info[i].script = HB_SCRIPT_INVALID;
|
rq->text_info[i].script = HB_SCRIPT_INVALID;
|
||||||
|
rq->text_info[i].spacing_after = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,6 +273,8 @@ _raqm_compare_text_info (_raqm_text_info a,
|
||||||
if (a.script != b.script)
|
if (a.script != b.script)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Spacing shouldn't break runs, so we don't compare them here. */
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +285,7 @@ _raqm_free_text(raqm_t* rq)
|
||||||
rq->text = NULL;
|
rq->text = NULL;
|
||||||
rq->text_info = NULL;
|
rq->text_info = NULL;
|
||||||
rq->text_utf8 = NULL;
|
rq->text_utf8 = NULL;
|
||||||
|
rq->text_utf16 = NULL;
|
||||||
rq->text_len = 0;
|
rq->text_len = 0;
|
||||||
rq->text_capacity_bytes = 0;
|
rq->text_capacity_bytes = 0;
|
||||||
}
|
}
|
||||||
|
@ -280,12 +293,15 @@ _raqm_free_text(raqm_t* rq)
|
||||||
static bool
|
static bool
|
||||||
_raqm_alloc_text(raqm_t *rq,
|
_raqm_alloc_text(raqm_t *rq,
|
||||||
size_t len,
|
size_t len,
|
||||||
bool need_utf8)
|
bool need_utf8,
|
||||||
|
bool need_utf16)
|
||||||
{
|
{
|
||||||
/* Allocate contiguous memory block for texts and text_info */
|
/* Allocate contiguous memory block for texts and text_info */
|
||||||
size_t mem_size = (sizeof (uint32_t) + sizeof (_raqm_text_info)) * len;
|
size_t mem_size = (sizeof (uint32_t) + sizeof (_raqm_text_info)) * len;
|
||||||
if (need_utf8)
|
if (need_utf8)
|
||||||
mem_size += sizeof (char) * len;
|
mem_size += sizeof (char) * len;
|
||||||
|
else if (need_utf16)
|
||||||
|
mem_size += sizeof (uint16_t) * len;
|
||||||
|
|
||||||
if (mem_size > rq->text_capacity_bytes)
|
if (mem_size > rq->text_capacity_bytes)
|
||||||
{
|
{
|
||||||
|
@ -302,6 +318,7 @@ _raqm_alloc_text(raqm_t *rq,
|
||||||
|
|
||||||
rq->text_info = (_raqm_text_info*)(rq->text + len);
|
rq->text_info = (_raqm_text_info*)(rq->text + len);
|
||||||
rq->text_utf8 = need_utf8 ? (char*)(rq->text_info + len) : NULL;
|
rq->text_utf8 = need_utf8 ? (char*)(rq->text_info + len) : NULL;
|
||||||
|
rq->text_utf16 = need_utf16 ? (uint16_t*)(rq->text_info + len) : NULL;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -357,7 +374,7 @@ _raqm_free_runs (raqm_run_t *runs)
|
||||||
* Return value:
|
* Return value:
|
||||||
* A newly allocated #raqm_t with a reference count of 1. The initial reference
|
* A newly allocated #raqm_t with a reference count of 1. The initial reference
|
||||||
* count should be released with raqm_destroy() when you are done using the
|
* count should be released with raqm_destroy() when you are done using the
|
||||||
* #raqm_t. Returns %NULL in case of error.
|
* #raqm_t. Returns `NULL` in case of error.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -381,6 +398,7 @@ raqm_create (void)
|
||||||
rq->invisible_glyph = 0;
|
rq->invisible_glyph = 0;
|
||||||
|
|
||||||
rq->text = NULL;
|
rq->text = NULL;
|
||||||
|
rq->text_utf16 = NULL;
|
||||||
rq->text_utf8 = NULL;
|
rq->text_utf8 = NULL;
|
||||||
rq->text_info = NULL;
|
rq->text_info = NULL;
|
||||||
rq->text_capacity_bytes = 0;
|
rq->text_capacity_bytes = 0;
|
||||||
|
@ -498,7 +516,7 @@ raqm_clear_contents (raqm_t *rq)
|
||||||
* separately can give improper output.
|
* separately can give improper output.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -518,7 +536,7 @@ raqm_set_text (raqm_t *rq,
|
||||||
if (!len)
|
if (!len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!_raqm_alloc_text(rq, len, false))
|
if (!_raqm_alloc_text(rq, len, false, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rq->text_len = len;
|
rq->text_len = len;
|
||||||
|
@ -575,6 +593,53 @@ _raqm_u8_to_u32 (const char *text, size_t len, uint32_t *unicode)
|
||||||
return (out_utf32 - unicode);
|
return (out_utf32 - unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
_raqm_get_utf16_codepoint (const void *str,
|
||||||
|
uint32_t *out_codepoint)
|
||||||
|
{
|
||||||
|
const uint16_t *s = (const uint16_t *)str;
|
||||||
|
|
||||||
|
if (s[0] > 0xD800 && s[0] < 0xDBFF)
|
||||||
|
{
|
||||||
|
if (s[1] > 0xDC00 && s[1] < 0xDFFF)
|
||||||
|
{
|
||||||
|
uint32_t X = ((s[0] & ((1 << 6) -1)) << 10) | (s[1] & ((1 << 10) -1));
|
||||||
|
uint32_t W = (s[0] >> 6) & ((1 << 5) - 1);
|
||||||
|
*out_codepoint = (W+1) << 16 | X;
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* A single high surrogate, this is an error. */
|
||||||
|
*out_codepoint = s[0];
|
||||||
|
s += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*out_codepoint = s[0];
|
||||||
|
s += 1;
|
||||||
|
}
|
||||||
|
return (void *)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
_raqm_u16_to_u32 (const uint16_t *text, size_t len, uint32_t *unicode)
|
||||||
|
{
|
||||||
|
size_t in_len = 0;
|
||||||
|
uint32_t *out_utf32 = unicode;
|
||||||
|
const uint16_t *in_utf16 = text;
|
||||||
|
|
||||||
|
while ((*in_utf16 != '\0') && (in_len < len))
|
||||||
|
{
|
||||||
|
in_utf16 = _raqm_get_utf16_codepoint (in_utf16, out_utf32);
|
||||||
|
++out_utf32;
|
||||||
|
++in_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (out_utf32 - unicode);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* raqm_set_text_utf8:
|
* raqm_set_text_utf8:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
|
@ -584,7 +649,7 @@ _raqm_u8_to_u32 (const char *text, size_t len, uint32_t *unicode)
|
||||||
* Same as raqm_set_text(), but for text encoded in UTF-8 encoding.
|
* Same as raqm_set_text(), but for text encoded in UTF-8 encoding.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -604,7 +669,7 @@ raqm_set_text_utf8 (raqm_t *rq,
|
||||||
if (!len)
|
if (!len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!_raqm_alloc_text(rq, len, true))
|
if (!_raqm_alloc_text(rq, len, true, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rq->text_len = _raqm_u8_to_u32 (text, len, rq->text);
|
rq->text_len = _raqm_u8_to_u32 (text, len, rq->text);
|
||||||
|
@ -614,6 +679,44 @@ raqm_set_text_utf8 (raqm_t *rq,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* raqm_set_text_utf16:
|
||||||
|
* @rq: a #raqm_t.
|
||||||
|
* @text: a UTF-16 encoded text string.
|
||||||
|
* @len: the length of @text in UTF-16 shorts.
|
||||||
|
*
|
||||||
|
* Same as raqm_set_text(), but for text encoded in UTF-16 encoding.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* `true` if no errors happened, `false` otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
raqm_set_text_utf16 (raqm_t *rq,
|
||||||
|
const uint16_t *text,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
if (!rq || !text)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Call raqm_clear_contents to reuse this raqm_t */
|
||||||
|
if (rq->text_len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Empty string, don’t fail but do nothing */
|
||||||
|
if (!len)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!_raqm_alloc_text(rq, len, false, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rq->text_len = _raqm_u16_to_u32 (text, len, rq->text);
|
||||||
|
memcpy (rq->text_utf16, text, sizeof (uint16_t) * len);
|
||||||
|
_raqm_init_text_info (rq);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* raqm_set_par_direction:
|
* raqm_set_par_direction:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
|
@ -640,7 +743,7 @@ raqm_set_text_utf8 (raqm_t *rq,
|
||||||
* text.
|
* text.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -673,7 +776,7 @@ raqm_set_par_direction (raqm_t *rq,
|
||||||
* parts of the text.
|
* parts of the text.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Stability:
|
* Stability:
|
||||||
* Unstable
|
* Unstable
|
||||||
|
@ -687,7 +790,7 @@ raqm_set_language (raqm_t *rq,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
hb_language_t language;
|
hb_language_t language;
|
||||||
size_t end = start + len;
|
size_t end;
|
||||||
|
|
||||||
if (!rq)
|
if (!rq)
|
||||||
return false;
|
return false;
|
||||||
|
@ -695,11 +798,8 @@ raqm_set_language (raqm_t *rq,
|
||||||
if (!rq->text_len)
|
if (!rq->text_len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (rq->text_utf8)
|
end = _raqm_encoding_to_u32_index (rq, start + len);
|
||||||
{
|
start = _raqm_encoding_to_u32_index (rq, start);
|
||||||
start = _raqm_u8_to_u32_index (rq, start);
|
|
||||||
end = _raqm_u8_to_u32_index (rq, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start >= rq->text_len || end > rq->text_len)
|
if (start >= rq->text_len || end > rq->text_len)
|
||||||
return false;
|
return false;
|
||||||
|
@ -716,11 +816,37 @@ raqm_set_language (raqm_t *rq,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_raqm_add_font_feature (raqm_t *rq,
|
||||||
|
hb_feature_t fea)
|
||||||
|
{
|
||||||
|
void* new_features;
|
||||||
|
|
||||||
|
if (!rq)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
new_features = realloc (rq->features,
|
||||||
|
sizeof (hb_feature_t) * (rq->features_len + 1));
|
||||||
|
if (!new_features)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fea.start != HB_FEATURE_GLOBAL_START)
|
||||||
|
fea.start = _raqm_encoding_to_u32_index (rq, fea.start);
|
||||||
|
if (fea.end != HB_FEATURE_GLOBAL_END)
|
||||||
|
fea.end = _raqm_encoding_to_u32_index (rq, fea.end);
|
||||||
|
|
||||||
|
rq->features = new_features;
|
||||||
|
rq->features[rq->features_len] = fea;
|
||||||
|
rq->features_len++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* raqm_add_font_feature:
|
* raqm_add_font_feature:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
* @feature: (transfer none): a font feature string.
|
* @feature: (transfer none): a font feature string.
|
||||||
* @len: length of @feature, -1 for %NULL-terminated.
|
* @len: length of @feature, -1 for `NULL`-terminated.
|
||||||
*
|
*
|
||||||
* Adds a font feature to be used by the #raqm_t during text layout. This is
|
* Adds a font feature to be used by the #raqm_t during text layout. This is
|
||||||
* usually used to turn on optional font features that are not enabled by
|
* usually used to turn on optional font features that are not enabled by
|
||||||
|
@ -734,7 +860,7 @@ raqm_set_language (raqm_t *rq,
|
||||||
* end of the features list and can potentially override previous features.
|
* end of the features list and can potentially override previous features.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if parsing @feature succeeded, %false otherwise.
|
* `true` if parsing @feature succeeded, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -751,16 +877,7 @@ raqm_add_font_feature (raqm_t *rq,
|
||||||
|
|
||||||
ok = hb_feature_from_string (feature, len, &fea);
|
ok = hb_feature_from_string (feature, len, &fea);
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
_raqm_add_font_feature (rq, fea);
|
||||||
void* new_features = realloc (rq->features,
|
|
||||||
sizeof (hb_feature_t) * (rq->features_len + 1));
|
|
||||||
if (!new_features)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rq->features = new_features;
|
|
||||||
rq->features[rq->features_len] = fea;
|
|
||||||
rq->features_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
@ -817,7 +934,7 @@ _raqm_set_freetype_face (raqm_t *rq,
|
||||||
* See also raqm_set_freetype_face_range().
|
* See also raqm_set_freetype_face_range().
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -832,21 +949,23 @@ raqm_set_freetype_face (raqm_t *rq,
|
||||||
* raqm_set_freetype_face_range:
|
* raqm_set_freetype_face_range:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
* @face: an #FT_Face.
|
* @face: an #FT_Face.
|
||||||
* @start: index of first character that should use @face.
|
* @start: index of first character that should use @face from the input string.
|
||||||
* @len: number of characters using @face.
|
* @len: number of elements using @face.
|
||||||
*
|
*
|
||||||
* Sets an #FT_Face to be used for @len-number of characters staring at @start.
|
* Sets an #FT_Face to be used for @len-number of characters staring at @start.
|
||||||
* The @start and @len are input string array indices (i.e. counting bytes in
|
* The @start and @len are input string array indices, counting elements
|
||||||
* UTF-8 and scaler values in UTF-32).
|
* according to the underlying encoding. @start must always be aligned to the
|
||||||
|
* start of an encoded codepoint, and @len must always end at a codepoint's
|
||||||
|
* final element.
|
||||||
*
|
*
|
||||||
* This method can be used repeatedly to set different faces for different
|
* This method can be used repeatedly to set different faces for different
|
||||||
* parts of the text. It is the responsibility of the client to make sure that
|
* parts of the text. It is the responsibility of the client to make sure that
|
||||||
* face ranges cover the whole text.
|
* face ranges cover the whole text, and is properly aligned.
|
||||||
*
|
*
|
||||||
* See also raqm_set_freetype_face().
|
* See also raqm_set_freetype_face().
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -856,7 +975,7 @@ raqm_set_freetype_face_range (raqm_t *rq,
|
||||||
size_t start,
|
size_t start,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
size_t end = start + len;
|
size_t end;
|
||||||
|
|
||||||
if (!rq)
|
if (!rq)
|
||||||
return false;
|
return false;
|
||||||
|
@ -864,11 +983,8 @@ raqm_set_freetype_face_range (raqm_t *rq,
|
||||||
if (!rq->text_len)
|
if (!rq->text_len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (rq->text_utf8)
|
end = _raqm_encoding_to_u32_index (rq, start + len);
|
||||||
{
|
start = _raqm_encoding_to_u32_index (rq, start);
|
||||||
start = _raqm_u8_to_u32_index (rq, start);
|
|
||||||
end = _raqm_u8_to_u32_index (rq, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _raqm_set_freetype_face (rq, face, start, end);
|
return _raqm_set_freetype_face (rq, face, start, end);
|
||||||
}
|
}
|
||||||
|
@ -909,7 +1025,7 @@ _raqm_set_freetype_load_flags (raqm_t *rq,
|
||||||
* older version the flags will be ignored.
|
* older version the flags will be ignored.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.3
|
* Since: 0.3
|
||||||
*/
|
*/
|
||||||
|
@ -943,7 +1059,7 @@ raqm_set_freetype_load_flags (raqm_t *rq,
|
||||||
* See also raqm_set_freetype_load_flags().
|
* See also raqm_set_freetype_load_flags().
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.9
|
* Since: 0.9
|
||||||
*/
|
*/
|
||||||
|
@ -953,7 +1069,7 @@ raqm_set_freetype_load_flags_range (raqm_t *rq,
|
||||||
size_t start,
|
size_t start,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
size_t end = start + len;
|
size_t end;
|
||||||
|
|
||||||
if (!rq)
|
if (!rq)
|
||||||
return false;
|
return false;
|
||||||
|
@ -961,15 +1077,161 @@ raqm_set_freetype_load_flags_range (raqm_t *rq,
|
||||||
if (!rq->text_len)
|
if (!rq->text_len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (rq->text_utf8)
|
end = _raqm_encoding_to_u32_index (rq, start + len);
|
||||||
{
|
start = _raqm_encoding_to_u32_index (rq, start);
|
||||||
start = _raqm_u8_to_u32_index (rq, start);
|
|
||||||
end = _raqm_u8_to_u32_index (rq, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _raqm_set_freetype_load_flags (rq, flags, start, end);
|
return _raqm_set_freetype_load_flags (rq, flags, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_raqm_set_spacing (raqm_t *rq,
|
||||||
|
int spacing,
|
||||||
|
bool word_spacing,
|
||||||
|
size_t start,
|
||||||
|
size_t end)
|
||||||
|
{
|
||||||
|
if (!rq)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!rq->text_len)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (start >= rq->text_len || end > rq->text_len)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!rq->text_info)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
bool set_spacing = i == 0;
|
||||||
|
if (!set_spacing)
|
||||||
|
set_spacing = _raqm_allowed_grapheme_boundary (rq->text[i-1], rq->text[i]);
|
||||||
|
|
||||||
|
if (set_spacing)
|
||||||
|
{
|
||||||
|
if (word_spacing)
|
||||||
|
{
|
||||||
|
if (_raqm_allowed_grapheme_boundary (rq->text[i], rq->text[i+1]))
|
||||||
|
{
|
||||||
|
/* CSS word seperators, word spacing is only applied on these.*/
|
||||||
|
if (rq->text[i] == 0x0020 || /* Space */
|
||||||
|
rq->text[i] == 0x00A0 || /* No Break Space */
|
||||||
|
rq->text[i] == 0x1361 || /* Ethiopic Word Space */
|
||||||
|
rq->text[i] == 0x10100 || /* Aegean Word Seperator Line */
|
||||||
|
rq->text[i] == 0x10101 || /* Aegean Word Seperator Dot */
|
||||||
|
rq->text[i] == 0x1039F || /* Ugaric Word Divider */
|
||||||
|
rq->text[i] == 0x1091F) /* Phoenician Word Separator */
|
||||||
|
{
|
||||||
|
rq->text_info[i].spacing_after = spacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rq->text_info[i].spacing_after = spacing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* raqm_set_letter_spacing_range:
|
||||||
|
* @rq: a #raqm_t.
|
||||||
|
* @spacing: amount of spacing in Freetype Font Units (26.6 format).
|
||||||
|
* @start: index of first character that should use @spacing.
|
||||||
|
* @len: number of characters using @spacing.
|
||||||
|
*
|
||||||
|
* Set the letter spacing or tracking for a given range, the value
|
||||||
|
* will be added onto the advance and offset for RTL, and the advance for
|
||||||
|
* other directions. Letter spacing will be applied between characters, so
|
||||||
|
* the last character will not have spacing applied after it.
|
||||||
|
* Note that not all scripts have a letter-spacing tradition,
|
||||||
|
* for example, Arabic does not, while Devanagari does.
|
||||||
|
*
|
||||||
|
* This will also add “disable `liga`, `clig`, `hlig`, `dlig`, and `calt`” font
|
||||||
|
* features to the internal features list, so call this function after setting
|
||||||
|
* the font features for best spacing results.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* `true` if no errors happened, `false` otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
raqm_set_letter_spacing_range(raqm_t *rq,
|
||||||
|
int spacing,
|
||||||
|
size_t start,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
size_t end;
|
||||||
|
|
||||||
|
if (!rq)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!rq->text_len)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
end = start + len - 1;
|
||||||
|
|
||||||
|
if (spacing != 0)
|
||||||
|
{
|
||||||
|
#define NUM_TAGS 5
|
||||||
|
static char *tags[NUM_TAGS] = { "clig", "liga", "hlig", "dlig", "calt" };
|
||||||
|
for (size_t i = 0; i < NUM_TAGS; i++)
|
||||||
|
{
|
||||||
|
hb_feature_t fea = { hb_tag_from_string(tags[i], 5), 0, start, end };
|
||||||
|
_raqm_add_font_feature (rq, fea);
|
||||||
|
}
|
||||||
|
#undef NUM_TAGS
|
||||||
|
}
|
||||||
|
|
||||||
|
start = _raqm_encoding_to_u32_index (rq, start);
|
||||||
|
end = _raqm_encoding_to_u32_index (rq, end);
|
||||||
|
|
||||||
|
return _raqm_set_spacing (rq, spacing, false, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* raqm_set_word_spacing_range:
|
||||||
|
* @rq: a #raqm_t.
|
||||||
|
* @spacing: amount of spacing in Freetype Font Units (26.6 format).
|
||||||
|
* @start: index of first character that should use @spacing.
|
||||||
|
* @len: number of characters using @spacing.
|
||||||
|
*
|
||||||
|
* Set the word spacing for a given range. Word spacing will only be applied to
|
||||||
|
* 'word separator' characters, such as 'space', 'no break space' and
|
||||||
|
* Ethiopic word separator'.
|
||||||
|
* The value will be added onto the advance and offset for RTL, and the advance
|
||||||
|
* for other directions.
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* `true` if no errors happened, `false` otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.10
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
raqm_set_word_spacing_range(raqm_t *rq,
|
||||||
|
int spacing,
|
||||||
|
size_t start,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
size_t end;
|
||||||
|
|
||||||
|
if (!rq)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!rq->text_len)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
end = _raqm_encoding_to_u32_index (rq, start + len);
|
||||||
|
start = _raqm_encoding_to_u32_index (rq, start);
|
||||||
|
|
||||||
|
return _raqm_set_spacing (rq, spacing, true, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* raqm_set_invisible_glyph:
|
* raqm_set_invisible_glyph:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
|
@ -984,7 +1246,7 @@ raqm_set_freetype_load_flags_range (raqm_t *rq,
|
||||||
* If @gid is a positive number, it will be used for invisible glyphs.
|
* If @gid is a positive number, it will be used for invisible glyphs.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* `true` if no errors happened, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.6
|
* Since: 0.6
|
||||||
*/
|
*/
|
||||||
|
@ -1014,7 +1276,7 @@ _raqm_shape (raqm_t *rq);
|
||||||
* text shaping, and any other part of the layout process.
|
* text shaping, and any other part of the layout process.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if the layout process was successful, %false otherwise.
|
* `true` if the layout process was successful, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -1048,7 +1310,9 @@ raqm_layout (raqm_t *rq)
|
||||||
static uint32_t
|
static uint32_t
|
||||||
_raqm_u32_to_u8_index (raqm_t *rq,
|
_raqm_u32_to_u8_index (raqm_t *rq,
|
||||||
uint32_t index);
|
uint32_t index);
|
||||||
|
static uint32_t
|
||||||
|
_raqm_u32_to_u16_index (raqm_t *rq,
|
||||||
|
uint32_t index);
|
||||||
/**
|
/**
|
||||||
* raqm_get_glyphs:
|
* raqm_get_glyphs:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
|
@ -1059,7 +1323,7 @@ _raqm_u32_to_u8_index (raqm_t *rq,
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
* Return value: (transfer none):
|
* Return value: (transfer none):
|
||||||
* An array of #raqm_glyph_t, or %NULL in case of error. This is owned by @rq
|
* An array of #raqm_glyph_t, or `NULL` in case of error. This is owned by @rq
|
||||||
* and must not be freed.
|
* and must not be freed.
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
|
@ -1147,6 +1411,12 @@ raqm_get_glyphs (raqm_t *rq,
|
||||||
RAQM_TEST ("\n");
|
RAQM_TEST ("\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else if (rq->text_utf16)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
rq->glyphs[i].cluster = _raqm_u32_to_u16_index (rq,
|
||||||
|
rq->glyphs[i].cluster);
|
||||||
|
}
|
||||||
return rq->glyphs;
|
return rq->glyphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1194,8 +1464,10 @@ raqm_get_direction_at_index (raqm_t *rq,
|
||||||
|
|
||||||
for (raqm_run_t *run = rq->runs; run != NULL; run = run->next)
|
for (raqm_run_t *run = rq->runs; run != NULL; run = run->next)
|
||||||
{
|
{
|
||||||
if (run->pos <= index && index < run->pos + run->len) {
|
if (run->pos <= index && index < run->pos + run->len)
|
||||||
switch (run->direction) {
|
{
|
||||||
|
switch (run->direction)
|
||||||
|
{
|
||||||
case HB_DIRECTION_LTR:
|
case HB_DIRECTION_LTR:
|
||||||
return RAQM_DIRECTION_LTR;
|
return RAQM_DIRECTION_LTR;
|
||||||
case HB_DIRECTION_RTL:
|
case HB_DIRECTION_RTL:
|
||||||
|
@ -1227,7 +1499,8 @@ _raqm_hb_dir (raqm_t *rq, _raqm_bidi_level_t level)
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
size_t pos;
|
size_t pos;
|
||||||
size_t len;
|
size_t len;
|
||||||
_raqm_bidi_level_t level;
|
_raqm_bidi_level_t level;
|
||||||
|
@ -1264,10 +1537,10 @@ _raqm_bidi_itemize (raqm_t *rq, size_t *run_count)
|
||||||
line = SBParagraphCreateLine (par, 0, par_len);
|
line = SBParagraphCreateLine (par, 0, par_len);
|
||||||
*run_count = SBLineGetRunCount (line);
|
*run_count = SBLineGetRunCount (line);
|
||||||
|
|
||||||
if (SBParagraphGetBaseLevel (par) == 0)
|
if (SBParagraphGetBaseLevel (par) == 1)
|
||||||
rq->resolved_dir = RAQM_DIRECTION_LTR;
|
|
||||||
else
|
|
||||||
rq->resolved_dir = RAQM_DIRECTION_RTL;
|
rq->resolved_dir = RAQM_DIRECTION_RTL;
|
||||||
|
else
|
||||||
|
rq->resolved_dir = RAQM_DIRECTION_LTR;
|
||||||
|
|
||||||
runs = malloc (sizeof (_raqm_bidi_run) * (*run_count));
|
runs = malloc (sizeof (_raqm_bidi_run) * (*run_count));
|
||||||
if (runs)
|
if (runs)
|
||||||
|
@ -1418,10 +1691,10 @@ _raqm_bidi_itemize (raqm_t *rq, size_t *run_count)
|
||||||
rq->text_len, &par_type,
|
rq->text_len, &par_type,
|
||||||
levels);
|
levels);
|
||||||
|
|
||||||
if (par_type == FRIBIDI_PAR_LTR)
|
if (par_type == FRIBIDI_PAR_RTL)
|
||||||
rq->resolved_dir = RAQM_DIRECTION_LTR;
|
|
||||||
else
|
|
||||||
rq->resolved_dir = RAQM_DIRECTION_RTL;
|
rq->resolved_dir = RAQM_DIRECTION_RTL;
|
||||||
|
else
|
||||||
|
rq->resolved_dir = RAQM_DIRECTION_LTR;
|
||||||
|
|
||||||
if (max_level == 0)
|
if (max_level == 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -1447,22 +1720,15 @@ _raqm_itemize (raqm_t *rq)
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
|
|
||||||
#ifdef RAQM_TESTING
|
#ifdef RAQM_TESTING
|
||||||
switch (rq->base_dir)
|
static char *dir_names[] = {
|
||||||
{
|
"DEFAULT",
|
||||||
case RAQM_DIRECTION_RTL:
|
"RTL",
|
||||||
RAQM_TEST ("Direction is: RTL\n\n");
|
"LTR",
|
||||||
break;
|
"TTB"
|
||||||
case RAQM_DIRECTION_LTR:
|
};
|
||||||
RAQM_TEST ("Direction is: LTR\n\n");
|
|
||||||
break;
|
assert (rq->base_dir < sizeof (dir_names));
|
||||||
case RAQM_DIRECTION_TTB:
|
RAQM_TEST ("Direction is: %s\n\n", dir_names[rq->base_dir]);
|
||||||
RAQM_TEST ("Direction is: TTB\n\n");
|
|
||||||
break;
|
|
||||||
case RAQM_DIRECTION_DEFAULT:
|
|
||||||
default:
|
|
||||||
RAQM_TEST ("Direction is: DEFAULT\n\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!_raqm_resolve_scripts (rq))
|
if (!_raqm_resolve_scripts (rq))
|
||||||
|
@ -1483,9 +1749,9 @@ _raqm_itemize (raqm_t *rq)
|
||||||
runs->len = rq->text_len;
|
runs->len = rq->text_len;
|
||||||
runs->level = 0;
|
runs->level = 0;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
runs = _raqm_bidi_itemize (rq, &run_count);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
runs = _raqm_bidi_itemize (rq, &run_count);
|
||||||
|
|
||||||
if (!runs)
|
if (!runs)
|
||||||
{
|
{
|
||||||
|
@ -1494,6 +1760,9 @@ _raqm_itemize (raqm_t *rq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RAQM_TESTING
|
#ifdef RAQM_TESTING
|
||||||
|
assert (rq->resolved_dir < sizeof (dir_names));
|
||||||
|
if (rq->base_dir == RAQM_DIRECTION_DEFAULT)
|
||||||
|
RAQM_TEST ("Resolved direction is: %s\n\n", dir_names[rq->resolved_dir]);
|
||||||
RAQM_TEST ("Number of runs before script itemization: %zu\n\n", run_count);
|
RAQM_TEST ("Number of runs before script itemization: %zu\n\n", run_count);
|
||||||
|
|
||||||
RAQM_TEST ("BiDi Runs:\n");
|
RAQM_TEST ("BiDi Runs:\n");
|
||||||
|
@ -1617,7 +1886,8 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stack to handle script detection */
|
/* Stack to handle script detection */
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
size_t size;
|
size_t size;
|
||||||
int *pair_index;
|
int *pair_index;
|
||||||
|
@ -1910,15 +2180,47 @@ _raqm_shape (raqm_t *rq)
|
||||||
|
|
||||||
{
|
{
|
||||||
FT_Matrix matrix;
|
FT_Matrix matrix;
|
||||||
|
hb_glyph_info_t *info;
|
||||||
hb_glyph_position_t *pos;
|
hb_glyph_position_t *pos;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
|
||||||
FT_Get_Transform (hb_ft_font_get_face (run->font), &matrix, NULL);
|
FT_Get_Transform (hb_ft_font_get_face (run->font), &matrix, NULL);
|
||||||
pos = hb_buffer_get_glyph_positions (run->buffer, &len);
|
pos = hb_buffer_get_glyph_positions (run->buffer, &len);
|
||||||
|
info = hb_buffer_get_glyph_infos (run->buffer, &len);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < len; i++)
|
for (unsigned int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
_raqm_ft_transform (&pos[i].x_advance, &pos[i].y_advance, matrix);
|
_raqm_ft_transform (&pos[i].x_advance, &pos[i].y_advance, matrix);
|
||||||
_raqm_ft_transform (&pos[i].x_offset, &pos[i].y_offset, matrix);
|
_raqm_ft_transform (&pos[i].x_offset, &pos[i].y_offset, matrix);
|
||||||
|
|
||||||
|
bool set_spacing = false;
|
||||||
|
if (run->direction == HB_DIRECTION_RTL)
|
||||||
|
{
|
||||||
|
set_spacing = i == 0;
|
||||||
|
if (!set_spacing)
|
||||||
|
set_spacing = info[i].cluster != info[i-1].cluster;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_spacing = i == len - 1;
|
||||||
|
if (!set_spacing)
|
||||||
|
set_spacing = info[i].cluster != info[i+1].cluster;
|
||||||
|
}
|
||||||
|
|
||||||
|
_raqm_text_info rq_info = rq->text_info[info[i].cluster];
|
||||||
|
|
||||||
|
if (rq_info.spacing_after != 0 && set_spacing)
|
||||||
|
{
|
||||||
|
if (run->direction == HB_DIRECTION_TTB)
|
||||||
|
pos[i].y_advance -= rq_info.spacing_after;
|
||||||
|
else if (run->direction == HB_DIRECTION_RTL)
|
||||||
|
{
|
||||||
|
pos[i].x_advance += rq_info.spacing_after;
|
||||||
|
pos[i].x_offset += rq_info.spacing_after;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pos[i].x_advance += rq_info.spacing_after;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1954,9 +2256,9 @@ _raqm_u32_to_u8_index (raqm_t *rq,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert index from UTF-8 to UTF-32 */
|
/* Convert index from UTF-8 to UTF-32 */
|
||||||
static uint32_t
|
static size_t
|
||||||
_raqm_u8_to_u32_index (raqm_t *rq,
|
_raqm_u8_to_u32_index (raqm_t *rq,
|
||||||
uint32_t index)
|
size_t index)
|
||||||
{
|
{
|
||||||
const unsigned char *s = (const unsigned char *) rq->text_utf8;
|
const unsigned char *s = (const unsigned char *) rq->text_utf8;
|
||||||
const unsigned char *t = s;
|
const unsigned char *t = s;
|
||||||
|
@ -1982,9 +2284,64 @@ _raqm_u8_to_u32_index (raqm_t *rq,
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
/* Count equivalent UTF-16 short in codepoint */
|
||||||
_raqm_allowed_grapheme_boundary (hb_codepoint_t l_char,
|
static size_t
|
||||||
hb_codepoint_t r_char);
|
_raqm_count_codepoint_utf16_short (uint32_t chr)
|
||||||
|
{
|
||||||
|
if (chr > 0x010000)
|
||||||
|
return 2;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert index from UTF-32 to UTF-16 */
|
||||||
|
static uint32_t
|
||||||
|
_raqm_u32_to_u16_index (raqm_t *rq,
|
||||||
|
uint32_t index)
|
||||||
|
{
|
||||||
|
size_t length = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < index; ++i)
|
||||||
|
length += _raqm_count_codepoint_utf16_short (rq->text[i]);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert index from UTF-16 to UTF-32 */
|
||||||
|
static size_t
|
||||||
|
_raqm_u16_to_u32_index (raqm_t *rq,
|
||||||
|
size_t index)
|
||||||
|
{
|
||||||
|
const uint16_t *s = (const uint16_t *) rq->text_utf16;
|
||||||
|
const uint16_t *t = s;
|
||||||
|
size_t length = 0;
|
||||||
|
|
||||||
|
while (((size_t) (s - t) < index) && ('\0' != *s))
|
||||||
|
{
|
||||||
|
if (*s < 0xD800 || *s > 0xDBFF)
|
||||||
|
s += 1;
|
||||||
|
else
|
||||||
|
s += 2;
|
||||||
|
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size_t) (s-t) > index)
|
||||||
|
length--;
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
_raqm_encoding_to_u32_index (raqm_t *rq,
|
||||||
|
size_t index)
|
||||||
|
{
|
||||||
|
if (rq->text_utf8)
|
||||||
|
return _raqm_u8_to_u32_index (rq, index);
|
||||||
|
else if (rq->text_utf16)
|
||||||
|
return _raqm_u16_to_u32_index (rq, index);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_raqm_in_hangul_syllable (hb_codepoint_t ch);
|
_raqm_in_hangul_syllable (hb_codepoint_t ch);
|
||||||
|
@ -2001,7 +2358,7 @@ _raqm_in_hangul_syllable (hb_codepoint_t ch);
|
||||||
* character is left-to-right, then the cursor will be at the right of it.
|
* character is left-to-right, then the cursor will be at the right of it.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if the process was successful, %false otherwise.
|
* `true` if the process was successful, `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.2
|
* Since: 0.2
|
||||||
*/
|
*/
|
||||||
|
@ -2018,8 +2375,7 @@ raqm_index_to_position (raqm_t *rq,
|
||||||
if (rq == NULL)
|
if (rq == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (rq->text_utf8)
|
*index = _raqm_encoding_to_u32_index (rq, *index);
|
||||||
*index = _raqm_u8_to_u32_index (rq, *index);
|
|
||||||
|
|
||||||
if (*index >= rq->text_len)
|
if (*index >= rq->text_len)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2077,6 +2433,8 @@ raqm_index_to_position (raqm_t *rq,
|
||||||
found:
|
found:
|
||||||
if (rq->text_utf8)
|
if (rq->text_utf8)
|
||||||
*index = _raqm_u32_to_u8_index (rq, *index);
|
*index = _raqm_u32_to_u8_index (rq, *index);
|
||||||
|
else if (rq->text_utf16)
|
||||||
|
*index = _raqm_u32_to_u16_index (rq, *index);
|
||||||
RAQM_TEST ("The position is %d at index %zu\n",*x ,*index);
|
RAQM_TEST ("The position is %d at index %zu\n",*x ,*index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2093,7 +2451,7 @@ found:
|
||||||
* @index.
|
* @index.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if the process was successful, %false in case of error.
|
* `true` if the process was successful, `false` in case of error.
|
||||||
*
|
*
|
||||||
* Since: 0.2
|
* Since: 0.2
|
||||||
*/
|
*/
|
||||||
|
@ -2371,8 +2729,8 @@ raqm_version_string (void)
|
||||||
* Checks if library version is less than or equal the specified version.
|
* Checks if library version is less than or equal the specified version.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if library version is less than or equal the specfied version, %false
|
* `true` if library version is less than or equal the specified version,
|
||||||
* otherwise.
|
* `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.7
|
* Since: 0.7
|
||||||
**/
|
**/
|
||||||
|
@ -2393,8 +2751,8 @@ raqm_version_atleast (unsigned int major,
|
||||||
* Checks if library version is less than or equal the specified version.
|
* Checks if library version is less than or equal the specified version.
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if library version is less than or equal the specfied version, %false
|
* `true` if library version is less than or equal the specified version,
|
||||||
* otherwise.
|
* `false` otherwise.
|
||||||
*
|
*
|
||||||
* Since: 0.7
|
* Since: 0.7
|
||||||
**/
|
**/
|
||||||
|
|
15
src/thirdparty/raqm/raqm.h
vendored
15
src/thirdparty/raqm/raqm.h
vendored
|
@ -118,6 +118,10 @@ RAQM_API bool
|
||||||
raqm_set_text_utf8 (raqm_t *rq,
|
raqm_set_text_utf8 (raqm_t *rq,
|
||||||
const char *text,
|
const char *text,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
RAQM_API bool
|
||||||
|
raqm_set_text_utf16 (raqm_t *rq,
|
||||||
|
const uint16_t *text,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
RAQM_API bool
|
RAQM_API bool
|
||||||
raqm_set_par_direction (raqm_t *rq,
|
raqm_set_par_direction (raqm_t *rq,
|
||||||
|
@ -154,6 +158,17 @@ raqm_set_freetype_load_flags_range (raqm_t *rq,
|
||||||
size_t start,
|
size_t start,
|
||||||
size_t len);
|
size_t len);
|
||||||
|
|
||||||
|
RAQM_API bool
|
||||||
|
raqm_set_letter_spacing_range(raqm_t *rq,
|
||||||
|
int spacing,
|
||||||
|
size_t start,
|
||||||
|
size_t len);
|
||||||
|
RAQM_API bool
|
||||||
|
raqm_set_word_spacing_range(raqm_t *rq,
|
||||||
|
int spacing,
|
||||||
|
size_t start,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
RAQM_API bool
|
RAQM_API bool
|
||||||
raqm_set_invisible_glyph (raqm_t *rq,
|
raqm_set_invisible_glyph (raqm_t *rq,
|
||||||
int gid);
|
int gid);
|
||||||
|
|
|
@ -152,9 +152,9 @@ deps = {
|
||||||
"libs": [r"*.lib"],
|
"libs": [r"*.lib"],
|
||||||
},
|
},
|
||||||
"xz": {
|
"xz": {
|
||||||
"url": SF_PROJECTS + "/lzmautils/files/xz-5.4.0.tar.gz/download",
|
"url": SF_PROJECTS + "/lzmautils/files/xz-5.4.1.tar.gz/download",
|
||||||
"filename": "xz-5.4.0.tar.gz",
|
"filename": "xz-5.4.1.tar.gz",
|
||||||
"dir": "xz-5.4.0",
|
"dir": "xz-5.4.1",
|
||||||
"license": "COPYING",
|
"license": "COPYING",
|
||||||
"patch": {
|
"patch": {
|
||||||
r"src\liblzma\api\lzma.h": {
|
r"src\liblzma\api\lzma.h": {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user