嵌入式GUI开发实战:SEGGER emWin 2D绘图库核心API与性能优化指南
2026/6/20 12:46:50 网站建设 项目流程

1. 项目概述:为什么嵌入式GUI开发离不开强大的2D绘图库?

在嵌入式系统开发领域,尤其是涉及人机交互界面(HMI)的项目中,图形用户界面(GUI)的实现往往是决定产品用户体验和开发效率的关键。不同于资源充沛的PC或移动平台,嵌入式设备通常受限于有限的处理器性能、内存大小和显示分辨率。在这种约束下,一个高效、稳定且功能完备的2D图形库就显得至关重要。它不仅是屏幕上绘制线条、矩形和文字的“画笔”,更是连接底层硬件驱动与上层应用逻辑的桥梁,直接决定了界面是否流畅、功能是否丰富以及开发周期是否可控。

SEGGER emWin正是为应对这一挑战而生的专业嵌入式GUI解决方案。它并非一个简单的图形绘制工具集,而是一个完整的图形库,其核心价值在于通过高度优化的算法和统一的API接口,将开发者从繁琐的像素操作、内存管理和硬件适配中解放出来。无论是需要在工业触摸屏上实时刷新传感器曲线,在智能家电面板上显示精美的图标和渐变背景,还是在医疗设备上绘制清晰的数据图表,emWin的2D图形库都提供了坚实的技术基础。本次分享将深入emWin的2D绘图世界,抛开官方手册的冰冷罗列,从一线开发者的实战视角,系统拆解其从基础像素操作到高级Alpha混合与位图显示的核心API,并附上大量你在官方文档里找不到的配置心得、性能调优技巧和避坑指南。

2. 核心设计思路:emWin 2D图形库的架构与哲学

在深入每个API之前,理解emWin 2D图形库的整体设计思路至关重要。这能帮助你在后续使用中做出更合理的选择,避免“能用但不好用”的尴尬局面。

2.1 分层抽象与硬件无关性

emWin的核心设计哲学是硬件抽象。它将图形操作分为几个清晰的层次:

  1. 应用层:开发者直接调用的API,如GUI_DrawLine(),GUI_FillRect()。这一层是稳定且统一的。
  2. 图形库核心层:包含所有绘图算法(如直线Bresenham算法、圆形中点画圆算法、多边形扫描线填充等)和资源管理(字体、位图)。
  3. LCD驱动层(LCD Driver):这是与硬件对接的关键。emWin通过一个结构体(通常是GUI_DEVICELCD_API)定义了一系列函数指针,如pfSetPixelIndex,pfFillRect等。你的任务就是根据自己使用的显示屏控制器(如ILI9341, SSD1963等)实现这些函数。

实操心得:很多新手在移植emWin时卡在第一步,就是因为没理解这个抽象层。你不需要修改emWin的核心代码,只需要在GUIDRV_Template.c这类模板文件中,用你显示屏的写点、画块函数去填充那些函数指针。一旦驱动层调通,上层的所有API就都能工作了。这种设计使得你的应用代码与硬件完全解耦,更换显示屏控制器时,只需重写驱动层,应用代码几乎无需改动。

2.2 窗口管理器(WM)与绘图上下文

emWin的另一个核心是窗口管理器(Window Manager, WM)。它管理着屏幕上可能重叠的多个矩形区域(窗口)。2D绘图API可以在“当前窗口”的“客户区”内进行。GUI_GetClientRect()这个函数的作用就是获取这个可绘制的区域范围。

  • 不使用WM:如果你开发的是简单的全屏界面,可以不初始化WM。此时,“当前窗口”就是整个屏幕,GUI_GetClientRect()返回的是整个LCD的尺寸。
  • 使用WM:当你需要对话框、按钮、列表等控件时,WM会自动管理每个控件的绘制区域(客户区)。在控件的回调函数中绘图,GUI_GetClientRect()返回的就是该控件内部的可用区域,绘图操作会自动被限制在这个区域内,无需手动进行复杂的区域裁剪判断,这极大地简化了复杂界面的开发。

2.3 颜色模型与绘制模式

emWin内部使用32位ARGB(Alpha, Red, Green, Blue)颜色模型,但对外提供了灵活的配置。你可以通过配置选择显示设备的实际色彩深度(如16位RGB565,8位灰度,甚至1位黑白)。库内部会进行颜色转换。

绘制模式(Draw Mode)是另一个容易被忽略但功能强大的特性,主要通过GUI_SetDrawMode()设置:

  • GUI_DM_NORMAL(默认):直接覆盖目标像素。
  • GUI_DM_XOR(异或模式):新像素颜色与原有像素颜色进行按位异或操作。这在实现“橡皮筋”效果(如画图时临时显示一个矩形框)时非常有用:在同一个位置绘制两次,图形会消失,恢复原背景。

注意事项:XOR模式在使用时限制较多。官方文档明确指出,它通常只在单色或双色窗口内工作良好,且与大于1像素的画笔尺寸、某些复杂绘图函数(如带抗锯齿的图形)兼容性不佳。在使用GUI_DrawLine()等函数前,如果启用了XOR模式,务必通过GUI_SetPenSize(1)将画笔设回1像素,否则可能出现非预期效果。

3. 基础绘图API详解:从像素到复杂形状

这是构建一切图形界面的砖瓦。emWin提供的基础绘图函数丰富且高效,但要用好它们,必须了解其行为细节。

3.1 像素与点:一切的起点

  • GUI_DrawPixel(int x, int y): 绘制单个像素。这是最底层的操作。在驱动层优化良好的情况下,直接调用此函数画图效率极低,应避免用于画线或区域填充。
  • GUI_DrawPoint(int x, int y): 用当前画笔大小绘制一个“点”。如果GUI_SetPenSize(3),那么这个“点”就是一个3x3的实心方块。它和GUI_DrawPixel的关键区别就在于对画笔尺寸的响应。

3.2 线条绘制:效率与风格的平衡

emWin提供了多种画线函数,适应不同场景:

  • GUI_DrawLine(int x0, int y0, int x1, int y1): 给定起点终点画线。最常用。
  • GUI_DrawLineTo(int x, int y): 从“当前画笔位置”画线到指定点。需要配合GUI_MoveTo()设置起点。这在连续绘制折线时很方便。
  • GUI_DrawPolyLine(const GUI_POINT* pPoint, int NumPoints): 绘制多段线。传入一个点数组和点数,效率高于多次调用GUI_DrawLineTo

线条样式:通过GUI_SetLineStyle()可以设置虚线、点线等样式。但请注意一个重要限制:线样式与画笔大小(PenSize)大于1是互斥的。如果你设置了虚线样式,同时又设置了GUI_SetPenSize(2),那么实际绘制出的很可能不是预期的虚线,而是实线。在需要粗虚线时,通常需要自己用多个矩形来模拟。

3.3 矩形与区域操作:界面布局的基石

矩形操作是GUI开发中最频繁使用的功能之一,emWin对此做了大量优化。

  • 轮廓与填充
    • GUI_DrawRect()/GUI_DrawRectEx(): 绘制矩形边框。后者接受一个GUI_RECT结构体指针,当需要频繁使用同一个矩形区域时更方便。
    • GUI_FillRect()/GUI_FillRectEx(): 填充矩形区域。这是优化最好的函数之一,底层驱动通常会实现一个高效的pfFillRect函数,用于快速填充整块显存,比用循环画线快几个数量级。
  • 清空与反转
    • GUI_ClearRect(): 用当前背景色填充矩形。常用于局部重绘前清除旧内容。
    • GUI_InvertRect(): 反转矩形区域内所有像素的颜色(颜色索引取反)。在黑白屏上实现“反白”选中效果非常高效。
  • 圆角矩形GUI_DrawRoundedRect()GUI_FillRoundedRect()用于绘制带圆角的矩形,参数r指定圆角半径。现代界面设计中圆角元素无处不在,这两个函数省去了自己计算圆弧的麻烦。
  • 渐变填充GUI_DrawGradientH/V()用于绘制水平/垂直渐变色的矩形。GUI_DrawGradientRoundedH/V()则是圆角矩形的渐变填充。它们通过在两个颜色间插值实现,能显著提升界面的视觉质感。

性能调优技巧:在需要频繁重绘的区域(如动态图表区),尽量使用GUI_FillRect()而不是多次调用GUI_DrawPixelGUI_DrawLine来清空背景。同样,绘制一个实心矩形,GUI_FillRect也比先用GUI_DrawRect画框再内部填充快得多。对于固定位置的静态背景(如带渐变的标题栏),可以考虑将其渲染到位图(Bitmap)中,然后直接贴图,避免每次重绘都进行渐变计算。

3.4 圆形、椭圆与多边形

  • GUI_DrawCircle()/GUI_FillCircle(): 绘制(填充)圆。参数是圆心坐标和半径。
  • GUI_DrawEllipse()/GUI_FillEllipse(): 绘制(填充)椭圆。参数是椭圆外接矩形的左上角和右下角坐标。
  • GUI_DrawPolygon()/GUI_FillPolygon(): 绘制(填充)多边形。需要传入顶点数组。GUI_FillPolygon使用的扫描线填充算法是这类函数中相对耗时的,应避免在性能敏感的循环中频繁调用复杂多边形。

一个关键细节:官方文档提到,在emWin V5.18中,只有GUI_DrawArc()(绘制圆弧)函数内部使用了浮点运算。如果你的单片机没有FPU(浮点处理单元),且需要绘制圆弧,请注意这可能会带来一定的性能开销。对于有FPU的芯片则无需担心。

4. Alpha混合技术:实现半透明与高级视觉效果

Alpha混合是让界面脱离“平面感”,实现叠加、阴影、平滑过渡等高级效果的核心技术。emWin的Alpha混合实现既强大又需谨慎使用。

4.1 原理与启用

emWin内部将颜色视为32位值:0xAARRGGBB(Alpha, Red, Green, Blue)。Alpha值(0-255)控制透明度:0为完全不透明(默认),255为完全透明。

启用Alpha混合非常简单:GUI_EnableAlpha(1)。一旦启用,之后所有绘图操作的颜色的Alpha通道(即32位颜色值的高8位)就会生效。

// 示例:绘制三个半透明叠加的矩形 GUI_EnableAlpha(1); // 启用Alpha混合 GUI_SetBkColor(GUI_WHITE); GUI_Clear(); // 绘制一个半透明的红色矩形 (Alpha = 0x40,约25%透明度) GUI_SetColor((0x40uL << 24) | GUI_RED); // 注意:必须将Alpha值左移24位 GUI_FillRect(0, 0, 49, 49); // 绘制一个更透明的绿色矩形 (Alpha = 0x80,约50%透明度) GUI_SetColor((0x80uL << 24) | GUI_GREEN); GUI_FillRect(20, 20, 69, 69); // 绘制一个轻微透明的蓝色矩形 (Alpha = 0xC0,约75%透明度) GUI_SetColor((0xC0uL << 24) | GUI_BLUE); GUI_FillRect(40, 40, 89, 89);

4.2 新旧API对比与选择

emWin提供了两套Alpha混合API,理解其区别很重要:

  1. 旧版GUI_SetAlpha()(已过时但可用)

    • 功能:为之后所有的绘图操作设置一个全局的、固定的Alpha值。
    • 缺点:它是“软件Alpha混合”,即通过CPU计算来实现颜色混合,会显著增加CPU负载。且它是全局状态,容易忘记恢复,影响后续绘图。
    • 用法:GUI_SetAlpha(0x80); // 设置后续绘制半透明,完成后必须GUI_SetAlpha(0); // 恢复不透明
  2. 新版 每像素Alpha (推荐)

    • 功能:通过GUI_EnableAlpha(1)启用后,每个绘图命令所使用的颜色值自身就携带Alpha信息(如上面的示例)。
    • 优点:更灵活,每个图形元素可以有不同的透明度。如果底层LCD驱动支持硬件Alpha混合(部分高端显示控制器有),效率会极高。
    • 这是当前推荐的做法

4.3 用户Alpha值:叠加控制

GUI_SetUserAlpha()提供了一个额外的控制层级。它设置一个“用户Alpha值”,会与物体自身的Alpha值进行二次混合。公式为:最终Alpha = 物体Alpha + ((255 - 物体Alpha) * 用户Alpha) / 255

这常用于实现整个图层或窗口的淡入淡出效果。例如,一个弹出对话框,其内部所有元素(按钮、文字)都有自己的Alpha,你可以通过GUI_SetUserAlpha控制整个对话框的总体透明度。

GUI_ALPHA_STATE AlphaState; // 保存当前状态并设置用户Alpha为0xC0(约75%) GUI_SetUserAlpha(&AlphaState, 0xC0); // ... 在此处绘制对话框的所有内容 ... // 恢复之前的用户Alpha状态 GUI_RestoreUserAlpha(&AlphaState);

避坑指南

  1. 性能陷阱:软件Alpha混合(尤其是旧版GUI_SetAlpha)是CPU密集型操作,在低端MCU(如Cortex-M0)上大面积使用会导致帧率严重下降。务必在目标硬件上评估性能。
  2. 颜色值构造:使用每像素Alpha时,构造颜色常量务必注意。GUI_RED等常量通常不包含Alpha值。正确做法是:(Alpha << 24) | GUI_RED。忘记左移24位是常见错误,会导致Alpha设置无效。
  3. 混合顺序:Alpha混合的结果依赖于绘制顺序。先画背景,再画半透明前景,才能得到正确的叠加效果。
  4. 硬件支持:如果你的LCD控制器支持硬件Alpha(如STM32的LTDC图层混合),务必查阅emWin的移植层文档,可能需要实现自定义的颜色转换函数(LCD_COLOR宏)来将emWin的ARGB格式转换为硬件所需的格式(通常是ARGB8888或类似)。

5. 位图显示全解析:从内存到流式加载

在嵌入式界面中,图标、logo、背景图片都离不开位图(Bitmap)显示。emWin的位图子系统功能复杂但设计精巧,支持从内存直接显示到从外部存储器流式解码。

5.1 基础位图显示

  • GUI_DrawBitmap(const GUI_BITMAP * pBM, int x, int y): 最常用的函数,从内存中绘制一个已解码的位图结构。GUI_BITMAP结构体包含了图像的像素数据、尺寸、颜色格式等信息。这个结构体通常由emWin的位图转换器(Bitmap Converter)工具从PNG、BMP等图片文件生成。
  • GUI_DrawBitmapMag(): 对位图进行整数倍放大。例如放大2倍,每个像素变成2x2的方块。不适合高质量缩放,仅适合像素风格图标放大。
  • GUI_DrawBitmapEx(): 功能最强大的位图绘制函数,支持缩放、镜像和指定锚点。参数xMag,yMag是千分比(1000代表原大小,2000代表放大2倍,-1000代表水平镜像)。你可以指定位图上的某个点 (xCenter,yCenter) 对齐到屏幕的 (x0,y0) 位置,再进行变换,这在实现旋转动画的某一帧时很有用。

5.2 流式位图:解决内存瓶颈的关键

嵌入式设备内存有限,一张全屏的RGB565位图可能就需要几百KB,无法全部载入内存。流式位图(Streamed Bitmap) API就是为了解决这个问题而生的。

核心思想:不一次性将整个位图文件加载到RAM,而是按需(通常是按行)从存储介质(如SPI Flash, SD卡)中读取数据,解码并显示。

emWin为此提供了两套函数族:

  1. GUI_DrawStreamedBitmap()/GUI_DrawStreamedBitmapAuto():适用于数据流已在可寻址内存(如已加载到RAM的数组或常量数组)中的情况。Auto版本会自动检测流格式。
  2. GUI_DrawStreamedBitmapEx()/GUI_DrawStreamedBitmapExAuto()及一系列具体格式函数:适用于数据在外部存储器中。这是更常用的场景。

Ex函数的工作流程

  1. 你需要提供一个GUI_GET_DATA_FUNC类型的回调函数。这个函数的作用是:当emWin需要更多位图数据时,它会被调用,你的实现需要从SD卡、Flash等地方读取指定长度的数据到提供的缓冲区。
  2. emWin利用这个回调函数,每次读取一部分数据(至少一行),解码并绘制,然后循环直到整个位图绘制完成。
  3. 这只需要很少的RAM缓冲区(几KB用于存放一行解码后的像素数据)。
// 示例:从文件系统流式显示一张位图 int myGetData(void * p, const U8 ** ppData, unsigned NumBytesReq, int Off) { // p: 调用时传入的用户参数,可以是文件句柄 // ppData: 用于返回数据指针的地址 // NumBytesReq: 请求的字节数 // Off: 请求的数据在流中的偏移量 FIL *file = (FIL*)p; UINT br; f_lseek(file, Off); // 移动文件指针 f_read(file, myBuffer, NumBytesReq, &br); // 读取到myBuffer *ppData = myBuffer; // 告诉emWin数据在哪里 return br; // 返回实际读取的字节数 } // 在主函数中 FIL file; f_open(&file, "picture.dta", FA_READ); // .dta是emWin位图转换器生成的流格式文件 GUI_DrawStreamedBitmapExAuto(myGetData, &file, 0, 0); // 从(0,0)开始绘制 f_close(&file);

5.3 位图格式与转换器

emWin支持丰富的位图格式,理解它们对优化存储空间和显示速度很重要:

格式标识描述适用场景
IDX (1-8bpp)索引色位图。包含一个调色板(最多256色)和索引数据。颜色数少的图标、图形,体积小。
565 / 55516位高彩色位图(RGB565: 5-6-5, RGB555: 5-5-5)。真彩图片,色彩过渡自然,无调色板开销。
M565 / M555同上,但红蓝通道交换(M=Mirrored)。用于适配某些硬件。硬件显示格式特殊时使用。
2424位真彩色位图(RGB888)。高质量图片,体积最大。
Alpha32位带Alpha通道的位图(ARGB8888)。需要每像素透明度的图片。
RLE4/RLE8/RLE16...对应格式的游程编码(RLE)压缩格式。对有大面积纯色区域的图片压缩率高。

SEGGER提供的位图转换器(Bitmap Converter)是必备工具。它可以将常见的PNG、BMP、JPEG图片转换为emWin支持的C数组或流文件(.dta)。在转换时,你需要权衡:

  • 色彩深度:选择能满足视觉要求的最低深度(如256色图标用8bpp IDX)。
  • 是否压缩:RLE压缩能减小体积,但解码会略微增加CPU开销。
  • 输出格式:开发阶段用C数组方便;量产时,将图片存为外部.dta文件,通过流式API读取,更利于维护和更新。

5.4 硬件Alpha混合位图

对于支持硬件图层混合的显示控制器(如STM32F7/H7系列的LTDC),emWin提供了GUI_DrawBitmapHWAlpha()函数。它的目的是将位图中预乘的Alpha通道信息直接传递给硬件,由显示控制器完成混合,从而解放CPU。

关键实现点:要使用此功能,你必须在LCD驱动层实现正确的颜色转换。emWin内部使用0x00RRGGBB(Alpha=0为不透明)格式,而你的硬件可能使用0xFFRRGGBB(Alpha=0xFF为不透明)或其他格式。你需要修改LCD_COLOR等宏或函数,确保传递的颜色值符合硬件预期。通常emWin的移植示例中会有一个LCD_ConvertColor()函数或类似的钩子(Hook)供你修改。

6. 实战技巧与常见问题排查

掌握了API,不等于能写出高效稳定的代码。下面分享一些从实际项目中总结的经验。

6.1 性能优化清单

  1. 减少重绘区域:不要动不动就GUI_Clear()全屏刷新。使用WM,并利用GUI_GetClientRect()GUI_SetClipRect()将绘图限制在脏矩形(需要更新的区域)内。
  2. 善用内存设备(Memory Device):对于复杂的、静态的或频繁重绘的图形(如仪表盘背景),可以将其先绘制到一个离屏的内存设备(GUI_MEMDEV_Create())中,然后通过GUI_MEMDEV_CopyToLCD()一次性快速拷贝到屏幕。这相当于“缓存”了绘制结果,避免了重复的复杂计算。
  3. 位图优于矢量:对于复杂的、不变化的图形(如公司Logo、复杂按钮皮肤),将其转换为位图显示,远比用一系列GUI_DrawLineGUI_FillPolygon调用要快得多。
  4. 谨慎使用Alpha和复杂函数:如前所述,软件Alpha混合、GUI_FillPolygonGUI_DrawArc(涉及浮点)都是性能杀手。评估需求,必要时寻找替代方案(如用预混合好的半透明位图代替实时Alpha计算)。
  5. 选择高效的色彩深度:在满足视觉需求的前提下,为你的项目配置最低的色彩深度(如GUI_565而不是GUI_8888)。这不仅能减少显存占用,还能大幅提升所有绘图函数的速度,因为需要处理的数据量变少了。

6.2 常见问题与解决方案速查表

问题现象可能原因排查步骤与解决方案
屏幕一片空白或花屏1. LCD驱动未正确初始化或时序错误。
2. emWin初始化 (GUI_Init()) 失败或在此之前调用了绘图API。
3. 堆栈大小不足,导致初始化崩溃。
1. 先单独测试LCD驱动,确保能画点画线。
2. 检查GUI_Init()返回值,确保在它之后绘图。
3. 增大启动文件或链接脚本中的堆栈大小。
绘图位置错误或偏移1. 坐标计算错误。
2. 未考虑窗口管理器(WM)的客户区偏移。
3. 画笔位置 (GUI_MoveTo) 未重置。
1. 使用GUI_DispDecAt()在关键位置打印坐标值调试。
2. 在WM回调中绘图,使用GUI_GetClientRect()获取基准。
3. 在开始一系列GUI_DrawLineTo前,务必调用GUI_MoveTo设置起点。
位图显示为乱码或错色1. 位图数据格式与当前LCD配置的色彩深度不匹配。
2. 位图转换器设置错误(如Endianness)。
3. 流式位图的GetData回调函数实现有误,返回了错误的数据或长度。
1. 确认GUIConf.h中的GUI_NUM_LAYERSGUI_NUM_COLORS配置,并与位图转换器输出格式一致。
2. 检查转换器中的“像素顺序”、“扫描方向”是否与LCD驱动匹配。
3. 在GetData函数中添加调试输出,确认偏移和读取长度是否正确。
使用XOR模式无效果或异常1. 当前色彩深度不是1位或2位(黑白或4级灰度)。
2. 画笔大小 (GUI_PenSize) 大于1。
3. 在绘制位图(颜色深度>1bpp)时使用。
1. XOR模式在真彩模式下行为不确定,尽量避免在彩色界面使用。
2. 使用XOR模式前,强制设置GUI_SetPenSize(1)
3. XOR模式对位图绘制无效,这是设计如此。
启用Alpha混合后显示异常1. 颜色值未正确包含Alpha通道(未左移24位)。
2. 硬件支持Alpha但驱动层颜色转换错误。
3. 绘制顺序错误,导致混合结果不符合预期。
1. 检查设置颜色的代码:GUI_SetColor((alpha << 24) | RGB_VALUE);
2. 如果使用硬件Alpha,仔细检查LCD_COLOR宏的实现,确保ARGB格式匹配硬件。
3. 牢记“从后往前”画:先画背景,再画半透明前景。
流式位图显示很慢1. 存储介质读取速度慢(如SPI Flash未使用Quad模式)。
2.GetData回调函数每次读取数据块太小,导致频繁调用。
3. 使用了压缩格式(如RLE),解码消耗CPU。
1. 优化底层读写函数,使用DMA或更大的缓冲区。
2. 在GetData中尽量一次读取多行数据(但不要超过提供的缓冲区)。
3. 对于性能敏感的图片,考虑使用未压缩的格式,或用内存设备缓存解码后的结果。

6.3 内存设备(Memory Device)进阶用法

内存设备是emWin中应对闪烁和提升复杂图形绘制速度的终极武器。其原理是开辟一块和显示区域一样大的内存缓冲区,先在这块“画布”上完成所有复杂的、耗时的绘制操作,最后一次性将整块内存拷贝到实际显存中。

// 创建并激活一个内存设备 GUI_MEMDEV_Handle hMem = GUI_MEMDEV_Create(0, 0, 320, 240); // 创建320x240的内存设备 GUI_MEMDEV_Select(hMem); // 后续所有绘图操作都指向这个内存设备 // 在内存设备上执行复杂绘制 GUI_SetBkColor(GUI_BLUE); GUI_Clear(); GUI_SetColor(GUI_YELLOW); GUI_FillCircle(160, 120, 50); // ... 更多复杂操作 ... GUI_MEMDEV_Select(0); // 切换回实际LCD // 将内存设备内容拷贝到LCD的指定位置 GUI_MEMDEV_CopyToLCD(hMem); // 拷贝到(0,0) // 或者 GUI_MEMDEV_CopyToLCDAt(hMem, x, y); // 拷贝到指定位置 // 不再需要时删除,释放内存 GUI_MEMDEV_Delete(hMem);

使用场景

  • 复杂仪表盘:将表盘、刻度线等静态背景绘制到内存设备,每次只更新指针。
  • 地图或图纸浏览:将整个地图绘制到内存设备,通过拷贝不同区域来实现平滑滚动。
  • 动画:预先将动画的每一帧渲染到多个内存设备中,播放时直接拷贝,极其流畅。

代价:内存设备会消耗一块和其尺寸、色彩深度成正比的内存。在资源紧张的设备上,需要权衡使用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询