/*
 * Copyright (C) 2016 Apple 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "Font.h"

#if USE(DIRECT2D)

#include "DirectWriteUtilities.h"
#include "FloatRect.h"
#include "FontCache.h"
#include "FontDescription.h"
#include "GlyphPage.h"
#include "GraphicsContext.h"
#include "HWndDC.h"
#include "NotImplemented.h"
#include <comutil.h>
#include <dwrite_3.h>
#include <mlang.h>
#include <unicode/uchar.h>
#include <unicode/unorm.h>
#include <winsock2.h>
#include <wtf/MathExtras.h>
#include <wtf/RetainPtr.h>
#include <wtf/text/WTFString.h>

namespace WebCore {

static Vector<WCHAR> getFaceName(IDWriteFont* font)
{
    if (!font)
        return Vector<WCHAR>();

    COMPtr<IDWriteLocalizedStrings> localizedFaceNames;
    HRESULT hr = font->GetFaceNames(&localizedFaceNames);
    RELEASE_ASSERT(SUCCEEDED(hr));

    UINT32 localeIndex = 0;
    BOOL exists = false;

    wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
    int localeLength = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH);
    if (localeLength)
        hr = localizedFaceNames->FindLocaleName(localeName, &localeIndex, &exists);

    if (!exists || !SUCCEEDED(hr))
        hr = localizedFaceNames->FindLocaleName(L"en-us", &localeIndex, &exists);

    if (!exists || !SUCCEEDED(hr))
        localeIndex = 0;

    UINT32 faceNameLength = 0;
    hr = localizedFaceNames->GetStringLength(localeIndex, &faceNameLength);
    if (!SUCCEEDED(hr))
        return Vector<WCHAR>();

    Vector<WCHAR> faceName(faceNameLength + 1);
    hr = localizedFaceNames->GetString(localeIndex, faceName.data(), faceName.size());

    return faceName;
}

void Font::platformInit()
{
    m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;
    m_scriptCache = 0;
    m_scriptFontProperties = 0;

    if (m_platformData.useGDI())
        return initGDIFont();

    float pointSize = m_platformData.size();

    auto font = m_platformData.dwFont();
    RELEASE_ASSERT(font);

    auto fontFace = m_platformData.dwFontFace();
    RELEASE_ASSERT(fontFace);

    DWRITE_FONT_METRICS fontMetrics;
    font->GetMetrics(&fontMetrics);

    int iAscent = fontMetrics.ascent;
    int iDescent = fontMetrics.descent;
    int iLineGap = fontMetrics.lineGap;
    int iCapHeight = fontMetrics.capHeight;

    unsigned unitsPerEm = fontMetrics.designUnitsPerEm;
    float fAscent = scaleEmToUnits(iAscent, unitsPerEm) * pointSize;
    float fDescent = scaleEmToUnits(iDescent, unitsPerEm) * pointSize;
    float fCapHeight = scaleEmToUnits(iCapHeight, unitsPerEm) * pointSize;
    float fLineGap = scaleEmToUnits(iLineGap, unitsPerEm) * pointSize;

    if (origin() == Origin::Local) {
        Vector<WCHAR> faceName = getFaceName(font);
        fAscent = ascentConsideringMacAscentHack(faceName.data(), fAscent, fDescent);
    }

    m_fontMetrics.setAscent(fAscent);
    m_fontMetrics.setDescent(fDescent);
    m_fontMetrics.setCapHeight(fCapHeight);
    m_fontMetrics.setLineGap(fLineGap);
    m_fontMetrics.setLineSpacing(lroundf(fAscent) + lroundf(fDescent) + lroundf(fLineGap));

    Glyph xGlyph = glyphDataForCharacter('x').glyph;

    if (xGlyph) {
        // Measure the actual character "x", since it's possible for it to extend below the baseline, and we need the
        // reported x-height to only include the portion of the glyph that is above the baseline.
        Vector<DWRITE_GLYPH_METRICS> glyphMetrics(1);
        HRESULT hr = fontFace->GetDesignGlyphMetrics(&xGlyph, 1, glyphMetrics.data(), m_platformData.orientation() == FontOrientation::Vertical);
        RELEASE_ASSERT(SUCCEEDED(hr));
        m_fontMetrics.setXHeight(scaleEmToUnits(glyphMetrics.first().verticalOriginY, unitsPerEm) * pointSize);
    } else {
        int iXHeight = fontMetrics.xHeight;
        m_fontMetrics.setXHeight(scaleEmToUnits(iXHeight, unitsPerEm) * pointSize);
    }

    m_fontMetrics.setUnitsPerEm(unitsPerEm);
}

FloatRect Font::platformBoundsForGlyph(Glyph glyph) const
{
    if (!platformData().size())
        return FloatRect();

    if (m_platformData.useGDI())
        return boundsForGDIGlyph(glyph);

    auto font = m_platformData.dwFont();
    RELEASE_ASSERT(font);

    auto fontFace = m_platformData.dwFontFace();
    RELEASE_ASSERT(fontFace);

    float pointSize = m_platformData.size();
    bool vertical = m_platformData.orientation() == FontOrientation::Vertical;

    Vector<DWRITE_GLYPH_METRICS> glyphMetrics(1);
    HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyph, 1, glyphMetrics.data(), m_platformData.orientation() == FontOrientation::Vertical);
    RELEASE_ASSERT(SUCCEEDED(hr));

    const auto& metrics = glyphMetrics.first();

    unsigned unitsPerEm = m_fontMetrics.unitsPerEm();

    FloatPoint origin(scaleEmToUnits(metrics.leftSideBearing, unitsPerEm) * pointSize, scaleEmToUnits(metrics.verticalOriginY, unitsPerEm) * pointSize);
    FloatSize size(scaleEmToUnits(metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing, unitsPerEm) * pointSize,
        scaleEmToUnits(metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing, unitsPerEm) * pointSize);

    FloatRect boundingBox(origin, size);
    if (m_syntheticBoldOffset)
        boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset);

    return boundingBox;
}

float Font::platformWidthForGlyph(Glyph glyph) const
{
    if (!platformData().size())
        return 0;

    if (m_platformData.useGDI())
        return widthForGDIGlyph(glyph);

    auto font = m_platformData.dwFont();
    RELEASE_ASSERT(font);

    auto fontFace = m_platformData.dwFontFace();
    RELEASE_ASSERT(fontFace);

    bool isVertical = m_platformData.orientation() == FontOrientation::Vertical;

    Vector<DWRITE_GLYPH_METRICS> glyphMetrics(1);
    HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyph, 1, glyphMetrics.data(), isVertical);
    RELEASE_ASSERT(SUCCEEDED(hr));

    const auto& metrics = glyphMetrics.first();
    int widthInEm = metrics.advanceWidth;

    float pointSize = m_platformData.size();
    unsigned unitsPerEm = m_fontMetrics.unitsPerEm();
    float width = scaleEmToUnits(widthInEm, unitsPerEm) * pointSize;

    return width + m_syntheticBoldOffset;
}

Path Font::platformPathForGlyph(Glyph) const
{
    notImplemented();
    return Path();
}

}

#endif
