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