/* * Copyright 2009, The Android Open Source Project * Copyright (C) 2006 Apple Computer, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //This file is part of the internal font implementation. It should not be included by anyone other than // FontMac.cpp, FontWin.cpp and Font.cpp. #include "config.h" #include "FontPlatformData.h" #ifdef SUPPORT_COMPLEX_SCRIPTS #include "HarfbuzzSkia.h" #endif #include "SkAdvancedTypefaceMetrics.h" #include "SkPaint.h" #include "SkTypeface.h" //#define TRACE_FONTPLATFORMDATA_LIFE //#define COUNT_FONTPLATFORMDATA_LIFE #ifdef COUNT_FONTPLATFORMDATA_LIFE static int gCount; static int gMaxCount; static void inc_count() { if (++gCount > gMaxCount) { gMaxCount = gCount; SkDebugf("---------- FontPlatformData %d\n", gMaxCount); } } static void dec_count() { --gCount; } #else #define inc_count() #define dec_count() #endif #ifdef TRACE_FONTPLATFORMDATA_LIFE #define trace(num) SkDebugf("FontPlatformData%d %p %g %d %d\n", num, mTypeface, mTextSize, mFakeBold, mFakeItalic) #else #define trace(num) #endif namespace WebCore { FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace() { #ifdef SUPPORT_COMPLEX_SCRIPTS HB_FreeFace(m_harfbuzzFace); #endif } FontPlatformData::FontPlatformData() : mTypeface(NULL), mTextSize(0), mEmSizeInFontUnits(0), mFakeBold(false), mFakeItalic(false), mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) { inc_count(); trace(1); } FontPlatformData::FontPlatformData(const FontPlatformData& src) { if (hashTableDeletedFontValue() != src.mTypeface) { SkSafeRef(src.mTypeface); } mTypeface = src.mTypeface; mTextSize = src.mTextSize; mEmSizeInFontUnits = src.mEmSizeInFontUnits; mFakeBold = src.mFakeBold; mFakeItalic = src.mFakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; mOrientation = src.mOrientation; mTextOrientation = src.mTextOrientation; inc_count(); trace(2); } FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation, TextOrientation textOrientation) : mTypeface(tf), mTextSize(textSize), mEmSizeInFontUnits(0), mFakeBold(fakeBold), mFakeItalic(fakeItalic), mOrientation(orientation), mTextOrientation(textOrientation) { if (hashTableDeletedFontValue() != mTypeface) { SkSafeRef(mTypeface); } inc_count(); trace(3); } FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) : mTypeface(src.mTypeface), mTextSize(textSize), mEmSizeInFontUnits(src.mEmSizeInFontUnits), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation), m_harfbuzzFace(src.m_harfbuzzFace) { if (hashTableDeletedFontValue() != mTypeface) { SkSafeRef(mTypeface); } inc_count(); trace(4); } FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) : mTypeface(NULL), mTextSize(size), mEmSizeInFontUnits(0), mFakeBold(bold), mFakeItalic(oblique), mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight) { inc_count(); trace(5); } FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf) : mTypeface(tf), mTextSize(src.mTextSize), mEmSizeInFontUnits(0), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation) { if (hashTableDeletedFontValue() != mTypeface) { SkSafeRef(mTypeface); } inc_count(); trace(6); } FontPlatformData::~FontPlatformData() { dec_count(); #ifdef TRACE_FONTPLATFORMDATA_LIFE SkDebugf("----------- ~FontPlatformData\n"); #endif if (hashTableDeletedFontValue() != mTypeface) { SkSafeUnref(mTypeface); } } int FontPlatformData::emSizeInFontUnits() const { if (mEmSizeInFontUnits) return mEmSizeInFontUnits; SkAdvancedTypefaceMetrics* metrics = 0; if (mTypeface) metrics = mTypeface->getAdvancedTypefaceMetrics(SkAdvancedTypefaceMetrics::kNo_PerGlyphInfo); if (metrics) { mEmSizeInFontUnits = metrics->fEmSize; metrics->unref(); } else mEmSizeInFontUnits = 1000; // default value copied from Skia. return mEmSizeInFontUnits; } FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) { if (hashTableDeletedFontValue() != src.mTypeface) { SkSafeRef(src.mTypeface); } if (hashTableDeletedFontValue() != mTypeface) { SkSafeUnref(mTypeface); } mTypeface = src.mTypeface; mEmSizeInFontUnits = src.mEmSizeInFontUnits; mTextSize = src.mTextSize; mFakeBold = src.mFakeBold; mFakeItalic = src.mFakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; mOrientation = src.mOrientation; mTextOrientation = src.mTextOrientation; return *this; } void FontPlatformData::setupPaint(SkPaint* paint) const { if (hashTableDeletedFontValue() == mTypeface) paint->setTypeface(0); else paint->setTypeface(mTypeface); paint->setAntiAlias(true); paint->setSubpixelText(true); paint->setHinting(SkPaint::kSlight_Hinting); paint->setTextSize(SkFloatToScalar(mTextSize)); paint->setFakeBoldText(mFakeBold); paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0); #ifndef SUPPORT_COMPLEX_SCRIPTS paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); #endif } uint32_t FontPlatformData::uniqueID() const { if (hashTableDeletedFontValue() == mTypeface) return SkTypeface::UniqueID(0); else return SkTypeface::UniqueID(mTypeface); } bool FontPlatformData::operator==(const FontPlatformData& a) const { return mTypeface == a.mTypeface && mTextSize == a.mTextSize && mFakeBold == a.mFakeBold && mFakeItalic == a.mFakeItalic && mOrientation == a.mOrientation && mTextOrientation == a.mTextOrientation; } unsigned FontPlatformData::hash() const { unsigned h; if (hashTableDeletedFontValue() == mTypeface) { h = reinterpret_cast(mTypeface); } else { h = SkTypeface::UniqueID(mTypeface); } uint32_t sizeAsInt = *reinterpret_cast(&mTextSize); h ^= 0x01010101 * ((static_cast(mTextOrientation) << 3) | (static_cast(mOrientation) << 2) | ((int)mFakeBold << 1) | (int)mFakeItalic); h ^= sizeAsInt; return h; } bool FontPlatformData::isFixedPitch() const { if (mTypeface && (mTypeface != hashTableDeletedFontValue())) return mTypeface->isFixedWidth(); else return false; } HB_FaceRec_* FontPlatformData::harfbuzzFace() const { #ifdef SUPPORT_COMPLEX_SCRIPTS if (!m_harfbuzzFace) m_harfbuzzFace = RefCountedHarfbuzzFace::create( HB_NewFace(const_cast(this), harfbuzzSkiaGetTable)); return m_harfbuzzFace->face(); #else return NULL; #endif } }