/////////////////////////////////////////////////////////// /// Copy /////////////////////////////////////////////////////////// void Bitmap::Copy(int x, int y, Bitmap* src_bitmap, Rect src_rect) { if (src_bitmap->GetWidth() == 0 || src_bitmap->GetHeight() == 0 || width == 0 || height == 0) return; if (x >= width || y >= height) return; if (x < 0) { src_rect.x -= x; x = 0; } if (y < 0) { src_rect.y -= y; y = 0; } src_rect.Adjust(src_bitmap->GetWidth(), src_bitmap->GetHeight()); if (src_rect.IsOutOfBounds(src_bitmap->GetWidth(), src_bitmap->GetHeight())) return; int src_width = src_rect.width; int src_height = src_rect.height; if (x + src_width > width) src_width = width - x; if (y + src_height > height) src_height = height - y; if (src_width <= 0 || src_height <= 0) return; int src_pitch = src_width * 4; int src_row = src_bitmap->GetWidth(); const Uint32* src_pixels = ((Uint32*)(&src_bitmap->pixels[0])) + src_rect.x + src_rect.y * src_bitmap->GetWidth(); Uint32* dst_pixels = ((Uint32*)(&pixels[0])) + x + y * width; for (int i = 0; i < src_height; ++i) { memcpy(dst_pixels, src_pixels, src_pitch); src_pixels += src_row; dst_pixels += width; } Changed(); }
void Bitmap::HSLChange(double h, double s, double l, Rect rect) { rect.Adjust(GetWidth(), GetHeight()); if (rect.IsOutOfBounds(GetWidth(), GetHeight())) return; for (int i = rect.y; i < rect.y + rect.height; i++) { for (int j = rect.x; j < rect.x + rect.width; j++) { Color color = Color::NewUint32(pixels[(i * width) + j]); pixels[(i * width) + j] = RGBAdjustHSL(color, h, s, l).GetUint32(); } } Changed(); }
/////////////////////////////////////////////////////////// /// Fill rect /////////////////////////////////////////////////////////// void Bitmap::FillRect(Rect rect, Color color) { rect.Adjust(GetWidth(), GetHeight()); if (rect.IsOutOfBounds(GetWidth(), GetHeight())) return; long dst = rect.x + rect.y * width; Uint32 col = color.GetUint32(); for (int i = 0; i < rect.height; i++) { fill_n(pixels.begin() + dst, rect.width, col); dst += width; } Changed(); }
/////////////////////////////////////////////////////////// /// Stretch blit /////////////////////////////////////////////////////////// void Bitmap::StretchBlit(Rect dst_rect, Bitmap* src_bitmap, Rect src_rect, int opacity) { if (src_rect.width == dst_rect.width && src_rect.height == dst_rect.height) { Blit(dst_rect.x, dst_rect.y, src_bitmap, src_rect, opacity); } else { src_rect.Adjust(src_bitmap->GetWidth(), src_bitmap->GetHeight()); if (src_rect.IsOutOfBounds(src_bitmap->GetWidth(), src_bitmap->GetHeight())) return; Bitmap* resampled = src_bitmap->Resample(dst_rect.width, dst_rect.height, src_rect); Rect rect(0, 0, dst_rect.width, dst_rect.height); Blit(dst_rect.x, dst_rect.y, resampled, rect, opacity); delete resampled; } Changed(); }
/////////////////////////////////////////////////////////// /// Blit /////////////////////////////////////////////////////////// void Bitmap::Blit(int x, int y, Bitmap* src_bitmap, Rect src_rect, int opacity) { if (src_bitmap->GetWidth() == 0 || src_bitmap->GetHeight() == 0 || width == 0 || height == 0) return; if (x >= width || y >= height) return; if (x < 0) { src_rect.x -= x; x = 0; } if (y < 0) { src_rect.y -= y; y = 0; } src_rect.Adjust(src_bitmap->GetWidth(), src_bitmap->GetHeight()); if (src_rect.IsOutOfBounds(src_bitmap->GetWidth(), src_bitmap->GetHeight())) return; int src_width = src_rect.width; int src_height = src_rect.height; if (x + src_width > width) src_width = width - x; if (y + src_height > height) src_height = height - y; if (src_width <= 0 || src_height <= 0) return; int src_row = src_bitmap->GetWidth() * 4; int dst_row = width * 4; const Uint8* src_pixels = ((Uint8*)(&src_bitmap->pixels[0])) + (src_rect.x + src_rect.y * src_bitmap->GetWidth()) * 4; Uint8* dst_pixels = ((Uint8*)(&pixels[0])) + (x + y * width) * 4; if (opacity > 255) opacity = 255; if (opacity > 0) { for (int i = 0; i < src_height; ++i) { for (int j = 0; j < src_width; ++j) { const Uint8* src = src_pixels + j * 4; Uint8* dst = dst_pixels + j * 4; Uint8 srca = (Uint8)(src[3] * opacity / 255); dst[0] = (dst[0] * (255 - srca) + src[0] * srca) / 255; dst[1] = (dst[1] * (255 - srca) + src[1] * srca) / 255; dst[2] = (dst[2] * (255 - srca) + src[2] * srca) / 255; dst[3] = dst[3] * (255 - srca) / 255 + srca; } src_pixels += src_row; dst_pixels += dst_row; } } Changed(); }
BitmapRef Sprite::Refresh(Rect& rect) { if (zoom_x_effect != 1.0 && zoom_y_effect != 1.0 && angle_effect != 0.0 && waver_effect_depth != 0) { // TODO: Out of bounds check adjustments for zoom, angle and waver // but even without this will catch most of the cases if (Rect(x - ox, y - oy, GetWidth(), GetHeight()).IsOutOfBounds(Rect(0, 0, SCREEN_TARGET_WIDTH, SCREEN_TARGET_HEIGHT))) { return BitmapRef(); }; } rect.Adjust(bitmap->GetWidth(), bitmap->GetHeight()); bool no_tone = tone_effect == Tone(); bool no_flash = flash_effect.alpha == 0; bool no_flip = !flipx_effect && !flipy_effect; bool no_effects = no_tone && no_flash && no_flip; bool effects_changed = tone_effect != current_tone || flash_effect != current_flash || flipx_effect != current_flip_x || flipy_effect != current_flip_y; bool effects_rect_changed = rect != bitmap_effects_src_rect; if (effects_changed || effects_rect_changed || bitmap_changed) { bitmap_effects_valid = false; } if (no_effects) return bitmap; if (bitmap_effects && bitmap_effects_valid) return bitmap_effects; BitmapRef src_bitmap; if (no_effects) src_bitmap = bitmap; else if (bitmap_effects_valid) src_bitmap = bitmap_effects; else { current_tone = tone_effect; current_flash = flash_effect; current_flip_x = flipx_effect; current_flip_y = flipy_effect; if (bitmap_effects && bitmap_effects->GetWidth() < rect.x + rect.width && bitmap_effects->GetHeight() < rect.y + rect.height) { bitmap_effects.reset(); } if (!bitmap_effects) bitmap_effects = Bitmap::Create(bitmap->GetWidth(), bitmap->GetHeight(), true); bitmap_effects->Clear(); if (no_tone && no_flash) bitmap_effects->FlipBlit(rect.x, rect.y, *bitmap, rect, flipx_effect, flipy_effect, Opacity::opaque); else if (no_flip && no_flash) bitmap_effects->ToneBlit(rect.x, rect.y, *bitmap, rect, tone_effect, Opacity::opaque); else if (no_flip && no_tone) bitmap_effects->BlendBlit(rect.x, rect.y, *bitmap, rect, flash_effect, Opacity::opaque); else if (no_flash) { bitmap_effects->ToneBlit(rect.x, rect.y, *bitmap, rect, tone_effect, Opacity::opaque); bitmap_effects->Flip(rect, flipx_effect, flipy_effect); } else if (no_tone) { bitmap_effects->BlendBlit(rect.x, rect.y, *bitmap, rect, flash_effect, Opacity::opaque); bitmap_effects->Flip(rect, flipx_effect, flipy_effect); } else if (no_flip) { bitmap_effects->ToneBlit(rect.x, rect.y, *bitmap, rect, tone_effect, Opacity::opaque); bitmap_effects->BlendBlit(rect.x, rect.y, *bitmap_effects, rect, flash_effect, Opacity::opaque); } else { bitmap_effects->ToneBlit(rect.x, rect.y, *bitmap, rect, tone_effect, Opacity::opaque); bitmap_effects->BlendBlit(rect.x, rect.y, *bitmap_effects, rect, flash_effect, Opacity::opaque); bitmap_effects->Flip(rect, flipx_effect, flipy_effect); } bitmap_effects_src_rect = rect; bitmap_effects_valid = true; src_bitmap = bitmap_effects; } return src_bitmap; }
BitmapRef BitmapScreen::Refresh(Rect& rect, bool& need_scale, int& bush_y) { need_scale = false; rect.Adjust(bitmap->GetWidth(), bitmap->GetHeight()); if (rect.IsOutOfBounds(bitmap->GetWidth(), bitmap->GetHeight())) return BitmapRef(); bool no_tone = tone_effect == Tone(); bool no_flash = flash_effect.alpha == 0; bool no_flip = !flipx_effect && !flipy_effect; bool no_effects = no_tone && no_flash && no_flip; bool no_zoom = zoom_x_effect == 1.0 && zoom_y_effect == 1.0; bool effects_changed = tone_effect != current_tone || flash_effect != current_flash || flipx_effect != current_flip_x || flipy_effect != current_flip_y; bool effects_rect_changed = rect != bitmap_effects_src_rect; if (effects_changed || effects_rect_changed || bitmap_changed) { bitmap_effects_valid = false; bitmap_scale_valid = false; } if (no_effects && no_zoom) return bitmap; if (bitmap_effects != NULL && bitmap_effects_valid && no_zoom) return bitmap_effects; BitmapRef src_bitmap; if (no_effects) src_bitmap = bitmap; else if (bitmap_effects_valid) src_bitmap = bitmap_effects; else { current_tone = tone_effect; current_flash = flash_effect; current_flip_x = flipx_effect; current_flip_y = flipy_effect; if (bitmap_effects != NULL && bitmap_effects->GetWidth() < rect.x + rect.width && bitmap_effects->GetHeight() < rect.y + rect.height) { bitmap_effects.reset(); } if (!bitmap_effects) bitmap_effects = Bitmap::Create(bitmap->GetWidth(), bitmap->GetHeight(), true); bitmap_effects->Clear(); if (no_tone && no_flash) bitmap_effects->FlipBlit(rect.x, rect.y, *bitmap, rect, flipx_effect, flipy_effect); else if (no_flip && no_flash) bitmap_effects->ToneBlit(rect.x, rect.y, *bitmap, rect, tone_effect); else if (no_flip && no_tone) bitmap_effects->BlendBlit(rect.x, rect.y, *bitmap, rect, flash_effect); else if (no_flash) { bitmap_effects->ToneBlit(rect.x, rect.y, *bitmap, rect, tone_effect); bitmap_effects->Flip(rect, flipx_effect, flipy_effect); } else if (no_tone) { bitmap_effects->BlendBlit(rect.x, rect.y, *bitmap, rect, flash_effect); bitmap_effects->Flip(rect, flipx_effect, flipy_effect); } else if (no_flip) { bitmap_effects->BlendBlit(rect.x, rect.y, *bitmap, rect, flash_effect); bitmap_effects->ToneBlit(rect.x, rect.y, *bitmap_effects, rect, tone_effect); } else { bitmap_effects->BlendBlit(rect.x, rect.y, *bitmap, rect, flash_effect); bitmap_effects->ToneBlit(rect.x, rect.y, *bitmap_effects, rect, tone_effect); bitmap_effects->Flip(rect, flipx_effect, flipy_effect); } bitmap_effects_src_rect = rect; bitmap_effects_valid = true; src_bitmap = bitmap_effects; } if (no_zoom || angle_effect != 0.0) return src_bitmap; int zoomed_width = (int)(rect.width * zoom_x_effect); int zoomed_height = (int)(rect.height * zoom_y_effect); if (zoomed_width > 640 || zoomed_height > 640) { need_scale = true; return src_bitmap; } bool zoom_changed = zoom_x_effect != current_zoom_x || zoom_y_effect != current_zoom_y; bool scale_rect_changed = rect != bitmap_scale_src_rect; if (zoom_changed || scale_rect_changed) bitmap_scale_valid = false; if (bitmap_scale != NULL && bitmap_scale_valid) { bush_y = bush_y * bitmap_scale->GetHeight() / rect.height; rect = bitmap_scale->GetRect(); return bitmap_scale; } current_zoom_x = zoom_x_effect; current_zoom_y = zoom_y_effect; bitmap_scale.reset(); bitmap_scale = src_bitmap->Resample(zoomed_width, zoomed_height, rect); bitmap_scale_src_rect = rect; bitmap_scale_valid = true; bush_y = bush_y * bitmap_scale->GetHeight() / rect.height; rect = bitmap_scale->GetRect(); return bitmap_scale; }