/****************************************************************************
**
** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt3D module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtGui/qrawfont.h>
#include <QtGui/qglyphrun.h>
#include <QtGui/private/qrawfont_p.h>

#include "qdistancefieldglyphcache_p.h"
#include "qtextureatlas_p.h"

#include <QtGui/qfont.h>
#include <QtGui/qpainterpath.h>
#include <QtGui/private/qdistancefield_p.h>
#include <Qt3DCore/private/qnode_p.h>
#include <Qt3DExtras/private/qtextureatlas_p.h>

QT_BEGIN_NAMESPACE

#define DEFAULT_IMAGE_PADDING 1

using namespace Qt3DCore;

namespace Qt3DExtras {

// ref-count glyphs and keep track of where they are stored
class StoredGlyph {
public:
    StoredGlyph() = default;
    StoredGlyph(const StoredGlyph &) = default;
    StoredGlyph(const QRawFont &font, quint32 glyph, bool doubleResolution);

    int refCount() const { return m_ref; }
    void ref() { ++m_ref; }
    int deref() { return m_ref = std::max(m_ref - 1, (quint32) 0); }

    bool addToTextureAtlas(QTextureAtlas *atlas);
    void removeFromTextureAtlas();

    QTextureAtlas *atlas() const { return m_atlas; }
    QRectF glyphPathBoundingRect() const { return m_glyphPathBoundingRect; }
    QRectF texCoords() const;

private:
    quint32 m_ref = 0;
    QTextureAtlas *m_atlas = nullptr;
    QTextureAtlas::TextureId m_atlasEntry = QTextureAtlas::InvalidTexture;
    QRectF m_glyphPathBoundingRect;
    QImage m_distanceFieldImage;    // only used until added to texture atlas
};

// A DistanceFieldFont stores all glyphs for a given QRawFont.
// it will use multiple QTextureAtlasess to store the distance
// fields and uses ref-counting for each glyph to ensure that
// unused glyphs are removed from the texture atlasses.
class DistanceFieldFont
{
public:
    DistanceFieldFont(const QRawFont &font, bool doubleRes, Qt3DCore::QNode *parent);
    ~DistanceFieldFont();

    StoredGlyph findGlyph(quint32 glyph) const;
    StoredGlyph refGlyph(quint32 glyph);
    void derefGlyph(quint32 glyph);

    bool doubleGlyphResolution() const { return m_doubleGlyphResolution; }

private:
    QRawFont m_font;
    bool m_doubleGlyphResolution;
    Qt3DCore::QNode *m_parentNode; // parent node for the QTextureAtlasses

    QHash<quint32, StoredGlyph> m_glyphs;

    QVector<QTextureAtlas*> m_atlasses;
};

StoredGlyph::StoredGlyph(const QRawFont &font, quint32 glyph, bool doubleResolution)
    : m_ref(1)
    , m_atlas(nullptr)
    , m_atlasEntry(QTextureAtlas::InvalidTexture)
{
    // create new single-channel distance field image for given glyph
    const QPainterPath path = font.pathForGlyph(glyph);
    const QDistanceField dfield(font, glyph, doubleResolution);
    m_distanceFieldImage = dfield.toImage(QImage::Format_Alpha8);

    // scale bounding rect down (as in QSGDistanceFieldGlyphCache::glyphData())
    const QRectF pathBound = path.boundingRect();
    float f = 1.0f / QT_DISTANCEFIELD_SCALE(doubleResolution);
    m_glyphPathBoundingRect = QRectF(pathBound.left() * f, -pathBound.top() * f, pathBound.width() * f, pathBound.height() * f);
}

bool StoredGlyph::addToTextureAtlas(QTextureAtlas *atlas)
{
    if (m_atlas || m_distanceFieldImage.isNull())
        return false;

    const auto texId = atlas->addImage(m_distanceFieldImage, DEFAULT_IMAGE_PADDING);
    if (texId != QTextureAtlas::InvalidTexture) {
        m_atlas = atlas;
        m_atlasEntry = texId;
        m_distanceFieldImage = QImage();    // free glyph image data
        return true;
    }

    return false;
}

void StoredGlyph::removeFromTextureAtlas()
{
    if (m_atlas) {
        m_atlas->removeImage(m_atlasEntry);
        m_atlas = nullptr;
        m_atlasEntry = QTextureAtlas::InvalidTexture;
    }
}

QRectF StoredGlyph::texCoords() const
{
    return m_atlas ? m_atlas->imageTexCoords(m_atlasEntry) : QRectF();
}

DistanceFieldFont::DistanceFieldFont(const QRawFont &font, bool doubleRes, Qt3DCore::QNode *parent)
    : m_font(font)
    , m_doubleGlyphResolution(doubleRes)
    , m_parentNode(parent)
{
}

DistanceFieldFont::~DistanceFieldFont()
{
    qDeleteAll(m_atlasses);
}

StoredGlyph DistanceFieldFont::findGlyph(quint32 glyph) const
{
    const auto it = m_glyphs.find(glyph);
    return (it != m_glyphs.cend()) ? it.value() : StoredGlyph();
}

StoredGlyph DistanceFieldFont::refGlyph(quint32 glyph)
{
    // if glyph already exists, just increase ref-count
    auto it = m_glyphs.find(glyph);
    if (it != m_glyphs.end()) {
        it.value().ref();
        return it.value();
    }

    // need to create new glyph
    StoredGlyph storedGlyph(m_font, glyph, m_doubleGlyphResolution);

    // see if one of the existing atlasses can hold the distance field image
    for (int i = 0; i < m_atlasses.size(); i++)
        if (storedGlyph.addToTextureAtlas(m_atlasses[i]))
            break;

    // if no texture atlas is big enough (or no exists yet), allocate a new one
    if (!storedGlyph.atlas()) {
        // this should be enough to store 40-60 glyphs, which should be sufficient for most
        // scenarios
        const int size = m_doubleGlyphResolution ? 512 : 256;

        QTextureAtlas *atlas = new QTextureAtlas(m_parentNode);
        atlas->setWidth(size);
        atlas->setHeight(size);
        atlas->setFormat(Qt3DRender::QAbstractTexture::R8_UNorm);
        atlas->setPixelFormat(QOpenGLTexture::Red);
        atlas->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear);
        atlas->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear);
        m_atlasses << atlas;

        if (!storedGlyph.addToTextureAtlas(atlas))
            qWarning() << Q_FUNC_INFO << "Couldn't add glyph to newly allocated atlas. Glyph could be huge?";
    }

    m_glyphs.insert(glyph, storedGlyph);
    return storedGlyph;
}

void DistanceFieldFont::derefGlyph(quint32 glyph)
{
    auto it = m_glyphs.find(glyph);
    if (it == m_glyphs.end())
        return;

    // TODO
    // possible optimization: keep unreferenced glyphs as the texture atlas
    // still has space. only if a new glyph needs to be allocated, and there
    // is no more space within the atlas, then we can actually remove the glyphs
    // from the atlasses.

    // remove glyph if no refs anymore
    if (it.value().deref() <= 0) {
        QTextureAtlas *atlas = it.value().atlas();
        it.value().removeFromTextureAtlas();

        // remove atlas, if it contains no glyphs anymore
        if (atlas && atlas->imageCount() == 0) {
            Q_ASSERT(m_atlasses.contains(atlas));

            m_atlasses.removeAll(atlas);
            delete atlas;
        }

        m_glyphs.erase(it);
    }
}

// copied from QSGDistanceFieldGlyphCacheManager::fontKey
// we use this function to compare QRawFonts, as QRawFont doesn't
// implement a stable comparison function
QString QDistanceFieldGlyphCache::fontKey(const QRawFont &font)
{
    QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine;
    if (!fe->faceId().filename.isEmpty()) {
        QByteArray keyName = fe->faceId().filename;
        if (font.style() != QFont::StyleNormal)
            keyName += QByteArray(" I");
        if (font.weight() != QFont::Normal)
            keyName += ' ' + QByteArray::number(font.weight());
        keyName += QByteArray(" DF");
        return QString::fromUtf8(keyName);
    } else {
        return QString::fromLatin1("%1_%2_%3_%4")
                  .arg(font.familyName())
                  .arg(font.styleName())
                  .arg(font.weight())
                  .arg(font.style());
    }
}

DistanceFieldFont* QDistanceFieldGlyphCache::getOrCreateDistanceFieldFont(const QRawFont &font)
{
    // return, if font already exists (make sure to only create one DistanceFieldFont for
    // each unique QRawFont, by building a hash on the QRawFont that ignores the font size)
    const QString key = fontKey(font);
    const auto it = m_fonts.constFind(key);
    if (it != m_fonts.cend())
        return it.value();

    // logic taken from QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache
    QRawFontPrivate *fontD = QRawFontPrivate::get(font);
    const int glyphCount = fontD->fontEngine->glyphCount();
    const bool useDoubleRes = qt_fontHasNarrowOutlines(font) && glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT();

    // only keep one FontCache with a fixed pixel size for each distinct font type
    QRawFont actualFont = font;
    actualFont.setPixelSize(QT_DISTANCEFIELD_BASEFONTSIZE(useDoubleRes) * QT_DISTANCEFIELD_SCALE(useDoubleRes));

    // create new font cache
    // we set the parent node to nullptr, since the parent node of QTextureAtlasses
    // will be set when we pass them to QText2DMaterial later
    DistanceFieldFont *dff = new DistanceFieldFont(actualFont, useDoubleRes, nullptr);
    m_fonts.insert(key, dff);
    return dff;
}

QDistanceFieldGlyphCache::QDistanceFieldGlyphCache()
    : m_rootNode(nullptr)
{
}

QDistanceFieldGlyphCache::~QDistanceFieldGlyphCache()
{
}

void QDistanceFieldGlyphCache::setRootNode(QNode *rootNode)
{
    m_rootNode = rootNode;
}

QNode *QDistanceFieldGlyphCache::rootNode() const
{
    return m_rootNode;
}

bool QDistanceFieldGlyphCache::doubleGlyphResolution(const QRawFont &font)
{
    return getOrCreateDistanceFieldFont(font)->doubleGlyphResolution();
}

namespace {
QDistanceFieldGlyphCache::Glyph refAndGetGlyph(DistanceFieldFont *dff, quint32 glyph)
{
    QDistanceFieldGlyphCache::Glyph ret;

    if (dff) {
        const auto entry = dff->refGlyph(glyph);

        if (entry.atlas()) {
            ret.glyphPathBoundingRect = entry.glyphPathBoundingRect();
            ret.texCoords = entry.texCoords();
            ret.texture = entry.atlas();
        }
    }

    return ret;
}
} // anonymous

QVector<QDistanceFieldGlyphCache::Glyph> QDistanceFieldGlyphCache::refGlyphs(const QGlyphRun &run)
{
    DistanceFieldFont *dff = getOrCreateDistanceFieldFont(run.rawFont());
    QVector<QDistanceFieldGlyphCache::Glyph> ret;

    const QVector<quint32> glyphs = run.glyphIndexes();
    for (quint32 glyph : glyphs)
        ret << refAndGetGlyph(dff, glyph);

    return ret;
}

QDistanceFieldGlyphCache::Glyph QDistanceFieldGlyphCache::refGlyph(const QRawFont &font, quint32 glyph)
{
    return refAndGetGlyph(getOrCreateDistanceFieldFont(font), glyph);
}

void QDistanceFieldGlyphCache::derefGlyphs(const QGlyphRun &run)
{
    DistanceFieldFont *dff = getOrCreateDistanceFieldFont(run.rawFont());

    const QVector<quint32> glyphs = run.glyphIndexes();
    for (quint32 glyph : glyphs)
        dff->derefGlyph(glyph);
}

void QDistanceFieldGlyphCache::derefGlyph(const QRawFont &font, quint32 glyph)
{
    getOrCreateDistanceFieldFont(font)->derefGlyph(glyph);
}

} // namespace Qt3DExtras

QT_END_NAMESPACE
