Snap for 8564071 from c4807feea9d365a2c8102b919520de965ae38ccc to mainline-sdkext-release

Change-Id: I2f79cd45eba0272ae69fad8b838bd3db2a2a817f
diff --git a/.gitignore b/.gitignore
index a47f568..e4f1510 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
-config.mk
-objs/vc2010/
-build
+/build/
+/config.mk
+include/dlg/
+src/dlg/dlg.c
+subprojects/*
+!subprojects/*.wrap
+/tests/data/*
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..5140aa7
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,198 @@
+stages:
+ - build
+
+# FIXME: Use --werror once warnings are fixed.
+variables:
+  MESON_ARGS: --fatal-meson-warnings
+  MESON_ARGS_WINDOWS: ${MESON_ARGS} --force-fallback-for=zlib
+
+.build windows common:
+  # See
+  # https://gitlab.freedesktop.org/gstreamer/gst-ci/container_registry/213
+  image: 'registry.freedesktop.org/gstreamer/gst-ci/amd64/windows:v14-master'
+  stage: 'build'
+  tags:
+    - 'docker'
+    - 'windows'
+    - '1809'
+    - 'gstreamer-windows'
+
+.build linux common:
+  # See
+  # https://gitlab.freedesktop.org/freetype/docker-images/container_registry/20896
+  image: 'registry.freedesktop.org/freetype/docker-images/debian:latest'
+  stage: 'build'
+
+.build macos common:
+  stage: 'build'
+  tags:
+    - 'gst-macos-11.1'
+
+.build windows meson:
+  extends: '.build windows common'
+  variables:
+    # Make sure any failure in PowerShell scripts is fatal.
+    ErrorActionPreference: 'Stop'
+    WarningPreference: 'Stop'
+    # Uncomment the following key if need to pass custom args, as well with
+    # the `$env:MESON_ARGS` line in the `script:` blocks.
+    # MESON_ARGS: >-
+    #   -Dfoo=enabled
+    #   -Dbar=disabled
+  before_script:
+    # Make sure meson is up to date, so we don't need to rebuild the image
+    # with each release.
+    - pip3 install meson==0.59.1
+    - pip3 install -U ninja
+  script:
+    # For some reason, options are separated by newlines instead of spaces,
+    # so we have to replace them first.
+    #- $env:MESON_ARGS = $env:MESON_ARGS.replace("`n"," ")
+    # Gitlab executes PowerShell in docker, but `VsDevCmd.bat` is a batch
+    # 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 &&
+        meson setup build $env:MESON_ARGS_WINDOWS &&
+        meson compile --verbose -C build &&
+        meson test -C build &&
+        meson test -C build --benchmark"
+
+
+# Format of job names:
+# <OS> <Build-Tool> <Build-Params> <Architecture> 
+
+
+# Windows jobs
+windows meson vs2017 amd64:
+  extends: '.build windows meson'
+  variables:
+    ARCH: 'amd64'
+
+windows meson vs2017 x86:
+  extends: '.build windows meson'
+  variables:
+    ARCH: 'x86'
+
+
+# Linux Jobs
+# Jobs with "libs" in the name force enable libraries.
+# They are disabled in rest of the jobs.
+linux autotools:
+  extends: '.build linux common'
+  script: |
+    ./autogen.sh
+    ./configure --with-brotli=no \
+                --with-bzip2=no \
+                --with-harfbuzz=no \
+                --with-png=no \
+                --with-zlib=no \
+                CC=gcc
+
+    make -j$(nproc) && make install
+
+linux autotools libs:
+  extends: '.build linux common'
+  script: |
+    ./autogen.sh
+    ./configure --with-brotli=yes \
+                --with-bzip2=yes \
+                --with-harfbuzz=yes \
+                --with-png=yes \
+                --with-zlib=yes \
+                CC=gcc
+
+    make -j$(nproc) && make install
+
+linux autotools libs clang:
+  extends: '.build linux common'
+  script: |
+    ./autogen.sh
+    ./configure --with-brotli=yes \
+                --with-bzip2=yes \
+                --with-harfbuzz=yes \
+                --with-png=yes \
+                --with-zlib=yes \
+                CC=clang
+
+    make -j$(nproc) && make install
+
+linux meson:
+  extends: '.build linux common'
+  script: |
+    meson setup build -Dbrotli=disabled \
+                      -Dbzip2=disabled \
+                      -Dharfbuzz=disabled \
+                      -Dpng=disabled \
+                      -Dzlib=disabled
+
+    meson compile --verbose -C build
+    meson install -C build
+
+linux meson libs:
+  extends: '.build linux common'
+  script: |
+    meson setup build -Dbrotli=enabled \
+                      -Dbzip2=enabled \
+                      -Dharfbuzz=disabled \
+                      -Dpng=disabled \
+                      -Dzlib=disabled
+
+    meson compile --verbose -C build
+    meson install -C build
+
+linux cmake:
+  extends: '.build linux common'
+  script: |
+    cmake -B build -D FT_DISABLE_BROTLI=TRUE \
+                   -D FT_DISABLE_BZIP2=TRUE \
+                   -D FT_DISABLE_HARFBUZZ=TRUE \
+                   -D FT_DISABLE_PNG=TRUE \
+                   -D FT_DISABLE_ZLIB=TRUE
+
+    cmake --build build --target install
+
+linux cmake libs:
+  extends: '.build linux common'
+  script: |
+    cmake -B build -D FT_REQUIRE_BROTLI=TRUE \
+                   -D FT_REQUIRE_BZIP2=TRUE \
+                   -D FT_REQUIRE_HARFBUZZ=TRUE \
+                   -D FT_REQUIRE_PNG=TRUE \
+                   -D FT_REQUIRE_ZLIB=TRUE
+
+    cmake --build build --target install
+
+macos autotools:
+  extends: '.build macos common'
+  before_script:
+    - '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"'
+  script:
+    - brew install autoconf automake libtool
+    - ./autogen.sh
+    - ./configure
+    - 'make -j$(sysctl -n hw.logicalcpu)'
+    - make install
+
+macos autotools clang:
+  extends: '.build macos common'
+  before_script:
+    - '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"'
+  script:
+    - brew install autoconf automake libtool
+    - ./autogen.sh
+    - './configure CC=clang'
+    - 'make -j$(sysctl -n hw.logicalcpu)'
+    - make install
+
+macos meson:
+  extends: '.build macos common'
+  script:
+    - pip3 install --upgrade pip
+    - pip3 install -U meson
+    - pip3 install --upgrade certifi
+    - pip3 install -U ninja
+    
+    - meson setup build
+    - meson compile --verbose -C build
+    - sudo meson install -C build
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..b452dff
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "dlg"]
+	path = subprojects/dlg
+	url = https://github.com/nyorain/dlg.git
diff --git a/.mailmap b/.mailmap
index 52d0506..af1e61e 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1,10 +1,21 @@
+Behdad Esfahbod (بهداد اسفهبد) <behdad@behdad.org> <behdad.esfahbod@gmail.com>
+Behdad Esfahbod (بهداد اسفهبد) <behdad@behdad.org> <behdad@google.com>
+Behdad Esfahbod (بهداد اسفهبد) <behdad@behdad.org>
+Ewald Hew (Hew Yih Shiuan 丘毅宣) <ewaldhew@gmail.com>
+Priyesh Kumar (प्रियेश कुमार) <priyeshkkumar@gmail.com>
 Alexei Podtelezhnikov (Алексей Подтележников) <apodtele@gmail.com>
-Behdad Esfahbod <behdad@behdad.org> <behdad.esfahbod@gmail.com>
-Bram Tassyns <bramt@enfocus.be> bram tassyns <BramT@enfocus.be>
-Bram Tassyns <bramt@enfocus.be> <BramT@enfocus.com>
+Nikhil Ramakrishnan (निखिल रामकृष्णन) <ramakrishnan.nikhil@gmail.com>
+Dominik Röttsches <drott@chromium.org> <drott@google.com>
+Kostya Serebryany <kcc@google.com> <konstantin.s.serebryany@gmail.com>
 Suzuki, Toshiya (鈴木俊哉) <mpsuzuki@hiroshima-u.ac.jp> <sssa@flavor1.ipc.hiroshima-u.ac.jp>
 Suzuki, Toshiya (鈴木俊哉) <mpsuzuki@hiroshima-u.ac.jp> sssa <sssa@IPA2004-mps.local>
+Suzuki, Toshiya (鈴木俊哉) <mpsuzuki@hiroshima-u.ac.jp> sssa <sssa@sssas-powerbook-g4-12.local>
 Suzuki, Toshiya (鈴木俊哉) <mpsuzuki@hiroshima-u.ac.jp> suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
+Bram Tassyns <bramt@enfocus.be> bram tassyns <BramT@enfocus.be>
+Bram Tassyns <bramt@enfocus.be> <BramT@enfocus.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>
-Ewald Hew (Hew Yih Shiuan 丘毅宣) <ewaldhew@gmail.com>
-Nikhil Ramakrishnan (निखिल रामकृष्णन) <ramakrishnan.nikhil@gmail.com>
+Ben Wagner <bungeman@gmail.com> <bungeman@google.com>
+Nikolaus Waxweiler <madigens@gmail.com> <nikolaus.waxweiler@daltonmaag.com>
diff --git a/Android.bp b/Android.bp
index 127d6e6..90c3ce8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -71,6 +71,7 @@
         "src/pshinter/pshinter.c",
         "src/psnames/psnames.c",
         "src/raster/raster.c",
+        "src/sdf/sdf.c",
         "src/sfnt/sfnt.c",
         "src/smooth/smooth.c",
         "src/truetype/truetype.c",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3ed55aa..4335d66 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 # CMakeLists.txt
 #
-# Copyright (C) 2013-2020 by
+# Copyright (C) 2013-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # Written originally by John Cary <cary@txcorp.com>
@@ -12,13 +12,17 @@
 # fully.
 #
 #
-# The following will 1. create a build directory and 2. change into it and
+# The following will (1) create a build directory, and (2) change into it and
 # call cmake to configure the build with default parameters as a static
-# library. See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
-# for information about Debug, Release, etc. builds.
+# library.  See
+#
+#   https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
+#
+# for information about debug or release builds, for example
 #
 #   cmake -B build -D CMAKE_BUILD_TYPE=Release
 #
+#
 # For a dynamic library, use
 #
 #   cmake -B build -D BUILD_SHARED_LIBS=true -D CMAKE_BUILD_TYPE=Release
@@ -39,7 +43,8 @@
 #
 #   cmake -E chdir build cmake -G Xcode -D IOS_PLATFORM=SIMULATOR64 ..
 #
-# Finally, build the project with:
+#
+# Finally, build the project with
 #
 #   cmake --build build
 #
@@ -56,40 +61,47 @@
 #
 # Some notes.
 #
-# . `cmake' creates configuration files in
+# - `cmake' creates configuration files in
 #
 #     <build-directory>/include/freetype/config
 #
 #   which should be further modified if necessary.
 #
-# . You can use `cmake' directly on a freshly cloned FreeType git
+# - You can use `cmake' directly on a freshly cloned FreeType git
 #   repository.
 #
-# . `CMakeLists.txt' is provided as-is since it is normally not used by the
+# - `CMakeLists.txt' is provided as-is since it is normally not used by the
 #   developer team.
 #
-# . Set the `FT_WITH_ZLIB', `FT_WITH_BZIP2', `FT_WITH_PNG',
-#   `FT_WITH_HARFBUZZ', and `FT_WITH_BROTLI' CMake variables to `ON' to
-#   force using a dependency.  Leave a variable undefined (which is the
-#   default) to use the dependency only if it is available. Example:
+# - Set the `FT_REQUIRE_ZLIB', `FT_REQUIRE_BZIP2', `FT_REQUIRE_PNG',
+#   `FT_REQUIRE_HARFBUZZ', and `FT_REQUIRE_BROTLI' CMake variables to `ON'
+#   or `TRUE' to force using a dependency.  Leave a variable undefined
+#   (which is the default) to use the dependency only if it is available.
+#   Example:
 #
-#     cmake -B build -D FT_WITH_ZLIB=ON \
-#                    -D FT_WITH_BZIP2=ON \
-#                    -D FT_WITH_PNG=ON \
-#                    -D FT_WITH_HARFBUZZ=ON \
-#                    -D FT_WITH_BROTLI=ON [...]
+#     cmake -B build -D FT_REQUIRE_ZLIB=TRUE \
+#                    -D FT_REQUIRE_BZIP2=TRUE \
+#                    -D FT_REQUIRE_PNG=TRUE \
+#                    -D FT_REQUIRE_HARFBUZZ=TRUE \
+#                    -D FT_REQUIRE_BROTLI=TRUE [...]
 #
-#   Set `CMAKE_DISABLE_FIND_PACKAGE_XXX=TRUE' to disable a dependency completely
-#   (where `XXX' is a CMake package name like `BZip2').  Example for disabling all
+# - Set `FT_DISABLE_XXX=TRUE' to disable a dependency completely (where
+#   `XXX' is a CMake package name like `BZip2').  Example for disabling all
 #   dependencies:
 #
-#     cmake -B build -D CMAKE_DISABLE_FIND_PACKAGE_ZLIB=TRUE \
-#                    -D CMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE \
-#                    -D CMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE \
-#                    -D CMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE \
-#                    -D CMAKE_DISABLE_FIND_PACKAGE_BrotliDec=TRUE [...]
+#     cmake -B build -D FT_DISABLE_ZLIB=TRUE \
+#                    -D FT_DISABLE_BZIP2=TRUE \
+#                    -D FT_DISABLE_PNG=TRUE \
+#                    -D FT_DISABLE_HARFBUZZ=TRUE \
+#                    -D FT_DISABLE_BROTLI=TRUE [...]
 #
-# . Installation of FreeType can be controlled with the CMake variables
+# - NOTE: If a package is set as DISABLED, it cannot be set as REQUIRED
+#   without unsetting the DISABLED value first.  For example, if
+#   `FT_DISABLE_HARFBUZZ=TRUE' has been set (Cache is present), you need to
+#   call `FT_DISABLE_HARFBUZZ=FALSE' before calling
+#   `FT_REQUIRE_HARFBUZZ=TRUE'.
+#
+# - Installation of FreeType can be controlled with the CMake variables
 #   `SKIP_INSTALL_HEADERS', `SKIP_INSTALL_LIBRARIES', and `SKIP_INSTALL_ALL'
 #   (this is compatible with the same CMake variables in zlib's CMake
 #   support).
@@ -103,9 +115,13 @@
   # Allow symbol visibility settings also on static libraries. CMake < 3.3
   # only sets the property on a shared library build.
   cmake_policy(SET CMP0063 NEW)
+
+  # Support new IN_LIST if() operator.
+  cmake_policy(SET CMP0057 NEW)
 endif ()
 
 include(CheckIncludeFile)
+include(CMakeDependentOption)
 
 # CMAKE_TOOLCHAIN_FILE must be set before `project' is called, which
 # configures the base build environment and references the toolchain file
@@ -146,8 +162,8 @@
 project(freetype C)
 
 set(VERSION_MAJOR "2")
-set(VERSION_MINOR "10")
-set(VERSION_PATCH "4")
+set(VERSION_MINOR "11")
+set(VERSION_PATCH "1")
 
 # Generate LIBRARY_VERSION and LIBRARY_SOVERSION.
 set(LIBTOOL_REGEX "version_info='([0-9]+):([0-9]+):([0-9]+)'")
@@ -168,13 +184,37 @@
 math(EXPR LIBRARY_SOVERSION "${LIBTOOL_CURRENT} - ${LIBTOOL_AGE}")
 set(LIBRARY_VERSION "${LIBRARY_SOVERSION}.${LIBTOOL_AGE}.${LIBTOOL_REVISION}")
 
-# External dependency library detection is automatic. See the notes at the top
-# of this file, for how to force or disable dependencies completely.
-option(FT_WITH_ZLIB "Use system zlib instead of internal library." OFF)
-option(FT_WITH_BZIP2 "Support bzip2 compressed fonts." OFF)
-option(FT_WITH_PNG "Support PNG compressed OpenType embedded bitmaps." OFF)
-option(FT_WITH_HARFBUZZ "Improve auto-hinting of OpenType fonts." OFF)
-option(FT_WITH_BROTLI "Support compressed WOFF2 fonts." OFF)
+# External dependency library detection is automatic.  See the notes at the
+# top of this file, for how to force or disable dependencies completely.
+option(FT_DISABLE_ZLIB
+  "Disable use of system zlib and use internal zlib library instead." OFF)
+cmake_dependent_option(FT_REQUIRE_ZLIB
+  "Require system zlib instead of internal zlib library." OFF
+  "NOT FT_DISABLE_ZLIB" OFF)
+
+option(FT_DISABLE_BZIP2
+  "Disable support of bzip2 compressed fonts." OFF)
+cmake_dependent_option(FT_REQUIRE_BZIP2
+  "Require support of bzip2 compressed fonts." OFF
+  "NOT FT_DISABLE_BZIP2" OFF)
+
+option(FT_DISABLE_PNG
+  "Disable support of PNG compressed OpenType embedded bitmaps." OFF)
+cmake_dependent_option(FT_REQUIRE_PNG
+  "Require support of PNG compressed OpenType embedded bitmaps." OFF
+  "NOT FT_DISABLE_PNG" OFF)
+
+option(FT_DISABLE_HARFBUZZ
+  "Disable HarfBuzz (used for improving auto-hinting of OpenType fonts)." OFF)
+cmake_dependent_option(FT_REQUIRE_HARFBUZZ
+  "Require HarfBuzz for improving auto-hinting of OpenType fonts." OFF
+  "NOT FT_DISABLE_HARFBUZZ" OFF)
+
+option(FT_DISABLE_BROTLI
+  "Disable support of compressed WOFF2 fonts." OFF)
+cmake_dependent_option(FT_REQUIRE_BROTLI
+  "Require support of compressed WOFF2 fonts." OFF
+  "NOT FT_DISABLE_BROTLI" OFF)
 
 
 # Disallow in-source builds
@@ -205,35 +245,45 @@
 
 
 # Find dependencies
-set(HARFBUZZ_MIN_VERSION "1.8.0")
-if (FT_WITH_HARFBUZZ)
-  find_package(HarfBuzz ${HARFBUZZ_MIN_VERSION} REQUIRED)
-else ()
-  find_package(HarfBuzz ${HARFBUZZ_MIN_VERSION})
+if (NOT FT_DISABLE_HARFBUZZ)
+  set(HARFBUZZ_MIN_VERSION "2.0.0")
+  if (FT_REQUIRE_HARFBUZZ)
+    find_package(HarfBuzz ${HARFBUZZ_MIN_VERSION} REQUIRED)
+  else ()
+    find_package(HarfBuzz ${HARFBUZZ_MIN_VERSION})
+  endif ()
 endif ()
 
-if (FT_WITH_PNG)
-  find_package(PNG REQUIRED)
-else ()
-  find_package(PNG)
+if (NOT FT_DISABLE_PNG)
+  if (FT_REQUIRE_PNG)
+    find_package(PNG REQUIRED)
+  else ()
+    find_package(PNG)
+  endif ()
 endif ()
 
-if (FT_WITH_ZLIB)
-  find_package(ZLIB REQUIRED)
-else ()
-  find_package(ZLIB)
+if (NOT FT_DISABLE_ZLIB)
+  if (FT_REQUIRE_ZLIB)
+    find_package(ZLIB REQUIRED)
+  else ()
+    find_package(ZLIB)
+  endif ()
 endif ()
 
-if (FT_WITH_BZIP2)
-  find_package(BZip2 REQUIRED)
-else ()
-  find_package(BZip2)
+if (NOT FT_DISABLE_BZIP2)
+  if (FT_REQUIRE_BZIP2)
+    find_package(BZip2 REQUIRED)
+  else ()
+    find_package(BZip2)
+  endif ()
 endif ()
 
-if (FT_WITH_BROTLI)
-  find_package(BrotliDec REQUIRED)
-else ()
-  find_package(BrotliDec)
+if (NOT FT_DISABLE_BROTLI)
+  if (FT_REQUIRE_BROTLI)
+    find_package(BrotliDec REQUIRED)
+  else ()
+    find_package(BrotliDec)
+  endif ()
 endif ()
 
 # Create the configuration file
@@ -347,6 +397,7 @@
   src/pshinter/pshinter.c
   src/psnames/psnames.c
   src/raster/raster.c
+  src/sdf/sdf.c
   src/sfnt/sfnt.c
   src/smooth/smooth.c
   src/truetype/truetype.c
@@ -357,6 +408,8 @@
 
 if (UNIX)
   list(APPEND BASE_SRCS "builds/unix/ftsystem.c")
+elseif (WIN32)
+  list(APPEND BASE_SRCS "builds/windows/ftsystem.c")
 else ()
   list(APPEND BASE_SRCS "src/base/ftsystem.c")
 endif ()
@@ -420,7 +473,7 @@
     PRIVATE
       ${CMAKE_CURRENT_BINARY_DIR}/include
       ${CMAKE_CURRENT_SOURCE_DIR}/include
-      
+
       # Make <ftconfig.h> available for builds/unix/ftsystem.c.
       ${CMAKE_CURRENT_BINARY_DIR}/include/freetype/config
 )
@@ -440,6 +493,7 @@
 
 
 set(PKG_CONFIG_REQUIRED_PRIVATE "")
+set(PKG_CONFIG_LIBS_PRIVATE "")
 
 if (ZLIB_FOUND)
   target_link_libraries(freetype PRIVATE ${ZLIB_LIBRARIES})
@@ -449,7 +503,7 @@
 if (BZIP2_FOUND)
   target_link_libraries(freetype PRIVATE ${BZIP2_LIBRARIES})
   target_include_directories(freetype PRIVATE ${BZIP2_INCLUDE_DIR}) # not BZIP2_INCLUDE_DIRS
-  list(APPEND PKG_CONFIG_REQUIRED_PRIVATE "bzip2")
+  list(APPEND PKG_CONFIG_LIBS_PRIVATE "-lbz2")
 endif ()
 if (PNG_FOUND)
   target_link_libraries(freetype PRIVATE ${PNG_LIBRARIES})
@@ -457,9 +511,9 @@
   target_include_directories(freetype PRIVATE ${PNG_INCLUDE_DIRS})
   list(APPEND PKG_CONFIG_REQUIRED_PRIVATE "libpng")
 endif ()
-if (HARFBUZZ_FOUND)
-  target_link_libraries(freetype PRIVATE ${HARFBUZZ_LIBRARIES})
-  target_include_directories(freetype PRIVATE ${HARFBUZZ_INCLUDE_DIRS})
+if (HarfBuzz_FOUND)
+  target_link_libraries(freetype PRIVATE ${HarfBuzz_LIBRARY})
+  target_include_directories(freetype PRIVATE ${HarfBuzz_INCLUDE_DIRS})
   list(APPEND PKG_CONFIG_REQUIRED_PRIVATE "harfbuzz >= ${HARFBUZZ_MIN_VERSION}")
 endif ()
 if (BROTLIDEC_FOUND)
@@ -491,41 +545,39 @@
 
 if (NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL)
   # Generate the pkg-config file
-  if (UNIX)
-    file(READ "${PROJECT_SOURCE_DIR}/builds/unix/freetype2.in" FREETYPE2_PC_IN)
+  file(READ "${PROJECT_SOURCE_DIR}/builds/unix/freetype2.in" FREETYPE2_PC_IN)
 
-    string(REPLACE ";" ", " PKG_CONFIG_REQUIRED_PRIVATE "${PKG_CONFIG_REQUIRED_PRIVATE}")
+  string(REPLACE ";" ", " PKG_CONFIG_REQUIRED_PRIVATE "${PKG_CONFIG_REQUIRED_PRIVATE}")
 
-    string(REPLACE "%prefix%" ${CMAKE_INSTALL_PREFIX}
-           FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
-    string(REPLACE "%exec_prefix%" "\${prefix}"
-           FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
-    string(REPLACE "%libdir%" "\${prefix}/${CMAKE_INSTALL_LIBDIR}"
-           FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
-    string(REPLACE "%includedir%" "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}"
-           FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
-    string(REPLACE "%ft_version%" "${LIBTOOL_CURRENT}.${LIBTOOL_REVISION}.${LIBTOOL_AGE}"
-           FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
-    string(REPLACE "%REQUIRES_PRIVATE%" "${PKG_CONFIG_REQUIRED_PRIVATE}"
-           FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
-    string(REPLACE "%LIBS_PRIVATE%" ""  # All libs support pkg-config
-           FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
+  string(REPLACE "%prefix%" ${CMAKE_INSTALL_PREFIX}
+          FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
+  string(REPLACE "%exec_prefix%" "\${prefix}"
+          FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
+  string(REPLACE "%libdir%" "\${prefix}/${CMAKE_INSTALL_LIBDIR}"
+          FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
+  string(REPLACE "%includedir%" "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}"
+          FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
+  string(REPLACE "%ft_version%" "${LIBTOOL_CURRENT}.${LIBTOOL_REVISION}.${LIBTOOL_AGE}"
+          FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
+  string(REPLACE "%REQUIRES_PRIVATE%" "${PKG_CONFIG_REQUIRED_PRIVATE}"
+          FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
+  string(REPLACE "%LIBS_PRIVATE%" "${PKG_CONFIG_LIBS_PRIVATE}"
+          FREETYPE2_PC_IN ${FREETYPE2_PC_IN})
 
-    set(FREETYPE2_PC_IN_NAME "${PROJECT_BINARY_DIR}/freetype2.pc")
-    if (EXISTS "${FREETYPE2_PC_IN_NAME}")
-      file(READ "${FREETYPE2_PC_IN_NAME}" ORIGINAL_FREETYPE2_PC_IN)
-    else ()
-      set(ORIGINAL_FREETYPE2_PC_IN "")
-    endif ()
-    if (NOT (ORIGINAL_FREETYPE2_PC_IN STREQUAL FREETYPE2_PC_IN))
-      file(WRITE "${FREETYPE2_PC_IN_NAME}" ${FREETYPE2_PC_IN})
-    endif ()
-
-    install(
-      FILES ${PROJECT_BINARY_DIR}/freetype2.pc
-      DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
-      COMPONENT pkgconfig)
+  set(FREETYPE2_PC_IN_NAME "${PROJECT_BINARY_DIR}/freetype2.pc")
+  if (EXISTS "${FREETYPE2_PC_IN_NAME}")
+    file(READ "${FREETYPE2_PC_IN_NAME}" ORIGINAL_FREETYPE2_PC_IN)
+  else ()
+    set(ORIGINAL_FREETYPE2_PC_IN "")
   endif ()
+  if (NOT (ORIGINAL_FREETYPE2_PC_IN STREQUAL FREETYPE2_PC_IN))
+    file(WRITE "${FREETYPE2_PC_IN_NAME}" ${FREETYPE2_PC_IN})
+  endif ()
+
+  install(
+    FILES ${PROJECT_BINARY_DIR}/freetype2.pc
+    DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
+    COMPONENT pkgconfig)
 
   include(CMakePackageConfigHelpers)
   write_basic_package_version_file(
@@ -557,7 +609,7 @@
 set(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME})
 set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The FreeType font rendering library.")
 set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/docs/LICENSE.TXT")
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.TXT")
 
 set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
 set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
diff --git a/LICENSE.TXT b/LICENSE.TXT
new file mode 100644
index 0000000..b1def65
--- /dev/null
+++ b/LICENSE.TXT
@@ -0,0 +1,42 @@
+FREETYPE LICENSES
+-----------------
+
+The FreeType  2 font  engine is  copyrighted work  and cannot  be used
+legally without  a software  license.  In order  to make  this project
+usable to  a vast majority of  developers, we distribute it  under two
+mutually exclusive open-source licenses.
+
+This means that *you* must choose  *one* of the two licenses described
+below, then obey all its terms and conditions when using FreeType 2 in
+any of your projects or products.
+
+  - The FreeType License,  found in the file  `docs/FTL.TXT`, which is
+    similar to the  original BSD license *with*  an advertising clause
+    that forces  you to explicitly  cite the FreeType project  in your
+    product's  documentation.  All  details are  in the  license file.
+    This license is suited to products which don't use the GNU General
+    Public License.
+
+    Note that  this license  is compatible to  the GNU  General Public
+    License version 3, but not version 2.
+
+  - The   GNU   General   Public   License   version   2,   found   in
+    `docs/GPLv2.TXT`  (any  later  version  can  be  used  also),  for
+    programs  which  already  use  the  GPL.  Note  that  the  FTL  is
+    incompatible with GPLv2 due to its advertisement clause.
+
+The contributed  BDF and PCF  drivers come  with a license  similar to
+that  of the  X Window  System.   It is  compatible to  the above  two
+licenses (see files `src/bdf/README`  and `src/pcf/README`).  The same
+holds   for   the   source    code   files   `src/base/fthash.c`   and
+`include/freetype/internal/fthash.h`; they wer part  of the BDF driver
+in earlier FreeType versions.
+
+The gzip  module uses the  zlib license (see  `src/gzip/zlib.h`) which
+too is compatible to the above two licenses.
+
+The  MD5 checksum  support  (only used  for  debugging in  development
+builds) is in the public domain.
+
+
+--- end of LICENSE.TXT ---
diff --git a/METADATA b/METADATA
index 7fd0dc5..48c8f42 100644
--- a/METADATA
+++ b/METADATA
@@ -16,4 +16,7 @@
     month: 10
     day: 22
   }
+  security {
+      tag: "NVD-CPE2.3:cpe:/a:freetype:freetype:2.10.4"
+  }
 }
diff --git a/Makefile b/Makefile
index e1d1469..f128417 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/README b/README
index e4c8cf1..6a320df 100644
--- a/README
+++ b/README
@@ -1,92 +1,98 @@
-  FreeType 2.10.4
-  ===============
+FreeType 2.11.1
+===============
 
-  Homepage: https://www.freetype.org
+Homepage: https://www.freetype.org
 
-  FreeType is a freely available software library to render fonts.
+FreeType is a freely available software library to render fonts.
 
-  It  is  written  in  C,  designed to  be  small,  efficient,  highly
-  customizable, and  portable while capable of  producing high-quality
-  output  (glyph  images) of  most  vector  and bitmap  font  formats.
+It  is  written  in  C,   designed  to  be  small,  efficient,  highly
+customizable,  and portable  while capable  of producing  high-quality
+output (glyph images) of most vector and bitmap font formats.
 
-  Please   read   the  docs/CHANGES   file,   it  contains   IMPORTANT
-  INFORMATION.
+Please   read  the   `docs/CHANGES`   file,   it  contains   IMPORTANT
+INFORMATION.
 
-  Read the  files `docs/INSTALL*'  for installation  instructions; see
-  the file `docs/LICENSE.TXT' for the available licenses.
+Read the files `docs/INSTALL*`  for installation instructions; see the
+file `docs/LICENSE.TXT` for the available licenses.
 
-  The FreeType  2 API  reference is located  in `docs/reference/site';
-  use the file `index.html' as the top entry point.  [Please note that
-  currently the  search function  for locally  installed documentation
-  doesn't work due to cross-site scripting issues.]
+For using FreeType's git repository  instead of a distribution bundle,
+please read file `README.git`.
 
-  Additional documentation is available as a separate package from our
-  sites.  Go to
+The FreeType 2 API reference is located in directory `docs/reference`;
+use the file  `index.html` as the top entry point.   [Please note that
+currently  the search  function  for  locally installed  documentation
+doesn't work due to cross-site scripting issues.]
 
-    https://download.savannah.gnu.org/releases/freetype/
+Additional documentation is  available as a separate  package from our
+sites.  Go to
 
-  and download one of the following files.
+  https://download.savannah.gnu.org/releases/freetype/
 
-    freetype-doc-2.10.4.tar.xz
-    freetype-doc-2.10.4.tar.gz
-    ftdoc2104.zip
+and download one of the following files.
 
-  To view the documentation online, go to
+  freetype-doc-2.11.1.tar.xz
+  freetype-doc-2.11.1.tar.gz
+  ftdoc2111.zip
 
-    https://www.freetype.org/freetype2/docs/
+To view the documentation online, go to
+
+  https://www.freetype.org/freetype2/docs/
 
 
-  Mailing Lists
-  =============
+Mailing Lists
+-------------
 
-  The preferred way  of communication with the FreeType  team is using
-  e-mail lists.
+The preferred  way of  communication with the  FreeType team  is using
+e-mail lists.
 
-    general use and discussion:      freetype@nongnu.org
-    engine internals, porting, etc.: freetype-devel@nongnu.org
-    announcements:                   freetype-announce@nongnu.org
-    git repository tracker:          freetype-commit@nongnu.org
+  general use and discussion:      freetype@nongnu.org
+  engine internals, porting, etc.: freetype-devel@nongnu.org
+  announcements:                   freetype-announce@nongnu.org
+  git repository tracker:          freetype-commit@nongnu.org
 
-  The lists are moderated; see
+The lists are moderated; see
 
-    https://www.freetype.org/contact.html
+  https://www.freetype.org/contact.html
 
-  how to subscribe.
+how to subscribe.
 
 
-  Bugs
-  ====
+Bugs
+----
 
-  Please submit bug reports at
+Please submit bug reports at
 
-    https://savannah.nongnu.org/bugs/?group=freetype
+  https://gitlab.freedesktop.org/freetype/freetype/-/issues
 
-  Alternatively,    you   might    report    bugs    by   e-mail    to
-  `freetype-devel@nongnu.org'.   Don't  forget   to  send  a  detailed
-  explanation of the problem --  there is nothing worse than receiving
-  a terse message that only says `it doesn't work'.
+Alternatively,    you    might    report    bugs    by    e-mail    to
+`freetype-devel@nongnu.org`.    Don't  forget   to  send   a  detailed
+explanation of the problem -- there  is nothing worse than receiving a
+terse message that only says 'it doesn't work'.
 
 
-  Patches
-  =======
+Patches
+-------
 
-  Please  submit patches  to  the `freetype-devel@nongnu.org'  mailing
-  list  --  and thank  you  in  advance  for  your work  on  improving
-  FreeType!
+For larger changes please provide merge requests at
 
-  Details on the process can be found here:
+  https://gitlab.freedesktop.org/freetype/freetype/-/merge_requests
 
-    https://www.freetype.org/developer.html#patches
+Alternatively, you can send patches to the `freetype-devel@nongnu.org`
+mailing list  -- and thank you  in advance for your  work on improving
+FreeType!
+
+Details on the process can be found here:
+
+  https://www.freetype.org/developer.html#patches
 
 
-  Enjoy!
+Enjoy!
 
-
-    The FreeType Team
+  The FreeType Team
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2006-2020 by
+Copyright (C) 2006-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/README.git b/README.git
index c4f0033..ad3c74c 100644
--- a/README.git
+++ b/README.git
@@ -1,4 +1,36 @@
-The git  archive doesn't  contain pre-built configuration  scripts for
+README.git
+==========
+
+
+repository issues
+-----------------
+
+FreeType's official repository site is
+
+  https://gitlab.freedesktop.org/freetype  ,
+
+from  which the  'freetype.git' and  'freetype-demos.git' repositories
+can be cloned in the usual way.
+
+  git clone https://gitlab.freedesktop.org/freetype/freetype.git
+  git clone https://gitlab.freedesktop.org/freetype/freetype-demos.git
+
+If you  want to  use the  Savannah mirror  instead, you  have to  do a
+slightly different  incantation because  the repository  names contain
+digit '2' for historical reasons.
+
+  git clone \
+    https://git.savannah.nongnu.org/git/freetype/freetype2.git \
+    freetype
+  git clone \
+    https://git.savannah.nongnu.org/git/freetype/freetype2-demos.git \
+    freetype-demos
+
+
+standard builds with `configure`
+--------------------------------
+
+The git repository doesn't contain pre-built configuration scripts for
 UNIXish platforms.  To generate them say
 
   sh autogen.sh
@@ -10,34 +42,54 @@
   autoconf (2.62)
 
 The versions given  in parentheses are known to  work.  Newer versions
-should work too, of course.   Note that autogen.sh also sets up proper
-file permissions for the `configure' and auxiliary scripts.
+should  work too,  of course.   Note  that `autogen.sh`  also sets  up
+proper file permissions for the `configure` and auxiliary scripts.
 
-The autogen.sh script  now checks the version of  above three packages
-whether they match the numbers  above.  Otherwise it will complain and
-suggest either upgrading or using  an environment variable to point to
-a more recent version of the required tool(s).
+The `autogen.sh` script checks whether the versions of the above three
+tools match the numbers above.  Otherwise it will complain and suggest
+either  upgrading or  using  environment variables  to  point to  more
+recent versions of the required tools.
 
-Note that  `aclocal' is provided  by the `automake' package  on Linux,
-and that `libtoolize' is called `glibtoolize' on Darwin (OS X).
+Note that  `aclocal` is provided  by the 'automake' package  on Linux,
+and that `libtoolize` is called `glibtoolize` on Darwin (OS X).
 
 
-For static builds which  don't use platform specific optimizations, no
+alternative build methods
+-------------------------
+
+For static  builds that don't use  platform-specific optimizations, no
 configure script is necessary at all; saying
 
   make setup ansi
   make
 
-should work on all platforms which have GNU make (or makepp).
+should work on all platforms that have GNU `make` (or `makepp`).
+
+A build  with `cmake`  or `meson`  can be done  directly from  the git
+repository.  However, if you want  to use the `FT_DEBUG_LOGGING` macro
+(see file `docs/DEBUG` for more information) it is currently mandatory
+to execute `autogen.sh`  in advance; this script clones  the 'dlg' git
+submodule and copies some files into FreeType's source tree.
 
 
-Similarly, a  build with  `cmake' can  be done  directly from  the git
-repository.
+Code of Conduct
+---------------
 
+Please note that  this project is released with a  Contributor Code of
+Conduct (CoC).  By participating in this project you agree to abide by
+its terms, which you can find in the following link:
+
+  https://www.freedesktop.org/wiki/CodeOfConduct
+
+CoC issues may  be raised to the project maintainers  at the following
+address:
+
+  wl@gnu.org
+  apodtele@gmail.com
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2005-2020 by
+Copyright (C) 2005-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/autogen.sh b/autogen.sh
index 79c4e4e..8cca7c8 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# Copyright (C) 2005-2020 by
+# Copyright (C) 2005-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -110,7 +110,10 @@
   fi
 }
 
-if test ! -f ./builds/unix/configure.raw; then
+# Solaris 10's shell doesn't like the `!` operator to negate the exit status.
+if test -f ./builds/unix/configure.raw; then
+  :
+else
   echo "You must be in the same directory as \`autogen.sh'."
   echo "Bootstrapping doesn't work if srcdir != builddir."
   exit 1
@@ -138,18 +141,25 @@
 check_tool_version $LIBTOOLIZE libtoolize LIBTOOLIZE 2.2.4
 check_tool_version $AUTOCONF   autoconf   AUTOCONF   2.62
 
-# This sets freetype_major, freetype_minor, and freetype_patch.
-eval `sed -nf version.sed include/freetype/freetype.h`
+# This sets FREETYPE version.
+eval `sed -n \
+-e 's/^#define  *\(FREETYPE_MAJOR\)  *\([0-9][0-9]*\).*/\1=\2/p' \
+-e 's/^#define  *\(FREETYPE_MINOR\)  *\([0-9][0-9]*\).*/\1=\2/p' \
+-e 's/^#define  *\(FREETYPE_PATCH\)  *\([0-9][0-9]*\).*/\1=\2/p' \
+include/freetype/freetype.h`
 
-# We set freetype-patch to an empty value if it is zero.
-if test "$freetype_patch" = ".0"; then
-  freetype_patch=
+if test "$FREETYPE_PATCH" = "0"; then
+  FREETYPE=$FREETYPE_MAJOR.$FREETYPE_MINOR
+else
+  FREETYPE=$FREETYPE_MAJOR.$FREETYPE_MINOR.$FREETYPE_PATCH
 fi
 
+echo "FreeType $FREETYPE:"
+
 cd builds/unix
 
 echo "generating \`configure.ac'"
-sed -e "s;@VERSION@;$freetype_major$freetype_minor$freetype_patch;" \
+sed -e "s;@VERSION@;$FREETYPE;" \
   < configure.raw > configure.ac
 
 run aclocal -I . --force
@@ -162,4 +172,29 @@
 
 chmod +x ./configure
 
+# Copy all necessary 'dlg' files.
+copy_submodule_files ()
+{
+  echo "Copying files from \`subprojects/dlg' to \`src/dlg' and \`include/dlg'"
+  mkdir include/dlg 2> /dev/null
+  cp $DLG_INC_DIR/output.h include/dlg
+  cp $DLG_INC_DIR/dlg.h include/dlg
+  cp $DLG_SRC_DIR/* src/dlg
+}
+
+if test -d ".git"; then
+  DLG_INC_DIR=subprojects/dlg/include/dlg
+  DLG_SRC_DIR=subprojects/dlg/src/dlg
+
+  if test -d "$DLG_INC_DIR"; then
+    :
+  else
+    echo "Checking out submodule in \`subprojects/dlg':"
+    git submodule init
+    git submodule update
+  fi
+
+  copy_submodule_files
+fi
+
 # EOF
diff --git a/builds/amiga/README b/builds/amiga/README
index c552527..4ec8770 100644
--- a/builds/amiga/README
+++ b/builds/amiga/README
@@ -1,7 +1,7 @@
 
 README for the builds/amiga subdirectory.
 
-Copyright (C) 2005-2020 by
+Copyright (C) 2005-2021 by
 Werner Lemberg and Detlef Würkner.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/amiga/include/config/ftconfig.h b/builds/amiga/include/config/ftconfig.h
index 4976c75..6deea6b 100644
--- a/builds/amiga/include/config/ftconfig.h
+++ b/builds/amiga/include/config/ftconfig.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Amiga-specific configuration file (specification only).              */
 /*                                                                         */
-/*  Copyright (C) 2005-2020 by                                             */
+/*  Copyright (C) 2005-2021 by                                             */
 /*  Werner Lemberg and Detlef Würkner.                                     */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/builds/amiga/include/config/ftmodule.h b/builds/amiga/include/config/ftmodule.h
index 6035bf0..873537c 100644
--- a/builds/amiga/include/config/ftmodule.h
+++ b/builds/amiga/include/config/ftmodule.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Amiga-specific FreeType module selection.                            */
 /*                                                                         */
-/*  Copyright (C) 2005-2020 by                                             */
+/*  Copyright (C) 2005-2021 by                                             */
 /*  Werner Lemberg and Detlef Würkner.                                     */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
diff --git a/builds/amiga/makefile b/builds/amiga/makefile
index 50315f3..ed7c780 100644
--- a/builds/amiga/makefile
+++ b/builds/amiga/makefile
@@ -5,7 +5,7 @@
 #
 
 
-# Copyright (C) 2005-2020 by
+# Copyright (C) 2005-2021 by
 # Werner Lemberg and Detlef Würkner.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/amiga/makefile.os4 b/builds/amiga/makefile.os4
index cd5151c..58c8920 100644
--- a/builds/amiga/makefile.os4
+++ b/builds/amiga/makefile.os4
@@ -4,7 +4,7 @@
 #
 
 
-# Copyright (C) 2005-2020 by
+# Copyright (C) 2005-2021 by
 # Werner Lemberg and Detlef Würkner.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/amiga/smakefile b/builds/amiga/smakefile
index fa41676..aaddd19 100644
--- a/builds/amiga/smakefile
+++ b/builds/amiga/smakefile
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2005-2020 by
+# Copyright (C) 2005-2021 by
 # Werner Lemberg and Detlef Würkner.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/amiga/src/base/ftdebug.c b/builds/amiga/src/base/ftdebug.c
index 6510d20..dc7e968 100644
--- a/builds/amiga/src/base/ftdebug.c
+++ b/builds/amiga/src/base/ftdebug.c
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component for amiga (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Detlef Wuerkner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/builds/amiga/src/base/ftsystem.c b/builds/amiga/src/base/ftsystem.c
index 1dfbd66..5c69e3a 100644
--- a/builds/amiga/src/base/ftsystem.c
+++ b/builds/amiga/src/base/ftsystem.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Amiga-specific FreeType low-level system interface (body).           */
 /*                                                                         */
-/*  Copyright (C) 1996-2020 by                                             */
+/*  Copyright (C) 1996-2021 by                                             */
 /*  David Turner, Robert Wilhelm, Werner Lemberg and Detlef Würkner.       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -264,7 +264,7 @@
 
     stream->descriptor.pointer = NULL;
     stream->size               = 0;
-    stream->base               = 0;
+    stream->base               = NULL;
   }
 
 
diff --git a/builds/ansi/ansi-def.mk b/builds/ansi/ansi-def.mk
index 9642098..218d5c0 100644
--- a/builds/ansi/ansi-def.mk
+++ b/builds/ansi/ansi-def.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -13,11 +13,11 @@
 # fully.
 
 
-DELETE    := rm -f
-CAT       := cat
-SEP       := /
-BUILD_DIR := $(TOP_DIR)/builds/ansi
-PLATFORM  := ansi
+DELETE       := rm -f
+CAT          := cat
+SEP          := /
+PLATFORM_DIR := $(TOP_DIR)/builds/ansi
+PLATFORM     := ansi
 
 # This is used for `make refdoc' and `make refdoc-venv'
 #
@@ -64,14 +64,14 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -c
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS :=
+ANSIFLAGS ?=
 
 
 # EOF
diff --git a/builds/ansi/ansi.mk b/builds/ansi/ansi.mk
index c244803..b36c64e 100644
--- a/builds/ansi/ansi.mk
+++ b/builds/ansi/ansi.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/atari/README.TXT b/builds/atari/README.TXT
index ffe6545..1300817 100644
--- a/builds/atari/README.TXT
+++ b/builds/atari/README.TXT
@@ -15,7 +15,7 @@
 
     INCLUDE;E:\freetype2\include
 
-- The file `freetype2/include/Ft2build.h' must be patched as follows to
+- The file `freetype/include/Ft2build.h' must be patched as follows to
   include ATARI.H:
 
     #ifndef FT2_BUILD_GENERIC_H_
@@ -40,7 +40,7 @@
 
     INCLUDE;E:\freetype2\include
 
-- In der Datei freetype2/include/Ft2build.h muss zu Beginn
+- In der Datei freetype/include/Ft2build.h muss zu Beginn
   ein #include "ATARI.H" wie folgt eingefgt werden:
 
     #ifndef FT2_BUILD_GENERIC_H_
diff --git a/builds/beos/beos-def.mk b/builds/beos/beos-def.mk
index 5ae7ed8..d7d63b3 100644
--- a/builds/beos/beos-def.mk
+++ b/builds/beos/beos-def.mk
@@ -5,7 +5,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -15,11 +15,11 @@
 # fully.
 
 
-DELETE    := rm -f
-CAT       := cat
-SEP       := /
-BUILD_DIR := $(TOP_DIR)/builds/beos
-PLATFORM  := beos
+DELETE       := rm -f
+CAT          := cat
+SEP          := /
+PLATFORM_DIR := $(TOP_DIR)/builds/beos
+PLATFORM     := beos
 
 # This is used for `make refdoc' and `make refdoc-venv'
 #
@@ -66,14 +66,14 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -c
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS :=
+ANSIFLAGS ?=
 
 
 # EOF
diff --git a/builds/beos/beos.mk b/builds/beos/beos.mk
index 1a082c1..f3e3fbb 100644
--- a/builds/beos/beos.mk
+++ b/builds/beos/beos.mk
@@ -2,7 +2,7 @@
 # FreeType 2 configuration rules for a BeOS system
 #
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/beos/detect.mk b/builds/beos/detect.mk
index 5b92512..521ecae 100644
--- a/builds/beos/detect.mk
+++ b/builds/beos/detect.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -27,11 +27,11 @@
 
 ifeq ($(PLATFORM),beos)
 
-  DELETE      := rm -f
-  CAT         := cat
-  SEP         := /
-  BUILD_DIR   := $(TOP_DIR)/builds/beos
-  CONFIG_FILE := beos.mk
+  DELETE         := rm -f
+  CAT            := cat
+  SEP            := /
+  PLATFORM_DIR   := $(TOP_DIR)/builds/beos
+  CONFIG_FILE    := beos.mk
 
   setup: std_setup
 
diff --git a/builds/cmake/FindBrotliDec.cmake b/builds/cmake/FindBrotliDec.cmake
index 7c484c7..46356b1 100644
--- a/builds/cmake/FindBrotliDec.cmake
+++ b/builds/cmake/FindBrotliDec.cmake
@@ -1,6 +1,6 @@
 # FindBrotliDec.cmake
 #
-# Copyright (C) 2019-2020 by
+# Copyright (C) 2019-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # Written by Werner Lemberg <wl@gnu.org>
@@ -19,7 +19,8 @@
 #   BROTLIDEC_INCLUDE_DIRS
 #   BROTLIDEC_LIBRARIES
 
-include(FindPkgConfig)
+find_package(PkgConfig QUIET)
+
 pkg_check_modules(PC_BROTLIDEC QUIET libbrotlidec)
 
 if (PC_BROTLIDEC_VERSION)
@@ -41,7 +42,7 @@
 
 include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(
-  brotlidec
+  BrotliDec
   REQUIRED_VARS BROTLIDEC_INCLUDE_DIRS BROTLIDEC_LIBRARIES
   FOUND_VAR BROTLIDEC_FOUND
   VERSION_VAR BROTLIDEC_VERSION)
diff --git a/builds/cmake/FindHarfBuzz.cmake b/builds/cmake/FindHarfBuzz.cmake
index d489613..b481fa4 100644
--- a/builds/cmake/FindHarfBuzz.cmake
+++ b/builds/cmake/FindHarfBuzz.cmake
@@ -1,4 +1,5 @@
 # Copyright (c) 2012, Intel Corporation
+# Copyright (c) 2019 Sony Interactive Entertainment Inc.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are met:
@@ -23,65 +24,180 @@
 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
-
-
-# Try to find HarfBuzz include and library directories.
+#
+# Try to find Harfbuzz include and library directories.
 #
 # After successful discovery, this will set for inclusion where needed:
-#
-#   HARFBUZZ_INCLUDE_DIRS - containg the HarfBuzz headers
-#   HARFBUZZ_LIBRARIES    - containg the HarfBuzz library
+# HarfBuzz_INCLUDE_DIRS - containg the HarfBuzz headers
+# HarfBuzz_LIBRARIES - containg the HarfBuzz library
 
-include(FindPkgConfig)
+#[=======================================================================[.rst:
+FindHarfBuzz
+--------------
+
+Find HarfBuzz headers and libraries.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+``HarfBuzz::HarfBuzz``
+  The HarfBuzz library, if found.
+
+``HarfBuzz::ICU``
+  The HarfBuzz ICU library, if found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This will define the following variables in your project:
+
+``HarfBuzz_FOUND``
+  true if (the requested version of) HarfBuzz is available.
+``HarfBuzz_VERSION``
+  the version of HarfBuzz.
+``HarfBuzz_LIBRARIES``
+  the libraries to link against to use HarfBuzz.
+``HarfBuzz_INCLUDE_DIRS``
+  where to find the HarfBuzz headers.
+``HarfBuzz_COMPILE_OPTIONS``
+  this should be passed to target_compile_options(), if the
+  target is not used for linking
+
+#]=======================================================================]
+
+find_package(PkgConfig QUIET)
 pkg_check_modules(PC_HARFBUZZ QUIET harfbuzz)
+set(HarfBuzz_COMPILE_OPTIONS ${PC_HARFBUZZ_CFLAGS_OTHER})
+set(HarfBuzz_VERSION ${PC_HARFBUZZ_CFLAGS_VERSION})
 
-find_path(HARFBUZZ_INCLUDE_DIRS
-  NAMES hb.h
-  HINTS ${PC_HARFBUZZ_INCLUDEDIR}
-        ${PC_HARFBUZZ_INCLUDE_DIRS}
-  PATH_SUFFIXES harfbuzz)
+find_path(HarfBuzz_INCLUDE_DIR
+    NAMES hb.h
+    HINTS ${PC_HARFBUZZ_INCLUDEDIR} ${PC_HARFBUZZ_INCLUDE_DIRS}
+    PATH_SUFFIXES harfbuzz
+)
 
-find_library(HARFBUZZ_LIBRARIES
-  NAMES harfbuzz
-  HINTS ${PC_HARFBUZZ_LIBDIR}
-        ${PC_HARFBUZZ_LIBRARY_DIRS})
+find_library(HarfBuzz_LIBRARY
+    NAMES ${HarfBuzz_NAMES} harfbuzz
+    HINTS ${PC_HARFBUZZ_LIBDIR} ${PC_HARFBUZZ_LIBRARY_DIRS}
+)
 
-if (HARFBUZZ_INCLUDE_DIRS)
-  if (EXISTS "${HARFBUZZ_INCLUDE_DIRS}/hb-version.h")
-    file(READ "${HARFBUZZ_INCLUDE_DIRS}/hb-version.h" _harfbuzz_version_content)
+if (HarfBuzz_INCLUDE_DIR AND NOT HarfBuzz_VERSION)
+    if (EXISTS "${HarfBuzz_INCLUDE_DIR}/hb-version.h")
+        file(READ "${HarfBuzz_INCLUDE_DIR}/hb-version.h" _harfbuzz_version_content)
 
-    string(REGEX MATCH
-           "#define +HB_VERSION_STRING +\"([0-9]+\\.[0-9]+\\.[0-9]+)\""
-           _dummy "${_harfbuzz_version_content}")
-    set(HARFBUZZ_VERSION "${CMAKE_MATCH_1}")
+        string(REGEX MATCH "#define +HB_VERSION_STRING +\"([0-9]+\\.[0-9]+\\.[0-9]+)\"" _dummy "${_harfbuzz_version_content}")
+        set(HarfBuzz_VERSION "${CMAKE_MATCH_1}")
+    endif ()
+endif ()
+
+if ("${HarfBuzz_FIND_VERSION}" VERSION_GREATER "${HarfBuzz_VERSION}")
+  if (HarfBuzz_FIND_REQUIRED)
+    message(FATAL_ERROR
+      "Required version (" ${HarfBuzz_FIND_VERSION} ")"
+      " is higher than found version (" ${HarfBuzz_VERSION} ")")
+  else ()
+    message(WARNING
+      "Required version (" ${HarfBuzz_FIND_VERSION} ")"
+      " is higher than found version (" ${HarfBuzz_VERSION} ")")
+    unset(HarfBuzz_VERSION)
+    unset(HarfBuzz_INCLUDE_DIRS)
+    unset(HarfBuzz_LIBRARIES)
+    return ()
   endif ()
 endif ()
 
-if ("${harfbuzz_FIND_VERSION}" VERSION_GREATER "${HARFBUZZ_VERSION}")
-  message(FATAL_ERROR
-    "Required version (" ${harfbuzz_FIND_VERSION} ")"
-    " is higher than found version (" ${HARFBUZZ_VERSION} ")")
+# Find components
+if (HarfBuzz_INCLUDE_DIR AND HarfBuzz_LIBRARY)
+    set(_HarfBuzz_REQUIRED_LIBS_FOUND ON)
+    set(HarfBuzz_LIBS_FOUND "HarfBuzz (required): ${HarfBuzz_LIBRARY}")
+else ()
+    set(_HarfBuzz_REQUIRED_LIBS_FOUND OFF)
+    set(HarfBuzz_LIBS_NOT_FOUND "HarfBuzz (required)")
+endif ()
+
+if (NOT CMAKE_VERSION VERSION_LESS 3.3)
+  if ("ICU" IN_LIST HarfBuzz_FIND_COMPONENTS)
+      pkg_check_modules(PC_HARFBUZZ_ICU QUIET harfbuzz-icu)
+      set(HarfBuzz_ICU_COMPILE_OPTIONS ${PC_HARFBUZZ_ICU_CFLAGS_OTHER})
+
+      find_path(HarfBuzz_ICU_INCLUDE_DIR
+          NAMES hb-icu.h
+          HINTS ${PC_HARFBUZZ_ICU_INCLUDEDIR} ${PC_HARFBUZZ_ICU_INCLUDE_DIRS}
+          PATH_SUFFIXES harfbuzz
+      )
+
+      find_library(HarfBuzz_ICU_LIBRARY
+          NAMES ${HarfBuzz_ICU_NAMES} harfbuzz-icu
+          HINTS ${PC_HARFBUZZ_ICU_LIBDIR} ${PC_HARFBUZZ_ICU_LIBRARY_DIRS}
+      )
+
+      if (HarfBuzz_ICU_LIBRARY)
+          if (HarfBuzz_FIND_REQUIRED_ICU)
+              list(APPEND HarfBuzz_LIBS_FOUND "ICU (required): ${HarfBuzz_ICU_LIBRARY}")
+          else ()
+            list(APPEND HarfBuzz_LIBS_FOUND "ICU (optional): ${HarfBuzz_ICU_LIBRARY}")
+          endif ()
+      else ()
+          if (HarfBuzz_FIND_REQUIRED_ICU)
+            set(_HarfBuzz_REQUIRED_LIBS_FOUND OFF)
+            list(APPEND HarfBuzz_LIBS_NOT_FOUND "ICU (required)")
+          else ()
+            list(APPEND HarfBuzz_LIBS_NOT_FOUND "ICU (optional)")
+          endif ()
+      endif ()
+  endif ()
+endif ()
+
+if (NOT HarfBuzz_FIND_QUIETLY)
+    if (HarfBuzz_LIBS_FOUND)
+        message(STATUS "Found the following HarfBuzz libraries:")
+        foreach (found ${HarfBuzz_LIBS_FOUND})
+            message(STATUS " ${found}")
+        endforeach ()
+    endif ()
+    if (HarfBuzz_LIBS_NOT_FOUND)
+        message(STATUS "The following HarfBuzz libraries were not found:")
+        foreach (found ${HarfBuzz_LIBS_NOT_FOUND})
+            message(STATUS " ${found}")
+        endforeach ()
+    endif ()
 endif ()
 
 include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(
-  harfbuzz
-  REQUIRED_VARS HARFBUZZ_INCLUDE_DIRS HARFBUZZ_LIBRARIES
-  VERSION_VAR HARFBUZZ_VERSION)
+find_package_handle_standard_args(HarfBuzz
+    FOUND_VAR HarfBuzz_FOUND
+    REQUIRED_VARS HarfBuzz_INCLUDE_DIR HarfBuzz_LIBRARY _HarfBuzz_REQUIRED_LIBS_FOUND
+    VERSION_VAR HarfBuzz_VERSION
+)
+
+if (NOT CMAKE_VERSION VERSION_LESS 3.1)
+  if (HarfBuzz_LIBRARY AND NOT TARGET HarfBuzz::HarfBuzz)
+      add_library(HarfBuzz::HarfBuzz UNKNOWN IMPORTED GLOBAL)
+      set_target_properties(HarfBuzz::HarfBuzz PROPERTIES
+          IMPORTED_LOCATION "${HarfBuzz_LIBRARY}"
+          INTERFACE_COMPILE_OPTIONS "${HarfBuzz_COMPILE_OPTIONS}"
+          INTERFACE_INCLUDE_DIRECTORIES "${HarfBuzz_INCLUDE_DIR}"
+      )
+  endif ()
+
+  if (HarfBuzz_ICU_LIBRARY AND NOT TARGET HarfBuzz::ICU)
+      add_library(HarfBuzz::ICU UNKNOWN IMPORTED GLOBAL)
+      set_target_properties(HarfBuzz::ICU PROPERTIES
+          IMPORTED_LOCATION "${HarfBuzz_ICU_LIBRARY}"
+          INTERFACE_COMPILE_OPTIONS "${HarfBuzz_ICU_COMPILE_OPTIONS}"
+          INTERFACE_INCLUDE_DIRECTORIES "${HarfBuzz_ICU_INCLUDE_DIR}"
+      )
+  endif ()
+endif ()
 
 mark_as_advanced(
-  HARFBUZZ_INCLUDE_DIRS
-  HARFBUZZ_LIBRARIES)
+    HarfBuzz_INCLUDE_DIR
+    HarfBuzz_ICU_INCLUDE_DIR
+    HarfBuzz_LIBRARY
+    HarfBuzz_ICU_LIBRARY
+)
 
-# Allow easy linking as in
-#
-#   target_link_libraries(freetype PRIVATE Harfbuzz::Harfbuzz)
-#
-if (NOT CMAKE_VERSION VERSION_LESS 3.1)
-  if (HARFBUZZ_FOUND AND NOT TARGET Harfbuzz::Harfbuzz)
-    add_library(Harfbuzz::Harfbuzz INTERFACE IMPORTED)
-    set_target_properties(
-        Harfbuzz::Harfbuzz PROPERTIES
-          INTERFACE_INCLUDE_DIRECTORIES "${HARFBUZZ_INCLUDE_DIRS}")
-  endif ()
+if (HarfBuzz_FOUND)
+   set(HarfBuzz_LIBRARIES ${HarfBuzz_LIBRARY} ${HarfBuzz_ICU_LIBRARY})
+   set(HarfBuzz_INCLUDE_DIRS ${HarfBuzz_INCLUDE_DIR} ${HarfBuzz_ICU_INCLUDE_DIR})
 endif ()
diff --git a/builds/cmake/iOS.cmake b/builds/cmake/iOS.cmake
index 6f46836..258654d 100644
--- a/builds/cmake/iOS.cmake
+++ b/builds/cmake/iOS.cmake
@@ -1,6 +1,6 @@
 # iOS.cmake
 #
-# Copyright (C) 2014-2020 by
+# Copyright (C) 2014-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # Written by David Wimsey <david@wimsey.us>
diff --git a/builds/cmake/testbuild.sh b/builds/cmake/testbuild.sh
index cc67abd..c6c6372 100755
--- a/builds/cmake/testbuild.sh
+++ b/builds/cmake/testbuild.sh
@@ -1,6 +1,6 @@
 #!/bin/sh -e
 
-# Copyright (C) 2015-2020 by
+# Copyright (C) 2015-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/compiler/ansi-cc.mk b/builds/compiler/ansi-cc.mk
index 78b13a4..e73e6fc 100644
--- a/builds/compiler/ansi-cc.mk
+++ b/builds/compiler/ansi-cc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -59,7 +59,7 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -c
@@ -68,7 +68,7 @@
 #
 #  we assume the compiler is already strictly ANSI
 #
-ANSIFLAGS :=
+ANSIFLAGS ?=
 
 
 # Library linking
diff --git a/builds/compiler/bcc-dev.mk b/builds/compiler/bcc-dev.mk
index 5f6f161..7180452 100644
--- a/builds/compiler/bcc-dev.mk
+++ b/builds/compiler/bcc-dev.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -60,14 +60,14 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -q -c -y -d -v -Od -w-par -w-ccc -w-rch -w-pro -w-aus
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS := -A
+ANSIFLAGS ?= -A
 
 
 # Library linking
diff --git a/builds/compiler/bcc.mk b/builds/compiler/bcc.mk
index f5e2e8a..321db10 100644
--- a/builds/compiler/bcc.mk
+++ b/builds/compiler/bcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -60,14 +60,14 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -c -q -y -d -v -Od -w-par -w-ccc -w-rch -w-pro -w-aus
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS := -A
+ANSIFLAGS ?= -A
 
 
 # Library linking
diff --git a/builds/compiler/emx.mk b/builds/compiler/emx.mk
index bbb7604..b3b6047 100644
--- a/builds/compiler/emx.mk
+++ b/builds/compiler/emx.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2003-2020 by
+# Copyright (C) 2003-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -58,14 +58,14 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -c -g -O6 -Wall
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS :=
+ANSIFLAGS ?=
 
 
 # Library linking
diff --git a/builds/compiler/gcc-dev.mk b/builds/compiler/gcc-dev.mk
index 95b5f50..f01192f 100644
--- a/builds/compiler/gcc-dev.mk
+++ b/builds/compiler/gcc-dev.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -59,7 +59,7 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 ifndef CFLAGS
@@ -82,8 +82,9 @@
 endif
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
+# You can override this on the command line.
 #
-ANSIFLAGS := -ansi -pedantic
+ANSIFLAGS ?= -std=c99 -pedantic
 
 
 # Library linking
diff --git a/builds/compiler/gcc.mk b/builds/compiler/gcc.mk
index 63cd93b..ede20b2 100644
--- a/builds/compiler/gcc.mk
+++ b/builds/compiler/gcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -58,14 +58,14 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -c -g -O3 -Wall
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS := -ansi -pedantic
+ANSIFLAGS ?= -std=c99 -pedantic
 
 
 # Library linking
diff --git a/builds/compiler/intelc.mk b/builds/compiler/intelc.mk
index b3c69b0..e5dcf90 100644
--- a/builds/compiler/intelc.mk
+++ b/builds/compiler/intelc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -61,7 +61,7 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 #   Note that the Intel C/C++ compiler version 4.5 complains about
@@ -74,7 +74,7 @@
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS := /Qansi_alias /Za
+ANSIFLAGS ?= /Qansi_alias /Za
 
 # Library linking
 #
diff --git a/builds/compiler/unix-lcc.mk b/builds/compiler/unix-lcc.mk
index 26f8e7b..40322b4 100644
--- a/builds/compiler/unix-lcc.mk
+++ b/builds/compiler/unix-lcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -60,7 +60,7 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -c -g
@@ -71,7 +71,7 @@
 #
 #  the "-A" flag simply increments verbosity about non ANSI code
 #
-ANSIFLAGS := -A
+ANSIFLAGS ?= -A
 
 
 # library linking
diff --git a/builds/compiler/visualage.mk b/builds/compiler/visualage.mk
index 4a8c8ac..ebc3e48 100644
--- a/builds/compiler/visualage.mk
+++ b/builds/compiler/visualage.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/compiler/visualc.mk b/builds/compiler/visualc.mk
index a9cf71d..dc6998a 100644
--- a/builds/compiler/visualc.mk
+++ b/builds/compiler/visualc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -63,14 +63,14 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= /nologo /c /Ox /W3 /WX
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS := /Za /D_CRT_SECURE_NO_DEPRECATE
+ANSIFLAGS ?= /Za /D_CRT_SECURE_NO_DEPRECATE
 
 
 # Library linking
diff --git a/builds/compiler/watcom.mk b/builds/compiler/watcom.mk
index 43a9e06..c1d1b66 100644
--- a/builds/compiler/watcom.mk
+++ b/builds/compiler/watcom.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -60,14 +60,14 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -zq
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
 #
-ANSIFLAGS := -za
+ANSIFLAGS ?= -za
 
 
 # Library linking
diff --git a/builds/compiler/win-lcc.mk b/builds/compiler/win-lcc.mk
index 00d9d31..27fbc30 100644
--- a/builds/compiler/win-lcc.mk
+++ b/builds/compiler/win-lcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -60,7 +60,7 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 CFLAGS ?= -c -g2 -O
@@ -69,7 +69,7 @@
 #
 #  LCC is pure ANSI anyway!
 #
-ANSIFLAGS :=
+ANSIFLAGS ?=
 
 
 # library linking
diff --git a/builds/detect.mk b/builds/detect.mk
index 94627fc..78e9e75 100644
--- a/builds/detect.mk
+++ b/builds/detect.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -16,7 +16,7 @@
 # This sub-Makefile is in charge of detecting the current platform.  It sets
 # the following variables:
 #
-#   BUILD_DIR    The configuration and system-specific directory.  Usually
+#   PLATFORM_DIR The configuration and system-specific directory.  Usually
 #                `builds/$(PLATFORM)' but can be different for custom builds
 #                of the library.
 #
@@ -49,8 +49,8 @@
 BUILD_CONFIG := $(TOP_DIR)/builds
 
 # These two assignments must be delayed.
-BUILD_DIR    = $(BUILD_CONFIG)/$(PLATFORM)
-CONFIG_RULES = $(BUILD_DIR)/$(CONFIG_FILE)
+PLATFORM_DIR = $(BUILD_CONFIG)/$(PLATFORM)
+CONFIG_RULES = $(PLATFORM_DIR)/$(CONFIG_FILE)
 
 # We define the BACKSLASH variable to hold a single back-slash character.
 # This is needed because a line like
@@ -113,7 +113,7 @@
 	$(info )
 	$(info $(empty)  platform                    $(PLATFORM))
 	$(info $(empty)  compiler                    $(CC))
-	$(info $(empty)  configuration directory     $(subst /,$(SEP),$(BUILD_DIR)))
+	$(info $(empty)  configuration directory     $(subst /,$(SEP),$(PLATFORM_DIR)))
 	$(info $(empty)  configuration rules         $(subst /,$(SEP),$(CONFIG_RULES)))
 	$(info )
 	$(info If this does not correspond to your system or settings please remove the file)
diff --git a/builds/dos/detect.mk b/builds/dos/detect.mk
index f598794..d95a2ca 100644
--- a/builds/dos/detect.mk
+++ b/builds/dos/detect.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/dos/dos-def.mk b/builds/dos/dos-def.mk
index 067d1d4..f7fbc4d 100644
--- a/builds/dos/dos-def.mk
+++ b/builds/dos/dos-def.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -13,11 +13,11 @@
 # fully.
 
 
-DELETE    := del
-CAT       := type
-SEP       := $(strip \ )
-BUILD_DIR := $(TOP_DIR)/builds/dos
-PLATFORM  := dos
+DELETE       := del
+CAT          := type
+SEP          := $(strip \ )
+PLATFORM_DIR := $(TOP_DIR)/builds/dos
+PLATFORM     := dos
 
 # This is used for `make refdoc' and `make refdoc-venv'
 #
diff --git a/builds/dos/dos-emx.mk b/builds/dos/dos-emx.mk
index 5173208..dd99479 100644
--- a/builds/dos/dos-emx.mk
+++ b/builds/dos/dos-emx.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2003-2020 by
+# Copyright (C) 2003-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/dos/dos-gcc.mk b/builds/dos/dos-gcc.mk
index 638892d..9abdabe 100644
--- a/builds/dos/dos-gcc.mk
+++ b/builds/dos/dos-gcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/dos/dos-wat.mk b/builds/dos/dos-wat.mk
index 4e39d21..7ab82af 100644
--- a/builds/dos/dos-wat.mk
+++ b/builds/dos/dos-wat.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2003-2020 by
+# Copyright (C) 2003-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/exports.mk b/builds/exports.mk
index eba9668..67c7c99 100644
--- a/builds/exports.mk
+++ b/builds/exports.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2005-2020 by
+# Copyright (C) 2005-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/freetype.mk b/builds/freetype.mk
index 1d7eeb6..bae8145 100644
--- a/builds/freetype.mk
+++ b/builds/freetype.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -20,8 +20,8 @@
 # The following variables (set by other Makefile components, in the
 # environment, or on the command line) are used:
 #
-#   BUILD_DIR      The architecture dependent directory,
-#                  e.g. `$(TOP_DIR)/builds/unix'.  Added to INCLUDES also.
+#   PLATFORM_DIR   The architecture-dependent directory,
+#                  e.g., `$(TOP_DIR)/builds/unix'.  Added to INCLUDES also.
 #
 #   OBJ_DIR        The directory in which object files are created.
 #
@@ -121,7 +121,7 @@
 #
 INCLUDES := $(subst /,$(COMPILER_SEP),$(OBJ_DIR) \
                                       $(DEVEL_DIR) \
-                                      $(BUILD_DIR) \
+                                      $(PLATFORM_DIR) \
                                       $(TOP_DIR)/include)
 
 INCLUDE_FLAGS := $(INCLUDES:%=$I%)
@@ -150,9 +150,9 @@
 #
 # `CPPFLAGS' might be specified by the user in the environment.
 #
-FT_CFLAGS  = $(CPPFLAGS) \
-             $(CFLAGS) \
-             $DFT2_BUILD_LIBRARY
+FT_CFLAGS = $(CPPFLAGS) \
+            $(CFLAGS) \
+            $DFT2_BUILD_LIBRARY
 
 FT_COMPILE := $(CC) $(ANSIFLAGS) $(INCLUDE_FLAGS) $(FT_CFLAGS)
 
@@ -175,16 +175,16 @@
 # changes, the whole library is recompiled.
 #
 ifneq ($(wildcard $(OBJ_DIR)/ftoption.h),)
-  FTOPTION_H    := $(OBJ_DIR)/ftoption.h
-else ifneq ($(wildcard $(BUILD_DIR)/ftoption.h),)
-  FTOPTION_H    := $(BUILD_DIR)/ftoption.h
+  FTOPTION_H := $(OBJ_DIR)/ftoption.h
+else ifneq ($(wildcard $(PLATFORM_DIR)/ftoption.h),)
+  FTOPTION_H := $(PLATFORM_DIR)/ftoption.h
 endif
 
 PUBLIC_H   := $(wildcard $(PUBLIC_DIR)/*.h)
 INTERNAL_H := $(wildcard $(INTERNAL_DIR)/*.h) \
               $(wildcard $(SERVICES_DIR)/*.h)
 CONFIG_H   := $(wildcard $(CONFIG_DIR)/*.h) \
-              $(wildcard $(BUILD_DIR)/config/*.h) \
+              $(wildcard $(PLATFORM_DIR)/config/*.h) \
               $(FTMODULE_H) \
               $(FTOPTION_H)
 DEVEL_H    := $(wildcard $(TOP_DIR)/devel/*.h)
@@ -220,6 +220,7 @@
 #
 include $(SRC_DIR)/base/rules.mk
 include $(patsubst %,$(SRC_DIR)/%/rules.mk,$(MODULES))
+include $(SRC_DIR)/dlg/rules.mk
 
 
 # ftinit component
@@ -260,8 +261,8 @@
 
 # All FreeType library objects.
 #
-OBJ_M := $(BASE_OBJ_M) $(BASE_EXT_OBJ) $(DRV_OBJS_M)
-OBJ_S := $(BASE_OBJ_S) $(BASE_EXT_OBJ) $(DRV_OBJS_S)
+OBJ_M := $(BASE_OBJ_M) $(BASE_EXT_OBJ) $(DRV_OBJS_M) $(DLG_OBJS_M)
+OBJ_S := $(BASE_OBJ_S) $(BASE_EXT_OBJ) $(DRV_OBJS_S) $(DLG_OBJS_S)
 
 
 # The target `multi' on the Make command line indicates that we want to
diff --git a/builds/link_dos.mk b/builds/link_dos.mk
index c1ed150..8716be5 100644
--- a/builds/link_dos.mk
+++ b/builds/link_dos.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/link_std.mk b/builds/link_std.mk
index 940e674..03f7772 100644
--- a/builds/link_std.mk
+++ b/builds/link_std.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/mac/ftmac.c b/builds/mac/ftmac.c
index 2cb3046..cd3f484 100644
--- a/builds/mac/ftmac.c
+++ b/builds/mac/ftmac.c
@@ -5,7 +5,7 @@
 /*    Mac FOND support.  Written by just@letterror.com.                    */
 /*  Heavily Fixed by mpsuzuki, George Williams and Sean McBride            */
 /*                                                                         */
-/*  Copyright (C) 1996-2020 by                                             */
+/*  Copyright (C) 1996-2021 by                                             */
 /*  Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.     */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -447,7 +447,7 @@
 
     stream->descriptor.pointer = NULL;
     stream->size               = 0;
-    stream->base               = 0;
+    stream->base               = NULL;
   }
 
 
@@ -939,7 +939,7 @@
     if ( lwfn_file_name[0] )
     {
       err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
-                                 buff, sizeof ( buff )  );
+                                 buff, sizeof ( buff ) );
       if ( !err )
         have_lwfn = 1;
     }
@@ -1011,7 +1011,7 @@
       old_total_size = total_size;
     }
 
-    if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
+    if ( FT_QALLOC( buffer, (FT_Long)total_size ) )
       goto Error;
 
     /* Second pass: append all POST data to the buffer, add PFB fields. */
@@ -1127,7 +1127,7 @@
       return FT_THROW( Invalid_Handle );
 
     sfnt_size = (FT_ULong)GetHandleSize( sfnt );
-    if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
+    if ( FT_QALLOC( sfnt_data, (FT_Long)sfnt_size ) )
     {
       ReleaseResource( sfnt );
       return error;
diff --git a/builds/meson/extract_freetype_version.py b/builds/meson/extract_freetype_version.py
index 15e87db..ab79fdb 100644
--- a/builds/meson/extract_freetype_version.py
+++ b/builds/meson/extract_freetype_version.py
@@ -1,4 +1,14 @@
 #!/usr/bin/env python
+#
+# Copyright (C) 2020-2021 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
 """Extract the FreeType version numbers from `<freetype/freetype.h>`.
 
 This script parses the header to extract the version number defined there.
diff --git a/builds/meson/extract_libtool_version.py b/builds/meson/extract_libtool_version.py
index 0569481..4527f11 100644
--- a/builds/meson/extract_libtool_version.py
+++ b/builds/meson/extract_libtool_version.py
@@ -1,4 +1,14 @@
 #!/usr/bin/env python
+#
+# Copyright (C) 2020-2021 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
 """Extract the libtool version from `configure.raw`.
 
 This script parses the `configure.raw` file to extract the libtool version
diff --git a/builds/meson/generate_reference_docs.py b/builds/meson/generate_reference_docs.py
index 219017c..15d9b06 100644
--- a/builds/meson/generate_reference_docs.py
+++ b/builds/meson/generate_reference_docs.py
@@ -1,4 +1,14 @@
 #!/usr/bin/env python
+#
+# Copyright (C) 2020-2021 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
 """Generate FreeType reference documentation."""
 
 from __future__ import print_function
diff --git a/builds/meson/parse_modules_cfg.py b/builds/meson/parse_modules_cfg.py
index e0f7605..aa6e9e1 100644
--- a/builds/meson/parse_modules_cfg.py
+++ b/builds/meson/parse_modules_cfg.py
@@ -1,4 +1,14 @@
 #!/usr/bin/env python
+#
+# Copyright (C) 2020-2021 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
 """Parse modules.cfg and dump its output either as ftmodule.h or a list of
 base extensions.
 """
diff --git a/builds/meson/process_ftoption_h.py b/builds/meson/process_ftoption_h.py
index b5f80c3..fe60887 100644
--- a/builds/meson/process_ftoption_h.py
+++ b/builds/meson/process_ftoption_h.py
@@ -1,4 +1,14 @@
-#!/usr/bin/python
+#!/usr/bin/env python
+#
+# Copyright (C) 2020-2021 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
 """Toggle settings in `ftoption.h` file based on command-line arguments.
 
 This script takes an `ftoption.h` file as input and rewrites
@@ -82,7 +92,7 @@
             line = "#define " + option_name
         new_lines.append(line)
 
-    result = "\n".join(new_lines)
+    result = "\n".join(new_lines) + "\n"
 
     # Sanity check that all command-line options were actually processed.
     cmdline_options = set(args.enable) | set(args.disable)
diff --git a/builds/modules.mk b/builds/modules.mk
index ae2e238..33fccdf 100644
--- a/builds/modules.mk
+++ b/builds/modules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/os2/detect.mk b/builds/os2/detect.mk
index 659b6c4..7b8962b 100644
--- a/builds/os2/detect.mk
+++ b/builds/os2/detect.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/os2/os2-def.mk b/builds/os2/os2-def.mk
index b097654..08aab95 100644
--- a/builds/os2/os2-def.mk
+++ b/builds/os2/os2-def.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -13,11 +13,11 @@
 # fully.
 
 
-DELETE    := del
-CAT       := type
-SEP       := $(strip \ )
-BUILD_DIR := $(TOP_DIR)/builds/os2
-PLATFORM  := os2
+DELETE       := del
+CAT          := type
+SEP          := $(strip \ )
+PLATFORM_DIR := $(TOP_DIR)/builds/os2
+PLATFORM     := os2
 
 # This is used for `make refdoc' and `make refdoc-venv'
 #
diff --git a/builds/os2/os2-dev.mk b/builds/os2/os2-dev.mk
index 8e2a4eb..40591ff 100644
--- a/builds/os2/os2-dev.mk
+++ b/builds/os2/os2-dev.mk
@@ -5,7 +5,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/os2/os2-gcc.mk b/builds/os2/os2-gcc.mk
index 2bd39ae..854c46d 100644
--- a/builds/os2/os2-gcc.mk
+++ b/builds/os2/os2-gcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/symbian/bld.inf b/builds/symbian/bld.inf
index 9739da1..b9d000b 100644
--- a/builds/symbian/bld.inf
+++ b/builds/symbian/bld.inf
@@ -2,7 +2,7 @@
 // FreeType 2 project for the symbian platform
 //
 
-// Copyright (C) 2008-2020 by
+// Copyright (C) 2008-2021 by
 // David Turner, Robert Wilhelm, and Werner Lemberg.
 //
 // This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/symbian/freetype.mmp b/builds/symbian/freetype.mmp
index 90fc6bb..fa49157 100644
--- a/builds/symbian/freetype.mmp
+++ b/builds/symbian/freetype.mmp
@@ -2,7 +2,7 @@
 // FreeType 2 makefile for the symbian platform
 //
 
-// Copyright (C) 2008-2020 by
+// Copyright (C) 2008-2021 by
 // David Turner, Robert Wilhelm, and Werner Lemberg.
 //
 // This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/toplevel.mk b/builds/toplevel.mk
index 5de61c1..53b6d6f 100644
--- a/builds/toplevel.mk
+++ b/builds/toplevel.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -103,6 +103,7 @@
   check_platform := 1
 endif
 
+
 # Include the automatic host platform detection rules when we need to
 # check the platform.
 #
@@ -112,6 +113,17 @@
 
   include $(TOP_DIR)/builds/detect.mk
 
+  # For builds directly from the git repository we need to copy files
+  # from `subprojects/dlg' to `src/dlg' and `include/dlg'.
+  #
+  ifeq ($(wildcard $(TOP_DIR)/src/dlg/dlg.*),)
+    ifeq ($(wildcard $(TOP_DIR)/subprojects/dlg/*),)
+      copy_submodule: check_out_submodule
+    endif
+
+    setup: copy_submodule
+  endif
+
   # This rule makes sense for Unix only to remove files created by a run of
   # the configure script which hasn't been successful (so that no
   # `config.mk' has been created).  It uses the built-in $(RM) command of
@@ -154,6 +166,23 @@
 endif # test check_platform
 
 
+.PHONY: check_out_submodule copy_submodule
+
+check_out_submodule:
+	$(info Checking out submodule in `subprojects/dlg')
+	git submodule init
+	git submodule update
+
+copy_submodule:
+	$(info Copying files from `subprojects/dlg' to `src/dlg' and `include/dlg')
+  ifeq ($(wildcard include/dlg),)
+	mkdir $(subst /,$(SEP),include/dlg)
+  endif
+	$(COPY) $(subst /,$(SEP),subprojects/dlg/include/dlg/output.h include/dlg)
+	$(COPY) $(subst /,$(SEP),subprojects/dlg/include/dlg/dlg.h include/dlg)
+	$(COPY) $(subst /,$(SEP),subprojects/dlg/src/dlg/dlg.c src/dlg)
+
+
 # We always need the list of modules in ftmodule.h.
 #
 all setup: $(FTMODULE_H)
@@ -197,6 +226,7 @@
 # else
   version := $(major).$(minor).$(patch)
   winversion := $(major)$(minor)$(patch)
+  version_tag := VER-$(major)-$(minor)-$(patch)
 # endif
 
 
@@ -219,7 +249,10 @@
 
 	currdir=`pwd` ; \
 	for f in `find . -wholename '*/.git' -prune \
+	                 -o -name .gitattributes \
 	                 -o -name .gitignore \
+	                 -o -name .gitlab-ci.yml \
+	                 -o -name .gitmodules \
 	                 -o -name .mailmap \
 	                 -o -type d \
 	                 -o -print` ; do \
@@ -250,6 +283,10 @@
 CONFIG_GUESS = ~/git/config/config.guess
 CONFIG_SUB   = ~/git/config/config.sub
 
+# We also use this repository to access the gnulib script that converts git
+# commit messages to a ChangeLog file.
+CHANGELOG_SCRIPT = ~/git/config/gitlog-to-changelog
+
 
 # Don't say `make do-dist'.  Always use `make dist' instead.
 #
@@ -267,8 +304,20 @@
 	cp $(CONFIG_GUESS) builds/unix
 	cp $(CONFIG_SUB) builds/unix
 
+	@# Generate `ChangeLog' file with commits since previous release.
+	$(CHANGELOG_SCRIPT) \
+	  --format='%B%n' \
+	  --no-cluster \
+	  -- `git describe --tags \
+	                   --abbrev=0 \
+	                   $(version_tag)^`..$(version_tag) \
+	> ChangeLog
+
 	@# Remove intermediate files created by the `refdoc' target.
 	rm -rf docs/markdown
 	rm -f docs/mkdocs.yml
 
+	@# Remove more stuff related to git.
+	rm -rf subprojects
+
 # EOF
diff --git a/builds/unix/ax_pthread.m4 b/builds/unix/ax_pthread.m4
new file mode 100644
index 0000000..e5858e5
--- /dev/null
+++ b/builds/unix/ax_pthread.m4
@@ -0,0 +1,522 @@
+# ===========================================================================
+#        https://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+#   This macro figures out how to build C programs using POSIX threads. It
+#   sets the PTHREAD_LIBS output variable to the threads library and linker
+#   flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+#   flags that are needed. (The user can also force certain compiler
+#   flags/libs to be tested by setting these environment variables.)
+#
+#   Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
+#   needed for multi-threaded programs (defaults to the value of CC
+#   respectively CXX otherwise). (This is necessary on e.g. AIX to use the
+#   special cc_r/CC_r compiler alias.)
+#
+#   NOTE: You are assumed to not only compile your program with these flags,
+#   but also to link with them as well. For example, you might link with
+#   $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#   $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+#   If you are only building threaded programs, you may wish to use these
+#   variables in your default LIBS, CFLAGS, and CC:
+#
+#     LIBS="$PTHREAD_LIBS $LIBS"
+#     CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+#     CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
+#     CC="$PTHREAD_CC"
+#     CXX="$PTHREAD_CXX"
+#
+#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+#   has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
+#   that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+#   Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+#   PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+#   PTHREAD_CFLAGS.
+#
+#   ACTION-IF-FOUND is a list of shell commands to run if a threads library
+#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+#   is not found. If ACTION-IF-FOUND is not specified, the default action
+#   will define HAVE_PTHREAD.
+#
+#   Please let the authors know if this macro fails on any platform, or if
+#   you have any other suggestions or comments. This macro was based on work
+#   by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+#   from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+#   Alejandro Forero Cuervo to the autoconf macro repository. We are also
+#   grateful for the helpful feedback of numerous users.
+#
+#   Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+#   Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
+#   Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 30
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_TARGET])
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_PROG_SED])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on Tru64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
+        ax_pthread_save_CC="$CC"
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
+        AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
+        AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
+        AC_MSG_RESULT([$ax_pthread_ok])
+        if test "x$ax_pthread_ok" = "xno"; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        CC="$ax_pthread_save_CC"
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items with a "," contain both
+# C compiler flags (before ",") and linker flags (after ","). Other items
+# starting with a "-" are C compiler flags, and remaining items are
+# library names, except for "none" which indicates that we try without
+# any flags at all, and "pthread-config" which is a program returning
+# the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
+#           (Note: HP C rejects this with "bad form for `-t' option")
+# -pthreads: Solaris/gcc (Note: HP C also rejects)
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads and
+#      -D_REENTRANT too), HP C (must be checked before -lpthread, which
+#      is present but should not be used directly; and before -mthreads,
+#      because the compiler interprets this as "-mt" + "-hreads")
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case $target_os in
+
+        freebsd*)
+
+        # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+        # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+
+        ax_pthread_flags="-kthread lthread $ax_pthread_flags"
+        ;;
+
+        hpux*)
+
+        # From the cc(1) man page: "[-mt] Sets various -D flags to enable
+        # multi-threading and also sets -lpthread."
+
+        ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
+        ;;
+
+        openedition*)
+
+        # IBM z/OS requires a feature-test macro to be defined in order to
+        # enable POSIX threads at all, so give the user a hint if this is
+        # not set. (We don't define these ourselves, as they can affect
+        # other portions of the system API in unpredictable ways.)
+
+        AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
+            [
+#            if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
+             AX_PTHREAD_ZOS_MISSING
+#            endif
+            ],
+            [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
+        ;;
+
+        solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed. (N.B.: The stubs are missing
+        # pthread_cleanup_push, or rather a function called by this macro,
+        # so we could check for that, but who knows whether they'll stub
+        # that too in a future libc.)  So we'll check first for the
+        # standard Solaris way of linking pthreads (-mt -lpthread).
+
+        ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
+        ;;
+esac
+
+# Are we compiling with Clang?
+
+AC_CACHE_CHECK([whether $CC is Clang],
+    [ax_cv_PTHREAD_CLANG],
+    [ax_cv_PTHREAD_CLANG=no
+     # Note that Autoconf sets GCC=yes for Clang as well as GCC
+     if test "x$GCC" = "xyes"; then
+        AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
+            [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
+#            if defined(__clang__) && defined(__llvm__)
+             AX_PTHREAD_CC_IS_CLANG
+#            endif
+            ],
+            [ax_cv_PTHREAD_CLANG=yes])
+     fi
+    ])
+ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
+
+
+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
+
+# Note that for GCC and Clang -pthread generally implies -lpthread,
+# except when -nostdlib is passed.
+# This is problematic using libtool to build C++ shared libraries with pthread:
+# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
+# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
+# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
+# To solve this, first try -pthread together with -lpthread for GCC
+
+AS_IF([test "x$GCC" = "xyes"],
+      [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
+
+# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
+
+AS_IF([test "x$ax_pthread_clang" = "xyes"],
+      [ax_pthread_flags="-pthread,-lpthread -pthread"])
+
+
+# The presence of a feature test macro requesting re-entrant function
+# definitions is, on some systems, a strong hint that pthreads support is
+# correctly enabled
+
+case $target_os in
+        darwin* | hpux* | linux* | osf* | solaris*)
+        ax_pthread_check_macro="_REENTRANT"
+        ;;
+
+        aix*)
+        ax_pthread_check_macro="_THREAD_SAFE"
+        ;;
+
+        *)
+        ax_pthread_check_macro="--"
+        ;;
+esac
+AS_IF([test "x$ax_pthread_check_macro" = "x--"],
+      [ax_pthread_check_cond=0],
+      [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
+
+
+if test "x$ax_pthread_ok" = "xno"; then
+for ax_pthread_try_flag in $ax_pthread_flags; do
+
+        case $ax_pthread_try_flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                *,*)
+                PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
+                PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
+                AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
+                PTHREAD_CFLAGS="$ax_pthread_try_flag"
+                ;;
+
+                pthread-config)
+                AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
+                AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
+                PTHREAD_CFLAGS="`pthread-config --cflags`"
+                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+                ;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
+                PTHREAD_LIBS="-l$ax_pthread_try_flag"
+                ;;
+        esac
+
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+#                       if $ax_pthread_check_cond
+#                        error "$ax_pthread_check_macro must be defined"
+#                       endif
+                        static void *some_global = NULL;
+                        static void routine(void *a)
+                          {
+                             /* To avoid any unused-parameter or
+                                unused-but-set-parameter warning.  */
+                             some_global = a;
+                          }
+                        static void *start_routine(void *a) { return a; }],
+                       [pthread_t th; pthread_attr_t attr;
+                        pthread_create(&th, 0, start_routine, 0);
+                        pthread_join(th, 0);
+                        pthread_attr_init(&attr);
+                        pthread_cleanup_push(routine, 0);
+                        pthread_cleanup_pop(0) /* ; */])],
+            [ax_pthread_ok=yes],
+            [])
+
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
+
+        AC_MSG_RESULT([$ax_pthread_ok])
+        AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+
+# Clang needs special handling, because older versions handle the -pthread
+# option in a rather... idiosyncratic way
+
+if test "x$ax_pthread_clang" = "xyes"; then
+
+        # Clang takes -pthread; it has never supported any other flag
+
+        # (Note 1: This will need to be revisited if a system that Clang
+        # supports has POSIX threads in a separate library.  This tends not
+        # to be the way of modern systems, but it's conceivable.)
+
+        # (Note 2: On some systems, notably Darwin, -pthread is not needed
+        # to get POSIX threads support; the API is always present and
+        # active.  We could reasonably leave PTHREAD_CFLAGS empty.  But
+        # -pthread does define _REENTRANT, and while the Darwin headers
+        # ignore this macro, third-party headers might not.)
+
+        # However, older versions of Clang make a point of warning the user
+        # that, in an invocation where only linking and no compilation is
+        # taking place, the -pthread option has no effect ("argument unused
+        # during compilation").  They expect -pthread to be passed in only
+        # when source code is being compiled.
+        #
+        # Problem is, this is at odds with the way Automake and most other
+        # C build frameworks function, which is that the same flags used in
+        # compilation (CFLAGS) are also used in linking.  Many systems
+        # supported by AX_PTHREAD require exactly this for POSIX threads
+        # support, and in fact it is often not straightforward to specify a
+        # flag that is used only in the compilation phase and not in
+        # linking.  Such a scenario is extremely rare in practice.
+        #
+        # Even though use of the -pthread flag in linking would only print
+        # a warning, this can be a nuisance for well-run software projects
+        # that build with -Werror.  So if the active version of Clang has
+        # this misfeature, we search for an option to squash it.
+
+        AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
+            [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
+            [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
+             # Create an alternate version of $ac_link that compiles and
+             # links in two steps (.c -> .o, .o -> exe) instead of one
+             # (.c -> exe), because the warning occurs only in the second
+             # step
+             ax_pthread_save_ac_link="$ac_link"
+             ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
+             ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
+             ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
+             ax_pthread_save_CFLAGS="$CFLAGS"
+             for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
+                AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
+                CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
+                ac_link="$ax_pthread_save_ac_link"
+                AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+                    [ac_link="$ax_pthread_2step_ac_link"
+                     AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
+                         [break])
+                    ])
+             done
+             ac_link="$ax_pthread_save_ac_link"
+             CFLAGS="$ax_pthread_save_CFLAGS"
+             AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
+             ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
+            ])
+
+        case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
+                no | unknown) ;;
+                *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
+        esac
+
+fi # $ax_pthread_clang = yes
+
+
+
+# Various other checks:
+if test "x$ax_pthread_ok" = "xyes"; then
+        ax_pthread_save_CFLAGS="$CFLAGS"
+        ax_pthread_save_LIBS="$LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+        AC_CACHE_CHECK([for joinable pthread attribute],
+            [ax_cv_PTHREAD_JOINABLE_ATTR],
+            [ax_cv_PTHREAD_JOINABLE_ATTR=unknown
+             for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+                 AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+                                                 [int attr = $ax_pthread_attr; return attr /* ; */])],
+                                [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
+                                [])
+             done
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
+               test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
+               test "x$ax_pthread_joinable_attr_defined" != "xyes"],
+              [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
+                                  [$ax_cv_PTHREAD_JOINABLE_ATTR],
+                                  [Define to necessary symbol if this constant
+                                   uses a non-standard name on your system.])
+               ax_pthread_joinable_attr_defined=yes
+              ])
+
+        AC_CACHE_CHECK([whether more special flags are required for pthreads],
+            [ax_cv_PTHREAD_SPECIAL_FLAGS],
+            [ax_cv_PTHREAD_SPECIAL_FLAGS=no
+             case $target_os in
+             solaris*)
+             ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
+             ;;
+             esac
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
+               test "x$ax_pthread_special_flags_added" != "xyes"],
+              [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
+               ax_pthread_special_flags_added=yes])
+
+        AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+            [ax_cv_PTHREAD_PRIO_INHERIT],
+            [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
+                                             [[int i = PTHREAD_PRIO_INHERIT;
+                                               return i;]])],
+                            [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+                            [ax_cv_PTHREAD_PRIO_INHERIT=no])
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
+               test "x$ax_pthread_prio_inherit_defined" != "xyes"],
+              [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
+               ax_pthread_prio_inherit_defined=yes
+              ])
+
+        CFLAGS="$ax_pthread_save_CFLAGS"
+        LIBS="$ax_pthread_save_LIBS"
+
+        # More AIX lossage: compile with *_r variant
+        if test "x$GCC" != "xyes"; then
+            case $target_os in
+                aix*)
+                AS_CASE(["x/$CC"],
+                    [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
+                    [#handle absolute path differently from PATH based program lookup
+                     AS_CASE(["x$CC"],
+                         [x/*],
+                         [
+			   AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
+			   AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
+			 ],
+                         [
+			   AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
+			   AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
+			 ]
+                     )
+                    ])
+                ;;
+            esac
+        fi
+fi
+
+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
+test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
+
+AC_SUBST([PTHREAD_LIBS])
+AC_SUBST([PTHREAD_CFLAGS])
+AC_SUBST([PTHREAD_CC])
+AC_SUBST([PTHREAD_CXX])
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test "x$ax_pthread_ok" = "xyes"; then
+        ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
+        :
+else
+        ax_pthread_ok=no
+        $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
diff --git a/builds/unix/configure.raw b/builds/unix/configure.raw
index bc65e45..f326872 100644
--- a/builds/unix/configure.raw
+++ b/builds/unix/configure.raw
@@ -2,7 +2,7 @@
 #
 # Process this file with autoconf to produce a configure script.
 #
-# Copyright (C) 2001-2020 by
+# Copyright (C) 2001-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -17,7 +17,7 @@
 
 # Don't forget to update `docs/VERSIONS.TXT'!
 
-version_info='23:4:17'
+version_info='24:1:18'
 AC_SUBST([version_info])
 ft_version=`echo $version_info | tr : .`
 AC_SUBST([ft_version])
@@ -97,85 +97,12 @@
 
 # checks for header files
 
-AC_HEADER_STDC
 AC_CHECK_HEADERS([fcntl.h unistd.h])
 
 
 # checks for typedefs, structures, and compiler characteristics
 
 AC_C_CONST
-AC_CHECK_SIZEOF([int])
-AC_CHECK_SIZEOF([long])
-AC_TYPE_LONG_LONG_INT
-
-
-# check whether cpp computation of size of int and long in ftconfig.h.in works
-
-AC_MSG_CHECKING([whether cpp computation of bit length in ftconfig.h.in works])
-orig_CPPFLAGS="${CPPFLAGS}"
-CPPFLAGS="-I${srcdir} -I. -I${srcdir}/../../include ${CPPFLAGS}"
-
-ac_clean_files=
-if test ! -f ft2build.h; then
-  ac_clean_files=ft2build.h
-  touch ft2build.h
-fi
-
-cat > conftest.c <<\_ACEOF
-#include <limits.h>
-#define FT_CONFIG_OPTIONS_H <freetype/config/ftoption.h>
-#define FT_CONFIG_STANDARD_LIBRARY_H <freetype/config/ftstdlib.h>
-#define FT_UINT_MAX  UINT_MAX
-#define FT_ULONG_MAX ULONG_MAX
-#include "ftconfig.h.in"
-_ACEOF
-echo >> conftest.c "#if FT_SIZEOF_INT == "${ac_cv_sizeof_int}
-echo >> conftest.c "ac_cpp_ft_sizeof_int="${ac_cv_sizeof_int}
-echo >> conftest.c "#endif"
-echo >> conftest.c "#if FT_SIZEOF_LONG == "${ac_cv_sizeof_long}
-echo >> conftest.c "ac_cpp_ft_sizeof_long="${ac_cv_sizeof_long}
-echo >> conftest.c "#endif"
-
-${CPP} ${CPPFLAGS} conftest.c | ${GREP} ac_cpp_ft > conftest.sh
-eval `cat conftest.sh`
-rm -f conftest.* $ac_clean_files
-
-if test x != "x${ac_cpp_ft_sizeof_int}" \
-   -a x != x"${ac_cpp_ft_sizeof_long}"; then
-  unset ft_use_autoconf_sizeof_types
-else
-  ft_use_autoconf_sizeof_types=yes
-fi
-
-AC_ARG_ENABLE(biarch-config,
-[  --enable-biarch-config  install biarch ftconfig.h to support multiple
-                          architectures by single file], [], [])
-
-case :${ft_use_autoconf_sizeof_types}:${enable_biarch_config}: in
-  :yes:yes:)
-    AC_MSG_RESULT([broken but use it])
-    unset ft_use_autoconf_sizeof_types
-    ;;
-  ::no:)
-    AC_MSG_RESULT([works but ignore it])
-    ft_use_autoconf_sizeof_types=yes
-    ;;
-  ::yes: | :::)
-    AC_MSG_RESULT([yes])
-    unset ft_use_autoconf_sizeof_types
-    ;;
-  *)
-    AC_MSG_RESULT([no])
-    ft_use_autoconf_sizeof_types=yes
-    ;;
-esac
-
-if test x"${ft_use_autoconf_sizeof_types}" = xyes; then
-  AC_DEFINE([FT_USE_AUTOCONF_SIZEOF_TYPES], [],
-            [Define if autoconf sizeof types should be used.])
-fi
-
-CPPFLAGS="${orig_CPPFLAGS}"
 
 AC_ARG_ENABLE([freetype-config],
   AS_HELP_STRING([--enable-freetype-config], [install freetype-config]),
@@ -192,53 +119,59 @@
 AC_SYS_LARGEFILE
 
 # Here we check whether we can use our mmap file component.
+#
+# Note that `ftsystem.c` for Windows has its own mmap-like implementation
+# not covered by `AC_FUNC_MMAP` and/or `FT_UNMAP_PARAM`.
 
 AC_ARG_ENABLE([mmap],
   AS_HELP_STRING([--disable-mmap],
                  [do not check mmap() and do not use]),
   [enable_mmap="no"], [enable_mmap="yes"])
 if test "x${enable_mmap}" != "xno"; then
-  AC_FUNC_MMAP
-fi
-if test "x${enable_mmap}" = "xno" \
-   -o "$ac_cv_func_mmap_fixed_mapped" != "yes"; then
-  FTSYS_SRC='$(BASE_DIR)/ftsystem.c'
-else
-  FTSYS_SRC='$(BUILD_DIR)/ftsystem.c'
+  case "$host" in
+  *-*-mingw*)
+    AC_MSG_CHECKING([for working mmap])
+    AC_MSG_RESULT([using MapViewOfFile in Windows])
+    FTSYS_SRC='$(TOP_DIR)/builds/windows/ftsystem.c'
+    ;;
+  *)
+    AC_FUNC_MMAP
+    if test "$ac_cv_func_mmap_fixed_mapped" = "yes"; then
+      FTSYS_SRC='$(PLATFORM_DIR)/ftsystem.c'
 
-  AC_CHECK_DECLS([munmap],
-    [],
-    [],
-    [
+      AC_CHECK_DECLS([munmap],
+        [],
+        [],
+        [
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 #include <sys/mman.h>
 
-    ])
+        ])
 
-  FT_MUNMAP_PARAM
+      FT_MUNMAP_PARAM
+    fi
+    ;;
+  esac
+fi
+
+if test -z "$FTSYS_SRC"; then
+  FTSYS_SRC='$(BASE_DIR)/ftsystem.c'
 fi
 AC_SUBST([FTSYS_SRC])
 
+
 AC_CHECK_FUNCS([memcpy memmove])
 
 
 # get compiler flags right
 #
-#   We try to make the compiler work for C89-strict source.  Even if the
-#   C compiler is gcc and C89 flags are available, some system headers
-#   (e.g., Android Bionic libc) are broken in C89 mode.  We have to check
-#   whether the compilation finishes successfully.
-#
-#   Due to bugs in mingwrt 4.0.3 we don't use `-ansi' for MinGW.
-#
-#   To avoid zillions of
-#
-#     ISO C90 does not support 'long long'
-#
-#   warnings, we disable `-pedantic' for gcc version < 4.6.
+#   We try to make the compiler work for C99-strict source.  Even if the
+#   C compiler is gcc and C99 flags are available, some system headers
+#   might be broken in C99 mode.  We have to check whether compilation
+#   finishes successfully.
 #
 if test "x$GCC" = xyes; then
   XX_CFLAGS="-Wall"
@@ -250,23 +183,11 @@
     XX_ANSIFLAGS="-pedantic"
     ;;
   *)
-    GCC_VERSION=`$CC -dumpversion`
-    GCC_MAJOR=`echo "$GCC_VERSION" | sed 's/\([[^.]][[^.]]*\).*/\1/'`
-    GCC_MINOR=`echo "$GCC_VERSION" | sed 's/[[^.]][[^.]]*.\([[^.]][[^.]]*\).*/\1/'`
-
-    XX_PEDANTIC=-pedantic
-    if test $GCC_MAJOR -lt 4; then
-      XX_PEDANTIC=
-    else
-      if test $GCC_MAJOR -eq 4 -a $GCC_MINOR -lt 6; then
-        XX_PEDANTIC=
-      fi
-    fi
-
     XX_ANSIFLAGS=""
-    for a in $XX_PEDANTIC -ansi
+
+    for a in "-pedantic" "-std=c99"
     do
-      AC_MSG_CHECKING([gcc compiler flag ${a} to assure ANSI C works correctly])
+      AC_MSG_CHECKING([$CC compiler flag ${a} to assure ANSI C99 works correctly])
       orig_CFLAGS="${CFLAGS}"
       CFLAGS="${CFLAGS} ${XX_ANSIFLAGS} ${a}"
       AC_COMPILE_IFELSE([
@@ -508,7 +429,7 @@
 
 have_harfbuzz=no
 if test x"$with_harfbuzz" = xyes -o x"$with_harfbuzz" = xauto; then
-  harfbuzz_pkg="harfbuzz >= 1.8.0"
+  harfbuzz_pkg="harfbuzz >= 2.0.0"
   have_harfbuzz_pkg=no
 
   if test x"$HARFBUZZ_CFLAGS" = x -a x"$HARFBUZZ_LIBS" = x; then
@@ -1012,6 +933,10 @@
     ;;
 esac
 
+# Check for pthreads
+
+AX_PTHREAD([have_pthread=yes], [have_pthread=no])
+
 # Check for Python and docwriter
 
 have_py3=no
@@ -1024,7 +949,7 @@
 
   if test "x$have_py3" = "xyes"; then
     PIP="$PYTHON -m $PIP"
-    AC_MSG_CHECKING([for \`docwriter' Python module])
+    AC_MSG_CHECKING([for `docwriter' Python module])
     $PYTHON -m docwriter -h > /dev/null 2>&1
     if test "x$?" = "x0"; then
       have_docwriter=yes
@@ -1142,6 +1067,11 @@
   ftoption_unset FT_CONFIG_OPTION_USE_BROTLI
 fi
 
+if test "$have_pthread" != no; then
+  CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+  LDFLAGS="$LDFLAGS $PTHREAD_CFLAGS $PTHREAD_LIBS"
+fi
+
 AC_SUBST([CFLAGS])
 AC_SUBST([LDFLAGS])
 
@@ -1176,16 +1106,27 @@
   libpng:        $have_libpng
   harfbuzz:      $have_harfbuzz
   brotli:        $have_brotli
+  pthread:       $have_pthread
 ])
 
 # Warn if docwriter is not installed
 
 if test $have_docwriter = no; then
   AC_MSG_WARN([
-  \`make refdoc' will fail since pip package \`docwriter' is not installed.
-  To install, run \`$PIP install docwriter', or to use a Python
-  virtual environment, run \`make refdoc-venv' (requires pip package
-  \`virtualenv'). These operations require Python >= 3.5.
+  `make refdoc' will fail since pip package `docwriter' is not installed.
+  To install, run `$PIP install docwriter', or to use a Python
+  virtual environment, run `make refdoc-venv' (requires pip package
+  `virtualenv').  These operations require Python >= 3.5.
+  ])
+fi
+
+# Warn if pthread is not available
+
+if test $have_pthread = no; then
+  AC_MSG_WARN([
+  `FT_DEBUG_LOGGING' will not work since the `pthread' library is not
+  available.  This warning can be safely ignored if you don't plan to use
+  this configuration macro.
   ])
 fi
 
diff --git a/builds/unix/detect.mk b/builds/unix/detect.mk
index c7e8408..862b432 100644
--- a/builds/unix/detect.mk
+++ b/builds/unix/detect.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/unix/freetype-config.in b/builds/unix/freetype-config.in
index 3918ddb..4edb092 100644
--- a/builds/unix/freetype-config.in
+++ b/builds/unix/freetype-config.in
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-# Copyright (C) 2000-2020 by
+# Copyright (C) 2000-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/unix/freetype2.m4 b/builds/unix/freetype2.m4
index 207c263..478a422 100644
--- a/builds/unix/freetype2.m4
+++ b/builds/unix/freetype2.m4
@@ -1,7 +1,7 @@
 # Configure paths for FreeType2
-# Marcelo Magallon 2001-10-26, based on gtk.m4 by Owen Taylor
+# Marcelo Magallon 2001-10-26, based on `gtk.m4` by Owen Taylor
 #
-# Copyright (C) 2001-2020 by
+# Copyright (C) 2001-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -15,32 +15,32 @@
 # generated by Autoconf, under the same distribution terms as the rest of
 # that program.
 #
-# serial 5
+# serial 6
 
 # AC_CHECK_FT2([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
 # Test for FreeType 2, and define FT2_CFLAGS and FT2_LIBS.
-# MINIMUM-VERSION is what libtool reports; the default is `7.0.1' (this is
+# MINIMUM-VERSION is what libtool reports; the default is '7.0.1' (this is
 # FreeType 2.0.4).
 #
+# To make this code work with older autoconf versions, `AS_HELP_STRING` is
+# not quoted.
+#
 AC_DEFUN([AC_CHECK_FT2],
   [# Get the cflags and libraries from the freetype-config script
    #
    AC_ARG_WITH([ft-prefix],
-     dnl don't quote AS_HELP_STRING!
      AS_HELP_STRING([--with-ft-prefix=PREFIX],
                     [Prefix where FreeType is installed (optional)]),
      [ft_config_prefix="$withval"],
      [ft_config_prefix=""])
 
    AC_ARG_WITH([ft-exec-prefix],
-     dnl don't quote AS_HELP_STRING!
      AS_HELP_STRING([--with-ft-exec-prefix=PREFIX],
                     [Exec prefix where FreeType is installed (optional)]),
      [ft_config_exec_prefix="$withval"],
      [ft_config_exec_prefix=""])
 
    AC_ARG_ENABLE([freetypetest],
-     dnl don't quote AS_HELP_STRING!
      AS_HELP_STRING([--disable-freetypetest],
                     [Do not try to compile and run a test FreeType program]),
      [],
diff --git a/builds/unix/ft-munmap.m4 b/builds/unix/ft-munmap.m4
index a1aea2b..275481b 100644
--- a/builds/unix/ft-munmap.m4
+++ b/builds/unix/ft-munmap.m4
@@ -1,6 +1,6 @@
 ## FreeType specific autoconf tests
 #
-# Copyright (C) 2002-2020 by
+# Copyright (C) 2002-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/unix/ftconfig.h.in b/builds/unix/ftconfig.h.in
index 00b5a82..b42fe42 100644
--- a/builds/unix/ftconfig.h.in
+++ b/builds/unix/ftconfig.h.in
@@ -4,7 +4,7 @@
  *
  *   UNIX-specific configuration file (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -42,16 +42,6 @@
 #undef HAVE_UNISTD_H
 #undef HAVE_FCNTL_H
 
-#undef FT_USE_AUTOCONF_SIZEOF_TYPES
-#ifdef FT_USE_AUTOCONF_SIZEOF_TYPES
-
-#undef SIZEOF_INT
-#undef SIZEOF_LONG
-#define FT_SIZEOF_INT  SIZEOF_INT
-#define FT_SIZEOF_LONG SIZEOF_LONG
-
-#endif /* FT_USE_AUTOCONF_SIZEOF_TYPES */
-
 #include <freetype/config/integer-types.h>
 #include <freetype/config/public-macros.h>
 #include <freetype/config/mac-support.h>
diff --git a/builds/unix/ftsystem.c b/builds/unix/ftsystem.c
index b4d71d4..81ed928 100644
--- a/builds/unix/ftsystem.c
+++ b/builds/unix/ftsystem.c
@@ -1,19 +1,19 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftsystem.c                                                             */
-/*                                                                         */
-/*    Unix-specific FreeType low-level system interface (body).            */
-/*                                                                         */
-/*  Copyright (C) 1996-2020 by                                             */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  modified, and distributed under the terms of the FreeType project      */
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
-/*  this file you indicate that you have read the license and              */
-/*  understand and accept it fully.                                        */
-/*                                                                         */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftsystem.c
+ *
+ *   Unix-specific FreeType low-level system interface (body).
+ *
+ * Copyright (C) 1996-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
 
 
 #include <ft2build.h>
@@ -70,29 +70,40 @@
 #include <errno.h>
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*                       MEMORY MANAGEMENT INTERFACE                     */
-  /*                                                                       */
-  /*************************************************************************/
+  /**************************************************************************
+   *
+   *                      MEMORY MANAGEMENT INTERFACE
+   *
+   */
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    ft_alloc                                                           */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The memory allocation function.                                    */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    memory :: A pointer to the memory object.                          */
-  /*                                                                       */
-  /*    size   :: The requested size in bytes.                             */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The address of newly allocated block.                              */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * It is not necessary to do any error checking for the
+   * allocation-related functions.  This will be done by the higher level
+   * routines like ft_mem_alloc() or ft_mem_realloc().
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_alloc
+   *
+   * @Description:
+   *   The memory allocation function.
+   *
+   * @Input:
+   *   memory ::
+   *     A pointer to the memory object.
+   *
+   *   size ::
+   *     The requested size in bytes.
+   *
+   * @Return:
+   *   The address of newly allocated block.
+   */
   FT_CALLBACK_DEF( void* )
   ft_alloc( FT_Memory  memory,
             long       size )
@@ -103,26 +114,30 @@
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    ft_realloc                                                         */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The memory reallocation function.                                  */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    memory   :: A pointer to the memory object.                        */
-  /*                                                                       */
-  /*    cur_size :: The current size of the allocated memory block.        */
-  /*                                                                       */
-  /*    new_size :: The newly requested size in bytes.                     */
-  /*                                                                       */
-  /*    block    :: The current address of the block in memory.            */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The address of the reallocated memory block.                       */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_realloc
+   *
+   * @Description:
+   *   The memory reallocation function.
+   *
+   * @Input:
+   *   memory ::
+   *     A pointer to the memory object.
+   *
+   *   cur_size ::
+   *     The current size of the allocated memory block.
+   *
+   *   new_size ::
+   *     The newly requested size in bytes.
+   *
+   *   block ::
+   *     The current address of the block in memory.
+   *
+   * @Return:
+   *   The address of the reallocated memory block.
+   */
   FT_CALLBACK_DEF( void* )
   ft_realloc( FT_Memory  memory,
               long       cur_size,
@@ -136,19 +151,21 @@
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    ft_free                                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The memory release function.                                       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    memory :: A pointer to the memory object.                          */
-  /*                                                                       */
-  /*    block  :: The address of block in memory to be freed.              */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_free
+   *
+   * @Description:
+   *   The memory release function.
+   *
+   * @Input:
+   *   memory ::
+   *     A pointer to the memory object.
+   *
+   *   block ::
+   *     The address of block in memory to be freed.
+   */
   FT_CALLBACK_DEF( void )
   ft_free( FT_Memory  memory,
            void*      block )
@@ -159,19 +176,19 @@
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*                     RESOURCE MANAGEMENT INTERFACE                     */
-  /*                                                                       */
-  /*************************************************************************/
+  /**************************************************************************
+   *
+   *                    RESOURCE MANAGEMENT INTERFACE
+   *
+   */
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
 #undef  FT_COMPONENT
 #define FT_COMPONENT  io
 
@@ -180,17 +197,17 @@
 #define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    ft_close_stream_by_munmap                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The function to close a stream which is opened by mmap.            */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    stream :: A pointer to the stream object.                          */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_close_stream_by_munmap
+   *
+   * @Description:
+   *   The function to close a stream which is opened by mmap.
+   *
+   * @Input:
+   *   stream :: A pointer to the stream object.
+   */
   FT_CALLBACK_DEF( void )
   ft_close_stream_by_munmap( FT_Stream  stream )
   {
@@ -198,29 +215,29 @@
 
     stream->descriptor.pointer = NULL;
     stream->size               = 0;
-    stream->base               = 0;
+    stream->base               = NULL;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    ft_close_stream_by_free                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    The function to close a stream which is created by ft_alloc.       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    stream :: A pointer to the stream object.                          */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_close_stream_by_free
+   *
+   * @Description:
+   *   The function to close a stream which is created by ft_alloc.
+   *
+   * @Input:
+   *   stream :: A pointer to the stream object.
+   */
   FT_CALLBACK_DEF( void )
   ft_close_stream_by_free( FT_Stream  stream )
   {
-    ft_free( NULL, stream->descriptor.pointer );
+    ft_free( stream->memory, stream->descriptor.pointer );
 
     stream->descriptor.pointer = NULL;
     stream->size               = 0;
-    stream->base               = 0;
+    stream->base               = NULL;
   }
 
 
@@ -296,8 +313,7 @@
                                           file,
                                           0 );
 
-    /* on some RTOS, mmap might return 0 */
-    if ( (long)stream->base != -1 && stream->base != NULL )
+    if ( stream->base != MAP_FAILED )
       stream->close = ft_close_stream_by_munmap;
     else
     {
@@ -307,7 +323,7 @@
       FT_ERROR(( "FT_Stream_Open:" ));
       FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
 
-      stream->base = (unsigned char*)ft_alloc( NULL, stream->size );
+      stream->base = (unsigned char*)ft_alloc( stream->memory, stream->size );
 
       if ( !stream->base )
       {
@@ -348,7 +364,7 @@
     stream->descriptor.pointer = stream->base;
     stream->pathname.pointer   = (char*)filepathname;
 
-    stream->read = 0;
+    stream->read = NULL;
 
     FT_TRACE1(( "FT_Stream_Open:" ));
     FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
@@ -357,7 +373,7 @@
     return FT_Err_Ok;
 
   Fail_Read:
-    ft_free( NULL, stream->base );
+    ft_free( stream->memory, stream->base );
 
   Fail_Map:
     close( file );
@@ -392,7 +408,7 @@
     memory = (FT_Memory)malloc( sizeof ( *memory ) );
     if ( memory )
     {
-      memory->user    = 0;
+      memory->user    = NULL;
       memory->alloc   = ft_alloc;
       memory->realloc = ft_realloc;
       memory->free    = ft_free;
diff --git a/builds/unix/install.mk b/builds/unix/install.mk
index aa25187..45b761d 100644
--- a/builds/unix/install.mk
+++ b/builds/unix/install.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -62,7 +62,7 @@
           $(DESTDIR)$(includedir)/freetype2/freetype/config/ftmodule.h
 	$(INSTALL_DATA) $(OBJ_BUILD)/ftoption.h                        \
           $(DESTDIR)$(includedir)/freetype2/freetype/config/ftoption.h
-	$(INSTALL_SCRIPT) -m 644 $(BUILD_DIR)/freetype2.m4             \
+	$(INSTALL_SCRIPT) -m 644 $(PLATFORM_DIR)/freetype2.m4          \
           $(DESTDIR)$(datadir)/aclocal/freetype2.m4
 	$(INSTALL_SCRIPT) -m 644 $(OBJ_BUILD)/freetype2.pc             \
           $(DESTDIR)$(libdir)/pkgconfig/freetype2.pc
diff --git a/builds/unix/unix-cc.in b/builds/unix/unix-cc.in
index 30d097b..89be450 100644
--- a/builds/unix/unix-cc.in
+++ b/builds/unix/unix-cc.in
@@ -2,7 +2,7 @@
 # FreeType 2 template for Unix-specific compiler definitions
 #
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -14,7 +14,7 @@
 
 CC           := @CC@
 COMPILER_SEP := $(SEP)
-FT_LIBTOOL_DIR ?= $(BUILD_DIR)
+FT_LIBTOOL_DIR ?= $(PLATFORM_DIR)
 
 LIBTOOL := $(FT_LIBTOOL_DIR)/libtool
 
@@ -73,7 +73,7 @@
 #
 #   These should concern: debug output, optimization & warnings.
 #
-#   Use the ANSIFLAGS variable to define the compiler flags used to enfore
+#   Use the ANSIFLAGS variable to define the compiler flags used to enforce
 #   ANSI compliance.
 #
 #   We use our own FreeType configuration files overriding defaults.
diff --git a/builds/unix/unix-def.in b/builds/unix/unix-def.in
index 5e04f1c..d0c758d 100644
--- a/builds/unix/unix-def.in
+++ b/builds/unix/unix-def.in
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -27,7 +27,7 @@
 BIN    := bin
 
 # this is used for `make distclean' and `make install'
-OBJ_BUILD ?= $(BUILD_DIR)
+OBJ_BUILD ?= $(PLATFORM_DIR)
 
 # don't use `:=' here since the path stuff will be included after this file
 #
diff --git a/builds/unix/unix-dev.mk b/builds/unix/unix-dev.mk
index 1352575..0b572a0 100644
--- a/builds/unix/unix-dev.mk
+++ b/builds/unix/unix-dev.mk
@@ -6,7 +6,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/unix/unix-lcc.mk b/builds/unix/unix-lcc.mk
index a6579db..db57835 100644
--- a/builds/unix/unix-lcc.mk
+++ b/builds/unix/unix-lcc.mk
@@ -6,7 +6,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/unix/unix.mk b/builds/unix/unix.mk
index e08727d..262fafb 100644
--- a/builds/unix/unix.mk
+++ b/builds/unix/unix.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -13,8 +13,8 @@
 # fully.
 
 # We need these declarations here since unix-def.mk is a generated file.
-BUILD_DIR := $(TOP_DIR)/builds/unix
-PLATFORM  := unix
+PLATFORM_DIR := $(TOP_DIR)/builds/unix
+PLATFORM     := unix
 
 have_mk := $(wildcard $(OBJ_DIR)/unix-def.mk)
 ifneq ($(have_mk),)
@@ -22,8 +22,8 @@
   include $(OBJ_DIR)/unix-def.mk
   include $(OBJ_DIR)/unix-cc.mk
 else
-  include $(BUILD_DIR)/unix-def.mk
-  include $(BUILD_DIR)/unix-cc.mk
+  include $(PLATFORM_DIR)/unix-def.mk
+  include $(PLATFORM_DIR)/unix-cc.mk
 endif
 
 ifdef BUILD_PROJECT
diff --git a/builds/unix/unixddef.mk b/builds/unix/unixddef.mk
index b8e3217..77c2a0d 100644
--- a/builds/unix/unixddef.mk
+++ b/builds/unix/unixddef.mk
@@ -4,7 +4,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -27,9 +27,6 @@
 #
 BIN := bin
 
-# we use a special devel ftoption.h
-DEVEL_DIR := $(TOP_DIR)/devel
-
 
 # library file name
 #
diff --git a/builds/vms/ftconfig.h b/builds/vms/ftconfig.h
index 07e5f83..2445b7d 100644
--- a/builds/vms/ftconfig.h
+++ b/builds/vms/ftconfig.h
@@ -4,7 +4,7 @@
  *
  *   VMS-specific configuration file (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/builds/vms/ftsystem.c b/builds/vms/ftsystem.c
index 177481a..31b0870 100644
--- a/builds/vms/ftsystem.c
+++ b/builds/vms/ftsystem.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    VMS-specific FreeType low-level system interface (body).             */
 /*                                                                         */
-/*  Copyright (C) 1996-2020 by                                             */
+/*  Copyright (C) 1996-2021 by                                             */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -197,7 +197,7 @@
 
     stream->descriptor.pointer = NULL;
     stream->size               = 0;
-    stream->base               = 0;
+    stream->base               = NULL;
   }
 
 
@@ -246,7 +246,7 @@
                                           file,
                                           0 );
 
-    if ( (long)stream->base == -1 )
+    if ( stream->base == MAP_FAILED )
     {
       FT_ERROR(( "FT_Stream_Open:" ));
       FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
@@ -259,7 +259,7 @@
     stream->pathname.pointer   = (char*)filepathname;
 
     stream->close = ft_close_stream;
-    stream->read  = 0;
+    stream->read  = NULL;
 
     FT_TRACE1(( "FT_Stream_Open:" ));
     FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
@@ -300,7 +300,7 @@
     memory = (FT_Memory)malloc( sizeof ( *memory ) );
     if ( memory )
     {
-      memory->user    = 0;
+      memory->user    = NULL;
       memory->alloc   = ft_alloc;
       memory->realloc = ft_realloc;
       memory->free    = ft_free;
diff --git a/builds/wince/ftdebug.c b/builds/wince/ftdebug.c
index 734c4f0..9e17776 100644
--- a/builds/wince/ftdebug.c
+++ b/builds/wince/ftdebug.c
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component for WinCE (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -230,7 +230,7 @@
 
     /* const char*  ft2_debug = getenv( "FT2_DEBUG" ); */
 
-    const char*  ft2_debug = 0;
+    const char*  ft2_debug = NULL;
 
 
     if ( ft2_debug )
diff --git a/builds/wince/vc2005-ce/index.html b/builds/wince/vc2005-ce/index.html
index 6936a89..3e42cf9 100644
--- a/builds/wince/vc2005-ce/index.html
+++ b/builds/wince/vc2005-ce/index.html
@@ -21,7 +21,7 @@
   <li>PPC/SP WM6 (Windows Mobile 6)</li>
 </ul>
 
-It compiles the following libraries from the FreeType 2.10.4 sources:</p>
+It compiles the following libraries from the FreeType 2.11.1 sources:</p>
 
 <ul>
   <pre>
diff --git a/builds/wince/vc2008-ce/index.html b/builds/wince/vc2008-ce/index.html
index ee385af..645675c 100644
--- a/builds/wince/vc2008-ce/index.html
+++ b/builds/wince/vc2008-ce/index.html
@@ -21,7 +21,7 @@
   <li>PPC/SP WM6 (Windows Mobile 6)</li>
 </ul>
 
-It compiles the following libraries from the FreeType 2.10.4 sources:</p>
+It compiles the following libraries from the FreeType 2.11.1 sources:</p>
 
 <ul>
   <pre>
diff --git a/builds/windows/detect.mk b/builds/windows/detect.mk
index 303dc8b..3eef47a 100644
--- a/builds/windows/detect.mk
+++ b/builds/windows/detect.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -81,9 +81,9 @@
   # (2004-11-11), and then in the devel mailing list (2004-11-20 to -23).
   #
   ifeq ($(OS),Windows_NT)
-    COPY := cmd.exe /c copy
+    COPY := >nul cmd.exe /c copy
   else
-    COPY := copy
+    COPY := >nul copy
   endif  # test NT
 
 
diff --git a/builds/windows/ftdebug.c b/builds/windows/ftdebug.c
index d589490..94c22da 100644
--- a/builds/windows/ftdebug.c
+++ b/builds/windows/ftdebug.c
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component for Win32 (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -42,33 +42,108 @@
 
 
 #include <freetype/freetype.h>
+#include <freetype/ftlogging.h>
 #include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef FT_DEBUG_LOGGING
+
+  /**************************************************************************
+   *
+   * Variables used to control logging.
+   *
+   * 1. `ft_default_trace_level` stores the value of trace levels, which are
+   *    provided to FreeType using the `FT2_DEBUG` environment variable.
+   *
+   * 2. `ft_fileptr` stores the `FILE*` handle.
+   *
+   * 3. `ft_component` is a string that holds the name of `FT_COMPONENT`.
+   *
+   * 4. The flag `ft_component_flag` prints the name of `FT_COMPONENT` along
+   *    with the actual log message if set to true.
+   *
+   * 5. The flag `ft_timestamp_flag` prints time along with the actual log
+   *    message if set to ture.
+   *
+   * 6. `ft_have_newline_char` is used to differentiate between a log
+   *    message with and without a trailing newline character.
+   *
+   * 7. `ft_custom_trace_level` stores the custom trace level value, which
+   *    is provided by the user at run-time.
+   *
+   * We use `static` to avoid 'unused variable' warnings.
+   *
+   */
+  static const char*  ft_default_trace_level = NULL;
+  static FILE*        ft_fileptr             = NULL;
+  static const char*  ft_component           = NULL;
+  static FT_Bool      ft_component_flag      = FALSE;
+  static FT_Bool      ft_timestamp_flag      = FALSE;
+  static FT_Bool      ft_have_newline_char   = TRUE;
+  static const char*  ft_custom_trace_level  = NULL;
+
+  /* declared in ftdebug.h */
+
+  dlg_handler            ft_default_log_handler = NULL;
+  FT_Custom_Log_Handler  custom_output_handler  = NULL;
+
+#endif /* FT_DEBUG_LOGGING */
 
 
 #ifdef FT_DEBUG_LEVEL_ERROR
 
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
 
+#ifdef _WIN32_WCE
+
+  FT_LOACAL_DEF( void )
+  OutputDebugStringA( LPCSTR lpOutputString )
+  {
+    int            len;
+    LPWSTR         lpOutputStringW;
+
+
+    /* allocate memory space for converted string */
+    len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
+                               lpOutputString, -1, NULL, 0 );
+
+    lpOutputStringW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
+
+    if ( !len || !lpOutputStringW )
+      return;
+
+    /* now it is safe to do the translation */
+    MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
+                         lpOutputString, -1, lpOutputStringW, len );
+
+    OutputDebugStringW( lpOutputStringW );
+  }
+
+#endif /* _WIN32_WCE */
+
+
   /* documentation is in ftdebug.h */
 
   FT_BASE_DEF( void )
   FT_Message( const char*  fmt,
               ... )
   {
-    static char  buf[8192];
-    va_list      ap;
+    va_list  ap;
 
 
     va_start( ap, fmt );
     vfprintf( stderr, fmt, ap );
-    /* send the string to the debugger as well */
-    vsprintf( buf, fmt, ap );
-    OutputDebugStringA( buf );
+    if ( IsDebuggerPresent() )
+    {
+      static char  buf[1024];
+
+
+      vsnprintf( buf, sizeof buf, fmt, ap );
+      OutputDebugStringA( buf );
+    }
     va_end( ap );
   }
 
@@ -79,13 +154,19 @@
   FT_Panic( const char*  fmt,
             ... )
   {
-    static char  buf[8192];
-    va_list      ap;
+    va_list  ap;
 
 
     va_start( ap, fmt );
-    vsprintf( buf, fmt, ap );
-    OutputDebugStringA( buf );
+    vfprintf( stderr, fmt, ap );
+    if ( IsDebuggerPresent() )
+    {
+      static char  buf[1024];
+
+
+      vsnprintf( buf, sizeof buf, fmt, ap );
+      OutputDebugStringA( buf );
+    }
     va_end( ap );
 
     exit( EXIT_FAILURE );
@@ -207,9 +288,18 @@
   FT_BASE_DEF( void )
   ft_debug_init( void )
   {
-    const char*  ft2_debug = getenv( "FT2_DEBUG" );
+    const char*  ft2_debug = NULL;
 
 
+#ifdef FT_DEBUG_LOGGING
+    if ( ft_custom_trace_level != NULL )
+      ft2_debug = ft_custom_trace_level;
+    else
+      ft2_debug = ft_default_trace_level;
+#else
+    ft2_debug = ft_getenv( "FT2_DEBUG" );
+#endif
+
     if ( ft2_debug )
     {
       const char*  p = ft2_debug;
@@ -222,6 +312,49 @@
         if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' )
           continue;
 
+#ifdef FT_DEBUG_LOGGING
+
+        /* check extra arguments for logging */
+        if ( *p == '-' )
+        {
+          const char*  r = ++p;
+
+
+          if ( *r == 'v' )
+          {
+            const char*  s = ++r;
+
+
+            ft_component_flag = TRUE;
+
+            if ( *s == 't' )
+            {
+              ft_timestamp_flag = TRUE;
+              p++;
+            }
+
+            p++;
+          }
+
+          else if ( *r == 't' )
+          {
+            const char*  s = ++r;
+
+
+            ft_timestamp_flag = TRUE;
+
+            if ( *s == 'v' )
+            {
+              ft_component_flag = TRUE;
+              p++;
+            }
+
+            p++;
+          }
+        }
+
+#endif /* FT_DEBUG_LOGGING */
+
         /* read toggle name, followed by ':' */
         q = p;
         while ( *p && *p != ':' )
@@ -323,8 +456,237 @@
     /* nothing */
   }
 
-
 #endif /* !FT_DEBUG_LEVEL_TRACE */
 
 
+#ifdef FT_DEBUG_LOGGING
+
+  /**************************************************************************
+   *
+   * Initialize and de-initialize 'dlg' library.
+   *
+   */
+
+  FT_BASE_DEF( void )
+  ft_logging_init( void )
+  {
+    ft_default_log_handler = ft_log_handler;
+    ft_default_trace_level = ft_getenv( "FT2_DEBUG" );
+
+    if ( ft_getenv( "FT_LOGGING_FILE" ) )
+      ft_fileptr = ft_fopen( ft_getenv( "FT_LOGGING_FILE" ), "w" );
+    else
+      ft_fileptr = stderr;
+
+    ft_debug_init();
+
+    /* Set the default output handler for 'dlg'. */
+    dlg_set_handler( ft_default_log_handler, NULL );
+  }
+
+
+  FT_BASE_DEF( void )
+  ft_logging_deinit( void )
+  {
+    if ( ft_fileptr != stderr )
+      ft_fclose( ft_fileptr );
+  }
+
+
+  /**************************************************************************
+   *
+   * An output log handler for FreeType.
+   *
+   */
+  FT_BASE_DEF( void )
+  ft_log_handler( const struct dlg_origin*  origin,
+                  const char*               string,
+                  void*                     data )
+  {
+    char         features_buf[128];
+    char*        bufp = features_buf;
+
+    FT_UNUSED( data );
+
+
+    if ( ft_have_newline_char )
+    {
+      const char*  features        = NULL;
+      size_t       features_length = 0;
+
+
+#define FEATURES_TIMESTAMP            "[%h:%m] "
+#define FEATURES_COMPONENT            "[%t] "
+#define FEATURES_TIMESTAMP_COMPONENT  "[%h:%m %t] "
+
+      if ( ft_timestamp_flag && ft_component_flag )
+      {
+        features        = FEATURES_TIMESTAMP_COMPONENT;
+        features_length = sizeof ( FEATURES_TIMESTAMP_COMPONENT );
+      }
+      else if ( ft_timestamp_flag )
+      {
+        features        = FEATURES_TIMESTAMP;
+        features_length = sizeof ( FEATURES_TIMESTAMP );
+      }
+      else if ( ft_component_flag )
+      {
+        features        = FEATURES_COMPONENT;
+        features_length = sizeof ( FEATURES_COMPONENT );
+      }
+
+      if ( ft_component_flag || ft_timestamp_flag )
+      {
+        ft_strncpy( features_buf, features, features_length );
+        bufp += features_length - 1;
+      }
+
+      if ( ft_component_flag )
+      {
+        size_t  tag_length = ft_strlen( *origin->tags );
+        size_t  i;
+
+
+        /* To vertically align tracing messages we compensate the */
+        /* different FT_COMPONENT string lengths by inserting an  */
+        /* appropriate amount of space characters.                */
+        for ( i = 0;
+              i < FT_MAX_TRACE_LEVEL_LENGTH - tag_length;
+              i++ )
+          *bufp++ = ' ';
+      }
+    }
+
+    /* Finally add the format string for the tracing message. */
+    *bufp++ = '%';
+    *bufp++ = 'c';
+    *bufp   = '\0';
+
+    dlg_generic_outputf_stream( ft_fileptr,
+                                (const char*)features_buf,
+                                origin,
+                                string,
+                                dlg_default_output_styles,
+                                true );
+
+    if ( ft_strrchr( string, '\n' ) )
+      ft_have_newline_char = TRUE;
+    else
+      ft_have_newline_char = FALSE;
+  }
+
+
+  /* documentation is in ftdebug.h */
+  FT_BASE_DEF( void )
+  ft_add_tag( const char*  tag )
+  {
+    ft_component = tag;
+
+    dlg_add_tag( tag, NULL );
+  }
+
+
+  /* documentation is in ftdebug.h */
+  FT_BASE_DEF( void )
+  ft_remove_tag( const char*  tag )
+  {
+    dlg_remove_tag( tag, NULL );
+  }
+
+
+  /* documentation is in ftlogging.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Trace_Set_Level( const char*  level )
+  {
+    ft_component_flag     = FALSE;
+    ft_timestamp_flag     = FALSE;
+    ft_custom_trace_level = level;
+
+    ft_debug_init();
+  }
+
+
+  /* documentation is in ftlogging.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Trace_Set_Default_Level( void )
+  {
+    ft_component_flag     = FALSE;
+    ft_timestamp_flag     = FALSE;
+    ft_custom_trace_level = NULL;
+
+    ft_debug_init();
+  }
+
+
+  /**************************************************************************
+   *
+   * Functions to handle a custom log handler.
+   *
+   */
+
+  /* documentation is in ftlogging.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Log_Handler( FT_Custom_Log_Handler  handler )
+  {
+    custom_output_handler = handler;
+  }
+
+
+  /* documentation is in ftlogging.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Default_Log_Handler( void )
+  {
+    custom_output_handler = NULL;
+  }
+
+
+  /* documentation is in ftdebug.h */
+  FT_BASE_DEF( void )
+  FT_Logging_Callback( const char*  fmt,
+                       ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    custom_output_handler( ft_component, fmt, ap );
+    va_end( ap );
+  }
+
+#else /* !FT_DEBUG_LOGGING */
+
+  FT_EXPORT_DEF( void )
+  FT_Trace_Set_Level( const char*  level )
+  {
+    FT_UNUSED( level );
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Trace_Set_Default_Level( void )
+  {
+    /* nothing */
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Log_Handler( FT_Custom_Log_Handler  handler )
+  {
+    FT_UNUSED( handler );
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Default_Log_Handler( void )
+  {
+    /* nothing */
+  }
+
+#endif /* !FT_DEBUG_LOGGING */
+
+
 /* END */
diff --git a/builds/windows/ftsystem.c b/builds/windows/ftsystem.c
new file mode 100644
index 0000000..1ebadd4
--- /dev/null
+++ b/builds/windows/ftsystem.c
@@ -0,0 +1,436 @@
+/****************************************************************************
+ *
+ * ftsystem.c
+ *
+ *   Windows-specific FreeType low-level system interface (body).
+ *
+ * Copyright (C) 2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <ft2build.h>
+  /* we use our special ftconfig.h file, not the standard one */
+#include FT_CONFIG_CONFIG_H
+#include <freetype/internal/ftdebug.h>
+#include <freetype/ftsystem.h>
+#include <freetype/fterrors.h>
+#include <freetype/fttypes.h>
+#include <freetype/internal/ftstream.h>
+
+  /* memory mapping and allocation includes and definitions */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+
+  /**************************************************************************
+   *
+   *                      MEMORY MANAGEMENT INTERFACE
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * It is not necessary to do any error checking for the
+   * allocation-related functions.  This will be done by the higher level
+   * routines like ft_mem_alloc() or ft_mem_realloc().
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_alloc
+   *
+   * @Description:
+   *   The memory allocation function.
+   *
+   * @Input:
+   *   memory ::
+   *     A pointer to the memory object.
+   *
+   *   size ::
+   *     The requested size in bytes.
+   *
+   * @Return:
+   *   The address of newly allocated block.
+   */
+  FT_CALLBACK_DEF( void* )
+  ft_alloc( FT_Memory  memory,
+            long       size )
+  {
+    return HeapAlloc( memory->user, 0, size );
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_realloc
+   *
+   * @Description:
+   *   The memory reallocation function.
+   *
+   * @Input:
+   *   memory ::
+   *     A pointer to the memory object.
+   *
+   *   cur_size ::
+   *     The current size of the allocated memory block.
+   *
+   *   new_size ::
+   *     The newly requested size in bytes.
+   *
+   *   block ::
+   *     The current address of the block in memory.
+   *
+   * @Return:
+   *   The address of the reallocated memory block.
+   */
+  FT_CALLBACK_DEF( void* )
+  ft_realloc( FT_Memory  memory,
+              long       cur_size,
+              long       new_size,
+              void*      block )
+  {
+    FT_UNUSED( cur_size );
+
+    return HeapReAlloc( memory->user, 0, block, new_size );
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_free
+   *
+   * @Description:
+   *   The memory release function.
+   *
+   * @Input:
+   *   memory ::
+   *     A pointer to the memory object.
+   *
+   *   block ::
+   *     The address of block in memory to be freed.
+   */
+  FT_CALLBACK_DEF( void )
+  ft_free( FT_Memory  memory,
+           void*      block )
+  {
+    HeapFree( memory->user, 0, block );
+  }
+
+
+  /**************************************************************************
+   *
+   *                    RESOURCE MANAGEMENT INTERFACE
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  io
+
+  /* We use the macro STREAM_FILE for convenience to extract the       */
+  /* system-specific stream handle from a given FreeType stream object */
+#define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_close_stream_by_munmap
+   *
+   * @Description:
+   *   The function to close a stream which is opened by mmap.
+   *
+   * @Input:
+   *   stream :: A pointer to the stream object.
+   */
+  FT_CALLBACK_DEF( void )
+  ft_close_stream_by_munmap( FT_Stream  stream )
+  {
+    UnmapViewOfFile( (LPCVOID)stream->descriptor.pointer );
+
+    stream->descriptor.pointer = NULL;
+    stream->size               = 0;
+    stream->base               = NULL;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   ft_close_stream_by_free
+   *
+   * @Description:
+   *   The function to close a stream which is created by ft_alloc.
+   *
+   * @Input:
+   *   stream :: A pointer to the stream object.
+   */
+  FT_CALLBACK_DEF( void )
+  ft_close_stream_by_free( FT_Stream  stream )
+  {
+    ft_free( stream->memory, stream->descriptor.pointer );
+
+    stream->descriptor.pointer = NULL;
+    stream->size               = 0;
+    stream->base               = NULL;
+  }
+
+
+#ifdef _WIN32_WCE
+
+  FT_LOCAL_DEF( HANDLE )
+  CreateFileA( LPCSTR                lpFileName,
+               DWORD                 dwDesiredAccess,
+               DWORD                 dwShareMode,
+               LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+               DWORD                 dwCreationDisposition,
+               DWORD                 dwFlagsAndAttributes,
+               HANDLE                hTemplateFile )
+  {
+    int            len;
+    LPWSTR         lpFileNameW;
+
+
+    /* allocate memory space for converted path name */
+    len = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
+                               lpFileName, -1, NULL, 0 );
+
+    lpFileNameW = (LPWSTR)_alloca( len * sizeof ( WCHAR ) );
+
+    if ( !len || !lpFileNameW )
+    {
+      FT_ERROR(( "FT_Stream_Open: cannot convert file name to LPWSTR\n" ));
+      return INVALID_HANDLE_VALUE;
+    }
+
+    /* now it is safe to do the translation */
+    MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS,
+                         lpFileName, -1, lpFileNameW, len );
+
+    /* open the file */
+    return CreateFileW( lpFileNameW, dwDesiredAccess, dwShareMode,
+                        lpSecurityAttributes, dwCreationDisposition,
+                        dwFlagsAndAttributes, hTemplateFile );
+  }
+
+
+  FT_LOCAL_DEF( BOOL )
+  GetFileSizeEx( HANDLE         hFile,
+                 PLARGE_INTEGER lpFileSize )
+  {
+    lpFileSize->u.LowPart = GetFileSize( hFile,
+                                         (DWORD *)&lpFileSize->u.HighPart );
+
+    if ( lpFileSize->u.LowPart == INVALID_FILE_SIZE &&
+         GetLastError() != NO_ERROR                 )
+      return FALSE;
+    else
+      return TRUE;
+  }
+
+#endif /* _WIN32_WCE */
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_BASE_DEF( FT_Error )
+  FT_Stream_Open( FT_Stream    stream,
+                  const char*  filepathname )
+  {
+    HANDLE         file;
+    HANDLE         fm;
+    LARGE_INTEGER  size;
+
+
+    if ( !stream )
+      return FT_THROW( Invalid_Stream_Handle );
+
+    /* open the file */
+    file = CreateFileA( (LPCSTR)filepathname, GENERIC_READ, FILE_SHARE_READ,
+                        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
+    if ( file == INVALID_HANDLE_VALUE )
+    {
+      FT_ERROR(( "FT_Stream_Open:" ));
+      FT_ERROR(( " could not open `%s'\n", filepathname ));
+      return FT_THROW( Cannot_Open_Resource );
+    }
+
+    if ( GetFileSizeEx( file, &size ) == FALSE )
+    {
+      FT_ERROR(( "FT_Stream_Open:" ));
+      FT_ERROR(( " could not retrieve size of file `%s'\n", filepathname ));
+      goto Fail_Open;
+    }
+
+    /* `stream->size' is typedef'd to unsigned long (in `ftsystem.h'); */
+    /* So avoid overflow caused by fonts in huge files larger than     */
+    /* 2GB, do a test.                                                 */
+    if ( size.QuadPart > LONG_MAX )
+    {
+      FT_ERROR(( "FT_Stream_Open: file is too big\n" ));
+      goto Fail_Open;
+    }
+    else if ( size.QuadPart == 0 )
+    {
+      FT_ERROR(( "FT_Stream_Open: zero-length file\n" ));
+      goto Fail_Open;
+    }
+
+    fm = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
+    if ( fm == NULL )
+    {
+      FT_ERROR(( "FT_Stream_Open: can not map file\n" ));
+      goto Fail_Open;
+    }
+
+    /* Store only the low part of this 64 bits integer because long is */
+    /* a 32 bits type. Anyway, a check has been done above to forbid   */
+    /* a size greater than LONG_MAX                                    */
+    stream->size = size.LowPart;
+    stream->pos  = 0;
+    stream->base = (unsigned char *)
+                     MapViewOfFile( fm, FILE_MAP_READ, 0, 0, 0 );
+
+    CloseHandle( fm );
+
+    if ( stream->base != NULL )
+      stream->close = ft_close_stream_by_munmap;
+    else
+    {
+      DWORD  total_read_count;
+
+
+      FT_ERROR(( "FT_Stream_Open:" ));
+      FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
+
+      stream->base = (unsigned char*)ft_alloc( stream->memory, stream->size );
+
+      if ( !stream->base )
+      {
+        FT_ERROR(( "FT_Stream_Open:" ));
+        FT_ERROR(( " could not `alloc' memory\n" ));
+        goto Fail_Open;
+      }
+
+      total_read_count = 0;
+      do
+      {
+        DWORD  read_count;
+
+
+        if ( ReadFile( file,
+                       stream->base + total_read_count,
+                       stream->size - total_read_count,
+                       &read_count, NULL ) == FALSE )
+        {
+          FT_ERROR(( "FT_Stream_Open:" ));
+          FT_ERROR(( " error while `read'ing file `%s'\n", filepathname ));
+          goto Fail_Read;
+        }
+
+        total_read_count += read_count;
+
+      } while ( total_read_count != stream->size );
+
+      stream->close = ft_close_stream_by_free;
+    }
+
+    CloseHandle( file );
+
+    stream->descriptor.pointer = stream->base;
+    stream->pathname.pointer   = (char*)filepathname;
+
+    stream->read = NULL;
+
+    FT_TRACE1(( "FT_Stream_Open:" ));
+    FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
+                filepathname, stream->size ));
+
+    return FT_Err_Ok;
+
+  Fail_Read:
+    ft_free( stream->memory, stream->base );
+
+  Fail_Open:
+    CloseHandle( file );
+
+    stream->base = NULL;
+    stream->size = 0;
+    stream->pos  = 0;
+
+    return FT_THROW( Cannot_Open_Stream );
+  }
+
+
+#ifdef FT_DEBUG_MEMORY
+
+  extern FT_Int
+  ft_mem_debug_init( FT_Memory  memory );
+
+  extern void
+  ft_mem_debug_done( FT_Memory  memory );
+
+#endif
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_BASE_DEF( FT_Memory )
+  FT_New_Memory( void )
+  {
+    HANDLE     heap;
+    FT_Memory  memory;
+
+
+    heap   = GetProcessHeap();
+    memory = heap ? (FT_Memory)HeapAlloc( heap, 0, sizeof ( *memory ) )
+                  : NULL;
+
+    if ( memory )
+    {
+      memory->user    = heap;
+      memory->alloc   = ft_alloc;
+      memory->realloc = ft_realloc;
+      memory->free    = ft_free;
+#ifdef FT_DEBUG_MEMORY
+      ft_mem_debug_init( memory );
+#endif
+    }
+
+    return memory;
+  }
+
+
+  /* documentation is in ftobjs.h */
+
+  FT_BASE_DEF( void )
+  FT_Done_Memory( FT_Memory  memory )
+  {
+#ifdef FT_DEBUG_MEMORY
+    ft_mem_debug_done( memory );
+#endif
+    memory->free( memory, memory );
+  }
+
+
+/* END */
diff --git a/builds/windows/vc2010/freetype.sln b/builds/windows/vc2010/freetype.sln
index 8698207..d88d70a 100644
--- a/builds/windows/vc2010/freetype.sln
+++ b/builds/windows/vc2010/freetype.sln
@@ -4,34 +4,49 @@
 EndProject

 Global

 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

-		Debug|Win32 = Debug|Win32

 		Debug|x64 = Debug|x64

-		Debug Static|Win32 = Debug Static|Win32

+		Debug|ARM64 = Debug|ARM64

+		Debug|Win32 = Debug|Win32

 		Debug Static|x64 = Debug Static|x64

-		Release|Win32 = Release|Win32

+		Debug Static|ARM64 = Debug Static|ARM64

+		Debug Static|Win32 = Debug Static|Win32

 		Release|x64 = Release|x64

-		Release Static|Win32 = Release Static|Win32

+		Release|ARM64 = Release|ARM64

+		Release|Win32 = Release|Win32

 		Release Static|x64 = Release Static|x64

+		Release Static|ARM64 = Release Static|ARM64

+		Release Static|Win32 = Release Static|Win32

 	EndGlobalSection

 	GlobalSection(ProjectConfigurationPlatforms) = postSolution

-		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug|Win32.ActiveCfg = Debug|Win32

-		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug|Win32.Build.0 = Debug|Win32

 		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug|x64.ActiveCfg = Debug|x64

 		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug|x64.Build.0 = Debug|x64

-		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug Static|Win32.ActiveCfg = Debug Static|Win32

-		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug Static|Win32.Build.0 = Debug Static|Win32

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug|ARM64.ActiveCfg = Debug|ARM64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug|ARM64.Build.0 = Debug|ARM64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug|Win32.ActiveCfg = Debug|Win32

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug|Win32.Build.0 = Debug|Win32

 		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug Static|x64.ActiveCfg = Debug Static|x64

 		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug Static|x64.Build.0 = Debug Static|x64

-		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release|Win32.ActiveCfg = Release|Win32

-		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release|Win32.Build.0 = Release|Win32

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug Static|ARM64.ActiveCfg = Debug Static|ARM64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug Static|ARM64.Build.0 = Debug Static|ARM64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug Static|Win32.ActiveCfg = Debug Static|Win32

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Debug Static|Win32.Build.0 = Debug Static|Win32

 		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release|x64.ActiveCfg = Release|x64

 		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release|x64.Build.0 = Release|x64

-		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release Static|Win32.ActiveCfg = Release Static|Win32

-		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release Static|Win32.Build.0 = Release Static|Win32

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release|ARM64.ActiveCfg = Release|ARM64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release|ARM64.Build.0 = Release|ARM64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release|Win32.ActiveCfg = Release|Win32

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release|Win32.Build.0 = Release|Win32

 		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release Static|x64.ActiveCfg = Release Static|x64

 		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release Static|x64.Build.0 = Release Static|x64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release Static|ARM64.ActiveCfg = Release Static|ARM64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release Static|ARM64.Build.0 = Release Static|ARM64

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release Static|Win32.ActiveCfg = Release Static|Win32

+		{78B079BD-9FC7-4B9E-B4A6-96DA0F00248B}.Release Static|Win32.Build.0 = Release Static|Win32

 	EndGlobalSection

 	GlobalSection(SolutionProperties) = preSolution

 		HideSolutionNode = FALSE

 	EndGlobalSection

+	GlobalSection(ExtensibilityGlobals) = postSolution

+		SolutionGuid = {90811697-0889-4381-80BC-C3FE8FA4931F}

+	EndGlobalSection

 EndGlobal

diff --git a/builds/windows/vc2010/freetype.vcxproj b/builds/windows/vc2010/freetype.vcxproj
index d61eeec..0d38678 100644
--- a/builds/windows/vc2010/freetype.vcxproj
+++ b/builds/windows/vc2010/freetype.vcxproj
@@ -1,10 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+<!--

+  You can use this file to build FreeType with MSBuild as follows

+

+    MSBuild.exe -t:Rebuild

+                -p:Configuration=Debug

+                -p:Platform=x64

+                -p:UserDefines=FT_DEBUG_LOGGING

+                   builds/windows/vc2010/freetype.vcxproj

+

+  or with different appropriate switches. It also works with Visual Studio.

+  Additional customization can be made in `freetype.user.props`.

+-->

+<Project DefaultTargets="DlgCopy;Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Debug|Win32">

       <Configuration>Debug</Configuration>

       <Platform>Win32</Platform>

     </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug|ARM64">

+      <Configuration>Debug</Configuration>

+      <Platform>ARM64</Platform>

+    </ProjectConfiguration>

     <ProjectConfiguration Include="Debug|x64">

       <Configuration>Debug</Configuration>

       <Platform>x64</Platform>

@@ -13,6 +29,10 @@
       <Configuration>Debug Static</Configuration>

       <Platform>Win32</Platform>

     </ProjectConfiguration>

+    <ProjectConfiguration Include="Debug Static|ARM64">

+      <Configuration>Debug Static</Configuration>

+      <Platform>ARM64</Platform>

+    </ProjectConfiguration>

     <ProjectConfiguration Include="Debug Static|x64">

       <Configuration>Debug Static</Configuration>

       <Platform>x64</Platform>

@@ -21,6 +41,10 @@
       <Configuration>Release</Configuration>

       <Platform>Win32</Platform>

     </ProjectConfiguration>

+    <ProjectConfiguration Include="Release|ARM64">

+      <Configuration>Release</Configuration>

+      <Platform>ARM64</Platform>

+    </ProjectConfiguration>

     <ProjectConfiguration Include="Release|x64">

       <Configuration>Release</Configuration>

       <Platform>x64</Platform>

@@ -29,6 +53,10 @@
       <Configuration>Release Static</Configuration>

       <Platform>Win32</Platform>

     </ProjectConfiguration>

+    <ProjectConfiguration Include="Release Static|ARM64">

+      <Configuration>Release Static</Configuration>

+      <Platform>ARM64</Platform>

+    </ProjectConfiguration>

     <ProjectConfiguration Include="Release Static|x64">

       <Configuration>Release Static</Configuration>

       <Platform>x64</Platform>

@@ -44,35 +72,51 @@
   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

     <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

     <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

+    <CharacterSet>NotSet</CharacterSet>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'" Label="Configuration">

     <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static|ARM64'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'" Label="Configuration">

     <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

+    <CharacterSet>NotSet</CharacterSet>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

     <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">

+    <ConfigurationType>DynamicLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

     <ConfigurationType>DynamicLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

+    <CharacterSet>NotSet</CharacterSet>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Static|Win32'" Label="Configuration">

     <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

+    <CharacterSet>NotSet</CharacterSet>

+  </PropertyGroup>

+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Static|ARM64'" Label="Configuration">

+    <ConfigurationType>StaticLibrary</ConfigurationType>

+    <CharacterSet>NotSet</CharacterSet>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'" Label="Configuration">

     <ConfigurationType>StaticLibrary</ConfigurationType>

-    <CharacterSet>Unicode</CharacterSet>

+    <CharacterSet>NotSet</CharacterSet>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

@@ -93,7 +137,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FT_DEBUG_LEVEL_ERROR;FT_DEBUG_LEVEL_TRACE;FT2_BUILD_LIBRARY;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>

-      <DisableLanguageExtensions>true</DisableLanguageExtensions>

+      <DisableLanguageExtensions>false</DisableLanguageExtensions>

       <WarningLevel>Level4</WarningLevel>

       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

       <CompileAs>Default</CompileAs>

@@ -106,11 +150,39 @@
       <PreprocessorDefinitions>_DEBUG;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <Culture>0x0409</Culture>

     </ResourceCompile>

-    <Lib>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

       <TargetMachine>MachineX86</TargetMachine>

       <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

-    </Lib>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>$(UserOptionDirectory);..\..\..\include;$(UserIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FT_DEBUG_LEVEL_ERROR;FT_DEBUG_LEVEL_TRACE;FT2_BUILD_LIBRARY;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>

+      <DisableLanguageExtensions>false</DisableLanguageExtensions>

+      <WarningLevel>Level4</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <CompileAs>Default</CompileAs>

+      <DisableSpecificWarnings>4001</DisableSpecificWarnings>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>

+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>

+    </ClCompile>

+    <ResourceCompile>

+      <PreprocessorDefinitions>_DEBUG;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <Culture>0x0409</Culture>

+    </ResourceCompile>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

+      <TargetMachine>MachineARM64</TargetMachine>

+      <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

     <ClCompile>

@@ -119,7 +191,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FT_DEBUG_LEVEL_ERROR;FT_DEBUG_LEVEL_TRACE;FT2_BUILD_LIBRARY;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>

-      <DisableLanguageExtensions>true</DisableLanguageExtensions>

+      <DisableLanguageExtensions>false</DisableLanguageExtensions>

       <WarningLevel>Level4</WarningLevel>

       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

       <CompileAs>Default</CompileAs>

@@ -132,11 +204,12 @@
       <PreprocessorDefinitions>_DEBUG;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <Culture>0x0409</Culture>

     </ResourceCompile>

-    <Lib>

+    <Link>

+      <GenerateDebugInformation>true</GenerateDebugInformation>

       <TargetMachine>MachineX64</TargetMachine>

       <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

-    </Lib>

+    </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static|Win32'">

     <ClCompile>

@@ -145,7 +218,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FT_DEBUG_LEVEL_ERROR;FT_DEBUG_LEVEL_TRACE;FT2_BUILD_LIBRARY;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <DisableLanguageExtensions>true</DisableLanguageExtensions>

+      <DisableLanguageExtensions>false</DisableLanguageExtensions>

       <WarningLevel>Level4</WarningLevel>

       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

       <CompileAs>Default</CompileAs>

@@ -164,6 +237,32 @@
       <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

     </Lib>

   </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static|ARM64'">

+    <ClCompile>

+      <Optimization>Disabled</Optimization>

+      <AdditionalIncludeDirectories>$(UserOptionDirectory);..\..\..\include;$(UserIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FT_DEBUG_LEVEL_ERROR;FT_DEBUG_LEVEL_TRACE;FT2_BUILD_LIBRARY;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

+      <DisableLanguageExtensions>false</DisableLanguageExtensions>

+      <WarningLevel>Level4</WarningLevel>

+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

+      <CompileAs>Default</CompileAs>

+      <DisableSpecificWarnings>4001</DisableSpecificWarnings>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>

+      <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>

+    </ClCompile>

+    <ResourceCompile>

+      <PreprocessorDefinitions>_DEBUG;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <Culture>0x0409</Culture>

+    </ResourceCompile>

+    <Lib>

+      <TargetMachine>MachineARM64</TargetMachine>

+      <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

+    </Lib>

+  </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Static|x64'">

     <ClCompile>

       <Optimization>Disabled</Optimization>

@@ -171,7 +270,7 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FT_DEBUG_LEVEL_ERROR;FT_DEBUG_LEVEL_TRACE;FT2_BUILD_LIBRARY;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

-      <DisableLanguageExtensions>true</DisableLanguageExtensions>

+      <DisableLanguageExtensions>false</DisableLanguageExtensions>

       <WarningLevel>Level4</WarningLevel>

       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>

       <CompileAs>Default</CompileAs>

@@ -210,12 +309,41 @@
       <PreprocessorDefinitions>NDEBUG;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <Culture>0x0409</Culture>

     </ResourceCompile>

-    <Lib>

-      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>

+    <Link>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

       <TargetMachine>MachineX86</TargetMachine>

       <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

-    </Lib>

+    </Link>

+  </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">

+    <ClCompile>

+      <Optimization>MaxSpeed</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(UserOptionDirectory);..\..\..\include;$(UserIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <DisableLanguageExtensions>true</DisableLanguageExtensions>

+      <WarningLevel>Level4</WarningLevel>

+      <CompileAs>Default</CompileAs>

+      <DisableSpecificWarnings>4001</DisableSpecificWarnings>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+    </ClCompile>

+    <ResourceCompile>

+      <PreprocessorDefinitions>NDEBUG;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <Culture>0x0409</Culture>

+    </ResourceCompile>

+    <Link>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

+      <TargetMachine>MachineARM64</TargetMachine>

+      <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

+    </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

     <ClCompile>

@@ -230,19 +358,19 @@
       <CompileAs>Default</CompileAs>

       <DisableSpecificWarnings>4001</DisableSpecificWarnings>

       <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>

       <IntrinsicFunctions>true</IntrinsicFunctions>

     </ClCompile>

     <ResourceCompile>

       <PreprocessorDefinitions>NDEBUG;DLL_EXPORT;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

       <Culture>0x0409</Culture>

     </ResourceCompile>

-    <Lib>

-      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>

+    <Link>

+      <EnableCOMDATFolding>true</EnableCOMDATFolding>

+      <OptimizeReferences>true</OptimizeReferences>

       <TargetMachine>MachineX64</TargetMachine>

       <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

-    </Lib>

+    </Link>

   </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Static|Win32'">

     <ClCompile>

@@ -265,12 +393,37 @@
       <Culture>0x0409</Culture>

     </ResourceCompile>

     <Lib>

-      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>

       <TargetMachine>MachineX86</TargetMachine>

       <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

     </Lib>

   </ItemDefinitionGroup>

+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Static|ARM64'">

+    <ClCompile>

+      <Optimization>MaxSpeed</Optimization>

+      <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

+      <AdditionalIncludeDirectories>$(UserOptionDirectory);..\..\..\include;$(UserIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>

+      <FunctionLevelLinking>true</FunctionLevelLinking>

+      <DisableLanguageExtensions>true</DisableLanguageExtensions>

+      <WarningLevel>Level4</WarningLevel>

+      <CompileAs>Default</CompileAs>

+      <DisableSpecificWarnings>4001</DisableSpecificWarnings>

+      <MultiProcessorCompilation>true</MultiProcessorCompilation>

+      <EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>

+      <IntrinsicFunctions>true</IntrinsicFunctions>

+    </ClCompile>

+    <ResourceCompile>

+      <PreprocessorDefinitions>NDEBUG;$(UserDefines);%(PreprocessorDefinitions)</PreprocessorDefinitions>

+      <Culture>0x0409</Culture>

+    </ResourceCompile>

+    <Lib>

+      <TargetMachine>MachineARM64</TargetMachine>

+      <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

+      <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

+    </Lib>

+  </ItemDefinitionGroup>

   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Static|x64'">

     <ClCompile>

       <Optimization>MaxSpeed</Optimization>

@@ -284,7 +437,6 @@
       <CompileAs>Default</CompileAs>

       <DisableSpecificWarnings>4001</DisableSpecificWarnings>

       <MultiProcessorCompilation>true</MultiProcessorCompilation>

-      <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>

       <IntrinsicFunctions>true</IntrinsicFunctions>

     </ClCompile>

     <ResourceCompile>

@@ -292,7 +444,6 @@
       <Culture>0x0409</Culture>

     </ResourceCompile>

     <Lib>

-      <LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>

       <TargetMachine>MachineX64</TargetMachine>

       <AdditionalLibraryDirectories>$(UserLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>

       <AdditionalDependencies>$(UserDependencies);%(AdditionalDependencies)</AdditionalDependencies>

@@ -316,13 +467,13 @@
     <ClCompile Include="..\..\..\src\base\ftpfr.c" />

     <ClCompile Include="..\..\..\src\base\ftstroke.c" />

     <ClCompile Include="..\..\..\src\base\ftsynth.c" />

-    <ClCompile Include="..\..\..\src\base\ftsystem.c" />

     <ClCompile Include="..\..\..\src\base\fttype1.c" />

     <ClCompile Include="..\..\..\src\base\ftwinfnt.c" />

     <ClCompile Include="..\..\..\src\bdf\bdf.c" />

     <ClCompile Include="..\..\..\src\cache\ftcache.c" />

     <ClCompile Include="..\..\..\src\cff\cff.c" />

     <ClCompile Include="..\..\..\src\cid\type1cid.c" />

+    <ClCompile Include="..\..\..\src\dlg\dlgwrap.c" />

     <ClCompile Include="..\..\..\src\gzip\ftgzip.c" />

     <ClCompile Include="..\..\..\src\lzw\ftlzw.c" />

     <ClCompile Include="..\..\..\src\pcf\pcf.c" />

@@ -333,6 +484,7 @@
     <ClCompile Include="..\..\..\src\raster\raster.c" />

     <ClCompile Include="..\..\..\src\sfnt\sfnt.c" />

     <ClCompile Include="..\..\..\src\smooth\smooth.c" />

+    <ClCompile Include="..\..\..\src\sdf\sdf.c" />

     <ClCompile Include="..\..\..\src\truetype\truetype.c" />

     <ClCompile Include="..\..\..\src\type1\type1.c" />

     <ClCompile Include="..\..\..\src\type42\type42.c" />

@@ -340,12 +492,33 @@
     <ClCompile Include="..\ftdebug.c">

       <DisableLanguageExtensions>false</DisableLanguageExtensions>

     </ClCompile>

+    <ClCompile Include="..\ftsystem.c">

+      <DisableLanguageExtensions>false</DisableLanguageExtensions>

+    </ClCompile>

     <ResourceCompile Include="..\..\..\src\base\ftver.rc" />

   </ItemGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

   <ImportGroup Label="ExtensionTargets">

   </ImportGroup>

+  <ItemGroup Condition="Exists('..\..\..\subprojects\dlg\.git')">

+    <DlgSrc Include="..\..\..\subprojects\dlg\include\dlg\output.h">

+      <DlgDst>..\..\..\include\dlg\output.h</DlgDst>

+    </DlgSrc>

+    <DlgSrc Include="..\..\..\subprojects\dlg\include\dlg\dlg.h">

+      <DlgDst>..\..\..\include\dlg\dlg.h</DlgDst>

+    </DlgSrc>

+    <DlgSrc Include="..\..\..\subprojects\dlg\src\dlg\dlg.c">

+      <DlgDst>..\..\..\src\dlg\dlg.c</DlgDst>

+    </DlgSrc>

+  </ItemGroup>

+  <Target Name="DlgCopy" Inputs="@(DlgSrc)" Outputs="@(DlgSrc->'%(DlgDst)')" Condition="Exists('..\..\..\subprojects\dlg\.git')">

+    <Copy SourceFiles="@(DlgSrc)" DestinationFiles="@(DlgSrc->'%(DlgDst)')" />

+  </Target>

   <Target Name="AfterBuild">

-    <Copy SourceFiles="$(TargetPath)" DestinationFolder="..\..\..\objs" />

+    <ItemGroup>

+      <TargetFiles Include="$(TargetDir)$(TargetName).*" />

+    </ItemGroup>

+    <Copy SourceFiles="@(TargetFiles)" DestinationFolder="..\..\..\objs" />

+    <Copy SourceFiles="$(TargetDir)$(TargetFileName)" DestinationFolder="..\..\..\..\freetype-demos\bin" Condition="'$(TargetExt)'=='.dll'" />

   </Target>

 </Project>

diff --git a/builds/windows/vc2010/freetype.vcxproj.filters b/builds/windows/vc2010/freetype.vcxproj.filters
index 345e1f1..3f68c82 100644
--- a/builds/windows/vc2010/freetype.vcxproj.filters
+++ b/builds/windows/vc2010/freetype.vcxproj.filters
@@ -23,9 +23,6 @@
     <ClCompile Include="..\..\..\src\base\ftinit.c">

       <Filter>Source Files</Filter>

     </ClCompile>

-    <ClCompile Include="..\..\..\src\base\ftsystem.c">

-      <Filter>Source Files</Filter>

-    </ClCompile>

     <ClCompile Include="..\..\..\src\bdf\bdf.c">

       <Filter>Source Files</Filter>

     </ClCompile>

@@ -65,6 +62,9 @@
     <ClCompile Include="..\..\..\src\sfnt\sfnt.c">

       <Filter>Source Files</Filter>

     </ClCompile>

+    <ClCompile Include="..\..\..\src\sdf\sdf.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

     <ClCompile Include="..\..\..\src\smooth\smooth.c">

       <Filter>Source Files</Filter>

     </ClCompile>

@@ -131,6 +131,12 @@
     <ClCompile Include="..\..\..\src\base\ftwinfnt.c">

       <Filter>Source Files\FT_MODULES</Filter>

     </ClCompile>

+    <ClCompile Include="..\..\..\src\dlg\dlgwrap.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

+    <ClCompile Include="..\ftsystem.c">

+      <Filter>Source Files</Filter>

+    </ClCompile>

   </ItemGroup>

   <ItemGroup>

     <ResourceCompile Include="..\..\..\src\base\ftver.rc">

diff --git a/builds/windows/vc2010/index.html b/builds/windows/vc2010/index.html
index 3b60c5f..dcb1944 100644
--- a/builds/windows/vc2010/index.html
+++ b/builds/windows/vc2010/index.html
@@ -12,7 +12,7 @@
 <p>This directory contains solution and project files for
 Visual&nbsp;C++&nbsp;2010 or newer, named <tt>freetype.sln</tt>,
 and <tt>freetype.vcxproj</tt>.  It compiles the following libraries
-from the FreeType 2.10.4 sources:</p>
+from the FreeType 2.11.1 sources:</p>
 
 <ul>
   <li>freetype.dll using 'Release' or 'Debug' configurations</li>
diff --git a/builds/windows/visualc/freetype.dsp b/builds/windows/visualc/freetype.dsp
index 028dd7b..540f5b9 100644
--- a/builds/windows/visualc/freetype.dsp
+++ b/builds/windows/visualc/freetype.dsp
@@ -58,7 +58,7 @@
 # ADD BSC32 /nologo

 LINK32=link.exe

 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386

-# ADD LINK32 /nologo /dll /machine:I386 /out:"$(OutDir)\freetype.dll"

+# ADD LINK32 /nologo /dll /machine:I386 /opt:REF,ICF /out:"$(OutDir)\freetype.dll"

 

 !ELSEIF  "$(CFG)" == "freetype - Win32 Debug"

 

diff --git a/builds/windows/visualc/freetype.vcproj b/builds/windows/visualc/freetype.vcproj
index ecb5b05..4cbb6b9 100644
--- a/builds/windows/visualc/freetype.vcproj
+++ b/builds/windows/visualc/freetype.vcproj
@@ -19,7 +19,7 @@
 			ConfigurationType="2"

 			UseOfMFC="0"

 			ATLMinimizesCRunTimeLibraryUsage="false"

-			CharacterSet="1"

+			CharacterSet="0"

 			>

 			<Tool

 				Name="VCPreBuildEventTool"

@@ -45,6 +45,7 @@
 				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY;DLL_EXPORT"

 				StringPooling="true"

 				RuntimeLibrary="2"

+				EnableEnhancedInstructionSet="2"

 				EnableFunctionLevelLinking="true"

 				DisableLanguageExtensions="true"

 				WarningLevel="4"

@@ -65,6 +66,8 @@
 			/>

 			<Tool

 				Name="VCLinkerTool"

+				OptimizeReferences="2"

+				EnableCOMDATFolding="2"

 			/>

 			<Tool

 				Name="VCALinkTool"

@@ -95,7 +98,7 @@
 			ConfigurationType="4"

 			UseOfMFC="0"

 			ATLMinimizesCRunTimeLibraryUsage="false"

-			CharacterSet="1"

+			CharacterSet="0"

 			>

 			<Tool

 				Name="VCPreBuildEventTool"

@@ -121,6 +124,7 @@
 				PreprocessorDefinitions="NDEBUG;WIN32;_LIB;_CRT_SECURE_NO_WARNINGS;FT2_BUILD_LIBRARY"

 				StringPooling="true"

 				RuntimeLibrary="0"

+				EnableEnhancedInstructionSet="2"

 				EnableFunctionLevelLinking="true"

 				DisableLanguageExtensions="true"

 				WarningLevel="4"

@@ -165,7 +169,7 @@
 			ConfigurationType="2"

 			UseOfMFC="0"

 			ATLMinimizesCRunTimeLibraryUsage="false"

-			CharacterSet="1"

+			CharacterSet="0"

 			>

 			<Tool

 				Name="VCPreBuildEventTool"

@@ -238,7 +242,7 @@
 			ConfigurationType="4"

 			UseOfMFC="0"

 			ATLMinimizesCRunTimeLibraryUsage="false"

-			CharacterSet="1"

+			CharacterSet="0"

 			>

 			<Tool

 				Name="VCPreBuildEventTool"

@@ -395,8 +399,40 @@
 				>

 			</File>

 			<File

-				RelativePath="..\..\..\src\base\ftsystem.c"

+				RelativePath="..\ftsystem.c"

 				>

+				<FileConfiguration

+					Name="Release|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						DisableLanguageExtensions="false"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Release Static|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						DisableLanguageExtensions="false"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Debug|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						DisableLanguageExtensions="false"

+					/>

+				</FileConfiguration>

+				<FileConfiguration

+					Name="Debug Static|Win32"

+					>

+					<Tool

+						Name="VCCLCompilerTool"

+						DisableLanguageExtensions="false"

+					/>

+				</FileConfiguration>

 			</File>

 			<File

 				RelativePath="..\..\..\src\smooth\smooth.c"

diff --git a/builds/windows/visualc/index.html b/builds/windows/visualc/index.html
index cec26d2..d0c8f2f 100644
--- a/builds/windows/visualc/index.html
+++ b/builds/windows/visualc/index.html
@@ -12,7 +12,7 @@
 <p>This directory contains project files <tt>freetype.dsp</tt> for
 Visual C++ 6.0, and <tt>freetype.vcproj</tt> for Visual C++ 2002
 through 2008, which you might need to upgrade automatically.
-It compiles the following libraries from the FreeType 2.10.4 sources:</p>
+It compiles the following libraries from the FreeType 2.11.1 sources:</p>
 
 <ul>
   <li>freetype.dll using 'Release' or 'Debug' configurations</li>
diff --git a/builds/windows/visualce/index.html b/builds/windows/visualce/index.html
index 474e85c..b50ef79 100644
--- a/builds/windows/visualce/index.html
+++ b/builds/windows/visualce/index.html
@@ -21,7 +21,7 @@
   <li>PPC/SP WM6 (Windows Mobile 6)</li>
 </ul>
 
-It compiles the following libraries from the FreeType 2.10.4 sources:</p>
+It compiles the following libraries from the FreeType 2.11.1 sources:</p>
 
 <ul>
   <pre>
diff --git a/builds/windows/w32-bcc.mk b/builds/windows/w32-bcc.mk
index c80710e..d497dd1 100644
--- a/builds/windows/w32-bcc.mk
+++ b/builds/windows/w32-bcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-bccd.mk b/builds/windows/w32-bccd.mk
index 966bdb5..701b83d 100644
--- a/builds/windows/w32-bccd.mk
+++ b/builds/windows/w32-bccd.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-dev.mk b/builds/windows/w32-dev.mk
index b2af667..a2f4644 100644
--- a/builds/windows/w32-dev.mk
+++ b/builds/windows/w32-dev.mk
@@ -5,7 +5,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-gcc.mk b/builds/windows/w32-gcc.mk
index f27e6b1..4117453 100644
--- a/builds/windows/w32-gcc.mk
+++ b/builds/windows/w32-gcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-icc.mk b/builds/windows/w32-icc.mk
index 2e69609..ebab45e 100644
--- a/builds/windows/w32-icc.mk
+++ b/builds/windows/w32-icc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-intl.mk b/builds/windows/w32-intl.mk
index 88e6269..0fef8d7 100644
--- a/builds/windows/w32-intl.mk
+++ b/builds/windows/w32-intl.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-lcc.mk b/builds/windows/w32-lcc.mk
index 6cf6460..7aed5b5 100644
--- a/builds/windows/w32-lcc.mk
+++ b/builds/windows/w32-lcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-mingw32.mk b/builds/windows/w32-mingw32.mk
index f2eb021..6731778 100644
--- a/builds/windows/w32-mingw32.mk
+++ b/builds/windows/w32-mingw32.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-vcc.mk b/builds/windows/w32-vcc.mk
index e800d27..278624f 100644
--- a/builds/windows/w32-vcc.mk
+++ b/builds/windows/w32-vcc.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/w32-wat.mk b/builds/windows/w32-wat.mk
index a0de4bb..df2ece3 100644
--- a/builds/windows/w32-wat.mk
+++ b/builds/windows/w32-wat.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/builds/windows/win32-def.mk b/builds/windows/win32-def.mk
index f759853..15bfd0c 100644
--- a/builds/windows/win32-def.mk
+++ b/builds/windows/win32-def.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -13,11 +13,11 @@
 # fully.
 
 
-DELETE    := del
-CAT       := type
-SEP       := $(strip \ )
-BUILD_DIR := $(TOP_DIR)/builds/windows
-PLATFORM  := windows
+DELETE       := del
+CAT          := type
+SEP          := $(strip \ )
+PLATFORM_DIR := $(TOP_DIR)/builds/windows
+PLATFORM     := windows
 
 # This is used for `make refdoc' and `make refdoc-venv'
 #
diff --git a/configure b/configure
index ac91a8e..584e6ec 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (C) 2002-2020 by
+# Copyright (C) 2002-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -93,7 +93,7 @@
 inode_src=`ls -id $abs_ft2_dir | awk '{print $1}'`
 inode_dst=`ls -id $abs_curr_dir | awk '{print $1}'`
 
-if test $inode_src -ne $inode_dst; then
+if test $inode_src != $inode_dst; then
   if test ! -d docs; then
     mkdir docs
     echo "Copying documentation assets"
diff --git a/devel-teeui/rules.mk b/devel-teeui/rules.mk
index 864a286..b834ce7 100644
--- a/devel-teeui/rules.mk
+++ b/devel-teeui/rules.mk
@@ -19,14 +19,14 @@
 	$(FREETYPE_ROOT)/src/autofit/autofit.c \
 	$(FREETYPE_ROOT)/src/gzip/ftgzip.c \
 
-GLOBAL_INCLUDES += \
+MODULE_EXPORT_INCLUDES += \
 	$(LOCAL_DIR) \
 	$(FREETYPE_ROOT)/include \
 
 MODULE_COMPILEFLAGS := -U__ANDROID__ -DFT2_BUILD_LIBRARY
 MODULE_COMPILEFLAGS += -Wno-implicit-fallthrough
 
-MODULE_DEPS += \
+MODULE_LIBRARY_DEPS += \
 	trusty/user/base/lib/libc-trusty \
 
-include make/module.mk
+include make/library.mk
diff --git a/devel/ft2build.h b/devel/ft2build.h
index 0ab8ba0..117532b 100644
--- a/devel/ft2build.h
+++ b/devel/ft2build.h
@@ -4,7 +4,7 @@
  *
  *   FreeType 2 build and setup macros (development version).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/devel/ftoption.h b/devel/ftoption.h
index 307d1a3..f92b416 100644
--- a/devel/ftoption.h
+++ b/devel/ftoption.h
@@ -4,7 +4,7 @@
  *
  *   User-selectable configuration macros (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -105,8 +105,7 @@
    *
    * ```
    *   FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
-   *                       cff:no-stem-darkening=1 \
-   *                       autofitter:warping=1
+   *                       cff:no-stem-darkening=1
    * ```
    *
    */
@@ -433,6 +432,21 @@
 
   /**************************************************************************
    *
+   * Logging
+   *
+   *   Compiling FreeType in debug or trace mode makes FreeType write error
+   *   and trace log messages to `stderr`.  Enabling this macro
+   *   automatically forces the `FT_DEBUG_LEVEL_ERROR` and
+   *   `FT_DEBUG_LEVEL_TRACE` macros and allows FreeType to write error and
+   *   trace log messages to a file instead of `stderr`.  For writing logs
+   *   to a file, FreeType uses an the external `dlg` library (the source
+   *   code is in `src/dlg`).
+   */
+#define FT_DEBUG_LOGGING
+
+
+  /**************************************************************************
+   *
    * Autofitter debugging
    *
    *   If `FT_DEBUG_AUTOFIT` is defined, FreeType provides some means to
@@ -894,24 +908,6 @@
 
   /**************************************************************************
    *
-   * Compile 'autofit' module with warp hinting.  The idea of the warping
-   * code is to slightly scale and shift a glyph within a single dimension so
-   * that as much of its segments are aligned (more or less) on the grid.  To
-   * find out the optimal scaling and shifting value, various parameter
-   * combinations are tried and scored.
-   *
-   * You can switch warping on and off with the `warping` property of the
-   * auto-hinter (see file `ftdriver.h` for more information; by default it
-   * is switched off).
-   *
-   * This experimental option is not active if the rendering mode is
-   * `FT_RENDER_MODE_LIGHT`.
-   */
-#define AF_CONFIG_OPTION_USE_WARPER
-
-
-  /**************************************************************************
-   *
    * Use TrueType-like size metrics for 'light' auto-hinting.
    *
    * It is strongly recommended to avoid this option, which exists only to
@@ -962,6 +958,21 @@
 
 
   /*
+   * The TT_SUPPORT_COLRV1 macro is defined to indicate to clients that this
+   * version of FreeType has support for 'COLR' v1 API.  This definition is
+   * useful to FreeType clients that want to build in support for 'COLR' v1
+   * depending on a tip-of-tree checkout before it is officially released in
+   * FreeType, and while the feature cannot yet be tested against using
+   * version macros.  Don't change this macro.  This may be removed once the
+   * feature is in a FreeType release version and version macros can be used
+   * to test for availability.
+   */
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+#define  TT_SUPPORT_COLRV1
+#endif
+
+
+  /*
    * Check CFF darkening parameters.  The checks are the same as in function
    * `cff_property_set` in file `cffdrivr.c`.
    */
diff --git a/docs/CHANGES b/docs/CHANGES
index 3bd5291..5eb8cdb 100644
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -1,4 +1,154 @@
-CHANGES BETWEEN 2.10.3 and 2.10.4
+CHANGES BETWEEN 2.11.0 and 2.11.1
+
+  I. IMPORTANT CHANGES
+
+    - Some  fields  in  the  `CID_FaceDictRec`, `CID_FaceInfoRec`, and
+      `FT_Data` structures  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. MISCELLANEOUS
+
+    - Cmake support  has been  further improved.   To do  that various
+      backward-incompatible  changes were  necessary; please  see file
+      `CMakeLists.txt` for more details.
+
+    - Since version  2.11.0, a  C99 compiler  is necessary  to compile
+      FreeType.
+
+    - The experimental  'COLR' v1 API  has been updated to  the latest
+      OpenType standard 1.9.
+
+    - The `apinames` tool got a new  option `-wV` to output an OpenVMS
+      Linker Option File.
+
+    - VMS support was updated.
+
+    - MS Visual Studio support was added to build the demo programs.
+
+
+======================================================================
+
+CHANGES BETWEEN 2.10.4 and 2.11.0
+
+  I. IMPORTANT CHANGES
+
+  - A  new rendering  module has  been  added to  create 8-bit  Signed
+    Distance Field (SDF)  bitmaps for both outline  and bitmap glyphs.
+    The new  rendering mode is called  `FT_RENDER_MODE_SDF`, the pixel
+    mode is  `FT_PIXEL_MODE_GRAY8`, and the corresponding  raster flag
+    is `FT_RASTER_FLAG_SDF`.
+
+    This work was Anuj Verma's GSoC 2020 project.
+
+  - A new, experimental API is  now available for surfacing properties
+    of 'COLR' v1  color fonts (as the name says,  this is an extension
+    to  the  'COLR' table  for  outline  color  fonts using  the  SFNT
+    container  format).   'COLR'  v1  fonts are  a  recently  proposed
+    addition to OFF and OpenType; specification work currently happens
+    in
+
+      https://github.com/googlefonts/colr-gradients-spec/
+
+    'COLR'  v1  is  expected  to   be  merged  to  OpenType;  the  ISO
+    standardisation process  for adding 'COLR'  v1 as an  amendment to
+    OFF is underway.
+
+    Functions similar  to the  already existing  'COLR' API  have been
+    added to access the corresponding data.
+
+      FT_Get_Color_Glyph_Paint
+        Retrieve the root paint for a given glyph ID.
+
+      FT_Get_Paint_Layers
+        Access the layers of a `PaintColrLayers` table.
+
+      FT_Get_Colorline_Stops
+        Retrieve the  'color stops' on a  color line.  As an  input, a
+        color stop iterator gets used, which in turn is retrieved from
+        a paint.
+
+      FT_Get_Paint
+        Dereference  an  `FT_OpaquePaint`   object  and  retrieve  the
+        corresponding `FT_COLR_Paint`  object, which  contains details
+        on how to draw the respective 'COLR' v1 `Paint` table.
+
+
+  II. MISCELLANEOUS
+
+  - FreeType has moved its infrastructure to
+
+      https://gitlab.freedesktop.org/freetype
+
+    A  side  effect  is  that  the git  repositories  are  now  called
+    `freetype.git` and  `freetype-demos.git`, which by  default expand
+    to the directories  `freetype` and `freetype-demos`, respectively.
+    The documentation has been updated accordingly.
+
+    FreeType's Savannah  repositories will stay; they  are now mirrors
+    of the 'freedesktop.org' repositories.
+
+  - A  new  function  `FT_Get_Transform`  returns  the  values set  by
+    `FT_Set_Transform`.
+
+  - A  new configuration  macro `FT_DEBUG_LOGGING`  is available.   It
+    provides extended debugging capabilities for FreeType, for example
+    showing a time stamp or displaying the component a tracing message
+    comes from.  See file `docs/DEBUG` for more information.
+
+    This work was Priyesh Kumar's GSoC 2020 project.
+
+  - The legacy Type 1 and CFF  engines are further demoted due to lack
+    of CFF2 charstring support.  You now need to use `FT_Property_Set`
+    to  enable  them  besides  the  `T1_CONFIG_OPTION_OLD_ENGINE`  and
+    `CFF_CONFIG_OPTION_OLD_ENGINE` options, respectively.
+
+  - The experimental 'warp' mode (AF_CONFIG_OPTION_USE_WARPER) for the
+    auto-hinter has been removed.
+
+  - The smooth rasterizer performance has been improved by >10%.  Note
+    that  due to  necessary code  changes there  might be  very subtle
+    differences  in  rendering.  They  are  not  visible by  the  eye,
+    however.
+
+  - PCF bitmap fonts compressed with LZW (these are usually files with
+    the extension `.pcf.Z`) are now handled correctly.
+
+  - Improved  Meson  build  files,  including  support  to  build  the
+    FreeType demo programs.
+
+  - A new demo program `ftsdf` is available to display Signed Distance
+    Fields of glyphs.
+
+  - The `ftlint` demo program has been  extended to do more testing of
+    its input.  In particular, it  can display horizontal and vertical
+    acutances  for quality  assessment,  together  with computing  MD5
+    checksums of rendered glyphs.
+
+    [The acutance measures  how sharply the pixel  coverage changes at
+     glyph edges.  For monochrome bitmaps,  it is always 2.0 in either
+     X or  Y direction.  For  anti-aliased bitmaps, it depends  on the
+     hinting and the shape of a glyph and might approach or even reach
+     value 2.0  for glyphs like 'I',  'L', '+', '-', or  '=', while it
+     might be lower for glyphs like 'O', 'S', or 'W'.]
+
+  - The `ttdebug`  demo program didn't show  changed point coordinates
+    (bug introduced in version 2.10.3).
+
+  - It is now possible to adjust the axis increment for variable fonts
+    in the `ftmulti` demo program.
+
+  - It is now possible to change  the hinting engine in the `ftstring`
+    demo program.
+
+  - The graphical demo programs work  better now in native color depth
+    on win32 and x11.
+
+
+======================================================================
+
+CHANGES BETWEEN 2.10.3 and 2.10.4 (2020-Oct-20)
 
   I. IMPORTANT BUG FIXES
 
@@ -13,7 +163,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.10.2 and 2.10.3
+CHANGES BETWEEN 2.10.2 and 2.10.3 (2020-Oct-10)
 
   I. IMPORTANT CHANGES
 
@@ -63,7 +213,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.10.1 and 2.10.2
+CHANGES BETWEEN 2.10.1 and 2.10.2 (2020-May-09)
 
   I. IMPORTANT CHANGES
 
@@ -100,7 +250,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.10.0 and 2.10.1
+CHANGES BETWEEN 2.10.0 and 2.10.1 (2019-Jul-01)
 
   I. IMPORTANT BUG FIXES
 
@@ -154,7 +304,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.9.1 and 2.10.0
+CHANGES BETWEEN 2.9.1 and 2.10.0 (2019-Mar-15)
 
   I. IMPORTANT CHANGES
 
@@ -280,7 +430,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.9 and 2.9.1
+CHANGES BETWEEN 2.9 and 2.9.1 (2019-May-01)
 
   I. IMPORTANT BUG FIXES
 
@@ -328,7 +478,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.8.1 and 2.9
+CHANGES BETWEEN 2.8.1 and 2.9 (2018-Jan-08)
 
   I. IMPORTANT BUG FIXES
 
@@ -418,7 +568,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.8 and 2.8.1
+CHANGES BETWEEN 2.8 and 2.8.1 (2017-Sep-16)
 
   I. IMPORTANT BUG FIXES
 
@@ -501,7 +651,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.7.1 and 2.8
+CHANGES BETWEEN 2.7.1 and 2.8 (2017-May-13)
 
   I. IMPORTANT CHANGES
 
@@ -622,7 +772,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.7 and 2.7.1
+CHANGES BETWEEN 2.7 and 2.7.1 (2016-Dec-30)
 
   I. IMPORTANT CHANGES
 
@@ -699,7 +849,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.6.5 and 2.7
+CHANGES BETWEEN 2.6.5 and 2.7 (2016-Sep-08)
 
   I. IMPORTANT CHANGES
 
@@ -763,7 +913,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.6.4 and 2.6.5
+CHANGES BETWEEN 2.6.4 and 2.6.5 (2016-Jul-12)
 
   I. IMPORTANT BUG FIXES
 
@@ -783,7 +933,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.6.3 and 2.6.4
+CHANGES BETWEEN 2.6.3 and 2.6.4 (2016-Jul-05)
 
   I. IMPORTANT CHANGES
 
@@ -849,7 +999,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.6.2 and 2.6.3
+CHANGES BETWEEN 2.6.2 and 2.6.3 (2016-Feb-08)
 
   I. IMPORTANT CHANGES
 
@@ -898,7 +1048,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.6.1 and 2.6.2
+CHANGES BETWEEN 2.6.1 and 2.6.2 (2015-Nov-28)
 
   I. IMPORTANT CHANGES
 
@@ -958,7 +1108,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.6 and 2.6.1
+CHANGES BETWEEN 2.6 and 2.6.1 (2015-Oct-04)
 
   I. IMPORTANT BUG FIXES
 
@@ -1039,7 +1189,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.5.5 and 2.6
+CHANGES BETWEEN 2.5.5 and 2.6 (2015-Jun-07)
 
   I. IMPORTANT CHANGES
 
@@ -1145,7 +1295,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.5.4 and 2.5.5
+CHANGES BETWEEN 2.5.4 and 2.5.5 (2014-Dec-30)
 
   I. IMPORTANT BUG FIXES
 
@@ -1155,7 +1305,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.5.3 and 2.5.4
+CHANGES BETWEEN 2.5.3 and 2.5.4 (2014-Dec-06)
 
   I. IMPORTANT BUG FIXES
 
@@ -1226,7 +1376,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.5.2 and 2.5.3
+CHANGES BETWEEN 2.5.2 and 2.5.3 (2014-Mar-06)
 
   I. IMPORTANT BUG FIXES
 
@@ -1294,7 +1444,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.5.1 and 2.5.2
+CHANGES BETWEEN 2.5.1 and 2.5.2 (2013-Dec-08)
 
   I. IMPORTANT BUG FIXES
 
@@ -1318,7 +1468,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.5 and 2.5.1
+CHANGES BETWEEN 2.5 and 2.5.1 (2013-Nov-25)
 
   I. IMPORTANT BUG FIXES
 
@@ -1422,7 +1572,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.12 and 2.5
+CHANGES BETWEEN 2.4.12 and 2.5 (2013-Jun-19)
 
   I. IMPORTANT BUG FIXES
 
@@ -1502,7 +1652,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.11 and 2.4.12
+CHANGES BETWEEN 2.4.11 and 2.4.12 (2013-May-08)
 
     - We have another CFF parsing and hinting engine!  Written by Dave
       Arnold <darnold@adobe.com>,  this work  has been  contributed by
@@ -1590,7 +1740,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.10 and 2.4.11
+CHANGES BETWEEN 2.4.10 and 2.4.11 (2012-Dec-20)
 
   I. IMPORTANT BUG FIXES
 
@@ -1650,7 +1800,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.9 and 2.4.10
+CHANGES BETWEEN 2.4.9 and 2.4.10 (2012-Jun-15)
 
   I. IMPORTANT BUG FIXES
 
@@ -1675,7 +1825,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.8 and 2.4.9
+CHANGES BETWEEN 2.4.8 and 2.4.9 (2012-Mar-08)
 
   I. IMPORTANT BUG FIXES
 
@@ -1703,7 +1853,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.7 and 2.4.8
+CHANGES BETWEEN 2.4.7 and 2.4.8 (2011-Nov-14)
 
   I. IMPORTANT BUG FIXES
 
@@ -1719,7 +1869,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.6 and 2.4.7
+CHANGES BETWEEN 2.4.6 and 2.4.7 (2011-Oct-18)
 
   I. IMPORTANT BUG FIXES
 
@@ -1736,7 +1886,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.5 and 2.4.6
+CHANGES BETWEEN 2.4.5 and 2.4.6 (2011-Jul-29)
 
   I. IMPORTANT BUG FIXES
 
@@ -1775,7 +1925,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.4 and 2.4.5
+CHANGES BETWEEN 2.4.4 and 2.4.5 (2011-Jun-25)
 
   I. IMPORTANT BUG FIXES
 
@@ -1822,7 +1972,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.3 and 2.4.4
+CHANGES BETWEEN 2.4.3 and 2.4.4 (2010-Nov-28)
 
   I. IMPORTANT BUG FIXES
 
@@ -1847,7 +1997,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.2 and 2.4.3
+CHANGES BETWEEN 2.4.2 and 2.4.3 (2010-Oct-03)
 
   I. IMPORTANT BUG FIXES
 
@@ -1866,7 +2016,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.1 and 2.4.2
+CHANGES BETWEEN 2.4.1 and 2.4.2 (2010-Aug-06)
 
   I. IMPORTANT BUG FIXES
 
@@ -1890,7 +2040,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.4.0 and 2.4.1
+CHANGES BETWEEN 2.4.0 and 2.4.1 (2010-Jul-18)
 
   I. IMPORTANT CHANGES
 
@@ -1900,7 +2050,7 @@
 
 ======================================================================
 
-CHANGES BETWEEN 2.3.12 and 2.4.0
+CHANGES BETWEEN 2.3.12 and 2.4.0 (2010-Jul-12)
 
   I. IMPORTANT CHANGES
 
@@ -5299,7 +5449,7 @@
 
 ------------------------------------------------------------------------
 
-Copyright (C) 2000-2020 by
+Copyright (C) 2000-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file  is  part  of the  FreeType  project, and may  only be  used,
diff --git a/docs/CUSTOMIZE b/docs/CUSTOMIZE
index 0f92e70..a03f9dd 100644
--- a/docs/CUSTOMIZE
+++ b/docs/CUSTOMIZE
@@ -139,7 +139,7 @@
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2003-2020 by
+Copyright (C) 2003-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/docs/DEBUG b/docs/DEBUG
index a96b5e2..4f35877 100644
--- a/docs/DEBUG
+++ b/docs/DEBUG
@@ -44,6 +44,21 @@
     When `FT2_DEBUG_MEMORY'  isn't defined  at runtime,  the debugging
     memory manager is ignored, and performance is unaffected.
 
+  FT_DEBUG_LOGGING
+
+    #define this macro for enhanced logging support; it automatically
+    sets `FT_DEBUG_LEVEL_TRACE' and `FT_DEBUG_LEVEL_ERROR'.
+
+    If  defined,  `FT_TRACE'  and  `FT_ERROR'  can  send  tracing  and
+    debugging messages to a file.  The location of the log file has to
+    be set  with the  `FT_LOGGING_FILE' environment variable  (more on
+    this later).
+
+    The main enhancements are the  possibility of logging the time and
+    the name  of the `FT_COMPONENT'  macro together with  the affected
+    `FT_TRACE' or `FT_ERROR' calls.  See below how to activate this in
+    the `FT2_DEBUG' environment variable.
+
 
 II. Debugging macros
 --------------------
@@ -150,6 +165,43 @@
     the memory and io components, which  are set to the trace levels 5
     and 4, respectively.
 
+    If `FT_DEBUG_LOGGING' is defined, two more options are available.
+
+    * -v: Print also  the name of FreeType's component  from which the
+          current log is produced, together with the tracing level.
+
+    * -t: Print also the time.
+
+    Here are some examples how the output might look like.
+
+      FT2_DEBUG="any:7 memory:5 -vt"
+
+        => [20:32:02:44969 ttload:2]    table directory loaded
+
+      FT2_DEBUG="any:7 memory:5 -t"
+
+        => [20:32:02:44969]    table directory loaded
+
+      FT2_DEBUG="any:7 memory:5 -v"
+
+        => [ttload:2]    table directory loaded
+
+
+  FT_LOGGING_FILE
+
+    This  variable  is  only  used  if  FreeType  is  built  with  the
+    `FT_DEBUG_LOGGING'  macro defined.   It contains  the path  to the
+    file where the user wants to put  his log file.  If it is not set,
+    FreeType uses stderr.
+
+    Examples:
+
+      On UNIX-like systems with bash:
+      export FT_LOGGING_FILE="/tmp/freetype2.log"
+
+      On Windows:
+      set FT_LOGGING_FILE=C:\Users\AppData\Local\Temp\freetype2.log
+
 
   FT2_DEBUG_MEMORY
 
@@ -201,9 +253,51 @@
     If it  is undefined,  or if  its value  is not  strictly positive,
     freed blocks are released at runtime.
 
+
+IV. Additional Capabilities with `FT_DEBUG_LOGGING'
+---------------------------------------------------
+
+If `FT_DEBUG_LOGGING' is  defined, four APIs are  available to provide
+additional debugging support.  Use
+
+  #include <freetype/ftlogging.h>
+
+to access them.
+
+  FT_Trace_Set_Level( const char*  level )
+
+    By  default,  FreeType   uses  the  tracing  levels   set  in  the
+    `FT2_DEBUG' environment  variable.  Use this function  to override
+    the value with `level'.  Use value `NULL' to disable tracing.
+
+  FT_Trace_Set_Default_Level():
+
+    Reset the tracing levels to the default value, i.e., the value of
+    the `FT2_DEBUG' environment variable or no tracing if not set.
+
+  FT_Set_Log_Handler( ft_custom_log_handler  handler ):
+
+    Use `handler' as a custom handler for formatting tracing and error
+    messages.  The  `ft_custom_log_handler' typedef has  the following
+    prototype.
+
+      void
+      (*ft_custom_log_handler)( const char*  ft_component,
+                                const char*  fmt,
+                                va_list      args );
+
+   `ft_component' is the current component like `ttload', `fmt' is the
+   first argument  of `FT_TRACE' or  `FT_ERROR', and `args'  holds the
+   remaining arguments.
+
+  FT_Set_Default_Log_Handler():
+
+    Reset the log handler to the default version.
+
+
 ------------------------------------------------------------------------
 
-Copyright (C) 2002-2020 by
+Copyright (C) 2002-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part  of the  FreeType  project, and  may  only be  used,
diff --git a/docs/DOCGUIDE b/docs/DOCGUIDE
index 89617b4..499608d 100644
--- a/docs/DOCGUIDE
+++ b/docs/DOCGUIDE
@@ -154,7 +154,7 @@
 
 Note that there may be cases where having two asterisks or underscores
 in a line may lead to text being picked up as italics or bold.
-Although unintentional, this is correct markdown behavior. 
+Although unintentional, this is correct markdown behavior.
 
 For inline code, wrap the sequence with backticks (see below).  This
 renders symbols correctly without modifications.  If a symbol is
@@ -201,7 +201,7 @@
 
     @description:
       While FreeType's CFF driver doesn't expose API functions by
-      itself, it is possible to control its behaviour with 
+      itself, it is possible to control its behaviour with
       @FT_Property_Set and @FT_Property_Get.
 
 If a field in the `values` table of another sub-section is linked, the
@@ -285,7 +285,7 @@
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2018-2020 by
+Copyright (C) 2018-2021 by
 Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/docs/INSTALL b/docs/INSTALL
index 814fc7b..be56e02 100644
--- a/docs/INSTALL
+++ b/docs/INSTALL
@@ -4,65 +4,89 @@
 overview of the documentation available:
 
 
-I. Normal installation and upgrades
-===================================
+I. Prerequisites and dependencies
+=================================
 
-  1. Unix Systems (including Mac OS X, Cygwin, and MSys on Windows)
+  FreeType is a low level C library  that only depends on the standard
+  C library with very few platform-dependent optimizations utilized at
+  build time.  Any  C99-compliant compiler  should be able  to compile
+  FreeType.  System libraries,  such as  zlib,  Gzip,  bzip2,  Brotli,
+  and libpng,  might  be  used  to handle  compressed fonts  or decode
+  embedded PNG glyphs.
 
-    Please read `INSTALL.UNIX' to install or upgrade FreeType  2 on  a
+  FreeType  auto-configuration scripts  should be  able to detect  the
+  prerequisites if the necessary headers are available  at the default
+  locations.  Otherwise,  modify  `include/freetype/config/ftoption.h`
+  to control how the FreeType library gets built.  Normally, you don't
+  need to change anything.
+
+  Applications have very limited control over FreeType's behaviour  at
+  run-time;  look at the documentation of function `FT_Property_Set`.
+
+
+II. Normal installation and upgrades
+====================================
+
+  1. Unix and Unix-like systems
+
+    This also includes MacOS, Cygwin, MinGW + MSYS, Mingw-w64 + MSYS2,
+    and possibly other, similar environments.
+
+    Please read `INSTALL.UNIX` to install or upgrade FreeType  2 on  a
     Unix system.   Note  that  you  *need*  GNU  Make   for  automatic
     compilation,  since other make tools won't work (this includes BSD
     Make).
 
     GNU Make VERSION 3.81 OR NEWER IS NEEDED!
 
-    [For `cmake' see below.]
+
+  2. Other systems using GNU Make
+
+    On some  non-Unix platforms, it  is possible to build  the library
+    using only  the GNU Make utility.   Note that *NO OTHER  MAKE TOOL
+    WILL  WORK*[1]!   This  methods   supports  several  compilers  on
+    Windows, OS/2, and BeOS,  including MinGW* (without MSYS*), Visual
+    C++, Borland C++, and more.
+
+    Instructions are provided in the file `INSTALL.GNU`.
 
 
-  2. On VMS with the `mms' build tool
+  3. Other build tools and platforms.
 
-    See `INSTALL.VMS' for installation instructions on this platform.
+    A few other tools  can be used  to build FreeType.  You  can  find
+    the  corresponding instruction files  in  the FreeType root folder
+    or the builds/ sub-folder.
 
-
-  3. Other systems using GNU Make
-
-    On non-Unix platforms,  it is possible to build  the library using
-    GNU Make  utility.  Note that  *NO OTHER MAKE TOOL  WILL WORK*[1]!
-    This  methods supports  several  compilers on  Windows, OS/2,  and
-    BeOS, including MinGW, Visual C++, Borland C++, and more.
-
-    Instructions are provided in the file `INSTALL.GNU'.
+      CMake   :: see `CMakeLists.txt` for more information
+      Meson   :: see `meson.build` for more information
+      MSBuild :: see `builds/windows/vc2010/freetype.vcxproj`
+      MMS     :: see `vms_make.com` and `docs/INSTALL.VMS`
 
 
   4. With an IDE Project File (e.g., for Visual Studio or CodeWarrior)
 
-    We provide a  small number of `project files'  for various IDEs to
+    We provide a  small number of 'project files'  for various IDEs to
     automatically build  the library as  well.  Note that  these files
-    are  not supported  and only  sporadically maintained  by FreeType
-    developers, so don't expect them to work in each release.
+    are not actively supported by FreeType developers,  they can break
+    or become obsolete.
 
-    To find them, have a  look at the content of the `builds/<system>'
+    To find them, have a  look at the content of the `builds/<system>`
     directory, where <system> stands for your OS or environment.
 
 
-  5. Using cmake
-
-    See the top-level `CMakeLists.txt' file for more information.
-
-
-  6. From you own IDE, or own Makefiles
+  5. From you own IDE, or own Makefiles
 
     If  you  want  to  create   your  own  project  file,  follow  the
-    instructions   given  in  the   `INSTALL.ANY'  document   of  this
+    instructions   given  in  the   `INSTALL.ANY`  document   of  this
     directory.
 
 
-II. Custom builds of the library
-================================
+III. Custom builds of the library
+=================================
 
   Customizing the compilation  of FreeType is easy, and  allows you to
   select only the components of  the font engine that you really need.
-  For more details read the file `CUSTOMIZE'.
+  For more details read the file `CUSTOMIZE`.
 
 
 ----------------------------------------------------------------------
@@ -73,11 +97,11 @@
       https://makepp.sourceforge.net
 
     for more information;  you need version 2.0 or newer, and you must
-    pass option `--norc-substitution'.
+    pass option `--norc-substitution`.
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2000-2020 by
+Copyright (C) 2000-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/docs/INSTALL.ANY b/docs/INSTALL.ANY
index 879dddb..3136613 100644
--- a/docs/INSTALL.ANY
+++ b/docs/INSTALL.ANY
@@ -10,7 +10,7 @@
 
   * If you use macro names  for FreeType header files (while mandatory
     in earlier versions,  this is now optional  since FreeType version
-    2.10.3) it  is necessary to disable pre-compiled headers.  This is
+    2.6.1) it  is necessary to  disable pre-compiled headers.  This is
     very important for Visual C++, because lines like
 
       #include FT_FREETYPE_H
@@ -21,9 +21,9 @@
   * You need to add the directory `include' to your  include path when
     compiling the library.
 
-  * FreeType 2 is made of  several components; each of them is located
-    in    a   subdirectory    of   `freetype2/src'.     For   example,
-    `freetype2/src/truetype/' contains the TrueType font driver.
+  * FreeType 2 is made of several  components; each of them is located
+    in    a   subdirectory    of    `freetype/src'.    For    example,
+    `freetype/src/truetype/' contains the TrueType font driver.
 
   * DO NOT COMPILE ALL C FILES!  Rather, compile the following ones.
 
@@ -73,6 +73,7 @@
        formats)
 
       src/raster/raster.c     -- monochrome rasterizer
+      src/sdf/sdf.c           -- Signed Distance Field driver
       src/smooth/smooth.c     -- anti-aliasing rasterizer
 
     -- auxiliary modules (optional)
@@ -125,9 +126,9 @@
 
   1. Copy all files in current directory
 
-      cp freetype2/src/base/*.[hc] .
-      cp freetype2/src/raster1/*.[hc] .
-      cp freetype2/src/smooth/*.[hc] .
+      cp freetype/src/base/*.[hc] .
+      cp freetype/src/raster1/*.[hc] .
+      cp freetype/src/smooth/*.[hc] .
       etc.
 
   2. Compile sources
@@ -143,7 +144,7 @@
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2003-2020 by
+Copyright (C) 2003-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/docs/INSTALL.CROSS b/docs/INSTALL.CROSS
index 8511805..f57b14c 100644
--- a/docs/INSTALL.CROSS
+++ b/docs/INSTALL.CROSS
@@ -163,7 +163,7 @@
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2006-2020 by
+Copyright (C) 2006-2021 by
 suzuki toshiya, David Turner, Robert Wilhelm, and Werner Lemberg.
 
 
diff --git a/docs/INSTALL.GNU b/docs/INSTALL.GNU
index 8fdbb82..a04e6fc 100644
--- a/docs/INSTALL.GNU
+++ b/docs/INSTALL.GNU
@@ -11,9 +11,6 @@
   1. Install GNU Make
   -------------------
 
-    Because  GNU Make  is  the  only Make  tool  supported to  compile
-    FreeType 2, you should install it on your machine.
-
     The FreeType 2 build system relies on many features special to GNU
     Make.
 
@@ -100,6 +97,28 @@
     step 5.
 
 
+  3a. Use clang instead of gcc
+  ----------------------------
+
+    The `clang'  compiler can  use FreeType's setup  for `gcc';  it is
+    sufficient to set the `CC' variable, for example
+
+      make CC=clang
+
+
+  3b. Compiling with a C++ compiler
+  ---------------------------------
+
+    FreeType can be built with a C++ compiler, for example
+
+      make CC="g++"
+
+    If `clang++' should  be used it is necessary to  also override the
+    `ANSIFLAGS' variable:
+
+      make CC="clang++" ANSIFLAGS=""
+
+
   4. Configure the build system for an unknown platform/compiler
   --------------------------------------------------------------
 
@@ -133,7 +152,8 @@
 
     To  launch  the build,  simply  invoke  GNU  Make again:  The  top
     Makefile will detect the configuration file and run the build with
-    it.
+    it.  If you have used variables in  step 3, you must use  the same
+    variables here, too.
 
 
   Final note
@@ -148,7 +168,7 @@
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2003-2020 by
+Copyright (C) 2003-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/docs/INSTALL.UNIX b/docs/INSTALL.UNIX
index f8d220a..ff4eabe 100644
--- a/docs/INSTALL.UNIX
+++ b/docs/INSTALL.UNIX
@@ -44,14 +44,23 @@
 
       sh autogen.sh
 
-    In case of problems, you  may need to install or upgrade Automake,
-    Autoconf or  Libtool.  See  README.git in the  top-level directory
+    In case of problems, you may  need to install or upgrade Automake,
+    Autoconf or Libtool.  See  `README.git' in the top-level directory
     for more information.
 
 
   3. Build and install the library
   --------------------------------
 
+    Say
+
+      ./configure --help
+
+    to see  the list of  possible configuration options  and important
+    environment  variables.  The ./configure script  will detect  some
+    prerequisite  system  libraries  (libpng, brotli, etc.)  if  their
+    headers are available at the default locations.
+
     The following  should work  on all Unix  systems where  the `make'
     command invokes GNU Make:
 
@@ -75,6 +84,18 @@
     If  this still doesn't  work, there  must be  a problem  with your
     system (e.g., you are using a very old version of GNU Make).
 
+    For library identification, FreeType's `configure' script uses the
+    `pkg-config' interface: Assuming it  needs library `foo', it calls
+    the  `pkg-config' program  to find  information on  library `foo',
+    which in turn  looks for a `foo.pc' file installed  at the system.
+    Some platforms,  however, don't come with  `pkg-support'; you then
+    have  to  use environment  variables  as  described by  `configure
+    --help'.  Example:
+
+      LIBPNG_CFLAGS="-I/path/to/libpng/include/directory" \
+      LIBPNG_LIBS="-L/path/to/libpng/lib/directory" \
+      configure ...
+
     It  is possible  to  compile FreeType  in  a different  directory.
     Assuming the FreeType source  files in directory `/src/freetype' a
     compilation in directory `foo' works as follows:
@@ -105,7 +126,7 @@
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2003-2020 by
+Copyright (C) 2003-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/docs/INSTALL.VMS b/docs/INSTALL.VMS
index e1817ec..f0dec3b 100644
--- a/docs/INSTALL.VMS
+++ b/docs/INSTALL.VMS
@@ -49,7 +49,7 @@
 
 ------------------------------------------------------------------------
 
-Copyright (C) 2000-2020 by
+Copyright (C) 2000-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file  is  part  of the  FreeType  project, and may  only be  used,
diff --git a/docs/LICENSE.TXT b/docs/LICENSE.TXT
deleted file mode 100644
index af5a1c5..0000000
--- a/docs/LICENSE.TXT
+++ /dev/null
@@ -1,39 +0,0 @@
-
-The  FreeType 2  font  engine is  copyrighted  work and  cannot be  used
-legally  without a  software license.   In  order to  make this  project
-usable  to a vast  majority of  developers, we  distribute it  under two
-mutually exclusive open-source licenses.
-
-This means  that *you* must choose  *one* of the  two licenses described
-below, then obey  all its terms and conditions when  using FreeType 2 in
-any of your projects or products.
-
-  - The FreeType License, found in  the file `FTL.TXT', which is similar
-    to the original BSD license *with* an advertising clause that forces
-    you  to  explicitly cite  the  FreeType  project  in your  product's
-    documentation.  All  details are in the license  file.  This license
-    is  suited  to products  which  don't  use  the GNU  General  Public
-    License.
-
-    Note that  this license  is  compatible  to the  GNU General  Public
-    License version 3, but not version 2.
-
-  - The GNU General Public License version 2, found in  `GPLv2.TXT' (any
-    later version can be used  also), for programs which already use the
-    GPL.  Note  that the  FTL is  incompatible  with  GPLv2 due  to  its
-    advertisement clause.
-
-The contributed BDF and PCF drivers  come with a license similar to that
-of the X Window System.  It is compatible to the above two licenses (see
-file src/bdf/README and  src/pcf/README).  The same holds  for the files
-`fthash.c' and  `fthash.h'; their  code was  part of  the BDF  driver in
-earlier FreeType versions.
-
-The gzip module uses the zlib license (see src/gzip/zlib.h) which too is
-compatible to the above two licenses.
-
-The MD5 checksum support (only used for debugging in development builds)
-is in the public domain.
-
-
---- end of LICENSE.TXT ---
diff --git a/docs/TODO b/docs/TODO
index 8b27e26..ecc1efd 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -27,7 +27,7 @@
 
 ------------------------------------------------------------------------
 
-Copyright (C) 2001-2020 by
+Copyright (C) 2001-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file  is  part  of the  FreeType  project, and may  only be  used,
diff --git a/docs/VERSIONS.TXT b/docs/VERSIONS.TXT
index 4e281a7..afe50a4 100644
--- a/docs/VERSIONS.TXT
+++ b/docs/VERSIONS.TXT
@@ -60,6 +60,8 @@
 
     release     libtool     so
   -------------------------------
+     2.11.1     24.1.18   6.18.1
+     2.11.0     24.0.18   6.18.0
      2.10.4     23.4.17   6.17.4
      2.10.3     23.3.17   6.17.3
      2.10.2     23.2.17   6.17.2
@@ -117,7 +119,7 @@
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2002-2020 by
+Copyright (C) 2002-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/docs/formats.txt b/docs/formats.txt
index e640fab..1c25ac0 100644
--- a/docs/formats.txt
+++ b/docs/formats.txt
@@ -79,8 +79,7 @@
 
   SFNT    PS      TYPE_1  ---        type1    Type 1 GX Font Format
                                               (for the Mac) [3]
-  SFNT    PS      TYPE_1  CID        cid      5180.sfnt.pdf (for the Mac)
-                                              [3]
+  SFNT    PS      TYPE_1  CID        cid      5180.sfnt.pdf (for the Mac) [3]
   SFNT    PS      CFF     ---        cff      OT spec, 5176.CFF.pdf
                                               (`OTTO' format)
   SFNT    PS      CFF     CID        cff      OT spec, 5176.CFF.pdf
@@ -97,6 +96,12 @@
                                               (`?var' + `?VAR' tables)
 
 
+  WOFF    ---     ---     ---        cff,     Compressed SFNT, ver. 1.0 [6]
+                                     truetype
+  WOFF2   ---     ---     ---        cff,     Compressed SFNT, ver. 2.0 [6]
+                                     truetype
+
+
   ---     PS      TYPE_1  ---        type1    T1_SPEC.pdf
                                               (PFA, Type 1 font resource)
   PFB     PS      TYPE_1  ---        type1    T1_SPEC.pdf,
@@ -185,13 +190,17 @@
 
       https://fontforge.github.io/pcf-format.html
 
-[5] This is from MS Windows 3; see Microsoft's Knowledge Base article at
+[5] This is from MS Windows 3;  see Microsoft's Knowledge Base article
+    at
 
       https://support.microsoft.com/kb/65123
 
+[6] Supported  font  formats  are   TrueType  and  OpenType  fonts  as
+    defined in the OpenType specification 1.6 and newer.
+
 ------------------------------------------------------------------------
 
-Copyright (C) 2004-2020 by
+Copyright (C) 2004-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part  of the  FreeType  project, and  may  only be  used,
diff --git a/docs/freetype-config.1 b/docs/freetype-config.1
index 7dea66a..8145c9f 100644
--- a/docs/freetype-config.1
+++ b/docs/freetype-config.1
@@ -1,4 +1,4 @@
-.TH FREETYPE-CONFIG 1 "October 2020" "FreeType 2.10.4"
+.TH FREETYPE-CONFIG 1 "December 2021" "FreeType 2.11.1"
 .
 .
 .SH NAME
diff --git a/docs/markdown/stylesheets/extra.css b/docs/markdown/stylesheets/extra.css
index a99e77f..5d999ed 100644
--- a/docs/markdown/stylesheets/extra.css
+++ b/docs/markdown/stylesheets/extra.css
@@ -1,13 +1,7 @@
 /* Body and page */
-.wy-nav-content {
-    max-width: 90%;
-}
 .md-grid {
     max-width: 90%;
 }
-.md-sidebar--secondary {
-    margin-left: 90%;
-}
 p {
     text-align: justify;
 }
diff --git a/ChangeLog.20 b/docs/oldlogs/ChangeLog.20
similarity index 99%
rename from ChangeLog.20
rename to docs/oldlogs/ChangeLog.20
index 9f81914..15ae8fe 100644
--- a/ChangeLog.20
+++ b/docs/oldlogs/ChangeLog.20
@@ -2597,7 +2597,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2000-2020 by
+Copyright (C) 2000-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.21 b/docs/oldlogs/ChangeLog.21
similarity index 99%
rename from ChangeLog.21
rename to docs/oldlogs/ChangeLog.21
index f36f5b7..71f9f00 100644
--- a/ChangeLog.21
+++ b/docs/oldlogs/ChangeLog.21
@@ -9422,7 +9422,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2002-2020 by
+Copyright (C) 2002-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog b/docs/oldlogs/ChangeLog.210
similarity index 62%
rename from ChangeLog
rename to docs/oldlogs/ChangeLog.210
index 42f7c34..eea4d27 100644
--- a/ChangeLog
+++ b/docs/oldlogs/ChangeLog.210
@@ -1,3 +1,2752 @@
+2021-07-18  Werner Lemberg  <wl@gnu.org>
+
+	* Version 2.11.0 released.
+	==========================
+
+
+	Tag sources with `VER-2-11-0'.
+
+	* docs/VERSION.TXT: Add entry for version 2.11.0.
+	* docs/CHANGES: Updated.
+
+	* README, src/base/ftver.rc, builds/windows/vc2010/index.html,
+	builds/windows/visualc/index.html,
+	builds/windows/visualce/index.html,
+	builds/wince/vc2005-ce/index.html,
+	builds/wince/vc2008-ce/index.html, docs/freetype-config.1:
+	s/2.10.4/2.11.0/, s/2104/2110/.
+
+	* include/freetype/freetype.h (FREETYPE_MINOR): Set to 11.
+	(FREETYPE_PATCH): Set to 0.
+
+	* builds/unix/configure.raw (version_info): Set to 24:0:18.
+	* CMakeLists.txt (VERSION_MINOR): Set to 11.
+	(VERSION_PATCH): Set to 0.
+
+	* builds/toplevel.mk (dist): Ignore more git-related files.
+
+2021-07-17  David Turner  <david@freetype.org>
+
+	* src/smooth/ftgrays.c: Fix compilation if `FT_LONG64` is undefined.
+
+	The code assumed that if `__SSE2__` is defined, then 64-bit integer
+	types are available.  This is not the case apparently for certain
+	multilib compiler targets like 'x86_32.x86' used by Gentoo.
+
+	This patch fixes the issue by disabling the special code path when
+	64-bit integer types are not available.
+
+	Fixes #1071.
+
+2021-07-16  Alex Richardson  <Alexander.Richardson@cl.cam.ac.uk>
+
+	[tests] Allow arbitrary build directories.
+
+	* tests/issue-1063/main.c (main): I am building with a build
+	directory that is not directly inside the source tree, so the path
+	`../tests/data/As.I.Lay.Dying.ttf` does not resolve to the test
+	input file.  This change passes the test data directory as an
+	environment variable to allow arbitrary build directories.
+
+	* tests/meson.build: Updated.
+
+2021-07-16  Alex Richardson  <Alexander.Richardson@cl.cam.ac.uk>
+
+	* tests/issue-1063/main.c (main): Fix uninitialized variable.
+
+	I tried running `meson test` but the test just crashed and gdb
+	reported that the face argument to `FT_Get_Char_Index` was nonsense.
+	With this change the test prints 'Could not open file: ' as it
+	should.
+
+2021-07-16  Werner Lemberg  <wl@gnu.org>
+
+	[smooth] Minor fixes.
+
+	* src/smooth/ftgrays.c (gray_render_conic): Move variable and
+	structure declarations to beginning of function.  Inspite of C99
+	compliance we still do this for the sake of backward compatibility.
+	This also avoids a shadowing declaration of `count`.
+	(gray_convert_glyph_inner): Fix typo.
+
+2021-07-15  Ben Wagner  <bungeman@chromium.org>
+
+	* src/smooth/ftgrays.c: Guard inclusion of `emmintrin.h`.
+
+	Guard inclusion of `emmintrin.h` with `#ifdef __SSE2__`.  The gcc
+	version of this header, `xmmintrin.h`, and `mmintrin.h` check that
+	the appropriate defines are set before defining anything (are
+	internally guarded).  However, the clang versions of these includes
+	are not internally guarded.  As a result of this, externally guard
+	the inclusion of these headers.
+
+2021-07-15  David Turner  <david@freetype.org>
+
+	[smooth] Implement Bézier quadratic arc flattening with DDA.
+
+	Benchmarking shows that this provides a very slighty performance
+	boost when rendering fonts with lots of quadratic Bézier arcs,
+	compared to the recursive arc splitting, but only when SSE2 is
+	available, or on 64-bit CPUs.
+
+	On a 2017 Core i5-7300U CPU on Linux/x86_64:
+
+	  ftbench -p -s10 -t5 -cb DroidSansFallbackFull.ttf
+
+	  Before: 4.033 us/op  (best of 5 runs for all numbers)
+	  After:  3.876 us/op
+
+	  ftbench -p -s60 -t5 -cb DroidSansFallbackFull.ttf
+
+	  Before: 13.467 us/op
+	  After:  13.385 us/op
+
+	* src/smooth/ftgrays.c (gray_render_conic): New implementation
+	based on DDA and optionally SSE2.
+
+2021-07-15  David Turner  <david@freetype.org>
+
+	[smooth] Minor speedup to smooth rasterizer.
+
+	This speeds up the smooth rasterizer by avoiding conditional
+	branches in the hot path.
+
+	- Define a fixed 'null cell', which will be pointed to whenever the
+	  current cell is outside of the current target region.  This avoids
+	  a `ras.cell != NULL` check in the `FT_INTEGRATE` macro.
+
+	- Also use the null cell as a sentinel at the end of all `ycells`
+	  linked-lists, by setting its x coordinate to `INT_MAX`.  This
+	  avoids a `if (!cell)` check in `gray_set_cell` as well.
+
+	- Slightly change the worker struct fields to perform a little less
+	  operations during rendering.
+
+	Example results (on a 2013 Corei5-3337U CPU)
+
+	  out/ftbench -p -s10 -t5 -bc DroidSansFallbackFull.ttf
+
+	  Before: 5.472 us/op
+	  After:  5.275 us/op
+
+	  out/ftbench -p -s60 -t5 -bc DroidSansFallbackFull.ttf
+
+	  Before: 17.988 us/op
+	  After:  17.389 us/op
+
+	* src/smooth/ftgrays.c (grat_TWorker): Replace `num_cells` field with
+	`cell_free` and `cell_limit`.
+	(NULL_CELL_PTR, CELL_MAX_X_VALUE, CELL_IS_NULL): New macros.
+	(gray_dump_cells, gray_set_cell, gray_sweep, gray_sweep_direct,
+	gray_convert_glyph_inner, gray_convert_glyph): Updated.
+
+2021-07-15  David Turner  <david@freetype.org>
+
+	[tests] Rewrite download script in Python3.
+
+	This commit replaces the bash script with a Python script that does
+	the same work, plus avoiding to download anything if the files are
+	already installed with the right content.
+
+	We now use the first 8 bytes of each file's sha256 hash for the
+	digest.
+
+	* tests/scripts/download-test-fonts.sh: Removed.
+	* tests/scripts/download-test-fonts.py: New script.
+	* tests/README.md: Updated.
+
+2021-07-15  Alex Richardson  <Alexander.Richardson@cl.cam.ac.uk>
+
+	Support architectures where `long` is smaller than pointers.
+
+	I am currently trying to compile FreeType for CHERI-extended ISAs
+	(CHERI-RISC-V and Arm's Morello), but I am getting compiler warnings
+	from the `FT_UINT_TO_POINTER` macro.  When compiling with the CHERI
+	Clang compiler, not using `uinptr_t` for casts between integers an
+	pointers results in the following `-Werror` build failures:
+
+	```
+	In file included from .../src/truetype/truetype.c:22:
+	  .../src/truetype/ttgload.c:1925:22: error:
+	    cast from provenance-free integer type to pointer type will
+	    give pointer that can not be dereferenced
+	    [-Werror,-Wcheri-capability-misuse]
+	  node->data = FT_UINT_TO_POINTER( glyph_index );
+	               ^
+	  .../include/freetype/internal/compiler-macros.h:79:34: note:
+	    expanded from macro 'FT_UINT_TO_POINTER'
+	```
+
+	* include/freetype/internal/compiler-macros.h (FT_UINT_TO_POINTER):
+	The ISO C standard compliant fix for this would be to use
+	`uintptr_t` from `stdint.h`, but I am not sure if this is supported
+	by the minimum compiler version.  Therefore, use the
+	compiler-defined `__UINTPTR_TYPE__` macro (supported in GCC 4.6+ and
+	Clang since about 3.0) before checking for `_WIN64` and falling back
+	to `unsigned long`.
+
+2021-07-13  Oleg Oshmyan  <chortos@inbox.lv>
+
+	[base] Fix `FT_Open_Face`'s handling of user-supplied streams.
+
+	This was already true (though undocumented) most of the time, but
+	not if `FT_NEW` inside `FT_Stream_New` failed or if the
+	`FT_OPEN_XXX` flags were bad.
+
+	Normally, `FT_Open_Face` calls `FT_Stream_New`, which returns the
+	user-supplied stream unchanged, and in case of any subsequent error
+	in `FT_Open_Face`, the stream is closed via `FT_Stream_Free`.
+
+	Up to now, however, `FT_Stream_New` allocates a new stream even if
+	it is already given one by the user.  If this allocation fails, the
+	user-supplied stream is not returned to `FT_Open_Face` and never
+	closed.  Moreover, the user cannot detect this situation: all they
+	see is that `FT_Open_Face` returns `FT_Err_Out_Of_Memory`, but that
+	can also happen after a different allocation fails within the main
+	body of `FT_Open_Face`, when the user's stream has already been
+	closed by `FT_Open_Face`.  It is plausible that the user stream's
+	`close` method frees memory allocated for the stream object itself,
+	so the user cannot defensively free it upon `FT_Open_Face` failure
+	lest it ends up doubly freed.  All in all, this ends up leaking the
+	memory/resources used by user's stream.
+
+	Furthermore, `FT_Stream_New` simply returns an error if the
+	`FT_OPEN_XXX` flags are unsupported, which can mean either an
+	invalid combination of flags or a perfectly innocent
+	`FT_OPEN_STREAM` on a FreeType build that lacks stream support.
+	With this patch, the user-supplied stream is closed even in these
+	cases, so the user can be sure that if `FT_Open_Face` failed, the
+	stream is definitely closed.
+
+	* src/base/ftobjs.c (FT_Stream_New): Don't allocate a buffer
+	unnecessarily.
+	Move error-handling code to make the control flow more obvious.
+	Close user-supplied stream if the flags are unsupported.
+	`FT_Stream_Open` always sets `pathname.pointer`, so remove the
+	redundant (re)assignment.  None of the `FT_Stream_Open...` functions
+	uses `stream->memory`, so keep just one assignment at the end,
+	shared among all possible control flow paths.
+	('Unsupported flags' that may need a stream closure can be either an
+	invalid combination of multiple `FT_OPEN_XXX` mode flags or a clean
+	`FT_OPEN_STREAM` flag on a FreeType build that lacks stream
+	support.)
+
+2021-07-13  Oleg Oshmyan  <chortos@inbox.lv>
+
+	[base] Reject combinations of incompatible `FT_OPEN_XXX` flags.
+
+	The three modes are mutually exclusive, and the documentation of the
+	`FT_OPEN_XXX` constants notes this.  However, there was no check to
+	validate this in the code, and the documentation on `FT_Open_Args`
+	claimed that the corresponding bits were checked in a well-defined
+	order, implying it was valid (if useless) to specify more than one.
+	Ironically, this documented order did not agree with the actual
+	code, so it could not be relied upon; hopefully, nobody did this and
+	nobody will be hurt by the new validation.
+
+	Even if multiple mode bits were allowed, they could cause memory
+	leaks: if both `FT_OPEN_STREAM` and `stream` are set along with
+	either `FT_OPEN_MEMORY` or `FT_OPEN_PATHNAME`, then `FT_Stream_New`
+	allocated a new stream but `FT_Open_Face` marked it as an 'external'
+	stream, so the stream object was never released.
+
+	* src/base/ftobjs.c (FT_Stream_New): Reject incompatible
+	`FT_OPEN_XXX` flags.
+
+2021-07-12  Alex Richardson  <Alexander.Richardson@cl.cam.ac.uk>
+
+	* meson.build: Fix build for other UNIX systems (e.g., FreeBSD).
+
+	Without this change the build of `unix/ftsystem.c` fails because the
+	`ftconfig.h` header that defines macros such as `HAVE_UNISTD_H` and
+	`HAVE_FCNTL_H` is only being generated for Linux, macOS, and Cygwin
+	systems:
+
+	```
+	.../builds/unix/ftsystem.c:258:32: error:
+	    use of undeclared identifier 'O_RDONLY'
+	file = open( filepathname, O_RDONLY );
+	```
+
+	Instead of hardcoding a list of operating systems for this check,
+	update the logic that decides whether to build the file and set a
+	boolean flag that can be checked instead.
+
+2021-07-12  Werner Lemberg  <wl@gnu.org>
+
+	[autofit] More clean-ups.
+
+	* src/autofit/afhints.h (AF_GlyphHintsRec): Remove the no longer
+	needed fields `xmin_delta` and `xmax_delta`.
+
+	* src/autofit/afhints.c (af_glyph_hints_reload),
+	src/autofit/afloader.c (af_loader_load_glyph): Updated.
+
+2021-07-12  Werner Lemberg  <wl@gnu.org>
+
+	Small clean-ups for the last few commits.
+
+	* include/freetype/fttrace.h (afwarp): Removed.
+
+2021-07-12  David Turner  <david@freetype.org>
+
+	Remove obsolete `AF_Angle` type and related sources.
+
+	* src/autofit/afangles.c: File removed.  Functions related to
+	sorting moved to...
+	* src/autofit/afhints.c (af_sort_pos, af_sort_and_quantize_widths):
+	This file.
+	* src/autofit/afangles.h: File removed.
+	* src/autofit/aftypes.h: Updated.
+	* src/autofit/autofit.c: Updated.
+
+	* src/autofit/rules.mk (AUTOF_DRV_SRC): Updated.
+
+2021-07-12  David Turner  <david@freetype.org>
+
+	Remove experimental auto-hinting 'warp' mode.
+
+	This feature was always experimental, and probably never worked
+	properly.  This patch completely removes it from the source code,
+	except for a documentation block describing it for historical
+	purposes.
+
+	* devel/ftoption.h, include/freetype/config/ftoption.h: Remove
+	`AF_CONFIG_OPTION_USE_WARPER`.
+
+	* include/freetype/ftdriver.h: Document 'warping' property as
+	obsolete.
+
+	* src/autofit/afwarp.c, src/autofit/afwarp.h: Files removed.
+	* src/autofit/*: Remove any code related to warp mode.
+
+2021-07-12  David Turner  <david@freetype.org>
+
+	Remove experimental 'Latin2' writing system (`FT_OPTION_AUTOFIT2`).
+
+	This code has always been experimental and was never compiled anyway
+	(`FT_OPTION_AUTOFIT2` does not appear in `ftoption.h` or even any of
+	our build files).
+
+	* include/freetype/internal/fttrace.h (aflatin2): Removed.
+	* src/autofit/aflatin2.h, src/autofit/aflatin2.c: Files removed.
+	* src/autofit/afloader.c: Remove undocumented hook to activate
+	Latin2 system.
+	* src/autofit/afstyles.h: Remove `ltn2_dflt` style definition.
+	* src/autofit/afwrtsys.h: Remove `LATIN2` writing system definition.
+	* src/autofit/autofit.c: Updated.
+
+2021-07-05  Werner Lemberg  <wl@gnu.org>
+
+	* src/base/ftlcdfil.c (FT_Library_SetLcdGeometry): Fix argument.
+
+	Reported by Hin-Tak.
+
+2021-07-03  Werner Lemberg  <wl@gnu.org>
+
+	* meson_options.txt: Sort alphabetically; no final full stops.
+
+2021-07-01  Ben Wagner  <bungeman@chromium.org>
+
+	* src/truetype/ttgxvar.c (tt_set_mm_blend): Test `coords`.
+
+	It is undefined behavior to pass `NULL` to `memcpy`.  `coords' is
+	passed to `memcpy` but `TT_Get_MM_Blend` and `TT_Get_Var_Design`
+	explictly call `tt_set_mm_blend` with `coords` as `NULL`.  In
+	addition, `TT_Set_MM_Blend` has a similar possible issue.
+
+2021-06-30  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Support PaintScale in 'COLR' v1 parsing.
+
+	* include/freetype/ftcolor.h (FT_PaintFormat): Renumber values, add
+	`FT_COLR_PAINTFORMAT_SCALE`.
+	(FT_PaintScale): New structure to represent 'PaintScale*' tables.
+	(FT_COLR_Paint): Updated.
+
+	* src/sfnt/ttcolr.c (FT_PaintFormat_Internal): New enumeration.
+	(read_paint): Parse 'PaintScale' and friends.
+
+2021-06-30  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Handle fonts without layer list in 'COLR' v1.
+
+	'COLR' v1 fonts do not necessarily need to have a layer list; for
+	this reason, 'fontTools' recently started generating fonts in a way
+	that drops the layer list if there are no layers in it.  This
+	results in the layer list offset becoming zero, which FreeType
+	treated as an invalid table.  Fix that and handle the case for layer
+	list offset being 0.  This slightly changes how we need to calculate
+	the starting offset for paints.
+
+	* src/sfnt/ttcolr.c (tt_face_load_colr): Handle case of layer list
+	offset being zero without outright rejecting table.
+
+2021-06-30  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/raster/ftraster.c (Render_Single_Pass): Simplify `band_stack'.
+
+2021-06-29  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[raster] Do not skip the second pass without dropout control.
+
+	The second pass also fixes horizontal lines through the pixel centers.
+
+	* src/raster/ftraster.c (black_TWorker): Do not use `second_pass'.
+	(Render_Glyph): Skip the second pass only with the appropriate flag.
+
+2021-06-29  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[raster] Handle sub-band stack locally.
+
+	* src/raster/ftraster.c (black_TWorker): Move `band_stack' from here..
+	(Render_Single_Pass): ... to here and accept limit arguments.
+	(Render_Glyph): Updated.
+
+2021-06-25  Anurag Thakur  <anuthadev@gmail.com>
+
+	[CI] Introduce linux CI and refactor job names.
+
+	* .gitlab-ci.yml: Added jobs for building freetype on linux.
+
+2021-06-28  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[raster] Handle Bézier stack locally.
+
+	* src/raster/ftraster.c (black_TWorker): Move `arcs' from here...
+	(Conic_To, Cubic_To): ... to here to tighten their scope.
+	(Bezier_Up, Bezier_Down): ... Take the current `arc' argument.
+
+2021-06-28  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Improve paint limit checks
+
+	Paint tables can appear before the `base_glyphs_v1` offset if the
+	font is produced with the layer list before the base glyph list.  In
+	this case paint tables can occur after the layer list but before the
+	base glyph list.  Checks in the 'COLR' v1 code were rejecting fonts
+	with this layout.  Improve these checks by calculating a minimum
+	offset after which paint tables can occur and use that in safety
+	checks.
+
+	* src/sfnt/ttcolr.c (Colr, tt_face_load_colr): Declare
+	`paint_start_v1` and calculate that as the minimum of the end of
+	layer list and base glyph list.
+	(get_child_table_pointer, read_paint, tt_face_get_paint_layers):
+	Use that in safety checks.
+
+2021-06-28  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[raster] Clean up vertical sweep.
+
+	* src/raster/ftraster.c (black_TWorker): Replace the current line
+	offset with the pointer and drop the increment.
+	(Function_Sweep_Init): Take values as arguments instead of pointers.
+	(Vertical_Sweep_*, Horizontal_Sweep_Init, Draw_Sweep): Updated.
+
+2021-06-25  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[raster] Make `band_top' local variable.
+
+	* src/raster/ftraster.c (black_TWorker): Move `band_top' from here...
+	(Render_Single_Pass): ... to here, and refactor.
+	(Render_Glyph): Updated.
+
+2021-06-25  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[raster] Adjust sub-band bisecting limits.
+
+	We can bisect a band until it is just a single scan line.  This might
+	be slow and cause time-outs but if we need to impose limits it should
+	be elsewhere.
+
+	* src/raster/ftraster.c (Render_Single_Pass): Tweak sub-banding.
+
+2021-06-25  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/raster/ftraster.c (Render_Single_Pass): Remove dead code.
+
+2021-06-25  Werner Lemberg  <wl@gnu.org>
+
+	[base] Add trace level to logging output.
+
+	Some practical debugging work has shown that displaying level X of
+	an `FT_TRACEX` macro in the output of `FT2_DEBUG="...  -v"` would be
+	very helpful to find out which trace level should be selected.  As
+	an example, we now get output like
+
+	```
+	[ttobjs:2]    TTF driver
+	[ttobjs:2]      SFNT driver
+	[sfobjs:2]      not a font using the SFNT container format
+	[t1objs:2]    Type 1 driver
+	[stream:7]    FT_Stream_EnterFrame: 14 bytes
+	```
+
+	* include/freetype/internal/ftdebug.h (FT_LOGGING_TAGX): New macro.
+	(FT_LOG): Use it to add the trace level to the logging tag.
+
+	* include/freetype/internal/fttrace.h (FT_MAX_TRACE_LEVEL_LENGTH):
+	Adjust.
+
+	* docs/DEBUG: Updated.
+
+2021-06-24  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[smooth, raster] Fix up and align error codes.
+
+	FT_Render_Glyph picked up FAILURE or 1 returned from the raster
+	function, which became a confusing error code. Instead, return
+	Raster_Overflow in the unlikely event that banding does not help or
+	another meaningful error.
+
+	* src/smooth/ftgrays.c (gray_convert_glyph_inner, gray_convert_glyph):
+	Use Raster_Overflow when the rendering pool is exhausted and return it
+	if banding does not help.
+	(gray_raster_render): Use Smooth_Err_Ok.
+
+	* src/raster/ftraster.c (Render_Single_Pass): Return Raster_Overflow
+	if banding does not help or another error code.
+
+2021-06-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[smooth, raster] Remove synonymous error macros.
+
+	* src/smooth/ftgays.c [STANDALONE_]: s/ErrRaster_/Smooth_Err_/.
+	(gray_convert_glyph_inner): Updated accordingly.
+
+	* src/raster/ftraster.c [STANDALONE_]: Do not abbreviate error macros.
+	(New_Profile, End_Profile, Insert_Y_Turn, Line_Up, Bezier_Up,
+	Decompose_Curve, Draw_Sweep, Render_Single_Pass, ft_black_render):
+	Updated accordingly.
+
+2021-06-22  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] s/PaintTransformed/PaintTransform/, s/transformed/transform/.
+
+	* include/freetype/ftcolor.h (FT_PaintTransformed, FT_PaintFormat,
+	FT_COLR_Paint): Do it to make it harmonize with other names such as
+	'PaintTranslate'.
+
+	* src/sfnt/ttcolr.c (read_paint, tt_face_get_paint): Ditto.
+
+2021-06-22  Dominik Röttsches  <drott@chromium.org>
+
+	Move 'COLR' API to `ftcolor.h`.
+
+	* include/freetype/freetype.h: Cut section layer managament
+	containing 'COLR' v0 and v1 API and move it to `ftcolor.h` as
+	requested by Werner on freetype-devel.
+	* include/freetype/ftcolor.h: Paste that section.
+
+2021-06-19  Werner Lemberg  <david@freetype.org>
+
+	[truetype] Fix integer overflow.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35312
+
+	* src/truetype/ttinterp.c (Ins_JMPR): Use `ADD_LONG`.
+
+2021-06-19  Werner Lemberg  <david@freetype.org>
+
+	[autofit] Prevent hinting if there are too many segments.
+
+	This speeds up handling of broken glyphs.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35309
+
+	* src/autofit/aflatin.c (af_latin_hints_compute_segments): Implement
+	it.
+
+2021-06-18  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/sdf/ftsdfrend.c (ft_(b)sdf_render): Do not FT_ERROR routinely.
+
+2021-06-16  David Turner  <david@freetype.org>
+
+	[autofit] Fix return value of `FT_Load_Glyph`.
+
+	* src/autofit/afglobal.c (af_face_globals_get_metrics): The issue is
+	that `style_metrics_init` sometimes returns -1 without clearing
+	`error`.  While looping to `Again`, the next operation is
+	successful, but -1 is still returned by the function.  The fix is to
+	set `error` to 0 appropriately.
+
+	Fixes #1063.
+
+2021-06-15  David Turner  <david@freetype.org>
+
+	[meson] Add first regression test to FreeType.
+
+	* tests/README.md: New file that explains how to build and run the
+	tests with the Meson build.
+
+	* tests/scripts/download-test-fonts.sh: New bash script to download
+	test font files to the `tests/data` folder.
+
+	* meson.build, meson_options.txt: Add 'tests' option to enable
+	building and running the test programs (disabled by default).
+
+	* tests/meson.build: New file.
+
+	* tests/issue-1063/main.c: Simple regression test to exhibit issue
+	1063.
+
+	* .gitignore: Ignore the content of the `tests/data` folder for
+	now.
+
+2021-06-12  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[type42] Fix new memory leak.
+
+	We need to inverse inheritance of FT_GlyphSlot_Internal so that we
+	have a chance to free the rendered bitmap from the parent slot.
+
+	* src/type42/t42objs.c (T42_GlyphSlot_Init): Remove the internal parts
+	of the child `ttslot' and replace it with the parent structure.
+	(T42_GlyphSlot_Done): Updated accordingly.
+
+2021-06-12  Werner Lemberg  <wl@gnu.org>
+
+	[psaux] Fix another assertion.
+
+	* src/psaux/psintrp.c (cf2_interpT2CharString)
+	<cf2_escCALLOTHERSUBR>: Convert assertion into error, since the
+	problem can happen with invalid user input.
+
+	Test case is file
+
+	  fuzzing/corpora/legacy/oss-fuzz/5754332360212480-unknown-read
+
+	in the `freetype2-testing` repository.
+
+2021-06-12  Werner Lemberg  <wl@gnu.org>
+
+	[psaux] Fix assertions.
+
+	* src/psaux/pshints.c (cf2_hintmap_adjustHints): Check for overflow
+	before emitting an assertion error.
+
+	Test case is file
+
+	 fuzzing/corpora/legacy/oss-fuzz/4594115297673216-integer-overflow
+
+	in the `freetype2-testing` repository.
+
+2021-06-09  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/truetype/ttinterp.c (TT_RunIns): Optimize tracing.
+
+2021-06-09  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[sdf] Fix SDF positioning.
+
+	* src/sdf/ftsdfrend.c (ft_sdf_render, ft_bsdf_render): Add padding to
+	`bitmap_top' and `bitmap_left'.
+
+	* sdf/sdf/ftsdf.c (sdf_generate_with_overlaps): Fix VC++ warning.
+
+2021-06-08  Werner Lemberg  <wl@gnu.org>
+
+	Fix 'devel' build for 'COLR' v1.
+
+	* devel/ftoption.h: Synchronize with
+	  `include/freetype/config/ftoption.h`.
+
+2021-06-08  Werner Lemberg  <wl@gnu.org>
+
+	[sfnt] Sanitize cmap4 table better.
+
+	Fixes #1062.
+
+	* src/sfnt/ttcmap.c (tt_cmap4_validate): Handle a too-small value of
+	`length` gracefully.
+
+2021-06-08  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Pointer validity check when reading 'COLR' v1 layers
+
+	* src/sfnt/ttcolr.c (tt_face_get_paint_layers): In addition to the
+	existing sanity checks, ensure that the pointer to the layer to be
+	read is within the 'COLR' v1 table.
+
+2021-06-08  Werner Lemberg  <wl@gnu.org>
+
+	* src/sdf/ftsdfcommon.c: Fix inclusion of header files.
+
+2021-06-08  Werner Lemberg  <wl@gnu.org>
+
+	[sdf] Make `make multi` work.
+
+	* src/sdf/ftsdf.c: Include `ftbitmap.h`.
+
+	* src/sdf/ftsdfcommon.h: Move function bodies to `ftsdfcommon.c`.
+	Include `ftobjs.h` to get definitions of `FT_LOCAL` and friends.
+
+	* src/sdf/ftsdfcommon.c: New file.
+
+	* src/sdf/rules.mk, src/sdf/sdf.c: Updated.
+
+2021-06-08  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Use 8 bits for final SDF output instead of 16bits.
+
+	Since 8-bits is enough to represent SDF data we no longer require
+	16-bits for this purpose.  Also, we now normalize the output data
+	to use the entire 8-bit range efficiently.  For example: if we use
+	3.5 format with a spread of 1 we basically only use the starting
+	5-bits.  By normalizing we can use the entire 8-bit range.
+
+	* include/freetype/freetype.h (FT_Render_Mode): Updated description
+	for `FT_RENDER_MODE_SDF` regarding this change.
+
+	* include/freetype/ftimage.h (FT_Pixel_Mode): Removed
+	`FT_PIXEL_MODE_GRAY16` since no longer required.
+
+	* include/freetype/fttypes.h (FT_F6Dot10): Removed since no longer
+	required.
+
+	* src/sdf/ftsdfrend.c (ft_sdf_render, ft_bsdf_render): Allocate 8-bit
+	bitmap instead of 16-bit buffer.
+
+	* src/sdf/ftsdfcommon.h (map_fixed_to_sdf): Added function to convert
+	16.16 distance value to our desired format.
+
+	* src/sdf/ftsdf.c (sdf_generate_with_overlaps,
+	sdf_generate_bounding_box): Use the new `map_fixed_to_sdf` function
+	and also use 8-bit output buffer.
+
+	* src/sdf/ftbsdf.c (finalize_sdf): Output to a 8-bit buffer instead
+	of 16-bit buffer.
+
+2021-06-02  Ben Wagner  <bungeman@chromium.org>
+	    Werner Lemberg  <wl@gnu.org>
+
+	[sfnt] Fix fallout from 2021-05-29 change.
+
+	* src/sfnt/ttcolr.c (find_base_glyph_record,
+	find_base_glyph_v1_record): Adjust binary search.
+
+	Needs to be updated with change to unsigned.
+
+2021-06-02  Werner Lemberg  <wl@gnu.org>
+
+	* src/autofit/aflatin.c (af_latin_metrics_scale_dim): Fix tracing.
+
+	Problem reported by Alexei.
+
+2021-06-02  Werner Lemberg  <wl@gnu.org>
+
+	[psaux] Fix MSVC compiler warnings.
+
+	* src/psaux/afmparse.c (afm_parse_track_kern, afm_parse_kern_pairs):
+	Add cast.
+
+2021-05-29  Werner Lemberg  <wl@gnu.org>
+
+	Fix compilation errors and (some) warnings for clang++.
+
+	* src/autofit/afmodule.c (AF_GlyphHintsRec): Make it static.
+
+	* src/cache/ftcache.c (FTC_Cache_NewNode), src/cache/ftcsbits.c
+	(ftc_snode_compare): Remove semicolon.
+
+	* src/cff/cffparse.c (cff_parser_run): Add `break` statement.
+
+	* src/cid/cidload.c (cid_hex_to_binary): Add cast.
+
+	* src/sdf/ftbsdf.c (CHECK_NEIGHBOR): Use `do {} while(0)` loop.
+	(bsdf_init_distance_map, finalize_sdf, bsdf_raster_render): Add
+	casts.
+	* src/sdf/ftsdf.c (sdf_generate_bounding_box,
+	sdf_generate_with_overlaps): Ditto.
+	* src/sdf/ftsdfcommon.h (square_root): Ditto.
+	* src/sdf/ftsdfrend.c (sdf_property_get, ft_sdf_render,
+	ft_bsdf_render): Ditto.
+
+	* src/sfnt/ttcolr.c (find_base_glyph_record,
+	find_base_glyph_v1_record): Fix variable signedness.
+	(read_color_line): Add cast.
+	(read_paint): Add casts.
+	Fix signedness issue.
+	(tt_face_get_colorline_stops) Fix signedness issues.
+
+	* src/sfnt/ttpost.c (load_format_20): Add casts.
+
+	* src/truetype/ttsubpix.c (TWEAK_RULES, TWEAK_RULES_EXCEPTIONS):
+	Remove final semicolons.
+
+2021-05-29  Werner Lemberg  <wl@gnu.org>
+
+	[build] Allow overriding of `ANSIFLAGS` for GNU make build.
+
+	* builds/*: Implement it.
+
+2021-05-27  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[type42] Fix auto-hinting.
+
+	The autohinter could not access the base (unscaled) outline in the
+	child TrueType glyph slot. We now share the internal parts between
+	the parent and child glyph slots. Fixes #1057.
+
+	* src/type42/t42objs.c (T42_GlyphSlot_Init): Remove the internal parts
+	of `T42_GlyphSlot' and replace it with the child TrueType structure.
+	(T42_GlyphSlot_Done): Updated accordingly.
+
+2021-05-25  Werner Lemberg  <wl@gnu.org>
+
+	[psaux] Guard and trace AFM kern data allocation.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=31543
+
+	* include/freetype/internal/fttrace.h: Add 'afmparse' trace
+	component.
+
+	* src/psaux/afmparse.c (FT_COMPONENT): Define.
+	(afm_parse_track_kern, afm_parse_kern_pairs): Protect against
+	allocations bombs.
+	Add tracing.
+	(afm_parse_kern_data): Don't allow multiple kern data sections.
+
+2021-05-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* meson.build (ft2_public_headers): Add missing `ftcid.h'.
+
+	Fixes #1058.
+
+2021-05-20  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[type42] Avoid some memory zeroing.
+
+	* src/type42/t42objs.c (T42_Open_Face): Tweak allocation macro.
+	* src/type42/t42parse.c (t42_parse_sfnts): Ditto.
+
+2021-05-19  Nikolaus Waxweiler  <madigens@gmail.com>
+
+	[CMake] Update dependency finders.
+
+	1. Fixes CMake using any found HarfBuzz version lower than the minimum
+	required. This is based on HALX99's merge request at
+	https://gitlab.freedesktop.org/freetype/freetype/-/merge_requests/31
+	2. Update FindHarfBuzz.cmake from
+	https://github.com/WebKit/WebKit/blob/1ce32454/Source/cmake/FindHarfBuzz.cmake
+	and guard post-CMake-3.1 features to keep the minimum version unchanged
+	3. Update FindBrotliDec.cmake to stop the warnings, based on what
+	https://github.com/google/woff2/blob/a0d0ed7d/cmake/FindBrotliDec.cmake
+	is doing
+
+	* CMakeLists.txt, builds/cmake/FindHarfBuzz.cmake: Implement 1 and 2.
+	* builds/cmake/FindBrotliDec.cmake: Implement 3.
+
+2021-05-19  Ben Wagner  <bungeman@chromium.org>
+
+	[gzip] Use exact type for `ft_gzip_alloc` and `ft_gzip_free`.
+
+	While a function pointer may be cast to another function pointer
+	type, it is required to cast the function pointer back to the
+	original function pointer type before calling it.  If a parameter is
+	a pointer the exact pointer type is required.  Using a pointer to a
+	different underlying type is technically undefined behavior.  The
+	wrapper functions `ft_gzip_alloc` and `ft_gzip_free` took
+	`FT_Memory` (a `FT_MemoryRec_*`) instead of `voidpf` (`void*`), so
+	when gzip calls these callbacks through `alloc_func` or `free_func`
+	it invokes undefined behavior.  On most platforms this works out as
+	expected, but newer undefined behavior detectors and targets like
+	wasm can detect this and will produce an error.
+
+	* src/gzip/ftgzip.c (ft_gzip_alloc, ft_gzip_free): Update signatures
+	to exactly match `alloc_func` and `free_func`, respectively.
+	Internally, cast the `void*` opaque pointer to `FT_Memory`.
+
+2021-05-18  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	Prioritize the anti-aliasing renderer module.
+
+	* modules.cfg: Reorder the renderers.
+	* include/freetype/config/ftmodule.h: Ditto.
+
+2021-05-16  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[sfnt] Additional guards on the POST table.
+
+	Fixes timeout (#1055) analyzed by Ben Wagner, reported as
+
+	  https://crbug.com/1194092
+
+	* src/sfnt/ttload.c (tt_face_load_post): Check POST format.
+	* src/sfnt/sfobjs.c (sfnt_load_face): Synthesize the missing unicode
+	charmap only if the glyph names exist.
+	* src/psnames/psmodule.c (ps_unicode_value): Short cut ".notdef" and
+	".null".
+
+2021-05-13  Daniel McArdle  <dmcardle@chromium.org>
+
+	[psaux] Use doubling allocation strategy for CF2_ArrStack.
+
+	Fixes timeout reported as
+
+	  https://crbug.com/1206181
+
+	* src/psaux/psarrst.c (cf2_arrstack_{push,init}): Implement it.
+	* src/psaux/psarrst.h (CF2_ArrStackiRec): Drop `chunk'.
+
+2021-05-12  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/smooth/ftgrays.c (FT_MAX_GRAY_SPANS): Increase from 10 to 16.
+
+	Ten was barely enough for two slanted stems. Sixteen can actually fit
+	a bit more complicated scanlines.
+
+2021-05-11  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/smooth/ftgrays.c (FT_GRAY_SET): Adjust for better code.
+
+2021-05-11  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[smooth] Faster bitmap sweeping.
+
+	Selecting the fill rule or checking the direct mode each time we call
+	`gray_hline' is sub-optimal.  This effectively splits the direct mode
+	into a separate code path while inlining `gray_hline' and saving 5-7%
+	of rendering time.
+
+	* src/smooth/ftgrays.c (gray_hline): Eliminated in favor of...
+	(FT_FILL_RULE, FT_GRAY_SET): ... these new macros...
+	(gray_sweep): ... inlined here.
+	(gray_sweep_direct): New function that handles the direct span buffer.
+	(gray_TWorker): Remove the span buffer.
+	(gray_raster_render, gray_convert_glyph): Updated.
+
+2021-05-10  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/smooth/ftgrays.c (gray_hline): Simplify even-odd computations.
+
+	It is too bad the even-odd rule is not used much.
+
+2021-05-07  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[type1] Avoid MM memory zeroing.
+
+	* src/type1/t1load.c (t1_allocate_blend, parse_blend_design_map):
+	Tweak allocation macros.
+	* src/type1/t1objs.c (T1_Face_Done): Minor.
+
+2021-05-07  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/bdf/bdflib.c (_bdf_list_ensure): Tweak allocation macro.
+
+2021-05-06  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/psaux/psobjs.c (ps_parser_load_field): Tweak allocation macro.
+
+2021-05-06  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/sfnt/sfobjs.c (sfnt_load_face): Tweak allocation macro.
+
+2021-05-06  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/cid/cidload.c (cid_read_subrs): Tweak allocation macro.
+
+2021-05-06  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Tweak allocation.
+
+2021-05-05  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[cff,psaux] Avoid memory zeroing (contd.).
+
+	* src/cff/cffload.c (cff_blend_doBlend, cff_blend_build_vector): Tweak
+	allocation macros.
+	* src/psaux/psarrst.c (cf2_arrstack_setNumElements): Ditto.
+	* src/psaux/psstack.c (cf2_stack_init): Ditto.
+
+2021-05-04  Ben Wagner  <bungeman@chromium.org>
+
+	* src/cid/cidload.c (cid_hex_to_binary): Improve return value.
+
+	Add argument to return the actual number of bytes that were decoded.
+	The actual number of bytes decoded can be quite variable depending
+	on the number of ignored 'whitespace' bytes or early termination
+	with `>`.
+	(cid_face_open): Updated to use this calculated value.  This avoids
+	trusting `parser->binary_length` is always be correct and reading
+	uninitialized bits if fewer are actually decoded.
+
+	First reported as
+
+	  https://crbug.com/1203240
+
+2021-05-03  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[sfnt] Streamline POST format 2.0 handing.
+
+	To reduce memory allocations, we read an entire Pascal-string buffer
+	and convert it to a C-string buffer.  We also reject tables with
+	Postscript glyph names exceeding 63 bytes.
+
+	* src/sfnt/ttpost.c (load_format20): Implement it.
+	(load_post_names): Check the minimal POST table size.
+	(load_format25, tt_face_free_ps_names): Updated accordingly.
+
+2021-05-02  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[bdf,pcf] Avoid memory zeroing (contd.).
+
+	* src/bdf/bdflib.c (bdf_create_property, _bdf_add_comment,
+	_bdf_add_property, bdf_load_font): Tweak allocation macros.
+	* src/pcf/pcfread.c (pcf_get_properties, pcf_get_metrics): Ditto.
+
+2021-05-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/cid/cidload.c (cid_read_subrs): Tweak allocaton macro.
+
+2021-05-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[sfnt] Avoid some memory zeroing.
+
+	* src/sfnt/sfobjs.c (sfnt_open_font, sfnt_init_face,
+	tt_name_ascii_from_{utf16,other}): Tweak allocaton macros.
+	* src/sfnt/ttload.c (tt_face_load_name): Ditto.
+
+2021-05-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/sfnt/ttpost.c (load_format_{20,25}): Tweak allocaton macros.
+
+2021-05-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/sfnt/pngshim.c (Load_SBit_Png): Tweak allocaton macro.
+
+2021-05-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[truetype] Avoid some memory zeroing.
+
+	* src/truetype/ttinterp.c (Init_Context): Tweak allocation macro.
+	* src/truetype/ttpload.c (tt_face_load_cvt): Ditto.
+
+2021-05-01  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[woff2] Avoid some memory zeroing.
+
+	* src/sfnt/sfwoff2.c (store_loca, woff2_open_font): Tweak macros.
+
+2021-04-30  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/gzip/ftgzip.c (ft_gzip_alloc): Zero out memory again.
+
+2021-04-27  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[lzw] Preserve decompression stack when relocating to heap.
+
+	* src/lzw/ftzopen.c (ft_lzwstate_stack_grow): Copy stack when
+	relocating to heap.
+
+2021-04-27  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/cid/cidgload.c (cid_load_glyph): Restore the glyph_length check.
+
+2021-04-27  Werner Lemberg  <wl@gnu.org>
+
+	* src/psmodule.c (ps_unicodes_init): Ignore empty glyph names.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=33637
+
+2021-04-26  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/sfnt/sfobjs.c (sfnt_init_face): Revert macro change.
+
+2021-04-26  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[cff] Avoid some memory zeroing.
+
+	* src/cff/cffparse.c (cff_parser_init): Tweak memory macro.
+	* src/cff/cffload.c (cff_index_load_offsets, cff_index_get_pointers,
+	cff_charset_load, cff_vstore_load): Ditto.
+
+2021-04-26  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[pfr] Avoid some memory zeroing.
+
+	* src/pfr/pfrobjs.c (pfr_face_init) : Tweak memory macro.
+	* src/pfr/pfrload.c (pfr_extra_item_load_stem_snaps,
+	pfr_phy_font_load): Ditto.
+
+2021-04-26  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/winfonts/winfnt.c (FNT_Face_Init): Tweak memory macro.
+
+2021-04-26  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[psaux,psnames] Avoid some memory zeroing.
+
+	* src/psaux/psstack.c (cf2_stack_init): Tweak memory macro.
+	* src/psnames/psmodule.c (ps_unicodes_init): Ditto.
+
+2021-04-25  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[base] Avoid some memory zeroing.
+
+	* src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Use FT_QNEW_ARRAY.
+	* src/base/ftsnames.c (FT_Get_Sfnt_{Name,LangTag}): Ditto.
+
+2021-04-25  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[bdf,pcf] Avoid some memory zeroing.
+
+	* src/pcf/pcfread.c (pcf_read_TOC, pcf_get_properties, pcf_load_font):
+	Tweak memory macros.
+	* src/bdf/bdfdrivr.c (BDF_Face_Init): Ditto.
+	* src/bdf/bdflib.c (_bdf_readstreami, bdf_create_property,
+	_bdf_parse_glyphs, _bdf_parse_start): Ditto.
+	(_bdf_add_property): Do not handle zero size.
+
+2021-04-25  Issam E. Maghni  <issam.e.maghni@mailbox.org>
+
+	* builds/meson/process_ftoption_h.py: Add LF at EOF.
+
+	This fixes
+
+	  .../ftoption.h:1030:10: error:
+	    no newline at end of file [-Werror,-Wnewline-eof]
+
+	for the generated `ftoption.h` file.
+
+2021-04-24  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/cff/cffload.c (cff_index_get_pointers): s/FT_QALLOC/FT_ALLOC/.
+
+2021-04-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/base/ftobjs.c (Mac_Read_POST_Resource): s/FT_ALLOC/FT_QALLOC/.
+	* builds/mac/ftmac.c (FT_New_Face_From_SFNT, read_lwfn): Ditto.
+
+2021-04-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/sdf/ftsdf.c (sdf_{edge,contour,shape}_new): Use FT_QALLOC.
+
+2021-04-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[sfnt] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+	* src/sfnt/sfdriver.c (get_win_string, get_apple_string,
+	sfnt_get_var_ps_name): Do not zero out the buffer.
+	* src/sfnt/sfobjs.c (sfnt_init_face): Ditto.
+	* src/sfnt/sfwoff.c (woff_open_font): Ditto.
+	* src/sfnt/sfwoff2.c (woff2_open_font): Ditto.
+
+2021-04-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[cff,type1,type42] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+	* src/cff/cffload.c (cff_index_get_pointers, cff_index_get_name):
+	Do not zero out the buffer.
+	* src/cff/cffdrivr.c (cff_ps_get_font_info): Ditto.
+	* src/type1/t1load.c (parse_subrs, parse_charstrings,
+	parse_blend_axis_types): Ditto.
+	* src/type1/t1parse.c (T1_New_Parser, T1_Get_Private_Dict): Ditto.
+	* src/type42/t42parse.c (t42_parser_init): Ditto.
+
+2021-04-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[cid] s/FT_ALLOC/FT_QALLOC/ and clean up.
+
+	* src/cid/cidgload.c (cid_load_glyph): Do not zero out the buffer.
+	* src/cid/cidload.c (cid_face_open, cid_read_subrs): Ditto.
+
+2021-04-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[pfr] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+	* src/pfr/pfrload.c (pfr_extra_item_load_font_id, pfr_aux_name_load):
+	Do not zero out the buffer.
+
+2021-04-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[bzip2,gzip] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+	* src/bzip2/ftbzip2.c (ft_bzip2_alloc): Do not zero out the buffer.
+	* src/gzip/ftgzip.c (ft_gzip_alloc, FT_Stream_OpenGzip): Ditto.
+
+2021-04-23  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[pcf,bdf,winfonts] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+	* src/pcf/pcfread.c (pcf_interpret_style): Do not zero out the buffer.
+	* src/bdf/bdfdrivr.c (bdf_interpret_style): Ditto.
+	* src/winfonts/winfnt.c (FNT_Face_Init, FNT_Load_Glyph): Ditto.
+
+2021-04-22  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[cache] Optimize SBit copying.
+
+	* src/cache/ftcsbits.c (ftc_snode_load): Do not initialize the buffer.
+	(ftc_sbit_copy_bitmap): Accept zero size, s/FT_ALLOC/FT_QALLOC/.
+
+2021-04-22  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[gxvalid,otvalid] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+	* src/gxvalid/gxvmod.c (gxv_load_table): Do not zero out the buffer.
+	* src/otvalid/otvmod.c (otv_load_table): Ditto.
+
+2021-04-22  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[psaux] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+	* src/psaux/psobjs.c (ps_table_done, ps_parser_load_field): Do not
+	zero out the buffer.
+
+2021-04-22  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[base] s/FT_ALLOC/FT_QALLOC/ for initialized buffers.
+
+	* src/base/ftobjs.c (open_face_PS_from_sfnt_stream,
+	Mac_Read_sfnt_Resource): Do not zero out the buffer.
+	* src/base/ftmac.c (FT_New_Face_From_SFNT, read_lwfn): Ditto.
+	* src/base/ftrfork.c (raccess_make_file_name,
+	raccess_guess_darwin_hfsplus, raccess_guess_darwin_newvfs): Ditto.
+
+2021-04-20  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[cache] Restore SBit copying for unowned (BDF) bitmaps.
+
+	* src/cache/ftcsbits.c (ftc_sbit_copy_bitmap): Restore.
+	(ftc_snode_load): Check ownership and copy unowned bitmaps.
+
+2021-04-19  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Return in 'COLR' v1 when layer pointer outside table
+
+	* src/sfnt/ttcolr.c (tt_face_get_paint_layers): Add missing return
+	when paint pointer outside table.
+	(read_paint): Add missing return when paint pointer outside table.
+
+2021-04-18  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[cache] Switch to lazy SBit setting.
+
+	* src/cache/ftcsbits.c (ftc_sbit_copy_bitmap): Removed.
+	(ftc_snode_load): Take the bitmap ownership instead of copying.
+
+2021-04-16  Daniel Welty  <@danielwelty>
+
+	* src/cache/ftcsbits.c (ftc_snode_load): Properly handle short pitch.
+
+2021-04-16  Werner Lemberg  <wl@gnu.org>
+
+	* builds/unix/freetype2.m4: Fix help string formatting.
+
+	The indented `dnl` macros inserted unwanted horizontal space.
+
+	Problem reported by Ozkan Sezer <sezeroz@gmail.com>.
+
+2021-04-16  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Safeguard 'COLR' v1 layer extraction
+
+	* src/sfnt/ttcolr.c (tt_face_get_paint_layers): Do not output
+	layer pointer to iterator if it is outside the 'COLR' table.
+	(read_paint): Do not attempt to read layers that are outside the
+	table.
+
+2021-04-02  Ben Wagner  <bungeman@chromium.org>
+
+	[base] Complete `ft_glyphslot_clear`.
+
+	* src/base/ftobjs.c (ft_glyphslot_clear): This function is intended
+	to reset all the values of a glyph slot.  However, it was not
+	resetting the values of the advances and `glyph_index`.  Reset the
+	advances and `glyph_index` to zero.
+
+2021-04-02  Ben Wagner  <bungeman@chromium.org>
+
+	[truetype] Prevent glyph program state from persisting.
+
+	`FDEF` instructions are specified as allowed only in 'prep' or
+	'fpgm'.  FreeType has attempted to prevent their use in the glyph
+	program, but they were still allowed in glyph programs if defined in
+	a function defined in 'prep' or 'fpgm' and called from the glyph
+	program.
+
+	Similarly, `IDEF` instructions are specified not to be able to
+	modify any existing instruction.  FreeType has attempted to prevent
+	their use in the glyph program, but they can still be used like
+	`FDEF`.
+
+	This change stores the initial bytecode range type and disallows the
+	use of `FDEF` and `IDEF` while running the glyph program.
+
+	Most other state is copied from the `TT_Size` into the execution
+	context.  However, it is possible for a glyph program to use `WS` to
+	write to the storage area or `WCVTP`, `WCVTF`, and `DELTAC[123]` to
+	write to the control value table.
+
+	Allowing any change to the global state from the glyph program is
+	problematic as the outlines of any given glyph may change based on
+	the order the glyphs are loaded or even how many times they are
+	loaded.  There exist fonts that write to the storage area or the
+	control value table in the glyph program, so their use should not be
+	an error.
+
+	Possible solutions to using these in the glyph program are
+
+	  * ignore the writes;
+	  * value-level copy on write, discard modified values when finished;
+	  * array-level copy on write, discard the copy when finished;
+	  * array-level copy up-front.
+
+	Ignoring the writes may break otherwise good uses.  A full copy
+	up-front was implemented, but was quite heavy as even well behaved
+	fonts required a full copy and the memory management that goes along
+	with it.  Value-level copy on write could use less memory but
+	requires a great deal more record keeping and complexity.  This
+	change implements array-level copy on write.  If any attempt is made
+	to write to the control value table or the storage area when the
+	initial bytecode range was in a glyph program, the relevant array
+	will be copied to a designated storage area and the copy used for
+	the rest of the glyph program's execution.
+
+	* src/truetype/ttinterp.h (TT_ExecContextRec): New fields
+	`iniRange`, `glyfCvtSize`, `glyfCvt`, `origCvt`, `glyfStoreSize`,
+	`glyfStorage`, and `origStorage`.
+
+	* src/truetype/ttinterp.c (Modify_CVT_Check): New function to handle
+	`exc->glyfCvt`.
+	(Write_CVT, Write_CVT_Stretched, Move_CVT, Move_CVT_Stretched): Use
+	it.
+	(Ins_WS): Handle `exc->glyfStorage`.
+	(Ins_FDEF, Ins_IDEF): Updated.
+	(TT_RunIns): Updated.
+	(TT_Done_Context): Free 'glyf' CVT working and storage area.
+	(TT_Load_Context): Fix/add casts.
+
+	* src/truetype/ttgload.c (TT_Load_Simple_Glyph): Fix cast.
+
+2021-03-30  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Check validity of pointer location of `read_color_line`.
+
+	* src/sfnt/ttcolr.c (get_child_table_pointer): New function to fetch
+	child table pointer early for all paint formats that compute a child
+	table pointer.
+	(read_color_line, read_paint): Updated.
+	(tt_face_get_colorline_stops): Check `colr->table`.
+
+2021-03-28  Nikhil Ramakrishnan  <ramakrishnan.nikhil@gmail.com>
+
+	[docs] Update docwriter stylesheet for 1.3.1.
+
+	This change is required to support docwriter 1.3.1.
+
+	See
+
+	  https://gitlab.freedesktop.org/freetype/docwriter/-/merge_requests/101
+
+	for more information.
+
+	* docs/markdown/stylesheets/extra.css:
+	(.wy-nav-content, .md-sidebar--secondary): Remove.
+
+2021-03-16  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/sfnt/pngshim.c (Load_SBit_Png): Free `rows` once later.
+
+2021-03-16  Ben Wagner  <bungeman@google.com>
+
+	[sfnt] Fix memory leak in png loading.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/chromium/issues/detail?id=1182552
+
+	Memory is allocated and the pointer assigned to `rows` inside a
+	'setjmp' scope.  This memory must be freed outside the 'setjmp'
+	scope after a 'longjmp'.  Since `rows` is a local and modified
+	inside the 'setjmp' scope it must be marked volatile or it will have
+	an indeterminate value after the 'longjmp'.
+
+	* src/sfnt/pngshim.c (Load_SBit_Png): Fix memory leak of `rows`.
+
+2021-03-16  Christopher Degawa  <ccom@randomderp.com>
+
+	* CMakeLists.txt: Don't limit generation of 'pkg-config' file to UNIX.
+
+	mingw-w64 uses the 'pkg-config' files but does not set UNIX.
+
+2021-03-11  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/smooth/ftgrays.c (gray_set_cell): Refactor to fix VC++ warning.
+
+2021-03-13  Werner Lemberg  <wl@gnu.org>
+
+	Handle various VC++ compiler warnings.
+
+	Fixes #1039.
+
+	* src/base/ftstroke.c (ft_stroker_inside, ft_stroker_outside):
+	Initialize `sigma`.
+
+	* src/sdf/ftsdf.c (sdf_generate_with_overlaps): Exit immediately if
+	function arguments are invalid.
+	* src/sdf/ftsdfrend.c (sdf_property_set) <"overlaps">: Fix cast.
+
+	* src/sfnt/sfwoff2.c (woff2_decompress)
+	[!FT_CONFIG_OPTION_USE_BROTLI]: Use `FT_UNUSED`.
+
+	* src/truetype/ttgxvar.c (TT_Get_MM_Var): Initialize `fvar_head`.
+
+2021-03-11  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[smooth] Reduce copying during integration phase.
+
+	We now record `cover' and `area' directly into the linked list. This
+	makes rendering faster by 10% or even more at larger sizes.
+
+	* src/smooth/ftgrays.c (FT_INTEGRATE): Write directly.
+	(gray_TWorker): Add direct cell reference and remove unused fields.
+	(gray_set_cell): Consolidate the linked list management and pointers.
+	(gray_convert_glyph, gray_convert_glyph_inner): Updated.
+
+2021-03-10  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/smooth/ftgrays.c (FT_INTEGRATE): New convenience macro.
+	(gray_render_line, gray_render_scanline): Use it.
+
+2021-03-09  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/smooth/ftgrays.c (gray_render_line): Rearrange conditionals.
+
+	These produce faster or more optimizable code.
+
+2021-03-08  Tim-Philipp Müller  <tim@centricular.com>
+
+	[meson] Fix 'mmap' handling on Windows.
+
+	* meson.build (ft2_sources): Always use `windows/ftsystem.c` on
+	Windows unless mmap has been disabled.
+
+	  https://gitlab.freedesktop.org/freetype/freetype/-/merge_requests/5#note_829289
+
+2021-03-07  Tim-Philipp Müller  <tim@centricular.com>
+
+	[ci] Add basic support for Meson builds with MSVC on Windows.
+
+	This adds meson jobs for VS2017 (x86 and x86_64).
+
+	* .gitlab-ci.yml: New file.
+
+2021-03-07  Tim-Philipp Müller  <tim@centricular.com>
+
+	[meson] Add subproject fallbacks for 'libpng' and 'zlib'.
+
+	* subprojects/libpng.wrap, subprojects/zlib.wrap: New files.
+
+	* meson.build: Updated.
+
+2021-03-07  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	[meson] Make it work with Windows.
+
+	* meson.build: Do not process `ftconfig.h` when not using
+	`ftconfig.h.in`.
+
+	Fixes #1029.
+
+2021-02-25  Werner Lemberg  <wl@gnu.org>
+
+	[woff2] Fix memory leak.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=28148
+
+	* src/sfnt/sfwoff2.c (woff2_open_font): Reject fonts that have
+	multiple tables with the same tag.  While not explicitly forbidden
+	in the OpenType specification, it is implicitly forbidden by
+	describing a binary search algorithm for tables that only works
+	reliably if table tags are unique.
+
+2021-02-22  Werner Lemberg  <wl@gnu.org>
+
+	* CMakeLists.txt: Update location of `LICENSE.TXT`.
+
+	Fixes #1035.
+
+2021-02-19  Werner Lemberg  <wl@gnu.org>
+
+	* builds/unix/ax_pthread.m4: Update from 'autoconf-archive'.
+
+	A bunch of fixes were added recently to its git repository.
+
+2021-02-17  Werner Lemberg  <wl@gnu.org>
+
+	[unix] Updates for autoconf 2.71.
+
+	This fixes warnings reported by autoupdate.
+
+	* builds/unix/ax_pthread.m4: Replace `as_echo` with `AS_ECHO`.
+
+	* builds/unix/configure.raw: Remove obsolete `AC_HEADER_STDC`.
+	Don't escape back quotes in messages for `AC_MSG_WARN`.
+
+2021-02-16  Werner Lemberg  <wl@gnu.org>
+
+	* builds/toplevel.mk: Fix previous commit.
+
+	<top_level>: Use `TOP_DIR` in `wildcard` function.
+	(check_out_submodule, copy_submodule): Move down to come after
+	definition of `all` rule.
+	Call `mkdir` conditionally.
+
+2021-02-16  Werner Lemberg  <wl@gnu.org>
+
+	* builds/toplevel.mk: Use rules for handling 'dlg'.
+
+	Suggested by Alexei.
+
+	(check_out_submodule, copy_submodule): New targets.
+	<top-level>: Replace calls to `shell` with rules.
+
+2021-02-16  Werner Lemberg  <wl@gnu.org>
+
+	* builds/toplevel.mk: Avoid side effects of `shell`.
+
+	We use a dummy variable to catch its output.  Otherwise the `make`
+	program is going to interpret the return value of `shell`; this can
+	cause obscure warning or error messages or even be harmful.
+
+2021-02-16  Werner Lemberg  <wl@gnu.org>
+
+	Move 'dlg' submodule to `subprojects` directory.
+
+	This is for future changes with Meson, which doesn't allow a
+	different name for its `subprojects` directory.  Having both a
+	`submodules` and a `subprojects` directory is confusing.
+
+	* .gitmodules, autogen.sh (copy_submodule_files, DLG_INC_DIR,
+	DLG_SRC_DIR): Updated.
+
+	* builds/toplevel.mk (<top-level>, do-dist),
+	builds/windows/vc2010/script.bat: Updated.
+
+	* src/tools/no-copyright: Updated.
+
+2021-02-16  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Update paint format values to support non-variable paints.
+
+	* freetype.h (FT_PaintFormat): Update paint format identifiers after
+	a specification change.  The specification was updated to have
+	sibling formats, variable and non-variable variants for each.
+	Reflect that here.
+
+	* sfnt/ttcolr.c (read_paint): Remove parsing of variable indices as
+	the non-variable formats no longer have them.
+
+2021-02-15  Daniel E  <daniel.engberg.lists@pyret.net>
+
+	* CMakeLists.txt: Improve 'bz2' support.
+
+	Not all distributions such as FreeBSD provide a `.pc` file for
+	'(lib)bz2' so follow autotools and add it to `Libs.private` instead.
+
+2021-02-13  Werner Lemberg  <wl@gnu.org>
+
+	* src/tools/update-copyright-year: Fix single-year entry handling.
+
+	The fix from 2021-01-17 didn't cover the case where the year to be
+	updated is identical to the current year.
+
+2021-02-13  Werner Lemberg  <wl@gnu.org>
+
+	Add new function `FT_Get_Transform`.
+
+	See
+
+	  https://github.com/harfbuzz/harfbuzz/issues/2428
+
+	for some reasons to introduce this function.
+
+	* include/freetype/freetype.h, src/base/ftobjs.c (FT_Get_Transform):
+	Implement it.
+
+2021-02-12  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	Decorate `qsort` callbacks with `cdecl`.
+
+	* include/freetype/internal/compiler-macros.h (FT_COMPARE_DEF):
+	Add new macro.
+
+	* src/base/ftrfork.c, src/bdf/bdflib.c, src/gxvalid/gxvcommn.c,
+	src/psaux/afmparse.c, src/psnames/psmodule.c, src/type1/t1afm.c,
+	src/sfnt/sfwoff.c, src/sfnt/sfwoff2.c: Update `qsort` callbacks.
+
+	Fixes #1026 when compiling FreeType with an unusual calling
+	convention while the C library function `qsort` still expects
+	`cdecl`.
+
+2021-02-10  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Implement 'COLR' v1 sweep gradients.
+
+	* freetype.h (FT_PaintSweepGradient): Add `FT_PaintSweepGradient` to
+	represent a 'COLR' v1 sweep gradient.
+	Update format.
+	(FT_PaintFormat): Update shifted paint formats.
+	Sync with spec.
+	* sfnt/ttcolr.c (read_paint): Logic to parse sweep gradients.
+	Fix struct access in radial gradient implementation.
+
+2021-02-09  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Provide optional root transform for 'COLR' v1 glyph graph.
+
+	* include/freetype/freetype.h (FT_Get_Color_Glyph_Paint):
+	Additional function argument `root_transform` to control whether
+	root transform should be returned.
+	(FT_OpaquePaint): Additional tracking field to denote whether
+	root transform is to be returned.
+	* include/freetype/internal/sfnt.h
+	(TT_Get_Color_Glyph_Paint_Func): Propagate additional argument.
+	* src/base/ftobjs.c (FT_Get_Color_Glyph_Paint): Ditto.
+	* src/sfnt/ttcolr.c (tt_face_get_colr_glyph_paint): Return root
+	transform reflecting the size and tranform configured on
+	`FT_Face`.
+	(read_paint): Initialize and track status of insert_root_transform
+	flag.
+
+2021-02-09  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	* meson.build: s/freetype2_dep/freetype_dep/.
+
+	Many projects (e.g., fontconfig, cairo) hardcode the `freetype_dep`
+	variable name to use FreeType as subproject because that was the
+	variable name in Centricular's Meson port of FreeType.  While they
+	should stop hardcoding that variable name, it does not cost us
+	anything to keep using that name to ease transition.
+
+2021-02-09  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	[meson] Fix handling of HarfBuzz library.
+
+	* meson.build (harfbuzz_dep): Do not fall back to HarfBuzz by
+	default.
+
+	Otherwise it causes a dependency cycle:
+
+	  cairo => fontconfig => freetype2 => harfbuzz => cairo
+
+	Meson will still fall back to HarfBuzz subprojects if the `harfbuzz`
+	option is set to `enabled` instead of `auto` and a
+	`subprojects/harfbuzz.wrap` file is present.  In that case it is the
+	responsibility of the main project to set the proper options on each
+	subproject to break the dependency cycle.
+
+	Fixes: #1028.
+
+2021-02-09  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	[meson] Fix dependency lookup and generate `ftconfig.h`.
+
+	- zlib: If not found on the system, meson can build it as a
+	  subproject.  We thus never use the (outdated) zlib support that
+	  comes with FreeType.  Doing so has the additional advantage that
+	  the zlib code can be shared with other projects like GLib if both
+	  are subprojects of an application.
+	- harfbuzz: Build as a subproject if not found on the system.
+	- 'QUESTION: What if the compiler doesn't support `-D` but uses `/D`
+	  instead as on Windows?'  Answer: Meson translate arguments for us.
+	- visibility: Replace self-made code with meson-specific solution.
+
+	* meson.build (ft2_defines): Rewrite logic to set and handle it.
+	(process_header_command): New variable, previously called
+	`ftoption_command`.
+	(ftoption_command, ftconfig_command): New variables.
+	(zlib_option): Removed.
+	(zlib_dep): New variable.
+	(ft2_deps): Updated.
+	(harfbuzz_dep): Updated.
+	(ftconfig_h_in, ftconfig_h): New variables.
+	(ft2_sources): Updated.
+	(ft2_lib): Updated, handle visibility.
+	(summary): Updted.
+
+	* meson_options.txt (zlib): Updated.
+
+2021-02-09  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	* meson.build: Fix resource compilation on Windows.
+
+	This is copied from GStreamer's meson port of FreeType.
+
+	(ft2_sources): Add both debug and resource file (the latter for
+	Windows only).
+	(ft2_debug_src): Removed.
+
+2021-02-09  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	* meson.build: s/ft2_libtool_version/ft2_pkgconfig_version/.
+
+	(freetype2_dep): Use it.
+
+	`ft2_libtool_version` would be the shared library version, not the
+	one we should use in file `freetype2.pc`.
+
+2021-02-09  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	* meson.build: Use `meson.override_dependency`.
+
+	This is a new meson mechanism to avoid other projects to hard-code
+	the `freetype2_dep` variable name in their build definition.  It
+	also ensures that meson does not mix system and subproject versions
+	of FreeType inside of the same project.
+
+	Also remove outdated TODO because `declare_dependency` was already
+	there.
+
+2021-02-09  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	* meson.build (bzip2_dep): Simplify.
+
+	We remove `static:false` from `find_library('bz2')`.
+
+	I don't know whether the previous code was a workaround for an old
+	meson bug, but at least with version >=0.55.0 (which FreeType uses)
+	it picks the shared library when both are available.
+
+	File `freetype2.pc` still contains the full path to file `libbz2.so`
+	instead of `-lbz2` – that we need to do this is a meson bug even
+	present in the current version (0.57.0).
+
+2021-02-09  Xavier Claessens  <xavier.claessens@collabora.com>
+
+	* meson.build: Set project version.
+
+2021-02-04  Werner Lemberg  <wl@gnu.org>
+
+	[base] Fix Netpbm tracing message.
+
+	* src/base/ftobjs.c (FT_Render_Glyph_Internal): Don't emit Netpbm
+	warning if there is nothing to output.
+
+2021-02-04  Werner Lemberg  <wl@gnu.org>
+
+	* src/*: Don't use more than one '\n' in `FT_TRACE` and `FT_ERROR`.
+
+	This ensures good logging output, with all lines having a proper
+	prefix (if requested).
+
+	This is a continuation of a similar patch from 2020-12-02, which
+	missed some locations.
+
+2021-02-03  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* builds/unix/configure.raw [mmap]: Restore default path.
+
+	Fixes #1023.
+
+2021-02-03  Werner Lemberg  <wl@gnu.org>
+
+	[psaux] Fix integer overflow.
+
+	Reported as
+
+	  https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=30154
+
+	* src/psaux/psblues.c (cf2_blues_capture): Use `SUB_INT32`.
+
+2021-02-02  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* builds/unix/configure.raw [mmap support]: Explicitly handle Windows.
+
+	Fixes #1024.
+
+2021-01-31  Werner Lemberg  <wl@gnu.org>
+
+	* builds/unix/configure.raw [mmap support]: Correctly handle Windows.
+
+	Fixes #1024.
+
+2021-01-31  Werner Lemberg  <wl@gnu.org>
+
+	* builds/windows/ftdebug.c: Synchronize with `src/base/ftdebug.c`.
+
+2021-01-31  Werner Lemberg  <wl@gnu.org>
+
+	Always provide logging API.
+
+	It's easier to have stubs if FT_DEBUG_LOGGING is undefined than to
+	modify `ftexport.sym` conditionally.
+
+	Problem reported by Alexei.
+
+	* src/base/ftdebug.c: Include `ftlogging.h`.
+	(FT_Trace_Set_Level, FT_Trace_Set_Default_Level, FT_Set_Log_Handler,
+	FT_Set_Default_Log_Handler) [!FT_DEBUG_LOGGING]: Provide stubs.
+
+2021-01-31  Werner Lemberg  <wl@gnu.org>
+
+	* builds/unix/configure.raw: Fix typo.
+
+	Bug introduced in Vincent's last commit bb33f03.
+
+	Fixes issue #1021.
+
+2021-01-27  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* src/base/ftstroke.c (FT_Stroker_EndSubPath): Ignore tiny gaps.
+
+	Fixes bug #1020.
+
+2021-01-27  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[stroker] Minor clean-up.
+
+	* src/base/ftstroke.c (FT_Stroker_{ConicTo,CubicTo}): Reset the last
+	line length.
+	(FT_Stroker_EndSubPath): Call `ft_stroker_process_corner'.
+
+2021-01-27  Vincent Torri  <vincent.torri@gmail.com>
+
+	* builds/windows/ftsystem.c: Add shared memory support on Windows.
+
+	* CMakeLists.txt (BASE_SRCS), builds/unix/configure.raw (FTSYS_SRC),
+	builds/windows/vc2010/freetype.vcxproj,
+	builds/windows/visualc/freetype.vcproj, meson.build (ft2_sources):
+	Add it (conditionally).
+
+2021-01-23  Werner Lemberg  <wl@gnu.org>
+
+	Require HarfBuzz 2.0.0.
+
+	This is needed to make commit f1f9705f9 work.
+
+	* CMakeLists.txt (HARFBUZZ_MIN_VERSION), builds/unix/configure.raw
+	(harfbuzz_pkg), meson.build (harfbuzz_dep): Updated.
+
+2021-01-22  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* autogen.sh: Absorb `version.sed'.
+	* version.sed: Removed.
+
+2021-01-19  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* srd/base/ftlcdfil.c (FT_Library_SetLcdGeometry): Fix return value.
+
+2021-01-15  Nikolaus Waxweiler  <madigens@gmail.com>
+
+	[afshaper] Fix hb_ot_tags_from_script deprecation warning.
+
+	* autofit/afshaper.c (af_shaper_get_coverage): Copy the source code
+	of the function as suggested in
+	https://github.com/harfbuzz/harfbuzz/issues/2737 and adjust to handle
+	at most three tags.
+
+2021-01-17  Werner Lemberg  <wl@gnu.org>
+
+	* src/tools/update-copyright-year: Fix single-year entry handling.
+
+2021-01-16  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* builds/unix/unixddef.mk: Remove the second DEVEL_DIR definition.
+
+2021-01-14  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Additional checks for 'colr' table presence.
+
+	* sfnt/ttcolr.c (tt_face_get_colr_glyph_paint,
+	tt_face_get_colorline_stops, tt_face_get_paint): Additional checks
+	for whether colr table is present.  Prevents crashes when these
+	methods are called on non-COLR fonts.
+
+2021-01-13  Dominik Röttsches  <drott@chromium.org>
+
+	Add config option to test for 'COLR' v1 support in headers.
+
+	* include/freetype/config/ftoption.h (TT_SUPPORT_COLRV1): New macro
+	so that clients can test whether the FreeType checkout that they are
+	building against supports the 'COLR' v1 API.  This is intended to be
+	a temporary solution until 'COLR' v1 support is released in a
+	FreeType version and such a check can be made by using the version
+	number instead.
+
+2020-12-16  Dominik Röttsches  <drott@chromium.org>
+
+	[base] Fill 'COLR' v1 API templates to make them work (#59703).
+
+	* src/base/ftobjs.c (FT_Get_Color_Glyph_Paint, FT_Get_Paint_Layers,
+	FT_Get_Paint, FT_Get_Colorline_Stops): Add basic sanity checks,
+	check for existence of `FT_Face`, check arguments and delegate calls
+	for the respective 'COLR' v1 API to the SFNT driver.
+
+2020-12-16  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Register 'COLR' v1 API in driver (#59703).
+
+	* include/freetype/internal/sfnt.h (TT_Get_Color_Glyph_Paint_Func,
+	TT_Get_Paint_Layers_Func, TT_Get_Colorline_Stops_Func,
+	TT_Get_Paint_Func): New function pointer types.
+	(SFNT_Interface): Add them.
+	(FT_DEFINE_SFNT_INTERFACE): Updated.
+
+	* src/sfnt/sfdriver.c (PUT_COLOR_LAYERS_V1): New macro.
+	(sfnt_interface): Add new function pointers.
+
+2020-12-16  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Add 'COLR' v1 API to retrieve color layers (#59703).
+
+	* src/sfnt/ttcolr.c (tt_face_get_paint_layers): New function to get
+	the layers of a `PaintColrLayers` table in the font, using an
+	`FT_LayerIterator` from an `FT_PaintColrLayers` object retrieved via
+	`tt_face_get_paint`.
+
+	* src/sfnt/ttcolr.h: Updated.
+
+2020-12-16  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Add 'COLR' v1 API to iterate color stops (#59703).
+
+	* src/sfnt/ttcolr.c (tt_face_get_colorline_stops): New function to
+	return the current `FT_ColorStop` object from `FT_ColorStopIterator`.
+	Also increment the iterator.
+
+	* src/sfnt/ttcolr.h: Updated.
+
+2020-12-16  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Add API to get actual paint from `FT_OpaquePaint` (#59703).
+
+	* src/sfnt/ttcolr.c (tt_face_get_paint): New function to resolve an
+	`FT_OpaquePaint` paint reference into an `FT_COLR_Paint` object of a
+	certain format, which contains the detailed information stored in a
+	paint of the respective format.
+	(read_paint): New function to provide the format specific parsing
+	and to populate the data members of each specific `FT_COLR_Paint`
+	subtype.
+	(read_color_line): New function to parse retrieved color line
+	information into an `FT_ColorLine` object, which has information
+	about the color line extend mode as well as an
+	`FT_ColorStopIterator` object.
+
+	* src/sfnt/ttcolr.h: Updated.
+
+2020-12-16  Dominik Röttsches  <drott@chromium.org>
+
+	[sfnt] Add API to retrieve 'COLR' v1 root paint (#59703).
+
+	* src/sfnt/ttcolr.c (BaseGlyphV1Record): New structure.
+	(tt_face_load_colr): Handle version 1 table header.
+	(find_base_glyph_v1_record): New auxiliary function.
+	(tt_face_get_colr_glyph_paint): New function to find the root
+	`FT_OpaquePaint` object for a given glyph ID.
+
+	* src/sfnt/ttcolr.h: Updated.
+
+2020-12-16  Dominik Röttsches  <drott@chromium.org>
+
+	Add new methods required for 'COLR' v1 to public API (#59703).
+
+	* include/freetype/freetype.h (FT_Get_Color_Glyph_Paint): New method
+	for retrieving the root paint object for a color glyph by specifying
+	a glyph ID.
+	(FT_Get_Paint_Layers): New method for retrieving the layers of a
+	`PaintColorGlyph`.
+	(FT_Get_ColorLine_Stops): New method for retrieving the stops of a
+	color.
+	(FT_Get_Paint): New method for resolving an `FT_OpaquePaint` into an
+	`FT_COLR_Paint` object.
+
+2020-12-16  Dominik Röttsches  <drott@chromium.org>
+
+	Add types required for 'COLR' v1 to public API (#59703).
+
+	* include/freetype/freetype.h (FT_PaintFormat, FT_ColorStopIterator,
+	FT_ColorIndex, FT_ColorStop, FT_PaintExtend, FT_ColorLine,
+	FT_Affine23, FT_CompositeMode, FT_OpaquePaint, FT_PaintColrLayers,
+	FT_PaintSolid, FT_PaintLinearGradient, FT_PaintRadialGradient,
+	FT_PaintGlyph, FT_PaintColrGlyph, FT_PaintTransformed,
+	FT_PaintTranslate, FT_PaintRotate, FT_PaintSkew, FT_PaintComposite,
+	FT_COLR_Paint): Adding structs and enum to represent paint format,
+	color stop information, gradient extend information, structs to
+	reference paint offsets, and to define transforms and compositions.
+	Adding a union type to represent the union of the structs,
+	distinguished by `FT_PaintFormat`.
+
+2021-01-10  Werner Lemberg  <wl@gnu.org>
+
+	* builds/*: s/BUILD_DIR/PLATFORM_DIR/.
+
+	The old variable name caused confusion.
+
+2021-01-08  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[builds] Revert `FTMODULE_H' changes.
+
+	* builds/toplevel.mk, builds/freetype.mk: Revert changes.
+
+2021-01-07  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[builds/windows] Fix up DLG build with VC++.
+
+	* builds/windows/vc2010/script.bat: Copy headers to include/.
+	* builds/windows/vc2010/freetype.vcxproj: Remove DLG paths.
+
+2021-01-07  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[builds] Relocate `FTMODULE_H'.
+
+	* builds/toplevel.mk: Place `FTMODULE_H' in include/.
+	* builds/freetype.mk: Simplify included path.
+
+2021-01-07  Werner Lemberg  <wl@gnu.org>
+
+	Fix ABI incompatibility.
+
+	* include/freetype/ftimage.h (FT_Pixel_Mode): Don't insert
+	`FT_PIXEL_MODE_GRAY16' but append it.
+
+	* src/base/ftobjs.c (pixel_modes): Updated.
+
+2021-01-07  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[dlg] Move the headers to include/dlg to simplify their use.
+
+	* autogen.sh, builds/toplevel.mk: Copy headers to include/dlg.
+	* builds/freetype.mk, builds/windows/vc2010/freetype.vcxproj:
+	Simplify included path.
+	* include/freetype/internal/ftdebug.h: Simplify #include.
+	* src/dlg/rules.mk, .gitignore: Updated.
+
+2021-01-06  Werner Lemberg  <wl@gnu.org>
+
+	* meson.build: Add summary.
+
+	Based on a patch from Vincent Torri <vincent.torri@gmail.com>.
+
+2021-01-06  Torsten Hilbrich  <emacs.nolkaf@hilbrich.tk>
+
+	* meson.build: Fix 'png' build option (#59458).
+
+	Without this patch, 'png' is always required.
+
+2021-01-04  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[builds/windows] Add SDF to VC2010 project.
+
+	* builds/windows/vc2010/freetype.vcxproj: Updated;
+	AfterBuild conveniences.
+
+2020-12-26  Werner Lemberg  <wl@gnu.org>
+
+	[sdf] Use 'counter-clockwise', not 'anti-clockwise'.
+
+	We prefer US nomenclature.
+
+	* src/sdf/ftsdf.c (SDF_Contour_Orientation):
+	s/SDF_ORIENTATION-ACW/SDF_ORIENTATION_CCW/.
+	Update all users.
+
+2020-12-26  Werner Lemberg  <wl@gnu.org>
+
+	* src/base/ftobjs.c (pixel_modes): Updated.
+
+2020-12-26  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Remove custom memory tracker.
+
+	The internal FreeType memory tracker is sufficient.
+
+	* src/sdf/ftsdf.c (FT_DEBUG_INNER, FT_ASSIGNP_INNER, SDF_MemoryUser,
+	sdf_alloc, sdf_free, SDF_ALLOC, SDF_FREE,
+	SDF_MEMORY_TRACKER_DECLARE, SDF_MEMORY_TRACKER_SETUP,
+	SDF_MEMORY_TRACKER_DONE): Removed.
+
+	s/SDF_ALLOC/FT_ALLOC/.
+	s/SDF_FREE/FT_FREE/.
+
+	Other updates.
+
+2020-12-24  Werner Lemberg  <wl@gnu.org>
+
+	[sdf] Fix `make multi`.
+
+	* src/sdf/ftsdf.c: Include `ftoutln.h`.
+
+2020-12-24  Werner Lemberg  <wl@gnu.org>
+
+	[sdf] Fix tracing.
+
+	* include/freetype/internal.fttrace.h: Add 'bsdf' component.
+
+	* src/sdf/ftbsdf.c, src/sdf/ftsdf.c (FT_COMPONENT): Define.
+
+2020-08-21  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add debugging function.
+
+	* src/sdf/ftsdf.c (sdf_shape_dump): New function.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add 'bsdf' renderer to 'sdf' module.
+
+	* src/sdf/ftsdfrend.c (ft_bsdf_render): New function.
+
+	(ft_bitmap_sdf_renderer_class): New structure.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add interface functions for the 'bsdf' rasterizer.
+
+	* src/sdf/ftsdf.c (bsdf_raster_new, bsdf_raster_reset,
+	bsdf_raster_set_mode, bsdf_raster_render, bsdf_raster_done): New
+	functions.
+
+	(ft_bitmap_sdf_raster): New variable.
+
+	* src/sdf/ftsdf.h: Updated.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add function to copy SDF data into output bitmap.
+
+	* src/sdf/ftbsdf.c (finalize_sdf): New function.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add '8-point sequential Euclidean distance mapping' algorithm.
+
+	* src/sdf/ftbsdf.c (compare_neighbor, first_pass, second_pass,
+	edt8): New functions.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add function to copy source bitmap to distance map.
+
+	* src/sdf/ftbsdf.c (bsdf_init_distance_map): New function.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add functions to compute pixel edge distances.
+
+	* src/sdf/ftbsdf.c (compute_edge_distance, bsdf_approximate_edge):
+	New functions.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add function to find edge pixels in a grid of alpha values.
+
+	* src/sdf/ftbsdf.c (bsdf_is_edge): New function.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add essential structures for the 'bsdf' rasterizer.
+
+	* src/sdf/ftbsdf.c (ONE): New macro.
+	(BSDF_TRaster, ED, BSDF_Worker): New structures.
+	(zero_ed): New constant.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add 'sdf' module to non-gnumake build systems.
+
+	* include/freetype/config/ftmodule.h: Add both the 'sdf' and 'bsdf'
+	renderers to the list of modules.
+
+	* CMakeLists.txt (BASE_SRCS): Add 'sdf' single-object module.
+
+2020-08-20  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Added basic overlapping contour support.
+
+	* src/sdf/ftsdf.c (sdf_generate_with_overlaps): New function.
+	(sdf_raster_render): Enable it.
+
+2020-08-19  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add build infrastructure.
+
+	* src/sdf/module.mk, src/sdf/rules.mk: New files.
+
+	* src/sdf/ftsdf.h (ft_sdf_raster): New forward declaration.
+
+	* include/freetype/ftmoderr.h (FT_MODERRDEF): Add error definition
+	for the 'sdf' module.
+
+	* include/freetype/internal/fttrace.h (FT_TRACE_DEF): Add trace
+	definition for the `sdf' module.
+
+	* modules.cfg (RASTER_MODULES): Add the `sdf' module to the list of
+	rasterizers.
+
+2020-08-19  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add interface functions for the 'sdf' rasterizer.
+
+	* src/sdf/ftsdf.c (sdf_raster_new, sdf_raster_reset,
+	sdf_raster_set_mode, sdf_raster_render, sdf_raster_done): New
+	functions.
+	(ft_sdf_raster): New structure.
+
+2020-08-19  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add subdivision and bounding box optimization.
+
+	* src/sdf/ftsdf.c (sdf_generate_bounding_box): New function, which
+	is an optimized version of `sdf_generate`.
+	(sdf_generate_subdivision): New function.
+
+2020-08-19  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add function to generate SDF.
+
+	* src/sdf/ftsdf.c (sdf_generate): New function, currently disabled.
+	This is a proof-of-concept implementation: It doesn't use any
+	optimization, it simply checks all grid points against all contours.
+
+2020-08-19  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add functions to get shortest distance from any edge/contour.
+
+	* src/sdf/ftsdf.c (sdf_edge_get_min_distance): New function.
+	(sdf_contour_get_min_distance): New function, currently disabled.
+
+2020-08-18  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add shortest distance finding functions.
+
+	* src/sdf/ftsdf.c (get_min_distance_line, get_min_distance_conic,
+	get_min_distance_cubic): New functions.  Note that
+	`get_min_distance_conic` comes with two implementations (using an
+	analytical and an iterative method, to be controlled with the
+	`USE_NEWTON_FOR_CONIC` macro).
+
+2020-08-18  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add function to resolve corner distances.
+
+	* src/sdf/ftsdf.c (resolve_corner): New function.
+
+2020-08-18  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add essential math functions.
+
+	* src/sdf/ftsdf.c (cube_root, arc_cos) [!USE_NEWTON_FOR_CONIC]: New
+	auxiliary functions.
+
+	* src/sdf/ftsdf.c (solve_quadratic_equation, solve_cubic_equation)
+	[!USE_NEWTON_FOR_CONIC]: New functions.
+
+2020-08-18  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add utility functions for contours.
+
+	* src/sdf/ftsdf.c (get_control_box, get_contour_orientation): New
+	functions.
+	(split_conic, split_cubic, split_sdf_conic, split_sdf_cubic,
+	split_sdf_shape): New functions.
+
+2020-08-17  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add functions to decompose `FT_Outline`.
+
+	* src/sdf/ftsdf.c (sdf_move_to, sdf_line_to, sdf_conic_to,
+	sdf_cubic_to): New auxiliary decomposition functions.
+	(sdf_compose_funcs): New structure.
+	(sdf_outline_decompose): New function.
+
+2020-08-17  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Structs, enums, macros, and functions for 'sdf' rasterizer.
+
+	* src/sdf/ftsdf.c (FT_DEBUG_INNER, FT_ASSIGNP_INNER)
+	[FT_DEBUG_LEVEL_TRACE && FT_DEBUG_MEMORY]: New macros.
+	(SDF_MemoryUser) [FT_DEBUG_LEVEL_TRACE && FT_DEBUG_MEMORY]: New
+	struct for memory usage tracing.
+	(sdf_alloc, sdf_free) [FT_DEBUG_LEVEL_TRACE && FT_DEBUG_MEMORY]: New
+	functions for memory usage tracing.
+
+	(SDF_ALLOC, SDF_FREE): New macros for memory management.
+	(SDF_MEMORY_TRACKER_DECLARE, SDF_MEMORY_TRACKER_SETUP,
+	SDF_MEMORY_TRACKER_DONE): New macros to set up memory usage tracing.
+
+	(USE_NEWTON_FOR_CONIC, MAX_NEWTON_DIVISIONS, MAX_NEWTON_STEPS,
+	CORNER_CHECK_EPSILON, CG_DIMEN): New configuration macros for
+	controlling the process of finding the shortest distance.
+
+	(MUL_26D6, VEC_26D6_DOT): New auxiliary macros.
+
+	(SDF_TRaster, SDF_Edge, SDF_Contour, SDF_Shape, SDF_Signed_Distance,
+	SDF_Params): New structs for setting up SDF data.
+	(SDF_Edge_Type, SDF_Contour_Orientation): New enums for SDF data.
+
+	(zero_vector, null_edge, null_contour, null_shape, max_sdf): Useful
+	constants.
+
+	(sdf_edge_new, sdf_edge_done, sdf_contour_new, sdf_contour_done,
+	sdf_shape_new, sdf_shape_done): New constructors and destructors.
+
+2020-08-17  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add raster parameters structure.
+
+	* src/sdf/ftsdf.h (SDF_Raster_Params): New structure.
+
+	* src/sdf/sdf.c: Include source files in order to make a single
+	object of the module.
+
+2020-08-17  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add 'sdf' renderer.
+
+	* src/sdf/ftsdf.c: Add 'sdf' renderer along with its interface
+	functions.
+	Also add functions to set and get properties.
+
+2020-08-17  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add common elements for 'sdf' and 'bsdf' renderers.
+
+	* src/sdf/ftsdfrend.h (SDF_Rendere_Module, ft_sdf_renderer_class,
+	ft_bitmap_sdf_renderer_class): New structures.
+
+	* src/sdf/ftsdfcommon.h (DEFAULT_SPREAD, MIN_SPREAD_MAX_SPREAD,
+	USE_SQUARED_DISTANCES): New macros.
+	(FT_INT_26D6, FT_INT_16D16, FT_26D6_16D16): New macros.
+	(FT_CALL, VECTOR_LENGTH_16D16): New macros.
+	(FT_26D6_Vec, FT_16D16_Vec, FT_16D16, FT_26D6, FT_6D10, FT_CBox):
+	New typedefs.
+	(square_root): New macro.
+
+	* src/sdf/ftsdferrs.h: Add module error setup.
+
+2020-08-16  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[sdf] Add files for new 'sdf' module.
+
+	Here is a breakdown of what the files will contain.
+
+	* src/sdf/ftsdfrend.c, src/sdf/ftsdfrend.h: The 'sdf' and 'bsdf'
+	renderers.
+
+	* src/sdf/ftsdf.c, src/sdf/ftsdf.h: The rasterizer for the 'sdf'
+	renderer.
+	* src/sdf/ftbsdf.c, src/sdf/ftbsdf.h: The rasterizer for the 'bsdf'
+	renderer.
+
+	* src/sdf/ftsdfcommon.h: Commmon properties and functions for both
+	rasterizers.
+	* src/sdf/ftsdferrs.h: Common error defines.
+
+	* src/sdf/sdf.c: For building a single object of the entire module.
+
+2020-08-16  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[base] Allow renderers of different formats.
+
+	* src/base/ftobjs.c (FT_Render_Glyph_Internal): Do not return if the
+	glyph's slot format is `FT_GLYPH_FORMAT_BITMAP`.  The forthcoming
+	'bsdf' renderer will require bitmaps for processing.
+
+	* src/base/ftobjs.c (ft_add_renderer, ft_remove_renderer): Remove
+	renderer's glyph format check before adding and removing them.  The
+	'bsdf' renderer will have a format `FT_GLYPH_FORMAT_BITMAP`.
+
+2020-08-16  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	Add data types required for the forthcoming 'sdf' module.
+
+	* include/freetype/freetype.h (FT_Render_Mode): Add new render mode
+	`FT_RENDER_MODE_SDF`, which will be used to generate SDF.
+
+	* include/freetype/ftimage.h (FT_Pixel_Mode): Add new pixel mode
+	`FT_PIXEL_MODE_GRAY16`, which will be the output of the 'sdf'
+	module.
+	(FT_RASTER_FLAG_SDF): New raster flag to be used internally by the
+	'sdf' module.
+
+	* include/freetype/fttypes.h (FT_F6Dot10): New data type.
+
+2020-08-16  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+	[base] Allow renderers of different formats.
+
+	* src/base/ftobjs.c (FT_Render_Glyph_Internal): Do not return if the
+	glyph's slot format is `FT_GLYPH_FORMAT_BITMAP`.  The forthcoming
+	'bsdf' renderer will require bitmaps for processing.
+
+	* src/base/ftobjs.c (ft_add_renderer, ft_remove_renderer): Remove
+	renderer's glyph format check before adding and removing them.  The
+	'bsdf' renderer will have a format `FT_GLYPH_FORMAT_BITMAP`.
+
+2020-12-23  Werner Lemberg  <wl@gnu.org>
+
+	* builds/windows/detect.mk (COPY): Make it work with `shell`.
+
+	Without this patch, we get the error
+
+	  builds/toplevel.mk:127: *** missing separator.  Stop.
+
+	Reported by Anuj, with a solution from Alexei.
+
+2020-12-23  Ignacio Casal Quinteiro  <qignacio@amazon.com>
+
+	* meson.build (ft2_defines): Fix builds on Windows.
+
+2020-12-18  Tatsuyuki Ishi  <ishitatsuyuki@gmail.com>
+
+	[autofit] Fix double division in stem darkening.
+
+	The old code used to divide the darkening amount by em_ratio twice,
+	leading to unnecessarily bold stems on certain fonts with higher
+	units per em (e.g. Inter). This patch fixes it.
+
+	The return value of af_loader_compute_darkening was also changed to
+	use 16.16 fixed point to get rid of a redundant truncation operation.
+	This should slightly improve the precision, although it's still
+	bottlenecked by the emboldening function, which uses 26.6 fixed point.
+
+	* src/autofit/afloader.[ch]
+	(af_loader_compute_darkening): Return FT_Fixed.
+	(af_loader_embolden_glyph_in_slot): Revise calculations.
+
+2020-12-17  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	* include/freetype/ftmodapi.h (FT_FACE_DRIVER_NAME): New public macro.
+
+	The driver name is needed for `FT_Property_Set' and `FT_Property_Get'.
+
+2020-12-16  Chris Liddell  <chris.liddell@artifex.com>
+
+	[truetype] Fix incremental metrics (#59503).
+
+	* src/truetype/ttgload.c (tt_get_metrics, load_truetype_glyph):
+	Previously, the code would populate the phantom points before
+	calling the `get_glyph_metrics` callback.  For formats like PCL XL
+	format 1, class 2 downloaded fonts (where metrics are removed from
+	the TTF header), this causes problems when the hinting program uses
+	the phantom points (misplaced and distorted glyphs) due to the
+	metrics being unset (all zeros).
+	(tt_get_metrics_incr_overrides): Renamed to...
+	(tt_get_metrics_incremental): ... this.  Updated caller
+
+	* include/freetype/ftincrem.h: Update the documentation to make it
+	clearer that `get_glyph_metrics` is to retrieve metrics from a
+	non-standard source, but *not* for the purpose of imposing custom
+	metrics.
+
+2020-12-14  Werner Lemberg  <wl@gnu.org>
+
+	[type42] Pacify static analysis tools (#59682).
+
+	* src/type42/t42objs.c (T42_Size_Init, T42_GlyphSlot_Init): Avoid
+	warnings about uninitialized variables.
+
+2020-12-07  Werner Lemberg  <wl@gnu.org>
+
+	* builds/unix/configure.raw: Don't set `FT_DEBUG_LOGGING`.
+
+	All debug options are handled exclusively in `ftoption.h`.
+
+2020-12-07  Werner Lemberg  <wl@gnu.org>
+
+	* src/*: More fixes for using a '\n' in `FT_TRACE` and `FT_ERROR`.
+
+2020-12-07  Werner Lemberg  <wl@gnu.org>
+
+	*/*: s/FT_LOGGING/FT_DEBUG_LOGGING/.
+
+2020-12-05  Werner Lemberg  <wl@gnu.org>
+
+	* builds/toplevel.mk (do-dist): Remove `submodules` directory.
+
+2020-12-02  Werner Lemberg  <wl@gnu.org>
+
+	* src/*: Don't use more than one '\n' in `FT_TRACE` and `FT_ERROR`.
+
+	This ensures good logging output, with all lines having a proper
+	prefix (if requested).
+
+2020-12-02  Werner Lemberg  <wl@gnu.org>
+
+	[base] Don't close 'stderr' after logging.
+
+	* src/base/ftdebug.c, builds/windows/ftdebug.c (ft_logging_deinit):
+	Fix it.
+
+2020-12-02  Werner Lemberg  <wl@gnu.org>
+
+	* submodules/dlg: Updated to commit 9f0c8b22.
+
+2020-12-02  Werner Lemberg  <wl@gnu.org>
+
+	* src/bdf/bdflib.c: Fix `-Wformat` warning.
+
+2020-12-02  Werner Lemberg  <wl@gnu.org>
+
+	Improve setup for 'dlg' library.
+
+	* autogen.sh (copy_submodule_file), builds/toplevel.mk: Redirect
+	stderr to `/dev/null`.
+
+	* builds/toplevel.mk: Move code block to handle 'dlg' stuff into
+	`check_platform` conditional.
+	Also fix wildcard expressions for guarding `git submodule` commands.
+	Also make file copying work with non-Unix platforms (untested).
+
+2020-12-01  Werner Lemberg  <wl@gnu.org>
+
+	[build] Use gcc (and clang) in C99 mode.
+
+	Other compilers are unchanged.
+
+	* builds/compiler/gcc-dev.mk, builds/compiler/gcc.mk (ANSIFLAGS):
+	s/-ansi/-std=c99/.
+
+	* builds/freetype.mk (FT_CFLAGS): Remove `-std=c99`.
+
+	* builds/unix/configure.raw: Handle C99.
+	Remove no longer needed test for gcc 4.6 and earlier.
+
+2020-12-01  Werner Lemberg  <wl@gnu.org>
+
+	[dlg] Fix compiler warnings.
+
+	* src/dlg/dlgwrap.c: Duplicate some feature test macros from
+	`dlg.c`, which must come first before loading standard headers.  For
+	example, `freetype.h` loads `stdio.h` if compiled in debug mode.
+
+2020-12-01  Werner Lemberg  <wl@gnu.org>
+
+	* src/type42/t42parse.c: Fix `-Wformat` warnings.
+
+2020-12-01  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	[builds/unix] Check for 'pthread' library.
+
+	* builds/unix/ax_pthread.m4: New file, taken from 'autoconf-archive'
+	git repository.
+
+	* builds/unix/configure.raw: Check for 'pthread'; also check whether
+	it works.
+
+2020-12-01  Werner Lemberg  <wl@gnu.org>
+
+	[base] Implement vertical alignment of log printing.
+
+	Based on a patch by Priyesh.
+
+	* include/freetype/internal/fttrace.h (FT_MAX_TRACE_LEVEL_LENGTH):
+	New macro.
+
+	* src/base/ftdebug.c, builds/windows/ftdebug.c (ft_log_handler):
+	Print logs after a fixed width to handle different lengths of
+	`FT_COMPONENT` entries.
+	Use `ft_strrchr` to check for final newline character.
+
+2020-11-30  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	Update logging related documentation.
+
+	* docs/DEBUG: Updates related to `FT_LOGGING`.
+
+	* README.git: Updates related to logging.
+
+2020-11-30  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	* src/*: Fix `-Wformat` warnings.
+
+2020-11-30  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	[builds/windows] Changes to build 'dlg' with FreeType on Windows.
+
+	We only support Visual C++ 2010 and newer.
+
+	* builds/windows/vc2010/script.bat: New windows batch file to copy
+	necessary 'dlg' files from `submodules/dlg` to `src/dlg`.  This file
+	is used as a pre-built event in Visual C++.
+
+	* builds/windows/ftdebug.c: Synchronize with `src/base/ftdebug.c`.
+
+	* builds/windows/vc2010/freetype.vcxproj.filters: Add
+	`src/dlgwrap.c`.
+
+	* builds/windows/vc2010/freetype.vcxproj
+	(AdditionalIncludeDirectories): Add include files of dlg for 'Debug'
+	and 'Debug Static' configurations on both 'x64' and 'win32'
+	platforms.
+	(PreprocessorDefinitions): Add `FT_LOGGING` for 'Debug' and 'Debug
+	Static' configurations on both 'x64' and 'win32' platforms.
+	Add `DLG_STATIC' for 'Debug' configuration on 'x64' and 'win32'
+	platforms.
+	(DisableLanguageExtensions): We need to disable the `/Za` option
+	when building 'dlg' with FreeType as 'dlg' strictly follows the C99
+	standard.  Visual C++ produces behaves unexpectedly when
+	compiling a C99 file with `/Za` option enabled.
+
+2020-11-30  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	[base] Add public API to change log handling function.
+
+	* include/freetype/ftlogging.h (FT_Custom_Log_Handler): New function
+	typedef to store the custom callback logging function.
+	(FT_Set_Log_Handler, FT_Set_Default_Log_Handler): New functions to
+	set and reset custom log handler.
+
+	* include/freetype/internal/ftdebug.h (custom_output_handler): New
+	variable to support a custom callback logging function.
+	(FT_Logging_Callback): A new function typedef to print log using
+	custom callback logging function, which is set using
+	`FT_Set_Log_Handler`.
+	(FT_Log): Use it.
+
+	* src/base/ftdebug.c (FT_Set_Log_Handler,
+	FT_Set_Default_Log_Handler, FT_Logging_Callback): Add function
+	definitions.
+
+2020-11-28  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	[base] Add public API to change the levels of tracing components.
+
+	* include/freetype/ftlogging.h: New header file.
+
+	* include/freetype/internal/ftdebug.h [FT_LOGGING]: Include
+	`ftlogging.h`.
+
+	* src/base/ftdebug.c (ft_custom_trace_level): New variable.
+	(ft_debug_init): Update to support change of levels of tracing
+	components of FreeType at run-time.
+	(FT_Trace_Set_Level): New function to change the levels of tracing
+	components at run-time.
+	(FT_Trace_Set_Default_Level): New function to reset the levels of
+	tracing components back to default.
+
+2020-11-28  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	[base] Updates to print timestamp and name of `FT_COMPONENT` in logs.
+
+	* include/freetype/internal/ftdebug.h (FT_LOGGING_TAG,
+	FT_LOGGING_TAG_): New macros to resolve the value of `FT_COMPONENT'
+	into a string.
+	(ft_add_tag, ft_remove_tag): New functions to add and remove dlg tags.
+
+	* src/base/ftdebug.c: Add new variables to control the logging of
+	timestamp and name of `FT_COMPONENT` along with actual logs.
+	(ft_add_tag, ft_remove_tag): Add function definitions.
+	(ft_log_handler): Updates to print timestamp and name of
+	`FT_COMPONENT`.
+	(ft_debug_init) [FT_LOGGING]: Users can now control the logging of
+	timestamp and name of `FT_COMPONENT` by adding tags in the
+	`FT2_DEBUG` environment variable.
+
+2020-11-27  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	[base] Add functions and variables to print logs to a file.
+
+	* include/freetype/internal/ftdebug.h: Added dlg's header files.
+	(FT_LOG): New macro to redirect trace logs to dlg's API's whenever
+	`FT_LOGGING' is defined.
+	(ft_logging_init, ft_logging_deinit): New functions to handle
+	initialization and uninitialization of logging related variables.
+	(ft_log_handler): New function to handle logs of FreeType.
+
+	* src/base/ftdebug.c: Add necessary logging related variables.
+	(ft_logging_init, ft_logging_deinit, ft_log_handler): Add function
+	definitions.
+
+	* src/base/ftinit.c (FT_Init_FreeType) [FT_LOGGING]: Call
+	`ft_logging_init`.
+	(FT_Done_FreeType) [FT_LOGGING]: Call `ft_logging_deinit`.
+
+	* src/base/ftobjs.c (FT_New_Library): Call `ft_debug_init` only if
+	`FT_LOGGING` is not defined.
+
+2020-11-27  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	[builds] Necessary changes to make 'dlg' compile.
+
+	* autogen.sh (copy_submodule_files): New script to copy all the
+	necessary source and include files from `submodules/dlg` to
+	`src/dlg`.
+
+	* src/dlg/dlgwrap.c: New wrapper file for `src/dlg.c`.  It enables
+	the build of 'dlg' if the `FT_LOGGING` macro is defined.
+
+	* src/dlg/rules.mk: New sub-Makefile.
+
+	* builds/freetype.mk (DLG_DIR): New variable to include the
+	header files of the 'dlg' library.
+	(INCLUDES): Add `DLG_DIR`.
+	(FT_CFLAGS): Add `-std=c99' flag.
+	Include `src/dlg/rules.mk` file to build 'dlg' library.
+	(OBJ_S, OBJ_M): Add `DLG_OBJS_M` and `DLG_OBJS_S`.
+
+	* builds/toplevel.mk: For builds directly from the git repository
+	we need to copy files from `submodule/dlg` to `src/dlg`.
+
+	* include/freetype/config/ftoption.h, devel/ftoption.h (FT_LOGGING):
+	New macro to enable or disable the logging facility in FreeType.
+
+2020-11-27  Priyesh Kumar  <priyeshkkumar@gmail.com>
+
+	* .gitmodules: Add 'dlg' library's git repository as submodule.
+
+2020-12-01  Werner Lemberg  <wl@gnu.org>
+
+	* src/tools/chktrcmp.py (trace_use_pat): Update to current use.
+
+2020-11-20  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
+	[cff,cid,type1] Demote old engine for lack of CFF2.
+
+	* src/cff/cffobjs.c (cff_driver_init): Always default to Adobe engine.
+	* src/cid/cidobjs.c (cid_driver_init): Ditto.
+	* src/type1/t1objs.c (T1_Driver_Init): Ditto.
+
+2020-11-09  Werner Lemberg  <wl@gnu.org>
+
+	* src/type42/t42parse.c (t42_parse_sfnts): More tracing messages.
+
+2020-11-04  Werner Lemberg  <wl@gnu.org>
+
+	* meson.build: Fix .pc file generation.
+
+	For backwards compatibility we need the libtool version, not the .so
+	number.
+
+	Reported by Nikolaus.
+
+2020-10-28  Werner Lemberg  <wl@gnu.org>
+
+	[truetype] Minor update to forthcoming OpenType 1.8.4 standard.
+
+	* src/truetype/ttgxvar.c (ft_var_load_item_variation_store): Limit
+	size of `regionCount`.
+
+2020-10-26  Werner Lemberg  <wl@gnu.org>
+
+	* meson.build: Fix 'harfbuzz' and 'brotli' build options (#59347).
+
+	Without this patch, 'harfbuzz' and 'brotli' are always required.
+
+	Patch submitted anonymously in Savannah bug report.
+
+2020-10-23  Ben Wagner  <bungeman@google.com>
+
+	* src/sfnt/pngshim.c (Load_SBit_Png): Fix memory leak (#59322).
+
+	The issue is that `rows` is allocated but will not be freed in the
+	event that the call to `png_read_image` fails and calls `longjmp`.
+
 2020-10-20  Werner Lemberg  <wl@gnu.org>
 
 	* Version 2.10.4 released.
@@ -875,7 +3624,7 @@
 	security or bug fixes will be provided for those versions.  See
 
 	  https://devguide.python.org/#status-of-python-branches
-	
+
 	for more information.
 
 	* Jamfile (RefDoc): Add `site' parameter.
@@ -5050,7 +7799,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2018-2020 by
+Copyright (C) 2018-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.22 b/docs/oldlogs/ChangeLog.22
similarity index 99%
rename from ChangeLog.22
rename to docs/oldlogs/ChangeLog.22
index 86662f6..e25cafc 100644
--- a/ChangeLog.22
+++ b/docs/oldlogs/ChangeLog.22
@@ -2821,7 +2821,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2005-2020 by
+Copyright (C) 2005-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.23 b/docs/oldlogs/ChangeLog.23
similarity index 99%
rename from ChangeLog.23
rename to docs/oldlogs/ChangeLog.23
index 4c80504..0e32ca8 100644
--- a/ChangeLog.23
+++ b/docs/oldlogs/ChangeLog.23
@@ -7932,7 +7932,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2006-2020 by
+Copyright (C) 2006-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.24 b/docs/oldlogs/ChangeLog.24
similarity index 99%
rename from ChangeLog.24
rename to docs/oldlogs/ChangeLog.24
index 17e98c4..9d06b0f 100644
--- a/ChangeLog.24
+++ b/docs/oldlogs/ChangeLog.24
@@ -6344,7 +6344,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2010-2020 by
+Copyright (C) 2010-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.25 b/docs/oldlogs/ChangeLog.25
similarity index 99%
rename from ChangeLog.25
rename to docs/oldlogs/ChangeLog.25
index 6e04427..5d0371c 100644
--- a/ChangeLog.25
+++ b/docs/oldlogs/ChangeLog.25
@@ -5145,7 +5145,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2013-2020 by
+Copyright (C) 2013-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.26 b/docs/oldlogs/ChangeLog.26
similarity index 99%
rename from ChangeLog.26
rename to docs/oldlogs/ChangeLog.26
index a4fc060..eb87803 100644
--- a/ChangeLog.26
+++ b/docs/oldlogs/ChangeLog.26
@@ -5695,7 +5695,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2015-2020 by
+Copyright (C) 2015-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.27 b/docs/oldlogs/ChangeLog.27
similarity index 99%
rename from ChangeLog.27
rename to docs/oldlogs/ChangeLog.27
index c59ed7b..c5fb1f9 100644
--- a/ChangeLog.27
+++ b/docs/oldlogs/ChangeLog.27
@@ -2090,7 +2090,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2016-2020 by
+Copyright (C) 2016-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.28 b/docs/oldlogs/ChangeLog.28
similarity index 99%
rename from ChangeLog.28
rename to docs/oldlogs/ChangeLog.28
index b17a751..d7cc2e0 100644
--- a/ChangeLog.28
+++ b/docs/oldlogs/ChangeLog.28
@@ -3120,7 +3120,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2016-2020 by
+Copyright (C) 2016-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/ChangeLog.29 b/docs/oldlogs/ChangeLog.29
similarity index 99%
rename from ChangeLog.29
rename to docs/oldlogs/ChangeLog.29
index 251c056..e668b4f 100644
--- a/ChangeLog.29
+++ b/docs/oldlogs/ChangeLog.29
@@ -2336,7 +2336,7 @@
 
 ----------------------------------------------------------------------------
 
-Copyright (C) 2017-2020 by
+Copyright (C) 2017-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This file is part of the FreeType project, and may only be used, modified,
diff --git a/docs/raster.txt b/docs/raster.txt
index 1bf4f67..72d9fe2 100644
--- a/docs/raster.txt
+++ b/docs/raster.txt
@@ -618,7 +618,7 @@
 
 ------------------------------------------------------------------------
 
-Copyright (C) 2003-2020 by
+Copyright (C) 2003-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file  is  part  of the  FreeType  project, and may  only be  used,
diff --git a/docs/release b/docs/release
index 628dded..05f730f 100644
--- a/docs/release
+++ b/docs/release
@@ -1,26 +1,23 @@
 How to prepare a new release
 ----------------------------
 
-. include/freetype/freetype.h:  Update FREETYPE_MAJOR, FREETYPE_MINOR,
-  and FREETYPE_PATCH.
+. include/freetype/freetype.h: Update `FREETYPE_MAJOR`,
+  `FREETYPE_MINOR`, and `FREETYPE_PATCH`.
 
 . Update version numbers in all files where necessary (for example, do
-  a grep for both `2.3.1' and `231' for release 2.3.1).
+  a grep for both '2.10.4' and '2104' for release 2.10.4).
 
-. builds/unix/configure.raw: Update `version_info'.
+. builds/unix/configure.raw: Update `version_info`.
 
 . docs/CHANGES: Document differences to last release.
 
 . README: Update.
 
-. docs/VERSIONS.TXT: Document changed `version_info'.
-
-. ChangeLog:   Announce  new  release   (both  in  the  freetype2  and
-  freetype2-demos modules).
+. docs/VERSIONS.TXT: Document changed `version_info`.
 
 . Clone the git archive to another directory with
 
-    git clone -l -s . ../freetype2.test
+    git clone -l -s . ../freetype.test
 
   or something like this and run
 
@@ -35,14 +32,14 @@
 
   in the cloned repository to test compilation with both gcc and g++.
 
-. Test C++ compilation  for freetype2-demos too  (using `git clone' as
+. Test C++ compilation for 'freetype-demos' too (using `git clone` as
   above).
 
-. Run  src/tools/chktrcmp.py  and check  that there  are no  undefined
-  trace_XXXX macros.
+. Run `src/tools/chktrcmp.py` and check that there are no undefined
+  `trace_XXXX` macros.
 
-. After pushing the new release,  tag the git repositories (freetype2,
-  freetype2-demos) with
+. After pushing the new release, tag the git repositories ('freetype',
+  'freetype-demos') with
 
     git tag VER-<version> -m "" -u <committer>
 
@@ -54,29 +51,29 @@
 
     git clean -ndx
 
-  that the git directory is really clean  (and remove extraneous files
+  that the git directory is really clean (and remove extraneous files
   if necessary).
 
-. Say `make  dist' in both the  freetype2 and freetype2-demos  modules
-  to generate the .tar.gz, .tar.xz, and .zip files.
+. Say `make dist` in both the 'freetype' and 'freetype-demos'
+  repositories to generate the `.tar.gz`, `.tar.xz`, and `.zip` files.
 
-. Create     the     doc    bundles    (freetype-doc-<version>.tar.gz,
-  freetype-doc-<version>.tar.xz,    ftdoc<version>.zip).    This    is
+. Create the doc bundles (`freetype-doc-<version>.tar.gz`,
+  `freetype-doc-<version>.tar.xz`, `ftdoc<version>.zip`).  This is
   everything in
 
     <freetype-web git repository>/freetype2/docs
 
-  except the `reference' subdirectory.   Do *not* use option `-l' from
+  except the `reference` subdirectory.  Do *not* use option `-l` from
   zip!
 
-. Run the following script (with updated `$VERSION', `$SAVANNAH_USER',
-  and $SOURCEFORGE_USER  variables) to sign and upload the  bundles to
+. Run the following script (with updated `$VERSION`, `$SAVANNAH_USER`,
+  and `$SOURCEFORGE_USER` variables) to sign and upload the bundles to
   both Savannah and SourceForge.  The signing code has been taken from
-  the `gnupload' script (part of the automake bundle).
+  the `gnupload` script (part of the 'automake' bundle).
 
     #!/bin/sh
 
-    VERSION=2.5.1
+    VERSION=2.10.4
     SAVANNAH_USER=wl
     SOURCEFORGE_USER=wlemb
 
@@ -155,12 +152,13 @@
 
     # EOF
 
-. Prepare a  README for SourceForge  and upload it  with the following
-  script (with updated `$VERSION' and $SOURCEFORGE_USER variables).
+. Prepare a `README` file for SourceForge and upload it with the
+  following script (with updated `$VERSION` and `$SOURCEFORGE_USER`
+  variables).
 
     #!/bin/sh
 
-    VERSION=2.5.1
+    VERSION=2.10.4
     SOURCEFORGE_USER=wlemb
 
     #####################################################################
@@ -170,26 +168,20 @@
 
     # EOF
 
-. On   SourceForge,   tag   the    just   uploaded   `ftXXX.zip'   and
-  `freetype-XXX.tar.xz'  files as the  default files to  download  for
-  `Windows' and `Others', respectively.
+. On SourceForge, tag the just uploaded `ftXXX.zip` and
+  `freetype-XXX.tar.xz` files as the default files to download for
+  'Windows' and 'Others', respectively.
 
-. Copy the reference files (generated by `make dist') to
+. Trigger the automatic generation of the online API reference by
+  updating the `FT_VERSION` variable in file `.gitlab-ci.yml` of the
+  'freetype-web' repository.
 
-    <freetype-web git repository>/freetype2/docs/reference
-
-. Update the `freetype-web' repository.  `git push' then automatically
-  triggers an update  of the public web pages  within ten minutes, due
-  to a cron script (on wl@freedesktop.org) that rsyncs with
-
-    freedesktop.org://srv/freetype.freedesktop.org/www
-
-. Announce new release on freetype-announce@nongnu.org and to relevant
-  newsgroups.
+. Announce new release on 'freetype-announce@nongnu.org' and to
+  relevant newsgroups.
 
 ----------------------------------------------------------------------
 
-Copyright (C) 2003-2020 by
+Copyright (C) 2003-2021 by
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
 This  file is  part of  the FreeType  project, and  may only  be used,
diff --git a/include/freetype/config/ftconfig.h b/include/freetype/config/ftconfig.h
index b464e0b..65effcb 100644
--- a/include/freetype/config/ftconfig.h
+++ b/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
  *
  *   ANSI-specific configuration file (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h
index 28b5cc6..e46d314 100644
--- a/include/freetype/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
  *
  *   Build macros of the FreeType 2 library.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/config/ftmodule.h b/include/freetype/config/ftmodule.h
index d604afb..84b468e 100644
--- a/include/freetype/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
@@ -19,12 +19,14 @@
 //FT_USE_MODULE( FT_Driver_ClassRec, t42_driver_class )
 //FT_USE_MODULE( FT_Driver_ClassRec, winfnt_driver_class )
 //FT_USE_MODULE( FT_Driver_ClassRec, pcf_driver_class )
+//FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
 FT_USE_MODULE( FT_Module_Class, psaux_module_class )
 FT_USE_MODULE( FT_Module_Class, psnames_module_class )
 FT_USE_MODULE( FT_Module_Class, pshinter_module_class )
-FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
 FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
 FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
-//FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_bitmap_sdf_renderer_class )
 
 /* EOF */
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index 3c7b71b..c7e46b5 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
  *
  *   User-selectable configuration macros (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -105,8 +105,7 @@
    *
    * ```
    *   FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
-   *                       cff:no-stem-darkening=1 \
-   *                       autofitter:warping=1
+   *                       cff:no-stem-darkening=1
    * ```
    *
    */
@@ -436,6 +435,23 @@
 
   /**************************************************************************
    *
+   * Logging
+   *
+   *   Compiling FreeType in debug or trace mode makes FreeType write error
+   *   and trace log messages to `stderr`.  Enabling this macro
+   *   automatically forces the `FT_DEBUG_LEVEL_ERROR` and
+   *   `FT_DEBUG_LEVEL_TRACE` macros and allows FreeType to write error and
+   *   trace log messages to a file instead of `stderr`.  For writing logs
+   *   to a file, FreeType uses an the external `dlg` library (the source
+   *   code is in `src/dlg`).
+   *
+   *   This option needs a C99 compiler.
+   */
+/* #define FT_DEBUG_LOGGING */
+
+
+  /**************************************************************************
+   *
    * Autofitter debugging
    *
    *   If `FT_DEBUG_AUTOFIT` is defined, FreeType provides some means to
@@ -900,24 +916,6 @@
 
   /**************************************************************************
    *
-   * Compile 'autofit' module with warp hinting.  The idea of the warping
-   * code is to slightly scale and shift a glyph within a single dimension so
-   * that as much of its segments are aligned (more or less) on the grid.  To
-   * find out the optimal scaling and shifting value, various parameter
-   * combinations are tried and scored.
-   *
-   * You can switch warping on and off with the `warping` property of the
-   * auto-hinter (see file `ftdriver.h` for more information; by default it
-   * is switched off).
-   *
-   * This experimental option is not active if the rendering mode is
-   * `FT_RENDER_MODE_LIGHT`.
-   */
-#define AF_CONFIG_OPTION_USE_WARPER
-
-
-  /**************************************************************************
-   *
    * Use TrueType-like size metrics for 'light' auto-hinting.
    *
    * It is strongly recommended to avoid this option, which exists only to
@@ -968,6 +966,21 @@
 
 
   /*
+   * The TT_SUPPORT_COLRV1 macro is defined to indicate to clients that this
+   * version of FreeType has support for 'COLR' v1 API.  This definition is
+   * useful to FreeType clients that want to build in support for 'COLR' v1
+   * depending on a tip-of-tree checkout before it is officially released in
+   * FreeType, and while the feature cannot yet be tested against using
+   * version macros.  Don't change this macro.  This may be removed once the
+   * feature is in a FreeType release version and version macros can be used
+   * to test for availability.
+   */
+#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
+#define  TT_SUPPORT_COLRV1
+#endif
+
+
+  /*
    * Check CFF darkening parameters.  The checks are the same as in function
    * `cff_property_set` in file `cffdrivr.c`.
    */
diff --git a/include/freetype/config/ftstdlib.h b/include/freetype/config/ftstdlib.h
index d6091f8..6ee412a 100644
--- a/include/freetype/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
  *   ANSI-specific library and header configuration file (specification
  *   only).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -43,7 +43,8 @@
    *
    * `UINT_MAX` and `ULONG_MAX` are used to automatically compute the size of
    * `int` and `long` in bytes at compile-time.  So far, this works for all
-   * platforms the library has been tested on.
+   * platforms the library has been tested on.  We also check `ULLONG_MAX`
+   * to see whether we can use 64-bit `long long` later on.
    *
    * Note that on the extremely rare platforms that do not provide integer
    * types that are _exactly_ 16 and 32~bits wide (e.g., some old Crays where
@@ -66,6 +67,15 @@
 #define FT_LONG_MIN    LONG_MIN
 #define FT_LONG_MAX    LONG_MAX
 #define FT_ULONG_MAX   ULONG_MAX
+#ifdef LLONG_MAX
+#define FT_LLONG_MAX   LLONG_MAX
+#endif
+#ifdef LLONG_MIN
+#define FT_LLONG_MIN   LLONG_MIN
+#endif
+#ifdef ULLONG_MAX
+#define FT_ULLONG_MAX  ULLONG_MAX
+#endif
 
 
   /**************************************************************************
diff --git a/include/freetype/config/integer-types.h b/include/freetype/config/integer-types.h
index a0ca0c9..5ef09f1 100644
--- a/include/freetype/config/integer-types.h
+++ b/include/freetype/config/integer-types.h
@@ -4,7 +4,7 @@
  *
  *   FreeType integer types definitions.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -60,6 +60,18 @@
 
 #endif /* !defined(FT_SIZEOF_LONG) */
 
+#ifndef FT_SIZEOF_LONG_LONG
+
+  /* The size of a `long long` type if available */
+#if defined( FT_ULLONG_MAX ) && FT_ULLONG_MAX >= 0xFFFFFFFFFFFFFFFFULL
+#define FT_SIZEOF_LONG_LONG  ( 64 / FT_CHAR_BIT )
+#else
+#define FT_SIZEOF_LONG_LONG  0
+#endif
+
+#endif /* !defined(FT_SIZEOF_LONG_LONG) */
+
+
   /**************************************************************************
    *
    * @section:
@@ -174,15 +186,17 @@
 #endif
 
 
-  /* determine whether we have a 64-bit `int` type for platforms without */
-  /* Autoconf                                                            */
+  /* determine whether we have a 64-bit integer type */
 #if FT_SIZEOF_LONG == ( 64 / FT_CHAR_BIT )
 
-  /* `FT_LONG64` must be defined if a 64-bit type is available */
-#define FT_LONG64
 #define FT_INT64   long
 #define FT_UINT64  unsigned long
 
+#elif FT_SIZEOF_LONG_LONG >= ( 64 / FT_CHAR_BIT )
+
+#define FT_INT64   long long int
+#define FT_UINT64  unsigned long long int
+
   /**************************************************************************
    *
    * A 64-bit data type may create compilation problems if you compile in
@@ -192,16 +206,9 @@
    */
 #elif !defined( __STDC__ ) || defined( FT_CONFIG_OPTION_FORCE_INT64 )
 
-#if defined( __STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L
-
-#define FT_LONG64
-#define FT_INT64   long long int
-#define FT_UINT64  unsigned long long int
-
-#elif defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
+#if defined( _MSC_VER ) && _MSC_VER >= 900 /* Visual C++ (and Intel C++) */
 
   /* this compiler provides the `__int64` type */
-#define FT_LONG64
 #define FT_INT64   __int64
 #define FT_UINT64  unsigned __int64
 
@@ -211,7 +218,6 @@
   /*       to test the compiler version.                                 */
 
   /* this compiler provides the `__int64` type */
-#define FT_LONG64
 #define FT_INT64   __int64
 #define FT_UINT64  unsigned __int64
 
@@ -221,22 +227,20 @@
 
 #elif defined( __MWERKS__ )    /* Metrowerks CodeWarrior */
 
-#define FT_LONG64
 #define FT_INT64   long long int
 #define FT_UINT64  unsigned long long int
 
 #elif defined( __GNUC__ )
 
   /* GCC provides the `long long` type */
-#define FT_LONG64
 #define FT_INT64   long long int
 #define FT_UINT64  unsigned long long int
 
-#endif /* __STDC_VERSION__ >= 199901L */
+#endif /* !__STDC__ */
 
 #endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
 
-#ifdef FT_LONG64
+#ifdef FT_INT64
   typedef FT_INT64   FT_Int64;
   typedef FT_UINT64  FT_UInt64;
 #endif
diff --git a/include/freetype/config/mac-support.h b/include/freetype/config/mac-support.h
index 9486708..ef58d8b 100644
--- a/include/freetype/config/mac-support.h
+++ b/include/freetype/config/mac-support.h
@@ -4,7 +4,7 @@
  *
  *   Mac/OS X support configuration header.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/config/public-macros.h b/include/freetype/config/public-macros.h
index 6aa673e..9fbb327 100644
--- a/include/freetype/config/public-macros.h
+++ b/include/freetype/config/public-macros.h
@@ -4,7 +4,7 @@
  *
  *   Define a set of compiler macros used in public FreeType headers.
  *
- * Copyright (C) 2020 by
+ * Copyright (C) 2020-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -103,6 +103,7 @@
    */
 #define FT_EXPORT( x )  FT_PUBLIC_FUNCTION_ATTRIBUTE extern x
 
+
   /*
    * `FT_UNUSED` indicates that a given parameter is not used -- this is
    * only used to get rid of unpleasant compiler warnings.
@@ -115,6 +116,23 @@
 #endif
 
 
+  /*
+   * Support for casts in both C and C++.
+   */
+#ifdef __cplusplus
+#define FT_STATIC_CAST( type, var )       static_cast<type>(var)
+#define FT_REINTERPRET_CAST( type, var )  reinterpret_cast<type>(var)
+
+#define FT_STATIC_BYTE_CAST( type, var )                         \
+          static_cast<type>( static_cast<unsigned char>( var ) )
+#else
+#define FT_STATIC_CAST( type, var )       (type)(var)
+#define FT_REINTERPRET_CAST( type, var )  (type)(var)
+
+#define FT_STATIC_BYTE_CAST( type, var )  (type)(unsigned char)(var)
+#endif
+
+
 FT_END_HEADER
 
 #endif  /* FREETYPE_CONFIG_PUBLIC_MACROS_H_ */
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index be191f5..f6c66b9 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -4,7 +4,7 @@
  *
  *   FreeType high-level API and common types (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -33,6 +33,34 @@
   /**************************************************************************
    *
    * @section:
+   *   preamble
+   *
+   * @title:
+   *   Preamble
+   *
+   * @abstract:
+   *   What FreeType is and isn't
+   *
+   * @description:
+   *   FreeType is a library that provides access to glyphs in font files.  It
+   *   scales the glyph images and their metrics to a requested size, and it
+   *   rasterizes the glyph images to produce pixel or subpixel alpha coverage
+   *   bitmaps.
+   *
+   *   Note that FreeType is _not_ a text layout engine.  You have to use
+   *   higher-level libraries like HarfBuzz, Pango, or ICU for that.
+   *
+   *   Note also that FreeType does _not_ perform alpha blending or
+   *   compositing the resulting bitmaps or pixmaps by itself.  Use your
+   *   favourite graphics library (for example, Cairo or Skia) to further
+   *   process FreeType's output.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @section:
    *   header_inclusion
    *
    * @title:
@@ -176,6 +204,7 @@
    *   FT_Size_RequestRec
    *   FT_Size_Request
    *   FT_Set_Transform
+   *   FT_Get_Transform
    *   FT_Load_Glyph
    *   FT_Get_Char_Index
    *   FT_Get_First_Char
@@ -587,11 +616,12 @@
    */
 
 #ifndef FT_ENC_TAG
-#define FT_ENC_TAG( value, a, b, c, d )         \
-          value = ( ( (FT_UInt32)(a) << 24 ) |  \
-                    ( (FT_UInt32)(b) << 16 ) |  \
-                    ( (FT_UInt32)(c) <<  8 ) |  \
-                      (FT_UInt32)(d)         )
+
+#define FT_ENC_TAG( value, a, b, c, d )                             \
+          value = ( ( FT_STATIC_BYTE_CAST( FT_UInt32, a ) << 24 ) | \
+                    ( FT_STATIC_BYTE_CAST( FT_UInt32, b ) << 16 ) | \
+                    ( FT_STATIC_BYTE_CAST( FT_UInt32, c ) <<  8 ) | \
+                      FT_STATIC_BYTE_CAST( FT_UInt32, d )         )
 
 #endif /* FT_ENC_TAG */
 
@@ -701,11 +731,16 @@
    *     Same as FT_ENCODING_JOHAB.  Deprecated.
    *
    * @note:
-   *   By default, FreeType enables a Unicode charmap and tags it with
-   *   `FT_ENCODING_UNICODE` when it is either provided or can be generated
-   *   from PostScript glyph name dictionaries in the font file.  All other
-   *   encodings are considered legacy and tagged only if explicitly defined
-   *   in the font file.  Otherwise, `FT_ENCODING_NONE` is used.
+   *   When loading a font, FreeType makes a Unicode charmap active if
+   *   possible (either if the font provides such a charmap, or if FreeType
+   *   can synthesize one from PostScript glyph name dictionaries; in either
+   *   case, the charmap is tagged with `FT_ENCODING_UNICODE`).  If such a
+   *   charmap is synthesized, it is placed at the first position of the
+   *   charmap array.
+   *
+   *   All other encodings are considered legacy and tagged only if
+   *   explicitly defined in the font file.  Otherwise, `FT_ENCODING_NONE` is
+   *   used.
    *
    *   `FT_ENCODING_NONE` is set by the BDF and PCF drivers if the charmap is
    *   neither Unicode nor ISO-8859-1 (otherwise it is set to
@@ -2065,7 +2100,8 @@
    *     The size in bytes of the file in memory.
    *
    *   pathname ::
-   *     A pointer to an 8-bit file pathname.  The pointer is not owned by
+   *     A pointer to an 8-bit file pathname, which must be a C~string (i.e.,
+   *     no null bytes except at the very end).  The pointer is not owned by
    *     FreeType.
    *
    *   stream ::
@@ -2084,8 +2120,7 @@
    *     Extra parameters passed to the font driver when opening a new face.
    *
    * @note:
-   *   The stream type is determined by the contents of `flags` that are
-   *   tested in the following order by @FT_Open_Face:
+   *   The stream type is determined by the contents of `flags`:
    *
    *   If the @FT_OPEN_MEMORY bit is set, assume that this is a memory file
    *   of `memory_size` bytes, located at `memory_address`.  The data are not
@@ -2098,6 +2133,9 @@
    *   Otherwise, if the @FT_OPEN_PATHNAME bit is set, assume that this is a
    *   normal file and use `pathname` to open it.
    *
+   *   If none of the above bits are set or if multiple are set at the same
+   *   time, the flags are invalid and @FT_Open_Face fails.
+   *
    *   If the @FT_OPEN_DRIVER bit is set, @FT_Open_Face only tries to open
    *   the file with the driver whose handler is in `driver`.
    *
@@ -2150,6 +2188,13 @@
    *   FreeType error code.  0~means success.
    *
    * @note:
+   *   The `pathname` string should be recognizable as such by a standard
+   *   `fopen` call on your system; in particular, this means that `pathname`
+   *   must not contain null bytes.  If that is not sufficient to address all
+   *   file name possibilities (for example, to handle wide character file
+   *   names on Windows in UTF-16 encoding) you might use @FT_Open_Face to
+   *   pass a memory array or a stream object instead.
+   *
    *   Use @FT_Done_Face to destroy the created @FT_Face object (along with
    *   its slot and sizes).
    */
@@ -2270,6 +2315,10 @@
    *   See the discussion of reference counters in the description of
    *   @FT_Reference_Face.
    *
+   *   If `FT_OPEN_STREAM` is set in `args->flags`, the stream in
+   *   `args->stream` is automatically closed before this function returns
+   *   any error (including `FT_Err_Invalid_Argument`).
+   *
    * @example:
    *   To loop over all faces, use code similar to the following snippet
    *   (omitting the error handling).
@@ -2428,6 +2477,7 @@
    *
    * @since:
    *   2.4.2
+   *
    */
   FT_EXPORT( FT_Error )
   FT_Reference_Face( FT_Face  face );
@@ -2874,7 +2924,7 @@
    *
    *     If the font is 'tricky' (see @FT_FACE_FLAG_TRICKY for more), using
    *     `FT_LOAD_NO_SCALE` usually yields meaningless outlines because the
-   *     subglyphs must be scaled and positioned with hinting instructions. 
+   *     subglyphs must be scaled and positioned with hinting instructions.
    *     This can be solved by loading the font without `FT_LOAD_NO_SCALE`
    *     and setting the character size to `font->units_per_EM`.
    *
@@ -3132,7 +3182,7 @@
    *   necessary to empty the cache after a mode switch to avoid false hits.
    *
    */
-#define FT_LOAD_TARGET_( x )   ( (FT_Int32)( (x) & 15 ) << 16 )
+#define FT_LOAD_TARGET_( x )   ( FT_STATIC_CAST( FT_Int32, (x) & 15 ) << 16 )
 
 #define FT_LOAD_TARGET_NORMAL  FT_LOAD_TARGET_( FT_RENDER_MODE_NORMAL )
 #define FT_LOAD_TARGET_LIGHT   FT_LOAD_TARGET_( FT_RENDER_MODE_LIGHT  )
@@ -3151,7 +3201,8 @@
    *   @FT_LOAD_TARGET_XXX value.
    *
    */
-#define FT_LOAD_TARGET_MODE( x )  ( (FT_Render_Mode)( ( (x) >> 16 ) & 15 ) )
+#define FT_LOAD_TARGET_MODE( x )                               \
+          FT_STATIC_CAST( FT_Render_Mode, ( (x) >> 16 ) & 15 )
 
 
   /**************************************************************************
@@ -3172,11 +3223,12 @@
    *     A pointer to the transformation's 2x2 matrix.  Use `NULL` for the
    *     identity matrix.
    *   delta ::
-   *     A pointer to the translation vector.  Use `NULL` for the null vector.
+   *     A pointer to the translation vector.  Use `NULL` for the null
+   *     vector.
    *
    * @note:
    *   This function is provided as a convenience, but keep in mind that
-   *   @FT_Matrix coefficients are only 16.16 fixed point values, which can
+   *   @FT_Matrix coefficients are only 16.16 fixed-point values, which can
    *   limit the accuracy of the results.  Using floating-point computations
    *   to perform the transform directly in client code instead will always
    *   yield better numbers.
@@ -3197,6 +3249,39 @@
 
   /**************************************************************************
    *
+   * @function:
+   *   FT_Get_Transform
+   *
+   * @description:
+   *   Return the transformation that is applied to glyph images when they
+   *   are loaded into a glyph slot through @FT_Load_Glyph.  See
+   *   @FT_Set_Transform for more details.
+   *
+   * @input:
+   *   face ::
+   *     A handle to the source face object.
+   *
+   * @output:
+   *   matrix ::
+   *     A pointer to a transformation's 2x2 matrix.  Set this to NULL if you
+   *     are not interested in the value.
+   *
+   *   delta ::
+   *     A pointer a translation vector.  Set this to NULL if you are not
+   *     interested in the value.
+   *
+   * @since:
+   *   2.11
+   *
+   */
+  FT_EXPORT( void )
+  FT_Get_Transform( FT_Face     face,
+                    FT_Matrix*  matrix,
+                    FT_Vector*  delta );
+
+
+  /**************************************************************************
+   *
    * @enum:
    *   FT_Render_Mode
    *
@@ -3213,6 +3298,10 @@
    *   correction to correctly render non-monochrome glyph bitmaps onto a
    *   surface; see @FT_Render_Glyph.
    *
+   *   The @FT_RENDER_MODE_SDF is a special render mode that uses up to 256
+   *   distance values, indicating the signed distance from the grid position
+   *   to the nearest outline.
+   *
    * @values:
    *   FT_RENDER_MODE_NORMAL ::
    *     Default render mode; it corresponds to 8-bit anti-aliased bitmaps.
@@ -3238,11 +3327,49 @@
    *     bitmaps that are 3~times the height of the original glyph outline in
    *     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.
+   *
    * @note:
    *   The selected render mode only affects 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.
+   *   }
+   *
+   *   ```
    */
   typedef enum  FT_Render_Mode_
   {
@@ -3251,6 +3378,7 @@
     FT_RENDER_MODE_MONO,
     FT_RENDER_MODE_LCD,
     FT_RENDER_MODE_LCD_V,
+    FT_RENDER_MODE_SDF,
 
     FT_RENDER_MODE_MAX
 
@@ -3338,7 +3466,8 @@
    *
    *   which is known as the OVER operator.
    *
-   *   To correctly composite an antialiased pixel of a glyph onto a surface,
+   *   To correctly composite an anti-aliased pixel of a glyph onto a
+   *   surface,
    *
    *   1. take the foreground and background colors (e.g., in sRGB space)
    *      and apply gamma to get them in a linear space,
@@ -4018,168 +4147,6 @@
   /**************************************************************************
    *
    * @section:
-   *   layer_management
-   *
-   * @title:
-   *   Glyph Layer Management
-   *
-   * @abstract:
-   *   Retrieving and manipulating OpenType's 'COLR' table data.
-   *
-   * @description:
-   *   The functions described here allow access of colored glyph layer data
-   *   in OpenType's 'COLR' tables.
-   */
-
-
-  /**************************************************************************
-   *
-   * @struct:
-   *   FT_LayerIterator
-   *
-   * @description:
-   *   This iterator object is needed for @FT_Get_Color_Glyph_Layer.
-   *
-   * @fields:
-   *   num_layers ::
-   *     The number of glyph layers for the requested glyph index.  Will be
-   *     set by @FT_Get_Color_Glyph_Layer.
-   *
-   *   layer ::
-   *     The current layer.  Will be set by @FT_Get_Color_Glyph_Layer.
-   *
-   *   p ::
-   *     An opaque pointer into 'COLR' table data.  The caller must set this
-   *     to `NULL` before the first call of @FT_Get_Color_Glyph_Layer.
-   */
-  typedef struct  FT_LayerIterator_
-  {
-    FT_UInt   num_layers;
-    FT_UInt   layer;
-    FT_Byte*  p;
-
-  } FT_LayerIterator;
-
-
-  /**************************************************************************
-   *
-   * @function:
-   *   FT_Get_Color_Glyph_Layer
-   *
-   * @description:
-   *   This is an interface to the 'COLR' table in OpenType fonts to
-   *   iteratively retrieve the colored glyph layers associated with the
-   *   current glyph slot.
-   *
-   *     https://docs.microsoft.com/en-us/typography/opentype/spec/colr
-   *
-   *   The glyph layer data for a given glyph index, if present, provides an
-   *   alternative, multi-color glyph representation: Instead of rendering
-   *   the outline or bitmap with the given glyph index, glyphs with the
-   *   indices and colors returned by this function are rendered layer by
-   *   layer.
-   *
-   *   The returned elements are ordered in the z~direction from bottom to
-   *   top; the 'n'th element should be rendered with the associated palette
-   *   color and blended on top of the already rendered layers (elements 0,
-   *   1, ..., n-1).
-   *
-   * @input:
-   *   face ::
-   *     A handle to the parent face object.
-   *
-   *   base_glyph ::
-   *     The glyph index the colored glyph layers are associated with.
-   *
-   * @inout:
-   *   iterator ::
-   *     An @FT_LayerIterator object.  For the first call you should set
-   *     `iterator->p` to `NULL`.  For all following calls, simply use the
-   *     same object again.
-   *
-   * @output:
-   *   aglyph_index ::
-   *     The glyph index of the current layer.
-   *
-   *   acolor_index ::
-   *     The color index into the font face's color palette of the current
-   *     layer.  The value 0xFFFF is special; it doesn't reference a palette
-   *     entry but indicates that the text foreground color should be used
-   *     instead (to be set up by the application outside of FreeType).
-   *
-   *     The color palette can be retrieved with @FT_Palette_Select.
-   *
-   * @return:
-   *   Value~1 if everything is OK.  If there are no more layers (or if there
-   *   are no layers at all), value~0 gets returned.  In case of an error,
-   *   value~0 is returned also.
-   *
-   * @note:
-   *   This function is necessary if you want to handle glyph layers by
-   *   yourself.  In particular, functions that operate with @FT_GlyphRec
-   *   objects (like @FT_Get_Glyph or @FT_Glyph_To_Bitmap) don't have access
-   *   to this information.
-   *
-   *   Note that @FT_Render_Glyph is able to handle colored glyph layers
-   *   automatically if the @FT_LOAD_COLOR flag is passed to a previous call
-   *   to @FT_Load_Glyph.  [This is an experimental feature.]
-   *
-   * @example:
-   *   ```
-   *     FT_Color*         palette;
-   *     FT_LayerIterator  iterator;
-   *
-   *     FT_Bool  have_layers;
-   *     FT_UInt  layer_glyph_index;
-   *     FT_UInt  layer_color_index;
-   *
-   *
-   *     error = FT_Palette_Select( face, palette_index, &palette );
-   *     if ( error )
-   *       palette = NULL;
-   *
-   *     iterator.p  = NULL;
-   *     have_layers = FT_Get_Color_Glyph_Layer( face,
-   *                                             glyph_index,
-   *                                             &layer_glyph_index,
-   *                                             &layer_color_index,
-   *                                             &iterator );
-   *
-   *     if ( palette && have_layers )
-   *     {
-   *       do
-   *       {
-   *         FT_Color  layer_color;
-   *
-   *
-   *         if ( layer_color_index == 0xFFFF )
-   *           layer_color = text_foreground_color;
-   *         else
-   *           layer_color = palette[layer_color_index];
-   *
-   *         // Load and render glyph `layer_glyph_index', then
-   *         // blend resulting pixmap (using color `layer_color')
-   *         // with previously created pixmaps.
-   *
-   *       } while ( FT_Get_Color_Glyph_Layer( face,
-   *                                           glyph_index,
-   *                                           &layer_glyph_index,
-   *                                           &layer_color_index,
-   *                                           &iterator ) );
-   *     }
-   *   ```
-   */
-  FT_EXPORT( FT_Bool )
-  FT_Get_Color_Glyph_Layer( FT_Face            face,
-                            FT_UInt            base_glyph,
-                            FT_UInt           *aglyph_index,
-                            FT_UInt           *acolor_index,
-                            FT_LayerIterator*  iterator );
-
-
-  /**************************************************************************
-   *
-   * @section:
    *   base_interface
    *
    */
@@ -4267,6 +4234,7 @@
    *
    * @since:
    *   2.3.8
+   *
    */
   FT_EXPORT( FT_UShort )
   FT_Get_FSType_Flags( FT_Face  face );
@@ -4360,6 +4328,7 @@
    *
    * @since:
    *   2.3.6
+   *
    */
   FT_EXPORT( FT_UInt )
   FT_Face_GetCharVariantIndex( FT_Face   face,
@@ -4396,6 +4365,7 @@
    *
    * @since:
    *   2.3.6
+   *
    */
   FT_EXPORT( FT_Int )
   FT_Face_GetCharVariantIsDefault( FT_Face   face,
@@ -4427,6 +4397,7 @@
    *
    * @since:
    *   2.3.6
+   *
    */
   FT_EXPORT( FT_UInt32* )
   FT_Face_GetVariantSelectors( FT_Face  face );
@@ -4460,6 +4431,7 @@
    *
    * @since:
    *   2.3.6
+   *
    */
   FT_EXPORT( FT_UInt32* )
   FT_Face_GetVariantsOfChar( FT_Face   face,
@@ -4494,6 +4466,7 @@
    *
    * @since:
    *   2.3.6
+   *
    */
   FT_EXPORT( FT_UInt32* )
   FT_Face_GetCharsOfVariant( FT_Face   face,
@@ -4766,8 +4739,8 @@
    *
    */
 #define FREETYPE_MAJOR  2
-#define FREETYPE_MINOR  10
-#define FREETYPE_PATCH  4
+#define FREETYPE_MINOR  11
+#define FREETYPE_PATCH  1
 
 
   /**************************************************************************
@@ -4829,6 +4802,7 @@
    *
    * @since:
    *   2.3.5
+   *
    */
   FT_EXPORT( FT_Bool )
   FT_Face_CheckTrueTypePatents( FT_Face  face );
@@ -4857,6 +4831,7 @@
    *
    * @since:
    *   2.3.5
+   *
    */
   FT_EXPORT( FT_Bool )
   FT_Face_SetUnpatentedHinting( FT_Face  face,
diff --git a/include/freetype/ftadvanc.h b/include/freetype/ftadvanc.h
index f166bc6..3a13bd3 100644
--- a/include/freetype/ftadvanc.h
+++ b/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
  *
  *   Quick computation of advance widths (specification only).
  *
- * Copyright (C) 2008-2020 by
+ * Copyright (C) 2008-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftbbox.h b/include/freetype/ftbbox.h
index fda1ad9..713aedb 100644
--- a/include/freetype/ftbbox.h
+++ b/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
  *
  *   FreeType exact bbox computation (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftbdf.h b/include/freetype/ftbdf.h
index 2e1daee..c428506 100644
--- a/include/freetype/ftbdf.h
+++ b/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing BDF-specific strings (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftbitmap.h b/include/freetype/ftbitmap.h
index 282c22e..11c45b0 100644
--- a/include/freetype/ftbitmap.h
+++ b/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
  *
  *   FreeType utility functions for bitmaps (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftbzip2.h b/include/freetype/ftbzip2.h
index eb6a5a5..afd2a82 100644
--- a/include/freetype/ftbzip2.h
+++ b/include/freetype/ftbzip2.h
@@ -4,7 +4,7 @@
  *
  *   Bzip2-compressed stream support.
  *
- * Copyright (C) 2010-2020 by
+ * Copyright (C) 2010-2021 by
  * Joel Klinghed.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftcache.h b/include/freetype/ftcache.h
index 6047275..70399a3 100644
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Cache subsystem (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -86,8 +86,8 @@
    *   later use @FTC_CMapCache_Lookup to perform the equivalent of
    *   @FT_Get_Char_Index, only much faster.
    *
-   *   If you want to use the @FT_Glyph caching, call @FTC_ImageCache, then
-   *   later use @FTC_ImageCache_Lookup to retrieve the corresponding
+   *   If you want to use the @FT_Glyph caching, call @FTC_ImageCache_New,
+   *   then later use @FTC_ImageCache_Lookup to retrieve the corresponding
    *   @FT_Glyph objects from the cache.
    *
    *   If you need lots of small bitmaps, it is much more memory efficient to
diff --git a/include/freetype/ftchapters.h b/include/freetype/ftchapters.h
index 2ee2697..4f32cc8 100644
--- a/include/freetype/ftchapters.h
+++ b/include/freetype/ftchapters.h
@@ -15,6 +15,7 @@
    *   General Remarks
    *
    * @sections:
+   *   preamble
    *   header_inclusion
    *   user_allocation
    *
@@ -123,6 +124,7 @@
    *   gzip
    *   lzw
    *   bzip2
+   *   debugging_apis
    *
    */
 
diff --git a/include/freetype/ftcid.h b/include/freetype/ftcid.h
index a29fb33..9a415bd 100644
--- a/include/freetype/ftcid.h
+++ b/include/freetype/ftcid.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing CID font information (specification).
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * Dereg Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftcolor.h b/include/freetype/ftcolor.h
index ecc6485..08dbac0 100644
--- a/include/freetype/ftcolor.h
+++ b/include/freetype/ftcolor.h
@@ -4,7 +4,7 @@
  *
  *   FreeType's glyph color management (specification).
  *
- * Copyright (C) 2018-2020 by
+ * Copyright (C) 2018-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -302,6 +302,1411 @@
   FT_Palette_Set_Foreground_Color( FT_Face   face,
                                    FT_Color  foreground_color );
 
+
+  /**************************************************************************
+   *
+   * @section:
+   *   layer_management
+   *
+   * @title:
+   *   Glyph Layer Management
+   *
+   * @abstract:
+   *   Retrieving and manipulating OpenType's 'COLR' table data.
+   *
+   * @description:
+   *   The functions described here allow access of colored glyph layer data
+   *   in OpenType's 'COLR' tables.
+   */
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_LayerIterator
+   *
+   * @description:
+   *   This iterator object is needed for @FT_Get_Color_Glyph_Layer.
+   *
+   * @fields:
+   *   num_layers ::
+   *     The number of glyph layers for the requested glyph index.  Will be
+   *     set by @FT_Get_Color_Glyph_Layer.
+   *
+   *   layer ::
+   *     The current layer.  Will be set by @FT_Get_Color_Glyph_Layer.
+   *
+   *   p ::
+   *     An opaque pointer into 'COLR' table data.  The caller must set this
+   *     to `NULL` before the first call of @FT_Get_Color_Glyph_Layer.
+   */
+  typedef struct  FT_LayerIterator_
+  {
+    FT_UInt   num_layers;
+    FT_UInt   layer;
+    FT_Byte*  p;
+
+  } FT_LayerIterator;
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Get_Color_Glyph_Layer
+   *
+   * @description:
+   *   This is an interface to the 'COLR' table in OpenType fonts to
+   *   iteratively retrieve the colored glyph layers associated with the
+   *   current glyph slot.
+   *
+   *     https://docs.microsoft.com/en-us/typography/opentype/spec/colr
+   *
+   *   The glyph layer data for a given glyph index, if present, provides an
+   *   alternative, multi-color glyph representation: Instead of rendering
+   *   the outline or bitmap with the given glyph index, glyphs with the
+   *   indices and colors returned by this function are rendered layer by
+   *   layer.
+   *
+   *   The returned elements are ordered in the z~direction from bottom to
+   *   top; the 'n'th element should be rendered with the associated palette
+   *   color and blended on top of the already rendered layers (elements 0,
+   *   1, ..., n-1).
+   *
+   * @input:
+   *   face ::
+   *     A handle to the parent face object.
+   *
+   *   base_glyph ::
+   *     The glyph index the colored glyph layers are associated with.
+   *
+   * @inout:
+   *   iterator ::
+   *     An @FT_LayerIterator object.  For the first call you should set
+   *     `iterator->p` to `NULL`.  For all following calls, simply use the
+   *     same object again.
+   *
+   * @output:
+   *   aglyph_index ::
+   *     The glyph index of the current layer.
+   *
+   *   acolor_index ::
+   *     The color index into the font face's color palette of the current
+   *     layer.  The value 0xFFFF is special; it doesn't reference a palette
+   *     entry but indicates that the text foreground color should be used
+   *     instead (to be set up by the application outside of FreeType).
+   *
+   *     The color palette can be retrieved with @FT_Palette_Select.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  If there are no more layers (or if there
+   *   are no layers at all), value~0 gets returned.  In case of an error,
+   *   value~0 is returned also.
+   *
+   * @note:
+   *   This function is necessary if you want to handle glyph layers by
+   *   yourself.  In particular, functions that operate with @FT_GlyphRec
+   *   objects (like @FT_Get_Glyph or @FT_Glyph_To_Bitmap) don't have access
+   *   to this information.
+   *
+   *   Note that @FT_Render_Glyph is able to handle colored glyph layers
+   *   automatically if the @FT_LOAD_COLOR flag is passed to a previous call
+   *   to @FT_Load_Glyph.  [This is an experimental feature.]
+   *
+   * @example:
+   *   ```
+   *     FT_Color*         palette;
+   *     FT_LayerIterator  iterator;
+   *
+   *     FT_Bool  have_layers;
+   *     FT_UInt  layer_glyph_index;
+   *     FT_UInt  layer_color_index;
+   *
+   *
+   *     error = FT_Palette_Select( face, palette_index, &palette );
+   *     if ( error )
+   *       palette = NULL;
+   *
+   *     iterator.p  = NULL;
+   *     have_layers = FT_Get_Color_Glyph_Layer( face,
+   *                                             glyph_index,
+   *                                             &layer_glyph_index,
+   *                                             &layer_color_index,
+   *                                             &iterator );
+   *
+   *     if ( palette && have_layers )
+   *     {
+   *       do
+   *       {
+   *         FT_Color  layer_color;
+   *
+   *
+   *         if ( layer_color_index == 0xFFFF )
+   *           layer_color = text_foreground_color;
+   *         else
+   *           layer_color = palette[layer_color_index];
+   *
+   *         // Load and render glyph `layer_glyph_index', then
+   *         // blend resulting pixmap (using color `layer_color')
+   *         // with previously created pixmaps.
+   *
+   *       } while ( FT_Get_Color_Glyph_Layer( face,
+   *                                           glyph_index,
+   *                                           &layer_glyph_index,
+   *                                           &layer_color_index,
+   *                                           &iterator ) );
+   *     }
+   *   ```
+   */
+  FT_EXPORT( FT_Bool )
+  FT_Get_Color_Glyph_Layer( FT_Face            face,
+                            FT_UInt            base_glyph,
+                            FT_UInt           *aglyph_index,
+                            FT_UInt           *acolor_index,
+                            FT_LayerIterator*  iterator );
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   FT_PaintFormat
+   *
+   * @description:
+   *   Enumeration describing the different paint format types of the v1
+   *   extensions to the 'COLR' table, see
+   *   'https://github.com/googlefonts/colr-gradients-spec'.
+   *
+   *   The enumeration values losely correspond with the format numbers of
+   *   the specification: FreeType always returns a fully specified 'Paint'
+   *   structure for the 'Transform', 'Translate', 'Scale', 'Rotate', and
+   *   'Skew' table types even though the specification has different formats
+   *   depending on whether or not a center is specified, whether the scale
+   *   is uniform in x and y~direction or not, etc.  Also, only non-variable
+   *   format identifiers are listed in this enumeration; as soon as support
+   *   for variable 'COLR' v1 fonts is implemented, interpolation is
+   *   performed dependent on axis coordinates, which are configured on the
+   *   @FT_Face through @FT_Set_Var_Design_Coordinates.  This implies that
+   *   always static, readily interpolated values are returned in the 'Paint'
+   *   structures.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef enum  FT_PaintFormat_
+  {
+    FT_COLR_PAINTFORMAT_COLR_LAYERS     = 1,
+    FT_COLR_PAINTFORMAT_SOLID           = 2,
+    FT_COLR_PAINTFORMAT_LINEAR_GRADIENT = 4,
+    FT_COLR_PAINTFORMAT_RADIAL_GRADIENT = 6,
+    FT_COLR_PAINTFORMAT_SWEEP_GRADIENT  = 8,
+    FT_COLR_PAINTFORMAT_GLYPH           = 10,
+    FT_COLR_PAINTFORMAT_COLR_GLYPH      = 11,
+    FT_COLR_PAINTFORMAT_TRANSFORM       = 12,
+    FT_COLR_PAINTFORMAT_TRANSLATE       = 14,
+    FT_COLR_PAINTFORMAT_SCALE           = 16,
+    FT_COLR_PAINTFORMAT_ROTATE          = 24,
+    FT_COLR_PAINTFORMAT_SKEW            = 28,
+    FT_COLR_PAINTFORMAT_COMPOSITE       = 32,
+    FT_COLR_PAINT_FORMAT_MAX            = 33,
+    FT_COLR_PAINTFORMAT_UNSUPPORTED     = 255
+
+  } FT_PaintFormat;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_ColorStopIterator
+   *
+   * @description:
+   *   This iterator object is needed for @FT_Get_Colorline_Stops.  It keeps
+   *   state while iterating over the stops of an @FT_ColorLine,
+   *   representing the `ColorLine` struct of the v1 extensions to 'COLR',
+   *   see 'https://github.com/googlefonts/colr-gradients-spec'.
+   *
+   * @fields:
+   *   num_color_stops ::
+   *     The number of color stops for the requested glyph index.  Set by
+   *     @FT_Get_Colorline_Stops.
+   *
+   *   current_color_stop ::
+   *     The current color stop.  Set by @FT_Get_Colorline_Stops.
+   *
+   *   p ::
+   *     An opaque pointer into 'COLR' table data.  The caller must set this
+   *     to `NULL` before the first call of @FT_Get_Colorline_Stops.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_ColorStopIterator_
+  {
+    FT_UInt  num_color_stops;
+    FT_UInt  current_color_stop;
+
+    FT_Byte*  p;
+
+  } FT_ColorStopIterator;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_ColorIndex
+   *
+   * @description:
+   *   A structure representing a `ColorIndex` value of the 'COLR' v1
+   *   extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+   *
+   * @fields:
+   *   palette_index ::
+   *     The palette index into a 'CPAL' palette.
+   *
+   *   alpha ::
+   *     Alpha transparency value multiplied with the value from 'CPAL'.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_ColorIndex_
+  {
+    FT_UInt16   palette_index;
+    FT_F2Dot14  alpha;
+
+  } FT_ColorIndex;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_ColorStop
+   *
+   * @description:
+   *   A structure representing a `ColorStop` value of the 'COLR' v1
+   *   extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+   *
+   * @fields:
+   *   stop_offset ::
+   *     The stop offset between 0 and 1 along the gradient.
+   *
+   *   color ::
+   *     The color information for this stop, see @FT_ColorIndex.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_ColorStop_
+  {
+    FT_F2Dot14     stop_offset;
+    FT_ColorIndex  color;
+
+  } FT_ColorStop;
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   FT_PaintExtend
+   *
+   * @description:
+   *   An enumeration representing the 'Extend' mode of the 'COLR' v1
+   *   extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+   *   It describes how the gradient fill continues at the other boundaries.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef enum  FT_PaintExtend_
+  {
+    FT_COLR_PAINT_EXTEND_PAD     = 0,
+    FT_COLR_PAINT_EXTEND_REPEAT  = 1,
+    FT_COLR_PAINT_EXTEND_REFLECT = 2
+
+  } FT_PaintExtend;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_ColorLine
+   *
+   * @description:
+   *   A structure representing a `ColorLine` value of the 'COLR' v1
+   *   extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+   *   It describes a list of color stops along the defined gradient.
+   *
+   * @fields:
+   *   extend ::
+   *     The extend mode at the outer boundaries, see @FT_PaintExtend.
+   *
+   *   color_stop_iterator ::
+   *     The @FT_ColorStopIterator used to enumerate and retrieve the
+   *     actual @FT_ColorStop's.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_ColorLine_
+  {
+    FT_PaintExtend        extend;
+    FT_ColorStopIterator  color_stop_iterator;
+
+  } FT_ColorLine;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_Affine23
+   *
+   * @description:
+   *   A structure used to store a 2x3 matrix.  Coefficients are in
+   *   16.16 fixed-point format.  The computation performed is
+   *
+   *   ```
+   *     x' = x*xx + y*xy + dx
+   *     y' = x*yx + y*yy + dy
+   *   ```
+   *
+   * @fields:
+   *   xx ::
+   *     Matrix coefficient.
+   *
+   *   xy ::
+   *     Matrix coefficient.
+   *
+   *   dx ::
+   *     x translation.
+   *
+   *   yx ::
+   *     Matrix coefficient.
+   *
+   *   yy ::
+   *     Matrix coefficient.
+   *
+   *   dy ::
+   *     y translation.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_Affine_23_
+  {
+    FT_Fixed  xx, xy, dx;
+    FT_Fixed  yx, yy, dy;
+
+  } FT_Affine23;
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   FT_Composite_Mode
+   *
+   * @description:
+   *   An enumeration listing the 'COLR' v1 composite modes used in
+   *   @FT_PaintComposite.  For more details on each paint mode, see
+   *   'https://www.w3.org/TR/compositing-1/#porterduffcompositingoperators'.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef enum  FT_Composite_Mode_
+  {
+    FT_COLR_COMPOSITE_CLEAR          = 0,
+    FT_COLR_COMPOSITE_SRC            = 1,
+    FT_COLR_COMPOSITE_DEST           = 2,
+    FT_COLR_COMPOSITE_SRC_OVER       = 3,
+    FT_COLR_COMPOSITE_DEST_OVER      = 4,
+    FT_COLR_COMPOSITE_SRC_IN         = 5,
+    FT_COLR_COMPOSITE_DEST_IN        = 6,
+    FT_COLR_COMPOSITE_SRC_OUT        = 7,
+    FT_COLR_COMPOSITE_DEST_OUT       = 8,
+    FT_COLR_COMPOSITE_SRC_ATOP       = 9,
+    FT_COLR_COMPOSITE_DEST_ATOP      = 10,
+    FT_COLR_COMPOSITE_XOR            = 11,
+    FT_COLR_COMPOSITE_PLUS           = 12,
+    FT_COLR_COMPOSITE_SCREEN         = 13,
+    FT_COLR_COMPOSITE_OVERLAY        = 14,
+    FT_COLR_COMPOSITE_DARKEN         = 15,
+    FT_COLR_COMPOSITE_LIGHTEN        = 16,
+    FT_COLR_COMPOSITE_COLOR_DODGE    = 17,
+    FT_COLR_COMPOSITE_COLOR_BURN     = 18,
+    FT_COLR_COMPOSITE_HARD_LIGHT     = 19,
+    FT_COLR_COMPOSITE_SOFT_LIGHT     = 20,
+    FT_COLR_COMPOSITE_DIFFERENCE     = 21,
+    FT_COLR_COMPOSITE_EXCLUSION      = 22,
+    FT_COLR_COMPOSITE_MULTIPLY       = 23,
+    FT_COLR_COMPOSITE_HSL_HUE        = 24,
+    FT_COLR_COMPOSITE_HSL_SATURATION = 25,
+    FT_COLR_COMPOSITE_HSL_COLOR      = 26,
+    FT_COLR_COMPOSITE_HSL_LUMINOSITY = 27,
+    FT_COLR_COMPOSITE_MAX            = 28
+
+  } FT_Composite_Mode;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_OpaquePaint
+   *
+   * @description:
+   *   A structure representing an offset to a `Paint` value stored in any
+   *   of the paint tables of a 'COLR' v1 font.  Compare Offset<24> there.
+   *   When 'COLR' v1 paint tables represented by FreeType objects such as
+   *   @FT_PaintColrLayers, @FT_PaintComposite, or @FT_PaintTransform
+   *   reference downstream nested paint tables, we do not immediately
+   *   retrieve them but encapsulate their location in this type.  Use
+   *   @FT_Get_Paint to retrieve the actual @FT_COLR_Paint object that
+   *   describes the details of the respective paint table.
+   *
+   * @fields:
+   *   p ::
+   *     An internal offset to a Paint table, needs to be set to NULL before
+   *     passing this struct as an argument to @FT_Get_Paint.
+   *
+   *   insert_root_transform ::
+   *     An internal boolean to track whether an initial root transform is
+   *     to be provided.  Do not set this value.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_Opaque_Paint_
+  {
+    FT_Byte*  p;
+    FT_Bool   insert_root_transform;
+  } FT_OpaquePaint;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintColrLayers
+   *
+   * @description:
+   *   A structure representing a `PaintColrLayers` table of a 'COLR' v1
+   *   font.  This table describes a set of layers that are to be composited
+   *   with composite mode `FT_COLR_COMPOSITE_SRC_OVER`.  The return value
+   *   of this function is an @FT_LayerIterator initialized so that it can
+   *   be used with @FT_Get_Paint_Layers to retrieve the @FT_OpaquePaint
+   *   objects as references to each layer.
+   *
+   * @fields:
+   *   layer_iterator ::
+   *     The layer iterator that describes the layers of this paint.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintColrLayers_
+  {
+    FT_LayerIterator  layer_iterator;
+
+  } FT_PaintColrLayers;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintSolid
+   *
+   * @description:
+   *   A structure representing a `PaintSolid` value of the 'COLR' v1
+   *   extensions, see 'https://github.com/googlefonts/colr-gradients-spec'.
+   *   Using a `PaintSolid` value means that the glyph layer filled with
+   *   this paint is solid-colored and does not contain a gradient.
+   *
+   * @fields:
+   *   color ::
+   *     The color information for this solid paint, see @FT_ColorIndex.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintSolid_
+  {
+    FT_ColorIndex  color;
+
+  } FT_PaintSolid;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintLinearGradient
+   *
+   * @description:
+   *   A structure representing a `PaintLinearGradient` value of the 'COLR'
+   *   v1 extensions, see
+   *   'https://github.com/googlefonts/colr-gradients-spec'.  The glyph
+   *   layer filled with this paint is drawn filled with a linear gradient.
+   *
+   * @fields:
+   *   colorline ::
+   *     The @FT_ColorLine information for this paint, i.e., the list of
+   *     color stops along the gradient.
+   *
+   *   p0 ::
+   *     The starting point of the gradient definition in font units
+   *     represented as a 16.16 fixed-point `FT_Vector`.
+   *
+   *   p1 ::
+   *     The end point of the gradient definition in font units
+   *     represented as a 16.16 fixed-point `FT_Vector`.
+   *
+   *   p2 ::
+   *     Optional point~p2 to rotate the gradient in font units
+   *     represented as a 16.16 fixed-point `FT_Vector`.
+   *     Otherwise equal to~p0.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintLinearGradient_
+  {
+    FT_ColorLine  colorline;
+
+    /* TODO: Potentially expose those as x0, y0 etc. */
+    FT_Vector  p0;
+    FT_Vector  p1;
+    FT_Vector  p2;
+
+  } FT_PaintLinearGradient;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintRadialGradient
+   *
+   * @description:
+   *   A structure representing a `PaintRadialGradient` value of the 'COLR'
+   *   v1 extensions, see
+   *   'https://github.com/googlefonts/colr-gradients-spec'.  The glyph
+   *   layer filled with this paint is drawn filled filled with a radial
+   *   gradient.
+   *
+   * @fields:
+   *   colorline ::
+   *     The @FT_ColorLine information for this paint, i.e., the list of
+   *     color stops along the gradient.
+   *
+   *   c0 ::
+   *     The center of the starting point of the radial gradient in font
+   *     units represented as a 16.16 fixed-point `FT_Vector`.
+   *
+   *   r0 ::
+   *     The radius of the starting circle of the radial gradient in font
+   *     units represented as a 16.16 fixed-point value.
+   *
+   *   c1 ::
+   *     The center of the end point of the radial gradient in font units
+   *     represented as a 16.16 fixed-point `FT_Vector`.
+   *
+   *   r1 ::
+   *     The radius of the end circle of the radial gradient in font
+   *     units represented as a 16.16 fixed-point value.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintRadialGradient_
+  {
+    FT_ColorLine  colorline;
+
+    FT_Vector  c0;
+    FT_Pos     r0;
+    FT_Vector  c1;
+    FT_Pos     r1;
+
+  } FT_PaintRadialGradient;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintSweepGradient
+   *
+   * @description:
+   *   A structure representing a `PaintSweepGradient` value of the 'COLR'
+   *   v1 extensions, see
+   *   'https://github.com/googlefonts/colr-gradients-spec'.  The glyph
+   *   layer filled with this paint is drawn filled with a sweep gradient
+   *   from `start_angle` to `end_angle`.
+   *
+   * @fields:
+   *   colorline ::
+   *     The @FT_ColorLine information for this paint, i.e., the list of
+   *     color stops along the gradient.
+   *
+   *   center ::
+   *     The center of the sweep gradient in font units represented as a
+   *     vector of 16.16 fixed-point values.
+   *
+   *   start_angle ::
+   *     The start angle of the sweep gradient in 16.16 fixed-point
+   *     format specifying degrees divided by 180.0 (as in the
+   *     spec).  Multiply by 180.0f to receive degrees value.  Values are
+   *     given counter-clockwise, starting from the (positive) y~axis.
+   *
+   *   end_angle ::
+   *     The end angle of the sweep gradient in 16.16 fixed-point
+   *     format specifying degrees divided by 180.0 (as in the
+   *     spec).  Multiply by 180.0f to receive degrees value.  Values are
+   *     given counter-clockwise, starting from the (positive) y~axis.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintSweepGradient_
+  {
+    FT_ColorLine  colorline;
+
+    FT_Vector  center;
+    FT_Fixed   start_angle;
+    FT_Fixed   end_angle;
+
+  } FT_PaintSweepGradient;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintGlyph
+   *
+   * @description:
+   *   A structure representing a 'COLR' v1 `PaintGlyph` paint table.
+   *
+   * @fields:
+   *   paint ::
+   *     An opaque paint object pointing to a `Paint` table that serves as
+   *     the fill for the glyph ID.
+   *
+   *   glyphID ::
+   *     The glyph ID from the 'glyf' table, which serves as the contour
+   *     information that is filled with paint.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintGlyph_
+  {
+    FT_OpaquePaint  paint;
+    FT_UInt         glyphID;
+
+  } FT_PaintGlyph;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintColrGlyph
+   *
+   * @description:
+   *   A structure representing a 'COLR' v1 `PaintColorGlyph` paint table.
+   *
+   * @fields:
+   *   glyphID ::
+   *     The glyph ID from the `BaseGlyphV1List` table that is drawn for
+   *     this paint.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintColrGlyph_
+  {
+    FT_UInt  glyphID;
+
+  } FT_PaintColrGlyph;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintTransform
+   *
+   * @description:
+   *   A structure representing a 'COLR' v1 `PaintTransform` paint table.
+   *
+   * @fields:
+   *   paint ::
+   *     An opaque paint that is subject to being transformed.
+   *
+   *   affine ::
+   *     A 2x3 transformation matrix in @FT_Affine23 format containing
+   *     16.16 fixed-point values.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintTransform_
+  {
+    FT_OpaquePaint  paint;
+    FT_Affine23     affine;
+
+  } FT_PaintTransform;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintTranslate
+   *
+   * @description:
+   *   A structure representing a 'COLR' v1 `PaintTranslate` paint table.
+   *   Used for translating downstream paints by a given x and y~delta.
+   *
+   * @fields:
+   *   paint ::
+   *     An @FT_OpaquePaint object referencing the paint that is to be
+   *     rotated.
+   *
+   *   dx ::
+   *     Translation in x~direction in font units represented as a
+   *     16.16 fixed-point value.
+   *
+   *   dy ::
+   *     Translation in y~direction in font units represented as a
+   *     16.16 fixed-point value.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintTranslate_
+  {
+    FT_OpaquePaint  paint;
+
+    FT_Fixed  dx;
+    FT_Fixed  dy;
+
+  } FT_PaintTranslate;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintScale
+   *
+   * @description:
+   *   A structure representing all of the 'COLR' v1 'PaintScale*' paint
+   *   tables.  Used for scaling downstream paints by a given x and y~scale,
+   *   with a given center.  This structure is used for all 'PaintScale*'
+   *   types that are part of specification; fields of this structure are
+   *   filled accordingly.  If there is a center, the center values are set,
+   *   otherwise they are set to the zero coordinate.  If the source font
+   *   file has 'PaintScaleUniform*' set, the scale values are set
+   *   accordingly to the same value.
+   *
+   * @fields:
+   *   paint ::
+   *     An @FT_OpaquePaint object referencing the paint that is to be
+   *     scaled.
+   *
+   *   scale_x ::
+   *     Scale factor in x~direction represented as a
+   *     16.16 fixed-point value.
+   *
+   *   scale_y ::
+   *     Scale factor in y~direction represented as a
+   *     16.16 fixed-point value.
+   *
+   *   center_x ::
+   *     x~coordinate of center point to scale from represented as a
+   *     16.16 fixed-point value.
+   *
+   *   center_y ::
+   *     y~coordinate of center point to scale from represented as a
+   *     16.16 fixed-point value.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward-compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintScale_
+  {
+    FT_OpaquePaint  paint;
+
+    FT_Fixed  scale_x;
+    FT_Fixed  scale_y;
+
+    FT_Fixed  center_x;
+    FT_Fixed  center_y;
+
+  } FT_PaintScale;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintRotate
+   *
+   * @description:
+   *   A structure representing a 'COLR' v1 `PaintRotate` paint table.  Used
+   *   for rotating downstream paints with a given center and angle.
+   *
+   * @fields:
+   *   paint ::
+   *     An @FT_OpaquePaint object referencing the paint that is to be
+   *     rotated.
+   *
+   *   angle ::
+   *     The rotation angle that is to be applied in degrees divided by
+   *     180.0 (as in the spec) represented as a 16.16 fixed-point
+   *     value.  Multiply by 180.0f to receive degrees value.
+   *
+   *   center_x ::
+   *     The x~coordinate of the pivot point of the rotation in font
+   *     units) represented as a 16.16 fixed-point value.
+   *
+   *   center_y ::
+   *     The y~coordinate of the pivot point of the rotation in font
+   *     units represented as a 16.16 fixed-point value.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+
+  typedef struct  FT_PaintRotate_
+  {
+    FT_OpaquePaint  paint;
+
+    FT_Fixed  angle;
+
+    FT_Fixed  center_x;
+    FT_Fixed  center_y;
+
+  } FT_PaintRotate;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintSkew
+   *
+   * @description:
+   *   A structure representing a 'COLR' v1 `PaintSkew` paint table.  Used
+   *   for skewing or shearing downstream paints by a given center and
+   *   angle.
+   *
+   * @fields:
+   *   paint ::
+   *     An @FT_OpaquePaint object referencing the paint that is to be
+   *     skewed.
+   *
+   *   x_skew_angle ::
+   *     The skewing angle in x~direction in degrees divided by 180.0
+   *     (as in the spec) represented as a 16.16 fixed-point
+   *     value. Multiply by 180.0f to receive degrees.
+   *
+   *   y_skew_angle ::
+   *     The skewing angle in y~direction in degrees divided by 180.0
+   *     (as in the spec) represented as a 16.16 fixed-point
+   *     value.  Multiply by 180.0f to receive degrees.
+   *
+   *   center_x ::
+   *     The x~coordinate of the pivot point of the skew in font units
+   *     represented as a 16.16 fixed-point value.
+   *
+   *   center_y ::
+   *     The y~coordinate of the pivot point of the skew in font units
+   *     represented as a 16.16 fixed-point value.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintSkew_
+  {
+    FT_OpaquePaint  paint;
+
+    FT_Fixed  x_skew_angle;
+    FT_Fixed  y_skew_angle;
+
+    FT_Fixed  center_x;
+    FT_Fixed  center_y;
+
+  } FT_PaintSkew;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_PaintComposite
+   *
+   * @description:
+   *   A structure representing a 'COLR'v1 `PaintComposite` paint table.
+   *   Used for compositing two paints in a 'COLR' v1 directed acycling
+   *   graph.
+   *
+   * @fields:
+   *   source_paint ::
+   *     An @FT_OpaquePaint object referencing the source that is to be
+   *     composited.
+   *
+   *   composite_mode ::
+   *     An @FT_Composite_Mode enum value determining the composition
+   *     operation.
+   *
+   *   backdrop_paint ::
+   *     An @FT_OpaquePaint object referencing the backdrop paint that
+   *     `source_paint` is composited onto.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_PaintComposite_
+  {
+    FT_OpaquePaint     source_paint;
+    FT_Composite_Mode  composite_mode;
+    FT_OpaquePaint     backdrop_paint;
+
+  } FT_PaintComposite;
+
+
+  /**************************************************************************
+   *
+   * @union:
+   *   FT_COLR_Paint
+   *
+   * @description:
+   *   A union object representing format and details of a paint table of a
+   *   'COLR' v1 font, see
+   *   'https://github.com/googlefonts/colr-gradients-spec'.  Use
+   *   @FT_Get_Paint to retrieve a @FT_COLR_Paint for an @FT_OpaquePaint
+   *   object.
+   *
+   * @fields:
+   *   format ::
+   *     The gradient format for this Paint structure.
+   *
+   *   u ::
+   *     Union of all paint table types:
+   *
+   *       * @FT_PaintColrLayers
+   *       * @FT_PaintGlyph
+   *       * @FT_PaintSolid
+   *       * @FT_PaintLinearGradient
+   *       * @FT_PaintRadialGradient
+   *       * @FT_PaintSweepGradient
+   *       * @FT_PaintTransform
+   *       * @FT_PaintTranslate
+   *       * @FT_PaintRotate
+   *       * @FT_PaintSkew
+   *       * @FT_PaintComposite
+   *       * @FT_PaintColrGlyph
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_COLR_Paint_
+  {
+    FT_PaintFormat format;
+
+    union
+    {
+      FT_PaintColrLayers      colr_layers;
+      FT_PaintGlyph           glyph;
+      FT_PaintSolid           solid;
+      FT_PaintLinearGradient  linear_gradient;
+      FT_PaintRadialGradient  radial_gradient;
+      FT_PaintSweepGradient   sweep_gradient;
+      FT_PaintTransform       transform;
+      FT_PaintTranslate       translate;
+      FT_PaintScale           scale;
+      FT_PaintRotate          rotate;
+      FT_PaintSkew            skew;
+      FT_PaintComposite       composite;
+      FT_PaintColrGlyph       colr_glyph;
+
+    } u;
+
+  } FT_COLR_Paint;
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   FT_Color_Root_Transform
+   *
+   * @description:
+   *   An enumeration to specify whether @FT_Get_Color_Glyph_Paint is to
+   *   return a root transform to configure the client's graphics context
+   *   matrix.
+   *
+   * @values:
+   *   FT_COLOR_INCLUDE_ROOT_TRANSFORM ::
+   *     Do include the root transform as the initial @FT_COLR_Paint object.
+   *
+   *   FT_COLOR_NO_ROOT_TRANSFORM ::
+   *     Do not output an initial root transform.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef enum  FT_Color_Root_Transform_
+  {
+    FT_COLOR_INCLUDE_ROOT_TRANSFORM,
+    FT_COLOR_NO_ROOT_TRANSFORM,
+
+    FT_COLOR_ROOT_TRANSFORM_MAX
+
+  } FT_Color_Root_Transform;
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_ClipBox
+   *
+   * @description:
+   *   A structure representing a 'COLR' v1 'ClipBox' table.  'COLR' v1
+   *   glyphs may optionally define a clip box for aiding allocation or
+   *   defining a maximum drawable region.  Use @FT_Get_Color_Glyph_ClipBox
+   *   to retrieve it.
+   *
+   * @fields:
+   *   bottom_left ::
+   *     The bottom left corner of the clip box as an @FT_Vector with
+   *     fixed-point coordinates in 26.6 format.
+   *
+   *   top_left ::
+   *     The top left corner of the clip box as an @FT_Vector with
+   *     fixed-point coordinates in 26.6 format.
+   *
+   *   top_right ::
+   *     The top right corner of the clip box as an @FT_Vector with
+   *     fixed-point coordinates in 26.6 format.
+   *
+   *   bottom_right ::
+   *     The bottom right corner of the clip box as an @FT_Vector with
+   *     fixed-point coordinates in 26.6 format.
+   *
+   * @since:
+   *   2.12 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  typedef struct  FT_ClipBox_
+  {
+    FT_Vector  bottom_left;
+    FT_Vector  top_left;
+    FT_Vector  top_right;
+    FT_Vector  bottom_right;
+
+  } FT_ClipBox;
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Get_Color_Glyph_Paint
+   *
+   * @description:
+   *   This is the starting point and interface to color gradient
+   *   information in a 'COLR' v1 table in OpenType fonts to recursively
+   *   retrieve the paint tables for the directed acyclic graph of a colored
+   *   glyph, given a glyph ID.
+   *
+   *     https://github.com/googlefonts/colr-gradients-spec
+   *
+   *   In a 'COLR' v1 font, each color glyph defines a directed acyclic
+   *   graph of nested paint tables, such as `PaintGlyph`, `PaintSolid`,
+   *   `PaintLinearGradient`, `PaintRadialGradient`, and so on.  Using this
+   *   function and specifying a glyph ID, one retrieves the root paint
+   *   table for this glyph ID.
+   *
+   *   This function allows control whether an initial root transform is
+   *   returned to configure scaling, transform, and translation correctly
+   *   on the client's graphics context.  The initial root transform is
+   *   computed and returned according to the values configured for @FT_Size
+   *   and @FT_Set_Transform on the @FT_Face object, see below for details
+   *   of the `root_transform` parameter.  This has implications for a
+   *   client 'COLR' v1 implementation: When this function returns an
+   *   initially computed root transform, at the time of executing the
+   *   @FT_PaintGlyph operation, the contours should be retrieved using
+   *   @FT_Load_Glyph at unscaled, untransformed size.  This is because the
+   *   root transform applied to the graphics context will take care of
+   *   correct scaling.
+   *
+   *   Alternatively, to allow hinting of contours, at the time of executing
+   *   @FT_Load_Glyph, the current graphics context transformation matrix
+   *   can be decomposed into a scaling matrix and a remainder, and
+   *   @FT_Load_Glyph can be used to retrieve the contours at scaled size.
+   *   Care must then be taken to blit or clip to the graphics context with
+   *   taking this remainder transformation into account.
+   *
+   * @input:
+   *   face ::
+   *     A handle to the parent face object.
+   *
+   *   base_glyph ::
+   *     The glyph index for which to retrieve the root paint table.
+   *
+   *   root_transform ::
+   *     Specifies whether an initially computed root is returned by the
+   *     @FT_PaintTransform operation to account for the activated size
+   *     (see @FT_Activate_Size) and the configured transform and translate
+   *     (see @FT_Set_Transform).
+   *
+   *     This root transform is returned before nodes of the glyph graph of
+   *     the font are returned.  Subsequent @FT_COLR_Paint structures
+   *     contain unscaled and untransformed values.  The inserted root
+   *     transform enables the client application to apply an initial
+   *     transform to its graphics context.  When executing subsequent
+   *     FT_COLR_Paint operations, values from @FT_COLR_Paint operations
+   *     will ultimately be correctly scaled because of the root transform
+   *     applied to the graphics context.  Use
+   *     @FT_COLOR_INCLUDE_ROOT_TRANSFORM to include the root transform, use
+   *     @FT_COLOR_NO_ROOT_TRANSFORM to not include it.  The latter may be
+   *     useful when traversing the 'COLR' v1 glyph graph and reaching a
+   *     @FT_PaintColrGlyph.  When recursing into @FT_PaintColrGlyph and
+   *     painting that inline, no additional root transform is needed as it
+   *     has already been applied to the graphics context at the beginning
+   *     of drawing this glyph.
+   *
+   * @output:
+   *   paint ::
+   *     The @FT_OpaquePaint object that references the actual paint table.
+   *
+   *     The respective actual @FT_COLR_Paint object is retrieved via
+   *     @FT_Get_Paint.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  If no color glyph is found, or the root
+   *   paint could not be retrieved, value~0 gets returned.  In case of an
+   *   error, value~0 is returned also.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  FT_EXPORT( FT_Bool )
+  FT_Get_Color_Glyph_Paint( FT_Face                  face,
+                            FT_UInt                  base_glyph,
+                            FT_Color_Root_Transform  root_transform,
+                            FT_OpaquePaint*          paint );
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Get_Color_Glyph_ClipBox
+   *
+   * @description:
+   *   Search for a 'COLR' v1 clip box for the specified `base_glyph` and
+   *   fill the `clip_box` parameter with the 'COLR' v1 'ClipBox' information
+   *   if one is found.
+   *
+   * @input:
+   *   face ::
+   *     A handle to the parent face object.
+   *
+   *   base_glyph ::
+   *     The glyph index for which to retrieve the clip box.
+   *
+   * @output:
+   *   clip_box ::
+   *     The clip box for the requested `base_glyph` if one is found.  The
+   *     clip box is computed taking scale and transformations configured on
+   *     the @FT_Face into account.  @FT_ClipBox contains @FT_Vector values
+   *     in 26.6 format.
+   *
+   * @return:
+   *   Value~1 if a clip box is found.  If no clip box is found or an error
+   *   occured, value~0 is returned.
+   *
+   * @note:
+   *   To retrieve the clip box in font units, reset scale to units-per-em
+   *   and remove transforms configured using @FT_Set_Transform.
+   *
+   * @since:
+   *   2.12 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  FT_EXPORT( FT_Bool )
+  FT_Get_Color_Glyph_ClipBox( FT_Face      face,
+                              FT_UInt      base_glyph,
+                              FT_ClipBox*  clip_box );
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Get_Paint_Layers
+   *
+   * @description:
+   *   Access the layers of a `PaintColrLayers` table.
+   *
+   *   If the root paint of a color glyph, or a nested paint of a 'COLR'
+   *   glyph is a `PaintColrLayers` table, this function retrieves the
+   *   layers of the `PaintColrLayers` table.
+   *
+   *   The @FT_PaintColrLayers object contains an @FT_LayerIterator, which
+   *   is used here to iterate over the layers.  Each layer is returned as
+   *   an @FT_OpaquePaint object, which then can be used with @FT_Get_Paint
+   *   to retrieve the actual paint object.
+   *
+   * @input:
+   *   face ::
+   *     A handle to the parent face object.
+   *
+   * @inout:
+   *   iterator ::
+   *     The @FT_LayerIterator from an @FT_PaintColrLayers object, for which
+   *     the layers are to be retrieved.  The internal state of the iterator
+   *     is incremented after one call to this function for retrieving one
+   *     layer.
+   *
+   * @output:
+   *   paint ::
+   *     The @FT_OpaquePaint object that references the actual paint table.
+   *     The respective actual @FT_COLR_Paint object is retrieved via
+   *     @FT_Get_Paint.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  Value~0 gets returned when the paint
+   *   object can not be retrieved or any other error occurs.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  FT_EXPORT( FT_Bool )
+  FT_Get_Paint_Layers( FT_Face            face,
+                       FT_LayerIterator*  iterator,
+                       FT_OpaquePaint*    paint );
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Get_Colorline_Stops
+   *
+   * @description:
+   *   This is an interface to color gradient information in a 'COLR' v1
+   *   table in OpenType fonts to iteratively retrieve the gradient and
+   *   solid fill information for colored glyph layers for a specified glyph
+   *   ID.
+   *
+   *     https://github.com/googlefonts/colr-gradients-spec
+   *
+   * @input:
+   *   face ::
+   *     A handle to the parent face object.
+   *
+   * @inout:
+   *   iterator ::
+   *     The retrieved @FT_ColorStopIterator, configured on an @FT_ColorLine,
+   *     which in turn got retrieved via paint information in
+   *     @FT_PaintLinearGradient or @FT_PaintRadialGradient.
+   *
+   * @output:
+   *   color_stop ::
+   *     Color index and alpha value for the retrieved color stop.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  If there are no more color stops,
+   *   value~0 gets returned.  In case of an error, value~0 is returned
+   *   also.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  FT_EXPORT( FT_Bool )
+  FT_Get_Colorline_Stops( FT_Face                face,
+                          FT_ColorStop*          color_stop,
+                          FT_ColorStopIterator*  iterator );
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *  FT_Get_Paint
+   *
+   * @description:
+   *   Access the details of a paint using an @FT_OpaquePaint opaque paint
+   *   object, which internally stores the offset to the respective `Paint`
+   *   object in the 'COLR' table.
+   *
+   * @input:
+   *   face ::
+   *     A handle to the parent face object.
+   *
+   *   opaque_paint ::
+   *     The opaque paint object for which the underlying @FT_COLR_Paint
+   *     data is to be retrieved.
+   *
+   * @output:
+   *   paint ::
+   *     The specific @FT_COLR_Paint object containing information coming
+   *     from one of the font's `Paint*` tables.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  Value~0 if no details can be found for
+   *   this paint or any other error occured.
+   *
+   * @since:
+   *   2.11 -- **currently experimental only!**  There might be changes
+   *   without retaining backward compatibility of both the API and ABI.
+   *
+   */
+  FT_EXPORT( FT_Bool )
+  FT_Get_Paint( FT_Face         face,
+                FT_OpaquePaint  opaque_paint,
+                FT_COLR_Paint*  paint );
+
   /* */
 
 
diff --git a/include/freetype/ftdriver.h b/include/freetype/ftdriver.h
index 804ec34..4936639 100644
--- a/include/freetype/ftdriver.h
+++ b/include/freetype/ftdriver.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for controlling driver modules (specification only).
  *
- * Copyright (C) 2017-2020 by
+ * Copyright (C) 2017-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -53,10 +53,10 @@
    *   reasons.
    *
    *   Available properties are @increase-x-height, @no-stem-darkening
-   *   (experimental), @darkening-parameters (experimental), @warping
-   *   (experimental), @glyph-to-script-map (experimental), @fallback-script
-   *   (experimental), and @default-script (experimental), as documented in
-   *   the @properties section.
+   *   (experimental), @darkening-parameters (experimental),
+   *   @glyph-to-script-map (experimental), @fallback-script (experimental),
+   *   and @default-script (experimental), as documented in the @properties
+   *   section.
    *
    */
 
@@ -84,15 +84,15 @@
    *   @properties section.
    *
    *
-   *   **Hinting and antialiasing principles of the new engine**
+   *   **Hinting and anti-aliasing principles of the new engine**
    *
    *   The rasterizer is positioning horizontal features (e.g., ascender
    *   height & x-height, or crossbars) on the pixel grid and minimizing the
-   *   amount of antialiasing applied to them, while placing vertical
+   *   amount of anti-aliasing applied to them, while placing vertical
    *   features (vertical stems) on the pixel grid without hinting, thus
    *   representing the stem position and weight accurately.  Sometimes the
    *   vertical stems may be only partially black.  In this context,
-   *   'antialiasing' means that stems are not positioned exactly on pixel
+   *   'anti-aliasing' means that stems are not positioned exactly on pixel
    *   borders, causing a fuzzy appearance.
    *
    *   There are two principles behind this approach.
@@ -108,7 +108,7 @@
    *   sizes are comparable to kerning values and thus would be noticeable
    *   (and distracting) while reading if hinting were applied.
    *
-   *   One of the reasons to not hint horizontally is antialiasing for LCD
+   *   One of the reasons to not hint horizontally is anti-aliasing for LCD
    *   screens: The pixel geometry of modern displays supplies three vertical
    *   subpixels as the eye moves horizontally across each visible pixel.  On
    *   devices where we can be certain this characteristic is present a
@@ -116,7 +116,7 @@
    *   weight.  In Western writing systems this turns out to be the more
    *   critical direction anyway; the weights and spacing of vertical stems
    *   (see above) are central to Armenian, Cyrillic, Greek, and Latin type
-   *   designs.  Even when the rasterizer uses greyscale antialiasing instead
+   *   designs.  Even when the rasterizer uses greyscale anti-aliasing instead
    *   of color (a necessary compromise when one doesn't know the screen
    *   characteristics), the unhinted vertical features preserve the design's
    *   weight and spacing much better than aliased type would.
@@ -362,12 +362,8 @@
    *   The same holds for the Type~1 and CID modules if compiled with
    *   `T1_CONFIG_OPTION_OLD_ENGINE`.
    *
-   *   For the 'cff' module, the default engine is 'freetype' if
-   *   `CFF_CONFIG_OPTION_OLD_ENGINE` is defined, and 'adobe' otherwise.
-   *
-   *   For both the 'type1' and 't1cid' modules, the default engine is
-   *   'freetype' if `T1_CONFIG_OPTION_OLD_ENGINE` is defined, and 'adobe'
-   *   otherwise.
+   *   For the 'cff' module, the default engine is 'adobe'.  For both the
+   *   'type1' and 't1cid' modules, the default engine is 'adobe', too.
    *
    * @note:
    *   This property can be used with @FT_Property_Get also.
@@ -1166,48 +1162,18 @@
    *   warping
    *
    * @description:
-   *   **Experimental only**
+   *   **Obsolete**
    *
-   *   If FreeType gets compiled with option `AF_CONFIG_OPTION_USE_WARPER` to
-   *   activate the warp hinting code in the auto-hinter, this property
-   *   switches warping on and off.
+   *   This property was always experimental and probably never worked
+   *   correctly.  It was entirely removed from the FreeType~2 sources.  This
+   *   entry is only here for historical reference.
    *
-   *   Warping only works in 'normal' auto-hinting mode replacing it.  The
-   *   idea of the code is to slightly scale and shift a glyph along the
+   *   Warping only worked in 'normal' auto-hinting mode replacing it.  The
+   *   idea of the code was to slightly scale and shift a glyph along the
    *   non-hinted dimension (which is usually the horizontal axis) so that as
-   *   much of its segments are aligned (more or less) to the grid.  To find
+   *   much of its segments were aligned (more or less) to the grid.  To find
    *   out a glyph's optimal scaling and shifting value, various parameter
-   *   combinations are tried and scored.
-   *
-   *   By default, warping is off.
-   *
-   * @note:
-   *   This property can be used with @FT_Property_Get also.
-   *
-   *   This property can be set via the `FREETYPE_PROPERTIES` environment
-   *   variable (using values 1 and 0 for 'on' and 'off', respectively).
-   *
-   *   The warping code can also change advance widths.  Have a look at the
-   *   `lsb_delta` and `rsb_delta` fields in the @FT_GlyphSlotRec structure
-   *   for details on improving inter-glyph distances while rendering.
-   *
-   *   Since warping is a global property of the auto-hinter it is best to
-   *   change its value before rendering any face.  Otherwise, you should
-   *   reload all faces that get auto-hinted in 'normal' hinting mode.
-   *
-   * @example:
-   *   This example shows how to switch on warping (omitting the error
-   *   handling).
-   *
-   *   ```
-   *     FT_Library  library;
-   *     FT_Bool     warping = 1;
-   *
-   *
-   *     FT_Init_FreeType( &library );
-   *
-   *     FT_Property_Set( library, "autofitter", "warping", &warping );
-   *   ```
+   *   combinations were tried and scored.
    *
    * @since:
    *   2.6
diff --git a/include/freetype/fterrdef.h b/include/freetype/fterrdef.h
index 895d2d4..6e9c4cc 100644
--- a/include/freetype/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
  *
  *   FreeType error codes (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/fterrors.h b/include/freetype/fterrors.h
index 60a637c..151941d 100644
--- a/include/freetype/fterrors.h
+++ b/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
  *
  *   FreeType error code handling (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -281,6 +281,8 @@
   FT_EXPORT( const char* )
   FT_Error_String( FT_Error  error_code );
 
+  /* */
+
 FT_END_HEADER
 
 
diff --git a/include/freetype/ftfntfmt.h b/include/freetype/ftfntfmt.h
index f803349..8e68a4a 100644
--- a/include/freetype/ftfntfmt.h
+++ b/include/freetype/ftfntfmt.h
@@ -4,7 +4,7 @@
  *
  *   Support functions for font formats.
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftgasp.h b/include/freetype/ftgasp.h
index 6b76882..76c45eb 100644
--- a/include/freetype/ftgasp.h
+++ b/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
  *
  *   Access of TrueType's 'gasp' table (specification).
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftglyph.h b/include/freetype/ftglyph.h
index 704619e..26b32ed 100644
--- a/include/freetype/ftglyph.h
+++ b/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
  *
  *   FreeType convenience functions to handle glyphs (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -337,9 +337,9 @@
    *   vector.
    */
   FT_EXPORT( FT_Error )
-  FT_Glyph_Transform( FT_Glyph    glyph,
-                      FT_Matrix*  matrix,
-                      FT_Vector*  delta );
+  FT_Glyph_Transform( FT_Glyph          glyph,
+                      const FT_Matrix*  matrix,
+                      const FT_Vector*  delta );
 
 
   /**************************************************************************
@@ -569,10 +569,10 @@
    *   ```
    */
   FT_EXPORT( FT_Error )
-  FT_Glyph_To_Bitmap( FT_Glyph*       the_glyph,
-                      FT_Render_Mode  render_mode,
-                      FT_Vector*      origin,
-                      FT_Bool         destroy );
+  FT_Glyph_To_Bitmap( FT_Glyph*         the_glyph,
+                      FT_Render_Mode    render_mode,
+                      const FT_Vector*  origin,
+                      FT_Bool           destroy );
 
 
   /**************************************************************************
diff --git a/include/freetype/ftgxval.h b/include/freetype/ftgxval.h
index 354460a..21bbbde 100644
--- a/include/freetype/ftgxval.h
+++ b/include/freetype/ftgxval.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating TrueTypeGX/AAT tables (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * Masatake YAMATO, Redhat K.K,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/include/freetype/ftgzip.h b/include/freetype/ftgzip.h
index ec5939a..ba82bab 100644
--- a/include/freetype/ftgzip.h
+++ b/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
  *
  *   Gzip-compressed stream support.
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index 7491162..88533b8 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
  *   FreeType glyph image formats and default raster interface
  *   (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -28,11 +28,6 @@
 #define FTIMAGE_H_
 
 
-  /* STANDALONE_ is from ftgrays.c */
-#ifndef STANDALONE_
-#endif
-
-
 FT_BEGIN_HEADER
 
 
@@ -201,6 +196,11 @@
 #define ft_pixel_mode_pal2   FT_PIXEL_MODE_GRAY2
 #define ft_pixel_mode_pal4   FT_PIXEL_MODE_GRAY4
 
+  /* */
+
+  /* For debugging, the @FT_Pixel_Mode enumeration must stay in sync */
+  /* with the `pixel_modes` array in file `ftobjs.c`.                */
+
 
   /**************************************************************************
    *
@@ -695,11 +695,13 @@
    *   to get a simple enumeration without assigning special numbers.
    */
 #ifndef FT_IMAGE_TAG
-#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )  \
-          value = ( ( (unsigned long)_x1 << 24 ) | \
-                    ( (unsigned long)_x2 << 16 ) | \
-                    ( (unsigned long)_x3 << 8  ) | \
-                      (unsigned long)_x4         )
+
+#define FT_IMAGE_TAG( value, _x1, _x2, _x3, _x4 )                         \
+          value = ( ( FT_STATIC_BYTE_CAST( unsigned long, _x1 ) << 24 ) | \
+                    ( FT_STATIC_BYTE_CAST( unsigned long, _x2 ) << 16 ) | \
+                    ( FT_STATIC_BYTE_CAST( unsigned long, _x3 ) << 8  ) | \
+                      FT_STATIC_BYTE_CAST( unsigned long, _x4 )         )
+
 #endif /* FT_IMAGE_TAG */
 
 
@@ -772,17 +774,6 @@
   /*************************************************************************/
 
 
-  /**************************************************************************
-   *
-   * A raster is a scan converter, in charge of rendering an outline into a
-   * bitmap.  This section contains the public API for rasters.
-   *
-   * Note that in FreeType 2, all rasters are now encapsulated within
-   * specific modules called 'renderers'.  See `ftrender.h` for more details
-   * on renderers.
-   *
-   */
-
 
   /**************************************************************************
    *
@@ -796,16 +787,35 @@
    *   How vectorial outlines are converted into bitmaps and pixmaps.
    *
    * @description:
-   *   This section contains technical definitions.
+   *   A raster or a rasterizer is a scan converter in charge of producing a
+   *   pixel coverage bitmap that can be used as an alpha channel when
+   *   compositing a glyph with a background.  FreeType comes with two
+   *   rasterizers: bilevel `raster1` and anti-aliased `smooth` are two
+   *   separate modules.  They are usually called from the high-level
+   *   @FT_Load_Glyph or @FT_Render_Glyph functions and produce the entire
+   *   coverage bitmap at once, while staying largely invisible to users.
+   *
+   *   Instead of working with complete coverage bitmaps, it is also possible
+   *   to intercept consecutive pixel runs on the same scanline with the same
+   *   coverage, called _spans_, and process them individually.  Only the
+   *   `smooth` rasterizer permits this when calling @FT_Outline_Render with
+   *   @FT_Raster_Params as described below.
+   *
+   *   Working with either complete bitmaps or spans it is important to think
+   *   of them as colorless coverage objects suitable as alpha channels to
+   *   blend arbitrary colors with a background.  For best results, it is
+   *   recommended to use gamma correction, too.
+   *
+   *   This section also describes the public API needed to set up alternative
+   *   @FT_Renderer modules.
    *
    * @order:
-   *   FT_Raster
    *   FT_Span
    *   FT_SpanFunc
-   *
    *   FT_Raster_Params
    *   FT_RASTER_FLAG_XXX
    *
+   *   FT_Raster
    *   FT_Raster_NewFunc
    *   FT_Raster_DoneFunc
    *   FT_Raster_ResetFunc
@@ -818,24 +828,12 @@
 
   /**************************************************************************
    *
-   * @type:
-   *   FT_Raster
-   *
-   * @description:
-   *   An opaque handle (pointer) to a raster object.  Each object can be
-   *   used independently to convert an outline into a bitmap or pixmap.
-   */
-  typedef struct FT_RasterRec_*  FT_Raster;
-
-
-  /**************************************************************************
-   *
    * @struct:
    *   FT_Span
    *
    * @description:
-   *   A structure used to model a single span of gray pixels when rendering
-   *   an anti-aliased bitmap.
+   *   A structure to model a single span of consecutive pixels when
+   *   rendering an anti-aliased bitmap.
    *
    * @fields:
    *   x ::
@@ -852,8 +850,8 @@
    *   This structure is used by the span drawing callback type named
    *   @FT_SpanFunc that takes the y~coordinate of the span as a parameter.
    *
-   *   The coverage value is always between 0 and 255.  If you want less gray
-   *   values, the callback function has to reduce them.
+   *   The anti-aliased rasterizer produces coverage values from 0 to 255,
+   *   this is, from completely transparent to completely opaque.
    */
   typedef struct  FT_Span_
   {
@@ -871,8 +869,8 @@
    *
    * @description:
    *   A function used as a call-back by the anti-aliased renderer in order
-   *   to let client applications draw themselves the gray pixel spans on
-   *   each scan line.
+   *   to let client applications draw themselves the pixel spans on each
+   *   scan line.
    *
    * @input:
    *   y ::
@@ -888,11 +886,12 @@
    *     User-supplied data that is passed to the callback.
    *
    * @note:
-   *   This callback allows client applications to directly render the gray
-   *   spans of the anti-aliased bitmap to any kind of surfaces.
+   *   This callback allows client applications to directly render the spans
+   *   of the anti-aliased bitmap to any kind of surfaces.
    *
    *   This can be used to write anti-aliased outlines directly to a given
-   *   background bitmap, and even perform translucency.
+   *   background bitmap using alpha compositing.  It can also be used for
+   *   oversampling and averaging.
    */
   typedef void
   (*FT_SpanFunc)( int             y,
@@ -962,11 +961,17 @@
    *     will be clipped to a box specified in the `clip_box` field of the
    *     @FT_Raster_Params structure.  Otherwise, the `clip_box` is
    *     effectively set to the bounding box and all spans are generated.
+   *
+   *   FT_RASTER_FLAG_SDF ::
+   *     This flag is set to indicate that a signed distance field glyph
+   *     image should be generated.  This is only used while rendering with
+   *     the @FT_RENDER_MODE_SDF render mode.
    */
 #define FT_RASTER_FLAG_DEFAULT  0x0
 #define FT_RASTER_FLAG_AA       0x1
 #define FT_RASTER_FLAG_DIRECT   0x2
 #define FT_RASTER_FLAG_CLIP     0x4
+#define FT_RASTER_FLAG_SDF      0x8
 
   /* these constants are deprecated; use the corresponding */
   /* `FT_RASTER_FLAG_XXX` values instead                   */
@@ -1049,6 +1054,23 @@
 
   /**************************************************************************
    *
+   * @type:
+   *   FT_Raster
+   *
+   * @description:
+   *   An opaque handle (pointer) to a raster object.  Each object can be
+   *   used independently to convert an outline into a bitmap or pixmap.
+   *
+   * @note:
+   *   In FreeType 2, all rasters are now encapsulated within specific
+   *   @FT_Renderer modules and only used in their context.
+   *
+   */
+  typedef struct FT_RasterRec_*  FT_Raster;
+
+
+  /**************************************************************************
+   *
    * @functype:
    *   FT_Raster_NewFunc
    *
diff --git a/include/freetype/ftincrem.h b/include/freetype/ftincrem.h
index f67655e..229b947 100644
--- a/include/freetype/ftincrem.h
+++ b/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
  *
  *   FreeType incremental loading (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -213,9 +213,14 @@
    *
    * @description:
    *   A function used to retrieve the basic metrics of a given glyph index
-   *   before accessing its data.  This is necessary because, in certain
-   *   formats like TrueType, the metrics are stored in a different place
-   *   from the glyph images proper.
+   *   before accessing its data.  This allows for handling font types such
+   *   as PCL~XL Format~1, Class~2 downloaded TrueType fonts, where the glyph
+   *   metrics (`hmtx` and `vmtx` tables) are permitted to be omitted from
+   *   the font, and the relevant metrics included in the header of the glyph
+   *   outline data.  Importantly, this is not intended to allow custom glyph
+   *   metrics (for example, Postscript Metrics dictionaries), because that
+   *   conflicts with the requirements of outline hinting.  Such custom
+   *   metrics must be handled separately, by the calling application.
    *
    * @input:
    *   incremental ::
@@ -235,7 +240,7 @@
    *
    * @output:
    *   ametrics ::
-   *     The replacement glyph metrics in font units.
+   *     The glyph metrics in font units.
    *
    */
   typedef FT_Error
@@ -264,7 +269,7 @@
    *
    *   get_glyph_metrics ::
    *     The function to get glyph metrics.  May be null if the font does not
-   *     provide overriding glyph metrics.
+   *     require it.
    *
    */
   typedef struct  FT_Incremental_FuncsRec_
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
index c6995f2..18e2544 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -5,7 +5,7 @@
  *   FreeType API for color filtering of subpixel bitmap glyphs
  *   (specification).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -44,7 +44,7 @@
    *   API to control subpixel rendering.
    *
    * @description:
-   *   FreeType provides two alternative subpixel rendering technologies. 
+   *   FreeType provides two alternative subpixel rendering technologies.
    *   Should you define `FT_CONFIG_OPTION_SUBPIXEL_RENDERING` in your
    *   `ftoption.h` file, this enables ClearType-style rendering.
    *   Otherwise, Harmony LCD rendering is enabled.  These technologies are
@@ -55,13 +55,12 @@
    *   ClearType-style LCD rendering exploits the color-striped structure of
    *   LCD pixels, increasing the available resolution in the direction of
    *   the stripe (usually horizontal RGB) by a factor of~3.  Using the
-   *   subpixels coverages unfiltered can create severe color fringes
+   *   subpixel coverages unfiltered can create severe color fringes
    *   especially when rendering thin features.  Indeed, to produce
    *   black-on-white text, the nearby color subpixels must be dimmed
-   *   equally.
-   *
-   *   A good 5-tap FIR filter should be applied to subpixel coverages
-   *   regardless of pixel boundaries and should have these properties:
+   *   evenly.  Therefore, an equalizing 5-tap FIR filter should be applied
+   *   to subpixel coverages regardless of pixel boundaries and should have
+   *   these properties:
    *
    *   1. It should be symmetrical, like {~a, b, c, b, a~}, to avoid
    *      any shifts in appearance.
@@ -84,7 +83,7 @@
    *   Harmony LCD rendering is suitable to panels with any regular subpixel
    *   structure, not just monitors with 3 color striped subpixels, as long
    *   as the color subpixels have fixed positions relative to the pixel
-   *   center.  In this case, each color channel is then rendered separately
+   *   center.  In this case, each color channel can be rendered separately
    *   after shifting the outline opposite to the subpixel shift so that the
    *   coverage maps are aligned.  This method is immune to color fringes
    *   because the shifts do not change integral coverage.
@@ -101,9 +100,9 @@
    *   clockwise.  Harmony with default LCD geometry is equivalent to
    *   ClearType with light filter.
    *
-   *   As a result of ClearType filtering or Harmony rendering, the
-   *   dimensions of LCD bitmaps can be either wider or taller than the
-   *   dimensions of the corresponding outline with regard to the pixel grid.
+   *   As a result of ClearType filtering or Harmony shifts, the resulting
+   *   dimensions of LCD bitmaps can be slightly wider or taller than the
+   *   dimensions the original outline with regard to the pixel grid.
    *   For example, for @FT_RENDER_MODE_LCD, the filter adds 2~subpixels to
    *   the left, and 2~subpixels to the right.  The bitmap offset values are
    *   adjusted accordingly, so clients shouldn't need to modify their layout
diff --git a/include/freetype/ftlist.h b/include/freetype/ftlist.h
index 4588922..55f0159 100644
--- a/include/freetype/ftlist.h
+++ b/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
  *
  *   Generic list support for FreeType (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftlogging.h b/include/freetype/ftlogging.h
new file mode 100644
index 0000000..a558b85
--- /dev/null
+++ b/include/freetype/ftlogging.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+ *
+ * ftlogging.h
+ *
+ *   Additional debugging APIs.
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTLOGGING_H_
+#define FTLOGGING_H_
+
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+
+
+FT_BEGIN_HEADER
+
+
+  /**************************************************************************
+   *
+   * @section:
+   *   debugging_apis
+   *
+   * @title:
+   *   External Debugging APIs
+   *
+   * @abstract:
+   *   Public APIs to control the `FT_DEBUG_LOGGING` macro.
+   *
+   * @description:
+   *   This section contains the declarations of public functions that
+   *   enables fine control of what the `FT_DEBUG_LOGGING` macro outputs.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Trace_Set_Level
+   *
+   * @description:
+   *   Change the levels of tracing components of FreeType at run time.
+   *
+   * @input:
+   *   tracing_level ::
+   *     New tracing value.
+   *
+   * @example:
+   *   The following call makes FreeType trace everything but the 'memory'
+   *   component.
+   *
+   *   ```
+   *   FT_Trace_Set_Level( "any:7 memory:0 );
+   *   ```
+   *
+   * @note:
+   *   This function does nothing if compilation option `FT_DEBUG_LOGGING`
+   *   isn't set.
+   *
+   * @since:
+   *   2.11
+   *
+   */
+  FT_EXPORT( void )
+  FT_Trace_Set_Level( const char*  tracing_level );
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Trace_Set_Default_Level
+   *
+   * @description:
+   *   Reset tracing value of FreeType's components to the default value
+   *   (i.e., to the value of the `FT2_DEBUG` environment value or to NULL
+   *   if `FT2_DEBUG` is not set).
+   *
+   * @note:
+   *   This function does nothing if compilation option `FT_DEBUG_LOGGING`
+   *   isn't set.
+   *
+   * @since:
+   *   2.11
+   *
+   */
+  FT_EXPORT( void )
+  FT_Trace_Set_Default_Level( void );
+
+
+  /**************************************************************************
+   *
+   * @functype:
+   *   FT_Custom_Log_Handler
+   *
+   * @description:
+   *   A function typedef that is used to handle the logging of tracing and
+   *   debug messages on a file system.
+   *
+   * @input:
+   *   ft_component ::
+   *     The name of `FT_COMPONENT` from which the current debug or error
+   *     message is produced.
+   *
+   *   fmt ::
+   *     Actual debug or tracing message.
+   *
+   *   args::
+   *     Arguments of debug or tracing messages.
+   *
+   * @since:
+   *   2.11
+   *
+   */
+  typedef void
+  (*FT_Custom_Log_Handler)( const char*  ft_component,
+                            const char*  fmt,
+                            va_list      args );
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Set_Log_Handler
+   *
+   * @description:
+   *   A function to set a custom log handler.
+   *
+   * @input:
+   *   handler ::
+   *     New logging function.
+   *
+   * @note:
+   *   This function does nothing if compilation option `FT_DEBUG_LOGGING`
+   *   isn't set.
+   *
+   * @since:
+   *   2.11
+   *
+   */
+  FT_EXPORT( void )
+  FT_Set_Log_Handler( FT_Custom_Log_Handler  handler );
+
+
+  /**************************************************************************
+   *
+   * @function:
+   *   FT_Set_Default_Log_Handler
+   *
+   * @description:
+   *   A function to undo the effect of @FT_Set_Log_Handler, resetting the
+   *   log handler to FreeType's built-in version.
+   *
+   * @note:
+   *   This function does nothing if compilation option `FT_DEBUG_LOGGING`
+   *   isn't set.
+   *
+   * @since:
+   *   2.11
+   *
+   */
+  FT_EXPORT( void )
+  FT_Set_Default_Log_Handler( void );
+
+  /* */
+
+
+FT_END_HEADER
+
+#endif /* FTLOGGING_H_ */
+
+
+/* END */
diff --git a/include/freetype/ftlzw.h b/include/freetype/ftlzw.h
index ae46ad6..fce1c9c 100644
--- a/include/freetype/ftlzw.h
+++ b/include/freetype/ftlzw.h
@@ -4,7 +4,7 @@
  *
  *   LZW-compressed stream support.
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftmac.h b/include/freetype/ftmac.h
index c9de981..607af9b 100644
--- a/include/freetype/ftmac.h
+++ b/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
  *
  *   Additional Mac-specific API.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftmm.h b/include/freetype/ftmm.h
index d8781a8..32579e9 100644
--- a/include/freetype/ftmm.h
+++ b/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Multiple Master font interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftmodapi.h b/include/freetype/ftmodapi.h
index 3f7ae82..b77d356 100644
--- a/include/freetype/ftmodapi.h
+++ b/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
  *
  *   FreeType modules public interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -45,10 +45,12 @@
    *
    * @description:
    *   The definitions below are used to manage modules within FreeType.
-   *   Modules can be added, upgraded, and removed at runtime.  Additionally,
-   *   some module properties can be controlled also.
+   *   Internal and external modules can be added, upgraded, and removed at
+   *   runtime.  For example, an alternative renderer or proprietary font
+   *   driver can be registered and prioritized.  Additionally, some module
+   *   properties can also be controlled.
    *
-   *   Here is a list of possible values of the `module_name` field in the
+   *   Here is a list of existing values of the `module_name` field in the
    *   @FT_Module_Class structure.
    *
    *   ```
@@ -86,6 +88,7 @@
    *   FT_Remove_Module
    *   FT_Add_Default_Modules
    *
+   *   FT_FACE_DRIVER_NAME
    *   FT_Property_Set
    *   FT_Property_Get
    *   FT_Set_Default_Properties
@@ -330,6 +333,27 @@
 
   /**************************************************************************
    *
+   * @macro:
+   *   FT_FACE_DRIVER_NAME
+   *
+   * @description:
+   *   A macro that retrieves the name of a font driver from a face object.
+   *
+   * @note:
+   *   The font driver name is a valid `module_name` for @FT_Property_Set
+   *   and @FT_Property_Get.  This is not the same as @FT_Get_Font_Format.
+   *
+   * @since:
+   *   2.11
+   *
+   */
+#define FT_FACE_DRIVER_NAME( face )                                     \
+          ( ( *FT_REINTERPRET_CAST( FT_Module_Class**,                  \
+                                    ( face )->driver ) )->module_name )
+
+
+  /**************************************************************************
+   *
    * @function:
    *    FT_Property_Set
    *
@@ -485,8 +509,7 @@
    *
    *   ```
    *     FREETYPE_PROPERTIES=truetype:interpreter-version=35 \
-   *                         cff:no-stem-darkening=0 \
-   *                         autofitter:warping=1
+   *                         cff:no-stem-darkening=0
    *   ```
    *
    * @inout:
diff --git a/include/freetype/ftmoderr.h b/include/freetype/ftmoderr.h
index f05fc53..b417cd5 100644
--- a/include/freetype/ftmoderr.h
+++ b/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
  *
  *   FreeType module error offsets (specification).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -171,6 +171,7 @@
   FT_MODERRDEF( Type42,   0x1400, "Type 42 module" )
   FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" )
   FT_MODERRDEF( GXvalid,  0x1600, "GX validation module" )
+  FT_MODERRDEF( Sdf,      0x1700, "Signed distance field raster module" )
 
 
 #ifdef FT_MODERR_END_LIST
diff --git a/include/freetype/ftotval.h b/include/freetype/ftotval.h
index 9c00ad3..00f9727 100644
--- a/include/freetype/ftotval.h
+++ b/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating OpenType tables (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftoutln.h b/include/freetype/ftoutln.h
index 84e9b14..6bb5f80 100644
--- a/include/freetype/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
  *   Support for the FT_Outline type used to store glyph shapes of
  *   most scalable font formats (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftparams.h b/include/freetype/ftparams.h
index 55ea2a3..04a3f44 100644
--- a/include/freetype/ftparams.h
+++ b/include/freetype/ftparams.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for possible FT_Parameter tags (specification only).
  *
- * Copyright (C) 2017-2020 by
+ * Copyright (C) 2017-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftpfr.h b/include/freetype/ftpfr.h
index 9a5383f..fbdb14c 100644
--- a/include/freetype/ftpfr.h
+++ b/include/freetype/ftpfr.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing PFR-specific data (specification only).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftrender.h b/include/freetype/ftrender.h
index 8007951..48d489d 100644
--- a/include/freetype/ftrender.h
+++ b/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
  *
  *   FreeType renderer modules public interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftsizes.h b/include/freetype/ftsizes.h
index a8682a3..2236639 100644
--- a/include/freetype/ftsizes.h
+++ b/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
  *
  *   FreeType size objects management (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftsnames.h b/include/freetype/ftsnames.h
index 729e6ab..c7f6581 100644
--- a/include/freetype/ftsnames.h
+++ b/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
  *
  *   This is _not_ used to retrieve glyph names!
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftstroke.h b/include/freetype/ftstroke.h
index a759c94..88b2a8a 100644
--- a/include/freetype/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
  *
  *   FreeType path stroker (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftsynth.h b/include/freetype/ftsynth.h
index bdb4c57..861dcb5 100644
--- a/include/freetype/ftsynth.h
+++ b/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
  *   FreeType synthesizing code for emboldening and slanting
  *   (specification).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/ftsystem.h b/include/freetype/ftsystem.h
index 22aead7..e5abb85 100644
--- a/include/freetype/ftsystem.h
+++ b/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
  *
  *   FreeType low-level system interface definition (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/fttrigon.h b/include/freetype/fttrigon.h
index 2ce6b32..dbe7b0d 100644
--- a/include/freetype/fttrigon.h
+++ b/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
  *
  *   FreeType trigonometric functions (specification).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/fttypes.h b/include/freetype/fttypes.h
index aaeb9e8..699bd00 100644
--- a/include/freetype/fttypes.h
+++ b/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
  *
  *   FreeType simple types definitions (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -413,7 +413,7 @@
   typedef struct  FT_Data_
   {
     const FT_Byte*  pointer;
-    FT_Int          length;
+    FT_UInt         length;
 
   } FT_Data;
 
@@ -479,18 +479,17 @@
    *
    * @description:
    *   This macro converts four-letter tags that are used to label TrueType
-   *   tables into an unsigned long, to be used within FreeType.
+   *   tables into an `FT_Tag` type, to be used within FreeType.
    *
    * @note:
    *   The produced values **must** be 32-bit integers.  Don't redefine this
    *   macro.
    */
-#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
-          (FT_Tag)                        \
-          ( ( (FT_ULong)_x1 << 24 ) |     \
-            ( (FT_ULong)_x2 << 16 ) |     \
-            ( (FT_ULong)_x3 <<  8 ) |     \
-              (FT_ULong)_x4         )
+#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 )                  \
+          ( ( FT_STATIC_BYTE_CAST( FT_Tag, _x1 ) << 24 ) | \
+            ( FT_STATIC_BYTE_CAST( FT_Tag, _x2 ) << 16 ) | \
+            ( FT_STATIC_BYTE_CAST( FT_Tag, _x3 ) <<  8 ) | \
+              FT_STATIC_BYTE_CAST( FT_Tag, _x4 )         )
 
 
   /*************************************************************************/
@@ -588,7 +587,7 @@
 
 
 #define FT_IS_EMPTY( list )  ( (list).head == 0 )
-#define FT_BOOL( x )  ( (FT_Bool)( (x) != 0 ) )
+#define FT_BOOL( x )         FT_STATIC_CAST( FT_Bool, (x) != 0 )
 
   /* concatenate C tokens */
 #define FT_ERR_XCAT( x, y )  x ## y
diff --git a/include/freetype/ftwinfnt.h b/include/freetype/ftwinfnt.h
index 786528c..f30f447 100644
--- a/include/freetype/ftwinfnt.h
+++ b/include/freetype/ftwinfnt.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing Windows fnt-specific data.
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -55,7 +55,7 @@
    *   FT_WinFNT_ID_XXX
    *
    * @description:
-   *   A list of valid values for the `charset` byte in @FT_WinFNT_HeaderRec. 
+   *   A list of valid values for the `charset` byte in @FT_WinFNT_HeaderRec.
    *   Exact mapping tables for the various 'cpXXXX' encodings (except for
    *   'cp1361') can be found at 'ftp://ftp.unicode.org/Public/' in the
    *   `MAPPINGS/VENDORS/MICSFT/WINDOWS` subdirectory.  'cp1361' is roughly a
diff --git a/include/freetype/internal/autohint.h b/include/freetype/internal/autohint.h
index 2a472e2..01585f5 100644
--- a/include/freetype/internal/autohint.h
+++ b/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
  *
  *   High-level 'autohint' module-specific interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/cffotypes.h b/include/freetype/internal/cffotypes.h
index a316fd1..a91dd55 100644
--- a/include/freetype/internal/cffotypes.h
+++ b/include/freetype/internal/cffotypes.h
@@ -4,7 +4,7 @@
  *
  *   Basic OpenType/CFF object type definitions (specification).
  *
- * Copyright (C) 2017-2020 by
+ * Copyright (C) 2017-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/cfftypes.h b/include/freetype/internal/cfftypes.h
index f21167b..99e8d41 100644
--- a/include/freetype/internal/cfftypes.h
+++ b/include/freetype/internal/cfftypes.h
@@ -5,7 +5,7 @@
  *   Basic OpenType/CFF type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/compiler-macros.h b/include/freetype/internal/compiler-macros.h
index 97c18d3..d8b61b3 100644
--- a/include/freetype/internal/compiler-macros.h
+++ b/include/freetype/internal/compiler-macros.h
@@ -4,7 +4,7 @@
  *
  *   Compiler-specific macro definitions used internally by FreeType.
  *
- * Copyright (C) 2020 by
+ * Copyright (C) 2020-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -71,12 +71,18 @@
    */
 #define FT_DUMMY_STMNT  FT_BEGIN_STMNT FT_END_STMNT
 
-#ifdef _WIN64
+#ifdef __UINTPTR_TYPE__
+  /*
+   * GCC and Clang both provide a `__UINTPTR_TYPE__` that can be used to
+   * avoid a dependency on `stdint.h`.
+   */
+#  define FT_UINT_TO_POINTER( x )  (void *)(__UINTPTR_TYPE__)(x)
+#elif defined( _WIN64 )
   /* only 64bit Windows uses the LLP64 data model, i.e., */
   /* 32-bit integers, 64-bit pointers.                   */
-#define FT_UINT_TO_POINTER( x )  (void *)(unsigned __int64)(x)
+#  define FT_UINT_TO_POINTER( x )  (void *)(unsigned __int64)(x)
 #else
-#define FT_UINT_TO_POINTER( x )  (void *)(unsigned long)(x)
+#  define FT_UINT_TO_POINTER( x )  (void *)(unsigned long)(x)
 #endif
 
   /*
@@ -216,79 +222,91 @@
 #define FT_EXPORT_VAR( x )  FT_FUNCTION_DECLARATION( x )
 #endif
 
-  /* When compiling FreeType as a DLL or DSO with hidden visibility,   */
-  /* some systems/compilers need a special attribute in front OR after */
-  /* the return type of function declarations.                         */
-  /*                                                                   */
-  /* Two macros are used within the FreeType source code to define     */
-  /* exported library functions: `FT_EXPORT` and `FT_EXPORT_DEF`.      */
-  /*                                                                   */
-  /* - `FT_EXPORT( return_type )`                                      */
-  /*                                                                   */
-  /*   is used in a function declaration, as in                        */
-  /*                                                                   */
-  /*   ```                                                             */
-  /*     FT_EXPORT( FT_Error )                                         */
-  /*     FT_Init_FreeType( FT_Library*  alibrary );                    */
-  /*   ```                                                             */
-  /*                                                                   */
-  /* - `FT_EXPORT_DEF( return_type )`                                  */
-  /*                                                                   */
-  /*   is used in a function definition, as in                         */
-  /*                                                                   */
-  /*   ```                                                             */
-  /*     FT_EXPORT_DEF( FT_Error )                                     */
-  /*     FT_Init_FreeType( FT_Library*  alibrary )                     */
-  /*     {                                                             */
-  /*       ... some code ...                                           */
-  /*       return FT_Err_Ok;                                           */
-  /*     }                                                             */
-  /*   ```                                                             */
-  /*                                                                   */
-  /* You can provide your own implementation of `FT_EXPORT` and        */
-  /* `FT_EXPORT_DEF` here if you want.                                 */
-  /*                                                                   */
-  /* To export a variable, use `FT_EXPORT_VAR`.                        */
-  /*                                                                   */
+  /*
+   * When compiling FreeType as a DLL or DSO with hidden visibility,
+   * some systems/compilers need a special attribute in front OR after
+   * the return type of function declarations.
+   *
+   * Two macros are used within the FreeType source code to define
+   * exported library functions: `FT_EXPORT` and `FT_EXPORT_DEF`.
+   *
+   * - `FT_EXPORT( return_type )`
+   *
+   *   is used in a function declaration, as in
+   *
+   *   ```
+   *     FT_EXPORT( FT_Error )
+   *     FT_Init_FreeType( FT_Library*  alibrary );
+   *   ```
+   *
+   * - `FT_EXPORT_DEF( return_type )`
+   *
+   *   is used in a function definition, as in
+   *
+   *   ```
+   *     FT_EXPORT_DEF( FT_Error )
+   *     FT_Init_FreeType( FT_Library*  alibrary )
+   *     {
+   *       ... some code ...
+   *       return FT_Err_Ok;
+   *     }
+   *   ```
+   *
+   * You can provide your own implementation of `FT_EXPORT` and
+   * `FT_EXPORT_DEF` here if you want.
+   *
+   * To export a variable, use `FT_EXPORT_VAR`.
+   */
 
   /* See `freetype/config/compiler_macros.h` for the `FT_EXPORT` definition */
 #define FT_EXPORT_DEF( x )  FT_FUNCTION_DEFINITION( x )
 
-  /* The following macros are needed to compile the library with a   */
-  /* C++ compiler and with 16bit compilers.                          */
-  /*                                                                 */
+  /*
+   * The following macros are needed to compile the library with a
+   * C++ compiler and with 16bit compilers.
+   */
 
-  /* This is special.  Within C++, you must specify `extern "C"` for */
-  /* functions which are used via function pointers, and you also    */
-  /* must do that for structures which contain function pointers to  */
-  /* assure C linkage -- it's not possible to have (local) anonymous */
-  /* functions which are accessed by (global) function pointers.     */
-  /*                                                                 */
-  /*                                                                 */
-  /* FT_CALLBACK_DEF is used to _define_ a callback function,        */
-  /* located in the same source code file as the structure that uses */
-  /* it.                                                             */
-  /*                                                                 */
-  /* FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare   */
-  /* and define a callback function, respectively, in a similar way  */
-  /* as FT_BASE and FT_BASE_DEF work.                                */
-  /*                                                                 */
-  /* FT_CALLBACK_TABLE is used to _declare_ a constant variable that */
-  /* contains pointers to callback functions.                        */
-  /*                                                                 */
-  /* FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable   */
-  /* that contains pointers to callback functions.                   */
-  /*                                                                 */
-  /*                                                                 */
-  /* Some 16bit compilers have to redefine these macros to insert    */
-  /* the infamous `_cdecl` or `__fastcall` declarations.             */
-  /*                                                                 */
+  /*
+   * This is special.  Within C++, you must specify `extern "C"` for
+   * functions which are used via function pointers, and you also
+   * must do that for structures which contain function pointers to
+   * assure C linkage -- it's not possible to have (local) anonymous
+   * functions which are accessed by (global) function pointers.
+   *
+   *
+   * FT_CALLBACK_DEF is used to _define_ a callback function,
+   * located in the same source code file as the structure that uses
+   * it.  FT_COMPARE_DEF, in addition, ensures the `cdecl` calling
+   * convention on x86, required by the C library function `qsort`.
+   *
+   * FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare
+   * and define a callback function, respectively, in a similar way
+   * as FT_BASE and FT_BASE_DEF work.
+   *
+   * FT_CALLBACK_TABLE is used to _declare_ a constant variable that
+   * contains pointers to callback functions.
+   *
+   * FT_CALLBACK_TABLE_DEF is used to _define_ a constant variable
+   * that contains pointers to callback functions.
+   *
+   *
+   * Some 16bit compilers have to redefine these macros to insert
+   * the infamous `_cdecl` or `__fastcall` declarations.
+   */
 #ifdef __cplusplus
 #define FT_CALLBACK_DEF( x )  extern "C"  x
 #else
 #define FT_CALLBACK_DEF( x )  static  x
 #endif
 
+#if defined( __i386__ )
+#define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x ) __attribute__(( cdecl ))
+#elif defined( _M_IX86 )
+#define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x ) __cdecl
+#else
+#define FT_COMPARE_DEF( x )  FT_CALLBACK_DEF( x )
+#endif
+
 #define FT_BASE_CALLBACK( x )      FT_FUNCTION_DECLARATION( x )
 #define FT_BASE_CALLBACK_DEF( x )  FT_FUNCTION_DEFINITION( x )
 
diff --git a/include/freetype/internal/ftcalc.h b/include/freetype/internal/ftcalc.h
index c653074..f88e055 100644
--- a/include/freetype/internal/ftcalc.h
+++ b/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
  *
  *   Arithmetic computations (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -359,8 +359,8 @@
 
 #ifndef  FT_CONFIG_OPTION_NO_ASSEMBLER
 
-#if defined( __GNUC__ )                                          && \
-    ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) )
+#if defined( __clang__ ) || ( defined( __GNUC__ )                &&  \
+    ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) ) )
 
 #if FT_SIZEOF_INT == 4
 
@@ -370,12 +370,25 @@
 
 #define FT_MSB( x )  ( 31 - __builtin_clzl( x ) )
 
-#endif /* __GNUC__ */
+#endif
 
+#elif defined( _MSC_VER ) && _MSC_VER >= 1400
 
-#elif defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
+#if defined( _WIN32_WCE )
 
-#if FT_SIZEOF_INT == 4
+#include <cmnintrin.h>
+#pragma intrinsic( _CountLeadingZeros )
+
+#define FT_MSB( x )  ( 31 - _CountLeadingZeros( x ) )
+
+#elif defined( _M_ARM64 ) || defined( _M_ARM )
+
+#include <intrin.h>
+#pragma intrinsic( _CountLeadingZeros )
+
+#define FT_MSB( x )  ( 31 - _CountLeadingZeros( x ) )
+
+#elif defined( _M_IX86 ) || defined( _M_AMD64 ) || defined( _M_IA64 )
 
 #include <intrin.h>
 #pragma intrinsic( _BitScanReverse )
@@ -391,15 +404,27 @@
     return (FT_Int32)where;
   }
 
-#define FT_MSB( x )  ( FT_MSB_i386( x ) )
+#define FT_MSB( x )  FT_MSB_i386( x )
 
 #endif
 
-#endif /* _MSC_VER */
+#elif defined( __DECC ) || defined( __DECCXX )
 
+#include <builtins.h>
+
+#define FT_MSB( x )  (FT_Int)( 63 - _leadz( x ) )
+
+#elif defined( _CRAYC )
+
+#include <intrinsics.h>
+
+#define FT_MSB( x )  (FT_Int)( 31 - _leadz32( x ) )
+
+#endif /* FT_MSB macro definitions */
 
 #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */
 
+
 #ifndef FT_MSB
 
   FT_BASE( FT_Int )
@@ -487,7 +512,7 @@
 #define NEG_INT32( a )                                  \
           (FT_Int32)( (FT_UInt32)0 - (FT_UInt32)(a) )
 
-#ifdef FT_LONG64
+#ifdef FT_INT64
 
 #define ADD_INT64( a, b )                               \
           (FT_Int64)( (FT_UInt64)(a) + (FT_UInt64)(b) )
@@ -498,7 +523,7 @@
 #define NEG_INT64( a )                                  \
           (FT_Int64)( (FT_UInt64)0 - (FT_UInt64)(a) )
 
-#endif /* FT_LONG64 */
+#endif /* FT_INT64 */
 
 
 FT_END_HEADER
diff --git a/include/freetype/internal/ftdebug.h b/include/freetype/internal/ftdebug.h
index df5357a..5e8d929 100644
--- a/include/freetype/internal/ftdebug.h
+++ b/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -31,9 +31,24 @@
 
 #include "compiler-macros.h"
 
+#ifdef FT_DEBUG_LOGGING
+#define DLG_STATIC
+#include <dlg/output.h>
+#include <dlg/dlg.h>
+
+#include <freetype/ftlogging.h>
+#endif /* FT_DEBUG_LOGGING */
+
 
 FT_BEGIN_HEADER
 
+  /* force the definition of FT_DEBUG_LEVEL_TRACE if FT_DEBUG_LOGGING is */
+  /* already defined.                                                    */
+  /*                                                                     */
+#ifdef FT_DEBUG_LOGGING
+#undef  FT_DEBUG_LEVEL_TRACE
+#define FT_DEBUG_LEVEL_TRACE
+#endif
 
   /* force the definition of FT_DEBUG_LEVEL_ERROR if FT_DEBUG_LEVEL_TRACE */
   /* is already defined; this simplifies the following #ifdefs            */
@@ -82,20 +97,66 @@
    * Each component must define the macro FT_COMPONENT to a valid FT_Trace
    * value before using any TRACE macro.
    *
+   * To get consistent logging output, there should be no newline character
+   * (i.e., '\n') or a single trailing one in the message string of
+   * `FT_TRACEx` and `FT_ERROR`.
    */
 
+
+  /*************************************************************************
+   *
+   * If FT_DEBUG_LOGGING is enabled, tracing messages are sent to dlg's API.
+   * If FT_DEBUG_LOGGING is disabled, tracing messages are sent to
+   * `FT_Message` (defined in ftdebug.c).
+   */
+#ifdef FT_DEBUG_LOGGING
+
+  /* we need two macros to convert the names of `FT_COMPONENT` to a string */
+#define FT_LOGGING_TAG( x )   FT_LOGGING_TAG_( x )
+#define FT_LOGGING_TAG_( x )  #x
+
+  /* we need two macros to convert the component and the trace level */
+  /* to a string that combines them                                  */
+#define FT_LOGGING_TAGX( x, y )   FT_LOGGING_TAGX_( x, y )
+#define FT_LOGGING_TAGX_( x, y )  #x ":" #y
+
+
+#define FT_LOG( level, varformat )                                         \
+          do                                                               \
+          {                                                                \
+            const char*  dlg_tag = FT_LOGGING_TAGX( FT_COMPONENT, level ); \
+                                                                           \
+                                                                           \
+            ft_add_tag( dlg_tag );                                         \
+            if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \
+            {                                                              \
+              if ( custom_output_handler != NULL )                         \
+                FT_Logging_Callback varformat;                             \
+              else                                                         \
+                dlg_trace varformat;                                       \
+            }                                                              \
+            ft_remove_tag( dlg_tag );                                      \
+          } while( 0 )
+
+#else /* !FT_DEBUG_LOGGING */
+
+#define FT_LOG( level, varformat )                                         \
+          do                                                               \
+          {                                                                \
+            if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \
+              FT_Message varformat;                                        \
+          } while ( 0 )
+
+#endif /* !FT_DEBUG_LOGGING */
+
+
 #ifdef FT_DEBUG_LEVEL_TRACE
 
   /* we need two macros here to make cpp expand `FT_COMPONENT' */
 #define FT_TRACE_COMP( x )   FT_TRACE_COMP_( x )
 #define FT_TRACE_COMP_( x )  trace_ ## x
 
-#define FT_TRACE( level, varformat )                                       \
-          do                                                               \
-          {                                                                \
-            if ( ft_trace_levels[FT_TRACE_COMP( FT_COMPONENT )] >= level ) \
-              FT_Message varformat;                                        \
-          } while ( 0 )
+#define FT_TRACE( level, varformat )  FT_LOG( level, varformat )
 
 #else /* !FT_DEBUG_LEVEL_TRACE */
 
@@ -204,7 +265,32 @@
 
 #ifdef FT_DEBUG_LEVEL_ERROR
 
-#define FT_ERROR( varformat )  FT_Message  varformat
+  /**************************************************************************
+   *
+   * If FT_DEBUG_LOGGING is enabled, error messages are sent to dlg's API.
+   * If FT_DEBUG_LOGGING is disabled, error messages are sent to `FT_Message`
+   * (defined in ftdebug.c).
+   *
+   */
+#ifdef FT_DEBUG_LOGGING
+
+#define FT_ERROR( varformat )                                      \
+          do                                                       \
+          {                                                        \
+            const char*  dlg_tag = FT_LOGGING_TAG( FT_COMPONENT ); \
+                                                                   \
+                                                                   \
+            ft_add_tag( dlg_tag );                                 \
+            dlg_trace varformat;                                   \
+            ft_remove_tag( dlg_tag );                              \
+          } while ( 0 )
+
+#else /* !FT_DEBUG_LOGGING */
+
+#define FT_ERROR( varformat )  FT_Message varformat
+
+#endif /* !FT_DEBUG_LOGGING */
+
 
 #else  /* !FT_DEBUG_LEVEL_ERROR */
 
@@ -277,6 +363,77 @@
   FT_BASE( void )
   ft_debug_init( void );
 
+
+#ifdef FT_DEBUG_LOGGING
+
+  /**************************************************************************
+   *
+   * 'dlg' uses output handlers to control how and where log messages are
+   * printed.  Therefore we need to define a default output handler for
+   * FreeType.
+   */
+  FT_BASE( void )
+  ft_log_handler( const struct dlg_origin*  origin,
+                  const char*               string,
+                  void*                     data );
+
+
+  /**************************************************************************
+   *
+   * 1. `ft_default_log_handler` stores the function pointer that is used
+   *    internally by FreeType to print logs to a file.
+   *
+   * 2. `custom_output_handler` stores the function pointer to the callback
+   *    function provided by the user.
+   *
+   * It is defined in `ftdebug.c`.
+   */
+  extern dlg_handler            ft_default_log_handler;
+  extern FT_Custom_Log_Handler  custom_output_handler;
+
+
+  /**************************************************************************
+   *
+   * If FT_DEBUG_LOGGING macro is enabled, FreeType needs to initialize and
+   * un-initialize `FILE*`.
+   *
+   * These functions are defined in `ftdebug.c`.
+   */
+  FT_BASE( void )
+  ft_logging_init( void );
+
+  FT_BASE( void )
+  ft_logging_deinit( void );
+
+
+  /**************************************************************************
+   *
+   * For printing the name of `FT_COMPONENT` along with the actual log we
+   * need to add a tag with the name of `FT_COMPONENT`.
+   *
+   * These functions are defined in `ftdebug.c`.
+   */
+  FT_BASE( void )
+  ft_add_tag( const char*  tag );
+
+  FT_BASE( void )
+  ft_remove_tag( const char*  tag );
+
+
+  /**************************************************************************
+   *
+   * A function to print log data using a custom callback logging function
+   * (which is set using `FT_Set_Log_Handler`).
+   *
+   * This function is defined in `ftdebug.c`.
+   */
+  FT_BASE( void )
+  FT_Logging_Callback( const char*  fmt,
+                       ... );
+
+#endif /* FT_DEBUG_LOGGING */
+
+
 FT_END_HEADER
 
 #endif /* FTDEBUG_H_ */
diff --git a/include/freetype/internal/ftdrv.h b/include/freetype/internal/ftdrv.h
index 7f22710..0db323d 100644
--- a/include/freetype/internal/ftdrv.h
+++ b/include/freetype/internal/ftdrv.h
@@ -4,7 +4,7 @@
  *
  *   FreeType internal font driver interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/ftgloadr.h b/include/freetype/internal/ftgloadr.h
index 27b8659..fea931c 100644
--- a/include/freetype/internal/ftgloadr.h
+++ b/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph loader (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
@@ -22,6 +22,7 @@
 
 #include <freetype/freetype.h>
 
+#include "compiler-macros.h"
 
 FT_BEGIN_HEADER
 
diff --git a/include/freetype/internal/ftmemory.h b/include/freetype/internal/ftmemory.h
index ddb18b0..e20d949 100644
--- a/include/freetype/internal/ftmemory.h
+++ b/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType memory management macros (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
@@ -344,14 +344,13 @@
 #define FT_RENEW_ARRAY( ptr, curcnt, newcnt )                           \
           FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )
 
-#define FT_QNEW( ptr )                           \
-          FT_MEM_SET_ERROR( FT_MEM_QNEW( ptr ) )
+#define FT_QNEW( ptr )  FT_MEM_SET_ERROR( FT_MEM_QNEW( ptr ) )
 
-#define FT_QNEW_ARRAY( ptr, count )                          \
-          FT_MEM_SET_ERROR( FT_MEM_NEW_ARRAY( ptr, count ) )
+#define FT_QNEW_ARRAY( ptr, count )                           \
+          FT_MEM_SET_ERROR( FT_MEM_QNEW_ARRAY( ptr, count ) )
 
-#define FT_QRENEW_ARRAY( ptr, curcnt, newcnt )                          \
-          FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )
+#define FT_QRENEW_ARRAY( ptr, curcnt, newcnt )                           \
+          FT_MEM_SET_ERROR( FT_MEM_QRENEW_ARRAY( ptr, curcnt, newcnt ) )
 
 
   FT_BASE( FT_Pointer )
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 25db2c4..e52a26a 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType private base classes (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -673,7 +673,7 @@
 
 
   /* Set the metrics according to a size request. */
-  FT_BASE( void )
+  FT_BASE( FT_Error )
   FT_Request_Metrics( FT_Face          face,
                       FT_Size_Request  req );
 
diff --git a/include/freetype/internal/ftpsprop.h b/include/freetype/internal/ftpsprop.h
index 81ec291..d94d0d7 100644
--- a/include/freetype/internal/ftpsprop.h
+++ b/include/freetype/internal/ftpsprop.h
@@ -4,7 +4,7 @@
  *
  *   Get and set properties of PostScript drivers (specification).
  *
- * Copyright (C) 2017-2020 by
+ * Copyright (C) 2017-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/ftrfork.h b/include/freetype/internal/ftrfork.h
index 1b7b25a..1c56d6c 100644
--- a/include/freetype/internal/ftrfork.h
+++ b/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
  *
  *   Embedded resource forks accessor (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * Masatake YAMATO and Redhat K.K.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/ftserv.h b/include/freetype/internal/ftserv.h
index 6e1a947..fa82c31 100644
--- a/include/freetype/internal/ftserv.h
+++ b/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType services (specification only).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h
index e7d9222..7f3af12 100644
--- a/include/freetype/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
  *
  *   Stream handling (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -196,9 +196,9 @@
                                        FT_BYTE_U32( p, 2,  8 ) | \
                                        FT_BYTE_U32( p, 3,  0 ) )
 
-#define FT_PEEK_OFF3( p )  FT_INT32( FT_BYTE_U32( p, 0, 16 ) | \
-                                     FT_BYTE_U32( p, 1,  8 ) | \
-                                     FT_BYTE_U32( p, 2,  0 ) )
+#define FT_PEEK_OFF3( p )  ( FT_INT32( FT_BYTE_U32( p, 0, 24 ) | \
+                                       FT_BYTE_U32( p, 1, 16 ) | \
+                                       FT_BYTE_U32( p, 2,  8 ) ) >> 8 )
 
 #define FT_PEEK_UOFF3( p )  FT_UINT32( FT_BYTE_U32( p, 0, 16 ) | \
                                        FT_BYTE_U32( p, 1,  8 ) | \
@@ -220,9 +220,9 @@
                                           FT_BYTE_U32( p, 1,  8 ) | \
                                           FT_BYTE_U32( p, 0,  0 ) )
 
-#define FT_PEEK_OFF3_LE( p )  FT_INT32( FT_BYTE_U32( p, 2, 16 ) | \
-                                        FT_BYTE_U32( p, 1,  8 ) | \
-                                        FT_BYTE_U32( p, 0,  0 ) )
+#define FT_PEEK_OFF3_LE( p )  ( FT_INT32( FT_BYTE_U32( p, 2, 24 ) | \
+                                          FT_BYTE_U32( p, 1, 16 ) | \
+                                          FT_BYTE_U32( p, 0,  8 ) ) >> 8 )
 
 #define FT_PEEK_UOFF3_LE( p )  FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \
                                           FT_BYTE_U32( p, 1,  8 ) | \
@@ -305,11 +305,10 @@
 #else
 #define FT_GET_MACRO( func, type )        ( (type)func( stream ) )
 
-#define FT_GET_CHAR()       FT_GET_MACRO( FT_Stream_GetChar, FT_Char )
-#define FT_GET_BYTE()       FT_GET_MACRO( FT_Stream_GetChar, FT_Byte )
+#define FT_GET_CHAR()       FT_GET_MACRO( FT_Stream_GetByte, FT_Char )
+#define FT_GET_BYTE()       FT_GET_MACRO( FT_Stream_GetByte, FT_Byte )
 #define FT_GET_SHORT()      FT_GET_MACRO( FT_Stream_GetUShort, FT_Short )
 #define FT_GET_USHORT()     FT_GET_MACRO( FT_Stream_GetUShort, FT_UShort )
-#define FT_GET_OFF3()       FT_GET_MACRO( FT_Stream_GetUOffset, FT_Long )
 #define FT_GET_UOFF3()      FT_GET_MACRO( FT_Stream_GetUOffset, FT_ULong )
 #define FT_GET_LONG()       FT_GET_MACRO( FT_Stream_GetULong, FT_Long )
 #define FT_GET_ULONG()      FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
@@ -333,11 +332,10 @@
    * `FT_STREAM_POS'.  They use the full machinery to check whether a read is
    * valid.
    */
-#define FT_READ_BYTE( var )       FT_READ_MACRO( FT_Stream_ReadChar, FT_Byte, var )
-#define FT_READ_CHAR( var )       FT_READ_MACRO( FT_Stream_ReadChar, FT_Char, var )
+#define FT_READ_BYTE( var )       FT_READ_MACRO( FT_Stream_ReadByte, FT_Byte, var )
+#define FT_READ_CHAR( var )       FT_READ_MACRO( FT_Stream_ReadByte, FT_Char, var )
 #define FT_READ_SHORT( var )      FT_READ_MACRO( FT_Stream_ReadUShort, FT_Short, var )
 #define FT_READ_USHORT( var )     FT_READ_MACRO( FT_Stream_ReadUShort, FT_UShort, var )
-#define FT_READ_OFF3( var )       FT_READ_MACRO( FT_Stream_ReadUOffset, FT_Long, var )
 #define FT_READ_UOFF3( var )      FT_READ_MACRO( FT_Stream_ReadUOffset, FT_ULong, var )
 #define FT_READ_LONG( var )       FT_READ_MACRO( FT_Stream_ReadULong, FT_Long, var )
 #define FT_READ_ULONG( var )      FT_READ_MACRO( FT_Stream_ReadULong, FT_ULong, var )
@@ -457,8 +455,8 @@
 
 
   /* read a byte from an entered frame */
-  FT_BASE( FT_Char )
-  FT_Stream_GetChar( FT_Stream  stream );
+  FT_BASE( FT_Byte )
+  FT_Stream_GetByte( FT_Stream  stream );
 
   /* read a 16-bit big-endian unsigned integer from an entered frame */
   FT_BASE( FT_UShort )
@@ -482,8 +480,8 @@
 
 
   /* read a byte from a stream */
-  FT_BASE( FT_Char )
-  FT_Stream_ReadChar( FT_Stream  stream,
+  FT_BASE( FT_Byte )
+  FT_Stream_ReadByte( FT_Stream  stream,
                       FT_Error*  error );
 
   /* read a 16-bit big-endian unsigned integer from a stream */
diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h
index 58bd774..3307556 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
  *
  *   Tracing handling (specification only).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -18,6 +18,11 @@
 
   /* definitions of trace levels for FreeType 2 */
 
+  /* the maximum string length (if the argument to `FT_TRACE_DEF` */
+  /* gets used as a string) plus one charachter for ':' plus      */
+  /* another one for the trace level                              */
+#define FT_MAX_TRACE_LEVEL_LENGTH  (9 + 1 + 1)
+
   /* the first level must always be `trace_any' */
 FT_TRACE_DEF( any )
 
@@ -38,12 +43,14 @@
 FT_TRACE_DEF( mm )        /* MM interface            (ftmm.c)     */
 FT_TRACE_DEF( psprops )   /* PS driver properties    (ftpsprop.c) */
 FT_TRACE_DEF( raccess )   /* resource fork accessor  (ftrfork.c)  */
-FT_TRACE_DEF( raster )    /* monochrome rasterizer   (ftraster.c) */
-FT_TRACE_DEF( smooth )    /* anti-aliasing raster    (ftgrays.c)  */
 FT_TRACE_DEF( synth )     /* bold/slant synthesizer  (ftsynth.c)  */
 
-  /* Cache sub-system */
-FT_TRACE_DEF( cache )     /* cache sub-system        (ftcache.c, etc.) */
+  /* rasterizers */
+FT_TRACE_DEF( raster )    /* monochrome rasterizer   (ftraster.c) */
+FT_TRACE_DEF( smooth )    /* anti-aliasing raster    (ftgrays.c)  */
+
+  /* cache sub-system */
+FT_TRACE_DEF( cache )     /* cache sub-system   (ftcache.c, etc.) */
 
   /* SFNT driver components */
 FT_TRACE_DEF( sfdriver )  /* SFNT font driver        (sfdriver.c) */
@@ -77,6 +84,7 @@
 FT_TRACE_DEF( t1parse )
 
   /* PostScript helper module `psaux' */
+FT_TRACE_DEF( afmparse )
 FT_TRACE_DEF( cffdecode )
 FT_TRACE_DEF( psconv )
 FT_TRACE_DEF( psobjs )
@@ -151,8 +159,10 @@
 FT_TRACE_DEF( afhints )
 FT_TRACE_DEF( afmodule )
 FT_TRACE_DEF( aflatin )
-FT_TRACE_DEF( aflatin2 )
 FT_TRACE_DEF( afshaper )
-FT_TRACE_DEF( afwarp )
+
+  /* SDF components */
+FT_TRACE_DEF( sdf )       /* signed distance raster for outlines (ftsdf.c) */
+FT_TRACE_DEF( bsdf )      /* signed distance raster for bitmaps (ftbsdf.c) */
 
 /* END */
diff --git a/include/freetype/internal/ftvalid.h b/include/freetype/internal/ftvalid.h
index a5bc6c9..7bdfa62 100644
--- a/include/freetype/internal/ftvalid.h
+++ b/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
  *
  *   FreeType validation support (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h
index 8e0a262..6c6399a 100644
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
  *   Auxiliary functions and data structures related to PostScript fonts
  *   (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/pshints.h b/include/freetype/internal/pshints.h
index 663e9d3..9dbb077 100644
--- a/include/freetype/internal/pshints.h
+++ b/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
  *   recorders (specification only).  These are used to support native
  *   T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svbdf.h b/include/freetype/internal/services/svbdf.h
index 81f5a06..879aa61 100644
--- a/include/freetype/internal/services/svbdf.h
+++ b/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType BDF services (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svcfftl.h b/include/freetype/internal/services/svcfftl.h
index 1d2dbb6..f6424e4 100644
--- a/include/freetype/internal/services/svcfftl.h
+++ b/include/freetype/internal/services/svcfftl.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType CFF tables loader service (specification).
  *
- * Copyright (C) 2017-2020 by
+ * Copyright (C) 2017-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svcid.h b/include/freetype/internal/services/svcid.h
index bd49f32..7ef5afd 100644
--- a/include/freetype/internal/services/svcid.h
+++ b/include/freetype/internal/services/svcid.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType CID font services (specification).
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * Derek Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svfntfmt.h b/include/freetype/internal/services/svfntfmt.h
index 6114d63..cc87fc1 100644
--- a/include/freetype/internal/services/svfntfmt.h
+++ b/include/freetype/internal/services/svfntfmt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType font format service (specification only).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svgldict.h b/include/freetype/internal/services/svgldict.h
index f9443e4..4256f14 100644
--- a/include/freetype/internal/services/svgldict.h
+++ b/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph dictionary services (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svgxval.h b/include/freetype/internal/services/svgxval.h
index 83c2f26..f36d556 100644
--- a/include/freetype/internal/services/svgxval.h
+++ b/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating TrueTypeGX/AAT tables (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/include/freetype/internal/services/svkern.h b/include/freetype/internal/services/svkern.h
index 13cfb32..99dc2d9 100644
--- a/include/freetype/internal/services/svkern.h
+++ b/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Kerning service (specification).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svmetric.h b/include/freetype/internal/services/svmetric.h
index 2b30eda..b9c95a7 100644
--- a/include/freetype/internal/services/svmetric.h
+++ b/include/freetype/internal/services/svmetric.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType services for metrics variations (specification).
  *
- * Copyright (C) 2016-2020 by
+ * Copyright (C) 2016-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svmm.h b/include/freetype/internal/services/svmm.h
index 5a80763..8eac3a3 100644
--- a/include/freetype/internal/services/svmm.h
+++ b/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Multiple Masters and GX var services (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svotval.h b/include/freetype/internal/services/svotval.h
index 763fb2e..7afb49e 100644
--- a/include/freetype/internal/services/svotval.h
+++ b/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType OpenType validation service (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svpfr.h b/include/freetype/internal/services/svpfr.h
index bdeba07..98442bf 100644
--- a/include/freetype/internal/services/svpfr.h
+++ b/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
  *
  *   Internal PFR service functions (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svpostnm.h b/include/freetype/internal/services/svpostnm.h
index 8ef62c5..5a25c5a 100644
--- a/include/freetype/internal/services/svpostnm.h
+++ b/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript name services (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svprop.h b/include/freetype/internal/services/svprop.h
index 8f75543..9b71000 100644
--- a/include/freetype/internal/services/svprop.h
+++ b/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType property service (specification).
  *
- * Copyright (C) 2012-2020 by
+ * Copyright (C) 2012-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svpscmap.h b/include/freetype/internal/services/svpscmap.h
index b4dcd80..346f5e2 100644
--- a/include/freetype/internal/services/svpscmap.h
+++ b/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript charmap service (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svpsinfo.h b/include/freetype/internal/services/svpsinfo.h
index 1e7276f..49aa4d5 100644
--- a/include/freetype/internal/services/svpsinfo.h
+++ b/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript info service (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svsfnt.h b/include/freetype/internal/services/svsfnt.h
index 39c8b5e..4306cbc 100644
--- a/include/freetype/internal/services/svsfnt.h
+++ b/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType SFNT table loading service (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svttcmap.h b/include/freetype/internal/services/svttcmap.h
index c18bb23..775b6bc 100644
--- a/include/freetype/internal/services/svttcmap.h
+++ b/include/freetype/internal/services/svttcmap.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType/sfnt cmap extra information service.
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * Masatake YAMATO, Redhat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/include/freetype/internal/services/svtteng.h b/include/freetype/internal/services/svtteng.h
index 7a17e4a..9649342 100644
--- a/include/freetype/internal/services/svtteng.h
+++ b/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType engine query service (specification).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svttglyf.h b/include/freetype/internal/services/svttglyf.h
index 90a81dd..4268467 100644
--- a/include/freetype/internal/services/svttglyf.h
+++ b/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType glyph service.
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/services/svwinfnt.h b/include/freetype/internal/services/svwinfnt.h
index 8c915f5..aa70aa4 100644
--- a/include/freetype/internal/services/svwinfnt.h
+++ b/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Windows FNT/FONT service (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h
index b4c12db..bf4c7e0 100644
--- a/include/freetype/internal/sfnt.h
+++ b/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
  *
  *   High-level 'sfnt' driver interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -527,6 +527,170 @@
   /**************************************************************************
    *
    * @functype:
+   *   TT_Get_Color_Glyph_Paint_Func
+   *
+   * @description:
+   *   Find the root @FT_OpaquePaint object for a given glyph ID.
+   *
+   * @input:
+   *   face ::
+   *     The target face object.
+   *
+   *   base_glyph ::
+   *     The glyph index the colored glyph layers are associated with.
+   *
+   * @output:
+   *   paint ::
+   *     The root @FT_OpaquePaint object.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  If no color glyph is found, or the root
+   *   paint could not be retrieved, value~0 gets returned.  In case of an
+   *   error, value~0 is returned also.
+   */
+  typedef FT_Bool
+  ( *TT_Get_Color_Glyph_Paint_Func )( TT_Face                   face,
+                                      FT_UInt                   base_glyph,
+                                      FT_Color_Root_Transform   root_transform,
+                                      FT_OpaquePaint           *paint );
+
+
+  /**************************************************************************
+   *
+   * @functype:
+   *   TT_Get_Color_Glyph_ClipBox_Func
+   *
+   * @description:
+   *   Search for a 'COLR' v1 clip box for the specified `base_glyph` and
+   *   fill the `clip_box` parameter with the 'COLR' v1 'ClipBox' information
+   *   if one is found.
+   *
+   * @input:
+   *   face ::
+   *     A handle to the parent face object.
+   *
+   *   base_glyph ::
+   *     The glyph index for which to retrieve the clip box.
+   *
+   * @output:
+   *   clip_box ::
+   *     The clip box for the requested `base_glyph` if one is found.  The
+   *     clip box is computed taking scale and transformations configured on
+   *     the @FT_Face into account.  @FT_ClipBox contains @FT_Vector values
+   *     in 26.6 format.
+   *
+   * @note:
+   *     To retrieve the clip box in font units, reset scale to units-per-em
+   *     and remove transforms configured using @FT_Set_Transform.
+   *
+   * @return:
+   *   Value~1 if a ClipBox is found.  If no clip box is found or an
+   *   error occured, value~0 is returned.
+   */
+  typedef FT_Bool
+  ( *TT_Get_Color_Glyph_ClipBox_Func )( TT_Face      face,
+                                        FT_UInt      base_glyph,
+                                        FT_ClipBox*  clip_box );
+
+
+  /**************************************************************************
+   *
+   * @functype:
+   *   TT_Get_Paint_Layers_Func
+   *
+   * @description:
+   *   Access the layers of a `PaintColrLayers` table.
+   *
+   * @input:
+   *   face ::
+   *     The target face object.
+   *
+   * @inout:
+   *   iterator ::
+   *     The @FT_LayerIterator from an @FT_PaintColrLayers object, for which
+   *     the layers are to be retrieved.  The internal state of the iterator
+   *     is incremented after one call to this function for retrieving one
+   *     layer.
+   *
+   * @output:
+   *   paint ::
+   *     The root @FT_OpaquePaint object referencing the actual paint table.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  Value~0 gets returned when the paint
+   *   object can not be retrieved or any other error occurs.
+   */
+  typedef FT_Bool
+  ( *TT_Get_Paint_Layers_Func )( TT_Face            face,
+                                 FT_LayerIterator*  iterator,
+                                 FT_OpaquePaint    *paint );
+
+
+  /**************************************************************************
+   *
+   * @functype:
+   *   TT_Get_Colorline_Stops_Func
+   *
+   * @description:
+   *   Get the gradient and solid fill information for a given glyph.
+   *
+   * @input:
+   *   face ::
+   *     The target face object.
+   *
+   * @inout:
+   *   iterator ::
+   *     An @FT_ColorStopIterator object.  For the first call you should set
+   *     `iterator->p` to `NULL`.  For all following calls, simply use the
+   *     same object again.
+   *
+   * @output:
+   *   color_stop ::
+   *     Color index and alpha value for the retrieved color stop.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  If there are no more color stops,
+   *   value~0 gets returned.  In case of an error, value~0 is returned
+   *   also.
+   */
+  typedef FT_Bool
+  ( *TT_Get_Colorline_Stops_Func )( TT_Face                face,
+                                    FT_ColorStop          *color_stop,
+                                    FT_ColorStopIterator*  iterator );
+
+
+  /**************************************************************************
+   *
+   * @functype:
+   *   TT_Get_Paint_Func
+   *
+   * @description:
+   *   Get the paint details for a given @FT_OpaquePaint object.
+   *
+   * @input:
+   *   face ::
+   *     The target face object.
+   *
+   *   opaque_paint ::
+   *     The @FT_OpaquePaint object.
+   *
+   * @output:
+   *   paint ::
+   *     An @FT_COLR_Paint object holding the details on `opaque_paint`.
+   *
+   * @return:
+   *   Value~1 if everything is OK.  Value~0 if no details can be found for
+   *   this paint or any other error occured.
+   */
+  typedef FT_Bool
+  ( *TT_Get_Paint_Func )( TT_Face         face,
+                          FT_OpaquePaint  opaque_paint,
+                          FT_COLR_Paint  *paint );
+
+
+  /**************************************************************************
+   *
+   * @functype:
    *   TT_Blend_Colr_Func
    *
    * @description:
@@ -709,73 +873,78 @@
    */
   typedef struct  SFNT_Interface_
   {
-    TT_Loader_GotoTableFunc      goto_table;
+    TT_Loader_GotoTableFunc  goto_table;
 
-    TT_Init_Face_Func            init_face;
-    TT_Load_Face_Func            load_face;
-    TT_Done_Face_Func            done_face;
-    FT_Module_Requester          get_interface;
+    TT_Init_Face_Func    init_face;
+    TT_Load_Face_Func    load_face;
+    TT_Done_Face_Func    done_face;
+    FT_Module_Requester  get_interface;
 
-    TT_Load_Any_Func             load_any;
+    TT_Load_Any_Func  load_any;
 
     /* these functions are called by `load_face' but they can also  */
     /* be called from external modules, if there is a need to do so */
-    TT_Load_Table_Func           load_head;
-    TT_Load_Metrics_Func         load_hhea;
-    TT_Load_Table_Func           load_cmap;
-    TT_Load_Table_Func           load_maxp;
-    TT_Load_Table_Func           load_os2;
-    TT_Load_Table_Func           load_post;
+    TT_Load_Table_Func    load_head;
+    TT_Load_Metrics_Func  load_hhea;
+    TT_Load_Table_Func    load_cmap;
+    TT_Load_Table_Func    load_maxp;
+    TT_Load_Table_Func    load_os2;
+    TT_Load_Table_Func    load_post;
 
-    TT_Load_Table_Func           load_name;
-    TT_Free_Table_Func           free_name;
+    TT_Load_Table_Func  load_name;
+    TT_Free_Table_Func  free_name;
 
     /* this field was called `load_kerning' up to version 2.1.10 */
-    TT_Load_Table_Func           load_kern;
+    TT_Load_Table_Func  load_kern;
 
-    TT_Load_Table_Func           load_gasp;
-    TT_Load_Table_Func           load_pclt;
+    TT_Load_Table_Func  load_gasp;
+    TT_Load_Table_Func  load_pclt;
 
     /* see `ttload.h'; this field was called `load_bitmap_header' up to */
     /* version 2.1.10                                                   */
-    TT_Load_Table_Func           load_bhed;
+    TT_Load_Table_Func  load_bhed;
 
-    TT_Load_SBit_Image_Func      load_sbit_image;
+    TT_Load_SBit_Image_Func  load_sbit_image;
 
     /* see `ttpost.h' */
-    TT_Get_PS_Name_Func          get_psname;
-    TT_Free_Table_Func           free_psnames;
+    TT_Get_PS_Name_Func  get_psname;
+    TT_Free_Table_Func   free_psnames;
 
     /* starting here, the structure differs from version 2.1.7 */
 
     /* this field was introduced in version 2.1.8, named `get_psname' */
-    TT_Face_GetKerningFunc       get_kerning;
+    TT_Face_GetKerningFunc  get_kerning;
 
     /* new elements introduced after version 2.1.10 */
 
     /* load the font directory, i.e., the offset table and */
     /* the table directory                                 */
-    TT_Load_Table_Func           load_font_dir;
-    TT_Load_Metrics_Func         load_hmtx;
+    TT_Load_Table_Func    load_font_dir;
+    TT_Load_Metrics_Func  load_hmtx;
 
-    TT_Load_Table_Func           load_eblc;
-    TT_Free_Table_Func           free_eblc;
+    TT_Load_Table_Func  load_eblc;
+    TT_Free_Table_Func  free_eblc;
 
     TT_Set_SBit_Strike_Func      set_sbit_strike;
     TT_Load_Strike_Metrics_Func  load_strike_metrics;
 
-    TT_Load_Table_Func           load_cpal;
-    TT_Load_Table_Func           load_colr;
-    TT_Free_Table_Func           free_cpal;
-    TT_Free_Table_Func           free_colr;
-    TT_Set_Palette_Func          set_palette;
-    TT_Get_Colr_Layer_Func       get_colr_layer;
-    TT_Blend_Colr_Func           colr_blend;
+    TT_Load_Table_Func               load_cpal;
+    TT_Load_Table_Func               load_colr;
+    TT_Free_Table_Func               free_cpal;
+    TT_Free_Table_Func               free_colr;
+    TT_Set_Palette_Func              set_palette;
+    TT_Get_Colr_Layer_Func           get_colr_layer;
+    TT_Get_Color_Glyph_Paint_Func    get_colr_glyph_paint;
+    TT_Get_Color_Glyph_ClipBox_Func  get_color_glyph_clipbox;
+    TT_Get_Paint_Layers_Func         get_paint_layers;
+    TT_Get_Colorline_Stops_Func      get_colorline_stops;
+    TT_Get_Paint_Func                get_paint;
+    TT_Blend_Colr_Func               colr_blend;
 
-    TT_Get_Metrics_Func          get_metrics;
+    TT_Get_Metrics_Func  get_metrics;
 
-    TT_Get_Name_Func             get_name;
-    TT_Get_Name_ID_Func          get_name_id;
+    TT_Get_Name_Func     get_name;
+    TT_Get_Name_ID_Func  get_name_id;
 
   } SFNT_Interface;
 
@@ -820,6 +989,11 @@
           free_colr_,                    \
           set_palette_,                  \
           get_colr_layer_,               \
+          get_colr_glyph_paint_,         \
+          get_color_glyph_clipbox,       \
+          get_paint_layers_,             \
+          get_colorline_stops_,          \
+          get_paint_,                    \
           colr_blend_,                   \
           get_metrics_,                  \
           get_name_,                     \
@@ -860,6 +1034,11 @@
     free_colr_,                          \
     set_palette_,                        \
     get_colr_layer_,                     \
+    get_colr_glyph_paint_,               \
+    get_color_glyph_clipbox,             \
+    get_paint_layers_,                   \
+    get_colorline_stops_,                \
+    get_paint_,                          \
     colr_blend_,                         \
     get_metrics_,                        \
     get_name_,                           \
diff --git a/include/freetype/internal/t1types.h b/include/freetype/internal/t1types.h
index 6a0fe5e..023c5d0 100644
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
  *   Basic Type1/Type2 type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index c36342c..651131c 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
  *   Basic SFNT/TrueType type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1372,7 +1372,7 @@
    *
    *   num_locations ::
    *     The number of glyph locations in this TrueType file.  This should be
-   *     identical to the number of glyphs.  Ignored for Type 2 fonts.
+   *     one more than the number of glyphs.  Ignored for Type 2 fonts.
    *
    *   glyph_locations ::
    *     An array of longs.  These are offsets to glyph data within the
@@ -1598,7 +1598,7 @@
     FT_ULong              horz_metrics_size;
     FT_ULong              vert_metrics_size;
 
-    FT_ULong              num_locations; /* in broken TTF, gid > 0xFFFF */
+    FT_ULong              num_locations; /* up to 0xFFFF + 1 */
     FT_Byte*              glyph_locations;
 
     FT_Byte*              hdmx_table;
@@ -1734,7 +1734,7 @@
     FT_UInt          glyph_index;
 
     FT_Stream        stream;
-    FT_Int           byte_len;
+    FT_UInt          byte_len;
 
     FT_Short         n_contours;
     FT_BBox          bbox;
diff --git a/include/freetype/internal/wofftypes.h b/include/freetype/internal/wofftypes.h
index 1874a13..c460107 100644
--- a/include/freetype/internal/wofftypes.h
+++ b/include/freetype/internal/wofftypes.h
@@ -5,7 +5,7 @@
  *   Basic WOFF/WOFF2 type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -92,7 +92,7 @@
    */
   typedef struct  WOFF_TableRec_
   {
-    FT_ULong  Tag;           /* table ID                  */
+    FT_Tag    Tag;           /* table ID                  */
     FT_ULong  Offset;        /* table file offset         */
     FT_ULong  CompLength;    /* compressed table length   */
     FT_ULong  OrigLength;    /* uncompressed table length */
@@ -191,7 +191,7 @@
   typedef struct  WOFF2_TableRec_
   {
     FT_Byte   FlagByte;           /* table type and flags      */
-    FT_ULong  Tag;                /* table file offset         */
+    FT_Tag    Tag;                /* table file offset         */
     FT_ULong  dst_length;         /* uncompressed table length */
     FT_ULong  TransformLength;    /* transformed length        */
 
diff --git a/include/freetype/t1tables.h b/include/freetype/t1tables.h
index 426e140..a5f6ae7 100644
--- a/include/freetype/t1tables.h
+++ b/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
  *   Basic Type 1/Type 2 tables definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -360,7 +360,7 @@
 
     FT_UInt        num_subrs;
     FT_ULong       subrmap_offset;
-    FT_Int         sd_bytes;
+    FT_UInt        sd_bytes;
 
   } CID_FaceDictRec;
 
@@ -415,11 +415,11 @@
     FT_ULong        xuid[16];
 
     FT_ULong        cidmap_offset;
-    FT_Int          fd_bytes;
-    FT_Int          gd_bytes;
+    FT_UInt         fd_bytes;
+    FT_UInt         gd_bytes;
     FT_ULong        cid_count;
 
-    FT_Int          num_dicts;
+    FT_UInt         num_dicts;
     CID_FaceDict    font_dicts;
 
     FT_ULong        data_offset;
diff --git a/include/freetype/ttnameid.h b/include/freetype/ttnameid.h
index 2b2ed4c..a09950f 100644
--- a/include/freetype/ttnameid.h
+++ b/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
  *
  *   TrueType name ID definitions (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -591,7 +591,7 @@
 #define TT_MS_LANGID_MALAY_MALAYSIA                    0x043E
 #define TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM           0x083E
 #define TT_MS_LANGID_KAZAKH_KAZAKHSTAN                 0x043F
-#define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic*/   0x0440
+#define TT_MS_LANGID_KYRGYZ_KYRGYZSTAN /* Cyrillic */  0x0440
 #define TT_MS_LANGID_KISWAHILI_KENYA                   0x0441
 #define TT_MS_LANGID_TURKMEN_TURKMENISTAN              0x0442
 #define TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN            0x0443
diff --git a/include/freetype/tttables.h b/include/freetype/tttables.h
index c8fa35e..c33d990 100644
--- a/include/freetype/tttables.h
+++ b/include/freetype/tttables.h
@@ -5,7 +5,7 @@
  *   Basic SFNT/TrueType tables definitions and interface
  *   (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/freetype/tttags.h b/include/freetype/tttags.h
index 3c9fbd5..47ccc6d 100644
--- a/include/freetype/tttags.h
+++ b/include/freetype/tttags.h
@@ -4,7 +4,7 @@
  *
  *   Tags for TrueType and OpenType tables (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/include/ft2build.h b/include/ft2build.h
index b4fd1f8..62686b1 100644
--- a/include/ft2build.h
+++ b/include/ft2build.h
@@ -4,7 +4,7 @@
  *
  *   FreeType 2 build and setup macros.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/meson.build b/meson.build
index ea30495..9998848 100644
--- a/meson.build
+++ b/meson.build
@@ -2,7 +2,7 @@
 # Meson project file for FreeType 2
 #
 
-# Copyright (C) 2020 by
+# Copyright (C) 2020-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -11,34 +11,45 @@
 # indicate that you have read the license and understand and accept it
 # fully.
 
+#
+# Say
+#
+#   meson configure
+#
+# to see all configuration options and their default values.  For example,
+# to build only a shared version of FreeType, override the default value
+# with
+#
+#   meson setup -Ddefault_library=shared
+#
 
 project('freetype2', 'c',
   meson_version: '>= 0.55.0',
   default_options: ['default_library=both'],
+  version: run_command('builds/meson/extract_freetype_version.py',
+                       'include/freetype/freetype.h').stdout().strip(),
 )
 
-#
-# Rules to compile the FreeType 2 library itself
-#
 
-
-# Apparently meson doesn't provide a read_file() function, so instead
-# running an external command is required.
+# Only meson >= 0.57 can read a file and assign its contents to a
+# variable; we thus use an external command to have this functionality
+# with older versions, too.
 
 python = import('python')
 python_exe = python.find_installation(required: true)
 
-ft2_version = run_command(python_exe,
-  files('builds/meson/extract_freetype_version.py'),
-  files('include/freetype/freetype.h')).stdout().strip()
-
-ft2_libtool_version = run_command(python_exe,
+ft2_so_version = run_command(python_exe,
   files('builds/meson/extract_libtool_version.py'),
   '--soversion',
   files('builds/unix/configure.raw')).stdout().strip()
 
+ft2_pkgconfig_version = run_command(python_exe,
+  files('builds/meson/extract_libtool_version.py'),
+  files('builds/unix/configure.raw')).stdout().strip()
+
 ft2_includes = include_directories('include')
 
+freetype_includedir = join_paths(get_option('includedir'), 'freetype2')
 
 # Generate a custom `ftmodule.h` version based on the content of
 # `modules.cfg`.
@@ -49,7 +60,7 @@
   command: [python_exe, files('builds/meson/parse_modules_cfg.py'),
             '--format=ftmodule.h', '@INPUT@', '--output', '@OUTPUT@'],
   install: true,
-  install_dir: 'include/freetype2/freetype/config',
+  install_dir: join_paths(freetype_includedir, 'freetype/config'),
 )
 ft2_sources = [ftmodule_h]
 
@@ -76,7 +87,7 @@
   ft2_sources += 'src/@0@/@1@.c'.format(mod, source)
 endforeach
 
-# NOTE: The `gzip` and `bzip2` aux modules are handled through options.
+# NOTE: The `bzip2` aux module is handled through options.
 ft_aux_modules = run_command(python_exe,
   files('builds/meson/parse_modules_cfg.py'),
   '--format=aux-modules',
@@ -90,7 +101,9 @@
     source = 'ftcache'
   elif auxmod == 'lzw'
     source = 'ftlzw'
-  elif auxmod == 'gzip' or auxmod == 'bzip2'
+  elif auxmod == 'gzip'
+    source = 'ftgzip'
+  elif auxmod == 'bzip2'
     # Handled through options instead, see below.
     continue
   endif
@@ -99,7 +112,7 @@
 
 
 # FreeType 2 base extensions.
-# Normally configured through `modules.cfg`.
+# To be configured in `modules.cfg`.
 
 base_extensions = run_command(python_exe,
   files('builds/meson/parse_modules_cfg.py'),
@@ -122,6 +135,7 @@
   'include/freetype/ftbzip2.h',
   'include/freetype/ftcache.h',
   'include/freetype/ftchapters.h',
+  'include/freetype/ftcid.h',
   'include/freetype/ftcolor.h',
   'include/freetype/ftdriver.h',
   'include/freetype/fterrdef.h',
@@ -168,7 +182,7 @@
   'include/freetype/config/public-macros.h',
 ])
 
-ft2_defines = []
+ft2_defines = ['-DFT2_BUILD_LIBRARY=1']
 
 
 # System support file.
@@ -180,24 +194,24 @@
 has_fcntl_h = cc.has_header('fcntl.h')
 has_sys_mman_h = cc.has_header('sys/mman.h')
 
-if has_unistd_h
-  ft2_defines += ['-DHAVE_UNISTD_H=1']
-endif
-if has_fcntl_h
-  ft2_defines += ['-DHAVE_FCNTL_H']
-endif
-
 mmap_option = get_option('mmap')
-if mmap_option.auto()
-  use_mmap = has_unistd_h and has_fcntl_h and has_sys_mman_h
-else
-  use_mmap = mmap_option.enabled()
-endif
-if use_mmap
-  # This version of ftsystem.c uses mmap() to read input font files.
-  ft2_sources += files(['builds/unix/ftsystem.c',])
-else
+
+use_unix_ftsystem_c = false
+if mmap_option.disabled()
   ft2_sources += files(['src/base/ftsystem.c',])
+elif host_machine.system() == 'windows'
+  ft2_sources += files(['builds/windows/ftsystem.c',])
+else
+  if has_unistd_h and has_fcntl_h and has_sys_mman_h
+    # This version of `ftsystem.c` uses `mmap` to read input font files.
+    ft2_sources += files(['builds/unix/ftsystem.c',])
+    use_unix_ftsystem_c = true
+  elif mmap_option.enabled()
+    error('mmap was enabled via options but is not available,'
+          + ' required headers were not found!')
+  else
+    ft2_sources += files(['src/base/ftsystem.c',])
+  endif
 endif
 
 
@@ -205,53 +219,64 @@
 #
 # NOTE: Some specialized versions exist for other platforms not supported by
 # Meson.  Most implementation differences are extremely minor, i.e., in the
-# implementation of FT_Message() and FT_Panic(), and getting the `FT2_DEBUG`
+# implementation of `FT_Message` and `FT_Panic`, and getting the `FT2_DEBUG`
 # value from the environment, when this is supported.  A smaller refactor
 # might make these platform-specific files much smaller, and could be moved
 # into `ftsystem.c` as well.
 #
 if host_machine.system() == 'windows'
-  ft2_debug_src = 'builds/windows/ftdebug.c'
+  winmod = import('windows')
+  ft2_sources += [
+    'builds/windows/ftdebug.c',
+    winmod.compile_resources('src/base/ftver.rc'),
+  ]
 else
-  ft2_debug_src = 'src/base/ftdebug.c'
+  ft2_sources += 'src/base/ftdebug.c'
 endif
-ft2_sources += files([ft2_debug_src])
+
 
 ft2_deps = []
+common_ldflags = []
+
+
+# Correct compatibility version for OS x.
+#
+# OSX sets the compatibility_version (aka libtools version) differently from
+# the library name.
+#
+if host_machine.system() == 'darwin'
+  # maintain compatibility with autotools on macOS
+  common_ldflags = [
+    '-compatibility_version', ft2_pkgconfig_version.split('.')[0],
+    '-current_version', ft2_pkgconfig_version
+  ]
+endif
 
 
 # Generate `ftoption.h` based on available dependencies.
 
-ftoption_command = [python_exe,
+process_header_command = [python_exe,
   files('builds/meson/process_ftoption_h.py'),
   '@INPUT@', '--output=@OUTPUT@']
+ftoption_command = process_header_command
 
-# GZip support
-zlib_option = get_option('zlib')
-if zlib_option == 'disabled'
-  ftoption_command += ['--disable=FT_CONFIG_OPTION_USE_ZLIB']
+
+# external GZip support
+zlib_dep = dependency('zlib',
+  required: get_option('zlib'),
+  fallback: 'zlib')
+
+if zlib_dep.found()
+  ftoption_command += ['--enable=FT_CONFIG_OPTION_SYSTEM_ZLIB']
+  ft2_deps += [zlib_dep]
 else
-  ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_ZLIB']
-  if zlib_option == 'builtin'
-    ftoption_command += ['--disable=FT_CONFIG_OPTION_SYSTEM_ZLIB']
-  else
-    # Probe for the system version.
-    zlib_system = dependency('zlib', required: zlib_option == 'system')
-    ft2_deps += [zlib_system]
-    ftoption_command += ['--enable=FT_CONFIG_OPTION_SYSTEM_ZLIB']
-  endif
-  ft2_sources += files(['src/gzip/ftgzip.c',])
+  ftoption_command += ['--disable=FT_CONFIG_OPTION_SYSTEM_ZLIB']
 endif
 
 # BZip2 support
-#
-# IMPORTANT NOTE: Without `static: false` here, Meson will find both the
-# static library version and the shared library version when they are
-# installed on the system, and will try to link them *both* to the final
-# library!
-bzip2_dep = meson.get_compiler('c').find_library('bz2',
-              static: false,
-              required: get_option('bzip2'))
+bzip2_dep = cc.find_library('bz2',
+  required: get_option('bzip2'))
+
 if bzip2_dep.found()
   ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BZIP2']
   ft2_sources += files(['src/bzip2/ftbzip2.c',])
@@ -259,21 +284,33 @@
 endif
 
 # PNG support
-libpng_dep = dependency('libpng', required: get_option('png'))
-ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_PNG']
-ft2_deps += [libpng_dep]
+libpng_dep = dependency('libpng',
+  required: get_option('png'),
+  fallback: 'libpng')
+
+if libpng_dep.found()
+  ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_PNG']
+  ft2_deps += [libpng_dep]
+endif
 
 # Harfbuzz support
 harfbuzz_dep = dependency('harfbuzz',
-                 version: '>= 1.8.0',
-                 required: get_option('harfbuzz'))
-ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_HARFBUZZ']
-ft2_deps += [harfbuzz_dep]
+  version: '>= 2.0.0',
+  required: get_option('harfbuzz'))
+
+if harfbuzz_dep.found()
+  ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_HARFBUZZ']
+  ft2_deps += [harfbuzz_dep]
+endif
 
 # Brotli decompression support
-brotli_dep = dependency('libbrotlidec', required: get_option('brotli'))
-ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BROTLI']
-ft2_deps += [brotli_dep]
+brotli_dep = dependency('libbrotlidec',
+  required: get_option('brotli'))
+
+if brotli_dep.found()
+  ftoption_command += ['--enable=FT_CONFIG_OPTION_USE_BROTLI']
+  ft2_deps += [brotli_dep]
+endif
 
 # We can now generate `ftoption.h`.
 ftoption_h = custom_target('ftoption.h',
@@ -281,75 +318,86 @@
   output: 'ftoption.h',
   command: ftoption_command,
   install: true,
-  install_dir: 'include/freetype2/freetype/config',
+  install_dir: join_paths(freetype_includedir, 'freetype/config'),
 )
 ft2_sources += ftoption_h
-
-
-# QUESTION: What if the compiler doesn't support `-D` but uses `/D` instead
-# as on Windows?
-#
-# Other build systems have something like c_defines to list defines in a
-# more portable way.  For now assume the compiler supports `-D` (hint: Visual
-# Studio does).
-ft2_defines += ['-DFT2_BUILD_LIBRARY=1']
-
-
-# Ensure that the `ftoption.h` file generated above will be used to build
-# FreeType.  Unfortunately, and very surprisingly, configure_file() does not
-# support putting the output file in a sub-directory, so we have to override
-# the default which is `<freetype/config/ftoption.h>`.
-#
-# It would be cleaner to generate the file directly into
-# `${MESON_BUILD_DIR}/freetype/config/ftoption.h`.  See
-# 'https://github.com/mesonbuild/meson/issues/2320' for details.
 ft2_defines += ['-DFT_CONFIG_OPTIONS_H=<ftoption.h>']
 
-ft2_c_args = ft2_defines
-if cc.has_function_attribute('visibility:hidden')
-  ft2_c_args += ['-fvisibility=hidden']
+if host_machine.system() == 'windows'
+  ft2_defines += ['-DDLL_EXPORT=1']
 endif
 
+
+# Generate `ftconfig.h`.
+
+ftconfig_command = process_header_command
+if has_unistd_h
+  ftconfig_command += '--enable=HAVE_UNISTD_H'
+endif
+if has_fcntl_h
+  ftconfig_command += '--enable=HAVE_FCNTL_H'
+endif
+
+if use_unix_ftsystem_c
+  ftconfig_h_in = files('builds/unix/ftconfig.h.in')
+  ftconfig_h = custom_target('ftconfig.h',
+    input: ftconfig_h_in,
+    output: 'ftconfig.h',
+    command: ftconfig_command,
+    install: true,
+    install_dir: join_paths(freetype_includedir, 'freetype/config'),
+  )
+  ft2_sources += ftconfig_h
+  ft2_defines += ['-DFT_CONFIG_CONFIG_H=<ftconfig.h>']
+endif
+
+
 ft2_lib = library('freetype',
   sources: ft2_sources + [ftmodule_h],
-  c_args: ft2_c_args,
+  c_args: ft2_defines,
+  gnu_symbol_visibility: 'hidden',
   include_directories: ft2_includes,
   dependencies: ft2_deps,
   install: true,
-  version: ft2_libtool_version,
+  version: ft2_so_version,
+  link_args: common_ldflags,
 )
 
 
-# To be used by other projects including this one through subproject().
-freetype2_dep = declare_dependency(
+# To be used by other projects including this one through `subproject`.
+freetype_dep = declare_dependency(
   include_directories: ft2_includes,
   link_with: ft2_lib,
-  version: ft2_libtool_version)
+  version: ft2_pkgconfig_version)
+
+meson.override_dependency('freetype2', freetype_dep)
 
 
 # NOTE: Using both `install_dir` and `subdir` doesn't seem to work below,
 # i.e., the subdir value seems to be ignored, contrary to examples in the
 # Meson documentation.
 install_headers('include/ft2build.h',
-   install_dir: 'include/freetype2')
+  install_dir: freetype_includedir)
 install_headers(ft2_public_headers,
-  install_dir: 'include/freetype2/freetype')
+  install_dir: join_paths(freetype_includedir, 'freetype'))
 install_headers(ft2_config_headers,
-  install_dir: 'include/freetype2/freetype/config')
+  install_dir: join_paths(freetype_includedir, 'freetype/config'))
 
 
-# TODO(david): Declare_dependency() for using this in a Meson subproject
-#
 pkgconfig = import('pkgconfig')
+
 pkgconfig.generate(ft2_lib,
   filebase: 'freetype2',
   name: 'FreeType 2',
   description: 'A free, high-quality, and portable font engine.',
   url: 'https://freetype.org',
   subdirs: 'freetype2',
-  version: ft2_libtool_version,
+  version: ft2_pkgconfig_version,
 )
 
+if get_option('tests').enabled()
+  subdir('tests')
+endif
 
 # NOTE: Unlike the old `make refdoc` command, this generates the
 # documentation under `$BUILD/docs/` since Meson doesn't support modifying
@@ -359,10 +407,21 @@
   input: ft2_public_headers + ft2_config_headers,
   command: [python_exe,
     files('builds/meson/generate_reference_docs.py'),
-    '--version=' + ft2_version,
-    '--input-dir=' + meson.source_root(),
+    '--version=' + meson.project_version(),
+    '--input-dir=' + meson.current_source_dir(),
     '--output-dir=@OUTPUT@'
   ],
 )
 
+
+summary({'OS': host_machine.system(),
+        }, section: 'Operating System')
+
+summary({'Zlib': zlib_dep.found() ? 'external' : 'internal',
+         'Bzip2': bzip2_dep.found() ? 'yes' : 'no',
+         'Png': libpng_dep.found() ? 'yes' : 'no',
+         'Harfbuzz': harfbuzz_dep.found() ? 'yes' : 'no',
+         'Brotli': brotli_dep.found() ? 'yes' : 'no',
+        }, section: 'Used Libraries')
+
 # EOF
diff --git a/meson_options.txt b/meson_options.txt
index 74ed16b..375eb71 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -2,7 +2,7 @@
 # meson_options.txt
 #
 
-# Copyright (C) 2020 by
+# Copyright (C) 2020-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -12,36 +12,42 @@
 # fully.
 
 
-option('zlib',
-  type: 'combo',
-  choices: ['disabled', 'auto', 'builtin', 'system'],
+option('brotli',
+  type: 'feature',
   value: 'auto',
-  description: 'Support reading gzip-compressed font files.')
+  description: 'Use Brotli library to support decompressing WOFF2 fonts')
 
 option('bzip2',
   type: 'feature',
   value: 'auto',
-  description: 'Support reading bzip2-compressed font files.')
-
-option('png',
-  type: 'feature',
-  value: 'auto',
-  description: 'Support color bitmap glyph formats in the PNG format.'
-               + 'Requires libpng.')
+  description: 'Support reading bzip2-compressed font files')
 
 option('harfbuzz',
   type: 'feature',
   value: 'auto',
-  description: 'Use Harfbuzz library to improve auto-hinting.'
-               + ' If available, many glyphs not directly addressable'
-               + ' by a font\'s character map will be hinted also.')
-
-option('brotli',
-  type: 'feature',
-  value: 'auto',
-  description: 'Use Brotli library to support decompressing WOFF2 fonts.')
+  description: 'Use Harfbuzz library to improve auto-hinting;'
+               + ' if available, many glyphs not directly addressable'
+               + ' by a font\'s character map will be hinted also')
 
 option('mmap',
   type: 'feature',
   value: 'auto',
-  description: 'Use mmap() to open font files for faster parsing.')
+  description: 'Use mmap() to open font files for faster parsing')
+
+option('png',
+  type: 'feature',
+  value: 'auto',
+  description: 'Support color bitmap glyph formats in the PNG format;'
+               + ' requires libpng')
+
+option('tests',
+  type: 'feature',
+  value: 'disabled',
+  description: 'Enable FreeType unit and regression tests')
+
+option('zlib',
+  type: 'feature',
+  value: 'auto',
+  description: 'Support reading gzip-compressed font files')
+
+# EOF
diff --git a/modules.cfg b/modules.cfg
index d6cdbe5..30f7fac 100644
--- a/modules.cfg
+++ b/modules.cfg
@@ -1,6 +1,6 @@
 # modules.cfg
 #
-# Copyright (C) 2005-2020 by
+# Copyright (C) 2005-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -93,11 +93,14 @@
 #### raster modules -- at least one is required for vector font formats
 ####
 
+# Anti-aliasing rasterizer.
+RASTER_MODULES += smooth
+
 # Monochrome rasterizer.
 RASTER_MODULES += raster
 
-# Anti-aliasing rasterizer.
-RASTER_MODULES += smooth
+# Signed distance field rasterizer.
+RASTER_MODULES += sdf
 
 
 ####
diff --git a/src/autofit/afangles.c b/src/autofit/afangles.c
deleted file mode 100644
index a2d45eb..0000000
--- a/src/autofit/afangles.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/****************************************************************************
- *
- * afangles.c
- *
- *   Routines used to compute vector angles with limited accuracy
- *   and very high speed.  It also contains sorting routines (body).
- *
- * Copyright (C) 2003-2020 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used,
- * modified, and distributed under the terms of the FreeType project
- * license, LICENSE.TXT.  By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- */
-
-
-#include "aftypes.h"
-
-
-  /*
-   * We are not using `af_angle_atan' anymore, but we keep the source
-   * code below just in case...
-   */
-
-
-#if 0
-
-
-  /*
-   * The trick here is to realize that we don't need a very accurate angle
-   * approximation.  We are going to use the result of `af_angle_atan' to
-   * only compare the sign of angle differences, or check whether its
-   * magnitude is very small.
-   *
-   * The approximation
-   *
-   *   dy * PI / (|dx|+|dy|)
-   *
-   * should be enough, and much faster to compute.
-   */
-  FT_LOCAL_DEF( AF_Angle )
-  af_angle_atan( FT_Fixed  dx,
-                 FT_Fixed  dy )
-  {
-    AF_Angle  angle;
-    FT_Fixed  ax = dx;
-    FT_Fixed  ay = dy;
-
-
-    if ( ax < 0 )
-      ax = -ax;
-    if ( ay < 0 )
-      ay = -ay;
-
-    ax += ay;
-
-    if ( ax == 0 )
-      angle = 0;
-    else
-    {
-      angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );
-      if ( dx < 0 )
-      {
-        if ( angle >= 0 )
-          angle = AF_ANGLE_PI - angle;
-        else
-          angle = -AF_ANGLE_PI - angle;
-      }
-    }
-
-    return angle;
-  }
-
-
-#elif 0
-
-
-  /* the following table has been automatically generated with */
-  /* the `mather.py' Python script                             */
-
-#define AF_ATAN_BITS  8
-
-  static const FT_Byte  af_arctan[1L << AF_ATAN_BITS] =
-  {
-     0,  0,  1,  1,  1,  2,  2,  2,
-     3,  3,  3,  3,  4,  4,  4,  5,
-     5,  5,  6,  6,  6,  7,  7,  7,
-     8,  8,  8,  9,  9,  9, 10, 10,
-    10, 10, 11, 11, 11, 12, 12, 12,
-    13, 13, 13, 14, 14, 14, 14, 15,
-    15, 15, 16, 16, 16, 17, 17, 17,
-    18, 18, 18, 18, 19, 19, 19, 20,
-    20, 20, 21, 21, 21, 21, 22, 22,
-    22, 23, 23, 23, 24, 24, 24, 24,
-    25, 25, 25, 26, 26, 26, 26, 27,
-    27, 27, 28, 28, 28, 28, 29, 29,
-    29, 30, 30, 30, 30, 31, 31, 31,
-    31, 32, 32, 32, 33, 33, 33, 33,
-    34, 34, 34, 34, 35, 35, 35, 35,
-    36, 36, 36, 36, 37, 37, 37, 38,
-    38, 38, 38, 39, 39, 39, 39, 40,
-    40, 40, 40, 41, 41, 41, 41, 42,
-    42, 42, 42, 42, 43, 43, 43, 43,
-    44, 44, 44, 44, 45, 45, 45, 45,
-    46, 46, 46, 46, 46, 47, 47, 47,
-    47, 48, 48, 48, 48, 48, 49, 49,
-    49, 49, 50, 50, 50, 50, 50, 51,
-    51, 51, 51, 51, 52, 52, 52, 52,
-    52, 53, 53, 53, 53, 53, 54, 54,
-    54, 54, 54, 55, 55, 55, 55, 55,
-    56, 56, 56, 56, 56, 57, 57, 57,
-    57, 57, 57, 58, 58, 58, 58, 58,
-    59, 59, 59, 59, 59, 59, 60, 60,
-    60, 60, 60, 61, 61, 61, 61, 61,
-    61, 62, 62, 62, 62, 62, 62, 63,
-    63, 63, 63, 63, 63, 64, 64, 64
-  };
-
-
-  FT_LOCAL_DEF( AF_Angle )
-  af_angle_atan( FT_Fixed  dx,
-                 FT_Fixed  dy )
-  {
-    AF_Angle  angle;
-
-
-    /* check trivial cases */
-    if ( dy == 0 )
-    {
-      angle = 0;
-      if ( dx < 0 )
-        angle = AF_ANGLE_PI;
-      return angle;
-    }
-    else if ( dx == 0 )
-    {
-      angle = AF_ANGLE_PI2;
-      if ( dy < 0 )
-        angle = -AF_ANGLE_PI2;
-      return angle;
-    }
-
-    angle = 0;
-    if ( dx < 0 )
-    {
-      dx = -dx;
-      dy = -dy;
-      angle = AF_ANGLE_PI;
-    }
-
-    if ( dy < 0 )
-    {
-      FT_Pos  tmp;
-
-
-      tmp = dx;
-      dx  = -dy;
-      dy  = tmp;
-      angle -= AF_ANGLE_PI2;
-    }
-
-    if ( dx == 0 && dy == 0 )
-      return 0;
-
-    if ( dx == dy )
-      angle += AF_ANGLE_PI4;
-    else if ( dx > dy )
-      angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
-    else
-      angle += AF_ANGLE_PI2 -
-               af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];
-
-    if ( angle > AF_ANGLE_PI )
-      angle -= AF_ANGLE_2PI;
-
-    return angle;
-  }
-
-
-#endif /* 0 */
-
-
-  FT_LOCAL_DEF( void )
-  af_sort_pos( FT_UInt  count,
-               FT_Pos*  table )
-  {
-    FT_UInt  i, j;
-    FT_Pos   swap;
-
-
-    for ( i = 1; i < count; i++ )
-    {
-      for ( j = i; j > 0; j-- )
-      {
-        if ( table[j] >= table[j - 1] )
-          break;
-
-        swap         = table[j];
-        table[j]     = table[j - 1];
-        table[j - 1] = swap;
-      }
-    }
-  }
-
-
-  FT_LOCAL_DEF( void )
-  af_sort_and_quantize_widths( FT_UInt*  count,
-                               AF_Width  table,
-                               FT_Pos    threshold )
-  {
-    FT_UInt      i, j;
-    FT_UInt      cur_idx;
-    FT_Pos       cur_val;
-    FT_Pos       sum;
-    AF_WidthRec  swap;
-
-
-    if ( *count == 1 )
-      return;
-
-    /* sort */
-    for ( i = 1; i < *count; i++ )
-    {
-      for ( j = i; j > 0; j-- )
-      {
-        if ( table[j].org >= table[j - 1].org )
-          break;
-
-        swap         = table[j];
-        table[j]     = table[j - 1];
-        table[j - 1] = swap;
-      }
-    }
-
-    cur_idx = 0;
-    cur_val = table[cur_idx].org;
-
-    /* compute and use mean values for clusters not larger than  */
-    /* `threshold'; this is very primitive and might not yield   */
-    /* the best result, but normally, using reference character  */
-    /* `o', `*count' is 2, so the code below is fully sufficient */
-    for ( i = 1; i < *count; i++ )
-    {
-      if ( table[i].org - cur_val > threshold ||
-           i == *count - 1                    )
-      {
-        sum = 0;
-
-        /* fix loop for end of array */
-        if ( table[i].org - cur_val <= threshold &&
-             i == *count - 1                     )
-          i++;
-
-        for ( j = cur_idx; j < i; j++ )
-        {
-          sum         += table[j].org;
-          table[j].org = 0;
-        }
-        table[cur_idx].org = sum / (FT_Pos)j;
-
-        if ( i < *count - 1 )
-        {
-          cur_idx = i + 1;
-          cur_val = table[cur_idx].org;
-        }
-      }
-    }
-
-    cur_idx = 1;
-
-    /* compress array to remove zero values */
-    for ( i = 1; i < *count; i++ )
-    {
-      if ( table[i].org )
-        table[cur_idx++] = table[i];
-    }
-
-    *count = cur_idx;
-  }
-
-
-/* END */
diff --git a/src/autofit/afangles.h b/src/autofit/afangles.h
deleted file mode 100644
index 18d7dae..0000000
--- a/src/autofit/afangles.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * afangles.h
- *
- * This is a dummy file, used to please the build system.  It is never
- * included by the auto-fitter sources.
- *
- */
diff --git a/src/autofit/afblue.c b/src/autofit/afblue.c
index 9ebffdd..c9e8045 100644
--- a/src/autofit/afblue.c
+++ b/src/autofit/afblue.c
@@ -7,7 +7,7 @@
  *
  *   Auto-fitter data for blue strings (body).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afblue.cin b/src/autofit/afblue.cin
index c6a697f..071e80b 100644
--- a/src/autofit/afblue.cin
+++ b/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter data for blue strings (body).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afblue.dat b/src/autofit/afblue.dat
index b19b8df..1aa9b26 100644
--- a/src/autofit/afblue.dat
+++ b/src/autofit/afblue.dat
@@ -2,7 +2,7 @@
 //
 //   Auto-fitter data for blue strings.
 //
-// Copyright (C) 2013-2020 by
+// Copyright (C) 2013-2021 by
 // David Turner, Robert Wilhelm, and Werner Lemberg.
 //
 // This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afblue.h b/src/autofit/afblue.h
index 486d663..311c9e3 100644
--- a/src/autofit/afblue.h
+++ b/src/autofit/afblue.h
@@ -7,7 +7,7 @@
  *
  *   Auto-fitter data for blue strings (specification).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afblue.hin b/src/autofit/afblue.hin
index 3957027..5186914 100644
--- a/src/autofit/afblue.hin
+++ b/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter data for blue strings (specification).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index 3b340cd..7e46b6b 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for CJK writing system (body).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -37,11 +37,6 @@
 #include "aferrors.h"
 
 
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-#include "afwarp.h"
-#endif
-
-
   /**************************************************************************
    *
    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
@@ -72,11 +67,11 @@
     AF_GlyphHintsRec  hints[1];
 
 
-    FT_TRACE5(( "\n"
-                "cjk standard widths computation (style `%s')\n"
-                "===================================================\n"
-                "\n",
+    FT_TRACE5(( "\n" ));
+    FT_TRACE5(( "cjk standard widths computation (style `%s')\n",
                 af_style_names[metrics->root.style_class->style] ));
+    FT_TRACE5(( "===================================================\n" ));
+    FT_TRACE5(( "\n" ));
 
     af_glyph_hints_init( hints, face->memory );
 
@@ -314,9 +309,9 @@
     /* style's entry in the `af_blue_stringset' array, computing its */
     /* extremum points (depending on the string properties)          */
 
-    FT_TRACE5(( "cjk blue zones computation\n"
-                "==========================\n"
-                "\n" ));
+    FT_TRACE5(( "cjk blue zones computation\n" ));
+    FT_TRACE5(( "==========================\n" ));
+    FT_TRACE5(( "\n" ));
 
 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
     shaper_buf = af_shaper_buf_create( face );
@@ -555,9 +550,8 @@
       if ( AF_CJK_IS_TOP_BLUE( bs ) )
         blue->flags |= AF_CJK_BLUE_TOP;
 
-      FT_TRACE5(( "    -> reference = %ld\n"
-                  "       overshoot = %ld\n",
-                  *blue_ref, *blue_shoot ));
+      FT_TRACE5(( "    -> reference = %ld\n", *blue_ref ));
+      FT_TRACE5(( "       overshoot = %ld\n", *blue_shoot ));
 
     } /* end for loop */
 
@@ -743,12 +737,12 @@
 
         blue->shoot.fit = blue->ref.fit - delta2;
 
-        FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n"
-                    "     ref:   cur=%.2f fit=%.2f\n"
-                    "     shoot: cur=%.2f fit=%.2f\n",
+        FT_TRACE5(( ">> active cjk blue zone %c%d[%ld/%ld]:\n",
                     ( dim == AF_DIMENSION_HORZ ) ? 'H' : 'V',
-                    nn, blue->ref.org, blue->shoot.org,
-                    blue->ref.cur / 64.0, blue->ref.fit / 64.0,
+                    nn, blue->ref.org, blue->shoot.org ));
+        FT_TRACE5(( "     ref:   cur=%.2f fit=%.2f\n",
+                    blue->ref.cur / 64.0, blue->ref.fit / 64.0 ));
+        FT_TRACE5(( "     shoot: cur=%.2f fit=%.2f\n",
                     blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
 
         blue->flags |= AF_CJK_BLUE_ACTIVE;
@@ -1401,11 +1395,6 @@
     /* compute flags depending on render mode, etc. */
     mode = metrics->root.scaler.render_mode;
 
-#if 0 /* AF_CONFIG_OPTION_USE_WARPER */
-    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
-      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
-#endif
-
     scaler_flags = hints->scaler_flags;
     other_flags  = 0;
 
@@ -1434,12 +1423,6 @@
 
     scaler_flags |= AF_SCALER_FLAG_NO_ADVANCE;
 
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-    /* get (global) warper flag */
-    if ( !metrics->root.globals->module->warping )
-      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
-#endif
-
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
@@ -2322,25 +2305,6 @@
       if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
            ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
       {
-
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-        if ( dim == AF_DIMENSION_HORZ                                  &&
-             metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
-             AF_HINTS_DO_WARP( hints )                                 )
-        {
-          AF_WarperRec  warper;
-          FT_Fixed      scale;
-          FT_Pos        delta;
-
-
-          af_warper_compute( &warper, hints, (AF_Dimension)dim,
-                             &scale, &delta );
-          af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
-                                    scale, delta );
-          continue;
-        }
-#endif /* AF_CONFIG_OPTION_USE_WARPER */
-
         af_cjk_hint_edges( hints, (AF_Dimension)dim );
         af_cjk_align_edge_points( hints, (AF_Dimension)dim );
         af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
index fd0f451..58aa298 100644
--- a/src/autofit/afcjk.h
+++ b/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for CJK writing system (specification).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afcover.h b/src/autofit/afcover.h
index 03085ad..c7ae1e9 100644
--- a/src/autofit/afcover.h
+++ b/src/autofit/afcover.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter coverages (specification only).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c
index 77d31df..a36b56f 100644
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
  *   Auto-fitter dummy routines to be used if no hinting should be
  *   performed (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afdummy.h b/src/autofit/afdummy.h
index efd799e..b58849f 100644
--- a/src/autofit/afdummy.h
+++ b/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
  *   Auto-fitter dummy routines to be used if no hinting should be
  *   performed (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/aferrors.h b/src/autofit/aferrors.h
index f908999..09bed66 100644
--- a/src/autofit/aferrors.h
+++ b/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
  *
  *   Autofitter error codes (specification only).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index d512942..b805b3b 100644
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter routines to compute global hinting values (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -19,6 +19,7 @@
 #include "afglobal.h"
 #include "afranges.h"
 #include "afshaper.h"
+#include "afws-decl.h"
 #include <freetype/internal/ftdebug.h>
 
 
@@ -32,11 +33,6 @@
 #define FT_COMPONENT  afglobal
 
 
-  /* get writing system specific header files */
-#undef  WRITING_SYSTEM
-#define WRITING_SYSTEM( ws, WS )  /* empty */
-#include "afwrtsys.h"
-
 #include "aferrors.h"
 
 
@@ -74,7 +70,7 @@
   af_writing_system_classes[] =
   {
 
-#include "afwrtsys.h"
+#include "afws-iter.h"
 
     NULL  /* do not remove */
   };
@@ -285,10 +281,10 @@
 
 #ifdef FT_DEBUG_LEVEL_TRACE
 
-    FT_TRACE4(( "\n"
-                "style coverage\n"
-                "==============\n"
-                "\n" ));
+    FT_TRACE4(( "\n" ));
+    FT_TRACE4(( "style coverage\n" ));
+    FT_TRACE4(( "==============\n" ));
+    FT_TRACE4(( "\n" ));
 
     for ( ss = 0; af_style_classes[ss]; ss++ )
     {
@@ -478,6 +474,10 @@
           {
             style = (AF_Style)( globals->glyph_styles[gindex] &
                                 AF_STYLE_UNASSIGNED           );
+            /* IMPORTANT: Clear the error code, see
+             * https://gitlab.freedesktop.org/freetype/freetype/-/issues/1063
+             */
+            error = FT_Err_Ok;
             goto Again;
           }
 
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index fecf7af..cd97e71 100644
--- a/src/autofit/afglobal.h
+++ b/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
  *   Auto-fitter routines to compute global hinting values
  *   (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index a8e0089..5506afd 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -32,6 +32,104 @@
 #define FT_COMPONENT  afhints
 
 
+  FT_LOCAL_DEF( void )
+  af_sort_pos( FT_UInt  count,
+               FT_Pos*  table )
+  {
+    FT_UInt  i, j;
+    FT_Pos   swap;
+
+
+    for ( i = 1; i < count; i++ )
+    {
+      for ( j = i; j > 0; j-- )
+      {
+        if ( table[j] >= table[j - 1] )
+          break;
+
+        swap         = table[j];
+        table[j]     = table[j - 1];
+        table[j - 1] = swap;
+      }
+    }
+  }
+
+
+  FT_LOCAL_DEF( void )
+  af_sort_and_quantize_widths( FT_UInt*  count,
+                               AF_Width  table,
+                               FT_Pos    threshold )
+  {
+    FT_UInt      i, j;
+    FT_UInt      cur_idx;
+    FT_Pos       cur_val;
+    FT_Pos       sum;
+    AF_WidthRec  swap;
+
+
+    if ( *count == 1 )
+      return;
+
+    /* sort */
+    for ( i = 1; i < *count; i++ )
+    {
+      for ( j = i; j > 0; j-- )
+      {
+        if ( table[j].org >= table[j - 1].org )
+          break;
+
+        swap         = table[j];
+        table[j]     = table[j - 1];
+        table[j - 1] = swap;
+      }
+    }
+
+    cur_idx = 0;
+    cur_val = table[cur_idx].org;
+
+    /* compute and use mean values for clusters not larger than  */
+    /* `threshold'; this is very primitive and might not yield   */
+    /* the best result, but normally, using reference character  */
+    /* `o', `*count' is 2, so the code below is fully sufficient */
+    for ( i = 1; i < *count; i++ )
+    {
+      if ( table[i].org - cur_val > threshold ||
+           i == *count - 1                    )
+      {
+        sum = 0;
+
+        /* fix loop for end of array */
+        if ( table[i].org - cur_val <= threshold &&
+             i == *count - 1                     )
+          i++;
+
+        for ( j = cur_idx; j < i; j++ )
+        {
+          sum         += table[j].org;
+          table[j].org = 0;
+        }
+        table[cur_idx].org = sum / (FT_Pos)j;
+
+        if ( i < *count - 1 )
+        {
+          cur_idx = i + 1;
+          cur_val = table[cur_idx].org;
+        }
+      }
+    }
+
+    cur_idx = 1;
+
+    /* compress array to remove zero values */
+    for ( i = 1; i < *count; i++ )
+    {
+      if ( table[i].org )
+        table[cur_idx++] = table[i];
+    }
+
+    *count = cur_idx;
+  }
+
   /* Get new segment for given axis. */
 
   FT_LOCAL_DEF( FT_Error )
@@ -764,7 +862,7 @@
   {
     FT_Error   error   = FT_Err_Ok;
     AF_Point   points;
-    FT_UInt    old_max, new_max;
+    FT_Int     old_max, new_max;
     FT_Fixed   x_scale = hints->x_scale;
     FT_Fixed   y_scale = hints->y_scale;
     FT_Pos     x_delta = hints->x_delta;
@@ -781,8 +879,8 @@
     hints->axis[1].num_edges    = 0;
 
     /* first of all, reallocate the contours array if necessary */
-    new_max = (FT_UInt)outline->n_contours;
-    old_max = (FT_UInt)hints->max_contours;
+    new_max = outline->n_contours;
+    old_max = hints->max_contours;
 
     if ( new_max <= AF_CONTOURS_EMBEDDED )
     {
@@ -797,12 +895,12 @@
       if ( hints->contours == hints->embedded.contours )
         hints->contours = NULL;
 
-      new_max = ( new_max + 3 ) & ~3U; /* round up to a multiple of 4 */
+      new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
 
       if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
         goto Exit;
 
-      hints->max_contours = (FT_Int)new_max;
+      hints->max_contours = new_max;
     }
 
     /*
@@ -810,8 +908,8 @@
      * note that we reserve two additional point positions, used to
      * hint metrics appropriately
      */
-    new_max = (FT_UInt)( outline->n_points + 2 );
-    old_max = (FT_UInt)hints->max_points;
+    new_max = outline->n_points + 2;
+    old_max = hints->max_points;
 
     if ( new_max <= AF_POINTS_EMBEDDED )
     {
@@ -826,12 +924,12 @@
       if ( hints->points == hints->embedded.points )
         hints->points = NULL;
 
-      new_max = ( new_max + 2 + 7 ) & ~7U; /* round up to a multiple of 8 */
+      new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
 
       if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
         goto Exit;
 
-      hints->max_points = (FT_Int)new_max;
+      hints->max_points = new_max;
     }
 
     hints->num_points   = outline->n_points;
@@ -855,9 +953,6 @@
     hints->x_delta = x_delta;
     hints->y_delta = y_delta;
 
-    hints->xmin_delta = 0;
-    hints->xmax_delta = 0;
-
     points = hints->points;
     if ( hints->num_points == 0 )
       goto Exit;
@@ -1688,33 +1783,4 @@
   }
 
 
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-
-  /* Apply (small) warp scale and warp delta for given dimension. */
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_scale_dim( AF_GlyphHints  hints,
-                            AF_Dimension   dim,
-                            FT_Fixed       scale,
-                            FT_Pos         delta )
-  {
-    AF_Point  points       = hints->points;
-    AF_Point  points_limit = points + hints->num_points;
-    AF_Point  point;
-
-
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      for ( point = points; point < points_limit; point++ )
-        point->x = FT_MulFix( point->fx, scale ) + delta;
-    }
-    else
-    {
-      for ( point = points; point < points_limit; point++ )
-        point->y = FT_MulFix( point->fy, scale ) + delta;
-    }
-  }
-
-#endif /* AF_CONFIG_OPTION_USE_WARPER */
-
 /* END */
diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
index 6397f09..38d2847 100644
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -362,9 +362,6 @@
                                     /* implementations         */
     AF_StyleMetrics  metrics;
 
-    FT_Pos           xmin_delta;    /* used for warping */
-    FT_Pos           xmax_delta;
-
     /* Two arrays to avoid allocation penalty.            */
     /* The `embedded' structure must be the last element! */
     struct
@@ -408,10 +405,6 @@
 #define AF_HINTS_DO_ADVANCE( h )                                \
           !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_ADVANCE )
 
-#define AF_HINTS_DO_WARP( h )                                  \
-          !AF_HINTS_TEST_SCALER( h, AF_SCALER_FLAG_NO_WARPER )
-
-
 
   FT_LOCAL( AF_Direction )
   af_direction_compute( FT_Pos  dx,
@@ -459,14 +452,6 @@
   af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
                                     AF_Dimension   dim );
 
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-  FT_LOCAL( void )
-  af_glyph_hints_scale_dim( AF_GlyphHints  hints,
-                            AF_Dimension   dim,
-                            FT_Fixed       scale,
-                            FT_Pos         delta );
-#endif
-
   FT_LOCAL( void )
   af_glyph_hints_done( AF_GlyphHints  hints );
 
diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c
index bc2837a..064c300 100644
--- a/src/autofit/afindic.c
+++ b/src/autofit/afindic.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for Indic writing system (body).
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -27,11 +27,6 @@
 #include "aferrors.h"
 
 
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-#include "afwarp.h"
-#endif
-
-
   static FT_Error
   af_indic_metrics_init( AF_CJKMetrics  metrics,
                          FT_Face        face )
diff --git a/src/autofit/afindic.h b/src/autofit/afindic.h
index 088b88b..3e46724 100644
--- a/src/autofit/afindic.h
+++ b/src/autofit/afindic.h
@@ -5,7 +5,7 @@
  *   Auto-fitter hinting routines for Indic writing system
  *   (specification).
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 21ec02e..5e81d77 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for latin writing system (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -24,11 +24,6 @@
 #include "aferrors.h"
 
 
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-#include "afwarp.h"
-#endif
-
-
   /**************************************************************************
    *
    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
@@ -63,11 +58,11 @@
     AF_GlyphHintsRec  hints[1];
 
 
-    FT_TRACE5(( "\n"
-                "latin standard widths computation (style `%s')\n"
-                "=====================================================\n"
-                "\n",
+    FT_TRACE5(( "\n" ));
+    FT_TRACE5(( "latin standard widths computation (style `%s')\n",
                 af_style_names[metrics->root.style_class->style] ));
+    FT_TRACE5(( "=====================================================\n" ));
+    FT_TRACE5(( "\n" ));
 
     af_glyph_hints_init( hints, face->memory );
 
@@ -350,9 +345,9 @@
     /* we walk over the blue character strings as specified in the */
     /* style's entry in the `af_blue_stringset' array              */
 
-    FT_TRACE5(( "latin blue zones computation\n"
-                "============================\n"
-                "\n" ));
+    FT_TRACE5(( "latin blue zones computation\n" ));
+    FT_TRACE5(( "============================\n" ));
+    FT_TRACE5(( "\n" ));
 
 #ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
     shaper_buf = af_shaper_buf_create( face );
@@ -976,9 +971,8 @@
       if ( AF_LATIN_IS_X_HEIGHT_BLUE( bs ) )
         blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
 
-      FT_TRACE5(( "    -> reference = %ld\n"
-                  "       overshoot = %ld\n",
-                  *blue_ref, *blue_shoot ));
+      FT_TRACE5(( "    -> reference = %ld\n", *blue_ref ));
+      FT_TRACE5(( "       overshoot = %ld\n", *blue_shoot ));
 
     } /* end for loop */
 
@@ -1275,29 +1269,28 @@
 
             if ( dist == 0 )
             {
-              FT_TRACE5((
-                "af_latin_metrics_scale_dim:"
-                " x height alignment (style `%s'):\n"
-                "                           "
-                " vertical scaling changed from %.5f to %.5f (by %ld%%)\n"
-                "\n",
-                af_style_names[metrics->root.style_class->style],
-                scale / 65536.0,
-                new_scale / 65536.0,
-                ( fitted - scaled ) * 100 / scaled ));
+              FT_TRACE5(( "af_latin_metrics_scale_dim:"
+                          " x height alignment (style `%s'):\n",
+                          af_style_names[metrics->root.style_class->style] ));
+              FT_TRACE5(( "                           "
+                          " vertical scaling changed"
+                          " from %.5f to %.5f (by %ld%%)\n",
+                          scale / 65536.0,
+                          new_scale / 65536.0,
+                          ( fitted - scaled ) * 100 / scaled ));
+              FT_TRACE5(( "\n" ));
 
               scale = new_scale;
             }
 #ifdef FT_DEBUG_LEVEL_TRACE
             else
             {
-              FT_TRACE5((
-                "af_latin_metrics_scale_dim:"
-                " x height alignment (style `%s'):\n"
-                "                           "
-                " excessive vertical scaling abandoned\n"
-                "\n",
-                af_style_names[metrics->root.style_class->style] ));
+              FT_TRACE5(( "af_latin_metrics_scale_dim:"
+                          " x height alignment (style `%s'):\n",
+                          af_style_names[metrics->root.style_class->style] ));
+              FT_TRACE5(( "                           "
+                          " excessive vertical scaling abandoned\n" ));
+              FT_TRACE5(( "\n" ));
             }
 #endif
           }
@@ -1346,9 +1339,11 @@
 
 #ifdef FT_DEBUG_LEVEL_TRACE
     if ( axis->extra_light )
-      FT_TRACE5(( "`%s' style is extra light (at current resolution)\n"
-                  "\n",
+    {
+      FT_TRACE5(( "`%s' style is extra light (at current resolution)\n",
                   af_style_names[metrics->root.style_class->style] ));
+      FT_TRACE5(( "\n" ));
+    }
 #endif
 
     if ( dim == AF_DIMENSION_VERT )
@@ -1473,13 +1468,13 @@
         AF_LatinBlue  blue = &axis->blues[nn];
 
 
-        FT_TRACE5(( "  reference %d: %ld scaled to %.2f%s\n"
-                    "  overshoot %d: %ld scaled to %.2f%s\n",
+        FT_TRACE5(( "  reference %d: %ld scaled to %.2f%s\n",
                     nn,
                     blue->ref.org,
                     blue->ref.fit / 64.0,
                     ( blue->flags & AF_LATIN_BLUE_ACTIVE ) ? ""
-                                                           : " (inactive)",
+                                                           : " (inactive)" ));
+        FT_TRACE5(( "  overshoot %d: %ld scaled to %.2f%s\n",
                     nn,
                     blue->shoot.org,
                     blue->shoot.fit / 64.0,
@@ -1847,6 +1842,31 @@
              ( FT_ABS( point->out_dir ) == major_dir ||
                point == point->prev                  ) )
         {
+          /*
+           * For efficiency, we restrict the number of segments to 1000,
+           * which is a heuristic value: it is very unlikely that a glyph
+           * with so many segments can be hinted in a sensible way.
+           * Reasons:
+           *
+           * - The glyph has really 1000 segments; this implies that it has
+           *   at least 2000 outline points.  Assuming 'normal' fonts that
+           *   have superfluous points optimized away, viewing such a glyph
+           *   only makes sense at large magnifications where hinting
+           *   isn't applied anyway.
+           *
+           * - We have a broken glyph.  Hinting doesn't make sense in this
+           *   case either.
+           */
+          if ( axis->num_segments > 1000 )
+          {
+            FT_TRACE0(( "af_latin_hints_compute_segments:"
+                        " more than 1000 segments in this glyph;\n" ));
+            FT_TRACE0(( "                                "
+                        " hinting is suppressed\n" ));
+            axis->num_segments = 0;
+            return FT_Err_Ok;
+          }
+
           /* this is the start of a new segment! */
           segment_dir = (AF_Direction)point->out_dir;
 
@@ -2089,7 +2109,7 @@
       {
         if ( seg2->link != seg1 )
         {
-          seg1->link  = 0;
+          seg1->link  = NULL;
           seg1->serif = seg2->link;
         }
       }
@@ -2611,11 +2631,6 @@
     /* compute flags depending on render mode, etc. */
     mode = metrics->root.scaler.render_mode;
 
-#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
-    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
-      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
-#endif
-
     scaler_flags = hints->scaler_flags;
     other_flags  = 0;
 
@@ -2653,12 +2668,6 @@
          ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0          )
       scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
 
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-    /* get (global) warper flag */
-    if ( !metrics->root.globals->module->warping )
-      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
-#endif
-
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
@@ -3575,24 +3584,6 @@
     /* grid-fit the outline */
     for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
     {
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-      if ( dim == AF_DIMENSION_HORZ                                  &&
-           metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
-           AF_HINTS_DO_WARP( hints )                                 )
-      {
-        AF_WarperRec  warper;
-        FT_Fixed      scale;
-        FT_Pos        delta;
-
-
-        af_warper_compute( &warper, hints, (AF_Dimension)dim,
-                           &scale, &delta );
-        af_glyph_hints_scale_dim( hints, (AF_Dimension)dim,
-                                  scale, delta );
-        continue;
-      }
-#endif /* AF_CONFIG_OPTION_USE_WARPER */
-
       if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
            ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
       {
diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
index 62bc4c8..d6b919e 100644
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
  *   Auto-fitter hinting routines for latin writing system
  *   (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
deleted file mode 100644
index 902f398..0000000
--- a/src/autofit/aflatin2.c
+++ /dev/null
@@ -1,2428 +0,0 @@
-/* ATTENTION: This file doesn't compile.  It is only here as a reference */
-/*            of an alternative latin hinting algorithm that was always  */
-/*            marked as experimental.                                    */
-
-
-/****************************************************************************
- *
- * aflatin2.c
- *
- *   Auto-fitter hinting routines for latin writing system (body).
- *
- * Copyright (C) 2003-2020 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used,
- * modified, and distributed under the terms of the FreeType project
- * license, LICENSE.TXT.  By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- */
-
-
-#include <freetype/ftadvanc.h>
-
-
-#ifdef FT_OPTION_AUTOFIT2
-
-#include "afglobal.h"
-#include "aflatin.h"
-#include "aflatin2.h"
-#include "aferrors.h"
-
-
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-#include "afwarp.h"
-#endif
-
-
-  /**************************************************************************
-   *
-   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
-   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
-   * messages during execution.
-   */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  aflatin2
-
-
-  FT_LOCAL_DEF( FT_Error )
-  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
-                                    AF_Dimension   dim );
-
-  FT_LOCAL_DEF( void )
-  af_latin2_hints_link_segments( AF_GlyphHints  hints,
-                                 AF_Dimension   dim );
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****            L A T I N   G L O B A L   M E T R I C S            *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  FT_LOCAL_DEF( void )
-  af_latin2_metrics_init_widths( AF_LatinMetrics  metrics,
-                                 FT_Face          face )
-  {
-    /* scan the array of segments in each direction */
-    AF_GlyphHintsRec  hints[1];
-
-
-    af_glyph_hints_init( hints, face->memory );
-
-    metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
-    metrics->axis[AF_DIMENSION_VERT].width_count = 0;
-
-    {
-      FT_Error             error;
-      FT_UInt              glyph_index;
-      int                  dim;
-      AF_LatinMetricsRec   dummy[1];
-      AF_Scaler            scaler = &dummy->root.scaler;
-
-
-      glyph_index = FT_Get_Char_Index(
-                      face,
-                      metrics->root.style_class->standard_char );
-      if ( glyph_index == 0 )
-        goto Exit;
-
-      error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
-      if ( error || face->glyph->outline.n_points <= 0 )
-        goto Exit;
-
-      FT_ZERO( dummy );
-
-      dummy->units_per_em = metrics->units_per_em;
-      scaler->x_scale     = scaler->y_scale = 0x10000L;
-      scaler->x_delta     = scaler->y_delta = 0;
-      scaler->face        = face;
-      scaler->render_mode = FT_RENDER_MODE_NORMAL;
-      scaler->flags       = 0;
-
-      af_glyph_hints_rescale( hints, (AF_StyleMetrics)dummy );
-
-      error = af_glyph_hints_reload( hints, &face->glyph->outline );
-      if ( error )
-        goto Exit;
-
-      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
-      {
-        AF_LatinAxis  axis    = &metrics->axis[dim];
-        AF_AxisHints  axhints = &hints->axis[dim];
-        AF_Segment    seg, limit, link;
-        FT_UInt       num_widths = 0;
-
-
-        error = af_latin2_hints_compute_segments( hints,
-                                                 (AF_Dimension)dim );
-        if ( error )
-          goto Exit;
-
-        af_latin2_hints_link_segments( hints,
-                                      (AF_Dimension)dim );
-
-        seg   = axhints->segments;
-        limit = seg + axhints->num_segments;
-
-        for ( ; seg < limit; seg++ )
-        {
-          link = seg->link;
-
-          /* we only consider stem segments there! */
-          if ( link && link->link == seg && link > seg )
-          {
-            FT_Pos  dist;
-
-
-            dist = seg->pos - link->pos;
-            if ( dist < 0 )
-              dist = -dist;
-
-            if ( num_widths < AF_LATIN_MAX_WIDTHS )
-              axis->widths[num_widths++].org = dist;
-          }
-        }
-
-        af_sort_widths( num_widths, axis->widths );
-        axis->width_count = num_widths;
-      }
-
-  Exit:
-      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
-      {
-        AF_LatinAxis  axis = &metrics->axis[dim];
-        FT_Pos        stdw;
-
-
-        stdw = ( axis->width_count > 0 )
-                 ? axis->widths[0].org
-                 : AF_LATIN_CONSTANT( metrics, 50 );
-
-        /* let's try 20% of the smallest width */
-        axis->edge_distance_threshold = stdw / 5;
-        axis->standard_width          = stdw;
-        axis->extra_light             = 0;
-      }
-    }
-
-    af_glyph_hints_done( hints );
-  }
-
-
-
-#define AF_LATIN_MAX_TEST_CHARACTERS  12
-
-
-  static const char af_latin2_blue_chars[AF_LATIN_MAX_BLUES]
-                                        [AF_LATIN_MAX_TEST_CHARACTERS+1] =
-  {
-    "THEZOCQS",
-    "HEZLOCUS",
-    "fijkdbh",
-    "xzroesc",
-    "xzroesc",
-    "pqgjy"
-  };
-
-
-  static void
-  af_latin2_metrics_init_blues( AF_LatinMetrics  metrics,
-                                FT_Face          face )
-  {
-    FT_Pos        flats [AF_LATIN_MAX_TEST_CHARACTERS];
-    FT_Pos        rounds[AF_LATIN_MAX_TEST_CHARACTERS];
-    FT_Int        num_flats;
-    FT_Int        num_rounds;
-    FT_Int        bb;
-    AF_LatinBlue  blue;
-    FT_Error      error;
-    AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];
-    FT_GlyphSlot  glyph = face->glyph;
-
-
-    /* we compute the blues simply by loading each character from the     */
-    /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
-    /* bottom-most points (depending on `AF_IS_TOP_BLUE')                 */
-
-    FT_TRACE5(( "blue zones computation\n"
-                "======================\n\n" ));
-
-    for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
-    {
-      const char*  p     = af_latin2_blue_chars[bb];
-      const char*  limit = p + AF_LATIN_MAX_TEST_CHARACTERS;
-      FT_Pos*      blue_ref;
-      FT_Pos*      blue_shoot;
-
-
-      FT_TRACE5(( "blue zone %d:\n", bb ));
-
-      num_flats  = 0;
-      num_rounds = 0;
-
-      for ( ; p < limit && *p; p++ )
-      {
-        FT_UInt     glyph_index;
-        FT_Int      best_point, best_y, best_first, best_last;
-        FT_Vector*  points;
-        FT_Bool     round;
-
-
-        /* load the character in the face -- skip unknown or empty ones */
-        glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
-        if ( glyph_index == 0 )
-          continue;
-
-        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
-        if ( error || glyph->outline.n_points <= 0 )
-          continue;
-
-        /* now compute min or max point indices and coordinates */
-        points      = glyph->outline.points;
-        best_point  = -1;
-        best_y      = 0;  /* make compiler happy */
-        best_first  = 0;  /* ditto */
-        best_last   = 0;  /* ditto */
-
-        {
-          FT_Int  nn;
-          FT_Int  first = 0;
-          FT_Int  last  = -1;
-
-
-          for ( nn = 0; nn < glyph->outline.n_contours; first = last+1, nn++ )
-          {
-            FT_Int  old_best_point = best_point;
-            FT_Int  pp;
-
-
-            last = glyph->outline.contours[nn];
-
-            /* Avoid single-point contours since they are never rasterized. */
-            /* In some fonts, they correspond to mark attachment points     */
-            /* which are way outside of the glyph's real outline.           */
-            if ( last <= first )
-                continue;
-
-            if ( AF_LATIN_IS_TOP_BLUE( bb ) )
-            {
-              for ( pp = first; pp <= last; pp++ )
-                if ( best_point < 0 || points[pp].y > best_y )
-                {
-                  best_point = pp;
-                  best_y     = points[pp].y;
-                }
-            }
-            else
-            {
-              for ( pp = first; pp <= last; pp++ )
-                if ( best_point < 0 || points[pp].y < best_y )
-                {
-                  best_point = pp;
-                  best_y     = points[pp].y;
-                }
-            }
-
-            if ( best_point != old_best_point )
-            {
-              best_first = first;
-              best_last  = last;
-            }
-          }
-          FT_TRACE5(( "  %c  %d", *p, best_y ));
-        }
-
-        /* now check whether the point belongs to a straight or round   */
-        /* segment; we first need to find in which contour the extremum */
-        /* lies, then inspect its previous and next points              */
-        if ( best_point >= 0 )
-        {
-          FT_Pos  best_x = points[best_point].x;
-          FT_Int  start, end, prev, next;
-          FT_Pos  dist;
-
-
-          /* now look for the previous and next points that are not on the */
-          /* same Y coordinate.  Threshold the `closeness'...              */
-          start = end = best_point;
-
-          do
-          {
-            prev = start - 1;
-            if ( prev < best_first )
-              prev = best_last;
-
-            dist = FT_ABS( points[prev].y - best_y );
-            /* accept a small distance or a small angle (both values are */
-            /* heuristic; value 20 corresponds to approx. 2.9 degrees)   */
-            if ( dist > 5 )
-              if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
-                break;
-
-            start = prev;
-
-          } while ( start != best_point );
-
-          do
-          {
-            next = end + 1;
-            if ( next > best_last )
-              next = best_first;
-
-            dist = FT_ABS( points[next].y - best_y );
-            if ( dist > 5 )
-              if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
-                break;
-
-            end = next;
-
-          } while ( end != best_point );
-
-          /* now, set the `round' flag depending on the segment's kind */
-          round = FT_BOOL(
-            FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
-            FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
-
-          FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
-        }
-
-        if ( round )
-          rounds[num_rounds++] = best_y;
-        else
-          flats[num_flats++]   = best_y;
-      }
-
-      if ( num_flats == 0 && num_rounds == 0 )
-      {
-        /*
-         * we couldn't find a single glyph to compute this blue zone,
-         * we will simply ignore it then
-         */
-        FT_TRACE5(( "  empty\n" ));
-        continue;
-      }
-
-      /* we have computed the contents of the `rounds' and `flats' tables, */
-      /* now determine the reference and overshoot position of the blue -- */
-      /* we simply take the median value after a simple sort               */
-      af_sort_pos( num_rounds, rounds );
-      af_sort_pos( num_flats,  flats );
-
-      blue       = & axis->blues[axis->blue_count];
-      blue_ref   = & blue->ref.org;
-      blue_shoot = & blue->shoot.org;
-
-      axis->blue_count++;
-
-      if ( num_flats == 0 )
-      {
-        *blue_ref   =
-        *blue_shoot = rounds[num_rounds / 2];
-      }
-      else if ( num_rounds == 0 )
-      {
-        *blue_ref   =
-        *blue_shoot = flats[num_flats / 2];
-      }
-      else
-      {
-        *blue_ref   = flats[num_flats / 2];
-        *blue_shoot = rounds[num_rounds / 2];
-      }
-
-      /* there are sometimes problems: if the overshoot position of top     */
-      /* zones is under its reference position, or the opposite for bottom  */
-      /* zones.  We must thus check everything there and correct the errors */
-      if ( *blue_shoot != *blue_ref )
-      {
-        FT_Pos   ref      = *blue_ref;
-        FT_Pos   shoot    = *blue_shoot;
-        FT_Bool  over_ref = FT_BOOL( shoot > ref );
-
-
-        if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
-        {
-          *blue_ref   =
-          *blue_shoot = ( shoot + ref ) / 2;
-
-          FT_TRACE5(( "  [overshoot smaller than reference,"
-                      " taking mean value]\n" ));
-        }
-      }
-
-      blue->flags = 0;
-      if ( AF_LATIN_IS_TOP_BLUE( bb ) )
-        blue->flags |= AF_LATIN_BLUE_TOP;
-
-      /*
-       * The following flag is used later to adjust the y and x scales
-       * in order to optimize the pixel grid alignment of the top of small
-       * letters.
-       */
-      if ( AF_LATIN_IS_X_HEIGHT_BLUE( bb ) )
-        blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
-
-      FT_TRACE5(( "    -> reference = %ld\n"
-                  "       overshoot = %ld\n",
-                  *blue_ref, *blue_shoot ));
-    }
-
-    return;
-  }
-
-
-  FT_LOCAL_DEF( void )
-  af_latin2_metrics_check_digits( AF_LatinMetrics  metrics,
-                                  FT_Face          face )
-  {
-    FT_UInt   i;
-    FT_Bool   started = 0, same_width = 1;
-    FT_Fixed  advance, old_advance = 0;
-
-
-    /* check whether all ASCII digits have the same advance width; */
-    /* digit `0' is 0x30 in all supported charmaps                 */
-    for ( i = 0x30; i <= 0x39; i++ )
-    {
-      FT_UInt  glyph_index;
-
-
-      glyph_index = FT_Get_Char_Index( face, i );
-      if ( glyph_index == 0 )
-        continue;
-
-      if ( FT_Get_Advance( face, glyph_index,
-                           FT_LOAD_NO_SCALE         |
-                           FT_LOAD_NO_HINTING       |
-                           FT_LOAD_IGNORE_TRANSFORM,
-                           &advance ) )
-        continue;
-
-      if ( started )
-      {
-        if ( advance != old_advance )
-        {
-          same_width = 0;
-          break;
-        }
-      }
-      else
-      {
-        old_advance = advance;
-        started     = 1;
-      }
-    }
-
-    metrics->root.digits_have_same_width = same_width;
-  }
-
-
-  FT_LOCAL_DEF( FT_Error )
-  af_latin2_metrics_init( AF_LatinMetrics  metrics,
-                          FT_Face          face )
-  {
-    FT_Error    error  = FT_Err_Ok;
-    FT_CharMap  oldmap = face->charmap;
-    FT_UInt     ee;
-
-    static const FT_Encoding  latin_encodings[] =
-    {
-      FT_ENCODING_UNICODE,
-      FT_ENCODING_APPLE_ROMAN,
-      FT_ENCODING_ADOBE_STANDARD,
-      FT_ENCODING_ADOBE_LATIN_1,
-      FT_ENCODING_NONE  /* end of list */
-    };
-
-
-    metrics->units_per_em = face->units_per_EM;
-
-    /* do we have a latin charmap in there? */
-    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
-    {
-      error = FT_Select_Charmap( face, latin_encodings[ee] );
-      if ( !error )
-        break;
-    }
-
-    if ( !error )
-    {
-      af_latin2_metrics_init_widths( metrics, face );
-      af_latin2_metrics_init_blues( metrics, face );
-      af_latin2_metrics_check_digits( metrics, face );
-    }
-
-    FT_Set_Charmap( face, oldmap );
-    return FT_Err_Ok;
-  }
-
-
-  static void
-  af_latin2_metrics_scale_dim( AF_LatinMetrics  metrics,
-                               AF_Scaler        scaler,
-                               AF_Dimension     dim )
-  {
-    FT_Fixed      scale;
-    FT_Pos        delta;
-    AF_LatinAxis  axis;
-    FT_UInt       nn;
-
-
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      scale = scaler->x_scale;
-      delta = scaler->x_delta;
-    }
-    else
-    {
-      scale = scaler->y_scale;
-      delta = scaler->y_delta;
-    }
-
-    axis = &metrics->axis[dim];
-
-    if ( axis->org_scale == scale && axis->org_delta == delta )
-      return;
-
-    axis->org_scale = scale;
-    axis->org_delta = delta;
-
-    /*
-     * correct Y scale to optimize the alignment of the top of small
-     * letters to the pixel grid
-     */
-    if ( dim == AF_DIMENSION_VERT )
-    {
-      AF_LatinAxis  vaxis = &metrics->axis[AF_DIMENSION_VERT];
-      AF_LatinBlue  blue = NULL;
-
-
-      for ( nn = 0; nn < vaxis->blue_count; nn++ )
-      {
-        if ( vaxis->blues[nn].flags & AF_LATIN_BLUE_ADJUSTMENT )
-        {
-          blue = &vaxis->blues[nn];
-          break;
-        }
-      }
-
-      if ( blue )
-      {
-        FT_Pos   scaled;
-        FT_Pos   threshold;
-        FT_Pos   fitted;
-        FT_UInt  limit;
-        FT_UInt  ppem;
-
-
-        scaled    = FT_MulFix( blue->shoot.org, scaler->y_scale );
-        ppem      = metrics->root.scaler.face->size->metrics.x_ppem;
-        limit     = metrics->root.globals->increase_x_height;
-        threshold = 40;
-
-        /* if the `increase-x-height' property is active, */
-        /* we round up much more often                    */
-        if ( limit                                 &&
-             ppem <= limit                         &&
-             ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN )
-          threshold = 52;
-
-        fitted = ( scaled + threshold ) & ~63;
-
-#if 1
-        if ( scaled != fitted )
-        {
-          scale = FT_MulDiv( scale, fitted, scaled );
-          FT_TRACE5(( "== scaled x-top = %.2g"
-                      "  fitted = %.2g, scaling = %.4g\n",
-                      scaled / 64.0, fitted / 64.0,
-                      ( fitted * 1.0 ) / scaled ));
-        }
-#endif
-      }
-    }
-
-    axis->scale = scale;
-    axis->delta = delta;
-
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      metrics->root.scaler.x_scale = scale;
-      metrics->root.scaler.x_delta = delta;
-    }
-    else
-    {
-      metrics->root.scaler.y_scale = scale;
-      metrics->root.scaler.y_delta = delta;
-    }
-
-    /* scale the standard widths */
-    for ( nn = 0; nn < axis->width_count; nn++ )
-    {
-      AF_Width  width = axis->widths + nn;
-
-
-      width->cur = FT_MulFix( width->org, scale );
-      width->fit = width->cur;
-    }
-
-    /* an extra-light axis corresponds to a standard width that is */
-    /* smaller than 5/8 pixels                                     */
-    axis->extra_light =
-      FT_BOOL( FT_MulFix( axis->standard_width, scale ) < 32 + 8 );
-
-    if ( dim == AF_DIMENSION_VERT )
-    {
-      /* scale the blue zones */
-      for ( nn = 0; nn < axis->blue_count; nn++ )
-      {
-        AF_LatinBlue  blue = &axis->blues[nn];
-        FT_Pos        dist;
-
-
-        blue->ref.cur   = FT_MulFix( blue->ref.org, scale ) + delta;
-        blue->ref.fit   = blue->ref.cur;
-        blue->shoot.cur = FT_MulFix( blue->shoot.org, scale ) + delta;
-        blue->shoot.fit = blue->shoot.cur;
-        blue->flags    &= ~AF_LATIN_BLUE_ACTIVE;
-
-        /* a blue zone is only active if it is less than 3/4 pixels tall */
-        dist = FT_MulFix( blue->ref.org - blue->shoot.org, scale );
-        if ( dist <= 48 && dist >= -48 )
-        {
-          FT_Pos  delta1, delta2;
-
-          delta1 = blue->shoot.org - blue->ref.org;
-          delta2 = delta1;
-          if ( delta1 < 0 )
-            delta2 = -delta2;
-
-          delta2 = FT_MulFix( delta2, scale );
-
-          if ( delta2 < 32 )
-            delta2 = 0;
-          else if ( delta2 < 64 )
-            delta2 = 32 + ( ( ( delta2 - 32 ) + 16 ) & ~31 );
-          else
-            delta2 = FT_PIX_ROUND( delta2 );
-
-          if ( delta1 < 0 )
-            delta2 = -delta2;
-
-          blue->ref.fit   = FT_PIX_ROUND( blue->ref.cur );
-          blue->shoot.fit = blue->ref.fit + delta2;
-
-          FT_TRACE5(( ">> activating blue zone %d:"
-                      "  ref.cur=%.2g ref.fit=%.2g"
-                      "  shoot.cur=%.2g shoot.fit=%.2g\n",
-                      nn, blue->ref.cur / 64.0, blue->ref.fit / 64.0,
-                      blue->shoot.cur / 64.0, blue->shoot.fit / 64.0 ));
-
-          blue->flags |= AF_LATIN_BLUE_ACTIVE;
-        }
-      }
-    }
-  }
-
-
-  FT_LOCAL_DEF( void )
-  af_latin2_metrics_scale( AF_LatinMetrics  metrics,
-                           AF_Scaler        scaler )
-  {
-    metrics->root.scaler.render_mode = scaler->render_mode;
-    metrics->root.scaler.face        = scaler->face;
-    metrics->root.scaler.flags       = scaler->flags;
-
-    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
-    af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
-  }
-
-
-  /* Extract standard_width from writing system/script specific */
-  /* metrics class.                                             */
-
-  FT_LOCAL_DEF( void )
-  af_latin2_get_standard_widths( AF_LatinMetrics  metrics,
-                                 FT_Pos*          stdHW,
-                                 FT_Pos*          stdVW )
-  {
-    if ( stdHW )
-      *stdHW = metrics->axis[AF_DIMENSION_VERT].standard_width;
-
-    if ( stdVW )
-      *stdVW = metrics->axis[AF_DIMENSION_HORZ].standard_width;
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****           L A T I N   G L Y P H   A N A L Y S I S             *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-#define  SORT_SEGMENTS
-
-  FT_LOCAL_DEF( FT_Error )
-  af_latin2_hints_compute_segments( AF_GlyphHints  hints,
-                                    AF_Dimension   dim )
-  {
-    AF_AxisHints  axis          = &hints->axis[dim];
-    FT_Memory     memory        = hints->memory;
-    FT_Error      error         = FT_Err_Ok;
-    AF_Segment    segment       = NULL;
-    AF_SegmentRec seg0;
-    AF_Point*     contour       = hints->contours;
-    AF_Point*     contour_limit = contour + hints->num_contours;
-    AF_Direction  major_dir, segment_dir;
-
-
-    FT_ZERO( &seg0 );
-    seg0.score = 32000;
-    seg0.flags = AF_EDGE_NORMAL;
-
-    major_dir   = (AF_Direction)FT_ABS( axis->major_dir );
-    segment_dir = major_dir;
-
-    axis->num_segments = 0;
-
-    /* set up (u,v) in each point */
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      AF_Point  point = hints->points;
-      AF_Point  limit = point + hints->num_points;
-
-
-      for ( ; point < limit; point++ )
-      {
-        point->u = point->fx;
-        point->v = point->fy;
-      }
-    }
-    else
-    {
-      AF_Point  point = hints->points;
-      AF_Point  limit = point + hints->num_points;
-
-
-      for ( ; point < limit; point++ )
-      {
-        point->u = point->fy;
-        point->v = point->fx;
-      }
-    }
-
-    /* do each contour separately */
-    for ( ; contour < contour_limit; contour++ )
-    {
-      AF_Point  point   =  contour[0];
-      AF_Point  start   =  point;
-      AF_Point  last    =  point->prev;
-
-
-      if ( point == last )  /* skip singletons -- just in case */
-        continue;
-
-      /* already on an edge ?, backtrack to find its start */
-      if ( FT_ABS( point->in_dir ) == major_dir )
-      {
-        point = point->prev;
-
-        while ( point->in_dir == start->in_dir )
-          point = point->prev;
-      }
-      else  /* otherwise, find first segment start, if any */
-      {
-        while ( FT_ABS( point->out_dir ) != major_dir )
-        {
-          point = point->next;
-
-          if ( point == start )
-            goto NextContour;
-        }
-      }
-
-      start = point;
-
-      for  (;;)
-      {
-        AF_Point  first;
-        FT_Pos    min_u, min_v, max_u, max_v;
-
-        /* we're at the start of a new segment */
-        FT_ASSERT( FT_ABS( point->out_dir ) == major_dir &&
-                           point->in_dir != point->out_dir );
-        first = point;
-
-        min_u = max_u = point->u;
-        min_v = max_v = point->v;
-
-        point = point->next;
-
-        while ( point->out_dir == first->out_dir )
-        {
-          point = point->next;
-
-          if ( point->u < min_u )
-            min_u = point->u;
-
-          if ( point->u > max_u )
-            max_u = point->u;
-        }
-
-        if ( point->v < min_v )
-          min_v = point->v;
-
-        if ( point->v > max_v )
-          max_v = point->v;
-
-        /* record new segment */
-        error = af_axis_hints_new_segment( axis, memory, &segment );
-        if ( error )
-          goto Exit;
-
-        segment[0]         = seg0;
-        segment->dir       = first->out_dir;
-        segment->first     = first;
-        segment->last      = point;
-        segment->pos       = (FT_Short)( ( min_u + max_u ) >> 1 );
-        segment->min_coord = (FT_Short) min_v;
-        segment->max_coord = (FT_Short) max_v;
-        segment->height    = (FT_Short)( max_v - min_v );
-
-        /* a segment is round if it doesn't have successive */
-        /* on-curve points.                                 */
-        {
-          AF_Point  pt   = first;
-          AF_Point  last = point;
-          FT_UInt   f0   = pt->flags & AF_FLAG_CONTROL;
-          FT_UInt   f1;
-
-
-          segment->flags &= ~AF_EDGE_ROUND;
-
-          for ( ; pt != last; f0 = f1 )
-          {
-            pt = pt->next;
-            f1 = pt->flags & AF_FLAG_CONTROL;
-
-            if ( !f0 && !f1 )
-              break;
-
-            if ( pt == last )
-              segment->flags |= AF_EDGE_ROUND;
-          }
-        }
-
-       /* this can happen in the case of a degenerate contour
-        * e.g. a 2-point vertical contour
-        */
-        if ( point == start )
-          break;
-
-        /* jump to the start of the next segment, if any */
-        while ( FT_ABS( point->out_dir ) != major_dir )
-        {
-          point = point->next;
-
-          if ( point == start )
-            goto NextContour;
-        }
-      }
-
-    NextContour:
-      ;
-    } /* contours */
-
-    /* now slightly increase the height of segments when this makes */
-    /* sense -- this is used to better detect and ignore serifs     */
-    {
-      AF_Segment  segments     = axis->segments;
-      AF_Segment  segments_end = segments + axis->num_segments;
-
-
-      for ( segment = segments; segment < segments_end; segment++ )
-      {
-        AF_Point  first   = segment->first;
-        AF_Point  last    = segment->last;
-        AF_Point  p;
-        FT_Pos    first_v = first->v;
-        FT_Pos    last_v  = last->v;
-
-
-        if ( first_v < last_v )
-        {
-          p = first->prev;
-          if ( p->v < first_v )
-            segment->height = (FT_Short)( segment->height +
-                                          ( ( first_v - p->v ) >> 1 ) );
-
-          p = last->next;
-          if ( p->v > last_v )
-            segment->height = (FT_Short)( segment->height +
-                                          ( ( p->v - last_v ) >> 1 ) );
-        }
-        else
-        {
-          p = first->prev;
-          if ( p->v > first_v )
-            segment->height = (FT_Short)( segment->height +
-                                          ( ( p->v - first_v ) >> 1 ) );
-
-          p = last->next;
-          if ( p->v < last_v )
-            segment->height = (FT_Short)( segment->height +
-                                          ( ( last_v - p->v ) >> 1 ) );
-        }
-      }
-    }
-
-#ifdef AF_SORT_SEGMENTS
-   /* place all segments with a negative direction to the start
-    * of the array, used to speed up segment linking later...
-    */
-    {
-      AF_Segment  segments = axis->segments;
-      FT_UInt     count    = axis->num_segments;
-      FT_UInt     ii, jj;
-
-      for ( ii = 0; ii < count; ii++ )
-      {
-        if ( segments[ii].dir > 0 )
-        {
-          for ( jj = ii + 1; jj < count; jj++ )
-          {
-            if ( segments[jj].dir < 0 )
-            {
-              AF_SegmentRec  tmp;
-
-
-              tmp          = segments[ii];
-              segments[ii] = segments[jj];
-              segments[jj] = tmp;
-
-              break;
-            }
-          }
-
-          if ( jj == count )
-            break;
-        }
-      }
-      axis->mid_segments = ii;
-    }
-#endif
-
-  Exit:
-    return error;
-  }
-
-
-  FT_LOCAL_DEF( void )
-  af_latin2_hints_link_segments( AF_GlyphHints  hints,
-                                 AF_Dimension   dim )
-  {
-    AF_AxisHints  axis          = &hints->axis[dim];
-    AF_Segment    segments      = axis->segments;
-    AF_Segment    segment_limit = segments + axis->num_segments;
-#ifdef AF_SORT_SEGMENTS
-    AF_Segment    segment_mid   = segments + axis->mid_segments;
-#endif
-    FT_Pos        len_threshold, len_score;
-    AF_Segment    seg1, seg2;
-
-
-    len_threshold = AF_LATIN_CONSTANT( hints->metrics, 8 );
-    if ( len_threshold == 0 )
-      len_threshold = 1;
-
-    len_score = AF_LATIN_CONSTANT( hints->metrics, 6000 );
-
-#ifdef AF_SORT_SEGMENTS
-    for ( seg1 = segments; seg1 < segment_mid; seg1++ )
-    {
-      if ( seg1->dir != axis->major_dir )
-        continue;
-
-      for ( seg2 = segment_mid; seg2 < segment_limit; seg2++ )
-#else
-    /* now compare each segment to the others */
-    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
-    {
-      if ( seg1->dir != axis->major_dir )
-        continue;
-
-      for ( seg2 = segments; seg2 < segment_limit; seg2++ )
-        if ( seg1->dir + seg2->dir == 0 && seg2->pos > seg1->pos )
-#endif
-        {
-          FT_Pos  pos1 = seg1->pos;
-          FT_Pos  pos2 = seg2->pos;
-          FT_Pos  dist = pos2 - pos1;
-
-
-          if ( dist < 0 )
-            continue;
-
-          {
-            FT_Pos  min = seg1->min_coord;
-            FT_Pos  max = seg1->max_coord;
-            FT_Pos  len, score;
-
-
-            if ( min < seg2->min_coord )
-              min = seg2->min_coord;
-
-            if ( max > seg2->max_coord )
-              max = seg2->max_coord;
-
-            len = max - min;
-            if ( len >= len_threshold )
-            {
-              score = dist + len_score / len;
-              if ( score < seg1->score )
-              {
-                seg1->score = score;
-                seg1->link  = seg2;
-              }
-
-              if ( score < seg2->score )
-              {
-                seg2->score = score;
-                seg2->link  = seg1;
-              }
-            }
-          }
-        }
-    }
-#if 0
-    }
-#endif
-
-    /* now, compute the `serif' segments */
-    for ( seg1 = segments; seg1 < segment_limit; seg1++ )
-    {
-      seg2 = seg1->link;
-
-      if ( seg2 )
-      {
-        if ( seg2->link != seg1 )
-        {
-          seg1->link  = NULL;
-          seg1->serif = seg2->link;
-        }
-      }
-    }
-  }
-
-
-  FT_LOCAL_DEF( FT_Error )
-  af_latin2_hints_compute_edges( AF_GlyphHints  hints,
-                                 AF_Dimension   dim )
-  {
-    AF_AxisHints  axis   = &hints->axis[dim];
-    FT_Error      error  = FT_Err_Ok;
-    FT_Memory     memory = hints->memory;
-    AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
-
-    AF_Segment    segments      = axis->segments;
-    AF_Segment    segment_limit = segments + axis->num_segments;
-    AF_Segment    seg;
-
-    AF_Direction  up_dir;
-    FT_Fixed      scale;
-    FT_Pos        edge_distance_threshold;
-    FT_Pos        segment_length_threshold;
-
-
-    axis->num_edges = 0;
-
-    scale = ( dim == AF_DIMENSION_HORZ ) ? hints->x_scale
-                                         : hints->y_scale;
-
-    up_dir = ( dim == AF_DIMENSION_HORZ ) ? AF_DIR_UP
-                                          : AF_DIR_RIGHT;
-
-    /*
-     * We want to ignore very small (mostly serif) segments, we do that
-     * by ignoring those that whose length is less than a given fraction
-     * of the standard width. If there is no standard width, we ignore
-     * those that are less than a given size in pixels
-     *
-     * also, unlink serif segments that are linked to segments farther
-     * than 50% of the standard width
-     */
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      if ( laxis->width_count > 0 )
-        segment_length_threshold = ( laxis->standard_width * 10 ) >> 4;
-      else
-        segment_length_threshold = FT_DivFix( 64, hints->y_scale );
-    }
-    else
-      segment_length_threshold = 0;
-
-    /**********************************************************************
-     *
-     * We will begin by generating a sorted table of edges for the
-     * current direction.  To do so, we simply scan each segment and try
-     * to find an edge in our table that corresponds to its position.
-     *
-     * If no edge is found, we create and insert a new edge in the
-     * sorted table.  Otherwise, we simply add the segment to the edge's
-     * list which will be processed in the second step to compute the
-     * edge's properties.
-     *
-     * Note that the edges table is sorted along the segment/edge
-     * position.
-     *
-     */
-
-    edge_distance_threshold = FT_MulFix( laxis->edge_distance_threshold,
-                                         scale );
-    if ( edge_distance_threshold > 64 / 4 )
-      edge_distance_threshold = 64 / 4;
-
-    edge_distance_threshold = FT_DivFix( edge_distance_threshold,
-                                         scale );
-
-    for ( seg = segments; seg < segment_limit; seg++ )
-    {
-      AF_Edge  found = NULL;
-      FT_Int   ee;
-
-
-      if ( seg->height < segment_length_threshold )
-        continue;
-
-      /* A special case for serif edges: If they are smaller than */
-      /* 1.5 pixels we ignore them.                               */
-      if ( seg->serif )
-      {
-        FT_Pos  dist = seg->serif->pos - seg->pos;
-
-
-        if ( dist < 0 )
-          dist = -dist;
-
-        if ( dist >= laxis->standard_width >> 1 )
-        {
-          /* unlink this serif, it is too distant from its reference stem */
-          seg->serif = NULL;
-        }
-        else if ( 2*seg->height < 3 * segment_length_threshold )
-          continue;
-      }
-
-      /* look for an edge corresponding to the segment */
-      for ( ee = 0; ee < axis->num_edges; ee++ )
-      {
-        AF_Edge  edge = axis->edges + ee;
-        FT_Pos   dist;
-
-
-        dist = seg->pos - edge->fpos;
-        if ( dist < 0 )
-          dist = -dist;
-
-        if ( dist < edge_distance_threshold && edge->dir == seg->dir )
-        {
-          found = edge;
-          break;
-        }
-      }
-
-      if ( !found )
-      {
-        AF_Edge   edge;
-
-
-        /* insert a new edge in the list and */
-        /* sort according to the position    */
-        error = af_axis_hints_new_edge( axis, seg->pos, seg->dir, 0,
-                                        memory, &edge );
-        if ( error )
-          goto Exit;
-
-        /* add the segment to the new edge's list */
-        FT_ZERO( edge );
-
-        edge->first    = seg;
-        edge->last     = seg;
-        edge->dir      = seg->dir;
-        edge->fpos     = seg->pos;
-        edge->opos     = FT_MulFix( seg->pos, scale );
-        edge->pos      = edge->opos;
-        seg->edge_next = seg;
-      }
-      else
-      {
-        /* if an edge was found, simply add the segment to the edge's */
-        /* list                                                       */
-        seg->edge_next         = found->first;
-        found->last->edge_next = seg;
-        found->last            = seg;
-      }
-    }
-
-
-    /**********************************************************************
-     *
-     * Good, we will now compute each edge's properties according to
-     * segments found on its position.  Basically, these are:
-     *
-     * - edge's main direction
-     * - stem edge, serif edge or both (which defaults to stem then)
-     * - rounded edge, straight or both (which defaults to straight)
-     * - link for edge
-     *
-     */
-
-    /* first of all, set the `edge' field in each segment -- this is */
-    /* required in order to compute edge links                       */
-
-    /*
-     * Note that removing this loop and setting the `edge' field of each
-     * segment directly in the code above slows down execution speed for
-     * some reasons on platforms like the Sun.
-     */
-    {
-      AF_Edge  edges      = axis->edges;
-      AF_Edge  edge_limit = edges + axis->num_edges;
-      AF_Edge  edge;
-
-
-      for ( edge = edges; edge < edge_limit; edge++ )
-      {
-        seg = edge->first;
-        if ( seg )
-          do
-          {
-            seg->edge = edge;
-            seg       = seg->edge_next;
-
-          } while ( seg != edge->first );
-      }
-
-      /* now, compute each edge properties */
-      for ( edge = edges; edge < edge_limit; edge++ )
-      {
-        FT_Int  is_round    = 0;  /* does it contain round segments?    */
-        FT_Int  is_straight = 0;  /* does it contain straight segments? */
-#if 0
-        FT_Pos  ups         = 0;  /* number of upwards segments         */
-        FT_Pos  downs       = 0;  /* number of downwards segments       */
-#endif
-
-
-        seg = edge->first;
-
-        do
-        {
-          FT_Bool  is_serif;
-
-
-          /* check for roundness of segment */
-          if ( seg->flags & AF_EDGE_ROUND )
-            is_round++;
-          else
-            is_straight++;
-
-#if 0
-          /* check for segment direction */
-          if ( seg->dir == up_dir )
-            ups   += seg->max_coord-seg->min_coord;
-          else
-            downs += seg->max_coord-seg->min_coord;
-#endif
-
-          /* check for links -- if seg->serif is set, then seg->link must */
-          /* be ignored                                                   */
-          is_serif = FT_BOOL( seg->serif               &&
-                              seg->serif->edge         &&
-                              seg->serif->edge != edge );
-
-          if ( ( seg->link && seg->link->edge ) || is_serif )
-          {
-            AF_Edge     edge2;
-            AF_Segment  seg2;
-
-
-            edge2 = edge->link;
-            seg2  = seg->link;
-
-            if ( is_serif )
-            {
-              seg2  = seg->serif;
-              edge2 = edge->serif;
-            }
-
-            if ( edge2 )
-            {
-              FT_Pos  edge_delta;
-              FT_Pos  seg_delta;
-
-
-              edge_delta = edge->fpos - edge2->fpos;
-              if ( edge_delta < 0 )
-                edge_delta = -edge_delta;
-
-              seg_delta = seg->pos - seg2->pos;
-              if ( seg_delta < 0 )
-                seg_delta = -seg_delta;
-
-              if ( seg_delta < edge_delta )
-                edge2 = seg2->edge;
-            }
-            else
-              edge2 = seg2->edge;
-
-            if ( is_serif )
-            {
-              edge->serif   = edge2;
-              edge2->flags |= AF_EDGE_SERIF;
-            }
-            else
-              edge->link  = edge2;
-          }
-
-          seg = seg->edge_next;
-
-        } while ( seg != edge->first );
-
-        /* set the round/straight flags */
-        edge->flags = AF_EDGE_NORMAL;
-
-        if ( is_round > 0 && is_round >= is_straight )
-          edge->flags |= AF_EDGE_ROUND;
-
-#if 0
-        /* set the edge's main direction */
-        edge->dir = AF_DIR_NONE;
-
-        if ( ups > downs )
-          edge->dir = (FT_Char)up_dir;
-
-        else if ( ups < downs )
-          edge->dir = (FT_Char)-up_dir;
-
-        else if ( ups == downs )
-          edge->dir = 0;  /* both up and down! */
-#endif
-
-        /* gets rid of serifs if link is set                */
-        /* XXX: This gets rid of many unpleasant artefacts! */
-        /*      Example: the `c' in cour.pfa at size 13     */
-
-        if ( edge->serif && edge->link )
-          edge->serif = NULL;
-      }
-    }
-
-  Exit:
-    return error;
-  }
-
-
-  FT_LOCAL_DEF( FT_Error )
-  af_latin2_hints_detect_features( AF_GlyphHints  hints,
-                                   AF_Dimension   dim )
-  {
-    FT_Error  error;
-
-
-    error = af_latin2_hints_compute_segments( hints, dim );
-    if ( !error )
-    {
-      af_latin2_hints_link_segments( hints, dim );
-
-      error = af_latin2_hints_compute_edges( hints, dim );
-    }
-    return error;
-  }
-
-
-  static void
-  af_latin2_hints_compute_blue_edges( AF_GlyphHints    hints,
-                                      AF_LatinMetrics  metrics )
-  {
-    AF_AxisHints  axis       = &hints->axis[AF_DIMENSION_VERT];
-    AF_Edge       edge       = axis->edges;
-    AF_Edge       edge_limit = edge + axis->num_edges;
-    AF_LatinAxis  latin      = &metrics->axis[AF_DIMENSION_VERT];
-    FT_Fixed      scale      = latin->scale;
-    FT_Pos        best_dist0;  /* initial threshold */
-
-
-    /* compute the initial threshold as a fraction of the EM size */
-    best_dist0 = FT_MulFix( metrics->units_per_em / 40, scale );
-
-    if ( best_dist0 > 64 / 2 )
-      best_dist0 = 64 / 2;
-
-    /* compute which blue zones are active, i.e. have their scaled */
-    /* size < 3/4 pixels                                           */
-
-    /* for each horizontal edge search the blue zone which is closest */
-    for ( ; edge < edge_limit; edge++ )
-    {
-      FT_Int    bb;
-      AF_Width  best_blue = NULL;
-      FT_Pos    best_dist = best_dist0;
-
-      for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
-      {
-        AF_LatinBlue  blue = latin->blues + bb;
-        FT_Bool       is_top_blue, is_major_dir;
-
-
-        /* skip inactive blue zones (i.e., those that are too small) */
-        if ( !( blue->flags & AF_LATIN_BLUE_ACTIVE ) )
-          continue;
-
-        /* if it is a top zone, check for right edges -- if it is a bottom */
-        /* zone, check for left edges                                      */
-        /*                                                                 */
-        /* of course, that's for TrueType                                  */
-        is_top_blue  = (FT_Byte)( ( blue->flags & AF_LATIN_BLUE_TOP ) != 0 );
-        is_major_dir = FT_BOOL( edge->dir == axis->major_dir );
-
-        /* if it is a top zone, the edge must be against the major    */
-        /* direction; if it is a bottom zone, it must be in the major */
-        /* direction                                                  */
-        if ( is_top_blue ^ is_major_dir )
-        {
-          FT_Pos     dist;
-          AF_Width   compare;
-
-
-          /* if it's a rounded edge, compare it to the overshoot position */
-          /* if it's a flat edge, compare it to the reference position    */
-          if ( edge->flags & AF_EDGE_ROUND )
-            compare = &blue->shoot;
-          else
-            compare = &blue->ref;
-
-          dist = edge->fpos - compare->org;
-          if ( dist < 0 )
-            dist = -dist;
-
-          dist = FT_MulFix( dist, scale );
-          if ( dist < best_dist )
-          {
-            best_dist = dist;
-            best_blue = compare;
-          }
-
-#if 0
-          /* now, compare it to the overshoot position if the edge is     */
-          /* rounded, and if the edge is over the reference position of a */
-          /* top zone, or under the reference position of a bottom zone   */
-          if ( edge->flags & AF_EDGE_ROUND && dist != 0 )
-          {
-            FT_Bool  is_under_ref = FT_BOOL( edge->fpos < blue->ref.org );
-
-
-            if ( is_top_blue ^ is_under_ref )
-            {
-              blue = latin->blues + bb;
-              dist = edge->fpos - blue->shoot.org;
-              if ( dist < 0 )
-                dist = -dist;
-
-              dist = FT_MulFix( dist, scale );
-              if ( dist < best_dist )
-              {
-                best_dist = dist;
-                best_blue = & blue->shoot;
-              }
-            }
-          }
-#endif
-        }
-      }
-
-      if ( best_blue )
-        edge->blue_edge = best_blue;
-    }
-  }
-
-
-  static FT_Error
-  af_latin2_hints_init( AF_GlyphHints    hints,
-                        AF_LatinMetrics  metrics )
-  {
-    FT_Render_Mode  mode;
-    FT_UInt32       scaler_flags, other_flags;
-    FT_Face         face = metrics->root.scaler.face;
-
-
-    af_glyph_hints_rescale( hints, (AF_StyleMetrics)metrics );
-
-    /*
-     * correct x_scale and y_scale if needed, since they may have
-     * been modified `af_latin2_metrics_scale_dim' above
-     */
-    hints->x_scale = metrics->axis[AF_DIMENSION_HORZ].scale;
-    hints->x_delta = metrics->axis[AF_DIMENSION_HORZ].delta;
-    hints->y_scale = metrics->axis[AF_DIMENSION_VERT].scale;
-    hints->y_delta = metrics->axis[AF_DIMENSION_VERT].delta;
-
-    /* compute flags depending on render mode, etc. */
-    mode = metrics->root.scaler.render_mode;
-
-#if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
-    if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
-      metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
-#endif
-
-    scaler_flags = hints->scaler_flags;
-    other_flags  = 0;
-
-    /*
-     * We snap the width of vertical stems for the monochrome and
-     * horizontal LCD rendering targets only.
-     */
-    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD )
-      other_flags |= AF_LATIN_HINTS_HORZ_SNAP;
-
-    /*
-     * We snap the width of horizontal stems for the monochrome and
-     * vertical LCD rendering targets only.
-     */
-    if ( mode == FT_RENDER_MODE_MONO || mode == FT_RENDER_MODE_LCD_V )
-      other_flags |= AF_LATIN_HINTS_VERT_SNAP;
-
-    /*
-     * We adjust stems to full pixels unless in `light' or `lcd' mode.
-     */
-    if ( mode != FT_RENDER_MODE_LIGHT && mode != FT_RENDER_MODE_LCD )
-      other_flags |= AF_LATIN_HINTS_STEM_ADJUST;
-
-    if ( mode == FT_RENDER_MODE_MONO )
-      other_flags |= AF_LATIN_HINTS_MONO;
-
-    /*
-     * In `light' or `lcd' mode we disable horizontal hinting completely.
-     * We also do it if the face is italic.
-     */
-    if ( mode == FT_RENDER_MODE_LIGHT || mode == FT_RENDER_MODE_LCD ||
-         ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0          )
-      scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
-
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-    /* get (global) warper flag */
-    if ( !metrics->root.globals->module->warping )
-      scaler_flags |= AF_SCALER_FLAG_NO_WARPER;
-#endif
-
-    hints->scaler_flags = scaler_flags;
-    hints->other_flags  = other_flags;
-
-    return 0;
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****        L A T I N   G L Y P H   G R I D - F I T T I N G        *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  /* snap a given width in scaled coordinates to one of the */
-  /* current standard widths                                */
-
-  static FT_Pos
-  af_latin2_snap_width( AF_Width  widths,
-                        FT_UInt   count,
-                        FT_Pos    width )
-  {
-    FT_UInt  n;
-    FT_Pos   best      = 64 + 32 + 2;
-    FT_Pos   reference = width;
-    FT_Pos   scaled;
-
-
-    for ( n = 0; n < count; n++ )
-    {
-      FT_Pos  w;
-      FT_Pos  dist;
-
-
-      w = widths[n].cur;
-      dist = width - w;
-      if ( dist < 0 )
-        dist = -dist;
-      if ( dist < best )
-      {
-        best      = dist;
-        reference = w;
-      }
-    }
-
-    scaled = FT_PIX_ROUND( reference );
-
-    if ( width >= reference )
-    {
-      if ( width < scaled + 48 )
-        width = reference;
-    }
-    else
-    {
-      if ( width > scaled - 48 )
-        width = reference;
-    }
-
-    return width;
-  }
-
-
-  /* compute the snapped width of a given stem */
-
-  static FT_Pos
-  af_latin2_compute_stem_width( AF_GlyphHints  hints,
-                                AF_Dimension   dim,
-                                FT_Pos         width,
-                                FT_UInt        base_flags,
-                                FT_UInt        stem_flags )
-  {
-    AF_LatinMetrics  metrics  = (AF_LatinMetrics) hints->metrics;
-    AF_LatinAxis     axis     = & metrics->axis[dim];
-    FT_Pos           dist     = width;
-    FT_Int           sign     = 0;
-    FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
-
-    FT_UNUSED( base_flags );
-
-
-    if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
-          axis->extra_light                      )
-      return width;
-
-    if ( dist < 0 )
-    {
-      dist = -width;
-      sign = 1;
-    }
-
-    if ( (  vertical && !AF_LATIN_HINTS_DO_VERT_SNAP( hints ) ) ||
-         ( !vertical && !AF_LATIN_HINTS_DO_HORZ_SNAP( hints ) ) )
-    {
-      /* smooth hinting process: very lightly quantize the stem width */
-
-      /* leave the widths of serifs alone */
-
-      if ( ( stem_flags & AF_EDGE_SERIF ) && vertical && ( dist < 3 * 64 ) )
-        goto Done_Width;
-
-#if 0
-      else if ( ( base_flags & AF_EDGE_ROUND ) )
-      {
-        if ( dist < 80 )
-          dist = 64;
-      }
-      else if ( dist < 56 )
-        dist = 56;
-#endif
-      if ( axis->width_count > 0 )
-      {
-        FT_Pos  delta;
-
-
-        /* compare to standard width */
-        if ( axis->width_count > 0 )
-        {
-          delta = dist - axis->widths[0].cur;
-
-          if ( delta < 0 )
-            delta = -delta;
-
-          if ( delta < 40 )
-          {
-            dist = axis->widths[0].cur;
-            if ( dist < 48 )
-              dist = 48;
-
-            goto Done_Width;
-          }
-        }
-
-        if ( dist < 3 * 64 )
-        {
-          delta  = dist & 63;
-          dist  &= -64;
-
-          if ( delta < 10 )
-            dist += delta;
-
-          else if ( delta < 32 )
-            dist += 10;
-
-          else if ( delta < 54 )
-            dist += 54;
-
-          else
-            dist += delta;
-        }
-        else
-          dist = ( dist + 32 ) & ~63;
-      }
-    }
-    else
-    {
-      /* strong hinting process: snap the stem width to integer pixels */
-      FT_Pos  org_dist = dist;
-
-
-      dist = af_latin2_snap_width( axis->widths, axis->width_count, dist );
-
-      if ( vertical )
-      {
-        /* in the case of vertical hinting, always round */
-        /* the stem heights to integer pixels            */
-
-        if ( dist >= 64 )
-          dist = ( dist + 16 ) & ~63;
-        else
-          dist = 64;
-      }
-      else
-      {
-        if ( AF_LATIN_HINTS_DO_MONO( hints ) )
-        {
-          /* monochrome horizontal hinting: snap widths to integer pixels */
-          /* with a different threshold                                   */
-
-          if ( dist < 64 )
-            dist = 64;
-          else
-            dist = ( dist + 32 ) & ~63;
-        }
-        else
-        {
-          /* for horizontal anti-aliased hinting, we adopt a more subtle */
-          /* approach: we strengthen small stems, round stems whose size */
-          /* is between 1 and 2 pixels to an integer, otherwise nothing  */
-
-          if ( dist < 48 )
-            dist = ( dist + 64 ) >> 1;
-
-          else if ( dist < 128 )
-          {
-            /* We only round to an integer width if the corresponding */
-            /* distortion is less than 1/4 pixel.  Otherwise this     */
-            /* makes everything worse since the diagonals, which are  */
-            /* not hinted, appear a lot bolder or thinner than the    */
-            /* vertical stems.                                        */
-
-            FT_Int  delta;
-
-
-            dist = ( dist + 22 ) & ~63;
-            delta = dist - org_dist;
-            if ( delta < 0 )
-              delta = -delta;
-
-            if ( delta >= 16 )
-            {
-              dist = org_dist;
-              if ( dist < 48 )
-                dist = ( dist + 64 ) >> 1;
-            }
-          }
-          else
-            /* round otherwise to prevent color fringes in LCD mode */
-            dist = ( dist + 32 ) & ~63;
-        }
-      }
-    }
-
-  Done_Width:
-    if ( sign )
-      dist = -dist;
-
-    return dist;
-  }
-
-
-  /* align one stem edge relative to the previous stem edge */
-
-  static void
-  af_latin2_align_linked_edge( AF_GlyphHints  hints,
-                               AF_Dimension   dim,
-                               AF_Edge        base_edge,
-                               AF_Edge        stem_edge )
-  {
-    FT_Pos  dist = stem_edge->opos - base_edge->opos;
-
-    FT_Pos  fitted_width = af_latin2_compute_stem_width( hints, dim, dist,
-                                                         base_edge->flags,
-                                                         stem_edge->flags );
-
-
-    stem_edge->pos = base_edge->pos + fitted_width;
-
-    FT_TRACE5(( "LINK: edge %d (opos=%.2f) linked to (%.2f), "
-                "dist was %.2f, now %.2f\n",
-                stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
-                stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
-  }
-
-
-  static void
-  af_latin2_align_serif_edge( AF_GlyphHints  hints,
-                              AF_Edge        base,
-                              AF_Edge        serif )
-  {
-    FT_UNUSED( hints );
-
-    serif->pos = base->pos + ( serif->opos - base->opos );
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /****                                                                 ****/
-  /****                    E D G E   H I N T I N G                      ****/
-  /****                                                                 ****/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-  static void
-  af_latin2_hint_edges( AF_GlyphHints  hints,
-                        AF_Dimension   dim )
-  {
-    AF_AxisHints  axis       = &hints->axis[dim];
-    AF_Edge       edges      = axis->edges;
-    AF_Edge       edge_limit = edges + axis->num_edges;
-    AF_Edge       edge;
-    AF_Edge       anchor     = NULL;
-    FT_Int        has_serifs = 0;
-    FT_Pos        anchor_drift = 0;
-
-
-
-    FT_TRACE5(( "==== hinting %s edges =====\n",
-                dim == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ));
-
-    /* we begin by aligning all stems relative to the blue zone */
-    /* if needed -- that's only for horizontal edges            */
-
-    if ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_BLUES( hints ) )
-    {
-      for ( edge = edges; edge < edge_limit; edge++ )
-      {
-        AF_Width  blue;
-        AF_Edge   edge1, edge2;
-
-
-        if ( edge->flags & AF_EDGE_DONE )
-          continue;
-
-        blue  = edge->blue_edge;
-        edge1 = NULL;
-        edge2 = edge->link;
-
-        if ( blue )
-        {
-          edge1 = edge;
-        }
-        else if ( edge2 && edge2->blue_edge )
-        {
-          blue  = edge2->blue_edge;
-          edge1 = edge2;
-          edge2 = edge;
-        }
-
-        if ( !edge1 )
-          continue;
-
-        FT_TRACE5(( "BLUE: edge %d (opos=%.2f) snapped to (%.2f), "
-                    "was (%.2f)\n",
-                    edge1-edges, edge1->opos / 64.0, blue->fit / 64.0,
-                    edge1->pos / 64.0 ));
-
-        edge1->pos    = blue->fit;
-        edge1->flags |= AF_EDGE_DONE;
-
-        if ( edge2 && !edge2->blue_edge )
-        {
-          af_latin2_align_linked_edge( hints, dim, edge1, edge2 );
-          edge2->flags |= AF_EDGE_DONE;
-        }
-
-        if ( !anchor )
-        {
-          anchor = edge;
-
-          anchor_drift = ( anchor->pos - anchor->opos );
-          if ( edge2 )
-            anchor_drift = ( anchor_drift +
-                             ( edge2->pos - edge2->opos ) ) >> 1;
-        }
-      }
-    }
-
-    /* now we will align all stem edges, trying to maintain the */
-    /* relative order of stems in the glyph                     */
-    for ( edge = edges; edge < edge_limit; edge++ )
-    {
-      AF_Edge  edge2;
-
-
-      if ( edge->flags & AF_EDGE_DONE )
-        continue;
-
-      /* skip all non-stem edges */
-      edge2 = edge->link;
-      if ( !edge2 )
-      {
-        has_serifs++;
-        continue;
-      }
-
-      /* now align the stem */
-
-      /* this should not happen, but it's better to be safe */
-      if ( edge2->blue_edge )
-      {
-        FT_TRACE5(( "ASSERTION FAILED for edge %d\n", edge2-edges ));
-
-        af_latin2_align_linked_edge( hints, dim, edge2, edge );
-        edge->flags |= AF_EDGE_DONE;
-        continue;
-      }
-
-      if ( !anchor )
-      {
-        FT_Pos  org_len, org_center, cur_len;
-        FT_Pos  cur_pos1, error1, error2, u_off, d_off;
-
-
-        org_len = edge2->opos - edge->opos;
-        cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
-                                                edge->flags,
-                                                edge2->flags );
-        if ( cur_len <= 64 )
-          u_off = d_off = 32;
-        else
-        {
-          u_off = 38;
-          d_off = 26;
-        }
-
-        if ( cur_len < 96 )
-        {
-          org_center = edge->opos + ( org_len >> 1 );
-
-          cur_pos1   = FT_PIX_ROUND( org_center );
-
-          error1 = org_center - ( cur_pos1 - u_off );
-          if ( error1 < 0 )
-            error1 = -error1;
-
-          error2 = org_center - ( cur_pos1 + d_off );
-          if ( error2 < 0 )
-            error2 = -error2;
-
-          if ( error1 < error2 )
-            cur_pos1 -= u_off;
-          else
-            cur_pos1 += d_off;
-
-          edge->pos  = cur_pos1 - cur_len / 2;
-          edge2->pos = edge->pos + cur_len;
-        }
-        else
-          edge->pos = FT_PIX_ROUND( edge->opos );
-
-        FT_TRACE5(( "ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
-                    " snapped to (%.2f) (%.2f)\n",
-                    edge-edges, edge->opos / 64.0,
-                    edge2-edges, edge2->opos / 64.0,
-                    edge->pos / 64.0, edge2->pos / 64.0 ));
-        anchor = edge;
-
-        edge->flags |= AF_EDGE_DONE;
-
-        af_latin2_align_linked_edge( hints, dim, edge, edge2 );
-
-        edge2->flags |= AF_EDGE_DONE;
-
-        anchor_drift = ( ( anchor->pos - anchor->opos ) +
-                         ( edge2->pos - edge2->opos ) ) >> 1;
-
-        FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
-      }
-      else
-      {
-        FT_Pos   org_pos, org_len, org_center, cur_center, cur_len;
-        FT_Pos   org_left, org_right;
-
-
-        org_pos    = edge->opos + anchor_drift;
-        org_len    = edge2->opos - edge->opos;
-        org_center = org_pos + ( org_len >> 1 );
-
-        cur_len = af_latin2_compute_stem_width( hints, dim, org_len,
-                                                edge->flags,
-                                                edge2->flags );
-
-        org_left  = org_pos + ( ( org_len - cur_len ) >> 1 );
-        org_right = org_pos + ( ( org_len + cur_len ) >> 1 );
-
-        FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
-                    org_left / 64.0, org_right / 64.0 ));
-        cur_center = org_center;
-
-        if ( edge2->flags & AF_EDGE_DONE )
-        {
-          FT_TRACE5(( "\n" ));
-          edge->pos = edge2->pos - cur_len;
-        }
-        else
-        {
-         /* we want to compare several displacement, and choose
-          * the one that increases fitness while minimizing
-          * distortion as well
-          */
-          FT_Pos   displacements[6], scores[6], org, fit, delta;
-          FT_UInt  count = 0;
-
-          /* note: don't even try to fit tiny stems */
-          if ( cur_len < 32 )
-          {
-            FT_TRACE5(( "tiny stem\n" ));
-            goto AlignStem;
-          }
-
-          /* if the span is within a single pixel, don't touch it */
-          if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) )
-          {
-            FT_TRACE5(( "single pixel stem\n" ));
-            goto AlignStem;
-          }
-
-          if ( cur_len <= 96 )
-          {
-           /* we want to avoid the absolute worst case which is
-            * when the left and right edges of the span each represent
-            * about 50% of the gray. we'd better want to change this
-            * to 25/75%, since this is much more pleasant to the eye with
-            * very acceptable distortion
-            */
-            FT_Pos  frac_left  = org_left  & 63;
-            FT_Pos  frac_right = org_right & 63;
-
-            if ( frac_left  >= 22 && frac_left  <= 42 &&
-                 frac_right >= 22 && frac_right <= 42 )
-            {
-              org = frac_left;
-              fit = ( org <= 32 ) ? 16 : 48;
-              delta = FT_ABS( fit - org );
-              displacements[count] = fit - org;
-              scores[count++]      = delta;
-              FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
-
-              org = frac_right;
-              fit = ( org <= 32 ) ? 16 : 48;
-              delta = FT_ABS( fit - org );
-              displacements[count] = fit - org;
-              scores[count++]     = delta;
-              FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
-            }
-          }
-
-          /* snapping the left edge to the grid */
-          org   = org_left;
-          fit   = FT_PIX_ROUND( org );
-          delta = FT_ABS( fit - org );
-          displacements[count] = fit - org;
-          scores[count++]      = delta;
-          FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
-
-          /* snapping the right edge to the grid */
-          org   = org_right;
-          fit   = FT_PIX_ROUND( org );
-          delta = FT_ABS( fit - org );
-          displacements[count] = fit - org;
-          scores[count++]      = delta;
-          FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
-
-          /* now find the best displacement */
-          {
-            FT_Pos  best_score = scores[0];
-            FT_Pos  best_disp  = displacements[0];
-            FT_UInt nn;
-
-            for ( nn = 1; nn < count; nn++ )
-            {
-              if ( scores[nn] < best_score )
-              {
-                best_score = scores[nn];
-                best_disp  = displacements[nn];
-              }
-            }
-
-            cur_center = org_center + best_disp;
-          }
-          FT_TRACE5(( "\n" ));
-        }
-
-      AlignStem:
-        edge->pos  = cur_center - ( cur_len >> 1 );
-        edge2->pos = edge->pos + cur_len;
-
-        FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
-                    " snapped to (%.2f) and (%.2f),"
-                    " org_len=%.2f cur_len=%.2f\n",
-                    edge-edges, edge->opos / 64.0,
-                    edge2-edges, edge2->opos / 64.0,
-                    edge->pos / 64.0, edge2->pos / 64.0,
-                    org_len / 64.0, cur_len / 64.0 ));
-
-        edge->flags  |= AF_EDGE_DONE;
-        edge2->flags |= AF_EDGE_DONE;
-
-        if ( edge > edges && edge->pos < edge[-1].pos )
-        {
-          FT_TRACE5(( "BOUND: %d (pos=%.2f) to (%.2f)\n",
-                      edge-edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
-          edge->pos = edge[-1].pos;
-        }
-      }
-    }
-
-    /* make sure that lowercase m's maintain their symmetry */
-
-    /* In general, lowercase m's have six vertical edges if they are sans */
-    /* serif, or twelve if they are with serifs.  This implementation is  */
-    /* based on that assumption, and seems to work very well with most    */
-    /* faces.  However, if for a certain face this assumption is not      */
-    /* true, the m is just rendered like before.  In addition, any stem   */
-    /* correction will only be applied to symmetrical glyphs (even if the */
-    /* glyph is not an m), so the potential for unwanted distortion is    */
-    /* relatively low.                                                    */
-
-    /* We don't handle horizontal edges since we can't easily assure that */
-    /* the third (lowest) stem aligns with the base line; it might end up */
-    /* one pixel higher or lower.                                         */
-
-#if 0
-    {
-      FT_Int  n_edges = edge_limit - edges;
-
-
-      if ( dim == AF_DIMENSION_HORZ && ( n_edges == 6 || n_edges == 12 ) )
-      {
-        AF_Edge  edge1, edge2, edge3;
-        FT_Pos   dist1, dist2, span, delta;
-
-
-        if ( n_edges == 6 )
-        {
-          edge1 = edges;
-          edge2 = edges + 2;
-          edge3 = edges + 4;
-        }
-        else
-        {
-          edge1 = edges + 1;
-          edge2 = edges + 5;
-          edge3 = edges + 9;
-        }
-
-        dist1 = edge2->opos - edge1->opos;
-        dist2 = edge3->opos - edge2->opos;
-
-        span = dist1 - dist2;
-        if ( span < 0 )
-          span = -span;
-
-        if ( span < 8 )
-        {
-          delta = edge3->pos - ( 2 * edge2->pos - edge1->pos );
-          edge3->pos -= delta;
-          if ( edge3->link )
-            edge3->link->pos -= delta;
-
-          /* move the serifs along with the stem */
-          if ( n_edges == 12 )
-          {
-            ( edges + 8 )->pos -= delta;
-            ( edges + 11 )->pos -= delta;
-          }
-
-          edge3->flags |= AF_EDGE_DONE;
-          if ( edge3->link )
-            edge3->link->flags |= AF_EDGE_DONE;
-        }
-      }
-    }
-#endif
-
-    if ( has_serifs || !anchor )
-    {
-      /*
-       * now hint the remaining edges (serifs and single) in order
-       * to complete our processing
-       */
-      for ( edge = edges; edge < edge_limit; edge++ )
-      {
-        FT_Pos  delta;
-
-
-        if ( edge->flags & AF_EDGE_DONE )
-          continue;
-
-        delta = 1000;
-
-        if ( edge->serif )
-        {
-          delta = edge->serif->opos - edge->opos;
-          if ( delta < 0 )
-            delta = -delta;
-        }
-
-        if ( delta < 64 + 16 )
-        {
-          af_latin2_align_serif_edge( hints, edge->serif, edge );
-          FT_TRACE5(( "SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
-                      " aligned to (%.2f)\n",
-                      edge-edges, edge->opos / 64.0,
-                      edge->serif - edges, edge->serif->opos / 64.0,
-                      edge->pos / 64.0 ));
-        }
-        else if ( !anchor )
-        {
-          FT_TRACE5(( "SERIF_ANCHOR: edge %d (opos=%.2f)"
-                      " snapped to (%.2f)\n",
-                      edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
-          edge->pos = FT_PIX_ROUND( edge->opos );
-          anchor    = edge;
-        }
-        else
-        {
-          AF_Edge  before, after;
-
-
-          for ( before = edge - 1; before >= edges; before-- )
-            if ( before->flags & AF_EDGE_DONE )
-              break;
-
-          for ( after = edge + 1; after < edge_limit; after++ )
-            if ( after->flags & AF_EDGE_DONE )
-              break;
-
-          if ( before >= edges && before < edge   &&
-               after < edge_limit && after > edge )
-          {
-            if ( after->opos == before->opos )
-              edge->pos = before->pos;
-            else
-              edge->pos = before->pos +
-                          FT_MulDiv( edge->opos - before->opos,
-                                     after->pos - before->pos,
-                                     after->opos - before->opos );
-            FT_TRACE5(( "SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
-                        " from %d (opos=%.2f)\n",
-                        edge-edges, edge->opos / 64.0, edge->pos / 64.0,
-                        before - edges, before->opos / 64.0 ));
-          }
-          else
-          {
-            edge->pos = anchor->pos +
-                        ( ( edge->opos - anchor->opos + 16 ) & ~31 );
-
-            FT_TRACE5(( "SERIF_LINK2: edge %d (opos=%.2f)"
-                        " snapped to (%.2f)\n",
-                        edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
-          }
-        }
-
-        edge->flags |= AF_EDGE_DONE;
-
-        if ( edge > edges && edge->pos < edge[-1].pos )
-          edge->pos = edge[-1].pos;
-
-        if ( edge + 1 < edge_limit        &&
-             edge[1].flags & AF_EDGE_DONE &&
-             edge->pos > edge[1].pos      )
-          edge->pos = edge[1].pos;
-      }
-    }
-  }
-
-
-  static FT_Error
-  af_latin2_hints_apply( FT_UInt          glyph_index,
-                         AF_GlyphHints    hints,
-                         FT_Outline*      outline,
-                         AF_LatinMetrics  metrics )
-  {
-    FT_Error  error;
-    int       dim;
-
-    FT_UNUSED( glyph_index );
-
-
-    error = af_glyph_hints_reload( hints, outline );
-    if ( error )
-      goto Exit;
-
-    /* analyze glyph outline */
-    if ( AF_HINTS_DO_HORIZONTAL( hints ) )
-    {
-      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_HORZ );
-      if ( error )
-        goto Exit;
-    }
-
-    if ( AF_HINTS_DO_VERTICAL( hints ) )
-    {
-      error = af_latin2_hints_detect_features( hints, AF_DIMENSION_VERT );
-      if ( error )
-        goto Exit;
-
-      af_latin2_hints_compute_blue_edges( hints, metrics );
-    }
-
-    /* grid-fit the outline */
-    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
-    {
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-      if ( dim == AF_DIMENSION_HORZ                                  &&
-           metrics->root.scaler.render_mode == FT_RENDER_MODE_NORMAL &&
-           AF_HINTS_DO_WARP( hints )                                 )
-      {
-        AF_WarperRec  warper;
-        FT_Fixed      scale;
-        FT_Pos        delta;
-
-
-        af_warper_compute( &warper, hints, dim, &scale, &delta );
-        af_glyph_hints_scale_dim( hints, dim, scale, delta );
-        continue;
-      }
-#endif /* AF_CONFIG_OPTION_USE_WARPER */
-
-      if ( ( dim == AF_DIMENSION_HORZ && AF_HINTS_DO_HORIZONTAL( hints ) ) ||
-           ( dim == AF_DIMENSION_VERT && AF_HINTS_DO_VERTICAL( hints ) )   )
-      {
-        af_latin2_hint_edges( hints, (AF_Dimension)dim );
-        af_glyph_hints_align_edge_points( hints, (AF_Dimension)dim );
-        af_glyph_hints_align_strong_points( hints, (AF_Dimension)dim );
-        af_glyph_hints_align_weak_points( hints, (AF_Dimension)dim );
-      }
-    }
-    af_glyph_hints_save( hints, outline );
-
-  Exit:
-    return error;
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****              L A T I N   S C R I P T   C L A S S              *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-  AF_DEFINE_WRITING_SYSTEM_CLASS(
-    af_latin2_writing_system_class,
-
-    AF_WRITING_SYSTEM_LATIN2,
-
-    sizeof ( AF_LatinMetricsRec ),
-
-    (AF_WritingSystem_InitMetricsFunc) af_latin2_metrics_init,        /* style_metrics_init    */
-    (AF_WritingSystem_ScaleMetricsFunc)af_latin2_metrics_scale,       /* style_metrics_scale   */
-    (AF_WritingSystem_DoneMetricsFunc) NULL,                          /* style_metrics_done    */
-    (AF_WritingSystem_GetStdWidthsFunc)af_latin2_get_standard_widths, /* style_metrics_getstdw */
-
-    (AF_WritingSystem_InitHintsFunc)   af_latin2_hints_init,          /* style_hints_init      */
-    (AF_WritingSystem_ApplyHintsFunc)  af_latin2_hints_apply          /* style_hints_apply     */
-  )
-
-#else /* !FT_OPTION_AUTOFIT2 */
-
-  /* ANSI C doesn't like empty source files */
-  typedef int  _af_latin2_dummy;
-
-#endif /* !FT_OPTION_AUTOFIT2 */
-
-
-/* END */
diff --git a/src/autofit/aflatin2.h b/src/autofit/aflatin2.h
deleted file mode 100644
index c2aebc4..0000000
--- a/src/autofit/aflatin2.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* ATTENTION: This file doesn't compile.  It is only here as a reference */
-/*            of an alternative latin hinting algorithm that was always  */
-/*            marked as experimental.                                    */
-
-
-/****************************************************************************
- *
- * aflatin2.h
- *
- *   Auto-fitter hinting routines for latin writing system
- *   (specification).
- *
- * Copyright (C) 2003-2020 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used,
- * modified, and distributed under the terms of the FreeType project
- * license, LICENSE.TXT.  By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- */
-
-
-#ifndef AFLATIN2_H_
-#define AFLATIN2_H_
-
-#include "afhints.h"
-
-
-FT_BEGIN_HEADER
-
-
-  /* the `latin' writing system */
-
-  AF_DECLARE_WRITING_SYSTEM_CLASS( af_latin2_writing_system_class )
-
-
-/* */
-
-FT_END_HEADER
-
-#endif /* AFLATIN_H_ */
-
-
-/* END */
diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index c35d85c..a06d49a 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter glyph loading routines (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -105,7 +105,6 @@
                               globals->stem_darkening_for_ppem;
 
     FT_Fixed  em_size  = af_intToFixed( face->units_per_EM );
-    FT_Fixed  em_ratio = FT_DivFix( af_intToFixed( 1000 ), em_size );
 
     FT_Matrix  scale_down_matrix = { 0x10000L, 0, 0, 0x10000L };
 
@@ -142,12 +141,11 @@
 
 
       darken_by_font_units_x =
-        af_intToFixed( af_loader_compute_darkening( loader,
-                                                    face,
-                                                    stdVW ) );
-      darken_x = FT_DivFix( FT_MulFix( darken_by_font_units_x,
-                                       size_metrics->x_scale ),
-                            em_ratio );
+         af_loader_compute_darkening( loader,
+                                      face,
+                                      stdVW ) ;
+      darken_x = FT_MulFix( darken_by_font_units_x,
+                            size_metrics->x_scale );
 
       globals->standard_vertical_width = stdVW;
       globals->stem_darkening_for_ppem = size_metrics->x_ppem;
@@ -161,12 +159,11 @@
 
 
       darken_by_font_units_y =
-        af_intToFixed( af_loader_compute_darkening( loader,
-                                                    face,
-                                                    stdHW ) );
-      darken_y = FT_DivFix( FT_MulFix( darken_by_font_units_y,
-                                       size_metrics->y_scale ),
-                            em_ratio );
+         af_loader_compute_darkening( loader,
+                                      face,
+                                      stdHW ) ;
+      darken_y = FT_MulFix( darken_by_font_units_y,
+                            size_metrics->y_scale );
 
       globals->standard_horizontal_width = stdHW;
       globals->stem_darkening_for_ppem   = size_metrics->x_ppem;
@@ -300,12 +297,6 @@
     if ( error )
       goto Exit;
 
-#ifdef FT_OPTION_AUTOFIT2
-    /* XXX: undocumented hook to activate the latin2 writing system. */
-    if ( load_flags & ( 1UL << 20 ) )
-      style_options = AF_STYLE_LTN2_DFLT;
-#endif
-
     /*
      * Glyphs (really code points) are assigned to scripts.  Script
      * analysis is done lazily: For each glyph that passes through here,
@@ -482,8 +473,8 @@
           FT_Pos  pp2x = loader->pp2.x;
 
 
-          loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
-          loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
+          loader->pp1.x = FT_PIX_ROUND( pp1x );
+          loader->pp2.x = FT_PIX_ROUND( pp2x );
 
           slot->lsb_delta = loader->pp1.x - pp1x;
           slot->rsb_delta = loader->pp2.x - pp2x;
@@ -594,7 +585,7 @@
    *
    * XXX: Currently a crude adaption of the original algorithm.  Do better?
    */
-  FT_LOCAL_DEF( FT_Int32 )
+  FT_LOCAL_DEF( FT_Fixed )
   af_loader_compute_darkening( AF_Loader  loader,
                                FT_Face    face,
                                FT_Pos     standard_width )
@@ -713,7 +704,7 @@
     }
 
     /* Convert darken_amount from per 1000 em to true character space. */
-    return af_fixedToInt( FT_DivFix( darken_amount, em_ratio ) );
+    return FT_DivFix( darken_amount, em_ratio );
   }
 
 
diff --git a/src/autofit/afloader.h b/src/autofit/afloader.h
index 9728237..b4936a8 100644
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter glyph loading routines (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -75,7 +75,7 @@
                         FT_UInt    gindex,
                         FT_Int32   load_flags );
 
-  FT_LOCAL_DEF( FT_Int32 )
+  FT_LOCAL_DEF( FT_Fixed )
   af_loader_compute_darkening( AF_Loader  loader,
                                FT_Face    face,
                                FT_Pos     standard_width );
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index e164944..76f9b37 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module implementation (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -48,7 +48,7 @@
   int  _af_debug_disable_blue_hints;
 
   /* we use a global object instead of a local one for debugging */
-  AF_GlyphHintsRec  _af_debug_hints_rec[1];
+  static AF_GlyphHintsRec  _af_debug_hints_rec[1];
 
   void*  _af_debug_hints = _af_debug_hints_rec;
 #endif
@@ -148,7 +148,7 @@
 
       if ( !af_style_classes[ss] )
       {
-        FT_TRACE0(( "af_property_set: Invalid value %d for property `%s'\n",
+        FT_TRACE2(( "af_property_set: Invalid value %d for property `%s'\n",
                     *fallback_script, property_name ));
         return FT_THROW( Invalid_Argument );
       }
@@ -190,35 +190,6 @@
 
       return error;
     }
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-    else if ( !ft_strcmp( property_name, "warping" ) )
-    {
-#ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
-      if ( value_is_string )
-      {
-        const char*  s = (const char*)value;
-        long         w = ft_strtol( s, NULL, 10 );
-
-
-        if ( w == 0 )
-          module->warping = 0;
-        else if ( w == 1 )
-          module->warping = 1;
-        else
-          return FT_THROW( Invalid_Argument );
-      }
-      else
-#endif
-      {
-        FT_Bool*  warping = (FT_Bool*)value;
-
-
-        module->warping = *warping;
-      }
-
-      return error;
-    }
-#endif /* AF_CONFIG_OPTION_USE_WARPER */
     else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
     {
       FT_Int*  darken_params;
@@ -307,7 +278,7 @@
       return error;
     }
 
-    FT_TRACE0(( "af_property_set: missing property `%s'\n",
+    FT_TRACE2(( "af_property_set: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
   }
@@ -322,9 +293,6 @@
     AF_Module  module         = (AF_Module)ft_module;
     FT_UInt    fallback_style = module->fallback_style;
     FT_UInt    default_script = module->default_script;
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-    FT_Bool    warping        = module->warping;
-#endif
 
 
     if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
@@ -371,17 +339,6 @@
 
       return error;
     }
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-    else if ( !ft_strcmp( property_name, "warping" ) )
-    {
-      FT_Bool*  val = (FT_Bool*)value;
-
-
-      *val = warping;
-
-      return error;
-    }
-#endif /* AF_CONFIG_OPTION_USE_WARPER */
     else if ( !ft_strcmp( property_name, "darkening-parameters" ) )
     {
       FT_Int*  darken_params = module->darken_params;
@@ -410,7 +367,7 @@
       return error;
     }
 
-    FT_TRACE0(( "af_property_get: missing property `%s'\n",
+    FT_TRACE2(( "af_property_get: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
   }
@@ -447,9 +404,6 @@
 
     module->fallback_style    = AF_STYLE_FALLBACK;
     module->default_script    = AF_SCRIPT_DEFAULT;
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-    module->warping           = 0;
-#endif
     module->no_stem_darkening = TRUE;
 
     module->darken_params[0]  = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h
index e8fe4a9..c5bd468 100644
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module implementation (specification).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -37,9 +37,6 @@
 
     FT_UInt       fallback_style;
     FT_UInt       default_script;
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-    FT_Bool       warping;
-#endif
     FT_Bool       no_stem_darkening;
     FT_Int        darken_params[8];
 
diff --git a/src/autofit/afranges.c b/src/autofit/afranges.c
index c8ebf5e..e06f182 100644
--- a/src/autofit/afranges.c
+++ b/src/autofit/afranges.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter Unicode script ranges (body).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afranges.h b/src/autofit/afranges.h
index c2ffda4..841d630 100644
--- a/src/autofit/afranges.h
+++ b/src/autofit/afranges.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter Unicode script ranges (specification).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afscript.h b/src/autofit/afscript.h
index 4cf9cc1..af78d57 100644
--- a/src/autofit/afscript.h
+++ b/src/autofit/afscript.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter scripts (specification only).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afshaper.c b/src/autofit/afshaper.c
index bbf7b6b..5d07893 100644
--- a/src/autofit/afshaper.c
+++ b/src/autofit/afshaper.c
@@ -4,7 +4,7 @@
  *
  *   HarfBuzz interface for accessing OpenType features (body).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -132,13 +132,24 @@
     /* Convert a HarfBuzz script tag into the corresponding OpenType */
     /* tag or tags -- some Indic scripts like Devanagari have an old */
     /* and a new set of features.                                    */
-    hb_ot_tags_from_script( script,
-                            &script_tags[0],
-                            &script_tags[1] );
+    {
+      unsigned int  tags_count = 3;
+      hb_tag_t      tags[3];
 
-    /* `hb_ot_tags_from_script' usually returns HB_OT_TAG_DEFAULT_SCRIPT */
-    /* as the second tag.  We change that to HB_TAG_NONE except for the  */
-    /* default script.                                                   */
+
+      hb_ot_tags_from_script_and_language( script,
+                                           HB_LANGUAGE_INVALID,
+                                           &tags_count,
+                                           tags,
+                                           NULL,
+                                           NULL );
+      script_tags[0] = tags_count > 0 ? tags[0] : HB_TAG_NONE;
+      script_tags[1] = tags_count > 1 ? tags[1] : HB_TAG_NONE;
+      script_tags[2] = tags_count > 2 ? tags[2] : HB_TAG_NONE;
+    }
+
+    /* If the second tag is HB_OT_TAG_DEFAULT_SCRIPT, change that to     */
+    /* HB_TAG_NONE except for the default script.                        */
     if ( default_script )
     {
       if ( script_tags[0] == HB_TAG_NONE )
@@ -157,9 +168,6 @@
       /* HarfBuzz maps them to `DFLT', which we don't want to handle here */
       if ( script_tags[0] == HB_OT_TAG_DEFAULT_SCRIPT )
         goto Exit;
-
-      if ( script_tags[1] == HB_OT_TAG_DEFAULT_SCRIPT )
-        script_tags[1] = HB_TAG_NONE;
     }
 
     gsub_lookups = hb_set_create();
@@ -173,9 +181,9 @@
     if ( hb_set_is_empty( gsub_lookups ) )
       goto Exit; /* nothing to do */
 
-    FT_TRACE4(( "GSUB lookups (style `%s'):\n"
-                " ",
+    FT_TRACE4(( "GSUB lookups (style `%s'):\n",
                 af_style_names[style_class->style] ));
+    FT_TRACE4(( " " ));
 
 #ifdef FT_DEBUG_LEVEL_TRACE
     count = 0;
@@ -202,12 +210,13 @@
 #ifdef FT_DEBUG_LEVEL_TRACE
     if ( !count )
       FT_TRACE4(( " (none)" ));
-    FT_TRACE4(( "\n\n" ));
+    FT_TRACE4(( "\n" ));
+    FT_TRACE4(( "\n" ));
 #endif
 
-    FT_TRACE4(( "GPOS lookups (style `%s'):\n"
-                " ",
+    FT_TRACE4(( "GPOS lookups (style `%s'):\n",
                 af_style_names[style_class->style] ));
+    FT_TRACE4(( " " ));
 
     gpos_lookups = hb_set_create();
     hb_ot_layout_collect_lookups( face,
@@ -242,7 +251,8 @@
 #ifdef FT_DEBUG_LEVEL_TRACE
     if ( !count )
       FT_TRACE4(( " (none)" ));
-    FT_TRACE4(( "\n\n" ));
+    FT_TRACE4(( "\n" ));
+    FT_TRACE4(( "\n" ));
 #endif
 
     /*
@@ -353,8 +363,10 @@
     {
 #ifdef FT_DEBUG_LEVEL_TRACE
       if ( !( count % 10 ) )
-        FT_TRACE4(( "\n"
-                    "   " ));
+      {
+        FT_TRACE4(( "\n" ));
+        FT_TRACE4(( "   " ));
+      }
 
       FT_TRACE4(( " %d", idx ));
       count++;
@@ -376,9 +388,12 @@
 
 #ifdef FT_DEBUG_LEVEL_TRACE
     if ( !count )
-      FT_TRACE4(( "\n"
-                  "    (none)" ));
-    FT_TRACE4(( "\n\n" ));
+    {
+      FT_TRACE4(( "\n" ));
+      FT_TRACE4(( "    (none)" ));
+    }
+    FT_TRACE4(( "\n" ));
+    FT_TRACE4(( "\n" ));
 #endif
 
   Exit:
diff --git a/src/autofit/afshaper.h b/src/autofit/afshaper.h
index 138c27b..cf3f813 100644
--- a/src/autofit/afshaper.h
+++ b/src/autofit/afshaper.h
@@ -4,7 +4,7 @@
  *
  *   HarfBuzz interface for accessing OpenType features (specification).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/autofit/afstyles.h b/src/autofit/afstyles.h
index 9113ec4..64c808c 100644
--- a/src/autofit/afstyles.h
+++ b/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter styles (specification only).
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -299,15 +299,6 @@
          AF_BLUE_STRINGSET_LATP,
          AF_COVERAGE_DEFAULT )
 
-#ifdef FT_OPTION_AUTOFIT2
-  STYLE( ltn2_dflt, LTN2_DFLT,
-         "Latin 2 default style",
-         AF_WRITING_SYSTEM_LATIN2,
-         AF_SCRIPT_LATN,
-         AF_BLUE_STRINGSET_LATN,
-         AF_COVERAGE_DEFAULT )
-#endif
-
   STYLE( lisu_dflt, LISU_DFLT,
          "Lisu default style",
          AF_WRITING_SYSTEM_LATIN,
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 5f040c6..1d792b9 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter types (specification only).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -92,63 +92,6 @@
                                FT_Pos    threshold );
 
 
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                   A N G L E   T Y P E S                       *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  /*
-   * The auto-fitter doesn't need a very high angular accuracy;
-   * this allows us to speed up some computations considerably with a
-   * light Cordic algorithm (see afangles.c).
-   */
-
-  typedef FT_Int  AF_Angle;
-
-
-#define AF_ANGLE_PI   256
-#define AF_ANGLE_2PI  ( AF_ANGLE_PI * 2 )
-#define AF_ANGLE_PI2  ( AF_ANGLE_PI / 2 )
-#define AF_ANGLE_PI4  ( AF_ANGLE_PI / 4 )
-
-
-#if 0
-  /*
-   * compute the angle of a given 2-D vector
-   */
-  FT_LOCAL( AF_Angle )
-  af_angle_atan( FT_Pos  dx,
-                 FT_Pos  dy );
-
-
-  /*
-   * compute `angle2 - angle1'; the result is always within
-   * the range [-AF_ANGLE_PI .. AF_ANGLE_PI - 1]
-   */
-  FT_LOCAL( AF_Angle )
-  af_angle_diff( AF_Angle  angle1,
-                 AF_Angle  angle2 );
-#endif /* 0 */
-
-
-#define AF_ANGLE_DIFF( result, angle1, angle2 ) \
-  FT_BEGIN_STMNT                                \
-    AF_Angle  _delta = (angle2) - (angle1);     \
-                                                \
-                                                \
-    while ( _delta <= -AF_ANGLE_PI )            \
-      _delta += AF_ANGLE_2PI;                   \
-                                                \
-    while ( _delta > AF_ANGLE_PI )              \
-      _delta -= AF_ANGLE_2PI;                   \
-                                                \
-    result = _delta;                            \
-  FT_END_STMNT
-
-
   /*
    * opaque handle to glyph-specific hints -- see `afhints.h' for more
    * details
@@ -172,7 +115,6 @@
 #define AF_SCALER_FLAG_NO_HORIZONTAL  1U /* disable horizontal hinting */
 #define AF_SCALER_FLAG_NO_VERTICAL    2U /* disable vertical hinting   */
 #define AF_SCALER_FLAG_NO_ADVANCE     4U /* disable advance hinting    */
-#define AF_SCALER_FLAG_NO_WARPER      8U /* disable warper             */
 
 
   typedef struct  AF_ScalerRec_
@@ -256,7 +198,6 @@
    *   outline according to the results of the glyph analyzer.
    */
 
-#define AFWRTSYS_H_  /* don't load header files */
 #undef  WRITING_SYSTEM
 #define WRITING_SYSTEM( ws, WS )    \
           AF_WRITING_SYSTEM_ ## WS,
@@ -265,14 +206,12 @@
   typedef enum  AF_WritingSystem_
   {
 
-#include "afwrtsys.h"
+#include "afws-iter.h"
 
     AF_WRITING_SYSTEM_MAX   /* do not remove */
 
   } AF_WritingSystem;
 
-#undef  AFWRTSYS_H_
-
 
   typedef struct  AF_WritingSystemClassRec_
   {
diff --git a/src/autofit/afwarp.c b/src/autofit/afwarp.c
deleted file mode 100644
index 808280d..0000000
--- a/src/autofit/afwarp.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/****************************************************************************
- *
- * afwarp.c
- *
- *   Auto-fitter warping algorithm (body).
- *
- * Copyright (C) 2006-2020 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used,
- * modified, and distributed under the terms of the FreeType project
- * license, LICENSE.TXT.  By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- */
-
-
-  /*
-   * The idea of the warping code is to slightly scale and shift a glyph
-   * within a single dimension so that as much of its segments are aligned
-   * (more or less) on the grid.  To find out the optimal scaling and
-   * shifting value, various parameter combinations are tried and scored.
-   */
-
-#include "afwarp.h"
-
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-
-  /**************************************************************************
-   *
-   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
-   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
-   * messages during execution.
-   */
-#undef  FT_COMPONENT
-#define FT_COMPONENT  afwarp
-
-
-  /* The weights cover the range 0/64 - 63/64 of a pixel.  Obviously, */
-  /* values around a half pixel (which means exactly between two grid */
-  /* lines) gets the worst weight.                                    */
-#if 1
-  static const AF_WarpScore
-  af_warper_weights[64] =
-  {
-    35, 32, 30, 25, 20, 15, 12, 10,  5,  1,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0, -1, -2, -5, -8,-10,-10,-20,-20,-30,-30,
-
-   -30,-30,-20,-20,-10,-10, -8, -5, -2, -1,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  1,  5, 10, 12, 15, 20, 25, 30, 32,
-  };
-#else
-  static const AF_WarpScore
-  af_warper_weights[64] =
-  {
-    30, 20, 10,  5,  4,  4,  3,  2,  1,  0,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0, -1, -2, -2, -5, -5,-10,-10,-15,-20,
-
-   -20,-15,-15,-10,-10, -5, -5, -2, -2, -1,  0,  0,  0,  0,  0,  0,
-     0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  3,  4,  4,  5, 10, 20,
-  };
-#endif
-
-
-  /* Score segments for a given `scale' and `delta' in the range */
-  /* `xx1' to `xx2', and store the best result in `warper'.  If  */
-  /* the new best score is equal to the old one, prefer the      */
-  /* value with a smaller distortion (around `base_distort').    */
-
-  static void
-  af_warper_compute_line_best( AF_Warper     warper,
-                               FT_Fixed      scale,
-                               FT_Pos        delta,
-                               FT_Pos        xx1,
-                               FT_Pos        xx2,
-                               AF_WarpScore  base_distort,
-                               AF_Segment    segments,
-                               FT_Int        num_segments )
-  {
-    FT_Int        idx_min, idx_max, idx0;
-    FT_Int        nn;
-    AF_WarpScore  scores[65];
-
-
-    for ( nn = 0; nn < 65; nn++ )
-      scores[nn] = 0;
-
-    idx0 = xx1 - warper->t1;
-
-    /* compute minimum and maximum indices */
-    {
-      FT_Pos  xx1min = warper->x1min;
-      FT_Pos  xx1max = warper->x1max;
-      FT_Pos  w      = xx2 - xx1;
-
-
-      if ( xx1min + w < warper->x2min )
-        xx1min = warper->x2min - w;
-
-      if ( xx1max + w > warper->x2max )
-        xx1max = warper->x2max - w;
-
-      idx_min = xx1min - warper->t1;
-      idx_max = xx1max - warper->t1;
-
-      if ( idx_min < 0 || idx_min > idx_max || idx_max > 64 )
-      {
-        FT_TRACE5(( "invalid indices:\n"
-                    "  min=%d max=%d, xx1=%ld xx2=%ld,\n"
-                    "  x1min=%ld x1max=%ld, x2min=%ld x2max=%ld\n",
-                    idx_min, idx_max, xx1, xx2,
-                    warper->x1min, warper->x1max,
-                    warper->x2min, warper->x2max ));
-        return;
-      }
-    }
-
-    for ( nn = 0; nn < num_segments; nn++ )
-    {
-      FT_Pos  len = segments[nn].max_coord - segments[nn].min_coord;
-      FT_Pos  y0  = FT_MulFix( segments[nn].pos, scale ) + delta;
-      FT_Pos  y   = y0 + ( idx_min - idx0 );
-      FT_Int  idx;
-
-
-      /* score the length of the segments for the given range */
-      for ( idx = idx_min; idx <= idx_max; idx++, y++ )
-        scores[idx] += af_warper_weights[y & 63] * len;
-    }
-
-    /* find best score */
-    {
-      FT_Int  idx;
-
-
-      for ( idx = idx_min; idx <= idx_max; idx++ )
-      {
-        AF_WarpScore  score = scores[idx];
-        AF_WarpScore  distort = base_distort + ( idx - idx0 );
-
-
-        if ( score > warper->best_score         ||
-             ( score == warper->best_score    &&
-               distort < warper->best_distort ) )
-        {
-          warper->best_score   = score;
-          warper->best_distort = distort;
-          warper->best_scale   = scale;
-          warper->best_delta   = delta + ( idx - idx0 );
-        }
-      }
-    }
-  }
-
-
-  /* Compute optimal scaling and delta values for a given glyph and */
-  /* dimension.                                                     */
-
-  FT_LOCAL_DEF( void )
-  af_warper_compute( AF_Warper      warper,
-                     AF_GlyphHints  hints,
-                     AF_Dimension   dim,
-                     FT_Fixed      *a_scale,
-                     FT_Pos        *a_delta )
-  {
-    AF_AxisHints  axis;
-    AF_Point      points;
-
-    FT_Fixed      org_scale;
-    FT_Pos        org_delta;
-
-    FT_Int        nn, num_points, num_segments;
-    FT_Int        X1, X2;
-    FT_Int        w;
-
-    AF_WarpScore  base_distort;
-    AF_Segment    segments;
-
-
-    /* get original scaling transformation */
-    if ( dim == AF_DIMENSION_VERT )
-    {
-      org_scale = hints->y_scale;
-      org_delta = hints->y_delta;
-    }
-    else
-    {
-      org_scale = hints->x_scale;
-      org_delta = hints->x_delta;
-    }
-
-    warper->best_scale   = org_scale;
-    warper->best_delta   = org_delta;
-    warper->best_score   = FT_INT_MIN;
-    warper->best_distort = 0;
-
-    axis         = &hints->axis[dim];
-    segments     = axis->segments;
-    num_segments = axis->num_segments;
-    points       = hints->points;
-    num_points   = hints->num_points;
-
-    *a_scale = org_scale;
-    *a_delta = org_delta;
-
-    /* get X1 and X2, minimum and maximum in original coordinates */
-    if ( num_segments < 1 )
-      return;
-
-#if 1
-    X1 = X2 = points[0].fx;
-    for ( nn = 1; nn < num_points; nn++ )
-    {
-      FT_Int  X = points[nn].fx;
-
-
-      if ( X < X1 )
-        X1 = X;
-      if ( X > X2 )
-        X2 = X;
-    }
-#else
-    X1 = X2 = segments[0].pos;
-    for ( nn = 1; nn < num_segments; nn++ )
-    {
-      FT_Int  X = segments[nn].pos;
-
-
-      if ( X < X1 )
-        X1 = X;
-      if ( X > X2 )
-        X2 = X;
-    }
-#endif
-
-    if ( X1 >= X2 )
-      return;
-
-    warper->x1 = FT_MulFix( X1, org_scale ) + org_delta;
-    warper->x2 = FT_MulFix( X2, org_scale ) + org_delta;
-
-    warper->t1 = AF_WARPER_FLOOR( warper->x1 );
-    warper->t2 = AF_WARPER_CEIL( warper->x2 );
-
-    /* examine a half pixel wide range around the maximum coordinates */
-    warper->x1min = warper->x1 & ~31;
-    warper->x1max = warper->x1min + 32;
-    warper->x2min = warper->x2 & ~31;
-    warper->x2max = warper->x2min + 32;
-
-    if ( warper->x1max > warper->x2 )
-      warper->x1max = warper->x2;
-
-    if ( warper->x2min < warper->x1 )
-      warper->x2min = warper->x1;
-
-    warper->w0 = warper->x2 - warper->x1;
-
-    if ( warper->w0 <= 64 )
-    {
-      warper->x1max = warper->x1;
-      warper->x2min = warper->x2;
-    }
-
-    /* examine (at most) a pixel wide range around the natural width */
-    warper->wmin = warper->x2min - warper->x1max;
-    warper->wmax = warper->x2max - warper->x1min;
-
-#if 1
-    /* some heuristics to reduce the number of widths to be examined */
-    {
-      int  margin = 16;
-
-
-      if ( warper->w0 <= 128 )
-      {
-         margin = 8;
-         if ( warper->w0 <= 96 )
-           margin = 4;
-      }
-
-      if ( warper->wmin < warper->w0 - margin )
-        warper->wmin = warper->w0 - margin;
-
-      if ( warper->wmax > warper->w0 + margin )
-        warper->wmax = warper->w0 + margin;
-    }
-
-    if ( warper->wmin < warper->w0 * 3 / 4 )
-      warper->wmin = warper->w0 * 3 / 4;
-
-    if ( warper->wmax > warper->w0 * 5 / 4 )
-      warper->wmax = warper->w0 * 5 / 4;
-#else
-    /* no scaling, just translation */
-    warper->wmin = warper->wmax = warper->w0;
-#endif
-
-    for ( w = warper->wmin; w <= warper->wmax; w++ )
-    {
-      FT_Fixed  new_scale;
-      FT_Pos    new_delta;
-      FT_Pos    xx1, xx2;
-
-
-      /* compute min and max positions for given width,       */
-      /* assuring that they stay within the coordinate ranges */
-      xx1 = warper->x1;
-      xx2 = warper->x2;
-      if ( w >= warper->w0 )
-      {
-        xx1 -= w - warper->w0;
-        if ( xx1 < warper->x1min )
-        {
-          xx2 += warper->x1min - xx1;
-          xx1  = warper->x1min;
-        }
-      }
-      else
-      {
-        xx1 -= w - warper->w0;
-        if ( xx1 > warper->x1max )
-        {
-          xx2 -= xx1 - warper->x1max;
-          xx1  = warper->x1max;
-        }
-      }
-
-      if ( xx1 < warper->x1 )
-        base_distort = warper->x1 - xx1;
-      else
-        base_distort = xx1 - warper->x1;
-
-      if ( xx2 < warper->x2 )
-        base_distort += warper->x2 - xx2;
-      else
-        base_distort += xx2 - warper->x2;
-
-      /* give base distortion a greater weight while scoring */
-      base_distort *= 10;
-
-      new_scale = org_scale + FT_DivFix( w - warper->w0, X2 - X1 );
-      new_delta = xx1 - FT_MulFix( X1, new_scale );
-
-      af_warper_compute_line_best( warper, new_scale, new_delta, xx1, xx2,
-                                   base_distort,
-                                   segments, num_segments );
-    }
-
-    {
-      FT_Fixed  best_scale = warper->best_scale;
-      FT_Pos    best_delta = warper->best_delta;
-
-
-      hints->xmin_delta = FT_MulFix( X1, best_scale - org_scale )
-                          + best_delta;
-      hints->xmax_delta = FT_MulFix( X2, best_scale - org_scale )
-                          + best_delta;
-
-      *a_scale = best_scale;
-      *a_delta = best_delta;
-    }
-  }
-
-#else /* !AF_CONFIG_OPTION_USE_WARPER */
-
-  /* ANSI C doesn't like empty source files */
-  typedef int  _af_warp_dummy;
-
-#endif /* !AF_CONFIG_OPTION_USE_WARPER */
-
-/* END */
diff --git a/src/autofit/afwarp.h b/src/autofit/afwarp.h
deleted file mode 100644
index cdea23e..0000000
--- a/src/autofit/afwarp.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************************
- *
- * afwarp.h
- *
- *   Auto-fitter warping algorithm (specification).
- *
- * Copyright (C) 2006-2020 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used,
- * modified, and distributed under the terms of the FreeType project
- * license, LICENSE.TXT.  By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- */
-
-
-#ifndef AFWARP_H_
-#define AFWARP_H_
-
-#include "afhints.h"
-
-FT_BEGIN_HEADER
-
-#define AF_WARPER_SCALE
-
-#define AF_WARPER_FLOOR( x )  ( (x) & ~FT_TYPEOF( x )63 )
-#define AF_WARPER_CEIL( x )   AF_WARPER_FLOOR( (x) + 63 )
-
-
-  typedef FT_Int32  AF_WarpScore;
-
-  typedef struct  AF_WarperRec_
-  {
-    FT_Pos        x1, x2;
-    FT_Pos        t1, t2;
-    FT_Pos        x1min, x1max;
-    FT_Pos        x2min, x2max;
-    FT_Pos        w0, wmin, wmax;
-
-    FT_Fixed      best_scale;
-    FT_Pos        best_delta;
-    AF_WarpScore  best_score;
-    AF_WarpScore  best_distort;
-
-  } AF_WarperRec, *AF_Warper;
-
-
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-  FT_LOCAL( void )
-  af_warper_compute( AF_Warper      warper,
-                     AF_GlyphHints  hints,
-                     AF_Dimension   dim,
-                     FT_Fixed      *a_scale,
-                     FT_Pos        *a_delta );
-#endif
-
-
-FT_END_HEADER
-
-
-#endif /* AFWARP_H_ */
-
-
-/* END */
diff --git a/src/autofit/afwrtsys.h b/src/autofit/afwrtsys.h
deleted file mode 100644
index 3990633..0000000
--- a/src/autofit/afwrtsys.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/****************************************************************************
- *
- * afwrtsys.h
- *
- *   Auto-fitter writing systems (specification only).
- *
- * Copyright (C) 2013-2020 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
- *
- * This file is part of the FreeType project, and may only be used,
- * modified, and distributed under the terms of the FreeType project
- * license, LICENSE.TXT.  By continuing to use, modify, or distribute
- * this file you indicate that you have read the license and
- * understand and accept it fully.
- *
- */
-
-
-#ifndef AFWRTSYS_H_
-#define AFWRTSYS_H_
-
-  /* Since preprocessor directives can't create other preprocessor */
-  /* directives, we have to include the header files manually.     */
-
-#include "afdummy.h"
-#include "aflatin.h"
-#include "afcjk.h"
-#include "afindic.h"
-#ifdef FT_OPTION_AUTOFIT2
-#include "aflatin2.h"
-#endif
-
-#endif /* AFWRTSYS_H_ */
-
-
-  /* The following part can be included multiple times. */
-  /* Define `WRITING_SYSTEM' as needed.                 */
-
-
-  /* Add new writing systems here.  The arguments are the writing system */
-  /* name in lowercase and uppercase, respectively.                      */
-
-  WRITING_SYSTEM( dummy,  DUMMY  )
-  WRITING_SYSTEM( latin,  LATIN  )
-  WRITING_SYSTEM( cjk,    CJK    )
-  WRITING_SYSTEM( indic,  INDIC  )
-#ifdef FT_OPTION_AUTOFIT2
-  WRITING_SYSTEM( latin2, LATIN2 )
-#endif
-
-
-/* END */
diff --git a/src/autofit/afws-decl.h b/src/autofit/afws-decl.h
new file mode 100644
index 0000000..c10dd57
--- /dev/null
+++ b/src/autofit/afws-decl.h
@@ -0,0 +1,33 @@
+/****************************************************************************
+ *
+ * afws-decl.h
+ *
+ *   Auto-fitter writing system declarations (specification only).
+ *
+ * Copyright (C) 2013-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef AFWS_DECL_H_
+#define AFWS_DECL_H_
+
+  /* Since preprocessor directives can't create other preprocessor */
+  /* directives, we have to include the header files manually.     */
+
+#include "afdummy.h"
+#include "aflatin.h"
+#include "afcjk.h"
+#include "afindic.h"
+
+#endif /* AFWS_DECL_H_ */
+
+
+/* END */
diff --git a/src/autofit/afws-iter.h b/src/autofit/afws-iter.h
new file mode 100644
index 0000000..5571420
--- /dev/null
+++ b/src/autofit/afws-iter.h
@@ -0,0 +1,31 @@
+/****************************************************************************
+ *
+ * afws-iter.h
+ *
+ *   Auto-fitter writing systems iterator (specification only).
+ *
+ * Copyright (C) 2013-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+  /* This header may be included multiple times. */
+  /* Define `WRITING_SYSTEM' as needed.          */
+
+
+  /* Add new writing systems here.  The arguments are the writing system */
+  /* name in lowercase and uppercase, respectively.                      */
+
+  WRITING_SYSTEM( dummy, DUMMY )
+  WRITING_SYSTEM( latin, LATIN )
+  WRITING_SYSTEM( cjk,   CJK   )
+  WRITING_SYSTEM( indic, INDIC )
+
+
+/* END */
diff --git a/src/autofit/autofit.c b/src/autofit/autofit.c
index ef5e7f1..7e692b4 100644
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -18,7 +18,6 @@
 
 #define FT_MAKE_OPTION_SINGLE_OBJECT
 
-#include "afangles.c"
 #include "afblue.c"
 #include "afcjk.c"
 #include "afdummy.c"
@@ -26,12 +25,10 @@
 #include "afhints.c"
 #include "afindic.c"
 #include "aflatin.c"
-#include "aflatin2.c"
 #include "afloader.c"
 #include "afmodule.c"
 #include "afranges.c"
 #include "afshaper.c"
-#include "afwarp.c"
 
 
 /* END */
diff --git a/src/autofit/module.mk b/src/autofit/module.mk
index c32781f..fab3a6b 100644
--- a/src/autofit/module.mk
+++ b/src/autofit/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2003-2020 by
+# Copyright (C) 2003-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/autofit/rules.mk b/src/autofit/rules.mk
index 553ddce..499c0e0 100644
--- a/src/autofit/rules.mk
+++ b/src/autofit/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2003-2020 by
+# Copyright (C) 2003-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -28,8 +28,7 @@
 
 # AUTOF driver sources (i.e., C files)
 #
-AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
-                 $(AUTOF_DIR)/afblue.c   \
+AUTOF_DRV_SRC := $(AUTOF_DIR)/afblue.c   \
                  $(AUTOF_DIR)/afcjk.c    \
                  $(AUTOF_DIR)/afdummy.c  \
                  $(AUTOF_DIR)/afglobal.c \
@@ -40,17 +39,17 @@
                  $(AUTOF_DIR)/afmodule.c \
                  $(AUTOF_DIR)/afranges.c \
                  $(AUTOF_DIR)/afshaper.c \
-                 $(AUTOF_DIR)/afwarp.c
 
 # AUTOF driver headers
 #
-AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h)  \
-               $(AUTOF_DIR)/afcover.h  \
-               $(AUTOF_DIR)/aferrors.h \
-               $(AUTOF_DIR)/afscript.h \
-               $(AUTOF_DIR)/afstyles.h \
-               $(AUTOF_DIR)/aftypes.h  \
-               $(AUTOF_DIR)/afwrtsys.h
+AUTOF_DRV_H := $(AUTOF_DRV_SRC:%c=%h)   \
+               $(AUTOF_DIR)/afcover.h   \
+               $(AUTOF_DIR)/aferrors.h  \
+               $(AUTOF_DIR)/afscript.h  \
+               $(AUTOF_DIR)/afstyles.h  \
+               $(AUTOF_DIR)/aftypes.h   \
+               $(AUTOF_DIR)/afws-decl.h \
+               $(AUTOF_DIR)/afws-iter.h
 
 
 # AUTOF driver object(s)
diff --git a/src/base/ftadvanc.c b/src/base/ftadvanc.c
index c689e6a..f20b992 100644
--- a/src/base/ftadvanc.c
+++ b/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
  *
  *   Quick computation of advance widths (body).
  *
- * Copyright (C) 2008-2020 by
+ * Copyright (C) 2008-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftbase.c b/src/base/ftbase.c
index bfbaffd..7366bc4 100644
--- a/src/base/ftbase.c
+++ b/src/base/ftbase.c
@@ -4,7 +4,7 @@
  *
  *   Single object library component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftbase.h b/src/base/ftbase.h
index 25afa9b..963ff93 100644
--- a/src/base/ftbase.h
+++ b/src/base/ftbase.h
@@ -4,7 +4,7 @@
  *
  *   Private functions used in the `base' module (specification).
  *
- * Copyright (C) 2008-2020 by
+ * Copyright (C) 2008-2021 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c
index 30a4eba..4db29cb 100644
--- a/src/base/ftbbox.c
+++ b/src/base/ftbbox.c
@@ -4,7 +4,7 @@
  *
  *   FreeType bbox computation (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff --git a/src/base/ftbdf.c b/src/base/ftbdf.c
index fc374c6..f93ca8e 100644
--- a/src/base/ftbdf.c
+++ b/src/base/ftbdf.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing BDF-specific strings (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index 584213d..2146d3e 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility functions for bitmaps (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -112,10 +112,10 @@
       target_size = (FT_ULong)target_pitch * target->rows;
 
       if ( target_size != size )
-        (void)FT_QREALLOC( target->buffer, target_size, size );
+        FT_MEM_QREALLOC( target->buffer, target_size, size );
     }
     else
-      (void)FT_QALLOC( target->buffer, size );
+      FT_MEM_QALLOC( target->buffer, size );
 
     if ( !error )
     {
@@ -907,8 +907,8 @@
     final_rows  = ( final_ury - final_lly ) >> 6;
 
 #ifdef FT_DEBUG_LEVEL_TRACE
-    FT_TRACE5(( "FT_Bitmap_Blend:\n"
-                "  source bitmap: (%ld, %ld) -- (%ld, %ld); %d x %d\n",
+    FT_TRACE5(( "FT_Bitmap_Blend:\n" ));
+    FT_TRACE5(( "  source bitmap: (%ld, %ld) -- (%ld, %ld); %d x %d\n",
       source_llx / 64, source_lly / 64,
       source_urx / 64, source_ury / 64,
       source_->width, source_->rows ));
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index b5258c8..9df8e40 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -4,7 +4,7 @@
  *
  *   Arithmetic computations (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -45,7 +45,7 @@
 
 /* we need to emulate a 64-bit data type if a real one isn't available */
 
-#ifndef FT_LONG64
+#ifndef FT_INT64
 
   typedef struct  FT_Int64_
   {
@@ -54,7 +54,7 @@
 
   } FT_Int64;
 
-#endif /* !FT_LONG64 */
+#endif /* !FT_INT64 */
 
 
   /**************************************************************************
@@ -79,7 +79,7 @@
   FT_END_STMNT
 
   /* The following three functions are available regardless of whether */
-  /* FT_LONG64 is defined.                                             */
+  /* FT_INT64 is defined.                                              */
 
   /* documentation is in freetype.h */
 
@@ -109,7 +109,7 @@
 
 #ifndef FT_MSB
 
-  FT_BASE_DEF ( FT_Int )
+  FT_BASE_DEF( FT_Int )
   FT_MSB( FT_UInt32 z )
   {
     FT_Int  shift = 0;
@@ -164,7 +164,7 @@
   }
 
 
-#ifdef FT_LONG64
+#ifdef FT_INT64
 
 
   /* documentation is in freetype.h */
@@ -272,7 +272,7 @@
   }
 
 
-#else /* !FT_LONG64 */
+#else /* !FT_INT64 */
 
 
   static void
@@ -651,7 +651,7 @@
   }
 
 
-#endif /* !FT_LONG64 */
+#endif /* !FT_INT64 */
 
 
   /* documentation is in ftglyph.h */
@@ -985,7 +985,7 @@
     /* we silently ignore overflow errors since such large values */
     /* lead to even more (harmless) rendering errors later on     */
 
-#ifdef FT_LONG64
+#ifdef FT_INT64
 
     FT_Int64  delta = SUB_INT64( MUL_INT64( in_x, out_y ),
                                  MUL_INT64( in_y, out_x ) );
diff --git a/src/base/ftcid.c b/src/base/ftcid.c
index ce8a876..216ee2b 100644
--- a/src/base/ftcid.c
+++ b/src/base/ftcid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing CID font information.
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * Derek Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftcolor.c b/src/base/ftcolor.c
index a50d680..3ef3256 100644
--- a/src/base/ftcolor.c
+++ b/src/base/ftcolor.c
@@ -4,7 +4,7 @@
  *
  *   FreeType's glyph color management (body).
  *
- * Copyright (C) 2018-2020 by
+ * Copyright (C) 2018-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index eb0d651..4f5c1e7 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
  *
  *   Memory debugger (body).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -302,46 +302,6 @@
   }
 
 
-  static FT_MemTable
-  ft_mem_table_new( FT_Memory  memory )
-  {
-    FT_MemTable  table;
-
-
-    table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) );
-    if ( !table )
-      goto Exit;
-
-    FT_ZERO( table );
-
-    table->size  = FT_MEM_SIZE_MIN;
-    table->nodes = 0;
-
-    table->memory = memory;
-
-    table->memory_user = memory->user;
-
-    table->alloc   = memory->alloc;
-    table->realloc = memory->realloc;
-    table->free    = memory->free;
-
-    table->buckets = (FT_MemNode *)
-                       memory->alloc(
-                         memory,
-                         table->size * (FT_Long)sizeof ( FT_MemNode ) );
-    if ( table->buckets )
-      FT_ARRAY_ZERO( table->buckets, table->size );
-    else
-    {
-      memory->free( memory, table );
-      table = NULL;
-    }
-
-  Exit:
-    return table;
-  }
-
-
   static void
   ft_mem_table_destroy( FT_MemTable  table )
   {
@@ -350,8 +310,6 @@
     FT_Long  leaks      = 0;
 
 
-    FT_DumpMemory( table->memory );
-
     /* remove all blocks from the table, revealing leaked ones */
     for ( i = 0; i < table->size; i++ )
     {
@@ -413,8 +371,6 @@
     printf( "FreeType: maximum memory footprint = %ld\n",
             table->alloc_max );
 
-    ft_mem_table_free( table, table );
-
     if ( leak_count > 0 )
       ft_mem_debug_panic(
         "FreeType: %ld bytes of memory leaked in %ld blocks\n",
@@ -821,17 +777,30 @@
   }
 
 
-  extern FT_Int
+  extern void
   ft_mem_debug_init( FT_Memory  memory )
   {
     FT_MemTable  table;
-    FT_Int       result = 0;
 
 
-    if ( ft_getenv( "FT2_DEBUG_MEMORY" ) )
+    if ( !ft_getenv( "FT2_DEBUG_MEMORY" ) )
+      return;
+
+    table = (FT_MemTable)memory->alloc( memory, sizeof ( *table ) );
+
+    if ( table )
     {
-      table = ft_mem_table_new( memory );
-      if ( table )
+      FT_ZERO( table );
+
+      table->memory      = memory;
+      table->memory_user = memory->user;
+      table->alloc       = memory->alloc;
+      table->realloc     = memory->realloc;
+      table->free        = memory->free;
+
+      ft_mem_table_resize( table );
+
+      if ( table->size )
       {
         const char*  p;
 
@@ -876,28 +845,31 @@
           if ( keep_alive > 0 )
             table->keep_alive = 1;
         }
-
-        result = 1;
       }
+      else
+        memory->free( memory, table );
     }
-    return result;
   }
 
 
   extern void
   ft_mem_debug_done( FT_Memory  memory )
   {
-    FT_MemTable  table = (FT_MemTable)memory->user;
-
-
-    if ( table )
+    if ( memory->free == ft_mem_debug_free )
     {
+      FT_MemTable  table = (FT_MemTable)memory->user;
+
+
+      FT_DumpMemory( memory );
+
+      ft_mem_table_destroy( table );
+
       memory->free    = table->free;
       memory->realloc = table->realloc;
       memory->alloc   = table->alloc;
+      memory->user    = table->memory_user;
 
-      ft_mem_table_destroy( table );
-      memory->user = NULL;
+      memory->free( memory, table );
     }
   }
 
@@ -922,11 +894,9 @@
   extern void
   FT_DumpMemory( FT_Memory  memory )
   {
-    FT_MemTable  table = (FT_MemTable)memory->user;
-
-
-    if ( table )
+    if ( memory->free == ft_mem_debug_free )
     {
+      FT_MemTable    table = (FT_MemTable)memory->user;
       FT_MemSource*  bucket = table->sources;
       FT_MemSource*  limit  = bucket + FT_MEM_SOURCE_BUCKETS;
       FT_MemSource*  sources;
diff --git a/src/base/ftdebug.c b/src/base/ftdebug.c
index 62cf680..3485791 100644
--- a/src/base/ftdebug.c
+++ b/src/base/ftdebug.c
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -42,7 +42,53 @@
 
 
 #include <freetype/freetype.h>
+#include <freetype/ftlogging.h>
 #include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+
+
+#ifdef FT_DEBUG_LOGGING
+
+  /**************************************************************************
+   *
+   * Variables used to control logging.
+   *
+   * 1. `ft_default_trace_level` stores the value of trace levels, which are
+   *    provided to FreeType using the `FT2_DEBUG` environment variable.
+   *
+   * 2. `ft_fileptr` stores the `FILE*` handle.
+   *
+   * 3. `ft_component` is a string that holds the name of `FT_COMPONENT`.
+   *
+   * 4. The flag `ft_component_flag` prints the name of `FT_COMPONENT` along
+   *    with the actual log message if set to true.
+   *
+   * 5. The flag `ft_timestamp_flag` prints time along with the actual log
+   *    message if set to ture.
+   *
+   * 6. `ft_have_newline_char` is used to differentiate between a log
+   *    message with and without a trailing newline character.
+   *
+   * 7. `ft_custom_trace_level` stores the custom trace level value, which
+   *    is provided by the user at run-time.
+   *
+   * We use `static` to avoid 'unused variable' warnings.
+   *
+   */
+  static const char*  ft_default_trace_level = NULL;
+  static FILE*        ft_fileptr             = NULL;
+  static const char*  ft_component           = NULL;
+  static FT_Bool      ft_component_flag      = FALSE;
+  static FT_Bool      ft_timestamp_flag      = FALSE;
+  static FT_Bool      ft_have_newline_char   = TRUE;
+  static const char*  ft_custom_trace_level  = NULL;
+
+  /* declared in ftdebug.h */
+
+  dlg_handler            ft_default_log_handler = NULL;
+  FT_Custom_Log_Handler  custom_output_handler  = NULL;
+
+#endif /* FT_DEBUG_LOGGING */
 
 
 #ifdef FT_DEBUG_LEVEL_ERROR
@@ -106,7 +152,6 @@
 #endif /* FT_DEBUG_LEVEL_ERROR */
 
 
-
 #ifdef FT_DEBUG_LEVEL_TRACE
 
   /* array of trace levels, initialized to 0; */
@@ -195,9 +240,18 @@
   FT_BASE_DEF( void )
   ft_debug_init( void )
   {
-    const char*  ft2_debug = ft_getenv( "FT2_DEBUG" );
+    const char*  ft2_debug = NULL;
 
 
+#ifdef FT_DEBUG_LOGGING
+    if ( ft_custom_trace_level != NULL )
+      ft2_debug = ft_custom_trace_level;
+    else
+      ft2_debug = ft_default_trace_level;
+#else
+    ft2_debug = ft_getenv( "FT2_DEBUG" );
+#endif
+
     if ( ft2_debug )
     {
       const char*  p = ft2_debug;
@@ -210,6 +264,49 @@
         if ( *p == ' ' || *p == '\t' || *p == ',' || *p == ';' || *p == '=' )
           continue;
 
+#ifdef FT_DEBUG_LOGGING
+
+        /* check extra arguments for logging */
+        if ( *p == '-' )
+        {
+          const char*  r = ++p;
+
+
+          if ( *r == 'v' )
+          {
+            const char*  s = ++r;
+
+
+            ft_component_flag = TRUE;
+
+            if ( *s == 't' )
+            {
+              ft_timestamp_flag = TRUE;
+              p++;
+            }
+
+            p++;
+          }
+
+          else if ( *r == 't' )
+          {
+            const char*  s = ++r;
+
+
+            ft_timestamp_flag = TRUE;
+
+            if ( *s == 'v' )
+            {
+              ft_component_flag = TRUE;
+              p++;
+            }
+
+            p++;
+          }
+        }
+
+#endif /* FT_DEBUG_LOGGING */
+
         /* read toggle name, followed by ':' */
         q = p;
         while ( *p && *p != ':' )
@@ -311,8 +408,237 @@
     /* nothing */
   }
 
-
 #endif /* !FT_DEBUG_LEVEL_TRACE */
 
 
+#ifdef FT_DEBUG_LOGGING
+
+  /**************************************************************************
+   *
+   * Initialize and de-initialize 'dlg' library.
+   *
+   */
+
+  FT_BASE_DEF( void )
+  ft_logging_init( void )
+  {
+    ft_default_log_handler = ft_log_handler;
+    ft_default_trace_level = ft_getenv( "FT2_DEBUG" );
+
+    if ( ft_getenv( "FT_LOGGING_FILE" ) )
+      ft_fileptr = ft_fopen( ft_getenv( "FT_LOGGING_FILE" ), "w" );
+    else
+      ft_fileptr = stderr;
+
+    ft_debug_init();
+
+    /* Set the default output handler for 'dlg'. */
+    dlg_set_handler( ft_default_log_handler, NULL );
+  }
+
+
+  FT_BASE_DEF( void )
+  ft_logging_deinit( void )
+  {
+    if ( ft_fileptr != stderr )
+      ft_fclose( ft_fileptr );
+  }
+
+
+  /**************************************************************************
+   *
+   * An output log handler for FreeType.
+   *
+   */
+  FT_BASE_DEF( void )
+  ft_log_handler( const struct dlg_origin*  origin,
+                  const char*               string,
+                  void*                     data )
+  {
+    char         features_buf[128];
+    char*        bufp = features_buf;
+
+    FT_UNUSED( data );
+
+
+    if ( ft_have_newline_char )
+    {
+      const char*  features        = NULL;
+      size_t       features_length = 0;
+
+
+#define FEATURES_TIMESTAMP            "[%h:%m] "
+#define FEATURES_COMPONENT            "[%t] "
+#define FEATURES_TIMESTAMP_COMPONENT  "[%h:%m %t] "
+
+      if ( ft_timestamp_flag && ft_component_flag )
+      {
+        features        = FEATURES_TIMESTAMP_COMPONENT;
+        features_length = sizeof ( FEATURES_TIMESTAMP_COMPONENT );
+      }
+      else if ( ft_timestamp_flag )
+      {
+        features        = FEATURES_TIMESTAMP;
+        features_length = sizeof ( FEATURES_TIMESTAMP );
+      }
+      else if ( ft_component_flag )
+      {
+        features        = FEATURES_COMPONENT;
+        features_length = sizeof ( FEATURES_COMPONENT );
+      }
+
+      if ( ft_component_flag || ft_timestamp_flag )
+      {
+        ft_strncpy( features_buf, features, features_length );
+        bufp += features_length - 1;
+      }
+
+      if ( ft_component_flag )
+      {
+        size_t  tag_length = ft_strlen( *origin->tags );
+        size_t  i;
+
+
+        /* To vertically align tracing messages we compensate the */
+        /* different FT_COMPONENT string lengths by inserting an  */
+        /* appropriate amount of space characters.                */
+        for ( i = 0;
+              i < FT_MAX_TRACE_LEVEL_LENGTH - tag_length;
+              i++ )
+          *bufp++ = ' ';
+      }
+    }
+
+    /* Finally add the format string for the tracing message. */
+    *bufp++ = '%';
+    *bufp++ = 'c';
+    *bufp   = '\0';
+
+    dlg_generic_outputf_stream( ft_fileptr,
+                                (const char*)features_buf,
+                                origin,
+                                string,
+                                dlg_default_output_styles,
+                                true );
+
+    if ( ft_strrchr( string, '\n' ) )
+      ft_have_newline_char = TRUE;
+    else
+      ft_have_newline_char = FALSE;
+  }
+
+
+  /* documentation is in ftdebug.h */
+  FT_BASE_DEF( void )
+  ft_add_tag( const char*  tag )
+  {
+    ft_component = tag;
+
+    dlg_add_tag( tag, NULL );
+  }
+
+
+  /* documentation is in ftdebug.h */
+  FT_BASE_DEF( void )
+  ft_remove_tag( const char*  tag )
+  {
+    dlg_remove_tag( tag, NULL );
+  }
+
+
+  /* documentation is in ftlogging.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Trace_Set_Level( const char*  level )
+  {
+    ft_component_flag     = FALSE;
+    ft_timestamp_flag     = FALSE;
+    ft_custom_trace_level = level;
+
+    ft_debug_init();
+  }
+
+
+  /* documentation is in ftlogging.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Trace_Set_Default_Level( void )
+  {
+    ft_component_flag     = FALSE;
+    ft_timestamp_flag     = FALSE;
+    ft_custom_trace_level = NULL;
+
+    ft_debug_init();
+  }
+
+
+  /**************************************************************************
+   *
+   * Functions to handle a custom log handler.
+   *
+   */
+
+  /* documentation is in ftlogging.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Log_Handler( FT_Custom_Log_Handler  handler )
+  {
+    custom_output_handler = handler;
+  }
+
+
+  /* documentation is in ftlogging.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Default_Log_Handler( void )
+  {
+    custom_output_handler = NULL;
+  }
+
+
+  /* documentation is in ftdebug.h */
+  FT_BASE_DEF( void )
+  FT_Logging_Callback( const char*  fmt,
+                       ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    custom_output_handler( ft_component, fmt, ap );
+    va_end( ap );
+  }
+
+#else /* !FT_DEBUG_LOGGING */
+
+  FT_EXPORT_DEF( void )
+  FT_Trace_Set_Level( const char*  level )
+  {
+    FT_UNUSED( level );
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Trace_Set_Default_Level( void )
+  {
+    /* nothing */
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Log_Handler( FT_Custom_Log_Handler  handler )
+  {
+    FT_UNUSED( handler );
+  }
+
+
+  FT_EXPORT_DEF( void )
+  FT_Set_Default_Log_Handler( void )
+  {
+    /* nothing */
+  }
+
+#endif /* !FT_DEBUG_LOGGING */
+
+
 /* END */
diff --git a/src/base/fterrors.c b/src/base/fterrors.c
index eba9e76..1464926 100644
--- a/src/base/fterrors.c
+++ b/src/base/fterrors.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for error code handling.
  *
- * Copyright (C) 2018-2020 by
+ * Copyright (C) 2018-2021 by
  * Armin Hasitzka, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftfntfmt.c b/src/base/ftfntfmt.c
index a45317e..4e1b830 100644
--- a/src/base/ftfntfmt.c
+++ b/src/base/ftfntfmt.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for font formats (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftfstype.c b/src/base/ftfstype.c
index bca548f..57e904d 100644
--- a/src/base/ftfstype.c
+++ b/src/base/ftfstype.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file to access FSType data (body).
  *
- * Copyright (C) 2008-2020 by
+ * Copyright (C) 2008-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftgasp.c b/src/base/ftgasp.c
index eed05a3..b744f0a 100644
--- a/src/base/ftgasp.c
+++ b/src/base/ftgasp.c
@@ -4,7 +4,7 @@
  *
  *   Access of TrueType's `gasp' table (body).
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftgloadr.c b/src/base/ftgloadr.c
index 05fc769..83ce066 100644
--- a/src/base/ftgloadr.c
+++ b/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph loader (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c
index 825eba2..e2c6f73 100644
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -4,7 +4,7 @@
  *
  *   FreeType convenience functions to handle glyphs (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -453,9 +453,9 @@
   /* documentation is in ftglyph.h */
 
   FT_EXPORT_DEF( FT_Error )
-  FT_Glyph_Transform( FT_Glyph    glyph,
-                      FT_Matrix*  matrix,
-                      FT_Vector*  delta )
+  FT_Glyph_Transform( FT_Glyph          glyph,
+                      const FT_Matrix*  matrix,
+                      const FT_Vector*  delta )
   {
     FT_Error  error = FT_Err_Ok;
 
@@ -533,10 +533,10 @@
   /* documentation is in ftglyph.h */
 
   FT_EXPORT_DEF( FT_Error )
-  FT_Glyph_To_Bitmap( FT_Glyph*       the_glyph,
-                      FT_Render_Mode  render_mode,
-                      FT_Vector*      origin,
-                      FT_Bool         destroy )
+  FT_Glyph_To_Bitmap( FT_Glyph*         the_glyph,
+                      FT_Render_Mode    render_mode,
+                      const FT_Vector*  origin,
+                      FT_Bool           destroy )
   {
     FT_GlyphSlotRec           dummy;
     FT_GlyphSlot_InternalRec  dummy_internal;
@@ -585,7 +585,7 @@
 #if 1
     /* if `origin' is set, translate the glyph image */
     if ( origin )
-      FT_Glyph_Transform( glyph, 0, origin );
+      FT_Glyph_Transform( glyph, NULL, origin );
 #else
     FT_UNUSED( origin );
 #endif
@@ -603,7 +603,7 @@
 
       v.x = -origin->x;
       v.y = -origin->y;
-      FT_Glyph_Transform( glyph, 0, &v );
+      FT_Glyph_Transform( glyph, NULL, &v );
     }
 #endif
 
diff --git a/src/base/ftgxval.c b/src/base/ftgxval.c
index f04df14..e9567f7 100644
--- a/src/base/ftgxval.c
+++ b/src/base/ftgxval.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating TrueTypeGX/AAT tables (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * Masatake YAMATO, Redhat K.K,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/base/ftinit.c b/src/base/ftinit.c
index 0acc75e..a2d2b93 100644
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -4,7 +4,7 @@
  *
  *   FreeType initialization layer (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -202,6 +202,10 @@
     FT_Memory  memory;
 
 
+#ifdef FT_DEBUG_LOGGING
+    ft_logging_init();
+#endif
+
     /* check of `alibrary' delayed to `FT_New_Library' */
 
     /* First of all, allocate a new system object -- this function is part */
@@ -248,6 +252,10 @@
     /* discard memory manager */
     FT_Done_Memory( memory );
 
+#ifdef FT_DEBUG_LOGGING
+    ft_logging_deinit();
+#endif
+
     return FT_Err_Ok;
   }
 
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index 1e84dbc..488b913 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for color filtering of subpixel bitmap glyphs (body).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -32,7 +32,7 @@
 
 
   /* add padding according to filter weights */
-  FT_BASE_DEF (void)
+  FT_BASE_DEF( void )
   ft_lcd_padding( FT_BBox*        cbox,
                   FT_GlyphSlot    slot,
                   FT_Render_Mode  mode )
@@ -357,7 +357,7 @@
 
   FT_EXPORT_DEF( FT_Error )
   FT_Library_SetLcdGeometry( FT_Library  library,
-                             FT_Vector*  sub )
+                             FT_Vector   sub[3] )
   {
     FT_UNUSED( library );
     FT_UNUSED( sub );
@@ -368,7 +368,7 @@
 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
   /* add padding to accommodate outline shifts */
-  FT_BASE_DEF (void)
+  FT_BASE_DEF( void )
   ft_lcd_padding( FT_BBox*        cbox,
                   FT_GlyphSlot    slot,
                   FT_Render_Mode  mode )
@@ -428,7 +428,7 @@
 
     ft_memcpy( library->lcd_geometry, sub, 3 * sizeof( FT_Vector ) );
 
-    return FT_THROW( Unimplemented_Feature );
+    return FT_Err_Ok;
   }
 
 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
diff --git a/src/base/ftmac.c b/src/base/ftmac.c
index 55a631f..36a8609 100644
--- a/src/base/ftmac.c
+++ b/src/base/ftmac.c
@@ -8,7 +8,7 @@
  * This file is for Mac OS X only; see builds/mac/ftoldmac.c for
  * classic platforms built by MPW.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -560,7 +560,7 @@
     if ( lwfn_file_name[0] )
     {
       err = lookup_lwfn_by_fond( pathname, lwfn_file_name,
-                                 buff, sizeof ( buff )  );
+                                 buff, sizeof ( buff ) );
       if ( !err )
         have_lwfn = 1;
     }
@@ -631,7 +631,7 @@
       old_total_size = total_size;
     }
 
-    if ( FT_ALLOC( buffer, (FT_Long)total_size ) )
+    if ( FT_QALLOC( buffer, (FT_Long)total_size ) )
       goto Error;
 
     /* Second pass: append all POST data to the buffer, add PFB fields. */
@@ -752,7 +752,7 @@
     if ( FT_MAC_RFORK_MAX_LEN < sfnt_size )
       return FT_THROW( Array_Too_Large );
 
-    if ( FT_ALLOC( sfnt_data, (FT_Long)sfnt_size ) )
+    if ( FT_QALLOC( sfnt_data, (FT_Long)sfnt_size ) )
     {
       ReleaseResource( sfnt );
       return error;
diff --git a/src/base/ftmm.c b/src/base/ftmm.c
index 9a702b9..fc5d4ec 100644
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -4,7 +4,7 @@
  *
  *   Multiple Master font support (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index c060bbb..883f1a8 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType private base classes (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -78,6 +78,9 @@
 #pragma warning( pop )
 #endif
 
+  /* This array must stay in sync with the @FT_Pixel_Mode enumeration */
+  /* (in file `ftimage.h`).                                           */
+
   static const char* const  pixel_modes[] =
   {
     "none",
@@ -87,7 +90,8 @@
     "gray 4-bit bitmap",
     "LCD 8-bit bitmap",
     "vertical LCD 8-bit bitmap",
-    "BGRA 32-bit color image bitmap"
+    "BGRA 32-bit color image bitmap",
+    "SDF 8-bit bitmap"
   };
 
 #endif /* FT_DEBUG_LEVEL_TRACE */
@@ -193,6 +197,7 @@
     FT_Error   error;
     FT_Memory  memory;
     FT_Stream  stream = NULL;
+    FT_UInt    mode;
 
 
     *astream = NULL;
@@ -204,49 +209,56 @@
       return FT_THROW( Invalid_Argument );
 
     memory = library->memory;
+    mode   = args->flags &
+               ( FT_OPEN_MEMORY | FT_OPEN_STREAM | FT_OPEN_PATHNAME );
 
-    if ( FT_NEW( stream ) )
-      goto Exit;
-
-    stream->memory = memory;
-
-    if ( args->flags & FT_OPEN_MEMORY )
+    if ( mode == FT_OPEN_MEMORY )
     {
       /* create a memory-based stream */
+      if ( FT_NEW( stream ) )
+        goto Exit;
+
       FT_Stream_OpenMemory( stream,
                             (const FT_Byte*)args->memory_base,
                             (FT_ULong)args->memory_size );
+      stream->memory = memory;
     }
 
 #ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
 
-    else if ( args->flags & FT_OPEN_PATHNAME )
+    else if ( mode == FT_OPEN_PATHNAME )
     {
       /* create a normal system stream */
+      if ( FT_NEW( stream ) )
+        goto Exit;
+
+      stream->memory = memory;
       error = FT_Stream_Open( stream, args->pathname );
-      stream->pathname.pointer = args->pathname;
+      if ( error )
+        FT_FREE( stream );
     }
-    else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
+    else if ( ( mode == FT_OPEN_STREAM ) && args->stream )
     {
       /* use an existing, user-provided stream */
 
       /* in this case, we do not need to allocate a new stream object */
       /* since the caller is responsible for closing it himself       */
-      FT_FREE( stream );
-      stream = args->stream;
+      stream         = args->stream;
+      stream->memory = memory;
+      error          = FT_Err_Ok;
     }
 
 #endif
 
     else
+    {
       error = FT_THROW( Invalid_Argument );
+      if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
+        FT_Stream_Close( args->stream );
+    }
 
-    if ( error )
-      FT_FREE( stream );
-    else
-      stream->memory = memory;  /* just to be certain */
-
-    *astream = stream;
+    if ( !error )
+      *astream       = stream;
 
   Exit:
     return error;
@@ -523,7 +535,7 @@
     else
       slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 
-    (void)FT_ALLOC( slot->bitmap.buffer, size );
+    FT_MEM_ALLOC( slot->bitmap.buffer, size );
     return error;
   }
 
@@ -535,6 +547,8 @@
     ft_glyphslot_free_bitmap( slot );
 
     /* clear all public fields in the glyph slot */
+    slot->glyph_index = 0;
+
     FT_ZERO( &slot->metrics );
     FT_ZERO( &slot->outline );
 
@@ -555,6 +569,8 @@
 
     slot->linearHoriAdvance = 0;
     slot->linearVertAdvance = 0;
+    slot->advance.x         = 0;
+    slot->advance.y         = 0;
     slot->lsb_delta         = 0;
     slot->rsb_delta         = 0;
   }
@@ -734,6 +750,29 @@
   }
 
 
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( void )
+  FT_Get_Transform( FT_Face     face,
+                    FT_Matrix*  matrix,
+                    FT_Vector*  delta )
+  {
+    FT_Face_Internal  internal;
+
+
+    if ( !face )
+      return;
+
+    internal = face->internal;
+
+    if ( matrix )
+      *matrix = internal->transform_matrix;
+
+    if ( delta )
+      *delta = internal->transform_delta;
+  }
+
+
   static FT_Renderer
   ft_lookup_glyph_renderer( FT_GlyphSlot  slot );
 
@@ -1056,19 +1095,24 @@
 #ifdef FT_DEBUG_LEVEL_TRACE
     FT_TRACE5(( "FT_Load_Glyph: index %d, flags 0x%x\n",
                 glyph_index, load_flags ));
+    FT_TRACE5(( "  bitmap %dx%d %s, %s (mode %d)\n",
+                slot->bitmap.width,
+                slot->bitmap.rows,
+                slot->outline.points ?
+                  slot->bitmap.buffer ? "rendered"
+                                      : "preset"
+                                     :
+                  slot->internal->flags & FT_GLYPH_OWN_BITMAP ? "owned"
+                                                              : "unowned",
+                pixel_modes[slot->bitmap.pixel_mode],
+                slot->bitmap.pixel_mode ));
+    FT_TRACE5(( "\n" ));
     FT_TRACE5(( "  x advance: %f\n", slot->advance.x / 64.0 ));
     FT_TRACE5(( "  y advance: %f\n", slot->advance.y / 64.0 ));
     FT_TRACE5(( "  linear x advance: %f\n",
                 slot->linearHoriAdvance / 65536.0 ));
     FT_TRACE5(( "  linear y advance: %f\n",
                 slot->linearVertAdvance / 65536.0 ));
-    FT_TRACE5(( "\n" ));
-    FT_TRACE5(( "  bitmap %dx%d, %s (mode %d)\n",
-                slot->bitmap.width,
-                slot->bitmap.rows,
-                pixel_modes[slot->bitmap.pixel_mode],
-                slot->bitmap.pixel_mode ));
-    FT_TRACE5(( "\n" ));
 
     {
       FT_Glyph_Metrics*  metrics = &slot->metrics;
@@ -1782,7 +1826,7 @@
     if ( error )
       goto Exit;
 
-    if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) )
+    if ( FT_QALLOC( sfnt_ps, (FT_Long)length ) )
       goto Exit;
 
     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
@@ -1892,7 +1936,7 @@
       goto Exit;
     }
 
-    if ( FT_ALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
+    if ( FT_QALLOC( pfb_data, (FT_Long)pfb_len + 2 ) )
       goto Exit;
 
     pfb_data[0] = 0x80;
@@ -1956,7 +2000,7 @@
       {
         FT_TRACE3(( "    Write POST fragment #%d header (4-byte) to buffer"
                     " %p + 0x%08lx\n",
-                    i, pfb_data, pfb_lenpos ));
+                    i, (void*)pfb_data, pfb_lenpos ));
 
         if ( pfb_lenpos + 3 > pfb_len + 2 )
           goto Exit2;
@@ -1971,7 +2015,7 @@
 
         FT_TRACE3(( "    Write POST fragment #%d header (6-byte) to buffer"
                     " %p + 0x%08lx\n",
-                    i, pfb_data, pfb_pos ));
+                    i, (void*)pfb_data, pfb_pos ));
 
         if ( pfb_pos + 6 > pfb_len + 2 )
           goto Exit2;
@@ -1994,7 +2038,7 @@
 
       FT_TRACE3(( "    Load POST fragment #%d (%ld byte) to buffer"
                   " %p + 0x%08lx\n",
-                  i, rlen, pfb_data, pfb_pos ));
+                  i, rlen, (void*)pfb_data, pfb_pos ));
 
       error = FT_Stream_Read( stream, (FT_Byte *)pfb_data + pfb_pos, rlen );
       if ( error )
@@ -2092,7 +2136,7 @@
     if ( error )
       goto Exit;
 
-    if ( FT_ALLOC( sfnt_data, rlen ) )
+    if ( FT_QALLOC( sfnt_data, rlen ) )
       return error;
     error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, (FT_ULong)rlen );
     if ( error ) {
@@ -2566,7 +2610,7 @@
     FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
 
     /* add the face object to its driver's list */
-    if ( FT_NEW( node ) )
+    if ( FT_QNEW( node ) )
       goto Fail;
 
     node->data = face;
@@ -2681,10 +2725,10 @@
 #ifdef FT_DEBUG_LEVEL_TRACE
     if ( !error && face_index < 0 )
     {
-      FT_TRACE3(( "FT_Open_Face: The font has %ld face%s\n"
-                  "              and %ld named instance%s for face %ld\n",
+      FT_TRACE3(( "FT_Open_Face: The font has %ld face%s\n",
                   face->num_faces,
-                  face->num_faces == 1 ? "" : "s",
+                  face->num_faces == 1 ? "" : "s" ));
+      FT_TRACE3(( "              and %ld named instance%s for face %ld\n",
                   face->style_flags >> 16,
                   ( face->style_flags >> 16 ) == 1 ? "" : "s",
                   -face_index - 1 ));
@@ -2851,7 +2895,7 @@
     memory = face->memory;
 
     /* Allocate new size object and perform basic initialisation */
-    if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
+    if ( FT_ALLOC( size, clazz->size_object_size ) || FT_QNEW( node ) )
       goto Exit;
 
     size->face = face;
@@ -3088,10 +3132,12 @@
   }
 
 
-  FT_BASE_DEF( void )
+  FT_BASE_DEF( FT_Error )
   FT_Request_Metrics( FT_Face          face,
                       FT_Size_Request  req )
   {
+    FT_Error  error = FT_Err_Ok;
+
     FT_Size_Metrics*  metrics;
 
 
@@ -3182,8 +3228,18 @@
         scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
       }
 
-      metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
-      metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
+      scaled_w = ( scaled_w + 32 ) >> 6;
+      scaled_h = ( scaled_h + 32 ) >> 6;
+      if ( scaled_w > (FT_Long)FT_USHORT_MAX ||
+           scaled_h > (FT_Long)FT_USHORT_MAX )
+      {
+        FT_ERROR(( "FT_Request_Metrics: Resulting ppem size too large\n" ));
+        error = FT_ERR( Invalid_Pixel_Size );
+        goto Exit;
+      }
+
+      metrics->x_ppem = (FT_UShort)scaled_w;
+      metrics->y_ppem = (FT_UShort)scaled_h;
 
       ft_recompute_scaled_metrics( face, metrics );
     }
@@ -3193,6 +3249,9 @@
       metrics->x_scale = 1L << 16;
       metrics->y_scale = 1L << 16;
     }
+
+  Exit:
+    return error;
   }
 
 
@@ -3256,7 +3315,7 @@
   FT_Request_Size( FT_Face          face,
                    FT_Size_Request  req )
   {
-    FT_Error         error = FT_Err_Ok;
+    FT_Error         error;
     FT_Driver_Class  clazz;
     FT_ULong         strike_index;
 
@@ -3292,13 +3351,15 @@
        */
       error = FT_Match_Size( face, req, 0, &strike_index );
       if ( error )
-        return error;
+        goto Exit;
 
       return FT_Select_Size( face, (FT_Int)strike_index );
     }
     else
     {
-      FT_Request_Metrics( face, req );
+      error = FT_Request_Metrics( face, req );
+      if ( error )
+        goto Exit;
 
       FT_TRACE5(( "FT_Request_Size:\n" ));
     }
@@ -3321,6 +3382,7 @@
     }
 #endif
 
+  Exit:
     return error;
   }
 
@@ -3645,9 +3707,9 @@
           FT_CharMap  last_charmap = face->charmaps[face->num_charmaps - 1];
 
 
-          if ( FT_RENEW_ARRAY( face->charmaps,
-                               face->num_charmaps,
-                               face->num_charmaps - 1 ) )
+          if ( FT_QRENEW_ARRAY( face->charmaps,
+                                face->num_charmaps,
+                                face->num_charmaps - 1 ) )
             return;
 
           /* remove it from our list of charmaps */
@@ -3679,7 +3741,7 @@
                FT_CharMap     charmap,
                FT_CMap       *acmap )
   {
-    FT_Error   error = FT_Err_Ok;
+    FT_Error   error;
     FT_Face    face;
     FT_Memory  memory;
     FT_CMap    cmap = NULL;
@@ -3704,9 +3766,9 @@
       }
 
       /* add it to our list of charmaps */
-      if ( FT_RENEW_ARRAY( face->charmaps,
-                           face->num_charmaps,
-                           face->num_charmaps + 1 ) )
+      if ( FT_QRENEW_ARRAY( face->charmaps,
+                            face->num_charmaps,
+                            face->num_charmaps + 1 ) )
         goto Fail;
 
       face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
@@ -4400,7 +4462,7 @@
     FT_ListNode  node    = NULL;
 
 
-    if ( FT_NEW( node ) )
+    if ( FT_QNEW( node ) )
       goto Exit;
 
     {
@@ -4412,8 +4474,7 @@
       render->glyph_format = clazz->glyph_format;
 
       /* allocate raster object if needed */
-      if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
-           clazz->raster_class->raster_new                )
+      if ( clazz->raster_class->raster_new )
       {
         error = clazz->raster_class->raster_new( memory, &render->raster );
         if ( error )
@@ -4460,8 +4521,7 @@
 
 
       /* release raster object, if any */
-      if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
-           render->raster                                         )
+      if ( render->raster )
         render->clazz->raster_class->raster_done( render->raster );
 
       /* remove from list */
@@ -4556,9 +4616,6 @@
 
     switch ( slot->format )
     {
-    case FT_GLYPH_FORMAT_BITMAP:   /* already a bitmap, don't do anything */
-      break;
-
     default:
       if ( slot->internal->load_flags & FT_LOAD_COLOR )
       {
@@ -4646,7 +4703,7 @@
         else
           renderer = FT_Lookup_Renderer( library, slot->format, &node );
 
-        error = FT_ERR( Unimplemented_Feature );
+        error = FT_ERR( Cannot_Render_Glyph );
         while ( renderer )
         {
           error = renderer->render( renderer, slot, render_mode, NULL );
@@ -4662,6 +4719,11 @@
           /* format.                                               */
           renderer = FT_Lookup_Renderer( library, slot->format, &node );
         }
+
+        /* it is not an error if we cannot render a bitmap glyph */
+        if ( FT_ERR_EQ( error, Cannot_Render_Glyph ) &&
+             slot->format == FT_GLYPH_FORMAT_BITMAP  )
+          error = FT_Err_Ok;
       }
     }
 
@@ -4734,11 +4796,11 @@
 
     /* we use FT_TRACE7 in this block */
     if ( !error                               &&
-         ft_trace_levels[trace_checksum] >= 7 )
+         ft_trace_levels[trace_checksum] >= 7 &&
+         slot->bitmap.buffer                  )
     {
       if ( slot->bitmap.rows  < 128U &&
-           slot->bitmap.width < 128U &&
-           slot->bitmap.buffer       )
+           slot->bitmap.width < 128U )
       {
         int  rows  = (int)slot->bitmap.rows;
         int  width = (int)slot->bitmap.width;
@@ -5149,16 +5211,16 @@
 
     if ( cur == limit )
     {
-      FT_ERROR(( "%s: can't find module `%s'\n",
-                 func_name, module_name ));
+      FT_TRACE2(( "%s: can't find module `%s'\n",
+                  func_name, module_name ));
       return FT_THROW( Missing_Module );
     }
 
     /* check whether we have a service interface */
     if ( !cur[0]->clazz->get_interface )
     {
-      FT_ERROR(( "%s: module `%s' doesn't support properties\n",
-                 func_name, module_name ));
+      FT_TRACE2(( "%s: module `%s' doesn't support properties\n",
+                  func_name, module_name ));
       return FT_THROW( Unimplemented_Feature );
     }
 
@@ -5167,8 +5229,8 @@
                                               FT_SERVICE_ID_PROPERTIES );
     if ( !interface )
     {
-      FT_ERROR(( "%s: module `%s' doesn't support properties\n",
-                 func_name, module_name ));
+      FT_TRACE2(( "%s: module `%s' doesn't support properties\n",
+                  func_name, module_name ));
       return FT_THROW( Unimplemented_Feature );
     }
 
@@ -5181,8 +5243,8 @@
 
     if ( missing_func )
     {
-      FT_ERROR(( "%s: property service of module `%s' is broken\n",
-                 func_name, module_name ));
+      FT_TRACE2(( "%s: property service of module `%s' is broken\n",
+                  func_name, module_name ));
       return FT_THROW( Unimplemented_Feature );
     }
 
@@ -5292,10 +5354,12 @@
     if ( !memory || !alibrary )
       return FT_THROW( Invalid_Argument );
 
+#ifndef FT_DEBUG_LOGGING
 #ifdef FT_DEBUG_LEVEL_ERROR
     /* init debugging support */
     ft_debug_init();
-#endif
+#endif /* FT_DEBUG_LEVEL_ERROR */
+#endif /* !FT_DEBUG_LOGGING */
 
     /* first of all, allocate the library object */
     if ( FT_NEW( library ) )
@@ -5567,4 +5631,145 @@
   }
 
 
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Bool )
+  FT_Get_Color_Glyph_Paint( FT_Face                  face,
+                            FT_UInt                  base_glyph,
+                            FT_Color_Root_Transform  root_transform,
+                            FT_OpaquePaint*          paint )
+  {
+    TT_Face       ttface;
+    SFNT_Service  sfnt;
+
+
+    if ( !face || !paint )
+      return 0;
+
+    if ( !FT_IS_SFNT( face ) )
+      return 0;
+
+    ttface = (TT_Face)face;
+    sfnt   = (SFNT_Service)ttface->sfnt;
+
+    if ( sfnt->get_colr_layer )
+      return sfnt->get_colr_glyph_paint( ttface,
+                                         base_glyph,
+                                         root_transform,
+                                         paint );
+    else
+      return 0;
+  }
+
+
+  /* documentation is in ftcolor.h */
+
+  FT_EXPORT_DEF( FT_Bool )
+  FT_Get_Color_Glyph_ClipBox( FT_Face      face,
+                              FT_UInt      base_glyph,
+                              FT_ClipBox*  clip_box )
+  {
+    TT_Face       ttface;
+    SFNT_Service  sfnt;
+
+
+    if ( !face || !clip_box )
+      return 0;
+
+    if ( !FT_IS_SFNT( face ) )
+      return 0;
+
+    ttface = (TT_Face)face;
+    sfnt   = (SFNT_Service)ttface->sfnt;
+
+    if ( sfnt->get_color_glyph_clipbox )
+      return sfnt->get_color_glyph_clipbox( ttface,
+                                            base_glyph,
+                                            clip_box );
+    else
+      return 0;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Bool )
+  FT_Get_Paint_Layers( FT_Face            face,
+                       FT_LayerIterator*  layer_iterator,
+                       FT_OpaquePaint*    paint )
+  {
+    TT_Face       ttface;
+    SFNT_Service  sfnt;
+
+
+    if ( !face || !paint || !layer_iterator )
+      return 0;
+
+    if ( !FT_IS_SFNT( face ) )
+      return 0;
+
+    ttface = (TT_Face)face;
+    sfnt   = (SFNT_Service)ttface->sfnt;
+
+    if ( sfnt->get_paint_layers )
+      return sfnt->get_paint_layers( ttface, layer_iterator, paint );
+    else
+      return 0;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Bool )
+  FT_Get_Paint( FT_Face face,
+                FT_OpaquePaint  opaque_paint,
+                FT_COLR_Paint*  paint )
+  {
+    TT_Face       ttface;
+    SFNT_Service  sfnt;
+
+
+    if ( !face || !paint || !paint )
+      return 0;
+
+    if ( !FT_IS_SFNT( face ) )
+      return 0;
+
+    ttface = (TT_Face)face;
+    sfnt   = (SFNT_Service)ttface->sfnt;
+
+    if ( sfnt->get_paint )
+      return sfnt->get_paint( ttface, opaque_paint, paint );
+    else
+      return 0;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Bool )
+  FT_Get_Colorline_Stops ( FT_Face                face,
+                           FT_ColorStop *         color_stop,
+                           FT_ColorStopIterator  *iterator )
+  {
+    TT_Face       ttface;
+    SFNT_Service  sfnt;
+
+
+    if ( !face || !color_stop || !iterator )
+      return 0;
+
+    if ( !FT_IS_SFNT( face ) )
+      return 0;
+
+    ttface = (TT_Face)face;
+    sfnt   = (SFNT_Service)ttface->sfnt;
+
+    if ( sfnt->get_colorline_stops )
+      return sfnt->get_colorline_stops ( ttface, color_stop, iterator );
+    else
+      return 0;
+  }
+
+
 /* END */
diff --git a/src/base/ftotval.c b/src/base/ftotval.c
index 90a5dd6..0f748d0 100644
--- a/src/base/ftotval.c
+++ b/src/base/ftotval.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating OpenType tables (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index 311f098..98c6ca1 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -4,7 +4,7 @@
  *
  *   FreeType outline management (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftpatent.c b/src/base/ftpatent.c
index a02c636..cd192d3 100644
--- a/src/base/ftpatent.c
+++ b/src/base/ftpatent.c
@@ -5,7 +5,7 @@
  *   FreeType API for checking patented TrueType bytecode instructions
  *   (body).  Obsolete, retained for backward compatibility.
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftpfr.c b/src/base/ftpfr.c
index c656fcd..5afd5a1 100644
--- a/src/base/ftpfr.c
+++ b/src/base/ftpfr.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing PFR-specific data (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftpsprop.c b/src/base/ftpsprop.c
index 8c29f50..3655ae9 100644
--- a/src/base/ftpsprop.c
+++ b/src/base/ftpsprop.c
@@ -5,7 +5,7 @@
  *   Get and set properties of PostScript drivers (body).
  *   See `ftdriver.h' for available properties.
  *
- * Copyright (C) 2017-2020 by
+ * Copyright (C) 2017-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -220,7 +220,7 @@
       return error;
     }
 
-    FT_TRACE0(( "ps_property_set: missing property `%s'\n",
+    FT_TRACE2(( "ps_property_set: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
   }
@@ -275,7 +275,7 @@
       return error;
     }
 
-    FT_TRACE0(( "ps_property_get: missing property `%s'\n",
+    FT_TRACE2(( "ps_property_get: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
   }
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index f989be4..cb7e94d 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -4,7 +4,7 @@
  *
  *   Embedded resource forks accessor (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * Masatake YAMATO and Redhat K.K.
  *
  * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
@@ -167,16 +167,11 @@
   }
 
 
-  static int
-  ft_raccess_sort_ref_by_id( FT_RFork_Ref*  a,
-                             FT_RFork_Ref*  b )
+  FT_COMPARE_DEF( int )
+  ft_raccess_sort_ref_by_id( const void*  a,
+                             const void*  b )
   {
-    if ( a->res_id < b->res_id )
-      return -1;
-    else if ( a->res_id > b->res_id )
-      return 1;
-    else
-      return 0;
+    return  ( (FT_RFork_Ref*)a )->res_id - ( (FT_RFork_Ref*)b )->res_id;
   }
 
 
@@ -256,7 +251,7 @@
         if ( error )
           return error;
 
-        if ( FT_NEW_ARRAY( ref, *count ) )
+        if ( FT_QNEW_ARRAY( ref, *count ) )
           return error;
 
         for ( j = 0; j < *count; j++ )
@@ -294,8 +289,7 @@
           ft_qsort( ref,
                     (size_t)*count,
                     sizeof ( FT_RFork_Ref ),
-                    ( int(*)(const void*,
-                             const void*) )ft_raccess_sort_ref_by_id );
+                    ft_raccess_sort_ref_by_id );
 
           FT_TRACE3(( "             -- sort resources by their ids --\n" ));
 
@@ -305,7 +299,7 @@
                         j, ref[j].res_id, ref[j].offset ));
         }
 
-        if ( FT_NEW_ARRAY( offsets_internal, *count ) )
+        if ( FT_QNEW_ARRAY( offsets_internal, *count ) )
           goto Exit;
 
         /* XXX: duplicated reference ID,
@@ -608,7 +602,7 @@
     if ( base_file_len + 6 > FT_INT_MAX )
       return FT_THROW( Array_Too_Large );
 
-    if ( FT_ALLOC( newpath, base_file_len + 6 ) )
+    if ( FT_QALLOC( newpath, base_file_len + 6 ) )
       return error;
 
     FT_MEM_COPY( newpath, base_file_name, base_file_len );
@@ -644,7 +638,7 @@
     if ( base_file_len + 18 > FT_INT_MAX )
       return FT_THROW( Array_Too_Large );
 
-    if ( FT_ALLOC( newpath, base_file_len + 18 ) )
+    if ( FT_QALLOC( newpath, base_file_len + 18 ) )
       return error;
 
     FT_MEM_COPY( newpath, base_file_name, base_file_len );
@@ -880,7 +874,7 @@
 
 
     new_length = ft_strlen( original_name ) + ft_strlen( insertion );
-    if ( FT_ALLOC( new_name, new_length + 1 ) )
+    if ( FT_QALLOC( new_name, new_length + 1 ) )
       return NULL;
 
     tmp = ft_strrchr( original_name, '/' );
diff --git a/src/base/ftsnames.c b/src/base/ftsnames.c
index 8507f28..44dba66 100644
--- a/src/base/ftsnames.c
+++ b/src/base/ftsnames.c
@@ -7,7 +7,7 @@
  *
  *   This is _not_ used to retrieve glyph names!
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -65,7 +65,7 @@
           FT_Stream  stream = face->stream;
 
 
-          if ( FT_NEW_ARRAY  ( entry->string, entry->stringLength ) ||
+          if ( FT_QNEW_ARRAY ( entry->string, entry->stringLength ) ||
                FT_STREAM_SEEK( entry->stringOffset )                ||
                FT_STREAM_READ( entry->string, entry->stringLength ) )
           {
@@ -121,7 +121,7 @@
           FT_Stream  stream = face->stream;
 
 
-          if ( FT_NEW_ARRAY  ( entry->string, entry->stringLength ) ||
+          if ( FT_QNEW_ARRAY ( entry->string, entry->stringLength ) ||
                FT_STREAM_SEEK( entry->stringOffset )                ||
                FT_STREAM_READ( entry->string, entry->stringLength ) )
           {
diff --git a/src/base/ftstream.c b/src/base/ftstream.c
index d940254..5992998 100644
--- a/src/base/ftstream.c
+++ b/src/base/ftstream.c
@@ -4,7 +4,7 @@
  *
  *   I/O stream support (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -61,7 +61,7 @@
 
     if ( stream->read )
     {
-      if ( stream->read( stream, pos, 0, 0 ) )
+      if ( stream->read( stream, pos, NULL, 0 ) )
       {
         FT_ERROR(( "FT_Stream_Seek:"
                    " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
@@ -347,17 +347,17 @@
   }
 
 
-  FT_BASE_DEF( FT_Char )
-  FT_Stream_GetChar( FT_Stream  stream )
+  FT_BASE_DEF( FT_Byte )
+  FT_Stream_GetByte( FT_Stream  stream )
   {
-    FT_Char  result;
+    FT_Byte  result;
 
 
     FT_ASSERT( stream && stream->cursor );
 
     result = 0;
     if ( stream->cursor < stream->limit )
-      result = (FT_Char)*stream->cursor++;
+      result = *stream->cursor++;
 
     return result;
   }
@@ -455,8 +455,8 @@
   }
 
 
-  FT_BASE_DEF( FT_Char )
-  FT_Stream_ReadChar( FT_Stream  stream,
+  FT_BASE_DEF( FT_Byte )
+  FT_Stream_ReadByte( FT_Stream  stream,
                       FT_Error*  error )
   {
     FT_Byte  result = 0;
@@ -464,31 +464,32 @@
 
     FT_ASSERT( stream );
 
-    *error = FT_Err_Ok;
-
-    if ( stream->read )
+    if ( stream->pos < stream->size )
     {
-      if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
-        goto Fail;
+      if ( stream->read )
+      {
+        if ( stream->read( stream, stream->pos, &result, 1L ) != 1L )
+          goto Fail;
+      }
+      else
+        result = stream->base[stream->pos];
     }
     else
-    {
-      if ( stream->pos < stream->size )
-        result = stream->base[stream->pos];
-      else
-        goto Fail;
-    }
+      goto Fail;
+
     stream->pos++;
 
-    return (FT_Char)result;
+    *error = FT_Err_Ok;
+
+    return result;
 
   Fail:
     *error = FT_THROW( Invalid_Stream_Operation );
-    FT_ERROR(( "FT_Stream_ReadChar:"
+    FT_ERROR(( "FT_Stream_ReadByte:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
-    return 0;
+    return result;
   }
 
 
@@ -497,14 +498,12 @@
                         FT_Error*  error )
   {
     FT_Byte    reads[2];
-    FT_Byte*   p      = 0;
+    FT_Byte*   p;
     FT_UShort  result = 0;
 
 
     FT_ASSERT( stream );
 
-    *error = FT_Err_Ok;
-
     if ( stream->pos + 1 < stream->size )
     {
       if ( stream->read )
@@ -525,6 +524,8 @@
 
     stream->pos += 2;
 
+    *error = FT_Err_Ok;
+
     return result;
 
   Fail:
@@ -533,7 +534,7 @@
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
-    return 0;
+    return result;
   }
 
 
@@ -542,14 +543,12 @@
                           FT_Error*  error )
   {
     FT_Byte    reads[2];
-    FT_Byte*   p      = 0;
+    FT_Byte*   p;
     FT_UShort  result = 0;
 
 
     FT_ASSERT( stream );
 
-    *error = FT_Err_Ok;
-
     if ( stream->pos + 1 < stream->size )
     {
       if ( stream->read )
@@ -570,6 +569,8 @@
 
     stream->pos += 2;
 
+    *error = FT_Err_Ok;
+
     return result;
 
   Fail:
@@ -578,7 +579,7 @@
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
-    return 0;
+    return result;
   }
 
 
@@ -587,14 +588,12 @@
                          FT_Error*  error )
   {
     FT_Byte   reads[3];
-    FT_Byte*  p      = 0;
+    FT_Byte*  p;
     FT_ULong  result = 0;
 
 
     FT_ASSERT( stream );
 
-    *error = FT_Err_Ok;
-
     if ( stream->pos + 2 < stream->size )
     {
       if ( stream->read )
@@ -615,6 +614,8 @@
 
     stream->pos += 3;
 
+    *error = FT_Err_Ok;
+
     return result;
 
   Fail:
@@ -623,7 +624,7 @@
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
-    return 0;
+    return result;
   }
 
 
@@ -632,14 +633,12 @@
                        FT_Error*  error )
   {
     FT_Byte   reads[4];
-    FT_Byte*  p      = 0;
+    FT_Byte*  p;
     FT_ULong  result = 0;
 
 
     FT_ASSERT( stream );
 
-    *error = FT_Err_Ok;
-
     if ( stream->pos + 3 < stream->size )
     {
       if ( stream->read )
@@ -660,6 +659,8 @@
 
     stream->pos += 4;
 
+    *error = FT_Err_Ok;
+
     return result;
 
   Fail:
@@ -668,7 +669,7 @@
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
-    return 0;
+    return result;
   }
 
 
@@ -677,14 +678,12 @@
                          FT_Error*  error )
   {
     FT_Byte   reads[4];
-    FT_Byte*  p      = 0;
+    FT_Byte*  p;
     FT_ULong  result = 0;
 
 
     FT_ASSERT( stream );
 
-    *error = FT_Err_Ok;
-
     if ( stream->pos + 3 < stream->size )
     {
       if ( stream->read )
@@ -705,6 +704,8 @@
 
     stream->pos += 4;
 
+    *error = FT_Err_Ok;
+
     return result;
 
   Fail:
@@ -713,7 +714,7 @@
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
 
-    return 0;
+    return result;
   }
 
 
diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c
index 56f98e1..37e9649 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -4,7 +4,7 @@
  *
  *   FreeType path stroker (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -974,7 +974,8 @@
     FT_StrokeBorder  border = stroker->borders + side;
     FT_Angle         phi, theta, rotate;
     FT_Fixed         length;
-    FT_Vector        sigma, delta;
+    FT_Vector        sigma = { 0, 0 };
+    FT_Vector        delta;
     FT_Error         error = FT_Err_Ok;
     FT_Bool          intersect;          /* use intersection of lines? */
 
@@ -1048,7 +1049,7 @@
     {
       /* this is a mitered (pointed) or beveled (truncated) corner */
       FT_Fixed   radius = stroker->radius;
-      FT_Vector  sigma;
+      FT_Vector  sigma = { 0, 0 };
       FT_Angle   theta = 0, phi = 0;
       FT_Bool    bevel, fixed_bevel;
 
@@ -1528,7 +1529,8 @@
       stroker->angle_in = angle_out;
     }
 
-    stroker->center = *to;
+    stroker->center      = *to;
+    stroker->line_length = 0;
 
   Exit:
     return error;
@@ -1744,7 +1746,8 @@
       stroker->angle_in = angle_out;
     }
 
-    stroker->center = *to;
+    stroker->center      = *to;
+    stroker->line_length = 0;
 
   Exit:
     return error;
@@ -1897,13 +1900,9 @@
     }
     else
     {
-      FT_Angle  turn;
-      FT_Int    inside_side;
-
-
       /* close the path if needed */
-      if ( stroker->center.x != stroker->subpath_start.x ||
-           stroker->center.y != stroker->subpath_start.y )
+      if ( !FT_IS_SMALL( stroker->center.x - stroker->subpath_start.x ) ||
+           !FT_IS_SMALL( stroker->center.y - stroker->subpath_start.y ) )
       {
          error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
          if ( error )
@@ -1912,29 +1911,11 @@
 
       /* process the corner */
       stroker->angle_out = stroker->subpath_angle;
-      turn               = FT_Angle_Diff( stroker->angle_in,
-                                          stroker->angle_out );
 
-      /* no specific corner processing is required if the turn is 0 */
-      if ( turn != 0 )
-      {
-        /* when we turn to the right, the inside side is 0 */
-        /* otherwise, the inside side is 1 */
-        inside_side = ( turn < 0 );
-
-        error = ft_stroker_inside( stroker,
-                                   inside_side,
-                                   stroker->subpath_line_length );
-        if ( error )
-          goto Exit;
-
-        /* process the outside side */
-        error = ft_stroker_outside( stroker,
-                                    !inside_side,
-                                    stroker->subpath_line_length );
-        if ( error )
-          goto Exit;
-      }
+      error = ft_stroker_process_corner( stroker,
+                                         stroker->subpath_line_length );
+      if ( error )
+        goto Exit;
 
       /* then end our two subpaths */
       ft_stroke_border_close( stroker->borders + 0, FALSE );
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index a9119e2..73565b1 100644
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -4,7 +4,7 @@
  *
  *   FreeType synthesizing code for emboldening and slanting (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c
index 3013cbd..9beb7e2 100644
--- a/src/base/ftsystem.c
+++ b/src/base/ftsystem.c
@@ -4,7 +4,7 @@
  *
  *   ANSI-specific FreeType low-level system interface (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -275,7 +275,7 @@
     stream->close = ft_ansi_stream_close;
 
     FT_TRACE1(( "FT_Stream_Open:" ));
-    FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
+    FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
                 filepathname, stream->size ));
 
     return FT_Err_Ok;
diff --git a/src/base/fttrigon.c b/src/base/fttrigon.c
index c6f027c..0ca6d78 100644
--- a/src/base/fttrigon.c
+++ b/src/base/fttrigon.c
@@ -4,7 +4,7 @@
  *
  *   FreeType trigonometric functions (body).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -53,7 +53,7 @@
   };
 
 
-#ifdef FT_LONG64
+#ifdef FT_INT64
 
   /* multiply a given value by the CORDIC shrink factor */
   static FT_Fixed
@@ -76,7 +76,7 @@
     return s < 0 ? -val : val;
   }
 
-#else /* !FT_LONG64 */
+#else /* !FT_INT64 */
 
   /* multiply a given value by the CORDIC shrink factor */
   static FT_Fixed
@@ -125,7 +125,7 @@
     return s < 0 ? -val : val;
   }
 
-#endif /* !FT_LONG64 */
+#endif /* !FT_INT64 */
 
 
   /* undefined and never called for zero vector */
diff --git a/src/base/fttype1.c b/src/base/fttype1.c
index be60ed6..0d0afbc 100644
--- a/src/base/fttype1.c
+++ b/src/base/fttype1.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for PS names support (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftutil.c b/src/base/ftutil.c
index d90cfbc..3142fae 100644
--- a/src/base/ftutil.c
+++ b/src/base/ftutil.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for memory and list management (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/ftver.rc b/src/base/ftver.rc
index 0b92e9b..a3d05b3 100644
--- a/src/base/ftver.rc
+++ b/src/base/ftver.rc
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType VERSIONINFO resource for Windows DLLs.                      */
 /*                                                                         */
-/*  Copyright (C) 2018-2020 by                                             */
+/*  Copyright (C) 2018-2021 by                                             */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,8 +18,8 @@
 
 #include<windows.h>
 
-#define FT_VERSION      2,10,4,0
-#define FT_VERSION_STR  "2.10.4"
+#define FT_VERSION      2,11,1,0
+#define FT_VERSION_STR  "2.11.1"
 
 VS_VERSION_INFO      VERSIONINFO
 FILEVERSION          FT_VERSION
@@ -45,7 +45,7 @@
       VALUE "FileVersion",      FT_VERSION_STR
       VALUE "ProductName",      "FreeType"
       VALUE "ProductVersion",   FT_VERSION_STR
-      VALUE "LegalCopyright",   "\251 2000-2020 The FreeType Project www.freetype.org. All rights reserved."
+      VALUE "LegalCopyright",   "\251 2000-2021 The FreeType Project www.freetype.org. All rights reserved."
       VALUE "InternalName",     "freetype"
       VALUE "OriginalFilename", FT_FILENAME
     END
diff --git a/src/base/ftwinfnt.c b/src/base/ftwinfnt.c
index 699dc3d..98f197a 100644
--- a/src/base/ftwinfnt.c
+++ b/src/base/ftwinfnt.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing Windows FNT specific info (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/base/rules.mk b/src/base/rules.mk
index 411c4c8..53289ae 100644
--- a/src/base/rules.mk
+++ b/src/base/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/bdf/bdfdrivr.c b/src/bdf/bdfdrivr.c
index d29188b..eb73a7c 100644
--- a/src/bdf/bdfdrivr.c
+++ b/src/bdf/bdfdrivr.c
@@ -276,7 +276,7 @@
       char*  s;
 
 
-      if ( FT_ALLOC( face->style_name, len ) )
+      if ( FT_QALLOC( face->style_name, len ) )
         return error;
 
       s = face->style_name;
@@ -442,7 +442,7 @@
       bdfface->num_glyphs = (FT_Long)( font->glyphs_size + 1 );
 
       bdfface->num_fixed_sizes = 1;
-      if ( FT_NEW_ARRAY( bdfface->available_sizes, 1 ) )
+      if ( FT_NEW( bdfface->available_sizes ) )
         goto Exit;
 
       {
@@ -451,8 +451,6 @@
         long             value;
 
 
-        FT_ZERO( bsize );
-
         /* sanity checks */
         if ( font->font_ascent > 0x7FFF || font->font_ascent < -0x7FFF )
         {
@@ -489,7 +487,7 @@
         else
         {
           /* this is a heuristical value */
-          bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 );
+          bsize->width = ( bsize->height * 2 + 1 ) / 3;
         }
 
         prop = bdf_get_font_property( font, "POINT_SIZE" );
@@ -608,7 +606,7 @@
         unsigned long  n;
 
 
-        if ( FT_NEW_ARRAY( face->en_table, font->glyphs_size ) )
+        if ( FT_QNEW_ARRAY( face->en_table, font->glyphs_size ) )
           goto Exit;
 
         face->default_glyph = 0;
diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c
index a4ddb9a..b65c8a2 100644
--- a/src/bdf/bdflib.c
+++ b/src/bdf/bdflib.c
@@ -170,7 +170,7 @@
 
   /* An auxiliary macro to parse properties, to be used in conditionals. */
   /* It behaves like `strncmp' but also tests the following character    */
-  /* whether it is a whitespace or NULL.                                 */
+  /* whether it is a whitespace or null.                                 */
   /* `property' is a constant string of length `n' to compare with.      */
 #define _bdf_strncmp( name, property, n )      \
           ( ft_strncmp( name, property, n ) || \
@@ -185,12 +185,12 @@
                  "Added `FONT_ASCENT %hd'.\n"
 #define ACMSG2   "FONT_DESCENT property missing.  " \
                  "Added `FONT_DESCENT %hd'.\n"
-#define ACMSG3   "Font width != actual width.  Old: %hd New: %hd.\n"
+#define ACMSG3   "Font width != actual width.  Old: %d New: %d.\n"
 #define ACMSG4   "Font left bearing != actual left bearing.  " \
                  "Old: %hd New: %hd.\n"
 #define ACMSG5   "Font ascent != actual ascent.  Old: %hd New: %hd.\n"
-#define ACMSG6   "Font descent != actual descent.  Old: %hd New: %hd.\n"
-#define ACMSG7   "Font height != actual height. Old: %hd New: %hd.\n"
+#define ACMSG6   "Font descent != actual descent.  Old: %d New: %d.\n"
+#define ACMSG7   "Font height != actual height. Old: %d New: %d.\n"
 #define ACMSG8   "Glyph scalable width (SWIDTH) adjustments made.\n"
 #define ACMSG9   "SWIDTH field missing at line %ld.  Set automatically.\n"
 #define ACMSG10  "DWIDTH field missing at line %ld.  Set to glyph width.\n"
@@ -328,7 +328,7 @@
       else if ( newsize < oldsize || newsize > bigsize )
         newsize = bigsize;
 
-      if ( FT_RENEW_ARRAY( list->field, oldsize, newsize ) )
+      if ( FT_QRENEW_ARRAY( list->field, oldsize, newsize ) )
         goto Exit;
 
       list->size = newsize;
@@ -346,7 +346,7 @@
     unsigned long  i, u;
 
 
-    if ( list == 0 || list->used == 0 || n == 0 )
+    if ( list == NULL || list->used == 0 || n == 0 )
       return;
 
     if ( n >= list->used )
@@ -377,7 +377,7 @@
 
     *alen = 0;
 
-    if ( list == 0 || list->used == 0 )
+    if ( list == NULL || list->used == 0 )
       return 0;
 
     dp = list->field[0];
@@ -436,7 +436,7 @@
     /* In the original code, if the `separators' parameter is NULL or */
     /* empty, the list is split into individual bytes.  We don't need */
     /* this, so an error is signaled.                                 */
-    if ( separators == 0 || *separators == 0 )
+    if ( separators == NULL || *separators == 0 )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
@@ -504,7 +504,7 @@
     if ( final_empty )
       list->field[list->used++] = (char*)empty;
 
-    list->field[list->used] = 0;
+    list->field[list->used] = NULL;
 
   Exit:
     return error;
@@ -529,7 +529,7 @@
     FT_Error          error  = FT_Err_Ok;
 
 
-    if ( callback == 0 )
+    if ( callback == NULL )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
@@ -538,7 +538,7 @@
     /* initial size and allocation of the input buffer */
     buf_size = 1024;
 
-    if ( FT_NEW_ARRAY( buf, buf_size ) )
+    if ( FT_QALLOC( buf, buf_size ) )
       goto Exit;
 
     cb      = callback;
@@ -581,8 +581,14 @@
       /* or even resizing it                                       */
       if ( end >= avail )
       {
-        if ( bytes == 0 )  /* last line in file doesn't end in \r or \n */
-          break;           /* ignore it then exit                       */
+        if ( bytes == 0 )
+        {
+          /* last line in file doesn't end in \r or \n; */
+          /* ignore it then exit                        */
+          if ( lineno == 1 )
+            error = FT_THROW( Missing_Startfont_Field );
+          break;
+        }
 
         if ( start == 0 )
         {
@@ -593,13 +599,18 @@
 
           if ( buf_size >= 65536UL )  /* limit ourselves to 64KByte */
           {
-            FT_ERROR(( "_bdf_readstream: " ERRMSG6, lineno ));
-            error = FT_THROW( Invalid_Argument );
+            if ( lineno == 1 )
+              error = FT_THROW( Missing_Startfont_Field );
+            else
+            {
+              FT_ERROR(( "_bdf_readstream: " ERRMSG6, lineno ));
+              error = FT_THROW( Invalid_Argument );
+            }
             goto Exit;
           }
 
           new_size = buf_size * 2;
-          if ( FT_RENEW_ARRAY( buf, buf_size, new_size ) )
+          if ( FT_QREALLOC( buf, buf_size, new_size ) )
             goto Exit;
 
           cursor   = (ptrdiff_t)buf_size;
@@ -697,7 +708,7 @@
     unsigned long  v;
 
 
-    if ( s == 0 || *s == 0 )
+    if ( s == NULL || *s == 0 )
       return 0;
 
     for ( v = 0; sbitset( ddigits, *s ); s++ )
@@ -722,7 +733,7 @@
     long  v, neg;
 
 
-    if ( s == 0 || *s == 0 )
+    if ( s == NULL || *s == 0 )
       return 0;
 
     /* Check for a minus sign. */
@@ -755,7 +766,7 @@
     unsigned short  v;
 
 
-    if ( s == 0 || *s == 0 )
+    if ( s == NULL || *s == 0 )
       return 0;
 
     for ( v = 0; sbitset( ddigits, *s ); s++ )
@@ -780,7 +791,7 @@
     short  v, neg;
 
 
-    if ( s == 0 || *s == 0 )
+    if ( s == NULL || *s == 0 )
       return 0;
 
     /* Check for a minus. */
@@ -807,7 +818,7 @@
 
 
   /* Routine to compare two glyphs by encoding so they can be sorted. */
-  static int
+  FT_COMPARE_DEF( int )
   by_encoding( const void*  a,
                const void*  b )
   {
@@ -844,25 +855,25 @@
     if ( ft_hash_str_lookup( name, &(font->proptbl) ) )
       goto Exit;
 
-    if ( FT_RENEW_ARRAY( font->user_props,
-                         font->nuser_props,
-                         font->nuser_props + 1 ) )
+    if ( FT_QRENEW_ARRAY( font->user_props,
+                          font->nuser_props,
+                          font->nuser_props + 1 ) )
       goto Exit;
 
     p = font->user_props + font->nuser_props;
-    FT_ZERO( p );
 
     n = ft_strlen( name ) + 1;
-    if ( n > FT_ULONG_MAX )
+    if ( n > FT_LONG_MAX )
       return FT_THROW( Invalid_Argument );
 
-    if ( FT_NEW_ARRAY( p->name, n ) )
+    if ( FT_QALLOC( p->name, n ) )
       goto Exit;
 
     FT_MEM_COPY( (char *)p->name, name, n );
 
-    p->format  = format;
-    p->builtin = 0;
+    p->format     = format;
+    p->builtin    = 0;
+    p->value.atom = NULL;  /* nothing is ever stored here */
 
     n = _num_bdf_properties + font->nuser_props;
 
@@ -884,7 +895,7 @@
     size_t*  propid;
 
 
-    if ( name == 0 || *name == 0 )
+    if ( name == NULL || *name == 0 )
       return 0;
 
     if ( ( propid = ft_hash_str_lookup( name, &(font->proptbl) ) ) == NULL )
@@ -942,15 +953,15 @@
     FT_Error   error  = FT_Err_Ok;
 
 
-    if ( FT_RENEW_ARRAY( font->comments,
-                         font->comments_len,
-                         font->comments_len + len + 1 ) )
+    if ( FT_QRENEW_ARRAY( font->comments,
+                          font->comments_len,
+                          font->comments_len + len + 1 ) )
       goto Exit;
 
     cp = font->comments + font->comments_len;
 
     FT_MEM_COPY( cp, comment, len );
-    cp[len] = '\n';
+    cp[len] = '\0';
 
     font->comments_len += len + 1;
 
@@ -975,7 +986,7 @@
     FT_UNUSED( lineno );        /* only used in debug mode */
 
 
-    if ( font == 0 || font->name == 0 || font->name[0] == 0 )
+    if ( font == NULL || font->name == NULL || font->name[0] == 0 )
     {
       error = FT_THROW( Invalid_Argument );
       goto Exit;
@@ -1159,21 +1170,12 @@
     /* Allocate another property if this is overflowing. */
     if ( font->props_used == font->props_size )
     {
-      if ( font->props_size == 0 )
-      {
-        if ( FT_NEW_ARRAY( font->props, 1 ) )
-          goto Exit;
-      }
-      else
-      {
-        if ( FT_RENEW_ARRAY( font->props,
-                             font->props_size,
-                             font->props_size + 1 ) )
-          goto Exit;
-      }
+      if ( FT_QRENEW_ARRAY( font->props,
+                            font->props_size,
+                            font->props_size + 1 ) )
+        goto Exit;
 
       fp = font->props + font->props_size;
-      FT_ZERO( fp );
       font->props_size++;
     }
 
@@ -1191,8 +1193,8 @@
     switch ( prop->format )
     {
     case BDF_ATOM:
-      fp->value.atom = 0;
-      if ( value != 0 && value[0] )
+      fp->value.atom = NULL;
+      if ( value && value[0] )
       {
         if ( FT_STRDUP( fp->value.atom, value ) )
           goto Exit;
@@ -1314,15 +1316,18 @@
     /* Check for a comment. */
     if ( _bdf_strncmp( line, "COMMENT", 7 ) == 0 )
     {
-      linelen -= 7;
-
-      s = line + 7;
-      if ( *s != 0 )
+      if ( p->opts->keep_comments )
       {
-        s++;
-        linelen--;
+        linelen -= 7;
+
+        s = line + 7;
+        if ( *s != 0 )
+        {
+          s++;
+          linelen--;
+        }
+        error = _bdf_add_comment( p->font, s, linelen );
       }
-      error = _bdf_add_comment( p->font, s, linelen );
       goto Exit;
     }
 
@@ -1438,7 +1443,7 @@
         goto Exit;
       }
 
-      if ( FT_NEW_ARRAY( p->glyph_name, slen + 1 ) )
+      if ( FT_QALLOC( p->glyph_name, slen + 1 ) )
         goto Exit;
 
       FT_MEM_COPY( p->glyph_name, s, slen + 1 );
@@ -1506,7 +1511,7 @@
       {
         /* Unencoded glyph.  Check whether it should */
         /* be added or not.                          */
-        if ( p->opts->keep_unencoded != 0 )
+        if ( p->opts->keep_unencoded )
         {
           /* Allocate the next unencoded glyph. */
           if ( font->unencoded_used == font->unencoded_size )
@@ -1619,20 +1624,20 @@
       if ( error )
         goto Exit;
 
-      glyph->swidth = (unsigned short)_bdf_atoul( p->list.field[1] );
+      glyph->swidth = _bdf_atous( p->list.field[1] );
       p->flags |= BDF_SWIDTH_;
 
       goto Exit;
     }
 
-    /* Expect the DWIDTH (scalable width) field next. */
+    /* Expect the DWIDTH (device width) field next. */
     if ( _bdf_strncmp( line, "DWIDTH", 6 ) == 0 )
     {
       error = _bdf_list_split( &p->list, " +", line, linelen );
       if ( error )
         goto Exit;
 
-      glyph->dwidth = (unsigned short)_bdf_atoul( p->list.field[1] );
+      glyph->dwidth = _bdf_atous( p->list.field[1] );
 
       if ( !( p->flags & BDF_SWIDTH_ ) )
       {
@@ -1687,7 +1692,7 @@
 
       /* If the BDF_CORRECT_METRICS flag is set, then adjust the SWIDTH */
       /* value if necessary.                                            */
-      if ( p->opts->correct_metrics != 0 )
+      if ( p->opts->correct_metrics )
       {
         /* Determine the point size of the glyph. */
         unsigned short  sw = (unsigned short)FT_MulDiv(
@@ -1735,7 +1740,7 @@
       else
         glyph->bytes = (unsigned short)bitmap_size;
 
-      if ( FT_NEW_ARRAY( glyph->bitmap, glyph->bytes ) )
+      if ( FT_ALLOC( glyph->bitmap, glyph->bytes ) )
         goto Exit;
 
       p->row    = 0;
@@ -1894,7 +1899,7 @@
     /* comments before the STARTFONT line for some reason.                */
     if ( _bdf_strncmp( line, "COMMENT", 7 ) == 0 )
     {
-      if ( p->opts->keep_comments != 0 && p->font != 0 )
+      if ( p->opts->keep_comments && p->font )
       {
         linelen -= 7;
 
@@ -1904,13 +1909,8 @@
           s++;
           linelen--;
         }
-
         error = _bdf_add_comment( p->font, s, linelen );
-        if ( error )
-          goto Exit;
-        /* here font is not defined! */
       }
-
       goto Exit;
     }
 
@@ -1927,14 +1927,13 @@
       }
 
       p->flags = BDF_START_;
-      font = p->font = 0;
+      font = p->font = NULL;
 
       if ( FT_NEW( font ) )
         goto Exit;
       p->font = font;
 
       font->memory = p->memory;
-      p->memory    = 0;
 
       { /* setup */
         size_t           i;
@@ -2055,7 +2054,7 @@
       /* Allowing multiple `FONT' lines (which is invalid) doesn't hurt... */
       FT_FREE( p->font->name );
 
-      if ( FT_NEW_ARRAY( p->font->name, slen + 1 ) )
+      if ( FT_QALLOC( p->font->name, slen + 1 ) )
         goto Exit;
       FT_MEM_COPY( p->font->name, s, slen + 1 );
 
@@ -2095,7 +2094,7 @@
         unsigned short bpp;
 
 
-        bpp = (unsigned short)_bdf_atos( p->list.field[4] );
+        bpp = _bdf_atous( p->list.field[4] );
 
         /* Only values 1, 2, 4, 8 are allowed for greymap fonts. */
         if ( bpp > 4 )
@@ -2174,34 +2173,32 @@
 
   FT_LOCAL_DEF( FT_Error )
   bdf_load_font( FT_Stream       stream,
-                 FT_Memory       extmemory,
+                 FT_Memory       memory,
                  bdf_options_t*  opts,
                  bdf_font_t*    *font )
   {
     unsigned long  lineno = 0; /* make compiler happy */
     _bdf_parse_t   *p     = NULL;
 
-    FT_Memory  memory = extmemory; /* needed for FT_NEW */
-    FT_Error   error  = FT_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( FT_NEW( p ) )
       goto Exit;
 
-    memory    = NULL;
-    p->opts   = (bdf_options_t*)( ( opts != 0 ) ? opts : &_bdf_opts );
+    p->opts   = (bdf_options_t*)( opts ? opts : &_bdf_opts );
     p->minlb  = 32767;
     p->size   = stream->size;
-    p->memory = extmemory;  /* only during font creation */
+    p->memory = memory;  /* only during font creation */
 
-    _bdf_list_init( &p->list, extmemory );
+    _bdf_list_init( &p->list, memory );
 
     error = _bdf_readstream( stream, _bdf_parse_start,
                              (void *)p, &lineno );
     if ( error )
       goto Fail;
 
-    if ( p->font != 0 )
+    if ( p->font )
     {
       /* If the font is not proportional, set the font's monowidth */
       /* field to the width of the font bounding box.              */
@@ -2282,22 +2279,7 @@
       }
     }
 
-    if ( p->font != 0 )
-    {
-      /* Make sure the comments are NULL terminated if they exist. */
-      memory = p->font->memory;
-
-      if ( p->font->comments_len > 0 )
-      {
-        if ( FT_RENEW_ARRAY( p->font->comments,
-                             p->font->comments_len,
-                             p->font->comments_len + 1 ) )
-          goto Fail;
-
-        p->font->comments[p->font->comments_len] = 0;
-      }
-    }
-    else if ( !error )
+    if ( !p->font && !error )
       error = FT_THROW( Invalid_File_Format );
 
     *font = p->font;
@@ -2307,8 +2289,6 @@
     {
       _bdf_list_done( &p->list );
 
-      memory = extmemory;
-
       FT_FREE( p->glyph_name );
       FT_FREE( p );
     }
@@ -2318,8 +2298,6 @@
   Fail:
     bdf_free_font( p->font );
 
-    memory = extmemory;
-
     FT_FREE( p->font );
 
     goto Exit;
@@ -2335,7 +2313,7 @@
     FT_Memory        memory;
 
 
-    if ( font == 0 )
+    if ( font == NULL )
       return;
 
     memory = font->memory;
@@ -2385,11 +2363,7 @@
     /* Free up the user defined properties. */
     for ( prop = font->user_props, i = 0;
           i < font->nuser_props; i++, prop++ )
-    {
       FT_FREE( prop->name );
-      if ( prop->format == BDF_ATOM )
-        FT_FREE( prop->value.atom );
-    }
 
     FT_FREE( font->user_props );
 
@@ -2404,7 +2378,7 @@
     size_t*  propid;
 
 
-    if ( font == 0 || font->props_size == 0 || name == 0 || *name == 0 )
+    if ( font == NULL || font->props_size == 0 || name == NULL || *name == 0 )
       return 0;
 
     propid = ft_hash_str_lookup( name, (FT_Hash)font->internal );
diff --git a/src/bzip2/ftbzip2.c b/src/bzip2/ftbzip2.c
index 411c5d2..296cea0 100644
--- a/src/bzip2/ftbzip2.c
+++ b/src/bzip2/ftbzip2.c
@@ -8,7 +8,7 @@
  * parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2010-2020 by
+ * Copyright (C) 2010-2021 by
  * Joel Klinghed.
  *
  * based on `src/gzip/ftgzip.c'
@@ -70,7 +70,7 @@
     FT_Pointer  p  = NULL;
 
 
-    (void)FT_ALLOC( p, sz );
+    FT_MEM_QALLOC( p, sz );
     return p;
   }
 
@@ -327,12 +327,13 @@
                              FT_ULong      count )
   {
     FT_Error  error = FT_Err_Ok;
-    FT_ULong  delta;
 
 
     for (;;)
     {
-      delta = (FT_ULong)( zip->limit - zip->cursor );
+      FT_ULong  delta = (FT_ULong)( zip->limit - zip->cursor );
+
+
       if ( delta >= count )
         delta = count;
 
@@ -494,7 +495,7 @@
 
     stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
     stream->pos   = 0;
-    stream->base  = 0;
+    stream->base  = NULL;
     stream->read  = ft_bzip2_stream_io;
     stream->close = ft_bzip2_stream_close;
 
diff --git a/src/bzip2/rules.mk b/src/bzip2/rules.mk
index eed0f4b..e584277 100644
--- a/src/bzip2/rules.mk
+++ b/src/bzip2/rules.mk
@@ -2,7 +2,7 @@
 # FreeType 2 BZIP2 support configuration rules
 #
 
-# Copyright (C) 2010-2020 by
+# Copyright (C) 2010-2021 by
 # Joel Klinghed.
 #
 # based on `src/lzw/rules.mk'
diff --git a/src/cache/ftcache.c b/src/cache/ftcache.c
index e90f463..ddd3e43 100644
--- a/src/cache/ftcache.c
+++ b/src/cache/ftcache.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType Caching sub-system (body only).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c
index 43ea314..1760c5f 100644
--- a/src/cache/ftcbasic.c
+++ b/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType basic cache interface (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -108,12 +108,16 @@
     if ( error || !face )
       return result;
 
+#ifdef FT_DEBUG_LEVEL_TRACE
     if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
+    {
       FT_TRACE1(( "ftc_basic_family_get_count:"
-                  " the number of glyphs in this face is %ld,\n"
-                  "                           "
-                  " which is too much and thus truncated\n",
+                  " the number of glyphs in this face is %ld,\n",
                   face->num_glyphs ));
+      FT_TRACE1(( "                           "
+                  " which is too much and thus truncated\n" ));
+    }
+#endif
 
     if ( !error )
       result = (FT_UInt)face->num_glyphs;
diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c
index 1c8e0f3..5bbf329 100644
--- a/src/cache/ftccache.c
+++ b/src/cache/ftccache.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType internal cache interface (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -90,15 +90,14 @@
   ftc_get_top_node_for_hash( FTC_Cache  cache,
                              FT_Offset  hash )
   {
-    FTC_Node*  pnode;
     FT_Offset  idx;
 
 
     idx = hash & cache->mask;
     if ( idx < cache->p )
       idx = hash & ( 2 * cache->mask + 1 );
-    pnode = cache->buckets + idx;
-    return pnode;
+
+    return cache->buckets + idx;
   }
 
 #endif /* !FTC_INLINE */
@@ -119,7 +118,7 @@
       FT_UFast  count = mask + p + 1;    /* number of buckets */
 
 
-      /* do we need to shrink the buckets array? */
+      /* do we need to expand the buckets array? */
       if ( cache->slack < 0 )
       {
         FTC_Node  new_list = NULL;
@@ -172,7 +171,7 @@
           cache->p = p + 1;
       }
 
-      /* do we need to expand the buckets array? */
+      /* do we need to shrink the buckets array? */
       else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD )
       {
         FT_UFast   old_index = p + mask;
@@ -189,7 +188,7 @@
 
 
           /* if we can't shrink the array, leave immediately */
-          if ( FT_RENEW_ARRAY( cache->buckets,
+          if ( FT_QRENEW_ARRAY( cache->buckets,
                                ( mask + 1 ) * 2, mask + 1 ) )
             break;
 
@@ -341,7 +340,7 @@
     cache->mask  = FTC_HASH_INITIAL_SIZE - 1;
     cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD;
 
-    (void)FT_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 );
+    FT_MEM_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 );
     return error;
   }
 
@@ -360,7 +359,7 @@
 
       for ( i = 0; i < count; i++ )
       {
-        FTC_Node  *pnode = cache->buckets + i, next, node = *pnode;
+        FTC_Node  node = cache->buckets[i], next;
 
 
         while ( node )
@@ -417,7 +416,7 @@
                  FTC_Node   node )
   {
     node->hash        = hash;
-    node->cache_index = (FT_UInt16)cache->index;
+    node->cache_index = (FT_UShort)cache->index;
     node->ref_count   = 0;
 
     ftc_node_hash_link( node, cache );
@@ -459,7 +458,7 @@
     {
       error = cache->clazz.node_new( &node, query, cache );
     }
-    FTC_CACHE_TRYLOOP_END( NULL );
+    FTC_CACHE_TRYLOOP_END( NULL )
 
     if ( error )
       node = NULL;
@@ -528,7 +527,7 @@
           goto NewNode;
         }
         else
-          pnode = &((*pnode)->link);
+          pnode = &(*pnode)->link;
       }
     }
 
@@ -571,8 +570,7 @@
     count = cache->p + cache->mask + 1;
     for ( i = 0; i < count; i++ )
     {
-      FTC_Node*  bucket = cache->buckets + i;
-      FTC_Node*  pnode  = bucket;
+      FTC_Node*  pnode = cache->buckets + i;
 
 
       for (;;)
diff --git a/src/cache/ftccache.h b/src/cache/ftccache.h
index 11698bb..4849b92 100644
--- a/src/cache/ftccache.h
+++ b/src/cache/ftccache.h
@@ -4,7 +4,7 @@
  *
  *   FreeType internal cache interface (specification).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -251,7 +251,7 @@
           goto NewNode_;                                                 \
         }                                                                \
         else                                                             \
-          _pnode = &((*_pnode)->link);                                   \
+          _pnode = &(*_pnode)->link;                                     \
       }                                                                  \
     }                                                                    \
                                                                          \
diff --git a/src/cache/ftccback.h b/src/cache/ftccback.h
index 542acb1..8185fe3 100644
--- a/src/cache/ftccback.h
+++ b/src/cache/ftccback.h
@@ -4,7 +4,7 @@
  *
  *   Callback functions of the caching sub-system (specification only).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftccmap.c b/src/cache/ftccmap.c
index 468c008..40b449b 100644
--- a/src/cache/ftccmap.c
+++ b/src/cache/ftccmap.c
@@ -4,7 +4,7 @@
  *
  *   FreeType CharMap cache (body)
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -273,12 +273,11 @@
     if ( error )
       goto Exit;
 
-    FT_ASSERT( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first ) <
-                FTC_CMAP_INDICES_MAX );
+    FT_ASSERT( char_code - FTC_CMAP_NODE( node )->first <
+               FTC_CMAP_INDICES_MAX );
 
     /* something rotten can happen with rogue clients */
-    if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >=
-                    FTC_CMAP_INDICES_MAX ) )
+    if ( char_code - FTC_CMAP_NODE( node )->first >= FTC_CMAP_INDICES_MAX )
       return 0; /* XXX: should return appropriate error */
 
     gindex = FTC_CMAP_NODE( node )->indices[char_code -
diff --git a/src/cache/ftcerror.h b/src/cache/ftcerror.h
index bedfd28..2c6faf6 100644
--- a/src/cache/ftcerror.h
+++ b/src/cache/ftcerror.h
@@ -4,7 +4,7 @@
  *
  *   Caching sub-system error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftcglyph.c b/src/cache/ftcglyph.c
index 7f5438a..52771c7 100644
--- a/src/cache/ftcglyph.c
+++ b/src/cache/ftcglyph.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Glyph Image (FT_Glyph) cache (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftcglyph.h b/src/cache/ftcglyph.h
index 5629545..cf00cdc 100644
--- a/src/cache/ftcglyph.h
+++ b/src/cache/ftcglyph.h
@@ -4,7 +4,7 @@
  *
  *   FreeType abstract glyph cache (specification).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftcimage.c b/src/cache/ftcimage.c
index 58ebad8..3f12a65 100644
--- a/src/cache/ftcimage.c
+++ b/src/cache/ftcimage.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Image cache (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftcimage.h b/src/cache/ftcimage.h
index a400788..8b28d6f 100644
--- a/src/cache/ftcimage.h
+++ b/src/cache/ftcimage.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Generic Image cache (specification)
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftcmanag.c b/src/cache/ftcmanag.c
index 436d41f..512de8a 100644
--- a/src/cache/ftcmanag.c
+++ b/src/cache/ftcmanag.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Cache Manager (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -357,7 +357,7 @@
   {
     FT_Error     error;
     FT_Memory    memory;
-    FTC_Manager  manager = 0;
+    FTC_Manager  manager = NULL;
 
 
     if ( !library )
@@ -368,7 +368,7 @@
 
     memory = library->memory;
 
-    if ( FT_NEW( manager ) )
+    if ( FT_QNEW( manager ) )
       goto Exit;
 
     if ( max_faces == 0 )
@@ -399,6 +399,10 @@
                       manager,
                       memory );
 
+    manager->nodes_list = NULL;
+    manager->num_nodes  = 0;
+    manager->num_caches = 0;
+
     *amanager = manager;
 
   Exit:
@@ -593,7 +597,7 @@
         goto Exit;
       }
 
-      if ( !FT_ALLOC( cache, clazz->cache_size ) )
+      if ( !FT_QALLOC( cache, clazz->cache_size ) )
       {
         cache->manager   = manager;
         cache->memory    = memory;
diff --git a/src/cache/ftcmanag.h b/src/cache/ftcmanag.h
index 6c6ec68..99aa926 100644
--- a/src/cache/ftcmanag.h
+++ b/src/cache/ftcmanag.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Cache Manager (specification).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c
index 8feed45..2cac6f9 100644
--- a/src/cache/ftcmru.c
+++ b/src/cache/ftcmru.c
@@ -4,7 +4,7 @@
  *
  *   FreeType MRU support (body).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -262,7 +262,7 @@
       if ( list->clazz.node_done )
         list->clazz.node_done( node, list->data );
     }
-    else if ( FT_ALLOC( node, list->clazz.node_size ) )
+    else if ( FT_QALLOC( node, list->clazz.node_size ) )
       goto Exit;
 
     error = list->clazz.node_init( node, key, list->data );
diff --git a/src/cache/ftcmru.h b/src/cache/ftcmru.h
index ac4f9b1..6befde3 100644
--- a/src/cache/ftcmru.h
+++ b/src/cache/ftcmru.h
@@ -4,7 +4,7 @@
  *
  *   Simple MRU list-cache (specification).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/ftcsbits.c b/src/cache/ftcsbits.c
index e0db930..362999f 100644
--- a/src/cache/ftcsbits.c
+++ b/src/cache/ftcsbits.c
@@ -4,7 +4,7 @@
  *
  *   FreeType sbits manager (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -52,10 +52,8 @@
       pitch = -pitch;
 
     size = (FT_ULong)pitch * bitmap->rows;
-    if ( !size )
-      return FT_Err_Ok;
 
-    if ( !FT_ALLOC( sbit->buffer, size ) )
+    if ( !FT_QALLOC( sbit->buffer, size ) )
       FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
 
     return error;
@@ -108,13 +106,12 @@
     FT_Error          error;
     FTC_GNode         gnode  = FTC_GNODE( snode );
     FTC_Family        family = gnode->family;
-    FT_Memory         memory = manager->memory;
     FT_Face           face;
     FTC_SBit          sbit;
     FTC_SFamilyClass  clazz;
 
 
-    if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )
+    if ( gindex - gnode->gindex >= snode->count )
     {
       FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
       return FT_THROW( Invalid_Argument );
@@ -123,8 +120,6 @@
     sbit  = snode->sbits + ( gindex - gnode->gindex );
     clazz = (FTC_SFamilyClass)family->clazz;
 
-    sbit->buffer = 0;
-
     error = clazz->family_load_glyph( family, gindex, manager, &face );
     if ( error )
       goto BadGlyph;
@@ -143,12 +138,13 @@
         goto BadGlyph;
       }
 
-      /* Check whether our values fit into 8-bit containers!    */
+      /* Check whether our values fit into 8/16-bit containers! */
       /* If this is not the case, our bitmap is too large       */
       /* and we will leave it as `missing' with sbit.buffer = 0 */
 
 #define CHECK_CHAR( d )  ( temp = (FT_Char)d, (FT_Int) temp == (FT_Int) d )
 #define CHECK_BYTE( d )  ( temp = (FT_Byte)d, (FT_UInt)temp == (FT_UInt)d )
+#define CHECK_SHRT( d )  ( temp = (FT_Short)d, (FT_Int)temp == (FT_Int) d )
 
       /* horizontal advance in pixels */
       xadvance = ( slot->advance.x + 32 ) >> 6;
@@ -156,7 +152,7 @@
 
       if ( !CHECK_BYTE( bitmap->rows  )     ||
            !CHECK_BYTE( bitmap->width )     ||
-           !CHECK_CHAR( bitmap->pitch )     ||
+           !CHECK_SHRT( bitmap->pitch )     ||
            !CHECK_CHAR( slot->bitmap_left ) ||
            !CHECK_CHAR( slot->bitmap_top  ) ||
            !CHECK_CHAR( xadvance )          ||
@@ -169,7 +165,7 @@
 
       sbit->width     = (FT_Byte)bitmap->width;
       sbit->height    = (FT_Byte)bitmap->rows;
-      sbit->pitch     = (FT_Char)bitmap->pitch;
+      sbit->pitch     = (FT_Short)bitmap->pitch;
       sbit->left      = (FT_Char)slot->bitmap_left;
       sbit->top       = (FT_Char)slot->bitmap_top;
       sbit->xadvance  = (FT_Char)xadvance;
@@ -177,8 +173,17 @@
       sbit->format    = (FT_Byte)bitmap->pixel_mode;
       sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
 
-      /* copy the bitmap into a new buffer -- ignore error */
-      error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
+      if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+      {
+        /* take the bitmap ownership */
+        sbit->buffer = bitmap->buffer;
+        slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+      }
+      else
+      {
+        /* copy the bitmap into a new buffer -- ignore error */
+        error = ftc_sbit_copy_bitmap( sbit, bitmap, manager->memory );
+      }
 
       /* now, compute size */
       if ( asize )
@@ -337,8 +342,8 @@
 
     if (list_changed)
       *list_changed = FALSE;
-    result = FT_BOOL( gnode->family == gquery->family                    &&
-                      (FT_UInt)( gindex - gnode->gindex ) < snode->count );
+    result = FT_BOOL( gnode->family == gquery->family       &&
+                      gindex - gnode->gindex < snode->count );
     if ( result )
     {
       /* check if we need to load the glyph bitmap now */
@@ -390,7 +395,7 @@
         {
           error = ftc_snode_load( snode, cache->manager, gindex, &size );
         }
-        FTC_CACHE_TRYLOOP_END( list_changed );
+        FTC_CACHE_TRYLOOP_END( list_changed )
 
         ftcsnode->ref_count--;  /* unlock the node */
 
diff --git a/src/cache/ftcsbits.h b/src/cache/ftcsbits.h
index 46f797e..9f2d5fb 100644
--- a/src/cache/ftcsbits.h
+++ b/src/cache/ftcsbits.h
@@ -4,7 +4,7 @@
  *
  *   A small-bitmap cache (specification).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cache/rules.mk b/src/cache/rules.mk
index 4738b51..0abd216 100644
--- a/src/cache/rules.mk
+++ b/src/cache/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2000-2020 by
+# Copyright (C) 2000-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/cff/cff.c b/src/cff/cff.c
index 0fa6c87..c2ffea3 100644
--- a/src/cff/cff.c
+++ b/src/cff/cff.c
@@ -4,7 +4,7 @@
  *
  *   FreeType OpenType driver component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cffcmap.c b/src/cff/cffcmap.c
index 6d16ed4..ff1aae6 100644
--- a/src/cff/cffcmap.c
+++ b/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
  *
  *   CFF character mapping table (cmap) support (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cffcmap.h b/src/cff/cffcmap.h
index 69fab8d..221e255 100644
--- a/src/cff/cffcmap.h
+++ b/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
  *
  *   CFF character mapping table (cmap) support (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index 486ab24..59210f3 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
  *
  *   OpenType font driver implementation (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -345,8 +345,8 @@
       else
       {
         FT_ERROR(( "cff_get_glyph_name:"
-                   " cannot get glyph name from a CFF2 font\n"
-                   "                   "
+                   " cannot get glyph name from a CFF2 font\n" ));
+        FT_ERROR(( "                   "
                    " without the `psnames' module\n" ));
         error = FT_THROW( Missing_Module );
         goto Exit;
@@ -356,8 +356,8 @@
     if ( !font->psnames )
     {
       FT_ERROR(( "cff_get_glyph_name:"
-                 " cannot get glyph name from CFF & CEF fonts\n"
-                 "                   "
+                 " cannot get glyph name from CFF & CEF fonts\n" ));
+      FT_ERROR(( "                   "
                  " without the `psnames' module\n" ));
       error = FT_THROW( Missing_Module );
       goto Exit;
@@ -412,8 +412,8 @@
       else
       {
         FT_ERROR(( "cff_get_name_index:"
-                   " cannot get glyph index from a CFF2 font\n"
-                   "                   "
+                   " cannot get glyph index from a CFF2 font\n" ));
+        FT_ERROR(( "                   "
                    " without the `psnames' module\n" ));
         return 0;
       }
@@ -474,11 +474,11 @@
     if ( cff && !cff->font_info )
     {
       CFF_FontRecDict  dict      = &cff->top_font.font_dict;
-      PS_FontInfoRec  *font_info = NULL;
       FT_Memory        memory    = face->root.memory;
+      PS_FontInfoRec*  font_info = NULL;
 
 
-      if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
+      if ( FT_QNEW( font_info ) )
         goto Fail;
 
       font_info->version     = cff_index_get_sid_string( cff,
@@ -515,15 +515,15 @@
     FT_Error  error = FT_Err_Ok;
 
 
-    if ( cff && cff->font_extra == NULL )
+    if ( cff && !cff->font_extra )
     {
       CFF_FontRecDict   dict       = &cff->top_font.font_dict;
-      PS_FontExtraRec*  font_extra = NULL;
       FT_Memory         memory     = face->root.memory;
+      PS_FontExtraRec*  font_extra = NULL;
       FT_String*        embedded_postscript;
 
 
-      if ( FT_ALLOC( font_extra, sizeof ( *font_extra ) ) )
+      if ( FT_QNEW( font_extra ) )
         goto Fail;
 
       font_extra->fs_type = 0U;
diff --git a/src/cff/cffdrivr.h b/src/cff/cffdrivr.h
index d198dd3..fce92bb 100644
--- a/src/cff/cffdrivr.h
+++ b/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
  *
  *   High-level OpenType driver interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cfferrs.h b/src/cff/cfferrs.h
index 5b00a3f..b507ec8 100644
--- a/src/cff/cfferrs.h
+++ b/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
  *
  *   CFF error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index feee38a..97e8f9c 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -59,7 +59,7 @@
 
 
       *pointer = (FT_Byte*)data.pointer;
-      *length  = (FT_ULong)data.length;
+      *length  = data.length;
 
       return error;
     }
@@ -94,7 +94,7 @@
 
 
       data.pointer = *pointer;
-      data.length  = (FT_Int)length;
+      data.length  = (FT_UInt)length;
 
       face->root.internal->incremental_interface->funcs->free_glyph_data(
         face->root.internal->incremental_interface->object, &data );
diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h
index 3b312f4..d0d6a6f 100644
--- a/src/cff/cffgload.h
+++ b/src/cff/cffgload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 73d3eec..3c3f6fe 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -4,7 +4,7 @@
  *
  *   OpenType and CFF data/program tables loader (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -356,9 +356,9 @@
 
       data_size = (FT_ULong)( idx->count + 1 ) * offsize;
 
-      if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
-           FT_STREAM_SEEK( idx->start + idx->hdr_size ) ||
-           FT_FRAME_ENTER( data_size )                  )
+      if ( FT_QNEW_ARRAY( idx->offsets, idx->count + 1 ) ||
+           FT_STREAM_SEEK( idx->start + idx->hdr_size )  ||
+           FT_FRAME_ENTER( data_size )                   )
         goto Exit;
 
       poff   = idx->offsets;
@@ -400,7 +400,7 @@
 
   /* Allocate a table containing pointers to an index's elements. */
   /* The `pool' argument makes this function convert the index    */
-  /* entries to C-style strings (this is, NULL-terminated).       */
+  /* entries to C-style strings (this is, null-terminated).       */
   static FT_Error
   cff_index_get_pointers( CFF_Index   idx,
                           FT_Byte***  table,
@@ -427,7 +427,7 @@
     new_size = idx->data_size + idx->count;
 
     if ( idx->count > 0                                &&
-         !FT_NEW_ARRAY( tbl, idx->count + 1 )          &&
+         !FT_QNEW_ARRAY( tbl, idx->count + 1 )         &&
          ( !pool || !FT_ALLOC( new_bytes, new_size ) ) )
     {
       FT_ULong  n, cur_offset;
@@ -622,7 +622,7 @@
     FT_Byte*    bytes;
     FT_ULong    byte_len;
     FT_Error    error;
-    FT_String*  name = 0;
+    FT_String*  name = NULL;
 
 
     if ( !idx->stream )  /* CFF2 does not include a name index */
@@ -634,10 +634,9 @@
     if ( error )
       goto Exit;
 
-    if ( !FT_ALLOC( name, byte_len + 1 ) )
+    if ( !FT_QALLOC( name, byte_len + 1 ) )
     {
-      if ( byte_len )
-        FT_MEM_COPY( name, bytes, byte_len );
+      FT_MEM_COPY( name, bytes, byte_len );
       name[byte_len] = 0;
     }
     cff_index_forget_element( idx, &bytes );
@@ -772,8 +771,7 @@
 
     case 3:
       /* first, compare to the cache */
-      if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
-                        fdselect->cache_count )
+      if ( glyph_index - fdselect->cache_first < fdselect->cache_count )
       {
         fd = fdselect->cache_fd;
         break;
@@ -836,7 +834,6 @@
   {
     FT_Error   error   = FT_Err_Ok;
     FT_UInt    i;
-    FT_Long    j;
     FT_UShort  max_cid = 0;
 
 
@@ -854,9 +851,10 @@
 
     /* When multiple GIDs map to the same CID, we choose the lowest */
     /* GID.  This is not described in any spec, but it matches the  */
-    /* behaviour of recent Acroread versions.                       */
-    for ( j = (FT_Long)num_glyphs - 1; j >= 0; j-- )
-      charset->cids[charset->sids[j]] = (FT_UShort)j;
+    /* behaviour of recent Acroread versions.  The loop stops when  */
+    /* the unsigned index wraps around after reaching zero.         */
+    for ( i = num_glyphs - 1; i < num_glyphs; i-- )
+      charset->cids[charset->sids[i]] = (FT_UShort)i;
 
     charset->max_cid    = max_cid;
     charset->num_glyphs = num_glyphs;
@@ -932,7 +930,7 @@
         goto Exit;
 
       /* Allocate memory for sids. */
-      if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
+      if ( FT_QNEW_ARRAY( charset->sids, num_glyphs ) )
         goto Exit;
 
       /* assign the .notdef glyph */
@@ -1018,14 +1016,14 @@
       case 0:
         if ( num_glyphs > 229 )
         {
-          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
-                     "predefined charset (Adobe ISO-Latin)\n" ));
+          FT_ERROR(( "cff_charset_load: implicit charset larger than\n" ));
+          FT_ERROR(( "predefined charset (Adobe ISO-Latin)\n" ));
           error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
 
         /* Allocate memory for sids. */
-        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
+        if ( FT_QNEW_ARRAY( charset->sids, num_glyphs ) )
           goto Exit;
 
         /* Copy the predefined charset into the allocated memory. */
@@ -1036,14 +1034,14 @@
       case 1:
         if ( num_glyphs > 166 )
         {
-          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
-                     "predefined charset (Adobe Expert)\n" ));
+          FT_ERROR(( "cff_charset_load: implicit charset larger than\n" ));
+          FT_ERROR(( "predefined charset (Adobe Expert)\n" ));
           error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
 
         /* Allocate memory for sids. */
-        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
+        if ( FT_QNEW_ARRAY( charset->sids, num_glyphs ) )
           goto Exit;
 
         /* Copy the predefined charset into the allocated memory.     */
@@ -1054,14 +1052,14 @@
       case 2:
         if ( num_glyphs > 87 )
         {
-          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
-                     "predefined charset (Adobe Expert Subset)\n" ));
+          FT_ERROR(( "cff_charset_load: implicit charset larger than\n" ));
+          FT_ERROR(( "predefined charset (Adobe Expert Subset)\n" ));
           error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
 
         /* Allocate memory for sids. */
-        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
+        if ( FT_QNEW_ARRAY( charset->sids, num_glyphs ) )
           goto Exit;
 
         /* Copy the predefined charset into the allocated memory.     */
@@ -1087,7 +1085,6 @@
       FT_FREE( charset->cids );
       charset->format = 0;
       charset->offset = 0;
-      charset->sids   = 0;
     }
 
     return error;
@@ -1141,6 +1138,8 @@
     {
       FT_UInt   vsOffset;
       FT_UInt   format;
+      FT_UInt   dataCount;
+      FT_UInt   regionCount;
       FT_ULong  regionListOffset;
 
 
@@ -1163,16 +1162,16 @@
       }
 
       /* read top level fields */
-      if ( FT_READ_ULONG( regionListOffset )   ||
-           FT_READ_USHORT( vstore->dataCount ) )
+      if ( FT_READ_ULONG( regionListOffset ) ||
+           FT_READ_USHORT( dataCount )       )
         goto Exit;
 
       /* make temporary copy of item variation data offsets; */
       /* we'll parse region list first, then come back       */
-      if ( FT_NEW_ARRAY( dataOffsetArray, vstore->dataCount ) )
+      if ( FT_QNEW_ARRAY( dataOffsetArray, dataCount ) )
         goto Exit;
 
-      for ( i = 0; i < vstore->dataCount; i++ )
+      for ( i = 0; i < dataCount; i++ )
       {
         if ( FT_READ_ULONG( dataOffsetArray[i] ) )
           goto Exit;
@@ -1181,20 +1180,24 @@
       /* parse regionList and axisLists */
       if ( FT_STREAM_SEEK( vsOffset + regionListOffset ) ||
            FT_READ_USHORT( vstore->axisCount )           ||
-           FT_READ_USHORT( vstore->regionCount )         )
+           FT_READ_USHORT( regionCount )                 )
         goto Exit;
 
-      if ( FT_NEW_ARRAY( vstore->varRegionList, vstore->regionCount ) )
+      vstore->regionCount = 0;
+      if ( FT_QNEW_ARRAY( vstore->varRegionList, regionCount ) )
         goto Exit;
 
-      for ( i = 0; i < vstore->regionCount; i++ )
+      for ( i = 0; i < regionCount; i++ )
       {
         CFF_VarRegion*  region = &vstore->varRegionList[i];
 
 
-        if ( FT_NEW_ARRAY( region->axisList, vstore->axisCount ) )
+        if ( FT_QNEW_ARRAY( region->axisList, vstore->axisCount ) )
           goto Exit;
 
+        /* keep track of how many axisList to deallocate on error */
+        vstore->regionCount++;
+
         for ( j = 0; j < vstore->axisCount; j++ )
         {
           CFF_AxisCoords*  axis = &region->axisList[j];
@@ -1214,10 +1217,11 @@
       }
 
       /* use dataOffsetArray now to parse varData items */
-      if ( FT_NEW_ARRAY( vstore->varData, vstore->dataCount ) )
+      vstore->dataCount = 0;
+      if ( FT_QNEW_ARRAY( vstore->varData, dataCount ) )
         goto Exit;
 
-      for ( i = 0; i < vstore->dataCount; i++ )
+      for ( i = 0; i < dataCount; i++ )
       {
         CFF_VarData*  data = &vstore->varData[i];
 
@@ -1236,9 +1240,12 @@
         if ( FT_READ_USHORT( data->regionIdxCount ) )
           goto Exit;
 
-        if ( FT_NEW_ARRAY( data->regionIndices, data->regionIdxCount ) )
+        if ( FT_QNEW_ARRAY( data->regionIndices, data->regionIdxCount ) )
           goto Exit;
 
+        /* keep track of how many regionIndices to deallocate on error */
+        vstore->dataCount++;
+
         for ( j = 0; j < data->regionIdxCount; j++ )
         {
           if ( FT_READ_USHORT( data->regionIndices[j] ) )
@@ -1322,9 +1329,9 @@
 
       /* increase or allocate `blend_stack' and reset `blend_top'; */
       /* prepare to append `numBlends' values to the buffer        */
-      if ( FT_REALLOC( subFont->blend_stack,
-                       subFont->blend_alloc,
-                       subFont->blend_alloc + size ) )
+      if ( FT_QREALLOC( subFont->blend_stack,
+                        subFont->blend_alloc,
+                        subFont->blend_alloc + size ) )
         goto Exit;
 
       subFont->blend_top    = subFont->blend_stack + subFont->blend_used;
@@ -1437,9 +1444,7 @@
 
     /* prepare buffer for the blend vector */
     len = varData->regionIdxCount + 1;    /* add 1 for default component */
-    if ( FT_REALLOC( blend->BV,
-                     blend->lenBV * sizeof( *blend->BV ),
-                     len * sizeof( *blend->BV ) ) )
+    if ( FT_QRENEW_ARRAY( blend->BV, blend->lenBV, len ) )
       goto Exit;
 
     blend->lenBV = len;
@@ -1456,10 +1461,8 @@
       if ( master == 0 )
       {
         blend->BV[master] = FT_FIXED_ONE;
-        FT_TRACE4(( "   build blend vector len %d\n"
-                    "   [ %f ",
-                    len,
-                    blend->BV[master] / 65536.0 ));
+        FT_TRACE4(( "   build blend vector len %d\n", len ));
+        FT_TRACE4(( "   [ %f ", blend->BV[master] / 65536.0 ));
         continue;
       }
 
@@ -1543,9 +1546,7 @@
     if ( lenNDV != 0 )
     {
       /* user has set a normalized vector */
-      if ( FT_REALLOC( blend->lastNDV,
-                       blend->lenNDV * sizeof ( *NDV ),
-                       lenNDV * sizeof ( *NDV ) ) )
+      if ( FT_QRENEW_ARRAY( blend->lastNDV, blend->lenNDV, lenNDV ) )
         goto Exit;
 
       FT_MEM_COPY( blend->lastNDV,
@@ -1827,7 +1828,8 @@
         /* Construct code to GID mapping from code to SID mapping */
         /* and charset.                                           */
 
-        encoding->count = 0;
+        encoding->offset = offset; /* used in cff_face_init */
+        encoding->count  = 0;
 
         error = cff_charset_compute_cids( charset, num_glyphs,
                                           stream->memory );
@@ -2363,8 +2365,8 @@
       if ( font->name_index.count > 1 )
       {
         FT_ERROR(( "cff_font_load:"
-                   " invalid CFF font with multiple subfonts\n"
-                   "              "
+                   " invalid CFF font with multiple subfonts\n" ));
+        FT_ERROR(( "              "
                    " in SFNT wrapper\n" ));
         error = FT_THROW( Invalid_File_Format );
         goto Exit;
diff --git a/src/cff/cffload.h b/src/cff/cffload.h
index fc998db..20f9296 100644
--- a/src/cff/cffload.h
+++ b/src/cff/cffload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType & CFF data/program tables loader (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index d555d52..3a4d47d 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
  *
  *   OpenType objects manager (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -283,6 +283,8 @@
   cff_size_request( FT_Size          size,
                     FT_Size_Request  req )
   {
+    FT_Error  error;
+
     CFF_Size           cffsize = (CFF_Size)size;
     PSH_Globals_Funcs  funcs;
 
@@ -304,7 +306,9 @@
 
 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
-    FT_Request_Metrics( size->face, req );
+    error = FT_Request_Metrics( size->face, req );
+    if ( error )
+      goto Exit;
 
     funcs = cff_size_get_globals_funcs( cffsize );
 
@@ -345,7 +349,8 @@
       }
     }
 
-    return FT_Err_Ok;
+  Exit:
+    return error;
   }
 
 
@@ -659,8 +664,8 @@
       if ( dict->cid_registry == 0xFFFFU && !psnames )
       {
         FT_ERROR(( "cff_face_init:"
-                   " cannot open CFF & CEF fonts\n"
-                   "              "
+                   " cannot open CFF & CEF fonts\n" ));
+        FT_ERROR(( "              "
                    " without the `psnames' module\n" ));
         error = FT_THROW( Missing_Module );
         goto Exit;
@@ -684,13 +689,13 @@
 
         /* In Multiple Master CFFs, two SIDs hold the Normalize Design  */
         /* Vector (NDV) and Convert Design Vector (CDV) charstrings,    */
-        /* which may contain NULL bytes in the middle of the data, too. */
+        /* which may contain null bytes in the middle of the data, too. */
         /* We thus access `cff->strings' directly.                      */
         for ( idx = 1; idx < cff->num_strings; idx++ )
         {
           FT_Byte*    s1    = cff->strings[idx - 1];
           FT_Byte*    s2    = cff->strings[idx];
-          FT_PtrDist  s1len = s2 - s1 - 1; /* without the final NULL byte */
+          FT_PtrDist  s1len = s2 - s1 - 1; /* without the final null byte */
           FT_PtrDist  l;
 
 
@@ -1049,11 +1054,11 @@
       {
         FT_CharMapRec  cmaprec;
         FT_CharMap     cmap;
-        FT_UInt        nn;
+        FT_Int         nn;
         CFF_Encoding   encoding = &cff->encoding;
 
 
-        for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ )
+        for ( nn = 0; nn < cffface->num_charmaps; nn++ )
         {
           cmap = cffface->charmaps[nn];
 
@@ -1078,7 +1083,7 @@
         cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
         cmaprec.encoding    = FT_ENCODING_UNICODE;
 
-        nn = (FT_UInt)cffface->num_charmaps;
+        nn = cffface->num_charmaps;
 
         error = FT_CMap_New( &cff_cmap_unicode_class_rec, NULL,
                              &cmaprec, NULL );
@@ -1089,7 +1094,7 @@
         error = FT_Err_Ok;
 
         /* if no Unicode charmap was previously selected, select this one */
-        if ( !cffface->charmap && nn != (FT_UInt)cffface->num_charmaps )
+        if ( !cffface->charmap && nn != cffface->num_charmaps )
           cffface->charmap = cffface->charmaps[nn];
 
       Skip_Unicode:
@@ -1174,11 +1179,7 @@
 
 
     /* set default property values, cf. `ftcffdrv.h' */
-#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
-    driver->hinting_engine = FT_HINTING_FREETYPE;
-#else
     driver->hinting_engine = FT_HINTING_ADOBE;
-#endif
 
     driver->no_stem_darkening = TRUE;
 
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index 845bd90..149a8a2 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
  *
  *   OpenType objects manager (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index 69bcd5d..dde55e9 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -4,7 +4,7 @@
  *
  *   CFF token stream parser (body)
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -62,7 +62,7 @@
     parser->num_axes    = num_axes;
 
     /* allocate the stack buffer */
-    if ( FT_NEW_ARRAY( parser->stack, stackSize ) )
+    if ( FT_QNEW_ARRAY( parser->stack, stackSize ) )
     {
       FT_FREE( parser->stack );
       goto Exit;
@@ -713,9 +713,10 @@
            ( max_scaling - min_scaling ) > 9 )
       {
         FT_TRACE1(( "cff_parse_font_matrix:"
-                    " strange scaling values (minimum %ld, maximum %ld),\n"
-                    "                      "
-                    " using default matrix\n", min_scaling, max_scaling ));
+                    " strange scaling values (minimum %ld, maximum %ld),\n",
+                    min_scaling, max_scaling ));
+        FT_TRACE1(( "                      "
+                    " using default matrix\n" ));
         goto Unlikely;
       }
 
@@ -1515,6 +1516,7 @@
 
               case cff_kind_fixed_thousand:
                 FT_TRACE4(( " %f\n", (double)val / 65536 / 1000 ));
+                break;
 
               default:
                 ; /* never reached */
diff --git a/src/cff/cffparse.h b/src/cff/cffparse.h
index 6f3fbb3..a28ab52 100644
--- a/src/cff/cffparse.h
+++ b/src/cff/cffparse.h
@@ -4,7 +4,7 @@
  *
  *   CFF token stream parser (specification)
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/cfftoken.h b/src/cff/cfftoken.h
index 4c6a53e..eef3069 100644
--- a/src/cff/cfftoken.h
+++ b/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
  *
  *   CFF token definitions (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cff/module.mk b/src/cff/module.mk
index bd728c6..cfa444d 100644
--- a/src/cff/module.mk
+++ b/src/cff/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/cff/rules.mk b/src/cff/rules.mk
index 70bb92d..e54614f 100644
--- a/src/cff/rules.mk
+++ b/src/cff/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/cid/ciderrs.h b/src/cid/ciderrs.h
index f698bb2..2d762d9 100644
--- a/src/cid/ciderrs.h
+++ b/src/cid/ciderrs.h
@@ -4,7 +4,7 @@
  *
  *   CID error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cid/cidgload.c b/src/cid/cidgload.c
index 54aa62f..a46d063 100644
--- a/src/cid/cidgload.c
+++ b/src/cid/cidgload.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 Glyph Loader (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -63,7 +63,7 @@
 #endif
 
 
-    FT_TRACE1(( "cid_load_glyph: glyph index %d\n", glyph_index ));
+    FT_TRACE1(( "cid_load_glyph: glyph index %u\n", glyph_index ));
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
 
@@ -76,20 +76,17 @@
 
       error = inc->funcs->get_glyph_data( inc->object,
                                           glyph_index, &glyph_data );
-      if ( error )
+      if ( error || glyph_data.length < cid->fd_bytes )
         goto Exit;
 
       p         = (FT_Byte*)glyph_data.pointer;
-      fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
+      fd_select = cid_get_offset( &p, cid->fd_bytes );
 
-      if ( glyph_data.length != 0 )
-      {
-        glyph_length = (FT_ULong)( glyph_data.length - cid->fd_bytes );
-        (void)FT_ALLOC( charstring, glyph_length );
-        if ( !error )
-          ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes,
+      glyph_length = glyph_data.length - cid->fd_bytes;
+
+      if ( !FT_QALLOC( charstring, glyph_length ) )
+        FT_MEM_COPY( charstring, glyph_data.pointer + cid->fd_bytes,
                      glyph_length );
-      }
 
       inc->funcs->free_glyph_data( inc->object, &glyph_data );
 
@@ -104,7 +101,7 @@
     /* For ordinary fonts read the CID font dictionary index */
     /* and charstring offset from the CIDMap.                */
     {
-      FT_UInt   entry_len = (FT_UInt)( cid->fd_bytes + cid->gd_bytes );
+      FT_UInt   entry_len = cid->fd_bytes + cid->gd_bytes;
       FT_ULong  off1, off2;
 
 
@@ -114,15 +111,15 @@
         goto Exit;
 
       p         = (FT_Byte*)stream->cursor;
-      fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
-      off1      = cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
+      fd_select = cid_get_offset( &p, cid->fd_bytes );
+      off1      = cid_get_offset( &p, cid->gd_bytes );
       p        += cid->fd_bytes;
-      off2      = cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
+      off2      = cid_get_offset( &p, cid->gd_bytes );
       FT_FRAME_EXIT();
 
-      if ( fd_select >= (FT_ULong)cid->num_dicts ||
-           off2 > stream->size                   ||
-           off1 > off2                           )
+      if ( fd_select >= cid->num_dicts ||
+           off2 > stream->size         ||
+           off1 > off2                 )
       {
         FT_TRACE0(( "cid_load_glyph: invalid glyph stream offsets\n" ));
         error = FT_THROW( Invalid_Offset );
@@ -130,11 +127,10 @@
       }
 
       glyph_length = off2 - off1;
-      if ( glyph_length == 0 )
-        goto Exit;
-      if ( FT_ALLOC( charstring, glyph_length ) )
-        goto Exit;
-      if ( FT_STREAM_READ_AT( cid->data_offset + off1,
+
+      if ( glyph_length == 0                             ||
+           FT_QALLOC( charstring, glyph_length )         ||
+           FT_STREAM_READ_AT( cid->data_offset + off1,
                               charstring, glyph_length ) )
         goto Exit;
     }
diff --git a/src/cid/cidgload.h b/src/cid/cidgload.h
index da36e37..8b515ef 100644
--- a/src/cid/cidgload.h
+++ b/src/cid/cidgload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cid/cidload.c b/src/cid/cidload.c
index bb9136a..496219d 100644
--- a/src/cid/cidload.c
+++ b/src/cid/cidload.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 font loader (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -41,7 +41,7 @@
   /* read a single offset */
   FT_LOCAL_DEF( FT_ULong )
   cid_get_offset( FT_Byte*  *start,
-                  FT_Byte    offsize )
+                  FT_UInt    offsize )
   {
     FT_ULong  result;
     FT_Byte*  p = *start;
@@ -113,7 +113,7 @@
         CID_FaceDict  dict;
 
 
-        if ( parser->num_dict < 0 || parser->num_dict >= cid->num_dicts )
+        if ( parser->num_dict >= cid->num_dicts )
         {
           FT_ERROR(( "cid_load_keyword: invalid use of `%s'\n",
                      keyword->ident ));
@@ -164,7 +164,7 @@
     FT_Fixed      temp_scale;
 
 
-    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
+    if ( parser->num_dict < face->cid.num_dicts )
     {
       FT_Matrix*  matrix;
       FT_Vector*  offset;
@@ -244,11 +244,11 @@
     FT_Memory     memory = face->root.memory;
     FT_Stream     stream = parser->stream;
     FT_Error      error  = FT_Err_Ok;
-    FT_Long       num_dicts;
+    FT_Long       num_dicts, max_dicts;
 
 
     num_dicts = cid_parser_to_int( parser );
-    if ( num_dicts < 0 )
+    if ( num_dicts < 0 || num_dicts > FT_INT_MAX )
     {
       FT_ERROR(( "parse_fd_array: invalid number of dictionaries\n" ));
       goto Exit;
@@ -272,18 +272,18 @@
      * need a `dup X' at the very beginning and a `put' at the end, so a
      * rough guess using 100 bytes as the minimum is justified.
      */
-    if ( (FT_ULong)num_dicts > stream->size / 100 )
+    max_dicts = (FT_Long)( stream->size / 100 );
+    if ( num_dicts > max_dicts )
     {
       FT_TRACE0(( "parse_fd_array: adjusting FDArray size"
                   " (from %ld to %ld)\n",
-                  num_dicts,
-                  stream->size / 100 ));
-      num_dicts = (FT_Long)( stream->size / 100 );
+                  num_dicts, max_dicts ));
+      num_dicts = max_dicts;
     }
 
     if ( !cid->font_dicts )
     {
-      FT_Int  n;
+      FT_UInt  n;
 
 
       if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
@@ -322,7 +322,7 @@
     CID_FaceDict  dict;
 
 
-    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
+    if ( parser->num_dict < face->cid.num_dicts )
     {
       dict = face->cid.font_dicts + parser->num_dict;
 
@@ -345,7 +345,7 @@
                    CID_Parser*  parser )
   {
 #ifdef FT_DEBUG_LEVEL_TRACE
-    if ( parser->num_dict >= 0 && parser->num_dict < face->cid.num_dicts )
+    if ( parser->num_dict < face->cid.num_dicts )
     {
       T1_TokenRec  token;
       FT_UInt      len;
@@ -427,7 +427,7 @@
               parser->num_dict++;
 
 #ifdef FT_DEBUG_LEVEL_TRACE
-              FT_TRACE4(( " FontDict %d", parser->num_dict ));
+              FT_TRACE4(( " FontDict %u", parser->num_dict ));
               if ( parser->num_dict > face->cid.num_dicts )
                 FT_TRACE4(( " (ignored)" ));
               FT_TRACE4(( "\n" ));
@@ -517,7 +517,7 @@
     FT_Memory      memory = face->root.memory;
     FT_Stream      stream = face->cid_stream;
     FT_Error       error;
-    FT_Int         n;
+    FT_UInt        n;
     CID_Subrs      subr;
     FT_UInt        max_offsets = 0;
     FT_ULong*      offsets = NULL;
@@ -552,20 +552,20 @@
           goto Fail;
         }
 
-        if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
+        if ( FT_QRENEW_ARRAY( offsets, max_offsets, new_max ) )
           goto Fail;
 
         max_offsets = new_max;
       }
 
       /* read the subrmap's offsets */
-      if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset )     ||
-           FT_FRAME_ENTER( ( num_subrs + 1 ) * (FT_UInt)dict->sd_bytes ) )
+      if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
+           FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes )      )
         goto Fail;
 
       p = (FT_Byte*)stream->cursor;
       for ( count = 0; count <= num_subrs; count++ )
-        offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
+        offsets[count] = cid_get_offset( &p, dict->sd_bytes );
 
       FT_FRAME_EXIT();
 
@@ -589,12 +589,12 @@
       /* allocate, and read them                     */
       data_len = offsets[num_subrs] - offsets[0];
 
-      if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
-           FT_ALLOC( subr->code[0], data_len )       )
+      if ( FT_QNEW_ARRAY( subr->code, num_subrs + 1 ) ||
+           FT_QALLOC( subr->code[0], data_len )       )
         goto Fail;
 
       if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
-           FT_STREAM_READ( subr->code[0], data_len )  )
+           FT_STREAM_READ( subr->code[0], data_len )       )
         goto Fail;
 
       /* set up pointers */
@@ -665,17 +665,18 @@
 
 
   static FT_Error
-  cid_hex_to_binary( FT_Byte*  data,
-                     FT_ULong  data_len,
-                     FT_ULong  offset,
-                     CID_Face  face )
+  cid_hex_to_binary( FT_Byte*   data,
+                     FT_ULong   data_len,
+                     FT_ULong   offset,
+                     CID_Face   face,
+                     FT_ULong*  data_written )
   {
     FT_Stream  stream = face->root.stream;
     FT_Error   error;
 
     FT_Byte    buffer[256];
     FT_Byte   *p, *plimit;
-    FT_Byte   *d, *dlimit;
+    FT_Byte   *d = data, *dlimit;
     FT_Byte    val;
 
     FT_Bool    upper_nibble, done;
@@ -684,7 +685,6 @@
     if ( FT_STREAM_SEEK( offset ) )
       goto Exit;
 
-    d      = data;
     dlimit = d + data_len;
     p      = buffer;
     plimit = p;
@@ -758,6 +758,7 @@
     error = FT_Err_Ok;
 
   Exit:
+    *data_written = (FT_ULong)( d - data );
     return error;
   }
 
@@ -770,12 +771,11 @@
     CID_Parser*  parser;
     FT_Memory    memory = face->root.memory;
     FT_Error     error;
-    FT_Int       n;
+    FT_UInt      n;
 
     CID_FaceInfo  cid = &face->cid;
 
     FT_ULong  binary_length;
-    FT_ULong  entry_len;
 
 
     cid_init_loader( &loader, face );
@@ -803,8 +803,8 @@
       if ( parser->binary_length >
              face->root.stream->size - parser->data_offset )
       {
-        FT_TRACE0(( "cid_face_open: adjusting length of binary data\n"
-                    "               (from %ld to %ld bytes)\n",
+        FT_TRACE0(( "cid_face_open: adjusting length of binary data\n" ));
+        FT_TRACE0(( "               (from %lu to %lu bytes)\n",
                     parser->binary_length,
                     face->root.stream->size - parser->data_offset ));
         parser->binary_length = face->root.stream->size -
@@ -812,15 +812,16 @@
       }
 
       /* we must convert the data section from hexadecimal to binary */
-      if ( FT_ALLOC( face->binary_data, parser->binary_length )    ||
+      if ( FT_QALLOC( face->binary_data, parser->binary_length )   ||
            FT_SET_ERROR( cid_hex_to_binary( face->binary_data,
                                             parser->binary_length,
                                             parser->data_offset,
-                                            face ) )               )
+                                            face,
+                                            &binary_length ) )     )
         goto Exit;
 
       FT_Stream_OpenMemory( face->cid_stream,
-                            face->binary_data, parser->binary_length );
+                            face->binary_data, binary_length );
       cid->data_offset = 0;
     }
     else
@@ -831,10 +832,10 @@
 
     /* sanity tests */
 
-    if ( cid->fd_bytes < 0 || cid->gd_bytes < 1 )
+    if ( cid->gd_bytes == 0 )
     {
       FT_ERROR(( "cid_face_open:"
-                 " Invalid `FDBytes' or `GDBytes' value\n" ));
+                 " Invalid `GDBytes' value\n" ));
       error = FT_THROW( Invalid_File_Format );
       goto Exit;
     }
@@ -843,15 +844,32 @@
     if ( cid->fd_bytes > 4 || cid->gd_bytes > 4 )
     {
       FT_ERROR(( "cid_face_open:"
-                 " Values of `FDBytes' or `GDBytes' larger than 4\n"
-                 "               "
+                 " Values of `FDBytes' or `GDBytes' larger than 4\n" ));
+      FT_ERROR(( "               "
                  " are not supported\n" ));
       error = FT_THROW( Invalid_File_Format );
       goto Exit;
     }
 
     binary_length = face->cid_stream->size - cid->data_offset;
-    entry_len     = (FT_ULong)( cid->fd_bytes + cid->gd_bytes );
+
+    if ( cid->cidmap_offset > binary_length )
+    {
+      FT_ERROR(( "cid_face_open: Invalid `CIDMapOffset' value\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    /* the initial pre-check prevents the multiplication overflow */
+    if ( cid->cid_count > FT_ULONG_MAX / 8                    ||
+         cid->cid_count * ( cid->fd_bytes + cid->gd_bytes ) >
+           binary_length - cid->cidmap_offset                 )
+    {
+      FT_ERROR(( "cid_face_open: Invalid `CIDCount' value\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
 
     for ( n = 0; n < cid->num_dicts; n++ )
     {
@@ -877,8 +895,7 @@
         dict->private_dict.blue_fuzz = 1;
       }
 
-      if ( dict->sd_bytes < 0                        ||
-           ( dict->num_subrs && dict->sd_bytes < 1 ) )
+      if ( dict->num_subrs && dict->sd_bytes == 0 )
       {
         FT_ERROR(( "cid_face_open: Invalid `SDBytes' value\n" ));
         error = FT_THROW( Invalid_File_Format );
@@ -901,11 +918,10 @@
         goto Exit;
       }
 
-      /* `num_subrs' is scanned as a signed integer */
-      if ( (FT_Int)dict->num_subrs < 0                                     ||
-           ( dict->sd_bytes                                              &&
-             dict->num_subrs > ( binary_length - dict->subrmap_offset ) /
-                                 (FT_UInt)dict->sd_bytes                 ) )
+      /* the initial pre-check prevents the multiplication overflow */
+      if ( dict->num_subrs > FT_UINT_MAX / 4      ||
+           dict->num_subrs * dict->sd_bytes >
+             binary_length - dict->subrmap_offset )
       {
         FT_ERROR(( "cid_face_open: Invalid `SubrCount' value\n" ));
         error = FT_THROW( Invalid_File_Format );
@@ -913,22 +929,6 @@
       }
     }
 
-    if ( cid->cidmap_offset > binary_length )
-    {
-      FT_ERROR(( "cid_face_open: Invalid `CIDMapOffset' value\n" ));
-      error = FT_THROW( Invalid_File_Format );
-      goto Exit;
-    }
-
-    if ( entry_len                                            &&
-         cid->cid_count >
-           ( binary_length - cid->cidmap_offset ) / entry_len )
-    {
-      FT_ERROR(( "cid_face_open: Invalid `CIDCount' value\n" ));
-      error = FT_THROW( Invalid_File_Format );
-      goto Exit;
-    }
-
     /* we can now safely proceed */
     error = cid_read_subrs( face );
 
diff --git a/src/cid/cidload.h b/src/cid/cidload.h
index 06fb9ef..ee1d486 100644
--- a/src/cid/cidload.h
+++ b/src/cid/cidload.h
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 font loader (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -37,7 +37,7 @@
 
   FT_LOCAL( FT_ULong )
   cid_get_offset( FT_Byte**  start,
-                  FT_Byte    offsize );
+                  FT_UInt    offsize );
 
   FT_LOCAL( FT_Error )
   cid_face_open( CID_Face  face,
diff --git a/src/cid/cidobjs.c b/src/cid/cidobjs.c
index 04b295e..e3c29c2 100644
--- a/src/cid/cidobjs.c
+++ b/src/cid/cidobjs.c
@@ -4,7 +4,7 @@
  *
  *   CID objects manager (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -157,10 +157,14 @@
   cid_size_request( FT_Size          size,
                     FT_Size_Request  req )
   {
+    FT_Error  error;
+
     PSH_Globals_Funcs  funcs;
 
 
-    FT_Request_Metrics( size->face, req );
+    error = FT_Request_Metrics( size->face, req );
+    if ( error )
+      goto Exit;
 
     funcs = cid_size_get_globals_funcs( (CID_Size)size );
 
@@ -170,7 +174,8 @@
                         size->metrics.y_scale,
                         0, 0 );
 
-    return FT_Err_Ok;
+  Exit:
+    return error;
   }
 
 
@@ -211,7 +216,7 @@
     /* release subrs */
     if ( face->subrs )
     {
-      FT_Int  n;
+      FT_UInt  n;
 
 
       for ( n = 0; n < cid->num_dicts; n++ )
@@ -479,11 +484,7 @@
 
 
     /* set default property values, cf. `ftt1drv.h' */
-#ifdef T1_CONFIG_OPTION_OLD_ENGINE
-    driver->hinting_engine = FT_HINTING_FREETYPE;
-#else
     driver->hinting_engine = FT_HINTING_ADOBE;
-#endif
 
     driver->no_stem_darkening = TRUE;
 
diff --git a/src/cid/cidobjs.h b/src/cid/cidobjs.h
index 6ae3061..32f59cb 100644
--- a/src/cid/cidobjs.h
+++ b/src/cid/cidobjs.h
@@ -4,7 +4,7 @@
  *
  *   CID objects manager (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cid/cidparse.c b/src/cid/cidparse.c
index 1fc098b..852c9b6 100644
--- a/src/cid/cidparse.c
+++ b/src/cid/cidparse.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 parser (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -73,7 +73,11 @@
 
     /* first of all, check the font format in the header */
     if ( FT_FRAME_ENTER( 31 ) )
+    {
+      FT_TRACE2(( "  not a CID-keyed font\n" ));
+      error = FT_THROW( Unknown_File_Format );
       goto Exit;
+    }
 
     if ( ft_strncmp( (char *)stream->cursor,
                      "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
@@ -181,7 +185,7 @@
     parser->root.base      = parser->postscript;
     parser->root.cursor    = parser->postscript;
     parser->root.limit     = parser->root.cursor + ps_len;
-    parser->num_dict       = -1;
+    parser->num_dict       = FT_UINT_MAX;
 
     /* Finally, we check whether `StartData' or `/sfnts' was real --  */
     /* it could be in a comment or string.  We also get the arguments */
diff --git a/src/cid/cidparse.h b/src/cid/cidparse.h
index 0b49beb..fbc437b 100644
--- a/src/cid/cidparse.h
+++ b/src/cid/cidparse.h
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 parser (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -78,7 +78,7 @@
     FT_ULong      binary_length;
 
     CID_FaceInfo  cid;
-    FT_Int        num_dict;
+    FT_UInt       num_dict;
 
   } CID_Parser;
 
diff --git a/src/cid/cidriver.c b/src/cid/cidriver.c
index d08cea1..a0898df 100644
--- a/src/cid/cidriver.c
+++ b/src/cid/cidriver.c
@@ -4,7 +4,7 @@
  *
  *   CID driver interface (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cid/cidriver.h b/src/cid/cidriver.h
index 0fc8ed3..3ff5f78 100644
--- a/src/cid/cidriver.h
+++ b/src/cid/cidriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level CID driver interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cid/cidtoken.h b/src/cid/cidtoken.h
index e9f068b..84c8258 100644
--- a/src/cid/cidtoken.h
+++ b/src/cid/cidtoken.h
@@ -4,7 +4,7 @@
  *
  *   CID token definitions (specification only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/cid/module.mk b/src/cid/module.mk
index 9fb0223..2e16262 100644
--- a/src/cid/module.mk
+++ b/src/cid/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/cid/rules.mk b/src/cid/rules.mk
index 94f663c..933b2da 100644
--- a/src/cid/rules.mk
+++ b/src/cid/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/cid/type1cid.c b/src/cid/type1cid.c
index 082e8bf..5405ecf 100644
--- a/src/cid/type1cid.c
+++ b/src/cid/type1cid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType OpenType driver component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/dlg/dlgwrap.c b/src/dlg/dlgwrap.c
new file mode 100644
index 0000000..e0b9a8d
--- /dev/null
+++ b/src/dlg/dlgwrap.c
@@ -0,0 +1,32 @@
+/****************************************************************************
+ *
+ * dlgwrap.c
+ *
+ *   Wrapper file for the 'dlg' library (body only)
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <ft2build.h>
+#include FT_CONFIG_OPTIONS_H
+
+
+#ifdef FT_DEBUG_LOGGING
+#define DLG_STATIC
+#include "dlg.c"
+#else
+  /* ANSI C doesn't like empty source files */
+  typedef int  _dlg_dummy;
+#endif
+
+
+/* END */
diff --git a/src/dlg/rules.mk b/src/dlg/rules.mk
new file mode 100644
index 0000000..a56dee6
--- /dev/null
+++ b/src/dlg/rules.mk
@@ -0,0 +1,70 @@
+#
+# FreeType 2 dlg logging library configuration rules
+#
+
+
+# Copyright (C) 2020-2021 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# dlg logging library directory
+#
+DLG_DIR := $(SRC_DIR)/dlg
+
+
+# compilation flags for the library
+#
+DLG_COMPILE := $(CC) $(ANSIFLAGS)                            \
+                     $I$(subst /,$(COMPILER_SEP),$(DLG_DIR)) \
+                     $(INCLUDE_FLAGS)                        \
+                     $(FT_CFLAGS)
+
+
+# dlg logging library sources (i.e., C files)
+#
+DLG_SRC := $(DLG_DIR)/dlgwrap.c
+
+# dlg logging library headers
+#
+DLG_H := $(TOP_DIR)/include/dlg/dlg.h \
+         $(TOP_DIR)/include/dlg/output.h
+
+
+# dlg logging library object(s)
+#
+#   DLG_OBJ_M is used during `multi' builds
+#   DLG_OBJ_S is used during `single' builds
+#
+DLG_OBJ_M := $(DLG_SRC:$(DLG_DIR)/%.c=$(OBJ_DIR)/%.$O)
+DLG_OBJ_S := $(OBJ_DIR)/dlg.$O
+
+# dlg logging library source file for single build
+#
+DLG_SRC_S := $(DLG_DIR)/dlgwrap.c
+
+
+# dlg logging library - single object
+#
+$(DLG_OBJ_S): $(DLG_SRC_S) $(DLG_SRC) $(FREETYPE_H) $(DLG_H)
+	$(DLG_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(DLG_SRC_S))
+
+
+# dlg logging library - multiple objects
+#
+$(OBJ_DIR)/%.$O: $(DLG_DIR)/%.c $(FREETYPE_H) $(DLG_H)
+	$(DLG_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
+
+
+# update main object lists
+#
+DLG_OBJS_S += $(DLG_OBJ_S)
+DLG_OBJS_M += $(DLG_OBJ_M)
+
+
+# EOF
diff --git a/src/gxvalid/README b/src/gxvalid/README
index 2a32bab..7fb0296 100644
--- a/src/gxvalid/README
+++ b/src/gxvalid/README
@@ -518,7 +518,7 @@
 
 ------------------------------------------------------------------------
 
-Copyright (C) 2004-2020 by
+Copyright (C) 2004-2021 by
 suzuki toshiya, Masatake YAMATO, Red hat K.K.,
 David Turner, Robert Wilhelm, and Werner Lemberg.
 
diff --git a/src/gxvalid/gxvalid.c b/src/gxvalid/gxvalid.c
index 683b8a6..309d517 100644
--- a/src/gxvalid/gxvalid.c
+++ b/src/gxvalid/gxvalid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType validator for TrueTypeGX/AAT tables (body only).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvalid.h b/src/gxvalid/gxvalid.h
index ff2812d..2c41c28 100644
--- a/src/gxvalid/gxvalid.h
+++ b/src/gxvalid/gxvalid.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT table validation (specification only).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvbsln.c b/src/gxvalid/gxvbsln.c
index ac58d46..af69cb5 100644
--- a/src/gxvalid/gxvbsln.c
+++ b/src/gxvalid/gxvbsln.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT bsln table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvcommn.c b/src/gxvalid/gxvcommn.c
index ead0f24..18e42b0 100644
--- a/src/gxvalid/gxvcommn.c
+++ b/src/gxvalid/gxvcommn.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT common tables validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -46,16 +46,11 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  static int
-  gxv_compare_ushort_offset( FT_UShort*  a,
-                             FT_UShort*  b )
+  FT_COMPARE_DEF( int )
+  gxv_compare_ushort_offset( const void*  a,
+                             const void*  b )
   {
-    if ( *a < *b )
-      return -1;
-    else if ( *a > *b )
-      return 1;
-    else
-      return 0;
+    return  *(FT_UShort*)a - *(FT_UShort*)b;
   }
 
 
@@ -78,7 +73,7 @@
     buff[nmemb] = limit;
 
     ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ),
-              ( int(*)(const void*, const void*) )gxv_compare_ushort_offset );
+              gxv_compare_ushort_offset );
 
     if ( buff[nmemb] > limit )
       FT_INVALID_OFFSET;
@@ -111,13 +106,17 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  static int
-  gxv_compare_ulong_offset( FT_ULong*  a,
-                            FT_ULong*  b )
+  FT_COMPARE_DEF( int )
+  gxv_compare_ulong_offset( const void*  a,
+                            const void*  b )
   {
-    if ( *a < *b )
+    FT_ULong  a_ = *(FT_ULong*)a;
+    FT_ULong  b_ = *(FT_ULong*)b;
+
+
+    if ( a_ < b_ )
       return -1;
-    else if ( *a > *b )
+    else if ( a_ > b_ )
       return 1;
     else
       return 0;
@@ -143,7 +142,7 @@
     buff[nmemb] = limit;
 
     ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ),
-              ( int(*)(const void*, const void*) )gxv_compare_ulong_offset );
+              gxv_compare_ulong_offset );
 
     if ( buff[nmemb] > limit )
       FT_INVALID_OFFSET;
@@ -439,7 +438,7 @@
       GXV_LIMIT_CHECK( 2 );
       if ( p + 2 >= limit )     /* some fonts have too-short fmt0 array */
       {
-        GXV_TRACE(( "too short, glyphs %d - %d are missing\n",
+        GXV_TRACE(( "too short, glyphs %d - %ld are missing\n",
                     i, gxvalid->face->num_glyphs ));
         GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
         break;
@@ -534,7 +533,7 @@
 
       if ( lastGlyph < firstGlyph )
       {
-        GXV_TRACE(( "reverse ordered range specification at unit %d:",
+        GXV_TRACE(( "reverse ordered range specification at unit %d:"
                     " lastGlyph %d < firstGlyph %d ",
                     unit, lastGlyph, firstGlyph ));
         GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
@@ -605,7 +604,7 @@
 
       if ( lastGlyph < firstGlyph )
       {
-        GXV_TRACE(( "reverse ordered range specification at unit %d:",
+        GXV_TRACE(( "reverse ordered range specification at unit %d:"
                     " lastGlyph %d < firstGlyph %d ",
                     unit, lastGlyph, firstGlyph ));
         GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
@@ -825,7 +824,7 @@
     face = gxvalid->face;
     if ( face->num_glyphs < gid )
     {
-      GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %d < %d\n",
+      GXV_TRACE(( " gxv_glyphid_check() gid overflow: num_glyphs %ld < %d\n",
                   face->num_glyphs, gid ));
       GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
     }
@@ -1419,7 +1418,7 @@
     GXV_NAME_ENTER( "XStateArray" );
 
     GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n",
-                (int)(*length_p), stateSize, (int)(maxClassID) ));
+                (int)(*length_p), (int)stateSize, (int)(maxClassID) ));
 
     /*
      * 2 states are predefined and must be described:
@@ -1493,9 +1492,11 @@
       state = (FT_UShort)( newState_idx / ( 1 + maxClassID ) );
       if ( 0 != ( newState_idx % ( 1 + maxClassID ) ) )
       {
-        FT_TRACE4(( "-> new state = %d (supposed)\n"
-                    "but newState index 0x%04x is not aligned to %d-classes\n",
-                    state, newState_idx,  1 + maxClassID ));
+        FT_TRACE4(( "-> new state = %d (supposed)\n",
+                    state ));
+        FT_TRACE4(( "but newState index 0x%04x"
+                    " is not aligned to %d-classes\n",
+                    newState_idx, 1 + maxClassID ));
         GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
       }
 
@@ -1581,10 +1582,10 @@
     stateArray = FT_NEXT_ULONG( p );
     entryTable = FT_NEXT_ULONG( p );
 
-    GXV_TRACE(( "nClasses =0x%08x\n", gxvalid->xstatetable.nClasses ));
-    GXV_TRACE(( "offset to classTable=0x%08x\n", classTable ));
-    GXV_TRACE(( "offset to stateArray=0x%08x\n", stateArray ));
-    GXV_TRACE(( "offset to entryTable=0x%08x\n", entryTable ));
+    GXV_TRACE(( "nClasses =0x%08lx\n", gxvalid->xstatetable.nClasses ));
+    GXV_TRACE(( "offset to classTable=0x%08lx\n", classTable ));
+    GXV_TRACE(( "offset to stateArray=0x%08lx\n", stateArray ));
+    GXV_TRACE(( "offset to entryTable=0x%08lx\n", entryTable ));
 
     if ( gxvalid->xstatetable.nClasses > 0xFFFFU )
       FT_INVALID_DATA;
diff --git a/src/gxvalid/gxvcommn.h b/src/gxvalid/gxvcommn.h
index 59d1492..b79b641 100644
--- a/src/gxvalid/gxvcommn.h
+++ b/src/gxvalid/gxvcommn.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT common tables validation (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -61,8 +61,11 @@
 
 #undef GXV_LOAD_UNUSED_VARS /* debug purpose */
 
-#define IS_PARANOID_VALIDATION          ( gxvalid->root->level >= FT_VALIDATE_PARANOID )
-#define GXV_SET_ERR_IF_PARANOID( err )  { if ( IS_PARANOID_VALIDATION ) ( err ); }
+#define IS_PARANOID_VALIDATION                             \
+          ( gxvalid->root->level >= FT_VALIDATE_PARANOID )
+#define GXV_SET_ERR_IF_PARANOID( err )                              \
+          do { if ( IS_PARANOID_VALIDATION ) ( err ); } while ( 0 )
+
 
   /*************************************************************************/
   /*************************************************************************/
@@ -261,17 +264,17 @@
   } GXV_ValidatorRec;
 
 
-#define GXV_TABLE_DATA( tag, field )                           \
+#define GXV_TABLE_DATA( tag, field )                             \
         ( ( (GXV_ ## tag ## _Data)gxvalid->table_data )->field )
 
 #undef  FT_INVALID_
-#define FT_INVALID_( _error ) \
+#define FT_INVALID_( _error )                                     \
           ft_validator_error( gxvalid->root, FT_THROW( _error ) )
 
-#define GXV_LIMIT_CHECK( _count )                                     \
-          FT_BEGIN_STMNT                                              \
+#define GXV_LIMIT_CHECK( _count )                                       \
+          FT_BEGIN_STMNT                                                \
             if ( p + _count > ( limit? limit : gxvalid->root->limit ) ) \
-              FT_INVALID_TOO_SHORT;                                   \
+              FT_INVALID_TOO_SHORT;                                     \
           FT_END_STMNT
 
 
@@ -279,19 +282,19 @@
 
 #define GXV_INIT  gxvalid->debug_indent = 0
 
-#define GXV_NAME_ENTER( name )                             \
-          FT_BEGIN_STMNT                                   \
-            gxvalid->debug_indent += 2;                      \
-            FT_TRACE4(( "%*.s", gxvalid->debug_indent, 0 )); \
-            FT_TRACE4(( "%s table\n", name ));             \
+#define GXV_NAME_ENTER( name )                                \
+          FT_BEGIN_STMNT                                      \
+            gxvalid->debug_indent += 2;                       \
+            FT_TRACE4(( "%*.s", gxvalid->debug_indent, "" )); \
+            FT_TRACE4(( "%s table\n", name ));                \
           FT_END_STMNT
 
 #define GXV_EXIT  gxvalid->debug_indent -= 2
 
-#define GXV_TRACE( s )                                     \
-          FT_BEGIN_STMNT                                   \
-            FT_TRACE4(( "%*.s", gxvalid->debug_indent, 0 )); \
-            FT_TRACE4( s );                                \
+#define GXV_TRACE( s )                                        \
+          FT_BEGIN_STMNT                                      \
+            FT_TRACE4(( "%*.s", gxvalid->debug_indent, "" )); \
+            FT_TRACE4( s );                                   \
           FT_END_STMNT
 
 #else /* !FT_DEBUG_LEVEL_TRACE */
diff --git a/src/gxvalid/gxverror.h b/src/gxvalid/gxverror.h
index 5d8f0b6..d20d395 100644
--- a/src/gxvalid/gxverror.h
+++ b/src/gxvalid/gxverror.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT validation module error codes (specification only).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvfeat.c b/src/gxvalid/gxvfeat.c
index 400ec8a..0a8e2f2 100644
--- a/src/gxvalid/gxvfeat.c
+++ b/src/gxvalid/gxvfeat.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT feat table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -90,7 +90,7 @@
 
     if ( feature >= gxv_feat_registry_length )
     {
-      GXV_TRACE(( "feature number %d is out of range %d\n",
+      GXV_TRACE(( "feature number %d is out of range %lu\n",
                   feature, gxv_feat_registry_length ));
       GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
       goto Exit;
diff --git a/src/gxvalid/gxvfeat.h b/src/gxvalid/gxvfeat.h
index 435dcef..f6d28fa 100644
--- a/src/gxvalid/gxvfeat.h
+++ b/src/gxvalid/gxvfeat.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT feat table validation (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvfgen.c b/src/gxvalid/gxvfgen.c
index fe05a6f..b47cd0f 100644
--- a/src/gxvalid/gxvfgen.c
+++ b/src/gxvalid/gxvfgen.c
@@ -5,7 +5,7 @@
  *   Generate feature registry data for gxv `feat' validator.
  *   This program is derived from gxfeatreg.c in gxlayout.
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * Masatake YAMATO and Redhat K.K.
  *
  * This file may only be used,
diff --git a/src/gxvalid/gxvjust.c b/src/gxvalid/gxvjust.c
index 3c7f1f9..ec289b8 100644
--- a/src/gxvalid/gxvjust.c
+++ b/src/gxvalid/gxvjust.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT just table validation (body).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -78,7 +78,7 @@
       return;
 
     GXV_TRACE(( "just table includes too large %s"
-                " GID=%d > %d (in maxp)\n",
+                " GID=%d > %ld (in maxp)\n",
                 msg_tag, gid, gxvalid->face->num_glyphs ));
     GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
   }
@@ -140,7 +140,7 @@
     count = FT_NEXT_ULONG( p );
     for ( i = 0; i < count; i++ )
     {
-      GXV_TRACE(( "validating wdc pair %d/%d\n", i + 1, count ));
+      GXV_TRACE(( "validating wdc pair %lu/%lu\n", i + 1, count ));
       gxv_just_wdp_entry_validate( p, limit, gxvalid );
       p += gxvalid->subtable_length;
     }
@@ -206,7 +206,8 @@
     if ( lowerLimit >= upperLimit )
     {
       GXV_TRACE(( "just table includes invalid range spec:"
-                  " lowerLimit(%d) > upperLimit(%d)\n"     ));
+                  " lowerLimit(%ld) > upperLimit(%ld)\n",
+                  lowerLimit, upperLimit ));
       GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
     }
 
@@ -294,14 +295,14 @@
     gxvalid->subtable_length = (FT_ULong)( p - table );
 
     if ( variantsAxis != 0x64756374L ) /* 'duct' */
-      GXV_TRACE(( "variantsAxis 0x%08x is non default value",
+      GXV_TRACE(( "variantsAxis 0x%08lx is non default value",
                    variantsAxis ));
 
     if ( minimumLimit > noStretchValue )
-      GXV_TRACE(( "type4:minimumLimit 0x%08x > noStretchValue 0x%08x\n",
+      GXV_TRACE(( "type4:minimumLimit 0x%08lx > noStretchValue 0x%08lx\n",
                   minimumLimit, noStretchValue ));
     else if ( noStretchValue > maximumLimit )
-      GXV_TRACE(( "type4:noStretchValue 0x%08x > maximumLimit 0x%08x\n",
+      GXV_TRACE(( "type4:noStretchValue 0x%08lx > maximumLimit 0x%08lx\n",
                   noStretchValue, maximumLimit ));
     else if ( !IS_PARANOID_VALIDATION )
       return;
@@ -389,7 +390,7 @@
 
     GXV_LIMIT_CHECK( 4 );
     actionCount = FT_NEXT_ULONG( p );
-    GXV_TRACE(( "actionCount = %d\n", actionCount ));
+    GXV_TRACE(( "actionCount = %lu\n", actionCount ));
 
     for ( i = 0; i < actionCount; i++ )
     {
@@ -514,14 +515,14 @@
     coverage        = FT_NEXT_USHORT( p );
     subFeatureFlags = FT_NEXT_ULONG( p );
 
-    GXV_TRACE(( "  justClassTable: coverage = 0x%04x (%s) ", coverage ));
+    GXV_TRACE(( "  justClassTable: coverage = 0x%04x ", coverage ));
     if ( ( coverage & 0x4000 ) == 0  )
       GXV_TRACE(( "ascending\n" ));
     else
       GXV_TRACE(( "descending\n" ));
 
     if ( subFeatureFlags )
-      GXV_TRACE(( "  justClassTable: nonzero value (0x%08x)"
+      GXV_TRACE(( "  justClassTable: nonzero value (0x%08lx)"
                   " in unused subFeatureFlags\n", subFeatureFlags ));
 
     gxvalid->statetable.optdata               = NULL;
@@ -684,7 +685,7 @@
 
 
     /* Version 1.0 (always:2000) */
-    GXV_TRACE(( " (version = 0x%08x)\n", version ));
+    GXV_TRACE(( " (version = 0x%08lx)\n", version ));
     if ( version != 0x00010000UL )
       FT_INVALID_FORMAT;
 
diff --git a/src/gxvalid/gxvkern.c b/src/gxvalid/gxvkern.c
index cc0b3df..542e8bc 100644
--- a/src/gxvalid/gxvkern.c
+++ b/src/gxvalid/gxvkern.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT kern table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -487,7 +487,7 @@
 
     if ( gxvalid->face->num_glyphs != glyphCount )
     {
-      GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n",
+      GXV_TRACE(( "maxGID=%ld, but glyphCount=%d\n",
                   gxvalid->face->num_glyphs, glyphCount ));
       GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
     }
@@ -745,7 +745,7 @@
 #ifdef GXV_LOAD_TRACE_VARS
     FT_UShort  version = 0;    /* MS only: subtable version, unused */
 #endif
-    FT_ULong   length;         /* MS: 16bit, Apple: 32bit*/
+    FT_ULong   length;         /* MS: 16bit, Apple: 32bit */
     FT_UShort  coverage;
 #ifdef GXV_LOAD_TRACE_VARS
     FT_UShort  tupleIndex = 0; /* Apple only */
@@ -772,7 +772,7 @@
       tupleIndex = 0;
 #endif
       GXV_TRACE(( "Subtable version = %d\n", version ));
-      GXV_TRACE(( "Subtable length = %d\n", length ));
+      GXV_TRACE(( "Subtable length = %lu\n", length ));
       break;
 
     case KERN_DIALECT_APPLE:
@@ -783,7 +783,7 @@
 #ifdef GXV_LOAD_TRACE_VARS
       tupleIndex = 0;
 #endif
-      GXV_TRACE(( "Subtable length = %d\n", length ));
+      GXV_TRACE(( "Subtable length = %lu\n", length ));
 
       if ( KERN_IS_NEW( gxvalid ) )
       {
@@ -800,7 +800,7 @@
     default:
       length = u16[1];
       GXV_TRACE(( "cannot detect subtable dialect, "
-                  "just skip %d byte\n", length ));
+                  "just skip %lu byte\n", length ));
       goto Exit;
     }
 
@@ -884,7 +884,7 @@
 
     for ( i = 0; i < nTables; i++ )
     {
-      GXV_TRACE(( "validating subtable %d/%d\n", i, nTables ));
+      GXV_TRACE(( "validating subtable %d/%lu\n", i, nTables ));
       /* p should be 32bit-aligned? */
       gxv_kern_subtable_validate( p, 0, gxvalid );
       p += gxvalid->subtable_length;
diff --git a/src/gxvalid/gxvlcar.c b/src/gxvalid/gxvlcar.c
index 82ac190..9db839b 100644
--- a/src/gxvalid/gxvlcar.c
+++ b/src/gxvalid/gxvlcar.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT lcar table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmod.c b/src/gxvalid/gxvmod.c
index a467e87..1a11426 100644
--- a/src/gxvalid/gxvmod.c
+++ b/src/gxvalid/gxvmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType's TrueTypeGX/AAT validation module implementation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -62,7 +62,7 @@
     if ( error )
       goto Exit;
 
-    if ( FT_ALLOC( *table, *table_len ) )
+    if ( FT_QALLOC( *table, *table_len ) )
       goto Exit;
 
     error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len );
@@ -76,27 +76,31 @@
           FT_Byte* volatile  _sfnt          = NULL; \
           FT_ULong            len_ ## _sfnt = 0
 
-#define GXV_TABLE_LOAD( _sfnt )                                     \
-          if ( ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) && \
-               ( gx_flags & FT_VALIDATE_ ## _sfnt )            )    \
-          {                                                         \
-            error = gxv_load_table( face, TTAG_ ## _sfnt,           \
-                                    &_sfnt, &len_ ## _sfnt );       \
-            if ( error )                                            \
-              goto Exit;                                            \
-          }
+#define GXV_TABLE_LOAD( _sfnt )                                       \
+          FT_BEGIN_STMNT                                              \
+            if ( ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) && \
+                 ( gx_flags & FT_VALIDATE_ ## _sfnt )            )    \
+            {                                                         \
+              error = gxv_load_table( face, TTAG_ ## _sfnt,           \
+                                      &_sfnt, &len_ ## _sfnt );       \
+              if ( error )                                            \
+                goto Exit;                                            \
+            }                                                         \
+          FT_END_STMNT
 
-#define GXV_TABLE_VALIDATE( _sfnt )                                  \
-          if ( _sfnt )                                               \
-          {                                                          \
-            ft_validator_init( &valid, _sfnt, _sfnt + len_ ## _sfnt, \
-                               FT_VALIDATE_DEFAULT );                \
-            if ( ft_setjmp( valid.jump_buffer ) == 0 )               \
-              gxv_ ## _sfnt ## _validate( _sfnt, face, &valid );     \
-            error = valid.error;                                     \
-            if ( error )                                             \
-              goto Exit;                                             \
-          }
+#define GXV_TABLE_VALIDATE( _sfnt )                                    \
+          FT_BEGIN_STMNT                                               \
+            if ( _sfnt )                                               \
+            {                                                          \
+              ft_validator_init( &valid, _sfnt, _sfnt + len_ ## _sfnt, \
+                                 FT_VALIDATE_DEFAULT );                \
+              if ( ft_setjmp( valid.jump_buffer ) == 0 )               \
+                gxv_ ## _sfnt ## _validate( _sfnt, face, &valid );     \
+              error = valid.error;                                     \
+              if ( error )                                             \
+                goto Exit;                                             \
+            }                                                          \
+          FT_END_STMNT
 
 #define GXV_TABLE_SET( _sfnt )                                        \
           if ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count )        \
diff --git a/src/gxvalid/gxvmod.h b/src/gxvalid/gxvmod.h
index f2982c9..90e0c10 100644
--- a/src/gxvalid/gxvmod.h
+++ b/src/gxvalid/gxvmod.h
@@ -5,7 +5,7 @@
  *   FreeType's TrueTypeGX/AAT validation module implementation
  *   (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmort.c b/src/gxvalid/gxvmort.c
index aae7f01..d0db7f4 100644
--- a/src/gxvalid/gxvmort.c
+++ b/src/gxvalid/gxvmort.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT mort table validation (body).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -288,7 +288,7 @@
 
     for ( i = 0; i < nChains; i++ )
     {
-      GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains ));
+      GXV_TRACE(( "validating chain %lu/%lu\n", i + 1, nChains ));
       GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
       gxv_mort_chain_validate( p, limit, gxvalid );
       p += gxvalid->subtable_length;
diff --git a/src/gxvalid/gxvmort.h b/src/gxvalid/gxvmort.h
index 7237c58..de5ab4e 100644
--- a/src/gxvalid/gxvmort.h
+++ b/src/gxvalid/gxvmort.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT common definition for mort table (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmort0.c b/src/gxvalid/gxvmort0.c
index d452c1c..0c695aa 100644
--- a/src/gxvalid/gxvmort0.c
+++ b/src/gxvalid/gxvmort0.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type0 (Indic Script Rearrangement) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmort1.c b/src/gxvalid/gxvmort1.c
index d743f89..0af2236 100644
--- a/src/gxvalid/gxvmort1.c
+++ b/src/gxvalid/gxvmort1.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type1 (Contextual Substitution) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmort2.c b/src/gxvalid/gxvmort2.c
index 9e69e12..73f418e 100644
--- a/src/gxvalid/gxvmort2.c
+++ b/src/gxvalid/gxvmort2.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type2 (Ligature Substitution) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -152,7 +152,7 @@
     GXV_32BIT_ALIGNMENT_VALIDATE( ligActionOffset );
     if ( p < lat_base )
     {
-      GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%d byte rewind)\n",
+      GXV_TRACE(( "too short offset 0x%04x: p < lat_base (%ld byte rewind)\n",
                   ligActionOffset, lat_base - p ));
 
       /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
@@ -160,7 +160,7 @@
     }
     else if ( lat_limit < p )
     {
-      GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%d byte overrun)\n",
+      GXV_TRACE(( "too large offset 0x%04x: lat_limit < p (%ld byte overrun)\n",
                   ligActionOffset, p - lat_limit ));
 
       /* FontValidator, ftxvalidator, ftxdumperfuser warn but continue */
@@ -187,17 +187,17 @@
       offset = lig_action & 0x3FFFFFFFUL;
       if ( offset * 2 < optdata->ligatureTable )
       {
-        GXV_TRACE(( "too short offset 0x%08x:"
-                    " 2 x offset < ligatureTable (%d byte rewind)\n",
+        GXV_TRACE(( "too short offset 0x%08lx:"
+                    " 2 x offset < ligatureTable (%lu byte rewind)\n",
                      offset, optdata->ligatureTable - offset * 2 ));
 
         GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
       } else if ( offset * 2 >
                   optdata->ligatureTable + optdata->ligatureTable_length )
       {
-        GXV_TRACE(( "too long offset 0x%08x:"
+        GXV_TRACE(( "too long offset 0x%08lx:"
                     " 2 x offset > ligatureTable + ligatureTable_length"
-                    " (%d byte overrun)\n",
+                    " (%lu byte overrun)\n",
                      offset,
                      optdata->ligatureTable + optdata->ligatureTable_length
                      - offset * 2 ));
diff --git a/src/gxvalid/gxvmort4.c b/src/gxvalid/gxvmort4.c
index 4584d20..1b0dd3e 100644
--- a/src/gxvalid/gxvmort4.c
+++ b/src/gxvalid/gxvmort4.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type4 (Non-Contextual Glyph Substitution) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmort5.c b/src/gxvalid/gxvmort5.c
index a15a24f..cfbf312 100644
--- a/src/gxvalid/gxvmort5.c
+++ b/src/gxvalid/gxvmort5.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT mort table validation
  *   body for type5 (Contextual Glyph Insertion) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -63,7 +63,7 @@
     *GXV_mort_subtable_type5_StateOptRecData;
 
 
-  FT_LOCAL_DEF( void )
+  static void
   gxv_mort_subtable_type5_subtable_setup( FT_UShort      table_size,
                                           FT_UShort      classTable,
                                           FT_UShort      stateArray,
diff --git a/src/gxvalid/gxvmorx.c b/src/gxvalid/gxvmorx.c
index 754d9f8..babff51 100644
--- a/src/gxvalid/gxvmorx.c
+++ b/src/gxvalid/gxvmorx.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT morx table validation (body).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -84,7 +84,7 @@
       p += 4;
 #endif
 
-      GXV_TRACE(( "validating chain subtable %d/%d (%d bytes)\n",
+      GXV_TRACE(( "validating chain subtable %d/%d (%lu bytes)\n",
                   i + 1, nSubtables, length ));
 
       type = coverage & 0x0007;
@@ -99,7 +99,7 @@
 
       func = fmt_funcs_table[type];
       if ( !func )
-        GXV_TRACE(( "morx type %d is reserved\n", type ));
+        GXV_TRACE(( "morx type %lu is reserved\n", type ));
 
       func( p, p + rest, gxvalid );
 
@@ -186,7 +186,7 @@
 
     for ( i = 0; i < nChains; i++ )
     {
-      GXV_TRACE(( "validating chain %d/%d\n", i + 1, nChains ));
+      GXV_TRACE(( "validating chain %lu/%lu\n", i + 1, nChains ));
       GXV_32BIT_ALIGNMENT_VALIDATE( p - table );
       gxv_morx_chain_validate( p, limit, gxvalid );
       p += gxvalid->subtable_length;
diff --git a/src/gxvalid/gxvmorx.h b/src/gxvalid/gxvmorx.h
index f747b1d..f155f18 100644
--- a/src/gxvalid/gxvmorx.h
+++ b/src/gxvalid/gxvmorx.h
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT common definition for morx table (specification).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmorx0.c b/src/gxvalid/gxvmorx0.c
index 5a42e55..e93cea9 100644
--- a/src/gxvalid/gxvmorx0.c
+++ b/src/gxvalid/gxvmorx0.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for type0 (Indic Script Rearrangement) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmorx1.c b/src/gxvalid/gxvmorx1.c
index 9f8b690..d380f8d 100644
--- a/src/gxvalid/gxvmorx1.c
+++ b/src/gxvalid/gxvmorx1.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for type1 (Contextual Substitution) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmorx2.c b/src/gxvalid/gxvmorx2.c
index 98b5c49..e7e008f 100644
--- a/src/gxvalid/gxvmorx2.c
+++ b/src/gxvalid/gxvmorx2.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for type2 (Ligature Substitution) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -72,11 +72,11 @@
     optdata->componentTable = FT_NEXT_ULONG( p );
     optdata->ligatureTable  = FT_NEXT_ULONG( p );
 
-    GXV_TRACE(( "offset to ligActionTable=0x%08x\n",
+    GXV_TRACE(( "offset to ligActionTable=0x%08lx\n",
                 optdata->ligActionTable ));
-    GXV_TRACE(( "offset to componentTable=0x%08x\n",
+    GXV_TRACE(( "offset to componentTable=0x%08lx\n",
                 optdata->componentTable ));
-    GXV_TRACE(( "offset to ligatureTable=0x%08x\n",
+    GXV_TRACE(( "offset to ligatureTable=0x%08lx\n",
                 optdata->ligatureTable ));
   }
 
@@ -116,19 +116,19 @@
 
     gxv_set_length_by_ulong_offset( o, l, buff, 6, table_size, gxvalid );
 
-    GXV_TRACE(( "classTable: offset=0x%08x length=0x%08x\n",
+    GXV_TRACE(( "classTable: offset=0x%08lx length=0x%08lx\n",
                 classTable, *classTable_length_p ));
-    GXV_TRACE(( "stateArray: offset=0x%08x length=0x%08x\n",
+    GXV_TRACE(( "stateArray: offset=0x%08lx length=0x%08lx\n",
                 stateArray, *stateArray_length_p ));
-    GXV_TRACE(( "entryTable: offset=0x%08x length=0x%08x\n",
+    GXV_TRACE(( "entryTable: offset=0x%08lx length=0x%08lx\n",
                 entryTable, *entryTable_length_p ));
-    GXV_TRACE(( "ligActionTable: offset=0x%08x length=0x%08x\n",
+    GXV_TRACE(( "ligActionTable: offset=0x%08lx length=0x%08lx\n",
                 optdata->ligActionTable,
                 optdata->ligActionTable_length ));
-    GXV_TRACE(( "componentTable: offset=0x%08x length=0x%08x\n",
+    GXV_TRACE(( "componentTable: offset=0x%08lx length=0x%08lx\n",
                 optdata->componentTable,
                 optdata->componentTable_length ));
-    GXV_TRACE(( "ligatureTable:  offset=0x%08x length=0x%08x\n",
+    GXV_TRACE(( "ligatureTable:  offset=0x%08lx length=0x%08lx\n",
                 optdata->ligatureTable,
                 optdata->ligatureTable_length ));
 
@@ -157,12 +157,12 @@
 
     if ( p < lat_base )
     {
-      GXV_TRACE(( "p < lat_base (%d byte rewind)\n", lat_base - p ));
+      GXV_TRACE(( "p < lat_base (%ld byte rewind)\n", lat_base - p ));
       FT_INVALID_OFFSET;
     }
     else if ( lat_limit < p )
     {
-      GXV_TRACE(( "lat_limit < p (%d byte overrun)\n", p - lat_limit ));
+      GXV_TRACE(( "lat_limit < p (%ld byte overrun)\n", p - lat_limit ));
       FT_INVALID_OFFSET;
     }
 
@@ -196,7 +196,7 @@
 
         GXV_TRACE(( "ligature action table includes"
                     " too negative offset moving all GID"
-                    " below defined range: 0x%04x\n",
+                    " below defined range: 0x%04lx\n",
                     offset & 0xFFFFU ));
         GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
       }
@@ -207,14 +207,14 @@
 
         GXV_TRACE(( "ligature action table includes"
                     " too large offset moving all GID"
-                    " over defined range: 0x%04x\n",
+                    " over defined range: 0x%04lx\n",
                     offset & 0xFFFFU ));
         GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
       }
 
       GXV_TRACE(( "ligature action table includes"
                   " invalid offset to add to 16-bit GID:"
-                  " 0x%08x\n", offset ));
+                  " 0x%08lx\n", offset ));
       GXV_SET_ERR_IF_PARANOID( FT_INVALID_OFFSET );
     }
   }
diff --git a/src/gxvalid/gxvmorx4.c b/src/gxvalid/gxvmorx4.c
index 857e4d4..e632e8d 100644
--- a/src/gxvalid/gxvmorx4.c
+++ b/src/gxvalid/gxvmorx4.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for "morx" type4 (Non-Contextual Glyph Substitution) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvmorx5.c b/src/gxvalid/gxvmorx5.c
index 7ceba07..5ad3397 100644
--- a/src/gxvalid/gxvmorx5.c
+++ b/src/gxvalid/gxvmorx5.c
@@ -5,7 +5,7 @@
  *   TrueTypeGX/AAT morx table validation
  *   body for type5 (Contextual Glyph Insertion) subtable.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/gxvalid/gxvopbd.c b/src/gxvalid/gxvopbd.c
index a398fe0..7a2feab 100644
--- a/src/gxvalid/gxvopbd.c
+++ b/src/gxvalid/gxvopbd.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT opbd table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -188,7 +188,7 @@
 
 
     /* only 0x00010000 is defined (1996) */
-    GXV_TRACE(( "(version=0x%08x)\n", version ));
+    GXV_TRACE(( "(version=0x%08lx)\n", version ));
     if ( 0x00010000UL != version )
       FT_INVALID_FORMAT;
 
diff --git a/src/gxvalid/gxvprop.c b/src/gxvalid/gxvprop.c
index bee8bab..98cd368 100644
--- a/src/gxvalid/gxvprop.c
+++ b/src/gxvalid/gxvprop.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT prop table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -283,7 +283,7 @@
     format      = FT_NEXT_USHORT( p );
     defaultProp = FT_NEXT_USHORT( p );
 
-    GXV_TRACE(( "  version 0x%08x\n", version ));
+    GXV_TRACE(( "  version 0x%08lx\n", version ));
     GXV_TRACE(( "  format  0x%04x\n", format ));
     GXV_TRACE(( "  defaultProp  0x%04x\n", defaultProp ));
 
@@ -309,7 +309,7 @@
     if ( format == 0 )
     {
       FT_TRACE3(( "(format 0, no per-glyph properties, "
-                  "remaining %d bytes are skipped)", limit - p ));
+                  "remaining %ld bytes are skipped)", limit - p ));
       goto Exit;
     }
 
diff --git a/src/gxvalid/gxvtrak.c b/src/gxvalid/gxvtrak.c
index 58a631c..c1ed928 100644
--- a/src/gxvalid/gxvtrak.c
+++ b/src/gxvalid/gxvtrak.c
@@ -4,7 +4,7 @@
  *
  *   TrueTypeGX/AAT trak table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
@@ -130,7 +130,7 @@
          p = table + j * ( 4 + 2 + 2 );
          t = FT_NEXT_LONG( p );
          if ( t == track )
-           GXV_TRACE(( "duplicated entries found for track value 0x%x\n",
+           GXV_TRACE(( "duplicated entries found for track value 0x%lx\n",
                         track ));
       }
     }
@@ -243,7 +243,7 @@
     vertOffset  = FT_NEXT_USHORT( p );
     reserved    = FT_NEXT_USHORT( p );
 
-    GXV_TRACE(( " (version = 0x%08x)\n", version ));
+    GXV_TRACE(( " (version = 0x%08lx)\n", version ));
     GXV_TRACE(( " (format = 0x%04x)\n", format ));
     GXV_TRACE(( " (horizOffset = 0x%04x)\n", horizOffset ));
     GXV_TRACE(( " (vertOffset = 0x%04x)\n", vertOffset ));
diff --git a/src/gxvalid/module.mk b/src/gxvalid/module.mk
index e7d408d..efb9c92 100644
--- a/src/gxvalid/module.mk
+++ b/src/gxvalid/module.mk
@@ -2,7 +2,7 @@
 # FreeType 2 gxvalid module definition
 #
 
-# Copyright (C) 2004-2020 by
+# Copyright (C) 2004-2021 by
 # suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
diff --git a/src/gxvalid/rules.mk b/src/gxvalid/rules.mk
index d55a493..8e0b453 100644
--- a/src/gxvalid/rules.mk
+++ b/src/gxvalid/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2004-2020 by
+# Copyright (C) 2004-2021 by
 # suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c
index de7d0fd..8f98a7d 100644
--- a/src/gzip/ftgzip.c
+++ b/src/gzip/ftgzip.c
@@ -8,7 +8,7 @@
  * parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -121,24 +121,29 @@
      'malloc/free' */
 
   static voidpf
-  ft_gzip_alloc( FT_Memory  memory,
-                 uInt       items,
-                 uInt       size )
+  ft_gzip_alloc( voidpf  opaque,
+                 uInt    items,
+                 uInt    size )
   {
-    FT_ULong    sz = (FT_ULong)size * items;
+    FT_Memory   memory = (FT_Memory)opaque;
+    FT_ULong    sz     = (FT_ULong)size * items;
     FT_Error    error;
-    FT_Pointer  p  = NULL;
+    FT_Pointer  p      = NULL;
 
 
-    (void)FT_ALLOC( p, sz );
+    /* allocate and zero out */
+    FT_MEM_ALLOC( p, sz );
     return p;
   }
 
 
   static void
-  ft_gzip_free( FT_Memory  memory,
-                voidpf     address )
+  ft_gzip_free( voidpf  opaque,
+                voidpf  address )
   {
+    FT_Memory  memory = (FT_Memory)opaque;
+
+
     FT_MEM_FREE( address );
   }
 
@@ -150,14 +155,14 @@
             unsigned  items,
             unsigned  size )
   {
-    return ft_gzip_alloc( (FT_Memory)opaque, items, size );
+    return ft_gzip_alloc( opaque, items, size );
   }
 
   local void
   zcfree( voidpf  opaque,
           voidpf  ptr )
   {
-    ft_gzip_free( (FT_Memory)opaque, ptr );
+    ft_gzip_free( opaque, ptr );
   }
 
 #endif /* !SYSTEM_ZLIB && !USE_ZLIB_ZCALLOC */
@@ -304,8 +309,8 @@
     }
 
     /* initialize zlib -- there is no zlib header in the compressed stream */
-    zstream->zalloc = (alloc_func)ft_gzip_alloc;
-    zstream->zfree  = (free_func) ft_gzip_free;
+    zstream->zalloc = ft_gzip_alloc;
+    zstream->zfree  = ft_gzip_free;
     zstream->opaque = stream->memory;
 
     zstream->avail_in = 0;
@@ -462,12 +467,13 @@
                             FT_ULong     count )
   {
     FT_Error  error = FT_Err_Ok;
-    FT_ULong  delta;
 
 
     for (;;)
     {
-      delta = (FT_ULong)( zip->limit - zip->cursor );
+      FT_ULong  delta = (FT_ULong)( zip->limit - zip->cursor );
+
+
       if ( delta >= count )
         delta = count;
 
@@ -671,7 +677,7 @@
         FT_Byte*  zip_buff = NULL;
 
 
-        if ( !FT_ALLOC( zip_buff, zip_size ) )
+        if ( !FT_QALLOC( zip_buff, zip_size ) )
         {
           FT_ULong  count;
 
@@ -741,8 +747,8 @@
     stream.next_out  = output;
     stream.avail_out = (uInt)*output_len;
 
-    stream.zalloc = (alloc_func)ft_gzip_alloc;
-    stream.zfree  = (free_func) ft_gzip_free;
+    stream.zalloc = ft_gzip_alloc;
+    stream.zfree  = ft_gzip_free;
     stream.opaque = memory;
 
     /* This is a temporary fix and will be removed once the internal
diff --git a/src/gzip/rules.mk b/src/gzip/rules.mk
index 4ea823f..1a90ae8 100644
--- a/src/gzip/rules.mk
+++ b/src/gzip/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2002-2020 by
+# Copyright (C) 2002-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/lzw/ftlzw.c b/src/lzw/ftlzw.c
index ddb81e6..e112418 100644
--- a/src/lzw/ftlzw.c
+++ b/src/lzw/ftlzw.c
@@ -8,7 +8,7 @@
  * be used to parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * Albert Chin-A-Young.
  *
  * based on code in `src/gzip/ftgzip.c'
@@ -383,7 +383,7 @@
 
     stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
     stream->pos   = 0;
-    stream->base  = 0;
+    stream->base  = NULL;
     stream->read  = ft_lzw_stream_io;
     stream->close = ft_lzw_stream_close;
 
diff --git a/src/lzw/ftzopen.c b/src/lzw/ftzopen.c
index 884d2ec..8b5b357 100644
--- a/src/lzw/ftzopen.c
+++ b/src/lzw/ftzopen.c
@@ -8,7 +8,7 @@
  * be used to parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -127,6 +127,7 @@
 
       new_size = new_size + ( new_size >> 1 ) + 4;
 
+      /* if relocating to heap */
       if ( state->stack == state->stack_0 )
       {
         state->stack = NULL;
@@ -142,9 +143,13 @@
           return -1;
       }
 
-      if ( FT_RENEW_ARRAY( state->stack, old_size, new_size ) )
+      if ( FT_QRENEW_ARRAY( state->stack, old_size, new_size ) )
         return -1;
 
+      /* if relocating to heap */
+      if ( old_size == 0 )
+        FT_MEM_COPY( state->stack, state->stack_0, FT_LZW_DEFAULT_STACK_SIZE );
+
       state->stack_size = new_size;
     }
     return 0;
diff --git a/src/lzw/ftzopen.h b/src/lzw/ftzopen.h
index d8768f7..9ada742 100644
--- a/src/lzw/ftzopen.h
+++ b/src/lzw/ftzopen.h
@@ -8,7 +8,7 @@
  * be used to parse compressed PCF fonts, as found with many X11 server
  * distributions.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/lzw/rules.mk b/src/lzw/rules.mk
index 3468ee0..747cbdc 100644
--- a/src/lzw/rules.mk
+++ b/src/lzw/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2004-2020 by
+# Copyright (C) 2004-2021 by
 # Albert Chin-A-Young.
 #
 # based on `src/lzw/rules.mk'
diff --git a/src/otvalid/module.mk b/src/otvalid/module.mk
index 67b9820..3009349 100644
--- a/src/otvalid/module.mk
+++ b/src/otvalid/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2004-2020 by
+# Copyright (C) 2004-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/otvalid/otvalid.c b/src/otvalid/otvalid.c
index d640209..869233c 100644
--- a/src/otvalid/otvalid.c
+++ b/src/otvalid/otvalid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType validator for OpenType tables (body only).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvalid.h b/src/otvalid/otvalid.h
index 8208ff0..f8ca454 100644
--- a/src/otvalid/otvalid.h
+++ b/src/otvalid/otvalid.h
@@ -4,7 +4,7 @@
  *
  *   OpenType table validation (specification only).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvbase.c b/src/otvalid/otvbase.c
index 250ae98..83f998c 100644
--- a/src/otvalid/otvbase.c
+++ b/src/otvalid/otvbase.c
@@ -4,7 +4,7 @@
  *
  *   OpenType BASE table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvcommn.c b/src/otvalid/otvcommn.c
index faaa846..40624bb 100644
--- a/src/otvalid/otvcommn.c
+++ b/src/otvalid/otvcommn.c
@@ -4,7 +4,7 @@
  *
  *   OpenType common tables validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvcommn.h b/src/otvalid/otvcommn.h
index f992603..3b096ec 100644
--- a/src/otvalid/otvcommn.h
+++ b/src/otvalid/otvcommn.h
@@ -4,7 +4,7 @@
  *
  *   OpenType common tables validation (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -105,10 +105,11 @@
                 FT_Byte*  pp = (FT_Byte*)_size ## _p;               \
                                                                     \
                                                                     \
-                FT_TRACE3(( "\n"                                    \
-                            "Invalid offset to optional table `%s'" \
-                            " set to zero.\n"                       \
-                            "\n", #_size ));                        \
+                FT_TRACE3(( "\n" ));                                \
+                FT_TRACE3(( "Invalid offset to optional table `%s'" \
+                            " set to zero.\n",                      \
+                            #_size ));                              \
+                FT_TRACE3(( "\n" ));                                \
                                                                     \
                 _size = pp[0] = pp[1] = 0;                          \
               }                                                     \
@@ -127,10 +128,11 @@
                 FT_Byte*  pp = (FT_Byte*)_size ## _p;               \
                                                                     \
                                                                     \
-                FT_TRACE3(( "\n"                                    \
-                            "Invalid offset to optional table `%s'" \
-                            " set to zero.\n"                       \
-                            "\n", #_size ));                        \
+                FT_TRACE3(( "\n" ));                                \
+                FT_TRACE3(( "Invalid offset to optional table `%s'" \
+                            " set to zero.\n",                      \
+                            #_size ));                              \
+                FT_TRACE3(( "\n" ));                                \
                                                                     \
                 _size = pp[0] = pp[1] = pp[2] = pp[3] = 0;          \
               }                                                     \
@@ -178,24 +180,24 @@
 #define OTV_ENTER                                                                \
           FT_BEGIN_STMNT                                                         \
             otvalid->debug_indent += 2;                                          \
-            FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 ));                     \
+            FT_TRACE4(( "%*.s", otvalid->debug_indent, "" ));                    \
             FT_TRACE4(( "%s table\n",                                            \
                         otvalid->debug_function_name[otvalid->nesting_level] )); \
           FT_END_STMNT
 
-#define OTV_NAME_ENTER( name )                               \
-          FT_BEGIN_STMNT                                     \
-            otvalid->debug_indent += 2;                      \
-            FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \
-            FT_TRACE4(( "%s table\n", name ));               \
+#define OTV_NAME_ENTER( name )                                \
+          FT_BEGIN_STMNT                                      \
+            otvalid->debug_indent += 2;                       \
+            FT_TRACE4(( "%*.s", otvalid->debug_indent, "" )); \
+            FT_TRACE4(( "%s table\n", name ));                \
           FT_END_STMNT
 
 #define OTV_EXIT  otvalid->debug_indent -= 2
 
-#define OTV_TRACE( s )                                       \
-          FT_BEGIN_STMNT                                     \
-            FT_TRACE4(( "%*.s", otvalid->debug_indent, 0 )); \
-            FT_TRACE4( s );                                  \
+#define OTV_TRACE( s )                                        \
+          FT_BEGIN_STMNT                                      \
+            FT_TRACE4(( "%*.s", otvalid->debug_indent, "" )); \
+            FT_TRACE4( s );                                   \
           FT_END_STMNT
 
 #else   /* !FT_DEBUG_LEVEL_TRACE */
diff --git a/src/otvalid/otverror.h b/src/otvalid/otverror.h
index 979e9cb..3e23234 100644
--- a/src/otvalid/otverror.h
+++ b/src/otvalid/otverror.h
@@ -4,7 +4,7 @@
  *
  *   OpenType validation module error codes (specification only).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvgdef.c b/src/otvalid/otvgdef.c
index 88874b8..5a160a4 100644
--- a/src/otvalid/otvgdef.c
+++ b/src/otvalid/otvgdef.c
@@ -4,7 +4,7 @@
  *
  *   OpenType GDEF table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvgpos.c b/src/otvalid/otvgpos.c
index 29d56f9..e0d4e42 100644
--- a/src/otvalid/otvgpos.c
+++ b/src/otvalid/otvgpos.c
@@ -4,7 +4,7 @@
  *
  *   OpenType GPOS table validation (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvgpos.h b/src/otvalid/otvgpos.h
index 06a03a0..176a688 100644
--- a/src/otvalid/otvgpos.h
+++ b/src/otvalid/otvgpos.h
@@ -4,7 +4,7 @@
  *
  *   OpenType GPOS table validator (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvgsub.c b/src/otvalid/otvgsub.c
index f0d563b..b426a17 100644
--- a/src/otvalid/otvgsub.c
+++ b/src/otvalid/otvgsub.c
@@ -4,7 +4,7 @@
  *
  *   OpenType GSUB table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvjstf.c b/src/otvalid/otvjstf.c
index 79de7b8..404dda8 100644
--- a/src/otvalid/otvjstf.c
+++ b/src/otvalid/otvjstf.c
@@ -4,7 +4,7 @@
  *
  *   OpenType JSTF table validation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/otvmath.c b/src/otvalid/otvmath.c
index dfdeaab..b4bfabb 100644
--- a/src/otvalid/otvmath.c
+++ b/src/otvalid/otvmath.c
@@ -4,7 +4,7 @@
  *
  *   OpenType MATH table validation (body).
  *
- * Copyright (C) 2007-2020 by
+ * Copyright (C) 2007-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Written by George Williams.
@@ -141,7 +141,7 @@
     OTV_OPTIONAL_TABLE( DeviceTableOffset );
 
 
-    /* OTV_NAME_ENTER( "MathKern" );*/
+    /* OTV_NAME_ENTER( "MathKern" ); */
 
     OTV_LIMIT_CHECK( 2 );
 
diff --git a/src/otvalid/otvmod.c b/src/otvalid/otvmod.c
index 0188b27..b7d674b 100644
--- a/src/otvalid/otvmod.c
+++ b/src/otvalid/otvmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType's OpenType validation module implementation (body).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -53,7 +53,7 @@
     if ( error )
       goto Exit;
 
-    if ( FT_ALLOC( *table, *table_len ) )
+    if ( FT_QALLOC( *table, *table_len ) )
       goto Exit;
 
     error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len );
@@ -94,7 +94,7 @@
      */
     if ( face->num_glyphs > 0xFFFFL )
     {
-      FT_TRACE1(( "otv_validate: Invalid glyphs index (0x0000FFFF - 0x%08x) ",
+      FT_TRACE1(( "otv_validate: Invalid glyphs index (0x0000FFFF - 0x%08lx) ",
                   face->num_glyphs ));
       FT_TRACE1(( "are not handled by OpenType tables\n" ));
       num_glyphs = 0xFFFF;
diff --git a/src/otvalid/otvmod.h b/src/otvalid/otvmod.h
index efd6da0..37c20e0 100644
--- a/src/otvalid/otvmod.h
+++ b/src/otvalid/otvmod.h
@@ -5,7 +5,7 @@
  *   FreeType's OpenType validation module implementation
  *   (specification).
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/otvalid/rules.mk b/src/otvalid/rules.mk
index 7f0169f..634a350 100644
--- a/src/otvalid/rules.mk
+++ b/src/otvalid/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2004-2020 by
+# Copyright (C) 2004-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/pcf/pcfdrivr.c b/src/pcf/pcfdrivr.c
index e9dd517..2a40af9 100644
--- a/src/pcf/pcfdrivr.c
+++ b/src/pcf/pcfdrivr.c
@@ -606,7 +606,7 @@
         if ( prop->value.l > 0x7FFFFFFFL          ||
              prop->value.l < ( -1 - 0x7FFFFFFFL ) )
         {
-          FT_TRACE1(( "pcf_get_bdf_property:"
+          FT_TRACE2(( "pcf_get_bdf_property:"
                       " too large integer 0x%lx is truncated\n",
                       prop->value.l ));
         }
@@ -705,7 +705,7 @@
 
 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
 
-    FT_TRACE0(( "pcf_property_set: missing property `%s'\n",
+    FT_TRACE2(( "pcf_property_set: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
   }
@@ -743,7 +743,7 @@
 
 #endif /* !PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */
 
-    FT_TRACE0(( "pcf_property_get: missing property `%s'\n",
+    FT_TRACE2(( "pcf_property_get: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
   }
diff --git a/src/pcf/pcfread.c b/src/pcf/pcfread.c
index 8817682..e60a0a5 100644
--- a/src/pcf/pcfread.c
+++ b/src/pcf/pcfread.c
@@ -127,7 +127,7 @@
       toc->count = FT_MIN( stream->size >> 4, 9 );
     }
 
-    if ( FT_NEW_ARRAY( face->toc.tables, toc->count ) )
+    if ( FT_QNEW_ARRAY( face->toc.tables, toc->count ) )
       return error;
 
     tables = face->toc.tables;
@@ -238,7 +238,7 @@
       {
         for ( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] );
               j++ )
-          if ( tables[i].type == (FT_UInt)( 1 << j ) )
+          if ( tables[i].type == 1UL << j )
             name = tableNames[j];
 
         FT_TRACE4(( "  %d: type=%s, format=0x%lX,"
@@ -501,8 +501,8 @@
     if ( FT_READ_ULONG_LE( format ) )
       goto Bail;
 
-    FT_TRACE4(( "pcf_get_properties:\n"
-                "  format: 0x%lX (%s)\n",
+    FT_TRACE4(( "pcf_get_properties:\n" ));
+    FT_TRACE4(( "  format: 0x%lX (%s)\n",
                 format,
                 PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" ));
 
@@ -540,7 +540,7 @@
 
     face->nprops = (int)nprops;
 
-    if ( FT_NEW_ARRAY( props, nprops ) )
+    if ( FT_QNEW_ARRAY( props, nprops ) )
       goto Bail;
 
     for ( i = 0; i < nprops; i++ )
@@ -607,13 +607,13 @@
     }
 
     /* allocate one more byte so that we have a final null byte */
-    if ( FT_NEW_ARRAY( strings, string_size + 1 ) )
+    if ( FT_QALLOC( strings, string_size + 1 )  ||
+         FT_STREAM_READ( strings, string_size ) )
       goto Bail;
 
-    error = FT_Stream_Read( stream, (FT_Byte*)strings, string_size );
-    if ( error )
-      goto Bail;
+    strings[string_size] = '\0';
 
+    /* zero out in case of failure */
     if ( FT_NEW_ARRAY( properties, nprops ) )
       goto Bail;
 
@@ -697,8 +697,8 @@
     if ( FT_READ_ULONG_LE( format ) )
       goto Bail;
 
-    FT_TRACE4(( "pcf_get_metrics:\n"
-                "  format: 0x%lX (%s, %s)\n",
+    FT_TRACE4(( "pcf_get_metrics:\n" ));
+    FT_TRACE4(( "  format: 0x%lX (%s, %s)\n",
                 format,
                 PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB",
                 PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) ?
@@ -767,7 +767,7 @@
 
     face->nmetrics = nmetrics + 1;
 
-    if ( FT_NEW_ARRAY( face->metrics, face->nmetrics ) )
+    if ( FT_QNEW_ARRAY( face->metrics, face->nmetrics ) )
       return error;
 
     /* we handle glyph index 0 later on */
@@ -840,17 +840,16 @@
 
     FT_Stream_ExitFrame( stream );
 
-    FT_TRACE4(( "pcf_get_bitmaps:\n"
-                "  format: 0x%lX\n"
-                "          (%s, %s,\n"
-                "           padding=%d bit%s, scanning=%d bit%s)\n",
-                format,
+    FT_TRACE4(( "pcf_get_bitmaps:\n" ));
+    FT_TRACE4(( "  format: 0x%lX\n", format ));
+    FT_TRACE4(( "          (%s, %s,\n",
                 PCF_BYTE_ORDER( format ) == MSBFirst
                   ? "most significant byte first"
                   : "least significant byte first",
                 PCF_BIT_ORDER( format ) == MSBFirst
                   ? "most significant bit first"
-                  : "least significant bit first",
+                  : "least significant bit first" ));
+    FT_TRACE4(( "           padding=%d bit%s, scanning=%d bit%s)\n",
                 8 << PCF_GLYPH_PAD_INDEX( format ),
                 ( 8 << PCF_GLYPH_PAD_INDEX( format ) ) == 1 ? "" : "s",
                 8 << PCF_SCAN_UNIT_INDEX( format ),
@@ -1001,8 +1000,8 @@
     if ( FT_READ_ULONG_LE( format ) )
       goto Bail;
 
-    FT_TRACE4(( "pcf_get_encodings:\n"
-                "  format: 0x%lX (%s)\n",
+    FT_TRACE4(( "pcf_get_encodings:\n" ));
+    FT_TRACE4(( "  format: 0x%lX (%s)\n",
                 format,
                 PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB" ));
 
@@ -1021,11 +1020,11 @@
         goto Bail;
     }
 
-    FT_TRACE4(( "  firstCol 0x%X, lastCol 0x%X\n"
-                "  firstRow 0x%X, lastRow 0x%X\n"
-                "  defaultChar 0x%X\n",
-                enc->firstCol, enc->lastCol,
-                enc->firstRow, enc->lastRow,
+    FT_TRACE4(( "  firstCol 0x%X, lastCol 0x%X\n",
+                enc->firstCol, enc->lastCol ));
+    FT_TRACE4(( "  firstRow 0x%X, lastRow 0x%X\n",
+                enc->firstRow, enc->lastRow ));
+    FT_TRACE4(( "  defaultChar 0x%X\n",
                 enc->defaultChar ));
 
     /* sanity checks; we limit numbers of rows and columns to 256 */
@@ -1088,8 +1087,8 @@
     if ( defaultCharEncodingOffset == 0xFFFF )
     {
       FT_TRACE0(( "pcf_get_encodings:"
-                  " No glyph for default character,\n"
-                  "                  "
+                  " No glyph for default character,\n" ));
+      FT_TRACE0(( "                  "
                   " setting it to the first glyph of the font\n" ));
       defaultCharEncodingOffset = 1;
     }
@@ -1100,8 +1099,8 @@
       if ( defaultCharEncodingOffset >= face->nmetrics )
       {
         FT_TRACE0(( "pcf_get_encodings:"
-                    " Invalid glyph index for default character,\n"
-                    "                  "
+                    " Invalid glyph index for default character,\n" ));
+        FT_TRACE0(( "                  "
                     " setting it to the first glyph of the font\n" ));
         defaultCharEncodingOffset = 1;
       }
@@ -1208,10 +1207,10 @@
     if ( FT_READ_ULONG_LE( format ) )
       goto Bail;
 
-    FT_TRACE4(( "pcf_get_accel%s:\n"
-                "  format: 0x%lX (%s, %s)\n",
+    FT_TRACE4(( "pcf_get_accel%s:\n",
                 type == PCF_BDF_ACCELERATORS ? " (getting BDF accelerators)"
-                                             : "",
+                                             : "" ));
+    FT_TRACE4(( "  format: 0x%lX (%s, %s)\n",
                 format,
                 PCF_BYTE_ORDER( format ) == MSBFirst ? "MSB" : "LSB",
                 PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) ?
@@ -1233,16 +1232,16 @@
     }
 
     FT_TRACE5(( "  noOverlap=%s, constantMetrics=%s,"
-                " terminalFont=%s, constantWidth=%s\n"
-                "  inkInside=%s, inkMetrics=%s, drawDirection=%s\n"
-                "  fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n",
+                " terminalFont=%s, constantWidth=%s\n",
                 accel->noOverlap ? "yes" : "no",
                 accel->constantMetrics ? "yes" : "no",
                 accel->terminalFont ? "yes" : "no",
-                accel->constantWidth ? "yes" : "no",
+                accel->constantWidth ? "yes" : "no" ));
+    FT_TRACE5(( "  inkInside=%s, inkMetrics=%s, drawDirection=%s\n",
                 accel->inkInside ? "yes" : "no",
                 accel->inkMetrics ? "yes" : "no",
-                accel->drawDirection ? "RTL" : "LTR",
+                accel->drawDirection ? "RTL" : "LTR" ));
+    FT_TRACE5(( "  fontAscent=%ld, fontDescent=%ld, maxOverlap=%ld\n",
                 accel->fontAscent,
                 accel->fontDescent,
                 accel->maxOverlap ));
@@ -1369,7 +1368,7 @@
       char*  s;
 
 
-      if ( FT_ALLOC( face->style_name, len ) )
+      if ( FT_QALLOC( face->style_name, len ) )
         return error;
 
       s = face->style_name;
@@ -1533,7 +1532,7 @@
           {
             l += ft_strlen( foundry_prop->value.atom ) + 1;
 
-            if ( FT_NEW_ARRAY( root->family_name, l ) )
+            if ( FT_QALLOC( root->family_name, l ) )
               goto Exit;
 
             ft_strcpy( root->family_name, foundry_prop->value.atom );
@@ -1542,7 +1541,7 @@
           }
           else
           {
-            if ( FT_NEW_ARRAY( root->family_name, l ) )
+            if ( FT_QALLOC( root->family_name, l ) )
               goto Exit;
 
             ft_strcpy( root->family_name, prop->value.atom );
@@ -1566,7 +1565,7 @@
       root->num_glyphs = (FT_Long)face->nmetrics;
 
       root->num_fixed_sizes = 1;
-      if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
+      if ( FT_NEW( root->available_sizes ) )
         goto Exit;
 
       {
@@ -1574,8 +1573,6 @@
         FT_Short         resolution_x = 0, resolution_y = 0;
 
 
-        FT_ZERO( bsize );
-
         /* for simplicity, we take absolute values of integer properties */
 
 #if 0
@@ -1616,7 +1613,7 @@
         else
         {
           /* this is a heuristical value */
-          bsize->width = (FT_Short)FT_MulDiv( bsize->height, 2, 3 );
+          bsize->width = ( bsize->height * 2 + 1 ) / 3;
         }
 
         prop = pcf_find_property( face, "POINT_SIZE" );
diff --git a/src/pfr/module.mk b/src/pfr/module.mk
index 762353d..4f49e12 100644
--- a/src/pfr/module.mk
+++ b/src/pfr/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2002-2020 by
+# Copyright (C) 2002-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/pfr/pfr.c b/src/pfr/pfr.c
index 9264c77..4058ad5 100644
--- a/src/pfr/pfr.c
+++ b/src/pfr/pfr.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR driver component.
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrcmap.c b/src/pfr/pfrcmap.c
index ebc7b84..6a7f573 100644
--- a/src/pfr/pfrcmap.c
+++ b/src/pfr/pfrcmap.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR cmap handling (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrcmap.h b/src/pfr/pfrcmap.h
index a6d920c..17c02a2 100644
--- a/src/pfr/pfrcmap.h
+++ b/src/pfr/pfrcmap.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR cmap handling (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrdrivr.c b/src/pfr/pfrdrivr.c
index b143208..16b8f79 100644
--- a/src/pfr/pfrdrivr.c
+++ b/src/pfr/pfrdrivr.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR driver interface (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrdrivr.h b/src/pfr/pfrdrivr.h
index 7646b4d..6ff16fe 100644
--- a/src/pfr/pfrdrivr.h
+++ b/src/pfr/pfrdrivr.h
@@ -4,7 +4,7 @@
  *
  *   High-level Type PFR driver interface (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrerror.h b/src/pfr/pfrerror.h
index 33460ef..255696e 100644
--- a/src/pfr/pfrerror.h
+++ b/src/pfr/pfrerror.h
@@ -4,7 +4,7 @@
  *
  *   PFR error codes (specification only).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrgload.c b/src/pfr/pfrgload.c
index aa640c3..b400042 100644
--- a/src/pfr/pfrgload.c
+++ b/src/pfr/pfrgload.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR glyph loader (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrgload.h b/src/pfr/pfrgload.h
index f356b4c..b726d56 100644
--- a/src/pfr/pfrgload.h
+++ b/src/pfr/pfrgload.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR glyph loader (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c
index a2832e5..a9c1e28 100644
--- a/src/pfr/pfrload.c
+++ b/src/pfr/pfrload.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR loader (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -565,7 +565,7 @@
     if ( phy_font->font_id )
       goto Exit;
 
-    if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
+    if ( FT_QALLOC( phy_font->font_id, len + 1 ) )
       goto Exit;
 
     /* copy font ID name, and terminate it for safety */
@@ -601,7 +601,7 @@
 
     PFR_CHECK( count * 2 );
 
-    if ( FT_NEW_ARRAY( snaps, count ) )
+    if ( FT_QNEW_ARRAY( snaps, count ) )
       goto Exit;
 
     phy_font->vertical.stem_snaps = snaps;
@@ -761,7 +761,7 @@
 
     if ( ok )
     {
-      if ( FT_ALLOC( result, len + 1 ) )
+      if ( FT_QALLOC( result, len + 1 ) )
         goto Exit;
 
       FT_MEM_COPY( result, p, len );
@@ -953,7 +953,7 @@
 
       PFR_CHECK( count * 2 );
 
-      if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
+      if ( FT_QNEW_ARRAY( phy_font->blue_values, count ) )
         goto Fail;
 
       for ( n = 0; n < count; n++ )
diff --git a/src/pfr/pfrload.h b/src/pfr/pfrload.h
index 7615b9c..4f467d1 100644
--- a/src/pfr/pfrload.h
+++ b/src/pfr/pfrload.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR loader (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c
index 918e7fd..3080cb6 100644
--- a/src/pfr/pfrobjs.c
+++ b/src/pfr/pfrobjs.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR object methods (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -83,7 +83,11 @@
     /* load the header and check it */
     error = pfr_header_load( &face->header, stream );
     if ( error )
+    {
+      FT_TRACE2(( "  not a PFR font\n" ));
+      error = FT_THROW( Unknown_File_Format );
       goto Exit;
+    }
 
     if ( !pfr_header_check( &face->header ) )
     {
@@ -213,7 +217,7 @@
         FT_Memory        memory = pfrface->stream->memory;
 
 
-        if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) )
+        if ( FT_QNEW_ARRAY( pfrface->available_sizes, count ) )
           goto Exit;
 
         size   = pfrface->available_sizes;
diff --git a/src/pfr/pfrobjs.h b/src/pfr/pfrobjs.h
index 808822f..70b0539 100644
--- a/src/pfr/pfrobjs.h
+++ b/src/pfr/pfrobjs.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR object methods (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrsbit.c b/src/pfr/pfrsbit.c
index a6691e6..255fd58 100644
--- a/src/pfr/pfrsbit.c
+++ b/src/pfr/pfrsbit.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR bitmap loader (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -310,8 +310,8 @@
       if ( lim > limit )
       {
         FT_TRACE0(( "pfr_lookup_bitmap_data:"
-                    " number of bitmap records too large,\n"
-                    "                       "
+                    " number of bitmap records too large,\n" ));
+        FT_TRACE0(( "                       "
                     " thus ignoring all bitmaps in this strike\n" ));
         *flags &= ~PFR_BITMAP_VALID_CHARCODES;
       }
@@ -328,8 +328,8 @@
           if ( (FT_Long)code <= prev_code )
           {
             FT_TRACE0(( "pfr_lookup_bitmap_data:"
-                        " bitmap records are not sorted,\n"
-                        "                       "
+                        " bitmap records are not sorted,\n" ));
+            FT_TRACE0(( "                       "
                         " thus ignoring all bitmaps in this strike\n" ));
             *flags &= ~PFR_BITMAP_VALID_CHARCODES;
             break;
diff --git a/src/pfr/pfrsbit.h b/src/pfr/pfrsbit.h
index 8cb0de0..f50d801 100644
--- a/src/pfr/pfrsbit.h
+++ b/src/pfr/pfrsbit.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR bitmap loader (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pfr/pfrtypes.h b/src/pfr/pfrtypes.h
index 06fb82d..dc4fead 100644
--- a/src/pfr/pfrtypes.h
+++ b/src/pfr/pfrtypes.h
@@ -4,7 +4,7 @@
  *
  *   FreeType PFR data structures (specification only).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -109,7 +109,7 @@
 #define PFR_BITMAP_2BYTE_SIZE      0x02U
 #define PFR_BITMAP_3BYTE_OFFSET    0x04U
 
-  /*not part of the specification but used for implementation */
+  /* not part of the specification but used for implementation */
 #define PFR_BITMAP_CHARCODES_VALIDATED  0x40U
 #define PFR_BITMAP_VALID_CHARCODES      0x80U
 
diff --git a/src/pfr/rules.mk b/src/pfr/rules.mk
index a1fe82b..00c791f 100644
--- a/src/pfr/rules.mk
+++ b/src/pfr/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2002-2020 by
+# Copyright (C) 2002-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/psaux/afmparse.c b/src/psaux/afmparse.c
index 2d6a0d9..0ad1760 100644
--- a/src/psaux/afmparse.c
+++ b/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
  *
  *   AFM parser (body).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -29,6 +29,16 @@
 
   /**************************************************************************
    *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  afmparse
+
+
+  /**************************************************************************
+   *
    * AFM_Stream
    *
    * The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib.
@@ -586,21 +596,39 @@
   static FT_Error
   afm_parse_track_kern( AFM_Parser  parser )
   {
-    AFM_FontInfo   fi = parser->FontInfo;
+    AFM_FontInfo   fi     = parser->FontInfo;
+    AFM_Stream     stream = parser->stream;
     AFM_TrackKern  tk;
-    char*          key;
-    FT_Offset      len;
-    int            n = -1;
-    FT_Int         tmp;
+
+    char*      key;
+    FT_Offset  len;
+    int        n = -1;
+    FT_Int     tmp;
 
 
     if ( afm_parser_read_int( parser, &tmp ) )
         goto Fail;
 
     if ( tmp < 0 )
+    {
+      FT_ERROR(( "afm_parse_track_kern: invalid number of track kerns\n" ));
       goto Fail;
+    }
 
     fi->NumTrackKern = (FT_UInt)tmp;
+    FT_TRACE3(( "afm_parse_track_kern: %u track kern%s expected\n",
+                fi->NumTrackKern,
+                fi->NumTrackKern == 1 ? "" : "s" ));
+
+    /* Rough sanity check: The minimum line length of the `TrackKern` */
+    /* command is 20 characters (including the EOL character).        */
+    if ( (FT_ULong)( stream->limit - stream->cursor ) / 20 <
+           fi->NumTrackKern )
+    {
+      FT_ERROR(( "afm_parse_track_kern:"
+                 " number of track kern entries exceeds stream size\n" ));
+      goto Fail;
+    }
 
     if ( fi->NumTrackKern )
     {
@@ -623,7 +651,10 @@
         n++;
 
         if ( n >= (int)fi->NumTrackKern )
-          goto Fail;
+          {
+            FT_ERROR(( "afm_parse_track_kern: too many track kern data\n" ));
+            goto Fail;
+          }
 
         tk = fi->TrackKerns + n;
 
@@ -633,7 +664,12 @@
         shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
         shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
         if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
+        {
+          FT_ERROR(( "afm_parse_track_kern:"
+                     " insufficient number of parameters for entry %d\n",
+                     n ));
           goto Fail;
+        }
 
         tk->degree     = shared_vals[0].u.i;
         tk->min_ptsize = shared_vals[1].u.f;
@@ -646,7 +682,19 @@
       case AFM_TOKEN_ENDTRACKKERN:
       case AFM_TOKEN_ENDKERNDATA:
       case AFM_TOKEN_ENDFONTMETRICS:
-        fi->NumTrackKern = (FT_UInt)( n + 1 );
+        tmp = n + 1;
+        if ( (FT_UInt)tmp != fi->NumTrackKern )
+        {
+          FT_TRACE1(( "afm_parse_track_kern: %s%d track kern entr%s seen\n",
+                      tmp == 0 ? "" : "only ",
+                      tmp,
+                      tmp == 1 ? "y" : "ies" ));
+          fi->NumTrackKern = (FT_UInt)tmp;
+        }
+        else
+          FT_TRACE3(( "afm_parse_track_kern: %d track kern entr%s seen\n",
+                      tmp,
+                      tmp == 1 ? "y" : "ies" ));
         return FT_Err_Ok;
 
       case AFM_TOKEN_UNKNOWN:
@@ -667,7 +715,7 @@
 
 
   /* compare two kerning pairs */
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   afm_compare_kern_pairs( const void*  a,
                           const void*  b )
   {
@@ -690,7 +738,8 @@
   static FT_Error
   afm_parse_kern_pairs( AFM_Parser  parser )
   {
-    AFM_FontInfo  fi = parser->FontInfo;
+    AFM_FontInfo  fi     = parser->FontInfo;
+    AFM_Stream    stream = parser->stream;
     AFM_KernPair  kp;
     char*         key;
     FT_Offset     len;
@@ -702,9 +751,26 @@
       goto Fail;
 
     if ( tmp < 0 )
+    {
+      FT_ERROR(( "afm_parse_kern_pairs: invalid number of kern pairs\n" ));
       goto Fail;
+    }
 
     fi->NumKernPair = (FT_UInt)tmp;
+    FT_TRACE3(( "afm_parse_kern_pairs: %u kern pair%s expected\n",
+                fi->NumKernPair,
+                fi->NumKernPair == 1 ? "" : "s" ));
+
+    /* Rough sanity check: The minimum line length of the `KP`,    */
+    /* `KPH`,`KPX`, and `KPY` commands is 10 characters (including */
+    /* the EOL character).                                         */
+    if ( (FT_ULong)( stream->limit - stream->cursor ) / 10 <
+           fi->NumKernPair )
+    {
+      FT_ERROR(( "afm_parse_kern_pairs:"
+                 " number of kern pairs exceeds stream size\n" ));
+      goto Fail;
+    }
 
     if ( fi->NumKernPair )
     {
@@ -734,7 +800,10 @@
           n++;
 
           if ( n >= (int)fi->NumKernPair )
+          {
+            FT_ERROR(( "afm_parse_kern_pairs: too many kern pairs\n" ));
             goto Fail;
+          }
 
           kp = fi->KernPairs + n;
 
@@ -744,7 +813,12 @@
           shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;
           r = afm_parser_read_vals( parser, shared_vals, 4 );
           if ( r < 3 )
+          {
+            FT_ERROR(( "afm_parse_kern_pairs:"
+                       " insufficient number of parameters for entry %d\n",
+                       n ));
             goto Fail;
+          }
 
           /* index values can't be negative */
           kp->index1 = shared_vals[0].u.u;
@@ -766,7 +840,20 @@
       case AFM_TOKEN_ENDKERNPAIRS:
       case AFM_TOKEN_ENDKERNDATA:
       case AFM_TOKEN_ENDFONTMETRICS:
-        fi->NumKernPair = (FT_UInt)( n + 1 );
+        tmp = n + 1;
+        if ( (FT_UInt)tmp != fi->NumKernPair )
+        {
+          FT_TRACE1(( "afm_parse_kern_pairs: %s%d kern pair%s seen\n",
+                      tmp == 0 ? "" : "only ",
+                      tmp,
+                      tmp == 1 ? "" : "s" ));
+          fi->NumKernPair = (FT_UInt)tmp;
+        }
+        else
+          FT_TRACE3(( "afm_parse_kern_pairs: %d kern pair%s seen\n",
+                      tmp,
+                      tmp == 1 ? "" : "s" ));
+
         ft_qsort( fi->KernPairs, fi->NumKernPair,
                   sizeof ( AFM_KernPairRec ),
                   afm_compare_kern_pairs );
@@ -792,22 +879,43 @@
     char*      key;
     FT_Offset  len;
 
+    int  have_trackkern = 0;
+    int  have_kernpairs = 0;
+
 
     while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
     {
       switch ( afm_tokenize( key, len ) )
       {
       case AFM_TOKEN_STARTTRACKKERN:
+        if ( have_trackkern )
+        {
+          FT_ERROR(( "afm_parse_kern_data:"
+                     " invalid second horizontal track kern section\n" ));
+          goto Fail;
+        }
+
         error = afm_parse_track_kern( parser );
         if ( error )
           return error;
+
+        have_trackkern = 1;
         break;
 
       case AFM_TOKEN_STARTKERNPAIRS:
       case AFM_TOKEN_STARTKERNPAIRS0:
+        if ( have_kernpairs )
+        {
+          FT_ERROR(( "afm_parse_kern_data:"
+                     " invalid second horizontal kern pair section\n" ));
+          goto Fail;
+        }
+
         error = afm_parse_kern_pairs( parser );
         if ( error )
           return error;
+
+        have_kernpairs = 1;
         break;
 
       case AFM_TOKEN_ENDKERNDATA:
diff --git a/src/psaux/afmparse.h b/src/psaux/afmparse.h
index 16a3a3e..44b05b2 100644
--- a/src/psaux/afmparse.h
+++ b/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
  *
  *   AFM parser (specification).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/cffdecode.c b/src/psaux/cffdecode.c
index 3d2da1e..29b68a8 100644
--- a/src/psaux/cffdecode.c
+++ b/src/psaux/cffdecode.c
@@ -4,7 +4,7 @@
  *
  *   PostScript CFF (Type 2) decoding routines (body).
  *
- * Copyright (C) 2017-2020 by
+ * Copyright (C) 2017-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1871,7 +1871,7 @@
         case cff_op_put:
           {
             FT_Fixed  val = args[0];
-            FT_Int    idx = (FT_Int)( args[1] >> 16 );
+            FT_UInt   idx = (FT_UInt)( args[1] >> 16 );
 
 
             FT_TRACE4(( " put\n" ));
@@ -1880,20 +1880,20 @@
             /* didn't give a hard-coded size limit of the temporary */
             /* storage array; instead, an argument of the           */
             /* `MultipleMaster' operator set the size               */
-            if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
+            if ( idx < CFF_MAX_TRANS_ELEMENTS )
               decoder->buildchar[idx] = val;
           }
           break;
 
         case cff_op_get:
           {
-            FT_Int    idx = (FT_Int)( args[0] >> 16 );
+            FT_UInt   idx = (FT_UInt)( args[0] >> 16 );
             FT_Fixed  val = 0;
 
 
             FT_TRACE4(( " get\n" ));
 
-            if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
+            if ( idx < CFF_MAX_TRANS_ELEMENTS )
               val = decoder->buildchar[idx];
 
             args[0] = val;
@@ -1914,9 +1914,9 @@
           /* this operator was removed from the Type2 specification */
           /* in version 16-March-2000                               */
           {
-            FT_Int  reg_idx = (FT_Int)args[0];
-            FT_Int  idx     = (FT_Int)args[1];
-            FT_Int  count   = (FT_Int)args[2];
+            FT_UInt  reg_idx = (FT_UInt)args[0];
+            FT_UInt  idx     = (FT_UInt)args[1];
+            FT_UInt  count   = (FT_UInt)args[2];
 
 
             FT_TRACE4(( " load\n" ));
@@ -1924,11 +1924,11 @@
             /* since we currently don't handle interpolation of multiple */
             /* master fonts, we store a vector [1 0 0 ...] in the        */
             /* temporary storage array regardless of the Registry index  */
-            if ( reg_idx >= 0 && reg_idx <= 2             &&
-                 idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS &&
-                 count >= 0 && count <= num_axes          )
+            if ( reg_idx <= 2                 &&
+                 idx < CFF_MAX_TRANS_ELEMENTS &&
+                 count <= num_axes            )
             {
-              FT_Int  end, i;
+              FT_UInt  end, i;
 
 
               end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS );
@@ -2153,7 +2153,7 @@
                                       decoder->locals_bias );
 
 
-            FT_TRACE4(( " callsubr (idx %d, entering level %d)\n",
+            FT_TRACE4(( " callsubr (idx %d, entering level %ld)\n",
                         idx,
                         zone - decoder->zones + 1 ));
 
@@ -2197,7 +2197,7 @@
                                       decoder->globals_bias );
 
 
-            FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n",
+            FT_TRACE4(( " callgsubr (idx %d, entering level %ld)\n",
                         idx,
                         zone - decoder->zones + 1 ));
 
@@ -2236,7 +2236,7 @@
           break;
 
         case cff_op_return:
-          FT_TRACE4(( " return (leaving level %d)\n",
+          FT_TRACE4(( " return (leaving level %ld)\n",
                       decoder->zone - decoder->zones ));
 
           if ( decoder->zone <= decoder->zones )
@@ -2271,7 +2271,8 @@
 
     } /* while ip < limit */
 
-    FT_TRACE4(( "..end..\n\n" ));
+    FT_TRACE4(( "..end..\n" ));
+    FT_TRACE4(( "\n" ));
 
   Fail:
     return error;
diff --git a/src/psaux/cffdecode.h b/src/psaux/cffdecode.h
index 77a4962..b1314ed 100644
--- a/src/psaux/cffdecode.h
+++ b/src/psaux/cffdecode.h
@@ -4,7 +4,7 @@
  *
  *   PostScript CFF (Type 2) decoding routines (specification).
  *
- * Copyright (C) 2017-2020 by
+ * Copyright (C) 2017-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/module.mk b/src/psaux/module.mk
index 651db01..06f7e72 100644
--- a/src/psaux/module.mk
+++ b/src/psaux/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/psaux/psarrst.c b/src/psaux/psarrst.c
index 8751d27..70313d2 100644
--- a/src/psaux/psarrst.c
+++ b/src/psaux/psarrst.c
@@ -65,7 +65,6 @@
     arrstack->error     = error;
     arrstack->sizeItem  = sizeItem;
     arrstack->allocated = 0;
-    arrstack->chunk     = 10;    /* chunks of 10 items */
     arrstack->count     = 0;
     arrstack->totalSize = 0;
     arrstack->ptr       = NULL;
@@ -110,7 +109,7 @@
 
       FT_ASSERT( newSize > 0 );   /* avoid realloc with zero size */
 
-      if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) )
+      if ( !FT_QREALLOC( arrstack->ptr, arrstack->totalSize, newSize ) )
       {
         arrstack->allocated = numElements;
         arrstack->totalSize = newSize;
@@ -216,9 +215,9 @@
 
     if ( arrstack->count == arrstack->allocated )
     {
-      /* grow the buffer by one chunk */
+      /* increase the buffer size */
       if ( !cf2_arrstack_setNumElements(
-             arrstack, arrstack->allocated + arrstack->chunk ) )
+             arrstack, arrstack->allocated * 2 + 16 ) )
       {
         /* on error, ignore the push */
         return;
diff --git a/src/psaux/psarrst.h b/src/psaux/psarrst.h
index 098617b..31e5330 100644
--- a/src/psaux/psarrst.h
+++ b/src/psaux/psarrst.h
@@ -55,7 +55,6 @@
 
     size_t  sizeItem;       /* bytes per element             */
     size_t  allocated;      /* items allocated               */
-    size_t  chunk;          /* allocation increment in items */
     size_t  count;          /* number of elements allocated  */
     size_t  totalSize;      /* total bytes allocated         */
 
diff --git a/src/psaux/psaux.c b/src/psaux/psaux.c
index f428222..2960c8b 100644
--- a/src/psaux/psaux.c
+++ b/src/psaux/psaux.c
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript driver component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/psauxerr.h b/src/psaux/psauxerr.h
index 8b9a958..e8ee291 100644
--- a/src/psaux/psauxerr.h
+++ b/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
  *
  *   PS auxiliary module error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/psauxmod.c b/src/psaux/psauxmod.c
index e73ba22..52da233 100644
--- a/src/psaux/psauxmod.c
+++ b/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript module implementation (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/psauxmod.h b/src/psaux/psauxmod.h
index a6bebe4..e3e8063 100644
--- a/src/psaux/psauxmod.h
+++ b/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript module implementation (specification).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/psblues.c b/src/psaux/psblues.c
index 3878e9b..f9c864f 100644
--- a/src/psaux/psblues.c
+++ b/src/psaux/psblues.c
@@ -506,7 +506,8 @@
             /* guarantee minimum of 1 pixel overshoot */
             dsNew = FT_MIN(
                       cf2_fixedRound( bottomHintEdge->dsCoord ),
-                      blues->zone[i].dsFlatEdge - cf2_intToFixed( 1 ) );
+                      SUB_INT32( blues->zone[i].dsFlatEdge,
+                                 cf2_intToFixed( 1 ) ) );
           }
 
           else
diff --git a/src/psaux/psconv.c b/src/psaux/psconv.c
index 4cf5cd5..c28d65d 100644
--- a/src/psaux/psconv.c
+++ b/src/psaux/psconv.c
@@ -4,7 +4,7 @@
  *
  *   Some convenience conversions (body).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/psconv.h b/src/psaux/psconv.h
index 833e827..cd91a7b 100644
--- a/src/psaux/psconv.h
+++ b/src/psaux/psconv.h
@@ -4,7 +4,7 @@
  *
  *   Some convenience conversions (specification).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/psft.c b/src/psaux/psft.c
index 41c1654..ac72d82 100644
--- a/src/psaux/psft.c
+++ b/src/psaux/psft.c
@@ -742,13 +742,13 @@
     /* For ordinary fonts get the character data stored in the face record. */
     {
       glyph_data.pointer = type1->charstrings[glyph_index];
-      glyph_data.length  = (FT_Int)type1->charstrings_len[glyph_index];
+      glyph_data.length  = type1->charstrings_len[glyph_index];
     }
 
     if ( !error )
     {
       FT_Byte*  charstring_base = (FT_Byte*)glyph_data.pointer;
-      FT_ULong  charstring_len  = (FT_ULong)glyph_data.length;
+      FT_ULong  charstring_len  = glyph_data.length;
 
 
       FT_ASSERT( charstring_base + charstring_len >= charstring_base );
@@ -778,7 +778,7 @@
     face = (T1_Face)decoder->builder.face;
 
     data.pointer = buf->start;
-    data.length  = (FT_Int)( buf->end - buf->start );
+    data.length  = (FT_UInt)( buf->end - buf->start );
 
     if ( face->root.internal->incremental_interface )
       face->root.internal->incremental_interface->funcs->free_glyph_data(
diff --git a/src/psaux/pshints.c b/src/psaux/pshints.c
index ce8cfca..ad472c9 100644
--- a/src/psaux/pshints.c
+++ b/src/psaux/pshints.c
@@ -412,6 +412,12 @@
     {
       FT_Bool  isPair = cf2_hint_isPair( &hintmap->edge[i] );
 
+      /* final amount to move edge or edge pair */
+      CF2_Fixed  move = 0;
+
+      CF2_Fixed  dsCoord_i;
+      CF2_Fixed  dsCoord_j;
+
 
       /* index of upper edge (same value for ghost hint) */
       j = isPair ? i + 1 : i;
@@ -422,11 +428,14 @@
       FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) ==
                    cf2_hint_isLocked( &hintmap->edge[j] ) );
 
+      dsCoord_i = hintmap->edge[i].dsCoord;
+      dsCoord_j = hintmap->edge[j].dsCoord;
+
       if ( !cf2_hint_isLocked( &hintmap->edge[i] ) )
       {
         /* hint edge is not locked, we can adjust it */
-        CF2_Fixed  fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord );
-        CF2_Fixed  fracUp   = cf2_fixedFraction( hintmap->edge[j].dsCoord );
+        CF2_Fixed  fracDown = cf2_fixedFraction( dsCoord_i );
+        CF2_Fixed  fracUp   = cf2_fixedFraction( dsCoord_j );
 
         /* calculate all four possibilities; moves down are negative */
         CF2_Fixed  downMoveDown = 0 - fracDown;
@@ -443,9 +452,6 @@
         /* smallest move down */
         CF2_Fixed  moveDown = FT_MAX( downMoveDown, upMoveDown );
 
-        /* final amount to move edge or edge pair */
-        CF2_Fixed  move;
-
         CF2_Fixed  downMinCounter = CF2_MIN_COUNTER;
         CF2_Fixed  upMinCounter   = CF2_MIN_COUNTER;
         FT_Bool    saveEdge       = FALSE;
@@ -467,16 +473,14 @@
         /* is there room to move up?                                    */
         /* there is if we are at top of array or the next edge is at or */
         /* beyond proposed move up?                                     */
-        if ( j >= hintmap->count - 1                ||
+        if ( j >= hintmap->count - 1                         ||
              hintmap->edge[j + 1].dsCoord >=
-               ADD_INT32( hintmap->edge[j].dsCoord,
-                          moveUp + upMinCounter )   )
+               ADD_INT32( dsCoord_j, moveUp + upMinCounter ) )
         {
           /* there is room to move up; is there also room to move down? */
-          if ( i == 0                                   ||
+          if ( i == 0                                              ||
                hintmap->edge[i - 1].dsCoord <=
-                 ADD_INT32( hintmap->edge[i].dsCoord,
-                            moveDown - downMinCounter ) )
+                 ADD_INT32( dsCoord_i, moveDown - downMinCounter ) )
           {
             /* move smaller absolute amount */
             move = ( -moveDown < moveUp ) ? moveDown : moveUp;  /* optimum */
@@ -487,10 +491,9 @@
         else
         {
           /* is there room to move down? */
-          if ( i == 0                                   ||
+          if ( i == 0                                              ||
                hintmap->edge[i - 1].dsCoord <=
-                 ADD_INT32( hintmap->edge[i].dsCoord,
-                            moveDown - downMinCounter ) )
+                 ADD_INT32( dsCoord_i, moveDown - downMinCounter ) )
           {
             move     = moveDown;
             /* true if non-optimum move */
@@ -524,17 +527,21 @@
         }
 
         /* move the edge(s) */
-        hintmap->edge[i].dsCoord = ADD_INT32( hintmap->edge[i].dsCoord,
-                                              move );
+        hintmap->edge[i].dsCoord = ADD_INT32( dsCoord_i, move );
         if ( isPair )
-          hintmap->edge[j].dsCoord = ADD_INT32( hintmap->edge[j].dsCoord,
-                                                move );
+          hintmap->edge[j].dsCoord = ADD_INT32( dsCoord_j, move );
       }
 
-      /* assert there are no overlaps in device space */
+      /* assert there are no overlaps in device space;     */
+      /* ignore tests if there was overflow (that is, if   */
+      /* operands have the same sign but the sum does not) */
       FT_ASSERT( i == 0                                                   ||
+                 ( ( dsCoord_i ^ move ) >= 0                    &&
+                   ( dsCoord_i ^ hintmap->edge[i].dsCoord ) < 0 )         ||
                  hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord );
       FT_ASSERT( i < j                                                ||
+                 ( ( dsCoord_j ^ move ) >= 0                    &&
+                   ( dsCoord_j ^ hintmap->edge[j].dsCoord ) < 0 )     ||
                  hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord );
 
       /* adjust the scales, avoiding divide by zero */
@@ -1022,10 +1029,17 @@
       }
     }
 
-    FT_TRACE6(( "%s\n", initialMap ? "flags: [p]air [g]host [t]op"
-                                     " [b]ottom [L]ocked [S]ynthetic\n"
-                                     "Initial hintmap"
-                                   : "Hints:" ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( initialMap )
+    {
+      FT_TRACE6(( "flags: [p]air [g]host [t]op"
+                  " [b]ottom [L]ocked [S]ynthetic\n" ));
+      FT_TRACE6(( "Initial hintmap" ));
+    }
+    else
+      FT_TRACE6(( "Hints:" ));
+#endif
+
     cf2_hintmap_dump( hintmap );
 
     /*
diff --git a/src/psaux/psintrp.c b/src/psaux/psintrp.c
index 519c694..c550533 100644
--- a/src/psaux/psintrp.c
+++ b/src/psaux/psintrp.c
@@ -469,7 +469,7 @@
    */
   FT_LOCAL_DEF( void )
   cf2_interpT2CharString( CF2_Font              font,
-                          CF2_Buffer            buf,
+                          const CF2_Buffer      buf,
                           CF2_OutlineCallbacks  callbacks,
                           const FT_Vector*      translation,
                           FT_Bool               doingSeac,
@@ -1340,9 +1340,9 @@
                       if ( decoder->glyph_names == 0 )
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
                       {
-                        FT_ERROR((
-                          "cf2_interpT2CharString: (Type 1 seac)"
-                          " glyph names table not available in this font\n" ));
+                        FT_ERROR(( "cf2_interpT2CharString:\n" ));
+                        FT_ERROR(( "  (Type 1 seac) glyph names table"
+                                   " not available in this font\n" ));
                         lastError = FT_THROW( Invalid_Glyph_Format );
                         goto exit;
                       }
@@ -1368,9 +1368,9 @@
 
                     if ( bchar_index < 0 || achar_index < 0 )
                     {
-                      FT_ERROR((
-                        "cf2_interpT2CharString: (Type 1 seac)"
-                        " invalid seac character code arguments\n" ));
+                      FT_ERROR(( "cf2_interpT2CharString:\n" ));
+                      FT_ERROR(( "  (Type 1 seac) invalid"
+                                 " seac character code arguments\n" ));
                       lastError = FT_THROW( Invalid_Glyph_Format );
                       goto exit;
                     }
@@ -1670,7 +1670,13 @@
                      */
 
                     count = cf2_stack_count( opStack );
-                    FT_ASSERT( (CF2_UInt)arg_cnt <= count );
+                    if ( (CF2_UInt)arg_cnt > count )
+                    {
+                      FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
+                                 " stack underflow\n" ));
+                      lastError = FT_THROW( Invalid_Glyph_Format );
+                      goto exit;
+                    }
 
                     opIdx += count - (CF2_UInt)arg_cnt;
 
@@ -1893,18 +1899,17 @@
                       /*     cvi( <idx> ) of BuildCharArray with  */
                       /*     WeightVector                         */
                       {
-                        FT_Int    idx;
+                        FT_UInt   idx;
                         PS_Blend  blend = decoder->blend;
 
 
                         if ( arg_cnt != 1 || !blend )
                           goto Unexpected_OtherSubr;
 
-                        idx = cf2_stack_popInt( opStack );
+                        idx = (FT_UInt)cf2_stack_popInt( opStack );
 
-                        if ( idx < 0                             ||
-                             (FT_UInt)idx + blend->num_designs >
-                               decoder->len_buildchar            )
+                        if ( idx + blend->num_designs >
+                               decoder->len_buildchar   )
                           goto Unexpected_OtherSubr;
 
                         ft_memcpy( &decoder->buildchar[idx],
@@ -2004,17 +2009,16 @@
                       /* <val> <idx> 2 24 callothersubr               */
                       /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
                       {
-                        CF2_Int   idx;
+                        CF2_UInt  idx;
                         PS_Blend  blend = decoder->blend;
 
 
                         if ( arg_cnt != 2 || !blend )
                           goto Unexpected_OtherSubr;
 
-                        idx = cf2_stack_popInt( opStack );
+                        idx = (CF2_UInt)cf2_stack_popInt( opStack );
 
-                        if ( idx < 0                                ||
-                             (FT_UInt)idx >= decoder->len_buildchar )
+                        if ( idx >= decoder->len_buildchar )
                           goto Unexpected_OtherSubr;
 
                         decoder->buildchar[idx] =
@@ -2027,17 +2031,16 @@
                       /* ==> push BuildCharArray[cvi( idx )] */
                       /*     onto T1 stack                   */
                       {
-                        CF2_Int   idx;
+                        CF2_UInt  idx;
                         PS_Blend  blend = decoder->blend;
 
 
                         if ( arg_cnt != 1 || !blend )
                           goto Unexpected_OtherSubr;
 
-                        idx = cf2_stack_popInt( opStack );
+                        idx = (CF2_UInt)cf2_stack_popInt( opStack );
 
-                        if ( idx < 0                                ||
-                             (FT_UInt)idx >= decoder->len_buildchar )
+                        if ( idx >= decoder->len_buildchar )
                           goto Unexpected_OtherSubr;
 
                         cf2_stack_pushFixed( opStack,
@@ -2179,29 +2182,29 @@
                 case cf2_escPUT:
                   {
                     CF2_F16Dot16  val;
-                    CF2_Int       idx;
+                    CF2_UInt      idx;
 
 
                     FT_TRACE4(( " put\n" ));
 
-                    idx = cf2_stack_popInt( opStack );
+                    idx = (CF2_UInt)cf2_stack_popInt( opStack );
                     val = cf2_stack_popFixed( opStack );
 
-                    if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
+                    if ( idx < CF2_STORAGE_SIZE )
                       storage[idx] = val;
                   }
                   continue; /* do not clear the stack */
 
                 case cf2_escGET:
                   {
-                    CF2_Int  idx;
+                    CF2_UInt  idx;
 
 
                     FT_TRACE4(( " get\n" ));
 
-                    idx = cf2_stack_popInt( opStack );
+                    idx = (CF2_UInt)cf2_stack_popInt( opStack );
 
-                    if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
+                    if ( idx < CF2_STORAGE_SIZE )
                       cf2_stack_pushFixed( opStack, storage[idx] );
                   }
                   continue; /* do not clear the stack */
diff --git a/src/psaux/psintrp.h b/src/psaux/psintrp.h
index 669c09c..d8b9342 100644
--- a/src/psaux/psintrp.h
+++ b/src/psaux/psintrp.h
@@ -65,7 +65,7 @@
 
   FT_LOCAL( void )
   cf2_interpT2CharString( CF2_Font              font,
-                          CF2_Buffer            charstring,
+                          const CF2_Buffer      buf,
                           CF2_OutlineCallbacks  callbacks,
                           const FT_Vector*      translation,
                           FT_Bool               doingSeac,
diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c
index defc4d4..30f5019 100644
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
  *
  *   Auxiliary functions for PostScript fonts (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -251,7 +251,7 @@
     if ( !old_base )
       return;
 
-    if ( FT_ALLOC( table->block, table->cursor ) )
+    if ( FT_QALLOC( table->block, table->cursor ) )
       return;
     FT_MEM_COPY( table->block, old_base, table->cursor );
     shift_elements( table, old_base );
@@ -595,10 +595,10 @@
     if ( cur < limit && cur == parser->cursor )
     {
       FT_ERROR(( "ps_parser_skip_PS_token:"
-                 " current token is `%c' which is self-delimiting\n"
-                 "                        "
-                 " but invalid at this point\n",
+                 " current token is `%c' which is self-delimiting\n",
                  *cur ));
+      FT_ERROR(( "                        "
+                 " but invalid at this point\n" ));
 
       error = FT_THROW( Invalid_File_Format );
     }
@@ -979,7 +979,7 @@
     }
 
     len = (FT_UInt)( cur - *cursor );
-    if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
+    if ( cur >= limit || FT_QALLOC( result, len + 1 ) )
       return 0;
 
     /* now copy the string */
@@ -1175,8 +1175,8 @@
           else
           {
             FT_ERROR(( "ps_parser_load_field:"
-                       " expected a name or string\n"
-                       "                     "
+                       " expected a name or string\n" ));
+            FT_ERROR(( "                     "
                        " but found token of type %d instead\n",
                        token.type ));
             error = FT_THROW( Invalid_File_Format );
@@ -1193,7 +1193,7 @@
             *(FT_String**)q = NULL;
           }
 
-          if ( FT_ALLOC( string, len + 1 ) )
+          if ( FT_QALLOC( string, len + 1 ) )
             goto Exit;
 
           FT_MEM_COPY( string, cur, len );
@@ -1248,7 +1248,7 @@
           FT_UInt    i;
 
 
-          if ( FT_NEW_ARRAY( temp, max_objects * 4 ) )
+          if ( FT_QNEW_ARRAY( temp, max_objects * 4 ) )
             goto Exit;
 
           for ( i = 0; i < 4; i++ )
@@ -1258,14 +1258,14 @@
             if ( result < 0 || (FT_UInt)result < max_objects )
             {
               FT_ERROR(( "ps_parser_load_field:"
-                         " expected %d integer%s in the %s subarray\n"
-                         "                     "
-                         " of /FontBBox in the /Blend dictionary\n",
+                         " expected %d integer%s in the %s subarray\n",
                          max_objects, max_objects > 1 ? "s" : "",
                          i == 0 ? "first"
                                 : ( i == 1 ? "second"
                                            : ( i == 2 ? "third"
                                                       : "fourth" ) ) ));
+              FT_ERROR(( "                     "
+                         " of /FontBBox in the /Blend dictionary\n" ));
               error = FT_THROW( Invalid_File_Format );
 
               FT_FREE( temp );
diff --git a/src/psaux/psobjs.h b/src/psaux/psobjs.h
index fdad672..99d1695 100644
--- a/src/psaux/psobjs.h
+++ b/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
  *
  *   Auxiliary functions for PostScript fonts (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/psstack.c b/src/psaux/psstack.c
index 7ae5256..7974865 100644
--- a/src/psaux/psstack.c
+++ b/src/psaux/psstack.c
@@ -54,20 +54,18 @@
                   FT_Error*  e,
                   FT_UInt    stackSize )
   {
-    FT_Error  error = FT_Err_Ok;     /* for FT_NEW */
-
+    FT_Error   error;        /* for FT_QNEW */
     CF2_Stack  stack = NULL;
 
 
-    if ( FT_NEW( stack ) )
+    if ( FT_QNEW( stack ) )
       return NULL;
 
-    /* initialize the structure; FT_NEW zeroes it */
     stack->memory = memory;
     stack->error  = e;
 
     /* allocate the stack buffer */
-    if ( FT_NEW_ARRAY( stack->buffer, stackSize ) )
+    if ( FT_QNEW_ARRAY( stack->buffer, stackSize ) )
     {
       FT_FREE( stack );
       return NULL;
diff --git a/src/psaux/rules.mk b/src/psaux/rules.mk
index f49aecb..0543912 100644
--- a/src/psaux/rules.mk
+++ b/src/psaux/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/psaux/t1cmap.c b/src/psaux/t1cmap.c
index e21e93c..3e7c577 100644
--- a/src/psaux/t1cmap.c
+++ b/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 character map support (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/t1cmap.h b/src/psaux/t1cmap.h
index 0317965..8f69600 100644
--- a/src/psaux/t1cmap.h
+++ b/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 character map support (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index 2ed27ca..7e65bde 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
  *
  *   PostScript Type 1 decoding routines (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -27,8 +27,11 @@
 
 #include "psauxerr.h"
 
+
 /* ensure proper sign extension */
-#define Fix2Int( f )  ( (FT_Int)(FT_Short)( (f) >> 16 ) )
+#define Fix2Int( f )   ( (FT_Int) (FT_Short)( (f) >> 16 ) )
+#define Fix2UInt( f )  ( (FT_UInt)(FT_Short)( (f) >> 16 ) )
+
 
   /**************************************************************************
    *
@@ -517,7 +520,7 @@
 #ifdef FT_DEBUG_LEVEL_TRACE
       if ( bol )
       {
-        FT_TRACE5(( " (%d)", decoder->top - decoder->stack ));
+        FT_TRACE5(( " (%ld)", decoder->top - decoder->stack ));
         bol = FALSE;
       }
 #endif
@@ -1025,16 +1028,16 @@
           /* <val> <idx> 2 24 callothersubr               */
           /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
           {
-            FT_Int    idx;
+            FT_UInt   idx;
             PS_Blend  blend = decoder->blend;
 
 
             if ( arg_cnt != 2 || !blend )
               goto Unexpected_OtherSubr;
 
-            idx = Fix2Int( top[1] );
+            idx = Fix2UInt( top[1] );
 
-            if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
+            if ( idx >= decoder->len_buildchar )
               goto Unexpected_OtherSubr;
 
             decoder->buildchar[idx] = top[0];
@@ -1046,16 +1049,16 @@
           /* ==> push BuildCharArray[cvi( idx )] */
           /*     onto T1 stack                   */
           {
-            FT_Int    idx;
+            FT_UInt   idx;
             PS_Blend  blend = decoder->blend;
 
 
             if ( arg_cnt != 1 || !blend )
               goto Unexpected_OtherSubr;
 
-            idx = Fix2Int( top[0] );
+            idx = Fix2UInt( top[0] );
 
-            if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar )
+            if ( idx >= decoder->len_buildchar )
               goto Unexpected_OtherSubr;
 
             top[0] = decoder->buildchar[idx];
@@ -1162,9 +1165,9 @@
           if ( top - decoder->stack != num_args )
             FT_TRACE0(( "t1_decoder_parse_charstrings:"
                         " too much operands on the stack"
-                        " (seen %d, expected %d)\n",
+                        " (seen %ld, expected %d)\n",
                         top - decoder->stack, num_args ));
-            break;
+          break;
         }
 
 #endif /* FT_DEBUG_LEVEL_TRACE */
@@ -1209,7 +1212,7 @@
             FT_TRACE4(( "BuildCharArray = [ " ));
 
             for ( i = 0; i < decoder->len_buildchar; i++ )
-              FT_TRACE4(( "%d ", decoder->buildchar[i] ));
+              FT_TRACE4(( "%ld ", decoder->buildchar[i] ));
 
             FT_TRACE4(( "]\n" ));
           }
@@ -1650,7 +1653,8 @@
 
     } /* while ip < limit */
 
-    FT_TRACE4(( "..end..\n\n" ));
+    FT_TRACE4(( "..end..\n" ));
+    FT_TRACE4(( "\n" ));
 
   Fail:
     return error;
@@ -2070,7 +2074,8 @@
 
     } /* while ip < limit */
 
-    FT_TRACE4(( "..end..\n\n" ));
+    FT_TRACE4(( "..end..\n" ));
+    FT_TRACE4(( "\n" ));
 
   No_Width:
     FT_ERROR(( "t1_decoder_parse_metrics:"
diff --git a/src/psaux/t1decode.h b/src/psaux/t1decode.h
index b793504..eea9d34 100644
--- a/src/psaux/t1decode.h
+++ b/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
  *
  *   PostScript Type 1 decoding routines (specification).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pshinter/module.mk b/src/pshinter/module.mk
index b440d2e..ca181ee 100644
--- a/src/pshinter/module.mk
+++ b/src/pshinter/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c
index 920b9a7..227caea 100644
--- a/src/pshinter/pshalgo.c
+++ b/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
  *
  *   PostScript hinting algorithm (body).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -305,17 +305,18 @@
     /* now, sort the hints; they are guaranteed to not overlap */
     /* so we can compare their "org_pos" field directly        */
     {
-      FT_Int     i1, i2;
+      FT_UInt    i1, i2;
       PSH_Hint   hint1, hint2;
       PSH_Hint*  sort = table->sort;
 
 
       /* a simple bubble sort will do, since in 99% of cases, the hints */
       /* will be already sorted -- and the sort will be linear          */
-      for ( i1 = 1; i1 < (FT_Int)count; i1++ )
+      for ( i1 = 1; i1 < count; i1++ )
       {
         hint1 = sort[i1];
-        for ( i2 = i1 - 1; i2 >= 0; i2-- )
+        /* this loop stops when i2 wraps around after reaching 0 */
+        for ( i2 = i1 - 1; i2 < i1; i2-- )
         {
           hint2 = sort[i2];
 
@@ -869,7 +870,7 @@
       return;
     }
 
-#endif /* DEBUG_HINTER*/
+#endif /* DEBUG_HINTER */
 
     hint  = table->hints;
     count = table->max_hints;
@@ -1049,12 +1050,12 @@
   }
 
 
-  static int
+  static PSH_Dir
   psh_compute_dir( FT_Pos  dx,
                    FT_Pos  dy )
   {
-    FT_Pos  ax, ay;
-    int     result = PSH_DIR_NONE;
+    FT_Pos   ax, ay;
+    PSH_Dir  result = PSH_DIR_NONE;
 
 
     ax = FT_ABS( dx );
@@ -1233,12 +1234,12 @@
         dxi = vec[n].x - vec[n_prev].x;
         dyi = vec[n].y - vec[n_prev].y;
 
-        point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi );
+        point->dir_in = psh_compute_dir( dxi, dyi );
 
         dxo = vec[n_next].x - vec[n].x;
         dyo = vec[n_next].y - vec[n].y;
 
-        point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo );
+        point->dir_out = psh_compute_dir( dxo, dyo );
 
         /* detect smooth points */
         if ( point->flags & PSH_POINT_OFF )
@@ -1403,16 +1404,13 @@
   }
 
 
-  /* major_dir is the direction for points on the bottom/left of the stem; */
-  /* Points on the top/right of the stem will have a direction of          */
-  /* -major_dir.                                                           */
-
+  /* the min and max are based on contour orientation and fill rule */
   static void
   psh_hint_table_find_strong_points( PSH_Hint_Table  table,
                                      PSH_Point       point,
                                      FT_UInt         count,
                                      FT_Int          threshold,
-                                     FT_Int          major_dir )
+                                     PSH_Dir         major_dir )
   {
     PSH_Hint*  sort      = table->sort;
     FT_UInt    num_hints = table->num_hints;
@@ -1420,59 +1418,53 @@
 
     for ( ; count > 0; count--, point++ )
     {
-      FT_Int  point_dir = 0;
-      FT_Pos  org_u     = point->org_u;
+      PSH_Dir  point_dir;
+      FT_Pos   org_u = point->org_u;
 
 
       if ( psh_point_is_strong( point ) )
         continue;
 
-      if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )
-        point_dir = point->dir_in;
+      point_dir =
+        (PSH_Dir)( ( point->dir_in | point->dir_out ) & major_dir );
 
-      else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )
-        point_dir = point->dir_out;
-
-      if ( point_dir )
+      if ( point_dir & ( PSH_DIR_DOWN | PSH_DIR_RIGHT ) )
       {
-        if ( point_dir == major_dir )
+        FT_UInt  nn;
+
+
+        for ( nn = 0; nn < num_hints; nn++ )
         {
-          FT_UInt  nn;
+          PSH_Hint  hint = sort[nn];
+          FT_Pos    d    = org_u - hint->org_pos;
 
 
-          for ( nn = 0; nn < num_hints; nn++ )
+          if ( d < threshold && -d < threshold )
           {
-            PSH_Hint  hint = sort[nn];
-            FT_Pos    d    = org_u - hint->org_pos;
-
-
-            if ( d < threshold && -d < threshold )
-            {
-              psh_point_set_strong( point );
-              point->flags2 |= PSH_POINT_EDGE_MIN;
-              point->hint    = hint;
-              break;
-            }
+            psh_point_set_strong( point );
+            point->flags2 |= PSH_POINT_EDGE_MIN;
+            point->hint    = hint;
+            break;
           }
         }
-        else if ( point_dir == -major_dir )
+      }
+      else if ( point_dir & ( PSH_DIR_UP | PSH_DIR_LEFT ) )
+      {
+        FT_UInt  nn;
+
+
+        for ( nn = 0; nn < num_hints; nn++ )
         {
-          FT_UInt  nn;
+          PSH_Hint  hint = sort[nn];
+          FT_Pos    d    = org_u - hint->org_pos - hint->org_len;
 
 
-          for ( nn = 0; nn < num_hints; nn++ )
+          if ( d < threshold && -d < threshold )
           {
-            PSH_Hint  hint = sort[nn];
-            FT_Pos    d    = org_u - hint->org_pos - hint->org_len;
-
-
-            if ( d < threshold && -d < threshold )
-            {
-              psh_point_set_strong( point );
-              point->flags2 |= PSH_POINT_EDGE_MAX;
-              point->hint    = hint;
-              break;
-            }
+            psh_point_set_strong( point );
+            point->flags2 |= PSH_POINT_EDGE_MAX;
+            point->hint    = hint;
+            break;
           }
         }
       }
@@ -1571,7 +1563,7 @@
     PS_Mask         mask      = table->hint_masks->masks;
     FT_UInt         num_masks = table->hint_masks->num_masks;
     FT_UInt         first     = 0;
-    FT_Int          major_dir = ( dimension == 0 ) ? PSH_DIR_VERTICAL
+    PSH_Dir         major_dir = ( dimension == 0 ) ? PSH_DIR_VERTICAL
                                                    : PSH_DIR_HORIZONTAL;
     PSH_Dimension   dim       = &glyph->globals->dimension[dimension];
     FT_Fixed        scale     = dim->scale_mult;
@@ -1656,8 +1648,8 @@
 
 
       /* check tangents */
-      if ( !PSH_DIR_COMPARE( point->dir_in,  PSH_DIR_HORIZONTAL ) &&
-           !PSH_DIR_COMPARE( point->dir_out, PSH_DIR_HORIZONTAL ) )
+      if ( !( point->dir_in  & PSH_DIR_HORIZONTAL ) &&
+           !( point->dir_out & PSH_DIR_HORIZONTAL ) )
         continue;
 
       /* skip strong points */
diff --git a/src/pshinter/pshalgo.h b/src/pshinter/pshalgo.h
index 5367a5d..999c601 100644
--- a/src/pshinter/pshalgo.h
+++ b/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinting algorithm (specification).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -93,21 +93,17 @@
   typedef struct PSH_PointRec_*    PSH_Point;
   typedef struct PSH_ContourRec_*  PSH_Contour;
 
-  enum
+  typedef enum PSH_Dir_
   {
-    PSH_DIR_NONE  =  4,
-    PSH_DIR_UP    = -1,
-    PSH_DIR_DOWN  =  1,
-    PSH_DIR_LEFT  = -2,
-    PSH_DIR_RIGHT =  2
-  };
+    PSH_DIR_NONE       = 0,
+    PSH_DIR_UP         = 1,
+    PSH_DIR_DOWN       = 2,
+    PSH_DIR_VERTICAL   = 1 | 2,
+    PSH_DIR_LEFT       = 4,
+    PSH_DIR_RIGHT      = 8,
+    PSH_DIR_HORIZONTAL = 4 | 8
 
-#define PSH_DIR_HORIZONTAL  2
-#define PSH_DIR_VERTICAL    1
-
-#define PSH_DIR_COMPARE( d1, d2 )   ( (d1) == (d2) || (d1) == -(d2) )
-#define PSH_DIR_IS_HORIZONTAL( d )  PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL )
-#define PSH_DIR_IS_VERTICAL( d )    PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL )
+  } PSH_Dir;
 
 
   /* the following bit-flags are computed once by the glyph */
@@ -160,8 +156,8 @@
     PSH_Contour  contour;
     FT_UInt      flags;
     FT_UInt      flags2;
-    FT_Char      dir_in;
-    FT_Char      dir_out;
+    PSH_Dir      dir_in;
+    PSH_Dir      dir_out;
     PSH_Hint     hint;
     FT_Pos       org_u;
     FT_Pos       org_v;
@@ -199,10 +195,6 @@
     PSH_Globals        globals;
     PSH_Hint_TableRec  hint_tables[2];
 
-    FT_Bool            vertical;
-    FT_Int             major_dir;
-    FT_Int             minor_dir;
-
     FT_Bool            do_horz_hints;
     FT_Bool            do_vert_hints;
     FT_Bool            do_horz_snapping;
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index cdc1c3a..2ca0f66 100644
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
  *   PostScript hinter global hinting management (body).
  *   Inspired by the new auto-hinter module.
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff --git a/src/pshinter/pshglob.h b/src/pshinter/pshglob.h
index 8181324..a8f9953 100644
--- a/src/pshinter/pshglob.h
+++ b/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinter global hinting management.
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pshinter/pshinter.c b/src/pshinter/pshinter.c
index 3cca0ad..705143d 100644
--- a/src/pshinter/pshinter.c
+++ b/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript Hinting module
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pshinter/pshmod.c b/src/pshinter/pshmod.c
index e0abd38..6674041 100644
--- a/src/pshinter/pshmod.c
+++ b/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript hinter module implementation (body).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pshinter/pshmod.h b/src/pshinter/pshmod.h
index 2a6eb1c..8b229bb 100644
--- a/src/pshinter/pshmod.h
+++ b/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinter module interface (specification).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pshinter/pshnterr.h b/src/pshinter/pshnterr.h
index d67955c..567d765 100644
--- a/src/pshinter/pshnterr.h
+++ b/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
  *
  *   PS Hinter error codes (specification only).
  *
- * Copyright (C) 2003-2020 by
+ * Copyright (C) 2003-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c
index bddccf2..1faabda 100644
--- a/src/pshinter/pshrec.c
+++ b/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript hints recorder (body).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -499,23 +499,18 @@
   ps_mask_table_merge_all( PS_Mask_Table  table,
                            FT_Memory      memory )
   {
-    FT_Int    index1, index2;
+    FT_UInt   index1, index2;
     FT_Error  error = FT_Err_Ok;
 
 
-    /* both loops go down to 0, thus FT_Int for index1 and index2 */
-    for ( index1 = (FT_Int)table->num_masks - 1; index1 > 0; index1-- )
+    /* the loops stop when unsigned indices wrap around after 0 */
+    for ( index1 = table->num_masks - 1; index1 < table->num_masks; index1-- )
     {
-      for ( index2 = index1 - 1; index2 >= 0; index2-- )
+      for ( index2 = index1 - 1; index2 < index1; index2-- )
       {
-        if ( ps_mask_table_test_intersect( table,
-                                           (FT_UInt)index1,
-                                           (FT_UInt)index2 ) )
+        if ( ps_mask_table_test_intersect( table, index1, index2 ) )
         {
-          error = ps_mask_table_merge( table,
-                                       (FT_UInt)index2,
-                                       (FT_UInt)index1,
-                                       memory );
+          error = ps_mask_table_merge( table, index2, index1, memory );
           if ( error )
             goto Exit;
 
diff --git a/src/pshinter/pshrec.h b/src/pshinter/pshrec.h
index b13c7be..e483981 100644
--- a/src/pshinter/pshrec.h
+++ b/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
  *
  *   Postscript (Type1/Type2) hints recorder (specification).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/pshinter/rules.mk b/src/pshinter/rules.mk
index c845c25..3c5a59a 100644
--- a/src/pshinter/rules.mk
+++ b/src/pshinter/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2001-2020 by
+# Copyright (C) 2001-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/psnames/module.mk b/src/psnames/module.mk
index 675bb37..abfb54f 100644
--- a/src/psnames/module.mk
+++ b/src/psnames/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c
index b38f9d3..74adefa 100644
--- a/src/psnames/psmodule.c
+++ b/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
  *
  *   psnames module implementation (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -155,31 +155,30 @@
     /* Look for a non-initial dot in the glyph name in order to */
     /* find variants like `A.swash', `e.final', etc.            */
     {
-      const char*  p   = glyph_name;
-      const char*  dot = NULL;
+      FT_UInt32    value = 0;
+      const char*  p     = glyph_name;
 
 
-      for ( ; *p; p++ )
+      for ( ; *p && *p != '.'; p++ )
+        ;
+
+      /* now look up the glyph in the Adobe Glyph List;      */
+      /* `.notdef', `.null' and the empty name are short cut */
+      if ( p > glyph_name )
       {
-        if ( *p == '.' && p > glyph_name )
-        {
-          dot = p;
-          break;
-        }
+        value = (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
+
+        if ( *p == '.' )
+          value |= (FT_UInt32)VARIANT_BIT;
       }
 
-      /* now look up the glyph in the Adobe Glyph List */
-      if ( !dot )
-        return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
-      else
-        return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
-                            VARIANT_BIT );
+      return value;
     }
   }
 
 
   /* ft_qsort callback to sort the unicode map */
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   compare_uni_maps( const void*  a,
                     const void*  b )
   {
@@ -326,9 +325,8 @@
 
     /* we first allocate the table */
     table->num_maps = 0;
-    table->maps     = NULL;
 
-    if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
+    if ( !FT_QNEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
     {
       FT_UInt     n;
       FT_UInt     count;
@@ -343,7 +341,7 @@
         const char*  gname = get_glyph_name( glyph_data, n );
 
 
-        if ( gname )
+        if ( gname && *gname )
         {
           ps_check_extra_glyph_name( gname, n,
                                      extra_glyphs, extra_glyph_list_states );
@@ -391,9 +389,9 @@
         /* Reallocate if the number of used entries is much smaller. */
         if ( count < num_glyphs / 2 )
         {
-          (void)FT_RENEW_ARRAY( table->maps,
-                                num_glyphs + EXTRA_GLYPH_LIST_SIZE,
-                                count );
+          FT_MEM_QRENEW_ARRAY( table->maps,
+                               num_glyphs + EXTRA_GLYPH_LIST_SIZE,
+                               count );
           error = FT_Err_Ok;
         }
 
diff --git a/src/psnames/psmodule.h b/src/psnames/psmodule.h
index c85a9ec..e92a975 100644
--- a/src/psnames/psmodule.h
+++ b/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
  *
  *   High-level psnames module interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psnames/psnamerr.h b/src/psnames/psnamerr.h
index 154c701..888b76c 100644
--- a/src/psnames/psnamerr.h
+++ b/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
  *
  *   PS names module error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psnames/psnames.c b/src/psnames/psnames.c
index cff3685..e7be670 100644
--- a/src/psnames/psnames.c
+++ b/src/psnames/psnames.c
@@ -4,7 +4,7 @@
  *
  *   FreeType psnames module component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psnames/pstables.h b/src/psnames/pstables.h
index c215f16..0bcadca 100644
--- a/src/psnames/pstables.h
+++ b/src/psnames/pstables.h
@@ -4,7 +4,7 @@
  *
  *   PostScript glyph names.
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/psnames/rules.mk b/src/psnames/rules.mk
index 14cdda3..6694f4e 100644
--- a/src/psnames/rules.mk
+++ b/src/psnames/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/raster/ftmisc.h b/src/raster/ftmisc.h
index 6efe4a9..b12a051 100644
--- a/src/raster/ftmisc.h
+++ b/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
  *   Miscellaneous macros for stand-alone rasterizer (specification
  *   only).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -47,11 +47,8 @@
   typedef signed long    FT_F26Dot6;
   typedef int            FT_Error;
 
-#define FT_MAKE_TAG( _x1, _x2, _x3, _x4 ) \
-          ( ( (FT_ULong)_x1 << 24 ) |     \
-            ( (FT_ULong)_x2 << 16 ) |     \
-            ( (FT_ULong)_x3 <<  8 ) |     \
-              (FT_ULong)_x4         )
+
+#define FT_STATIC_BYTE_CAST( type, var )  (type)(FT_Byte)(var)
 
 
   /* from include/freetype/ftsystem.h */
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index 9f0a797..bfc059c 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -149,9 +149,6 @@
   /*************************************************************************/
   /*************************************************************************/
 
-  /* define DEBUG_RASTER if you want to compile a debugging version */
-/* #define DEBUG_RASTER */
-
 
   /*************************************************************************/
   /*************************************************************************/
@@ -200,12 +197,13 @@
 #define FT_THROW( e )  FT_ERR_CAT( Raster_Err_, e )
 #endif
 
-#define Raster_Err_None          0
-#define Raster_Err_Not_Ini      -1
-#define Raster_Err_Overflow     -2
-#define Raster_Err_Neg_Height   -3
-#define Raster_Err_Invalid      -4
-#define Raster_Err_Unsupported  -5
+#define Raster_Err_Ok                       0
+#define Raster_Err_Invalid_Outline         -1
+#define Raster_Err_Cannot_Render_Glyph     -2
+#define Raster_Err_Invalid_Argument        -3
+#define Raster_Err_Raster_Overflow         -4
+#define Raster_Err_Raster_Uninitialized    -5
+#define Raster_Err_Raster_Negative_Height  -6
 
 #define ft_memset  memset
 
@@ -230,13 +228,6 @@
 
 #include "rasterrs.h"
 
-#define Raster_Err_None         FT_Err_Ok
-#define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
-#define Raster_Err_Overflow     Raster_Err_Raster_Overflow
-#define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
-#define Raster_Err_Invalid      Raster_Err_Invalid_Outline
-#define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
-
 
 #endif /* !STANDALONE_ */
 
@@ -375,16 +366,6 @@
   typedef PProfile*  PProfileList;
 
 
-  /* Simple record used to implement a stack of bands, required */
-  /* by the sub-banding mechanism                               */
-  typedef struct  black_TBand_
-  {
-    Short  y_min;   /* band's minimum */
-    Short  y_max;   /* band's maximum */
-
-  } black_TBand;
-
-
 #define AlignProfileSize \
   ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
 
@@ -426,8 +407,8 @@
 
   /* prototypes used for sweep function dispatch */
   typedef void
-  Function_Sweep_Init( RAS_ARGS Short*  min,
-                                Short*  max );
+  Function_Sweep_Init( RAS_ARGS Short  min,
+                                Short  max );
 
   typedef void
   Function_Sweep_Span( RAS_ARGS Short       y,
@@ -492,10 +473,11 @@
 
     Int         numTurns;           /* number of Y-turns in outline        */
 
-    TPoint*     arc;                /* current Bezier arc pointer          */
+    Byte        dropOutControl;     /* current drop_out control method     */
 
     UShort      bWidth;             /* target bitmap width                 */
     PByte       bOrigin;            /* target bitmap bottom-left origin    */
+    PByte       bLine;              /* target bitmap current line          */
 
     Long        lastX, lastY;
     Long        minY, maxY;
@@ -517,9 +499,6 @@
     FT_Bitmap   target;             /* description of target bit/pixmap    */
     FT_Outline  outline;
 
-    Long        traceOfs;           /* current offset in target bitmap     */
-    Short       traceIncr;          /* sweep's increment in target bitmap  */
-
     /* dispatch variables */
 
     Function_Sweep_Init*  Proc_Sweep_Init;
@@ -527,18 +506,6 @@
     Function_Sweep_Span*  Proc_Sweep_Drop;
     Function_Sweep_Step*  Proc_Sweep_Step;
 
-    Byte        dropOutControl;     /* current drop_out control method     */
-
-    Bool        second_pass;        /* indicates whether a horizontal pass */
-                                    /* should be performed to control      */
-                                    /* drop-out accurately when calling    */
-                                    /* Render_Glyph.                       */
-
-    TPoint      arcs[3 * MaxBezier + 1]; /* The Bezier stack               */
-
-    black_TBand  band_stack[16];    /* band stack used for sub-banding     */
-    Int          band_top;          /* band stack top                      */
-
   };
 
 
@@ -660,7 +627,7 @@
 
     if ( ras.top >= ras.maxBuff )
     {
-      ras.error = FT_THROW( Overflow );
+      ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
@@ -689,7 +656,7 @@
 
     default:
       FT_ERROR(( "New_Profile: invalid profile direction\n" ));
-      ras.error = FT_THROW( Invalid );
+      ras.error = FT_THROW( Invalid_Outline );
       return FAILURE;
     }
 
@@ -731,7 +698,7 @@
     if ( h < 0 )
     {
       FT_ERROR(( "End_Profile: negative height encountered\n" ));
-      ras.error = FT_THROW( Neg_Height );
+      ras.error = FT_THROW( Raster_Negative_Height );
       return FAILURE;
     }
 
@@ -767,7 +734,7 @@
     if ( ras.top >= ras.maxBuff )
     {
       FT_TRACE1(( "overflow in End_Profile\n" ));
-      ras.error = FT_THROW( Overflow );
+      ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
@@ -822,7 +789,7 @@
       ras.maxBuff--;
       if ( ras.maxBuff <= ras.top )
       {
-        ras.error = FT_THROW( Overflow );
+        ras.error = FT_THROW( Raster_Overflow );
         return FAILURE;
       }
       ras.numTurns++;
@@ -1086,7 +1053,7 @@
     size = e2 - e1 + 1;
     if ( ras.top + size >= ras.maxBuff )
     {
-      ras.error = FT_THROW( Overflow );
+      ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
@@ -1209,6 +1176,7 @@
    */
   static Bool
   Bezier_Up( RAS_ARGS Int        degree,
+                      TPoint*    arc,
                       TSplitter  splitter,
                       Long       miny,
                       Long       maxy )
@@ -1216,13 +1184,11 @@
     Long   y1, y2, e, e2, e0;
     Short  f1;
 
-    TPoint*  arc;
     TPoint*  start_arc;
 
     PLong top;
 
 
-    arc = ras.arc;
     y1  = arc[degree].y;
     y2  = arc[0].y;
     top = ras.top;
@@ -1271,7 +1237,7 @@
     if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
     {
       ras.top   = top;
-      ras.error = FT_THROW( Overflow );
+      ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
@@ -1314,7 +1280,6 @@
 
   Fin:
     ras.top  = top;
-    ras.arc -= degree;
     return SUCCESS;
   }
 
@@ -1346,11 +1311,11 @@
    */
   static Bool
   Bezier_Down( RAS_ARGS Int        degree,
+                        TPoint*    arc,
                         TSplitter  splitter,
                         Long       miny,
                         Long       maxy )
   {
-    TPoint*  arc = ras.arc;
     Bool     result, fresh;
 
 
@@ -1362,7 +1327,7 @@
 
     fresh = ras.fresh;
 
-    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
+    result = Bezier_Up( RAS_VARS degree, arc, splitter, -maxy, -miny );
 
     if ( fresh && !ras.fresh )
       ras.cProfile->start = -ras.cProfile->start;
@@ -1503,22 +1468,24 @@
   {
     Long     y1, y2, y3, x3, ymin, ymax;
     TStates  state_bez;
+    TPoint   arcs[2 * MaxBezier + 1]; /* The Bezier stack           */
+    TPoint*  arc;                     /* current Bezier arc pointer */
 
 
-    ras.arc      = ras.arcs;
-    ras.arc[2].x = ras.lastX;
-    ras.arc[2].y = ras.lastY;
-    ras.arc[1].x = cx;
-    ras.arc[1].y = cy;
-    ras.arc[0].x = x;
-    ras.arc[0].y = y;
+    arc      = arcs;
+    arc[2].x = ras.lastX;
+    arc[2].y = ras.lastY;
+    arc[1].x = cx;
+    arc[1].y = cy;
+    arc[0].x = x;
+    arc[0].y = y;
 
     do
     {
-      y1 = ras.arc[2].y;
-      y2 = ras.arc[1].y;
-      y3 = ras.arc[0].y;
-      x3 = ras.arc[0].x;
+      y1 = arc[2].y;
+      y2 = arc[1].y;
+      y3 = arc[0].y;
+      x3 = arc[0].x;
 
       /* first, categorize the Bezier arc */
 
@@ -1536,13 +1503,13 @@
       if ( y2 < ymin || y2 > ymax )
       {
         /* this arc has no given direction, split it! */
-        Split_Conic( ras.arc );
-        ras.arc += 2;
+        Split_Conic( arc );
+        arc += 2;
       }
       else if ( y1 == y3 )
       {
         /* this arc is flat, ignore it and pop it from the Bezier stack */
-        ras.arc -= 2;
+        arc -= 2;
       }
       else
       {
@@ -1569,15 +1536,18 @@
         /* now call the appropriate routine */
         if ( state_bez == Ascending_State )
         {
-          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+          if ( Bezier_Up( RAS_VARS 2, arc, Split_Conic,
+                                   ras.minY, ras.maxY ) )
             goto Fail;
         }
         else
-          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+          if ( Bezier_Down( RAS_VARS 2, arc, Split_Conic,
+                                     ras.minY, ras.maxY ) )
             goto Fail;
+        arc -= 2;
       }
 
-    } while ( ras.arc >= ras.arcs );
+    } while ( arc >= arcs );
 
     ras.lastX = x3;
     ras.lastY = y3;
@@ -1632,25 +1602,27 @@
   {
     Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
     TStates  state_bez;
+    TPoint   arcs[3 * MaxBezier + 1]; /* The Bezier stack           */
+    TPoint*  arc;                     /* current Bezier arc pointer */
 
 
-    ras.arc      = ras.arcs;
-    ras.arc[3].x = ras.lastX;
-    ras.arc[3].y = ras.lastY;
-    ras.arc[2].x = cx1;
-    ras.arc[2].y = cy1;
-    ras.arc[1].x = cx2;
-    ras.arc[1].y = cy2;
-    ras.arc[0].x = x;
-    ras.arc[0].y = y;
+    arc      = arcs;
+    arc[3].x = ras.lastX;
+    arc[3].y = ras.lastY;
+    arc[2].x = cx1;
+    arc[2].y = cy1;
+    arc[1].x = cx2;
+    arc[1].y = cy2;
+    arc[0].x = x;
+    arc[0].y = y;
 
     do
     {
-      y1 = ras.arc[3].y;
-      y2 = ras.arc[2].y;
-      y3 = ras.arc[1].y;
-      y4 = ras.arc[0].y;
-      x4 = ras.arc[0].x;
+      y1 = arc[3].y;
+      y2 = arc[2].y;
+      y3 = arc[1].y;
+      y4 = arc[0].y;
+      x4 = arc[0].x;
 
       /* first, categorize the Bezier arc */
 
@@ -1679,13 +1651,13 @@
       if ( ymin2 < ymin1 || ymax2 > ymax1 )
       {
         /* this arc has no given direction, split it! */
-        Split_Cubic( ras.arc );
-        ras.arc += 3;
+        Split_Cubic( arc );
+        arc += 3;
       }
       else if ( y1 == y4 )
       {
         /* this arc is flat, ignore it and pop it from the Bezier stack */
-        ras.arc -= 3;
+        arc -= 3;
       }
       else
       {
@@ -1711,15 +1683,18 @@
         /* compute intersections */
         if ( state_bez == Ascending_State )
         {
-          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+          if ( Bezier_Up( RAS_VARS 3, arc, Split_Cubic,
+                                   ras.minY, ras.maxY ) )
             goto Fail;
         }
         else
-          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+          if ( Bezier_Down( RAS_VARS 3, arc, Split_Cubic,
+                                     ras.minY, ras.maxY ) )
             goto Fail;
+        arc -= 3;
       }
 
-    } while ( ras.arc >= ras.arcs );
+    } while ( arc >= arcs );
 
     ras.lastX = x4;
     ras.lastY = y4;
@@ -1967,7 +1942,7 @@
     return SUCCESS;
 
   Invalid_Outline:
-    ras.error = FT_THROW( Invalid );
+    ras.error = FT_THROW( Invalid_Outline );
 
   Fail:
     return FAILURE;
@@ -2120,8 +2095,8 @@
    *   Removes an old profile from a linked list.
    */
   static void
-  DelOld( PProfileList  list,
-          PProfile      profile )
+  DelOld( PProfileList    list,
+          const PProfile  profile )
   {
     PProfile  *old, current;
 
@@ -2214,16 +2189,13 @@
    */
 
   static void
-  Vertical_Sweep_Init( RAS_ARGS Short*  min,
-                                Short*  max )
+  Vertical_Sweep_Init( RAS_ARGS Short  min,
+                                Short  max )
   {
-    Long  pitch = ras.target.pitch;
-
     FT_UNUSED( max );
 
 
-    ras.traceIncr = (Short)-pitch;
-    ras.traceOfs  = -*min * pitch;
+    ras.bLine = ras.bOrigin - min * ras.target.pitch;
   }
 
 
@@ -2234,8 +2206,7 @@
                                 PProfile    left,
                                 PProfile    right )
   {
-    Long   e1, e2;
-    Byte*  target;
+    Long  e1, e2;
 
     Int  dropOutControl = left->flags & 7;
 
@@ -2268,6 +2239,8 @@
 
     if ( e2 >= 0 && e1 < ras.bWidth )
     {
+      Byte*  target;
+
       Int   c1, c2;
       Byte  f1, f2;
 
@@ -2285,7 +2258,7 @@
       f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
       f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
 
-      target = ras.bOrigin + ras.traceOfs + c1;
+      target = ras.bLine + c1;
       c2 -= c1;
 
       if ( c2 > 0 )
@@ -2437,8 +2410,8 @@
         c1 = (Short)( e1 >> 3 );
         f1 = (Short)( e1 &  7 );
 
-        if ( e1 >= 0 && e1 < ras.bWidth                      &&
-             ras.bOrigin[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+        if ( e1 >= 0 && e1 < ras.bWidth     &&
+             ras.bLine[c1] & ( 0x80 >> f1 ) )
           goto Exit;
       }
       else
@@ -2454,7 +2427,7 @@
       c1 = (Short)( e1 >> 3 );
       f1 = (Short)( e1 & 7 );
 
-      ras.bOrigin[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+      ras.bLine[c1] |= (char)( 0x80 >> f1 );
     }
 
   Exit:
@@ -2465,7 +2438,7 @@
   static void
   Vertical_Sweep_Step( RAS_ARG )
   {
-    ras.traceOfs += ras.traceIncr;
+    ras.bLine -= ras.target.pitch;
   }
 
 
@@ -2479,8 +2452,8 @@
    */
 
   static void
-  Horizontal_Sweep_Init( RAS_ARGS Short*  min,
-                                  Short*  max )
+  Horizontal_Sweep_Init( RAS_ARGS Short  min,
+                                  Short  max )
   {
     /* nothing, really */
     FT_UNUSED_RASTER;
@@ -2744,13 +2717,13 @@
     /* check the Y-turns */
     if ( ras.numTurns == 0 )
     {
-      ras.error = FT_THROW( Invalid );
+      ras.error = FT_THROW( Invalid_Outline );
       return FAILURE;
     }
 
     /* now initialize the sweep */
 
-    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
+    ras.Proc_Sweep_Init( RAS_VARS min_Y, max_Y );
 
     /* then compute the distance of each profile from min_Y */
 
@@ -2977,11 +2950,11 @@
   FT_Outline_Get_CBox( const FT_Outline*  outline,
                        FT_BBox           *acbox )
   {
-    Long  xMin, yMin, xMax, yMax;
-
-
     if ( outline && acbox )
     {
+      Long  xMin, yMin, xMax, yMax;
+
+
       if ( outline->n_points == 0 )
       {
         xMin = 0;
@@ -3039,63 +3012,54 @@
    *   Renderer error code.
    */
   static int
-  Render_Single_Pass( RAS_ARGS Bool  flipped )
+  Render_Single_Pass( RAS_ARGS Bool  flipped,
+                               Int   y_min,
+                               Int   y_max )
   {
-    Short  i, j, k;
+    Int  y_mid;
+    Int  band_top = 0;
+    Int  band_stack[32];  /* enough to bisect 32-bit int bands */
 
 
-    while ( ras.band_top >= 0 )
+    while ( 1 )
     {
-      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
-      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
+      ras.minY = (Long)y_min * ras.precision;
+      ras.maxY = (Long)y_max * ras.precision;
 
       ras.top = ras.buff;
 
-      ras.error = Raster_Err_None;
+      ras.error = Raster_Err_Ok;
 
       if ( Convert_Glyph( RAS_VARS flipped ) )
       {
-        if ( ras.error != Raster_Err_Overflow )
-          return FAILURE;
-
-        ras.error = Raster_Err_None;
+        if ( ras.error != Raster_Err_Raster_Overflow )
+          return ras.error;
 
         /* sub-banding */
 
-#ifdef DEBUG_RASTER
-        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
-#endif
+        if ( y_min == y_max )
+          return ras.error;  /* still Raster_Overflow */
 
-        i = ras.band_stack[ras.band_top].y_min;
-        j = ras.band_stack[ras.band_top].y_max;
+        y_mid = ( y_min + y_max ) >> 1;
 
-        k = (Short)( ( i + j ) / 2 );
-
-        if ( ras.band_top >= 7 || k < i )
-        {
-          ras.band_top = 0;
-          ras.error    = FT_THROW( Invalid );
-
-          return ras.error;
-        }
-
-        ras.band_stack[ras.band_top + 1].y_min = k;
-        ras.band_stack[ras.band_top + 1].y_max = j;
-
-        ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
-
-        ras.band_top++;
+        band_stack[band_top++] = y_min;
+        y_min                  = y_mid + 1;
       }
       else
       {
         if ( ras.fProfile )
           if ( Draw_Sweep( RAS_VAR ) )
              return ras.error;
-        ras.band_top--;
+
+        if ( --band_top < 0 )
+          break;
+
+        y_max = y_min - 1;
+        y_min = band_stack[band_top];
       }
     }
 
-    return SUCCESS;
+    return Raster_Err_Ok;
   }
 
 
@@ -3132,9 +3096,6 @@
         ras.dropOutControl += 1;
     }
 
-    ras.second_pass = (Bool)( !( ras.outline.flags      &
-                                 FT_OUTLINE_SINGLE_PASS ) );
-
     /* Vertical Sweep */
     FT_TRACE7(( "Vertical pass (ftraster)\n" ));
 
@@ -3143,21 +3104,18 @@
     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
     ras.Proc_Sweep_Step = Vertical_Sweep_Step;
 
-    ras.band_top            = 0;
-    ras.band_stack[0].y_min = 0;
-    ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 );
-
     ras.bWidth  = (UShort)ras.target.width;
     ras.bOrigin = (Byte*)ras.target.buffer;
 
     if ( ras.target.pitch > 0 )
       ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
 
-    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
+    error = Render_Single_Pass( RAS_VARS 0, 0, (Int)ras.target.rows - 1 );
+    if ( error )
       return error;
 
     /* Horizontal Sweep */
-    if ( ras.second_pass && ras.dropOutControl != 2 )
+    if ( !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS ) )
     {
       FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
 
@@ -3166,22 +3124,12 @@
       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
 
-      ras.band_top            = 0;
-      ras.band_stack[0].y_min = 0;
-      ras.band_stack[0].y_max = (Short)( ras.target.width - 1 );
-
-      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
+      error = Render_Single_Pass( RAS_VARS 1, 0, (Int)ras.target.width - 1 );
+      if ( error )
         return error;
     }
 
-    return Raster_Err_None;
-  }
-
-
-  static void
-  ft_black_init( black_PRaster  raster )
-  {
-    FT_UNUSED( raster );
+    return Raster_Err_Ok;
   }
 
 
@@ -3202,7 +3150,6 @@
 
      *araster = (FT_Raster)&the_raster;
      FT_ZERO( &the_raster );
-     ft_black_init( &the_raster );
 
      return 0;
   }
@@ -3227,14 +3174,10 @@
     black_PRaster  raster = NULL;
 
 
-    *araster = 0;
     if ( !FT_NEW( raster ) )
-    {
       raster->memory = memory;
-      ft_black_init( raster );
 
-      *araster = raster;
-    }
+    *araster = raster;
 
     return error;
   }
@@ -3292,38 +3235,36 @@
 
 
     if ( !raster )
-      return FT_THROW( Not_Ini );
+      return FT_THROW( Raster_Uninitialized );
 
     if ( !outline )
-      return FT_THROW( Invalid );
+      return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
     if ( outline->n_points == 0 || outline->n_contours <= 0 )
-      return Raster_Err_None;
+      return Raster_Err_Ok;
 
     if ( !outline->contours || !outline->points )
-      return FT_THROW( Invalid );
+      return FT_THROW( Invalid_Outline );
 
     if ( outline->n_points !=
            outline->contours[outline->n_contours - 1] + 1 )
-      return FT_THROW( Invalid );
+      return FT_THROW( Invalid_Outline );
 
     /* this version of the raster does not support direct rendering, sorry */
-    if ( params->flags & FT_RASTER_FLAG_DIRECT )
-      return FT_THROW( Unsupported );
-
-    if ( params->flags & FT_RASTER_FLAG_AA )
-      return FT_THROW( Unsupported );
+    if ( params->flags & FT_RASTER_FLAG_DIRECT ||
+         params->flags & FT_RASTER_FLAG_AA     )
+      return FT_THROW( Cannot_Render_Glyph );
 
     if ( !target_map )
-      return FT_THROW( Invalid );
+      return FT_THROW( Invalid_Argument );
 
     /* nothing to do */
     if ( !target_map->width || !target_map->rows )
-      return Raster_Err_None;
+      return Raster_Err_Ok;
 
     if ( !target_map->buffer )
-      return FT_THROW( Invalid );
+      return FT_THROW( Invalid_Argument );
 
     ras.outline = *outline;
     ras.target  = *target_map;
diff --git a/src/raster/ftraster.h b/src/raster/ftraster.h
index 1b2ee3c..4affd48 100644
--- a/src/raster/ftraster.h
+++ b/src/raster/ftraster.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c
index 57fed9b..236a8da 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer interface (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/raster/ftrend1.h b/src/raster/ftrend1.h
index 3f6be53..e4cea53 100644
--- a/src/raster/ftrend1.h
+++ b/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/raster/module.mk b/src/raster/module.mk
index 3600732..fbc1d64 100644
--- a/src/raster/module.mk
+++ b/src/raster/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/raster/raster.c b/src/raster/raster.c
index cd37943..ad81a39 100644
--- a/src/raster/raster.c
+++ b/src/raster/raster.c
@@ -4,7 +4,7 @@
  *
  *   FreeType monochrome rasterer module component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/raster/rasterrs.h b/src/raster/rasterrs.h
index a29651a..852dd5b 100644
--- a/src/raster/rasterrs.h
+++ b/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
  *
  *   monochrome renderer error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/raster/rules.mk b/src/raster/rules.mk
index 3e949d7..7ffda77 100644
--- a/src/raster/rules.mk
+++ b/src/raster/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/sdf/ftbsdf.c b/src/sdf/ftbsdf.c
new file mode 100644
index 0000000..8da5c9d
--- /dev/null
+++ b/src/sdf/ftbsdf.c
@@ -0,0 +1,1347 @@
+/****************************************************************************
+ *
+ * ftbsdf.c
+ *
+ *   Signed Distance Field support for bitmap fonts (body only).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftmemory.h>
+#include <freetype/fttrigon.h>
+
+#include "ftsdf.h"
+#include "ftsdferrs.h"
+#include "ftsdfcommon.h"
+
+
+  /**************************************************************************
+   *
+   * A brief technical overview of how the BSDF rasterizer works
+   * -----------------------------------------------------------
+   *
+   * [Notes]:
+   *   * SDF stands for Signed Distance Field everywhere.
+   *
+   *   * BSDF stands for Bitmap to Signed Distance Field rasterizer.
+   *
+   *   * This renderer converts rasterized bitmaps to SDF.  There is another
+   *     renderer called 'sdf', which generates SDF directly from outlines;
+   *     see file `ftsdf.c` for more.
+   *
+   *   * The idea of generating SDF from bitmaps is taken from two research
+   *     papers, where one is dependent on the other:
+   *
+   *     - Per-Erik Danielsson: Euclidean Distance Mapping
+   *       http://webstaff.itn.liu.se/~stegu/JFA/Danielsson.pdf
+   *
+   *       From this paper we use the eight-point sequential Euclidean
+   *       distance mapping (8SED).  This is the heart of the process used
+   *       in this rasterizer.
+   *
+   *     - Stefan Gustavson, Robin Strand: Anti-aliased Euclidean distance transform.
+   *       http://weber.itn.liu.se/~stegu/aadist/edtaa_preprint.pdf
+   *
+   *       The original 8SED algorithm discards the pixels' alpha values,
+   *       which can contain information about the actual outline of the
+   *       glyph.  This paper takes advantage of those alpha values and
+   *       approximates outline pretty accurately.
+   *
+   *   * This rasterizer also works for monochrome bitmaps.  However, the
+   *     result is not as accurate since we don't have any way to
+   *     approximate outlines from binary bitmaps.
+   *
+   * ========================================================================
+   *
+   * Generating SDF from bitmap is done in several steps.
+   *
+   * (1) The only information we have is the bitmap itself.  It can
+   *     be monochrome or anti-aliased.  If it is anti-aliased, pixel values
+   *     are nothing but coverage values.  These coverage values can be used
+   *     to extract information about the outline of the image.  For
+   *     example, if the pixel's alpha value is 0.5, then we can safely
+   *     assume that the outline passes through the center of the pixel.
+   *
+   * (2) Find edge pixels in the bitmap (see `bsdf_is_edge` for more).  For
+   *     all edge pixels we use the Anti-aliased Euclidean distance
+   *     transform algorithm and compute approximate edge distances (see
+   *     `compute_edge_distance` and/or the second paper for more).
+   *
+   * (3) Now that we have computed approximate distances for edge pixels we
+   *     use the 8SED algorithm to basically sweep the entire bitmap and
+   *     compute distances for the rest of the pixels.  (Since the algorithm
+   *     is pretty convoluted it is only explained briefly in a comment to
+   *     function `edt8`.  To see the actual algorithm refer to the first
+   *     paper.)
+   *
+   * (4) Finally, compute the sign for each pixel.  This is done in function
+   *     `finalize_sdf`.  The basic idea is that if a pixel's original
+   *     alpha/coverage value is greater than 0.5 then it is 'inside' (and
+   *     'outside' otherwise).
+   *
+   * Pseudo Code:
+   *
+   * ```
+   * b  = source bitmap;
+   * t  = target bitmap;
+   * dm = list of distances; // dimension equal to b
+   *
+   * foreach grid_point (x, y) in b:
+   * {
+   *   if (is_edge(x, y)):
+   *     dm = approximate_edge_distance(b, x, y);
+   *
+   *   // do the 8SED on the distances
+   *   edt8(dm);
+   *
+   *   // determine the signs
+   *   determine_signs(dm):
+   *
+   *   // copy SDF data to the target bitmap
+   *   copy(dm to t);
+   * }
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  bsdf
+
+
+  /**************************************************************************
+   *
+   * useful macros
+   *
+   */
+
+#define ONE  65536 /* 1 in 16.16 */
+
+
+  /**************************************************************************
+   *
+   * structs
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   BSDF_TRaster
+   *
+   * @Description:
+   *   This struct is used in place of @FT_Raster and is stored within the
+   *   internal FreeType renderer struct.  While rasterizing this is passed
+   *   to the @FT_Raster_RenderFunc function, which then can be used however
+   *   we want.
+   *
+   * @Fields:
+   *   memory ::
+   *     Used internally to allocate intermediate memory while raterizing.
+   *
+   */
+  typedef struct  BSDF_TRaster_
+  {
+    FT_Memory  memory;
+
+  } BSDF_TRaster, *BSDF_PRaster;
+
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   ED
+   *
+   * @Description:
+   *   Euclidean distance.  It gets used for Euclidean distance transforms;
+   *   it can also be interpreted as an edge distance.
+   *
+   * @Fields:
+   *   dist ::
+   *     Vector length of the `near` parameter.  Can be squared or absolute
+   *     depending on the `USE_SQUARED_DISTANCES` macro defined in file
+   *     `ftsdfcommon.h`.
+   *
+   *   near ::
+   *     Vector to the nearest edge.  Can also be interpreted as shortest
+   *     distance of a point.
+   *
+   *   alpha ::
+   *     Alpha value of the original bitmap from which we generate SDF.
+   *     Needed for computing the gradient and determining the proper sign
+   *     of a pixel.
+   *
+   */
+  typedef struct  ED_
+  {
+    FT_16D16      dist;
+    FT_16D16_Vec  near;
+    FT_Byte       alpha;
+
+  } ED;
+
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   BSDF_Worker
+   *
+   * @Description:
+   *   A convenience struct that is passed to functions while generating
+   *   SDF; most of those functions require the same parameters.
+   *
+   * @Fields:
+   *   distance_map ::
+   *     A one-dimensional array that gets interpreted as two-dimensional
+   *     one.  It contains the Euclidean distances of all points of the
+   *     bitmap.
+   *
+   *   width ::
+   *     Width of the above `distance_map`.
+   *
+   *   rows ::
+   *     Number of rows in the above `distance_map`.
+   *
+   *   params ::
+   *     Internal parameters and properties required by the rasterizer.  See
+   *     file `ftsdf.h` for more.
+   *
+   */
+  typedef struct  BSDF_Worker_
+  {
+    ED*  distance_map;
+
+    FT_Int  width;
+    FT_Int  rows;
+
+    SDF_Raster_Params  params;
+
+  } BSDF_Worker;
+
+
+  /**************************************************************************
+   *
+   * initializer
+   *
+   */
+
+  static const ED  zero_ed = { 0, { 0, 0 }, 0 };
+
+
+  /**************************************************************************
+   *
+   * rasterizer functions
+   *
+   */
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   bsdf_is_edge
+   *
+   * @Description:
+   *   Check whether a pixel is an edge pixel, i.e., whether it is
+   *   surrounded by a completely black pixel (zero alpha), and the current
+   *   pixel is not a completely black pixel.
+   *
+   * @Input:
+   *   dm ::
+   *     Array of distances.  The parameter must point to the current
+   *     pixel, i.e., the pixel that is to be checked for being an edge.
+   *
+   *   x ::
+   *     The x position of the current pixel.
+   *
+   *   y ::
+   *     The y position of the current pixel.
+   *
+   *   w ::
+   *     Width of the bitmap.
+   *
+   *   r ::
+   *     Number of rows in the bitmap.
+   *
+   * @Return:
+   *   1~if the current pixel is an edge pixel, 0~otherwise.
+   *
+   */
+
+#ifdef CHECK_NEIGHBOR
+#undef CHECK_NEIGHBOR
+#endif
+
+#define CHECK_NEIGHBOR( x_offset, y_offset )              \
+          do                                              \
+          {                                               \
+            if ( x + x_offset >= 0 && x + x_offset < w && \
+                 y + y_offset >= 0 && y + y_offset < r )  \
+            {                                             \
+              num_neighbors++;                            \
+                                                          \
+              to_check = dm + y_offset * w + x_offset;    \
+              if ( to_check->alpha == 0 )                 \
+              {                                           \
+                is_edge = 1;                              \
+                goto Done;                                \
+              }                                           \
+            }                                             \
+          } while ( 0 )
+
+  static FT_Bool
+  bsdf_is_edge( ED*     dm,   /* distance map              */
+                FT_Int  x,    /* x index of point to check */
+                FT_Int  y,    /* y index of point to check */
+                FT_Int  w,    /* width                     */
+                FT_Int  r )   /* rows                      */
+  {
+    FT_Bool  is_edge       = 0;
+    ED*      to_check      = NULL;
+    FT_Int   num_neighbors = 0;
+
+
+    if ( dm->alpha == 0 )
+      goto Done;
+
+    if ( dm->alpha > 0 && dm->alpha < 255 )
+    {
+      is_edge = 1;
+      goto Done;
+    }
+
+    /* up */
+    CHECK_NEIGHBOR(  0, -1 );
+
+    /* down */
+    CHECK_NEIGHBOR(  0,  1 );
+
+    /* left */
+    CHECK_NEIGHBOR( -1,  0 );
+
+    /* right */
+    CHECK_NEIGHBOR(  1,  0 );
+
+    /* up left */
+    CHECK_NEIGHBOR( -1, -1 );
+
+    /* up right */
+    CHECK_NEIGHBOR(  1, -1 );
+
+    /* down left */
+    CHECK_NEIGHBOR( -1,  1 );
+
+    /* down right */
+    CHECK_NEIGHBOR(  1,  1 );
+
+    if ( num_neighbors != 8 )
+      is_edge = 1;
+
+  Done:
+    return is_edge;
+  }
+
+#undef CHECK_NEIGHBOR
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   compute_edge_distance
+   *
+   * @Description:
+   *   Approximate the outline and compute the distance from `current`
+   *   to the approximated outline.
+   *
+   * @Input:
+   *   current ::
+   *     Array of Euclidean distances.  `current` must point to the position
+   *     for which the distance is to be caculated.  We treat this array as
+   *     a two-dimensional array mapped to a one-dimensional array.
+   *
+   *   x ::
+   *     The x coordinate of the `current` parameter in the array.
+   *
+   *   y ::
+   *     The y coordinate of the `current` parameter in the array.
+   *
+   *   w ::
+   *     The width of the distances array.
+   *
+   *   r ::
+   *     Number of rows in the distances array.
+   *
+   * @Return:
+   *   A vector pointing to the approximate edge distance.
+   *
+   * @Note:
+   *   This is a computationally expensive function.  Try to reduce the
+   *   number of calls to this function.  Moreover, this must only be used
+   *   for edge pixel positions.
+   *
+   */
+  static FT_16D16_Vec
+  compute_edge_distance( ED*     current,
+                         FT_Int  x,
+                         FT_Int  y,
+                         FT_Int  w,
+                         FT_Int  r )
+  {
+    /*
+     * This function, based on the paper presented by Stefan Gustavson and
+     * Robin Strand, gets used to approximate edge distances from
+     * anti-aliased bitmaps.
+     *
+     * The algorithm is as follows.
+     *
+     * (1) In anti-aliased images, the pixel's alpha value is the coverage
+     *     of the pixel by the outline.  For example, if the alpha value is
+     *     0.5f we can assume that the outline passes through the center of
+     *     the pixel.
+     *
+     * (2) For this reason we can use that alpha value to approximate the real
+     *     distance of the pixel to edge pretty accurately.  A simple
+     *     approximation is `(0.5f - alpha)`, assuming that the outline is
+     *     parallel to the x or y~axis.  However, in this algorithm we use a
+     *     different approximation which is quite accurate even for
+     *     non-axis-aligned edges.
+     *
+     * (3) The only remaining piece of information that we cannot
+     *     approximate directly from the alpha is the direction of the edge.
+     *     This is where we use Sobel's operator to compute the gradient of
+     *     the pixel.  The gradient give us a pretty good approximation of
+     *     the edge direction.  We use a 3x3 kernel filter to compute the
+     *     gradient.
+     *
+     * (4) After the above two steps we have both the direction and the
+     *     distance to the edge which is used to generate the Signed
+     *     Distance Field.
+     *
+     * References:
+     *
+     * - Anti-Aliased Euclidean Distance Transform:
+     *     http://weber.itn.liu.se/~stegu/aadist/edtaa_preprint.pdf
+     * - Sobel Operator:
+     *     https://en.wikipedia.org/wiki/Sobel_operator
+     */
+
+    FT_16D16_Vec  g = { 0, 0 };
+    FT_16D16      dist, current_alpha;
+    FT_16D16      a1, temp;
+    FT_16D16      gx, gy;
+    FT_16D16      alphas[9];
+
+
+    /* Since our spread cannot be 0, this condition */
+    /* can never be true.                           */
+    if ( x <= 0 || x >= w - 1 ||
+         y <= 0 || y >= r - 1 )
+      return g;
+
+    /* initialize the alphas */
+    alphas[0] = 256 * (FT_16D16)current[-w - 1].alpha;
+    alphas[1] = 256 * (FT_16D16)current[-w    ].alpha;
+    alphas[2] = 256 * (FT_16D16)current[-w + 1].alpha;
+    alphas[3] = 256 * (FT_16D16)current[    -1].alpha;
+    alphas[4] = 256 * (FT_16D16)current[     0].alpha;
+    alphas[5] = 256 * (FT_16D16)current[     1].alpha;
+    alphas[6] = 256 * (FT_16D16)current[ w - 1].alpha;
+    alphas[7] = 256 * (FT_16D16)current[ w    ].alpha;
+    alphas[8] = 256 * (FT_16D16)current[ w + 1].alpha;
+
+    current_alpha = alphas[4];
+
+    /* Compute the gradient using the Sobel operator. */
+    /* In this case we use the following 3x3 filters: */
+    /*                                                */
+    /* For x: |   -1     0   -1    |                  */
+    /*        | -root(2) 0 root(2) |                  */
+    /*        |    -1    0    1    |                  */
+    /*                                                */
+    /* For y: |   -1 -root(2) -1   |                  */
+    /*        |    0    0      0   |                  */
+    /*        |    1  root(2)  1   |                  */
+    /*                                                */
+    /* [Note]: 92681 is root(2) in 16.16 format.      */
+    g.x = -alphas[0] -
+           FT_MulFix( alphas[3], 92681 ) -
+           alphas[6] +
+           alphas[2] +
+           FT_MulFix( alphas[5], 92681 ) +
+           alphas[8];
+
+    g.y = -alphas[0] -
+           FT_MulFix( alphas[1], 92681 ) -
+           alphas[2] +
+           alphas[6] +
+           FT_MulFix( alphas[7], 92681 ) +
+           alphas[8];
+
+    FT_Vector_NormLen( &g );
+
+    /* The gradient gives us the direction of the    */
+    /* edge for the current pixel.  Once we have the */
+    /* approximate direction of the edge, we can     */
+    /* approximate the edge distance much better.    */
+
+    if ( g.x == 0 || g.y == 0 )
+      dist = ONE / 2 - alphas[4];
+    else
+    {
+      gx = g.x;
+      gy = g.y;
+
+      gx = FT_ABS( gx );
+      gy = FT_ABS( gy );
+
+      if ( gx < gy )
+      {
+        temp = gx;
+        gx   = gy;
+        gy   = temp;
+      }
+
+      a1 = FT_DivFix( gy, gx ) / 2;
+
+      if ( current_alpha < a1 )
+        dist = ( gx + gy ) / 2 -
+               square_root( 2 * FT_MulFix( gx,
+                                           FT_MulFix( gy,
+                                                      current_alpha ) ) );
+
+      else if ( current_alpha < ( ONE - a1 ) )
+        dist = FT_MulFix( ONE / 2 - current_alpha, gx );
+
+      else
+        dist = -( gx + gy ) / 2 +
+               square_root( 2 * FT_MulFix( gx,
+                                           FT_MulFix( gy,
+                                                      ONE - current_alpha ) ) );
+    }
+
+    g.x = FT_MulFix( g.x, dist );
+    g.y = FT_MulFix( g.y, dist );
+
+    return g;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   bsdf_approximate_edge
+   *
+   * @Description:
+   *   Loops over all the pixels and call `compute_edge_distance` only for
+   *   edge pixels.  This maked the process a lot faster since
+   *   `compute_edge_distance` uses functions such as `FT_Vector_NormLen',
+   *   which are quite slow.
+   *
+   * @InOut:
+   *   worker ::
+   *     Contains the distance map as well as all the relevant parameters
+   *     required by the function.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   * @Note:
+   *   The function directly manipulates `worker->distance_map`.
+   *
+   */
+  static FT_Error
+  bsdf_approximate_edge( BSDF_Worker*  worker )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_Int    i, j;
+    FT_Int    index;
+    ED*       ed;
+
+
+    if ( !worker || !worker->distance_map )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    ed = worker->distance_map;
+
+    for ( j = 0; j < worker->rows; j++ )
+    {
+      for ( i = 0; i < worker->width; i++ )
+      {
+        index = j * worker->width + i;
+
+        if ( bsdf_is_edge( worker->distance_map + index,
+                           i, j,
+                           worker->width,
+                           worker->rows ) )
+        {
+          /* approximate the edge distance for edge pixels */
+          ed[index].near = compute_edge_distance( ed + index,
+                                                  i, j,
+                                                  worker->width,
+                                                  worker->rows );
+          ed[index].dist = VECTOR_LENGTH_16D16( ed[index].near );
+        }
+        else
+        {
+          /* for non-edge pixels assign far away distances */
+          ed[index].dist   = 400 * ONE;
+          ed[index].near.x = 200 * ONE;
+          ed[index].near.y = 200 * ONE;
+        }
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   bsdf_init_distance_map
+   *
+   * @Description:
+   *   Initialize the distance map according to the '8-point sequential
+   *   Euclidean distance mapping' (8SED) algorithm.  Basically it copies
+   *   the `source` bitmap alpha values to the `distance_map->alpha`
+   *   parameter of `worker`.
+   *
+   * @Input:
+   *   source ::
+   *     Source bitmap to copy the data from.
+   *
+   * @Output:
+   *   worker ::
+   *     Target distance map to copy the data to.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   */
+  static FT_Error
+  bsdf_init_distance_map( const FT_Bitmap*  source,
+                          BSDF_Worker*      worker )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+    FT_Int    x_diff, y_diff;
+    FT_Int    t_i, t_j, s_i, s_j;
+    FT_Byte*  s;
+    ED*       t;
+
+
+    /* again check the parameters (probably unnecessary) */
+    if ( !source || !worker )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* Because of the way we convert a bitmap to SDF, */
+    /* i.e., aligning the source to the center of the */
+    /* target, the target's width and rows must be    */
+    /* checked before copying.                        */
+    if ( worker->width < (FT_Int)source->width ||
+         worker->rows  < (FT_Int)source->rows  )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* check pixel mode */
+    if ( source->pixel_mode == FT_PIXEL_MODE_NONE )
+    {
+      FT_ERROR(( "bsdf_copy_source_to_target:"
+                 " Invalid pixel mode of source bitmap" ));
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( source->pixel_mode == FT_PIXEL_MODE_MONO )
+    {
+      FT_TRACE0(( "bsdf_copy_source_to_target:"
+                  " The `bsdf' renderer can convert monochrome\n" ));
+      FT_TRACE0(( "                           "
+                  " bitmaps to SDF but the results are not perfect\n" ));
+      FT_TRACE0(( "                           "
+                  " because there is no way to approximate actual\n" ));
+      FT_TRACE0(( "                           "
+                  " outlines from monochrome bitmaps.  Consider\n" ));
+      FT_TRACE0(( "                           "
+                  " using an anti-aliased bitmap instead.\n" ));
+    }
+#endif
+
+    /* Calculate the width and row differences */
+    /* between target and source.              */
+    x_diff = worker->width - (int)source->width;
+    y_diff = worker->rows - (int)source->rows;
+
+    x_diff /= 2;
+    y_diff /= 2;
+
+    t = (ED*)worker->distance_map;
+    s = source->buffer;
+
+    /* For now we only support pixel mode `FT_PIXEL_MODE_MONO`  */
+    /* and `FT_PIXEL_MODE_GRAY`.  More will be added later.     */
+    /*                                                          */
+    /* [NOTE]: We can also use @FT_Bitmap_Convert to convert    */
+    /*         bitmap to 8bpp.  To avoid extra allocation and   */
+    /*         since the target bitmap can be 16bpp we manually */
+    /*         convert the source bitmap to the desired bpp.    */
+
+    switch ( source->pixel_mode )
+    {
+    case FT_PIXEL_MODE_MONO:
+      {
+        FT_Int  t_width = worker->width;
+        FT_Int  t_rows  = worker->rows;
+        FT_Int  s_width = (int)source->width;
+        FT_Int  s_rows  = (int)source->rows;
+
+
+        for ( t_j = 0; t_j < t_rows; t_j++ )
+        {
+          for ( t_i = 0; t_i < t_width; t_i++ )
+          {
+            FT_Int   t_index = t_j * t_width + t_i;
+            FT_Int   s_index;
+            FT_Int   div, mod;
+            FT_Byte  pixel, byte;
+
+
+            t[t_index] = zero_ed;
+
+            s_i = t_i - x_diff;
+            s_j = t_j - y_diff;
+
+            /* Assign 0 to padding similar to */
+            /* the source bitmap.             */
+            if ( s_i < 0 || s_i >= s_width ||
+                 s_j < 0 || s_j >= s_rows  )
+              continue;
+
+            if ( worker->params.flip_y )
+              s_index = ( s_rows - s_j - 1 ) * source->pitch;
+            else
+              s_index = s_j * source->pitch;
+
+            div = s_index + s_i / 8;
+            mod = 7 - s_i % 8;
+
+            pixel = s[div];
+            byte  = (FT_Byte)( 1 << mod );
+
+            t[t_index].alpha = pixel & byte ? 255 : 0;
+
+            pixel = 0;
+          }
+        }
+      }
+      break;
+
+    case FT_PIXEL_MODE_GRAY:
+      {
+        FT_Int  t_width = worker->width;
+        FT_Int  t_rows  = worker->rows;
+        FT_Int  s_width = (int)source->width;
+        FT_Int  s_rows  = (int)source->rows;
+
+
+        /* loop over all pixels and assign pixel values from source */
+        for ( t_j = 0; t_j < t_rows; t_j++ )
+        {
+          for ( t_i = 0; t_i < t_width; t_i++ )
+          {
+            FT_Int  t_index = t_j * t_width + t_i;
+            FT_Int  s_index;
+
+
+            t[t_index] = zero_ed;
+
+            s_i = t_i - x_diff;
+            s_j = t_j - y_diff;
+
+            /* Assign 0 to padding similar to */
+            /* the source bitmap.             */
+            if ( s_i < 0 || s_i >= s_width ||
+                 s_j < 0 || s_j >= s_rows  )
+              continue;
+
+            if ( worker->params.flip_y )
+              s_index = ( s_rows - s_j - 1 ) * s_width + s_i;
+            else
+              s_index = s_j * s_width + s_i;
+
+            /* simply copy the alpha values */
+            t[t_index].alpha = s[s_index];
+          }
+        }
+      }
+      break;
+
+    default:
+      FT_ERROR(( "bsdf_copy_source_to_target:"
+                 " unsopported pixel mode of source bitmap\n" ));
+
+      error = FT_THROW( Unimplemented_Feature );
+      break;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   compare_neighbor
+   *
+   * @Description:
+   *   Compare neighbor pixel (which is defined by the offset) and update
+   *   `current` distance if the new distance is shorter than the original.
+   *
+   * @Input:
+   *   x_offset ::
+   *     X offset of the neighbor to be checked.  The offset is relative to
+   *     the `current`.
+   *
+   *   y_offset ::
+   *     Y offset of the neighbor to be checked.  The offset is relative to
+   *     the `current`.
+   *
+   *   width ::
+   *     Width of the `current` array.
+   *
+   * @InOut:
+   *   current ::
+   *     Pointer into array of distances.  This parameter must point to the
+   *     position whose neighbor is to be checked.  The array is treated as
+   *     a two-dimensional array.
+   *
+   */
+  static void
+  compare_neighbor( ED*     current,
+                    FT_Int  x_offset,
+                    FT_Int  y_offset,
+                    FT_Int  width )
+  {
+    ED*           to_check;
+    FT_16D16      dist;
+    FT_16D16_Vec  dist_vec;
+
+
+    to_check = current + ( y_offset * width ) + x_offset;
+
+    /*
+     * While checking for the nearest point we first approximate the
+     * distance of `current` by adding the deviation (which is sqrt(2) at
+     * most).  Only if the new value is less than the current value we
+     * calculate the actual distances using `FT_Vector_Length`.  This last
+     * step can be omitted by using squared distances.
+     */
+
+    /*
+     * Approximate the distance.  We subtract 1 to avoid precision errors,
+     * which could happen because the two directions can be opposite.
+     */
+    dist = to_check->dist - ONE;
+
+    if ( dist < current->dist )
+    {
+      dist_vec = to_check->near;
+
+      dist_vec.x += x_offset * ONE;
+      dist_vec.y += y_offset * ONE;
+      dist = VECTOR_LENGTH_16D16( dist_vec );
+
+      if ( dist < current->dist )
+      {
+        current->dist = dist;
+        current->near = dist_vec;
+      }
+    }
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   first_pass
+   *
+   * @Description:
+   *   First pass of the 8SED algorithm.  Loop over the bitmap from top to
+   *   bottom and scan each row left to right, updating the distances in
+   *   `worker->distance_map`.
+   *
+   * @InOut:
+   *   worker::
+   *     Contains all the relevant parameters.
+   *
+   */
+  static void
+  first_pass( BSDF_Worker*  worker )
+  {
+    FT_Int  i, j; /* iterators    */
+    FT_Int  w, r; /* width, rows  */
+    ED*     dm;   /* distance map */
+
+
+    dm = worker->distance_map;
+    w  = worker->width;
+    r  = worker->rows;
+
+    /* Start scanning from top to bottom and sweep each    */
+    /* row back and forth comparing the distances of the   */
+    /* neighborhood.  Leave the first row as it has no top */
+    /* neighbor; it will be covered in the second scan of  */
+    /* the image (from bottom to top).                     */
+    for ( j = 1; j < r; j++ )
+    {
+      FT_Int  index;
+      ED*     current;
+
+
+      /* Forward pass of rows (left -> right).  Leave the first  */
+      /* column, which gets covered in the backward pass.        */
+      for ( i = 1; i < w - 1; i++ )
+      {
+        index   = j * w + i;
+        current = dm + index;
+
+        /* left-up */
+        compare_neighbor( current, -1, -1, w );
+        /* up */
+        compare_neighbor( current,  0, -1, w );
+        /* up-right */
+        compare_neighbor( current,  1, -1, w );
+        /* left */
+        compare_neighbor( current, -1,  0, w );
+      }
+
+      /* Backward pass of rows (right -> left).  Leave the last */
+      /* column, which was already covered in the forward pass. */
+      for ( i = w - 2; i >= 0; i-- )
+      {
+        index   = j * w + i;
+        current = dm + index;
+
+        /* right */
+        compare_neighbor( current, 1, 0, w );
+      }
+    }
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   second_pass
+   *
+   * @Description:
+   *   Second pass of the 8SED algorithm.  Loop over the bitmap from bottom
+   *   to top and scan each row left to right, updating the distances in
+   *   `worker->distance_map`.
+   *
+   * @InOut:
+   *   worker::
+   *     Contains all the relevant parameters.
+   *
+   */
+  static void
+  second_pass( BSDF_Worker*  worker )
+  {
+    FT_Int  i, j; /* iterators    */
+    FT_Int  w, r; /* width, rows  */
+    ED*     dm;   /* distance map */
+
+
+    dm = worker->distance_map;
+    w  = worker->width;
+    r  = worker->rows;
+
+    /* Start scanning from bottom to top and sweep each    */
+    /* row back and forth comparing the distances of the   */
+    /* neighborhood.  Leave the last row as it has no down */
+    /* neighbor; it is already covered in the first scan   */
+    /* of the image (from top to bottom).                  */
+    for ( j = r - 2; j >= 0; j-- )
+    {
+      FT_Int  index;
+      ED*     current;
+
+
+      /* Forward pass of rows (left -> right).  Leave the first */
+      /* column, which gets covered in the backward pass.       */
+      for ( i = 1; i < w - 1; i++ )
+      {
+        index   = j * w + i;
+        current = dm + index;
+
+        /* left-up */
+        compare_neighbor( current, -1, 1, w );
+        /* up */
+        compare_neighbor( current,  0, 1, w );
+        /* up-right */
+        compare_neighbor( current,  1, 1, w );
+        /* left */
+        compare_neighbor( current, -1, 0, w );
+      }
+
+      /* Backward pass of rows (right -> left).  Leave the last */
+      /* column, which was already covered in the forward pass. */
+      for ( i = w - 2; i >= 0; i-- )
+      {
+        index   = j * w + i;
+        current = dm + index;
+
+        /* right */
+        compare_neighbor( current, 1, 0, w );
+      }
+    }
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   edt8
+   *
+   * @Description:
+   *   Compute the distance map of the a bitmap.  Execute both first and
+   *   second pass of the 8SED algorithm.
+   *
+   * @InOut:
+   *   worker::
+   *     Contains all the relevant parameters.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   */
+  static FT_Error
+  edt8( BSDF_Worker*  worker )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+
+    if ( !worker || !worker->distance_map )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* first scan of the image */
+    first_pass( worker );
+
+    /* second scan of the image */
+    second_pass( worker );
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   finalize_sdf
+   *
+   * @Description:
+   *   Copy the SDF data from `worker->distance_map` to the `target` bitmap.
+   *   Also transform the data to output format, (which is 6.10 fixed-point
+   *   format at the moment).
+   *
+   * @Input:
+   *   worker ::
+   *     Contains source distance map and other SDF data.
+   *
+   * @Output:
+   *   target ::
+   *     Target bitmap to which the SDF data is copied to.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   */
+  static FT_Error
+  finalize_sdf( BSDF_Worker*      worker,
+                const FT_Bitmap*  target )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+    FT_Int  w, r;
+    FT_Int  i, j;
+
+    FT_SDFFormat*  t_buffer;
+    FT_16D16       spread;
+
+
+    if ( !worker || !target )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    w        = (int)target->width;
+    r        = (int)target->rows;
+    t_buffer = (FT_SDFFormat*)target->buffer;
+
+    if ( w != worker->width ||
+         r != worker->rows  )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+#if USE_SQUARED_DISTANCES
+    spread = FT_INT_16D16( worker->params.spread *
+                           worker->params.spread );
+#else
+    spread = FT_INT_16D16( worker->params.spread );
+#endif
+
+    for ( j = 0; j < r; j++ )
+    {
+      for ( i = 0; i < w; i++ )
+      {
+        FT_Int        index;
+        FT_16D16      dist;
+        FT_SDFFormat  final_dist;
+        FT_Char       sign;
+
+
+        index = j * w + i;
+        dist  = worker->distance_map[index].dist;
+
+        if ( dist < 0 || dist > spread )
+          dist = spread;
+
+#if USE_SQUARED_DISTANCES
+        dist = square_root( dist );
+#endif
+
+        /* We assume that if the pixel is inside a contour */
+        /* its coverage value must be > 127.               */
+        sign = worker->distance_map[index].alpha < 127 ? -1 : 1;
+
+        /* flip the sign according to the property */
+        if ( worker->params.flip_sign )
+          sign = -sign;
+
+        /* concatenate from 16.16 to appropriate format */
+        final_dist = map_fixed_to_sdf( dist * sign, spread );
+
+        t_buffer[index] = final_dist;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * interface functions
+   *
+   */
+
+  /* called when adding a new module through @FT_Add_Module */
+  static FT_Error
+  bsdf_raster_new( FT_Memory      memory,
+                   BSDF_PRaster*  araster )
+  {
+    FT_Error      error;
+    BSDF_PRaster  raster = NULL;
+
+
+    if ( !FT_NEW( raster ) )
+      raster->memory = memory;
+
+    *araster = raster;
+
+    return error;
+  }
+
+
+  /* unused */
+  static void
+  bsdf_raster_reset( FT_Raster       raster,
+                     unsigned char*  pool_base,
+                     unsigned long   pool_size )
+  {
+    FT_UNUSED( raster );
+    FT_UNUSED( pool_base );
+    FT_UNUSED( pool_size );
+  }
+
+
+  /* unused */
+  static FT_Error
+  bsdf_raster_set_mode( FT_Raster      raster,
+                        unsigned long  mode,
+                        void*          args )
+  {
+    FT_UNUSED( raster );
+    FT_UNUSED( mode );
+    FT_UNUSED( args );
+
+    return FT_Err_Ok;
+  }
+
+
+  /* called while rendering through @FT_Render_Glyph */
+  static FT_Error
+  bsdf_raster_render( FT_Raster                raster,
+                      const FT_Raster_Params*  params )
+  {
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = NULL;
+
+    const FT_Bitmap*  source = NULL;
+    const FT_Bitmap*  target = NULL;
+
+    BSDF_TRaster*  bsdf_raster = (BSDF_TRaster*)raster;
+    BSDF_Worker    worker;
+
+    const SDF_Raster_Params*  sdf_params = (const SDF_Raster_Params*)params;
+
+
+    worker.distance_map = NULL;
+
+    /* check for valid parameters */
+    if ( !raster || !params )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* check whether the flag is set */
+    if ( sdf_params->root.flags != FT_RASTER_FLAG_SDF )
+    {
+      error = FT_THROW( Raster_Corrupted );
+      goto Exit;
+    }
+
+    source = (const FT_Bitmap*)sdf_params->root.source;
+    target = (const FT_Bitmap*)sdf_params->root.target;
+
+    /* check source and target bitmap */
+    if ( !source || !target )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    memory = bsdf_raster->memory;
+    if ( !memory )
+    {
+      FT_TRACE0(( "bsdf_raster_render: Raster not set up properly,\n" ));
+      FT_TRACE0(( "                    unable to find memory handle.\n" ));
+
+      error = FT_THROW( Invalid_Handle );
+      goto Exit;
+    }
+
+    /* check whether spread is set properly */
+    if ( sdf_params->spread > MAX_SPREAD ||
+         sdf_params->spread < MIN_SPREAD )
+    {
+      FT_TRACE0(( "bsdf_raster_render:"
+                  " The `spread' field of `SDF_Raster_Params'\n" ));
+      FT_TRACE0(( "                   "
+                  " is invalid; the value of this field must be\n" ));
+      FT_TRACE0(( "                   "
+                  " within [%d, %d].\n",
+                  MIN_SPREAD, MAX_SPREAD ));
+      FT_TRACE0(( "                   "
+                  " Also, you must pass `SDF_Raster_Params'\n" ));
+      FT_TRACE0(( "                   "
+                  " instead of the default `FT_Raster_Params'\n" ));
+      FT_TRACE0(( "                   "
+                  " while calling this function and set the fields\n" ));
+      FT_TRACE0(( "                   "
+                  " accordingly.\n" ));
+
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* set up the worker */
+
+    /* allocate the distance map */
+    if ( FT_QALLOC_MULT( worker.distance_map, target->rows,
+                         target->width * sizeof ( *worker.distance_map ) ) )
+      goto Exit;
+
+    worker.width  = (int)target->width;
+    worker.rows   = (int)target->rows;
+    worker.params = *sdf_params;
+
+    FT_CALL( bsdf_init_distance_map( source, &worker ) );
+    FT_CALL( bsdf_approximate_edge( &worker ) );
+    FT_CALL( edt8( &worker ) );
+    FT_CALL( finalize_sdf( &worker, target ) );
+
+    FT_TRACE0(( "bsdf_raster_render: Total memory used = %ld\n",
+                worker.width * worker.rows *
+                  (long)sizeof ( *worker.distance_map ) ));
+
+  Exit:
+    if ( worker.distance_map )
+      FT_FREE( worker.distance_map );
+
+    return error;
+  }
+
+
+  /* called while deleting `FT_Library` only if the module is added */
+  static void
+  bsdf_raster_done( FT_Raster  raster )
+  {
+    FT_Memory  memory = (FT_Memory)((BSDF_TRaster*)raster)->memory;
+
+
+    FT_FREE( raster );
+  }
+
+
+  FT_DEFINE_RASTER_FUNCS(
+    ft_bitmap_sdf_raster,
+
+    FT_GLYPH_FORMAT_BITMAP,
+
+    (FT_Raster_New_Func)     bsdf_raster_new,       /* raster_new      */
+    (FT_Raster_Reset_Func)   bsdf_raster_reset,     /* raster_reset    */
+    (FT_Raster_Set_Mode_Func)bsdf_raster_set_mode,  /* raster_set_mode */
+    (FT_Raster_Render_Func)  bsdf_raster_render,    /* raster_render   */
+    (FT_Raster_Done_Func)    bsdf_raster_done       /* raster_done     */
+  )
+
+
+/* END */
diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c
new file mode 100644
index 0000000..f69cf49
--- /dev/null
+++ b/src/sdf/ftsdf.c
@@ -0,0 +1,3872 @@
+/****************************************************************************
+ *
+ * ftsdf.c
+ *
+ *   Signed Distance Field support for outline fonts (body).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/ftoutln.h>
+#include <freetype/fttrigon.h>
+#include <freetype/ftbitmap.h>
+#include "ftsdf.h"
+
+#include "ftsdferrs.h"
+
+
+  /**************************************************************************
+   *
+   * A brief technical overview of how the SDF rasterizer works
+   * ----------------------------------------------------------
+   *
+   * [Notes]:
+   *   * SDF stands for Signed Distance Field everywhere.
+   *
+   *   * This renderer generates SDF directly from outlines.  There is
+   *     another renderer called 'bsdf', which converts bitmaps to SDF; see
+   *     file `ftbsdf.c` for more.
+   *
+   *   * The basic idea of generating the SDF is taken from Viktor Chlumsky's
+   *     research paper.  The paper explains both single and multi-channel
+   *     SDF, however, this implementation only generates single-channel SDF.
+   *
+   *       Chlumsky, Viktor: Shape Decomposition for Multi-channel Distance
+   *       Fields.  Master's thesis.  Czech Technical University in Prague,
+   *       Faculty of InformationTechnology, 2015.
+   *
+   *     For more information: https://github.com/Chlumsky/msdfgen
+   *
+   * ========================================================================
+   *
+   * Generating SDF from outlines is pretty straightforward.
+   *
+   * (1) We have a set of contours that make the outline of a shape/glyph.
+   *     Each contour comprises of several edges, with three types of edges.
+   *
+   *     * line segments
+   *     * conic Bezier curves
+   *     * cubic Bezier curves
+   *
+   * (2) Apart from the outlines we also have a two-dimensional grid, namely
+   *     the bitmap that is used to represent the final SDF data.
+   *
+   * (3) In order to generate SDF, our task is to find shortest signed
+   *     distance from each grid point to the outline.  The 'signed
+   *     distance' means that if the grid point is filled by any contour
+   *     then its sign is positive, otherwise it is negative.  The pseudo
+   *     code is as follows.
+   *
+   *     ```
+   *     foreach grid_point (x, y):
+   *     {
+   *       int min_dist = INT_MAX;
+   *
+   *       foreach contour in outline:
+   *       {
+   *         foreach edge in contour:
+   *         {
+   *           // get shortest distance from point (x, y) to the edge
+   *           d = get_min_dist(x, y, edge);
+   *
+   *           if (d < min_dist)
+   *             min_dist = d;
+   *         }
+   *
+   *         bitmap[x, y] = min_dist;
+   *       }
+   *     }
+   *     ```
+   *
+   * (4) After running this algorithm the bitmap contains information about
+   *     the shortest distance from each point to the outline of the shape.
+   *     Of course, while this is the most straightforward way of generating
+   *     SDF, we use various optimizations in our implementation.  See the
+   *     `sdf_generate_*' functions in this file for all details.
+   *
+   *     The optimization currently used by default is subdivision; see
+   *     function `sdf_generate_subdivision` for more.
+   *
+   *     Also, to see how we compute the shortest distance from a point to
+   *     each type of edge, check out the `get_min_distance_*' functions.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  sdf
+
+
+  /**************************************************************************
+   *
+   * definitions
+   *
+   */
+
+  /*
+   * If set to 1, the rasterizer uses Newton-Raphson's method for finding
+   * the shortest distance from a point to a conic curve.
+   *
+   * If set to 0, an analytical method gets used instead, which computes the
+   * roots of a cubic polynomial to find the shortest distance.  However,
+   * the analytical method can currently underflow; we thus use Newton's
+   * method by default.
+   */
+#ifndef USE_NEWTON_FOR_CONIC
+#define USE_NEWTON_FOR_CONIC  1
+#endif
+
+  /*
+   * The number of intervals a Bezier curve gets sampled and checked to find
+   * the shortest distance.
+   */
+#define MAX_NEWTON_DIVISIONS  4
+
+  /*
+   * The number of steps of Newton's iterations in each interval of the
+   * Bezier curve.  Basically, we run Newton's approximation
+   *
+   *   x -= Q(t) / Q'(t)
+   *
+   * for each division to get the shortest distance.
+   */
+#define MAX_NEWTON_STEPS  4
+
+  /*
+   * The epsilon distance (in 16.16 fractional units) used for corner
+   * resolving.  If the difference of two distances is less than this value
+   * they will be checked for a corner if they are ambiguous.
+   */
+#define CORNER_CHECK_EPSILON  32
+
+#if 0
+  /*
+   * Coarse grid dimension.  Will probably be removed in the future because
+   * coarse grid optimization is the slowest algorithm.
+   */
+#define CG_DIMEN  8
+#endif
+
+
+  /**************************************************************************
+   *
+   * macros
+   *
+   */
+
+#define MUL_26D6( a, b )  ( ( ( a ) * ( b ) ) / 64 )
+#define VEC_26D6_DOT( p, q )  ( MUL_26D6( p.x, q.x ) + \
+                                MUL_26D6( p.y, q.y ) )
+
+
+  /**************************************************************************
+   *
+   * structures and enums
+   *
+   */
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   SDF_TRaster
+   *
+   * @Description:
+   *   This struct is used in place of @FT_Raster and is stored within the
+   *   internal FreeType renderer struct.  While rasterizing it is passed to
+   *   the @FT_Raster_RenderFunc function, which then can be used however we
+   *   want.
+   *
+   * @Fields:
+   *   memory ::
+   *     Used internally to allocate intermediate memory while raterizing.
+   *
+   */
+  typedef struct  SDF_TRaster_
+  {
+    FT_Memory  memory;
+
+  } SDF_TRaster, *SDF_PRaster;
+
+
+  /**************************************************************************
+   *
+   * @Enum:
+   *   SDF_Edge_Type
+   *
+   * @Description:
+   *   Enumeration of all curve types present in fonts.
+   *
+   * @Fields:
+   *   SDF_EDGE_UNDEFINED ::
+   *     Undefined edge, simply used to initialize and detect errors.
+   *
+   *   SDF_EDGE_LINE ::
+   *     Line segment with start and end point.
+   *
+   *   SDF_EDGE_CONIC ::
+   *     A conic/quadratic Bezier curve with start, end, and one control
+   *     point.
+   *
+   *   SDF_EDGE_CUBIC ::
+   *     A cubic Bezier curve with start, end, and two control points.
+   *
+   */
+  typedef enum  SDF_Edge_Type_
+  {
+    SDF_EDGE_UNDEFINED = 0,
+    SDF_EDGE_LINE      = 1,
+    SDF_EDGE_CONIC     = 2,
+    SDF_EDGE_CUBIC     = 3
+
+  } SDF_Edge_Type;
+
+
+  /**************************************************************************
+   *
+   * @Enum:
+   *   SDF_Contour_Orientation
+   *
+   * @Description:
+   *   Enumeration of all orientation values of a contour.  We determine the
+   *   orientation by calculating the area covered by a contour.  Contrary
+   *   to values returned by @FT_Outline_Get_Orientation,
+   *   `SDF_Contour_Orientation` is independent of the fill rule, which can
+   *   be different for different font formats.
+   *
+   * @Fields:
+   *   SDF_ORIENTATION_NONE ::
+   *     Undefined orientation, used for initialization and error detection.
+   *
+   *   SDF_ORIENTATION_CW ::
+   *     Clockwise orientation (positive area covered).
+   *
+   *   SDF_ORIENTATION_CCW ::
+   *     Counter-clockwise orientation (negative area covered).
+   *
+   * @Note:
+   *   See @FT_Outline_Get_Orientation for more details.
+   *
+   */
+  typedef enum  SDF_Contour_Orientation_
+  {
+    SDF_ORIENTATION_NONE = 0,
+    SDF_ORIENTATION_CW   = 1,
+    SDF_ORIENTATION_CCW  = 2
+
+  } SDF_Contour_Orientation;
+
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   SDF_Edge
+   *
+   * @Description:
+   *   Represent an edge of a contour.
+   *
+   * @Fields:
+   *   start_pos ::
+   *     Start position of an edge.  Valid for all types of edges.
+   *
+   *   end_pos ::
+   *     Etart position of an edge.  Valid for all types of edges.
+   *
+   *   control_a ::
+   *     A control point of the edge.  Valid only for `SDF_EDGE_CONIC`
+   *     and `SDF_EDGE_CUBIC`.
+   *
+   *   control_b ::
+   *     Another control point of the edge.  Valid only for
+   *     `SDF_EDGE_CONIC`.
+   *
+   *   edge_type ::
+   *     Type of the edge, see @SDF_Edge_Type for all possible edge types.
+   *
+   *   next ::
+   *     Used to create a singly linked list, which can be interpreted
+   *     as a contour.
+   *
+   */
+  typedef struct  SDF_Edge_
+  {
+    FT_26D6_Vec  start_pos;
+    FT_26D6_Vec  end_pos;
+    FT_26D6_Vec  control_a;
+    FT_26D6_Vec  control_b;
+
+    SDF_Edge_Type  edge_type;
+
+    struct SDF_Edge_*  next;
+
+  } SDF_Edge;
+
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   SDF_Contour
+   *
+   * @Description:
+   *   Represent a complete contour, which contains a list of edges.
+   *
+   * @Fields:
+   *   last_pos ::
+   *     Contains the value of `end_pos' of the last edge in the list of
+   *     edges.  Useful while decomposing the outline with
+   *     @FT_Outline_Decompose.
+   *
+   *   edges ::
+   *     Linked list of all the edges that make the contour.
+   *
+   *   next ::
+   *     Used to create a singly linked list, which can be interpreted as a
+   *     complete shape or @FT_Outline.
+   *
+   */
+  typedef struct  SDF_Contour_
+  {
+    FT_26D6_Vec  last_pos;
+    SDF_Edge*    edges;
+
+    struct SDF_Contour_*  next;
+
+  } SDF_Contour;
+
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   SDF_Shape
+   *
+   * @Description:
+   *   Represent a complete shape, which is the decomposition of
+   *   @FT_Outline.
+   *
+   * @Fields:
+   *   memory ::
+   *     Used internally to allocate memory.
+   *
+   *   contours ::
+   *     Linked list of all the contours that make the shape.
+   *
+   */
+  typedef struct  SDF_Shape_
+  {
+    FT_Memory     memory;
+    SDF_Contour*  contours;
+
+  } SDF_Shape;
+
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   SDF_Signed_Distance
+   *
+   * @Description:
+   *   Represent signed distance of a point, i.e., the distance of the edge
+   *   nearest to the point.
+   *
+   * @Fields:
+   *   distance ::
+   *     Distance of the point from the nearest edge.  Can be squared or
+   *     absolute depending on the `USE_SQUARED_DISTANCES` macro defined in
+   *     file `ftsdfcommon.h`.
+   *
+   *   cross ::
+   *     Cross product of the shortest distance vector (i.e., the vector
+   *     from the point to the nearest edge) and the direction of the edge
+   *     at the nearest point.  This is used to resolve ambiguities of
+   *     `sign`.
+   *
+   *   sign ::
+   *     A value used to indicate whether the distance vector is outside or
+   *     inside the contour corresponding to the edge.
+   *
+   * @Note:
+   *   `sign` may or may not be correct, therefore it must be checked
+   *   properly in case there is an ambiguity.
+   *
+   */
+  typedef struct SDF_Signed_Distance_
+  {
+    FT_16D16  distance;
+    FT_16D16  cross;
+    FT_Char   sign;
+
+  } SDF_Signed_Distance;
+
+
+  /**************************************************************************
+   *
+   * @Struct:
+   *   SDF_Params
+   *
+   * @Description:
+   *   Yet another internal parameters required by the rasterizer.
+   *
+   * @Fields:
+   *   orientation ::
+   *     This is not the @SDF_Contour_Orientation value but @FT_Orientation,
+   *     which determines whether clockwise-oriented outlines are to be
+   *     filled or counter-clockwise-oriented ones.
+   *
+   *   flip_sign ::
+   *     If set to true, flip the sign.  By default the points filled by the
+   *     outline are positive.
+   *
+   *   flip_y ::
+   *     If set to true the output bitmap is upside-down.  Can be useful
+   *     because OpenGL and DirectX use different coordinate systems for
+   *     textures.
+   *
+   *   overload_sign ::
+   *     In the subdivision and bounding box optimization, the default
+   *     outside sign is taken as -1.  This parameter can be used to modify
+   *     that behaviour.  For example, while generating SDF for a single
+   *     counter-clockwise contour, the outside sign should be 1.
+   *
+   */
+  typedef struct SDF_Params_
+  {
+    FT_Orientation  orientation;
+    FT_Bool         flip_sign;
+    FT_Bool         flip_y;
+
+    FT_Int  overload_sign;
+
+  } SDF_Params;
+
+
+  /**************************************************************************
+   *
+   * constants, initializer, and destructor
+   *
+   */
+
+  static
+  const FT_Vector  zero_vector = { 0, 0 };
+
+  static
+  const SDF_Edge  null_edge = { { 0, 0 }, { 0, 0 },
+                                { 0, 0 }, { 0, 0 },
+                                SDF_EDGE_UNDEFINED, NULL };
+
+  static
+  const SDF_Contour  null_contour = { { 0, 0 }, NULL, NULL };
+
+  static
+  const SDF_Shape  null_shape = { NULL, NULL };
+
+  static
+  const SDF_Signed_Distance  max_sdf = { INT_MAX, 0, 0 };
+
+
+  /* Create a new @SDF_Edge on the heap and assigns the `edge` */
+  /* pointer to the newly allocated memory.                    */
+  static FT_Error
+  sdf_edge_new( FT_Memory   memory,
+                SDF_Edge**  edge )
+  {
+    FT_Error   error = FT_Err_Ok;
+    SDF_Edge*  ptr   = NULL;
+
+
+    if ( !memory || !edge )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) )
+    {
+      *ptr = null_edge;
+      *edge = ptr;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* Free the allocated `edge` variable. */
+  static void
+  sdf_edge_done( FT_Memory   memory,
+                 SDF_Edge**  edge )
+  {
+    if ( !memory || !edge || !*edge )
+      return;
+
+    FT_FREE( *edge );
+  }
+
+
+  /* Create a new @SDF_Contour on the heap and assign     */
+  /* the `contour` pointer to the newly allocated memory. */
+  static FT_Error
+  sdf_contour_new( FT_Memory      memory,
+                   SDF_Contour**  contour )
+  {
+    FT_Error      error = FT_Err_Ok;
+    SDF_Contour*  ptr   = NULL;
+
+
+    if ( !memory || !contour )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) )
+    {
+      *ptr     = null_contour;
+      *contour = ptr;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* Free the allocated `contour` variable. */
+  /* Also free the list of edges.           */
+  static void
+  sdf_contour_done( FT_Memory      memory,
+                    SDF_Contour**  contour )
+  {
+    SDF_Edge*  edges;
+    SDF_Edge*  temp;
+
+
+    if ( !memory || !contour || !*contour )
+      return;
+
+    edges = (*contour)->edges;
+
+    /* release all edges */
+    while ( edges )
+    {
+      temp  = edges;
+      edges = edges->next;
+
+      sdf_edge_done( memory, &temp );
+    }
+
+    FT_FREE( *contour );
+  }
+
+
+  /* Create a new @SDF_Shape on the heap and assign     */
+  /* the `shape` pointer to the newly allocated memory. */
+  static FT_Error
+  sdf_shape_new( FT_Memory    memory,
+                 SDF_Shape**  shape )
+  {
+    FT_Error    error = FT_Err_Ok;
+    SDF_Shape*  ptr   = NULL;
+
+
+    if ( !memory || !shape )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) )
+    {
+      *ptr        = null_shape;
+      ptr->memory = memory;
+      *shape      = ptr;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* Free the allocated `shape` variable. */
+  /* Also free the list of contours.      */
+  static void
+  sdf_shape_done( SDF_Shape**  shape )
+  {
+    FT_Memory     memory;
+    SDF_Contour*  contours;
+    SDF_Contour*  temp;
+
+
+    if ( !shape || !*shape )
+      return;
+
+    memory   = (*shape)->memory;
+    contours = (*shape)->contours;
+
+    if ( !memory )
+      return;
+
+    /* release all contours */
+    while ( contours )
+    {
+      temp     = contours;
+      contours = contours->next;
+
+      sdf_contour_done( memory, &temp );
+    }
+
+    /* release the allocated shape struct  */
+    FT_FREE( *shape );
+  }
+
+
+  /**************************************************************************
+   *
+   * shape decomposition functions
+   *
+   */
+
+  /* This function is called when starting a new contour at `to`, */
+  /* which gets added to the shape's list.                        */
+  static FT_Error
+  sdf_move_to( const FT_26D6_Vec* to,
+               void*              user )
+  {
+    SDF_Shape*    shape   = ( SDF_Shape* )user;
+    SDF_Contour*  contour = NULL;
+
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = shape->memory;
+
+
+    if ( !to || !user )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    FT_CALL( sdf_contour_new( memory, &contour ) );
+
+    contour->last_pos = *to;
+    contour->next     = shape->contours;
+    shape->contours   = contour;
+
+  Exit:
+    return error;
+  }
+
+
+  /* This function is called when there is a line in the      */
+  /* contour.  The line starts at the previous edge point and */
+  /* stops at `to`.                                           */
+  static FT_Error
+  sdf_line_to( const FT_26D6_Vec*  to,
+               void*               user )
+  {
+    SDF_Shape*    shape    = ( SDF_Shape* )user;
+    SDF_Edge*     edge     = NULL;
+    SDF_Contour*  contour  = NULL;
+
+    FT_Error      error    = FT_Err_Ok;
+    FT_Memory     memory   = shape->memory;
+
+
+    if ( !to || !user )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    contour = shape->contours;
+
+    if ( contour->last_pos.x == to->x &&
+         contour->last_pos.y == to->y )
+      goto Exit;
+
+    FT_CALL( sdf_edge_new( memory, &edge ) );
+
+    edge->edge_type = SDF_EDGE_LINE;
+    edge->start_pos = contour->last_pos;
+    edge->end_pos   = *to;
+
+    edge->next        = contour->edges;
+    contour->edges    = edge;
+    contour->last_pos = *to;
+
+  Exit:
+    return error;
+  }
+
+
+  /* This function is called when there is a conic Bezier curve   */
+  /* in the contour.  The curve starts at the previous edge point */
+  /* and stops at `to`, with control point `control_1`.           */
+  static FT_Error
+  sdf_conic_to( const FT_26D6_Vec*  control_1,
+                const FT_26D6_Vec*  to,
+                void*               user )
+  {
+    SDF_Shape*    shape    = ( SDF_Shape* )user;
+    SDF_Edge*     edge     = NULL;
+    SDF_Contour*  contour  = NULL;
+
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = shape->memory;
+
+
+    if ( !control_1 || !to || !user )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    contour = shape->contours;
+
+    FT_CALL( sdf_edge_new( memory, &edge ) );
+
+    edge->edge_type = SDF_EDGE_CONIC;
+    edge->start_pos = contour->last_pos;
+    edge->control_a = *control_1;
+    edge->end_pos   = *to;
+
+    edge->next        = contour->edges;
+    contour->edges    = edge;
+    contour->last_pos = *to;
+
+  Exit:
+    return error;
+  }
+
+
+  /* This function is called when there is a cubic Bezier curve   */
+  /* in the contour.  The curve starts at the previous edge point */
+  /* and stops at `to`, with two control points `control_1` and   */
+  /* `control_2`.                                                 */
+  static FT_Error
+  sdf_cubic_to( const FT_26D6_Vec*  control_1,
+                const FT_26D6_Vec*  control_2,
+                const FT_26D6_Vec*  to,
+                void*               user )
+  {
+    SDF_Shape*    shape    = ( SDF_Shape* )user;
+    SDF_Edge*     edge     = NULL;
+    SDF_Contour*  contour  = NULL;
+
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = shape->memory;
+
+
+    if ( !control_2 || !control_1 || !to || !user )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    contour = shape->contours;
+
+    FT_CALL( sdf_edge_new( memory, &edge ) );
+
+    edge->edge_type = SDF_EDGE_CUBIC;
+    edge->start_pos = contour->last_pos;
+    edge->control_a = *control_1;
+    edge->control_b = *control_2;
+    edge->end_pos   = *to;
+
+    edge->next        = contour->edges;
+    contour->edges    = edge;
+    contour->last_pos = *to;
+
+  Exit:
+    return error;
+  }
+
+
+  /* Construct the structure to hold all four outline */
+  /* decomposition functions.                         */
+  FT_DEFINE_OUTLINE_FUNCS(
+    sdf_decompose_funcs,
+
+    (FT_Outline_MoveTo_Func) sdf_move_to,   /* move_to  */
+    (FT_Outline_LineTo_Func) sdf_line_to,   /* line_to  */
+    (FT_Outline_ConicTo_Func)sdf_conic_to,  /* conic_to */
+    (FT_Outline_CubicTo_Func)sdf_cubic_to,  /* cubic_to */
+
+    0,                                      /* shift    */
+    0                                       /* delta    */
+  )
+
+
+  /* Decompose `outline` and put it into the `shape` structure.  */
+  static FT_Error
+  sdf_outline_decompose( FT_Outline*  outline,
+                         SDF_Shape*   shape )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+
+    if ( !outline || !shape )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    error = FT_Outline_Decompose( outline,
+                                  &sdf_decompose_funcs,
+                                  (void*)shape );
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * utility functions
+   *
+   */
+
+  /* Return the control box of an edge.  The control box is a rectangle */
+  /* in which all the control points can fit tightly.                   */
+  static FT_CBox
+  get_control_box( SDF_Edge  edge )
+  {
+    FT_CBox  cbox   = { 0, 0, 0, 0 };
+    FT_Bool  is_set = 0;
+
+
+    switch ( edge.edge_type )
+    {
+    case SDF_EDGE_CUBIC:
+      cbox.xMin = edge.control_b.x;
+      cbox.xMax = edge.control_b.x;
+      cbox.yMin = edge.control_b.y;
+      cbox.yMax = edge.control_b.y;
+
+      is_set = 1;
+      /* fall through */
+
+    case SDF_EDGE_CONIC:
+      if ( is_set )
+      {
+        cbox.xMin = edge.control_a.x < cbox.xMin
+                    ? edge.control_a.x
+                    : cbox.xMin;
+        cbox.xMax = edge.control_a.x > cbox.xMax
+                    ? edge.control_a.x
+                    : cbox.xMax;
+
+        cbox.yMin = edge.control_a.y < cbox.yMin
+                    ? edge.control_a.y
+                    : cbox.yMin;
+        cbox.yMax = edge.control_a.y > cbox.yMax
+                    ? edge.control_a.y
+                    : cbox.yMax;
+      }
+      else
+      {
+        cbox.xMin = edge.control_a.x;
+        cbox.xMax = edge.control_a.x;
+        cbox.yMin = edge.control_a.y;
+        cbox.yMax = edge.control_a.y;
+
+        is_set = 1;
+      }
+      /* fall through */
+
+    case SDF_EDGE_LINE:
+      if ( is_set )
+      {
+        cbox.xMin = edge.start_pos.x < cbox.xMin
+                    ? edge.start_pos.x
+                    : cbox.xMin;
+        cbox.xMax = edge.start_pos.x > cbox.xMax
+                    ? edge.start_pos.x
+                    : cbox.xMax;
+
+        cbox.yMin = edge.start_pos.y < cbox.yMin
+                    ? edge.start_pos.y
+                    : cbox.yMin;
+        cbox.yMax = edge.start_pos.y > cbox.yMax
+                    ? edge.start_pos.y
+                    : cbox.yMax;
+      }
+      else
+      {
+        cbox.xMin = edge.start_pos.x;
+        cbox.xMax = edge.start_pos.x;
+        cbox.yMin = edge.start_pos.y;
+        cbox.yMax = edge.start_pos.y;
+      }
+
+      cbox.xMin = edge.end_pos.x < cbox.xMin
+                  ? edge.end_pos.x
+                  : cbox.xMin;
+      cbox.xMax = edge.end_pos.x > cbox.xMax
+                  ? edge.end_pos.x
+                  : cbox.xMax;
+
+      cbox.yMin = edge.end_pos.y < cbox.yMin
+                  ? edge.end_pos.y
+                  : cbox.yMin;
+      cbox.yMax = edge.end_pos.y > cbox.yMax
+                  ? edge.end_pos.y
+                  : cbox.yMax;
+
+      break;
+
+    default:
+      break;
+    }
+
+    return cbox;
+  }
+
+
+  /* Return orientation of a single contour.                    */
+  /* Note that the orientation is independent of the fill rule! */
+  /* So, for TTF a clockwise-oriented contour has to be filled  */
+  /* and the opposite for OTF fonts.                            */
+  static SDF_Contour_Orientation
+  get_contour_orientation ( SDF_Contour*  contour )
+  {
+    SDF_Edge*  head = NULL;
+    FT_26D6    area = 0;
+
+
+    /* return none if invalid parameters */
+    if ( !contour || !contour->edges )
+      return SDF_ORIENTATION_NONE;
+
+    head = contour->edges;
+
+    /* Calculate the area of the control box for all edges. */
+    while ( head )
+    {
+      switch ( head->edge_type )
+      {
+      case SDF_EDGE_LINE:
+        area += MUL_26D6( ( head->end_pos.x - head->start_pos.x ),
+                          ( head->end_pos.y + head->start_pos.y ) );
+        break;
+
+      case SDF_EDGE_CONIC:
+        area += MUL_26D6( head->control_a.x - head->start_pos.x,
+                          head->control_a.y + head->start_pos.y );
+        area += MUL_26D6( head->end_pos.x - head->control_a.x,
+                          head->end_pos.y + head->control_a.y );
+        break;
+
+      case SDF_EDGE_CUBIC:
+        area += MUL_26D6( head->control_a.x - head->start_pos.x,
+                          head->control_a.y + head->start_pos.y );
+        area += MUL_26D6( head->control_b.x - head->control_a.x,
+                          head->control_b.y + head->control_a.y );
+        area += MUL_26D6( head->end_pos.x - head->control_b.x,
+                          head->end_pos.y + head->control_b.y );
+        break;
+
+      default:
+        return SDF_ORIENTATION_NONE;
+      }
+
+      head = head->next;
+    }
+
+    /* Clockwise contours cover a positive area, and counter-clockwise */
+    /* contours cover a negative area.                                 */
+    if ( area > 0 )
+      return SDF_ORIENTATION_CW;
+    else
+      return SDF_ORIENTATION_CCW;
+  }
+
+
+  /* This function is exactly the same as the one */
+  /* in the smooth renderer.  It splits a conic   */
+  /* into two conics exactly half way at t = 0.5. */
+  static void
+  split_conic( FT_26D6_Vec*  base )
+  {
+    FT_26D6  a, b;
+
+
+    base[4].x = base[2].x;
+    a         = base[0].x + base[1].x;
+    b         = base[1].x + base[2].x;
+    base[3].x = b / 2;
+    base[2].x = ( a + b ) / 4;
+    base[1].x = a / 2;
+
+    base[4].y = base[2].y;
+    a         = base[0].y + base[1].y;
+    b         = base[1].y + base[2].y;
+    base[3].y = b / 2;
+    base[2].y = ( a + b ) / 4;
+    base[1].y = a / 2;
+  }
+
+
+  /* This function is exactly the same as the one */
+  /* in the smooth renderer.  It splits a cubic   */
+  /* into two cubics exactly half way at t = 0.5. */
+  static void
+  split_cubic( FT_26D6_Vec*  base )
+  {
+    FT_26D6  a, b, c;
+
+
+    base[6].x = base[3].x;
+    a         = base[0].x + base[1].x;
+    b         = base[1].x + base[2].x;
+    c         = base[2].x + base[3].x;
+    base[5].x = c / 2;
+    c        += b;
+    base[4].x = c / 4;
+    base[1].x = a / 2;
+    a        += b;
+    base[2].x = a / 4;
+    base[3].x = ( a + c ) / 8;
+
+    base[6].y = base[3].y;
+    a         = base[0].y + base[1].y;
+    b         = base[1].y + base[2].y;
+    c         = base[2].y + base[3].y;
+    base[5].y = c / 2;
+    c        += b;
+    base[4].y = c / 4;
+    base[1].y = a / 2;
+    a        += b;
+    base[2].y = a / 4;
+    base[3].y = ( a + c ) / 8;
+  }
+
+
+  /* Split a conic Bezier curve into a number of lines */
+  /* and add them to `out'.                            */
+  /*                                                   */
+  /* This function uses recursion; we thus need        */
+  /* parameter `max_splits' for stopping.              */
+  static FT_Error
+  split_sdf_conic( FT_Memory     memory,
+                   FT_26D6_Vec*  control_points,
+                   FT_Int        max_splits,
+                   SDF_Edge**    out )
+  {
+    FT_Error     error = FT_Err_Ok;
+    FT_26D6_Vec  cpos[5];
+    SDF_Edge*    left,*  right;
+
+
+    if ( !memory || !out  )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* split conic outline */
+    cpos[0] = control_points[0];
+    cpos[1] = control_points[1];
+    cpos[2] = control_points[2];
+
+    split_conic( cpos );
+
+    /* If max number of splits is done */
+    /* then stop and add the lines to  */
+    /* the list.                       */
+    if ( max_splits <= 2 )
+      goto Append;
+
+    /* Otherwise keep splitting. */
+    FT_CALL( split_sdf_conic( memory, &cpos[0], max_splits / 2, out ) );
+    FT_CALL( split_sdf_conic( memory, &cpos[2], max_splits / 2, out ) );
+
+    /* [NOTE]: This is not an efficient way of   */
+    /* splitting the curve.  Check the deviation */
+    /* instead and stop if the deviation is less */
+    /* than a pixel.                             */
+
+    goto Exit;
+
+  Append:
+    /* Do allocation and add the lines to the list. */
+
+    FT_CALL( sdf_edge_new( memory, &left ) );
+    FT_CALL( sdf_edge_new( memory, &right ) );
+
+    left->start_pos  = cpos[0];
+    left->end_pos    = cpos[2];
+    left->edge_type  = SDF_EDGE_LINE;
+
+    right->start_pos = cpos[2];
+    right->end_pos   = cpos[4];
+    right->edge_type = SDF_EDGE_LINE;
+
+    left->next  = right;
+    right->next = (*out);
+    *out        = left;
+
+  Exit:
+    return error;
+  }
+
+
+  /* Split a cubic Bezier curve into a number of lines */
+  /* and add them to `out`.                            */
+  /*                                                   */
+  /* This function uses recursion; we thus need        */
+  /* parameter `max_splits' for stopping.              */
+  static FT_Error
+  split_sdf_cubic( FT_Memory     memory,
+                   FT_26D6_Vec*  control_points,
+                   FT_Int        max_splits,
+                   SDF_Edge**    out )
+  {
+    FT_Error     error = FT_Err_Ok;
+    FT_26D6_Vec  cpos[7];
+    SDF_Edge*    left,*  right;
+
+
+    if ( !memory || !out  )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* split the conic */
+    cpos[0] = control_points[0];
+    cpos[1] = control_points[1];
+    cpos[2] = control_points[2];
+    cpos[3] = control_points[3];
+
+    split_cubic( cpos );
+
+    /* If max number of splits is done */
+    /* then stop and add the lines to  */
+    /* the list.                       */
+    if ( max_splits <= 2 )
+      goto Append;
+
+    /* Otherwise keep splitting. */
+    FT_CALL( split_sdf_cubic( memory, &cpos[0], max_splits / 2, out ) );
+    FT_CALL( split_sdf_cubic( memory, &cpos[3], max_splits / 2, out ) );
+
+    /* [NOTE]: This is not an efficient way of   */
+    /* splitting the curve.  Check the deviation */
+    /* instead and stop if the deviation is less */
+    /* than a pixel.                             */
+
+    goto Exit;
+
+  Append:
+    /* Do allocation and add the lines to the list. */
+
+    FT_CALL( sdf_edge_new( memory, &left) );
+    FT_CALL( sdf_edge_new( memory, &right) );
+
+    left->start_pos  = cpos[0];
+    left->end_pos    = cpos[3];
+    left->edge_type  = SDF_EDGE_LINE;
+
+    right->start_pos = cpos[3];
+    right->end_pos   = cpos[6];
+    right->edge_type = SDF_EDGE_LINE;
+
+    left->next  = right;
+    right->next = (*out);
+    *out        = left;
+
+  Exit:
+    return error;
+  }
+
+
+  /* Subdivide an entire shape into line segments */
+  /* such that it doesn't look visually different */
+  /* from the original curve.                     */
+  static FT_Error
+  split_sdf_shape( SDF_Shape*  shape )
+  {
+    FT_Error   error = FT_Err_Ok;
+    FT_Memory  memory;
+
+    SDF_Contour*  contours;
+    SDF_Contour*  new_contours = NULL;
+
+
+    if ( !shape || !shape->memory )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    contours = shape->contours;
+    memory   = shape->memory;
+
+    /* for each contour */
+    while ( contours )
+    {
+      SDF_Edge*  edges     = contours->edges;
+      SDF_Edge*  new_edges = NULL;
+
+      SDF_Contour*  tempc;
+
+
+      /* for each edge */
+      while ( edges )
+      {
+        SDF_Edge*  edge = edges;
+        SDF_Edge*  temp;
+
+        switch ( edge->edge_type )
+        {
+        case SDF_EDGE_LINE:
+          /* Just create a duplicate edge in case     */
+          /* it is a line.  We can use the same edge. */
+          FT_CALL( sdf_edge_new( memory, &temp ) );
+
+          ft_memcpy( temp, edge, sizeof ( *edge ) );
+
+          temp->next = new_edges;
+          new_edges  = temp;
+          break;
+
+        case SDF_EDGE_CONIC:
+          /* Subdivide the curve and add it to the list. */
+          {
+            FT_26D6_Vec  ctrls[3];
+
+
+            ctrls[0] = edge->start_pos;
+            ctrls[1] = edge->control_a;
+            ctrls[2] = edge->end_pos;
+
+            error = split_sdf_conic( memory, ctrls, 32, &new_edges );
+          }
+          break;
+
+        case SDF_EDGE_CUBIC:
+          /* Subdivide the curve and add it to the list. */
+          {
+            FT_26D6_Vec  ctrls[4];
+
+
+            ctrls[0] = edge->start_pos;
+            ctrls[1] = edge->control_a;
+            ctrls[2] = edge->control_b;
+            ctrls[3] = edge->end_pos;
+
+            error = split_sdf_cubic( memory, ctrls, 32, &new_edges );
+          }
+          break;
+
+        default:
+          error = FT_THROW( Invalid_Argument );
+          goto Exit;
+        }
+
+        edges = edges->next;
+      }
+
+      /* add to the contours list */
+      FT_CALL( sdf_contour_new( memory, &tempc ) );
+
+      tempc->next  = new_contours;
+      tempc->edges = new_edges;
+      new_contours = tempc;
+      new_edges    = NULL;
+
+      /* deallocate the contour */
+      tempc    = contours;
+      contours = contours->next;
+
+      sdf_contour_done( memory, &tempc );
+    }
+
+    shape->contours = new_contours;
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * for debugging
+   *
+   */
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+  static void
+  sdf_shape_dump( SDF_Shape*  shape )
+  {
+    FT_UInt  num_contours = 0;
+
+    FT_UInt  total_edges = 0;
+    FT_UInt  total_lines = 0;
+    FT_UInt  total_conic = 0;
+    FT_UInt  total_cubic = 0;
+
+    SDF_Contour*  contour_list;
+
+
+    if ( !shape )
+    {
+      FT_TRACE5(( "sdf_shape_dump: null shape\n" ));
+      return;
+    }
+
+    contour_list = shape->contours;
+
+    FT_TRACE5(( "sdf_shape_dump (values are in 26.6 format):\n" ));
+
+    while ( contour_list )
+    {
+      FT_UInt       num_edges = 0;
+      SDF_Edge*     edge_list;
+      SDF_Contour*  contour = contour_list;
+
+
+      FT_TRACE5(( "  Contour %d\n", num_contours ));
+
+      edge_list = contour->edges;
+
+      while ( edge_list )
+      {
+        SDF_Edge*  edge = edge_list;
+
+
+        FT_TRACE5(( "  %3d: ", num_edges ));
+
+        switch ( edge->edge_type )
+        {
+        case SDF_EDGE_LINE:
+          FT_TRACE5(( "Line:  (%ld, %ld) -- (%ld, %ld)\n",
+                      edge->start_pos.x, edge->start_pos.y,
+                      edge->end_pos.x, edge->end_pos.y ));
+          total_lines++;
+          break;
+
+        case SDF_EDGE_CONIC:
+          FT_TRACE5(( "Conic: (%ld, %ld) .. (%ld, %ld) .. (%ld, %ld)\n",
+                      edge->start_pos.x, edge->start_pos.y,
+                      edge->control_a.x, edge->control_a.y,
+                      edge->end_pos.x, edge->end_pos.y ));
+          total_conic++;
+          break;
+
+        case SDF_EDGE_CUBIC:
+          FT_TRACE5(( "Cubic: (%ld, %ld) .. (%ld, %ld)"
+                      " .. (%ld, %ld) .. (%ld %ld)\n",
+                      edge->start_pos.x, edge->start_pos.y,
+                      edge->control_a.x, edge->control_a.y,
+                      edge->control_b.x, edge->control_b.y,
+                      edge->end_pos.x, edge->end_pos.y ));
+          total_cubic++;
+          break;
+
+        default:
+          break;
+        }
+
+        num_edges++;
+        total_edges++;
+        edge_list = edge_list->next;
+      }
+
+      num_contours++;
+      contour_list = contour_list->next;
+    }
+
+    FT_TRACE5(( "\n" ));
+    FT_TRACE5(( "  total number of contours = %d\n", num_contours ));
+    FT_TRACE5(( "  total number of edges    = %d\n", total_edges ));
+    FT_TRACE5(( "    |__lines = %d\n", total_lines ));
+    FT_TRACE5(( "    |__conic = %d\n", total_conic ));
+    FT_TRACE5(( "    |__cubic = %d\n", total_cubic ));
+  }
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+
+  /**************************************************************************
+   *
+   * math functions
+   *
+   */
+
+#if !USE_NEWTON_FOR_CONIC
+
+  /* [NOTE]: All the functions below down until rasterizer */
+  /*         can be avoided if we decide to subdivide the  */
+  /*         curve into lines.                             */
+
+  /* This function uses Newton's iteration to find */
+  /* the cube root of a fixed-point integer.       */
+  static FT_16D16
+  cube_root( FT_16D16  val )
+  {
+    /* [IMPORTANT]: This function is not good as it may */
+    /* not break, so use a lookup table instead.  Or we */
+    /* can use an algorithm similar to `square_root`.   */
+
+    FT_Int  v, g, c;
+
+
+    if ( val == 0                  ||
+         val == -FT_INT_16D16( 1 ) ||
+         val ==  FT_INT_16D16( 1 ) )
+      return val;
+
+    v = val < 0 ? -val : val;
+    g = square_root( v );
+    c = 0;
+
+    while ( 1 )
+    {
+      c = FT_MulFix( FT_MulFix( g, g ), g ) - v;
+      c = FT_DivFix( c, 3 * FT_MulFix( g, g ) );
+
+      g -= c;
+
+      if ( ( c < 0 ? -c : c ) < 30 )
+        break;
+    }
+
+    return val < 0 ? -g : g;
+  }
+
+
+  /* Calculate the perpendicular by using '1 - base^2'. */
+  /* Then use arctan to compute the angle.              */
+  static FT_16D16
+  arc_cos( FT_16D16  val )
+  {
+    FT_16D16  p;
+    FT_16D16  b   = val;
+    FT_16D16  one = FT_INT_16D16( 1 );
+
+
+    if ( b > one )
+      b = one;
+    if ( b < -one )
+      b = -one;
+
+    p = one - FT_MulFix( b, b );
+    p = square_root( p );
+
+    return FT_Atan2( b, p );
+  }
+
+
+  /* Compute roots of a quadratic polynomial, assign them to `out`, */
+  /* and return number of real roots.                               */
+  /*                                                                */
+  /* The procedure can be found at                                  */
+  /*                                                                */
+  /*   https://mathworld.wolfram.com/QuadraticFormula.html          */
+  static FT_UShort
+  solve_quadratic_equation( FT_26D6   a,
+                            FT_26D6   b,
+                            FT_26D6   c,
+                            FT_16D16  out[2] )
+  {
+    FT_16D16  discriminant = 0;
+
+
+    a = FT_26D6_16D16( a );
+    b = FT_26D6_16D16( b );
+    c = FT_26D6_16D16( c );
+
+    if ( a == 0 )
+    {
+      if ( b == 0 )
+        return 0;
+      else
+      {
+        out[0] = FT_DivFix( -c, b );
+
+        return 1;
+      }
+    }
+
+    discriminant = FT_MulFix( b, b ) - 4 * FT_MulFix( a, c );
+
+    if ( discriminant < 0 )
+      return 0;
+    else if ( discriminant == 0 )
+    {
+      out[0] = FT_DivFix( -b, 2 * a );
+
+      return 1;
+    }
+    else
+    {
+      discriminant = square_root( discriminant );
+
+      out[0] = FT_DivFix( -b + discriminant, 2 * a );
+      out[1] = FT_DivFix( -b - discriminant, 2 * a );
+
+      return 2;
+    }
+  }
+
+
+  /* Compute roots of a cubic polynomial, assign them to `out`, */
+  /* and return number of real roots.                           */
+  /*                                                            */
+  /* The procedure can be found at                              */
+  /*                                                            */
+  /*   https://mathworld.wolfram.com/CubicFormula.html          */
+  static FT_UShort
+  solve_cubic_equation( FT_26D6   a,
+                        FT_26D6   b,
+                        FT_26D6   c,
+                        FT_26D6   d,
+                        FT_16D16  out[3] )
+  {
+    FT_16D16  q = 0;      /* intermediate */
+    FT_16D16  r = 0;      /* intermediate */
+
+    FT_16D16  a2 = b;     /* x^2 coefficients */
+    FT_16D16  a1 = c;     /* x coefficients   */
+    FT_16D16  a0 = d;     /* constant         */
+
+    FT_16D16  q3   = 0;
+    FT_16D16  r2   = 0;
+    FT_16D16  a23  = 0;
+    FT_16D16  a22  = 0;
+    FT_16D16  a1x2 = 0;
+
+
+    /* cutoff value for `a` to be a cubic, otherwise solve quadratic */
+    if ( a == 0 || FT_ABS( a ) < 16 )
+      return solve_quadratic_equation( b, c, d, out );
+
+    if ( d == 0 )
+    {
+      out[0] = 0;
+
+      return solve_quadratic_equation( a, b, c, out + 1 ) + 1;
+    }
+
+    /* normalize the coefficients; this also makes them 16.16 */
+    a2 = FT_DivFix( a2, a );
+    a1 = FT_DivFix( a1, a );
+    a0 = FT_DivFix( a0, a );
+
+    /* compute intermediates */
+    a1x2 = FT_MulFix( a1, a2 );
+    a22  = FT_MulFix( a2, a2 );
+    a23  = FT_MulFix( a22, a2 );
+
+    q = ( 3 * a1 - a22 ) / 9;
+    r = ( 9 * a1x2 - 27 * a0 - 2 * a23 ) / 54;
+
+    /* [BUG]: `q3` and `r2` still cause underflow. */
+
+    q3 = FT_MulFix( q, q );
+    q3 = FT_MulFix( q3, q );
+
+    r2 = FT_MulFix( r, r );
+
+    if ( q3 < 0 && r2 < -q3 )
+    {
+      FT_16D16  t = 0;
+
+
+      q3 = square_root( -q3 );
+      t  = FT_DivFix( r, q3 );
+
+      if ( t > ( 1 << 16 ) )
+        t =  ( 1 << 16 );
+      if ( t < -( 1 << 16 ) )
+        t = -( 1 << 16 );
+
+      t   = arc_cos( t );
+      a2 /= 3;
+      q   = 2 * square_root( -q );
+
+      out[0] = FT_MulFix( q, FT_Cos( t / 3 ) ) - a2;
+      out[1] = FT_MulFix( q, FT_Cos( ( t + FT_ANGLE_PI * 2 ) / 3 ) ) - a2;
+      out[2] = FT_MulFix( q, FT_Cos( ( t + FT_ANGLE_PI * 4 ) / 3 ) ) - a2;
+
+      return 3;
+    }
+
+    else if ( r2 == -q3 )
+    {
+      FT_16D16  s = 0;
+
+
+      s   = cube_root( r );
+      a2 /= -3;
+
+      out[0] = a2 + ( 2 * s );
+      out[1] = a2 - s;
+
+      return 2;
+    }
+
+    else
+    {
+      FT_16D16  s    = 0;
+      FT_16D16  t    = 0;
+      FT_16D16  dis  = 0;
+
+
+      if ( q3 == 0 )
+        dis = FT_ABS( r );
+      else
+        dis = square_root( q3 + r2 );
+
+      s = cube_root( r + dis );
+      t = cube_root( r - dis );
+      a2 /= -3;
+      out[0] = ( a2 + ( s + t ) );
+
+      return 1;
+    }
+  }
+
+#endif /* !USE_NEWTON_FOR_CONIC */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  RASTERIZER                                                         **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   resolve_corner
+   *
+   * @Description:
+   *   At some places on the grid two edges can give opposite directions;
+   *   this happens when the closest point is on one of the endpoint.  In
+   *   that case we need to check the proper sign.
+   *
+   *   This can be visualized by an example:
+   *
+   *   ```
+   *                x
+   *
+   *                   o
+   *                  ^ \
+   *                 /   \
+   *                /     \
+   *           (a) /       \  (b)
+   *              /         \
+   *             /           \
+   *            /             v
+   *   ```
+   *
+   *   Suppose `x` is the point whose shortest distance from an arbitrary
+   *   contour we want to find out.  It is clear that `o` is the nearest
+   *   point on the contour.  Now to determine the sign we do a cross
+   *   product of the shortest distance vector and the edge direction, i.e.,
+   *
+   *   ```
+   *   => sign = cross(x - o, direction(a))
+   *   ```
+   *
+   *   Using the right hand thumb rule we can see that the sign will be
+   *   positive.
+   *
+   *   If we use `b', however, we have
+   *
+   *   ```
+   *   => sign = cross(x - o, direction(b))
+   *   ```
+   *
+   *   In this case the sign will be negative.  To determine the correct
+   *   sign we thus divide the plane in two halves and check which plane the
+   *   point lies in.
+   *
+   *   ```
+   *                   |
+   *                x  |
+   *                   |
+   *                   o
+   *                  ^|\
+   *                 / | \
+   *                /  |  \
+   *           (a) /   |   \  (b)
+   *              /    |    \
+   *             /           \
+   *            /             v
+   *   ```
+   *
+   *   We can see that `x` lies in the plane of `a`, so we take the sign
+   *   determined by `a`.  This test can be easily done by calculating the
+   *   orthogonality and taking the greater one.
+   *
+   *   The orthogonality is simply the sinus of the two vectors (i.e.,
+   *   x - o) and the corresponding direction.  We efficiently pre-compute
+   *   the orthogonality with the corresponding `get_min_distance_*`
+   *   functions.
+   *
+   * @Input:
+   *   sdf1 ::
+   *     First signed distance (can be any of `a` or `b`).
+   *
+   *   sdf1 ::
+   *     Second signed distance (can be any of `a` or `b`).
+   *
+   * @Return:
+   *   The correct signed distance, which is computed by using the above
+   *   algorithm.
+   *
+   * @Note:
+   *   The function does not care about the actual distance, it simply
+   *   returns the signed distance which has a larger cross product.  As a
+   *   consequence, this function should not be used if the two distances
+   *   are fairly apart.  In that case simply use the signed distance with
+   *   a shorter absolute distance.
+   *
+   */
+  static SDF_Signed_Distance
+  resolve_corner( SDF_Signed_Distance  sdf1,
+                  SDF_Signed_Distance  sdf2 )
+  {
+    return FT_ABS( sdf1.cross ) > FT_ABS( sdf2.cross ) ? sdf1 : sdf2;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   get_min_distance_line
+   *
+   * @Description:
+   *   Find the shortest distance from the `line` segment to a given `point`
+   *   and assign it to `out`.  Use it for line segments only.
+   *
+   * @Input:
+   *   line ::
+   *     The line segment to which the shortest distance is to be computed.
+   *
+   *   point ::
+   *     Point from which the shortest distance is to be computed.
+   *
+   * @Output:
+   *   out ::
+   *     Signed distance from `point` to `line`.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   * @Note:
+   *   The `line' parameter must have an edge type of `SDF_EDGE_LINE`.
+   *
+   */
+  static FT_Error
+  get_min_distance_line( SDF_Edge*             line,
+                         FT_26D6_Vec           point,
+                         SDF_Signed_Distance*  out )
+  {
+    /*
+     * In order to calculate the shortest distance from a point to
+     * a line segment, we do the following.  Let's assume that
+     *
+     * ```
+     * a = start point of the line segment
+     * b = end point of the line segment
+     * p = point from which shortest distance is to be calculated
+     * ```
+     *
+     * (1) Write the parametric equation of the line.
+     *
+     *     ```
+     *     point_on_line = a + (b - a) * t   (t is the factor)
+     *     ```
+     *
+     * (2) Find the projection of point `p` on the line.  The projection
+     *     will be perpendicular to the line, which allows us to get the
+     *     solution by making the dot product zero.
+     *
+     *     ```
+     *     (point_on_line - a) . (p - point_on_line) = 0
+     *
+     *                (point_on_line)
+     *      (a) x-------o----------------x (b)
+     *                |_|
+     *                  |
+     *                  |
+     *                 (p)
+     *     ```
+     *
+     * (3) Simplification of the above equation yields the factor of
+     *     `point_on_line`:
+     *
+     *     ```
+     *     t = ((p - a) . (b - a)) / |b - a|^2
+     *     ```
+     *
+     * (4) We clamp factor `t` between [0.0f, 1.0f] because `point_on_line`
+     *     can be outside of the line segment:
+     *
+     *     ```
+     *                                          (point_on_line)
+     *     (a) x------------------------x (b) -----o---
+     *                                           |_|
+     *                                             |
+     *                                             |
+     *                                            (p)
+     *     ```
+     *
+     * (5) Finally, the distance we are interested in is
+     *
+     *     ```
+     *     |point_on_line - p|
+     *     ```
+     */
+
+    FT_Error  error = FT_Err_Ok;
+
+    FT_Vector  a;                   /* start position */
+    FT_Vector  b;                   /* end position   */
+    FT_Vector  p;                   /* current point  */
+
+    FT_26D6_Vec  line_segment;      /* `b` - `a` */
+    FT_26D6_Vec  p_sub_a;           /* `p` - `a` */
+
+    FT_26D6   sq_line_length;       /* squared length of `line_segment` */
+    FT_16D16  factor;               /* factor of the nearest point      */
+    FT_26D6   cross;                /* used to determine sign           */
+
+    FT_16D16_Vec  nearest_point;    /* `point_on_line`       */
+    FT_16D16_Vec  nearest_vector;   /* `p` - `nearest_point` */
+
+
+    if ( !line || !out )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( line->edge_type != SDF_EDGE_LINE )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    a = line->start_pos;
+    b = line->end_pos;
+    p = point;
+
+    line_segment.x = b.x - a.x;
+    line_segment.y = b.y - a.y;
+
+    p_sub_a.x = p.x - a.x;
+    p_sub_a.y = p.y - a.y;
+
+    sq_line_length = ( line_segment.x * line_segment.x ) / 64 +
+                     ( line_segment.y * line_segment.y ) / 64;
+
+    /* currently factor is 26.6 */
+    factor = ( p_sub_a.x * line_segment.x ) / 64 +
+             ( p_sub_a.y * line_segment.y ) / 64;
+
+    /* now factor is 16.16 */
+    factor = FT_DivFix( factor, sq_line_length );
+
+    /* clamp the factor between 0.0 and 1.0 in fixed point */
+    if ( factor > FT_INT_16D16( 1 ) )
+      factor = FT_INT_16D16( 1 );
+    if ( factor < 0 )
+      factor = 0;
+
+    nearest_point.x = FT_MulFix( FT_26D6_16D16( line_segment.x ),
+                                 factor );
+    nearest_point.y = FT_MulFix( FT_26D6_16D16( line_segment.y ),
+                                 factor );
+
+    nearest_point.x = FT_26D6_16D16( a.x ) + nearest_point.x;
+    nearest_point.y = FT_26D6_16D16( a.y ) + nearest_point.y;
+
+    nearest_vector.x = nearest_point.x - FT_26D6_16D16( p.x );
+    nearest_vector.y = nearest_point.y - FT_26D6_16D16( p.y );
+
+    cross = FT_MulFix( nearest_vector.x, line_segment.y ) -
+            FT_MulFix( nearest_vector.y, line_segment.x );
+
+    /* assign the output */
+    out->sign     = cross < 0 ? 1 : -1;
+    out->distance = VECTOR_LENGTH_16D16( nearest_vector );
+
+    /* Instead of finding `cross` for checking corner we */
+    /* directly set it here.  This is more efficient     */
+    /* because if the distance is perpendicular we can   */
+    /* directly set it to 1.                             */
+    if ( factor != 0 && factor != FT_INT_16D16( 1 ) )
+      out->cross = FT_INT_16D16( 1 );
+    else
+    {
+      /* [OPTIMIZATION]: Pre-compute this direction. */
+      /* If not perpendicular then compute `cross`.  */
+      FT_Vector_NormLen( &line_segment );
+      FT_Vector_NormLen( &nearest_vector );
+
+      out->cross = FT_MulFix( line_segment.x, nearest_vector.y ) -
+                   FT_MulFix( line_segment.y, nearest_vector.x );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   get_min_distance_conic
+   *
+   * @Description:
+   *   Find the shortest distance from the `conic` Bezier curve to a given
+   *   `point` and assign it to `out`.  Use it for conic/quadratic curves
+   *   only.
+   *
+   * @Input:
+   *   conic ::
+   *     The conic Bezier curve to which the shortest distance is to be
+   *     computed.
+   *
+   *   point ::
+   *     Point from which the shortest distance is to be computed.
+   *
+   * @Output:
+   *   out ::
+   *     Signed distance from `point` to `conic`.
+   *
+   * @Return:
+   *     FreeType error, 0 means success.
+   *
+   * @Note:
+   *   The `conic` parameter must have an edge type of `SDF_EDGE_CONIC`.
+   *
+   */
+
+#if !USE_NEWTON_FOR_CONIC
+
+  /*
+   * The function uses an analytical method to find the shortest distance
+   * which is faster than the Newton-Raphson method, but has underflows at
+   * the moment.  Use Newton's method if you can see artifacts in the SDF.
+   */
+  static FT_Error
+  get_min_distance_conic( SDF_Edge*             conic,
+                          FT_26D6_Vec           point,
+                          SDF_Signed_Distance*  out )
+  {
+    /*
+     * The procedure to find the shortest distance from a point to a
+     * quadratic Bezier curve is similar to the line segment algorithm.  The
+     * shortest distance is perpendicular to the Bezier curve; the only
+     * difference from line is that there can be more than one
+     * perpendicular, and we also have to check the endpoints, because the
+     * perpendicular may not be the shortest.
+     *
+     * Let's assume that
+     * ```
+     * p0 = first endpoint
+     * p1 = control point
+     * p2 = second endpoint
+     * p  = point from which shortest distance is to be calculated
+     * ```
+     *
+     * (1) The equation of a quadratic Bezier curve can be written as
+     *
+     *     ```
+     *     B(t) = (1 - t)^2 * p0 + 2(1 - t)t * p1 + t^2 * p2
+     *     ```
+     *
+     *     with `t` a factor in the range [0.0f, 1.0f].  This equation can
+     *     be rewritten as
+     *
+     *     ```
+     *     B(t) = t^2 * (p0 - 2p1 + p2) + 2t * (p1 - p0) + p0
+     *     ```
+     *
+     *     With
+     *
+     *     ```
+     *     A = p0 - 2p1 + p2
+     *     B = p1 - p0
+     *     ```
+     *
+     *     we have
+     *
+     *     ```
+     *     B(t) = t^2 * A + 2t * B + p0
+     *     ```
+     *
+     * (2) The derivative of the last equation above is
+     *
+     *     ```
+     *     B'(t) = 2 *(tA + B)
+     *     ```
+     *
+     * (3) To find the shortest distance from `p` to `B(t)` we find the
+     *     point on the curve at which the shortest distance vector (i.e.,
+     *     `B(t) - p`) and the direction (i.e., `B'(t)`) make 90 degrees.
+     *     In other words, we make the dot product zero.
+     *
+     *     ```
+     *     (B(t) - p) . (B'(t)) = 0
+     *     (t^2 * A + 2t * B + p0 - p) . (2 * (tA + B)) = 0
+     *     ```
+     *
+     *     After simplifying we get a cubic equation
+     *
+     *     ```
+     *     at^3 + bt^2 + ct + d = 0
+     *     ```
+     *
+     *     with
+     *
+     *     ```
+     *     a = A.A
+     *     b = 3A.B
+     *     c = 2B.B + A.p0 - A.p
+     *     d = p0.B - p.B
+     *     ```
+     *
+     * (4) Now the roots of the equation can be computed using 'Cardano's
+     *     Cubic formula'; we clamp the roots in the range [0.0f, 1.0f].
+     *
+     * [note]: `B` and `B(t)` are different in the above equations.
+     */
+
+    FT_Error  error = FT_Err_Ok;
+
+    FT_26D6_Vec  aA, bB;         /* A, B in the above comment             */
+    FT_26D6_Vec  nearest_point;  /* point on curve nearest to `point`     */
+    FT_26D6_Vec  direction;      /* direction of curve at `nearest_point` */
+
+    FT_26D6_Vec  p0, p1, p2;     /* control points of a conic curve       */
+    FT_26D6_Vec  p;              /* `point` to which shortest distance    */
+
+    FT_26D6  a, b, c, d;         /* cubic coefficients                    */
+
+    FT_16D16  roots[3] = { 0, 0, 0 };    /* real roots of the cubic eq.   */
+    FT_16D16  min_factor;                /* factor at `nearest_point`     */
+    FT_16D16  cross;                     /* to determine the sign         */
+    FT_16D16  min      = FT_INT_MAX;     /* shortest squared distance     */
+
+    FT_UShort  num_roots;                /* number of real roots of cubic */
+    FT_UShort  i;
+
+
+    if ( !conic || !out )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( conic->edge_type != SDF_EDGE_CONIC )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    p0 = conic->start_pos;
+    p1 = conic->control_a;
+    p2 = conic->end_pos;
+    p  = point;
+
+    /* compute substitution coefficients */
+    aA.x = p0.x - 2 * p1.x + p2.x;
+    aA.y = p0.y - 2 * p1.y + p2.y;
+
+    bB.x = p1.x - p0.x;
+    bB.y = p1.y - p0.y;
+
+    /* compute cubic coefficients */
+    a = VEC_26D6_DOT( aA, aA );
+
+    b = 3 * VEC_26D6_DOT( aA, bB );
+
+    c = 2 * VEC_26D6_DOT( bB, bB ) +
+            VEC_26D6_DOT( aA, p0 ) -
+            VEC_26D6_DOT( aA, p );
+
+    d = VEC_26D6_DOT( p0, bB ) -
+        VEC_26D6_DOT( p, bB );
+
+    /* find the roots */
+    num_roots = solve_cubic_equation( a, b, c, d, roots );
+
+    if ( num_roots == 0 )
+    {
+      roots[0]  = 0;
+      roots[1]  = FT_INT_16D16( 1 );
+      num_roots = 2;
+    }
+
+    /* [OPTIMIZATION]: Check the roots, clamp them and discard */
+    /*                 duplicate roots.                        */
+
+    /* convert these values to 16.16 for further computation */
+    aA.x = FT_26D6_16D16( aA.x );
+    aA.y = FT_26D6_16D16( aA.y );
+
+    bB.x = FT_26D6_16D16( bB.x );
+    bB.y = FT_26D6_16D16( bB.y );
+
+    p0.x = FT_26D6_16D16( p0.x );
+    p0.y = FT_26D6_16D16( p0.y );
+
+    p.x = FT_26D6_16D16( p.x );
+    p.y = FT_26D6_16D16( p.y );
+
+    for ( i = 0; i < num_roots; i++ )
+    {
+      FT_16D16  t    = roots[i];
+      FT_16D16  t2   = 0;
+      FT_16D16  dist = 0;
+
+      FT_16D16_Vec  curve_point;
+      FT_16D16_Vec  dist_vector;
+
+      /*
+       * Ideally we should discard the roots which are outside the range
+       * [0.0, 1.0] and check the endpoints of the Bezier curve, but Behdad
+       * Esfahbod proved the following lemma.
+       *
+       * Lemma:
+       *
+       * (1) If the closest point on the curve [0, 1] is to the endpoint at
+       *     `t` = 1 and the cubic has no real roots at `t` = 1 then the
+       *     cubic must have a real root at some `t` > 1.
+       *
+       * (2) Similarly, if the closest point on the curve [0, 1] is to the
+       *     endpoint at `t` = 0 and the cubic has no real roots at `t` = 0
+       *     then the cubic must have a real root at some `t` < 0.
+       *
+       * Now because of this lemma we only need to clamp the roots and that
+       * will take care of the endpoints.
+       *
+       * For more details see
+       *
+       *   https://lists.nongnu.org/archive/html/freetype-devel/2020-06/msg00147.html
+       */
+
+      if ( t < 0 )
+        t = 0;
+      if ( t > FT_INT_16D16( 1 ) )
+        t = FT_INT_16D16( 1 );
+
+      t2 = FT_MulFix( t, t );
+
+      /* B(t) = t^2 * A + 2t * B + p0 - p */
+      curve_point.x = FT_MulFix( aA.x, t2 ) +
+                      2 * FT_MulFix( bB.x, t ) + p0.x;
+      curve_point.y = FT_MulFix( aA.y, t2 ) +
+                      2 * FT_MulFix( bB.y, t ) + p0.y;
+
+      /* `curve_point` - `p` */
+      dist_vector.x = curve_point.x - p.x;
+      dist_vector.y = curve_point.y - p.y;
+
+      dist = VECTOR_LENGTH_16D16( dist_vector );
+
+      if ( dist < min )
+      {
+        min           = dist;
+        nearest_point = curve_point;
+        min_factor    = t;
+      }
+    }
+
+    /* B'(t) = 2 * (tA + B) */
+    direction.x = 2 * FT_MulFix( aA.x, min_factor ) + 2 * bB.x;
+    direction.y = 2 * FT_MulFix( aA.y, min_factor ) + 2 * bB.y;
+
+    /* determine the sign */
+    cross = FT_MulFix( nearest_point.x - p.x, direction.y ) -
+            FT_MulFix( nearest_point.y - p.y, direction.x );
+
+    /* assign the values */
+    out->distance = min;
+    out->sign     = cross < 0 ? 1 : -1;
+
+    if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) )
+      out->cross = FT_INT_16D16( 1 );   /* the two are perpendicular */
+    else
+    {
+      /* convert to nearest vector */
+      nearest_point.x -= FT_26D6_16D16( p.x );
+      nearest_point.y -= FT_26D6_16D16( p.y );
+
+      /* compute `cross` if not perpendicular */
+      FT_Vector_NormLen( &direction );
+      FT_Vector_NormLen( &nearest_point );
+
+      out->cross = FT_MulFix( direction.x, nearest_point.y ) -
+                   FT_MulFix( direction.y, nearest_point.x );
+    }
+
+  Exit:
+    return error;
+  }
+
+#else /* USE_NEWTON_FOR_CONIC */
+
+  /*
+   * The function uses Newton's approximation to find the shortest distance,
+   * which is a bit slower than the analytical method but doesn't cause
+   * underflow.
+   */
+  static FT_Error
+  get_min_distance_conic( SDF_Edge*             conic,
+                          FT_26D6_Vec           point,
+                          SDF_Signed_Distance*  out )
+  {
+    /*
+     * This method uses Newton-Raphson's approximation to find the shortest
+     * distance from a point to a conic curve.  It does not involve solving
+     * any cubic equation, that is why there is no risk of underflow.
+     *
+     * Let's assume that
+     *
+     * ```
+     * p0 = first endpoint
+     * p1 = control point
+     * p3 = second endpoint
+     * p  = point from which shortest distance is to be calculated
+     * ```
+     *
+     * (1) The equation of a quadratic Bezier curve can be written as
+     *
+     *     ```
+     *     B(t) = (1 - t)^2 * p0 + 2(1 - t)t * p1 + t^2 * p2
+     *     ```
+     *
+     *     with `t` the factor in the range [0.0f, 1.0f].  The above
+     *     equation can be rewritten as
+     *
+     *     ```
+     *     B(t) = t^2 * (p0 - 2p1 + p2) + 2t * (p1 - p0) + p0
+     *     ```
+     *
+     *     With
+     *
+     *     ```
+     *     A = p0 - 2p1 + p2
+     *     B = 2 * (p1 - p0)
+     *     ```
+     *
+     *     we have
+     *
+     *     ```
+     *     B(t) = t^2 * A + t * B + p0
+     *     ```
+     *
+     * (2) The derivative of the above equation is
+     *
+     *     ```
+     *     B'(t) = 2t * A + B
+     *     ```
+     *
+     * (3) The second derivative of the above equation is
+     *
+     *     ```
+     *     B''(t) = 2A
+     *     ```
+     *
+     * (4) The equation `P(t)` of the distance from point `p` to the curve
+     *     can be written as
+     *
+     *     ```
+     *     P(t) = t^2 * A + t^2 * B + p0 - p
+     *     ```
+     *
+     *     With
+     *
+     *     ```
+     *     C = p0 - p
+     *     ```
+     *
+     *     we have
+     *
+     *     ```
+     *     P(t) = t^2 * A + t * B + C
+     *     ```
+     *
+     * (5) Finally, the equation of the angle between `B(t)` and `P(t)` can
+     *     be written as
+     *
+     *     ```
+     *     Q(t) = P(t) . B'(t)
+     *     ```
+     *
+     * (6) Our task is to find a value of `t` such that the above equation
+     *     `Q(t)` becomes zero, this is, the point-to-curve vector makes
+     *     90~degrees with the curve.  We solve this with the Newton-Raphson
+     *     method.
+     *
+     * (7) We first assume an arbitary value of factor `t`, which we then
+     *     improve.
+     *
+     *     ```
+     *     t := Q(t) / Q'(t)
+     *     ```
+     *
+     *     Putting the value of `Q(t)` from the above equation gives
+     *
+     *     ```
+     *     t := P(t) . B'(t) / derivative(P(t) . B'(t))
+     *     t := P(t) . B'(t) /
+     *            (P'(t) . B'(t) + P(t) . B''(t))
+     *     ```
+     *
+     *     Note that `P'(t)` is the same as `B'(t)` because the constant is
+     *     gone due to the derivative.
+     *
+     * (8) Finally we get the equation to improve the factor as
+     *
+     *     ```
+     *     t := P(t) . B'(t) /
+     *            (B'(t) . B'(t) + P(t) . B''(t))
+     *     ```
+     *
+     * [note]: `B` and `B(t)` are different in the above equations.
+     */
+
+    FT_Error  error = FT_Err_Ok;
+
+    FT_26D6_Vec  aA, bB, cC;     /* A, B, C in the above comment          */
+    FT_26D6_Vec  nearest_point;  /* point on curve nearest to `point`     */
+    FT_26D6_Vec  direction;      /* direction of curve at `nearest_point` */
+
+    FT_26D6_Vec  p0, p1, p2;     /* control points of a conic curve       */
+    FT_26D6_Vec  p;              /* `point` to which shortest distance    */
+
+    FT_16D16  min_factor = 0;            /* factor at `nearest_point'     */
+    FT_16D16  cross;                     /* to determine the sign         */
+    FT_16D16  min        = FT_INT_MAX;   /* shortest squared distance     */
+
+    FT_UShort  iterations;
+    FT_UShort  steps;
+
+
+    if ( !conic || !out )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( conic->edge_type != SDF_EDGE_CONIC )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    p0 = conic->start_pos;
+    p1 = conic->control_a;
+    p2 = conic->end_pos;
+    p  = point;
+
+    /* compute substitution coefficients */
+    aA.x = p0.x - 2 * p1.x + p2.x;
+    aA.y = p0.y - 2 * p1.y + p2.y;
+
+    bB.x = 2 * ( p1.x - p0.x );
+    bB.y = 2 * ( p1.y - p0.y );
+
+    cC.x = p0.x;
+    cC.y = p0.y;
+
+    /* do Newton's iterations */
+    for ( iterations = 0; iterations <= MAX_NEWTON_DIVISIONS; iterations++ )
+    {
+      FT_16D16  factor = FT_INT_16D16( iterations ) / MAX_NEWTON_DIVISIONS;
+      FT_16D16  factor2;
+      FT_16D16  length;
+
+      FT_16D16_Vec  curve_point; /* point on the curve  */
+      FT_16D16_Vec  dist_vector; /* `curve_point` - `p` */
+
+      FT_26D6_Vec  d1;           /* first  derivative   */
+      FT_26D6_Vec  d2;           /* second derivative   */
+
+      FT_16D16  temp1;
+      FT_16D16  temp2;
+
+
+      for ( steps = 0; steps < MAX_NEWTON_STEPS; steps++ )
+      {
+        factor2 = FT_MulFix( factor, factor );
+
+        /* B(t) = t^2 * A + t * B + p0 */
+        curve_point.x = FT_MulFix( aA.x, factor2 ) +
+                        FT_MulFix( bB.x, factor ) + cC.x;
+        curve_point.y = FT_MulFix( aA.y, factor2 ) +
+                        FT_MulFix( bB.y, factor ) + cC.y;
+
+        /* convert to 16.16 */
+        curve_point.x = FT_26D6_16D16( curve_point.x );
+        curve_point.y = FT_26D6_16D16( curve_point.y );
+
+        /* P(t) in the comment */
+        dist_vector.x = curve_point.x - FT_26D6_16D16( p.x );
+        dist_vector.y = curve_point.y - FT_26D6_16D16( p.y );
+
+        length = VECTOR_LENGTH_16D16( dist_vector );
+
+        if ( length < min )
+        {
+          min           = length;
+          min_factor    = factor;
+          nearest_point = curve_point;
+        }
+
+        /* This is Newton's approximation.          */
+        /*                                          */
+        /*   t := P(t) . B'(t) /                    */
+        /*          (B'(t) . B'(t) + P(t) . B''(t)) */
+
+        /* B'(t) = 2tA + B */
+        d1.x = FT_MulFix( aA.x, 2 * factor ) + bB.x;
+        d1.y = FT_MulFix( aA.y, 2 * factor ) + bB.y;
+
+        /* B''(t) = 2A */
+        d2.x = 2 * aA.x;
+        d2.y = 2 * aA.y;
+
+        dist_vector.x /= 1024;
+        dist_vector.y /= 1024;
+
+        /* temp1 = P(t) . B'(t) */
+        temp1 = VEC_26D6_DOT( dist_vector, d1 );
+
+        /* temp2 = B'(t) . B'(t) + P(t) . B''(t) */
+        temp2 = VEC_26D6_DOT( d1, d1 ) +
+                VEC_26D6_DOT( dist_vector, d2 );
+
+        factor -= FT_DivFix( temp1, temp2 );
+
+        if ( factor < 0 || factor > FT_INT_16D16( 1 ) )
+          break;
+      }
+    }
+
+    /* B'(t) = 2t * A + B */
+    direction.x = 2 * FT_MulFix( aA.x, min_factor ) + bB.x;
+    direction.y = 2 * FT_MulFix( aA.y, min_factor ) + bB.y;
+
+    /* determine the sign */
+    cross = FT_MulFix( nearest_point.x - FT_26D6_16D16( p.x ),
+                       direction.y )                           -
+            FT_MulFix( nearest_point.y - FT_26D6_16D16( p.y ),
+                       direction.x );
+
+    /* assign the values */
+    out->distance = min;
+    out->sign     = cross < 0 ? 1 : -1;
+
+    if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) )
+      out->cross = FT_INT_16D16( 1 );   /* the two are perpendicular */
+    else
+    {
+      /* convert to nearest vector */
+      nearest_point.x -= FT_26D6_16D16( p.x );
+      nearest_point.y -= FT_26D6_16D16( p.y );
+
+      /* compute `cross` if not perpendicular */
+      FT_Vector_NormLen( &direction );
+      FT_Vector_NormLen( &nearest_point );
+
+      out->cross = FT_MulFix( direction.x, nearest_point.y ) -
+                   FT_MulFix( direction.y, nearest_point.x );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+#endif /* USE_NEWTON_FOR_CONIC */
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   get_min_distance_cubic
+   *
+   * @Description:
+   *   Find the shortest distance from the `cubic` Bezier curve to a given
+   *   `point` and assigns it to `out`.  Use it for cubic curves only.
+   *
+   * @Input:
+   *   cubic ::
+   *     The cubic Bezier curve to which the shortest distance is to be
+   *     computed.
+   *
+   *   point ::
+   *     Point from which the shortest distance is to be computed.
+   *
+   * @Output:
+   *   out ::
+   *     Signed distance from `point` to `cubic`.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   * @Note:
+   *   The function uses Newton's approximation to find the shortest
+   *   distance.  Another way would be to divide the cubic into conic or
+   *   subdivide the curve into lines, but that is not implemented.
+   *
+   *   The `cubic` parameter must have an edge type of `SDF_EDGE_CUBIC`.
+   *
+   */
+  static FT_Error
+  get_min_distance_cubic( SDF_Edge*             cubic,
+                          FT_26D6_Vec           point,
+                          SDF_Signed_Distance*  out )
+  {
+    /*
+     * The procedure to find the shortest distance from a point to a cubic
+     * Bezier curve is similar to quadratic curve algorithm.  The only
+     * difference is that while calculating factor `t`, instead of a cubic
+     * polynomial equation we have to find the roots of a 5th degree
+     * polynomial equation.  Solving this would require a significant amount
+     * of time, and still the results may not be accurate.  We are thus
+     * going to directly approximate the value of `t` using the Newton-Raphson
+     * method.
+     *
+     * Let's assume that
+     *
+     * ```
+     * p0 = first endpoint
+     * p1 = first control point
+     * p2 = second control point
+     * p3 = second endpoint
+     * p  = point from which shortest distance is to be calculated
+     * ```
+     *
+     * (1) The equation of a cubic Bezier curve can be written as
+     *
+     *     ```
+     *     B(t) = (1 - t)^3 * p0 + 3(1 - t)^2 t * p1 +
+     *              3(1 - t)t^2 * p2 + t^3 * p3
+     *     ```
+     *
+     *     The equation can be expanded and written as
+     *
+     *     ```
+     *     B(t) = t^3 * (-p0 + 3p1 - 3p2 + p3) +
+     *              3t^2 * (p0 - 2p1 + p2) + 3t * (-p0 + p1) + p0
+     *     ```
+     *
+     *     With
+     *
+     *     ```
+     *     A = -p0 + 3p1 - 3p2 + p3
+     *     B = 3(p0 - 2p1 + p2)
+     *     C = 3(-p0 + p1)
+     *     ```
+     *
+     *     we have
+     *
+     *     ```
+     *     B(t) = t^3 * A + t^2 * B + t * C + p0
+     *     ```
+     *
+     * (2) The derivative of the above equation is
+     *
+     *     ```
+     *     B'(t) = 3t^2 * A + 2t * B + C
+     *     ```
+     *
+     * (3) The second derivative of the above equation is
+     *
+     *     ```
+     *     B''(t) = 6t * A + 2B
+     *     ```
+     *
+     * (4) The equation `P(t)` of the distance from point `p` to the curve
+     *     can be written as
+     *
+     *     ```
+     *     P(t) = t^3 * A + t^2 * B + t * C + p0 - p
+     *     ```
+     *
+     *     With
+     *
+     *     ```
+     *     D = p0 - p
+     *     ```
+     *
+     *     we have
+     *
+     *     ```
+     *     P(t) = t^3 * A + t^2 * B + t * C + D
+     *     ```
+     *
+     * (5) Finally the equation of the angle between `B(t)` and `P(t)` can
+     *     be written as
+     *
+     *     ```
+     *     Q(t) = P(t) . B'(t)
+     *     ```
+     *
+     * (6) Our task is to find a value of `t` such that the above equation
+     *     `Q(t)` becomes zero, this is, the point-to-curve vector makes
+     *     90~degree with curve.  We solve this with the Newton-Raphson
+     *     method.
+     *
+     * (7) We first assume an arbitary value of factor `t`, which we then
+     *     improve.
+     *
+     *     ```
+     *     t := Q(t) / Q'(t)
+     *     ```
+     *
+     *     Putting the value of `Q(t)` from the above equation gives
+     *
+     *     ```
+     *     t := P(t) . B'(t) / derivative(P(t) . B'(t))
+     *     t := P(t) . B'(t) /
+     *            (P'(t) . B'(t) + P(t) . B''(t))
+     *     ```
+     *
+     *     Note that `P'(t)` is the same as `B'(t)` because the constant is
+     *     gone due to the derivative.
+     *
+     * (8) Finally we get the equation to improve the factor as
+     *
+     *     ```
+     *     t := P(t) . B'(t) /
+     *            (B'(t) . B'( t ) + P(t) . B''(t))
+     *     ```
+     *
+     * [note]: `B` and `B(t)` are different in the above equations.
+     */
+
+    FT_Error  error = FT_Err_Ok;
+
+    FT_26D6_Vec   aA, bB, cC, dD; /* A, B, C in the above comment          */
+    FT_16D16_Vec  nearest_point;  /* point on curve nearest to `point`     */
+    FT_16D16_Vec  direction;      /* direction of curve at `nearest_point` */
+
+    FT_26D6_Vec  p0, p1, p2, p3;  /* control points of a cubic curve       */
+    FT_26D6_Vec  p;               /* `point` to which shortest distance    */
+
+    FT_16D16  min_factor    = 0;            /* factor at shortest distance */
+    FT_16D16  min_factor_sq = 0;            /* factor at shortest distance */
+    FT_16D16  cross;                        /* to determine the sign       */
+    FT_16D16  min           = FT_INT_MAX;   /* shortest distance           */
+
+    FT_UShort  iterations;
+    FT_UShort  steps;
+
+
+    if ( !cubic || !out )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( cubic->edge_type != SDF_EDGE_CUBIC )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    p0 = cubic->start_pos;
+    p1 = cubic->control_a;
+    p2 = cubic->control_b;
+    p3 = cubic->end_pos;
+    p  = point;
+
+    /* compute substitution coefficients */
+    aA.x = -p0.x + 3 * ( p1.x - p2.x ) + p3.x;
+    aA.y = -p0.y + 3 * ( p1.y - p2.y ) + p3.y;
+
+    bB.x = 3 * ( p0.x - 2 * p1.x + p2.x );
+    bB.y = 3 * ( p0.y - 2 * p1.y + p2.y );
+
+    cC.x = 3 * ( p1.x - p0.x );
+    cC.y = 3 * ( p1.y - p0.y );
+
+    dD.x = p0.x;
+    dD.y = p0.y;
+
+    for ( iterations = 0; iterations <= MAX_NEWTON_DIVISIONS; iterations++ )
+    {
+      FT_16D16  factor  = FT_INT_16D16( iterations ) / MAX_NEWTON_DIVISIONS;
+
+      FT_16D16  factor2;         /* factor^2            */
+      FT_16D16  factor3;         /* factor^3            */
+      FT_16D16  length;
+
+      FT_16D16_Vec  curve_point; /* point on the curve  */
+      FT_16D16_Vec  dist_vector; /* `curve_point' - `p' */
+
+      FT_26D6_Vec  d1;           /* first  derivative   */
+      FT_26D6_Vec  d2;           /* second derivative   */
+
+      FT_16D16  temp1;
+      FT_16D16  temp2;
+
+
+      for ( steps = 0; steps < MAX_NEWTON_STEPS; steps++ )
+      {
+        factor2 = FT_MulFix( factor, factor );
+        factor3 = FT_MulFix( factor2, factor );
+
+        /* B(t) = t^3 * A + t^2 * B + t * C + D */
+        curve_point.x = FT_MulFix( aA.x, factor3 ) +
+                        FT_MulFix( bB.x, factor2 ) +
+                        FT_MulFix( cC.x, factor ) + dD.x;
+        curve_point.y = FT_MulFix( aA.y, factor3 ) +
+                        FT_MulFix( bB.y, factor2 ) +
+                        FT_MulFix( cC.y, factor ) + dD.y;
+
+        /* convert to 16.16 */
+        curve_point.x = FT_26D6_16D16( curve_point.x );
+        curve_point.y = FT_26D6_16D16( curve_point.y );
+
+        /* P(t) in the comment */
+        dist_vector.x = curve_point.x - FT_26D6_16D16( p.x );
+        dist_vector.y = curve_point.y - FT_26D6_16D16( p.y );
+
+        length = VECTOR_LENGTH_16D16( dist_vector );
+
+        if ( length < min )
+        {
+          min           = length;
+          min_factor    = factor;
+          min_factor_sq = factor2;
+          nearest_point = curve_point;
+        }
+
+        /* This the Newton's approximation.         */
+        /*                                          */
+        /*   t := P(t) . B'(t) /                    */
+        /*          (B'(t) . B'(t) + P(t) . B''(t)) */
+
+        /* B'(t) = 3t^2 * A + 2t * B + C */
+        d1.x = FT_MulFix( aA.x, 3 * factor2 ) +
+               FT_MulFix( bB.x, 2 * factor ) + cC.x;
+        d1.y = FT_MulFix( aA.y, 3 * factor2 ) +
+               FT_MulFix( bB.y, 2 * factor ) + cC.y;
+
+        /* B''(t) = 6t * A + 2B */
+        d2.x = FT_MulFix( aA.x, 6 * factor ) + 2 * bB.x;
+        d2.y = FT_MulFix( aA.y, 6 * factor ) + 2 * bB.y;
+
+        dist_vector.x /= 1024;
+        dist_vector.y /= 1024;
+
+        /* temp1 = P(t) . B'(t) */
+        temp1 = VEC_26D6_DOT( dist_vector, d1 );
+
+        /* temp2 = B'(t) . B'(t) + P(t) . B''(t) */
+        temp2 = VEC_26D6_DOT( d1, d1 ) +
+                VEC_26D6_DOT( dist_vector, d2 );
+
+        factor -= FT_DivFix( temp1, temp2 );
+
+        if ( factor < 0 || factor > FT_INT_16D16( 1 ) )
+          break;
+      }
+    }
+
+    /* B'(t) = 3t^2 * A + 2t * B + C */
+    direction.x = FT_MulFix( aA.x, 3 * min_factor_sq ) +
+                  FT_MulFix( bB.x, 2 * min_factor ) + cC.x;
+    direction.y = FT_MulFix( aA.y, 3 * min_factor_sq ) +
+                  FT_MulFix( bB.y, 2 * min_factor ) + cC.y;
+
+    /* determine the sign */
+    cross = FT_MulFix( nearest_point.x - FT_26D6_16D16( p.x ),
+                       direction.y )                           -
+            FT_MulFix( nearest_point.y - FT_26D6_16D16( p.y ),
+                       direction.x );
+
+    /* assign the values */
+    out->distance = min;
+    out->sign     = cross < 0 ? 1 : -1;
+
+    if ( min_factor != 0 && min_factor != FT_INT_16D16( 1 ) )
+      out->cross = FT_INT_16D16( 1 );   /* the two are perpendicular */
+    else
+    {
+      /* convert to nearest vector */
+      nearest_point.x -= FT_26D6_16D16( p.x );
+      nearest_point.y -= FT_26D6_16D16( p.y );
+
+      /* compute `cross` if not perpendicular */
+      FT_Vector_NormLen( &direction );
+      FT_Vector_NormLen( &nearest_point );
+
+      out->cross = FT_MulFix( direction.x, nearest_point.y ) -
+                   FT_MulFix( direction.y, nearest_point.x );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   sdf_edge_get_min_distance
+   *
+   * @Description:
+   *   Find shortest distance from `point` to any type of `edge`.  It checks
+   *   the edge type and then calls the relevant `get_min_distance_*`
+   *   function.
+   *
+   * @Input:
+   *   edge ::
+   *     An edge to which the shortest distance is to be computed.
+   *
+   *   point ::
+   *     Point from which the shortest distance is to be computed.
+   *
+   * @Output:
+   *   out ::
+   *     Signed distance from `point` to `edge`.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   */
+  static FT_Error
+  sdf_edge_get_min_distance( SDF_Edge*             edge,
+                             FT_26D6_Vec           point,
+                             SDF_Signed_Distance*  out )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+
+    if ( !edge || !out )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    /* edge-specific distance calculation */
+    switch ( edge->edge_type )
+    {
+    case SDF_EDGE_LINE:
+      get_min_distance_line( edge, point, out );
+      break;
+
+    case SDF_EDGE_CONIC:
+      get_min_distance_conic( edge, point, out );
+      break;
+
+    case SDF_EDGE_CUBIC:
+      get_min_distance_cubic( edge, point, out );
+      break;
+
+    default:
+      error = FT_THROW( Invalid_Argument );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* `sdf_generate' is not used at the moment */
+#if 0
+
+  #error "DO NOT USE THIS!"
+  #error "The function still outputs 16-bit data, which might cause memory"
+  #error "corruption.  If required I will add this later."
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   sdf_contour_get_min_distance
+   *
+   * @Description:
+   *   Iterate over all edges that make up the contour, find the shortest
+   *   distance from a point to this contour, and assigns result to `out`.
+   *
+   * @Input:
+   *   contour ::
+   *     A contour to which the shortest distance is to be computed.
+   *
+   *   point ::
+   *     Point from which the shortest distance is to be computed.
+   *
+   * @Output:
+   *   out ::
+   *     Signed distance from the `point' to the `contour'.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   * @Note:
+   *   The function does not return a signed distance for each edge which
+   *   makes up the contour, it simply returns the shortest of all the
+   *   edges.
+   *
+   */
+  static FT_Error
+  sdf_contour_get_min_distance( SDF_Contour*          contour,
+                                FT_26D6_Vec           point,
+                                SDF_Signed_Distance*  out )
+  {
+    FT_Error             error    = FT_Err_Ok;
+    SDF_Signed_Distance  min_dist = max_sdf;
+    SDF_Edge*            edge_list;
+
+
+    if ( !contour || !out )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    edge_list = contour->edges;
+
+    /* iterate over all the edges manually */
+    while ( edge_list )
+    {
+      SDF_Signed_Distance  current_dist = max_sdf;
+      FT_16D16             diff;
+
+
+      FT_CALL( sdf_edge_get_min_distance( edge_list,
+                                          point,
+                                          &current_dist ) );
+
+      if ( current_dist.distance >= 0 )
+      {
+        diff = current_dist.distance - min_dist.distance;
+
+
+        if ( FT_ABS(diff ) < CORNER_CHECK_EPSILON )
+          min_dist = resolve_corner( min_dist, current_dist );
+        else if ( diff < 0 )
+          min_dist = current_dist;
+      }
+      else
+        FT_TRACE0(( "sdf_contour_get_min_distance: Overflow.\n" ));
+
+      edge_list = edge_list->next;
+    }
+
+    *out = min_dist;
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   sdf_generate
+   *
+   * @Description:
+   *   This is the main function that is responsible for generating signed
+   *   distance fields.  The function does not align or compute the size of
+   *   `bitmap`; therefore the calling application must set up `bitmap`
+   *   properly and transform the `shape' appropriately in advance.
+   *
+   *   Currently we check all pixels against all contours and all edges.
+   *
+   * @Input:
+   *   internal_params ::
+   *     Internal parameters and properties required by the rasterizer.  See
+   *     @SDF_Params for more.
+   *
+   *   shape ::
+   *     A complete shape which is used to generate SDF.
+   *
+   *   spread ::
+   *     Maximum distances to be allowed in the output bitmap.
+   *
+   * @Output:
+   *   bitmap ::
+   *     The output bitmap which will contain the SDF information.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   */
+  static FT_Error
+  sdf_generate( const SDF_Params  internal_params,
+                const SDF_Shape*  shape,
+                FT_UInt           spread,
+                const FT_Bitmap*  bitmap )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+    FT_UInt  width = 0;
+    FT_UInt  rows  = 0;
+    FT_UInt  x     = 0;   /* used to loop in x direction, i.e., width     */
+    FT_UInt  y     = 0;   /* used to loop in y direction, i.e., rows      */
+    FT_UInt  sp_sq = 0;   /* `spread` [* `spread`] as a 16.16 fixed value */
+
+    FT_Short*  buffer;
+
+
+    if ( !shape || !bitmap )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( spread < MIN_SPREAD || spread > MAX_SPREAD )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    width  = bitmap->width;
+    rows   = bitmap->rows;
+    buffer = (FT_Short*)bitmap->buffer;
+
+    if ( USE_SQUARED_DISTANCES )
+      sp_sq = FT_INT_16D16( spread * spread );
+    else
+      sp_sq = FT_INT_16D16( spread );
+
+    if ( width == 0 || rows == 0 )
+    {
+      FT_TRACE0(( "sdf_generate:"
+                  " Cannot render glyph with width/height == 0\n" ));
+      FT_TRACE0(( "             "
+                  " (width, height provided [%d, %d])\n",
+                  width, rows ));
+
+      error = FT_THROW( Cannot_Render_Glyph );
+      goto Exit;
+    }
+
+    /* loop over all rows */
+    for ( y = 0; y < rows; y++ )
+    {
+      /* loop over all pixels of a row */
+      for ( x = 0; x < width; x++ )
+      {
+        /* `grid_point` is the current pixel position; */
+        /* our task is to find the shortest distance   */
+        /* from this point to the entire shape.        */
+        FT_26D6_Vec          grid_point = zero_vector;
+        SDF_Signed_Distance  min_dist   = max_sdf;
+        SDF_Contour*         contour_list;
+
+        FT_UInt   index;
+        FT_Short  value;
+
+
+        grid_point.x = FT_INT_26D6( x );
+        grid_point.y = FT_INT_26D6( y );
+
+        /* This `grid_point' is at the corner, but we */
+        /* use the center of the pixel.               */
+        grid_point.x += FT_INT_26D6( 1 ) / 2;
+        grid_point.y += FT_INT_26D6( 1 ) / 2;
+
+        contour_list = shape->contours;
+
+        /* iterate over all contours manually */
+        while ( contour_list )
+        {
+          SDF_Signed_Distance  current_dist = max_sdf;
+
+
+          FT_CALL( sdf_contour_get_min_distance( contour_list,
+                                                 grid_point,
+                                                 &current_dist ) );
+
+          if ( current_dist.distance < min_dist.distance )
+            min_dist = current_dist;
+
+          contour_list = contour_list->next;
+        }
+
+        /* [OPTIMIZATION]: if (min_dist > sp_sq) then simply clamp  */
+        /*                 the value to spread to avoid square_root */
+
+        /* clamp the values to spread */
+        if ( min_dist.distance > sp_sq )
+          min_dist.distance = sp_sq;
+
+        /* square_root the values and fit in a 6.10 fixed point */
+        if ( USE_SQUARED_DISTANCES )
+          min_dist.distance = square_root( min_dist.distance );
+
+        if ( internal_params.orientation == FT_ORIENTATION_FILL_LEFT )
+          min_dist.sign = -min_dist.sign;
+        if ( internal_params.flip_sign )
+          min_dist.sign = -min_dist.sign;
+
+        min_dist.distance /= 64; /* convert from 16.16 to 22.10 */
+
+        value  = min_dist.distance & 0x0000FFFF; /* truncate to 6.10 */
+        value *= min_dist.sign;
+
+        if ( internal_params.flip_y )
+          index = y * width + x;
+        else
+          index = ( rows - y - 1 ) * width + x;
+
+        buffer[index] = value;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+#endif /* 0 */
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   sdf_generate_bounding_box
+   *
+   * @Description:
+   *   This function does basically the same thing as `sdf_generate` above
+   *   but more efficiently.
+   *
+   *   Instead of checking all pixels against all edges, we loop over all
+   *   edges and only check pixels around the control box of the edge; the
+   *   control box is increased by the spread in all directions.  Anything
+   *   outside of the control box that exceeds `spread` doesn't need to be
+   *   computed.
+   *
+   *   Lastly, to determine the sign of unchecked pixels, we do a single
+   *   pass of all rows starting with a '+' sign and flipping when we come
+   *   across a '-' sign and continue.  This also eliminates the possibility
+   *   of overflow because we only check the proximity of the curve.
+   *   Therefore we can use squared distanced safely.
+   *
+   * @Input:
+   *   internal_params ::
+   *     Internal parameters and properties required by the rasterizer.
+   *     See @SDF_Params for more.
+   *
+   *   shape ::
+   *     A complete shape which is used to generate SDF.
+   *
+   *   spread ::
+   *     Maximum distances to be allowed in the output bitmap.
+   *
+   * @Output:
+   *   bitmap ::
+   *     The output bitmap which will contain the SDF information.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   */
+  static FT_Error
+  sdf_generate_bounding_box( const SDF_Params  internal_params,
+                             const SDF_Shape*  shape,
+                             FT_UInt           spread,
+                             const FT_Bitmap*  bitmap )
+  {
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = NULL;
+
+    FT_Int  width, rows, i, j;
+    FT_Int  sp_sq;            /* max value to check   */
+
+    SDF_Contour*   contours;  /* list of all contours */
+    FT_SDFFormat*  buffer;    /* the bitmap buffer    */
+
+    /* This buffer has the same size in indices as the    */
+    /* bitmap buffer.  When we check a pixel position for */
+    /* a shortest distance we keep it in this buffer.     */
+    /* This way we can find out which pixel is set,       */
+    /* and also determine the signs properly.             */
+    SDF_Signed_Distance*  dists = NULL;
+
+    const FT_16D16  fixed_spread = FT_INT_16D16( spread );
+
+
+    if ( !shape || !bitmap )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( spread < MIN_SPREAD || spread > MAX_SPREAD )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    memory = shape->memory;
+    if ( !memory )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( FT_ALLOC( dists,
+                   bitmap->width * bitmap->rows * sizeof ( *dists ) ) )
+      goto Exit;
+
+    contours = shape->contours;
+    width    = (FT_Int)bitmap->width;
+    rows     = (FT_Int)bitmap->rows;
+    buffer   = (FT_SDFFormat*)bitmap->buffer;
+
+    if ( USE_SQUARED_DISTANCES )
+      sp_sq = fixed_spread * fixed_spread;
+    else
+      sp_sq = fixed_spread;
+
+    if ( width == 0 || rows == 0 )
+    {
+      FT_TRACE0(( "sdf_generate:"
+                  " Cannot render glyph with width/height == 0\n" ));
+      FT_TRACE0(( "             "
+                  " (width, height provided [%d, %d])", width, rows ));
+
+      error = FT_THROW( Cannot_Render_Glyph );
+      goto Exit;
+    }
+
+    /* loop over all contours */
+    while ( contours )
+    {
+      SDF_Edge*  edges = contours->edges;
+
+
+      /* loop over all edges */
+      while ( edges )
+      {
+        FT_CBox  cbox;
+        FT_Int   x, y;
+
+
+        /* get the control box and increase it by `spread' */
+        cbox = get_control_box( *edges );
+
+        cbox.xMin = ( cbox.xMin - 63 ) / 64 - ( FT_Pos )spread;
+        cbox.xMax = ( cbox.xMax + 63 ) / 64 + ( FT_Pos )spread;
+        cbox.yMin = ( cbox.yMin - 63 ) / 64 - ( FT_Pos )spread;
+        cbox.yMax = ( cbox.yMax + 63 ) / 64 + ( FT_Pos )spread;
+
+        /* now loop over the pixels in the control box. */
+        for ( y = cbox.yMin; y < cbox.yMax; y++ )
+        {
+          for ( x = cbox.xMin; x < cbox.xMax; x++ )
+          {
+            FT_26D6_Vec          grid_point = zero_vector;
+            SDF_Signed_Distance  dist       = max_sdf;
+            FT_UInt              index      = 0;
+
+
+            if ( x < 0 || x >= width )
+              continue;
+            if ( y < 0 || y >= rows )
+              continue;
+
+            grid_point.x = FT_INT_26D6( x );
+            grid_point.y = FT_INT_26D6( y );
+
+            /* This `grid_point` is at the corner, but we */
+            /* use the center of the pixel.               */
+            grid_point.x += FT_INT_26D6( 1 ) / 2;
+            grid_point.y += FT_INT_26D6( 1 ) / 2;
+
+            FT_CALL( sdf_edge_get_min_distance( edges,
+                                                grid_point,
+                                                &dist ) );
+
+            if ( internal_params.orientation == FT_ORIENTATION_FILL_LEFT )
+              dist.sign = -dist.sign;
+
+            /* ignore if the distance is greater than spread;       */
+            /* otherwise it creates artifacts due to the wrong sign */
+            if ( dist.distance > sp_sq )
+              continue;
+
+            /* square_root the values and fit in a 6.10 fixed-point */
+            if ( USE_SQUARED_DISTANCES )
+              dist.distance = square_root( dist.distance );
+
+            if ( internal_params.flip_y )
+              index = (FT_UInt)( y * width + x );
+            else
+              index = (FT_UInt)( ( rows - y - 1 ) * width + x );
+
+            /* check whether the pixel is set or not */
+            if ( dists[index].sign == 0 )
+              dists[index] = dist;
+            else if ( dists[index].distance > dist.distance )
+              dists[index] = dist;
+            else if ( FT_ABS( dists[index].distance - dist.distance )
+                        < CORNER_CHECK_EPSILON )
+              dists[index] = resolve_corner( dists[index], dist );
+          }
+        }
+
+        edges = edges->next;
+      }
+
+      contours = contours->next;
+    }
+
+    /* final pass */
+    for ( j = 0; j < rows; j++ )
+    {
+      /* We assume the starting pixel of each row is outside. */
+      FT_Char  current_sign = -1;
+      FT_UInt  index;
+
+
+      if ( internal_params.overload_sign != 0 )
+        current_sign = internal_params.overload_sign < 0 ? -1 : 1;
+
+      for ( i = 0; i < width; i++ )
+      {
+        index = (FT_UInt)( j * width + i );
+
+        /* if the pixel is not set                     */
+        /* its shortest distance is more than `spread` */
+        if ( dists[index].sign == 0 )
+          dists[index].distance = fixed_spread;
+        else
+          current_sign = dists[index].sign;
+
+        /* clamp the values */
+        if ( dists[index].distance > fixed_spread )
+          dists[index].distance = fixed_spread;
+
+        /* flip sign if required */
+        dists[index].distance *= internal_params.flip_sign ? -current_sign
+                                                           :  current_sign;
+
+        /* concatenate to appropriate format */
+        buffer[index] = map_fixed_to_sdf( dists[index].distance,
+                                          fixed_spread );
+      }
+    }
+
+  Exit:
+    FT_FREE( dists );
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   sdf_generate_subdivision
+   *
+   * @Description:
+   *   Subdivide the shape into a number of straight lines, then use the
+   *   above `sdf_generate_bounding_box` function to generate the SDF.
+   *
+   *   Note: After calling this function `shape` no longer has the original
+   *         edges, it only contains lines.
+   *
+   * @Input:
+   *   internal_params ::
+   *     Internal parameters and properties required by the rasterizer.
+   *     See @SDF_Params for more.
+   *
+   *   shape ::
+   *     A complete shape which is used to generate SDF.
+   *
+   *   spread ::
+   *     Maximum distances to be allowed inthe output bitmap.
+   *
+   * @Output:
+   *   bitmap ::
+   *     The output bitmap which will contain the SDF information.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   */
+  static FT_Error
+  sdf_generate_subdivision( const SDF_Params  internal_params,
+                            SDF_Shape*        shape,
+                            FT_UInt           spread,
+                            const FT_Bitmap*  bitmap )
+  {
+    /*
+     * Thanks to Alexei for providing the idea of this optimization.
+     *
+     * We take advantage of two facts.
+     *
+     * (1) Computing the shortest distance from a point to a line segment is
+     *     very fast.
+     * (2) We don't have to compute the shortest distance for the entire
+     *     two-dimensional grid.
+     *
+     * Both ideas lead to the following optimization.
+     *
+     * (1) Split the outlines into a number of line segments.
+     *
+     * (2) For each line segment, only process its neighborhood.
+     *
+     * (3) Compute the closest distance to the line only for neighborhood
+     *     grid points.
+     *
+     * This greatly reduces the number of grid points to check.
+     */
+
+    FT_Error  error = FT_Err_Ok;
+
+
+    FT_CALL( split_sdf_shape( shape ) );
+    FT_CALL( sdf_generate_bounding_box( internal_params,
+                                        shape, spread, bitmap ) );
+
+  Exit:
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   sdf_generate_with_overlaps
+   *
+   * @Description:
+   *   This function can be used to generate SDF for glyphs with overlapping
+   *   contours.  The function generates SDF for contours separately on
+   *   separate bitmaps (to generate SDF it uses
+   *   `sdf_generate_subdivision`).  At the end it simply combines all the
+   *   SDF into the output bitmap; this fixes all the signs and removes
+   *   overlaps.
+   *
+   * @Input:
+   *   internal_params ::
+   *     Internal parameters and properties required by the rasterizer.  See
+   *     @SDF_Params for more.
+   *
+   *   shape ::
+   *     A complete shape which is used to generate SDF.
+   *
+   *   spread ::
+   *     Maximum distances to be allowed in the output bitmap.
+   *
+   * @Output:
+   *   bitmap ::
+   *     The output bitmap which will contain the SDF information.
+   *
+   * @Return:
+   *   FreeType error, 0 means success.
+   *
+   * @Note:
+   *   The function cannot generate a proper SDF for glyphs with
+   *   self-intersecting contours because we cannot separate them into two
+   *   separate bitmaps.  In case of self-intersecting contours it is
+   *   necessary to remove the overlaps before generating the SDF.
+   *
+   */
+  static FT_Error
+  sdf_generate_with_overlaps( SDF_Params        internal_params,
+                              SDF_Shape*        shape,
+                              FT_UInt           spread,
+                              const FT_Bitmap*  bitmap )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+    FT_Int      num_contours;        /* total number of contours      */
+    FT_Int      i, j;                /* iterators                     */
+    FT_Int      width, rows;         /* width and rows of the bitmap  */
+    FT_Bitmap*  bitmaps;             /* separate bitmaps for contours */
+
+    SDF_Contour*  contour;           /* temporary variable to iterate */
+    SDF_Contour*  temp_contour;      /* temporary contour             */
+    SDF_Contour*  head;              /* head of the contour list      */
+    SDF_Shape     temp_shape;        /* temporary shape               */
+
+    FT_Memory      memory;           /* to allocate memory            */
+    FT_SDFFormat*  t;                /* target bitmap buffer          */
+    FT_Bool        flip_sign;        /* flip sign?                    */
+
+    /* orientation of all the separate contours */
+    SDF_Contour_Orientation*  orientations;
+
+
+    bitmaps      = NULL;
+    orientations = NULL;
+    head         = NULL;
+
+    if ( !shape || !bitmap || !shape->memory )
+      return FT_THROW( Invalid_Argument );
+
+    /* Disable `flip_sign` to avoid extra complication */
+    /* during the combination phase.                   */
+    flip_sign                 = internal_params.flip_sign;
+    internal_params.flip_sign = 0;
+
+    contour           = shape->contours;
+    memory            = shape->memory;
+    temp_shape.memory = memory;
+    width             = (FT_Int)bitmap->width;
+    rows              = (FT_Int)bitmap->rows;
+    num_contours      = 0;
+
+    /* find the number of contours in the shape */
+    while ( contour )
+    {
+      num_contours++;
+      contour = contour->next;
+    }
+
+    /* allocate the bitmaps to generate SDF for separate contours */
+    if ( FT_ALLOC( bitmaps,
+                   (FT_UInt)num_contours * sizeof ( *bitmaps ) ) )
+      goto Exit;
+
+    /* allocate array to hold orientation for all contours */
+    if ( FT_ALLOC( orientations,
+                   (FT_UInt)num_contours * sizeof ( *orientations ) ) )
+      goto Exit;
+
+    contour = shape->contours;
+
+    /* Iterate over all contours and generate SDF separately. */
+    for ( i = 0; i < num_contours; i++ )
+    {
+      /* initialize the corresponding bitmap */
+      FT_Bitmap_Init( &bitmaps[i] );
+
+      bitmaps[i].width      = bitmap->width;
+      bitmaps[i].rows       = bitmap->rows;
+      bitmaps[i].pitch      = bitmap->pitch;
+      bitmaps[i].num_grays  = bitmap->num_grays;
+      bitmaps[i].pixel_mode = bitmap->pixel_mode;
+
+      /* allocate memory for the buffer */
+      if ( FT_ALLOC( bitmaps[i].buffer,
+                     bitmap->rows * (FT_UInt)bitmap->pitch ) )
+        goto Exit;
+
+      /* determine the orientation */
+      orientations[i] = get_contour_orientation( contour );
+
+      /* The `overload_sign` property is specific to  */
+      /* `sdf_generate_bounding_box`.  This basically */
+      /* overloads the default sign of the outside    */
+      /* pixels, which is necessary for               */
+      /* counter-clockwise contours.                  */
+      if ( orientations[i] == SDF_ORIENTATION_CCW                   &&
+           internal_params.orientation == FT_ORIENTATION_FILL_RIGHT )
+        internal_params.overload_sign = 1;
+      else if ( orientations[i] == SDF_ORIENTATION_CW                   &&
+                internal_params.orientation == FT_ORIENTATION_FILL_LEFT )
+        internal_params.overload_sign = 1;
+      else
+        internal_params.overload_sign = 0;
+
+      /* Make `contour->next` NULL so that there is   */
+      /* one contour in the list.  Also hold the next */
+      /* contour in a temporary variable so as to     */
+      /* restore the original value.                  */
+      temp_contour  = contour->next;
+      contour->next = NULL;
+
+      /* Use `temp_shape` to hold the new contour. */
+      /* Now, `temp_shape` has only one contour.   */
+      temp_shape.contours = contour;
+
+      /* finally generate the SDF */
+      FT_CALL( sdf_generate_subdivision( internal_params,
+                                         &temp_shape,
+                                         spread,
+                                         &bitmaps[i] ) );
+
+      /* Restore the original `next` variable. */
+      contour->next = temp_contour;
+
+      /* Since `split_sdf_shape` deallocated the original */
+      /* contours list we need to assign the new value to */
+      /* the shape's contour.                             */
+      temp_shape.contours->next = head;
+      head                      = temp_shape.contours;
+
+      /* Simply flip the orientation in case of post-script fonts */
+      /* so as to avoid modificatons in the combining phase.      */
+      if ( internal_params.orientation == FT_ORIENTATION_FILL_LEFT )
+      {
+        if ( orientations[i] == SDF_ORIENTATION_CW )
+          orientations[i] = SDF_ORIENTATION_CCW;
+        else if ( orientations[i] == SDF_ORIENTATION_CCW )
+          orientations[i] = SDF_ORIENTATION_CW;
+      }
+
+      contour = contour->next;
+    }
+
+    /* assign the new contour list to `shape->contours` */
+    shape->contours = head;
+
+    /* cast the output bitmap buffer */
+    t = (FT_SDFFormat*)bitmap->buffer;
+
+    /* Iterate over all pixels and combine all separate    */
+    /* contours.  These are the rules for combining:       */
+    /*                                                     */
+    /* (1) For all clockwise contours, compute the largest */
+    /*     value.  Name this as `val_c`.                   */
+    /* (2) For all counter-clockwise contours, compute the */
+    /*     smallest value.  Name this as `val_ac`.         */
+    /* (3) Now, finally use the smaller value of `val_c'   */
+    /*     and `val_ac'.                                   */
+    for ( j = 0; j < rows; j++ )
+    {
+      for ( i = 0; i < width; i++ )
+      {
+        FT_Int  id = j * width + i;       /* index of current pixel    */
+        FT_Int  c;                        /* contour iterator          */
+
+        FT_SDFFormat  val_c  = 0;         /* max clockwise value       */
+        FT_SDFFormat  val_ac = UCHAR_MAX; /* min counter-clockwise val */
+
+
+        /* iterate through all the contours */
+        for ( c = 0; c < num_contours; c++ )
+        {
+          /* current contour value */
+          FT_SDFFormat  temp = ( (FT_SDFFormat*)bitmaps[c].buffer )[id];
+
+
+          if ( orientations[c] == SDF_ORIENTATION_CW )
+            val_c = FT_MAX( val_c, temp );   /* clockwise         */
+          else
+            val_ac = FT_MIN( val_ac, temp ); /* counter-clockwise */
+        }
+
+        /* Finally find the smaller of the two and assign to output. */
+        /* Also apply `flip_sign` if set.                            */
+        t[id] = FT_MIN( val_c, val_ac );
+
+        if ( flip_sign )
+          t[id] = invert_sign( t[id] );
+      }
+    }
+
+  Exit:
+    /* deallocate orientations array */
+    if ( orientations )
+      FT_FREE( orientations );
+
+    /* deallocate temporary bitmaps */
+    if ( bitmaps )
+    {
+      if ( num_contours == 0 )
+        error = FT_THROW( Raster_Corrupted );
+      else
+      {
+        for ( i = 0; i < num_contours; i++ )
+          FT_FREE( bitmaps[i].buffer );
+
+        FT_FREE( bitmaps );
+      }
+    }
+
+    /* restore the `flip_sign` property */
+    internal_params.flip_sign = flip_sign;
+
+    return error;
+  }
+
+
+  /**************************************************************************
+   *
+   * interface functions
+   *
+   */
+
+  static FT_Error
+  sdf_raster_new( FT_Memory     memory,
+                  SDF_PRaster*  araster )
+  {
+    FT_Error     error;
+    SDF_PRaster  raster = NULL;
+
+
+    if ( !FT_NEW( raster ) )
+      raster->memory = memory;
+
+    *araster = raster;
+
+   return error;
+  }
+
+
+  static void
+  sdf_raster_reset( FT_Raster       raster,
+                    unsigned char*  pool_base,
+                    unsigned long   pool_size )
+  {
+    FT_UNUSED( raster );
+    FT_UNUSED( pool_base );
+    FT_UNUSED( pool_size );
+  }
+
+
+  static FT_Error
+  sdf_raster_set_mode( FT_Raster      raster,
+                       unsigned long  mode,
+                       void*          args )
+  {
+    FT_UNUSED( raster );
+    FT_UNUSED( mode );
+    FT_UNUSED( args );
+
+    return FT_Err_Ok;
+  }
+
+
+  static FT_Error
+  sdf_raster_render( FT_Raster                raster,
+                     const FT_Raster_Params*  params )
+  {
+    FT_Error                  error      = FT_Err_Ok;
+    SDF_TRaster*              sdf_raster = (SDF_TRaster*)raster;
+    FT_Outline*               outline    = NULL;
+    const SDF_Raster_Params*  sdf_params = (const SDF_Raster_Params*)params;
+
+    FT_Memory   memory = NULL;
+    SDF_Shape*  shape  = NULL;
+    SDF_Params  internal_params;
+
+
+    /* check for valid arguments */
+    if ( !sdf_raster || !sdf_params )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    outline = (FT_Outline*)sdf_params->root.source;
+
+    /* check whether outline is valid */
+    if ( !outline )
+    {
+      error = FT_THROW( Invalid_Outline );
+      goto Exit;
+    }
+
+    /* if the outline is empty, return */
+    if ( outline->n_points <= 0 || outline->n_contours <= 0 )
+      goto Exit;
+
+    /* check whether the outline has valid fields */
+    if ( !outline->contours || !outline->points )
+    {
+      error = FT_THROW( Invalid_Outline );
+      goto Exit;
+    }
+
+    /* check whether spread is set properly */
+    if ( sdf_params->spread > MAX_SPREAD ||
+         sdf_params->spread < MIN_SPREAD )
+    {
+      FT_TRACE0(( "sdf_raster_render:"
+                  " The `spread' field of `SDF_Raster_Params' is invalid,\n" ));
+      FT_TRACE0(( "                  "
+                  " the value of this field must be within [%d, %d].\n",
+                  MIN_SPREAD, MAX_SPREAD ));
+      FT_TRACE0(( "                  "
+                  " Also, you must pass `SDF_Raster_Params' instead of\n" ));
+      FT_TRACE0(( "                  "
+                  " the default `FT_Raster_Params' while calling\n" ));
+      FT_TRACE0(( "                  "
+                  " this function and set the fields properly.\n" ));
+
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    memory = sdf_raster->memory;
+    if ( !memory )
+    {
+      FT_TRACE0(( "sdf_raster_render:"
+                  " Raster not setup properly,\n" ));
+      FT_TRACE0(( "                  "
+                  " unable to find memory handle.\n" ));
+
+      error = FT_THROW( Invalid_Handle );
+      goto Exit;
+    }
+
+    /* set up the parameters */
+    internal_params.orientation   = FT_Outline_Get_Orientation( outline );
+    internal_params.flip_sign     = sdf_params->flip_sign;
+    internal_params.flip_y        = sdf_params->flip_y;
+    internal_params.overload_sign = 0;
+
+    FT_CALL( sdf_shape_new( memory, &shape ) );
+
+    FT_CALL( sdf_outline_decompose( outline, shape ) );
+
+    if ( sdf_params->overlaps )
+      FT_CALL( sdf_generate_with_overlaps( internal_params,
+                                           shape, sdf_params->spread,
+                                           sdf_params->root.target ) );
+    else
+      FT_CALL( sdf_generate_subdivision( internal_params,
+                                         shape, sdf_params->spread,
+                                         sdf_params->root.target ) );
+
+    if ( shape )
+      sdf_shape_done( &shape );
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  sdf_raster_done( FT_Raster  raster )
+  {
+    FT_Memory  memory = (FT_Memory)((SDF_TRaster*)raster)->memory;
+
+
+    FT_FREE( raster );
+  }
+
+
+  FT_DEFINE_RASTER_FUNCS(
+    ft_sdf_raster,
+
+    FT_GLYPH_FORMAT_OUTLINE,
+
+    (FT_Raster_New_Func)     sdf_raster_new,       /* raster_new      */
+    (FT_Raster_Reset_Func)   sdf_raster_reset,     /* raster_reset    */
+    (FT_Raster_Set_Mode_Func)sdf_raster_set_mode,  /* raster_set_mode */
+    (FT_Raster_Render_Func)  sdf_raster_render,    /* raster_render   */
+    (FT_Raster_Done_Func)    sdf_raster_done       /* raster_done     */
+  )
+
+
+/* END */
diff --git a/src/sdf/ftsdf.h b/src/sdf/ftsdf.h
new file mode 100644
index 0000000..187b418
--- /dev/null
+++ b/src/sdf/ftsdf.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+ *
+ * ftsdf.h
+ *
+ *   Signed Distance Field support (specification).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTSDF_H_
+#define FTSDF_H_
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include <freetype/ftimage.h>
+
+/* common properties and function */
+#include "ftsdfcommon.h"
+
+FT_BEGIN_HEADER
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   SDF_Raster_Params
+   *
+   * @description:
+   *   This struct must be passed to the raster render function
+   *   @FT_Raster_RenderFunc instead of @FT_Raster_Params because the
+   *   rasterizer requires some additional information to render properly.
+   *
+   * @fields:
+   *   root ::
+   *     The native raster parameters structure.
+   *
+   *   spread ::
+   *     This is an essential parameter/property required by the renderer.
+   *     `spread` defines the maximum unsigned value that is present in the
+   *     final SDF output.  For the default value check file
+   *     `ftsdfcommon.h`.
+   *
+   *   flip_sign ::
+   *     By default positive values indicate positions inside of contours,
+   *     i.e., filled by a contour.  If this property is true then that
+   *     output will be the opposite of the default, i.e., negative values
+   *     indicate positions inside of contours.
+   *
+   *   flip_y ::
+   *     Setting this parameter to true maked the output image flipped
+   *     along the y-axis.
+   *
+   *   overlaps ::
+   *     Set this to true to generate SDF for glyphs having overlapping
+   *     contours.  The overlapping support is limited to glyphs that do not
+   *     have self-intersecting contours.  Also, removing overlaps require a
+   *     considerable amount of extra memory; additionally, it will not work
+   *     if generating SDF from bitmap.
+   *
+   * @note:
+   *   All properties are valid for both the 'sdf' and 'bsdf' renderers; the
+   *   exception is `overlaps`, which gets ignored by the 'bsdf' renderer.
+   *
+   */
+  typedef struct  SDF_Raster_Params_
+  {
+    FT_Raster_Params  root;
+    FT_UInt           spread;
+    FT_Bool           flip_sign;
+    FT_Bool           flip_y;
+    FT_Bool           overlaps;
+
+  } SDF_Raster_Params;
+
+
+  /* rasterizer to convert outline to SDF */
+  FT_EXPORT_VAR( const FT_Raster_Funcs )  ft_sdf_raster;
+
+  /* rasterizer to convert bitmap to SDF */
+  FT_EXPORT_VAR( const FT_Raster_Funcs )  ft_bitmap_sdf_raster;
+
+FT_END_HEADER
+
+#endif /* FTSDF_H_ */
+
+
+/* END */
diff --git a/src/sdf/ftsdfcommon.c b/src/sdf/ftsdfcommon.c
new file mode 100644
index 0000000..91aa521
--- /dev/null
+++ b/src/sdf/ftsdfcommon.c
@@ -0,0 +1,147 @@
+/****************************************************************************
+ *
+ * ftsdfcommon.c
+ *
+ *   Auxiliary data for Signed Distance Field support (body).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include "ftsdf.h"
+#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
+   *
+   */
+
+  /*
+   * Convert 16.16 fixed point values to the desired output format.
+   * In this case we reduce 16.16 fixed point values to normalized
+   * 8-bit values.
+   *
+   * The `max_value` in the parameter is the maximum value in the
+   * distance field map and is equal to the spread.  We normalize
+   * the distances using this value instead of computing the maximum
+   * value for the entire bitmap.
+   *
+   * You can use this function to map the 16.16 signed values to any
+   * format required.  Do note that the output buffer is 8-bit, so only
+   * use an 8-bit format for `FT_SDFFormat`, or increase the buffer size in
+   * `ftsdfrend.c`.
+   */
+  FT_LOCAL_DEF( FT_SDFFormat )
+  map_fixed_to_sdf( FT_16D16  dist,
+                    FT_16D16  max_value )
+  {
+    FT_SDFFormat  out;
+    FT_16D16      udist;
+
+
+    /* normalize the distance values */
+    dist = FT_DivFix( dist, max_value );
+
+    udist = dist < 0 ? -dist : dist;
+
+    /* Reduce the distance values to 8 bits.                   */
+    /*                                                         */
+    /* Since +1/-1 in 16.16 takes the 16th bit, we right-shift */
+    /* the number by 9 to make it fit into the 7-bit range.    */
+    /*                                                         */
+    /* One bit is reserved for the sign.                       */
+    udist >>= 9;
+
+    /* Since `char` can only store a maximum positive value    */
+    /* of 127 we need to make sure it does not wrap around and */
+    /* give a negative value.                                  */
+    if ( dist > 0 && udist > 127 )
+      udist = 127;
+    if ( dist < 0 && udist > 128 )
+      udist = 128;
+
+    /* Output the data; negative values are from [0, 127] and positive    */
+    /* from [128, 255].  One important thing is that negative values      */
+    /* are inverted here, that means [0, 128] maps to [-128, 0] linearly. */
+    /* More on that in `freetype.h` near the documentation of             */
+    /* `FT_RENDER_MODE_SDF`.                                              */
+    out = dist < 0 ? 128 - (FT_SDFFormat)udist
+                   : (FT_SDFFormat)udist + 128;
+
+    return out;
+  }
+
+
+  /*
+   * Invert the signed distance packed into the corresponding format.
+   * So if the values are negative they will become positive in the
+   * chosen format.
+   *
+   * [Note]: This function should only be used after converting the
+   *         16.16 signed distance values to `FT_SDFFormat`.  If that
+   *         conversion has not been done, then simply invert the sign
+   *         and use the above function to pack the values.
+   */
+  FT_LOCAL_DEF( FT_SDFFormat )
+  invert_sign( FT_SDFFormat  dist )
+  {
+    return 255 - dist;
+  }
+
+
+/* END */
diff --git a/src/sdf/ftsdfcommon.h b/src/sdf/ftsdfcommon.h
new file mode 100644
index 0000000..44f6bba
--- /dev/null
+++ b/src/sdf/ftsdfcommon.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+ *
+ * ftsdfcommon.h
+ *
+ *   Auxiliary data for Signed Distance Field support (specification).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+  /****************************************************
+   *
+   * This file contains common functions and properties
+   * for both the 'sdf' and 'bsdf' renderers.
+   *
+   */
+
+#ifndef FTSDFCOMMON_H_
+#define FTSDFCOMMON_H_
+
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
+#include <freetype/internal/ftobjs.h>
+
+
+FT_BEGIN_HEADER
+
+
+  /**************************************************************************
+   *
+   * default values (cannot be set individually for each renderer)
+   *
+   */
+
+  /* default spread value */
+#define DEFAULT_SPREAD  8
+  /* minimum spread supported by the renderer */
+#define MIN_SPREAD      2
+  /* maximum spread supported by the renderer */
+#define MAX_SPREAD      32
+
+
+  /**************************************************************************
+   *
+   * common definitions (cannot be set individually for each renderer)
+   *
+   */
+
+  /* If this macro is set to 1 the rasterizer uses squared distances for */
+  /* computation.  It can greatly improve the performance but there is a */
+  /* chance of overflow and artifacts.  You can safely use it up to a    */
+  /* pixel size of 128.                                                  */
+#ifndef USE_SQUARED_DISTANCES
+#define USE_SQUARED_DISTANCES  0
+#endif
+
+
+  /**************************************************************************
+   *
+   * common macros
+   *
+   */
+
+  /* convert int to 26.6 fixed-point   */
+#define FT_INT_26D6( x )   ( x * 64 )
+  /* convert int to 16.16 fixed-point  */
+#define FT_INT_16D16( x )  ( x * 65536 )
+  /* convert 26.6 to 16.16 fixed-point */
+#define FT_26D6_16D16( x ) ( x * 1024 )
+
+
+  /* Convenience macro to call a function; it  */
+  /* jumps to label `Exit` if an error occurs. */
+#define FT_CALL( x ) do                          \
+                     {                           \
+                       error = ( x );            \
+                       if ( error != FT_Err_Ok ) \
+                         goto Exit;              \
+                     } while ( 0 )
+
+
+  /*
+   * The macro `VECTOR_LENGTH_16D16` computes either squared distances or
+   * actual distances, depending on the value of `USE_SQUARED_DISTANCES`.
+   *
+   * By using squared distances the performance can be greatly improved but
+   * there is a risk of overflow.
+   */
+#if USE_SQUARED_DISTANCES
+#define VECTOR_LENGTH_16D16( v )  ( FT_MulFix( v.x, v.x ) + \
+                                    FT_MulFix( v.y, v.y ) )
+#else
+#define VECTOR_LENGTH_16D16( v )  FT_Vector_Length( &v )
+#endif
+
+
+  /**************************************************************************
+   *
+   * common typedefs
+   *
+   */
+
+  typedef FT_Vector FT_26D6_Vec;   /* with 26.6 fixed-point components  */
+  typedef FT_Vector FT_16D16_Vec;  /* with 16.16 fixed-point components */
+
+  typedef FT_Fixed  FT_16D16;      /* 16.16 fixed-point representation  */
+  typedef FT_Fixed  FT_26D6;       /* 26.6 fixed-point representation   */
+  typedef FT_Byte   FT_SDFFormat;  /* format to represent SDF data      */
+
+  typedef FT_BBox   FT_CBox;       /* control box of a curve            */
+
+
+  FT_LOCAL( FT_16D16 )
+  square_root( FT_16D16  val );
+
+  FT_LOCAL( FT_SDFFormat )
+  map_fixed_to_sdf( FT_16D16  dist,
+                    FT_16D16  max_value );
+
+  FT_LOCAL( FT_SDFFormat )
+  invert_sign( FT_SDFFormat  dist );
+
+
+FT_END_HEADER
+
+#endif /* FTSDFCOMMON_H_ */
+
+
+/* END */
diff --git a/src/sdf/ftsdferrs.h b/src/sdf/ftsdferrs.h
new file mode 100644
index 0000000..dbb113d
--- /dev/null
+++ b/src/sdf/ftsdferrs.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+ *
+ * ftsdferrs.h
+ *
+ *   Signed Distance Field error codes (specification only).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTSDFERRS_H_
+#define FTSDFERRS_H_
+
+#include <freetype/ftmoderr.h>
+
+#undef FTERRORS_H_
+
+#undef  FT_ERR_PREFIX
+#define FT_ERR_PREFIX  Sdf_Err_
+#define FT_ERR_BASE    FT_Mod_Err_Sdf
+
+#include <freetype/fterrors.h>
+
+#endif /* FTSDFERRS_H_ */
+
+
+/* END */
diff --git a/src/sdf/ftsdfrend.c b/src/sdf/ftsdfrend.c
new file mode 100644
index 0000000..30f2e62
--- /dev/null
+++ b/src/sdf/ftsdfrend.c
@@ -0,0 +1,614 @@
+/****************************************************************************
+ *
+ * ftsdfrend.c
+ *
+ *   Signed Distance Field renderer interface (body).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/services/svprop.h>
+#include <freetype/ftoutln.h>
+#include <freetype/ftbitmap.h>
+#include "ftsdfrend.h"
+#include "ftsdf.h"
+
+#include "ftsdferrs.h"
+
+
+  /**************************************************************************
+   *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  sdf
+
+
+  /**************************************************************************
+   *
+   * macros and default property values
+   *
+   */
+#define SDF_RENDERER( rend )  ( (SDF_Renderer)rend )
+
+
+  /**************************************************************************
+   *
+   * for setting properties
+   *
+   */
+
+  /* property setter function */
+  static FT_Error
+  sdf_property_set( FT_Module    module,
+                    const char*  property_name,
+                    const void*  value,
+                    FT_Bool      value_is_string )
+  {
+    FT_Error      error  = FT_Err_Ok;
+    SDF_Renderer  render = SDF_RENDERER( FT_RENDERER( module ) );
+
+    FT_UNUSED( value_is_string );
+
+
+    if ( ft_strcmp( property_name, "spread" ) == 0 )
+    {
+      FT_Int  val = *(const FT_Int*)value;
+
+
+      if ( val > MAX_SPREAD || val < MIN_SPREAD )
+      {
+        FT_TRACE0(( "[sdf] sdf_property_set:"
+                    " the `spread' property can have a value\n" ));
+        FT_TRACE0(( "                       "
+                    " within range [%d, %d] (value provided: %d)\n",
+                    MIN_SPREAD, MAX_SPREAD, val ));
+
+        error = FT_THROW( Invalid_Argument );
+        goto Exit;
+      }
+
+      render->spread = (FT_UInt)val;
+      FT_TRACE7(( "[sdf] sdf_property_set:"
+                  " updated property `spread' to %d\n", val ));
+    }
+
+    else if ( ft_strcmp( property_name, "flip_sign" ) == 0 )
+    {
+      FT_Int  val = *(const FT_Int*)value;
+
+
+      render->flip_sign = val ? 1 : 0;
+      FT_TRACE7(( "[sdf] sdf_property_set:"
+                  " updated property `flip_sign' to %d\n", val ));
+    }
+
+    else if ( ft_strcmp( property_name, "flip_y" ) == 0 )
+    {
+      FT_Int  val = *(const FT_Int*)value;
+
+
+      render->flip_y = val ? 1 : 0;
+      FT_TRACE7(( "[sdf] sdf_property_set:"
+                  " updated property `flip_y' to %d\n", val ));
+    }
+
+    else if ( ft_strcmp( property_name, "overlaps" ) == 0 )
+    {
+      FT_Bool  val = *(const FT_Bool*)value;
+
+
+      render->overlaps = val;
+      FT_TRACE7(( "[sdf] sdf_property_set:"
+                  " updated property `overlaps' to %d\n", val ));
+    }
+
+    else
+    {
+      FT_TRACE0(( "[sdf] sdf_property_set:"
+                  " missing property `%s'\n", property_name ));
+      error = FT_THROW( Missing_Property );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* property getter function */
+  static FT_Error
+  sdf_property_get( FT_Module    module,
+                    const char*  property_name,
+                    void*        value )
+  {
+    FT_Error      error  = FT_Err_Ok;
+    SDF_Renderer  render = SDF_RENDERER( FT_RENDERER( module ) );
+
+
+    if ( ft_strcmp( property_name, "spread" ) == 0 )
+    {
+      FT_UInt*  val = (FT_UInt*)value;
+
+
+      *val = render->spread;
+    }
+
+    else if ( ft_strcmp( property_name, "flip_sign" ) == 0 )
+    {
+      FT_Int*  val = (FT_Int*)value;
+
+
+      *val = render->flip_sign;
+    }
+
+    else if ( ft_strcmp( property_name, "flip_y" ) == 0 )
+    {
+      FT_Int*  val = (FT_Int*)value;
+
+
+      *val = render->flip_y;
+    }
+
+    else if ( ft_strcmp( property_name, "overlaps" ) == 0 )
+    {
+      FT_Int*  val = (FT_Int*)value;
+
+
+      *val = render->overlaps;
+    }
+
+    else
+    {
+      FT_TRACE0(( "[sdf] sdf_property_get:"
+                  " missing property `%s'\n", property_name ));
+      error = FT_THROW( Missing_Property );
+    }
+
+    return error;
+  }
+
+
+  FT_DEFINE_SERVICE_PROPERTIESREC(
+    sdf_service_properties,
+
+    (FT_Properties_SetFunc)sdf_property_set,        /* set_property */
+    (FT_Properties_GetFunc)sdf_property_get )       /* get_property */
+
+
+  FT_DEFINE_SERVICEDESCREC1(
+    sdf_services,
+
+    FT_SERVICE_ID_PROPERTIES, &sdf_service_properties )
+
+
+  static FT_Module_Interface
+  ft_sdf_requester( FT_Renderer  render,
+                    const char*  module_interface )
+  {
+    FT_UNUSED( render );
+
+    return ft_service_list_lookup( sdf_services, module_interface );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  OUTLINE TO SDF CONVERTER                                           **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /**************************************************************************
+   *
+   * interface functions
+   *
+   */
+
+  static FT_Error
+  ft_sdf_init( FT_Renderer  render )
+  {
+    SDF_Renderer  sdf_render = SDF_RENDERER( render );
+
+
+    sdf_render->spread    = DEFAULT_SPREAD;
+    sdf_render->flip_sign = 0;
+    sdf_render->flip_y    = 0;
+    sdf_render->overlaps  = 0;
+
+    return FT_Err_Ok;
+  }
+
+
+  static void
+  ft_sdf_done( FT_Renderer  render )
+  {
+    FT_UNUSED( render );
+  }
+
+
+  /* generate signed distance field from a glyph's slot image */
+  static FT_Error
+  ft_sdf_render( FT_Renderer       module,
+                 FT_GlyphSlot      slot,
+                 FT_Render_Mode    mode,
+                 const FT_Vector*  origin )
+  {
+    FT_Error     error   = FT_Err_Ok;
+    FT_Outline*  outline = &slot->outline;
+    FT_Bitmap*   bitmap  = &slot->bitmap;
+    FT_Memory    memory  = NULL;
+    FT_Renderer  render  = NULL;
+
+    FT_Pos  x_shift = 0;
+    FT_Pos  y_shift = 0;
+
+    FT_Pos  x_pad = 0;
+    FT_Pos  y_pad = 0;
+
+    SDF_Raster_Params  params;
+    SDF_Renderer       sdf_module = SDF_RENDERER( module );
+
+
+    render = &sdf_module->root;
+    memory = render->root.memory;
+
+    /* check whether slot format is correct before rendering */
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_THROW( Invalid_Glyph_Format );
+      goto Exit;
+    }
+
+    /* check whether render mode is correct */
+    if ( mode != FT_RENDER_MODE_SDF )
+    {
+      error = FT_THROW( Cannot_Render_Glyph );
+      goto Exit;
+    }
+
+    /* deallocate the previously allocated bitmap */
+    if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+    {
+      FT_FREE( bitmap->buffer );
+      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+    }
+
+    /* preset the bitmap using the glyph's outline;         */
+    /* the sdf bitmap is similar to an anti-aliased bitmap  */
+    /* with a slightly bigger size and different pixel mode */
+    if ( ft_glyphslot_preset_bitmap( slot, FT_RENDER_MODE_NORMAL, origin ) )
+    {
+      error = FT_THROW( Raster_Overflow );
+      goto Exit;
+    }
+
+    /* the rows and pitch must be valid after presetting the */
+    /* bitmap using outline                                  */
+    if ( !bitmap->rows || !bitmap->pitch )
+    {
+      FT_ERROR(( "ft_sdf_render: failed to preset bitmap\n" ));
+
+      error = FT_THROW( Cannot_Render_Glyph );
+      goto Exit;
+    }
+
+    /* the padding will simply be equal to the `spread' */
+    x_pad = sdf_module->spread;
+    y_pad = sdf_module->spread;
+
+    /* apply the padding; will be in all the directions */
+    bitmap->rows  += y_pad * 2;
+    bitmap->width += x_pad * 2;
+
+    /* ignore the pitch, pixel mode and set custom */
+    bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
+    bitmap->pitch      = (int)( bitmap->width );
+    bitmap->num_grays  = 255;
+
+    /* allocate new buffer */
+    if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
+      goto Exit;
+
+    slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+
+    slot->bitmap_top  += y_pad;
+    slot->bitmap_left -= x_pad;
+
+    x_shift  = 64 * -slot->bitmap_left;
+    y_shift  = 64 * -slot->bitmap_top;
+    y_shift += 64 * (FT_Int)bitmap->rows;
+
+    if ( origin )
+    {
+      x_shift += origin->x;
+      y_shift += origin->y;
+    }
+
+    /* translate outline to render it into the bitmap */
+    if ( x_shift || y_shift )
+      FT_Outline_Translate( outline, x_shift, y_shift );
+
+    /* set up parameters */
+    params.root.target = bitmap;
+    params.root.source = outline;
+    params.root.flags  = FT_RASTER_FLAG_SDF;
+    params.spread      = sdf_module->spread;
+    params.flip_sign   = sdf_module->flip_sign;
+    params.flip_y      = sdf_module->flip_y;
+    params.overlaps    = sdf_module->overlaps;
+
+    /* render the outline */
+    error = render->raster_render( render->raster,
+                                   (const FT_Raster_Params*)&params );
+
+    /* transform the outline back to the original state */
+    if ( x_shift || y_shift )
+      FT_Outline_Translate( outline, -x_shift, -y_shift );
+
+  Exit:
+    if ( !error )
+    {
+      /* the glyph is successfully rendered to a bitmap */
+      slot->format = FT_GLYPH_FORMAT_BITMAP;
+    }
+    else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+    {
+      FT_FREE( bitmap->buffer );
+      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+    }
+
+    return error;
+  }
+
+
+  /* transform the glyph using matrix and/or delta */
+  static FT_Error
+  ft_sdf_transform( FT_Renderer       render,
+                    FT_GlyphSlot      slot,
+                    const FT_Matrix*  matrix,
+                    const FT_Vector*  delta )
+  {
+    FT_Error  error = FT_Err_Ok;
+
+
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( matrix )
+      FT_Outline_Transform( &slot->outline, matrix );
+
+    if ( delta )
+      FT_Outline_Translate( &slot->outline, delta->x, delta->y );
+
+  Exit:
+    return error;
+  }
+
+
+  /* return the control box of a glyph's outline */
+  static void
+  ft_sdf_get_cbox( FT_Renderer   render,
+                   FT_GlyphSlot  slot,
+                   FT_BBox*      cbox )
+  {
+    FT_ZERO( cbox );
+
+    if ( slot->format == render->glyph_format )
+      FT_Outline_Get_CBox( &slot->outline, cbox );
+  }
+
+
+  /* set render specific modes or attributes */
+  static FT_Error
+  ft_sdf_set_mode( FT_Renderer  render,
+                   FT_ULong     mode_tag,
+                   FT_Pointer   data )
+  {
+    /* pass it to the rasterizer */
+    return render->clazz->raster_class->raster_set_mode( render->raster,
+                                                         mode_tag,
+                                                         data );
+  }
+
+
+  FT_DEFINE_RENDERER(
+    ft_sdf_renderer_class,
+
+    FT_MODULE_RENDERER,
+    sizeof ( SDF_Renderer_Module ),
+
+    "sdf",
+    0x10000L,
+    0x20000L,
+
+    NULL,
+
+    (FT_Module_Constructor)ft_sdf_init,
+    (FT_Module_Destructor) ft_sdf_done,
+    (FT_Module_Requester)  ft_sdf_requester,
+
+    FT_GLYPH_FORMAT_OUTLINE,
+
+    (FT_Renderer_RenderFunc)   ft_sdf_render,     /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_sdf_transform,  /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_sdf_get_cbox,   /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_sdf_set_mode,   /* set_mode        */
+
+    (FT_Raster_Funcs*)&ft_sdf_raster              /* raster_class    */
+  )
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  BITMAP TO SDF CONVERTER                                            **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* generate signed distance field from glyph's bitmap */
+  static FT_Error
+  ft_bsdf_render( FT_Renderer       module,
+                  FT_GlyphSlot      slot,
+                  FT_Render_Mode    mode,
+                  const FT_Vector*  origin )
+  {
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = NULL;
+
+    FT_Bitmap*   bitmap  = &slot->bitmap;
+    FT_Renderer  render  = NULL;
+    FT_Bitmap    target;
+
+    FT_Pos  x_pad = 0;
+    FT_Pos  y_pad = 0;
+
+    SDF_Raster_Params  params;
+    SDF_Renderer       sdf_module = SDF_RENDERER( module );
+
+
+    /* initialize the bitmap in case any error occurs */
+    FT_Bitmap_Init( &target );
+
+    render = &sdf_module->root;
+    memory = render->root.memory;
+
+    /* check whether slot format is correct before rendering */
+    if ( slot->format != render->glyph_format )
+    {
+      error = FT_THROW( Invalid_Glyph_Format );
+      goto Exit;
+    }
+
+    /* check whether render mode is correct */
+    if ( mode != FT_RENDER_MODE_SDF )
+    {
+      error = FT_THROW( Cannot_Render_Glyph );
+      goto Exit;
+    }
+
+    if ( origin )
+    {
+      FT_ERROR(( "ft_bsdf_render: can't translate the bitmap\n" ));
+
+      error = FT_THROW( Unimplemented_Feature );
+      goto Exit;
+    }
+
+    /* Do not generate SDF if the bitmap is not owned by the       */
+    /* glyph: it might be that the source buffer is already freed. */
+    if ( !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
+    {
+      FT_ERROR(( "ft_bsdf_render: can't generate SDF from"
+                 " unowned source bitmap\n" ));
+
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( !bitmap->rows || !bitmap->pitch )
+    {
+      FT_ERROR(( "ft_bsdf_render: invalid bitmap size\n" ));
+
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    FT_Bitmap_New( &target );
+
+    /* padding will simply be equal to `spread` */
+    x_pad = sdf_module->spread;
+    y_pad = sdf_module->spread;
+
+    /* apply padding, which extends to all directions */
+    target.rows  = bitmap->rows  + y_pad * 2;
+    target.width = bitmap->width + x_pad * 2;
+
+    /* set up the target bitmap */
+    target.pixel_mode = FT_PIXEL_MODE_GRAY;
+    target.pitch      = (int)( target.width );
+    target.num_grays  = 255;
+
+    if ( FT_ALLOC_MULT( target.buffer, target.rows, target.pitch ) )
+      goto Exit;
+
+    /* set up parameters */
+    params.root.target = &target;
+    params.root.source = bitmap;
+    params.root.flags  = FT_RASTER_FLAG_SDF;
+    params.spread      = sdf_module->spread;
+    params.flip_sign   = sdf_module->flip_sign;
+    params.flip_y      = sdf_module->flip_y;
+
+    error = render->raster_render( render->raster,
+                                   (const FT_Raster_Params*)&params );
+
+  Exit:
+    if ( !error )
+    {
+      /* the glyph is successfully converted to a SDF */
+      if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+      {
+        FT_FREE( bitmap->buffer );
+        slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+      }
+
+      slot->bitmap           = target;
+      slot->bitmap_top      += y_pad;
+      slot->bitmap_left     -= x_pad;
+      slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+    }
+    else if ( target.buffer )
+      FT_FREE( target.buffer );
+
+    return error;
+  }
+
+
+  FT_DEFINE_RENDERER(
+    ft_bitmap_sdf_renderer_class,
+
+    FT_MODULE_RENDERER,
+    sizeof ( SDF_Renderer_Module ),
+
+    "bsdf",
+    0x10000L,
+    0x20000L,
+
+    NULL,
+
+    (FT_Module_Constructor)ft_sdf_init,
+    (FT_Module_Destructor) ft_sdf_done,
+    (FT_Module_Requester)  ft_sdf_requester,
+
+    FT_GLYPH_FORMAT_BITMAP,
+
+    (FT_Renderer_RenderFunc)   ft_bsdf_render,    /* render_glyph    */
+    (FT_Renderer_TransformFunc)ft_sdf_transform,  /* transform_glyph */
+    (FT_Renderer_GetCBoxFunc)  ft_sdf_get_cbox,   /* get_glyph_cbox  */
+    (FT_Renderer_SetModeFunc)  ft_sdf_set_mode,   /* set_mode        */
+
+    (FT_Raster_Funcs*)&ft_bitmap_sdf_raster       /* raster_class    */
+  )
+
+
+/* END */
diff --git a/src/sdf/ftsdfrend.h b/src/sdf/ftsdfrend.h
new file mode 100644
index 0000000..bc88707
--- /dev/null
+++ b/src/sdf/ftsdfrend.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+ *
+ * ftsdfrend.h
+ *
+ *   Signed Distance Field renderer interface (specification).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef FTSDFREND_H_
+#define FTSDFREND_H_
+
+#include <freetype/ftrender.h>
+#include <freetype/ftmodapi.h>
+#include <freetype/internal/ftobjs.h>
+
+FT_BEGIN_HEADER
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   SDF_Renderer_Module
+   *
+   * @description:
+   *   This struct extends the native renderer struct `FT_RendererRec`.  It
+   *   is basically used to store various parameters required by the
+   *   renderer and some additional parameters that can be used to tweak the
+   *   output of the renderer.
+   *
+   * @fields:
+   *   root ::
+   *     The native rendere struct.
+   *
+   *   spread ::
+   *     This is an essential parameter/property required by the renderer.
+   *     `spread` defines the maximum unsigned value that is present in the
+   *     final SDF output.  For the default value check file
+   *     `ftsdfcommon.h`.
+   *
+   *   flip_sign ::
+   *     By default positive values indicate positions inside of contours,
+   *     i.e., filled by a contour.  If this property is true then that
+   *     output will be the opposite of the default, i.e., negative values
+   *     indicate positions inside of contours.
+   *
+   *   flip_y ::
+   *     Setting this parameter to true makes the output image flipped
+   *     along the y-axis.
+   *
+   *   overlaps ::
+   *     Set this to true to generate SDF for glyphs having overlapping
+   *     contours.  The overlapping support is limited to glyphs that do not
+   *     have self-intersecting contours.  Also, removing overlaps require a
+   *     considerable amount of extra memory; additionally, it will not work
+   *     if generating SDF from bitmap.
+   *
+   * @note:
+   *   All properties except `overlaps` are valid for both the 'sdf' and
+   *   'bsdf' renderers.
+   *
+   */
+  typedef struct  SDF_Renderer_Module_
+  {
+    FT_RendererRec  root;
+    FT_UInt         spread;
+    FT_Bool         flip_sign;
+    FT_Bool         flip_y;
+    FT_Bool         overlaps;
+
+  } SDF_Renderer_Module, *SDF_Renderer;
+
+
+  /**************************************************************************
+   *
+   * @renderer:
+   *   ft_sdf_renderer_class
+   *
+   * @description:
+   *   Renderer to convert @FT_Outline to signed distance fields.
+   *
+   */
+  FT_DECLARE_RENDERER( ft_sdf_renderer_class )
+
+
+  /**************************************************************************
+   *
+   * @renderer:
+   *   ft_bitmap_sdf_renderer_class
+   *
+   * @description:
+   *   This is not exactly a renderer; it is just a converter that
+   *   transforms bitmaps to signed distance fields.
+   *
+   * @note:
+   *   This is not a separate module, it is part of the 'sdf' module.
+   *
+   */
+  FT_DECLARE_RENDERER( ft_bitmap_sdf_renderer_class )
+
+
+FT_END_HEADER
+
+#endif /* FTSDFREND_H_ */
+
+
+/* END */
diff --git a/src/sdf/module.mk b/src/sdf/module.mk
new file mode 100644
index 0000000..6be4b0c
--- /dev/null
+++ b/src/sdf/module.mk
@@ -0,0 +1,29 @@
+#
+# FreeType 2 Signed Distance Field module definition
+#
+
+
+# Copyright (C) 2020-2021 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+FTMODULE_H_COMMANDS += SDF_RENDERER
+FTMODULE_H_COMMANDS += BSDF_RENDERER
+
+define SDF_RENDERER
+$(OPEN_DRIVER) FT_Renderer_Class, ft_sdf_renderer_class $(CLOSE_DRIVER)
+$(ECHO_DRIVER)sdf       $(ECHO_DRIVER_DESC)signed distance field renderer$(ECHO_DRIVER_DONE)
+endef
+
+define BSDF_RENDERER
+$(OPEN_DRIVER) FT_Renderer_Class, ft_bitmap_sdf_renderer_class $(CLOSE_DRIVER)
+$(ECHO_DRIVER)bsdf      $(ECHO_DRIVER_DESC)bitmap to signed distance field converter$(ECHO_DRIVER_DONE)
+endef
+
+#EOF
diff --git a/src/sdf/rules.mk b/src/sdf/rules.mk
new file mode 100644
index 0000000..7e7e4fb
--- /dev/null
+++ b/src/sdf/rules.mk
@@ -0,0 +1,78 @@
+#
+# FreeType 2 Signed Distance Field driver configuration rules
+#
+
+
+# Copyright (C) 2020-2021 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT.  By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+
+# sdf driver directory
+#
+SDF_DIR := $(SRC_DIR)/sdf
+
+
+# compilation flags for the driver
+#
+SDF_COMPILE := $(CC) $(ANSIFLAGS)                            \
+                     $I$(subst /,$(COMPILER_SEP),$(SDF_DIR)) \
+                     $(INCLUDE_FLAGS)                        \
+                     $(FT_CFLAGS)
+
+
+# sdf driver sources (i.e., C files)
+#
+SDF_DRV_SRC := $(SDF_DIR)/ftsdfrend.c   \
+               $(SDF_DIR)/ftsdf.c       \
+               $(SDF_DIR)/ftbsdf.c      \
+               $(SDF_DIR)/ftsdfcommon.c
+
+
+# sdf driver headers
+#
+SDF_DRV_H := $(SDF_DIR)/ftsdfrend.h   \
+             $(SDF_DIR)/ftsdf.h       \
+             $(SDF_DIR)/ftsdferrs.h   \
+             $(SDF_DIR)/ftsdfcommon.h
+
+
+# sdf driver object(s)
+#
+#   SDF_DRV_OBJ_M is used during `multi' builds.
+#   SDF_DRV_OBJ_S is used during `single' builds.
+#
+SDF_DRV_OBJ_M := $(SDF_DRV_SRC:$(SDF_DIR)/%.c=$(OBJ_DIR)/%.$O)
+SDF_DRV_OBJ_S := $(OBJ_DIR)/sdf.$O
+
+
+# sdf driver source file for single build
+#
+SDF_DRV_SRC_S := $(SDF_DIR)/sdf.c
+
+
+# sdf driver - single object
+#
+$(SDF_DRV_OBJ_S): $(SDF_DRV_SRC_S) $(SDF_DRV_SRC) \
+                  $(FREETYPE_H) $(SDF_DRV_H)
+	$(SDF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(SDF_DRV_SRC_S))
+
+
+# sdf driver - multiple objects
+#
+$(OBJ_DIR)/%.$O: $(SDF_DIR)/%.c $(FREETYPE_H) $(SDF_DRV_H)
+	$(SDF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
+
+
+# update main driver list
+#
+DRV_OBJS_S += $(SDF_DRV_OBJ_S)
+DRV_OBJS_M += $(SDF_DRV_OBJ_M)
+
+
+# EOF
diff --git a/src/sdf/sdf.c b/src/sdf/sdf.c
new file mode 100644
index 0000000..1bc3fc3
--- /dev/null
+++ b/src/sdf/sdf.c
@@ -0,0 +1,29 @@
+/****************************************************************************
+ *
+ * sdf.c
+ *
+ *   FreeType Signed Distance Field renderer module component (body only).
+ *
+ * Copyright (C) 2020-2021 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Written by Anuj Verma.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include "ftsdfrend.c"
+#include "ftsdfcommon.c"
+#include "ftbsdf.c"
+#include "ftsdf.c"
+
+
+/* END */
diff --git a/src/sfnt/module.mk b/src/sfnt/module.mk
index 0f459d8..eabd48f 100644
--- a/src/sfnt/module.mk
+++ b/src/sfnt/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
index f550161..02fe374 100644
--- a/src/sfnt/pngshim.c
+++ b/src/sfnt/pngshim.c
@@ -4,7 +4,7 @@
  *
  *   PNG Bitmap glyph support.
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * Google, Inc.
  * Written by Stuart Gill and Behdad Esfahbod.
  *
@@ -270,7 +270,10 @@
 
     int         bitdepth, color_type, interlace;
     FT_Int      i;
-    png_byte*  *rows = NULL; /* pacify compiler */
+
+    /* `rows` gets modified within a 'setjmp' scope; */
+    /* we thus need the `volatile` keyword.          */
+    png_byte* *volatile  rows = NULL;
 
 
     if ( x_offset < 0 ||
@@ -427,7 +430,7 @@
         goto DestroyExit;
     }
 
-    if ( FT_NEW_ARRAY( rows, imgHeight ) )
+    if ( FT_QNEW_ARRAY( rows, imgHeight ) )
     {
       error = FT_THROW( Out_Of_Memory );
       goto DestroyExit;
@@ -438,11 +441,11 @@
 
     png_read_image( png, rows );
 
-    FT_FREE( rows );
-
     png_read_end( png, info );
 
   DestroyExit:
+    /* even if reading fails with longjmp, rows must be freed */
+    FT_FREE( rows );
     png_destroy_read_struct( &png, &info, NULL );
     FT_Stream_Close( &stream );
 
diff --git a/src/sfnt/pngshim.h b/src/sfnt/pngshim.h
index 2d6e83d..89efd27 100644
--- a/src/sfnt/pngshim.h
+++ b/src/sfnt/pngshim.h
@@ -4,7 +4,7 @@
  *
  *   PNG Bitmap glyph support.
  *
- * Copyright (C) 2013-2020 by
+ * Copyright (C) 2013-2021 by
  * Google, Inc.
  * Written by Stuart Gill and Behdad Esfahbod.
  *
diff --git a/src/sfnt/rules.mk b/src/sfnt/rules.mk
index f56ef06..d41305c 100644
--- a/src/sfnt/rules.mk
+++ b/src/sfnt/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index 0460339..d1d01c9 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
  *
  *   High-level SFNT driver interface (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -501,7 +501,7 @@
     FT_UNUSED( error );
 
 
-    if ( FT_ALLOC( result, entry->stringLength / 2 + 1 ) )
+    if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) )
       return NULL;
 
     if ( FT_STREAM_SEEK( entry->stringOffset ) ||
@@ -560,7 +560,7 @@
     FT_UNUSED( error );
 
 
-    if ( FT_ALLOC( result, entry->stringLength + 1 ) )
+    if ( FT_QALLOC( result, entry->stringLength + 1 ) )
       return NULL;
 
     if ( FT_STREAM_SEEK( entry->stringOffset ) ||
@@ -868,8 +868,8 @@
         result[len] = '\0';
 
         FT_TRACE0(( "sfnt_get_var_ps_name:"
-                    " Shortening variation PS name prefix\n"
-                    "                     "
+                    " Shortening variation PS name prefix\n" ));
+        FT_TRACE0(( "                     "
                     " to %d characters\n", len ));
       }
 
@@ -920,16 +920,16 @@
         if ( !subfamily_name )
         {
           FT_TRACE1(( "sfnt_get_var_ps_name:"
-                      " can't construct named instance PS name;\n"
-                      "                     "
+                      " can't construct named instance PS name;\n" ));
+          FT_TRACE1(( "                     "
                       " trying to construct normal instance PS name\n" ));
           goto construct_instance_name;
         }
 
         /* after the prefix we have character `-' followed by the   */
         /* subfamily name (using only characters a-z, A-Z, and 0-9) */
-        if ( FT_ALLOC( result, face->var_postscript_prefix_len +
-                               1 + ft_strlen( subfamily_name ) + 1 ) )
+        if ( FT_QALLOC( result, face->var_postscript_prefix_len +
+                                1 + ft_strlen( subfamily_name ) + 1 ) )
           return NULL;
 
         ft_strcpy( result, face->var_postscript_prefix );
@@ -957,9 +957,9 @@
     construct_instance_name:
       axis = mm_var->axis;
 
-      if ( FT_ALLOC( result,
-                     face->var_postscript_prefix_len +
-                       num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) )
+      if ( FT_QALLOC( result,
+                      face->var_postscript_prefix_len +
+                        num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) )
         return NULL;
 
       p = result;
@@ -993,6 +993,7 @@
         if ( t != ' ' && ft_isalnum( t ) )
           *p++ = t;
       }
+      *p++ = '\0';
     }
 
   check_length:
@@ -1213,6 +1214,8 @@
 #define PUT_COLOR_LAYERS( a )  NULL
 #endif
 
+#define PUT_COLOR_LAYERS_V1( a )  PUT_COLOR_LAYERS( a )
+
 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
 #define PUT_PS_NAMES( a )  a
 #else
@@ -1271,9 +1274,9 @@
                             /* TT_Free_Table_Func      free_eblc       */
 
     PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike     ),
-                   /* TT_Set_SBit_Strike_Func      set_sbit_strike     */
+                  /* TT_Set_SBit_Strike_Func      set_sbit_strike      */
     PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
-                   /* TT_Load_Strike_Metrics_Func  load_strike_metrics */
+                  /* TT_Load_Strike_Metrics_Func  load_strike_metrics  */
 
     PUT_COLOR_LAYERS( tt_face_load_cpal ),
                             /* TT_Load_Table_Func      load_cpal       */
@@ -1287,6 +1290,18 @@
                             /* TT_Set_Palette_Func     set_palette     */
     PUT_COLOR_LAYERS( tt_face_get_colr_layer ),
                             /* TT_Get_Colr_Layer_Func  get_colr_layer  */
+
+    PUT_COLOR_LAYERS_V1( tt_face_get_colr_glyph_paint ),
+              /* TT_Get_Color_Glyph_Paint_Func    get_colr_glyph_paint */
+    PUT_COLOR_LAYERS_V1( tt_face_get_color_glyph_clipbox ),
+              /* TT_Get_Color_Glyph_ClipBox_Func  get_clipbox          */
+    PUT_COLOR_LAYERS_V1( tt_face_get_paint_layers ),
+              /* TT_Get_Paint_Layers_Func         get_paint_layers     */
+    PUT_COLOR_LAYERS_V1( tt_face_get_colorline_stops ),
+              /* TT_Get_Paint                     get_paint            */
+    PUT_COLOR_LAYERS_V1( tt_face_get_paint ),
+              /* TT_Get_Colorline_Stops_Func      get_colorline_stops  */
+
     PUT_COLOR_LAYERS( tt_face_colr_blend_layer ),
                             /* TT_Blend_Colr_Func      colr_blend      */
 
diff --git a/src/sfnt/sfdriver.h b/src/sfnt/sfdriver.h
index 1ac2706..8d5b5ce 100644
--- a/src/sfnt/sfdriver.h
+++ b/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level SFNT driver interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/sferrors.h b/src/sfnt/sferrors.h
index 55c3e76..78e6f03 100644
--- a/src/sfnt/sferrors.h
+++ b/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
  *
  *   SFNT error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c
index 471239f..97692cd 100644
--- a/src/sfnt/sfnt.c
+++ b/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
  *
  *   Single object library component.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index 39460be..7891024 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
  *
  *   SFNT object management (base).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -65,7 +65,7 @@
 
     len = (FT_UInt)entry->stringLength / 2;
 
-    if ( FT_NEW_ARRAY( string, len + 1 ) )
+    if ( FT_QNEW_ARRAY( string, len + 1 ) )
       return NULL;
 
     for ( n = 0; n < len; n++ )
@@ -100,7 +100,7 @@
 
     len = (FT_UInt)entry->stringLength;
 
-    if ( FT_NEW_ARRAY( string, len + 1 ) )
+    if ( FT_QNEW_ARRAY( string, len + 1 ) )
       return NULL;
 
     for ( n = 0; n < len; n++ )
@@ -360,17 +360,27 @@
       FT_FRAME_END
     };
 
+#ifndef FT_CONFIG_OPTION_USE_BROTLI
+    FT_UNUSED( face_instance_index );
+    FT_UNUSED( woff2_num_faces );
+#endif
+
 
     face->ttc_header.tag     = 0;
     face->ttc_header.version = 0;
     face->ttc_header.count   = 0;
 
+#if defined( FT_CONFIG_OPTION_USE_ZLIB )   || \
+    defined( FT_CONFIG_OPTION_USE_BROTLI )
   retry:
+#endif
+
     offset = FT_STREAM_POS();
 
     if ( FT_READ_ULONG( tag ) )
       return error;
 
+#ifdef FT_CONFIG_OPTION_USE_ZLIB
     if ( tag == TTAG_wOFF )
     {
       FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" ));
@@ -386,7 +396,9 @@
       stream = face->root.stream;
       goto retry;
     }
+#endif
 
+#ifdef FT_CONFIG_OPTION_USE_BROTLI
     if ( tag == TTAG_wOF2 )
     {
       FT_TRACE2(( "sfnt_open_font: file is a WOFF2; synthesizing SFNT\n" ));
@@ -405,6 +417,7 @@
       stream = face->root.stream;
       goto retry;
     }
+#endif
 
     if ( tag != 0x00010000UL &&
          tag != TTAG_ttcf    &&
@@ -446,7 +459,7 @@
         return FT_THROW( Array_Too_Large );
 
       /* now read the offsets of each font in the file */
-      if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
+      if ( FT_QNEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
         return error;
 
       if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
@@ -464,7 +477,7 @@
       face->ttc_header.version = 1 << 16;
       face->ttc_header.count   = 1;
 
-      if ( FT_NEW( face->ttc_header.offsets ) )
+      if ( FT_QNEW( face->ttc_header.offsets ) )
         return error;
 
       face->ttc_header.offsets[0] = offset;
@@ -643,8 +656,8 @@
        */
 
       if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) &&
-           !( FT_ALLOC( default_values, num_axes * 4 )  ||
-              FT_ALLOC( instance_values, num_axes * 4 ) )      )
+           !( FT_QALLOC(  default_values, num_axes * 4 ) ||
+              FT_QALLOC( instance_values, num_axes * 4 ) )     )
       {
         /* the current stream position is 16 bytes after the table start */
         FT_ULong  array_start = FT_STREAM_POS() - 16 + offset;
@@ -820,7 +833,8 @@
     /* it doesn't contain outlines.                                */
     /*                                                             */
 
-    FT_TRACE2(( "sfnt_load_face: %p\n\n", (void *)face ));
+    FT_TRACE2(( "sfnt_load_face: %p\n", (void *)face ));
+    FT_TRACE2(( "\n" ));
 
     /* do we have outlines in there? */
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
@@ -1149,9 +1163,10 @@
         }
 
         /* synthesize Unicode charmap if one is missing */
-        if ( !has_unicode )
+        if ( !has_unicode                                &&
+             root->face_flags & FT_FACE_FLAG_GLYPH_NAMES )
         {
-          FT_CharMapRec cmaprec;
+          FT_CharMapRec  cmaprec;
 
 
           cmaprec.face        = root;
@@ -1207,7 +1222,7 @@
           /* of `FT_Face', we map `available_sizes' indices to strike    */
           /* indices                                                     */
           if ( FT_NEW_ARRAY( root->available_sizes, count ) ||
-               FT_NEW_ARRAY( sbit_strike_map, count ) )
+               FT_QNEW_ARRAY( sbit_strike_map, count ) )
             goto Exit;
 
           bsize_idx = 0;
@@ -1236,7 +1251,7 @@
           }
 
           /* reduce array size to the actually used elements */
-          (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx );
+          FT_MEM_QRENEW_ARRAY( sbit_strike_map, count, bsize_idx );
 
           /* from now on, all strike indices are mapped */
           /* using `sbit_strike_map'                    */
diff --git a/src/sfnt/sfobjs.h b/src/sfnt/sfobjs.h
index e8e3042..172c47e 100644
--- a/src/sfnt/sfobjs.h
+++ b/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
  *
  *   SFNT object management (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/sfwoff.c b/src/sfnt/sfwoff.c
index f0a32e1..422c816 100644
--- a/src/sfnt/sfwoff.c
+++ b/src/sfnt/sfwoff.c
@@ -4,7 +4,7 @@
  *
  *   WOFF format management (base).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -23,6 +23,9 @@
 #include <freetype/ftgzip.h>
 
 
+#ifdef FT_CONFIG_OPTION_USE_ZLIB
+
+
   /**************************************************************************
    *
    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
@@ -66,7 +69,7 @@
   }
 
 
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   compare_offsets( const void*  a,
                    const void*  b )
   {
@@ -109,7 +112,7 @@
     FT_ULong        sfnt_offset;
 
     FT_Int          nn;
-    FT_ULong        old_tag = 0;
+    FT_Tag          old_tag = 0;
 
     static const FT_Frame_Field  woff_header_fields[] =
     {
@@ -160,8 +163,8 @@
     }
 
     /* Don't trust `totalSfntSize' before thorough checks. */
-    if ( FT_ALLOC( sfnt, 12 + woff.num_tables * 16UL ) ||
-         FT_NEW( sfnt_stream )                         )
+    if ( FT_QALLOC( sfnt, 12 + woff.num_tables * 16UL ) ||
+         FT_NEW( sfnt_stream )                          )
       goto Exit;
 
     sfnt_header = sfnt;
@@ -198,9 +201,9 @@
          FT_NEW_ARRAY( indices, woff.num_tables ) )
       goto Exit;
 
-    FT_TRACE2(( "\n"
-                "  tag    offset    compLen  origLen  checksum\n"
-                "  -------------------------------------------\n" ));
+    FT_TRACE2(( "\n" ));
+    FT_TRACE2(( "  tag    offset    compLen  origLen  checksum\n" ));
+    FT_TRACE2(( "  -------------------------------------------\n" ));
 
     if ( FT_FRAME_ENTER( 20L * woff.num_tables ) )
       goto Exit;
@@ -360,8 +363,6 @@
       }
       else
       {
-#ifdef FT_CONFIG_OPTION_USE_ZLIB
-
         /* Uncompress with zlib. */
         FT_ULong  output_len = table->OrigLength;
 
@@ -377,13 +378,6 @@
           error = FT_THROW( Invalid_Table );
           goto Exit1;
         }
-
-#else /* !FT_CONFIG_OPTION_USE_ZLIB */
-
-        error = FT_THROW( Unimplemented_Feature );
-        goto Exit1;
-
-#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
       }
 
       FT_FRAME_EXIT();
@@ -433,5 +427,12 @@
 #undef WRITE_USHORT
 #undef WRITE_ULONG
 
+#else /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+  /* ANSI C doesn't like empty source files */
+  typedef int  _sfwoff_dummy;
+
+#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
+
 
 /* END */
diff --git a/src/sfnt/sfwoff.h b/src/sfnt/sfwoff.h
index d177ab1..3fbdac0 100644
--- a/src/sfnt/sfwoff.h
+++ b/src/sfnt/sfwoff.h
@@ -4,7 +4,7 @@
  *
  *   WOFFF format management (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -26,12 +26,15 @@
 
 FT_BEGIN_HEADER
 
+#ifdef FT_CONFIG_OPTION_USE_ZLIB
 
   FT_LOCAL( FT_Error )
   woff_open_font( FT_Stream  stream,
                   TT_Face    face );
 
 
+#endif
+
 FT_END_HEADER
 
 #endif /* SFWOFF_H_ */
diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c
index 5c8202f..5ee8dea 100644
--- a/src/sfnt/sfwoff2.c
+++ b/src/sfnt/sfwoff2.c
@@ -4,7 +4,7 @@
  *
  *   WOFF2 format management (base).
  *
- * Copyright (C) 2019-2020 by
+ * Copyright (C) 2019-2021 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -26,8 +26,6 @@
 
 #include <brotli/decode.h>
 
-#endif
-
 
   /**************************************************************************
    *
@@ -101,15 +99,15 @@
   }
 
 
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   compare_tags( const void*  a,
                 const void*  b )
   {
     WOFF2_Table  table1 = *(WOFF2_Table*)a;
     WOFF2_Table  table2 = *(WOFF2_Table*)b;
 
-    FT_ULong  tag1 = table1->Tag;
-    FT_ULong  tag2 = table2->Tag;
+    FT_Tag  tag1 = table1->Tag;
+    FT_Tag  tag2 = table2->Tag;
 
 
     if ( tag1 > tag2 )
@@ -316,8 +314,6 @@
                     const FT_Byte*  src,
                     FT_ULong        src_size )
   {
-#ifdef FT_CONFIG_OPTION_USE_BROTLI
-
     /* this cast is only of importance on 32bit systems; */
     /* we don't validate it                              */
     FT_Offset            uncompressed_size = (FT_Offset)dst_size;
@@ -338,20 +334,13 @@
 
     FT_TRACE2(( "woff2_decompress: Brotli stream decompressed.\n" ));
     return FT_Err_Ok;
-
-#else /* !FT_CONFIG_OPTION_USE_BROTLI */
-
-    FT_ERROR(( "woff2_decompress: Brotli support not available.\n" ));
-    return FT_THROW( Unimplemented_Feature );
-
-#endif /* !FT_CONFIG_OPTION_USE_BROTLI */
   }
 
 
   static WOFF2_Table
   find_table( WOFF2_Table*  tables,
               FT_UShort     num_tables,
-              FT_ULong      tag )
+              FT_Tag        tag )
   {
     FT_Int  i;
 
@@ -790,7 +779,7 @@
       goto Fail;
 
     loca_buf_size = loca_values_size * offset_size;
-    if ( FT_NEW_ARRAY( loca_buf, loca_buf_size ) )
+    if ( FT_QNEW_ARRAY( loca_buf, loca_buf_size ) )
       goto Fail;
 
     dst = loca_buf;
@@ -1852,11 +1841,10 @@
          FT_NEW_ARRAY( indices, woff2.num_tables ) )
       goto Exit;
 
-    FT_TRACE2((
-      "\n"
-      "  tag    flags    transform  origLen   transformLen   offset\n"
-      "  -----------------------------------------------------------\n" ));
-   /* "  XXXX  XXXXXXXX  XXXXXXXX   XXXXXXXX    XXXXXXXX    XXXXXXXX" */
+    FT_TRACE2(( "\n" ));
+    FT_TRACE2(( "  tag    flags    transform  origLen   transformLen   offset\n" ));
+    FT_TRACE2(( "  -----------------------------------------------------------\n" ));
+             /* "  XXXX  XXXXXXXX  XXXXXXXX   XXXXXXXX    XXXXXXXX    XXXXXXXX" */
 
     for ( nn = 0; nn < woff2.num_tables; nn++ )
     {
@@ -2119,8 +2107,8 @@
 
 
       /* Create a temporary array. */
-      if ( FT_NEW_ARRAY( temp_indices,
-                         ttc_font->num_tables ) )
+      if ( FT_QNEW_ARRAY( temp_indices,
+                          ttc_font->num_tables ) )
         goto Exit;
 
       FT_TRACE4(( "Storing tables for TTC face index %d.\n", face_index ));
@@ -2128,9 +2116,9 @@
         temp_indices[nn] = indices[ttc_font->table_indices[nn]];
 
       /* Resize array to required size. */
-      if ( FT_RENEW_ARRAY( indices,
-                           woff2.num_tables,
-                           ttc_font->num_tables ) )
+      if ( FT_QRENEW_ARRAY( indices,
+                            woff2.num_tables,
+                            ttc_font->num_tables ) )
         goto Exit;
 
       for ( nn = 0; nn < ttc_font->num_tables; nn++ )
@@ -2170,8 +2158,8 @@
     }
 
     /* Write sfnt header. */
-    if ( FT_ALLOC( sfnt, sfnt_size ) ||
-         FT_NEW( sfnt_stream )       )
+    if ( FT_QALLOC( sfnt, sfnt_size ) ||
+         FT_NEW( sfnt_stream )        )
       goto Exit;
 
     sfnt_header = sfnt;
@@ -2209,6 +2197,25 @@
               sizeof ( WOFF2_Table ),
               compare_tags );
 
+    /* reject fonts that have multiple tables with the same tag */
+    for ( nn = 1; nn < woff2.num_tables; nn++ )
+    {
+      FT_Tag  tag = indices[nn]->Tag;
+
+
+      if ( tag == indices[nn - 1]->Tag )
+      {
+        FT_ERROR(( "woff2_open_font:"
+                   " multiple tables with tag `%c%c%c%c'.\n",
+                   (FT_Char)( tag >> 24 ),
+                   (FT_Char)( tag >> 16 ),
+                   (FT_Char)( tag >> 8  ),
+                   (FT_Char)( tag       ) ));
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+    }
+
     if ( woff2.uncompressed_size < 1 )
     {
       error = FT_THROW( Invalid_Table );
@@ -2223,8 +2230,8 @@
     }
 
     /* Allocate memory for uncompressed table data. */
-    if ( FT_ALLOC( uncompressed_buf, woff2.uncompressed_size ) ||
-         FT_FRAME_ENTER( woff2.totalCompressedSize )           )
+    if ( FT_QALLOC( uncompressed_buf, woff2.uncompressed_size ) ||
+         FT_FRAME_ENTER( woff2.totalCompressedSize )            )
       goto Exit;
 
     /* Uncompress the stream. */
@@ -2333,5 +2340,12 @@
 #undef BBOX_STREAM
 #undef INSTRUCTION_STREAM
 
+#else /* !FT_CONFIG_OPTION_USE_BROTLI */
+
+  /* ANSI C doesn't like empty source files */
+  typedef int  _sfwoff2_dummy;
+
+#endif /* !FT_CONFIG_OPTION_USE_BROTLI */
+
 
 /* END */
diff --git a/src/sfnt/sfwoff2.h b/src/sfnt/sfwoff2.h
index 798f66b..fa78b02 100644
--- a/src/sfnt/sfwoff2.h
+++ b/src/sfnt/sfwoff2.h
@@ -4,7 +4,7 @@
  *
  *   WOFFF2 format management (specification).
  *
- * Copyright (C) 2019-2020 by
+ * Copyright (C) 2019-2021 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -26,6 +26,7 @@
 
 FT_BEGIN_HEADER
 
+#ifdef FT_CONFIG_OPTION_USE_BROTLI
 
   /* Leave the first byte open to store `flag_byte'. */
 #define WOFF2_FLAGS_TRANSFORM   1 << 8
@@ -66,6 +67,7 @@
                    FT_Int*    face_index,
                    FT_Long*   num_faces );
 
+#endif /* FT_CONFIG_OPTION_USE_BROTLI */
 
 FT_END_HEADER
 
diff --git a/src/sfnt/ttbdf.c b/src/sfnt/ttbdf.c
index a287d3a..b8d9473 100644
--- a/src/sfnt/ttbdf.c
+++ b/src/sfnt/ttbdf.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded BDF properties (body).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttbdf.h b/src/sfnt/ttbdf.h
index e60c01c..91271d9 100644
--- a/src/sfnt/ttbdf.h
+++ b/src/sfnt/ttbdf.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded BDF properties (specification).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
index 556a712..b369d83 100644
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
  *
  *   TrueType character mapping table (cmap) support (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -916,6 +916,16 @@
       length = (FT_UInt)( valid->limit - table );
     }
 
+    /* it also happens that the `length' field is too small; */
+    /* this is easy to correct                               */
+    if ( length < (FT_UInt)( valid->limit - table ) )
+    {
+      if ( valid->level >= FT_VALIDATE_PARANOID )
+        FT_INVALID_DATA;
+
+      length = (FT_UInt)( valid->limit - table );
+    }
+
     if ( length < 16 )
       FT_INVALID_TOO_SHORT;
 
diff --git a/src/sfnt/ttcmap.h b/src/sfnt/ttcmap.h
index c7d7c21..504fc95 100644
--- a/src/sfnt/ttcmap.h
+++ b/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
  *
  *   TrueType character mapping table (cmap) support (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttcmapc.h b/src/sfnt/ttcmapc.h
index 2e4ce50..4e6cd46 100644
--- a/src/sfnt/ttcmapc.h
+++ b/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
  *
  *   TT CMAP classes definitions (specification only).
  *
- * Copyright (C) 2009-2020 by
+ * Copyright (C) 2009-2021 by
  * Oran Agra and Mickey Gabel.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c
index 9025e35..8f5cc8b 100644
--- a/src/sfnt/ttcolr.c
+++ b/src/sfnt/ttcolr.c
@@ -4,8 +4,8 @@
  *
  *   TrueType and OpenType colored glyph layer support (body).
  *
- * Copyright (C) 2018-2020 by
- * David Turner, Robert Wilhelm, and Werner Lemberg.
+ * Copyright (C) 2018-2021 by
+ * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
  *
@@ -27,10 +27,12 @@
    */
 
 
+#include <freetype/internal/ftcalc.h>
 #include <freetype/internal/ftdebug.h>
 #include <freetype/internal/ftstream.h>
 #include <freetype/tttags.h>
 #include <freetype/ftcolor.h>
+#include <freetype/config/integer-types.h>
 
 
 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS
@@ -39,12 +41,27 @@
 
 
   /* NOTE: These are the table sizes calculated through the specs. */
-#define BASE_GLYPH_SIZE            6U
-#define LAYER_SIZE                 4U
-#define COLR_HEADER_SIZE          14U
+#define BASE_GLYPH_SIZE                   6U
+#define BASE_GLYPH_PAINT_RECORD_SIZE      6U
+#define LAYER_V1_LIST_PAINT_OFFSET_SIZE   4U
+#define LAYER_V1_LIST_NUM_LAYERS_SIZE     4U
+#define COLOR_STOP_SIZE                   6U
+#define LAYER_SIZE                        4U
+#define COLR_HEADER_SIZE                 14U
 
 
-  typedef struct BaseGlyphRecord_
+  typedef enum  FT_PaintFormat_Internal_
+  {
+    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         = 18,
+    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM        = 20,
+    FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER = 22,
+    FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER        = 26,
+    FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER          = 30
+
+  } FT_PaintFormat_Internal;
+
+
+  typedef struct  BaseGlyphRecord_
   {
     FT_UShort  gid;
     FT_UShort  first_layer_index;
@@ -53,7 +70,16 @@
   } BaseGlyphRecord;
 
 
-  typedef struct Colr_
+  typedef struct  BaseGlyphV1Record_
+  {
+    FT_UShort  gid;
+    /* Offset from start of BaseGlyphV1List, i.e., from base_glyphs_v1. */
+    FT_ULong   paint_offset;
+
+  } BaseGlyphV1Record;
+
+
+  typedef struct  Colr_
   {
     FT_UShort  version;
     FT_UShort  num_base_glyphs;
@@ -62,7 +88,23 @@
     FT_Byte*  base_glyphs;
     FT_Byte*  layers;
 
-    /* The memory which backs up the `COLR' table. */
+    FT_ULong  num_base_glyphs_v1;
+    /* Points at beginning of BaseGlyphV1List. */
+    FT_Byte*  base_glyphs_v1;
+
+    FT_ULong  num_layers_v1;
+    FT_Byte*  layers_v1;
+
+    FT_Byte*  clip_list;
+
+    /*
+     * Paint tables start at the minimum of the end of the LayerList and the
+     * end of the BaseGlyphList.  Record this location in a field here for
+     * safety checks when accessing paint tables.
+     */
+    FT_Byte*  paints_start_v1;
+
+    /* The memory that backs up the `COLR' table. */
     void*     table;
     FT_ULong  table_size;
 
@@ -88,10 +130,14 @@
 
     FT_Byte*  table = NULL;
     FT_Byte*  p     = NULL;
+    /* Needed for reading array lengths in referenced tables. */
+    FT_Byte*  p1    = NULL;
 
     Colr*  colr = NULL;
 
     FT_ULong  base_glyph_offset, layer_offset;
+    FT_ULong  base_glyphs_offset_v1, num_base_glyphs_v1;
+    FT_ULong  layer_offset_v1, num_layers_v1, clip_list_offset;
     FT_ULong  table_size;
 
 
@@ -115,7 +161,7 @@
       goto NoColr;
 
     colr->version = FT_NEXT_USHORT( p );
-    if ( colr->version != 0 )
+    if ( colr->version != 0 && colr->version != 1 )
       goto InvalidTable;
 
     colr->num_base_glyphs = FT_NEXT_USHORT( p );
@@ -135,6 +181,66 @@
     if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
       goto InvalidTable;
 
+    if ( colr->version == 1 )
+    {
+      base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
+
+      if ( base_glyphs_offset_v1 >= table_size )
+        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 )
+        goto InvalidTable;
+
+      colr->num_base_glyphs_v1 = num_base_glyphs_v1;
+      colr->base_glyphs_v1     = p1;
+
+      layer_offset_v1 = FT_NEXT_ULONG( p );
+
+      if ( layer_offset_v1 >= table_size )
+        goto InvalidTable;
+
+      if ( layer_offset_v1 )
+      {
+        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 )
+          goto InvalidTable;
+
+        colr->num_layers_v1 = num_layers_v1;
+        colr->layers_v1     = p1;
+
+        colr->paints_start_v1 =
+            FT_MIN( colr->base_glyphs_v1 +
+                    colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE,
+                    colr->layers_v1 +
+                    colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE );
+      }
+      else
+      {
+        colr->num_layers_v1   = 0;
+        colr->layers_v1       = 0;
+        colr->paints_start_v1 =
+          colr->base_glyphs_v1 +
+          colr->num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE;
+      }
+
+      clip_list_offset = FT_NEXT_ULONG( p );
+
+      if ( clip_list_offset >= table_size )
+        goto InvalidTable;
+
+      if ( clip_list_offset )
+        colr->clip_list = (FT_Byte*)( table + clip_list_offset );
+      else
+        colr->clip_list = 0;
+    }
+
     colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset );
     colr->layers      = (FT_Byte*)( table + layer_offset      );
     colr->table       = table;
@@ -174,17 +280,17 @@
 
   static FT_Bool
   find_base_glyph_record( FT_Byte*          base_glyph_begin,
-                          FT_Int            num_base_glyph,
+                          FT_UInt           num_base_glyph,
                           FT_UInt           glyph_id,
                           BaseGlyphRecord*  record )
   {
-    FT_Int  min = 0;
-    FT_Int  max = num_base_glyph - 1;
+    FT_UInt  min = 0;
+    FT_UInt  max = num_base_glyph;
 
 
-    while ( min <= max )
+    while ( min < max )
     {
-      FT_Int    mid = min + ( max - min ) / 2;
+      FT_UInt   mid = min + ( max - min ) / 2;
       FT_Byte*  p   = base_glyph_begin + mid * BASE_GLYPH_SIZE;
 
       FT_UShort  gid = FT_NEXT_USHORT( p );
@@ -193,7 +299,7 @@
       if ( gid < glyph_id )
         min = mid + 1;
       else if (gid > glyph_id )
-        max = mid - 1;
+        max = mid;
       else
       {
         record->gid               = gid;
@@ -265,6 +371,747 @@
   }
 
 
+  static FT_Bool
+  read_color_line( FT_Byte*      color_line_p,
+                   FT_ColorLine  *colorline )
+  {
+    FT_Byte*        p = color_line_p;
+    FT_PaintExtend  paint_extend;
+
+
+    paint_extend = (FT_PaintExtend)FT_NEXT_BYTE( p );
+    if ( paint_extend > FT_COLR_PAINT_EXTEND_REFLECT )
+      return 0;
+
+    colorline->extend = paint_extend;
+
+    colorline->color_stop_iterator.num_color_stops    = FT_NEXT_USHORT( p );
+    colorline->color_stop_iterator.p                  = p;
+    colorline->color_stop_iterator.current_color_stop = 0;
+
+    return 1;
+  }
+
+
+  /*
+   * Read a paint offset for `FT_Paint*` objects that have them and check
+   * whether it is within reasonable limits within the font and the COLR
+   * table.
+   *
+   * Return 1 on success, 0 on failure.
+   */
+  static FT_Bool
+  get_child_table_pointer ( Colr*      colr,
+                            FT_Byte*   paint_base,
+                            FT_Byte**  p,
+                            FT_Byte**  child_table_pointer )
+  {
+    FT_UInt32  paint_offset;
+    FT_Byte*   child_table_p;
+
+
+    if ( !child_table_pointer )
+      return 0;
+
+    paint_offset = FT_NEXT_UOFF3( *p );
+    if ( !paint_offset )
+      return 0;
+
+    child_table_p = (FT_Byte*)( paint_base + paint_offset );
+
+    if ( child_table_p < colr->paints_start_v1                         ||
+         child_table_p >= ( (FT_Byte*)colr->table + colr->table_size ) )
+      return 0;
+
+    *child_table_pointer = child_table_p;
+    return 1;
+  }
+
+
+  static FT_Bool
+  read_paint( Colr*           colr,
+              FT_Byte*        p,
+              FT_COLR_Paint*  apaint )
+  {
+    FT_Byte*  paint_base     = p;
+    FT_Byte*  child_table_p  = NULL;
+
+
+    if ( !p || !colr || !colr->table )
+      return 0;
+
+    if ( p < colr->paints_start_v1                         ||
+         p >= ( (FT_Byte*)colr->table + colr->table_size ) )
+      return 0;
+
+    apaint->format = (FT_PaintFormat)FT_NEXT_BYTE( p );
+
+    if ( apaint->format >= FT_COLR_PAINT_FORMAT_MAX )
+      return 0;
+
+    if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_LAYERS )
+    {
+      /* Initialize layer iterator/ */
+      FT_Byte    num_layers;
+      FT_UInt32  first_layer_index;
+
+
+      num_layers = FT_NEXT_BYTE( p );
+      if ( num_layers > colr->num_layers_v1 )
+        return 0;
+
+      first_layer_index = FT_NEXT_ULONG( p );
+      if ( first_layer_index + num_layers > colr->num_layers_v1 )
+        return 0;
+
+      apaint->u.colr_layers.layer_iterator.num_layers = num_layers;
+      apaint->u.colr_layers.layer_iterator.layer      = 0;
+      /* TODO: Check whether pointer is outside colr? */
+      apaint->u.colr_layers.layer_iterator.p =
+        colr->layers_v1 +
+        LAYER_V1_LIST_NUM_LAYERS_SIZE +
+        LAYER_V1_LIST_PAINT_OFFSET_SIZE * first_layer_index;
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID )
+    {
+      apaint->u.solid.color.palette_index = FT_NEXT_USHORT( p );
+      apaint->u.solid.color.alpha         = FT_NEXT_SHORT( p );
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH )
+    {
+      apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p );
+
+      return 1;
+    }
+
+    /*
+     * Grouped below here are all paint formats that have an offset to a
+     * child paint table as the first entry (for example, a color line or a
+     * child paint table).  Retrieve that and determine whether that paint
+     * offset is valid first.
+     */
+
+    if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
+      return 0;
+
+    if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT )
+    {
+      if ( !read_color_line( child_table_p,
+                             &apaint->u.linear_gradient.colorline ) )
+        return 0;
+
+      /*
+       * In order to support variations expose these as FT_Fixed 16.16 values so
+       * that we can support fractional values after interpolation.
+       */
+      apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.linear_gradient.p1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT )
+    {
+      if ( !read_color_line( child_table_p,
+                             &apaint->u.radial_gradient.colorline ) )
+        return 0;
+
+      apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      apaint->u.radial_gradient.r0 = FT_NEXT_USHORT( p ) << 16;
+
+      apaint->u.radial_gradient.c1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.radial_gradient.c1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      apaint->u.radial_gradient.r1 = FT_NEXT_USHORT( p ) << 16;
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT )
+    {
+      if ( !read_color_line( child_table_p,
+                             &apaint->u.sweep_gradient.colorline ) )
+        return 0;
+
+      apaint->u.sweep_gradient.center.x =
+          INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.sweep_gradient.center.y =
+          INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      apaint->u.sweep_gradient.start_angle =
+          F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.sweep_gradient.end_angle =
+          F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      return 1;
+    }
+
+    if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH )
+    {
+      apaint->u.glyph.paint.p                     = child_table_p;
+      apaint->u.glyph.paint.insert_root_transform = 0;
+      apaint->u.glyph.glyphID                     = FT_NEXT_USHORT( p );
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORM )
+    {
+      apaint->u.transform.paint.p                     = child_table_p;
+      apaint->u.transform.paint.insert_root_transform = 0;
+
+      if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
+         return 0;
+
+      p = child_table_p;
+
+      /*
+       * The following matrix coefficients are encoded as
+       * OpenType 16.16 fixed-point values.
+       */
+      apaint->u.transform.affine.xx = FT_NEXT_LONG( p );
+      apaint->u.transform.affine.yx = FT_NEXT_LONG( p );
+      apaint->u.transform.affine.xy = FT_NEXT_LONG( p );
+      apaint->u.transform.affine.yy = FT_NEXT_LONG( p );
+      apaint->u.transform.affine.dx = FT_NEXT_LONG( p );
+      apaint->u.transform.affine.dy = FT_NEXT_LONG( p );
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE )
+    {
+      apaint->u.translate.paint.p                     = child_table_p;
+      apaint->u.translate.paint.insert_root_transform = 0;
+
+      apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      return 1;
+    }
+
+    else if ( apaint->format ==
+                FT_COLR_PAINTFORMAT_SCALE                         ||
+              (FT_PaintFormat_Internal)apaint->format ==
+                FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         ||
+              (FT_PaintFormat_Internal)apaint->format ==
+                FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM        ||
+              (FT_PaintFormat_Internal)apaint->format ==
+                FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER )
+    {
+      apaint->u.scale.paint.p                     = child_table_p;
+      apaint->u.scale.paint.insert_root_transform = 0;
+
+      /* All scale paints get at least one scale value. */
+      apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      /* Non-uniform ones read an extra y value. */
+      if ( apaint->format ==
+             FT_COLR_PAINTFORMAT_SCALE                 ||
+           (FT_PaintFormat_Internal)apaint->format ==
+             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER )
+        apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+      else
+        apaint->u.scale.scale_y = apaint->u.scale.scale_x;
+
+      /* Scale paints that have a center read center coordinates, */
+      /* otherwise the center is (0,0).                           */
+      if ( (FT_PaintFormat_Internal)apaint->format ==
+             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER         ||
+           (FT_PaintFormat_Internal)apaint->format ==
+             FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER )
+      {
+        apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
+        apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
+      }
+      else
+      {
+        apaint->u.scale.center_x = 0;
+        apaint->u.scale.center_y = 0;
+      }
+
+      /* FT 'COLR' v1 API output format always returns fully defined */
+      /* structs; we thus set the format to the public API value.    */
+      apaint->format = FT_COLR_PAINTFORMAT_SCALE;
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE ||
+              (FT_PaintFormat_Internal)apaint->format ==
+                FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER )
+    {
+      apaint->u.rotate.paint.p                     = child_table_p;
+      apaint->u.rotate.paint.insert_root_transform = 0;
+
+      apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      if ( (FT_PaintFormat_Internal)apaint->format ==
+           FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER )
+      {
+        apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+        apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      }
+      else
+      {
+        apaint->u.rotate.center_x = 0;
+        apaint->u.rotate.center_y = 0;
+      }
+
+      apaint->format = FT_COLR_PAINTFORMAT_ROTATE;
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW ||
+              (FT_PaintFormat_Internal)apaint->format ==
+                FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER )
+    {
+      apaint->u.skew.paint.p                     = child_table_p;
+      apaint->u.skew.paint.insert_root_transform = 0;
+
+      apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+      apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+
+      if ( (FT_PaintFormat_Internal)apaint->format ==
+           FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER )
+      {
+        apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+        apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+      }
+      else
+      {
+        apaint->u.skew.center_x = 0;
+        apaint->u.skew.center_y = 0;
+      }
+
+      apaint->format = FT_COLR_PAINTFORMAT_SKEW;
+
+      return 1;
+    }
+
+    else if ( apaint->format == FT_COLR_PAINTFORMAT_COMPOSITE )
+    {
+      FT_UInt  composite_mode;
+
+
+      apaint->u.composite.source_paint.p                     = child_table_p;
+      apaint->u.composite.source_paint.insert_root_transform = 0;
+
+      composite_mode = FT_NEXT_BYTE( p );
+      if ( composite_mode >= FT_COLR_COMPOSITE_MAX )
+        return 0;
+
+      apaint->u.composite.composite_mode = (FT_Composite_Mode)composite_mode;
+
+      if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
+         return 0;
+
+      apaint->u.composite.backdrop_paint.p =
+        child_table_p;
+      apaint->u.composite.backdrop_paint.insert_root_transform =
+        0;
+
+      return 1;
+    }
+
+    return 0;
+  }
+
+
+  static FT_Bool
+  find_base_glyph_v1_record( FT_Byte *           base_glyph_begin,
+                             FT_UInt             num_base_glyph,
+                             FT_UInt             glyph_id,
+                             BaseGlyphV1Record  *record )
+  {
+    FT_UInt  min = 0;
+    FT_UInt  max = num_base_glyph;
+
+
+    while ( min < max )
+    {
+      FT_UInt  mid = min + ( max - min ) / 2;
+
+      /*
+       * `base_glyph_begin` is the beginning of `BaseGlyphV1List`;
+       * skip `numBaseGlyphV1Records` by adding 4 to start binary search
+       * in the array of `BaseGlyphV1Record`.
+       */
+      FT_Byte  *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE;
+
+      FT_UShort  gid = FT_NEXT_USHORT( p );
+
+
+      if ( gid < glyph_id )
+        min = mid + 1;
+      else if (gid > glyph_id )
+        max = mid;
+      else
+      {
+        record->gid          = gid;
+        record->paint_offset = FT_NEXT_ULONG ( p );
+        return 1;
+      }
+    }
+
+    return 0;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  tt_face_get_colr_glyph_paint( TT_Face                  face,
+                                FT_UInt                  base_glyph,
+                                FT_Color_Root_Transform  root_transform,
+                                FT_OpaquePaint*          opaque_paint )
+  {
+    Colr*              colr = (Colr*)face->colr;
+    BaseGlyphV1Record  base_glyph_v1_record;
+    FT_Byte*           p;
+
+    if ( !colr || !colr->table )
+      return 0;
+
+    if ( colr->version < 1 || !colr->num_base_glyphs_v1 ||
+         !colr->base_glyphs_v1 )
+      return 0;
+
+    if ( opaque_paint->p )
+      return 0;
+
+    if ( !find_base_glyph_v1_record( colr->base_glyphs_v1,
+                                     colr->num_base_glyphs_v1,
+                                     base_glyph,
+                                     &base_glyph_v1_record ) )
+      return 0;
+
+    if ( !base_glyph_v1_record.paint_offset                   ||
+         base_glyph_v1_record.paint_offset > colr->table_size )
+      return 0;
+
+    p = (FT_Byte*)( colr->base_glyphs_v1 +
+                    base_glyph_v1_record.paint_offset );
+    if ( p >= ( (FT_Byte*)colr->table + colr->table_size ) )
+      return 0;
+
+    opaque_paint->p = p;
+
+    if ( root_transform == FT_COLOR_INCLUDE_ROOT_TRANSFORM )
+      opaque_paint->insert_root_transform = 1;
+    else
+      opaque_paint->insert_root_transform = 0;
+
+    return 1;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  tt_face_get_color_glyph_clipbox( TT_Face      face,
+                                   FT_UInt      base_glyph,
+                                   FT_ClipBox*  clip_box )
+  {
+    Colr*  colr;
+
+    FT_Byte  *p, *p1, *clip_base;
+
+    FT_Byte    clip_list_format;
+    FT_ULong   num_clip_boxes, i;
+    FT_UShort  gid_start, gid_end;
+    FT_UInt32  clip_box_offset;
+    FT_Byte    format;
+
+    const FT_Byte  num_corners = 4;
+    FT_Vector      corners[4];
+    FT_Byte        j;
+    FT_BBox        font_clip_box;
+
+
+    colr = (Colr*)face->colr;
+    if ( !colr )
+      return 0;
+
+    if ( !colr->clip_list )
+      return 0;
+
+    p = colr->clip_list;
+
+    clip_base        = p;
+    clip_list_format = FT_NEXT_BYTE ( p );
+
+    /* Format byte used here to be able to upgrade ClipList for >16bit */
+    /* glyph ids; for now we can expect it to be 0. */
+    if ( !( clip_list_format == 1 ) )
+      return 0;
+
+    num_clip_boxes = FT_NEXT_ULONG( p );
+
+    for ( i = 0; i < num_clip_boxes; ++i )
+    {
+      gid_start       = FT_NEXT_USHORT( p );
+      gid_end         = FT_NEXT_USHORT( p );
+      clip_box_offset = FT_NEXT_UOFF3( p );
+
+      if ( base_glyph >= gid_start && base_glyph <= gid_end )
+      {
+        p1 = (FT_Byte*)( clip_base + clip_box_offset );
+
+        if ( p1 >= ( (FT_Byte*)colr->table + colr->table_size ) )
+          return 0;
+
+        format = FT_NEXT_BYTE( p1 );
+
+        if ( format > 1 )
+          return 0;
+
+        /* `face->root.size->metrics.x_scale` and `y_scale` are factors   */
+        /* that scale a font unit value in integers to a 26.6 fixed value */
+        /* according to the requested size, see for example               */
+        /* `ft_recompute_scaled_metrics`.                                 */
+        font_clip_box.xMin = FT_MulFix( FT_NEXT_SHORT( p1 ),
+                                        face->root.size->metrics.x_scale );
+        font_clip_box.yMin = FT_MulFix( FT_NEXT_SHORT( p1 ),
+                                        face->root.size->metrics.x_scale );
+        font_clip_box.xMax = FT_MulFix( FT_NEXT_SHORT( p1 ),
+                                        face->root.size->metrics.x_scale );
+        font_clip_box.yMax = FT_MulFix( FT_NEXT_SHORT( p1 ),
+                                        face->root.size->metrics.x_scale );
+
+        /* Make 4 corner points (xMin, yMin), (xMax, yMax) and transform */
+        /* them.  If we we would only transform two corner points and    */
+        /* span a rectangle based on those, the rectangle may become too */
+        /* small to cover the glyph.                                     */
+        corners[0].x = font_clip_box.xMin;
+        corners[1].x = font_clip_box.xMin;
+        corners[2].x = font_clip_box.xMax;
+        corners[3].x = font_clip_box.xMax;
+
+        corners[0].y = font_clip_box.yMin;
+        corners[1].y = font_clip_box.yMax;
+        corners[2].y = font_clip_box.yMax;
+        corners[3].y = font_clip_box.yMin;
+
+        for ( j = 0; j < num_corners; ++j )
+        {
+          if ( face->root.internal->transform_flags & 1 )
+            FT_Vector_Transform( &corners[j],
+                                 &face->root.internal->transform_matrix );
+
+          if ( face->root.internal->transform_flags & 2 )
+          {
+            corners[j].x += face->root.internal->transform_delta.x;
+            corners[j].y += face->root.internal->transform_delta.y;
+          }
+        }
+
+        clip_box->bottom_left  = corners[0];
+        clip_box->top_left     = corners[1];
+        clip_box->top_right    = corners[2];
+        clip_box->bottom_right = corners[3];
+
+        return 1;
+      }
+    }
+
+    return 0;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  tt_face_get_paint_layers( TT_Face            face,
+                            FT_LayerIterator*  iterator,
+                            FT_OpaquePaint*    opaque_paint )
+  {
+    FT_Byte*   p             = NULL;
+    FT_Byte*   p_first_layer = NULL;
+    FT_Byte*   p_paint       = NULL;
+    FT_UInt32  paint_offset;
+
+    Colr*  colr;
+
+
+    if ( iterator->layer == iterator->num_layers )
+      return 0;
+
+    colr = (Colr*)face->colr;
+    if ( !colr )
+      return 0;
+
+    /*
+     * We have an iterator pointing at a paint offset as part of the
+     * `paintOffset` array in `LayerV1List`.
+     */
+    p = iterator->p;
+
+    /*
+     * First ensure that p is within COLRv1.
+     */
+    if ( p < colr->layers_v1                               ||
+         p >= ( (FT_Byte*)colr->table + colr->table_size ) )
+      return 0;
+
+    /*
+     * Do a cursor sanity check of the iterator.  Counting backwards from
+     * where it stands, we need to end up at a position after the beginning
+     * of the `LayerV1List` table and not after the end of the
+     * `LayerV1List`.
+     */
+    p_first_layer = p -
+                      iterator->layer * LAYER_V1_LIST_PAINT_OFFSET_SIZE -
+                      LAYER_V1_LIST_NUM_LAYERS_SIZE;
+    if ( p_first_layer < (FT_Byte*)colr->layers_v1 )
+      return 0;
+    if ( p_first_layer >= (FT_Byte*)(
+           colr->layers_v1 + LAYER_V1_LIST_NUM_LAYERS_SIZE +
+           colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ) )
+      return 0;
+
+    paint_offset =
+      FT_NEXT_ULONG( p );
+    opaque_paint->insert_root_transform =
+      0;
+
+    p_paint = (FT_Byte*)( colr->layers_v1 + paint_offset );
+
+    if ( p_paint < colr->paints_start_v1                         ||
+         p_paint >= ( (FT_Byte*)colr->table + colr->table_size ) )
+      return 0;
+
+    opaque_paint->p = p_paint;
+
+    iterator->p = p;
+
+    iterator->layer++;
+
+    return 1;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  tt_face_get_colorline_stops( TT_Face                face,
+                               FT_ColorStop*          color_stop,
+                               FT_ColorStopIterator  *iterator )
+  {
+    Colr*  colr = (Colr*)face->colr;
+
+    FT_Byte*  p;
+
+
+    if ( !colr || !colr->table )
+      return 0;
+
+    if ( iterator->current_color_stop >= iterator->num_color_stops )
+      return 0;
+
+    if ( iterator->p +
+           ( ( iterator->num_color_stops - iterator->current_color_stop ) *
+             COLOR_STOP_SIZE ) >
+         ( (FT_Byte *)colr->table + colr->table_size ) )
+      return 0;
+
+    /* Iterator points at first `ColorStop` of `ColorLine`. */
+    p = iterator->p;
+
+    color_stop->stop_offset = FT_NEXT_SHORT( p );
+
+    color_stop->color.palette_index = FT_NEXT_USHORT( p );
+
+    color_stop->color.alpha = FT_NEXT_SHORT( p );
+
+    iterator->p = p;
+    iterator->current_color_stop++;
+
+    return 1;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  tt_face_get_paint( TT_Face         face,
+                     FT_OpaquePaint  opaque_paint,
+                     FT_COLR_Paint*  paint )
+  {
+    Colr*           colr = (Colr*)face->colr;
+    FT_OpaquePaint  next_paint;
+    FT_Matrix       ft_root_scale;
+
+    if ( !colr || !colr->base_glyphs_v1 || !colr->table )
+      return 0;
+
+    if ( opaque_paint.insert_root_transform )
+    {
+      /* 'COLR' v1 glyph information is returned in unscaled coordinates,
+       * i.e., `FT_Size` is not applied or multiplied into the values.  When
+       * client applications draw color glyphs, they can request to include
+       * a top-level transform, which includes the active `x_scale` and
+       * `y_scale` information for scaling the glyph, as well the additional
+       * transform and translate configured through `FT_Set_Transform`.
+       * This allows client applications to apply this top-level transform
+       * to the graphics context first and only once, then have gradient and
+       * contour scaling applied correctly when performing the additional
+       * drawing operations for subsequenct paints.  Prepare this initial
+       * transform here.
+       */
+      paint->format = FT_COLR_PAINTFORMAT_TRANSFORM;
+
+      next_paint.p                     = opaque_paint.p;
+      next_paint.insert_root_transform = 0;
+      paint->u.transform.paint         = next_paint;
+
+      /* `x_scale` and `y_scale` are in 26.6 format, representing the scale
+       * factor to get from font units to requested size.  However, expected
+       * return values are in 16.16, so we shift accordingly with rounding.
+       */
+      ft_root_scale.xx = ( face->root.size->metrics.x_scale + 32 ) >> 6;
+      ft_root_scale.xy = 0;
+      ft_root_scale.yx = 0;
+      ft_root_scale.yy = ( face->root.size->metrics.y_scale + 32 ) >> 6;
+
+      if ( face->root.internal->transform_flags & 1 )
+        FT_Matrix_Multiply( &face->root.internal->transform_matrix,
+                            &ft_root_scale );
+
+      paint->u.transform.affine.xx = ft_root_scale.xx;
+      paint->u.transform.affine.xy = ft_root_scale.xy;
+      paint->u.transform.affine.yx = ft_root_scale.yx;
+      paint->u.transform.affine.yy = ft_root_scale.yy;
+
+      /* The translation is specified in 26.6 format and, according to the
+       * documentation of `FT_Set_Translate`, is performed on the character
+       * size given in the last call to `FT_Set_Char_Size`.  The
+       * 'PaintTransform' paint table's `FT_Affine23` format expects
+       * values in 16.16 format, thus we need to shift by 10 bits.
+       */
+      if ( face->root.internal->transform_flags & 2 )
+      {
+        paint->u.transform.affine.dx =
+          face->root.internal->transform_delta.x * ( 1 << 10 );
+        paint->u.transform.affine.dy =
+          face->root.internal->transform_delta.y * ( 1 << 10 );
+      }
+      else
+      {
+        paint->u.transform.affine.dx = 0;
+        paint->u.transform.affine.dy = 0;
+      }
+
+      return 1;
+    }
+
+    return read_paint( colr, opaque_paint.p, paint );
+  }
+
+
   FT_LOCAL_DEF( FT_Error )
   tt_face_colr_blend_layer( TT_Face       face,
                             FT_UInt       color_index,
diff --git a/src/sfnt/ttcolr.h b/src/sfnt/ttcolr.h
index 6412162..b81e4cb 100644
--- a/src/sfnt/ttcolr.h
+++ b/src/sfnt/ttcolr.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType colored glyph layer support (specification).
  *
- * Copyright (C) 2018-2020 by
+ * Copyright (C) 2018-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
@@ -42,6 +42,32 @@
                           FT_UInt           *acolor_index,
                           FT_LayerIterator*  iterator );
 
+  FT_LOCAL( FT_Bool )
+  tt_face_get_colr_glyph_paint( TT_Face                  face,
+                                FT_UInt                  base_glyph,
+                                FT_Color_Root_Transform  root_transform,
+                                FT_OpaquePaint*          paint );
+
+  FT_LOCAL( FT_Bool )
+  tt_face_get_color_glyph_clipbox( TT_Face      face,
+                                   FT_UInt      base_glyph,
+                                   FT_ClipBox*  clip_box );
+
+  FT_LOCAL( FT_Bool )
+  tt_face_get_paint_layers( TT_Face            face,
+                            FT_LayerIterator*  iterator,
+                            FT_OpaquePaint*    paint );
+
+  FT_LOCAL( FT_Bool )
+  tt_face_get_colorline_stops( TT_Face                face,
+                               FT_ColorStop*          color_stop,
+                               FT_ColorStopIterator*  iterator );
+
+  FT_LOCAL( FT_Bool )
+  tt_face_get_paint( TT_Face         face,
+                     FT_OpaquePaint  opaque_paint,
+                     FT_COLR_Paint*  paint );
+
   FT_LOCAL( FT_Error )
   tt_face_colr_blend_layer( TT_Face       face,
                             FT_UInt       color_index,
diff --git a/src/sfnt/ttcpal.c b/src/sfnt/ttcpal.c
index 9c514ba..a0d84bc 100644
--- a/src/sfnt/ttcpal.c
+++ b/src/sfnt/ttcpal.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType color palette support (body).
  *
- * Copyright (C) 2018-2020 by
+ * Copyright (C) 2018-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/src/sfnt/ttcpal.h b/src/sfnt/ttcpal.h
index b544be6..1c55868 100644
--- a/src/sfnt/ttcpal.h
+++ b/src/sfnt/ttcpal.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType color palette support (specification).
  *
- * Copyright (C) 2018-2020 by
+ * Copyright (C) 2018-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c
index d4a70c7..bb1922c 100644
--- a/src/sfnt/ttkern.c
+++ b/src/sfnt/ttkern.c
@@ -5,7 +5,7 @@
  *   Load the basic TrueType kerning table.  This doesn't handle
  *   kerning data within the GPOS table at the moment.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttkern.h b/src/sfnt/ttkern.h
index f44b5bd..3d8f1e8 100644
--- a/src/sfnt/ttkern.h
+++ b/src/sfnt/ttkern.h
@@ -5,7 +5,7 @@
  *   Load the basic TrueType kerning table.  This doesn't handle
  *   kerning data within the GPOS table at the moment.
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index 4b46f41..51416d8 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
  *   Load the basic TrueType tables, i.e., tables that can be either in
  *   TTF or OTF fonts (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -416,9 +416,9 @@
          FT_FRAME_ENTER( sfnt.num_tables * 16L ) )
       goto Exit;
 
-    FT_TRACE2(( "\n"
-                "  tag    offset    length   checksum\n"
-                "  ----------------------------------\n" ));
+    FT_TRACE2(( "\n" ));
+    FT_TRACE2(( "  tag    offset    length   checksum\n" ));
+    FT_TRACE2(( "  ----------------------------------\n" ));
 
     valid_entries = 0;
     for ( nn = 0; nn < sfnt.num_tables; nn++ )
@@ -505,7 +505,8 @@
 
     FT_FRAME_EXIT();
 
-    FT_TRACE2(( "table directory loaded\n\n" ));
+    FT_TRACE2(( "table directory loaded\n" ));
+    FT_TRACE2(( "\n" ));
 
   Exit:
     return error;
@@ -794,8 +795,8 @@
       if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )
       {
         FT_TRACE0(( "tt_face_load_maxp:"
-                    " too much twilight points in `maxp' table;\n"
-                    "                  "
+                    " too much twilight points in `maxp' table;\n" ));
+        FT_TRACE0(( "                  "
                     " some glyphs might be rendered incorrectly\n" ));
 
         maxProfile->maxTwilightPoints = 0xFFFFU - 4;
@@ -836,6 +837,8 @@
     FT_ULong      table_pos, table_len;
     FT_ULong      storage_start, storage_limit;
     TT_NameTable  table;
+    TT_Name       names    = NULL;
+    TT_LangTag    langTags = NULL;
 
     static const FT_Frame_Field  name_table_fields[] =
     {
@@ -916,13 +919,13 @@
       storage_start += 2 + 4 * table->numLangTagRecords;
 
       /* allocate language tag records array */
-      if ( FT_NEW_ARRAY( table->langTags, table->numLangTagRecords ) ||
-           FT_FRAME_ENTER( table->numLangTagRecords * 4 )            )
+      if ( FT_QNEW_ARRAY( langTags, table->numLangTagRecords ) ||
+           FT_FRAME_ENTER( table->numLangTagRecords * 4 )      )
         goto Exit;
 
       /* load language tags */
       {
-        TT_LangTag  entry = table->langTags;
+        TT_LangTag  entry = langTags;
         TT_LangTag  limit = FT_OFFSET( entry, table->numLangTagRecords );
 
 
@@ -938,7 +941,13 @@
             /* invalid entry; ignore it */
             entry->stringLength = 0;
           }
+
+          /* mark the string as not yet loaded */
+          entry->string = NULL;
         }
+
+        table->langTags = langTags;
+        langTags        = NULL;
       }
 
       FT_FRAME_EXIT();
@@ -947,14 +956,15 @@
     }
 
     /* allocate name records array */
-    if ( FT_NEW_ARRAY( table->names, table->numNameRecords ) ||
-         FT_FRAME_ENTER( table->numNameRecords * 12 )        )
+    if ( FT_QNEW_ARRAY( names, table->numNameRecords ) ||
+         FT_FRAME_ENTER( table->numNameRecords * 12 )  )
       goto Exit;
 
     /* load name records */
     {
-      TT_Name  entry = table->names;
+      TT_Name  entry = names;
       FT_UInt  count = table->numNameRecords;
+      FT_UInt  valid = 0;
 
 
       for ( ; count > 0; count-- )
@@ -987,15 +997,20 @@
           }
         }
 
+        /* mark the string as not yet converted */
+        entry->string = NULL;
+
+        valid++;
         entry++;
       }
 
       /* reduce array size to the actually used elements */
-      count = (FT_UInt)( entry - table->names );
-      (void)FT_RENEW_ARRAY( table->names,
-                            table->numNameRecords,
-                            count );
-      table->numNameRecords = count;
+      FT_MEM_QRENEW_ARRAY( names,
+                           table->numNameRecords,
+                           valid );
+      table->names          = names;
+      names                 = NULL;
+      table->numNameRecords = valid;
     }
 
     FT_FRAME_EXIT();
@@ -1004,6 +1019,8 @@
     face->num_names = (FT_UShort)table->numNameRecords;
 
   Exit:
+    FT_FREE( names );
+    FT_FREE( langTags );
     return error;
   }
 
@@ -1311,6 +1328,12 @@
     if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
       return error;
 
+    if ( post->FormatType != 0x00030000L &&
+         post->FormatType != 0x00025000L &&
+         post->FormatType != 0x00020000L &&
+         post->FormatType != 0x00010000L )
+      return FT_THROW( Invalid_Post_Table_Format );
+
     /* we don't load the glyph names, we do that in another */
     /* module (ttpost).                                     */
 
@@ -1410,8 +1433,8 @@
     FT_Error   error;
     FT_Memory  memory = stream->memory;
 
-    FT_UInt        j,num_ranges;
-    TT_GaspRange   gaspranges = NULL;
+    FT_UShort      j, num_ranges;
+    TT_GaspRange   gasp_ranges = NULL;
 
 
     /* the gasp table is optional */
@@ -1422,8 +1445,8 @@
     if ( FT_FRAME_ENTER( 4L ) )
       goto Exit;
 
-    face->gasp.version   = FT_GET_USHORT();
-    face->gasp.numRanges = FT_GET_USHORT();
+    face->gasp.version = FT_GET_USHORT();
+    num_ranges         = FT_GET_USHORT();
 
     FT_FRAME_EXIT();
 
@@ -1435,29 +1458,31 @@
       goto Exit;
     }
 
-    num_ranges = face->gasp.numRanges;
-    FT_TRACE3(( "numRanges: %u\n", num_ranges ));
+    FT_TRACE3(( "numRanges: %hu\n", num_ranges ));
 
-    if ( FT_QNEW_ARRAY( face->gasp.gaspRanges, num_ranges ) ||
-         FT_FRAME_ENTER( num_ranges * 4L )                  )
+    if ( FT_QNEW_ARRAY( gasp_ranges, num_ranges ) ||
+         FT_FRAME_ENTER( num_ranges * 4L )        )
       goto Exit;
 
-    gaspranges = face->gasp.gaspRanges;
-
     for ( j = 0; j < num_ranges; j++ )
     {
-      gaspranges[j].maxPPEM  = FT_GET_USHORT();
-      gaspranges[j].gaspFlag = FT_GET_USHORT();
+      gasp_ranges[j].maxPPEM  = FT_GET_USHORT();
+      gasp_ranges[j].gaspFlag = FT_GET_USHORT();
 
       FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
                   j,
-                  gaspranges[j].maxPPEM,
-                  gaspranges[j].gaspFlag ));
+                  gasp_ranges[j].maxPPEM,
+                  gasp_ranges[j].gaspFlag ));
     }
 
+    face->gasp.gaspRanges = gasp_ranges;
+    gasp_ranges           = NULL;
+    face->gasp.numRanges  = num_ranges;
+
     FT_FRAME_EXIT();
 
   Exit:
+    FT_FREE( gasp_ranges );
     return error;
   }
 
diff --git a/src/sfnt/ttload.h b/src/sfnt/ttload.h
index 4e53d8b..cab15cd 100644
--- a/src/sfnt/ttload.h
+++ b/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
  *   Load the basic TrueType tables, i.e., tables that can be either in
  *   TTF or OTF fonts (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index 0211233..7aece36 100644
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
  *
  *   Load the metrics tables common to TTF and OTF fonts (body).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttmtx.h b/src/sfnt/ttmtx.h
index dba65ca..270170d 100644
--- a/src/sfnt/ttmtx.h
+++ b/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
  *
  *   Load the metrics tables common to TTF and OTF fonts (specification).
  *
- * Copyright (C) 2006-2020 by
+ * Copyright (C) 2006-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index e93a4bf..b92ca5d 100644
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
  *   PostScript name table processing for TrueType and OpenType fonts
  *   (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -158,7 +158,7 @@
   static FT_Error
   load_format_20( TT_Face    face,
                   FT_Stream  stream,
-                  FT_ULong   post_limit )
+                  FT_ULong   post_len )
   {
     FT_Memory   memory = stream->memory;
     FT_Error    error;
@@ -168,6 +168,7 @@
 
     FT_UShort*  glyph_indices = NULL;
     FT_Char**   name_strings  = NULL;
+    FT_Byte*    strings       = NULL;
 
 
     if ( FT_READ_USHORT( num_glyphs ) )
@@ -179,7 +180,8 @@
     /* There already exist fonts which have more than 32768 glyph names */
     /* in this table, so the test for this threshold has been dropped.  */
 
-    if ( num_glyphs > face->max_profile.numGlyphs )
+    if ( num_glyphs > face->max_profile.numGlyphs  ||
+         (FT_ULong)num_glyphs * 2UL > post_len - 2 )
     {
       error = FT_THROW( Invalid_File_Format );
       goto Exit;
@@ -190,7 +192,7 @@
       FT_Int  n;
 
 
-      if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) ||
+      if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) ||
            FT_FRAME_ENTER( num_glyphs * 2L )          )
         goto Fail;
 
@@ -223,60 +225,56 @@
     }
 
     /* now load the name strings */
+    if ( num_names )
     {
       FT_UShort  n;
+      FT_ULong   p;
 
 
-      if ( FT_NEW_ARRAY( name_strings, num_names ) )
+      post_len -= (FT_ULong)num_glyphs * 2UL + 2;
+
+      if ( FT_QALLOC( strings, post_len + 1 )       ||
+           FT_STREAM_READ( strings, post_len )      ||
+           FT_QNEW_ARRAY( name_strings, num_names ) )
         goto Fail;
 
-      for ( n = 0; n < num_names; n++ )
+      /* convert from Pascal- to C-strings and set pointers */
+      for ( p = 0, n = 0; p < post_len && n < num_names; n++ )
       {
-        FT_UInt  len;
+        FT_UInt  len = strings[p];
 
 
-        if ( FT_STREAM_POS() >= post_limit )
-          break;
-        else
+        if ( len > 63U )
         {
-          FT_TRACE6(( "load_format_20: %ld byte left in post table\n",
-                      post_limit - FT_STREAM_POS() ));
-
-          if ( FT_READ_BYTE( len ) )
-            goto Fail1;
+          error = FT_THROW( Invalid_File_Format );
+          goto Fail;
         }
 
-        if ( len > post_limit                   ||
-             FT_STREAM_POS() > post_limit - len )
-        {
-          FT_Int  d = (FT_Int)post_limit - (FT_Int)FT_STREAM_POS();
-
-
-          FT_ERROR(( "load_format_20:"
-                     " exceeding string length (%d),"
-                     " truncating at end of post table (%d byte left)\n",
-                     len, d ));
-          len = (FT_UInt)FT_MAX( 0, d );
-        }
-
-        if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
-             FT_STREAM_READ( name_strings[n], len   ) )
-          goto Fail1;
-
-        name_strings[n][len] = '\0';
+        strings[p]      = 0;
+        name_strings[n] = (FT_Char*)strings + p + 1;
+        p              += len + 1;
       }
+      strings[post_len] = 0;
 
+      /* deal with missing or insufficient string data */
       if ( n < num_names )
       {
+        if ( post_len == 0 )
+        {
+          /* fake empty string */
+          if ( FT_QREALLOC( strings, 1, 2 ) )
+            goto Fail;
+
+          post_len          = 1;
+          strings[post_len] = 0;
+        }
+
         FT_ERROR(( "load_format_20:"
                    " all entries in post table are already parsed,"
                    " using NULL names for gid %d - %d\n",
                     n, num_names - 1 ));
         for ( ; n < num_names; n++ )
-          if ( FT_NEW_ARRAY( name_strings[n], 1 ) )
-            goto Fail1;
-          else
-            name_strings[n][0] = '\0';
+          name_strings[n] = (FT_Char*)strings + post_len;
       }
     }
 
@@ -292,17 +290,9 @@
     }
     return FT_Err_Ok;
 
-  Fail1:
-    {
-      FT_UShort  n;
-
-
-      for ( n = 0; n < num_names; n++ )
-        FT_FREE( name_strings[n] );
-    }
-
   Fail:
     FT_FREE( name_strings );
+    FT_FREE( strings );
     FT_FREE( glyph_indices );
 
   Exit:
@@ -313,7 +303,7 @@
   static FT_Error
   load_format_25( TT_Face    face,
                   FT_Stream  stream,
-                  FT_ULong   post_limit )
+                  FT_ULong   post_len )
   {
     FT_Memory  memory = stream->memory;
     FT_Error   error;
@@ -321,7 +311,7 @@
     FT_Int     num_glyphs;
     FT_Char*   offset_table = NULL;
 
-    FT_UNUSED( post_limit );
+    FT_UNUSED( post_len );
 
 
     if ( FT_READ_USHORT( num_glyphs ) )
@@ -336,7 +326,7 @@
       goto Exit;
     }
 
-    if ( FT_NEW_ARRAY( offset_table, num_glyphs )   ||
+    if ( FT_QNEW_ARRAY( offset_table, num_glyphs )  ||
          FT_STREAM_READ( offset_table, num_glyphs ) )
       goto Fail;
 
@@ -384,7 +374,6 @@
     FT_Error   error;
     FT_Fixed   format;
     FT_ULong   post_len;
-    FT_ULong   post_limit;
 
 
     /* get a stream for the face's resource */
@@ -395,8 +384,6 @@
     if ( error )
       goto Exit;
 
-    post_limit = FT_STREAM_POS() + post_len;
-
     format = face->postscript.FormatType;
 
     /* go to beginning of subtable */
@@ -404,10 +391,10 @@
       goto Exit;
 
     /* now read postscript table */
-    if ( format == 0x00020000L )
-      error = load_format_20( face, stream, post_limit );
-    else if ( format == 0x00025000L )
-      error = load_format_25( face, stream, post_limit );
+    if ( format == 0x00020000L && post_len >= 34 )
+      error = load_format_20( face, stream, post_len - 32 );
+    else if ( format == 0x00025000L && post_len >= 34 )
+      error = load_format_25( face, stream, post_len - 32 );
     else
       error = FT_THROW( Invalid_File_Format );
 
@@ -433,17 +420,19 @@
       if ( format == 0x00020000L )
       {
         TT_Post_20  table = &names->names.format_20;
-        FT_UShort   n;
 
 
         FT_FREE( table->glyph_indices );
         table->num_glyphs = 0;
 
-        for ( n = 0; n < table->num_names; n++ )
-          FT_FREE( table->glyph_names[n] );
+        if ( table->num_names )
+        {
+          table->glyph_names[0]--;
+          FT_FREE( table->glyph_names[0] );
 
-        FT_FREE( table->glyph_names );
-        table->num_names = 0;
+          FT_FREE( table->glyph_names );
+          table->num_names = 0;
+        }
       }
       else if ( format == 0x00025000L )
       {
diff --git a/src/sfnt/ttpost.h b/src/sfnt/ttpost.h
index 94c7d16..6d65b57 100644
--- a/src/sfnt/ttpost.h
+++ b/src/sfnt/ttpost.h
@@ -5,7 +5,7 @@
  *   PostScript name table processing for TrueType and OpenType fonts
  *   (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index 9dd4419..e9ba697 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded bitmap support (body).
  *
- * Copyright (C) 2005-2020 by
+ * Copyright (C) 2005-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Copyright 2013 by Google, Inc.
@@ -172,13 +172,17 @@
           goto Exit;
         }
 
+#ifdef FT_DEBUG_LEVEL_TRACE
         /* we currently don't support bit 1; however, it is better to */
         /* draw at least something...                                 */
         if ( flags == 3 )
+        {
           FT_TRACE1(( "tt_face_load_sbit_strikes:"
-                      " sbix overlay not supported yet\n"
-                      "                          "
+                      " sbix overlay not supported yet\n" ));
+          FT_TRACE1(( "                          "
                       " expect bad rendering results\n" ));
+        }
+#endif
 
         /*
          * Count the number of strikes available in the table.  We are a bit
@@ -240,8 +244,8 @@
     if ( !face->ebdt_size )
     {
       FT_TRACE2(( "tt_face_load_sbit_strikes:"
-                  " no embedded bitmap data table found;\n"
-                  "                          "
+                  " no embedded bitmap data table found;\n" ));
+      FT_TRACE2(( "                          "
                   " resetting number of strikes to zero\n" ));
       face->sbit_num_strikes = 0;
     }
@@ -345,8 +349,8 @@
           if ( metrics->ascender == 0 )
           {
             FT_TRACE2(( "tt_face_load_strike_metrics:"
-                        " sanitizing invalid ascender and descender\n"
-                        "                            "
+                        " sanitizing invalid ascender and descender\n" ));
+            FT_TRACE2(( "                            "
                         " values for strike %ld (%dppem, %dppem)\n",
                         strike_index,
                         metrics->x_ppem, metrics->y_ppem ));
@@ -374,8 +378,8 @@
         if ( metrics->height == 0 )
         {
           FT_TRACE2(( "tt_face_load_strike_metrics:"
-                      " sanitizing invalid height value\n"
-                      "                            "
+                      " sanitizing invalid height value\n" ));
+          FT_TRACE2(( "                            "
                       " for strike (%d, %d)\n",
                       metrics->x_ppem, metrics->y_ppem ));
           metrics->height    = metrics->y_ppem * 64;
diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h
index b867e43..7a0ed92 100644
--- a/src/sfnt/ttsbit.h
+++ b/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded bitmap support (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/sfnt/woff2tags.c b/src/sfnt/woff2tags.c
index fd9f2e6..fe8f5cf 100644
--- a/src/sfnt/woff2tags.c
+++ b/src/sfnt/woff2tags.c
@@ -4,7 +4,7 @@
  *
  *   WOFF2 Font table tags (base).
  *
- * Copyright (C) 2019-2020 by
+ * Copyright (C) 2019-2021 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -17,6 +17,9 @@
 
 
 #include <freetype/tttags.h>
+
+#ifdef FT_CONFIG_OPTION_USE_BROTLI
+
 #include "woff2tags.h"
 
   /*
@@ -28,10 +31,10 @@
    *
    * for details.
    */
-  FT_LOCAL_DEF( FT_ULong )
+  FT_LOCAL_DEF( FT_Tag )
   woff2_known_tags( FT_Byte  index )
   {
-    const FT_ULong  known_tags[63] =
+    static const FT_Tag  known_tags[63] =
     {
       FT_MAKE_TAG('c', 'm', 'a', 'p'),  /*  0  */
       FT_MAKE_TAG('h', 'e', 'a', 'd'),  /*  1  */
@@ -105,5 +108,12 @@
     return known_tags[index];
   }
 
+#else /* !FT_CONFIG_OPTION_USE_BROTLI */
+
+  /* ANSI C doesn't like empty source files */
+  typedef int  _woff2tags_dummy;
+
+#endif /* !FT_CONFIG_OPTION_USE_BROTLI */
+
 
 /* END */
diff --git a/src/sfnt/woff2tags.h b/src/sfnt/woff2tags.h
index c437c77..4ef0a65 100644
--- a/src/sfnt/woff2tags.h
+++ b/src/sfnt/woff2tags.h
@@ -2,9 +2,9 @@
  *
  * woff2tags.h
  *
- *   WOFFF2 Font table tags (specification).
+ *   WOFF2 Font table tags (specification).
  *
- * Copyright (C) 2019-2020 by
+ * Copyright (C) 2019-2021 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -26,10 +26,12 @@
 
 FT_BEGIN_HEADER
 
+#ifdef FT_CONFIG_OPTION_USE_BROTLI
 
-  FT_LOCAL( FT_ULong )
+  FT_LOCAL( FT_Tag )
   woff2_known_tags( FT_Byte  index );
 
+#endif
 
 FT_END_HEADER
 
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 681900f..d982c28 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
  *
  *   A new `perfect' anti-aliasing renderer (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -149,14 +149,10 @@
 #define FT_INT_MAX    INT_MAX
 #define FT_ULONG_MAX  ULONG_MAX
 
-#define ADD_LONG( a, b )                                    \
-          (long)( (unsigned long)(a) + (unsigned long)(b) )
-#define SUB_LONG( a, b )                                    \
-          (long)( (unsigned long)(a) - (unsigned long)(b) )
-#define MUL_LONG( a, b )                                    \
-          (long)( (unsigned long)(a) * (unsigned long)(b) )
-#define NEG_LONG( a )                                       \
-          (long)( -(unsigned long)(a) )
+#define ADD_INT( a, b )                                  \
+          (int)( (unsigned int)(a) + (unsigned int)(b) )
+
+#define FT_STATIC_BYTE_CAST( type, var )  (type)(unsigned char)(var)
 
 
 #define ft_memset   memset
@@ -168,10 +164,11 @@
 typedef ptrdiff_t  FT_PtrDist;
 
 
-#define ErrRaster_Invalid_Mode      -2
-#define ErrRaster_Invalid_Outline   -1
-#define ErrRaster_Invalid_Argument  -3
-#define ErrRaster_Memory_Overflow   -4
+#define Smooth_Err_Ok                    0
+#define Smooth_Err_Invalid_Outline      -1
+#define Smooth_Err_Cannot_Render_Glyph  -2
+#define Smooth_Err_Invalid_Argument     -3
+#define Smooth_Err_Raster_Overflow      -4
 
 #define FT_BEGIN_HEADER
 #define FT_END_HEADER
@@ -229,23 +226,26 @@
 #define FT_ERROR( varformat )   FT_Message varformat
 #endif
 
-#define FT_THROW( e )                               \
-          ( FT_Throw( FT_ERR_CAT( ErrRaster_, e ),  \
-                      __LINE__,                     \
-                      __FILE__ )                  | \
-            FT_ERR_CAT( ErrRaster_, e )           )
+#define FT_THROW( e )                                \
+          ( FT_Throw( FT_ERR_CAT( Smooth_Err_, e ),  \
+                      __LINE__,                      \
+                      __FILE__ )                   | \
+            FT_ERR_CAT( Smooth_Err_, e )           )
 
 #else /* !FT_DEBUG_LEVEL_TRACE */
 
 #define FT_TRACE5( x )  do { } while ( 0 )     /* nothing */
 #define FT_TRACE7( x )  do { } while ( 0 )     /* nothing */
 #define FT_ERROR( x )   do { } while ( 0 )     /* nothing */
-#define FT_THROW( e )   FT_ERR_CAT( ErrRaster_, e )
-
+#define FT_THROW( e )   FT_ERR_CAT( Smooth_Err_, e )
 
 #endif /* !FT_DEBUG_LEVEL_TRACE */
 
 
+#define FT_Trace_Enable()   do { } while ( 0 )  /* nothing */
+#define FT_Trace_Disable()  do { } while ( 0 )  /* nothing */
+
+
 #define FT_DEFINE_OUTLINE_FUNCS( class_,               \
                                  move_to_, line_to_,   \
                                  conic_to_, cubic_to_, \
@@ -278,6 +278,8 @@
 #else /* !STANDALONE_ */
 
 
+#include <ft2build.h>
+#include FT_CONFIG_CONFIG_H
 #include "ftgrays.h"
 #include <freetype/internal/ftobjs.h>
 #include <freetype/internal/ftdebug.h>
@@ -286,10 +288,6 @@
 
 #include "ftsmerrs.h"
 
-#define Smooth_Err_Invalid_Mode     Smooth_Err_Cannot_Render_Glyph
-#define Smooth_Err_Memory_Overflow  Smooth_Err_Out_Of_Memory
-#define ErrRaster_Memory_Overflow   Smooth_Err_Out_Of_Memory
-
 
 #endif /* !STANDALONE_ */
 
@@ -362,7 +360,7 @@
     }                                                              \
   FT_END_STMNT
 
-#ifdef  __arm__
+#if defined( __GNUC__ ) && __GNUC__ < 7 && defined( __arm__ )
   /* Work around a bug specific to GCC which make the compiler fail to */
   /* optimize a division and modulo operation on the same parameters   */
   /* into a single call to `__aeabi_idivmod'.  See                     */
@@ -382,14 +380,58 @@
 #endif /* __arm__ */
 
 
-  /* These macros speed up repetitive divisions by replacing them */
-  /* with multiplications and right shifts.                       */
-#define FT_UDIVPREP( c, b )                                        \
-  long  b ## _r = c ? (long)( FT_ULONG_MAX >> PIXEL_BITS ) / ( b ) \
-                    : 0
-#define FT_UDIV( a, b )                                                \
-  (TCoord)( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >>   \
-            ( sizeof( long ) * FT_CHAR_BIT - PIXEL_BITS ) )
+  /* Calculating coverages for a slanted line requires a division each */
+  /* time the line crosses from cell to cell.  These macros speed up   */
+  /* the repetitive divisions by replacing them with multiplications   */
+  /* and right shifts so that at most two divisions are performed for  */
+  /* each slanted line.  Nevertheless, these divisions are noticeable  */
+  /* in the overall performance because flattened curves produce a     */
+  /* very large number of slanted lines.                               */
+  /*                                                                   */
+  /* The division results here are always within ONE_PIXEL.  Therefore */
+  /* the shift magnitude should be at least PIXEL_BITS wider than the  */
+  /* divisors to provide sufficient accuracy of the multiply-shift.    */
+  /* It should not exceed (64 - PIXEL_BITS) to prevent overflowing and */
+  /* leave enough room for 64-bit unsigned multiplication however.     */
+#define FT_UDIVPREP( c, b )                                \
+  FT_Int64  b ## _r = c ? (FT_Int64)0xFFFFFFFF / ( b ) : 0
+#define FT_UDIV( a, b )                                           \
+  (TCoord)( ( (FT_UInt64)( a ) * (FT_UInt64)( b ## _r ) ) >> 32 )
+
+
+  /* Scale area and apply fill rule to calculate the coverage byte. */
+  /* The top fill bit is used for the non-zero rule. The eighth     */
+  /* fill bit is used for the even-odd rule.  The higher coverage   */
+  /* bytes are either clamped for the non-zero-rule or discarded    */
+  /* later for the even-odd rule.                                   */
+#define FT_FILL_RULE( coverage, area, fill )                \
+  FT_BEGIN_STMNT                                            \
+    coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) ); \
+    if ( coverage & fill )                                  \
+      coverage = ~coverage;                                 \
+    if ( coverage > 255 && fill & INT_MIN )                 \
+      coverage = 255;                                       \
+  FT_END_STMNT
+
+
+  /* It is faster to write small spans byte-by-byte than calling     */
+  /* `memset'.  This is mainly due to the cost of the function call. */
+#define FT_GRAY_SET( d, s, count )                          \
+  FT_BEGIN_STMNT                                            \
+    unsigned char* q = d;                                   \
+    switch ( count )                                        \
+    {                                                       \
+      case 7: *q++ = (unsigned char)s; /* fall through */   \
+      case 6: *q++ = (unsigned char)s; /* fall through */   \
+      case 5: *q++ = (unsigned char)s; /* fall through */   \
+      case 4: *q++ = (unsigned char)s; /* fall through */   \
+      case 3: *q++ = (unsigned char)s; /* fall through */   \
+      case 2: *q++ = (unsigned char)s; /* fall through */   \
+      case 1: *q   = (unsigned char)s; /* fall through */   \
+      case 0: break;                                        \
+      default: FT_MEM_SET( d, s, count );                   \
+    }                                                       \
+  FT_END_STMNT
 
 
   /**************************************************************************
@@ -432,7 +474,7 @@
 #endif
 
   /* FT_Span buffer size for direct rendering only */
-#define FT_MAX_GRAY_SPANS  10
+#define FT_MAX_GRAY_SPANS  16
 
 
 #if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
@@ -447,28 +489,24 @@
   {
     ft_jmp_buf  jump_buffer;
 
-    TCoord  ex, ey;
-    TCoord  min_ex, max_ex;
+    TCoord  min_ex, max_ex;  /* min and max integer pixel coordinates */
     TCoord  min_ey, max_ey;
+    TCoord  count_ey;        /* same as (max_ey - min_ey) */
 
-    TArea   area;
-    TCoord  cover;
-    int     invalid;
+    PCell       cell;        /* current cell                             */
+    PCell       cell_free;   /* call allocation next free slot           */
+    PCell       cell_null;   /* last cell, used as dumpster and limit    */
 
-    PCell*      ycells;
-    PCell       cells;
-    FT_PtrDist  max_cells;
-    FT_PtrDist  num_cells;
+    PCell*      ycells;      /* array of cell linked-lists; one per      */
+                             /* vertical coordinate in the current band  */
 
-    TPos    x,  y;
+    TPos        x,  y;       /* last point position */
 
-    FT_Outline  outline;
-    TPixmap     target;
+    FT_Outline  outline;     /* input outline */
+    TPixmap     target;      /* target pixmap */
 
     FT_Raster_Span_Func  render_span;
     void*                render_span_data;
-    FT_Span              spans[FT_MAX_GRAY_SPANS];
-    int                  num_spans;
 
   } gray_TWorker, *gray_PWorker;
 
@@ -476,17 +514,25 @@
 #pragma warning( pop )
 #endif
 
-
 #ifndef FT_STATIC_RASTER
 #define ras  (*worker)
 #else
   static gray_TWorker  ras;
 #endif
 
+  /* The |x| value of the null cell.  Must be the largest possible */
+  /* integer value stored in a `TCell.x` field.                    */
+#define CELL_MAX_X_VALUE    INT_MAX
+
+
+#define FT_INTEGRATE( ras, a, b )                                       \
+          ras.cell->cover = ADD_INT( ras.cell->cover, a ),              \
+          ras.cell->area  = ADD_INT( ras.cell->area, (a) * (TArea)(b) )
+
 
   typedef struct gray_TRaster_
   {
-    void*         memory;
+    void*  memory;
 
   } gray_TRaster, *gray_PRaster;
 
@@ -508,7 +554,7 @@
 
       printf( "%3d:", y );
 
-      for ( ; cell != NULL; cell = cell->next )
+      for ( ; cell != ras.cell_null; cell = cell->next )
         printf( " (%3d, c:%4d, a:%6d)",
                 cell->x, cell->cover, cell->area );
       printf( "\n" );
@@ -520,59 +566,15 @@
 
   /**************************************************************************
    *
-   * Record the current cell in the linked list.
-   */
-  static void
-  gray_record_cell( RAS_ARG )
-  {
-    PCell  *pcell, cell;
-    TCoord  x = ras.ex;
-
-
-    pcell = &ras.ycells[ras.ey - ras.min_ey];
-    while ( ( cell = *pcell ) )
-    {
-      if ( cell->x > x )
-        break;
-
-      if ( cell->x == x )
-        goto Found;
-
-      pcell = &cell->next;
-    }
-
-    if ( ras.num_cells >= ras.max_cells )
-      ft_longjmp( ras.jump_buffer, 1 );
-
-    /* insert new cell */
-    cell        = ras.cells + ras.num_cells++;
-    cell->x     = x;
-    cell->area  = ras.area;
-    cell->cover = ras.cover;
-
-    cell->next  = *pcell;
-    *pcell      = cell;
-
-    return;
-
-  Found:
-    /* update old cell */
-    cell->area  += ras.area;
-    cell->cover += ras.cover;
-  }
-
-
-  /**************************************************************************
-   *
    * Set the current cell to a new position.
    */
   static void
   gray_set_cell( RAS_ARG_ TCoord  ex,
                           TCoord  ey )
   {
-    /* Move the cell pointer to a new position.  We set the `invalid'      */
-    /* flag to indicate that the cell isn't part of those we're interested */
-    /* in during the render phase.  This means that:                       */
+    /* Move the cell pointer to a new position in the linked list. We use  */
+    /* a dumpster null cell for everything outside of the clipping region  */
+    /* during the render phase.  This means that:                          */
     /*                                                                     */
     /* . the new vertical position must be within min_ey..max_ey-1.        */
     /* . the new horizontal position must be strictly less than max_ex     */
@@ -580,21 +582,51 @@
     /* Note that if a cell is to the left of the clipping region, it is    */
     /* actually set to the (min_ex-1) horizontal position.                 */
 
-    /* record the current one if it is valid and substantial */
-    if ( !ras.invalid && ( ras.area || ras.cover ) )
-      gray_record_cell( RAS_VAR );
+    TCoord  ey_index = ey - ras.min_ey;
 
-    ras.area  = 0;
-    ras.cover = 0;
-    ras.ex    = FT_MAX( ex, ras.min_ex - 1 );
-    ras.ey    = ey;
 
-    ras.invalid = ( ey >= ras.max_ey || ey < ras.min_ey ||
-                    ex >= ras.max_ex );
+    if ( ey_index < 0 || ey_index >= ras.count_ey || ex >= ras.max_ex )
+      ras.cell = ras.cell_null;
+    else
+    {
+      PCell*  pcell = ras.ycells + ey_index;
+      PCell   cell;
+
+
+      ex = FT_MAX( ex, ras.min_ex - 1 );
+
+      while ( 1 )
+      {
+        cell = *pcell;
+
+        if ( cell->x > ex )
+          break;
+
+        if ( cell->x == ex )
+          goto Found;
+
+        pcell = &cell->next;
+      }
+
+      /* insert new cell */
+      cell = ras.cell_free++;
+      if ( cell >= ras.cell_null )
+        ft_longjmp( ras.jump_buffer, 1 );
+
+      cell->x     = ex;
+      cell->area  = 0;
+      cell->cover = 0;
+
+      cell->next  = *pcell;
+      *pcell      = cell;
+
+    Found:
+      ras.cell = cell;
+    }
   }
 
 
-#ifndef FT_LONG64
+#ifndef FT_INT64
 
   /**************************************************************************
    *
@@ -622,8 +654,8 @@
       return;
     }
 
-    fx1   = FRACT( x1 );
-    fx2   = FRACT( x2 );
+    fx1 = FRACT( x1 );
+    fx2 = FRACT( x2 );
 
     /* everything is located in a single cell.  That is easy! */
     /*                                                        */
@@ -655,10 +687,9 @@
     /* XXX: y-delta and x-delta below should be related.            */
     FT_DIV_MOD( TCoord, p, dx, delta, mod );
 
-    ras.area  += (TArea)( ( fx1 + first ) * delta );
-    ras.cover += delta;
-    y1        += delta;
-    ex1       += incr;
+    FT_INTEGRATE( ras, delta, fx1 + first );
+    y1  += delta;
+    ex1 += incr;
     gray_set_cell( RAS_VAR_ ex1, ey );
 
     if ( ex1 != ex2 )
@@ -679,10 +710,9 @@
           delta++;
         }
 
-        ras.area  += (TArea)( ONE_PIXEL * delta );
-        ras.cover += delta;
-        y1        += delta;
-        ex1       += incr;
+        FT_INTEGRATE( ras, delta, ONE_PIXEL );
+        y1  += delta;
+        ex1 += incr;
         gray_set_cell( RAS_VAR_ ex1, ey );
       } while ( ex1 != ex2 );
     }
@@ -690,10 +720,7 @@
     fx1 = ONE_PIXEL - first;
 
   End:
-    dy = y2 - y1;
-
-    ras.area  += (TArea)( ( fx1 + fx2 ) * dy );
-    ras.cover += dy;
+    FT_INTEGRATE( ras, y2 - y1, fx1 + fx2 );
   }
 
 
@@ -736,7 +763,6 @@
     {
       TCoord  ex     = TRUNC( ras.x );
       TCoord  two_fx = FRACT( ras.x ) << 1;
-      TArea   area;
 
 
       if ( dy > 0)
@@ -750,27 +776,23 @@
         incr  = -1;
       }
 
-      delta      = first - fy1;
-      ras.area  += (TArea)two_fx * delta;
-      ras.cover += delta;
-      ey1       += incr;
+      delta = first - fy1;
+      FT_INTEGRATE( ras, delta, two_fx);
+      ey1 += incr;
 
       gray_set_cell( RAS_VAR_ ex, ey1 );
 
       delta = first + first - ONE_PIXEL;
-      area  = (TArea)two_fx * delta;
       while ( ey1 != ey2 )
       {
-        ras.area  += area;
-        ras.cover += delta;
-        ey1       += incr;
+        FT_INTEGRATE( ras, delta, two_fx);
+        ey1 += incr;
 
         gray_set_cell( RAS_VAR_ ex, ey1 );
       }
 
-      delta      = fy2 - ONE_PIXEL + first;
-      ras.area  += (TArea)two_fx * delta;
-      ras.cover += delta;
+      delta = fy2 - ONE_PIXEL + first;
+      FT_INTEGRATE( ras, delta, two_fx);
 
       goto End;
     }
@@ -883,8 +905,7 @@
         do
         {
           fy2 = ONE_PIXEL;
-          ras.cover += ( fy2 - fy1 );
-          ras.area  += ( fy2 - fy1 ) * fx1 * 2;
+          FT_INTEGRATE( ras, fy2 - fy1, fx1 * 2 );
           fy1 = 0;
           ey1++;
           gray_set_cell( RAS_VAR_ ex1, ey1 );
@@ -893,8 +914,7 @@
         do
         {
           fy2 = 0;
-          ras.cover += ( fy2 - fy1 );
-          ras.area  += ( fy2 - fy1 ) * fx1 * 2;
+          FT_INTEGRATE( ras, fy2 - fy1, fx1 * 2 );
           fy1 = ONE_PIXEL;
           ey1--;
           gray_set_cell( RAS_VAR_ ex1, ey1 );
@@ -902,7 +922,7 @@
     }
     else                                  /* any other line */
     {
-      TPos  prod = dx * (TPos)fy1 - dy * (TPos)fx1;
+      FT_Int64  prod = dx * (FT_Int64)fy1 - dy * (FT_Int64)fx1;
       FT_UDIVPREP( ex1 != ex2, dx );
       FT_UDIVPREP( ey1 != ey2, dy );
 
@@ -912,72 +932,308 @@
       /* also easily updated when moving from one cell to the next.  */
       do
       {
-        if      ( prod                                   <= 0 &&
-                  prod - dx * ONE_PIXEL                  >  0 ) /* left */
+        if      ( prod - dx * ONE_PIXEL                  >  0 &&
+                  prod                                   <= 0 ) /* left */
         {
           fx2 = 0;
           fy2 = FT_UDIV( -prod, -dx );
           prod -= dy * ONE_PIXEL;
-          ras.cover += ( fy2 - fy1 );
-          ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+          FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
           fx1 = ONE_PIXEL;
           fy1 = fy2;
           ex1--;
         }
-        else if ( prod - dx * ONE_PIXEL                  <= 0 &&
-                  prod - dx * ONE_PIXEL + dy * ONE_PIXEL >  0 ) /* up */
+        else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL >  0 &&
+                  prod - dx * ONE_PIXEL                  <= 0 ) /* up */
         {
           prod -= dx * ONE_PIXEL;
           fx2 = FT_UDIV( -prod, dy );
           fy2 = ONE_PIXEL;
-          ras.cover += ( fy2 - fy1 );
-          ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+          FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
           fx1 = fx2;
           fy1 = 0;
           ey1++;
         }
-        else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
-                  prod                  + dy * ONE_PIXEL >= 0 ) /* right */
+        else if ( prod                  + dy * ONE_PIXEL >= 0 &&
+                  prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 ) /* right */
         {
           prod += dy * ONE_PIXEL;
           fx2 = ONE_PIXEL;
           fy2 = FT_UDIV( prod, dx );
-          ras.cover += ( fy2 - fy1 );
-          ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+          FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
           fx1 = 0;
           fy1 = fy2;
           ex1++;
         }
-        else /* ( prod                  + dy * ONE_PIXEL <  0 &&
-                  prod                                   >  0 )    down */
+        else /* ( prod                                   >  0 &&
+                  prod                  + dy * ONE_PIXEL <  0 )    down */
         {
           fx2 = FT_UDIV( prod, -dy );
           fy2 = 0;
           prod += dx * ONE_PIXEL;
-          ras.cover += ( fy2 - fy1 );
-          ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+          FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
           fx1 = fx2;
           fy1 = ONE_PIXEL;
           ey1--;
         }
 
         gray_set_cell( RAS_VAR_ ex1, ey1 );
+
       } while ( ex1 != ex2 || ey1 != ey2 );
     }
 
     fx2 = FRACT( to_x );
     fy2 = FRACT( to_y );
 
-    ras.cover += ( fy2 - fy1 );
-    ras.area  += ( fy2 - fy1 ) * ( fx1 + fx2 );
+    FT_INTEGRATE( ras, fy2 - fy1, fx1 + fx2 );
 
   End:
-    ras.x       = to_x;
-    ras.y       = to_y;
+    ras.x = to_x;
+    ras.y = to_y;
   }
 
 #endif
 
+  /*
+   * Benchmarking shows that using DDA to flatten the quadratic Bézier arcs
+   * is slightly faster in the following cases:
+   *
+   *   - When the host CPU is 64-bit.
+   *   - When SSE2 SIMD registers and instructions are available (even on
+   *     x86).
+   *
+   * For other cases, using binary splits is actually slightly faster.
+   */
+#if defined( __SSE2__ )                          || \
+    defined( __x86_64__ )                        || \
+    defined( _M_AMD64 )                          || \
+    ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 )
+#  define FT_SSE2 1
+#else
+#  define FT_SSE2 0
+#endif
+
+#if FT_SSE2                || \
+    defined( __aarch64__ ) || \
+    defined( _M_ARM64 )
+#  define BEZIER_USE_DDA  1
+#else
+#  define BEZIER_USE_DDA  0
+#endif
+
+  /*
+   * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64`
+   * to be defined.  If `FT_INT64` is not defined, meaning there is no
+   * 64-bit type available, disable it to avoid compilation errors.  See for
+   * example https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
+   */
+#if !defined( FT_INT64 )
+#  undef BEZIER_USE_DDA
+#  define BEZIER_USE_DDA  0
+#endif
+
+#if BEZIER_USE_DDA
+
+#if FT_SSE2
+#  include <emmintrin.h>
+#endif
+
+#define LEFT_SHIFT( a, b )  (FT_Int64)( (FT_UInt64)(a) << (b) )
+
+
+  static void
+  gray_render_conic( RAS_ARG_ const FT_Vector*  control,
+                              const FT_Vector*  to )
+  {
+    FT_Vector  p0, p1, p2;
+    TPos       ax, ay, bx, by, dx, dy;
+    int        shift;
+
+    FT_Int64  rx, ry;
+    FT_Int64  qx, qy;
+    FT_Int64  px, py;
+
+    FT_UInt  count;
+
+
+    p0.x = ras.x;
+    p0.y = ras.y;
+    p1.x = UPSCALE( control->x );
+    p1.y = UPSCALE( control->y );
+    p2.x = UPSCALE( to->x );
+    p2.y = UPSCALE( to->y );
+
+    /* short-cut the arc that crosses the current band */
+    if ( ( TRUNC( p0.y ) >= ras.max_ey &&
+           TRUNC( p1.y ) >= ras.max_ey &&
+           TRUNC( p2.y ) >= ras.max_ey ) ||
+         ( TRUNC( p0.y ) <  ras.min_ey &&
+           TRUNC( p1.y ) <  ras.min_ey &&
+           TRUNC( p2.y ) <  ras.min_ey ) )
+    {
+      ras.x = p2.x;
+      ras.y = p2.y;
+      return;
+    }
+
+    bx = p1.x - p0.x;
+    by = p1.y - p0.y;
+    ax = p2.x - p1.x - bx;  /* p0.x + p2.x - 2 * p1.x */
+    ay = p2.y - p1.y - by;  /* p0.y + p2.y - 2 * p1.y */
+
+    dx = FT_ABS( ax );
+    dy = FT_ABS( ay );
+    if ( dx < dy )
+      dx = dy;
+
+    if ( dx <= ONE_PIXEL / 4 )
+    {
+      gray_render_line( RAS_VAR_ p2.x, p2.y );
+      return;
+    }
+
+    /* We can calculate the number of necessary bisections because  */
+    /* each bisection predictably reduces deviation exactly 4-fold. */
+    /* Even 32-bit deviation would vanish after 16 bisections.      */
+    shift = 0;
+    do
+    {
+      dx   >>= 2;
+      shift += 1;
+
+    } while ( dx > ONE_PIXEL / 4 );
+
+    /*
+     * The (P0,P1,P2) arc equation, for t in [0,1] range:
+     *
+     * P(t) = P0*(1-t)^2 + P1*2*t*(1-t) + P2*t^2
+     *
+     * P(t) = P0 + 2*(P1-P0)*t + (P0+P2-2*P1)*t^2
+     *      = P0 + 2*B*t + A*t^2
+     *
+     *    for A = P0 + P2 - 2*P1
+     *    and B = P1 - P0
+     *
+     * Let's consider the difference when advancing by a small
+     * parameter h:
+     *
+     *    Q(h,t) = P(t+h) - P(t) = 2*B*h + A*h^2 + 2*A*h*t
+     *
+     * And then its own difference:
+     *
+     *    R(h,t) = Q(h,t+h) - Q(h,t) = 2*A*h*h = R (constant)
+     *
+     * Since R is always a constant, it is possible to compute
+     * successive positions with:
+     *
+     *     P = P0
+     *     Q = Q(h,0) = 2*B*h + A*h*h
+     *     R = 2*A*h*h
+     *
+     *   loop:
+     *     P += Q
+     *     Q += R
+     *     EMIT(P)
+     *
+     * To ensure accurate results, perform computations on 64-bit
+     * values, after scaling them by 2^32.
+     *
+     *           h = 1 / 2^N
+     *
+     *     R << 32 = 2 * A << (32 - N - N)
+     *             = A << (33 - 2*N)
+     *
+     *     Q << 32 = (2 * B << (32 - N)) + (A << (32 - N - N))
+     *             = (B << (33 - N)) + (A << (32 - 2*N))
+     */
+
+#if FT_SSE2
+    /* Experience shows that for small shift values, */
+    /* SSE2 is actually slower.                      */
+    if ( shift > 2 )
+    {
+      union
+      {
+        struct { FT_Int64  ax, ay, bx, by; }  i;
+        struct { __m128i  a, b; }  vec;
+
+      } u;
+
+      union
+      {
+        struct { FT_Int32  px_lo, px_hi, py_lo, py_hi; }  i;
+        __m128i  vec;
+
+      } v;
+
+      __m128i  a, b;
+      __m128i  r, q, q2;
+      __m128i  p;
+
+
+      u.i.ax = ax;
+      u.i.ay = ay;
+      u.i.bx = bx;
+      u.i.by = by;
+
+      a = _mm_load_si128( &u.vec.a );
+      b = _mm_load_si128( &u.vec.b );
+
+      r  = _mm_slli_epi64( a, 33 - 2 * shift );
+      q  = _mm_slli_epi64( b, 33 - shift );
+      q2 = _mm_slli_epi64( a, 32 - 2 * shift );
+
+      q = _mm_add_epi64( q2, q );
+
+      v.i.px_lo = 0;
+      v.i.px_hi = p0.x;
+      v.i.py_lo = 0;
+      v.i.py_hi = p0.y;
+
+      p = _mm_load_si128( &v.vec );
+
+      for ( count = 1U << shift; count > 0; count-- )
+      {
+        p = _mm_add_epi64( p, q );
+        q = _mm_add_epi64( q, r );
+
+        _mm_store_si128( &v.vec, p );
+
+        gray_render_line( RAS_VAR_ v.i.px_hi, v.i.py_hi );
+      }
+
+      return;
+    }
+#endif  /* FT_SSE2 */
+
+    rx = LEFT_SHIFT( ax, 33 - 2 * shift );
+    ry = LEFT_SHIFT( ay, 33 - 2 * shift );
+
+    qx = LEFT_SHIFT( bx, 33 - shift ) + LEFT_SHIFT( ax, 32 - 2 * shift );
+    qy = LEFT_SHIFT( by, 33 - shift ) + LEFT_SHIFT( ay, 32 - 2 * shift );
+
+    px = LEFT_SHIFT( p0.x, 32 );
+    py = LEFT_SHIFT( p0.y, 32 );
+
+    for ( count = 1U << shift; count > 0; count-- )
+    {
+      px += qx;
+      py += qy;
+      qx += rx;
+      qy += ry;
+
+      gray_render_line( RAS_VAR_ (FT_Pos)( px >> 32 ),
+                                 (FT_Pos)( py >> 32 ) );
+    }
+  }
+
+#else  /* !BEZIER_USE_DDA */
+
+  /*
+   * Note that multiple attempts to speed up the function below
+   * with SSE2 intrinsics, using various data layouts, have turned
+   * out to be slower than the non-SIMD code below.
+   */
   static void
   gray_split_conic( FT_Vector*  base )
   {
@@ -1007,7 +1263,7 @@
     FT_Vector   bez_stack[16 * 2 + 1];  /* enough to accommodate bisections */
     FT_Vector*  arc = bez_stack;
     TPos        dx, dy;
-    int         draw, split;
+    int         draw;
 
 
     arc[0].x = UPSCALE( to->x );
@@ -1050,7 +1306,9 @@
     /* many times as there are trailing zeros in the counter.         */
     do
     {
-      split = draw & ( -draw );  /* isolate the rightmost 1-bit */
+      int  split = draw & ( -draw );  /* isolate the rightmost 1-bit */
+
+
       while ( ( split >>= 1 ) )
       {
         gray_split_conic( arc );
@@ -1063,7 +1321,17 @@
     } while ( --draw );
   }
 
+#endif  /* !BEZIER_USE_DDA */
 
+
+  /*
+   * For cubic Bézier, binary splits are still faster than DDA
+   * because the splits are adaptive to how quickly each sub-arc
+   * approaches their chord trisection points.
+   *
+   * It might be useful to experiment with SSE2 to speed up
+   * `gray_split_cubic`, though.
+   */
   static void
   gray_split_cubic( FT_Vector*  base )
   {
@@ -1205,92 +1473,11 @@
 
 
   static void
-  gray_hline( RAS_ARG_ TCoord  x,
-                       TCoord  y,
-                       TArea   coverage,
-                       TCoord  acount )
-  {
-    /* scale the coverage from 0..(ONE_PIXEL*ONE_PIXEL*2) to 0..256  */
-    coverage >>= PIXEL_BITS * 2 + 1 - 8;
-
-    /* compute the line's coverage depending on the outline fill rule */
-    if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
-    {
-      coverage &= 511;
-
-      if ( coverage >= 256 )
-        coverage = 511 - coverage;
-    }
-    else  /* default non-zero winding rule */
-    {
-      if ( coverage < 0 )
-        coverage = ~coverage;  /* the same as -coverage - 1 */
-
-      if ( coverage >= 256 )
-        coverage = 255;
-    }
-
-    if ( ras.num_spans >= 0 )  /* for FT_RASTER_FLAG_DIRECT only */
-    {
-      FT_Span*  span = ras.spans + ras.num_spans++;
-
-
-      span->x        = (short)x;
-      span->len      = (unsigned short)acount;
-      span->coverage = (unsigned char)coverage;
-
-      if ( ras.num_spans == FT_MAX_GRAY_SPANS )
-      {
-        /* flush the span buffer and reset the count */
-        ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
-        ras.num_spans = 0;
-      }
-    }
-    else
-    {
-      unsigned char*  q = ras.target.origin - ras.target.pitch * y + x;
-      unsigned char   c = (unsigned char)coverage;
-
-
-      /* For small-spans it is faster to do it by ourselves than
-       * calling `memset'.  This is mainly due to the cost of the
-       * function call.
-       */
-      switch ( acount )
-      {
-      case 7:
-        *q++ = c;
-        /* fall through */
-      case 6:
-        *q++ = c;
-        /* fall through */
-      case 5:
-        *q++ = c;
-        /* fall through */
-      case 4:
-        *q++ = c;
-        /* fall through */
-      case 3:
-        *q++ = c;
-        /* fall through */
-      case 2:
-        *q++ = c;
-        /* fall through */
-      case 1:
-        *q = c;
-        /* fall through */
-      case 0:
-        break;
-      default:
-        FT_MEM_SET( q, c, acount );
-      }
-    }
-  }
-
-
-  static void
   gray_sweep( RAS_ARG )
   {
+    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+                                                                 : INT_MIN;
+    int  coverage;
     int  y;
 
 
@@ -1299,31 +1486,120 @@
       PCell   cell  = ras.ycells[y - ras.min_ey];
       TCoord  x     = ras.min_ex;
       TArea   cover = 0;
-      TArea   area;
+
+      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
 
 
-      for ( ; cell != NULL; cell = cell->next )
+      for ( ; cell != ras.cell_null; cell = cell->next )
       {
+        TArea  area;
+
+
         if ( cover != 0 && cell->x > x )
-          gray_hline( RAS_VAR_ x, y, cover, cell->x - x );
+        {
+          FT_FILL_RULE( coverage, cover, fill );
+          FT_GRAY_SET( line + x, coverage, cell->x - x );
+        }
 
         cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
         area   = cover - cell->area;
 
         if ( area != 0 && cell->x >= ras.min_ex )
-          gray_hline( RAS_VAR_ cell->x, y, area, 1 );
+        {
+          FT_FILL_RULE( coverage, area, fill );
+          line[cell->x] = (unsigned char)coverage;
+        }
 
         x = cell->x + 1;
       }
 
-      if ( cover != 0 )
-        gray_hline( RAS_VAR_ x, y, cover, ras.max_ex - x );
+      if ( cover != 0 )  /* only if cropped */
+      {
+        FT_FILL_RULE( coverage, cover, fill );
+        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
+      }
+    }
+  }
 
-      if ( ras.num_spans > 0 )  /* for FT_RASTER_FLAG_DIRECT only */
+
+  static void
+  gray_sweep_direct( RAS_ARG )
+  {
+    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+                                                                 : INT_MIN;
+    int  coverage;
+    int  y;
+
+    FT_Span  span[FT_MAX_GRAY_SPANS];
+    int      n = 0;
+
+
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+    {
+      PCell   cell  = ras.ycells[y - ras.min_ey];
+      TCoord  x     = ras.min_ex;
+      TArea   cover = 0;
+
+
+      for ( ; cell != ras.cell_null; cell = cell->next )
+      {
+        TArea  area;
+
+
+        if ( cover != 0 && cell->x > x )
+        {
+          FT_FILL_RULE( coverage, cover, fill );
+
+          span[n].coverage = (unsigned char)coverage;
+          span[n].x        = (short)x;
+          span[n].len      = (unsigned short)( cell->x - x );
+
+          if ( ++n == FT_MAX_GRAY_SPANS )
+          {
+            /* flush the span buffer and reset the count */
+            ras.render_span( y, n, span, ras.render_span_data );
+            n = 0;
+          }
+        }
+
+        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+        area   = cover - cell->area;
+
+        if ( area != 0 && cell->x >= ras.min_ex )
+        {
+          FT_FILL_RULE( coverage, area, fill );
+
+          span[n].coverage = (unsigned char)coverage;
+          span[n].x        = (short)cell->x;
+          span[n].len      = 1;
+
+          if ( ++n == FT_MAX_GRAY_SPANS )
+          {
+            /* flush the span buffer and reset the count */
+            ras.render_span( y, n, span, ras.render_span_data );
+            n = 0;
+          }
+        }
+
+        x = cell->x + 1;
+      }
+
+      if ( cover != 0 )  /* only if cropped */
+      {
+        FT_FILL_RULE( coverage, cover, fill );
+
+        span[n].coverage = (unsigned char)coverage;
+        span[n].x        = (short)x;
+        span[n].len      = (unsigned short)( ras.max_ex - x );
+
+        ++n;
+      }
+
+      if ( n )
       {
         /* flush the span buffer and reset the count */
-        ras.render_span( y, ras.num_spans, ras.spans, ras.render_span_data );
-        ras.num_spans = 0;
+        ras.render_span( y, n, span, ras.render_span_data );
+        n = 0;
       }
     }
   }
@@ -1604,7 +1880,7 @@
     }
 
     FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
-    return 0;
+    return Smooth_Err_Ok;
 
   Exit:
     FT_TRACE5(( "FT_Outline_Decompose: Error 0x%x\n", error ));
@@ -1645,18 +1921,15 @@
       if ( continued )
         FT_Trace_Enable();
 
-      if ( !ras.invalid )
-        gray_record_cell( RAS_VAR );
-
-      FT_TRACE7(( "band [%d..%d]: %ld cell%s\n",
+      FT_TRACE7(( "band [%d..%d]: %ld cell%s remaining/\n",
                   ras.min_ey,
                   ras.max_ey,
-                  ras.num_cells,
-                  ras.num_cells == 1 ? "" : "s" ));
+                  ras.cell_null - ras.cell_free,
+                  ras.cell_null - ras.cell_free == 1 ? "" : "s" ));
     }
     else
     {
-      error = FT_THROW( Memory_Overflow );
+      error = FT_THROW( Raster_Overflow );
 
       FT_TRACE7(( "band [%d..%d]: to be bisected\n",
                   ras.min_ey, ras.max_ey ));
@@ -1682,7 +1955,16 @@
     int  continued = 0;
 
 
+    /* Initialize the null cell at the end of the poll. */
+    ras.cell_null        = buffer + FT_MAX_GRAY_POOL - 1;
+    ras.cell_null->x     = CELL_MAX_X_VALUE;
+    ras.cell_null->area  = 0;
+    ras.cell_null->cover = 0;
+    ras.cell_null->next  = NULL;
+
     /* set up vertical bands */
+    ras.ycells     = (PCell*)buffer;
+
     if ( height > n )
     {
       /* two divisions rounded up */
@@ -1690,13 +1972,6 @@
       height  = ( height + n - 1 ) / n;
     }
 
-    /* memory management */
-    n = ( height * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) / sizeof ( TCell );
-
-    ras.cells     = buffer + n;
-    ras.max_cells = (FT_PtrDist)( FT_MAX_GRAY_POOL - n );
-    ras.ycells    = (PCell*)buffer;
-
     for ( y = yMin; y < yMax; )
     {
       ras.min_ey = y;
@@ -1710,27 +1985,37 @@
       do
       {
         TCoord  width = band[0] - band[1];
+        TCoord  w;
         int     error;
 
 
-        FT_MEM_ZERO( ras.ycells, height * sizeof ( PCell ) );
+        for ( w = 0; w < width; ++w )
+          ras.ycells[w] = ras.cell_null;
 
-        ras.num_cells = 0;
-        ras.invalid   = 1;
+        /* memory management: skip ycells */
+        n = ( (size_t)width * 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;
 
         if ( !error )
         {
-          gray_sweep( RAS_VAR );
+          if ( ras.render_span )  /* for FT_RASTER_FLAG_DIRECT only */
+            gray_sweep_direct( RAS_VAR );
+          else
+            gray_sweep( RAS_VAR );
           band--;
           continue;
         }
-        else if ( error != ErrRaster_Memory_Overflow )
-          return 1;
+        else if ( error != Smooth_Err_Raster_Overflow )
+          return error;
 
         /* render pool overflow; we will reduce the render band by half */
         width >>= 1;
@@ -1739,7 +2024,7 @@
         if ( width == 0 )
         {
           FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
-          return 1;
+          return FT_THROW( Raster_Overflow );
         }
 
         band++;
@@ -1748,7 +2033,7 @@
       } while ( band >= bands );
     }
 
-    return 0;
+    return Smooth_Err_Ok;
   }
 
 
@@ -1769,14 +2054,14 @@
 
     /* this version does not support monochrome rendering */
     if ( !( params->flags & FT_RASTER_FLAG_AA ) )
-      return FT_THROW( Invalid_Mode );
+      return FT_THROW( Cannot_Render_Glyph );
 
     if ( !outline )
       return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
     if ( outline->n_points == 0 || outline->n_contours <= 0 )
-      return 0;
+      return Smooth_Err_Ok;
 
     if ( !outline->contours || !outline->points )
       return FT_THROW( Invalid_Outline );
@@ -1790,11 +2075,10 @@
     if ( params->flags & FT_RASTER_FLAG_DIRECT )
     {
       if ( !params->gray_spans )
-        return 0;
+        return Smooth_Err_Ok;
 
       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
       ras.render_span_data = params->user;
-      ras.num_spans        = 0;
 
       ras.min_ex = params->clip_box.xMin;
       ras.min_ey = params->clip_box.yMin;
@@ -1809,7 +2093,7 @@
 
       /* nothing to do */
       if ( !target_map->width || !target_map->rows )
-        return 0;
+        return Smooth_Err_Ok;
 
       if ( !target_map->buffer )
         return FT_THROW( Invalid_Argument );
@@ -1824,7 +2108,6 @@
 
       ras.render_span      = (FT_Raster_Span_Func)NULL;
       ras.render_span_data = NULL;
-      ras.num_spans        = -1;  /* invalid */
 
       ras.min_ex = 0;
       ras.min_ey = 0;
@@ -1834,7 +2117,7 @@
 
     /* exit if nothing to do */
     if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
-      return 0;
+      return Smooth_Err_Ok;
 
     return gray_convert_glyph( RAS_VAR );
   }
@@ -1871,19 +2154,17 @@
 #else /* !STANDALONE_ */
 
   static int
-  gray_raster_new( FT_Memory   memory,
-                   FT_Raster*  araster )
+  gray_raster_new( FT_Memory      memory,
+                   gray_PRaster*  araster )
   {
     FT_Error      error;
     gray_PRaster  raster = NULL;
 
 
-    *araster = 0;
-    if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) )
-    {
+    if ( !FT_NEW( raster ) )
       raster->memory = memory;
-      *araster       = (FT_Raster)raster;
-    }
+
+    *araster = raster;
 
     return error;
   }
diff --git a/src/smooth/ftgrays.h b/src/smooth/ftgrays.h
index caba632..3dad049 100644
--- a/src/smooth/ftgrays.h
+++ b/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
  *
  *   FreeType smooth renderer declaration
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/smooth/ftsmerrs.h b/src/smooth/ftsmerrs.h
index e93f3df..dc2c40c 100644
--- a/src/smooth/ftsmerrs.h
+++ b/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
  *
  *   smooth renderer error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 5d66bd6..bea3b4a 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
  *
  *   Anti-aliasing renderer interface (body).
  *
- * Copyright (C) 2000-2020 by
+ * Copyright (C) 2000-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/smooth/ftsmooth.h b/src/smooth/ftsmooth.h
index 22a88d5..2dd81e8 100644
--- a/src/smooth/ftsmooth.h
+++ b/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
  *
  *   Anti-aliasing renderer interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/smooth/module.mk b/src/smooth/module.mk
index 9b1507f..ec6537f 100644
--- a/src/smooth/module.mk
+++ b/src/smooth/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/smooth/rules.mk b/src/smooth/rules.mk
index b08056f..de701d9 100644
--- a/src/smooth/rules.mk
+++ b/src/smooth/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/smooth/smooth.c b/src/smooth/smooth.c
index 04b531c..9e25440 100644
--- a/src/smooth/smooth.c
+++ b/src/smooth/smooth.c
@@ -4,7 +4,7 @@
  *
  *   FreeType anti-aliasing rasterer module component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/tools/afblue.pl b/src/tools/afblue.pl
index bbc4f47..9548162 100644
--- a/src/tools/afblue.pl
+++ b/src/tools/afblue.pl
@@ -5,7 +5,7 @@
 #
 # Process a blue zone character data file.
 #
-# Copyright (C) 2013-2020 by
+# Copyright (C) 2013-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used,
diff --git a/src/tools/apinames.c b/src/tools/apinames.c
index aeecf88..8a8b082 100644
--- a/src/tools/apinames.c
+++ b/src/tools/apinames.c
@@ -22,7 +22,7 @@
 #include <ctype.h>
 
 #define  PROGRAM_NAME     "apinames"
-#define  PROGRAM_VERSION  "0.3"
+#define  PROGRAM_VERSION  "0.4"
 
 #define  LINEBUFF_SIZE  1024
 
@@ -33,6 +33,7 @@
   OUTPUT_WINDOWS_DEF,   /* output a Windows .DEF file for Visual C++ or Mingw */
   OUTPUT_BORLAND_DEF,   /* output a Windows .DEF file for Borland C++         */
   OUTPUT_WATCOM_LBC,    /* output a Watcom Linker Command File                */
+  OUTPUT_VMS_OPT,       /* output an OpenVMS Linker Option File               */
   OUTPUT_NETWARE_IMP,   /* output a NetWare ImportFile                        */
   OUTPUT_GNU_VERMAP     /* output a version map for GNU or Solaris linker     */
 
@@ -167,7 +168,6 @@
   case OUTPUT_WATCOM_LBC:
     {
       const char*  dot;
-      char         temp[512];
 
 
       if ( !dll_name )
@@ -181,7 +181,8 @@
       dot = strchr( dll_name, '.' );
       if ( dot )
       {
-        int  len = dot - dll_name;
+        char  temp[512];
+        int   len = dot - dll_name;
 
 
         if ( len > (int)( sizeof ( temp ) - 1 ) )
@@ -200,6 +201,16 @@
 
     break;
 
+  case OUTPUT_VMS_OPT:
+    fprintf( out, "GSMATCH=LEQUAL,2,0\n"
+                  "CASE_SENSITIVE=YES\n"
+                  "SYMBOL_VECTOR=(-\n" );
+    for ( nn = 0; nn < num_names - 1; nn++ )
+      fprintf( out, "    %s=PROCEDURE,-\n", the_names[nn].name );
+    fprintf( out, "    %s=PROCEDURE)\n", the_names[num_names - 1].name );
+
+    break;
+
   case OUTPUT_NETWARE_IMP:
     if ( dll_name )
       fprintf( out, "  (%s)\n", dll_name );
@@ -352,6 +363,7 @@
     "           -w      output .DEF file for Visual C++ and Mingw\n"
     "           -wB     output .DEF file for Borland C++\n"
     "           -wW     output Watcom Linker Response File\n"
+    "           -wV     output OpenVMS Linker Options File\n"
     "           -wN     output NetWare Import File\n"
     "           -wL     output version map for GNU or Solaris linker\n"
     "\n";
@@ -445,6 +457,10 @@
         format = OUTPUT_WATCOM_LBC;
         break;
 
+      case 'V':
+        format = OUTPUT_VMS_OPT;
+        break;
+
       case 'N':
         format = OUTPUT_NETWARE_IMP;
         break;
diff --git a/src/tools/chktrcmp.py b/src/tools/chktrcmp.py
index 4c40bda..244a24a 100755
--- a/src/tools/chktrcmp.py
+++ b/src/tools/chktrcmp.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 #
 # Check trace components in FreeType 2 source.
-# Author: suzuki toshiya, 2009, 2013
+# Author: suzuki toshiya, 2009, 2013, 2020
 #
 # This code is explicitly into the public domain.
 
@@ -50,7 +50,7 @@
 #
 
 c_pathname_pat = re.compile( '^.*\.[ch]$', re.IGNORECASE )
-trace_use_pat  = re.compile( '^[ \t]*#define[ \t]+FT_COMPONENT[ \t]+trace_' )
+trace_use_pat  = re.compile( '^[ \t]*#define[ \t]+FT_COMPONENT[ \t]+' )
 
 for d in SRC_FILE_DIRS:
   for ( p, dlst, flst ) in os.walk( d ):
diff --git a/src/tools/ftrandom/ftrandom.c b/src/tools/ftrandom/ftrandom.c
index ab62429..4f912cd 100644
--- a/src/tools/ftrandom/ftrandom.c
+++ b/src/tools/ftrandom/ftrandom.c
@@ -29,7 +29,7 @@
 /* This file is now part of the FreeType library */
 
 
-#define _XOPEN_SOURCE 500 /* for `kill', `strdup', `random', and `srandom' */
+#define _XOPEN_SOURCE 600 /* for `kill', `strdup', `random', and `srandom' */
 
 
 #include <stdio.h>
diff --git a/src/tools/glnames.py b/src/tools/glnames.py
index a19ce17..c6f2f27 100644
--- a/src/tools/glnames.py
+++ b/src/tools/glnames.py
@@ -6,7 +6,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/tools/no-copyright b/src/tools/no-copyright
index d639aa4..1eaa630 100644
--- a/src/tools/no-copyright
+++ b/src/tools/no-copyright
@@ -7,8 +7,6 @@
 #
 # Don't put empty lines into this file!
 #
-.gitignore
-#
 builds/unix/pkg.m4
 #
 docs/FTL.TXT
@@ -62,4 +60,6 @@
 src/tools/apinames.c
 src/tools/ftrandom/ftrandom.c
 #
+subprojects/dlg
+#
 # EOF
diff --git a/src/tools/update-copyright-year b/src/tools/update-copyright-year
index c659bba..69d63b6 100755
--- a/src/tools/update-copyright-year
+++ b/src/tools/update-copyright-year
@@ -2,7 +2,7 @@
   & eval 'exec perl -wS -i "$0" $argv:q'
     if 0;
 
-# Copyright (C) 2015-2020 by
+# Copyright (C) 2015-2021 by
 # Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
@@ -28,20 +28,20 @@
 #
 # or
 #
-#   /* Copyright 2000,  2001, 2004-2007 by    */
-#   /* foobar                                 */
+#   /* Copyright (c) 2000,  2001, 2004-2007 by    */
+#   /* foobar                                     */
 #
 # and replaces them uniformly with
 #
-#   Copyright 2000-2015
+#   Copyright (C) 2000-2021
 #   foobar
 #
 # and
 #
-#   /* Copyright 2000-2015 by                 */
-#   /* foobar                                 */
+#   /* Copyright (C) 2000-2021 by                 */
+#   /* foobar                                     */
 #
-# (assuming that the current year is 2015).  As can be seen, the line length
+# (assuming that the current year is 2021).  As can be seen, the line length
 # is retained if there is non-whitespace after the word `by' on the same
 # line.
 
@@ -80,11 +80,11 @@
       {
         # Fill line to the same length (if appropriate); we skip the middle
         # part but insert `(C)', three spaces, and `-'.
-        my $space = length($+{space1}) - 1
-                    + length($+{middle}) - 1
-                    + length($+{space2}) - 1
+        my $space = length($+{space1})
+                    + length($+{middle})
+                    + length($+{space2})
                     + length($+{space3})
-                    - (length("(C)") + 1);
+                    - (length("(C)") + 3 + 1);
 
         print "$+{begin}";
         print "Copyright\ (C)\ $+{first}-$year\ by";
@@ -106,19 +106,38 @@
         (?<end>.*)
       }
       {
-        # Fill line to the same length (if appropriate); we insert three
-        # spaces, a `-', and the current year.
-        my $space = length($+{space1}) - 1
-                    + length($+{space2}) - 1
-                    + length($+{space3})
-                    - (length($year) + 1);
+        if ($+{first} < $year)
+        {
+          # Fill line to the same length (if appropriate); we insert three
+          # spaces, the string `(C)', a `-', and the current year.
+          my $space = length($+{space1})
+                      + length($+{space2})
+                      + length($+{space3})
+                      - (length($year) + length("(C)") + 3 + 1);
 
-        print "$+{begin}";
-        print "Copyright\ (C)\ $+{first}-$year\ by";
-        # If $space is negative this inserts nothing.
-        print ' ' x $space if length($+{end});
-        print "$+{end}\n";
-        $replaced = 1;
+          print "$+{begin}";
+          print "Copyright\ (C)\ $+{first}-$year\ by";
+          # If $space is negative this inserts nothing.
+          print ' ' x $space if length($+{end});
+          print "$+{end}\n";
+          $replaced = 1;
+        }
+        else
+        {
+          # Fill line to the same length (if appropriate); we insert three
+          # spaces and the string `(C)'.
+          my $space = length($+{space1})
+                      + length($+{space2})
+                      + length($+{space3})
+                      - (length("(C)") + 3);
+
+          print "$+{begin}";
+          print "Copyright\ (C)\ $+{first}\ by";
+          # If $space is negative this inserts nothing.
+          print ' ' x $space if length($+{end});
+          print "$+{end}\n";
+          $replaced = 1;
+        }
       }ex
     ||
     # Otherwise print line unaltered.
diff --git a/src/truetype/module.mk b/src/truetype/module.mk
index 2d8d39d..485ef05 100644
--- a/src/truetype/module.mk
+++ b/src/truetype/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/truetype/rules.mk b/src/truetype/rules.mk
index 2f6fecf..cfd6b3b 100644
--- a/src/truetype/rules.mk
+++ b/src/truetype/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/truetype/truetype.c b/src/truetype/truetype.c
index 41b6808..4232aca 100644
--- a/src/truetype/truetype.c
+++ b/src/truetype/truetype.c
@@ -4,7 +4,7 @@
  *
  *   FreeType TrueType driver component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index bf830b1..6fcfdb2 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
  *
  *   TrueType font driver implementation (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -108,7 +108,7 @@
       return error;
     }
 
-    FT_TRACE0(( "tt_property_set: missing property `%s'\n",
+    FT_TRACE2(( "tt_property_set: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
   }
@@ -135,7 +135,7 @@
       return error;
     }
 
-    FT_TRACE0(( "tt_property_get: missing property `%s'\n",
+    FT_TRACE2(( "tt_property_get: missing property `%s'\n",
                 property_name ));
     return FT_THROW( Missing_Property );
   }
@@ -354,7 +354,16 @@
 
 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
-    FT_Request_Metrics( size->face, req );
+    {
+      FT_Error  err = FT_Request_Metrics( size->face, req );
+
+
+      if ( err )
+      {
+        error = err;
+        goto Exit;
+      }
+    }
 
     if ( FT_IS_SCALABLE( size->face ) )
     {
@@ -382,6 +391,7 @@
 #endif
     }
 
+  Exit:
     return error;
   }
 
diff --git a/src/truetype/ttdriver.h b/src/truetype/ttdriver.h
index ee1438e..4e6d52d 100644
--- a/src/truetype/ttdriver.h
+++ b/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level TrueType driver interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/truetype/tterrors.h b/src/truetype/tterrors.h
index efeafd3..0ce247e 100644
--- a/src/truetype/tterrors.h
+++ b/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
  *
  *   TrueType error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index 1dd319d..11968f6 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
  *
  *   TrueType Glyph Loader (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -197,10 +197,17 @@
     }
 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
-    if ( !loader->linear_def )
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+    /* With the incremental interface, these values are set by  */
+    /* a call to `tt_get_metrics_incremental'.                  */
+    if ( face->root.internal->incremental_interface == NULL )
+#endif
     {
-      loader->linear_def = 1;
-      loader->linear     = advance_width;
+      if ( !loader->linear_def )
+      {
+        loader->linear_def = 1;
+        loader->linear     = advance_width;
+      }
     }
 
     return FT_Err_Ok;
@@ -210,8 +217,8 @@
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
 
   static void
-  tt_get_metrics_incr_overrides( TT_Loader  loader,
-                                 FT_UInt    glyph_index )
+  tt_get_metrics_incremental( TT_Loader  loader,
+                              FT_UInt    glyph_index )
   {
     TT_Face  face = loader->face;
 
@@ -451,7 +458,7 @@
                           (void*)&load->exec->glyphIns,
                           n_ins );
 
-      load->exec->glyphSize = (FT_UShort)tmp;
+      load->exec->glyphSize = (FT_UInt)tmp;
       if ( error )
         return error;
 
@@ -736,12 +743,14 @@
                       subglyph->transform.xx / 65536.0,
                       subglyph->transform.yy / 65536.0 ));
         else if ( subglyph->flags & WE_HAVE_A_2X2 )
-          FT_TRACE7(( "      scaling: xx=%f, yx=%f\n"
-                      "               xy=%f, yy=%f\n",
+        {
+          FT_TRACE7(( "      scaling: xx=%f, yx=%f\n",
                       subglyph->transform.xx / 65536.0,
-                      subglyph->transform.yx / 65536.0,
+                      subglyph->transform.yx / 65536.0 ));
+          FT_TRACE7(( "               xy=%f, yy=%f\n",
                       subglyph->transform.xy / 65536.0,
                       subglyph->transform.yy / 65536.0 ));
+        }
 
         subglyph++;
       }
@@ -1383,7 +1392,7 @@
            FT_READ_USHORT( n_ins )           )
         return error;
 
-      FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
+      FT_TRACE5(( "  Instructions size = %hu\n", n_ins ));
 
       /* check it */
       max_ins = loader->face->max_profile.maxSizeOfInstructions;
@@ -1391,10 +1400,10 @@
       {
         /* don't trust `maxSizeOfInstructions'; */
         /* only do a rough safety check         */
-        if ( (FT_Int)n_ins > loader->byte_len )
+        if ( n_ins > loader->byte_len )
         {
           FT_TRACE1(( "TT_Process_Composite_Glyph:"
-                      " too many instructions (%d) for glyph with length %d\n",
+                      " too many instructions (%hu) for glyph with length %u\n",
                       n_ins, loader->byte_len ));
           return FT_THROW( Too_Many_Hints );
         }
@@ -1677,7 +1686,7 @@
       FT_ZERO( &inc_stream );
       FT_Stream_OpenMemory( &inc_stream,
                             glyph_data.pointer,
-                            (FT_ULong)glyph_data.length );
+                            glyph_data.length );
 
       loader->stream = &inc_stream;
     }
@@ -1685,8 +1694,7 @@
 
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
-      offset = tt_face_get_location( face, glyph_index,
-                                     (FT_UInt*)&loader->byte_len );
+      offset = tt_face_get_location( face, glyph_index, &loader->byte_len );
 
     if ( loader->byte_len > 0 )
     {
@@ -1705,7 +1713,7 @@
 
       error = face->access_glyph_frame( loader, glyph_index,
                                         face->glyf_offset + offset,
-                                        (FT_UInt)loader->byte_len );
+                                        loader->byte_len );
       if ( error )
         goto Exit;
 
@@ -1739,13 +1747,11 @@
 
     if ( loader->byte_len == 0 || loader->n_contours == 0 )
     {
-      /* must initialize points before (possibly) overriding */
-      /* glyph metrics from the incremental interface        */
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+      tt_get_metrics_incremental( loader, glyph_index );
+#endif
       tt_loader_set_pp( loader );
 
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-      tt_get_metrics_incr_overrides( loader, glyph_index );
-#endif
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
@@ -1828,13 +1834,11 @@
       goto Exit;
     }
 
-    /* must initialize phantom points before (possibly) overriding */
-    /* glyph metrics from the incremental interface                */
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+    tt_get_metrics_incremental( loader, glyph_index );
+#endif
     tt_loader_set_pp( loader );
 
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-    tt_get_metrics_incr_overrides( loader, glyph_index );
-#endif
 
     /***********************************************************************/
     /***********************************************************************/
@@ -1844,7 +1848,7 @@
     /* (which consists of 10 bytes)                            */
     error = face->access_glyph_frame( loader, glyph_index,
                                       face->glyf_offset + offset + 10,
-                                      (FT_UInt)loader->byte_len - 10 );
+                                      loader->byte_len - 10 );
     if ( error )
       goto Exit;
 
@@ -1898,7 +1902,7 @@
       /* clear the nodes filled by sibling chains */
       node = ft_list_get_node_at( &loader->composites, recurse_count );
       for ( node2 = node; node2; node2 = node2->next )
-        node2->data = (void*)FT_ULONG_MAX;
+        node2->data = (void*)-1;
 
       /* check whether we already have a composite glyph with this index */
       if ( FT_List_Find( &loader->composites,
@@ -1915,7 +1919,7 @@
 
       else
       {
-        if ( FT_NEW( node ) )
+        if ( FT_QNEW( node ) )
           goto Exit;
         node->data = FT_UINT_TO_POINTER( glyph_index );
         FT_List_Add( &loader->composites, node );
@@ -2100,7 +2104,7 @@
         FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
 
         FT_Stream    old_stream     = loader->stream;
-        FT_Int       old_byte_len   = loader->byte_len;
+        FT_UInt      old_byte_len   = loader->byte_len;
 
 
         FT_GlyphLoader_Add( gloader );
@@ -2713,6 +2717,9 @@
         error = tt_size_run_prep( size, pedantic );
         if ( error )
           return error;
+        error = TT_Load_Context( exec, face, size );
+        if ( error )
+          return error;
       }
 
       /* check whether the cvt program has disabled hinting */
diff --git a/src/truetype/ttgload.h b/src/truetype/ttgload.h
index 8f72cd5..78fdeaa 100644
--- a/src/truetype/ttgload.h
+++ b/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
  *
  *   TrueType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index b462263..7f2db0c 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
  *
  *   TrueType GX Font Variation loader
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -178,7 +178,7 @@
     /* in the nested loops below we increase `i' twice; */
     /* it is faster to simply allocate one more slot    */
     /* than to add another test within the loop         */
-    if ( FT_NEW_ARRAY( points, n + 1 ) )
+    if ( FT_QNEW_ARRAY( points, n + 1 ) )
       return NULL;
 
     *point_cnt = n;
@@ -264,55 +264,80 @@
     FT_Fixed  *deltas = NULL;
     FT_UInt    runcnt, cnt;
     FT_UInt    i, j;
+    FT_UInt    bytes_used;
     FT_Memory  memory = stream->memory;
     FT_Error   error  = FT_Err_Ok;
 
     FT_UNUSED( error );
 
 
-    if ( delta_cnt > size )
-    {
-      FT_TRACE1(( "ft_var_readpackeddeltas: number of points too large\n" ));
-      return NULL;
-    }
-
-    if ( FT_NEW_ARRAY( deltas, delta_cnt ) )
+    if ( FT_QNEW_ARRAY( deltas, delta_cnt ) )
       return NULL;
 
-    i = 0;
-    while ( i < delta_cnt )
+    i          = 0;
+    bytes_used = 0;
+
+    while ( i < delta_cnt && bytes_used < size )
     {
       runcnt = FT_GET_BYTE();
       cnt    = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
 
+      bytes_used++;
+
       if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
       {
-        /* `runcnt' zeroes get added */
+        /* `cnt` + 1 zeroes get added */
         for ( j = 0; j <= cnt && i < delta_cnt; j++ )
           deltas[i++] = 0;
       }
       else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
       {
-        /* `runcnt' shorts from the stack */
+        /* `cnt` + 1 shorts from the stack */
+        bytes_used += 2 * ( cnt + 1 );
+        if ( bytes_used > size )
+        {
+          FT_TRACE1(( "ft_var_readpackeddeltas:"
+                      " number of short deltas too large\n" ));
+          goto Fail;
+        }
+
         for ( j = 0; j <= cnt && i < delta_cnt; j++ )
           deltas[i++] = FT_intToFixed( FT_GET_SHORT() );
       }
       else
       {
-        /* `runcnt' signed bytes from the stack */
+        /* `cnt` + 1 signed bytes from the stack */
+        bytes_used += cnt + 1;
+        if ( bytes_used > size )
+        {
+          FT_TRACE1(( "ft_var_readpackeddeltas:"
+                      " number of byte deltas too large\n" ));
+          goto Fail;
+        }
+
         for ( j = 0; j <= cnt && i < delta_cnt; j++ )
           deltas[i++] = FT_intToFixed( FT_GET_CHAR() );
       }
 
       if ( j <= cnt )
       {
-        /* bad format */
-        FT_FREE( deltas );
-        return NULL;
+        FT_TRACE1(( "ft_var_readpackeddeltas:"
+                    " number of deltas too large\n" ));
+        goto Fail;
       }
     }
 
+    if ( i < delta_cnt )
+    {
+      FT_TRACE1(( "ft_var_readpackeddeltas: not enough deltas\n" ));
+      goto Fail;
+    }
+
     return deltas;
+
+  Fail:
+    FT_FREE( deltas );
+    return NULL;
   }
 
 
@@ -371,12 +396,13 @@
 
     if ( axisCount != (FT_Long)blend->mmvar->num_axis )
     {
-      FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `fvar'\n"
-                  "                  table are different\n" ));
+      FT_TRACE2(( "ft_var_load_avar:"
+                  " number of axes in `avar' and `fvar'\n" ));
+      FT_TRACE2(( "                  table are different\n" ));
       goto Exit;
     }
 
-    if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
+    if ( FT_QNEW_ARRAY( blend->avar_segment, axisCount ) )
       goto Exit;
 
     segment = &blend->avar_segment[0];
@@ -385,8 +411,8 @@
       FT_TRACE5(( "  axis %d:\n", i ));
 
       segment->pairCount = FT_GET_USHORT();
-      if ( (FT_ULong)segment->pairCount * 4 > table_len                ||
-           FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
+      if ( (FT_ULong)segment->pairCount * 4 > table_len                 ||
+           FT_QNEW_ARRAY( segment->correspondence, segment->pairCount ) )
       {
         /* Failure.  Free everything we have done so far.  We must do */
         /* it right now since loading the `avar' table is optional.   */
@@ -431,7 +457,8 @@
     FT_UShort  format;
     FT_ULong   region_offset;
     FT_UInt    i, j, k;
-    FT_UInt    shortDeltaCount;
+    FT_UInt    wordDeltaCount;
+    FT_Bool    long_words;
 
     GX_Blend        blend = face->blend;
     GX_ItemVarData  varData;
@@ -466,7 +493,7 @@
 
     /* make temporary copy of item variation data offsets; */
     /* we will parse region list first, then come back     */
-    if ( FT_NEW_ARRAY( dataOffsetArray, itemStore->dataCount ) )
+    if ( FT_QNEW_ARRAY( dataOffsetArray, itemStore->dataCount ) )
       goto Exit;
 
     for ( i = 0; i < itemStore->dataCount; i++ )
@@ -486,13 +513,22 @@
     if ( itemStore->axisCount != (FT_Long)blend->mmvar->num_axis )
     {
       FT_TRACE2(( "ft_var_load_item_variation_store:"
-                  " number of axes in item variation store\n"
-                  "                                 "
+                  " number of axes in item variation store\n" ));
+      FT_TRACE2(( "                                 "
                   " and `fvar' table are different\n" ));
       error = FT_THROW( Invalid_Table );
       goto Exit;
     }
 
+    /* new constraint in OpenType 1.8.4 */
+    if ( itemStore->regionCount >= 32768U )
+    {
+      FT_TRACE2(( "ft_var_load_item_variation_store:"
+                  " too many variation region tables\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
     if ( FT_NEW_ARRAY( itemStore->varRegionList, itemStore->regionCount ) )
       goto Exit;
 
@@ -537,15 +573,18 @@
         goto Exit;
 
       if ( FT_READ_USHORT( varData->itemCount )      ||
-           FT_READ_USHORT( shortDeltaCount )         ||
+           FT_READ_USHORT( wordDeltaCount )          ||
            FT_READ_USHORT( varData->regionIdxCount ) )
         goto Exit;
 
+      long_words      = !!( wordDeltaCount & 0x8000 );
+      wordDeltaCount &= 0x7FFF;
+
       /* check some data consistency */
-      if ( shortDeltaCount > varData->regionIdxCount )
+      if ( wordDeltaCount > varData->regionIdxCount )
       {
         FT_TRACE2(( "bad short count %d or region count %d\n",
-                    shortDeltaCount,
+                    wordDeltaCount,
                     varData->regionIdxCount ));
         error = FT_THROW( Invalid_Table );
         goto Exit;
@@ -581,39 +620,52 @@
 
       /* Parse delta set.                                                */
       /*                                                                 */
-      /* On input, deltas are (shortDeltaCount + regionIdxCount) bytes   */
-      /* each; on output, deltas are expanded to `regionIdxCount' shorts */
-      /* each.                                                           */
+      /* On input, deltas are (wordDeltaCount + regionIdxCount) bytes    */
+      /* each if `long_words` isn't set, and twice as much otherwise.    */
+      /*                                                                 */
+      /* On output, deltas are expanded to `regionIdxCount` shorts each. */
       if ( FT_NEW_ARRAY( varData->deltaSet,
                          varData->regionIdxCount * varData->itemCount ) )
         goto Exit;
 
-      /* the delta set is stored as a 2-dimensional array of shorts; */
-      /* sign-extend signed bytes to signed shorts                   */
-      for ( j = 0; j < varData->itemCount * varData->regionIdxCount; )
+      /* the delta set is stored as a 2-dimensional array of shorts */
+      if ( long_words )
       {
-        for ( k = 0; k < shortDeltaCount; k++, j++ )
+        /* new in OpenType 1.9, currently for 'COLR' table only;          */
+        /* the deltas are interpreted as 16.16 fixed-point scaling values */
+
+        /* not supported yet */
+
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+      else
+      {
+        for ( j = 0; j < varData->itemCount * varData->regionIdxCount; )
         {
-          /* read the short deltas */
-          FT_Short  delta;
+          for ( k = 0; k < wordDeltaCount; k++, j++ )
+          {
+            /* read the short deltas */
+            FT_Short  delta;
 
 
-          if ( FT_READ_SHORT( delta ) )
-            goto Exit;
+            if ( FT_READ_SHORT( delta ) )
+              goto Exit;
 
-          varData->deltaSet[j] = delta;
-        }
+            varData->deltaSet[j] = delta;
+          }
 
-        for ( ; k < varData->regionIdxCount; k++, j++ )
-        {
-          /* read the (signed) byte deltas */
-          FT_Char  delta;
+          for ( ; k < varData->regionIdxCount; k++, j++ )
+          {
+            /* read the (signed) byte deltas */
+            FT_Char  delta;
 
 
-          if ( FT_READ_CHAR( delta ) )
-            goto Exit;
+            if ( FT_READ_CHAR( delta ) )
+              goto Exit;
 
-          varData->deltaSet[j] = delta;
+            varData->deltaSet[j] = delta;
+          }
         }
       }
     }
@@ -629,37 +681,66 @@
   ft_var_load_delta_set_index_mapping( TT_Face            face,
                                        FT_ULong           offset,
                                        GX_DeltaSetIdxMap  map,
-                                       GX_ItemVarStore    itemStore )
+                                       GX_ItemVarStore    itemStore,
+                                       FT_ULong           table_len )
   {
     FT_Stream  stream = FT_FACE_STREAM( face );
     FT_Memory  memory = stream->memory;
 
-    FT_Error   error;
+    FT_Error  error;
 
-    FT_UShort  format;
-    FT_UInt    entrySize;
-    FT_UInt    innerBitCount;
-    FT_UInt    innerIndexMask;
-    FT_UInt    i, j;
+    FT_Byte   format;
+    FT_Byte   entryFormat;
+    FT_UInt   entrySize;
+    FT_UInt   innerBitCount;
+    FT_UInt   innerIndexMask;
+    FT_ULong  i;
+    FT_UInt   j;
 
 
-    if ( FT_STREAM_SEEK( offset )        ||
-         FT_READ_USHORT( format )        ||
-         FT_READ_USHORT( map->mapCount ) )
+    if ( FT_STREAM_SEEK( offset )    ||
+         FT_READ_BYTE( format )      ||
+         FT_READ_BYTE( entryFormat ) )
       goto Exit;
 
-    if ( format & 0xFFC0 )
+    if ( format == 0 )
+    {
+      if ( FT_READ_USHORT( map->mapCount ) )
+        goto Exit;
+    }
+    else if ( format == 1 ) /* new in OpenType 1.9 */
+    {
+      if ( FT_READ_ULONG( map->mapCount ) )
+        goto Exit;
+    }
+    else
     {
       FT_TRACE2(( "bad map format %d\n", format ));
       error = FT_THROW( Invalid_Table );
       goto Exit;
     }
 
+    if ( entryFormat & 0xC0 )
+    {
+      FT_TRACE2(( "bad entry format %d\n", format ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
     /* bytes per entry: 1, 2, 3, or 4 */
-    entrySize      = ( ( format & 0x0030 ) >> 4 ) + 1;
-    innerBitCount  = ( format & 0x000F ) + 1;
+    entrySize      = ( ( entryFormat & 0x30 ) >> 4 ) + 1;
+    innerBitCount  = ( entryFormat & 0x0F ) + 1;
     innerIndexMask = ( 1 << innerBitCount ) - 1;
 
+    /* rough sanity check */
+    if ( map->mapCount * entrySize > table_len )
+    {
+      FT_TRACE1(( "ft_var_load_delta_set_index_mapping:"
+                  " invalid number of delta-set index mappings\n" ));
+      error = FT_THROW( Invalid_Table );
+      goto Exit;
+    }
+
     if ( FT_NEW_ARRAY( map->innerIndex, map->mapCount ) )
       goto Exit;
 
@@ -688,7 +769,7 @@
 
       if ( outerIndex >= itemStore->dataCount )
       {
-        FT_TRACE2(( "outerIndex[%d] == %d out of range\n",
+        FT_TRACE2(( "outerIndex[%ld] == %d out of range\n",
                     i,
                     outerIndex ));
         error = FT_THROW( Invalid_Table );
@@ -701,7 +782,7 @@
 
       if ( innerIndex >= itemStore->varData[outerIndex].itemCount )
       {
-        FT_TRACE2(( "innerIndex[%d] == %d out of range\n",
+        FT_TRACE2(( "innerIndex[%ld] == %d out of range\n",
                     i,
                     innerIndex ));
         error = FT_THROW( Invalid_Table );
@@ -826,7 +907,8 @@
                 face,
                 table_offset + widthMap_offset,
                 &table->widthMap,
-                &table->itemStore );
+                &table->itemStore,
+                table_len );
       if ( error )
         goto Exit;
     }
@@ -1515,8 +1597,9 @@
 
     if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
     {
-      FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
-                  "                  table are different\n" ));
+      FT_TRACE1(( "ft_var_load_gvar:"
+                  " number of axes in `gvar' and `cvar'\n" ));
+      FT_TRACE1(( "                  table are different\n" ));
       error = FT_THROW( Invalid_Table );
       goto Exit;
     }
@@ -1558,7 +1641,7 @@
       goto Exit;
 
     /* offsets (one more offset than glyphs, to mark size of last) */
-    if ( FT_NEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) )
+    if ( FT_QNEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) )
       goto Fail2;
 
     if ( gvar_head.flags & 1 )
@@ -1637,8 +1720,8 @@
         goto Fail;
       }
 
-      if ( FT_NEW_ARRAY( blend->tuplecoords,
-                         gvar_head.axisCount * gvar_head.globalCoordCount ) )
+      if ( FT_QNEW_ARRAY( blend->tuplecoords,
+                          gvar_head.axisCount * gvar_head.globalCoordCount ) )
         goto Fail2;
 
       for ( i = 0; i < gvar_head.globalCoordCount; i++ )
@@ -1841,25 +1924,22 @@
       FT_TRACE5(( "    %d: %.5f\n", i, coord / 65536.0 ));
       if ( coord > a->maximum || coord < a->minimum )
       {
-        FT_TRACE1((
-          "ft_var_to_normalized: design coordinate %.5f\n"
-          "                      is out of range [%.5f;%.5f]; clamping\n",
-          coord / 65536.0,
-          a->minimum / 65536.0,
-          a->maximum / 65536.0 ));
-
-        if ( coord > a->maximum )
-          coord = a->maximum;
-        else
-          coord = a->minimum;
+        FT_TRACE1(( "ft_var_to_normalized: design coordinate %.5f\n",
+                    coord / 65536.0 ));
+        FT_TRACE1(( "                      is out of range [%.5f;%.5f];"
+                    " clamping\n",
+                    a->minimum / 65536.0,
+                    a->maximum / 65536.0 ));
       }
 
-      if ( coord < a->def )
-        normalized[i] = -FT_DivFix( SUB_LONG( coord, a->def ),
-                                    SUB_LONG( a->minimum, a->def ) );
-      else if ( coord > a->def )
-        normalized[i] = FT_DivFix( SUB_LONG( coord, a->def ),
+      if ( coord > a->def )
+        normalized[i] = coord >= a->maximum ?  0x10000L :
+                        FT_DivFix( SUB_LONG( coord, a->def ),
                                    SUB_LONG( a->maximum, a->def ) );
+      else if ( coord < a->def )
+        normalized[i] = coord <= a->minimum ? -0x10000L :
+                        FT_DivFix( SUB_LONG( coord, a->def ),
+                                   SUB_LONG( a->def, a->minimum ) );
       else
         normalized[i] = 0;
     }
@@ -2049,7 +2129,7 @@
     FT_Var_Axis*         a;
     FT_Fixed*            c;
     FT_Var_Named_Style*  ns;
-    GX_FVar_Head         fvar_head;
+    GX_FVar_Head         fvar_head  = { 0, 0, 0, 0, 0, 0 };
     FT_Bool              usePsName  = 0;
     FT_UInt              num_instances;
     FT_UInt              num_axes;
@@ -2115,8 +2195,8 @@
         if ( FT_SET_ERROR( face->goto_table( face, TTAG_CFF2,
                                              stream, &table_len ) ) )
         {
-          FT_TRACE1(( "\n"
-                      "TT_Get_MM_Var: `gvar' or `CFF2' table is missing\n" ));
+          FT_TRACE1(( "\n" ));
+          FT_TRACE1(( "TT_Get_MM_Var: `gvar' or `CFF2' table is missing\n" ));
           goto Exit;
         }
       }
@@ -2544,17 +2624,17 @@
       num_coords = mmvar->num_axis;
     }
 
-    FT_TRACE5(( "TT_Set_MM_Blend:\n"
-                "  normalized design coordinates:\n" ));
+    FT_TRACE5(( "TT_Set_MM_Blend:\n" ));
+    FT_TRACE5(( "  normalized design coordinates:\n" ));
 
     for ( i = 0; i < num_coords; i++ )
     {
       FT_TRACE5(( "    %.5f\n", coords[i] / 65536.0 ));
       if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
       {
-        FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n"
-                    "                 is out of range [-1;1]\n",
+        FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.5f\n",
                     coords[i] / 65536.0 ));
+        FT_TRACE1(( "                 is out of range [-1;1]\n" ));
         error = FT_THROW( Invalid_Argument );
         goto Exit;
       }
@@ -2652,9 +2732,10 @@
     }
 
     blend->num_axis = mmvar->num_axis;
-    FT_MEM_COPY( blend->normalizedcoords,
-                 coords,
-                 num_coords * sizeof ( FT_Fixed ) );
+    if ( coords )
+      FT_MEM_COPY( blend->normalizedcoords,
+                   coords,
+                   num_coords * sizeof ( FT_Fixed ) );
 
     if ( set_design_coords )
       ft_var_to_design( face,
@@ -2952,8 +3033,8 @@
     if ( !face->blend->avar_loaded )
       ft_var_load_avar( face );
 
-    FT_TRACE5(( "TT_Set_Var_Design:\n"
-                "  normalized design coordinates:\n" ));
+    FT_TRACE5(( "TT_Set_Var_Design:\n" ));
+    FT_TRACE5(( "  normalized design coordinates:\n" ));
     ft_var_to_normalized( face, num_coords, blend->coords, normalized );
 
     error = tt_set_mm_blend( face, mmvar->num_axis, normalized, 0 );
@@ -3152,6 +3233,8 @@
   /*************************************************************************/
 
 
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
   static FT_Error
   tt_cvt_ready_iterator( FT_ListNode  node,
                          void*        user )
@@ -3166,6 +3249,9 @@
     return FT_Err_Ok;
   }
 
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+
 
   /**************************************************************************
    *
@@ -3194,6 +3280,8 @@
   tt_face_vary_cvt( TT_Face    face,
                     FT_Stream  stream )
   {
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
     FT_Error   error;
     FT_Memory  memory = stream->memory;
 
@@ -3229,16 +3317,16 @@
 
     if ( !blend )
     {
-      FT_TRACE2(( "\n"
-                  "tt_face_vary_cvt: no blend specified\n" ));
+      FT_TRACE2(( "\n" ));
+      FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
       error = FT_Err_Ok;
       goto Exit;
     }
 
     if ( !face->cvt )
     {
-      FT_TRACE2(( "\n"
-                  "tt_face_vary_cvt: no `cvt ' table\n" ));
+      FT_TRACE2(( "\n" ));
+      FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
       error = FT_Err_Ok;
       goto Exit;
     }
@@ -3397,9 +3485,7 @@
                                         point_count == 0 ? face->cvt_size
                                                          : point_count );
 
-      if ( !points                                                        ||
-           !deltas                                                        ||
-           ( localpoints == ALL_POINTS && point_count != face->cvt_size ) )
+      if ( !points || !deltas )
         ; /* failure, ignore it */
 
       else if ( localpoints == ALL_POINTS )
@@ -3514,6 +3600,16 @@
                      NULL );
 
     return error;
+
+#else /* !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    FT_UNUSED( face );
+    FT_UNUSED( stream );
+
+    return FT_Err_Ok;
+
+#endif /* !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
   }
 
 
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 26e89bc..ded9ea1 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
  *
  *   TrueType GX Font Variation loader (specification)
  *
- * Copyright (C) 2004-2020 by
+ * Copyright (C) 2004-2021 by
  * David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -106,9 +106,9 @@
 
   typedef struct  GX_DeltaSetIdxMapRec_
   {
-    FT_UInt   mapCount;
-    FT_UInt*  outerIndex;             /* indices to item var data */
-    FT_UInt*  innerIndex;             /* indices to delta set     */
+    FT_ULong  mapCount;
+    FT_UInt*  outerIndex;               /* indices to item var data */
+    FT_UInt*  innerIndex;               /* indices to delta set     */
 
   } GX_DeltaSetIdxMapRec, *GX_DeltaSetIdxMap;
 
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 0c3cb10..731095e 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
  *
  *   TrueType bytecode interpreter (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -251,6 +251,14 @@
     FT_FREE( exec->stack );
     exec->stackSize = 0;
 
+    /* free glyf cvt working area */
+    FT_FREE( exec->glyfCvt );
+    exec->glyfCvtSize = 0;
+
+    /* free glyf storage working area */
+    FT_FREE( exec->glyfStorage );
+    exec->glyfStoreSize = 0;
+
     /* free call stack */
     FT_FREE( exec->callStack );
     exec->callSize = 0;
@@ -270,64 +278,6 @@
   /**************************************************************************
    *
    * @Function:
-   *   Init_Context
-   *
-   * @Description:
-   *   Initializes a context object.
-   *
-   * @Input:
-   *   memory ::
-   *     A handle to the parent memory object.
-   *
-   * @InOut:
-   *   exec ::
-   *     A handle to the target execution context.
-   *
-   * @Return:
-   *   FreeType error code.  0 means success.
-   */
-  static FT_Error
-  Init_Context( TT_ExecContext  exec,
-                FT_Memory       memory )
-  {
-    FT_Error  error;
-
-
-    FT_TRACE1(( "Init_Context: new object at %p\n", (void *)exec ));
-
-    exec->memory   = memory;
-    exec->callSize = 32;
-
-    if ( FT_NEW_ARRAY( exec->callStack, exec->callSize ) )
-      goto Fail_Memory;
-
-    /* all values in the context are set to 0 already, but this is */
-    /* here as a remainder                                         */
-    exec->maxPoints   = 0;
-    exec->maxContours = 0;
-
-    exec->stackSize = 0;
-    exec->glyphSize = 0;
-
-    exec->stack    = NULL;
-    exec->glyphIns = NULL;
-
-    exec->face = NULL;
-    exec->size = NULL;
-
-    return FT_Err_Ok;
-
-  Fail_Memory:
-    FT_ERROR(( "Init_Context: not enough memory for %p\n", (void *)exec ));
-    TT_Done_Context( exec );
-
-    return error;
- }
-
-
-  /**************************************************************************
-   *
-   * @Function:
    *   Update_Max
    *
    * @Description:
@@ -367,7 +317,7 @@
 
     if ( *size < new_max )
     {
-      if ( FT_REALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
+      if ( FT_QREALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
         return error;
       *size = new_max;
     }
@@ -400,6 +350,8 @@
    *
    * @Note:
    *   Only the glyph loader and debugger should call this function.
+   *
+   *   Note that not all members of `TT_ExecContext` get initialized.
    */
   FT_LOCAL_DEF( FT_Error )
   TT_Load_Context( TT_ExecContext  exec,
@@ -464,13 +416,13 @@
     if ( error )
       return error;
 
-    tmp = exec->glyphSize;
+    tmp = (FT_ULong)exec->glyphSize;
     error = Update_Max( exec->memory,
                         &tmp,
                         sizeof ( FT_Byte ),
                         (void*)&exec->glyphIns,
                         maxp->maxSizeOfInstructions );
-    exec->glyphSize = (FT_UShort)tmp;
+    exec->glyphSize = (FT_UInt)tmp;
     if ( error )
       return error;
 
@@ -609,19 +561,19 @@
 
     memory = driver->root.root.memory;
 
-    /* allocate object */
+    /* allocate object and zero everything inside */
     if ( FT_NEW( exec ) )
       goto Fail;
 
-    /* initialize it; in case of error this deallocates `exec' too */
-    error = Init_Context( exec, memory );
-    if ( error )
-      goto Fail;
+    /* create callStack here, other allocations delayed */
+    exec->memory   = memory;
+    exec->callSize = 32;
 
-    return exec;
+    if ( FT_QNEW_ARRAY( exec->callStack, exec->callSize ) )
+      FT_FREE( exec );
 
   Fail:
-    return NULL;
+    return exec;
   }
 
 
@@ -1572,11 +1524,36 @@
   }
 
 
+  static void
+  Modify_CVT_Check( TT_ExecContext  exc )
+  {
+    /* TT_RunIns sets origCvt and restores cvt to origCvt when done. */
+    if ( exc->iniRange == tt_coderange_glyph &&
+         exc->cvt == exc->origCvt            )
+    {
+      exc->error = Update_Max( exc->memory,
+                               &exc->glyfCvtSize,
+                               sizeof ( FT_Long ),
+                               (void*)&exc->glyfCvt,
+                               exc->cvtSize );
+      if ( exc->error )
+        return;
+
+      FT_ARRAY_COPY( exc->glyfCvt, exc->cvt, exc->glyfCvtSize );
+      exc->cvt = exc->glyfCvt;
+    }
+  }
+
+
   FT_CALLBACK_DEF( void )
   Write_CVT( TT_ExecContext  exc,
              FT_ULong        idx,
              FT_F26Dot6      value )
   {
+    Modify_CVT_Check( exc );
+    if ( exc->error )
+      return;
+
     exc->cvt[idx] = value;
   }
 
@@ -1586,6 +1563,10 @@
                        FT_ULong        idx,
                        FT_F26Dot6      value )
   {
+    Modify_CVT_Check( exc );
+    if ( exc->error )
+      return;
+
     exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) );
   }
 
@@ -1595,6 +1576,10 @@
             FT_ULong        idx,
             FT_F26Dot6      value )
   {
+    Modify_CVT_Check( exc );
+    if ( exc->error )
+      return;
+
     exc->cvt[idx] = ADD_LONG( exc->cvt[idx], value );
   }
 
@@ -1604,6 +1589,10 @@
                       FT_ULong        idx,
                       FT_F26Dot6      value )
   {
+    Modify_CVT_Check( exc );
+    if ( exc->error )
+      return;
+
     exc->cvt[idx] = ADD_LONG( exc->cvt[idx],
                               FT_DivFix( value, Current_Ratio( exc ) ) );
   }
@@ -3125,7 +3114,30 @@
         ARRAY_BOUND_ERROR;
     }
     else
+    {
+      /* TT_RunIns sets origStorage and restores storage to origStorage */
+      /* when done.                                                     */
+      if ( exc->iniRange == tt_coderange_glyph &&
+           exc->storage == exc->origStorage    )
+      {
+        FT_ULong  tmp = (FT_ULong)exc->glyfStoreSize;
+
+
+        exc->error = Update_Max( exc->memory,
+                                 &tmp,
+                                 sizeof ( FT_Long ),
+                                 (void*)&exc->glyfStorage,
+                                 exc->storeSize );
+        exc->glyfStoreSize = (FT_UShort)tmp;
+        if ( exc->error )
+          return;
+
+        FT_ARRAY_COPY( exc->glyfStorage, exc->storage, exc->glyfStoreSize );
+        exc->storage = exc->glyfStorage;
+      }
+
       exc->storage[I] = args[1];
+    }
   }
 
 
@@ -3525,7 +3537,7 @@
       return;
     }
 
-    exc->IP += args[0];
+    exc->IP = ADD_LONG( exc->IP, args[0] );
     if ( exc->IP < 0                                             ||
          ( exc->callTop > 0                                    &&
            exc->IP > exc->callStack[exc->callTop - 1].Def->end ) )
@@ -3697,7 +3709,7 @@
 
 
     /* FDEF is only allowed in `prep' or `fpgm' */
-    if ( exc->curRange == tt_coderange_glyph )
+    if ( exc->iniRange == tt_coderange_glyph )
     {
       exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
       return;
@@ -3771,7 +3783,7 @@
 
             if ( opcode_pointer[i] == opcode_size[i] )
             {
-              FT_TRACE6(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
+              FT_TRACE6(( "sph: Function %d, opcode ptrn: %ld, %s %s\n",
                           i, n,
                           exc->face->root.family_name,
                           exc->face->root.style_name ));
@@ -4133,7 +4145,7 @@
 
 
     /* we enable IDEF only in `prep' or `fpgm' */
-    if ( exc->curRange == tt_coderange_glyph )
+    if ( exc->iniRange == tt_coderange_glyph )
     {
       exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
       return;
@@ -4362,7 +4374,7 @@
 
     if ( ( opcode & 1 ) != 0 )
     {
-      C = B;   /* counter clockwise rotation */
+      C = B;   /* counter-clockwise rotation */
       B = A;
       A = NEG_LONG( C );
     }
@@ -4991,9 +5003,9 @@
 
 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
     /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
-    if ( SUBPIXEL_HINTING_INFINALITY &&
-         exc->ignore_x_mode          &&
-         FT_ABS( D ) == 64           )
+    if ( SUBPIXEL_HINTING_INFINALITY         &&
+         exc->ignore_x_mode                  &&
+         ( D < 0 ? NEG_LONG( D ) : D ) == 64 )
       D += 1;
 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
 
@@ -5050,7 +5062,7 @@
 
     if ( ( opcode & 1 ) != 0 )
     {
-      C = B;   /* counter clockwise rotation */
+      C = B;   /* counter-clockwise rotation */
       B = A;
       A = NEG_LONG( C );
     }
@@ -5074,7 +5086,7 @@
 
     if ( ( opcode & 1 ) != 0 )
     {
-      C = B;   /* counter clockwise rotation */
+      C = B;   /* counter-clockwise rotation */
       B = A;
       A = NEG_LONG( C );
     }
@@ -7781,8 +7793,8 @@
       if ( num_twilight_points > 0xFFFFU )
         num_twilight_points = 0xFFFFU;
 
-      FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n"
-                  "           from %d to the more reasonable value %ld\n",
+      FT_TRACE5(( "TT_RunIns: Resetting number of twilight points\n" ));
+      FT_TRACE5(( "           from %d to the more reasonable value %ld\n",
                   exc->twilight.n_points,
                   num_twilight_points ));
       exc->twilight.n_points = (FT_UShort)num_twilight_points;
@@ -7842,6 +7854,10 @@
       exc->func_move_cvt  = Move_CVT;
     }
 
+    exc->origCvt     = exc->cvt;
+    exc->origStorage = exc->storage;
+    exc->iniRange    = exc->curRange;
+
     Compute_Funcs( exc );
     Compute_Round( exc, (FT_Byte)exc->GS.round_state );
 
@@ -7850,6 +7866,7 @@
       exc->opcode = exc->code[exc->IP];
 
 #ifdef FT_DEBUG_LEVEL_TRACE
+      if ( ft_trace_levels[trace_ttinterp] >= 6 )
       {
         FT_Long  cnt = FT_MIN( 8, exc->top );
         FT_Long  n;
@@ -8566,8 +8583,10 @@
 
       /* increment instruction counter and check if we didn't */
       /* run this program for too long (e.g. infinite loops). */
-      if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
-        return FT_THROW( Execution_Too_Long );
+      if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES ) {
+        exc->error = FT_THROW( Execution_Too_Long );
+        goto LErrorLabel_;
+      }
 
     LSuiteLabel_:
       if ( exc->IP >= exc->codeSize )
@@ -8586,6 +8605,10 @@
     FT_TRACE4(( "  %ld instruction%s executed\n",
                 ins_counter,
                 ins_counter == 1 ? "" : "s" ));
+
+    exc->cvt     = exc->origCvt;
+    exc->storage = exc->origStorage;
+
     return FT_Err_Ok;
 
   LErrorCodeOverflow_:
@@ -8595,6 +8618,9 @@
     if ( exc->error && !exc->instruction_trap )
       FT_TRACE1(( "  The interpreter returned error 0x%x\n", exc->error ));
 
+    exc->cvt     = exc->origCvt;
+    exc->storage = exc->origStorage;
+
     return exc->error;
   }
 
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index 6a83705..9c01ec8 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
  *
  *   TrueType bytecode interpreter (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -144,37 +144,41 @@
    *
    * The main structure for the interpreter which collects all necessary
    * variables and states.
+   *
+   * Members that are initialized by `TT_Load_Context` are marked with '!'.
+   * Members that are initialized by `TT_Run_Context` are marked with '@'.
    */
   typedef struct  TT_ExecContextRec_
   {
-    TT_Face            face;
-    TT_Size            size;
+    TT_Face            face;       /* ! */
+    TT_Size            size;       /* ! */
     FT_Memory          memory;
 
     /* instructions state */
 
     FT_Error           error;      /* last execution error */
 
-    FT_Long            top;        /* top of exec. stack   */
+    FT_Long            top;        /* @ top of exec. stack */
 
-    FT_Long            stackSize;  /* size of exec. stack  */
-    FT_Long*           stack;      /* current exec. stack  */
+    FT_Long            stackSize;  /* ! size of exec. stack */
+    FT_Long*           stack;      /* ! current exec. stack */
 
     FT_Long            args;
-    FT_Long            new_top;    /* new top after exec.  */
+    FT_Long            new_top;    /* new top after exec. */
 
-    TT_GlyphZoneRec    zp0,        /* zone records */
-                       zp1,
-                       zp2,
-                       pts,
-                       twilight;
+    TT_GlyphZoneRec    zp0,        /* @! zone records */
+                       zp1,        /* @!              */
+                       zp2,        /* @!              */
+                       pts,        /*  !              */
+                       twilight;   /*  !              */
 
-    FT_Long            pointSize;  /* in 26.6 format */
-    FT_Size_Metrics    metrics;
-    TT_Size_Metrics    tt_metrics; /* size metrics */
+    FT_Long            pointSize;  /* ! in 26.6 format */
+    FT_Size_Metrics    metrics;    /* !                */
+    TT_Size_Metrics    tt_metrics; /* ! size metrics   */
 
-    TT_GraphicsState   GS;         /* current graphics state */
+    TT_GraphicsState   GS;         /* !@ current graphics state */
 
+    FT_Int             iniRange;  /* initial code range number   */
     FT_Int             curRange;  /* current code range number   */
     FT_Byte*           code;      /* current code range          */
     FT_Long            IP;        /* current instruction pointer */
@@ -185,43 +189,49 @@
 
     FT_Bool            step_ins;  /* true if the interpreter must */
                                   /* increment IP after ins. exec */
-    FT_ULong           cvtSize;
-    FT_Long*           cvt;
+    FT_ULong           cvtSize;   /* ! */
+    FT_Long*           cvt;       /* ! */
+    FT_ULong           glyfCvtSize;
+    FT_Long*           glyfCvt;   /* cvt working copy for glyph */
+    FT_Long*           origCvt;
 
-    FT_UInt            glyphSize; /* glyph instructions buffer size */
-    FT_Byte*           glyphIns;  /* glyph instructions buffer */
+    FT_UInt            glyphSize; /* ! glyph instructions buffer size */
+    FT_Byte*           glyphIns;  /* ! glyph instructions buffer      */
 
-    FT_UInt            numFDefs;  /* number of function defs         */
-    FT_UInt            maxFDefs;  /* maximum number of function defs */
-    TT_DefArray        FDefs;     /* table of FDefs entries          */
+    FT_UInt            numFDefs;  /* ! number of function defs         */
+    FT_UInt            maxFDefs;  /* ! maximum number of function defs */
+    TT_DefArray        FDefs;     /*   table of FDefs entries          */
 
-    FT_UInt            numIDefs;  /* number of instruction defs */
-    FT_UInt            maxIDefs;  /* maximum number of ins defs */
-    TT_DefArray        IDefs;     /* table of IDefs entries     */
+    FT_UInt            numIDefs;  /* ! number of instruction defs */
+    FT_UInt            maxIDefs;  /* ! maximum number of ins defs */
+    TT_DefArray        IDefs;     /*   table of IDefs entries     */
 
-    FT_UInt            maxFunc;   /* maximum function index     */
-    FT_UInt            maxIns;    /* maximum instruction index  */
+    FT_UInt            maxFunc;   /* ! maximum function index    */
+    FT_UInt            maxIns;    /* ! maximum instruction index */
 
-    FT_Int             callTop,    /* top of call stack during execution */
-                       callSize;   /* size of call stack */
-    TT_CallStack       callStack;  /* call stack */
+    FT_Int             callTop,    /* @ top of call stack during execution */
+                       callSize;   /*   size of call stack                 */
+    TT_CallStack       callStack;  /*   call stack                         */
 
     FT_UShort          maxPoints;    /* capacity of this context's `pts' */
     FT_Short           maxContours;  /* record, expressed in points and  */
                                      /* contours.                        */
 
-    TT_CodeRangeTable  codeRangeTable;  /* table of valid code ranges */
-                                        /* useful for the debugger   */
+    TT_CodeRangeTable  codeRangeTable;  /* ! table of valid code ranges */
+                                        /*   useful for the debugger    */
 
-    FT_UShort          storeSize;  /* size of current storage */
-    FT_Long*           storage;    /* storage area            */
+    FT_UShort          storeSize;    /* ! size of current storage */
+    FT_Long*           storage;      /* ! storage area            */
+    FT_UShort          glyfStoreSize;
+    FT_Long*           glyfStorage;  /* storage working copy for glyph */
+    FT_Long*           origStorage;
 
     FT_F26Dot6         period;     /* values used for the */
     FT_F26Dot6         phase;      /* `SuperRounding'     */
     FT_F26Dot6         threshold;
 
-    FT_Bool            instruction_trap; /* If `True', the interpreter will */
-                                         /* exit after each instruction     */
+    FT_Bool            instruction_trap; /* ! If `True', the interpreter   */
+                                         /*   exits after each instruction */
 
     TT_GraphicsState   default_GS;       /* graphics state resulting from   */
                                          /* the prep program                */
@@ -238,7 +248,7 @@
                        func_dualproj,  /* current dual proj. function */
                        func_freeProj;  /* current freedom proj. func  */
 
-    TT_Move_Func       func_move;      /* current point move function */
+    TT_Move_Func       func_move;      /* current point move function     */
     TT_Move_Func       func_move_orig; /* move original position function */
 
     TT_Cur_Ppem_Func   func_cur_ppem;  /* get current proj. ppem value  */
@@ -469,16 +479,15 @@
    *   TT_New_Context
    *
    * @Description:
-   *   Queries the face context for a given font.  Note that there is
-   *   now a _single_ execution context in the TrueType driver which is
-   *   shared among faces.
+   *   Create a `TT_ExecContext`.  Note that there is now an execution
+   *   context per `TT_Size` that is not shared among faces.
    *
    * @Input:
-   *   face ::
-   *     A handle to the source face object.
+   *   driver ::
+   *     A handle to the driver, used for memory allocation.
    *
    * @Return:
-   *   A handle to the execution context.  Initialized for `face'.
+   *   A handle to a new empty execution context.
    *
    * @Note:
    *   Only the glyph loader and debugger should call this function.
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 06d4569..93fc548 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
  *
  *   Objects manager (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -140,7 +140,31 @@
 
     return error;
   }
-#endif /* TT_USE_BYTECODE_INTERPRETER */
+
+
+  /*
+   * Fonts embedded in PDFs are made unique by prepending randomization
+   * prefixes to their names: as defined in Section 5.5.3, 'Font Subsets',
+   * of the PDF Reference, they consist of 6 uppercase letters followed by
+   * the `+` sign.  For safety, we do not skip prefixes violating this rule.
+   */
+
+  static const FT_String*
+  tt_skip_pdffont_random_tag( const FT_String*  name )
+  {
+    unsigned int  i;
+
+
+    if ( ft_strlen( name ) < 8 || name[6] != '+' )
+      return name;
+
+    for ( i = 0; i < 6; i++ )
+      if ( !ft_isupper( name[i] ) )
+        return name;
+
+    FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
+    return name + 7;
+  }
 
 
   /* Compare the face with a list of well-known `tricky' fonts. */
@@ -151,7 +175,7 @@
   {
 
 #define TRICK_NAMES_MAX_CHARACTERS  19
-#define TRICK_NAMES_COUNT           26
+#define TRICK_NAMES_COUNT           20
 
     static const char trick_names[TRICK_NAMES_COUNT]
                                  [TRICK_NAMES_MAX_CHARACTERS + 1] =
@@ -171,22 +195,28 @@
       "DFGirl-W6-WIN-BF",   /* dftt-h6.ttf; version 1.00, 1993 */
       "DFGothic-EB",        /* DynaLab Inc. 1992-1995 */
       "DFGyoSho-Lt",        /* DynaLab Inc. 1992-1995 */
-      "DFHei-Md-HK-BF",     /* maybe DynaLab Inc. */
+      "DFHei",              /* DynaLab Inc. 1992-1995 [DFHei-Bd-WIN-HK-BF] */
+                            /* covers "DFHei-Md-HK-BF", maybe DynaLab Inc. */
+
       "DFHSGothic-W5",      /* DynaLab Inc. 1992-1995 */
       "DFHSMincho-W3",      /* DynaLab Inc. 1992-1995 */
       "DFHSMincho-W7",      /* DynaLab Inc. 1992-1995 */
       "DFKaiSho-SB",        /* dfkaisb.ttf */
-      "DFKaiShu",
-      "DFKaiShu-Md-HK-BF",  /* maybe DynaLab Inc. */
+      "DFKaiShu",           /* covers "DFKaiShu-Md-HK-BF", maybe DynaLab Inc. */
       "DFKai-SB",           /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */
-      "DFMing-Bd-HK-BF",    /* maybe DynaLab Inc. */
+
+      "DFMing",             /* DynaLab Inc. 1992-1995 [DFMing-Md-WIN-HK-BF] */
+                            /* covers "DFMing-Bd-HK-BF", maybe DynaLab Inc. */
+
       "DLC",                /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */
                             /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */
-      "DLCHayMedium",       /* dftt-b5.ttf; version 1.00, 1993 */
-      "DLCHayBold",         /* dftt-b7.ttf; version 1.00, 1993 */
-      "DLCKaiMedium",       /* dftt-k5.ttf; version 1.00, 1992 */
-      "DLCLiShu",           /* dftt-l5.ttf; version 1.00, 1992 */
-      "DLCRoundBold",       /* dftt-r7.ttf; version 1.00, 1993 */
+                            /* covers following */
+                            /* "DLCHayMedium", dftt-b5.ttf; version 1.00, 1993 */
+                            /* "DLCHayBold",   dftt-b7.ttf; version 1.00, 1993 */
+                            /* "DLCKaiMedium", dftt-k5.ttf; version 1.00, 1992 */
+                            /* "DLCLiShu",     dftt-l5.ttf; version 1.00, 1992 */
+                            /* "DLCRoundBold", dftt-r7.ttf; version 1.00, 1993 */
+
       "HuaTianKaiTi?",      /* htkt2.ttf */
       "HuaTianSongTi?",     /* htst3.ttf */
       "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */
@@ -199,10 +229,12 @@
     };
 
     int  nn;
+    const FT_String*  name_without_tag;
 
 
+    name_without_tag = tt_skip_pdffont_random_tag( name );
     for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ )
-      if ( ft_strstr( name, trick_names[nn] ) )
+      if ( ft_strstr( name_without_tag, trick_names[nn] ) )
         return TRUE;
 
     return FALSE;
@@ -277,7 +309,7 @@
   tt_check_trickyness_sfnt_ids( TT_Face  face )
   {
 #define TRICK_SFNT_IDS_PER_FACE   3
-#define TRICK_SFNT_IDS_NUM_FACES  29
+#define TRICK_SFNT_IDS_NUM_FACES  31
 
     static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
                                        [TRICK_SFNT_IDS_PER_FACE] = {
@@ -430,6 +462,16 @@
         { 0x00170003UL, 0x00000060UL }, /* cvt  */
         { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */
         { 0xD643482AUL, 0x00000035UL }  /* prep */
+      },
+        { /* DFHei-Bd-WIN-HK-BF, issue #1087 */
+        { 0x1269EB58UL, 0x00000350UL }, /* cvt  */
+        { 0x5CD5957AUL, 0x00006A4EUL }, /* fpgm */
+        { 0xF758323AUL, 0x00000380UL }  /* prep */
+      },
+        { /* DFMing-Md-WIN-HK-BF, issue #1087 */
+        { 0x122FEB0BUL, 0x00000350UL }, /* cvt  */
+        { 0x7F10919AUL, 0x000070A9UL }, /* fpgm */
+        { 0x7CD7E7B7UL, 0x0000025CUL }  /* prep */
       }
     };
 
@@ -510,17 +552,27 @@
     /* For first, check the face name for quick check. */
     if ( face->family_name                               &&
          tt_check_trickyness_family( face->family_name ) )
+    {
+      FT_TRACE3(( "found as a tricky font"
+                  " by its family name: %s\n", face->family_name ));
       return TRUE;
+    }
 
     /* Type42 fonts may lack `name' tables, we thus try to identify */
     /* tricky fonts by checking the checksums of Type42-persistent  */
     /* sfnt tables (`cvt', `fpgm', and `prep').                     */
     if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) )
+    {
+      FT_TRACE3(( "found as a tricky font"
+                  " by its cvt/fpgm/prep table checksum\n" ));
       return TRUE;
+    }
 
     return FALSE;
   }
 
+#endif /* TT_USE_BYTECODE_INTERPRETER */
+
 
   /* Check whether `.notdef' is the only glyph in the `loca' table. */
   static FT_Bool
@@ -666,8 +718,10 @@
     if ( error )
       goto Exit;
 
+#ifdef TT_USE_BYTECODE_INTERPRETER
     if ( tt_check_trickyness( ttface ) )
       ttface->face_flags |= FT_FACE_FLAG_TRICKY;
+#endif
 
     error = tt_face_load_hdmx( face, stream );
     if ( error )
@@ -712,8 +766,8 @@
              tt_check_single_notdef( ttface ) )
         {
           FT_TRACE5(( "tt_face_init:"
-                      " Only the `.notdef' glyph has an outline.\n"
-                      "             "
+                      " Only the `.notdef' glyph has an outline.\n" ));
+          FT_TRACE5(( "             "
                       " Resetting scalable flag to FALSE.\n" ));
 
           ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE;
@@ -1190,11 +1244,11 @@
     /* rescale CVT when needed */
     if ( size->cvt_ready < 0 )
     {
-      FT_UInt  i;
+      FT_UShort  i;
 
 
       /* all twilight points are originally zero */
-      for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ )
+      for ( i = 0; i < size->twilight.n_points; i++ )
       {
         size->twilight.org[i].x = 0;
         size->twilight.org[i].y = 0;
@@ -1203,7 +1257,7 @@
       }
 
       /* clear storage area */
-      for ( i = 0; i < (FT_UInt)size->storage_size; i++ )
+      for ( i = 0; i < size->storage_size; i++ )
         size->storage[i] = 0;
 
       size->GS = tt_default_graphics_state;
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index d986dea..fd72378 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
  *
  *   Objects manager (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index b1255b8..71db75a 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
  *
  *   TrueType-specific tables loader (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -98,36 +98,23 @@
       goto Exit;
     }
 
-    if ( face->header.Index_To_Loc_Format != 0 )
-    {
-      shift = 2;
+    shift = face->header.Index_To_Loc_Format != 0 ? 2 : 1;
 
-      if ( table_len >= 0x40000L )
-      {
-        FT_TRACE2(( "table too large\n" ));
-        table_len = 0x3FFFFL;
-      }
-      face->num_locations = table_len >> shift;
-    }
-    else
+    if ( table_len > 0x10000UL << shift )
     {
-      shift = 1;
-
-      if ( table_len >= 0x20000L )
-      {
-        FT_TRACE2(( "table too large\n" ));
-        table_len = 0x1FFFFL;
-      }
-      face->num_locations = table_len >> shift;
+      FT_TRACE2(( "table too large\n" ));
+      table_len = 0x10000UL << shift;
     }
 
+    face->num_locations = table_len >> shift;
+
     if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
     {
       FT_TRACE2(( "glyph count mismatch!  loca: %ld, maxp: %ld\n",
                   face->num_locations - 1, face->root.num_glyphs ));
 
       /* we only handle the case where `maxp' gives a larger value */
-      if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
+      if ( face->num_locations < (FT_ULong)face->root.num_glyphs + 1 )
       {
         FT_ULong  new_loca_len =
                     ( (FT_ULong)face->root.num_glyphs + 1 ) << shift;
@@ -237,10 +224,11 @@
     if ( pos1 > face->glyf_len )
     {
       FT_TRACE1(( "tt_face_get_location:"
-                  " too large offset (0x%08lx) found for glyph index %d,\n"
-                  "                     "
+                  " too large offset (0x%08lx) found for glyph index %d,\n",
+                  pos1, gindex ));
+      FT_TRACE1(( "                     "
                   " exceeding the end of `glyf' table (0x%08lx)\n",
-                  pos1, gindex, face->glyf_len ));
+                  face->glyf_len ));
       *asize = 0;
       return 0;
     }
@@ -251,19 +239,21 @@
       if ( gindex == face->num_locations - 2 )
       {
         FT_TRACE1(( "tt_face_get_location:"
-                    " too large size (%ld bytes) found for glyph index %d,\n"
-                    "                     "
+                    " too large size (%ld bytes) found for glyph index %d,\n",
+                    pos2 - pos1, gindex ));
+        FT_TRACE1(( "                     "
                     " truncating at the end of `glyf' table to %ld bytes\n",
-                    pos2 - pos1, gindex, face->glyf_len - pos1 ));
+                    face->glyf_len - pos1 ));
         pos2 = face->glyf_len;
       }
       else
       {
         FT_TRACE1(( "tt_face_get_location:"
-                    " too large offset (0x%08lx) found for glyph index %d,\n"
-                    "                     "
+                    " too large offset (0x%08lx) found for glyph index %d,\n",
+                    pos2, gindex + 1 ));
+        FT_TRACE1(( "                     "
                     " exceeding the end of `glyf' table (0x%08lx)\n",
-                    pos2, gindex + 1, face->glyf_len ));
+                    face->glyf_len ));
         *asize = 0;
         return 0;
       }
@@ -344,7 +334,7 @@
 
     face->cvt_size = table_len / 2;
 
-    if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
+    if ( FT_QNEW_ARRAY( face->cvt, face->cvt_size ) )
       goto Exit;
 
     if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
@@ -557,12 +547,6 @@
     num_records = FT_NEXT_USHORT( p );
     record_size = FT_NEXT_ULONG( p );
 
-    /* The maximum number of bytes in an hdmx device record is the */
-    /* maximum number of glyphs + 2; this is 0xFFFF + 2, thus      */
-    /* explaining why `record_size' is a long (which we read as    */
-    /* unsigned long for convenience).  In practice, two bytes are */
-    /* sufficient to hold the size value.                          */
-    /*                                                             */
     /* There are at least two fonts, HANNOM-A and HANNOM-B version */
     /* 2.0 (2005), which get this wrong: The upper two bytes of    */
     /* the size value are set to 0xFF instead of 0x00.  We catch   */
@@ -571,19 +555,30 @@
     if ( record_size >= 0xFFFF0000UL )
       record_size &= 0xFFFFU;
 
+    FT_TRACE2(( "Hdmx " ));
+
     /* The limit for `num_records' is a heuristic value. */
-    if ( num_records > 255              ||
-         ( num_records > 0            &&
-           ( record_size > 0x10001L ||
-             record_size < 4        ) ) )
+    if ( num_records > 255 || num_records == 0 )
     {
-      error = FT_THROW( Invalid_File_Format );
+      FT_TRACE2(( "with unreasonable %u records rejected\n", num_records ));
       goto Fail;
     }
 
-    if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
+    /* Out-of-spec tables are rejected.  The record size must be */
+    /* equal to the number of glyphs + 2 + 32-bit padding.       */
+    if ( (FT_Long)record_size != ( ( face->root.num_glyphs + 2 + 3 ) & ~3 ) )
+    {
+      FT_TRACE2(( "with record size off by %ld bytes rejected\n",
+                  (FT_Long)record_size -
+                    ( ( face->root.num_glyphs + 2 + 3 ) & ~3 ) ));
+      goto Fail;
+    }
+
+    if ( FT_QNEW_ARRAY( face->hdmx_record_sizes, num_records ) )
       goto Fail;
 
+    /* XXX: We do not check if the records are sorted by ppem */
+    /* and cannot use binary search later.                    */
     for ( nn = 0; nn < num_records; nn++ )
     {
       if ( p + record_size > limit )
@@ -597,6 +592,8 @@
     face->hdmx_table_size   = table_size;
     face->hdmx_record_size  = record_size;
 
+    FT_TRACE2(( "%ux%lu loaded\n", num_records, record_size ));
+
   Exit:
     return error;
 
diff --git a/src/truetype/ttpload.h b/src/truetype/ttpload.h
index bb669e0..84c42cd 100644
--- a/src/truetype/ttpload.h
+++ b/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
  *
  *   TrueType-specific tables loader (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c
index 56667de..c484665 100644
--- a/src/truetype/ttsubpix.c
+++ b/src/truetype/ttsubpix.c
@@ -4,7 +4,7 @@
  *
  *   TrueType Subpixel Hinting.
  *
- * Copyright (C) 2010-2020 by
+ * Copyright (C) 2010-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -315,7 +315,7 @@
   static const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules
                               [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
   {
-    /* fix vwxyz thinness*/
+    /* fix vwxyz thinness */
     { "Consolas", 0, "", 0 },
     /* Fix thin middle stems */
     { "Core MS Legacy Fonts", 0, "Regular", 0 },
@@ -891,12 +891,12 @@
 #define TWEAK_RULES( x )                                       \
   if ( sph_test_tweak( face, family, ppem, style, glyph_index, \
                        x##_Rules, x##_RULES_SIZE ) )           \
-    loader->exec->sph_tweak_flags |= SPH_TWEAK_##x;
+    loader->exec->sph_tweak_flags |= SPH_TWEAK_##x
 
 #define TWEAK_RULES_EXCEPTIONS( x )                                        \
   if ( sph_test_tweak( face, family, ppem, style, glyph_index,             \
                        x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \
-    loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x;
+    loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x
 
 
   FT_LOCAL_DEF( void )
diff --git a/src/truetype/ttsubpix.h b/src/truetype/ttsubpix.h
index 229a6cf..762b7c9 100644
--- a/src/truetype/ttsubpix.h
+++ b/src/truetype/ttsubpix.h
@@ -4,7 +4,7 @@
  *
  *   TrueType Subpixel Hinting.
  *
- * Copyright (C) 2010-2020 by
+ * Copyright (C) 2010-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/module.mk b/src/type1/module.mk
index cffb774..5da4716 100644
--- a/src/type1/module.mk
+++ b/src/type1/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/type1/rules.mk b/src/type1/rules.mk
index 213e619..985248d 100644
--- a/src/type1/rules.mk
+++ b/src/type1/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/type1/t1afm.c b/src/type1/t1afm.c
index b9cd66b..4c18ed1 100644
--- a/src/type1/t1afm.c
+++ b/src/type1/t1afm.c
@@ -4,7 +4,7 @@
  *
  *   AFM support for Type 1 fonts (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -83,7 +83,7 @@
 
 
   /* compare two kerning pairs */
-  FT_CALLBACK_DEF( int )
+  FT_COMPARE_DEF( int )
   compare_kern_pairs( const void*  a,
                       const void*  b )
   {
diff --git a/src/type1/t1afm.h b/src/type1/t1afm.h
index edf919c..86fe45e 100644
--- a/src/type1/t1afm.h
+++ b/src/type1/t1afm.h
@@ -4,7 +4,7 @@
  *
  *   AFM support for Type 1 fonts (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/t1driver.c b/src/type1/t1driver.c
index b786a87..f4d7a08 100644
--- a/src/type1/t1driver.c
+++ b/src/type1/t1driver.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 driver interface (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/t1driver.h b/src/type1/t1driver.h
index e7eae0b..20a827f 100644
--- a/src/type1/t1driver.h
+++ b/src/type1/t1driver.h
@@ -4,7 +4,7 @@
  *
  *   High-level Type 1 driver interface (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/t1errors.h b/src/type1/t1errors.h
index ad03a3d..18ef754 100644
--- a/src/type1/t1errors.h
+++ b/src/type1/t1errors.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/t1gload.c b/src/type1/t1gload.c
index d16b81f..86649ed 100644
--- a/src/type1/t1gload.c
+++ b/src/type1/t1gload.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 Glyph Loader (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -79,7 +79,7 @@
     /* For ordinary fonts get the character data stored in the face record. */
     {
       char_string->pointer = type1->charstrings[glyph_index];
-      char_string->length  = (FT_Int)type1->charstrings_len[glyph_index];
+      char_string->length  = type1->charstrings_len[glyph_index];
     }
 
     if ( !error )
diff --git a/src/type1/t1gload.h b/src/type1/t1gload.h
index 9947507..a924d55 100644
--- a/src/type1/t1gload.h
+++ b/src/type1/t1gload.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 Glyph Loader (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/t1load.c b/src/type1/t1load.c
index 8498600..bb62c79 100644
--- a/src/type1/t1load.c
+++ b/src/type1/t1load.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 font loader (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -117,6 +117,9 @@
         goto Exit;
 
       blend->num_default_design_vector = 0;
+      blend->weight_vector             = NULL;
+      blend->default_weight_vector     = NULL;
+      blend->design_pos[0]             = NULL;
 
       face->blend = blend;
     }
@@ -130,14 +133,11 @@
 
 
         /* allocate the blend `private' and `font_info' dictionaries */
-        if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs     ) ||
-             FT_NEW_ARRAY( blend->privates  [1], num_designs     ) ||
-             FT_NEW_ARRAY( blend->bboxes    [1], num_designs     ) ||
-             FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) )
+        if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) ||
+             FT_NEW_ARRAY( blend->privates  [1], num_designs ) ||
+             FT_NEW_ARRAY( blend->bboxes    [1], num_designs ) )
           goto Exit;
 
-        blend->default_weight_vector = blend->weight_vector + num_designs;
-
         blend->font_infos[0] = &face->type1.font_info;
         blend->privates  [0] = &face->type1.private_dict;
         blend->bboxes    [0] = &face->type1.font_bbox;
@@ -164,21 +164,6 @@
       blend->num_axis = num_axis;
     }
 
-    /* allocate the blend design pos table if needed */
-    num_designs = blend->num_designs;
-    num_axis    = blend->num_axis;
-    if ( num_designs && num_axis && blend->design_pos[0] == 0 )
-    {
-      FT_UInt  n;
-
-
-      if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) )
-        goto Exit;
-
-      for ( n = 1; n < num_designs; n++ )
-        blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
-    }
-
   Exit:
     return error;
 
@@ -580,7 +565,7 @@
   {
     FT_Error  error;
     PS_Blend  blend = face->blend;
-    FT_UInt   n, p;
+    FT_UInt   n;
     FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
 
 
@@ -599,7 +584,7 @@
       PS_DesignMap  map     = blend->design_map + n;
       FT_Long*      designs = map->design_points;
       FT_Fixed*     blends  = map->blend_points;
-      FT_Int        before  = -1, after = -1;
+      FT_Int        p, before  = -1, after = -1;
 
 
       /* use a default value if we don't have a coordinate */
@@ -608,7 +593,7 @@
       else
         design = ( designs[map->num_points - 1] - designs[0] ) / 2;
 
-      for ( p = 0; p < (FT_UInt)map->num_points; p++ )
+      for ( p = 0; p < (FT_Int)map->num_points; p++ )
       {
         FT_Long  p_design = designs[p];
 
@@ -622,11 +607,11 @@
 
         if ( design < p_design )
         {
-          after = (FT_Int)p;
+          after = p;
           break;
         }
 
-        before = (FT_Int)p;
+        before = p;
       }
 
       /* now interpolate if necessary */
@@ -851,7 +836,7 @@
         FT_FREE( name );
       }
 
-      if ( FT_ALLOC( blend->axis_names[n], len + 1 ) )
+      if ( FT_QALLOC( blend->axis_names[n], len + 1 ) )
         goto Exit;
 
       name = (FT_Byte*)blend->axis_names[n];
@@ -872,12 +857,14 @@
   {
     T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
     FT_Int       num_designs;
-    FT_Int       num_axis;
-    T1_Parser    parser = &loader->parser;
+    FT_Int       num_axis = 0; /* make compiler happy */
+    T1_Parser    parser   = &loader->parser;
+    FT_Memory    memory   = face->root.memory;
+    FT_Error     error    = FT_Err_Ok;
+    FT_Fixed*    design_pos[T1_MAX_MM_DESIGNS];
 
-    FT_Error     error = FT_Err_Ok;
-    PS_Blend     blend;
 
+    design_pos[0] = NULL;
 
     /* get the array of design tokens -- compute number of designs */
     T1_ToTokenArray( parser, design_tokens,
@@ -899,12 +886,10 @@
     {
       FT_Byte*  old_cursor = parser->root.cursor;
       FT_Byte*  old_limit  = parser->root.limit;
-      FT_Int    n;
+      FT_Int    n, nn;
+      PS_Blend  blend;
 
 
-      blend    = face->blend;
-      num_axis = 0;  /* make compiler happy */
-
       FT_TRACE4(( " [" ));
 
       for ( n = 0; n < num_designs; n++ )
@@ -937,7 +922,13 @@
                                      (FT_UInt)num_axis );
           if ( error )
             goto Exit;
-          blend = face->blend;
+
+          /* allocate a blend design pos table */
+          if ( FT_QNEW_ARRAY( design_pos[0], num_designs * num_axis ) )
+            goto Exit;
+
+          for ( nn = 1; nn < num_designs; nn++ )
+            design_pos[nn] = design_pos[0] + num_axis * nn;
         }
         else if ( n_axis != num_axis )
         {
@@ -955,8 +946,8 @@
 
           parser->root.cursor = token2->start;
           parser->root.limit  = token2->limit;
-          blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
-          FT_TRACE4(( " %f", (double)blend->design_pos[n][axis] / 65536 ));
+          design_pos[n][axis] = T1_ToFixed( parser, 0 );
+          FT_TRACE4(( " %f", (double)design_pos[n][axis] / 65536 ));
         }
         FT_TRACE4(( "]" )) ;
       }
@@ -965,9 +956,21 @@
 
       loader->parser.root.cursor = old_cursor;
       loader->parser.root.limit  = old_limit;
+
+      /* a valid BlendDesignPosition has been parsed */
+      blend = face->blend;
+      if ( blend->design_pos[0] )
+        FT_FREE( blend->design_pos[0] );
+
+      for ( n = 0; n < num_designs; n++ )
+      {
+        blend->design_pos[n] = design_pos[n];
+        design_pos[n]        = NULL;
+      }
     }
 
   Exit:
+    FT_FREE( design_pos[0] );
     loader->parser.root.error = error;
   }
 
@@ -1044,7 +1047,7 @@
       }
 
       /* allocate design map data */
-      if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) )
+      if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) )
         goto Exit;
       map->blend_points = map->design_points + num_points;
       map->num_points   = (FT_Byte)num_points;
@@ -1088,6 +1091,7 @@
     T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
     FT_Int       num_designs;
     FT_Error     error  = FT_Err_Ok;
+    FT_Memory    memory = face->root.memory;
     T1_Parser    parser = &loader->parser;
     PS_Blend     blend  = face->blend;
     T1_Token     token;
@@ -1122,13 +1126,19 @@
     else if ( blend->num_designs != (FT_UInt)num_designs )
     {
       FT_ERROR(( "parse_weight_vector:"
-                 " /BlendDesignPosition and /WeightVector have\n"
-                 "                    "
+                 " /BlendDesignPosition and /WeightVector have\n" ));
+      FT_ERROR(( "                    "
                  " different number of elements\n" ));
       error = FT_THROW( Invalid_File_Format );
       goto Exit;
     }
 
+    if ( !blend->weight_vector )
+      if ( FT_QNEW_ARRAY( blend->weight_vector, num_designs * 2 ) )
+        goto Exit;
+
+    blend->default_weight_vector = blend->weight_vector + num_designs;
+
     old_cursor = parser->root.cursor;
     old_limit  = parser->root.limit;
 
@@ -1307,9 +1317,9 @@
     else
     {
       FT_TRACE1(( "t1_load_keyword: ignoring keyword `%s'"
-                  " which is not valid at this point\n"
-                  "                 (probably due to missing keywords)\n",
+                  " which is not valid at this point\n",
                  field->ident ));
+      FT_TRACE1(( "                 (probably due to missing keywords)\n" ));
       error = FT_Err_Ok;
     }
 
@@ -1858,7 +1868,7 @@
         }
 
         /* t1_decrypt() shouldn't write to base -- make temporary copy */
-        if ( FT_ALLOC( temp, size ) )
+        if ( FT_QALLOC( temp, size ) )
           goto Fail;
         FT_MEM_COPY( temp, base, size );
         psaux->t1_decrypt( temp, size, 4330 );
@@ -2068,7 +2078,7 @@
           }
 
           /* t1_decrypt() shouldn't write to base -- make temporary copy */
-          if ( FT_ALLOC( temp, size ) )
+          if ( FT_QALLOC( temp, size ) )
             goto Fail;
           FT_MEM_COPY( temp, base, size );
           psaux->t1_decrypt( temp, size, 4330 );
@@ -2578,7 +2588,15 @@
          ( !face->blend->num_designs || !face->blend->num_axis ) )
       T1_Done_Blend( face );
 
-    /* another safety check */
+    /* the font may have no valid WeightVector */
+    if ( face->blend && !face->blend->weight_vector )
+      T1_Done_Blend( face );
+
+    /* the font may have no valid BlendDesignPositions */
+    if ( face->blend && !face->blend->design_pos[0] )
+      T1_Done_Blend( face );
+
+    /* the font may have no valid BlendDesignMap */
     if ( face->blend )
     {
       FT_UInt  i;
diff --git a/src/type1/t1load.h b/src/type1/t1load.h
index 4396415..ba19adb 100644
--- a/src/type1/t1load.h
+++ b/src/type1/t1load.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 font loader (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/t1objs.c b/src/type1/t1objs.c
index 3b918b7..50dad03 100644
--- a/src/type1/t1objs.c
+++ b/src/type1/t1objs.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 objects manager (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -116,11 +116,15 @@
   T1_Size_Request( FT_Size          t1size,     /* T1_Size */
                    FT_Size_Request  req )
   {
+    FT_Error  error;
+
     T1_Size            size  = (T1_Size)t1size;
     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
 
 
-    FT_Request_Metrics( size->root.face, req );
+    error = FT_Request_Metrics( size->root.face, req );
+    if ( error )
+      goto Exit;
 
     if ( funcs )
       funcs->set_scale( (PSH_Globals)t1size->internal->module_data,
@@ -128,7 +132,8 @@
                         size->root.metrics.y_scale,
                         0, 0 );
 
-    return FT_Err_Ok;
+  Exit:
+    return error;
   }
 
 
@@ -217,7 +222,6 @@
     {
       FT_FREE( face->buildchar );
 
-      face->buildchar     = NULL;
       face->len_buildchar = 0;
     }
 
@@ -598,11 +602,7 @@
 
 
     /* set default property values, cf. `ftt1drv.h' */
-#ifdef T1_CONFIG_OPTION_OLD_ENGINE
-    driver->hinting_engine = FT_HINTING_FREETYPE;
-#else
     driver->hinting_engine = FT_HINTING_ADOBE;
-#endif
 
     driver->no_stem_darkening = TRUE;
 
diff --git a/src/type1/t1objs.h b/src/type1/t1objs.h
index 536be8b..5f103b5 100644
--- a/src/type1/t1objs.h
+++ b/src/type1/t1objs.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 objects manager (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/t1parse.c b/src/type1/t1parse.c
index 74cf38b..9f22629 100644
--- a/src/type1/t1parse.c
+++ b/src/type1/t1parse.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 parser (body).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -221,7 +221,7 @@
     else
     {
       /* read segment in memory -- this is clumsy, but so does the format */
-      if ( FT_ALLOC( parser->base_dict, size )       ||
+      if ( FT_QALLOC( parser->base_dict, size )      ||
            FT_STREAM_READ( parser->base_dict, size ) )
         goto Exit;
       parser->base_len = size;
@@ -302,8 +302,8 @@
         goto Fail;
       }
 
-      if ( FT_STREAM_SEEK( start_pos )                           ||
-           FT_ALLOC( parser->private_dict, parser->private_len ) )
+      if ( FT_STREAM_SEEK( start_pos )                            ||
+           FT_QALLOC( parser->private_dict, parser->private_len ) )
         goto Fail;
 
       parser->private_len = 0;
@@ -450,7 +450,7 @@
       if ( parser->in_memory )
       {
         /* note that we allocate one more byte to put a terminating `0' */
-        if ( FT_ALLOC( parser->private_dict, size + 1 ) )
+        if ( FT_QALLOC( parser->private_dict, size + 1 ) )
           goto Fail;
         parser->private_len = size;
       }
diff --git a/src/type1/t1parse.h b/src/type1/t1parse.h
index 1ea0110..247ff73 100644
--- a/src/type1/t1parse.h
+++ b/src/type1/t1parse.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 parser (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/t1tokens.h b/src/type1/t1tokens.h
index c094203..13ac8ac 100644
--- a/src/type1/t1tokens.h
+++ b/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 tokenizer (specification).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type1/type1.c b/src/type1/type1.c
index cadee78..003b78c 100644
--- a/src/type1/type1.c
+++ b/src/type1/type1.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Type 1 driver component (body only).
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type42/module.mk b/src/type42/module.mk
index 6ef3a95..ec3214c 100644
--- a/src/type42/module.mk
+++ b/src/type42/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2002-2020 by
+# Copyright (C) 2002-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/type42/rules.mk b/src/type42/rules.mk
index f4ce91a..9821943 100644
--- a/src/type42/rules.mk
+++ b/src/type42/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 2002-2020 by
+# Copyright (C) 2002-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/type42/t42drivr.c b/src/type42/t42drivr.c
index 90898b4..e74ba1d 100644
--- a/src/type42/t42drivr.c
+++ b/src/type42/t42drivr.c
@@ -4,7 +4,7 @@
  *
  *   High-level Type 42 driver interface (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type42/t42drivr.h b/src/type42/t42drivr.h
index 8bf2afc..c6d8a44 100644
--- a/src/type42/t42drivr.h
+++ b/src/type42/t42drivr.h
@@ -4,7 +4,7 @@
  *
  *   High-level Type 42 driver interface (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type42/t42error.h b/src/type42/t42error.h
index e48132e..470f518 100644
--- a/src/type42/t42error.h
+++ b/src/type42/t42error.h
@@ -4,7 +4,7 @@
  *
  *   Type 42 error codes (specification only).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type42/t42objs.c b/src/type42/t42objs.c
index 6acfcdf..03955e9 100644
--- a/src/type42/t42objs.c
+++ b/src/type42/t42objs.c
@@ -4,7 +4,7 @@
  *
  *   Type 42 objects manager (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -44,7 +44,7 @@
 
     parser = &loader.parser;
 
-    if ( FT_ALLOC( face->ttf_data, 12 ) )
+    if ( FT_QALLOC( face->ttf_data, 12 ) )
       goto Exit;
 
     /* while parsing the font we always update `face->ttf_size' so that */
@@ -510,7 +510,8 @@
 
 
     error = FT_New_Size( t42face->ttf_face, &ttsize );
-    t42size->ttsize = ttsize;
+    if ( !error )
+      t42size->ttsize = ttsize;
 
     FT_Activate_Size( ttsize );
 
@@ -582,6 +583,7 @@
     FT_Face        face    = t42slot->face;
     T42_Face       t42face = (T42_Face)face;
     FT_GlyphSlot   ttslot;
+    FT_Memory      memory  = face->memory;
     FT_Error       error   = FT_Err_Ok;
 
 
@@ -593,9 +595,15 @@
     else
     {
       error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot );
-      slot->ttslot = ttslot;
+      if ( !error )
+        slot->ttslot = ttslot;
     }
 
+    /* share the loader so that the autohinter can see it */
+    FT_GlyphLoader_Done( slot->ttslot->internal->loader );
+    FT_FREE( slot->ttslot->internal );
+    slot->ttslot->internal = t42slot->internal;
+
     return error;
   }
 
@@ -606,6 +614,8 @@
     T42_GlyphSlot  slot = (T42_GlyphSlot)t42slot;
 
 
+    /* do not destroy the inherited internal structure just yet */
+    slot->ttslot->internal = NULL;
     FT_Done_GlyphSlot( slot->ttslot );
   }
 
diff --git a/src/type42/t42objs.h b/src/type42/t42objs.h
index 69f5cff..cbd344f 100644
--- a/src/type42/t42objs.h
+++ b/src/type42/t42objs.h
@@ -4,7 +4,7 @@
  *
  *   Type 42 objects manager (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type42/t42parse.c b/src/type42/t42parse.c
index 9850769..ea2c519 100644
--- a/src/type42/t42parse.c
+++ b/src/type42/t42parse.c
@@ -4,7 +4,7 @@
  *
  *   Type 42 font parser (body).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -197,7 +197,7 @@
     else
     {
       /* read segment in memory */
-      if ( FT_ALLOC( parser->base_dict, size )       ||
+      if ( FT_QALLOC( parser->base_dict, size )      ||
            FT_STREAM_READ( parser->base_dict, size ) )
         goto Exit;
 
@@ -576,6 +576,9 @@
     old_string_size = 0;
     count           = 0;
 
+    FT_TRACE2(( "\n" ));
+    FT_TRACE2(( "t42_parse_sfnts:\n" ));
+
     while ( parser->root.cursor < limit )
     {
       FT_ULong  size;
@@ -611,7 +614,7 @@
           error = FT_THROW( Invalid_File_Format );
           goto Fail;
         }
-        if ( FT_REALLOC( string_buf, old_string_size, string_size ) )
+        if ( FT_QREALLOC( string_buf, old_string_size, string_size ) )
           goto Fail;
 
         allocated = 1;
@@ -680,6 +683,9 @@
         goto Fail;
       }
 
+      FT_TRACE2(( "  PS string size %5lu bytes, offset 0x%08lx (%lu)\n",
+                  string_size, count, count ));
+
       /* The whole TTF is now loaded into `string_buf'.  We are */
       /* checking its contents while copying it to `ttf_data'.  */
 
@@ -702,6 +708,9 @@
             status         = BEFORE_TABLE_DIR;
             face->ttf_size = 12 + 16 * num_tables;
 
+            FT_TRACE2(( "  SFNT directory contains %d tables\n",
+                        num_tables ));
+
             if ( (FT_Long)size < face->ttf_size )
             {
               FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" ));
@@ -709,7 +718,7 @@
               goto Fail;
             }
 
-            if ( FT_REALLOC( face->ttf_data, 12, face->ttf_size ) )
+            if ( FT_QREALLOC( face->ttf_data, 12, face->ttf_size ) )
               goto Fail;
           }
           /* fall through */
@@ -727,12 +736,18 @@
             FT_ULong  len;
 
 
+            FT_TRACE2(( "\n" ));
+            FT_TRACE2(( "  table    length\n" ));
+            FT_TRACE2(( "  ------------------------------\n" ));
+
             for ( i = 0; i < num_tables; i++ )
             {
               FT_Byte*  p = face->ttf_data + 12 + 16 * i + 12;
 
 
               len = FT_PEEK_ULONG( p );
+              FT_TRACE2(( "   %4i  0x%08lx (%lu)\n", i, len, len ));
+
               if ( len > size                               ||
                    face->ttf_size > (FT_Long)( size - len ) )
               {
@@ -748,8 +763,12 @@
 
             status = OTHER_TABLES;
 
-            if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
-                             face->ttf_size + 1 ) )
+            FT_TRACE2(( "\n" ));
+            FT_TRACE2(( "  allocating %ld bytes\n", face->ttf_size + 1 ));
+            FT_TRACE2(( "\n" ));
+
+            if ( FT_QREALLOC( face->ttf_data, 12 + 16 * num_tables,
+                              face->ttf_size + 1 ) )
               goto Fail;
           }
           /* fall through */
diff --git a/src/type42/t42parse.h b/src/type42/t42parse.h
index 2ccf052..0fbd2b5 100644
--- a/src/type42/t42parse.h
+++ b/src/type42/t42parse.h
@@ -4,7 +4,7 @@
  *
  *   Type 42 font parser (specification).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type42/t42types.h b/src/type42/t42types.h
index ba0cc21..ea2f03e 100644
--- a/src/type42/t42types.h
+++ b/src/type42/t42types.h
@@ -4,7 +4,7 @@
  *
  *   Type 42 font data types (specification only).
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * Roberto Alameda.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/type42/type42.c b/src/type42/type42.c
index 012559e..d8d3936 100644
--- a/src/type42/type42.c
+++ b/src/type42/type42.c
@@ -4,7 +4,7 @@
  *
  *   FreeType Type 42 driver component.
  *
- * Copyright (C) 2002-2020 by
+ * Copyright (C) 2002-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/winfonts/fnterrs.h b/src/winfonts/fnterrs.h
index 550de38..d582a9b 100644
--- a/src/winfonts/fnterrs.h
+++ b/src/winfonts/fnterrs.h
@@ -4,7 +4,7 @@
  *
  *   Win FNT/FON error codes (specification only).
  *
- * Copyright (C) 2001-2020 by
+ * Copyright (C) 2001-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/winfonts/module.mk b/src/winfonts/module.mk
index 4614c55..4a8580c 100644
--- a/src/winfonts/module.mk
+++ b/src/winfonts/module.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/winfonts/rules.mk b/src/winfonts/rules.mk
index e73ef5e..1384f23 100644
--- a/src/winfonts/rules.mk
+++ b/src/winfonts/rules.mk
@@ -3,7 +3,7 @@
 #
 
 
-# Copyright (C) 1996-2020 by
+# Copyright (C) 1996-2021 by
 # David Turner, Robert Wilhelm, and Werner Lemberg.
 #
 # This file is part of the FreeType project, and may only be used, modified,
diff --git a/src/winfonts/winfnt.c b/src/winfonts/winfnt.c
index e83312d..b4fabad 100644
--- a/src/winfonts/winfnt.c
+++ b/src/winfonts/winfnt.c
@@ -4,7 +4,7 @@
  *
  *   FreeType font driver for Windows FNT/FON files
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  * Copyright 2003 Huw D M Davies for Codeweavers
  * Copyright 2007 Dmitry Timoshkov for Codeweavers
@@ -217,7 +217,11 @@
     /* first of all, read the FNT header */
     if ( FT_STREAM_SEEK( font->offset )                        ||
          FT_STREAM_READ_FIELDS( winfnt_header_fields, header ) )
+    {
+      FT_TRACE2(( "  not a Windows FNT file\n" ));
+      error = FT_THROW( Unknown_File_Format );
       goto Exit;
+    }
 
     /* check header */
     if ( header->version != 0x200 &&
@@ -284,7 +288,10 @@
     /* does it begin with an MZ header? */
     if ( FT_STREAM_SEEK( 0 )                                      ||
          FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) )
+    {
+      error = FT_ERR( Unknown_File_Format );
       goto Exit;
+    }
 
     error = FT_ERR( Unknown_File_Format );
     if ( mz_header.magic == WINFNT_MZ_MAGIC )
@@ -420,12 +427,12 @@
           goto Exit;
 
         FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "
-                    "size_of_optional_header %02x\n"
-                    "magic32 %02x, rsrc_virtual_address %04lx, "
-                    "rsrc_size %04lx\n",
+                    "size_of_optional_header %02x\n",
                     pe32_header.magic, pe32_header.machine,
                     pe32_header.number_of_sections,
-                    pe32_header.size_of_optional_header,
+                    pe32_header.size_of_optional_header ));
+        FT_TRACE2(( "magic32 %02x, rsrc_virtual_address %04lx, "
+                    "rsrc_size %04lx\n",
                     pe32_header.magic32, pe32_header.rsrc_virtual_address,
                     pe32_header.rsrc_size ));
 
@@ -793,7 +800,7 @@
         root->style_flags |= FT_STYLE_FLAG_BOLD;
 
       /* set up the `fixed_sizes' array */
-      if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
+      if ( FT_QNEW( root->available_sizes ) )
         goto Fail;
 
       root->num_fixed_sizes = 1;
@@ -885,10 +892,10 @@
       }
       family_size = font->header.file_size - font->header.face_name_offset;
       /* Some broken fonts don't delimit the face name with a final */
-      /* NULL byte -- the frame is erroneously one byte too small.  */
+      /* null byte -- the frame is erroneously one byte too small.  */
       /* We thus allocate one more byte, setting it explicitly to   */
       /* zero.                                                      */
-      if ( FT_ALLOC( font->family_name, family_size + 1 ) )
+      if ( FT_QALLOC( font->family_name, family_size + 1 ) )
         goto Fail;
 
       FT_MEM_COPY( font->family_name,
@@ -897,9 +904,10 @@
 
       font->family_name[family_size] = '\0';
 
-      if ( FT_REALLOC( font->family_name,
-                       family_size,
-                       ft_strlen( font->family_name ) + 1 ) )
+      /* shrink it to the actual length */
+      if ( FT_QREALLOC( font->family_name,
+                        family_size + 1,
+                        ft_strlen( font->family_name ) + 1 ) )
         goto Fail;
 
       root->family_name = font->family_name;
@@ -1094,7 +1102,7 @@
 
       /* note: since glyphs are stored in columns and not in rows we */
       /*       can't use ft_glyphslot_set_bitmap                     */
-      if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, pitch ) )
+      if ( FT_QALLOC_MULT( bitmap->buffer, bitmap->rows, pitch ) )
         goto Exit;
 
       column = (FT_Byte*)bitmap->buffer;
diff --git a/src/winfonts/winfnt.h b/src/winfonts/winfnt.h
index 3367c77..a7134ab 100644
--- a/src/winfonts/winfnt.h
+++ b/src/winfonts/winfnt.h
@@ -4,7 +4,7 @@
  *
  *   FreeType font driver for Windows FNT/FON files
  *
- * Copyright (C) 1996-2020 by
+ * Copyright (C) 1996-2021 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  * Copyright 2007 Dmitry Timoshkov for Codeweavers
  *
diff --git a/subprojects/dlg b/subprojects/dlg
new file mode 160000
index 0000000..d142e64
--- /dev/null
+++ b/subprojects/dlg
@@ -0,0 +1 @@
+Subproject commit d142e646e263c89f93663e027c2f0d03739ab42d
diff --git a/subprojects/libpng.wrap b/subprojects/libpng.wrap
new file mode 100644
index 0000000..94435e8
--- /dev/null
+++ b/subprojects/libpng.wrap
@@ -0,0 +1,12 @@
+[wrap-file]
+directory = libpng-1.6.37
+source_url = https://github.com/glennrp/libpng/archive/v1.6.37.tar.gz
+source_filename = libpng-1.6.37.tar.gz
+source_hash = ca74a0dace179a8422187671aee97dd3892b53e168627145271cad5b5ac81307
+patch_filename = libpng_1.6.37-5_patch.zip
+patch_url = https://wrapdb.mesonbuild.com/v2/libpng_1.6.37-5/get_patch
+patch_hash = 822200906ad2e82dc8b44e79fe960e980ccad96263548c35eef721086a9926f1
+
+[provide]
+libpng = libpng_dep
+
diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap
new file mode 100644
index 0000000..ce20fb0
--- /dev/null
+++ b/subprojects/zlib.wrap
@@ -0,0 +1,12 @@
+[wrap-file]
+directory = zlib-1.2.11
+source_url = http://zlib.net/fossils/zlib-1.2.11.tar.gz
+source_filename = zlib-1.2.11.tar.gz
+source_hash = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
+patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.11/5/get_zip
+patch_filename = zlib-1.2.11-5-wrap.zip
+patch_hash = 728c8e24acbc2e6682fbd950fec39e2fc77528af361adb87259f8a8511434004
+
+[provide]
+zlib = zlib_dep
+
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 0000000..0d0b99a
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,22 @@
+# Unit and regression tests for the FreeType library
+
+## Quick Start
+
+### Download test fonts
+
+Run the `tests/scripts/download-fonts.py` script, which will
+download test fonts to the `tests/data/` directory first.
+
+### Build the test programs
+
+The tests are only built with the Meson build system, and
+are disabled by default, enable the 'tests' option to compile
+them, as in:
+
+  meson setup out -Dtests=enabled
+  meson compile -C out
+
+### Run the test programs
+
+  meson test -C out
+
diff --git a/tests/issue-1063/main.c b/tests/issue-1063/main.c
new file mode 100644
index 0000000..fd5404e
--- /dev/null
+++ b/tests/issue-1063/main.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+
+#include <freetype/freetype.h>
+#include <ft2build.h>
+
+
+int
+main( void )
+{
+  FT_Library  library;
+  FT_Face     face = NULL;
+
+  /*
+   * We assume that `FREETYPE_TESTS_DATA_DIR` was set by `meson test`.
+   * Otherwise we default to `../tests/data`.
+   *
+   * TODO (David): Rewrite this to pass the test directory through the
+   * command-line.
+   */
+  const char*  testdata_dir = getenv( "FREETYPE_TESTS_DATA_DIR" );
+  char         filepath[FILENAME_MAX];
+
+
+  snprintf( filepath, sizeof( filepath ), "%s/%s",
+            testdata_dir ? testdata_dir : "../tests/data",
+            "As.I.Lay.Dying.ttf" );
+
+  FT_Init_FreeType( &library );
+  if ( FT_New_Face( library, filepath, 0, &face ) != 0 )
+  {
+    fprintf( stderr, "Could not open file: %s\n", filepath );
+    return 1;
+  }
+
+  for ( FT_ULong  i = 59; i < 171; i++ )
+  {
+    FT_UInt   gid  = FT_Get_Char_Index( face, i );
+    FT_Error  code = FT_Load_Glyph( face, gid, FT_LOAD_DEFAULT );
+
+
+    if ( code )
+      printf( "unknown %d for char %lu, gid %u\n", code, i, gid );
+  }
+
+  return 0;
+}
+
+/* EOF */
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 0000000..527998f
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,14 @@
+test_issue_1063 = executable('issue-1063',
+  files([ 'issue-1063/main.c' ]),
+  dependencies: freetype_dep,
+)
+
+test_env = ['FREETYPE_TESTS_DATA_DIR='
+            + join_paths(meson.current_source_dir(), 'data')]
+
+test('issue-1063',
+  test_issue_1063,
+  env: test_env,
+  suite: 'regression')
+
+# EOF
diff --git a/tests/scripts/download-test-fonts.py b/tests/scripts/download-test-fonts.py
new file mode 100755
index 0000000..52b742e
--- /dev/null
+++ b/tests/scripts/download-test-fonts.py
@@ -0,0 +1,302 @@
+#!/usr/bin/env python3
+
+"""Download test fonts used by the FreeType regression test programs.  These
+will be copied to $FREETYPE/tests/data/ by default."""
+
+import argparse
+import collections
+import hashlib
+import io
+import os
+import requests
+import sys
+import zipfile
+
+from typing import Callable, List, Optional, Tuple
+
+# The list of download items describing the font files to install.  Each
+# download item is a dictionary with one of the following schemas:
+#
+# - File item:
+#
+#      file_url
+#        Type: URL string.
+#        Required: Yes.
+#        Description: URL to download the file from.
+#
+#      install_name
+#        Type: file name string
+#        Required: No
+#        Description: Installation name for the font file, only provided if
+#          it must be different from the original URL's basename.
+#
+#      hex_digest
+#        Type: hexadecimal string
+#        Required: No
+#        Description: Digest of the input font file.
+#
+# - Zip items:
+#
+#   These items correspond to one or more font files that are embedded in a
+#   remote zip archive.  Each entry has the following fields:
+#
+#      zip_url
+#        Type: URL string.
+#        Required: Yes.
+#        Description: URL to download the zip archive from.
+#
+#      zip_files
+#        Type: List of file entries (see below)
+#        Required: Yes
+#        Description: A list of entries describing a single font file to be
+#          extracted from the archive
+#
+# Apart from that, some schemas are used for dictionaries used inside
+# download items:
+#
+# - File entries:
+#
+#   These are dictionaries describing a single font file to extract from an
+#   archive.
+#
+#      filename
+#        Type: file path string
+#        Required: Yes
+#        Description: Path of source file, relative to the archive's
+#          top-level directory.
+#
+#      install_name
+#        Type: file name string
+#        Required: No
+#        Description: Installation name for the font file; only provided if
+#          it must be different from the original filename value.
+#
+#      hex_digest
+#        Type: hexadecimal string
+#        Required: No
+#        Description: Digest of the input source file
+#
+_DOWNLOAD_ITEMS = [
+    {
+        "zip_url": "https://github.com/python-pillow/Pillow/files/6622147/As.I.Lay.Dying.zip",
+        "zip_files": [
+            {
+                "filename": "As I Lay Dying.ttf",
+                "install_name": "As.I.Lay.Dying.ttf",
+                "hex_digest": "ef146bbc2673b387",
+            },
+        ],
+    },
+]
+
+
+def digest_data(data: bytes):
+    """Compute the digest of a given input byte string, which are the first
+    8 bytes of its sha256 hash."""
+    m = hashlib.sha256()
+    m.update(data)
+    return m.digest()[:8]
+
+
+def check_existing(path: str, hex_digest: str):
+    """Return True if |path| exists and matches |hex_digest|."""
+    if not os.path.exists(path) or hex_digest is None:
+        return False
+
+    with open(path, "rb") as f:
+        existing_content = f.read()
+
+    return bytes.fromhex(hex_digest) == digest_data(existing_content)
+
+
+def install_file(content: bytes, dest_path: str):
+    """Write a byte string to a given destination file.
+
+    Args:
+      content: Input data, as a byte string
+      dest_path: Installation path
+    """
+    parent_path = os.path.dirname(dest_path)
+    if not os.path.exists(parent_path):
+        os.makedirs(parent_path)
+
+    with open(dest_path, "wb") as f:
+        f.write(content)
+
+
+def download_file(url: str, expected_digest: Optional[bytes] = None):
+    """Download a file from a given URL.
+
+    Args:
+      url: Input URL
+      expected_digest: Optional digest of the file
+        as a byte string
+    Returns:
+      URL content as binary string.
+    """
+    r = requests.get(url, allow_redirects=True)
+    content = r.content
+    if expected_digest is not None:
+        digest = digest_data(r.content)
+        if digest != expected_digest:
+            raise ValueError(
+                "%s has invalid digest %s (expected %s)"
+                % (url, digest.hex(), expected_digest.hex())
+            )
+
+    return content
+
+
+def extract_file_from_zip_archive(
+    archive: zipfile.ZipFile,
+    archive_name: str,
+    filepath: str,
+    expected_digest: Optional[bytes] = None,
+):
+    """Extract a file from a given zipfile.ZipFile archive.
+
+    Args:
+      archive: Input ZipFile objec.
+      archive_name: Archive name or URL, only used to generate a
+        human-readable error message.
+
+      filepath: Input filepath in archive.
+      expected_digest: Optional digest for the file.
+    Returns:
+      A new File instance corresponding to the extract file.
+    Raises:
+      ValueError if expected_digest is not None and does not match the
+      extracted file.
+    """
+    file = archive.open(filepath)
+    if expected_digest is not None:
+        digest = digest_data(archive.open(filepath).read())
+        if digest != expected_digest:
+            raise ValueError(
+                "%s in zip archive at %s has invalid digest %s (expected %s)"
+                % (filepath, archive_name, digest.hex(), expected_digest.hex())
+            )
+    return file.read()
+
+
+def _get_and_install_file(
+    install_path: str,
+    hex_digest: Optional[str],
+    force_download: bool,
+    get_content: Callable[[], bytes],
+) -> bool:
+    if not force_download and hex_digest is not None \
+      and os.path.exists(install_path):
+        with open(install_path, "rb") as f:
+            content: bytes = f.read()
+        if bytes.fromhex(hex_digest) == digest_data(content):
+            return False
+
+    content = get_content()
+    install_file(content, install_path)
+    return True
+
+
+def download_and_install_item(
+    item: dict, install_dir: str, force_download: bool
+) -> List[Tuple[str, bool]]:
+    """Download and install one item.
+
+    Args:
+      item: Download item as a dictionary, see above for schema.
+      install_dir: Installation directory.
+      force_download: Set to True to force download and installation, even
+        if the font file is already installed with the right content.
+
+    Returns:
+      A list of (install_name, status) tuples, where 'install_name' is the
+      file's installation name under 'install_dir', and 'status' is a
+      boolean that is True to indicate that the file was downloaded and
+      installed, or False to indicate that the file is already installed
+      with the right content.
+    """
+    if "file_url" in item:
+        file_url = item["file_url"]
+        install_name = item.get("install_name", os.path.basename(file_url))
+        install_path = os.path.join(install_dir, install_name)
+        hex_digest = item.get("hex_digest")
+
+        def get_content():
+            return download_file(file_url, hex_digest)
+
+        status = _get_and_install_file(
+            install_path, hex_digest, force_download, get_content
+        )
+        return [(install_name, status)]
+
+    if "zip_url" in item:
+        # One or more files from a zip archive.
+        archive_url = item["zip_url"]
+        archive = zipfile.ZipFile(io.BytesIO(download_file(archive_url)))
+
+        result = []
+        for f in item["zip_files"]:
+            filename = f["filename"]
+            install_name = f.get("install_name", filename)
+            hex_digest = f.get("hex_digest")
+
+            def get_content():
+                return extract_file_from_zip_archive(
+                    archive,
+                    archive_url,
+                    filename,
+                    bytes.fromhex(hex_digest) if hex_digest else None,
+                )
+
+            status = _get_and_install_file(
+                os.path.join(install_dir, install_name),
+                hex_digest,
+                force_download,
+                get_content,
+            )
+            result.append((install_name, status))
+
+        return result
+
+    else:
+        raise ValueError("Unknown download item schema: %s" % item)
+
+
+def main():
+    parser = argparse.ArgumentParser(description=__doc__)
+
+    # Assume this script is under tests/scripts/ and tests/data/
+    # is the default installation directory.
+    install_dir = os.path.normpath(
+        os.path.join(os.path.dirname(__file__), "..", "data")
+    )
+
+    parser.add_argument(
+        "--force",
+        action="store_true",
+        default=False,
+        help="Force download and installation of font files",
+    )
+
+    parser.add_argument(
+        "--install-dir",
+        default=install_dir,
+        help="Specify installation directory [%s]" % install_dir,
+    )
+
+    args = parser.parse_args()
+
+    for item in _DOWNLOAD_ITEMS:
+        for install_name, status in download_and_install_item(
+            item, args.install_dir, args.force
+        ):
+            print("%s %s" % (install_name,
+                             "INSTALLED" if status else "UP-TO-DATE"))
+
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(main())
+
+# EOF
diff --git a/version.sed b/version.sed
deleted file mode 100644
index c281ff5..0000000
--- a/version.sed
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /usr/bin/sed -nf
-
-s/^#define  *FREETYPE_MAJOR  *\([^ ][^ ]*\).*$/freetype_major="\1" ;/p
-s/^#define  *FREETYPE_MINOR  *\([^ ][^ ]*\).*$/freetype_minor=".\1" ;/p
-s/^#define  *FREETYPE_PATCH  *\([^ ][^ ]*\).*$/freetype_patch=".\1" ;/p
diff --git a/vms_make.com b/vms_make.com
index d0f4909..6e6337d 100644
--- a/vms_make.com
+++ b/vms_make.com
@@ -1,6 +1,6 @@
 $! make FreeType 2 under OpenVMS
 $!
-$! Copyright (C) 2003-2020 by
+$! Copyright (C) 2003-2021 by
 $! David Turner, Robert Wilhelm, and Werner Lemberg.
 $!
 $! This file is part of the FreeType project, and may only be used, modified,