Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (C) 2006, 2007 Apple Computer, Inc.
      3  * Copyright (c) 2006, 2007, 2008, 2009, 2012 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 "core/platform/graphics/FontPlatformData.h"
     34 
     35 #include <windows.h>
     36 #include <mlang.h>
     37 #include <objidl.h>
     38 #include "SkPaint.h"
     39 #include "SkTypeface_win.h"
     40 #include "core/platform/SharedBuffer.h"
     41 #include "core/platform/graphics/FontCache.h"
     42 #include "core/platform/graphics/skia/SkiaFontWin.h"
     43 #include "core/platform/win/HWndDC.h"
     44 #include "public/platform/Platform.h"
     45 #include "public/platform/win/WebSandboxSupport.h"
     46 #include "wtf/PassOwnPtr.h"
     47 #include "wtf/StdLibExtras.h"
     48 
     49 namespace WebCore {
     50 
     51 #if !ENABLE(GDI_FONTS_ON_WINDOWS)
     52 void FontPlatformData::setupPaint(SkPaint* paint) const
     53 {
     54     const float ts = m_size >= 0 ? m_size : 12;
     55     paint->setTextSize(SkFloatToScalar(m_size));
     56     paint->setTypeface(m_typeface);
     57 }
     58 #endif
     59 
     60 // Lookup the current system settings for font smoothing.
     61 // We cache these values for performance, but if the browser has a way to be
     62 // notified when these change, we could re-query them at that time.
     63 static uint32_t getDefaultGDITextFlags()
     64 {
     65     static bool gInited;
     66     static uint32_t gFlags;
     67     if (!gInited) {
     68         BOOL enabled;
     69         gFlags = 0;
     70         if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0) && enabled) {
     71             gFlags |= SkPaint::kAntiAlias_Flag;
     72 
     73             UINT smoothType;
     74             if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smoothType, 0)) {
     75                 if (FE_FONTSMOOTHINGCLEARTYPE == smoothType)
     76                     gFlags |= SkPaint::kLCDRenderText_Flag;
     77             }
     78         }
     79         gInited = true;
     80     }
     81     return gFlags;
     82 }
     83 
     84 static int computePaintTextFlags(const LOGFONT& lf)
     85 {
     86     int textFlags = 0;
     87     switch (lf.lfQuality) {
     88     case NONANTIALIASED_QUALITY:
     89         textFlags = 0;
     90         break;
     91     case ANTIALIASED_QUALITY:
     92         textFlags = SkPaint::kAntiAlias_Flag;
     93         break;
     94     case CLEARTYPE_QUALITY:
     95         textFlags = (SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag);
     96         break;
     97     default:
     98         textFlags = getDefaultGDITextFlags();
     99         break;
    100     }
    101 
    102     // only allow features that SystemParametersInfo allows
    103     return textFlags & getDefaultGDITextFlags();
    104 }
    105 
    106 PassRefPtr<SkTypeface> CreateTypefaceFromHFont(HFONT hfont, int* size, int* paintTextFlags)
    107 {
    108     LOGFONT info;
    109     GetObject(hfont, sizeof(info), &info);
    110     if (size) {
    111         int height = info.lfHeight;
    112         if (height < 0)
    113             height = -height;
    114         *size = height;
    115     }
    116     if (paintTextFlags)
    117         *paintTextFlags = computePaintTextFlags(info);
    118     return adoptRef(SkCreateTypefaceFromLOGFONT(info));
    119 }
    120 
    121 FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType)
    122     : m_font(0)
    123     , m_size(-1)
    124     , m_orientation(Horizontal)
    125     , m_scriptCache(0)
    126     , m_paintTextFlags(0)
    127     , m_isHashTableDeletedValue(true)
    128 {
    129 }
    130 
    131 FontPlatformData::FontPlatformData()
    132     : m_font(0)
    133     , m_size(0)
    134     , m_orientation(Horizontal)
    135     , m_scriptCache(0)
    136     , m_paintTextFlags(0)
    137     , m_isHashTableDeletedValue(false)
    138 {
    139 }
    140 
    141 FontPlatformData::FontPlatformData(HFONT font, float size, FontOrientation orientation)
    142     : m_font(RefCountedHFONT::create(font))
    143     , m_size(size)
    144     , m_orientation(orientation)
    145     , m_scriptCache(0)
    146     , m_typeface(CreateTypefaceFromHFont(font, 0, &m_paintTextFlags))
    147     , m_isHashTableDeletedValue(false)
    148 {
    149 }
    150 
    151 // FIXME: this constructor is needed for SVG fonts but doesn't seem to do much
    152 FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
    153     : m_font(0)
    154     , m_size(size)
    155     , m_orientation(Horizontal)
    156     , m_scriptCache(0)
    157     , m_paintTextFlags(0)
    158     , m_isHashTableDeletedValue(false)
    159 {
    160 }
    161 
    162 FontPlatformData::FontPlatformData(const FontPlatformData& data)
    163     : m_font(data.m_font)
    164     , m_size(data.m_size)
    165     , m_orientation(data.m_orientation)
    166     , m_scriptCache(0)
    167     , m_typeface(data.m_typeface)
    168     , m_paintTextFlags(data.m_paintTextFlags)
    169     , m_isHashTableDeletedValue(false)
    170 {
    171 }
    172 
    173 FontPlatformData::FontPlatformData(const FontPlatformData& data, float textSize)
    174     : m_font(data.m_font)
    175     , m_size(textSize)
    176     , m_orientation(data.m_orientation)
    177     , m_scriptCache(0)
    178     , m_typeface(data.m_typeface)
    179     , m_paintTextFlags(data.m_paintTextFlags)
    180     , m_isHashTableDeletedValue(false)
    181 {
    182 }
    183 
    184 FontPlatformData& FontPlatformData::operator=(const FontPlatformData& data)
    185 {
    186     if (this != &data) {
    187         m_font = data.m_font;
    188         m_size = data.m_size;
    189         m_orientation = data.m_orientation;
    190         m_typeface = data.m_typeface;
    191         m_paintTextFlags = data.m_paintTextFlags;
    192 
    193         // The following fields will get re-computed if necessary.
    194         ScriptFreeCache(&m_scriptCache);
    195         m_scriptCache = 0;
    196         m_scriptFontProperties.clear();
    197     }
    198     return *this;
    199 }
    200 
    201 FontPlatformData::~FontPlatformData()
    202 {
    203     ScriptFreeCache(&m_scriptCache);
    204     m_scriptCache = 0;
    205 }
    206 
    207 bool FontPlatformData::isFixedPitch() const
    208 {
    209 #if ENABLE(GDI_FONTS_ON_WINDOWS)
    210     // TEXTMETRICS have this. Set m_treatAsFixedPitch based off that.
    211     HWndDC dc(0);
    212     HGDIOBJ oldFont = SelectObject(dc, hfont());
    213 
    214     // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
    215     // is *not* fixed pitch. Unbelievable but true.
    216     TEXTMETRIC textMetric = { 0 };
    217     if (!GetTextMetrics(dc, &textMetric)) {
    218         if (ensureFontLoaded(hfont())) {
    219             // Retry GetTextMetrics.
    220             // FIXME: Handle gracefully the error if this call also fails.
    221             // See http://crbug.com/6401.
    222             if (!GetTextMetrics(dc, &textMetric))
    223                 LOG_ERROR("Unable to get the text metrics after second attempt");
    224         }
    225     }
    226 
    227     bool treatAsFixedPitch = !(textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH);
    228 
    229     SelectObject(dc, oldFont);
    230 
    231     return treatAsFixedPitch;
    232 #else
    233     return typeface()->isFixedPitch();
    234 #endif
    235 }
    236 
    237 FontPlatformData::RefCountedHFONT::~RefCountedHFONT()
    238 {
    239     DeleteObject(m_hfont);
    240 }
    241 
    242 SCRIPT_FONTPROPERTIES* FontPlatformData::scriptFontProperties() const
    243 {
    244     if (!m_scriptFontProperties) {
    245         m_scriptFontProperties = adoptPtr(new SCRIPT_FONTPROPERTIES);
    246         memset(m_scriptFontProperties.get(), 0, sizeof(SCRIPT_FONTPROPERTIES));
    247         m_scriptFontProperties->cBytes = sizeof(SCRIPT_FONTPROPERTIES);
    248         HRESULT result = ScriptGetFontProperties(0, scriptCache(), m_scriptFontProperties.get());
    249         if (result == E_PENDING) {
    250             HWndDC dc(0);
    251             HGDIOBJ oldFont = SelectObject(dc, hfont());
    252             HRESULT hr = ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties.get());
    253             if (S_OK != hr) {
    254                 if (FontPlatformData::ensureFontLoaded(hfont())) {
    255                     // FIXME: Handle gracefully the error if this call also fails.
    256                     hr = ScriptGetFontProperties(dc, scriptCache(), m_scriptFontProperties.get());
    257                     if (S_OK != hr) {
    258                         LOG_ERROR("Unable to get the font properties after second attempt");
    259                     }
    260                 }
    261             }
    262 
    263             SelectObject(dc, oldFont);
    264         }
    265     }
    266     return m_scriptFontProperties.get();
    267 }
    268 
    269 #ifndef NDEBUG
    270 String FontPlatformData::description() const
    271 {
    272     return String();
    273 }
    274 #endif
    275 
    276 bool FontPlatformData::ensureFontLoaded(HFONT font)
    277 {
    278     WebKit::WebSandboxSupport* sandboxSupport = WebKit::Platform::current()->sandboxSupport();
    279     // if there is no sandbox, then we can assume the font
    280     // was able to be loaded successfully already
    281     return sandboxSupport ? sandboxSupport->ensureFontLoaded(font) : true;
    282 }
    283 
    284 }
    285