1// LAF Gfx Library
2// Copyright (C) 2020 Igara Studio S.A.
3// Copyright (C) 2001-2016 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifndef GFX_CLIP_H_INCLUDED
9#define GFX_CLIP_H_INCLUDED
10#pragma once
11
12#include "gfx/point.h"
13#include "gfx/rect.h"
14#include "gfx/size.h"
15
16namespace gfx {
17
18 template<typename T>
19 class ClipT {
20 public:
21 PointT<T> dst;
22 PointT<T> src;
23 SizeT<T> size;
24
25 ClipT()
26 : dst(0, 0)
27 , src(0, 0)
28 , size(0, 0) {
29 }
30
31 ClipT(T w, T h)
32 : dst(0, 0)
33 , src(0, 0)
34 , size(w, h) {
35 }
36
37 ClipT(T dst_x, T dst_y, T src_x, T src_y, T w, T h)
38 : dst(dst_x, dst_y)
39 , src(src_x, src_y)
40 , size(w, h) {
41 }
42
43 ClipT(T dst_x, T dst_y, const RectT<T>& srcBounds)
44 : dst(dst_x, dst_y)
45 , src(srcBounds.x, srcBounds.y)
46 , size(srcBounds.w, srcBounds.h) {
47 }
48
49 ClipT(const PointT<T>& dst, const PointT<T>& src, const SizeT<T>& size)
50 : dst(dst)
51 , src(src)
52 , size(size) {
53 }
54
55 ClipT(const PointT<T>& dst, const RectT<T>& srcBounds)
56 : dst(dst)
57 , src(srcBounds.x, srcBounds.y)
58 , size(srcBounds.w, srcBounds.h) {
59 }
60
61 ClipT(const RectT<T>& bounds)
62 : dst(bounds.x, bounds.y)
63 , src(bounds.x, bounds.y)
64 , size(bounds.w, bounds.h) {
65 }
66
67 template<typename U>
68 ClipT(const ClipT<U>& other)
69 : dst(other.dst)
70 , src(other.src)
71 , size(other.size) {
72 }
73
74 RectT<T> dstBounds() const { return RectT<T>(dst, size); }
75 RectT<T> srcBounds() const { return RectT<T>(src, size); }
76
77 bool operator==(const ClipT<T>& other) const {
78 return (dst == other.dst &&
79 src == other.src &&
80 size == other.size);
81 }
82
83 bool clip(
84 // Available area
85 T avail_dst_w,
86 T avail_dst_h,
87 T avail_src_w,
88 T avail_src_h) {
89 // Clip srcBounds
90
91 if (src.x < T(0)) {
92 size.w += src.x;
93 dst.x -= src.x;
94 src.x = T(0);
95 }
96
97 if (src.y < T(0)) {
98 size.h += src.y;
99 dst.y -= src.y;
100 src.y = T(0);
101 }
102
103 if (src.x + size.w > avail_src_w)
104 size.w -= src.x + size.w - avail_src_w;
105
106 if (src.y + size.h > avail_src_h)
107 size.h -= src.y + size.h - avail_src_h;
108
109 // Clip dstBounds
110
111 if (dst.x < T(0)) {
112 size.w += dst.x;
113 src.x -= dst.x;
114 dst.x = T(0);
115 }
116
117 if (dst.y < T(0)) {
118 size.h += dst.y;
119 src.y -= dst.y;
120 dst.y = T(0);
121 }
122
123 if (dst.x + size.w > avail_dst_w)
124 size.w -= dst.x + size.w - avail_dst_w;
125
126 if (dst.y + size.h > avail_dst_h)
127 size.h -= dst.y + size.h - avail_dst_h;
128
129 return (size.w > T(0) && size.h > T(0));
130 }
131
132 };
133
134 typedef ClipT<int> Clip;
135 typedef ClipT<double> ClipF;
136
137} // namespace gfx
138
139#endif
140