Make GlyphBufferData as another class 30/289930/4
authorEunki Hong <eunkiki.hong@samsung.com>
Wed, 15 Mar 2023 17:13:58 +0000 (02:13 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Thu, 23 Mar 2023 03:58:10 +0000 (12:58 +0900)
GlyphBufferData did a lot of process.
Since that struct job has more line than FontClient itself,
seperate new cpp file for it.

Change-Id: I85a2c9a1b011ef6d5455cc7d93ac11348b59e6e0
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
22 files changed:
automated-tests/src/dali-adaptor-internal/utc-Dali-FontClient.cpp
dali/devel-api/file.list
dali/devel-api/text-abstraction/font-client.cpp
dali/devel-api/text-abstraction/font-client.h
dali/devel-api/text-abstraction/glyph-buffer-data.cpp [new file with mode: 0644]
dali/devel-api/text-abstraction/glyph-buffer-data.h [new file with mode: 0644]
dali/internal/text/text-abstraction/cairo-renderer.cpp
dali/internal/text/text-abstraction/font-client-impl.cpp
dali/internal/text/text-abstraction/font-client-impl.h
dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.cpp
dali/internal/text/text-abstraction/plugin/bitmap-font-cache-item.h
dali/internal/text/text-abstraction/plugin/embedded-item.cpp
dali/internal/text/text-abstraction/plugin/embedded-item.h
dali/internal/text/text-abstraction/plugin/font-cache-item-interface.h
dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.cpp
dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h
dali/internal/text/text-abstraction/plugin/font-client-utils.cpp
dali/internal/text/text-abstraction/plugin/font-client-utils.h
dali/internal/text/text-abstraction/plugin/font-face-cache-item.cpp
dali/internal/text/text-abstraction/plugin/font-face-cache-item.h
dali/internal/text/text-abstraction/plugin/font-face-glyph-cache-manager.cpp
dali/internal/text/text-abstraction/plugin/font-face-glyph-cache-manager.h

index 4868e3c..be22f59 100644 (file)
@@ -139,9 +139,9 @@ int UtcDaliFontClientAtlasLimitationEnabled(void)
 
   // Block's width or height are less than 512
   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=200");
-  uint32_t                                     pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  TextAbstraction::FontId                      fontId200    = fontClient.GetFontId(fontDescription, pointSize200);
-  TextAbstraction::FontClient::GlyphBufferData glyphBufferData200;
+  uint32_t                         pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId          fontId200    = fontClient.GetFontId(fontDescription, pointSize200);
+  TextAbstraction::GlyphBufferData glyphBufferData200;
   glyphBufferData200.width  = 0;
   glyphBufferData200.height = 0;
   fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
@@ -152,8 +152,8 @@ int UtcDaliFontClientAtlasLimitationEnabled(void)
   // Block's width or height are  greater than 512 and less than 1024
   uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=1000");
-  TextAbstraction::FontId                      fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
-  TextAbstraction::FontClient::GlyphBufferData glyphBufferData1000;
+  TextAbstraction::FontId          fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
+  TextAbstraction::GlyphBufferData glyphBufferData1000;
   glyphBufferData1000.width  = 0;
   glyphBufferData1000.height = 0;
   fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
@@ -164,8 +164,8 @@ int UtcDaliFontClientAtlasLimitationEnabled(void)
   // Block's width or height are greater than 1024 and less than 2048
   uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=2000");
-  TextAbstraction::FontId                      fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
-  TextAbstraction::FontClient::GlyphBufferData glyphBufferData2000;
+  TextAbstraction::FontId          fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
+  TextAbstraction::GlyphBufferData glyphBufferData2000;
   glyphBufferData2000.width  = 0;
   glyphBufferData2000.height = 0;
   fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
@@ -196,9 +196,9 @@ int UtcDaliFontClientAtlasLimitationDisabled(void)
 
   // Block's width or height are less than 512
   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=200");
-  uint32_t                                     pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  TextAbstraction::FontId                      fontId200    = fontClient.GetFontId(fontDescription, pointSize200);
-  TextAbstraction::FontClient::GlyphBufferData glyphBufferData200;
+  uint32_t                         pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId          fontId200    = fontClient.GetFontId(fontDescription, pointSize200);
+  TextAbstraction::GlyphBufferData glyphBufferData200;
   glyphBufferData200.width  = 0;
   glyphBufferData200.height = 0;
   fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
@@ -208,9 +208,9 @@ int UtcDaliFontClientAtlasLimitationDisabled(void)
 
   // Block's width or height are  greater than 512 and less than 1024
   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=1000");
-  uint32_t                                     pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  TextAbstraction::FontId                      fontId1000    = fontClient.GetFontId(fontDescription, pointSize1000);
-  TextAbstraction::FontClient::GlyphBufferData glyphBufferData1000;
+  uint32_t                         pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId          fontId1000    = fontClient.GetFontId(fontDescription, pointSize1000);
+  TextAbstraction::GlyphBufferData glyphBufferData1000;
   glyphBufferData1000.width  = 0;
   glyphBufferData1000.height = 0;
   fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
@@ -220,9 +220,9 @@ int UtcDaliFontClientAtlasLimitationDisabled(void)
 
   // Block's width or height are greater than 1024 and less than 2048
   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=2000");
-  uint32_t                                     pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  TextAbstraction::FontId                      fontId2000    = fontClient.GetFontId(fontDescription, pointSize2000);
-  TextAbstraction::FontClient::GlyphBufferData glyphBufferData2000;
+  uint32_t                         pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId          fontId2000    = fontClient.GetFontId(fontDescription, pointSize2000);
+  TextAbstraction::GlyphBufferData glyphBufferData2000;
   glyphBufferData2000.width  = 0;
   glyphBufferData2000.height = 0;
   fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
@@ -231,11 +231,11 @@ int UtcDaliFontClientAtlasLimitationDisabled(void)
   DALI_TEST_GREATER(glyphBufferData2000.height, 1024u, TEST_LOCATION); //1148u
 
   // Test GlyphBufferData move
-  TextAbstraction::FontClient::GlyphBufferData movedGlyphBufferData2000 = std::move(glyphBufferData2000);
+  TextAbstraction::GlyphBufferData movedGlyphBufferData2000 = std::move(glyphBufferData2000);
 
   for(int i = 0; i < 50; ++i)
   {
-    TextAbstraction::FontClient::GlyphBufferData dummy = std::move(movedGlyphBufferData2000);
+    TextAbstraction::GlyphBufferData dummy = std::move(movedGlyphBufferData2000);
     movedGlyphBufferData2000                           = std::move(dummy);
 
     // Test moved GlyphBufferData destruct well
index 9a6bd2f..9199da3 100755 (executable)
@@ -172,6 +172,7 @@ SET( devel_api_text_abstraction_src_files
    ${adaptor_devel_api_dir}/text-abstraction/font-client.cpp
    ${adaptor_devel_api_dir}/text-abstraction/font-list.cpp
    ${adaptor_devel_api_dir}/text-abstraction/font-metrics.cpp
+   ${adaptor_devel_api_dir}/text-abstraction/glyph-buffer-data.cpp
    ${adaptor_devel_api_dir}/text-abstraction/glyph-info.cpp
    ${adaptor_devel_api_dir}/text-abstraction/script.cpp
    ${adaptor_devel_api_dir}/text-abstraction/segmentation.cpp
@@ -190,6 +191,7 @@ SET( text_abstraction_header_files
    ${adaptor_devel_api_dir}/text-abstraction/font-client.h
    ${adaptor_devel_api_dir}/text-abstraction/font-list.h
    ${adaptor_devel_api_dir}/text-abstraction/font-metrics.h
+   ${adaptor_devel_api_dir}/text-abstraction/glyph-buffer-data.h
    ${adaptor_devel_api_dir}/text-abstraction/glyph-info.h
    ${adaptor_devel_api_dir}/text-abstraction/script.h
    ${adaptor_devel_api_dir}/text-abstraction/segmentation.h
index 27c9160..908acea 100644 (file)
 #include <dali/devel-api/text-abstraction/font-client.h>
 
 // INTERNAL INCLUDES
-#include <dali/internal/imaging/common/image-operations.h>
 #include <dali/internal/text/text-abstraction/font-client-impl.h>
 
 namespace Dali
 {
 namespace TextAbstraction
 {
+// FontClient static const value definition.
+
 const PointSize26Dot6 FontClient::DEFAULT_POINT_SIZE   = 768u;                           // 12*64
 const float           FontClient::DEFAULT_ITALIC_ANGLE = 12.f * Dali::Math::PI_OVER_180; // FreeType documentation states the software italic is done by doing a horizontal shear of 12 degrees (file ftsynth.h).
 
@@ -49,571 +50,6 @@ const Size FontClient::MAX_SIZE_FIT_IN_ATLAS(MAX_TEXT_ATLAS_WIDTH - PADDING_TEXT
 
 const uint32_t FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE = 64u; //Found this value from toolkit
 
-// FontClient::GlyphBufferData
-
-FontClient::GlyphBufferData::GlyphBufferData()
-: buffer{nullptr},
-  width{0u},
-  height{0u},
-  outlineOffsetX{0},
-  outlineOffsetY{0},
-  format{Pixel::A8},
-  compressionType{CompressionType::NO_COMPRESSION},
-  isColorEmoji{false},
-  isColorBitmap{false},
-  isBufferOwned{false}
-{
-}
-
-FontClient::GlyphBufferData::~GlyphBufferData()
-{
-  if(isBufferOwned)
-  {
-    free(buffer);
-  }
-}
-
-FontClient::GlyphBufferData::GlyphBufferData(FontClient::GlyphBufferData&& rhs) noexcept
-: buffer{rhs.buffer},
-  width{rhs.width},
-  height{rhs.height},
-  outlineOffsetX{rhs.outlineOffsetX},
-  outlineOffsetY{rhs.outlineOffsetY},
-  format{rhs.format},
-  compressionType{rhs.compressionType},
-  isColorEmoji{rhs.isColorEmoji},
-  isColorBitmap{rhs.isColorBitmap},
-  isBufferOwned{rhs.isBufferOwned}
-{
-  // Remove moved data
-  rhs.buffer        = nullptr;
-  rhs.isBufferOwned = false;
-}
-
-FontClient::GlyphBufferData& FontClient::GlyphBufferData::operator=(FontClient::GlyphBufferData&& rhs) noexcept
-{
-  buffer          = rhs.buffer;
-  width           = rhs.width;
-  height          = rhs.height;
-  outlineOffsetX  = rhs.outlineOffsetX;
-  outlineOffsetY  = rhs.outlineOffsetY;
-  format          = rhs.format;
-  compressionType = rhs.compressionType;
-  isColorEmoji    = rhs.isColorEmoji;
-  isColorBitmap   = rhs.isColorBitmap;
-  isBufferOwned   = rhs.isBufferOwned;
-
-  // Remove moved data
-  rhs.buffer        = nullptr;
-  rhs.isBufferOwned = false;
-
-  return *this;
-}
-
-size_t FontClient::GlyphBufferData::Compress(const uint8_t* const __restrict__ inBuffer, GlyphBufferData& __restrict__ outBufferData)
-{
-  size_t bufferSize                       = 0u;
-  uint8_t*& __restrict__ compressedBuffer = outBufferData.buffer;
-  switch(outBufferData.compressionType)
-  {
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION:
-    {
-      bufferSize = static_cast<size_t>(outBufferData.width) * static_cast<size_t>(outBufferData.height) * static_cast<size_t>(Pixel::GetBytesPerPixel(outBufferData.format));
-
-      compressedBuffer = (uint8_t*)malloc(bufferSize);
-      if(DALI_UNLIKELY(compressedBuffer == nullptr))
-      {
-        return 0u;
-      }
-      outBufferData.isBufferOwned = true;
-
-      // Copy buffer without compress
-      memcpy(compressedBuffer, inBuffer, bufferSize);
-      break;
-    }
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::BPP_4:
-    {
-      const uint32_t widthByte       = outBufferData.width * Pixel::GetBytesPerPixel(outBufferData.format);
-      const uint32_t componentCount  = (widthByte >> 1);
-      const bool     considerPadding = (widthByte & 1) ? true : false;
-
-      // For BIT_PER_PIXEL_4 type, we can know final compressed buffer size immediatly.
-      bufferSize       = static_cast<size_t>(outBufferData.height) * static_cast<size_t>(componentCount + (considerPadding ? 1 : 0));
-      compressedBuffer = (uint8_t*)malloc(bufferSize);
-      if(DALI_UNLIKELY(compressedBuffer == nullptr))
-      {
-        return 0u;
-      }
-      outBufferData.isBufferOwned = true;
-
-      uint8_t* __restrict__ outBufferPtr      = compressedBuffer;
-      const uint8_t* __restrict__ inBufferPtr = inBuffer;
-
-      // Compress for each line
-      for(uint32_t y = 0; y < outBufferData.height; ++y)
-      {
-        for(uint32_t x = 0; x < componentCount; ++x)
-        {
-          const uint8_t v0 = Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++));
-          const uint8_t v1 = Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++));
-
-          *(outBufferPtr++) = (v0 << 4) | v1;
-        }
-        if(considerPadding)
-        {
-          *(outBufferPtr++) = Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++));
-        }
-      }
-      break;
-    }
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::RLE_4:
-    {
-      const uint32_t widthByte = outBufferData.width * Pixel::GetBytesPerPixel(outBufferData.format);
-
-      // Allocate temperal buffer. Note that RLE4 can be bigger than original buffer.
-      uint8_t* __restrict__ tempBuffer = (uint8_t*)malloc(outBufferData.height * (widthByte + 1));
-      if(DALI_UNLIKELY(tempBuffer == nullptr))
-      {
-        return 0u;
-      }
-
-      uint8_t* __restrict__ outBufferPtr      = tempBuffer;
-      const uint8_t* __restrict__ inBufferPtr = inBuffer;
-
-      bufferSize = 0u;
-
-      // Compress for each line
-      for(uint32_t y = 0; y < outBufferData.height; ++y)
-      {
-        uint32_t encodedByte = 0;
-        while(encodedByte < widthByte)
-        {
-          // Case 1 : Remain only 1 byte
-          if(DALI_UNLIKELY(encodedByte + 1 == widthByte))
-          {
-            const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-            const uint8_t v0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev0) & 0x0f; // Intented underflow
-            *(outBufferPtr++)   = v0;
-            ++encodedByte;
-            ++bufferSize;
-          }
-          // Case 2 : Remain only 2 byte
-          else if(DALI_UNLIKELY(encodedByte + 2 == widthByte))
-          {
-            const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-            const uint8_t v0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev0) & 0x0f; // Intented underflow
-            const uint8_t prev1 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-            const uint8_t v1    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev1) & 0x0f; // Intented underflow
-            encodedByte += 2;
-            if(v0 == v1)
-            {
-              *(outBufferPtr++) = 0x80 | v0;
-              ++bufferSize;
-            }
-            else
-            {
-              *(outBufferPtr++) = 0x10 | v0;
-              *(outBufferPtr++) = v1 << 4;
-              bufferSize += 2;
-            }
-          }
-          // Case 3 : Normal case. Remain byte bigger or equal than 3.
-          else
-          {
-            // Compress rule -
-            // Read 2 byte as v0 and v1.
-            // - If v0 == v1, We can compress. mark the first bit as 1. and remain 3 bit mark as the "runLength - 2".
-            //   runLength can be maximum 9.
-            // - If v0 != v1, We cannot compress. mark the first bit as 0. and remain 3 bit mark as the "(nonRunLength - 1) / 2"
-            //   Due to the BitPerPixel is 4, nonRunLength should be odd value.
-            //   nonRunLength cutted if v0 == v1.
-            //   nonRunLength can be maximum 15.
-
-            const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-            const uint8_t v0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev0) & 0x0f; // Intented underflow
-            const uint8_t prev1 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-            const uint8_t v1    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev1) & 0x0f; // Intented underflow
-            encodedByte += 2;
-            // We can compress by RLE
-            if(v0 == v1)
-            {
-              uint8_t runLength = 2;
-              while(encodedByte < widthByte && runLength < 9)
-              {
-                const uint8_t prev2 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-                const uint8_t v2    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr)) - prev2) & 0x0f; // Intented underflow
-                if(v2 == v0)
-                {
-                  ++inBufferPtr;
-                  ++encodedByte;
-                  ++runLength;
-                }
-                else
-                {
-                  break;
-                }
-              }
-
-              // Update (runLength - 2) result.
-              *(outBufferPtr++) = ((0x8 | (runLength - 2)) << 4) | v0;
-              ++bufferSize;
-            }
-            // We cannot compress by RLE.
-            else
-            {
-              // Read one more value.
-              const uint8_t prev2 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-              const uint8_t v2    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev2) & 0x0f; // Intented underflow
-              ++encodedByte;
-
-              uint8_t  nonRunLength          = 3;
-              uint8_t* nonRunLengthHeaderPtr = outBufferPtr;
-              *(outBufferPtr++)              = v0;
-              *(outBufferPtr++)              = (v1 << 4) | v2;
-              bufferSize += 2;
-              while(encodedByte < widthByte && nonRunLength < 15)
-              {
-                if(DALI_LIKELY(encodedByte + 1 < widthByte))
-                {
-                  const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-                  const uint8_t w0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr)) - prew0) & 0x0f; // Intented underflow
-                  const uint8_t prew1 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr + 1 - widthByte));
-                  const uint8_t w1    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr + 1)) - prew1) & 0x0f; // Intented underflow
-                  if(w0 == w1)
-                  {
-                    // Stop non-compress logic.
-                    break;
-                  }
-                  else
-                  {
-                    ++bufferSize;
-                    *(outBufferPtr++) = (w0 << 4) | w1;
-                    inBufferPtr += 2;
-                    encodedByte += 2;
-                    nonRunLength += 2;
-                  }
-                }
-                else
-                {
-                  // Edge case. There is only one pixel remained.
-                  const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
-                  const uint8_t w0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr)) - prew0) & 0x0f; // Intented underflow
-                  {
-                    ++bufferSize;
-                    *(outBufferPtr++) = (w0 << 4);
-                    ++encodedByte;
-                    ++inBufferPtr;
-                    // Increase nonRunLength 2 even latest value is invalid.
-                    nonRunLength += 2;
-                  }
-                }
-              }
-
-              // Update (nonRunLength-1)/2 result into header.
-              *(nonRunLengthHeaderPtr) |= (nonRunLength >> 1) << 4;
-            }
-          }
-        }
-      }
-
-      // Allocate and copy data
-      compressedBuffer = (uint8_t*)malloc(bufferSize);
-      if(DALI_UNLIKELY(compressedBuffer == nullptr))
-      {
-        free(tempBuffer);
-        return 0u;
-      }
-      outBufferData.isBufferOwned = true;
-
-      memcpy(compressedBuffer, tempBuffer, bufferSize);
-      free(tempBuffer);
-
-      break;
-    }
-    default:
-    {
-      break;
-    }
-  }
-
-  return bufferSize;
-}
-
-void FontClient::GlyphBufferData::Decompress(const GlyphBufferData& __restrict__ inBufferData, uint8_t* __restrict__ outBuffer)
-{
-  if(DALI_UNLIKELY(outBuffer == nullptr))
-  {
-    return;
-  }
-
-  switch(inBufferData.compressionType)
-  {
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION:
-    {
-      const auto bufferSize = inBufferData.width * inBufferData.height * Pixel::GetBytesPerPixel(inBufferData.format);
-
-      // Copy buffer without compress
-      memcpy(outBuffer, inBufferData.buffer, bufferSize);
-      break;
-    }
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::BPP_4:
-    {
-      const uint32_t widthByte       = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
-      const uint32_t componentCount  = (widthByte >> 1);
-      const bool     considerPadding = (widthByte & 1) ? true : false;
-
-      uint8_t* __restrict__ outBufferPtr      = outBuffer;
-      const uint8_t* __restrict__ inBufferPtr = inBufferData.buffer;
-
-      // Compress for each line
-      for(uint32_t y = 0; y < inBufferData.height; ++y)
-      {
-        for(uint32_t x = 0; x < componentCount; ++x)
-        {
-          const uint8_t v  = *(inBufferPtr++);
-          const uint8_t v0 = (v >> 4) & 0x0f;
-          const uint8_t v1 = v & 0x0f;
-
-          *(outBufferPtr++) = (v0 << 4) | v0;
-          *(outBufferPtr++) = (v1 << 4) | v1;
-        }
-        if(considerPadding)
-        {
-          const uint8_t v   = *(inBufferPtr++);
-          *(outBufferPtr++) = (v << 4) | v;
-        }
-      }
-      break;
-    }
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::RLE_4:
-    {
-      const uint32_t widthByte = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
-
-      uint8_t* __restrict__ outBufferPtr      = outBuffer;
-      const uint8_t* __restrict__ inBufferPtr = inBufferData.buffer;
-      // Compress for each line
-      for(uint32_t y = 0; y < inBufferData.height; ++y)
-      {
-        uint32_t x           = 0;
-        uint32_t decodedByte = 0;
-        while(decodedByte < widthByte)
-        {
-          const uint8_t v = *(inBufferPtr++);
-          ++x;
-          // Compress by RLE
-          if(v & 0x80)
-          {
-            const uint8_t runLength = ((v >> 4) & 0x07) + 2u;
-            decodedByte += runLength;
-            const uint8_t repeatValue = v & 0x0f;
-            for(uint8_t iter = 0; iter < runLength; ++iter)
-            {
-              const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
-              const uint8_t v0    = (prev0 + repeatValue) & 0x0f;
-              *(outBufferPtr++)   = (v0 << 4) | v0;
-            }
-          }
-          // Not compress by RLE
-          else
-          {
-            const uint8_t nonRunLength = (((v >> 4) & 0x07) << 1u) + 1u;
-            decodedByte += nonRunLength;
-            // First value.
-            const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
-            const uint8_t v0    = (prev0 + (v & 0x0f)) & 0x0f;
-            *(outBufferPtr++)   = (v0 << 4) | v0;
-
-            const bool ignoreLastValue = decodedByte > widthByte ? true : false;
-            if(DALI_UNLIKELY(ignoreLastValue))
-            {
-              --decodedByte;
-              for(uint8_t iter = 1; iter + 2 < nonRunLength; iter += 2)
-              {
-                const uint8_t w     = *(inBufferPtr++);
-                const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
-                const uint8_t w0    = (prew0 + ((w >> 4) & 0x0f)) & 0x0f;
-                const uint8_t prew1 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte + 1)) & 0x0f;
-                const uint8_t w1    = (prew1 + (w & 0x0f)) & 0x0f;
-                ++x;
-
-                *(outBufferPtr++) = (w0 << 4) | w0;
-                *(outBufferPtr++) = (w1 << 4) | w1;
-              }
-              // Last value.
-              {
-                const uint8_t w     = ((*(inBufferPtr++)) >> 4) & 0x0f;
-                const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
-                const uint8_t w0    = (prew0 + w) & 0x0f;
-                ++x;
-
-                *(outBufferPtr++) = (w0 << 4) | w0;
-              }
-            }
-            else
-            {
-              for(uint8_t iter = 1; iter < nonRunLength; iter += 2)
-              {
-                const uint8_t w     = *(inBufferPtr++);
-                const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
-                const uint8_t w0    = (prew0 + ((w >> 4) & 0x0f)) & 0x0f;
-                const uint8_t prew1 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte + 1)) & 0x0f;
-                const uint8_t w1    = (prew1 + (w & 0x0f)) & 0x0f;
-                ++x;
-
-                *(outBufferPtr++) = (w0 << 4) | w0;
-                *(outBufferPtr++) = (w1 << 4) | w1;
-              }
-            }
-          }
-        }
-      }
-      break;
-    }
-    default:
-    {
-      break;
-    }
-  }
-}
-
-void FontClient::GlyphBufferData::DecompressScanline(const GlyphBufferData& __restrict__ inBufferData, uint8_t* __restrict__ outBuffer, uint32_t& __restrict__ offset)
-{
-  switch(inBufferData.compressionType)
-  {
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION:
-    {
-      const auto bufferSize = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
-
-      // Copy buffer without compress
-      memcpy(outBuffer, inBufferData.buffer + offset, bufferSize);
-
-      // Update offset
-      offset += bufferSize;
-      break;
-    }
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::BPP_4:
-    {
-      const uint32_t widthByte       = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
-      const uint32_t componentCount  = (widthByte >> 1);
-      const bool     considerPadding = (widthByte & 1) ? true : false;
-
-      uint8_t* __restrict__ outBufferPtr      = outBuffer;
-      const uint8_t* __restrict__ inBufferPtr = inBufferData.buffer + offset;
-
-      // Decompress scanline
-      for(uint32_t x = 0; x < componentCount; ++x)
-      {
-        const uint8_t v  = *(inBufferPtr++);
-        const uint8_t v0 = (v >> 4) & 0x0f;
-        const uint8_t v1 = v & 0x0f;
-
-        *(outBufferPtr++) = (v0 << 4) | v0;
-        *(outBufferPtr++) = (v1 << 4) | v1;
-      }
-      if(considerPadding)
-      {
-        const uint8_t v   = *(inBufferPtr++);
-        *(outBufferPtr++) = (v << 4) | v;
-      }
-
-      // Update offset
-      offset += (widthByte + 1u) >> 1u;
-      break;
-    }
-    case TextAbstraction::FontClient::GlyphBufferData::CompressionType::RLE_4:
-    {
-      const uint32_t widthByte = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
-
-      uint8_t* __restrict__ outBufferPtr      = outBuffer;
-      const uint8_t* __restrict__ inBufferPtr = inBufferData.buffer + offset;
-
-      // If offset is zero, fill outBuffer as 0 first.
-      if(DALI_UNLIKELY(offset == 0))
-      {
-        memset(outBufferPtr, 0, widthByte);
-      }
-
-      // Decompress scanline
-      uint32_t decodedByte = 0;
-      while(decodedByte < widthByte)
-      {
-        const uint8_t v = *(inBufferPtr++);
-        ++offset;
-        // Compress by RLE
-        if(v & 0x80)
-        {
-          const uint8_t runLength = ((v >> 4) & 0x07) + 2u;
-          decodedByte += runLength;
-          const uint8_t repeatValue = (v & 0x0f);
-          for(uint8_t iter = 0; iter < runLength; ++iter)
-          {
-            const uint8_t prev0 = (*(outBufferPtr)) & 0x0f;
-            const uint8_t v0    = (prev0 + repeatValue) & 0x0f;
-            *(outBufferPtr++)   = (v0 << 4) | v0;
-          }
-        }
-        // Not compress by RLE
-        else
-        {
-          const uint8_t nonRunLength = (((v >> 4) & 0x07) << 1u) + 1u;
-          decodedByte += nonRunLength;
-          // First value.
-          const uint8_t prev0 = (*(outBufferPtr)) & 0x0f;
-          const uint8_t v0    = (prev0 + (v & 0x0f)) & 0x0f;
-          *(outBufferPtr++)   = (v0 << 4) | v0;
-
-          const bool ignoreLastValue = decodedByte > widthByte ? true : false;
-          if(DALI_UNLIKELY(ignoreLastValue))
-          {
-            --decodedByte;
-            for(uint8_t iter = 1; iter + 2 < nonRunLength; iter += 2)
-            {
-              const uint8_t w     = *(inBufferPtr++);
-              const uint8_t prew0 = (*(outBufferPtr)) & 0x0f;
-              const uint8_t w0    = (prew0 + ((w >> 4) & 0x0f)) & 0x0f;
-              const uint8_t prew1 = (*(outBufferPtr + 1)) & 0x0f;
-              const uint8_t w1    = (prew1 + (w & 0x0f)) & 0x0f;
-              ++offset;
-
-              *(outBufferPtr++) = (w0 << 4) | w0;
-              *(outBufferPtr++) = (w1 << 4) | w1;
-            }
-            // Last value.
-            {
-              const uint8_t w     = ((*(inBufferPtr++)) >> 4) & 0x0f;
-              const uint8_t prew0 = (*(outBufferPtr)) & 0x0f;
-              const uint8_t w0    = (prew0 + w) & 0x0f;
-              ++offset;
-
-              *(outBufferPtr++) = (w0 << 4) | w0;
-            }
-          }
-          else
-          {
-            for(uint8_t iter = 1; iter < nonRunLength; iter += 2)
-            {
-              const uint8_t w     = *(inBufferPtr++);
-              const uint8_t prew0 = (*(outBufferPtr)) & 0x0f;
-              const uint8_t w0    = (prew0 + ((w >> 4) & 0x0f)) & 0x0f;
-              const uint8_t prew1 = (*(outBufferPtr + 1)) & 0x0f;
-              const uint8_t w1    = (prew1 + (w & 0x0f)) & 0x0f;
-              ++offset;
-
-              *(outBufferPtr++) = (w0 << 4) | w0;
-              *(outBufferPtr++) = (w1 << 4) | w1;
-            }
-          }
-        }
-      }
-      break;
-    }
-    default:
-    {
-      break;
-    }
-  }
-}
-
 // FontClient
 
 FontClient FontClient::Get()
index 2f75e8c..df11ebf 100644 (file)
@@ -20,6 +20,7 @@
 
 // INTERNAL INCLUDES
 #include <dali/devel-api/text-abstraction/font-list.h>
+#include <dali/devel-api/text-abstraction/glyph-buffer-data.h>
 #include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
 #include <dali/public-api/common/dali-vector.h>
 #include <dali/public-api/dali-adaptor-common.h>
@@ -79,99 +80,6 @@ public:
   static const uint32_t NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE; ///< Factor multiply point-size in toolkit.
 
   /**
-   * @brief Struct used to retrieve the glyph's bitmap.
-   */
-  struct DALI_ADAPTOR_API GlyphBufferData
-  {
-    /**
-     * @brief Constructor.
-     *
-     * Initializes struct members to their defaults.
-     */
-    GlyphBufferData();
-
-    /**
-     * @brief Destructor.
-     */
-    ~GlyphBufferData();
-
-    /**
-     * @brief Move constructor.
-     *
-     * @param[in] rhs moved data.
-     */
-    GlyphBufferData(GlyphBufferData&& rhs) noexcept;
-
-    /**
-     * @brief Move assign operator.
-     *
-     * @param[in] rhs moved data.
-     * @return A reference to this.
-     */
-    GlyphBufferData& operator=(GlyphBufferData&& rhs) noexcept;
-
-    // Compression method of buffer. Each buffer compressed line by line
-    enum class CompressionType
-    {
-      NO_COMPRESSION = 0, // No compression
-      BPP_4          = 1, // Compress as 4 bit. Color become value * 17 (0x00, 0x11, 0x22, ... 0xee, 0xff).
-                          // Only works for Pixel::L8 format
-      RLE_4 = 2,          // Compress as 4 bit, and Run-Length-Encode. For more high compress rate, we store difference between previous scanline.
-                          // Only works for Pixel::L8 format
-    };
-
-    /**
-     * @brief Helper static function to compress raw buffer from inBuffer to outBufferData.buffer.
-     * outBufferData will have it's own buffer.
-     *
-     * @pre outBufferData must not have it's own buffer.
-     * @param[in] inBuffer The input raw data.
-     * @param[in, out] outBufferData The output glyph buffer data.
-     * @return Size of compressed out buffer, Or 0 if compress failed.
-     */
-    static size_t Compress(const uint8_t* const inBuffer, GlyphBufferData& outBufferData);
-
-    /**
-     * @brief Helper static function to decompress raw buffer from inBuffer to outBufferPtr.
-     * If outBuffer is nullptr, Do nothing.
-     *
-     * @pre outBuffer memory should be allocated.
-     * @param[in] inBufferData The input glyph buffer data.
-     * @param[in, out] outBuffer The output pointer of raw buffer data.
-     */
-    static void Decompress(const GlyphBufferData& inBufferData, uint8_t* outBuffer);
-
-    /**
-     * @brief Special Helper static function to decompress raw buffer from inBuffer to outBuffer one scanline.
-     * After decompress one scanline successed, offset will be changed.
-     *
-     * @pre outBuffer memory should be allocated.
-     * @pre if inBufferData's compression type is RLE4, outBuffer memory should store the previous scanline data.
-     * @param[in] inBufferData The input glyph buffer data.
-     * @param[in, out] outBuffer The output pointer of raw buffer data.
-     * @param[in, out] offset The offset of input. It will be changed as next scanline's offset.
-     */
-    static void DecompressScanline(const GlyphBufferData& inBufferData, uint8_t* outBuffer, uint32_t& offset);
-
-  private:
-    // Delete copy operation.
-    GlyphBufferData(const GlyphBufferData& rhs) = delete;
-    GlyphBufferData& operator=(const GlyphBufferData& rhs) = delete;
-
-  public:
-    uint8_t*        buffer;            ///< The glyph's bitmap buffer data.
-    uint32_t        width;             ///< The width of the bitmap.
-    uint32_t        height;            ///< The height of the bitmap.
-    int             outlineOffsetX;    ///< The additional horizontal offset to be added for the glyph's position for outline.
-    int             outlineOffsetY;    ///< The additional vertical offset to be added for the glyph's position for outline.
-    Pixel::Format   format;            ///< The pixel's format of the bitmap.
-    CompressionType compressionType;   ///< The type of buffer compression.
-    bool            isColorEmoji : 1;  ///< Whether the glyph is an emoji.
-    bool            isColorBitmap : 1; ///< Whether the glyph is a color bitmap.
-    bool            isBufferOwned : 1; ///< Whether the glyph's bitmap buffer data owned by this class or not. Becareful when you use non-owned buffer data.
-  };
-
-  /**
    * @brief Used to load an embedded item into the font client.
    */
   struct EmbeddedItemDescription
diff --git a/dali/devel-api/text-abstraction/glyph-buffer-data.cpp b/dali/devel-api/text-abstraction/glyph-buffer-data.cpp
new file mode 100644 (file)
index 0000000..fec3884
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/text-abstraction/glyph-buffer-data.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/imaging/common/image-operations.h>
+
+namespace Dali
+{
+namespace TextAbstraction
+{
+GlyphBufferData::GlyphBufferData()
+: buffer{nullptr},
+  width{0u},
+  height{0u},
+  outlineOffsetX{0},
+  outlineOffsetY{0},
+  format{Pixel::A8},
+  compressionType{CompressionType::NO_COMPRESSION},
+  isColorEmoji{false},
+  isColorBitmap{false},
+  isBufferOwned{false}
+{
+}
+
+GlyphBufferData::~GlyphBufferData()
+{
+  if(isBufferOwned)
+  {
+    free(buffer);
+  }
+}
+
+GlyphBufferData::GlyphBufferData(GlyphBufferData&& rhs) noexcept
+: buffer{rhs.buffer},
+  width{rhs.width},
+  height{rhs.height},
+  outlineOffsetX{rhs.outlineOffsetX},
+  outlineOffsetY{rhs.outlineOffsetY},
+  format{rhs.format},
+  compressionType{rhs.compressionType},
+  isColorEmoji{rhs.isColorEmoji},
+  isColorBitmap{rhs.isColorBitmap},
+  isBufferOwned{rhs.isBufferOwned}
+{
+  // Remove moved data
+  rhs.buffer        = nullptr;
+  rhs.isBufferOwned = false;
+}
+
+GlyphBufferData& GlyphBufferData::operator=(GlyphBufferData&& rhs) noexcept
+{
+  buffer          = rhs.buffer;
+  width           = rhs.width;
+  height          = rhs.height;
+  outlineOffsetX  = rhs.outlineOffsetX;
+  outlineOffsetY  = rhs.outlineOffsetY;
+  format          = rhs.format;
+  compressionType = rhs.compressionType;
+  isColorEmoji    = rhs.isColorEmoji;
+  isColorBitmap   = rhs.isColorBitmap;
+  isBufferOwned   = rhs.isBufferOwned;
+
+  // Remove moved data
+  rhs.buffer        = nullptr;
+  rhs.isBufferOwned = false;
+
+  return *this;
+}
+
+size_t GlyphBufferData::Compress(const uint8_t* const __restrict__ inBuffer, GlyphBufferData& __restrict__ outBufferData)
+{
+  size_t bufferSize                       = 0u;
+  uint8_t*& __restrict__ compressedBuffer = outBufferData.buffer;
+  switch(outBufferData.compressionType)
+  {
+    case TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION:
+    {
+      bufferSize = static_cast<size_t>(outBufferData.width) * static_cast<size_t>(outBufferData.height) * static_cast<size_t>(Pixel::GetBytesPerPixel(outBufferData.format));
+
+      compressedBuffer = (uint8_t*)malloc(bufferSize);
+      if(DALI_UNLIKELY(compressedBuffer == nullptr))
+      {
+        return 0u;
+      }
+      outBufferData.isBufferOwned = true;
+
+      // Copy buffer without compress
+      memcpy(compressedBuffer, inBuffer, bufferSize);
+      break;
+    }
+    case TextAbstraction::GlyphBufferData::CompressionType::BPP_4:
+    {
+      const uint32_t widthByte       = outBufferData.width * Pixel::GetBytesPerPixel(outBufferData.format);
+      const uint32_t componentCount  = (widthByte >> 1);
+      const bool     considerPadding = (widthByte & 1) ? true : false;
+
+      // For BIT_PER_PIXEL_4 type, we can know final compressed buffer size immediatly.
+      bufferSize       = static_cast<size_t>(outBufferData.height) * static_cast<size_t>(componentCount + (considerPadding ? 1 : 0));
+      compressedBuffer = (uint8_t*)malloc(bufferSize);
+      if(DALI_UNLIKELY(compressedBuffer == nullptr))
+      {
+        return 0u;
+      }
+      outBufferData.isBufferOwned = true;
+
+      uint8_t* __restrict__ outBufferPtr      = compressedBuffer;
+      const uint8_t* __restrict__ inBufferPtr = inBuffer;
+
+      // Compress for each line
+      for(uint32_t y = 0; y < outBufferData.height; ++y)
+      {
+        for(uint32_t x = 0; x < componentCount; ++x)
+        {
+          const uint8_t v0 = Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++));
+          const uint8_t v1 = Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++));
+
+          *(outBufferPtr++) = (v0 << 4) | v1;
+        }
+        if(considerPadding)
+        {
+          *(outBufferPtr++) = Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++));
+        }
+      }
+      break;
+    }
+    case TextAbstraction::GlyphBufferData::CompressionType::RLE_4:
+    {
+      const uint32_t widthByte = outBufferData.width * Pixel::GetBytesPerPixel(outBufferData.format);
+
+      // Allocate temperal buffer. Note that RLE4 can be bigger than original buffer.
+      uint8_t* __restrict__ tempBuffer = (uint8_t*)malloc(outBufferData.height * (widthByte + 1));
+      if(DALI_UNLIKELY(tempBuffer == nullptr))
+      {
+        return 0u;
+      }
+
+      uint8_t* __restrict__ outBufferPtr      = tempBuffer;
+      const uint8_t* __restrict__ inBufferPtr = inBuffer;
+
+      bufferSize = 0u;
+
+      // Compress for each line
+      for(uint32_t y = 0; y < outBufferData.height; ++y)
+      {
+        uint32_t encodedByte = 0;
+        while(encodedByte < widthByte)
+        {
+          // Case 1 : Remain only 1 byte
+          if(DALI_UNLIKELY(encodedByte + 1 == widthByte))
+          {
+            const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+            const uint8_t v0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev0) & 0x0f; // Intented underflow
+            *(outBufferPtr++)   = v0;
+            ++encodedByte;
+            ++bufferSize;
+          }
+          // Case 2 : Remain only 2 byte
+          else if(DALI_UNLIKELY(encodedByte + 2 == widthByte))
+          {
+            const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+            const uint8_t v0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev0) & 0x0f; // Intented underflow
+            const uint8_t prev1 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+            const uint8_t v1    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev1) & 0x0f; // Intented underflow
+            encodedByte += 2;
+            if(v0 == v1)
+            {
+              *(outBufferPtr++) = 0x80 | v0;
+              ++bufferSize;
+            }
+            else
+            {
+              *(outBufferPtr++) = 0x10 | v0;
+              *(outBufferPtr++) = v1 << 4;
+              bufferSize += 2;
+            }
+          }
+          // Case 3 : Normal case. Remain byte bigger or equal than 3.
+          else
+          {
+            // Compress rule -
+            // Read 2 byte as v0 and v1.
+            // - If v0 == v1, We can compress. mark the first bit as 1. and remain 3 bit mark as the "runLength - 2".
+            //   runLength can be maximum 9.
+            // - If v0 != v1, We cannot compress. mark the first bit as 0. and remain 3 bit mark as the "(nonRunLength - 1) / 2"
+            //   Due to the BitPerPixel is 4, nonRunLength should be odd value.
+            //   nonRunLength cutted if v0 == v1.
+            //   nonRunLength can be maximum 15.
+
+            const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+            const uint8_t v0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev0) & 0x0f; // Intented underflow
+            const uint8_t prev1 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+            const uint8_t v1    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev1) & 0x0f; // Intented underflow
+            encodedByte += 2;
+            // We can compress by RLE
+            if(v0 == v1)
+            {
+              uint8_t runLength = 2;
+              while(encodedByte < widthByte && runLength < 9)
+              {
+                const uint8_t prev2 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+                const uint8_t v2    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr)) - prev2) & 0x0f; // Intented underflow
+                if(v2 == v0)
+                {
+                  ++inBufferPtr;
+                  ++encodedByte;
+                  ++runLength;
+                }
+                else
+                {
+                  break;
+                }
+              }
+
+              // Update (runLength - 2) result.
+              *(outBufferPtr++) = ((0x8 | (runLength - 2)) << 4) | v0;
+              ++bufferSize;
+            }
+            // We cannot compress by RLE.
+            else
+            {
+              // Read one more value.
+              const uint8_t prev2 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+              const uint8_t v2    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr++)) - prev2) & 0x0f; // Intented underflow
+              ++encodedByte;
+
+              uint8_t  nonRunLength          = 3;
+              uint8_t* nonRunLengthHeaderPtr = outBufferPtr;
+              *(outBufferPtr++)              = v0;
+              *(outBufferPtr++)              = (v1 << 4) | v2;
+              bufferSize += 2;
+              while(encodedByte < widthByte && nonRunLength < 15)
+              {
+                if(DALI_LIKELY(encodedByte + 1 < widthByte))
+                {
+                  const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+                  const uint8_t w0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr)) - prew0) & 0x0f; // Intented underflow
+                  const uint8_t prew1 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr + 1 - widthByte));
+                  const uint8_t w1    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr + 1)) - prew1) & 0x0f; // Intented underflow
+                  if(w0 == w1)
+                  {
+                    // Stop non-compress logic.
+                    break;
+                  }
+                  else
+                  {
+                    ++bufferSize;
+                    *(outBufferPtr++) = (w0 << 4) | w1;
+                    inBufferPtr += 2;
+                    encodedByte += 2;
+                    nonRunLength += 2;
+                  }
+                }
+                else
+                {
+                  // Edge case. There is only one pixel remained.
+                  const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr - widthByte));
+                  const uint8_t w0    = (Dali::Internal::Platform::CompressBitPerPixel8To4(*(inBufferPtr)) - prew0) & 0x0f; // Intented underflow
+                  {
+                    ++bufferSize;
+                    *(outBufferPtr++) = (w0 << 4);
+                    ++encodedByte;
+                    ++inBufferPtr;
+                    // Increase nonRunLength 2 even latest value is invalid.
+                    nonRunLength += 2;
+                  }
+                }
+              }
+
+              // Update (nonRunLength-1)/2 result into header.
+              *(nonRunLengthHeaderPtr) |= (nonRunLength >> 1) << 4;
+            }
+          }
+        }
+      }
+
+      // Allocate and copy data
+      compressedBuffer = (uint8_t*)malloc(bufferSize);
+      if(DALI_UNLIKELY(compressedBuffer == nullptr))
+      {
+        free(tempBuffer);
+        return 0u;
+      }
+      outBufferData.isBufferOwned = true;
+
+      memcpy(compressedBuffer, tempBuffer, bufferSize);
+      free(tempBuffer);
+
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+
+  return bufferSize;
+}
+
+void GlyphBufferData::Decompress(const GlyphBufferData& __restrict__ inBufferData, uint8_t* __restrict__ outBuffer)
+{
+  if(DALI_UNLIKELY(outBuffer == nullptr))
+  {
+    return;
+  }
+
+  switch(inBufferData.compressionType)
+  {
+    case TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION:
+    {
+      const auto bufferSize = inBufferData.width * inBufferData.height * Pixel::GetBytesPerPixel(inBufferData.format);
+
+      // Copy buffer without compress
+      memcpy(outBuffer, inBufferData.buffer, bufferSize);
+      break;
+    }
+    case TextAbstraction::GlyphBufferData::CompressionType::BPP_4:
+    {
+      const uint32_t widthByte       = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
+      const uint32_t componentCount  = (widthByte >> 1);
+      const bool     considerPadding = (widthByte & 1) ? true : false;
+
+      uint8_t* __restrict__ outBufferPtr      = outBuffer;
+      const uint8_t* __restrict__ inBufferPtr = inBufferData.buffer;
+
+      // Compress for each line
+      for(uint32_t y = 0; y < inBufferData.height; ++y)
+      {
+        for(uint32_t x = 0; x < componentCount; ++x)
+        {
+          const uint8_t v  = *(inBufferPtr++);
+          const uint8_t v0 = (v >> 4) & 0x0f;
+          const uint8_t v1 = v & 0x0f;
+
+          *(outBufferPtr++) = (v0 << 4) | v0;
+          *(outBufferPtr++) = (v1 << 4) | v1;
+        }
+        if(considerPadding)
+        {
+          const uint8_t v   = *(inBufferPtr++);
+          *(outBufferPtr++) = (v << 4) | v;
+        }
+      }
+      break;
+    }
+    case TextAbstraction::GlyphBufferData::CompressionType::RLE_4:
+    {
+      const uint32_t widthByte = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
+
+      uint8_t* __restrict__ outBufferPtr      = outBuffer;
+      const uint8_t* __restrict__ inBufferPtr = inBufferData.buffer;
+      // Compress for each line
+      for(uint32_t y = 0; y < inBufferData.height; ++y)
+      {
+        uint32_t x           = 0;
+        uint32_t decodedByte = 0;
+        while(decodedByte < widthByte)
+        {
+          const uint8_t v = *(inBufferPtr++);
+          ++x;
+          // Compress by RLE
+          if(v & 0x80)
+          {
+            const uint8_t runLength = ((v >> 4) & 0x07) + 2u;
+            decodedByte += runLength;
+            const uint8_t repeatValue = v & 0x0f;
+            for(uint8_t iter = 0; iter < runLength; ++iter)
+            {
+              const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
+              const uint8_t v0    = (prev0 + repeatValue) & 0x0f;
+              *(outBufferPtr++)   = (v0 << 4) | v0;
+            }
+          }
+          // Not compress by RLE
+          else
+          {
+            const uint8_t nonRunLength = (((v >> 4) & 0x07) << 1u) + 1u;
+            decodedByte += nonRunLength;
+            // First value.
+            const uint8_t prev0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
+            const uint8_t v0    = (prev0 + (v & 0x0f)) & 0x0f;
+            *(outBufferPtr++)   = (v0 << 4) | v0;
+
+            const bool ignoreLastValue = decodedByte > widthByte ? true : false;
+            if(DALI_UNLIKELY(ignoreLastValue))
+            {
+              --decodedByte;
+              for(uint8_t iter = 1; iter + 2 < nonRunLength; iter += 2)
+              {
+                const uint8_t w     = *(inBufferPtr++);
+                const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
+                const uint8_t w0    = (prew0 + ((w >> 4) & 0x0f)) & 0x0f;
+                const uint8_t prew1 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte + 1)) & 0x0f;
+                const uint8_t w1    = (prew1 + (w & 0x0f)) & 0x0f;
+                ++x;
+
+                *(outBufferPtr++) = (w0 << 4) | w0;
+                *(outBufferPtr++) = (w1 << 4) | w1;
+              }
+              // Last value.
+              {
+                const uint8_t w     = ((*(inBufferPtr++)) >> 4) & 0x0f;
+                const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
+                const uint8_t w0    = (prew0 + w) & 0x0f;
+                ++x;
+
+                *(outBufferPtr++) = (w0 << 4) | w0;
+              }
+            }
+            else
+            {
+              for(uint8_t iter = 1; iter < nonRunLength; iter += 2)
+              {
+                const uint8_t w     = *(inBufferPtr++);
+                const uint8_t prew0 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte)) & 0x0f;
+                const uint8_t w0    = (prew0 + ((w >> 4) & 0x0f)) & 0x0f;
+                const uint8_t prew1 = DALI_UNLIKELY(y == 0) ? 0 : (*(outBufferPtr - widthByte + 1)) & 0x0f;
+                const uint8_t w1    = (prew1 + (w & 0x0f)) & 0x0f;
+                ++x;
+
+                *(outBufferPtr++) = (w0 << 4) | w0;
+                *(outBufferPtr++) = (w1 << 4) | w1;
+              }
+            }
+          }
+        }
+      }
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+}
+
+void GlyphBufferData::DecompressScanline(const GlyphBufferData& __restrict__ inBufferData, uint8_t* __restrict__ outBuffer, uint32_t& __restrict__ offset)
+{
+  switch(inBufferData.compressionType)
+  {
+    case TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION:
+    {
+      const auto bufferSize = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
+
+      // Copy buffer without compress
+      memcpy(outBuffer, inBufferData.buffer + offset, bufferSize);
+
+      // Update offset
+      offset += bufferSize;
+      break;
+    }
+    case TextAbstraction::GlyphBufferData::CompressionType::BPP_4:
+    {
+      const uint32_t widthByte       = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
+      const uint32_t componentCount  = (widthByte >> 1);
+      const bool     considerPadding = (widthByte & 1) ? true : false;
+
+      uint8_t* __restrict__ outBufferPtr      = outBuffer;
+      const uint8_t* __restrict__ inBufferPtr = inBufferData.buffer + offset;
+
+      // Decompress scanline
+      for(uint32_t x = 0; x < componentCount; ++x)
+      {
+        const uint8_t v  = *(inBufferPtr++);
+        const uint8_t v0 = (v >> 4) & 0x0f;
+        const uint8_t v1 = v & 0x0f;
+
+        *(outBufferPtr++) = (v0 << 4) | v0;
+        *(outBufferPtr++) = (v1 << 4) | v1;
+      }
+      if(considerPadding)
+      {
+        const uint8_t v   = *(inBufferPtr++);
+        *(outBufferPtr++) = (v << 4) | v;
+      }
+
+      // Update offset
+      offset += (widthByte + 1u) >> 1u;
+      break;
+    }
+    case TextAbstraction::GlyphBufferData::CompressionType::RLE_4:
+    {
+      const uint32_t widthByte = inBufferData.width * Pixel::GetBytesPerPixel(inBufferData.format);
+
+      uint8_t* __restrict__ outBufferPtr      = outBuffer;
+      const uint8_t* __restrict__ inBufferPtr = inBufferData.buffer + offset;
+
+      // If offset is zero, fill outBuffer as 0 first.
+      if(DALI_UNLIKELY(offset == 0))
+      {
+        memset(outBufferPtr, 0, widthByte);
+      }
+
+      // Decompress scanline
+      uint32_t decodedByte = 0;
+      while(decodedByte < widthByte)
+      {
+        const uint8_t v = *(inBufferPtr++);
+        ++offset;
+        // Compress by RLE
+        if(v & 0x80)
+        {
+          const uint8_t runLength = ((v >> 4) & 0x07) + 2u;
+          decodedByte += runLength;
+          const uint8_t repeatValue = (v & 0x0f);
+          for(uint8_t iter = 0; iter < runLength; ++iter)
+          {
+            const uint8_t prev0 = (*(outBufferPtr)) & 0x0f;
+            const uint8_t v0    = (prev0 + repeatValue) & 0x0f;
+            *(outBufferPtr++)   = (v0 << 4) | v0;
+          }
+        }
+        // Not compress by RLE
+        else
+        {
+          const uint8_t nonRunLength = (((v >> 4) & 0x07) << 1u) + 1u;
+          decodedByte += nonRunLength;
+          // First value.
+          const uint8_t prev0 = (*(outBufferPtr)) & 0x0f;
+          const uint8_t v0    = (prev0 + (v & 0x0f)) & 0x0f;
+          *(outBufferPtr++)   = (v0 << 4) | v0;
+
+          const bool ignoreLastValue = decodedByte > widthByte ? true : false;
+          if(DALI_UNLIKELY(ignoreLastValue))
+          {
+            --decodedByte;
+            for(uint8_t iter = 1; iter + 2 < nonRunLength; iter += 2)
+            {
+              const uint8_t w     = *(inBufferPtr++);
+              const uint8_t prew0 = (*(outBufferPtr)) & 0x0f;
+              const uint8_t w0    = (prew0 + ((w >> 4) & 0x0f)) & 0x0f;
+              const uint8_t prew1 = (*(outBufferPtr + 1)) & 0x0f;
+              const uint8_t w1    = (prew1 + (w & 0x0f)) & 0x0f;
+              ++offset;
+
+              *(outBufferPtr++) = (w0 << 4) | w0;
+              *(outBufferPtr++) = (w1 << 4) | w1;
+            }
+            // Last value.
+            {
+              const uint8_t w     = ((*(inBufferPtr++)) >> 4) & 0x0f;
+              const uint8_t prew0 = (*(outBufferPtr)) & 0x0f;
+              const uint8_t w0    = (prew0 + w) & 0x0f;
+              ++offset;
+
+              *(outBufferPtr++) = (w0 << 4) | w0;
+            }
+          }
+          else
+          {
+            for(uint8_t iter = 1; iter < nonRunLength; iter += 2)
+            {
+              const uint8_t w     = *(inBufferPtr++);
+              const uint8_t prew0 = (*(outBufferPtr)) & 0x0f;
+              const uint8_t w0    = (prew0 + ((w >> 4) & 0x0f)) & 0x0f;
+              const uint8_t prew1 = (*(outBufferPtr + 1)) & 0x0f;
+              const uint8_t w1    = (prew1 + (w & 0x0f)) & 0x0f;
+              ++offset;
+
+              *(outBufferPtr++) = (w0 << 4) | w0;
+              *(outBufferPtr++) = (w1 << 4) | w1;
+            }
+          }
+        }
+      }
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+}
+
+} // namespace TextAbstraction
+
+} // namespace Dali
diff --git a/dali/devel-api/text-abstraction/glyph-buffer-data.h b/dali/devel-api/text-abstraction/glyph-buffer-data.h
new file mode 100644 (file)
index 0000000..89afaa8
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef DALI_TEXT_ABSTRACTION_GLYPH_BUFFER_DATA_H
+#define DALI_TEXT_ABSTRACTION_GLYPH_BUFFER_DATA_H
+
+/*
+ * Copyright (c) 2023 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/images/pixel.h>
+#include <cstddef> /// for size_t
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
+#include <dali/public-api/dali-adaptor-common.h>
+
+namespace Dali
+{
+namespace TextAbstraction
+{
+/**
+  * @brief Struct used to retrieve the glyph's bitmap.
+  */
+struct DALI_ADAPTOR_API GlyphBufferData
+{
+  /**
+    * @brief Constructor.
+    *
+    * Initializes struct members to their defaults.
+    */
+  GlyphBufferData();
+
+  /**
+    * @brief Destructor.
+    */
+  ~GlyphBufferData();
+
+  /**
+    * @brief Move constructor.
+    *
+    * @param[in] rhs moved data.
+    */
+  GlyphBufferData(GlyphBufferData&& rhs) noexcept;
+
+  /**
+    * @brief Move assign operator.
+    *
+    * @param[in] rhs moved data.
+    * @return A reference to this.
+    */
+  GlyphBufferData& operator=(GlyphBufferData&& rhs) noexcept;
+
+  // Compression method of buffer. Each buffer compressed line by line
+  enum class CompressionType
+  {
+    NO_COMPRESSION = 0, // No compression
+    BPP_4          = 1, // Compress as 4 bit. Color become value * 17 (0x00, 0x11, 0x22, ... 0xee, 0xff).
+                        // Only works for Pixel::L8 format
+    RLE_4 = 2,          // Compress as 4 bit, and Run-Length-Encode. For more high compress rate, we store difference between previous scanline.
+                        // Only works for Pixel::L8 format
+  };
+
+  /**
+    * @brief Helper static function to compress raw buffer from inBuffer to outBufferData.buffer.
+    * outBufferData will have it's own buffer.
+    *
+    * @pre outBufferData must not have it's own buffer.
+    * @param[in] inBuffer The input raw data.
+    * @param[in, out] outBufferData The output glyph buffer data.
+    * @return Size of compressed out buffer, Or 0 if compress failed.
+    */
+  static size_t Compress(const uint8_t* const inBuffer, GlyphBufferData& outBufferData);
+
+  /**
+    * @brief Helper static function to decompress raw buffer from inBuffer to outBufferPtr.
+    * If outBuffer is nullptr, Do nothing.
+    *
+    * @pre outBuffer memory should be allocated.
+    * @param[in] inBufferData The input glyph buffer data.
+    * @param[in, out] outBuffer The output pointer of raw buffer data.
+    */
+  static void Decompress(const GlyphBufferData& inBufferData, uint8_t* outBuffer);
+
+  /**
+    * @brief Special Helper static function to decompress raw buffer from inBuffer to outBuffer one scanline.
+    * After decompress one scanline successed, offset will be changed.
+    *
+    * @pre outBuffer memory should be allocated.
+    * @pre if inBufferData's compression type is RLE4, outBuffer memory should store the previous scanline data.
+    * @param[in] inBufferData The input glyph buffer data.
+    * @param[in, out] outBuffer The output pointer of raw buffer data.
+    * @param[in, out] offset The offset of input. It will be changed as next scanline's offset.
+    */
+  static void DecompressScanline(const GlyphBufferData& inBufferData, uint8_t* outBuffer, uint32_t& offset);
+
+private:
+  // Delete copy operation.
+  GlyphBufferData(const GlyphBufferData& rhs) = delete;
+  GlyphBufferData& operator=(const GlyphBufferData& rhs) = delete;
+
+public:
+  uint8_t*        buffer;            ///< The glyph's bitmap buffer data.
+  uint32_t        width;             ///< The width of the bitmap.
+  uint32_t        height;            ///< The height of the bitmap.
+  int             outlineOffsetX;    ///< The additional horizontal offset to be added for the glyph's position for outline.
+  int             outlineOffsetY;    ///< The additional vertical offset to be added for the glyph's position for outline.
+  Pixel::Format   format;            ///< The pixel's format of the bitmap.
+  CompressionType compressionType;   ///< The type of buffer compression.
+  bool            isColorEmoji : 1;  ///< Whether the glyph is an emoji.
+  bool            isColorBitmap : 1; ///< Whether the glyph is a color bitmap.
+  bool            isBufferOwned : 1; ///< Whether the glyph's bitmap buffer data owned by this class or not. Becareful when you use non-owned buffer data.
+};
+
+} // namespace TextAbstraction
+
+} // namespace Dali
+
+#endif //DALI_TEXT_ABSTRACTION_GLYPH_INFO_H
index d58c3f1..4d7af0d 100644 (file)
@@ -92,7 +92,7 @@ struct GlyphBuffer
     DELETE
   };
 
-  GlyphBuffer(Dali::TextAbstraction::FontClient::GlyphBufferData& data, DestructorType type)
+  GlyphBuffer(Dali::TextAbstraction::GlyphBufferData& data, DestructorType type)
   : data(data),
     type(type)
   {
@@ -114,8 +114,8 @@ struct GlyphBuffer
     }
   }
 
-  Dali::TextAbstraction::FontClient::GlyphBufferData& data;
-  DestructorType                                      type;
+  Dali::TextAbstraction::GlyphBufferData& data;
+  DestructorType                          type;
 };
 
 /**
@@ -364,7 +364,7 @@ bool ConvertSizeForCairo(
 void CopyImageToSurface(
   const TextAbstraction::TextRenderer::Parameters& parameters,
   const Pixel::Format                              pixelFormat,
-  TextAbstraction::FontClient::GlyphBufferData&    data,
+  TextAbstraction::GlyphBufferData&                data,
   unsigned char*                                   buffer,
   const int                                        rgbaCase,
   const double                                     glyphX,
@@ -853,7 +853,7 @@ Devel::PixelBuffer RenderTextCairo(const TextAbstraction::TextRenderer::Paramete
           const cairo_glyph_t& glyph = *(cairoGlyphsBuffer + index);
 
           // Retrieve the image
-          TextAbstraction::FontClient::GlyphBufferData data;
+          TextAbstraction::GlyphBufferData data;
           if(isEmoji)
           {
             data.width  = parameters.glyphs[run.glyphIndex].width;
@@ -893,12 +893,12 @@ Devel::PixelBuffer RenderTextCairo(const TextAbstraction::TextRenderer::Paramete
             const unsigned int pixelSize = Pixel::GetBytesPerPixel(data.format);
 
             // If we need to decompress, create new memory and replace ownership.
-            if(data.compressionType != TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION)
+            if(data.compressionType != TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION)
             {
               uint8_t* newBuffer = (uint8_t*)malloc(widthOut * heightOut * pixelSize);
               if(DALI_LIKELY(newBuffer != nullptr))
               {
-                TextAbstraction::FontClient::GlyphBufferData::Decompress(data, newBuffer);
+                TextAbstraction::GlyphBufferData::Decompress(data, newBuffer);
                 if(data.isBufferOwned)
                 {
                   // Release previous buffer
@@ -906,7 +906,7 @@ Devel::PixelBuffer RenderTextCairo(const TextAbstraction::TextRenderer::Paramete
                 }
                 data.isBufferOwned   = true;
                 data.buffer          = newBuffer;
-                data.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+                data.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
               }
             }
 
@@ -926,7 +926,7 @@ Devel::PixelBuffer RenderTextCairo(const TextAbstraction::TextRenderer::Paramete
                 free(data.buffer);
               }
               data.isBufferOwned   = true;
-              data.compressionType = Dali::TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+              data.compressionType = Dali::TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
               data.buffer          = pixelsOut;
               data.width           = widthOut;
               data.height          = heightOut;
index f6e5c9c..6ea5072 100644 (file)
@@ -298,7 +298,7 @@ bool FontClient::GetGlyphMetrics(GlyphInfo* array, uint32_t size, GlyphType type
   return mPlugin->GetGlyphMetrics(array, size, type, horizontal);
 }
 
-void FontClient::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth)
+void FontClient::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth)
 {
   CreatePlugin();
 
index d93a053..288b8aa 100644 (file)
@@ -197,9 +197,9 @@ public: // API for Dali::TextAbstraction::FontClient used.
   bool GetGlyphMetrics(GlyphInfo* array, uint32_t size, GlyphType type, bool horizontal);
 
   /**
-   * @copydoc Dali::TextAbstraction::FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth )
+   * @copydoc Dali::TextAbstraction::FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth )
    */
-  void CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth);
+  void CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth);
 
   /**
    * @copydoc Dali::TextAbstraction::FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth )
index 248bf82..addd860 100644 (file)
@@ -98,7 +98,7 @@ bool BitmapFontCacheItem::GetGlyphMetrics(GlyphInfo& glyphInfo, unsigned int dpi
 }
 
 void BitmapFontCacheItem::CreateBitmap(
-  GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const
+  GlyphIndex glyphIndex, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const
 {
   unsigned int index = 0u;
   for(auto& item : font.glyphs)
index c763c84..889b5b8 100644 (file)
@@ -59,7 +59,7 @@ struct BitmapFontCacheItem : public FontCacheItemInterface
   /**
    * @copydoc FontCacheItemInterface::CreateBitmap()
    */
-  void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const override;
+  void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const override;
 
   /**
    * @copydoc FontCacheItemInterface::IsColorGlyph()
index c2486c1..a0c8335 100644 (file)
@@ -30,8 +30,8 @@ void EmbeddedItem::GetGlyphMetrics(GlyphInfo& glyph)
   glyph.scaleFactor = 1.f;
 }
 
-void EmbeddedItem::CreateBitmap(const std::vector<PixelBufferCacheItem>&            pixelBufferCache,
-                                Dali::TextAbstraction::FontClient::GlyphBufferData& data)
+void EmbeddedItem::CreateBitmap(const std::vector<PixelBufferCacheItem>& pixelBufferCache,
+                                Dali::TextAbstraction::GlyphBufferData&  data)
 {
   data.width  = width;
   data.height = height;
@@ -46,7 +46,7 @@ void EmbeddedItem::CreateBitmap(const std::vector<PixelBufferCacheItem>&
   else
   {
     data.isBufferOwned   = true;
-    data.compressionType = Dali::TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+    data.compressionType = Dali::TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
 
     // Creates the output buffer
     const uint32_t bufferSize = data.width * data.height * 4u;
index 4f58b8b..863a75e 100644 (file)
@@ -48,8 +48,8 @@ struct EmbeddedItem
    * @param[in]  pixelBufferCache The pixel buffer cache
    * @param[out] data The bitmap data.
    */
-  void CreateBitmap(const std::vector<PixelBufferCacheItem>&            pixelBufferCache,
-                    Dali::TextAbstraction::FontClient::GlyphBufferData& data);
+  void CreateBitmap(const std::vector<PixelBufferCacheItem>& pixelBufferCache,
+                    Dali::TextAbstraction::GlyphBufferData&  data);
 
   PixelBufferId pixelBufferId{0u}; ///< Index to the vector of pixel buffers
   uint32_t      width{0u};         ///< The desired width.
index c5cce86..01a5d1c 100644 (file)
@@ -54,7 +54,7 @@ struct FontCacheItemInterface
    * @param[in] isItalicRequired
    * @param[in] isBoldRequired
    */
-  virtual void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const = 0;
+  virtual void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const = 0;
 
   /**
    * Return true if the glyph is colored
index e319b46..8814847 100644 (file)
@@ -778,7 +778,7 @@ bool FontClient::Plugin::GetVectorMetrics(GlyphInfo* array,
 #endif
 }
 
-void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth) const
+void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth) const
 {
   data.isColorBitmap                          = false;
   data.isColorEmoji                           = false;
@@ -796,15 +796,15 @@ void FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool
 
 PixelData FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex, int outlineWidth) const
 {
-  TextAbstraction::FontClient::GlyphBufferData data;
+  TextAbstraction::GlyphBufferData data;
 
   CreateBitmap(fontId, glyphIndex, false, false, data, outlineWidth);
 
   // If data is compressed or not owned buffer, copy this.
-  if(!data.isBufferOwned || data.compressionType != TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION)
+  if(!data.isBufferOwned || data.compressionType != TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION)
   {
     uint8_t* newBuffer = (uint8_t*)malloc(data.width * data.height * Pixel::GetBytesPerPixel(data.format));
-    TextAbstraction::FontClient::GlyphBufferData::Decompress(data, newBuffer);
+    TextAbstraction::GlyphBufferData::Decompress(data, newBuffer);
     if(data.isBufferOwned)
     {
       free(data.buffer);
@@ -812,7 +812,7 @@ PixelData FontClient::Plugin::CreateBitmap(FontId fontId, GlyphIndex glyphIndex,
 
     data.buffer          = newBuffer;
     data.isBufferOwned   = true;
-    data.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+    data.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
   }
 
   return PixelData::New(data.buffer,
index 8961200..2eeb281 100644 (file)
@@ -228,9 +228,9 @@ public: // Dali::TextAbstraction::FontClient
   bool GetVectorMetrics(GlyphInfo* array, uint32_t size, bool horizontal) const;
 
   /**
-   * @copydoc Dali::TextAbstraction::FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth )
+   * @copydoc Dali::TextAbstraction::FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth )
    */
-  void CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth) const;
+  void CreateBitmap(FontId fontId, GlyphIndex glyphIndex, bool isItalicRequired, bool isBoldRequired, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth) const;
 
   /**
    * @copydoc Dali::TextAbstraction::FontClient::CreateBitmap( FontId fontId, GlyphIndex glyphIndex, int outlineWidth )
index 2ca3b1c..5bfedb1 100644 (file)
@@ -161,7 +161,7 @@ const FontSlant::Type DefaultFontSlant()
  * @param[in] srcHeight The height of the bitmap.
  * @param[in] srcBuffer The buffer of the bitmap.
  */
-void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, unsigned int srcWidth, unsigned int srcHeight, const unsigned char* const srcBuffer, const Pixel::Format srcFormat)
+void ConvertBitmap(TextAbstraction::GlyphBufferData& data, unsigned int srcWidth, unsigned int srcHeight, const unsigned char* const srcBuffer, const Pixel::Format srcFormat)
 {
   // Set the input dimensions.
   const ImageDimensions inputDimensions(srcWidth, srcHeight);
@@ -176,7 +176,7 @@ void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, unsigned
   data.format = srcFormat;
 
   // Note we don't compress here
-  data.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+  data.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
 
   const uint32_t bytePerPixel = Dali::Pixel::GetBytesPerPixel(srcFormat);
 
@@ -211,7 +211,7 @@ void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, unsigned
  * @param[in] moveBuffer Whether the bitmap buffer move. True if just copy buffer pointer. False if we use memcpy. (Default is false.)
  * @note If you set moveBuffer=true, the bitmap's buffer moved frome srcBitmap to data. So srcBitmap buffer changed as nullptr.
  */
-void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap& srcBitmap, bool isShearRequired, bool moveBuffer)
+void ConvertBitmap(TextAbstraction::GlyphBufferData& data, FT_Bitmap& srcBitmap, bool isShearRequired, bool moveBuffer)
 {
   data.buffer = nullptr;
   if(srcBitmap.width * srcBitmap.rows > 0)
@@ -305,7 +305,7 @@ void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap
           data.format = Pixel::L8; // Sets the pixel format.
 
           // Note we don't compress here
-          data.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+          data.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
 
           if(moveBuffer)
           {
index 17ff1d7..e6b5f5f 100644 (file)
 
 namespace Dali::TextAbstraction::Internal
 {
-void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data,
-                   unsigned int                                  srcWidth,
-                   unsigned int                                  srcHeight,
-                   const unsigned char* const                    srcBuffer,
-                   const Pixel::Format                           srcFormat);
-
-void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data,
-                   FT_Bitmap&                                    srcBitmap,
-                   bool                                          isShearRequired,
-                   bool                                          moveBuffer = false);
+void ConvertBitmap(TextAbstraction::GlyphBufferData& data,
+                   unsigned int                      srcWidth,
+                   unsigned int                      srcHeight,
+                   const unsigned char* const        srcBuffer,
+                   const Pixel::Format               srcFormat);
+
+void ConvertBitmap(TextAbstraction::GlyphBufferData& data,
+                   FT_Bitmap&                        srcBitmap,
+                   bool                              isShearRequired,
+                   bool                              moveBuffer = false);
 
 /**
  * @brief Creates a font family pattern used to match fonts.
index 90fbb02..b0087f2 100644 (file)
@@ -357,7 +357,7 @@ bool FontFaceCacheItem::GetGlyphMetrics(GlyphInfo& glyphInfo, unsigned int dpiVe
  * @param[in]  isBoldRequired    Whether the glyph requires bold style.
  */
 void FontFaceCacheItem::CreateBitmap(
-  GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const
+  GlyphIndex glyphIndex, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const
 {
   GlyphCacheManager::GlyphCacheData glyphData;
   FT_Error                          error;
index 10608d7..f7ca2eb 100644 (file)
@@ -79,7 +79,7 @@ struct FontFaceCacheItem : public FontCacheItemInterface
   /**
    * @copydoc FontCacheItemInterface::CreateBitmap()
    */
-  void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::FontClient::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const override;
+  void CreateBitmap(GlyphIndex glyphIndex, Dali::TextAbstraction::GlyphBufferData& data, int outlineWidth, bool isItalicRequired, bool isBoldRequired) const override;
 
   /**
    * @copydoc FontCacheItemInterface::IsColorGlyph()
index a241635..097e9cd 100644 (file)
@@ -316,14 +316,14 @@ void GlyphCacheManager::CacheRenderedGlyphBuffer(
 
       GlyphCacheData& destinationGlpyhData = mLRUGlyphCache.GetElement(iter);
 
-      destinationGlpyhData.mRenderedBuffer = new TextAbstraction::FontClient::GlyphBufferData();
+      destinationGlpyhData.mRenderedBuffer = new TextAbstraction::GlyphBufferData();
       if(DALI_UNLIKELY(!destinationGlpyhData.mRenderedBuffer))
       {
         DALI_LOG_ERROR("Allocate GlyphBufferData failed\n");
         return;
       }
 
-      TextAbstraction::FontClient::GlyphBufferData& renderBuffer = *destinationGlpyhData.mRenderedBuffer;
+      TextAbstraction::GlyphBufferData& renderBuffer = *destinationGlpyhData.mRenderedBuffer;
 
       // Set basic informations.
       renderBuffer.width  = srcBitmap.width;
@@ -338,22 +338,22 @@ void GlyphCacheManager::CacheRenderedGlyphBuffer(
           if(policy == CompressionPolicyType::SPEED)
           {
             // If policy is SPEED, we will not compress bitmap.
-            renderBuffer.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+            renderBuffer.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
           }
           else
           {
             // If small enough glyph, compress as BPP4 method.
             if(srcBitmap.width < THRESHOLD_WIDTH_FOR_RLE4_COMPRESSION)
             {
-              renderBuffer.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::BPP_4;
+              renderBuffer.compressionType = TextAbstraction::GlyphBufferData::CompressionType::BPP_4;
             }
             else
             {
-              renderBuffer.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::RLE_4;
+              renderBuffer.compressionType = TextAbstraction::GlyphBufferData::CompressionType::RLE_4;
             }
           }
 
-          const auto compressedBufferSize = TextAbstraction::FontClient::GlyphBufferData::Compress(srcBitmap.buffer, renderBuffer);
+          const auto compressedBufferSize = TextAbstraction::GlyphBufferData::Compress(srcBitmap.buffer, renderBuffer);
           if(DALI_UNLIKELY(compressedBufferSize == 0u))
           {
             DALI_ASSERT_DEBUG(0 == "Compress failed at FT_PIXEL_MODE_GRAY");
@@ -368,10 +368,10 @@ void GlyphCacheManager::CacheRenderedGlyphBuffer(
         case FT_PIXEL_MODE_BGRA:
         {
           // Copy buffer without compress
-          renderBuffer.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+          renderBuffer.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
           renderBuffer.format          = Pixel::BGRA8888;
 
-          const auto compressedBufferSize = TextAbstraction::FontClient::GlyphBufferData::Compress(srcBitmap.buffer, renderBuffer);
+          const auto compressedBufferSize = TextAbstraction::GlyphBufferData::Compress(srcBitmap.buffer, renderBuffer);
           if(DALI_UNLIKELY(compressedBufferSize == 0u))
           {
             DALI_ASSERT_DEBUG(0 == "Compress failed at FT_PIXEL_MODE_BGRA");
index 15f5e45..dc19c76 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 // INTERNAL INCLUDES
-#include <dali/devel-api/text-abstraction/font-client.h> // For GlyphBufferData
+#include <dali/devel-api/text-abstraction/glyph-buffer-data.h>
 #include <dali/devel-api/text-abstraction/text-abstraction-definitions.h>
 #include <dali/internal/text/text-abstraction/plugin/lru-cache-container.h>
 
@@ -67,7 +67,7 @@ public:
     FT_Int32          mStyleFlags{0};  // Get from FT_Face
     bool              mIsBitmap{false};
 
-    TextAbstraction::FontClient::GlyphBufferData* mRenderedBuffer{nullptr}; // Rendered glyph buffer. Cached only if system allow to cache and we rendered it before. Otherwise, just nullptr
+    TextAbstraction::GlyphBufferData* mRenderedBuffer{nullptr}; // Rendered glyph buffer. Cached only if system allow to cache and we rendered it before. Otherwise, just nullptr
 
     /**
      * @brief Release the memory of loaded mGlyph / mBitmap.