Files
Sprinter-SDCC/libbgi/common/_bgi_draw_scaled.c
T
snark13 ba09c0bd05 libbgi: _bgi_draw_scaled — рендер текста run'ами вместо поштучных плотов
Строка глифа сканируется на прогоны единичных битов; прогон n битов =
прямоугольник n*size×size → hspan/vspan-примитивы (одиночный пиксель —
plot_raw).  Координаты инкрементальные (+= size за бит) — умножений на
пиксель нет.  Прогон клипится до span'а — клип теперь работает и в
fast-сборке (span-raw диапазон не клипят).  ~2× на size=1, ~6× на
size=4.  Проверено в MAME (bgitest: масштабы 1..4 + VERT — пиксель в
пиксель).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 19:36:53 +03:00

106 lines
4.3 KiB
C
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.
/*
* _bgi_draw_scaled — строка растровым шрифтом 8×8 с целочисленным
* масштабом и направлением, цветом _bgi_fg, прозрачным фоном.
*
* HORIZ_DIR: пиксель глифа (c,r) → экран (x+c*size, y+r*size).
* VERT_DIR (поворот 90° против часовой): (c,r) → (x+r*size, y-c*size).
*
* Рендер run'ами (v2, 2026-07-10): строка глифа сканируется на прогоны
* подряд идущих единичных битов; каждый прогон из n битов — это
* прямоугольник n*size × size, он льётся span-примитивами (hspan для
* HORIZ, vspan для VERT; одиночный пиксель — plot_raw), а не size²×n
* отдельными плотами. Все координаты ведутся инкрементально (px/py
* += size за бит) — ни одного умножения на пиксель. Прогон клипится
* по экрану ДО span'а (span-raw не клипят диапазон!) — в отличие от
* старой версии клип работает и в fast-сборке (GFX_NOCHECK).
* Выигрыш: size=1 ~2×, size=4 ~6× против поштучных плотов.
* Всё в одной W3-скобке.
*/
#include "../_bgi.h"
/* Горизонтальная полоса прогона: (left..left+len-1) × (top..top+h-1),
* клип по экрану; len после клипа 1..320. */
static void ds_hrun(int left, int top, int len, uint8_t h, uint8_t fg)
{
uint8_t by;
int yy;
if (left < 0) { len += left; left = 0; }
if (left + len > _bgi_maxx + 1) len = _bgi_maxx + 1 - left;
if (len <= 0) return;
for (by = 0; by < h; by++) {
yy = top + by;
if (yy < 0 || yy > _bgi_maxy) continue;
if (len == 1) _bgi_plot_raw(left, yy, fg);
else _bgi_hspan_raw(left, yy, len, fg);
}
}
/* Вертикальная полоса прогона: (x0..x0+w-1) × (bottom-len+1..bottom),
* клип по экрану; len после клипа 1..256. */
static void ds_vrun(int x0, int bottom, int len, uint8_t w, uint8_t fg)
{
uint8_t bx;
int xx, top;
top = bottom - len + 1;
if (top < 0) { len += top; top = 0; }
if (top + len > _bgi_maxy + 1) len = _bgi_maxy + 1 - top;
if (len <= 0) return;
for (bx = 0; bx < w; bx++) {
xx = x0 + bx;
if (xx < 0 || xx > _bgi_maxx) continue;
if (len == 1) _bgi_plot_raw(xx, top, fg);
else _bgi_vspan_raw(xx, top, len, fg);
}
}
void _bgi_draw_scaled(int x, int y, const char *s)
{
uint8_t rows[8];
uint8_t b, fg, size, dir, r;
int px, py, run0, runl;
fg = _bgi_fg;
size = _bgi_text_size ? _bgi_text_size : 1;
dir = _bgi_text_dir;
_bgi_begin();
while (*s) {
_bgi_font_rows((unsigned char)*s, rows);
if (dir == VERT_DIR) {
px = x; /* колонка ряда r глифа */
for (r = 0; r < 8; r++) {
b = rows[r];
py = y; /* низ ячейки бита c=0 */
while (b) {
if (!(b & 0x80)) { b <<= 1; py -= size; continue; }
run0 = py; /* низ прогона */
runl = 0;
while (b & 0x80) { b <<= 1; py -= size; runl += size; }
ds_vrun(px, run0, runl, size, fg);
}
px += size;
}
y -= 8 * size;
} else {
py = y; /* верх ряда r глифа */
for (r = 0; r < 8; r++) {
b = rows[r];
px = x; /* левый край ячейки бита c=0 */
while (b) {
if (!(b & 0x80)) { b <<= 1; px += size; continue; }
run0 = px; /* левый край прогона */
runl = 0;
while (b & 0x80) { b <<= 1; px += size; runl += size; }
ds_hrun(run0, py, runl, size, fg);
}
py += size;
}
x += 8 * size;
}
s++;
}
_bgi_end();
}