summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mbgl/sprite/sprite_image.hpp20
-rw-r--r--platform/android/src/jni.cpp17
-rw-r--r--platform/default/glfw_view.cpp6
-rw-r--r--platform/ios/src/MGLMapView.mm11
-rw-r--r--platform/osx/src/MGLMapView.mm9
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp2
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp4
-rw-r--r--src/mbgl/sprite/sprite_atlas.cpp34
-rw-r--r--src/mbgl/sprite/sprite_atlas.hpp6
-rw-r--r--src/mbgl/sprite/sprite_image.cpp18
-rw-r--r--src/mbgl/sprite/sprite_parser.cpp6
-rw-r--r--src/mbgl/sprite/sprite_store.cpp2
-rw-r--r--src/mbgl/text/shaping.cpp8
-rw-r--r--test/api/annotations.cpp2
-rw-r--r--test/fixtures/util.cpp5
-rw-r--r--test/fixtures/util.hpp1
-rw-r--r--test/sprite/sprite_atlas.cpp38
-rw-r--r--test/sprite/sprite_image.cpp47
-rw-r--r--test/sprite/sprite_parser.cpp70
-rw-r--r--test/sprite/sprite_store.cpp22
20 files changed, 160 insertions, 168 deletions
diff --git a/include/mbgl/sprite/sprite_image.hpp b/include/mbgl/sprite/sprite_image.hpp
index c5b063ff7f..4c375e58b9 100644
--- a/include/mbgl/sprite/sprite_image.hpp
+++ b/include/mbgl/sprite/sprite_image.hpp
@@ -3,6 +3,7 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/geo.hpp>
+#include <mbgl/util/image.hpp>
#include <string>
#include <memory>
@@ -12,27 +13,18 @@ namespace mbgl {
class SpriteImage : private util::noncopyable {
public:
- SpriteImage(
- uint16_t width, uint16_t height, float pixelRatio, std::string&& data, bool sdf = false);
+ SpriteImage(PremultipliedImage&&, float pixelRatio, bool sdf = false);
- // Logical dimensions of the sprite image.
- const uint16_t width;
- const uint16_t height;
+ PremultipliedImage image;
// Pixel ratio of the sprite image.
const float pixelRatio;
- // Physical dimensions of the sprite image.
- const uint16_t pixelWidth;
- const uint16_t pixelHeight;
-
- // A string of an RGBA8 representation of the sprite. It must have exactly
- // (width * ratio) * (height * ratio) * 4 (RGBA) bytes. The scan lines may
- // not have gaps between them (i.e. stride == 0).
- const std::string data;
-
// Whether this image should be interpreted as a signed distance field icon.
const bool sdf;
+
+ float getWidth() const { return image.width / pixelRatio; }
+ float getHeight() const { return image.height / pixelRatio; }
};
} // namespace mbgl
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 8157820d70..23be6a38f8 100644
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -24,6 +24,7 @@
#include <mbgl/platform/event.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/storage/network_status.hpp>
+#include <mbgl/util/exception.hpp>
#pragma clang diagnostic ignored "-Wunused-parameter"
@@ -1225,16 +1226,18 @@ void JNICALL nativeAddAnnotationIcon(JNIEnv *env, jobject obj, jlong nativeMapVi
const std::string symbolName = std_string_from_jstring(env, symbol);
- jbyte* pixelData = env->GetByteArrayElements(jpixels, nullptr);
jsize size = env->GetArrayLength(jpixels);
- std::string pixels(reinterpret_cast<char*>(pixelData), size);
- env->ReleaseByteArrayElements(jpixels, pixelData, JNI_ABORT);
+ mbgl::PremultipliedImage premultipliedImage(width, height);
+
+ if (premultipliedImage.size() != uint32_t(size)) {
+ throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
+ }
+
+ env->GetByteArrayRegion(jpixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
auto iconImage = std::make_shared<mbgl::SpriteImage>(
- uint16_t(width),
- uint16_t(height),
- float(scale),
- std::move(pixels));
+ std::move(premultipliedImage),
+ float(scale));
nativeMapView->getMap().addAnnotationIcon(symbolName, iconImage);
}
diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp
index bdd48d9d96..3103f09831 100644
--- a/platform/default/glfw_view.cpp
+++ b/platform/default/glfw_view.cpp
@@ -200,8 +200,8 @@ GLFWView::makeSpriteImage(int width, int height, float pixelRatio) {
const int w = std::ceil(pixelRatio * width);
const int h = std::ceil(pixelRatio * height);
- std::string pixels(w * h * 4, '\x00');
- auto data = reinterpret_cast<uint32_t*>(const_cast<char*>(pixels.data()));
+ mbgl::PremultipliedImage image(w, h);
+ auto data = reinterpret_cast<uint32_t*>(image.data.get());
const int dist = (w / 2) * (w / 2);
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
@@ -217,7 +217,7 @@ GLFWView::makeSpriteImage(int width, int height, float pixelRatio) {
}
}
- return std::make_shared<mbgl::SpriteImage>(width, height, pixelRatio, std::move(pixels));
+ return std::make_shared<mbgl::SpriteImage>(std::move(image), pixelRatio);
}
void GLFWView::nextOrientation() {
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 3e63cd4b76..bc1419ef63 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -2334,22 +2334,19 @@ std::chrono::steady_clock::duration MGLDurationInSeconds(float duration)
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
- std::string pixels(width * height * 4, '\0');
+ mbgl::PremultipliedImage cPremultipliedImage(width, height);
size_t bytesPerPixel = 4;
size_t bytesPerRow = bytesPerPixel * width;
size_t bitsPerComponent = 8;
- char *pixelData = const_cast<char *>(pixels.data());
- CGContextRef context = CGBitmapContextCreate(pixelData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
+ CGContextRef context = CGBitmapContextCreate(cPremultipliedImage.data.get(), width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), image);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
// add sprite
auto cSpriteImage = std::make_shared<mbgl::SpriteImage>(
- uint16_t(width),
- uint16_t(height),
- float(annotationImage.image.scale),
- std::move(pixels));
+ std::move(cPremultipliedImage),
+ float(annotationImage.image.scale));
// sprite upload
NSString *symbolName = [MGLAnnotationSpritePrefix stringByAppendingString:annotationImage.reuseIdentifier];
diff --git a/platform/osx/src/MGLMapView.mm b/platform/osx/src/MGLMapView.mm
index 596b909fa2..9c32e7204d 100644
--- a/platform/osx/src/MGLMapView.mm
+++ b/platform/osx/src/MGLMapView.mm
@@ -1590,10 +1590,11 @@ public:
// Get the image’s raw pixel data as an RGBA buffer.
std::string pixelString((const char *)rep.bitmapData, rep.pixelsWide * rep.pixelsHigh * 4 /* RGBA */);
- auto cSpriteImage = std::make_shared<mbgl::SpriteImage>((uint16_t)rep.pixelsWide,
- (uint16_t)rep.pixelsHigh,
- (float)(rep.pixelsWide / size.width),
- std::move(pixelString));
+
+ mbgl::PremultipliedImage cPremultipliedImage(rep.pixelsWide, rep.pixelsHigh);
+ std::copy(rep.bitmapData, rep.bitmapData + cPremultipliedImage.size(), cPremultipliedImage.data.get());
+ auto cSpriteImage = std::make_shared<mbgl::SpriteImage>(std::move(cPremultipliedImage),
+ (float)(rep.pixelsWide / size.width));
NSString *symbolName = [MGLAnnotationSpritePrefix stringByAppendingString:annotationImage.reuseIdentifier];
_mbglMap->addAnnotationIcon(symbolName.UTF8String, cSpriteImage);
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp
index 4e395e0638..b4d9fe4b66 100644
--- a/src/mbgl/annotation/annotation_manager.cpp
+++ b/src/mbgl/annotation/annotation_manager.cpp
@@ -165,7 +165,7 @@ void AnnotationManager::removeIcon(const std::string& name) {
double AnnotationManager::getTopOffsetPixelsForIcon(const std::string& name) {
auto sprite = spriteStore.getSprite(name);
- return sprite ? -sprite->height / 2 : 0;
+ return sprite ? -(sprite->image.height / sprite->pixelRatio) / 2 : 0;
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index a34cbcd028..45e718fd94 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -248,8 +248,8 @@ void SymbolBucket::addFeatures(uintptr_t tileUID,
auto image = spriteAtlas.getImage(feature.sprite, false);
if (image) {
shapedIcon = shapeIcon(*image, layout);
- assert((*image).texture);
- if ((*image).texture->sdf) {
+ assert((*image).spriteImage);
+ if ((*image).spriteImage->sdf) {
sdfIcons = true;
}
if ((*image).relativePixelRatio != 1.0f) {
diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp
index 53f97e4546..be5c59c74c 100644
--- a/src/mbgl/sprite/sprite_atlas.cpp
+++ b/src/mbgl/sprite/sprite_atlas.cpp
@@ -26,10 +26,10 @@ SpriteAtlas::SpriteAtlas(dimension width_, dimension height_, float pixelRatio_,
dirty(true) {
}
-Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(float src_width, float src_height) {
+Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(const SpriteImage& spriteImage) {
- const uint16_t pixel_width = std::ceil(src_width / pixelRatio);
- const uint16_t pixel_height = std::ceil(src_height / pixelRatio);
+ const uint16_t pixel_width = std::ceil(spriteImage.image.width / pixelRatio);
+ const uint16_t pixel_height = std::ceil(spriteImage.image.height / pixelRatio);
// Increase to next number divisible by 4, but at least 1.
// This is so we can scale down the texture coordinates and pack them
@@ -52,7 +52,7 @@ optional<SpriteAtlasElement> SpriteAtlas::getImage(const std::string& name, cons
auto rect_it = images.find({ name, wrap });
if (rect_it != images.end()) {
- return SpriteAtlasElement { rect_it->second.pos, rect_it->second.texture, rect_it->second.texture->pixelRatio / pixelRatio };
+ return SpriteAtlasElement { rect_it->second.pos, rect_it->second.spriteImage, rect_it->second.spriteImage->pixelRatio / pixelRatio };
}
auto sprite = store.getSprite(name);
@@ -60,7 +60,7 @@ optional<SpriteAtlasElement> SpriteAtlas::getImage(const std::string& name, cons
return {};
}
- Rect<dimension> rect = allocateImage(sprite->width * sprite->pixelRatio, sprite->height * sprite->pixelRatio);
+ Rect<dimension> rect = allocateImage(*sprite);
if (rect.w == 0) {
if (debug::spriteWarnings) {
Log::Warning(Event::Sprite, "sprite atlas bitmap overflow");
@@ -85,13 +85,13 @@ optional<SpriteAtlasPosition> SpriteAtlas::getPosition(const std::string& name,
auto rect = (*img).pos;
const float padding = 1;
- auto image = (*img).texture;
+ auto spriteImage = (*img).spriteImage;
- const float w = image->width * (*img).relativePixelRatio;
- const float h = image->height * (*img).relativePixelRatio;
+ const float w = spriteImage->getWidth() * (*img).relativePixelRatio;
+ const float h = spriteImage->getHeight() * (*img).relativePixelRatio;
return SpriteAtlasPosition {
- {{ float(image->width), float(image->height) }},
+ {{ float(spriteImage->getWidth()), spriteImage->getHeight() }},
{{ float(rect.x + padding) / width, float(rect.y + padding) / height }},
{{ float(rect.x + padding + w) / width, float(rect.y + padding + h) / height }}
};
@@ -131,15 +131,15 @@ void SpriteAtlas::copy(const Holder& holder, const bool wrap) {
std::fill(data.get(), data.get() + pixelWidth * pixelHeight, 0);
}
- const uint32_t *srcData = reinterpret_cast<const uint32_t *>(holder.texture->data.data());
+ const uint32_t *srcData = reinterpret_cast<const uint32_t *>(holder.spriteImage->image.data.get());
if (!srcData) return;
uint32_t *const dstData = data.get();
const int padding = 1;
- copyBitmap(srcData, holder.texture->pixelWidth, 0, 0,
+ copyBitmap(srcData, uint32_t(holder.spriteImage->image.width), 0, 0,
dstData, pixelWidth, (holder.pos.x + padding) * pixelRatio, (holder.pos.y + padding) * pixelRatio, pixelWidth * pixelHeight,
- holder.texture->pixelWidth, holder.texture->pixelHeight, wrap);
+ uint32_t(holder.spriteImage->image.width), uint32_t(holder.spriteImage->image.height), wrap);
dirty = true;
}
@@ -168,8 +168,8 @@ void SpriteAtlas::updateDirty() {
} else {
// The two names match;
Holder& holder = imageIterator->second;
- holder.texture = spriteIterator->second;
- if (holder.texture != nullptr) {
+ holder.spriteImage = spriteIterator->second;
+ if (holder.spriteImage != nullptr) {
copy(holder, imageIterator->first.second);
++imageIterator;
} else {
@@ -255,10 +255,10 @@ SpriteAtlas::~SpriteAtlas() {
}
}
-SpriteAtlas::Holder::Holder(const std::shared_ptr<const SpriteImage>& texture_,
+SpriteAtlas::Holder::Holder(const std::shared_ptr<const SpriteImage>& spriteImage_,
const Rect<dimension>& pos_)
- : texture(texture_), pos(pos_) {
+ : spriteImage(spriteImage_), pos(pos_) {
}
-SpriteAtlas::Holder::Holder(Holder&& h) : texture(std::move(h.texture)), pos(h.pos) {
+SpriteAtlas::Holder::Holder(Holder&& h) : spriteImage(std::move(h.spriteImage)), pos(h.pos) {
}
diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp
index f577004704..73b3037ec6 100644
--- a/src/mbgl/sprite/sprite_atlas.hpp
+++ b/src/mbgl/sprite/sprite_atlas.hpp
@@ -32,7 +32,7 @@ struct SpriteAtlasPosition {
struct SpriteAtlasElement {
Rect<uint16_t> pos;
- std::shared_ptr<const SpriteImage> texture;
+ std::shared_ptr<const SpriteImage> spriteImage;
float relativePixelRatio;
};
@@ -77,13 +77,13 @@ private:
struct Holder : private util::noncopyable {
inline Holder(const std::shared_ptr<const SpriteImage>&, const Rect<dimension>&);
inline Holder(Holder&&);
- std::shared_ptr<const SpriteImage> texture;
+ std::shared_ptr<const SpriteImage> spriteImage;
const Rect<dimension> pos;
};
using Key = std::pair<std::string, bool>;
- Rect<SpriteAtlas::dimension> allocateImage(float width, float height);
+ Rect<SpriteAtlas::dimension> allocateImage(const SpriteImage&);
void copy(const Holder& holder, const bool wrap);
std::recursive_mutex mtx;
diff --git a/src/mbgl/sprite/sprite_image.cpp b/src/mbgl/sprite/sprite_image.cpp
index e55d676b34..d7e422ed1d 100644
--- a/src/mbgl/sprite/sprite_image.cpp
+++ b/src/mbgl/sprite/sprite_image.cpp
@@ -6,23 +6,17 @@
namespace mbgl {
-SpriteImage::SpriteImage(const uint16_t pixelWidth_,
- const uint16_t pixelHeight_,
+SpriteImage::SpriteImage(PremultipliedImage&& image_,
const float pixelRatio_,
- std::string&& data_,
bool sdf_)
- : width(std::ceil(pixelWidth_ / pixelRatio_)),
- height(std::ceil(pixelHeight_ / pixelRatio_)),
+ : image(std::move(image_)),
pixelRatio(pixelRatio_),
- pixelWidth(pixelWidth_),
- pixelHeight(pixelHeight_),
- data(std::move(data_)),
sdf(sdf_) {
- const size_t size = pixelWidth * pixelHeight * 4;
- if (size == 0) {
+
+ if (image.size() == 0) {
throw util::SpriteImageException("Sprite image dimensions may not be zero");
- } else if (size != data.size()) {
- throw util::SpriteImageException("Sprite image pixel count mismatch");
+ } else if (pixelRatio <= 0) {
+ throw util::SpriteImageException("Sprite pixelRatio may not be <= 0");
}
}
diff --git a/src/mbgl/sprite/sprite_parser.cpp b/src/mbgl/sprite/sprite_parser.cpp
index 6942d009f3..9baf933177 100644
--- a/src/mbgl/sprite/sprite_parser.cpp
+++ b/src/mbgl/sprite/sprite_parser.cpp
@@ -26,10 +26,10 @@ SpriteImagePtr createSpriteImage(const PremultipliedImage& image,
return nullptr;
}
- std::string data(width * height * 4, '\0');
+ PremultipliedImage dstImage(width, height);
auto srcData = reinterpret_cast<const uint32_t*>(image.data.get());
- auto dstData = reinterpret_cast<uint32_t*>(const_cast<char*>(data.data()));
+ auto dstData = reinterpret_cast<uint32_t*>(dstImage.data.get());
const int32_t maxX = std::min(uint32_t(image.width), uint32_t(width + srcX)) - srcX;
assert(maxX <= int32_t(image.width));
@@ -45,7 +45,7 @@ SpriteImagePtr createSpriteImage(const PremultipliedImage& image,
}
}
- return std::make_unique<const SpriteImage>(width, height, ratio, std::move(data), sdf);
+ return std::make_unique<const SpriteImage>(std::move(dstImage), ratio, sdf);
}
namespace {
diff --git a/src/mbgl/sprite/sprite_store.cpp b/src/mbgl/sprite/sprite_store.cpp
index a8d6c2fcd3..e051b969a1 100644
--- a/src/mbgl/sprite/sprite_store.cpp
+++ b/src/mbgl/sprite/sprite_store.cpp
@@ -113,7 +113,7 @@ void SpriteStore::_setSprite(const std::string& name,
auto it = sprites.find(name);
if (it != sprites.end()) {
// There is already a sprite with that name in our store.
- if ((it->second->width != sprite->width || it->second->height != sprite->height)) {
+ if ((it->second->image.width != sprite->image.width || it->second->image.height != sprite->image.height)) {
Log::Warning(Event::Sprite, "Can't change sprite dimensions for '%s'", name.c_str());
return;
}
diff --git a/src/mbgl/text/shaping.cpp b/src/mbgl/text/shaping.cpp
index f12658c669..342a27a66f 100644
--- a/src/mbgl/text/shaping.cpp
+++ b/src/mbgl/text/shaping.cpp
@@ -6,10 +6,10 @@ namespace mbgl {
PositionedIcon shapeIcon(const SpriteAtlasElement& image, const SymbolLayoutProperties& layout) {
float dx = layout.icon.offset.value[0];
float dy = layout.icon.offset.value[1];
- float x1 = dx - image.texture->width / 2.0f;
- float x2 = x1 + image.texture->width;
- float y1 = dy - image.texture->height / 2.0f;
- float y2 = y1 + image.texture->height;
+ float x1 = dx - image.spriteImage->getWidth() / 2.0f;
+ float x2 = x1 + image.spriteImage->getWidth();
+ float y1 = dy - image.spriteImage->getHeight() / 2.0f;
+ float y2 = y1 + image.spriteImage->getHeight();
return PositionedIcon(image, y1, y2, x1, x2);
}
diff --git a/test/api/annotations.cpp b/test/api/annotations.cpp
index d80cff9e8e..f427331eef 100644
--- a/test/api/annotations.cpp
+++ b/test/api/annotations.cpp
@@ -16,7 +16,7 @@ using namespace mbgl;
std::shared_ptr<SpriteImage> namedMarker(const std::string &name) {
PremultipliedImage image = decodeImage(util::read_file("test/fixtures/sprites/" + name));
- return std::make_shared<SpriteImage>(image.width, image.height, 1.0, std::string(reinterpret_cast<char*>(image.data.get()), image.size()));
+ return std::make_shared<SpriteImage>(std::move(image), 1.0);
}
namespace {
diff --git a/test/fixtures/util.cpp b/test/fixtures/util.cpp
index 926e267631..c2a5d83637 100644
--- a/test/fixtures/util.cpp
+++ b/test/fixtures/util.cpp
@@ -89,6 +89,7 @@ Server::~Server() {
}
}
+
// from https://gist.github.com/ArtemGr/997887
uint64_t crc64(const char* data, size_t size) {
boost::crc_optimal<64, 0x04C11DB7, 0, 0, false, false> crc;
@@ -100,6 +101,10 @@ uint64_t crc64(const std::string& str) {
return crc64(str.data(), str.size());
}
+uint64_t crc64(const PremultipliedImage &image) {
+ return crc64(reinterpret_cast<const char*>(image.data.get()), image.size());
+}
+
PremultipliedImage render(Map& map, std::chrono::milliseconds timeout) {
std::promise<PremultipliedImage> promise;
map.renderStill([&](std::exception_ptr, PremultipliedImage&& image) {
diff --git a/test/fixtures/util.hpp b/test/fixtures/util.hpp
index d7c9c63a89..7a240cb41f 100644
--- a/test/fixtures/util.hpp
+++ b/test/fixtures/util.hpp
@@ -33,6 +33,7 @@ private:
uint64_t crc64(const char*, size_t);
uint64_t crc64(const std::string&);
+uint64_t crc64(const PremultipliedImage&);
PremultipliedImage render(Map&,
std::chrono::milliseconds timeout = std::chrono::milliseconds(1000));
diff --git a/test/sprite/sprite_atlas.cpp b/test/sprite/sprite_atlas.cpp
index 8e3c4317c0..d9a8c5c720 100644
--- a/test/sprite/sprite_atlas.cpp
+++ b/test/sprite/sprite_atlas.cpp
@@ -34,11 +34,11 @@ TEST(Sprite, SpriteAtlas) {
EXPECT_EQ(0, metro.pos.y);
EXPECT_EQ(20, metro.pos.w);
EXPECT_EQ(20, metro.pos.h);
- EXPECT_EQ(18, metro.texture->width);
- EXPECT_EQ(18, metro.texture->height);
- EXPECT_EQ(18, metro.texture->pixelWidth);
- EXPECT_EQ(18, metro.texture->pixelHeight);
- EXPECT_EQ(1.0f, metro.texture->pixelRatio);
+ EXPECT_EQ(18, metro.spriteImage->getWidth());
+ EXPECT_EQ(18, metro.spriteImage->getHeight());
+ EXPECT_EQ(18, metro.spriteImage->image.width);
+ EXPECT_EQ(18, metro.spriteImage->image.height);
+ EXPECT_EQ(1.0f, metro.spriteImage->pixelRatio);
EXPECT_TRUE(atlas.getData());
@@ -96,11 +96,11 @@ TEST(Sprite, SpriteAtlasSize) {
EXPECT_EQ(0, metro.pos.y);
EXPECT_EQ(16, metro.pos.w);
EXPECT_EQ(16, metro.pos.h);
- EXPECT_EQ(18, metro.texture->width);
- EXPECT_EQ(18, metro.texture->height);
- EXPECT_EQ(18, metro.texture->pixelWidth);
- EXPECT_EQ(18, metro.texture->pixelHeight);
- EXPECT_EQ(1.0f, metro.texture->pixelRatio);
+ EXPECT_EQ(18, metro.spriteImage->getWidth());
+ EXPECT_EQ(18, metro.spriteImage->getHeight());
+ EXPECT_EQ(18, metro.spriteImage->image.width);
+ EXPECT_EQ(18, metro.spriteImage->image.height);
+ EXPECT_EQ(1.0f, metro.spriteImage->pixelRatio);
const size_t bytes = atlas.getTextureWidth() * atlas.getTextureHeight() * 4;
const auto hash = test::crc64(reinterpret_cast<const char*>(atlas.getData()), bytes);
@@ -122,24 +122,28 @@ TEST(Sprite, SpriteAtlasUpdates) {
EXPECT_EQ(32, atlas.getTextureWidth());
EXPECT_EQ(32, atlas.getTextureHeight());
- store.setSprite("one", std::make_shared<SpriteImage>(16, 12, 1, std::string(16 * 12 * 4, '\x00')));
+ store.setSprite("one", std::make_shared<SpriteImage>(PremultipliedImage(16, 12), 1));
auto one = *atlas.getImage("one", false);
EXPECT_EQ(0, one.pos.x);
EXPECT_EQ(0, one.pos.y);
EXPECT_EQ(20, one.pos.w);
EXPECT_EQ(16, one.pos.h);
- EXPECT_EQ(16, one.texture->width);
- EXPECT_EQ(12, one.texture->height);
- EXPECT_EQ(16, one.texture->pixelWidth);
- EXPECT_EQ(12, one.texture->pixelHeight);
- EXPECT_EQ(1.0f, one.texture->pixelRatio);
+ EXPECT_EQ(16, one.spriteImage->getWidth());
+ EXPECT_EQ(12, one.spriteImage->getHeight());
+ EXPECT_EQ(16, one.spriteImage->image.width);
+ EXPECT_EQ(12, one.spriteImage->image.height);
+ EXPECT_EQ(1.0f, one.spriteImage->pixelRatio);
const size_t bytes = atlas.getTextureWidth() * atlas.getTextureHeight() * 4;
const auto hash = test::crc64(reinterpret_cast<const char*>(atlas.getData()), bytes);
EXPECT_EQ(0x0000000000000000u, hash) << std::hex << hash;
// Update sprite
- auto newSprite = std::make_shared<SpriteImage>(16, 12, 1, std::string(16 * 12 * 4, '\xFF'));
+ PremultipliedImage image2(16, 12);
+ for (size_t i = 0; i < image2.size(); i++) {
+ image2.data.get()[i] = 255;
+ }
+ auto newSprite = std::make_shared<SpriteImage>(std::move(image2), 1);
store.setSprite("one", newSprite);
ASSERT_EQ(newSprite, store.getSprite("one"));
diff --git a/test/sprite/sprite_image.cpp b/test/sprite/sprite_image.cpp
index 1ed4e56ff6..c2e889134f 100644
--- a/test/sprite/sprite_image.cpp
+++ b/test/sprite/sprite_image.cpp
@@ -1,13 +1,15 @@
#include "../fixtures/util.hpp"
#include <mbgl/sprite/sprite_image.hpp>
+#include <mbgl/util/image.hpp>
#include <mbgl/util/exception.hpp>
using namespace mbgl;
TEST(Sprite, SpriteImageZeroWidth) {
+ PremultipliedImage image(0, 16);
try {
- SpriteImage(0, 16, 2, "");
+ SpriteImage(std::move(image), 2.0);
FAIL() << "Expected exception";
} catch (util::SpriteImageException& ex) {
EXPECT_STREQ("Sprite image dimensions may not be zero", ex.what());
@@ -15,8 +17,9 @@ TEST(Sprite, SpriteImageZeroWidth) {
}
TEST(Sprite, SpriteImageZeroHeight) {
+ PremultipliedImage image(16, 0);
try {
- SpriteImage(16, 0, 2, "");
+ SpriteImage(std::move(image), 2.0);
FAIL() << "Expected exception";
} catch (util::SpriteImageException& ex) {
EXPECT_STREQ("Sprite image dimensions may not be zero", ex.what());
@@ -24,41 +27,31 @@ TEST(Sprite, SpriteImageZeroHeight) {
}
TEST(Sprite, SpriteImageZeroRatio) {
+ PremultipliedImage image(16, 16);
try {
- SpriteImage(16, 16, 0, "");
+ SpriteImage(std::move(image), 0.0);
FAIL() << "Expected exception";
} catch (util::SpriteImageException& ex) {
- EXPECT_STREQ("Sprite image pixel count mismatch", ex.what());
- }
-}
-
-TEST(Sprite, SpriteImageMismatchedData) {
- try {
- SpriteImage(16, 16, 2, "");
- FAIL() << "Expected exception";
- } catch (util::SpriteImageException& ex) {
- EXPECT_STREQ("Sprite image pixel count mismatch", ex.what());
+ EXPECT_STREQ("Sprite pixelRatio may not be <= 0", ex.what());
}
}
TEST(Sprite, SpriteImage) {
- std::string pixels(32 * 24 * 4, '\0');
- SpriteImage sprite(32, 24, 2, std::move(pixels));
- EXPECT_EQ(16, sprite.width);
- EXPECT_EQ(32, sprite.pixelWidth);
- EXPECT_EQ(12, sprite.height);
- EXPECT_EQ(24, sprite.pixelHeight);
+ PremultipliedImage image(32, 24);
+ SpriteImage sprite(std::move(image), 2.0);
+ EXPECT_EQ(16, sprite.getWidth());
+ EXPECT_EQ(32, sprite.image.width);
+ EXPECT_EQ(12, sprite.getHeight());
+ EXPECT_EQ(24, sprite.image.height);
EXPECT_EQ(2, sprite.pixelRatio);
- EXPECT_EQ(32u * 24 * 4, sprite.data.size());
}
TEST(Sprite, SpriteImageFractionalRatio) {
- std::string pixels(20 * 12 * 4, '\0');
- SpriteImage sprite(20, 12, 1.5, std::move(pixels));
- EXPECT_EQ(14, sprite.width);
- EXPECT_EQ(20, sprite.pixelWidth);
- EXPECT_EQ(8, sprite.height);
- EXPECT_EQ(12, sprite.pixelHeight);
+ PremultipliedImage image(20, 12);
+ SpriteImage sprite(std::move(image), 1.5);
+ EXPECT_EQ(float(20.0 / 1.5), sprite.getWidth());
+ EXPECT_EQ(20, sprite.image.width);
+ EXPECT_EQ(float(12.0 / 1.5), sprite.getHeight());
+ EXPECT_EQ(12, sprite.image.height);
EXPECT_EQ(1.5, sprite.pixelRatio);
- EXPECT_EQ(20u * 12 * 4, sprite.data.size());
}
diff --git a/test/sprite/sprite_parser.cpp b/test/sprite/sprite_parser.cpp
index 9eb19a8095..54c013e936 100644
--- a/test/sprite/sprite_parser.cpp
+++ b/test/sprite/sprite_parser.cpp
@@ -43,34 +43,34 @@ TEST(Sprite, SpriteImageCreation1x) {
{ // "museum_icon":{"x":177,"y":187,"width":18,"height":18,"pixelRatio":1,"sdf":false}
const auto sprite = createSpriteImage(image_1x, 177, 187, 18, 18, 1, false);
ASSERT_TRUE(sprite.get());
- EXPECT_EQ(18, sprite->width);
- EXPECT_EQ(18, sprite->height);
- EXPECT_EQ(18, sprite->pixelWidth);
- EXPECT_EQ(18, sprite->pixelHeight);
+ EXPECT_EQ(18, sprite->getWidth());
+ EXPECT_EQ(18, sprite->getHeight());
+ EXPECT_EQ(18, sprite->image.width);
+ EXPECT_EQ(18, sprite->image.height);
EXPECT_EQ(1, sprite->pixelRatio);
- EXPECT_EQ(0x7FCC5F263D1FFE16u, test::crc64(sprite->data));
+ EXPECT_EQ(0x7FCC5F263D1FFE16u, test::crc64(sprite->image));
}
{ // outside image == blank
const auto sprite = createSpriteImage(image_1x, 200, 0, 16, 16, 1, false);
ASSERT_TRUE(sprite.get());
- EXPECT_EQ(16, sprite->width);
- EXPECT_EQ(16, sprite->height);
- EXPECT_EQ(16, sprite->pixelWidth);
- EXPECT_EQ(16, sprite->pixelHeight);
+ EXPECT_EQ(16, sprite->getWidth());
+ EXPECT_EQ(16, sprite->getHeight());
+ EXPECT_EQ(16, sprite->image.width);
+ EXPECT_EQ(16, sprite->image.height);
EXPECT_EQ(1, sprite->pixelRatio);
- EXPECT_EQ(0x0000000000000000u, test::crc64(sprite->data)) << std::hex << test::crc64(sprite->data);
+ EXPECT_EQ(0x0000000000000000u, test::crc64(sprite->image)) << std::hex << test::crc64(sprite->image);
}
{ // outside image == blank
const auto sprite = createSpriteImage(image_1x, 0, 300, 16, 16, 1, false);
ASSERT_TRUE(sprite.get());
- EXPECT_EQ(16, sprite->width);
- EXPECT_EQ(16, sprite->height);
- EXPECT_EQ(16, sprite->pixelWidth);
- EXPECT_EQ(16, sprite->pixelHeight);
+ EXPECT_EQ(16, sprite->getWidth());
+ EXPECT_EQ(16, sprite->getHeight());
+ EXPECT_EQ(16, sprite->image.width);
+ EXPECT_EQ(16, sprite->image.height);
EXPECT_EQ(1, sprite->pixelRatio);
- EXPECT_EQ(0x0000000000000000u, test::crc64(sprite->data)) << std::hex << test::crc64(sprite->data);
+ EXPECT_EQ(0x0000000000000000u, test::crc64(sprite->image)) << std::hex << test::crc64(sprite->image);
}
}
@@ -80,12 +80,12 @@ TEST(Sprite, SpriteImageCreation2x) {
// "museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false}
const auto sprite = createSpriteImage(image_2x, 354, 374, 36, 36, 2, false);
ASSERT_TRUE(sprite.get());
- EXPECT_EQ(18, sprite->width);
- EXPECT_EQ(18, sprite->height);
- EXPECT_EQ(36, sprite->pixelWidth);
- EXPECT_EQ(36, sprite->pixelHeight);
+ EXPECT_EQ(18, sprite->getWidth());
+ EXPECT_EQ(18, sprite->getHeight());
+ EXPECT_EQ(36, sprite->image.width);
+ EXPECT_EQ(36, sprite->image.height);
EXPECT_EQ(2, sprite->pixelRatio);
- EXPECT_EQ(0x85F345098DD4F9E3u, test::crc64(sprite->data));
+ EXPECT_EQ(0x85F345098DD4F9E3u, test::crc64(sprite->image));
}
TEST(Sprite, SpriteImageCreation1_5x) {
@@ -94,22 +94,22 @@ TEST(Sprite, SpriteImageCreation1_5x) {
// "museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false}
const auto sprite = createSpriteImage(image_2x, 354, 374, 36, 36, 1.5, false);
ASSERT_TRUE(sprite.get());
- EXPECT_EQ(24, sprite->width);
- EXPECT_EQ(24, sprite->height);
- EXPECT_EQ(36, sprite->pixelWidth);
- EXPECT_EQ(36, sprite->pixelHeight);
+ EXPECT_EQ(24, sprite->getWidth());
+ EXPECT_EQ(24, sprite->getHeight());
+ EXPECT_EQ(36, sprite->image.width);
+ EXPECT_EQ(36, sprite->image.height);
EXPECT_EQ(1.5, sprite->pixelRatio);
- EXPECT_EQ(0x85F345098DD4F9E3u, test::crc64(sprite->data));
+ EXPECT_EQ(0x85F345098DD4F9E3u, test::crc64(sprite->image));
// "hospital_icon":{"x":314,"y":518,"width":36,"height":36,"pixelRatio":2,"sdf":false}
const auto sprite2 = createSpriteImage(image_2x, 314, 518, 35, 35, 1.5, false);
ASSERT_TRUE(sprite2.get());
- EXPECT_EQ(24, sprite2->width);
- EXPECT_EQ(24, sprite2->height);
- EXPECT_EQ(35, sprite2->pixelWidth);
- EXPECT_EQ(35, sprite2->pixelHeight);
+ EXPECT_EQ(float(35 / 1.5), sprite2->getWidth());
+ EXPECT_EQ(float(35 / 1.5), sprite2->getHeight());
+ EXPECT_EQ(35, sprite2->image.width);
+ EXPECT_EQ(35, sprite2->image.height);
EXPECT_EQ(1.5, sprite2->pixelRatio);
- EXPECT_EQ(14312995667113444493u, test::crc64(sprite2->data));
+ EXPECT_EQ(14312995667113444493u, test::crc64(sprite2->image));
}
TEST(Sprite, SpriteParsing) {
@@ -199,12 +199,12 @@ TEST(Sprite, SpriteParsing) {
{
auto sprite = images.find("generic-metro")->second;
- EXPECT_EQ(18, sprite->width);
- EXPECT_EQ(18, sprite->height);
- EXPECT_EQ(18, sprite->pixelWidth);
- EXPECT_EQ(18, sprite->pixelHeight);
+ EXPECT_EQ(18, sprite->getWidth());
+ EXPECT_EQ(18, sprite->getHeight());
+ EXPECT_EQ(18, sprite->image.width);
+ EXPECT_EQ(18, sprite->image.height);
EXPECT_EQ(1, sprite->pixelRatio);
- EXPECT_EQ(0xFF56F5F48F707147u, test::crc64(sprite->data));
+ EXPECT_EQ(0xFF56F5F48F707147u, test::crc64(sprite->image));
}
}
diff --git a/test/sprite/sprite_store.cpp b/test/sprite/sprite_store.cpp
index 5056b89cb7..ca5f0ed9e4 100644
--- a/test/sprite/sprite_store.cpp
+++ b/test/sprite/sprite_store.cpp
@@ -13,9 +13,9 @@ using namespace mbgl;
TEST(SpriteStore, SpriteStore) {
FixtureLog log;
- const auto sprite1 = std::make_shared<SpriteImage>(16, 16, 2, std::string(16 * 16 * 4, '\0'));
- const auto sprite2 = std::make_shared<SpriteImage>(16, 16, 2, std::string(16 * 16 * 4, '\0'));
- const auto sprite3 = std::make_shared<SpriteImage>(16, 16, 2, std::string(16 * 16 * 4, '\0'));
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
+ const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
+ const auto sprite3 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);
@@ -79,7 +79,7 @@ TEST(SpriteStore, SpriteStore) {
TEST(SpriteStore, OtherPixelRatio) {
FixtureLog log;
- const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 1, std::string(8 * 8 * 4, '\0'));
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(8, 8), 1);
using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);
@@ -90,8 +90,8 @@ TEST(SpriteStore, OtherPixelRatio) {
}
TEST(SpriteStore, Multiple) {
- const auto sprite1 = std::make_shared<SpriteImage>(16, 16, 2, std::string(16 * 16 * 4, '\0'));
- const auto sprite2 = std::make_shared<SpriteImage>(16, 16, 2, std::string(16 * 16 * 4, '\0'));
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
+ const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);
@@ -109,8 +109,8 @@ TEST(SpriteStore, Multiple) {
TEST(SpriteStore, Replace) {
FixtureLog log;
- const auto sprite1 = std::make_shared<SpriteImage>(16, 16, 2, std::string(16 * 16 * 4, '\0'));
- const auto sprite2 = std::make_shared<SpriteImage>(16, 16, 2, std::string(16 * 16 * 4, '\0'));
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
+ const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);
@@ -126,8 +126,10 @@ TEST(SpriteStore, Replace) {
TEST(SpriteStore, ReplaceWithDifferentDimensions) {
FixtureLog log;
- const auto sprite1 = std::make_shared<SpriteImage>(16, 16, 2, std::string(16 * 16 * 4, '\0'));
- const auto sprite2 = std::make_shared<SpriteImage>(18, 18, 2, std::string(18 * 18 * 4, '\0'));
+ PremultipliedImage image(16, 16);
+ PremultipliedImage image2(18, 18);
+ const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2);
+ const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(18, 18), 2);
using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);