From 5de118b7626cf74084078d888f3e95af1f2e689f Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Wed, 17 Sep 2025 12:20:13 -0400 Subject: [PATCH] Corrected the greatest common factor routine that is run when doing "save", which was missing checks on properties representing coordinates (e.g., FIXED_BBOX) resulting in those values potentially getting truncated by scaling the output to an incompatible common factor. Thanks to Sylvain Munaut for finding the issue! --- VERSION | 2 +- database/DBio.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/VERSION b/VERSION index 1fcc6f54..7314abf6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.551 +8.3.552 diff --git a/database/DBio.c b/database/DBio.c index 6a8aeaec..fa5afb20 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -3136,7 +3136,7 @@ int DBCellFindScale(cellDef) CellDef *cellDef; { - int dbFindGCFFunc(), dbFindCellGCFFunc(); + int dbFindGCFFunc(), dbFindCellGCFFunc(), dbFindPropGCFFunc(); TileType type; TileTypeBitMask typeMask; int pNum; @@ -3180,8 +3180,13 @@ DBCellFindScale(cellDef) } } - /* Finally, cell uses */ + /* Properties, where they are coordinates. This includes + * FIXED_BBOX and MASKHINTS_* + */ + if (DBPropEnum(cellDef, dbFindPropGCFFunc, (ClientData)&ggcf)) + return 1; + /* Finally, cell uses */ if (DBCellEnum(cellDef, dbFindCellGCFFunc, (ClientData) &ggcf)) return 1; @@ -3249,6 +3254,72 @@ dbFindCellGCFFunc(cellUse, ggcf) return (*ggcf == 1) ? 1 : 0; } +int +dbFindPropGCFFunc(key, value, ggcf) + char *key; + ClientData value; + int *ggcf; /* Client data */ +{ + Rect bbox; + char *vptr = value, *sptr; + int numvals, n; + + if (!strcmp(key, "FIXED_BBOX")) + { + if (sscanf(value, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot, + &bbox.r_xtop, &bbox.r_ytop) == 4) + { + /* Check bounding box */ + if (bbox.r_xtop % (*ggcf) != 0) + *ggcf = FindGCF(bbox.r_xtop, *ggcf); + if (bbox.r_xbot % (*ggcf) != 0) + *ggcf = FindGCF(bbox.r_xbot, *ggcf); + if (bbox.r_ytop % (*ggcf) != 0) + *ggcf = FindGCF(bbox.r_ytop, *ggcf); + if (bbox.r_ybot % (*ggcf) != 0) + *ggcf = FindGCF(bbox.r_ybot, *ggcf); + } + else + TxError("Error: Cannot parse FIXED_BBOX property value!\n"); + } + else if (!strncmp(key, "MASKHINTS_", 10)) + { + while (TRUE) + { + numvals = sscanf(vptr, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot, + &bbox.r_xtop, &bbox.r_ytop); + if (numvals <= 0) + break; + else if (numvals != 4) + { + TxError("Error: Cannot parse %s property value!\n", key); + break; + } + else + { + /* Check bounding box */ + if (bbox.r_xtop % (*ggcf) != 0) + *ggcf = FindGCF(bbox.r_xtop, *ggcf); + if (bbox.r_xbot % (*ggcf) != 0) + *ggcf = FindGCF(bbox.r_xbot, *ggcf); + if (bbox.r_ytop % (*ggcf) != 0) + *ggcf = FindGCF(bbox.r_ytop, *ggcf); + if (bbox.r_ybot % (*ggcf) != 0) + *ggcf = FindGCF(bbox.r_ybot, *ggcf); + } + + /* Skip forward four values in value */ + for (n = 0; n < 4; n++) + { + while (!isspace(*vptr)) vptr++; + while (isspace(*vptr) && (*vptr != '\0')) vptr++; + } + } + } + return (*ggcf == 1) ? 1 : 0; +} + + /* * ---------------------------------------------------------------------------- *