From 657c6d29557ba0fcb0edb3fb5cd5033e1541fb3f Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Wed, 8 Jul 2026 16:18:48 +0300 Subject: [PATCH] =?UTF-8?q?libc:=20BGI=20=D0=A4=D0=B0=D0=B7=D0=B0=202d-3?= =?UTF-8?q?=20=E2=80=94=20settextstyle=20(=D0=BC=D0=B0=D1=81=D1=88=D1=82?= =?UTF-8?q?=D0=B0=D0=B1=20=D0=B8=20=D0=BD=D0=B0=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D0=BA=D1=81=D1=82?= =?UTF-8?q?=D0=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit settextstyle/gettextsettings/textwidth/textheight: DEFAULT_FONT 8×8, целочисленный масштаб 1..10, HORIZ/VERT (поворот 90° CCW), прозрачный фон. Свой scaled-рендер (_bgi_draw_scaled) читает глиф через leaf _bgi_font_rows (interleaved системный шрифт) и рисует блоки size×size raw в одной W3-скобке. outtext/outtextxy переведены на него. Проверено в MAME (tests/bgitest): размеры 1..4 + вертикальный текст. Доки обновлены (Ф2d-1/2/3 готовы; осталось viewport/клиппинг). Co-Authored-By: Claude Opus 4.8 --- docs/TODO.md | 21 ++++++++----- docs/libc-reference.md | 12 ++++++-- docs/size_baseline.tsv | 2 +- libc/bgi/_bgi.h | 12 ++++++++ libc/bgi/_bgi_draw_scaled.c | 48 +++++++++++++++++++++++++++++ libc/bgi/_bgi_text_state.c | 8 +++++ libc/bgi/drv256/_bgi_font_rows.c | 17 ++++++++++ libc/bgi/gettextsettings.c | 12 ++++++++ libc/bgi/initgraph.c | 2 ++ libc/bgi/outtext.c | 10 +++--- libc/bgi/outtextxy.c | 5 +-- libc/bgi/settextstyle.c | 12 ++++++++ libc/bgi/textheight.c | 9 ++++++ libc/bgi/textwidth.c | 11 +++++++ libc/include/graphics.h | 21 +++++++++++++ tests/bgitest/bgitest.c | 53 +++++++++++++++----------------- 16 files changed, 210 insertions(+), 45 deletions(-) create mode 100644 libc/bgi/_bgi_draw_scaled.c create mode 100644 libc/bgi/_bgi_text_state.c create mode 100644 libc/bgi/drv256/_bgi_font_rows.c create mode 100644 libc/bgi/gettextsettings.c create mode 100644 libc/bgi/settextstyle.c create mode 100644 libc/bgi/textheight.c create mode 100644 libc/bgi/textwidth.c diff --git a/docs/TODO.md b/docs/TODO.md index 076ef42..80228bc 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -46,13 +46,20 @@ outtext/outtextxy. initgraph грузит EGA-палитру 0..15. Пакет - 2c: floodfill (scanline span; медленный — self-bracket чтение, но корректный), pieslice, sector. -**Фаза 2d (осталось):** getimage/putimage/imagesize (COPY/XOR/AND/OR/ -NOT_PUT), setviewport/clearviewport + клиппинг, settextstyle/textwidth/ -textheight (размеры/направление), setlinestyle, setactivepage/ -setvisualpage (2 страницы в gfx уже есть), setaspectratio (пиксели -320×256 неквадратные — круги визуально эллиптичны), setfillpattern -(USER_FILL). Оптимизации: floodfill на raw-чтении; ellipse/arc в одной -W3-сессии. Потом drv16 + sprinter_gfx16.lib (--gfx 16). +**Фаза 2d-1/2/3 ГОТОВЫ (2026-07-08, MAME tests/bgitest):** +- 2d-1: getimage/putimage/imagesize (COPY/XOR/OR/AND/NOT_PUT), raw-блит + в одной W3-скобке (_gfx_getpixel256_raw). +- 2d-2: setlinestyle/getlinesettings (SOLID/DOTTED/CENTER/DASHED/USERBIT + + NORM/THICK) — line/lineto/linerel/rectangle/drawpoly. +- 2d-3: settextstyle/gettextsettings/textwidth/textheight — масштаб + 1..10, HORIZ/VERT, прозрачный фон (свой scaled-рендер поверх 8×8). + +**Фаза 2d (осталось):** setviewport/clearviewport + клиппинг (инвазивно — +трогает все примитивы), settextjustify, setaspectratio (пиксели 320×256 +неквадратные — круги визуально эллиптичны), setfillpattern (USER_FILL), +setactivepage/setvisualpage (2 страницы в gfx уже есть). Оптимизации: +floodfill на raw-чтении; ellipse/arc в одной W3-сессии. Потом drv16 + +sprinter_gfx16.lib (--gfx 16). Acceptance: типичная BGI-программа переносится без существенных правок. Референс: Turbo C 2.x BGIDEMO. diff --git a/docs/libc-reference.md b/docs/libc-reference.md index 80e7e28..47b88f6 100644 --- a/docs/libc-reference.md +++ b/docs/libc-reference.md @@ -229,11 +229,19 @@ CP), `line(x1,y1,x2,y2)` (не двигает). `fillpoly(n,pts)`, `fillellipse(x,y,xr,yr)`. Заливка областей (Ф2c): `floodfill(x,y,border)` (медленно, но верно), `pieslice(x,y,st,end,r)`, `sector(x,y,st,end,xr,yr)`. +Спрайты (Ф2d): `imagesize/getimage/putimage` (COPY/XOR/OR/AND/NOT_PUT; +формат буфера: uint16 w,h + w*h байт). +Стиль линий (Ф2d): `setlinestyle(style,upattern,thick)`/`getlinesettings` +(SOLID/DOTTED/CENTER/DASHED/USERBIT + NORM/THICK) — на line/rectangle/ +drawpoly. +Стиль текста (Ф2d): `settextstyle(font,dir,size)`/`gettextsettings`, +`textwidth`/`textheight` — масштаб 1..10, HORIZ/VERT, прозрачный фон +(только DEFAULT_FONT 8×8). Реализация: libc/bgi/*.c (math) + libc/bgi/drv256/*.c (leaf → sprinter_gfx256.lib). Пакетные примитивы — одна W3-скобка на примитив; тригонометрия/эллипсы целочисленные (Q7/isqrt, БЕЗ 32-бит). -Ф2d (осталось): getimage/putimage, viewport/клиппинг, settextstyle, -setlinestyle, setaspectratio — см. docs/TODO.md. +Ф2d (осталось): setviewport/клиппинг, settextjustify, setaspectratio — +см. docs/TODO.md. ## — user-ISR кадрового прерывания (IM 2) diff --git a/docs/size_baseline.tsv b/docs/size_baseline.tsv index f0a8460..b016a5c 100644 --- a/docs/size_baseline.tsv +++ b/docs/size_baseline.tsv @@ -6,7 +6,7 @@ banked 1056 bankedbg 1067 banklocl 4832 banktest 3767 -bgitest 3896 +bgitest 4196 bios_text 4470 cat 915 cblstream 6277 diff --git a/libc/bgi/_bgi.h b/libc/bgi/_bgi.h index 78ca992..c735fee 100644 --- a/libc/bgi/_bgi.h +++ b/libc/bgi/_bgi.h @@ -76,6 +76,18 @@ void _bgi_hspan_raw(int x, int y, int len, uint8_t color); /* Raw чтение пикселя (без своей W3-скобки) — для getimage/putimage. */ unsigned _bgi_read_raw(int x, int y); +/* ---- Стиль текста (_bgi_text_state.c) ---------------------------- */ +extern uint8_t _bgi_text_dir; /* HORIZ_DIR / VERT_DIR */ +extern uint8_t _bgi_text_size; /* масштаб 1..10 */ + +/* Заполнить 8 байт строк глифа символа c (грузит шрифт при первом + * использовании) — drv256/_bgi_font_rows.c. */ +void _bgi_font_rows(unsigned char c, uint8_t *rows8); + +/* Нарисовать строку s в (x,y) текущим стилем текста (масштаб/направление, + * цвет _bgi_fg, прозрачный фон) — _bgi_draw_scaled.c. */ +void _bgi_draw_scaled(int x, int y, const char *s); + /* Залить строку [x0..x1] на y ТЕКУЩИМ стилем заливки (паттерн+цвет), * с клипом по экрану. Вызывать между _bgi_begin/_bgi_end. */ void _bgi_fill_span(int x0, int x1, int y); diff --git a/libc/bgi/_bgi_draw_scaled.c b/libc/bgi/_bgi_draw_scaled.c new file mode 100644 index 0000000..10c703c --- /dev/null +++ b/libc/bgi/_bgi_draw_scaled.c @@ -0,0 +1,48 @@ +/* + * _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). + * Каждый «пиксель» глифа — блок size×size из raw-плотов, всё в одной + * W3-скобке. + */ +#include "_bgi.h" + +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; + + 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); + 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) y -= 8 * size; + else x += 8 * size; + s++; + } + _bgi_end(); +} diff --git a/libc/bgi/_bgi_text_state.c b/libc/bgi/_bgi_text_state.c new file mode 100644 index 0000000..5c4e664 --- /dev/null +++ b/libc/bgi/_bgi_text_state.c @@ -0,0 +1,8 @@ +/* + * _bgi_text_state — направление и масштаб текста BGI. + * initgraph ставит HORIZ_DIR / size 1. Без инициализации. + */ +#include "_bgi.h" + +uint8_t _bgi_text_dir; +uint8_t _bgi_text_size; diff --git a/libc/bgi/drv256/_bgi_font_rows.c b/libc/bgi/drv256/_bgi_font_rows.c new file mode 100644 index 0000000..bd9e627 --- /dev/null +++ b/libc/bgi/drv256/_bgi_font_rows.c @@ -0,0 +1,17 @@ +/* + * _bgi_font_rows (drv256) — 8 байт строк глифа символа c. + * Шрифт системный, interleaved: offset = row*256 + char (MSB-first), + * см. memory/sprinter_font_format. Грузится лениво (_gfx_font_ensure). + */ +#include "../_bgi.h" +#include "../../gfx/_gfx.h" + +void _bgi_font_rows(unsigned char c, uint8_t *rows8) +{ + const uint8_t *f; + int r; + _gfx_font_ensure(); + f = _gfx_font_ptr; + for (r = 0; r < 8; r++) + rows8[r] = f[r * 256 + c]; +} diff --git a/libc/bgi/gettextsettings.c b/libc/bgi/gettextsettings.c new file mode 100644 index 0000000..1d0217b --- /dev/null +++ b/libc/bgi/gettextsettings.c @@ -0,0 +1,12 @@ +/* gettextsettings — текущий стиль текста (justify не реализован → 0). */ +#include "_bgi.h" + +void gettextsettings(struct textsettingstype *textinfo) +{ + if (!textinfo) return; + textinfo->font = DEFAULT_FONT; + textinfo->direction = _bgi_text_dir; + textinfo->charsize = _bgi_text_size; + textinfo->horiz = 0; + textinfo->vert = 0; +} diff --git a/libc/bgi/initgraph.c b/libc/bgi/initgraph.c index 8753f10..27b6bd0 100644 --- a/libc/bgi/initgraph.c +++ b/libc/bgi/initgraph.c @@ -20,4 +20,6 @@ void initgraph(void) _bgi_line_style = SOLID_LINE; _bgi_line_thick = NORM_WIDTH; _bgi_line_pattern = 0xFFFF; + _bgi_text_dir = HORIZ_DIR; + _bgi_text_size = 1; } diff --git a/libc/bgi/outtext.c b/libc/bgi/outtext.c index f573ce1..9d433b4 100644 --- a/libc/bgi/outtext.c +++ b/libc/bgi/outtext.c @@ -1,12 +1,12 @@ /* - * outtext — строка в текущей позиции (CP) текущим цветом; CP сдвигается - * вправо на ширину строки (шрифт 8×8, 8 пикселей на символ). + * outtext — строка в текущей позиции (CP) текущим стилем текста; CP + * сдвигается на textwidth (гориз.) или вверх на textheight (верт.). */ #include "_bgi.h" -#include void outtext(const char *text) { - _bgi_drawtext(_bgi_cx, _bgi_cy, text, _bgi_fg, _bgi_bg); - _bgi_cx += (int)strlen(text) * 8; + _bgi_draw_scaled(_bgi_cx, _bgi_cy, text); + if (_bgi_text_dir == VERT_DIR) _bgi_cy -= textheight(text); + else _bgi_cx += textwidth(text); } diff --git a/libc/bgi/outtextxy.c b/libc/bgi/outtextxy.c index c9a65f3..e87f11e 100644 --- a/libc/bgi/outtextxy.c +++ b/libc/bgi/outtextxy.c @@ -1,7 +1,8 @@ -/* outtextxy — строка шрифтом 8×8 в (x,y) текущим цветом; CP не меняет. */ +/* outtextxy — строка в (x,y) текущим стилем текста (масштаб/направление, + * прозрачный фон); CP не меняет. */ #include "_bgi.h" void outtextxy(int x, int y, const char *text) { - _bgi_drawtext(x, y, text, _bgi_fg, _bgi_bg); + _bgi_draw_scaled(x, y, text); } diff --git a/libc/bgi/settextstyle.c b/libc/bgi/settextstyle.c new file mode 100644 index 0000000..f105a0f --- /dev/null +++ b/libc/bgi/settextstyle.c @@ -0,0 +1,12 @@ +/* + * settextstyle — шрифт (поддержан только DEFAULT_FONT), направление и + * масштаб текста. font игнорируется (всегда растровый 8×8). + */ +#include "_bgi.h" + +void settextstyle(int font, int direction, int charsize) +{ + (void)font; + _bgi_text_dir = (direction == VERT_DIR) ? VERT_DIR : HORIZ_DIR; + _bgi_text_size = (charsize < 1) ? 1 : (charsize > 10 ? 10 : (uint8_t)charsize); +} diff --git a/libc/bgi/textheight.c b/libc/bgi/textheight.c new file mode 100644 index 0000000..55b6376 --- /dev/null +++ b/libc/bgi/textheight.c @@ -0,0 +1,9 @@ +/* textheight — высота строки как она будет нарисована (масштаб/направление). */ +#include "_bgi.h" +#include + +int textheight(const char *text) +{ + if (_bgi_text_dir == VERT_DIR) return (int)strlen(text) * 8 * _bgi_text_size; + return 8 * _bgi_text_size; +} diff --git a/libc/bgi/textwidth.c b/libc/bgi/textwidth.c new file mode 100644 index 0000000..b24a1d3 --- /dev/null +++ b/libc/bgi/textwidth.c @@ -0,0 +1,11 @@ +/* textwidth — ширина строки как она будет нарисована (с учётом + * масштаба и направления). */ +#include "_bgi.h" +#include + +int textwidth(const char *text) +{ + int n = (int)strlen(text); + if (_bgi_text_dir == VERT_DIR) return 8 * _bgi_text_size; + return n * 8 * _bgi_text_size; +} diff --git a/libc/include/graphics.h b/libc/include/graphics.h index b053793..c81397d 100644 --- a/libc/include/graphics.h +++ b/libc/include/graphics.h @@ -169,4 +169,25 @@ void putimage(int left, int top, const void *bitmap, int op); void outtextxy(int x, int y, const char *text); /* в (x,y), CP не меняет */ void outtext(const char *text); /* в CP; CP сдвигается вправо */ +/* ---- Стиль текста ------------------------------------------------ * + * Поддержан только DEFAULT_FONT (8×8, растровый); charsize 1..10 — + * целочисленный масштаб; direction — HORIZ_DIR или VERT_DIR (поворот + * 90° против часовой). Фон текста прозрачный (рисуется только цвет). */ +enum { DEFAULT_FONT = 0, TRIPLEX_FONT, SMALL_FONT, SANS_SERIF_FONT, + GOTHIC_FONT }; +enum { HORIZ_DIR = 0, VERT_DIR = 1 }; + +struct textsettingstype { + int font; + int direction; + int charsize; + int horiz; + int vert; +}; + +void settextstyle(int font, int direction, int charsize); +void gettextsettings(struct textsettingstype *textinfo); +int textwidth(const char *text); +int textheight(const char *text); + #endif diff --git a/tests/bgitest/bgitest.c b/tests/bgitest/bgitest.c index 904e446..4731fc7 100644 --- a/tests/bgitest/bgitest.c +++ b/tests/bgitest/bgitest.c @@ -1,14 +1,13 @@ /* * bgitest — демонстрация BGI-слоя graphics.h (режим 320×256×256). - * Фаза 2d-2: setlinestyle (SOLID/DOTTED/CENTER/DASHED + THICK). + * Фаза 2d-3: settextstyle — масштаб и направление текста. */ #include int main(void) { - int mx, my, i, y; - static const char *name[4] = { "SOLID", "DOTTED", "CENTER", "DASHED" }; + int mx, my; initgraph(); mx = getmaxx(); @@ -17,37 +16,35 @@ int main(void) setcolor(WHITE); rectangle(0, 0, mx, my); + setcolor(YELLOW); - outtextxy(104, 6, "BGI linestyle"); + settextstyle(DEFAULT_FONT, HORIZ_DIR, 1); + outtextxy(96, 8, "settextstyle demo"); - /* Четыре стиля тонкой линией. */ - for (i = 0; i < 4; i++) { - y = 40 + i * 22; - setcolor(WHITE); - outtextxy(12, y - 3, name[i]); - setcolor(LIGHTGREEN); - setlinestyle(i, 0, NORM_WIDTH); - line(80, y, 300, y); - } + setcolor(LIGHTGREEN); + settextstyle(DEFAULT_FONT, HORIZ_DIR, 1); + outtextxy(16, 34, "size 1 ABC"); - /* Толстые версии тех же стилей. */ - for (i = 0; i < 4; i++) { - y = 140 + i * 16; - setcolor(LIGHTCYAN); - setlinestyle(i, 0, THICK_WIDTH); - line(80, y, 300, y); - } - setcolor(WHITE); - outtextxy(12, 150, "THICK"); + setcolor(LIGHTCYAN); + settextstyle(DEFAULT_FONT, HORIZ_DIR, 2); + outtextxy(16, 52, "size 2 ABC"); + + setcolor(LIGHTRED); + settextstyle(DEFAULT_FONT, HORIZ_DIR, 3); + outtextxy(16, 86, "size 3"); - /* Прямоугольник пунктиром + диагонали. */ setcolor(LIGHTMAGENTA); - setlinestyle(DASHED_LINE, 0, NORM_WIDTH); - rectangle(20, 212, 130, 250); - line(20, 212, 130, 250); + settextstyle(DEFAULT_FONT, HORIZ_DIR, 4); + outtextxy(16, 140, "BIG 4"); + + /* Вертикальный текст (поворот 90° CCW). */ + setcolor(YELLOW); + settextstyle(DEFAULT_FONT, VERT_DIR, 2); + outtextxy(280, 240, "VERTICAL"); + setcolor(WHITE); - setlinestyle(SOLID_LINE, 0, NORM_WIDTH); - outtextxy(150, 228, "dashed rect"); + settextstyle(DEFAULT_FONT, HORIZ_DIR, 1); + outtextxy(16, 200, "horiz + vert, scale 1..4"); for (;;) { } }