TouchGFX的画布控件,在使用相对较小的存储空间的同时保持高性能,可提供平滑、抗锯齿效果良好的几何图形绘制。
TouchGFX 设计器中可用的画布控件:
存储空间分配和使用
为了生成反锯齿效果良好的复杂几何图形,需要额外的存储空间。 为此,CWR必须具有专门分配的存储缓冲区,以便在渲染过程中使用。 CWR与TouchGFX的其余部分一样,没有动态存储空间分配。
在TouchGFX Designer中,可以在屏幕属性中重写画布缓冲区大小
需要的CWR存储空间的量取决于要在应用中绘制的最大图形大小。 但是,您可以保留比最复杂形状所需内存空间更少的内存。 为了应对这种情况,CWR将图形绘制分割成较小的帧缓存部分,在这种情况下,由于有时需要不止一次地渲染图像,因此渲染时间稍长。 在模拟器模式下运行时,可以更细致地查看存储空间消耗并进行微调。 只需向main.cpp中添加函数CanvasWidgetRenderer::setWriteMemoryUsageReport(true),具体操作如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace touchgfx;
#ifdef __linux__
int main(int argc, char** argv)
{
#else
#include
#ifdef _UNICODE
#error Cannot run in unicode mode
#endif
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
int argc;
char** argv = touchgfx::HALSDL2::getArgv(&argc);
#endif
touchgfx::NoDMA dma; //For windows/linux, DMA transfers are simulated
LCD& lcd = setupLCD();
touchgfx::SDL2TouchController tc;
touchgfx::HAL& hal = touchgfx::touchgfx_generic_init(dma, lcd, tc, SIM_WIDTH, SIM_HEIGHT, 0, 0);
setupSimulator(argc, argv, hal);
// Ensure there is a console window to print to using printf() or
// std::cout, and read from using e.g. fgets or std::cin.
// Alternatively, instead of using printf(), always use
// touchgfx_printf() which will ensure there is a console to write
// to.
//touchgfx_enable_stdio();
CanvasWidgetRenderer::setWriteMemoryUsageReport(true);
touchgfx::HAL::getInstance()->taskEntry(); //Never returns
return EXIT_SUCCESS;
}
自定义画布控件
实现自定义画布控件需要用下列函数实现新类:
virtual bool drawCanvasWidget(const Rect& invalidatedArea) const;
virtual Rect getMinimalRect() const;
drawCanvasWidget()
必须绘制自定义控件需要绘制的任何内容,并且 getMinimalRect()
应该返回 Widget 中包含几何形状的实际矩形。
举例:在10x10方块内部粗略实现一个菱形块
Diamond10x10.hpp
#ifndef DIAMOND10X10_HPP
#define DIAMOND10X10_HPP
#include
#include
using namespace touchgfx;
class Diamond10x10 : public CanvasWidget
{
public:
virtual Rect getMinimalRect() const
{
return Rect(0,0,10,10);
}
virtual bool drawCanvasWidget(const Rect& invalidatedArea) const
{
Canvas canvas(this, invalidatedArea);
canvas.moveTo(5,0);
canvas.lineTo(10,5);
canvas.lineTo(5,10);
canvas.lineTo(0,5);
return canvas.render(); // Shape is automatically closed
}
};
#endif
screenView.hpp
#ifndef SCREENVIEW_HPP
#define SCREENVIEW_HPP
#include
#include
#include
#include
class screenView : public screenViewBase
{
public:
screenView();
virtual ~screenView() {}
virtual void setupScreen();
virtual void tearDownScreen();
protected:
private:
Diamond10x10 box;
PainterRGB565 myPainter; // For 16bpp displays
};
#endif // SCREENVIEW_HPP
screenView.cpp
#include
#include
screenView::screenView()
{
}
void screenView::setupScreen()
{
screenViewBase::setupScreen();
myPainter.setColor(Color::getColorFromRGB(0xFF, 0x0, 0x0));
box.setPosition(100,100,10,10);
box.setPainter(myPainter);
add(box);
}
void screenView::tearDownScreen()
{
screenViewBase::tearDownScreen();
}
运行模拟器,效果如下(意味着画布缓冲区大小可以调整到大于168字节即可)
平铺位图
首先在模拟器中添加图片资源
然后修改程序
#ifndef DIAMOND10X10_HPP
#define DIAMOND10X10_HPP
#include
#include
using namespace touchgfx;
class Diamond10x10 : public CanvasWidget
{
public:
virtual Rect getMinimalRect() const
{
return Rect(0,0,100,100);
}
virtual bool drawCanvasWidget(const Rect& invalidatedArea) const
{
Canvas canvas(this, invalidatedArea);
canvas.moveTo(50,0);
canvas.lineTo(100,50);
canvas.lineTo(50,100);
canvas.lineTo(0,50);
return canvas.render(); // Shape is automatically closed
}
};
#endif
#ifndef SCREENVIEW_HPP
#define SCREENVIEW_HPP
#include
#include
#include
#include
class screenView : public screenViewBase
{
public:
screenView();
virtual ~screenView() {}
virtual void setupScreen();
virtual void tearDownScreen();
protected:
private:
Diamond10x10 box;
PainterRGB565Bitmap bitmapPainter;
};
#endif // SCREENVIEW_HPP
#include
#include
#include
screenView::screenView()
{
}
void screenView::setupScreen()
{
screenViewBase::setupScreen();
bitmapPainter.setBitmap(touchgfx::Bitmap(BITMAP_TEST_ID));
bitmapPainter.setTiled(true);
box.setPosition(100,100,100,100);
box.setPainter(bitmapPainter);
add(box);
}
void screenView::tearDownScreen()
{
screenViewBase::tearDownScreen();
}
运行模拟器,效果如下
定制绘图器
尽管TouchGFX提供一组预定义的画笔类,涵盖了大多数用例场景,但也可实现定制画笔
#ifndef REDPAINTER_HPP
#define REDPAINTER_HPP
#include
using namespace touchgfx;
class StripePainter : public AbstractPainterRGB565
{
public:
virtual void paint(uint8_t* destination, int16_t offset, int16_t widgetX, int16_t widgetY, int16_t count, uint8_t alpha) const
{
if ((widgetY & 2) == 0)
{
return; // Do not draw anything on line 0,1, 4,5, 8,9, etc.
}
uint16_t* framebuffer = reinterpret_cast(destination) + offset;
const uint16_t* const lineend = framebuffer + count;
if (alpha == 0xFF)
{
do
{
*framebuffer = 0xF800;
} while (++framebuffer < lineend);
}
else
{
do
{
*framebuffer = alphaBlend(0xF800, *framebuffer, alpha);
} while (++framebuffer < lineend);
}
}
};
#endif
#ifndef SCREENVIEW_HPP
#define SCREENVIEW_HPP
#include
#include
#include
#include
class screenView : public screenViewBase
{
public:
screenView();
virtual ~screenView() {}
virtual void setupScreen();
virtual void tearDownScreen();
protected:
private:
Diamond10x10 box;
StripePainter myPainter;
};
#endif // SCREENVIEW_HPP
#include
#include
screenView::screenView()
{
}
void screenView::setupScreen()
{
screenViewBase::setupScreen();
box.setPosition(100,100,100,100);
box.setPainter(myPainter);
add(box);
}
void screenView::tearDownScreen()
{
screenViewBase::tearDownScreen();
}
运行模拟器,效果如下