|
@@ -2442,6 +2442,39 @@ Ref<Image> Image::get_rect(const Rect2 &p_area) const {
|
|
return img;
|
|
return img;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void Image::_get_clipped_src_and_dest_rects(const Ref<Image> &p_src, const Rect2i &p_src_rect, const Point2i &p_dest, Rect2i &r_clipped_src_rect, Rect2i &r_clipped_dest_rect) const {
|
|
|
|
+ r_clipped_dest_rect.position = p_dest;
|
|
|
|
+ r_clipped_src_rect = p_src_rect;
|
|
|
|
+
|
|
|
|
+ if (r_clipped_src_rect.position.x < 0) {
|
|
|
|
+ r_clipped_dest_rect.position.x -= r_clipped_src_rect.position.x;
|
|
|
|
+ r_clipped_src_rect.size.x += r_clipped_src_rect.position.x;
|
|
|
|
+ r_clipped_src_rect.position.x = 0;
|
|
|
|
+ }
|
|
|
|
+ if (r_clipped_src_rect.position.y < 0) {
|
|
|
|
+ r_clipped_dest_rect.position.y -= r_clipped_src_rect.position.y;
|
|
|
|
+ r_clipped_src_rect.size.y += r_clipped_src_rect.position.y;
|
|
|
|
+ r_clipped_src_rect.position.y = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (r_clipped_dest_rect.position.x < 0) {
|
|
|
|
+ r_clipped_src_rect.position.x -= r_clipped_dest_rect.position.x;
|
|
|
|
+ r_clipped_src_rect.size.x += r_clipped_dest_rect.position.x;
|
|
|
|
+ r_clipped_dest_rect.position.x = 0;
|
|
|
|
+ }
|
|
|
|
+ if (r_clipped_dest_rect.position.y < 0) {
|
|
|
|
+ r_clipped_src_rect.position.y -= r_clipped_dest_rect.position.y;
|
|
|
|
+ r_clipped_src_rect.size.y += r_clipped_dest_rect.position.y;
|
|
|
|
+ r_clipped_dest_rect.position.y = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ r_clipped_src_rect.size.x = MAX(0, MIN(r_clipped_src_rect.size.x, MIN(p_src->width - r_clipped_src_rect.position.x, width - r_clipped_dest_rect.position.x)));
|
|
|
|
+ r_clipped_src_rect.size.y = MAX(0, MIN(r_clipped_src_rect.size.y, MIN(p_src->height - r_clipped_src_rect.position.y, height - r_clipped_dest_rect.position.y)));
|
|
|
|
+
|
|
|
|
+ r_clipped_dest_rect.size.x = r_clipped_src_rect.size.x;
|
|
|
|
+ r_clipped_dest_rect.size.y = r_clipped_src_rect.size.y;
|
|
|
|
+}
|
|
|
|
+
|
|
void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
|
|
void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest) {
|
|
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
|
|
ERR_FAIL_COND_MSG(p_src.is_null(), "It's not a reference to a valid Image object.");
|
|
int dsize = data.size();
|
|
int dsize = data.size();
|
|
@@ -2451,22 +2484,13 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
|
|
ERR_FAIL_COND(format != p_src->format);
|
|
ERR_FAIL_COND(format != p_src->format);
|
|
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot blit_rect in compressed or custom image formats.");
|
|
ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot blit_rect in compressed or custom image formats.");
|
|
|
|
|
|
- Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect);
|
|
|
|
-
|
|
|
|
- if (p_dest.x < 0) {
|
|
|
|
- clipped_src_rect.position.x = ABS(p_dest.x);
|
|
|
|
- }
|
|
|
|
- if (p_dest.y < 0) {
|
|
|
|
- clipped_src_rect.position.y = ABS(p_dest.y);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (clipped_src_rect.has_no_area()) {
|
|
|
|
|
|
+ Rect2i src_rect;
|
|
|
|
+ Rect2i dest_rect;
|
|
|
|
+ _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
|
|
|
|
+ if (src_rect.has_no_area() || dest_rect.has_no_area()) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
|
|
|
|
- Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
|
|
|
|
-
|
|
|
|
uint8_t *wp = data.ptrw();
|
|
uint8_t *wp = data.ptrw();
|
|
uint8_t *dst_data_ptr = wp;
|
|
uint8_t *dst_data_ptr = wp;
|
|
|
|
|
|
@@ -2477,8 +2501,8 @@ void Image::blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Po
|
|
|
|
|
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
|
- int src_x = clipped_src_rect.position.x + j;
|
|
|
|
- int src_y = clipped_src_rect.position.y + i;
|
|
|
|
|
|
+ int src_x = src_rect.position.x + j;
|
|
|
|
+ int src_y = src_rect.position.y + i;
|
|
|
|
|
|
int dst_x = dest_rect.position.x + j;
|
|
int dst_x = dest_rect.position.x + j;
|
|
int dst_y = dest_rect.position.y + i;
|
|
int dst_y = dest_rect.position.y + i;
|
|
@@ -2506,22 +2530,13 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
|
|
ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
|
|
ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
|
|
ERR_FAIL_COND(format != p_src->format);
|
|
ERR_FAIL_COND(format != p_src->format);
|
|
|
|
|
|
- Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect);
|
|
|
|
-
|
|
|
|
- if (p_dest.x < 0) {
|
|
|
|
- clipped_src_rect.position.x = ABS(p_dest.x);
|
|
|
|
- }
|
|
|
|
- if (p_dest.y < 0) {
|
|
|
|
- clipped_src_rect.position.y = ABS(p_dest.y);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (clipped_src_rect.has_no_area()) {
|
|
|
|
|
|
+ Rect2i src_rect;
|
|
|
|
+ Rect2i dest_rect;
|
|
|
|
+ _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
|
|
|
|
+ if (src_rect.has_no_area() || dest_rect.has_no_area()) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
|
|
|
|
- Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
|
|
|
|
-
|
|
|
|
uint8_t *wp = data.ptrw();
|
|
uint8_t *wp = data.ptrw();
|
|
uint8_t *dst_data_ptr = wp;
|
|
uint8_t *dst_data_ptr = wp;
|
|
|
|
|
|
@@ -2534,8 +2549,8 @@ void Image::blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, co
|
|
|
|
|
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
|
- int src_x = clipped_src_rect.position.x + j;
|
|
|
|
- int src_y = clipped_src_rect.position.y + i;
|
|
|
|
|
|
+ int src_x = src_rect.position.x + j;
|
|
|
|
+ int src_y = src_rect.position.y + i;
|
|
|
|
|
|
if (msk->get_pixel(src_x, src_y).a != 0) {
|
|
if (msk->get_pixel(src_x, src_y).a != 0) {
|
|
int dst_x = dest_rect.position.x + j;
|
|
int dst_x = dest_rect.position.x + j;
|
|
@@ -2560,28 +2575,19 @@ void Image::blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const P
|
|
ERR_FAIL_COND(srcdsize == 0);
|
|
ERR_FAIL_COND(srcdsize == 0);
|
|
ERR_FAIL_COND(format != p_src->format);
|
|
ERR_FAIL_COND(format != p_src->format);
|
|
|
|
|
|
- Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect);
|
|
|
|
-
|
|
|
|
- if (p_dest.x < 0) {
|
|
|
|
- clipped_src_rect.position.x = ABS(p_dest.x);
|
|
|
|
- }
|
|
|
|
- if (p_dest.y < 0) {
|
|
|
|
- clipped_src_rect.position.y = ABS(p_dest.y);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (clipped_src_rect.has_no_area()) {
|
|
|
|
|
|
+ Rect2i src_rect;
|
|
|
|
+ Rect2i dest_rect;
|
|
|
|
+ _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
|
|
|
|
+ if (src_rect.has_no_area() || dest_rect.has_no_area()) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
|
|
|
|
- Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
|
|
|
|
-
|
|
|
|
Ref<Image> img = p_src;
|
|
Ref<Image> img = p_src;
|
|
|
|
|
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
|
- int src_x = clipped_src_rect.position.x + j;
|
|
|
|
- int src_y = clipped_src_rect.position.y + i;
|
|
|
|
|
|
+ int src_x = src_rect.position.x + j;
|
|
|
|
+ int src_y = src_rect.position.y + i;
|
|
|
|
|
|
int dst_x = dest_rect.position.x + j;
|
|
int dst_x = dest_rect.position.x + j;
|
|
int dst_y = dest_rect.position.y + i;
|
|
int dst_y = dest_rect.position.y + i;
|
|
@@ -2609,29 +2615,20 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c
|
|
ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
|
|
ERR_FAIL_COND_MSG(p_src->height != p_mask->height, "Source image height is different from mask height.");
|
|
ERR_FAIL_COND(format != p_src->format);
|
|
ERR_FAIL_COND(format != p_src->format);
|
|
|
|
|
|
- Rect2i clipped_src_rect = Rect2i(0, 0, p_src->width, p_src->height).intersection(p_src_rect);
|
|
|
|
-
|
|
|
|
- if (p_dest.x < 0) {
|
|
|
|
- clipped_src_rect.position.x = ABS(p_dest.x);
|
|
|
|
- }
|
|
|
|
- if (p_dest.y < 0) {
|
|
|
|
- clipped_src_rect.position.y = ABS(p_dest.y);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (clipped_src_rect.has_no_area()) {
|
|
|
|
|
|
+ Rect2i src_rect;
|
|
|
|
+ Rect2i dest_rect;
|
|
|
|
+ _get_clipped_src_and_dest_rects(p_src, p_src_rect, p_dest, src_rect, dest_rect);
|
|
|
|
+ if (src_rect.has_no_area() || dest_rect.has_no_area()) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- Point2 src_underscan = Point2(MIN(0, p_src_rect.position.x), MIN(0, p_src_rect.position.y));
|
|
|
|
- Rect2i dest_rect = Rect2i(0, 0, width, height).intersection(Rect2i(p_dest - src_underscan, clipped_src_rect.size));
|
|
|
|
-
|
|
|
|
Ref<Image> img = p_src;
|
|
Ref<Image> img = p_src;
|
|
Ref<Image> msk = p_mask;
|
|
Ref<Image> msk = p_mask;
|
|
|
|
|
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
for (int i = 0; i < dest_rect.size.y; i++) {
|
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
|
for (int j = 0; j < dest_rect.size.x; j++) {
|
|
- int src_x = clipped_src_rect.position.x + j;
|
|
|
|
- int src_y = clipped_src_rect.position.y + i;
|
|
|
|
|
|
+ int src_x = src_rect.position.x + j;
|
|
|
|
+ int src_y = src_rect.position.y + i;
|
|
|
|
|
|
// If the mask's pixel is transparent then we skip it
|
|
// If the mask's pixel is transparent then we skip it
|
|
//Color c = msk->get_pixel(src_x, src_y);
|
|
//Color c = msk->get_pixel(src_x, src_y);
|