自已实现一个UI库
[2014年写一个UI库时写的几个文章,公布出来]
几年前的一个嵌入式的UI开发,使自己有机会接触到了UI的一些底层知识,尽管之前也开发过非常多Windows下的信息应用系统,也做非常多的界面开发,但一直却对UI的一些运作却不了解。
BOSS决定使用UCGUI做为UI的基本库来开发UI界面的一些应用。用UCGUI的库来做开发。它已经有非常完好的基本构件,像窗口的管理,主要的控件,图片,文字处理等。只是听说UCGUI的授权费用也是不菲的。但我觉得它确实是一个物有所值的东西。
在使用中也还是遇到过一些问题,但这些基本都不会有什么大的影响,基本的是有源码,有一些小的BUG。也能够自己处理。满足不了的控件能够自己开发,也能够非常方便的在他的控件基础上做一些扩展。
使用它避免不了要去读了解它的一些底层代码,这样自己有机会对UI的动作有了一些主要的了解。近期也做些UI的事。想起UCGUI的代码架构还是值得学习的,所以自己从UI的基本原理上再次学习了一次,自己也花时间动手做了一些主要的代码实现。非常多基本原理都是从UCGUI上学习来的。再把这些主要的东西记下来,方便后来的学习者。
怎样自己动手写一个UI?在我自己没接触底层UI前,一直没想过,也认为它是一件比較复杂和难的事情。
它有多难?如今我认为假设会一门编程语言就能够写一个UI出来。这种基础就够了,我想能够试一试。
从画一个点開始
“像素”这个词我们一定已经非常熟悉了。如今买手机时大家非常观注的一个參数就是摄像头的成像像素是多少,由于图像的质量非常大成度就是它决定的。一个像素代表一个点。相同在显示器上也是一样,我们说的分辨率就是长宽多少个像素,在一个屏幕上显示有文字,有窗口。有图片及各种形状等等!看起来这是一个挺复杂的东西,但它却是由一个一个的点构成的。一个点代表一个像素,而这个点不同的像素值就代表不同的颜色。一个像素能够用8位,16位,32位来表示,位数越多。表示它能表示的颜色就越多显示的色彩也就越丰富了。
一个屏幕像是这种:
我们以左上角为原点,做一个坐标系。分别有X,Y方向。
像我如今的电脑的分辨率是1440x900,这样 X 最大取值是1440,Y最大取值是900。
假设我们要在一个屏幕上画一个点,给定一个点如:(500,500),仅仅要在坐标系里找到对应的位置就能够写一个像素值进去。屏幕就会显示出一个颜色点。
显示器有一个显存。要在屏幕上画出点,也就须要在对应的显存位置写入颜色值。显存又会映射到内存的一块连续的区域。这样我们仅仅要把值写入内存的区域。系统又会作I/O读写把更新显存的值。所心我们仅仅要关心写的内存的区域就好了。
操作显存
在Linux里有一个叫framebuffer的概念。叫“帧缓存”,事实上就是对显存当前值的缓存,Linux系统的显卡驱动都有实现,我们对framebuffer的读写就是对显存的读写。
在Linux里/dev文件夹里,应都有一个类似fbx(x表示一个数字)设备文件。打开它,再用mmap函数把framebuffer内存映射进我们的进程里就可认方便的对显示器操作了,这样我们能够画点,画线显示在显示器上面。
如以下的代码操作,打开fb0,并读取设置对应的參数:
static struct fb_var_screeninfo stVarInfo;
static struct fb_fix_screeninfo stfixInfo;
static unsigned char *pFrameBuffer = NULL;
char *file_name = "/dev/fb0";
int fbDev, s32Ret;
fbDev = open(file_name,O_RDWR,0);
if(fbDev < 0)
{
printf("open framebuff failed!\n");
return;
}
stVarInfo.bits_per_pixel = 16;
stVarInfo.activate = FB_ACTIVATE_NOW;
stVarInfo.xres = stVarInfo.xres_virtual = 1440;
stVarInfo.yres = stVarInfo.yres_virtual = 900;
s32Ret = ioctl(fbDev, FBIOPUT_VSCREENINFO, &stVarInfo);
if(s32Ret < 0)
{
printf("PUT_VSCREENINFO failed!%x\n",s32Ret);
return ;
}
if (ioctl(fbDev, FBIOGET_FSCREENINFO, &stfixInfo) < 0)
{
printf("Get fix screen info failed!\n");
return ;
}
pFrameBuffer = mmap(HI_NULL, stfixInfo.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fbDev, 0);
memset(pFrameBuffer,0x00,stfixInfo.smem_len);
在上面的代码中打开一个framebuffer,设置读取显示器的信息当中两个比較重要的结构:fb_var_screeninfo和fb_fix_screeninfo 。详细的能够搜索了解一下。
在mmap时,stfixInfo.smem_len就是显存在内存区域的大小。 memset的操作效果就是我们把显示器设成全黑色了,由于我们写入的每个点的像素值都是0x0。
在一个指定的点画点
显存的地址空间是一个线性的一维地址空间,我们的屏幕像上面的坐标系,是一个二维的了。给定一个点(x,y),这样我们就须要把它转换成对应的内存所在的地址。当知道一个屏幕的分辨率了,如1440 * 900,如今通过FBIOGET_FSCREENINFO知道了一些主要的信息,通过mmap知道了首地址。一个像素能够用8位。或16位,或32位,或很多其它的位表示。如我的板上的系统是16位,我用的LINUX系统是用32位的。以我板上的为例,用16位来表示一个像素点。也就是2个字节表示一个像素点。
那么屏幕上的点是这样确定的,想像你拿支笔从第一行画点,但把第一行画满后。再从第二行開始,持续的把整个屏画满,在屏上画点也是这样,假如是16位2个字节表示一个像素,分辨率是1400*900。所以给定的点(x,y)的地址为:
x * 2 + y * (1440 * 2),
假设用上一步代码里得到的信息来表示就是:
(x + stVarInfo.xoffset) * (stVarInfo.bits_per_pixel >> 3) + (y + stVarInfo.yoffset) * stfixInfo.line_length;
Xoffset,yoffset表示是否相对原点的偏移,bit_per_pixel表示一个像素用多少位表示。line_length表示一行占用多少字节。
画一个点(x,y)的地址确定了,这样写入一个值,对应的位置显示对应的颜色。
那么对应的画点函数例如以下:
void UI_SetPointPixel(int x, int y, int pixelValue)
{
int location = 0;
location = (x + stVarInfo.xoffset) * (stVarInfo.bits_per_pixel >> 3) + (y + stVarInfo.yoffset) * stfixInfo.line_length;
*(short *)(pFrameBuffer + location) = (short)pixelValue;
}
应为是16位的。所以注意上面的转换 (short *).
获取一个点的颜色
相同有时操作须要得到一个点的颜色,依据上面画点的函数。能够例如以下写出获取点的函数:
unsigned int fb_GetPointPixel(int x, int y)
{
int location = 0;
location = (x + stVarInfo.xoffset) * (stVarInfo.bits_per_pixel >> 3) + (y + stVarInfo.yoffset) * stfixInfo.line_length;
int PixelIndex = *(short*)(pShowScreen + location);
return PixelIndex;
}
主要的UI底层操作
我们工作用的操作UI上,有窗口。图片,视频等等,非常多东西,看起来非常复杂。但这种复杂北后,却是主要的像素点组成的,但再复杂的实现。都是在上面的画点函数。为基础的。为了方便我们开法。于是扩展了上面的画点函数,有画线段。矩形,圆等等。为了方便后面画更复杂的。我们实现画线和填充矩形函数:
void fb_DrawHLine(int x0, int y0, int x1)
{
U16 PixelColor = UI_GetDrawPixeColor();
for(; x0 <= x1; x0++)
{
UI_SetPointPixel(x0, y0, PixelColor);
}
}
void fb_DrawVLine(int x0, int y0, int y1)
{
U16 PixelColor = UI_GetDrawPixeColor();
for(; y0 <= y1; y0++)
{
UI_SetPointPixel(x0, y0, PixelColor);
}
}
void fb_DrawFillRect(int x0, int y0, int x1, int y1)
{
for(; y0<=y1; y0++)
{
UI_DrawHLine(x0, y0, x1);
}
}
分别实现画水平,垂直线。画填充的矩形。上面的 UI_GetDrawPixeColor 函数得到当前画点线的填充颜色值。
这样我们就有了主要的操作UI的工具了。
我们如今用上面的函数就能够画点,线。矩形,还是非常easy的。
2014-11-15
自已实现一个UI库的更多相关文章
- avalon新一代UI库发布
任何前端框架,尤其是国内的,想推广开,必须有一个UI库,光是一个核心库当光头司令是不行的.此外还有一个小圈子,供大家遇到问题时可以发问,一起完善.自从avalon嫁入"去哪儿网"后 ...
- 腾讯出品的一个超棒的 Android UI 库
腾讯出品的一个超棒的 Android UI 库 相信做 Android 久了大家都会有种体会,那就是 Android 开发相对于前端开发来说统一的 UI 开源库比较少.造成这种现象的原因一方面是大多数 ...
- ZanUI-WeApp -- 一个颜值高、好用、易扩展的微信小程序 UI 库
ZanUI-WeApp -- 一个颜值高.好用.易扩展的微信小程序 UI 库:https://cnodejs.org/topic/589d625a5c8036f7019e7a4a 微信小程序之官方UI ...
- 新建一个UI窗口-XproerUI(MFC)教程
版权所有 2009-2015 荆门泽优软件有限公司 保留所有权利 产品首页:http://www.ncmem.com/apps/xproerui/index.asp 在线文档(XproerUI):Xp ...
- Riot - 比 Facebook React 更轻量的 UI 库
Riot 是一个类似 Facebook React 的用户界面库,只有3.5KB,非常轻量.支持IE8+浏览器的自定义标签,虚拟 DOM,语法简洁.Riot 给前端开发人员提供了除 React 和 P ...
- 免费的Android UI库及组件推荐
短短数年时间Android平台就已经形成了一个庞大而活跃的开发者社区.许多社区开发的项目业已进入成熟阶段,甚至可以用于商业的软件生产中,且不用担心质量问题. 本文编译自androiduipattern ...
- [转] 国内外最全面和主流的JS框架与WEB UI库(强烈推荐)
国内外最全面和主流的JS框架与WEB UI库... 当下对于网站前段开发人员来说,很少有人不使用一些JS框架或者WEB UI库,因此这些可以有效提高网站前段开发速度,并且能够统一开发环境,对于不同 ...
- 重大发现: windows下C++ UI库 UI神器-SOUI(转载)
转载:http://www.cnblogs.com/setoutsoft/p/4996870.html 在Windows平台上开发客户端产品是一个非常痛苦的过程,特别是还要用C++的时候.尽管很多语言 ...
- 移动端和web端前端UI库—Frozen UI、WeUI、SUI Mobile
web http://www.pintuer.com/ 拼图 http://www.h-ui.net/ http://www.layui.com/ 很厉害的一个个人产品 http://amazeui ...
随机推荐
- myslq 5.7 root 默认密码
sudo sumysqld_safe --skip-grant-tables --skip-networking & UPDATE mysql.user SET password=PASSWO ...
- android 开源
http://blog.csdn.net/xiaoxiao_job/article/details/45196119?ref=myread MPAndroidChart https://github. ...
- codeforces_1066_B.Heaters
题意:一个数组只含有0或1,1表示该元素可以覆盖其自身.左边r-1个元素和右边r-1个元素,问最少保留多少个1元素可以覆盖整个数组. 思路:一个指针指向当前未被覆盖的最左边的元素下标,每次找离它最远且 ...
- 01C#程序结构及编辑编译环境
C#程序结构及编辑编译环境 程序结构 C# 中的组织结构的关键概念是程序 (program).命名空间 (namespace).类型 (type).成员 (member) 和程序集 (assembly ...
- No-4.变量的基本使用
变量的基本使用 程序就是用来处理数据的,而变量就是用来存储数据的 目标 变量定义 变量的类型 变量的命名 01. 变量定义 在 Python 中,每个变量 在使用前都必须赋值,变量 赋值以后 该变量 ...
- css一个div设置多个背景图片
html:定义一个div <div class="item__content"></div> css:样式 .item__content { positio ...
- CentOS7-Git安装以及使用
2018-09-14 Git安装 在bash终端中输入命令sudo yum install git回车. (出乎意料的顺利) 在随后出现的交互式对话中输入y即可. 随后,当任务执行完后,在bash中键 ...
- yum 软件管理器
yum软件管理器 yum是一个强大的软件包管理器,能够自动解决安装时rpm包之间的依赖关系. 一.使用yum管理软件包 1.使用命令 yum help 查看使用方法 [root@majinhai ~] ...
- JavaScript中数据类型的转换规则
JavaScript中数据类型的转换规则 制作人:全心全意 JavaScript是一种无类型语言,也就是说,在声明变量时无须指定数据类型,这使得JavaScript更具有灵活性和简单性. 在代码执行过 ...
- xcap发包工具的简单使用1(构造报文)
xcap是一个免费的网络发包工具,可以构造和发送常用的网络报文,如arp,ip,icmp,udp等,支持构造报文和发送报文等. 报文隶属于报文组,每个报文组包含多个报文,因此,创建报文首先要创建报文组 ...