summaryrefslogtreecommitdiff
path: root/NxWidgets/libnxwidgets
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-10-15 11:09:20 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-10-15 11:09:20 -0600
commit24ee5014675d43c80c0580882fe5cc24ca17e7a8 (patch)
treee723687b37dcce6d8d582830c8ca0d52d057e9c6 /NxWidgets/libnxwidgets
parentb5a37a3e45ac9faea285cc252e742c1c7267a6d7 (diff)
downloadnuttx-24ee5014675d43c80c0580882fe5cc24ca17e7a8.tar.gz
nuttx-24ee5014675d43c80c0580882fe5cc24ca17e7a8.tar.bz2
nuttx-24ee5014675d43c80c0580882fe5cc24ca17e7a8.zip
NxWidgets::CScaledImage: New class that wraps any class that provides IBitMap and adds image scaling
Diffstat (limited to 'NxWidgets/libnxwidgets')
-rw-r--r--NxWidgets/libnxwidgets/Makefile4
-rw-r--r--NxWidgets/libnxwidgets/include/cbitmap.hxx2
-rw-r--r--NxWidgets/libnxwidgets/include/crlepalettebitmap.hxx2
-rw-r--r--NxWidgets/libnxwidgets/include/cscaledbitmap.hxx209
-rw-r--r--NxWidgets/libnxwidgets/include/ibitmap.hxx15
-rw-r--r--NxWidgets/libnxwidgets/src/cbitmap.cxx4
-rw-r--r--NxWidgets/libnxwidgets/src/crlepalettebitmap.cxx2
-rw-r--r--NxWidgets/libnxwidgets/src/cscaledbitmap.cxx583
8 files changed, 807 insertions, 14 deletions
diff --git a/NxWidgets/libnxwidgets/Makefile b/NxWidgets/libnxwidgets/Makefile
index 4f6840aaa..cf219cc7e 100644
--- a/NxWidgets/libnxwidgets/Makefile
+++ b/NxWidgets/libnxwidgets/Makefile
@@ -1,7 +1,7 @@
#################################################################################
# NxWidgets/libnxwidgets/Makefile
#
-# Copyright (C) 2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2012-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@ CXXSRCS = cbitmap.cxx cbgwindow.cxx ccallback.cxx cgraphicsport.cxx
CXXSRCS += clistdata.cxx clistdataitem.cxx cnxfont.cxx
CXXSRCS += cnxserver.cxx cnxstring.cxx cnxtimer.cxx cnxwidget.cxx cnxwindow.cxx
CXXSRCS += cnxtkwindow.cxx cnxtoolbar.cxx crect.cxx crlepalettebitmap.cxx
-CXXSRCS += cstringiterator.cxx ctext.cxx cwidgetcontrol.cxx cwidgeteventhandlerlist.cxx
+CXXSRCS += cscaledbitmap.cxx cstringiterator.cxx ctext.cxx cwidgetcontrol.cxx cwidgeteventhandlerlist.cxx
CXXSRCS += cwindoweventhandlerlist.cxx singletons.cxx
# Widget APIs
CXXSRCS += cbutton.cxx cbuttonarray.cxx ccheckbox.cxx ccyclebutton.cxx
diff --git a/NxWidgets/libnxwidgets/include/cbitmap.hxx b/NxWidgets/libnxwidgets/include/cbitmap.hxx
index 4828ca9cc..0fd133303 100644
--- a/NxWidgets/libnxwidgets/include/cbitmap.hxx
+++ b/NxWidgets/libnxwidgets/include/cbitmap.hxx
@@ -179,7 +179,7 @@ namespace NXWidgets
* @return The bitmap's width.
*/
- const nxgl_coord_t getStride(void) const;
+ const size_t getStride(void) const;
/**
* Use the colors associated with a selected image.
diff --git a/NxWidgets/libnxwidgets/include/crlepalettebitmap.hxx b/NxWidgets/libnxwidgets/include/crlepalettebitmap.hxx
index dd869c476..1235c80fb 100644
--- a/NxWidgets/libnxwidgets/include/crlepalettebitmap.hxx
+++ b/NxWidgets/libnxwidgets/include/crlepalettebitmap.hxx
@@ -235,7 +235,7 @@ namespace NXWidgets
* @return The bitmap's width.
*/
- const nxgl_coord_t getStride(void) const;
+ const size_t getStride(void) const;
/**
* Use the colors associated with a selected image.
diff --git a/NxWidgets/libnxwidgets/include/cscaledbitmap.hxx b/NxWidgets/libnxwidgets/include/cscaledbitmap.hxx
new file mode 100644
index 000000000..4c5d8f729
--- /dev/null
+++ b/NxWidgets/libnxwidgets/include/cscaledbitmap.hxx
@@ -0,0 +1,209 @@
+/****************************************************************************
+ * NxWidgets/libnxwidgets/include/cscaledbitmap.hxx
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX, NxWidgets, nor the names of its contributors
+ * me be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_CSCALEDBITMAP_HXX
+#define __INCLUDE_CSCALEDBITMAP_HXX
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <fixedmath.h>
+#include <debug.h>
+
+#include <nuttx/rgbcolors.h>
+#include <nuttx/nx/nxglib.h>
+
+#include "nxconfig.hxx"
+#include "ibitmap.hxx"
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Implementation Classes
+ ****************************************************************************/
+
+#if defined(__cplusplus)
+
+namespace NXWidgets
+{
+ /**
+ * Class for scaling layer for any bitmap that inherits from IBitMap
+ */
+
+ class CScaledBitmap : public IBitmap
+ {
+ protected:
+ FAR IBitmap *m_bitmap; /**< The bitmap that is being scaled */
+ struct nxgl_size_s m_size; /**< Scaled size of the image */
+ FAR uint8_t *m_rowCache[2]; /**< Two cached rows of the image */
+ unsigned int m_row; /**< Row number of the first cached row */
+ b16_t m_xScale; /**< X scale factor */
+ b16_t m_yScale; /**< Y scale factor */
+
+ /**
+ * Read two rows into the row cache
+ *
+ * @param row - The row number of the first row to cache
+ */
+
+ bool cacheRows(unsigned int row);
+
+ /**
+ * Given an two RGB colors and a fractional value, return the scaled
+ * value between the two colors.
+ *
+ * @param incolor1 - The first color to be used
+ * @param incolor2 - The second color to be used
+ * @param fraction - The fractional value
+ * @param outcolor - The returned, scaled color
+ */
+
+ bool scaleColor(FAR const struct rgbcolor_s &incolor1,
+ FAR const struct rgbcolor_s &incolor2,
+ b16_t fraction, FAR struct rgbcolor_s &outcolor);
+
+ /**
+ * Given an image row and a non-integer column offset, return the
+ * interpolated RGB color value corresponding to that position
+ *
+ * @param row - The pointer to the row in the row cache to use
+ * @param column - The non-integer column offset
+ * @param outcolor - The returned, interpolated color
+ *
+ */
+
+ bool rowColor(FAR uint8_t *row, b16_t column,
+ FAR struct rgbcolor_s &outcolor);
+
+ /**
+ * Copy constructor is protected to prevent usage.
+ */
+
+ inline CScaledBitmap(const CScaledBitmap &bitmap) { }
+
+ public:
+
+ /**
+ * Constructor.
+ *
+ * @param bitmap The bitmap structure being scaled.
+ * @newSize The new, scaled size of the image
+ */
+
+ CScaledBitmap(IBitmap *bitmap, struct nxgl_size_s &newSize);
+
+ /**
+ * Destructor.
+ */
+
+ ~CScaledBitmap(void);
+
+ /**
+ * Get the bitmap's color format.
+ *
+ * @return The bitmap's color format.
+ */
+
+ const uint8_t getColorFormat(void) const;
+
+ /**
+ * Get the bitmap's color format.
+ *
+ * @return The bitmap's pixel depth.
+ */
+
+ const uint8_t getBitsPerPixel(void) const;
+
+ /**
+ * Get the bitmap's width (in pixels/columns).
+ *
+ * @return The bitmap's width (in pixels/columns).
+ */
+
+ const nxgl_coord_t getWidth(void) const;
+
+ /**
+ * Get the bitmap's height (in rows).
+ *
+ * @return The bitmap's height (in rows).
+ */
+
+ inline const nxgl_coord_t getHeight(void) const;
+
+ /**
+ * Get the bitmap's width (in bytes).
+ *
+ * @return The bitmap's width (in bytes).
+ */
+
+ const size_t getStride(void) const;
+
+ /**
+ * Use the colors associated with a selected image.
+ *
+ * @param selected. true: Use colors for a selected widget,
+ * false: Use normal (default) colors.
+ */
+
+ inline void setSelected(bool selected) {}
+
+ /**
+ * Get one row from the bit map image.
+ *
+ * @param x The offset into the row to get
+ * @param y The row number to get
+ * @param width The number of pixels to get from the row
+ * @param data The memory location provided by the caller
+ * in which to return the data. This should be at least
+ * (getWidth()*getBitsPerPixl() + 7)/8 bytes in length
+ * and properly aligned for the pixel color format.
+ * @param True if the run was returned successfully.
+ */
+
+ bool getRun(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width,
+ FAR void *data);
+ };
+}
+
+#endif // __cplusplus
+
+#endif // __INCLUDE_CSCALEDBITMAP_HXX
diff --git a/NxWidgets/libnxwidgets/include/ibitmap.hxx b/NxWidgets/libnxwidgets/include/ibitmap.hxx
index 923df407a..c4e235dc5 100644
--- a/NxWidgets/libnxwidgets/include/ibitmap.hxx
+++ b/NxWidgets/libnxwidgets/include/ibitmap.hxx
@@ -73,9 +73,10 @@
/****************************************************************************
* Included Files
****************************************************************************/
-
+
#include <nuttx/config.h>
+#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
@@ -84,11 +85,11 @@
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
-
+
/****************************************************************************
* Implementation Classes
****************************************************************************/
-
+
#if defined(__cplusplus)
namespace NXWidgets
@@ -114,7 +115,7 @@ namespace NXWidgets
/**
* Get the bitmap's color format.
*
- * @return The bitmap's width.
+ * @return The bitmap's color format.
*/
virtual const uint8_t getColorFormat(void) const = 0;
@@ -130,7 +131,7 @@ namespace NXWidgets
/**
* Get the bitmap's width (in pixels/columns).
*
- * @return The bitmap's pixel depth.
+ * @return The bitmap's width (in pixels/columns).
*/
virtual const nxgl_coord_t getWidth(void) const = 0;
@@ -138,7 +139,7 @@ namespace NXWidgets
/**
* Get the bitmap's height (in rows).
*
- * @return The bitmap's height.
+ * @return The bitmap's height (in rows).
*/
virtual const nxgl_coord_t getHeight(void) const = 0;
@@ -149,7 +150,7 @@ namespace NXWidgets
* @return The bitmap's width.
*/
- virtual const nxgl_coord_t getStride(void) const = 0;
+ virtual const size_t getStride(void) const = 0;
/**
* Use the colors associated with a selected image.
diff --git a/NxWidgets/libnxwidgets/src/cbitmap.cxx b/NxWidgets/libnxwidgets/src/cbitmap.cxx
index c9c974814..c0cf71ea4 100644
--- a/NxWidgets/libnxwidgets/src/cbitmap.cxx
+++ b/NxWidgets/libnxwidgets/src/cbitmap.cxx
@@ -149,7 +149,7 @@ const nxgl_coord_t CBitmap::getHeight(void) const
* @return The bitmap's width.
*/
-const nxgl_coord_t CBitmap::getStride(void) const
+const size_t CBitmap::getStride(void) const
{
return m_bitmap->stride;
}
@@ -172,7 +172,7 @@ bool CBitmap::getRun(nxgl_coord_t x, nxgl_coord_t y, nxgl_coord_t width,
{
// Check ranges. Casts to unsigned int are ugly but permit one-sided comparisons
- if (((unsigned int)x < (unsigned int)width) &&
+ if (((unsigned int)x < (unsigned int)m_bitmap->width) &&
((unsigned int)(x + width) <= (unsigned int)m_bitmap->width) &&
((unsigned int)y < (unsigned int)m_bitmap->height))
{
diff --git a/NxWidgets/libnxwidgets/src/crlepalettebitmap.cxx b/NxWidgets/libnxwidgets/src/crlepalettebitmap.cxx
index 99f7fdbba..241736add 100644
--- a/NxWidgets/libnxwidgets/src/crlepalettebitmap.cxx
+++ b/NxWidgets/libnxwidgets/src/crlepalettebitmap.cxx
@@ -155,7 +155,7 @@ const nxgl_coord_t CRlePaletteBitmap::getHeight(void) const
* @return The bitmap's width.
*/
-const nxgl_coord_t CRlePaletteBitmap::getStride(void) const
+const size_t CRlePaletteBitmap::getStride(void) const
{
// This only works if the bpp is an even multiple of 8-bit bytes
diff --git a/NxWidgets/libnxwidgets/src/cscaledbitmap.cxx b/NxWidgets/libnxwidgets/src/cscaledbitmap.cxx
new file mode 100644
index 000000000..6fe211ca4
--- /dev/null
+++ b/NxWidgets/libnxwidgets/src/cscaledbitmap.cxx
@@ -0,0 +1,583 @@
+/****************************************************************************
+ * NxWidgets/libnxwidgets/src/cscaledbitmap.hxx
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX, NxWidgets, nor the names of its contributors
+ * me be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <cstring>
+
+#include <nuttx/nx/nxglib.h>
+
+#include "cscaledbitmap.hxx"
+
+/****************************************************************************
+ * Pre-Processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Method Implementations
+ ****************************************************************************/
+
+using namespace NXWidgets;
+
+/**
+ * Constructor.
+ *
+ * @param bitmap The bitmap structure being scaled.
+ * @newSize The new, scaled size of the image
+ */
+
+CScaledBitmap::CScaledBitmap(IBitmap *bitmap, struct nxgl_size_s &newSize)
+: m_bitmap(bitmap), m_size(newSize)
+{
+ // xScale will be used to convert a request X position to an X position
+ // in the contained bitmap:
+ //
+ // xImage = xRequested * oldWidth / newWidth
+ // = xRequested * xScale
+
+ m_xScale = itob16((uint32_t)m_bitmap->getWidth()) / newSize.w;
+
+ // Similarly, yScale will be used to convert a request Y position to a Y
+ // positionin the contained bitmap:
+ //
+ // yImage = yRequested * oldHeight / newHeight
+ // = yRequested * yScale
+
+ m_xScale = itob16((uint32_t)m_bitmap->getHeight()) / newSize.h;
+
+ // Allocate and initialize the row cache
+
+ size_t stride = bitmap->getStride();
+ m_rowCache[0] = new uint8_t(stride);
+ m_rowCache[1] = new uint8_t(stride);
+
+ // Read the first two rows into the cache
+
+ cacheRows(0);
+}
+
+/**
+ * Destructor.
+ */
+
+CScaledBitmap::~CScaledBitmap(void)
+{
+ if (m_rowCache[0])
+ {
+ delete m_rowCache[0];
+ }
+
+ if (m_rowCache[1])
+ {
+ delete m_rowCache[1];
+ }
+}
+
+/**
+ * Get the bitmap's color format.
+ *
+ * @return The bitmap's width.
+ */
+
+const uint8_t CScaledBitmap::getColorFormat(void) const
+{
+ return m_bitmap->getColorFormat();
+}
+
+/**
+ * Get the bitmap's color format.
+ *
+ * @return The bitmap's color format.
+ */
+
+const uint8_t CScaledBitmap::getBitsPerPixel(void) const
+{
+ return m_bitmap->getBitsPerPixel();
+}
+
+/**
+ * Get the bitmap's width (in pixels/columns).
+ *
+ * @return The bitmap's pixel depth.
+ */
+
+const nxgl_coord_t CScaledBitmap::getWidth(void) const
+{
+ return m_size.w;
+}
+
+/**
+ * Get the bitmap's height (in rows).
+ *
+ * @return The bitmap's height (in rows).
+ */
+
+const nxgl_coord_t CScaledBitmap::getHeight(void) const
+{
+ return m_size.h;
+}
+
+/**
+ * Get the bitmap's width (in bytes).
+ *
+ * @return The bitmap's width (in bytes).
+ */
+
+const size_t CScaledBitmap::getStride(void) const
+{
+ return (m_bitmap->getBitsPerPixel() * m_size.w + 7) / 8;
+}
+
+/**
+ * Get one row from the bit map image.
+ *
+ * @param x The offset into the row to get
+ * @param y The row number to get
+ * @param width The number of pixels to get from the row
+ * @param data The memory location provided by the caller
+ * in which to return the data. This should be at least
+ * (getWidth()*getBitsPerPixl() + 7)/8 bytes in length
+ * and properly aligned for the pixel color format.
+ * @param True if the run was returned successfully.
+ */
+
+bool CScaledBitmap::getRun(nxgl_coord_t x, nxgl_coord_t y,
+ nxgl_coord_t width, FAR void *data)
+{
+#if CONFIG_NXWIDGETS_FMT == FB_FMT_RGB8_332 || CONFIG_NXWIDGETS_FMT == FB_FMT_RGB24
+ FAR uint8_t *dest = (FAR uint8_t *)data;
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB16_565
+ FAR uint16_t *dest = (FAR uint16_t *)data;
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB32
+ FAR uint32_t *dest = (FAR uint32_t *)data;
+#else
+# error Unsupported, invalid, or undefined color format
+#endif
+
+ // Check ranges. Casts to unsigned int are ugly but permit one-sided comparisons
+
+ if (((unsigned int)x >= (unsigned int)m_size.w) &&
+ ((unsigned int)(x + width) > (unsigned int)m_size.w) &&
+ ((unsigned int)y <= (unsigned int)m_size.h))
+ {
+ return false;
+ }
+
+ // Get the row number in the unscaled image corresponding to the
+ // requested y position. This must be either the exact row or the
+ // closest row just before the requested position
+
+ b16_t row16 = y * m_yScale;
+ nxgl_coord_t row = b16toi(row16);
+
+ // Get that row and the one after it into the row cache. We know that
+ // the pixel value that we want is one between the two rows. This
+ // may seem wasteful to read two entire rows. However, in normal usage
+ // we will be traversal each image from top-left to bottom-right in
+ // order. In that case, the caching is most efficient.
+
+ if (!cacheRows(row))
+ {
+ return false;
+ }
+
+ // Now scale and copy the data from the cached row data
+
+ for (int i = 0; i < width; i++, x++)
+ {
+ // Get the column number in the unscaled row corresponding to the
+ // requested x position. This must be either the exact column or the
+ // closest column just before the requested position
+
+ b16_t column = x * m_xScale;
+
+ // Get the color at the position on the first row
+
+ struct rgbcolor_s color1;
+ if (!rowColor(m_rowCache[0], column, color1))
+ {
+ gdbg("ERROR rowColor failed for the first row\n");
+ return false;
+ }
+
+ // Get the color at the position on the first row
+
+ struct rgbcolor_s color2;
+ if (!rowColor(m_rowCache[1], column, color2))
+ {
+ gdbg("ERROR rowColor failed for the second row\n");
+ return false;
+ }
+
+ // Check for transparent colors
+
+ bool transparent1;
+ bool transparent2;
+
+#if CONFIG_NXWIDGETS_FMT == FB_FMT_RGB8_332
+ uint8_t color = RGBTO8(color1.r, color1.g, color1.b);
+ transparent1 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+ color = RGBTO8(color2.r, color2.g, color2.b);
+ transparent2 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB16_565
+ uint16_t color = RGBTO16(color1.r, color1.g, color1.b);
+ transparent1 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+ color = RGBTO16(color2.r, color2.g, color2.b);
+ transparent2 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB24 || CONFIG_NXWIDGETS_FMT == FB_FMT_RGB32
+ uint32_t color = RGBTO24(color1.r, color1.g, color1.b);
+ transparent1 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+ color = RGBTO24(color2.r, color2.g, color2.b);
+ transparent2 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+#else
+# error Unsupported, invalid, or undefined color format
+#endif
+
+ // Is one of the colors transparent?
+
+ struct rgbcolor_s scaledColor;
+ b16_t fraction b16frac(row16);
+
+ if (transparent1 || transparent2)
+ {
+ // Yes.. don't interpolate within transparent regions or
+ // between transparent and opaque regions.
+
+ // Get the color closest to the requested position
+
+ if (fraction < b16HALF)
+ {
+ scaledColor.r = color1.r;
+ scaledColor.g = color1.g;
+ scaledColor.b = color1.b;
+ }
+ else
+ {
+ scaledColor.r = color2.r;
+ scaledColor.g = color2.g;
+ scaledColor.b = color2.b;
+ }
+ }
+ else
+ {
+ // No.. both colors are opaque
+
+ if (!scaleColor(color1, color2, fraction, scaledColor))
+ {
+ return false;
+ }
+ }
+
+ // Write the interpolated data to the user buffer
+
+#if CONFIG_NXWIDGETS_FMT == FB_FMT_RGB8_332
+ color = RGBTO8(scaledColor.r, scaledColor.g, scaledColor.b);
+ *dest++ = color;
+
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB16_565
+ color = RGBTO16(scaledColor.r, scaledColor.g, scaledColor.b);
+ *dest++ = color;
+
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB24
+ *dest++ = color2.b;
+ *dest++ = color2.r;
+ *dest++ = color2.g;
+
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB32
+ color = RGBTO24(scaledColor.r, scaledColor.g, scaledColor.b);
+ *dest++ = color;
+
+#else
+# error Unsupported, invalid, or undefined color format
+#endif
+ }
+
+ return true;
+}
+
+/**
+ * Read two rows into the row cache
+ *
+ * @param row - The row number of the first row to cache
+ */
+
+bool CScaledBitmap::cacheRows(unsigned int row)
+{
+ nxgl_coord_t bitmapWidth = m_bitmap->getWidth();
+ nxgl_coord_t bitmapHeight = m_bitmap->getHeight();
+
+ // A common case is to advance by one row. In this case, we only
+ // need to read one row
+
+ if (row == m_row + 1)
+ {
+ // Swap rows
+
+ FAR uint8_t *saveRow = m_rowCache[0];
+ m_rowCache[0] = m_rowCache[1];
+ m_rowCache[1] = saveRow;
+
+ // Save number of the first row that we have in the cache
+
+ m_row = row;
+
+ // Now read the new row into the second row cache buffer
+
+ if (++row >= (unsigned int)bitmapHeight)
+ {
+ row = bitmapHeight - 1;
+ }
+
+ if (!m_bitmap->getRun(0, row, bitmapWidth, &m_rowCache[1]))
+ {
+ gdbg("Failed to read bitmap row %d\n", row);
+ return false;
+ }
+ }
+
+ // Do we need to read two new rows? Or do we already have the
+ // request row in the cache?
+
+ else if (row != m_row)
+ {
+ // Read the first row into the cache
+
+ if (row >= (unsigned int)bitmapHeight)
+ {
+ row = bitmapHeight - 1;
+ }
+
+ if (!m_bitmap->getRun(0, row, bitmapWidth, &m_rowCache[0]))
+ {
+ gdbg("Failed to read bitmap row %d\n", row);
+ return false;
+ }
+
+ // Save number of the first row that we have in the cache
+
+ m_row = row;
+
+ // Read the next row into the cache
+
+ if (++row >= (unsigned int)bitmapHeight)
+ {
+ row = bitmapHeight - 1;
+ }
+
+ if (!m_bitmap->getRun(0, row, bitmapWidth, &m_rowCache[1]))
+ {
+ gdbg("Failed to read bitmap row %d\n", row);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Given an two RGB colors and a fractional value, return the scaled
+ * value between the two colors.
+ *
+ * @param incolor1 - The first color to be used
+ * @param incolor2 - The second color to be used
+ * @param fraction - The fractional value
+ * @param outcolor - The returned, scaled color
+ */
+
+bool CScaledBitmap::scaleColor(FAR const struct rgbcolor_s &incolor1,
+ FAR const struct rgbcolor_s &incolor2,
+ b16_t fraction, FAR struct rgbcolor_s &outcolor)
+{
+ unsigned int red;
+ unsigned int green;
+ unsigned int blue;
+ b16_t remainder = b16ONE - fraction;
+
+ red = (unsigned int)incolor1.r * fraction +
+ (unsigned int)incolor2.r * remainder;
+ green = (unsigned int)incolor1.g * fraction +
+ (unsigned int)incolor2.g * remainder;
+ blue = (unsigned int)incolor1.b * fraction +
+ (unsigned int)incolor2.b * remainder;
+
+ outcolor.r = red < 256 ? red : 255;
+ outcolor.g = green < 256 ? green : 255;
+ outcolor.b = blue < 256 ? blue : 255;
+ return true;
+}
+
+/**
+ * Given an image row and a non-integer column offset, return the
+ * interpolated RGB color value corresponding to that position
+ *
+ * @param row - The pointer to the row in the row cache to use
+ * @param column - The non-integer column offset
+ * @param outcolor - The returned, interpolated color
+ *
+ */
+
+bool CScaledBitmap::rowColor(FAR uint8_t *row, b16_t column,
+ FAR struct rgbcolor_s &outcolor)
+{
+ // This is the col at or just before the pixel of interest
+
+ nxgl_coord_t col1 = b16toi(column);
+ nxgl_coord_t col2 = col1 + 1;
+
+ nxgl_coord_t bitmapWidth = m_bitmap->getWidth();
+ if (col2 >= bitmapWidth)
+ {
+ col2 = bitmapWidth - 1;
+ }
+
+ b16_t fraction = b16frac(column);
+
+ struct rgbcolor_s color1;
+ struct rgbcolor_s color2;
+
+ bool transparent1;
+ bool transparent2;
+
+#if CONFIG_NXWIDGETS_FMT == FB_FMT_RGB8_332
+ uint8_t color = row[col1];
+ color1.r = RBG8RED(color);
+ color1.g = RBG8GREEN(color);
+ color1.b = RBG8BLUE(color);
+
+ transparent1 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+ color = row[col2];
+ color2.r = RBG8RED(color);
+ color2.g = RBG8GREEN(color);
+ color2.b = RBG8BLUE(color);
+
+ transparent2 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB16_565
+ FAR uint16_t *row16 = (FAR uint16_t*)row;
+ uint16_t color = row16[col1];
+ color1.r = RBG16RED(color);
+ color1.g = RBG16GREEN(color);
+ color1.b = RBG16BLUE(color);
+
+ transparent1 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+ color = row16[col2];
+ color2.r = RBG16RED(color);
+ color2.g = RBG16GREEN(color);
+ color2.b = RBG16BLUE(color);
+
+ transparent2 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB24
+ unsigned int ndx = 3*col1;
+ color1.r = row[ndx+2];
+ color1.g = row[ndx+1];
+ color1.b = row[ndx];
+
+ uint32_t color = RGBTO24(color1.r, color1.g, color1.b);
+ transparent1 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+ ndx = 3*col2;
+ color2.r = row[ndx+2];
+ color2.g = row[ndx+1];
+ color2.b = row[ndx];
+
+ color = RGBTO24(color2.r, color2.g, color2.b);
+ transparent2 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+#elif CONFIG_NXWIDGETS_FMT == FB_FMT_RGB32
+ FAR uint32_t *row32 = (FAR uint32_t*)row;
+ uint32_t color = row32[col1];
+ color1.r = RBG24RED(color);
+ color1.g = RBG24GREEN(color);
+ color1.b = RBG24BLUE(color);
+
+ transparent1 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+ color = row32[col2];
+ color2.r = RBG24RED(color);
+ color2.g = RBG24GREEN(color);
+ color2.b = RBG24BLUE(color);
+
+ transparent2 = (color == CONFIG_NXWIDGETS_TRANSPARENT_COLOR);
+
+#else
+# error Unsupported, invalid, or undefined color format
+#endif
+
+ // Is one of the colors transparent?
+
+ if (transparent1 || transparent2)
+ {
+ // Yes.. don't interpolate within transparent regions or
+ // between transparent and opaque regions.
+
+ // Return the color closest to the requested position
+
+ if (fraction < b16HALF)
+ {
+ outcolor.r = color1.r;
+ outcolor.g = color1.b;
+ outcolor.g = color1.g;
+ }
+ else
+ {
+ outcolor.r = color2.r;
+ outcolor.g = color2.b;
+ outcolor.g = color2.g;
+ }
+
+ return true;
+ }
+ else
+ {
+ // No.. both colors are opaque
+
+ return scaleColor(color1, color2, fraction, outcolor);
+ }
+}