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>
This commit is contained in:
@@ -4,16 +4,62 @@
|
||||
*
|
||||
* HORIZ_DIR: пиксель глифа (c,r) → экран (x+c*size, y+r*size).
|
||||
* VERT_DIR (поворот 90° против часовой): (c,r) → (x+r*size, y-c*size).
|
||||
* Каждый «пиксель» глифа — блок size×size из raw-плотов, всё в одной
|
||||
* W3-скобке.
|
||||
*
|
||||
* Рендер 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;
|
||||
int r, c, bx, by, px, py;
|
||||
uint8_t b, fg, size, dir, r;
|
||||
int px, py, run0, runl;
|
||||
|
||||
fg = _bgi_fg;
|
||||
size = _bgi_text_size ? _bgi_text_size : 1;
|
||||
@@ -22,26 +68,37 @@ void _bgi_draw_scaled(int x, int y, const char *s)
|
||||
_bgi_begin();
|
||||
while (*s) {
|
||||
_bgi_font_rows((unsigned char)*s, rows);
|
||||
for (r = 0; r < 8; r++) {
|
||||
b = rows[r];
|
||||
for (c = 0; c < 8; c++) {
|
||||
if (!((b >> (7 - c)) & 1)) continue;
|
||||
for (by = 0; by < size; by++) {
|
||||
for (bx = 0; bx < size; bx++) {
|
||||
if (dir == VERT_DIR) {
|
||||
px = x + r * size + by;
|
||||
py = y - c * size - bx;
|
||||
} else {
|
||||
px = x + c * size + bx;
|
||||
py = y + r * size + by;
|
||||
}
|
||||
_bgi_plot_raw(px, py, fg);
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (dir == VERT_DIR) y -= 8 * size;
|
||||
else x += 8 * size;
|
||||
s++;
|
||||
}
|
||||
_bgi_end();
|
||||
|
||||
Reference in New Issue
Block a user