fontconfig: Branch 'main' - 5 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Apr 23 15:15:51 UTC 2025


 .gitlab-ci.yml                |    4 
 .gitlab-ci/ci.template        |    3 
 .gitlab-ci/fedora-install.sh  |    2 
 .gitlab-ci/freebsd-install.sh |    1 
 build-aux/fetch-testfonts.py  |  193 ++++++++++++++++++++++++++++++++++++++++++
 meson.build                   |    1 
 test/meson.build              |   21 +++-
 test/test_issue431.py         |   37 +++++---
 8 files changed, 244 insertions(+), 18 deletions(-)

New commits:
commit a352486ad464084ac765b8c954a6d3fc6dc3b0e6
Merge: 88ee3ad 1911d1c
Author: Akira TAGOH <akira at tagoh.org>
Date:   Wed Apr 23 15:15:48 2025 +0000

    Merge branch 'crosTestFonts' into 'main'
    
    [Fontations] Local and container download of test font files
    
    See merge request fontconfig/fontconfig!386

commit 1911d1ce00ae3b088aeba5326e5205e64b2238f7
Author: Dominik Röttsches <drott at chromium.org>
Date:   Wed Apr 23 15:27:21 2025 +0300

    Migrate pytest testcase 431 to pre-downloaded fonts

diff --git a/test/meson.build b/test/meson.build
index da5ac1f..895dbab 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -92,9 +92,10 @@ if host_machine.system() != 'windows'
   if pytest.found()
     test('pytest', pytest, args: ['--tap'],
          workdir: meson.current_source_dir(),
-         env: ['builddir=@0@'.format(meson.current_build_dir())],
+         env: ['builddir=@0@'.format(meson.project_build_root())],
          protocol: 'tap',
-         timeout: 600)
+         timeout: 600,
+         depends: fetch_test_fonts)
   endif
 endif
 
diff --git a/test/test_issue431.py b/test/test_issue431.py
index 55ca2b4..ba0b336 100644
--- a/test/test_issue431.py
+++ b/test/test_issue431.py
@@ -12,16 +12,29 @@ from pathlib import Path
 
 
 def test_issue431(tmp_path):
-    req = requests.get('https://github.com/googlefonts/roboto-flex/releases/download/3.100/roboto-flex-fonts.zip',
-                       allow_redirects=True)
-    with open(tmp_path / 'roboto-flex-fonts.zip', 'wb') as f:
-        f.write(req.content)
-    shutil.unpack_archive(tmp_path / 'roboto-flex-fonts.zip', tmp_path)
-    builddir = Path(os.environ.get('builddir', Path(__file__).parent)).parent
-    result = subprocess.run([builddir / 'fc-query' / 'fc-query', '-f', '%{family[0]}:%{index}:%{style[0]}:%{postscriptname}\n', tmp_path / 'roboto-flex-fonts/fonts/variable/RobotoFlex[GRAD,XOPQ,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght].ttf'], stdout=subprocess.PIPE)
+    builddir = Path(os.environ.get("builddir", Path(__file__).parent.parent))
+    roboto_flex_font = (
+        builddir
+        / "testfonts"
+        / "roboto-flex-fonts/fonts/variable/RobotoFlex[GRAD,XOPQ,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC,opsz,slnt,wdth,wght].ttf"
+    )
 
-    for line in result.stdout.decode('utf-8').splitlines():
-        family, index, style, psname = line.split(':')
-        normstyle = re.sub('[\x04\\(\\)/<>\\[\\]{}\t\f\r\n ]', '', style)
-        assert psname.split('-')[-1] == normstyle, \
-            f'postscriptname `{psname}\' does not contain style name `{normstyle}\': index {index}'
+    if not roboto_flex_font.exists():
+        pytest.skip(f"Font file not found: {roboto_flex_font}")
+
+    result = subprocess.run(
+        [
+            builddir / "fc-query" / "fc-query",
+            "-f",
+            "%{family[0]}:%{index}:%{style[0]}:%{postscriptname}\n",
+            roboto_flex_font,
+        ],
+        stdout=subprocess.PIPE,
+    )
+
+    for line in result.stdout.decode("utf-8").splitlines():
+        family, index, style, psname = line.split(":")
+        normstyle = re.sub("[\x04\\(\\)/<>\\[\\]{}\t\f\r\n ]", "", style)
+        assert (
+            psname.split("-")[-1] == normstyle
+        ), f"postscriptname `{psname}' does not contain style name `{normstyle}': index {index}"
commit 00c57ca34ac1c532a0568c7584558185ddeb866e
Author: Dominik Röttsches <drott at chromium.org>
Date:   Wed Apr 23 15:27:52 2025 +0300

    Add Roboto Flex to font downloading script
    
    Preparation for removing custom download from issue 431 testcase.

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8920035..a783d87 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -43,8 +43,8 @@ variables:
 # changing these will force rebuilding the associated image
 # Note: these tags have no meaning and are not tied to a particular
 # fontconfig version
-  FEDORA_TAG:    '2025-04-23.1-21487182ca34'
-  FREEBSD_TAG:   '2025-04-23.1-1c3182609f3d'
+  FEDORA_TAG:    '2025-04-23.1-36c045e261d1'
+  FREEBSD_TAG:   '2025-04-23.1-61a4c35ef3b2'
 
   FEDORA_EXEC:   'bash .gitlab-ci/fedora-install.sh'
   FREEBSD_EXEC:  'bash .gitlab-ci/freebsd-install.sh'
diff --git a/build-aux/fetch-testfonts.py b/build-aux/fetch-testfonts.py
index 0bec884..85f11a1 100755
--- a/build-aux/fetch-testfonts.py
+++ b/build-aux/fetch-testfonts.py
@@ -30,6 +30,7 @@ SOURCE_FILES = (
     "ko-nanumfonts-3.20.tar.bz2",
 )
 SOURCES = [URL_TEMPLATE % source for source in SOURCE_FILES]
+SOURCES += ["https://github.com/googlefonts/roboto-flex/releases/download/3.100/roboto-flex-fonts.zip"]
 
 CONTAINER_DOWNLOAD_DIR = "/testfonts"
 
@@ -41,6 +42,7 @@ notofonts-20250214.tar.xz      cb0f9edc030e07eca58b799c607d000dfde588911d8e228fc
 robotofonts-2.132.tar.bz2      087c6f0708fe71f71a056f70fdbd5a85f4d2ce916670a98bd4be10b168abe16a
 lohitfonts-cros-2.5.5.tar.bz2  ce0ce2a5098c8ffc52327cc030576df7f5328ad9fd8a3289e2476990ad133ff1
 ko-nanumfonts-3.20.tar.bz2     59f9b6d7fcf63ca2bea7156ad66c784a1f0601d47be1b11237e17733d7112832
+roboto-flex-fonts.zip          02e0f5db84e69f254958434269d83aa6057b06f3c2a21042bb81b1afe1a0c8c6
 """
 
 STAMP_FILE = ".stamp"
@@ -74,6 +76,8 @@ def extract_archive(filepath, target_dir):
     logger.info(f"Extracting {filepath} to {target_dir}")
     if filename.endswith((".tar.bz2", ".tar.gz", ".tar.xz")):
         subprocess.run(["tar", "xf", filepath, "-C", target_dir], check=True)
+    elif filename.endswith(".zip"):
+        shutil.unpack_archive(filepath, target_dir)
     else:
         raise ValueError(f"Unsupported archive type: {filename}")
 
commit 5f00c2e653690489428ff1b26d43c09551f7adb2
Author: Dominik Röttsches <drott at chromium.org>
Date:   Wed Apr 23 15:26:55 2025 +0300

    Add Pytest status to Meson Summary

diff --git a/meson.build b/meson.build
index cce3585..344682e 100644
--- a/meson.build
+++ b/meson.build
@@ -604,6 +604,7 @@ summary({
   'Documentation': (doc_targets.length() > 0 ? doc_targets : false),
   'NLS': not opt_nls.disabled(),
   'Tests': not get_option('tests').disabled(),
+  'Pytest': pytest.found(),
   'Tools': not get_option('tools').disabled(),
   'iconv': found_iconv == 1,
   'XML backend': xmltype,
commit 1597b9bafd732f4f7ed8ca6d3eb0b2b57c9c94f7
Author: Dominik Röttsches <drott at chromium.org>
Date:   Wed Apr 16 13:23:28 2025 +0300

    [Fontations] Container and local download of testfiles
    
    * Add a python script that downloads a set of Chrome OS test
      files. Intended as preparation for testing Fontations indexing against
      FreeType indexing based on the set of fonts in ChromeOS.
    * Define a custom target in Meson that ensure the test files are
      available in the build directory. In containers: symlink them from the
      directory in the container. Locally: Download them into the
      build/testfonts. Skip the test if a stamp file with matching hashes is
      present.
    * Depend on the presence of the test fonts for the testing target
      executables.

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4fa6385..8920035 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -43,8 +43,8 @@ variables:
 # changing these will force rebuilding the associated image
 # Note: these tags have no meaning and are not tied to a particular
 # fontconfig version
-  FEDORA_TAG:    '2025-04-23.1-dd4daa0bc582'
-  FREEBSD_TAG:   '2025-04-23.1-e06fb6df1f3e'
+  FEDORA_TAG:    '2025-04-23.1-21487182ca34'
+  FREEBSD_TAG:   '2025-04-23.1-1c3182609f3d'
 
   FEDORA_EXEC:   'bash .gitlab-ci/fedora-install.sh'
   FREEBSD_EXEC:  'bash .gitlab-ci/freebsd-install.sh'
diff --git a/.gitlab-ci/ci.template b/.gitlab-ci/ci.template
index 0a6397d..6f97c72 100644
--- a/.gitlab-ci/ci.template
+++ b/.gitlab-ci/ci.template
@@ -46,7 +46,8 @@ variables:
 {% for distro in distributions|unique(attribute="name") %}
   {{"%-15s"| format(distro.name.upper() + '_TAG:')}}'{{distro.tag}}-{{
     (ci_fairy.hashfiles('.gitlab-ci/config.yml',
-                        '.gitlab-ci/' + distro.name + '-install.sh'))[0:12]
+                        '.gitlab-ci/' + distro.name + '-install.sh',
+                        'build-aux/fetch-testfonts.py'))[0:12]
   }}'
 {% endfor %}
 
diff --git a/.gitlab-ci/fedora-install.sh b/.gitlab-ci/fedora-install.sh
index 710b02e..d8ecddd 100644
--- a/.gitlab-ci/fedora-install.sh
+++ b/.gitlab-ci/fedora-install.sh
@@ -27,3 +27,5 @@ unzip android-ndk-r28-linux.zip
 ln -sf android-ndk-r28 ndk
 rm android-ndk-r28-linux.zip
 popd
+
+python3 build-aux/fetch-testfonts.py --target-dir /testfonts
\ No newline at end of file
diff --git a/.gitlab-ci/freebsd-install.sh b/.gitlab-ci/freebsd-install.sh
index 4a21923..5ae6e23 100644
--- a/.gitlab-ci/freebsd-install.sh
+++ b/.gitlab-ci/freebsd-install.sh
@@ -1,3 +1,4 @@
 #! /bin/bash
 
 set -ex
+
diff --git a/build-aux/fetch-testfonts.py b/build-aux/fetch-testfonts.py
new file mode 100755
index 0000000..0bec884
--- /dev/null
+++ b/build-aux/fetch-testfonts.py
@@ -0,0 +1,189 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import shutil
+import subprocess
+import sys
+import tempfile
+from urllib.request import urlretrieve
+import multiprocessing
+
+import logging
+import sys
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger()
+
+if not sys.stdout.isatty():
+    logger.handlers = []
+
+URL_TEMPLATE = (
+    "https://commondatastorage.googleapis.com/chromeos-localmirror/distfiles/%s"
+)
+SOURCE_FILES = (
+    "noto-cjk-20210501.tar.bz2",
+    "crosextrafonts-20130214.tar.gz",
+    "notofonts-20250214.tar.xz",
+    "robotofonts-2.132.tar.bz2",
+    "lohitfonts-cros-2.5.5.tar.bz2",
+    "ko-nanumfonts-3.20.tar.bz2",
+)
+SOURCES = [URL_TEMPLATE % source for source in SOURCE_FILES]
+
+CONTAINER_DOWNLOAD_DIR = "/testfonts"
+
+# If you want to update these, copy the contents of the .stamp file from the target directory here.
+EXPECTED_HASHES = """
+noto-cjk-20210501.tar.bz2      5c70f246c392bf15aeaee22b2fba26bb0ac54e47c00a4b9c3b556bd06fe89281
+crosextrafonts-20130214.tar.gz c48d1c2fd613c9c06c959c34da7b8388059e2408d2bb19845dc3ed35f76e4d09
+notofonts-20250214.tar.xz      cb0f9edc030e07eca58b799c607d000dfde588911d8e228fc82d5f61b9e5b6b3
+robotofonts-2.132.tar.bz2      087c6f0708fe71f71a056f70fdbd5a85f4d2ce916670a98bd4be10b168abe16a
+lohitfonts-cros-2.5.5.tar.bz2  ce0ce2a5098c8ffc52327cc030576df7f5328ad9fd8a3289e2476990ad133ff1
+ko-nanumfonts-3.20.tar.bz2     59f9b6d7fcf63ca2bea7156ad66c784a1f0601d47be1b11237e17733d7112832
+"""
+
+STAMP_FILE = ".stamp"
+
+
+def download_file(url, tmp_dir, target_dir):
+    filename = os.path.basename(url)
+    filepath = os.path.join(tmp_dir, filename)
+    logger.info(f"Downloading {url} to {filepath}")
+    urlretrieve(url, filepath)
+    return filepath
+
+
+def compute_sha256(filepath):
+    """Computes the SHA-256 hash of a file."""
+    import hashlib
+
+    hasher = hashlib.sha256()
+    with open(filepath, "rb") as file:
+        while True:
+            chunk = file.read(4096)
+            if not chunk:
+                break
+            hasher.update(chunk)
+    return hasher.hexdigest()
+
+
+def extract_archive(filepath, target_dir):
+    """Extracts an archive to the target directory."""
+    filename = os.path.basename(filepath)
+    logger.info(f"Extracting {filepath} to {target_dir}")
+    if filename.endswith((".tar.bz2", ".tar.gz", ".tar.xz")):
+        subprocess.run(["tar", "xf", filepath, "-C", target_dir], check=True)
+    else:
+        raise ValueError(f"Unsupported archive type: {filename}")
+
+
+def download_and_extract(url, tmp_dir, target_dir):
+    archivepath = download_file(url, tmp_dir, target_dir)
+    archivehash = compute_sha256(archivepath)
+    extract_archive(archivepath, target_dir)
+    return os.path.basename(archivepath), archivehash
+
+
+def stamp_target_dir(target_dir, downloaded_files_hashes):
+    if not downloaded_files_hashes or len(downloaded_files_hashes) == 0:
+        logger.error("No files to stamp")
+        return
+
+    stamp_path = os.path.join(target_dir, STAMP_FILE)
+    if os.path.exists(stamp_path):
+        os.remove(stamp_path)
+
+    max_filename_length = (
+        max(len(filename) for filename, _ in downloaded_files_hashes)
+        if downloaded_files_hashes
+        else 0
+    )
+
+    hash_results = "\n".join(
+        f"{filename:<{max_filename_length}} {hash}"
+        for filename, hash in downloaded_files_hashes
+    )
+    with open(stamp_path, "w") as f:
+        f.write(hash_results)
+
+    if not stamp_hashes_match(stamp_path):
+        raise ValueError("Downloaded files do not match recorded hashes!")
+
+
+def stamp_hashes_match(stamp_path):
+    if not os.path.exists(stamp_path):
+        return False
+
+    lines = []
+    with open(stamp_path, "r") as f:
+        lines = f.readlines()
+
+    expected_hashes = {}
+    for line in EXPECTED_HASHES.strip().split("\n"):
+        filename, hash = line.split()
+        expected_hashes[filename] = hash
+
+    for line in lines:
+        filename, hash = line.split()
+        if filename not in expected_hashes:
+            logger.error(f"Unexpected file in stamp: {filename}")
+            return False
+        if expected_hashes[filename] != hash:
+            logger.error(
+                f"Hash mismatch for {filename}: expected {expected_hashes[filename]}, got {hash}"
+            )
+            return False
+    return True
+
+
+def main():
+    """Main function to parse arguments and download/extract fonts."""
+
+    parser = argparse.ArgumentParser(description="Download and extract ChromeOS fonts.")
+
+    parser.add_argument("--target-dir", help="Target directory for extracted fonts.")
+    parser.add_argument(
+        "--try-symlink",
+        action="store_true",
+        help="Try to symlink test files previously downloaded to the container.",
+    )
+    args = parser.parse_args()
+
+    target_dir = args.target_dir
+
+    if args.try_symlink:
+        if os.path.exists(CONTAINER_DOWNLOAD_DIR) and stamp_hashes_match(
+            os.path.join(CONTAINER_DOWNLOAD_DIR, STAMP_FILE)
+        ):
+            try:
+                os.symlink(CONTAINER_DOWNLOAD_DIR, target_dir, target_is_directory=True)
+            except FileExistsError:
+                logger.debug(
+                    f"Target directory {target_dir} already exists. Skipping symlink."
+                )
+            except OSError as e:
+                logger.warning(f"Failed to create symlink: {e}")
+            logger.info(
+                f"Symlinked test fonts directory from {CONTAINER_DOWNLOAD_DIR} to {target_dir}."
+            )
+        else:
+            logger.debug("Pre-downloaded test fonts not found.")
+
+    if stamp_hashes_match(os.path.join(target_dir, STAMP_FILE)):
+        logger.info("Fonts already downloaded and extracted.")
+        return 0
+
+    os.makedirs(target_dir, exist_ok=True)
+
+    with tempfile.TemporaryDirectory() as tmp_dir:
+        with multiprocessing.Pool(processes=multiprocessing.cpu_count()) as pool:
+            hashes = pool.starmap(
+                download_and_extract,
+                [(source, tmp_dir, target_dir) for source in SOURCES],
+            )
+            stamp_target_dir(target_dir, hashes)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/test/meson.build b/test/meson.build
index a7b2637..da5ac1f 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -1,3 +1,17 @@
+fetch_test_fonts = custom_target(
+  'fetch_test_fonts',
+  output: 'testfonts',
+  command: [
+    python3,
+    join_paths(meson.project_source_root(), 'build-aux', 'fetch-testfonts.py'),
+    '--target-dir',
+    '@BUILD_ROOT@/testfonts',
+    '--try-symlink',
+  ],
+  build_by_default: false,
+  build_always_stale: true,
+)
+
 tests = [
   ['test-bz89617.c', {'c_args': ['-DSRCDIR="@0@"'.format(meson.current_source_dir())]}],
   ['test-bz131804.c'],
@@ -59,7 +73,7 @@ endforeach
 
 if get_option('fontations').enabled()
   rust = import('rust')
-  rust.test('fc_fontations_rust_tests', fc_fontations, link_with: [fc_fontations, libfontconfig_internal])
+  rust.test('fc_fontations_rust_tests', fc_fontations, link_with: [fc_fontations, libfontconfig_internal], depends: fetch_test_fonts)
 endif
 
 fs = import('fs')


More information about the Fontconfig mailing list