Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[core][ios][osx][android] fix icons with non-integer width/height
Browse files Browse the repository at this point in the history
ref #3031
ref #2198

For example, an icon that has:
- a pixel width of 10
- a pixel ratio of 3
- a scaled with of 3.333
is now supported.
  • Loading branch information
ansis committed Jan 15, 2016
1 parent 15f4ca5 commit ea9ba90
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2320,8 +2320,8 @@ private void loadIcon(Icon icon) {

mNativeMapView.addAnnotationIcon(
id,
(int) (bitmap.getWidth() / scale),
(int) (bitmap.getHeight() / scale),
bitmap.getWidth(),
bitmap.getHeight(),
scale, buffer.array());
}

Expand Down
4 changes: 2 additions & 2 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2316,8 +2316,8 @@ - (void)installAnnotationImage:(MGLAnnotationImage *)annotationImage

// add sprite
auto cSpriteImage = std::make_shared<mbgl::SpriteImage>(
uint16_t(annotationImage.image.size.width),
uint16_t(annotationImage.image.size.height),
uint16_t(width),
uint16_t(height),
float(annotationImage.image.scale),
std::move(pixels));

Expand Down
4 changes: 2 additions & 2 deletions platform/osx/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1531,8 +1531,8 @@ - (void)installAnnotationImage:(MGLAnnotationImage *)annotationImage {

// 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.size.width,
(uint16_t)rep.size.height,
auto cSpriteImage = std::make_shared<mbgl::SpriteImage>((uint16_t)rep.pixelsWide,
(uint16_t)rep.pixelsHigh,
(float)(rep.pixelsWide / size.width),
std::move(pixelString));
NSString *symbolName = [MGLAnnotationSpritePrefix stringByAppendingString:annotationImage.reuseIdentifier];
Expand Down
12 changes: 6 additions & 6 deletions src/mbgl/sprite/sprite_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@

namespace mbgl {

SpriteImage::SpriteImage(const uint16_t width_,
const uint16_t height_,
SpriteImage::SpriteImage(const uint16_t pixelWidth_,
const uint16_t pixelHeight_,
const float pixelRatio_,
std::string&& data_,
bool sdf_)
: width(width_),
height(height_),
: width(std::ceil(pixelWidth_ / pixelRatio_)),
height(std::ceil(pixelHeight_ / pixelRatio_)),
pixelRatio(pixelRatio_),
pixelWidth(std::ceil(width * pixelRatio)),
pixelHeight(std::ceil(height * pixelRatio)),
pixelWidth(pixelWidth_),
pixelHeight(pixelHeight_),
data(std::move(data_)),
sdf(sdf_) {
const size_t size = pixelWidth * pixelHeight * 4;
Expand Down
23 changes: 8 additions & 15 deletions src/mbgl/sprite/sprite_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,30 @@ namespace mbgl {
SpriteImagePtr createSpriteImage(const PremultipliedImage& image,
const uint16_t srcX,
const uint16_t srcY,
const uint16_t srcWidth,
const uint16_t srcHeight,
const uint16_t width,
const uint16_t height,
const double ratio,
const bool sdf) {
// Disallow invalid parameter configurations.
if (srcWidth == 0 || srcHeight == 0 || ratio <= 0 || ratio > 10 || srcWidth > 1024 ||
srcHeight > 1024) {
if (width == 0 || height == 0 || ratio <= 0 || ratio > 10 || width > 1024 ||
height > 1024) {
Log::Warning(Event::Sprite, "Can't create sprite with invalid metrics");
return nullptr;
}

const uint16_t width = std::ceil(double(srcWidth) / ratio);
const uint16_t dstWidth = std::ceil(width * ratio);
assert(dstWidth >= srcWidth);
const uint16_t height = std::ceil(double(srcHeight) / ratio);
const uint16_t dstHeight = std::ceil(height * ratio);
assert(dstHeight >= srcHeight);

std::string data(dstWidth * dstHeight * 4, '\0');
std::string data(width * height * 4, '\0');

auto srcData = reinterpret_cast<const uint32_t*>(image.data.get());
auto dstData = reinterpret_cast<uint32_t*>(const_cast<char*>(data.data()));

const int32_t maxX = std::min(uint32_t(image.width), uint32_t(srcWidth + srcX)) - srcX;
const int32_t maxX = std::min(uint32_t(image.width), uint32_t(width + srcX)) - srcX;
assert(maxX <= int32_t(image.width));
const int32_t maxY = std::min(uint32_t(image.height), uint32_t(srcHeight + srcY)) - srcY;
const int32_t maxY = std::min(uint32_t(image.height), uint32_t(height + srcY)) - srcY;
assert(maxY <= int32_t(image.height));

// Copy from the source image into our individual sprite image
for (uint16_t y = 0; y < maxY; ++y) {
const auto dstRow = y * dstWidth;
const auto dstRow = y * width;
const auto srcRow = (y + srcY) * image.width + srcX;
for (uint16_t x = 0; x < maxX; ++x) {
dstData[dstRow + x] = srcData[srcRow + x];
Expand Down
8 changes: 4 additions & 4 deletions test/sprite/sprite_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ TEST(Sprite, SpriteImageZeroRatio) {
SpriteImage(16, 16, 0, "");
FAIL() << "Expected exception";
} catch (util::SpriteImageException& ex) {
EXPECT_STREQ("Sprite image dimensions may not be zero", ex.what());
EXPECT_STREQ("Sprite image pixel count mismatch", ex.what());
}
}

Expand All @@ -43,7 +43,7 @@ TEST(Sprite, SpriteImageMismatchedData) {

TEST(Sprite, SpriteImage) {
std::string pixels(32 * 24 * 4, '\0');
SpriteImage sprite(16, 12, 2, std::move(pixels));
SpriteImage sprite(32, 24, 2, std::move(pixels));
EXPECT_EQ(16, sprite.width);
EXPECT_EQ(32, sprite.pixelWidth);
EXPECT_EQ(12, sprite.height);
Expand All @@ -54,8 +54,8 @@ TEST(Sprite, SpriteImage) {

TEST(Sprite, SpriteImageFractionalRatio) {
std::string pixels(20 * 12 * 4, '\0');
SpriteImage sprite(13, 8, 1.5, std::move(pixels));
EXPECT_EQ(13, sprite.width);
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);
Expand Down
6 changes: 3 additions & 3 deletions test/sprite/sprite_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ TEST(Sprite, SpriteImageCreation1_5x) {
ASSERT_TRUE(sprite2.get());
EXPECT_EQ(24, sprite2->width);
EXPECT_EQ(24, sprite2->height);
EXPECT_EQ(36, sprite2->pixelWidth);
EXPECT_EQ(36, sprite2->pixelHeight);
EXPECT_EQ(35, sprite2->pixelWidth);
EXPECT_EQ(35, sprite2->pixelHeight);
EXPECT_EQ(1.5, sprite2->pixelRatio);
EXPECT_EQ(0x134A530C742DD141u, test::crc64(sprite2->data));
EXPECT_EQ(14312995667113444493u, test::crc64(sprite2->data));
}

TEST(Sprite, SpriteParsing) {
Expand Down
18 changes: 9 additions & 9 deletions test/sprite/sprite_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ using namespace mbgl;
TEST(SpriteStore, SpriteStore) {
FixtureLog log;

const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
const auto sprite2 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
const auto sprite3 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
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'));

using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);
Expand Down Expand Up @@ -90,8 +90,8 @@ TEST(SpriteStore, OtherPixelRatio) {
}

TEST(SpriteStore, Multiple) {
const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
const auto sprite2 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
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'));

using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);
Expand All @@ -109,8 +109,8 @@ TEST(SpriteStore, Multiple) {
TEST(SpriteStore, Replace) {
FixtureLog log;

const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
const auto sprite2 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
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'));

using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);
Expand All @@ -126,8 +126,8 @@ TEST(SpriteStore, Replace) {
TEST(SpriteStore, ReplaceWithDifferentDimensions) {
FixtureLog log;

const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
const auto sprite2 = std::make_shared<SpriteImage>(9, 9, 2, std::string(18 * 18 * 4, '\0'));
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'));

using Sprites = std::map<std::string, std::shared_ptr<const SpriteImage>>;
SpriteStore store(1);
Expand Down

0 comments on commit ea9ba90

Please sign in to comment.