/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2024 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.
#if defined(DEBUG_ENABLED)
extern Dali::Integration::Log::Filter* gFontClientLogFilter;
+
+#define FONT_LOG_DESCRIPTION(fontDescription, prefix) \
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, #prefix " description; family : [%s]\n", fontDescription.family.c_str()); \
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::Verbose, \
+ " path : [%s]\n" \
+ " width : [%s]\n" \
+ " weight : [%s]\n" \
+ " slant : [%s]\n\n", \
+ fontDescription.path.c_str(), \
+ FontWidth::Name[fontDescription.width], \
+ FontWeight::Name[fontDescription.weight], \
+ FontSlant::Name[fontDescription.slant])
+
+#define FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor) \
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, \
+ " character : %p\n" \
+ " requestedPointSize : %d\n" \
+ " preferColor : %s\n", \
+ charcode, \
+ requestedPointSize, \
+ (preferColor ? "true" : "false"))
+
+#else
+
+#define FONT_LOG_DESCRIPTION(fontDescription, prefix)
+#define FONT_LOG_REQUEST(charcode, requestedPointSize, preferColor)
+
#endif
namespace Dali::TextAbstraction::Internal
return static_cast<FontSlant::Type>(ValueToIndex(slant, FONT_SLANT_TYPE_TO_INT, NUM_FONT_SLANT_TYPE - 1u));
}
-const int DEFAULT_FONT_WIDTH(100);
-const int DEFAULT_FONT_WEIGHT(80);
-const int DEFAULT_FONT_SLANT(0);
+const char* DEFAULT_FONT_FAMILY_NAME("Tizen");
+const int DEFAULT_FONT_WIDTH(100);
+const int DEFAULT_FONT_WEIGHT(80);
+const int DEFAULT_FONT_SLANT(0);
+const std::string_view DefaultFontFamily()
+{
+ return DEFAULT_FONT_FAMILY_NAME;
+}
const FontWidth::Type DefaultFontWidth()
{
return IntToWidthType(DEFAULT_FONT_WIDTH);
* @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)
+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.height = (data.height == 0) ? srcHeight : data.height;
const ImageDimensions desiredDimensions(data.width, data.height);
+ data.format = srcFormat;
+
+ // Note we don't compress here
+ data.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
+
+ const uint32_t bytePerPixel = Dali::Pixel::GetBytesPerPixel(srcFormat);
+
// Creates the output buffer
- const unsigned int bufferSize = data.width * data.height * 4u;
- data.buffer = (uint8_t*)malloc(bufferSize * sizeof(uint8_t)); // @note The caller is responsible for deallocating the bitmap data using free.
+ const uint32_t bufferSize = data.width * data.height * bytePerPixel;
if(inputDimensions == desiredDimensions)
{
// There isn't downscaling.
- memcpy(data.buffer, srcBuffer, bufferSize);
+ data.isBufferOwned = false;
+ data.buffer = const_cast<uint8_t*>(srcBuffer);
}
else
{
- Dali::Internal::Platform::LanczosSample4BPP(srcBuffer,
- inputDimensions,
- srcWidth,
- data.buffer,
- desiredDimensions);
+ data.isBufferOwned = true;
+ data.buffer = (uint8_t*)malloc(bufferSize); // @note The caller is responsible for deallocating the bitmap data using free.
+
+ if(DALI_UNLIKELY(!data.buffer))
+ {
+ DALI_LOG_ERROR("malloc is failed. request malloc size : %u\n", bufferSize);
+ return;
+ }
+ Dali::Internal::Platform::LanczosSample(srcBuffer,
+ inputDimensions,
+ srcWidth,
+ srcFormat,
+ data.buffer,
+ desiredDimensions);
}
}
* @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)
{
switch(srcBitmap.pixel_mode)
data.height = height;
data.format = Pixel::L8; // Sets the pixel format.
+ // Note we don't compress here
+ data.compressionType = TextAbstraction::GlyphBufferData::CompressionType::NO_COMPRESSION;
+
if(moveBuffer)
{
- data.buffer = pixelsIn;
+ data.isBufferOwned = true;
+ data.buffer = pixelsIn;
// Happy trick for copyless convert bitmap!
srcBitmap.buffer = nullptr;
}
else
{
- const unsigned int bufferSize = width * height;
- data.buffer = (uint8_t*)malloc(bufferSize * sizeof(uint8_t)); // @note The caller is responsible for deallocating the bitmap data using free.
-
- memcpy(data.buffer, pixelsIn, bufferSize);
+ data.isBufferOwned = false;
+ data.buffer = pixelsIn;
}
if(releaseRequiredPixelPtr)
if(srcBitmap.pitch == static_cast<int>(srcBitmap.width << 2u))
{
// Color glyph doesn't support copyless convert bitmap. Just memcpy
- ConvertBitmap(data, srcBitmap.width, srcBitmap.rows, srcBitmap.buffer);
-
- // Sets the pixel format.
- data.format = Pixel::BGRA8888;
+ ConvertBitmap(data, srcBitmap.width, srcBitmap.rows, srcBitmap.buffer, Pixel::BGRA8888);
}
break;
}
return characterSet;
}
+bool MatchFontDescriptionToPattern(FcPattern* pattern, Dali::TextAbstraction::FontDescription& fontDescription, FcCharSet** characterSet)
+{
+ DALI_LOG_TRACE_METHOD(gFontClientLogFilter);
+
+ FcResult result = FcResultMatch;
+ FcPattern* match = FcFontMatch(nullptr /* use default configure */, pattern, &result); // Creates a new font pattern that needs to be destroyed by calling FcPatternDestroy.
+
+ const bool matched = nullptr != match;
+ DALI_LOG_INFO(gFontClientLogFilter, Debug::General, " pattern matched : %s\n", (matched ? "true" : "false"));
+
+ if(matched)
+ {
+ int width = 0;
+ int weight = 0;
+ int slant = 0;
+ GetFcString(match, FC_FILE, fontDescription.path);
+ GetFcString(match, FC_FAMILY, fontDescription.family);
+ GetFcInt(match, FC_WIDTH, width);
+ GetFcInt(match, FC_WEIGHT, weight);
+ GetFcInt(match, FC_SLANT, slant);
+ fontDescription.width = IntToWidthType(width);
+ fontDescription.weight = IntToWeightType(weight);
+ fontDescription.slant = IntToSlantType(slant);
+
+ // Retrieve the character set and increase the reference counter.
+ FcPatternGetCharSet(match, FC_CHARSET, 0u, characterSet);
+ *characterSet = FcCharSetCopy(*characterSet);
+
+ // destroyed the matched pattern
+ FcPatternDestroy(match);
+ FONT_LOG_DESCRIPTION(fontDescription, "");
+ }
+ return matched;
+}
+
+bool GetFcString(const FcPattern* const pattern, const char* const n, std::string& string)
+{
+ FcChar8* file = nullptr;
+ const FcResult retVal = FcPatternGetString(pattern, n, 0u, &file);
+
+ if(FcResultMatch == retVal)
+ {
+ // Have to use reinterpret_cast because FcChar8 is unsigned char*, not a const char*.
+ string.assign(reinterpret_cast<const char*>(file));
+
+ return true;
+ }
+
+ return false;
+}
+
+bool GetFcInt(const _FcPattern* const pattern, const char* const n, int& intVal)
+{
+ const FcResult retVal = FcPatternGetInteger(pattern, n, 0u, &intVal);
+
+ if(FcResultMatch == retVal)
+ {
+ return true;
+ }
+
+ return false;
+}
+
} // namespace Dali::TextAbstraction::Internal