libc: BGI Фаза 2d-3 — settextstyle (масштаб и направление текста)
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 <noreply@anthropic.com>
This commit is contained in:
+14
-7
@@ -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.
|
||||
|
||||
|
||||
+10
-2
@@ -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.
|
||||
|
||||
## <irq.h> — user-ISR кадрового прерывания (IM 2)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ banked 1056
|
||||
bankedbg 1067
|
||||
banklocl 4832
|
||||
banktest 3767
|
||||
bgitest 3896
|
||||
bgitest 4196
|
||||
bios_text 4470
|
||||
cat 915
|
||||
cblstream 6277
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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];
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* outtext — строка в текущей позиции (CP) текущим цветом; CP сдвигается
|
||||
* вправо на ширину строки (шрифт 8×8, 8 пикселей на символ).
|
||||
* outtext — строка в текущей позиции (CP) текущим стилем текста; CP
|
||||
* сдвигается на textwidth (гориз.) или вверх на textheight (верт.).
|
||||
*/
|
||||
#include "_bgi.h"
|
||||
#include <string.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* textheight — высота строки как она будет нарисована (масштаб/направление). */
|
||||
#include "_bgi.h"
|
||||
#include <string.h>
|
||||
|
||||
int textheight(const char *text)
|
||||
{
|
||||
if (_bgi_text_dir == VERT_DIR) return (int)strlen(text) * 8 * _bgi_text_size;
|
||||
return 8 * _bgi_text_size;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
/* textwidth — ширина строки как она будет нарисована (с учётом
|
||||
* масштаба и направления). */
|
||||
#include "_bgi.h"
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
+25
-28
@@ -1,14 +1,13 @@
|
||||
/*
|
||||
* bgitest — демонстрация BGI-слоя graphics.h (режим 320×256×256).
|
||||
* Фаза 2d-2: setlinestyle (SOLID/DOTTED/CENTER/DASHED + THICK).
|
||||
* Фаза 2d-3: settextstyle — масштаб и направление текста.
|
||||
*/
|
||||
|
||||
#include <graphics.h>
|
||||
|
||||
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 (;;) { }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user