2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Flora License, Version 1.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
9 // http://floralicense.org/license/
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.
20 * @brief This is the implementation file for internal util class.
24 #include <unique_ptr.h>
26 #include <FBaseSysLog.h>
28 #include "FGrp_BitmapImpl.h"
29 #include "../FGrp_Canvas.h"
30 #include "../FGrp_Bitmap.h"
31 #include "FGrp_Util.h"
32 #include "../effect/FGrp_Effect.h"
35 using namespace Tizen::Base;
37 namespace Tizen { namespace Graphics
45 IntersectGeneralRect(Rectangle<T>& outRect, const Rectangle<T>& srcRect1, const Rectangle<T>& srcRect2)
52 TBound(const Rectangle<T>& rect)
56 , y2(rect.y + rect.h) {}
59 TBound srcBound1(srcRect1);
60 TBound srcBound2(srcRect2);
62 if (((srcRect1.w > 0 && srcRect1.h > 0) && (srcRect2.w > 0 && srcRect2.h > 0))
63 && ((srcBound2.x2 > srcBound1.x1) && (srcBound2.x1 < srcBound1.x2) && (srcBound2.y2 > srcBound1.y1) &&
64 (srcBound2.y1 < srcBound1.y2)))
66 outRect.x = (srcBound2.x1 <= srcBound1.x1) ? srcBound1.x1 : srcBound2.x1;
67 outRect.y = (srcBound2.y1 <= srcBound1.y1) ? srcBound1.y1 : srcBound2.y1;
68 outRect.w = ((srcBound2.x2 >= srcBound1.x2) ? srcBound1.x2 : srcBound2.x2) - outRect.x;
69 outRect.h = ((srcBound2.y2 >= srcBound1.y2) ? srcBound1.y2 : srcBound2.y2) - outRect.y;
87 _Util::Validate(const ::Tizen::Graphics::Rectangle& rtSrc, const ::Tizen::Graphics::Rectangle& rtDest)
89 // check 1. is width/height less or equal than 0?
90 if (rtSrc.width <= 0 || rtSrc.height <= 0 || rtDest.width <= 0 || rtDest.height <= 0)
92 SysTryReturnResult(NID_GRP, 0, E_OUT_OF_RANGE, "The argument is out of range. (src(w:%d,h:%d), dst(w:%d,h:%d)).\n",
93 rtSrc.width, rtSrc.height, rtDest.width,
97 // check 2. is src exiting outside of dest entirely?
98 if (rtSrc.x > rtDest.x + rtDest.width - 1 ||
99 rtSrc.x + rtSrc.width - 1 < rtDest.x)
101 SysTryReturnResult(NID_GRP, 0, E_OUT_OF_RANGE,
102 "The argument is out of range. (src(x:%d,y:%d,w:%d,h:%d), dst(x:%d,y:%d,w:%d,h:%d)).\n",
104 rtSrc.y, rtSrc.width, rtSrc.height, rtDest.x, rtDest.y, rtDest.width,
108 if (rtSrc.y > rtDest.y + rtDest.height - 1 ||
109 rtSrc.y + rtSrc.height - 1 < rtDest.y)
111 SysTryReturnResult(NID_GRP, 0, E_OUT_OF_RANGE,
112 "The argument is out of range. (src(x:%d,y:%d,w:%d,h:%d), dst(x:%d,y:%d,w:%d,h:%d)).\n",
114 rtSrc.y, rtSrc.width, rtSrc.height, rtDest.x, rtDest.y, rtDest.width,
122 _Util::Validate(const ::Tizen::Graphics::Point& ptSrc, const ::Tizen::Graphics::Rectangle& rtDest)
124 SysTryReturnResult(NID_GRP, rtDest.x <= ptSrc.x &&
125 ptSrc.x < rtDest.x + rtDest.width &&
126 rtDest.y <= ptSrc.y &&
127 ptSrc.y < rtDest.y + rtDest.height,
128 E_OUT_OF_RANGE, "The argument is out of range. (src(x:%d,y:%d), dst(x:%d,y:%d,w:%d,h:%d)).\n",
129 ptSrc.x, ptSrc.y, rtDest.x, rtDest.y, rtDest.width,
136 _Util::IntersectRect(Rectangle<float>& outRect, const Rectangle<float>& srcRect1, const Rectangle<float>& srcRect2)
138 return _Util::IntersectGeneralRect<float>(outRect, srcRect1, srcRect2);
142 _Util::IntersectRect(Rectangle<int>& outRect, const Rectangle<int>& srcRect1, const Rectangle<int>& srcRect2)
144 return _Util::IntersectGeneralRect<int>(outRect, srcRect1, srcRect2);
147 ////////////////////////////////////////////////////////////////////////////////
150 _Util::LockManager::LockManager(const _Bitmap& bitmap)
151 : __pBitmap(const_cast <_Bitmap*>(&bitmap))
153 , __pBitmapImpl(null)
154 , __pCanvasImpl(null)
156 if ((__result = __pBitmap->Lock(__bufferInfo)) != E_SUCCESS)
162 _Util::LockManager::LockManager(const _Canvas& canvas)
164 , __pCanvas(const_cast <_Canvas*>(&canvas))
165 , __pBitmapImpl(null)
166 , __pCanvasImpl(null)
168 if ((__result = __pCanvas->Lock(__bufferInfo)) != E_SUCCESS)
174 _Util::LockManager::LockManager(const class _BitmapImpl& bitmapImpl)
177 , __pBitmapImpl(const_cast <_BitmapImpl*>(&bitmapImpl))
178 , __pCanvasImpl(null)
180 if ((__result = __pBitmapImpl->Lock(__bufferInfo)) != E_SUCCESS)
182 __pBitmapImpl = null;
186 _Util::LockManager::LockManager(const class _CanvasImpl& canvasImpl)
189 , __pBitmapImpl(null)
190 , __pCanvasImpl(const_cast <_CanvasImpl*>(&canvasImpl))
192 if ((__result = __pCanvasImpl->Lock(__bufferInfo)) != E_SUCCESS)
194 __pCanvasImpl = null;
198 _Util::LockManager::~LockManager()
202 __pBitmapImpl->Unlock();
207 __pCanvasImpl->Unlock();
222 _Util::LockManager::IsValid(void) const
224 return (__pBitmap || __pCanvas || __pBitmapImpl || __pCanvasImpl);
228 _Util::LockManager::GetResult(void) const
234 _Util::LockManager::GetBufferInfo(void) const
239 ////////////////////////////////////////////////////////////////////////////////
240 // GetPatchList() function
245 template<typename Pixel>
246 struct _NinePatchedKey
251 struct _NinePatchedKey <unsigned long>
260 struct _NinePatchedKey <unsigned short>
268 template<typename Pixel>
270 _FindWidthOfSubregions(const _Util::Pixmap& dstImage, int pRegionWidthes[], bool pWidthStretchable[])
274 KEY = _NinePatchedKey <Pixel>::KEY
277 if (dstImage.depth != sizeof(Pixel) * 8)
282 // find a set of width
284 Pixel* pProbe = (Pixel*) (dstImage.pBitmap) + 1;
285 Pixel* pProbeNext = pProbe + 1;
286 Pixel* pProbeEnd = pProbe + dstImage.width - 1;
288 while (pProbeNext < pProbeEnd)
290 pRegionWidthes[index]++;
292 if (((*pProbe == KEY) && (*pProbeNext != KEY)) || ((*pProbe != KEY) && (*pProbeNext == KEY)))
294 pWidthStretchable[index] = (*pProbe == KEY) ? true : false;
301 // pRegionWidthes[index]++;
306 template<typename Pixel>
308 _FindHeightOfSubregions(const _Util::Pixmap& dstImage, int pRegionHeights[], bool pHeightStretchable[])
312 KEY = _NinePatchedKey <Pixel>::KEY
315 if (dstImage.depth != sizeof(Pixel) * 8)
320 // find a set of height
322 int pitch = dstImage.bytesPerLine / (dstImage.depth / 8);
323 Pixel* pProbe = (Pixel*) (dstImage.pBitmap) + pitch;
324 Pixel* pProbeNext = pProbe + pitch;
325 Pixel* pProbeEnd = pProbe + (dstImage.height - 1) * pitch;
327 while (pProbeNext < pProbeEnd)
329 pRegionHeights[index]++;
331 if (((*pProbe == KEY) && (*pProbeNext != KEY)) || ((*pProbe != KEY) && (*pProbeNext == KEY)))
333 pHeightStretchable[index] = (*pProbe == KEY) ? true : false;
340 // pRegionHeights[index]++;
348 _Util::GetPatchList(_Util::AccumList <_Util::Pair <_Util::Rectangle<int>, _Util::Rectangle<int> > >& outList, const ::Tizen::Graphics::Rectangle& rect, const _Bitmap& bitmap)
350 // 1. Find withes and heights of stretchable/unstretchable regions.
351 _Util::LockManager srcLock(bitmap);
352 SysTryReturnResult(NID_GRP, srcLock.IsValid(), E_OPERATION_FAILED, "The source bitmap cannot be locked.\n");
354 const BufferInfo& srcBufferInfo = srcLock.GetBufferInfo();
355 _Util::Pixmap srcImage(srcBufferInfo.width, srcBufferInfo.height, srcBufferInfo.bitsPerPixel, srcBufferInfo.pPixels,
356 srcBufferInfo.pitch);
357 // APPLY_SRC_BITMAP_ATTRIB(srcImage, bitmap);
359 std::unique_ptr<int[]> pRegionWidthes(new (std::nothrow) int[srcImage.width]);
360 SysTryReturnResult(NID_GRP, pRegionWidthes, E_OUT_OF_MEMORY, "Fails to allocate memory.\n");
362 std::unique_ptr<bool[]> pWidthStretchable(new (std::nothrow) bool[srcImage.width]);
363 SysTryReturnResult(NID_GRP, pWidthStretchable, E_OUT_OF_MEMORY, "Fails to allocate memory.\n");
365 memset(pRegionWidthes.get(), 0, sizeof(int) * srcImage.width);
366 memset(pWidthStretchable.get(), 0, sizeof(bool) * srcImage.width);
368 std::unique_ptr<int[]> pRegionHeights(new (std::nothrow) int[srcImage.height]);
369 SysTryReturnResult(NID_GRP, pRegionHeights, E_OUT_OF_MEMORY, "Fails to allocate memory.\n");
371 std::unique_ptr<bool[]> pHeightStretchable(new (std::nothrow) bool[srcImage.height]);
372 SysTryReturnResult(NID_GRP, pHeightStretchable, E_OUT_OF_MEMORY, "Fails to allocate memory.\n");
374 memset(pRegionHeights.get(), 0, sizeof(int) * srcImage.height);
375 memset(pHeightStretchable.get(), 0, sizeof(bool) * srcImage.height);
380 switch (srcImage.depth)
383 numWidth = _FindWidthOfSubregions <unsigned long>(srcImage, pRegionWidthes.get(), pWidthStretchable.get());
384 numHeight = _FindHeightOfSubregions <unsigned long>(srcImage, pRegionHeights.get(), pHeightStretchable.get());
388 numWidth = _FindWidthOfSubregions <unsigned short>(srcImage, pRegionWidthes.get(), pWidthStretchable.get());
389 numHeight = _FindHeightOfSubregions <unsigned short>(srcImage, pRegionHeights.get(), pHeightStretchable.get());
392 SysTryReturnResult(NID_GRP, numWidth > 0 && numHeight > 0, E_OPERATION_FAILED,
393 "The source bitmap is not allowable for NintPatchedBitmap.\n");
395 // 2. Split source image into separate stretchable/unstretchable regions.
396 std::unique_ptr< ::Tizen::Graphics::Rectangle[]> pSrcRectLists(new (std::nothrow) ::Tizen::Graphics::Rectangle[numWidth * numHeight]);
397 SysTryReturnResult(NID_GRP, pSrcRectLists, E_OUT_OF_MEMORY, "Fails to allocate memory.\n");
403 for (horizontal = 0; horizontal < numHeight; horizontal++)
405 pSrcRectLists[index].x = 1;
406 pSrcRectLists[index].y =
407 (horizontal == 0) ? 1 : pSrcRectLists[index - numWidth].y + pSrcRectLists[index - numWidth].height;
408 pSrcRectLists[index].width = pRegionWidthes[0];
409 pSrcRectLists[index].height = pRegionHeights[horizontal];
412 for (vertical = 1; vertical < numWidth; vertical++)
414 pSrcRectLists[index].x = pSrcRectLists[index - 1].x + pSrcRectLists[index - 1].width;
415 pSrcRectLists[index].y = pSrcRectLists[index - 1].y;
416 pSrcRectLists[index].width = pRegionWidthes[vertical];
417 pSrcRectLists[index].height = pSrcRectLists[index - 1].height;
422 // 3. Calculate stretchable/unstretchable regions of the target size.
423 int sumWidthSrcStretchableRegions = 0;
424 int sumHeightSrcStretchableRegions = 0;
426 for (vertical = 0; vertical < numWidth; vertical++)
428 if (pWidthStretchable[vertical])
430 sumWidthSrcStretchableRegions += pRegionWidthes[vertical];
434 for (horizontal = 0; horizontal < numHeight; horizontal++)
436 if (pHeightStretchable[horizontal])
438 sumHeightSrcStretchableRegions += pRegionHeights[horizontal];
442 int sumWidthDstStretchableRegions = rect.width - ((srcImage.width - 2) - sumWidthSrcStretchableRegions);
443 int sumHeightDstStretchableRegions = rect.height - ((srcImage.height - 2) - sumHeightSrcStretchableRegions);
445 for (vertical = 0; vertical < numWidth; vertical++)
447 if (pWidthStretchable[vertical])
449 pRegionWidthes[vertical] =
450 int(float(sumWidthDstStretchableRegions) * float(pRegionWidthes[vertical]) /
451 float(sumWidthSrcStretchableRegions) + 0.5f);
455 for (horizontal = 0; horizontal < numHeight; horizontal++)
457 if (pHeightStretchable[horizontal])
459 pRegionHeights[horizontal] =
460 int(float(sumHeightDstStretchableRegions) * float(pRegionHeights[horizontal]) /
461 float(sumHeightSrcStretchableRegions) + 0.5f);
465 std::unique_ptr< ::Tizen::Graphics::Rectangle[]> pDstRectLists(new (std::nothrow) ::Tizen::Graphics::Rectangle[numWidth * numHeight]);
466 SysTryReturnResult(NID_GRP, pDstRectLists, E_OUT_OF_MEMORY, "Fails to allocate memory.\n");
470 for (horizontal = 0; horizontal < numHeight; horizontal++)
472 pDstRectLists[index].x = rect.x;
473 pDstRectLists[index].y = (horizontal == 0) ? rect.y : pDstRectLists[index - numWidth].y + pDstRectLists[index - numWidth].height;
474 pDstRectLists[index].width = pRegionWidthes[0];
475 pDstRectLists[index].height = pRegionHeights[horizontal];
478 for (vertical = 1; vertical < numWidth; vertical++)
480 pDstRectLists[index].x = pDstRectLists[index - 1].x + pDstRectLists[index - 1].width;
481 pDstRectLists[index].y = pDstRectLists[index - 1].y;
482 pDstRectLists[index].width = pRegionWidthes[vertical];
483 pDstRectLists[index].height = pDstRectLists[index - 1].height;
488 // 4. Record stretchable/unstretchable regions of bitmap to list.
491 for (index = 0; index < numWidth * numHeight; index++)
493 _Util::Rectangle<int> destRect =
495 pDstRectLists[index].x,
496 pDstRectLists[index].y,
497 pDstRectLists[index].width,
498 pDstRectLists[index].height
501 _Util::Rectangle<int> sourRect =
503 pSrcRectLists[index].x,
504 pSrcRectLists[index].y,
505 pSrcRectLists[index].width,
506 pSrcRectLists[index].height
509 outList.Push(_Util::MakePair(destRect, sourRect));
515 }} // Tizen::Graphics