@@ -68,6 +68,16 @@ def get_pixel(framebuf, x, y):
6868 offset = 7 - x & 0x07
6969 return (framebuf .buf [index ] >> offset ) & 0x01
7070
71+ @staticmethod
72+ def fill (framebuf , color ):
73+ """completely fill/clear the buffer with a color"""
74+ if color :
75+ fill = 0xFF
76+ else :
77+ fill = 0x00
78+ for i in range (len (framebuf .buf )):
79+ framebuf .buf [i ] = fill
80+
7181 @staticmethod
7282 def fill_rect (framebuf , x , y , width , height , color ):
7383 """Draw a rectangle at the given location, size and color. The ``fill_rect`` method draws
@@ -96,6 +106,16 @@ def get_pixel(framebuf, x, y):
96106 offset = y & 0x07
97107 return (framebuf .buf [index ] >> offset ) & 0x01
98108
109+ @staticmethod
110+ def fill (framebuf , color ):
111+ """completely fill/clear the buffer with a color"""
112+ if color :
113+ fill = 0xFF
114+ else :
115+ fill = 0x00
116+ for i in range (len (framebuf .buf )):
117+ framebuf .buf [i ] = fill
118+
99119 @staticmethod
100120 def fill_rect (framebuf , x , y , width , height , color ):
101121 """Draw a rectangle at the given location, size and color. The ``fill_rect`` method draws
@@ -110,36 +130,6 @@ def fill_rect(framebuf, x, y, width, height, color):
110130 y += 1
111131 height -= 1
112132
113-
114- class RGB565Format :
115- """RGB565Format"""
116- @staticmethod
117- def set_pixel (framebuf , x , y , color ):
118- """Set a given pixel to a color."""
119- index = (x + y * framebuf .stride ) * 2
120- framebuf .buf [index ] = (color >> 8 ) & 0xFF
121- framebuf .buf [index + 1 ] = color & 0xFF
122-
123- @staticmethod
124- def get_pixel (framebuf , x , y ):
125- """Get the color of a given pixel"""
126- index = (x + y * framebuf .stride ) * 2
127- return (framebuf .buf [index ] << 8 ) | framebuf .buf [index + 1 ]
128-
129- @staticmethod
130- def fill_rect (framebuf , x , y , width , height , color ):
131- # pylint: disable=too-many-arguments
132- """Draw a rectangle at the given location, size and color. The ``fill_rect`` method draws
133- both the outline and interior."""
134- while height > 0 :
135- for w_w in range (width ):
136- index = (w_w + x + y * framebuf .stride ) * 2
137- framebuf .buf [index ] = (color >> 8 ) & 0xFF
138- framebuf .buf [index + 1 ] = color & 0xFF
139- y += 1
140- height -= 1
141-
142-
143133class FrameBuffer :
144134 """FrameBuffer object.
145135
@@ -171,31 +161,44 @@ def __init__(self, buf, width, height, buf_format=MVLSB, stride=None):
171161 self .format = MVLSBFormat ()
172162 elif buf_format == MHMSB :
173163 self .format = MHMSBFormat ()
174- elif buf_format == RGB565 :
175- self .format = RGB565Format ()
176164 else :
177165 raise ValueError ('invalid format' )
166+ self ._rotation = 0
167+
168+ @property
169+ def rotation (self ):
170+ """The rotation setting of the display, can be one of (0, 1, 2, 3)"""
171+ return self ._rotation
172+
173+ @rotation .setter
174+ def rotation (self , val ):
175+ if not val in (0 , 1 , 2 , 3 ):
176+ raise RuntimeError ("Bad rotation setting" )
177+ self ._rotation = val
178178
179179 def fill (self , color ):
180180 """Fill the entire FrameBuffer with the specified color."""
181- self .format .fill_rect (self , 0 , 0 , self . width , self . height , color )
181+ self .format .fill (self , color )
182182
183183 def fill_rect (self , x , y , width , height , color ):
184184 """Draw a rectangle at the given location, size and color. The ``fill_rect`` method draws
185185 both the outline and interior."""
186186 # pylint: disable=too-many-arguments, too-many-boolean-expressions
187- if width < 1 or height < 1 or (x + width ) <= 0 or (y + height ) <= 0 or y >= self .height \
188- or x >= self .width :
189- return
190- x_end = min (self .width , x + width )
191- y_end = min (self .height , y + height )
192- x = max (x , 0 )
193- y = max (y , 0 )
194- self .format .fill_rect (self , x , y , x_end - x , y_end - y , color )
187+ self .rect (x , y , width , height , color , fill = True )
195188
196189 def pixel (self , x , y , color = None ):
197190 """If ``color`` is not given, get the color value of the specified pixel. If ``color`` is
198191 given, set the specified pixel to the given color."""
192+ if self .rotation == 1 :
193+ x , y = y , x
194+ x = self .width - x - 1
195+ if self .rotation == 2 :
196+ x = self .width - x - 1
197+ y = self .height - y - 1
198+ if self .rotation == 3 :
199+ x , y = y , x
200+ y = self .height - y - 1
201+
199202 if x < 0 or x >= self .width or y < 0 or y >= self .height :
200203 return None
201204 if color is None :
@@ -205,20 +208,43 @@ def pixel(self, x, y, color=None):
205208
206209 def hline (self , x , y , width , color ):
207210 """Draw a horizontal line up to a given length."""
208- self .fill_rect (x , y , width , 1 , color )
211+ self .rect (x , y , width , 1 , color , fill = True )
209212
210213 def vline (self , x , y , height , color ):
211214 """Draw a vertical line up to a given length."""
212- self .fill_rect (x , y , 1 , height , color )
215+ self .rect (x , y , 1 , height , color , fill = True )
213216
214- def rect (self , x , y , width , height , color ):
217+ def rect (self , x , y , width , height , color , * , fill = False ):
215218 """Draw a rectangle at the given location, size and color. The ```rect``` method draws only
216219 a 1 pixel outline."""
217220 # pylint: disable=too-many-arguments
218- self .fill_rect (x , y , width , 1 , color )
219- self .fill_rect (x , y + height - 1 , width , 1 , color )
220- self .fill_rect (x , y , 1 , height , color )
221- self .fill_rect (x + width - 1 , y , 1 , height , color )
221+ if self .rotation == 1 :
222+ x , y = y , x
223+ width , height = height , width
224+ x = self .width - x - width
225+ if self .rotation == 2 :
226+ x = self .width - x - width
227+ y = self .height - y - height
228+ if self .rotation == 3 :
229+ x , y = y , x
230+ width , height = height , width
231+ y = self .height - y - height
232+
233+ # pylint: disable=too-many-boolean-expressions
234+ if width < 1 or height < 1 or (x + width ) <= 0 or (y + height ) <= 0 or \
235+ y >= self .height or x >= self .width :
236+ return
237+ x_end = min (self .width - 1 , x + width - 1 )
238+ y_end = min (self .height - 1 , y + height - 1 )
239+ x = max (x , 0 )
240+ y = max (y , 0 )
241+ if fill :
242+ self .format .fill_rect (self , x , y , x_end - x + 1 , y_end - y + 1 , color )
243+ else :
244+ self .format .fill_rect (self , x , y , x_end - x + 1 , 1 , color )
245+ self .format .fill_rect (self , x , y , 1 , y_end - y + 1 , color )
246+ self .format .fill_rect (self , x , y_end , x_end - x + 1 , 1 , color )
247+ self .format .fill_rect (self , x_end , y , 1 , y_end - y + 1 , color )
222248
223249 def line (self , x_0 , y_0 , x_1 , y_1 , color ):
224250 # pylint: disable=too-many-arguments
@@ -356,14 +382,17 @@ def draw_char(self, char, x, y, framebuffer, color):
356382 # pylint: disable=too-many-arguments
357383 """Draw one character at position (x,y) to a framebuffer in a given color"""
358384 # Don't draw the character if it will be clipped off the visible area.
359- if x < - self .font_width or x >= framebuffer .width or \
360- y < - self .font_height or y >= framebuffer .height :
361- return
385+ # if x < -self.font_width or x >= framebuffer.width or \
386+ # y < -self.font_height or y >= framebuffer.height:
387+ # return
362388 # Go through each column of the character.
363389 for char_x in range (self .font_width ):
364390 # Grab the byte for the current column of font data.
365391 self ._font .seek (2 + (ord (char ) * self .font_width ) + char_x )
366- line = struct .unpack ('B' , self ._font .read (1 ))[0 ]
392+ try :
393+ line = struct .unpack ('B' , self ._font .read (1 ))[0 ]
394+ except RuntimeError :
395+ continue # maybe character isnt there? go to next
367396 # Go through each row in the column byte.
368397 for char_y in range (self .font_height ):
369398 # Draw a pixel for each bit that's flipped on.
0 commit comments