1// Aseprite
2// Copyright (C) 2019-2021 Igara Studio S.A.
3// Copyright (C) 2001-2015 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "app/cmd/set_palette.h"
13
14#include "app/doc.h"
15#include "base/serialization.h"
16#include "doc/palette.h"
17#include "doc/sprite.h"
18
19namespace app {
20namespace cmd {
21
22using namespace doc;
23
24SetPalette::SetPalette(Sprite* sprite, frame_t frame, const Palette* newPalette)
25 : WithSprite(sprite)
26 , m_frame(frame)
27{
28 const Palette* curPalette = sprite->palette(frame);
29
30 m_oldNColors = curPalette->size();
31 m_newNColors = newPalette->size();
32
33 // Check differences between current sprite palette and the new one
34 m_from = m_to = -1;
35 int diffs = curPalette->countDiff(newPalette, &m_from, &m_to);
36 (void)diffs;
37 ASSERT(diffs > 0);
38
39 if (m_from >= 0 && m_to >= m_from) {
40 int oldColors = std::min(m_to+1, m_oldNColors)-m_from;
41 if (oldColors > 0)
42 m_oldColors.resize(oldColors);
43
44 int newColors = std::min(m_to+1, m_newNColors)-m_from;
45 if (newColors > 0)
46 m_newColors.resize(newColors);
47
48 for (size_t i=0; i<size_t(m_to-m_from+1); ++i) {
49 if (i < m_oldColors.size())
50 m_oldColors[i] = curPalette->getEntry(m_from+i);
51
52 if (i < m_newColors.size())
53 m_newColors[i] = newPalette->getEntry(m_from+i);
54 }
55 }
56
57 if (sprite->pixelFormat() == IMAGE_INDEXED) {
58 m_oldTransparentIndex = sprite->transparentColor();
59 if (m_oldTransparentIndex >= newPalette->size())
60 m_newTransparentIndex = newPalette->size() - 1;
61 else
62 m_newTransparentIndex = m_oldTransparentIndex;
63 }
64 else {
65 ASSERT(sprite->transparentColor() == 0);
66 m_oldTransparentIndex = 0;
67 m_newTransparentIndex = 0;
68 }
69}
70
71void SetPalette::onExecute()
72{
73 Sprite* sprite = this->sprite();
74 Palette* palette = sprite->palette(m_frame);
75 palette->resize(m_newNColors);
76
77 for (size_t i=0; i<m_newColors.size(); ++i)
78 palette->setEntry(m_from+i, m_newColors[i]);
79
80 if (m_newTransparentIndex != m_oldTransparentIndex)
81 sprite->setTransparentColor(m_newTransparentIndex);
82
83 palette->incrementVersion();
84}
85
86void SetPalette::onUndo()
87{
88 Sprite* sprite = this->sprite();
89 Palette* palette = sprite->palette(m_frame);
90 palette->resize(m_oldNColors);
91
92 for (size_t i=0; i<m_oldColors.size(); ++i)
93 palette->setEntry(m_from+i, m_oldColors[i]);
94
95 if (m_newTransparentIndex != m_oldTransparentIndex)
96 sprite->setTransparentColor(m_oldTransparentIndex);
97
98 palette->incrementVersion();
99}
100
101void SetPalette::onFireNotifications()
102{
103 doc::Sprite* sprite = this->sprite();
104 Doc* doc = static_cast<Doc*>(sprite->document());
105 doc->notifyPaletteChanged();
106}
107
108} // namespace cmd
109} // namespace app
110