LCUI 0.12.6 开发日志
2012年09月12日 · 28872 字 · 阅读
2012-9-12
打算将LCUI的widget属性命名方式,搞成html 的 CSS 标签属性那样,当然,这会应用在widget 的C++类上。
2012-9-13
为了完善按键输入,研究linux/input.h中的函数声明。
使用 cat /proc/bus/input/devices 可以看到每个eventX是什么设备的事件,电源键都有!
网上找了一下,没看到几个结果是说读按键输入,大多是模拟按键输入,写按键输入事件,于是,将“写数据”改成“读数据”,测试的设备是/dev/input/event3,结果无任何效果;加了printf函数打印信息后,有输出了,个人认为是输入缓冲的关系,改用fflush函数清空输入缓冲,结果正常。之后,又用了LCUI自带的Set_Raw函数设置终端为无缓冲模式,fflush函数就不要了,再次测试,结果正常。
效果比较满意,但放到学习机上测试时,发现学习机用的是/dev/input/event0,这没什么大碍,可是,无法判断某个为“按住”状态,只有“按下”和“释放”,按住某个键时,结果表明,程序把“按住”状态识别成了“按下”和“释放”这两个状态。
2012-9-14
文本框设计方案: 文本框要支持不同大小、不同字体、不同颜色的文字显示。 用一个结构体保存字符码以及指向该字符属性的指针。 字符属性包括:颜色、背景色、字体类型、字体大小、粗体、斜体、下划线。
考虑到代码编辑器会用到文本框,那么,文本框要有一个记录能够保存哪些字符串要使用什么颜色、什么字体、什么背景色等数据。 是否自动换行。 用一个结构体记录光标的相对位置、在字符串中的位置、长度、闪烁频率,增删文字时,以光标位置为基础,对该位置的字符进行增删,之后会自动调整光标位置。 文本框能够响应鼠标事件。
需要记录每一行文字的高度, 因为这一行的文字的大小可能不统一。
2012-9-15
感觉文本框用链表式队列来储存源文本好一些,用数组式队列的话,只要增删一个字,都要要移动这个字后面的所有字。
正在实现TextBox部件的样式标签处理功能, 之前的Label部件,只支持<color>标签来设置文本颜色,而TextBox部件不只是支持这个标签,还有<size>, <family>, <style>, <weight>, <decoration>这5个标签,在TextBox部件完成后,Label部件可能需要进行一次改写。
2012-9-17
现在新增功能模块,大致流程就是这样: 先设计好数据结构,然后设计相关函数接口,最后就是写函数的实现,在写函数的实现时,有时灵感来了,就会新增几个函数接口,修改一下数据结构。
已经将开发中的TextBox部件的源代码上传至github.com, 可到这查看 。
2012-9-19
为队列添加链表式储存模式,可以在数组式和链表式这两种模式之间进行选择,各有各的特点。
代码添加完成,函数接口名没变,有的函数的参数就是多加了个const , 请看这里 ,还有BUG,等待修复。
2012-9-20
经过一番调试后,这次修改的队列处理已经能够正常工作了, 可看这里 。
调试的方法,主要是分析出错的函数,然后用修改前备份的函数代替它,测试如果没问题,那么就是这个函数有问题,然后将新函数与旧函数进行对比,看新函数哪里有问题,有则进行修正。最后也就是用测试程序测试队列的主要功能是否异常。
队列的数据删除函数出了点问题,需要进行修复。
已经进行修复 。只是修改了一下数据有效性检测,无效则退出函数,居然会出错,只好再改一下。
准备继续实现文本框。。。
又折腾了一下主页,项目主页在windows平台上,用IE9和Chrome浏览器浏览时,可以在音乐播放器中播放音乐,但改用FireFox 和 Opera浏览器后,只能看,不能用。。。
本来是怀疑我修改的网页代码的问题,又重新去audiojs官方网站下载audiojs,解压后用浏览器打开里面的index.html,结果,问题依旧,FireFox 和 Opera浏览器不能播放音乐;不知为什么,同样是一张网页,在它的官方网站上可以正常播放音乐,下载到本地的却不能,难道作者没有测试压缩包里面的文件?
IE浏览器和Chrome浏览器显示的效果不一样,比如音乐播放器:
font-family是monospace,Chrome里显示得很亮很细,而IE9里,有点暗且有点宽;标签的效果也有点差异,对于标号和条目间隔,IE9比Chrome更宽一些。之前再IE9里测试,进度条边上显示时间没有了,个人猜测是由于排版的问题,使用IE自带的工具查看元素,发现时间显示在下面去了,调整padding和margin后,终于显示出来了。
在测试网页效果的过程中,发现FireFox的“查看元素”功能的3D视图不错,可以看到各个区块的层叠顺序。
主页上的那个按钮,在webkit引擎的浏览器中显示的效果正常,其它浏览器中却不正常,如下图所示:
按钮使用了linear-gradient,也就是CSS3的线性渐变效果,发现这属性不在所有浏览器中通用,Opera里要用-o-linear-gradient,FireFox里用-moz-linear-gradient,Chrome里用-webkit-linear-gradient,IE不支持,需要用其它方法,不只是这一个,比如transition,它用于实现过渡效果,div的移动就是用它实现的。
进了兔斯基的网站,然后,又修改了一下自己的项目主页。。。
2012-9-21
修改中文文档的文件名为英文,包含汉字的文件名在打包压缩后,在其它平台上解压会出现乱码,比如在linux下打包压缩,在windows下解压,中文名乱码,同样,在windows下打包压缩,在linux下解压也会出现这问题。
对于文本框,貌似需要用一个库,记录字体文件句柄与字体族名,使用<family>标签指定文本框中某段文本的字体族时,就根据这个字体族名在库中查找与之对应的字体文件句柄,找到后,就使用这个句柄,获取字形。
2012-9-22
测试文本框时,发现队列处理上出了毛病,数据存入队列后,再取出来,内容一样,经过调试后发现,本来是用memcpy( p->data, data, queue->element_size ); 我却写成了:memcpy( p->data, data, sizeof(queue->element_size) ); ,怪不得数据前半部分一样,后半部分异常。
看样子,代码还是需要进行一次规范化,等以后有时间再说。
文本框的绘制功能已经完成,中途发现图形处理方面的小BUG,对图形进行“写”操作前,没有使用“写”锁锁定数据,操作后没有进行解锁,也无法更新图形相关属性,导致图形处理时进行了错误的判断,最终使绘制的文本框无法显示, 点击这里可查看被改动的代码 。
以下是文本框的截图:
只实现了文本位图的绘制,文本输入、自动换行、光标、滚动条等还未添加,但测试时发现了一些问题:
按钮本该整体刷新的,结果没刷新,只是在鼠标移动时刷新了鼠标范围内的图形。
字数异常,连标题栏上的字都出问题了。
个人猜测是实现文本框的代码中有数据访问越界,使LCUI其它的功能发生异常,之前在测试PictureBox部件时出现过类似问题。
经过测试,发现把TextBox_Get_Char_Bitmap ( &char_data );这行注释掉后,没有上述问题,往复运行多次测试程序,无异常,需要看看字体位图的获取上有什么问题。
2012-9-23
折腾了一天,为了移植些软件到目标设备中,configure运行到最后,正要创建config.h文件,却出现以下信息:
config.status: creating config.h config.status: config.h is unchanged
libtool,libiconv,libjpeg这三个的源代码也是这样,搞得在编译时因找不到config.h文件而报错; 直接手动创建config.h文件话,对于libjpeg还可以,但对于其它的就不行了,config.h中没有定义相应宏,源文件中又用到了这些宏。
还好我的lcui不需要config.h,补全了依赖库后顺利安装。
在我修改config.status里的代码后,才能正常生成config.h。
由于目标设备的root分区可用空间少,只有几百MB,剩余空间不足10MB,于是我创建了个root.ext2文件,512MB大小,格式化成ext2,然后挂载了它; 在里面创建了usr文件夹,把同架构的另一个设备(学习机)里的include,share等文件夹复制到了usr文件夹里,usr/include等文件夹也挂载到了/usr/下。
编译freetype2时连configure都不能运行,直接报错说缺少Make程序或支持环境。
运行autogen.sh也出错,好像缺少了什么。
搞得最后交叉编译,由于依赖关系,去编译GNU Guile,而Guile依赖libgmp, libiconv, libintl,libltdl,libunistring,libgc,libffi,补充了些依赖软件后,configure还是不通过,于是就放弃了。
2012-9-24
在看了GNU主页上的一些文章后,就修改LCUI主页,添加些内容。
在设备上测试LCUI,显示器是16位,窗口移动后的残余区域图形显示异常,经分析发现是拷贝的屏幕图形数据有问题,屏幕是16位的,那么像素点的RGB色彩值就是以16位表示的,而LCUI却把16位当24位来处理,导致图形显示异常。
测试照片查看器,发现Load_Image()函数有问题。LCUI退出时出现段错误。
指针间相减,不需要再除以sizeof(指针类型),比如:
wchar_t src[10]=L”abcdeg”, *p, *q; p = src; q = &src[5];
q-p就等于5,也就是相差的元素个数,之前还一直以为是直接拿指针内的地址编号相减。
现在又纠结一个问题:
往文本框里添加一段文本:<color=255,0,0>红色文字</color>普通文字
然后呢,插入一段文本,变为:<color=255,0,0>红色文字 新增文字</color>普通文字
该如何处理呢?这彩色文字,目前的处理方式只是在添加它时处理新文本的字体样式,处理结果就是新增文字不会变成红色,如果是每次更新文本时统一处理这些文字的样式,虽然能达到效果,但是,如果有10000行以上的文字呢?那不就是每修改一个字都要遍历一次呢?字越多,耗时越长,会卡顿。
先暂时不考虑字体样式的处理,把基本功能完成后再考虑。
2012-9-26
在CSDN上看了某网友的文章,有这么一段话:“unix有三个基本思想:1.程序只做一件事情;2.程序之间能协同工作;3,程序处理文本流,因为它是一个通用的接口。”,再看看我之前写的代码,的确很乱,LCUI的源代码需要进行重新规划;
之前就想好了一些,LCUI的源码目录结构大致是这样的: / ../src/ ../…/bmp/ (图片文件的读取/写入) ../…/draw/ (图形绘制) ../…/font/ (字体处理) ../…/gui/ (一些现成的图形界面,例如MessageBox、颜色选择、字体选择等) ../…/input/ (处理输入设备输入的数据,例如鼠标、触屏、键盘等) ../…/loadso/ (动态库的操作) ../…/……/dlopen.c ../…/output/ (数据输出,一般是图形数据) ../…/……/framebuffer.c (通过帧缓冲显示图形) ../…/……/x11.c (通过X Window系统显示图形) ../…/thread/ (线程支持) ../…/……/pthread.c ../…/widget/ (GUI部件)
对于LCUI程序,如果在X11环境下运行,那么,就使用X11进行图形输出,也就是创建个窗口,把图形数据输出到窗口里; 如果是在字符控制台模式下运行,就直接使用FrameBuffer。 那么,LCUI程序如何知道自己是在哪种环境下运行呢?这个可以参考SDL的源代码。
widget的属性,参考html标签的css属性,添加padding,margin,position,x-index,display等属性,省得自己纠结属性的命名了,这些属性所产生的效果我也知道,就算不知道可以写代码用浏览器测试,所以实现起来不是很难。
2012-9-27
工作量比较大,需要分割源文件,整理源代码。先不对源代码进行修改,以免测试时出现问题。
2012-9-28
源代码分割已经基本完成,剩下的就是整理头文件,完善细节。
头文件已经整理完成,测试程序运行时还有异常,需要解决。
2012-9-30
解决了字体位图异常的问题 ,个人估计是用了FontBMP_Free()函数的缘故,把野指针释放了,结果获取字体位图时就出现问题了。修改代码后,多次测试,没异常。
需要整理一下思路,毕竟有一段时间没搞文本框了,现在不知从何开始。
<color>标签应该要支持#abc,#fb89cc等之类的色彩表示。
2012-10-1
正调整字体位图的处理功能。
2012-10-2
目前正在纠结FreeType2,又看了一下中译版的FreeType2文档,发现除了glyph->bitmap_top,还有个glyph->bitmap_left,怪不得中文的逗号和英文的逗号占的宽度都一样,原来是没有利用glyph->left的值来调整字形的距离。
2012-10-3
先暂时禁用Label部件的绘制功能,等TextBox部件的文本绘制功能完成后,再让Label部件使用TextBox的文本绘制功能。
文本框分成两个图层:背景 + 文本,这样,每次绘制文本时,就不必重绘背景了。
打算让LCUI能够在系统目录中扫描字体文件,比如Ubuntu,它的字体文件在/usr/share/fonts/ 目录下,那么,就遍历文件目录,找个合适的字体。
Label和TextBox部件都是显示文本的,只不过,后者可以编辑文本内容,考虑到windows上的Label控件内的文本可以选中和复制,那么就让Label和TextBox部件使用同一个文本位图处理模块。
2012-10-4
使用这段文本:<color=#FF0000>1<color=#0000FF>2</color>3</color>4
理论上 1 和 3会变成红色, 2 变成蓝色,而4是默认的黑色,测试结果只有1和2变了色,34是默认的黑色,看样子是处理</color>这标签是出了问题。
问题已解决,原因是这个函数:wchar_t *get_style_endtag ( wchar_t *str, char *out_tag_name ); 调用它后,没有判断返回值是否为NULL,直接用strcmp对比</color>和out_tag_name,而get_style_endtag在返回NULL前又没有清空字符out_tag_name的内容,out_tag_name内容无变化,导致误删标签数据。
接下来就是光标显示了,光标能够闪烁,貌似需要一个定时器,每隔M时间显示光标,每隔N时间隐藏光标;
光标定位是个问题。。。
将TextBox部件作为文本图层的容器,而文本图层就作为光标(一个widget)的容器。
那个文本图层该取什么名字呢?Text Surface?Text Layer?纠结中。。。
2012-10-5
文本框里的文本位图处理的代码划分至font目录里,这属于文字+字体位图处理。
正添加一些函数。
正在修改Label部件的源代码,原有的彩色文本绘制以及<color>标签处理的几百行代码就作废了,删除之。
2012-10-7
Label部件的源代码已经修改,原有的彩色文本渲染代码已经删除,改用新增的文本位图处理功能,该功能之前是写在TextBox部件的代码里的,后来分离出来了。
具体修改内容可 查看这里 。
在修改Label部件的源代码的过程中,也纠正了文本位图处理功能上的一些问题。
2012-10-8 至 2012-10-13
由于blog.lcui.org无法访问,没有该段时间记录的日志,只备份了10月7日的日志,还好之前sourceforge.net上还有我搭建的wordpress,FTP上传导入工具插件,启用插件后,在上面恢复了这个备份。
各种图片在本地上有备份,博客无法使用对我没多大的影响。
github上也建了个主页。
这段时间内只是研究了高斯模糊算法,这是处理前的图像:
sigma 设为 20,高斯模糊处理后:
Label部件 和 文本图层的处理做了修改,具体可到github上查看代码提交记录。
项目的构建脚本做了修改,./configure执行完后,会有检测结果,具体如下图所示:
2012-10-14
为了保险起见,已在项目主页上添加开发日志的静态html页面,主页也随之做了些修改。
项目主页的音乐播放器中的音乐列表做了修改。
2012-10-15
正准备添加滚动条。
文本图层的部分字体位图绘制不完全,少了一行像素,如下图所示,“/* 最经典的C语言代”这行文本位图少了一行像素。
2012-10-16
由于在绘制字体位图前,需要将能容纳该字体的最大区域的alpha通道填充为0,导致之前绘制的上一行文本位图的最后一行像素被填充掉了。该最大区域的尺寸,只是用当前 字体像素+2 得出的,是一个正方形。
修改一下,在文字改变或大小改变时,将当前文字所在区域添加至队列,等待将这些区域的alpha通道填充为0.
又发现一个问题,由4改变至其它窄一些的字后,会留有残余图形;调试时,打印的信息表明有些变量未赋初始值,字体位图转移后,又初始化源字体位图,尺寸为0,导致坐标计算错误,添加了错误的刷新区域;修改的代码 可到这查看 。
源文件的编码是GB2312.,转换成了UTF-8.
发现不能连续换多行,用了几个换行符 \n ,也只换一行。
OK,已完成,在调用TextLayer_Text_Add_NewRow()函数更新每一行尺寸时,初始最大高度为当前文本风格设定的字体尺寸+2;
2012-10-17
纠结滚动条的设计,能够设置滚动条是纵向还是横向,是纵向的话,高度与容器高度一致,横向的话,宽度与容器宽度一致,但是,怎么实现呢?貌似需要添加一些属性。
另外,要设计一个函数,这个函数能够添加指定容器内的部件,使滚动条在移动时,该容器内的部件能够一同移动;但是,若容器内有多个滚动条,移动时,哪个滚动条该被移动?各种纠结,不知如何用语言描述纠结的问题。
2012-10-18
部件的尺寸、位置可以用浮点数,限制尺寸可以只限制宽或高,当使用浮点数时,尺寸和位置需根据容器的尺寸x浮点数确定,这个浮点数其实是代表百分比,该设计参考了html元素的css属性,比如div元素,width=50px是宽为50像素,width=50%那就是宽为容器宽度的一半。 其实,C++的重载函数蛮有用的,假设要设定部件尺寸,有这么些尺寸: 宽为100px,高为80% 宽为50%,高为100% 宽高都为100px 宽高都为100% 用C的话,函数名要4个,用C++的话,可用同名函数,参数类型可以不一样。 好吧,参数都用字符串,处理是判断字符内容即可。
部件数据结构需要修改,分为两类成员: 基本属性,比如已经计算出的坐标位置、尺寸。 附加属性,比如:位置限制范围,尺寸限制范围,这些属性影响基本属性,因为有的是描述性的,尤其是使用百分比,需要经过计算。
添加一个结构体,用于同时存储整型和浮点型数据,类型名定为:comb_t ,也就是复合类型。
部件的属性,还是参考QT、VC的设计。
添加属性:auto_size_mode,用于指定部件的自动尺寸调整的模式,有两个值:grow_only(只增加)和grow_and_shrink(增加和缩小)。
添加属性:Dock,用于指定部件的停靠位置,有上、下、左、右、填充、无。
2012-10-21
LCUI_Widget结构体已经修改完毕,相关函数的代码也已修改完毕,修改过程中所产生的BUG已被处理。
开始实现文本图层的缺省文本样式设置。
已基本完成,效果图如下:
缺省字体大小设置为20像素,没设置颜色的文本的大小是12像素,而彩色文本的大小却是20像素。
处理效果还不错,即使是不同大小的字体,排列得也比较整齐,看来,可以加入<size>标签的支持。
combo_t更名为PX_P_t,新增PX_PT_t类型 ;PX是pixel,P是percent,也就是用于表示像素数或百分比,部件的位置和尺寸可以用具体像素数或百分比表示。PX_PT_t类型用于表示字体大小,因为字体大小单位有两个:像素 和 点数。
已经添加<size>标签的支持 ,可以用该标签设定指定段文本的字体大小,但字体位置还有点小问题。
调整了字体位图粘贴位置 ,之前是根据当前字体大小最大高度(当前像素+2)计算的,现在改为根据当前文本行最大高度来计算。
2012-10-22
开始实现部件的dock属性,还有以百分比为单位的部件尺寸的处理。
在测试dock属性时,发现下划线 ‘_’ 没有显示出来,切换几个dock属性后程序崩溃。
调试结果表明,是图像引用出现问题,引用区域不在图像的有效范围内, 现在已经纠正 。
打印了下划线 ‘_’的位图信息,发现它的top值为-1,怪不得没有在区域内绘制,因为最大高度减去 -1,已经超出这个区域了,解决方法就是改成: 最大高度-1 – top 。
测试程序已经添加 ,效果如下图所示:
计划添加padding和margin属性的处理。
2012-10-23
想将wordpress上的评论同步到静态html网页,合并同一文章的评论,可出了些问题,本以为导出的数据可以再导入,于是就将评论数据清空,而 多说 评论的导入工具暂时不能用,这就悲剧了,只好等开发者完善。
发现一个BUG,拖动窗口到屏幕边缘时,卡住了。
2012-10-24
只能怀疑问题出在最近修改的代码里,最有可能的就是与图形处理 + 区域计算 相关的函数。
原来是Quote_Graph函数的问题,由于在判断区域为无效后,没有用return退出函数,结果又执行了 引用区域有效时 所做的操作, 现已解决 。
开始实现部件的定位类型处理功能,和css的postion属性类似,有absolute, fixed, relative, static这些值。
fixed,可以有这么个效果:一个窗口里嵌套个子部件,子部件的定位类型为fixed,拖动这个窗口,子部件不会跟着窗口移动,位置还是屏幕上的绝对位置。
absolute,部件的位置默认就是相对于父部件的,而”left”, “top”, “right” 以及 “bottom” 这四个属性,可以通过设置部件的Pos,或者设置Anlign外加offset,以实现这四个属性的效果,部件就不用添加这四个属性。
relative,舍去,直接使用static定位类型,然后设置offset即可。位置还是原来的位置,但显示时,如果有几个部件挨着它,它就会覆盖到别的部件。
static,部件位置由LCUI决定,同属这个定位类型的部件,不会叠加在一起,只会挨个挤在一起。
2012-10-25
查看了与CSS的postion属性相关文章,还是添加relative定位,static定位则不受pos,align,offset的影响,完全由LCUI决定位置布局;而relative定位只是static的支持offset的版本。
看了下面这张图,发现relative定位的区块都是显示在static定位的区块之上,看来处理部件的堆叠顺序时还需要分组,先处理static定位的部件的显示,再处理其他定位的部件的显示。
需要纠结定位类型为static的部件的位置处理,具体可看下图:
该用怎样的算法实现以上的部件布局呢?
2012-10-26
先把上图所示的部件布局处理流程写下来,毕竟存在脑子里也不好思考。
添加区块A,位置为(0,0),没有重叠其它区块,位置更新完成。 添加区块B,位置为(0,0),与区块A重叠;X轴坐标加上区块A的宽度,位置为(A.w, 0),无重叠区块,位置更新完成。 添加区块C,位置为(0,0),与区块A重叠;X轴坐标加上区块A的宽度,位置为(A.w, 0),与区块B重叠;X轴坐标加上区块A的宽度,位置为(A.w+B.w, 0),无重叠区域,位置更新完成。 添加区块D,位置为(0,0),与区块A重叠;X轴坐标加上区块A的宽度,位置为(A.w, 0),与区块B重叠;X轴坐标加上区块A的宽度,位置为(A.w+B.w, 0),与区块C重叠;X轴坐标加上区块C的宽度,坐标为(A.w+B.w+C.w, 0),区块D超过容器范围;
将区块ABC的区域数据记录到队列中,从队列中获取第一个区域数据(也就是A),Y轴坐标加上区块A的高度,区块D的位置为(0,A.h),无重叠区域,位置更新完成。
添加区块E,重复区块D的操作;区块E的位置为(0,A.h),与区块D重叠,X轴坐标加上区块D的宽度,位置为:(D.w,A.h);无重叠区块,位置更新完成。
添加区块F,重复区块E的操作;区块F的位置为(D.w+E.w,A.h),由于区块F与区块C和B在X轴上有重叠,又因为区块C的高度大于B,因此区块F的位置为(D.w+E.w,C.h);无重叠区块,位置更新完成。
添加区块G,重复区块F的操作,区块G超出容器范围,将区块DEFC的区域数据记录到队列中,从队列中获取第一个区域数据(也就是D),Y轴坐标加上区块D的高度,区块G的位置为(0,D.x+D.h),超出容器范围;X轴坐标加上区块D的宽度,位置为(D.w, D.y+D.h);与区块E重叠,增加Y轴坐标到区块E的高度,区块G的位置为(D.w,E.y+E.h);超出容器范围;X轴坐标加上区块E的宽度,位置为(D.w+E.w,E.y+E.h);由于区块G与区块E在X轴上没有重叠关系,与区块F有重叠关系,更改Y轴坐标,位置为(D.w+E.w,F.y+F.h);无重叠区块,在容器范围内,位置更新完成。
个人觉得实现这个功能的函数,应该是用于处理一个容器内所有定位类型为static的部件,一次性将这些部件的位置更新掉;如果只用于更新一个部件,那么,效率低下,部件越多,重复的操作也越多。
在写这处理过程时发现,队列中只需要保存外围区块的区域信息即可,更新新部件的位置时,只需要将它与队列中记录的区域对比,即可算出适合的位置;但如何得出外围区块的区域数据,需要思考。
新的算法:
用一个二维指针(假设为ptr),作为一个表,用X和Y变量,表示记录点的位置。
按照显示顺序遍历部件队列,每遍历到一个部件,就把部件指针记录到记录点,更新部件位置,并使X++,当当前部件区块超出容器范围时,Y++,开始记录下一行。
如果有上一行记录,那么,就将当前部件区块与上一行的对比,只对比X轴坐标,如果当前部件区块的X轴占用区域与上一行的若干个部件区块重叠,那么,记录这些部件;当前部件区块的Y轴坐标就会根据那几个部件区块来调整,从左至右,当有个Y轴坐标能够不与上一行其它区块重叠时,那么该区块的位置就更新完毕。
举个例子,当前部件区块如上图中的区块E,在X轴上,它与区块A(ptr[0][0])和区块B(ptr[0][1])重叠,先让区块E的Y轴坐标为A.y+A.h,由于区块E使用这个坐标后,不与区块B(ptr[0][1])重叠,所以区块E的位置更新完毕。
而X坐标是随着部件位置的更新而更新,在更新区块E时,X坐标就已经到了D.x+D.w。
2012-10-27
若要实现下图所示的部件布局效果,该怎么实现?
对于B、E这种高度较高的区块,其它区块该怎样确定好位置?
拿区块M举例,更新完L的位置后,要更新区块M的位置,区块M是应该在灰色M那个区块,还是应该在蓝色M区块?
如果要放在灰色M区块,按照之前的方法还是可以实现的。
还有那个区块H,按照之前的方法,区块H会在区块J的位置,那么,加个处理:
如果当前区块底边的y轴坐标小于上一行区块的底边y轴坐标,那么,就将上一行区块再记录到当前行,因为它的高度足以占用两行(或以上)的区块区域。
但还是觉得会浪费空间,如果区块B底边的y轴坐标小于当前区块底边的y轴坐标几个像素,按照之前的方法,它当前区块的y轴坐标就等于区块B底边的y轴坐标+1,这样看起来,区块C到H之间,有一块比较大的空区域,若要节省些空区域,还是调整一下,判断条件改为:B.y+B.h > (H.y+H.h)/2.0 ,也就是判断区块B的底边是否超过区块H的一半,这应该好一点了。
好像不需要一个表,只需要两个队列即可,一个队列保存上一行记录部件,一个队列保存当前行正记录的部件。
基本代码已经完成, 点此查看新增的代码 。
新增测试程序 ,测试程序效果图如下所示:
第一个显示的部件居然排后面,明明是按照部件显示的先后顺序处理的,而调试信息表明第一个显示的部件排在队列末尾。
问题出在部件队列处理函数上,之前为了实现“保持前端显示”的功能,写了个WidgetQueue_Move函数,代码还有BUG,现在暂时不需要“保持前端显示”的功能,就用预处理命令取消(相当于注释掉)这函数的代码, 改用Queue_Move函数实现 ,效果图:
已实现分组处理各个定位类型的部件的显示 ,还未测试。
padding和margin支持百分比太麻烦了,还是改用整型变量保存。
正在实现部件内边距的支持。
2012-10-28
部件已经支持padding属性;
添加测试部件padding属性的测试程序 ,测试效果如下图所示:
左边距为10px,上边距为15px,右边距和下边距没作用。
2012-10-29
部件的布局方面的功能暂时就搞到这里,以后会根据需要再添加。
开始实现滚动条。
滚动条的长度,根据设定的max_size和current_size决定,由于之前让widget的尺寸支持百分比,那么,就用current_size / max_size * 100 得出百分比,然后转换成字符串,即可设定尺寸。
在测试滚动条时发现,若子部件尺寸大于父部件,父部件设置了内边距(都为1px)和边框,显示后,子部件会把父部件的边框覆盖掉;获取部件的有效区域时还要考虑到所在容器的实际尺寸,现在已经完善。
加个Update_Widget函数,用于让部件根据已设定的属性,进行相应数据的更新,每当设置部件相关属性时,就会调用它。
拖动滚动条移动时有问题:
当拖动子部件超过容器范围后,子部件的图形显示不完整。
运行了之前的滑动解锁的测试程序,发现显示的界面异常。。。
2012-10-30
测试发现,导致上面那个问题的原因是由于在调用Move_Widget函数时,Move_Widget函数没有检测新位置是否超出限制移动范围。
当在原位置点击并释放滚动条后,滚动条位置会移动,估计是在计算自身位置时没有考虑到父部件的内边距,在处理拖动事件时,减去内边距即可。
滚动条已经修改完成,效果如下图所示:
打算为windows部件添加一些窗口风格。
如果在Label部件设置文本内容后设置文本风格,那么,label部件尺寸不会改变;但先设置文本风格,再设置文本,不会后出现问题。
2012-10-31
窗口新风格的测试效果如下:
关于那个label部件的问题,是由于更新了字体位图后,没有更新当前文本行的尺寸,导致在后面更新label部件时,获取的文本位图尺寸不正确,现已解决此问题。
在检查LCUI_Widget.c源文件中的代码的时候,发现Get_Widget_Real_Graph()函数的这两行代码有点怪异: Quote_Graph( &temp, &widget->graph, cut_rect ); Graph_Mix( &widget->graph, &temp, Pos(x, y) ); 引用了自己的一块图形,又将之合成到自己的图形上,这是干什么的?
修改后,测试多窗口的嵌套,在窗口客户区内拖动子窗口至边缘,结果显示的图形异常。
原来之前测试滚动条所出现的图形异常也是这个问题。
刚刚测试,窗口移动到屏幕边缘也有此问题。
通过分析调试时得到的信息,发现Get_Widget_Valid_Rect()函数有点问题,返回的区域数据异常。
2012-11-1
当坐标小于0时,由于计算错误,导致出现了上述问题,现已纠正。
窗口移动还有点小问题,正在解决中。。。
用了过多的if-else嵌套,缩进的太深,影响美观,现已改用switch-case语句。
拖动部件所使用的新坐标的计算方法:
点击时,用鼠标全局坐标 减去 部件的全局坐标,得出偏移坐标。
拖动过程中,用鼠标全局坐标 减去 偏移坐标,得出部件的新全局坐标,之后,转换成部件当前容器区域的相对坐标。
在部件处于拖动状态后,每次位置变更都会将部件的新全局坐标转换成相对坐标,交给与拖动事件关联的回调函数处理。这样有个问题,测试窗口移动时,慢速拖动是没问题,快速移动就有问题了,位置异常,xy轴坐标有时是正负几千,不知这计算异常出在哪,自己写的那个全局坐标转相对坐标的函数,看代码也没发现不对的地方。
改了一下,取消掉每次的坐标转换,让与拖动事件关联的回调函数自己转换成相对坐标,测试正常。
部件的鼠标事件响应还有待完善,先凑合着用。
代码已经提交,主要进行了这些修改: 更新鼠标事件处理的代码 , 解决Get_Widget_Valid_Rect()函数存在的BUG ,也删减了部分无用代码。其它的修改也就是为了适应新修改的部件处理代码。
测试文本框时,发现嵌套使用样式标签后,效果不正常, 现已纠正 :原因是由于在为文字获取样式时,没有把样式对应的标志变量赋值为1,从而导致同一样式被覆盖。
2012-11-2
准备添加定时器。ActiveBox部件播放动态图像需要开线程,文本框的光标闪烁也要开线程,感觉线程不要开太多为好,有点想将用于处理触屏、鼠标、按键这三种输入的三个线程合并为一个。
说到这个合并,又有了个想法:提供一些函数,用于注册这些处理输入设备的函数,比如:鼠标,注册初始化函数,供LCUI初始化时调用,打开鼠标设备;注册处理函数,让LCUI在输入处理 线程中调用它,当然,只有在初始化函数的返回值为0时,才调用这个回调函数;注册析构函数,在LCUI结束后,就可以关闭鼠标设备,释放资源。
时间单位是毫秒,定时器还是用单独一个线程来处理。
测试helloworld时,发现设定缺省字体尺寸为24px后,有自定义样式的文字的尺寸是12px。
定时器功能已经添加 ,还有个 测试程序 ,以下是测试程序的效果:
已纠正 自定义样式的文本 不能 使用全局字体尺寸 的问题, 可到这查看修改的代码 。
2012-11-3
测试鼠标设备正常,但是,鼠标事件数据用的是全局变量保存的,如果是每次触发事件都分配一块内存,发给回调函数处理,那么怎么释放?让回调函数释放?万一我用一个局部变量保存鼠标事件再发过去,回调函数用free函数释放不会出错吗?暂时先用全局变量,懒得纠结。
鼠标设备的数据输入处理已修改,剩下的就是触屏和按键了。
触屏和按键的处理功能已修改完毕。
2012-11-4
添加1个widget的属性:clickable_area_alpha ,用于指定部件图层中的区域的alpha值大于多少时可被鼠标点击,默认为0,最大为255。比如要实现不规则形状的按钮,设定该属性值为254,点击那些透明区域,该按钮不会被按下,只有点击按钮中完全不透明的区域才能使按钮按下,触发事件。当设置为255后,鼠标就无法点击到该部件。
文本框中闪烁的光标,还是用widget实现,让它使用上面所说的属性,这样,鼠标点击文本框中的光标,不会影响拖动选中文本。
2012-11-5
国内类似GitHub.com的网站有gitcafe.com和gitcd.com,关注进展,个人感觉前者的界面比后者好一些。
为了减少缩进深度,有些if–else语句做了修改。
用按钮来测试clickable_area_alpha属性时,发现鼠标点击按钮后,按钮还处于按下状态, 现已纠正 。
调整了一下项目主页,标题栏区块变窄,更换LOGO。
发现有些网页的元素会在浏览器窗口达到一定大小时改变布局,比如谷歌浏览器的官网,宽屏浏览是一个样式,窄屏浏览又是一个样式;
浏览过 MiniGUI 官方网站,它也实现了这个功能,于是就查看网页源码,发现css样式中有这么一段内容:@media only screen and (max-width: 959px) and (min-width: 768px) ,这个就是规定浏览器窗口大小在某个范围内时,使用里面的样式。
已应用到项目主页上,默认的样式是让文本摆放在左边,图片摆在右边,而当浏览器窗口变窄时,会改变文本div和图片div的样式,使图片摆在上面,文本摆在下面。
说到不规则形状的部件,显示的子部件图形也要根据该部件的形状而定;例如,父部件是五角星形按钮,子部件是矩形的,那么,父部件中显示的子部件图形的形状也要是五角星形。
看来需要具备类似PhotoShop的图层蒙版功能。
差点忽略了一点,递归函数中如果使用static关键字修饰变量 ,每次递归都会使用同一地址,这样的话,递归获取数据会出问题。
需要加个属性:clickable_mode,用之前的那个属性,如果我要设置完全不能被点击或完全能被点击,貌似不能实现,用这个clickable_mode,来设定是 小于,还是要 大于。例如:clickable_mode = 0; 那么,鼠标指针所指的像素点的alpha值,就要小于clickable_area_alpha才能忽略鼠标点击。
在测试时发现鼠标指针在按钮上移动会使按钮图形闪烁,删去用于调试的打印信息的代码后,没这问题了。
2012-11-7
需要修改一下部件对鼠标事件的响应方式, 目前是只能有一个部件响应鼠标游事件,比如:鼠标游标移动在一个部件上,该部件就会变为高亮状态,被它遮挡的部件,还是普通状态;但是,考虑到部件嵌套,父部件里有个子部件,鼠标游标移到子部件上,到底该谁要变为高亮状态呢?
用html代码做了个简单的测试,两个div嵌套,浏览器给出了答案:都会变为高亮状态,两个div都变为hover状态,并且,点击子div,父div也会变为active状态。
这个功能打算在下个版本中应用。
文本框的光标闪烁已经实现,可通过鼠标来为文本框中的光标定位,可是存在一些问题,有时点击文本框,点了很多次,光标也没闪烁,位置不会变动。光标移动到大尺寸文字后,文本没了,好奇怪。
2012-11-8
参考了 在gtk实现拖动部件 的代码,主要是这么做的:
用 gtk_widget_set_events 设置部件获取鼠标事件。
用 gtk_signal_connect 为这些事件关联回调函数。
这些回调函数都有三个参数,一个是部件指针,一个是事件指针,一个是指向自定义数据的指针。
鼠标事件处理以后还会改动, 因为会用到鼠标右键,滚轮,目前只是处理鼠标左键。
经过测试发现,文本框内的光标不能正常移动,是因为子部件label抢了文本框的鼠标事件响应机会,明明设置了可点击区域的alpha值,怎么没忽略label部件呢?
之前是clickable_mode 为 1,表示“大于”,现在改为“不小于”。
clickable_mode 置为 1,clickable_area_alpha 置为 0,那么,在判断时就判断该部件的像素点的alpha是否不小于0,成立则忽略该部件,这样的话,整个部件都会被忽略。
还留有一个BUG,看图即可:
到最后,光标移动到hello world行时,文本消失了。
2012-11-9
调试时打印信息表明,label部件的图层在光标移动到hello world那行时改变了尺寸,也变为了不可视,需要用gdb跟踪变量变化。
是Auto_Resize_Widget()函数的问题,由于父部件label是启用自动尺寸调整,当光标要改变尺寸时,label部件也会更新一次尺寸,尺寸被调整为光标的尺寸。
为LCUI_Label结构体添加auto_size,用于指定是否根据文本图层的尺寸自动调整label部件的尺寸,这样,子部件-文本光标 改变尺寸后,不会使label部件自动改变尺寸。
现有的文本框的BUG已经基本解决,开始实现文本编辑功能。
按键事件关联功能需要修改,之前是每个按键关联一个回调函数,可是对于文本框部件而言,要用到众多按键,这样关联起来很麻烦,一次性关联整个键盘,当有按键按下时直接调用回调函数,让回调函数自己判断按的是什么键,并做相应操作。
2012-11-10
准备完善事件机制,完善按键输入,按键产生的事件将发送给当前处于焦点状态的部件的回调函数,如果没有为该部件关联回调函数,则不调用。
2012-11-11
有了文本框,就需要实现部件焦点功能,焦点机制设计如下:
- 不可见的部件 不能被 设置 为焦点部件。
- 在部件获得或者失去焦点时产生 FOCUS_IN 和 FOCUS_OUT 事件。
- 获得焦点的部件,作为它容器的父级部件也会获得焦点,前提是父级部件之前没有获得过焦点。
- 当有按键输入时,会调用焦点部件关联的相应回调函数,如果未关联,则在父级部件中查找已关联的部件。
- 焦点部件获得的按键输入,如果不是指定的按键,可以将该事件转移给父级部件。
- 为部件加个属性:focus,用于指示是否需要焦点,比如Label部件,不需要焦点,focus置为FALSE即可。
- 添加两个函数,用于前后切换焦点,比如:按钮部件,只需要回车按键,如果是方向键和tab键,则调用函数切换焦点。
功能要求有了,剩下的就是数据结构和算法的设计,继续纠结。
2012-11-12
当键盘输入的数据不是焦点部件所需要的时候,可以将按键输入事件返回给父部件。
键盘事件处理已经修改,部件焦点处理也基本完成,等待在调试过程中继续完善。
2012-11-13
一开始,默认不会把焦点给任何部件。
当获得焦点的部件改变容器时,之前容器的焦点记录需要进行更新。
默认将新显示出的部件设置为焦点。
若部件显示或隐藏,则更新容器焦点。
点击窗口标题栏文字时,无法拖动窗口,正在解决中。
改用部件指针保存当前获得焦点的子部件,用整形变量保存部件在队列中的位置有点不妥,因为窗口在获得焦点时会进行前置,也就是将它排在队列首位,由于那个整形变量未做修改,因此会造成窗口需要点两下才会变为焦点状态。
部件焦点处理功能已经基本完成,代码增删情况可到 这查看 ,以下是窗口的测试效果:
源代码在 这里 。
2012-11-14
在上图中,仔细看的话会发现一个小问题,当橙色子窗口超出客户区右边边缘时,边缘有残余图形显示,经过调试,还是Get_Widget_Valid_Rect函数的问题,区域计算有误,现已纠正此问题, 可到此查看代码修改情况 。
文本框中的光标闪烁,会使原本已失去焦点的窗口又获得焦点, 修改了一下Show_Widget函数的代码 ,不支持焦点的部件不会调用Set_Focus函数设定焦点。
已 添加部件按键输入事件的关联功能 , 文本框做了修改 ,测试结果表明,当文本框获得焦点后,用键盘进行输入,能够调用之前为文本框关联的回调函数,并打印键值,还需要继续完善文本框。
2012-11-15
开始添加方向键控制光标移动的功能。
光标移动处理相关的函数存在一些小问题,需要进行解决。
光标有三个位置:在字符串中的位置,在文本中的位置(多少行,第几个字),相对于文本框的位置(像素坐标)。对于文本中的位置,光标会显示在那个字的前面,而不是后面。
方向键控制光标移动的功能已经完成 ,存在的问题也 已经解决 (之前忘记提交text_layer.c源文件了,显示不了这次问题代码的修改情况)。
修改了 README.md 文件,部分内容参考自TextMate的 README.md 文件,而README.zh-cn改为 README.zh-cn.md ,其内容实际是README.md的中文版,翻译TextMate的README.md文件的内容费了点时间,借助谷歌翻译,再结合环境及自己的理解,把英文语句翻译成中文,比如Contributing那段中的第4条,就两句,但很长,纠结了一段时间,看了一下它的Issues,发现这段话是在说代码提交信息的编写格式。
现在需要解决的是: 光标的文本坐标与源字符串中的一维坐标的对应关系的处理。 在启用样式标签的情况下,编辑文本时如何处理这些样式标签,比如这段字符串:<color=#00ff00>green1<color=#ff0000>red</color>green2</color>,删除“green1”后,该如何判断是否需要删除<color=#00ff0000></color>这两个样式标签呢?要么,删除完”green1″后,在“green2”前面加个<color=#00ff00>,然后删除“green1”前面的<color=#00ff00>。
2012-11-16
开始添加文本删除功能。
先完成普通文本的删除功能,暂不考虑样式标签的处理。
大致流程就是这样:找到当前光标所在的字的位置,当按下Backspace键后,记录该字及后面的字的所在区域,并标记它们需要重绘,以便重绘时清空之前的残留图形;然后,从 源字符串 和 行文本数据 中删除该字的数据;最后,更新Label部件,重绘文本图层中已标记的字符的位图。
代码已完成, 修改文本框代码 ,支持HOME键和END键的光标控制,支持Backspace键删除字符;文本图层处理中, 添加字符删除功能 ;以下是效果图:
不能在行尾按Backspace键删除字符,删除字符时,还有残余图形,有待完善。
2012-11-17
字符删除功能已经完善,之前字符删除后有残余图形,是因为没有记录删除的字的区域,只记录了它后面的字的区域。删除字符时,偶尔会出现段错误,gdb上已给出问题代码所在行,为指针加个有效性判断即可。连续删除文字时,发现逗号在向左移动后显示不全,鼠标指针移至该逗号上,逗号完全显示,目测是在更新字体位图时没有添加正确的刷新区域,导致刷新不全。
上述问题的代码修改情况 可到这查看 。
用 git commit –amend 命令,可修改还未push的commit信息。
已经可以从行尾进行字符删除了,接下来就是多行文本的删除,比如:在第二行行首按Backspace键,则删除源字符串中的换行符’\n’,并将第二行文本转接第一行行尾上。
但是,考虑到以后的自动换行功能,文本的换行,并不一定是因为换行符’\n’,而会是该行文本超出限定宽度而自动换行,那么,源字符中不存在换行符’\n’,就不能删除换行符’\n’。
2012-11-18
TextLayer_Text_Backspace函数和TextLayer_Text_Delete函数都是删除字符,只不过,前者是删除光标之前的N个字符,后者是删除光标之后的N个字符,那么,再加个函数_TextLayer_Text_Delete函数,让这两个函数只负责计算需删除的文字的起点位置,以及删除的字符个数,而字符删除操作都由_TextLayer_Text_Delete函数实现。
上述修改已经完成, 可到这 查看代码修改情况。
新增Queue_Cat函数 ,用于将上一行与下一行文本的拼接,因为每一行的文本是使用各自的队列记录的。
已经基本实现 跨行文本删除功能 ,具体效果如下图所示:
用方向键移动光标,若光标在最后一行的最后一个字上,再往右移动的话,光标会被移动至行首, 此问题已经纠正 。
文本框里显示的文本是看得到的,但和源字符串里的文本不一定相同,还需要完成源字符串中的字符删减功能。
原来那个工具叫cygwin,先用用看。
2012-11-19
Cygwin上,cd到lcui源码目录,执行configure,有点慢,linux下,configure打印的信息是刷刷的出来,而在windows下,这速度就慢了很多。
编译时发现一些问题,没有删除LCUI.h中的LCUI_TS,touchscreen.c编译失败;Cygwin下没fb.h头文件,那么,应该在configure检测一下,没有则fb.h头文件的话,图形输出方式不用framebuffer,也就不编译framebuffer.c,改为编译dummy.c,dummy是“虚设”的意思,里面虽有函数,但没有实际代码。
configure.ac里,添加代码,以检测–enable-graph-display选项,如果选项等于yes,那么,检测是否有linux/fb.h头文件,有则GRAPH_OUTPUT_DEV_NAME=framebuffer,否则GRAPH_OUTPUT_DEV_NAME=dummy。
Makefile.am里的liboutput_la_SOURCES = framebuffer.c graph_display.c 改为 liboutput_la_SOURCES = $(GRAPH_OUTPUT_DEV_NAME).c graph_display.c 。
测试出问题,用了./configure –enable-graph-display=no 命令后,make时说没有dummy.Plo文件,用ls src/output/.deps/ -a命令查看该目录文件列表,的确没有dummy.Plo文件,但有个$(GRAPH_OUTPUT_DEV_NAME).c文件,这是什么情况?
在configure.ac里加了echo -e “GRAPH_OUTPUT_DEV_NAME = $GRAPH_OUTPUT_DEV_NAME”,再configure一次,打印的是GRAPH_OUTPUT_DEV_NAME = dummy,但为什么创建的.Plo文件是$(GRAPH_OUTPUT_DEV_NAME).Plo而不是dummy.c ?
改用宏定义算了。
听说有个工具叫MSYS,比Cygmin速度更快、体积更小、功能强大,有空试试。
准备实现文本框的源文本的编辑操作,以使文本框上对可见文本的编辑操作能应用在源文本里。
2012-11-20
测试文本框时,字母 i 由于bitmap.left是负值,导致被它后面的字母 j 的字体位图覆盖,需要参考FreeType的文档,以解决字体的跨距问题。
找到了,FT_Glyph_Metrics结构体用于保存步进跨距相关的信息,主要利用horiBearingX、horiBearingY 和 horiAdvance 这三个成员变量,目前LCUI只考虑水平文本处理,垂直文本以后按照需求再考虑。测试时打印这几个成员变量,发现不是个正常的值,但看见FreeType文档上有这么短代码:slot->advance.x >> 6; 于是修改代码,使之打印向右位移6位后的值,也就是除以64后的值,结果,打印的值是正常的。
修改了bitmapfont.c里的代码 ,以获取上述的数据。
为了利用上述数据, text_layer.c的代码也进行了相应的修改 ,主要是修改字体位图定位的计算方式。
文本框的源文本删除操作还需要考虑一下,如何根据rows_data(用于记录每行显示的文字的信息)里的数据,来删除源文本中相应的字符数据?虽然两个地方保存的字符数据指针所指向的地址是同一地址,但是,直接遍历的并对比地址的话,效率不会变低吗?
对了,应该让光标在移动后,记录光标前的字符在源文本中的位置,这样,删除字符时,以该位置为起点,开始遍历;若按backspace键来删除字符,就往左边遍历队列中的字符数据,而按delete键,就往右遍历;
光标每次移动时,会根据移动的方向,以之前确定的位置为起点,在队列中以相应的方向遍历字符数据的地址,直到地址匹配为止,这样,效率就比较高了。
2012-11-21
无法登陆sourceforge.net的FTP,数据库在前天就发现无法使用,估计是被删除了。还好github上有网站副本,修改index.html,因为不像之前那样,网站有github.com和sourceforge.net两个镜像可选,现在只能选语言了。
2012-11-23
行数据结构体中,加入一个成员变量,用于保存行尾的换行符’\n’,也方便在跨行删除文本时,确定换行符’\n’的位置。
测试同时删除多个文字时,出现问题:字体位图刷新 和 跨行文本删除出现异常。
OK, 文本框的字符删除功能已经基本实现,重写了_TextLayer_Text_Delete函数的大部分代码,经过一番调试+完善后,基本没什么问题,其它地方添加变量的有效性判断,以正常处理数据。
代码改动情况 可到这查看 。
2012-11-24
测试文本添加功能时,发现在第一行行首添加字符时,源文本内容和显示的文本都异常,第一个字符没有添加进去。
花了几个小时调试,开始是怀疑队列处理有问题,可是单独测试Queue_Insert函数并没出现问题,由于源文本是使用链表方式储存的,在相关函数里加了printf函数打印链表头结点的地址和第一个结点中记录的上个结点(prev指针保存)的地址; 结果表明,添加文本前,头结点的地址和第一个结点的prev指针是一致的,添加时,就不一致了。 仔细分析之后,恍然大悟,问题出在TextLayer_Merge函数,在处理后期,直接将A源文本赋给B源文本,并未修改数据中的第一个结点的prev指针。 为解决此问题,增加了Queue_Quote函数,用于让一个队列引用另一个队列。
正修复添加文本时所出现的文字显示问题。
修改了Queue_Cat函数,之前以为,如果两个队列的数据储存都是使用链表,那么直接拼接首位结点即可,但现在才发现,队列有已用和未用这两种空间,仅仅是拼接首尾结点是不可行的,还需要将已用空间的后半段链表拼接。
断行处理功能已经完成,可以通过按回车使当前行断行,断点后面的字符转移至新行。
2012-11-27
运行label部件测试程序,发现一个问题,目测是断行处理有问题。
打印调试信息,发现记录的区域中,有些区域的y轴是负数,奇怪了。
之前记录区域是直接调用RectQueue_Add函数,但为方便调试,还是封装一下。
负数的原因是,没有更新当前行的尺寸,计算y轴坐标时,拿0去减。
在频繁调用Set_Label_Text函数设置label部件的文本时,显示的文本位图有时会不完整,还会使程序异常。
看来,需要一个缓冲,存储文本,等绘制文本位图时再更新。
删除了TextLayer_Merge函数,之前只是为了减少刷新区域,但现在觉得那点刷新区域不减少也没事,况且测试时添加的区域有问题,导致部分文字被刷没了,懒得解决这问题。
TextLayer_Text函数改为直接清空原文本,再添加新文本,并重绘所有字体位图。
文本图层的代码修改情况可查看这里。
测试发现,label部件不显示文本,需要更新一次才显示。
由于label部件是在绘制文本图层前获取文本位图的尺寸,而添加缓冲功能后,需要在绘制文本图层后才能获得文本图层的尺寸,改一下laebl部件的代码即可解决。
TextLayer代码修改情况可到这查看,label部件的代码修改情况可到这查看。
Label部件的代码修改情况可查看这里。
2012-11-28
可以将回调函数与滚动条部件连接,在滚动条被滚动时,将会修改label部件上显示的文字。
文本框添加两个滚动条,现在先测试右边的滚动条。
为测试文本框的文本滚动功能,加了个定时器,用于定时滚动文本,但测试结果表明,只能用一个定时器,这个定时器用于文本框内的光标闪烁。
是Queue_Swap函数问题,导致不能对定时器列表进行排序,已纠正。
测试文本框的文本滚动时,发现文本刷新不正常,时不时的还会来个段错误。
经过调试后,出错原因是在绘制字体位图时,获取的裁剪区域不正常,区域的高度是负数,导致绘制时使用的下标不正常,从而访问越界,产生段错误。已纠正。
解决换行后当前行下面的所有行未被重绘的问题,考虑到会遇到频繁滚动文本图层的情况,更改了文本图层的坐标偏移处理方式。
其它细节问题的解决情况就不多说了,下图是目前的文本框的效果:
移动光标时,浏览区域会不自动调整,以使光标在浏览区域内。
滚动条的位置及长度,会根据文本内容自动调整,但是,光标移动后的滚动条更新处理 会与它存在冲突,导致移动光标后,不能正常更新滚动条。
经过测试,有时会产生段错误。
2012-11-29
用C-Free5编译了一个测试程序,程序就是显示个windows窗口。
初看测试程序的源代码的时候,感觉很陌生,经过一番修改和测试后,对这代码还算比较熟悉了。
就两个函数:WinMain和WndProc,WinMain函数里将WndProc保存至WNDCLASS类中的lpfnWndProc,然后调用RegisterClass函数注册WNDCLASS类,再调用CreateWindow创建窗口,最后进入消息循环。
在WndProc函数里,响应WM_PAINT消息,在客户区里绘图,百度过程中,了解到BeginPaint和EndPaint函数要成对使用,矩形区域填充用FillRect函数,参数1指定目标,参数2指定区域,参数3指定填充的颜色。
有个InvalidateRect函数,让指定区域无效,等待重绘,这个和我的LCUI中的Add_Screen_Refresh_Area函数、ADD_Widget_Refresh_Area函数一样,记录所需刷新的区域,等待重绘。
2012-11-30
拆分了部分代码至新的函数。
添加Exec_TextBox_Resize函数,文本框在尺寸改变时能够调用它,以调整滚动条位置和长度。 Exec_TextBox_Update函数,在编辑文本时会被调用,会调整滚动条的长度。 TextBox_ViewArea_Update函数,用于更新文本显示区域,调整滚动条的位置。
TextBox_Cursor_Move函数,在光标移动时被调用,更新完光标位置后,会调用TextBox_ViewArea_Update函数,以调整文本浏览区域。
文本框的纵向滚动条已经调整完毕,能够完成所需要的基本功能。
在优化文本框的文本滚动刷新时,发现如果添加的刷新区域很小(15x15左右),数量很多的话,拖动滚动条时会有卡顿。 想出了个解决方法:再加个队列和一个标志变量; 标志变量的值只有0和1,为1时,处理的区域刷新会锁住队列1,在锁住的过程中,添加的区域数据都会添加至队列0中,为0时,则相反。这样就不会因为队列被锁住而延迟区域的记录了。
优化已经完成,代码改动情况可到这里查看。
测试文本行的删减功能时,发现文本显示区域移动有问题,光标不在文本显示区域内。
问题已经解决,源代码加了11行,删了4行,改动并不大,就是修改了文本图层的偏移坐标的计算方式。
发现了一个问题:在文本框里按住鼠标左键,快速的移动鼠标,跑几圈,然后停住,调试信息会打印几个屏幕,干的都是重复的事,延续了几秒才停住;个人猜测是添加处理鼠标拖动事件的问题,鼠标每次移动都将关联的函数指针+参数转换成任务,追加至程序任务队列,鼠标移动轨迹有多像素,就加多少次任务,这里需要优化一下,任务添加模式由之前的ADD_MODE_ADD_NEW改为ADD_MODE_REPLACE | AND_ARG_F,也就是使用替换模式,如果队列里有个任务和 新任务的函数指针+参数1指针 一样,那么,直接替换。 |
问题已经解决,代码改动情况可到这里查看。
文本框的纵向滚动条已经完成,剩下的任务就是: 添加横向滚动条 文本框可设置成单行 完善多文本框内的文本输入功能 修改现有测试程序代码 对各个源文件中的代码进行检查 基本完成后,准备发布0.12.6版本。
2012-12-1
测试让文本框显示README.md文件内容,载入速度有点慢,看来需要优化一下;
对于纯英文文本,就那26个字母,外加其它ASCII码字符,也就百来个可显字符,对于这些重复字符,不必重新获取字符的字体位图,直接引用现存的字体位图即可,这样就省得重新载入字体位图了。
主要实现方法:加个队列,队列里保存的字符数据 根据字符编码从小到大排列,在获取字体位图时,会先在队列里查找,使用的是二分法查找,若找到指定编码的字符数据,则在里面找符合当前尺寸、字体族、字体风格的字体位图,如果找到了,就直接引用,否则,重新获取字体位图,并记录至该字符数据里。 这个还是放到后续的更新中。
测试移动滚动条时,发现个问题,光标在文本末尾,拖动滚动条,移动显示区域,之后,鼠标再点一次滚动条,显示区域居然跳到文本末尾去了。
修改了Record_WidgetUpdate函数的代码,Queue_Replace函数有点小问题,在拖动滚动条滚动文本框的文本时,有时会出错,出错位置在Queue_Replace函数里,覆盖一个队列成员前,调用free函数释放它就会出错。
又修改了一次Record_WidgetUpdate函数,在记录部件更新时,如果已经存在2个相同记录,则进行覆盖,否则新增一条记录,这是为了让文本框能够正常分段处理显示文本,而又保证 部件更新时的再次记录更新 不会导致无限添加记录。代码改动情况可到这里查看。
修改了TextLayer,支持在末尾追加文本,且不会改变光标位置。
文本框做了修改,在为文本框添加文本时,会先将其分成若干个文本块,并添加至缓冲区内,在更新文本框时,会检测缓冲区是否有数据,有则获取一个文本块,追加至当前文本末尾,然后再标记文本框更新,以处理显示剩下的文本块。效果如下图所示:
窗口设置为640x480,用大文本框显示文本,文本位图的获取速度感觉很慢,拖动滚动条滚动文本,有卡顿,记得以前的照片查看器拖动图片都没这么卡。
测试时,发现窗口标题栏上的关闭按钮的大小不对,查看了window部件的代码,没什么问题,后来才怀疑是没有禁用按钮部件的自动尺寸调整,再看了一下代码,果真没有禁用,现已修复。让人感到奇怪的是,之前怎么是正常的大小?
2012-12-2
测试进度条时,进度条前景图形不对,感觉是向上下两边拉伸了一样,后来发现是get_PX_P_t函数有时无法将字符串“100%”处理成1.00,已纠正。
测试发现,即使不动鼠标,也会刷新屏幕区域,该区域和窗口所在的区域相同。
该问题是上次修改Record_WidgetUpdate函数造成的,又改了一下代码。
2012-12-3
测试照片查看器,主循环里执行几个任务后出错,调试+分析后,初步认定是ActiveBox部件的问题。
ActiveBox部件代码中,没有初始化LCUI_Func结构体,尤其是destroy_arg这个标志,用于指示参数1和2是否在执行完任务后free掉,由于没赋值,它的值时不确定,从而导致在执行任务后对不能free的参数进行free,产生错误。
顺便改了ActiveBox部件的代码,之前是用单独一个线程来处理动画更新,现已改成用定时器。
测试ActiveBox部件的动画暂停+播放功能,查看打印的调试信息后,发现每多一次暂停+播放,打印的更新动画条目就会多一条,问题出在Frames_Play函数,每次调用它,不管该动画是否已存在队列中,都进行添加,现已纠正,但是纠正后,两个ActiveBox部件就不能播放同一个动画,必须为该动画重新开辟一个内存来存储。
ActiveBox部件的代码提交信息可到这里查看。
为滚动条添加横向显示功能,修改了滚动条容器的背景色。
为文本框添加横向滚动条,滚动条的尺寸和位置改用两个函数别更新,这是代码提交信息。
更新文本框的测试程序,效果如下图所示。
本来是拷贝LCUI_Widget.c文件并提交的,可是拖错了,把LCUI_Queue.c拖进去了,添加commit信息时又没注意,把LCUI_Widget.c文件的commit信息加到了LCUI_Queue.c上。
2012-12-4
测试文本框,在删除当前行唯一的一个字符时出现了错误,调试+分析后,确定BUG来自于队列删除操作上,由于使用的是链表模式,没考虑到只有一个成员的情况,没正常处理好结点,导致在删除该成员时异常,现已纠正。
文本框内使用TextBox_Text_Add添加文本的话,获取的字体信息异常,一个字的位图的X轴跨距上万,导致在调整部件尺寸时,因无法为大尺寸部件分配内存而异常终止。
加了些代码,用于打印信息,仔细对比正常情况和异常情况下输出的内容,得出以下结果: 如果TextLayer_Text_GenerateBMP()函数的两次调用是依次调用的话,获取的字体信息是正常的。 如果TextLayer_Text_GenerateBMP()函数被两个线程调用,并且在同一时间段内这两次调用都未结束,打印的信息是异常的。
话说,FreeType是不是不能在多线程上正常工作?有空再单独测试一下,看看多线程获取字体位图时是否还会出现此问题,如果有,那么FreeType的这个问题,可能 和多线程读写同一个文件所产生的问题类似。
完善了文本框的滚动条处理,编辑文本时会自动更新滚动条的位置及长度。
启用样式标签支持,并往文本框内添加带样式标签的文本,显示不正常,后来发现,是由于在添加文本时将文本分割掉了,导致样式标签不完整,这个以后再解决。
2012-12-5
修改TextBox_Text_Add函数,它会将文本分割成若干个文本块,等待更新文本框时将该文本块插入至光标处。
文本框支持单行模式,所有文字都显示在一行里,并且隐藏滚动条。
添加屏蔽字符的支持,可实现密码输入框。
可对文本框的内容进行限制,使其在输入时,忽略限制范围外的字符。
文本框的代码修改情况,可到这查看。
修改了文本框的测试程序,效果如下图所示:
2012-12-5
剩下的任务就是更新测试程序的代码,照片查看器有的小问题,看看重写后是否存在此问题。
照片查看器的ActiveBox部件无法播放动画,调试发现是定时器记录的程序ID与程序实际ID不同,后来才发现,是因为在创建的线程中添加的定时器。
2012-12-6
切换查看其它图片时,会卡住。
BUG范围已经缩小至PictureBox部件的重绘函数里,在对图形设置锁时,出现了死锁导致程序卡在这里。
2012-12-7
在LCUI_Graph结构体中加了两个变量,分别记录读和写的次数,又加了个全局指针变量,在创建PictureBox部件后,保存该部件的图形数据的地址。<、p>
Graph_Lock函数中,累计次数,而Graph_Unlock函数,用于将当前锁的状态与当前锁住的次数对比,如果不正常,则调用abort函数终止,这样可以用gdb查看函数调用栈。
测试结果表明,调用了Graph_Tile函数,raph_Tile函数又调用了Graph_Fill_Alpha函数,在Graph_Fill_Alpha函数前已经对图形数据设置了锁,而Graph_Fill_Alpha函数又对图形数据上了一次锁,因而出现死锁,现已纠正该问题。
2012-12-8
在为照片查看器设置第三个定时器后,不起作用,按钮没有隐藏,后来发现,该定时器被暂停了。
花了一段时间,找到了问题原因:调用pause_timer函数时,本来是要传定时器的ID的,但是还没创建定时器,没有ID,变量保存的是-1,于是把-1传进去了,而pause_timer函数居然还能找到ID为-1的定时器。
2012-12-9
在为照片查看器的部件添加淡出效果时,发现只有父部件的透明度改变了,而子部件没改变,应该加个属性inherit_alpha,用于指示子部件图层透明度是否随着父部件的透明度的改变而改变。
照片查看器已经完成,效果如下图所示: 重新规划了代码,可到这查看目前的代码。
猜拳游戏、触屏校正、滑动解锁等程序的代码也做了一些修改。
2012-12-10
把LCUI的源代码放到学习机上编译,本以为这次代码改动较大,不会出现之前的那个SIGTTOU问题,结果,运行进度条的测试程序,直接退出,就连之前可以正常运行的照片查看器也不行了,虽然不带参数运行是可以运行的,但让它打开一个图片文件,程序就会直接退出。
这是以前在学习机上用gdb调试时截的图: 给的信息是:program received signal SIGTTOU, Stoped(tty output).
本来想在stackoverflow.com上提个问题,但不能贴图,翻译出来的英文也感觉有问题,最后还是放弃。
2012-12-11
删除了helloworld2.cpp源文件,把它里面的C++代码加进了helloworld.c,用gcc编译器编译就会编译C代码,用g++编译器编译就会编译C++代码;可到这查看目前的helloworld代码。
完善部分C++头文件,LCUI类改为LCUIApp,而label、window、button等部件的C++类,改用继承方式,属性及成员函数继承自LCUIWidget类,因为它们都是LCUIWidget部件。
运行文本框测试程序时,发现单行文本框居然会显示滚动条,记得之前没这问题,哪里搞错了?
貌似是因为之前改label部件,让它默认启用多行文本模式,而文本框又是直接用label部件,使得文本框也默认启用多行文本模式,现在已经纠正。
在密码框里输入密码,光标的位置不对,没在文本框里,目测是计算文本框尺寸时,不是累计屏蔽符的尺寸,而是累计实际输入的字符的位图尺寸,现已纠正。
准备更新程序截图。
百度了一下关于SIGTTOU的信息,最后决定试试 signal(SIGTTOU, SIG_IGN);,看能否忽略该信号。
2012-12-12
测试无效,还是有问题,gdb也不好调试,看不到函数调用栈,gdb的backtrace命令结果就是no Stack。
修改了README、FAQ和CHANGES文件,除了中文版的,还要翻译成英文版,用谷歌翻译,再自己修改。
2012-12-13
在sourceforge.net上又创建了个项目, name是:GUI toolkit: LC User Interfaces,而unixname是:lc-ui,项目页面地址:https://sourceforge.net/projects/lc-ui/。
LCUI的各个版本的源码包都上传至了这个新建项目的文件列表里。
用git上传项目源代码至sourceforge.net上,在上面稍微浏览了一下项目代码,感觉sourceforge.net的页面比较粗糙,有些小字占的空间太大,不紧凑,比较零散,打开源文件,中文是乱码的,看来还是用github.com算了,已删除托管在sourceforge.net上面的项目代码。
2012-12-14
LCUI 0.12.6 已经发布,顺便更新了百度百科上的词条,项目主页也做了相应修改。
文章版权归作者所有,未经许可不得转载。