/*
 * Copyright (C) 2020-2021 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 "DrawGlyphsRecorder.h"

#include "BitmapImage.h"
#include "Color.h"
#include "FloatPoint.h"
#include "Font.h"
#include "FontCascade.h"
#include "FontPlatformData.h"
#include "GlyphBuffer.h"
#include "GraphicsContextCG.h"

#include <CoreText/CoreText.h>
#include <wtf/Vector.h>

#if PLATFORM(WIN)
#include <pal/spi/win/CoreTextSPIWin.h>
#endif

namespace WebCore {

static CGContextDelegateRef beginLayer(CGContextDelegateRef delegate, CGRenderingStateRef rstate, CGGStateRef gstate, CGRect rect, CFDictionaryRef, CGContextDelegateRef)
{
    DrawGlyphsRecorder& recorder = *static_cast<DrawGlyphsRecorder*>(CGContextDelegateGetInfo(delegate));
    recorder.recordBeginLayer(rstate, gstate, rect);
    return delegate;
}

static CGContextDelegateRef endLayer(CGContextDelegateRef delegate, CGRenderingStateRef rstate, CGGStateRef gstate)
{
    DrawGlyphsRecorder& recorder = *static_cast<DrawGlyphsRecorder*>(CGContextDelegateGetInfo(delegate));
    recorder.recordEndLayer(rstate, gstate);
    return delegate;
}

static CGError drawGlyphs(CGContextDelegateRef delegate, CGRenderingStateRef rstate, CGGStateRef gstate, const CGAffineTransform* tm, const CGGlyph glyphs[], const CGPoint positions[], size_t count)
{
    if (CGGStateGetAlpha(gstate) > 0) {
        DrawGlyphsRecorder& recorder = *static_cast<DrawGlyphsRecorder*>(CGContextDelegateGetInfo(delegate));
        recorder.recordDrawGlyphs(rstate, gstate, tm, glyphs, positions, count);
    }
    return kCGErrorSuccess;
}

static CGError drawImage(CGContextDelegateRef delegate, CGRenderingStateRef rstate, CGGStateRef gstate, CGRect rect, CGImageRef image)
{
    DrawGlyphsRecorder& recorder = *static_cast<DrawGlyphsRecorder*>(CGContextDelegateGetInfo(delegate));
    recorder.recordDrawImage(rstate, gstate, rect, image);
    return kCGErrorSuccess;
}

UniqueRef<GraphicsContext> DrawGlyphsRecorder::createInternalContext()
{
    auto contextDelegate = adoptCF(CGContextDelegateCreate(this));
    CGContextDelegateSetCallback(contextDelegate.get(), deBeginLayer, reinterpret_cast<CGContextDelegateCallback>(&beginLayer));
    CGContextDelegateSetCallback(contextDelegate.get(), deEndLayer, reinterpret_cast<CGContextDelegateCallback>(&endLayer));
    CGContextDelegateSetCallback(contextDelegate.get(), deDrawGlyphs, reinterpret_cast<CGContextDelegateCallback>(&WebCore::drawGlyphs));
    CGContextDelegateSetCallback(contextDelegate.get(), deDrawImage, reinterpret_cast<CGContextDelegateCallback>(&drawImage));
    auto context = adoptCF(CGContextCreateWithDelegate(contextDelegate.get(), kCGContextTypeUnknown, nullptr, nullptr));
    return makeUniqueRef<GraphicsContextCG>(context.get());
}

DrawGlyphsRecorder::DrawGlyphsRecorder(GraphicsContext& owner, DeconstructDrawGlyphs deconstructDrawGlyphs, DeriveFontFromContext deriveFontFromContext)
    : m_owner(owner)
    , m_deconstructDrawGlyphs(deconstructDrawGlyphs)
    , m_deriveFontFromContext(deriveFontFromContext)
    , m_internalContext(createInternalContext())
{
}

void DrawGlyphsRecorder::populateInternalState(const GraphicsContextState& contextState)
{
    m_originalState.fillStyle.color = contextState.fillColor;
    m_originalState.fillStyle.gradient = contextState.fillGradient;
    m_originalState.fillStyle.gradientSpaceTransform = contextState.fillGradientSpaceTransform;
    m_originalState.fillStyle.pattern = contextState.fillPattern;

    m_originalState.strokeStyle.color = contextState.strokeColor;
    m_originalState.strokeStyle.gradient = contextState.strokeGradient;
    m_originalState.strokeStyle.gradientSpaceTransform = contextState.strokeGradientSpaceTransform;
    m_originalState.strokeStyle.pattern = contextState.strokePattern;

    m_originalState.ctm = m_owner.getCTM(); // FIXME: Deal with base CTM.

    m_originalState.shadow.offset = contextState.shadowOffset;
    m_originalState.shadow.blur = contextState.shadowBlur;
    m_originalState.shadow.color = contextState.shadowColor;
    m_originalState.shadow.ignoreTransforms = contextState.shadowsIgnoreTransforms;

    m_currentState = m_originalState;
}

void DrawGlyphsRecorder::populateInternalContext(const GraphicsContextState& contextState)
{
    if (m_originalState.fillStyle.color.isValid())
        m_internalContext->setFillColor(m_originalState.fillStyle.color);
    else if (m_originalState.fillStyle.gradient)
        m_internalContext->setFillGradient(*m_originalState.fillStyle.gradient, m_originalState.fillStyle.gradientSpaceTransform);
    else {
        ASSERT(m_originalState.fillStyle.pattern);
        if (m_originalState.fillStyle.pattern)
            m_internalContext->setFillPattern(*m_originalState.fillStyle.pattern);
    }

    if (m_originalState.strokeStyle.color.isValid())
        m_internalContext->setStrokeColor(m_originalState.strokeStyle.color);
    else if (m_originalState.strokeStyle.gradient)
        m_internalContext->setStrokeGradient(*m_originalState.strokeStyle.gradient, m_originalState.strokeStyle.gradientSpaceTransform);
    else {
        ASSERT(m_originalState.strokeStyle.pattern);
        if (m_originalState.strokeStyle.pattern)
            m_internalContext->setStrokePattern(*m_originalState.strokeStyle.pattern);
    }

    m_internalContext->setCTM(m_originalState.ctm);

    m_internalContext->setShadowsIgnoreTransforms(m_originalState.shadow.ignoreTransforms);
    m_internalContext->setShadow(m_originalState.shadow.offset, m_originalState.shadow.blur, m_originalState.shadow.color, contextState.shadowRadiusMode);

    m_internalContext->setTextDrawingMode(contextState.textDrawingMode);
}

void DrawGlyphsRecorder::prepareInternalContext(const Font& font, FontSmoothingMode smoothingMode)
{
    ASSERT(CGAffineTransformIsIdentity(CTFontGetMatrix(font.platformData().ctFont())));

    m_originalFont = &font;
    m_smoothingMode = smoothingMode;

    m_originalTextMatrix = computeOverallTextMatrix(font);
    if (font.platformData().orientation() == FontOrientation::Vertical)
        m_originalTextMatrix = computeVerticalTextMatrix(font, m_originalTextMatrix);

    auto& contextState = m_owner.state();
    populateInternalState(contextState);
    populateInternalContext(contextState);
}

void DrawGlyphsRecorder::concludeInternalContext()
{
    updateCTM(m_originalState.ctm);
    updateFillColor(m_originalState.fillStyle.color, m_originalState.fillStyle.gradient.get(), m_originalState.fillStyle.pattern.get());
    updateStrokeColor(m_originalState.strokeStyle.color, m_originalState.strokeStyle.gradient.get(), m_originalState.strokeStyle.pattern.get());
    updateShadow(m_originalState.shadow.offset, m_originalState.shadow.blur, m_originalState.shadow.color, m_originalState.shadow.ignoreTransforms ? ShadowsIgnoreTransforms::Yes : ShadowsIgnoreTransforms::No);
}

void DrawGlyphsRecorder::updateFillColor(const Color& newColor, Gradient* newGradient, Pattern* newPattern)
{
    // This check looks wrong but it actually isn't, for our limited use.
    // CT will only ever set this to a solid color, which this is the correct check for.
    // In concludeInternalContext() we set it back to what it was originally, which this check works correctly for too.
    if (newColor == m_currentState.fillStyle.color)
        return;

    GraphicsContextState newState;
    newState.fillColor = newColor;
    if (newGradient)
        newState.fillGradient = newGradient;
    if (newPattern)
        newState.fillPattern = newPattern;
    m_owner.didUpdateState(newState, { GraphicsContextState::FillColorChange });
    m_currentState.fillStyle.color = newColor;
}

void DrawGlyphsRecorder::updateStrokeColor(const Color& newColor, Gradient* newGradient, Pattern* newPattern)
{
    // This check looks wrong but it actually isn't, for our limited use.
    // CT will only ever set this to a solid color, which this is the correct check for.
    // In concludeInternalContext() we set it back to what it was originally, which this check works correctly for too.
    if (newColor == m_currentState.strokeStyle.color)
        return;

    GraphicsContextState newState;
    newState.strokeColor = newColor;
    if (newGradient)
        newState.strokeGradient = newGradient;
    if (newPattern)
        newState.strokePattern = newPattern;
    m_owner.didUpdateState(newState, { GraphicsContextState::StrokeColorChange });
    m_currentState.strokeStyle.color = newColor;
}

void DrawGlyphsRecorder::updateCTM(const AffineTransform& ctm)
{
    if (ctm == m_currentState.ctm)
        return;

    m_owner.setCTM(ctm);
    m_currentState.ctm = ctm;
}

static bool shadowIsCleared(const FloatSize& shadowOffset, float shadowBlur)
{
    return shadowOffset == FloatSize() && !shadowBlur;
}

void DrawGlyphsRecorder::updateShadow(const FloatSize& shadowOffset, float shadowBlur, const Color& shadowColor, ShadowsIgnoreTransforms shadowsIgnoreTransforms)
{
    // We don't need to consider shadowsIgnoreTransforms if nobody has any shadows.
    if (shadowIsCleared(shadowOffset, shadowBlur) && shadowIsCleared(m_currentState.shadow.offset, m_currentState.shadow.blur))
        return;

    GraphicsContextState newState;
    GraphicsContextState::StateChangeFlags stateChangeFlags;

    if (shadowOffset != m_currentState.shadow.offset || shadowBlur != m_currentState.shadow.blur || shadowColor != m_currentState.shadow.color) {
        newState.shadowOffset = shadowOffset;
        newState.shadowBlur = shadowBlur;
        newState.shadowColor = shadowColor;
        stateChangeFlags.add(GraphicsContextState::ShadowChange);
    }
    if (shadowsIgnoreTransforms != ShadowsIgnoreTransforms::Unspecified && (shadowsIgnoreTransforms == ShadowsIgnoreTransforms::Yes) != m_currentState.shadow.ignoreTransforms) {
        newState.shadowsIgnoreTransforms = (shadowsIgnoreTransforms == ShadowsIgnoreTransforms::Yes);
        stateChangeFlags.add(GraphicsContextState::ShadowsIgnoreTransformsChange);
    }
    if (stateChangeFlags.isEmpty())
        return;
    m_owner.didUpdateState(newState, stateChangeFlags);

    m_currentState.shadow.offset = shadowOffset;
    m_currentState.shadow.blur = shadowBlur;
    m_currentState.shadow.color = shadowColor;
    m_currentState.shadow.ignoreTransforms = (shadowsIgnoreTransforms == ShadowsIgnoreTransforms::Yes);
}

void DrawGlyphsRecorder::updateShadow(CGStyleRef style)
{
    if (CGStyleGetType(style) != kCGStyleShadow) {
        // FIXME: Support more kinds of CGStyles.
        updateShadow({0, 0}, 0, Color(), ShadowsIgnoreTransforms::Unspecified);
        return;
    }

    const auto& shadowStyle = *static_cast<const CGShadowStyle*>(CGStyleGetData(style));
    auto rad = deg2rad(shadowStyle.azimuth - 180);
    auto shadowOffset = FloatSize(std::cos(rad), std::sin(rad)) * shadowStyle.height;
    auto shadowColor = CGStyleGetColor(style);
    updateShadow(shadowOffset, shadowStyle.radius, Color::createAndPreserveColorSpace(shadowColor), ShadowsIgnoreTransforms::Yes);
}

void DrawGlyphsRecorder::recordBeginLayer(CGRenderingStateRef, CGGStateRef gstate, CGRect)
{
    updateCTM(*CGGStateGetCTM(gstate));
    auto alpha = CGGStateGetAlpha(gstate);
    m_owner.beginTransparencyLayer(alpha);
}

void DrawGlyphsRecorder::recordEndLayer(CGRenderingStateRef, CGGStateRef gstate)
{
    updateCTM(*CGGStateGetCTM(gstate));
    m_owner.endTransparencyLayer();
}

static Vector<CGSize> computeAdvancesFromPositions(const CGPoint positions[], size_t count, const CGAffineTransform& textMatrix)
{
    Vector<CGSize> result;
    for (size_t i = 0; i < count - 1; ++i) {
        auto nextPosition = positions[i + 1];
        auto currentPosition = positions[i];
        auto advance = CGSizeMake(nextPosition.x - currentPosition.x, nextPosition.y - currentPosition.y);
        result.append(CGSizeApplyAffineTransform(advance, textMatrix));
    }
    result.constructAndAppend(CGSizeMake(0, 0));
    return result;
}

void DrawGlyphsRecorder::recordDrawGlyphs(CGRenderingStateRef, CGGStateRef gstate, const CGAffineTransform*, const CGGlyph glyphs[], const CGPoint positions[], size_t count)
{
    ASSERT_IMPLIES(m_deriveFontFromContext == DeriveFontFromContext::No, m_originalFont);

    if (!count)
        return;

    CGFontRef usedFont = CGGStateGetFont(gstate);
    if (m_deriveFontFromContext == DeriveFontFromContext::No && usedFont != adoptCF(CTFontCopyGraphicsFont(m_originalFont->platformData().ctFont(), nullptr)).get())
        return;

    updateCTM(*CGGStateGetCTM(gstate));

    // We want the replayer's CTM and text matrix to match the current CTM and text matrix.
    // The current text matrix is a concatenation of whatever WebKit sets it to and whatever
    // Core Text appends to it. So, we have
    // CTM * m_originalTextMatrix * Core Text's text matrix.
    // However, CGContextGetTextMatrix() just tells us what the whole text matrix is, so
    // m_originalTextMatrix * Core Text's text matrix = currentTextMatrix.
    // The only way we can emulate Core Text's text matrix is by modifying the CTM here.
    // So, if we do that, the GPU process will have
    // CTM * X * m_originalTextMatrix
    // If you set these two equal to each other, and solve for X, you get
    // CTM * currentTextMatrix = CTM * X * m_originalTextMatrix
    // currentTextMatrix * inverse(m_originalTextMatrix) = X
    AffineTransform currentTextMatrix = CGContextGetTextMatrix(m_internalContext->platformContext());
    AffineTransform ctmFixup;
    if (auto invertedOriginalTextMatrix = m_originalTextMatrix.inverse())
        ctmFixup = currentTextMatrix * invertedOriginalTextMatrix.value();
    AffineTransform inverseCTMFixup;
    if (auto inverse = ctmFixup.inverse())
        inverseCTMFixup = inverse.value();
    else
        ctmFixup = AffineTransform();
    m_owner.concatCTM(ctmFixup);

    auto fillColor = CGGStateGetFillColor(gstate);
    auto strokeColor = CGGStateGetStrokeColor(gstate);
    updateFillColor(Color::createAndPreserveColorSpace(fillColor));
    updateStrokeColor(Color::createAndPreserveColorSpace(strokeColor));
    updateShadow(CGGStateGetStyle(gstate));

    auto fontSize = CGGStateGetFontSize(gstate);
    Ref font = m_deriveFontFromContext == DeriveFontFromContext::No ? *m_originalFont : Font::create(FontPlatformData(adoptCF(CTFontCreateWithGraphicsFont(usedFont, fontSize, nullptr, nullptr)), fontSize));

    // The above does the work of ensuring the right CTM (which is the combination of CG's CTM and
    // CG's text matrix) is set for the replayer, but in order to provide the right values to
    // `FontCascade::drawGlyphs` we need to recalculate the original advances from the resulting
    // positions by inverting the operations applied to the original advances.
    auto textMatrix = m_originalTextMatrix;
    if (font->platformData().orientation() == FontOrientation::Vertical) {
        // Keep this in sync as the inverse of `fillVectorWithVerticalGlyphPositions`.
        // FIXME: <https://webkit.org/b/232917> (`DrawGlyphsRecorder` should be able to record+replay vertical text)
    }

    m_owner.drawGlyphsAndCacheFont(font, glyphs, computeAdvancesFromPositions(positions, count, textMatrix).data(), count, textMatrix.mapPoint(positions[0]), m_smoothingMode);

    m_owner.concatCTM(inverseCTMFixup);
}

void DrawGlyphsRecorder::recordDrawImage(CGRenderingStateRef, CGGStateRef gstate, CGRect rect, CGImageRef cgImage)
{
    updateCTM(*CGGStateGetCTM(gstate));
    updateShadow(CGGStateGetStyle(gstate));

    // Core Graphics assumes a "y up" coordinate system, but in WebKit, we use a "y-down" coordinate system.
    // This means that WebKit's drawing routines (GraphicsContext::drawImage()) intentionally draw images upside-down from Core Graphics's point of view.
    // (There's a y-flip inside the implementation of GraphicsContext::drawImage().)
    // The rect has the right bounds, but we need to transform from CG's coordinate system to WebKit's by performing our own y-flip so images are drawn the right-side-up.
    // We do this at the boundary between the two APIs, which is right here.
    m_owner.translate(0, rect.size.height + 2 * rect.origin.y);
    m_owner.scale(FloatSize(1, -1));

    auto image = NativeImage::create(cgImage);
    m_owner.drawNativeImage(*image, image->size(), FloatRect(rect), FloatRect {{ }, image->size()}, ImagePaintingOptions { ImageOrientation::OriginTopLeft });

    // Undo the above y-flip to restore the context.
    m_owner.scale(FloatSize(1, -1));
    m_owner.translate(0, -(rect.size.height + 2 * rect.origin.y));
}

struct GlyphsAndAdvancesStorage {
    Vector<GlyphBufferGlyph> glyphs;
    Vector<GlyphBufferAdvance> advances;
};

struct GlyphsAndAdvances {
    const GlyphBufferGlyph* glyphs;
    const GlyphBufferAdvance* advances;
    unsigned numGlyphs;
    GlyphBufferAdvance initialAdvance;
    std::optional<GlyphsAndAdvancesStorage> storage;
};

static GlyphsAndAdvances filterOutOTSVGGlyphs(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned numGlyphs)
{
    auto otsvgGlyphs = font.findOTSVGGlyphs(glyphs, numGlyphs);
    if (!otsvgGlyphs)
        return { glyphs, advances, numGlyphs, makeGlyphBufferAdvance(), { }};

    ASSERT(otsvgGlyphs->size() >= numGlyphs);

    GlyphsAndAdvances result;
    result.initialAdvance = makeGlyphBufferAdvance();
    result.storage = GlyphsAndAdvancesStorage();

    result.storage->glyphs.reserveInitialCapacity(numGlyphs);
    result.storage->advances.reserveInitialCapacity(numGlyphs);

    for (unsigned i = 0; i < numGlyphs; ++i) {
        ASSERT(result.storage->glyphs.size() == result.storage->advances.size());
        if (otsvgGlyphs->quickGet(i)) {
            if (result.storage->advances.isEmpty())
                result.initialAdvance = makeGlyphBufferAdvance(size(result.initialAdvance) + size(advances[i]));
            else
                result.storage->advances.last() = makeGlyphBufferAdvance(size(result.storage->advances.last()) + size(advances[i]));
        } else {
            result.storage->glyphs.uncheckedAppend(glyphs[i]);
            result.storage->advances.uncheckedAppend(advances[i]);
        }
        ASSERT(result.storage->glyphs.size() == result.storage->advances.size());
    }

    result.glyphs = result.storage->glyphs.data();
    result.advances = result.storage->advances.data();
    result.numGlyphs = result.storage->glyphs.size();

    return result;
}

void DrawGlyphsRecorder::drawGlyphs(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned numGlyphs, const FloatPoint& startPoint, FontSmoothingMode smoothingMode)
{
    if (m_deconstructDrawGlyphs == DeconstructDrawGlyphs::No) {
        m_owner.drawGlyphsAndCacheFont(font, glyphs, advances, numGlyphs, startPoint, smoothingMode);
        return;
    }

    ASSERT(m_deconstructDrawGlyphs == DeconstructDrawGlyphs::Yes);

    // FIXME: <rdar://problem/70166552> Record OTSVG glyphs.
    GlyphsAndAdvances glyphsAndAdvancesWithoutOTSVGGlyphs = filterOutOTSVGGlyphs(font, glyphs, advances, numGlyphs);
    ASSERT(glyphsAndAdvancesWithoutOTSVGGlyphs.glyphs == glyphs || glyphsAndAdvancesWithoutOTSVGGlyphs.glyphs == glyphsAndAdvancesWithoutOTSVGGlyphs.storage->glyphs.data());
    ASSERT(glyphsAndAdvancesWithoutOTSVGGlyphs.advances == advances || glyphsAndAdvancesWithoutOTSVGGlyphs.advances == glyphsAndAdvancesWithoutOTSVGGlyphs.storage->advances.data());

    prepareInternalContext(font, smoothingMode);
    FontCascade::drawGlyphs(m_internalContext, font, glyphsAndAdvancesWithoutOTSVGGlyphs.glyphs, glyphsAndAdvancesWithoutOTSVGGlyphs.advances, glyphsAndAdvancesWithoutOTSVGGlyphs.numGlyphs, startPoint + size(glyphsAndAdvancesWithoutOTSVGGlyphs.initialAdvance), smoothingMode);
    concludeInternalContext();
}

void DrawGlyphsRecorder::drawNativeText(CTFontRef font, CGFloat fontSize, CTLineRef line, CGRect lineRect)
{
    ASSERT(m_deconstructDrawGlyphs == DeconstructDrawGlyphs::Yes);

    GraphicsContextStateSaver saver(m_owner);

    m_owner.translate(lineRect.origin.x, lineRect.origin.y + lineRect.size.height);
    m_owner.scale(FloatSize(1, -1));

    prepareInternalContext(Font::create(FontPlatformData(font, fontSize)), FontSmoothingMode::SubpixelAntialiased);
    CGContextSetTextPosition(m_internalContext->platformContext(), 0, 0);
    CTLineDraw(line, m_internalContext->platformContext());
    concludeInternalContext();
}

} // namespace WebCore
