1/*
2 * Copyright 2009, The Android Open Source Project
3 * Copyright (C) 2006 Apple Computer, Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27//This file is part of the internal font implementation.  It should not be included by anyone other than
28// FontMac.cpp, FontWin.cpp and Font.cpp.
29
30#include "config.h"
31#include "FontPlatformData.h"
32
33#ifdef SUPPORT_COMPLEX_SCRIPTS
34#include "HarfbuzzSkia.h"
35#endif
36#include "SkPaint.h"
37#include "SkTypeface.h"
38
39//#define TRACE_FONTPLATFORMDATA_LIFE
40//#define COUNT_FONTPLATFORMDATA_LIFE
41
42#ifdef COUNT_FONTPLATFORMDATA_LIFE
43static int gCount;
44static int gMaxCount;
45
46static void inc_count()
47{
48    if (++gCount > gMaxCount)
49    {
50        gMaxCount = gCount;
51        SkDebugf("---------- FontPlatformData %d\n", gMaxCount);
52    }
53}
54
55static void dec_count() { --gCount; }
56#else
57    #define inc_count()
58    #define dec_count()
59#endif
60
61#ifdef TRACE_FONTPLATFORMDATA_LIFE
62    #define trace(num)  SkDebugf("FontPlatformData%d %p %g %d %d\n", num, mTypeface, mTextSize, mFakeBold, mFakeItalic)
63#else
64    #define trace(num)
65#endif
66
67namespace WebCore {
68
69FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace()
70{
71#ifdef SUPPORT_COMPLEX_SCRIPTS
72    HB_FreeFace(m_harfbuzzFace);
73#endif
74}
75
76FontPlatformData::FontPlatformData()
77    : mTypeface(NULL), mTextSize(0), mFakeBold(false), mFakeItalic(false),
78      mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight)
79{
80    inc_count();
81    trace(1);
82}
83
84FontPlatformData::FontPlatformData(const FontPlatformData& src)
85{
86    if (hashTableDeletedFontValue() != src.mTypeface) {
87        SkSafeRef(src.mTypeface);
88    }
89
90    mTypeface   = src.mTypeface;
91
92    mTextSize   = src.mTextSize;
93    mFakeBold   = src.mFakeBold;
94    mFakeItalic = src.mFakeItalic;
95    m_harfbuzzFace = src.m_harfbuzzFace;
96    mOrientation = src.mOrientation;
97    mTextOrientation = src.mTextOrientation;
98
99    inc_count();
100    trace(2);
101}
102
103FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic,
104    FontOrientation orientation, TextOrientation textOrientation)
105    : mTypeface(tf), mTextSize(textSize), mFakeBold(fakeBold), mFakeItalic(fakeItalic),
106      mOrientation(orientation), mTextOrientation(textOrientation)
107{
108    if (hashTableDeletedFontValue() != mTypeface) {
109        SkSafeRef(mTypeface);
110    }
111
112    inc_count();
113    trace(3);
114}
115
116FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
117    : mTypeface(src.mTypeface), mTextSize(textSize), mFakeBold(src.mFakeBold), mFakeItalic(src.mFakeItalic),
118      m_harfbuzzFace(src.m_harfbuzzFace), mOrientation(src.mOrientation), mTextOrientation(src.mTextOrientation)
119{
120    if (hashTableDeletedFontValue() != mTypeface) {
121        SkSafeRef(mTypeface);
122    }
123
124    inc_count();
125    trace(4);
126}
127
128FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
129    : mTypeface(NULL), mTextSize(size), mFakeBold(bold), mFakeItalic(oblique),
130      mOrientation(Horizontal), mTextOrientation(TextOrientationVerticalRight)
131{
132    inc_count();
133    trace(5);
134}
135
136FontPlatformData::FontPlatformData(const FontPlatformData& src, SkTypeface* tf)
137    : mTypeface(tf), mTextSize(src.mTextSize), mFakeBold(src.mFakeBold),
138      mFakeItalic(src.mFakeItalic), mOrientation(src.mOrientation),
139      mTextOrientation(src.mTextOrientation)
140{
141    if (hashTableDeletedFontValue() != mTypeface) {
142        SkSafeRef(mTypeface);
143    }
144
145    inc_count();
146    trace(6);
147}
148
149FontPlatformData::~FontPlatformData()
150{
151    dec_count();
152#ifdef TRACE_FONTPLATFORMDATA_LIFE
153    SkDebugf("----------- ~FontPlatformData\n");
154#endif
155
156    if (hashTableDeletedFontValue() != mTypeface) {
157        SkSafeUnref(mTypeface);
158    }
159}
160
161FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
162{
163    if (hashTableDeletedFontValue() != src.mTypeface) {
164        SkSafeRef(src.mTypeface);
165    }
166    if (hashTableDeletedFontValue() != mTypeface) {
167        SkSafeUnref(mTypeface);
168    }
169
170    mTypeface   = src.mTypeface;
171    mTextSize   = src.mTextSize;
172    mFakeBold   = src.mFakeBold;
173    mFakeItalic = src.mFakeItalic;
174    m_harfbuzzFace = src.m_harfbuzzFace;
175    mOrientation = src.mOrientation;
176    mTextOrientation = src.mTextOrientation;
177
178    return *this;
179}
180
181void FontPlatformData::setupPaint(SkPaint* paint) const
182{
183    float ts = mTextSize;
184    if (!(ts > 0))
185        ts = 12;
186
187    if (hashTableDeletedFontValue() == mTypeface)
188        paint->setTypeface(0);
189    else
190        paint->setTypeface(mTypeface);
191
192    paint->setAntiAlias(true);
193    paint->setSubpixelText(true);
194    paint->setHinting(SkPaint::kSlight_Hinting);
195    paint->setTextSize(SkFloatToScalar(ts));
196    paint->setFakeBoldText(mFakeBold);
197    paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0);
198#ifndef SUPPORT_COMPLEX_SCRIPTS
199    paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
200#endif
201}
202
203uint32_t FontPlatformData::uniqueID() const
204{
205    if (hashTableDeletedFontValue() == mTypeface)
206        return SkTypeface::UniqueID(0);
207    else
208        return SkTypeface::UniqueID(mTypeface);
209}
210
211bool FontPlatformData::operator==(const FontPlatformData& a) const
212{
213    return  mTypeface == a.mTypeface &&
214            mTextSize == a.mTextSize &&
215            mFakeBold == a.mFakeBold &&
216            mFakeItalic == a.mFakeItalic &&
217            mOrientation == a.mOrientation &&
218            mTextOrientation == a.mTextOrientation;
219}
220
221unsigned FontPlatformData::hash() const
222{
223    unsigned h;
224
225    if (hashTableDeletedFontValue() == mTypeface) {
226        h = reinterpret_cast<unsigned>(mTypeface);
227    } else {
228        h = SkTypeface::UniqueID(mTypeface);
229    }
230
231    uint32_t sizeAsInt = *reinterpret_cast<const uint32_t*>(&mTextSize);
232
233    h ^= 0x01010101 * ((static_cast<int>(mTextOrientation) << 3) | (static_cast<int>(mOrientation) << 2) |
234         ((int)mFakeBold << 1) | (int)mFakeItalic);
235    h ^= sizeAsInt;
236    return h;
237}
238
239bool FontPlatformData::isFixedPitch() const
240{
241    if (mTypeface && (mTypeface != hashTableDeletedFontValue()))
242        return mTypeface->isFixedWidth();
243    else
244        return false;
245}
246
247HB_FaceRec_* FontPlatformData::harfbuzzFace() const
248{
249#ifdef SUPPORT_COMPLEX_SCRIPTS
250    if (!m_harfbuzzFace)
251        m_harfbuzzFace = RefCountedHarfbuzzFace::create(
252            HB_NewFace(const_cast<FontPlatformData*>(this), harfbuzzSkiaGetTable));
253
254    return m_harfbuzzFace->face();
255#else
256    return NULL;
257#endif
258}
259}
260