uCGUI字符串显示过程分析

GUI_DispString()函数源码                                          

 1 void GUI_DispString(const char GUI_UNI_PTR *s) {
 2   int xAdjust, yAdjust, xOrg;
 3   int FontSizeY;
 4   if (!s)
 5     return;
 6   GUI_LOCK();
 7   FontSizeY = GUI_GetFontDistY();         //获取字体的高度
 8   xOrg = GUI_Context.DispPosX;            //获取当前显示的x坐标
 9  /* Adjust vertical position */
10   yAdjust = GUI_GetYAdjust();
11   GUI_Context.DispPosY -= yAdjust;        //根据Y方向上的对齐方式对y进行调整
12   for (; *s; s++) {
13     GUI_RECT r;
14     int LineNumChars = GUI__GetLineNumChars(s, 0x7fff);           //当前一行要显示几个字符
15     int xLineSize    = GUI__GetLineDistX(s, LineNumChars);        //当前一行在x方向上的像素数
16   /* Check if x-position needs to be changed due to h-alignment */
17     switch (GUI_Context.TextAlign & GUI_TA_HORIZONTAL) {
18       case GUI_TA_CENTER: xAdjust = xLineSize / 2; break;
19       case GUI_TA_RIGHT:  xAdjust = xLineSize; break;
20       default:            xAdjust = 0;
21     }
22     /* 计算出每一行显示内容的矩形区域 */
23     r.x0 = GUI_Context.DispPosX -= xAdjust;          //根据水平方向的对齐方式对x坐标进行调整
24     r.x1 = r.x0 + xLineSize - 1;
25     r.y0 = GUI_Context.DispPosY;
26     r.y1 = r.y0 + FontSizeY - 1;
27
28     GUI__DispLine(s, LineNumChars, &r);              //以计算好的矩形区域显示当前行字符
29     GUI_Context.DispPosY = r.y0;
30     s += GUI_UC__NumChars2NumBytes(s, LineNumChars); //从第一个字符开始,地址加1,可以遍历整行字符串
31     if ((*s == ‘\n‘) || (*s == ‘\r‘)) {
32       switch (GUI_Context.TextAlign & GUI_TA_HORIZONTAL) {
33       case GUI_TA_CENTER:
34       case GUI_TA_RIGHT:
35         GUI_Context.DispPosX = xOrg;
36         break;
37       default:
38         GUI_Context.DispPosX = GUI_Context.LBorder;
39         break;
40       }
41       if (*s == ‘\n‘)
42         GUI_Context.DispPosY += FontSizeY;
43     } else {
44       GUI_Context.DispPosX = r.x0 + xLineSize;
45     }
46     if (*s == 0)    /* end of string (last line) reached ? */
47       break;
48   }
49   GUI_Context.DispPosY += yAdjust;                //
50   GUI_Context.TextAlign &= ~GUI_TA_HORIZONTAL;    //
51   GUI_UNLOCK();
52 }

字符串显示过程概括                                                

<1> 获取选择字体的高度、宽度

<2> 从所传字符串参数中,依次读出一行的字符数,最终得到一行显示所对应的矩形区域

<3> 将一行所得到的详细信息传给行显示函数,行显示函数会从字库中找到匹配的字依次将一行的字符进行显示,完成一行的显示

<4> 如果不是只有一行,重新计算下一行显示的坐标,重复<1、2、3>的工作,直到将字符串显示完毕。

============================================================================================

                   重要细节分析

============================================================================================

 1、GUI运行的全局变量                                             

  GUI_Context是GUI保存运行环境的全局变量,它的类型GUI_CONTEXT在GUI.h中被定义。

struct GUI_CONTEXT {
/* Variables in LCD module */
  LCD_COLORINDEX_UNION LCD;
  LCD_RECT       ClipRect;
  U8             DrawMode;
  U8             SelLayer;
  U8             TextStyle;
/* Variables in GL module */
  GUI_RECT* pClipRect_HL;                /* High level clip rectangle ... Speed optimization so drawing routines can optimize */
  U8        PenSize;
  U8        PenShape;
  U8        LineStyle;
  U8        FillStyle;
/* Variables in GUICHAR module */
  const GUI_FONT           GUI_UNI_PTR * pAFont;  //指向当前选择的字体
  #if GUI_SUPPORT_UNICODE
    const GUI_UC_ENC_APILIST * pUC_API;    /* Unicode encoding API */
  #endif
  I16P LBorder;
  I16P DispPosX, DispPosY;
  I16P DrawPosX, DrawPosY;
  I16P TextMode, TextAlign;                       //对齐方式
  GUI_COLOR Color, BkColor;           /* Required only when changing devices and for speed opt (caching) */
/* Variables in WM module */
  #if GUI_WINSUPPORT
    const GUI_RECT* WM__pUserClipRect;
    GUI_HWIN hAWin;
    int xOff, yOff;
  #endif
/* Variables in MEMDEV module (with memory devices only) */
  #if GUI_SUPPORT_DEVICES
    const tLCDDEV_APIList* pDeviceAPI;  /* function pointers only */
    GUI_HMEM    hDevData;
    GUI_RECT    ClipRectPrev;
  #endif
/* Variables in Anitaliasing module */
  #if GUI_SUPPORT_AA
    const tLCD_HL_APIList* pLCD_HL;     /* Required to reroute drawing (HLine & Pixel) to the AA module */
    U8 AA_Factor;
    U8 AA_HiResEnable;
  #endif
};

2、GUI_FONT的定义                                                 

一种字库想要被uCGUI所调用,需要将其定义成GUI_GONT类型的一个常量,当我们需要自己制作字库的时候,就需要这样做。GUI_FONT类型的定义在GUIType.h文件中。

struct GUI_FONT {
  GUI_DISPCHAR*     pfDispChar;             //显示一个属于当前字库字符的函数
  GUI_GETCHARDISTX* pfGetCharDistX;         //获取字库中某字符的宽度
  GUI_GETFONTINFO*  pfGetFontInfo;          //获取字库信息
  GUI_ISINFONT*     pfIsInFont;             //查询字库中是否存在此字符
  const tGUI_ENC_APIList* pafEncode;        //
  U8 YSize;                        //高度
  U8 YDist;                        //对应的像素点
  U8 XMag;                         //X方向上的放大系数
  U8 YMag;                         //Y方向上的放大系数
  union {                          //此共用体主要是提供字库数据的访问地址,
                                   //对于不同的字库,其从字库中查找字模的方法,是不一样的
                                   //这里主要分成三种情况,对应三种类型的指针
    const void          GUI_UNI_PTR * pFontData;
    const GUI_FONT_MONO GUI_UNI_PTR * pMono;
    const GUI_FONT_PROP GUI_UNI_PTR * pProp;
  } p;
  U8 Baseline;                                //
  U8 LHeight;     /* height of a small lower case character (a,x) */    //小写高度
  U8 CHeight;     /* height of a small upper case character (A,X) */    //大写高度
};

(1)

时间: 2024-10-05 14:48:35

uCGUI字符串显示过程分析的相关文章

STM32移植uCGUI+触摸屏显示,没有加入uCOS Ⅱ

实验板子 ——李想STM32开发板 开发工具—— keil uVision5.0 for MDK 本次终极任务为显示示波器的GUI界面,此文章只是简单总结移植uCGUI+触摸屏,之后会加入视窗管理器及uCOSⅡ. 下面说说移植步骤,会穿插一些个人简单的理解,为像我一样的新手提供方便. 步骤分为三大步: 一.移植uCGUI 二.显示汉字 三.移植触摸屏 一.移植uCGUI 1.建立工程模版. 个人会先建立一个工程模板,里边只包含系统的一些文件,主函数是while(1);的循环.每次项目用到就直接复

解决CsvWriter:中文乱码、末尾行多一行空格(/r)、非第一列空字符串&quot;&quot;显示null问题

一:主要内容 解决CsvWriter存csv,csv文件打开后中文乱码问题 解决CsvWriter存csv,csv文件最后一行总是多一行空行的问题 解决CsvWriter存csv,csv文件不是第一列的时候,想存入""即空字符串无法存入显示null的问题 二:解决问题前:需要做的事情 因为网上的CsvWrite的jar包导入到我们的工程中是class文件,针对上面的问题是无法修改源码的,但是我们又想用这个工具来操作csv,所以可以在自己的工程中首先pom引用这个jar包 <dep

emWin(ucGui)数值显示例程 -【worldsing笔记】

本例程下载:2.emWin5.26(ucGui)VS2008数字显示.zip ? 在emWin显示文本字符还是容易,我们也可以使用字符串和标准 C 库的函数来显示数值.然而,有时候这会是件困难的事.通常,较为容易(也更为有效)的是调用一个例程显示所需结 构的数值. emWin 支持各种十进制.十六进制和二进制输出.本章将对这些例程进行逐一描述.所有函数不需要使用浮点库,并对速度和大小进行了优化.当然"Sprintf"可以用于任何系统.使 用本章介绍的例程,有时可以简化操作,节省 ROM

windows客户端开发--如何测量一个字符串显示的物理长度

首先需要说明的是,我所说的字符串的长度,不是string的length,也不是string的size.我指的是显示的长度,即物理长度. 缘由: 之所以要提到这个,是因为遇到了一些问题. 再使用duilib进行开发时,发现label控件不能自适应宽度. 思考: 这显示是这个库的一个不足,但是我们可以试图去修改一下这个库.但是本着开源的精神,或许这个库的设计初衷就是label不能自适应字符串的宽度呢? 所有只有走第二条路,我们首先获得要显示字符串的宽度width值,然后把这个label的宽度设置为w

plsql developer 查询含有chr(0) 字符串显示不全问题

[问题现象] 接到维护组投诉工单,用户上行短信到10086短信办理业务失败,结果查询数据显示为空. 正常情况下系统会将空短信过滤掉,此次该用户的上行短信已经进入业务引擎入库. 维护用plsql developer查看短信字段显示空白,点击详细也是没有内容可复制. 但是在用户受理详情查询可看到用户上行内容. [初步判断] 用户上行肯定有内容,上行短信估计编码有问题,数据库显示不出. [处理] 使用length查看字段长度,大于0,确定有内容.百度varchar2 内容不显示. 发现plsql de

ASP.net:截取固定长度字符串显示在页面,多余部分显示为省略号

方法一: public static string GetString(string str, int length) { int i = 0, j = 0; foreach(char chr in str) { if((int)chr > 127) { i += 2; } else { i ++; } if (i > length) { str = str.Substring(0, j) + "..."; break; } j ++; } return str; } 方法

windowsclient开发--怎样測量一个字符串显示的物理长度

首先须要说明的是,我所说的字符串的长度,不是string的length,也不是string的size.我指的是显示的长度.即物理长度. 缘由: 之所以要提到这个.是由于遇到了一些问题. 再使用duilib进行开发时.发现label控件不能自适应宽度. 思考: 这显示是这个库的一个不足,可是我们能够试图去改动一下这个库. 可是本着开源的精神.也许这个库的设计初衷就是label不能自适应字符串的宽度呢? 全部仅仅有走第二条路,我们首先获得要显示字符串的宽度width值.然后把这个label的宽度设置

c#中字符串显示上标和下标解决办法

由于工作的需求,需要在word中插入带入带有上标和下标的字符串,比如这样的一个字符串:SO?²?(mg/L).在网上搜了好久,终是摸索出点思路. 解决办法:使用转义字符加Unicode的HexEntity就可以实现了.比如定义一个SO?²?(mg/L)这样的字符串如下:"SO\x2084\x00B2\x207B(mg/L)".其中x2084为 ?(注意:此处为4的下标) 的Unicode HexEntity,x00B2为 ²(注意:此处为2的上标) 的Unicode HexEntity

iOS_字符串显示不同颜色

最近写代码需要根据不同的内容显示不同的颜色.在这里mark一下. 设置颜色: NSString *contentStr = @"简介:hello world"; NSMutableAttributedString *str = [[NSMutableAttributedString alloc]initWithString:contentStr]; //设置:在0-3个单位长度内的内容显示成红色 [str addAttribute:NSForegroundColorAttributeN