Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package fcft for openSUSE:Factory checked in at 2023-07-17 19:23:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/fcft (Old) and /work/SRC/openSUSE:Factory/.fcft.new.3193 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "fcft" Mon Jul 17 19:23:07 2023 rev:17 rq:1098717 version:3.1.6 Changes: -------- --- /work/SRC/openSUSE:Factory/fcft/fcft.changes 2022-09-25 15:35:30.439652449 +0200 +++ /work/SRC/openSUSE:Factory/.fcft.new.3193/fcft.changes 2023-07-17 19:23:25.313784515 +0200 @@ -1,0 +2,6 @@ +Fri Jul 14 15:44:24 UTC 2023 - Arnav Singh <[email protected]> + +- Update to 3.1.6: + * Updated bundled nanosvg. + +------------------------------------------------------------------- Old: ---- fcft-3.1.5.tar.gz New: ---- fcft-3.1.6.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ fcft.spec ++++++ --- /var/tmp/diff_new_pack.ThcVCD/_old 2023-07-17 19:23:26.437791026 +0200 +++ /var/tmp/diff_new_pack.ThcVCD/_new 2023-07-17 19:23:26.441791049 +0200 @@ -1,7 +1,7 @@ # # spec file for package fcft # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %define libname libfcft4 Name: fcft -Version: 3.1.5 +Version: 3.1.6 Release: 0 Summary: A library for font loading and glyph rasterization using FreeType/pixman License: MIT @@ -38,7 +38,7 @@ BuildRequires: pkgconfig(harfbuzz) >= 5.2 BuildRequires: pkgconfig(libutf8proc) BuildRequires: pkgconfig(pixman-1) -BuildRequires: pkgconfig(tllist) +BuildRequires: pkgconfig(tllist) >= 1.0.1 %description fcft is a font loading and glyph rasterization library built on-top ++++++ fcft-3.1.5.tar.gz -> fcft-3.1.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/.gitlab-ci.yml new/fcft/.gitlab-ci.yml --- old/fcft/.gitlab-ci.yml 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/.gitlab-ci.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,92 +0,0 @@ -stages: - - build - -variables: - GIT_SUBMODULE_STRATEGY: normal - -before_script: - - apk update - - apk add musl-dev linux-headers meson ninja gcc scdoc - - apk add pixman-dev freetype-dev fontconfig-dev harfbuzz-dev - - apk add utf8proc-dev wayland-dev wayland-protocols - - apk add git - - apk add check-dev - - apk add ttf-hack font-noto-emoji - - mkdir -p subprojects && cd subprojects - - git clone https://codeberg.org/dnkl/tllist.git - - cd .. - -debug-x64: - image: alpine:latest - stage: build - script: - - mkdir -p bld/debug - - cd bld/debug - - meson --buildtype=debug -Drun-shaping=enabled -Dtest-text-shaping=true -Dexamples=true ../../ - - ninja -v -k0 - - ninja -v test - artifacts: - reports: - junit: bld/debug/meson-logs/testlog.junit.xml - -debug-x64-no-text-shaping: - image: alpine:latest - stage: build - script: - - apk del harfbuzz harfbuzz-dev - - mkdir -p bld/debug - - cd bld/debug - - meson --buildtype=debug -Dgrapheme-shaping=disabled -Drun-shaping=disabled -Dtest-text-shaping=false ../../ - - ninja -v -k0 - - ninja -v test - artifacts: - reports: - junit: bld/debug/meson-logs/testlog.junit.xml - -release-x64: - image: alpine:latest - stage: build - script: - - mkdir -p bld/release - - cd bld/release - - meson --buildtype=release -Drun-shaping=enabled -Dtest-text-shaping=true -Dexamples=true ../../ - - ninja -v -k0 - - ninja -v test - artifacts: - reports: - junit: bld/release/meson-logs/testlog.junit.xml - -debug-x86: - image: i386/alpine:latest - stage: build - script: - - mkdir -p bld/debug - - cd bld/debug - - meson --buildtype=debug -Drun-shaping=enabled -Dtest-text-shaping=true -Dexamples=true ../../ - - ninja -v -k0 - - ninja -v test - artifacts: - reports: - junit: bld/debug/meson-logs/testlog.junit.xml - -release-x86: - image: i386/alpine:latest - stage: build - script: - - mkdir -p bld/release - - cd bld/release - - meson --buildtype=release -Drun-shaping=enabled -Dtest-text-shaping=true -Dexamples=true ../../ - - ninja -v -k0 - - ninja -v test - artifacts: - reports: - junit: bld/release/meson-logs/testlog.junit.xml - -codespell: - image: alpine:latest - stage: build - script: - - apk add python3 - - apk add py3-pip - - pip install codespell - - codespell README.md CHANGELOG.md *.c *.h fcft/*.h doc/*.scd diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/3rd-party/nanosvg/CMakeLists.txt new/fcft/3rd-party/nanosvg/CMakeLists.txt --- old/fcft/3rd-party/nanosvg/CMakeLists.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/fcft/3rd-party/nanosvg/CMakeLists.txt 2023-07-14 12:28:59.000000000 +0200 @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.10) + +project(NanoSVG C) + +# CMake needs *.c files to do something useful +configure_file(src/nanosvg.h ${CMAKE_CURRENT_BINARY_DIR}/nanosvg.c) +configure_file(src/nanosvgrast.h ${CMAKE_CURRENT_BINARY_DIR}/nanosvgrast.c) + +add_library(nanosvg ${CMAKE_CURRENT_BINARY_DIR}/nanosvg.c) + +find_library(MATH_LIBRARY m) # Business as usual +if(MATH_LIBRARY) + target_link_libraries(nanosvg PUBLIC ${MATH_LIBRARY}) +endif() + +target_include_directories(nanosvg PUBLIC $<INSTALL_INTERFACE:include/nanosvg>) +target_compile_definitions(nanosvg PRIVATE NANOSVG_IMPLEMENTATION) + +# Same for nanosvgrast +add_library(nanosvgrast ${CMAKE_CURRENT_BINARY_DIR}/nanosvgrast.c) +target_link_libraries(nanosvgrast PUBLIC nanosvg) +target_include_directories(nanosvgrast PRIVATE src) +target_compile_definitions(nanosvgrast PRIVATE NANOSVGRAST_IMPLEMENTATION) + +# Installation and export: + +include(CMakePackageConfigHelpers) + +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + VERSION 1.0 + COMPATIBILITY AnyNewerVersion +) + +install(TARGETS nanosvg nanosvgrast + EXPORT ${PROJECT_NAME}Targets +) + +export(EXPORT ${PROJECT_NAME}Targets + FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake" + NAMESPACE ${PROJECT_NAME}:: +) + +set(ConfigPackageLocation lib/cmake/${PROJECT_NAME}) + +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION ${ConfigPackageLocation} + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) + +install( + FILES + src/nanosvg.h + src/nanosvgrast.h + DESTINATION + include/nanosvg + ) + +install(EXPORT ${PROJECT_NAME}Targets + FILE + ${PROJECT_NAME}Targets.cmake + NAMESPACE + ${PROJECT_NAME}:: + DESTINATION + ${ConfigPackageLocation} +) + +install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION + ${ConfigPackageLocation} +) \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/3rd-party/nanosvg/Config.cmake.in new/fcft/3rd-party/nanosvg/Config.cmake.in --- old/fcft/3rd-party/nanosvg/Config.cmake.in 1970-01-01 01:00:00.000000000 +0100 +++ new/fcft/3rd-party/nanosvg/Config.cmake.in 2023-07-14 12:28:59.000000000 +0200 @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/NanoSVGTargets.cmake) + include("${CMAKE_CURRENT_LIST_DIR}/NanoSVGTargets.cmake") +endif () \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/3rd-party/nanosvg/README.md new/fcft/3rd-party/nanosvg/README.md --- old/fcft/3rd-party/nanosvg/README.md 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/3rd-party/nanosvg/README.md 2023-07-14 12:28:59.000000000 +0200 @@ -78,6 +78,16 @@ #include "nanosvg.h" ``` +Alternatively, you can install the library using CMake and import it into your project using the standard CMake `find_package` command. + +```CMake +add_executable(myexe main.c) + +find_package(NanoSVG REQUIRED) + +target_link_libraries(myexe NanoSVG::nanosvg NanoSVG::nanosvgrast) +``` + ## Compiling Example Project In order to compile the demo project, your will need to install [GLFW](http://www.glfw.org/) to compile. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/3rd-party/nanosvg/src/nanosvg.h new/fcft/3rd-party/nanosvg/src/nanosvg.h --- old/fcft/3rd-party/nanosvg/src/nanosvg.h 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/3rd-party/nanosvg/src/nanosvg.h 2023-07-14 12:28:59.000000000 +0200 @@ -72,6 +72,7 @@ */ enum NSVGpaintType { + NSVG_PAINT_UNDEF = -1, NSVG_PAINT_NONE = 0, NSVG_PAINT_COLOR = 1, NSVG_PAINT_LINEAR_GRADIENT = 2, @@ -119,7 +120,7 @@ } NSVGgradient; typedef struct NSVGpaint { - char type; + signed char type; union { unsigned int color; NSVGgradient* gradient; @@ -143,14 +144,17 @@ float opacity; // Opacity of the shape. float strokeWidth; // Stroke width (scaled). float strokeDashOffset; // Stroke dash offset (scaled). - float strokeDashArray[8]; // Stroke dash array (scaled). - char strokeDashCount; // Number of dash values in dash array. + float strokeDashArray[8]; // Stroke dash array (scaled). + char strokeDashCount; // Number of dash values in dash array. char strokeLineJoin; // Stroke join type. char strokeLineCap; // Stroke cap type. float miterLimit; // Miter limit char fillRule; // Fill rule, see NSVGfillRule. unsigned char flags; // Logical or of NSVG_FLAGS_* flags float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. + char fillGradient[64]; // Optional 'id' of fill gradient + char strokeGradient[64]; // Optional 'id' of stroke gradient + float xform[6]; // Root transformation for fill/stroke gradient NSVGpath* paths; // Linked list of paths in the image. struct NSVGshape* next; // Pointer to next shape, or NULL if last element. } NSVGshape; @@ -181,12 +185,11 @@ #endif #endif -#endif // NANOSVG_H - #ifdef NANOSVG_IMPLEMENTATION #include <string.h> #include <stdlib.h> +#include <stdio.h> #include <math.h> #define NSVG_PI (3.14159265358979323846264338327f) @@ -395,7 +398,7 @@ { char id[64]; char ref[64]; - char type; + signed char type; union { NSVGlinearData linear; NSVGradialData radial; @@ -611,7 +614,7 @@ } } -static NSVGparser* nsvg__createParser() +static NSVGparser* nsvg__createParser(void) { NSVGparser* p; p = (NSVGparser*)malloc(sizeof(NSVGparser)); @@ -815,9 +818,8 @@ return NULL; } -static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType) +static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, float *xform, signed char* paintType) { - NSVGattrib* attr = nsvg__getAttr(p); NSVGgradientData* data = NULL; NSVGgradientData* ref = NULL; NSVGgradientStop* stops = NULL; @@ -892,7 +894,7 @@ } nsvg__xformMultiply(grad->xform, data->xform); - nsvg__xformMultiply(grad->xform, attr->xform); + nsvg__xformMultiply(grad->xform, xform); grad->spread = data->spread; memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop)); @@ -956,6 +958,9 @@ memset(shape, 0, sizeof(NSVGshape)); memcpy(shape->id, attr->id, sizeof shape->id); + memcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient); + memcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient); + memcpy(shape->xform, attr->xform, sizeof shape->xform); scale = nsvg__getAverageScale(attr->xform); shape->strokeWidth = attr->strokeWidth * scale; shape->strokeDashOffset = attr->strokeDashOffset * scale; @@ -991,13 +996,7 @@ shape->fill.color = attr->fillColor; shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24; } else if (attr->hasFill == 2) { - float inv[6], localBounds[4]; - nsvg__xformInverse(inv, attr->xform); - nsvg__getLocalBounds(localBounds, shape, inv); - shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type); - if (shape->fill.gradient == NULL) { - shape->fill.type = NSVG_PAINT_NONE; - } + shape->fill.type = NSVG_PAINT_UNDEF; } // Set stroke @@ -1008,12 +1007,7 @@ shape->stroke.color = attr->strokeColor; shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24; } else if (attr->hasStroke == 2) { - float inv[6], localBounds[4]; - nsvg__xformInverse(inv, attr->xform); - nsvg__getLocalBounds(localBounds, shape, inv); - shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type); - if (shape->stroke.gradient == NULL) - shape->stroke.type = NSVG_PAINT_NONE; + shape->stroke.type = NSVG_PAINT_UNDEF; } // Set flags @@ -1195,6 +1189,19 @@ return s; } +static const char* nsvg__getNextPathItemWhenArcFlag(const char* s, char* it) +{ + it[0] = '\0'; + while (*s && (nsvg__isspace(*s) || *s == ',')) s++; + if (!*s) return s; + if (*s == '0' || *s == '1') { + it[0] = *s++; + it[1] = '\0'; + return s; + } + return s; +} + static const char* nsvg__getNextPathItem(const char* s, char* it) { it[0] = '\0'; @@ -1223,15 +1230,58 @@ return NSVG_RGB(128, 128, 128); } +// Parse rgb color. The pointer 'str' must point at "rgb(" (4+ characters). +// This function returns gray (rgb(128, 128, 128) == '#808080') on parse errors +// for backwards compatibility. Note: other image viewers return black instead. + static unsigned int nsvg__parseColorRGB(const char* str) { - unsigned int r=0, g=0, b=0; - float rf=0, gf=0, bf=0; - if (sscanf(str, "rgb(%u, %u, %u)", &r, &g, &b) == 3) // decimal integers - return NSVG_RGB(r, g, b); - if (sscanf(str, "rgb(%f%%, %f%%, %f%%)", &rf, &gf, &bf) == 3) // decimal integer percentage - return NSVG_RGB(roundf(rf*2.55f), roundf(gf*2.55f), roundf(bf*2.55f)); // (255 / 100.0f) - return NSVG_RGB(128, 128, 128); + int i; + unsigned int rgbi[3]; + float rgbf[3]; + // try decimal integers first + if (sscanf(str, "rgb(%u, %u, %u)", &rgbi[0], &rgbi[1], &rgbi[2]) != 3) { + // integers failed, try percent values (float, locale independent) + const char delimiter[3] = {',', ',', ')'}; + str += 4; // skip "rgb(" + for (i = 0; i < 3; i++) { + while (*str && (nsvg__isspace(*str))) str++; // skip leading spaces + if (*str == '+') str++; // skip '+' (don't allow '-') + if (!*str) break; + rgbf[i] = nsvg__atof(str); + + // Note 1: it would be great if nsvg__atof() returned how many + // bytes it consumed but it doesn't. We need to skip the number, + // the '%' character, spaces, and the delimiter ',' or ')'. + + // Note 2: The following code does not allow values like "33.%", + // i.e. a decimal point w/o fractional part, but this is consistent + // with other image viewers, e.g. firefox, chrome, eog, gimp. + + while (*str && nsvg__isdigit(*str)) str++; // skip integer part + if (*str == '.') { + str++; + if (!nsvg__isdigit(*str)) break; // error: no digit after '.' + while (*str && nsvg__isdigit(*str)) str++; // skip fractional part + } + if (*str == '%') str++; else break; + while (nsvg__isspace(*str)) str++; + if (*str == delimiter[i]) str++; + else break; + } + if (i == 3) { + rgbi[0] = roundf(rgbf[0] * 2.55f); + rgbi[1] = roundf(rgbf[1] * 2.55f); + rgbi[2] = roundf(rgbf[2] * 2.55f); + } else { + rgbi[0] = rgbi[1] = rgbi[2] = 128; + } + } + // clip values as the CSS spec requires + for (i = 0; i < 3; i++) { + if (rgbi[i] > 255) rgbi[i] = 255; + } + return NSVG_RGB(rgbi[0], rgbi[1], rgbi[2]); } typedef struct NSVGNamedColor { @@ -1639,9 +1689,9 @@ { int i = 0; str += 4; // "url("; - if (*str == '#') + if (*str && *str == '#') str++; - while (i < 63 && *str != ')') { + while (i < 63 && *str && *str != ')') { id[i] = *str++; i++; } @@ -2237,7 +2287,11 @@ nargs = 0; while (*s) { - s = nsvg__getNextPathItem(s, item); + item[0] = '\0'; + if ((cmd == 'A' || cmd == 'a') && (nargs == 3 || nargs == 4)) + s = nsvg__getNextPathItemWhenArcFlag(s, item); + if (!*item) + s = nsvg__getNextPathItem(s, item); if (!*item) break; if (cmd != '\0' && nsvg__isCoordinate(item)) { if (nargs < 10) @@ -2582,7 +2636,7 @@ } } -static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type) +static void nsvg__parseGradient(NSVGparser* p, const char** attr, signed char type) { int i; NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData)); @@ -2907,6 +2961,36 @@ } } +static void nsvg__createGradients(NSVGparser* p) +{ + NSVGshape* shape; + + for (shape = p->image->shapes; shape != NULL; shape = shape->next) { + if (shape->fill.type == NSVG_PAINT_UNDEF) { + if (shape->fillGradient[0] != '\0') { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, shape->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->fill.gradient = nsvg__createGradient(p, shape->fillGradient, localBounds, shape->xform, &shape->fill.type); + } + if (shape->fill.type == NSVG_PAINT_UNDEF) { + shape->fill.type = NSVG_PAINT_NONE; + } + } + if (shape->stroke.type == NSVG_PAINT_UNDEF) { + if (shape->strokeGradient[0] != '\0') { + float inv[6], localBounds[4]; + nsvg__xformInverse(inv, shape->xform); + nsvg__getLocalBounds(localBounds, shape, inv); + shape->stroke.gradient = nsvg__createGradient(p, shape->strokeGradient, localBounds, shape->xform, &shape->stroke.type); + } + if (shape->stroke.type == NSVG_PAINT_UNDEF) { + shape->stroke.type = NSVG_PAINT_NONE; + } + } + } +} + NSVGimage* nsvgParse(char* input, const char* units, float dpi) { NSVGparser* p; @@ -2920,6 +3004,9 @@ nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p); + // Create gradients after all definitions have been parsed + nsvg__createGradients(p); + // Scale to viewBox nsvg__scaleToViewbox(p, units); @@ -3006,4 +3093,6 @@ free(image); } -#endif +#endif // NANOSVG_IMPLEMENTATION + +#endif // NANOSVG_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/3rd-party/nanosvg/src/nanosvgrast.h new/fcft/3rd-party/nanosvg/src/nanosvgrast.h --- old/fcft/3rd-party/nanosvg/src/nanosvgrast.h 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/3rd-party/nanosvg/src/nanosvgrast.h 2023-07-14 12:28:59.000000000 +0200 @@ -25,6 +25,8 @@ #ifndef NANOSVGRAST_H #define NANOSVGRAST_H +#include "nanosvg.h" + #ifndef NANOSVGRAST_CPLUSPLUS #ifdef __cplusplus extern "C" { @@ -47,7 +49,7 @@ */ // Allocated rasterizer context. -NSVGrasterizer* nsvgCreateRasterizer(); +NSVGrasterizer* nsvgCreateRasterizer(void); // Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) // r - pointer to rasterizer context @@ -72,11 +74,11 @@ #endif #endif -#endif // NANOSVGRAST_H - #ifdef NANOSVGRAST_IMPLEMENTATION #include <math.h> +#include <stdlib.h> +#include <string.h> #define NSVG__SUBSAMPLES 5 #define NSVG__FIXSHIFT 10 @@ -112,7 +114,7 @@ } NSVGmemPage; typedef struct NSVGcachedPaint { - char type; + signed char type; char spread; float xform[6]; unsigned int colors[256]; @@ -148,7 +150,7 @@ int width, height, stride; }; -NSVGrasterizer* nsvgCreateRasterizer() +NSVGrasterizer* nsvgCreateRasterizer(void) { NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer)); if (r == NULL) goto error; @@ -1361,6 +1363,7 @@ fclose(fp); } */ + void nsvgRasterize(NSVGrasterizer* r, NSVGimage* image, float tx, float ty, float scale, unsigned char* dst, int w, int h, int stride) @@ -1405,7 +1408,8 @@ } // Rasterize edges - qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + if (r->nedges != 0) + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule nsvg__initPaint(&cache, &shape->fill, shape->opacity); @@ -1431,7 +1435,8 @@ } // Rasterize edges - qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); + if (r->nedges != 0) + qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule nsvg__initPaint(&cache, &shape->stroke, shape->opacity); @@ -1448,4 +1453,6 @@ r->stride = 0; } -#endif +#endif // NANOSVGRAST_IMPLEMENTATION + +#endif // NANOSVGRAST_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/CHANGELOG.md new/fcft/CHANGELOG.md --- old/fcft/CHANGELOG.md 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/CHANGELOG.md 2023-07-14 12:28:59.000000000 +0200 @@ -1,5 +1,6 @@ # Changelog +* [3.1.6][#3-1-6] * [3.1.5](#3-1-5) * [3.1.4](#3-1-4) * [3.1.3](#3-1-3) @@ -37,6 +38,13 @@ * [1.1.7](#1-1-7) +## 3.1.6 + +### Added + +* nanosvg updated to 9da543e (2022-12-04) + + ## 3.1.5 ### Changed diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/PKGBUILD new/fcft/PKGBUILD --- old/fcft/PKGBUILD 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/PKGBUILD 2023-07-14 12:28:59.000000000 +0200 @@ -1,5 +1,5 @@ pkgname=fcft -pkgver=3.1.5 +pkgver=3.1.6 pkgrel=1 pkgdesc="Simple font loading and glyph rasterization library" changelog=CHANGELOG.md diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/README.md new/fcft/README.md --- old/fcft/README.md 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/README.md 2023-07-14 12:28:59.000000000 +0200 @@ -31,8 +31,23 @@  -_Top: `fcft_glyph_rasterize()`, middle: `fcft_grapheme_rasterize()`, -bottom: `fcft_text_run_rasterize()`_ +The screenshot above is the output of the example program shipped with +the fcft sources (but not built by default). It showcases the three +different levels, at which fcft can rasterize glyphs: + +Top: `fcft_glyph_rasterize()` +: Glyphs are rasterized character by character; no ligatures, no + grapheme shaping, and right-to-left scripts are not rendered + correctly. + +Middle: `fcft_grapheme_rasterize()` +: Glyphs are rasterized grapheme by grapheme. Here, graphemes are + shaped correctly (e.g. the family emoji), but ligatures and RTL + scripts are still not rendered correctly. + +Bottom: `fcft_text_run_rasterize()` +: The entire string is rasterized in one go. This means full shaping + is applied; ligatures, graphemes, and RTL scripts. ## Requirements diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_capabilities.3.scd new/fcft/doc/fcft_capabilities.3.scd --- old/fcft/doc/fcft_capabilities.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_capabilities.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_capabilities(3) "3.1.5" "fcft" +fcft_capabilities(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_clone.3.scd new/fcft/doc/fcft_clone.3.scd --- old/fcft/doc/fcft_clone.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_clone.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_clone(3) "3.1.5" "fcft" +fcft_clone(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_destroy.3.scd new/fcft/doc/fcft_destroy.3.scd --- old/fcft/doc/fcft_destroy.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_destroy.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_destroy(3) "3.1.5" "fcft" +fcft_destroy(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_fini.3.scd new/fcft/doc/fcft_fini.3.scd --- old/fcft/doc/fcft_fini.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_fini.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_fini(3) "3.1.5" "fcft" +fcft_fini(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_from_name.3.scd new/fcft/doc/fcft_from_name.3.scd --- old/fcft/doc/fcft_from_name.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_from_name.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_from_name(3) "3.1.5" "fcft" +fcft_from_name(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_init.3.scd new/fcft/doc/fcft_init.3.scd --- old/fcft/doc/fcft_init.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_init.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_init(3) "3.1.5" "fcft" +fcft_init(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_kerning.3.scd new/fcft/doc/fcft_kerning.3.scd --- old/fcft/doc/fcft_kerning.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_kerning.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_kerning(3) "3.1.5" "fcft" +fcft_kerning(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_log_init.3.scd new/fcft/doc/fcft_log_init.3.scd --- old/fcft/doc/fcft_log_init.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_log_init.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_log_init(3) "3.1.5" "fcft" +fcft_log_init(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_precompose.3.scd new/fcft/doc/fcft_precompose.3.scd --- old/fcft/doc/fcft_precompose.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_precompose.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_precompose(3) "3.1.5" "fcft" +fcft_precompose(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_rasterize_char_utf32.3.scd new/fcft/doc/fcft_rasterize_char_utf32.3.scd --- old/fcft/doc/fcft_rasterize_char_utf32.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_rasterize_char_utf32.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_rasterize_char_utf32(3) "3.1.5" "fcft" +fcft_rasterize_char_utf32(3) "3.1.6" "fcft" # NAME @@ -99,7 +99,7 @@ glyph is an un-antialiased bitmask. Use as a mask when blending. *PIXMAN\_a8* corresponds to *FT\_PIXEL\_MODE\_GRAY*. I.e. the - glyph is a grayscale antialiased bitmask. use as a mask when + glyph is a grayscale antialiased bitmask. Use as a mask when blending. *PIXMAN\_x8r8g8b8* corresponds to either *FT\_PIXEL\_MODE\_LCD* or diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_rasterize_grapheme_utf32.3.scd new/fcft/doc/fcft_rasterize_grapheme_utf32.3.scd --- old/fcft/doc/fcft_rasterize_grapheme_utf32.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_rasterize_grapheme_utf32.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_rasterize_grapheme_utf32(3) "3.1.5" "fcft" +fcft_rasterize_grapheme_utf32(3) "3.1.6" "fcft" # NAME @@ -49,13 +49,10 @@ }; ``` -_cols_ is the number of "columns" the grapheme occupised (effectively) -_cp_ is the same _cp_ from the *fcft_rasterize_char_utf32*() call. - _cols_ is the number of "columns" the glyph occupies (effectively, *wcswidth*(_cluster_*)*). -_glyphs_ is an array of rasterized glyphs. See +_glyphs_ is an array of _count_ rasterized glyphs. See *fcft_rasterize_char_utf32*() for a description of *struct fcft_glyph*. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_rasterize_text_run_utf32.3.scd new/fcft/doc/fcft_rasterize_text_run_utf32.3.scd --- old/fcft/doc/fcft_rasterize_text_run_utf32.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_rasterize_text_run_utf32.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_rasterize_text_run_utf32(3) "3.1.5" "fcft" +fcft_rasterize_text_run_utf32(3) "3.1.6" "fcft" # NAME @@ -21,29 +21,16 @@ _subpixel_ allows you to specify which subpixel mode to use. See *fcft_rasterize_char_utf32*() for details. -The string is passed to HarfBuzz for shaping, initially using the -primary font. The shaping data is parsed, and when an unshaped -codepoint is encountered, it is retried with the first fallback -font. If that fails too, the next fallback font is tried. After -successfully shaping the failed codepoint, the primary font is used to -shape the rest of the string. This continues until the entire string -has been shaped. - -There is limited support for right-to-left -scripts. *hb_buffer_guess_segment_properties*() is used to guess -whether to use left-to-right, or right-to-left, logic, and this is -done each time we try to shape a part of the string. - -As a consequence, the result of mixed LTR and RTL strings depends on -the font; if the font has glyphs for all characters in the string, -*hb_buffer_guess_segment_properties*() is only called once, on the -entire string. Meaning the entire string is subject to either LTR, or -RTL logic, but not both. - -If the (primary) font does not have glyphs for all characters, then -*hb_buffer_guess_segment_properties*() will be called for each segment -where shaping failed. In this case, parts of the string may be treated -as LTR while others are treated as RTL. +The string is first segmented into grapheme clusters using +utf8proc. Each grapheme is assigned a font using the normal font +lookup rules (see *fcft_rasterize_char_utf32*()). + +Next, HarfBuzz is used to guess each grapheme's script +(~language). Consecutiv graphemes that both have been assigned the +same font, and belong to the same script are merged into a "partial" +text run. + +Finally, each partial text run is shaped with HarfBuzz. # RETURN VALUE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_set_emoji_presentation.3.scd new/fcft/doc/fcft_set_emoji_presentation.3.scd --- old/fcft/doc/fcft_set_emoji_presentation.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_set_emoji_presentation.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_set_emoji_presentation(3) "3.1.5" "fcft" +fcft_set_emoji_presentation(3) "3.1.6" "fcft" # NAME @@ -17,16 +17,16 @@ style to use with emojis with both a text presentation, and an emoji presentation style. +These emojis can be followed by an (invisible) variation +selector. When they are not followed by a selector, the implementation +must choose a style. + One example of such an emoji is U+263A - WHITE SMILING FACE: - unqualified: ⺠- text: âºï¸ - emoji: âºï¸ -These emojis can be followed by an (invisible) variation -selector. When they are not followed by a selector, the implementation -must choose a style. - The Unicode standard defines the default presentation styles, and this is what fcft defaults to. @@ -58,5 +58,5 @@ # SEE ALSO -*fcft_glyph_rasterize*(), *fcft_grapheme_rasterize*(), -*fcft_text_run_rasterize*() +*fcft_rasterize_char_utf32*(), *fcft_rasterize_grapheme_utf32*(), +*fcft_rasterize_text_run_utf32*() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_set_scaling_filter.3.scd new/fcft/doc/fcft_set_scaling_filter.3.scd --- old/fcft/doc/fcft_set_scaling_filter.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_set_scaling_filter.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_set_scaling_filter(3) "3.1.5" "fcft" +fcft_set_scaling_filter(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_size_adjust.3.scd new/fcft/doc/fcft_size_adjust.3.scd --- old/fcft/doc/fcft_size_adjust.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_size_adjust.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_size_adjust(3) "3.1.5" "fcft" +fcft_size_adjust(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/doc/fcft_text_run_destroy.3.scd new/fcft/doc/fcft_text_run_destroy.3.scd --- old/fcft/doc/fcft_text_run_destroy.3.scd 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/doc/fcft_text_run_destroy.3.scd 2023-07-14 12:28:59.000000000 +0200 @@ -1,4 +1,4 @@ -fcft_text_run_destroy(3) "3.1.5" "fcft" +fcft_text_run_destroy(3) "3.1.6" "fcft" # NAME diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/example/main.c new/fcft/example/main.c --- old/fcft/example/main.c 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/example/main.c 2023-07-14 12:28:59.000000000 +0200 @@ -116,6 +116,8 @@ { for (size_t i = 0; i < count; i++) { const struct fcft_glyph *g = glyphs[i]; + if (g == NULL) + continue; if (kern != NULL) *x += kern[i]; @@ -144,6 +146,8 @@ for (size_t i = 0; i < text_len; i++) { glyphs[i] = fcft_rasterize_char_utf32(font, text[i], subpixel_mode); + if (glyphs[i] == NULL) + continue; kern[i] = 0; if (i > 0) { @@ -241,6 +245,17 @@ struct buffer *buf = shm_get_buffer(shm, w, h, 0xdeadbeef); assert(buf != NULL); + /* + * Set clip region to the entire surface size. This allows us to + * render without considering wether things are outside the buffer + * or not. + */ + + pixman_region32_t clip; + pixman_region32_init_rect(&clip, 0, 0, buf->width, buf->height); + pixman_image_set_clip_region32(buf->pix, &clip); + pixman_region32_fini(&clip); + /* Background */ pixman_image_fill_rectangles( PIXMAN_OP_SRC, buf->pix, &bg, 1, @@ -415,7 +430,7 @@ {NULL, no_argument, NULL, '\0'}, }; - const char *user_text = u8"hello world <<<ð¸ðª ð¨âð©âð§âð¦ ð©ð¿>>>"; + const char *user_text = u8"hello world | ligatures: fi | اÙÙÙØ¹ÙØ±ÙØ¨ÙÙÙÙØ©Ù | ×¢Ö´×ְרִ×תâ | graphemes: ð¨âð©âð§âð¦ ð¸ðª"; const char *font_list = "serif:size=24"; while (true) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/meson.build new/fcft/meson.build --- old/fcft/meson.build 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/meson.build 2023-07-14 12:28:59.000000000 +0200 @@ -1,5 +1,5 @@ project('fcft', 'c', - version: '3.1.5', # Don't forget to update version in man pages + version: '3.1.6', # Don't forget to update version in man pages license: 'MIT', meson_version: '>=0.58.0', default_options: [ @@ -20,7 +20,7 @@ so_version = [ '4', # MAJOR: increment on non-backward compatible ABI changes '1', # MINOR: increment with backward compatible ABI changes - '5', # PATCH: increment with non-ABI affecting changes + '6', # PATCH: increment with non-ABI affecting changes ] is_debug_build = get_option('buildtype').startswith('debug') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fcft/nanosvg.c new/fcft/nanosvg.c --- old/fcft/nanosvg.c 2022-09-20 19:11:37.000000000 +0200 +++ new/fcft/nanosvg.c 2023-07-14 12:28:59.000000000 +0200 @@ -1,5 +1,6 @@ #include <stdio.h> #include <string.h> #include <math.h> +#define NANOSVG_ALL_COLOR_KEYWORDS #define NANOSVG_IMPLEMENTATION #include <nanosvg.h> Binary files old/fcft/screenshot.png and new/fcft/screenshot.png differ
