| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * | |
| 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. | |
| 16 * | |
| 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. | |
| 27 */ | |
| 28 | |
| 29 #include "config.h" | |
| 30 #include "SimpleFontData.h" | |
| 31 | |
| 32 #include "Font.h" | |
| 33 #include "FontCache.h" | |
| 34 #include "FloatRect.h" | |
| 35 #include "FontDescription.h" | |
| 36 #include "HWndDC.h" | |
| 37 #include <mlang.h> | |
| 38 #include <wtf/MathExtras.h> | |
| 39 | |
| 40 namespace WebCore { | |
| 41 | |
| 42 const float cSmallCapsFontSizeMultiplier = 0.7f; | |
| 43 | |
| 44 static bool g_shouldApplyMacAscentHack; | |
| 45 | |
| 46 void SimpleFontData::setShouldApplyMacAscentHack(bool b) | |
| 47 { | |
| 48 g_shouldApplyMacAscentHack = b; | |
| 49 } | |
| 50 | |
| 51 bool SimpleFontData::shouldApplyMacAscentHack() | |
| 52 { | |
| 53 return g_shouldApplyMacAscentHack; | |
| 54 } | |
| 55 | |
| 56 float SimpleFontData::ascentConsideringMacAscentHack(const WCHAR* faceName, floa
t ascent, float descent) | |
| 57 { | |
| 58 if (!shouldApplyMacAscentHack()) | |
| 59 return ascent; | |
| 60 | |
| 61 // This code comes from FontDataMac.mm. We only ever do this when running re
gression tests so that our metrics will match Mac. | |
| 62 | |
| 63 // We need to adjust Times, Helvetica, and Courier to closely match the | |
| 64 // vertical metrics of their Microsoft counterparts that are the de facto | |
| 65 // web standard. The AppKit adjustment of 20% is too big and is | |
| 66 // incorrectly added to line spacing, so we use a 15% adjustment instead | |
| 67 // and add it to the ascent. | |
| 68 if (!wcscmp(faceName, L"Times") || !wcscmp(faceName, L"Helvetica") || !wcscm
p(faceName, L"Courier")) | |
| 69 ascent += floorf(((ascent + descent) * 0.15f) + 0.5f); | |
| 70 | |
| 71 return ascent; | |
| 72 } | |
| 73 | |
| 74 void SimpleFontData::initGDIFont() | |
| 75 { | |
| 76 if (!m_platformData.size()) { | |
| 77 m_fontMetrics.reset(); | |
| 78 m_avgCharWidth = 0; | |
| 79 m_maxCharWidth = 0; | |
| 80 return; | |
| 81 } | |
| 82 | |
| 83 HWndDC hdc(0); | |
| 84 HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont()); | |
| 85 OUTLINETEXTMETRIC metrics; | |
| 86 GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics); | |
| 87 TEXTMETRIC& textMetrics = metrics.otmTextMetrics; | |
| 88 float ascent = textMetrics.tmAscent; | |
| 89 float descent = textMetrics.tmDescent; | |
| 90 float lineGap = textMetrics.tmExternalLeading; | |
| 91 m_fontMetrics.setAscent(ascent); | |
| 92 m_fontMetrics.setDescent(descent); | |
| 93 m_fontMetrics.setLineGap(lineGap); | |
| 94 m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(li
neGap)); | |
| 95 m_avgCharWidth = textMetrics.tmAveCharWidth; | |
| 96 m_maxCharWidth = textMetrics.tmMaxCharWidth; | |
| 97 float xHeight = ascent * 0.56f; // Best guess for xHeight if no x glyph is p
resent. | |
| 98 #if !OS(WINCE) | |
| 99 GLYPHMETRICS gm; | |
| 100 static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 }; | |
| 101 DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &identity); | |
| 102 if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0) | |
| 103 xHeight = gm.gmptGlyphOrigin.y; | |
| 104 #endif | |
| 105 m_fontMetrics.setXHeight(xHeight); | |
| 106 m_fontMetrics.setUnitsPerEm(metrics.otmEMSquare); | |
| 107 | |
| 108 SelectObject(hdc, oldFont); | |
| 109 } | |
| 110 | |
| 111 void SimpleFontData::platformCharWidthInit() | |
| 112 { | |
| 113 // GDI Fonts init charwidths in initGDIFont. | |
| 114 if (!m_platformData.useGDI()) { | |
| 115 m_avgCharWidth = 0.f; | |
| 116 m_maxCharWidth = 0.f; | |
| 117 initCharWidths(); | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 void SimpleFontData::platformDestroy() | |
| 122 { | |
| 123 #if !OS(WINCE) | |
| 124 ScriptFreeCache(&m_scriptCache); | |
| 125 delete m_scriptFontProperties; | |
| 126 #endif | |
| 127 } | |
| 128 | |
| 129 PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const Fo
ntDescription& fontDescription, float scaleFactor) const | |
| 130 { | |
| 131 float scaledSize = scaleFactor * m_platformData.size(); | |
| 132 if (isCustomFont()) { | |
| 133 FontPlatformData scaledFont(m_platformData); | |
| 134 scaledFont.setSize(scaledSize); | |
| 135 return SimpleFontData::create(scaledFont, true, false); | |
| 136 } | |
| 137 | |
| 138 LOGFONT winfont; | |
| 139 GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont); | |
| 140 winfont.lfHeight = -lroundf(scaledSize * (m_platformData.useGDI() ? 1 : 32))
; | |
| 141 HFONT hfont = CreateFontIndirect(&winfont); | |
| 142 return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platform
Data.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()
), isCustomFont(), false); | |
| 143 } | |
| 144 | |
| 145 bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
st | |
| 146 { | |
| 147 // FIXME: Support custom fonts. | |
| 148 if (isCustomFont()) | |
| 149 return false; | |
| 150 | |
| 151 // FIXME: Microsoft documentation seems to imply that characters can be outp
ut using a given font and DC | |
| 152 // merely by testing code page intersection. This seems suspect though. Ca
n't a font only partially | |
| 153 // cover a given code page? | |
| 154 IMLangFontLinkType* langFontLink = fontCache()->getFontLinkInterface(); | |
| 155 if (!langFontLink) | |
| 156 return false; | |
| 157 | |
| 158 HWndDC dc(0); | |
| 159 | |
| 160 DWORD acpCodePages; | |
| 161 langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages); | |
| 162 | |
| 163 DWORD fontCodePages; | |
| 164 langFontLink->GetFontCodePages(dc, m_platformData.hfont(), &fontCodePages); | |
| 165 | |
| 166 DWORD actualCodePages; | |
| 167 long numCharactersProcessed; | |
| 168 long offset = 0; | |
| 169 while (offset < length) { | |
| 170 langFontLink->GetStrCodePages(characters, length, acpCodePages, &actualC
odePages, &numCharactersProcessed); | |
| 171 if ((actualCodePages & fontCodePages) == 0) | |
| 172 return false; | |
| 173 offset += numCharactersProcessed; | |
| 174 } | |
| 175 | |
| 176 return true; | |
| 177 } | |
| 178 | |
| 179 void SimpleFontData::determinePitch() | |
| 180 { | |
| 181 if (isCustomFont()) { | |
| 182 m_treatAsFixedPitch = false; | |
| 183 return; | |
| 184 } | |
| 185 | |
| 186 // TEXTMETRICS have this. Set m_treatAsFixedPitch based off that. | |
| 187 HWndDC dc(0); | |
| 188 SaveDC(dc); | |
| 189 SelectObject(dc, m_platformData.hfont()); | |
| 190 | |
| 191 // Yes, this looks backwards, but the fixed pitch bit is actually set if the
font | |
| 192 // is *not* fixed pitch. Unbelievable but true. | |
| 193 TEXTMETRIC tm; | |
| 194 GetTextMetrics(dc, &tm); | |
| 195 m_treatAsFixedPitch = ((tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0); | |
| 196 | |
| 197 RestoreDC(dc, -1); | |
| 198 } | |
| 199 | |
| 200 FloatRect SimpleFontData::boundsForGDIGlyph(Glyph glyph) const | |
| 201 { | |
| 202 #if OS(WINCE) | |
| 203 return FloatRect(); | |
| 204 #else | |
| 205 HWndDC hdc(0); | |
| 206 SetGraphicsMode(hdc, GM_ADVANCED); | |
| 207 HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont()); | |
| 208 | |
| 209 GLYPHMETRICS gdiMetrics; | |
| 210 static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 }; | |
| 211 GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0
, &identity); | |
| 212 | |
| 213 SelectObject(hdc, oldFont); | |
| 214 | |
| 215 return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y
, | |
| 216 gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY);
| |
| 217 #endif | |
| 218 } | |
| 219 | |
| 220 float SimpleFontData::widthForGDIGlyph(Glyph glyph) const | |
| 221 { | |
| 222 HWndDC hdc(0); | |
| 223 #if !OS(WINCE) | |
| 224 SetGraphicsMode(hdc, GM_ADVANCED); | |
| 225 #endif | |
| 226 HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont()); | |
| 227 | |
| 228 #if OS(WINCE) | |
| 229 WCHAR c = glyph; | |
| 230 SIZE fontSize; | |
| 231 GetTextExtentPoint32W(hdc, &c, 1, &fontSize); | |
| 232 float result = fontSize.cx * m_platformData.size() / 72.f; | |
| 233 #else | |
| 234 GLYPHMETRICS gdiMetrics; | |
| 235 static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 }; | |
| 236 GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0
, &identity); | |
| 237 float result = gdiMetrics.gmCellIncX + m_syntheticBoldOffset; | |
| 238 #endif | |
| 239 | |
| 240 SelectObject(hdc, oldFont); | |
| 241 | |
| 242 return result; | |
| 243 } | |
| 244 | |
| 245 #if !OS(WINCE) | |
| 246 SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const | |
| 247 { | |
| 248 if (!m_scriptFontProperties) { | |
| 249 m_scriptFontProperties = new SCRIPT_FONTPROPERTIES; | |
| 250 memset(m_scriptFontProperties, 0, sizeof(SCRIPT_FONTPROPERTIES)); | |
| 251 m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES); | |
| 252 HRESULT result = ScriptGetFontProperties(0, scriptCache(), m_scriptFontP
roperties); | |
| 253 if (result == E_PENDING) { | |
| 254 HWndDC dc(0); | |
| 255 SaveDC(dc); | |
| 256 SelectObject(dc, m_platformData.hfont()); | |
| 257 ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties); | |
| 258 RestoreDC(dc, -1); | |
| 259 } | |
| 260 } | |
| 261 return m_scriptFontProperties; | |
| 262 } | |
| 263 #endif | |
| 264 | |
| 265 } // namespace WebCore | |
| OLD | NEW |