| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKFONTMGR_COBALT_H_ |
| #define COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKFONTMGR_COBALT_H_ |
| |
| #include <bitset> |
| #include <limits> |
| #include <string> |
| #include <utility> |
| |
| #include "base/hash_tables.h" |
| #include "cobalt/base/poller.h" |
| #include "cobalt/renderer/rasterizer/skia/skia/src/ports/SkFontUtil_cobalt.h" |
| #include "SkFontHost.h" |
| #include "SkFontDescriptor.h" |
| #include "SkFontMgr.h" |
| #include "SkThread.h" |
| #include "SkTypefaceCache.h" |
| |
| class SkFontMgr_Cobalt; |
| class SkTypeface_CobaltSystem; |
| |
| // This class is used by SkFontMgr_Cobalt to hold SkTypeface_Cobalt families. |
| // |
| // To avoid the memory hit from keeping all fonts around, both the full |
| // character map for fonts and the font faces for fonts are lazily loaded |
| // when needed. After this, they are retained in memory. |
| // |
| // The style sets contain an array of page ranges, providing information on |
| // characters that are potentially contained. To determine whether or not a |
| // character is actually contained, the full character map is generated. |
| class SkFontStyleSet_Cobalt : public SkFontStyleSet { |
| public: |
| struct SkFontStyleSetEntry_Cobalt : public SkRefCnt { |
| SkFontStyleSetEntry_Cobalt(const SkString& file_path, const int index, |
| const SkFontStyle& style, |
| const std::string& full_name, |
| const std::string& postscript_name) |
| : font_file_path(file_path), |
| ttc_index(index), |
| font_style(style), |
| full_font_name(full_name.data(), full_name.size()), |
| font_postscript_name(postscript_name.data(), postscript_name.size()), |
| typeface(NULL) {} |
| |
| const SkString font_file_path; |
| const int ttc_index; |
| const SkFontStyle font_style; |
| |
| // these two members are declared as std::string since we have a hasher |
| // for std::string, but not SkString at this point. |
| const std::string full_font_name; |
| const std::string font_postscript_name; |
| |
| SkAutoTUnref<SkTypeface> typeface; |
| }; |
| |
| SkFontStyleSet_Cobalt(const SkFontMgr_Cobalt* const manager, |
| const FontFamily& family, const char* base_path, |
| SkMutex* const manager_owned_mutex); |
| |
| // From SkFontStyleSet |
| virtual int count() SK_OVERRIDE; |
| // NOTE: SkFontStyleSet_Cobalt does not support |getStyle|, as publicly |
| // accessing styles by index is unsafe. |
| virtual void getStyle(int index, SkFontStyle* style, |
| SkString* name) SK_OVERRIDE; |
| // NOTE: SkFontStyleSet_Cobalt does not support |createTypeface|, as |
| // publicly accessing styles by index is unsafe. |
| virtual SkTypeface* createTypeface(int index) SK_OVERRIDE; |
| |
| virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE; |
| |
| const SkString& get_family_name() const { return family_name_; } |
| |
| private: |
| // NOTE: It is the responsibility of the caller to lock the mutex before |
| // calling any of the non-const private functions. |
| |
| SkTypeface* MatchStyleWithoutLocking(const SkFontStyle& pattern); |
| bool ContainsTypeface(const SkTypeface* typeface); |
| |
| bool ContainsCharacter(const SkFontStyle& style, SkUnichar character); |
| bool CharacterMapContainsCharacter(SkUnichar character); |
| void GenerateCharacterMapFromData(SkData* font_data); |
| |
| int GetClosestStyleIndex(const SkFontStyle& pattern); |
| void CreateSystemTypeface(SkFontStyleSetEntry_Cobalt* style); |
| void CreateSystemTypefaceFromData(SkFontStyleSetEntry_Cobalt* style, |
| SkData* data); |
| |
| // NOTE: The following variables can safely be accessed outside of a lock. |
| const SkFontMgr_Cobalt* const font_manager_; |
| SkMutex* const manager_owned_mutex_; |
| |
| SkString family_name_; |
| bool is_fallback_font_; |
| SkLanguage language_; |
| font_character_map::PageRanges page_ranges_; |
| |
| // NOTE: The following characters require locking when being accessed. |
| bool is_character_map_generated_; |
| font_character_map::CharacterMap character_map_; |
| |
| SkTArray<SkAutoTUnref<SkFontStyleSetEntry_Cobalt>, true> styles_; |
| |
| friend class SkFontMgr_Cobalt; |
| }; |
| |
| // This class is essentially a collection of SkFontStyleSet_Cobalt, one |
| // SkFontStyleSet_Cobalt for each family. This class may be modified to load |
| // fonts from any source by changing the initialization. |
| // |
| // In addition to containing a collection of SkFontStyleSet_Cobalt, the class |
| // also contains a mapping of names to families, allowing for multiple aliases |
| // to map to the same back-end family. |
| // |
| // It also contains a list of fallback fonts, which are used when attempting |
| // to match a character, rather than a family name. If a language is provided |
| // then fallback fonts with that language are given priority. Otherwise, the |
| // fallback fonts are checked in order. |
| class SkFontMgr_Cobalt : public SkFontMgr { |
| public: |
| SkFontMgr_Cobalt(const char* directory, |
| const SkTArray<SkString, true>& default_fonts); |
| |
| // Note: Unlike the other similar onMatch* functions, this function can return |
| // NULL. This is so that we can try other things in case the match is not |
| // found. |
| SkTypeface* matchFaceNameOnlyIfFound(const std::string& font_face_name) const; |
| |
| protected: |
| // Note: These match*Name helper functions can return NULL. |
| SkTypeface* matchFullFontFaceName(const std::string& font_face_name) const; |
| SkTypeface* matchPostScriptName(const std::string& font_face_name) const; |
| SkTypeface* matchFullFontFaceNameHelper( |
| SkFontStyleSet_Cobalt* style_set, |
| SkFontStyleSet_Cobalt::SkFontStyleSetEntry_Cobalt* style) const; |
| |
| // From SkFontMgr |
| virtual int onCountFamilies() const SK_OVERRIDE; |
| |
| virtual void onGetFamilyName(int index, |
| SkString* family_name) const SK_OVERRIDE; |
| |
| virtual SkFontStyleSet_Cobalt* onCreateStyleSet(int index) const SK_OVERRIDE; |
| |
| virtual SkFontStyleSet_Cobalt* onMatchFamily(const char family_name[]) const |
| SK_OVERRIDE; |
| |
| virtual SkTypeface* onMatchFamilyStyle( |
| const char family_name[], const SkFontStyle& style) const SK_OVERRIDE; |
| |
| #ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER |
| virtual SkTypeface* onMatchFamilyStyleCharacter( |
| const char family_name[], const SkFontStyle& style, const char* bcp47[], |
| int bcp47_count, SkUnichar character) const SK_OVERRIDE; |
| #else |
| virtual SkTypeface* onMatchFamilyStyleCharacter( |
| const char family_name[], const SkFontStyle& style, const char bcp47[], |
| SkUnichar character) const SK_OVERRIDE; |
| #endif |
| |
| virtual SkTypeface* onMatchFaceStyle(const SkTypeface* family_member, |
| const SkFontStyle& font_style) const |
| SK_OVERRIDE; |
| |
| virtual SkTypeface* onCreateFromData(SkData* data, |
| int ttc_index) const SK_OVERRIDE; |
| |
| virtual SkTypeface* onCreateFromStream(SkStream* stream, |
| int ttc_index) const SK_OVERRIDE; |
| |
| virtual SkTypeface* onCreateFromFile(const char path[], |
| int ttc_index) const SK_OVERRIDE; |
| |
| virtual SkTypeface* onLegacyCreateTypeface( |
| const char family_name[], unsigned style_bits) const SK_OVERRIDE; |
| |
| private: |
| struct TimedSystemTypeface { |
| TimedSystemTypeface(const SkTypeface_CobaltSystem* system_typeface, |
| const base::TimeTicks& event_time) |
| : typeface(system_typeface), time(event_time) {} |
| |
| const SkTypeface_CobaltSystem* typeface; |
| base::TimeTicks time; |
| }; |
| |
| // Map names to the back end so that all names for a given family refer to |
| // the same (non-replicated) set of typefaces. |
| typedef base::hash_map<std::string, SkFontStyleSet_Cobalt*> NameToFamilyMap; |
| |
| struct FontFaceInfo { |
| FontFaceInfo() : style_set_entry(NULL), style_set_entry_parent(NULL) {} |
| FontFaceInfo(SkFontStyleSet_Cobalt::SkFontStyleSetEntry_Cobalt* entry, |
| SkFontStyleSet_Cobalt* parent) |
| : style_set_entry(entry), style_set_entry_parent(parent) {} |
| |
| SkFontStyleSet_Cobalt::SkFontStyleSetEntry_Cobalt* style_set_entry; |
| SkFontStyleSet_Cobalt* style_set_entry_parent; |
| }; |
| |
| typedef base::hash_map<std::string, FontFaceInfo> |
| FullFontNameToFontFaceInfoMap; |
| typedef base::hash_map<std::string, FontFaceInfo> PostScriptToFontFaceInfoMap; |
| |
| void BuildNameToFamilyMap(const char* base_path, |
| SkTDArray<FontFamily*>* families); |
| void FindDefaultFont(const SkTArray<SkString, true>& default_fonts); |
| |
| // NOTE: |style_sets_mutex_| should be locked prior to calling this function. |
| SkTypeface* FindFamilyStyleCharacter(const SkFontStyle& style, |
| const SkString& lang_tag, |
| SkUnichar character) const; |
| |
| void HandlePeriodicProcessing(); |
| |
| // System typeface stream related |
| |
| // Called by SkTypeface_CobaltSystem when it opens a new stream, this adds |
| // the system typeface to the active open stream list and adds the stream's |
| // bytes into the open stream cache size. |
| // NOTE1: This assumes that the typeface is not already in the list. |
| // NOTE2: This requires the caller to lock |system_typeface_stream_mutex_| |
| void AddSystemTypefaceWithActiveOpenStream( |
| const SkTypeface_CobaltSystem* system_typeface) const; |
| // Called by SkTypeface_CobaltSystem when an already open stream shows |
| // activity, this moves the system typeface from the inactive open stream list |
| // to the active open stream list. |
| // NOTE: This requires the caller to lock |system_typeface_stream_mutex_| |
| void NotifySystemTypefaceOfOpenStreamActivity( |
| const SkTypeface_CobaltSystem* system_typeface) const; |
| // Called by |system_typeface_open_stream_timer_|, this handles periodic |
| // processing on the open streams, including moving typefaces from the |
| // active to the inactive list and releasing inactive open streams. |
| // NOTE: Handles locking |system_typeface_stream_mutex_| internally |
| void ProcessSystemTypefacesWithOpenStreams( |
| const base::TimeTicks& current_time) const; |
| // Mutex shared by all system typefaces for accessing/modifying stream data. |
| SkMutex& GetSystemTypefaceStreamMutex() const; |
| |
| SkTArray<SkAutoTUnref<SkFontStyleSet_Cobalt>, true> font_style_sets_; |
| |
| SkTArray<SkString> family_names_; |
| NameToFamilyMap name_to_family_map_; |
| FullFontNameToFontFaceInfoMap fullfontname_to_fontface_info_map_; |
| PostScriptToFontFaceInfoMap postscriptname_to_fontface_info_map_; |
| |
| SkTArray<SkFontStyleSet_Cobalt*> fallback_families_; |
| |
| SkFontStyleSet_Cobalt* default_family_; |
| SkAutoTUnref<SkTypeface> default_typeface_; |
| |
| // System typeface stream related |
| // NOTE: mutable is required on all variables potentially modified via calls |
| // from SkFontStyleSet_Cobalt::onOpenStream(), which is const. |
| |
| // Tracking of active and inactive open streams among the system typefaces. |
| // The streams are initially active and are moved to the inactive list when |
| // the stream's underlying SkData no longer has any external references. |
| // Inactive open streams are stored and released in temporal order. |
| mutable SkTArray<const SkTypeface_CobaltSystem*> |
| system_typefaces_with_active_open_streams_; |
| mutable SkTArray<TimedSystemTypeface> |
| system_typefaces_with_inactive_open_streams_; |
| |
| // This mutex is used when accessing/modifying both the system typeface stream |
| // data itself and the variables used with tracking that data. |
| mutable SkMutex system_typeface_stream_mutex_; |
| |
| // Mutex shared by all style sets for accessing their modifiable data. |
| mutable SkMutex style_sets_mutex_; |
| |
| // The last time that a partial purge of Skia's font cache was forced. This is |
| // done periodically to ensure that unused fonts are not indefinitely |
| // referenced by Skia. |
| base::TimeTicks last_font_cache_purge_time_; |
| |
| // SkTypeface_CobaltSystem is a friend so that it can make system typeface |
| // open stream calls into SkFontMgr_Cobalt from |
| // SkTypeface_CobaltSystem::onOpenStream(). Those calls should not be |
| // accessible publicly. |
| friend class SkTypeface_CobaltSystem; |
| }; |
| |
| #endif // COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_PORTS_SKFONTMGR_COBALT_H_ |