# 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 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'', 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)] → s tou istou transformáciou ako pôvodný .""" 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'' 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'([^<]*)', 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'(.*?)', 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'\s*$', '', re.sub(r'^.*?]*>', '', 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']])