2
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. 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
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14
* its contributors may be used to endorse or promote products derived
15
* from this software without specific prior written permission.
17
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
#include "FontCache.h"
34
#include "FloatRect.h"
35
#include "FontDescription.h"
36
#include <wtf/MathExtras.h>
37
#include <unicode/uchar.h>
38
#include <unicode/unorm.h>
39
#include <ApplicationServices/ApplicationServices.h>
42
#include <WebKitSystemInterface/WebKitSystemInterface.h>
48
static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return unitsPerEm ? x / (float)unitsPerEm : x; }
50
void FontData::platformInit()
55
SelectObject(dc, m_font.hfont());
57
int faceLength = GetTextFace(dc, 0, 0);
58
Vector<TCHAR> faceName(faceLength);
59
GetTextFace(dc, faceLength, faceName.data());
61
m_isMLangFont = false;
63
m_syntheticBoldOffset = m_font.syntheticBold() ? 1.0f : 0.f;
65
CGFontRef font = m_font.cgFont();
66
int iAscent = CGFontGetAscent(font);
67
int iDescent = CGFontGetDescent(font);
68
int iLineGap = CGFontGetLeading(font);
69
unsigned unitsPerEm = CGFontGetUnitsPerEm(font);
70
float pointSize = m_font.size();
71
float fAscent = scaleEmToUnits(iAscent, unitsPerEm) * pointSize;
72
float fDescent = -scaleEmToUnits(iDescent, unitsPerEm) * pointSize;
73
float fLineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;
75
m_isSystemFont = !_tcscmp(faceName.data(), _T("Lucida Grande"));
77
// We need to adjust Times, Helvetica, and Courier to closely match the
78
// vertical metrics of their Microsoft counterparts that are the de facto
79
// web standard. The AppKit adjustment of 20% is too big and is
80
// incorrectly added to line spacing, so we use a 15% adjustment instead
81
// and add it to the ascent.
82
if (!_tcscmp(faceName.data(), _T("Times")) || !_tcscmp(faceName.data(), _T("Helvetica")) || !_tcscmp(faceName.data(), _T("Courier")))
83
fAscent += floorf(((fAscent + fDescent) * 0.15f) + 0.5f);
85
m_ascent = lroundf(fAscent);
86
m_descent = lroundf(fDescent);
87
m_lineGap = lroundf(fLineGap);
88
m_lineSpacing = m_ascent + m_descent + m_lineGap;
90
// Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font.
91
// Unfortunately, NSFont will round this for us so we don't quite get the right value.
92
Glyph xGlyph = GlyphPageTreeNode::getRootChild(this, 0)->page()->glyphDataForCharacter('x').glyph;
95
CGFontGetGlyphBBoxes(font, &xGlyph, 1, &xBox);
96
// Use the maximum of either width or height because "x" is nearly square
97
// and web pages that foolishly use this metric for width will be laid out
98
// poorly if we return an accurate height. Classic case is Times 13 point,
99
// which has an "x" that is 7x6 pixels.
100
m_xHeight = scaleEmToUnits(max(CGRectGetMaxX(xBox), CGRectGetMaxY(xBox)), unitsPerEm) * pointSize;
102
int iXHeight = CGFontGetXHeight(font);
103
m_xHeight = scaleEmToUnits(iXHeight, unitsPerEm) * pointSize;
110
m_scriptFontProperties = 0;
113
void FontData::platformDestroy()
115
CGFontRelease(m_font.cgFont());
118
// We have to release the font instead of just deleting it, since we didn't make it.
119
IMLangFontLink2* langFontLink = FontCache::getFontLinkInterface();
121
langFontLink->ReleaseFont(m_font.hfont());
123
DeleteObject(m_font.hfont());
125
// We don't hash this on Win32, so it's effectively owned by us.
126
delete m_smallCapsFontData;
128
ScriptFreeCache(&m_scriptCache);
129
delete m_scriptFontProperties;
132
FontData* FontData::smallCapsFontData(const FontDescription& fontDescription) const
134
if (!m_smallCapsFontData) {
136
GetObject(m_font.hfont(), sizeof(LOGFONT), &winfont);
137
int smallCapsHeight = lroundf(0.70f * fontDescription.computedSize());
138
winfont.lfHeight = -smallCapsHeight * 32;
139
HFONT hfont = CreateFontIndirect(&winfont);
140
m_smallCapsFontData = new FontData(FontPlatformData(hfont, smallCapsHeight, fontDescription.bold(), fontDescription.italic()));
142
return m_smallCapsFontData;
145
bool FontData::containsCharacters(const UChar* characters, int length) const
147
Vector<CGGlyph> glyphBuffer(length);
148
wkGetGlyphs(m_font.cgFont(), characters, glyphBuffer.data(), length);
150
for (int i = 0; i < length; i++) {
151
if (glyphBuffer[i] == 0xFFFFFFFF) {
159
void FontData::determinePitch()
161
// TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
162
HDC dc = GetDC((HWND)0);
164
SelectObject(dc, m_font.hfont());
166
// Yes, this looks backwards, but the fixed pitch bit is actually set if the font
167
// is *not* fixed pitch. Unbelievable but true.
169
GetTextMetrics(dc, &tm);
170
m_treatAsFixedPitch = ((tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
176
float FontData::platformWidthForGlyph(Glyph glyph) const
178
CGFontRef font = m_font.cgFont();
179
float pointSize = m_font.size();
181
CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
182
// FIXME: Need to add real support for printer fonts.
183
bool isPrinterFont = false;
184
wkGetGlyphAdvances(font, m, m_isSystemFont, isPrinterFont, glyph, advance);
185
return advance.width + m_syntheticBoldOffset;
188
SCRIPT_FONTPROPERTIES* FontData::scriptFontProperties() const
190
if (!m_scriptFontProperties) {
191
m_scriptFontProperties = new SCRIPT_FONTPROPERTIES;
192
memset(m_scriptFontProperties, 0, sizeof(SCRIPT_FONTPROPERTIES));
193
m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
194
HRESULT result = ScriptGetFontProperties(0, scriptCache(), m_scriptFontProperties);
195
if (result == E_PENDING) {
198
SelectObject(dc, m_font.hfont());
199
ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties);
204
return m_scriptFontProperties;