diff options
Diffstat (limited to 'core/io')
-rw-r--r-- | core/io/config_file.cpp | 4 | ||||
-rw-r--r-- | core/io/image.cpp | 72 | ||||
-rw-r--r-- | core/io/image.h | 9 | ||||
-rw-r--r-- | core/io/packed_data_container.cpp | 4 |
4 files changed, 62 insertions, 27 deletions
diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 49fa73dab2..33f992e153 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -183,7 +183,9 @@ Error ConfigFile::_internal_save(FileAccess *file) { if (E != values.front()) { file->store_string("\n"); } - file->store_string("[" + E.key() + "]\n\n"); + if (E.key() != "") { + file->store_string("[" + E.key() + "]\n\n"); + } for (OrderedHashMap<String, Variant>::Element F = E.get().front(); F; F = F.next()) { String vstr; diff --git a/core/io/image.cpp b/core/io/image.cpp index b82e6637b4..3f34de132f 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -86,20 +86,14 @@ SaveEXRFunc Image::save_exr_func = nullptr; SavePNGBufferFunc Image::save_png_buffer_func = nullptr; -void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel) { - uint32_t ofs = (p_y * width + p_x) * p_pixelsize; - - for (uint32_t i = 0; i < p_pixelsize; i++) { - p_data[ofs + i] = p_pixel[i]; - } +void Image::_put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel) { + uint32_t ofs = (p_y * width + p_x) * p_pixel_size; + memcpy(p_data + ofs, p_pixel, p_pixel_size); } -void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel) { - uint32_t ofs = (p_y * width + p_x) * p_pixelsize; - - for (uint32_t i = 0; i < p_pixelsize; i++) { - p_pixel[i] = p_data[ofs + i]; - } +void Image::_get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t *p_data, uint8_t *p_pixel) { + uint32_t ofs = (p_y * width + p_x) * p_pixel_size; + memcpy(p_pixel, p_data + ofs, p_pixel_size); } int Image::get_format_pixel_size(Format p_format) { @@ -2697,24 +2691,55 @@ void Image::blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, c } } -void Image::fill(const Color &c) { +// Repeats `p_pixel` `p_count` times in consecutive memory. +// Results in the original pixel and `p_count - 1` subsequent copies of it. +void Image::_repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_size, int p_count) { + int offset = 1; + for (int stride = 1; offset + stride <= p_count; stride *= 2) { + memcpy(p_pixel + offset * p_pixel_size, p_pixel, stride * p_pixel_size); + offset += stride; + } + if (offset < p_count) { + memcpy(p_pixel + offset * p_pixel_size, p_pixel, (p_count - offset) * p_pixel_size); + } +} + +void Image::fill(const Color &p_color) { ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill in compressed or custom image formats."); - uint8_t *wp = data.ptrw(); - uint8_t *dst_data_ptr = wp; + uint8_t *dst_data_ptr = data.ptrw(); int pixel_size = get_format_pixel_size(format); - // put first pixel with the format-aware API - set_pixel(0, 0, c); + // Put first pixel with the format-aware API. + _set_color_at_ofs(dst_data_ptr, 0, p_color); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - uint8_t *dst = &dst_data_ptr[(y * width + x) * pixel_size]; + _repeat_pixel_over_subsequent_memory(dst_data_ptr, pixel_size, width * height); +} - for (int k = 0; k < pixel_size; k++) { - dst[k] = dst_data_ptr[k]; - } +void Image::fill_rect(const Rect2 &p_rect, const Color &p_color) { + ERR_FAIL_COND_MSG(!_can_modify(format), "Cannot fill rect in compressed or custom image formats."); + + Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect.abs()); + if (r.has_no_area()) { + return; + } + + uint8_t *dst_data_ptr = data.ptrw(); + + int pixel_size = get_format_pixel_size(format); + + // Put first pixel with the format-aware API. + uint8_t *rect_first_pixel_ptr = &dst_data_ptr[(r.position.y * width + r.position.x) * pixel_size]; + _set_color_at_ofs(rect_first_pixel_ptr, 0, p_color); + + if (r.size.x == width) { + // No need to fill rows separately. + _repeat_pixel_over_subsequent_memory(rect_first_pixel_ptr, pixel_size, width * r.size.y); + } else { + _repeat_pixel_over_subsequent_memory(rect_first_pixel_ptr, pixel_size, r.size.x); + for (int y = 1; y < r.size.y; y++) { + memcpy(rect_first_pixel_ptr + y * width * pixel_size, rect_first_pixel_ptr, r.size.x * pixel_size); } } } @@ -3160,6 +3185,7 @@ void Image::_bind_methods() { ClassDB::bind_method(D_METHOD("blend_rect", "src", "src_rect", "dst"), &Image::blend_rect); ClassDB::bind_method(D_METHOD("blend_rect_mask", "src", "mask", "src_rect", "dst"), &Image::blend_rect_mask); ClassDB::bind_method(D_METHOD("fill", "color"), &Image::fill); + ClassDB::bind_method(D_METHOD("fill_rect", "rect", "color"), &Image::fill_rect); ClassDB::bind_method(D_METHOD("get_used_rect"), &Image::get_used_rect); ClassDB::bind_method(D_METHOD("get_rect", "rect"), &Image::get_rect); diff --git a/core/io/image.h b/core/io/image.h index d31a065aa7..9023463b08 100644 --- a/core/io/image.h +++ b/core/io/image.h @@ -190,8 +190,10 @@ private: static int _get_dst_image_size(int p_width, int p_height, Format p_format, int &r_mipmaps, int p_mipmaps = -1, int *r_mm_width = nullptr, int *r_mm_height = nullptr); bool _can_modify(Format p_format) const; - _FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixelsize, uint8_t *p_data, const uint8_t *p_pixel); - _FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixelsize, const uint8_t *p_data, uint8_t *p_pixel); + _FORCE_INLINE_ void _put_pixelb(int p_x, int p_y, uint32_t p_pixel_size, uint8_t *p_data, const uint8_t *p_pixel); + _FORCE_INLINE_ void _get_pixelb(int p_x, int p_y, uint32_t p_pixel_size, const uint8_t *p_data, uint8_t *p_pixel); + + _FORCE_INLINE_ void _repeat_pixel_over_subsequent_memory(uint8_t *p_pixel, int p_pixel_size, int p_count); void _set_data(const Dictionary &p_data); Dictionary _get_data() const; @@ -362,7 +364,8 @@ public: void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); void blend_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest); void blend_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest); - void fill(const Color &c); + void fill(const Color &p_color); + void fill_rect(const Rect2 &p_rect, const Color &p_color); Rect2 get_used_rect() const; Ref<Image> get_rect(const Rect2 &p_area) const; diff --git a/core/io/packed_data_container.cpp b/core/io/packed_data_container.cpp index 4a76f0191d..d34b5b6fe3 100644 --- a/core/io/packed_data_container.cpp +++ b/core/io/packed_data_container.cpp @@ -100,6 +100,7 @@ Variant PackedDataContainer::_iter_get_ofs(const Variant &p_iter, uint32_t p_off } Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, bool &err) const { + ERR_FAIL_COND_V(p_ofs + 4 > (uint32_t)data.size(), Variant()); uint32_t type = decode_uint32(p_buf + p_ofs); if (type == TYPE_ARRAY || type == TYPE_DICT) { @@ -122,6 +123,7 @@ Variant PackedDataContainer::_get_at_ofs(uint32_t p_ofs, const uint8_t *p_buf, b } uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const { + ERR_FAIL_COND_V(p_ofs + 4 > (uint32_t)data.size(), 0); const uint8_t *rd = data.ptr(); ERR_FAIL_COND_V(!rd, 0); const uint8_t *r = &rd[p_ofs]; @@ -131,6 +133,7 @@ uint32_t PackedDataContainer::_type_at_ofs(uint32_t p_ofs) const { } int PackedDataContainer::_size(uint32_t p_ofs) const { + ERR_FAIL_COND_V(p_ofs + 4 > (uint32_t)data.size(), 0); const uint8_t *rd = data.ptr(); ERR_FAIL_COND_V(!rd, 0); const uint8_t *r = &rd[p_ofs]; @@ -149,6 +152,7 @@ int PackedDataContainer::_size(uint32_t p_ofs) const { } Variant PackedDataContainer::_key_at_ofs(uint32_t p_ofs, const Variant &p_key, bool &err) const { + ERR_FAIL_COND_V(p_ofs + 4 > (uint32_t)data.size(), Variant()); const uint8_t *rd = data.ptr(); if (!rd) { err = true; |