2 * Copyright (c) 2014 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.
19 #include <dali/internal/event/text/font-impl.h>
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>
35 using Dali::Integration::PlatformAbstraction;
43 namespace // unnamed namespace
45 #if defined(DEBUG_ENABLED)
46 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_FONT");
49 const float INCH_TO_POINTS( 72.f );
50 const float POINT_TO_INCHES( 1.f / INCH_TO_POINTS );
52 const float MINIMUM_TEXT_SIZE = 1.0f; // Text will not be drawn if it's less than this size in pixels
54 } // unnamed namespace
56 const float Font::MIN_FONT_POINT_SIZE( 4.0f );
57 const float Font::MAX_FONT_POINT_SIZE( 128.0f );
59 Font* Font::New(const std::string& fontFamily, const std::string& fontStyle, float size)
61 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
63 FontFactory& fontFactory( tls.GetFontFactory() );
65 return new Font(fontFamily,
68 tls.GetPlatformAbstraction(),
69 tls.GetResourceClient(),
71 fontFactory.GetAtlasManagerInterface());
75 bool Font::operator==( const Font& font ) const
77 return ( font.GetResourceId() == GetResourceId() ) && ( fabsf( font.GetPointSize() - GetPointSize() ) < Math::MACHINE_EPSILON_1000 );
80 const std::string Font::GetFamilyForText(const Integration::TextArray& text)
82 Integration::PlatformAbstraction& platform = ThreadLocalStorage::Get().GetPlatformAbstraction();
83 // this is a synchronous request
84 return platform.GetFontFamilyForChars( text );
87 PixelSize Font::GetLineHeightFromCapsHeight(const std::string& fontFamily, const std::string& fontStyle, const CapsHeight& capsHeight)
89 std::string name,style;
90 bool isDefault( false );
92 Integration::PlatformAbstraction& platform = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
93 if (!platform.ValidateFontFamilyName(fontFamily, fontStyle, isDefault, name, style))
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());
99 return platform.GetFontLineHeightFromCapsHeight(name, style, capsHeight);
102 void Font::GetInstalledFonts( Dali::Font::FontListMode mode, std::vector<std::string>& fontList )
104 Integration::PlatformAbstraction& platform = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
106 Integration::PlatformAbstraction::FontListMode listMode ;
109 case Dali::Font::LIST_SYSTEM_FONTS:
111 listMode = Integration::PlatformAbstraction::LIST_SYSTEM_FONTS;
114 case Dali::Font::LIST_APPLICATION_FONTS:
116 listMode = Integration::PlatformAbstraction::LIST_APPLICATION_FONTS;
119 case Dali::Font::LIST_ALL_FONTS:
121 listMode = Integration::PlatformAbstraction::LIST_ALL_FONTS;
126 listMode = Integration::PlatformAbstraction::LIST_ALL_FONTS;
131 platform.GetFontList( listMode, fontList );
134 bool Font::AllGlyphsSupported(const Integration::TextArray& text) const
136 // this is a synchronous request
137 return mPlatform.AllGlyphsSupported(mName, mStyle, text);
140 unsigned int Font::GetResourceId() const
142 return mMetrics->GetFontId();
145 float Font::MeasureTextWidth(const Integration::TextArray& text, float textHeightPx) const
147 Vector3 size = MeasureText(text);
149 if( ( size.x < MINIMUM_TEXT_SIZE ) || ( size.y < MINIMUM_TEXT_SIZE ) || ( textHeightPx < MINIMUM_TEXT_SIZE ) )
154 float scale = textHeightPx / size.y;
155 float width = size.x * scale;
160 float Font::MeasureTextHeight(const Integration::TextArray& text, float textWidthPx) const
162 Vector3 size = MeasureText(text);
164 if (size.x < MINIMUM_TEXT_SIZE || size.y < MINIMUM_TEXT_SIZE || textWidthPx < MINIMUM_TEXT_SIZE)
169 float scale = textWidthPx / size.x;
170 float height = size.y * scale;
175 Vector3 Font::MeasureText(const Integration::TextArray& text) const
179 return mMetrics->MeasureText(text ) * GetUnitsToPixels();
183 DALI_LOG_WARNING("Font not initialized!\n");
184 return Vector3::ZERO;
188 bool Font::IsDefaultSystemFont() const
193 bool Font::IsDefaultSystemSize() const
195 return mIsDefaultSize;
198 const std::string& Font::GetName() const
203 const std::string& Font::GetStyle() const
208 float Font::GetPointSize() const
213 unsigned int Font::GetPixelSize() const
215 return PointsToPixels( mPointSize );
218 float Font::GetLineHeight() const
220 return (mMetrics) ? mMetrics->GetLineHeight() : 0.0f;
223 float Font::GetAscender() const
225 return (mMetrics) ? mMetrics->GetAscender() : 0.0f;
228 float Font::GetUnderlineThickness() const
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;
234 float Font::GetUnderlinePosition() const
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;
240 float Font::GetUnitsToPixels() const
242 return mMetrics->GetUnitsToPixels(mPointSize);
245 void Font::GetMetrics(const Dali::Character& character, Dali::Font::Metrics::Impl& metricsImpl) const
247 Integration::TextArray text;
248 text.PushBack( character.GetImplementation().GetCharacter() );
250 mMetrics->GetMetrics( character, metricsImpl );
252 const float unitsToPixel( GetUnitsToPixels() );
254 metricsImpl.advance *= unitsToPixel;
255 metricsImpl.bearing *= unitsToPixel;
256 metricsImpl.width *= unitsToPixel;
257 metricsImpl.height *= unitsToPixel;
260 unsigned int Font::PointsToPixels(float pointSize)
262 const Vector2& dpi = Dali::Stage::GetCurrent().GetDpi();
263 const float meanDpi = (dpi.height + dpi.width) / 2.0f;
265 return static_cast<unsigned int>((pointSize * meanDpi) * POINT_TO_INCHES + 0.5f);
268 float Font::PixelsToPoints(int pixelSize)
270 const Vector2& dpi = Dali::Stage::GetCurrent().GetDpi();
271 const float meanDpi = (dpi.height + dpi.width) / 2.0f;
273 return (pixelSize * INCH_TO_POINTS) / meanDpi;
276 void Font::ValidateFontRequest(std::string& fontFamily, std::string& fontStyle, float& fontPointSize, bool& fontFamilyDefault, bool& fontPointSizeDefault )
278 Internal::ThreadLocalStorage& tls = Internal::ThreadLocalStorage::Get();
279 Integration::PlatformAbstraction& platform = tls.GetPlatformAbstraction();
281 std::string requestedFamily = fontFamily;
282 std::string requestedStyle = fontStyle;
284 fontFamilyDefault = false;
286 if ( !platform.ValidateFontFamilyName( requestedFamily, requestedStyle, fontFamilyDefault, fontFamily, fontStyle ) )
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());
292 // check for zero size, and calculate the pixel size from point size and vice-versa
293 if( fontPointSize < GetRangedEpsilon( fontPointSize, 0.0f ) )
295 fontPointSize = platform.GetDefaultFontSize();
296 fontPointSizeDefault = true;
300 fontPointSizeDefault = false;
303 if( fontPointSize < MIN_FONT_POINT_SIZE )
305 DALI_LOG_ERROR("pointSize %.2f is less than min of %.2f\n", fontPointSize, MIN_FONT_POINT_SIZE);
306 fontPointSize = MIN_FONT_POINT_SIZE;
308 else if( fontPointSize > MAX_FONT_POINT_SIZE )
310 DALI_LOG_ERROR("pointSize %.2f is greater than max of %.2f\n", fontPointSize, MAX_FONT_POINT_SIZE);
311 fontPointSize = MAX_FONT_POINT_SIZE;
315 void Font::AddObserver(TextObserver& observer)
317 mAtlasManager.AddTextObserver(observer);
320 void Font::RemoveObserver(TextObserver& observer)
322 mAtlasManager.RemoveTextObserver(observer);
325 TextVertexBuffer* Font::TextRequired( const Integration::TextArray& text, const TextFormat& format)
327 // make sure the metrics are loaded for the text string, along with underline character if required
328 if( format.IsUnderLined() )
330 Integration::TextArray underline;
331 underline.PushBack( SpecialCharacters::UNDERLINE_CHARACTER );
333 mMetrics->LoadMetricsSynchronously( underline );
336 mMetrics->LoadMetricsSynchronously( text );
338 return mAtlasManager.TextRequired(text, format, *(mMetrics.Get()));
341 void Font::TextNotRequired( const Integration::TextArray& text, const TextFormat& format, unsigned int mTextureId )
343 // let the atlas manager we no longer need the text
344 mAtlasManager.TextNotRequired( text, format, mMetrics->GetFontId(), mTextureId );
347 void Font::AddTextureObserver(GlyphTextureObserver& observer )
349 mAtlasManager.AddTextureObserver( observer );
352 void Font::RemoveTextureObserver(GlyphTextureObserver& observer )
354 mAtlasManager.RemoveTextureObserver( observer );
357 bool Font::IsTextLoaded( const Integration::TextArray& text, const TextFormat& format, unsigned int textureId ) const
359 return mAtlasManager.IsTextLoaded( text, format, mMetrics->GetFontId(), textureId );
362 Font::Font(const std::string& fontFamily,
363 const std::string& fontStyle,
365 Integration::PlatformAbstraction& platform,
366 ResourceClient& resourceClient,
367 FontFactory& fontfactory,
368 GlyphAtlasManagerInterface& atlasInterface)
370 mIsDefaultSize(false),
375 mUnitsToPixels(1.0f),
377 mResourceClient(resourceClient),
378 mFontFactory(fontfactory),
379 mAtlasManager( atlasInterface )
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);
384 // get font metrics (cached global metrics will be available instantly)
385 mMetrics = mFontFactory.GetFontMetrics(mName, mStyle);
390 // Guard to allow handle destruction after Core has been destroyed
391 if ( Stage::IsInstalled() )
393 mFontFactory.RemoveFontMetrics(mName,mStyle);
397 } // namespace Internal