Home | History | Annotate | Download | only in win
      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 
     56 void SimpleFontData::setShouldApplyMacAscentHack(bool b)
     57 {
     58     g_shouldApplyMacAscentHack = b;
     59 }
     60 
     61 bool SimpleFontData::shouldApplyMacAscentHack()
     62 {
     63     return g_shouldApplyMacAscentHack;
     64 }
     65 
     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 
     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 
    105 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 
    124 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 
    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 
    182 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 
    194 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