[subset] Preserve overflowing COLR geometry defaults

Extend partial-instance default overflow checks to signed coordinates,
unsigned radii, affine values, transform centers, and clip boxes. These
values must remain unbounded while retained axes can still vary them.
Use the constant-region fallback introduced for F2DOT14 fields.

Regressions check default-location painting of a 40000-unit translation,
a negative radial radius, and a 40000 affine coefficient, plus composed
instances with explicit and implicit maps. All 254 configured Meson tests
pass. Skera, HarfBuzz, and FontTools agree on six full-instance COLR tables.

Assisted-by: Codex
diff --git a/src/OT/Color/COLR/COLR.hh b/src/OT/Color/COLR/COLR.hh
index 73fd58c..76ed6de 100644
--- a/src/OT/Color/COLR/COLR.hh
+++ b/src/OT/Color/COLR/COLR.hh
@@ -337,6 +337,18 @@
   return bits < -32768.f || bits >= 32768.f;
 }
 
+static bool colr_word_overflows (int value, float delta, bool is_unsigned = false)
+{
+  double derived = value + (double) roundf (delta);
+  return derived < (is_unsigned ? 0 : -32768) || derived > (is_unsigned ? 65535 : 32767);
+}
+
+static bool colr_fixed_overflows (F16DOT16 value, float delta)
+{
+  float derived = value.to_float (delta);
+  return derived < -32768.f || derived >= 32768.f;
+}
+
 template <typename T>
 struct Variable
 {
@@ -1845,6 +1857,17 @@
 
 struct ClipBox
 {
+  bool default_overflows (const ItemVarStoreInstancer &instancer) const
+  {
+    if (u.format.v != 2) return false;
+    const auto &box = u.format2.get_value ();
+    unsigned base = u.format2.varIdxBase;
+    return colr_word_overflows (box.xMin, instancer (base, 0)) ||
+           colr_word_overflows (box.yMin, instancer (base, 1)) ||
+           colr_word_overflows (box.xMax, instancer (base, 2)) ||
+           colr_word_overflows (box.yMax, instancer (base, 3));
+  }
+
   bool subset (hb_subset_context_t *c,
                const ItemVarStoreInstancer &instancer) const
   {
@@ -2073,31 +2096,77 @@
       case 5:
       {
         const auto &paint = u.paintformat5.get_value ();
-        return (&paint+paint.colorLine).default_overflows (instancer);
+        unsigned base = u.paintformat5.varIdxBase;
+        return (&paint+paint.colorLine).default_overflows (instancer) ||
+               colr_word_overflows (paint.x0, instancer (base, 0)) ||
+               colr_word_overflows (paint.y0, instancer (base, 1)) ||
+               colr_word_overflows (paint.x1, instancer (base, 2)) ||
+               colr_word_overflows (paint.y1, instancer (base, 3)) ||
+               colr_word_overflows (paint.x2, instancer (base, 4)) ||
+               colr_word_overflows (paint.y2, instancer (base, 5));
       }
       case 7:
       {
         const auto &paint = u.paintformat7.get_value ();
-        return (&paint+paint.colorLine).default_overflows (instancer);
+        unsigned base = u.paintformat7.varIdxBase;
+        return (&paint+paint.colorLine).default_overflows (instancer) ||
+               colr_word_overflows (paint.x0, instancer (base, 0)) ||
+               colr_word_overflows (paint.y0, instancer (base, 1)) ||
+               colr_word_overflows (paint.radius0, instancer (base, 2), true) ||
+               colr_word_overflows (paint.x1, instancer (base, 3)) ||
+               colr_word_overflows (paint.y1, instancer (base, 4)) ||
+               colr_word_overflows (paint.radius1, instancer (base, 5), true);
       }
       case 9:
       {
         const auto &paint = u.paintformat9.get_value ();
         unsigned base = u.paintformat9.varIdxBase;
         return (&paint+paint.colorLine).default_overflows (instancer) ||
+               colr_word_overflows (paint.centerX, instancer (base, 0)) ||
+               colr_word_overflows (paint.centerY, instancer (base, 1)) ||
                colr_f2dot14_overflows (paint.startAngle, instancer (base, 2)) ||
                colr_f2dot14_overflows (paint.endAngle, instancer (base, 3));
       }
+      case 13:
+      {
+        const auto &paint = u.paintformat13;
+        const auto &transform = &paint+paint.transform;
+        const auto &value = transform.get_value ();
+        unsigned base = transform.varIdxBase;
+        return colr_fixed_overflows (value.xx, instancer (base, 0)) ||
+               colr_fixed_overflows (value.yx, instancer (base, 1)) ||
+               colr_fixed_overflows (value.xy, instancer (base, 2)) ||
+               colr_fixed_overflows (value.yy, instancer (base, 3)) ||
+               colr_fixed_overflows (value.dx, instancer (base, 4)) ||
+               colr_fixed_overflows (value.dy, instancer (base, 5));
+      }
+      case 15:
+      {
+        const auto &paint = u.paintformat15.get_value ();
+        unsigned base = u.paintformat15.varIdxBase;
+        return colr_word_overflows (paint.dx, instancer (base, 0)) ||
+               colr_word_overflows (paint.dy, instancer (base, 1));
+      }
       case 17:
         return colr_f2dot14_overflows (u.paintformat17.get_value ().scaleX, instancer (u.paintformat17.varIdxBase, 0)) ||
                colr_f2dot14_overflows (u.paintformat17.get_value ().scaleY, instancer (u.paintformat17.varIdxBase, 1));
       case 19:
         return colr_f2dot14_overflows (u.paintformat19.get_value ().scaleX, instancer (u.paintformat19.varIdxBase, 0)) ||
-               colr_f2dot14_overflows (u.paintformat19.get_value ().scaleY, instancer (u.paintformat19.varIdxBase, 1));
+               colr_f2dot14_overflows (u.paintformat19.get_value ().scaleY, instancer (u.paintformat19.varIdxBase, 1)) ||
+               colr_word_overflows (u.paintformat19.get_value ().centerX, instancer (u.paintformat19.varIdxBase, 2)) ||
+               colr_word_overflows (u.paintformat19.get_value ().centerY, instancer (u.paintformat19.varIdxBase, 3));
       case 21:
         return colr_f2dot14_overflows (u.paintformat21.get_value ().scale, instancer (u.paintformat21.varIdxBase, 0));
       case 23:
-        return colr_f2dot14_overflows (u.paintformat23.get_value ().scale, instancer (u.paintformat23.varIdxBase, 0));
+        return colr_f2dot14_overflows (u.paintformat23.get_value ().scale, instancer (u.paintformat23.varIdxBase, 0)) ||
+               colr_word_overflows (u.paintformat23.get_value ().centerX, instancer (u.paintformat23.varIdxBase, 1)) ||
+               colr_word_overflows (u.paintformat23.get_value ().centerY, instancer (u.paintformat23.varIdxBase, 2));
+      case 27:
+        return colr_word_overflows (u.paintformat27.get_value ().centerX, instancer (u.paintformat27.varIdxBase, 1)) ||
+               colr_word_overflows (u.paintformat27.get_value ().centerY, instancer (u.paintformat27.varIdxBase, 2));
+      case 31:
+        return colr_word_overflows (u.paintformat31.get_value ().centerX, instancer (u.paintformat31.varIdxBase, 2)) ||
+               colr_word_overflows (u.paintformat31.get_value ().centerY, instancer (u.paintformat31.varIdxBase, 3));
       default:
         return false;
     }
@@ -2631,6 +2700,13 @@
           *preserve_defaults = true;
           break;
         }
+      for (const ClipRecord &clip_record : cliplist.clips.iter ())
+        if (glyphset->intersects (clip_record.startGlyphID, clip_record.endGlyphID) &&
+            (&cliplist+clip_record.clipBox).default_overflows (instancer))
+        {
+          *preserve_defaults = true;
+          break;
+        }
     }
 
     // if a DeltaSetIndexMap is included, collected variation indices are
diff --git a/test/api/fonts/colr-geometry-overflow-mapped.ttf b/test/api/fonts/colr-geometry-overflow-mapped.ttf
new file mode 100644
index 0000000..7c38642
--- /dev/null
+++ b/test/api/fonts/colr-geometry-overflow-mapped.ttf
Binary files differ
diff --git a/test/api/fonts/colr-geometry-overflow.ttf b/test/api/fonts/colr-geometry-overflow.ttf
new file mode 100644
index 0000000..7c38642
--- /dev/null
+++ b/test/api/fonts/colr-geometry-overflow.ttf
Binary files differ
diff --git a/test/api/fonts/generate-colr-geometry-overflow-fonts.py b/test/api/fonts/generate-colr-geometry-overflow-fonts.py
new file mode 100644
index 0000000..2a8a95b
--- /dev/null
+++ b/test/api/fonts/generate-colr-geometry-overflow-fonts.py
@@ -0,0 +1,71 @@
+"""Generate COLRv1 geometry defaults that overflow signed and unsigned fields."""
+
+from pathlib import Path
+from fontTools.fontBuilder import FontBuilder
+from fontTools.colorLib.builder import buildCOLR, buildCPAL
+from fontTools.pens.ttGlyphPen import TTGlyphPen
+from fontTools.varLib.builder import (
+    buildVarRegionList,
+    buildVarData,
+    buildVarStore,
+    buildDeltaSetIndexMap,
+)
+
+fb = FontBuilder(1000, isTTF=True)
+names = [".notdef", "a", "b", "c"]
+fb.setupGlyphOrder(names)
+fb.setupCharacterMap({97: "a", 98: "b", 99: "c"})
+fb.setupGlyf({name: TTGlyphPen(None).glyph() for name in names})
+fb.setupHorizontalMetrics({name: (500, 0) for name in names})
+fb.setupHorizontalHeader(ascent=800, descent=-200)
+fb.setupNameTable({"familyName": "COLR Partial Overflow", "styleName": "Regular"})
+fb.setupOS2(sTypoAscender=800, sTypoDescender=-200, usWinAscent=800, usWinDescent=200)
+fb.setupPost()
+fb.setupFvar([("wght", 0, 0, 1, "Weight"), ("wdth", 0, 0, 1, "Width")], [])
+regions = buildVarRegionList(
+    [{"wght": (0, 1, 1)}, {"wdth": (0, 1, 1)}], ["wght", "wdth"]
+)
+rows = [[0, 0] for _ in range(18)]
+rows[0] = [10000, -40000]
+rows[4] = [-200, 400]
+rows[8] = [10000 * 65536, -30000 * 65536]
+rows[16] = [10000, -40000]
+store = buildVarStore(regions, [buildVarData([0, 1], rows)])
+solid = dict(Format=2, PaletteIndex=0, Alpha=1)
+line = dict(
+    Extend="pad",
+    ColorStop=[dict(StopOffset=0, PaletteIndex=0, Alpha=1, VarIndexBase=0xFFFFFFFF)],
+)
+paints = {
+    "a": dict(Format=15, Paint=solid, dx=30000, dy=0, VarIndexBase=0),
+    "b": dict(
+        Format=7,
+        ColorLine=line,
+        x0=0,
+        y0=0,
+        r0=100,
+        x1=400,
+        y1=0,
+        r1=500,
+        VarIndexBase=2,
+    ),
+    "c": dict(
+        Format=13,
+        Paint=solid,
+        Transform=dict(xx=30000, yx=0, xy=0, yy=1, dx=0, dy=0, VarIndexBase=8),
+    ),
+}
+fb.font["COLR"] = buildCOLR(
+    paints,
+    version=1,
+    glyphMap=fb.font.getReverseGlyphMap(),
+    varStore=store,
+    clipBoxes={name: (0, 0, 30000, 100, 14) for name in paints},
+)
+fb.font["CPAL"] = buildCPAL([[(1, 0, 0, 1)]])
+fb.font.recalcTimestamp = False
+fb.font["head"].created = fb.font["head"].modified = 2082844800
+root = Path(__file__).parent
+fb.save(root / "colr-geometry-overflow.ttf")
+fb.font["COLR"].table.VarIndexMap = buildDeltaSetIndexMap(list(range(18)))
+fb.save(root / "colr-geometry-overflow-mapped.ttf")
diff --git a/test/api/test-subset-colr.c b/test/api/test-subset-colr.c
index f45930e..9108852 100644
--- a/test/api/test-subset-colr.c
+++ b/test/api/test-subset-colr.c
@@ -236,6 +236,65 @@
   }
 }
 
+typedef struct {
+  float xx, dx, radius;
+} geometry_t;
+
+static void
+record_transform (hb_paint_funcs_t *funcs HB_UNUSED, void *paint_data,
+                  float xx, float yx HB_UNUSED, float xy HB_UNUSED, float yy HB_UNUSED,
+                  float dx, float dy HB_UNUSED, void *user_data HB_UNUSED)
+{
+  geometry_t *geometry = paint_data;
+  geometry->xx = xx;
+  geometry->dx = dx;
+}
+
+static void
+record_radial (hb_paint_funcs_t *funcs HB_UNUSED, void *paint_data,
+               hb_color_line_t *line HB_UNUSED,
+               float x0 HB_UNUSED, float y0 HB_UNUSED, float r0,
+               float x1 HB_UNUSED, float y1 HB_UNUSED, float r1 HB_UNUSED,
+               void *user_data HB_UNUSED)
+{
+  ((geometry_t *) paint_data)->radius = r0;
+}
+
+static void
+test_subset_colr_geometry_overflow (void)
+{
+  const char *files[] = {"fonts/colr-geometry-overflow.ttf", "fonts/colr-geometry-overflow-mapped.ttf"};
+  for (unsigned file = 0; file < G_N_ELEMENTS (files); file++)
+  {
+    hb_face_t *face = hb_test_open_font_file (files[file]);
+    hb_face_t *partial = instance_colr (face, 1, 0, true, false);
+    hb_font_t *font = hb_font_create (partial);
+    hb_paint_funcs_t *funcs = hb_paint_funcs_create ();
+    hb_paint_funcs_set_push_transform_func (funcs, record_transform, NULL, NULL);
+    hb_paint_funcs_set_radial_gradient_func (funcs, record_radial, NULL, NULL);
+    geometry_t geometry = {0};
+    hb_font_paint_glyph (font, 1, funcs, &geometry, 0, HB_COLOR (0, 0, 0, 255));
+    g_assert_cmpfloat (geometry.dx, ==, 40000.f);
+    hb_font_paint_glyph (font, 2, funcs, &geometry, 0, HB_COLOR (0, 0, 0, 255));
+    g_assert_cmpfloat (geometry.radius, ==, -100.f);
+    hb_font_paint_glyph (font, 3, funcs, &geometry, 0, HB_COLOR (0, 0, 0, 255));
+    g_assert_cmpfloat (geometry.xx, ==, 40000.f);
+    hb_paint_funcs_destroy (funcs);
+    hb_font_destroy (font);
+    const float widths[] = {0.5f, 0.75f, 1.f};
+    for (unsigned i = 0; i < G_N_ELEMENTS (widths); i++)
+    {
+      hb_face_t *direct = instance_colr (face, 1, widths[i], true, true);
+      hb_face_t *composed = instance_colr (partial, 0, widths[i], false, true);
+      hb_subset_test_check (direct, composed, HB_TAG ('C','O','L','R'));
+      hb_face_destroy (composed);
+      hb_face_destroy (direct);
+    }
+    hb_face_destroy (partial);
+    hb_face_destroy (face);
+  }
+}
+
 static void
 test_subset_colr_constant_default (void)
 {
@@ -317,6 +376,7 @@
   hb_test_add (test_subset_colr_partial_overflow);
   hb_test_add (test_subset_colr_constant_default);
   hb_test_add (test_subset_colr_default_paint);
+  hb_test_add (test_subset_colr_geometry_overflow);
 
   return hb_test_run();
 }