2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <dali/internal/text/text-abstraction/plugin/font-client-utils.h>
19 #include <dali/integration-api/debug.h>
20 #include <dali/internal/imaging/common/image-operations.h>
24 #if defined(DEBUG_ENABLED)
25 extern Dali::Integration::Log::Filter* gFontClientLogFilter;
28 namespace Dali::TextAbstraction::Internal
32 // http://www.freedesktop.org/software/fontconfig/fontconfig-user.html
34 // NONE -1 --> DEFAULT_FONT_WIDTH (NORMAL) will be used.
44 const int FONT_WIDTH_TYPE_TO_INT[] = {-1, 50, 63, 75, 87, 100, 113, 125, 150, 200};
45 const unsigned int NUM_FONT_WIDTH_TYPE = sizeof(FONT_WIDTH_TYPE_TO_INT) / sizeof(int);
47 // NONE -1 --> DEFAULT_FONT_WEIGHT (NORMAL) will be used.
49 // ULTRA_LIGHT, EXTRA_LIGHT 40
51 // DEMI_LIGHT, SEMI_LIGHT 55
55 // DEMI_BOLD, SEMI_BOLD 180
57 // ULTRA_BOLD, EXTRA_BOLD 205
58 // BLACK, HEAVY, EXTRA_BLACK 210
59 const int FONT_WEIGHT_TYPE_TO_INT[] = {-1, 0, 40, 50, 55, 75, 80, 100, 180, 200, 205, 210};
60 const unsigned int NUM_FONT_WEIGHT_TYPE = sizeof(FONT_WEIGHT_TYPE_TO_INT) / sizeof(int);
62 // NONE -1 --> DEFAULT_FONT_SLANT (NORMAL) will be used.
66 const int FONT_SLANT_TYPE_TO_INT[] = {-1, 0, 100, 110};
67 const unsigned int NUM_FONT_SLANT_TYPE = sizeof(FONT_SLANT_TYPE_TO_INT) / sizeof(int);
72 * @brief Returns the FontWidth's enum index for the given width value.
74 * @param[in] width The width value.
76 * @return The FontWidth's enum index.
78 const FontWidth::Type IntToWidthType(int width)
80 return static_cast<FontWidth::Type>(ValueToIndex(width, FONT_WIDTH_TYPE_TO_INT, NUM_FONT_WIDTH_TYPE - 1u));
84 * @brief Returns the FontWeight's enum index for the given weight value.
86 * @param[in] weight The weight value.
88 * @return The FontWeight's enum index.
90 const FontWeight::Type IntToWeightType(int weight)
92 return static_cast<FontWeight::Type>(ValueToIndex(weight, FONT_WEIGHT_TYPE_TO_INT, NUM_FONT_WEIGHT_TYPE - 1u));
96 * @brief Returns the FontSlant's enum index for the given slant value.
98 * @param[in] slant The slant value.
100 * @return The FontSlant's enum index.
102 const FontSlant::Type IntToSlantType(int slant)
104 return static_cast<FontSlant::Type>(ValueToIndex(slant, FONT_SLANT_TYPE_TO_INT, NUM_FONT_SLANT_TYPE - 1u));
107 const int DEFAULT_FONT_WIDTH(100);
108 const int DEFAULT_FONT_WEIGHT(80);
109 const int DEFAULT_FONT_SLANT(0);
111 const FontWidth::Type DefaultFontWidth()
113 return IntToWidthType(DEFAULT_FONT_WIDTH);
115 const FontWeight::Type DefaultFontWeight()
117 return IntToWeightType(DEFAULT_FONT_WEIGHT);
119 const FontSlant::Type DefaultFontSlant()
121 return IntToSlantType(DEFAULT_FONT_SLANT);
125 * @brief Copy the color bitmap given in @p srcBuffer to @p data.
127 * @param[out] data The bitmap data.
128 * @param[in] srcWidth The width of the bitmap.
129 * @param[in] srcHeight The height of the bitmap.
130 * @param[in] srcBuffer The buffer of the bitmap.
132 void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, unsigned int srcWidth, unsigned int srcHeight, const unsigned char* const srcBuffer)
134 // Set the input dimensions.
135 const ImageDimensions inputDimensions(srcWidth, srcHeight);
137 // Set the output dimensions.
138 // If the output dimension is not given, the input dimension is set
139 // and won't be downscaling.
140 data.width = (data.width == 0) ? srcWidth : data.width;
141 data.height = (data.height == 0) ? srcHeight : data.height;
142 const ImageDimensions desiredDimensions(data.width, data.height);
144 // Creates the output buffer
145 const unsigned int bufferSize = data.width * data.height * 4u;
146 data.buffer = (uint8_t*)malloc(bufferSize * sizeof(uint8_t)); // @note The caller is responsible for deallocating the bitmap data using free.
148 if(inputDimensions == desiredDimensions)
150 // There isn't downscaling.
151 memcpy(data.buffer, srcBuffer, bufferSize);
155 Dali::Internal::Platform::LanczosSample4BPP(srcBuffer,
164 * @brief Copy the FreeType bitmap to the given buffer.
166 * @param[out] data The bitmap data.
167 * @param[in,out] srcBitmap The FreeType bitmap.
168 * @param[in] isShearRequired Whether the bitmap needs a shear transform (for software italics).
169 * @param[in] moveBuffer Whether the bitmap buffer move. True if just copy buffer pointer. False if we use memcpy. (Default is false.)
170 * @note If you set moveBuffer=true, the bitmap's buffer moved frome srcBitmap to data. So srcBitmap buffer changed as nullptr.
172 void ConvertBitmap(TextAbstraction::FontClient::GlyphBufferData& data, FT_Bitmap& srcBitmap, bool isShearRequired, bool moveBuffer)
174 if(srcBitmap.width * srcBitmap.rows > 0)
176 switch(srcBitmap.pixel_mode)
178 case FT_PIXEL_MODE_GRAY:
180 if(srcBitmap.pitch == static_cast<int>(srcBitmap.width))
182 uint8_t* pixelsIn = srcBitmap.buffer;
183 unsigned int width = srcBitmap.width;
184 unsigned height = srcBitmap.rows;
186 uint8_t* releaseRequiredPixelPtr = nullptr;
191 * Glyphs' bitmaps with no slant retrieved from FreeType:
201 * Expected glyphs' bitmaps with italic slant:
202 * ____________ ______
209 * ------------ ------
211 * Glyphs' bitmaps with software italic slant retrieved from FreeType:
221 * This difference in some bitmaps' width causes an overlap of some glyphs. This is the reason why a shear operation is done here instead of relying on the experimental FT_GlyphSlot_Oblique() implementation.
223 unsigned int widthOut = 0u;
224 unsigned int heightOut = 0u;
225 uint8_t* pixelsOut = nullptr;
227 Dali::Internal::Platform::HorizontalShear(pixelsIn,
232 -TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE,
237 if(DALI_LIKELY(pixelsOut))
244 releaseRequiredPixelPtr = pixelsIn;
248 releaseRequiredPixelPtr = pixelsOut;
251 // Change input buffer ptr.
252 pixelsIn = pixelsOut;
256 DALI_LOG_ERROR("ERROR! software italic slant failed!\n");
261 data.height = height;
262 data.format = Pixel::L8; // Sets the pixel format.
266 data.buffer = pixelsIn;
268 // Happy trick for copyless convert bitmap!
269 srcBitmap.buffer = nullptr;
273 const unsigned int bufferSize = width * height;
274 data.buffer = (uint8_t*)malloc(bufferSize * sizeof(uint8_t)); // @note The caller is responsible for deallocating the bitmap data using free.
276 memcpy(data.buffer, pixelsIn, bufferSize);
279 if(releaseRequiredPixelPtr)
281 free(releaseRequiredPixelPtr);
287 #ifdef FREETYPE_BITMAP_SUPPORT
288 case FT_PIXEL_MODE_BGRA:
290 if(srcBitmap.pitch == static_cast<int>(srcBitmap.width << 2u))
292 // Color glyph doesn't support copyless convert bitmap. Just memcpy
293 ConvertBitmap(data, srcBitmap.width, srcBitmap.rows, srcBitmap.buffer);
295 // Sets the pixel format.
296 data.format = Pixel::BGRA8888;
303 DALI_LOG_INFO(gFontClientLogFilter, Debug::General, "FontClient::Plugin::ConvertBitmap. FontClient Unable to create Bitmap of this PixelType\n");
310 FcPattern* CreateFontFamilyPattern(const FontDescription& fontDescription)
312 // create the cached font family lookup pattern
313 // a pattern holds a set of names, each name refers to a property of the font
314 FcPattern* fontFamilyPattern = FcPatternCreate(); // FcPatternCreate creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
316 if(!fontFamilyPattern)
321 // add a property to the pattern for the font family
322 FcPatternAddString(fontFamilyPattern, FC_FAMILY, reinterpret_cast<const FcChar8*>(fontDescription.family.c_str()));
324 // add a property to the pattern for local setting.
325 const char* locale = setlocale(LC_MESSAGES, nullptr);
326 if(locale != nullptr)
328 FcPatternAddString(fontFamilyPattern, FC_LANG, reinterpret_cast<const FcChar8*>(locale));
331 int width = FONT_WIDTH_TYPE_TO_INT[fontDescription.width];
335 width = DEFAULT_FONT_WIDTH;
338 int weight = FONT_WEIGHT_TYPE_TO_INT[fontDescription.weight];
342 weight = DEFAULT_FONT_WEIGHT;
345 int slant = FONT_SLANT_TYPE_TO_INT[fontDescription.slant];
349 slant = DEFAULT_FONT_SLANT;
352 FcPatternAddInteger(fontFamilyPattern, FC_WIDTH, width);
353 FcPatternAddInteger(fontFamilyPattern, FC_WEIGHT, weight);
354 FcPatternAddInteger(fontFamilyPattern, FC_SLANT, slant);
356 // modify the config, with the mFontFamilyPatterm
357 FcConfigSubstitute(nullptr /* use default configure */, fontFamilyPattern, FcMatchPattern);
359 // provide default values for unspecified properties in the font pattern
360 // e.g. patterns without a specified style or weight are set to Medium
361 FcDefaultSubstitute(fontFamilyPattern);
363 return fontFamilyPattern;
366 FcCharSet* CreateCharacterSetFromDescription(const FontDescription& description)
368 FcCharSet* characterSet = nullptr;
370 FcPattern* pattern = CreateFontFamilyPattern(description); // Creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
372 if(nullptr != pattern)
374 FcResult result = FcResultMatch;
375 FcPattern* match = FcFontMatch(nullptr, pattern, &result); // FcFontMatch creates a new pattern that needs to be destroyed by calling FcPatternDestroy.
377 FcPatternGetCharSet(match, FC_CHARSET, 0u, &characterSet);
379 // Destroys the created patterns.
380 FcPatternDestroy(match);
381 FcPatternDestroy(pattern);
387 } // namespace Dali::TextAbstraction::Internal