#!/usr/bin/env python3 """Troca a fonte embutida no Main.swf do Alien Egg Farm. O Flixel 2.35 embute a "Nokia Cellphone FC" (zeh, fatorcaos.com.br), uma fonte freeware sem licenca de redistribuicao. Este script reescreve a tag DefineFont3 do SWF com os contornos da Silkscreen (OFL 1.1, google/fonts), mantendo o mesmo conjunto de caracteres e a mesma metrica vertical (avanco proporcional: borda da tinta mais um pixel, com a margem esquerda tirada; espaco e sem tinta ficam como antes), de modo que o texto ocupe quase o mesmo espaco. Tira tambem a DefineFontAlignZones (zonas da fonte antiga) e reescreve a DefineFontName (nome e copyright). O resto do SWF nao muda. Uso (fontTools necessario, ex.: o venv do projeto): python3 -I patch-font.py """ import struct import sys import zlib from fontTools.pens.recordingPen import DecomposingRecordingPen from fontTools.ttLib import TTFont class Bits: def __init__(self): self.bits = [] def u(self, n, v): assert 0 <= v < (1 << n) or n == 0, (n, v) for i in range(n - 1, -1, -1): self.bits.append((v >> i) & 1) def s(self, n, v): self.u(n, v & ((1 << n) - 1) if n else 0) def data(self): b = self.bits + [0] * (-len(self.bits) % 8) return bytes(int("".join(map(str, b[i:i + 8])), 2) for i in range(0, len(b), 8)) def nbits_signed(*vals): n = 1 for v in vals: while not (-(1 << (n - 1)) <= v < (1 << (n - 1))): n += 1 return n def glyph_shape(contours): """contours: listas de pontos (x, y) em unidades SWF (y para baixo); cada uma e um poligono fechado.""" w = Bits() w.u(4, 1) # NumFillBits w.u(4, 0) # NumLineBits cx = cy = 0 for pts in contours: # StyleChangeRecord: sem estilos novos, FillStyle1 = 1, MoveTo w.u(1, 0); w.u(1, 0); w.u(1, 0); w.u(1, 1); w.u(1, 0); w.u(1, 1) x0, y0 = pts[0] nb = nbits_signed(x0, y0) w.u(5, nb); w.s(nb, x0); w.s(nb, y0) w.u(1, 1) # FillStyle1 = 1 (NumFillBits = 1) cx, cy = x0, y0 for (x, y) in pts[1:] + [pts[0]]: dx, dy = x - cx, y - cy if dx == 0 and dy == 0: continue n = nbits_signed(dx, dy) n = max(n, 2) w.u(1, 1); w.u(1, 1) # StraightEdgeRecord w.u(4, n - 2) w.u(1, 1) # general line w.s(n, dx); w.s(n, dy) cx, cy = x, y w.u(1, 0); w.u(5, 0) # EndShapeRecord return w.data() def rect(xmin, xmax, ymin, ymax): w = Bits() n = nbits_signed(xmin, xmax, ymin, ymax) w.u(5, n) for v in (xmin, xmax, ymin, ymax): w.s(n, v) return w.data() def build_font(old, ttf): fid, flags, lang, nl = struct.unpack_from(" 1: cur.pop() if len(cur) >= 3: contours.append(cur) cur = None else: raise SystemExit("contorno com curva: %s" % op) # sem o pixel de margem esquerda da Silkscreen (125 unidades): o texto fica mais estreito, perto do antigo sc = [[(round((x - 125) * scale), -round(y * scale)) for x, y in c] for c in contours] shapes.append(glyph_shape(sc)) xs = [p[0] for c in sc for p in c] or [0] ys = [p[1] for c in sc for p in c] or [0] bounds.append(rect(min(xs), max(xs), min(ys), max(ys))) # avanco proporcional: borda direita da tinta + 1 pixel (125 de 1000 unidades); sem tinta, o da fonte antiga newadv.append(max(xs) + round(125 * scale) if contours else oadv) offs, pos = [], 2 * ng + 2 # a tabela de offsets (ng * 2) + o CodeTableOffset (2) for s in shapes: offs.append(pos) pos += len(s) assert pos < 65536 out = struct.pack("> 3) pos = (5 + 4 * nrect + 7) // 8 + 4 tags, font_id = [], None while pos < len(body): h = struct.unpack_from("> 6, h & 63 hl = 2 if l == 63: l = struct.unpack_from("