Adjust the position of the partial Frame
[platform/framework/native/uifw.git] / src / app / FApp_AppResourceBitmapUtil.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FApp_AppResourceBitmapUtil.cpp
20  * @brief       This is the implementation for the _AppResourceBitmapUtil class.
21  */
22
23 #include <unique_ptr.h>
24
25 #include <FAppPkgPackageInfo.h>
26 #include <FBaseSysLog.h>
27 #include <FBaseByteBuffer.h>
28 #include <FMediaImageTypes.h>
29 #include <FMedia_ImageDecoder.h>
30 #include <FSys_SystemInfoImpl.h>
31 #include <FUi_ControlManager.h>
32 #include <FUi_CoordinateSystemUtils.h>
33
34 #include "FApp_AppInfo.h"
35 #include "FAppPkg_PackageInfoImpl.h"
36 #include "FApp_AppResourceBitmapUtil.h"
37
38 using namespace Tizen::App::Package;
39 using namespace Tizen::Base;
40 using namespace Tizen::Graphics;
41 using namespace Tizen::Io;
42 using namespace Tizen::Media;
43 using namespace Tizen::Ui;
44
45 namespace // unnamed
46 {
47 MediaPixelFormat
48 ConvertBitmapPixelFormatToMediaPixelFormat(BitmapPixelFormat format)
49 {
50         MediaPixelFormat out = MEDIA_PIXEL_FORMAT_NONE;
51         switch (format)
52         {
53         case BITMAP_PIXEL_FORMAT_RGB565:
54                 out = MEDIA_PIXEL_FORMAT_RGB565LE;
55                 break;
56         case BITMAP_PIXEL_FORMAT_ARGB8888:
57                 out = MEDIA_PIXEL_FORMAT_BGRA8888;
58                 break;
59         case BITMAP_PIXEL_FORMAT_R8G8B8A8:
60                 out = MEDIA_PIXEL_FORMAT_RGBA8888;
61                 break;
62         default:
63                 break;
64         }
65         return out;
66 }} // unnamed namespace
67
68 namespace Tizen { namespace Graphics
69 {
70 result
71 _CreateCoordinateTransformer(_ICoordinateSystemTransformer*& pTransformer, int srcResolution, _BaseScreenSize srcBaseScreenSize, Dimension destResolution, _BaseScreenSize destBaseScreenSize);
72 }} // Tizen::Graphics
73
74 namespace Tizen { namespace App
75 {
76
77 _AppResourceBitmapUtil::_AppResourceBitmapUtil(void)
78         : __physicalResolutionDim(0, 0)
79         , __physicalBaseScreenSize(BASE_SCREEN_SIZE_DEFAULT)
80         , __resolutionDirectories(L"")
81         , __sortedDensityDirectories()
82 {
83         for (int i = 0; i < DENSITY_MAX; i++)
84         {
85                 __sortedDensity[i] = DENSITY_NONE;
86         }
87         __physicalResolutionDim = _CoordinateSystem::GetInstance()->GetPhysicalResolutionDim();
88         __physicalBaseScreenSize = _CoordinateSystem::GetInstance()->GetPhysicalBaseScreenSize();
89 }
90
91 _AppResourceBitmapUtil::~_AppResourceBitmapUtil(void)
92 {
93 }
94
95 _AppResourceBitmapUtil*
96 _AppResourceBitmapUtil::GetInstanceN(int type, const String& value)
97 {
98         String resourceFolder(L"");
99         Tizen::App::_AppResourceBitmapUtil::AppResourceBy appResourceType = _AppResourceBitmapUtil::APP_RESOURCE_DEFAULT;
100
101         switch(type)
102         {
103         case _AppResourceBitmapUtil::APP_RESOURCE_BITMAP:
104                 appResourceType = _AppResourceBitmapUtil::APP_RESOURCE_BITMAP;
105                 break;
106         case _AppResourceBitmapUtil::APP_RESOURCE_DEFAULT:
107                 //fall through
108         case _AppResourceBitmapUtil::APP_RESOURCE_BY_LIBRARY_NAME:
109                 //fall through
110         default:
111                 resourceFolder = _AppInfo::GetAppRootPath();
112                 resourceFolder.Append(L"res/");
113                 if (!value.IsEmpty())
114                 {
115                         resourceFolder.Append(value);
116                         resourceFolder.Append(L'/');
117                 }
118                 break;
119         case _AppResourceBitmapUtil::APP_RESOURCE_BY_APP_ID:
120                 std::unique_ptr< PackageInfo> pPkgInfo(_PackageManagerImpl::GetInstance()->GetPackageInfoN(value));
121                 SysTryReturn(NID_APP, pPkgInfo != null, null, E_APP_NOT_INSTALLED, "[E_APP_NOT_INSTALLED] Failed to get the package info.");
122
123                 _PackageInfoImpl* pPkgInfoImpl = _PackageInfoImpl::GetInstance(pPkgInfo.get());
124                 SysTryReturn(NID_APP, pPkgInfoImpl != null, null, E_APP_NOT_INSTALLED, "[E_APP_NOT_INSTALLED] Failed to get the package info impl.");
125
126                 resourceFolder = pPkgInfoImpl->GetAppRootPath();
127                 resourceFolder.Append(L"/res/");
128                 break;
129         }
130
131         std::unique_ptr< _AppResourceBitmapUtil > pAppResourceBitmapUtil(new (std::nothrow) _AppResourceBitmapUtil());
132         SysTryReturn(NID_APP, pAppResourceBitmapUtil != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient." );
133
134         pAppResourceBitmapUtil->__resourceType = appResourceType;
135
136         result r = pAppResourceBitmapUtil->Construct(resourceFolder);
137         SysTryReturn(NID_APP, r == E_SUCCESS, null, r, "[%s] Failed to construct _AppResourceBitmapUtil.", GetErrorMessage(r));
138
139         return pAppResourceBitmapUtil.release();
140 }
141
142 result
143 _AppResourceBitmapUtil::Construct(const String& resourceFolder)
144 {
145         if (__resourceType == _AppResourceBitmapUtil::APP_RESOURCE_BITMAP)
146         {
147                 SysLog(NID_APP, "This is a BitmapUtil for getting a non-scaling bitmap resource");
148                 return E_SUCCESS;
149         }
150
151         int deviceDPI = 0;
152         result r = Tizen::System::_SystemInfoImpl::GetSysInfo(L"http://tizen.org/feature/screen.dpi", deviceDPI);
153         SysTryReturnResult(NID_APP, r == E_SUCCESS, r, "[%s] Failed to get Screen DPI", GetErrorMessage(r));
154
155         // 1. Get directory path matched device's resolution (e.g.720x1280)
156         if (GetDirectoryPath(resourceFolder, DENSITY_NONE, __resolutionDirectories) == false)
157         {
158                 __resolutionDirectories = L"";
159                 SysLog(NID_APP, "Failed to get a Device Resolution Directory path");
160         }
161
162         // 2. Get screen density & directory path matched device's DPI (e.g.screen-density-xhigh)
163         if (deviceDPI >= DPI_FOR_XHIGH)
164         {
165                 __sortedDensity[0] = DENSITY_XHIGH;
166         }
167         else if (deviceDPI >= DPI_FOR_HIGH)
168         {
169                 __sortedDensity[0] = DENSITY_HIGH;
170         }
171         else if (deviceDPI >= DPI_FOR_MIDDLE)
172         {
173                 __sortedDensity[0] = DENSITY_MIDDLE;
174         }
175         else if (deviceDPI < DPI_FOR_MIDDLE && deviceDPI >= DPI_FOR_LOW)
176         {
177                 __sortedDensity[0] = DENSITY_LOW;
178         }
179         else
180         {
181                 __sortedDensity[0] = DENSITY_XHIGH;
182                 SysLog(NID_APP, "Failed to get a Device Density (DPI = %d)", deviceDPI);
183         }
184
185         if (GetDirectoryPath(resourceFolder, __sortedDensity[0], __sortedDensityDirectories[0]) == false)
186         {
187                 __sortedDensityDirectories[0] = L"";
188                 SysLog(NID_APP, "Failed to get a Device Density Directory path");
189         }
190
191         // 3. Get screen density & directory path with fall back system (XHIGH-HIGH-MIDDLE-LOW)
192         int densityIndex = 1;
193
194         for (int currentDensity = DENSITY_XHIGH; currentDensity >= DENSITY_LOW; currentDensity--)
195         {
196                 SysAssert(densityIndex > DENSITY_NONE && densityIndex < DENSITY_MAX);
197
198                 if (static_cast<int>(__sortedDensity[0]) == currentDensity)
199                 {
200                         continue;
201                 }
202
203                 __sortedDensity[densityIndex] = static_cast<_Density>(currentDensity);
204
205                 if (GetDirectoryPath(resourceFolder, __sortedDensity[densityIndex], __sortedDensityDirectories[densityIndex]) == false)
206                 {
207                         __sortedDensityDirectories[densityIndex] = L"";
208                         SysLog(NID_APP, "Failed to get a %dth Fall-Back Directory path", densityIndex);
209                 }
210
211                 densityIndex++;
212         }
213
214         return r;
215 }
216
217 // Get Resource DirectoryPath
218 bool
219 _AppResourceBitmapUtil::GetDirectoryPath(const String& homePath, const _Density resourceDirectory, String& dirPath) const
220 {
221         switch (resourceDirectory)
222         {
223         case DENSITY_NONE:
224                 switch (__physicalResolutionDim.width)
225                 {
226                 case 720:
227                         dirPath = L"720x1280";
228                         break;
229
230                 case 480:
231                         dirPath = L"480x800";
232                         break;
233
234                 case 240:
235                         dirPath = L"240x400";
236                         break;
237
238                 case 320:
239                         dirPath = L"320x480";
240                         break;
241
242                 default:
243                         break;
244                 }
245                 break;
246
247         case DENSITY_XHIGH:
248                 dirPath = L"screen-density-xhigh";
249                 break;
250
251         case DENSITY_HIGH:
252                 dirPath = L"screen-density-high";
253                 break;
254
255         case DENSITY_MIDDLE:
256                 dirPath = L"screen-density-middle";
257                 break;
258
259         case DENSITY_LOW:
260                 dirPath = L"screen-density-low";
261                 break;
262
263         default:
264                 dirPath = L'\0';
265                 return false;
266         }
267
268         result r = dirPath.Insert(homePath, 0);
269         SysTryReturn(NID_APP, r == E_SUCCESS, false, r, "[%s] Failed to insert string.", GetErrorMessage(r));
270
271         if ( File::IsFileExist(dirPath) == false )
272         {
273                 dirPath = L'\0';
274                 return false;
275         }
276         return true;
277 }
278
279 // Get Resource File Path
280 bool
281 _AppResourceBitmapUtil::GetFilePath(const String& directoryPath, const String& fileName, String& filePath) const
282 {
283         if (directoryPath == L"")
284         {
285                 filePath = L"";
286                 return false;
287         }
288
289         const String& normalizedPseudoPath = NormalizePath(fileName);
290         SysAssert(normalizedPseudoPath.StartsWith(L"/", 0));
291
292         filePath = directoryPath + normalizedPseudoPath;
293         return true;
294 }
295
296 // Normalizing Path
297 String
298 _AppResourceBitmapUtil::NormalizePath(const String& path) const
299 {
300         String normalizedPath = path;
301
302         normalizedPath.Replace(L'\\', L'/');
303
304         if (normalizedPath.StartsWith(L"/", 0) == false)
305         {
306                 result r = normalizedPath.Insert(L'/', 0);
307                 SysTryLog(NID_APP, r == E_SUCCESS, "[%s] Propagating.", GetErrorMessage(r));
308         }
309
310         return normalizedPath;
311 }
312
313 // Get Matched Resource File Path
314 result
315 _AppResourceBitmapUtil::GetResourcePath(const String& fileName, String& resourcePath, _Density& resourceDensity, bool& imageScaling) const
316 {
317         result r = E_SUCCESS;
318
319         // 0. Try to check nine patch image
320         bool isNinePatchImage = false;
321
322         if (_BitmapImpl::HasNinePatchedBitmapTag(fileName))
323         {
324                 isNinePatchImage = true;
325                 SysLog(NID_APP, "%S is nine patch image", fileName.GetPointer());
326         }
327
328         // 1. Try to search resolution Folder
329         String resourcePathForResolution(L"");
330
331         if (__resolutionDirectories.IsEmpty() == false &&
332                         GetFilePath(__resolutionDirectories, fileName, resourcePathForResolution))
333         {
334                 if (File::IsFileExist(resourcePathForResolution))
335                 {
336                         resourcePath = resourcePathForResolution;
337                         resourceDensity = DENSITY_NONE;
338                         imageScaling = false;
339
340                         r = E_SUCCESS;
341                         return r;
342                 }
343         }
344
345         // 2. Try to search resource directory matched device's DPI
346         String resourcePathForDensity(L"");
347
348         if (__sortedDensityDirectories[0].IsEmpty() == false &&
349                         GetFilePath(__sortedDensityDirectories[0], fileName, resourcePathForDensity))
350         {
351                 if (File::IsFileExist(resourcePathForDensity))
352                 {
353                         resourcePath = resourcePathForDensity;
354                         resourceDensity = __sortedDensity[0];
355                         imageScaling = isNinePatchImage ? false : _CoordinateSystem::GetInstance()->IsTransformEnabled();
356
357                         r = E_SUCCESS;
358                         return r;
359                 }
360         }
361
362         // 3. Try to find the alternative path with fall back
363         int fallbackIndex = 1;
364         String alternativeResourcePath(L"");
365
366         for (int findingDensity = DENSITY_XHIGH; findingDensity > DENSITY_LOW; findingDensity--)
367         {
368                 if (__sortedDensityDirectories[fallbackIndex].IsEmpty() == false &&
369                                 GetFilePath(__sortedDensityDirectories[fallbackIndex], fileName, alternativeResourcePath))
370                 {
371                         if (File::IsFileExist(alternativeResourcePath))
372                         {
373                                 resourcePath = alternativeResourcePath;
374                                 resourceDensity = __sortedDensity[fallbackIndex];
375                                 imageScaling = !isNinePatchImage;
376
377                                 r = E_SUCCESS;
378                                 return r;
379                         }
380                 }
381                 fallbackIndex++;
382         }
383
384         SysTryReturn(NID_APP, r == E_SUCCESS, E_FILE_NOT_FOUND, E_FILE_NOT_FOUND, "[E_FILE_NOT_FOUND] The specified file cannot be found.");
385
386         return r;
387 }
388
389 // GetBitmapN
390 Bitmap*
391 _AppResourceBitmapUtil::GetBitmapN(const String& resourcePath, const _Density resourceDensity,
392                                                                 BitmapPixelFormat pixelFormat, bool imageScaling, const Color* pChromaKeyColor) const
393 {
394         ClearLastResult();
395         SysTryReturn(NID_APP, (pixelFormat > BITMAP_PIXEL_FORMAT_MIN && pixelFormat < BITMAP_PIXEL_FORMAT_MAX), null,
396                                 E_UNSUPPORTED_FORMAT, "[E_UNSUPPORTED_FORMAT] The image file format or specified pixel format(%d) is not supported.", pixelFormat);
397
398         result r = E_SUCCESS;
399
400         std::unique_ptr<Bitmap> pBitmap;
401
402         if (!pChromaKeyColor && imageScaling == false)  // NonScaling
403         {
404                 pBitmap.reset(new (std::nothrow) Bitmap());
405                 SysTryReturn(NID_APP, pBitmap != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
406
407                 r = _BitmapImpl::GetInstance(*pBitmap)->Construct(resourcePath, pixelFormat);
408                 SysTryReturn(NID_APP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
409
410                 return pBitmap.release();
411         }
412         else    // Scaling
413         {
414                 MediaPixelFormat format = ConvertBitmapPixelFormatToMediaPixelFormat(pixelFormat);
415                 int imageWidth(-1);
416                 int imageHeight(-1);
417
418                 std::unique_ptr<ByteBuffer> pBuffer(_ImageDecoder::DecodeToBufferN(resourcePath, format, imageWidth, imageHeight));
419                 r = GetLastResult();
420                 SysTryReturn(NID_APP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
421                 SysTryReturn(NID_APP, pBuffer != null, null, E_SYSTEM, "[E_SYSTEM] A system error has occurred.");
422
423                 pBitmap.reset(_BitmapImpl::GetNonScaledBitmapN(*pBuffer, Dimension(imageWidth, imageHeight), pixelFormat));
424                 r = GetLastResult();
425                 SysTryReturn(NID_APP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
426                 SysTryReturn(NID_APP, pBitmap != null, null, E_SYSTEM, "[E_SYSTEM] A system error has occurred.");
427
428                 int resourceLogicalCoordinate = __physicalResolutionDim.width;
429
430                 switch (resourceDensity)
431                 {
432                 case DENSITY_XHIGH:
433                         resourceLogicalCoordinate = 720;
434                         break;
435
436                 case DENSITY_HIGH:
437                         resourceLogicalCoordinate = 480;
438                         break;
439
440                 case DENSITY_MIDDLE:
441                         resourceLogicalCoordinate = 320;
442                         break;
443
444                 case DENSITY_LOW:
445                         resourceLogicalCoordinate = 240;
446                         break;
447
448                 default:
449                         break;
450                 }
451
452                 _ICoordinateSystemTransformer* pTempXformer(null);
453                 r = _CreateCoordinateTransformer(pTempXformer,
454                                         resourceLogicalCoordinate, __physicalBaseScreenSize,
455                                         Dimension(_CoordinateSystem::GetInstance()->GetLogicalResolutionInt(), _CoordinateSystem::GetInstance()->GetLogicalResolutionInt()), _CoordinateSystem::GetInstance()->GetLogicalBaseScreenSize());
456
457                 std::unique_ptr<_ICoordinateSystemTransformer> pXformer(pTempXformer);
458                 SysTryReturn(NID_APP, pXformer != null, null, E_SYSTEM, "[E_SYSTEM] A system error has occurred.");
459                 SysTryReturn(NID_APP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
460
461                 FloatDimension physicalImageDim = _CoordinateSystemUtils::ConvertToFloat(Dimension(imageWidth, imageHeight));
462                 FloatDimension logicalImageSize = pXformer->Transform(physicalImageDim);
463                 r = GetLastResult();
464                 SysTryReturn(NID_APP, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] A system error has occurred.");
465
466                 r = pBitmap->Scale(logicalImageSize);
467                 SysTryReturn(NID_APP, r == E_SUCCESS, null, E_SYSTEM, "[E_SYSTEM] A system error has occurred.");
468         }
469
470         if (pChromaKeyColor != null)
471         {
472                 r = pBitmap->SetMaskingColor(pChromaKeyColor);
473                 SysTryReturn(NID_APP, r == E_SUCCESS, null, r, "[%s] Propagating.", GetErrorMessage(r));
474         }
475
476         SetLastResult(E_SUCCESS);
477
478         return pBitmap.release();
479 }
480
481 Tizen::App::_AppResourceBitmapUtil::AppResourceBy 
482 _AppResourceBitmapUtil::GetAppResourceType(void)
483 {
484         return __resourceType;
485 }
486
487 }} // Tizen::App