/*
 * Copyright (C) 2022 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 "GlyphDisplayListCache.h"

#include "DisplayListItems.h"
#include "DisplayListIterator.h"

namespace WebCore {

static bool canShareDisplayListWithItem(DisplayList::ItemType itemType)
{
    using DisplayList::ItemType;

    switch (itemType) {
    case ItemType::Translate:
    case ItemType::Scale:
    case ItemType::ConcatenateCTM:
    case ItemType::DrawDecomposedGlyphs:
    case ItemType::DrawImageBuffer:
    case ItemType::DrawNativeImage:
    case ItemType::BeginTransparencyLayer:
    case ItemType::EndTransparencyLayer:
        return true;
    case ItemType::Save:
    case ItemType::Restore:
    case ItemType::Rotate:
    case ItemType::SetCTM:
    case ItemType::SetInlineFillColor:
    case ItemType::SetInlineStrokeColor:
    case ItemType::SetStrokeThickness:
    case ItemType::SetState:
    case ItemType::SetLineCap:
    case ItemType::SetLineDash:
    case ItemType::SetLineJoin:
    case ItemType::SetMiterLimit:
    case ItemType::ClearShadow:
    case ItemType::Clip:
    case ItemType::ClipOut:
    case ItemType::ClipToImageBuffer:
    case ItemType::ClipOutToPath:
    case ItemType::ClipPath:
    case ItemType::DrawFilteredImageBuffer:
    case ItemType::DrawSystemImage:
    case ItemType::DrawGlyphs:
    case ItemType::DrawPattern:
    case ItemType::DrawRect:
    case ItemType::DrawLine:
    case ItemType::DrawLinesForText:
    case ItemType::DrawDotsForDocumentMarker:
    case ItemType::DrawEllipse:
    case ItemType::DrawPath:
    case ItemType::DrawFocusRingPath:
    case ItemType::DrawFocusRingRects:
    case ItemType::FillRect:
    case ItemType::FillRectWithColor:
    case ItemType::FillRectWithGradient:
    case ItemType::FillCompositedRect:
    case ItemType::FillRoundedRect:
    case ItemType::FillRectWithRoundedHole:
#if ENABLE(INLINE_PATH_DATA)
    case ItemType::FillLine:
    case ItemType::FillArc:
    case ItemType::FillQuadCurve:
    case ItemType::FillBezierCurve:
#endif
    case ItemType::FillPath:
    case ItemType::FillEllipse:
#if ENABLE(VIDEO)
    case ItemType::PaintFrameForMedia:
#endif
    case ItemType::StrokeRect:
    case ItemType::StrokeLine:
#if ENABLE(INLINE_PATH_DATA)
    case ItemType::StrokeArc:
    case ItemType::StrokeQuadCurve:
    case ItemType::StrokeBezierCurve:
#endif
    case ItemType::StrokePath:
    case ItemType::StrokeEllipse:
    case ItemType::ClearRect:
#if USE(CG)
    case ItemType::ApplyStrokePattern:
    case ItemType::ApplyFillPattern:
#endif
    case ItemType::ApplyDeviceScaleFactor:
        return false;
    }
    ASSERT_NOT_REACHED();
    return false;
}

struct GlyphDisplayListCacheKey {
    const TextRun& textRun;
    const FontCascade& font;
    GraphicsContext& context;
};

static void add(Hasher& hasher, const GlyphDisplayListCacheKey& key)
{
    add(hasher, key.textRun, key.context.scaleFactor().width(), key.context.scaleFactor().height(), key.font.generation(), key.context.shouldSubpixelQuantizeFonts());
}

struct GlyphDisplayListCacheKeyTranslator {
    static unsigned hash(const GlyphDisplayListCacheKey& key)
    {
        return computeHash(key);
    }

    static bool equal(GlyphDisplayListCacheEntry* entry, const GlyphDisplayListCacheKey& key)
    {
        return entry->m_textRun == key.textRun
            && entry->m_scaleFactor == key.context.scaleFactor()
            && entry->m_fontCascadeGeneration == key.font.generation()
            && entry->m_shouldSubpixelQuantizeFont == key.context.shouldSubpixelQuantizeFonts();
    }
};

GlyphDisplayListCache& GlyphDisplayListCache::singleton()
{
    static NeverDestroyed<GlyphDisplayListCache> cache;
    return cache;
}

void GlyphDisplayListCache::clear()
{
    m_entriesForLayoutRun.clear();
    m_entries.clear();
}

unsigned GlyphDisplayListCache::size() const
{
    return m_entries.size();
}

size_t GlyphDisplayListCache::sizeInBytes() const
{
    size_t sizeInBytes = 0;
    for (auto entry : m_entries)
        sizeInBytes += entry->displayList().sizeInBytes();
    return sizeInBytes;
}

DisplayList::DisplayList* GlyphDisplayListCache::get(const void* run, const FontCascade& font, GraphicsContext& context, const TextRun& textRun)
{
    if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) {
        if (!m_entries.isEmpty()) {
            LOG(MemoryPressure, "GlyphDisplayListCache::%s - Under memory pressure - size: %d - sizeInBytes: %ld", __FUNCTION__, size(), sizeInBytes());
            clear();
        }
        return nullptr;
    }

    if (font.isLoadingCustomFonts() || !font.fonts())
        return nullptr;

    if (auto entry = m_entriesForLayoutRun.get(run))
        return &entry->displayList();

    if (auto entry = m_entries.find<GlyphDisplayListCacheKeyTranslator>(GlyphDisplayListCacheKey { textRun, font, context }); entry != m_entries.end())
        return &m_entriesForLayoutRun.add(run, Ref { **entry }).iterator->value->displayList();

    if (auto displayList = font.displayListForTextRun(context, textRun)) {
        auto entry = GlyphDisplayListCacheEntry::create(WTFMove(displayList), textRun, font, context);
        if (canShareDisplayList(entry->displayList()))
            m_entries.add(entry.ptr());
        return &m_entriesForLayoutRun.add(run, WTFMove(entry)).iterator->value->displayList();
    }

    return nullptr;
}

DisplayList::DisplayList* GlyphDisplayListCache::getIfExists(const void* run)
{
    if (auto entry = m_entriesForLayoutRun.get(run))
        return &entry->displayList();
    return nullptr;
}

void GlyphDisplayListCache::remove(const void* run)
{
    m_entriesForLayoutRun.remove(run);
}

bool GlyphDisplayListCache::canShareDisplayList(const DisplayList::InMemoryDisplayList& displayList)
{
    for (auto displayListItem : displayList) {
        if (!canShareDisplayListWithItem(displayListItem.value().item.type()))
            return false;
    }
    return true;
}

GlyphDisplayListCacheEntry::~GlyphDisplayListCacheEntry()
{
    GlyphDisplayListCache::singleton().m_entries.remove(this);
}

} // namespace WebCore
