#include "render_util.h" #include "camera.h" #include "render_pattern.h" #include "easyx.h" #include "types.h" #include "util/vector.h" #include "app.h" #include #include #include #include extern "C" { static vector_Vector *tbuf; #ifdef __MINGW32__ #define NCHAR char #else #define NCHAR wchar_t #endif void render_DrawText(int x, int y, const char *str) { if (!tbuf) tbuf = vector_Create(sizeof(NCHAR)); int cx = x, cy = y; const NCHAR zero = 0; vector_Clear(tbuf); int len = strlen(str); int i = 0; while (i < len) { if (str[i] == '\n') { vector_Push(tbuf, &zero); outtextxy(cx, cy, (LPCTSTR)vector_Data(tbuf)); cy += TEXTHEIGHT; vector_Clear(tbuf); } else { NCHAR wc = str[i]; vector_Push(tbuf, &wc); } i++; } if (vector_Size(tbuf) > 0) { vector_Push(tbuf, &zero); outtextxy(cx, cy, (LPCTSTR)vector_Data(tbuf)); vector_Clear(tbuf); } } const FillMode render_ModeDefault = { .rop2 = R2_COPYPEN, .style = BS_SOLID, .hatch = 0, .rotate = {.microseconds = 0}, .dissolve = {.microseconds = 0}, .fadein = false}; const FillMode render_ModeInverse = { .rop2 = R2_NOT, .style = BS_SOLID, .hatch = 0, .rotate = {.microseconds = 0}, .dissolve = {.microseconds = 0}, .fadein = false}; extern const FillMode render_ModeRotate = { .rop2 = R2_COPYPEN, .style = BS_SOLID, .hatch = 0, .rotate = {.microseconds = 100000}, .dissolve = {.microseconds = 0}, .fadein = false}; void render_SetModes(FillMode mode, TimePoint since) { if (mode.dissolve.microseconds != 0) { // Dissolve mode double progress = duration_Seconds(time_Since(since)) / duration_Seconds(mode.dissolve); if (mode.fadein) setfillstyle(render_DissolvePatternIn(progress)); // progress is capped into [0,1] in this func else setfillstyle(render_DissolvePatternOut(progress)); setrop2(R2_COPYPEN); return; } if (mode.rotate.microseconds != 0) { // Rotate mode int steps = (int)round(duration_Seconds(time_Since(since)) / duration_Seconds(mode.rotate)); static const long hatches[] = {HS_HORIZONTAL, HS_FDIAGONAL, HS_VERTICAL, HS_BDIAGONAL}; setfillstyle(BS_HATCHED, hatches[steps % 4], NULL); setrop2(R2_COPYPEN); return; } // Normal mode setfillstyle(mode.style, mode.hatch, NULL); setrop2(mode.rop2); } void render_FillScreen() { solidrectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); } void render_FillRectW(App *app, Box2 rect) { if (app->camera) rect = camera_TransformBox2(app->camera, rect); else fprintf(stderr, "[WARN][render_FillRectW] called without an active camera system\n"); solidrectangle( (int)round(rect.lefttop.x), (int)round(rect.lefttop.y), (int)round(rect.lefttop.x + rect.size.x), (int)round(rect.lefttop.y + rect.size.y)); } void render_FillCircleW(App *app, Vec2 center, double radius) { if (app->camera) { center = camera_TransformVec2(app->camera, center); radius = camera_TransformSize(app->camera, vec2(radius, 0)).x; // TODO non-aspect scaling } else fprintf(stderr, "[WARN][render_FillCircleW] called without an active camera system\n"); solidcircle( (int)round(center.x), (int)round(center.y), (int)round(radius)); } }