diff options
Diffstat (limited to 'scene/resources/bit_map.cpp')
-rw-r--r-- | scene/resources/bit_map.cpp | 128 |
1 files changed, 53 insertions, 75 deletions
diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index 06323a8d31..de557494c3 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -33,30 +33,27 @@ #include "core/io/image_loader.h" void BitMap::create(const Size2 &p_size) { - ERR_FAIL_COND(p_size.width < 1); ERR_FAIL_COND(p_size.height < 1); width = p_size.width; height = p_size.height; - bitmask.resize(((width * height) / 8) + 1); - zeromem(bitmask.ptrw(), bitmask.size()); + bitmask.resize((((width * height) - 1) / 8) + 1); + memset(bitmask.ptrw(), 0, bitmask.size()); } void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshold) { - - ERR_FAIL_COND(p_image.is_null() || p_image->empty()); + ERR_FAIL_COND(p_image.is_null() || p_image->is_empty()); Ref<Image> img = p_image->duplicate(); img->convert(Image::FORMAT_LA8); ERR_FAIL_COND(img->get_format() != Image::FORMAT_LA8); create(Size2(img->get_width(), img->get_height())); - PoolVector<uint8_t>::Read r = img->get_data().read(); + const uint8_t *r = img->get_data().ptr(); uint8_t *w = bitmask.ptrw(); for (int i = 0; i < width * height; i++) { - int bbyte = i / 8; int bbit = i % 8; if (r[i * 2 + 1] / 255.0 > p_threshold) { @@ -66,24 +63,22 @@ void BitMap::create_from_image_alpha(const Ref<Image> &p_image, float p_threshol } void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) { - - Rect2i current = Rect2i(0, 0, width, height).clip(p_rect); + Rect2i current = Rect2i(0, 0, width, height).intersection(p_rect); uint8_t *data = bitmask.ptrw(); for (int i = current.position.x; i < current.position.x + current.size.x; i++) { - for (int j = current.position.y; j < current.position.y + current.size.y; j++) { - int ofs = width * j + i; int bbyte = ofs / 8; int bbit = ofs % 8; uint8_t b = data[bbyte]; - if (p_value) + if (p_value) { b |= (1 << bbit); - else + } else { b &= ~(1 << bbit); + } data[bbyte] = b; } @@ -91,7 +86,6 @@ void BitMap::set_bit_rect(const Rect2 &p_rect, bool p_value) { } int BitMap::get_true_bit_count() const { - int ds = bitmask.size(); const uint8_t *d = bitmask.ptr(); int c = 0; @@ -99,7 +93,6 @@ int BitMap::get_true_bit_count() const { //fast, almost branchless version for (int i = 0; i < ds; i++) { - c += (d[i] & (1 << 7)) >> 7; c += (d[i] & (1 << 6)) >> 6; c += (d[i] & (1 << 5)) >> 5; @@ -114,7 +107,6 @@ int BitMap::get_true_bit_count() const { } void BitMap::set_bit(const Point2 &p_pos, bool p_value) { - int x = p_pos.x; int y = p_pos.y; @@ -127,16 +119,16 @@ void BitMap::set_bit(const Point2 &p_pos, bool p_value) { uint8_t b = bitmask[bbyte]; - if (p_value) + if (p_value) { b |= (1 << bbit); - else + } else { b &= ~(1 << bbit); + } bitmask.write[bbyte] = b; } bool BitMap::get_bit(const Point2 &p_pos) const { - int x = Math::fast_ftoi(p_pos.x); int y = Math::fast_ftoi(p_pos.y); ERR_FAIL_INDEX_V(x, width, false); @@ -150,12 +142,10 @@ bool BitMap::get_bit(const Point2 &p_pos) const { } Size2 BitMap::get_size() const { - return Size2(width, height); } void BitMap::_set_data(const Dictionary &p_d) { - ERR_FAIL_COND(!p_d.has("size")); ERR_FAIL_COND(!p_d.has("data")); @@ -164,7 +154,6 @@ void BitMap::_set_data(const Dictionary &p_d) { } Dictionary BitMap::_get_data() const { - Dictionary d; d["size"] = get_size(); d["data"] = bitmask; @@ -172,7 +161,6 @@ Dictionary BitMap::_get_data() const { } Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) const { - int stepx = 0; int stepy = 0; int prevx = 0; @@ -209,7 +197,6 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) } switch (sv) { - case 1: case 5: case 13: @@ -298,7 +285,7 @@ Vector<Vector2> BitMap::_march_square(const Rect2i &rect, const Point2i &start) +---+---+ | 4 | | +---+---+ - this normally go RIGHT, but if its coming from RIGHT, it should go LEFT + this normally go RIGHT, but if it's coming from RIGHT, it should go LEFT */ if (case6s.has(Point2i(curx, cury))) { //found, so we go left, and delete from case6s; @@ -354,11 +341,12 @@ static float perpendicular_distance(const Vector2 &i, const Vector2 &start, cons } static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) { - if (v.size() < 3) + if (v.size() < 3) { return v; + } int index = -1; - float dist = 0; + float dist = 0.0; //not looping first and last point for (size_t i = 1, size = v.size(); i < size - 1; ++i) { float cdist = perpendicular_distance(v[i], v[0], v[v.size() - 1]); @@ -368,7 +356,6 @@ static Vector<Vector2> rdp(const Vector<Vector2> &v, float optimization) { } } if (dist > optimization) { - Vector<Vector2> left, right; left.resize(index); for (int i = 0; i < index; i++) { @@ -419,14 +406,13 @@ static Vector<Vector2> reduce(const Vector<Vector2> &points, const Rect2i &rect, struct FillBitsStackEntry { Point2i pos; - int i; - int j; + int i = 0; + int j = 0; }; static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_pos, const Rect2i &rect) { - // Using a custom stack to work iteratively to avoid stack overflow on big bitmaps - PoolVector<FillBitsStackEntry> stack; + Vector<FillBitsStackEntry> stack; // Tracking size since we won't be shrinking the stack vector int stack_size = 0; @@ -453,15 +439,17 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_ continue; } - if (i < rect.position.x || i >= rect.position.x + rect.size.x) + if (i < rect.position.x || i >= rect.position.x + rect.size.x) { continue; - if (j < rect.position.y || j >= rect.position.y + rect.size.y) + } + if (j < rect.position.y || j >= rect.position.y + rect.size.y) { continue; + } - if (p_map->get_bit(Vector2(i, j))) + if (p_map->get_bit(Vector2(i, j))) { continue; - else if (p_src->get_bit(Vector2(i, j))) { + } else if (p_src->get_bit(Vector2(i, j))) { p_map->set_bit(Vector2(i, j), true); FillBitsStackEntry se = { pos, i, j }; @@ -493,21 +481,19 @@ static void fill_bits(const BitMap *p_src, Ref<BitMap> &p_map, const Point2i &p_ print_verbose("BitMap: Max stack size: " + itos(stack.size())); } -Vector<Vector<Vector2> > BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const { - - Rect2i r = Rect2i(0, 0, width, height).clip(p_rect); +Vector<Vector<Vector2>> BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, float p_epsilon) const { + Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect); print_verbose("BitMap: Rect: " + r); Point2i from; Ref<BitMap> fill; - fill.instance(); + fill.instantiate(); fill->create(get_size()); - Vector<Vector<Vector2> > polygons; + Vector<Vector<Vector2>> polygons; for (int i = r.position.y; i < r.position.y + r.size.height; i++) { for (int j = r.position.x; j < r.position.x + r.size.width; j++) { if (!fill->get_bit(Point2(j, i)) && get_bit(Point2(j, i))) { - fill_bits(this, fill, Point2i(j, i), r); Vector<Vector2> polygon = _march_square(r, Point2i(j, i)); @@ -529,7 +515,6 @@ Vector<Vector<Vector2> > BitMap::clip_opaque_to_polygons(const Rect2 &p_rect, fl } void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) { - if (p_pixels == 0) { return; } @@ -537,44 +522,47 @@ void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) { bool bit_value = p_pixels > 0; p_pixels = Math::abs(p_pixels); - Rect2i r = Rect2i(0, 0, width, height).clip(p_rect); + Rect2i r = Rect2i(0, 0, width, height).intersection(p_rect); Ref<BitMap> copy; - copy.instance(); + copy.instantiate(); copy->create(get_size()); copy->bitmask = bitmask; for (int i = r.position.y; i < r.position.y + r.size.height; i++) { for (int j = r.position.x; j < r.position.x + r.size.width; j++) { - if (bit_value == get_bit(Point2(j, i))) + if (bit_value == get_bit(Point2(j, i))) { continue; + } bool found = false; for (int y = i - p_pixels; y <= i + p_pixels; y++) { for (int x = j - p_pixels; x <= j + p_pixels; x++) { - bool outside = false; if ((x < p_rect.position.x) || (x >= p_rect.position.x + p_rect.size.x) || (y < p_rect.position.y) || (y >= p_rect.position.y + p_rect.size.y)) { // outside of rectangle counts as bit not set - if (!bit_value) + if (!bit_value) { outside = true; - else + } else { continue; + } } float d = Point2(j, i).distance_to(Point2(x, y)) - CMP_EPSILON; - if (d > p_pixels) + if (d > p_pixels) { continue; + } if (outside || (bit_value == copy->get_bit(Point2(x, y)))) { found = true; break; } } - if (found) + if (found) { break; + } } if (found) { @@ -585,27 +573,24 @@ void BitMap::grow_mask(int p_pixels, const Rect2 &p_rect) { } void BitMap::shrink_mask(int p_pixels, const Rect2 &p_rect) { - grow_mask(-p_pixels, p_rect); } Array BitMap::_opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) const { - - Vector<Vector<Vector2> > result = clip_opaque_to_polygons(p_rect, p_epsilon); + Vector<Vector<Vector2>> result = clip_opaque_to_polygons(p_rect, p_epsilon); // Convert result to bindable types Array result_array; result_array.resize(result.size()); for (int i = 0; i < result.size(); i++) { - const Vector<Vector2> &polygon = result[i]; - PoolVector2Array polygon_array; + PackedVector2Array polygon_array; polygon_array.resize(polygon.size()); { - PoolVector2Array::Write w = polygon_array.write(); + Vector2 *w = polygon_array.ptrw(); for (int j = 0; j < polygon.size(); j++) { w[j] = polygon[j]; } @@ -618,9 +603,8 @@ Array BitMap::_opaque_to_polygons_bind(const Rect2 &p_rect, float p_epsilon) con } void BitMap::resize(const Size2 &p_new_size) { - Ref<BitMap> new_bitmap; - new_bitmap.instance(); + new_bitmap.instantiate(); new_bitmap->create(p_new_size); int lw = MIN(width, p_new_size.width); int lh = MIN(height, p_new_size.height); @@ -636,23 +620,20 @@ void BitMap::resize(const Size2 &p_new_size) { } Ref<Image> BitMap::convert_to_image() const { - Ref<Image> image; - image.instance(); + image.instantiate(); image->create(width, height, false, Image::FORMAT_L8); - image->lock(); + for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { image->set_pixel(i, j, get_bit(Point2(i, j)) ? Color(1, 1, 1) : Color(0, 0, 0)); } } - image->unlock(); - return image; } -void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) { +void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) { int x = p_pos.x; int y = p_pos.y; int w = p_bitmap->get_size().width; @@ -662,10 +643,12 @@ void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) { for (int j = 0; j < h; j++) { int px = x + i; int py = y + j; - if (px < 0 || px >= width) + if (px < 0 || px >= width) { continue; - if (py < 0 || py >= height) + } + if (py < 0 || py >= height) { continue; + } if (p_bitmap->get_bit(Vector2(i, j))) { set_bit(Vector2(x, y), true); } @@ -674,7 +657,6 @@ void BitMap::blit(const Vector2 &p_pos, const Ref<BitMap> &p_bitmap) { } void BitMap::_bind_methods() { - ClassDB::bind_method(D_METHOD("create", "size"), &BitMap::create); ClassDB::bind_method(D_METHOD("create_from_image_alpha", "image", "threshold"), &BitMap::create_from_image_alpha, DEFVAL(0.1)); @@ -695,10 +677,6 @@ void BitMap::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); } -BitMap::BitMap() { - - width = 0; - height = 0; -} +BitMap::BitMap() {} ////////////////////////////////////// |