973 lines
45 KiB
C++

/******************************************************************************
* Copyright (c) 2018(-2023) STMicroelectronics.
* All rights reserved.
*
* This file is part of the TouchGFX 4.21.2 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/lcd/LCD.hpp
*
* This file contains two super classes, namely LCD and DebugPrinter. The LCD class specifies
* various functions that allow drawing images, texts and boxes on the display. In general,
* these functions are available through various widgets which encapsulates these drawing
* operations and keep track of the state of image/text/etc. Please consult the documentation
* for the widgets for more information.
*
* @see touchgfx::LCD, touchgfx::DebugPrinter
*/
#ifndef TOUCHGFX_LCD_HPP
#define TOUCHGFX_LCD_HPP
// LCD is defined in some CubeFW C header file. We have to undef to be able to create the LCD class
#ifdef LCD
#undef LCD
#endif
#include <touchgfx/Bitmap.hpp>
#include <touchgfx/Font.hpp>
#include <touchgfx/TextProvider.hpp>
#include <touchgfx/TextureMapTypes.hpp>
#include <touchgfx/Unicode.hpp>
#include <touchgfx/hal/Types.hpp>
#include <touchgfx/lcd/DebugPrinter.hpp>
namespace touchgfx
{
/**
* This class contains the various low-level drawing routines for drawing bitmaps, texts and
* rectangles/boxes. Normally, these draw operations are called from widgets, which also
* keep track of logical states such as visibility etc.
*
* The LCD class cannot be instantiated, instead use one of the subclasses which
* implements the LCD drawing operations for a specific display configuration.
*
* @note All coordinates sent to functions in the LCD class are expected to be in absolute
* coordinates, i.e. (0, 0) is upper left corner of the display.
*/
class LCD
{
public:
/** Initializes a new instance of the LCD class. */
LCD()
: textureMapperClass(0)
{
}
/** Finalizes an instance of the LCD class. */
virtual ~LCD()
{
}
/**
* Draws all (or a part) of a \a bitmap. The coordinates of the corner of the bitmap is
* given in (\a x, \a y) and \a rect describes which part of the \a bitmap should be
* drawn. The bitmap can be drawn as it is or more or less transparent depending on the
* value of \a alpha. The value of \a alpha is independent of the transparency of the
* individual pixels of the given \a bitmap.
*
* @param bitmap The bitmap to draw.
* @param x The absolute x coordinate to place (0, 0) of the bitmap on the screen.
* @param y The absolute y coordinate to place (0, 0) of the bitmap on the screen.
* @param rect A rectangle describing what region of the bitmap is to be drawn.
* @param alpha (Optional) Optional alpha value ranging from 0=invisible to
* 255=solid. Default is 255 (solid).
* @param useOptimized (Optional) if false, do not attempt to substitute (parts of) this
* bitmap with faster fillrects.
*/
virtual void drawPartialBitmap(const Bitmap& bitmap, int16_t x, int16_t y, const Rect& rect, uint8_t alpha = 255, bool useOptimized = true) = 0;
/**
* Blits (directly copies) a block of data to the framebuffer, performing alpha blending
* (and tranparency keying) as specified. Performs a software blend if HAL does not
* support BLIT_COPY_WITH_ALPHA and alpha != 255 (solid).
*
* @param sourceData The source array pointer (points to the beginning of the
* data). The sourceData must be stored in a format
* suitable for the selected display.
* @param source The position and dimensions of the source. The x and y of this
* rect should both be 0.
* @param blitRect A rectangle describing what region of the \a sourceData is to
* be copied to the framebuffer.
* @param alpha The alpha value to use for blending ranging from 0=invisible
* to 255=solid=no blending.
* @param hasTransparentPixels If true, this data copy contains transparent pixels and
* require hardware support for that to be enabled.
*/
virtual void blitCopy(const uint16_t* sourceData, const Rect& source, const Rect& blitRect, uint8_t alpha, bool hasTransparentPixels) = 0;
/**
* Blits (directly copies) a block of data to the framebuffer, performing alpha blending
* (and tranparency keying) as specified. Performs a software blend if HAL does not
* support BLIT_COPY_WITH_ALPHA and alpha < 255 (solid).
*
* If the display does not support the specified \a sourceFormat, an \a assert will be
* raised.
*
* @param sourceData The source array pointer (points to the beginning of the
* data). The sourceData must be stored in a format
* suitable for the selected display.
* @param sourceFormat The bitmap format used in the source data.
* @param source The position and dimensions of the source. The x and y of this
* rect should both be 0.
* @param blitRect A rectangle describing what region of the \a sourceData is to
* be copied to the framebuffer.
* @param alpha The alpha value to use for blending ranging from 0=invisible
* to 255=solid=no blending.
* @param hasTransparentPixels If true, this data copy contains transparent pixels and
* require hardware support for that to be enabled.
*/
virtual void blitCopy(const uint8_t* sourceData, Bitmap::BitmapFormat sourceFormat, const Rect& source, const Rect& blitRect, uint8_t alpha, bool hasTransparentPixels) = 0;
/**
* Copies part of the framebuffer to the data section of a bitmap. The bitmap must be a
* dynamic bitmap or animation storage (BITMAP_ANIMATION_STORAGE). Only the part
* specified with by parameter \a region is copied.
*
* If \a region has negative x/y coordinates of if width/height exceeds those of the
* given bitmap, only the visible and legal part of the framebuffer is copied. The rest
* of the bitmap image is left untouched.
*
* @param region The part of the framebuffer to copy.
* @param bitmapId (Optional) The bitmap to store the data in. Default is to use
* Animation Storage.
*
* @return A pointer to the copy.
*
* @see blitCopy
*
* @note There is only one instance of animation storage. The content of the bitmap data (or
* animation storage) outside the given region is left untouched.
*/
uint16_t* copyFrameBufferRegionToMemory(const Rect& region, const BitmapId bitmapId = BITMAP_ANIMATION_STORAGE)
{
return copyFrameBufferRegionToMemory(region, region, bitmapId);
}
/**
* Copies part of the framebuffer to the data section of a bitmap. The bitmap must be a
* dynamic bitmap or animation storage (BITMAP_ANIMATION_STORAGE). The two regions given
* are the visible region and the absolute region on screen. This is used to copy only a
* part of the framebuffer. This might be the case if a SnapshotWidget is placed inside
* a Container where parts of the SnapshowWidget is outside the area defined by the
* Container. The visible region must be completely inside the absolute region.
*
* @param visRegion The visible region.
* @param absRegion The absolute region.
* @param bitmapId Identifier for the bitmap.
*
* @return Null if it fails, else a pointer to the data in the given bitmap.
*
* @see blitCopy, copyFrameBufferRegionToMemory(const Rect&, const Rect&, uint8_t*, int16_t, int16_t)
*
* @note There is only one instance of animation storage. The content of the bitmap data
* /animation storage outside the given region is left untouched.
*/
virtual uint16_t* copyFrameBufferRegionToMemory(const Rect& visRegion, const Rect& absRegion, const BitmapId bitmapId) = 0;
/**
* Copies part of the framebuffer to memory. The memory is assumed to have the same format as
* the framebuffer. The two regions given are the visible region and the absolute region on
* screen. This is used to copy only a part of the framebuffer. This might be the case if a
* SnapshotWidget is placed inside a Container where parts of the SnapshowWidget is outside the
* area defined by the Container. The visible region must be completely inside the absolute
* region.
*
* @param visRegion The visible region.
* @param absRegion The absolute region.
* @param [in,out] dst Destination memory in same format as the framebuffer.
* @param dstWidth Width of the destination.
* @param dstHeight Height of the destination.
*
* @return The rect that was actually copied to the destination buffer.
*
* @see blitCopy, copyFrameBufferRegionToMemory(const Rect&, const Rect&, const BitmapId)
*
* @note There is only one instance of animation storage. The content of the bitmap data
* /animation storage outside the given region is left untouched.
*/
virtual Rect copyFrameBufferRegionToMemory(const Rect& visRegion, const Rect& absRegion, uint8_t* dst, int16_t dstWidth, int16_t dstHeight) = 0;
/**
* Copies part of the displayed framebuffer to current framebuffer.
* The region given is the absolute region on screen.
*
* @param region A rectangle describing what region of the displayed framebuffer
* is to be copied to the framebuffer.
*
* @note The copy is performed only when double buffering is enabled. Otherwise the given
* region in current framebuffer is left untouched.
*/
virtual void copyAreaFromTFTToClientBuffer(const Rect& region) = 0;
/**
* Draws a filled rectangle in the framebuffer in the specified color and opacity. By
* default the rectangle will be drawn as a solid box. The rectangle can be drawn with
* transparency by specifying alpha from 0=invisible to 255=solid.
*
* @param rect The rectangle to draw in absolute display coordinates.
* @param color The rectangle color.
* @param alpha (Optional) The rectangle opacity, from 0=invisible to 255=solid.
*
* @see fillBuffer
*/
virtual void fillRect(const Rect& rect, colortype color, uint8_t alpha = 255) = 0;
/**
* Draws a filled rectangle in destination memory using the specified color and opacity. The
* destination memory must have the same format as the display framebuffer. By default the
* rectangle will be drawn as a solid box. The rectangle can be drawn with transparency by
* specifying alpha from 0=invisible to 255=solid.
*
* @param [in] destination The start of the memory area to fill.
* @param pixelStride The pixel stride, i.e. number of pixels in a row.
* @param rect The rectangle to fill absolute coordinates.
* @param color The rectangle color.
* @param alpha The rectangle opacity, from 0=invisible to 255=solid.
*
* @note The pixelStride is rounded up to nearest whole bytes for displays with more than one
* pixel per byte (LCD1bpp, LCD2bpp and LCD4bpp)
*/
virtual void fillBuffer(uint8_t* const destination, uint16_t pixelStride, const Rect& rect, const colortype color, const uint8_t alpha) = 0;
/** The visual elements when writing a string. */
struct StringVisuals
{
const Font* font; ///< The font to use.
Alignment alignment; ///< The alignment to use. Default is LEFT.
TextDirection textDirection; ///< The direction to use. Default is LTR
TextRotation rotation; ///< Orientation (rotation) of the text. Default is TEXT_ROTATE_0.
colortype color; ///< RGB color value. Default is 0 (black).
int16_t linespace; ///< Line space in pixels for multiline strings. Default is 0.
uint8_t alpha; ///< 8-bit alpha value. Default is 255 (solid).
uint8_t indentation; ///< Indentation of text inside rectangle. Text will start this far from the left/right edge
WideTextAction wideTextAction; ///< What to do with wide text lines
/** Initializes a new instance of the LCD class. */
StringVisuals()
: font(0), alignment(LEFT), textDirection(TEXT_DIRECTION_LTR), rotation(TEXT_ROTATE_0), color(0), linespace(0), alpha(255), indentation(0), wideTextAction(WIDE_TEXT_NONE)
{
}
/**
* Construct a StringVisual object for rendering text.
*
* @param svFont The Font with which to draw the text.
* @param svColor The color with which to draw the text.
* @param svAlpha Alpha blending. Default value is 255 (solid)
* @param svAlignment How to align the text.
* @param svLinespace Line space in pixels between each line, in case the text contains
* newline characters.
* @param svRotation How to rotate the text.
* @param svTextDirection The text direction.
* @param svIndentation The indentation of the text from the left and right of the text area
* rectangle.
* @param svWideTextAction (Optional) What to do with lines longer than the width of the
* TextArea.
*/
StringVisuals(const Font* svFont, colortype svColor, uint8_t svAlpha, Alignment svAlignment, int16_t svLinespace, TextRotation svRotation, TextDirection svTextDirection, uint8_t svIndentation, WideTextAction svWideTextAction = WIDE_TEXT_NONE)
: font(svFont), alignment(svAlignment), textDirection(svTextDirection), rotation(svRotation), color(svColor), linespace(svLinespace), alpha(svAlpha), indentation(svIndentation), wideTextAction(svWideTextAction)
{
}
};
/**
* Draws the specified Unicode string. Breaks line on newline.
*
* @param widgetArea The area covered by the drawing widget in absolute
* coordinates.
* @param invalidatedArea The (sub)region of the widget area to draw, expressed
* relative to the widget area. If the widgetArea is x=10, y=10,
* width=20, height=20 and invalidatedArea is x=5, y=5, width=6,
* height=6 the widgetArea drawn on the LCD is x=15, y=15,
* width=6, height=6.
* @param stringVisuals The string visuals (font, alignment, line space, color)
* with which to draw this string.
* @param format A pointer to a null-terminated text string with optional
* additional wildcard arguments.
* @param ... Variable arguments providing additional information.
*/
void drawString(Rect widgetArea,
const Rect& invalidatedArea,
const StringVisuals& stringVisuals,
const Unicode::UnicodeChar* format,
...);
/**
* Number of bits per pixel used by the display.
*
* @return The number of bits per pixel.
*/
virtual uint8_t bitDepth() const = 0;
/**
* Framebuffer format used by the display.
*
* @return A Bitmap::BitmapFormat.
*/
virtual Bitmap::BitmapFormat framebufferFormat() const = 0;
/**
* Framebuffer stride in bytes. The distance (in bytes) from the start of one
* framebuffer row, to the next.
*
* @return The number of bytes in one framebuffer row.
*/
virtual uint16_t framebufferStride() const = 0;
/**
* Check if LCD support dynamic bitmap drawing.
*
* @param format The dynamic bitmap format.
*
* @return true if dynamic bitmap drawing is supported, false otherwise.
*/
virtual bool supportDynamicBitmapDrawing(const Bitmap::BitmapFormat format)
{
// return true if bitmap format matches framebuffer format
return (format == framebufferFormat());
}
/**
* Sets default color as used by alpha level only bitmap formats, e.g. A4. The default
* color, if no color is set, is black.
*
* @param color The color.
*
* @see getDefaultColor
*/
virtual void setDefaultColor(colortype color)
{
defaultColor = color;
}
/**
* Gets default color previously set using setDefaultColor.
*
* @return The default color.
*
* @see setDefaultColor
*/
colortype getDefaultColor() const
{
return defaultColor;
}
/**
* Texture map triangle. Draw a perspective correct texture mapped triangle. The
* vertices describes the surface, the x,y,z coordinates and the u,v coordinates of the
* texture. The texture contains the image data to be drawn The triangle line will be
* placed and clipped using the absolute and dirty rectangles The alpha will determine
* how the triangle should be alpha blended. The subDivisionSize will determine the size
* of the piecewise affine texture mapped portions of the triangle.
*
* @param dest The description of where the texture is drawn - can be used
* to issue a draw off screen.
* @param vertices The vertices of the triangle.
* @param texture The texture.
* @param absoluteRect The containing rectangle in absolute coordinates.
* @param dirtyAreaAbsolute The dirty area in absolute coordinates.
* @param renderVariant The render variant - includes the algorithm and the pixel
* format.
* @param alpha (Optional) the alpha. Default is 255 (solid).
* @param subDivisionSize (Optional) the size of the subdivisions of the scan line.
* Default is 12.
*/
virtual void drawTextureMapTriangle(const DrawingSurface& dest,
const Point3D* vertices,
const TextureSurface& texture,
const Rect& absoluteRect,
const Rect& dirtyAreaAbsolute,
RenderingVariant renderVariant,
uint8_t alpha = 255,
uint16_t subDivisionSize = 12);
/**
* Texture map quad. Draw a perspective correct texture mapped quad. The
* vertices describes the surface, the x,y,z coordinates and the u,v coordinates of the
* texture. The texture contains the image data to be drawn The quad line will be
* placed and clipped using the absolute and dirty rectangles The alpha will determine
* how the quad should be alpha blended. The subDivisionSize will determine the size
* of the piecewise affine texture mapped portions of the quad.
*
* @param dest The description of where the texture is drawn - can be used
* to issue a draw off screen.
* @param vertices The vertices of the quad.
* @param texture The texture.
* @param absoluteRect The containing rectangle in absolute coordinates.
* @param dirtyAreaAbsolute The dirty area in absolute coordinates.
* @param renderVariant The render variant - includes the algorithm and the pixel
* format.
* @param alpha (Optional) the alpha. Default is 255 (solid).
* @param subDivisionSize (Optional) the size of the subdivisions of the scan line.
* Default is 12.
*/
virtual void drawTextureMapQuad(const DrawingSurface& dest,
const Point3D* vertices,
const TextureSurface& texture,
const Rect& absoluteRect,
const Rect& dirtyAreaAbsolute,
RenderingVariant renderVariant,
uint8_t alpha = 255,
uint16_t subDivisionSize = 12);
/**
* Approximates an integer division of a 16bit value by 255. Divides numerator num (e.g.
* the sum resulting from an alpha-blending operation) by 255.
*
* @param [in] num The numerator to divide by 255.
*
* @return The result of a division by 255.
*/
FORCE_INLINE_FUNCTION static uint8_t div255(uint16_t num)
{
return (num + 1 + (num >> 8)) >> 8;
}
/**
* Divides the red and blue components of pixelxAlpha by 255.
*
* @param [in] pixelxAlpha The red and blue components of a 32bit ARGB pixel multiplied
* by an alpha factor.
*
* @return pixelxAlpha with its red and blue components divided by 255.
*/
FORCE_INLINE_FUNCTION static uint32_t div255rb(uint32_t pixelxAlpha)
{
return ((pixelxAlpha + 0x10001 + ((pixelxAlpha >> 8) & 0xFF00FF)) >> 8) & 0xFF00FF;
}
/**
* Divides the green component of pixelxAlpha by 255.
*
* @param [in] pixelxAlpha The green component of a 32bit ARGB pixel multiplied by an
* alpha factor.
*
* @return pixelxAlpha with its green component divided by 255.
*/
FORCE_INLINE_FUNCTION static uint32_t div255g(uint32_t pixelxAlpha)
{
return ((pixelxAlpha + 0x100 + (pixelxAlpha >> 8)) >> 8) & 0x00FF00;
}
protected:
static const uint16_t newLine = 10; ///< NewLine value.
static colortype defaultColor; ///< Default Color to use when displaying transparency-only elements, e.g. A4 bitmaps
/** Base class for drawing scanline by the texture mapper. */
class DrawTextureMapScanLineBase
{
public:
/** Finalizes an instance of the DrawTextureMapScanLineBase class. */
virtual ~DrawTextureMapScanLineBase()
{
}
/**
* Draw texture map scan line subdivisions.
*
* @param subdivisions The number of subdivisions.
* @param widthModLength Remainder of length (after subdivisions).
* @param pixelsToDraw The pixels to draw.
* @param affineLength Length of one subdivision.
* @param oneOverZRight 1/Z right.
* @param UOverZRight U/Z right.
* @param VOverZRight V/Z right.
* @param U U Coordinate in fixed16_16 notation.
* @param V V Coordinate in fixed16_16 notation.
* @param deltaU U delta to get to next pixel coordinate.
* @param deltaV V delta to get to next pixel coordinate.
* @param ULeft The left U.
* @param VLeft The left V.
* @param URight The right U.
* @param VRight The right V.
* @param ZRight The right Z.
* @param dest Destination drawing surface.
* @param destX Destination x coordinate.
* @param destY Destination y coordinate.
* @param texture The texture.
* @param alpha The global alpha.
* @param dOneOverZdXAff 1/ZdX affine.
* @param dUOverZdXAff U/ZdX affine.
* @param dVOverZdXAff V/ZdX affine.
*/
virtual void drawTextureMapScanLineSubdivisions(int subdivisions, const int widthModLength, int pixelsToDraw, const int affineLength, float oneOverZRight, float UOverZRight, float VOverZRight, fixed16_16 U, fixed16_16 V, fixed16_16 deltaU, fixed16_16 deltaV, float ULeft, float VLeft, float URight, float VRight, float ZRight, const DrawingSurface& dest, const int destX, const int destY, const TextureSurface& texture, uint8_t alpha, const float dOneOverZdXAff, const float dUOverZdXAff, const float dVOverZdXAff) = 0;
protected:
static const fixed16_16 half = 0x8000; ///< 1/2 in fixed16_16 format
/**
* Draw texture map next subdivision.
*
* @param [out] ULeft U left.
* @param [out] VLeft V left.
* @param [out] ZRight Z right.
* @param [out] URight U right.
* @param [out] VRight V right.
* @param [in,out] oneOverZRight 1/Z right.
* @param dOneOverZdXAff d1/ZdX affine.
* @param [in,out] UOverZRight U/Z right.
* @param dUOverZdXAff dU/ZdX affine.
* @param [in,out] VOverZRight V/Z right.
* @param dVOverZdXAff dV/ZdX affine.
* @param affineLength Length of the affine.
* @param [out] U Bitmap X in fixed16_16.
* @param [out] V Bitmap Y in fixed16_16.
* @param [out] deltaU U delta.
* @param [out] deltaV V delta.
*/
FORCE_INLINE_FUNCTION void drawTextureMapNextSubdivision(float& ULeft, float& VLeft, float& ZRight, float& URight, float& VRight, float& oneOverZRight, const float dOneOverZdXAff, float& UOverZRight, const float dUOverZdXAff, float& VOverZRight, const float dVOverZdXAff, const int affineLength, fixed16_16& U, fixed16_16& V, fixed16_16& deltaU, fixed16_16& deltaV)
{
ULeft = URight;
VLeft = VRight;
oneOverZRight += dOneOverZdXAff;
UOverZRight += dUOverZdXAff;
VOverZRight += dVOverZdXAff;
ZRight = 1 / oneOverZRight;
URight = ZRight * UOverZRight;
VRight = ZRight * VOverZRight;
U = floatToFixed16_16(ULeft);
V = floatToFixed16_16(VLeft);
deltaU = floatToFixed16_16(URight - ULeft) / affineLength;
deltaV = floatToFixed16_16(VRight - VLeft) / affineLength;
}
/**
* Check if value is inside [0..limit[.
*
* @param [in] value Value to check.
* @param [in] limit Upper limit.
*
* @return true if value is inside given limit.
*/
FORCE_INLINE_FUNCTION bool is1Inside(int value, int limit) const
{
return (value >= 0 && value < limit);
}
/**
* Check if (x,y) is inside ([0..width[, [0..height[)
*
* @param [in] x X coordinate.
* @param [in] y Y coordinate.
* @param [in] width X limit.
* @param [in] height Y limit.
*
* @return true if (x,y) is inside given limits.
*/
FORCE_INLINE_FUNCTION bool is1x1Inside(int x, int y, int width, int height) const
{
return is1Inside(x, width) && is1Inside(y, height);
}
/**
* Check if both value and value+1 are inside [0..limit[.
*
* @param [in] value Value to check.
* @param [in] limit Upper limit.
*
* @return true if value and value+1 are inside given limit.
*/
FORCE_INLINE_FUNCTION bool is2Inside(int value, int limit) const
{
return is1Inside(value, limit - 1);
}
/**
* Check if both (x,y) and (x+1,y+1) are inside ([0..width[,[0..height[)
*
* @param [in] x X coordinate.
* @param [in] y Y coordinate.
* @param [in] width X limit.
* @param [in] height Y limit.
*
* @return true if (x,y) and (x+1,y+1) are inside given limits.
*/
FORCE_INLINE_FUNCTION bool is2x2Inside(int x, int y, int width, int height) const
{
return is2Inside(x, width) && is2Inside(y, height);
}
/**
* Check if either value or value+1 is inside [0..limit[.
*
* @param [in] value Value to check.
* @param [in] limit Upper limit.
*
* @return true if either value or value+1 is inside given limit.
*/
FORCE_INLINE_FUNCTION bool is2PartiallyInside(int value, int limit) const
{
return is1Inside(value + 1, limit + 1);
}
/**
* Check if either (x,y) or (x+1,y+1) is inside ([0..width[,[0..height[)
*
* @param [in] x X coordinate.
* @param [in] y Y coordinate.
* @param [in] width X limit.
* @param [in] height Y limit.
*
* @return true if either (x,y) or (x+1,y+1) is inside given limits.
*/
FORCE_INLINE_FUNCTION bool is2x2PartiallyInside(int x, int y, int width, int height) const
{
return is2PartiallyInside(x, width) && is2PartiallyInside(y, height);
}
};
/**
* Gets pointer to object that can draw a scan line which allows for highly specialized
* and optimized implementation.
*
* @param texture The texture Surface.
* @param renderVariant The render variant.
* @param alpha The global alpha.
*
* @return Null if it fails, else the pointer to the texture mapper draw scan line
* object.
*/
virtual DrawTextureMapScanLineBase* getTextureMapperDrawScanLine(const TextureSurface& texture, RenderingVariant renderVariant, uint8_t alpha);
/**
* Draw scan line. Draw one horizontal line of the texture map on screen. The scan line
* will be drawn using perspective correct texture mapping. The appearance of the line
* is determined by the left and right edge and the gradients structure. The edges
* contain the information about the x,y,z coordinates of the left and right side
* respectively and also information about the u,v coordinates of the texture map used.
* The gradients structure contains information about how to interpolate all the values
* across the scan line. The data drawn should be present in the texture argument.
*
* The scan line will be drawn using the additional arguments. The scan line will be
* placed and clipped using the absolute and dirty rectangles The alpha will determine
* how the scan line should be alpha blended. The subDivisionSize will determine the
* size of the piecewise affine texture mapped lines.
*
* @param dest The description of where the texture is drawn - can be used
* to issue a draw off screen.
* @param gradients The gradients using in interpolation across the scan line.
* @param leftEdge The left edge of the scan line.
* @param rightEdge The right edge of the scan line.
* @param texture The texture.
* @param absoluteRect The containing rectangle in absolute coordinates.
* @param dirtyAreaAbsolute The dirty area in absolute coordinates.
* @param renderVariant The render variant - includes the algorithm and the pixel
* format.
* @param alpha The alpha.
* @param subDivisionSize The size of the subdivisions of the scan line. A value of 1
* will give a completely perspective correct texture mapped
* scan line. A large value will give an affine texture mapped
* scan line.
*/
virtual void drawTextureMapScanLine(const DrawingSurface& dest, const Gradients& gradients, const Edge* leftEdge, const Edge* rightEdge, const TextureSurface& texture, const Rect& absoluteRect, const Rect& dirtyAreaAbsolute, RenderingVariant renderVariant, uint8_t alpha, uint16_t subDivisionSize);
/**
* Private version of draw-glyph with explicit destination buffer pointer argument. For
* all parameters (except the buffer pointer) see the public function drawString().
*
* @param [out] wbuf16 The destination (frame) buffer to draw to.
* @param widgetArea The canvas to draw the glyph inside.
* @param x Horizontal offset to start drawing the glyph.
* @param y Vertical offset to start drawing the glyph.
* @param offsetX Horizontal offset in the glyph to start drawing from.
* @param offsetY Vertical offset in the glyph to start drawing from.
* @param invalidatedArea The area to draw inside.
* @param glyph Specifications of the glyph to draw.
* @param glyphData Data containing the actual glyph (dense format)
* @param byteAlignRow Each row of glyph data starts in a new byte.
* @param color The color of the glyph.
* @param bitsPerPixel Bit depth of the glyph.
* @param alpha The transparency of the glyph.
* @param rotation Rotation to do before drawing the glyph.
*/
virtual void drawGlyph(uint16_t* wbuf16, Rect widgetArea, int16_t x, int16_t y, uint16_t offsetX, uint16_t offsetY, const Rect& invalidatedArea, const GlyphNode* glyph, const uint8_t* glyphData, uint8_t byteAlignRow, colortype color, uint8_t bitsPerPixel, uint8_t alpha, TextRotation rotation) = 0;
/**
* Rotate a rectangle inside another rectangle.
*
* @param [in,out] rect The rectangle to rotate.
* @param canvas The rectangle containing the rect to rotate.
* @param rotation Rotation to perform on rect.
*/
static void rotateRect(Rect& rect, const Rect& canvas, const TextRotation rotation);
/**
* Find the real, absolute x coordinate of a point inside a widget with regards to
* rotation.
*
* @param [in] widgetArea The widget containing the point.
* @param x The x coordinate.
* @param y The y coordinate.
* @param rotation Rotation to perform.
*
* @return The absolute x coordinate after applying appropriate rotation.
*/
static int realX(const Rect& widgetArea, int16_t x, int16_t y, TextRotation rotation);
/**
* Find the real, absolute y coordinate of a point inside a widget with regards to
* rotation.
*
* @param [in] widgetArea The widget containing the point.
* @param x The x coordinate.
* @param y The y coordinate.
* @param rotation Rotation to perform.
*
* @return The absolute y coordinate after applying appropriate rotation.
*/
static int realY(const Rect& widgetArea, int16_t x, int16_t y, TextRotation rotation);
/**
* Draws the specified Unicode string. Breaks line on newline. The string is assumed to
* contain only Latin characters written left-to-right.
*
* @param widgetArea The area covered by the drawing widget in absolute
* coordinates.
* @param invalidatedArea The (sub)region of the widget area to draw, expressed
* relative to the widget area. If the widgetArea is
* x=10, y=10, width=20, height=20 and invalidatedArea
* is x=5, y=5, width=6, height=6 the widgetArea drawn
* on the LCD is x=15, y=15, width=6, height=6.
* @param [in] visuals The string visuals (font, alignment, line space, color)
* with which to draw this string.
* @param format A pointer to a null-terminated text string with optional
* additional wildcard arguments.
* @param pArg Variable arguments providing additional information.
*
* @see drawString
*/
void drawStringLTR(const Rect& widgetArea,
const Rect& invalidatedArea,
const StringVisuals& visuals,
const Unicode::UnicodeChar* format,
va_list pArg);
/**
* Draws the specified Unicode string. Breaks line on newline. The string can be either
* right-to-left or left-to-right and may contain sequences of Arabic / Hebrew and Latin
* characters.
*
* @param widgetArea The area covered by the drawing widget in absolute
* coordinates.
* @param invalidatedArea The (sub)region of the widget area to draw, expressed
* relative to the widget area. If the widgetArea is
* x=10, y=10, width=20, height=20 and invalidatedArea
* is x=5, y=5, width=6, height=6 the widgetArea drawn
* on the LCD is x=15, y=15, width=6, height=6.
* @param [in] visuals The string visuals (font, alignment, line space, color)
* with which to draw this string.
* @param format A pointer to a null-terminated text string with optional
* additional wildcard arguments.
* @param pArg Variable arguments providing additional information.
*
* @see drawString
*/
void drawStringRTL(const Rect& widgetArea,
const Rect& invalidatedArea,
const StringVisuals& visuals,
const Unicode::UnicodeChar* format,
va_list pArg);
/**
* Find string width of the given number of ligatures read from the given TextProvider.
* After the introduction of Arabic, Thai, Hindi and other languages, ligatures are
* counted instead of characters. For Latin languages, number of characters equal number
* of ligatures.
*
* @param [in] textProvider The text provider.
* @param font The font.
* @param numChars Number of characters (ligatures).
* @param textDirection The text direction.
*
* @return An int16_t.
*/
static uint16_t stringWidth(TextProvider& textProvider, const Font& font, const int numChars, TextDirection textDirection);
/**
* Gets number of lines for a given text taking word wrap into consideration. The font
* and width are required to find the number of lines in case word wrap is true.
*
* @param [in] textProvider The text provider.
* @param wideTextAction The wide text action in case lines are longer than the width
* of the text area.
* @param textDirection The text direction (LTR or RTL).
* @param font The font.
* @param width The width.
*
* @return The number lines.
*/
static uint16_t getNumLines(TextProvider& textProvider, WideTextAction wideTextAction, TextDirection textDirection, const Font* font, int16_t width);
friend class Font;
friend class TextArea;
friend class TextAreaWithWildcardBase;
/**
* Gets alpha from A4 image at given offset. The value is scaled up from range 0-15 to 0-
* 255.
*
* @param data A pointer to the start of the A4 data.
* @param offset The offset into the A4 image.
*
* @return The alpha from A4 (0-255).
*/
FORCE_INLINE_FUNCTION static uint8_t getAlphaFromA4(const uint16_t* data, uint32_t offset)
{
uint8_t byte = reinterpret_cast<const uint8_t*>(data)[offset / 2];
return ((offset & 1) == 0 ? byte & 0xF : byte >> 4) * 0x11;
}
private:
DrawTextureMapScanLineBase* textureMapperClass; ///< Used during faster TextureMapper rendering
/** A draw string internal structure. */
class DrawStringInternalStruct
{
public:
uint16_t* frameBuffer;
const Rect* widgetArea;
int16_t widgetRectY;
const Rect* toDraw;
const StringVisuals* stringVisuals;
/** Initializes a new instance of the DrawStringInternalStruct class. */
DrawStringInternalStruct()
: frameBuffer(0), widgetArea(0), widgetRectY(0), toDraw(0), stringVisuals(0)
{
}
};
void drawStringRTLLine(int16_t& offset, const Font* font, TextDirection textDirection, TextProvider& textProvider, const int numChars, const bool useEllipsis, const DrawStringInternalStruct* data);
void drawStringRTLInternal(int16_t& offset, const Font* font, const TextDirection textDirection, TextProvider& drawTextProvider, const int numChars, const uint16_t widthOfNumChars, const DrawStringInternalStruct* data);
bool drawStringInternal(uint16_t* frameBuffer, const Rect* widgetArea, int16_t widgetRectY, int16_t offset, const Rect& invalidatedArea, const StringVisuals* stringVisuals, const TextDirection textDirection, TextProvider& textProvider, const int numChars, bool useEllipsis);
/** A wide text internal structure. */
class WideTextInternalStruct
{
public:
/**
* Initializes a new instance of the WideTextInternalStruct class.
*
* @param [in] textProvider The text provider.
* @param width The maximum width.
* @param height The height.
* @param direction The text direction.
* @param _font The font.
* @param _linespace The linespace.
* @param action The action.
*/
WideTextInternalStruct(TextProvider& textProvider, uint16_t width, uint16_t height, TextDirection direction, const Font* _font, int16_t _linespace, WideTextAction action)
: currChar(0), tp(textProvider), textDirection(direction), wideTextAction(action), font(_font), areaWidth(width), areaHeight(height), linespace(_linespace), charsRead(0), widthUsed(0), charsReadAhead(0), widthAhead(0), widthWithoutWhiteSpaceAtEnd(0), ellipsisGlyphWidth(0), useEllipsis(false)
{
if (wideTextAction != WIDE_TEXT_NONE)
{
Unicode::UnicodeChar ellipsisChar = font->getEllipsisChar();
if (ellipsisChar != 0)
{
const GlyphNode* ellipsisGlyph = font->getGlyph(ellipsisChar);
if (ellipsisGlyph != 0)
{
ellipsisGlyphWidth = ellipsisGlyph->advance();
if (wideTextAction == WIDE_TEXT_CHARWRAP_DOUBLE_ELLIPSIS)
{
ellipsisGlyphWidth += font->getKerning(ellipsisChar, ellipsisGlyph) + ellipsisGlyph->advance();
}
}
}
}
}
/**
* Gets string length for line.
*
* @param useWideTextEllipsisFlag True to use wide text ellipsis flag.
*/
void scanStringLengthForLine();
/**
* Query if 'ch' is space.
*
* @param ch The ch.
*
* @return True if space, false if not.
*/
bool isSpace(Unicode::UnicodeChar ch)
{
return ch == ' ' || ch == 0x200B;
}
/**
* Gets current character.
*
* @return The current character.
*/
Unicode::UnicodeChar getCurrChar() const
{
return currChar;
}
/**
* Gets line width.
*
* @return The line width.
*/
uint16_t getLineWidth() const
{
return widthWithoutWhiteSpaceAtEnd;
}
/**
* Gets characters read.
*
* @return The characters read.
*/
uint16_t getCharsRead() const
{
return charsRead;
}
/**
* Determines if we ellipsis was added at end of line.
*
* @return True if it succeeds (not more text), false otherwise.
*/
bool ellipsisAtEndOfLine() const
{
return useEllipsis;
}
private:
Unicode::UnicodeChar currChar;
TextProvider& tp;
TextDirection textDirection;
WideTextAction wideTextAction;
const Font* font;
uint16_t areaWidth;
uint16_t areaHeight;
int16_t linespace;
uint16_t charsRead;
uint16_t widthUsed;
uint16_t charsReadAhead;
uint16_t widthAhead;
uint16_t widthWithoutWhiteSpaceAtEnd;
uint16_t ellipsisGlyphWidth;
bool useEllipsis;
void addWord(uint16_t widthBeforeCurrChar, uint16_t widthBeforeWhiteSpaceAtEnd, uint16_t charsReadTooMany);
};
};
} // namespace touchgfx
#endif // TOUCHGFX_LCD_HPP