| 36 | } |
| 37 | |
| 38 | List<Vec2I> ImageMetadataDatabase::imageSpaces(AssetPath const& path, Vec2F position, float fillLimit, bool flip) const { |
| 39 | SpacesEntry key = make_tuple(path, Vec2I::round(position), fillLimit, flip); |
| 40 | |
| 41 | MutexLocker locker(m_mutex); |
| 42 | if (auto cached = m_spacesCache.ptr(key)) { |
| 43 | return *cached; |
| 44 | } |
| 45 | |
| 46 | auto filteredPath = filterProcessing(path); |
| 47 | SpacesEntry filteredKey = make_tuple(filteredPath, Vec2I::round(position), fillLimit, flip); |
| 48 | |
| 49 | if (auto cached = m_spacesCache.ptr(filteredKey)) { |
| 50 | m_spacesCache.set(key, *cached); |
| 51 | return *cached; |
| 52 | } |
| 53 | |
| 54 | locker.unlock(); |
| 55 | |
| 56 | auto image = Root::singleton().assets()->image(filteredPath); |
| 57 | int imageWidth = image->width(); |
| 58 | int imageHeight = image->height(); |
| 59 | |
| 60 | Vec2I min((position / TilePixels).floor()); |
| 61 | Vec2I max(((Vec2F(imageWidth, imageHeight) + position) / TilePixels).ceil()); |
| 62 | |
| 63 | List<Vec2I> spaces; |
| 64 | |
| 65 | for (int yspace = min[1]; yspace < max[1]; ++yspace) { |
| 66 | for (int xspace = min[0]; xspace < max[0]; ++xspace) { |
| 67 | float fillRatio = 0.0f; |
| 68 | |
| 69 | for (int y = 0; y < (int)TilePixels; ++y) { |
| 70 | int ypixel = round(yspace * (int)TilePixels + y - position[1]); |
| 71 | if (ypixel < 0 || ypixel >= imageHeight) |
| 72 | continue; |
| 73 | |
| 74 | for (int x = 0; x < (int)TilePixels; ++x) { |
| 75 | int xpixel = round(xspace * (int)TilePixels + x - position[0]); |
| 76 | if (flip) |
| 77 | xpixel = imageWidth - 1 - xpixel; |
| 78 | |
| 79 | if (xpixel < 0 || xpixel >= imageWidth) |
| 80 | continue; |
| 81 | |
| 82 | if (image->get(xpixel, ypixel)[3] > 0) |
| 83 | fillRatio += 1.0f / square(TilePixels); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | if (fillRatio >= fillLimit) |
| 88 | spaces.append(Vec2I(xspace, yspace)); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | locker.lock(); |
| 93 | m_spacesCache.set(key, spaces); |
| 94 | m_spacesCache.set(filteredKey, spaces); |
| 95 |
no test coverage detected