diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2015-06-24 17:40:03 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2015-07-08 19:45:59 +0200 |
commit | a96a8fef767bacb2b1a57c9e4a808d54d87623e3 (patch) | |
tree | e943811029f8eda70a8667f693f67cc70374af38 | |
parent | a68b47b9699514547ccc529361e01530c3fa05cc (diff) | |
download | qtlocation-mapboxgl-a96a8fef767bacb2b1a57c9e4a808d54d87623e3.tar.gz |
add a separate SpriteParser object
transforms a JSON and an associated PNG file into individual SpriteImage objects that can be inserted into a SpriteStore
-rw-r--r-- | src/mbgl/annotation/sprite_parser.cpp | 147 | ||||
-rw-r--r-- | src/mbgl/annotation/sprite_parser.hpp | 39 | ||||
-rw-r--r-- | test/annotations/sprite_parser.cpp | 309 | ||||
-rw-r--r-- | test/fixtures/annotations/emerald.json | 1 | ||||
-rw-r--r-- | test/fixtures/annotations/emerald.png | bin | 0 -> 39041 bytes | |||
-rw-r--r-- | test/fixtures/annotations/emerald@2x.json | 1 | ||||
-rw-r--r-- | test/fixtures/annotations/emerald@2x.png | bin | 0 -> 80896 bytes | |||
-rw-r--r-- | test/test.gypi | 1 |
8 files changed, 498 insertions, 0 deletions
diff --git a/src/mbgl/annotation/sprite_parser.cpp b/src/mbgl/annotation/sprite_parser.cpp new file mode 100644 index 0000000000..8285eecba5 --- /dev/null +++ b/src/mbgl/annotation/sprite_parser.cpp @@ -0,0 +1,147 @@ +#include <mbgl/annotation/sprite_parser.hpp> +#include <mbgl/annotation/sprite_image.hpp> + +#include <mbgl/platform/log.hpp> + +#include <mbgl/util/image.hpp> + +#include <rapidjson/document.h> + +#include <cmath> + +namespace mbgl { + +SpriteImagePtr createSpriteImage(const util::Image& image, + const uint16_t srcX, + const uint16_t srcY, + const uint16_t srcWidth, + const uint16_t srcHeight, + const double ratio, + const bool) { + // Disallow invalid parameter configurations. + if (srcWidth == 0 || srcHeight == 0 || ratio <= 0 || ratio > 10 || srcWidth > 1024 || + srcHeight > 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'); + + auto srcData = reinterpret_cast<const uint32_t*>(image.getData()); + auto dstData = reinterpret_cast<uint32_t*>(const_cast<char*>(data.data())); + + const int32_t maxX = std::min(image.getWidth(), uint32_t(srcWidth + srcX)) - srcX; + assert(maxX <= int32_t(image.getWidth())); + const int32_t maxY = std::min(image.getHeight(), uint32_t(srcHeight + srcY)) - srcY; + assert(maxY <= int32_t(image.getHeight())); + + // 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 srcRow = (y + srcY) * image.getWidth() + srcX; + for (uint16_t x = 0; x < maxX; ++x) { + dstData[dstRow + x] = srcData[srcRow + x]; + } + } + + return std::make_unique<const SpriteImage>(width, height, ratio, std::move(data)); +} + +namespace { + +inline uint16_t getUInt16(const rapidjson::Value& value, const char* name, const uint16_t def = 0) { + if (value.HasMember(name)) { + auto& v = value[name]; + if (v.IsUint() && v.GetUint() <= std::numeric_limits<uint16_t>::max()) { + return v.GetUint(); + } else { + Log::Warning(Event::Sprite, "Value of '%s' must be an integer between 0 and 65535", + name); + } + } + + return def; +} + +inline double getDouble(const rapidjson::Value& value, const char* name, const double def = 0) { + if (value.HasMember(name)) { + auto& v = value[name]; + if (v.IsNumber()) { + return v.GetDouble(); + } else { + Log::Warning(Event::Sprite, "Value of '%s' must be a number", name); + } + } + + return def; +} + +inline bool getBoolean(const rapidjson::Value& value, const char* name, const bool def = false) { + if (value.HasMember(name)) { + auto& v = value[name]; + if (v.IsBool()) { + return v.GetBool(); + } else { + Log::Warning(Event::Sprite, "Value of '%s' must be a boolean", name); + } + } + + return def; +} + +} // namespace + +Sprites parseSprite(const std::string& image, const std::string& json) { + using namespace rapidjson; + + Sprites sprites; + + // Parse the sprite image. + const util::Image raster(image); + if (!raster) { + Log::Warning(Event::Sprite, "Could not parse sprite image"); + return sprites; + } + + Document doc; + doc.Parse<0>(json.c_str()); + + if (doc.HasParseError()) { + Log::Warning(Event::Sprite, std::string{ "Failed to parse JSON: " } + doc.GetParseError() + + " at offset " + std::to_string(doc.GetErrorOffset())); + return sprites; + } else if (!doc.IsObject()) { + Log::Warning(Event::Sprite, "Sprite JSON root must be an object"); + return sprites; + } else { + for (Value::ConstMemberIterator itr = doc.MemberBegin(); itr != doc.MemberEnd(); ++itr) { + const std::string name = { itr->name.GetString(), itr->name.GetStringLength() }; + const Value& value = itr->value; + + if (value.IsObject()) { + const uint16_t x = getUInt16(value, "x", 0); + const uint16_t y = getUInt16(value, "y", 0); + const uint16_t width = getUInt16(value, "width", 0); + const uint16_t height = getUInt16(value, "height", 0); + const double pixelRatio = getDouble(value, "pixelRatio", 1); + const bool sdf = getBoolean(value, "sdf", false); + + auto sprite = createSpriteImage(image, x, y, width, height, pixelRatio, sdf); + if (sprite) { + sprites.emplace(name, sprite); + } + } + } + } + + return sprites; +} + +} // namespace mbgl diff --git a/src/mbgl/annotation/sprite_parser.hpp b/src/mbgl/annotation/sprite_parser.hpp new file mode 100644 index 0000000000..71228aacf6 --- /dev/null +++ b/src/mbgl/annotation/sprite_parser.hpp @@ -0,0 +1,39 @@ +#ifndef MBGL_ANNOTATIONS_SPRITE_PARSER +#define MBGL_ANNOTATIONS_SPRITE_PARSER + +#include <mbgl/util/noncopyable.hpp> +#include <mbgl/util/geo.hpp> + +#include <string> +#include <memory> +#include <map> + +namespace mbgl { + +namespace util { + +class Image; + +} // namespace util + +class SpriteImage; + +using SpriteImagePtr = std::shared_ptr<const SpriteImage>; + +// Extracts an individual image from a spritesheet from the given location. +SpriteImagePtr createSpriteImage(const util::Image& image, + uint16_t srcX, + uint16_t srcY, + uint16_t srcWidth, + uint16_t srcHeight, + double ratio, + bool sdf); + +using Sprites = std::map<std::string, SpriteImagePtr>; + +// Parses an image and an associated JSON file and returns the sprite objects. +Sprites parseSprite(const std::string& image, const std::string& json); + +} // namespace mbgl + +#endif diff --git a/test/annotations/sprite_parser.cpp b/test/annotations/sprite_parser.cpp new file mode 100644 index 0000000000..e8dcfd70a5 --- /dev/null +++ b/test/annotations/sprite_parser.cpp @@ -0,0 +1,309 @@ +#include "../fixtures/util.hpp" +#include "../fixtures/fixture_log_observer.hpp" + +#include <mbgl/annotation/sprite_parser.hpp> +#include <mbgl/annotation/sprite_image.hpp> +#include <mbgl/util/image.hpp> +#include <mbgl/util/io.hpp> + +using namespace mbgl; + +TEST(Annotations, SpriteImageCreationInvalid) { + const util::Image image_1x = { util::read_file("test/fixtures/annotations/emerald.png") }; + ASSERT_TRUE(image_1x); + ASSERT_EQ(200u, image_1x.getWidth()); + ASSERT_EQ(299u, image_1x.getHeight()); + + // invalid dimensions + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 0, 16, 1, false)); // width == 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, 0, 1, false)); // height == 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 1, 1, 0, false)); // ratio == 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 1, 1, 23, false)); // ratio too large + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 2048, 16, 1, false)); // too wide + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, 1025, 1, false)); // too tall +} + +TEST(Annotations, SpriteImageCreation1x) { + const util::Image image_1x = { util::read_file("test/fixtures/annotations/emerald.png") }; + ASSERT_TRUE(image_1x); + ASSERT_EQ(200u, image_1x.getWidth()); + ASSERT_EQ(299u, image_1x.getHeight()); + + { // "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(1, sprite->pixelRatio); + EXPECT_EQ(0xC83FE8FA9665D177u, std::hash<std::string>()(sprite->data)); + } + + { // 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(1, sprite->pixelRatio); + EXPECT_EQ(0x5599CFD89CB402A6u, std::hash<std::string>()(sprite->data)); + } + + { // 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(1, sprite->pixelRatio); + EXPECT_EQ(0x5599CFD89CB402A6u, std::hash<std::string>()(sprite->data)); + } +} + +TEST(Annotations, SpriteImageCreation2x) { + const util::Image image_2x = { util::read_file("test/fixtures/annotations/emerald@2x.png") }; + ASSERT_TRUE(image_2x); + + // "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(2, sprite->pixelRatio); + EXPECT_EQ(0x2446A6D2C350B6AEu, std::hash<std::string>()(sprite->data)); +} + +TEST(Annotations, SpriteImageCreation1_5x) { + const util::Image image_2x = { util::read_file("test/fixtures/annotations/emerald@2x.png") }; + ASSERT_TRUE(image_2x); + + // "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(1.5, sprite->pixelRatio); + EXPECT_EQ(0x2446A6D2C350B6AEu, std::hash<std::string>()(sprite->data)); + + // "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(36, sprite2->pixelWidth); + EXPECT_EQ(36, sprite2->pixelHeight); + EXPECT_EQ(1.5, sprite2->pixelRatio); + EXPECT_EQ(0xF5274FF7FABA1C8Du, std::hash<std::string>()(sprite2->data)); +} + +TEST(Annotations, SpriteParsing) { + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = util::read_file("test/fixtures/annotations/emerald.json"); + + const auto images = parseSprite(image_1x, json_1x); + + std::set<std::string> names; + std::transform(images.begin(), images.end(), std::inserter(names, names.begin()), + [](const auto& pair) { return pair.first; }); + + EXPECT_EQ(std::set<std::string>({ "airfield_icon", + "airport_icon", + "background", + "cemetery_icon", + "college_icon", + "default_1", + "default_2", + "default_3", + "default_4", + "default_5", + "default_6", + "default_marker", + "dlr", + "dlr.london-overground.london-underground.national-rail", + "dlr.london-underground", + "dlr.london-underground.national-rail", + "dlr.national-rail", + "dot", + "embassy_icon", + "fire-station_icon", + "generic-metro", + "generic-rail", + "generic_icon", + "golf_icon", + "government_icon", + "grass_pattern", + "harbor_icon", + "hospital_icon", + "hospital_striped", + "interstate_1", + "interstate_2", + "interstate_3", + "library_icon", + "london-overground", + "london-overground.london-underground", + "london-overground.london-underground.national-rail", + "london-overground.national-rail", + "london-underground", + "london-underground.national-rail", + "marker_icon", + "metro", + "metro.rer", + "monument_icon", + "moscow-metro", + "museum_icon", + "national-rail", + "oneway_motorway", + "oneway_road", + "park_icon", + "police_icon", + "post_icon", + "prison_icon", + "religious-christian_icon", + "religious-jewish_icon", + "religious-muslim_icon", + "rer", + "rer.transilien", + "s-bahn", + "s-bahn.u-bahn", + "sand_noise", + "school_icon", + "school_striped", + "secondary_marker", + "u-bahn", + "us_highway_1", + "us_highway_2", + "us_highway_3", + "us_state_1", + "us_state_2", + "us_state_3", + "washington-metro", + "wiener-linien", + "zoo_icon" }), + names); + + { + 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(1, sprite->pixelRatio); + EXPECT_EQ(0X4829734034980451u, std::hash<std::string>()(sprite->data)); + } +} + +TEST(Annotations, SpriteParsingInvalidJSON) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": " })JSON"; + + const auto images = parseSprite(image_1x, json_1x); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ( + 1u, + log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Failed to parse JSON: lacks ending quotation before the end of string at offset 10", + })); +} + +TEST(Annotations, SpriteParsingEmptyImage) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": {} })JSON"; + + const auto images = parseSprite(image_1x, json_1x); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} + +TEST(Annotations, SpriteParsingSimpleWidthHeight) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": { "width": 32, "height": 32 } })JSON"; + + const auto images = parseSprite(image_1x, json_1x); + EXPECT_EQ(1u, images.size()); +} + +TEST(Annotations, SpriteParsingWidthTooBig) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": { "width": 65536, "height": 32 } })JSON"; + + const auto images = parseSprite(image_1x, json_1x); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Value of 'width' must be an integer between 0 and 65535", + })); + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} + +TEST(Annotations, SpriteParsingNegativeWidth) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": { "width": -1, "height": 32 } })JSON"; + + const auto images = parseSprite(image_1x, json_1x); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Value of 'width' must be an integer between 0 and 65535", + })); + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} + +TEST(Annotations, SpriteParsingNullRatio) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": { "width": 32, "height": 32, "pixelRatio": 0 } })JSON"; + + const auto images = parseSprite(image_1x, json_1x); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} diff --git a/test/fixtures/annotations/emerald.json b/test/fixtures/annotations/emerald.json new file mode 100644 index 0000000000..dcc2b4808c --- /dev/null +++ b/test/fixtures/annotations/emerald.json @@ -0,0 +1 @@ +{"background":{"x":0,"y":20,"width":50,"height":50,"pixelRatio":1,"sdf":false},"grass_pattern":{"x":100,"y":80,"width":50,"height":50,"pixelRatio":1,"sdf":false},"interstate_1":{"x":0,"y":100,"width":41,"height":40,"pixelRatio":1,"sdf":false},"interstate_2":{"x":0,"y":100,"width":41,"height":40,"pixelRatio":1,"sdf":false},"interstate_3":{"x":41,"y":100,"width":48,"height":39,"pixelRatio":1,"sdf":false},"us_state_1":{"x":0,"y":73,"width":29,"height":24,"pixelRatio":1,"sdf":false},"us_state_2":{"x":0,"y":73,"width":29,"height":24,"pixelRatio":1,"sdf":false},"us_state_3":{"x":30,"y":73,"width":32,"height":24,"pixelRatio":1,"sdf":false},"us_highway_1":{"x":0,"y":142,"width":29,"height":29,"pixelRatio":1,"sdf":false},"us_highway_2":{"x":30,"y":142,"width":33,"height":29,"pixelRatio":1,"sdf":false},"us_highway_3":{"x":64,"y":142,"width":36,"height":29,"pixelRatio":1,"sdf":false},"default_1":{"x":0,"y":0,"width":17,"height":16,"pixelRatio":1,"sdf":false},"default_2":{"x":17,"y":0,"width":22,"height":16,"pixelRatio":1,"sdf":false},"default_3":{"x":39,"y":0,"width":27,"height":16,"pixelRatio":1,"sdf":false},"default_4":{"x":66,"y":0,"width":32,"height":16,"pixelRatio":1,"sdf":false},"default_5":{"x":98,"y":0,"width":37,"height":16,"pixelRatio":1,"sdf":false},"default_6":{"x":135,"y":0,"width":42,"height":16,"pixelRatio":1,"sdf":false},"london-overground":{"x":70,"y":25,"width":18,"height":18,"pixelRatio":1,"sdf":false},"london-underground":{"x":88,"y":25,"width":18,"height":18,"pixelRatio":1,"sdf":false},"national-rail":{"x":106,"y":25,"width":18,"height":18,"pixelRatio":1,"sdf":false},"dlr":{"x":106,"y":25,"width":18,"height":18,"pixelRatio":1,"sdf":false},"dlr.london-overground.london-underground.national-rail":{"x":70,"y":25,"width":72,"height":18,"pixelRatio":1,"sdf":false},"dlr.london-underground":{"x":88,"y":25,"width":36,"height":18,"pixelRatio":1,"sdf":false},"dlr.london-underground.national-rail":{"x":88,"y":25,"width":54,"height":18,"pixelRatio":1,"sdf":false},"dlr.national-rail":{"x":106,"y":25,"width":36,"height":18,"pixelRatio":1,"sdf":false},"london-overground.london-underground":{"x":70,"y":25,"width":36,"height":18,"pixelRatio":1,"sdf":false},"london-overground.london-underground.national-rail":{"x":124,"y":25,"width":54,"height":18,"pixelRatio":1,"sdf":false},"london-overground.national-rail":{"x":124,"y":25,"width":36,"height":18,"pixelRatio":1,"sdf":false},"london-underground.national-rail":{"x":124,"y":43,"width":36,"height":18,"pixelRatio":1,"sdf":false},"metro":{"x":71,"y":43,"width":18,"height":18,"pixelRatio":1,"sdf":false},"rer":{"x":87,"y":43,"width":18,"height":18,"pixelRatio":1,"sdf":false},"metro.rer":{"x":71,"y":43,"width":34,"height":18,"pixelRatio":1,"sdf":false},"rer.transilien":{"x":87,"y":43,"width":36,"height":18,"pixelRatio":1,"sdf":false},"u-bahn":{"x":70,"y":62,"width":18,"height":18,"pixelRatio":1,"sdf":false},"s-bahn":{"x":88,"y":62,"width":18,"height":18,"pixelRatio":1,"sdf":false},"s-bahn.u-bahn":{"x":70,"y":62,"width":36,"height":18,"pixelRatio":1,"sdf":false},"washington-metro":{"x":106,"y":62,"width":18,"height":18,"pixelRatio":1,"sdf":false},"wiener-linien":{"x":124,"y":62,"width":18,"height":18,"pixelRatio":1,"sdf":false},"moscow-metro":{"x":142,"y":61,"width":21,"height":18,"pixelRatio":1,"sdf":false},"generic-metro":{"x":160,"y":43,"width":18,"height":18,"pixelRatio":1,"sdf":false},"generic-rail":{"x":178,"y":43,"width":18,"height":18,"pixelRatio":1,"sdf":false},"dot":{"x":166,"y":63,"width":13,"height":13,"pixelRatio":1,"sdf":false},"default_marker":{"x":0,"y":175,"width":33,"height":86,"pixelRatio":1,"sdf":false},"secondary_marker":{"x":33,"y":175,"width":33,"height":86,"pixelRatio":1,"sdf":false},"oneway_motorway":{"x":178,"y":24,"width":21,"height":19,"pixelRatio":1,"sdf":false},"oneway_road":{"x":178,"y":62,"width":21,"height":19,"pixelRatio":1,"sdf":false},"hospital_icon":{"x":157,"y":259,"width":18,"height":18,"pixelRatio":1,"sdf":false},"fire-station_icon":{"x":157,"y":241,"width":18,"height":18,"pixelRatio":1,"sdf":false},"cemetery_icon":{"x":157,"y":79,"width":18,"height":18,"pixelRatio":1,"sdf":false},"zoo_icon":{"x":177,"y":79,"width":18,"height":18,"pixelRatio":1,"sdf":false},"park_icon":{"x":177,"y":97,"width":18,"height":18,"pixelRatio":1,"sdf":false},"golf_icon":{"x":177,"y":115,"width":18,"height":18,"pixelRatio":1,"sdf":false},"school_icon":{"x":177,"y":133,"width":18,"height":18,"pixelRatio":1,"sdf":false},"monument_icon":{"x":177,"y":151,"width":18,"height":18,"pixelRatio":1,"sdf":false},"library_icon":{"x":177,"y":169,"width":18,"height":18,"pixelRatio":1,"sdf":false},"museum_icon":{"x":177,"y":187,"width":18,"height":18,"pixelRatio":1,"sdf":false},"college_icon":{"x":177,"y":205,"width":18,"height":18,"pixelRatio":1,"sdf":false},"religious-christian_icon":{"x":157,"y":115,"width":18,"height":18,"pixelRatio":1,"sdf":false},"religious-jewish_icon":{"x":157,"y":133,"width":18,"height":18,"pixelRatio":1,"sdf":false},"religious-muslim_icon":{"x":157,"y":151,"width":18,"height":18,"pixelRatio":1,"sdf":false},"government_icon":{"x":157,"y":169,"width":18,"height":18,"pixelRatio":1,"sdf":false},"post_icon":{"x":157,"y":205,"width":18,"height":18,"pixelRatio":1,"sdf":false},"embassy_icon":{"x":157,"y":223,"width":18,"height":18,"pixelRatio":1,"sdf":false},"police_icon":{"x":157,"y":169,"width":18,"height":18,"pixelRatio":1,"sdf":false},"marker_icon":{"x":157,"y":169,"width":18,"height":18,"pixelRatio":1,"sdf":false},"prison_icon":{"x":157,"y":169,"width":18,"height":18,"pixelRatio":1,"sdf":false},"airfield_icon":{"x":157,"y":187,"width":18,"height":18,"pixelRatio":1,"sdf":false},"airport_icon":{"x":157,"y":187,"width":18,"height":18,"pixelRatio":1,"sdf":false},"harbor_icon":{"x":139,"y":169,"width":18,"height":18,"pixelRatio":1,"sdf":false},"generic_icon":{"x":139,"y":187,"width":18,"height":18,"pixelRatio":1,"sdf":false},"hospital_striped":{"x":117,"y":135,"width":3,"height":3,"pixelRatio":1,"sdf":false},"school_striped":{"x":114,"y":135,"width":3,"height":3,"pixelRatio":1,"sdf":false},"sand_noise":{"x":75,"y":174,"width":50,"height":50,"pixelRatio":1,"sdf":false}}
\ No newline at end of file diff --git a/test/fixtures/annotations/emerald.png b/test/fixtures/annotations/emerald.png Binary files differnew file mode 100644 index 0000000000..967f2e76a6 --- /dev/null +++ b/test/fixtures/annotations/emerald.png diff --git a/test/fixtures/annotations/emerald@2x.json b/test/fixtures/annotations/emerald@2x.json new file mode 100644 index 0000000000..250aa36194 --- /dev/null +++ b/test/fixtures/annotations/emerald@2x.json @@ -0,0 +1 @@ +{"background":{"x":0,"y":40,"width":100,"height":100,"pixelRatio":2,"sdf":false},"grass_pattern":{"x":200,"y":160,"width":100,"height":100,"pixelRatio":2,"sdf":false},"interstate_1":{"x":0,"y":200,"width":82,"height":80,"pixelRatio":2,"sdf":false},"interstate_2":{"x":0,"y":200,"width":82,"height":80,"pixelRatio":2,"sdf":false},"interstate_3":{"x":82,"y":200,"width":96,"height":78,"pixelRatio":2,"sdf":false},"us_state_1":{"x":0,"y":146,"width":58,"height":48,"pixelRatio":2,"sdf":false},"us_state_2":{"x":0,"y":146,"width":58,"height":48,"pixelRatio":2,"sdf":false},"us_state_3":{"x":60,"y":146,"width":64,"height":48,"pixelRatio":2,"sdf":false},"us_highway_1":{"x":0,"y":284,"width":58,"height":58,"pixelRatio":2,"sdf":false},"us_highway_2":{"x":60,"y":284,"width":66,"height":58,"pixelRatio":2,"sdf":false},"us_highway_3":{"x":128,"y":284,"width":72,"height":58,"pixelRatio":2,"sdf":false},"default_1":{"x":0,"y":0,"width":34,"height":32,"pixelRatio":2,"sdf":false},"default_2":{"x":34,"y":0,"width":44,"height":32,"pixelRatio":2,"sdf":false},"default_3":{"x":78,"y":0,"width":54,"height":32,"pixelRatio":2,"sdf":false},"default_4":{"x":132,"y":0,"width":64,"height":32,"pixelRatio":2,"sdf":false},"default_5":{"x":196,"y":0,"width":74,"height":32,"pixelRatio":2,"sdf":false},"default_6":{"x":270,"y":0,"width":84,"height":32,"pixelRatio":2,"sdf":false},"london-overground":{"x":140,"y":50,"width":36,"height":36,"pixelRatio":2,"sdf":false},"london-underground":{"x":176,"y":50,"width":36,"height":36,"pixelRatio":2,"sdf":false},"national-rail":{"x":212,"y":50,"width":36,"height":36,"pixelRatio":2,"sdf":false},"dlr":{"x":212,"y":50,"width":36,"height":36,"pixelRatio":2,"sdf":false},"dlr.london-overground.london-underground.national-rail":{"x":140,"y":50,"width":144,"height":36,"pixelRatio":2,"sdf":false},"dlr.london-underground":{"x":176,"y":50,"width":72,"height":36,"pixelRatio":2,"sdf":false},"dlr.london-underground.national-rail":{"x":176,"y":50,"width":108,"height":36,"pixelRatio":2,"sdf":false},"dlr.national-rail":{"x":212,"y":50,"width":72,"height":36,"pixelRatio":2,"sdf":false},"london-overground.london-underground":{"x":140,"y":50,"width":72,"height":36,"pixelRatio":2,"sdf":false},"london-overground.london-underground.national-rail":{"x":248,"y":50,"width":108,"height":36,"pixelRatio":2,"sdf":false},"london-overground.national-rail":{"x":248,"y":50,"width":72,"height":36,"pixelRatio":2,"sdf":false},"london-underground.national-rail":{"x":248,"y":86,"width":72,"height":36,"pixelRatio":2,"sdf":false},"metro":{"x":142,"y":86,"width":36,"height":36,"pixelRatio":2,"sdf":false},"rer":{"x":174,"y":86,"width":36,"height":36,"pixelRatio":2,"sdf":false},"metro.rer":{"x":142,"y":86,"width":68,"height":36,"pixelRatio":2,"sdf":false},"rer.transilien":{"x":174,"y":86,"width":72,"height":36,"pixelRatio":2,"sdf":false},"u-bahn":{"x":140,"y":124,"width":36,"height":36,"pixelRatio":2,"sdf":false},"s-bahn":{"x":176,"y":124,"width":36,"height":36,"pixelRatio":2,"sdf":false},"s-bahn.u-bahn":{"x":140,"y":124,"width":72,"height":36,"pixelRatio":2,"sdf":false},"washington-metro":{"x":212,"y":124,"width":36,"height":36,"pixelRatio":2,"sdf":false},"wiener-linien":{"x":248,"y":124,"width":36,"height":36,"pixelRatio":2,"sdf":false},"moscow-metro":{"x":284,"y":122,"width":42,"height":36,"pixelRatio":2,"sdf":false},"generic-metro":{"x":320,"y":86,"width":36,"height":36,"pixelRatio":2,"sdf":false},"generic-rail":{"x":356,"y":86,"width":36,"height":36,"pixelRatio":2,"sdf":false},"dot":{"x":332,"y":126,"width":26,"height":26,"pixelRatio":2,"sdf":false},"default_marker":{"x":0,"y":350,"width":66,"height":172,"pixelRatio":2,"sdf":false},"secondary_marker":{"x":66,"y":350,"width":66,"height":172,"pixelRatio":2,"sdf":false},"oneway_motorway":{"x":356,"y":48,"width":42,"height":38,"pixelRatio":2,"sdf":false},"oneway_road":{"x":356,"y":124,"width":42,"height":38,"pixelRatio":2,"sdf":false},"hospital_icon":{"x":314,"y":518,"width":36,"height":36,"pixelRatio":2,"sdf":false},"fire-station_icon":{"x":314,"y":482,"width":36,"height":36,"pixelRatio":2,"sdf":false},"cemetery_icon":{"x":314,"y":158,"width":36,"height":36,"pixelRatio":2,"sdf":false},"zoo_icon":{"x":354,"y":158,"width":36,"height":36,"pixelRatio":2,"sdf":false},"park_icon":{"x":354,"y":194,"width":36,"height":36,"pixelRatio":2,"sdf":false},"golf_icon":{"x":354,"y":230,"width":36,"height":36,"pixelRatio":2,"sdf":false},"school_icon":{"x":354,"y":266,"width":36,"height":36,"pixelRatio":2,"sdf":false},"monument_icon":{"x":354,"y":302,"width":36,"height":36,"pixelRatio":2,"sdf":false},"library_icon":{"x":354,"y":338,"width":36,"height":36,"pixelRatio":2,"sdf":false},"museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false},"college_icon":{"x":354,"y":410,"width":36,"height":36,"pixelRatio":2,"sdf":false},"religious-christian_icon":{"x":314,"y":230,"width":36,"height":36,"pixelRatio":2,"sdf":false},"religious-jewish_icon":{"x":314,"y":266,"width":36,"height":36,"pixelRatio":2,"sdf":false},"religious-muslim_icon":{"x":314,"y":302,"width":36,"height":36,"pixelRatio":2,"sdf":false},"government_icon":{"x":314,"y":338,"width":36,"height":36,"pixelRatio":2,"sdf":false},"post_icon":{"x":314,"y":410,"width":36,"height":36,"pixelRatio":2,"sdf":false},"embassy_icon":{"x":314,"y":446,"width":36,"height":36,"pixelRatio":2,"sdf":false},"police_icon":{"x":314,"y":338,"width":36,"height":36,"pixelRatio":2,"sdf":false},"marker_icon":{"x":314,"y":338,"width":36,"height":36,"pixelRatio":2,"sdf":false},"prison_icon":{"x":314,"y":338,"width":36,"height":36,"pixelRatio":2,"sdf":false},"airfield_icon":{"x":314,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false},"airport_icon":{"x":314,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false},"harbor_icon":{"x":278,"y":338,"width":36,"height":36,"pixelRatio":2,"sdf":false},"generic_icon":{"x":278,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false},"hospital_striped":{"x":234,"y":270,"width":6,"height":6,"pixelRatio":2,"sdf":false},"school_striped":{"x":228,"y":270,"width":6,"height":6,"pixelRatio":2,"sdf":false},"sand_noise":{"x":150,"y":348,"width":100,"height":100,"pixelRatio":2,"sdf":false}}
\ No newline at end of file diff --git a/test/fixtures/annotations/emerald@2x.png b/test/fixtures/annotations/emerald@2x.png Binary files differnew file mode 100644 index 0000000000..a1ffbd95ea --- /dev/null +++ b/test/fixtures/annotations/emerald@2x.png diff --git a/test/test.gypi b/test/test.gypi index 588c61f59a..93f1cc81ed 100644 --- a/test/test.gypi +++ b/test/test.gypi @@ -39,6 +39,7 @@ 'annotations/sprite_image.cpp', 'annotations/sprite_store.cpp', + 'annotations/sprite_parser.cpp', 'api/api_misuse.cpp', 'api/repeated_render.cpp', |