Add stride to PixelBuffer 55/270455/13
authorHeeyong Song <heeyong.song@samsung.com>
Thu, 3 Feb 2022 05:21:57 +0000 (14:21 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Wed, 6 Apr 2022 03:21:04 +0000 (12:21 +0900)
Change-Id: I9f7c46e63b78e186a2bb47deb63d35d5a5102f5f

13 files changed:
automated-tests/src/dali-adaptor-internal/utc-Dali-ImageOperations.cpp
automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp
dali/devel-api/adaptor-framework/pixel-buffer.cpp
dali/devel-api/adaptor-framework/pixel-buffer.h
dali/internal/graphics/gles-impl/egl-graphics-controller.cpp
dali/internal/imaging/common/alpha-mask.cpp
dali/internal/imaging/common/gaussian-blur.cpp
dali/internal/imaging/common/image-operations.cpp
dali/internal/imaging/common/image-operations.h
dali/internal/imaging/common/pixel-buffer-impl.cpp
dali/internal/imaging/common/pixel-buffer-impl.h
dali/internal/text/text-abstraction/cairo-renderer.cpp
dali/internal/text/text-abstraction/plugin/font-client-utils.cpp

index e7414ff..6c54a62 100644 (file)
@@ -402,7 +402,7 @@ int UtcDaliImageOperationsDownscaleBitmap(void)
  */
 int UtcDaliImageOperationsDownscaleInPlacePow2RGB888(void)
 {
-  unsigned outWidth = -1, outHeight = -1;
+  unsigned outWidth = -1, outHeight = -1, outStride = -1;
 
   // Do downscaling to 1 x 1 so we can easily assert the value of the single pixel produced:
 
@@ -410,26 +410,29 @@ int UtcDaliImageOperationsDownscaleInPlacePow2RGB888(void)
   unsigned char check_4x4[16 * 3] = {
     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff};
 
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(check_4x4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(check_4x4, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
   DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
   DALI_TEST_EQUALS(check_4x4[0], (unsigned char)0x7f, TEST_LOCATION);
 
   // Scale down a 16 pixel black image with a single white pixel to a 1/16th grey single pixel:
   unsigned char single_4x4[16 * 3] = {
     0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
   DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
   DALI_TEST_EQUALS(single_4x4[0], (unsigned char)0xf, TEST_LOCATION);
 
   // Scale down a 16 pixel black image with a single white pixel to a 1/16th grey single pixel:
   // (white pixel at bottom-right of image)
   unsigned char single_4x4_2[16 * 3] = {
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff};
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4_2, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(single_4x4_2, 4, 4, 4, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
   DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(outStride, 1u, TEST_LOCATION);
   DALI_TEST_EQUALS(single_4x4_2[0], (unsigned char)0xf, TEST_LOCATION);
 
   // Build a larger ~600 x ~600 uniform magenta image for tests which only test output dimensions:
@@ -443,41 +446,50 @@ int UtcDaliImageOperationsDownscaleInPlacePow2RGB888(void)
   }
 
   // Scaling to 0 x 0 should stop at 1 x 1:
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 0, 0, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
   DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+  DALI_TEST_CHECK(outStride == outWidth);
 
   // Scaling to 1 x 1 should hit 1 x 1:
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 608, 608, 1, 1, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 608, 608, 608, 1, 1, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_EQUALS(outWidth, 1u, TEST_LOCATION);
   DALI_TEST_EQUALS(outHeight, 1u, TEST_LOCATION);
+  DALI_TEST_CHECK(outStride == outWidth);
 
   // Scaling to original dimensions should NOP:
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 384, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 384, 384, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_EQUALS(outWidth, 384u, TEST_LOCATION);
   DALI_TEST_EQUALS(outHeight, 384u, TEST_LOCATION);
+  DALI_TEST_CHECK(outStride == outWidth);
 
   // More dimension tests:
 
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 44, 11, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 44, 11, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_EQUALS(outWidth, 44u, TEST_LOCATION);
   DALI_TEST_EQUALS(outHeight, 44u, TEST_LOCATION);
+  DALI_TEST_CHECK(outStride == outWidth);
 
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 3, 48, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 3, 48, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_EQUALS(outWidth, 48u, TEST_LOCATION);
   DALI_TEST_EQUALS(outHeight, 48u, TEST_LOCATION);
+  DALI_TEST_CHECK(outStride == outWidth);
 
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 3, 3, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 384, 384, 384, 3, 3, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_CHECK(outWidth == 3u && outHeight == 3u);
+  DALI_TEST_CHECK(outStride == outWidth);
 
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 320, 320, 5, 5, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 320, 320, 320, 5, 5, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_CHECK(outWidth == 5u && outHeight == 5u);
+  DALI_TEST_CHECK(outStride == outWidth);
 
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 448, 448, 7, 7, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 448, 448, 448, 7, 7, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_CHECK(outWidth == 7u && outHeight == 7u);
+  DALI_TEST_CHECK(outStride == outWidth);
 
-  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 11, 11, BoxDimensionTestBoth, outWidth, outHeight);
+  Dali::Internal::Platform::DownscaleInPlacePow2RGB888(magenta_600_x_600, 352, 352, 352, 11, 11, BoxDimensionTestBoth, outWidth, outHeight, outStride);
   DALI_TEST_CHECK(outWidth == 11u && outHeight == 11u);
+  DALI_TEST_CHECK(outStride == outWidth);
 
   // Check that no pixel values were modified by the repeated averaging of identical pixels in tests above:
   unsigned int numNonMagenta = 0u;
@@ -495,19 +507,22 @@ int UtcDaliImageOperationsDownscaleInPlacePow2RGB888(void)
  */
 void TestDownscaleOutputsExpectedDimensionsRGBA8888(uint32_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
 {
-  unsigned int resultingWidth = -1, resultingHeight = -1;
+  unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
   Dali::Internal::Platform::DownscaleInPlacePow2RGBA8888(
     reinterpret_cast<unsigned char*>(pixels),
     inputWidth,
     inputHeight,
+    inputWidth,
     desiredWidth,
     desiredHeight,
     BoxDimensionTestBoth,
     resultingWidth,
-    resultingHeight);
+    resultingHeight,
+    resultingStride);
 
   DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
   DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
+  DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
 }
 
 /**
@@ -515,19 +530,22 @@ void TestDownscaleOutputsExpectedDimensionsRGBA8888(uint32_t pixels[], unsigned
  */
 void TestDownscaleOutputsExpectedDimensionsRGB565(uint16_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
 {
-  unsigned int resultingWidth = -1, resultingHeight = -1;
+  unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
   Dali::Internal::Platform::DownscaleInPlacePow2RGB565(
     reinterpret_cast<unsigned char*>(pixels),
     inputWidth,
     inputHeight,
+    inputWidth,
     desiredWidth,
     desiredHeight,
     BoxDimensionTestBoth,
     resultingWidth,
-    resultingHeight);
+    resultingHeight,
+    resultingStride);
 
   DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
   DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
+  DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
 }
 
 /**
@@ -535,19 +553,22 @@ void TestDownscaleOutputsExpectedDimensionsRGB565(uint16_t pixels[], unsigned in
  */
 void TestDownscaleOutputsExpectedDimensions2ComponentPair(uint8_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
 {
-  unsigned int resultingWidth = -1, resultingHeight = -1;
+  unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
   Dali::Internal::Platform::DownscaleInPlacePow2ComponentPair(
     pixels,
     inputWidth,
     inputHeight,
+    inputWidth,
     desiredWidth,
     desiredHeight,
     BoxDimensionTestBoth,
     resultingWidth,
-    resultingHeight);
+    resultingHeight,
+    resultingStride);
 
   DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
   DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
+  DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
 }
 
 /**
@@ -555,19 +576,22 @@ void TestDownscaleOutputsExpectedDimensions2ComponentPair(uint8_t pixels[], unsi
  */
 void TestDownscaleOutputsExpectedDimensionsSingleComponent(uint8_t pixels[], unsigned inputWidth, unsigned inputHeight, unsigned int desiredWidth, unsigned int desiredHeight, unsigned int expectedWidth, unsigned int expectedHeight, const char* const location)
 {
-  unsigned int resultingWidth = -1, resultingHeight = -1;
+  unsigned int resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
   Dali::Internal::Platform::DownscaleInPlacePow2SingleBytePerPixel(
     pixels,
     inputWidth,
     inputHeight,
+    inputWidth,
     desiredWidth,
     desiredHeight,
     BoxDimensionTestBoth,
     resultingWidth,
-    resultingHeight);
+    resultingHeight,
+    resultingStride);
 
   DALI_TEST_EQUALS(resultingWidth, expectedWidth, location);
   DALI_TEST_EQUALS(resultingHeight, expectedHeight, location);
+  DALI_TEST_EQUALS(resultingStride, expectedWidth, location);
 }
 
 /**
@@ -581,58 +605,68 @@ int UtcDaliImageOperationsDownscaleInPlacePow2RGBA8888(void)
     image[i] = 0xffffffff;
   }
   unsigned char* const pixels         = reinterpret_cast<unsigned char*>(image);
-  unsigned int         resultingWidth = -1, resultingHeight = -1;
+  unsigned int         resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
 
   // Test downscaling where the input size is an exact multiple of the desired size:
   // (We expect a perfect result here)
 
-  DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 600, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 75u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 75u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
-  DownscaleInPlacePow2RGBA8888(pixels, 512, 512, 16, 16, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 512, 512, 512, 16, 16, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 16u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 16u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
-  DownscaleInPlacePow2RGBA8888(pixels, 512, 64, 16, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 512, 64, 512, 16, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 16u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
-  DownscaleInPlacePow2RGBA8888(pixels, 64, 1024, 4, 64, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 64, 1024, 64, 4, 64, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 4u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 64u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
   // Test downscaling where the input size is slightly off being an exact multiple of the desired size:
   // (We expect a perfect match at the end because of rounding-down to an even width and height at each step)
 
-  DownscaleInPlacePow2RGBA8888(pixels, 601, 603, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 601, 603, 601, 75, 75, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 75u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 75u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
-  DownscaleInPlacePow2RGBA8888(pixels, 736 + 1, 352 + 3, 23, 11, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 736 + 1, 352 + 3, 736 + 1, 23, 11, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 23u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 11u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
-  DownscaleInPlacePow2RGBA8888(pixels, 384 + 3, 896 + 1, 3, 7, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 384 + 3, 896 + 1, 384 + 3, 3, 7, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 3u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 7u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
   // Test downscales with source dimensions which are under a nice power of two by one:
 
   // The target is hit exactly due to losing spare columns or rows at each iteration:
-  DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 7, 3, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 63, 7, 3, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 3u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
   // Asking to downscale a bit smaller should stop at the dimensions of the last test as one more halving would go down to 3 x 1, which is too small.
-  DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 4, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 63, 31, 63, 4, 2, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 3u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
   // Should stop at almost twice the requested dimensions:
-  DownscaleInPlacePow2RGBA8888(pixels, 15, 127, 4, 32, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 15, 127, 15, 4, 32, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 7u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 63u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
   // Test downscales to 1 in one or both dimensions:
   // Parameters:                                         input-x  input-y, desired-x, desired-y, expected-x, expected-y
@@ -678,22 +712,25 @@ int UtcDaliImageOperationsDownscaleInPlacePow2RGBA8888Nops(void)
   }
   const uint32_t       imageHash      = HashPixels(image, numPixels);
   unsigned char* const pixels         = reinterpret_cast<unsigned char*>(image);
-  unsigned int         resultingWidth = -1, resultingHeight = -1;
+  unsigned int         resultingWidth = -1, resultingHeight = -1, resultingStride = -1;
 
   // Test downscales to the same size:
   // The point is just to be sure the downscale is a NOP in this case:
 
-  DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 600, 600, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 600, 600, 600, 600, 600, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 600u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 600u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
-  DownscaleInPlacePow2RGBA8888(pixels, 512, 128, 512, 128, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 512, 128, 512, 512, 128, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 512u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 128u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
-  DownscaleInPlacePow2RGBA8888(pixels, 17, 1001, 17, 1001, BoxDimensionTestBoth, resultingWidth, resultingHeight);
+  DownscaleInPlacePow2RGBA8888(pixels, 17, 1001, 17, 17, 1001, BoxDimensionTestBoth, resultingWidth, resultingHeight, resultingStride);
   DALI_TEST_EQUALS(resultingWidth, 17u, TEST_LOCATION);
   DALI_TEST_EQUALS(resultingHeight, 1001u, TEST_LOCATION);
+  DALI_TEST_EQUALS(resultingStride, resultingWidth, TEST_LOCATION);
 
   // Test downscales that request a larger size (we never upscale so these are NOPs too):
   // Parameters:                                         input-x  input-y, desired-x, desired-y, expected-x, expected-y
@@ -714,8 +751,8 @@ int UtcDaliImageOperationsDownscaleInPlacePow2RGBA8888Nops(void)
 int UtcDaliImageOperationsDownscaleInPlacePow2RGB565(void)
 {
   // Test that calling with null and zero parameters doesn't blow up:
-  unsigned int outWidth, outHeight;
-  DownscaleInPlacePow2RGB565(0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight);
+  unsigned int outWidth, outHeight, outStride;
+  DownscaleInPlacePow2RGB565(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
 
   uint16_t image[608 * 608];
   for(unsigned i = 0; i < sizeof(image) / sizeof(image[0]); ++i)
@@ -754,8 +791,8 @@ int UtcDaliImageOperationsDownscaleInPlacePow2RGB565(void)
 int UtcDaliImageOperationsDownscaleInPlacePow2ComponentPair(void)
 {
   // Simple test that a null pointer does not get dereferenced in the function:
-  unsigned int outWidth, outHeight;
-  DownscaleInPlacePow2ComponentPair(0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight);
+  unsigned int outWidth, outHeight, outStride;
+  DownscaleInPlacePow2ComponentPair(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
 
   // Simple tests of dimensions output:
 
@@ -793,8 +830,8 @@ int UtcDaliImageOperationsDownscaleInPlacePow2ComponentPair(void)
 int UtcDaliImageOperationsDownscaleInPlacePow2SingleBytePerPixel(void)
 {
   // Simple test that a null pointer does not get dereferenced in the function:
-  unsigned int outWidth, outHeight;
-  DownscaleInPlacePow2SingleBytePerPixel(0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight);
+  unsigned int outWidth, outHeight, outStride;
+  DownscaleInPlacePow2SingleBytePerPixel(0, 0, 0, 0, 0, 0, BoxDimensionTestBoth, outWidth, outHeight, outStride);
 
   // Tests of output dimensions from downscaling:
   uint8_t image[608 * 608];
@@ -1298,7 +1335,7 @@ int UtcDaliImageOperationsPointSampleCheckerboardRGBA888(void)
 
   uint32_t outputImage[desiredWidth * desiredHeight];
 
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)&image->GetVector()[0], 256, 256, (unsigned char*)outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)&image->GetVector()[0], 256, 256, 256, (unsigned char*)outputImage, desiredWidth, desiredHeight);
 
   DALI_TEST_EQUALS(outputImage[0], (uint32_t)0xff0000ff, TEST_LOCATION);         // < Red corner pixel
   DALI_TEST_EQUALS(outputImage[7], (uint32_t)0xff00ff00, TEST_LOCATION);         // < Green corner pixel
@@ -1367,7 +1404,7 @@ int UtcDaliImageOperationsPointSampleRGBA888PixelsCorrectColor(void)
   buffer.resize(outputBufferSize);
   uint32_t* outputImage = &buffer[0];
 
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, inputWidth, inputHeight, (unsigned char*)outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, inputWidth, inputHeight, inputWidth, (unsigned char*)outputImage, desiredWidth, desiredHeight);
 
   // Check that all the output pixels are the right color:
   const uint32_t reference           = inputImage[inputWidth * inputHeight / 2];
@@ -1400,38 +1437,38 @@ int UtcDaliImageOperationsPointSampleRGBA888ScaleToSinglePixel(void)
   // Try several different starting image sizes:
 
   // 1x1 -> 1x1:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
   DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
   outputImage = 0;
 
   // Single-pixel wide tall stripe:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1024, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1024, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
   DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
   outputImage = 0;
 
   // Single-pixel tall, wide strip:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1024, 1, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1024, 1, 1024, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
   DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
   outputImage = 0;
 
   // Square mid-size image:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, 103, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
   DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
   outputImage = 0;
 
   // Wide mid-size image:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, 313, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
   DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
   outputImage = 0;
 
   // Tall mid-size image:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 467, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 467, 53, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
   DALI_TEST_EQUALS(outputImage, inputImage[0], TEST_LOCATION);
   outputImage = 0;
 
   // 0 x 0 input image (make sure output not written to):
   outputImage = 0xDEADBEEF;
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, 0, (unsigned char*)&outputImage, desiredWidth, desiredHeight);
   DALI_TEST_EQUALS(outputImage, (uint32_t)0xDEADBEEF, TEST_LOCATION);
   outputImage = 0;
 
@@ -1452,31 +1489,31 @@ int UtcDaliImageOperationsPointSampleRGBA888N(void)
   // Try several different starting image sizes:
 
   // 1x1 -> 1x1:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, (unsigned char*)outputImage, 0, 0);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 1, 1, (unsigned char*)outputImage, 0, 0);
   DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
 
   // Single-pixel wide tall stripe:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 102, (unsigned char*)outputImage, 0, 33);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 1, 102, 1, (unsigned char*)outputImage, 0, 33);
   DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
 
   // Single-pixel tall, wide strip:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 102, 1, (unsigned char*)outputImage, 0, 67);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 102, 1, 102, (unsigned char*)outputImage, 0, 67);
   DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
 
   // Square mid-size image:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, (unsigned char*)outputImage, 21, 0);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 103, 103, 103, (unsigned char*)outputImage, 21, 0);
   DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
 
   // Wide mid-size image to 0 height
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, (unsigned char*)outputImage, 99, 0);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 313, 79, 313, (unsigned char*)outputImage, 99, 0);
   DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
 
   // Tall mid-size image to 0 height, over width
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 46, (unsigned char*)outputImage, 9999, 0);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 53, 46, 53, (unsigned char*)outputImage, 9999, 0);
   DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
 
   // 0 x 0 input image:
-  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, (unsigned char*)outputImage, 200, 99);
+  Dali::Internal::Platform::PointSample4BPP((const unsigned char*)inputImage, 0, 0, 0, (unsigned char*)outputImage, 200, 99);
   DALI_TEST_EQUALS(0xaaaaaaaa, outputImage[0], TEST_LOCATION);
 
   END_TEST;
index 9958472..bed76e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -227,6 +227,7 @@ int UtcDaliPixelBufferConvert(void)
     DALI_TEST_CHECK(pixelData);
     DALI_TEST_EQUALS(pixelData.GetWidth(), 10, TEST_LOCATION);
     DALI_TEST_EQUALS(pixelData.GetHeight(), 10, TEST_LOCATION);
+    DALI_TEST_EQUALS(pixelData.GetStride(), 10, TEST_LOCATION);
     DALI_TEST_EQUALS(pixelData.GetPixelFormat(), Pixel::RGB565, TEST_LOCATION);
 
     // Try drawing it
@@ -261,6 +262,7 @@ int UtcDaliPixelBufferGetWidth(void)
   FillCheckerboard(pixbuf);
 
   DALI_TEST_EQUALS(pixbuf.GetWidth(), 10, TEST_LOCATION);
+  DALI_TEST_EQUALS(pixbuf.GetStride(), 10, TEST_LOCATION);
 
   END_TEST;
 }
index e5856c3..e033afa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -84,6 +84,11 @@ unsigned int PixelBuffer::GetHeight() const
   return GetImplementation(*this).GetHeight();
 }
 
+unsigned int PixelBuffer::GetStride() const
+{
+  return GetImplementation(*this).GetStride();
+}
+
 Pixel::Format PixelBuffer::GetPixelFormat() const
 {
   return GetImplementation(*this).GetPixelFormat();
index 9e6f58a..51c6739 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_PIXEL_BUFFER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -157,6 +157,14 @@ public:
   unsigned int GetHeight() const;
 
   /**
+   * @brief Gets the stride of the buffer in pixels.
+   *
+   * @SINCE_2_1.17
+   * @return The stride of the buffer in pixels. 0 means the buffer is tightly packed.
+   */
+  unsigned int GetStride() const;
+
+  /**
    * @brief Gets the pixel format.
    *
    * @SINCE_1_2.46
index 56c5f2d..84325ae 100644 (file)
@@ -663,6 +663,8 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
       }
 
       mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+      mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, info.srcStride);
+
       mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
 
       if(!isSubImage)
index 5205da5..9abdfec 100644 (file)
@@ -51,9 +51,8 @@ void ApplyMaskToAlphaChannel(PixelBuffer& buffer, const PixelBuffer& mask)
   unsigned char* destBuffer       = buffer.GetBuffer();
 
   unsigned int destBytesPerPixel = Dali::Pixel::GetBytesPerPixel(buffer.GetPixelFormat());
-
-  int srcOffset  = 0;
-  int destOffset = 0;
+  unsigned int srcStrideBytes    = mask.GetStride() * srcBytesPerPixel;
+  unsigned int destStrideBytes   = buffer.GetStride() * destBytesPerPixel;
 
   // if image is premultiplied, the other channels of the image need to multiply by alpha.
   if(buffer.IsAlphaPreMultiplied())
@@ -71,6 +70,9 @@ void ApplyMaskToAlphaChannel(PixelBuffer& buffer, const PixelBuffer& mask)
     {
       for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
       {
+        int srcOffset  = 0;
+        int destOffset = 0;
+
         for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
         {
           auto srcAlpha = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
@@ -96,6 +98,8 @@ void ApplyMaskToAlphaChannel(PixelBuffer& buffer, const PixelBuffer& mask)
           srcOffset += srcBytesPerPixel;
           destOffset += destBytesPerPixel;
         }
+        srcBuffer += srcStrideBytes;
+        destBuffer += destStrideBytes;
       }
     }
   }
@@ -103,6 +107,9 @@ void ApplyMaskToAlphaChannel(PixelBuffer& buffer, const PixelBuffer& mask)
   {
     for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
     {
+      int srcOffset  = 0;
+      int destOffset = 0;
+
       for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
       {
         unsigned char srcAlpha  = srcBuffer[srcOffset + srcAlphaByteOffset] & srcAlphaMask;
@@ -116,6 +123,8 @@ void ApplyMaskToAlphaChannel(PixelBuffer& buffer, const PixelBuffer& mask)
         srcOffset += srcBytesPerPixel;
         destOffset += destBytesPerPixel;
       }
+      srcBuffer += srcStrideBytes;
+      destBuffer += destStrideBytes;
     }
   }
 }
@@ -136,12 +145,14 @@ PixelBufferPtr CreateNewMaskedBuffer(const PixelBuffer& buffer, const PixelBuffe
     srcAlphaMask = 0xFF;
   }
 
-  unsigned int   srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcPixelFormat);
   unsigned char* srcBuffer        = mask.GetBuffer();
+  unsigned int   srcBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcPixelFormat);
+  unsigned int   srcStrideBytes   = mask.GetStride() * srcBytesPerPixel;
 
   // Set up source color offsets
   Dali::Pixel::Format srcColorPixelFormat   = buffer.GetPixelFormat();
   unsigned int        srcColorBytesPerPixel = Dali::Pixel::GetBytesPerPixel(srcColorPixelFormat);
+  unsigned int        srcColorStrideBytes   = buffer.GetStride() * srcColorBytesPerPixel;
 
   // Setup destination offsets
   Dali::Pixel::Format destPixelFormat     = Dali::Pixel::RGBA8888;
@@ -150,19 +161,20 @@ PixelBufferPtr CreateNewMaskedBuffer(const PixelBuffer& buffer, const PixelBuffe
   int                 destAlphaMask       = 0;
   Dali::Pixel::GetAlphaOffsetAndMask(destPixelFormat, destAlphaByteOffset, destAlphaMask);
 
-  PixelBufferPtr newPixelBuffer = PixelBuffer::New(buffer.GetWidth(), buffer.GetHeight(), destPixelFormat);
-  unsigned char* destBuffer     = newPixelBuffer->GetBuffer();
-  unsigned char* oldBuffer      = buffer.GetBuffer();
+  PixelBufferPtr newPixelBuffer  = PixelBuffer::New(buffer.GetWidth(), buffer.GetHeight(), destPixelFormat);
+  unsigned char* destBuffer      = newPixelBuffer->GetBuffer();
+  unsigned char* oldBuffer       = buffer.GetBuffer();
+  unsigned int   destStrideBytes = newPixelBuffer->GetStride() * destBytesPerPixel;
 
-  int  srcAlphaOffset = 0;
-  int  srcColorOffset = 0;
-  int  destOffset     = 0;
-  bool hasAlpha       = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
+  bool hasAlpha = Dali::Pixel::HasAlpha(buffer.GetPixelFormat());
 
   unsigned char destAlpha = 0;
 
   for(unsigned int row = 0; row < buffer.GetHeight(); ++row)
   {
+    int srcAlphaOffset = 0;
+    int srcColorOffset = 0;
+    int destOffset     = 0;
     for(unsigned int col = 0; col < buffer.GetWidth(); ++col)
     {
       unsigned char srcAlpha = srcBuffer[srcAlphaOffset + srcAlphaByteOffset] & srcAlphaMask;
@@ -186,6 +198,9 @@ PixelBufferPtr CreateNewMaskedBuffer(const PixelBuffer& buffer, const PixelBuffe
       srcAlphaOffset += srcBytesPerPixel;
       destOffset += destBytesPerPixel;
     }
+    oldBuffer += srcColorStrideBytes;
+    srcBuffer += srcStrideBytes;
+    destBuffer += destStrideBytes;
   }
 
   return newPixelBuffer;
index c10c577..01b5b5b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
  */
 
 // EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
 #include <memory.h>
 #include <cmath>
 
@@ -32,6 +33,8 @@ void ConvoluteAndTranspose(unsigned char*     inBuffer,
                            unsigned char*     outBuffer,
                            const unsigned int bufferWidth,
                            const unsigned int bufferHeight,
+                           const unsigned int inBufferStride,
+                           const unsigned int outBufferStride,
                            const float        blurRadius)
 {
   // Calculate the weights for gaussian blur
@@ -73,7 +76,7 @@ void ConvoluteAndTranspose(unsigned char*     inBuffer,
   for(unsigned int y = 0; y < bufferHeight; y++)
   {
     unsigned int targetPixelIndex = y;
-    unsigned int ioffset          = y * bufferWidth;
+    unsigned int ioffset          = y * inBufferStride;
     for(unsigned int x = 0; x < bufferWidth; x++)
     {
       float r = 0.0f, g = 0.0f, b = 0.0f, a = 0.0f;
@@ -98,7 +101,7 @@ void ConvoluteAndTranspose(unsigned char*     inBuffer,
       outBuffer[targetPixelIndex * 4 + 2] = std::max(0, std::min(static_cast<int>(b + 0.5f), 255));
       outBuffer[targetPixelIndex * 4 + 3] = std::max(0, std::min(static_cast<int>(a + 0.5f), 255));
 
-      targetPixelIndex += bufferHeight;
+      targetPixelIndex += outBufferStride;
     }
   }
 
@@ -109,18 +112,24 @@ void PerformGaussianBlurRGBA(PixelBuffer& buffer, const float blurRadius)
 {
   unsigned int bufferWidth  = buffer.GetWidth();
   unsigned int bufferHeight = buffer.GetHeight();
+  unsigned int bufferStride = buffer.GetStride();
+
+  if(bufferWidth == 0 || bufferHeight == 0 || bufferStride == 0 || buffer.GetPixelFormat() != Pixel::RGBA8888)
+  {
+    DALI_LOG_ERROR("Invalid buffer!\n");
+    return;
+  }
 
   // Create a temporary buffer for the two-pass blur
   PixelBufferPtr softShadowImageBuffer = PixelBuffer::New(bufferWidth, bufferHeight, Pixel::RGBA8888);
-  memcpy(softShadowImageBuffer->GetBuffer(), buffer.GetBuffer(), 4u * bufferWidth * bufferHeight);
 
   // We perform the blur first but write its output image buffer transposed, so that we
   // can just do it in two passes. The first pass blurs horizontally and transposes, the
   // second pass does the same, but as the image is now transposed, it's really doing a
   // vertical blur. The second transposition makes the image the right way up again. This
   // is much faster than doing a 2D convolution.
-  ConvoluteAndTranspose(buffer.GetBuffer(), softShadowImageBuffer->GetBuffer(), bufferWidth, bufferHeight, blurRadius);
-  ConvoluteAndTranspose(softShadowImageBuffer->GetBuffer(), buffer.GetBuffer(), bufferHeight, bufferWidth, blurRadius);
+  ConvoluteAndTranspose(buffer.GetBuffer(), softShadowImageBuffer->GetBuffer(), bufferWidth, bufferHeight, bufferStride, bufferHeight, blurRadius);
+  ConvoluteAndTranspose(softShadowImageBuffer->GetBuffer(), buffer.GetBuffer(), bufferHeight, bufferWidth, bufferHeight, bufferStride, blurRadius);
 
   // On leaving scope, softShadowImageBuffer will get destroyed.
 }
index 772d26f..360c9ad 100644 (file)
@@ -57,7 +57,7 @@ const float RAD_315 = RAD_225 + Math::PI_2;    ///< 315 degrees in radians;
 
 using Integration::Bitmap;
 using Integration::BitmapPtr;
-typedef unsigned char PixelBuffer;
+typedef uint8_t PixelBuffer;
 
 /**
  * @brief 4 byte pixel structure.
@@ -505,6 +505,7 @@ ImageDimensions CalculateDesiredDimensions(unsigned int bitmapWidth, unsigned in
  * @param[in] pixelsIn The input buffer.
  * @param[in] widthIn The width of the input buffer.
  * @param[in] heightIn The height of the input buffer.
+ * @param[in] strideIn The stride of the input buffer.
  * @param[in] pixelSize The size of the pixel.
  * @param[out] pixelsOut The rotated output buffer.
  * @param[out] widthOut The width of the output buffer.
@@ -515,6 +516,7 @@ ImageDimensions CalculateDesiredDimensions(unsigned int bitmapWidth, unsigned in
 bool Rotate90(const uint8_t* const pixelsIn,
               unsigned int         widthIn,
               unsigned int         heightIn,
+              unsigned int         strideIn,
               unsigned int         pixelSize,
               uint8_t*&            pixelsOut,
               unsigned int&        widthOut,
@@ -525,6 +527,7 @@ bool Rotate90(const uint8_t* const pixelsIn,
   heightOut = widthIn;
 
   // Allocate memory for the rotated buffer.
+  // Output buffer is tightly packed
   pixelsOut = static_cast<uint8_t*>(malloc(widthOut * heightOut * pixelSize));
   if(nullptr == pixelsOut)
   {
@@ -538,7 +541,7 @@ bool Rotate90(const uint8_t* const pixelsIn,
   // Rotate the buffer.
   for(unsigned int y = 0u; y < heightIn; ++y)
   {
-    const unsigned int srcLineIndex = y * widthIn;
+    const unsigned int srcLineIndex = y * strideIn;
     const unsigned int dstX         = y;
     for(unsigned int x = 0u; x < widthIn; ++x)
     {
@@ -566,6 +569,7 @@ bool Rotate90(const uint8_t* const pixelsIn,
  * @param[in] pixelsIn The input buffer.
  * @param[in] widthIn The width of the input buffer.
  * @param[in] heightIn The height of the input buffer.
+ * @param[in] strideIn The stride of the input buffer.
  * @param[in] pixelSize The size of the pixel.
  * @param[out] pixelsOut The rotated output buffer.
  *
@@ -574,10 +578,12 @@ bool Rotate90(const uint8_t* const pixelsIn,
 bool Rotate180(const uint8_t* const pixelsIn,
                unsigned int         widthIn,
                unsigned int         heightIn,
+               unsigned int         strideIn,
                unsigned int         pixelSize,
                uint8_t*&            pixelsOut)
 {
   // Allocate memory for the rotated buffer.
+  // Output buffer is tightly packed
   pixelsOut = static_cast<uint8_t*>(malloc(widthIn * heightIn * pixelSize));
   if(nullptr == pixelsOut)
   {
@@ -588,7 +594,7 @@ bool Rotate180(const uint8_t* const pixelsIn,
   // Rotate the buffer.
   for(unsigned int y = 0u; y < heightIn; ++y)
   {
-    const unsigned int srcLineIndex = y * widthIn;
+    const unsigned int srcLineIndex = y * strideIn;
     const unsigned int dstY         = heightIn - y - 1u;
     for(unsigned int x = 0u; x < widthIn; ++x)
     {
@@ -616,6 +622,7 @@ bool Rotate180(const uint8_t* const pixelsIn,
  * @param[in] pixelsIn The input buffer.
  * @param[in] widthIn The width of the input buffer.
  * @param[in] heightIn The height of the input buffer.
+ * @param[in] strideIn The stride of the input buffer.
  * @param[in] pixelSize The size of the pixel.
  * @param[out] pixelsOut The rotated output buffer.
  * @param[out] widthOut The width of the output buffer.
@@ -626,6 +633,7 @@ bool Rotate180(const uint8_t* const pixelsIn,
 bool Rotate270(const uint8_t* const pixelsIn,
                unsigned int         widthIn,
                unsigned int         heightIn,
+               unsigned int         strideIn,
                unsigned int         pixelSize,
                uint8_t*&            pixelsOut,
                unsigned int&        widthOut,
@@ -636,6 +644,7 @@ bool Rotate270(const uint8_t* const pixelsIn,
   heightOut = widthIn;
 
   // Allocate memory for the rotated buffer.
+  // Output buffer is tightly packed
   pixelsOut = static_cast<uint8_t*>(malloc(widthOut * heightOut * pixelSize));
   if(nullptr == pixelsOut)
   {
@@ -649,7 +658,7 @@ bool Rotate270(const uint8_t* const pixelsIn,
   // Rotate the buffer.
   for(unsigned int y = 0u; y < heightIn; ++y)
   {
-    const unsigned int srcLineIndex = y * widthIn;
+    const unsigned int srcLineIndex = y * strideIn;
     const unsigned int dstX         = widthOut - y - 1u;
     for(unsigned int x = 0u; x < widthIn; ++x)
     {
@@ -675,6 +684,7 @@ bool Rotate270(const uint8_t* const pixelsIn,
  *
  * @param[in] srcBufferPtr Pointer to the input pixel buffer.
  * @param[in] srcWidth The width of the input pixel buffer.
+ * @param[in] srcStride The stride of the input pixel buffer.
  * @param[in] pixelSize The size of the pixel.
  * @param[in,out] dstPixelBuffer Pointer to the output pixel buffer.
  * @param[in] dstWidth The width of the output pixel buffer.
@@ -684,6 +694,7 @@ bool Rotate270(const uint8_t* const pixelsIn,
  */
 void HorizontalSkew(const uint8_t* const srcBufferPtr,
                     int                  srcWidth,
+                    int                  srcStride,
                     unsigned int         pixelSize,
                     uint8_t*&            dstBufferPtr,
                     int                  dstWidth,
@@ -703,7 +714,7 @@ void HorizontalSkew(const uint8_t* const srcBufferPtr,
   for(i = 0u; i < srcWidth; ++i)
   {
     // Loop through row pixels
-    const unsigned int srcIndex = pixelSize * (row * srcWidth + i);
+    const unsigned int srcIndex = pixelSize * (row * srcStride + i);
 
     unsigned char src[4u] = {0u, 0u, 0u, 0u};
     for(unsigned int channel = 0u; channel < pixelSize; ++channel)
@@ -766,6 +777,7 @@ void HorizontalSkew(const uint8_t* const srcBufferPtr,
  * @param[in] srcBufferPtr Pointer to the input pixel buffer.
  * @param[in] srcWidth The width of the input pixel buffer.
  * @param[in] srcHeight The height of the input pixel buffer.
+ * @param[in] srcStride The stride of the input pixel buffer.
  * @param[in] pixelSize The size of the pixel.
  * @param[in,out] dstPixelBuffer Pointer to the output pixel buffer.
  * @param[in] dstWidth The width of the output pixel buffer.
@@ -777,6 +789,7 @@ void HorizontalSkew(const uint8_t* const srcBufferPtr,
 void VerticalSkew(const uint8_t* const srcBufferPtr,
                   int                  srcWidth,
                   int                  srcHeight,
+                  int                  srcStride,
                   unsigned int         pixelSize,
                   uint8_t*&            dstBufferPtr,
                   int                  dstWidth,
@@ -803,7 +816,7 @@ void VerticalSkew(const uint8_t* const srcBufferPtr,
   for(i = 0; i < srcHeight; ++i)
   {
     // Loop through column pixels
-    const unsigned int srcIndex = pixelSize * (i * srcWidth + column);
+    const unsigned int srcIndex = pixelSize * (i * srcStride + column);
 
     unsigned char src[4u] = {0u, 0u, 0u, 0u};
     for(unsigned int channel = 0u; channel < pixelSize; ++channel)
@@ -932,6 +945,7 @@ Dali::Devel::PixelBuffer CropAndPadForFittingMode(Dali::Devel::PixelBuffer& bitm
 {
   const unsigned int inputWidth  = bitmap.GetWidth();
   const unsigned int inputHeight = bitmap.GetHeight();
+  const unsigned int inputStride = bitmap.GetStride();
 
   if(desiredDimensions.GetWidth() < 1u || desiredDimensions.GetHeight() < 1u)
   {
@@ -984,7 +998,7 @@ Dali::Devel::PixelBuffer CropAndPadForFittingMode(Dali::Devel::PixelBuffer& bitm
       // Add some pre-calculated offsets to the bitmap pointers so this is not done within a loop.
       // The cropping is added to the source pointer, and the padding is added to the destination.
       const auto               bytesPerPixel      = Pixel::GetBytesPerPixel(pixelFormat);
-      const PixelBuffer* const sourcePixels       = bitmap.GetBuffer() + ((((scanlinesToCrop / 2) * inputWidth) + (columnsToCrop / 2)) * bytesPerPixel);
+      const PixelBuffer* const sourcePixels       = bitmap.GetBuffer() + ((((scanlinesToCrop / 2) * inputStride) + (columnsToCrop / 2)) * bytesPerPixel);
       PixelBuffer* const       targetPixels       = croppedBitmap.GetBuffer();
       PixelBuffer* const       targetPixelsActive = targetPixels + ((((scanlinesToPad / 2) * desiredWidth) + (columnsToPad / 2)) * bytesPerPixel);
       DALI_ASSERT_DEBUG(sourcePixels && targetPixels);
@@ -992,7 +1006,7 @@ Dali::Devel::PixelBuffer CropAndPadForFittingMode(Dali::Devel::PixelBuffer& bitm
       // Copy the image data to the new bitmap.
       // Optimize to a single memcpy if the left and right edges don't need a crop or a pad.
       unsigned int outputSpan(desiredWidth * bytesPerPixel);
-      if(columnsToCrop == 0 && columnsToPad == 0)
+      if(columnsToCrop == 0 && columnsToPad == 0 && inputStride == inputWidth)
       {
         memcpy(targetPixelsActive, sourcePixels, (desiredHeight - scanlinesToPad) * outputSpan);
       }
@@ -1000,7 +1014,7 @@ Dali::Devel::PixelBuffer CropAndPadForFittingMode(Dali::Devel::PixelBuffer& bitm
       {
         // The width needs to change (due to either a crop or a pad), so we copy a scanline at a time.
         // Precalculate any constants to optimize the inner loop.
-        const unsigned int inputSpan(inputWidth * bytesPerPixel);
+        const unsigned int inputSpan(inputStride * bytesPerPixel);
         const unsigned int copySpan((desiredWidth - columnsToPad) * bytesPerPixel);
         const unsigned int scanlinesToCopy(desiredHeight - scanlinesToPad);
 
@@ -1078,6 +1092,7 @@ Dali::Devel::PixelBuffer DownscaleBitmap(Dali::Devel::PixelBuffer bitmap,
   // Source dimensions as loaded from resources (e.g. filesystem):
   auto bitmapWidth  = bitmap.GetWidth();
   auto bitmapHeight = bitmap.GetHeight();
+  auto bitmapStride = bitmap.GetStride();
   // Desired dimensions (the rectangle to fit the source image to):
   auto desiredWidth  = desired.GetWidth();
   auto desiredHeight = desired.GetHeight();
@@ -1092,8 +1107,8 @@ Dali::Devel::PixelBuffer DownscaleBitmap(Dali::Devel::PixelBuffer bitmap,
     auto pixelFormat = bitmap.GetPixelFormat();
 
     // Do the fast power of 2 iterated box filter to get to roughly the right side if the filter mode requests that:
-    unsigned int shrunkWidth = -1, shrunkHeight = -1;
-    DownscaleInPlacePow2(bitmap.GetBuffer(), pixelFormat, bitmapWidth, bitmapHeight, desiredWidth, desiredHeight, fittingMode, samplingMode, shrunkWidth, shrunkHeight);
+    unsigned int shrunkWidth = -1, shrunkHeight = -1, outStride = -1;
+    DownscaleInPlacePow2(bitmap.GetBuffer(), pixelFormat, bitmapWidth, bitmapHeight, bitmapStride, desiredWidth, desiredHeight, fittingMode, samplingMode, shrunkWidth, shrunkHeight, outStride);
 
     // Work out the dimensions of the downscaled bitmap, given the scaling mode and desired dimensions:
     const ImageDimensions filteredDimensions = FitToScalingMode(ImageDimensions(desiredWidth, desiredHeight), ImageDimensions(shrunkWidth, shrunkHeight), fittingMode);
@@ -1113,11 +1128,11 @@ Dali::Devel::PixelBuffer DownscaleBitmap(Dali::Devel::PixelBuffer bitmap,
         {
           if(samplingMode == SamplingMode::LINEAR || samplingMode == SamplingMode::BOX_THEN_LINEAR)
           {
-            LinearSample(bitmap.GetBuffer(), ImageDimensions(shrunkWidth, shrunkHeight), pixelFormat, outputBitmap.GetBuffer(), filteredDimensions);
+            LinearSample(bitmap.GetBuffer(), ImageDimensions(shrunkWidth, shrunkHeight), outStride, pixelFormat, outputBitmap.GetBuffer(), filteredDimensions);
           }
           else
           {
-            PointSample(bitmap.GetBuffer(), shrunkWidth, shrunkHeight, pixelFormat, outputBitmap.GetBuffer(), filteredWidth, filteredHeight);
+            PointSample(bitmap.GetBuffer(), shrunkWidth, shrunkHeight, outStride, pixelFormat, outputBitmap.GetBuffer(), filteredWidth, filteredHeight);
           }
           filtered = true;
         }
@@ -1126,6 +1141,7 @@ Dali::Devel::PixelBuffer DownscaleBitmap(Dali::Devel::PixelBuffer bitmap,
     // Copy out the 2^x downscaled, box-filtered pixels if no secondary filter (point or linear) was applied:
     if(filtered == false && (shrunkWidth < bitmapWidth || shrunkHeight < bitmapHeight))
     {
+      // The buffer is downscaled and it is tightly packed. We don't need to set a stride.
       outputBitmap = MakePixelBuffer(bitmap.GetBuffer(), pixelFormat, shrunkWidth, shrunkHeight);
     }
   }
@@ -1195,11 +1211,13 @@ template<
 void DownscaleInPlacePow2Generic(unsigned char* const pixels,
                                  const unsigned int   inputWidth,
                                  const unsigned int   inputHeight,
+                                 const unsigned int   inputStride,
                                  const unsigned int   desiredWidth,
                                  const unsigned int   desiredHeight,
                                  BoxDimensionTest     dimensionTest,
                                  unsigned&            outWidth,
-                                 unsigned&            outHeight)
+                                 unsigned&            outHeight,
+                                 unsigned&            outStride)
 {
   if(pixels == 0)
   {
@@ -1209,12 +1227,14 @@ void DownscaleInPlacePow2Generic(unsigned char* const pixels,
 
   // Scale the image until it would be smaller than desired, stopping if the
   // resulting height or width would be less than 1:
-  unsigned int scaledWidth = inputWidth, scaledHeight = inputHeight;
+  unsigned int scaledWidth = inputWidth, scaledHeight = inputHeight, stride = inputStride;
   while(ContinueScaling(dimensionTest, scaledWidth, scaledHeight, desiredWidth, desiredHeight))
   {
-    const unsigned int lastWidth = scaledWidth;
+    const unsigned int lastWidth  = scaledWidth;
+    const unsigned int lastStride = stride;
     scaledWidth >>= 1u;
     scaledHeight >>= 1u;
+    stride = scaledWidth;
 
     DALI_LOG_INFO(gImageOpsLogFilter, Dali::Integration::Log::Verbose, "Scaling to %u\t%u.\n", scaledWidth, scaledHeight);
 
@@ -1224,8 +1244,8 @@ void DownscaleInPlacePow2Generic(unsigned char* const pixels,
     for(unsigned int y = 0; y <= lastScanlinePair; ++y)
     {
       // Scale two scanlines horizontally:
-      HalveScanlineInPlace(&pixels[y * 2 * lastWidth * BYTES_PER_PIXEL], lastWidth);
-      HalveScanlineInPlace(&pixels[(y * 2 + 1) * lastWidth * BYTES_PER_PIXEL], lastWidth);
+      HalveScanlineInPlace(&pixels[y * 2 * lastStride * BYTES_PER_PIXEL], lastWidth);
+      HalveScanlineInPlace(&pixels[(y * 2 + 1) * lastStride * BYTES_PER_PIXEL], lastWidth);
 
       // Scale vertical pairs of pixels while the last two scanlines are still warm in
       // the CPU cache(s):
@@ -1233,8 +1253,8 @@ void DownscaleInPlacePow2Generic(unsigned char* const pixels,
       // images but even a 4k wide RGB888 image will use just 24kB of cache (4k pixels
       // * 3 Bpp * 2 scanlines) for two scanlines on the first iteration.
       AverageScanlines(
-        &pixels[y * 2 * lastWidth * BYTES_PER_PIXEL],
-        &pixels[(y * 2 + 1) * lastWidth * BYTES_PER_PIXEL],
+        &pixels[y * 2 * lastStride * BYTES_PER_PIXEL],
+        &pixels[(y * 2 + 1) * lastStride * BYTES_PER_PIXEL],
         &pixels[y * scaledWidth * BYTES_PER_PIXEL],
         scaledWidth);
     }
@@ -1243,6 +1263,7 @@ void DownscaleInPlacePow2Generic(unsigned char* const pixels,
   ///@note: we could finish off with one of two mutually exclusive passes, one squashing horizontally as far as possible, and the other vertically, if we knew a following cpu point or bilinear filter would restore the desired aspect ratio.
   outWidth  = scaledWidth;
   outHeight = scaledHeight;
+  outStride = stride;
 }
 
 } // namespace
@@ -1511,15 +1532,18 @@ void DownscaleInPlacePow2(unsigned char* const pixels,
                           Pixel::Format        pixelFormat,
                           unsigned int         inputWidth,
                           unsigned int         inputHeight,
+                          unsigned int         inputStride,
                           unsigned int         desiredWidth,
                           unsigned int         desiredHeight,
                           FittingMode::Type    fittingMode,
                           SamplingMode::Type   samplingMode,
                           unsigned&            outWidth,
-                          unsigned&            outHeight)
+                          unsigned&            outHeight,
+                          unsigned&            outStride)
 {
   outWidth  = inputWidth;
   outHeight = inputHeight;
+  outStride = inputStride;
   // Perform power of 2 iterated 4:1 box filtering if the requested filter mode requires it:
   if(samplingMode == SamplingMode::BOX || samplingMode == SamplingMode::BOX_THEN_NEAREST || samplingMode == SamplingMode::BOX_THEN_LINEAR)
   {
@@ -1532,28 +1556,28 @@ void DownscaleInPlacePow2(unsigned char* const pixels,
       {
         case Pixel::RGBA8888:
         {
-          Internal::Platform::DownscaleInPlacePow2RGBA8888(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+          Internal::Platform::DownscaleInPlacePow2RGBA8888(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
           break;
         }
         case Pixel::RGB888:
         {
-          Internal::Platform::DownscaleInPlacePow2RGB888(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+          Internal::Platform::DownscaleInPlacePow2RGB888(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
           break;
         }
         case Pixel::RGB565:
         {
-          Internal::Platform::DownscaleInPlacePow2RGB565(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+          Internal::Platform::DownscaleInPlacePow2RGB565(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
           break;
         }
         case Pixel::LA88:
         {
-          Internal::Platform::DownscaleInPlacePow2ComponentPair(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+          Internal::Platform::DownscaleInPlacePow2ComponentPair(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
           break;
         }
         case Pixel::L8:
         case Pixel::A8:
         {
-          Internal::Platform::DownscaleInPlacePow2SingleBytePerPixel(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+          Internal::Platform::DownscaleInPlacePow2SingleBytePerPixel(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
           break;
         }
         default:
@@ -1572,38 +1596,44 @@ void DownscaleInPlacePow2(unsigned char* const pixels,
 void DownscaleInPlacePow2RGB888(unsigned char*   pixels,
                                 unsigned int     inputWidth,
                                 unsigned int     inputHeight,
+                                unsigned int     inputStride,
                                 unsigned int     desiredWidth,
                                 unsigned int     desiredHeight,
                                 BoxDimensionTest dimensionTest,
                                 unsigned&        outWidth,
-                                unsigned&        outHeight)
+                                unsigned&        outHeight,
+                                unsigned&        outStride)
 {
-  DownscaleInPlacePow2Generic<3, HalveScanlineInPlaceRGB888, AverageScanlines3>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+  DownscaleInPlacePow2Generic<3, HalveScanlineInPlaceRGB888, AverageScanlines3>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
 }
 
 void DownscaleInPlacePow2RGBA8888(unsigned char*   pixels,
                                   unsigned int     inputWidth,
                                   unsigned int     inputHeight,
+                                  unsigned int     inputStride,
                                   unsigned int     desiredWidth,
                                   unsigned int     desiredHeight,
                                   BoxDimensionTest dimensionTest,
                                   unsigned&        outWidth,
-                                  unsigned&        outHeight)
+                                  unsigned&        outHeight,
+                                  unsigned&        outStride)
 {
   DALI_ASSERT_DEBUG(((reinterpret_cast<ptrdiff_t>(pixels) & 3u) == 0u) && "Pointer should be 4-byte aligned for performance on some platforms.");
-  DownscaleInPlacePow2Generic<4, HalveScanlineInPlaceRGBA8888, AverageScanlinesRGBA8888>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+  DownscaleInPlacePow2Generic<4, HalveScanlineInPlaceRGBA8888, AverageScanlinesRGBA8888>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
 }
 
 void DownscaleInPlacePow2RGB565(unsigned char*   pixels,
                                 unsigned int     inputWidth,
                                 unsigned int     inputHeight,
+                                unsigned int     inputStride,
                                 unsigned int     desiredWidth,
                                 unsigned int     desiredHeight,
                                 BoxDimensionTest dimensionTest,
                                 unsigned int&    outWidth,
-                                unsigned int&    outHeight)
+                                unsigned int&    outHeight,
+                                unsigned int&    outStride)
 {
-  DownscaleInPlacePow2Generic<2, HalveScanlineInPlaceRGB565, AverageScanlinesRGB565>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+  DownscaleInPlacePow2Generic<2, HalveScanlineInPlaceRGB565, AverageScanlinesRGB565>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
 }
 
 /**
@@ -1614,25 +1644,29 @@ void DownscaleInPlacePow2RGB565(unsigned char*   pixels,
 void DownscaleInPlacePow2ComponentPair(unsigned char*   pixels,
                                        unsigned int     inputWidth,
                                        unsigned int     inputHeight,
+                                       unsigned int     inputStride,
                                        unsigned int     desiredWidth,
                                        unsigned int     desiredHeight,
                                        BoxDimensionTest dimensionTest,
                                        unsigned&        outWidth,
-                                       unsigned&        outHeight)
+                                       unsigned&        outHeight,
+                                       unsigned&        outStride)
 {
-  DownscaleInPlacePow2Generic<2, HalveScanlineInPlace2Bytes, AverageScanlines2>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+  DownscaleInPlacePow2Generic<2, HalveScanlineInPlace2Bytes, AverageScanlines2>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
 }
 
 void DownscaleInPlacePow2SingleBytePerPixel(unsigned char*   pixels,
                                             unsigned int     inputWidth,
                                             unsigned int     inputHeight,
+                                            unsigned int     inputStride,
                                             unsigned int     desiredWidth,
                                             unsigned int     desiredHeight,
                                             BoxDimensionTest dimensionTest,
                                             unsigned int&    outWidth,
-                                            unsigned int&    outHeight)
+                                            unsigned int&    outHeight,
+                                            unsigned int&    outStride)
 {
-  DownscaleInPlacePow2Generic<1, HalveScanlineInPlace1Byte, AverageScanlines1>(pixels, inputWidth, inputHeight, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight);
+  DownscaleInPlacePow2Generic<1, HalveScanlineInPlace1Byte, AverageScanlines1>(pixels, inputWidth, inputHeight, inputStride, desiredWidth, desiredHeight, dimensionTest, outWidth, outHeight, outStride);
 }
 
 // Point sampling group below
@@ -1650,12 +1684,13 @@ template<typename PIXEL>
 inline void PointSampleAddressablePixels(const uint8_t* inPixels,
                                          unsigned int   inputWidth,
                                          unsigned int   inputHeight,
+                                         unsigned int   inputStride,
                                          uint8_t*       outPixels,
                                          unsigned int   desiredWidth,
                                          unsigned int   desiredHeight)
 {
   DALI_ASSERT_DEBUG(((desiredWidth <= inputWidth && desiredHeight <= inputHeight) ||
-                     outPixels >= inPixels + inputWidth * inputHeight * sizeof(PIXEL) || outPixels <= inPixels - desiredWidth * desiredHeight * sizeof(PIXEL)) &&
+                     outPixels >= inPixels + inputStride * inputHeight * sizeof(PIXEL) || outPixels <= inPixels - desiredWidth * desiredHeight * sizeof(PIXEL)) &&
                     "The input and output buffers must not overlap for an upscaling.");
   DALI_ASSERT_DEBUG(reinterpret_cast<uint64_t>(inPixels) % sizeof(PIXEL) == 0 && "Pixel pointers need to be aligned to the size of the pixels (E.g., 4 bytes for RGBA, 2 bytes for RGB565, ...).");
   DALI_ASSERT_DEBUG(reinterpret_cast<uint64_t>(outPixels) % sizeof(PIXEL) == 0 && "Pixel pointers need to be aligned to the size of the pixels (E.g., 4 bytes for RGBA, 2 bytes for RGB565, ...).");
@@ -1674,11 +1709,11 @@ inline void PointSampleAddressablePixels(const uint8_t* inPixels,
   {
     // Round fixed point y coordinate to nearest integer:
     const unsigned int integerY    = (inY + (1u << 15u)) >> 16u;
-    const PIXEL* const inScanline  = &inAligned[inputWidth * integerY];
+    const PIXEL* const inScanline  = &inAligned[inputStride * integerY];
     PIXEL* const       outScanline = &outAligned[desiredWidth * outY];
 
     DALI_ASSERT_DEBUG(integerY < inputHeight);
-    DALI_ASSERT_DEBUG(reinterpret_cast<const uint8_t*>(inScanline) < (inPixels + inputWidth * inputHeight * sizeof(PIXEL)));
+    DALI_ASSERT_DEBUG(reinterpret_cast<const uint8_t*>(inScanline) < (inPixels + inputStride * inputHeight * sizeof(PIXEL)));
     DALI_ASSERT_DEBUG(reinterpret_cast<uint8_t*>(outScanline) < (outPixels + desiredWidth * desiredHeight * sizeof(PIXEL)));
 
     unsigned int inX = 0;
@@ -1701,33 +1736,36 @@ inline void PointSampleAddressablePixels(const uint8_t* inPixels,
 void PointSample4BPP(const unsigned char* inPixels,
                      unsigned int         inputWidth,
                      unsigned int         inputHeight,
+                     unsigned int         inputStride,
                      unsigned char*       outPixels,
                      unsigned int         desiredWidth,
                      unsigned int         desiredHeight)
 {
-  PointSampleAddressablePixels<uint32_t>(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+  PointSampleAddressablePixels<uint32_t>(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
 }
 
 // RGB565, LA88
 void PointSample2BPP(const unsigned char* inPixels,
                      unsigned int         inputWidth,
                      unsigned int         inputHeight,
+                     unsigned int         inputStride,
                      unsigned char*       outPixels,
                      unsigned int         desiredWidth,
                      unsigned int         desiredHeight)
 {
-  PointSampleAddressablePixels<uint16_t>(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+  PointSampleAddressablePixels<uint16_t>(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
 }
 
 // L8, A8
 void PointSample1BPP(const unsigned char* inPixels,
                      unsigned int         inputWidth,
                      unsigned int         inputHeight,
+                     unsigned int         inputStride,
                      unsigned char*       outPixels,
                      unsigned int         desiredWidth,
                      unsigned int         desiredHeight)
 {
-  PointSampleAddressablePixels<uint8_t>(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+  PointSampleAddressablePixels<uint8_t>(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
 }
 
 /* RGB888
@@ -1736,6 +1774,7 @@ void PointSample1BPP(const unsigned char* inPixels,
 void PointSample3BPP(const uint8_t* inPixels,
                      unsigned int   inputWidth,
                      unsigned int   inputHeight,
+                     unsigned int   inputStride,
                      uint8_t*       outPixels,
                      unsigned int   desiredWidth,
                      unsigned int   desiredHeight)
@@ -1757,7 +1796,7 @@ void PointSample3BPP(const uint8_t* inPixels,
   for(unsigned int outY = 0; outY < desiredHeight; ++outY)
   {
     const unsigned int   integerY    = (inY + (1u << 15u)) >> 16u;
-    const uint8_t* const inScanline  = &inPixels[inputWidth * integerY * BYTES_PER_PIXEL];
+    const uint8_t* const inScanline  = &inPixels[inputStride * integerY * BYTES_PER_PIXEL];
     uint8_t* const       outScanline = &outPixels[desiredWidth * outY * BYTES_PER_PIXEL];
     unsigned int         inX         = 0; //< 16.16 fixed-point input image x-coord.
 
@@ -1790,6 +1829,7 @@ void PointSample3BPP(const uint8_t* inPixels,
 void PointSample(const unsigned char* inPixels,
                  unsigned int         inputWidth,
                  unsigned int         inputHeight,
+                 unsigned int         inputStride,
                  Pixel::Format        pixelFormat,
                  unsigned char*       outPixels,
                  unsigned int         desiredWidth,
@@ -1802,24 +1842,24 @@ void PointSample(const unsigned char* inPixels,
     {
       case Pixel::RGB888:
       {
-        PointSample3BPP(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+        PointSample3BPP(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
         break;
       }
       case Pixel::RGBA8888:
       {
-        PointSample4BPP(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+        PointSample4BPP(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
         break;
       }
       case Pixel::RGB565:
       case Pixel::LA88:
       {
-        PointSample2BPP(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+        PointSample2BPP(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
         break;
       }
       case Pixel::L8:
       case Pixel::A8:
       {
-        PointSample1BPP(inPixels, inputWidth, inputHeight, outPixels, desiredWidth, desiredHeight);
+        PointSample1BPP(inPixels, inputWidth, inputHeight, inputStride, outPixels, desiredWidth, desiredHeight);
         break;
       }
       default:
@@ -1894,6 +1934,7 @@ template<
   bool DEBUG_ASSERT_ALIGNMENT>
 inline void LinearSampleGeneric(const unsigned char* __restrict__ inPixels,
                                 ImageDimensions inputDimensions,
+                                unsigned int    inputStride,
                                 unsigned char* __restrict__ outPixels,
                                 ImageDimensions desiredDimensions)
 {
@@ -1902,7 +1943,7 @@ inline void LinearSampleGeneric(const unsigned char* __restrict__ inPixels,
   const unsigned int desiredWidth  = desiredDimensions.GetWidth();
   const unsigned int desiredHeight = desiredDimensions.GetHeight();
 
-  DALI_ASSERT_DEBUG(((outPixels >= inPixels + inputWidth * inputHeight * sizeof(PIXEL)) ||
+  DALI_ASSERT_DEBUG(((outPixels >= inPixels + inputStride * inputHeight * sizeof(PIXEL)) ||
                      (inPixels >= outPixels + desiredWidth * desiredHeight * sizeof(PIXEL))) &&
                     "Input and output buffers cannot overlap.");
   if(DEBUG_ASSERT_ALIGNMENT)
@@ -1933,8 +1974,8 @@ inline void LinearSampleGeneric(const unsigned char* __restrict__ inPixels,
     DALI_ASSERT_DEBUG(integerY1 < inputHeight);
     DALI_ASSERT_DEBUG(integerY2 < inputHeight);
 
-    const PIXEL* const inScanline1 = &inAligned[inputWidth * integerY1];
-    const PIXEL* const inScanline2 = &inAligned[inputWidth * integerY2];
+    const PIXEL* const inScanline1 = &inAligned[inputStride * integerY1];
+    const PIXEL* const inScanline2 = &inAligned[inputStride * integerY2];
 
     unsigned int inX = 0;
     for(unsigned int outX = 0; outX < desiredWidth; ++outX)
@@ -1966,46 +2007,52 @@ inline void LinearSampleGeneric(const unsigned char* __restrict__ inPixels,
 
 void LinearSample1BPP(const unsigned char* __restrict__ inPixels,
                       ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
                       unsigned char* __restrict__ outPixels,
                       ImageDimensions desiredDimensions)
 {
-  LinearSampleGeneric<uint8_t, BilinearFilter1BPPByte, false>(inPixels, inputDimensions, outPixels, desiredDimensions);
+  LinearSampleGeneric<uint8_t, BilinearFilter1BPPByte, false>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
 }
 
 void LinearSample2BPP(const unsigned char* __restrict__ inPixels,
                       ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
                       unsigned char* __restrict__ outPixels,
                       ImageDimensions desiredDimensions)
 {
-  LinearSampleGeneric<Pixel2Bytes, BilinearFilter2Bytes, true>(inPixels, inputDimensions, outPixels, desiredDimensions);
+  LinearSampleGeneric<Pixel2Bytes, BilinearFilter2Bytes, true>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
 }
 
 void LinearSampleRGB565(const unsigned char* __restrict__ inPixels,
                         ImageDimensions inputDimensions,
+                        unsigned int    inputStride,
                         unsigned char* __restrict__ outPixels,
                         ImageDimensions desiredDimensions)
 {
-  LinearSampleGeneric<PixelRGB565, BilinearFilterRGB565, true>(inPixels, inputDimensions, outPixels, desiredDimensions);
+  LinearSampleGeneric<PixelRGB565, BilinearFilterRGB565, true>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
 }
 
 void LinearSample3BPP(const unsigned char* __restrict__ inPixels,
                       ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
                       unsigned char* __restrict__ outPixels,
                       ImageDimensions desiredDimensions)
 {
-  LinearSampleGeneric<Pixel3Bytes, BilinearFilterRGB888, false>(inPixels, inputDimensions, outPixels, desiredDimensions);
+  LinearSampleGeneric<Pixel3Bytes, BilinearFilterRGB888, false>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
 }
 
 void LinearSample4BPP(const unsigned char* __restrict__ inPixels,
                       ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
                       unsigned char* __restrict__ outPixels,
                       ImageDimensions desiredDimensions)
 {
-  LinearSampleGeneric<Pixel4Bytes, BilinearFilter4Bytes, true>(inPixels, inputDimensions, outPixels, desiredDimensions);
+  LinearSampleGeneric<Pixel4Bytes, BilinearFilter4Bytes, true>(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions);
 }
 
 void Resample(const unsigned char* __restrict__ inPixels,
               ImageDimensions inputDimensions,
+              unsigned int    inputStride,
               unsigned char* __restrict__ outPixels,
               ImageDimensions   desiredDimensions,
               Resampler::Filter filterType,
@@ -2089,7 +2136,7 @@ void Resample(const unsigned char* __restrict__ inPixels,
     samples[i].ResizeUninitialized(srcWidth);
   }
 
-  const int srcPitch = srcWidth * numChannels;
+  const int srcPitch = inputStride * numChannels;
   const int dstPitch = dstWidth * numChannels;
   int       dstY     = 0;
 
@@ -2185,24 +2232,27 @@ void Resample(const unsigned char* __restrict__ inPixels,
 
 void LanczosSample4BPP(const unsigned char* __restrict__ inPixels,
                        ImageDimensions inputDimensions,
+                       unsigned int    inputStride,
                        unsigned char* __restrict__ outPixels,
                        ImageDimensions desiredDimensions)
 {
-  Resample(inPixels, inputDimensions, outPixels, desiredDimensions, Resampler::LANCZOS4, 4, true);
+  Resample(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions, Resampler::LANCZOS4, 4, true);
 }
 
 void LanczosSample1BPP(const unsigned char* __restrict__ inPixels,
                        ImageDimensions inputDimensions,
+                       unsigned int    inputStride,
                        unsigned char* __restrict__ outPixels,
                        ImageDimensions desiredDimensions)
 {
   // For L8 images
-  Resample(inPixels, inputDimensions, outPixels, desiredDimensions, Resampler::LANCZOS4, 1, false);
+  Resample(inPixels, inputDimensions, inputStride, outPixels, desiredDimensions, Resampler::LANCZOS4, 1, false);
 }
 
 // Dispatch to a format-appropriate linear sampling function:
 void LinearSample(const unsigned char* __restrict__ inPixels,
                   ImageDimensions inDimensions,
+                  unsigned int    inStride,
                   Pixel::Format   pixelFormat,
                   unsigned char* __restrict__ outPixels,
                   ImageDimensions outDimensions)
@@ -2214,28 +2264,28 @@ void LinearSample(const unsigned char* __restrict__ inPixels,
     {
       case Pixel::RGB888:
       {
-        LinearSample3BPP(inPixels, inDimensions, outPixels, outDimensions);
+        LinearSample3BPP(inPixels, inDimensions, inStride, outPixels, outDimensions);
         break;
       }
       case Pixel::RGBA8888:
       {
-        LinearSample4BPP(inPixels, inDimensions, outPixels, outDimensions);
+        LinearSample4BPP(inPixels, inDimensions, inStride, outPixels, outDimensions);
         break;
       }
       case Pixel::L8:
       case Pixel::A8:
       {
-        LinearSample1BPP(inPixels, inDimensions, outPixels, outDimensions);
+        LinearSample1BPP(inPixels, inDimensions, inStride, outPixels, outDimensions);
         break;
       }
       case Pixel::LA88:
       {
-        LinearSample2BPP(inPixels, inDimensions, outPixels, outDimensions);
+        LinearSample2BPP(inPixels, inDimensions, inStride, outPixels, outDimensions);
         break;
       }
       case Pixel::RGB565:
       {
-        LinearSampleRGB565(inPixels, inDimensions, outPixels, outDimensions);
+        LinearSampleRGB565(inPixels, inDimensions, inStride, outPixels, outDimensions);
         break;
       }
       default:
@@ -2253,6 +2303,7 @@ void LinearSample(const unsigned char* __restrict__ inPixels,
 void RotateByShear(const uint8_t* const pixelsIn,
                    unsigned int         widthIn,
                    unsigned int         heightIn,
+                   unsigned int         strideIn,
                    unsigned int         pixelSize,
                    float                radians,
                    uint8_t*&            pixelsOut,
@@ -2273,6 +2324,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
     fastRotationPerformed = Rotate90(pixelsIn,
                                      widthIn,
                                      heightIn,
+                                     strideIn,
                                      pixelSize,
                                      pixelsOut,
                                      widthOut,
@@ -2297,6 +2349,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
     fastRotationPerformed = Rotate180(pixelsIn,
                                       widthIn,
                                       heightIn,
+                                      strideIn,
                                       pixelSize,
                                       pixelsOut);
 
@@ -2321,6 +2374,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
     fastRotationPerformed = Rotate270(pixelsIn,
                                       widthIn,
                                       heightIn,
+                                      strideIn,
                                       pixelSize,
                                       pixelsOut,
                                       widthOut,
@@ -2348,6 +2402,8 @@ void RotateByShear(const uint8_t* const pixelsIn,
   const uint8_t* const                      firstHorizontalSkewPixelsIn = fastRotationPerformed ? pixelsOut : pixelsIn;
   std::unique_ptr<uint8_t, void (*)(void*)> tmpPixelsInPtr((fastRotationPerformed ? pixelsOut : nullptr), free);
 
+  unsigned int stride = fastRotationPerformed ? widthOut : strideIn;
+
   // Reset the input/output
   widthIn   = widthOut;
   heightIn  = heightOut;
@@ -2386,7 +2442,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
     const float shear = angleTangent * ((angleTangent >= 0.f) ? (0.5f + static_cast<float>(y)) : (0.5f + static_cast<float>(y) - static_cast<float>(heightOut)));
 
     const int intShear = static_cast<int>(floor(shear));
-    HorizontalSkew(firstHorizontalSkewPixelsIn, widthIn, pixelSize, pixelsOut, widthOut, y, intShear, shear - static_cast<float>(intShear));
+    HorizontalSkew(firstHorizontalSkewPixelsIn, widthIn, stride, pixelSize, pixelsOut, widthOut, y, intShear, shear - static_cast<float>(intShear));
   }
 
   // Reset the 'pixel in' pointer with the output of the 'First Horizontal Skew' and free the memory allocated by the 'Fast Rotations'.
@@ -2425,7 +2481,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
   for(column = 0u; column < widthOut; ++column, offset -= angleSinus)
   {
     const int shear = static_cast<int>(floor(offset));
-    VerticalSkew(tmpPixelsInPtr.get(), tmpWidthIn, tmpHeightIn, pixelSize, pixelsOut, widthOut, heightOut, column, shear, offset - static_cast<float>(shear));
+    VerticalSkew(tmpPixelsInPtr.get(), tmpWidthIn, tmpHeightIn, tmpWidthIn, pixelSize, pixelsOut, widthOut, heightOut, column, shear, offset - static_cast<float>(shear));
   }
   // Reset the 'pixel in' pointer with the output of the 'Vertical Skew' and free the memory allocated by the 'First Horizontal Skew'.
   // Reset the input/output
@@ -2460,7 +2516,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
   for(unsigned int y = 0u; y < heightOut; ++y, offset += angleTangent)
   {
     const int shear = static_cast<int>(floor(offset));
-    HorizontalSkew(tmpPixelsInPtr.get(), tmpWidthIn, pixelSize, pixelsOut, widthOut, y, shear, offset - static_cast<float>(shear));
+    HorizontalSkew(tmpPixelsInPtr.get(), tmpWidthIn, tmpWidthIn, pixelSize, pixelsOut, widthOut, y, shear, offset - static_cast<float>(shear));
   }
 
   // The deleter of the tmpPixelsInPtr unique pointer is called freeing the memory allocated by the 'Vertical Skew'.
@@ -2470,6 +2526,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
 void HorizontalShear(const uint8_t* const pixelsIn,
                      unsigned int         widthIn,
                      unsigned int         heightIn,
+                     unsigned int         strideIn,
                      unsigned int         pixelSize,
                      float                radians,
                      uint8_t*&            pixelsOut,
@@ -2510,7 +2567,7 @@ void HorizontalShear(const uint8_t* const pixelsIn,
     const float shear = radians * ((radians >= 0.f) ? (0.5f + static_cast<float>(y)) : (0.5f + static_cast<float>(y) - static_cast<float>(heightOut)));
 
     const int intShear = static_cast<int>(floor(shear));
-    HorizontalSkew(pixelsIn, widthIn, pixelSize, pixelsOut, widthOut, y, intShear, shear - static_cast<float>(intShear));
+    HorizontalSkew(pixelsIn, widthIn, strideIn, pixelSize, pixelsOut, widthOut, y, intShear, shear - static_cast<float>(intShear));
   }
 }
 
index d1105ad..fd330a0 100644 (file)
@@ -107,21 +107,25 @@ Dali::Devel::PixelBuffer DownscaleBitmap(Dali::Devel::PixelBuffer bitmap,
  * @param[in]     pixelFormat The format of the image pointed at by pixels.
  * @param[in]     inputWidth The width of the input image.
  * @param[in]     inputHeight The height of the input image.
+ * @param[in]     inputStride The stride of the input image.
  * @param[in]     desiredWidth The width the client is requesting.
  * @param[in]     desiredHeight The height the client is requesting.
  * @param[out]    outWidth  The resulting width after downscaling.
  * @param[out]    outHeight The resulting height after downscaling.
+ * @param[out]    outStride The resulting stride after downscaling.
  */
 void DownscaleInPlacePow2(unsigned char* const pixels,
                           Pixel::Format        pixelFormat,
                           unsigned int         inputWidth,
                           unsigned int         inputHeight,
+                          unsigned int         inputStride,
                           unsigned int         desiredWidth,
                           unsigned int         desiredHeight,
                           FittingMode::Type    fittingMode,
                           SamplingMode::Type   samplingMode,
                           unsigned&            outWidth,
-                          unsigned&            outHeight);
+                          unsigned&            outHeight,
+                          unsigned&            outStride);
 
 /**
  * @brief Destructive in-place downscaling by a power of 2 factor.
@@ -132,19 +136,23 @@ void DownscaleInPlacePow2(unsigned char* const pixels,
  * @param[in,out] pixels The buffer both to read from and write the result to.
  * @param[in]     inputWidth The width of the input image.
  * @param[in]     inputHeight The height of the input image.
+ * @param[in]     inputStride The stride of the input image.
  * @param[in]     desiredWidth The width the client is requesting.
  * @param[in]     desiredHeight The height the client is requesting.
  * @param[out]    outWidth  The resulting width after downscaling.
  * @param[out]    outHeight The resulting height after downscaling.
+ * @param[out]    outStride The resulting stride after downscaling.
  */
 void DownscaleInPlacePow2RGB888(unsigned char*   pixels,
                                 unsigned int     inputWidth,
                                 unsigned int     inputHeight,
+                                unsigned int     inputStride,
                                 unsigned int     desiredWidth,
                                 unsigned int     desiredHeight,
                                 BoxDimensionTest dimensionTest,
                                 unsigned int&    outWidth,
-                                unsigned int&    outHeight);
+                                unsigned int&    outHeight,
+                                unsigned int&    outStride);
 
 /**
  * @copydoc DownscaleInPlacePow2RGB888
@@ -152,11 +160,13 @@ void DownscaleInPlacePow2RGB888(unsigned char*   pixels,
 void DownscaleInPlacePow2RGBA8888(unsigned char*   pixels,
                                   unsigned int     inputWidth,
                                   unsigned int     inputHeight,
+                                  unsigned int     inputStride,
                                   unsigned int     desiredWidth,
                                   unsigned int     desiredHeight,
                                   BoxDimensionTest dimensionTest,
                                   unsigned int&    outWidth,
-                                  unsigned int&    outHeight);
+                                  unsigned int&    outHeight,
+                                  unsigned int&    outStride);
 
 /**
  * @copydoc DownscaleInPlacePow2RGB888
@@ -166,11 +176,13 @@ void DownscaleInPlacePow2RGBA8888(unsigned char*   pixels,
 void DownscaleInPlacePow2RGB565(unsigned char*   pixels,
                                 unsigned int     inputWidth,
                                 unsigned int     inputHeight,
+                                unsigned int     inputStride,
                                 unsigned int     desiredWidth,
                                 unsigned int     desiredHeight,
                                 BoxDimensionTest dimensionTest,
                                 unsigned int&    outWidth,
-                                unsigned int&    outHeight);
+                                unsigned int&    outHeight,
+                                unsigned int&    outStride);
 
 /**
  * @copydoc DownscaleInPlacePow2RGB888
@@ -180,11 +192,13 @@ void DownscaleInPlacePow2RGB565(unsigned char*   pixels,
 void DownscaleInPlacePow2ComponentPair(unsigned char*   pixels,
                                        unsigned int     inputWidth,
                                        unsigned int     inputHeight,
+                                       unsigned int     inputStride,
                                        unsigned int     desiredWidth,
                                        unsigned int     desiredHeight,
                                        BoxDimensionTest dimensionTest,
                                        unsigned int&    outWidth,
-                                       unsigned int&    outHeight);
+                                       unsigned int&    outHeight,
+                                       unsigned int&    outStride);
 
 /**
  * @copydoc DownscaleInPlacePow2RGB888
@@ -194,11 +208,13 @@ void DownscaleInPlacePow2ComponentPair(unsigned char*   pixels,
 void DownscaleInPlacePow2SingleBytePerPixel(unsigned char*   pixels,
                                             unsigned int     inputWidth,
                                             unsigned int     inputHeight,
+                                            unsigned int     inputStride,
                                             unsigned int     desiredWidth,
                                             unsigned int     desiredHeight,
                                             BoxDimensionTest dimensionTest,
                                             unsigned int&    outWidth,
-                                            unsigned int&    outHeight);
+                                            unsigned int&    outHeight,
+                                            unsigned int&    outStride);
 
 /**
  * @brief Rescales an input image into the exact output dimensions passed-in.
@@ -211,6 +227,7 @@ void DownscaleInPlacePow2SingleBytePerPixel(unsigned char*   pixels,
 void PointSample(const unsigned char* inPixels,
                  unsigned int         inputWidth,
                  unsigned int         inputHeight,
+                 unsigned int         inputStride,
                  Pixel::Format        pixelFormat,
                  unsigned char*       outPixels,
                  unsigned int         desiredWidth,
@@ -224,6 +241,7 @@ void PointSample(const unsigned char* inPixels,
 void PointSample4BPP(const unsigned char* inPixels,
                      unsigned int         inputWidth,
                      unsigned int         inputHeight,
+                     unsigned int         inputStride,
                      unsigned char*       outPixels,
                      unsigned int         desiredWidth,
                      unsigned int         desiredHeight);
@@ -236,6 +254,7 @@ void PointSample4BPP(const unsigned char* inPixels,
 void PointSample3BPP(const unsigned char* inPixels,
                      unsigned int         inputWidth,
                      unsigned int         inputHeight,
+                     unsigned int         inputStride,
                      unsigned char*       outPixels,
                      unsigned int         desiredWidth,
                      unsigned int         desiredHeight);
@@ -248,6 +267,7 @@ void PointSample3BPP(const unsigned char* inPixels,
 void PointSample2BPP(const unsigned char* inPixels,
                      unsigned int         inputWidth,
                      unsigned int         inputHeight,
+                     unsigned int         inputStride,
                      unsigned char*       outPixels,
                      unsigned int         desiredWidth,
                      unsigned int         desiredHeight);
@@ -260,6 +280,7 @@ void PointSample2BPP(const unsigned char* inPixels,
 void PointSample1BPP(const unsigned char* inPixels,
                      unsigned int         inputWidth,
                      unsigned int         inputHeight,
+                     unsigned int         inputStride,
                      unsigned char*       outPixels,
                      unsigned int         desiredWidth,
                      unsigned int         desiredHeight);
@@ -274,6 +295,7 @@ void PointSample1BPP(const unsigned char* inPixels,
  */
 void LinearSample(const unsigned char* __restrict__ inPixels,
                   ImageDimensions inDimensions,
+                  unsigned int    inStride,
                   Pixel::Format   pixelFormat,
                   unsigned char* __restrict__ outPixels,
                   ImageDimensions outDimensions);
@@ -285,6 +307,7 @@ void LinearSample(const unsigned char* __restrict__ inPixels,
  */
 void LinearSample1BPP(const unsigned char* __restrict__ inPixels,
                       ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
                       unsigned char* __restrict__ outPixels,
                       ImageDimensions desiredDimensions);
 
@@ -295,6 +318,7 @@ void LinearSample1BPP(const unsigned char* __restrict__ inPixels,
  */
 void LinearSample2BPP(const unsigned char* __restrict__ inPixels,
                       ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
                       unsigned char* __restrict__ outPixels,
                       ImageDimensions desiredDimensions);
 
@@ -305,6 +329,7 @@ void LinearSample2BPP(const unsigned char* __restrict__ inPixels,
  */
 void LinearSampleRGB565(const unsigned char* __restrict__ inPixels,
                         ImageDimensions inputDimensions,
+                        unsigned int    inputStride,
                         unsigned char* __restrict__ outPixels,
                         ImageDimensions desiredDimensions);
 
@@ -315,6 +340,7 @@ void LinearSampleRGB565(const unsigned char* __restrict__ inPixels,
  */
 void LinearSample3BPP(const unsigned char* __restrict__ inPixels,
                       ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
                       unsigned char* __restrict__ outPixels,
                       ImageDimensions desiredDimensions);
 
@@ -326,6 +352,7 @@ void LinearSample3BPP(const unsigned char* __restrict__ inPixels,
  */
 void LinearSample4BPP(const unsigned char* __restrict__ inPixels,
                       ImageDimensions inputDimensions,
+                      unsigned int    inputStride,
                       unsigned char* __restrict__ outPixels,
                       ImageDimensions desiredDimensions);
 
@@ -337,11 +364,13 @@ void LinearSample4BPP(const unsigned char* __restrict__ inPixels,
  *
  * @param[in] inPixels Pointer to the input image buffer.
  * @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride of the image.
  * @param[out] outPixels Pointer to the output image buffer.
  * @param[in] desiredDimensions The output dimensions of the image.
  */
 void LanczosSample4BPP(const unsigned char* __restrict__ inPixels,
                        ImageDimensions inputDimensions,
+                       unsigned int    inputStride,
                        unsigned char* __restrict__ outPixels,
                        ImageDimensions desiredDimensions);
 
@@ -353,11 +382,13 @@ void LanczosSample4BPP(const unsigned char* __restrict__ inPixels,
  *
  * @param[in] inPixels Pointer to the input image buffer.
  * @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride of the image.
  * @param[out] outPixels Pointer to the output image buffer.
  * @param[in] desiredDimensions The output dimensions of the image.
  */
 void LanczosSample1BPP(const unsigned char* __restrict__ inPixels,
                        ImageDimensions inputDimensions,
+                       unsigned int    inputStride,
                        unsigned char* __restrict__ outPixels,
                        ImageDimensions desiredDimensions);
 
@@ -369,11 +400,13 @@ void LanczosSample1BPP(const unsigned char* __restrict__ inPixels,
  *
  * @param[in] inPixels Pointer to the input image buffer.
  * @param[in] inputDimensions The input dimensions of the image.
+ * @param[in] inputStride The input stride of the image.
  * @param[out] outPixels Pointer to the output image buffer.
  * @param[in] desiredDimensions The output dimensions of the image.
  */
 void Resample(const unsigned char* __restrict__ inPixels,
               ImageDimensions inputDimensions,
+              unsigned int    inputStride,
               unsigned char* __restrict__ outPixels,
               ImageDimensions   desiredDimensions,
               Resampler::Filter filterType,
@@ -391,6 +424,7 @@ void Resample(const unsigned char* __restrict__ inPixels,
  * @param[in] pixelsIn The input buffer.
  * @param[in] widthIn The width of the input buffer.
  * @param[in] heightIn The height of the input buffer.
+ * @param[in] strideIn The stride of the input buffer.
  * @param[in] pixelSize The size of the pixel.
  * @param[in] radians The rotation angle in radians.
  * @param[out] pixelsOut The rotated output buffer.
@@ -400,6 +434,7 @@ void Resample(const unsigned char* __restrict__ inPixels,
 void RotateByShear(const uint8_t* const pixelsIn,
                    unsigned int         widthIn,
                    unsigned int         heightIn,
+                   unsigned int         strideIn,
                    unsigned int         pixelSize,
                    float                radians,
                    uint8_t*&            pixelsOut,
@@ -418,6 +453,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
  * @param[in] pixelsIn The input buffer.
  * @param[in] widthIn The width of the input buffer.
  * @param[in] heightIn The height of the input buffer.
+ * @param[in] strideIn The stride of the input buffer.
  * @param[in] pixelSize The size of the pixel.
  * @param[in] radians The shear angle in radians.
  * @param[out] pixelsOut The rotated output buffer.
@@ -427,6 +463,7 @@ void RotateByShear(const uint8_t* const pixelsIn,
 void HorizontalShear(const uint8_t* const pixelsIn,
                      unsigned int         widthIn,
                      unsigned int         heightIn,
+                     unsigned int         strideIn,
                      unsigned int         pixelSize,
                      float                radians,
                      uint8_t*&            pixelsOut,
index 4ff2250..f2594ac 100644 (file)
@@ -47,12 +47,14 @@ PixelBuffer::PixelBuffer(unsigned char*      buffer,
                          unsigned int        bufferSize,
                          unsigned int        width,
                          unsigned int        height,
+                         unsigned int        stride,
                          Dali::Pixel::Format pixelFormat)
 : mMetadata(),
   mBuffer(buffer),
   mBufferSize(bufferSize),
   mWidth(width),
   mHeight(height),
+  mStride(stride ? stride : width),
   mPixelFormat(pixelFormat),
   mPreMultiplied(false)
 {
@@ -73,16 +75,17 @@ PixelBufferPtr PixelBuffer::New(unsigned int        width,
   {
     buffer = static_cast<unsigned char*>(malloc(bufferSize));
   }
-  return new PixelBuffer(buffer, bufferSize, width, height, pixelFormat);
+  return new PixelBuffer(buffer, bufferSize, width, height, width, pixelFormat);
 }
 
 PixelBufferPtr PixelBuffer::New(unsigned char*      buffer,
                                 unsigned int        bufferSize,
                                 unsigned int        width,
                                 unsigned int        height,
+                                unsigned int        stride,
                                 Dali::Pixel::Format pixelFormat)
 {
-  return new PixelBuffer(buffer, bufferSize, width, height, pixelFormat);
+  return new PixelBuffer(buffer, bufferSize, width, height, stride, pixelFormat);
 }
 
 Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer)
@@ -91,12 +94,14 @@ Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer)
                                                    pixelBuffer.mBufferSize,
                                                    pixelBuffer.mWidth,
                                                    pixelBuffer.mHeight,
+                                                   pixelBuffer.mStride,
                                                    pixelBuffer.mPixelFormat,
                                                    Dali::PixelData::FREE);
   pixelBuffer.mBuffer       = NULL;
   pixelBuffer.mWidth        = 0;
   pixelBuffer.mHeight       = 0;
   pixelBuffer.mBufferSize   = 0;
+  pixelBuffer.mStride       = 0;
 
   return pixelData;
 }
@@ -111,6 +116,11 @@ unsigned int PixelBuffer::GetHeight() const
   return mHeight;
 }
 
+uint32_t PixelBuffer::GetStride() const
+{
+  return mStride;
+}
+
 Dali::Pixel::Format PixelBuffer::GetPixelFormat() const
 {
   return mPixelFormat;
@@ -141,7 +151,7 @@ Dali::PixelData PixelBuffer::CreatePixelData() const
     memcpy(destBuffer, mBuffer, mBufferSize);
   }
 
-  Dali::PixelData pixelData = Dali::PixelData::New(destBuffer, mBufferSize, mWidth, mHeight, mPixelFormat, Dali::PixelData::FREE);
+  Dali::PixelData pixelData = Dali::PixelData::New(destBuffer, mBufferSize, mWidth, mHeight, mStride, mPixelFormat, Dali::PixelData::FREE);
   return pixelData;
 }
 
@@ -201,6 +211,7 @@ void PixelBuffer::TakeOwnershipOfBuffer(PixelBuffer& pixelBuffer)
   mBufferSize         = pixelBuffer.mBufferSize;
   mWidth              = pixelBuffer.mWidth;
   mHeight             = pixelBuffer.mHeight;
+  mStride             = pixelBuffer.mStride;
   mPixelFormat        = pixelBuffer.mPixelFormat;
 }
 
@@ -271,6 +282,7 @@ bool PixelBuffer::Rotate(Degree angle)
   Platform::RotateByShear(mBuffer,
                           mWidth,
                           mHeight,
+                          mStride,
                           pixelSize,
                           radians,
                           pixelsOut,
@@ -289,6 +301,7 @@ bool PixelBuffer::Rotate(Degree angle)
     mBuffer     = pixelsOut;
     pixelsOut   = nullptr;
     mBufferSize = mWidth * mHeight * pixelSize;
+    mStride     = mWidth; // The buffer is tightly packed.
   }
 
   return success;
@@ -327,8 +340,8 @@ PixelBufferPtr PixelBuffer::NewCrop(const PixelBuffer& inBuffer, uint16_t x, uin
 {
   PixelBufferPtr outBuffer     = PixelBuffer::New(cropDimensions.GetWidth(), cropDimensions.GetHeight(), inBuffer.GetPixelFormat());
   int            bytesPerPixel = Pixel::GetBytesPerPixel(inBuffer.mPixelFormat);
-  int            srcStride     = inBuffer.mWidth * bytesPerPixel;
-  int            destStride    = cropDimensions.GetWidth() * bytesPerPixel;
+  int            srcStride     = inBuffer.mStride * bytesPerPixel;
+  int            destStride    = cropDimensions.GetWidth() * bytesPerPixel; // The destination buffer is tightly packed
 
   // Clamp crop to right edge
   if(x + cropDimensions.GetWidth() > inBuffer.mWidth)
@@ -409,7 +422,7 @@ PixelBufferPtr PixelBuffer::NewResize(const PixelBuffer& inBuffer, ImageDimensio
      inBuffer.mPixelFormat == Pixel::RGBA8888 ||
      inBuffer.mPixelFormat == Pixel::BGRA8888)
   {
-    Dali::Internal::Platform::Resample(inBuffer.mBuffer, inDimensions, outBuffer->GetBuffer(), outDimensions, filterType, bytesPerPixel, hasAlpha);
+    Dali::Internal::Platform::Resample(inBuffer.mBuffer, inDimensions, inBuffer.mStride, outBuffer->GetBuffer(), outDimensions, filterType, bytesPerPixel, hasAlpha);
   }
   else
   {
@@ -443,8 +456,9 @@ void PixelBuffer::MultiplyColorByAlpha()
   // must be skipped in such case
   if(Pixel::GetBytesPerPixel(mPixelFormat) && Pixel::HasAlpha(mPixelFormat))
   {
-    unsigned char*     pixel      = mBuffer;
-    const unsigned int bufferSize = mWidth * mHeight;
+    unsigned char*     pixel       = mBuffer;
+    const unsigned int strideBytes = mStride * bytesPerPixel;
+    const unsigned int widthBytes  = mWidth * bytesPerPixel;
 
     // Collect all valid channel list before lookup whole buffer
     std::vector<Channel> validChannelList;
@@ -458,32 +472,35 @@ void PixelBuffer::MultiplyColorByAlpha()
 
     if(DALI_LIKELY(!validChannelList.empty()))
     {
-      for(unsigned int i = 0; i < bufferSize; ++i)
+      for(unsigned int y = 0; y < mHeight; y++)
       {
-        unsigned int alpha = ReadChannel(pixel, mPixelFormat, Adaptor::ALPHA);
-        if(alpha < 255)
+        for(unsigned int x = 0; x < widthBytes; x += bytesPerPixel)
         {
-          // If alpha is 255, we don't need to change color. Skip current pixel
-          // But if alpha is not 255, we should change color.
-          if(alpha > 0)
+          unsigned int alpha = ReadChannel(&pixel[x], mPixelFormat, Adaptor::ALPHA);
+          if(alpha < 255)
           {
-            for(const Channel& channel : validChannelList)
+            // If alpha is 255, we don't need to change color. Skip current pixel
+            // But if alpha is not 255, we should change color.
+            if(alpha > 0)
             {
-              auto color = ReadChannel(pixel, mPixelFormat, channel);
-              WriteChannel(pixel, mPixelFormat, channel, color * alpha / 255);
+              for(const Channel& channel : validChannelList)
+              {
+                auto color = ReadChannel(&pixel[x], mPixelFormat, channel);
+                WriteChannel(&pixel[x], mPixelFormat, channel, color * alpha / 255);
+              }
+            }
+            else
+            {
+              // If alpha is 0, just set all pixel as zero.
+              memset(&pixel[x], 0, bytesPerPixel);
             }
-          }
-          else
-          {
-            // If alpha is 0, just set all pixel as zero.
-            memset(pixel, 0, bytesPerPixel);
           }
         }
-        pixel += bytesPerPixel;
+        pixel += strideBytes;
       }
     }
+    mPreMultiplied = true;
   }
-  mPreMultiplied = true;
 }
 
 bool PixelBuffer::IsAlphaPreMultiplied() const
@@ -493,30 +510,33 @@ bool PixelBuffer::IsAlphaPreMultiplied() const
 
 uint32_t PixelBuffer::GetBrightness() const
 {
-  uint32_t brightness = 0;
-
+  uint32_t brightness    = 0;
   uint32_t bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
-  if(bytesPerPixel)
+
+  if(bytesPerPixel && mWidth && mHeight)
   {
-    unsigned char* pixel      = mBuffer;
-    const uint32_t bufferSize = mWidth * mHeight;
+    unsigned char* pixel       = mBuffer;
+    const uint32_t strideBytes = mStride * bytesPerPixel;
+    const uint32_t widthBytes  = mWidth * bytesPerPixel;
+    const uint32_t bufferSize  = mWidth * mHeight;
 
-    if(bufferSize) // avoid division by zero to calculate brightness
-    {
-      uint64_t red   = 0;
-      uint64_t green = 0;
-      uint64_t blue  = 0;
+    uint64_t red   = 0;
+    uint64_t green = 0;
+    uint64_t blue  = 0;
 
-      for(uint32_t i = 0; i < bufferSize; ++i)
+    for(unsigned int y = 0; y < mHeight; y++)
+    {
+      for(unsigned int x = 0; x < widthBytes; x += bytesPerPixel)
       {
-        red += ReadChannel(pixel, mPixelFormat, Adaptor::RED);
-        green += ReadChannel(pixel, mPixelFormat, Adaptor::GREEN);
-        blue += ReadChannel(pixel, mPixelFormat, Adaptor::BLUE);
-        pixel += bytesPerPixel;
+        red += ReadChannel(&pixel[x], mPixelFormat, Adaptor::RED);
+        green += ReadChannel(&pixel[x], mPixelFormat, Adaptor::GREEN);
+        blue += ReadChannel(&pixel[x], mPixelFormat, Adaptor::BLUE);
       }
-      // http://www.w3.org/TR/AERT#color-contrast
-      brightness = (red * BRIGHTNESS_CONSTANT_R + green * BRIGHTNESS_CONSTANT_G + blue * BRIGHTNESS_CONSTANT_B) / (1000uLL * bufferSize);
+      pixel += strideBytes;
     }
+
+    // http://www.w3.org/TR/AERT#color-contrast
+    brightness = (red * BRIGHTNESS_CONSTANT_R + green * BRIGHTNESS_CONSTANT_G + blue * BRIGHTNESS_CONSTANT_B) / (1000uLL * bufferSize);
   }
 
   return brightness;
index da25097..6e02f3c 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -60,13 +60,14 @@ public:
    * @param [in] bufferSize       The size of the buffer in bytes
    * @param [in] width            Buffer width in pixels
    * @param [in] height           Buffer height in pixels
+   * @param [in] stride           Buffer stride in pixels, 0 means the buffer is tightly packed
    * @param [in] pixelFormat      The pixel format
-   * @param [in] releaseFunction  The function used to release the memory.
    */
   static PixelBufferPtr New(unsigned char* buffer,
                             unsigned int   bufferSize,
                             unsigned int   width,
                             unsigned int   height,
+                            unsigned int   stride,
                             Pixel::Format  pixelFormat);
 
   /**
@@ -85,12 +86,14 @@ public:
    * @param [in] bufferSize       The size of the buffer in bytes
    * @param [in] width            Buffer width in pixels
    * @param [in] height           Buffer height in pixels
+   * @param [in] stride           Buffer stride in pixels, 0 means the buffer is tightly packed
    * @param [in] pixelFormat      The pixel format
    */
   PixelBuffer(unsigned char* buffer,
               unsigned int   bufferSize,
               unsigned int   width,
               unsigned int   height,
+              unsigned int   stride,
               Pixel::Format  pixelFormat);
 
 protected:
@@ -115,6 +118,12 @@ public:
   unsigned int GetHeight() const;
 
   /**
+   * @brief Gets the stride of the buffer in pixels.
+   * @return The stride of the buffer in pixels. 0 means the buffer is tightly packed.
+   */
+  unsigned int GetStride() const;
+
+  /**
    * Get the pixel format
    * @return The pixel format
    */
@@ -281,10 +290,11 @@ private:
 
 private:
   std::unique_ptr<Property::Map> mMetadata;      ///< Metadata fields
-  unsigned char*                 mBuffer;        ///< The raw pixel data
-  unsigned int                   mBufferSize;    ///< Buffer sized in bytes
-  unsigned int                   mWidth;         ///< Buffer width in pixels
-  unsigned int                   mHeight;        ///< Buffer height in pixels
+  uint8_t*                       mBuffer;        ///< The raw pixel data
+  uint32_t                       mBufferSize;    ///< Buffer sized in bytes
+  uint32_t                       mWidth;         ///< Buffer width in pixels
+  uint32_t                       mHeight;        ///< Buffer height in pixels
+  uint32_t                       mStride;        ///< Buffer stride in bytes, 0 means the buffer is tightly packed
   Pixel::Format                  mPixelFormat;   ///< Pixel format
   bool                           mPreMultiplied; ///< PreMultiplied
 };
index 0735798..dd11c76 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -896,6 +896,7 @@ Devel::PixelBuffer RenderTextCairo(const TextAbstraction::TextRenderer::Paramete
             Dali::Internal::Platform::RotateByShear(data.buffer,
                                                     data.width,
                                                     data.height,
+                                                    data.width,
                                                     pixelSize,
                                                     radians,
                                                     pixelsOut,
index 3f9743f..869609c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -154,6 +154,7 @@ void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, unsigned
   {
     Dali::Internal::Platform::LanczosSample4BPP(srcBuffer,
                                                 inputDimensions,
+                                                srcWidth,
                                                 data.buffer,
                                                 desiredDimensions);
   }
@@ -224,6 +225,7 @@ void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap
             Dali::Internal::Platform::HorizontalShear(pixelsIn,
                                                       width,
                                                       height,
+                                                      width,
                                                       1u,
                                                       -TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE,
                                                       pixelsOut,