#include "plat.h" #include "maths.h" #include "render.h" static struct { Rectangle clip; } renderer; Colour make_colour(unsigned rgb, unsigned char a) { Colour r; r.r = (unsigned char)(rgb >> 16); r.g = (unsigned char)(rgb >> 8); r.b = (unsigned char)rgb; r.a = a; return r; } Colour make_black() { Colour r = { 0, 0, 0, 255 }; return r; } Colour make_white() { return make_colour(0xffffff, 255); } void init_bitmap( Bitmap* bitmap, Colour* pixels, int w, int h ) { bitmap->pixels = pixels; bitmap->w = w; bitmap->h = h; } void render_init(void) { int i, e; Colour b, * p; b = make_black(); p = get_fb(); e = get_render_w() * get_render_h(); for (i = 0; i < e; i++) p[i] = b; } void render_begin(void) { int i, e; Colour b, * p; b = make_black(); p = get_fb(); e = get_render_w() * get_render_h(); for (i = 0; i < e; i++) p[i] = b; render_reset_clip(); } void render_clear(void) { render_clear_col(make_black()); } void render_clear_col(Colour col) { Colour* d; int ox, x, y, ex, ey, w; d = get_fb(); x = renderer.clip.x; y = renderer.clip.y; ex = renderer.clip.w; ey = renderer.clip.h; ox = x; w = get_render_w(); for (; y < ey; y++) for (x = ox; x < ex; x++) d[x + y * w] = col; } void render_clip(const Rectangle* rect) { renderer.clip = *rect; renderer.clip.x = maxi(renderer.clip.x, 0); renderer.clip.y = maxi(renderer.clip.y, 0); renderer.clip.w = mini( renderer.clip.w, get_render_w() ); renderer.clip.h = mini( renderer.clip.h, get_render_h() ); } void render_reset_clip(void) { renderer.clip.x = 0; renderer.clip.y = 0; renderer.clip.w = get_render_w(); renderer.clip.h = get_render_h(); } Colour* get_render_pixels(void) { return get_fb(); } Colour blend(Colour dst, Colour src) { int ima; ima = 0xff - src.a; dst.r = (unsigned char)(((src.r * src.a) + (dst.r * ima)) >> 8); dst.g = (unsigned char)(((src.g * src.a) + (dst.g * ima)) >> 8); dst.b = (unsigned char)(((src.b * src.a) + (dst.b * ima)) >> 8); return dst; } Colour blend_mod(Colour dst, Colour src, Colour mod) { int ima; src.a = (src.a * mod.a) >> 8; ima = 0xff - src.a; dst.r = (unsigned char)(((src.r * mod.r * src.a) >> 16) + ((dst.r * ima) >> 8)); dst.g = (unsigned char)(((src.g * mod.g * src.a) >> 16) + ((dst.g * ima) >> 8)); dst.b = (unsigned char)(((src.b * mod.b * src.a) >> 16) + ((dst.b * ima) >> 8)); return dst; } #define blit_vars(t_) \ int i, j, stride, sstride, n; \ Colour* dst; \ const t_* src; \ Rectangle sub; #define blit( \ src_, \ dst_, \ pitch_, \ clip_, \ src_w_, \ src_h_, \ expr_ \ ) \ sub = *rect; \ if (sub.w <= 0) { goto end; } \ if (sub.h <= 0) { goto end; } \ if (sub.w > (src_w_)) { goto end; } \ if (sub.h > (src_h_)) { goto end; } \ if ((n = (clip_).x - x) > 0) { \ sub.w -= n; \ sub.x += n; \ x += n; \ } \ if ((n = (clip_).y - y) > 0) { \ sub.h -= n; \ sub.y += n; \ y += n; \ } \ if ((n = x + sub.w - (clip_).w) > 0) { \ sub.w -= n; \ } \ if ((n = y + sub.h - (clip_).h) > 0) { \ sub.h -= n; \ } \ if (sub.w <= 0) { goto end; } \ if (sub.h <= 0) { goto end; } \ dst = (dst_) + (x + y * (pitch_)); \ src = (src_) + (sub.x + sub.y * (src_w_)); \ stride = (pitch_) - sub.w; \ sstride = (src_w_) - sub.w; \ for (i = 0; i < sub.h; i++) { \ for (j = 0; j < sub.w; j++) { \ expr_; \ dst++; \ src++; \ } \ dst += stride; \ src += sstride; \ } \ end: #define blit_rect_vars \ int x1, y1, x2, y2, dr, j, i; \ Colour* dst; #define blit_rect(dst_, pitch_, clip_) \ x1 = rect->x < (clip_).x ? (clip_).x : rect->x; \ y1 = rect->y < (clip_).y ? (clip_).y : rect->y; \ x2 = rect->x + rect->w; \ y2 = rect->y + rect->h; \ x2 = x2 > (clip_).w? (clip_).w: x2; \ y2 = y2 > (clip_).h? (clip_).h: y2; \ dst = dst_; \ dst += x1 + y1 * pitch_; \ dr = pitch_ - (x2 - x1); \ for (j = y1; j < y2; j++) { \ for (i = x1; i < x2; i++) { \ *dst = blend(*dst, colour); \ dst++; \ } \ dst += dr; \ } void render_bitmap( const Bitmap* bitmap, int x, int y, const Rectangle* rect ) { blit_vars(Colour) int renderer_w; Colour* renderer_pixels; renderer_w = get_render_w(); renderer_pixels = get_fb(); blit( bitmap->pixels, renderer_pixels, renderer_w, renderer.clip, bitmap->w, bitmap->h, *dst = blend(*dst, *src) ); } void render_bitmap_col( const Bitmap* bitmap, int x, int y, const Rectangle* rect, Colour colour ) { blit_vars(Colour) int renderer_w; Colour* renderer_pixels; renderer_w = get_render_w(); renderer_pixels = get_fb(); blit( bitmap->pixels, renderer_pixels, renderer_w, renderer.clip, bitmap->w, bitmap->h, *dst = blend_mod(*dst, *src, colour) ); } void render_mask( const unsigned char* pixels, int x, int y, int w, int h, const Rectangle* rect, Colour colour ) { blit_vars(unsigned char) int renderer_w; Colour c; Colour* renderer_pixels; renderer_w = get_render_w(); renderer_pixels = get_fb(); c = colour; blit( pixels, renderer_pixels, renderer_w, renderer.clip, w, h, { c.a = colour.a * *src; *dst = blend(*dst, c); } ); } void render_rect( const Rectangle* rect, Colour colour ) { blit_rect_vars int renderer_w; Colour* renderer_pixels; renderer_w = get_render_w(); renderer_pixels = get_fb(); blit_rect( renderer_pixels, renderer_w, renderer.clip ); } void rcopy( Bitmap* to, const Bitmap* from, int x, int y, const Rectangle* rect ) { Rectangle clip; blit_vars(Colour); clip.x = 0; clip.y = 0; clip.w = to->w; clip.h = to->h; blit( from->pixels, to->pixels, to->w, clip, from->w, from->h, *dst = blend(*dst, *src) ); } void rcopy_col( Bitmap* to, const Bitmap* from, int x, int y, const Rectangle* rect, Colour colour ) { Rectangle clip; blit_vars(Colour) clip.x = 0; clip.y = 0; clip.w = to->w; clip.h = to->h; blit( from->pixels, to->pixels, to->w, clip, from->w, from->h, *dst = blend_mod(*dst, *src, colour); ); } void rcopy_ac( Bitmap* to, const Bitmap* from, int x, int y, const Rectangle* rect, unsigned char t ) { Rectangle clip; blit_vars(Colour) clip.x = 0; clip.y = 0; clip.w = to->w; clip.h = to->h; blit( from->pixels, to->pixels, to->w, clip, from->w, from->h, *dst = src->a > t ? *src : *dst; ); } void rcopy_rect( Bitmap* to, const Rectangle* rect, Colour colour ) { Rectangle clip; blit_rect_vars clip.x = 0; clip.y = 0; clip.w = to->w; clip.h = to->h; blit_rect( to->pixels, to->w, clip ); }