/* * gfx_blit_part_vflip — под-прямоугольник картинки С КЛИПОМ по экрану, * ЗЕРКАЛЬНО ПО ВЕРТИКАЛИ. Пара к gfx_blit_part; механика зеркала — см. * gfx_blit_noclip_vflip (знак src-страйда). * * Клип здесь СВОЙ, а не через _gfx_blit_full: общее ядро режет источник в * прямом порядке строк, а у зеркала обрезка сверху экрана съедает НИЖНИЕ * строки источника — считать это внутри общего ядра дороже, чем восемь * строк арифметики здесь (функция и так вызывается только у края экрана, * в тайловом слое основной путь — noclip-двойники). * * Соответствие строк: экранная (y + i) <- источник (sy + h - 1 - i). * Значит обрезка сверху (y < 0) сдвигает старт по i, а обрезка снизу * просто укорачивает h. */ #include "../include/gfx.h" #include "../_bgi.h" void gfx_blit_part_vflip(int x, int y, const void *img, int sx, int sy, int w, int h) { const uint8_t *p = (const uint8_t *)img; uint16_t stride = (uint16_t)(p[0] | (p[1] << 8)); int skip; int h0 = h; /* высота ДО клипа — от неё считается первая * строка источника (h ниже укорачивается) */ if (!stride || w <= 0 || h <= 0) return; /* --- клип по X: источник сдвигается вместе с экраном --- */ if (x < 0) { sx -= x; w += x; x = 0; } if (x + w > GFX_WIDTH) w = GFX_WIDTH - x; if (w <= 0) return; /* --- клип по Y: сверху съедаются НИЖНИЕ строки источника --- */ if (y < 0) { skip = -y; h -= skip; y = 0; } else { skip = 0; } if (y + h > GFX_HEIGHT) h = GFX_HEIGHT - y; if (h <= 0) return; /* Полосы шире одного accel-блока режет вызывающий у noclip-двойников; * здесь ширина приходит от тайла (≤ 64), поэтому хватает одной. */ if (w > 255) w = 255; _bgi_begin(); /* Экранная строка (y+i) <- источник (sy + h0 - 1 - i). Обрезка сверху * сдвигает старт на skip строк ВНИЗ по источнику, обрезка снизу только * укорачивает h и первой строки не касается. */ _bgi_blit_rows_raw(p + 4 + (uint16_t)(sy + h0 - 1 - skip) * stride + (uint16_t)sx, (uint8_t *)(_gfx_addr_base + x), (uint8_t)w, (uint8_t)h, -(int)stride, (uint8_t)y); _bgi_end(); }