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.
17 #include "here_view.h"
18 #include <Elementary.h>
20 using namespace HERE_PLUGIN_NAMESPACE_PREFIX;
22 static const char SIG_LOADED[] = "loaded";
25 HERE_PLUGIN_BEGIN_NAMESPACE
27 GLData *HereView::m_pImpl = NULL;
29 HereView::HereView(void *pCbFunc, void *pUserData, int nReqId)
32 m_pUserData = pUserData;
40 GLData* HereView::GetImplHandler()
45 here_error_e HereView::Init(maps_view_h hView, maps_plugin_map_view_ready_cb pCbFunc)
48 return HERE_ERROR_INVALID_PARAMETER;
51 return HERE_ERROR_INVALID_OPERATION;
55 m_pImpl = new (std::nothrow) GLData();
58 return HERE_ERROR_INVALID_PARAMETER;
60 m_pImpl->idler = ecore_idler_add(__idlerCb, (void*)m_pImpl);
61 m_pImpl->readyCb = NULL;
64 here_error_e error = HERE_ERROR_NONE;
65 int error2 = MAPS_ERROR_NONE;
68 error2 = maps_view_get_viewport(hView, &m_pImpl->img);
69 if (error2 != MAPS_ERROR_NONE) break;
71 error2 = maps_view_get_screen_location(hView, &m_pImpl->x, &m_pImpl->y, &m_pImpl->w, &m_pImpl->h);
72 if (error2 != MAPS_ERROR_NONE) break;
74 m_pImpl->hView = hView;
76 error = InitOpenGL(m_pImpl);
77 if (error != HERE_ERROR_NONE) break;
79 error = InitOpenGLSurface(m_pImpl);
80 if (error != HERE_ERROR_NONE) break;
82 error = InitMap(m_pImpl, pCbFunc);
85 if (error == HERE_ERROR_NONE && error2 != MAPS_ERROR_NONE)
86 error = (here_error_e)ConvertToHereError(error2);
91 here_error_e HereView::InitOpenGL(GLData *gld)
94 return HERE_ERROR_INVALID_PARAMETER;
97 gld->cfg = evas_gl_config_new();
100 MAPS_LOGE("evas_gl_config_new() failed");
101 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
104 gld->cfg->color_format = EVAS_GL_RGBA_8888; // Surface Color Format
105 gld->cfg->depth_bits = EVAS_GL_DEPTH_NONE; // Surface Depth Format
106 gld->cfg->stencil_bits = EVAS_GL_STENCIL_NONE; // Surface Stencil Format
107 gld->cfg->options_bits = EVAS_GL_OPTIONS_DIRECT; // Configuration options (here, no extra options)
109 gld->gl = evas_gl_new(evas_object_evas_get(gld->img));
112 MAPS_LOGE("evas_gl_new() failed");
113 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
116 gld->api = evas_gl_api_get(gld->gl);
119 MAPS_LOGE("evas_gl_api_get() failed");
120 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
123 gld->ctx = evas_gl_context_create(gld->gl, NULL);
126 MAPS_LOGE("evas_gl_context_create() failed");
127 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
130 return HERE_ERROR_NONE;
133 here_error_e HereView::InitOpenGLSurface(GLData *gld)
135 if (!gld || !gld->gl || !gld->cfg || !gld->img || !gld->ctx)
136 return HERE_ERROR_INVALID_PARAMETER;
139 evas_object_image_pixels_get_callback_set(gld->img, NULL, NULL);
143 evas_object_image_native_surface_set(gld->img, NULL);
144 evas_gl_surface_destroy(gld->gl, gld->sfc);
147 m_pImpl->w = MAX(m_pImpl->w, 1);
148 m_pImpl->h = MAX(m_pImpl->h, 1);
150 evas_object_image_size_set(gld->img, gld->w, gld->h);
152 Evas_Native_Surface ns;
153 gld->sfc = evas_gl_surface_create(gld->gl, gld->cfg, gld->w, gld->h);
156 MAPS_LOGE("evas_gl_surface_create() failed");
157 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
160 if (!evas_gl_native_surface_get(gld->gl, gld->sfc, &ns))
162 evas_gl_make_current(gld->gl, NULL, NULL);
163 evas_gl_surface_destroy(gld->gl, gld->sfc);
165 MAPS_LOGE("evas_gl_native_surface_get() faile");
166 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
169 evas_object_image_native_surface_set(gld->img, &ns);
171 evas_object_image_pixels_get_callback_set(gld->img, __pixelGetCb, this);
173 gld->isInitialized = true;
174 //MAPS_LOGD("initializing is Done!!!");
176 return HERE_ERROR_NONE;
179 here_error_e HereView::InitMap(GLData *gld, maps_plugin_map_view_ready_cb pCbFunc)
182 return HERE_ERROR_INVALID_PARAMETER;
184 gld->map = new (std::nothrow) GeoTiledMap();
187 return HERE_ERROR_OUT_OF_MEMORY;
189 gld->readyCb = pCbFunc;
191 gld->map->SetReadyMapSignal((GeoTiledMap::ReadyMapSignalFunctor)__readyCb);
193 gld->map->SetEvasGlApi(gld->api);
195 MAPS_LOGD("gld->api=%p, m_pImpl->api=%p", gld->api, m_pImpl->api);
197 gld->map->SetMapSize(Dimension(gld->w,gld->h));
199 //gld->map->SetUpdateMapSignal(RenderingCb, this);
201 m_pImpl->visualObjects.set(gld->map, evas_object_evas_get(gld->img));
203 return HERE_ERROR_NONE;
206 here_error_e HereView::Close()
210 m_pImpl->isInitialized = false;
214 m_pImpl->map->SetUpdateMapSignal(NULL);
217 m_pImpl->visualObjects.set(NULL, NULL);
221 evas_object_image_pixels_get_callback_set(m_pImpl->img, NULL, NULL);
226 ecore_idler_del(m_pImpl->idler);
227 m_pImpl->idler = NULL;
232 m_pImpl->map->SetUpdateMapSignal(NULL);
239 evas_gl_make_current(m_pImpl->gl, m_pImpl->sfc, m_pImpl->ctx);
243 evas_object_image_native_surface_set(m_pImpl->img, NULL);
244 evas_gl_surface_destroy(m_pImpl->gl, m_pImpl->sfc);
250 evas_gl_context_destroy(m_pImpl->gl, m_pImpl->ctx);
254 evas_gl_free(m_pImpl->gl);
260 evas_gl_config_free(m_pImpl->cfg);
268 return HERE_ERROR_NONE;
271 void HereView::__readyCb()
273 if (m_pImpl->readyCb)
274 m_pImpl->readyCb(m_pImpl->hView);
277 void HereView::__pixelGetCb(void *data, Evas_Object *obj)
279 if (!m_pImpl || !m_pImpl->map) return;
280 if (!m_pImpl->gl || !m_pImpl->sfc || !m_pImpl->ctx) return;
282 evas_gl_make_current(m_pImpl->gl, m_pImpl->sfc, m_pImpl->ctx);
283 m_pImpl->map->PaintMap(m_pImpl->w, m_pImpl->h);
286 void HereView::__renderingCb(void *data)
289 evas_object_image_pixels_dirty_set((Evas_Object*)data, EINA_TRUE);
292 void HereView::__setMapType()
294 /* When the theme is changed, clear cache */
295 maps_view_type_e map_type;
296 maps_view_get_type(m_pImpl->hView, &map_type);
298 bool buildings_enabled = false;
299 maps_view_get_buildings_enabled(m_pImpl->hView, &buildings_enabled);
301 bool traffic_enabled = false;
302 maps_view_get_traffic_enabled(m_pImpl->hView, &traffic_enabled);
304 bool public_transit_enabled = false;
306 GeoTiledMap::MapType hereMapType = HereUtils::Convert(map_type, buildings_enabled,
307 traffic_enabled, public_transit_enabled);
309 if (hereMapType != m_pImpl->map->GetMapType())
311 MAPS_LOGD("Clear cache, because map type is changed.");
312 m_pImpl->map->ClearCache();
313 #ifdef TIZEN_SUPPORT_TILE_FILE_CACHE
314 m_pImpl->map->ClearTileFileCache();
316 m_pImpl->map->SetMapType(hereMapType);
320 here_error_e HereView::RenderMap(const maps_coordinates_h mapsCoord, double dZoom, double dAngle)
323 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map || !m_pImpl->api)
324 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
327 return HERE_ERROR_INVALID_PARAMETER;
334 maps_view_get_screen_location(m_pImpl->hView, &x, &y, &w, &h);
335 m_pImpl->w = MAX(m_pImpl->w, 1);
336 m_pImpl->h = MAX(m_pImpl->h, 1);
338 if (x != m_pImpl->x || y != m_pImpl->y || w != m_pImpl->w || h != m_pImpl->h)
345 m_pImpl->api->glViewport(0, 0, m_pImpl->w, m_pImpl->h);
346 m_pImpl->map->SetMapSize(Dimension(m_pImpl->w,m_pImpl->h));
347 InitOpenGLSurface(m_pImpl);
351 GeoTiledMap::UpdateMapSignalFunctor callback = std::tr1::bind(&__renderingCb, m_pImpl->img);
352 m_pImpl->map->SetUpdateMapSignal(callback);
355 if (m_pImpl->map->GetZoomLevel() != dZoom)
357 m_pImpl->zoom = dZoom;
358 m_pImpl->map->SetZoomLevel(dZoom, false);
362 if (m_pImpl->angle != dAngle) {
363 m_pImpl->angle = dAngle;
364 m_pImpl->map->SetAngle(dAngle);
369 maps_coordinates_get_latitude(mapsCoord, &lat);
370 maps_coordinates_get_longitude(mapsCoord, &lng);
372 GeoCoordinates geoCoord(lat, lng);
375 m_pImpl->map->SetCenter(geoCoord);
377 return HERE_ERROR_NONE;
380 here_error_e HereView::RenderMapByArea(const maps_area_h hArea, double dZoom, double dAngle)
382 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map || !m_pImpl->map->GetRootPixmap() || !m_pImpl->api)
383 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
386 return HERE_ERROR_INVALID_PARAMETER;
388 return HERE_ERROR_NONE;
391 here_error_e HereView::MoveCenter(int delta_x, int delta_y)
393 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map || !m_pImpl->map->GetRootPixmap() || !m_pImpl->api)
394 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
396 if (delta_x == 0 && delta_y == 0)
397 return HERE_ERROR_NONE;
399 m_pImpl->map->Pan(delta_x, delta_y);
401 return HERE_ERROR_NONE;
404 here_error_e HereView::SetScalebar(bool enable)
406 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map)
407 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
409 m_pImpl->map->SetScalebar(enable);
411 return HERE_ERROR_NONE;
414 here_error_e HereView::GetScalebar(bool *enabled)
416 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map || !enabled)
417 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
419 *enabled = m_pImpl->map->GetScalebar();
420 return HERE_ERROR_NONE;
423 here_error_e HereView::DrawMap(Evas* pCanvas, int x, int y, int nWidth, int nHeight)
425 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map || !m_pImpl->map->GetRootPixmap() || !m_pImpl->api)
426 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
428 if (!pCanvas || nWidth <= 0 || nHeight <= 0)
429 return HERE_ERROR_INVALID_PARAMETER;
431 if (m_pImpl->w <= 0 || m_pImpl->h <= 0)
432 return HERE_ERROR_INVALID_PARAMETER;
434 unsigned char* srcimg_data = (unsigned char*)malloc(m_pImpl->w*m_pImpl->h*4);
436 return HERE_ERROR_OUT_OF_MEMORY;
438 Evas_Object *dstimg = evas_object_image_filled_add(pCanvas);
442 return HERE_ERROR_INVALID_OPERATION;
445 unsigned char *dstimg_data = (unsigned char *)evas_object_image_data_get(dstimg, EINA_TRUE);
449 return HERE_ERROR_INVALID_OPERATION;
455 if (m_pImpl->w < w) w = m_pImpl->w;
456 if (m_pImpl->h < h) h = m_pImpl->h;
458 m_pImpl->api->glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, srcimg_data);
461 for (int i = 0; i < h; i++)
462 memcpy(dstimg_data+(i*w), srcimg_data+(i*m_pImpl->w+x), w*4);
464 catch (std::exception &e) {
465 MAPS_LOGD("Exception caught: %s", e.what());
469 return HERE_ERROR_NONE;
472 here_error_e HereView::GetCenter(maps_coordinates_h *center)
475 return HERE_ERROR_INVALID_PARAMETER;
477 GeoCoordinates geoCoord = m_pImpl->map->GetCenter();
481 maps_coordinates_create(geoCoord.GetLatitude(), geoCoord.GetLongitude(), center);
485 maps_coordinates_set_latitude(*center, geoCoord.GetLatitude());
486 maps_coordinates_set_longitude(*center, geoCoord.GetLongitude());
489 return HERE_ERROR_NONE;
492 here_error_e HereView::ScreenToGeolocation(int x, int y, maps_coordinates_h *mapsCoord)
494 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map)
495 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
498 return HERE_ERROR_INVALID_PARAMETER;
500 Tizen::Maps::Point mapsPoint(x, y);
501 GeoCoordinates hereCoord = m_pImpl->map->ScreenPositionToCoordinate(mapsPoint);
502 double lat = hereCoord.GetLatitude();
503 double lng = hereCoord.GetLongitude();
506 int error = maps_coordinates_create(lat, lng, mapsCoord);
507 if (error != MAPS_ERROR_NONE)
508 return (here_error_e)ConvertToHereError(error);
510 maps_coordinates_h __mapsCoord;
511 int error = maps_coordinates_create(lat, lng, &__mapsCoord);
512 if (error != MAPS_ERROR_NONE)
513 return (here_error_e)ConvertToHereError(error);
516 /* maps_coord is already allocated in heap memory */
517 maps_coordinates_get_latitude(__mapsCoord, &lat);
518 maps_coordinates_get_longitude(__mapsCoord, &lng);
519 maps_coordinates_set_latitude(*mapsCoord, lat);
520 maps_coordinates_set_longitude(*mapsCoord, lng);
522 /* maps_coord is not allocated yet */
523 maps_coordinates_clone(__mapsCoord, mapsCoord);
525 maps_coordinates_destroy(__mapsCoord);
528 return HERE_ERROR_NONE;
531 here_error_e HereView::GeolocationToScreen(const maps_coordinates_h mapsCoord, int *x, int *y)
533 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map)
534 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
537 return HERE_ERROR_INVALID_PARAMETER;
540 maps_coordinates_get_latitude(mapsCoord, &lat);
541 maps_coordinates_get_longitude(mapsCoord, &lng);
542 GeoCoordinates hereCoord(lat, lng);
543 Tizen::Maps::Point mapsPoint = m_pImpl->map->CoordinateToScreenPosition(hereCoord);
548 return HERE_ERROR_NONE;
551 here_error_e HereView::GetMinZoomLevel(int *nMinZoomLevel)
553 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map)
554 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
557 return HERE_ERROR_INVALID_PARAMETER;
559 *nMinZoomLevel = (int)m_pImpl->map->GetMinimumZoomLevel();
561 return HERE_ERROR_NONE;
564 here_error_e HereView::GetMaxZoomLevel(int *nMaxZoomLevel)
566 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map)
567 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
570 return HERE_ERROR_INVALID_PARAMETER;
572 *nMaxZoomLevel = (int)m_pImpl->map->GetMaximumZoomLevel();
574 return HERE_ERROR_NONE;
577 here_error_e HereView::OnViewObject(const maps_view_object_h object, maps_view_object_operation_e operation)
579 if (!m_pImpl || !m_pImpl->isInitialized || !m_pImpl->map)
580 return HERE_ERROR_SERVICE_NOT_AVAILABLE;
582 if (!object || operation < MAPS_VIEW_OBJECT_ADD || operation > MAPS_VIEW_OBJECT_REMOVE)
583 return HERE_ERROR_INVALID_PARAMETER;
585 if (m_pImpl->map->GetRootPixmap())
586 __processViewObject(object, operation);
588 m_pImpl->pendingObjects.push_back(std::make_pair(object, operation));
590 return HERE_ERROR_NONE;
593 Eina_Bool HereView::__idlerCb(void *data)
595 GLData *pImpl = (GLData*)data;
597 if (!pImpl || !pImpl->map || !pImpl->map->GetRootPixmap()) return true;
599 while (pImpl->pendingObjects.size())
601 PendingObject pending = pImpl->pendingObjects.front();
602 pImpl->pendingObjects.pop_front();
603 maps_view_object_h object = pending.first;
604 maps_view_object_operation_e operation = pending.second;
606 __processViewObject(object, operation);
612 void HereView::__processViewObject(const maps_view_object_h object, maps_view_object_operation_e operation)
614 maps_view_object_type_e type;
615 maps_view_object_get_type(object, &type);
617 if (type < MAPS_VIEW_OBJECT_POLYLINE || type > MAPS_VIEW_OBJECT_MARKER) return;
618 if (operation < MAPS_VIEW_OBJECT_ADD || operation > MAPS_VIEW_OBJECT_REMOVE) return;
620 const char *oper_str[20] = { "ADD", "SET_VISIBLE", "MOVE", "CHANGE", "REMOVE"};
621 const char *type_str[20] = { "POLYLINE", "POLYGON", "MARKER", "ROUTE", "UNKNOWN"};
623 MAPS_LOGD("type=%s, operation=%s, object=%p",
624 (type >= MAPS_VIEW_OBJECT_POLYLINE && type <= MAPS_VIEW_OBJECT_MARKER) ? type_str[type] : "?",
625 (operation >= MAPS_VIEW_OBJECT_ADD && operation <= MAPS_VIEW_OBJECT_REMOVE) ? oper_str[operation] : "?",
630 case MAPS_VIEW_OBJECT_ADD: m_pImpl->visualObjects.add(object); break;
631 case MAPS_VIEW_OBJECT_SET_VISIBLE: m_pImpl->visualObjects.setVisible(object); break;
632 case MAPS_VIEW_OBJECT_CHANGE: m_pImpl->visualObjects.update(object); break;
633 case MAPS_VIEW_OBJECT_REMOVE: m_pImpl->visualObjects.remove(object); break;
638 HERE_PLUGIN_END_NAMESPACE