1 // This file is part of the utio library, a terminal I/O library.
3 // Copyright (C) 2004 by Mike Sharov <msharov@users.sourceforge.net>
4 // This file is free software, distributed under the MIT License.
14 //----------------------------------------------------------------------
24 void CGC::Resize (Size2d sz
)
28 m_Canvas
.resize (sz
[0] * sz
[1]);
32 inline CGC::canvas_t::iterator
CGC::CanvasAt (Point2d p
)
34 return (m_Canvas
.begin() + p
[1] * m_Size
[0] + p
[0]);
37 inline CGC::canvas_t::const_iterator
CGC::CanvasAt (Point2d p
) const
39 return (m_Canvas
.begin() + p
[1] * m_Size
[0] + p
[0]);
42 /// Clears the canvas with spaces with current attributes.
43 void CGC::Clear (wchar_t c
)
45 const CCharCell
vlc (c
, m_Template
);
49 /// Draws a line art box.
50 void CGC::Box (Rect r
)
53 if ((r
.Width() < 2) | (r
.Height() < 2))
56 Point2d
trCorner (r
[1][0], r
[0][1]);
57 Point2d
blCorner (r
[0][0], r
[1][1]);
58 const Rect
rr (trCorner
, blCorner
);
59 HLine (r
[0], r
.Width());
60 HLine (rr
[1], r
.Width());
61 VLine (r
[0], r
.Height());
62 VLine (rr
[0], r
.Height());
63 *CanvasAt(rr
[0]) = CCharCell (acsv_UpperRightCorner
, m_Template
);
64 *CanvasAt(rr
[1]) = CCharCell (acsv_LowerLeftCorner
, m_Template
);
65 *CanvasAt(r
[1]) = CCharCell (acsv_LowerRightCorner
, m_Template
);
66 *CanvasAt(r
[0]) = CCharCell (acsv_UpperLeftCorner
, m_Template
);
69 /// Draws a box with character \p c as the border.
70 void CGC::Bar (Rect r
, wchar_t c
)
73 const CCharCell
vlc (c
, m_Template
);
74 for (dim_t y
= 0; y
< r
.Height(); ++ y
)
75 fill_n (CanvasAt (Point2d (r
[0][0], r
[0][1] + y
)), r
.Width(), vlc
);
78 /// Draws a horizontal line from \p p of length \p l.
79 void CGC::HLine (Point2d p
, dim_t l
)
83 if (coord_t(l
) > m_Size
[0] - p
[0])
85 const CCharCell
vlc (acsv_HLine
, m_Template
);
86 fill_n (CanvasAt(p
), l
, vlc
);
89 /// Draws a vertical line from \p p of length \p l.
90 void CGC::VLine (Point2d p
, dim_t l
)
94 if (coord_t(l
) > m_Size
[1] - p
[1])
96 const CCharCell
vlc (acsv_VLine
, m_Template
);
97 for (dim_t i
= 0; i
< l
; ++ i
)
98 *CanvasAt (Point2d (p
[0], p
[1] + i
)) = vlc
;
101 /// Copies canvas data from \p r into \p cells.
102 void CGC::GetImage (Rect r
, canvas_t
& cells
) const
104 const size_t inyskip
= Width() - r
.Width();
106 cells
.resize (r
.Width() * r
.Height());
107 canvas_t::iterator
dout (cells
.begin());
108 canvas_t::const_iterator
din (CanvasAt (r
[0]));
109 for (dim_t y
= 0; y
< r
.Height(); ++ y
, din
+= inyskip
)
110 for (dim_t x
= 0; x
< r
.Width(); ++ x
, ++ din
, ++ dout
)
115 /// Copies canvas data from \p cells into \p r.
116 void CGC::Image (Rect r
, const canvas_t
& cells
)
118 const size_t outyskip
= Width() - r
.Width();
120 canvas_t::const_iterator
din (cells
.begin());
121 canvas_t::iterator
dout (CanvasAt (r
[0]));
122 for (dim_t y
= 0; y
< r
.Height(); ++ y
, dout
+= outyskip
)
123 for (dim_t x
= 0; x
< r
.Width(); ++ x
, ++ din
, ++ dout
)
128 /// Zeroes out cells which are identical to those in \p src.
129 bool CGC::MakeDiffFrom (const CGC
& src
)
131 assert (src
.Canvas().size() == m_Canvas
.size() && "Diffs can only be made on equally sized canvasses");
132 register canvas_t::pointer
inew (Canvas().begin());
133 register canvas_t::const_pointer
iold (src
.Canvas().begin());
134 const canvas_t::const_pointer
iend (src
.Canvas().end());
135 const CCharCell
nullCell (0, color_Preserve
, color_Preserve
, 0);
136 bool bHaveChanges
= false;
137 for (; iold
< iend
; ++iold
, ++inew
) {
138 const bool bSameCell (*iold
== *inew
);
141 bHaveChanges
|= !bSameCell
;
143 return (bHaveChanges
);
146 /// Prints character \p c.
147 void CGC::Char (Point2d p
, wchar_t c
)
150 *CanvasAt(p
) = CCharCell (c
, m_Template
);
153 /// Prints string \p str at \p p.
154 void CGC::Text (Point2d p
, const string
& str
)
158 const canvas_t::iterator
doutstart (CanvasAt (p
));
159 const canvas_t::iterator doutend
= doutstart
+ (m_Size
[0] - p
[0]);
160 assert (doutend
>= doutstart
);
161 canvas_t::iterator
dout (doutstart
);
162 for (string::utf8_iterator si
= str
.utf8_begin(); (si
< str
.utf8_end()) & (dout
< doutend
); ++si
) {
164 const size_t absX
= p
[0] + distance (doutstart
, dout
);
165 size_t toTab
= Align (absX
+ 1, m_TabSize
) - absX
;
166 toTab
= min (toTab
, size_t(distance (dout
, doutend
)));
167 dout
= fill_n (dout
, toTab
, CCharCell (' ', m_Template
));
169 *dout
++ = CCharCell (*si
, m_Template
);
173 static const CGC::Point2d
c_ZeroPoint (0, 0);
175 /// Clips point \p pt to the canvas size.
176 bool CGC::Clip (Point2d
& pt
) const
178 const Point2d
oldPoint (pt
);
179 Point2d
bottomright (m_Size
);
181 simd::pmax (c_ZeroPoint
, pt
);
182 simd::pmin (bottomright
, pt
);
183 return ((oldPoint
== pt
) & (m_Size
[0] > 0) & (m_Size
[1] > 0));
186 /// Clips rectangle \p r to the canvas.
187 bool CGC::Clip (Rect
& r
) const
189 const Rect
oldRect (r
);
190 const Point2d
bottomright (m_Size
);
191 simd::pmax (c_ZeroPoint
, r
[0]);
192 simd::pmin (bottomright
, r
[0]);
193 simd::pmax (c_ZeroPoint
, r
[1]);
194 simd::pmin (bottomright
, r
[1]);
195 if (r
[0][1] > r
[1][1])
197 if (r
[0][0] > r
[1][0])
198 swap (r
[0][0], r
[1][0]);
199 simd::pmax (r
[0], r
[1]);
200 return (oldRect
== r
);
203 //----------------------------------------------------------------------