1/*
2 * Copyright (C) 2006, 2007 Apple Computer, Inc.
3 * Copyright (c) 2006, 2007, 2008, 2009, Google Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "config.h"
33#include "FontPlatformData.h"
34
35#include <windows.h>
36#include <objidl.h>
37#include <mlang.h>
38
39#include "PlatformBridge.h"
40#include "SkiaFontWin.h"
41
42namespace WebCore {
43
44FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType)
45    : m_font(hashTableDeletedFontValue())
46    , m_size(-1)
47    , m_scriptCache(0)
48    , m_scriptFontProperties(0)
49{
50}
51
52FontPlatformData::FontPlatformData()
53    : m_font(0)
54    , m_size(0)
55    , m_scriptCache(0)
56    , m_scriptFontProperties(0)
57{
58}
59
60FontPlatformData::FontPlatformData(HFONT font, float size)
61    : m_font(RefCountedHFONT::create(font))
62    , m_size(size)
63    , m_scriptCache(0)
64    , m_scriptFontProperties(0)
65{
66}
67
68// FIXME: this constructor is needed for SVG fonts but doesn't seem to do much
69FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
70    : m_font(0)
71    , m_size(size)
72    , m_scriptCache(0)
73    , m_scriptFontProperties(0)
74{
75}
76
77FontPlatformData::FontPlatformData(const FontPlatformData& data)
78    : m_font(data.m_font)
79    , m_size(data.m_size)
80    , m_scriptCache(0)
81    , m_scriptFontProperties(0)
82{
83}
84
85FontPlatformData& FontPlatformData::operator=(const FontPlatformData& data)
86{
87    if (this != &data) {
88        m_font = data.m_font;
89        m_size = data.m_size;
90
91        // The following fields will get re-computed if necessary.
92        ScriptFreeCache(&m_scriptCache);
93        m_scriptCache = 0;
94
95        delete m_scriptFontProperties;
96        m_scriptFontProperties = 0;
97    }
98    return *this;
99}
100
101FontPlatformData::~FontPlatformData()
102{
103    ScriptFreeCache(&m_scriptCache);
104    m_scriptCache = 0;
105
106    delete m_scriptFontProperties;
107    m_scriptFontProperties = 0;
108}
109
110FontPlatformData::RefCountedHFONT::~RefCountedHFONT()
111{
112    if (m_hfont != reinterpret_cast<HFONT>(-1)) {
113        SkiaWinOutlineCache::removePathsForFont(m_hfont);
114        DeleteObject(m_hfont);
115    }
116}
117
118FontPlatformData::RefCountedHFONT* FontPlatformData::hashTableDeletedFontValue()
119{
120    static RefPtr<RefCountedHFONT> deletedValue =
121        RefCountedHFONT::create(reinterpret_cast<HFONT>(-1));
122    return deletedValue.get();
123}
124
125SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const
126{
127    if (!m_scriptFontProperties) {
128        m_scriptFontProperties = new SCRIPT_FONTPROPERTIES;
129        memset(m_scriptFontProperties, 0, sizeof(SCRIPT_FONTPROPERTIES));
130        m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
131        HRESULT result = ScriptGetFontProperties(0, scriptCache(),
132                                                 m_scriptFontProperties);
133        if (result == E_PENDING) {
134            HDC dc = GetDC(0);
135            HGDIOBJ oldFont = SelectObject(dc, hfont());
136            HRESULT hr = ScriptGetFontProperties(dc, scriptCache(),
137                                                 m_scriptFontProperties);
138            if (S_OK != hr) {
139                if (PlatformBridge::ensureFontLoaded(hfont())) {
140                    // FIXME: Handle gracefully the error if this call also fails.
141                    hr = ScriptGetFontProperties(dc, scriptCache(),
142                                                 m_scriptFontProperties);
143                    if (S_OK != hr) {
144                        LOG_ERROR("Unable to get the font properties after second attempt");
145                    }
146                }
147            }
148
149            SelectObject(dc, oldFont);
150            ReleaseDC(0, dc);
151        }
152    }
153    return m_scriptFontProperties;
154}
155
156#ifndef NDEBUG
157String FontPlatformData::description() const
158{
159    return String();
160}
161#endif
162
163}
164