• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <winsock2.h>
33 #include "Font.h"
34 #include "FontCache.h"
35 #include "FloatRect.h"
36 #include "FontDescription.h"
37 #include <wtf/MathExtras.h>
38 #include <unicode/uchar.h>
39 #include <unicode/unorm.h>
40 #include <mlang.h>
41 #include <tchar.h>
42 
43 #if PLATFORM(CG)
44 #include <ApplicationServices/ApplicationServices.h>
45 #include <WebKitSystemInterface/WebKitSystemInterface.h>
46 #endif
47 
48 namespace WebCore {
49 
50 using std::max;
51 
52 const float cSmallCapsFontSizeMultiplier = 0.7f;
53 
54 static bool g_shouldApplyMacAscentHack;
55 
setShouldApplyMacAscentHack(bool b)56 void SimpleFontData::setShouldApplyMacAscentHack(bool b)
57 {
58     g_shouldApplyMacAscentHack = b;
59 }
60 
shouldApplyMacAscentHack()61 bool SimpleFontData::shouldApplyMacAscentHack()
62 {
63     return g_shouldApplyMacAscentHack;
64 }
65 
initGDIFont()66 void SimpleFontData::initGDIFont()
67 {
68      HDC hdc = GetDC(0);
69      HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
70      OUTLINETEXTMETRIC metrics;
71      GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics);
72      TEXTMETRIC& textMetrics = metrics.otmTextMetrics;
73      m_ascent = textMetrics.tmAscent;
74      m_descent = textMetrics.tmDescent;
75      m_lineGap = textMetrics.tmExternalLeading;
76      m_lineSpacing = m_ascent + m_descent + m_lineGap;
77      m_avgCharWidth = textMetrics.tmAveCharWidth;
78      m_maxCharWidth = textMetrics.tmMaxCharWidth;
79      m_xHeight = m_ascent * 0.56f; // Best guess for xHeight if no x glyph is present.
80 
81      GLYPHMETRICS gm;
82      MAT2 mat = { 1, 0, 0, 1 };
83      DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &mat);
84      if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
85          m_xHeight = gm.gmptGlyphOrigin.y;
86 
87      m_unitsPerEm = metrics.otmEMSquare;
88 
89      SelectObject(hdc, oldFont);
90      ReleaseDC(0, hdc);
91 
92      return;
93 }
94 
platformDestroy()95 void SimpleFontData::platformDestroy()
96 {
97     // We don't hash this on Win32, so it's effectively owned by us.
98     delete m_smallCapsFontData;
99     m_smallCapsFontData = 0;
100 
101     ScriptFreeCache(&m_scriptCache);
102     delete m_scriptFontProperties;
103 }
104 
smallCapsFontData(const FontDescription & fontDescription) const105 SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
106 {
107     if (!m_smallCapsFontData) {
108         float smallCapsHeight = cSmallCapsFontSizeMultiplier * m_platformData.size();
109         if (isCustomFont()) {
110             FontPlatformData smallCapsFontData(m_platformData);
111             smallCapsFontData.setSize(smallCapsHeight);
112             m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false);
113         } else {
114             LOGFONT winfont;
115             GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont);
116             winfont.lfHeight = -lroundf(smallCapsHeight * (m_platformData.useGDI() ? 1 : 32));
117             HFONT hfont = CreateFontIndirect(&winfont);
118             m_smallCapsFontData = new SimpleFontData(FontPlatformData(hfont, smallCapsHeight, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()));
119         }
120     }
121     return m_smallCapsFontData;
122 }
123 
containsCharacters(const UChar * characters,int length) const124 bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
125 {
126     // FIXME: Support custom fonts.
127     if (isCustomFont())
128         return false;
129 
130     // FIXME: Microsoft documentation seems to imply that characters can be output using a given font and DC
131     // merely by testing code page intersection.  This seems suspect though.  Can't a font only partially
132     // cover a given code page?
133     IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface();
134     if (!langFontLink)
135         return false;
136 
137     HDC dc = GetDC(0);
138 
139     DWORD acpCodePages;
140     langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages);
141 
142     DWORD fontCodePages;
143     langFontLink->GetFontCodePages(dc, m_platformData.hfont(), &fontCodePages);
144 
145     DWORD actualCodePages;
146     long numCharactersProcessed;
147     long offset = 0;
148     while (offset < length) {
149         langFontLink->GetStrCodePages(characters, length, acpCodePages, &actualCodePages, &numCharactersProcessed);
150         if ((actualCodePages & fontCodePages) == 0)
151             return false;
152         offset += numCharactersProcessed;
153     }
154 
155     ReleaseDC(0, dc);
156 
157     return true;
158 }
159 
determinePitch()160 void SimpleFontData::determinePitch()
161 {
162     if (isCustomFont()) {
163         m_treatAsFixedPitch = false;
164         return;
165     }
166 
167     // TEXTMETRICS have this.  Set m_treatAsFixedPitch based off that.
168     HDC dc = GetDC(0);
169     SaveDC(dc);
170     SelectObject(dc, m_platformData.hfont());
171 
172     // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
173     // is *not* fixed pitch.  Unbelievable but true.
174     TEXTMETRIC tm;
175     GetTextMetrics(dc, &tm);
176     m_treatAsFixedPitch = ((tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
177 
178     RestoreDC(dc, -1);
179     ReleaseDC(0, dc);
180 }
181 
widthForGDIGlyph(Glyph glyph) const182 float SimpleFontData::widthForGDIGlyph(Glyph glyph) const
183 {
184     HDC hdc = GetDC(0);
185     SetGraphicsMode(hdc, GM_ADVANCED);
186     HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
187     int width;
188     GetCharWidthI(hdc, glyph, 1, 0, &width);
189     SelectObject(hdc, oldFont);
190     ReleaseDC(0, hdc);
191     return width + m_syntheticBoldOffset;
192 }
193 
scriptFontProperties() const194 SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const
195 {
196     if (!m_scriptFontProperties) {
197         m_scriptFontProperties = new SCRIPT_FONTPROPERTIES;
198         memset(m_scriptFontProperties, 0, sizeof(SCRIPT_FONTPROPERTIES));
199         m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
200         HRESULT result = ScriptGetFontProperties(0, scriptCache(), m_scriptFontProperties);
201         if (result == E_PENDING) {
202             HDC dc = GetDC(0);
203             SaveDC(dc);
204             SelectObject(dc, m_platformData.hfont());
205             ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties);
206             RestoreDC(dc, -1);
207             ReleaseDC(0, dc);
208         }
209     }
210     return m_scriptFontProperties;
211 }
212 
213 }
214