/*
 * Copyright (C) 2006, 2007 Apple Computer, Inc.
 * Copyright (c) 2006, 2007, 2008, 2009, 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "platform/fonts/FontPlatformData.h"

#include "SkTypeface.h"
#include "platform/LayoutTestSupport.h"
#include "platform/fonts/FontCache.h"
#include "platform/graphics/GraphicsContext.h"
#include <windows.h>

namespace blink {

// Maximum font size, in pixels, at which embedded bitmaps will be used
// if available.
const float kMaxSizeForEmbeddedBitmap = 24.0f;

void FontPlatformData::setupPaint(SkPaint* paint, GraphicsContext* context, const Font*) const
{
    const float ts = m_textSize >= 0 ? m_textSize : 12;
    paint->setTextSize(SkFloatToScalar(m_textSize));
    paint->setTypeface(typeface());
    paint->setFakeBoldText(m_syntheticBold);
    paint->setTextSkewX(m_syntheticItalic ? -SK_Scalar1 / 4 : 0);

    uint32_t textFlags = paintTextFlags();
    uint32_t flags = paint->getFlags();
    static const uint32_t textFlagsMask = SkPaint::kAntiAlias_Flag |
        SkPaint::kLCDRenderText_Flag |
        SkPaint::kGenA8FromLCD_Flag;
    flags &= ~textFlagsMask;

    if (ts <= kMaxSizeForEmbeddedBitmap)
        flags |= SkPaint::kEmbeddedBitmapText_Flag;

    if (ts >= m_minSizeForAntiAlias) {

        if (m_useSubpixelPositioning
            // Disable subpixel text for certain older fonts at smaller sizes as
            // they tend to get quite blurry at non-integer sizes and positions.
            // For high-DPI this workaround isn't required.
            && (ts >= m_minSizeForSubpixel
                || FontCache::fontCache()->deviceScaleFactor() >= 1.5)

            // Subpixel text positioning looks pretty bad without font
            // smoothing. Disable it unless some type of font smoothing is used.
            // As most tests run without font smoothing we enable it for tests
            // to ensure we get good test coverage matching the more common
            // smoothing enabled behavior.
            && ((textFlags & SkPaint::kAntiAlias_Flag)
                || LayoutTestSupport::isRunningLayoutTest()))
            flags |= SkPaint::kSubpixelText_Flag;

        // Only set painting flags when we're actually painting.
        if (context && !context->couldUseLCDRenderedText()) {
            textFlags &= ~SkPaint::kLCDRenderText_Flag;
            // If we *just* clear our request for LCD, then GDI seems to
            // sometimes give us AA text, and sometimes give us BW text. Since the
            // original intent was LCD, we want to force AA (rather than BW), so we
            // add a special bit to tell Skia to do its best to avoid the BW: by
            // drawing LCD offscreen and downsampling that to AA.
            textFlags |= SkPaint::kGenA8FromLCD_Flag;
        }
        SkASSERT(!(textFlags & ~textFlagsMask));
        flags |= textFlags;
    }

    paint->setFlags(flags);
}

// Lookup the current system settings for font smoothing.
// We cache these values for performance, but if the browser has a way to be
// notified when these change, we could re-query them at that time.
static uint32_t getSystemTextFlags()
{
    static bool gInited;
    static uint32_t gFlags;
    if (!gInited) {
        BOOL enabled;
        gFlags = 0;
        if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &enabled, 0)) {
            if (enabled) {
                gFlags |= SkPaint::kAntiAlias_Flag;

                UINT smoothType;
                if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &smoothType, 0)) {
                    if (FE_FONTSMOOTHINGCLEARTYPE == smoothType)
                        gFlags |= SkPaint::kLCDRenderText_Flag;
                }
            }
        } else {
            // SystemParametersInfo will fail only under full sandbox lockdown on Win8+.
            // So, we default to settings we know are supported and look good.
            // FIXME(eae): We should be querying the DirectWrite settings directly
            // so we can respect the settings for users who turn off smoothing.
            gFlags = SkPaint::kAntiAlias_Flag | SkPaint::kLCDRenderText_Flag;
        }
        gInited = true;
    }
    return gFlags;
}

static bool isWebFont(const String& familyName)
{
    // Web-fonts have artifical names constructed to always be:
    // 1. 24 characters, followed by a '\0'
    // 2. the last two characters are '=='
    return familyName.length() == 24
        && '=' == familyName[22] && '=' == familyName[23];
}

static int computePaintTextFlags(String fontFamilyName)
{
    if (LayoutTestSupport::isRunningLayoutTest())
        return LayoutTestSupport::isFontAntialiasingEnabledForTest() ? SkPaint::kAntiAlias_Flag : 0;

    int textFlags = getSystemTextFlags();

    // Many web-fonts are so poorly hinted that they are terrible to read when drawn in BW.
    // In these cases, we have decided to FORCE these fonts to be drawn with at least grayscale AA,
    // even when the System (getSystemTextFlags) tells us to draw only in BW.
    if (isWebFont(fontFamilyName))
        textFlags |= SkPaint::kAntiAlias_Flag;

    return textFlags;
}


void FontPlatformData::querySystemForRenderStyle(bool)
{
    m_paintTextFlags = computePaintTextFlags(fontFamilyName());
}

bool FontPlatformData::defaultUseSubpixelPositioning()
{
    return FontCache::fontCache()->useSubpixelPositioning();
}

} // namespace blink
