text: #pragma once
  
  #ifndef TPALETTE_H
  #define TPALETTE_H
  
  // TnzCore includes
  #include "tpersist.h"
  #include "timage.h"
  #include "tfilepath.h"
  #include "tpixel.h"
  #include "tcolorstyles.h"
  
  // Qt includes
  #include <QMutex>
  
  #undef DVAPI
  #undef DVVAR
  #ifdef TVRENDER_EXPORTS
  #define DVAPI DV_EXPORT_API
  #define DVVAR DV_EXPORT_VAR
  #else
  #define DVAPI DV_IMPORT_API
  #define DVVAR DV_IMPORT_VAR
  #endif
  
  #ifdef _MSC_VER
  #pragma warning(push)
  #pragma warning(disable : 4251)
  #endif
  
  //=========================================================
  
  //    Forward declarations
  
  class TPixelRGBM32;
  
  typedef TSmartPointerT<TPalette> TPaletteP;
  
  //=========================================================
  
  //*****************************************************************************************
  //    TPalette  declaration
  //*****************************************************************************************
  
  /*!
    \brief    The class representing a Toonz palette object.
  
    \par Rationale
      A palette is a collection of <I>color styles</I> that adds a level of
  indirection
      on color selections when drawing certain graphical objects.
  \n
      Palette-based objects store <I>style identifiers</I> into an associated
  palette object,
      rather than the colors directly. When a color needs to be accessed, the
  palette
      objects is queried for a <I>style id</I>, and the associated \a style is
  returned.
  \n
      A TColorStyle instance generalizes the notion of \a color, providing the
  ability to
      reduce a style instance to a color, \a and specialized drawing functions for
      <I>vector graphics</I> objects.
  
    \par Reserved colors
      A palette object has two fixed \a reserved styles - which <I>cannot be
  removed</I> - at
      indexes \p 0 and \p1. Index \p 0 is reserved for the \b transparent color.
  Index \p 1
      is reserved for the \b ink color, initialized by default to black.
  
    \par Syntax
      A palette is supposedly created <B>on the heap</B>, to the point that, <I>in
  current
      implementation</I>, copy and assignment are \a forbidden. This behavior is
  somewhat
      inconsistent since a palette \b is currently \a clonable and \a assignable
  with the
      appropriate functions. Normalization to common C++ syntax should be enforced
  ASAP.
  
  \sa The TColorStyle class.
  */
  
  class DVAPI TPalette final : public TPersist, public TSmartObject {
    DECLARE_CLASS_CODE
    PERSIST_DECLARATION(TPalette);
  
  public:
    /*!
            \brief A palette page is a restricted view of a palette instance.
    */
  
    class DVAPI Page {
      friend class TPalette;
  
    private:
      std::wstring m_name;  //!< Name of the page to be displayed.
      int m_index;  //!< Index of the page in the palette's pages collection.
      TPalette *m_palette;  //!< (\p not \p owned)  Palette the page refers to.
      std::vector<int> m_styleIds;  //!< Palette style ids contained in the page.
  
    public:
      Page(std::wstring name);
  
      std::wstring getName() const {
        return m_name;
      }  //!< Returns the name of the page.
      void setName(std::wstring name) {
        m_name = name;
      }  //!< Sets the name of the page.
  
      TPalette *getPalette() const {
        return m_palette;
      }  //!< Returns a pointer to the palette that contains this page.
  
      int getIndex() const {
        return m_index;
      }  //!< Returns the page index in the palette.
  
      int getStyleCount() const {
        return (int)m_styleIds.size();
      }  //!< Returns the number of the styles contained in the page.
  
      int getStyleId(int indexInPage) const;  //!< Returns the \a index-th style
                                              //! id in the page, or \p -1 if not
      //! found.
      TColorStyle *getStyle(int indexInPage) const;  //!< Returns the \a index-th
      //! style in the page, or \p 0
      //! if not found.
  
      //! \return The insertion index in the page, or \p -1 on failure
      int addStyle(int styleId);  //!< Adds the specified style Id to the page (at
                                  //! the \a back
                                  //!  of the page).
                                  /*!
                              \warning  The supplied style must have been allocated with \a new.
                              \warning  Style ownership is surrendered to the palette.
                              \return   The insertion index in the page, or \p -1 on failure.
                                  In case of failure, the supplied style is \a deleted.
                              */
      int addStyle(TColorStyle *style);  //!< Adds the specified style to the
                                         //! palette, and assigns it
      //!  to this page.
      //! \return The insertion index in the page, or \p -1 on failure
      int addStyle(TPixel32 color);  //!< Add a solid color style to the palette,
                                     //! and assigns it
      //!  to this page.
  
      void insertStyle(int indexInPage, int styleId);  //!< Inserts the supplied
                                                       //! style id at the
      //! specified position
      //!  in the page.
      //! \sa The specifics of addStyle(TColorStyle*) apply here.
      void insertStyle(int indexInPage, TColorStyle *style);  //!< Inserts the
      //! supplied style in
      //! the palette, and
      //! assigns its
      //!  id at the specified position in the page.
      void insertStyle(int indexInPage, TPixel32 color);  //!< Inserts a solid
                                                          //! color style in the
      //! palette, and assigns
      //! its
      //!  id at the specified position in the page.
  
      void removeStyle(int indexInPage);  //!< Removes the style at the specified
                                          //! position from this page.
      int search(int styleId)
          const;  //!< Returns the page position of the specified style id,
                  //!  or \p -1 if it cannot be found on the page.
      int search(TColorStyle *style)
          const;  //!< Returns the page position of the specified style,
                  //!  or \p -1 if it cannot be found on the page.
    };
  
  private:
    typedef std::map<int, TColorStyleP>
        StyleAnimation;  //!< Style keyframes list.
    typedef std::map<int, StyleAnimation>
        StyleAnimationTable;  //!< Style keyframes list per style id.
  
    friend class Page;
  
  private:
    std::wstring m_globalName;   //!< Palette \a global name.
    std::wstring m_paletteName;  //!< Palette name.
  
    int m_version;                //!< Palette version number.
    std::vector<Page *> m_pages;  //!< Pages list.
    std::vector<std::pair<Page *, TColorStyleP>> m_styles;  //!< Styles container.
    std::map<int, int> m_shortcuts;
    StyleAnimationTable
        m_styleAnimationTable;  //!< Table of style animations (per style).
    int m_currentFrame;         //!< Palette's current frame in style animations.
    bool m_isCleanupPalette;    //!< Whether the palette is used for cleanup
                                //! purposes.
  
    TImageP m_refImg;
    TFilePath m_refImgPath;
    std::vector<TFrameId> m_refLevelFids;
  
    bool m_dirtyFlag;  //!< Whether the palette changed and needs to be refreshed.
    QMutex m_mutex;    //!< Synchronization mutex for multithreading purposes.
  
    bool m_isLocked;          //!< Whether the palette is locked.
    bool m_askOverwriteFlag;  //!< This variable is quite unique. This flag is to
                              //! achieve following behavior:
    //! When saving the level with the palette being edited, ask whether the
    //! palette
    //! should be overwritten ONLY ONCE AT THE FIRST TIME.
    //! The confirmation dialog will not be opened unless the palette is edited
    //! again,
    //! even if the palette's dirtyflag is true.
  
    int m_shortcutScopeIndex;
  
    int m_currentStyleId;
  
    bool m_areRefLevelFidsSpecified = false;
  
  public:
    TPalette();
    ~TPalette();
  
    TPalette *clone()
        const;  //!< Allocates a \a new copy of this palette instance.
  
    static void setRootDir(const TFilePath &fp);  //!< It must be specified to
                                                  //! save textures in \e
    //! fp/textures.
    static TFilePath getRootDir();
  
    std::wstring getGlobalName() const {
      return m_globalName;
    }  //!< Returns the name of the palette object.
    void setGlobalName(std::wstring name) {
      m_globalName = name;
    }  //!< Assigns the name of the palette.
  
    void setDirtyFlag(bool dirtyFlag)  //!< Declares the palette \a changed with
                                       //! respect to the last <I>saved state</I>.
    {
      m_dirtyFlag = dirtyFlag;
      // synchronize with the dirty flag
      m_askOverwriteFlag = dirtyFlag;
    }
    bool getDirtyFlag() {
      return m_dirtyFlag;
    }  //!< Returns whether the palette changed with respect to the last <I>saved
       //! state</I>.
  
    TColorStyle *getStyle(int styleId)
        const;  //!< Returns a pointer to the color style with the specified id,
                //!  or \p 0 if said id is not stored in the palette.
    int getStyleCount() const {
      return (int)m_styles.size();
    }  //!< Returns the number of the color styles in the palette.
    int getStyleInPagesCount()
        const;  //!< Returns the number of styles contained in palette pages.
  
    int getFirstUnpagedStyle() const;  //!< Returns the styleId of the first style
                                       //! not in a page (\p -1 if none).
  
    /*!
            \remark   Style ownserhip is \a surrendered to the palette
            \return   The styleId associated to the inserted style, or \a -1 on
       failure.
    */
    int addStyle(TColorStyle *style);         //!< Adds the specified style to the
                                              //! palette (but in no page).
    int addStyle(const TPixelRGBM32 &color);  //!< Adds a solid color style to the
                                              //! palette (but in no page).
  
    /*!
  \remark     Style ownserhip is \a surrendered to the palette.
  \remark     Any existing style's animation will be discarded.
  */
    void setStyle(
        int styleId,
        TColorStyle *style);  //!< Replaces the style with the specified style id.
    void setStyle(int styleId, const TPixelRGBM32 &color);  //!< Replaces the
                                                            //! style with the
    //! specified style id.
  
    int getPageCount() const;  //!< Returns the pages count.
  
    Page *getPage(int pageIndex);  //!< Returns the \a index-th palette page, or
                                   //!\p 0 if no such page was found.
    const Page *getPage(int pageIndex) const;  //!< Const version of getPage(int).
  
    /*!
  \return  A pointer to the newly created page.
  */
    Page *addPage(
        std::wstring name);     //!< Creates a new page with the specified name.
    void erasePage(int index);  //!< Deletes the \a index-th page.
  
    void movePage(Page *page, int dstPageIndex);  //!< Moves the specified page to
                                                  //! a different page index.
  
    Page *getStylePage(int styleId)
        const;  //!< Returns the page containing the specified \a styleId.
  
    /*!
  \note   The distance between colors is calculated with the usual sphrical norm
  between RGBA color components.
  \return The style id of the nearest style, or \p -1 if none was found.
    */
    int getClosestStyle(const TPixelRGBM32 &color)
        const;  //!< Returns the index of the style whose main color
                //!  is nearest to the requested one.
  
    void loadData(TIStream &is) override;  //!< I/O palette save function.
    void saveData(TOStream &os) override;  //!< I/O palette load function.
  
    int getVersion() const {
      return m_version;
    }  //!< Returns the palette's version number
    void setVersion(int v) {
      m_version = v;
    }  //!< Sets the palette's version number
  
    void setRefLevelFids(const std::vector<TFrameId> fids,
                         bool specified);  //!< Associates the
                                           //! list of frames \e
    //! fids to this palette.
    //! When specified == true fids were specified by user on loading.
    std::vector<TFrameId> getRefLevelFids();  //!< Returns the list of frames
                                              //! associated to this palette.
  
    //! \deprecated  Should be substituted by operator=(const TPalette&).
    void assign(const TPalette *src,
                bool isFromStudioPalette = false);  //!< Copies src's page, color
                                                    //! styles an animation table
    //! to the
    //!  corresponding features of the palette.
    //!  if the palette is copied from studio palette, this function will modify
    //!  the original names.
    void merge(const TPalette *src,
               bool isFromStudioPalette =
                   false);  //!< Adds src's styles and pages to the palette.
    //!  if the palette is merged from studio palette, this function will modify
    //!  the original names.
  
    void setAskOverwriteFlag(
        bool askOverwriteFlag) {  //!< Sets the ask-overwrite flag.
      m_askOverwriteFlag = askOverwriteFlag;
    }
    bool getAskOverwriteFlag() {
      return m_askOverwriteFlag;
    }  //!< Returns the ask-overwrite flag.
  
    void setIsCleanupPalette(
        bool on);  //!< Sets the palette's identity as a cleanup palette.
    bool isCleanupPalette() const {
      return m_isCleanupPalette;
    }  //!< Returns whether this is a cleanup palette.
  
    const TImageP &getRefImg() const {
      return m_refImg;
    }  //!< Returns an image that represents the frame image associated to this
       //! palette.
    void setRefImg(const TImageP &img);  //!< Associates an image to this palette,
                                         //! that is an image in the frame
    //!  built or modified using this palette.
  
    const TFilePath getRefImgPath() const {
      return m_refImgPath;
    }  //!< Returns the file path of the reference image.
    void setRefImgPath(
        const TFilePath &fp);  //!< Sets the path filename of the reference image.
  
    bool isAnimated() const;  //!< Returns whether this palette is animated
                              //!(styles change through time).
  
    int getFrame() const;      //!< Returns the index of the current frame.
    void setFrame(int frame);  //!< Sets the index of the current frame.
  
    bool isKeyframe(int styleId, int frame) const;  //!< Returns whether the
                                                    //! specified frame is a \a
    //! keyframe in styleId's
    //! animation
    int getKeyframeCount(int styleId)
        const;  //!< Returns the keyframes count in styleId's animation.
  
    int getKeyframe(int styleId, int index)
        const;  //!< Returns the \a index-th frame in styleId's animation,
                //!  or \p -1 if it couldn't be found.
    void setKeyframe(int styleId, int frame);  //!< Sets a keyframe at the
                                               //! specified frame of styleId's
    //! animation.
    void clearKeyframe(int styleId, int frame);  //!< Deletes the keyframe at the
                                                 //! specified frame of styleId's
    //! animation.
  
    /*!
  \note   Key is an integer between 0 and 9 included.
  */
    int getShortcutValue(
        int key) const;  //!< Returns the style id \a shortcut associated to key,
                         //!  or \p -1 if it couldn't be found.
    /*!
  
    */
    int getStyleShortcut(
        int styleId) const;  //!< Returns the shortcut associated to styleId, or
                             //!  or \p -1 if it couldn't be found.
    void setShortcutValue(
        int key, int styleId);  //!< Associates the specified key to a styleId.
  
    void setPaletteName(std::wstring name) {
      m_paletteName = name;
    }  //!< Sets the name of the palette.
    std::wstring getPaletteName() const {
      return m_paletteName;
    }  //!< Returns the name of the palette.
  
    QMutex *mutex() { return &m_mutex; }  //!< Returns the palette's mutex
  
    bool isLocked() const {
      return m_isLocked;
    }                            //!< Returns whether the palette is locked.
    void setIsLocked(bool lock)  //!< Sets lock/unlock to the palette.
    {
      m_isLocked = lock;
    }
  
    bool hasPickedPosStyle();  // Returns true if there is at least one style with
                               // picked pos value
  
    void nextShortcutScope(bool invert);
  
    void setCurrentStyleId(int id) { m_currentStyleId = id; }
    int getCurrentStyleId() const { return m_currentStyleId; }
  
  public:
    // Deprecated functions
  
    //! \deprecated  Used only once throughout Toonz, should be verified.
    bool getFxRects(const TRect &rect, TRect &rectIn, TRect &rectOut);
  
  private:
    // Not copyable
    TPalette(const TPalette &);             //!< Not implemented
    TPalette &operator=(const TPalette &);  //!< Not implemented
  };
  
  //-------------------------------------------------------------------
  
  #ifdef _WIN32
  template class DVAPI TSmartPointerT<TPalette>;
  #endif
  
  //-------------------------------------------------------------------
  
  #ifdef _MSC_VER
  #pragma warning(pop)
  #endif
  
  #endif  // TPALETTE_H
  