NXWidgets  1.19
cimage.cxx
Go to the documentation of this file.
1 /****************************************************************************
2  * NxWidgets/libnxwidgets/include/cimage.cxx
3  *
4  * Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
5  * Author: Gregory Nutt <gnutt@nuttx.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  * 3. Neither the name NuttX, NxWidgets, nor the names of its contributors
18  * me be used to endorse or promote products derived from this software
19  * without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  ****************************************************************************
35  *
36  * Portions of this package derive from Woopsi (http://woopsi.org/) and
37  * portions are original efforts. It is difficult to determine at this
38  * point what parts are original efforts and which parts derive from Woopsi.
39  * However, in any event, the work of Antony Dzeryn will be acknowledged
40  * in most NxWidget files. Thanks Antony!
41  *
42  * Copyright (c) 2007-2011, Antony Dzeryn
43  * All rights reserved.
44  *
45  * Redistribution and use in source and binary forms, with or without
46  * modification, are permitted provided that the following conditions are met:
47  *
48  * * Redistributions of source code must retain the above copyright
49  * notice, this list of conditions and the following disclaimer.
50  * * Redistributions in binary form must reproduce the above copyright
51  * notice, this list of conditions and the following disclaimer in the
52  * documentation and/or other materials provided with the distribution.
53  * * Neither the names "Woopsi", "Simian Zombie" nor the
54  * names of its contributors may be used to endorse or promote products
55  * derived from this software without specific prior written permission.
56  *
57  * THIS SOFTWARE IS PROVIDED BY Antony Dzeryn ``AS IS'' AND ANY
58  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
59  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
60  * DISCLAIMED. IN NO EVENT SHALL Antony Dzeryn BE LIABLE FOR ANY
61  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
62  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
63  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
64  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
66  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67  *
68  ****************************************************************************/
69 
70 /****************************************************************************
71  * Included Files
72  ****************************************************************************/
73 
74 #include <nuttx/config.h>
75 
76 #include <stdint.h>
77 #include <stdbool.h>
78 #include <debug.h>
79 
80 #include <nuttx/nx/nxglib.h>
81 
82 #include "nxconfig.hxx"
83 #include "cgraphicsport.hxx"
84 #include "ibitmap.hxx"
85 #include "cbitmap.hxx"
86 #include "cimage.hxx"
87 
88 /****************************************************************************
89  * Pre-Processor Definitions
90  ****************************************************************************/
91 
92 /****************************************************************************
93  * Method Implementations
94  ****************************************************************************/
95 
96 using namespace NXWidgets;
97 
98 /**
99  * Constructor for a label containing a string.
100  *
101  * @param pWidgetControl The controlling widget for the display
102  * @param x The x coordinate of the image box, relative to its parent.
103  * @param y The y coordinate of the image box, relative to its parent.
104  * @param width The width of the textbox.
105  * @param height The height of the textbox.
106  * @param bitmap The source bitmap image.
107  * @param style The style that the widget should use. If this is not
108  * specified, the button will use the global default widget
109  * style.
110  */
111 
112 CImage::CImage(CWidgetControl *pWidgetControl, nxgl_coord_t x, nxgl_coord_t y,
113  nxgl_coord_t width, nxgl_coord_t height, FAR IBitmap *bitmap,
114  CWidgetStyle *style)
115  : CNxWidget(pWidgetControl, x, y, width, height, 0, style)
116 {
117  // Save the IBitmap instance
118 
119  m_bitmap = bitmap;
120 
121  // Not highlighted
122 
123  m_highlighted = false;
124 
125  // Position the top/left corner of the bitmap in the top/left corner of the display
126 
127  m_origin.x = 0;
128  m_origin.y = 0;
129 }
130 
131 /**
132  * Insert the dimensions that this widget wants to have into the rect
133  * passed in as a parameter. All coordinates are relative to the
134  * widget's parent.
135  *
136  * @param rect Reference to a rect to populate with data.
137  */
138 
140 {
141  if (!m_bitmap)
142  {
143  rect.setX(m_rect.getX());
144  rect.setY(m_rect.getY());
145  rect.setWidth(0);
146  rect.setHeight(0);
147  }
148  else
149  {
150  nxgl_coord_t width = m_bitmap->getWidth();
151  nxgl_coord_t height = m_bitmap->getHeight();
152 
153  if (!m_flags.borderless)
154  {
155  width += (m_borderSize.left + m_borderSize.right);
156  height += (m_borderSize.top + m_borderSize.bottom);
157  }
158 
159  rect.setX(m_rect.getX());
160  rect.setY(m_rect.getY());
161  rect.setWidth(width);
162  rect.setHeight(height);
163  }
164 }
165 
166 /**
167  * Draw the area of this widget that falls within the clipping region.
168  * Called by the drawContents(port) and by classes that inherit from
169  * CImage.
170  *
171  * @param port The CGraphicsPort to draw to.
172  * @see redraw()
173  */
174 
175 void CImage::drawContents(CGraphicsPort *port, bool selected)
176 {
177  if (!m_bitmap)
178  {
179  // No image to draw
180 
181  return;
182  }
183 
184  // Get the the drawable region
185 
186  CRect rect;
187  getRect(rect);
188 
189  // Allocate a working buffer that will hold one row of the bitmap
190 
191  FAR nxwidget_pixel_t *buffer = new nxwidget_pixel_t[rect.getWidth()];
192 
193  // Set up a simple bitmap structure to describe one row
194 
195  struct SBitmap bitmap;
196  bitmap.bpp = m_bitmap->getBitsPerPixel();
197  bitmap.fmt = m_bitmap->getColorFormat();
198  bitmap.width = rect.getWidth();
199  bitmap.height = 1;
200  bitmap.stride = (rect.getWidth() * m_bitmap->getBitsPerPixel()) >> 3;
201  bitmap.data = buffer;
202 
203  // Select the correct colorization
204 
205  m_bitmap->setSelected(selected || m_highlighted);
206 
207  // This is the end row + 1 that we can write into
208 
209  nxgl_coord_t bottomRow = m_bitmap->getHeight() + m_origin.y;
210  if (bottomRow > rect.getHeight())
211  {
212  bottomRow = rect.getHeight();
213  }
214 
215  // Apply padding entire line buffer.
216 
217  FAR nxwidget_pixel_t *ptr = buffer;
218  nxwidget_pixel_t backColor = getBackgroundColor();
219 
220  for (int column = 0; column < rect.getWidth(); column++)
221  {
222  *ptr++ = backColor;
223  }
224 
225  // This the starting row in the display image where we will begin drawing.
226 
227  nxgl_coord_t destRow = rect.getY();
228 
229  // Draw any padded rows at the top of the widget before this
230 
231  for (int padRow = 0; padRow < m_origin.y; padRow++, destRow++)
232  {
233  // Put the padded row on the display (never greyscale)
234 
235  port->drawBitmap(rect.getX(), destRow, rect.getWidth(), 1,
236  &bitmap, 0, 0);
237  }
238 
239  // This is the number of rows that we can draw at the top of the display
240 
241  nxgl_coord_t nTopRows = bottomRow - m_origin.y;
242 
243  // Are we going to draw any rows at the top of the display?
244 
245  if (nTopRows > 0)
246  {
247  // This is the end column + 1 that we can write into
248 
249  nxgl_coord_t rightColumn = m_bitmap->getWidth() + m_origin.x;
250  if (rightColumn > rect.getWidth())
251  {
252  rightColumn = rect.getWidth();
253  }
254 
255  // This is the number of columns that we can draw on the left side of
256  // the display at the offset m_origin.x.
257 
258  nxgl_coord_t nLeftPixels = rightColumn - m_origin.x;
259 
260  // This is the row number of the first row that we cannot draw into
261 
262  nxgl_coord_t lastTopRow = nTopRows + destRow;
263 
264  for (int srcRow = 0; destRow < lastTopRow; srcRow++, destRow++)
265  {
266  // Read the graphics data for the left hand side of this row and
267  // place it in the row buffer at offset origin.x.
268 
269  if (!m_bitmap->getRun(0, srcRow, nLeftPixels, &buffer[m_origin.x]))
270  {
271  ginfo("IBitmap::getRun failed at image row\n", srcRow);
272  delete buffer;
273  return;
274  }
275 
276  // Pre-process special pixel values... Then we can use the faster
277  // opaque drawBitmap() function.
278 
279  ptr = &buffer[m_origin.x];
280  for (int i = 0; i < nLeftPixels; i++, ptr++)
281  {
282  // Replace any transparent pixels with the background color.
283 
284  if (*ptr == CONFIG_NXWIDGETS_TRANSPARENT_COLOR)
285  {
286  *ptr = backColor;
287  }
288 
289  // Convert pixels (other than the background color) to grey
290  // scale if the image is disabled. We can't use
291  // CGraphicsPort::drawBitmapGreyColor because it does not
292  // (yet) understand transparent pixels and has no idea what it
293  // should do with background colors.
294 
295  else if (*ptr != backColor && !isEnabled())
296  {
297  // Get the next RGB pixel and break out the individual
298  // components
299 
300  nxwidget_pixel_t rgb = *ptr;
301  nxwidget_pixel_t r = RGB2RED(rgb);
302  nxwidget_pixel_t g = RGB2GREEN(rgb);
303  nxwidget_pixel_t b = RGB2BLUE(rgb);
304 
305  // A truly accurate greyscale conversion would be complex.
306  // Let's just average.
307 
308  nxwidget_pixel_t avg = (r + g + b) / 3;
309  *ptr = MKRGB(avg, avg, avg);
310  }
311  }
312 
313  // And put these on the display
314 
315  port->drawBitmap(rect.getX(), destRow, rect.getWidth(), 1,
316  &bitmap, 0, 0);
317  }
318  }
319 
320  // Are we going to draw any rows at the bottom of the display?
321 
322  if (nTopRows < rect.getHeight())
323  {
324  // Pad the entire row
325 
326  ptr = buffer;
327  for (int column = 0; column < rect.getWidth(); column++)
328  {
329  *ptr++ = backColor;
330  }
331 
332  // Now draw the rows from the offset position
333 
334  for (; destRow < rect.getHeight(); destRow++)
335  {
336  // Put the padded row on the display (never greyscale)
337 
338  port->drawBitmap(rect.getX(), destRow, rect.getWidth(), 1,
339  &bitmap, 0, 0);
340  }
341  }
342 
343  delete buffer;
344 }
345 
346 /**
347  * Draw the area of this widget that falls within the clipping region.
348  * Called by the redraw() function to draw all visible regions.
349  *
350  * @param port The CGraphicsPort to draw to.
351  * @see redraw()
352  */
353 
355 {
356  drawContents(port, isClicked());
357 }
358 
359 /**
360  * Draw the border of this widget. Called by the indirectly via
361  * drawBoard(port) and also by classes that inherit from CImage.
362  *
363  * @param port The CGraphicsPort to draw to.
364  * @see redraw()
365  */
366 
367 void CImage::drawBorder(CGraphicsPort *port, bool selected)
368 {
369  // Stop drawing if the widget indicates it should not have an outline
370 
371  if (isBorderless())
372  {
373  return;
374  }
375 
376  // Work out which colors to use
377 
378  nxgl_coord_t color1;
379  nxgl_coord_t color2;
380 
381  if (selected)
382  {
383  // Bevelled into the screen
384 
385  color1 = getShadowEdgeColor();
386  color2 = getShineEdgeColor();
387  }
388  else
389  {
390  // Bevelled out of the screen
391 
392  color1 = getShineEdgeColor();
393  color2 = getShadowEdgeColor();
394  }
395 
396  port->drawBevelledRect(getX(), getY(), getWidth(), getHeight(), color1, color2);
397 }
398 
399 /**
400  * Draw the border of this widget. Called by the redraw() function to draw
401  * all visible regions.
402  *
403  * @param port The CGraphicsPort to draw to.
404  * @see redraw()
405  */
406 
408 {
409  drawBorder(port, isClicked());
410 }
411 
412 /**
413  * Control the highlight state.
414  *
415  * @param highlightOn True(1), the image will be highlighted
416  */
417 
418 void CImage::highlight(bool highlightOn)
419 {
420  if (m_highlighted != highlightOn)
421  {
422  m_highlighted = highlightOn;
423  redraw();
424  }
425 }
426 
427 /**
428  * Redraws the button.
429  *
430  * @param x The x coordinate of the click.
431  * @param y The y coordinate of the click.
432  */
433 
434 void CImage::onClick(nxgl_coord_t x, nxgl_coord_t y)
435 {
436  redraw();
437 }
438 
439 /**
440  * Raises an action.
441  *
442  * @param x The x coordinate of the mouse.
443  * @param y The y coordinate of the mouse.
444  */
445 
446 void CImage::onPreRelease(nxgl_coord_t x, nxgl_coord_t y)
447 {
449 }
450 
451 /**
452  * Redraws the image.
453  *
454  * @param x The x coordinate of the mouse.
455  * @param y The y coordinate of the mouse.
456  */
457 
458 void CImage::onRelease(nxgl_coord_t x, nxgl_coord_t y)
459 {
460  redraw();
461 }
462 
463 /**
464  * Redraws the image.
465  *
466  * @param x The x coordinate of the mouse.
467  * @param y The y coordinate of the mouse.
468  */
469 
470 void CImage::onReleaseOutside(nxgl_coord_t x, nxgl_coord_t y)
471 {
472  redraw();
473 }
474 
475 /**
476  * Set the horizontal position of the bitmap. Zero is the left edge
477  * of the bitmap and values > 0 will move the bit map to the right.
478  * This method is useful for horizontal scrolling a large bitmap
479  * within a smaller window
480  *
481  * REVISIT: m_origin.x should be permitted to go negative.
482  */
483 
484 void CImage::setImageLeft(nxgl_coord_t column)
485 {
486  // Get the the drawable region
487 
488  CRect rect;
489  getRect(rect);
490 
491  if (m_bitmap && column >= 0 && column < rect.getWidth())
492  {
493  m_origin.x = column;
494  }
495 }
496 
497 /**
498  * Align the image at the left of the widget region.
499  *
500  * NOTE: The CImage widget does not support any persistent alignment
501  * attribute (at least not at the moment). As a result, this alignment
502  * can be lost if the image is changed or if the widget is resized.
503  */
504 
506 {
507  // Get the the drawable region
508 
509  CRect rect;
510  getRect(rect);
511 
512  // Center the image
513 
514  setImageLeft((rect.getWidth() - m_bitmap->getWidth()) >> 1);
515 }
516 
517 /**
518  * Align the image at the left of the widget region.
519  *
520  * NOTE: The CImage widget does not support any persistent alignment
521  * attribute (at least not at the moment). As a result, this alignment
522  * can be lost if the image is changed or if the widget is resized.
523  */
524 
526 {
527  // Get the the drawable region
528 
529  CRect rect;
530  getRect(rect);
531 
532  // Position the image at the right of the widget region
533 
534  setImageLeft(rect.getWidth() - m_bitmap->getWidth());
535 }
536 
537 /**
538  * Set the vertical position of the bitmap. Zero is the top edge
539  * of the bitmap and values >0 will move the bit map down.
540  * This method is useful for vertical scrolling a large bitmap
541  * within a smaller window
542  *
543  * REVISIT: m_origin.y should be permitted to go negative.
544  */
545 
546 void CImage::setImageTop(nxgl_coord_t row)
547 {
548  // Get the the drawable region
549 
550  CRect rect;
551  getRect(rect);
552 
553  // Check the attempted Y position
554 
555  if (m_bitmap && row >= 0 && row < rect.getHeight())
556  {
557  m_origin.y = row;
558  }
559 }
560 
561 /**
562  * Align the image at the middle of the widget region.
563  *
564  * NOTE: The CImage widget does not support any persistent alignment
565  * attribute (at least not at the moment). As a result, this alignment
566  * can be lost if the image is changed or if the widget is resized.
567  */
568 
570 {
571  // Get the the drawable region
572 
573  CRect rect;
574  getRect(rect);
575 
576  // Center the image
577 
578  setImageTop((rect.getHeight() - m_bitmap->getHeight()) >> 1);
579 }
580 
581 /**
582  * Align the image at the left of the widget region.
583  *
584  * NOTE: The CImage widget does not support any persistent alignment
585  * attribute (at least not at the moment). As a result, this alignment
586  * can be lost if the image is changed or if the widget is resized.
587  */
588 
590 {
591  // Get the the drawable region
592 
593  CRect rect;
594  getRect(rect);
595 
596  // Position the image at the bottom of the widget region
597 
599 }
void setImageLeft(nxgl_coord_t column)
Definition: cimage.cxx:484
WidgetBorderSize m_borderSize
Definition: cnxwidget.hxx:208
bool isClicked(void) const
Definition: cnxwidget.hxx:560
bool isBorderless(void) const
Definition: cnxwidget.hxx:549
nxgl_mxpixel_t getShadowEdgeColor(void) const
Definition: cnxwidget.hxx:749
nxgl_coord_t getHeight(void) const
Definition: crect.hxx:204
virtual void onClick(nxgl_coord_t x, nxgl_coord_t y)
Definition: cimage.cxx:434
void getRect(CRect &rect) const
Definition: cnxwidget.cxx:448
nxgl_coord_t getWidth(void) const
Definition: crect.hxx:181
void drawBevelledRect(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, nxgl_mxpixel_t shineColor, nxgl_mxpixel_t shadowColor)
nxgl_coord_t getX(void) const
Definition: crect.hxx:160
virtual bool getRun(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, FAR void *data)=0
void drawBitmap(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, const struct SBitmap *bitmap, int bitmapX, int bitmapY)
nxgl_mxpixel_t getBackgroundColor(void) const
Definition: cnxwidget.hxx:716
virtual const nxgl_coord_t getHeight(void) const =0
void alignHorizontalCenter(void)
Definition: cimage.cxx:505
void highlight(bool highlightOn)
Definition: cimage.cxx:418
uint8_t nxwidget_pixel_t
Definition: nxconfig.hxx:442
void getPreferredDimensions(CRect &rect) const
Definition: cimage.cxx:139
void drawBorder(CGraphicsPort *port, bool selected)
Definition: cimage.cxx:367
bool isEnabled(void) const
Definition: cnxwidget.cxx:381
nxgl_coord_t getHeight(void) const
Definition: cnxwidget.hxx:593
void alignHorizontalRight(void)
Definition: cimage.cxx:525
void setHeight(nxgl_coord_t height)
Definition: crect.hxx:261
void drawContents(CGraphicsPort *port, bool selected)
Definition: cimage.cxx:175
void setX(nxgl_coord_t x)
Definition: crect.hxx:229
void setImageTop(nxgl_coord_t row)
Definition: cimage.cxx:546
FAR IBitmap * m_bitmap
Definition: cimage.hxx:112
virtual void onPreRelease(nxgl_coord_t x, nxgl_coord_t y)
Definition: cimage.cxx:446
void alignVerticalCenter(void)
Definition: cimage.cxx:569
nxgl_coord_t height
Definition: cbitmap.hxx:108
FAR const void * data
Definition: cbitmap.hxx:110
nxgl_mxpixel_t getShineEdgeColor(void) const
Definition: cnxwidget.hxx:738
virtual void onReleaseOutside(nxgl_coord_t x, nxgl_coord_t y)
Definition: cimage.cxx:470
struct nxgl_point_s m_origin
Definition: cimage.hxx:113
CWidgetEventHandlerList * m_widgetEventHandlers
Definition: cnxwidget.hxx:191
CImage(const CImage &label)
Definition: cimage.hxx:197
nxgl_coord_t width
Definition: cbitmap.hxx:107
virtual const nxgl_coord_t getWidth(void) const =0
nxgl_coord_t getY(void) const
Definition: cnxwidget.cxx:261
void setWidth(nxgl_coord_t width)
Definition: crect.hxx:250
nxgl_coord_t getWidth(void) const
Definition: cnxwidget.hxx:582
nxgl_coord_t getX(void) const
Definition: cnxwidget.cxx:245
nxgl_coord_t getY(void) const
Definition: crect.hxx:170
virtual void setSelected(bool selected)=0
static const NXWidgets::SRlePaletteBitmapEntry bitmap[]
virtual const uint8_t getBitsPerPixel(void) const =0
virtual const uint8_t getColorFormat(void) const =0
void setY(nxgl_coord_t y)
Definition: crect.hxx:240
virtual void onRelease(nxgl_coord_t x, nxgl_coord_t y)
Definition: cimage.cxx:458
void alignVerticalBottom(void)
Definition: cimage.cxx:589