189cba8b0efa1b6f2877cb05631ea4b2428cecf5
[platform/core/location/maps-plugin-here.git] / src / here_view_objects.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "here_view_objects.h"
18 #include "here_utils.h"
19
20 #include <graphic/Grp_Util.h>
21 #include <maps/GeoMapObjectMarker.h>
22 #include <maps/GeoMapObjectPolygon.h>
23 #include <maps/GeoMapObjectPolyline.h>
24
25
26 using namespace HERE_PLUGIN_NAMESPACE_PREFIX;
27
28 HERE_PLUGIN_BEGIN_NAMESPACE
29
30 HereViewObjects::HereViewObjects()
31 {
32         pthread_mutex_init(&__mutex, NULL);
33 }
34
35 HereViewObjects::~HereViewObjects()
36 {
37         pthread_mutex_destroy(&__mutex);
38 }
39
40 void HereViewObjects::set(GeoTiledMap *map, Evas *evas)
41 {
42         if (!map && !evas) removeAll();
43         __map = map;
44         __evas = evas;
45 }
46
47 here_error_e HereViewObjects::add(maps_view_object_h hObj)
48 {
49         if (!hObj) return HERE_ERROR_INVALID_PARAMETER;
50
51         here_error_e error = HERE_ERROR_INVALID_PARAMETER;
52         if (__currentObjects.find(hObj) == __currentObjects.end())
53                 error = __add(hObj);
54
55         if (error == HERE_ERROR_NONE) __invalidate(hObj);
56         return error;
57 }
58
59 here_error_e HereViewObjects::__add(maps_view_object_h hObj)
60 {
61         if (!hObj) return HERE_ERROR_INVALID_PARAMETER;
62         if (!__map) return HERE_ERROR_INVALID_OPERATION;
63
64         here_error_e error = HERE_ERROR_NONE;
65         GeoMapObject *hereObject = NULL;
66         maps_view_object_type_e type;
67         maps_view_object_get_type(hObj, &type);
68
69         switch(type)
70         {
71         case MAPS_VIEW_OBJECT_MARKER:
72                 hereObject = new (std::nothrow) GeoMapObjectMarker;
73                 error = __updateMarker(hObj, (GeoMapObjectMarker*)hereObject);
74                 break;
75
76         case MAPS_VIEW_OBJECT_POLYGON:
77                 hereObject = new (std::nothrow) GeoMapObjectPolygon;
78                 error = __updatePolygon(hObj, (GeoMapObjectPolygon*)hereObject);
79                 break;
80
81         case MAPS_VIEW_OBJECT_POLYLINE:
82                 hereObject = new (std::nothrow) GeoMapObjectPolyline;
83                 error = __updatePolyline(hObj, (GeoMapObjectPolyline*)hereObject);
84                 break;
85 #ifdef TIZEN_3_0_NEXT_MS
86         case MAPS_VIEW_OBJECT_ROUTE:
87                 for (int i=0; i < 2; i++)
88                 {
89                         hereObject = new (std::nothrow) GeoMapObjectPolyline;
90                         if (hereObject)
91                         {
92                                 __map->AddObject(hereObject);
93                                 error = __updateRoute(hObj);
94                                 if (error != HERE_ERROR_NONE) break;
95                                 pthread_mutex_lock(&__mutex);
96                                 __currentObjects.insert(std::make_pair(hObj, (GeoMapObjectPolyline*)hereObject));
97                                 pthread_mutex_unlock(&__mutex);
98                         }
99
100                         hereObject = new (std::nothrow) GeoMapObjectMarker;
101                         if (hereObject)
102                         {
103                                 __map->AddObject(hereObject);
104                                 error = __updateRoute(hObj);
105                                 if (error != HERE_ERROR_NONE) break;
106                                 pthread_mutex_lock(&__mutex);
107                                 __currentObjects.insert(std::make_pair(hObj, (GeoMapObjectMarker*)hereObject));
108                                 pthread_mutex_unlock(&__mutex);
109                         }
110                 }
111                 break;
112 #endif /* TIZEN_3_0_NEXT_MS */
113         default:
114                 error = HERE_ERROR_INVALID_PARAMETER;
115                 break;
116         }
117
118         if (error != HERE_ERROR_NONE)
119         {
120                 if (hereObject) delete hereObject;
121                 hereObject = NULL;
122         }
123
124 #ifdef TIZEN_3_0_NEXT_MS
125         if (hereObject && type != MAPS_VIEW_OBJECT_ROUTE)
126 #else
127         if (hereObject)
128 #endif /* TIZEN_3_0_NEXT_MS */
129         {
130                 __map->AddObject(hereObject);
131                 pthread_mutex_lock(&__mutex);
132                 __currentObjects.insert(std::make_pair(hObj, hereObject));
133                 pthread_mutex_unlock(&__mutex);
134         }
135
136         return error;
137 }
138
139 here_error_e HereViewObjects::remove(maps_view_object_h hObj)
140 {
141         here_error_e error = __remove(hObj);
142         if (error == HERE_ERROR_NONE) __invalidate(hObj);
143         return error;
144 }
145
146 here_error_e HereViewObjects::__remove(maps_view_object_h hObj)
147 {
148         if (!hObj) return HERE_ERROR_INVALID_PARAMETER;
149         if (!__map) return HERE_ERROR_INVALID_OPERATION;
150
151         here_error_e error = HERE_ERROR_NOT_FOUND;
152
153         VisualObjects::iterator it;
154         pthread_mutex_lock(&__mutex);
155         while ((it = __currentObjects.find(hObj)) != __currentObjects.end())
156         {
157                 __map->RemoveObject((GeoMapObject*)it->second);
158                 it = __currentObjects.erase(it);
159                 error = HERE_ERROR_NONE;
160         }
161         pthread_mutex_unlock(&__mutex);
162
163         return error;
164 }
165
166 here_error_e HereViewObjects::removeAll()
167 {
168         pthread_mutex_lock(&__mutex);
169         __currentObjects.clear();
170         __map->ClearMapObjects();
171         pthread_mutex_unlock(&__mutex);
172         __invalidate();
173
174         return HERE_ERROR_NONE;
175 }
176
177 here_error_e HereViewObjects::move(maps_view_object_h hObj)
178 {
179         if (!hObj) return HERE_ERROR_INVALID_PARAMETER;
180
181         VisualObjects::iterator it;
182         while ((it = __currentObjects.find(hObj)) != __currentObjects.end())
183         {
184                 MAPS_LOGD("TODO: implement moving");
185         }
186
187         return HERE_ERROR_NONE;
188 }
189
190 here_error_e HereViewObjects::update(maps_view_object_h hObj)
191 {
192         if (!hObj) return HERE_ERROR_INVALID_PARAMETER;
193
194         here_error_e error = HERE_ERROR_NOT_FOUND;
195
196         VisualObjects::iterator it = __currentObjects.find(hObj);
197         if (it != __currentObjects.end())
198                 error = __update(hObj, (GeoMapObject*)(it->second));
199
200         if (error == HERE_ERROR_NONE) __invalidate(hObj);
201         return error;
202 }
203
204 here_error_e HereViewObjects::__update(maps_view_object_h hObj, GeoMapObject *hereObject)
205 {
206         if (!hObj) return HERE_ERROR_INVALID_PARAMETER;
207
208         here_error_e error = HERE_ERROR_UNKNOWN;
209
210         do {
211                 maps_view_object_type_e type;
212                 maps_view_object_get_type(hObj, &type);
213
214                 switch(type)
215                 {
216                 case MAPS_VIEW_OBJECT_MARKER:
217                         error = __updateMarker(hObj, (GeoMapObjectMarker*)hereObject);
218                         break;
219
220                 case MAPS_VIEW_OBJECT_POLYGON:
221                         error = __updatePolygon(hObj, (GeoMapObjectPolygon*)hereObject);
222                         break;
223
224                 case MAPS_VIEW_OBJECT_POLYLINE:
225                         error = __updatePolyline(hObj, (GeoMapObjectPolyline*)hereObject);
226                         break;
227
228 #ifdef TIZEN_3_0_NEXT_MS
229                 case MAPS_VIEW_OBJECT_ROUTE:
230                         error = __updateRoute(hObj);
231                         break;
232 #endif /* TIZEN_3_0_NEXT_MS */
233
234                 default:
235                         break;
236                 }
237         } while(0);
238
239         return error;
240 }
241
242 here_error_e HereViewObjects::__updateMarker(maps_view_object_h hMarker, GeoMapObjectMarker *hereMarker)
243 {
244         if (!hMarker || !hereMarker)
245                 return HERE_ERROR_INVALID_PARAMETER;
246
247         if (!__evas || !__map)
248                 return HERE_ERROR_INVALID_OPERATION;
249
250
251         int error = MAPS_ERROR_NONE;
252         maps_view_marker_type_e type;
253         int nSize = 0, w, h;
254         char *szPath = NULL;
255         double lat, lng;
256         maps_coordinates_h mapsCoord;
257         Evas_Object *img = NULL;
258
259
260         do {
261                 /* image */
262                 error = maps_view_object_marker_get_type(hMarker, &type);
263                 if (error != MAPS_ERROR_NONE || type < MAPS_VIEW_MARKER_PIN || type > MAPS_VIEW_MARKER_STICKER) break;
264
265                 error = maps_view_object_marker_get_image_file(hMarker, &szPath);
266                 if (error != MAPS_ERROR_NONE || !szPath) break;
267
268                 img = evas_object_image_add(__evas);
269                 evas_object_image_file_set(img, szPath, NULL);
270                 int err = evas_object_image_load_error_get(img);
271
272                 if (err != EVAS_LOAD_ERROR_NONE)
273                 {
274                         MAPS_LOGE("Failed to load the image file for new marker. '%s'",
275                                 (szPath ? szPath : "null"));
276                         g_free(szPath);
277                         break;
278                 }
279                 g_free(szPath);
280
281                 evas_object_image_size_get(img, &w, &h);
282                 nSize = w * h * 4;
283
284                 unsigned char *src = (unsigned char*)evas_object_image_data_get(img, EINA_FALSE);
285                 if (!src || nSize <= 0) {
286                         MAPS_LOGE("Failed to get the image buffer of new marker");
287                         error = MAPS_ERROR_OUT_OF_MEMORY;
288                         break;
289                 }
290
291                 unsigned char *dst = (unsigned char*)malloc(nSize);
292                 if (!dst) {
293                         error = MAPS_ERROR_OUT_OF_MEMORY;
294                         break;
295                 }
296                 memcpy(dst, src, nSize);
297
298                 /* resize the marker image */
299                 int nw = 0, nh = 0;
300                 if (__resizeMarker(hMarker, w, h, &nw, &nh, &dst))
301                 {
302                         w = nw;
303                         h = nh;
304                         nSize = w * h * 4;
305                         maps_view_object_marker_set_size(hMarker, w, h);
306                 }
307
308                 /* convert RGBA to BGRA for GL */
309                 _Util::ConvertRGBA2BGRA(dst, (unsigned)w, (unsigned)h);
310
311                 Bitmap bmp;
312                 bmp.Construct((const unsigned char*)dst, nSize, Dimension(w, h));
313                 hereMarker->SetBitmap(bmp);
314                 g_free(dst);
315
316
317                 /* position */
318                 maps_view_object_marker_get_coordinates(hMarker, &mapsCoord);
319                 maps_coordinates_get_latitude(mapsCoord, &lat);
320                 maps_coordinates_get_longitude(mapsCoord, &lng);
321                 maps_coordinates_destroy(mapsCoord);
322
323                 if (!HereUtils::IsValidCoord(lat, lng))
324                 {
325                         error = MAPS_ERROR_INVALID_PARAMETER;
326                         break;
327                 }
328
329                 hereMarker->SetPosition(GeoCoordinates(lat, lng));
330
331                 /* origin */
332                 Tizen::Maps::FloatPoint fpntOrigin(0.5, 0.5);
333                 if (type == MAPS_VIEW_MARKER_PIN)
334                         fpntOrigin.y = 1.0;
335                 hereMarker->SetMarkerOrigin(fpntOrigin);
336
337                 /* z-order */
338                 int z_order = 0;
339                 maps_view_object_marker_get_z_order(hMarker, &z_order);
340                 hereMarker->SetZorder(z_order);
341         } while(0);
342
343         if (img) evas_object_del(img);
344         return (here_error_e)ConvertToHereError(error);
345 }
346
347 here_error_e HereViewObjects::__updatePolyline(maps_view_object_h hPolyline, GeoMapObjectPolyline *herePolyline)
348 {
349         if (!hPolyline || !herePolyline)
350                 return HERE_ERROR_INVALID_PARAMETER;
351
352         int error = MAPS_ERROR_NONE;
353         GeoCoordinateList coordList;
354         unsigned char r, g, b, a;
355         int nThickness;
356
357         do {
358                 error = maps_view_object_polyline_foreach_point(hPolyline, __foreachForCoordinates, &coordList);
359                 if (error != MAPS_ERROR_NONE) break;
360                 herePolyline->SetPath(coordList);
361
362                 error = maps_view_object_polyline_get_color(hPolyline, &r, &g, &b, &a);
363                 if (error != MAPS_ERROR_NONE) break;
364                 herePolyline->SetStrokeColor(Color(r, g, b, a));
365
366                 error = maps_view_object_polyline_get_width(hPolyline, &nThickness);
367                 if (error != MAPS_ERROR_NONE) break;
368                 herePolyline->SetStrokeThickness(nThickness);
369         } while(0);
370
371         return (here_error_e)ConvertToHereError(error);
372 }
373
374 here_error_e HereViewObjects::__updatePolygon(maps_view_object_h hPolygon, GeoMapObjectPolygon *herePolygon)
375 {
376         if (!hPolygon || !herePolygon)
377                 return HERE_ERROR_INVALID_PARAMETER;
378
379         int error = MAPS_ERROR_NONE;
380         GeoCoordinateList coordList;
381         unsigned char r, g, b, a;
382
383         do {
384                 error = maps_view_object_polygon_foreach_point(hPolygon, __foreachForCoordinates, &coordList);
385                 if (error != MAPS_ERROR_NONE) break;
386                 herePolygon->SetPath(coordList);
387
388                 error = maps_view_object_polygon_get_fill_color(hPolygon, &r, &g, &b, &a);
389                 if (error != MAPS_ERROR_NONE) break;
390                 herePolygon->SetFillColor(Color(r, g, b, a));
391         } while(0);
392
393         return (here_error_e)ConvertToHereError(error);
394 }
395
396 here_error_e HereViewObjects::__updateRoute(maps_view_object_h hRoute)
397 {
398 #ifdef TIZEN_3_0_NEXT_MS
399         if (!hRoute) return HERE_ERROR_INVALID_PARAMETER;
400
401         VisualObjects::iterator it;
402
403         if ((it = __currentObjects.find(hRoute)) != __currentObjects.end())
404         {
405                 maps_route_h route = NULL;
406                 int ret = maps_view_object_route_get_content(hRoute, &route);
407                 if (ret !=  MAPS_ERROR_NONE || !route)
408                         return HERE_ERROR_NONE;
409
410                 GeoCoordinateList coordList;
411                 GeoMapObjectPolyline *polyline_path = NULL, *polyline_seg = NULL;
412
413                 if (it->second->GetType() == GeoMapObject::GMO_Polyline)
414                 {
415                         if (!polyline_path)
416                         {
417                                 MAPS_LOGD("Route Path");
418                                 polyline_path = (GeoMapObjectPolyline*)it->second;
419                                 maps_route_foreach_path(route, __foreachForCoordinates, &coordList);
420                                 polyline_path->SetPath(coordList);
421                                 polyline_path->SetStrokeColor(Tizen::Maps::Color(255, 0, 0, 255));
422                                 polyline_path->SetStrokeThickness(3);
423                         }
424                         else if (!polyline_seg)
425                         {
426                                 MAPS_LOGD("Route Segments");
427                                 polyline_seg = (GeoMapObjectPolyline*)it->second;
428                                 maps_route_foreach_path(route, __foreachForCoordinates, &coordList);
429                                 polyline_seg->SetPath(coordList);
430                                 polyline_seg->SetStrokeColor(Tizen::Maps::Color(0, 255, 0, 255));
431                                 polyline_seg->SetStrokeThickness(3);
432                         }
433                 }
434                 else if (it->second->GetType() == GeoMapObject::GMO_Marker)
435                 {
436                         // to implement
437                 }
438                 maps_route_destroy(route);
439         }
440
441 #endif /* TIZEN_3_0_NEXT_MS */
442         return HERE_ERROR_NONE;
443 }
444
445 here_error_e HereViewObjects::setVisible(maps_view_object_h hObj)
446 {
447         if (!hObj) return HERE_ERROR_INVALID_PARAMETER;
448
449         bool visible;
450         maps_view_object_get_visible(hObj, &visible);
451         return __setVisible(hObj, visible);
452 }
453
454 here_error_e HereViewObjects::__setVisible(maps_view_object_h hObj, bool bVisible)
455 {
456         if (!hObj) return HERE_ERROR_INVALID_PARAMETER;
457
458         here_error_e error = HERE_ERROR_NOT_FOUND;
459
460         VisualObjects::iterator it;
461         for (it = __currentObjects.begin(); it != __currentObjects.end(); it++)
462         {
463                 if (it->first == hObj)
464                 {
465                         ((GeoMapObject*)it->second)->SetVisible(bVisible);
466                         error = HERE_ERROR_NONE;
467                 }
468         }
469
470         if (error == HERE_ERROR_NONE) __invalidate(hObj);
471         return error;
472 }
473
474 bool HereViewObjects::__foreachForCoordinates(int index, maps_coordinates_h point, void *user_data)
475 {
476         if (!point || !user_data)
477                 return false;
478
479         if (!HereUtils::IsValid(*(maps_coordinates_s*)point))
480         {
481                 return false;
482         }
483
484         int error;
485         double lat = 0.0, lng = 0.0;
486
487         do {
488                 error = maps_coordinates_get_latitude(point, &lat);
489                 if (error != MAPS_ERROR_NONE) break;
490
491                 error = maps_coordinates_get_longitude(point, &lng);
492                 if (error != MAPS_ERROR_NONE) break;
493         } while(0);
494
495         MAPS_LOGD("[%d] %f,%f", index+1, lat, lng);
496
497         GeoCoordinateList *coordList = (GeoCoordinateList*)user_data;
498         coordList->push_back(GeoCoordinates(lat, lng));
499         return true;
500 }
501
502 bool HereViewObjects::__foreachForAddingGroupObjects(int index, int total, maps_view_object_h object, void *user_data)
503 {
504         if (!user_data) return false;
505
506         HereViewObjects *hereViewObjects = (HereViewObjects*)user_data;
507         here_error_e error = hereViewObjects->add(object);
508         return (error == HERE_ERROR_NONE);
509 }
510
511 bool HereViewObjects::__foreachForRemovingGroupObjects(int index, int total, maps_view_object_h object, void *user_data)
512 {
513         if (!user_data) return false;
514
515         HereViewObjects *hereViewObjects = (HereViewObjects*)user_data;
516         here_error_e error = hereViewObjects->remove(object);
517         return (error == HERE_ERROR_NONE);
518 }
519
520 bool HereViewObjects::__foreachForUpdatingGroupObjects(int index, int total, maps_view_object_h object, void *user_data)
521 {
522         if (!user_data) return false;
523
524         HereViewObjects *hereViewObjects = (HereViewObjects*)user_data;
525         here_error_e error = hereViewObjects->update(object);
526         return (error == HERE_ERROR_NONE);
527 }
528
529 bool HereViewObjects::__foreachForSettingVisibleGroupObjects(int index, int total, maps_view_object_h object, void *user_data)
530 {
531         if (!user_data) return false;
532
533         HereViewObjects *hereViewObjects = (HereViewObjects*)user_data;
534         here_error_e error = hereViewObjects->setVisible(object);
535         return (error == HERE_ERROR_NONE);
536 }
537
538 bool HereViewObjects::__resizeMarker(maps_view_object_h hMarker,
539                                         const int originWidth, const int originHeight,
540                                         int *newWidth, int *newHeight, unsigned char **bitmap)
541 {
542         if (!hMarker || !newWidth || !newHeight || !bitmap || !*bitmap)
543                 return false;
544
545         int resizedWidth = 0, resizedHeight = 0;
546         maps_view_object_marker_get_size(hMarker, &resizedWidth, &resizedHeight);
547
548         if (__resizeBitmap(bitmap, originWidth, originHeight, resizedWidth, resizedHeight))
549         {
550                 *newWidth = resizedWidth;
551                 *newHeight = resizedHeight;
552                 return true;
553         }
554         return false;
555 }
556
557 bool HereViewObjects::__resizeBitmap(unsigned char **curBmp, int curWidth, int curHeight, int newWidth, int newHeight)
558 {
559         if (!curBmp || curWidth <= 0 || curHeight <= 0 || newWidth <= 0 || newHeight <= 0) return false;
560         if (curWidth == newWidth && curHeight == newHeight) return false;
561
562         unsigned char* newBmp = new unsigned char[newWidth * newHeight * 4];
563
564         double scaleWidth =  (double)newWidth / (double)curWidth;
565         double scaleHeight = (double)newHeight / (double)curHeight;
566
567         int newPixel, curPixel;
568
569         for(int y = 0; y < newHeight; y++)
570         {
571             for(int x = 0; x < newWidth; x++)
572             {
573                 newPixel = (y * (newWidth *4)) + (x * 4);
574                 curPixel = (((int)(y / scaleHeight) * (curWidth * 4)) + ((int)(x / scaleWidth) * 4));
575
576                 newBmp[newPixel    ] =  (*curBmp)[curPixel    ];
577                 newBmp[newPixel + 1] =  (*curBmp)[curPixel + 1];
578                 newBmp[newPixel + 2] =  (*curBmp)[curPixel + 2];
579                 newBmp[newPixel + 3] =  (*curBmp)[curPixel + 3];
580             }
581         }
582
583         delete [] *curBmp;
584         *curBmp = newBmp;
585         return true;
586 }
587
588 void HereViewObjects::__invalidate(maps_view_object_h hObj)
589 {
590         maps_view_object_type_e type;
591         maps_view_object_get_type(hObj, &type);
592
593         if (!hObj || type != MAPS_VIEW_OBJECT_MARKER)
594                 __map->InvalidateMapObjects();
595         else
596                 __map->InvalidateMapMarkers();
597 }
598
599 HERE_PLUGIN_END_NAMESPACE