1// Aseprite
2// Copyright (C) 2001-2015 David Capello
3//
4// This program is distributed under the terms of
5// the End-User License Agreement for Aseprite.
6#ifndef APP_TILED_MODE_H_INCLUDED
7#define APP_TILED_MODE_H_INCLUDED
8#pragma once
9
10#include "filters/tiled_mode.h"
11
12#include "app/doc.h"
13#include "gfx/region.h"
14#include "render/projection.h"
15
16namespace app {
17
18 class TiledModeHelper {
19 public:
20 TiledModeHelper(const filters::TiledMode mode, const doc::Sprite* canvas) :
21 m_mode(mode),
22 m_canvas(canvas) {
23 }
24 ~TiledModeHelper() {}
25
26 void mode(const filters::TiledMode mode) {
27 m_mode = mode;
28 }
29
30 gfx::Size canvasSize() const {
31 gfx::Size sz(m_canvas->width(),
32 m_canvas->height());
33 if (int(m_mode) & int(filters::TiledMode::X_AXIS)) {
34 sz.w += sz.w * 2;
35 }
36 if (int(m_mode) & int(filters::TiledMode::Y_AXIS)) {
37 sz.h += sz.h * 2;
38 }
39 return sz;
40 }
41
42 gfx::Point mainTilePosition() const {
43 gfx::Point pt(0, 0);
44 if (int(m_mode) & int(filters::TiledMode::X_AXIS)) {
45 pt.x += m_canvas->width();
46 }
47 if (int(m_mode) & int(filters::TiledMode::Y_AXIS)) {
48 pt.y += m_canvas->height();
49 }
50 return pt;
51 }
52
53 void expandRegionByTiledMode(gfx::Region& rgn,
54 const render::Projection* proj = nullptr) const {
55 gfx::Region tile = rgn;
56 const bool xTiled = (int(m_mode) & int(filters::TiledMode::X_AXIS));
57 const bool yTiled = (int(m_mode) & int(filters::TiledMode::Y_AXIS));
58 int w = m_canvas->width();
59 int h = m_canvas->height();
60 if (proj) {
61 w = proj->applyX(w);
62 h = proj->applyY(h);
63 }
64 if (xTiled) {
65 tile.offset(w, 0); rgn |= tile;
66 tile.offset(w, 0); rgn |= tile;
67 tile.offset(-2 * w, 0);
68 }
69 if (yTiled) {
70 tile.offset(0, h); rgn |= tile;
71 tile.offset(0, h); rgn |= tile;
72 tile.offset(0, -2 * h);
73 }
74 if (xTiled && yTiled) {
75 tile.offset(w, h); rgn |= tile;
76 tile.offset(w, 0); rgn |= tile;
77 tile.offset(-w, h); rgn |= tile;
78 tile.offset(w, 0); rgn |= tile;
79 }
80 }
81
82 void collapseRegionByTiledMode(gfx::Region& rgn) const {
83 auto canvasSize = this->canvasSize();
84 rgn &= gfx::Region(gfx::Rect(canvasSize));
85
86 const int sprW = m_canvas->width();
87 const int sprH = m_canvas->height();
88
89 gfx::Region newRgn;
90 for (int v = 0; v < canvasSize.h; v += sprH) {
91 for (int u = 0; u < canvasSize.w; u += sprW) {
92 gfx::Region tmp(gfx::Rect(u, v, sprW, sprH));
93 tmp &= rgn;
94 tmp.offset(-u, -v);
95 newRgn |= tmp;
96 }
97 }
98 rgn = newRgn;
99 }
100
101 void wrapPosition(gfx::Region& rgn) const {
102 if (int(m_mode) == int(filters::TiledMode::NONE))
103 return;
104
105 if (int(m_mode) & int(filters::TiledMode::X_AXIS))
106 rgn.offset(m_canvas->width() * (1 - (rgn.bounds().x / m_canvas->width())), 0);
107
108 if (int(m_mode) & int(filters::TiledMode::Y_AXIS))
109 rgn.offset(0, m_canvas->height() * (1 - (rgn.bounds().y / m_canvas->height())));
110 }
111
112 private:
113 filters::TiledMode m_mode;
114 const doc::Sprite* m_canvas;
115
116 };
117
118} // namespace app
119
120#endif
121