Previously, font-face-glyph-cache-manager release GlyphCacheData by manager side.
Now, let we keep cache data by shared_ptr<GlyphCacheData>, and also get pointer,
not whole copy of data.
After this patch, we don't need to worry about glyph cache data's lifecycle.
Change-Id: Iceb58d78085f0415b679434cd5066ea93ab2859a
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
/*
- * 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);
void FontFaceCacheItem::CreateBitmap(
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;
/*
- * 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::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::GlyphBufferData& renderBuffer = *destinationGlpyhData.mRenderedBuffer;
+ TextAbstraction::GlyphBufferData& renderBuffer = *glyphData.mRenderedBuffer;
// Set basic informations.
renderBuffer.width = srcBitmap.width;
{
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;
{
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.
#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
{
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;