/*
  SPDX-FileCopyrightText: 2008 Brad Hards <bradh@frogmouth.net>
  SPDX-FileCopyrightText: 2009 Inge Wallin <inge@lysator.liu.se>

  SPDX-License-Identifier: LGPL-2.1-or-later
*/

#ifndef EMFRECORDS_H
#define EMFRECORDS_H

#include <QColor>
#include <QDataStream>
#include <QImage>
#include <QRect> // also provides QSize
#include <QString>

#include "Bitmap.h"
/**
   \file

   Primary definitions for EMF Records
*/

/**
   Namespace for Enhanced Metafile (EMF) classes
*/
namespace Libemf
{

class EmrTextObject;

/*****************************************************************************/

/**
    Simple representation of an EMR_BITBLT record

    See MS-EMF Section 2.3.1.2 for details
*/
class BitBltRecord
{
public:
    /**
       Constructor for record type

       \param stream the stream to read the record structure from
       \param recordSize the record size
    */
    BitBltRecord(QDataStream &stream, quint32 recordSize);
    ~BitBltRecord();

    /**
        The X origin of the destination rectangle
     */
    qint32 xDest() const
    {
        return m_xDest;
    };

    /**
       The Y origin of the destination rectangle
    */
    qint32 yDest() const
    {
        return m_yDest;
    };

    /**
       The width of the destination rectangle
    */
    qint32 cxDest() const
    {
        return m_cxDest;
    };

    /**
       The height of the destination rectangle
    */
    qint32 cyDest() const
    {
        return m_cyDest;
    };

    quint32 rasterOperation() const
    {
        return m_BitBltRasterOperation;
    }

    QColor bkColorSrc() const
    {
        return QColor(m_red, m_green, m_blue, m_reserved);
    }

    /**
       The destination rectangle
    */
    QRect destinationRectangle() const
    {
        return QRect(xDest(), yDest(), cxDest(), cyDest());
    };

    /**
       The image to display
    */
    QImage image();

    /**
       Whether there is a valid image in this BitBlt record
    */
    bool hasImage() const;

private:
    // No copying for now, because we will get into trouble with the pointers.
    // The remedy is to write a real operator=() and BitBltRecord(BitBltRecord&).
    explicit BitBltRecord(BitBltRecord &) = delete;
    BitBltRecord &operator=(BitBltRecord &) = delete;

private:
    QRect m_bounds;
    qint32 m_xDest;
    qint32 m_yDest;
    qint32 m_cxDest;
    qint32 m_cyDest;
    quint32 m_BitBltRasterOperation;
    qint32 m_xSrc;
    qint32 m_ySrc;
    QTransform m_XFormSrc;

    // Background color - elements below
    quint8 m_red;
    quint8 m_green;
    quint8 m_blue;
    quint8 m_reserved;

    // Color table interpretation
    quint32 m_UsageSrc;

    // The source bitmap meta data
    quint32 m_offBmiSrc;
    quint32 m_cbBmiSrc;
    quint32 m_offBitsSrc;
    quint32 m_cbBitsSrc;

    Bitmap *m_bitmap; // The source bitmap

    // QByteArray m_imageData;
    // QImage *m_image;
};

/*****************************************************************************/

/**
    Simple representation of an EMR_STRETCHDIBITS record

    See MS-EMF Section 2.3.1.7 for details
*/
class StretchDiBitsRecord
{
public:
    /**
       Constructor for record type

       \param stream the stream to read the record structure from
       \param recordSize the record size
    */
    StretchDiBitsRecord(QDataStream &stream, quint32 recordSize);
    ~StretchDiBitsRecord();

    /**
       The bounds of the affected area, in device units
    */
    QRect bounds() const;

    /**
       The X origin of the destination rectangle
    */
    qint32 xDest() const
    {
        return m_xDest;
    };

    /**
       The Y origin of the destination rectangle
    */
    qint32 yDest() const
    {
        return m_yDest;
    };

    /**
       The width of the destination rectangle
    */
    qint32 cxDest() const
    {
        return m_cxDest;
    };

    /**
       The height of the destination rectangle
    */
    qint32 cyDest() const
    {
        return m_cyDest;
    };

    /**
       The destination rectangle
    */
    QRect destinationRectangle() const
    {
        return QRect(xDest(), yDest(), cxDest(), cyDest());
    };

    /**
       The X origin of the source rectangle
    */
    qint32 xSrc() const
    {
        return m_xSrc;
    };

    /**
       The Y origin of the source rectangle
    */
    qint32 ySrc() const
    {
        return m_ySrc;
    };

    /**
       The width of the source rectangle
    */
    qint32 cxSrc() const
    {
        return m_cxSrc;
    };

    /**
       The height of the source rectangle
    */
    qint32 cySrc() const
    {
        return m_cySrc;
    };

    /**
       The source rectangle
    */
    QRect sourceRectangle() const
    {
        return QRect(xSrc(), ySrc(), cxSrc(), cySrc());
    };

    /**
       The raster operation
    */
    qint32 rasterOperation() const
    {
        return m_BitBltRasterOperation;
    };

    quint32 usageSrc() const
    {
        return m_UsageSrc;
    };

    /**
       The image to display
    */
    QImage image();
    /**
       Whether there is a valid image in this StretchDiBitsRecord record
    */
    bool hasImage() const;

private:
    // No copying for now, because we will get into trouble with the pointers.
    // The remedy is to write a real operator=() and StretchDiBitsRecord(StretchDiBitsRecord&).
    explicit StretchDiBitsRecord(StretchDiBitsRecord &) = delete;
    StretchDiBitsRecord &operator=(StretchDiBitsRecord &) = delete;

private:
    QRect m_Bounds;
    qint32 m_xDest;
    qint32 m_yDest;
    qint32 m_xSrc;
    qint32 m_ySrc;
    qint32 m_cxSrc;
    qint32 m_cySrc;
    quint32 m_offBmiSrc;
    quint32 m_cbBmiSrc;
    quint32 m_offBitsSrc;
    quint32 m_cbBitsSrc;
    quint32 m_UsageSrc;
    quint32 m_BitBltRasterOperation;
    qint32 m_cxDest;
    qint32 m_cyDest;

    Bitmap *m_bitmap; // The source bitmap
};

/*****************************************************************************/

/**
    Simple representation of an EMR_EXTCREATEFONTINDIRECTW record

    See MS-EMF Section 2.3.7.8 for details
*/
class ExtCreateFontIndirectWRecord
{
public:
    /**
       Constructor for record type

       \param stream the stream to read the record structure from
       \param size the number of bytes in this record
    */
    ExtCreateFontIndirectWRecord(QDataStream &stream, quint32 size);
    ~ExtCreateFontIndirectWRecord();

    /**
       The font handle index
    */
    quint32 ihFonts() const
    {
        return m_ihFonts;
    };

    /**
       The height of the font
    */
    qint32 height() const
    {
        return m_height;
    };

    /**
       Whether this is a italic font
    */
    quint8 italic() const
    {
        return m_italic;
    };

    /**
       Whether this is a underlined font
    */
    quint8 underline() const
    {
        return m_underline;
    };

    /**
       The weight of this font
    */
    quint32 weight() const
    {
        return m_weight;
    };

    /**
       The name of the font face
    */
    QString fontFace() const
    {
        return m_facename;
    };

private:
    quint32 m_ihFonts;

    qint32 m_height;
    qint32 m_width;
    qint32 m_escapement;
    qint32 m_orientation;
    qint32 m_weight;
    quint8 m_italic;
    quint8 m_underline;
    quint8 m_strikeout;
    quint8 m_charSet;
    quint8 m_outPrecision;
    quint8 m_clipPrecision;
    quint8 m_quality;
    quint8 m_pitchAndFamily;
    QString m_facename;
    QString m_fullName;
    QString m_style;
    QString m_script;

    // Routine to throw away a specific number of bytes
    void soakBytes(QDataStream &stream, int numBytes);
};

}

#endif
