David Turner pushed to branch download-test-fonts at FreeType / FreeType
Commits:
-
205d1ae4
by Werner Lemberg at 2021-07-12T22:03:25+02:00
-
825b7ea2
by Werner Lemberg at 2021-07-12T22:11:24+02:00
-
c5516e0f
by Alex Richardson at 2021-07-12T22:23:42+02:00
-
e592982a
by Anuj Verma at 2021-07-13T10:00:22+02:00
-
a4c8f21a
by Oleg Oshmyan at 2021-07-13T10:44:38+02:00
-
5d27b10f
by Oleg Oshmyan at 2021-07-13T11:00:48+02:00
-
f7c6a06c
by Alex Richardson at 2021-07-15T12:09:04+02:00
-
2811ef99
by David Turner at 2021-07-15T13:17:30+02:00
18 changed files:
- ChangeLog
- devel/ftoption.h
- docs/CHANGES
- include/freetype/config/ftoption.h
- include/freetype/freetype.h
- include/freetype/ftdriver.h
- include/freetype/ftmodapi.h
- include/freetype/internal/compiler-macros.h
- include/freetype/internal/fttrace.h
- meson.build
- src/autofit/afhints.c
- src/autofit/afhints.h
- src/autofit/afloader.c
- src/base/ftobjs.c
- src/sdf/ftsdf.c
- tests/README.md
- + tests/scripts/download-test-fonts.py
- − tests/scripts/download-test-fonts.sh
Changes:
1 |
+2021-07-15 David Turner <david@freetype.org>
|
|
2 |
+ |
|
3 |
+ Replaces download-test-fonts.sh with download-test-fonts.py which
|
|
4 |
+ does the same work, and also avoids downloading anything if the
|
|
5 |
+ files are already installed with the right content.
|
|
6 |
+ |
|
7 |
+ Now uses the first 8 byte of each file's sha256 hash for the digest.
|
|
8 |
+ |
|
9 |
+ * tests/scripts/download-test-fonts.sh: Removed
|
|
10 |
+ * tests/scripts/download-test-fonts.py: New script
|
|
11 |
+ * tests/README.md: Updated
|
|
12 |
+ |
|
13 |
+2021-07-15 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
|
|
14 |
+ |
|
15 |
+ Support architectures where `long` is smaller than pointers.
|
|
16 |
+ |
|
17 |
+ I am currently trying to compile FreeType for CHERI-extended ISAs
|
|
18 |
+ (CHERI-RISC-V and Arm's Morello), but I am getting compiler warnings
|
|
19 |
+ from the `FT_UINT_TO_POINTER` macro. When compiling with the CHERI
|
|
20 |
+ Clang compiler, not using `uinptr_t` for casts between integers an
|
|
21 |
+ pointers results in the following `-Werror` build failures:
|
|
22 |
+ |
|
23 |
+ ```
|
|
24 |
+ In file included from .../src/truetype/truetype.c:22:
|
|
25 |
+ .../src/truetype/ttgload.c:1925:22: error:
|
|
26 |
+ cast from provenance-free integer type to pointer type will
|
|
27 |
+ give pointer that can not be dereferenced
|
|
28 |
+ [-Werror,-Wcheri-capability-misuse]
|
|
29 |
+ node->data = "" glyph_index );
|
|
30 |
+ ^
|
|
31 |
+ .../include/freetype/internal/compiler-macros.h:79:34: note:
|
|
32 |
+ expanded from macro 'FT_UINT_TO_POINTER'
|
|
33 |
+ ```
|
|
34 |
+ |
|
35 |
+ * include/freetype/internal/compiler-macros.h (FT_UINT_TO_POINTER):
|
|
36 |
+ The ISO C standard compliant fix for this would be to use
|
|
37 |
+ `uintptr_t` from `stdint.h`, but I am not sure if this is supported
|
|
38 |
+ by the minimum compiler version. Therefore, use the
|
|
39 |
+ compiler-defined `__UINTPTR_TYPE__` macro (supported in GCC 4.6+ and
|
|
40 |
+ Clang since about 3.0) before checking for `_WIN64` and falling back
|
|
41 |
+ to `unsigned long`.
|
|
42 |
+ |
|
43 |
+2021-07-13 Oleg Oshmyan <chortos@inbox.lv>
|
|
44 |
+ |
|
45 |
+ [base] Fix `FT_Open_Face`'s handling of user-supplied streams.
|
|
46 |
+ |
|
47 |
+ This was already true (though undocumented) most of the time, but
|
|
48 |
+ not if `FT_NEW` inside `FT_Stream_New` failed or if the
|
|
49 |
+ `FT_OPEN_XXX` flags were bad.
|
|
50 |
+ |
|
51 |
+ Normally, `FT_Open_Face` calls `FT_Stream_New`, which returns the
|
|
52 |
+ user-supplied stream unchanged, and in case of any subsequent error
|
|
53 |
+ in `FT_Open_Face`, the stream is closed via `FT_Stream_Free`.
|
|
54 |
+ |
|
55 |
+ Up to now, however, `FT_Stream_New` allocates a new stream even if
|
|
56 |
+ it is already given one by the user. If this allocation fails, the
|
|
57 |
+ user-supplied stream is not returned to `FT_Open_Face` and never
|
|
58 |
+ closed. Moreover, the user cannot detect this situation: all they
|
|
59 |
+ see is that `FT_Open_Face` returns `FT_Err_Out_Of_Memory`, but that
|
|
60 |
+ can also happen after a different allocation fails within the main
|
|
61 |
+ body of `FT_Open_Face`, when the user's stream has already been
|
|
62 |
+ closed by `FT_Open_Face`. It is plausible that the user stream's
|
|
63 |
+ `close` method frees memory allocated for the stream object itself,
|
|
64 |
+ so the user cannot defensively free it upon `FT_Open_Face` failure
|
|
65 |
+ lest it ends up doubly freed. All in all, this ends up leaking the
|
|
66 |
+ memory/resources used by user's stream.
|
|
67 |
+ |
|
68 |
+ Furthermore, `FT_Stream_New` simply returns an error if the
|
|
69 |
+ `FT_OPEN_XXX` flags are unsupported, which can mean either an
|
|
70 |
+ invalid combination of flags or a perfectly innocent
|
|
71 |
+ `FT_OPEN_STREAM` on a FreeType build that lacks stream support.
|
|
72 |
+ With this patch, the user-supplied stream is closed even in these
|
|
73 |
+ cases, so the user can be sure that if `FT_Open_Face` failed, the
|
|
74 |
+ stream is definitely closed.
|
|
75 |
+ |
|
76 |
+ * src/base/ftobjs.c (FT_Stream_New): Don't allocate a buffer
|
|
77 |
+ unnecessarily.
|
|
78 |
+ Move error-handling code to make the control flow more obvious.
|
|
79 |
+ Close user-supplied stream if the flags are unsupported.
|
|
80 |
+ `FT_Stream_Open` always sets `pathname.pointer`, so remove the
|
|
81 |
+ redundant (re)assignment. None of the `FT_Stream_Open...` functions
|
|
82 |
+ uses `stream->memory`, so keep just one assignment at the end,
|
|
83 |
+ shared among all possible control flow paths.
|
|
84 |
+ ('Unsupported flags' that may need a stream closure can be either an
|
|
85 |
+ invalid combination of multiple `FT_OPEN_XXX` mode flags or a clean
|
|
86 |
+ `FT_OPEN_STREAM` flag on a FreeType build that lacks stream
|
|
87 |
+ support.)
|
|
88 |
+ |
|
89 |
+2021-07-13 Oleg Oshmyan <chortos@inbox.lv>
|
|
90 |
+ |
|
91 |
+ [base] Reject combinations of incompatible `FT_OPEN_XXX` flags.
|
|
92 |
+ |
|
93 |
+ The three modes are mutually exclusive, and the documentation of the
|
|
94 |
+ `FT_OPEN_XXX` constants notes this. However, there was no check to
|
|
95 |
+ validate this in the code, and the documentation on `FT_Open_Args`
|
|
96 |
+ claimed that the corresponding bits were checked in a well-defined
|
|
97 |
+ order, implying it was valid (if useless) to specify more than one.
|
|
98 |
+ Ironically, this documented order did not agree with the actual
|
|
99 |
+ code, so it could not be relied upon; hopefully, nobody did this and
|
|
100 |
+ nobody will be hurt by the new validation.
|
|
101 |
+ |
|
102 |
+ Even if multiple mode bits were allowed, they could cause memory
|
|
103 |
+ leaks: if both `FT_OPEN_STREAM` and `stream` are set along with
|
|
104 |
+ either `FT_OPEN_MEMORY` or `FT_OPEN_PATHNAME`, then `FT_Stream_New`
|
|
105 |
+ allocated a new stream but `FT_Open_Face` marked it as an 'external'
|
|
106 |
+ stream, so the stream object was never released.
|
|
107 |
+ |
|
108 |
+ * src/base/ftobjs.c (FT_Stream_New): Reject incompatible
|
|
109 |
+ `FT_OPEN_XXX` flags.
|
|
110 |
+ |
|
111 |
+2021-07-12 Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
|
|
112 |
+ |
|
113 |
+ * meson.build: Fix build for other UNIX systems (e.g., FreeBSD).
|
|
114 |
+ |
|
115 |
+ Without this change the build of `unix/ftsystem.c` fails because the
|
|
116 |
+ `ftconfig.h` header that defines macros such as `HAVE_UNISTD_H` and
|
|
117 |
+ `HAVE_FCNTL_H` is only being generated for Linux, macOS, and Cygwin
|
|
118 |
+ systems:
|
|
119 |
+ |
|
120 |
+ ```
|
|
121 |
+ .../builds/unix/ftsystem.c:258:32: error:
|
|
122 |
+ use of undeclared identifier 'O_RDONLY'
|
|
123 |
+ file = open( filepathname, O_RDONLY );
|
|
124 |
+ ```
|
|
125 |
+ |
|
126 |
+ Instead of hardcoding a list of operating systems for this check,
|
|
127 |
+ update the logic that decides whether to build the file and set a
|
|
128 |
+ boolean flag that can be checked instead.
|
|
129 |
+ |
|
130 |
+2021-07-12 Werner Lemberg <wl@gnu.org>
|
|
131 |
+ |
|
132 |
+ [autofit] More clean-ups.
|
|
133 |
+ |
|
134 |
+ * src/autofit/afhints.h (AF_GlyphHintsRec): Remove the no longer
|
|
135 |
+ needed fields `xmin_delta` and `xmax_delta`.
|
|
136 |
+ |
|
137 |
+ * src/autofit/afhints.c (af_glyph_hints_reload),
|
|
138 |
+ src/autofit/afloader.c (af_loader_load_glyph): Updated.
|
|
139 |
+ |
|
140 |
+2021-07-12 Werner Lemberg <wl@gnu.org>
|
|
141 |
+ |
|
142 |
+ Small clean-ups for the last few commits.
|
|
143 |
+ |
|
144 |
+ * include/freetype/fttrace.h (afwarp): Removed.
|
|
145 |
+ |
|
1 | 146 |
2021-07-12 David Turner <david@freetype.org>
|
2 | 147 |
|
3 | 148 |
Remove obsolete AF_Angle type and related sources.
|
4 | 149 |
|
5 |
- Move the af_sort_xxx() functions from afangles.c to afhints.c in
|
|
6 |
- order to get rid of the obsolete angle-related types, macros and
|
|
7 |
- function definitions.
|
|
150 |
+ * src/autofit/afangles.c: File removed. Functions related to
|
|
151 |
+ sorting moved to...
|
|
152 |
+ * src/autofit/afhints.c (af_sort_pos, af_sort_and_quantize_widths):
|
|
153 |
+ This file.
|
|
154 |
+ * src/autofit/afangles.h: File removed.
|
|
155 |
+ * src/autofit/aftypes.h: Updated.
|
|
156 |
+ * src/autofit/autofit.c: Updated.
|
|
8 | 157 |
|
9 |
- * src/autofit/*: Remove code.
|
|
158 |
+ * src/autofit/rules.mk (AUTOF_DRV_SRC): Updated.
|
|
10 | 159 |
|
11 | 160 |
2021-07-12 David Turner <david@freetype.org>
|
12 | 161 |
|
13 | 162 |
Remove experimental auto-hinting 'warp' mode.
|
14 | 163 |
|
15 |
- This feature was always experimental, and probably nevery worked
|
|
16 |
- properly. This patch completely removes it from the source code,
|
|
164 |
+ This feature was always experimental, and probably never worked
|
|
165 |
+ properly. This patch completely removes it from the source code,
|
|
17 | 166 |
except for a documentation block describing it for historical
|
18 |
- purpose.
|
|
167 |
+ purposes.
|
|
168 |
+ |
|
169 |
+ * devel/ftoption.h, include/freetype/config/ftoption.h: Remove
|
|
170 |
+ `AF_CONFIG_OPTION_USE_WARPER`.
|
|
171 |
+ |
|
172 |
+ * include/freetype/ftdriver.h: Document 'warping' property as
|
|
173 |
+ obsolete.
|
|
19 | 174 |
|
20 |
- * devel/ftoption.h: Remove AF_CONFIG_OPTION_USE_WARPER.
|
|
21 |
- * include/freetype/config/ftoption.h: Remove AF_CONFIG_OPTION_USE_WARPER.
|
|
22 |
- * include/freetype/ftdriver.h: Document 'warping' property as obsolete.
|
|
23 |
- * src/autofit/*: Remove any warp mode related code.
|
|
175 |
+ * src/autofit/afwarp.c, src/autofit/afwarp.h: Files removed.
|
|
176 |
+ * src/autofit/*: Remove any code related to warp mode.
|
|
24 | 177 |
|
25 | 178 |
2021-07-12 David Turner <david@freetype.org>
|
26 | 179 |
|
27 |
- Remove experimental "Latin2" writing system (FT_OPTION_AUTOFIT2)
|
|
180 |
+ Remove experimental 'Latin2' writing system (`FT_OPTION_AUTOFIT2`).
|
|
28 | 181 |
|
29 | 182 |
This code has always been experimental and was never compiled anyway
|
30 |
- (FT_OPTION_AUTOFIT2 does not appear in ftoption.h or even any of our
|
|
31 |
- build files).
|
|
32 |
- |
|
33 |
- * include/freetype/internal/fttrace.h: Remove 'FT_TRACE_DEF( aflatin2 )'.
|
|
34 |
- * src/autofit/aflatin2.[hc]: Removed.
|
|
35 |
- * src/autofit/afloader.c: Remove undocumented hook to activate Latin2 system.
|
|
36 |
- * src/autofit/afstyles.h: Remove ltn2_dflt style definition.
|
|
37 |
- * src/autofit/afwrtsys.h: Remove LATIN2 writing system definition.
|
|
183 |
+ (`FT_OPTION_AUTOFIT2` does not appear in `ftoption.h` or even any of
|
|
184 |
+ our build files).
|
|
185 |
+ |
|
186 |
+ * include/freetype/internal/fttrace.h (aflatin2): Removed.
|
|
187 |
+ * src/autofit/aflatin2.h, src/autofit/aflatin2.c: Files removed.
|
|
188 |
+ * src/autofit/afloader.c: Remove undocumented hook to activate
|
|
189 |
+ Latin2 system.
|
|
190 |
+ * src/autofit/afstyles.h: Remove `ltn2_dflt` style definition.
|
|
191 |
+ * src/autofit/afwrtsys.h: Remove `LATIN2` writing system definition.
|
|
38 | 192 |
* src/autofit/autofit.c: Updated.
|
39 | 193 |
|
40 | 194 |
2021-07-05 Werner Lemberg <wl@gnu.org>
|
... | ... | @@ -105,8 +105,7 @@ FT_BEGIN_HEADER |
105 | 105 |
*
|
106 | 106 |
* ```
|
107 | 107 |
* FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
|
108 |
- * cff:no-stem-darkening=1 \
|
|
109 |
- * autofitter:warping=1
|
|
108 |
+ * cff:no-stem-darkening=1
|
|
110 | 109 |
* ```
|
111 | 110 |
*
|
112 | 111 |
*/
|
... | ... | @@ -72,6 +72,9 @@ CHANGES BETWEEN 2.10.4 and 2.11.0 |
72 | 72 |
|
73 | 73 |
This work was Priyesh Kumar's GSoC 2020 project.
|
74 | 74 |
|
75 |
+ - The experimental 'warp' mode (AF_CONFIG_OPTION_USE_WARPER) for the
|
|
76 |
+ auto-hinter has been removed.
|
|
77 |
+ |
|
75 | 78 |
- The smooth rasterizer performance has been improved by >10%.
|
76 | 79 |
|
77 | 80 |
- PCF bitmap fonts compressed with LZW (these are usually files with
|
... | ... | @@ -105,8 +105,7 @@ FT_BEGIN_HEADER |
105 | 105 |
*
|
106 | 106 |
* ```
|
107 | 107 |
* FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
|
108 |
- * cff:no-stem-darkening=1 \
|
|
109 |
- * autofitter:warping=1
|
|
108 |
+ * cff:no-stem-darkening=1
|
|
110 | 109 |
* ```
|
111 | 110 |
*
|
112 | 111 |
*/
|
... | ... | @@ -2113,8 +2113,7 @@ FT_BEGIN_HEADER |
2113 | 2113 |
* Extra parameters passed to the font driver when opening a new face.
|
2114 | 2114 |
*
|
2115 | 2115 |
* @note:
|
2116 |
- * The stream type is determined by the contents of `flags` that are
|
|
2117 |
- * tested in the following order by @FT_Open_Face:
|
|
2116 |
+ * The stream type is determined by the contents of `flags`:
|
|
2118 | 2117 |
*
|
2119 | 2118 |
* If the @FT_OPEN_MEMORY bit is set, assume that this is a memory file
|
2120 | 2119 |
* of `memory_size` bytes, located at `memory_address`. The data are not
|
... | ... | @@ -2127,6 +2126,9 @@ FT_BEGIN_HEADER |
2127 | 2126 |
* Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this is a
|
2128 | 2127 |
* normal file and use `pathname` to open it.
|
2129 | 2128 |
*
|
2129 |
+ * If none of the above bits are set or if multiple are set at the same
|
|
2130 |
+ * time, the flags are invalid and @FT_Open_Face fails.
|
|
2131 |
+ *
|
|
2130 | 2132 |
* If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to open
|
2131 | 2133 |
* the file with the driver whose handler is in `driver`.
|
2132 | 2134 |
*
|
... | ... | @@ -2299,6 +2301,10 @@ FT_BEGIN_HEADER |
2299 | 2301 |
* See the discussion of reference counters in the description of
|
2300 | 2302 |
* @FT_Reference_Face.
|
2301 | 2303 |
*
|
2304 |
+ * If `FT_OPEN_STREAM` is set in `args->flags`, the stream in
|
|
2305 |
+ * `args->stream` is automatically closed before this function returns
|
|
2306 |
+ * any error (including `FT_Err_Invalid_Argument`).
|
|
2307 |
+ *
|
|
2302 | 2308 |
* @example:
|
2303 | 2309 |
* To loop over all faces, use code similar to the following snippet
|
2304 | 2310 |
* (omitting the error handling).
|
... | ... | @@ -3307,13 +3313,13 @@ FT_BEGIN_HEADER |
3307 | 3313 |
* pixels and use the @FT_PIXEL_MODE_LCD_V mode.
|
3308 | 3314 |
*
|
3309 | 3315 |
* FT_RENDER_MODE_SDF ::
|
3310 |
- * This mode corresponds to 8-bit signed distance fields (SDF)
|
|
3311 |
- * bitmaps. Each pixel in a SDF bitmap contains information about the
|
|
3312 |
- * nearest edge of the glyph outline. The distances are calculated
|
|
3313 |
- * from the center of the pixel and are positive if they are filled by
|
|
3314 |
- * the outline (i.e., inside the outline) and negative otherwise.
|
|
3315 |
- * Check the note below on how to convert the output values to usable
|
|
3316 |
- * data.
|
|
3316 |
+ * This mode corresponds to 8-bit, single-channel signed distance field
|
|
3317 |
+ * (SDF) bitmaps. Each pixel in the SDF grid is the value from the
|
|
3318 |
+ * pixel's position to the nearest glyph's outline. The distances are
|
|
3319 |
+ * calculated from the center of the pixel and are positive if they are
|
|
3320 |
+ * filled by the outline (i.e., inside the outline) and negative
|
|
3321 |
+ * otherwise. Check the note below on how to convert the output values
|
|
3322 |
+ * to usable data.
|
|
3317 | 3323 |
*
|
3318 | 3324 |
* @note:
|
3319 | 3325 |
* The selected render mode only affects vector glyphs of a font.
|
... | ... | @@ -53,10 +53,10 @@ FT_BEGIN_HEADER |
53 | 53 |
* reasons.
|
54 | 54 |
*
|
55 | 55 |
* Available properties are @increase-x-height, @no-stem-darkening
|
56 |
- * (experimental), @darkening-parameters (experimental), @warping
|
|
57 |
- * (experimental), @glyph-to-script-map (experimental), @fallback-script
|
|
58 |
- * (experimental), and @default-script (experimental), as documented in
|
|
59 |
- * the @properties section.
|
|
56 |
+ * (experimental), @darkening-parameters (experimental),
|
|
57 |
+ * @glyph-to-script-map (experimental), @fallback-script (experimental),
|
|
58 |
+ * and @default-script (experimental), as documented in the @properties
|
|
59 |
+ * section.
|
|
60 | 60 |
*
|
61 | 61 |
*/
|
62 | 62 |
|
... | ... | @@ -1165,15 +1165,15 @@ FT_BEGIN_HEADER |
1165 | 1165 |
* **Obsolete**
|
1166 | 1166 |
*
|
1167 | 1167 |
* This property was always experimental and probably never worked
|
1168 |
- * correctly. It was entirely removed from the FreeType 2 sources.
|
|
1169 |
- * This entry is only here for historical reference.
|
|
1168 |
+ * correctly. It was entirely removed from the FreeType~2 sources. This
|
|
1169 |
+ * entry is only here for historical reference.
|
|
1170 | 1170 |
*
|
1171 |
- * Warping only works in 'normal' auto-hinting mode replacing it. The
|
|
1172 |
- * idea of the code is to slightly scale and shift a glyph along the
|
|
1171 |
+ * Warping only worked in 'normal' auto-hinting mode replacing it. The
|
|
1172 |
+ * idea of the code was to slightly scale and shift a glyph along the
|
|
1173 | 1173 |
* non-hinted dimension (which is usually the horizontal axis) so that as
|
1174 |
- * much of its segments are aligned (more or less) to the grid. To find
|
|
1174 |
+ * much of its segments were aligned (more or less) to the grid. To find
|
|
1175 | 1175 |
* out a glyph's optimal scaling and shifting value, various parameter
|
1176 |
- * combinations are tried and scored.
|
|
1176 |
+ * combinations were tried and scored.
|
|
1177 | 1177 |
*
|
1178 | 1178 |
* @since:
|
1179 | 1179 |
* 2.6
|
... | ... | @@ -508,8 +508,7 @@ FT_BEGIN_HEADER |
508 | 508 |
*
|
509 | 509 |
* ```
|
510 | 510 |
* FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
|
511 |
- * cff:no-stem-darkening=0 \
|
|
512 |
- * autofitter:warping=1
|
|
511 |
+ * cff:no-stem-darkening=0
|
|
513 | 512 |
* ```
|
514 | 513 |
*
|
515 | 514 |
* @inout:
|
... | ... | @@ -71,12 +71,18 @@ FT_BEGIN_HEADER |
71 | 71 |
*/
|
72 | 72 |
#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
|
73 | 73 |
|
74 |
-#ifdef _WIN64
|
|
74 |
+#ifdef __UINTPTR_TYPE__
|
|
75 |
+ /*
|
|
76 |
+ * GCC and Clang both provide a `__UINTPTR_TYPE__` that can be used to
|
|
77 |
+ * avoid a dependency on `stdint.h`.
|
|
78 |
+ */
|
|
79 |
+# define FT_UINT_TO_POINTER( x ) (void *)(__UINTPTR_TYPE__)(x)
|
|
80 |
+#elif defined( _WIN64 )
|
|
75 | 81 |
/* only 64bit Windows uses the LLP64 data model, i.e., */
|
76 | 82 |
/* 32-bit integers, 64-bit pointers. */
|
77 |
-#define FT_UINT_TO_POINTER( x ) (void *)(unsigned __int64)(x)
|
|
83 |
+# define FT_UINT_TO_POINTER( x ) (void *)(unsigned __int64)(x)
|
|
78 | 84 |
#else
|
79 |
-#define FT_UINT_TO_POINTER( x ) (void *)(unsigned long)(x)
|
|
85 |
+# define FT_UINT_TO_POINTER( x ) (void *)(unsigned long)(x)
|
|
80 | 86 |
#endif
|
81 | 87 |
|
82 | 88 |
/*
|
... | ... | @@ -160,7 +160,6 @@ FT_TRACE_DEF( afhints ) |
160 | 160 |
FT_TRACE_DEF( afmodule )
|
161 | 161 |
FT_TRACE_DEF( aflatin )
|
162 | 162 |
FT_TRACE_DEF( afshaper )
|
163 |
-FT_TRACE_DEF( afwarp )
|
|
164 | 163 |
|
165 | 164 |
/* SDF components */
|
166 | 165 |
FT_TRACE_DEF( sdf ) /* signed distance raster for outlines (ftsdf.c) */
|
... | ... | @@ -193,6 +193,7 @@ has_sys_mman_h = cc.has_header('sys/mman.h') |
193 | 193 |
|
194 | 194 |
mmap_option = get_option('mmap')
|
195 | 195 |
|
196 |
+use_unix_ftsystem_c = false
|
|
196 | 197 |
if mmap_option.disabled()
|
197 | 198 |
ft2_sources += files(['src/base/ftsystem.c',])
|
198 | 199 |
elif host_machine.system() == 'windows'
|
... | ... | @@ -201,6 +202,7 @@ else |
201 | 202 |
if has_unistd_h and has_fcntl_h and has_sys_mman_h
|
202 | 203 |
# This version of `ftsystem.c` uses `mmap` to read input font files.
|
203 | 204 |
ft2_sources += files(['builds/unix/ftsystem.c',])
|
205 |
+ use_unix_ftsystem_c = true
|
|
204 | 206 |
elif mmap_option.enabled()
|
205 | 207 |
error('mmap was enabled via options but is not available,'
|
206 | 208 |
+ ' required headers were not found!')
|
... | ... | @@ -321,7 +323,7 @@ if has_fcntl_h |
321 | 323 |
ftconfig_command += '--enable=HAVE_FCNTL_H'
|
322 | 324 |
endif
|
323 | 325 |
|
324 |
-if host_machine.system() in ['linux', 'darwin', 'cygwin']
|
|
326 |
+if use_unix_ftsystem_c
|
|
325 | 327 |
ftconfig_h_in = files('builds/unix/ftconfig.h.in')
|
326 | 328 |
ftconfig_h = custom_target('ftconfig.h',
|
327 | 329 |
input: ftconfig_h_in,
|
... | ... | @@ -953,9 +953,6 @@ |
953 | 953 |
hints->x_delta = x_delta;
|
954 | 954 |
hints->y_delta = y_delta;
|
955 | 955 |
|
956 |
- hints->xmin_delta = 0;
|
|
957 |
- hints->xmax_delta = 0;
|
|
958 |
- |
|
959 | 956 |
points = hints->points;
|
960 | 957 |
if ( hints->num_points == 0 )
|
961 | 958 |
goto Exit;
|
... | ... | @@ -362,9 +362,6 @@ FT_BEGIN_HEADER |
362 | 362 |
/* implementations */
|
363 | 363 |
AF_StyleMetrics metrics;
|
364 | 364 |
|
365 |
- FT_Pos xmin_delta; /* used for warping */
|
|
366 |
- FT_Pos xmax_delta;
|
|
367 |
- |
|
368 | 365 |
/* Two arrays to avoid allocation penalty. */
|
369 | 366 |
/* The `embedded' structure must be the last element! */
|
370 | 367 |
struct
|
... | ... | @@ -473,8 +473,8 @@ |
473 | 473 |
FT_Pos pp2x = loader->pp2.x;
|
474 | 474 |
|
475 | 475 |
|
476 |
- loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
|
|
477 |
- loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
|
|
476 |
+ loader->pp1.x = FT_PIX_ROUND( pp1x );
|
|
477 |
+ loader->pp2.x = FT_PIX_ROUND( pp2x );
|
|
478 | 478 |
|
479 | 479 |
slot->lsb_delta = loader->pp1.x - pp1x;
|
480 | 480 |
slot->rsb_delta = loader->pp2.x - pp2x;
|
... | ... | @@ -197,6 +197,7 @@ |
197 | 197 |
FT_Error error;
|
198 | 198 |
FT_Memory memory;
|
199 | 199 |
FT_Stream stream = NULL;
|
200 |
+ FT_UInt mode;
|
|
200 | 201 |
|
201 | 202 |
|
202 | 203 |
*astream = NULL;
|
... | ... | @@ -208,15 +209,15 @@ |
208 | 209 |
return FT_THROW( Invalid_Argument );
|
209 | 210 |
|
210 | 211 |
memory = library->memory;
|
212 |
+ mode = args->flags &
|
|
213 |
+ ( FT_OPEN_MEMORY | FT_OPEN_STREAM | FT_OPEN_PATHNAME );
|
|
211 | 214 |
|
212 |
- if ( FT_NEW( stream ) )
|
|
213 |
- goto Exit;
|
|
214 |
- |
|
215 |
- stream->memory = memory;
|
|
216 |
- |
|
217 |
- if ( args->flags & FT_OPEN_MEMORY )
|
|
215 |
+ if ( mode == FT_OPEN_MEMORY )
|
|
218 | 216 |
{
|
219 | 217 |
/* create a memory-based stream */
|
218 |
+ if ( FT_NEW( stream ) )
|
|
219 |
+ goto Exit;
|
|
220 |
+ |
|
220 | 221 |
FT_Stream_OpenMemory( stream,
|
221 | 222 |
(const FT_Byte*)args->memory_base,
|
222 | 223 |
(FT_ULong)args->memory_size );
|
... | ... | @@ -224,33 +225,40 @@ |
224 | 225 |
|
225 | 226 |
#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
|
226 | 227 |
|
227 |
- else if ( args->flags & FT_OPEN_PATHNAME )
|
|
228 |
+ else if ( mode == FT_OPEN_PATHNAME )
|
|
228 | 229 |
{
|
229 | 230 |
/* create a normal system stream */
|
231 |
+ if ( FT_NEW( stream ) )
|
|
232 |
+ goto Exit;
|
|
233 |
+ |
|
230 | 234 |
error = FT_Stream_Open( stream, args->pathname );
|
231 |
- stream->pathname.pointer = args->pathname;
|
|
235 |
+ if ( error )
|
|
236 |
+ FT_FREE( stream );
|
|
232 | 237 |
}
|
233 |
- else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
|
|
238 |
+ else if ( ( mode == FT_OPEN_STREAM ) && args->stream )
|
|
234 | 239 |
{
|
235 | 240 |
/* use an existing, user-provided stream */
|
236 | 241 |
|
237 | 242 |
/* in this case, we do not need to allocate a new stream object */
|
238 | 243 |
/* since the caller is responsible for closing it himself */
|
239 |
- FT_FREE( stream );
|
|
240 | 244 |
stream = args->stream;
|
245 |
+ error = FT_Err_Ok;
|
|
241 | 246 |
}
|
242 | 247 |
|
243 | 248 |
#endif
|
244 | 249 |
|
245 | 250 |
else
|
251 |
+ {
|
|
246 | 252 |
error = FT_THROW( Invalid_Argument );
|
253 |
+ if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
|
|
254 |
+ FT_Stream_Close( args->stream );
|
|
255 |
+ }
|
|
247 | 256 |
|
248 |
- if ( error )
|
|
249 |
- FT_FREE( stream );
|
|
250 |
- else
|
|
251 |
- stream->memory = memory; /* just to be certain */
|
|
252 |
- |
|
253 |
- *astream = stream;
|
|
257 |
+ if ( !error )
|
|
258 |
+ {
|
|
259 |
+ stream->memory = memory;
|
|
260 |
+ *astream = stream;
|
|
261 |
+ }
|
|
254 | 262 |
|
255 | 263 |
Exit:
|
256 | 264 |
return error;
|
... | ... | @@ -41,7 +41,8 @@ |
41 | 41 |
* file `ftbsdf.c` for more.
|
42 | 42 |
*
|
43 | 43 |
* * The basic idea of generating the SDF is taken from Viktor Chlumsky's
|
44 |
- * research paper.
|
|
44 |
+ * research paper. The paper explains both single and multi-channel
|
|
45 |
+ * SDF, however, this implementation only generates single-channel SDF.
|
|
45 | 46 |
*
|
46 | 47 |
* Chlumsky, Viktor: Shape Decomposition for Multi-channel Distance
|
47 | 48 |
* Fields. Master's thesis. Czech Technical University in Prague,
|
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 |
|
5 | 5 |
### Download test fonts
|
6 | 6 |
|
7 |
-Run the `tests/scripts/download-fonts.sh` script, which will
|
|
7 |
+Run the `tests/scripts/download-fonts.py` script, which will
|
|
8 | 8 |
download test fonts to the `tests/data/` directory first.
|
9 | 9 |
|
10 | 10 |
### Build the test programs
|
1 |
+#!/usr/bin/env python3
|
|
2 |
+ |
|
3 |
+"""Download test fonts used by the FreeType regression test programs.
|
|
4 |
+These will be copied to $FREETYPE/tests/data/ by default.
|
|
5 |
+"""
|
|
6 |
+ |
|
7 |
+import argparse
|
|
8 |
+import collections
|
|
9 |
+import hashlib
|
|
10 |
+import io
|
|
11 |
+import os
|
|
12 |
+import requests
|
|
13 |
+import sys
|
|
14 |
+import zipfile
|
|
15 |
+ |
|
16 |
+from typing import Callable, List, Optional, Tuple
|
|
17 |
+ |
|
18 |
+# The list of download items describing the font files to install.
|
|
19 |
+# Each download item is a dictionary with one of the following schemas:
|
|
20 |
+#
|
|
21 |
+# - File item:
|
|
22 |
+#
|
|
23 |
+# file_url
|
|
24 |
+# Type: URL string.
|
|
25 |
+# Required: Yes.
|
|
26 |
+# Description: URL to download the file from.
|
|
27 |
+#
|
|
28 |
+# install_name
|
|
29 |
+# Type: file name string
|
|
30 |
+# Required: No
|
|
31 |
+# Description: Installation name for the font file, only provided if it
|
|
32 |
+# must be different from the original URL's basename.
|
|
33 |
+#
|
|
34 |
+# hex_digest
|
|
35 |
+# Type: hexadecimal string
|
|
36 |
+# Required: No
|
|
37 |
+# Description: Digest of the input font file.
|
|
38 |
+#
|
|
39 |
+# - Zip items:
|
|
40 |
+#
|
|
41 |
+# These items correspond to one or more font files that are embedded in a
|
|
42 |
+# remote zip archive. Each entry has the following fields:
|
|
43 |
+#
|
|
44 |
+# zip_url
|
|
45 |
+# Type: URL string.
|
|
46 |
+# Required: Yes.
|
|
47 |
+# Description: URL to download the zip archive from.
|
|
48 |
+#
|
|
49 |
+# zip_files
|
|
50 |
+# Type: List of file entries (see below)
|
|
51 |
+# Required: Yes
|
|
52 |
+# Description: A list of entries describing a single font file to be
|
|
53 |
+# extracted from the archive
|
|
54 |
+#
|
|
55 |
+# Apart from that, some schemas are used for dictionaries used inside download
|
|
56 |
+# items:
|
|
57 |
+#
|
|
58 |
+# - File entries:
|
|
59 |
+#
|
|
60 |
+# These are dictionaries describing a single font file to extract from an archive.
|
|
61 |
+#
|
|
62 |
+# filename
|
|
63 |
+# Type: file path string
|
|
64 |
+# Required: Yes
|
|
65 |
+# Description: Path of source file, relative to the archive's top-level directory.
|
|
66 |
+#
|
|
67 |
+# install_name
|
|
68 |
+# Type: file name string
|
|
69 |
+# Required: No
|
|
70 |
+# Description: Installation name for the font file, only provided if it must be
|
|
71 |
+# different from the original filename value.
|
|
72 |
+#
|
|
73 |
+# hex_digest
|
|
74 |
+# Type: hexadecimal string
|
|
75 |
+# Required: No
|
|
76 |
+# Description: Digest of the input source file
|
|
77 |
+#
|
|
78 |
+_DOWNLOAD_ITEMS = [
|
|
79 |
+ {
|
|
80 |
+ "zip_url": "https://github.com/python-pillow/Pillow/files/6622147/As.I.Lay.Dying.zip",
|
|
81 |
+ "zip_files": [
|
|
82 |
+ {
|
|
83 |
+ "filename": "As I Lay Dying.ttf",
|
|
84 |
+ "install_name": "As.I.Lay.Dying.ttf",
|
|
85 |
+ "hex_digest": "ef146bbc2673b387",
|
|
86 |
+ },
|
|
87 |
+ ],
|
|
88 |
+ },
|
|
89 |
+]
|
|
90 |
+ |
|
91 |
+ |
|
92 |
+def digest_data(data: bytes):
|
|
93 |
+ """Compute the digest of a given input byte string, which are the first 8 bytes of its sha256 hash."""
|
|
94 |
+ m = hashlib.sha256()
|
|
95 |
+ m.update(data)
|
|
96 |
+ return m.digest()[:8]
|
|
97 |
+ |
|
98 |
+ |
|
99 |
+def check_existing(path: str, hex_digest: str):
|
|
100 |
+ """Return True if |path| exists and matches |hex_digest|."""
|
|
101 |
+ if not os.path.exists(path) or hex_digest is None:
|
|
102 |
+ return False
|
|
103 |
+ |
|
104 |
+ with open(path, "rb") as f:
|
|
105 |
+ existing_content = f.read()
|
|
106 |
+ |
|
107 |
+ return bytes.fromhex(hex_digest) == digest_data(existing_content)
|
|
108 |
+ |
|
109 |
+ |
|
110 |
+def install_file(content: bytes, dest_path: str):
|
|
111 |
+ """Write a byte string to a given destination file.
|
|
112 |
+ |
|
113 |
+ Args:
|
|
114 |
+ content: Input data, as a byte string
|
|
115 |
+ dest_path: Installation path
|
|
116 |
+ """
|
|
117 |
+ parent_path = os.path.dirname(dest_path)
|
|
118 |
+ if not os.path.exists(parent_path):
|
|
119 |
+ os.makedirs(parent_path)
|
|
120 |
+ |
|
121 |
+ with open(dest_path, "wb") as f:
|
|
122 |
+ f.write(content)
|
|
123 |
+ |
|
124 |
+ |
|
125 |
+def download_file(url: str, expected_digest: Optional[bytes] = None):
|
|
126 |
+ """Download a file from a given URL.
|
|
127 |
+ |
|
128 |
+ Args:
|
|
129 |
+ url: Input URL
|
|
130 |
+ expected_digest: Optional digest of the file
|
|
131 |
+ as a byte string
|
|
132 |
+ Returns:
|
|
133 |
+ URL content as binary string.
|
|
134 |
+ """
|
|
135 |
+ r = requests.get(url, allow_redirects=True)
|
|
136 |
+ content = r.content
|
|
137 |
+ if expected_digest is not None:
|
|
138 |
+ digest = digest_data(r.content)
|
|
139 |
+ if digest != expected_digest:
|
|
140 |
+ raise ValueError(
|
|
141 |
+ "%s has invalid digest %s (expected %s)"
|
|
142 |
+ % (url, digest.hex(), expected_digest.hex())
|
|
143 |
+ )
|
|
144 |
+ |
|
145 |
+ return content
|
|
146 |
+ |
|
147 |
+ |
|
148 |
+def extract_file_from_zip_archive(
|
|
149 |
+ archive: zipfile.ZipFile,
|
|
150 |
+ archive_name: str,
|
|
151 |
+ filepath: str,
|
|
152 |
+ expected_digest: Optional[bytes] = None,
|
|
153 |
+):
|
|
154 |
+ """Extract a file from a given zipfile.ZipFile archive.
|
|
155 |
+ |
|
156 |
+ Args:
|
|
157 |
+ archive: Input ZipFile objec.
|
|
158 |
+ archive_name: Archive name or URL, only used to generate a human-readable error
|
|
159 |
+ message.
|
|
160 |
+ filepath: Input filepath in archive.
|
|
161 |
+ expected_digest: Optional digest for the file.
|
|
162 |
+ Returns:
|
|
163 |
+ A new File instance corresponding to the extract file.
|
|
164 |
+ Raises:
|
|
165 |
+ ValueError if expected_digest is not None and does not match the extracted file.
|
|
166 |
+ """
|
|
167 |
+ file = archive.open(filepath)
|
|
168 |
+ if expected_digest is not None:
|
|
169 |
+ digest = digest_data(archive.open(filepath).read())
|
|
170 |
+ if digest != expected_digest:
|
|
171 |
+ raise ValueError(
|
|
172 |
+ "%s in zip archive at %s has invalid digest %s (expected %s)"
|
|
173 |
+ % (filepath, archive_name, digest.hex(), expected_digest.hex())
|
|
174 |
+ )
|
|
175 |
+ return file.read()
|
|
176 |
+ |
|
177 |
+ |
|
178 |
+def _get_and_install_file(
|
|
179 |
+ install_path: str,
|
|
180 |
+ hex_digest: Optional[str],
|
|
181 |
+ force_download: bool,
|
|
182 |
+ get_content: Callable[[], bytes],
|
|
183 |
+) -> bool:
|
|
184 |
+ if not force_download and hex_digest is not None and os.path.exists(install_path):
|
|
185 |
+ with open(install_path, "rb") as f:
|
|
186 |
+ content: bytes = f.read()
|
|
187 |
+ if bytes.fromhex(hex_digest) == digest_data(content):
|
|
188 |
+ return False
|
|
189 |
+ |
|
190 |
+ content = get_content()
|
|
191 |
+ install_file(content, install_path)
|
|
192 |
+ return True
|
|
193 |
+ |
|
194 |
+ |
|
195 |
+def download_and_install_item(
|
|
196 |
+ item: dict, install_dir: str, force_download: bool
|
|
197 |
+) -> List[Tuple[str, bool]]:
|
|
198 |
+ """Download and install one item.
|
|
199 |
+ |
|
200 |
+ Args:
|
|
201 |
+ item: Download item as a dictionary, see above for schema.
|
|
202 |
+ install_dir: Installation directory.
|
|
203 |
+ force_download: Set to True to force download and installation, even if
|
|
204 |
+ the font file is already installed with the right content.
|
|
205 |
+ |
|
206 |
+ Returns:
|
|
207 |
+ A list of (install_name, status) tuples, where 'install_name' is the file's
|
|
208 |
+ installation name under 'install_dir', and 'status' is a boolean that is True
|
|
209 |
+ to indicate that the file was downloaded and installed, or False to indicate that
|
|
210 |
+ the file is already installed with the right content.
|
|
211 |
+ """
|
|
212 |
+ if "file_url" in item:
|
|
213 |
+ file_url = item["file_url"]
|
|
214 |
+ install_name = item.get("install_name", os.path.basename(file_url))
|
|
215 |
+ install_path = os.path.join(install_dir, install_name)
|
|
216 |
+ hex_digest = item.get("hex_digest")
|
|
217 |
+ |
|
218 |
+ def get_content():
|
|
219 |
+ return download_file(file_url, hex_digest)
|
|
220 |
+ |
|
221 |
+ status = _get_and_install_file(
|
|
222 |
+ install_path, hex_digest, force_download, get_content
|
|
223 |
+ )
|
|
224 |
+ return [(install_name, status)]
|
|
225 |
+ |
|
226 |
+ if "zip_url" in item:
|
|
227 |
+ # One or more files from a zip archive.
|
|
228 |
+ archive_url = item["zip_url"]
|
|
229 |
+ archive = zipfile.ZipFile(io.BytesIO(download_file(archive_url)))
|
|
230 |
+ |
|
231 |
+ result = []
|
|
232 |
+ for f in item["zip_files"]:
|
|
233 |
+ filename = f["filename"]
|
|
234 |
+ install_name = f.get("install_name", filename)
|
|
235 |
+ hex_digest = f.get("hex_digest")
|
|
236 |
+ |
|
237 |
+ def get_content():
|
|
238 |
+ return extract_file_from_zip_archive(
|
|
239 |
+ archive,
|
|
240 |
+ archive_url,
|
|
241 |
+ filename,
|
|
242 |
+ bytes.fromhex(hex_digest) if hex_digest else None,
|
|
243 |
+ )
|
|
244 |
+ |
|
245 |
+ status = _get_and_install_file(
|
|
246 |
+ os.path.join(install_dir, install_name),
|
|
247 |
+ hex_digest,
|
|
248 |
+ force_download,
|
|
249 |
+ get_content,
|
|
250 |
+ )
|
|
251 |
+ result.append((install_name, status))
|
|
252 |
+ |
|
253 |
+ return result
|
|
254 |
+ |
|
255 |
+ else:
|
|
256 |
+ raise ValueError("Unknown download item schema: %s" % item)
|
|
257 |
+ |
|
258 |
+ |
|
259 |
+def main():
|
|
260 |
+ parser = argparse.ArgumentParser(description=__doc__)
|
|
261 |
+ |
|
262 |
+ # Assume this script is under tests/scripts/ and tests/data/
|
|
263 |
+ # is the default installation directory.
|
|
264 |
+ install_dir = os.path.normpath(
|
|
265 |
+ os.path.join(os.path.dirname(__file__), "..", "data")
|
|
266 |
+ )
|
|
267 |
+ |
|
268 |
+ parser.add_argument(
|
|
269 |
+ "--force",
|
|
270 |
+ action="store_true",
|
|
271 |
+ default=False,
|
|
272 |
+ help="Force download and installation of font files",
|
|
273 |
+ )
|
|
274 |
+ |
|
275 |
+ parser.add_argument(
|
|
276 |
+ "--install-dir",
|
|
277 |
+ default=install_dir,
|
|
278 |
+ help="Specify installation directory [%s]" % install_dir,
|
|
279 |
+ )
|
|
280 |
+ |
|
281 |
+ args = parser.parse_args()
|
|
282 |
+ |
|
283 |
+ for item in _DOWNLOAD_ITEMS:
|
|
284 |
+ for install_name, status in download_and_install_item(
|
|
285 |
+ item, args.install_dir, args.force
|
|
286 |
+ ):
|
|
287 |
+ print("%s %s" % (install_name, "INSTALLED" if status else "UP-TO-DATE"))
|
|
288 |
+ |
|
289 |
+ return 0
|
|
290 |
+ |
|
291 |
+ |
|
292 |
+if __name__ == "__main__":
|
|
293 |
+ sys.exit(main())
|
1 |
-#!/usr/bin/bash
|
|
2 |
-# Download test fonts used by the FreeType regression test programs.
|
|
3 |
-# These will be copied to $FREETYPE/tests/data/
|
|
4 |
-# Each font file contains an 8-hexchar prefix corresponding to its md5sum
|
|
5 |
- |
|
6 |
-set -e
|
|
7 |
- |
|
8 |
-export LANG=C
|
|
9 |
-export LC_ALL=C
|
|
10 |
- |
|
11 |
-PROGDIR=$(dirname "$0")
|
|
12 |
-PROGNAME=$(basename "$0")
|
|
13 |
- |
|
14 |
-# Download a file from a given URL
|
|
15 |
-#
|
|
16 |
-# $1: URL
|
|
17 |
-# $2: Destination directory
|
|
18 |
-# $3: If not empty, destination file name. Default is to take
|
|
19 |
-# the URL's basename.
|
|
20 |
-#
|
|
21 |
-download_file () {
|
|
22 |
- local URL=$1
|
|
23 |
- local DST_DIR=$2
|
|
24 |
- local DST_FILE=$3
|
|
25 |
- if [[ -z "$DST_FILE" ]]; then
|
|
26 |
- DST_FILE=$(basename "$URL")
|
|
27 |
- fi
|
|
28 |
- echo "URL: $URL"
|
|
29 |
- wget -q -O "$DST_DIR/$DST_FILE" "$URL"
|
|
30 |
-}
|
|
31 |
- |
|
32 |
-# $1: URL
|
|
33 |
-# $2: Destination directory
|
|
34 |
-# $3+: Optional file list, otherwise the full archive is extracted to $2
|
|
35 |
-download_and_extract_zip () {
|
|
36 |
- local URL=$1
|
|
37 |
- local DST_DIR=$2
|
|
38 |
- shift
|
|
39 |
- shift
|
|
40 |
- TEMP_DST_DIR=$(mktemp -d)
|
|
41 |
- TEMP_DST_NAME="a.zip"
|
|
42 |
- download_file "$URL" "$TEMP_DST_DIR" "$TEMP_DST_NAME"
|
|
43 |
- unzip -qo "$TEMP_DST_DIR/$TEMP_DST_NAME" -d "$DST_DIR" "$@"
|
|
44 |
- rm -rf "$TEMP_DST_DIR"
|
|
45 |
-}
|
|
46 |
- |
|
47 |
-# $1: File path
|
|
48 |
-# $2: Expected md5sum
|
|
49 |
-md5sum_check () {
|
|
50 |
- local FILE=$1
|
|
51 |
- local EXPECTED=$2
|
|
52 |
- local HASH=$(md5sum "$FILE" | cut -d" " -f1)
|
|
53 |
- if [[ "$EXPECTED" != "$HASH" ]]; then
|
|
54 |
- echo "$FILE: Invalid md5sum $HASH expected $EXPECTED"
|
|
55 |
- return 1
|
|
56 |
- fi
|
|
57 |
-}
|
|
58 |
- |
|
59 |
-INSTALL_DIR=$(cd $PROGDIR/.. && pwd)/data
|
|
60 |
- |
|
61 |
-mkdir -p "$INSTALL_DIR"
|
|
62 |
- |
|
63 |
-# See https://gitlab.freedesktop.org/freetype/freetype/-/issues/1063
|
|
64 |
-download_and_extract_zip "https://github.com/python-pillow/Pillow/files/6622147/As.I.Lay.Dying.zip" "$INSTALL_DIR"
|
|
65 |
-mv "$INSTALL_DIR/As I Lay Dying.ttf" "$INSTALL_DIR/As.I.Lay.Dying.ttf"
|
|
66 |
-md5sum_check "$INSTALL_DIR/As.I.Lay.Dying.ttf" e153d60e66199660f7cfe99ef4705ad7
|