Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CFF2] Lift uint16 VariationStore.length limitation #30

Open
behdad opened this issue Oct 25, 2024 · 1 comment
Open

[CFF2] Lift uint16 VariationStore.length limitation #30

behdad opened this issue Oct 25, 2024 · 1 comment

Comments

@behdad
Copy link

behdad commented Oct 25, 2024

See this for details:
harfbuzz/boring-expansion-spec#159

I suggest we implement that already. That is, if the VariationStore struct's length field is 65,535, then allow the embedded ItemVariationStore to reach out to the rest of the font file.

@justvanrossum has been building a font that hit that limit.

We are going to also implement this change in FontTools and OTS. HarfBuzz already renders such fonts fine, and I will test FreeType and report.

OTS report: harfbuzz/boring-expansion-spec#159

@behdad
Copy link
Author

behdad commented Nov 7, 2024

Here's proof of concept patch. I had to bump one of the limits for the font we're dealing with. It has regionCount of 4342, way over the hardcoded 512 limit!

diff --git a/c/shared/resource/txops.h b/c/shared/resource/txops.h
index 3c9e8cb1..ddebb7d4 100644
--- a/c/shared/resource/txops.h
+++ b/c/shared/resource/txops.h
@@ -210,8 +210,8 @@
 #define T1_MAX_AXIS_MAPS    12  /* Max axis maps (piecewise division) */
 
 /* CFF2 (where different from above) */
-#define CFF2_MAX_AXES         512   /* Max design axes */
-#define CFF2_MAX_MASTERS      512  /* Max master designs */
+#define CFF2_MAX_AXES         512  /* Max design axes */
+#define CFF2_MAX_MASTERS    16384  /* Max master designs */
 #define CFF2_MAX_AXIS_MAPS    512  /* Max axis maps (piecewise division) */
 
 
diff --git a/c/shared/source/cffread/cffread.c b/c/shared/source/cffread/cffread.c
index e1bc6718..729ae20f 100644
--- a/c/shared/source/cffread/cffread.c
+++ b/c/shared/source/cffread/cffread.c
@@ -1012,7 +1012,7 @@ static int setNumMasters(cfrCtx h, unsigned short vsindex) {
 /* -------------------------------- VarStore ------------------------------- */
 
 static void readVarStore(cfrCtx h) {
-    unsigned short length;
+    unsigned int length;
     unsigned int vstoreStart = h->region.VarStore.begin + 2;
 
     if (h->region.VarStore.begin == -1)
@@ -1025,6 +1025,8 @@ static void readVarStore(cfrCtx h) {
 
     srcSeek(h, h->region.VarStore.begin);
     length = (unsigned long)read2(h);
+    if (length == 65535)
+        length *= 128;
     h->region.VarStore.end = vstoreStart + length;
     h->cff2.varStore = var_loadItemVariationStore(&h->cb.shstm, (unsigned long)vstoreStart, length, 0);
     if (!h->cff2.varStore)
diff --git a/c/shared/source/cffwrite/cffwrite_varstore.c b/c/shared/source/cffwrite/cffwrite_varstore.c
index 3efac562..a7542ada 100644
--- a/c/shared/source/cffwrite/cffwrite_varstore.c
+++ b/c/shared/source/cffwrite/cffwrite_varstore.c
@@ -107,6 +107,8 @@ void cfwDictFillVarStore(cfwCtx g, DICT *dst, abfTopDict *top) {
 
     // Write length
     {
+        if (offset > 65535)
+            offset = 65535;
         char *arg = &(dst->array[0]);
         arg[0] = (unsigned char)(offset >> 8);
         arg[1] = (unsigned char)offset;

I still am facing a T2CharString error. I have no clue if that's related.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant