Fix group offsets and TypeLayer boundingBox

- Group children render offset by the group bbox movement (the app moves
  groups without updating child layer bboxes). Apply the group offset
  using only the group's OWN layers (exclude nested groups' layers from
  the inner bbox, which wrongly shifted parent groups like group_167).
- TypeLayer boundingBox is relative to the transform origin; set it to
  (0,0)-(w,h) so text renders at the ppl boundingRect (verified:
  display pos = transform x boundingBox).
Fixes: overlapping groups 178/181, '最佳记录' shifted up, shape_168
dropped down, overall diff vs app render 11.84 -> 8.84.
This commit is contained in:
AskaEth committed 2026-08-27 15:43:41 +08:00
1 parent ea2d043d26
commit 3568472eeb
1 file changed
+30 -2
+30 -2
View File
@@ -527,9 +527,17 @@ def build_type_layer_tysh(ly: dict, font_ps: str) -> bytes:
res["FontSet"][0]["Name"] = String(font_ps)
l, t, rr, bb = bounding_rect(ly)
l, t, rr, bb2 = bounding_rect(ly)
tysh.transform = [1.0, 0.0, 0.0, 1.0, float(l), float(t)]
tysh.left, tysh.top, tysh.right, tysh.bottom = int(l), int(t), int(rr), int(bb)
tysh.left, tysh.top, tysh.right, tysh.bottom = int(l), int(t), int(rr), int(bb2)
# boundingBox is relative to the transform origin; PS shows the text at
# transform(boundingBox). Set it to (0,0)-(w,h) so the text lands on the
# ppl boundingRect (verified: l.psd display pos = transform x boundingBox).
bbd = td[b"boundingBox"]
bbd[b"Left"].value = 0.0
bbd[b"Top "].value = 0.0
bbd[b"Rght"].value = float(rr - l)
bbd[b"Btom"].value = float(bb2 - t)
return tysh.tobytes()
@@ -725,6 +733,23 @@ def convert(ppl_path: str, out_path: str, preview_path: Optional[str] = None,
group_ranges[gid] = [i, i]
else:
group_ranges[gid][1] = i
# The app renders group children offset by the group bbox movement
# (moving a group updates the group bbox but not the child layer
# bboxes). Apply that offset so children land where the app shows them.
group_offset = {}
for gid, (first, last) in group_ranges.items():
g = group_map.get(gid)
if not g or "boundingRect" not in g:
continue
gl, gt, _, _ = bounding_rect(g)
# only this group's OWN layers (nested groups' layers excluded)
own = [i for i in range(first, last + 1)
if layers[i].get("groupId") == gid]
if not own:
continue
inner_l = min(bounding_rect(layers[i])[0] for i in own)
inner_t = min(bounding_rect(layers[i])[1] for i in own)
group_offset[gid] = (gl - inner_l, gt - inner_t)
rendered = []
skipped = 0
@@ -763,6 +788,9 @@ def convert(ppl_path: str, out_path: str, preview_path: Optional[str] = None,
skipped += 1
continue
img, (lx, ly_) = res
if gid and gid in group_offset:
lx = int(lx + group_offset[gid][0])
ly_ = int(ly_ + group_offset[gid][1])
visible = ly.get("visible", "1") != "0"
opacity = int(ly.get("alpha", "255") or 255)
name = f"{ly['_type']}_{ly.get('objectId', i)}"