первое движение

This commit is contained in:
2025-11-17 15:58:18 +03:00
parent 92f4632803
commit 2c383b20e9
4 changed files with 115 additions and 2 deletions

View File

@@ -1,5 +1,5 @@
#ifndef FIGURE_DRAW_H #ifndef FIGURE_DRAW_H
#define FIGURE_ANFIGURE_DRAW_HIMATE_H #define FIGURE_DRAW_H
#include "window.h" #include "window.h"

View File

109
wayland/src/figure-draw.c Normal file
View File

@@ -0,0 +1,109 @@
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include "figure-draw.h"
/* C implementation of the drawing routine. The .asm file simply forwards to this
* function so we keep the symbol present in an assembly file. */
void figure_draw(struct window_draw_info* draw_info, float border_thickness, uint32_t border_color, uint32_t fill_color)
{
if (!draw_info || !draw_info->data)
return;
int w = draw_info->width;
int h = draw_info->height;
uint32_t *pixels = (uint32_t *)draw_info->data;
struct figure_animation_info fig = draw_info->figure;
/* center in pixels */
float cx = fig.position.x * (float)w;
float cy = fig.position.y * (float)h;
float r = fig.radius * (float)w; /* normalized to width */
float r2 = r * r;
float border = border_thickness;
if (border < 0.0f) border = 0.0f;
/* bounding box */
int minx = (int)floorf(cx - r);
int maxx = (int)ceilf(cx + r);
int miny = (int)floorf(cy - r);
int maxy = (int)ceilf(cy + r);
/* make sure we don't go out of bounds */
if (miny < 0) miny = 0;
if (minx < 0) minx = 0;
if (maxy >= h) maxy = h - 1;
if (maxx >= w) maxx = w - 1;
/* We'll compute pixel centers at (x + 0.5f, y + 0.5f) */
for (int y = miny; y <= maxy; ++y)
{
float py = (float)y + 0.5f;
for (int x = minx; x <= maxx; ++x)
{
float px = (float)x + 0.5f;
int draw = 0;
int border_pixel = 0;
switch (fig.type)
{
case FIGURE_CIRCLE:
{
float dx = px - cx;
float dy = py - cy;
float d2 = dx*dx + dy*dy;
if (d2 <= r2)
{
draw = 1;
if (d2 >= (r - border)*(r - border))
border_pixel = 1;
}
break;
}
case FIGURE_SQUARE:
{
float dx = fabsf(px - cx);
float dy = fabsf(py - cy);
if (dx <= r && dy <= r)
{
draw = 1;
if (fmaxf(dx, dy) >= r - border)
border_pixel = 1;
}
break;
}
case FIGURE_TRIANGLE:
{
/* Equilateral triangle centered at cx,cy. Apex up. *
* Vertices: A=(cx, cy - r), B=(cx + r*0.866, cy + r*0.5), C=(cx - r*0.866, cy + r*0.5) */
float v1x = r * 0.8660254037844386f;
float v1y = r * 0.5f;
float ax = cx; float ay = cy - r;
float bx = cx + v1x; float by = cy + v1y;
float cx2 = cx - v1x; float cy2 = by;
/* barycentric tests: point inside triangle if all cross products have same sign */
float s1 = (px - bx)*(ay - by) - (ax - bx)*(py - by);
float s2 = (px - cx2)*(by - cy2) - (bx - cx2)*(py - cy2);
float s3 = (px - ax)*(cy2 - ay) - (cx2 - ax)*(py - ay);
int neg = (s1 < 0) + (s2 < 0) + (s3 < 0);
int pos = (s1 > 0) + (s2 > 0) + (s3 > 0);
if (neg == 0 || pos == 0)
{
draw = 1;
}
break;
}
default:
break;
}
if (draw)
{
uint32_t col = border_pixel ? border_color : fill_color;
pixels[y * w + x] = col;
}
}
}
}
/* C symbol exported to be called by minimal assembly wrapper */

View File

@@ -1,5 +1,6 @@
#include "window.h" #include "window.h"
#include "registry.h" #include "registry.h"
#include "figure-draw.h"
#include "xdg-shell-client-protocol.h" #include "xdg-shell-client-protocol.h"
#include <wayland-client.h> #include <wayland-client.h>
#include <stddef.h> #include <stddef.h>
@@ -128,9 +129,12 @@ static void draw(struct wayland_window *win)
{ {
uint32_t *row = (uint32_t *)(bytes + y * stride); uint32_t *row = (uint32_t *)(bytes + y * stride);
for (int32_t x = 0; x < (int32_t)draw_info->width; ++x) for (int32_t x = 0; x < (int32_t)draw_info->width; ++x)
row[x] = color; row[x] = 0xFF000000; /* background black */
} }
/* Draw figure into buffer. border thickness in pixels = 3.0f */
figure_draw(&win->draw_info, 3.0f, 0xFFFFFFFF, color);
wl_surface_attach(win->wl_surface, win->buffer, 0, 0); wl_surface_attach(win->wl_surface, win->buffer, 0, 0);
wl_surface_damage_buffer(win->wl_surface, 0, 0, draw_info->width, draw_info->height); wl_surface_damage_buffer(win->wl_surface, 0, 0, draw_info->width, draw_info->height);
wl_surface_commit(win->wl_surface); wl_surface_commit(win->wl_surface);