NXWidgets  1.19
cgraphicsport.cxx
Go to the documentation of this file.
1 /****************************************************************************
2  * NxWidgets/libnxwidgets/src/cgraphicsport.cxx
3  *
4  * Copyright (C) 2012, 2015 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 <sys/types.h>
77 #include <stdint.h>
78 #include <stdbool.h>
79 #include <cerrno>
80 #include <debug.h>
81 
82 #include <nuttx/nx/nxglib.h>
83 #include <nuttx/video/rgbcolors.h>
84 
85 #include "nxconfig.hxx"
86 #include "inxwindow.hxx"
87 #include "cnxstring.hxx"
88 #include "crect.hxx"
89 #include "cnxfont.hxx"
90 #include "cgraphicsport.hxx"
91 #include "cwidgetstyle.hxx"
92 #include "cbitmap.hxx"
93 #include "singletons.hxx"
94 
95 /****************************************************************************
96  * Pre-Processor Definitions
97  ****************************************************************************/
98 
99 /****************************************************************************
100  * Method Implementations
101  ****************************************************************************/
102 
103 using namespace NXWidgets;
104 
105 /**
106  * Constructor.
107  *
108  * @param pNxWnd. An instance of the underlying window type.
109  * @param backColor. The background color is only needed if we
110  * cannot read from the graphics device.
111  */
112 
113 #ifdef CONFIG_NX_WRITEONLY
114 CGraphicsPort::CGraphicsPort(INxWindow *pNxWnd, nxgl_mxpixel_t backColor)
115 {
116  m_pNxWnd = pNxWnd;
117  m_backColor = backColor;
118 }
119 #else
121 {
122  m_pNxWnd = pNxWnd;
123 }
124 #endif
125 
126 /**
127  * Destructor.
128  */
129 
131 {
132  // m_pNxWnd is not deleted. This is an abstract base class and
133  // the caller of the CGraphicsPort instance is responsible for
134  // the window destruction.
135 };
136 
137 /**
138  * Return the absolute x coordinate of the upper left hand corner of the
139  * underlying window.
140  *
141  * @return The x coordinate of the underlying window.
142  */
143 
144 const nxgl_coord_t CGraphicsPort::getX(void) const
145 {
146  struct nxgl_point_s pos;
147  (void)m_pNxWnd->getPosition(&pos);
148  return pos.x;
149 };
150 
151 /**
152  * Return the absolute y coordinate of the upper left hand corner of the
153  * underlying window.
154  *
155  * @return The y coordinate of the underlying window.
156  */
157 
158 const nxgl_coord_t CGraphicsPort::getY(void) const
159 {
160  struct nxgl_point_s pos;
161  (void)m_pNxWnd->getPosition(&pos);
162  return pos.y;
163 };
164 
165 /**
166  * Draw a pixel into the window.
167  *
168  * @param x The window-relative x coordinate of the pixel.
169  * @param y The window-relative y coordinate of the pixel.
170  * @param color The color of the pixel.
171  */
172 
173 void CGraphicsPort::drawPixel(nxgl_coord_t x, nxgl_coord_t y,
174  nxgl_mxpixel_t color)
175 {
176  struct nxgl_point_s pos;
177  pos.x = x;
178  pos.y = y;
179  m_pNxWnd->setPixel(&pos, color);
180 }
181 
182 /**
183  * Draw a horizontal line of the specified start position, width, and color.
184  *
185  * @param x The x coordinate of the line.
186  * @param y The y coordinate of the top-most end of the line.
187  * @param width The width of the line in pixels.
188  * @param color The color of the line.
189  */
190 
191 void CGraphicsPort::drawHorizLine(nxgl_coord_t x, nxgl_coord_t y,
192  nxgl_coord_t width, nxgl_mxpixel_t color)
193 {
194  FAR struct nxgl_rect_s dest;
195 
196  // Express the line as a rectangle
197 
198  dest.pt1.x = x;
199  dest.pt1.y = y;
200  dest.pt2.x = x + width - 1;
201  dest.pt2.y = y;
202 
203  // Draw the line
204 
205  if (!m_pNxWnd->fill(&dest, color))
206  {
207  gerr("ERROR: INxWindow::fill failed\n");
208  }
209 }
210 
211 /**
212  * Draw a vertical line of the specified start position, width, and
213  * color.
214  *
215  * @param x The x coordinate of the left-most end of the line.
216  * @param y The y coordinate of the line.
217  * @param height The height of the line in rows.
218  * @param color The color of the line.
219  */
220 
221 void CGraphicsPort::drawVertLine(nxgl_coord_t x, nxgl_coord_t y,
222  nxgl_coord_t height, nxgl_mxpixel_t color)
223 {
224  FAR struct nxgl_rect_s dest;
225 
226  // Express the line as a rectangle
227 
228  dest.pt1.x = x;
229  dest.pt1.y = y;
230  dest.pt2.x = x;
231  dest.pt2.y = y + height - 1;
232 
233  // Draw the line
234 
235  if (!m_pNxWnd->fill(&dest, color))
236  {
237  gerr("ERROR: INxWindow::fill failed\n");
238  }
239 }
240 
241 /**
242  * Draw a line of a fixed color in the window.
243  *
244  * @param x1 - The x coordinate of the start point of the line.
245  * @param y1 - The y coordinate of the start point of the line.
246  * @param x2 - The x coordinate of the end point of the line.
247  * @param y2 - The y coordinate of the end point of the line.
248  * @param color - The color of the line.
249  * @param caps - Draw a circular cap one the ends of the line to support
250  * - better line joins
251  */
252 
253 void CGraphicsPort::drawLine(nxgl_coord_t x1, nxgl_coord_t y1,
254  nxgl_coord_t x2, nxgl_coord_t y2,
255  nxgl_mxpixel_t color, enum INxWindow::ELineCaps caps)
256 {
257  struct nxgl_vector_s vector;
258 
259  vector.pt1.x = x1;
260  vector.pt1.y = y1;
261  vector.pt2.x = x2;
262  vector.pt2.y = y2;
263 
264  if (!m_pNxWnd->drawLine(&vector, 1, color, caps))
265  {
266  gerr("ERROR: INxWindow::drawLine failed\n");
267  }
268 }
269 
270 /**
271  * Draw a filled rectangle to the bitmap.
272  *
273  * @param x The window-relative x coordinate of the rectangle.
274  * @param y The window-relative y coordinate of the rectangle.
275  * @param width The width of the rectangle in pixels.
276  * @param height The height of the rectangle in rows.
277  * @param color The color of the rectangle.
278  */
279 
280 void CGraphicsPort::drawFilledRect(nxgl_coord_t x, nxgl_coord_t y,
281  nxgl_coord_t width, nxgl_coord_t height,
282  nxgl_mxpixel_t color)
283 {
284  struct nxgl_rect_s rect;
285  rect.pt1.x = x;
286  rect.pt1.y = y;
287  rect.pt2.x = x + width - 1;
288  rect.pt2.y = y + height - 1;
289  m_pNxWnd->fill(&rect, color);
290 }
291 
292 /**
293  * Draw an unfilled rectangle to the window
294  *
295  * @param x The window-relative x coordinate of the rectangle.
296  * @param y The window-relative y coordinate of the rectangle.
297  * @param width The width of the rectangle.
298  * @param height The height of the rectangle.
299  * @param color The color of the rectangle outline.
300  */
301 
302 void CGraphicsPort::drawRect(nxgl_coord_t x, nxgl_coord_t y,
303  nxgl_coord_t width, nxgl_coord_t height,
304  nxgl_mxpixel_t color)
305 {
306  drawHorizLine(x, y, width, color);
307  drawHorizLine(x, y + height - 1, width, color);
308  drawVertLine(x, y, height, color);
309  drawVertLine(x + width -1, y, height, color);
310 }
311 
312 /**
313  * Draw a bevelled rectangle to the window.
314  *
315  * @param x The x coordinate of the rectangle.
316  * @param y The y coordinate of the rectangle.
317  * @param width The width of the rectangle.
318  * @param height The height of the rectangle.
319  * @param shineColor The color of the top/left sides.
320  * @param shadowColor The color of the bottom/right sides.
321  */
322 
323 void CGraphicsPort::drawBevelledRect(nxgl_coord_t x, nxgl_coord_t y,
324  nxgl_coord_t width, nxgl_coord_t height,
325  nxgl_mxpixel_t shineColor,
326  nxgl_mxpixel_t shadowColor)
327 {
328  drawHorizLine(x, y, width, shineColor); // Top
329  drawHorizLine(x, y + height - 1, width, shadowColor); // Bottom
330  drawVertLine(x, y + 1, height - 2, shineColor); // Left
331  drawVertLine(x + width - 1, y + 1, height - 2, shadowColor); // Right
332 }
333 
334 /**
335  * Draw an opaque bitmap to the window.
336  *
337  * @param x The window-relative x coordinate to draw the bitmap to.
338  * @param y The window-relative y coordinate to draw the bitmap to.
339  * @param width The width of the bitmap to draw.
340  * @param height The height of the bitmap to draw.
341  * @param bitmap Pointer to the bitmap to draw.
342  * @param bitmapX The window-relative x coordinate within the supplied
343  * bitmap to use as the origin.
344  * @param bitmapY The window-relative y coordinate within the supplied
345  * bitmap to use as the origin.
346  */
347 
348 void CGraphicsPort::drawBitmap(nxgl_coord_t x, nxgl_coord_t y,
349  nxgl_coord_t width, nxgl_coord_t height,
350  const struct SBitmap *bitmap,
351  int bitmapX, int bitmapY)
352 {
353  // origin - The origin of the upper, left-most corner of the full bitmap.
354  // Both dest and origin are in window coordinates, however, origin
355  // may lie outside of the display.
356 
357  struct nxgl_point_s origin;
358  origin.x = x - bitmapX;
359  origin.y = y - bitmapY;
360 
361  // dest - Describes the rectangular on the display that will receive the
362  // the bit map.
363 
364  struct nxgl_rect_s dest;
365  dest.pt1.x = x;
366  dest.pt1.y = y;
367  dest.pt2.x = x + width - 1;
368  dest.pt2.y = y + height - 1;
369 
370  // Blit the bitmap
371 
372  (void)m_pNxWnd->bitmap(&dest, (FAR const void *)bitmap->data, &origin, bitmap->stride);
373 }
374 
375 /**
376  * Draw a bitmap to the window, using the supplied transparent
377  * color as an invisible color.
378  *
379  * @param x The window-relative x coordinate to draw the bitmap to.
380  * @param y The window-relative y coordinate to draw the bitmap to.
381  * @param width The width of the bitmap to draw.
382  * @param height The height of the bitmap to draw.
383  * @param bitmap Pointer to the bitmap to draw.
384  * @param bitmapX The window-relative x coordinate within the supplied bitmap to use as
385  * the origin.
386  * @param bitmapY The window-relative y coordinate within the supplied bitmap to use as
387  * the origin.
388  * @param transparentColor The transparent color used in the bitmap.
389  */
390 
391 void CGraphicsPort::drawBitmap(nxgl_coord_t x, nxgl_coord_t y,
392  nxgl_coord_t width, nxgl_coord_t height,
393  const struct SBitmap *bitmap,
394  int bitmapX, int bitmapY,
395  nxgl_mxpixel_t transparentColor)
396 {
397  // Get the starting position in the image, offset by bitmapX and bitmapY into the image.
398 
399  FAR uint8_t *srcLine = (uint8_t *)bitmap->data +
400  bitmapY * bitmap->stride +
401  ((bitmapX * bitmap->bpp + 7) >> 3);
402  FAR nxwidget_pixel_t *srcPtr = (nxwidget_pixel_t *)srcLine;
403 
404  // Loop until all rows have been displayed
405 
406  nxgl_coord_t firstX = x;
407  nxgl_coord_t lastX = x + width;
408  nxgl_coord_t lastY = y + height;
409 
410  while (y < lastY)
411  {
412  // Search for the next non-transparent pixel in the source image
413 
414  while (*srcPtr == transparentColor)
415  {
416  // The pixel is transparent. Move to the next column
417 
418  if (++x >= lastX)
419  {
420  // We are at the end of the row. Reset to the next row
421 
422  x = firstX;
423  y++;
424 
425  // Was that the last row:
426 
427  if (y >= lastY)
428  {
429  // Yes, then we are finished
430 
431  return;
432  }
433 
434  // Update the source data pointers to the beginning of the next
435  // row
436 
437  srcLine += bitmap->stride;
438  srcPtr = (nxwidget_pixel_t *)srcLine;
439  }
440  else
441  {
442  // This is another transparent pixel on the same row
443 
444  srcPtr++;
445  }
446  }
447 
448  // srcPtr points to the next non-transparent color. Save this
449  // as the start of a run that has length of at least one
450 
451  FAR nxwidget_pixel_t *runPtr = srcPtr;
452  nxgl_coord_t runX = x;
453  nxgl_coord_t runWidth = 0;
454 
455  // Now search for the next transparent pixel on the same row.
456  // This will determine the length of the run
457 
458  do
459  {
460  // This is another non-transparent pixel on the same row
461 
462  runWidth++;
463  srcPtr++;
464 
465  // Move to the next column
466 
467  if (++x >= lastX)
468  {
469  // We are at the end of the row. Reset to the next row
470 
471  x = firstX;
472  y++;
473 
474  // Update the source data pointers to the beginning of the next
475  // row
476 
477  srcLine += bitmap->stride;
478  srcPtr = (nxwidget_pixel_t *)srcLine;
479 
480  // And break out of this loop
481 
482  break;
483  }
484  }
485  while (*srcPtr != transparentColor);
486 
487  // When we come out of the above loop, either (1) srcPtr points to the
488  // next transparent pixel on the same row, or (2) srcPtr points to the
489  // first pixel in the next row.
490 
491  // origin - The origin of the upper, left-most corner of the full bitmap.
492  // Both dest and origin are in window coordinates, however, origin
493  // may lie outside of the display.
494 
495  struct nxgl_point_s origin;
496  origin.x = runX;
497  origin.y = y;
498 
499  // dest - Describes the rectangular on the display that will receive the
500  // the bit map.
501 
502  struct nxgl_rect_s dest;
503  dest.pt1.x = runX;
504  dest.pt1.y = y;
505  dest.pt2.x = runX + runWidth - 1;
506  dest.pt2.y = y;
507 
508  // Blit the bitmap
509 
510  (void)m_pNxWnd->bitmap(&dest, (FAR const void *)runPtr, &origin, bitmap->stride);
511  }
512 }
513 
514 /**
515  * Draw a bitmap to the port in greyscale.
516  *
517  * @param x The window-relative x coordinate to draw the bitmap to.
518  * @param y The window-relative y coordinate to draw the bitmap to.
519  * @param width The width of the bitmap to draw.
520  * @param height The height of the bitmap to draw.
521  * @param bitmap Pointer to the bitmap to draw.
522  * @param bitmapX The window-relative x coordinate within the supplied bitmap to use as
523  * the origin.
524  * @param bitmapY The window-relative y coordinate within the supplied bitmap to use as
525  * the origin.
526  */
527 
528 void CGraphicsPort::drawBitmapGreyScale(nxgl_coord_t x, nxgl_coord_t y,
529  nxgl_coord_t width, nxgl_coord_t height,
530  const struct SBitmap *bitmap,
531  int bitmapX, int bitmapY)
532 {
533  // Working buffer. Holds one converted row from the bitmap
534 
535  FAR nxwidget_pixel_t *run = new nxwidget_pixel_t[width];
536  if (!run)
537  {
538  ginfo("ERROR: Failed to allocated run buffer\n");
539  return;
540  }
541 
542  // Pointer to the beginning of the first source row
543 
544  FAR uint8_t *src = (FAR uint8_t *)bitmap->data + bitmapY * bitmap->stride + bitmapX;
545 
546  // Setup non-changing blit parameters
547 
548  struct nxgl_point_s origin;
549  origin.x = x;
550  origin.y = y;
551 
552  struct nxgl_rect_s dest;
553  dest.pt1.x = x;
554  dest.pt1.y = y;
555  dest.pt2.x = x + width - 1;
556  dest.pt2.y = y;
557 
558  // Convert each row to greyscale and send it to the display
559 
560  for (int row = 0; row < height; row++)
561  {
562  // Convert the next row
563 
564  FAR nxwidget_pixel_t *runSrc = (FAR nxwidget_pixel_t *)src;
565  FAR nxwidget_pixel_t *runDest = run;
566 
567  for (int col = 0; col < width; col++)
568  {
569  // Get the next RGB pixel and break out the individual components
570 
571  nxwidget_pixel_t rgb = *runSrc++;
572  nxwidget_pixel_t r = RGB2RED(rgb);
573  nxwidget_pixel_t g = RGB2GREEN(rgb);
574  nxwidget_pixel_t b = RGB2BLUE(rgb);
575 
576  // A truly accurate greyscale conversion would be complex. Let's
577  // just average.
578 
579  nxwidget_pixel_t avg = (r + g + b) / 3;
580  *runDest++ = MKRGB(avg, avg, avg);
581  }
582 
583  // Now blit the single row
584 
585  (void)m_pNxWnd->bitmap(&dest, run, &origin, bitmap->stride);
586 
587  // Setup for the next source row
588 
589  y++;
590  origin.y = y;
591  dest.pt1.y = y;
592  dest.pt2.y = y;
593 
594  src += bitmap->stride;
595  }
596 
597  delete run;
598 }
599 
600 /**
601  * Draw a string to the window.
602  *
603  * @param pos The window-relative x/y coordinate of the string.
604  * @param bound The window-relative bounds of the string.
605  * @param font The font to draw with.
606  * @param string The string to output.
607  */
608 
609 void CGraphicsPort::drawText(struct nxgl_point_s *pos, CRect *bound,
610  CNxFont *font, const CNxString &string)
611 {
612  _drawText(pos, bound, font, string, 0, string.getLength(), 0, true);
613 }
614 
615 /**
616  * Draw a particular length of a string to the window in a secific color.
617  *
618  * @param pos The window-relative x/y coordinate of the string.
619  * @param bound The window-relative bounds of the string.
620  * @param font The font to draw with.
621  * @param string The string to output.
622  * @param startIndex The start index within the string from which
623  * drawing will commence.
624  * @param length The number of characters to draw.
625  * @param color The color of the string.
626  */
627 
628 void CGraphicsPort::drawText(struct nxgl_point_s *pos, CRect *bound,
629  CNxFont *font, const CNxString &string,
630  int startIndex, int length,
631  nxgl_mxpixel_t color)
632 {
633  // Temporarily change the font color
634 
635  nxgl_mxpixel_t savedColor = font->getColor();
636  font->setColor(color);
637 
638  // Draw the string with this new color
639 
640  _drawText(pos, bound, font, string, startIndex, length, 0, true);
641 
642  // Restore the font color
643 
644  font->setColor(savedColor);
645 }
646 
647 /**
648  * Draw a portion of a string to the window.
649  * @param pos The window-relative x/y coordinate of the string.
650  * @param bound The window-relative bounds of the string.
651  * @param font The font to draw with.
652  * @param string The string to output.
653  * @param startIndex The start index within the string from which
654  * drawing will commence.
655  * @param length The number of characters to draw.
656  */
657 
658 void CGraphicsPort::drawText(struct nxgl_point_s *pos, CRect *bound,
659  CNxFont *font, const CNxString &string,
660  int startIndex, int length)
661 {
662  _drawText(pos, bound, font, string, startIndex, length, 0, true);
663 }
664 
665 /**
666  * Draw a portion of a string to the window and fill the background
667  * in one go.
668  * @param pos The window-relative x/y coordinate of the string.
669  * @param bound The window-relative bounds of the string.
670  * @param font The font to draw with.
671  * @param string The string to output.
672  * @param startIndex The start index within the string from which
673  * drawing will commence.
674  * @param length The number of characters to draw.
675  * @param color Foreground color
676  * @param background Background color
677  */
678 
679 void CGraphicsPort::drawText(struct nxgl_point_s *pos, CRect *bound,
680  CNxFont *font, const CNxString &string,
681  int startIndex, int length,
682  nxgl_mxpixel_t color,
683  nxgl_mxpixel_t background)
684 {
685  nxgl_mxpixel_t savedColor = font->getColor();
686  font->setColor(color);
687 
688  _drawText(pos, bound, font, string, startIndex, length, background, false);
689 
690  font->setColor(savedColor);
691 }
692 
693 /**
694  * The underlying implementation for drawText functions
695  * @param pos The window-relative x/y coordinate of the string.
696  * @param bound The window-relative bounds of the string.
697  * @param font The font to draw with.
698  * @param string The string to output.
699  * @param startIndex The start index within the string from which
700  * drawing will commence.
701  * @param length The number of characters to draw.
702  * @param background Color to use for background if transparent is false.
703  * @param transparent Whether to fill the background.
704  */
705 
706 void CGraphicsPort::_drawText(struct nxgl_point_s *pos, CRect *bound,
707  CNxFont *font, const CNxString &string,
708  int startIndex, int length,
709  nxgl_mxpixel_t background,
710  bool transparent)
711 {
712  // Verify index and length
713 
714  int stringLength = string.getLength();
715  if (startIndex >= stringLength)
716  {
717  return;
718  }
719 
720  int endIndex = startIndex + length;
721  if (endIndex > stringLength)
722  {
723  endIndex = stringLength;
724  }
725 
726 #ifdef CONFIG_NX_WRITEONLY
727  if (transparent)
728  {
729  // Can't render transparently without reading memory.
730 
731  transparent = false;
732  background = m_backColor;
733  }
734 #endif
735 
736  // Allocate a bit of memory to hold the largest rendered font
737 
738  unsigned int bmWidth = ((unsigned int)font->getMaxWidth() * CONFIG_NXWIDGETS_BPP + 7) >> 3;
739  unsigned int bmHeight = (unsigned int)font->getHeight();
740 
741  unsigned int glyphSize = bmWidth * bmHeight;
742  FAR uint8_t *glyph = new uint8_t[glyphSize];
743 
744  // Get the bounding rectangle in NX form
745 
746  struct nxgl_rect_s boundingBox;
747  bound->getNxRect(&boundingBox);
748 
749  // Loop setup
750 
751  struct SBitmap bitmap;
752  bitmap.bpp = CONFIG_NXWIDGETS_BPP;
753  bitmap.fmt = CONFIG_NXWIDGETS_FMT;
754  bitmap.data = (FAR const nxgl_mxpixel_t*)glyph;
755 
756  // Loop for each letter in the sub-string
757 
758  for (int i = startIndex; i < endIndex; i++)
759  {
760  // Get the next letter in the string
761 
762  const nxwidget_char_t letter = string.getCharAt(i);
763 
764  // Get the font metrics for this letter
765 
766  struct nx_fontmetric_s metrics;
767  font->getCharMetrics(letter, &metrics);
768 
769  // Get the width of the font (in pixels)
770 
771  nxgl_coord_t fontWidth = (nxgl_coord_t)(metrics.width + metrics.xoffset);
772 
773  // Does the letter have height? Spaces have width, but no height
774 
775  if (metrics.height > 0 || !transparent)
776  {
777  // Set the current, effective size of the bitmap
778 
779  bitmap.width = fontWidth;
780  bitmap.height = bmHeight;
781  bitmap.stride = (fontWidth * bitmap.bpp + 7) >> 3;
782 
783  // Describe the destination of the font as a bounding box
784 
785  struct nxgl_rect_s dest;
786  dest.pt1.x = pos->x;
787  dest.pt1.y = pos->y;
788  dest.pt2.x = pos->x + fontWidth - 1;
789  dest.pt2.y = pos->y + bmHeight - 1;
790 
791  // Get the interection of the font box and the bounding box
792 
793  struct nxgl_rect_s intersection;
794  nxgl_rectintersect(&intersection, &dest, &boundingBox);
795 
796  // Skip to the next character if this one is completely outside
797  // the bounding box.
798 
799  if (!nxgl_nullrect(&intersection))
800  {
801  // If we have been given a background color, use it to fill the array.
802  // Otherwise initialize the bitmap memory by reading from the display.
803  // The font renderer always renders the fonts on a transparent background.
804 
805  if (!transparent)
806  {
807  // Set the glyph memory to the background color
808 
809  nxwidget_pixel_t *bmPtr = (nxwidget_pixel_t *)bitmap.data;
810  unsigned int npixels = fontWidth * bmHeight;
811  for (unsigned int j = 0; j < npixels; j++)
812  {
813  *bmPtr++ = background;
814  }
815  }
816  else
817  {
818  // Read the current contents of the destination into the glyph memory
819 
820  m_pNxWnd->getRectangle(&dest, &bitmap);
821  }
822 
823  // Render the font into the initialized bitmap
824 
825  font->drawChar(&bitmap, letter);
826 
827  // Then put the font on the display
828 
829  if (!m_pNxWnd->bitmap(&intersection, (FAR const void *)bitmap.data,
830  pos, bitmap.stride))
831  {
832  ginfo("nx_bitmapwindow failed: %d\n", errno);
833  }
834  }
835  }
836 
837  // Adjust the X position for the next character in the string
838 
839  pos->x += fontWidth;
840  }
841 
842  delete glyph;
843 }
844 
845 /**
846  * Copy a rectangular region from the source coordinates to the
847  * destination coordinates.
848  *
849  * @param sourceX Source x coordinate.
850  * @param sourceY Source y coordinate.
851  * @param destX Destination x coordinate.
852  * @param destY Destination y coordinate.
853  * @param width Width of the rectangle to copy.
854  * @param height Height of the rectangle to copy.
855  */
856 
857 void CGraphicsPort::copy(nxgl_coord_t sourceX, nxgl_coord_t sourceY,
858  nxgl_coord_t destX, nxgl_coord_t destY,
859  nxgl_coord_t width, nxgl_coord_t height)
860 {
861  struct nxgl_rect_s rect;
862  struct nxgl_point_s offset;
863 
864  rect.pt1.x = sourceX;
865  rect.pt1.y = sourceY;
866  rect.pt1.x = sourceX + width - 1;
867  rect.pt1.y = sourceY + height - 1;
868 
869  offset.x = destX - sourceX;
870  offset.y = destY - sourceY;
871 
872  (void)m_pNxWnd->move(&rect, &offset);
873 }
874 
875 /**
876  * Move a region by a specified distance in two dimensions.
877  *
878  * @param x X coordinate of the source area to move.
879  * @param y Y coordinate of the source area to move.
880  * @param deltaX Horizontal distance to move.
881  * @param deltaY Vertical distance to move.
882  * @param width Width of the area to move.
883  * @param height Height of the area to move.
884  */
885 
886 void CGraphicsPort::move(nxgl_coord_t x, nxgl_coord_t y,
887  nxgl_coord_t deltaX, nxgl_coord_t deltaY,
888  nxgl_coord_t width, nxgl_coord_t height)
889 {
890  struct nxgl_rect_s rect;
891  rect.pt1.x = x;
892  rect.pt1.y = y;
893  rect.pt2.x = x + width - 1;
894  rect.pt2.y = y + height - 1;
895 
896  struct nxgl_point_s offset;
897  offset.x = deltaX;
898  offset.y = deltaY;
899 
900  (void)m_pNxWnd->move(&rect, &offset);
901 }
902 
903 /**
904  * Convert the region to greyscale.
905  *
906  * @param x X coordinate of the region to change.
907  * @param y Y coordinate of the region to change.
908  * @param width Width of the region to change.
909  * @param height Height of the region to change.
910  */
911 
912 void CGraphicsPort::greyScale(nxgl_coord_t x, nxgl_coord_t y,
913  nxgl_coord_t width, nxgl_coord_t height)
914 {
915  // Allocate memory to hold one row of graphics data
916 
917  unsigned int stride = ((unsigned int)width * CONFIG_NXWIDGETS_BPP + 7) >> 3;
918  FAR uint8_t *rowBuffer = new uint8_t[height * stride];
919  if (!rowBuffer)
920  {
921  return;
922  }
923 
924  // Describe the receiving bitmap memory
925 
926  SBitmap rowBitmap;
927  rowBitmap.bpp = CONFIG_NXWIDGETS_BPP;
928  rowBitmap.fmt = CONFIG_NXWIDGETS_FMT;
929  rowBitmap.width = width;
930  rowBitmap.height = 1;
931  rowBitmap.stride = stride;
932  rowBitmap.data = (FAR const nxgl_mxpixel_t *)rowBuffer;
933 
934  // Partially describe the source rectangle
935 
936  struct nxgl_rect_s rect;
937  rect.pt1.x = x;
938  rect.pt2.x = x + width - 1;
939 
940  // Partially setup the graphics origin
941 
942  struct nxgl_point_s origin;
943  origin.x = x;
944 
945  // Loop for each row in the region to be inverted
946 
947  for (int row = 0; row < height; row++)
948  {
949  // Read the graphic memory corresponding to the row
950 
951  rect.pt1.y = rect.pt2.y = y + row;
952  m_pNxWnd->getRectangle(&rect, &rowBitmap);
953 
954  // Convert each bit to each bit
955 
956  nxwidget_pixel_t *ptr = (nxwidget_pixel_t *)rowBuffer;
957  for (int col = 0; col < width; col++)
958  {
959  // Get the next RGB pixel and break out the individual components
960 
961  nxwidget_pixel_t color = *ptr;
962  uint8_t red = RGB2RED(color);
963  uint8_t green = RGB2GREEN(color);
964  uint8_t blue = RGB2BLUE(color);
965 
966  // A truly accurate greyscale conversion would be complex. Let's
967  // just average.
968 
969  nxwidget_pixel_t avg = (red + green + blue) / 3;
970  *ptr++ = MKRGB(avg, avg, avg);
971  }
972 
973  // Then write the row back to graphics memory
974 
975  origin.y = rect.pt1.y;
976  m_pNxWnd->bitmap(&rect, (FAR const void *)rowBitmap.data,
977  &origin, rowBitmap.stride) ;
978  }
979 
980  delete rowBuffer;
981 }
982 
983 /**
984  * Invert colors in a region. NOTE: This allocates an in-memory
985  * buffer the size of one row in graphic memory. So it may only be
986  * useful for inverting small regions and its only current use of for
987  * the inverted cursor text.
988  *
989  * @param x X coordinate of the region to change.
990  * @param y Y coordinate of the region to change.
991  * @param width Width of the region to change.
992  * @param height Height of the region to change.
993  */
994 
995 void CGraphicsPort::invert(nxgl_coord_t x, nxgl_coord_t y,
996  nxgl_coord_t width, nxgl_coord_t height)
997 {
998  // Allocate memory to hold one row of graphics data
999 
1000  unsigned int stride = ((unsigned int)width * CONFIG_NXWIDGETS_BPP + 7) >> 3;
1001  FAR uint8_t *rowBuffer = new uint8_t[height * stride];
1002  if (!rowBuffer)
1003  {
1004  return;
1005  }
1006 
1007  // Describe the receiving bitmap memory
1008 
1009  SBitmap rowBitmap;
1010  rowBitmap.bpp = CONFIG_NXWIDGETS_BPP;
1011  rowBitmap.fmt = CONFIG_NXWIDGETS_FMT;
1012  rowBitmap.width = width;
1013  rowBitmap.height = 1;
1014  rowBitmap.stride = stride;
1015  rowBitmap.data = (FAR const nxgl_mxpixel_t *)rowBuffer;
1016 
1017  // Partially describe the source rectangle
1018 
1019  struct nxgl_rect_s rect;
1020  rect.pt1.x = x;
1021  rect.pt2.x = x + width - 1;
1022 
1023  // Partially setup the graphics origin
1024 
1025  struct nxgl_point_s origin;
1026  origin.x = x;
1027 
1028  // Loop for each row in the region to be inverted
1029 
1030  for (int row = 0; row < height; row++)
1031  {
1032  // Read the graphic memory corresponding to the row
1033 
1034  rect.pt1.y = rect.pt2.y = y + row;
1035  m_pNxWnd->getRectangle(&rect, &rowBitmap);
1036 
1037  // Invert each bit
1038 
1039  nxwidget_pixel_t *ptr = (nxwidget_pixel_t *)rowBuffer;
1040  for (int col = 0; col < width; col++)
1041  {
1042  nxwidget_pixel_t color = *ptr;
1043  uint8_t red = RGB2RED(color);
1044  uint8_t green = RGB2GREEN(color);
1045  uint8_t blue = RGB2BLUE(color);
1046  *ptr++ = MKRGB(~red, ~green, ~blue);
1047  }
1048 
1049  // Then write the row back to graphics memory
1050 
1051  origin.y = rect.pt1.y;
1052  m_pNxWnd->bitmap(&rect, (FAR const void *)rowBitmap.data,
1053  &origin, rowBitmap.stride) ;
1054  }
1055 
1056  delete rowBuffer;
1057 };
1058 
virtual bool bitmap(FAR const struct nxgl_rect_s *pDest, FAR const void *pSrc, FAR const struct nxgl_point_s *pOrigin, unsigned int stride)=0
void copy(nxgl_coord_t sourceX, nxgl_coord_t sourceY, nxgl_coord_t destX, nxgl_coord_t destY, nxgl_coord_t width, nxgl_coord_t height)
void drawVertLine(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t height, nxgl_mxpixel_t color)
const nxgl_coord_t getY(void) const
void getNxRect(FAR struct nxgl_rect_s *rect) const
Definition: crect.hxx:215
virtual bool move(FAR const struct nxgl_rect_s *pRect, FAR const struct nxgl_point_s *pOffset)=0
CGraphicsPort(INxWindow *pNxWnd, nxgl_mxpixel_t backColor=CONFIG_NXWIDGETS_DEFAULT_BACKGROUNDCOLOR)
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)
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)
virtual void getRectangle(FAR const struct nxgl_rect_s *rect, struct SBitmap *dest)=0
void drawHorizLine(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_mxpixel_t color)
void drawBitmapGreyScale(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, const struct SBitmap *bitmap, int bitmapX, int bitmapY)
uint8_t nxwidget_pixel_t
Definition: nxconfig.hxx:442
const nxgl_mxpixel_t getColor() const
Definition: cnxfont.hxx:115
virtual bool setPixel(FAR const struct nxgl_point_s *pPos, nxgl_mxpixel_t color)=0
const uint8_t getMaxWidth(void) const
Definition: cnxfont.hxx:218
void setColor(const nxgl_mxpixel_t color)
Definition: cnxfont.hxx:126
void greyScale(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height)
uint16_t nxwidget_char_t
Definition: nxconfig.hxx:454
virtual bool drawLine(FAR struct nxgl_vector_s *vector, nxgl_coord_t width, nxgl_mxpixel_t color, enum ELineCaps caps)=0
void drawFilledRect(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, nxgl_mxpixel_t color)
void drawChar(FAR SBitmap *bitmap, nxwidget_char_t letter)
Definition: cnxfont.cxx:114
void drawLine(nxgl_coord_t x1, nxgl_coord_t y1, nxgl_coord_t x2, nxgl_coord_t y2, nxgl_mxpixel_t color, enum INxWindow::ELineCaps caps)
virtual bool getPosition(FAR struct nxgl_point_s *pPos)=0
void invert(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height)
nxgl_coord_t height
Definition: cbitmap.hxx:108
FAR const void * data
Definition: cbitmap.hxx:110
const uint8_t getHeight(void) const
Definition: cnxfont.hxx:229
const nxgl_coord_t getX(void) const
nxgl_coord_t width
Definition: cbitmap.hxx:107
void drawPixel(nxgl_coord_t x, nxgl_coord_t y, nxgl_mxpixel_t color)
virtual bool fill(FAR const struct nxgl_rect_s *pRect, nxgl_mxpixel_t color)=0
void move(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t deltaX, nxgl_coord_t deltaY, nxgl_coord_t width, nxgl_coord_t height)
static const NXWidgets::SRlePaletteBitmapEntry bitmap[]
void _drawText(struct nxgl_point_s *pos, CRect *bound, CNxFont *font, const CNxString &string, int startIndex, int length, nxgl_mxpixel_t background, bool transparent)
void getCharMetrics(nxwidget_char_t letter, FAR struct nx_fontmetric_s *metrics) const
Definition: cnxfont.cxx:220
void drawText(struct nxgl_point_s *pos, CRect *bound, CNxFont *font, const CNxString &string)
void drawRect(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width, nxgl_coord_t height, nxgl_mxpixel_t color)