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 "platform/fonts/FontPlatformData.h"
34
35#include "SkTypeface.h"
36#include "platform/LayoutTestSupport.h"
37#include "platform/fonts/FontCache.h"
38#include "platform/graphics/GraphicsContext.h"
39#include <windows.h>
40
41namespace WebCore {
42
43// Maximum font size, in pixels, at which embedded bitmaps will be used
44// if available.
45const float kMaxSizeForEmbeddedBitmap = 24.0f;
46
47void FontPlatformData::setupPaint(SkPaint* paint, GraphicsContext* context) const
48{
49    const float ts = m_textSize >= 0 ? m_textSize : 12;
50    paint->setTextSize(SkFloatToScalar(m_textSize));
51    paint->setTypeface(typeface());
52    paint->setFakeBoldText(m_syntheticBold);
53    paint->setTextSkewX(m_syntheticItalic ? -SK_Scalar1 / 4 : 0);
54
55    uint32_t textFlags = paintTextFlags();
56    uint32_t flags = paint->getFlags();
57    static const uint32_t textFlagsMask = SkPaint::kAntiAlias_Flag |
58        SkPaint::kLCDRenderText_Flag |
59        SkPaint::kGenA8FromLCD_Flag;
60    flags &= ~textFlagsMask;
61
62    if (ts <= kMaxSizeForEmbeddedBitmap)
63        flags |= SkPaint::kEmbeddedBitmapText_Flag;
64
65    if (ts >= m_minSizeForAntiAlias) {
66        if (m_useSubpixelPositioning)
67            flags |= SkPaint::kSubpixelText_Flag;
68
69        // Only set painting flags when we're actually painting.
70        if (context && !context->couldUseLCDRenderedText()) {
71            textFlags &= ~SkPaint::kLCDRenderText_Flag;
72            // If we *just* clear our request for LCD, then GDI seems to
73            // sometimes give us AA text, and sometimes give us BW text. Since the
74            // original intent was LCD, we want to force AA (rather than BW), so we
75            // add a special bit to tell Skia to do its best to avoid the BW: by
76            // drawing LCD offscreen and downsampling that to AA.
77            textFlags |= SkPaint::kGenA8FromLCD_Flag;
78        }
79        SkASSERT(!(textFlags & ~textFlagsMask));
80        flags |= textFlags;
81    }
82
83    paint->setFlags(flags);
84}
85
86// Lookup the current system settings for font smoothing.
87// We cache these values for performance, but if the browser has a way to be
88// notified when these change, we could re-query them at that time.
89static uint32_t getSystemTextFlags()
90{
91    static bool gInited;
92    static uint32_t gFlags;
93    if (!gInited) {
94        BOOL enabled;
95        gFlags = 0;
96        if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0)) {
97            if (enabled) {
98                gFlags |= SkPaint::kAntiAlias_Flag;
99
100                UINT smoothType;
101                if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smoothType, 0)) {
102                    if (FE_FONTSMOOTHINGCLEARTYPE == smoothType)
103                        gFlags |= SkPaint::kLCDRenderText_Flag;
104                }
105            }
106        } else {
107            // SystemParametersInfo will fail only under full sandbox lockdown on Win8+.
108            // So, we default to settings we know are supported and look good.
109            // FIXME(eae): We should be querying the DirectWrite settings directly
110            // so we can respect the settings for users who turn off smoothing.
111            gFlags = SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag;
112        }
113        gInited = true;
114    }
115    return gFlags;
116}
117
118static bool isWebFont(const String& familyName)
119{
120    // Web-fonts have artifical names constructed to always be:
121    // 1. 24 characters, followed by a '\0'
122    // 2. the last two characters are '=='
123    return familyName.length() == 24
124        && '=' == familyName[22] && '=' == familyName[23];
125}
126
127static int computePaintTextFlags(String fontFamilyName)
128{
129    if (isRunningLayoutTest())
130        return isFontAntialiasingEnabledForTest() ? SkPaint::kAntiAlias_Flag : 0;
131
132    int textFlags = getSystemTextFlags();
133
134    // Many web-fonts are so poorly hinted that they are terrible to read when drawn in BW.
135    // In these cases, we have decided to FORCE these fonts to be drawn with at least grayscale AA,
136    // even when the System (getSystemTextFlags) tells us to draw only in BW.
137    if (isWebFont(fontFamilyName))
138        textFlags |= SkPaint::kAntiAlias_Flag;
139
140    return textFlags;
141}
142
143
144void FontPlatformData::querySystemForRenderStyle(bool)
145{
146    m_paintTextFlags = computePaintTextFlags(fontFamilyName());
147}
148
149bool FontPlatformData::defaultUseSubpixelPositioning()
150{
151    return FontCache::fontCache()->useSubpixelPositioning();
152}
153
154} // namespace WebCore
155