#include "config.h" #include #include #include #include "portab.h" #include "system.h" #include "surface.h" #include "graph.h" #include "ngraph.h" #include "nact.h" /* gr_xxxx はクリッピングあり gre_xxxx はクリッピングなし */ #undef WARNING #define WARNING(...) #undef NOTICE #define NOTICE(...) /** * surface から surface にコピーなどをする際に、転送元と転送先のsurface * の大きさや、転送元・転送先座標、転送する領域の大きさなどから、実際に * コピーする領域をクリッピングする * * @param ss: 転送元surface * @param sx: 転送元X座標 * @param sy: 転送元Y座標 * @param sw: 転送幅 * @param sh: 転送高さ * @param ds: 転送先surface * @param dx: 転送先X座標 * @param dy: 転送先Y座標 * @return TRUE -> 描画領域がある * FALSE-> 転送領域の高さや幅が0以下になったり、転送元、転送先の座標が * surfaceの範囲外になり、描画領域がなくなった。 * それぞれの引数は適宜変更されている */ boolean gr_clip(surface_t *ss, int *sx, int *sy, int *sw, int *sh, surface_t *ds, int *dx, int *dy) { int w, h; if (ss == NULL) { WARNING("ss surface is null"); return FALSE; } if (ss == NULL) { WARNING("ss surface is null"); return FALSE; } if (*sx > ss->width) { WARNING("sx is too large (sx=%d,width=%d)", *sx, ss->width); return FALSE; } if (*sy > ss->height) { WARNING("sy is too large (sy=%d,height=%d)", *sy, ss->height); return FALSE; } if (*sx < 0) { WARNING("sx is too small (sx=%d)", *sx); return FALSE; } if (*sy < 0) { WARNING("sy is too small (sy=%d)", *sy); return FALSE; } if (*dx > ds->width) { WARNING("dx is too large (dx=%d,width=%d)", *dx, ds->width); return FALSE; } if (*dy > ds->height) { WARNING("dy is too large (dy=%d,height=%d)", *dy, ds->height); return FALSE; } w = *sw; h = *sh; if (*dx < 0) { *sx -= *dx; *sw += *dx; *dx = 0; } if (*dy < 0) { *sy -= *dy; *sh += *dy; *dy = 0; } *sw = min(ss->width - *sx, min(ds->width - *dx, *sw)); *sh = min(ss->height - *sy, min(ds->height - *dy, *sh)); if (*sw <= 0) { WARNING("sw become <=0"); return FALSE; } if (*sh <= 0) { WARNING("sh become <=0"); return FALSE; } if (*sw != w) { NOTICE("width change %d -> %d", w, *sw); } if (*sh != h) { NOTICE("height change %d -> %d", h, *sh); } return TRUE; } /** * surface 内に描画を行う際に、surface の大きさで描画領域をクリッピングする * * @param ss: 描画surface * @param sx: 描画開始X座標 * @param sy: 描画開始Y座標 * @param sw: 描画幅 * @param sh: 描画高さ * @return TRUE -> 描画領域がある * FALSE-> 描画領域の高さや幅が0以下になったり、描画開始座標が * surfaceの範囲外になり、描画領域がなくなった。 * それぞれの引数は適宜変更されている */ boolean gr_clip_xywh(surface_t *ss, int *sx, int *sy, int *sw, int *sh) { int w, h; if (ss == NULL) { WARNING("ss surface is null"); return FALSE; } if (*sx > ss->width) { WARNING("sx is too large (sx=%d,width=%d)", *sx, ss->width); return FALSE; } if (*sy > ss->height) { WARNING("sy is too large (sy=%d,height=%d)", *sy, ss->height); return FALSE; } w = *sw; h = *sh; if (*sx < 0) { *sw += *sx; *sx = 0; } if (*sy < 0) { *sh += *sy; *sy = 0; } *sw = min(ss->width - *sx, *sw); *sh = min(ss->height - *sy, *sh); if (*sw <= 0) { WARNING("sw become <=0"); return FALSE; } if (*sh <= 0) { WARNING("sh become <=0"); return FALSE; } if (*sw != w) { NOTICE("width change %d -> %d", w, *sw); } if (*sh != h) { NOTICE("height change %d -> %d", h, *sh); } return TRUE; } void gr_init() { } void gr_blend(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int lv) { } void gr_blend_src_bright(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int alpha, int rate) { } void gr_blend_add_satur(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height) { } void gr_blend_alpha_map_src_only(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height) { // Dest Pixel = Blend(DestPixel, SrcPixel, SrcAlphaMap); } void gr_blend_alpha_map_color(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int r, int g, int b) { // Dest Pixel = Blend(DestPixel, Color, SrcAlphaMap); } void gr_blend_alpha_map_color_alpha(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int r, int g, int b, int rate) { // Dest Pixel = Blend(DestPixel, Color, SrcAlphaMap x rate); } void gr_blend_alpha_map_alpha(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int rate) { // Dest Pixel = Blend(DestPixel, SrcPixel, SrcAlphaMap x rate); } void gr_blend_alpha_map_bright(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int lv) { // Dest Pixel = Blend(DestPixel, SrcPixel x lv, SrcAlphaMap); } void gr_blend_alpha_map_alpha_src_bright(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height, int rate, int lv) { // Dest Pixel = Blend(DestPixel, SrcPixel x lv, SrcAlphaMap x rate); } void gr_blend_use_amap_color(surface_t *dst, int dx, int dy, int width, int height, surface_t *alpha, int ax, int ay, int r, int g, int b, int rate) { } void gr_blend_multiply(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int w, int h) { } void gr_blend_screen_alpha(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int w, int h, int rate) { // Screen x rate } void gr_screen_DA_DAxSA(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height) { // DestAlpha = Screen(DestAlpha, SrcAlpha); } void gr_add_DA_DAxSA(surface_t *dst, int dx, int dy, surface_t *src, int sx, int sy, int width, int height) { // Dest Alpha = Satur(DestAlpha + SrcAlpha); } void gr_copy_texture_wrap() { } void gr_copy_texture_wrap_alpha() { } void gr_copy_stretch_blend() { } void gr_copy_stretch_blend_alpha_map(surface_t *dst, int dx, int dy, int dw, int dh, surface_t *src, int sx, int sy, int sw, int sh) { float a1, a2, xd, yd; int *row, *col; int x, y; uint8_t *sp, *dp, *sa; if (!gr_clip_xywh(dst, &dx, &dy, &dw, &dh)) return; if (!gr_clip_xywh(src, &sx, &sy, &sw, &sh)) return; sp = GETOFFSET_PIXEL(src, sx, sy); dp = GETOFFSET_PIXEL(dst, dx, dy); sa = GETOFFSET_ALPHA(src, sx, sy); a1 = (float)sw / (float)dw; a2 = (float)sh / (float)dh; // src width と dst width が同じときに問題があるので+1 row = calloc(dw+1, sizeof(int)); // 1おおきくして初期化しないと col[dw-1]とcol[dw]が同じになる // 可能性がある。 col = calloc(dh+1, sizeof(int)); for (yd = 0.0, y = 0; y < dh; y++) { col[y] = yd; yd += a2; } for (xd = 0.0, x = 0; x < dw; x++) { row[x] = xd; xd += a1; } switch(dst->depth) { case 16: { uint16_t *yls, *yld; uint8_t *yla; for (y = 0; y < dh; y++) { yls = (uint16_t *)(sp + *(y + col) * src->bytes_per_line); yld = (uint16_t *)(dp + y * dst->bytes_per_line); yla = (uint8_t *)(sa + *(y + col) * src->width); for (x = 0; x < dw; x++) { *(yld + x) = ALPHABLEND16(*(yls+ *(row + x)), *(yld+x), *(yla+*(row+x))); } while(*(col + y) == *(col + y + 1)) { yld += dst->width; for (x = 0; x < dw; x++) { *(yld + x) = ALPHABLEND16(*(yls+ *(row+x)), *(yld+x), *(yla+*(row+x))); } y++; } } break; } case 24: case 32: { uint32_t *yls, *yld; uint8_t *yla; for (y = 0; y < dh; y++) { yls = (uint32_t *)(sp + *(y + col) * src->bytes_per_line); yld = (uint32_t *)(dp + y * dst->bytes_per_line); yla = (uint8_t *)(sa + *(y + col) * src->width); for (x = 0; x < dw; x++) { *(yld + x) = ALPHABLEND24(*(yls+ *(row + x)), *(yld+x), *(yla+*(row+x))); } while(*(col + y) == *(col + y + 1)) { yld += dst->width; for (x = 0; x < dw; x++) { *(yld + x) = ALPHABLEND24(*(yls+ *(row+x)), *(yld+x), *(yla+*(row+x))); } y++; } } break; } } free(row); free(col); } #include "graph2.c"