2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "mapzen_queue.h"
19 #include "mapzen_debug.h"
20 #include "mapzen_util.h"
21 #include "mapzen_restcurl.h"
24 #include "mapzen_plugin_internal.h"
25 #include "tangram_view.hpp"
26 #include "tangram/tangram.h"
27 #include "tangram/platform_tizen.h"
28 #include <Elementary.h>
33 #define NORMAL_SCENE_FILE_PATH "/usr/share/maps/mapzen/scenes/bubble-wrap/bubble-wrap.yaml"
34 #define TERRAIN_SCENE_FILE_PATH "/usr/share/maps/mapzen/scenes/walkabout-style/walkabout-style.yaml"
37 TangramView::TangramView()
42 TangramView::~TangramView()
47 mapzen_error_e TangramView::create(maps_view_h view, maps_plugin_map_view_ready_cb callback, const char* providerKey)
50 return MAPZEN_ERROR_INVALID_PARAMETER;
53 int maps_error = MAPS_ERROR_NONE;
54 maps_error = maps_view_get_viewport(view, &m_image);
55 if (maps_error != MAPS_ERROR_NONE) {
56 return (mapzen_error_e)convert_maps_error_to_mapzen_error(maps_error);
59 maps_error = maps_view_get_screen_location(view, &m_x, &m_y, &m_w, &m_h);
60 if (maps_error != MAPS_ERROR_NONE) {
61 return (mapzen_error_e)convert_maps_error_to_mapzen_error(maps_error);
64 // Create an OpenGL context.
66 m_config = evas_gl_config_new();
68 MAPS_LOGE("evas_gl_config_new() failed");
69 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
72 m_config->color_format = EVAS_GL_RGBA_8888;
73 m_config->depth_bits = EVAS_GL_DEPTH_BIT_24;
74 m_config->stencil_bits = EVAS_GL_STENCIL_NONE;
75 m_config->options_bits = EVAS_GL_OPTIONS_DIRECT;
77 m_gl = evas_gl_new(evas_object_evas_get(m_image));
79 MAPS_LOGE("evas_gl_new() failed");
80 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
83 m_api = evas_gl_api_get(m_gl);
85 MAPS_LOGE("evas_gl_api_get() failed");
86 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
89 m_context = evas_gl_context_create(m_gl, nullptr);
91 MAPS_LOGE("evas_gl_context_create() failed");
92 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
96 // Set up rendering surface.
97 auto error = setupOpenGlSurface(view);
98 if (error != MAPZEN_ERROR_NONE) {
102 m_readyCb = callback;
103 // TODO: What to do for multiple instances
104 Tangram::setEvasGlAPI(m_api);
106 Tangram::UrlClient::Options urlOptions;
107 char* proxyAddress = NULL;
108 get_proxy_address(&proxyAddress);
109 urlOptions.proxyAddress = proxyAddress;
110 g_free(proxyAddress);
112 auto platform = std::shared_ptr<Tangram::TizenPlatform>(new Tangram::TizenPlatform(urlOptions));
113 //auto platform = std::make_shared<Tangram::TizenPlatform>();
115 platform->setRenderCallbackFunction([=](){
116 ecore_main_loop_thread_safe_call_async(&renderingCb, m_image);
119 // Set up the tangram map.
120 m_map = new Tangram::Map(platform);
122 float scaleFactor = elm_config_scale_get();
123 MAPS_LOGD("evas_gl_context_create() set PixelScale %f", scaleFactor);
124 m_map->setPixelScale(scaleFactor);
127 m_providerKey = providerKey;
130 // Start loading the scene by setting the map type.
133 // Make the GL context current and perform GL setup.
134 evas_gl_make_current(m_gl, m_surface, m_context);
137 m_map->resize(m_w, m_h);
139 if (m_sceneLoaded && m_w > 1 && m_h > 1) {
140 readyMapCb((void*)view);
143 m_isInitialized = true;
145 return MAPZEN_ERROR_NONE;
148 mapzen_error_e TangramView::setupOpenGlSurface(maps_view_h view)
150 if (!view || !m_gl || !m_config || !m_image || !m_context) {
151 return MAPZEN_ERROR_INVALID_PARAMETER;
154 // Remove any previous pixel callback on the image.
155 evas_object_image_pixels_get_callback_set(m_image, nullptr, nullptr);
158 // Destroy the old surface.
159 evas_object_image_native_surface_set(m_image, nullptr);
160 evas_gl_surface_destroy(m_gl, m_surface);
166 evas_object_image_size_set(m_image, m_w, m_h);
168 Evas_Native_Surface native_surface;
169 m_surface = evas_gl_surface_create(m_gl, m_config, m_w, m_h);
171 MAPS_LOGE("evas_gl_surface_create() failed");
172 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
175 if (!evas_gl_native_surface_get(m_gl, m_surface, &native_surface)) {
176 // Could not get the native surface information, so destroy the surface and exit.
177 evas_gl_make_current(m_gl, nullptr, nullptr);
178 evas_gl_surface_destroy(m_gl, m_surface);
180 MAPS_LOGE("evas_gl_native_surface_get() failed");
181 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
184 // Set the native surface information and pixel callback on the image.
185 evas_object_image_native_surface_set(m_image, &native_surface);
186 evas_object_image_pixels_get_callback_set(m_image, pixelGetCb, view);
188 return MAPZEN_ERROR_NONE;
191 mapzen_error_e TangramView::destroy(maps_view_h view)
194 return MAPZEN_ERROR_INVALID_PARAMETER;
197 m_isInitialized = false;
198 m_sceneLoaded = false;
201 evas_object_image_pixels_get_callback_set(m_image, nullptr, nullptr);
205 if (m_surface && m_context) {
206 evas_gl_make_current(m_gl, m_surface, m_context);
209 evas_object_image_native_surface_set(m_image, nullptr);
210 evas_gl_surface_destroy(m_gl, m_surface);
213 evas_gl_context_destroy(m_gl, m_context);
220 evas_gl_config_free(m_config);
224 static_cast<Tangram::TizenPlatform*>(m_map->getPlatform().get())->setRenderCallbackFunction(nullptr);
231 return MAPZEN_ERROR_NONE;
234 mapzen_error_e TangramView::render(maps_view_h view, const maps_coordinates_h coord, double zoom, double angle)
236 if (!view || !coord) {
237 MAPS_LOGE("Render requested with invalid 'view' or 'coord'.");
238 return MAPZEN_ERROR_INVALID_PARAMETER;
241 if (!m_isInitialized) {
242 MAPS_LOGE("Render requested with view that is not initialized.");
243 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
248 int x = 0, y = 0, w = 0, h = 0;
249 maps_view_get_screen_location(view, &x, &y, &w, &h);
253 if (x != m_x || y != m_y || w != m_w || h != m_h) {
254 if ( (m_w <= 1 || m_h <= 1) && w > 1 && h > 1 && m_sceneLoaded) {
255 // Send a tangram view ready callback when we have a legit canvas size
256 readyMapCb((void*)view);
262 evas_gl_make_current(m_gl, m_surface, m_context);
263 m_map->resize(m_w, m_h);
264 setupOpenGlSurface(view);
267 if (m_zoom != zoom) {
269 m_map->setZoom(zoom);
272 if (m_angle != angle) {
274 m_map->setRotation(degrees_to_radians(angle));
277 double lng = 0, lat = 0;
278 maps_coordinates_get_longitude(coord, &lng);
279 maps_coordinates_get_latitude(coord, &lat);
281 if (m_lng != lng || m_lat != lat) {
284 m_map->setPosition(m_lng, m_lat);
287 m_map->getPlatform()->requestRender();
289 return MAPZEN_ERROR_NONE;
292 mapzen_error_e TangramView::moveCenter(maps_view_h view, int delta_x, int delta_y)
295 return MAPZEN_ERROR_INVALID_PARAMETER;
298 if (!m_isInitialized) {
299 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
302 if (delta_x == 0 && delta_y == 0) {
303 return MAPZEN_ERROR_NONE;
306 // The delta_x and delta_y values are in pixels, so we need to determine the equivalent displacement in
307 // longitude and latitude to set the new center position.
309 double x = 0.5 * m_w + (double)delta_x;
310 double y = 0.5 * m_h + (double)delta_y;
311 double lng = 0.0, lat = 0.0;
312 if (m_map->screenPositionToLngLat(x, y, &lng, &lat)) {
313 lng = wrap_longitude(lng);
314 lat = wrap_latitude(lat);
315 m_map->setPosition(lng, lat);
318 MAPS_LOGD("Moved with delta x: %d, y: %d to coordinates lon: %f, lat: %f", delta_x, delta_y, lng, lat);
320 return MAPZEN_ERROR_NONE;
323 mapzen_error_e TangramView::getCenter(maps_view_h view, maps_coordinates_h *center)
325 if (!view || !center) {
326 return MAPZEN_ERROR_INVALID_PARAMETER;
329 if (!m_isInitialized) {
330 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
333 double longitude = 0, latitude = 0;
334 m_map->getPosition(longitude, latitude);
336 longitude = wrap_longitude(longitude);
337 latitude = wrap_latitude(latitude);
338 if (*center == nullptr) {
339 maps_coordinates_create(latitude, longitude, center);
341 maps_coordinates_set_latitude(*center, latitude);
342 maps_coordinates_set_longitude(*center, longitude);
345 return MAPZEN_ERROR_NONE;
348 mapzen_error_e TangramView::setScalebarEnabled(maps_view_h view, bool enable)
350 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
353 mapzen_error_e TangramView::getScalebarEnabled(maps_view_h view, bool *enabled)
355 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
358 mapzen_error_e TangramView::convertScreenToGeolocation(maps_view_h view, int x, int y, maps_coordinates_h *coord)
360 if (!view || !coord) {
361 return MAPZEN_ERROR_INVALID_PARAMETER;
364 if (!m_isInitialized) {
365 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
368 double longitude = (double)x, latitude = (double)y;
369 m_map->screenPositionToLngLat(x, y, &longitude, &latitude);
371 longitude = wrap_longitude(longitude);
372 latitude = wrap_latitude(latitude);
373 if (*coord == nullptr) {
374 maps_coordinates_create(latitude, longitude, coord);
376 maps_coordinates_set_latitude(*coord, latitude);
377 maps_coordinates_set_longitude(*coord, longitude);
380 return MAPZEN_ERROR_NONE;
383 mapzen_error_e TangramView::convertGeolocationToScreen(maps_view_h view, const maps_coordinates_h coord, int *x, int *y)
385 if (!view || !coord) {
386 return MAPZEN_ERROR_INVALID_PARAMETER;
389 if (!m_isInitialized) {
390 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
394 maps_coordinates_get_latitude(coord, &lat);
395 maps_coordinates_get_longitude(coord, &lng);
397 double screenx, screeny;
398 m_map->lngLatToScreenPosition(lng, lat, &screenx, &screeny);
403 return MAPZEN_ERROR_NONE;
406 mapzen_error_e TangramView::getMinZoomLevel(maps_view_h view, int *zoom)
409 return MAPZEN_ERROR_NONE;
412 mapzen_error_e TangramView::getMaxZoomLevel(maps_view_h view, int *zoom)
415 return MAPZEN_ERROR_NONE;
418 mapzen_error_e TangramView::onViewObject(maps_view_h view, const maps_view_object_h object, maps_view_object_operation_e operation)
420 if (!view || !object || operation < MAPS_VIEW_OBJECT_ADD || operation > MAPS_VIEW_OBJECT_REMOVE) {
421 return MAPZEN_ERROR_INVALID_PARAMETER;
424 if (!m_isInitialized || !m_map) {
425 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
428 mapzen_error_e error = MAPZEN_ERROR_NONE;
430 TangramView *tv = nullptr;
431 int maps_error = maps_view_get_maps_plugin_view_handle(view, (void**)&tv);
432 if (maps_error != MAPS_ERROR_NONE || !tv) { return MAPZEN_ERROR_INVALID_PARAMETER; }
434 maps_view_object_type_e type = MAPS_VIEW_OBJECT_POLYLINE;
435 maps_view_object_get_type(object, &type);
437 if (type < MAPS_VIEW_OBJECT_POLYLINE || type > MAPS_VIEW_OBJECT_MARKER) { return MAPZEN_ERROR_INVALID_PARAMETER; }
439 auto& mapViewObjs = tv->mapViewObjects();
440 auto& mutex = tv->viewObjectMutex();
441 MapViewObjects::iterator iter;
442 MapViewObjects::iterator end;
444 std::lock_guard<std::mutex> lock(mutex);
445 iter = mapViewObjs.find(object);
446 end = mapViewObjs.end();
450 case MAPS_VIEW_OBJECT_ADD:
451 error = tv->addObject(object);
453 case MAPS_VIEW_OBJECT_SET_VISIBLE:
455 error = tv->setObjectVisible(object, iter->second);
458 case MAPS_VIEW_OBJECT_CHANGE:
460 error = tv->updateObject(object, iter->second);
463 case MAPS_VIEW_OBJECT_REMOVE:
464 error = tv->removeObject(object);
469 const char *oper_str[20] = { "ADD", "SET_VISIBLE", "MOVE", "CHANGE", "REMOVE"};
470 const char *type_str[20] = { "POLYLINE", "POLYGON", "MARKER", "UNKNOWN"};
472 MAPS_LOGD("Done Processing View Object: type=%s, operation=%s, object=%p",
473 (type >= MAPS_VIEW_OBJECT_POLYLINE && type <= MAPS_VIEW_OBJECT_MARKER) ? type_str[type] : "?",
474 (operation >= MAPS_VIEW_OBJECT_ADD && operation <= MAPS_VIEW_OBJECT_REMOVE) ? oper_str[operation] : "?",
477 if (error != MAPZEN_ERROR_NONE) {
478 MAPS_LOGD("Something went wrong in processing this ViewObject operation");
484 mapzen_error_e TangramView::addObject(maps_view_object_h object)
486 if (!object || !m_map) { return MAPZEN_ERROR_INVALID_PARAMETER; }
488 mapzen_error_e error = MAPZEN_ERROR_NONE;
489 Tangram::MarkerID tvMarker = 0;
490 maps_view_object_type_e type = MAPS_VIEW_OBJECT_POLYLINE;
492 maps_view_object_get_type(object, &type);
494 MapViewObjects::iterator iter;
495 MapViewObjects::iterator end;
498 std::lock_guard<std::mutex> lock(m_viewObjectMutex);
499 iter = m_mapViewObjs.find(object);
500 end = m_mapViewObjs.end();
503 tvMarker = m_map->markerAdd();
505 error = updateObject(object, tvMarker);
506 if (error == MAPZEN_ERROR_NONE) {
507 std::lock_guard<std::mutex> lock(m_viewObjectMutex);
508 m_mapViewObjs.insert(std::make_pair(object, tvMarker));
510 m_map->markerRemove(tvMarker);
519 mapzen_error_e TangramView::setObjectVisible(maps_view_object_h object, Tangram::MarkerID tvMarker)
521 if (!object || !tvMarker || !m_map) { return MAPZEN_ERROR_INVALID_PARAMETER; }
524 maps_view_object_get_visible(object, &visible);
526 m_map->markerSetVisible(tvMarker, visible);
527 return MAPZEN_ERROR_NONE;
530 mapzen_error_e TangramView::updateObject(maps_view_object_h object, Tangram::MarkerID tvMarker)
532 if (!object || !tvMarker || !m_map) { return MAPZEN_ERROR_INVALID_PARAMETER; }
534 mapzen_error_e error = MAPZEN_ERROR_NONE;
535 maps_view_object_type_e type = MAPS_VIEW_OBJECT_POLYLINE;
537 maps_view_object_get_type(object, &type);
540 case MAPS_VIEW_OBJECT_MARKER:
541 error = updateMarker(object, tvMarker);
543 case MAPS_VIEW_OBJECT_POLYLINE:
544 error = updatePolyline(object, tvMarker);
546 case MAPS_VIEW_OBJECT_POLYGON:
547 error = updatePolygon(object, tvMarker);
556 mapzen_error_e TangramView::getBitmapMarkerImage(maps_view_object_h object, unsigned char *&imgData, int &imgWidth, int &imgHeight) {
557 char *imgPath = nullptr;
558 Evas_Object *img = nullptr;
560 int error = MAPS_ERROR_NONE;
563 error = maps_view_object_marker_get_image_file(object, &imgPath);
564 if (error != MAPS_ERROR_NONE || !imgPath) { break; }
566 img = evas_object_image_add(evas_object_evas_get(m_image));
567 evas_object_image_file_set(img, imgPath, nullptr);
568 int err = evas_object_image_load_error_get(img);
569 if (err != EVAS_LOAD_ERROR_NONE) {
570 MAPS_LOGE("Failed to load marker image file: %s", imgPath);
576 evas_object_image_size_get(img, &imgWidth, &imgHeight);
577 imgSize = imgWidth * imgHeight * 4;
579 // Get Raw data pointer to the image
580 const unsigned char *srcData = (unsigned char *)evas_object_image_data_get(img, EINA_FALSE);
581 if (!srcData || imgSize <= 0) {
582 MAPS_LOGE("Failed to get image data from the evas image for the marker");
583 error = MAPS_ERROR_OUT_OF_MEMORY;
587 imgData = (unsigned char *)malloc(imgSize);
589 MAPS_LOGE("Failed to malloc!! for image data");
590 error = MAPS_ERROR_OUT_OF_MEMORY;
594 // convert data from rgba to bgra (also flip the image)
595 for (int i = 0; i < imgHeight; i++) {
596 for (int j = 0; j < imgWidth; j++) {
597 int offset = ((i * imgWidth) + j) * 4;
598 int offset_flip = (((imgHeight - 1 - i) * imgWidth) + j) * 4;
599 *(imgData + offset_flip) = *(srcData + offset + 2);
600 *(imgData + offset_flip + 1) = *(srcData + offset + 1);
601 *(imgData + offset_flip + 2) = *(srcData + offset);
602 *(imgData + offset_flip + 3) = *(srcData + offset + 3);
608 return (mapzen_error_e)convert_maps_error_to_mapzen_error(error);
611 mapzen_error_e TangramView::updateMarker(maps_view_object_h object, Tangram::MarkerID tvMarker)
613 maps_coordinates_h mapsCoord = nullptr;
614 double lat = 0.0, lng = 0.0;
615 int markerWidth = 0, markerHeight = 0;
616 int imgWidth = 0, imgHeight = 0;
617 int error = MAPS_ERROR_NONE;
618 unsigned char *imgData = nullptr;
620 const char* styleFormat = "{ style: 'sdk-point-overlay', color: white, size: [%dpx, %dpx], collide: false, anchor: %s, transition: { [show, hide]: { time: 0s } } }";
622 static std::string anchor;
624 maps_view_marker_type_e type;
625 error = maps_view_object_marker_get_type(object, &type);
628 if (error != MAPS_ERROR_NONE || type < MAPS_VIEW_MARKER_PIN || type > MAPS_VIEW_MARKER_STICKER) { break; }
630 error = getBitmapMarkerImage(object, imgData, imgWidth, imgHeight);
632 if (error != MAPS_ERROR_NONE || !imgData) {
633 MAPS_LOGE("Failed getting image data from marker object, with error code: %d", error);
636 m_map->markerSetBitmap(tvMarker, imgWidth, imgHeight, reinterpret_cast<unsigned int *>(imgData));
640 if (type == MAPS_VIEW_MARKER_PIN) {
644 float scaleFactor = 1.0/elm_config_scale_get();
645 error = maps_view_object_marker_get_size(object, &markerWidth, &markerHeight);
646 if (error != MAPS_ERROR_NONE) { break; }
649 * - Sets the marker dimension to be image dimension if both the specified marker dimensions are zero
650 * - Sets the marker dimension such that aspect ratio is maintained when one of the marker dimensions is
653 if (markerWidth == 0 && markerHeight == 0) {
654 markerWidth = imgWidth;
655 markerHeight = imgHeight;
656 } else if (markerWidth == 0 && markerHeight > 0) {
657 markerWidth = (float)markerHeight * (float)imgWidth / (float)imgHeight;
658 } else if (markerWidth > 0 && markerHeight == 0) {
659 markerHeight = (float)markerWidth * (float)imgHeight / (float)imgWidth;
662 float scaledWidth = scaleFactor * markerWidth;
663 float scaledHeight = scaleFactor * markerHeight;
665 char styleString[256];
666 std::snprintf(styleString, sizeof(styleString), styleFormat, int(scaledWidth), int(scaledHeight), anchor.c_str());
668 MAPS_LOGD("Marker Style String: %s", styleString);
669 m_map->markerSetStylingFromString(tvMarker, styleString);
671 error = maps_view_object_marker_get_coordinates(object, &mapsCoord);
672 if (error != MAPS_ERROR_NONE) { break; }
674 error = maps_coordinates_get_longitude(mapsCoord, &lng);
675 if (error != MAPS_ERROR_NONE) {
676 maps_coordinates_destroy(mapsCoord);
680 error = maps_coordinates_get_latitude(mapsCoord, &lat);
681 if (error != MAPS_ERROR_NONE) {
682 maps_coordinates_destroy(mapsCoord);
686 maps_coordinates_destroy(mapsCoord);
687 m_map->markerSetPoint(tvMarker, Tangram::LngLat(lng, lat));
690 error = maps_view_object_marker_get_z_order(object, &drawOrder);
691 if (error != MAPS_ERROR_NONE) { break; }
692 m_map->markerSetDrawOrder(tvMarker, drawOrder);
695 return (mapzen_error_e)convert_maps_error_to_mapzen_error(error);
698 mapzen_error_e TangramView::updatePolyline(maps_view_object_h object, Tangram::MarkerID tvMarker)
700 int error = MAPS_ERROR_NONE;
701 Tangram::Coordinates coords = {};
702 unsigned char r = 0, g = 0, b = 0, a = 0;
705 const char* styleFormat = "{ style: 'ux-route-line-overlay', color: [%d, %d, %d, %d], width: %dpx, order: 500 }";
708 error = maps_view_object_polyline_get_color(object, &r, &g, &b, &a);
709 if (error != MAPS_ERROR_NONE) { break; }
711 error = maps_view_object_polyline_get_width(object, &width);
712 if (error != MAPS_ERROR_NONE) { break; }
714 char styleString[256];
715 std::snprintf(styleString, sizeof(styleString), styleFormat, r, g, b, a, width);
717 MAPS_LOGD("Polyline Style String: %s", styleString);
719 m_map->markerSetStylingFromString(tvMarker, styleString);
721 error = maps_view_object_polyline_foreach_point(object, emplaceCoord, &coords);
722 if (error != MAPS_ERROR_NONE) { break; }
724 m_map->markerSetPolyline(tvMarker, coords.data(), static_cast<int>(coords.size()));
727 return (mapzen_error_e)convert_maps_error_to_mapzen_error(error);
730 mapzen_error_e TangramView::updatePolygon(maps_view_object_h object, Tangram::MarkerID tvMarker)
732 int error = MAPS_ERROR_NONE;
733 Tangram::Coordinates coords = {};
734 unsigned char r = 0, g = 0, b = 0, a = 0;
735 const char* styleFormat = "{ style: 'polygons', color: [%d, %d, %d, %d] }";
738 error = maps_view_object_polygon_get_fill_color(object, &r, &g, &b, &a);
739 if (error != MAPS_ERROR_NONE) { break; }
741 char styleString[256];
742 std::snprintf(styleString, sizeof(styleString), styleFormat, r, g, b, a);
744 MAPS_LOGD("Polygon Style String: %s", styleString);
746 m_map->markerSetStylingFromString(tvMarker, styleString);
748 error = maps_view_object_polygon_foreach_point(object, emplaceCoord, &coords);
749 if (error != MAPS_ERROR_NONE) { break; }
751 int count = (int)coords.size();
752 m_map->markerSetPolygon(tvMarker, coords.data(), &count, 1);
755 return (mapzen_error_e)convert_maps_error_to_mapzen_error(error);
758 mapzen_error_e TangramView::removeObject(maps_view_object_h object)
760 if (!object || !m_map) { return MAPZEN_ERROR_INVALID_PARAMETER; }
762 mapzen_error_e error = MAPZEN_ERROR_NONE;
764 std::lock_guard<std::mutex> lock(m_viewObjectMutex);
765 auto iter = m_mapViewObjs.find(object);
766 if (iter != m_mapViewObjs.end()) {
768 m_map->markerRemove(iter->second);
770 iter = m_mapViewObjs.erase(iter);
771 error = MAPZEN_ERROR_NONE;
777 void TangramView::removeAllObjects()
779 std::lock_guard<std::mutex> lock(m_viewObjectMutex);
780 m_mapViewObjs.clear();
781 m_map->markerRemoveAll();
784 bool TangramView::emplaceCoord(int index, maps_coordinates_h coordinate, void *user_data)
786 if (!coordinate || !user_data) { return false; }
789 double lng = 0.0, lat = 0.0;
791 error = maps_coordinates_get_longitude(coordinate, &lng);
792 if (error != MAPS_ERROR_NONE) {
793 MAPS_LOGD("Not able to extract longitude from coordiate");
796 error = maps_coordinates_get_latitude(coordinate, &lat);
797 if (error != MAPS_ERROR_NONE) {
798 MAPS_LOGD("Not able to extract longitude from coordiate");
802 MAPS_LOGD("[%d] %f, %f", index+1, lng, lat);
804 Tangram::Coordinates *coords = static_cast<Tangram::Coordinates*>(user_data);
805 coords->emplace_back(lng, lat);
809 mapzen_error_e TangramView::captureSnapshot(maps_view_h view, void **data, int *width, int *height, maps_view_colorspace_type_e *cs)
812 return MAPZEN_ERROR_INVALID_PARAMETER;
815 if (!m_isInitialized) {
816 return MAPZEN_ERROR_SERVICE_NOT_AVAILABLE;
819 *data = (void*)malloc(m_w * m_h * sizeof(unsigned int));
821 return MAPZEN_ERROR_OUT_OF_MEMORY;
824 pixelGetCb(view, nullptr);
826 unsigned int *pixels = (unsigned int*)malloc(m_w * m_h * sizeof(unsigned int));
828 return MAPZEN_ERROR_OUT_OF_MEMORY;
831 m_map->captureSnapshot(pixels);
833 for (int i = 0; i < m_h; ++i) {
834 memcpy((unsigned int*)*data + m_w * i, pixels + m_w * (m_h - i - 1), m_w * sizeof(unsigned int));
837 *cs = MAPS_VIEW_COLORSPACE_RGBA8888;
842 return MAPZEN_ERROR_NONE;
846 void TangramView::setMapType(maps_view_h view)
852 std::vector<Tangram::SceneUpdate> sceneUpdates;
853 maps_view_type_e map_type;
854 maps_view_get_type(view, &map_type);
856 tangram_view_type newViewType = (tangram_view_type)convert_maps_view_type_to_tangram_view_type(map_type);
858 // If Scene is being reloaded then reset all the scene preferences to their defaults (building/transit/language/providerKey)
859 if (newViewType != m_viewType) {
860 m_buildingsEnabled = true;
861 m_publicTransitEnabled = false;
863 m_isProviderKeySet = false;
866 bool buildings_enabled = false;
867 maps_view_get_buildings_enabled(view, &buildings_enabled);
868 if (buildings_enabled != m_buildingsEnabled) {
869 m_buildingsEnabled = buildings_enabled;
870 if (m_buildingsEnabled) {
871 sceneUpdates.push_back( {"global.sdk_building_extrude", "true"} );
873 sceneUpdates.push_back( {"global.sdk_building_extrude", "false"} );
877 bool public_transit_enabled = false;
878 maps_view_get_public_transit_enabled(view, &public_transit_enabled);
879 if (public_transit_enabled != m_publicTransitEnabled) {
880 m_publicTransitEnabled = public_transit_enabled;
881 if (m_publicTransitEnabled) {
882 sceneUpdates.push_back( {"global.sdk_transit_overlay", "true"} );
884 sceneUpdates.push_back( {"global.sdk_transit_overlay", "false"} );
888 char* language = nullptr;
889 maps_view_get_language(view, &language);
890 if (m_language != language) {
891 m_language = language;
892 sceneUpdates.push_back( {"global.ux_language", m_language.substr(0, 2).c_str()} );
896 // set provider key for vector tiles
897 if (m_providerKey.size() > 0 && !m_isProviderKeySet) {
898 MAPS_LOGD("Queueing API key update: %s", m_providerKey.c_str());
899 sceneUpdates.push_back( {"global.sdk_mapzen_api_key", m_providerKey.c_str()} );
900 m_isProviderKeySet = true;
903 // Loading a new tangram scene resets the map states/caches.
904 if (newViewType != m_viewType) {
905 // When the scene is changed, update the 'sdk-point-overlay' style to remove it's texture;
906 // this allows us to use this style for markers with custom bitmaps.
907 sceneUpdates.push_back( {"styles.sdk-point-overlay.texture", "null"} );
909 const char* newSceneFile = NORMAL_SCENE_FILE_PATH;
910 switch(newViewType) {
911 case TANGRAM_VIEW_TERRAIN:
912 newSceneFile = TERRAIN_SCENE_FILE_PATH;
914 case TANGRAM_VIEW_NORMAL:
915 newSceneFile = NORMAL_SCENE_FILE_PATH;
920 m_viewType = newViewType;
921 m_map->loadSceneAsync(newSceneFile, false, sceneLoadedCb, (void*)view, sceneUpdates);
923 // bool traffic_enabled = false;
924 // maps_view_get_traffic_enabled(view, &traffic_enabled);
925 if (sceneUpdates.empty()) { return; }
926 m_map->queueSceneUpdate(sceneUpdates);
927 m_map->applySceneUpdates();
931 void TangramView::sceneLoadedCb(void *data) {
932 TangramView *tv = nullptr;
933 int maps_error = maps_view_get_maps_plugin_view_handle((maps_view_h)data, (void**)&tv);
934 if (maps_error != MAPS_ERROR_NONE || !tv) { return; }
936 // only do this for first scene load not for any sceneUpdates
937 if (!tv->isSceneLoaded()) {
938 if (tv->getWidth() > 1 && tv->getHeight() > 1) {
941 tv->setSceneLoaded(true);
945 void TangramView::readyMapCb(void *data)
947 TangramView *tv = nullptr;
948 int maps_error = maps_view_get_maps_plugin_view_handle((maps_view_h)data, (void**)&tv);
949 if (maps_error != MAPS_ERROR_NONE || !tv) { return; }
956 void TangramView::pixelGetCb(void *data, Evas_Object *obj)
958 TangramView *tv = nullptr;
959 int maps_error = maps_view_get_maps_plugin_view_handle(data, (void**)&tv);
960 if (maps_error != MAPS_ERROR_NONE || !tv || !tv->m_gl || !tv->m_surface || !tv->m_context) {
964 evas_gl_make_current(tv->m_gl, tv->m_surface, tv->m_context);
965 tv->m_api->glViewport(0, 0, tv->m_w, tv->m_h);
967 tv->m_map->update(0);
969 MAPS_LOGD("pixelGetCb called on TangramView");
971 MAPS_LOGD("tv->m_map is null, in pixelGelCb");
975 void TangramView::renderingCb(void *data) {
979 evas_object_image_pixels_dirty_set((Evas_Object*)data, EINA_TRUE);