-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathdisplay_bitsboard.h
397 lines (347 loc) · 14 KB
/
display_bitsboard.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
/***************************************************************************
* Copyright (C) 2010, 2011 by Terraneo Federico *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* As a special exception, if other files instantiate templates or use *
* macros or inline functions from this file, or you compile this file *
* and link it with other works to produce a work based on this file, *
* this file does not by itself cause the resulting work to be covered *
* by the GNU General Public License. However the source code for this *
* file must still be made available in accordance with the GNU General *
* Public License. This exception does not invalidate any other reasons *
* why a work based on this file might be covered by the GNU General *
* Public License. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#pragma once
#ifndef MXGUI_LIBRARY
#error "This is header is private, it can be used only within mxgui."
#error "If your code depends on a private header, it IS broken."
#endif //MXGUI_LIBRARY
#ifdef _BOARD_BITSBOARD
#include <config/mxgui_settings.h>
#include "display.h"
#include "point.h"
#include "color.h"
#include "font.h"
#include "image.h"
#include "iterator_direction.h"
#include <stdexcept>
#include <limits>
//This display is 1 bit per pixel, check that the color depth is properly
//configured
#ifndef MXGUI_COLOR_DEPTH_1_BIT_LINEAR
#error The bitsboard driver requires a color depth of 1bit per pixel
#endif
namespace mxgui {
class DisplayImpl : public Display
{
public:
/**
* \return an instance to this class (singleton)
*/
static DisplayImpl& instance();
/**
* Turn the display On after it has been turned Off.
* Display initial state is On.
*/
void doTurnOn() override;
/**
* Turn the display Off. It can be later turned back On.
*/
void doTurnOff() override;
/**
* Set display brightness. Depending on the underlying driver,
* may do nothing.
* \param brt from 0 to 100
*/
void doSetBrightness(int brt) override;
/**
* \return a pair with the display height and width
*/
std::pair<short int, short int> doGetSize() const override;
/**
* Write text to the display. If text is too long it will be truncated
* \param p point where the upper left corner of the text will be printed
* \param text, text to print.
*/
void write(Point p, const char *text) override;
/**
* Write part of text to the display
* \param p point of the upper left corner where the text will be drawn.
* Negative coordinates are allowed, as long as the clipped view has
* positive or zero coordinates
* \param a Upper left corner of clipping rectangle
* \param b Lower right corner of clipping rectangle
* \param text text to write
*/
void clippedWrite(Point p, Point a, Point b, const char *text) override;
/**
* Clear the Display. The screen will be filled with the desired color
* \param color fill color
*/
void clear(Color color) override;
/**
* Clear an area of the screen
* \param p1 upper left corner of area to clear
* \param p2 lower right corner of area to clear
* \param color fill color
*/
void clear(Point p1, Point p2, Color color) override;
/**
* This member function is used on some target displays to reset the
* drawing window to its default value. You have to call beginPixel() once
* before calling setPixel(). Yo can then make any number of calls to
* setPixel() without calling beginPixel() again, as long as you don't
* call any other member function in this class. If you call another
* member function, for example line(), you have to call beginPixel() again
* before calling setPixel().
*/
void beginPixel() override;
/**
* Draw a pixel with desired color. You have to call beginPixel() once
* before calling setPixel()
* \param p point where to draw pixel
* \param color pixel color
*/
void setPixel(Point p, Color color) override;
/**
* Draw a line between point a and point b, with color c
* \param a first point
* \param b second point
* \param c line color
*/
void line(Point a, Point b, Color color) override;
/**
* Draw an horizontal line on screen.
* Instead of line(), this member function takes an array of colors to be
* able to individually set pixel colors of a line.
* \param p starting point of the line
* \param colors an array of pixel colors whoase size must be b.x()-a.x()+1
* \param length length of colors array.
* p.x()+length must be <= display.width()
*/
void scanLine(Point p, const Color *colors, unsigned short length) override;
/**
* \return a buffer of length equal to this->getWidth() that can be used to
* render a scanline.
*/
Color *getScanLineBuffer() override;
/**
* Draw the content of the last getScanLineBuffer() on an horizontal line
* on the screen.
* \param p starting point of the line
* \param length length of colors array.
* p.x()+length must be <= display.width()
*/
void scanLineBuffer(Point p, unsigned short length) override;
/**
* Draw an image on the screen
* \param p point of the upper left corner where the image will be drawn
* \param i image to draw
*/
void drawImage(Point p, const ImageBase& img) override;
/**
* Draw part of an image on the screen
* \param p point of the upper left corner where the image will be drawn.
* Negative coordinates are allowed, as long as the clipped view has
* positive or zero coordinates
* \param a Upper left corner of clipping rectangle
* \param b Lower right corner of clipping rectangle
* \param i Image to draw
*/
void clippedDrawImage(Point p, Point a, Point b, const ImageBase& img) override;
/**
* Draw a rectangle (not filled) with the desired color
* \param a upper left corner of the rectangle
* \param b lower right corner of the rectangle
* \param c color of the line
*/
void drawRectangle(Point a, Point b, Color c) override;
/**
* Pixel iterator. A pixel iterator is an output iterator that allows to
* define a window on the display and write to its pixels.
*/
class pixel_iterator
{
public:
/**
* Default constructor, results in an invalid iterator.
*/
pixel_iterator(): dataPtr(0) {}
/**
* Set a pixel and move the pointer to the next one
* \param color color to set the current pixel
* \return a reference to this
*/
pixel_iterator& operator= (Color color)
{
*dataPtr= color ? 0 : 1;
//This is to move to the adjacent pixel
dataPtr+=aIncr;
//This is in case the 64th vertical line is crossed, and is because
//the display framebuffer is logically 256x128 but physically 512x64
if(--quirkCtr<=0)
{
quirkCtr=quirkReload[quirkFlag];
dataPtr+=qIncr[quirkFlag];
quirkFlag=1-quirkFlag;
}
//This is the step move to the next horizontal/vertical line
if(++ctr>=endCtr)
{
ctr=0;
dataPtr+=sIncr;
}
return *this;
}
/**
* Compare two pixel_iterators for equality.
* They are equal if they point to the same location.
*/
bool operator== (const pixel_iterator& itr)
{
return this->dataPtr==itr.dataPtr;
}
/**
* Compare two pixel_iterators for inequality.
* They different if they point to different locations.
*/
bool operator!= (const pixel_iterator& itr)
{
return this->dataPtr!=itr.dataPtr;
}
/**
* \return a reference to this.
*/
pixel_iterator& operator* () { return *this; }
/**
* \return a reference to this. Does not increment pixel pointer.
*/
pixel_iterator& operator++ () { return *this; }
/**
* \return a reference to this. Does not increment pixel pointer.
*/
pixel_iterator& operator++ (int) { return *this; }
/**
* Must be called if not all pixels of the required window are going
* to be written.
*/
void invalidate() {}
private:
/**
* Constructor
* \param start Upper left corner of window
* \param end Lower right corner of window
* \param direction Iterator direction
* \param disp Display we're associated
*/
pixel_iterator(Point start, Point end, IteratorDirection direction,
DisplayImpl *disp) : ctr(0),
quirkCtr(std::numeric_limits<int>::max()), quirkFlag(0),
dataPtr(disp->framebufferBitBandAlias)
{
//Handle the framebuffer quirk if the start is in the bottom half
short ys=start.y();
short half=disp->getHeight()/2;
if(ys>=half)
{
ys-=half;
dataPtr+=disp->getWidth();
}
//Compite the increment in the adjacent direction (aIncr) and in the
//step direction (sIncr) depending on the direction
dataPtr+=2*ys*disp->getWidth()+start.x();
if(direction==RD)
{
endCtr=end.x()+1-start.x();
aIncr=1;
sIncr=start.x()+2*disp->getWidth()-1-end.x();
} else {
endCtr=end.y()+1-start.y();
aIncr=2*disp->getWidth();
sIncr=-aIncr*endCtr+1;
}
//Handle the framebuffer quirk if the window crosses the screen half
if(start.y()<half && end.y()>=half)
{
if(direction==RD)
{
//In this case the 64th line is crossed only once
quirkCtr=endCtr*(half-start.y());
quirkReload[0]=std::numeric_limits<int>::max();
qIncr[0]=-(disp->getHeight()-1)*disp->getWidth();
} else {
//In this case the 64th line is crossed many times
quirkReload[0]=end.y()+1-half;
quirkReload[1]=quirkCtr=half-start.y();
qIncr[0]=-(disp->getHeight()-1)*disp->getWidth();
qIncr[1]=(disp->getHeight()-1)*disp->getWidth();
}
}
}
unsigned short ctr; ///< Counter to decide when to step
unsigned short endCtr; ///< When ctr==endCtr apply a step
int quirkCtr; ///< Quirk increment is done if reaches zero
unsigned short quirkReload[2];///< Value reloaded into quirkCtr
int qIncr[2]; ///< Quirk increments
short quirkFlag; ///< Used as index in the previous arrays
short aIncr; ///< Adjacent increment
int sIncr; ///< Step increment
unsigned int *dataPtr; ///< Pointer to bit band area
friend class DisplayImpl; //Needs access to ctor
};
/**
* Specify a window on screen and return an object that allows to write
* its pixels.
* Note: a call to begin() will invalidate any previous iterator.
* \param p1 upper left corner of window
* \param p2 lower right corner (included)
* \param d increment direction
* \return a pixel iterator
*/
pixel_iterator begin(Point p1, Point p2, IteratorDirection d);
/**
* \return an iterator which is one past the last pixel in the pixel
* specified by begin. Behaviour is undefined if called before calling
* begin()
*/
pixel_iterator end() const { return last; }
/**
* Destructor
*/
~DisplayImpl() override;
private:
/**
* Constructor.
* Do not instantiate objects of this type directly from application code.
*/
DisplayImpl();
#if defined MXGUI_ORIENTATION_VERTICAL || \
defined MXGUI_ORIENTATION_VERTICAL_MIRRORED
static const short int width=128;
static const short int height=256;
#elif defined MXGUI_ORIENTATION_HORIZONTAL || \
defined MXGUI_ORIENTATION_HORIZONTAL_MIRRORED
static const short int width=256;
static const short int height=128;
#else
#error No orientation defined
#endif
Color *buffer; ///< For scanLineBuffer
pixel_iterator last; ///< Last iterator for end of iteration check
unsigned int *framebufferBitBandAlias; ///< For fast pixel_iterator
};
} //namespace mxgui
#endif //_BOARD_BITSBOARD