1 /* 2 * Copyright (C) 2006, 2007 Apple Inc. All Rights Reserved. 3 * Copyright (c) 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 "SimpleFontData.h" 34 35 #include "ChromiumBridge.h" 36 #include "Font.h" 37 #include "FontCache.h" 38 #include "FloatRect.h" 39 #include "FontDescription.h" 40 #include <wtf/MathExtras.h> 41 42 #include <unicode/uchar.h> 43 #include <unicode/unorm.h> 44 #include <objidl.h> 45 #include <mlang.h> 46 47 namespace WebCore { 48 49 static inline float scaleEmToUnits(float x, int unitsPerEm) 50 { 51 return unitsPerEm ? x / static_cast<float>(unitsPerEm) : x; 52 } 53 54 void SimpleFontData::platformInit() 55 { 56 HDC dc = GetDC(0); 57 HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont()); 58 59 TEXTMETRIC textMetric = {0}; 60 if (!GetTextMetrics(dc, &textMetric)) { 61 if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) { 62 // Retry GetTextMetrics. 63 // FIXME: Handle gracefully the error if this call also fails. 64 // See http://crbug.com/6401. 65 if (!GetTextMetrics(dc, &textMetric)) 66 LOG_ERROR("Unable to get the text metrics after second attempt"); 67 } 68 } 69 70 m_avgCharWidth = textMetric.tmAveCharWidth; 71 m_maxCharWidth = textMetric.tmMaxCharWidth; 72 73 m_ascent = textMetric.tmAscent; 74 m_descent = textMetric.tmDescent; 75 m_lineGap = textMetric.tmExternalLeading; 76 m_xHeight = m_ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts. 77 78 OUTLINETEXTMETRIC outlineTextMetric; 79 if (GetOutlineTextMetrics(dc, sizeof(outlineTextMetric), &outlineTextMetric) > 0) { 80 // This is a TrueType font. We might be able to get an accurate xHeight. 81 GLYPHMETRICS glyphMetrics = {0}; 82 MAT2 identityMatrix = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; 83 DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &glyphMetrics, 0, 0, &identityMatrix); 84 if (len != GDI_ERROR && glyphMetrics.gmBlackBoxY > 0) 85 m_xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY); 86 } 87 88 m_lineSpacing = m_ascent + m_descent + m_lineGap; 89 90 SelectObject(dc, oldFont); 91 ReleaseDC(0, dc); 92 } 93 94 void SimpleFontData::platformCharWidthInit() 95 { 96 // charwidths are set in platformInit. 97 } 98 99 void SimpleFontData::platformDestroy() 100 { 101 // We don't hash this on Win32, so it's effectively owned by us. 102 delete m_smallCapsFontData; 103 m_smallCapsFontData = 0; 104 } 105 106 SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const 107 { 108 if (!m_smallCapsFontData) { 109 LOGFONT winFont; 110 GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont); 111 float smallCapsSize = 0.70f * fontDescription.computedSize(); 112 // Unlike WebKit trunk, we don't multiply the size by 32. That seems 113 // to be some kind of artifact of their CG backend, or something. 114 winFont.lfHeight = -lroundf(smallCapsSize); 115 HFONT hfont = CreateFontIndirect(&winFont); 116 m_smallCapsFontData = 117 new SimpleFontData(FontPlatformData(hfont, smallCapsSize)); 118 } 119 return m_smallCapsFontData; 120 } 121 122 bool SimpleFontData::containsCharacters(const UChar* characters, int length) const 123 { 124 // This used to be implemented with IMLangFontLink2, but since that code has 125 // been disabled, this would always return false anyway. 126 return false; 127 } 128 129 void SimpleFontData::determinePitch() 130 { 131 // TEXTMETRICS have this. Set m_treatAsFixedPitch based off that. 132 HDC dc = GetDC(0); 133 HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont()); 134 135 // Yes, this looks backwards, but the fixed pitch bit is actually set if the font 136 // is *not* fixed pitch. Unbelievable but true. 137 TEXTMETRIC textMetric = {0}; 138 if (!GetTextMetrics(dc, &textMetric)) { 139 if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) { 140 // Retry GetTextMetrics. 141 // FIXME: Handle gracefully the error if this call also fails. 142 // See http://crbug.com/6401. 143 if (!GetTextMetrics(dc, &textMetric)) 144 LOG_ERROR("Unable to get the text metrics after second attempt"); 145 } 146 } 147 148 m_treatAsFixedPitch = ((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0); 149 150 SelectObject(dc, oldFont); 151 ReleaseDC(0, dc); 152 } 153 154 float SimpleFontData::platformWidthForGlyph(Glyph glyph) const 155 { 156 HDC dc = GetDC(0); 157 HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont()); 158 159 int width = 0; 160 if (!GetCharWidthI(dc, glyph, 1, 0, &width)) { 161 // Ask the browser to preload the font and retry. 162 if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) { 163 // FIXME: Handle gracefully the error if this call also fails. 164 // See http://crbug.com/6401. 165 if (!GetCharWidthI(dc, glyph, 1, 0, &width)) 166 LOG_ERROR("Unable to get the char width after second attempt"); 167 } 168 } 169 170 SelectObject(dc, oldFont); 171 ReleaseDC(0, dc); 172 173 return static_cast<float>(width); 174 } 175 176 } // namespace WebCore 177