Files
Coop-NL/scripts/badges/convert-illustrator-svg.py
T
Jakub_HostacnyandClaude Opus 5.5 af35334688 feat: vsetky sablony cenoviek z novych SVG (zakladne, appkaci, vernostna karta)
- 22 sablon: Super cena / Super vyhodne / Zakladna v 3 farbach so SK aj bez,
  Appkaci (SK / bez), Vernostna karta (so zlavou / bez); orezane na viditelny
  obsah, rovnaka mierka (sirka = viewBox x 130 / 80,1)
- nove premenne {zlava_app}, {jednotkova_cena_app}, {cena_bez_karty},
  {zlava_bez_karty}, {jednotkova_cena_s_kartou}, {jednotkova_cena_bez_karty};
  zvisle natiahnutie textu (scaleY), viac nazvov pisma, napis zlava len pri zlave
- Vernostna karta je predvolena cenovka sekcie Vernostne zlavy
- produkty pri nacitani dostanu aktualnu verziu svojej sablony
- import: zlava pre appkacov a s vernostnou kartou z poznamky, jednotkova cena
  pre appkacov prepocitana, sirka cenovky podla sablony
- okraj stitkov predajni podla mierky cenovky
- postup prevodu v scripts/badges

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 10:36:37 +02:00

133 lines
7.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Prevod SVG cenoviek z Illustratora na pozadia šablón cenoviek:
# - texty v písmach Aptly / Korolev (ceny, zľavy, „zľava“, jednotkové ceny, popisy) sa z pozadia odstránia
# a zapíšu sa do výstupu – vznikne z nich vrstva editora (premenná alebo pevný text),
# - statické nápisy v písme Gilroy (SUPER / CENA / VÝHODNÉ) sa prevedú na krivky (Gilroy je nainštalovaný),
# - triedy a id dostanú jedinečnú predponu (inak by sa viaceré cenovky na jednej stránke prebíjali).
# Orezanie na viditeľný obsah (bez priehľadného okraja) a meranie polôh textov sa robí v prehliadači
# (scripts/badges/README.md), lebo potrebuje vykreslenie s písmom Aptly.
#
# Použitie: pip install fonttools; python convert-illustrator-svg.py <priečinok so SVG> <výstup.json>
import json
import re
import sys
from fontTools.pens.svgPathPen import SVGPathPen
from fontTools.pens.transformPen import TransformPen
from fontTools.ttLib import TTFont
SRC = sys.argv[1]
OUT = sys.argv[2]
GILROY = r'C:\Users\jakub\AppData\Local\Microsoft\Windows\Fonts\Gilroy-Heavy.ttf'
font = TTFont(GILROY)
glyphs = font.getGlyphSet()
cmap = font.getBestCmap()
upem = font['head'].unitsPerEm
# súbor → (názov šablóny, tagy pre import)
ASSETS = {
'Asset 12.svg': ('Super cena | Červená | SK', {'type': 'SUPER CENA', 'color': 'cervena', 'origin': 'SK'}),
'Asset 18.svg': ('Super cena | Červená', {'type': 'SUPER CENA', 'color': 'cervena', 'origin': ''}),
'Asset 14.svg': ('Super cena | Oranžová | SK', {'type': 'SUPER CENA', 'color': 'oranzova', 'origin': 'SK'}),
'Asset 20.svg': ('Super cena | Oranžová', {'type': 'SUPER CENA', 'color': 'oranzova', 'origin': ''}),
'Asset 16.svg': ('Super cena | Zelená | SK', {'type': 'SUPER CENA', 'color': 'zelena', 'origin': 'SK'}),
'Asset 22.svg': ('Super cena | Zelená', {'type': 'SUPER CENA', 'color': 'zelena', 'origin': ''}),
'Asset 13.svg': ('Super výhodné | Červená | SK', {'type': 'SUPER VÝHODNÉ', 'color': 'cervena', 'origin': 'SK'}),
'Asset 19.svg': ('Super výhodné | Červená', {'type': 'SUPER VÝHODNÉ', 'color': 'cervena', 'origin': ''}),
'Asset 15.svg': ('Super výhodné | Oranžová | SK', {'type': 'SUPER VÝHODNÉ', 'color': 'oranzova', 'origin': 'SK'}),
'Asset 21.svg': ('Super výhodné | Oranžová', {'type': 'SUPER VÝHODNÉ', 'color': 'oranzova', 'origin': ''}),
'Asset 17.svg': ('Super výhodné | Zelená | SK', {'type': 'SUPER VÝHODNÉ', 'color': 'zelena', 'origin': 'SK'}),
'Asset 23.svg': ('Super výhodné | Zelená', {'type': 'SUPER VÝHODNÉ', 'color': 'zelena', 'origin': ''}),
'Asset 27.svg': ('Základná | Červená | SK', {'type': 'ZÁKLADNÁ', 'color': 'cervena', 'origin': 'SK'}),
'Asset 28.svg': ('Základná | Červená', {'type': 'ZÁKLADNÁ', 'color': 'cervena', 'origin': ''}),
'Asset 30.svg': ('Základná | Oranžová | SK', {'type': 'ZÁKLADNÁ', 'color': 'oranzova', 'origin': 'SK'}),
'Asset 29.svg': ('Základná | Oranžová', {'type': 'ZÁKLADNÁ', 'color': 'oranzova', 'origin': ''}),
'Asset 32.svg': ('Základná | Zelená | SK', {'type': 'ZÁKLADNÁ', 'color': 'zelena', 'origin': 'SK'}),
'Asset 31.svg': ('Základná | Zelená', {'type': 'ZÁKLADNÁ', 'color': 'zelena', 'origin': ''}),
'Asset 33.svg': ('Appkáči | SK', {'type': 'ZÁKLADNÁ', 'origin': 'SK', 'app': True}),
'Asset 36.svg': ('Appkáči', {'type': 'ZÁKLADNÁ', 'origin': '', 'app': True}),
'Asset 34.svg': ('Vernostná karta', {'loyalty': True}),
'Asset 35.svg': ('Vernostná karta | bez zľavy', {'loyalty': True}),
}
def parse_css(svg):
style = re.search(r'<style>(.*?)</style>', svg, re.S).group(1)
props = {}
for sel, body in re.findall(r'([^{}]+)\{([^}]*)\}', style):
decl = dict((k.strip(), v.strip()) for k, v in (d.split(':', 1) for d in body.split(';') if ':' in d))
for cls in sel.split(','):
props.setdefault(cls.strip().lstrip('.'), {}).update(decl)
return props
def text_to_path(transform, runs, size, fill):
"""runs: [(x, text, letter_spacing_em)] → <path> s tou istou transformáciou ako pôvodný <text>."""
s = size / upem
pen = SVGPathPen(glyphs)
for x, txt, ls in runs:
cursor = x
for ch in txt:
name = cmap.get(ord(ch))
if not name:
continue
glyphs[name].draw(TransformPen(pen, (s, 0, 0, -s, cursor, 0)))
cursor += glyphs[name].width * s + ls * size
d = pen.getCommands()
return f'<path transform="{transform}" fill="{fill}" d="{d}"/>' if d else ''
result = []
for fname, (name, tags) in ASSETS.items():
svg = open(f'{SRC}/{fname}', encoding='utf-8').read()
key = 'k' + re.sub(r'\D', '', fname)
css = parse_css(svg)
texts = []
def replace_text(m):
p = {}
for c in m.group(1).split():
p.update(css.get(c, {}))
transform, body = m.group(2), m.group(3)
size = float(p.get('font-size', '0').replace('px', ''))
family = p.get('font-family', '')
runs = []
for tcls, x, txt in re.findall(r'<tspan(?: class="([^"]*)")? x="([\d.\-]+)" y="[\d.\-]+">([^<]*)</tspan>', body):
ls = css.get(tcls, {}).get('letter-spacing', '0em').replace('em', '') if tcls else '0'
runs.append((float(x), txt, float(ls or 0)))
if not runs:
runs = [(0.0, re.sub(r'<[^>]+>', '', body), 0.0)]
content = ''.join(r[1] for r in runs)
if not content.strip():
return ''
if 'Gilroy' in family:
return text_to_path(transform, runs, size, p.get('fill', '#000'))
tr = re.match(r'translate\(([\d.\-]+) ([\d.\-]+)\)(?: scale\(([\d.]+) ([\d.]+)\))?', transform)
texts.append({
'text': content, 'x': float(tr.group(1)), 'y': float(tr.group(2)),
'scaleY': float(tr.group(4)) if tr.group(4) else 1,
'size': size, 'fill': p.get('fill', '#000'), 'family': family,
'weight': p.get('font-weight', ''), 'transform': transform, 'markup': m.group(0),
})
return ''
clean = re.sub(r'<text class="([^"]+)" transform="([^"]+)">(.*?)</text>', replace_text, svg, flags=re.S)
original = svg
# jedinečné triedy a id (vo vyčistenom aj v pôvodnom SVG – pôvodné slúži na meranie textov)
def uniq(s):
s = re.sub(r'\bcls-(\d+)\b', rf'{key}-c\1', s)
for ident in set(re.findall(r'id="([^"]+)"', s)):
s = re.sub(rf'(id="|url\(#|xlink:href="#){re.escape(ident)}(["\)])', rf'\1{key}-{ident}\2', s)
return s
clean, original = uniq(clean), uniq(original)
inner = re.sub(r'</svg>\s*$', '', re.sub(r'^.*?<svg[^>]*>', '', clean, flags=re.S))
vb = [float(v) for v in re.search(r'viewBox="([^"]+)"', svg).group(1).split()]
result.append({'file': fname, 'key': key, 'name': name, 'tags': tags, 'vb': vb, 'texts': texts,
'inner': inner.strip(), 'original': original})
json.dump(result, open(OUT, 'w', encoding='utf-8'), ensure_ascii=False)
for r in result:
print(r['file'], r['name'], [t['text'] for t in r['texts']])