mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-27 02:16:19 +03:00
Merge remote-tracking branch 'upstream/main' into add-cygwin-to-ci
This commit is contained in:
commit
b582806887
1
.github/workflows/test-docker.yml
vendored
1
.github/workflows/test-docker.yml
vendored
|
@ -19,7 +19,6 @@ jobs:
|
||||||
amazon-2-amd64,
|
amazon-2-amd64,
|
||||||
arch,
|
arch,
|
||||||
centos-7-amd64,
|
centos-7-amd64,
|
||||||
centos-8-amd64,
|
|
||||||
centos-stream-8-amd64,
|
centos-stream-8-amd64,
|
||||||
debian-10-buster-x86,
|
debian-10-buster-x86,
|
||||||
debian-11-bullseye-x86,
|
debian-11-bullseye-x86,
|
||||||
|
|
2
.github/workflows/test-mingw.yml
vendored
2
.github/workflows/test-mingw.yml
vendored
|
@ -4,7 +4,7 @@ on: [push, pull_request, workflow_dispatch]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: windows-2019
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
2
.github/workflows/test-windows.yml
vendored
2
.github/workflows/test-windows.yml
vendored
|
@ -4,7 +4,7 @@ on: [push, pull_request, workflow_dispatch]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: windows-2019
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
15
CHANGES.rst
15
CHANGES.rst
|
@ -5,6 +5,12 @@ Changelog (Pillow)
|
||||||
9.1.0 (unreleased)
|
9.1.0 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- Enable arm64 for MSVC on Windows #5811
|
||||||
|
[gaborkertesz-linaro, gaborkertesz]
|
||||||
|
|
||||||
|
- Keep IPython/Jupyter text/plain output stable #5891
|
||||||
|
[shamrin, radarhere]
|
||||||
|
|
||||||
- Raise an error when performing a negative crop #5972
|
- Raise an error when performing a negative crop #5972
|
||||||
[radarhere, hugovk]
|
[radarhere, hugovk]
|
||||||
|
|
||||||
|
@ -26,6 +32,15 @@ Changelog (Pillow)
|
||||||
- Remove readonly from Image.__eq__ #5930
|
- Remove readonly from Image.__eq__ #5930
|
||||||
[hugovk]
|
[hugovk]
|
||||||
|
|
||||||
|
9.0.1 (2022-02-03)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- In show_file, use os.remove to remove temporary images. CVE-2022-24303 #6010
|
||||||
|
[radarhere, hugovk]
|
||||||
|
|
||||||
|
- Restrict builtins within lambdas for ImageMath.eval. CVE-2022-22817 #6009
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
9.0.0 (2022-01-02)
|
9.0.0 (2022-01-02)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,15 @@ def test_sanity():
|
||||||
assert image2_scale2.format == "EPS"
|
assert image2_scale2.format == "EPS"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not HAS_GHOSTSCRIPT, reason="Ghostscript not available")
|
||||||
|
def test_load():
|
||||||
|
with Image.open(FILE1) as im:
|
||||||
|
assert im.load()[0, 0] == (255, 255, 255)
|
||||||
|
|
||||||
|
# Test again now that it has already been loaded once
|
||||||
|
assert im.load()[0, 0] == (255, 255, 255)
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_file():
|
def test_invalid_file():
|
||||||
invalid_file = "Tests/images/flower.jpg"
|
invalid_file = "Tests/images/flower.jpg"
|
||||||
|
|
||||||
|
|
|
@ -5,20 +5,28 @@ from PIL import GbrImagePlugin, Image
|
||||||
from .helper import assert_image_equal_tofile
|
from .helper import assert_image_equal_tofile
|
||||||
|
|
||||||
|
|
||||||
def test_invalid_file():
|
|
||||||
invalid_file = "Tests/images/flower.jpg"
|
|
||||||
|
|
||||||
with pytest.raises(SyntaxError):
|
|
||||||
GbrImagePlugin.GbrImageFile(invalid_file)
|
|
||||||
|
|
||||||
|
|
||||||
def test_gbr_file():
|
def test_gbr_file():
|
||||||
with Image.open("Tests/images/gbr.gbr") as im:
|
with Image.open("Tests/images/gbr.gbr") as im:
|
||||||
assert_image_equal_tofile(im, "Tests/images/gbr.png")
|
assert_image_equal_tofile(im, "Tests/images/gbr.png")
|
||||||
|
|
||||||
|
|
||||||
|
def test_load():
|
||||||
|
with Image.open("Tests/images/gbr.gbr") as im:
|
||||||
|
assert im.load()[0, 0] == (0, 0, 0, 0)
|
||||||
|
|
||||||
|
# Test again now that it has already been loaded once
|
||||||
|
assert im.load()[0, 0] == (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_load_operations():
|
def test_multiple_load_operations():
|
||||||
with Image.open("Tests/images/gbr.gbr") as im:
|
with Image.open("Tests/images/gbr.gbr") as im:
|
||||||
im.load()
|
im.load()
|
||||||
im.load()
|
im.load()
|
||||||
assert_image_equal_tofile(im, "Tests/images/gbr.png")
|
assert_image_equal_tofile(im, "Tests/images/gbr.png")
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_file():
|
||||||
|
invalid_file = "Tests/images/flower.jpg"
|
||||||
|
|
||||||
|
with pytest.raises(SyntaxError):
|
||||||
|
GbrImagePlugin.GbrImageFile(invalid_file)
|
||||||
|
|
|
@ -28,6 +28,14 @@ def test_sanity():
|
||||||
assert im.format == "ICNS"
|
assert im.format == "ICNS"
|
||||||
|
|
||||||
|
|
||||||
|
def test_load():
|
||||||
|
with Image.open(TEST_FILE) as im:
|
||||||
|
assert im.load()[0, 0] == (0, 0, 0, 0)
|
||||||
|
|
||||||
|
# Test again now that it has already been loaded once
|
||||||
|
assert im.load()[0, 0] == (0, 0, 0, 0)
|
||||||
|
|
||||||
|
|
||||||
def test_save(tmp_path):
|
def test_save(tmp_path):
|
||||||
temp_file = str(tmp_path / "temp.icns")
|
temp_file = str(tmp_path / "temp.icns")
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,11 @@ def test_sanity():
|
||||||
assert im.get_format_mimetype() == "image/x-icon"
|
assert im.get_format_mimetype() == "image/x-icon"
|
||||||
|
|
||||||
|
|
||||||
|
def test_load():
|
||||||
|
with Image.open(TEST_ICO_FILE) as im:
|
||||||
|
assert im.load()[0, 0] == (1, 1, 9, 255)
|
||||||
|
|
||||||
|
|
||||||
def test_mask():
|
def test_mask():
|
||||||
with Image.open("Tests/images/hopper_mask.ico") as im:
|
with Image.open("Tests/images/hopper_mask.ico") as im:
|
||||||
assert_image_equal_tofile(im, "Tests/images/hopper_mask.png")
|
assert_image_equal_tofile(im, "Tests/images/hopper_mask.png")
|
||||||
|
|
|
@ -2,15 +2,11 @@ from PIL import WalImageFile
|
||||||
|
|
||||||
from .helper import assert_image_equal_tofile
|
from .helper import assert_image_equal_tofile
|
||||||
|
|
||||||
|
|
||||||
def test_open():
|
|
||||||
# Arrange
|
|
||||||
TEST_FILE = "Tests/images/hopper.wal"
|
TEST_FILE = "Tests/images/hopper.wal"
|
||||||
|
|
||||||
# Act
|
|
||||||
with WalImageFile.open(TEST_FILE) as im:
|
|
||||||
|
|
||||||
# Assert
|
def test_open():
|
||||||
|
with WalImageFile.open(TEST_FILE) as im:
|
||||||
assert im.format == "WAL"
|
assert im.format == "WAL"
|
||||||
assert im.format_description == "Quake2 Texture"
|
assert im.format_description == "Quake2 Texture"
|
||||||
assert im.mode == "P"
|
assert im.mode == "P"
|
||||||
|
@ -19,3 +15,11 @@ def test_open():
|
||||||
assert isinstance(im, WalImageFile.WalImageFile)
|
assert isinstance(im, WalImageFile.WalImageFile)
|
||||||
|
|
||||||
assert_image_equal_tofile(im, "Tests/images/hopper_wal.png")
|
assert_image_equal_tofile(im, "Tests/images/hopper_wal.png")
|
||||||
|
|
||||||
|
|
||||||
|
def test_load():
|
||||||
|
with WalImageFile.open(TEST_FILE) as im:
|
||||||
|
assert im.load()[0, 0] == 122
|
||||||
|
|
||||||
|
# Test again now that it has already been loaded once
|
||||||
|
assert im.load()[0, 0] == 122
|
||||||
|
|
|
@ -24,6 +24,12 @@ def test_load_raw():
|
||||||
assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref.png", 2.0)
|
assert_image_similar_tofile(im, "Tests/images/drawing_wmf_ref.png", 2.0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_load():
|
||||||
|
with Image.open("Tests/images/drawing.emf") as im:
|
||||||
|
if hasattr(Image.core, "drawwmf"):
|
||||||
|
assert im.load()[0, 0] == (255, 255, 255)
|
||||||
|
|
||||||
|
|
||||||
def test_register_handler(tmp_path):
|
def test_register_handler(tmp_path):
|
||||||
class TestHandler:
|
class TestHandler:
|
||||||
methodCalled = False
|
methodCalled = False
|
||||||
|
|
|
@ -52,9 +52,17 @@ def test_ops():
|
||||||
assert pixel(ImageMath.eval("float(B)**33", images)) == "F 8589934592.0"
|
assert pixel(ImageMath.eval("float(B)**33", images)) == "F 8589934592.0"
|
||||||
|
|
||||||
|
|
||||||
def test_prevent_exec():
|
@pytest.mark.parametrize(
|
||||||
|
"expression",
|
||||||
|
(
|
||||||
|
"exec('pass')",
|
||||||
|
"(lambda: exec('pass'))()",
|
||||||
|
"(lambda: (lambda: exec('pass'))())()",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_prevent_exec(expression):
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
ImageMath.eval("exec('pass')")
|
ImageMath.eval(expression)
|
||||||
|
|
||||||
|
|
||||||
def test_logical():
|
def test_logical():
|
||||||
|
|
|
@ -85,11 +85,13 @@ def test_ipythonviewer():
|
||||||
not on_ci() or is_win32(),
|
not on_ci() or is_win32(),
|
||||||
reason="Only run on CIs; hangs on Windows CIs",
|
reason="Only run on CIs; hangs on Windows CIs",
|
||||||
)
|
)
|
||||||
def test_file_deprecated():
|
def test_file_deprecated(tmp_path):
|
||||||
|
f = str(tmp_path / "temp.jpg")
|
||||||
for viewer in ImageShow._viewers:
|
for viewer in ImageShow._viewers:
|
||||||
|
hopper().save(f)
|
||||||
with pytest.warns(DeprecationWarning):
|
with pytest.warns(DeprecationWarning):
|
||||||
try:
|
try:
|
||||||
viewer.show_file(file="test.jpg")
|
viewer.show_file(file=f)
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
pass
|
pass
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# install libimagequant
|
# install libimagequant
|
||||||
|
|
||||||
archive=libimagequant-2.17.0
|
archive=libimagequant-4.0.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
|
||||||
|
|
||||||
pushd $archive
|
pushd $archive/imagequant-sys
|
||||||
|
|
||||||
make shared
|
cargo install cargo-c
|
||||||
sudo cp libimagequant.so* /usr/lib/
|
cargo cinstall --prefix=/usr --destdir=.
|
||||||
sudo cp libimagequant.h /usr/include/
|
sudo cp usr/lib/libimagequant.so* /usr/lib/
|
||||||
|
sudo cp usr/include/libimagequant.h /usr/include/
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# install raqm
|
# install raqm
|
||||||
|
|
||||||
|
|
||||||
archive=libraqm-0.8.0
|
archive=libraqm-0.9.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
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ Many of Pillow's features require external libraries:
|
||||||
* **littlecms** provides color management
|
* **littlecms** provides color management
|
||||||
|
|
||||||
* Pillow version 2.2.1 and below uses liblcms1, Pillow 2.3.0 and
|
* Pillow version 2.2.1 and below uses liblcms1, Pillow 2.3.0 and
|
||||||
above uses liblcms2. Tested with **1.19** and **2.7-2.12**.
|
above uses liblcms2. Tested with **1.19** and **2.7-2.13**.
|
||||||
|
|
||||||
* **libwebp** provides the WebP format.
|
* **libwebp** provides the WebP format.
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ Many of Pillow's features require external libraries:
|
||||||
|
|
||||||
* **libimagequant** provides improved color quantization
|
* **libimagequant** provides improved color quantization
|
||||||
|
|
||||||
* Pillow has been tested with libimagequant **2.6-2.17.0**
|
* Pillow has been tested with libimagequant **2.6-4.0**
|
||||||
* Libimagequant is licensed GPLv3, which is more restrictive than
|
* Libimagequant is licensed GPLv3, which is more restrictive than
|
||||||
the Pillow license, therefore we will not be distributing binaries
|
the Pillow license, therefore we will not be distributing binaries
|
||||||
with libimagequant support enabled.
|
with libimagequant support enabled.
|
||||||
|
@ -453,8 +453,6 @@ These platforms are built and tested for every change.
|
||||||
+----------------------------------+----------------------------+---------------------+
|
+----------------------------------+----------------------------+---------------------+
|
||||||
| CentOS 7 | 3.9 | x86-64 |
|
| CentOS 7 | 3.9 | x86-64 |
|
||||||
+----------------------------------+----------------------------+---------------------+
|
+----------------------------------+----------------------------+---------------------+
|
||||||
| CentOS 8 | 3.9 | x86-64 |
|
|
||||||
+----------------------------------+----------------------------+---------------------+
|
|
||||||
| CentOS Stream 8 | 3.9 | x86-64 |
|
| CentOS Stream 8 | 3.9 | x86-64 |
|
||||||
+----------------------------------+----------------------------+---------------------+
|
+----------------------------------+----------------------------+---------------------+
|
||||||
| Debian 10 Buster | 3.7 | x86 |
|
| Debian 10 Buster | 3.7 | x86 |
|
||||||
|
@ -532,6 +530,8 @@ These platforms have been reported to work at the versions mentioned.
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+---------------------------+------------------+--------------+
|
||||||
| CentOS 6.3 | 2.7, 3.3 | |x86 |
|
| CentOS 6.3 | 2.7, 3.3 | |x86 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+---------------------------+------------------+--------------+
|
||||||
|
| CentOS 8 | 3.9 | 9.0.0 |x86-64 |
|
||||||
|
+----------------------------------+---------------------------+------------------+--------------+
|
||||||
| Fedora 23 | 2.7, 3.4 | 3.1.0 |x86-64 |
|
| Fedora 23 | 2.7, 3.4 | 3.1.0 |x86-64 |
|
||||||
+----------------------------------+---------------------------+------------------+--------------+
|
+----------------------------------+---------------------------+------------------+--------------+
|
||||||
| Ubuntu Linux 12.04 LTS (Precise) | | 2.6, 3.2, 3.3, 3.4, 3.5 | 3.4.1 |x86,x86-64 |
|
| Ubuntu Linux 12.04 LTS (Precise) | | 2.6, 3.2, 3.3, 3.4, 3.5 | 3.4.1 |x86,x86-64 |
|
||||||
|
|
23
docs/releasenotes/9.0.1.rst
Normal file
23
docs/releasenotes/9.0.1.rst
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
9.0.1
|
||||||
|
-----
|
||||||
|
|
||||||
|
Security
|
||||||
|
========
|
||||||
|
|
||||||
|
This release addresses several security problems.
|
||||||
|
|
||||||
|
:cve:`CVE-2022-24303`: If the path to the temporary directory on Linux or macOS
|
||||||
|
contained a space, this would break removal of the temporary image file after
|
||||||
|
``im.show()`` (and related actions), and potentially remove an unrelated file. This
|
||||||
|
has been present since PIL.
|
||||||
|
|
||||||
|
:cve:`CVE-2022-22817`: While Pillow 9.0 restricted top-level builtins available to
|
||||||
|
:py:meth:`PIL.ImageMath.eval`, it did not prevent builtins available to lambda
|
||||||
|
expressions. These are now also restricted.
|
||||||
|
|
||||||
|
Other Changes
|
||||||
|
=============
|
||||||
|
|
||||||
|
Pillow 9.0 added support for ``xdg-open`` as an image viewer, but there have been
|
||||||
|
reports that the temporary image file was removed too quickly to be loaded into the
|
||||||
|
final application. A delay has been added.
|
|
@ -14,6 +14,7 @@ expected to be backported to earlier versions.
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
9.0.1
|
||||||
9.0.0
|
9.0.0
|
||||||
8.4.0
|
8.4.0
|
||||||
8.3.2
|
8.3.2
|
||||||
|
|
|
@ -329,12 +329,12 @@ class EpsImageFile(ImageFile.ImageFile):
|
||||||
|
|
||||||
def load(self, scale=1, transparency=False):
|
def load(self, scale=1, transparency=False):
|
||||||
# Load EPS via Ghostscript
|
# Load EPS via Ghostscript
|
||||||
if not self.tile:
|
if self.tile:
|
||||||
return
|
|
||||||
self.im = Ghostscript(self.tile, self.size, self.fp, scale, transparency)
|
self.im = Ghostscript(self.tile, self.size, self.fp, scale, transparency)
|
||||||
self.mode = self.im.mode
|
self.mode = self.im.mode
|
||||||
self._size = self.im.size
|
self._size = self.im.size
|
||||||
self.tile = []
|
self.tile = []
|
||||||
|
return Image.Image.load(self)
|
||||||
|
|
||||||
def load_seek(self, *args, **kwargs):
|
def load_seek(self, *args, **kwargs):
|
||||||
# we can't incrementally load, so force ImageFile.parser to
|
# we can't incrementally load, so force ImageFile.parser to
|
||||||
|
|
|
@ -84,12 +84,10 @@ class GbrImageFile(ImageFile.ImageFile):
|
||||||
self._data_size = width * height * color_depth
|
self._data_size = width * height * color_depth
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
if self.im:
|
if not self.im:
|
||||||
# Already loaded
|
|
||||||
return
|
|
||||||
|
|
||||||
self.im = Image.core.new(self.mode, self.size)
|
self.im = Image.core.new(self.mode, self.size)
|
||||||
self.frombytes(self.fp.read(self._data_size))
|
self.frombytes(self.fp.read(self._data_size))
|
||||||
|
return Image.Image.load(self)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -286,21 +286,22 @@ class IcnsImageFile(ImageFile.ImageFile):
|
||||||
self.best_size[1] * self.best_size[2],
|
self.best_size[1] * self.best_size[2],
|
||||||
)
|
)
|
||||||
|
|
||||||
Image.Image.load(self)
|
px = Image.Image.load(self)
|
||||||
if self.im and self.im.size == self.size:
|
if self.im and self.im.size == self.size:
|
||||||
# Already loaded
|
# Already loaded
|
||||||
return
|
return px
|
||||||
self.load_prepare()
|
self.load_prepare()
|
||||||
# This is likely NOT the best way to do it, but whatever.
|
# This is likely NOT the best way to do it, but whatever.
|
||||||
im = self.icns.getimage(self.best_size)
|
im = self.icns.getimage(self.best_size)
|
||||||
|
|
||||||
# If this is a PNG or JPEG 2000, it won't be loaded yet
|
# If this is a PNG or JPEG 2000, it won't be loaded yet
|
||||||
im.load()
|
px = im.load()
|
||||||
|
|
||||||
self.im = im.im
|
self.im = im.im
|
||||||
self.mode = im.mode
|
self.mode = im.mode
|
||||||
self.size = im.size
|
self.size = im.size
|
||||||
self.load_end()
|
|
||||||
|
return px
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
|
|
|
@ -306,7 +306,7 @@ class IcoImageFile(ImageFile.ImageFile):
|
||||||
def load(self):
|
def load(self):
|
||||||
if self.im and self.im.size == self.size:
|
if self.im and self.im.size == self.size:
|
||||||
# Already loaded
|
# Already loaded
|
||||||
return
|
return Image.Image.load(self)
|
||||||
im = self.ico.getimage(self.size)
|
im = self.ico.getimage(self.size)
|
||||||
# if tile is PNG, it won't really be loaded yet
|
# if tile is PNG, it won't really be loaded yet
|
||||||
im.load()
|
im.load()
|
||||||
|
|
|
@ -328,6 +328,7 @@ class StubImageFile(ImageFile):
|
||||||
# become the other object (!)
|
# become the other object (!)
|
||||||
self.__class__ = image.__class__
|
self.__class__ = image.__class__
|
||||||
self.__dict__ = image.__dict__
|
self.__dict__ = image.__dict__
|
||||||
|
return image.load()
|
||||||
|
|
||||||
def _load(self):
|
def _load(self):
|
||||||
"""(Hook) Find actual image loader."""
|
"""(Hook) Find actual image loader."""
|
||||||
|
|
|
@ -240,11 +240,18 @@ def eval(expression, _dict={}, **kw):
|
||||||
if hasattr(v, "im"):
|
if hasattr(v, "im"):
|
||||||
args[k] = _Operand(v)
|
args[k] = _Operand(v)
|
||||||
|
|
||||||
code = compile(expression, "<string>", "eval")
|
compiled_code = compile(expression, "<string>", "eval")
|
||||||
|
|
||||||
|
def scan(code):
|
||||||
|
for const in code.co_consts:
|
||||||
|
if type(const) == type(compiled_code):
|
||||||
|
scan(const)
|
||||||
|
|
||||||
for name in code.co_names:
|
for name in code.co_names:
|
||||||
if name not in args and name != "abs":
|
if name not in args and name != "abs":
|
||||||
raise ValueError(f"'{name}' not allowed")
|
raise ValueError(f"'{name}' not allowed")
|
||||||
|
|
||||||
|
scan(compiled_code)
|
||||||
out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
|
out = builtins.eval(expression, {"__builtins": {"abs": abs}}, args)
|
||||||
try:
|
try:
|
||||||
return out.im
|
return out.im
|
||||||
|
|
|
@ -15,7 +15,6 @@ import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
|
||||||
import warnings
|
import warnings
|
||||||
from shlex import quote
|
from shlex import quote
|
||||||
|
|
||||||
|
@ -127,6 +126,16 @@ class Viewer:
|
||||||
os.system(self.get_command(path, **options))
|
os.system(self.get_command(path, **options))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
def _remove_path_after_delay(self, path):
|
||||||
|
subprocess.Popen(
|
||||||
|
[
|
||||||
|
sys.executable,
|
||||||
|
"-c",
|
||||||
|
"import os, sys, time; time.sleep(20); os.remove(sys.argv[1])",
|
||||||
|
path,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -180,16 +189,8 @@ class MacViewer(Viewer):
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
raise TypeError("Missing required argument: 'path'")
|
||||||
fd, temp_path = tempfile.mkstemp()
|
subprocess.call(["open", "-a", "Preview.app", path])
|
||||||
with os.fdopen(fd, "w") as f:
|
self._remove_path_after_delay(path)
|
||||||
f.write(path)
|
|
||||||
with open(temp_path) as f:
|
|
||||||
subprocess.Popen(
|
|
||||||
["im=$(cat); open -a Preview.app $im; sleep 20; rm -f $im"],
|
|
||||||
shell=True,
|
|
||||||
stdin=f,
|
|
||||||
)
|
|
||||||
os.remove(temp_path)
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
@ -205,6 +206,16 @@ class UnixViewer(Viewer):
|
||||||
command = self.get_command_ex(file, **options)[0]
|
command = self.get_command_ex(file, **options)[0]
|
||||||
return f"({command} {quote(file)}; rm -f {quote(file)})&"
|
return f"({command} {quote(file)}; rm -f {quote(file)})&"
|
||||||
|
|
||||||
|
|
||||||
|
class XDGViewer(UnixViewer):
|
||||||
|
"""
|
||||||
|
The freedesktop.org ``xdg-open`` command.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_command_ex(self, file, **options):
|
||||||
|
command = executable = "xdg-open"
|
||||||
|
return command, executable
|
||||||
|
|
||||||
def show_file(self, path=None, **options):
|
def show_file(self, path=None, **options):
|
||||||
"""
|
"""
|
||||||
Display given file.
|
Display given file.
|
||||||
|
@ -223,28 +234,11 @@ class UnixViewer(Viewer):
|
||||||
path = options.pop("file")
|
path = options.pop("file")
|
||||||
else:
|
else:
|
||||||
raise TypeError("Missing required argument: 'path'")
|
raise TypeError("Missing required argument: 'path'")
|
||||||
fd, temp_path = tempfile.mkstemp()
|
subprocess.Popen(["xdg-open", path])
|
||||||
with os.fdopen(fd, "w") as f:
|
self._remove_path_after_delay(path)
|
||||||
f.write(path)
|
|
||||||
with open(temp_path) as f:
|
|
||||||
command = self.get_command_ex(path, **options)[0]
|
|
||||||
subprocess.Popen(
|
|
||||||
["im=$(cat);" + command + " $im; rm -f $im"], shell=True, stdin=f
|
|
||||||
)
|
|
||||||
os.remove(temp_path)
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class XDGViewer(UnixViewer):
|
|
||||||
"""
|
|
||||||
The freedesktop.org ``xdg-open`` command.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def get_command_ex(self, file, **options):
|
|
||||||
command = executable = "xdg-open"
|
|
||||||
return command, executable
|
|
||||||
|
|
||||||
|
|
||||||
class DisplayViewer(UnixViewer):
|
class DisplayViewer(UnixViewer):
|
||||||
"""
|
"""
|
||||||
The ImageMagick ``display`` command.
|
The ImageMagick ``display`` command.
|
||||||
|
@ -257,6 +251,32 @@ class DisplayViewer(UnixViewer):
|
||||||
command += f" -name {quote(title)}"
|
command += f" -name {quote(title)}"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
|
def show_file(self, path=None, **options):
|
||||||
|
"""
|
||||||
|
Display given file.
|
||||||
|
|
||||||
|
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
||||||
|
and ``path`` should be used instead.
|
||||||
|
"""
|
||||||
|
if path is None:
|
||||||
|
if "file" in options:
|
||||||
|
warnings.warn(
|
||||||
|
"The 'file' argument is deprecated and will be removed in Pillow "
|
||||||
|
"10 (2023-07-01). Use 'path' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
|
path = options.pop("file")
|
||||||
|
else:
|
||||||
|
raise TypeError("Missing required argument: 'path'")
|
||||||
|
args = ["display"]
|
||||||
|
if "title" in options:
|
||||||
|
args += ["-name", options["title"]]
|
||||||
|
args.append(path)
|
||||||
|
|
||||||
|
subprocess.Popen(args)
|
||||||
|
os.remove(path)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class GmDisplayViewer(UnixViewer):
|
class GmDisplayViewer(UnixViewer):
|
||||||
"""The GraphicsMagick ``gm display`` command."""
|
"""The GraphicsMagick ``gm display`` command."""
|
||||||
|
@ -266,6 +286,27 @@ class GmDisplayViewer(UnixViewer):
|
||||||
command = "gm display"
|
command = "gm display"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
|
def show_file(self, path=None, **options):
|
||||||
|
"""
|
||||||
|
Display given file.
|
||||||
|
|
||||||
|
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
||||||
|
and ``path`` should be used instead.
|
||||||
|
"""
|
||||||
|
if path is None:
|
||||||
|
if "file" in options:
|
||||||
|
warnings.warn(
|
||||||
|
"The 'file' argument is deprecated and will be removed in Pillow "
|
||||||
|
"10 (2023-07-01). Use 'path' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
|
path = options.pop("file")
|
||||||
|
else:
|
||||||
|
raise TypeError("Missing required argument: 'path'")
|
||||||
|
subprocess.Popen(["gm", "display", path])
|
||||||
|
os.remove(path)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class EogViewer(UnixViewer):
|
class EogViewer(UnixViewer):
|
||||||
"""The GNOME Image Viewer ``eog`` command."""
|
"""The GNOME Image Viewer ``eog`` command."""
|
||||||
|
@ -275,6 +316,27 @@ class EogViewer(UnixViewer):
|
||||||
command = "eog -n"
|
command = "eog -n"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
|
def show_file(self, path=None, **options):
|
||||||
|
"""
|
||||||
|
Display given file.
|
||||||
|
|
||||||
|
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
||||||
|
and ``path`` should be used instead.
|
||||||
|
"""
|
||||||
|
if path is None:
|
||||||
|
if "file" in options:
|
||||||
|
warnings.warn(
|
||||||
|
"The 'file' argument is deprecated and will be removed in Pillow "
|
||||||
|
"10 (2023-07-01). Use 'path' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
|
path = options.pop("file")
|
||||||
|
else:
|
||||||
|
raise TypeError("Missing required argument: 'path'")
|
||||||
|
subprocess.Popen(["eog", "-n", path])
|
||||||
|
os.remove(path)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
class XVViewer(UnixViewer):
|
class XVViewer(UnixViewer):
|
||||||
"""
|
"""
|
||||||
|
@ -290,6 +352,32 @@ class XVViewer(UnixViewer):
|
||||||
command += f" -name {quote(title)}"
|
command += f" -name {quote(title)}"
|
||||||
return command, executable
|
return command, executable
|
||||||
|
|
||||||
|
def show_file(self, path=None, **options):
|
||||||
|
"""
|
||||||
|
Display given file.
|
||||||
|
|
||||||
|
Before Pillow 9.1.0, the first argument was ``file``. This is now deprecated,
|
||||||
|
and ``path`` should be used instead.
|
||||||
|
"""
|
||||||
|
if path is None:
|
||||||
|
if "file" in options:
|
||||||
|
warnings.warn(
|
||||||
|
"The 'file' argument is deprecated and will be removed in Pillow "
|
||||||
|
"10 (2023-07-01). Use 'path' instead.",
|
||||||
|
DeprecationWarning,
|
||||||
|
)
|
||||||
|
path = options.pop("file")
|
||||||
|
else:
|
||||||
|
raise TypeError("Missing required argument: 'path'")
|
||||||
|
args = ["xv"]
|
||||||
|
if "title" in options:
|
||||||
|
args += ["-name", options["title"]]
|
||||||
|
args.append(path)
|
||||||
|
|
||||||
|
subprocess.Popen(args)
|
||||||
|
os.remove(path)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
if sys.platform not in ("win32", "darwin"): # unixoids
|
if sys.platform not in ("win32", "darwin"): # unixoids
|
||||||
if shutil.which("xdg-open"):
|
if shutil.which("xdg-open"):
|
||||||
|
|
|
@ -51,14 +51,11 @@ class WalImageFile(ImageFile.ImageFile):
|
||||||
self.info["next_name"] = next_name
|
self.info["next_name"] = next_name
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
if self.im:
|
if not self.im:
|
||||||
# Already loaded
|
|
||||||
return
|
|
||||||
|
|
||||||
self.im = Image.core.new(self.mode, self.size)
|
self.im = Image.core.new(self.mode, self.size)
|
||||||
self.frombytes(self.fp.read(self.size[0] * self.size[1]))
|
self.frombytes(self.fp.read(self.size[0] * self.size[1]))
|
||||||
self.putpalette(quake2palette)
|
self.putpalette(quake2palette)
|
||||||
Image.Image.load(self)
|
return Image.Image.load(self)
|
||||||
|
|
||||||
|
|
||||||
def open(filename):
|
def open(filename):
|
||||||
|
|
|
@ -158,7 +158,7 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
(x1 - x0) * self.info["dpi"] // self._inch,
|
(x1 - x0) * self.info["dpi"] // self._inch,
|
||||||
(y1 - y0) * self.info["dpi"] // self._inch,
|
(y1 - y0) * self.info["dpi"] // self._inch,
|
||||||
)
|
)
|
||||||
super().load()
|
return super().load()
|
||||||
|
|
||||||
|
|
||||||
def _save(im, fp, filename):
|
def _save(im, fp, filename):
|
||||||
|
|
2
src/thirdparty/raqm/COPYING
vendored
2
src/thirdparty/raqm/COPYING
vendored
|
@ -1,7 +1,7 @@
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright © 2015 Information Technology Authority (ITA) <foss@ita.gov.om>
|
Copyright © 2015 Information Technology Authority (ITA) <foss@ita.gov.om>
|
||||||
Copyright © 2016-2021 Khaled Hosny <khaled@aliftype.com>
|
Copyright © 2016-2022 Khaled Hosny <khaled@aliftype.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
5
src/thirdparty/raqm/README.md
vendored
5
src/thirdparty/raqm/README.md
vendored
|
@ -68,6 +68,7 @@ Projects using Raqm
|
||||||
3. [FontView](https://github.com/googlei18n/fontview)
|
3. [FontView](https://github.com/googlei18n/fontview)
|
||||||
4. [Pillow](https://github.com/python-pillow)
|
4. [Pillow](https://github.com/python-pillow)
|
||||||
5. [mplcairo](https://github.com/anntzer/mplcairo)
|
5. [mplcairo](https://github.com/anntzer/mplcairo)
|
||||||
|
6. [CEGUI](https://github.com/cegui/cegui)
|
||||||
|
|
||||||
The following projects have patches to support complex text layout using Raqm:
|
The following projects have patches to support complex text layout using Raqm:
|
||||||
|
|
||||||
|
@ -77,8 +78,8 @@ The following projects have patches to support complex text layout using Raqm:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[1]: http://fribidi.org
|
[1]: https://github.com/fribidi/fribidi
|
||||||
[2]: https://github.com/Tehreer/SheenBidi
|
[2]: https://github.com/Tehreer/SheenBidi
|
||||||
[3]: http://harfbuzz.org
|
[3]: https://github.com/harfbuzz/harfbuzz
|
||||||
[4]: https://www.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 8
|
#define RAQM_VERSION_MINOR 9
|
||||||
#define RAQM_VERSION_MICRO 0
|
#define RAQM_VERSION_MICRO 0
|
||||||
|
|
||||||
#define RAQM_VERSION_STRING "0.8.0"
|
#define RAQM_VERSION_STRING "0.9.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) <= \
|
||||||
|
|
469
src/thirdparty/raqm/raqm.c
vendored
469
src/thirdparty/raqm/raqm.c
vendored
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2015 Information Technology Authority (ITA) <foss@ita.gov.om>
|
* Copyright © 2015 Information Technology Authority (ITA) <foss@ita.gov.om>
|
||||||
* Copyright © 2016-2021 Khaled Hosny <khaled@aliftype.com>
|
* Copyright © 2016-2022 Khaled Hosny <khaled@aliftype.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#undef HAVE_CONFIG_H // Workaround for Fribidi 1.0.5 and earlier
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
@ -38,29 +37,11 @@
|
||||||
#else
|
#else
|
||||||
#include "../fribidi-shim/fribidi.h"
|
#include "../fribidi-shim/fribidi.h"
|
||||||
#endif
|
#endif
|
||||||
#if FRIBIDI_MAJOR_VERSION >= 1
|
|
||||||
#define USE_FRIBIDI_EX_API
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <hb.h>
|
#include <hb.h>
|
||||||
#include <hb-ft.h>
|
#include <hb-ft.h>
|
||||||
|
|
||||||
#if FREETYPE_MAJOR > 2 || \
|
|
||||||
FREETYPE_MAJOR == 2 && FREETYPE_MINOR >= 11
|
|
||||||
#define HAVE_FT_GET_TRANSFORM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HB_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
#define HAVE_HB_BUFFER_SET_INVISIBLE_GLYPH
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HB_VERSION_ATLEAST(1, 8, 0)
|
|
||||||
#define HAVE_DECL_HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES 1
|
|
||||||
#else
|
|
||||||
#define HAVE_DECL_HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "raqm.h"
|
#include "raqm.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -190,13 +171,9 @@
|
||||||
typedef FriBidiLevel _raqm_bidi_level_t;
|
typedef FriBidiLevel _raqm_bidi_level_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
RAQM_FLAG_NONE = 0,
|
|
||||||
RAQM_FLAG_UTF8 = 1 << 0
|
|
||||||
} _raqm_flags_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FT_Face ftface;
|
FT_Face ftface;
|
||||||
|
int ftloadflags;
|
||||||
hb_language_t lang;
|
hb_language_t lang;
|
||||||
hb_script_t script;
|
hb_script_t script;
|
||||||
} _raqm_text_info;
|
} _raqm_text_info;
|
||||||
|
@ -209,6 +186,7 @@ struct _raqm {
|
||||||
uint32_t *text;
|
uint32_t *text;
|
||||||
char *text_utf8;
|
char *text_utf8;
|
||||||
size_t text_len;
|
size_t text_len;
|
||||||
|
size_t text_capacity_bytes;
|
||||||
|
|
||||||
_raqm_text_info *text_info;
|
_raqm_text_info *text_info;
|
||||||
|
|
||||||
|
@ -219,17 +197,17 @@ struct _raqm {
|
||||||
size_t features_len;
|
size_t features_len;
|
||||||
|
|
||||||
raqm_run_t *runs;
|
raqm_run_t *runs;
|
||||||
|
raqm_run_t *runs_pool;
|
||||||
|
|
||||||
raqm_glyph_t *glyphs;
|
raqm_glyph_t *glyphs;
|
||||||
|
size_t glyphs_capacity;
|
||||||
|
|
||||||
_raqm_flags_t flags;
|
|
||||||
|
|
||||||
int ft_loadflags;
|
|
||||||
int invisible_glyph;
|
int invisible_glyph;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _raqm_run {
|
struct _raqm_run {
|
||||||
int pos;
|
uint32_t pos;
|
||||||
int len;
|
uint32_t len;
|
||||||
|
|
||||||
hb_direction_t direction;
|
hb_direction_t direction;
|
||||||
hb_script_t script;
|
hb_script_t script;
|
||||||
|
@ -243,31 +221,21 @@ static uint32_t
|
||||||
_raqm_u8_to_u32_index (raqm_t *rq,
|
_raqm_u8_to_u32_index (raqm_t *rq,
|
||||||
uint32_t index);
|
uint32_t index);
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
_raqm_init_text_info (raqm_t *rq)
|
_raqm_init_text_info (raqm_t *rq)
|
||||||
{
|
{
|
||||||
hb_language_t default_lang;
|
hb_language_t default_lang = hb_language_get_default ();
|
||||||
|
|
||||||
if (rq->text_info)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
rq->text_info = malloc (sizeof (_raqm_text_info) * rq->text_len);
|
|
||||||
if (!rq->text_info)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default_lang = hb_language_get_default ();
|
|
||||||
for (size_t i = 0; i < rq->text_len; i++)
|
for (size_t i = 0; i < rq->text_len; i++)
|
||||||
{
|
{
|
||||||
rq->text_info[i].ftface = NULL;
|
rq->text_info[i].ftface = NULL;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_raqm_free_text_info (raqm_t *rq)
|
_raqm_release_text_info (raqm_t *rq)
|
||||||
{
|
{
|
||||||
if (!rq->text_info)
|
if (!rq->text_info)
|
||||||
return;
|
return;
|
||||||
|
@ -277,9 +245,6 @@ _raqm_free_text_info (raqm_t *rq)
|
||||||
if (rq->text_info[i].ftface)
|
if (rq->text_info[i].ftface)
|
||||||
FT_Done_Face (rq->text_info[i].ftface);
|
FT_Done_Face (rq->text_info[i].ftface);
|
||||||
}
|
}
|
||||||
|
|
||||||
free (rq->text_info);
|
|
||||||
rq->text_info = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -289,6 +254,9 @@ _raqm_compare_text_info (_raqm_text_info a,
|
||||||
if (a.ftface != b.ftface)
|
if (a.ftface != b.ftface)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (a.ftloadflags != b.ftloadflags)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (a.lang != b.lang)
|
if (a.lang != b.lang)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -298,6 +266,88 @@ _raqm_compare_text_info (_raqm_text_info a,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_raqm_free_text(raqm_t* rq)
|
||||||
|
{
|
||||||
|
free (rq->text);
|
||||||
|
rq->text = NULL;
|
||||||
|
rq->text_info = NULL;
|
||||||
|
rq->text_utf8 = NULL;
|
||||||
|
rq->text_len = 0;
|
||||||
|
rq->text_capacity_bytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_raqm_alloc_text(raqm_t *rq,
|
||||||
|
size_t len,
|
||||||
|
bool need_utf8)
|
||||||
|
{
|
||||||
|
/* Allocate contiguous memory block for texts and text_info */
|
||||||
|
size_t mem_size = (sizeof (uint32_t) + sizeof (_raqm_text_info)) * len;
|
||||||
|
if (need_utf8)
|
||||||
|
mem_size += sizeof (char) * len;
|
||||||
|
|
||||||
|
if (mem_size > rq->text_capacity_bytes)
|
||||||
|
{
|
||||||
|
void* new_mem = realloc (rq->text, mem_size);
|
||||||
|
if (!new_mem)
|
||||||
|
{
|
||||||
|
_raqm_free_text (rq);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rq->text_capacity_bytes = mem_size;
|
||||||
|
rq->text = new_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
rq->text_info = (_raqm_text_info*)(rq->text + len);
|
||||||
|
rq->text_utf8 = need_utf8 ? (char*)(rq->text_info + len) : NULL;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static raqm_run_t*
|
||||||
|
_raqm_alloc_run (raqm_t *rq)
|
||||||
|
{
|
||||||
|
raqm_run_t *run = rq->runs_pool;
|
||||||
|
if (run)
|
||||||
|
{
|
||||||
|
rq->runs_pool = run->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
run = malloc (sizeof (raqm_run_t));
|
||||||
|
run->font = NULL;
|
||||||
|
run->buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
run->pos = 0;
|
||||||
|
run->len = 0;
|
||||||
|
run->direction = HB_DIRECTION_INVALID;
|
||||||
|
run->script = HB_SCRIPT_INVALID;
|
||||||
|
run->next = NULL;
|
||||||
|
|
||||||
|
return run;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_raqm_free_runs (raqm_run_t *runs)
|
||||||
|
{
|
||||||
|
while (runs)
|
||||||
|
{
|
||||||
|
raqm_run_t *run = runs;
|
||||||
|
runs = runs->next;
|
||||||
|
|
||||||
|
if (run->buffer)
|
||||||
|
hb_buffer_destroy (run->buffer);
|
||||||
|
|
||||||
|
if (run->font)
|
||||||
|
hb_font_destroy (run->font);
|
||||||
|
|
||||||
|
free (run);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* raqm_create:
|
* raqm_create:
|
||||||
*
|
*
|
||||||
|
@ -322,26 +372,26 @@ raqm_create (void)
|
||||||
|
|
||||||
rq->ref_count = 1;
|
rq->ref_count = 1;
|
||||||
|
|
||||||
rq->text = NULL;
|
|
||||||
rq->text_utf8 = NULL;
|
|
||||||
rq->text_len = 0;
|
|
||||||
|
|
||||||
rq->text_info = NULL;
|
|
||||||
|
|
||||||
rq->base_dir = RAQM_DIRECTION_DEFAULT;
|
rq->base_dir = RAQM_DIRECTION_DEFAULT;
|
||||||
rq->resolved_dir = RAQM_DIRECTION_DEFAULT;
|
rq->resolved_dir = RAQM_DIRECTION_DEFAULT;
|
||||||
|
|
||||||
rq->features = NULL;
|
rq->features = NULL;
|
||||||
rq->features_len = 0;
|
rq->features_len = 0;
|
||||||
|
|
||||||
rq->runs = NULL;
|
|
||||||
rq->glyphs = NULL;
|
|
||||||
|
|
||||||
rq->flags = RAQM_FLAG_NONE;
|
|
||||||
|
|
||||||
rq->ft_loadflags = -1;
|
|
||||||
rq->invisible_glyph = 0;
|
rq->invisible_glyph = 0;
|
||||||
|
|
||||||
|
rq->text = NULL;
|
||||||
|
rq->text_utf8 = NULL;
|
||||||
|
rq->text_info = NULL;
|
||||||
|
rq->text_capacity_bytes = 0;
|
||||||
|
rq->text_len = 0;
|
||||||
|
|
||||||
|
rq->runs = NULL;
|
||||||
|
rq->runs_pool = NULL;
|
||||||
|
|
||||||
|
rq->glyphs = NULL;
|
||||||
|
rq->glyphs_capacity = 0;
|
||||||
|
|
||||||
return rq;
|
return rq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,28 +416,13 @@ raqm_reference (raqm_t *rq)
|
||||||
return rq;
|
return rq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
_raqm_free_runs (raqm_t *rq)
|
|
||||||
{
|
|
||||||
raqm_run_t *runs = rq->runs;
|
|
||||||
while (runs)
|
|
||||||
{
|
|
||||||
raqm_run_t *run = runs;
|
|
||||||
runs = runs->next;
|
|
||||||
|
|
||||||
hb_buffer_destroy (run->buffer);
|
|
||||||
hb_font_destroy (run->font);
|
|
||||||
free (run);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* raqm_destroy:
|
* raqm_destroy:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
*
|
*
|
||||||
* Decreases the reference count on @rq by one. If the result is zero, then @rq
|
* Decreases the reference count on @rq by one. If the result is zero, then @rq
|
||||||
* and all associated resources are freed.
|
* and all associated resources are freed.
|
||||||
* See cairo_reference().
|
* See raqm_reference().
|
||||||
*
|
*
|
||||||
* Since: 0.1
|
* Since: 0.1
|
||||||
*/
|
*/
|
||||||
|
@ -397,14 +432,60 @@ raqm_destroy (raqm_t *rq)
|
||||||
if (!rq || --rq->ref_count != 0)
|
if (!rq || --rq->ref_count != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
free (rq->text);
|
_raqm_release_text_info (rq);
|
||||||
free (rq->text_utf8);
|
_raqm_free_text (rq);
|
||||||
_raqm_free_text_info (rq);
|
_raqm_free_runs (rq->runs);
|
||||||
_raqm_free_runs (rq);
|
_raqm_free_runs (rq->runs_pool);
|
||||||
free (rq->glyphs);
|
free (rq->glyphs);
|
||||||
|
free (rq->features);
|
||||||
free (rq);
|
free (rq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* raqm_clear_contents:
|
||||||
|
* @rq: a #raqm_t.
|
||||||
|
*
|
||||||
|
* Clears internal state of previously used raqm_t object, making it ready
|
||||||
|
* for reuse and keeping some of allocated memory to increase performance.
|
||||||
|
*
|
||||||
|
* Since: 0.9
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
raqm_clear_contents (raqm_t *rq)
|
||||||
|
{
|
||||||
|
if (!rq)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_raqm_release_text_info (rq);
|
||||||
|
|
||||||
|
/* Return allocated runs to the pool, keep hb buffers for reuse */
|
||||||
|
raqm_run_t *run = rq->runs;
|
||||||
|
while (run)
|
||||||
|
{
|
||||||
|
if (run->buffer)
|
||||||
|
hb_buffer_reset (run->buffer);
|
||||||
|
|
||||||
|
if (run->font)
|
||||||
|
{
|
||||||
|
hb_font_destroy (run->font);
|
||||||
|
run->font = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!run->next)
|
||||||
|
{
|
||||||
|
run->next = rq->runs_pool;
|
||||||
|
rq->runs_pool = rq->runs;
|
||||||
|
rq->runs = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
run = run->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
rq->text_len = 0;
|
||||||
|
rq->resolved_dir = RAQM_DIRECTION_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* raqm_set_text:
|
* raqm_set_text:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
|
@ -429,23 +510,20 @@ raqm_set_text (raqm_t *rq,
|
||||||
if (!rq || !text)
|
if (!rq || !text)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rq->text_len = len;
|
/* Call raqm_clear_contents to reuse this raqm_t */
|
||||||
|
if (rq->text_len)
|
||||||
|
return false;
|
||||||
|
|
||||||
/* Empty string, don’t fail but do nothing */
|
/* Empty string, don’t fail but do nothing */
|
||||||
if (!len)
|
if (!len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
free (rq->text);
|
if (!_raqm_alloc_text(rq, len, false))
|
||||||
|
|
||||||
rq->text = malloc (sizeof (uint32_t) * rq->text_len);
|
|
||||||
if (!rq->text)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_raqm_free_text_info (rq);
|
rq->text_len = len;
|
||||||
if (!_raqm_init_text_info (rq))
|
memcpy (rq->text, text, sizeof (uint32_t) * len);
|
||||||
return false;
|
_raqm_init_text_info (rq);
|
||||||
|
|
||||||
memcpy (rq->text, text, sizeof (uint32_t) * rq->text_len);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -515,37 +593,25 @@ raqm_set_text_utf8 (raqm_t *rq,
|
||||||
const char *text,
|
const char *text,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
uint32_t *unicode;
|
|
||||||
size_t ulen;
|
|
||||||
bool ok;
|
|
||||||
|
|
||||||
if (!rq || !text)
|
if (!rq || !text)
|
||||||
return false;
|
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 */
|
/* Empty string, don’t fail but do nothing */
|
||||||
if (!len)
|
if (!len)
|
||||||
{
|
|
||||||
rq->text_len = len;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
rq->flags |= RAQM_FLAG_UTF8;
|
if (!_raqm_alloc_text(rq, len, true))
|
||||||
|
|
||||||
rq->text_utf8 = malloc (sizeof (char) * len);
|
|
||||||
if (!rq->text_utf8)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
unicode = malloc (sizeof (uint32_t) * len);
|
|
||||||
if (!unicode)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
rq->text_len = _raqm_u8_to_u32 (text, len, rq->text);
|
||||||
memcpy (rq->text_utf8, text, sizeof (char) * len);
|
memcpy (rq->text_utf8, text, sizeof (char) * len);
|
||||||
|
_raqm_init_text_info (rq);
|
||||||
|
|
||||||
ulen = _raqm_u8_to_u32 (text, len, unicode);
|
return true;
|
||||||
ok = raqm_set_text (rq, unicode, ulen);
|
|
||||||
|
|
||||||
free (unicode);
|
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -561,7 +627,7 @@ raqm_set_text_utf8 (raqm_t *rq,
|
||||||
*
|
*
|
||||||
* The default is #RAQM_DIRECTION_DEFAULT, which determines the paragraph
|
* The default is #RAQM_DIRECTION_DEFAULT, which determines the paragraph
|
||||||
* direction based on the first character with strong bidi type (see [rule
|
* direction based on the first character with strong bidi type (see [rule
|
||||||
* P2](http://unicode.org/reports/tr9/#P2) in Unicode Bidirectional Algorithm),
|
* P2](https://unicode.org/reports/tr9/#P2) in Unicode Bidirectional Algorithm),
|
||||||
* which can be good enough for many cases but has problems when a mainly
|
* which can be good enough for many cases but has problems when a mainly
|
||||||
* right-to-left paragraph starts with a left-to-right character and vice versa
|
* right-to-left paragraph starts with a left-to-right character and vice versa
|
||||||
* as the detected paragraph direction will be the wrong one, or when text does
|
* as the detected paragraph direction will be the wrong one, or when text does
|
||||||
|
@ -629,7 +695,7 @@ raqm_set_language (raqm_t *rq,
|
||||||
if (!rq->text_len)
|
if (!rq->text_len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (rq->flags & RAQM_FLAG_UTF8)
|
if (rq->text_utf8)
|
||||||
{
|
{
|
||||||
start = _raqm_u8_to_u32_index (rq, start);
|
start = _raqm_u8_to_u32_index (rq, start);
|
||||||
end = _raqm_u8_to_u32_index (rq, end);
|
end = _raqm_u8_to_u32_index (rq, end);
|
||||||
|
@ -686,13 +752,14 @@ 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)
|
||||||
{
|
{
|
||||||
rq->features_len++;
|
void* new_features = realloc (rq->features,
|
||||||
rq->features = realloc (rq->features,
|
sizeof (hb_feature_t) * (rq->features_len + 1));
|
||||||
sizeof (hb_feature_t) * (rq->features_len));
|
if (!new_features)
|
||||||
if (!rq->features)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rq->features[rq->features_len - 1] = fea;
|
rq->features = new_features;
|
||||||
|
rq->features[rq->features_len] = fea;
|
||||||
|
rq->features_len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
|
@ -700,12 +767,13 @@ raqm_add_font_feature (raqm_t *rq,
|
||||||
|
|
||||||
static hb_font_t *
|
static hb_font_t *
|
||||||
_raqm_create_hb_font (raqm_t *rq,
|
_raqm_create_hb_font (raqm_t *rq,
|
||||||
FT_Face face)
|
FT_Face face,
|
||||||
|
int loadflags)
|
||||||
{
|
{
|
||||||
hb_font_t *font = hb_ft_font_create_referenced (face);
|
hb_font_t *font = hb_ft_font_create_referenced (face);
|
||||||
|
|
||||||
if (rq->ft_loadflags >= 0)
|
if (loadflags >= 0)
|
||||||
hb_ft_font_set_load_flags (font, rq->ft_loadflags);
|
hb_ft_font_set_load_flags (font, loadflags);
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
|
@ -796,7 +864,7 @@ raqm_set_freetype_face_range (raqm_t *rq,
|
||||||
if (!rq->text_len)
|
if (!rq->text_len)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (rq->flags & RAQM_FLAG_UTF8)
|
if (rq->text_utf8)
|
||||||
{
|
{
|
||||||
start = _raqm_u8_to_u32_index (rq, start);
|
start = _raqm_u8_to_u32_index (rq, start);
|
||||||
end = _raqm_u8_to_u32_index (rq, end);
|
end = _raqm_u8_to_u32_index (rq, end);
|
||||||
|
@ -805,6 +873,30 @@ raqm_set_freetype_face_range (raqm_t *rq,
|
||||||
return _raqm_set_freetype_face (rq, face, start, end);
|
return _raqm_set_freetype_face (rq, face, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_raqm_set_freetype_load_flags (raqm_t *rq,
|
||||||
|
int flags,
|
||||||
|
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++)
|
||||||
|
rq->text_info[i].ftloadflags = flags;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* raqm_set_freetype_load_flags:
|
* raqm_set_freetype_load_flags:
|
||||||
* @rq: a #raqm_t.
|
* @rq: a #raqm_t.
|
||||||
|
@ -825,12 +917,57 @@ bool
|
||||||
raqm_set_freetype_load_flags (raqm_t *rq,
|
raqm_set_freetype_load_flags (raqm_t *rq,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
|
return _raqm_set_freetype_load_flags(rq, flags, 0, rq->text_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* raqm_set_freetype_load_flags_range:
|
||||||
|
* @rq: a #raqm_t.
|
||||||
|
* @flags: FreeType load flags.
|
||||||
|
* @start: index of first character that should use @flags.
|
||||||
|
* @len: number of characters using @flags.
|
||||||
|
*
|
||||||
|
* Sets the load flags passed to FreeType when loading glyphs for @len-number
|
||||||
|
* of characters staring at @start. Flags should be the same as used by the
|
||||||
|
* client when rendering corresponding FreeType glyphs. The @start and @len
|
||||||
|
* are input string array indices (i.e. counting bytes in UTF-8 and scaler
|
||||||
|
* values in UTF-32).
|
||||||
|
*
|
||||||
|
* This method can be used repeatedly to set different flags for different
|
||||||
|
* parts of the text. It is the responsibility of the client to make sure that
|
||||||
|
* flag ranges cover the whole text.
|
||||||
|
*
|
||||||
|
* This requires version of HarfBuzz that has hb_ft_font_set_load_flags(), for
|
||||||
|
* older version the flags will be ignored.
|
||||||
|
*
|
||||||
|
* See also raqm_set_freetype_load_flags().
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* %true if no errors happened, %false otherwise.
|
||||||
|
*
|
||||||
|
* Since: 0.9
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
raqm_set_freetype_load_flags_range (raqm_t *rq,
|
||||||
|
int flags,
|
||||||
|
size_t start,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
size_t end = start + len;
|
||||||
|
|
||||||
if (!rq)
|
if (!rq)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rq->ft_loadflags = flags;
|
if (!rq->text_len)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (rq->text_utf8)
|
||||||
|
{
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -841,17 +978,10 @@ raqm_set_freetype_load_flags (raqm_t *rq,
|
||||||
* Sets the glyph id to be used for invisible glyhphs.
|
* Sets the glyph id to be used for invisible glyhphs.
|
||||||
*
|
*
|
||||||
* If @gid is negative, invisible glyphs will be suppressed from the output.
|
* If @gid is negative, invisible glyphs will be suppressed from the output.
|
||||||
* This requires HarfBuzz 1.8.0 or later. If raqm is used with an earlier
|
|
||||||
* HarfBuzz version, the return value will be %false and the shaping behavior
|
|
||||||
* does not change.
|
|
||||||
*
|
*
|
||||||
* If @gid is zero, invisible glyphs will be rendered as space.
|
* If @gid is zero, invisible glyphs will be rendered as space.
|
||||||
* This works on all versions of HarfBuzz.
|
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
* This requires a version of HarfBuzz that has
|
|
||||||
* hb_buffer_set_invisible_glyph(). For older versions, the return value
|
|
||||||
* will be %false and the shaping behavior does not change.
|
|
||||||
*
|
*
|
||||||
* Return value:
|
* Return value:
|
||||||
* %true if no errors happened, %false otherwise.
|
* %true if no errors happened, %false otherwise.
|
||||||
|
@ -865,17 +995,6 @@ raqm_set_invisible_glyph (raqm_t *rq,
|
||||||
if (!rq)
|
if (!rq)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#ifndef HAVE_HB_BUFFER_SET_INVISIBLE_GLYPH
|
|
||||||
if (gid > 0)
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(HAVE_DECL_HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) || \
|
|
||||||
!HAVE_DECL_HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES
|
|
||||||
if (gid < 0)
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rq->invisible_glyph = gid;
|
rq->invisible_glyph = gid;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -961,18 +1080,21 @@ raqm_get_glyphs (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)
|
||||||
count += hb_buffer_get_length (run->buffer);
|
count += hb_buffer_get_length (run->buffer);
|
||||||
|
|
||||||
*length = count;
|
if (count > rq->glyphs_capacity)
|
||||||
|
{
|
||||||
if (rq->glyphs)
|
void* new_mem = realloc (rq->glyphs, sizeof (raqm_glyph_t) * count);
|
||||||
free (rq->glyphs);
|
if (!new_mem)
|
||||||
|
|
||||||
rq->glyphs = malloc (sizeof (raqm_glyph_t) * count);
|
|
||||||
if (!rq->glyphs)
|
|
||||||
{
|
{
|
||||||
*length = 0;
|
*length = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rq->glyphs = new_mem;
|
||||||
|
rq->glyphs_capacity = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
*length = count;
|
||||||
|
|
||||||
RAQM_TEST ("Glyph information:\n");
|
RAQM_TEST ("Glyph information:\n");
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -1005,7 +1127,7 @@ raqm_get_glyphs (raqm_t *rq,
|
||||||
count += len;
|
count += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rq->flags & RAQM_FLAG_UTF8)
|
if (rq->text_utf8)
|
||||||
{
|
{
|
||||||
#ifdef RAQM_TESTING
|
#ifdef RAQM_TESTING
|
||||||
RAQM_TEST ("\nUTF-32 clusters:");
|
RAQM_TEST ("\nUTF-32 clusters:");
|
||||||
|
@ -1276,24 +1398,14 @@ _raqm_bidi_itemize (raqm_t *rq, size_t *run_count)
|
||||||
FriBidiCharType *types;
|
FriBidiCharType *types;
|
||||||
_raqm_bidi_level_t *levels;
|
_raqm_bidi_level_t *levels;
|
||||||
int max_level = 0;
|
int max_level = 0;
|
||||||
#ifdef USE_FRIBIDI_EX_API
|
|
||||||
FriBidiBracketType *btypes;
|
FriBidiBracketType *btypes;
|
||||||
#endif
|
|
||||||
|
|
||||||
types = calloc (rq->text_len, sizeof (FriBidiCharType));
|
types = calloc (rq->text_len, sizeof (FriBidiCharType));
|
||||||
#ifdef USE_FRIBIDI_EX_API
|
|
||||||
btypes = calloc (rq->text_len, sizeof (FriBidiBracketType));
|
btypes = calloc (rq->text_len, sizeof (FriBidiBracketType));
|
||||||
#endif
|
|
||||||
levels = calloc (rq->text_len, sizeof (_raqm_bidi_level_t));
|
levels = calloc (rq->text_len, sizeof (_raqm_bidi_level_t));
|
||||||
|
|
||||||
if (!types || !levels
|
if (!types || !levels || !btypes)
|
||||||
#ifdef USE_FRIBIDI_EX_API
|
|
||||||
|| !btypes
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
|
|
||||||
if (rq->base_dir == RAQM_DIRECTION_RTL)
|
if (rq->base_dir == RAQM_DIRECTION_RTL)
|
||||||
par_type = FRIBIDI_PAR_RTL;
|
par_type = FRIBIDI_PAR_RTL;
|
||||||
|
@ -1301,15 +1413,10 @@ _raqm_bidi_itemize (raqm_t *rq, size_t *run_count)
|
||||||
par_type = FRIBIDI_PAR_LTR;
|
par_type = FRIBIDI_PAR_LTR;
|
||||||
|
|
||||||
fribidi_get_bidi_types (rq->text, rq->text_len, types);
|
fribidi_get_bidi_types (rq->text, rq->text_len, types);
|
||||||
#ifdef USE_FRIBIDI_EX_API
|
|
||||||
fribidi_get_bracket_types (rq->text, rq->text_len, types, btypes);
|
fribidi_get_bracket_types (rq->text, rq->text_len, types, btypes);
|
||||||
max_level = fribidi_get_par_embedding_levels_ex (types, btypes,
|
max_level = fribidi_get_par_embedding_levels_ex (types, btypes,
|
||||||
rq->text_len, &par_type,
|
rq->text_len, &par_type,
|
||||||
levels);
|
levels);
|
||||||
#else
|
|
||||||
max_level = fribidi_get_par_embedding_levels (types, rq->text_len,
|
|
||||||
&par_type, levels);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (par_type == FRIBIDI_PAR_LTR)
|
if (par_type == FRIBIDI_PAR_LTR)
|
||||||
rq->resolved_dir = RAQM_DIRECTION_LTR;
|
rq->resolved_dir = RAQM_DIRECTION_LTR;
|
||||||
|
@ -1325,9 +1432,7 @@ _raqm_bidi_itemize (raqm_t *rq, size_t *run_count)
|
||||||
done:
|
done:
|
||||||
free (types);
|
free (types);
|
||||||
free (levels);
|
free (levels);
|
||||||
#ifdef USE_FRIBIDI_EX_API
|
|
||||||
free (btypes);
|
free (btypes);
|
||||||
#endif
|
|
||||||
|
|
||||||
return runs;
|
return runs;
|
||||||
}
|
}
|
||||||
|
@ -1403,7 +1508,7 @@ _raqm_itemize (raqm_t *rq)
|
||||||
last = NULL;
|
last = NULL;
|
||||||
for (size_t i = 0; i < run_count; i++)
|
for (size_t i = 0; i < run_count; i++)
|
||||||
{
|
{
|
||||||
raqm_run_t *run = calloc (1, sizeof (raqm_run_t));
|
raqm_run_t *run = _raqm_alloc_run (rq);
|
||||||
if (!run)
|
if (!run)
|
||||||
{
|
{
|
||||||
ok = false;
|
ok = false;
|
||||||
|
@ -1422,13 +1527,14 @@ _raqm_itemize (raqm_t *rq)
|
||||||
{
|
{
|
||||||
run->pos = runs[i].pos + runs[i].len - 1;
|
run->pos = runs[i].pos + runs[i].len - 1;
|
||||||
run->script = rq->text_info[run->pos].script;
|
run->script = rq->text_info[run->pos].script;
|
||||||
run->font = _raqm_create_hb_font (rq, rq->text_info[run->pos].ftface);
|
run->font = _raqm_create_hb_font (rq, rq->text_info[run->pos].ftface,
|
||||||
|
rq->text_info[run->pos].ftloadflags);
|
||||||
for (int j = runs[i].len - 1; j >= 0; j--)
|
for (int j = runs[i].len - 1; j >= 0; j--)
|
||||||
{
|
{
|
||||||
_raqm_text_info info = rq->text_info[runs[i].pos + j];
|
_raqm_text_info info = rq->text_info[runs[i].pos + j];
|
||||||
if (!_raqm_compare_text_info (rq->text_info[run->pos], info))
|
if (!_raqm_compare_text_info (rq->text_info[run->pos], info))
|
||||||
{
|
{
|
||||||
raqm_run_t *newrun = calloc (1, sizeof (raqm_run_t));
|
raqm_run_t *newrun = _raqm_alloc_run (rq);
|
||||||
if (!newrun)
|
if (!newrun)
|
||||||
{
|
{
|
||||||
ok = false;
|
ok = false;
|
||||||
|
@ -1438,7 +1544,8 @@ _raqm_itemize (raqm_t *rq)
|
||||||
newrun->len = 1;
|
newrun->len = 1;
|
||||||
newrun->direction = _raqm_hb_dir (rq, runs[i].level);
|
newrun->direction = _raqm_hb_dir (rq, runs[i].level);
|
||||||
newrun->script = info.script;
|
newrun->script = info.script;
|
||||||
newrun->font = _raqm_create_hb_font (rq, info.ftface);
|
newrun->font = _raqm_create_hb_font (rq, info.ftface,
|
||||||
|
info.ftloadflags);
|
||||||
run->next = newrun;
|
run->next = newrun;
|
||||||
run = newrun;
|
run = newrun;
|
||||||
}
|
}
|
||||||
|
@ -1453,13 +1560,14 @@ _raqm_itemize (raqm_t *rq)
|
||||||
{
|
{
|
||||||
run->pos = runs[i].pos;
|
run->pos = runs[i].pos;
|
||||||
run->script = rq->text_info[run->pos].script;
|
run->script = rq->text_info[run->pos].script;
|
||||||
run->font = _raqm_create_hb_font (rq, rq->text_info[run->pos].ftface);
|
run->font = _raqm_create_hb_font (rq, rq->text_info[run->pos].ftface,
|
||||||
|
rq->text_info[run->pos].ftloadflags);
|
||||||
for (size_t j = 0; j < runs[i].len; j++)
|
for (size_t j = 0; j < runs[i].len; j++)
|
||||||
{
|
{
|
||||||
_raqm_text_info info = rq->text_info[runs[i].pos + j];
|
_raqm_text_info info = rq->text_info[runs[i].pos + j];
|
||||||
if (!_raqm_compare_text_info (rq->text_info[run->pos], info))
|
if (!_raqm_compare_text_info (rq->text_info[run->pos], info))
|
||||||
{
|
{
|
||||||
raqm_run_t *newrun = calloc (1, sizeof (raqm_run_t));
|
raqm_run_t *newrun = _raqm_alloc_run (rq);
|
||||||
if (!newrun)
|
if (!newrun)
|
||||||
{
|
{
|
||||||
ok = false;
|
ok = false;
|
||||||
|
@ -1469,7 +1577,8 @@ _raqm_itemize (raqm_t *rq)
|
||||||
newrun->len = 1;
|
newrun->len = 1;
|
||||||
newrun->direction = _raqm_hb_dir (rq, runs[i].level);
|
newrun->direction = _raqm_hb_dir (rq, runs[i].level);
|
||||||
newrun->script = info.script;
|
newrun->script = info.script;
|
||||||
newrun->font = _raqm_create_hb_font (rq, info.ftface);
|
newrun->font = _raqm_create_hb_font (rq, info.ftface,
|
||||||
|
info.ftloadflags);
|
||||||
run->next = newrun;
|
run->next = newrun;
|
||||||
run = newrun;
|
run = newrun;
|
||||||
}
|
}
|
||||||
|
@ -1758,7 +1867,6 @@ _raqm_resolve_scripts (raqm_t *rq)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_FT_GET_TRANSFORM
|
|
||||||
static void
|
static void
|
||||||
_raqm_ft_transform (int *x,
|
_raqm_ft_transform (int *x,
|
||||||
int *y,
|
int *y,
|
||||||
|
@ -1773,21 +1881,18 @@ _raqm_ft_transform (int *x,
|
||||||
*x = vector.x;
|
*x = vector.x;
|
||||||
*y = vector.y;
|
*y = vector.y;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_raqm_shape (raqm_t *rq)
|
_raqm_shape (raqm_t *rq)
|
||||||
{
|
{
|
||||||
hb_buffer_flags_t hb_buffer_flags = HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT;
|
hb_buffer_flags_t hb_buffer_flags = HB_BUFFER_FLAG_BOT | HB_BUFFER_FLAG_EOT;
|
||||||
|
|
||||||
#if defined(HAVE_DECL_HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES) && \
|
|
||||||
HAVE_DECL_HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES
|
|
||||||
if (rq->invisible_glyph < 0)
|
if (rq->invisible_glyph < 0)
|
||||||
hb_buffer_flags |= HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES;
|
hb_buffer_flags |= HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES;
|
||||||
#endif
|
|
||||||
|
|
||||||
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->buffer)
|
||||||
run->buffer = hb_buffer_create ();
|
run->buffer = hb_buffer_create ();
|
||||||
|
|
||||||
hb_buffer_add_utf32 (run->buffer, rq->text, rq->text_len,
|
hb_buffer_add_utf32 (run->buffer, rq->text, rq->text_len,
|
||||||
|
@ -1797,15 +1902,12 @@ _raqm_shape (raqm_t *rq)
|
||||||
hb_buffer_set_direction (run->buffer, run->direction);
|
hb_buffer_set_direction (run->buffer, run->direction);
|
||||||
hb_buffer_set_flags (run->buffer, hb_buffer_flags);
|
hb_buffer_set_flags (run->buffer, hb_buffer_flags);
|
||||||
|
|
||||||
#ifdef HAVE_HB_BUFFER_SET_INVISIBLE_GLYPH
|
|
||||||
if (rq->invisible_glyph > 0)
|
if (rq->invisible_glyph > 0)
|
||||||
hb_buffer_set_invisible_glyph (run->buffer, rq->invisible_glyph);
|
hb_buffer_set_invisible_glyph (run->buffer, rq->invisible_glyph);
|
||||||
#endif
|
|
||||||
|
|
||||||
hb_shape_full (run->font, run->buffer, rq->features, rq->features_len,
|
hb_shape_full (run->font, run->buffer, rq->features, rq->features_len,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
#ifdef HAVE_FT_GET_TRANSFORM
|
|
||||||
{
|
{
|
||||||
FT_Matrix matrix;
|
FT_Matrix matrix;
|
||||||
hb_glyph_position_t *pos;
|
hb_glyph_position_t *pos;
|
||||||
|
@ -1819,7 +1921,6 @@ _raqm_shape (raqm_t *rq)
|
||||||
_raqm_ft_transform (&pos[i].x_offset, &pos[i].y_offset, matrix);
|
_raqm_ft_transform (&pos[i].x_offset, &pos[i].y_offset, matrix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1917,7 +2018,7 @@ raqm_index_to_position (raqm_t *rq,
|
||||||
if (rq == NULL)
|
if (rq == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (rq->flags & RAQM_FLAG_UTF8)
|
if (rq->text_utf8)
|
||||||
*index = _raqm_u8_to_u32_index (rq, *index);
|
*index = _raqm_u8_to_u32_index (rq, *index);
|
||||||
|
|
||||||
if (*index >= rq->text_len)
|
if (*index >= rq->text_len)
|
||||||
|
@ -1974,7 +2075,7 @@ raqm_index_to_position (raqm_t *rq,
|
||||||
}
|
}
|
||||||
|
|
||||||
found:
|
found:
|
||||||
if (rq->flags & RAQM_FLAG_UTF8)
|
if (rq->text_utf8)
|
||||||
*index = _raqm_u32_to_u8_index (rq, *index);
|
*index = _raqm_u32_to_u8_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;
|
||||||
|
|
11
src/thirdparty/raqm/raqm.h
vendored
11
src/thirdparty/raqm/raqm.h
vendored
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2015 Information Technology Authority (ITA) <foss@ita.gov.om>
|
* Copyright © 2015 Information Technology Authority (ITA) <foss@ita.gov.om>
|
||||||
* Copyright © 2016-2021 Khaled Hosny <khaled@aliftype.com>
|
* Copyright © 2016-2022 Khaled Hosny <khaled@aliftype.com>
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
@ -106,6 +106,9 @@ raqm_reference (raqm_t *rq);
|
||||||
RAQM_API void
|
RAQM_API void
|
||||||
raqm_destroy (raqm_t *rq);
|
raqm_destroy (raqm_t *rq);
|
||||||
|
|
||||||
|
RAQM_API void
|
||||||
|
raqm_clear_contents (raqm_t *rq);
|
||||||
|
|
||||||
RAQM_API bool
|
RAQM_API bool
|
||||||
raqm_set_text (raqm_t *rq,
|
raqm_set_text (raqm_t *rq,
|
||||||
const uint32_t *text,
|
const uint32_t *text,
|
||||||
|
@ -145,6 +148,12 @@ RAQM_API bool
|
||||||
raqm_set_freetype_load_flags (raqm_t *rq,
|
raqm_set_freetype_load_flags (raqm_t *rq,
|
||||||
int flags);
|
int flags);
|
||||||
|
|
||||||
|
RAQM_API bool
|
||||||
|
raqm_set_freetype_load_flags_range (raqm_t *rq,
|
||||||
|
int flags,
|
||||||
|
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);
|
||||||
|
|
|
@ -24,7 +24,7 @@ Download and install:
|
||||||
* `CMake 3.12 or newer <https://cmake.org/download/>`_
|
* `CMake 3.12 or newer <https://cmake.org/download/>`_
|
||||||
(also available as Visual Studio component C++ CMake tools for Windows)
|
(also available as Visual Studio component C++ CMake tools for Windows)
|
||||||
|
|
||||||
* `NASM <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_
|
* x86/x64: `NASM <https://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D>`_
|
||||||
|
|
||||||
Any version of Visual Studio 2017 or newer should be supported,
|
Any version of Visual Studio 2017 or newer should be supported,
|
||||||
including Visual Studio 2017 Community, or Build Tools for Visual Studio 2019.
|
including Visual Studio 2017 Community, or Build Tools for Visual Studio 2019.
|
||||||
|
@ -42,8 +42,8 @@ behaviour of ``build_prepare.py``:
|
||||||
If ``PYTHON`` is unset, the version of Python used to run
|
If ``PYTHON`` is unset, the version of Python used to run
|
||||||
``build_prepare.py`` will be used. If only ``PYTHON`` is set,
|
``build_prepare.py`` will be used. If only ``PYTHON`` is set,
|
||||||
``EXECUTABLE`` defaults to ``python.exe``.
|
``EXECUTABLE`` defaults to ``python.exe``.
|
||||||
* ``ARCHITECTURE`` is used to select a ``x86`` or ``x64`` build. By default,
|
* ``ARCHITECTURE`` is used to select a ``x86``, ``x64`` or ``ARM64``build.
|
||||||
uses same architecture as the version of Python used to run ``build_prepare.py``.
|
By default, uses same architecture as the version of Python used to run ``build_prepare.py``.
|
||||||
is used.
|
is used.
|
||||||
* ``PILLOW_BUILD`` can be used to override the ``winbuild\build`` directory
|
* ``PILLOW_BUILD`` can be used to override the ``winbuild\build`` directory
|
||||||
path, used to store generated build scripts and compiled libraries.
|
path, used to store generated build scripts and compiled libraries.
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import struct
|
import struct
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -93,6 +94,7 @@ SF_MIRROR = "http://iweb.dl.sourceforge.net"
|
||||||
architectures = {
|
architectures = {
|
||||||
"x86": {"vcvars_arch": "x86", "msbuild_arch": "Win32"},
|
"x86": {"vcvars_arch": "x86", "msbuild_arch": "Win32"},
|
||||||
"x64": {"vcvars_arch": "x86_amd64", "msbuild_arch": "x64"},
|
"x64": {"vcvars_arch": "x86_amd64", "msbuild_arch": "x64"},
|
||||||
|
"ARM64": {"vcvars_arch": "x86_arm64", "msbuild_arch": "ARM64"},
|
||||||
}
|
}
|
||||||
|
|
||||||
header = [
|
header = [
|
||||||
|
@ -219,25 +221,25 @@ deps = {
|
||||||
# "bins": [r"objs\{msbuild_arch}\Release\freetype.dll"],
|
# "bins": [r"objs\{msbuild_arch}\Release\freetype.dll"],
|
||||||
},
|
},
|
||||||
"lcms2": {
|
"lcms2": {
|
||||||
"url": SF_MIRROR + "/project/lcms/lcms/2.12/lcms2-2.12.tar.gz",
|
"url": SF_MIRROR + "/project/lcms/lcms/2.13/lcms2-2.13.tar.gz",
|
||||||
"filename": "lcms2-2.12.tar.gz",
|
"filename": "lcms2-2.13.tar.gz",
|
||||||
"dir": "lcms2-2.12",
|
"dir": "lcms2-2.13",
|
||||||
"patch": {
|
"patch": {
|
||||||
r"Projects\VC2017\lcms2_static\lcms2_static.vcxproj": {
|
r"Projects\VC2019\lcms2_static\lcms2_static.vcxproj": {
|
||||||
# default is /MD for x86 and /MT for x64, we need /MD always
|
# default is /MD for x86 and /MT for x64, we need /MD always
|
||||||
"<RuntimeLibrary>MultiThreaded</RuntimeLibrary>": "<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>", # noqa: E501
|
"<RuntimeLibrary>MultiThreaded</RuntimeLibrary>": "<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>", # noqa: E501
|
||||||
# retarget to default toolset (selected by vcvarsall.bat)
|
# retarget to default toolset (selected by vcvarsall.bat)
|
||||||
"<PlatformToolset>v141</PlatformToolset>": "<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>", # noqa: E501
|
"<PlatformToolset>v142</PlatformToolset>": "<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>", # noqa: E501
|
||||||
# retarget to latest (selected by vcvarsall.bat)
|
# retarget to latest (selected by vcvarsall.bat)
|
||||||
"<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>": "<WindowsTargetPlatformVersion>$(WindowsSDKVersion)</WindowsTargetPlatformVersion>", # noqa: E501
|
"<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>": "<WindowsTargetPlatformVersion>$(WindowsSDKVersion)</WindowsTargetPlatformVersion>", # noqa: E501
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"build": [
|
"build": [
|
||||||
cmd_rmdir("Lib"),
|
cmd_rmdir("Lib"),
|
||||||
cmd_rmdir(r"Projects\VC2017\Release"),
|
cmd_rmdir(r"Projects\VC2019\Release"),
|
||||||
cmd_msbuild(r"Projects\VC2017\lcms2.sln", "Release", "Clean"),
|
cmd_msbuild(r"Projects\VC2019\lcms2.sln", "Release", "Clean"),
|
||||||
cmd_msbuild(
|
cmd_msbuild(
|
||||||
r"Projects\VC2017\lcms2.sln", "Release", "lcms2_static:Rebuild"
|
r"Projects\VC2019\lcms2.sln", "Release", "lcms2_static:Rebuild"
|
||||||
),
|
),
|
||||||
cmd_xcopy("include", "{inc_dir}"),
|
cmd_xcopy("include", "{inc_dir}"),
|
||||||
],
|
],
|
||||||
|
@ -278,9 +280,9 @@ deps = {
|
||||||
"libs": [r"imagequant.lib"],
|
"libs": [r"imagequant.lib"],
|
||||||
},
|
},
|
||||||
"harfbuzz": {
|
"harfbuzz": {
|
||||||
"url": "https://github.com/harfbuzz/harfbuzz/archive/3.2.0.zip",
|
"url": "https://github.com/harfbuzz/harfbuzz/archive/3.3.1.zip",
|
||||||
"filename": "harfbuzz-3.2.0.zip",
|
"filename": "harfbuzz-3.3.1.zip",
|
||||||
"dir": "harfbuzz-3.2.0",
|
"dir": "harfbuzz-3.3.1",
|
||||||
"build": [
|
"build": [
|
||||||
cmd_cmake("-DHB_HAVE_FREETYPE:BOOL=TRUE"),
|
cmd_cmake("-DHB_HAVE_FREETYPE:BOOL=TRUE"),
|
||||||
cmd_nmake(target="clean"),
|
cmd_nmake(target="clean"),
|
||||||
|
@ -490,7 +492,10 @@ if __name__ == "__main__":
|
||||||
python_dir = os.environ.get("PYTHON")
|
python_dir = os.environ.get("PYTHON")
|
||||||
python_exe = os.environ.get("EXECUTABLE", "python.exe")
|
python_exe = os.environ.get("EXECUTABLE", "python.exe")
|
||||||
architecture = os.environ.get(
|
architecture = os.environ.get(
|
||||||
"ARCHITECTURE", "x86" if struct.calcsize("P") == 4 else "x64"
|
"ARCHITECTURE",
|
||||||
|
"ARM64"
|
||||||
|
if platform.machine() == "ARM64"
|
||||||
|
else ("x86" if struct.calcsize("P") == 4 else "x64"),
|
||||||
)
|
)
|
||||||
build_dir = os.environ.get("PILLOW_BUILD", os.path.join(winbuild_dir, "build"))
|
build_dir = os.environ.get("PILLOW_BUILD", os.path.join(winbuild_dir, "build"))
|
||||||
sources_dir = ""
|
sources_dir = ""
|
||||||
|
|
Loading…
Reference in New Issue
Block a user