TextActor - New constructor with a parameter object replaces previous constructors.
[platform/core/uifw/dali-core.git] / dali / internal / event / text / font-impl.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/text/font-impl.h>
20
21 // INTERNAL HEADERS
22 #include <dali/public-api/common/stage.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/integration-api/glyph-set.h>
25 #include <dali/integration-api/platform-abstraction.h>
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/event/text/font-factory.h>
28 #include <dali/internal/event/text/font-metrics.h>
29 #include <dali/internal/event/text/utf8-impl.h>
30 #include <dali/internal/event/text/text-impl.h>
31 #include <dali/internal/event/text/character-impl.h>
32 #include <dali/internal/event/text/special-characters.h>
33 #include <dali/internal/event/common/thread-local-storage.h>
34
35 using Dali::Integration::PlatformAbstraction;
36
37 namespace Dali
38 {
39
40 namespace Internal
41 {
42
43 namespace // unnamed namespace
44 {
45 #if defined(DEBUG_ENABLED)
46 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FONT");
47 #endif
48
49 const float INCH_TO_POINTS( 72.f );
50 const float POINT_TO_INCHES( 1.f / INCH_TO_POINTS );
51
52 const char * const DALI_DEFAULT_FONT_CACHE_PATH( DALI_GLYPH_CACHE_DIR );
53
54 const float MINIMUM_TEXT_SIZE = 1.0f;     // Text will not be drawn if it's less than this size in pixels
55
56 } // unnamed namespace
57
58 const float    Font::MIN_FONT_POINT_SIZE( 4.0f );
59 const float    Font::MAX_FONT_POINT_SIZE( 128.0f );
60
61 Font* Font::New(const std::string& fontFamily, const std::string& fontStyle, float size)
62 {
63   ThreadLocalStorage& tls = ThreadLocalStorage::Get();
64
65   FontFactory& fontFactory( tls.GetFontFactory() );
66
67   return new Font(fontFamily,
68                   fontStyle,
69                   size,
70                   tls.GetPlatformAbstraction(),
71                   tls.GetResourceClient(),
72                   fontFactory,
73                   fontFactory.GetAtlasManagerInterface());
74
75 }
76
77 bool Font::operator==( const Font& font ) const
78 {
79   return ( font.GetResourceId() == GetResourceId() ) && ( fabsf( font.GetPointSize() - GetPointSize() ) < Math::MACHINE_EPSILON_1000 );
80 }
81
82 const std::string Font::GetFamilyForText(const TextArray& text)
83 {
84   Integration::PlatformAbstraction& platform = ThreadLocalStorage::Get().GetPlatformAbstraction();
85   // this is a synchronous request
86   return platform.GetFontFamilyForChars(text);
87 }
88
89 PixelSize Font::GetLineHeightFromCapsHeight(const std::string& fontFamily, const std::string& fontStyle, const CapsHeight& capsHeight)
90 {
91   std::string name,style;
92   bool isDefault( false );
93
94   Integration::PlatformAbstraction& platform = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
95   if (!platform.ValidateFontFamilyName(fontFamily, fontStyle, isDefault, name, style))
96   {
97     DALI_LOG_INFO( gLogFilter, Debug::General, "%s: requested font <%s:%s> not found. Using <%s:%s> for measurements\n",
98                    __PRETTY_FUNCTION__, fontFamily.c_str(), fontStyle.c_str(), name.c_str(), style.c_str());
99   }
100
101   return platform.GetFontLineHeightFromCapsHeight(name, style, capsHeight);
102 }
103
104 void Font::GetInstalledFonts( Dali::Font::FontListMode mode, std::vector<std::string>& fontList )
105 {
106   Integration::PlatformAbstraction& platform = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
107
108   Integration::PlatformAbstraction::FontListMode listMode ;
109   switch( mode )
110   {
111     case Dali::Font::LIST_SYSTEM_FONTS:
112     {
113       listMode = Integration::PlatformAbstraction::LIST_SYSTEM_FONTS;
114       break;
115     }
116     case Dali::Font::LIST_APPLICATION_FONTS:
117     {
118       listMode = Integration::PlatformAbstraction::LIST_APPLICATION_FONTS;
119       break;
120     }
121     case Dali::Font::LIST_ALL_FONTS:
122     {
123       listMode = Integration::PlatformAbstraction::LIST_ALL_FONTS;
124       break;
125     }
126     default:
127     {
128       listMode = Integration::PlatformAbstraction::LIST_ALL_FONTS;
129       break;
130     }
131   }
132
133   platform.GetFontList( listMode, fontList );
134 }
135
136 bool Font::AllGlyphsSupported(const TextArray& text) const
137 {
138   // this is a synchronous request
139   return mPlatform.AllGlyphsSupported(mName, mStyle, text);
140 }
141
142 unsigned int Font::GetResourceId() const
143 {
144   return mMetrics->GetFontId();
145 }
146
147 float Font::MeasureTextWidth(const TextArray& text, float textHeightPx) const
148 {
149   Vector3 size = MeasureText(text);
150
151   if( ( size.x < MINIMUM_TEXT_SIZE ) || ( size.y < MINIMUM_TEXT_SIZE ) || ( textHeightPx < MINIMUM_TEXT_SIZE ) )
152   {
153     return 0.0f;
154   }
155
156   float scale = textHeightPx / size.y;
157   float width = size.x * scale;
158
159   return width;
160 }
161
162 float Font::MeasureTextHeight(const TextArray& text, float textWidthPx) const
163 {
164   Vector3 size = MeasureText(text);
165
166   if (size.x < MINIMUM_TEXT_SIZE || size.y < MINIMUM_TEXT_SIZE || textWidthPx < MINIMUM_TEXT_SIZE)
167   {
168     return 0.0f;
169   }
170
171   float scale = textWidthPx / size.x;
172   float height = size.y * scale;
173
174   return height;
175 }
176
177 Vector3 Font::MeasureText(const TextArray& text) const
178 {
179   if (mMetrics)
180   {
181     return mMetrics->MeasureText(text ) * GetUnitsToPixels();
182   }
183   else
184   {
185     DALI_LOG_WARNING("Font not initialized!\n");
186     return Vector3::ZERO;
187   }
188 }
189
190 bool Font::IsDefaultSystemFont() const
191 {
192   return mIsDefault;
193 }
194
195 bool Font::IsDefaultSystemSize() const
196 {
197   return mIsDefaultSize;
198 }
199
200 const std::string& Font::GetName() const
201 {
202   return mName;
203 }
204
205 const std::string& Font::GetStyle() const
206 {
207   return mStyle;
208 }
209
210 float Font::GetPointSize() const
211 {
212   return mPointSize;
213 }
214
215 unsigned int Font::GetPixelSize() const
216 {
217   return PointsToPixels( mPointSize );
218 }
219
220 float Font::GetLineHeight() const
221 {
222   return (mMetrics) ? mMetrics->GetLineHeight() : 0.0f;
223 }
224
225 float Font::GetAscender() const
226 {
227   return (mMetrics) ? mMetrics->GetAscender() : 0.0f;
228 }
229
230 float Font::GetUnderlineThickness() const
231 {
232   // It adds the vertical pad adjust used to fit some effects like glow or shadow.
233   return (mMetrics) ? mMetrics->GetUnderlineThickness() + 2.f * mMetrics->GetPadAdjustY(): 0.f;
234 }
235
236 float Font::GetUnderlinePosition() const
237 {
238   // It adds the vertical pad adjust used to fit some effects like glow or shadow.
239   return (mMetrics) ? mMetrics->GetAscender() - mMetrics->GetUnderlinePosition() + mMetrics->GetPadAdjustY() : 0.f;
240 }
241
242 float Font::GetUnitsToPixels() const
243 {
244   return mMetrics->GetUnitsToPixels(mPointSize);
245 }
246
247 void Font::GetMetrics(const Dali::Character& character, Dali::Font::Metrics::Impl& metricsImpl) const
248 {
249   TextArray text;
250   text.push_back( character.GetImplementation().GetCharacter() );
251
252   mMetrics->GetMetrics( character, metricsImpl );
253
254   const float unitsToPixel( GetUnitsToPixels() );
255
256   metricsImpl.advance *= unitsToPixel;
257   metricsImpl.bearing *= unitsToPixel;
258   metricsImpl.width *= unitsToPixel;
259   metricsImpl.height *= unitsToPixel;
260 }
261
262 unsigned int Font::PointsToPixels(float pointSize)
263 {
264   const Vector2& dpi = Dali::Stage::GetCurrent().GetDpi();
265   const float meanDpi = (dpi.height + dpi.width) / 2.0f;
266
267   return static_cast<unsigned int>((pointSize * meanDpi) * POINT_TO_INCHES + 0.5f);
268 }
269
270 float Font::PixelsToPoints(int pixelSize)
271 {
272   const Vector2& dpi = Dali::Stage::GetCurrent().GetDpi();
273   const float meanDpi = (dpi.height + dpi.width) / 2.0f;
274
275   return (pixelSize * INCH_TO_POINTS) / meanDpi;
276 }
277
278 void Font::ValidateFontRequest(std::string& fontFamily, std::string& fontStyle, float& fontPointSize, bool& fontFamilyDefault, bool& fontPointSizeDefault )
279 {
280   Internal::ThreadLocalStorage& tls = Internal::ThreadLocalStorage::Get();
281   Integration::PlatformAbstraction& platform = tls.GetPlatformAbstraction();
282
283   std::string requestedFamily = fontFamily;
284   std::string requestedStyle = fontStyle;
285
286   fontFamilyDefault = false;
287
288   if ( !platform.ValidateFontFamilyName( requestedFamily, requestedStyle, fontFamilyDefault, fontFamily, fontStyle ) )
289   {
290     DALI_LOG_INFO( gLogFilter, Debug::General, "%s: requested font <%s:%s> not found. Using <%s:%s>\n",
291                    __PRETTY_FUNCTION__, requestedFamily.c_str(), requestedStyle.c_str(), fontFamily.c_str(), fontStyle.c_str());
292   }
293
294   // check for zero size, and calculate the pixel size from point size and vice-versa
295   if( fontPointSize < GetRangedEpsilon( fontPointSize, 0.0f ) )
296   {
297     fontPointSize = platform.GetDefaultFontSize();
298     fontPointSizeDefault = true;
299   }
300   else
301   {
302     fontPointSizeDefault = false;
303   }
304
305   if( fontPointSize < MIN_FONT_POINT_SIZE )
306   {
307     DALI_LOG_ERROR("pointSize %.2f is less than min of %.2f\n", fontPointSize, MIN_FONT_POINT_SIZE);
308     fontPointSize = MIN_FONT_POINT_SIZE;
309   }
310   else if( fontPointSize > MAX_FONT_POINT_SIZE )
311   {
312     DALI_LOG_ERROR("pointSize %.2f is greater than max of %.2f\n", fontPointSize, MAX_FONT_POINT_SIZE);
313     fontPointSize = MAX_FONT_POINT_SIZE;
314   }
315 }
316
317 void Font::AddObserver(TextObserver& observer)
318 {
319   mAtlasManager.AddTextObserver(observer);
320 }
321
322 void Font::RemoveObserver(TextObserver& observer)
323 {
324   mAtlasManager.RemoveTextObserver(observer);
325 }
326
327 TextVertexBuffer* Font::TextRequired( const TextArray& text, const TextFormat& format)
328 {
329   // make sure the metrics are loaded for the text string, along with underline character if required
330   if( format.IsUnderLined() )
331   {
332     TextArray underline;
333     underline.push_back( SpecialCharacters::UNDERLINE_CHARACTER );
334
335     mMetrics->LoadMetricsSynchronously( underline );
336   }
337
338   mMetrics->LoadMetricsSynchronously( text );
339
340
341   return mAtlasManager.TextRequired(text, format, *(mMetrics.Get()));
342 }
343
344 void Font::TextNotRequired( const TextArray& text, const TextFormat& format, unsigned int mTextureId )
345 {
346   // let the atlas manager we no longer need the text
347   mAtlasManager.TextNotRequired( text, format, mMetrics->GetFontId(), mTextureId );
348 };
349
350 void Font::AddTextureObserver(GlyphTextureObserver& observer )
351 {
352   mAtlasManager.AddTextureObserver( observer );
353 }
354
355 void Font::RemoveTextureObserver(GlyphTextureObserver& observer )
356 {
357   mAtlasManager.RemoveTextureObserver( observer );
358 }
359
360 bool Font::IsTextLoaded( const TextArray& text, const TextFormat& format, unsigned int textureId ) const
361 {
362   return mAtlasManager.IsTextLoaded( text, format, mMetrics->GetFontId(), textureId );
363 }
364
365 Font::Font(const std::string& fontFamily,
366            const std::string& fontStyle,
367            float size,
368            Integration::PlatformAbstraction& platform,
369            ResourceClient& resourceClient,
370            FontFactory& fontfactory,
371            GlyphAtlasManagerInterface& atlasInterface)
372 :  mIsDefault(false),
373    mIsDefaultSize(false),
374    mName(fontFamily),
375    mStyle(fontStyle),
376    mMetrics(NULL),
377    mPointSize(size),
378    mUnitsToPixels(1.0f),
379    mPlatform(platform),
380    mResourceClient(resourceClient),
381    mFontFactory(fontfactory),
382    mAtlasManager( atlasInterface )
383 {
384   // Validates the font name, style, and point size (determines if point size is default i.e 0.0pt)
385   ValidateFontRequest(mName, mStyle, mPointSize, mIsDefault, mIsDefaultSize);
386
387   // get font metrics (cached global metrics will be available instantly)
388   mMetrics = mFontFactory.GetFontMetrics(mName, mStyle);
389 }
390
391 Font::~Font()
392 {
393   // Guard to allow handle destruction after Core has been destroyed
394   if ( Stage::IsInstalled() )
395   {
396     mFontFactory.RemoveFontMetrics(mName,mStyle);
397   }
398 }
399
400 } // namespace Internal
401
402 } // namespace Dali