Add Inter Fonts
This commit is contained in:
		@ -0,0 +1,82 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
* Copyright (c) 2018(-2024) STMicroelectronics.
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* This file is part of the TouchGFX 4.24.0 distribution.
 | 
			
		||||
*
 | 
			
		||||
* This software is licensed under terms that can be found in the LICENSE file in
 | 
			
		||||
* the root directory of this software component.
 | 
			
		||||
* If no LICENSE file comes with this software, it is provided AS-IS.
 | 
			
		||||
*
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file touchgfx/VectorFontRendererImpl.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * Defines the touchgfx::VectorFontRendererImpl class, implementing the rendering of vector font glyphs.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef TOUCHGFX_VECTORFONTRENDERERIMPL_HPP
 | 
			
		||||
#define TOUCHGFX_VECTORFONTRENDERERIMPL_HPP
 | 
			
		||||
 | 
			
		||||
#include <touchgfx/hal/Types.hpp>
 | 
			
		||||
#include <touchgfx/hal/VectorFontRenderer.hpp>
 | 
			
		||||
 | 
			
		||||
namespace touchgfx
 | 
			
		||||
{
 | 
			
		||||
/**
 | 
			
		||||
 * Implementation of the VectorFontRenderer interface
 | 
			
		||||
 */
 | 
			
		||||
class VectorFontRendererImpl : public VectorFontRenderer
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    VectorFontRendererImpl();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get buffers for commands and points for the vector font.
 | 
			
		||||
     *
 | 
			
		||||
     * @param pointArray         Array for the points.
 | 
			
		||||
     * @param pointArraySize     Size of the pointArray.
 | 
			
		||||
     * @param commandArray       Array for the commands.
 | 
			
		||||
     * @param commandArraySize   Size of the commandArray.
 | 
			
		||||
     */
 | 
			
		||||
    static void getVectorFontBuffers(float*& pointArray, int& pointArraySize, uint8_t*& commandArray, int& commandArraySize);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Draws one glyph from the provided data.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  canvasAreaAbs         The canvas dimensions in absolute coordinates.
 | 
			
		||||
     * @param  invalidatedAreaRel    The area which should be updated in relative coordinates to the canvas area.
 | 
			
		||||
     * @param  data                  Data containing tags and points for all contours of the glyph.
 | 
			
		||||
     * @param  font                  The font to use.
 | 
			
		||||
     * @param  color                 The color of the glyph.
 | 
			
		||||
     * @param  alpha                 The transparency of the glyph.
 | 
			
		||||
     * @param  rotation              Rotation to do before drawing the glyph.
 | 
			
		||||
     * @param  x                     Distance to advance horizontally.
 | 
			
		||||
     * @param  y                     Distance to move down.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void drawGlyph(const Rect& canvasAreaAbs, const Rect& invalidatedAreaRel, const uint16_t* data, const Font* font, colortype color, uint8_t alpha, TextRotation rotation, int x, int y);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    VectorRenderer* renderer;
 | 
			
		||||
 | 
			
		||||
    uint8_t* cmds; // Buffer of commands for VectorRenderer::drawPath
 | 
			
		||||
    float* points; // Buffer of points for VectorRenderer::drawPath
 | 
			
		||||
    int commandBufferSize;
 | 
			
		||||
    int pointBufferSize;
 | 
			
		||||
 | 
			
		||||
    uint16_t cmdIndex;
 | 
			
		||||
    uint16_t pointsIndex;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Draws a single contour.
 | 
			
		||||
     *
 | 
			
		||||
     * @param tagCount   The number of tags for the contour to draw.
 | 
			
		||||
     * @param tagList    List of tags; one tag-bit for each cmd (segment) of the contour.
 | 
			
		||||
     * @param pointList  The points defining the contour, including intermediate control points.
 | 
			
		||||
     */
 | 
			
		||||
    const int16_t* drawContour(uint16_t tagCount, const uint16_t* const tagList, const int16_t* const pointList);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace touchgfx
 | 
			
		||||
 | 
			
		||||
#endif // TOUCHGFX_VECTORFONTRENDERERIMPL_HPP
 | 
			
		||||
@ -0,0 +1,270 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
* Copyright (c) 2018(-2024) STMicroelectronics.
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* This file is part of the TouchGFX 4.24.0 distribution.
 | 
			
		||||
*
 | 
			
		||||
* This software is licensed under terms that can be found in the LICENSE file in
 | 
			
		||||
* the root directory of this software component.
 | 
			
		||||
* If no LICENSE file comes with this software, it is provided AS-IS.
 | 
			
		||||
*
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file touchgfx/hal/PaintARGB8888Impl.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * Implements ARGB8888 software painter functions for widgets
 | 
			
		||||
 */
 | 
			
		||||
#ifndef TOUCHGFX_PAINTARGB8888IMPL_HPP
 | 
			
		||||
#define TOUCHGFX_PAINTARGB8888IMPL_HPP
 | 
			
		||||
 | 
			
		||||
#include <touchgfx/Color.hpp>
 | 
			
		||||
#include <touchgfx/hal/Paint.hpp>
 | 
			
		||||
#include <touchgfx/hal/PaintImpl.hpp>
 | 
			
		||||
 | 
			
		||||
namespace touchgfx
 | 
			
		||||
{
 | 
			
		||||
namespace paint
 | 
			
		||||
{
 | 
			
		||||
namespace argb8888
 | 
			
		||||
{
 | 
			
		||||
void lineFromColor(uint32_t* const ptr, const int16_t count, const uint32_t painterColor, const uint8_t alpha)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t* framebuffer = ptr;
 | 
			
		||||
    const uint32_t* const lineEnd = framebuffer + count;
 | 
			
		||||
    const uint32_t color = (painterColor & 0x00FFFFFF) | (alpha << 24);
 | 
			
		||||
 | 
			
		||||
    if (alpha == 0xFF)
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            *framebuffer = color;
 | 
			
		||||
        } while (++framebuffer < lineEnd);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        const uint8_t painterRed = Color::getRed(color);
 | 
			
		||||
        const uint8_t painterGreen = Color::getGreen(color);
 | 
			
		||||
        const uint8_t painterBlue = Color::getBlue(color);
 | 
			
		||||
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            const uint32_t argbBg = *framebuffer;
 | 
			
		||||
            const uint8_t alphaBg = argbBg >> 24;
 | 
			
		||||
            if (alphaBg == 0)
 | 
			
		||||
            {
 | 
			
		||||
                *framebuffer = color;
 | 
			
		||||
            }
 | 
			
		||||
            else if (alpha > 0)
 | 
			
		||||
            {
 | 
			
		||||
                // DMA2D blending algorithm
 | 
			
		||||
                const uint8_t alphaMult = LCD::div255(alpha * alphaBg);
 | 
			
		||||
                const uint8_t alphaOut = alpha + alphaBg - alphaMult;
 | 
			
		||||
                const uint8_t blueBg = (argbBg & 0xFF);
 | 
			
		||||
                const uint8_t greenBg = ((argbBg >> 8) & 0xFF);
 | 
			
		||||
                const uint8_t redBg = ((argbBg >> 16) & 0xFF);
 | 
			
		||||
                *framebuffer = ((painterBlue * alpha + blueBg * alphaBg - blueBg * alphaMult) / alphaOut) |
 | 
			
		||||
                               (((painterGreen * alpha + greenBg * alphaBg - greenBg * alphaMult) / alphaOut) << 8) |
 | 
			
		||||
                               (((painterRed * alpha + redBg * alphaBg - redBg * alphaMult) / alphaOut) << 16) |
 | 
			
		||||
                               (alphaOut << 24);
 | 
			
		||||
            }
 | 
			
		||||
        } while (++framebuffer < lineEnd);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lineFromRGB888(uint8_t* const ptr, const uint8_t* const data, const int16_t length, const uint8_t alpha)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* framebuffer = ptr;
 | 
			
		||||
    const uint8_t* const chunkend = framebuffer + length * 4;
 | 
			
		||||
    const uint8_t* bitmapPointer = data;
 | 
			
		||||
 | 
			
		||||
    if (alpha == 255)
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            *framebuffer++ = *bitmapPointer++;
 | 
			
		||||
            *framebuffer++ = *bitmapPointer++;
 | 
			
		||||
            *framebuffer++ = *bitmapPointer++;
 | 
			
		||||
            *framebuffer++ = 255;
 | 
			
		||||
        } while (framebuffer < chunkend);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t alphaBg = framebuffer[3];
 | 
			
		||||
            const uint8_t alphaMult = LCD::div255(alpha * alphaBg);
 | 
			
		||||
            const uint8_t alphaOut = alpha + alphaBg - alphaMult;
 | 
			
		||||
 | 
			
		||||
            const uint8_t blueBg = *framebuffer;
 | 
			
		||||
            const uint8_t blueFg = *bitmapPointer++;
 | 
			
		||||
            *framebuffer++ = (blueFg * alpha + blueBg * alphaBg - blueBg * alphaMult) / alphaOut;
 | 
			
		||||
            const uint8_t greenBg = *framebuffer;
 | 
			
		||||
            const uint8_t greenFg = *bitmapPointer++;
 | 
			
		||||
            *framebuffer++ = (greenFg * alpha + greenBg * alphaBg - greenBg * alphaMult) / alphaOut;
 | 
			
		||||
            const uint8_t redBg = *framebuffer;
 | 
			
		||||
            const uint8_t redFg = *bitmapPointer++;
 | 
			
		||||
            *framebuffer++ = (redFg * alpha + redBg * alphaBg - redBg * alphaMult) / alphaOut;
 | 
			
		||||
            *framebuffer++ = alphaOut;
 | 
			
		||||
        } while (framebuffer < chunkend);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lineFromRGB565(uint8_t* const ptr, const uint16_t* const data, const int16_t length, const uint8_t alpha)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* framebuffer = ptr;
 | 
			
		||||
    const uint8_t* const chunkend = framebuffer + length * 4;
 | 
			
		||||
    const uint16_t* bitmapPointer = data;
 | 
			
		||||
 | 
			
		||||
    if (alpha == 255)
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            const uint16_t pixel565 = *bitmapPointer++;
 | 
			
		||||
            *framebuffer++ = Color::getBlueFromRGB565(pixel565);
 | 
			
		||||
            *framebuffer++ = Color::getGreenFromRGB565(pixel565);
 | 
			
		||||
            *framebuffer++ = Color::getRedFromRGB565(pixel565);
 | 
			
		||||
            *framebuffer++ = 255;
 | 
			
		||||
        } while (framebuffer < chunkend);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t alphaBg = framebuffer[3];
 | 
			
		||||
            const uint8_t alphaMult = LCD::div255(alpha * alphaBg);
 | 
			
		||||
            const uint8_t alphaOut = alpha + alphaBg - alphaMult;
 | 
			
		||||
 | 
			
		||||
            const uint8_t blueBg = *framebuffer;
 | 
			
		||||
            const uint8_t blueFg = Color::getBlueFromRGB565(*bitmapPointer);
 | 
			
		||||
            *framebuffer++ = (blueFg * alpha + blueBg * alphaBg - blueBg * alphaMult) / alphaOut;
 | 
			
		||||
            const uint8_t greenBg = *framebuffer;
 | 
			
		||||
            const uint8_t greenFg = Color::getGreenFromRGB565(*bitmapPointer);
 | 
			
		||||
            *framebuffer++ = (greenFg * alpha + greenBg * alphaBg - greenBg * alphaMult) / alphaOut;
 | 
			
		||||
            const uint8_t redBg = *framebuffer;
 | 
			
		||||
            const uint8_t redFg = Color::getRedFromRGB565(*bitmapPointer);
 | 
			
		||||
            *framebuffer++ = (redFg * alpha + redBg * alphaBg - redBg * alphaMult) / alphaOut;
 | 
			
		||||
            *framebuffer++ = alphaOut;
 | 
			
		||||
            bitmapPointer++;
 | 
			
		||||
        } while (framebuffer < chunkend);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lineFromARGB8888(uint8_t* const ptr, const uint32_t* const data, const int16_t length, const uint8_t alpha)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* framebuffer = ptr;
 | 
			
		||||
    const uint8_t* const chunkend = framebuffer + length * 4;
 | 
			
		||||
    const uint32_t* bitmapPointer = data;
 | 
			
		||||
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        const uint8_t srcAlpha = (*bitmapPointer) >> 24;
 | 
			
		||||
        const uint8_t alphaFg = LCD::div255(alpha * srcAlpha);
 | 
			
		||||
        const uint8_t alphaBg = framebuffer[3];
 | 
			
		||||
        if (alphaFg == 255 || alphaBg == 0)
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t blueFg = *bitmapPointer;
 | 
			
		||||
            *framebuffer++ = blueFg;
 | 
			
		||||
            const uint8_t greenFg = (*bitmapPointer) >> 8;
 | 
			
		||||
            *framebuffer++ = greenFg;
 | 
			
		||||
            const uint8_t redFg = (*bitmapPointer) >> 16;
 | 
			
		||||
            *framebuffer++ = redFg;
 | 
			
		||||
            *framebuffer++ = alphaFg;
 | 
			
		||||
        }
 | 
			
		||||
        else if (alphaFg)
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t alphaMult = LCD::div255(alphaFg * alphaBg);
 | 
			
		||||
            const uint8_t alphaOut = alphaFg + alphaBg - alphaMult;
 | 
			
		||||
 | 
			
		||||
            const uint8_t blueBg = *framebuffer;
 | 
			
		||||
            const uint8_t blueFg = *bitmapPointer;
 | 
			
		||||
            *framebuffer++ = (blueFg * alphaFg + blueBg * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
            const uint8_t greenBg = *framebuffer;
 | 
			
		||||
            const uint8_t greenFg = (*bitmapPointer) >> 8;
 | 
			
		||||
            *framebuffer++ = (greenFg * alphaFg + greenBg * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
            const uint8_t redBg = *framebuffer;
 | 
			
		||||
            const uint8_t redFg = (*bitmapPointer) >> 16;
 | 
			
		||||
            *framebuffer++ = (redFg * alphaFg + redBg * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
            *framebuffer++ = alphaOut;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            framebuffer += 4;
 | 
			
		||||
        }
 | 
			
		||||
        bitmapPointer++;
 | 
			
		||||
    } while (framebuffer < chunkend);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lineFromL8RGB888(uint8_t* const ptr, const uint8_t* const data, const int16_t length, const uint8_t alpha)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* framebuffer = ptr;
 | 
			
		||||
    const uint8_t* const chunkend = framebuffer + length * 4;
 | 
			
		||||
    const uint8_t* bitmapPointer = data;
 | 
			
		||||
 | 
			
		||||
    if (alpha == 0xFF)
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t* src = &blendL8CLUT[*bitmapPointer++ * 3];
 | 
			
		||||
            *framebuffer++ = *src++;
 | 
			
		||||
            *framebuffer++ = *src++;
 | 
			
		||||
            *framebuffer++ = *src;
 | 
			
		||||
            *framebuffer++ = 0xFF;
 | 
			
		||||
        } while (framebuffer < chunkend);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t* src = &blendL8CLUT[*bitmapPointer++ * 3];
 | 
			
		||||
            const uint8_t ialpha = 0xFF - alpha;
 | 
			
		||||
            *framebuffer = LCD::div255(*src++ * alpha + *framebuffer * ialpha);
 | 
			
		||||
            framebuffer++;
 | 
			
		||||
            *framebuffer = LCD::div255(*src++ * alpha + *framebuffer * ialpha);
 | 
			
		||||
            framebuffer++;
 | 
			
		||||
            *framebuffer = LCD::div255(*src * alpha + *framebuffer * ialpha);
 | 
			
		||||
            framebuffer++;
 | 
			
		||||
            *framebuffer = *framebuffer + alpha - LCD::div255(*framebuffer * alpha);
 | 
			
		||||
            framebuffer++;
 | 
			
		||||
        } while (framebuffer < chunkend);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void lineFromL8ARGB8888(uint8_t* const ptr, const uint8_t* const data, const int16_t length, const uint8_t alpha)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* framebuffer = ptr;
 | 
			
		||||
    const uint8_t* const chunkend = framebuffer + length * 4;
 | 
			
		||||
    const uint8_t* bitmapPointer = data;
 | 
			
		||||
 | 
			
		||||
    do
 | 
			
		||||
    {
 | 
			
		||||
        const uint32_t src = reinterpret_cast<const uint32_t*>(blendL8CLUT)[*bitmapPointer++];
 | 
			
		||||
        const uint8_t srcAlpha = src >> 24;
 | 
			
		||||
        const uint8_t a = LCD::div255(alpha * srcAlpha);
 | 
			
		||||
        if (a == 0xFF)
 | 
			
		||||
        {
 | 
			
		||||
            *framebuffer++ = src;       // Blue
 | 
			
		||||
            *framebuffer++ = src >> 8;  // Green
 | 
			
		||||
            *framebuffer++ = src >> 16; // Red
 | 
			
		||||
            *framebuffer++ = 0xFF;      // Alpha
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t ialpha = 0xFF - a;
 | 
			
		||||
            *framebuffer = LCD::div255((src & 0xFF) * a + *framebuffer * ialpha);
 | 
			
		||||
            framebuffer++;
 | 
			
		||||
            *framebuffer = LCD::div255(((src >> 8) & 0xFF) * a + *framebuffer * ialpha);
 | 
			
		||||
            framebuffer++;
 | 
			
		||||
            *framebuffer = LCD::div255(((src >> 16) & 0xFF) * a + *framebuffer * ialpha);
 | 
			
		||||
            framebuffer++;
 | 
			
		||||
            *framebuffer = *framebuffer + a - LCD::div255(*framebuffer * a);
 | 
			
		||||
            framebuffer++;
 | 
			
		||||
        }
 | 
			
		||||
    } while (framebuffer < chunkend);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace argb8888
 | 
			
		||||
} // namespace paint
 | 
			
		||||
} // namespace touchgfx
 | 
			
		||||
 | 
			
		||||
#endif // TOUCHGFX_PAINTARGB8888IMPL_HPP
 | 
			
		||||
@ -0,0 +1,55 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
* Copyright (c) 2018(-2024) STMicroelectronics.
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* This file is part of the TouchGFX 4.24.0 distribution.
 | 
			
		||||
*
 | 
			
		||||
* This software is licensed under terms that can be found in the LICENSE file in
 | 
			
		||||
* the root directory of this software component.
 | 
			
		||||
* If no LICENSE file comes with this software, it is provided AS-IS.
 | 
			
		||||
*
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file touchgfx/hal/VectorFontRenderer.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * Defines the touchgfx::VectorFontRenderer class.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef TOUCHGFX_VECTORFONTRENDERER_HPP
 | 
			
		||||
#define TOUCHGFX_VECTORFONTRENDERER_HPP
 | 
			
		||||
 | 
			
		||||
#include <touchgfx/Font.hpp>
 | 
			
		||||
#include <touchgfx/hal/VectorRenderer.hpp>
 | 
			
		||||
 | 
			
		||||
namespace touchgfx
 | 
			
		||||
{
 | 
			
		||||
/**
 | 
			
		||||
 * Abstract interface for classes implementing vector font rendering.
 | 
			
		||||
 */
 | 
			
		||||
class VectorFontRenderer
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /** Virtual destructor. */
 | 
			
		||||
    virtual ~VectorFontRenderer()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Draws one glyph from the provided data.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  canvasAreaAbs         The canvas dimensions in absolute coordinates.
 | 
			
		||||
     * @param  invalidatedAreaRel    The area which should be updated in relative coordinates to the canvas area.
 | 
			
		||||
     * @param  data                  Data containing tags and points for all contours of the glyph.
 | 
			
		||||
     * @param  font                  The font to use.
 | 
			
		||||
     * @param  color                 The color of the glyph.
 | 
			
		||||
     * @param  alpha                 The transparency of the glyph.
 | 
			
		||||
     * @param  rotation              Rotation to do before drawing the glyph.
 | 
			
		||||
     * @param  x                     Distance to advance horizontally.
 | 
			
		||||
     * @param  y                     Distance to move down.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void drawGlyph(const Rect& canvasAreaAbs, const Rect& invalidatedAreaRel, const uint16_t* data, const Font* font, colortype color, uint8_t alpha, TextRotation rotation, int x, int y) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace touchgfx
 | 
			
		||||
 | 
			
		||||
#endif // TOUCHGFX_VECTORFONTRENDERER_HPP
 | 
			
		||||
@ -0,0 +1,295 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
* Copyright (c) 2018(-2024) STMicroelectronics.
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* This file is part of the TouchGFX 4.24.0 distribution.
 | 
			
		||||
*
 | 
			
		||||
* This software is licensed under terms that can be found in the LICENSE file in
 | 
			
		||||
* the root directory of this software component.
 | 
			
		||||
* If no LICENSE file comes with this software, it is provided AS-IS.
 | 
			
		||||
*
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file touchgfx/widgets/QRCode.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * Declares the touchgfx::QRCode class.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef TOUCHGFX_QRCODE_HPP
 | 
			
		||||
#define TOUCHGFX_QRCODE_HPP
 | 
			
		||||
 | 
			
		||||
#include <touchgfx/Color.hpp>
 | 
			
		||||
#include <touchgfx/Unicode.hpp>
 | 
			
		||||
#include <touchgfx/hal/Types.hpp>
 | 
			
		||||
#include <touchgfx/widgets/Widget.hpp>
 | 
			
		||||
#include <touchgfx/widgets/utils/qrcodegen.hpp>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Macro to calculate the size of the buffers required for QR code generation.
 | 
			
		||||
 */
 | 
			
		||||
#define QRCODE_BUFFER_SIZE(version) ((((version)*4 + 17) * ((version)*4 + 17) + 7) / 8 + 1)
 | 
			
		||||
 | 
			
		||||
namespace touchgfx
 | 
			
		||||
{
 | 
			
		||||
/**
 | 
			
		||||
 * Widget capable of generating and showing a QRCode.
 | 
			
		||||
 *
 | 
			
		||||
 * This widget uses the QR Code generator library (C).
 | 
			
		||||
 * https://www.nayuki.io/page/qr-code-generator-library
 | 
			
		||||
 *
 | 
			
		||||
 * Important: The application must allocate buffers and provide these
 | 
			
		||||
 * through QRCode::setBuffers.
 | 
			
		||||
 *
 | 
			
		||||
 * The QRCode supports framebuffer formats RGB565, RGB888, ARGB8888.
 | 
			
		||||
 */
 | 
			
		||||
class QRCode : public Widget
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a new QRCode using black and white colors with
 | 
			
		||||
     * alpha 255. The user must supply buffers and set the scale and
 | 
			
		||||
     * QR version as wanted.
 | 
			
		||||
     */
 | 
			
		||||
    QRCode();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Convert a text to QRCode data and save in the buffer.
 | 
			
		||||
     * The function returns false if the encoding of the string does
 | 
			
		||||
     * not fit in the QRCode. This depends on the version of the
 | 
			
		||||
     * QRCode and the ECCLevel. If the text was not accepted, the
 | 
			
		||||
     * QRCode Widget does not draw anything.
 | 
			
		||||
     * User must call invalidate() after changing the
 | 
			
		||||
     * data.
 | 
			
		||||
     *
 | 
			
		||||
     * @param text The text to show in the QRCode.
 | 
			
		||||
     * @return True if data was converted.
 | 
			
		||||
     */
 | 
			
		||||
    bool convertStringToQRCode(const char* text);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Convert data to QRCode data and save in the buffer.
 | 
			
		||||
     * The function returns false if the encoding of the data does
 | 
			
		||||
     * not fit in the QRCode. This depends on the version of the
 | 
			
		||||
     * QRCode and the ECCLevel. If the data was not accepted, the
 | 
			
		||||
     * QRCode Widget does not draw anything.
 | 
			
		||||
     * User must call invalidate() after changing the data. This
 | 
			
		||||
     * function can e.g. be used to store UTF8 encoded strings.
 | 
			
		||||
     *
 | 
			
		||||
     * @param data The data to show in the QRCode.
 | 
			
		||||
     * @param length Length of the data.
 | 
			
		||||
     * @return True if data was converted.
 | 
			
		||||
     */
 | 
			
		||||
    bool convertBinaryDataToQRCode(const uint8_t* data, size_t length);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the scale of the QRCode.
 | 
			
		||||
     * Each bit will be shown as scale pixels.
 | 
			
		||||
     *
 | 
			
		||||
     * @param newScale The scale to use.
 | 
			
		||||
     */
 | 
			
		||||
    void setScale(int newScale)
 | 
			
		||||
    {
 | 
			
		||||
        // Multiply the size of the QRCode Container by the scale
 | 
			
		||||
        // Every QR Code version has a specific size, so we can't use arbitrary dimensions
 | 
			
		||||
        scale = newScale;
 | 
			
		||||
        updateWidthAndHeight();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the current scale of the QRCode.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The current scale.
 | 
			
		||||
     *
 | 
			
		||||
     * @see setScale
 | 
			
		||||
     */
 | 
			
		||||
    int getScale() const
 | 
			
		||||
    {
 | 
			
		||||
        return scale;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the version (size) of the QRCode.
 | 
			
		||||
     * Version is between 1 to 40.
 | 
			
		||||
     *
 | 
			
		||||
     * @param version The QRCode version to use.
 | 
			
		||||
     */
 | 
			
		||||
    void setQRCodeVersion(uint8_t version)
 | 
			
		||||
    {
 | 
			
		||||
        qrCodeVersion = version;
 | 
			
		||||
        sizeOfQRCodeSymbol = version * 4 + 17;
 | 
			
		||||
        updateWidthAndHeight();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the current QRCode version.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The current version.
 | 
			
		||||
     *
 | 
			
		||||
     * @see setQRCodeVersion
 | 
			
		||||
     */
 | 
			
		||||
    uint8_t getQRCodeVersion() const
 | 
			
		||||
    {
 | 
			
		||||
        return qrCodeVersion;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** ECC levels */
 | 
			
		||||
    enum ECCLevel
 | 
			
		||||
    {
 | 
			
		||||
        ECC_LOW = 0,      ///< Low level of ECC (handles around 7% faults)
 | 
			
		||||
        ECC_MED = 1,      ///< Medium level of ECC (handles around 15% faults)
 | 
			
		||||
        ECC_QUARTILE = 2, ///< Good level of ECC (handles around 25% faults)
 | 
			
		||||
        ECC_HIGH = 3      ///< High level of ECC (handles around 30% faults)
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the desired level of error correction codes.
 | 
			
		||||
     *
 | 
			
		||||
     * @param level The level of ECC.
 | 
			
		||||
     */
 | 
			
		||||
    void setErrorCorrectionLevel(ECCLevel level)
 | 
			
		||||
    {
 | 
			
		||||
        eccLevel = level;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the current error correction level.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The current error correction level.
 | 
			
		||||
     *
 | 
			
		||||
     * @see setErrorCorrectionLevel
 | 
			
		||||
     */
 | 
			
		||||
    ECCLevel getErrorCorrectionLevel() const
 | 
			
		||||
    {
 | 
			
		||||
        return eccLevel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the buffers used for QRCode generation.
 | 
			
		||||
     * The length of the buffers must match the version of the QRCode
 | 
			
		||||
     * used.  Use the above macro QRCODE_BUFFER_SIZE(version) when
 | 
			
		||||
     * allocating buffers.
 | 
			
		||||
     * The qrBuffer is holding the QRCode bit-stream.  The tempBuffer
 | 
			
		||||
     * is only used during QRCode generation. It can be used for other
 | 
			
		||||
     * purposes afterwards and shared between Widgets.
 | 
			
		||||
     *
 | 
			
		||||
     * @param qrBuffer Buffer to store the QRcode.
 | 
			
		||||
     * @param tempBuffer Scratch buffer used during QRCode generation.
 | 
			
		||||
     */
 | 
			
		||||
    void setBuffers(uint8_t* qrBuffer, uint8_t* tempBuffer)
 | 
			
		||||
    {
 | 
			
		||||
        qrCodeData = qrBuffer;
 | 
			
		||||
        qrTempBuffer = tempBuffer;
 | 
			
		||||
        qrCodeData[0] = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the opacity (alpha value). This can be used to fade it away by gradually
 | 
			
		||||
     * decreasing the alpha value from 255 (solid) to 0 (invisible).
 | 
			
		||||
     *
 | 
			
		||||
     * @param  newAlpha The new alpha value. 255=solid, 0=invisible.
 | 
			
		||||
     *
 | 
			
		||||
     * @note The user code must call invalidate() in order to update the display.
 | 
			
		||||
     */
 | 
			
		||||
    void setAlpha(uint8_t newAlpha)
 | 
			
		||||
    {
 | 
			
		||||
        alpha = newAlpha;
 | 
			
		||||
        ialpha = 0xFF - newAlpha;
 | 
			
		||||
        multiplyAlphaColors();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the current alpha value of the widget. The alpha value is in range 255
 | 
			
		||||
     * (solid) to 0 (invisible).
 | 
			
		||||
     *
 | 
			
		||||
     * @return The current alpha value.
 | 
			
		||||
     *
 | 
			
		||||
     * @see setAlpha
 | 
			
		||||
     */
 | 
			
		||||
    uint8_t getAlpha() const
 | 
			
		||||
    {
 | 
			
		||||
        return alpha;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Sets the colors used for the QRCode.
 | 
			
		||||
     * Black and White is traditionally used, but other colors will
 | 
			
		||||
     * also work.
 | 
			
		||||
     *
 | 
			
		||||
     * @param colorBlack The color used for 'black' pixels.
 | 
			
		||||
     * @param colorWhite The color used the 'white' pixels.
 | 
			
		||||
     */
 | 
			
		||||
    void setColors(colortype colorBlack, colortype colorWhite)
 | 
			
		||||
    {
 | 
			
		||||
        // Split in RGB
 | 
			
		||||
        r0 = Color::getRed(colorBlack);
 | 
			
		||||
        g0 = Color::getGreen(colorBlack);
 | 
			
		||||
        b0 = Color::getBlue(colorBlack);
 | 
			
		||||
        r1 = Color::getRed(colorWhite);
 | 
			
		||||
        g1 = Color::getGreen(colorWhite);
 | 
			
		||||
        b1 = Color::getBlue(colorWhite);
 | 
			
		||||
        // Calculate RGB565 values
 | 
			
		||||
        color0_565 = getRGB565Color(colorBlack);
 | 
			
		||||
        color1_565 = getRGB565Color(colorWhite);
 | 
			
		||||
        // Premultiply alpha
 | 
			
		||||
        multiplyAlphaColors();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void draw(const Rect& invalidatedArea) const;
 | 
			
		||||
    virtual Rect getSolidRect() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void updateWidthAndHeight();
 | 
			
		||||
    uint8_t* drawBitRGB565(uint8_t* dst, bool on, int pixels) const;
 | 
			
		||||
    uint8_t* drawBitRGB565Blend(uint8_t* dst, bool on, int pixels) const;
 | 
			
		||||
    uint8_t* drawBitRGB888(uint8_t* dst, bool on, int pixels) const;
 | 
			
		||||
    uint8_t* drawBitRGB888Blend(uint8_t* dst, bool on, int pixels) const;
 | 
			
		||||
    uint8_t* drawBitARGB8888(uint8_t* dst, bool on, int pixels) const;
 | 
			
		||||
    uint8_t* drawBitARGB8888Blend(uint8_t* dst, bool on, int pixels) const;
 | 
			
		||||
 | 
			
		||||
    void multiplyAlphaColors()
 | 
			
		||||
    {
 | 
			
		||||
        alphaR0 = alpha * r0;
 | 
			
		||||
        alphaR1 = alpha * r1;
 | 
			
		||||
        alphaG0 = alpha * g0;
 | 
			
		||||
        alphaG1 = alpha * g1;
 | 
			
		||||
        alphaB0 = alpha * b0;
 | 
			
		||||
        alphaB1 = alpha * b1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FORCE_INLINE_FUNCTION static uint16_t getRGB565Color(colortype color)
 | 
			
		||||
    {
 | 
			
		||||
        return ((color >> 8) & 0xF800) | ((color >> 5) & 0x07E0) | ((color >> 3) & 0x001F);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FORCE_INLINE_FUNCTION static uint16_t getRGB565ColorFromRGB(uint8_t red, uint8_t green, uint8_t blue)
 | 
			
		||||
    {
 | 
			
		||||
        return ((red << 8) & 0xF800) | ((green << 3) & 0x07E0) | ((blue >> 3) & 0x001F);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FORCE_INLINE_FUNCTION static uint8_t div255(uint16_t num)
 | 
			
		||||
    {
 | 
			
		||||
        return (num + 1 + (num >> 8)) >> 8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FORCE_INLINE_FUNCTION bool getQRBit(int x, int y) const
 | 
			
		||||
    {
 | 
			
		||||
        const int index = y * sizeOfQRCodeSymbol + x;
 | 
			
		||||
        const int value = qrCodeData[(index >> 3) + 1];
 | 
			
		||||
        return (value >> (index & 7)) & 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t* qrCodeData;
 | 
			
		||||
    uint8_t* qrTempBuffer;
 | 
			
		||||
    uint8_t qrCodeVersion;
 | 
			
		||||
    int sizeOfQRCodeSymbol;
 | 
			
		||||
    int scale;
 | 
			
		||||
    ECCLevel eccLevel;
 | 
			
		||||
    uint16_t color0_565, color1_565;
 | 
			
		||||
    uint16_t alphaR0, alphaR1, alphaG0, alphaG1, alphaB0, alphaB1;
 | 
			
		||||
    uint8_t r0, g0, b0, r1, g1, b1;
 | 
			
		||||
    uint8_t alpha, ialpha; ///< The Alpha and inverse Alpha for this QR code.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace touchgfx
 | 
			
		||||
 | 
			
		||||
#endif // TOUCHGFX_QRCODE_HPP
 | 
			
		||||
@ -0,0 +1,42 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
* Copyright (c) 2018(-2024) STMicroelectronics.
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* This file is part of the TouchGFX 4.24.0 distribution.
 | 
			
		||||
*
 | 
			
		||||
* This software is licensed under terms that can be found in the LICENSE file in
 | 
			
		||||
* the root directory of this software component.
 | 
			
		||||
* If no LICENSE file comes with this software, it is provided AS-IS.
 | 
			
		||||
*
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @file touchgfx/widgets/canvas/PainterARGB8888LinearGradient.hpp
 | 
			
		||||
 *
 | 
			
		||||
 * Declares the touchgfx::PainterARGB8888LinearGradient class.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef TOUCHGFX_PAINTERARGB8888LINEARGRADIENT_HPP
 | 
			
		||||
#define TOUCHGFX_PAINTERARGB8888LINEARGRADIENT_HPP
 | 
			
		||||
 | 
			
		||||
#include <touchgfx/hal/Types.hpp>
 | 
			
		||||
#include <touchgfx/widgets/canvas/AbstractPainterLinearGradient.hpp>
 | 
			
		||||
 | 
			
		||||
namespace touchgfx
 | 
			
		||||
{
 | 
			
		||||
/**
 | 
			
		||||
 * An abstract class for creating painter classes for drawing canvas widgets. All canvas widgets
 | 
			
		||||
 * need a painter to fill the shape drawn with a CanvasWidgetRenderer. The painter must provide
 | 
			
		||||
 * the color of a pixel on a given coordinate, which will the be blended into the framebuffer
 | 
			
		||||
 * depending on the position of the canvas widget and the transparency of the given pixel.
 | 
			
		||||
 */
 | 
			
		||||
class PainterARGB8888LinearGradient : public AbstractPainterLinearGradient
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual void paint(uint8_t* destination, int16_t offset, int16_t widgetX, int16_t widgetY, int16_t count, uint8_t alpha) const;
 | 
			
		||||
 | 
			
		||||
    virtual void tearDown() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace touchgfx
 | 
			
		||||
 | 
			
		||||
#endif // TOUCHGFX_PAINTERARGB8888LINEARGRADIENT_HPP
 | 
			
		||||
@ -0,0 +1,381 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
* Copyright (c) 2018(-2024) STMicroelectronics.
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* This file is part of the TouchGFX 4.24.0 distribution.
 | 
			
		||||
*
 | 
			
		||||
* This software is licensed under terms that can be found in the LICENSE file in
 | 
			
		||||
* the root directory of this software component.
 | 
			
		||||
* If no LICENSE file comes with this software, it is provided AS-IS.
 | 
			
		||||
*
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * QR Code generator library (C)
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) Project Nayuki. (MIT License)
 | 
			
		||||
 * https://www.nayuki.io/page/qr-code-generator-library
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
 * this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 * the Software without restriction, including without limitation the rights to
 | 
			
		||||
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 | 
			
		||||
 * the Software, and to permit persons to whom the Software is furnished to do so,
 | 
			
		||||
 * subject to the following conditions:
 | 
			
		||||
 * - The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 *   all copies or substantial portions of the Software.
 | 
			
		||||
 * - The Software is provided "as is", without warranty of any kind, express or
 | 
			
		||||
 *   implied, including but not limited to the warranties of merchantability,
 | 
			
		||||
 *   fitness for a particular purpose and noninfringement. In no event shall the
 | 
			
		||||
 *   authors or copyright holders be liable for any claim, damages or other
 | 
			
		||||
 *   liability, whether in an action of contract, tort or otherwise, arising from,
 | 
			
		||||
 *   out of or in connection with the Software or the use or other dealings in the
 | 
			
		||||
 *   Software.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef TOUCHGFX_QRCODEGEN_HPP
 | 
			
		||||
#define TOUCHGFX_QRCODEGEN_HPP
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <touchgfx/hal/Types.hpp>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This library creates QR Code symbols, which is a type of two-dimension barcode.
 | 
			
		||||
 * Invented by Denso Wave and described in the ISO/IEC 18004 standard.
 | 
			
		||||
 * A QR Code structure is an immutable square grid of dark and light cells.
 | 
			
		||||
 * The library provides functions to create a QR Code from text or binary data.
 | 
			
		||||
 * The library covers the QR Code Model 2 specification, supporting all versions (sizes)
 | 
			
		||||
 * from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
 | 
			
		||||
 *
 | 
			
		||||
 * Ways to create a QR Code object:
 | 
			
		||||
 * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary().
 | 
			
		||||
 * - Low level: Custom-make the list of segments and call
 | 
			
		||||
 *   qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced().
 | 
			
		||||
 * (Note that all ways require supplying the desired error correction level and various byte buffers.)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*---- Enum and struct types----*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The error correction level in a QR Code symbol.
 | 
			
		||||
 */
 | 
			
		||||
enum qrcodegen_Ecc
 | 
			
		||||
{
 | 
			
		||||
    // Must be declared in ascending order of error protection
 | 
			
		||||
    // so that an internal qrcodegen function works properly
 | 
			
		||||
    qrcodegen_Ecc_LOW = 0,  // The QR Code can tolerate about  7% erroneous codewords
 | 
			
		||||
    qrcodegen_Ecc_MEDIUM,   // The QR Code can tolerate about 15% erroneous codewords
 | 
			
		||||
    qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords
 | 
			
		||||
    qrcodegen_Ecc_HIGH      // The QR Code can tolerate about 30% erroneous codewords
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The mask pattern used in a QR Code symbol.
 | 
			
		||||
 */
 | 
			
		||||
enum qrcodegen_Mask
 | 
			
		||||
{
 | 
			
		||||
    // A special value to tell the QR Code encoder to
 | 
			
		||||
    // automatically select an appropriate mask pattern
 | 
			
		||||
    qrcodegen_Mask_AUTO = -1,
 | 
			
		||||
    // The eight actual mask patterns
 | 
			
		||||
    qrcodegen_Mask_0 = 0,
 | 
			
		||||
    qrcodegen_Mask_1,
 | 
			
		||||
    qrcodegen_Mask_2,
 | 
			
		||||
    qrcodegen_Mask_3,
 | 
			
		||||
    qrcodegen_Mask_4,
 | 
			
		||||
    qrcodegen_Mask_5,
 | 
			
		||||
    qrcodegen_Mask_6,
 | 
			
		||||
    qrcodegen_Mask_7
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Describes how a segment's data bits are interpreted.
 | 
			
		||||
 */
 | 
			
		||||
enum qrcodegen_Mode
 | 
			
		||||
{
 | 
			
		||||
    qrcodegen_Mode_NUMERIC = 0x1,
 | 
			
		||||
    qrcodegen_Mode_ALPHANUMERIC = 0x2,
 | 
			
		||||
    qrcodegen_Mode_BYTE = 0x4,
 | 
			
		||||
    qrcodegen_Mode_KANJI = 0x8,
 | 
			
		||||
    qrcodegen_Mode_ECI = 0x7
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A segment of character/binary/control data in a QR Code symbol.
 | 
			
		||||
 * The mid-level way to create a segment is to take the payload data
 | 
			
		||||
 * and call a factory function such as qrcodegen_makeNumeric().
 | 
			
		||||
 * The low-level way to create a segment is to custom-make the bit buffer
 | 
			
		||||
 * and initialize a qrcodegen_Segment struct with appropriate values.
 | 
			
		||||
 * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data.
 | 
			
		||||
 * Any segment longer than this is meaningless for the purpose of generating QR Codes.
 | 
			
		||||
 * Moreover, the maximum allowed bit length is 32767 because
 | 
			
		||||
 * the largest QR Code (version 40) has 31329 modules.
 | 
			
		||||
 */
 | 
			
		||||
struct qrcodegen_Segment
 | 
			
		||||
{
 | 
			
		||||
    // The mode indicator of this segment.
 | 
			
		||||
    enum qrcodegen_Mode mode;
 | 
			
		||||
 | 
			
		||||
    // The length of this segment's unencoded data. Measured in characters for
 | 
			
		||||
    // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode.
 | 
			
		||||
    // Always zero or positive. Not the same as the data's bit length.
 | 
			
		||||
    int numChars;
 | 
			
		||||
 | 
			
		||||
    // The data bits of this segment, packed in bitwise big endian.
 | 
			
		||||
    // Can be null if the bit length is zero.
 | 
			
		||||
    uint8_t* data;
 | 
			
		||||
 | 
			
		||||
    // The number of valid data bits used in the buffer. Requires
 | 
			
		||||
    // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8.
 | 
			
		||||
    // The character count (numChars) must agree with the mode and the bit buffer length.
 | 
			
		||||
    int bitLength;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*---- Macro constants and functions ----*/
 | 
			
		||||
 | 
			
		||||
#define qrcodegen_VERSION_MIN 1  // The minimum version number supported in the QR Code Model 2 standard
 | 
			
		||||
#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard
 | 
			
		||||
 | 
			
		||||
// Calculates the number of bytes needed to store any QR Code up to and including the given version number,
 | 
			
		||||
// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];'
 | 
			
		||||
// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16).
 | 
			
		||||
// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX.
 | 
			
		||||
#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n)*4 + 17) * ((n)*4 + 17) + 7) / 8 + 1)
 | 
			
		||||
 | 
			
		||||
// The worst-case number of bytes needed to store one QR Code, up to and including
 | 
			
		||||
// version 40. This value equals 3918, which is just under 4 kilobytes.
 | 
			
		||||
// Use this more convenient value to avoid calculating tighter memory bounds for buffers.
 | 
			
		||||
#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX)
 | 
			
		||||
 | 
			
		||||
/*---- Functions (high level) to generate QR Codes ----*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Encodes the given text string to a QR Code, returning true if successful.
 | 
			
		||||
 * If the data is too long to fit in any version in the given range
 | 
			
		||||
 * at the given ECC level, then false is returned.
 | 
			
		||||
 *
 | 
			
		||||
 * The input text must be encoded in UTF-8 and contain no NULs.
 | 
			
		||||
 * Requires 1 <= minVersion <= maxVersion <= 40.
 | 
			
		||||
 *
 | 
			
		||||
 * The smallest possible QR Code version within the given range is automatically
 | 
			
		||||
 * chosen for the output. Iff boostEcl is true, then the ECC level of the result
 | 
			
		||||
 * may be higher than the ecl argument if it can be done without increasing the
 | 
			
		||||
 * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or
 | 
			
		||||
 * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow).
 | 
			
		||||
 *
 | 
			
		||||
 * About the arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion):
 | 
			
		||||
 * - Before calling the function:
 | 
			
		||||
 *   - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow
 | 
			
		||||
 *     reading and writing; hence each array must have a length of at least len.
 | 
			
		||||
 *   - The two ranges must not overlap (aliasing).
 | 
			
		||||
 *   - The initial state of both ranges can be uninitialized
 | 
			
		||||
 *     because the function always writes before reading.
 | 
			
		||||
 * - After the function returns:
 | 
			
		||||
 *   - Both ranges have no guarantee on which elements are initialized and what values are stored.
 | 
			
		||||
 *   - tempBuffer contains no useful data and should be treated as entirely uninitialized.
 | 
			
		||||
 *   - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule().
 | 
			
		||||
 *
 | 
			
		||||
 * If successful, the resulting QR Code may use numeric,
 | 
			
		||||
 * alphanumeric, or byte mode to encode the text.
 | 
			
		||||
 *
 | 
			
		||||
 * In the most optimistic case, a QR Code at version 40 with low ECC
 | 
			
		||||
 * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string
 | 
			
		||||
 * up to 4296 characters, or any digit string up to 7089 characters.
 | 
			
		||||
 * These numbers represent the hard upper limit of the QR Code standard.
 | 
			
		||||
 *
 | 
			
		||||
 * Please consult the QR Code specification for information on
 | 
			
		||||
 * data capacities per version, ECC level, and text encoding mode.
 | 
			
		||||
 */
 | 
			
		||||
bool qrcodegen_encodeText(const char* text, uint8_t tempBuffer[], uint8_t qrcode[],
 | 
			
		||||
                          enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Encodes the given binary data to a QR Code, returning true if successful.
 | 
			
		||||
 * If the data is too long to fit in any version in the given range
 | 
			
		||||
 * at the given ECC level, then false is returned.
 | 
			
		||||
 *
 | 
			
		||||
 * Requires 1 <= minVersion <= maxVersion <= 40.
 | 
			
		||||
 *
 | 
			
		||||
 * The smallest possible QR Code version within the given range is automatically
 | 
			
		||||
 * chosen for the output. Iff boostEcl is true, then the ECC level of the result
 | 
			
		||||
 * may be higher than the ecl argument if it can be done without increasing the
 | 
			
		||||
 * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or
 | 
			
		||||
 * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow).
 | 
			
		||||
 *
 | 
			
		||||
 * About the arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion):
 | 
			
		||||
 * - Before calling the function:
 | 
			
		||||
 *   - The array ranges dataAndTemp[0 : len] and qrcode[0 : len] must allow
 | 
			
		||||
 *     reading and writing; hence each array must have a length of at least len.
 | 
			
		||||
 *   - The two ranges must not overlap (aliasing).
 | 
			
		||||
 *   - The input array range dataAndTemp[0 : dataLen] should normally be
 | 
			
		||||
 *     valid UTF-8 text, but is not required by the QR Code standard.
 | 
			
		||||
 *   - The initial state of dataAndTemp[dataLen : len] and qrcode[0 : len]
 | 
			
		||||
 *     can be uninitialized because the function always writes before reading.
 | 
			
		||||
 * - After the function returns:
 | 
			
		||||
 *   - Both ranges have no guarantee on which elements are initialized and what values are stored.
 | 
			
		||||
 *   - dataAndTemp contains no useful data and should be treated as entirely uninitialized.
 | 
			
		||||
 *   - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule().
 | 
			
		||||
 *
 | 
			
		||||
 * If successful, the resulting QR Code will use byte mode to encode the data.
 | 
			
		||||
 *
 | 
			
		||||
 * In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte
 | 
			
		||||
 * sequence up to length 2953. This is the hard upper limit of the QR Code standard.
 | 
			
		||||
 *
 | 
			
		||||
 * Please consult the QR Code specification for information on
 | 
			
		||||
 * data capacities per version, ECC level, and text encoding mode.
 | 
			
		||||
 */
 | 
			
		||||
bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[],
 | 
			
		||||
                            enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);
 | 
			
		||||
 | 
			
		||||
/*---- Functions (low level) to generate QR Codes ----*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Encodes the given segments to a QR Code, returning true if successful.
 | 
			
		||||
 * If the data is too long to fit in any version at the given ECC level,
 | 
			
		||||
 * then false is returned.
 | 
			
		||||
 *
 | 
			
		||||
 * The smallest possible QR Code version is automatically chosen for
 | 
			
		||||
 * the output. The ECC level of the result may be higher than the
 | 
			
		||||
 * ecl argument if it can be done without increasing the version.
 | 
			
		||||
 *
 | 
			
		||||
 * About the byte arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX):
 | 
			
		||||
 * - Before calling the function:
 | 
			
		||||
 *   - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow
 | 
			
		||||
 *     reading and writing; hence each array must have a length of at least len.
 | 
			
		||||
 *   - The two ranges must not overlap (aliasing).
 | 
			
		||||
 *   - The initial state of both ranges can be uninitialized
 | 
			
		||||
 *     because the function always writes before reading.
 | 
			
		||||
 *   - The input array segs can contain segments whose data buffers overlap with tempBuffer.
 | 
			
		||||
 * - After the function returns:
 | 
			
		||||
 *   - Both ranges have no guarantee on which elements are initialized and what values are stored.
 | 
			
		||||
 *   - tempBuffer contains no useful data and should be treated as entirely uninitialized.
 | 
			
		||||
 *   - Any segment whose data buffer overlaps with tempBuffer[0 : len]
 | 
			
		||||
 *     must be treated as having invalid values in that array.
 | 
			
		||||
 *   - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule().
 | 
			
		||||
 *
 | 
			
		||||
 * Please consult the QR Code specification for information on
 | 
			
		||||
 * data capacities per version, ECC level, and text encoding mode.
 | 
			
		||||
 *
 | 
			
		||||
 * This function allows the user to create a custom sequence of segments that switches
 | 
			
		||||
 * between modes (such as alphanumeric and byte) to encode text in less space.
 | 
			
		||||
 * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary().
 | 
			
		||||
 */
 | 
			
		||||
bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len,
 | 
			
		||||
                              enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Encodes the given segments to a QR Code, returning true if successful.
 | 
			
		||||
 * If the data is too long to fit in any version in the given range
 | 
			
		||||
 * at the given ECC level, then false is returned.
 | 
			
		||||
 *
 | 
			
		||||
 * Requires 1 <= minVersion <= maxVersion <= 40.
 | 
			
		||||
 *
 | 
			
		||||
 * The smallest possible QR Code version within the given range is automatically
 | 
			
		||||
 * chosen for the output. Iff boostEcl is true, then the ECC level of the result
 | 
			
		||||
 * may be higher than the ecl argument if it can be done without increasing the
 | 
			
		||||
 * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or
 | 
			
		||||
 * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow).
 | 
			
		||||
 *
 | 
			
		||||
 * About the byte arrays, letting len = qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX):
 | 
			
		||||
 * - Before calling the function:
 | 
			
		||||
 *   - The array ranges tempBuffer[0 : len] and qrcode[0 : len] must allow
 | 
			
		||||
 *     reading and writing; hence each array must have a length of at least len.
 | 
			
		||||
 *   - The two ranges must not overlap (aliasing).
 | 
			
		||||
 *   - The initial state of both ranges can be uninitialized
 | 
			
		||||
 *     because the function always writes before reading.
 | 
			
		||||
 *   - The input array segs can contain segments whose data buffers overlap with tempBuffer.
 | 
			
		||||
 * - After the function returns:
 | 
			
		||||
 *   - Both ranges have no guarantee on which elements are initialized and what values are stored.
 | 
			
		||||
 *   - tempBuffer contains no useful data and should be treated as entirely uninitialized.
 | 
			
		||||
 *   - Any segment whose data buffer overlaps with tempBuffer[0 : len]
 | 
			
		||||
 *     must be treated as having invalid values in that array.
 | 
			
		||||
 *   - If successful, qrcode can be passed into qrcodegen_getSize() and qrcodegen_getModule().
 | 
			
		||||
 *
 | 
			
		||||
 * Please consult the QR Code specification for information on
 | 
			
		||||
 * data capacities per version, ECC level, and text encoding mode.
 | 
			
		||||
 *
 | 
			
		||||
 * This function allows the user to create a custom sequence of segments that switches
 | 
			
		||||
 * between modes (such as alphanumeric and byte) to encode text in less space.
 | 
			
		||||
 * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary().
 | 
			
		||||
 */
 | 
			
		||||
bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl,
 | 
			
		||||
                                      int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Tests whether the given string can be encoded as a segment in numeric mode.
 | 
			
		||||
 * A string is encodable iff each character is in the range 0 to 9.
 | 
			
		||||
 */
 | 
			
		||||
bool qrcodegen_isNumeric(const char* text);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Tests whether the given string can be encoded as a segment in alphanumeric mode.
 | 
			
		||||
 * A string is encodable iff each character is in the following set: 0 to 9, A to Z
 | 
			
		||||
 * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon.
 | 
			
		||||
 */
 | 
			
		||||
bool qrcodegen_isAlphanumeric(const char* text);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns the number of bytes (uint8_t) needed for the data buffer of a segment
 | 
			
		||||
 * containing the given number of characters using the given mode. Notes:
 | 
			
		||||
 * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or the internal
 | 
			
		||||
 *   calculation of the number of needed bits exceeds INT16_MAX (i.e. 32767).
 | 
			
		||||
 * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096.
 | 
			
		||||
 * - It is okay for the user to allocate more bytes for the buffer than needed.
 | 
			
		||||
 * - For byte mode, numChars measures the number of bytes, not Unicode code points.
 | 
			
		||||
 * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned.
 | 
			
		||||
 *   An actual ECI segment can have shorter data. For non-ECI modes, the result is exact.
 | 
			
		||||
 */
 | 
			
		||||
size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns a segment representing the given binary data encoded in
 | 
			
		||||
 * byte mode. All input byte arrays are acceptable. Any text string
 | 
			
		||||
 * can be converted to UTF-8 bytes and encoded as a byte mode segment.
 | 
			
		||||
 */
 | 
			
		||||
struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns a segment representing the given string of decimal digits encoded in numeric mode.
 | 
			
		||||
 */
 | 
			
		||||
struct qrcodegen_Segment qrcodegen_makeNumeric(const char* digits, uint8_t buf[]);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns a segment representing the given text string encoded in alphanumeric mode.
 | 
			
		||||
 * The characters allowed are: 0 to 9, A to Z (uppercase only), space,
 | 
			
		||||
 * dollar, percent, asterisk, plus, hyphen, period, slash, colon.
 | 
			
		||||
 */
 | 
			
		||||
struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char* text, uint8_t buf[]);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns a segment representing an Extended Channel Interpretation
 | 
			
		||||
 * (ECI) designator with the given assignment value.
 | 
			
		||||
 */
 | 
			
		||||
struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]);
 | 
			
		||||
 | 
			
		||||
/*---- Functions to extract raw data from QR Codes ----*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns the side length of the given QR Code, assuming that encoding succeeded.
 | 
			
		||||
 * The result is in the range [21, 177]. Note that the length of the array buffer
 | 
			
		||||
 * is related to the side length - every 'uint8_t qrcode[]' must have length at least
 | 
			
		||||
 * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1).
 | 
			
		||||
 */
 | 
			
		||||
int qrcodegen_getSize(const uint8_t qrcode[]);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Returns the color of the module (pixel) at the given coordinates, which is false
 | 
			
		||||
 * for light or true for dark. The top left corner has the coordinates (x=0, y=0).
 | 
			
		||||
 * If the given coordinates are out of bounds, then false (light) is returned.
 | 
			
		||||
 */
 | 
			
		||||
bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // TOUCHGFX_QRCODEGEN_HPP
 | 
			
		||||
@ -0,0 +1,311 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
* Copyright (c) 2018(-2024) STMicroelectronics.
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* This file is part of the TouchGFX 4.24.0 distribution.
 | 
			
		||||
*
 | 
			
		||||
* This software is licensed under terms that can be found in the LICENSE file in
 | 
			
		||||
* the root directory of this software component.
 | 
			
		||||
* If no LICENSE file comes with this software, it is provided AS-IS.
 | 
			
		||||
*
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <touchgfx/hal/HAL.hpp>
 | 
			
		||||
#include <touchgfx/transforms/DisplayTransformation.hpp>
 | 
			
		||||
#include <touchgfx/widgets/QRCode.hpp>
 | 
			
		||||
 | 
			
		||||
namespace touchgfx
 | 
			
		||||
{
 | 
			
		||||
QRCode::QRCode()
 | 
			
		||||
    : qrCodeData(0),
 | 
			
		||||
      qrTempBuffer(0),
 | 
			
		||||
      qrCodeVersion(1),
 | 
			
		||||
      sizeOfQRCodeSymbol(0),
 | 
			
		||||
      scale(1),
 | 
			
		||||
      eccLevel(ECC_LOW),
 | 
			
		||||
      alpha(0xFF)
 | 
			
		||||
{
 | 
			
		||||
    setColors(0x000000, 0xFFFFFF);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QRCode::convertStringToQRCode(const char* text)
 | 
			
		||||
{
 | 
			
		||||
    if (qrTempBuffer && qrCodeData)
 | 
			
		||||
    {
 | 
			
		||||
        // Clear old QR size field.
 | 
			
		||||
        qrCodeData[0] = 0;
 | 
			
		||||
        bool ok = qrcodegen_encodeText(text, qrTempBuffer, qrCodeData, (qrcodegen_Ecc)eccLevel,
 | 
			
		||||
                                       qrCodeVersion, qrCodeVersion, qrcodegen_Mask_AUTO, true);
 | 
			
		||||
 | 
			
		||||
        return ok;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool QRCode::convertBinaryDataToQRCode(const uint8_t* data, size_t length)
 | 
			
		||||
{
 | 
			
		||||
    const size_t bufferLength = qrcodegen_BUFFER_LEN_FOR_VERSION(qrCodeVersion);
 | 
			
		||||
    // Assuming qrTempBuffer has correct length (bufferLength)
 | 
			
		||||
    if (length <= bufferLength)
 | 
			
		||||
    {
 | 
			
		||||
        if (qrTempBuffer && qrCodeData)
 | 
			
		||||
        {
 | 
			
		||||
            // Copy data to scratch buffer
 | 
			
		||||
            memcpy(qrTempBuffer, data, length);
 | 
			
		||||
            // Clear old QR size field.
 | 
			
		||||
            qrCodeData[0] = 0;
 | 
			
		||||
            bool ok = qrcodegen_encodeBinary(qrTempBuffer, length, qrCodeData, (qrcodegen_Ecc)eccLevel,
 | 
			
		||||
                                             qrCodeVersion, qrCodeVersion, qrcodegen_Mask_AUTO, true);
 | 
			
		||||
 | 
			
		||||
            return ok;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t* QRCode::drawBitRGB565(uint8_t* dst, bool on, int pixels) const
 | 
			
		||||
{
 | 
			
		||||
    uint16_t* dst16 = (uint16_t*)dst;
 | 
			
		||||
    uint16_t* const dst_end = dst16 + pixels;
 | 
			
		||||
    const uint16_t color = on ? color0_565 : color1_565;
 | 
			
		||||
    while (dst16 < dst_end)
 | 
			
		||||
    {
 | 
			
		||||
        *dst16++ = color;
 | 
			
		||||
    }
 | 
			
		||||
    return (uint8_t*)dst16;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t* QRCode::drawBitRGB565Blend(uint8_t* dst, bool on, int pixels) const
 | 
			
		||||
{
 | 
			
		||||
    uint16_t* dst16 = (uint16_t*)dst;
 | 
			
		||||
    uint16_t* const dst_end = dst16 + pixels;
 | 
			
		||||
 | 
			
		||||
    const uint16_t alphaR = on ? alphaR0 : alphaR1;
 | 
			
		||||
    const uint16_t alphaG = on ? alphaG0 : alphaG1;
 | 
			
		||||
    const uint16_t alphaB = on ? alphaB0 : alphaB1;
 | 
			
		||||
 | 
			
		||||
    while (dst16 < dst_end)
 | 
			
		||||
    {
 | 
			
		||||
        const uint16_t bufpix = *dst16;
 | 
			
		||||
        const uint8_t fbr = Color::getRedFromRGB565(bufpix);
 | 
			
		||||
        const uint8_t fbg = Color::getGreenFromRGB565(bufpix);
 | 
			
		||||
        const uint8_t fbb = Color::getBlueFromRGB565(bufpix);
 | 
			
		||||
 | 
			
		||||
        *dst16++ = getRGB565ColorFromRGB(div255(alphaR + fbr * ialpha), div255(alphaG + fbg * ialpha), div255(alphaB + fbb * ialpha));
 | 
			
		||||
    }
 | 
			
		||||
    return (uint8_t*)dst16;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t* QRCode::drawBitRGB888(uint8_t* dst, bool on, int pixels) const
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* const dst_end = dst + pixels * 3;
 | 
			
		||||
 | 
			
		||||
    const uint8_t r = on ? r0 : r1;
 | 
			
		||||
    const uint8_t g = on ? g0 : g1;
 | 
			
		||||
    const uint8_t b = on ? b0 : b1;
 | 
			
		||||
 | 
			
		||||
    while (dst < dst_end)
 | 
			
		||||
    {
 | 
			
		||||
        *dst++ = b;
 | 
			
		||||
        *dst++ = g;
 | 
			
		||||
        *dst++ = r;
 | 
			
		||||
    }
 | 
			
		||||
    return dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t* QRCode::drawBitRGB888Blend(uint8_t* dst, bool on, int pixels) const
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* const dst_end = dst + pixels * 3;
 | 
			
		||||
    const uint16_t alphaRed = on ? alphaR0 : alphaR1;
 | 
			
		||||
    const uint16_t alphaGreen = on ? alphaG0 : alphaG1;
 | 
			
		||||
    const uint16_t alphaBlue = on ? alphaB0 : alphaB1;
 | 
			
		||||
 | 
			
		||||
    while (dst < dst_end)
 | 
			
		||||
    {
 | 
			
		||||
        *dst = div255(alphaBlue + *dst * ialpha);
 | 
			
		||||
        dst++; // Avoid side effects
 | 
			
		||||
        *dst = div255(alphaGreen + *dst * ialpha);
 | 
			
		||||
        dst++; // Avoid side effects
 | 
			
		||||
        *dst = div255(alphaRed + *dst * ialpha);
 | 
			
		||||
        dst++; // Avoid side effects
 | 
			
		||||
    }
 | 
			
		||||
    return dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t* QRCode::drawBitARGB8888(uint8_t* dst, bool on, int pixels) const
 | 
			
		||||
{
 | 
			
		||||
    uint8_t* const dst_end = dst + pixels * 4;
 | 
			
		||||
 | 
			
		||||
    const uint8_t r = on ? r0 : r1;
 | 
			
		||||
    const uint8_t g = on ? g0 : g1;
 | 
			
		||||
    const uint8_t b = on ? b0 : b1;
 | 
			
		||||
 | 
			
		||||
    while (dst < dst_end)
 | 
			
		||||
    {
 | 
			
		||||
        *dst++ = b;
 | 
			
		||||
        *dst++ = g;
 | 
			
		||||
        *dst++ = r;
 | 
			
		||||
        *dst++ = 0xFF;
 | 
			
		||||
    }
 | 
			
		||||
    return dst;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t* QRCode::drawBitARGB8888Blend(uint8_t* dst, bool on, int pixels) const
 | 
			
		||||
{
 | 
			
		||||
    uint32_t* dst32 = (uint32_t*)dst;
 | 
			
		||||
    uint32_t* dst32_end = dst32 + pixels;
 | 
			
		||||
    const uint16_t alphaRed = on ? alphaR0 : alphaR1;
 | 
			
		||||
    const uint16_t alphaGreen = on ? alphaG0 : alphaG1;
 | 
			
		||||
    const uint16_t alphaBlue = on ? alphaB0 : alphaB1;
 | 
			
		||||
 | 
			
		||||
    while (dst32 < dst32_end)
 | 
			
		||||
    {
 | 
			
		||||
        const uint32_t rgbBg = *dst32;
 | 
			
		||||
        const uint8_t alphaBg = rgbBg >> 24;
 | 
			
		||||
        if (alphaBg == 0)
 | 
			
		||||
        {
 | 
			
		||||
            // Completely transparent background
 | 
			
		||||
            uint8_t* dst8 = (uint8_t*)dst32;
 | 
			
		||||
            if (on)
 | 
			
		||||
            {
 | 
			
		||||
                *dst8++ = b0;
 | 
			
		||||
                *dst8++ = g0;
 | 
			
		||||
                *dst8++ = r0;
 | 
			
		||||
                *dst8 = alpha;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                *dst8++ = b1;
 | 
			
		||||
                *dst8++ = g1;
 | 
			
		||||
                *dst8++ = r1;
 | 
			
		||||
                *dst8 = alpha;
 | 
			
		||||
            }
 | 
			
		||||
            dst32++;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t alphaMult = div255(alpha * alphaBg);
 | 
			
		||||
            const uint8_t alphaOut = alpha + alphaBg - alphaMult;
 | 
			
		||||
 | 
			
		||||
            const uint8_t blueOut = (alphaBlue + (rgbBg & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
            const uint8_t greenOut = (alphaGreen + ((rgbBg >> 8) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
            const uint8_t redOut = (alphaRed + ((rgbBg >> 16) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
 | 
			
		||||
            *dst32++ = (alphaOut << 24) | (redOut << 16) | (greenOut << 8) | blueOut;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (uint8_t*)dst32;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QRCode::draw(const Rect& invalidatedArea) const
 | 
			
		||||
{
 | 
			
		||||
    // To check if qrCodeData is ready to be drawn
 | 
			
		||||
    int result = qrCodeData[0];
 | 
			
		||||
    if (!((qrcodegen_VERSION_MIN * 4 + 17) <= result) || !(result <= (qrcodegen_VERSION_MAX * 4 + 17)))
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (alpha == 0)
 | 
			
		||||
    {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Rect absInvalidated = invalidatedArea;
 | 
			
		||||
    translateRectToAbsolute(absInvalidated);
 | 
			
		||||
 | 
			
		||||
    // QR bit drawing function
 | 
			
		||||
    uint8_t* (QRCode::*drawfunc)(uint8_t * dst, bool on, int pixels) const = 0;
 | 
			
		||||
 | 
			
		||||
    const int bpp = HAL::lcd().bitDepth();
 | 
			
		||||
 | 
			
		||||
    // Select correct drawing function for framebuffer format and alpha
 | 
			
		||||
    switch (bpp)
 | 
			
		||||
    {
 | 
			
		||||
    case 16:
 | 
			
		||||
        // RGB565
 | 
			
		||||
        drawfunc = (alpha < 255) ? &QRCode::drawBitRGB565Blend : &QRCode::drawBitRGB565;
 | 
			
		||||
        break;
 | 
			
		||||
    case 24:
 | 
			
		||||
        // RGB888
 | 
			
		||||
        drawfunc = (alpha < 255) ? &QRCode::drawBitRGB888Blend : &QRCode::drawBitRGB888;
 | 
			
		||||
        break;
 | 
			
		||||
    case 32:
 | 
			
		||||
        // ARGB8888
 | 
			
		||||
        drawfunc = (alpha < 255) ? &QRCode::drawBitARGB8888Blend : &QRCode::drawBitARGB8888;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const int bytespp = bpp / 8;
 | 
			
		||||
    const int line_stride = HAL::lcd().framebufferStride();
 | 
			
		||||
 | 
			
		||||
    uint8_t* const fb = (uint8_t*)HAL::getInstance()->lockFrameBuffer();
 | 
			
		||||
 | 
			
		||||
    if (HAL::DISPLAY_ROTATION == rotate90)
 | 
			
		||||
    {
 | 
			
		||||
        Rect transformedAbs = absInvalidated;
 | 
			
		||||
        DisplayTransformation::transformDisplayToFrameBuffer(transformedAbs);
 | 
			
		||||
        // Find address of first pixel in (unrotated) framebuffer = top right corner of inv. area.
 | 
			
		||||
        uint8_t* fb_line = fb + bytespp * (transformedAbs.x + transformedAbs.y * HAL::FRAME_BUFFER_WIDTH);
 | 
			
		||||
        // Start in rightmost column = top row in framebuffer
 | 
			
		||||
        // Drawing downwards in display = increasing address in framebuffer
 | 
			
		||||
        for (int col = 0; col < invalidatedArea.width; col++)
 | 
			
		||||
        {
 | 
			
		||||
            const int qr_x = (invalidatedArea.right() - 1 - col) / scale;
 | 
			
		||||
            const int row_end = invalidatedArea.y + invalidatedArea.height;
 | 
			
		||||
            uint8_t* dest = fb_line;
 | 
			
		||||
            for (int row = invalidatedArea.y; row < row_end;)
 | 
			
		||||
            {
 | 
			
		||||
                const int length = MIN(scale - row % scale, row_end - row);
 | 
			
		||||
                const bool bit = getQRBit(qr_x, row / scale);
 | 
			
		||||
                dest = (this->*drawfunc)(dest, bit, length);
 | 
			
		||||
                row += length;
 | 
			
		||||
            }
 | 
			
		||||
            fb_line += line_stride;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t* fb_line = fb + (absInvalidated.x + absInvalidated.y * HAL::FRAME_BUFFER_WIDTH) * bytespp;
 | 
			
		||||
        for (int y = 0; y < absInvalidated.height; y++)
 | 
			
		||||
        {
 | 
			
		||||
            const int qr_y = (invalidatedArea.y + y) / scale;
 | 
			
		||||
            const int x_end = invalidatedArea.x + invalidatedArea.width;
 | 
			
		||||
            uint8_t* dest = fb_line;
 | 
			
		||||
            for (int x = invalidatedArea.x; x < x_end;)
 | 
			
		||||
            {
 | 
			
		||||
                const int length = MIN(scale - x % scale, x_end - x);
 | 
			
		||||
                const bool bit = getQRBit(x / scale, qr_y);
 | 
			
		||||
                dest = (this->*drawfunc)(dest, bit, length);
 | 
			
		||||
                x += length;
 | 
			
		||||
            }
 | 
			
		||||
            fb_line += line_stride;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    HAL::getInstance()->unlockFrameBuffer();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Rect QRCode::getSolidRect() const
 | 
			
		||||
{
 | 
			
		||||
    // Widget does not draw anything if it has no valid qrCodeData, so
 | 
			
		||||
    // report transparent to show background
 | 
			
		||||
    if (alpha == 255 && qrCodeData && qrCodeData[0] != 0)
 | 
			
		||||
    {
 | 
			
		||||
        return Rect(0, 0, getWidth(), getHeight());
 | 
			
		||||
    }
 | 
			
		||||
    return Rect();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QRCode::updateWidthAndHeight()
 | 
			
		||||
{
 | 
			
		||||
    setWidth(sizeOfQRCodeSymbol * scale);
 | 
			
		||||
    setHeight(sizeOfQRCodeSymbol * scale);
 | 
			
		||||
}
 | 
			
		||||
} // namespace touchgfx
 | 
			
		||||
@ -0,0 +1,257 @@
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
* Copyright (c) 2018(-2024) STMicroelectronics.
 | 
			
		||||
* All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* This file is part of the TouchGFX 4.24.0 distribution.
 | 
			
		||||
*
 | 
			
		||||
* This software is licensed under terms that can be found in the LICENSE file in
 | 
			
		||||
* the root directory of this software component.
 | 
			
		||||
* If no LICENSE file comes with this software, it is provided AS-IS.
 | 
			
		||||
*
 | 
			
		||||
*******************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <touchgfx/hal/Paint.hpp>
 | 
			
		||||
#include <touchgfx/widgets/canvas/PainterARGB8888LinearGradient.hpp>
 | 
			
		||||
 | 
			
		||||
namespace touchgfx
 | 
			
		||||
{
 | 
			
		||||
void PainterARGB8888LinearGradient::paint(uint8_t* destination, int16_t offset, int16_t widgetX, int16_t widgetY, int16_t count, uint8_t alpha) const
 | 
			
		||||
{
 | 
			
		||||
    uint32_t* p = reinterpret_cast<uint32_t*>(destination) + offset;
 | 
			
		||||
 | 
			
		||||
    if (isVertical)
 | 
			
		||||
    {
 | 
			
		||||
        // The whole line is the same color
 | 
			
		||||
        uint32_t color;
 | 
			
		||||
        if (widgetY <= coord0)
 | 
			
		||||
        {
 | 
			
		||||
            color = texture[deltaColor > 0 ? 0 : 1023];
 | 
			
		||||
        }
 | 
			
		||||
        else if (widgetY >= coord1)
 | 
			
		||||
        {
 | 
			
		||||
            color = texture[deltaColor > 0 ? 1023 : 0];
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const int32_t colorOffset = (int)((widgetY - coord0) * deltaColor);
 | 
			
		||||
            color = texture[deltaColor > 0 ? colorOffset : 1023 + colorOffset];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        uint32_t* const p_end = p + count;
 | 
			
		||||
 | 
			
		||||
        if (isSolid && (alpha == 255))
 | 
			
		||||
        {
 | 
			
		||||
            const int32_t solidColor = (0xFFU << 24) | color;
 | 
			
		||||
 | 
			
		||||
            while (p < p_end)
 | 
			
		||||
            {
 | 
			
		||||
                *p++ = solidColor;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t a = (color >> 24) & 0xFF;
 | 
			
		||||
            const uint8_t alphaFg = LCD::div255(a * alpha);
 | 
			
		||||
 | 
			
		||||
            if (alphaFg)
 | 
			
		||||
            {
 | 
			
		||||
                const uint8_t b = color & 0xFF;
 | 
			
		||||
                const uint8_t g = (color >> 8) & 0xFF;
 | 
			
		||||
                const uint8_t r = (color >> 16) & 0xFF;
 | 
			
		||||
 | 
			
		||||
                while (p < p_end)
 | 
			
		||||
                {
 | 
			
		||||
                    const uint32_t rgbBg = *p;
 | 
			
		||||
                    const uint8_t alphaBg = rgbBg >> 24;
 | 
			
		||||
 | 
			
		||||
                    // DMA2D blending algo
 | 
			
		||||
                    const uint8_t alphaMult = LCD::div255(alphaFg * alphaBg);
 | 
			
		||||
                    const uint8_t alphaOut = alphaFg + alphaBg - alphaMult;
 | 
			
		||||
                    const uint8_t blueOut = (b * alphaFg + (rgbBg & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
                    const uint8_t greenOut = (g * alphaFg + ((rgbBg >> 8) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
                    const uint8_t redOut = (r * alphaFg + ((rgbBg >> 16) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
 | 
			
		||||
                    *p++ = (alphaOut << 24) | (redOut << 16) | (greenOut << 8) | blueOut;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // vx0 is where first color line (y=clSlope*x+clOffset) intersects the horizontal line y=widgetY
 | 
			
		||||
    float vx0;
 | 
			
		||||
    if (isHorizontal)
 | 
			
		||||
    {
 | 
			
		||||
        vx0 = coord0;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        vx0 = (widgetY - clOffset) / clSlope;
 | 
			
		||||
        if (deltaColor < 0.0f)
 | 
			
		||||
        {
 | 
			
		||||
            vx0 -= horizontalDistance;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int x = widgetX;
 | 
			
		||||
 | 
			
		||||
    // Left of gradient
 | 
			
		||||
    // All pixels up to first gradient line, paint using fixed color
 | 
			
		||||
    if (x <= vx0)
 | 
			
		||||
    {
 | 
			
		||||
        // Starting before gradient
 | 
			
		||||
        const int pixels = (int)(MIN(vx0 + 1 - x, count));
 | 
			
		||||
        // Start in correct end of palette depending on direction
 | 
			
		||||
        const uint32_t colorStart = texture[deltaColor > 0 ? 0 : 1023];
 | 
			
		||||
        uint32_t* const p_end = p + pixels;
 | 
			
		||||
        if (isSolid && (alpha == 255))
 | 
			
		||||
        {
 | 
			
		||||
            const int32_t solidColor = (0xFFU << 24) | colorStart;
 | 
			
		||||
 | 
			
		||||
            while (p < p_end)
 | 
			
		||||
            {
 | 
			
		||||
                *p++ = solidColor;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            const uint8_t a = (colorStart >> 24) & 0xFF;
 | 
			
		||||
            const uint8_t alphaFg = LCD::div255(a * alpha);
 | 
			
		||||
 | 
			
		||||
            if (alphaFg)
 | 
			
		||||
            {
 | 
			
		||||
                const uint8_t b = colorStart & 0xFF;
 | 
			
		||||
                const uint8_t g = (colorStart >> 8) & 0xFF;
 | 
			
		||||
                const uint8_t r = (colorStart >> 16) & 0xFF;
 | 
			
		||||
 | 
			
		||||
                while (p < p_end)
 | 
			
		||||
                {
 | 
			
		||||
                    const uint32_t rgbBg = *p;
 | 
			
		||||
                    const uint8_t alphaBg = rgbBg >> 24;
 | 
			
		||||
 | 
			
		||||
                    // DMA2D blending algo
 | 
			
		||||
                    const uint8_t alphaMult = LCD::div255(alphaFg * alphaBg);
 | 
			
		||||
                    const uint8_t alphaOut = alphaFg + alphaBg - alphaMult;
 | 
			
		||||
                    const uint8_t blueOut = (b * alphaFg + (rgbBg & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
                    const uint8_t greenOut = (g * alphaFg + ((rgbBg >> 8) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
                    const uint8_t redOut = (r * alphaFg + ((rgbBg >> 16) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
 | 
			
		||||
                    *p++ = (alphaOut << 24) | (redOut << 16) | (greenOut << 8) | blueOut;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
        x += pixels;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const int16_t right = widgetX + count;
 | 
			
		||||
    if (x < right) // More to draw
 | 
			
		||||
    {
 | 
			
		||||
        // vx1 is where y=widgetY intersects the last color line (fixed distance from vx0)
 | 
			
		||||
        const float vx1 = vx0 + horizontalDistance;
 | 
			
		||||
 | 
			
		||||
        if (x < vx1) // Draw gradient part until last color line
 | 
			
		||||
        {
 | 
			
		||||
            const int endx = (int)(MIN(right, vx1));
 | 
			
		||||
            const uint32_t* const p_end = p + (endx - x);
 | 
			
		||||
 | 
			
		||||
            // Start with first or last color depending on direction
 | 
			
		||||
            float colorF = deltaColor > 0 ? 0.0000f : 1023.9999f;
 | 
			
		||||
            colorF += (x - vx0) * deltaColor;
 | 
			
		||||
 | 
			
		||||
            if (isSolid && (alpha == 255))
 | 
			
		||||
            {
 | 
			
		||||
                while (p < p_end)
 | 
			
		||||
                {
 | 
			
		||||
                    const int colorIndex = (int)colorF;
 | 
			
		||||
                    const uint32_t* color = (const uint32_t*)(texture + colorIndex);
 | 
			
		||||
 | 
			
		||||
                    *p++ = (0xFFU << 24) | *color;
 | 
			
		||||
 | 
			
		||||
                    colorF += deltaColor;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                // Go to 8-bit pointers
 | 
			
		||||
                const uint32_t* const gradient = (const uint32_t*)texture;
 | 
			
		||||
                while (p < p_end)
 | 
			
		||||
                {
 | 
			
		||||
                    const int colorIndex = (int)colorF;
 | 
			
		||||
 | 
			
		||||
                    const uint32_t* color = gradient + colorIndex;
 | 
			
		||||
                    const uint8_t a = (*color >> 24) & 0xFF;
 | 
			
		||||
                    const uint8_t alphaFg = LCD::div255(a * alpha);
 | 
			
		||||
 | 
			
		||||
                    if (alphaFg)
 | 
			
		||||
                    {
 | 
			
		||||
                        const uint8_t b = *color & 0xFF;
 | 
			
		||||
                        const uint8_t g = (*color >> 8) & 0xFF;
 | 
			
		||||
                        const uint8_t r = (*color >> 16) & 0xFF;
 | 
			
		||||
 | 
			
		||||
                        const uint32_t rgbBg = *p;
 | 
			
		||||
                        const uint8_t alphaBg = rgbBg >> 24;
 | 
			
		||||
 | 
			
		||||
                        // DMA2D blending algo
 | 
			
		||||
                        const uint8_t alphaMult = LCD::div255(alphaFg * alphaBg);
 | 
			
		||||
                        const uint8_t alphaOut = alphaFg + alphaBg - alphaMult;
 | 
			
		||||
                        const uint8_t blueOut = (b * alphaFg + (rgbBg & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
                        const uint8_t greenOut = (g * alphaFg + ((rgbBg >> 8) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
                        const uint8_t redOut = (r * alphaFg + ((rgbBg >> 16) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
 | 
			
		||||
                        *p++ = (alphaOut << 24) | (redOut << 16) | (greenOut << 8) | blueOut;
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    colorF += deltaColor;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            x = endx;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (x < right) // Second fixed color part
 | 
			
		||||
        {
 | 
			
		||||
            const uint32_t* const p_end = p + (right - x);
 | 
			
		||||
            const uint32_t colorEnd = texture[deltaColor > 0 ? 1023 : 0];
 | 
			
		||||
            if (isSolid && (alpha == 255))
 | 
			
		||||
            {
 | 
			
		||||
                const int32_t solidColor = (0xFFU << 24) | colorEnd;
 | 
			
		||||
 | 
			
		||||
                while (p < p_end)
 | 
			
		||||
                {
 | 
			
		||||
                    *p++ = solidColor;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                const uint8_t b = colorEnd & 0xFF;
 | 
			
		||||
                const uint8_t g = (colorEnd >> 8) & 0xFF;
 | 
			
		||||
                const uint8_t r = (colorEnd >> 16) & 0xFF;
 | 
			
		||||
 | 
			
		||||
                const uint8_t a = (colorEnd >> 24) & 0xFF;
 | 
			
		||||
                const uint8_t alphaFg = LCD::div255(a * alpha);
 | 
			
		||||
 | 
			
		||||
                while (p < p_end)
 | 
			
		||||
                {
 | 
			
		||||
                    if (alphaFg)
 | 
			
		||||
                    {
 | 
			
		||||
                        const uint32_t rgbBg = *p;
 | 
			
		||||
                        const uint8_t alphaBg = rgbBg >> 24;
 | 
			
		||||
 | 
			
		||||
                        // DMA2D blending algo
 | 
			
		||||
                        const uint8_t alphaMult = LCD::div255(alphaFg * alphaBg);
 | 
			
		||||
                        const uint8_t alphaOut = alphaFg + alphaBg - alphaMult;
 | 
			
		||||
                        const uint8_t blueOut = (b * alphaFg + (rgbBg & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
                        const uint8_t greenOut = (g * alphaFg + ((rgbBg >> 8) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
                        const uint8_t redOut = (r * alphaFg + ((rgbBg >> 16) & 0xFF) * (alphaBg - alphaMult)) / alphaOut;
 | 
			
		||||
 | 
			
		||||
                        *p++ = (alphaOut << 24) | (redOut << 16) | (greenOut << 8) | blueOut;
 | 
			
		||||
                    };
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PainterARGB8888LinearGradient::tearDown() const
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
} // namespace touchgfx
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
/* DO NOT EDIT THIS FILE */
 | 
			
		||||
/* This file is autogenerated by the text-database code generator */
 | 
			
		||||
#include <touchgfx/VectorFontRendererImpl.hpp>
 | 
			
		||||
 | 
			
		||||
<% if get_num_commands != 0 %>
 | 
			
		||||
static float ptArray[<%= get_num_floats %>];
 | 
			
		||||
static uint8_t cmdArray[<%= get_num_commands %>];
 | 
			
		||||
 | 
			
		||||
void touchgfx::VectorFontRendererImpl::getVectorFontBuffers(float*& pointArray, int& pointArraySize, uint8_t*& commandArray, int& commandArraySize)
 | 
			
		||||
{
 | 
			
		||||
    pointArray = ptArray;
 | 
			
		||||
    pointArraySize = <%= get_num_floats %>;
 | 
			
		||||
    commandArray = cmdArray;
 | 
			
		||||
    commandArraySize = <%= get_num_commands %>;
 | 
			
		||||
}
 | 
			
		||||
<% else %>
 | 
			
		||||
void touchgfx::VectorFontRendererImpl::getVectorFontBuffers(float*& pointArray, int& pointArraySize, uint8_t*& commandArray, int& commandArraySize)
 | 
			
		||||
{
 | 
			
		||||
    pointArray = 0;
 | 
			
		||||
    pointArraySize = 0;
 | 
			
		||||
    commandArray = 0;
 | 
			
		||||
    commandArraySize = 0;
 | 
			
		||||
}
 | 
			
		||||
<% end %>
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								Middlewares/ST/touchgfx/lib/core/cortex_m55/gcc/libtouchgfx.a
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Middlewares/ST/touchgfx/lib/core/cortex_m55/gcc/libtouchgfx.a
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user