Index: skia/ext/SkFontHost_fontconfig.cpp |
=================================================================== |
--- skia/ext/SkFontHost_fontconfig.cpp (revision 186715) |
+++ skia/ext/SkFontHost_fontconfig.cpp (working copy) |
@@ -1,369 +0,0 @@ |
-/* libs/graphics/ports/SkFontHost_fontconfig.cpp |
-** |
-** Copyright 2008, 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. |
-*/ |
- |
-// ----------------------------------------------------------------------------- |
-// This file provides implementations of the font resolution members of |
-// SkFontHost by using the fontconfig[1] library. Fontconfig is usually found |
-// on Linux systems and handles configuration, parsing and caching issues |
-// involved with enumerating and matching fonts. |
-// |
-// [1] http://fontconfig.org |
-// ----------------------------------------------------------------------------- |
- |
-#include <map> |
-#include <string> |
- |
-#include <sys/mman.h> |
-#include <sys/stat.h> |
-#include <unistd.h> |
- |
-#include "base/compiler_specific.h" |
-#include "third_party/skia/src/core/SkFontDescriptor.h" |
-#include "SkFontHost.h" |
-#include "SkStream.h" |
-#include "SkFontHost_fontconfig_control.h" |
-#include "SkFontHost_fontconfig_impl.h" |
-#include "SkFontHost_fontconfig_direct.h" |
- |
-static FontConfigInterface* global_fc_impl = NULL; |
- |
-void SkiaFontConfigUseDirectImplementation() { |
- if (global_fc_impl) |
- delete global_fc_impl; |
- global_fc_impl = new FontConfigDirect; |
-} |
- |
-void SkiaFontConfigSetImplementation(FontConfigInterface* font_config) { |
- if (global_fc_impl) |
- delete global_fc_impl; |
- global_fc_impl = font_config; |
-} |
- |
-static FontConfigInterface* GetFcImpl() { |
- if (!global_fc_impl) |
- global_fc_impl = new FontConfigDirect; |
- return global_fc_impl; |
-} |
- |
-SK_DECLARE_STATIC_MUTEX(global_remote_font_map_lock); |
-static std::map<uint32_t, std::pair<uint8_t*, size_t> >* global_remote_fonts; |
- |
-// Initialize the map declared above. Note that its corresponding mutex must be |
-// locked before calling this function. |
-static void AllocateGlobalRemoteFontsMapOnce() { |
- if (!global_remote_fonts) { |
- global_remote_fonts = |
- new std::map<uint32_t, std::pair<uint8_t*, size_t> >(); |
- } |
-} |
- |
-static unsigned global_next_remote_font_id; |
- |
-// This is the maximum size of the font cache. |
-static const unsigned kFontCacheMemoryBudget = 2 * 1024 * 1024; // 2MB |
- |
-// UniqueIds are encoded as (filefaceid << 8) | style |
-// For system fonts, filefaceid = (fileid << 4) | face_index. |
-// For remote fonts, filefaceid = fileid. |
- |
-static unsigned UniqueIdToFileFaceId(unsigned uniqueid) |
-{ |
- return uniqueid >> 8; |
-} |
- |
-static SkTypeface::Style UniqueIdToStyle(unsigned uniqueid) |
-{ |
- return static_cast<SkTypeface::Style>(uniqueid & 0xff); |
-} |
- |
-static unsigned FileFaceIdAndStyleToUniqueId(unsigned filefaceid, |
- SkTypeface::Style style) |
-{ |
- SkASSERT((style & 0xff) == style); |
- return (filefaceid << 8) | static_cast<int>(style); |
-} |
- |
-static const unsigned kRemoteFontMask = 0x00800000u; |
- |
-static bool IsRemoteFont(unsigned filefaceid) |
-{ |
- return filefaceid & kRemoteFontMask; |
-} |
- |
-class FontConfigTypeface : public SkTypeface { |
-public: |
- FontConfigTypeface(Style style, uint32_t id) |
- : SkTypeface(style, id) |
- { } |
- |
- virtual ~FontConfigTypeface() |
- { |
- const uint32_t id = uniqueID(); |
- if (IsRemoteFont(UniqueIdToFileFaceId(id))) { |
- SkAutoMutexAcquire ac(global_remote_font_map_lock); |
- AllocateGlobalRemoteFontsMapOnce(); |
- std::map<uint32_t, std::pair<uint8_t*, size_t> >::iterator iter |
- = global_remote_fonts->find(id); |
- if (iter != global_remote_fonts->end()) { |
- sk_free(iter->second.first); // remove the font on memory. |
- global_remote_fonts->erase(iter); |
- } |
- } |
- } |
-}; |
- |
-// static |
-SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace, |
- const char familyName[], |
- SkTypeface::Style style) |
-{ |
- std::string resolved_family_name; |
- |
- if (familyFace) { |
- // Given the fileid we can ask fontconfig for the familyname of the |
- // font. |
- const unsigned filefaceid = UniqueIdToFileFaceId(familyFace->uniqueID()); |
- if (!GetFcImpl()->Match(&resolved_family_name, NULL, |
- true /* filefaceid valid */, filefaceid, "", |
- NULL, 0, NULL, NULL)) { |
- return NULL; |
- } |
- } else if (familyName) { |
- resolved_family_name = familyName; |
- } |
- |
- bool bold = style & SkTypeface::kBold; |
- bool italic = style & SkTypeface::kItalic; |
- unsigned filefaceid; |
- if (!GetFcImpl()->Match(NULL, &filefaceid, |
- false, -1, /* no filefaceid */ |
- resolved_family_name, NULL, 0, |
- &bold, &italic)) { |
- return NULL; |
- } |
- const SkTypeface::Style resulting_style = static_cast<SkTypeface::Style>( |
- (bold ? SkTypeface::kBold : 0) | |
- (italic ? SkTypeface::kItalic : 0)); |
- |
- const unsigned id = FileFaceIdAndStyleToUniqueId(filefaceid, |
- resulting_style); |
- SkTypeface* typeface = SkNEW_ARGS(FontConfigTypeface, (resulting_style, id)); |
- return typeface; |
-} |
- |
-// static |
-SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) |
-{ |
- if (!stream) |
- return NULL; |
- |
- const size_t length = stream->read(0, 0); |
- if (!length) |
- return NULL; |
- if (length >= 1024 * 1024 * 1024) |
- return NULL; // don't accept too large fonts (>= 1GB) for safety. |
- |
- uint8_t* font = (uint8_t*)sk_malloc_throw(length); |
- if (stream->read(font, length) != length) { |
- sk_free(font); |
- return NULL; |
- } |
- |
- SkTypeface::Style style = static_cast<SkTypeface::Style>(0); |
- unsigned id = 0; |
- { |
- SkAutoMutexAcquire ac(global_remote_font_map_lock); |
- AllocateGlobalRemoteFontsMapOnce(); |
- id = FileFaceIdAndStyleToUniqueId( |
- global_next_remote_font_id | kRemoteFontMask, style); |
- |
- if (++global_next_remote_font_id >= kRemoteFontMask) |
- global_next_remote_font_id = 0; |
- |
- if (!global_remote_fonts->insert( |
- std::make_pair(id, std::make_pair(font, length))).second) { |
- sk_free(font); |
- return NULL; |
- } |
- } |
- |
- SkTypeface* typeface = SkNEW_ARGS(FontConfigTypeface, (style, id)); |
- return typeface; |
-} |
- |
-// static |
-SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) |
-{ |
- SkASSERT(!"SkFontHost::CreateTypefaceFromFile unimplemented"); |
- return NULL; |
-} |
- |
-uint32_t SkFontHost::NextLogicalFont(SkFontID curr, SkFontID orig) { |
- // We don't handle font fallback, WebKit does. |
- return 0; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-// Serialize, Deserialize need to be compatible across platforms, hence the use |
-// of SkFontDescriptor. |
- |
-void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { |
- SkFontDescriptor desc(face->style()); |
- |
- std::string resolved_family_name; |
- |
- const unsigned filefaceid = UniqueIdToFileFaceId(face->uniqueID()); |
- if (GetFcImpl()->Match(&resolved_family_name, NULL, |
- true /* filefaceid valid */, filefaceid, "", NULL, 0, NULL, NULL)) |
- desc.setFamilyName(resolved_family_name.c_str()); |
- else |
- desc.setFamilyName("sans-serif"); |
- |
- // would also like other names (see SkFontDescriptor.h) |
- |
- desc.serialize(stream); |
- |
- // by convention, we also write out the actual sfnt data, preceeded by |
- // a packed-length. For now we skip that, so we just write the zero. |
- stream->writePackedUInt(0); |
-} |
- |
-SkTypeface* SkFontHost::Deserialize(SkStream* stream) { |
- SkFontDescriptor desc(stream); |
- |
- // by convention, Serialize will have also written the actual sfnt data. |
- // for now, we just want to skip it. |
- size_t size = stream->readPackedUInt(); |
- stream->skip(size); |
- |
- return SkFontHost::CreateTypeface(NULL, desc.getFamilyName(), |
- desc.getStyle()); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-class SkFileDescriptorStream : public SkStream { |
- public: |
- SkFileDescriptorStream(int fd) { |
- memory_ = NULL; |
- offset_ = 0; |
- |
- // this ensures that if we fail in the constructor, we will safely |
- // ignore all subsequent calls to read() because we will always trim |
- // the requested size down to 0 |
- length_ = 0; |
- |
- struct stat st; |
- if (fstat(fd, &st)) |
- return; |
- |
- void* memory = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); |
- close(fd); |
- if (memory == MAP_FAILED) |
- return; |
- |
- memory_ = reinterpret_cast<uint8_t*>(memory); |
- length_ = st.st_size; |
- } |
- |
- virtual ~SkFileDescriptorStream() { |
- munmap(const_cast<uint8_t*>(memory_), length_); |
- } |
- |
- virtual bool rewind() OVERRIDE { |
- offset_ = 0; |
- return true; |
- } |
- |
- // SkStream implementation. |
- virtual size_t read(void* buffer, size_t size) OVERRIDE { |
- if (!buffer && !size) { |
- // This is request for the length of the stream. |
- return length_; |
- } |
- |
- size_t remaining = length_ - offset_; |
- if (size > remaining) |
- size = remaining; |
- if (buffer) |
- memcpy(buffer, memory_ + offset_, size); |
- |
- offset_ += size; |
- return size; |
- } |
- |
- virtual const void* getMemoryBase() OVERRIDE { |
- return memory_; |
- } |
- |
- private: |
- const uint8_t* memory_; |
- size_t offset_, length_; |
-}; |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-// static |
-SkStream* SkFontHost::OpenStream(uint32_t id) |
-{ |
- const unsigned filefaceid = UniqueIdToFileFaceId(id); |
- |
- if (IsRemoteFont(filefaceid)) { |
- // remote font |
- SkAutoMutexAcquire ac(global_remote_font_map_lock); |
- AllocateGlobalRemoteFontsMapOnce(); |
- std::map<uint32_t, std::pair<uint8_t*, size_t> >::const_iterator iter |
- = global_remote_fonts->find(id); |
- if (iter == global_remote_fonts->end()) |
- return NULL; |
- return SkNEW_ARGS( |
- SkMemoryStream, (iter->second.first, iter->second.second)); |
- } |
- |
- // system font |
- const int fd = GetFcImpl()->Open(filefaceid); |
- if (fd < 0) |
- return NULL; |
- |
- return SkNEW_ARGS(SkFileDescriptorStream, (fd)); |
-} |
- |
-// static |
-size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length, |
- int32_t* index) { |
- const unsigned filefaceid = UniqueIdToFileFaceId(fontID); |
- |
- if (IsRemoteFont(filefaceid)) |
- return 0; |
- |
- if (index) { |
- *index = filefaceid & 0xfu; |
- // 1 is a bogus return value. |
- // We had better change the signature of this function in Skia |
- // to return bool to indicate success/failure and have another |
- // out param for fileName length. |
- if (!path) |
- return 1; |
- } |
- |
- if (path) |
- SkASSERT(!"SkFontHost::GetFileName does not support the font path " |
- "retrieval."); |
- |
- return 0; |
-} |