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:
1 parent
ea2d043d26
commit
3568472eeb
1 file changed
+30
-2
+30
-2
@@ -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)}"
|
||||
|
||||
Reference in new issue
Block a user