Commit 4ae02979 by PLN (Algolia)

midiviz: the wordmark lives inside the D1 cell, at the cell's margin

PLN: 'stuck to left wall, should fit in d1 cell so have same margin as
cell'. The fit is honest: probe core-only ink (the glow inflated the
measurement), shrink the type to the span — never squash, never clip —
crop to true ink, clamp to the cell's outer rect. Glow trimmed another
notch: 'less blurry still neon but somewhat less'.
parent fda0a9aa
......@@ -1743,7 +1743,7 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0,
self._word_font, self._word_font_key = f, key
return f
def _draw_word_layer(self, qp, base, pad, f, fm, pen):
def _draw_word_layer(self, qp, base, pad, fm, pen):
"""One pass of the word: glyphs drawn one by one with the tracked
advance, so the letter spacing is OURS and identical under the
glow rings and the core."""
......@@ -1777,81 +1777,104 @@ def build_widget(port_label: str, reader: "Reader | None", scale: float = 1.0,
def _word_pixmap(self, span_w: float, span_h: float):
"""The wordmark BAKED — glyphs, tracking and neon glow rendered
once per geometry, not per frame. PLN's verdicts are all in here:
the glow is TIGHT ("a little less blurry? esp made fullscreen"),
the type is ExtraBold-800 ("too light"), and the bake measures
its own ink and crops to it ("i see PARVAGU how come missing end
of letters"). Any width overrun is taken by a vector condense at
draw time — never raster scaling, so fullscreen rebakes stay
sharp."""
the glow is TIGHT ("too blurry"), the type is ExtraBold-800
("too light"), the bake measures its own ink and crops ("i see
PARVAGU"), and it must FIT the D1 cell at the cell's margin —
which means the TYPE shrinks to the width, honestly, rather than
a squash that would make the letters strangers to themselves."""
key = (round(span_w), round(span_h))
if self._word_pm_key == key:
return self._word_pm
f = self._wave_font(span_w, span_h)
if f is None:
return None
fm = QtGui.QFontMetricsF(f)
pad = max(2, int(f.pixelSize() * 0.25))
# PROBE: draw once, generously, and ask the pixels how wide the
# word really is. Metrics-driven sizing cut the tail; ink does not.
probe_w = span_w * 3
probe = QtGui.QImage(probe_w, round(span_h) + pad * 2,
QtGui.QImage.Format.Format_ARGB32_Premultiplied)
probe.fill(0)
qp = QtGui.QPainter(probe)
try:
qp.setRenderHint(QtGui.QPainter.RenderHint.TextAntialiasing,
True)
qp.setFont(f)
base = pad + (span_h + fm.ascent() - fm.descent()) / 2.0
self._draw_word_layer(qp, base, pad, f, fm,
QtGui.QPen(QtGui.QColor("#d900ff")))
finally:
qp.end()
def bake(px, canvas_w, glow=True):
fb = QtGui.QFont(f)
fb.setPixelSize(max(4, px))
fmb = QtGui.QFontMetricsF(fb)
pad_b = max(2, int(px * 0.25))
img = QtGui.QImage(round(canvas_w), round(span_h) + pad_b * 2,
QtGui.QImage.Format.Format_ARGB32_Premultiplied)
img.fill(0)
qp = QtGui.QPainter(img)
try:
qp.setRenderHint(
QtGui.QPainter.RenderHint.TextAntialiasing, True)
qp.setFont(fb)
base = pad_b + (span_h + fmb.ascent() - fmb.descent()) / 2.0
if glow:
# the glow: two CLOSE rings, faint — rim of neon, not fog
r0 = max(1.0, px * 0.07)
for rad, alpha in ((r0, 24), (r0 * 0.5, 38)):
glow_pen = QtGui.QPen(QtGui.QColor(217, 0, 255, alpha))
glow_pen.setWidthF(max(1.2, px * 0.06))
for i in range(10):
a = 2 * math.pi * i / 10
qp.save()
qp.translate(math.cos(a) * rad, math.sin(a) * rad)
self._draw_word_layer(qp, base, pad_b, fmb, glow_pen)
qp.restore()
# the core: --neon-high itself, the site's own pink
self._draw_word_layer(qp, base, pad_b, fmb,
QtGui.QPen(QtGui.QColor("#d900ff")))
finally:
qp.end()
return img, pad_b
# PASS 1 — probe CORE-ONLY (the glow's ink would inflate the
# measurement and the fit would undershoot), on a canvas the word
# can never outrun: the D1-span cut came from a probe narrower
# than the word, where the ink scan believed the clip was the edge.
px = max(6.0, span_h * 0.92)
probe, pad1 = bake(px, int(px * 12), glow=False)
ink = self._word_ink_width(probe)
sx = min(1.0, span_w / max(1.0, ink - pad))
img = QtGui.QImage(round((ink) * sx) + pad * 2,
round(span_h) + pad * 2,
QtGui.QImage.Format.Format_ARGB32_Premultiplied)
img.fill(0)
qp = QtGui.QPainter(img)
try:
qp.setRenderHint(QtGui.QPainter.RenderHint.TextAntialiasing,
True)
qp.setFont(f)
qp.scale(sx, 1.0)
base = pad + (span_h + fm.ascent() - fm.descent()) / 2.0
# the glow: two CLOSE rings, faint — a rim of neon, not a fog
r0 = max(1.0, f.pixelSize() * 0.09)
for rad, alpha in ((r0, 40), (r0 * 0.45, 60)):
glow = QtGui.QPen(QtGui.QColor(217, 0, 255, alpha))
glow.setWidthF(max(1.5, f.pixelSize() * 0.07))
for i in range(10):
a = 2 * math.pi * i / 10
qp.save()
qp.translate(math.cos(a) * rad, math.sin(a) * rad)
self._draw_word_layer(qp, base, pad, f, fm, glow)
qp.restore()
# the core: --neon-high itself, the site's own pink
self._draw_word_layer(qp, base, pad, f, fm,
QtGui.QPen(QtGui.QColor("#d900ff")))
finally:
qp.end()
pm = QtGui.QPixmap.fromImage(img)
word_w = ink - 2 * pad1
# PASS 2 — if the word outruns the span, shrink the TYPE to fit;
# never squash it, never clip it.
if word_w > span_w:
fit = max(8.0, span_w * 0.94)
px = max(4.0, px * fit / word_w)
img, pad = bake(px, span_w + int(px * 2))
else:
img, pad = bake(px, word_w + pad * 2)
# crop to the true ink so the margins are the cell's, no more
left = 0
w_ = img.width()
while left < w_ and not self._col_has_ink(img, left):
left += 1
right = w_ - 1
while right > left and not self._col_has_ink(img, right):
right -= 1
cropped = img.copy(max(0, left - pad // 2), 0,
min(w_, right - left + 1 + pad),
img.height())
pm = QtGui.QPixmap.fromImage(cropped)
self._word_pm, self._word_pm_key = pm, key
return pm
def _col_has_ink(self, img, x):
return any(img.pixelColor(x, y).alpha() > 8
for y in range(img.height()))
def _paint_word(self, p):
"""PARVAGUES over D1-D3 — PLN: "bolted to D1-D3 even better as
over the djfs :D" — in the site's own display face."""
span_w, span_h = 3 * self.cw, self.ch
"""PARVAGUES inside the D1 cell, with the cell's own margin —
PLN, 2026-09-24: "appears stuck to left wall, should fit in d1
cell so have same margin as cell". The span is the cell's inner
rectangle, not three columns."""
span_w, span_h = max(20.0, self.cw - self.inset), max(8.0, self.ch - self.inset)
pm = self._word_pixmap(span_w, span_h)
if pm is None:
return
row_y = self.my + 3 * self.ch # PHYSICAL_ORDER index of D
p.setOpacity(WORD_ALPHA)
try:
p.drawPixmap(round(self.mx + (span_w - pm.width()) / 2.0),
round(row_y + (span_h - pm.height()) / 2.0), pm)
# clamped to the cell's outer rect: at the smallest windows
# the glow ring can reach 1px past the inner margin, and a
# 1px lean beats 1px of overlap
p.drawPixmap(max(round(self.mx),
round(self.mx + (self.cw - pm.width()) / 2.0)),
round(row_y + (self.ch - pm.height()) / 2.0), pm)
finally:
p.setOpacity(1.0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment