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 char * const DALI_DEFAULT_FONT_CACHE_PATH( DALI_GLYPH_CACHE_DIR );
54 const float MINIMUM_TEXT_SIZE = 1.0f; // Text will not be drawn if it's less than this size in pixels
56 } // unnamed namespace
58 const float Font::MIN_FONT_POINT_SIZE( 4.0f );
59 const float Font::MAX_FONT_POINT_SIZE( 128.0f );
61 Font* Font::New(const std::string& fontFamily, const std::string& fontStyle, float size)
63 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
65 FontFactory& fontFactory( tls.GetFontFactory() );
67 return new Font(fontFamily,
70 tls.GetPlatformAbstraction(),
71 tls.GetResourceClient(),
73 fontFactory.GetAtlasManagerInterface());
77 bool Font::operator==( const Font& font ) const
79 return ( font.GetResourceId() == GetResourceId() ) && ( fabsf( font.GetPointSize() - GetPointSize() ) < Math::MACHINE_EPSILON_1000 );
82 const std::string Font::GetFamilyForText(const TextArray& text)
84 Integration::PlatformAbstraction& platform = ThreadLocalStorage::Get().GetPlatformAbstraction();
85 // this is a synchronous request
86 return platform.GetFontFamilyForChars(text);
89 PixelSize Font::GetLineHeightFromCapsHeight(const std::string& fontFamily, const std::string& fontStyle, const CapsHeight& capsHeight)
91 std::string name,style;
92 bool isDefault( false );
94 Integration::PlatformAbstraction& platform = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
95 if (!platform.ValidateFontFamilyName(fontFamily, fontStyle, isDefault, name, style))
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());
101 return platform.GetFontLineHeightFromCapsHeight(name, style, capsHeight);
104 void Font::GetInstalledFonts( Dali::Font::FontListMode mode, std::vector<std::string>& fontList )
106 Integration::PlatformAbstraction& platform = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
108 Integration::PlatformAbstraction::FontListMode listMode ;
111 case Dali::Font::LIST_SYSTEM_FONTS:
113 listMode = Integration::PlatformAbstraction::LIST_SYSTEM_FONTS;
116 case Dali::Font::LIST_APPLICATION_FONTS:
118 listMode = Integration::PlatformAbstraction::LIST_APPLICATION_FONTS;
121 case Dali::Font::LIST_ALL_FONTS:
123 listMode = Integration::PlatformAbstraction::LIST_ALL_FONTS;
128 listMode = Integration::PlatformAbstraction::LIST_ALL_FONTS;
133 platform.GetFontList( listMode, fontList );
136 bool Font::AllGlyphsSupported(const TextArray& text) const
138 // this is a synchronous request
139 return mPlatform.AllGlyphsSupported(mName, mStyle, text);
142 unsigned int Font::GetResourceId() const
144 return mMetrics->GetFontId();
147 float Font::MeasureTextWidth(const TextArray& text, float textHeightPx) const
149 Vector3 size = MeasureText(text);
151 if( ( size.x < MINIMUM_TEXT_SIZE ) || ( size.y < MINIMUM_TEXT_SIZE ) || ( textHeightPx < MINIMUM_TEXT_SIZE ) )
156 float scale = textHeightPx / size.y;
157 float width = size.x * scale;
162 float Font::MeasureTextHeight(const TextArray& text, float textWidthPx) const
164 Vector3 size = MeasureText(text);
166 if (size.x < MINIMUM_TEXT_SIZE || size.y < MINIMUM_TEXT_SIZE || textWidthPx < MINIMUM_TEXT_SIZE)
171 float scale = textWidthPx / size.x;
172 float height = size.y * scale;
177 Vector3 Font::MeasureText(const TextArray& text) const
181 return mMetrics->MeasureText(text ) * GetUnitsToPixels();
185 DALI_LOG_WARNING("Font not initialized!\n");
186 return Vector3::ZERO;
190 bool Font::IsDefaultSystemFont() const
195 bool Font::IsDefaultSystemSize() const
197 return mIsDefaultSize;
200 const std::string& Font::GetName() const
205 const std::string& Font::GetStyle() const
210 float Font::GetPointSize() const
215 unsigned int Font::GetPixelSize() const
217 return PointsToPixels( mPointSize );
220 float Font::GetLineHeight() const
222 return (mMetrics) ? mMetrics->GetLineHeight() : 0.0f;
225 float Font::GetAscender() const
227 return (mMetrics) ? mMetrics->GetAscender() : 0.0f;
230 float Font::GetUnderlineThickness() const
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;
236 float Font::GetUnderlinePosition() const
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;
242 float Font::GetUnitsToPixels() const
244 return mMetrics->GetUnitsToPixels(mPointSize);
247 void Font::GetMetrics(const Dali::Character& character, Dali::Font::Metrics::Impl& metricsImpl) const
250 text.push_back( character.GetImplementation().GetCharacter() );
252 mMetrics->GetMetrics( character, metricsImpl );
254 const float unitsToPixel( GetUnitsToPixels() );
256 metricsImpl.advance *= unitsToPixel;
257 metricsImpl.bearing *= unitsToPixel;
258 metricsImpl.width *= unitsToPixel;
259 metricsImpl.height *= unitsToPixel;
262 unsigned int Font::PointsToPixels(float pointSize)
264 const Vector2& dpi = Dali::Stage::GetCurrent().GetDpi();
265 const float meanDpi = (dpi.height + dpi.width) / 2.0f;
267 return static_cast<unsigned int>((pointSize * meanDpi) * POINT_TO_INCHES + 0.5f);
270 float Font::PixelsToPoints(int pixelSize)
272 const Vector2& dpi = Dali::Stage::GetCurrent().GetDpi();
273 const float meanDpi = (dpi.height + dpi.width) / 2.0f;
275 return (pixelSize * INCH_TO_POINTS) / meanDpi;
278 void Font::ValidateFontRequest(std::string& fontFamily, std::string& fontStyle, float& fontPointSize, bool& fontFamilyDefault, bool& fontPointSizeDefault )
280 Internal::ThreadLocalStorage& tls = Internal::ThreadLocalStorage::Get();
281 Integration::PlatformAbstraction& platform = tls.GetPlatformAbstraction();
283 std::string requestedFamily = fontFamily;
284 std::string requestedStyle = fontStyle;
286 fontFamilyDefault = false;
288 if ( !platform.ValidateFontFamilyName( requestedFamily, requestedStyle, fontFamilyDefault, fontFamily, fontStyle ) )
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());
294 // check for zero size, and calculate the pixel size from point size and vice-versa
295 if( fontPointSize < GetRangedEpsilon( fontPointSize, 0.0f ) )
297 fontPointSize = platform.GetDefaultFontSize();
298 fontPointSizeDefault = true;
302 fontPointSizeDefault = false;
305 if( fontPointSize < MIN_FONT_POINT_SIZE )
307 DALI_LOG_ERROR("pointSize %.2f is less than min of %.2f\n", fontPointSize, MIN_FONT_POINT_SIZE);
308 fontPointSize = MIN_FONT_POINT_SIZE;
310 else if( fontPointSize > MAX_FONT_POINT_SIZE )
312 DALI_LOG_ERROR("pointSize %.2f is greater than max of %.2f\n", fontPointSize, MAX_FONT_POINT_SIZE);
313 fontPointSize = MAX_FONT_POINT_SIZE;
317 void Font::AddObserver(TextObserver& observer)
319 mAtlasManager.AddTextObserver(observer);
322 void Font::RemoveObserver(TextObserver& observer)
324 mAtlasManager.RemoveTextObserver(observer);
327 TextVertexBuffer* Font::TextRequired( const TextArray& text, const TextFormat& format)
329 // make sure the metrics are loaded for the text string, along with underline character if required
330 if( format.IsUnderLined() )
333 underline.push_back( SpecialCharacters::UNDERLINE_CHARACTER );
335 mMetrics->LoadMetricsSynchronously( underline );
338 mMetrics->LoadMetricsSynchronously( text );
341 return mAtlasManager.TextRequired(text, format, *(mMetrics.Get()));
344 void Font::TextNotRequired( const TextArray& text, const TextFormat& format, unsigned int mTextureId )
346 // let the atlas manager we no longer need the text
347 mAtlasManager.TextNotRequired( text, format, mMetrics->GetFontId(), mTextureId );
350 void Font::AddTextureObserver(GlyphTextureObserver& observer )
352 mAtlasManager.AddTextureObserver( observer );
355 void Font::RemoveTextureObserver(GlyphTextureObserver& observer )
357 mAtlasManager.RemoveTextureObserver( observer );
360 bool Font::IsTextLoaded( const TextArray& text, const TextFormat& format, unsigned int textureId ) const
362 return mAtlasManager.IsTextLoaded( text, format, mMetrics->GetFontId(), textureId );
365 Font::Font(const std::string& fontFamily,
366 const std::string& fontStyle,
368 Integration::PlatformAbstraction& platform,
369 ResourceClient& resourceClient,
370 FontFactory& fontfactory,
371 GlyphAtlasManagerInterface& atlasInterface)
373 mIsDefaultSize(false),
378 mUnitsToPixels(1.0f),
380 mResourceClient(resourceClient),
381 mFontFactory(fontfactory),
382 mAtlasManager( atlasInterface )
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);
387 // get font metrics (cached global metrics will be available instantly)
388 mMetrics = mFontFactory.GetFontMetrics(mName, mStyle);
393 // Guard to allow handle destruction after Core has been destroyed
394 if ( Stage::IsInstalled() )
396 mFontFactory.RemoveFontMetrics(mName,mStyle);
400 } // namespace Internal