//========================================================================
//
// MarkedContentOutputDev.h
//
// This file is licensed under the GPLv2 or later
//
// Copyright 2013 Igalia S.L.
// Copyright 2018 Albert Astals Cid <aacid@kde.org>
//
//========================================================================

#ifndef MARKEDCONTENTOUTPUTDEV_H
#define MARKEDCONTENTOUTPUTDEV_H

#include "goo/gmem.h"
#include "OutputDev.h"
#include "GfxState.h"
#include "GfxFont.h"
#include <vector>

class Dict;
class UnicodeMap;


class TextSpan {
public:
  TextSpan(const TextSpan& other): data(other.data) {
    data->refcount++;
  }

  TextSpan& operator=(const TextSpan& other) {
    if (this != &other) {
      data = other.data;
      data->refcount++;
    }
    return *this;
  }

  ~TextSpan() {
    if (data && --data->refcount == 0)
      delete data;
  }

  GfxFont* getFont() const { return data->font; }
  GooString* getText() const { return data->text; }
  GfxRGB& getColor() const { return data->color; }

private:
  // Note: Takes ownership of strings, increases refcount for font.
  TextSpan(GooString *text,
           GfxFont *font,
           const GfxRGB color)
      : data(new Data) {
    data->text = text;
    data->font = font;
    data->color = color;
    if (data->font)
      data->font->incRefCnt();
  }

  struct Data {
    GfxFont   *font;
    GooString *text;
    GfxRGB     color;
    unsigned refcount;

    Data(): refcount(1) {}

    ~Data() {
      assert(refcount == 0);
      if (font)
        font->decRefCnt();
      delete text;
    }

    Data(const Data &) = delete;
    Data& operator=(const Data &) = delete;
  };

  Data *data;

  friend class MarkedContentOutputDev;
};


typedef std::vector<TextSpan> TextSpanArray;


class MarkedContentOutputDev: public OutputDev {
public:
  MarkedContentOutputDev(int mcidA);
  virtual ~MarkedContentOutputDev();

  virtual bool isOk() { return true; }
  bool upsideDown() override { return true; }
  bool useDrawChar() override { return true; }
  bool interpretType3Chars() override { return false; }
  bool needNonText() override { return false; }
  bool needCharCount() override { return false; }

  void startPage(int pageNum, GfxState *state, XRef *xref) override;
  void endPage() override;

  void drawChar(GfxState *state,
                        double xx, double yy,
                        double dx, double dy,
                        double ox, double oy,
                        CharCode c, int nBytes,
                        Unicode *u, int uLen) override;

  void beginMarkedContent(const char *name, Dict *properties) override;
  void endMarkedContent(GfxState *state) override;

  const TextSpanArray& getTextSpans() const;

private:

  void endSpan();
  bool inMarkedContent() const { return mcidStack.size() > 0; }
  bool needFontChange(const GfxFont* font) const;

  GfxFont         *currentFont;
  GooString       *currentText;
  GfxRGB           currentColor;
  TextSpanArray    textSpans;
  int              mcid;
  std::vector<int> mcidStack;
  double           pageWidth;
  double           pageHeight;
  UnicodeMap      *unicodeMap;
};

#endif /* !MARKEDCONTENTOUTPUTDEV_H */
