1 引言

  我们在本系列主题五中曾经详细描述了在 MiniGUI 1.1.0 版本开发过程中添加的新 GDI 功能和函数。这些接口首次出现在版本 1.1.0Pre4 当中。目前 MiniGUI 1.1.0Pre7 版本已经发布,该版本中的新 GDI 接口趋于稳定,相对 1.1.0Pre4 版本而言,又新增了若干高级图形接口。这些接口涉及到直线和曲线生成器、复杂曲线的绘制、封闭曲线填充、复杂区域的创建、直接的显示缓冲区访问、YUV 覆盖和 Gamma 校正等等。本文将就这些主题详细描述各个接口的用法。

  2 曲线和填充生成器

  在一般的图形系统中,通常给用户提供若干用于进行直线或者复杂曲线,比如圆弧、椭圆和样条曲线的绘图函数。用户可以通过这些函数进行绘图,但不能利用这些系统中已有的曲线生成算法完成其他的工作。在 MiniGUI 新的 GDI 接口设计当中,我们采用了一种特殊的设计方法来实现曲线和封闭曲线的填充,这种方法非常灵活,而且给用户提供了直接使用系统内部算法的机会:

  1)系统中定义了若干用来生成直线和曲线的函数,我们称之为"曲线生成器";

  2)用户在调用生成器之前,需要定义一个回调函数,并将函数地址传递给曲线生成器,曲线生成器在生成了一个曲线上的点或者封闭曲线中的一条水平填充线时,将调用这个回调函数。

  3)用户可以在回调函数当中完成针对新的点或者新的水平填充线的操作。对 MiniGUI 绘图函数来说,就是完成绘图工作。

  4)因为回调函数在生成器的运行过程中不断调用,为了保持一致的上下文环境,系统允许用户在调?们呱善魇贝菀桓霰硎旧舷挛牡闹刚耄善鹘迅弥刚氪莞氐骱?

  下面将分小节讲述目前的 MiniGUI 版本所提供的曲线和填充生成器。

  2.1 直线剪切器和直线生成器

  直线剪切器和生成器的原型如下:

  

  BOOL GUIAPI LineClipper (const RECT* cliprc, int *_x0, int *_y0, int *_x1, int *_y1);

  

  typedef void (* CB_LINE) (void* context, int stepx, int stepy);

  void GUIAPI LineGenerator (void* context, int x1, int y1, int x2, int y2, CB_LINE cb);

  直线剪切器并不是生成器,它用于对给定的直线进行剪切操作。cliprc 是给定的直线,而 _x0、_y0、_x1 和 _y1 传递要剪切的直线起始端点,并通过这些指针返回剪切之后的直线起始端点。MiniGUI 内部使用了 Cohen-Sutherland 算法。

  LineGenerator 是采用 Breshenham 算法的生成器。该生成器从给定直线的起始端点开始,每生成一个点调用一次 cb 回调函数,并传递上下文 context、以及新的点相对于上一个点的步进值或者差量。比如,传递 stepx =1,stepy = 0 表示新的点比上一个点在 X 轴上前进一步,而在 Y 轴上保持不变。回调函数可以在步进值基础上实现某种程度上的优化。

  2.2 圆生成器

  MiniGUI 定义的圆生成器原型如下:

  

  typedef void (* CB_CIRCLE) (void* context, int x1, int x2, int y);

  void GUIAPI CircleGenerator (void* context, int sx, int sy, int r, CB_CIRCLE cb);

  首先要指定圆心坐标以及半径,并传递上下文信息以及回调函数,每生成一个点,生成器将调用一次 cb 回调函数,并传递三个值:x1、x2 和 y。这三个值实际表示了圆上的两个点:(x1, y) 和 (x2, y)。因为圆的对称性,生成器只要计算圆上的四分之一圆弧点即可得出圆上所有的点。

  2.3 椭圆生成器

  椭圆生成器和圆生成器类似,原型如下:

  

  typedef void (* CB_ELLIPSE) (void* context, int x1, int x2, int y);

  void GUIAPI EllipseGenerator (void* context, int sx, int sy, int rx, int ry, CB_ELLIPSE cb);

  首先要指定椭圆心坐标以及 X 轴和 Y 轴半径,并传递上下文信息以及回调函数,每生成一个点,生成器将调用一次 cb 回调函数,并传递三个值:x1、x2 和 y。这三个值实际表示了椭圆上的两个点:(x1, y) 和 (x2, y)。因为椭圆的对称性,生成器只要计算椭圆上的二分之一圆弧点即可得出椭圆上所有的点。

  2.4 圆弧生成器

  MiniGUI 定义的圆弧生成器如下所示:

  

  typedef void (* CB_ARC) (void* context, int x, int y);

  void GUIAPI ArcGenerator (void* context, int sx, int sy, int r, fixed ang1, fixed ang2, CB_ARC cb);

  首先要指定圆弧的圆心、半径、起始弧度和终止弧度。需要注意的是,起始弧度和终止弧度是采用定点数表示的,而不是浮点数,并且是弧度而不是角度。然后传递 cb 回调函数。每生成一个圆弧上的点,该函数将调用回调函数,并传递新点的坐标值 (x, y)。

  有关定点数的信息,请参阅本系列"主题六:MiniGUI 提供的非 GUI/GDI 接口"一文。

  2.5 垂直单调多边形生成器

  通常而言,多边形有凸多边形和凹多边形之分。这里的垂直单调多边形,是为了优化多边形填充算法而针对计算机图形特点而提出的一种特殊多边形,这种多边形的定义如下:

  垂直单调多边形是指,多边形的边和计算机屏幕上的所有水平扫描线,只能有一个或者两个交点,不会有更多交点。

  图 1 给出了凸多边形、凹多边形和垂直单调多边形的几个示例。

  

  需要注意的是,凸多边形一定是垂直单调多边形,但垂直单调多边形可以是凹多边形。显然,普通的多边形填充算法需要判断多边形边和每条屏幕扫描线之间的交点个数,而垂直单调多边形则可以免去这一判断,所以可以大大提高多边形填充的速度。

  MiniGUI 所定义的垂直单调多边形相关函数原型如下:

  

  BOOL GUIAPI PolygonIsMonotoneVertical (const POINT* pts, int vertices);

  

  typedef void (* CB_POLYGON) (void* context, int x1, int x2, int y);

  BOOL GUIAPI MonotoneVerticalPolygonGenerator (void* context, const POINT* pts, int vertices, CB_POLYGON cb);

  PolygonIsMonotoneVertical 用来判断给定的多边形是否是垂直单调多边形,而 MonotoneVerticalPolygonGenerator 函数是垂直多边形生成器。在 MiniGUI 当中,多边形是由组成多边形的顶点来表示的。pts 表示顶点数组,而 vertices 表示顶点个数。生成器生成的实际是填充多边形的每一条水平线,端点为 (x1, y) 和 (x2, y)。

  2.6 一般矩形生成器

  MiniGUI 还提供了一般的矩形生成器,该生成器可以处理凸多边形,也可以处理凹多边形。原型如下:

  

  typedef void (* CB_POLYGON) (void* context, int x1, int x2, int y);

  BOOL GUIAPI PolygonGenerator (void* context, const POINT* pts, int vertices, CB_POLYGON cb);

  和垂直单调多边形生成器一样,该函数生成的是填充多边形的每一条水平扫描线:x1 是水平线的起始X坐标;x2 是水平线的终止 X 坐标;y 是水平线的 Y 坐标值。

  2.7 填注生成器

  填注(flood filling)生成器比较复杂。这个函数在 MiniGUI 内部用于 FloodFill 函数。我们知道,FloodFill 函数从给定的起始位置开始,以给定的颜色向四面八方填充某个区域(像水一样蔓延,因此叫 Flood Filling),一直到遇到与给定起始位置的象素值不同的点为止。因此,在这一过程中,我们需要两个回调函数,一个回调函数用来判断蔓延过程中遇到的点的象素值是否和起始点相同,另外一个回调函数用来生成填充该区域的水平扫描线。在进行绘图时,该函数比较的是象素值,但实际上,该函数也可以比较任何其他值,从而完成特有的蔓延动作。这就是将填注生成器单独出来的初衷。MiniGUI 如下定义填注生成器:

  

  typedef BOOL (* CB_EQUAL_PIXEL) (void* context, int x, int y);

  typedef void (* CB_FLOOD_FILL) (void* context, int x1, int x2, int y);

  BOOL GUIAPI FloodFillGenerator (void* context, const RECT* src_rc, int x, int y,

  CB_EQUAL_PIXEL cb_equal_pixel, CB_FLOOD_FILL cb_flood_fill);

  cb_equal_pixel 被调用,以便判断目标点的象素值是否和起始点一样,起始点的象素值可以通过 context 来传递。cb_flood_fill 函数用来填充一条扫描线,传递的是水平扫描线的端点,即(x1, y) 和 (x2, y)。

  2.8 曲线和填充生成器的用法

  曲线和填充生成器的用法非常简单。为了对曲线和填充生成器有个更好的了解,我们首先看 MiniGUI 内部是如何使用曲线和填充生成器的。

  下面的程序段来自 MiniGUI 的 FloodFill 函数(src/newgdi/flood.c):

  static void _flood_fill_draw_hline (void* context, int x1, int x2, int y)

  {

  PDC pdc = (PDC)context;

  RECT rcOutput = {MIN (x1, x2), y, MAX (x1, x2) + 1, y + 1};

  ENTER_DRAWING (pdc, rcOutput);

基于Linux和MiniGUI的嵌入式系统软件开发指南(七)相关推荐

  1. 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(一)(转)

    自 MiniGUI 从 1998 年底推出以来,越来越多的人开始选择 MiniGUI 在 Linux 上开发实时嵌入式系统.为了帮助嵌入式软件开发人员使用 MiniGUI编写出更好的应用程序,我们将撰 ...

  2. 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南题八——MiniGUI 和其他嵌入式 Linux 上的图形及图形用户界面系统

    简介: 为了让读者对嵌入式 Linux 当中能够使用的图形及图形用户界面有个较为全面的认识,本文将为读者介绍一些嵌入式 Linux 系统中常见的图形及图形用户界面系统,并作为<基于 Linux ...

  3. 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南

    内容: 1 Linux 图形领域的基础设施 2 Linux 图形领域的高级函数库 3 面向嵌入式Linux 系统的图形用户界面 4 小结 关于作者 相关内容: 主题一:选择MiniGUI-Thread ...

  4. 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(八)

    基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(八) MiniGUI 和其他嵌入式 Linux 上的图形及图形用户界面系统 魏永明 (ymwei@minigui.org) 自由撰稿人 ...

  5. 10001.基于Linux和MiniGUI的嵌入式系统软件开发指南(转载)

    1 Linux 图形领域的基础设施 2 Linux 图形领域的高级函数库 3 面向嵌入式Linux 系统的图形用户界面 4 小结 关于作者 相关内容: 主题一:选择MiniGUI-Threads 或者 ...

  6. 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(六) MiniGUI 提供的非 GUI/GDI 接口...

    1 引言 一般而言,GUI 系统的应用程序编程接口主要集中于窗口.消息队列.图形设备等相关方面.但因为 GUI 系统在处理系统事件时通常会提供自己的机制,而这些机制往往会和操作系统本身提供的机制不相兼 ...

  7. 基于Linux和MiniGUI的嵌入式系统软件开发指南(五)

    MiniGUI 1.1.0 版本引入的新 GDI 功能和函数 本文向读者展现了 MiniGUI 的最新开发成果,即在 MiniGUI 1.1.0Pre4 版本中引入的新的 GAL 和新的 GDI 功能 ...

  8. 基于Linux和MiniGUI的嵌入式系统软件开发指南(六)

    本文讲述了 MiniGUI 为应用程序提供的非 GUI/GDI 接口,这些接口能够帮助应用程序更好地和操作系统交互,扩展应用程序功能,并提高应用程序的可移植性.内容主要涉及到如下几个方面:MiniGU ...

  9. 基于 Linux 和 MiniGUI 的嵌入式系统软件开发指南(三)

    1 引言 对话框编程是一个快速构建用户界面的技术.通常,我们编写简单的图形用户界面时,可以通过调用 CreateWindow 函数直接创建所有需要的子窗口,即控件.但在图形用户界面比较复杂的情况下,每 ...

最新文章

  1. 神器np.unique、np.argsort
  2. Docker-----仓库
  3. 日常工作问题解决:rhel7下配置多路径设备
  4. 不生成新数组的迭代器方法:forEach()every()some()reduce()reduceRight()
  5. wcf高并发 mysql_使用nginx搭建高可用,高并发的wcf集群
  6. [转]JS获取当前对象大小以及屏幕分辨率等
  7. 拆分文件_领导让把工作表拆分每个文件,我花半个小时,同事1分钟搞定了
  8. openCV中waitKey函数介绍
  9. vs工具箱里面没有工具怎么办_装机技巧系列(一):用U盘制作自己的PE工具箱...
  10. 吴恩达深度学习4.4练习_Convolutional Neural Networks_Face Recognition for the Happy House
  11. PHP设计模式——解释器模式
  12. 管理欲望:领导者的自我觉察与突破
  13. MATLAB虚数矩阵不可随意转置
  14. 英文歌曲:Yesterday Once More(昨日重现)
  15. 美国实用生活指南—综合篇
  16. 典型相关分析(Canonical Correlation Analysis, CCA)
  17. 在IDEA中写Python
  18. WAR3改键工具FinalKey beta 1.0制作完成
  19. STATA学习笔记:数据合并
  20. Ambari添加快速链接Quick Links

热门文章

  1. 重装系统计算机名称回对ug,电脑重装系统后UG软件没有卸载的情况下重新启动UG软件的方法...
  2. 证明人工智能的数据只要足够多,就可以接近理想效果
  3. RelativeLayout 常用属性
  4. tomcat运行指定JDK,不运行环境变量配置的JDK
  5. spring boot 中文文档地址
  6. 将m文件通过matlab 的编译器转换为可执行文件,【转】 Matlab中提高m文件执行效率的小技巧...
  7. 联想r720内存频率_联想小新Pro 14 2021怎么样 联想小新Pro 14 2021全面评测
  8. qc成果报告范例_株洲水务集团QC成果再获省一等奖
  9. 判断一棵树是否为完全二叉树的算法c语言_[二叉树的面试算法](六)之二叉树结构判断-相关题型总结(4题)...
  10. 哪吒汽车在售车型涨价3000-5000元