/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui 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 "qstatictext.h"
#include "qstatictext_p.h"
#include <qmath.h>
#include <private/qtextengine_p.h>
#include <private/qfontengine_p.h>
#include <qabstracttextdocumentlayout.h>

QT_BEGIN_NAMESPACE

QStaticTextUserData::~QStaticTextUserData()
{
}

/*!
    \class QStaticText
    \brief The QStaticText class enables optimized drawing of text when the text and its layout
    is updated rarely.
    \since 4.7
    \inmodule QtGui

    \ingroup multimedia
    \ingroup text
    \ingroup shared

    QStaticText provides a way to cache layout data for a block of text so that it can be drawn
    more efficiently than by using QPainter::drawText() in which the layout information is
    recalculated with every call.

    The class primarily provides an optimization for cases where the text, its font and the
    transformations on the painter are static over several paint events. If the text or its layout
    is changed for every iteration, QPainter::drawText() is the more efficient alternative, since
    the static text's layout would have to be recalculated to take the new state into consideration.

    Translating the painter will not cause the layout of the text to be recalculated, but will cause
    a very small performance impact on drawStaticText(). Altering any other parts of the painter's
    transformation or the painter's font will cause the layout of the static text to be
    recalculated. This should be avoided as often as possible to maximize the performance
    benefit of using QStaticText.

    In addition, only affine transformations are supported by drawStaticText(). Calling
    drawStaticText() on a projected painter will perform slightly worse than using the regular
    drawText() call, so this should be avoided.

    \code
    class MyWidget: public QWidget
    {
    public:
        MyWidget(QWidget *parent = 0) : QWidget(parent), m_staticText("This is static text")

    protected:
        void paintEvent(QPaintEvent *)
        {
            QPainter painter(this);
            painter.drawStaticText(0, 0, m_staticText);
        }

    private:
        QStaticText m_staticText;
    };
    \endcode

    The QStaticText class can be used to mimic the behavior of QPainter::drawText() to a specific
    point with no boundaries, and also when QPainter::drawText() is called with a bounding
    rectangle.

    If a bounding rectangle is not required, create a QStaticText object without setting a preferred
    text width. The text will then occupy a single line.

    If you set a text width on the QStaticText object, this will bound the text. The text will
    be formatted so that no line exceeds the given width. The text width set for QStaticText will
    not automatically be used for clipping. To achieve clipping in addition to line breaks, use
    QPainter::setClipRect(). The position of the text is decided by the argument passed to
    QPainter::drawStaticText() and can change from call to call with a minimal impact on
    performance.

    For extra convenience, it is possible to apply formatting to the text using the HTML subset
    supported by QTextDocument. QStaticText will attempt to guess the format of the input text using
    Qt::mightBeRichText(), and interpret it as rich text if this function returns \c true. To force
    QStaticText to display its contents as either plain text or rich text, use the function
    QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and Qt::RichText.

    QStaticText can only represent text, so only HTML tags which alter the layout or appearance of
    the text will be respected. Adding an image to the input HTML, for instance, will cause the
    image to be included as part of the layout, affecting the positions of the text glyphs, but it
    will not be displayed. The result will be an empty area the size of the image in the output.
    Similarly, using tables will cause the text to be laid out in table format, but the borders
    will not be drawn.

    If it's the first time the static text is drawn, or if the static text, or the painter's font
    has been altered since the last time it was drawn, the text's layout has to be
    recalculated. On some paint engines, changing the matrix of the painter will also cause the
    layout to be recalculated. In particular, this will happen for any engine except for the
    OpenGL2 paint engine. Recalculating the layout will impose an overhead on the
    QPainter::drawStaticText() call where it occurs. To avoid this overhead in the paint event, you
    can call prepare() ahead of time to ensure that the layout is calculated.

    \sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument
*/

/*!
    \enum QStaticText::PerformanceHint

    This enum the different performance hints that can be set on the QStaticText. These hints
    can be used to indicate that the QStaticText should use additional caches, if possible,
    to improve performance at the expense of memory. In particular, setting the performance hint
    AggressiveCaching on the QStaticText will improve performance when using the OpenGL graphics
    system or when drawing to a QOpenGLWidget.

    \value ModerateCaching Do basic caching for high performance at a low memory cost.
    \value AggressiveCaching Use additional caching when available. This may improve performance
           at a higher memory cost.
*/

/*!
    Constructs an empty QStaticText
*/
QStaticText::QStaticText()
    : data(new QStaticTextPrivate)
{
}

/*!
    Constructs a QStaticText object with the given \a text.
*/
QStaticText::QStaticText(const QString &text)
    : data(new QStaticTextPrivate)
{
    data->text = text;
    data->invalidate();
}

/*!
    Constructs a QStaticText object which is a copy of \a other.
*/
QStaticText::QStaticText(const QStaticText &other)
{
    data = other.data;
}

/*!
    Destroys the QStaticText.
*/
QStaticText::~QStaticText()
{
    Q_ASSERT(!data || data->ref.loadRelaxed() >= 1);
}

/*!
    \internal
*/
void QStaticText::detach()
{
    if (data->ref.loadRelaxed() != 1)
        data.detach();
}

/*!
  Prepares the QStaticText object for being painted with the given \a matrix and the given \a font
  to avoid overhead when the actual drawStaticText() call is made.

  When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part
  of the QStaticText object has changed since the last time it was drawn. It will also be
  recalculated if the painter's font is not the same as when the QStaticText was last drawn, or,
  on any other paint engine than the OpenGL2 engine, if the painter's matrix has been altered
  since the static text was last drawn.

  To avoid the overhead of creating the layout the first time you draw the QStaticText after
  making changes, you can use the prepare() function and pass in the \a matrix and \a font you
  expect to use when drawing the text.

  \sa QPainter::setFont(), QPainter::setMatrix()
*/
void QStaticText::prepare(const QTransform &matrix, const QFont &font)
{
    data->matrix = matrix;
    data->font = font;
    data->init();
}


/*!
    Assigns \a other to this QStaticText.
*/
QStaticText &QStaticText::operator=(const QStaticText &other)
{
    data = other.data;
    return *this;
}

/*!
    \fn void QStaticText::swap(QStaticText &other)
    \since 5.0

    Swaps this static text instance with \a other. This function is
    very fast and never fails.
*/

/*!
    Compares \a other to this QStaticText. Returns \c true if the texts, fonts and text widths
    are equal.
*/
bool QStaticText::operator==(const QStaticText &other) const
{
    return (data == other.data
            || (data->text == other.data->text
                && data->font == other.data->font
                && data->textWidth == other.data->textWidth));
}

/*!
    Compares \a other to this QStaticText. Returns \c true if the texts, fonts or maximum sizes
    are different.
*/
bool QStaticText::operator!=(const QStaticText &other) const
{
    return !(*this == other);
}

/*!
    Sets the text of the QStaticText to \a text.

    \note This function will cause the layout of the text to require recalculation.

    \sa text()
*/
void QStaticText::setText(const QString &text)
{
    detach();
    data->text = text;
    data->invalidate();
}

/*!
   Sets the text format of the QStaticText to \a textFormat. If \a textFormat is set to
   Qt::AutoText (the default), the format of the text will try to be determined using the
   function Qt::mightBeRichText(). If the text format is Qt::PlainText, then the text will be
   displayed as is, whereas it will be interpreted as HTML if the format is Qt::RichText. HTML tags
   that alter the font of the text, its color, or its layout are supported by QStaticText.

   \note This function will cause the layout of the text to require recalculation.

   \sa textFormat(), setText(), text()
*/
void QStaticText::setTextFormat(Qt::TextFormat textFormat)
{
    detach();
    data->textFormat = textFormat;
    data->invalidate();
}

/*!
  Returns the text format of the QStaticText.

  \sa setTextFormat(), setText(), text()
*/
Qt::TextFormat QStaticText::textFormat() const
{
    return Qt::TextFormat(data->textFormat);
}

/*!
    Returns the text of the QStaticText.

    \sa setText()
*/
QString QStaticText::text() const
{
    return data->text;
}

/*!
  Sets the performance hint of the QStaticText according to the \a
  performanceHint provided. The \a performanceHint is used to
  customize how much caching is done internally to improve
  performance.

  The default is QStaticText::ModerateCaching.

  \note This function will cause the layout of the text to require recalculation.

  \sa performanceHint()
*/
void QStaticText::setPerformanceHint(PerformanceHint performanceHint)
{
    if ((performanceHint == ModerateCaching && !data->useBackendOptimizations)
        || (performanceHint == AggressiveCaching && data->useBackendOptimizations)) {
        return;
    }
    detach();
    data->useBackendOptimizations = (performanceHint == AggressiveCaching);
    data->invalidate();
}

/*!
  Returns which performance hint is set for the QStaticText.

  \sa setPerformanceHint()
*/
QStaticText::PerformanceHint QStaticText::performanceHint() const
{
    return data->useBackendOptimizations ? AggressiveCaching : ModerateCaching;
}

/*!
   Sets the text option structure that controls the layout process to the given \a textOption.

   \sa textOption()
*/
void QStaticText::setTextOption(const QTextOption &textOption)
{
    detach();
    data->textOption = textOption;
    data->invalidate();
}

/*!
    Returns the current text option used to control the layout process.
*/
QTextOption QStaticText::textOption() const
{
    return data->textOption;
}

/*!
    Sets the preferred width for this QStaticText. If the text is wider than the specified width,
    it will be broken into multiple lines and grow vertically. If the text cannot be split into
    multiple lines, it will be larger than the specified \a textWidth.

    Setting the preferred text width to a negative number will cause the text to be unbounded.

    Use size() to get the actual size of the text.

    \note This function will cause the layout of the text to require recalculation.

    \sa textWidth(), size()
*/
void QStaticText::setTextWidth(qreal textWidth)
{
    detach();
    data->textWidth = textWidth;
    data->invalidate();
}

/*!
    Returns the preferred width for this QStaticText.

    \sa setTextWidth()
*/
qreal QStaticText::textWidth() const
{
    return data->textWidth;
}

/*!
  Returns the size of the bounding rect for this QStaticText.

  \sa textWidth()
*/
QSizeF QStaticText::size() const
{
    if (data->needsRelayout)
        data->init();
    return data->actualSize;
}

QStaticTextPrivate::QStaticTextPrivate()
        : textWidth(-1.0), items(0), itemCount(0), glyphPool(0), positionPool(0),
          needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText),
          untransformedCoordinates(false)
{
}

QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other)
    : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix),
      items(0), itemCount(0), glyphPool(0), positionPool(0), textOption(other.textOption),
      needsRelayout(true), useBackendOptimizations(other.useBackendOptimizations),
      textFormat(other.textFormat), untransformedCoordinates(other.untransformedCoordinates)
{
}

QStaticTextPrivate::~QStaticTextPrivate()
{
    delete[] items;
    delete[] glyphPool;
    delete[] positionPool;
}

QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q)
{
    return q->data.data();
}

namespace {

    class DrawTextItemRecorder: public QPaintEngine
    {
    public:
        DrawTextItemRecorder(bool untransformedCoordinates, bool useBackendOptimizations)
                : m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations),
                  m_untransformedCoordinates(untransformedCoordinates), m_currentColor(0, 0, 0, 0)
        {
        }

        virtual void updateState(const QPaintEngineState &newState) override
        {
            if (newState.state() & QPaintEngine::DirtyPen
                && newState.pen().color() != m_currentColor) {
                m_dirtyPen = true;
                m_currentColor = newState.pen().color();
            }
        }

        virtual void drawTextItem(const QPointF &position, const QTextItem &textItem) override
        {
            const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);

            QStaticTextItem currentItem;
            currentItem.setFontEngine(ti.fontEngine);
            currentItem.font = ti.font();
            currentItem.glyphOffset = m_glyphs.size(); // Store offset into glyph pool
            currentItem.positionOffset = m_glyphs.size(); // Offset into position pool
            currentItem.useBackendOptimizations = m_useBackendOptimizations;
            if (m_dirtyPen)
                currentItem.color = m_currentColor;

            QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform();
            matrix.translate(position.x(), position.y());

            QVarLengthArray<glyph_t> glyphs;
            QVarLengthArray<QFixedPoint> positions;
            ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);

            int size = glyphs.size();
            Q_ASSERT(size == positions.size());
            currentItem.numGlyphs = size;

            m_glyphs.resize(m_glyphs.size() + size);
            m_positions.resize(m_glyphs.size());

            glyph_t *glyphsDestination = m_glyphs.data() + currentItem.glyphOffset;
            memcpy(glyphsDestination, glyphs.constData(), sizeof(glyph_t) * currentItem.numGlyphs);

            QFixedPoint *positionsDestination = m_positions.data() + currentItem.positionOffset;
            memcpy(positionsDestination, positions.constData(), sizeof(QFixedPoint) * currentItem.numGlyphs);

            m_items.append(currentItem);
        }

        virtual void drawPolygon(const QPointF *, int , PolygonDrawMode ) override
        {
            /* intentionally empty */
        }

        virtual bool begin(QPaintDevice *) override  { return true; }
        virtual bool end() override { return true; }
        virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) override {}
        virtual Type type() const override
        {
            return User;
        }

        QVector<QStaticTextItem> items() const
        {
            return m_items;
        }

        QVector<QFixedPoint> positions() const
        {
            return m_positions;
        }

        QVector<glyph_t> glyphs() const
        {
            return m_glyphs;
        }

    private:
        QVector<QStaticTextItem> m_items;
        QVector<QFixedPoint> m_positions;
        QVector<glyph_t> m_glyphs;

        bool m_dirtyPen;
        bool m_useBackendOptimizations;
        bool m_untransformedCoordinates;
        QColor m_currentColor;
    };

    class DrawTextItemDevice: public QPaintDevice
    {
    public:
        DrawTextItemDevice(bool untransformedCoordinates, bool useBackendOptimizations)
        {
            m_paintEngine = new DrawTextItemRecorder(untransformedCoordinates,
                                                     useBackendOptimizations);
        }

        ~DrawTextItemDevice()
        {
            delete m_paintEngine;
        }

        int metric(PaintDeviceMetric m) const override
        {
            int val;
            switch (m) {
            case PdmWidth:
            case PdmHeight:
            case PdmWidthMM:
            case PdmHeightMM:
                val = 0;
                break;
            case PdmDpiX:
            case PdmPhysicalDpiX:
                val = qt_defaultDpiX();
                break;
            case PdmDpiY:
            case PdmPhysicalDpiY:
                val = qt_defaultDpiY();
                break;
            case PdmNumColors:
                val = 16777216;
                break;
            case PdmDepth:
                val = 24;
                break;
            case PdmDevicePixelRatio:
                val = 1;
                break;
            case PdmDevicePixelRatioScaled:
                val = devicePixelRatioFScale();
                break;
            default:
                val = 0;
                qWarning("DrawTextItemDevice::metric: Invalid metric command");
            }
            return val;
        }

        virtual QPaintEngine *paintEngine() const override
        {
            return m_paintEngine;
        }

        QVector<glyph_t> glyphs() const
        {
            return m_paintEngine->glyphs();
        }

        QVector<QFixedPoint> positions() const
        {
            return m_paintEngine->positions();
        }

        QVector<QStaticTextItem> items() const
        {
            return m_paintEngine->items();
        }

    private:
        DrawTextItemRecorder *m_paintEngine;
    };
}

void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p, const QColor &pen)
{
    bool preferRichText = textFormat == Qt::RichText
                          || (textFormat == Qt::AutoText && Qt::mightBeRichText(text));

    if (!preferRichText) {
        QTextLayout textLayout;
        textLayout.setText(text);
        textLayout.setFont(font);
        textLayout.setTextOption(textOption);
        textLayout.setCacheEnabled(true);

        qreal height = 0;
        textLayout.beginLayout();
        while (1) {
            QTextLine line = textLayout.createLine();
            if (!line.isValid())
                break;
            line.setLeadingIncluded(true);

            if (textWidth >= 0.0)
                line.setLineWidth(textWidth);
            else
                line.setLineWidth(QFIXED_MAX);
            line.setPosition(QPointF(0.0, height));
            height += line.height();
            if (line.leading() < 0)
                height += qCeil(line.leading());
        }
        textLayout.endLayout();

        actualSize = textLayout.boundingRect().size();
        p->setPen(pen);
        textLayout.draw(p, topLeftPosition);
    } else {
        QTextDocument document;
#ifndef QT_NO_CSSPARSER
        document.setDefaultStyleSheet(QString::fromLatin1("body { color: rgba(%1, %2, %3, %4%) }")
                                      .arg(QString::number(pen.red()))
                                      .arg(QString::number(pen.green()))
                                      .arg(QString::number(pen.blue()))
                                      .arg(QString::number(pen.alpha())));
#endif
        document.setDefaultFont(font);
        document.setDocumentMargin(0.0);
#ifndef QT_NO_TEXTHTMLPARSER
        document.setHtml(text);
#else
        document.setPlainText(text);
#endif
        if (textWidth >= 0.0)
            document.setTextWidth(textWidth);
        else
            document.adjustSize();
        document.setDefaultTextOption(textOption);

        p->save();
        p->translate(topLeftPosition);
        QAbstractTextDocumentLayout::PaintContext ctx;
        ctx.palette.setColor(QPalette::Text, pen);
        document.documentLayout()->draw(p, ctx);
        p->restore();

        actualSize = document.size();
    }
}

void QStaticTextPrivate::init()
{
    delete[] items;
    delete[] glyphPool;
    delete[] positionPool;

    position = QPointF(0, 0);

    DrawTextItemDevice device(untransformedCoordinates, useBackendOptimizations);
    {
        QPainter painter(&device);
        painter.setFont(font);
        painter.setTransform(matrix);

        paintText(QPointF(0, 0), &painter, QColor(0, 0, 0, 0));
    }

    QVector<QStaticTextItem> deviceItems = device.items();
    QVector<QFixedPoint> positions = device.positions();
    QVector<glyph_t> glyphs = device.glyphs();

    itemCount = deviceItems.size();
    items = new QStaticTextItem[itemCount];

    glyphPool = new glyph_t[glyphs.size()];
    memcpy(glyphPool, glyphs.constData(), glyphs.size() * sizeof(glyph_t));

    positionPool = new QFixedPoint[positions.size()];
    memcpy(positionPool, positions.constData(), positions.size() * sizeof(QFixedPoint));

    for (int i=0; i<itemCount; ++i) {
        items[i] = deviceItems.at(i);

        items[i].glyphs = glyphPool + items[i].glyphOffset;
        items[i].glyphPositions = positionPool + items[i].positionOffset;
    }

    needsRelayout = false;
}

QT_END_NAMESPACE
