blob: fc254c094e82d2a05d9537652007456cf37fdbc5 [file] [log] [blame]
/*
* 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<unsigned>(mTypeface);
} else {
h = SkTypeface::UniqueID(mTypeface);
}
uint32_t sizeAsInt = *reinterpret_cast<const uint32_t*>(&mTextSize);
h ^= 0x01010101 * ((static_cast<int>(mTextOrientation) << 3) | (static_cast<int>(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<FontPlatformData*>(this), harfbuzzSkiaGetTable));
return m_harfbuzzFace->face();
#else
return NULL;
#endif
}
}