// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
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
utc-Dali-GraphicsNativeImage.cpp
utc-Dali-GraphicsProgram.cpp
utc-Dali-GraphicsSampler.cpp
+ utc-Dali-GraphicsTexture.cpp
)
LIST(APPEND TC_SOURCES
../dali-adaptor/dali-test-suite-utils/test-actor-utils.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-application.cpp
../dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
+
../dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp
../dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-sampler.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-shader.cpp
- ../dali-adaptor/dali-test-suite-utils/test-graphics-program.cpp
+
../dali-adaptor/dali-test-suite-utils/test-native-image.cpp
../dali-adaptor/dali-test-suite-utils/test-platform-abstraction.cpp
../dali-adaptor/dali-test-suite-utils/test-render-controller.cpp
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
auto& gl = app.GetGlAbstraction();
- uint32_t width = 16u;
- uint32_t height = 24u;
+ {
+ uint32_t width = 16u;
+ uint32_t height = 24u;
- FrameBuffer framebuffer = FrameBuffer::New(width, height, FrameBuffer::Attachment::STENCIL);
+ FrameBuffer framebuffer = FrameBuffer::New(width, height, FrameBuffer::Attachment::STENCIL);
- DALI_TEST_CHECK(framebuffer);
+ DALI_TEST_CHECK(framebuffer);
- Texture dummyColorTexture = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
- Texture dummyDepthStencilTexture = CreateTexture(TextureType::TEXTURE_2D, Pixel::DEPTH_STENCIL, width, height);
- Actor dummyActor = CreateRenderableActor(dummyColorTexture);
- framebuffer.AttachColorTexture(dummyColorTexture);
- DevelFrameBuffer::AttachDepthStencilTexture(framebuffer, dummyDepthStencilTexture);
+ Texture dummyColorTexture = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height);
+ Texture dummyDepthStencilTexture = CreateTexture(TextureType::TEXTURE_2D, Pixel::DEPTH_STENCIL, width, height);
+ Actor dummyActor = CreateRenderableActor(dummyColorTexture);
+ framebuffer.AttachColorTexture(dummyColorTexture);
+ DevelFrameBuffer::AttachDepthStencilTexture(framebuffer, dummyDepthStencilTexture);
- app.GetScene().Add(dummyActor);
+ app.GetScene().Add(dummyActor);
- auto renderTask = CreateRenderTask(app, framebuffer);
+ auto renderTask = CreateRenderTask(app, framebuffer);
- DALI_TEST_CHECK(renderTask);
+ DALI_TEST_CHECK(renderTask);
- app.SendNotification();
- app.Render(16); // The above actor will get rendered and drawn once.
+ app.SendNotification();
+ app.Render(16); // The above actor will get rendered and drawn once.
- DALI_TEST_EQUALS(gl.CheckFramebufferColorAttachmentCount(), 1u, TEST_LOCATION);
- DALI_TEST_EQUALS(gl.CheckFramebufferDepthAttachmentCount(), 1u, TEST_LOCATION);
- DALI_TEST_EQUALS(gl.CheckFramebufferStencilAttachmentCount(), 1u, TEST_LOCATION);
- DALI_TEST_EQUALS(gl.CheckFramebufferDepthStencilAttachmentCount(), 1u, TEST_LOCATION);
- DALI_TEST_EQUALS(gl.CheckFramebufferDepthAttachment(), (GLenum)GL_FALSE, TEST_LOCATION);
- DALI_TEST_EQUALS(gl.CheckFramebufferStencilAttachment(), (GLenum)GL_FALSE, TEST_LOCATION);
- DALI_TEST_EQUALS(gl.CheckFramebufferDepthStencilAttachment(), (GLenum)GL_FALSE, TEST_LOCATION); // Check whether renderbuffer attached by DEPTH_STENCIL.
+ DALI_TEST_EQUALS(gl.CheckFramebufferColorAttachmentCount(), 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckFramebufferDepthAttachmentCount(), 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckFramebufferStencilAttachmentCount(), 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckFramebufferDepthStencilAttachmentCount(), 1u, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckFramebufferDepthAttachment(), (GLenum)GL_FALSE, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckFramebufferStencilAttachment(), (GLenum)GL_FALSE, TEST_LOCATION);
+ DALI_TEST_EQUALS(gl.CheckFramebufferDepthStencilAttachment(), (GLenum)GL_FALSE, TEST_LOCATION); // Check whether renderbuffer attached by DEPTH_STENCIL.
+
+ UnparentAndReset(dummyActor);
+ }
+ // Ensure some cleanup happens!
+ app.SendNotification();
+ app.Render(16);
+ app.SendNotification();
+ app.Render(16);
END_TEST;
}
DALI_TEST_EQUALS(gl.CheckFramebufferDepthStencilAttachment(), (GLenum)GL_FALSE, TEST_LOCATION); // Check whether renderbuffer attached by DEPTH_STENCIL.
END_TEST;
-}
\ No newline at end of file
+}
--- /dev/null
+/*
+ * 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.
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali/dali.h>
+
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+#include <test-actor-utils.h>
+#include <test-graphics-application.h>
+#include <test-graphics-framebuffer.h>
+
+using namespace Dali;
+
+namespace
+{
+} // namespace
+
+void utc_dali_texture_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+void utc_dali_texture_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+int UtcDaliTextureConvertUpload(void)
+{
+ TestGraphicsApplication app;
+ tet_infoline("UtcDaliGraphicsConvertUpload - Test that an RGB image is converted to RGBA after upload");
+
+ auto& gl = app.GetGlAbstraction();
+ gl.EnableTextureCallTrace(true);
+ gl.EnableTexParameterCallTrace(true);
+
+ int size = 200;
+ Texture texture = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, size, size);
+
+ int bufferSize = size * size * 3;
+ uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(bufferSize));
+ PixelData pixelData = PixelData::New(buffer, bufferSize, size, size, Pixel::RGB888, PixelData::FREE);
+ texture.Upload(pixelData, 0u, 0u, 0u, 0u, size, size);
+
+ Sampler sampler = Sampler::New();
+ sampler.SetFilterMode(FilterMode::LINEAR, FilterMode::LINEAR);
+
+ TextureSet textureSet = TextureSet::New();
+ textureSet.SetTexture(0u, texture);
+ textureSet.SetSampler(0u, sampler);
+
+ Actor dummyActor = CreateRenderableActor2(textureSet, "", "");
+ app.GetScene().Add(dummyActor);
+
+ app.SendNotification();
+ app.Render(16);
+
+ // Check that TexImage2D was called with right format
+ auto& textureTrace = gl.GetTextureTrace();
+ auto& texParameterTrace = gl.GetTexParameterTrace();
+ TraceCallStack::NamedParams namedParams;
+ DALI_TEST_CHECK(textureTrace.FindMethodAndGetParameters("TexImage2D", namedParams));
+ std::stringstream s;
+ s << std::hex << GL_RGBA;
+
+ DALI_TEST_EQUALS(texParameterTrace.CountMethod("TexParameteri"), 4, TEST_LOCATION);
+ std::stringstream out;
+ out << std::hex << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR;
+ DALI_TEST_EQUALS(texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+ DALI_TEST_EQUALS(namedParams["format"].str(), s.str(), TEST_LOCATION);
+ END_TEST;
+}
virtual void EmitBoundsChanged(Accessible* obj, Rect<> rect) = 0;
/**
+ * @brief Emits org.a11y.atspi.Event.Window.PostRender on the AT-SPI bus.
+ *
+ * @param[in] obj The Accessible sender object
+ *
+ * The sender of this event is expected to be an Accessible object that
+ * represents a top-level window.
+ *
+ * The actual number of events emitted during a given time interval may be smaller
+ * than the number of calls to this method, but at least one is guaranteed.
+ */
+ virtual void EmitPostRender(Accessible *obj) = 0;
+
+ /**
* @brief Emits key event on at-spi bus.
*
* Screen-reader might receive this event and reply, that given keycode is consumed. In that case
void OnPostRender()
{
- Accessibility::Bridge::GetCurrentBridge()->Emit(Accessibility::Accessible::Get(Self()), Accessibility::WindowEvent::POST_RENDER);
+ Accessibility::Bridge::GetCurrentBridge()->EmitPostRender(this);
}
-
}; // AdaptorAccessible
using AdaptorAccessiblesType = std::unordered_map<const Dali::RefObject*, std::unique_ptr<AdaptorAccessible> >;
return StyleMonitor(dynamic_cast<Internal::Adaptor::StyleMonitor*>(handle.GetObjectPtr()));
}
+bool StyleMonitor::EnsureFontClientCreated()
+{
+ return GetImplementation(*this).EnsureFontClientCreated();
+}
+
std::string StyleMonitor::GetDefaultFontFamily() const
{
return GetImplementation(*this).GetDefaultFontFamily();
static StyleMonitor DownCast(BaseHandle handle);
public: // Style Information
+
+ /**
+ * @brief Ensure the font client has been created.
+ *
+ * If font client doesn't exist, create it and set default values.
+ * @return true if the font client has been created.
+ */
+ bool EnsureFontClientCreated();
+
/**
* @brief Retrieves the default font family.
* @return The default font family.
${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
${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
#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).
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()
// 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>
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
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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
{
BOUNDS_CHANGED, ///< Bounds changed
SET_OFFSET, ///< Set offset
+ POST_RENDER, ///< Post render
};
// Custom specialization of std::hash
});
}
+void BridgeObject::EmitPostRender(Accessible *obj)
+{
+ AddCoalescableMessage(CoalescableMessages::POST_RENDER, obj, 0.5f, [=]() {
+ Emit(obj, WindowEvent::POST_RENDER);
+ });
+}
+
void BridgeObject::EmitCursorMoved(Accessible* obj, unsigned int cursorPosition)
{
if(!IsUp() || obj->IsHidden() || obj->GetSuppressedEvents()[AtspiEvent::TEXT_CARET_MOVED])
Accessible::GetInterfaceName(AtspiInterface::EVENT_OBJECT),
"ScrollFinished",
{"", "root"});
-}
\ No newline at end of file
+}
void EmitBoundsChanged(Dali::Accessibility::Accessible* obj, Dali::Rect<> rect) override;
/**
+ * @copydoc Dali::Accessibility::Bridge::EmitPostRender()
+ */
+ void EmitPostRender(Dali::Accessibility::Accessible* obj) override;
+
+ /**
* @copydoc Dali::Accessibility::Bridge::EmitMovedOutOfScreen()
*/
void EmitMovedOutOfScreen(Dali::Accessibility::Accessible* obj, Dali::Accessibility::ScreenRelativeMoveType type) override;
{
}
+ void EmitPostRender(Accessibility::Accessible *obj) override
+ {
+ }
+
Accessibility::Consumed Emit(Accessibility::KeyEventType type, unsigned int keyCode, const std::string& keyName, unsigned int timeStamp, bool isText) override
{
return Accessibility::Consumed::YES;
#include <dali/internal/window-system/common/event-handler.h>
#include <dali/internal/window-system/common/window-impl.h>
#include <dali/internal/window-system/common/window-render-surface.h>
+#include <dali/internal/window-system/common/window-system.h>
#include <dali/devel-api/adaptor-framework/accessibility-bridge.h>
#include <dali/internal/system/common/logging.h>
dpiHor = dpiVer = 0;
defaultWindow->GetSurface()->GetDpi(dpiHor, dpiVer);
-
- // set the DPI value for font rendering
- FontClient fontClient = FontClient::Get();
- fontClient.SetDpi(dpiHor, dpiVer);
+ Dali::Internal::Adaptor::WindowSystem::SetDpi(dpiHor, dpiVer);
// Initialize the thread controller
mThreadController->Initialize();
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
// CLASS HEADER
#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
// INTERNAL INCLUDES
#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
#include <dali/integration-api/debug.h>
#include <dali/integration-api/gl-abstraction.h>
#include <dali/integration-api/gl-defines.h>
#include <dali/integration-api/graphics-sync-abstraction.h>
+#include <dali/integration-api/pixel-data-integ.h>
#include <dali/internal/graphics/gles-impl/egl-sync-object.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
#include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
#include <dali/internal/graphics/gles-impl/gles-sync-object.h>
#include <dali/internal/graphics/gles-impl/gles3-graphics-memory.h>
#include <dali/internal/graphics/gles/egl-sync-implementation.h>
-#include <dali/public-api/common/dali-common.h>
#include <dali/internal/graphics/gles/egl-graphics.h>
void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface)
{
mSurfaceContexts.erase(std::remove_if(
- mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter)
- { return surface == iter.first; }),
+ mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
mSurfaceContexts.end());
}
{
if(surface && mGraphics->IsResourceContextSupported())
{
- auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter)
- { return (iter.first == surface); });
+ auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return (iter.first == surface); });
if(iter != mSurfaceContexts.end())
{
auto& info = request.first;
auto& source = request.second;
- if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
+ switch(source.sourceType)
{
- // GPU memory must be already allocated.
-
- // Check if it needs conversion
- auto* texture = static_cast<GLES::Texture*>(info.dstTexture);
- const auto& createInfo = texture->GetCreateInfo();
- auto srcFormat = GLES::GLTextureFormatType(info.srcFormat).format;
- auto srcType = GLES::GLTextureFormatType(info.srcFormat).type;
- auto destInternalFormat = GLES::GLTextureFormatType(createInfo.format).internalFormat;
- auto destFormat = GLES::GLTextureFormatType(createInfo.format).format;
+ case Graphics::TextureUpdateSourceInfo::Type::MEMORY:
+ case Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA:
+ {
+ // GPU memory must be already allocated.
- // From render-texture.cpp
- const bool isSubImage(info.dstOffset2D.x != 0 || info.dstOffset2D.y != 0 ||
- info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) ||
- info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
+ // Check if it needs conversion
+ auto* texture = static_cast<GLES::Texture*>(info.dstTexture);
+ const auto& createInfo = texture->GetCreateInfo();
+ auto srcFormat = GLES::GLTextureFormatType(info.srcFormat).format;
+ auto srcType = GLES::GLTextureFormatType(info.srcFormat).type;
+ auto destInternalFormat = GLES::GLTextureFormatType(createInfo.format).internalFormat;
+ auto destFormat = GLES::GLTextureFormatType(createInfo.format).format;
- auto* sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
- auto sourceStride = info.srcStride;
- std::vector<uint8_t> tempBuffer;
+ // From render-texture.cpp
+ const bool isSubImage(info.dstOffset2D.x != 0 || info.dstOffset2D.y != 0 ||
+ info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) ||
+ info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
- if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
- {
- // Convert RGB to RGBA if necessary.
- if(texture->TryConvertPixelData(source.memorySource.memory, info.srcFormat, createInfo.format, info.srcSize, info.srcStride, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer))
+ uint8_t* sourceBuffer;
+ if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
{
- sourceBuffer = &tempBuffer[0];
- sourceStride = 0u; // Converted buffer compacted. make stride as 0.
- srcFormat = destFormat;
- srcType = GLES::GLTextureFormatType(createInfo.format).type;
+ sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
}
- }
+ else
+ {
+ // Get buffer of PixelData
+ Dali::Integration::PixelDataBuffer pixelBufferData = Dali::Integration::GetPixelDataBuffer(source.pixelDataSource.pixelData);
- // Calculate the maximum mipmap level for the texture
- texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
+ sourceBuffer = pixelBufferData.buffer + info.srcOffset;
+ }
- GLenum bindTarget{GL_TEXTURE_2D};
- GLenum target{GL_TEXTURE_2D};
+ auto sourceStride = info.srcStride;
+ std::vector<uint8_t> tempBuffer;
- if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
- {
- bindTarget = GL_TEXTURE_CUBE_MAP;
- target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
- }
+ if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
+ {
+ // Convert RGB to RGBA if necessary.
+ if(texture->TryConvertPixelData(sourceBuffer, info.srcFormat, createInfo.format, info.srcSize, info.srcStride, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer))
+ {
+ sourceBuffer = &tempBuffer[0];
+ sourceStride = 0u; // Converted buffer compacted. make stride as 0.
+ srcFormat = destFormat;
+ srcType = GLES::GLTextureFormatType(createInfo.format).type;
+ }
+ }
- mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
- mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
+ // Calculate the maximum mipmap level for the texture
+ texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
- mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
+ GLenum bindTarget{GL_TEXTURE_2D};
+ GLenum target{GL_TEXTURE_2D};
- if(!isSubImage)
- {
- if(!texture->IsCompressed())
+ if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
{
- mGlAbstraction->TexImage2D(target,
- info.level,
- destInternalFormat,
- info.srcExtent2D.width,
- info.srcExtent2D.height,
- 0,
- srcFormat,
- srcType,
- sourceBuffer);
+ bindTarget = GL_TEXTURE_CUBE_MAP;
+ target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
}
- else
+
+ mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ mGlAbstraction->PixelStorei(GL_UNPACK_ROW_LENGTH, sourceStride);
+
+ mCurrentContext->BindTexture(bindTarget, texture->GetTextureTypeId(), texture->GetGLTexture());
+
+ if(!isSubImage)
{
- mGlAbstraction->CompressedTexImage2D(target,
- info.level,
- destInternalFormat,
- info.srcExtent2D.width,
- info.srcExtent2D.height,
- 0,
- info.srcSize,
- sourceBuffer);
+ if(!texture->IsCompressed())
+ {
+ mGlAbstraction->TexImage2D(target,
+ info.level,
+ destInternalFormat,
+ info.srcExtent2D.width,
+ info.srcExtent2D.height,
+ 0,
+ srcFormat,
+ srcType,
+ sourceBuffer);
+ }
+ else
+ {
+ mGlAbstraction->CompressedTexImage2D(target,
+ info.level,
+ destInternalFormat,
+ info.srcExtent2D.width,
+ info.srcExtent2D.height,
+ 0,
+ info.srcSize,
+ sourceBuffer);
+ }
}
- }
- else
- {
- if(!texture->IsCompressed())
+ else
{
- mGlAbstraction->TexSubImage2D(target,
- info.level,
- info.dstOffset2D.x,
- info.dstOffset2D.y,
- info.srcExtent2D.width,
- info.srcExtent2D.height,
- srcFormat,
- srcType,
- sourceBuffer);
+ if(!texture->IsCompressed())
+ {
+ mGlAbstraction->TexSubImage2D(target,
+ info.level,
+ info.dstOffset2D.x,
+ info.dstOffset2D.y,
+ info.srcExtent2D.width,
+ info.srcExtent2D.height,
+ srcFormat,
+ srcType,
+ sourceBuffer);
+ }
+ else
+ {
+ mGlAbstraction->CompressedTexSubImage2D(target,
+ info.level,
+ info.dstOffset2D.x,
+ info.dstOffset2D.y,
+ info.srcExtent2D.width,
+ info.srcExtent2D.height,
+ srcFormat,
+ info.srcSize,
+ sourceBuffer);
+ }
}
- else
+
+ if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
{
- mGlAbstraction->CompressedTexSubImage2D(target,
- info.level,
- info.dstOffset2D.x,
- info.dstOffset2D.y,
- info.srcExtent2D.width,
- info.srcExtent2D.height,
- srcFormat,
- info.srcSize,
- sourceBuffer);
+ // free staging memory
+ free(source.memorySource.memory);
}
+ break;
+ }
+ default:
+ {
+ // TODO: other sources
+ break;
}
- // free staging memory
- free(source.memorySource.memory);
- }
- else
- {
- // TODO: other sources
}
mTextureUpdateRequests.pop();
source.memorySource.memory = stagingBuffer;
break;
}
+ case Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA:
+ {
+ // Increase CPU memory usage since ownership of PixelData is now on mTextureUpdateRequests.
+ mTextureUploadTotalCPUMemoryUsed += info.srcSize;
+ break;
+ }
case Graphics::TextureUpdateSourceInfo::Type::BUFFER:
{
// TODO, with PBO support
StyleMonitor::StyleMonitor()
: mDefaultFontSize(-1)
{
- mFontClient = TextAbstraction::FontClient::Get();
- GetSystemDefaultFontFamily(mFontClient, mDefaultFontFamily);
- DALI_LOG_INFO(gLogFilter, Debug::Verbose, "StyleMonitor::StyleMonitor::DefaultFontFamily(%s)\n", mDefaultFontFamily.c_str());
- mDefaultFontSize = mFontClient.GetDefaultFontSize();
}
StyleMonitor::~StyleMonitor()
{
}
+bool StyleMonitor::EnsureFontClientCreated()
+{
+ if(!mFontClient)
+ {
+ mFontClient = TextAbstraction::FontClient::Get();
+ GetSystemDefaultFontFamily(mFontClient, mDefaultFontFamily);
+ DALI_LOG_INFO(gLogFilter, Debug::Verbose, "StyleMonitor::StyleMonitor::DefaultFontFamily(%s)\n", mDefaultFontFamily.c_str());
+ mDefaultFontSize = mFontClient.GetDefaultFontSize();
+ }
+
+ return mFontClient != nullptr ? true : false;
+}
+
void StyleMonitor::StyleChanged(StyleChange::Type styleChange)
{
switch(styleChange)
{
case StyleChange::DEFAULT_FONT_CHANGE:
{
- if(mFontClient)
+ if(EnsureFontClientCreated())
{
mFontClient.ResetSystemDefaults();
GetSystemDefaultFontFamily(mFontClient, mDefaultFontFamily);
case StyleChange::DEFAULT_FONT_SIZE_CHANGE:
{
- mDefaultFontSize = mFontClient.GetDefaultFontSize();
+ if(EnsureFontClientCreated())
+ {
+ mDefaultFontSize = mFontClient.GetDefaultFontSize();
+ }
break;
}
// Style Information
/**
+ * @copydoc Dali::StyleMonitor::EnsureFontClientCreated()
+ */
+ bool EnsureFontClientCreated();
+
+ /**
* @copydoc Dali::StyleMonitor::GetDefaultFontFamily() const
*/
std::string GetDefaultFontFamily() const;
DELETE
};
- GlyphBuffer(Dali::TextAbstraction::FontClient::GlyphBufferData& data, DestructorType type)
+ GlyphBuffer(Dali::TextAbstraction::GlyphBufferData& data, DestructorType type)
: data(data),
type(type)
{
}
}
- Dali::TextAbstraction::FontClient::GlyphBufferData& data;
- DestructorType type;
+ Dali::TextAbstraction::GlyphBufferData& data;
+ DestructorType type;
};
/**
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,
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;
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
}
data.isBufferOwned = true;
data.buffer = newBuffer;
- data.compressionType = TextAbstraction::FontClient::GlyphBufferData::CompressionType::NO_COMPRESSION;
+ data.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
}
}
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;
// INTERNAL INCLUDES
#include <dali/devel-api/common/singleton-service.h>
#include <dali/internal/text/text-abstraction/plugin/font-client-plugin-impl.h>
+#include <dali/internal/window-system/common/window-system.h>
#include <dali/devel-api/text-abstraction/glyph-info.h>
fontClientHandle = Dali::TextAbstraction::FontClient(new FontClient);
}
+ uint32_t horizontalDpi, verticalDpi;
+ fontClientHandle.GetDpi(horizontalDpi, verticalDpi);
+ if(horizontalDpi == 0u || verticalDpi == 0u)
+ {
+ horizontalDpi = verticalDpi = 0u;
+ Dali::Internal::Adaptor::WindowSystem::GetDpi(horizontalDpi, verticalDpi);
+ fontClientHandle.SetDpi(horizontalDpi, verticalDpi);
+ }
+
service.Register(typeid(fontClientHandle), fontClientHandle);
}
}
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();
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 )
}
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)
/**
* @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()
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;
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;
* @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.
* @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
#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;
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);
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,
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 )
* @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);
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);
* @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)
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)
{
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.
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
using Dali::EnvironmentVariable::GetEnvironmentVariable;
static auto policyString = GetEnvironmentVariable(RENDERED_GLYPH_COMPRESS_POLICY_ENV);
- static auto policy = policyString ? policyString[0] == 's' || policyString[0] == 'S' ? GlyphCacheManager::CompressionPolicyType::SPEED
- : policyString[0] == 'm' || policyString[0] == 'M' ? GlyphCacheManager::CompressionPolicyType::MEMORY
- : DEFAULT_RENDERED_GLYPH_COMPRESS_POLICY
+ static auto policy = policyString ? policyString[0] == 's' || policyString[0] == 'S' ? GlyphCacheManager::CompressionPolicyType::SPEED
+ : policyString[0] == 'm' || policyString[0] == 'M' ? GlyphCacheManager::CompressionPolicyType::MEMORY
+ : DEFAULT_RENDERED_GLYPH_COMPRESS_POLICY
: DEFAULT_RENDERED_GLYPH_COMPRESS_POLICY;
return policy;
}
{
bool success(true);
- GlyphCacheManager::GlyphCacheData glyphData;
- FT_Error error;
+ GlyphCacheManager::GlyphCacheDataPtr glyphDataPtr;
+ FT_Error error;
#ifdef FREETYPE_BITMAP_SUPPORT
// Check to see if we should be loading a Fixed Size bitmap?
if(mIsFixedSizeBitmap)
{
FT_Select_Size(mFreeTypeFace, mFixedSizeIndex); ///< @todo: needs to be investigated why it's needed to select the size again.
- mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphInfo.index, FT_LOAD_COLOR, glyphInfo.isBoldRequired, glyphData, error);
+ mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphInfo.index, FT_LOAD_COLOR, glyphInfo.isBoldRequired, glyphDataPtr, error);
if(FT_Err_Ok == error)
{
+ GlyphCacheManager::GlyphCacheData& glyphData = *glyphDataPtr.get();
+
glyphInfo.width = mFixedWidthPixels;
glyphInfo.height = mFixedHeightPixels;
glyphInfo.advance = mFixedWidthPixels;
// FT_LOAD_DEFAULT causes some issues in the alignment of the glyph inside the bitmap.
// i.e. with the SNum-3R font.
// @todo: add an option to use the FT_LOAD_DEFAULT if required?
- mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphInfo.index, FT_LOAD_NO_AUTOHINT, glyphInfo.isBoldRequired, glyphData, error);
+ mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphInfo.index, FT_LOAD_NO_AUTOHINT, glyphInfo.isBoldRequired, glyphDataPtr, error);
// Keep the width of the glyph before doing the software emboldening.
// It will be used to calculate a scale factor to be applied to the
if(FT_Err_Ok == error)
{
+ GlyphCacheManager::GlyphCacheData& glyphData = *glyphDataPtr.get();
+
const auto& metrics = glyphData.mGlyphMetrics;
glyphInfo.width = static_cast<float>(metrics.width) * FROM_266;
if(isEmboldeningRequired)
{
// Get dummy glyph data without embolden.
- GlyphCacheManager::GlyphCacheData dummyData;
- if(mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphInfo.index, FT_LOAD_NO_AUTOHINT, false, dummyData, error))
+ GlyphCacheManager::GlyphCacheDataPtr dummyDataPtr;
+ if(mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphInfo.index, FT_LOAD_NO_AUTOHINT, false, dummyDataPtr, error))
{
// If the glyph is emboldened by software, the advance is multiplied by a
// scale factor to make it slightly bigger.
- const float width = static_cast<float>(dummyData.mGlyphMetrics.width) * FROM_266;
+ const float width = static_cast<float>(dummyDataPtr->mGlyphMetrics.width) * FROM_266;
if(!EqualsZero(width))
{
glyphInfo.advance *= (glyphInfo.width / width);
* @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;
- FT_Int32 loadFlag;
+ GlyphCacheManager::GlyphCacheDataPtr glyphDataPtr;
+ FT_Error error;
+ FT_Int32 loadFlag;
// For the software italics.
bool isShearRequired = false;
// @todo: add an option to use the FT_LOAD_DEFAULT if required?
loadFlag = FT_LOAD_NO_AUTOHINT;
}
- mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphIndex, loadFlag, isBoldRequired, glyphData, error);
+ mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphIndex, loadFlag, isBoldRequired, glyphDataPtr, error);
if(FT_Err_Ok == error)
{
+ GlyphCacheManager::GlyphCacheData& glyphData = *glyphDataPtr.get();
+
if(isItalicRequired && !(glyphData.mStyleFlags & FT_STYLE_FLAG_ITALIC))
{
// Will do the software italic.
{
mGlyphCacheManager->CacheRenderedGlyphBuffer(mFreeTypeFace, glyphIndex, loadFlag, isBoldRequired, bitmapGlyph->bitmap, GetRenderedGlyphCompressPolicy());
- GlyphCacheManager::GlyphCacheData dummyData;
- mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphIndex, loadFlag, isBoldRequired, dummyData, error);
+ GlyphCacheManager::GlyphCacheDataPtr dummyDataPtr;
+ mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphIndex, loadFlag, isBoldRequired, dummyDataPtr, error);
- if(DALI_LIKELY(FT_Err_Ok == error && dummyData.mRenderedBuffer))
+ if(DALI_LIKELY(FT_Err_Ok == error && dummyDataPtr->mRenderedBuffer))
{
- data.buffer = dummyData.mRenderedBuffer->buffer;
- data.width = dummyData.mRenderedBuffer->width;
- data.height = dummyData.mRenderedBuffer->height;
- data.format = dummyData.mRenderedBuffer->format;
- data.compressionType = dummyData.mRenderedBuffer->compressionType;
+ data.buffer = dummyDataPtr->mRenderedBuffer->buffer;
+ data.width = dummyDataPtr->mRenderedBuffer->width;
+ data.height = dummyDataPtr->mRenderedBuffer->height;
+ data.format = dummyDataPtr->mRenderedBuffer->format;
+ data.compressionType = dummyDataPtr->mRenderedBuffer->compressionType;
data.isBufferOwned = false;
}
else
// Check to see if this is fixed size bitmap
if(mHasColorTables)
{
- GlyphCacheManager::GlyphCacheData dummyData;
- mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphIndex, FT_LOAD_COLOR, false, dummyData, error);
+ GlyphCacheManager::GlyphCacheDataPtr dummyDataPtr;
+ mGlyphCacheManager->GetGlyphCacheDataFromIndex(mFreeTypeFace, glyphIndex, FT_LOAD_COLOR, false, dummyDataPtr, error);
}
#endif
return FT_Err_Ok == error;
/**
* @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()
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
}
bool GlyphCacheManager::GetGlyphCacheDataFromIndex(
- const FT_Face freeTypeFace,
- const GlyphIndex index,
- const FT_Int32 flag,
- const bool isBoldRequired,
- GlyphCacheData& glyphData,
- FT_Error& error)
+ const FT_Face freeTypeFace,
+ const GlyphIndex index,
+ const FT_Int32 flag,
+ const bool isBoldRequired,
+ GlyphCacheDataPtr& glyphDataPtr,
+ FT_Error& error)
{
// Append some error value here instead of FT_Err_Ok.
error = static_cast<FT_Error>(-1);
{
auto removedData = mLRUGlyphCache.Pop();
- DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "FontClient::Plugin::GlyphCacheManager::GetGlyphCacheDataFromIndex. Remove oldest cache for glyph : %p\n", removedData.mGlyph);
-
- // Release Glyph data resource
- removedData.ReleaseGlyphData();
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "FontClient::Plugin::GlyphCacheManager::GetGlyphCacheDataFromIndex. Remove oldest cache for glyph : %p\n", removedData->mGlyph);
}
+ // Create new GlyphCacheData.
+ glyphDataPtr = std::make_shared<GlyphCacheData>();
+
+ GlyphCacheData& glyphData = *glyphDataPtr.get();
+
const bool loadSuccess = LoadGlyphDataFromIndex(freeTypeFace, index, flag, isBoldRequired, glyphData, error);
if(loadSuccess)
{
// Copy and cached data.
- mLRUGlyphCache.Push(key, glyphData);
+ mLRUGlyphCache.Push(key, glyphDataPtr);
DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "FontClient::Plugin::GlyphCacheManager::GetGlyphCacheDataFromIndex. Create cache for face : %p, index : %u flag : %d isBold : %d isBitmap : %d, glyph : %p\n", freeTypeFace, index, static_cast<int>(flag), isBoldRequired, glyphData.mIsBitmap, glyphData.mGlyph);
}
error = FT_Err_Ok;
// We already notify that we use this glyph. And now, copy cached data.
- glyphData = mLRUGlyphCache.GetElement(iter);
+ glyphDataPtr = mLRUGlyphCache.GetElement(iter);
- DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "FontClient::Plugin::GlyphCacheManager::GetGlyphCacheDataFromIndex. Find cache for face : %p, index : %u flag : %d isBold : %d isBitmap : %d, glyph : %p\n", freeTypeFace, index, static_cast<int>(flag), isBoldRequired, glyphData.mIsBitmap, glyphData.mGlyph);
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "FontClient::Plugin::GlyphCacheManager::GetGlyphCacheDataFromIndex. Find cache for face : %p, index : %u flag : %d isBold : %d isBitmap : %d, glyph : %p\n", freeTypeFace, index, static_cast<int>(flag), isBoldRequired, glyphDataPtr->mIsBitmap, glyphDataPtr->mGlyph);
return true;
}
}
// Skip this API if desired size is zero
return;
}
- FT_Error error;
- GlyphCacheData originGlyphData;
- if(GetGlyphCacheDataFromIndex(freeTypeFace, index, flag, isBoldRequired, originGlyphData, error))
+ FT_Error error;
+ GlyphCacheDataPtr glyphDataPtr;
+ if(GetGlyphCacheDataFromIndex(freeTypeFace, index, flag, isBoldRequired, glyphDataPtr, error))
{
- if(DALI_LIKELY(originGlyphData.mIsBitmap && originGlyphData.mBitmap))
+ GlyphCacheData& glyphData = *glyphDataPtr.get();
+ if(DALI_LIKELY(glyphData.mIsBitmap && glyphData.mBitmap))
{
- const bool requiredResize = (originGlyphData.mBitmap->rows != desiredHeight) || (originGlyphData.mBitmap->width != desiredWidth);
+ const bool requiredResize = (glyphData.mBitmap->rows != desiredHeight) || (glyphData.mBitmap->width != desiredWidth);
if(requiredResize)
{
- // originalGlyphData is copy data. For change cached information, we should access as iterator.
- const GlyphCacheKey key = GlyphCacheKey(freeTypeFace, index, flag, isBoldRequired);
- auto iter = mLRUGlyphCache.Find(key);
-
- GlyphCacheData& destinationGlpyhData = mLRUGlyphCache.GetElement(iter);
-
- const ImageDimensions inputDimensions(destinationGlpyhData.mBitmap->width, destinationGlpyhData.mBitmap->rows);
+ const ImageDimensions inputDimensions(glyphData.mBitmap->width, glyphData.mBitmap->rows);
const ImageDimensions desiredDimensions(desiredWidth, desiredHeight);
uint8_t* desiredBuffer = nullptr;
- switch(destinationGlpyhData.mBitmap->pixel_mode)
+ switch(glyphData.mBitmap->pixel_mode)
{
case FT_PIXEL_MODE_GRAY:
{
- if(destinationGlpyhData.mBitmap->pitch == static_cast<int>(destinationGlpyhData.mBitmap->width))
+ if(glyphData.mBitmap->pitch == static_cast<int>(glyphData.mBitmap->width))
{
desiredBuffer = (uint8_t*)malloc(desiredWidth * desiredHeight * sizeof(uint8_t)); // @note The caller is responsible for deallocating the bitmap data using free.
// Resize bitmap here.
- Dali::Internal::Platform::LanczosSample1BPP(destinationGlpyhData.mBitmap->buffer,
+ Dali::Internal::Platform::LanczosSample1BPP(glyphData.mBitmap->buffer,
inputDimensions,
- destinationGlpyhData.mBitmap->width,
+ glyphData.mBitmap->width,
desiredBuffer,
desiredDimensions);
}
#ifdef FREETYPE_BITMAP_SUPPORT
case FT_PIXEL_MODE_BGRA:
{
- if(destinationGlpyhData.mBitmap->pitch == static_cast<int>(destinationGlpyhData.mBitmap->width << 2u))
+ if(glyphData.mBitmap->pitch == static_cast<int>(glyphData.mBitmap->width << 2u))
{
desiredBuffer = (uint8_t*)malloc((desiredWidth * desiredHeight * sizeof(uint8_t)) << 2u); // @note The caller is responsible for deallocating the bitmap data using free.
// Resize bitmap here.
- Dali::Internal::Platform::LanczosSample4BPP(destinationGlpyhData.mBitmap->buffer,
+ Dali::Internal::Platform::LanczosSample4BPP(glyphData.mBitmap->buffer,
inputDimensions,
- destinationGlpyhData.mBitmap->width,
+ glyphData.mBitmap->width,
desiredBuffer,
desiredDimensions);
}
{
// Success to resize bitmap glyph.
// Release origin bitmap buffer.
- free(destinationGlpyhData.mBitmap->buffer);
+ free(glyphData.mBitmap->buffer);
// Replace as desired buffer and size.
- destinationGlpyhData.mBitmap->buffer = desiredBuffer;
- destinationGlpyhData.mBitmap->width = desiredWidth;
- destinationGlpyhData.mBitmap->rows = desiredHeight;
- switch(destinationGlpyhData.mBitmap->pixel_mode)
+ glyphData.mBitmap->buffer = desiredBuffer;
+ glyphData.mBitmap->width = desiredWidth;
+ glyphData.mBitmap->rows = desiredHeight;
+ switch(glyphData.mBitmap->pixel_mode)
{
case FT_PIXEL_MODE_GRAY:
{
- destinationGlpyhData.mBitmap->pitch = desiredWidth;
+ glyphData.mBitmap->pitch = desiredWidth;
break;
}
#ifdef FREETYPE_BITMAP_SUPPORT
case FT_PIXEL_MODE_BGRA:
{
- destinationGlpyhData.mBitmap->pitch = desiredWidth << 2u;
+ glyphData.mBitmap->pitch = desiredWidth << 2u;
break;
}
#endif
// Skip this API if rendered bitmap size is zero
return;
}
- FT_Error error;
- GlyphCacheData originGlyphData;
- if(GetGlyphCacheDataFromIndex(freeTypeFace, index, flag, isBoldRequired, originGlyphData, error))
+ FT_Error error;
+ GlyphCacheDataPtr glyphDataPtr;
+ if(GetGlyphCacheDataFromIndex(freeTypeFace, index, flag, isBoldRequired, glyphDataPtr, error))
{
- if(DALI_LIKELY(!originGlyphData.mIsBitmap && originGlyphData.mRenderedBuffer == nullptr))
+ GlyphCacheData& glyphData = *glyphDataPtr.get();
+ if(DALI_LIKELY(!glyphData.mIsBitmap && glyphData.mRenderedBuffer == nullptr))
{
- // originalGlyphData is copy data. For change cached information, we should access as iterator.
- const GlyphCacheKey key = GlyphCacheKey(freeTypeFace, index, flag, isBoldRequired);
- auto iter = mLRUGlyphCache.Find(key);
-
- GlyphCacheData& destinationGlpyhData = mLRUGlyphCache.GetElement(iter);
-
- destinationGlpyhData.mRenderedBuffer = new TextAbstraction::FontClient::GlyphBufferData();
- if(DALI_UNLIKELY(!destinationGlpyhData.mRenderedBuffer))
+ glyphData.mRenderedBuffer = new TextAbstraction::GlyphBufferData();
+ if(DALI_UNLIKELY(!glyphData.mRenderedBuffer))
{
DALI_LOG_ERROR("Allocate GlyphBufferData failed\n");
return;
}
- TextAbstraction::FontClient::GlyphBufferData& renderBuffer = *destinationGlpyhData.mRenderedBuffer;
+ TextAbstraction::GlyphBufferData& renderBuffer = *glyphData.mRenderedBuffer;
// Set basic informations.
renderBuffer.width = srcBitmap.width;
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");
DALI_LOG_ERROR("Compress failed. Ignore cache\n");
- delete destinationGlpyhData.mRenderedBuffer;
- destinationGlpyhData.mRenderedBuffer = nullptr;
+ delete glyphData.mRenderedBuffer;
+ glyphData.mRenderedBuffer = nullptr;
return;
}
break;
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");
DALI_LOG_ERROR("Compress failed. Ignore cache\n");
- delete destinationGlpyhData.mRenderedBuffer;
- destinationGlpyhData.mRenderedBuffer = nullptr;
+ delete glyphData.mRenderedBuffer;
+ glyphData.mRenderedBuffer = nullptr;
return;
}
break;
default:
{
DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::GlyphCacheManager::CacheRenderedGlyphBuffer. FontClient Unable to create Bitmap of this PixelType\n");
- delete destinationGlpyhData.mRenderedBuffer;
- destinationGlpyhData.mRenderedBuffer = nullptr;
+ delete glyphData.mRenderedBuffer;
+ glyphData.mRenderedBuffer = nullptr;
break;
}
}
{
if(remainCount == 0u)
{
- // Release all data memory first.
- auto endIter = mLRUGlyphCache.End();
- for(auto iter = mLRUGlyphCache.Begin(); iter != endIter; ++iter)
- {
- // Get the reference of data. and release it.
- auto& removedData = mLRUGlyphCache.GetElement(iter);
- removedData.ReleaseGlyphData();
- }
-
// Clear all cache.
mLRUGlyphCache.Clear();
}
{
auto removedData = mLRUGlyphCache.Pop();
- DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "FontClient::Plugin::GlyphCacheManager::ClearCache[%zu / %zu]. Remove oldest cache for glyph : %p\n", mLRUGlyphCache.Count(), remainCount, removedData.mGlyph);
-
- // Release Glyph data resource
- removedData.ReleaseGlyphData();
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, "FontClient::Plugin::GlyphCacheManager::ClearCache[%zu / %zu]. Remove oldest cache for glyph : %p\n", mLRUGlyphCache.Count(), remainCount, removedData->mGlyph);
}
}
}
+// GlyphCacheManager::GlyphCacheData
+
void GlyphCacheManager::GlyphCacheData::ReleaseGlyphData()
{
if(mIsBitmap && mBitmap)
{
// Created FT_Bitmap object must be released with FT_Bitmap_Done
+ // But, this class's mBitmap it not an actual FT_Bitmap object. So free buffer is enough.
free(mBitmap->buffer); // This buffer created by malloc
delete mBitmap;
mStyleFlags = 0;
}
+GlyphCacheManager::GlyphCacheData::GlyphCacheData()
+: mGlyph{nullptr},
+ mGlyphMetrics{},
+ mStyleFlags{0},
+ mIsBitmap{false},
+ mRenderedBuffer{nullptr}
+{
+}
+
+GlyphCacheManager::GlyphCacheData::~GlyphCacheData()
+{
+ ReleaseGlyphData();
+}
+
+GlyphCacheManager::GlyphCacheData::GlyphCacheData(GlyphCacheData&& rhs) noexcept
+: mGlyph{nullptr},
+ mGlyphMetrics{},
+ mStyleFlags{0},
+ mIsBitmap{false},
+ mRenderedBuffer{nullptr}
+{
+ *this = std::move(rhs);
+}
+
+GlyphCacheManager::GlyphCacheData& GlyphCacheManager::GlyphCacheData::operator=(GlyphCacheData&& rhs) noexcept
+{
+ // Self-assignment detection
+ if(this == &rhs)
+ {
+ return *this;
+ }
+
+ // Delete self data first.
+ ReleaseGlyphData();
+
+ mIsBitmap = false;
+
+ if(rhs.mIsBitmap && rhs.mBitmap)
+ {
+ mIsBitmap = true;
+ mBitmap = rhs.mBitmap;
+
+ rhs.mBitmap = nullptr;
+ }
+ else if(rhs.mGlyph)
+ {
+ mGlyph = rhs.mGlyph;
+
+ rhs.mGlyph = nullptr;
+ }
+ else
+ {
+ mGlyph = nullptr;
+ }
+
+ if(rhs.mRenderedBuffer)
+ {
+ mRenderedBuffer = rhs.mRenderedBuffer;
+ rhs.mRenderedBuffer = nullptr;
+ }
+ else
+ {
+ mRenderedBuffer = nullptr;
+ }
+
+ mStyleFlags = rhs.mStyleFlags;
+ return *this;
+}
+
} // namespace Dali::TextAbstraction::Internal
#define DALI_TEST_ABSTRACTION_INTERNAL_FONT_FACE_GLYPH_CACHE_MANAGER_H
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
*/
// 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>
// EXTERNAL INCLUDES
+#include <memory> // for std::shared_ptr
+
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
*/
struct GlyphCacheData
{
- GlyphCacheData()
- : mGlyph{nullptr}
- {
- }
+ GlyphCacheData();
+ ~GlyphCacheData();
+
+ // Move operations
+ GlyphCacheData(GlyphCacheData&& rhs) noexcept;
+ GlyphCacheData& operator=(GlyphCacheData&& rhs) noexcept;
union
{
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
+
+ private:
+ // Delete copy operations
+ GlyphCacheData(const GlyphCacheData&) = delete;
+ GlyphCacheData& operator=(const GlyphCacheData&) = delete;
/**
- * @brief Release the memory of loaded mGlyph / mBitmap.
+ * @brief Release the memory of loaded mGlyph / mBitmap and mRenderedBuffer.
*/
void ReleaseGlyphData();
};
+ using GlyphCacheDataPtr = std::shared_ptr<GlyphCacheData>;
+
// Compression priority of rendered glyph buffer.
enum class CompressionPolicyType
{
/**
* @brief Load GlyphCacheData from face. The result will be cached.
+ * @note Inputed glyph data pointer will be overwrited.
*
* @param[in] freeTypeFace The freetype face handle.
* @param[in] index Index of glyph in this face.
* @param[in] flag Flag when we load the glyph.
* @param[in] isBoldRequired True if we require some software bold.
- * @param[out] data Result of glyph load.
+ * @param[out] glyphDataPtr Result of pointer of glyph load.
* @param[out] error Error code during load glyph.
* @return True if load successfully. False if something error occured.
*/
bool GetGlyphCacheDataFromIndex(
- const FT_Face freeTypeFace,
- const GlyphIndex index,
- const FT_Int32 flag,
- const bool isBoldRequired,
- GlyphCacheData& data,
- FT_Error& error);
+ const FT_Face freeTypeFace,
+ const GlyphIndex index,
+ const FT_Int32 flag,
+ const bool isBoldRequired,
+ GlyphCacheDataPtr& glyphDataPtr,
+ FT_Error& error);
/**
* @brief Load GlyphCacheData from face. The result will not be cached.
- * @note If we call this API, We should release GlyphCacheData manually.
*
* @param[in] freeTypeFace The freetype face handle.
* @param[in] index Index of glyph in this face.
* @param[in] flag Flag when we load the glyph.
* @param[in] isBoldRequired True if we require some software bold.
- * @param[out] data Result of glyph load.
+ * @param[in, out] glyphData Result of glyph load.
* @param[out] error Error code during load glyph.
* @return True if load successfully. False if something error occured.
*/
const GlyphIndex index,
const FT_Int32 flag,
const bool isBoldRequired,
- GlyphCacheData& data,
+ GlyphCacheData& glyphData,
FT_Error& error);
/**
// Private member value area.
std::size_t mGlyphCacheMaxSize; ///< The maximum capacity of glyph cache.
- using CacheContainer = LRUCacheContainer<GlyphCacheKey, GlyphCacheData, GlyphCacheKeyHash>;
+ using CacheContainer = LRUCacheContainer<GlyphCacheKey, GlyphCacheDataPtr, GlyphCacheKeyHash>;
CacheContainer mLRUGlyphCache; ///< LRU Cache container of glyph
};
/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * 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.
*
* @param[in] font_data HarfBuzzProxyFont::Impl pointer that register this callback as void* type.
* @param[in] glyphIndex Index of glyph.
- * @param[out] glyphData The result of cached glyph data.
+ * @param[out] glyphDataPtr The result of cached glyph data pointer.
* @return True if we success to get some glyph data. False otherwise.
*/
-static bool GetGlyphCacheData(void* font_data, const GlyphIndex& glyphIndex, GlyphCacheManager::GlyphCacheData& glyphData)
+static bool GetGlyphCacheData(void* font_data, const GlyphIndex& glyphIndex, GlyphCacheManager::GlyphCacheDataPtr& glyphDataPtr)
{
HarfBuzzProxyFont::Impl* impl = reinterpret_cast<HarfBuzzProxyFont::Impl*>(font_data);
if(DALI_LIKELY(impl && impl->mGlyphCacheManager))
{
FT_Error error;
- return impl->mGlyphCacheManager->GetGlyphCacheDataFromIndex(impl->mFreeTypeFace, glyphIndex, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING, false, glyphData, error);
+ return impl->mGlyphCacheManager->GetGlyphCacheDataFromIndex(impl->mFreeTypeFace, glyphIndex, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING, false, glyphDataPtr, error);
}
return false;
}
static hb_position_t GlyphHorizontalAdvanceFunc(hb_font_t* font, void* font_data, hb_codepoint_t glyphIndex, void* user_data)
{
// Output data stored here.
- GlyphCacheManager::GlyphCacheData glyphData;
- if(GetGlyphCacheData(font_data, static_cast<GlyphIndex>(glyphIndex), glyphData))
+ GlyphCacheManager::GlyphCacheDataPtr glyphDataPtr;
+ if(GetGlyphCacheData(font_data, static_cast<GlyphIndex>(glyphIndex), glyphDataPtr))
{
+ GlyphCacheManager::GlyphCacheData& glyphData = *glyphDataPtr.get();
+
// Note : It may return invalid value for fixed size bitmap glyph.
// But, Harfbuzz library also return Undefined advanced value if it is fixed size font.
// So we'll also ignore that case.
static hb_position_t GlyphVerticalAdvanceFunc(hb_font_t* font, void* font_data, hb_codepoint_t glyphIndex, void* user_data)
{
// Output data stored here.
- GlyphCacheManager::GlyphCacheData glyphData;
- if(GetGlyphCacheData(font_data, static_cast<GlyphIndex>(glyphIndex), glyphData))
+ GlyphCacheManager::GlyphCacheDataPtr glyphDataPtr;
+ if(GetGlyphCacheData(font_data, static_cast<GlyphIndex>(glyphIndex), glyphDataPtr))
{
+ GlyphCacheManager::GlyphCacheData& glyphData = *glyphDataPtr.get();
+
// Note : It may return invalid value for fixed size bitmap glyph.
// But, Harfbuzz library also return Undefined advanced value if it is fixed size font.
// So we'll also ignore that case.
static hb_bool_t GlyphVerticalOriginFunc(hb_font_t* font, void* font_data, hb_codepoint_t glyphIndex, hb_position_t* x, hb_position_t* y, void* user_data)
{
// Output data stored here.
- GlyphCacheManager::GlyphCacheData glyphData;
- if(GetGlyphCacheData(font_data, static_cast<GlyphIndex>(glyphIndex), glyphData))
+ GlyphCacheManager::GlyphCacheDataPtr glyphDataPtr;
+ if(GetGlyphCacheData(font_data, static_cast<GlyphIndex>(glyphIndex), glyphDataPtr))
{
+ GlyphCacheManager::GlyphCacheData& glyphData = *glyphDataPtr.get();
+
*x = glyphData.mGlyphMetrics.horiBearingX - glyphData.mGlyphMetrics.vertBearingX;
*y = glyphData.mGlyphMetrics.horiBearingY + glyphData.mGlyphMetrics.vertBearingY;
return true;
static hb_bool_t GlyphExtentsFunc(hb_font_t* font, void* font_data, hb_codepoint_t glyphIndex, hb_glyph_extents_t* extents, void* user_data)
{
// Output data stored here.
- GlyphCacheManager::GlyphCacheData glyphData;
- if(!GetGlyphCacheData(font_data, static_cast<GlyphIndex>(glyphIndex), glyphData))
+ GlyphCacheManager::GlyphCacheDataPtr glyphDataPtr;
+ if(GetGlyphCacheData(font_data, static_cast<GlyphIndex>(glyphIndex), glyphDataPtr))
{
+ GlyphCacheManager::GlyphCacheData& glyphData = *glyphDataPtr.get();
+
extents->x_bearing = glyphData.mGlyphMetrics.horiBearingX;
extents->y_bearing = glyphData.mGlyphMetrics.horiBearingY;
extents->width = glyphData.mGlyphMetrics.width;
int32_t newX = position.GetX();
int32_t newY = position.GetY();
- mWindowSurface->MoveResize(PositionSize(newX, newY, oldRect.width, oldRect.height));
+ mWindowSurface->Move(PositionSize(newX, newY, oldRect.width, oldRect.height));
if((oldRect.x != newX) || (oldRect.y != newY))
{
}
}
+void WindowRenderSurface::Move(Dali::PositionSize positionSize)
+{
+ mPositionSize.x = positionSize.x;
+ mPositionSize.y = positionSize.y;
+
+ DALI_LOG_RELEASE_INFO("Update Position by client (%d, %d)\n", positionSize.x, positionSize.y);
+
+ mWindowBase->Move(positionSize);
+}
+
void WindowRenderSurface::MoveResize(Dali::PositionSize positionSize)
{
mPositionSize.x = positionSize.x;
void UpdatePositionSize(Dali::PositionSize positionSize);
/**
+ * @brief Moves the window to the specified position.
+ *
+ * @param positionSize The new position of the window.
+ */
+ void Move(Dali::PositionSize positionSize);
+
+ /**
* @brief This signal is emitted when the output is transformed.
*/
OutputSignalType& OutputTransformedSignal();
--- /dev/null
+/*
+ * 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.
+ *
+ */
+
+// INTERNAL HEADERS
+#include <dali/internal/window-system/common/window-system.h>
+
+// EXTERNAL_HEADERS
+#include <cstdio>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace Adaptor
+{
+namespace WindowSystem
+{
+namespace
+{
+static uint32_t gDpiHorizontal = 0u;
+static uint32_t gDpiVertical = 0u;
+} // unnamed namespaces
+
+void SetDpi(uint32_t dpiHorizontal, uint32_t dpiVertical)
+{
+ gDpiHorizontal = dpiHorizontal;
+ gDpiVertical = dpiVertical;
+}
+
+void GetDpi(uint32_t& dpiHorizontal, uint32_t& dpiVertical)
+{
+ dpiHorizontal = gDpiHorizontal;
+ dpiVertical = gDpiVertical;
+}
+
+} // namespace WindowSystem
+
+} // namespace Adaptor
+
+} // namespace Internal
+
+} // namespace Dali
+
+#pragma GCC diagnostic pop
void Shutdown();
/**
+ * @brief Set the DPI of the target screen.
+ *
+ * @note Multiple screens are not currently supported.
+ * @param[in] horizontalDpi The horizontal resolution in DPI.
+ * @param[in] verticalDpi The vertical resolution in DPI.
+ */
+void SetDpi(uint32_t dpiHorizontal, uint32_t dpiVertical);
+
+/**
+ * @brief Retrieves the DPI previously set to the target screen.
+ *
+ * @note Multiple screens are not currently supported.
+ * @param[out] horizontalDpi The horizontal resolution in DPI.
+ * @param[out] verticalDpi The vertical resolution in DPI.
+ */
+void GetDpi(uint32_t& dpiHorizontal, uint32_t& dpiVertical);
+
+/**
* @brief Get the screen size
*/
void GetScreenSize(int32_t& width, int32_t& height);
SET( adaptor_window_system_common_src_files
${adaptor_window_system_dir}/common/display-connection.cpp
${adaptor_window_system_dir}/common/event-handler.cpp
+ ${adaptor_window_system_dir}/common/gl-window-impl.cpp
+ ${adaptor_window_system_dir}/common/gl-window-render-thread.cpp
${adaptor_window_system_dir}/common/native-render-surface-factory.cpp
${adaptor_window_system_dir}/common/orientation-impl.cpp
${adaptor_window_system_dir}/common/window-base.cpp
${adaptor_window_system_dir}/common/window-impl.cpp
${adaptor_window_system_dir}/common/window-render-surface.cpp
- ${adaptor_window_system_dir}/common/gl-window-impl.cpp
- ${adaptor_window_system_dir}/common/gl-window-render-thread.cpp
+ ${adaptor_window_system_dir}/common/window-system.cpp
)
# module: window-system, backend: tizen-wayland
{
const unsigned int ADAPTOR_MAJOR_VERSION = 2;
const unsigned int ADAPTOR_MINOR_VERSION = 2;
-const unsigned int ADAPTOR_MICRO_VERSION = 18;
+const unsigned int ADAPTOR_MICRO_VERSION = 19;
const char* const ADAPTOR_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
Name: dali2-adaptor
Summary: The DALi Tizen Adaptor
-Version: 2.2.18
+Version: 2.2.19
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-3-Clause and MIT