Compare commits

...

61 Commits

Author SHA1 Message Date
57a643ae75 Merge remote-tracking branch 'upstream/master' 2024-06-21 12:23:04 +03:00
Alexei Podtelezhnikov
044d142be7 Use unsigned tags FT_Outline.
This change comes along with 2a7bb4596f56 ans is only meant to reduce
pointer casting in the code.

* include/freetype/ftimage.h (FT_Outline): Do it.
* src/*: Update `FT_Outline` users.
2024-06-20 22:16:51 -04:00
Ben Wagner
b1cbcb2045 [ttgxvar] Avoid "applying zero offset to null pointer"
In C it is undefined behavior to do arithmetic on a null pointer, including
adding zero. When using NotoSansKhmer[wdth,wght].ttf UBSAN produces a report
like

ttgxvar.c:1052:31: runtime error: applying zero offset to null pointer

when adding zero to `varData->deltaSet` (which is null) to produce `bytes`.
Protect against all the potential issues of this kind by returning early if
`varData->regionIdxCount == 0`.

* src/truetype/ttgxvar.c (tt_var_get_item_delta): early return on no regions
2024-06-21 01:41:40 +00:00
Alexei Podtelezhnikov
2a7bb4596f Use unsigned point and contour indexing in FT_Outline.
This doubles the number or allowed points, see
    https://github.com/harfbuzz/harfbuzz/issues/4752

Although it is hardly practical to use more than 32767 points,
other font engines seem to support it.

* docs/CHANGES: Announce it.
* include/freetype/ftimage.h (FT_Outline): Do it and update limits.
* src/*: Update `FT_Outline` users.
2024-06-20 20:49:56 -04:00
Alexei Podtelezhnikov
2b9fdec5fa * src/pfr/pfrgload.c (pfr_glyph_curve_to): Avoid casting. 2024-06-19 21:38:58 -04:00
Alexei Podtelezhnikov
7a753c9653 * src/base/ftgloadr.c (FT_GlyphLoader_Prepare): Minor refactoring. 2024-06-18 21:14:58 -04:00
Alexei Podtelezhnikov
93a067e312 [base, autofit, psaux] Remove unnecessary casting.
* src/autofit/afhints.c (af_glyph_hints_reload): Remove (short) casting.
* src/base/ftgloadr.c (FT_GlyphLoader_Add): Ditto.
* src/psaux/psobjs.c ({t1,cff,ps}_builder_{add,close}_contour): Ditto.
2024-06-18 17:48:41 +00:00
Alexei Podtelezhnikov
deba7feb57 * include/freetype/ftimage.h: Explain standard types. 2024-06-18 14:01:58 +00:00
Ben Wagner
d41a855aab [ttgxvar] Replace tabs with spaces
Also clarify comments around conversion and clamping.

* src/truetype/ttgxvar.c (ft_var_to_normalized): doit
2024-05-29 17:01:29 -04:00
Alexei Podtelezhnikov
7ff43d3e9f [truetype/GX] Consolidate memory allocations.
* src/truetype/ttgxvar.c (tt_face_vary_cvt, TT_Vary_Apply_Glyph_Deltas):
Allocate and split bigger memory blocks, avoid unnecessary zeroing,
do not copy shared tuples, revise error exit paths.
2024-05-26 19:40:20 -04:00
Alexei Podtelezhnikov
3416ac16d0 Whitespace. 2024-05-26 08:10:21 -04:00
Alexei Podtelezhnikov
b6dbbd9630 * src/truetype/ttgxvar.c (ft_var_apply_tuple): Reduce checks. 2024-05-24 17:38:14 +00:00
Alexei Podtelezhnikov
70299c924f Revert "[truetype] Reduce allocation scope."
This reverts commit 9ff4153cbfd60491f11bb56905ce6e20e94d23c7.
2024-05-23 22:50:32 -04:00
Alexei Podtelezhnikov
9ff4153cbf [truetype] Reduce allocation scope.
* src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Reduce scope
of `points_org` and 'points_out`.
2024-05-22 23:38:34 -04:00
Alexei Podtelezhnikov (Алексей Подтележников)
a498873652 * .gitlab-ci.yml: Disable UWP compilation. 2024-05-23 03:05:59 +00:00
Alexei Podtelezhnikov
42d406ab04 * include/freetype/internal/ftmemory.h (FT_MEM_DUP): Fix g++ error. 2024-05-22 21:08:34 -04:00
Alexei Podtelezhnikov
5f131cfd20 [cff, truetype] Validate variation axes immediately.
Instead of validating variation axes in every access, OpenType specs
suggest that peak = 0 be used to tag invalid ranges.  This implements
just that once during loading.

* src/cff/cffload.c (cff_blend_build_vector): Move the range checks...
(cff_vstore_load): ... here.
* src/truetype/ttgxvar.c (tt_var_get_item_delta): Ditto...
(tt_var_load_item_variation_store): ... ditto.
2024-05-21 16:24:43 -04:00
Alexei Podtelezhnikov
99be2b3154 [cff, truetype] Rearrange variation range checks.
This should achieve quicker results for common cases.

* src/cff/cffload.c (cff_blend_build_vector): Rearrange conditionals.
* src/truetype/ttgxvar.c (tt_var_get_item_delta): Ditto.
2024-05-21 18:26:09 +00:00
Alexei Podtelezhnikov
347276c1f6 * src/truetype/ttgxvar.c (tt_var_get_item_delta): Align with specs. 2024-05-21 13:12:45 +00:00
Alexei Podtelezhnikov
39f2fbf80c * src/truetype/ttgxvar.c (tt_var_get_item_delta): Minor refactoring. 2024-05-20 22:47:14 -04:00
Alexei Podtelezhnikov
4ccdc9f982 [cff] Optimize the blend vector computations.
* src/cff/cffload.c (cff_blend_build_vector): Use FT_MulDiv and skip
multiplying by 1.
2024-05-20 18:53:57 -04:00
Alexei Podtelezhnikov
b25265fe55 [bdf] Use concise macros.
* src/bdf/bdflib.c (bdf_create_property): Use FT_STRDUP.
(bdf_parse_glyphs_, bdf_parse_start_): Use FT_DUP for brevity.
2024-05-19 22:58:23 -04:00
Alexei Podtelezhnikov
026fd5d4f0 [cache] Use FT_DUP to duplicate data.
* src/cache/ftcsbits.c (ftc_sbit_copy_bitmap): Use concise FT_MEM_DUP.
2024-05-19 22:54:57 -04:00
Alexei Podtelezhnikov
d7cf931ac6 [truetype, type1] Use FT_DUP to duplicate data.
* src/truetype/ttgload.c (TT_Load_Simple_Glyph): Use concise FT_DUP.
* src/truetype/ttgxvar.c (TT_Get_MM_Var): Ditto.
* src/type1/t1load.c (parse_subrs): Ditto.
2024-05-19 22:48:13 -04:00
Alexei Podtelezhnikov
cdd3572e52 * builds/windows/ftsystem.c: Use _WINRT_DLL to check for UWP.
Fixes compilation using Windows GDK, reported by Erin Melucci.
2024-05-17 22:25:00 -04:00
Alexei Podtelezhnikov
68399b4244 * include/freetype/ftmm.h: Include freetype.h.
Reported by Ben Wagner, see !326.
2024-05-13 16:57:35 +00:00
Alexei Podtelezhnikov
b8db819768 [type1/MM] Safer handle arrays of different types.
* src/type1/t1load.c (parse_blend_design_map): Separately allocate...
(T1_Done_Blend): ... and free `design_points` and `blend_points`.
2024-05-12 22:38:38 -04:00
Alexei Podtelezhnikov
5b1cde804d * src/type1/t1load.c (parse_blend_design_map): Add risky cast. 2024-05-11 23:27:34 -04:00
Alexei Podtelezhnikov
e834786b34 * docs/CHANGES: Mention the last commit. 2024-05-11 23:25:37 -04:00
Alexei Podtelezhnikov
4a85db7e31 [type1/MM] Tighten headers.
* include/freetype/internal/t1types.h: Host PS_DesignMap and PS_Blend.
* include/freetype/ftmm.h: Host and document TT_MAX_MM_XXX.
* include/freetype/t1tables.h: Remove them from here.
2024-05-11 22:19:25 -04:00
Alexei Podtelezhnikov
b875924a6f * src/pshinter/pshrec.c (ps_hints_stem): Correct argument. 2024-05-10 23:01:23 -04:00
Ben Wagner
a46424228f [psaux] Fix location and type order in initializer
`T1_FIELD_ZERO` is used to zero initialize a `T1_FieldRec`.
`T1_FIELD_ZERO` is currently initilizing `T1_FieldRec::location` with a
`T1_FieldType` and `T1_FieldRec::type` with a `T1_FieldLocation`. This
was detected with `-Wenum-conversion`.

* include/freetype/internal/psaux.h (T1_FIELD_ZERO): correct order of
initalizers
2024-05-08 11:36:18 -04:00
Alexei Podtelezhnikov
1264b84c08 * include/freetype/internal/psaux.h: Fix g++ warning.
Reported by Hin-Tak Leung.
2024-05-07 23:35:59 -04:00
Ben Wagner
5858fa16ca [colr] Avoid overflow in range checks
In 32 bit builds `FT_ULong` is 32 bits and can silently overflow when a
large number is read into one and then it is summed or multiplied with
another number.  Checks for range overflow must be written so that they
themselves do not overflow.  Also ensure that the table_size is always the
first part of the range check and consistently use `<` or `<=`.

* src/sfnt/ttcolr.c (tt_face_load_colr): Avoid overflow.
(find_base_glyph_v1_record): Remove old work-around.

Bug: https://issues.chromium.org/issues/41495455
Bug: https://issues.chromium.org/issues/40945818
2024-05-08 05:01:16 +02:00
Werner Lemberg
2240e21cf5 .mailmap: Fix entry for Ben Wagner. 2024-05-06 21:53:24 +02:00
Alexei Podtelezhnikov
d0e3239f32 [sdf, bsdf] Use shared FT_SqrtFixed.
FT_SqrtFixed (95b0fe2a6dff) is faster and does not overflow.

* src/sdf/ftsdfcommin.h (square_root): Replace with a macro.
* src/sdf/ftsdfcommin.c (square_root): Remove function.
2024-05-06 13:39:06 +00:00
Alexei Podtelezhnikov
2edfd7e168 * src/autofit/aflatin.c (af_latin_metrics_scale_dim): Remove FT_ABS.
See
    https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=68679
2024-05-04 16:42:47 -04:00
Alexei Podtelezhnikov
7bd887f177 * src/sfnt/sfwoff2.c (woff2_open_font): Fix copy-paste typo. 2024-05-03 16:04:35 +00:00
Alexei Podtelezhnikov
3f28a6b6af [woff,woff2] Limit the number of tables and use FT_MSB.
The upper limit of 4095 is implied by the SFNT header format
where the multiplication by 16 would overflow without it.

* src/sfnt/sfwoff.c (woff_open_font): Updated.
* src/sfnt/sfwoff2.c (woff2_open_font): Ditto.
2024-05-03 15:44:57 +00:00
Ben Wanger
13d1180f45 [woff2] Disallow zero table font entries
The existing code already disallows zero table woff2 overall, but still
allows for individual CollectionFontEntry to create font instances with
zero tables. Such fonts are not useful so error early.

This also fixes an MSAN discovered issue where if a CollectionFontEntry
numTables is zero then the sfnt_header was not fully initialized.

* src/sfnt/sfwoff2.c (woff2_open_font): error on zero tables, always
initalize sfnt_header

Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=68384
2024-05-02 15:00:27 -04:00
Alexei Podtelezhnikov
4d50468478 [sfnt] Use faster macros in checksums.
* src/truetype/ttobjs.c (tt_synth_sfnt_checksum): Use FT_NEXT_XXX.
* src/sfnt/sfwoff2.c (compute_ULong_sum): Use macros.
2024-05-01 23:19:31 -04:00
Alexei Podtelezhnikov
13da904267 * src/sfnt/sfwoff2.c (compute_ULong_sum): Clean up. 2024-05-01 00:34:21 -04:00
Alexei Podtelezhnikov
2c9691e7c1 * docs/CHANGES: Updated. 2024-04-30 12:59:52 +00:00
Alexei Podtelezhnikov
5962d3c1b9 * src/cache/ftccache.c (FTC_Cache_RemoveFaceID): Remove nodes instantly. 2024-04-29 22:34:09 -04:00
Alexei Podtelezhnikov
a209e1adcd [cache] Remove unused node_reset.
* src/cache/ftcmru.h (FTC_MruListClassRec): Remove `node_reset` field.
* src/cache/ftcbasic.c (ftc_basic_{image,sbit}_family_class): Ditto.
* src/cache/ftcmanag.c (ftc_face_list_class): Ditto.
(ftc_size_node_reset): Remove function.
* src/cache/ftcglyph.h: Fix comment.
2024-04-29 17:54:30 -04:00
Alexei Podtelezhnikov
f8f0d1a1d9 * src/cache/ftcmru.c (FTC_MruList_New): Do not reset nodes.
Resetting of the size nodes can crash, if a parent face purge happens
simultaneously and destroys the node. It is safer to create a new node.
Fixes #1270, reopened with a separate issue.
2024-04-29 16:58:59 -04:00
Alexei Podtelezhnikov
1168b1b5b0 * src/cache/ftcimage.c (ftc_inode_weight): Formatting. 2024-04-27 20:44:01 -04:00
Alexei Podtelezhnikov
4e079f6357 Document the SDF spread further. 2024-04-27 20:07:36 -04:00
Alexei Podtelezhnikov
e2bcca40ca * include/freetype/ftdriver.h: s/truncated/clamped/. 2024-04-22 22:43:41 -04:00
Alexei Podtelezhnikov
ec46a50dac Improve SDF documentation. 2024-04-22 21:21:12 -04:00
Alexei Podtelezhnikov
982bc83849 [cache] Minor tweaks.
* src/cache/ftcimage.c (ftc_inode_free): Remove unnecessary check.
* src/cache/ftcmanag.c (FTC_Manager_Done): Do not zero before freeing.
2024-04-21 15:53:05 -04:00
Alexei Podtelezhnikov
5a3bfa92d9 * src/cache/ftcbasic.c: Cosmetic harmonization. 2024-04-20 23:28:17 -04:00
Alexei Podtelezhnikov
23e1d64556 [cache] Reduce type mismatches.
* src/cache/ftcbasic.c (FTC_BasicAttrRec): Match type of `load_flags`
to its main purpose in `FT_Load_Glyph`.
(FTC_ImageCache_Lookup{,Scaler},FTC_SBitCache_Lookup{,Scaler}): Updated.
2024-04-20 12:01:58 -04:00
Alexei Podtelezhnikov
9a2d6d97b2 * src/cache/{ftcbasic.c,ftccmap.c}: Use FTC_INLINE. 2024-04-19 14:45:39 -04:00
Alexei Podtelezhnikov
dbdcd75889 [cache] Tweak headers.
* src/cache/ftccback.h: Include less and move `ftc_node_destroy`...
* src/cache/ftccache.h: ... to here.
* src/cache/ftcmanag.c: Include less.
2024-04-19 14:02:43 -04:00
Alexei Podtelezhnikov
db83e9c0ec * src/cache/ftcglyph.c [!FTC_INLINE]: Fix compilation. 2024-04-18 23:23:13 -04:00
Alexei Podtelezhnikov
12adfc212b [cache] Improve MRU list management.
* src/cache/ftcmru.c (FTC_MruList_Remove): Cosmetic.
(FTC_MruList_New): Accept only valid changes.
* src/cache/ftcmanag.c (ftc_size_node_done):  Simplify.
2024-04-17 15:07:23 +00:00
Alexei Podtelezhnikov
d091bca546 [cache] Fix error handling.
Manipulate the cache after a face is requested or a size is looked up
successfully. Fixes #1270.

* src/cache/ftcmanag.c (ftc_size_node_init, ftc_size_node_reset,
ftc_face_node_init): Check for errors before accepting a change.
* src/cache/ftcmru.c (FTC_MruList_New): Do nothing if reset fails.
2024-04-17 00:33:14 -04:00
Alexei Podtelezhnikov
b3a6a20a80 [smooth] Switch to vertical bisections.
With horizontal bisections, the smallest section is a whole single
scanline. Almost horizontal lines or other complex scanlines can
easily overflow the rendering pool. Switching to vertical bisections
splits the scanlines and should rule out the overflows.  Fixes #1269.

* src/smooth/ftgrays.c (gray_convert_glyph): Bisect vertically.
2024-04-14 15:37:57 -04:00
Alexei Podtelezhnikov
fff58f5424 * src/smooth/ftgrays.c (gray_convert_glyph): Refactor for convenience. 2024-04-14 15:12:31 -04:00
Alexei Podtelezhnikov
674d629b5e [smooth] Store persistent clipping box.
* src/smooth/ftgrays.c (gray_TWorker, gray_raster_render): Add and set
the new structure field.
(gray_convert_glyph): Use it.
2024-04-14 13:06:01 -04:00
51 changed files with 641 additions and 860 deletions

@ -54,17 +54,7 @@ variables:
# Make sure meson is up to date so we don't need to rebuild the image
# with each release.
- pip3 install -U 'meson==0.59.*'
- pip3 install --upgrade certifi
- pip3 install -U ninja
# Generate a UWP cross-file in case it's used
- $PSDefaultParameterValues['Out-File:Encoding'] = 'ASCII'
- echo "[binaries]" > uwp-crossfile.meson
- echo "c = 'cl'" >> uwp-crossfile.meson
- echo "strip = ['true']" >> uwp-crossfile.meson
- echo "[built-in options]" >> uwp-crossfile.meson
- echo "c_args = ['-DWINAPI_FAMILY=WINAPI_FAMILY_APP', '-DUNICODE', '-D_WIN32_WINNT=0x0A00', '-we4013']" >> uwp-crossfile.meson
- echo "c_winlibs = ['windowsapp.lib']" >> uwp-crossfile.meson
script:
# For some reason, options are separated by newlines instead of spaces,
# so we have to replace them first.
@ -75,10 +65,12 @@ variables:
# script. Environment variables substitutions is done by PowerShell
# before calling `cmd.exe`, that's why we use `$env:FOO` instead of
# `%FOO%`.
- cmd.exe /C "C:\BuildTools\Common7\Tools\VsDevCmd.bat -host_arch=amd64 -arch=$env:ARCH $env:VS_UWP &&
meson setup build $env:MESON_ARGS_WINDOWS $env:MESON_ARGS_UWP &&
meson compile --verbose -C build
$env:MESON_WINDOWS_TESTS"
- cmd.exe /C "C:\BuildTools\Common7\Tools\VsDevCmd.bat -host_arch=amd64 -arch=$env:ARCH &&
meson setup build $env:MESON_ARGS_WINDOWS &&
meson compile --verbose -C build &&
meson test -C build &&
meson test -C build --benchmark"
.build windows msbuild:
extends: '.build windows common'
@ -106,20 +98,11 @@ windows meson vs2019 amd64:
extends: '.build windows meson'
variables:
ARCH: 'amd64'
MESON_WINDOWS_TESTS: '&& meson test -C build && meson test -C build --benchmark'
windows meson vs2019 x86:
extends: '.build windows meson'
variables:
ARCH: 'x86'
MESON_WINDOWS_TESTS: '&& meson test -C build && meson test -C build --benchmark'
windows meson vs2019 amd64 uwp:
extends: '.build windows meson'
variables:
ARCH: 'amd64'
VS_UWP: '-app_platform=UWP'
MESON_ARGS_UWP: '--cross-file uwp-crossfile.meson -Dc_winlibs="windowsapp.lib"'
windows msbuild vs2019 amd64:
extends: '.build windows msbuild'

@ -19,7 +19,7 @@ Anurag Thakur (अनुराग ठाकुर) <anuthadev@gmail.com>
David Turner <david@freetype.org> <david.turner.dev@gmail.com>
David Turner <david@freetype.org> <digit@google.com>
Anuj Verma (अनुज वर्मा) <anujv@iitbhilai.ac.in>
Ben Wagner <bungeman@gmail.com> Bungeman <bungeman@gmail.com>
Ben Wagner <bungeman@gmail.com>
Ben Wagner <bungeman@gmail.com> <bungeman@google.com>
Ben Wagner <bungeman@gmail.com> <bungeman@chromium.org>
Nikolaus Waxweiler <madigens@gmail.com> <nikolaus.waxweiler@daltonmaag.com>

@ -196,8 +196,8 @@
}
/* non-desktop Universal Windows Platform */
#if defined( WINAPI_FAMILY ) && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP
/* support for Universal Windows Platform UWP, formerly WinRT */
#ifdef _WINRT_DLL
#define PACK_DWORD64( hi, lo ) ( ( (DWORD64)(hi) << 32 ) | (DWORD)(lo) )
@ -248,10 +248,11 @@
dwCreationDisposition, &createExParams );
}
#endif
#endif /* _WINRT_DLL */
#if defined( _WIN32_WCE )
/* support for Windows CE */
#ifdef _WIN32_WCE
/* malloc.h provides implementation of alloca()/_alloca() */
#include <malloc.h>
@ -291,9 +292,9 @@
dwFlagsAndAttributes, hTemplateFile );
}
#endif
#endif /* _WIN32_WCE */
/* support for really old Windows */
#if defined( _WIN32_WCE ) || defined ( _WIN32_WINDOWS ) || \
!defined( _WIN32_WINNT ) || _WIN32_WINNT <= 0x0400
@ -311,7 +312,7 @@
return TRUE;
}
#endif
#endif /* _WIN32_WCE || _WIN32_WINDOWS || _WIN32_WINNT <= 0x0400 */
/* documentation is in ftobjs.h */

@ -1,11 +1,21 @@
CHANGES BETWEEN 2.13.2 and 2.13.3 (202Y-Mmm-DD)
CHANGES BETWEEN 2.13.2 and 2.13.3 (2024-Mmm-DD)
I. IMPORTANT BUG FIXES
I. IMPORTANT CHANGES
- Some fields in the `FT_Outline` structure have been changed
from signed to unsigned type, which better reflects the actual
usage. It is also an additional means to protect against
malformed input.
II. IMPORTANT BUG FIXES
- Rare double-free crashes in the cache subsystem have been fixed.
- Excessive stack allocation in the autohinter has been fixed.
II. MISCELLANEOUS
III. MISCELLANEOUS
- The B/W rasterizer has received a major upkeep that resulted in
large performance improvement. The rendering speed has increased
@ -21,6 +31,10 @@ CHANGES BETWEEN 2.13.2 and 2.13.3 (202Y-Mmm-DD)
Code contributed by David Saltzman <davidbsaltzman@gmail.com>.
- The internal structures `PS_DesignMap` and `PS_Blend` related to
parsing of old Multiple Masters fonts have been removed from the
public header file `t1tables.h`.
======================================================================

@ -3771,87 +3771,18 @@ FT_BEGIN_HEADER
* pixels and use the @FT_PIXEL_MODE_LCD_V mode.
*
* FT_RENDER_MODE_SDF ::
* This mode corresponds to 8-bit, single-channel signed distance field
* (SDF) bitmaps. Each pixel in the SDF grid is the value from the
* pixel's position to the nearest glyph's outline. The distances are
* calculated from the center of the pixel and are positive if they are
* filled by the outline (i.e., inside the outline) and negative
* otherwise. Check the note below on how to convert the output values
* to usable data.
* The positive (unsigned) 8-bit bitmap values can be converted to the
* single-channel signed distance field (SDF) by subtracting 128, with
* the positive and negative results corresponding to the inside and
* the outside of a glyph contour, respectively. The distance units are
* arbitrarily determined by an adjustable @spread property.
*
* @note:
* The selected render mode only affects vector glyphs of a font.
* The selected render mode only affects scalable vector glyphs of a font.
* Embedded bitmaps often have a different pixel mode like
* @FT_PIXEL_MODE_MONO. You can use @FT_Bitmap_Convert to transform them
* into 8-bit pixmaps.
*
* For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized
* distances that are packed into unsigned 8-bit values. To get pixel
* values in floating point representation use the following pseudo-C
* code for the conversion.
*
* ```
* // Load glyph and render using FT_RENDER_MODE_SDF,
* // then use the output buffer as follows.
*
* ...
* FT_Byte buffer = glyph->bitmap->buffer;
*
*
* for pixel in buffer
* {
* // `sd` is the signed distance and `spread` is the current spread;
* // the default spread is 2 and can be changed.
*
* float sd = (float)pixel - 128.0f;
*
*
* // Convert to pixel values.
* sd = ( sd / 128.0f ) * spread;
*
* // Store `sd` in a buffer or use as required.
* }
*
* ```
*
* FreeType has two rasterizers for generating SDF, namely:
*
* 1. `sdf` for generating SDF directly from glyph's outline, and
*
* 2. `bsdf` for generating SDF from rasterized bitmaps.
*
* Depending on the glyph type (i.e., outline or bitmap), one of the two
* rasterizers is chosen at runtime and used for generating SDFs. To
* force the use of `bsdf` you should render the glyph with any of the
* FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
* then re-render with `FT_RENDER_MODE_SDF`.
*
* There are some issues with stability and possible failures of the SDF
* renderers (specifically `sdf`).
*
* 1. The `sdf` rasterizer is sensitive to really small features (e.g.,
* sharp turns that are less than 1~pixel) and imperfections in the
* glyph's outline, causing artifacts in the final output.
*
* 2. The `sdf` rasterizer has limited support for handling intersecting
* contours and *cannot* handle self-intersecting contours whatsoever.
* Self-intersection happens when a single connected contour
* intersects itself at some point; having these in your font
* definitely poses a problem to the rasterizer and cause artifacts,
* too.
*
* 3. Generating SDF for really small glyphs may result in undesirable
* output; the pixel grid (which stores distance information) becomes
* too coarse.
*
* 4. Since the output buffer is normalized, precision at smaller spreads
* is greater than precision at larger spread values because the
* output range of [0..255] gets mapped to a smaller SDF range. A
* spread of~2 should be sufficient in most cases.
*
* Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
* which is more stable than the `sdf` rasterizer in general.
*
*/
typedef enum FT_Render_Mode_
{

@ -817,6 +817,80 @@ FT_BEGIN_HEADER
* 2.5
*/
/**************************************************************************
*
* @property:
* spread
*
* @description:
* This property of the 'sdf' and 'bsdf' renderers defines how the signed
* distance field (SDF) is represented in the output bitmap. The output
* values are calculated as follows, '128 * ( SDF / spread + 1 )', with
* the result clamped to the 8-bit range [0..255]. Therefore, 'spread'
* is also the maximum euclidean distance from the edge after which the
* values are clamped. The spread is specified in pixels with the
* default value of 8. For accurate SDF texture mapping (interpolation),
* the spread should be large enough to accommodate the target grid unit.
*
* @example:
* The following example code demonstrates how to set the SDF spread
* (omitting the error handling).
*
* ```
* FT_Library library;
* FT_Int spread = 2;
*
*
* FT_Init_FreeType( &library );
*
* FT_Property_Set( library, "sdf", "spread", &spread );
* ```
*
* @note
* FreeType has two rasterizers for generating SDF, namely:
*
* 1. `sdf` for generating SDF directly from glyph's outline, and
*
* 2. `bsdf` for generating SDF from rasterized bitmaps.
*
* Depending on the glyph type (i.e., outline or bitmap), one of the two
* rasterizers is chosen at runtime and used for generating SDFs. To
* force the use of `bsdf` you should render the glyph with any of the
* FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
* then re-render with `FT_RENDER_MODE_SDF`.
*
* There are some issues with stability and possible failures of the SDF
* renderers (specifically `sdf`).
*
* 1. The `sdf` rasterizer is sensitive to really small features (e.g.,
* sharp turns that are less than 1~pixel) and imperfections in the
* glyph's outline, causing artifacts in the final output.
*
* 2. The `sdf` rasterizer has limited support for handling intersecting
* contours and *cannot* handle self-intersecting contours whatsoever.
* Self-intersection happens when a single connected contour
* intersects itself at some point; having these in your font
* definitely poses a problem to the rasterizer and cause artifacts,
* too.
*
* 3. Generating SDF for really small glyphs may result in undesirable
* output; the pixel grid (which stores distance information) becomes
* too coarse.
*
* 4. Since the output buffer is normalized, precision at smaller spreads
* is greater than precision at larger spread values because the
* output range of [0..255] gets mapped to a smaller SDF range. A
* spread of~2 should be sufficient in most cases.
*
* Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
* which is more stable than the `sdf` rasterizer in general.
*
* @since:
* 2.11
*/
/**************************************************************************
*
* @property:

@ -21,6 +21,10 @@
* Note: A 'raster' is simply a scan-line converter, used to render
* `FT_Outline`s into `FT_Bitmap`s.
*
* Note: This file can be used for STANDALONE_ compilation of raster (B/W)
* and smooth (anti-aliased) renderers. Therefore, it must rely on
* standard variable types only rather than aliases in fttypes.h.
*
*/
@ -342,14 +346,14 @@ FT_BEGIN_HEADER
*/
typedef struct FT_Outline_
{
short n_contours; /* number of contours in glyph */
short n_points; /* number of points in the glyph */
unsigned short n_contours; /* number of contours in glyph */
unsigned short n_points; /* number of points in the glyph */
FT_Vector* points; /* the outline's points */
char* tags; /* the points flags */
short* contours; /* the contour end points */
FT_Vector* points; /* the outline's points */
unsigned char* tags; /* the points flags */
unsigned short* contours; /* the contour end points */
int flags; /* outline masks */
int flags; /* outline masks */
} FT_Outline;
@ -357,8 +361,8 @@ FT_BEGIN_HEADER
/* Following limits must be consistent with */
/* FT_Outline.{n_contours,n_points} */
#define FT_OUTLINE_CONTOURS_MAX SHRT_MAX
#define FT_OUTLINE_POINTS_MAX SHRT_MAX
#define FT_OUTLINE_CONTOURS_MAX USHRT_MAX
#define FT_OUTLINE_POINTS_MAX USHRT_MAX
/**************************************************************************

@ -19,8 +19,13 @@
#ifndef FTMM_H_
#define FTMM_H_
#include <freetype/freetype.h>
#include <freetype/t1tables.h>
#ifdef FREETYPE_H
#error "freetype.h of FreeType 1 has been loaded!"
#error "Please fix the directory search order for header files"
#error "so that freetype.h of FreeType 2 is found first."
#endif
FT_BEGIN_HEADER
@ -53,6 +58,30 @@ FT_BEGIN_HEADER
*/
/**************************************************************************
*
* @enum:
* T1_MAX_MM_XXX
*
* @description:
* Multiple Masters limits as defined in their specifications.
*
* @values:
* T1_MAX_MM_AXIS ::
* The maximum number of Multiple Masters axes.
*
* T1_MAX_MM_DESIGNS ::
* The maximum number of Multiple Masters designs.
*
* T1_MAX_MM_MAP_POINTS ::
* The maximum number of elements in a design map.
*
*/
#define T1_MAX_MM_AXIS 4
#define T1_MAX_MM_DESIGNS 16
#define T1_MAX_MM_MAP_POINTS 20
/**************************************************************************
*
* @struct:

@ -371,8 +371,11 @@ extern "C++"
#define FT_STRDUP( dst, str ) \
FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) )
#define FT_MEM_DUP( dst, address, size ) \
(dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error )
#define FT_MEM_DUP( dst, address, size ) \
FT_ASSIGNP_INNER( dst, ft_mem_dup( memory, \
(address), \
(FT_ULong)(size), \
&error ) )
#define FT_DUP( dst, address, size ) \
FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) )

@ -225,6 +225,7 @@ FT_BEGIN_HEADER
typedef enum T1_FieldLocation_
{
T1_FIELD_LOCATION_NONE = 0,
T1_FIELD_LOCATION_CID_INFO,
T1_FIELD_LOCATION_FONT_DICT,
T1_FIELD_LOCATION_FONT_EXTRA,
@ -359,7 +360,12 @@ FT_BEGIN_HEADER
#define T1_FIELD_CALLBACK( _ident, _name, _dict ) \
T1_NEW_CALLBACK_FIELD( _ident, _name, _dict )
#define T1_FIELD_ZERO { 0, NULL, 0, 0, NULL, 0, 0, 0, 0, 0 }
#define T1_FIELD_ZERO \
{ \
0, \
NULL, T1_FIELD_LOCATION_NONE, T1_FIELD_TYPE_NONE, \
NULL, 0, 0, 0, 0, 0 \
}
/*************************************************************************/

@ -21,7 +21,7 @@
#define T1TYPES_H_
#include <freetype/t1tables.h>
#include <freetype/ftmm.h>
#include <freetype/internal/pshints.h>
#include <freetype/internal/ftserv.h>
#include <freetype/internal/fthash.h>
@ -137,6 +137,54 @@ FT_BEGIN_HEADER
} CID_SubrsRec, *CID_Subrs;
/* this structure is used to store the BlendDesignMap entry for an axis */
typedef struct PS_DesignMap_
{
FT_Byte num_points;
FT_Long* design_points;
FT_Fixed* blend_points;
} PS_DesignMapRec, *PS_DesignMap;
/* backward compatible definition */
typedef PS_DesignMapRec T1_DesignMap;
typedef struct PS_BlendRec_
{
FT_UInt num_designs;
FT_UInt num_axis;
FT_String* axis_names[T1_MAX_MM_AXIS];
FT_Fixed* design_pos[T1_MAX_MM_DESIGNS];
PS_DesignMapRec design_map[T1_MAX_MM_AXIS];
FT_Fixed* weight_vector;
FT_Fixed* default_weight_vector;
PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1];
PS_Private privates [T1_MAX_MM_DESIGNS + 1];
FT_ULong blend_bitflags;
FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1];
/* since 2.3.0 */
/* undocumented, optional: the default design instance; */
/* corresponds to default_weight_vector -- */
/* num_default_design_vector == 0 means it is not present */
/* in the font and associated metrics files */
FT_UInt default_design_vector[T1_MAX_MM_DESIGNS];
FT_UInt num_default_design_vector;
} PS_BlendRec, *PS_Blend;
/* backward compatible definition */
typedef PS_BlendRec T1_Blend;
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/

@ -1655,9 +1655,9 @@ FT_BEGIN_HEADER
{
FT_Memory memory;
FT_UShort max_points;
FT_Short max_contours;
FT_UShort max_contours;
FT_UShort n_points; /* number of points in zone */
FT_Short n_contours; /* number of contours */
FT_UShort n_contours; /* number of contours */
FT_Vector* org; /* original point coordinates */
FT_Vector* cur; /* current point coordinates */

@ -269,64 +269,6 @@ FT_BEGIN_HEADER
/* */
/* maximum number of Multiple Masters designs, as defined in the spec */
#define T1_MAX_MM_DESIGNS 16
/* maximum number of Multiple Masters axes, as defined in the spec */
#define T1_MAX_MM_AXIS 4
/* maximum number of elements in a design map */
#define T1_MAX_MM_MAP_POINTS 20
/* this structure is used to store the BlendDesignMap entry for an axis */
typedef struct PS_DesignMap_
{
FT_Byte num_points;
FT_Long* design_points;
FT_Fixed* blend_points;
} PS_DesignMapRec, *PS_DesignMap;
/* backward compatible definition */
typedef PS_DesignMapRec T1_DesignMap;
typedef struct PS_BlendRec_
{
FT_UInt num_designs;
FT_UInt num_axis;
FT_String* axis_names[T1_MAX_MM_AXIS];
FT_Fixed* design_pos[T1_MAX_MM_DESIGNS];
PS_DesignMapRec design_map[T1_MAX_MM_AXIS];
FT_Fixed* weight_vector;
FT_Fixed* default_weight_vector;
PS_FontInfo font_infos[T1_MAX_MM_DESIGNS + 1];
PS_Private privates [T1_MAX_MM_DESIGNS + 1];
FT_ULong blend_bitflags;
FT_BBox* bboxes [T1_MAX_MM_DESIGNS + 1];
/* since 2.3.0 */
/* undocumented, optional: the default design instance; */
/* corresponds to default_weight_vector -- */
/* num_default_design_vector == 0 means it is not present */
/* in the font and associated metrics files */
FT_UInt default_design_vector[T1_MAX_MM_DESIGNS];
FT_UInt num_default_design_vector;
} PS_BlendRec, *PS_Blend;
/* backward compatible definition */
typedef PS_BlendRec T1_Blend;
/**************************************************************************
*
* @struct:

@ -979,8 +979,8 @@
/* compute coordinates & Bezier flags, next and prev */
{
FT_Vector* vec = outline->points;
char* tag = outline->tags;
FT_Short endpoint = outline->contours[0];
FT_Byte* tag = outline->tags;
FT_UShort endpoint = outline->contours[0];
AF_Point end = points + endpoint;
AF_Point prev = end;
FT_Int contour_index = 0;
@ -1046,16 +1046,16 @@
/* set up the contours array */
{
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
short* end = outline->contours;
short idx = 0;
AF_Point* contour = hints->contours;
AF_Point* contour_limit = contour + hints->num_contours;
FT_UShort* end = outline->contours;
FT_Int idx = 0;
for ( ; contour < contour_limit; contour++, end++ )
{
contour[0] = points + idx;
idx = (short)( end[0] + 1 );
idx = *end + 1;
}
}
@ -1292,7 +1292,7 @@
AF_Point point = hints->points;
AF_Point limit = point + hints->num_points;
FT_Vector* vec = outline->points;
char* tag = outline->tags;
FT_Byte* tag = outline->tags;
for ( ; point < limit; point++, vec++, tag++ )

@ -1263,10 +1263,9 @@
max_height = FT_MAX( max_height, -Axis->blues[nn].descender );
}
dist = FT_ABS( FT_MulFix( max_height, new_scale - scale ) );
dist &= ~127;
dist = FT_MulFix( max_height, new_scale - scale );
if ( dist == 0 )
if ( -128 < dist && dist < 128 )
{
FT_TRACE5(( "af_latin_metrics_scale_dim:"
" x height alignment (style `%s'):\n",

@ -489,7 +489,7 @@
return FT_THROW( Invalid_Outline );
/* if outline is empty, return (0,0,0,0) */
if ( outline->n_points == 0 || outline->n_contours <= 0 )
if ( outline->n_points == 0 || outline->n_contours == 0 )
{
abbox->xMin = abbox->xMax = 0;
abbox->yMin = abbox->yMax = 0;

@ -355,34 +355,25 @@
FT_BASE_DEF( void )
FT_GlyphLoader_Add( FT_GlyphLoader loader )
{
FT_GlyphLoad base;
FT_GlyphLoad current;
FT_Int n_curr_contours;
FT_Int n_base_points;
FT_Int n;
FT_Outline* base;
FT_Outline* current;
FT_Int n;
if ( !loader )
return;
base = &loader->base;
current = &loader->current;
n_curr_contours = current->outline.n_contours;
n_base_points = base->outline.n_points;
base->outline.n_points =
(short)( base->outline.n_points + current->outline.n_points );
base->outline.n_contours =
(short)( base->outline.n_contours + current->outline.n_contours );
base->num_subglyphs += current->num_subglyphs;
base = &loader->base.outline;
current = &loader->current.outline;
/* adjust contours count in newest outline */
for ( n = 0; n < n_curr_contours; n++ )
current->outline.contours[n] =
(short)( current->outline.contours[n] + n_base_points );
for ( n = 0; n < current->n_contours; n++ )
current->contours[n] += base->n_points;
base->n_points += current->n_points;
base->n_contours += current->n_contours;
loader->base.num_subglyphs += loader->current.num_subglyphs;
/* prepare for another new glyph image */
FT_GlyphLoader_Prepare( loader );

@ -53,7 +53,7 @@
FT_Vector* point;
FT_Vector* limit;
char* tags;
FT_Byte* tags;
FT_Error error;
@ -332,8 +332,8 @@
FT_NEW_ARRAY( anoutline->contours, numContours ) )
goto Fail;
anoutline->n_points = (FT_Short)numPoints;
anoutline->n_contours = (FT_Short)numContours;
anoutline->n_points = (FT_UShort)numPoints;
anoutline->n_contours = (FT_UShort)numContours;
anoutline->flags |= FT_OUTLINE_OWNER;
return FT_Err_Ok;
@ -359,12 +359,14 @@
FT_Int n;
FT_TRACE5(( "FT_Outline_Check: contours = %d, points = %d\n",
n_contours, n_points ));
/* empty glyph? */
if ( n_points == 0 && n_contours == 0 )
return FT_Err_Ok;
/* check point and contour counts */
if ( n_points <= 0 || n_contours <= 0 )
if ( n_points == 0 || n_contours == 0 )
goto Bad;
end0 = -1;
@ -576,13 +578,13 @@
/* reverse tags table */
{
char* p = outline->tags + first;
char* q = outline->tags + last;
FT_Byte* p = outline->tags + first;
FT_Byte* q = outline->tags + last;
while ( p < q )
{
char swap;
FT_Byte swap;
swap = *p;

@ -711,7 +711,7 @@
{
FT_UInt count = border->num_points;
FT_Byte* read = border->tags;
FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points;
FT_Byte* write = outline->tags + outline->n_points;
for ( ; count > 0; count--, read++, write++ )
@ -727,10 +727,10 @@
/* copy contours */
{
FT_UInt count = border->num_points;
FT_Byte* tags = border->tags;
FT_Short* write = outline->contours + outline->n_contours;
FT_Short idx = (FT_Short)outline->n_points;
FT_UInt count = border->num_points;
FT_Byte* tags = border->tags;
FT_UShort* write = outline->contours + outline->n_contours;
FT_UShort idx = outline->n_points;
for ( ; count > 0; count--, tags++, idx++ )
@ -743,7 +743,7 @@
}
}
outline->n_points += (short)border->num_points;
outline->n_points += (FT_UShort)border->num_points;
FT_ASSERT( FT_Outline_Check( outline ) == 0 );
}
@ -2050,7 +2050,7 @@
FT_Vector* point;
FT_Vector* limit;
char* tags;
FT_Byte* tags;
FT_Error error;

@ -864,15 +864,9 @@
p = font->user_props + font->nuser_props;
n = ft_strlen( name ) + 1;
if ( n > FT_LONG_MAX )
return FT_THROW( Invalid_Argument );
if ( FT_QALLOC( p->name, n ) )
if ( FT_STRDUP( p->name, name ) )
goto Exit;
FT_MEM_COPY( (char *)p->name, name, n );
p->format = format;
p->builtin = 0;
p->value.atom = NULL; /* nothing is ever stored here */
@ -1442,11 +1436,9 @@
goto Exit;
}
if ( FT_QALLOC( p->glyph_name, slen + 1 ) )
if ( FT_DUP( p->glyph_name, s, slen + 1 ) )
goto Exit;
FT_MEM_COPY( p->glyph_name, s, slen + 1 );
p->flags |= BDF_GLYPH_;
FT_TRACE4(( DBGMSG1, lineno, s ));
@ -2051,9 +2043,8 @@
/* Allowing multiple `FONT' lines (which is invalid) doesn't hurt... */
FT_FREE( p->font->name );
if ( FT_QALLOC( p->font->name, slen + 1 ) )
if ( FT_DUP( p->font->name, s, slen + 1 ) )
goto Exit;
FT_MEM_COPY( p->font->name, s, slen + 1 );
/* If the font name is an XLFD name, set the spacing to the one in */
/* the font name. If there is no spacing fall back on the default. */

113
src/cache/ftcbasic.c vendored

@ -37,7 +37,7 @@
typedef struct FTC_BasicAttrRec_
{
FTC_ScalerRec scaler;
FT_UInt load_flags;
FT_Int32 load_flags;
} FTC_BasicAttrRec, *FTC_BasicAttrs;
@ -143,10 +143,9 @@
FT_Face face = size->face;
error = FT_Load_Glyph(
face,
gindex,
(FT_Int)family->attrs.load_flags | FT_LOAD_RENDER );
error = FT_Load_Glyph( face,
gindex,
family->attrs.load_flags | FT_LOAD_RENDER );
if ( !error )
*aface = face;
}
@ -176,9 +175,7 @@
{
face = size->face;
error = FT_Load_Glyph( face,
gindex,
(FT_Int)family->attrs.load_flags );
error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
if ( !error )
{
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
@ -246,7 +243,6 @@
ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */
ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */
NULL, /* FTC_MruNode_ResetFunc node_reset */
NULL /* FTC_MruNode_DoneFunc node_done */
},
@ -293,40 +289,24 @@
FT_Glyph *aglyph,
FTC_Node *anode )
{
FTC_BasicQueryRec query;
FTC_Node node = 0; /* make compiler happy */
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = NULL; /* make compiler happy */
FT_Offset hash;
/* some argument checks are delayed to `FTC_Cache_Lookup' */
/* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !aglyph )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
return FT_THROW( Invalid_Argument );
*aglyph = NULL;
if ( anode )
*anode = NULL;
/*
* Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
* but public `FT_ImageType->flags' is of type `FT_Int32'.
*
* On 16bit systems, higher bits of type->flags cannot be handled.
*/
#if 0xFFFFFFFFUL > FT_UINT_MAX
if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
FT_TRACE1(( "FTC_ImageCache_Lookup:"
" higher bits in load_flags 0x%lx are dropped\n",
(FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
#endif
*anode = NULL;
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
query.attrs.scaler.height = type->height;
query.attrs.load_flags = (FT_UInt)type->flags;
query.attrs.load_flags = type->flags;
query.attrs.scaler.pixel = 1;
query.attrs.scaler.x_res = 0; /* make compilers happy */
@ -334,7 +314,7 @@
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
#if 1 /* inlining is about 50% faster! */
#ifdef FTC_INLINE /* inlining is about 50% faster! */
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
ftc_gnode_compare,
@ -359,7 +339,6 @@
}
}
Exit:
return error;
}
@ -374,38 +353,35 @@
FT_Glyph *aglyph,
FTC_Node *anode )
{
FTC_BasicQueryRec query;
FTC_Node node = 0; /* make compiler happy */
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = NULL; /* make compiler happy */
FT_Offset hash;
/* some argument checks are delayed to `FTC_Cache_Lookup' */
/* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !aglyph || !scaler )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
return FT_THROW( Invalid_Argument );
*aglyph = NULL;
if ( anode )
*anode = NULL;
*anode = NULL;
/*
* Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
* Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32',
* but public `FT_Face->face_flags' is of type `FT_Long'.
*
* On long > int systems, higher bits of load_flags cannot be handled.
*/
#if FT_ULONG_MAX > FT_UINT_MAX
if ( load_flags > FT_UINT_MAX )
#if FT_ULONG_MAX > 0xFFFFFFFFUL
if ( load_flags > 0xFFFFFFFFUL )
FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
" higher bits in load_flags 0x%lx are dropped\n",
load_flags & ~((FT_ULong)FT_UINT_MAX) ));
load_flags & ~0xFFFFFFFFUL ));
#endif
query.attrs.scaler = scaler[0];
query.attrs.load_flags = (FT_UInt)load_flags;
query.attrs.load_flags = (FT_Int32)load_flags;
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
@ -427,7 +403,6 @@
}
}
Exit:
return error;
}
@ -445,7 +420,6 @@
sizeof ( FTC_BasicFamilyRec ),
ftc_basic_family_compare, /* FTC_MruNode_CompareFunc node_compare */
ftc_basic_family_init, /* FTC_MruNode_InitFunc node_init */
NULL, /* FTC_MruNode_ResetFunc node_reset */
NULL /* FTC_MruNode_DoneFunc node_done */
},
@ -495,36 +469,22 @@
{
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = 0; /* make compiler happy */
FTC_Node node = NULL; /* make compiler happy */
FT_Offset hash;
if ( anode )
*anode = NULL;
/* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !ansbit )
return FT_THROW( Invalid_Argument );
*ansbit = NULL;
/*
* Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
* but public `FT_ImageType->flags' is of type `FT_Int32'.
*
* On 16bit systems, higher bits of type->flags cannot be handled.
*/
#if 0xFFFFFFFFUL > FT_UINT_MAX
if ( (type->flags & (FT_ULong)FT_UINT_MAX) )
FT_TRACE1(( "FTC_ImageCache_Lookup:"
" higher bits in load_flags 0x%lx are dropped\n",
(FT_ULong)type->flags & ~((FT_ULong)FT_UINT_MAX) ));
#endif
if ( anode )
*anode = NULL;
query.attrs.scaler.face_id = type->face_id;
query.attrs.scaler.width = type->width;
query.attrs.scaler.height = type->height;
query.attrs.load_flags = (FT_UInt)type->flags;
query.attrs.load_flags = type->flags;
query.attrs.scaler.pixel = 1;
query.attrs.scaler.x_res = 0; /* make compilers happy */
@ -534,7 +494,7 @@
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
gindex / FTC_SBIT_ITEMS_PER_NODE;
#if 1 /* inlining is about 50% faster! */
#ifdef FTC_INLINE /* inlining is about 50% faster! */
FTC_GCACHE_LOOKUP_CMP( cache,
ftc_basic_family_compare,
ftc_snode_compare,
@ -578,34 +538,33 @@
{
FT_Error error;
FTC_BasicQueryRec query;
FTC_Node node = 0; /* make compiler happy */
FTC_Node node = NULL; /* make compiler happy */
FT_Offset hash;
if ( anode )
*anode = NULL;
/* other argument checks delayed to `FTC_Cache_Lookup' */
if ( !ansbit || !scaler )
return FT_THROW( Invalid_Argument );
return FT_THROW( Invalid_Argument );
*ansbit = NULL;
if ( anode )
*anode = NULL;
/*
* Internal `FTC_BasicAttr->load_flags' is of type `FT_UInt',
* Internal `FTC_BasicAttr->load_flags' is of type `FT_Int32',
* but public `FT_Face->face_flags' is of type `FT_Long'.
*
* On long > int systems, higher bits of load_flags cannot be handled.
*/
#if FT_ULONG_MAX > FT_UINT_MAX
if ( load_flags > FT_UINT_MAX )
#if FT_ULONG_MAX > 0xFFFFFFFFUL
if ( load_flags > 0xFFFFFFFFUL )
FT_TRACE1(( "FTC_ImageCache_LookupScaler:"
" higher bits in load_flags 0x%lx are dropped\n",
load_flags & ~((FT_ULong)FT_UINT_MAX) ));
load_flags & ~0xFFFFFFFFUL ));
#endif
query.attrs.scaler = scaler[0];
query.attrs.load_flags = (FT_UInt)load_flags;
query.attrs.load_flags = (FT_Int32)load_flags;
/* beware, the hash must be the same for all glyph ranges! */
hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +

33
src/cache/ftccache.c vendored

@ -544,7 +544,6 @@
FTC_FaceID face_id )
{
FTC_Manager manager = cache->manager;
FTC_Node frees = NULL;
FT_UFast count = cache->p;
FT_UFast i;
@ -557,41 +556,27 @@
for (;;)
{
FTC_Node node = *pnode;
FT_Bool list_changed = FALSE;
if ( !node )
break;
if ( cache->clazz.node_remove_faceid( node, face_id,
cache, &list_changed ) )
if ( cache->clazz.node_remove_faceid( node, face_id, cache, NULL ) )
{
*pnode = node->link;
node->link = frees;
frees = node;
*pnode = node->link;
manager->cur_weight -= cache->clazz.node_weight( node, cache );
ftc_node_mru_unlink( node, manager );
cache->clazz.node_free( node, cache );
cache->slack++;
}
else
pnode = &node->link;
}
}
/* remove all nodes in the free list */
while ( frees )
{
FTC_Node node;
node = frees;
frees = node->link;
manager->cur_weight -= cache->clazz.node_weight( node, cache );
ftc_node_mru_unlink( node, manager );
cache->clazz.node_free( node, cache );
cache->slack++;
}
ftc_cache_resize( cache );
}

@ -87,6 +87,10 @@ FT_BEGIN_HEADER
ftc_get_top_node_for_hash( ( cache ), ( hash ) )
#endif
FT_LOCAL( void )
ftc_node_destroy( FTC_Node node,
FTC_Manager manager );
/*************************************************************************/
/*************************************************************************/

10
src/cache/ftccback.h vendored

@ -19,11 +19,7 @@
#define FTCCBACK_H_
#include <freetype/ftcache.h>
#include "ftcmru.h"
#include "ftcimage.h"
#include "ftcmanag.h"
#include "ftcglyph.h"
#include "ftcsbits.h"
#include "ftccache.h"
FT_BEGIN_HEADER
@ -81,10 +77,6 @@ FT_BEGIN_HEADER
FT_LOCAL( void )
ftc_cache_done( FTC_Cache cache );
FT_LOCAL( void )
ftc_node_destroy( FTC_Node node,
FTC_Manager manager );
FT_END_HEADER
#endif /* FTCCBACK_H_ */

2
src/cache/ftccmap.c vendored

@ -264,7 +264,7 @@
hash = FTC_CMAP_HASH( face_id, (FT_UInt)cmap_index, char_code );
#if 1
#ifdef FTC_INLINE
FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
node, error );
#else

@ -180,7 +180,7 @@
query->gindex = gindex;
FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error );
FTC_MRULIST_LOOKUP( &gcache->families, query, query->family, error );
if ( !error )
{
FTC_Family family = query->family;
@ -193,7 +193,7 @@
error = FTC_Cache_Lookup( FTC_CACHE( gcache ), hash, query, anode );
if ( --family->num_nodes == 0 )
FTC_FAMILY_FREE( family, cache );
FTC_FAMILY_FREE( family, FTC_CACHE( gcache ) );
}
return error;
}

@ -65,7 +65,6 @@
* - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
* my_family_compare
* my_family_init
* my_family_reset (optional)
* my_family_done
*
* - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query

12
src/cache/ftcimage.c vendored

@ -34,11 +34,7 @@
FT_Memory memory = cache->memory;
if ( inode->glyph )
{
FT_Done_Glyph( inode->glyph );
inode->glyph = NULL;
}
FT_Done_Glyph( inode->glyph );
FTC_GNode_Done( FTC_GNODE( inode ), cache );
FT_FREE( inode );
@ -119,10 +115,9 @@
{
case FT_GLYPH_FORMAT_BITMAP:
{
FT_BitmapGlyph bitg;
FT_BitmapGlyph bitg = (FT_BitmapGlyph)glyph;
bitg = (FT_BitmapGlyph)glyph;
size = bitg->bitmap.rows * (FT_Offset)FT_ABS( bitg->bitmap.pitch ) +
sizeof ( *bitg );
}
@ -130,10 +125,9 @@
case FT_GLYPH_FORMAT_OUTLINE:
{
FT_OutlineGlyph outg;
FT_OutlineGlyph outg = (FT_OutlineGlyph)glyph;
outg = (FT_OutlineGlyph)glyph;
size = (FT_Offset)outg->outline.n_points *
( sizeof ( FT_Vector ) + sizeof ( FT_Byte ) ) +
(FT_Offset)outg->outline.n_contours * sizeof ( FT_Short ) +

55
src/cache/ftcmanag.c vendored

@ -22,7 +22,6 @@
#include <freetype/internal/ftdebug.h>
#include <freetype/ftsizes.h>
#include "ftccback.h"
#include "ftcerror.h"
@ -86,12 +85,10 @@
FT_Pointer data )
{
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
FT_Size size = node->size;
FT_UNUSED( data );
if ( size )
FT_Done_Size( size );
FT_Done_Size( node->size );
}
@ -118,32 +115,21 @@
FT_Pointer ftcscaler,
FT_Pointer ftcmanager )
{
FT_Error error;
FT_Size size;
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
FTC_Manager manager = (FTC_Manager)ftcmanager;
node->scaler = scaler[0];
error = ftc_scaler_lookup_size( manager, scaler, &size );
if ( !error )
{
node->size = size;
node->scaler = scaler[0];
}
return ftc_scaler_lookup_size( manager, scaler, &node->size );
}
FT_CALLBACK_DEF( FT_Error )
ftc_size_node_reset( FTC_MruNode ftcnode,
FT_Pointer ftcscaler,
FT_Pointer ftcmanager )
{
FTC_SizeNode node = (FTC_SizeNode)ftcnode;
FTC_Scaler scaler = (FTC_Scaler)ftcscaler;
FTC_Manager manager = (FTC_Manager)ftcmanager;
FT_Done_Size( node->size );
node->scaler = scaler[0];
return ftc_scaler_lookup_size( manager, scaler, &node->size );
return error;
}
@ -154,7 +140,6 @@
ftc_size_node_compare, /* FTC_MruNode_CompareFunc node_compare */
ftc_size_node_init, /* FTC_MruNode_InitFunc node_init */
ftc_size_node_reset, /* FTC_MruNode_ResetFunc node_reset */
ftc_size_node_done /* FTC_MruNode_DoneFunc node_done */
};
@ -231,23 +216,25 @@
FT_Pointer ftcface_id,
FT_Pointer ftcmanager )
{
FT_Error error;
FT_Face face;
FTC_FaceNode node = (FTC_FaceNode)ftcnode;
FTC_FaceID face_id = (FTC_FaceID)ftcface_id;
FTC_Manager manager = (FTC_Manager)ftcmanager;
FT_Error error;
node->face_id = face_id;
error = manager->request_face( face_id,
manager->library,
manager->request_data,
&node->face );
&face );
if ( !error )
{
/* destroy initial size object; it will be re-created later */
if ( node->face->size )
FT_Done_Size( node->face->size );
if ( face->size )
FT_Done_Size( face->size );
node->face = face;
node->face_id = face_id;
}
return error;
@ -294,7 +281,6 @@
ftc_face_node_compare, /* FTC_MruNode_CompareFunc node_compare */
ftc_face_node_init, /* FTC_MruNode_InitFunc node_init */
NULL, /* FTC_MruNode_ResetFunc node_reset */
ftc_face_node_done /* FTC_MruNode_DoneFunc node_done */
};
@ -435,18 +421,13 @@
{
cache->clazz.cache_done( cache );
FT_FREE( cache );
manager->caches[idx] = NULL;
}
}
manager->num_caches = 0;
/* discard faces and sizes */
FTC_MruList_Done( &manager->sizes );
FTC_MruList_Done( &manager->faces );
manager->library = NULL;
manager->memory = NULL;
FT_FREE( manager );
}

67
src/cache/ftcmru.c vendored

@ -238,52 +238,43 @@
{
FT_Error error;
FTC_MruNode node = NULL;
FTC_MruNode prev = NULL;
FT_Memory memory = list->memory;
if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
{
node = list->nodes->prev;
FT_ASSERT( node );
if ( list->clazz.node_reset )
{
FTC_MruNode_Up( &list->nodes, node );
error = list->clazz.node_reset( node, key, list->data );
if ( !error )
goto Exit;
}
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
}
/* zero new node in case of node_init failure */
else if ( FT_ALLOC( node, list->clazz.node_size ) )
if ( FT_ALLOC( node, list->clazz.node_size ) )
goto Exit;
error = list->clazz.node_init( node, key, list->data );
if ( error )
goto Fail;
{
prev = node;
node = NULL;
goto Clean;
}
else if ( list->max_nodes > 0 && list->num_nodes >= list->max_nodes )
prev = list->nodes->prev;
FTC_MruNode_Prepend( &list->nodes, node );
list->num_nodes++;
if ( !prev )
goto Exit;
FTC_MruNode_Remove( &list->nodes, prev );
list->num_nodes--;
Clean:
if ( list->clazz.node_done )
list->clazz.node_done( prev, list->data );
FT_FREE( prev );
Exit:
*anode = node;
return error;
Fail:
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
goto Exit;
}
@ -309,18 +300,16 @@
FTC_MruList_Remove( FTC_MruList list,
FTC_MruNode node )
{
FT_Memory memory = list->memory;
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
{
FT_Memory memory = list->memory;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
}
FT_FREE( node );
}

6
src/cache/ftcmru.h vendored

@ -95,11 +95,6 @@ FT_BEGIN_HEADER
FT_Pointer key,
FT_Pointer data );
typedef FT_Error
(*FTC_MruNode_ResetFunc)( FTC_MruNode node,
FT_Pointer key,
FT_Pointer data );
typedef void
(*FTC_MruNode_DoneFunc)( FTC_MruNode node,
FT_Pointer data );
@ -111,7 +106,6 @@ FT_BEGIN_HEADER
FTC_MruNode_CompareFunc node_compare;
FTC_MruNode_InitFunc node_init;
FTC_MruNode_ResetFunc node_reset;
FTC_MruNode_DoneFunc node_done;
} FTC_MruListClassRec;

@ -53,8 +53,7 @@
size = (FT_ULong)pitch * bitmap->rows;
if ( !FT_QALLOC( sbit->buffer, size ) )
FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
FT_MEM_DUP( sbit->buffer, bitmap->buffer, size );
return error;
}

@ -1202,17 +1202,21 @@
{
CFF_AxisCoords* axis = &region->axisList[j];
FT_Int16 start14, peak14, end14;
FT_Int start, peak, end;
if ( FT_READ_SHORT( start14 ) ||
FT_READ_SHORT( peak14 ) ||
FT_READ_SHORT( end14 ) )
if ( FT_READ_SHORT( start ) ||
FT_READ_SHORT( peak ) ||
FT_READ_SHORT( end ) )
goto Exit;
axis->startCoord = FT_fdot14ToFixed( start14 );
axis->peakCoord = FT_fdot14ToFixed( peak14 );
axis->endCoord = FT_fdot14ToFixed( end14 );
/* immediately tag invalid ranges with special peak = 0 */
if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
peak = 0;
axis->startCoord = FT_fdot14ToFixed( start );
axis->peakCoord = FT_fdot14ToFixed( peak );
axis->endCoord = FT_fdot14ToFixed( end );
}
}
@ -1495,44 +1499,31 @@
for ( j = 0; j < lenNDV; j++ )
{
CFF_AxisCoords* axis = &varRegion->axisList[j];
FT_Fixed axisScalar;
/* compute the scalar contribution of this axis; */
/* ignore invalid ranges */
if ( axis->startCoord > axis->peakCoord ||
axis->peakCoord > axis->endCoord )
axisScalar = FT_FIXED_ONE;
else if ( axis->startCoord < 0 &&
axis->endCoord > 0 &&
axis->peakCoord != 0 )
axisScalar = FT_FIXED_ONE;
/* peak of 0 means ignore this axis */
else if ( axis->peakCoord == 0 )
axisScalar = FT_FIXED_ONE;
/* compute the scalar contribution of this axis */
/* with peak of 0 used for invalid axes */
if ( axis->peakCoord == NDV[j] ||
axis->peakCoord == 0 )
continue;
/* ignore this region if coords are out of range */
else if ( NDV[j] < axis->startCoord ||
NDV[j] > axis->endCoord )
axisScalar = 0;
/* calculate a proportional factor */
else
else if ( NDV[j] <= axis->startCoord ||
NDV[j] >= axis->endCoord )
{
if ( NDV[j] == axis->peakCoord )
axisScalar = FT_FIXED_ONE;
else if ( NDV[j] < axis->peakCoord )
axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
axis->peakCoord - axis->startCoord );
else
axisScalar = FT_DivFix( axis->endCoord - NDV[j],
axis->endCoord - axis->peakCoord );
blend->BV[master] = 0;
break;
}
/* take product of all the axis scalars */
blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
/* adjust proportionally */
else if ( NDV[j] < axis->peakCoord )
blend->BV[master] = FT_MulDiv( blend->BV[master],
NDV[j] - axis->startCoord,
axis->peakCoord - axis->startCoord );
else /* NDV[j] > axis->peakCoord ) */
blend->BV[master] = FT_MulDiv( blend->BV[master],
axis->endCoord - NDV[j],
axis->endCoord - axis->peakCoord );
}
FT_TRACE4(( ", %f ",

@ -108,7 +108,7 @@
/* don't add empty contours */
if ( last >= first )
outline->contours[outline->n_contours++] = (short)last;
outline->contours[outline->n_contours++] = (FT_UShort)last;
glyph->path_begun = 0;
}
@ -178,8 +178,8 @@
error = FT_GLYPHLOADER_CHECK_POINTS( loader, 3, 0 );
if ( !error )
{
FT_Vector* vec = outline->points + outline->n_points;
FT_Byte* tag = (FT_Byte*)outline->tags + outline->n_points;
FT_Vector* vec = outline->points + outline->n_points;
FT_Byte* tag = outline->tags + outline->n_points;
vec[0] = *control1;
@ -189,7 +189,7 @@
tag[1] = FT_CURVE_TAG_CUBIC;
tag[2] = FT_CURVE_TAG_ON;
outline->n_points = (FT_Short)( outline->n_points + 3 );
outline->n_points += 3;
}
Exit:

@ -1624,7 +1624,7 @@
if ( builder->load_points )
{
FT_Vector* point = outline->points + outline->n_points;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
FT_Byte* control = outline->tags + outline->n_points;
point->x = FIXED_TO_INT( x );
@ -1677,8 +1677,7 @@
if ( !error )
{
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
outline->n_contours++;
}
@ -1740,7 +1739,7 @@
{
FT_Vector* p1 = outline->points + first;
FT_Vector* p2 = outline->points + outline->n_points - 1;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
FT_Byte* control = outline->tags + outline->n_points - 1;
/* `delete' last point only if it coincides with the first */
@ -1760,8 +1759,7 @@
outline->n_points--;
}
else
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
}
}
@ -1899,7 +1897,7 @@
if ( builder->load_points )
{
FT_Vector* point = outline->points + outline->n_points;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
FT_Byte* control = outline->tags + outline->n_points;
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
@ -1959,8 +1957,7 @@
if ( !error )
{
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
outline->n_contours++;
}
@ -2019,7 +2016,7 @@
{
FT_Vector* p1 = outline->points + first;
FT_Vector* p2 = outline->points + outline->n_points - 1;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
FT_Byte* control = outline->tags + outline->n_points - 1;
/* `delete' last point only if it coincides with the first */
@ -2039,8 +2036,7 @@
outline->n_points--;
}
else
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
}
}
@ -2188,7 +2184,7 @@
if ( builder->load_points )
{
FT_Vector* point = outline->points + outline->n_points;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
FT_Byte* control = outline->tags + outline->n_points;
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
@ -2267,8 +2263,7 @@
if ( !error )
{
if ( outline->n_contours > 0 )
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
outline->n_contours++;
}
@ -2327,7 +2322,7 @@
{
FT_Vector* p1 = outline->points + first;
FT_Vector* p2 = outline->points + outline->n_points - 1;
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
FT_Byte* control = outline->tags + outline->n_points - 1;
/* `delete' last point only if it coincides with the first */
@ -2347,8 +2342,7 @@
outline->n_points--;
}
else
outline->contours[outline->n_contours - 1] =
(short)( outline->n_points - 1 );
outline->contours[outline->n_contours - 1] = outline->n_points - 1;
}
}

@ -1118,7 +1118,7 @@
FT_UInt n;
PSH_Point point = glyph->points;
FT_Vector* vec = glyph->outline->points;
char* tags = glyph->outline->tags;
FT_Byte* tags = glyph->outline->tags;
for ( n = 0; n < glyph->num_points; n++ )
@ -1171,8 +1171,8 @@
FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) )
goto Exit;
glyph->num_points = (FT_UInt)outline->n_points;
glyph->num_contours = (FT_UInt)outline->n_contours;
glyph->num_points = outline->n_points;
glyph->num_contours = outline->n_contours;
{
FT_UInt first = 0, next, n;
@ -1186,7 +1186,7 @@
PSH_Point point;
next = (FT_UInt)outline->contours[n] + 1;
next = outline->contours[n] + 1;
count = next - first;
contour->start = points + first;

@ -806,7 +806,7 @@
ps_hints_stem( PS_Hints hints,
FT_UInt dimension,
FT_Int count,
FT_Long* stems )
FT_Pos* stems )
{
PS_Dimension dim;

@ -1598,7 +1598,7 @@
FT_Vector* points;
FT_Vector* point;
FT_Vector* limit;
char* tags;
FT_Byte* tags;
UInt tag; /* current point's state */
@ -2683,7 +2683,7 @@
return FT_THROW( Invalid_Outline );
/* return immediately if the outline is empty */
if ( outline->n_points == 0 || outline->n_contours <= 0 )
if ( outline->n_points == 0 || outline->n_contours == 0 )
return Raster_Err_Ok;
if ( !outline->contours || !outline->points )

@ -3837,7 +3837,7 @@
}
/* if the outline is empty, return */
if ( outline->n_points <= 0 || outline->n_contours <= 0 )
if ( outline->n_points == 0 || outline->n_contours == 0 )
goto Exit;
/* check whether the outline has valid fields */

@ -22,49 +22,6 @@
#include "ftsdfcommon.h"
/**************************************************************************
*
* common functions
*
*/
/*
* Original algorithm:
*
* https://github.com/chmike/fpsqrt
*
* Use this to compute the square root of a 16.16 fixed-point number.
*/
FT_LOCAL_DEF( FT_16D16 )
square_root( FT_16D16 val )
{
FT_ULong t, q, b, r;
r = (FT_ULong)val;
b = 0x40000000L;
q = 0;
while ( b > 0x40L )
{
t = q + b;
if ( r >= t )
{
r -= t;
q = t + b;
}
r <<= 1;
b >>= 1;
}
q >>= 8;
return (FT_16D16)q;
}
/**************************************************************************
*
* format and sign manipulating functions

@ -122,8 +122,7 @@ FT_BEGIN_HEADER
typedef FT_BBox FT_CBox; /* control box of a curve */
FT_LOCAL( FT_16D16 )
square_root( FT_16D16 val );
#define square_root( x ) (FT_16D16)FT_SqrtFixed( (FT_UInt32)( x ) )
FT_LOCAL( FT_SDFFormat )
map_fixed_to_sdf( FT_16D16 dist,

@ -18,6 +18,7 @@
#include "sfwoff.h"
#include <freetype/tttags.h>
#include <freetype/internal/ftcalc.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
#include <freetype/ftgzip.h>
@ -149,6 +150,7 @@
/* Miscellaneous checks. */
if ( woff.length != stream->size ||
woff.num_tables == 0 ||
woff.num_tables > 0xFFFU ||
44 + woff.num_tables * 20UL >= woff.length ||
12 + woff.num_tables * 16UL >= woff.totalSfntSize ||
( woff.totalSfntSize & 3 ) != 0 ||
@ -169,21 +171,11 @@
/* Write sfnt header. */
{
FT_UInt searchRange, entrySelector, rangeShift, x;
FT_Int entrySelector = FT_MSB( woff.num_tables );
FT_Int searchRange = ( 1 << entrySelector ) * 16;
FT_Int rangeShift = woff.num_tables * 16 - searchRange;
x = woff.num_tables;
entrySelector = 0;
while ( x )
{
x >>= 1;
entrySelector += 1;
}
entrySelector--;
searchRange = ( 1 << entrySelector ) * 16;
rangeShift = woff.num_tables * 16 - searchRange;
WRITE_ULONG ( sfnt_header, woff.flavor );
WRITE_USHORT( sfnt_header, woff.num_tables );
WRITE_USHORT( sfnt_header, searchRange );

@ -18,6 +18,7 @@
#include "sfwoff2.h"
#include "woff2tags.h"
#include <freetype/tttags.h>
#include <freetype/internal/ftcalc.h>
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>
@ -289,23 +290,15 @@
FT_ULong checksum = 0;
FT_ULong aligned_size = size & ~3UL;
FT_ULong i;
FT_ULong v;
FT_Int shift;
for ( i = 0; i < aligned_size; i += 4 )
checksum += ( (FT_ULong)buf[i ] << 24 ) |
( (FT_ULong)buf[i + 1] << 16 ) |
( (FT_ULong)buf[i + 2] << 8 ) |
( (FT_ULong)buf[i + 3] << 0 );
checksum += FT_NEXT_ULONG( buf );
/* If size is not aligned to 4, treat as if it is padded with 0s. */
if ( size != aligned_size )
{
v = 0;
for ( i = aligned_size ; i < size; ++i )
v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) );
checksum += v;
}
/* remaining bytes can be shifted and added one at a time */
for ( shift = 24; i < size; i++, shift -= 8 )
checksum += (FT_UInt32)FT_NEXT_BYTE( buf ) << shift;
return checksum;
}
@ -1799,7 +1792,6 @@
FT_Byte* sfnt = NULL;
FT_Stream sfnt_stream = NULL;
FT_Byte* sfnt_header;
FT_ULong sfnt_size;
FT_Byte* uncompressed_buf = NULL;
@ -1853,6 +1845,7 @@
/* Miscellaneous checks. */
if ( woff2.length != stream->size ||
woff2.num_tables == 0 ||
woff2.num_tables > 0xFFFU ||
48 + woff2.num_tables * 20UL >= woff2.length ||
( woff2.metaOffset == 0 && ( woff2.metaLength != 0 ||
woff2.metaOrigLength != 0 ) ) ||
@ -2143,6 +2136,13 @@
WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index;
if ( ttc_font->num_tables == 0 || ttc_font->num_tables > 0xFFFU )
{
FT_ERROR(( "woff2_open_font: invalid WOFF2 CollectionFontEntry\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
/* Create a temporary array. */
if ( FT_QNEW_ARRAY( temp_indices,
ttc_font->num_tables ) )
@ -2198,27 +2198,15 @@
FT_NEW( sfnt_stream ) )
goto Exit;
sfnt_header = sfnt;
WRITE_ULONG( sfnt_header, woff2.flavor );
if ( woff2.num_tables )
{
FT_UInt searchRange, entrySelector, rangeShift, x;
FT_Byte* sfnt_header = sfnt;
FT_Int entrySelector = FT_MSB( woff2.num_tables );
FT_Int searchRange = ( 1 << entrySelector ) * 16;
FT_Int rangeShift = woff2.num_tables * 16 - searchRange;
x = woff2.num_tables;
entrySelector = 0;
while ( x )
{
x >>= 1;
entrySelector += 1;
}
entrySelector--;
searchRange = ( 1 << entrySelector ) * 16;
rangeShift = ( woff2.num_tables * 16 ) - searchRange;
WRITE_ULONG ( sfnt_header, woff2.flavor );
WRITE_USHORT( sfnt_header, woff2.num_tables );
WRITE_USHORT( sfnt_header, searchRange );
WRITE_USHORT( sfnt_header, entrySelector );

@ -208,18 +208,19 @@
colr->num_base_glyphs = FT_NEXT_USHORT( p );
base_glyph_offset = FT_NEXT_ULONG( p );
if ( base_glyph_offset >= table_size )
if ( table_size <= base_glyph_offset )
goto InvalidTable;
if ( colr->num_base_glyphs * BASE_GLYPH_SIZE >
table_size - base_glyph_offset )
if ( ( table_size - base_glyph_offset ) / BASE_GLYPH_SIZE
< colr->num_base_glyphs )
goto InvalidTable;
layer_offset = FT_NEXT_ULONG( p );
colr->num_layers = FT_NEXT_USHORT( p );
if ( layer_offset >= table_size )
if ( table_size <= layer_offset )
goto InvalidTable;
if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
if ( ( table_size - layer_offset ) / LAYER_SIZE
< colr->num_layers )
goto InvalidTable;
if ( colr->version == 1 )
@ -229,14 +230,14 @@
base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
if ( base_glyphs_offset_v1 >= table_size - 4 )
if ( table_size - 4 <= base_glyphs_offset_v1 )
goto InvalidTable;
p1 = (FT_Byte*)( table + base_glyphs_offset_v1 );
num_base_glyphs_v1 = FT_PEEK_ULONG( p1 );
if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE >
table_size - base_glyphs_offset_v1 )
if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE
< num_base_glyphs_v1 )
goto InvalidTable;
colr->num_base_glyphs_v1 = num_base_glyphs_v1;
@ -244,19 +245,19 @@
layer_offset_v1 = FT_NEXT_ULONG( p );
if ( layer_offset_v1 >= table_size )
if ( table_size <= layer_offset_v1 )
goto InvalidTable;
if ( layer_offset_v1 )
{
if ( layer_offset_v1 >= table_size - 4 )
if ( table_size - 4 <= layer_offset_v1 )
goto InvalidTable;
p1 = (FT_Byte*)( table + layer_offset_v1 );
num_layers_v1 = FT_PEEK_ULONG( p1 );
if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE >
table_size - layer_offset_v1 )
if ( ( table_size - layer_offset_v1 ) / LAYER_V1_LIST_PAINT_OFFSET_SIZE
< num_layers_v1 )
goto InvalidTable;
colr->num_layers_v1 = num_layers_v1;
@ -279,7 +280,7 @@
clip_list_offset = FT_NEXT_ULONG( p );
if ( clip_list_offset >= table_size )
if ( table_size <= clip_list_offset )
goto InvalidTable;
if ( clip_list_offset )
@ -311,7 +312,7 @@
goto InvalidTable;
var_store_offset = FT_NEXT_ULONG( p );
if ( var_store_offset >= table_size )
if ( table_size <= var_store_offset )
goto InvalidTable;
if ( var_store_offset )
@ -1270,7 +1271,6 @@
static FT_Bool
find_base_glyph_v1_record( FT_Byte * base_glyph_begin,
FT_UInt num_base_glyph,
FT_Byte * end_colr,
FT_UInt glyph_id,
BaseGlyphV1Record *record )
{
@ -1290,14 +1290,6 @@
*/
FT_Byte *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE;
/* We need to be able to read 2 bytes (FT_NEXT_USHORT) for the glyph */
/* ID, then 4 bytes (FT_NEXT_ULONG) for the paint offset. If that's */
/* not available before the end of the table, something's wrong with */
/* the font and we can't find a COLRv1 glyph. */
if ( p > end_colr - 2 - 4 )
return 0;
gid = FT_NEXT_USHORT( p );
if ( gid < glyph_id )
@ -1338,7 +1330,6 @@
if ( !find_base_glyph_v1_record( colr->base_glyphs_v1,
colr->num_base_glyphs_v1,
(FT_Byte*)colr->table + colr->table_size,
base_glyph,
&base_glyph_v1_record ) )
return 0;

@ -489,7 +489,7 @@ typedef ptrdiff_t FT_PtrDist;
typedef struct gray_TWorker_
{
ft_jmp_buf jump_buffer;
FT_BBox cbox;
TCoord min_ex, max_ex; /* min and max integer pixel coordinates */
TCoord min_ey, max_ey;
@ -510,6 +510,8 @@ typedef ptrdiff_t FT_PtrDist;
FT_Raster_Span_Func render_span;
void* render_span_data;
ft_jmp_buf jump_buffer;
} gray_TWorker, *gray_PWorker;
#if defined( _MSC_VER )
@ -1863,11 +1865,8 @@ typedef ptrdiff_t FT_PtrDist;
static int
gray_convert_glyph( RAS_ARG )
{
const TCoord yMin = ras.min_ey;
const TCoord yMax = ras.max_ey;
TCell buffer[FT_MAX_GRAY_POOL];
size_t height = (size_t)( yMax - yMin );
size_t height = (size_t)( ras.cbox.yMax - ras.cbox.yMin );
size_t n = FT_MAX_GRAY_POOL / 8;
TCoord y;
TCoord bands[32]; /* enough to accommodate bisections */
@ -1893,35 +1892,36 @@ typedef ptrdiff_t FT_PtrDist;
height = ( height + n - 1 ) / n;
}
for ( y = yMin; y < yMax; )
for ( y = ras.cbox.yMin; y < ras.cbox.yMax; )
{
ras.min_ey = y;
y += height;
ras.max_ey = FT_MIN( y, yMax );
ras.max_ey = FT_MIN( y, ras.cbox.yMax );
ras.count_ey = ras.max_ey - ras.min_ey;
band = bands;
band[1] = ras.min_ey;
band[0] = ras.max_ey;
band[1] = ras.cbox.xMin;
band[0] = ras.cbox.xMax;
do
{
TCoord width = band[0] - band[1];
TCoord w;
TCoord i;
int error;
for ( w = 0; w < width; ++w )
ras.ycells[w] = ras.cell_null;
ras.min_ex = band[1];
ras.max_ex = band[0];
/* memory management: skip ycells */
n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
sizeof ( TCell );
/* memory management: zero out and skip ycells */
for ( i = 0; i < ras.count_ey; ++i )
ras.ycells[i] = ras.cell_null;
n = ( (size_t)ras.count_ey * sizeof ( PCell ) + sizeof ( TCell ) - 1 )
/ sizeof ( TCell );
ras.cell_free = buffer + n;
ras.cell = ras.cell_null;
ras.min_ey = band[1];
ras.max_ey = band[0];
ras.count_ey = width;
error = gray_convert_glyph_inner( RAS_VAR_ continued );
continued = 1;
@ -1939,10 +1939,10 @@ typedef ptrdiff_t FT_PtrDist;
return error;
/* render pool overflow; we will reduce the render band by half */
width >>= 1;
i = ( band[0] - band[1] ) >> 1;
/* this should never happen even with tiny rendering pool */
if ( width == 0 )
if ( i == 0 )
{
FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
return FT_THROW( Raster_Overflow );
@ -1950,7 +1950,7 @@ typedef ptrdiff_t FT_PtrDist;
band++;
band[1] = band[0];
band[0] += width;
band[0] += i;
} while ( band >= bands );
}
@ -1981,7 +1981,7 @@ typedef ptrdiff_t FT_PtrDist;
return FT_THROW( Invalid_Outline );
/* return immediately if the outline is empty */
if ( outline->n_points == 0 || outline->n_contours <= 0 )
if ( outline->n_points == 0 || outline->n_contours == 0 )
return Smooth_Err_Ok;
if ( !outline->contours || !outline->points )
@ -2001,10 +2001,7 @@ typedef ptrdiff_t FT_PtrDist;
ras.render_span = (FT_Raster_Span_Func)params->gray_spans;
ras.render_span_data = params->user;
ras.min_ex = params->clip_box.xMin;
ras.min_ey = params->clip_box.yMin;
ras.max_ex = params->clip_box.xMax;
ras.max_ey = params->clip_box.yMax;
ras.cbox = params->clip_box;
}
else
{
@ -2030,14 +2027,14 @@ typedef ptrdiff_t FT_PtrDist;
ras.render_span = (FT_Raster_Span_Func)NULL;
ras.render_span_data = NULL;
ras.min_ex = 0;
ras.min_ey = 0;
ras.max_ex = (FT_Pos)target_map->width;
ras.max_ey = (FT_Pos)target_map->rows;
ras.cbox.xMin = 0;
ras.cbox.yMin = 0;
ras.cbox.xMax = (FT_Pos)target_map->width;
ras.cbox.yMax = (FT_Pos)target_map->rows;
}
/* exit if nothing to do */
if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
if ( ras.cbox.xMin >= ras.cbox.xMax || ras.cbox.yMin >= ras.cbox.yMax )
return Smooth_Err_Ok;
return gray_convert_glyph( RAS_VAR );

@ -353,7 +353,8 @@
FT_Byte c, count;
FT_Vector *vec, *vec_limit;
FT_Pos x, y;
FT_Short *cont, *cont_limit, last;
FT_UShort *cont, *cont_limit;
FT_Int last;
/* check that we can add the contours to the glyph */
@ -372,7 +373,7 @@
last = -1;
for ( ; cont < cont_limit; cont++ )
{
*cont = FT_NEXT_SHORT( p );
*cont = FT_NEXT_USHORT( p );
if ( *cont <= last )
goto Invalid_Outline;
@ -418,11 +419,9 @@
/* and thus allocate the bytecode array size by ourselves */
if ( n_ins )
{
if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) )
if ( FT_DUP( exec->glyphIns, p, n_ins ) )
return error;
FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins );
exec->glyphSize = n_ins;
}
}
@ -432,7 +431,7 @@
p += n_ins;
/* reading the point tags */
flag = (FT_Byte*)outline->tags;
flag = outline->tags;
flag_limit = flag + n_points;
FT_ASSERT( flag );
@ -465,7 +464,7 @@
vec = outline->points;
vec_limit = vec + n_points;
flag = (FT_Byte*)outline->tags;
flag = outline->tags;
x = 0;
for ( ; vec < vec_limit; vec++, flag++ )
@ -499,7 +498,7 @@
vec = outline->points;
vec_limit = vec + n_points;
flag = (FT_Byte*)outline->tags;
flag = outline->tags;
y = 0;
for ( ; vec < vec_limit; vec++, flag++ )
@ -532,8 +531,8 @@
*flag = (FT_Byte)( f & ON_CURVE_POINT );
}
outline->n_points = (FT_Short)n_points;
outline->n_contours = (FT_Short)n_contours;
outline->n_points = (FT_UShort)n_points;
outline->n_contours = (FT_UShort)n_contours;
load->cursor = p;
@ -754,15 +753,13 @@
FT_UInt start_point,
FT_UInt start_contour )
{
zone->n_points = (FT_UShort)load->outline.n_points + 4 -
(FT_UShort)start_point;
zone->n_contours = load->outline.n_contours -
(FT_Short)start_contour;
zone->n_points = load->outline.n_points + 4 - (FT_UShort)start_point;
zone->n_contours = load->outline.n_contours - (FT_UShort)start_contour;
zone->org = load->extra_points + start_point;
zone->cur = load->outline.points + start_point;
zone->orus = load->extra_points2 + start_point;
zone->tags = (FT_Byte*)load->outline.tags + start_point;
zone->contours = (FT_UShort*)load->outline.contours + start_contour;
zone->tags = load->outline.tags + start_point;
zone->contours = load->outline.contours + start_contour;
zone->first_point = (FT_UShort)start_point;
}
@ -1046,7 +1043,7 @@
current.points = gloader->base.outline.points +
num_base_points;
current.n_points = gloader->base.outline.n_points -
(short)num_base_points;
(FT_UShort)num_base_points;
have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
WE_HAVE_AN_XY_SCALE |
@ -1059,7 +1056,7 @@
/* get offset */
if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
{
FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points;
FT_UInt num_points = gloader->base.outline.n_points;
FT_UInt k = (FT_UInt)subglyph->arg1;
FT_UInt l = (FT_UInt)subglyph->arg2;
FT_Vector* p1;
@ -1721,8 +1718,8 @@
FT_List_Add( &loader->composites, node );
}
start_point = (FT_UInt)gloader->base.outline.n_points;
start_contour = (FT_UInt)gloader->base.outline.n_contours;
start_point = gloader->base.outline.n_points;
start_contour = gloader->base.outline.n_contours;
/* for each subglyph, read composite header */
error = face->read_composite_glyph( loader );
@ -1874,7 +1871,7 @@
linear_hadvance = loader->linear;
linear_vadvance = loader->vadvance;
num_base_points = (FT_UInt)gloader->base.outline.n_points;
num_base_points = gloader->base.outline.n_points;
error = load_truetype_glyph( loader,
(FT_UInt)subglyph->index,
@ -1898,7 +1895,7 @@
loader->vadvance = linear_vadvance;
}
num_points = (FT_UInt)gloader->base.outline.n_points;
num_points = gloader->base.outline.n_points;
if ( num_points == num_base_points )
continue;
@ -2719,7 +2716,7 @@
size->metrics->y_ppem < 24 )
glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
FT_TRACE1(( " subglyphs = %u, contours = %hd, points = %hd,"
FT_TRACE1(( " subglyphs = %u, contours = %hu, points = %hu,"
" flags = 0x%.3x\n",
loader.gloader->base.num_subglyphs,
glyph->outline.n_contours,

@ -596,7 +596,7 @@
for ( j = 0; j < itemStore->axisCount; j++ )
{
FT_Short start, peak, end;
FT_Int start, peak, end;
if ( FT_READ_SHORT( start ) ||
@ -604,6 +604,10 @@
FT_READ_SHORT( end ) )
goto Exit;
/* immediately tag invalid ranges with special peak = 0 */
if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
peak = 0;
axisCoords[j].startCoord = FT_fdot14ToFixed( start );
axisCoords[j].peakCoord = FT_fdot14ToFixed( peak );
axisCoords[j].endCoord = FT_fdot14ToFixed( end );
@ -1024,6 +1028,9 @@
if ( innerIndex >= varData->itemCount )
return 0; /* Out of range. */
if ( varData->regionIdxCount == 0 )
return 0; /* Avoid "applying zero offset to null pointer". */
if ( varData->regionIdxCount < 16 )
{
deltaSet = deltaSetStack;
@ -1074,43 +1081,32 @@
/* inner loop steps through axes in this region */
for ( j = 0; j < itemStore->axisCount; j++, axis++ )
{
/* compute the scalar contribution of this axis; */
/* ignore invalid ranges */
if ( axis->startCoord > axis->peakCoord ||
axis->peakCoord > axis->endCoord )
continue;
FT_Fixed ncv = ttface->blend->normalizedcoords[j];
else if ( axis->startCoord < 0 &&
axis->endCoord > 0 &&
axis->peakCoord != 0 )
continue;
/* peak of 0 means ignore this axis */
else if ( axis->peakCoord == 0 )
continue;
else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord )
/* compute the scalar contribution of this axis */
/* with peak of 0 used for invalid axes */
if ( axis->peakCoord == ncv ||
axis->peakCoord == 0 )
continue;
/* ignore this region if coords are out of range */
else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord ||
ttface->blend->normalizedcoords[j] >= axis->endCoord )
else if ( ncv <= axis->startCoord ||
ncv >= axis->endCoord )
{
scalar = 0;
break;
}
/* cumulative product of all the axis scalars */
else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord )
scalar =
FT_MulDiv( scalar,
ttface->blend->normalizedcoords[j] - axis->startCoord,
axis->peakCoord - axis->startCoord );
else
scalar =
FT_MulDiv( scalar,
axis->endCoord - ttface->blend->normalizedcoords[j],
axis->endCoord - axis->peakCoord );
else if ( ncv < axis->peakCoord )
scalar = FT_MulDiv( scalar,
ncv - axis->startCoord,
axis->peakCoord - axis->startCoord );
else /* ncv > axis->peakCoord */
scalar = FT_MulDiv( scalar,
axis->endCoord - ncv,
axis->endCoord - axis->peakCoord );
} /* per-axis loop */
@ -1920,28 +1916,17 @@
for ( i = 0; i < blend->num_axis; i++ )
{
FT_TRACE6(( " axis %d coordinate %.5f:\n",
i, (double)blend->normalizedcoords[i] / 65536 ));
FT_Fixed ncv = blend->normalizedcoords[i];
FT_TRACE6(( " axis %d coordinate %.5f:\n", i, (double)ncv / 65536 ));
/* It's not clear why (for intermediate tuples) we don't need */
/* to check against start/end -- the documentation says we don't. */
/* Similarly, it's unclear why we don't need to scale along the */
/* axis. */
if ( tuple_coords[i] == 0 )
{
FT_TRACE6(( " tuple coordinate is zero, ignore\n" ));
continue;
}
if ( blend->normalizedcoords[i] == 0 )
{
FT_TRACE6(( " axis coordinate is zero, stop\n" ));
apply = 0;
break;
}
if ( blend->normalizedcoords[i] == tuple_coords[i] )
if ( tuple_coords[i] == ncv )
{
FT_TRACE6(( " tuple coordinate %.5f fits perfectly\n",
(double)tuple_coords[i] / 65536 ));
@ -1949,31 +1934,37 @@
continue;
}
if ( tuple_coords[i] == 0 )
{
FT_TRACE6(( " tuple coordinate is zero, ignore\n" ));
continue;
}
if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
{
/* not an intermediate tuple */
if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
if ( ( tuple_coords[i] > ncv && ncv > 0 ) ||
( tuple_coords[i] < ncv && ncv < 0 ) )
{
FT_TRACE6(( " tuple coordinate %.5f fits\n",
(double)tuple_coords[i] / 65536 ));
apply = FT_MulDiv( apply, ncv, tuple_coords[i] );
}
else
{
FT_TRACE6(( " tuple coordinate %.5f is exceeded, stop\n",
(double)tuple_coords[i] / 65536 ));
apply = 0;
break;
}
FT_TRACE6(( " tuple coordinate %.5f fits\n",
(double)tuple_coords[i] / 65536 ));
apply = FT_MulDiv( apply,
blend->normalizedcoords[i],
tuple_coords[i] );
}
else
{
/* intermediate tuple */
if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
blend->normalizedcoords[i] >= im_end_coords[i] )
if ( ncv <= im_start_coords[i] ||
ncv >= im_end_coords[i] )
{
FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ is exceeded,"
" stop\n",
@ -1986,13 +1977,13 @@
FT_TRACE6(( " intermediate tuple range ]%.5f;%.5f[ fits\n",
(double)im_start_coords[i] / 65536,
(double)im_end_coords[i] / 65536 ));
if ( blend->normalizedcoords[i] < tuple_coords[i] )
if ( ncv < tuple_coords[i] )
apply = FT_MulDiv( apply,
blend->normalizedcoords[i] - im_start_coords[i],
ncv - im_start_coords[i],
tuple_coords[i] - im_start_coords[i] );
else
else /* ncv > tuple_coords[i] */
apply = FT_MulDiv( apply,
im_end_coords[i] - blend->normalizedcoords[i],
im_end_coords[i] - ncv,
im_end_coords[i] - tuple_coords[i] );
}
}
@ -2141,12 +2132,12 @@
outerIndex,
innerIndex );
/* Convert to 16.16 format before adding. */
v += MUL_INT( delta, 4 );
/* Convert delta in F2DOT14 to 16.16 before adding. */
v += MUL_INT( delta, 4 );
/* Clamp value range. */
v = v >= 0x10000L ? 0x10000 : v;
v = v <= -0x10000L ? -0x10000 : v;
/* Clamp value range [-1, 1]. */
v = v >= 0x10000L ? 0x10000 : v;
v = v <= -0x10000L ? -0x10000 : v;
new_normalized[i] = v;
}
@ -2722,9 +2713,8 @@
FT_UInt n;
if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) )
if ( FT_DUP( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ) )
goto Exit;
FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len );
axis_flags =
(FT_UShort*)( (char*)mmvar + mmvar_size );
@ -3534,9 +3524,10 @@
FT_ULong here;
FT_UInt i, j;
FT_Fixed* tuple_coords = NULL;
FT_Fixed* im_start_coords = NULL;
FT_Fixed* im_end_coords = NULL;
FT_Fixed* peak_coords = NULL;
FT_Fixed* tuple_coords;
FT_Fixed* im_start_coords;
FT_Fixed* im_end_coords;
GX_Blend blend = face->blend;
@ -3557,16 +3548,16 @@
{
FT_TRACE2(( "\n" ));
FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
error = FT_Err_Ok;
goto Exit;
return FT_Err_Ok;
}
if ( !face->cvt )
{
FT_TRACE2(( "\n" ));
FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
error = FT_Err_Ok;
goto Exit;
return FT_Err_Ok;
}
error = face->goto_table( face, TTAG_cvar, stream, &table_len );
@ -3574,15 +3565,11 @@
{
FT_TRACE2(( "is missing\n" ));
error = FT_Err_Ok;
goto Exit;
return FT_Err_Ok;
}
if ( FT_FRAME_ENTER( table_len ) )
{
error = FT_Err_Ok;
goto Exit;
}
return FT_Err_Ok;
table_start = FT_Stream_FTell( stream );
if ( FT_GET_LONG() != 0x00010000L )
@ -3595,11 +3582,6 @@
FT_TRACE2(( "loaded\n" ));
if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
goto FExit;
tupleCount = FT_GET_USHORT();
offsetToData = FT_GET_USHORT();
@ -3635,8 +3617,12 @@
tupleCount & GX_TC_TUPLE_COUNT_MASK,
( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
if ( FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) )
goto FExit;
if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) )
goto Exit;
im_start_coords = peak_coords + blend->num_axis;
im_end_coords = im_start_coords + blend->num_axis;
for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
{
@ -3653,32 +3639,19 @@
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
for ( j = 0; j < blend->num_axis; j++ )
tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
tuple_coords = peak_coords;
}
else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
tuple_coords = blend->tuplecoords +
( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
else
{
FT_TRACE2(( "tt_face_vary_cvt:"
" invalid tuple index\n" ));
error = FT_THROW( Invalid_Table );
goto FExit;
}
else
{
if ( !blend->tuplecoords )
{
FT_TRACE2(( "tt_face_vary_cvt:"
" no valid tuple coordinates available\n" ));
error = FT_THROW( Invalid_Table );
goto FExit;
}
FT_MEM_COPY(
tuple_coords,
blend->tuplecoords +
( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
blend->num_axis * sizeof ( FT_Fixed ) );
goto Exit;
}
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
@ -3821,23 +3794,21 @@
for ( i = 0; i < face->cvt_size; i++ )
face->cvt[i] += FT_fixedToFdot6( cvt_deltas[i] );
FExit:
FT_FRAME_EXIT();
Exit:
if ( sharedpoints != ALL_POINTS )
FT_FREE( sharedpoints );
FT_FREE( tuple_coords );
FT_FREE( im_start_coords );
FT_FREE( im_end_coords );
FT_FREE( cvt_deltas );
/* iterate over all FT_Size objects and set `cvt_ready' to -1 */
/* to trigger rescaling of all CVT values */
FT_List_Iterate( &root->sizes_list,
tt_cvt_ready_iterator,
NULL );
Exit:
if ( sharedpoints != ALL_POINTS )
FT_FREE( sharedpoints );
FT_FREE( cvt_deltas );
FT_FREE( peak_coords );
FExit:
FT_FRAME_EXIT();
return error;
#else /* !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
@ -4100,9 +4071,10 @@
FT_ULong here;
FT_UInt i, j;
FT_Fixed* tuple_coords = NULL;
FT_Fixed* im_start_coords = NULL;
FT_Fixed* im_end_coords = NULL;
FT_Fixed* peak_coords = NULL;
FT_Fixed* tuple_coords;
FT_Fixed* im_start_coords;
FT_Fixed* im_end_coords;
GX_Blend blend = face->blend;
@ -4137,27 +4109,17 @@
return FT_Err_Ok;
}
if ( FT_NEW_ARRAY( points_org, n_points ) ||
FT_NEW_ARRAY( points_out, n_points ) ||
FT_NEW_ARRAY( has_delta, n_points ) )
goto Fail1;
dataSize = blend->glyphoffsets[glyph_index + 1] -
blend->glyphoffsets[glyph_index];
if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
FT_FRAME_ENTER( dataSize ) )
goto Fail1;
return error;
glyph_start = FT_Stream_FTell( stream );
/* each set of glyph variation data is formatted similarly to `cvar' */
if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
goto Fail2;
tupleCount = FT_GET_USHORT();
offsetToData = FT_GET_USHORT();
@ -4169,7 +4131,7 @@
" invalid glyph variation array header\n" ));
error = FT_THROW( Invalid_Table );
goto Fail2;
goto FExit;
}
offsetToData += glyph_start;
@ -4193,9 +4155,16 @@
tupleCount & GX_TC_TUPLE_COUNT_MASK,
( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
if ( FT_NEW_ARRAY( point_deltas_x, n_points ) ||
FT_NEW_ARRAY( point_deltas_y, n_points ) )
goto Fail3;
if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
FT_NEW_ARRAY( point_deltas_x, 2 * n_points ) ||
FT_QNEW_ARRAY( points_org, n_points ) ||
FT_QNEW_ARRAY( points_out, n_points ) ||
FT_QNEW_ARRAY( has_delta, n_points ) )
goto Exit;
im_start_coords = peak_coords + blend->num_axis;
im_end_coords = im_start_coords + blend->num_axis;
point_deltas_y = point_deltas_x + n_points;
for ( j = 0; j < n_points; j++ )
{
@ -4218,22 +4187,20 @@
if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
{
for ( j = 0; j < blend->num_axis; j++ )
tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
tuple_coords = peak_coords;
}
else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
tuple_coords = blend->tuplecoords +
( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
else
{
FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
" invalid tuple index\n" ));
error = FT_THROW( Invalid_Table );
goto Fail3;
goto Exit;
}
else
FT_MEM_COPY(
tuple_coords,
blend->tuplecoords +
( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
blend->num_axis * sizeof ( FT_Fixed ) );
if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
{
@ -4461,23 +4428,17 @@
unrounded[n_points - 2].y ) / 64;
}
Fail3:
FT_FREE( point_deltas_x );
FT_FREE( point_deltas_y );
Fail2:
Exit:
if ( sharedpoints != ALL_POINTS )
FT_FREE( sharedpoints );
FT_FREE( tuple_coords );
FT_FREE( im_start_coords );
FT_FREE( im_end_coords );
FT_FRAME_EXIT();
Fail1:
FT_FREE( points_org );
FT_FREE( points_out );
FT_FREE( has_delta );
FT_FREE( peak_coords );
FT_FREE( point_deltas_x );
FExit:
FT_FRAME_EXIT();
return error;
}

@ -5270,11 +5270,11 @@
FT_UShort refp;
FT_F26Dot6 dx, dy;
FT_Short contour, bounds;
FT_UShort contour, bounds;
FT_UShort start, limit, i;
contour = (FT_Short)args[0];
contour = (FT_UShort)args[0];
bounds = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
if ( BOUNDS( contour, bounds ) )
@ -5290,15 +5290,13 @@
if ( contour == 0 )
start = 0;
else
start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
exc->zp2.first_point );
start = exc->zp2.contours[contour - 1] + 1 - exc->zp2.first_point;
/* we use the number of points if in the twilight zone */
if ( exc->GS.gep2 == 0 )
limit = exc->zp2.n_points;
else
limit = (FT_UShort)( exc->zp2.contours[contour] -
exc->zp2.first_point + 1 );
limit = exc->zp2.contours[contour] + 1 - exc->zp2.first_point;
for ( i = start; i < limit; i++ )
{
@ -5341,9 +5339,9 @@
/* Normal zone's `n_points' includes phantoms, so must */
/* use end of last contour. */
if ( exc->GS.gep2 == 0 )
limit = (FT_UShort)exc->zp2.n_points;
limit = exc->zp2.n_points;
else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1;
else
limit = 0;

@ -115,7 +115,7 @@
FT_LOCAL_DEF( FT_Error )
tt_glyphzone_new( FT_Memory memory,
FT_UShort maxPoints,
FT_Short maxContours,
FT_UShort maxContours,
TT_GlyphZone zone )
{
FT_Error error;
@ -256,17 +256,20 @@
{
FT_Error error;
FT_UInt32 checksum = 0;
FT_UInt i;
FT_Byte* p;
FT_Int shift;
if ( FT_FRAME_ENTER( length ) )
return 0;
for ( ; length > 3; length -= 4 )
checksum += (FT_UInt32)FT_GET_ULONG();
p = (FT_Byte*)stream->cursor;
for ( i = 3; length > 0; length--, i-- )
checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
for ( ; length > 3; length -= 4 )
checksum += FT_NEXT_ULONG( p );
for ( shift = 24; length > 0; length--, shift -=8 )
checksum += (FT_UInt32)FT_NEXT_BYTE( p ) << shift;
FT_FRAME_EXIT();

@ -105,7 +105,7 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
tt_glyphzone_new( FT_Memory memory,
FT_UShort maxPoints,
FT_Short maxContours,
FT_UShort maxContours,
TT_GlyphZone zone );
#endif /* TT_USE_BYTECODE_INTERPRETER */

@ -751,6 +751,7 @@
PS_DesignMap dmap = blend->design_map + n;
FT_FREE( dmap->blend_points );
FT_FREE( dmap->design_points );
dmap->num_points = 0;
}
@ -1043,9 +1044,9 @@
}
/* allocate design map data */
if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) )
if ( FT_QNEW_ARRAY( map->design_points, num_points ) ||
FT_QNEW_ARRAY( map->blend_points, num_points ) )
goto Exit;
map->blend_points = map->design_points + num_points;
map->num_points = (FT_Byte)num_points;
for ( p = 0; p < num_points; p++ )
@ -1876,9 +1877,8 @@
}
/* t1_decrypt() shouldn't write to base -- make temporary copy */
if ( FT_QALLOC( temp, size ) )
if ( FT_DUP( temp, base, size ) )
goto Fail;
FT_MEM_COPY( temp, base, size );
psaux->t1_decrypt( temp, size, 4330 );
size -= (FT_ULong)t1face->type1.private_dict.lenIV;
error = T1_Add_Table( table,
@ -2090,9 +2090,8 @@
}
/* t1_decrypt() shouldn't write to base -- make temporary copy */
if ( FT_QALLOC( temp, size ) )
if ( FT_DUP( temp, base, size ) )
goto Fail;
FT_MEM_COPY( temp, base, size );
psaux->t1_decrypt( temp, size, 4330 );
size -= (FT_ULong)t1face->type1.private_dict.lenIV;
error = T1_Add_Table( code_table,