01c62c7fff31e6ebcaa4e023f743e5530fcac6a2
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / glyph-metrics-helper.cpp
1
2 /*
3  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 // FILE HEADER
20 #include <dali-toolkit/internal/text/glyph-metrics-helper.h>
21
22 namespace Dali
23 {
24 namespace Toolkit
25 {
26 namespace Text
27 {
28 Length GetNumberOfGlyphsOfGroup(GlyphIndex          glyphIndex,
29                                 GlyphIndex          lastGlyphPlusOne,
30                                 const Length* const charactersPerGlyphBuffer)
31 {
32   Length numberOfGLyphsInGroup = 1u;
33
34   for(GlyphIndex index = glyphIndex; index < lastGlyphPlusOne; ++index)
35   {
36     if(0u == *(charactersPerGlyphBuffer + index))
37     {
38       ++numberOfGLyphsInGroup;
39     }
40     else
41     {
42       break;
43     }
44   }
45
46   return numberOfGLyphsInGroup;
47 }
48
49 void GetGlyphsMetrics(GlyphIndex             glyphIndex,
50                       Length                 numberOfGlyphs,
51                       GlyphMetrics&          glyphMetrics,
52                       const GlyphInfo* const glyphsBuffer,
53                       MetricsPtr&            metrics,
54                       float                  calculatedAdvance)
55 {
56   const GlyphInfo& firstGlyph = *(glyphsBuffer + glyphIndex);
57
58   Text::FontMetrics fontMetrics;
59   if(0u != firstGlyph.fontId)
60   {
61     metrics->GetFontMetrics(firstGlyph.fontId, fontMetrics);
62   }
63   else if(0u != firstGlyph.index)
64   {
65     // It may be an embedded image.
66     fontMetrics.ascender  = firstGlyph.height;
67     fontMetrics.descender = 0.f;
68     fontMetrics.height    = fontMetrics.ascender;
69   }
70
71   const bool isItalicFont = metrics->HasItalicStyle(firstGlyph.fontId);
72
73   glyphMetrics.fontId     = firstGlyph.fontId;
74   glyphMetrics.fontHeight = fontMetrics.height;
75   glyphMetrics.width      = firstGlyph.width;
76   glyphMetrics.advance    = calculatedAdvance;
77   glyphMetrics.ascender   = fontMetrics.ascender;
78   glyphMetrics.xBearing   = firstGlyph.xBearing;
79
80   if(1u < numberOfGlyphs)
81   {
82     float maxWidthEdge = firstGlyph.xBearing + firstGlyph.width;
83
84     for(unsigned int i = 1u; i < numberOfGlyphs; ++i)
85     {
86       const GlyphInfo& glyphInfo = *(glyphsBuffer + glyphIndex + i);
87
88       // update the initial xBearing if smaller.
89       glyphMetrics.xBearing = std::min(glyphMetrics.xBearing, glyphMetrics.advance + glyphInfo.xBearing);
90
91       // update the max width edge if bigger.
92       const float currentMaxGlyphWidthEdge = glyphMetrics.advance + glyphInfo.xBearing + glyphInfo.width;
93       maxWidthEdge                         = std::max(maxWidthEdge, currentMaxGlyphWidthEdge);
94
95       glyphMetrics.advance += (glyphInfo.advance);
96     }
97
98     glyphMetrics.width = maxWidthEdge - glyphMetrics.xBearing;
99   }
100
101   glyphMetrics.width += (firstGlyph.isItalicRequired && !isItalicFont) ? TextAbstraction::FontClient::DEFAULT_ITALIC_ANGLE * firstGlyph.height : 0.f;
102 }
103
104 void GetGlyphMetricsFromCharacterIndex(CharacterIndex         index,
105                                        const VisualModelPtr&  visualModel,
106                                        const LogicalModelPtr& logicalModel,
107                                        MetricsPtr&            metrics,
108                                        GlyphMetrics&          glyphMetrics,
109                                        GlyphIndex&            glyphIndex,
110                                        Length&                numberOfGlyphs)
111 {
112   const GlyphIndex* const charactersToGlyphBuffer   = visualModel->mCharactersToGlyph.Begin();
113   const Length* const     glyphsPerCharacterBuffer  = visualModel->mGlyphsPerCharacter.Begin();
114   const GlyphInfo* const  glyphInfoBuffer           = visualModel->mGlyphs.Begin();
115   Vector<CharacterIndex>& glyphToCharacterMap       = visualModel->mGlyphsToCharacters;
116   const CharacterIndex*   glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
117   const float             characterSpacing          = visualModel->GetCharacterSpacing();
118
119   //Takes the character index, obtains the glyph index (and the number of Glyphs) from it and finally gets the glyph metrics.
120   glyphIndex     = *(charactersToGlyphBuffer + index);
121   numberOfGlyphs = *(glyphsPerCharacterBuffer + index);
122
123   float calculatedAdvance = 0.f;
124
125   calculatedAdvance = GetCalculatedAdvance(*(logicalModel->mText.Begin() + (*(glyphToCharacterMapBuffer + glyphIndex))), characterSpacing, (*(visualModel->mGlyphs.Begin() + glyphIndex)).advance);
126
127   // Get the metrics for the group of glyphs.
128   GetGlyphsMetrics(glyphIndex,
129                    numberOfGlyphs,
130                    glyphMetrics,
131                    glyphInfoBuffer,
132                    metrics,
133                    calculatedAdvance);
134 }
135
136 float GetCalculatedAdvance(unsigned int character, float characterSpacing, float advance)
137 {
138   //Gets the final advance value by adding the CharacterSpacing value to it
139   //In some cases the CharacterSpacing should not be added. Ex: when the glyph is a ZWSP (Zero Width Space)
140   return (TextAbstraction::IsZeroWidthNonJoiner(character) || TextAbstraction::IsZeroWidthJoiner(character) ||
141           TextAbstraction::IsZeroWidthSpace(character) || TextAbstraction::IsNewParagraph(character) ||
142           TextAbstraction::IsLeftToRightMark(character) || TextAbstraction::IsRightToLeftMark(character))
143            ? advance
144            : advance + characterSpacing;
145 }
146
147 } // namespace Text
148
149 } // namespace Toolkit
150
151 } // namespace Dali