blob: cebba88e9e0dcff02203766e8d8401c680ed9b73 [file] [log] [blame]
/*
* 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_