<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The linux mobile development</title>
	<atom:link href="http://www.limodev.cn/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://www.limodev.cn/blog</link>
	<description>致力于基于linux的嵌入式系统的学习和研究，包括内核、驱动、GUI、MMI、软件设计和优化等。欢迎交换友情链接。代码请到Projects里下载。</description>
	<lastBuildDate>Tue, 13 Jul 2010 14:55:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=abc</generator>
		<item>
		<title>《系统程序员成长计划》@DouBan:</title>
		<link>http://www.limodev.cn/blog/archives/1524</link>
		<comments>http://www.limodev.cn/blog/archives/1524#comments</comments>
		<pubDate>Wed, 07 Apr 2010 12:34:39 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1524</guid>
		<description><![CDATA[《系统程序员成长计划》@DouBan: http://book.douban.com/subject/4722708/ 欢迎评论。]]></description>
			<content:encoded><![CDATA[<div class="announcement_post"><p>《系统程序员成长计划》@DouBan: <a href="http://book.douban.com/subject/4722708/">http://book.douban.com/subject/4722708/</a> 欢迎评论。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1524/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>系统程序员成长计划(china-pub首发)</title>
		<link>http://www.limodev.cn/blog/archives/1497</link>
		<comments>http://www.limodev.cn/blog/archives/1497#comments</comments>
		<pubDate>Thu, 25 Mar 2010 05:47:25 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[系统程序员成长计划]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1497</guid>
		<description><![CDATA[《系统程序员成长计划》(china-pub首发) http://www.china-pub.com/196523]]></description>
			<content:encoded><![CDATA[<div class="announcement_post"><p>《系统程序员成长计划》(china-pub首发) <a href="http://www.china-pub.com/196523">http://www.china-pub.com/196523</a></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1497/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI FTK设计与实现-显示设备(FtkDisplay)</title>
		<link>http://www.limodev.cn/blog/archives/1544</link>
		<comments>http://www.limodev.cn/blog/archives/1544#comments</comments>
		<pubDate>Tue, 13 Jul 2010 14:55:17 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1544</guid>
		<description><![CDATA[对于GUI来说，输入设备(如键盘和鼠标)和显示设备 (如LCD)都是与硬件相关的。在前面关于《事件源(FtkSource)》的一节中，我们看到了FtkSource很好的抽象了输入设备，让FTK独立于具体的输入设备，从而提高了FTK的可移植性。同样为了提高FTK的可移植性，我们需要对显示设备进行抽象。这里我们引入接口FtkDisplay来抽象显示设备： FtkDisplay的主要接口函数有： * ftk_display_width: 获取显示设备的宽度。 * ftk_display_height: 获取显示设备的高度。 * ftk_display_update: 在指定位置显示位图数据。 * ftk_display_snap: 从显示设备中指定位置截图。 1.ftk_display_x11 这是针对X Window实现的显示设备，它将一个X窗口当作显示设备，让所有FTK窗口都显示在同一个X窗口上。这样做的目的是在PC上模拟运行FTK的应用程序，从而提高用FTK开发软件的效率。 创建 X窗口： win = XCreateSimpleWindow&#40;display, RootWindow&#40;display, screen&#41;, 0, 0, width, height, 3, BlackPixel&#40;display, screen&#41;, WhitePixel&#40;display, screen&#41;&#41;; 创建XImage: priv-&#62;bits = FTK_ZALLOC&#40;width * height * priv-&#62;pixelsize&#41;; priv-&#62;ximage = XCreateImage&#40;display, priv-&#62;visual, priv-&#62;depth, ZPixmap, 0, &#40;char*&#41;priv-&#62;bits, width, height, 32, width * [...]]]></description>
			<content:encoded><![CDATA[<p>对于GUI来说，输入设备(如键盘和鼠标)和显示设备 (如LCD)都是与硬件相关的。在前面关于《事件源(FtkSource)》的一节中，我们看到了FtkSource很好的抽象了输入设备，让FTK独立于具体的输入设备，从而提高了FTK的可移植性。同样为了提高FTK的可移植性，我们需要对显示设备进行抽象。这里我们引入接口FtkDisplay来抽象显示设备：<span id="more-1544"></span></p>
<p><img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk_display.png" alt="ftk_display" /></p>
<p>FtkDisplay的主要接口函数有：</p>
<p>    * ftk_display_width: 获取显示设备的宽度。<br />
    * ftk_display_height: 获取显示设备的高度。<br />
    * ftk_display_update: 在指定位置显示位图数据。<br />
    * ftk_display_snap: 从显示设备中指定位置截图。</p>
<p>1.ftk_display_x11<br />
这是针对X Window实现的显示设备，它将一个X窗口当作显示设备，让所有FTK窗口都显示在同一个X窗口上。这样做的目的是在PC上模拟运行FTK的应用程序，从而提高用FTK开发软件的效率。</p>
<p>创建 X窗口：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">    win <span style="color: #339933;">=</span> XCreateSimpleWindow<span style="color: #009900;">&#40;</span>display<span style="color: #339933;">,</span> RootWindow<span style="color: #009900;">&#40;</span>display<span style="color: #339933;">,</span> screen<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
       <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> width<span style="color: #339933;">,</span> height<span style="color: #339933;">,</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">,</span> BlackPixel<span style="color: #009900;">&#40;</span>display<span style="color: #339933;">,</span> screen<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> WhitePixel<span style="color: #009900;">&#40;</span>display<span style="color: #339933;">,</span> screen<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>创建XImage:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">       priv<span style="color: #339933;">-&gt;</span>bits <span style="color: #339933;">=</span> FTK_ZALLOC<span style="color: #009900;">&#40;</span>width <span style="color: #339933;">*</span> height <span style="color: #339933;">*</span> priv<span style="color: #339933;">-&gt;</span>pixelsize<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       priv<span style="color: #339933;">-&gt;</span>ximage <span style="color: #339933;">=</span> XCreateImage<span style="color: #009900;">&#40;</span>display<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>visual<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>depth<span style="color: #339933;">,</span> ZPixmap<span style="color: #339933;">,</span>
           <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>priv<span style="color: #339933;">-&gt;</span>bits<span style="color: #339933;">,</span> width<span style="color: #339933;">,</span> height<span style="color: #339933;">,</span>
           <span style="color: #0000dd;">32</span><span style="color: #339933;">,</span> width <span style="color: #339933;">*</span> priv<span style="color: #339933;">-&gt;</span>pixelsize<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>获取宽度：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_display_x11_width<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>width<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>获取高度：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_display_x11_height<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>height<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>显示位图：先把位图拷贝到XImage上，然后调用 XPutImage显示XImage。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> Ret ftk_display_x11_update<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #339933;">,</span> FtkBitmap<span style="color: #339933;">*</span> bitmap<span style="color: #339933;">,</span> FtkRect<span style="color: #339933;">*</span> rect<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> xoffset<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> yoffset<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    Ret ret <span style="color: #339933;">=</span> RET_FAIL<span style="color: #339933;">;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>bitmap <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       <span style="color: #993333;">int</span> display_width  <span style="color: #339933;">=</span> priv<span style="color: #339933;">-&gt;</span>width<span style="color: #339933;">;</span>
       <span style="color: #993333;">int</span> display_height <span style="color: #339933;">=</span> priv<span style="color: #339933;">-&gt;</span>height<span style="color: #339933;">;</span>
       ret <span style="color: #339933;">=</span> priv<span style="color: #339933;">-&gt;</span>copy_to_data<span style="color: #009900;">&#40;</span>bitmap<span style="color: #339933;">,</span> rect<span style="color: #339933;">,</span>
           priv<span style="color: #339933;">-&gt;</span>bits<span style="color: #339933;">,</span> xoffset<span style="color: #339933;">,</span> yoffset<span style="color: #339933;">,</span> display_width<span style="color: #339933;">,</span> display_height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       XPutImage<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>win<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>gc<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>ximage<span style="color: #339933;">,</span>
           xoffset<span style="color: #339933;">,</span> yoffset<span style="color: #339933;">,</span> xoffset<span style="color: #339933;">,</span> yoffset<span style="color: #339933;">,</span> rect<span style="color: #339933;">-&gt;</span>width<span style="color: #339933;">,</span> rect<span style="color: #339933;">-&gt;</span>height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
       XPutImage<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>win<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>gc<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>ximage<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>width<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       ret <span style="color: #339933;">=</span> RET_OK<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    XFlush<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    XSync<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>截取位图：从XImage拷贝数据到位图中。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> Ret ftk_display_x11_snap<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #339933;">,</span> FtkRect<span style="color: #339933;">*</span> r<span style="color: #339933;">,</span> FtkBitmap<span style="color: #339933;">*</span> bitmap<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    FtkRect rect <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> w <span style="color: #339933;">=</span> ftk_display_width<span style="color: #009900;">&#40;</span>thiz<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> h <span style="color: #339933;">=</span> ftk_display_height<span style="color: #009900;">&#40;</span>thiz<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> bw <span style="color: #339933;">=</span> ftk_bitmap_width<span style="color: #009900;">&#40;</span>bitmap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> bh <span style="color: #339933;">=</span> ftk_bitmap_height<span style="color: #009900;">&#40;</span>bitmap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    rect.<span style="color: #202020;">x</span> <span style="color: #339933;">=</span> r<span style="color: #339933;">-&gt;</span>x<span style="color: #339933;">;</span>
    rect.<span style="color: #202020;">y</span> <span style="color: #339933;">=</span> r<span style="color: #339933;">-&gt;</span>y<span style="color: #339933;">;</span>
    rect.<span style="color: #202020;">width</span> <span style="color: #339933;">=</span> FTK_MIN<span style="color: #009900;">&#40;</span>bw<span style="color: #339933;">,</span> r<span style="color: #339933;">-&gt;</span>width<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    rect.<span style="color: #202020;">height</span> <span style="color: #339933;">=</span> FTK_MIN<span style="color: #009900;">&#40;</span>bh<span style="color: #339933;">,</span> r<span style="color: #339933;">-&gt;</span>height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>copy_from_data<span style="color: #009900;">&#40;</span>bitmap<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>bits<span style="color: #339933;">,</span> w<span style="color: #339933;">,</span> h<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>在运行configure时，用&#8211;with- backend=linux-x11:widh x height来指定宽度和高度。</p>
<p>2.ftk_display_mem</p>
<p>这是针对类似于framebuffer显示设备实现的基类，用于简化像Linux FrameBuffer，Sigma和ucosii(Windows模拟)的显示设备的实现。</p>
<p>创建函数：宽度、高度、格式和显存地址在创建时传入：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">FtkDisplay<span style="color: #339933;">*</span> ftk_display_mem_create<span style="color: #009900;">&#40;</span>FtkPixelFormat format<span style="color: #339933;">,</span>
    <span style="color: #993333;">int</span> width<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> height<span style="color: #339933;">,</span> <span style="color: #993333;">void</span><span style="color: #339933;">*</span> bits<span style="color: #339933;">,</span> FtkDestroy on_destroy<span style="color: #339933;">,</span> <span style="color: #993333;">void</span><span style="color: #339933;">*</span> ctx<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    FtkDisplay<span style="color: #339933;">*</span> thiz <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
&nbsp;
    thiz <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span>FTK_ZALLOC<span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>PrivInfo<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>thiz <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       thiz<span style="color: #339933;">-&gt;</span>update   <span style="color: #339933;">=</span> ftk_display_mem_update<span style="color: #339933;">;</span>
       thiz<span style="color: #339933;">-&gt;</span>width    <span style="color: #339933;">=</span> ftk_display_mem_width<span style="color: #339933;">;</span>
       thiz<span style="color: #339933;">-&gt;</span>height   <span style="color: #339933;">=</span> ftk_display_mem_height<span style="color: #339933;">;</span>
       thiz<span style="color: #339933;">-&gt;</span>snap     <span style="color: #339933;">=</span> ftk_display_mem_snap<span style="color: #339933;">;</span>
       thiz<span style="color: #339933;">-&gt;</span>destroy  <span style="color: #339933;">=</span> ftk_display_mem_destroy<span style="color: #339933;">;</span>
&nbsp;
       priv<span style="color: #339933;">-&gt;</span>bits <span style="color: #339933;">=</span> bits<span style="color: #339933;">;</span>
       priv<span style="color: #339933;">-&gt;</span>width <span style="color: #339933;">=</span> width<span style="color: #339933;">;</span>
       priv<span style="color: #339933;">-&gt;</span>height <span style="color: #339933;">=</span> height<span style="color: #339933;">;</span>
       priv<span style="color: #339933;">-&gt;</span>format <span style="color: #339933;">=</span> format<span style="color: #339933;">;</span>
       priv<span style="color: #339933;">-&gt;</span>on_destroy <span style="color: #339933;">=</span> on_destroy<span style="color: #339933;">;</span>
       priv<span style="color: #339933;">-&gt;</span>on_destroy_ctx <span style="color: #339933;">=</span> ctx<span style="color: #339933;">;</span>
&nbsp;
       <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span>format<span style="color: #009900;">&#41;</span>
       <span style="color: #009900;">&#123;</span>
           <span style="color: #b1b100;">case</span> FTK_PIXEL_RGB565<span style="color: #339933;">:</span>
           <span style="color: #009900;">&#123;</span>
               priv<span style="color: #339933;">-&gt;</span>copy_to_data   <span style="color: #339933;">=</span> ftk_bitmap_copy_to_data_rgb565<span style="color: #339933;">;</span>
               priv<span style="color: #339933;">-&gt;</span>copy_from_data <span style="color: #339933;">=</span> ftk_bitmap_copy_from_data_rgb565<span style="color: #339933;">;</span>
               <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
           <span style="color: #009900;">&#125;</span>
           <span style="color: #b1b100;">case</span> FTK_PIXEL_BGR24<span style="color: #339933;">:</span>
           <span style="color: #009900;">&#123;</span>
               priv<span style="color: #339933;">-&gt;</span>copy_to_data   <span style="color: #339933;">=</span> ftk_bitmap_copy_to_data_bgr24<span style="color: #339933;">;</span>
               priv<span style="color: #339933;">-&gt;</span>copy_from_data <span style="color: #339933;">=</span> ftk_bitmap_copy_from_data_bgr24<span style="color: #339933;">;</span>
               <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
           <span style="color: #009900;">&#125;</span>
           <span style="color: #b1b100;">case</span> FTK_PIXEL_BGRA32<span style="color: #339933;">:</span>
           <span style="color: #009900;">&#123;</span>
               priv<span style="color: #339933;">-&gt;</span>copy_to_data   <span style="color: #339933;">=</span> ftk_bitmap_copy_to_data_bgra32<span style="color: #339933;">;</span>
               priv<span style="color: #339933;">-&gt;</span>copy_from_data <span style="color: #339933;">=</span> ftk_bitmap_copy_from_data_bgra32<span style="color: #339933;">;</span>
               <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
           <span style="color: #009900;">&#125;</span>
           <span style="color: #b1b100;">case</span> FTK_PIXEL_RGBA32<span style="color: #339933;">:</span>
           <span style="color: #009900;">&#123;</span>
               priv<span style="color: #339933;">-&gt;</span>copy_to_data   <span style="color: #339933;">=</span> ftk_bitmap_copy_to_data_rgba32<span style="color: #339933;">;</span>
               priv<span style="color: #339933;">-&gt;</span>copy_from_data <span style="color: #339933;">=</span> ftk_bitmap_copy_from_data_rgba32<span style="color: #339933;">;</span>
               <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
           <span style="color: #009900;">&#125;</span>
           <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span>
           <span style="color: #009900;">&#123;</span>
               assert<span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #ff0000;">&quot;not supported framebuffer format.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
               <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
           <span style="color: #009900;">&#125;</span>
       <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> thiz<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这里根据格式选择适当的拷贝函数，用于把位图拷贝到显存，和从显存拷贝数据到位图。</p>
<p>获取宽度：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_display_mem_width<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>width<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>获取高度：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_display_mem_height<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>height<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>显示位图：这里只简单的调用copy_to_data。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> Ret ftk_display_mem_update<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #339933;">,</span> FtkBitmap<span style="color: #339933;">*</span> bitmap<span style="color: #339933;">,</span> FtkRect<span style="color: #339933;">*</span> rect<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> xoffset<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> yoffset<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> display_width  <span style="color: #339933;">=</span> priv<span style="color: #339933;">-&gt;</span>width<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> display_height <span style="color: #339933;">=</span> priv<span style="color: #339933;">-&gt;</span>height<span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ftk_logd<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s: ox=%d oy=%d (%d %d %d %d)<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> __func__<span style="color: #339933;">,</span> xoffset<span style="color: #339933;">,</span> yoffset<span style="color: #339933;">,</span>
       rect<span style="color: #339933;">-&gt;</span>x<span style="color: #339933;">,</span> rect<span style="color: #339933;">-&gt;</span>y<span style="color: #339933;">,</span> rect<span style="color: #339933;">-&gt;</span>width<span style="color: #339933;">,</span> rect<span style="color: #339933;">-&gt;</span>height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>copy_to_data<span style="color: #009900;">&#40;</span>bitmap<span style="color: #339933;">,</span> rect<span style="color: #339933;">,</span>
       priv<span style="color: #339933;">-&gt;</span>bits<span style="color: #339933;">,</span> xoffset<span style="color: #339933;">,</span> yoffset<span style="color: #339933;">,</span> display_width<span style="color: #339933;">,</span> display_height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>截取位图：这里只是简单的调用 copy_from_data。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> Ret ftk_display_mem_snap<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #339933;">,</span> FtkRect<span style="color: #339933;">*</span> r<span style="color: #339933;">,</span> FtkBitmap<span style="color: #339933;">*</span> bitmap<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    FtkRect rect <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> w <span style="color: #339933;">=</span> ftk_display_width<span style="color: #009900;">&#40;</span>thiz<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> h <span style="color: #339933;">=</span> ftk_display_height<span style="color: #009900;">&#40;</span>thiz<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> bw <span style="color: #339933;">=</span> ftk_bitmap_width<span style="color: #009900;">&#40;</span>bitmap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> bh <span style="color: #339933;">=</span> ftk_bitmap_height<span style="color: #009900;">&#40;</span>bitmap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    rect.<span style="color: #202020;">x</span> <span style="color: #339933;">=</span> r<span style="color: #339933;">-&gt;</span>x<span style="color: #339933;">;</span>
    rect.<span style="color: #202020;">y</span> <span style="color: #339933;">=</span> r<span style="color: #339933;">-&gt;</span>y<span style="color: #339933;">;</span>
    rect.<span style="color: #202020;">width</span> <span style="color: #339933;">=</span> FTK_MIN<span style="color: #009900;">&#40;</span>bw<span style="color: #339933;">,</span> r<span style="color: #339933;">-&gt;</span>width<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    rect.<span style="color: #202020;">height</span> <span style="color: #339933;">=</span> FTK_MIN<span style="color: #009900;">&#40;</span>bh<span style="color: #339933;">,</span> r<span style="color: #339933;">-&gt;</span>height<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>copy_from_data<span style="color: #009900;">&#40;</span>bitmap<span style="color: #339933;">,</span> priv<span style="color: #339933;">-&gt;</span>bits<span style="color: #339933;">,</span> w<span style="color: #339933;">,</span> h<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>rect<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>3.ftk_display_fb</p>
<p>这针对Linux FrameBuffer实现的显示设备，Linux FrameBuffer设备文件通常是/dev/fb0或/dev/graphic/fb0。</p>
<p>打开FrameBuffer并获取相关参数：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> fb_open<span style="color: #009900;">&#40;</span><span style="color: #993333;">struct</span> FbInfo <span style="color: #339933;">*</span>fb<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">char</span><span style="color: #339933;">*</span> fbfilename<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    fb<span style="color: #339933;">-&gt;</span>fd <span style="color: #339933;">=</span> open<span style="color: #009900;">&#40;</span>fbfilename<span style="color: #339933;">,</span> O_RDWR<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>fb<span style="color: #339933;">-&gt;</span>fd <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ioctl<span style="color: #009900;">&#40;</span>fb<span style="color: #339933;">-&gt;</span>fd<span style="color: #339933;">,</span> FBIOGET_FSCREENINFO<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>fb<span style="color: #339933;">-&gt;</span>fi<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
       <span style="color: #b1b100;">goto</span> fail<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ioctl<span style="color: #009900;">&#40;</span>fb<span style="color: #339933;">-&gt;</span>fd<span style="color: #339933;">,</span> FBIOGET_VSCREENINFO<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>fb<span style="color: #339933;">-&gt;</span>vi<span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
       <span style="color: #b1b100;">goto</span> fail<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #339933;">#ifdef FTK_FB_NOMMAP</span>
    <span style="color: #666666; font-style: italic;">//uclinux doesn't support MAP_SHARED or MAP_PRIVATE with PROT_WRITE, so no mmap at all is simpler</span>
    fb<span style="color: #339933;">-&gt;</span>bits <span style="color: #339933;">=</span> fb<span style="color: #339933;">-&gt;</span>fi.<span style="color: #202020;">smem_start</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#else</span>
    fb<span style="color: #339933;">-&gt;</span>bits <span style="color: #339933;">=</span> mmap<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> fb_size<span style="color: #009900;">&#40;</span>fb<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> PROT_READ <span style="color: #339933;">|</span> PROT_WRITE<span style="color: #339933;">,</span> MAP_SHARED<span style="color: #339933;">,</span> fb<span style="color: #339933;">-&gt;</span>fd<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">#endif</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>然后调用ftk_display_mem去创建显示设备：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">   thiz <span style="color: #339933;">=</span> ftk_display_mem_create<span style="color: #009900;">&#40;</span>format<span style="color: #339933;">,</span> fb<span style="color: #339933;">-&gt;</span>vi.<span style="color: #202020;">xres</span><span style="color: #339933;">,</span> fb<span style="color: #339933;">-&gt;</span>vi.<span style="color: #202020;">yres</span><span style="color: #339933;">,</span>
           fb<span style="color: #339933;">-&gt;</span>bits<span style="color: #339933;">,</span> fb_close<span style="color: #339933;">,</span> fb<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>对于sigma和ucosii(Windows模拟)实现的显示设备也很简单，这里就不再多说了。</p>
<p>4.ftk_display_rotate</p>
<p>这并不是针对某种物理显示设备的实现。而是利用装饰模式，不改变显示设备对象的接口，让显示设备具有屏幕旋转的功能。它可以对不同的显示设备进行装饰，所以只需要实现一次即可。</p>
<p>创建：传入一个FtkDisplay，返回新的一个 FtkDisplay，这是装饰模式的典型特征。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">FtkDisplay<span style="color: #339933;">*</span> ftk_display_rotate_create<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> display<span style="color: #339933;">,</span> FtkRotate rotate<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    FtkDisplay<span style="color: #339933;">*</span> thiz <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>display <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    thiz <span style="color: #339933;">=</span> FTK_ZALLOC<span style="color: #009900;">&#40;</span><span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>PrivInfo<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>thiz <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
       priv<span style="color: #339933;">-&gt;</span>display <span style="color: #339933;">=</span> display<span style="color: #339933;">;</span>
       thiz<span style="color: #339933;">-&gt;</span>width   <span style="color: #339933;">=</span> ftk_display_rotate_width<span style="color: #339933;">;</span>
       thiz<span style="color: #339933;">-&gt;</span>height  <span style="color: #339933;">=</span> ftk_display_rotate_height<span style="color: #339933;">;</span>
       thiz<span style="color: #339933;">-&gt;</span>destroy <span style="color: #339933;">=</span> ftk_display_rotate_destroy<span style="color: #339933;">;</span>
&nbsp;
       ftk_display_set_rotate<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> rotate<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> thiz<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>获取宽度：根据旋转角度决定返回高度还是宽度。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_display_rotate_width<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>rotate <span style="color: #339933;">==</span> FTK_ROTATE_0 <span style="color: #339933;">||</span> priv<span style="color: #339933;">-&gt;</span>rotate <span style="color: #339933;">==</span> FTK_ROTATE_180<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span>
       ftk_display_width<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> ftk_display_height<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>获取高度：根据旋转角度决定返回高度还是宽度。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_display_rotate_height<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>rotate <span style="color: #339933;">!=</span> FTK_ROTATE_0 <span style="color: #339933;">&amp;&amp;</span> priv<span style="color: #339933;">-&gt;</span>rotate <span style="color: #339933;">!=</span> FTK_ROTATE_180<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span>
       ftk_display_width<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> ftk_display_height<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>设置旋转的角度：根据角度选择适当的变换函数，这里用到了策略模式。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">const</span> FtkDisplayUpdate updates<span style="color: #009900;">&#91;</span>FTK_ROTATE_NR<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>
<span style="color: #009900;">&#123;</span>
    ftk_display_rotate_update_0<span style="color: #339933;">,</span>
    ftk_display_rotate_update_90<span style="color: #339933;">,</span>
    ftk_display_rotate_update_180<span style="color: #339933;">,</span>
    ftk_display_rotate_update_270
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">const</span> FtkDisplaySnap snaps<span style="color: #009900;">&#91;</span>FTK_ROTATE_NR<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>
<span style="color: #009900;">&#123;</span>
    ftk_display_rotate_snap_0<span style="color: #339933;">,</span>
    ftk_display_rotate_snap_90<span style="color: #339933;">,</span>
    ftk_display_rotate_snap_180<span style="color: #339933;">,</span>
    ftk_display_rotate_snap_270
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
Ret ftk_display_set_rotate<span style="color: #009900;">&#40;</span>FtkDisplay<span style="color: #339933;">*</span> thiz<span style="color: #339933;">,</span> FtkRotate rotate<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL <span style="color: #339933;">&amp;&amp;</span> priv<span style="color: #339933;">-&gt;</span>display <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">-&gt;</span>destroy <span style="color: #339933;">==</span> ftk_display_rotate_destroy<span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>rotate <span style="color: #339933;">==</span> rotate <span style="color: #339933;">&amp;&amp;</span> priv<span style="color: #339933;">-&gt;</span>bitmap <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">return</span> RET_OK<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    priv<span style="color: #339933;">-&gt;</span>rotate <span style="color: #339933;">=</span> rotate<span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>bitmap <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       ftk_bitmap_unref<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>bitmap<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       priv<span style="color: #339933;">-&gt;</span>bitmap <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>rotate <span style="color: #339933;">!=</span> FTK_ROTATE_0<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       FtkColor bg <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
       memset<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>bg<span style="color: #339933;">,</span> <span style="color: #208080;">0xff</span><span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span><span style="color: #009900;">&#40;</span>bg<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       priv<span style="color: #339933;">-&gt;</span>bitmap <span style="color: #339933;">=</span> ftk_bitmap_create<span style="color: #009900;">&#40;</span>ftk_display_width<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>        ftk_display_height<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>display<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> bg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    thiz<span style="color: #339933;">-&gt;</span>snap <span style="color: #339933;">=</span> snaps<span style="color: #009900;">&#91;</span>rotate<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    thiz<span style="color: #339933;">-&gt;</span>update <span style="color: #339933;">=</span> updates<span style="color: #009900;">&#91;</span>rotate<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> RET_OK<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>(具体算法请参考源代码)。</p>
<p>另外FtkDisplay还利用观察者模式实现了更新通知功能，目前主要用在更新sprite(光标）上，当屏幕有更新时，通知sprite重新截图。以后可以还用于VNC的实现，当屏幕有更新时通知客户端更新。</p>
<p>    * ftk_display_reg_update_listener 注册监听者。<br />
    * ftk_display_unreg_update_listener 注销监听者。<br />
    * ftk_display_update_and_notify 更新屏幕并通知监听者。</p>
<p>其它一些FtkDisplay的实现这就不多说了，有兴趣的朋友可以阅读源代码。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1544/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI FTK设计与实现-事件源(FtkSource)</title>
		<link>http://www.limodev.cn/blog/archives/1540</link>
		<comments>http://www.limodev.cn/blog/archives/1540#comments</comments>
		<pubDate>Fri, 09 Jul 2010 03:07:40 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1540</guid>
		<description><![CDATA[在《主循环》一节中， 我们介绍了MainLoop 处理各个事件源的方法，它在事件源上等待事件发生，然后调用事件源的处理函数去处理事件。事件源(FtkSource)是对事件来源的一种抽象，事件的来源可能是一个输入设备(如键盘和触摸屏)，可能是一个定时器，也可能是一个网络套接字或管道。总之，只要实现FtkSource要求的接口，就可以让 MainLoop来处理了。 FtkSource 要求实现下列接口函数： * ftk_source_get_fd 用来获取文件描述符，这个文件描述符不一定是真正的文件描述符，只要是能MainLoop挂在上面等待的句柄(Handle)即可。 * ftk_source_check 用来检查事件源要求等待的时间。-1表示不关心等待时间。0表示要马上就有事件发生，正数表示在指定的时间内将有事件发生。 * ftk_source_dispatch 用来处理事件，每个事件源都有自己的处理函数，这样可以简化程序的实现。 目前FTK内部使用的事件源主要有： 1.ftk_source_input(.c/.h) 在Linux下，输入设备文件都在/dev /input/下，并用一致的事件结构(input_event)将事件上报给应用程序，ftk_source_input是针对这些设备文件实现的事件源。 由于是从设备文件读取输入事件，那主循环可以挂在这些设备文件上等待事件发生。所以ftk_source_get_fd只要返回文件描述符，而 ftk_source_check返回-1即可。 static int ftk_source_input_get_fd&#40;FtkSource* thiz&#41; &#123; DECL_PRIV&#40;thiz, priv&#41;; &#160; return priv-&#62;fd; &#125; &#160; static int ftk_source_input_check&#40;FtkSource* thiz&#41; &#123; return -1; &#125; ftk_source_dispatch中读取事件(input_event)，将它转换成FTK的事件结构，然后通过将事件分发(调用 ftk_wnd_manager_queue_event)出去。 键值的映射是放在表 s_key_mapp中的： static unsigned short s_key_map&#91;0x100&#93; = &#123; &#91;KEY_1&#93; = FTK_KEY_1, &#91;KEY_2&#93; [...]]]></description>
			<content:encoded><![CDATA[<p>在《主循环》一节中， 我们介绍了MainLoop 处理各个事件源的方法，它在事件源上等待事件发生，然后调用事件源的处理函数去处理事件。事件源(FtkSource)是对事件来源的一种抽象，事件的来源可能是一个输入设备(如键盘和触摸屏)，可能是一个定时器，也可能是一个网络套接字或管道。总之，只要实现FtkSource要求的接口，就可以让 MainLoop来处理了。<span id="more-1540"></span></p>
<p>FtkSource 要求实现下列接口函数：</p>
<p>* ftk_source_get_fd 用来获取文件描述符，这个文件描述符不一定是真正的文件描述符，只要是能MainLoop挂在上面等待的句柄(Handle)即可。</p>
<p>* ftk_source_check 用来检查事件源要求等待的时间。-1表示不关心等待时间。0表示要马上就有事件发生，正数表示在指定的时间内将有事件发生。</p>
<p>* ftk_source_dispatch 用来处理事件，每个事件源都有自己的处理函数，这样可以简化程序的实现。</p>
<p>目前FTK内部使用的事件源主要有：</p>
<p>1.ftk_source_input(.c/.h)</p>
<p>在Linux下，输入设备文件都在/dev /input/下，并用一致的事件结构(input_event)将事件上报给应用程序，ftk_source_input是针对这些设备文件实现的事件源。</p>
<p>由于是从设备文件读取输入事件，那主循环可以挂在这些设备文件上等待事件发生。所以ftk_source_get_fd只要返回文件描述符，而 ftk_source_check返回-1即可。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_input_get_fd<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>fd<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_input_check<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>ftk_source_dispatch中读取事件(input_event)，将它转换成FTK的事件结构，然后通过将事件分发(调用 ftk_wnd_manager_queue_event)出去。</p>
<p>键值的映射是放在表 s_key_mapp中的：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">unsigned</span> <span style="color: #993333;">short</span> s_key_map<span style="color: #009900;">&#91;</span><span style="color: #208080;">0x100</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #009900;">&#91;</span>KEY_1<span style="color: #009900;">&#93;</span>           <span style="color: #339933;">=</span>  FTK_KEY_1<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>KEY_2<span style="color: #009900;">&#93;</span>           <span style="color: #339933;">=</span>  FTK_KEY_2<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>KEY_3<span style="color: #009900;">&#93;</span>           <span style="color: #339933;">=</span>  FTK_KEY_3<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>KEY_4<span style="color: #009900;">&#93;</span>           <span style="color: #339933;">=</span>  FTK_KEY_4<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>KEY_5<span style="color: #009900;">&#93;</span>           <span style="color: #339933;">=</span>  FTK_KEY_5<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>KEY_6<span style="color: #009900;">&#93;</span>           <span style="color: #339933;">=</span>  FTK_KEY_6<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>KEY_7<span style="color: #009900;">&#93;</span>           <span style="color: #339933;">=</span>  FTK_KEY_7<span style="color: #339933;">,</span>
   ...
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>如果有特殊键值或其它需求，修改这个结构即可。</p>
<p>2.ftk_source_dfb(.c/.h)</p>
<p>FTK可以用DirectFB作为 backend，ftk_source_dfb是针对DirectFB输入事件实现的事件源。DirectFB可以通从EventBuffer直接读取，也可以从EventBuffer获取一个管道的文件描述符，然后从这个管道读取事件。为了方便，我们使用后者来实现ftk_source_dfb，主循环可以挂在这个文件描述符上等待事件。所以ftk_source_get_fd只要返回文件描述符，而 ftk_source_check返回-1即可。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span>  ftk_source_dfb_get_fd<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>fd<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span>  ftk_source_dfb_check<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>ftk_source_dispatch中读取事件(DFBEvent)，将它转换成FTK的事件结构，然后通过将事件分发(调用 ftk_wnd_manager_queue_event)出去。</p>
<p>键值的映射是放在表 s_key_mapp中的：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">const</span> <span style="color: #993333;">int</span> s_key_map<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #009900;">&#91;</span>DIKI_A<span style="color: #339933;">-</span>DIKI_UNKNOWN<span style="color: #009900;">&#93;</span>              <span style="color: #339933;">=</span>  FTK_KEY_a<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>DIKI_B<span style="color: #339933;">-</span>DIKI_UNKNOWN<span style="color: #009900;">&#93;</span>              <span style="color: #339933;">=</span>  FTK_KEY_b<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>DIKI_C<span style="color: #339933;">-</span>DIKI_UNKNOWN<span style="color: #009900;">&#93;</span>              <span style="color: #339933;">=</span>  FTK_KEY_c<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>DIKI_D<span style="color: #339933;">-</span>DIKI_UNKNOWN<span style="color: #009900;">&#93;</span>              <span style="color: #339933;">=</span>  FTK_KEY_d<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>DIKI_E<span style="color: #339933;">-</span>DIKI_UNKNOWN<span style="color: #009900;">&#93;</span>              <span style="color: #339933;">=</span>  FTK_KEY_e<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>DIKI_F<span style="color: #339933;">-</span>DIKI_UNKNOWN<span style="color: #009900;">&#93;</span>              <span style="color: #339933;">=</span>  FTK_KEY_f<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>DIKI_G<span style="color: #339933;">-</span>DIKI_UNKNOWN<span style="color: #009900;">&#93;</span>              <span style="color: #339933;">=</span>  FTK_KEY_g<span style="color: #339933;">,</span>
    <span style="color: #009900;">&#91;</span>DIKI_H<span style="color: #339933;">-</span>DIKI_UNKNOWN<span style="color: #009900;">&#93;</span>              <span style="color: #339933;">=</span>  FTK_KEY_h<span style="color: #339933;">,</span>
   ...
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></pre></div></div>

<p>如果有特殊键值或其它需求，修改这个结构即可。</p>
<p>3.ftk_source_tslib(.c/.h)</p>
<p>对于电阻式的触摸屏，虽然通常在Linux下也是通过(/dev/input)下的设备文件上报事件的，但是需要对输入事件进行去抖、滤波和校正之后才能使用，tslib是专门做这些工作的，所以这时我们用tslib读取事件是更明智的选择。</p>
<p>tslib 提供了一个函数用于获取文件描述符，主循环可以挂在这个文件描述符上等待事件。所以ftk_source_get_fd只要返回文件描述符，而 ftk_source_check返回-1即可。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_tslib_get_fd<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL <span style="color: #339933;">&amp;&amp;</span> priv<span style="color: #339933;">-&gt;</span>ts <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ts_fd<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>ts<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_tslib_check<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>ftk_source_dispatch中读取事件(ts_sample)，将它转换成FTK的事件结构，然后通过将事件分发(调用 ftk_wnd_manager_queue_event)出去。</p>
<p>4.ftk_source_primary(.c/.h)</p>
<p>ftk_source_primary的地位比较特别，相当于其它GUI中的事件队列。</p>
<p>ftk_source_primary 使用管道来实现队列先进先出(FIFO)的特性，这样可以避免引入互斥机制来保护队列，管道有自己的文件描述符，主循环可以挂在这个文件描述符上等待事件。所以ftk_source_get_fd只要返回文件描述符，而 ftk_source_check返回-1即可。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_primary_get_fd<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ftk_pipe_get_read_handle<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>pipe<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_primary_check<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>ftk_source_primary_dispatch 函数中对FTK_EVT_ADD_SOURCE/FTK_EVT_REMOVE_SOURCE两个事件做了特殊处理，用于增加和移除事件源，对于其余事件只是调用窗口管理器的事件分发函数(ftk_wnd_manager_default_dispatch_event)去处理事件。</p>
<p>ftk_source_primary提供了 ftk_source_queue_event用于向管道中写入事件，向管道中写入事件当于其它GUI向事件队列中增加事件。</p>
<p>5.ftk_source_timer</p>
<p>ftk_source_timer主要用于定时执行一个动作，比如闪动光标和更新时间。它与前面的事件源不同的是，它没有相应的文件描述符，主循环无法通过挂在文件描述符上来等待事件的发生。所以 ftk_source_get_fd始终返回-1：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_timer_get_fd<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>ftk_source_check返回下一次事件发生的时间间隔，告诉MainLoop 必须在这个时刻唤醒，并执行处理函数：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_timer_check<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> t <span style="color: #339933;">=</span> priv<span style="color: #339933;">-&gt;</span>next_time <span style="color: #339933;">-</span> ftk_get_relative_time<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    t <span style="color: #339933;">=</span> t <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">?</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">:</span> t<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> t<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>ftk_source_timer_dispatch 的实现很简单，它计算下一次timer的时间，然后调用用户设置的回调函数。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">tatic Ret ftk_source_timer_dispatch<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    Ret ret <span style="color: #339933;">=</span> RET_FAIL<span style="color: #339933;">;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>action <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> RET_REMOVE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">-&gt;</span>disable <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       ftk_source_timer_calc_timer<span style="color: #009900;">&#40;</span>priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       <span style="color: #b1b100;">return</span> RET_OK<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    ret <span style="color: #339933;">=</span> priv<span style="color: #339933;">-&gt;</span>action<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>user_data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ftk_source_timer_calc_timer<span style="color: #009900;">&#40;</span>priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>5.ftk_source_idle(.c/.h)</p>
<p>idle的主要用途有：</p>
<p>    * 在空闲时执行低优先级任务。有的任务优先级比较低，但费耗时间相对较长，比如屏幕刷新等操作。如果为了避免它阻碍当前操作太久，此时我们把它放到idle里去做。</p>
<p>    * 将同步操作异步化。有的操作你可能不希望它在当前的处理函数中同步执行，这时也可以用idle来异步化 ，让它在后面的dispatch中执行。</p>
<p>    * 串行化对GUI的访问。在FTK中，出于效率的考虑， GUI对象是没有加锁保护的，也就是只有GUI线程能访问这些对象。如果其它线程要访问GUI对象，此时就需要用idle来串行化了。idle是GUI线程(主线程)中执行的，所以它能访问GUI对象。</p>
<p>idle的实现有点timeout为0的定时器，把它独立出来主要为了概念上更清楚一点：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_idle_get_fd<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">int</span> ftk_source_idle_check<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>ftk_source_idle_dispatch 只是简单的调用用户设置的回调函数。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> Ret ftk_source_idle_dispatch<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    return_val_if_fail<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>action <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> RET_REMOVE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">-&gt;</span>disable <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">return</span> RET_OK<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> priv<span style="color: #339933;">-&gt;</span>action<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>user_data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>FTK中还有其它一些事件源，比如针对X11模拟运行的事件源，它们的实现都是类似的，这里就不再多说了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1540/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>用Android模拟器运行FTK</title>
		<link>http://www.limodev.cn/blog/archives/1537</link>
		<comments>http://www.limodev.cn/blog/archives/1537#comments</comments>
		<pubDate>Mon, 05 Jul 2010 02:24:38 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1537</guid>
		<description><![CDATA[用Android模拟器运行FTK 以前写过一篇文章介绍如何在Androidr模拟器上运行FTK（http://www.limodev.cn/blog/archives/1400），那种方法有点别扭，而且要下载Android 的源代码才能编译。最近几个开发板都坏了，所以上周末研究了一下Android模拟器，自己生成文件系统，只是利用Android的模拟器来运行FTK。 Android的模拟器是基于qemu的，个人感觉qemu不好用，除了用Openmoko做的模拟器外，我还没成功用qemu来模拟运行过arm linux。Android在qemu做了不少人性化的工作，用起来比较方便。 0.请参考网上的方法安装Android SDK。 1.生成自己的init程序。 创建几个基本目录。 int init_dirs&#40;void&#41; &#123; umask&#40;0&#41;; mkdir&#40;&#34;/dev&#34;, 0755&#41;; mkdir&#40;&#34;/system&#34;, 0777&#41;; mkdir&#40;&#34;/dev/block&#34;, 0755&#41;; &#160; return 0; &#125; 创建MTD设备的结点。 int init_dev_nodes&#40;void&#41; &#123; int ret = 0; ret = mknod&#40;&#34;/dev/block/mtdblock0&#34;, 0755&#124;S_IFBLK, makedev&#40;31, 0&#41;&#41;; printf&#40;&#34;mknod /dev/block/mtdblock0 ret = %d errno=%d\n&#34;, ret, errno&#41;; &#160; return 0; &#125; 加载system.img 分区。 int mount_filesystem&#40;void&#41; &#123; int [...]]]></description>
			<content:encoded><![CDATA[<p>用Android模拟器运行FTK</p>
<p>以前写过一篇文章介绍如何在Androidr模拟器上运行FTK（http://www.limodev.cn/blog/archives/1400），那种方法有点别扭，而且要下载Android 的源代码才能编译。最近几个开发板都坏了，所以上周末研究了一下Android模拟器，自己生成文件系统，只是利用Android的模拟器来运行FTK。</p>
<p>Android的模拟器是基于qemu的，个人感觉qemu不好用，除了用Openmoko做的模拟器外，我还没成功用qemu来模拟运行过arm linux。Android在qemu做了不少人性化的工作，用起来比较方便。</p>
<p>0.请参考网上的方法安装Android SDK。</p>
<p>1.生成自己的init程序。</p>
<p>创建几个基本目录。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> init_dirs<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    umask<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    mkdir<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev&quot;</span><span style="color: #339933;">,</span> <span style="color: #208080;">0755</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    mkdir<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/system&quot;</span><span style="color: #339933;">,</span> <span style="color: #208080;">0777</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    mkdir<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/block&quot;</span><span style="color: #339933;">,</span> <span style="color: #208080;">0755</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>创建MTD设备的结点。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> init_dev_nodes<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> ret <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    ret <span style="color: #339933;">=</span> mknod<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/block/mtdblock0&quot;</span><span style="color: #339933;">,</span> <span style="color: #208080;">0755</span><span style="color: #339933;">|</span>S_IFBLK<span style="color: #339933;">,</span> makedev<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">31</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;mknod /dev/block/mtdblock0 ret = %d errno=%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> ret<span style="color: #339933;">,</span> errno<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>加载system.img 分区。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> mount_filesystem<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> ret <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    ret <span style="color: #339933;">=</span> mount<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/dev/block/mtdblock0&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;/system&quot;</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;yaffs2&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;mount /dev/block/mtdblock0 ret = %d errno=%d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> ret<span style="color: #339933;">,</span> errno<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>运行FTK的桌面。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> startup_desktop<span style="color: #009900;">&#40;</span><span style="color: #993333;">const</span> <span style="color: #993333;">char</span><span style="color: #339933;">*</span> name<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">struct</span> stat st <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> ret <span style="color: #339933;">=</span> stat<span style="color: #009900;">&#40;</span>name<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>st<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">!=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">return</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;starting the second init: %s.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       ret <span style="color: #339933;">=</span> execl<span style="color: #009900;">&#40;</span>name<span style="color: #339933;">,</span> name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> switch_root<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> ret <span style="color: #339933;">=</span> chroot<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/system&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ret <span style="color: #339933;">=</span> startup_desktop<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;/opt/bin/desktop&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ret<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>2.生成ramdisk.img</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">rm <span style="color: #339933;">-</span>rf ramdisk
mkdir ramdisk
&nbsp;
cd init <span style="color: #339933;">&amp;&amp;</span> make<span style="color: #339933;">;</span> cd <span style="color: #339933;">-</span> <span style="color: #339933;">&gt;/</span>dev<span style="color: #339933;">/</span><span style="color: #000000; font-weight: bold;">null</span>
&nbsp;
echo <span style="color: #ff0000;">&quot;Generating ramdisk...&quot;</span>
&nbsp;
cd ramdisk <span style="color: #339933;">&amp;&amp;</span> find . <span style="color: #339933;">|</span> cpio <span style="color: #339933;">-</span>c <span style="color: #339933;">-</span>o <span style="color: #339933;">&gt;</span> ..<span style="color: #339933;">/</span>initrd<span style="color: #339933;">;</span> cd <span style="color: #339933;">-</span> <span style="color: #339933;">&gt;/</span>dev<span style="color: #339933;">/</span><span style="color: #000000; font-weight: bold;">null</span>
gzip initrd <span style="color: #339933;">&amp;&amp;</span> mv initrd.<span style="color: #202020;">gz</span> ramdisk.<span style="color: #202020;">img</span></pre></div></div>

<p>3.生成system.img</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#91;</span> <span style="color: #339933;">!</span> <span style="color: #339933;">-</span>d rootfs <span style="color: #009900;">&#93;</span>
then
    tar xf rootfs.<span style="color: #202020;">tar</span>.<span style="color: #202020;">gz</span>
fi</pre></div></div>

<p>(在这里解压编译好的FTK（ftk-dist.tar.gz）到rootfsrts)</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">.<span style="color: #339933;">/</span>mkyaffs2image rootfs system.<span style="color: #202020;">img</span></pre></div></div>

<p>4.拷贝生成的ramdisk.img system.img到SDK目录里。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">echo <span style="color: #ff0000;">&quot;Copying files...&quot;</span>
<span style="color: #b1b100;">for</span> f in ramdisk.<span style="color: #202020;">img</span> system.<span style="color: #202020;">img</span>
<span style="color: #b1b100;">do</span>
    echo <span style="color: #ff0000;">&quot;  $f --&gt; $ADNROID_SDK_IMAGES_DIR&quot;</span>
    mv <span style="color: #339933;">-</span>f $f $ADNROID_SDK_IMAGES_DIR
done</pre></div></div>

<p><img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/android-ftk.png" alt="android-ftk" /><br />
完整源代码和脚本请到这里下载：<br />
svn checkout http://ftke.googlecode.com/svn/trunk/android-ftk-emu android-ftk-emu</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1537/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《系统程序员成长计划》示例代码</title>
		<link>http://www.limodev.cn/blog/archives/1533</link>
		<comments>http://www.limodev.cn/blog/archives/1533#comments</comments>
		<pubDate>Wed, 14 Apr 2010 14:05:00 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[系统程序员成长计划]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1533</guid>
		<description><![CDATA[在googlecode上建立了一个项目：http://code.google.com/p/spexamples/ 用来维护《系统程序员成长计划》示例代码。 无论是示例代码还是书中的BUG，请大家Report到http://code.google.com/p/spexamples/issues/list。 如果以后有机会出新版本，将有样书赠送给第一个发现BUG的朋友。 谢谢大家支持。]]></description>
			<content:encoded><![CDATA[<p>在googlecode上建立了一个项目：<a href="http://code.google.com/p/spexamples/">http://code.google.com/p/spexamples/</a> 用来维护《系统程序员成长计划》示例代码。</p>
<p>无论是示例代码还是书中的BUG，请大家Report到<a href="http://code.google.com/p/spexamples/issues/list">http://code.google.com/p/spexamples/issues/list</a>。<span id="more-1533"></span></p>
<p>如果以后有机会出新版本，将有样书赠送给第一个发现BUG的朋友。</p>
<p>谢谢大家支持。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1533/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>《系统程序员成长计划》成长过程</title>
		<link>http://www.limodev.cn/blog/archives/1531</link>
		<comments>http://www.limodev.cn/blog/archives/1531#comments</comments>
		<pubDate>Mon, 12 Apr 2010 12:38:28 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[系统程序员成长计划]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1531</guid>
		<description><![CDATA[《系统程序员成长计划》的起源应该追溯到六年前了。04年我进入恒基伟业深圳研发部，参与商务通隐形手机开发。在此之前我是做服务器软件开发的，对嵌入式软件开发非常好奇，所以想方设法进入这个行业。恒基伟业在嵌入式方面的实力也是相当高的，很多在消费类设备方面的开发高手都有在恒基伟业工作过的经验。原以为做嵌入式开发的程序员都是非常牛的人，动不动都是能写上上万行汇编语言。真正进入这个行业之后，才知道牛人毕竟是少数，大部分人都和我一样是普通的程序员。 过了几个月，我当了小组长，手下带了几位同事。有刚毕业的，有工作两年的，也有工作经验和我差不多的。有次我让一位同事写一个小程序，过了好几天他还没有写完。和他讨论了一会儿后，才知道他写的程序动不动就死掉，查了几天没有查出原因来。由于我以前做过两年全职的调试工作，看了一下他的代码，马上发现问题所在：指针声明之后，没有指向任何有效的内存，就直接使用了！ 后来和他们交流多了，才发现有的同事工作几年之后，连一些编程的基本技能都没有掌握，代码写得乱七糟八的。这些代码集成到项目中后，产品越来越不稳定，整个项目慢慢失去控制。那个项目后来BUG总数超过了10000个，当时大家都知道在做一件不可能完成的任务，士气变得非常低落。经历那一段非常郁闷的时期之后，我更深刻的体会到高素质的程序员才是软件开发成功的关键。于是我开始对手下的同事进行培训，把一些我认为重要的知识和方法教给他们。虽然没有收到预期的效果，不过积累了一些素材。 05年我跟着现在的上司进入鼎智通信，我还是小组长，带了几个新手。我根据前面的经验制定了一个培训计划，我的上司看了之后觉得不错，就在软件部推广。下面是当时我发在博客上的培训计划： 学习的方式： 对于基础性知识，指定几本教材，大家轮流学习，学习完成后给其他讲解。对于较难的知识，由我或者请其他有经验的人讲解。集中学习时间定在周三晚上。 第一阶段： 目标：熟悉常见的算法和调试方法，培养良好的编程风格，从而提高编程 能力。 时间：8周 内容： 1. 编程规范 2. 双向链表 3. 调试方法与调式工具的使用 4. 动态数组 5. 快速排序/归并排 序/堆排序/二分查找 6. 状态机 7. 下推自动机 8. 嵌入式软件开发 9. Unicode基本知识 第二阶段： 目标: 学习如何阅读和改进别人的代 码。 时间: 4周 内容： 1. 代码阅读方法 2. 代码重构 第三阶段： 目标：自动测试 时间：2周 内容： 1. 测试理论 2. 常用的自动测试框架 第四阶段： 目标：软件设计和文档编写 时间：12周 内容： 1. 面向对象的设计与分析 [...]]]></description>
			<content:encoded><![CDATA[<p>《系统程序员成长计划》的起源应该追溯到六年前了。04年我进入恒基伟业深圳研发部，参与商务通隐形手机开发。在此之前我是做服务器软件开发的，对嵌入式软件开发非常好奇，所以想方设法进入这个行业。恒基伟业在嵌入式方面的实力也是相当高的，很多在消费类设备方面的开发高手都有在恒基伟业工作过的经验。原以为做嵌入式开发的程序员都是非常牛的人，动不动都是能写上上万行汇编语言。真正进入这个行业之后，才知道牛人毕竟是少数，大部分人都和我一样是普通的程序员。<span id="more-1531"></span></p>
<p>过了几个月，我当了小组长，手下带了几位同事。有刚毕业的，有工作两年的，也有工作经验和我差不多的。有次我让一位同事写一个小程序，过了好几天他还没有写完。和他讨论了一会儿后，才知道他写的程序动不动就死掉，查了几天没有查出原因来。由于我以前做过两年全职的调试工作，看了一下他的代码，马上发现问题所在：指针声明之后，没有指向任何有效的内存，就直接使用了！</p>
<p>后来和他们交流多了，才发现有的同事工作几年之后，连一些编程的基本技能都没有掌握，代码写得乱七糟八的。这些代码集成到项目中后，产品越来越不稳定，整个项目慢慢失去控制。那个项目后来BUG总数超过了10000个，当时大家都知道在做一件不可能完成的任务，士气变得非常低落。经历那一段非常郁闷的时期之后，我更深刻的体会到高素质的程序员才是软件开发成功的关键。于是我开始对手下的同事进行培训，把一些我认为重要的知识和方法教给他们。虽然没有收到预期的效果，不过积累了一些素材。</p>
<p>05年我跟着现在的上司进入鼎智通信，我还是小组长，带了几个新手。我根据前面的经验制定了一个培训计划，我的上司看了之后觉得不错，就在软件部推广。下面是当时我发在博客上的培训计划：</p>
<p>学习的方式：</p>
<p>对于基础性知识，指定几本教材，大家轮流学习，学习完成后给其他讲解。对于较难的知识，由我或者请其他有经验的人讲解。集中学习时间定在周三晚上。</p>
<p>第一阶段：</p>
<p>目标：熟悉常见的算法和调试方法，培养良好的编程风格，从而提高编程 能力。<br />
时间：8周<br />
内容：</p>
<p>   1. 编程规范<br />
   2. 双向链表<br />
   3. 调试方法与调式工具的使用<br />
   4. 动态数组<br />
   5. 快速排序/归并排 序/堆排序/二分查找<br />
   6. 状态机<br />
   7. 下推自动机<br />
   8. 嵌入式软件开发<br />
   9. Unicode基本知识</p>
<p>第二阶段：</p>
<p>目标: 学习如何阅读和改进别人的代 码。<br />
时间: 4周<br />
内容：<br />
   1. 代码阅读方法<br />
   2. 代码重构</p>
<p>第三阶段：</p>
<p>目标：自动测试<br />
时间：2周<br />
内容：<br />
   1. 测试理论<br />
   2. 常用的自动测试框架</p>
<p>第四阶段：</p>
<p>目标：软件设计和文档编写<br />
时间：12周<br />
内容：</p>
<p>   1. 面向对象的设计与分析<br />
   2. 契约式编程<br />
   3. 设计模式<br />
   4. 软件架构编档<br />
   5. 了解常见的软件过程: XP/RUP等</p>
<p>第五阶段：</p>
<p>目标：学习一种脚本语言，能自动化的工作尽量让计算机去做，从而提高 工作效率。</p>
<p>时间：4周<br />
内容：cygwin + bash 或者 python 或者 perl 或者vbscript。</p>
<p>第六阶段：</p>
<p>目标：综合应用所学的知识，完成一个模块的设计、编程、测试。<br />
时间：4周<br />
内容：待定</p>
<p>这个培训坚持了半年，收到一些效果，但是不够理想。主要原因是这个培训计划追求大而全，加上大家工作很忙，还没有消化就进入了下一个阶段。现在来看，这个计划完全可以作为一个程序员的三年学习计划了。</p>
<p>05年下半年，Broncho团队成立。我改为手把手的培训方式，通过代码评审等方式，发现新手犯的错误，然后纠正他，并把一些典型的错误统一讲解。慢慢的积累了典型错误和问题的素材，后来我开始思考：能不能搞一系列的题目，让新手把他们该犯的错误犯一遍，让这些典型的错误在他们正式工作之前就被纠正了呢？</p>
<p>这些题目要有足够的挑战，又不能让人望而生畏。要解决这个难题不容易，记得当时《C++沉思录》给了我一些启示：用一个好的程序的演化过程，逐步深入的学习各种基本的技术和方法。于是有了第一章双向链表演化的雏形，第二章写得又快又好的秘诀，则是我多年来一直在思考的。</p>
<p>07年下半年正式在Broncho团队起用这套培训课程，记得Broncho团队的吴松是第一位参加这个培训的同事。经过一年多时间，前前后后有十多位同事的参与，这套培训课程逐渐完善起来，到现在Broncho团队仍然在使用。</p>
<p>08年十月份开始把这些培训资料整理成文字，并在我的博客上发布。这是一项艰苦的工作，虽然这些内容在脑子里都过了几十遍了，但写出来的时候，要讲清楚还是不容易的。一年多时间，经过读者的建议，又做了些完善。</p>
<p>09年七月底完稿，并确定由人民邮电出版社旗下的图灵出版社出版。我一直强调图书的质量，并多次跟出版社要求，我不要稿费甚至自己拿钱出来补贴工作人员都可以，但是一定要保证图书的质量。出版的过程中出现了一些波折，到今年三月本书才终于与读者见面。</p>
<p>另外我解释一下，书上为什么没有推荐序之类的东西。在出版之前，一些热心的朋友主动说帮我写或者请名人写推荐序，我都一一婉拒了。我的理由很简单，那些“名人”都没有仔细读过我的书，帮忙写推荐只是纯粹的吹捧，都是虚假的，对读者不负责的。我希望更多的读者读本书，但是决不能用这种手段来欺骗读者。只有真正的读者才有资格对书做出评论，如果有机会出第二版，我会请读者写推荐序的。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1531/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>FTK移植指南(初稿）</title>
		<link>http://www.limodev.cn/blog/archives/1529</link>
		<comments>http://www.limodev.cn/blog/archives/1529#comments</comments>
		<pubDate>Wed, 07 Apr 2010 13:13:16 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1529</guid>
		<description><![CDATA[1.内存分配 要求：实现malloc/realloc/free三个函数，函数原型和标准C一致。或者实现FtkAllocator接口。 参考：ftk_allocator_default.c 2.文件操作 要求：实现FtkMmap接口。libpng和libjpeg还要求实现标准C的FILE(也可以用自己的解码器)。 参考：os/linux/ftk_mmap_linux.c 3.显示设备 要求：实现FtkDisplay接口，对于基本framebuffer的显示方式，可以利用ftk_display_mem来实现。 参考：backend/fb/ftk_display_fb.c 4.输入设备 要求：输入事件如果在主线程中读取，则要实现FtkSource接口。输入事件如果在单独线程中读取，可以用ftk_wnd_manager_queue_event来分发。 参考：backend/fb/ftk_source_input.c 注意：按键需要映射成FTK的键值。 5.管道 要求：实现FtkPipe接口。 参考：ftk_pipe_socket.c 6.图形解码 如果有自定义的图像格式或优化过的解码器，请实现ftk_image_decoder接口。 7.主函数 主函数可以是main或者ftk_main，由宏FTK_HAS_MAIN决定。 8.主循环 要求：实现FtkMainLoop 参考：ftk_main_loop_select.c 对于RTOS，FTK通常只是需要ftk_source_primary一个管道，所有输入事件都通过它来串行化，所以实现MainLoop时挂在这个管道上即可。 9.辅助函数和宏 usleep ftk_strncpy ftk_snprintf ftk_vsnprintf ftk_getcwd ftk_sscanf ftk_get_relative_time FTK_ROOT_DIR FTK_FONT DATA_DIR LOCAL_DATA_DIR FTK_DATA_ROOT TESTDATA_DIR 参考：os/windows/ftk_win32.h 10.编译系统 对于兼容gcc的编译器，尽量使用automake来管理。对于不能兼容gcc的编译器，请把相关工程文件放到src/compiler下。]]></description>
			<content:encoded><![CDATA[<p>1.内存分配<br />
    要求：实现malloc/realloc/free三个函数，函数原型和标准C一致。或者实现FtkAllocator接口。<br />
    参考：ftk_allocator_default.c</p>
<p>2.文件操作<br />
    要求：实现FtkMmap接口。libpng和libjpeg还要求实现标准C的FILE(也可以用自己的解码器)。<br />
    参考：os/linux/ftk_mmap_linux.c<br />
<span id="more-1529"></span><br />
3.显示设备<br />
    要求：实现FtkDisplay接口，对于基本framebuffer的显示方式，可以利用ftk_display_mem来实现。<br />
    参考：backend/fb/ftk_display_fb.c</p>
<p>4.输入设备<br />
    要求：输入事件如果在主线程中读取，则要实现FtkSource接口。输入事件如果在单独线程中读取，可以用ftk_wnd_manager_queue_event来分发。<br />
    参考：backend/fb/ftk_source_input.c<br />
    注意：按键需要映射成FTK的键值。</p>
<p>5.管道<br />
    要求：实现FtkPipe接口。<br />
    参考：ftk_pipe_socket.c</p>
<p>6.图形解码<br />
    如果有自定义的图像格式或优化过的解码器，请实现ftk_image_decoder接口。</p>
<p>7.主函数<br />
    主函数可以是main或者ftk_main，由宏FTK_HAS_MAIN决定。</p>
<p>8.主循环<br />
    要求：实现FtkMainLoop<br />
    参考：ftk_main_loop_select.c</p>
<p>    对于RTOS，FTK通常只是需要ftk_source_primary一个管道，所有输入事件都通过它来串行化，所以实现MainLoop时挂在这个管道上即可。</p>
<p>9.辅助函数和宏<br />
    usleep<br />
    ftk_strncpy<br />
    ftk_snprintf<br />
    ftk_vsnprintf<br />
    ftk_getcwd<br />
    ftk_sscanf<br />
    ftk_get_relative_time</p>
<p>    FTK_ROOT_DIR<br />
    FTK_FONT<br />
    DATA_DIR<br />
    LOCAL_DATA_DIR<br />
    FTK_DATA_ROOT<br />
    TESTDATA_DIR </p>
<p>    参考：os/windows/ftk_win32.h</p>
<p>10.编译系统<br />
    对于兼容gcc的编译器，尽量使用automake来管理。对于不能兼容gcc的编译器，请把相关工程文件放到src/compiler下。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1529/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>FTK-0.4 发布</title>
		<link>http://www.limodev.cn/blog/archives/1517</link>
		<comments>http://www.limodev.cn/blog/archives/1517#comments</comments>
		<pubDate>Mon, 05 Apr 2010 07:11:54 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1517</guid>
		<description><![CDATA[经过大家一个月的努力，在FTK诞生6个月之际，FTK-0.4如期发布，其主要修改有： 1. 修改了一些BUG。 2. 完整的支持LUA绑定。 3. 完善交叉编译脚本。 4. 增加FTK配置文件。 5. 优化显示速度。 6. 增加缩放动画效果。 7. UCOSII支持(Windows模拟环境）。 特别感谢minpengli，Riwen Huang，zhangalion，tao yu，yapo su, phil song, ZhiHua Huang, hua song, Richard Sharpe和其他参与FTK开发和讨论的朋友们。欢迎大家加入邮件列表讨论。 有兴趣的朋友请到FTK下载源代码。 附： A gui library for embedded system. FTK equals funny tool kit, write it just for fun. General features: Lightweght. Beautiful look and feel. High code quality: [...]]]></description>
			<content:encoded><![CDATA[<p>经过大家一个月的努力，在FTK诞生6个月之际，FTK-0.4如期发布，其主要修改有：</p>
<p>1. 修改了一些BUG。<br />
2. 完整的支持LUA绑定。<br />
3. 完善交叉编译脚本。<br />
4. 增加FTK配置文件。<br />
5. 优化显示速度。<br />
6. 增加缩放动画效果。<br />
7. UCOSII支持(Windows模拟环境）。</p>
<p><span><span>特别感谢minpengli，Riwen Huang，zhangalion，tao yu，yapo su, phil song, ZhiHua Huang, hua song, Richard Sharpe和其他参与FTK开发和讨论的朋友们。欢迎大家加入<a href="https://groups.google.com/group/funnytoolkit">邮件列表</a>讨论。<span id="more-1517"></span></p>
<p>有兴趣的朋友请到<a href="http://code.google.com/p/ftk/downloads/list">FTK</a>下载源代码。</p>
<p>附：<br />
A gui library for embedded system. FTK equals funny tool kit, write it just for fun.</p>
<p><img src="../../gallery/albums/blog-pictures/ftk/logo.png" alt="ftk" /><span id="more-1428"> </span></p>
<p>General features:</p>
<ul>
<li> Lightweght.</li>
<li> Beautiful look and feel.</li>
<li> High code quality: design pattern, good code style.</li>
<li> Stable: code review, unit test, stress test, valgrind checked.</li>
<li> Full gui features: window, dialog, panel, button, menu…</li>
<li> Good portability: Unix, Windows, RTOS…</li>
</ul>
<p>Modern features:</p>
<ul>
<li> Theme.</li>
<li> Window animation.</li>
<li> Alpha channel to implement transparent/translucent window.</li>
<li> XML UI description language.</li>
<li> Script binding.</li>
<li> InputMethod with Handwrite(working)</li>
<li> Screen rotation(TODO).</li>
<li> Guesture recognition(TODO).</li>
</ul>
<p></span></span></p>
<p>FTK-0.4截图：<br />
按钮：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_button.png" alt="" /><br />
单选/多选框：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_check_box.png" alt="" /><br />
下拉框：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_combo_box.png" alt="" /><br />
对话框：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_dialog.png" alt="" /><br />
列表框：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_list_view.png" alt="" /><br />
进度条：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_progress_bar.png" alt="" /><br />
多行编辑器：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_text_view.png" alt="" /><br />
忙等待：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_wait_box.png" alt="" /><br />
图标视图：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_icon_view.png" alt="" /><br />
输入法:<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_ime.png" alt="" /><br />
单行编辑器：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_entry.png" alt="" /><br />
全屏效果：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_fullscreen.png" alt="" /><br />
桌面：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_desktop.png" alt="" /><br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_desktop1.png" alt="" /><br />
计算器：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-4/ftk_calc.png" alt="" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1517/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>爬塘朗山</title>
		<link>http://www.limodev.cn/blog/archives/1509</link>
		<comments>http://www.limodev.cn/blog/archives/1509#comments</comments>
		<pubDate>Sun, 04 Apr 2010 13:16:28 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[沉思录]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1509</guid>
		<description><![CDATA[塘朗山比南山好玩，南山完全是为爬山而爬山，塘朗山还可以看下风景。 最近脸色有些苍白。 老婆还不太像全职师奶。]]></description>
			<content:encoded><![CDATA[<p>塘朗山比南山好玩，南山完全是为爬山而爬山，塘朗山还可以看下风景。<img src="http://www.limodev.cn/gallery/albums/xianjimli/tanglangshan/tls.JPG" alt="tls" /></p>
<p>最近脸色有些苍白。<br />
<img src="http://www.limodev.cn/gallery/albums/xianjimli/tanglangshan/tls_lxj1.JPG" alt="lxj" /></p>
<p>老婆还不太像全职师奶。<br />
<img src="http://www.limodev.cn/gallery/albums/xianjimli/tanglangshan/tls_huan1.JPG" alt="huan" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1509/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI FTK设计与实现-主循环</title>
		<link>http://www.limodev.cn/blog/archives/1500</link>
		<comments>http://www.limodev.cn/blog/archives/1500#comments</comments>
		<pubDate>Sun, 28 Mar 2010 04:19:11 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1500</guid>
		<description><![CDATA[带图形用户界面(GUI)的应用程序和传统的批处理程序是不同的： * 批处理程序是一步一步的执行，直到完成任务为止，完成任务后程序立即退出。 * 图形用户界面应用程序则是事件驱动的，它等待事件发生，然后处理事件，如此循环，直到用户要求退出为止。 两种执行模型如下图所示： 通常我们把等待事件/处理事件的循环称为主循环(MainLoop)，主循环是GUI应用程序必要组件之一，FTK当然也离开不主循环 (MainLoop)。大多数嵌入式GUI都采用了Windows类似的主循环： while&#40;GetMessage&#40;&#38;msg&#41;&#41; &#123; TranslateMessage&#40;&#38;msg&#41;; DispatchMessage&#40;&#38;msg&#41;; &#125; 我不太喜欢这种主循环，主要原因有两点： * 它看似简洁，但内部实现并不简洁。它从当前线程的队列里获取消息，然后处理消息。这些消息从来哪里的？当然是由其它线程传递给当前线程的，这就意味着GUI需要多线程的支持。而FTK不想引入多线程来折磨自己，至少在GUI部分是不想的。 * 这是面向过程的处理方式。消息是一个对象，按照面向对象的思想来说，对象的数据和行为应该绑定在一起。而这里的消息是纯粹的数据，所有消息都由目标窗口的消息处理函数来处理的。FTK希望每类消息都有自己的处理函数，而不是全部由窗口来处理。 FTK采用了GTK类似的主循环： ftk_run&#40;&#41;; 它看起来更简洁，内部实现也不需要多线程的支持。这里采用了POSA(面向模式的软件架构）中的Reactor模式，它的主要好处有： * 用单线程处理多个事件源。 * 增加新事件源时不会影响事件分发的框架。 整个主循环由下列组件构成： FtkSource 是一个接口，是所有事件源的抽象，它要求事件源实现下列函数： * ftk_source_get_fd 用来获取文件描述符，当然这个文件描述符不一定是真正的文件描述符，只要是MainLoop能挂在上面等待的句柄(Handle)即可。 * ftk_source_check 用来检查事件源要求等待的时间。-1表示不关心等待时间。0表示要马就有事件发生，正数表示在指定的时间内将有事件发生。 * ftk_source_dispatch 用来处理事件，每个事件源都有自己的处理函数，而不是全部耦合到窗口的处理函数中。 FtkSourcesManager负责管理所有事件源。主要提供下列函数： * ftk_sources_manager_add 增加一个事件源。 * ftk_sources_manager_remove 删除一个事件源。 * ftk_sources_manager_get_count 获取事件源总数。 * ftk_sources_manager_get 获取指定索引的事件源。 FtkMainLoop负责循环的等待事件发生，然后调用事件源的处理函数去处理。主要提供下列函数： * ftk_main_loop_run 启动主循环 * [...]]]></description>
			<content:encoded><![CDATA[<p>带图形用户界面(GUI)的应用程序和传统的批处理程序是不同的：</p>
<p>    * 批处理程序是一步一步的执行，直到完成任务为止，完成任务后程序立即退出。<br />
    * 图形用户界面应用程序则是事件驱动的，它等待事件发生，然后处理事件，如此循环，直到用户要求退出为止。<span id="more-1500"></span></p>
<p>两种执行模型如下图所示：</p>
<p><img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-book/ftk_mainloop_cmp.JPG" alt="cmp" /></p>
<p>通常我们把等待事件/处理事件的循环称为主循环(MainLoop)，主循环是GUI应用程序必要组件之一，FTK当然也离开不主循环 (MainLoop)。大多数嵌入式GUI都采用了Windows类似的主循环：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>GetMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        TranslateMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        DispatchMessage<span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>msg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>我不太喜欢这种主循环，主要原因有两点：</p>
<p>    * 它看似简洁，但内部实现并不简洁。它从当前线程的队列里获取消息，然后处理消息。这些消息从来哪里的？当然是由其它线程传递给当前线程的，这就意味着GUI需要多线程的支持。而FTK不想引入多线程来折磨自己，至少在GUI部分是不想的。</p>
<p>    * 这是面向过程的处理方式。消息是一个对象，按照面向对象的思想来说，对象的数据和行为应该绑定在一起。而这里的消息是纯粹的数据，所有消息都由目标窗口的消息处理函数来处理的。FTK希望每类消息都有自己的处理函数，而不是全部由窗口来处理。</p>
<p>FTK采用了GTK类似的主循环：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">    ftk_run<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>它看起来更简洁，内部实现也不需要多线程的支持。这里采用了POSA(面向模式的软件架构）中的Reactor模式，它的主要好处有：</p>
<p>    * 用单线程处理多个事件源。<br />
    * 增加新事件源时不会影响事件分发的框架。</p>
<p>整个主循环由下列组件构成：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-book/ftk_mainloop.JPG" alt="mainloop" /><br />
FtkSource 是一个接口，是所有事件源的抽象，它要求事件源实现下列函数：</p>
<p>    * ftk_source_get_fd 用来获取文件描述符，当然这个文件描述符不一定是真正的文件描述符，只要是MainLoop能挂在上面等待的句柄(Handle)即可。<br />
    * ftk_source_check 用来检查事件源要求等待的时间。-1表示不关心等待时间。0表示要马就有事件发生，正数表示在指定的时间内将有事件发生。<br />
    * ftk_source_dispatch 用来处理事件，每个事件源都有自己的处理函数，而不是全部耦合到窗口的处理函数中。</p>
<p>FtkSourcesManager负责管理所有事件源。主要提供下列函数：</p>
<p>    * ftk_sources_manager_add 增加一个事件源。<br />
    * ftk_sources_manager_remove 删除一个事件源。<br />
    * ftk_sources_manager_get_count 获取事件源总数。<br />
    * ftk_sources_manager_get 获取指定索引的事件源。</p>
<p>FtkMainLoop负责循环的等待事件发生，然后调用事件源的处理函数去处理。主要提供下列函数：</p>
<p>    * ftk_main_loop_run 启动主循环<br />
    * ftk_main_loop_quit 退出主循环<br />
    * ftk_main_loop_add_source 增加一个事件源<br />
    * ftk_main_loop_remove_source 删除一个事件源</p>
<p>FtkMainLoop提供了add_source和remove_source两个函数对 FtkSourcesManager相应函数进行包装，这里包装不是简单的调用FtkSourcesManager的函数，而是发送一个事件：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">Ret ftk_main_loop_add_source<span style="color: #009900;">&#40;</span>FtkMainLoop<span style="color: #339933;">*</span> thiz<span style="color: #339933;">,</span> FtkSource<span style="color: #339933;">*</span> source<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    FtkEvent event <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>thiz <span style="color: #339933;">!=</span> NULL <span style="color: #339933;">&amp;&amp;</span> source <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    event.<span style="color: #202020;">type</span> <span style="color: #339933;">=</span> FTK_EVT_ADD_SOURCE<span style="color: #339933;">;</span>
    event.<span style="color: #202020;">u</span>.<span style="color: #202020;">extra</span> <span style="color: #339933;">=</span> source<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ftk_source_queue_event<span style="color: #009900;">&#40;</span>ftk_primary_source<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>event<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
Ret ftk_main_loop_remove_source<span style="color: #009900;">&#40;</span>FtkMainLoop<span style="color: #339933;">*</span> thiz<span style="color: #339933;">,</span> FtkSource<span style="color: #339933;">*</span> source<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    FtkEvent event <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>thiz <span style="color: #339933;">!=</span> NULL <span style="color: #339933;">&amp;&amp;</span> source <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    event.<span style="color: #202020;">type</span> <span style="color: #339933;">=</span> FTK_EVT_REMOVE_SOURCE<span style="color: #339933;">;</span>
    event.<span style="color: #202020;">u</span>.<span style="color: #202020;">extra</span> <span style="color: #339933;">=</span> source<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ftk_source_queue_event<span style="color: #009900;">&#40;</span>ftk_primary_source<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>event<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这个事件由Primary Source进行处理：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> Ret ftk_source_primary_dispatch<span style="color: #009900;">&#40;</span>FtkSource<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    ...
    <span style="color: #b1b100;">switch</span><span style="color: #009900;">&#40;</span>event.<span style="color: #202020;">type</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">case</span> FTK_EVT_ADD_SOURCE<span style="color: #339933;">:</span>
        <span style="color: #009900;">&#123;</span>
            ftk_sources_manager_add<span style="color: #009900;">&#40;</span>ftk_default_sources_manager<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> event.<span style="color: #202020;">u</span>.<span style="color: #202020;">extra</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">case</span> FTK_EVT_REMOVE_SOURCE<span style="color: #339933;">:</span>
        <span style="color: #009900;">&#123;</span>
            ftk_sources_manager_remove<span style="color: #009900;">&#40;</span>ftk_default_sources_manager<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> event.<span style="color: #202020;">u</span>.<span style="color: #202020;">extra</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    ...
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>为什么要多此一举呢？原因这样的：FTK是单线程的，GUI线程只负责用户界面的管理，由后台工作的线程负责长时间的操作。但是后台工作的线程经常需要更新用户界面，比如下载网络数据的线程要更新下载进度界面。FTK需要提供一种机制，让后台线程来更新用户界面但又不需要引入互斥机制。这可以通过idle来串行化对GUI的操作，后台线程要更新GUI时，就增加一个idle source，后台线程不能直接调用ftk_sources_manager_add，那样需要互斥机制，而且也不能唤醒主循环去处理这个idle。所以它通过Primary Source的管道发送一个事件，这个事件会唤醒睡眠中的主循环，然后调用Primary Source分发函数去处理事件。</p>
<p>现在我们来看ftk_main_loop_run的实现，ftk_main_loop_run的实现是平台相关的，对于支持select的平台，用 select是最好的方法。下面是基于select的实现：</p>
<p>1.找出最小等待时间和文件描述符</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">        <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> ftk_sources_manager_get_count<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">-&gt;</span>sources_manager<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            source <span style="color: #339933;">=</span> ftk_sources_manager_get<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">-&gt;</span>sources_manager<span style="color: #339933;">,</span> i<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>fd <span style="color: #339933;">=</span> ftk_source_get_fd<span style="color: #009900;">&#40;</span>source<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;=</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                FD_SET<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>thiz<span style="color: #339933;">-&gt;</span>fdset<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>mfd <span style="color: #339933;">&lt;</span> fd<span style="color: #009900;">&#41;</span> mfd <span style="color: #339933;">=</span> fd<span style="color: #339933;">;</span>
                n<span style="color: #339933;">++;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            source_wait_time <span style="color: #339933;">=</span> ftk_source_check<span style="color: #009900;">&#40;</span>source<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>source_wait_time <span style="color: #339933;">&gt;=</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">&amp;&amp;</span> source_wait_time <span style="color: #339933;">&lt;</span> wait_time<span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                wait_time <span style="color: #339933;">=</span> source_wait_time<span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span></pre></div></div>

<p>这里遍历所有source，找出一个最小的等待时间和要等待的文件描述符。</p>
<p>2. 等待事件发生</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">        tv.<span style="color: #202020;">tv_sec</span> <span style="color: #339933;">=</span> wait_time<span style="color: #339933;">/</span><span style="color: #0000dd;">1000</span><span style="color: #339933;">;</span>
        tv.<span style="color: #202020;">tv_usec</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>wait_time<span style="color: #339933;">%</span><span style="color:#800080;">1000</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">*</span> <span style="color: #0000dd;">1000</span><span style="color: #339933;">;</span>
        ret <span style="color: #339933;">=</span> select<span style="color: #009900;">&#40;</span>mfd <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>thiz<span style="color: #339933;">-&gt;</span>fdset<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> NULL<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>tv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>3.检查事件源并调用相应的事件处理函数</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span>fd <span style="color: #339933;">=</span> ftk_source_get_fd<span style="color: #009900;">&#40;</span>source<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;=</span> <span style="color: #0000dd;">0</span> <span style="color: #339933;">&amp;&amp;</span> FD_ISSET<span style="color: #009900;">&#40;</span>fd<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>thiz<span style="color: #339933;">-&gt;</span>fdset<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>ftk_source_dispatch<span style="color: #009900;">&#40;</span>source<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> RET_OK<span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #808080; font-style: italic;">/*as current is removed, the next will be move to current, so dont call i++*/</span>
                    ftk_sources_manager_remove<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">-&gt;</span>sources_manager<span style="color: #339933;">,</span> source<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    ftk_logd<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s:%d remove %p<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> __func__<span style="color: #339933;">,</span> __LINE__<span style="color: #339933;">,</span> source<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">else</span>
                <span style="color: #009900;">&#123;</span>
                    i<span style="color: #339933;">++;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
            <span style="color: #666666; font-style: italic;">//这里处理timer和idle。</span>
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>source_wait_time <span style="color: #339933;">=</span> ftk_source_check<span style="color: #009900;">&#40;</span>source<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>ftk_source_dispatch<span style="color: #009900;">&#40;</span>source<span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> RET_OK<span style="color: #009900;">&#41;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #808080; font-style: italic;">/*as current is removed, the next will be move to current, so dont call i++*/</span>
                    ftk_sources_manager_remove<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">-&gt;</span>sources_manager<span style="color: #339933;">,</span> source<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #666666; font-style: italic;">//ftk_logd(&quot;%s:%d remove %p\n&quot;, __func__, __LINE__, source);</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">else</span>
                <span style="color: #009900;">&#123;</span>
                    i<span style="color: #339933;">++;</span>
                <span style="color: #009900;">&#125;</span>
                <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span></pre></div></div>

<p>如果事件源处理函数的返回值不是RET_OK的事件，我们认为出错了或者是事件要求自己被移除，那就把它移除掉。</p>
<p>GUI是事件驱动的，创建一个窗口后，函数马上就返回了，窗口中的控件对用户事件处理是在以后的事件循环中进行的。这对于大多数情况是正常的，但有时我们需要用户确认一些问题，根据确认的结果做相应的处理。比如，用户删除一个文件，我们要确认他是否真的想删除后才能去删除。也就是在创建对话框后，函数不是马上返回，而且等用户确认，关闭对话框后才返回。</p>
<p>为了做到这一点，我们要在一个事件处理函数中，创建另外一个主循环来分发事件。模态对话框就是这样实现的：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> ftk_dialog_run<span style="color: #009900;">&#40;</span>FtkWidget<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV1<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>thiz <span style="color: #339933;">!=</span> NULL<span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>ftk_widget_type<span style="color: #009900;">&#40;</span>thiz<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> FTK_DIALOG<span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ftk_widget_show_all<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    priv<span style="color: #339933;">-&gt;</span>main_loop <span style="color: #339933;">=</span> ftk_main_loop_create<span style="color: #009900;">&#40;</span>ftk_default_sources_manager<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ftk_main_loop_run<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>main_loop<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ftk_main_loop_destroy<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>main_loop<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    priv<span style="color: #339933;">-&gt;</span>main_loop <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> ftk_widget_id<span style="color: #009900;">&#40;</span>ftk_window_get_focus<span style="color: #009900;">&#40;</span>thiz<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>对话模型提供了一个用于退出该主循环的函数：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">Ret ftk_dialog_quit<span style="color: #009900;">&#40;</span>FtkWidget<span style="color: #339933;">*</span> thiz<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    DECL_PRIV1<span style="color: #009900;">&#40;</span>thiz<span style="color: #339933;">,</span> priv<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    return_val_if_fail<span style="color: #009900;">&#40;</span>ftk_dialog_is_modal<span style="color: #009900;">&#40;</span>thiz<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> RET_FAIL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    ftk_main_loop_quit<span style="color: #009900;">&#40;</span>priv<span style="color: #339933;">-&gt;</span>main_loop<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> RET_OK<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1500/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI FTK设计与实现-分层视图</title>
		<link>http://www.limodev.cn/blog/archives/1494</link>
		<comments>http://www.limodev.cn/blog/archives/1494#comments</comments>
		<pubDate>Mon, 22 Mar 2010 13:14:04 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1494</guid>
		<description><![CDATA[为了从整体上把握FTK的架构，我们先看看FTK的分层视图： 这里我们从下至上的来介绍一下各个组件的功能： 1.最下层是平台相关的适配层。它包括两个部分： * 操作系统适配层：它主要是封装平台相关的函数，为上层提供统一的接口，比如mmap和pipe等。 * Backend: 主要是对输入/显示设备的抽象。像mouse/keyboard之类的输入设备和framebuffer的显示设备等。 2. 再上层是一些interface，这些interface为上层提供统一的接口，隔离了具体的实现细节，从提高了系统的可移植性和灵活性。比如图片解码器和字体引擎都可以根据实际情况进行配置。 3.再上层是窗口、窗口管理器和主循环等基础设施。 * 顶层窗口包括应用程序窗口，菜单条，状态栏和对话框几种，它们是放置各种控件的容器。 * 窗口管理器负责控制各个窗口的位置/大小和事件的分发。 * 主循环负责监听来自各个事件源的事件，如输入设备事件，定时器和idle等，然后调用相应的分发函数去处理这些事件。 4.再上层是控件的实现，如按钮、文本、进度条和列表框等等。这些大部分控件都是可以裁减的，开发者可以根据实际需求去掉一些不必要的组件。 5. 再上层是XUL，包括XML界面描述和脚本绑定。目前实现了lua的绑定，以后会增加其它脚本的绑定。 6.最上层是基于FTK的应用环境和平台。目前计划的有: * 一个基本的桌面环境，包括桌面、Shell、文件管理器、音乐播放器和其它一些工具。 * PhoneME(J2ME) * Webkit]]></description>
			<content:encoded><![CDATA[<p>为了从整体上把握FTK的架构，我们先看看FTK的分层视图：</p>
<p><img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk_layer_view.JPG" alt="ftk_layer_view" /><span id="more-1494"></span></p>
<p>这里我们从下至上的来介绍一下各个组件的功能：</p>
<p>1.最下层是平台相关的适配层。它包括两个部分：</p>
<p>    * 操作系统适配层：它主要是封装平台相关的函数，为上层提供统一的接口，比如mmap和pipe等。<br />
    * Backend: 主要是对输入/显示设备的抽象。像mouse/keyboard之类的输入设备和framebuffer的显示设备等。</p>
<p>2. 再上层是一些interface，这些interface为上层提供统一的接口，隔离了具体的实现细节，从提高了系统的可移植性和灵活性。比如图片解码器和字体引擎都可以根据实际情况进行配置。</p>
<p>3.再上层是窗口、窗口管理器和主循环等基础设施。</p>
<p>    * 顶层窗口包括应用程序窗口，菜单条，状态栏和对话框几种，它们是放置各种控件的容器。<br />
    * 窗口管理器负责控制各个窗口的位置/大小和事件的分发。<br />
    * 主循环负责监听来自各个事件源的事件，如输入设备事件，定时器和idle等，然后调用相应的分发函数去处理这些事件。</p>
<p>4.再上层是控件的实现，如按钮、文本、进度条和列表框等等。这些大部分控件都是可以裁减的，开发者可以根据实际需求去掉一些不必要的组件。</p>
<p>5. 再上层是XUL，包括XML界面描述和脚本绑定。目前实现了lua的绑定，以后会增加其它脚本的绑定。</p>
<p>6.最上层是基于FTK的应用环境和平台。目前计划的有:</p>
<p>    * 一个基本的桌面环境，包括桌面、Shell、文件管理器、音乐播放器和其它一些工具。<br />
    * PhoneME(J2ME)<br />
    * Webkit</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1494/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FTK在ben上运行起来了</title>
		<link>http://www.limodev.cn/blog/archives/1492</link>
		<comments>http://www.limodev.cn/blog/archives/1492#comments</comments>
		<pubDate>Sat, 20 Mar 2010 06:58:44 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1492</guid>
		<description><![CDATA[Qi Hardware是由一帮出色的hacker组成的团队，和他们老大Wolfgang Spraul 有过一面之缘，对他们也是很佩服的。呵，帮他们打个广告吧。另外，FTK已经在ben上运行起来了。 Hi, Qi Hardware is proud to announce the availability of the first product that tries to adhere to copyleft hardware standards: Ben NanoNote It&#8217;s a 99 USD Linux clamshell device, others have called it &#8220;The $99 open hardware thingie&#8221; (CrunchGear) &#8220;Dedicated Vi device&#8221; (The Register) &#8220;tiny, hackable&#8221; (Engadget) &#8220;totalmente libre&#8221; (viva [...]]]></description>
			<content:encoded><![CDATA[<p>Qi Hardware是由一帮出色的hacker组成的团队，和他们老大Wolfgang Spraul 有过一面之缘，对他们也是很佩服的。呵，帮他们打个广告吧。另外，<a href="http://en.qi-hardware.com/pipermail/developer/2010-March/002382.html">FTK已经在ben上运行</a>起来了。<span id="more-1492"></span></p>
<p>Hi,<br />
Qi Hardware is proud to announce the availability of the first product<br />
that tries to adhere to copyleft hardware standards:</p>
<p>Ben NanoNote</p>
<p>It&#8217;s a 99 USD Linux clamshell device, others have called it</p>
<p>&#8220;The $99 open hardware thingie&#8221; (CrunchGear)<br />
&#8220;Dedicated Vi device&#8221; (The Register)<br />
&#8220;tiny, hackable&#8221; (Engadget)<br />
&#8220;totalmente libre&#8221; (viva linux!)<br />
&#8220;adorabile 3 pollici Linux&#8221; (Netbook News)</p>
<p>(source: http://sharism.cc/voices/)</p>
<p>Get more detailed product information at http://sharism.cc/specs/<br />
The Ben is available and in stock at an online store nearby you:</p>
<p>Europe (99 EUR): http://www.tuxbrain.com/<br />
Belgium (99 EUR): http://hackable-devices.com/products/product/nanonote/<br />
Netherlands (125 EUR): http://openmobile.nl<br />
Germany (119 EUR): http://www.pulster.de<br />
India (6500 INR): http://www.idasystems.net<br />
USA/Canada/rest of the world (shipping from Hong Kong, 99 USD): http://nanonote.cc</p>
<p>Thanks for interest in our project, more background information about<br />
what we do at http://en.qi-hardware.com<br />
viva linux!<br />
Wolfgang</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1492/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于变量的初始化</title>
		<link>http://www.limodev.cn/blog/archives/1490</link>
		<comments>http://www.limodev.cn/blog/archives/1490#comments</comments>
		<pubDate>Thu, 18 Mar 2010 23:26:10 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1490</guid>
		<description><![CDATA[做了两年的调试工作后，我对没有初始化的变量引起BUG总是有种恐慌，所以习惯给任何变量都赋上一个初始值。今天一个新同事问到一个问题，int a[100] = {0};是初始化第一个元素还是所有元素？我说是所有的。我们看看下面这个例子： #include &#60;stdio.h&#62; #include &#60;stdlib.h&#62; &#160; typedef struct _Book &#123; int isbn; char name&#91;32&#93;; char author&#91;32&#93;; &#125;Book; &#160; int main&#40;int argc, char* argv&#91;&#93;&#41; &#123; int a&#91;100&#93; = &#123;0&#125;; Book b = &#123;0&#125;; &#160; return 0; &#125; 反汇编出来： int a&#91;100&#93; = &#123;0&#125;; 80483a3: 8d 95 68 fe ff ff lea -0x198&#40;%ebp&#41;,%edx 80483a9: b8 [...]]]></description>
			<content:encoded><![CDATA[<p>做了两年的调试工作后，我对没有初始化的变量引起BUG总是有种恐慌，所以习惯给任何变量都赋上一个初始值。今天一个新同事问到一个问题，int a[100] = {0};是初始化第一个元素还是所有元素？我说是所有的。我们看看下面这个例子：<span id="more-1490"></span></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;stdlib.h&gt;</span>
&nbsp;
<span style="color: #993333;">typedef</span> <span style="color: #993333;">struct</span> _Book
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> isbn<span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> name<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">32</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #993333;">char</span> author<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">32</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>Book<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> argc<span style="color: #339933;">,</span> <span style="color: #993333;">char</span><span style="color: #339933;">*</span> argv<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    Book b <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>反汇编出来：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">    <span style="color: #993333;">int</span> a<span style="color: #009900;">&#91;</span><span style="color: #0000dd;">100</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
 80483a3<span style="color: #339933;">:</span>    8d <span style="color: #0000dd;">95</span> <span style="color: #0000dd;">68</span> fe ff ff        lea    <span style="color: #339933;">-</span><span style="color: #208080;">0x198</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">%</span>ebp<span style="color: #009900;">&#41;</span><span style="color: #339933;">,%</span>edx
 80483a9<span style="color: #339933;">:</span>    b8 <span style="color: #0000dd;">90</span> <span style="color: #208080;">01</span> <span style="color: #208080;">00</span> <span style="color: #208080;">00</span>           mov    $<span style="color: #208080;">0x190</span><span style="color: #339933;">,%</span>eax
 80483ae<span style="color: #339933;">:</span>    <span style="color: #0000dd;">89</span> <span style="color: #0000dd;">44</span> <span style="color: #0000dd;">24</span> <span style="color:#800080;">08</span>              mov    <span style="color: #339933;">%</span>eax<span style="color: #339933;">,</span><span style="color: #208080;">0x8</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">%</span>esp<span style="color: #009900;">&#41;</span>
 80483b2<span style="color: #339933;">:</span>    c7 <span style="color: #0000dd;">44</span> <span style="color: #0000dd;">24</span> <span style="color: #208080;">04</span> <span style="color: #208080;">00</span> <span style="color: #208080;">00</span> <span style="color: #208080;">00</span>     movl   $<span style="color: #208080;">0x0</span><span style="color: #339933;">,</span><span style="color: #208080;">0x4</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">%</span>esp<span style="color: #009900;">&#41;</span>
 80483b9<span style="color: #339933;">:</span>    <span style="color: #208080;">00</span>
 80483ba<span style="color: #339933;">:</span>    <span style="color: #0000dd;">89</span> <span style="color: #0000dd;">14</span> <span style="color: #0000dd;">24</span>                 mov    <span style="color: #339933;">%</span>edx<span style="color: #339933;">,</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">%</span>esp<span style="color: #009900;">&#41;</span>
 80483bd<span style="color: #339933;">:</span>    e8 <span style="color: #208080;">06</span> ff ff ff           call   80482c8 <span style="color: #339933;">&lt;</span>memset@plt<span style="color: #339933;">&gt;</span>
    Book b <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #0000dd;">0</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
 80483c2<span style="color: #339933;">:</span>    8d <span style="color: #0000dd;">95</span> <span style="color: #0000dd;">18</span> fe ff ff        lea    <span style="color: #339933;">-</span><span style="color: #208080;">0x1e8</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">%</span>ebp<span style="color: #009900;">&#41;</span><span style="color: #339933;">,%</span>edx
 80483c8<span style="color: #339933;">:</span>    b8 <span style="color: #0000dd;">44</span> <span style="color: #208080;">00</span> <span style="color: #208080;">00</span> <span style="color: #208080;">00</span>           mov    $<span style="color: #208080;">0x44</span><span style="color: #339933;">,%</span>eax
 80483cd<span style="color: #339933;">:</span>    <span style="color: #0000dd;">89</span> <span style="color: #0000dd;">44</span> <span style="color: #0000dd;">24</span> <span style="color:#800080;">08</span>              mov    <span style="color: #339933;">%</span>eax<span style="color: #339933;">,</span><span style="color: #208080;">0x8</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">%</span>esp<span style="color: #009900;">&#41;</span>
 80483d1<span style="color: #339933;">:</span>    c7 <span style="color: #0000dd;">44</span> <span style="color: #0000dd;">24</span> <span style="color: #208080;">04</span> <span style="color: #208080;">00</span> <span style="color: #208080;">00</span> <span style="color: #208080;">00</span>     movl   $<span style="color: #208080;">0x0</span><span style="color: #339933;">,</span><span style="color: #208080;">0x4</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">%</span>esp<span style="color: #009900;">&#41;</span>
 80483d8<span style="color: #339933;">:</span>    <span style="color: #208080;">00</span>
 80483d9<span style="color: #339933;">:</span>    <span style="color: #0000dd;">89</span> <span style="color: #0000dd;">14</span> <span style="color: #0000dd;">24</span>                 mov    <span style="color: #339933;">%</span>edx<span style="color: #339933;">,</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">%</span>esp<span style="color: #009900;">&#41;</span>
 80483dc<span style="color: #339933;">:</span>    e8 e7 fe ff ff           call   80482c8 <span style="color: #339933;">&lt;</span>memset@plt<span style="color: #339933;">&gt;</span></pre></div></div>

<p>可以看到：<br />
0&#215;190 = sizeof(int)*100<br />
0&#215;44 ＝ sizeof(Book)</p>
<p>即对整个变量做了清零动作。</p>
<p>呵，我不知道gcc之外的编译器是不是这样做的，反正建议大家在修改FTK时遵循一下这个原则。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1490/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>FTK编程风格</title>
		<link>http://www.limodev.cn/blog/archives/1486</link>
		<comments>http://www.limodev.cn/blog/archives/1486#comments</comments>
		<pubDate>Wed, 17 Mar 2010 23:51:35 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1486</guid>
		<description><![CDATA[命名规则 名称要表达出对象的意义。 1.文件名 以ftk开头（demo和测试程序除外）。 单词小写。 多个单词用下划线分隔。 示例： ftk_window.c ftk_window.h 2.函数名 以ftk开头（内部函数或工具函数外可以例外）。 单词小写。 多个单词用下划线分隔。 示例： ftk_window_set_focus ftk_window_get_focus 3.变量名 单词小写。 多个单词用下划线分隔。 对象以thiz命名。 示例： int fullscreen FtkWidget* thiz int update_disabled 4.结构名/枚举名/联合名 以Ftk开头(C文件内部使用的结构可以例外)。 单词首字大写。 多个单词连写。 接口的私有信息统一用PrivInfo。 示例： typedef struct _FtkPoint &#123; int x; int y; &#125;FtkPoint; &#160; typedef struct _PrivInfo &#123; FtkCanvas*  canvas; ... &#125;PrivInfo; 7.常量(宏/枚举变量） 以FTK开头（RET_系列除外）。 单词大写。 多个单词用下划线分隔。 [...]]]></description>
			<content:encoded><![CDATA[<div><strong>命名规则</strong></p>
<p>名称要表达出对象的意义。</p>
<p>1.文件名</p>
<ul>
<li>以ftk开头（demo和测试程序除外）。</li>
<li>单词小写。</li>
<li>多个单词用下划线分隔。</li>
</ul>
</div>
<p>示例：<span id="more-1486"></span></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">ftk_window.<span style="color: #202020;">c</span>
ftk_window.<span style="color: #202020;">h</span></pre></div></div>

<div>2.函数名</p>
<ul>
<li>以ftk开头（内部函数或工具函数外可以例外）。</li>
<li>单词小写。</li>
<li>多个单词用下划线分隔。</li>
</ul>
<p>示例：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">ftk_window_set_focus
ftk_window_get_focus</pre></div></div>

<p>3.变量名</p>
<ul>
<li>单词小写。</li>
<li>多个单词用下划线分隔。</li>
<li>对象以thiz命名。</li>
</ul>
<p>示例：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> fullscreen
FtkWidget<span style="color: #339933;">*</span> thiz
<span style="color: #993333;">int</span> update_disabled</pre></div></div>

<p>4.结构名/枚举名/联合名</p>
<ul>
<li>以Ftk开头(C文件内部使用的结构可以例外)。</li>
<li>单词首字大写。</li>
<li>多个单词连写。</li>
<li>接口的私有信息统一用PrivInfo。</li>
</ul>
</div>
<div>示例：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">typedef</span> <span style="color: #993333;">struct</span> _FtkPoint
<span style="color: #009900;">&#123;</span>
<span style="color: #993333;">int</span> x<span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> y<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>FtkPoint<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">typedef</span> <span style="color: #993333;">struct</span> _PrivInfo
<span style="color: #009900;">&#123;</span>
FtkCanvas<span style="color: #339933;">*</span>  canvas<span style="color: #339933;">;</span>
...
<span style="color: #009900;">&#125;</span>PrivInfo<span style="color: #339933;">;</span></pre></div></div>

<p>7.常量(宏/枚举变量）</p>
<ul>
<li>以FTK开头（RET_系列除外）。</li>
<li>单词大写。</li>
<li>多个单词用下划线分隔。</li>
</ul>
<p>示例：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">FTK_WIDGET_NORMAL
FTK_WIDGET_FOCUSED</pre></div></div>

<p><strong><br />
排版规则</strong><br />
1.缩进</p>
<ul>
<li>以TAB键缩进。</li>
<li>TAB键的宽度设置为4。</li>
</ul>
</div>
<div>vim可用下面的设置：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">set ts<span style="color: #339933;">=</span><span style="color: #0000dd;">4</span>
set sw<span style="color: #339933;">=</span><span style="color: #0000dd;">4</span>
set ai
set ci</pre></div></div>

<p>2.空行</p>
<ul>
<li>避免连续多个空行。</li>
<li>函数之间要加空行。</li>
<li>return与其它语句之要加空行。</li>
<li>变量声明与执行代码之间要加空行。</li>
<li>逻辑块之间要加空行。</li>
</ul>
<p>3.空格</p>
<ul>
<li>操作符两端用加空格</li>
<li>函数参数之间用加空格</li>
<li>用./-&gt;等访问成员时，不要加空格。</li>
<li>定义指针时，*与类型之间不要加空格。</li>
</ul>
<p><strong>可移性</strong></p>
<ul>
<li>避免使用编译器特有的特性。</li>
<li>避免使用C99等新的特性。</li>
<li>使用FTK包装的函数(如内存管理和字符串操作)</li>
<li>平台相关的函数要抽象后使用。</li>
<li>变量声明要在执行语句之前。</li>
<li>对于在多个平台上运行的代码，要在多个平台编译测试。</li>
</ul>
</div>
<p><strong>稳定性</strong></p>
<ul>
<li>变量声明时即对其进行初始化。</li>
<li>功能测试通过后，用valgrind检测内存越界和持续内存泄露。</li>
</ul>
<p><strong><br />
杂项<br />
</strong></p>
<ul>
<li>避免使用全局变量。</li>
<li>内部函数加static</li>
</ul>
<p><strong> </strong><br />
<strong>注释规则</strong></p>
<ul>
<li>用简单明了的代码代替注释。</li>
<li>注释用英文书写。</li>
<li>注释中写背景和原因，而不是重复代码。</li>
<li>文件头注释的格式如下（演示程序、测试程序和自动产生的代码可以例外）：</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/*
* File: 文件名
* Author: 作者及邮件
* Brief: 说明
*
* Copyright (c) 2009 - 2010 版权
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/*
* History:
* ================================================================
* date who what
*
*/</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1486/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>0xlab对Broncho A1的评测</title>
		<link>http://www.limodev.cn/blog/archives/1484</link>
		<comments>http://www.limodev.cn/blog/archives/1484#comments</comments>
		<pubDate>Mon, 15 Mar 2010 14:20:03 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1484</guid>
		<description><![CDATA[0xlab对Broncho A1的评测。原文：http://blog.kanru.info/archives/688 上週末下班前，在桌上發現一個包裹，原來是渡海而來的兩隻 A1！這兩隻 A1 是 Broncho 的產品，詳細規格可以參考 Broncho 的網頁。 大伙興奮的開箱啦！ 包裝和 Hero 的很像。3.2 寸 LCD, 480×320 的解析度，200 萬畫素的相機鏡頭，CPU 是 Marvell 300 (624 MHz)，記憶體是 256 + 128 MB，支援 WIFI, Bluetooth, FM, GPS。不是使用標準的 USB 接口，但同一個接口可以接 USB、耳機、變壓器。觸控螢幕使用起來的感覺像是電容式的，反應非常靈敏，輕輕的觸摸就有反應。 系統是 Android Cupcake，內建軟體有不少 Google App，最另人驚訝旳是上面有 Android Market 可以用，試著從 Market 上面下載了一些小遊戲下來玩，完全沒有問題，真是太牛了！另外一點就是有內建手寫輸入，速度不快但是準確度不錯。除此之外還有谷歌拼音可以用。 測試的途中無線網路與 GPS 不是很穩，除此之外以一隻中低價位的手機來說表現的相當不錯。]]></description>
			<content:encoded><![CDATA[<p><!-- end postaction --></p>
<div>
<p>0xlab对Broncho A1的评测。原文：<a href="http://blog.kanru.info/archives/688">http://blog.kanru.info/archives/688</a></p>
<p>上週末下班前，在桌上發現一個包裹，原來是渡海而來的兩隻 A1！這兩隻 A1 是 Broncho  的產品，詳細規格可以參考 <a onclick="javascript:pageTracker._trackPageview('/http://www.broncho.cn/products/a1/');" href="http://www.broncho.cn/products/a1/">Broncho  的網頁</a>。</p>
<p>大伙興奮的開箱啦！</p>
<p><a href="http://blog.kanru.info/wp-content/uploads/2010/03/FxCam_1268373797319.jpg"><img title="unbox" src="http://blog.kanru.info/wp-content/uploads/2010/03/FxCam_1268373797319-150x150.jpg" alt="開箱" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/FxCam_1268373867309.jpg"><img title="unbox2" src="http://blog.kanru.info/wp-content/uploads/2010/03/FxCam_1268373867309-150x150.jpg" alt="開箱" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/2010-03-12-14.04.52.jpg"><img title="合照" src="http://blog.kanru.info/wp-content/uploads/2010/03/2010-03-12-14.04.52-150x150.jpg" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/2010-03-12-14.06.25.jpg"><img title="真像" src="http://blog.kanru.info/wp-content/uploads/2010/03/2010-03-12-14.06.25-150x150.jpg" alt="" width="150" height="150" /></a></p>
<p>包裝和 Hero 的很像。3.2 寸 LCD, 480×320 的解析度，200 萬畫素的相機鏡頭，CPU 是 Marvell 300  (624 MHz)，記憶體是 256 + 128 MB，支援 WIFI, Bluetooth, FM, GPS。不是使用標準的 USB  接口，但同一個接口可以接 USB、耳機、變壓器。觸控螢幕使用起來的感覺像是電容式的，反應非常靈敏，輕輕的觸摸就有反應。</p>
<p>系統是 Android Cupcake，內建軟體有不少 Google App，最另人驚訝旳是上面有 Android Market  可以用，試著從 Market  上面下載了一些小遊戲下來玩，完全沒有問題，真是太牛了！另外一點就是有內建手寫輸入，速度不快但是準確度不錯。除此之外還有谷歌拼音可以用。</p>
<p>測試的途中無線網路與 GPS 不是很穩，除此之外以一隻中低價位的手機來說表現的相當不錯。</p>
<p><a href="http://blog.kanru.info/wp-content/uploads/2010/03/lock.png"><img title="lock" src="http://blog.kanru.info/wp-content/uploads/2010/03/lock-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/home.png"><img title="home" src="http://blog.kanru.info/wp-content/uploads/2010/03/home-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/apps.png"><img title="apps" src="http://blog.kanru.info/wp-content/uploads/2010/03/apps-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/market.png"><img title="market" src="http://blog.kanru.info/wp-content/uploads/2010/03/market-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/market2.png"><img title="market2" src="http://blog.kanru.info/wp-content/uploads/2010/03/market2-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/market3.png"><img title="market3" src="http://blog.kanru.info/wp-content/uploads/2010/03/market3-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/weather.png"><img title="weather" src="http://blog.kanru.info/wp-content/uploads/2010/03/weather-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/handwriting1.png"><img title="handwriting1" src="http://blog.kanru.info/wp-content/uploads/2010/03/handwriting1-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/handwriting2.png"><img title="handwriting2" src="http://blog.kanru.info/wp-content/uploads/2010/03/handwriting2-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/handwriting3.png"><img title="handwriting3" src="http://blog.kanru.info/wp-content/uploads/2010/03/handwriting3-150x150.png" alt="" width="150" height="150" /></a> <a href="http://blog.kanru.info/wp-content/uploads/2010/03/handwriting4.png"><img title="handwriting4" src="http://blog.kanru.info/wp-content/uploads/2010/03/handwriting4-150x150.png" alt="" width="150" height="150" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1484/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI FTK设计与实现-三项基本原则</title>
		<link>http://www.limodev.cn/blog/archives/1482</link>
		<comments>http://www.limodev.cn/blog/archives/1482#comments</comments>
		<pubDate>Sun, 14 Mar 2010 08:13:45 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1482</guid>
		<description><![CDATA[记得X Window在设计初期就提出了七项基本指导原则，在后面X Window几十年的演变过程中，都以这些基本原则作为指导思想。其中给我印象比较深的一条就是：提供机制而不是策略。X Window一直都遵循这条原则，它只提供实现某些功能的机制，而把实现的策略留给ToolKit或其它辅助软件。为了让FTK在以后的演化过程中不至于迷失方向，我们也给FTK定了三项基本原则： 第一：程序首先是给人读的，其次才是给机器读的。 程序首先是给人读的，其次才是给机器读的。这句话是很多程序员都认同的，加上FTK最初的目的就是作为《系统程序员成长计划》的综合练习项目，目标是让《系统程序员成长计划》的读者通过阅读FTK的源代码，来学习如何把前面学到的知识应用到一个实际的项目中。所以把FTK代码的可读性放在第一位是理所当然的。 GUI无疑是最复杂的基础软件之一，在我研究过的GUI中，像X Window、DirectFB、 GTK+和MicroWindows，它们都是非常复杂的软件系统。我写过不少关于它们内部实现的文章，但是我现在要非常惭愧的告诉你，这些GUI的实现太复杂了，我其实没有完全搞明白过其中任何一个系统。分析一个GUI系统，对一个工作经验丰富的程序员来说尚且如此困难，对初学者的难度就可想而知了。不过FTK则是希望成为人人可以读懂的GUI系统。如果你在阅读代码的过程遇到了难题，请不要犹豫，大胆的来和我们讨论吧，让我们一起想办法把它变得更加简单。 为了提高FTK的可读性，我们采用了下列措施： 1.保持简单。 简单的东西才是容易理解的。从代码量来讲，FTK的代码量只有GTK+的十分之一，总共代码在两万行以内，90%的文件的都是少于600行代码的，80%的模块对外的函数是少于10个的，单个函数基本上都是少于50行代码的。从设计时，FTK也尽量选择简单的模型，比如只支持单进程单线程方式运行(其它线程可以通过idle来串行化对GUI 的访问)，从而避免引入进程间通信机制和并发带来的复杂度，这一点我们在后面有更详细的描述。 2.一致的代码风格。 代码风格的一致性对代码可读性的帮助很大。FTK的文件名、函数名、变量名和类型名都遵循统一的命名风格，FTK中的命名风格和GTK+的命名风格基本上是一致的。FTK所有代码的排版布局也保持高度一致，整体上的代码风格与《系统程序员成长计划》一书介绍的一致，如果你读过《系统程序员成长计划》，再看 FTK的代码就像见到熟人一样。 3.避免复杂的算法。 GUI和图形算法相对是比较复杂的。出人意料的是FTK几乎没有使用任何复杂的算法，连画普通直线和圆弧的算法都没有，更不要说线性代数中那些矩阵变换了。FTK中尽量使用水平线和垂直线来绘制基本的图形，而用图像来实现更复杂更美观的界面，这样就绕开了复杂的图形算法。不过，可以使用可选组件cairo来绘制复杂的矢量图和做些高级的图形变换。 4.设计高内聚的模块。 高内聚简单的说就是一个模块(或函数）只完成单一的功能，单一的功能从逻辑上更容易理解，代码量也更少。要保持简单，设计高内聚的模块是必要条件，把多个功能糅合在一起，自然不可能做得简单了。 5.编写内部实现文档。 隔行如隔山。对于对GUI一点概念都没有的初学者来说，再简单的GUI也是难读的。为了降低初学者阅读FTK的门槛，我们决定写《嵌入式GUI FTK设计与实现》系列文章了，也希望大家都参与进来讨论和完善。 保持简单但是不能太简单。 记得这句话是爱因斯坦说（Keep it simple but not too simple! ）。它的道理是非常明显的，在完成需要的功能的前提下，实现越简单越好。反过来说，实现越简单越好，前提是要完成需要的功能。如果不能实现所需要的功能，再简单又有什么用呢。我们要保持FTK实现上的简单性，但同时我们必须要实现GUI所需要的功能。 记得在开始FTK项目时，我和一位朋友讨论FTK的需求。他说，对于嵌入式GUI，他关心的是，能不能在几K到几十K的内存的系统上使用。我说，这样的小系统，它的界面会很复杂吗，需要一个真正的GUI吗？他后来说不需要。为一个简单得根本不需要GUI的系统设计一个GUI是没有什么意义的，FTK要保持简单，但是不能太简单。 GTK+ 太庞大，不适合在嵌入式系统中使用。而X Window和DirectFB虽然够轻量级，但它们没提供足够的功能，它们离开ToolKit单独使用非常困难。FTK要取其所长避其所短，设计得够简单够小，才能在GTK+等传统GUI不能使用的地方使用，但是又必须要提供GUI常用的元素，对用户才有实用价值。 要够酷够时髦。 之前我也分析过一些其它嵌入式GUI系统，它们通常都是仿照Windows传统的界面风格来实现的。它们的实现确实够轻易级，通常可执行二进制大小在 100K到500K之间，但给我的印象就是太土气了点，不能满足现代消费电子产品的需求(呵，真的不想通过扁别人来提高自己，欢迎对我的作法不满的朋友来扁FTK)。所以在设计FTK时，我一直提醒自己，FTK一定要够酷够时髦。其中主要表现有： 1.支持主题 支持主题是现代GUI的基本特征了。众口难调，没有一个GUI会让所有人喜欢，但是有了主题机制，通过一些数据和图片文件来配置显示风格，可以给用户多种不同的选择。 FTK的主题非常简单，在一个XML中设置各个控件的表现属性(不同状态的颜色和图片)，然后提供相关的图片文件即可。 2.支持窗口动画 窗口动画也是现代GUI吸人眼球的特征之一，是制作各种比较炫的效果的基础。FTK实现了滚动和淡入效果，并提供了一种机制，让开发者实现任何自己想要的效果。 3.支持透明/半透明效果 很多炫的效果离不开透明/半透明机制的支持。在FTK中，不管硬件平台的支持的多少颜色数和颜色格式，每个像素在内存中都由ARGB四个分量组成，其中8bit的alpha通道用来实现透明/半透明效果。 4.支持XML界面描述 XML界面描述也是现代GUI的基本特征了，它的魅力在于分离用户界面和内部实现，让它们能够独立变化。而且借助一些界面构建工具，生成用户界面变得更加容易。FTK实现了一个小巧的XML解析器，以非常轻量级的方式实现了对XML界面描述的支持。 5.支持脚本语言绑定 脚本语言的开发效率相对较高，部署也更加容易，越来越开发者的欢迎。呵，不懂一门脚本语言的程序员经常会被人鄙视的。FTK和其作者们自然不想被人鄙视，所以支持脚本绑定是FTK的首要目标之一，目前已经支持LUA的绑定(还需要进一步完善)。 6.支持输入法(特别是手写) GUI 少了对中日韩文字的支持，注定是要失败的。对中日韩文字的支持包括编码，字体显示和输入法三个主要部分。FTK采用UTF-8编码，可以表示 Unicode中的所有字符。FTK支持点阵(内置)和矢量(需要freetype)字体，所以显示中日韩文字不成问题。输入法相对复杂一点，FTK目前已经支持中文拼音、中文五笔和手写三种最常用的输入方式了。 7.支持屏幕旋转 [...]]]></description>
			<content:encoded><![CDATA[<p>记得X Window在设计初期就提出了七项基本指导原则，在后面X Window几十年的演变过程中，都以这些基本原则作为指导思想。其中给我印象比较深的一条就是：提供机制而不是策略。X Window一直都遵循这条原则，它只提供实现某些功能的机制，而把实现的策略留给ToolKit或其它辅助软件。为了让FTK在以后的演化过程中不至于迷失方向，我们也给FTK定了三项基本原则：<span id="more-1482"></span></p>
<p>第一：程序首先是给人读的，其次才是给机器读的。</p>
<p>程序首先是给人读的，其次才是给机器读的。这句话是很多程序员都认同的，加上FTK最初的目的就是作为《系统程序员成长计划》的综合练习项目，目标是让《系统程序员成长计划》的读者通过阅读FTK的源代码，来学习如何把前面学到的知识应用到一个实际的项目中。所以把FTK代码的可读性放在第一位是理所当然的。</p>
<p>GUI无疑是最复杂的基础软件之一，在我研究过的GUI中，像X Window、DirectFB、 GTK+和MicroWindows，它们都是非常复杂的软件系统。我写过不少关于它们内部实现的文章，但是我现在要非常惭愧的告诉你，这些GUI的实现太复杂了，我其实没有完全搞明白过其中任何一个系统。分析一个GUI系统，对一个工作经验丰富的程序员来说尚且如此困难，对初学者的难度就可想而知了。不过FTK则是希望成为人人可以读懂的GUI系统。如果你在阅读代码的过程遇到了难题，请不要犹豫，大胆的来和我们讨论吧，让我们一起想办法把它变得更加简单。</p>
<p>为了提高FTK的可读性，我们采用了下列措施：</p>
<p>1.保持简单。</p>
<p>简单的东西才是容易理解的。从代码量来讲，FTK的代码量只有GTK+的十分之一，总共代码在两万行以内，90%的文件的都是少于600行代码的，80%的模块对外的函数是少于10个的，单个函数基本上都是少于50行代码的。从设计时，FTK也尽量选择简单的模型，比如只支持单进程单线程方式运行(其它线程可以通过idle来串行化对GUI 的访问)，从而避免引入进程间通信机制和并发带来的复杂度，这一点我们在后面有更详细的描述。</p>
<p>2.一致的代码风格。</p>
<p>代码风格的一致性对代码可读性的帮助很大。FTK的文件名、函数名、变量名和类型名都遵循统一的命名风格，FTK中的命名风格和GTK+的命名风格基本上是一致的。FTK所有代码的排版布局也保持高度一致，整体上的代码风格与《系统程序员成长计划》一书介绍的一致，如果你读过《系统程序员成长计划》，再看 FTK的代码就像见到熟人一样。</p>
<p>3.避免复杂的算法。</p>
<p>GUI和图形算法相对是比较复杂的。出人意料的是FTK几乎没有使用任何复杂的算法，连画普通直线和圆弧的算法都没有，更不要说线性代数中那些矩阵变换了。FTK中尽量使用水平线和垂直线来绘制基本的图形，而用图像来实现更复杂更美观的界面，这样就绕开了复杂的图形算法。不过，可以使用可选组件cairo来绘制复杂的矢量图和做些高级的图形变换。</p>
<p>4.设计高内聚的模块。</p>
<p>高内聚简单的说就是一个模块(或函数）只完成单一的功能，单一的功能从逻辑上更容易理解，代码量也更少。要保持简单，设计高内聚的模块是必要条件，把多个功能糅合在一起，自然不可能做得简单了。</p>
<p>5.编写内部实现文档。</p>
<p>隔行如隔山。对于对GUI一点概念都没有的初学者来说，再简单的GUI也是难读的。为了降低初学者阅读FTK的门槛，我们决定写《嵌入式GUI FTK设计与实现》系列文章了，也希望大家都参与进来讨论和完善。</p>
<p>保持简单但是不能太简单。</p>
<p>记得这句话是爱因斯坦说（Keep it simple but not too simple! ）。它的道理是非常明显的，在完成需要的功能的前提下，实现越简单越好。反过来说，实现越简单越好，前提是要完成需要的功能。如果不能实现所需要的功能，再简单又有什么用呢。我们要保持FTK实现上的简单性，但同时我们必须要实现GUI所需要的功能。</p>
<p>记得在开始FTK项目时，我和一位朋友讨论FTK的需求。他说，对于嵌入式GUI，他关心的是，能不能在几K到几十K的内存的系统上使用。我说，这样的小系统，它的界面会很复杂吗，需要一个真正的GUI吗？他后来说不需要。为一个简单得根本不需要GUI的系统设计一个GUI是没有什么意义的，FTK要保持简单，但是不能太简单。</p>
<p>GTK+ 太庞大，不适合在嵌入式系统中使用。而X Window和DirectFB虽然够轻量级，但它们没提供足够的功能，它们离开ToolKit单独使用非常困难。FTK要取其所长避其所短，设计得够简单够小，才能在GTK+等传统GUI不能使用的地方使用，但是又必须要提供GUI常用的元素，对用户才有实用价值。</p>
<p>要够酷够时髦。</p>
<p>之前我也分析过一些其它嵌入式GUI系统，它们通常都是仿照Windows传统的界面风格来实现的。它们的实现确实够轻易级，通常可执行二进制大小在 100K到500K之间，但给我的印象就是太土气了点，不能满足现代消费电子产品的需求(呵，真的不想通过扁别人来提高自己，欢迎对我的作法不满的朋友来扁FTK)。所以在设计FTK时，我一直提醒自己，FTK一定要够酷够时髦。其中主要表现有：</p>
<p>1.支持主题</p>
<p>支持主题是现代GUI的基本特征了。众口难调，没有一个GUI会让所有人喜欢，但是有了主题机制，通过一些数据和图片文件来配置显示风格，可以给用户多种不同的选择。 FTK的主题非常简单，在一个XML中设置各个控件的表现属性(不同状态的颜色和图片)，然后提供相关的图片文件即可。</p>
<p>2.支持窗口动画</p>
<p>窗口动画也是现代GUI吸人眼球的特征之一，是制作各种比较炫的效果的基础。FTK实现了滚动和淡入效果，并提供了一种机制，让开发者实现任何自己想要的效果。</p>
<p>3.支持透明/半透明效果</p>
<p>很多炫的效果离不开透明/半透明机制的支持。在FTK中，不管硬件平台的支持的多少颜色数和颜色格式，每个像素在内存中都由ARGB四个分量组成，其中8bit的alpha通道用来实现透明/半透明效果。</p>
<p>4.支持XML界面描述</p>
<p>XML界面描述也是现代GUI的基本特征了，它的魅力在于分离用户界面和内部实现，让它们能够独立变化。而且借助一些界面构建工具，生成用户界面变得更加容易。FTK实现了一个小巧的XML解析器，以非常轻量级的方式实现了对XML界面描述的支持。</p>
<p>5.支持脚本语言绑定</p>
<p>脚本语言的开发效率相对较高，部署也更加容易，越来越开发者的欢迎。呵，不懂一门脚本语言的程序员经常会被人鄙视的。FTK和其作者们自然不想被人鄙视，所以支持脚本绑定是FTK的首要目标之一，目前已经支持LUA的绑定(还需要进一步完善)。</p>
<p>6.支持输入法(特别是手写)</p>
<p>GUI 少了对中日韩文字的支持，注定是要失败的。对中日韩文字的支持包括编码，字体显示和输入法三个主要部分。FTK采用UTF-8编码，可以表示 Unicode中的所有字符。FTK支持点阵(内置)和矢量(需要freetype)字体，所以显示中日韩文字不成问题。输入法相对复杂一点，FTK目前已经支持中文拼音、中文五笔和手写三种最常用的输入方式了。</p>
<p>7.支持屏幕旋转</p>
<p>很多手持设备，其屏幕的长度和宽度不一样。而有的内容适合横着看，有的内容适合竖着看，通过重力感应器自动旋转屏幕，可以提高系统的易用性。支持这个功能不难，只是优先级不高，FTK将会在今年支持这个功能。</p>
<p>8.支持手势识别和多点触摸</p>
<p>手势识别可以大大提高系统的易用性，随着触摸屏越来越流行，新一代GUI都支持手势识别了。多点触摸是手势识别的特例，需要硬件支持，从GUI的角度来说，实现难度不大。FTK将在今年支持手势识别和多点触摸，有兴趣的朋友可以来帮助增加这个功能。</p>
<p>欢迎大家参与讨论、学习、开发、编写文档和在产品中使用，让我们一起把FTK做成最好的嵌入式GUI吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1482/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI FTK设计与实现-目录</title>
		<link>http://www.limodev.cn/blog/archives/1476</link>
		<comments>http://www.limodev.cn/blog/archives/1476#comments</comments>
		<pubDate>Fri, 05 Mar 2010 23:24:53 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1476</guid>
		<description><![CDATA[总体介绍 1.FTK的三项基本原则 2.GUI的几种常见模型 3.FTK的分层视图 基本框架 1. 主循环 2. 事件源 3. 显示设备 4. 位图 5. 画布 6. 图片加载 7. 字体与编码 8. Widget 9. 主题 窗口与窗口管理器 1. 窗口 2. 窗口管理器 3. 对话框 4. 状态栏 5. 弹出菜单 各种控件 1. Button 2. Label 3. Entry 4. ProgressBar 5. ... 输入法 1. 输入法框架 2. 拼音/五笔输入法 3. 手写输入法 平台移植 1. X11 [...]]]></description>
			<content:encoded><![CDATA[<pre>
总体介绍
    1.FTK的三项基本原则
    2.GUI的几种常见模型
    3.FTK的分层视图
<span id="more-1476"></span>
基本框架

   1. 主循环
   2. 事件源
   3. 显示设备
   4. 位图
   5. 画布
   6. 图片加载
   7. 字体与编码
   8. Widget
   9. 主题

窗口与窗口管理器

   1. 窗口
   2. 窗口管理器
   3. 对话框
   4. 状态栏
   5. 弹出菜单

各种控件

   1. Button
   2. Label
   3. Entry
   4. ProgressBar
   5. ...

输入法

   1. 输入法框架
   2. 拼音/五笔输入法
   3. 手写输入法

平台移植

   1. X11
   2. FrameBuffer
   3. DirectFB
   4. Windows

其它

   1. XUL
   2. 动画效果
   3. 内存管理
   4. 脚本绑定
</pre>
<p>欢迎大家补充和参与文档编写。</p>
<p>附：<br />
FTK google group开通，欢迎加入交流。<br />
Homepage: 		<a href="https://groups.google.com/group/funnytoolkit">https://groups.google.com/group/funnytoolkit</a><br />
Group email: 	funnytoolkit@googlegroups.com</p>
<p>如果你不会翻墙，请用gmail发邮件给我。谢谢。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1476/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>FTK google group开通，欢迎加入交流。</title>
		<link>http://www.limodev.cn/blog/archives/1470</link>
		<comments>http://www.limodev.cn/blog/archives/1470#comments</comments>
		<pubDate>Sun, 28 Feb 2010 06:44:42 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1470</guid>
		<description><![CDATA[FTK google group开通，欢迎加入交流。 Homepage: https://groups.google.com/group/funnytoolkit Group email: funnytoolkit@googlegroups.com 如果你不会翻墙，请用gmail发邮件给我。谢谢。]]></description>
			<content:encoded><![CDATA[<p>FTK google group开通，欢迎加入交流。</p>
<table border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr valign="baseline">
<td>Homepage:</td>
<td width="4" align="right"></td>
<td width="450"><a href="https://groups.google.com/group/funnytoolkit?lnk=gcamh">https://groups.google.com/group/funnytoolkit</a></td>
</tr>
<tr valign="baseline">
<td>Group email:</td>
<td align="right"></td>
<td><a href="mailto:funnytoolkit@googlegroups.com">funnytoolkit@googlegroups.com</a></td>
</tr>
</tbody>
</table>
<p>如果你不会翻墙，请用gmail发邮件给我。谢谢。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1470/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI ftk-0.3发布</title>
		<link>http://www.limodev.cn/blog/archives/1458</link>
		<comments>http://www.limodev.cn/blog/archives/1458#comments</comments>
		<pubDate>Sat, 27 Feb 2010 13:02:10 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1458</guid>
		<description><![CDATA[经过春节长假的努力，FTK-0.3如期发布，其主要修改有： 引入FtkAllocator接口，用于内存使用情况统计分析。 支持非压缩的BMP图像的解码。 支持拼音输入法。 支持五笔输入法。 实现手写输入法框架。 支持长按事件。 修改了编译脚本的一些小问题。 做了其它一些优化和完善。 特别感谢Huang Riwen兄和Feng HuaJun兄，Riwen兄发现并修改了BMP图像解码中的BUG。HuaJun同意我在FTK使用fitx输入法中的词库。 有兴趣的朋友请到FTK下载源代码。 附： A gui library for embedded system. FTK equals funny tool kit, write it just for fun. General features: Lightweght. Beautiful look and feel. High code quality: design pattern, good code style. Stable: code review, unit test, stress test, valgrind checked. Full [...]]]></description>
			<content:encoded><![CDATA[<p>经过春节长假的努力，FTK-0.3如期发布，其主要修改有：</p>
<div id="postcontent">
<ul>
<li> 引入FtkAllocator接口，用于内存使用情况统计分析。</li>
<li> 支持非压缩的BMP图像的解码。</li>
<li> 支持拼音输入法。</li>
<li> 支持五笔输入法。</li>
<li> 实现手写输入法框架。</li>
<li>支持长按事件。</li>
<li> 修改了编译脚本的一些小问题。</li>
<li> 做了其它一些优化和完善。</li>
</ul>
<p>特别感谢Huang Riwen兄和Feng HuaJun兄，Riwen兄发现并修改了BMP图像解码中的BUG。HuaJun同意我在FTK使用<a title="fitx输入法" href="http://code.google.com/p/fitx/" target="_blank">fitx输入法</a>中的词库。</p>
<p>有兴趣的朋友请到<a href="http://code.google.com/p/ftk/downloads/list">FTK</a>下载源代码。<span id="more-1458"></span></p>
<p>附：<br />
A gui library for embedded system. FTK equals funny tool kit, write it just for fun.</p>
<p><img src="../../gallery/albums/blog-pictures/ftk/logo.png" alt="ftk" /><span id="more-1428"> </span></p>
<p>General features:</p>
<ul>
<li> Lightweght.</li>
<li> Beautiful look and feel.</li>
<li> High code quality: design pattern, good code style.</li>
<li> Stable: code review, unit test, stress test, valgrind checked.</li>
<li> Full gui features: window, dialog, panel, button, menu…</li>
<li> Good portability: Unix, Windows, RTOS…</li>
</ul>
<p>Modern features:</p>
<ul>
<li> Theme.</li>
<li> Window animation.</li>
<li> Alpha channel to implement transparent/translucent window.</li>
<li> XML UI description language.</li>
<li> Script binding.</li>
<li> InputMethod with Handwrite(working)</li>
<li> Screen rotation(TODO).</li>
<li> Guesture recognition(TODO).</li>
</ul>
</div>
<div id="postcontent">输入法截图：</div>
<p><span> </span></p>
<div>
<p>目前只是entry加了输入法支持，等稳定后再加到text_view里。可以运行demo_ime测试，在entry上长按mouse左键弹出输入法选择框。</p>
<p>输入法选择：<br />
<img src="../../gallery/albums/blog-pictures/ftk/ime-choose.png" alt="ime-choose" /></p>
<p>拼音输入法：<br />
<img src="../../gallery/albums/blog-pictures/ftk/ime-pinyin.png" alt="ime-pinyin" /></p>
<p>五笔输入法：<br />
<img src="../../gallery/albums/blog-pictures/ftk/ime-wubi.png" alt="ime-wubi" /></p>
<p>手写输入法：<br />
<img src="../../gallery/albums/blog-pictures/ftk/ime-hw.png" alt="ime-hw" /><br />
<!--more--></div>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1458/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>在终端下修改Broncho A1的系统设置</title>
		<link>http://www.limodev.cn/blog/archives/1453</link>
		<comments>http://www.limodev.cn/blog/archives/1453#comments</comments>
		<pubDate>Tue, 23 Feb 2010 10:30:05 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Broncho-A1-Hack]]></category>
		<category><![CDATA[a1]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[broncho]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1453</guid>
		<description><![CDATA[一位朋友玩Broncho A1的锁屏图案，结果手机被锁住了，输入google ID也不行(在我这里可以）。恢复系统吧，他又不想重装所有软件，于是我研究了一下在命令行修改系统设置的方法。他不是搞技术的，所以我让他把 settings.db改个名或者删除掉，不过那样做有点暴力。这里介绍一种稍微麻烦但更友好一点的方法。 1.先要编译一个sqlite3命令行工具（external/sqlite/dist）。 （需要在Android.mk里把LOCAL_MODULE_TAGS := debug一行注释掉） 2.把编译好的sqlite3上传到A1上。 # adb push out/target/product/littleton/system/xbin/sqlite3 /data 3.用串口或adb连接到A1的终端上。 adb shell # cd /data # chmod 775 sqlite3 4.用sqlite3操作数据系统设置数据库。 # ./sqlite3 /data/data/com.android.providers.settings/databases/settings.db 查看数据库中的表： sqlite&#62; .tables android_metadata bookmarks secure bluetooth_devices gservices system 查看表system中的内容： sqlite&#62; select * from system; 1&#124;volume_music&#124;11 3&#124;volume_system&#124;5 5&#124;volume_alarm&#124;6 7&#124;mode_ringer&#124;2 8&#124;vibrate_on&#124;4 9&#124;mode_ringer_streams_affected&#124;38 10&#124;mute_streams_affected&#124;46 11&#124;dim_screen&#124;1 12&#124;stay_on_while_plugged_in&#124;0 13&#124;screen_off_timeout&#124;60000 14&#124;airplane_mode_on&#124;0 15&#124;airplane_mode_radios&#124;cell,bluetooth,wifi [...]]]></description>
			<content:encoded><![CDATA[<p>一位朋友玩Broncho A1的锁屏图案，结果手机被锁住了，输入google ID也不行(在我这里可以）。恢复系统吧，他又不想重装所有软件，于是我研究了一下在命令行修改系统设置的方法。他不是搞技术的，所以我让他把 settings.db改个名或者删除掉，不过那样做有点暴力。这里介绍一种稍微麻烦但更友好一点的方法。<span id="more-1453"></span></p>
<p>1.先要编译一个sqlite3命令行工具（external/sqlite/dist）。<br />
（需要在Android.mk里把LOCAL_MODULE_TAGS := debug一行注释掉）</p>
<p>2.把编译好的sqlite3上传到A1上。</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># adb push out/target/product/littleton/system/xbin/sqlite3 /data</span></pre></div></div>

<p>3.用串口或adb连接到A1的终端上。</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">adb shell
<span style="color: #666666; font-style: italic;"># cd /data</span>
<span style="color: #666666; font-style: italic;"># chmod 775 sqlite3</span></pre></div></div>

<p>4.用sqlite3操作数据系统设置数据库。</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># ./sqlite3 /data/data/com.android.providers.settings/databases/settings.db</span></pre></div></div>

<p>查看数据库中的表：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">sqlite<span style="color: #000000; font-weight: bold;">&gt;</span> .tables
android_metadata   bookmarks          secure           
bluetooth_devices  gservices          system</pre></div></div>

<p>查看表system中的内容：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">sqlite<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">select</span> <span style="color: #000000; font-weight: bold;">*</span> from system;
<span style="color: #000000;">1</span><span style="color: #000000; font-weight: bold;">|</span>volume_music<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">11</span>
<span style="color: #000000;">3</span><span style="color: #000000; font-weight: bold;">|</span>volume_system<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">5</span>
<span style="color: #000000;">5</span><span style="color: #000000; font-weight: bold;">|</span>volume_alarm<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">6</span>
<span style="color: #000000;">7</span><span style="color: #000000; font-weight: bold;">|</span>mode_ringer<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">2</span>
<span style="color: #000000;">8</span><span style="color: #000000; font-weight: bold;">|</span>vibrate_on<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">4</span>
<span style="color: #000000;">9</span><span style="color: #000000; font-weight: bold;">|</span>mode_ringer_streams_affected<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">38</span>
<span style="color: #000000;">10</span><span style="color: #000000; font-weight: bold;">|</span>mute_streams_affected<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">46</span>
<span style="color: #000000;">11</span><span style="color: #000000; font-weight: bold;">|</span>dim_screen<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">12</span><span style="color: #000000; font-weight: bold;">|</span>stay_on_while_plugged_in<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">0</span>
<span style="color: #000000;">13</span><span style="color: #000000; font-weight: bold;">|</span>screen_off_timeout<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">60000</span>
<span style="color: #000000;">14</span><span style="color: #000000; font-weight: bold;">|</span>airplane_mode_on<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">0</span>
<span style="color: #000000;">15</span><span style="color: #000000; font-weight: bold;">|</span>airplane_mode_radios<span style="color: #000000; font-weight: bold;">|</span>cell,bluetooth,wifi
<span style="color: #000000;">16</span><span style="color: #000000; font-weight: bold;">|</span>auto_time<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">17</span><span style="color: #000000; font-weight: bold;">|</span>screen_brightness<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">102</span>
<span style="color: #000000;">18</span><span style="color: #000000; font-weight: bold;">|</span>window_animation_scale<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1.0</span>
<span style="color: #000000;">19</span><span style="color: #000000; font-weight: bold;">|</span>transition_animation_scale<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">0.0</span>
<span style="color: #000000;">20</span><span style="color: #000000; font-weight: bold;">|</span>accelerometer_rotation<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">21</span><span style="color: #000000; font-weight: bold;">|</span>dtmf_tone<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">0</span>
<span style="color: #000000;">22</span><span style="color: #000000; font-weight: bold;">|</span>date_format<span style="color: #000000; font-weight: bold;">|</span>MM-dd-yyyy
<span style="color: #000000;">23</span><span style="color: #000000; font-weight: bold;">|</span>notify_led_color<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">255</span>
<span style="color: #000000;">24</span><span style="color: #000000; font-weight: bold;">|</span>notify_incoming_call<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">25</span><span style="color: #000000; font-weight: bold;">|</span>notify_missed_call<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">26</span><span style="color: #000000; font-weight: bold;">|</span>notify_SMS_MMS<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">27</span><span style="color: #000000; font-weight: bold;">|</span>notify_email<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">28</span><span style="color: #000000; font-weight: bold;">|</span>notify_voice_mail<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">29</span><span style="color: #000000; font-weight: bold;">|</span>notify_remind<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">63</span><span style="color: #000000; font-weight: bold;">|</span>volume_voice<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">4</span>
<span style="color: #000000;">64</span><span style="color: #000000; font-weight: bold;">|</span>volume_voice_last_audible<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">4</span>
<span style="color: #000000;">73</span><span style="color: #000000; font-weight: bold;">|</span>lock_pattern_tactile_feedback_enabled<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">0</span>
<span style="color: #000000;">111</span><span style="color: #000000; font-weight: bold;">|</span>lock_pattern_visible_pattern<span style="color: #000000; font-weight: bold;">|</span>１
<span style="color: #000000;">122</span><span style="color: #000000; font-weight: bold;">|</span>font_scale<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1.0</span>
<span style="color: #000000;">127</span><span style="color: #000000; font-weight: bold;">|</span>next_alarm_formatted<span style="color: #000000; font-weight: bold;">|</span>
<span style="color: #000000;">129</span><span style="color: #000000; font-weight: bold;">|</span>lock_pattern_autolock<span style="color: #000000; font-weight: bold;">|</span>１
<span style="color: #000000;">130</span><span style="color: #000000; font-weight: bold;">|</span>lockscreen.patterneverchosen<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span>
<span style="color: #000000;">131</span><span style="color: #000000; font-weight: bold;">|</span>volume_notification<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">5</span>
<span style="color: #000000;">132</span><span style="color: #000000; font-weight: bold;">|</span>volume_notification_last_audible<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">5</span>
<span style="color: #000000;">133</span><span style="color: #000000; font-weight: bold;">|</span>volume_ring<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">5</span>
<span style="color: #000000;">134</span><span style="color: #000000; font-weight: bold;">|</span>volume_ring_last_audible<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">5</span>
<span style="color: #000000;">135</span><span style="color: #000000; font-weight: bold;">|</span>lockscreen.lockedoutpermanently<span style="color: #000000; font-weight: bold;">|</span><span style="color: #000000;">1</span></pre></div></div>

<p>查看表system的schema:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">sqlite<span style="color: #000000; font-weight: bold;">&gt;</span> .schema system
CREATE TABLE system <span style="color: #7a0874; font-weight: bold;">&#40;</span>_id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT UNIQUE ON CONFLICT REPLACE,value TEXT<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
CREATE INDEX systemIndex1 ON system <span style="color: #7a0874; font-weight: bold;">&#40;</span>name<span style="color: #7a0874; font-weight: bold;">&#41;</span>;</pre></div></div>

<p>修改表中相关内容：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">sqlite<span style="color: #000000; font-weight: bold;">&gt;</span> update system <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">value</span>=<span style="color: #ff0000;">'0'</span> where <span style="color: #007800;">name</span>=<span style="color: #ff0000;">'lockscreen.lockedoutpermanently'</span>;
sqlite<span style="color: #000000; font-weight: bold;">&gt;</span> update system <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">value</span>=<span style="color: #ff0000;">'0'</span> where <span style="color: #007800;">name</span>=<span style="color: #ff0000;">'lock_pattern_autolock'</span>;
sqlite<span style="color: #000000; font-weight: bold;">&gt;</span> update system <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #007800;">value</span>=<span style="color: #ff0000;">'0'</span> where <span style="color: #007800;">name</span>=<span style="color: #ff0000;">'lock_pattern_visible_pattern'</span>;</pre></div></div>

<p>退出数据库：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">sqlite<span style="color: #000000; font-weight: bold;">&gt;</span> .quit</pre></div></div>

<p>5.重启Broncho A1：</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">/</span>data <span style="color: #666666; font-style: italic;"># reboot</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1453/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI FTK支持输入法</title>
		<link>http://www.limodev.cn/blog/archives/1446</link>
		<comments>http://www.limodev.cn/blog/archives/1446#comments</comments>
		<pubDate>Sun, 21 Feb 2010 14:32:41 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1446</guid>
		<description><![CDATA[春节期间给FTK增加输入法支持，目前支持拼音输入法，五笔输入法和手写输入法。手写输入法只是实现了框架，识别引擎才开个头，这是今年FTK开发的重点任务。拼音输入法，五笔输入法的基本功能都可以用了吧，易用性方面还需要进一步完善。 这样配置：./configure &#8211;with-backend=linux-x11:320&#215;480 &#8211;with-fontengine=freetype &#8211;enable-cairo &#8211;enable-handwrite 目前只是entry加了输入法支持，等稳定后再加到text_view里。可以运行demo_ime测试，在entry上长按mouse左键弹出输入法选择框。 输入法选择： 拼音输入法： 五笔输入法： 手写输入法：]]></description>
			<content:encoded><![CDATA[<p>春节期间给FTK增加输入法支持，目前支持拼音输入法，五笔输入法和手写输入法。手写输入法只是实现了框架，识别引擎才开个头，这是今年FTK开发的重点任务。拼音输入法，五笔输入法的基本功能都可以用了吧，易用性方面还需要进一步完善。<span id="more-1446"></span></p>
<p>这样配置：./configure &#8211;with-backend=linux-x11:320&#215;480 &#8211;with-fontengine=freetype &#8211;enable-cairo &#8211;enable-handwrite</p>
<p>目前只是entry加了输入法支持，等稳定后再加到text_view里。可以运行demo_ime测试，在entry上长按mouse左键弹出输入法选择框。</p>
<p>输入法选择：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ime-choose.png" alt="ime-choose" /></p>
<p>拼音输入法：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ime-pinyin.png" alt="ime-pinyin" /></p>
<p>五笔输入法：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ime-wubi.png" alt="ime-wubi" /></p>
<p>手写输入法：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ime-hw.png" alt="ime-hw" /><br />
<!--more--></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1446/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>改用gmail了：xianjimli at gmail.com</title>
		<link>http://www.limodev.cn/blog/archives/1444</link>
		<comments>http://www.limodev.cn/blog/archives/1444#comments</comments>
		<pubDate>Sat, 20 Feb 2010 14:36:53 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1444</guid>
		<description><![CDATA[hotmail的邮件搜索功能太难用了，逼着我用gmail了:xianjimli at gmail.com]]></description>
			<content:encoded><![CDATA[<p>hotmail的邮件搜索功能太难用了，逼着我用gmail了:xianjimli at gmail.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1444/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>嵌入式GUI ftk-0.2发布</title>
		<link>http://www.limodev.cn/blog/archives/1428</link>
		<comments>http://www.limodev.cn/blog/archives/1428#comments</comments>
		<pubDate>Sun, 31 Jan 2010 03:54:28 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[FTK(嵌入式GUI)]]></category>
		<category><![CDATA[FTK]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1428</guid>
		<description><![CDATA[经过一个月的努力，FTK-0.2如期发布，其主要修改有： 修改了一些BUG，对代码做了一些优化。考虑到RTOS不支持select，所以去掉了main loop对pipe的依赖，提高FTK的可移植性。 移植到Windows平台，加了VS2008 Express Edition的工程文件。 增加了MessageBox和Tips的支持。 增加了弹出菜单的支持。 增加了ComboBox的支持。 增加了窗口从中间向四周扩展的效果。 增加窗口淡入效果。 对话框支持模态和非模态两种。 增加了C++调用的支持。 增加了Cursor的支持，由&#8211;enable-cursor命令行参数决定。 有兴趣的朋友请到FTK下载源代码。 附： A gui library for embedded system. FTK equals funny tool kit, write it just for fun. General features: Lightweght. Beautiful look and feel. High code quality: design pattern, good code style. Stable: code review, unit test, stress test, valgrind [...]]]></description>
			<content:encoded><![CDATA[<p>经过一个月的努力，FTK-0.2如期发布，其主要修改有：</p>
<ul>
<li> 修改了一些BUG，对代码做了一些优化。考虑到RTOS不支持select，所以去掉了main loop对pipe的依赖，提高FTK的可移植性。</li>
<li> 移植到Windows平台，加了VS2008 Express Edition的工程文件。</li>
<li> 增加了MessageBox和Tips的支持。</li>
<li> 增加了弹出菜单的支持。</li>
<li> 增加了ComboBox的支持。</li>
<li> 增加了窗口从中间向四周扩展的效果。</li>
<li> 增加窗口淡入效果。</li>
<li> 对话框支持模态和非模态两种。</li>
<li> 增加了C++调用的支持。</li>
<li> 增加了Cursor的支持，由&#8211;enable-cursor命令行参数决定。</li>
</ul>
<p>有兴趣的朋友请到<a href="http://code.google.com/p/ftk/downloads/list">FTK</a>下载源代码。</p>
<p>附：<br />
A gui library for embedded system. FTK equals funny tool kit, write it just for fun.</p>
<p><img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/logo.png" alt="ftk" /><span id="more-1428"></span></p>
<p>General features:</p>
<ul>
<li> Lightweght.</li>
<li> Beautiful look and feel.</li>
<li> High code quality: design pattern, good code style.</li>
<li> Stable: code review, unit test, stress test, valgrind checked.</li>
<li> Full gui features: window, dialog, panel, button, menu&#8230;</li>
<li> Good portability: Unix, Windows, RTOS&#8230;</li>
</ul>
<p>Modern features:</p>
<ul>
<li> Theme.</li>
<li> Window animation.</li>
<li> Alpha channel to implement transparent/translucent window.</li>
<li> XML UI description language.</li>
<li> Script binding.</li>
<li> InputMethod with Handwrite(working)</li>
<li> Screen rotation(TODO).</li>
<li> Guesture recognition(TODO).</li>
</ul>
<p>FTK-0.2 Release Notes:</p>
<ul>
<li> Bug fix &amp; optimization.</li>
<li> MS windows supported(vs2008 express edition)</li>
<li> Message box</li>
<li> Popup menu</li>
<li> ComboBox</li>
<li> Brink expand animator.</li>
<li> Alpha animator.</li>
<li> Support normal dialog and modal dialog.</li>
<li> Support C++ caller</li>
<li> add &#8211;enable-cursor command line option.</li>
</ul>
<p>ComboBox截图：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-2/combobox.png" alt="combobox" /></p>
<p>MessageBox截图：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-2/messagebox.png" alt="messagebox" /></p>
<p>Popup Menu截图：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-2/pupup_menu.png" alt="Popup" /></p>
<p>Tips截图：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-2/tips.png" alt="tips" /></p>
<p>其它一些改善：<br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-2/dialog.png" alt="dialog" /><br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-2/icon_view.png" alt="iconview" /><br />
<img src="http://www.limodev.cn/gallery/albums/blog-pictures/ftk/ftk-0-2/list_view.png" alt="listview" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1428/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PC通过Android手机(Broncho A1)访问Internet</title>
		<link>http://www.limodev.cn/blog/archives/1422</link>
		<comments>http://www.limodev.cn/blog/archives/1422#comments</comments>
		<pubDate>Mon, 25 Jan 2010 14:34:06 +0000</pubDate>
		<dc:creator>李先静</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[a1]]></category>

		<guid isPermaLink="false">http://www.limodev.cn/blog/?p=1422</guid>
		<description><![CDATA[Broncho A1和普通Android手机一样，不能直接拿来当modem使用，不过可以把它当作一个网关或代理，这样，PC就可以通过A1来访问Internet 了。今天用privoxy(http://www.privoxy.org/)试了一下，工作正常，具体步骤如下： 1. 下载 privoxy-3.0.15-beta-src.tar.gz 2. 解压到android/extern目录中。 3. 先编译一个正常Linux的版本。 cd external/privoxy-3.0.15-beta; autoheader &#38;&#38; autoconf &#38;&#38; ./configure --disable-acl-files; make 4. 创建一个Android.mk # # Copyright : Written by and Copyright (C) 2010 Li XianJing &#60;xianjimli@hotmail.com&#62; # LOCAL_PATH:= $&#40;call my-dir&#41; &#160; include $&#40;CLEAR_VARS&#41; &#160; LOCAL_C_CFLAGS=-DANDROID LOCAL_C_INCLUDES += external/privoxy/pcre external/privoxy external/zlib LOCAL_SRC_FILES:= actions.c cgi.c cgiedit.c cgisimple.c deanimate.c \ [...]]]></description>
			<content:encoded><![CDATA[<p>Broncho A1和普通Android手机一样，不能直接拿来当modem使用，不过可以把它当作一个网关或代理，这样，PC就可以通过A1来访问Internet 了。今天用privoxy(http://www.privoxy.org/)试了一下，工作正常，具体步骤如下：<span id="more-1422"></span></p>
<p>1. 下载 privoxy-3.0.15-beta-src.tar.gz</p>
<p>2. 解压到android/extern目录中。</p>
<p>3. 先编译一个正常Linux的版本。</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> external<span style="color: #000000; font-weight: bold;">/</span>privoxy-3.0.15-beta;
<span style="color: #c20cb9; font-weight: bold;">autoheader</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">autoconf</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> .<span style="color: #000000; font-weight: bold;">/</span>configure --disable-acl-files;
<span style="color: #c20cb9; font-weight: bold;">make</span></pre></div></div>

<p>4. 创建一个Android.mk</p>

<div class="wp_syntax"><div class="code"><pre class="make" style="font-family:monospace;"><span style="color: #339900; font-style: italic;">#</span>
<span style="color: #339900; font-style: italic;"># Copyright :  Written by and Copyright (C) 2010 Li XianJing &lt;xianjimli@hotmail.com&gt;</span>
<span style="color: #339900; font-style: italic;">#</span>
LOCAL_PATH<span style="color: #004400;">:=</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #0000CC; font-weight: bold;">call</span> my<span style="color: #004400;">-</span>dir<span style="color: #004400;">&#41;</span>
&nbsp;
<span style="color: #666622; font-weight: bold;">include</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">CLEAR_VARS</span><span style="color: #004400;">&#41;</span>
&nbsp;
LOCAL_C_CFLAGS<span style="color: #004400;">=-</span>DANDROID
LOCAL_C_INCLUDES <span style="color: #004400;">+=</span> external<span style="color: #004400;">/</span>privoxy<span style="color: #004400;">/</span>pcre external<span style="color: #004400;">/</span>privoxy external<span style="color: #004400;">/</span>zlib
LOCAL_SRC_FILES<span style="color: #004400;">:=</span> actions<span style="color: #004400;">.</span>c cgi<span style="color: #004400;">.</span>c cgiedit<span style="color: #004400;">.</span>c cgisimple<span style="color: #004400;">.</span>c deanimate<span style="color: #004400;">.</span>c \
    encode<span style="color: #004400;">.</span>c errlog<span style="color: #004400;">.</span>c filters<span style="color: #004400;">.</span>c gateway<span style="color: #004400;">.</span>c jbsockets<span style="color: #004400;">.</span>c jcc<span style="color: #004400;">.</span>c list<span style="color: #004400;">.</span>c \
    loadcfg<span style="color: #004400;">.</span>c loaders<span style="color: #004400;">.</span>c miscutil<span style="color: #004400;">.</span>c parsers<span style="color: #004400;">.</span>c ssplit<span style="color: #004400;">.</span>c urlmatch<span style="color: #004400;">.</span>c  \
    pcrs<span style="color: #004400;">.</span>c pcre<span style="color: #004400;">/</span>get<span style="color: #004400;">.</span>c pcre<span style="color: #004400;">/</span>maketables<span style="color: #004400;">.</span>c pcre<span style="color: #004400;">/</span>study<span style="color: #004400;">.</span>c pcre<span style="color: #004400;">/</span>pcre<span style="color: #004400;">.</span>c \
    pcre<span style="color: #004400;">/</span>pcreposix<span style="color: #004400;">.</span>c
&nbsp;
LOCAL_MODULE <span style="color: #004400;">:=</span> privoxy
&nbsp;
LOCAL_SHARED_LIBRARIES <span style="color: #004400;">:=</span> libc
LOCAL_STATIC_LIBRARIES <span style="color: #004400;">:=</span> libz
<span style="color: #666622; font-weight: bold;">include</span> <span style="color: #004400;">$</span><span style="color: #004400;">&#40;</span><span style="color: #000088;">BUILD_EXECUTABLE</span><span style="color: #004400;">&#41;</span></pre></div></div>

<p>5. 修改一下miscutil.c</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#if !defined(HAVE_TIMEGM) &amp;&amp; defined(HAVE_TZSET) &amp;&amp; defined(HAVE_PUTENV)</span>
<span style="color: #339933;">--&gt;</span>
<span style="color: #339933;">#if !defined(HAVE_TIMEGM) &amp;&amp; defined(HAVE_TZSET) &amp;&amp; defined(HAVE_PUTENV) || defined(ANDROID)</span></pre></div></div>

<p>6. 编译(先设置Android的环境)</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mm</pre></div></div>

<p>7. 上传下列文件到Broncho A1</p>
<pre>
default.filter
user.action
default.action
match-all.action
config
privoxy
</pre>
<p>8. 在Broncho A1上运行代理。</p>
<pre>
./privoxy &#038;
</pre>
<p>9. 在PC端设置tcp转发</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">adb forward tcp:<span style="color: #000000;">8118</span> tcp:<span style="color: #000000;">8118</span></pre></div></div>

<p>10. 把浏览器的代理设置为localhost 8118</p>
<p>好了，PC就可以通过Broncho A1访问Internet了。</p>
<p>大家也可以到这里下载编译好的版本(包括源代码）: <a href="http://www.limodev.cn/download/privoxy-broncho-a1.tar.gz">http://www.limodev.cn/download/privoxy-broncho-a1.tar.gz</a><br />
解压后，把privoxy-3.0.15-beta/for-broncho-a1/目录中的文件上传到Broncho A1上，参考本文的最后几步即可用A1访问Internet。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.limodev.cn/blog/archives/1422/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
