diff --git a/docs/size_baseline.tsv b/docs/size_baseline.tsv index b21070f..f0a8460 100644 --- a/docs/size_baseline.tsv +++ b/docs/size_baseline.tsv @@ -6,7 +6,7 @@ banked 1056 bankedbg 1067 banklocl 4832 banktest 3767 -bgitest 5482 +bgitest 3896 bios_text 4470 cat 915 cblstream 6277 diff --git a/libc/bgi/_bgi.h b/libc/bgi/_bgi.h index dbe3f98..78ca992 100644 --- a/libc/bgi/_bgi.h +++ b/libc/bgi/_bgi.h @@ -58,6 +58,14 @@ void _bgi_ellipse_arc(int cx, int cy, int stangle, int endangle, /* Целочисленный sqrt (0..~32767) для fillellipse (_bgi_isqrt.c). */ int _bgi_isqrt(int n); +/* ---- Состояние линий (_bgi_line_state.c) ------------------------- */ +extern uint8_t _bgi_line_style; /* SOLID_LINE..USERBIT_LINE */ +extern uint8_t _bgi_line_thick; /* 1 (NORM) или 3 (THICK) */ +extern uint16_t _bgi_line_pattern; /* маска для USERBIT_LINE */ + +/* Отрезок текущим стилем/толщиной линии (_bgi_styled_line.c). */ +void _bgi_styled_line(int x0, int y0, int x1, int y1, uint8_t color); + /* ---- Состояние заливки (_bgi_fill_state.c) ----------------------- */ extern uint8_t _bgi_fill_pattern; /* *_FILL */ extern uint8_t _bgi_fill_color; diff --git a/libc/bgi/_bgi_line_state.c b/libc/bgi/_bgi_line_state.c new file mode 100644 index 0000000..f66ad51 --- /dev/null +++ b/libc/bgi/_bgi_line_state.c @@ -0,0 +1,9 @@ +/* + * _bgi_line_state — текущий стиль/толщина/маска линий BGI. + * initgraph ставит SOLID_LINE / NORM / 0xFFFF. Без инициализации. + */ +#include "_bgi.h" + +uint8_t _bgi_line_style; +uint8_t _bgi_line_thick; +uint16_t _bgi_line_pattern; diff --git a/libc/bgi/_bgi_styled_line.c b/libc/bgi/_bgi_styled_line.c new file mode 100644 index 0000000..415f649 --- /dev/null +++ b/libc/bgi/_bgi_styled_line.c @@ -0,0 +1,58 @@ +/* + * _bgi_styled_line — отрезок текущим стилем и толщиной линии. + * + * SOLID+NORM → быстрый _bgi_lineseg (accel). Иначе — Брезенхэм с + * 16-битной маской (бит на шаг; когда бит 0 — пропуск) и, для THICK, + * дублированием перпендикулярно основной оси (±1). Всё raw в одной + * W3-скобке. + */ +#include "_bgi.h" + +/* Маски стандартных стилей (SOLID/DOTTED/CENTER/DASHED). */ +static const uint16_t _bgi_line_pat[4] = { 0xFFFF, 0xCCCC, 0xFF18, 0xF8F8 }; + +void _bgi_styled_line(int x0, int y0, int x1, int y1, uint8_t color) +{ + uint16_t pat; + uint8_t bit, style, thick; + int dx, dy, sx, sy, err, e2, major_x; + + style = _bgi_line_style; + thick = _bgi_line_thick; + if (style == SOLID_LINE && thick <= 1) { + _bgi_lineseg(x0, y0, x1, y1, color); + return; + } + pat = (style == USERBIT_LINE) ? _bgi_line_pattern + : _bgi_line_pat[style & 3]; + + dx = x1 - x0; if (dx < 0) dx = -dx; + dy = y1 - y0; if (dy < 0) dy = -dy; + sx = (x0 < x1) ? 1 : -1; + sy = (y0 < y1) ? 1 : -1; + err = dx - dy; + major_x = (dx >= dy); + bit = 0; + + _bgi_begin(); + for (;;) { + if ((pat >> (bit & 15)) & 1) { + _bgi_plot_raw(x0, y0, color); + if (thick > 1) { + if (major_x) { + _bgi_plot_raw(x0, y0 - 1, color); + _bgi_plot_raw(x0, y0 + 1, color); + } else { + _bgi_plot_raw(x0 - 1, y0, color); + _bgi_plot_raw(x0 + 1, y0, color); + } + } + } + bit++; + if (x0 == x1 && y0 == y1) break; + e2 = 2 * err; + if (e2 > -dy) { err -= dy; x0 += sx; } + if (e2 < dx) { err += dx; y0 += sy; } + } + _bgi_end(); +} diff --git a/libc/bgi/drawpoly.c b/libc/bgi/drawpoly.c index fd023e5..9f0ec46 100644 --- a/libc/bgi/drawpoly.c +++ b/libc/bgi/drawpoly.c @@ -10,7 +10,7 @@ void drawpoly(int numpoints, const int *polypoints) int i; if (numpoints < 2) return; for (i = 0; i < numpoints - 1; i++) { - _bgi_lineseg(polypoints[2 * i], polypoints[2 * i + 1], + _bgi_styled_line(polypoints[2 * i], polypoints[2 * i + 1], polypoints[2 * i + 2], polypoints[2 * i + 3], _bgi_fg); } diff --git a/libc/bgi/getlinesettings.c b/libc/bgi/getlinesettings.c new file mode 100644 index 0000000..7a5b74c --- /dev/null +++ b/libc/bgi/getlinesettings.c @@ -0,0 +1,10 @@ +/* getlinesettings — прочитать текущий стиль/маску/толщину линий. */ +#include "_bgi.h" + +void getlinesettings(struct linesettingstype *lineinfo) +{ + if (!lineinfo) return; + lineinfo->linestyle = _bgi_line_style; + lineinfo->upattern = _bgi_line_pattern; + lineinfo->thickness = _bgi_line_thick; +} diff --git a/libc/bgi/initgraph.c b/libc/bgi/initgraph.c index bdf4fac..8753f10 100644 --- a/libc/bgi/initgraph.c +++ b/libc/bgi/initgraph.c @@ -17,4 +17,7 @@ void initgraph(void) _bgi_result = grOk; _bgi_fill_pattern = SOLID_FILL; _bgi_fill_color = WHITE; + _bgi_line_style = SOLID_LINE; + _bgi_line_thick = NORM_WIDTH; + _bgi_line_pattern = 0xFFFF; } diff --git a/libc/bgi/line.c b/libc/bgi/line.c index 5ccb0c3..c9a0b42 100644 --- a/libc/bgi/line.c +++ b/libc/bgi/line.c @@ -3,5 +3,5 @@ void line(int x1, int y1, int x2, int y2) { - _bgi_lineseg(x1, y1, x2, y2, _bgi_fg); + _bgi_styled_line(x1, y1, x2, y2, _bgi_fg); } diff --git a/libc/bgi/linerel.c b/libc/bgi/linerel.c index b6b715d..bbb0c27 100644 --- a/libc/bgi/linerel.c +++ b/libc/bgi/linerel.c @@ -5,7 +5,7 @@ void linerel(int dx, int dy) { int nx = _bgi_cx + dx; int ny = _bgi_cy + dy; - _bgi_lineseg(_bgi_cx, _bgi_cy, nx, ny, _bgi_fg); + _bgi_styled_line(_bgi_cx, _bgi_cy, nx, ny, _bgi_fg); _bgi_cx = nx; _bgi_cy = ny; } diff --git a/libc/bgi/lineto.c b/libc/bgi/lineto.c index 1197884..7fe6291 100644 --- a/libc/bgi/lineto.c +++ b/libc/bgi/lineto.c @@ -3,7 +3,7 @@ void lineto(int x, int y) { - _bgi_lineseg(_bgi_cx, _bgi_cy, x, y, _bgi_fg); + _bgi_styled_line(_bgi_cx, _bgi_cy, x, y, _bgi_fg); _bgi_cx = x; _bgi_cy = y; } diff --git a/libc/bgi/rectangle.c b/libc/bgi/rectangle.c index 09509e2..96523bb 100644 --- a/libc/bgi/rectangle.c +++ b/libc/bgi/rectangle.c @@ -4,8 +4,8 @@ void rectangle(int left, int top, int right, int bottom) { uint8_t c = _bgi_fg; - _bgi_lineseg(left, top, right, top, c); /* верх */ - _bgi_lineseg(right, top, right, bottom, c); /* право */ - _bgi_lineseg(right, bottom, left, bottom, c); /* низ */ - _bgi_lineseg(left, bottom, left, top, c); /* лево */ + _bgi_styled_line(left, top, right, top, c); /* верх */ + _bgi_styled_line(right, top, right, bottom, c); /* право */ + _bgi_styled_line(right, bottom, left, bottom, c); /* низ */ + _bgi_styled_line(left, bottom, left, top, c); /* лево */ } diff --git a/libc/bgi/setlinestyle.c b/libc/bgi/setlinestyle.c new file mode 100644 index 0000000..9fc98e0 --- /dev/null +++ b/libc/bgi/setlinestyle.c @@ -0,0 +1,9 @@ +/* setlinestyle — задать стиль, пользовательскую маску и толщину линий. */ +#include "_bgi.h" + +void setlinestyle(int linestyle, unsigned upattern, int thickness) +{ + _bgi_line_style = (uint8_t)linestyle; + _bgi_line_pattern = (uint16_t)upattern; + _bgi_line_thick = (thickness >= THICK_WIDTH) ? THICK_WIDTH : NORM_WIDTH; +} diff --git a/libc/include/graphics.h b/libc/include/graphics.h index d438253..b053793 100644 --- a/libc/include/graphics.h +++ b/libc/include/graphics.h @@ -93,6 +93,19 @@ void ellipse(int x, int y, int stangle, int endangle, /* Ломаная по numpoints точкам {x0,y0,x1,y1,…}; НЕ замыкается сама. */ void drawpoly(int numpoints, const int *polypoints); +/* ---- Стиль линий ------------------------------------------------- * + * Действует на line/lineto/linerel/rectangle/drawpoly. USERBIT_LINE + * использует 16-битный upattern. thickness: NORM_WIDTH или THICK_WIDTH. + * (Окружности/дуги пока всегда сплошные 1px — упрощение.) */ +enum { SOLID_LINE = 0, DOTTED_LINE, CENTER_LINE, DASHED_LINE, USERBIT_LINE }; +#define NORM_WIDTH 1 +#define THICK_WIDTH 3 + +struct linesettingstype { int linestyle; unsigned upattern; int thickness; }; + +void setlinestyle(int linestyle, unsigned upattern, int thickness); +void getlinesettings(struct linesettingstype *lineinfo); + /* ---- Заливки ----------------------------------------------------- * * Стиль заливки — паттерн (8×8) + цвет; действует на bar/bar3d/ * fillpoly/fillellipse. SOLID_FILL заполняет сплошняком, EMPTY_FILL — diff --git a/tests/bgitest/bgitest.c b/tests/bgitest/bgitest.c index e9a2052..904e446 100644 --- a/tests/bgitest/bgitest.c +++ b/tests/bgitest/bgitest.c @@ -1,15 +1,14 @@ /* * bgitest — демонстрация BGI-слоя graphics.h (режим 320×256×256). - * Фаза 2d-1: getimage/putimage/imagesize (спрайты, COPY/XOR/OR). + * Фаза 2d-2: setlinestyle (SOLID/DOTTED/CENTER/DASHED + THICK). */ #include -static unsigned char buf[2048]; - int main(void) { - int mx, my; + int mx, my, i, y; + static const char *name[4] = { "SOLID", "DOTTED", "CENTER", "DASHED" }; initgraph(); mx = getmaxx(); @@ -19,37 +18,36 @@ int main(void) setcolor(WHITE); rectangle(0, 0, mx, my); setcolor(YELLOW); - outtextxy(88, 6, "BGI image / sprite"); + outtextxy(104, 6, "BGI linestyle"); - /* Исходный спрайт 40×30 в левом верхнем углу. */ - setfillstyle(SOLID_FILL, LIGHTBLUE); - bar(12, 28, 51, 57); - setcolor(YELLOW); - rectangle(12, 28, 51, 57); - setcolor(LIGHTRED); - line(12, 28, 51, 57); - setfillstyle(SOLID_FILL, LIGHTGREEN); - fillellipse(31, 42, 8, 8); + /* Четыре стиля тонкой линией. */ + 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); + } + + /* Толстые версии тех же стилей. */ + 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, 60, "src"); + outtextxy(12, 150, "THICK"); - /* Захват и раскладка копий (COPY_PUT). */ - getimage(12, 28, 51, 57, buf); - putimage(80, 28, buf, COPY_PUT); - putimage(130, 28, buf, COPY_PUT); - putimage(180, 28, buf, COPY_PUT); + /* Прямоугольник пунктиром + диагонали. */ + setcolor(LIGHTMAGENTA); + setlinestyle(DASHED_LINE, 0, NORM_WIDTH); + rectangle(20, 212, 130, 250); + line(20, 212, 130, 250); setcolor(WHITE); - outtextxy(80, 60, "copy x3"); - - /* XOR и OR поверх серого фона. */ - setfillstyle(SOLID_FILL, DARKGRAY); - bar(20, 110, 240, 170); - putimage(30, 122, buf, XOR_PUT); - outtextxy(30, 176, "xor"); - putimage(110, 122, buf, OR_PUT); - outtextxy(110, 176, "or"); - putimage(190, 122, buf, COPY_PUT); - outtextxy(190, 176, "copy"); + setlinestyle(SOLID_LINE, 0, NORM_WIDTH); + outtextxy(150, 228, "dashed rect"); for (;;) { } }