帆's profile思想坐标PhotosBlogLists Tools Help
Photo 1 of 1

思想坐标

September 12

为Adobe Acrobat 编写插件

在看pdf的时候,经常遇到一个烦心的问题,书签里的链接打开后,页面不是叶宽显示,而是显示的一整页,还要手动去选。专门研究了一下,写了一个JavaScript脚本,来解决这个问题。顺便说一下,Acrobat的JavaScript真烂。

   1: function SetBookmarksWidthPage(bm, nLevel)
   2: {
   3:         if(nLevel!=0)
   4:     {
   5:         console.println(bm.name+event.target.pageNum);
   6:         bm.execute(); 
   7:  
   8:         bm.setAction("this.pageNum="+event.target.pageNum+";this.zoomType = zoomtype.fitW;")
   9:     }
  10:     if (bm.children != null)
  11:         for (var i = 0; i < bm.children.length; i++)
  12:              SetBookmarksWidthPage(bm.children[i], nLevel + 1); 
  13:  
  14: }
  15: app.addMenuItem({ cName: "Reset Bookmark View", cParent: "Advanced",
  16: cExec: "SetBookmarksWidthPage(event.target.bookmarkRoot, 0);",
  17: cEnable: "event.rc = (event.target != null);",
  18: nPos: 0
  19: }); 

会在“高级”菜单下添加一项"Reset Bookmark View"。

可是这样依然有个问题,书签里的Action显示的是Script,而不是象其他标准的显示的时Goto Destination。没办法,只好用C了。

   1: ACCB1 ASBool ACCB2 MyPluginSetmenu()
   2: {
   3:     return PluginMenuItem("Set Bookmark Fit Visable", "ADBE:BookmarkFit", false); 
   4: }
   5: void iteratebookmark(PDBookmark bookmark,PDDoc doc)
   6: { 
   7:  
   8:     PDAction action = PDBookmarkGetAction(bookmark);
   9:     ASAtom atom = PDActionGetSubtype (action);
  10:     if(!strcmp(ASAtomGetString (atom),"GoTo"))
  11:     {
  12:         //AVAlertNote(ASAtomGetString (atom));
  13:         PDViewDestination dest = PDActionGetDest(action);
  14:         ASInt32 pageNum;
  15:         ASAtom fitType;
  16:         ASFixedRect destRect;
  17:         ASFixed zoom;
  18:         //AVAlertNote("done1");
  19:         PDViewDestGetAttr(dest,&pageNum,&fitType,&destRect,&zoom);
  20:         //AVAlertNote("done2");
  21:         PDViewDestination newdest = PDViewDestCreate(doc,PDDocAcquirePage (doc, pageNum),ASAtomFromString("FitBV"),&destRect,PDViewDestNULL, 0);
  22:         PDAction newaction = PDActionNewFromDest ( doc,newdest,doc);
  23:         PDBookmarkSetAction ( bookmark,newaction);
  24:         //AVAlertNote("done3");
  25:     }
  26:     if (PDBookmarkHasChildren (bookmark))
  27:     {
  28:         PDBookmark treeBookmark = PDBookmarkGetFirstChild(bookmark);
  29:         while (PDBookmarkIsValid (treeBookmark))
  30:         {
  31:             iteratebookmark (treeBookmark,doc);
  32:             treeBookmark = PDBookmarkGetNext(treeBookmark);
  33:         }
  34:     }
  35: }
  36: ACCB1 void ACCB2 MyPluginCommand(void *clientData)
  37: {
  38:     // get this plugin's name for display
  39:     ASAtom NameAtom = ASExtensionGetRegisteredName (gExtensionID);
  40:     const char * name = ASAtomGetString(NameAtom);
  41:     char str[256];
  42:     sprintf(str,"This menu item is added by plugin %s.\n", name); 
  43:     AVDoc avDoc = AVAppGetActiveDoc(); 
  44:  
  45:     if(avDoc==NULL) {
  46:         // if no doc is loaded, make a message.
  47:         //strcat(str,);
  48:         AVAlertNote("There is no PDF document loaded in Acrobat.");
  49:     }
  50:     else {
  51:         PDBookmark theroot;
  52:         PDDoc pddoc = AVDocGetPDDoc (avDoc);
  53:         theroot = PDDocGetBookmarkRoot(pddoc);
  54:         iteratebookmark(theroot,pddoc);
  55:         return;
  56:     }
  57:     return;
  58: } 
  59:  
  60: ACCB1 ASBool ACCB2 MyPluginIsEnabled(void *clientData)
  61: {
  62:     return AVAppGetActiveDoc()!=NULL;
  63: } 

依然是一个递归算法。只需要和Acrobat SDK里面的Basic Plugin的BasicPluginInit.cpp结合就可以使用了。生成的.api文件实际上是一个dll。

可是这样还是不够完美。书签属性里面,Zoom显示的是Custom,而不是Fit Width。想不出什么原因了。。。

PDViewDestCreate所使用的ASAtom,可以由以下几种String得到:FitBV,FitBH,FitH, FitV, FitR, FitB, Fit, XYZ。Acrobat的文档上竟然没有,还是从http://itext.ugent.be/library/api/com/lowagie/text/pdf/PdfDestination.html找到的。

October 04

政治倾向测试

Your political compass

Economic Left/Right: -4.25
Social Libertarian/Authoritarian: 1.54

http://politicalcompass.org/questionnaire

留做标记,看看多年以后我会不会变

职业生涯规划

每一个有志于技术的IT人都面临着职业规划的选择。
第一,成为软件工程人员,设计桌面软件,网络软件,游戏,嵌入式软件等。面临的问题是竞争激烈,工作辛苦。
第二,成为软件研究人员,研究算法,可是门槛很高,对个人的要求很高
第三,成为硬件工程人员,设计电路、PCB,他和软件工程人员很相像
第四,成为芯片设计人员,问题是对公司和资金的依赖太大,难于开创自己的事业
第五,成为硬件研究人员,大部分中国人都没有条件选择。
软件工程人员可以向软件研究人员转变。而其他几类之间转变很困难。
选择了硬件这条路,出于三点考虑。其一是由于觉得软件的门槛太低,竞争过于激烈;其二是觉得学习硬件设计有利于今后创业;最后是觉得学习硬件可为软件设计打下基础。
然而,我对这些初衷越来越感怀疑。第一,普通的程序员门槛固然很低,但软件行业的职业发展空间很大。例如图形图像、人工智能、并行计算这些都需要深厚的积累,而这样的高端人才的回报是很丰厚的。第二,电路设计和嵌入式软件的设计联系紧密,但从整个电子行业来说,嵌入式设计依然属于低端。第三,电路设计的基础,很难成为高端电子技术的基石。
其实,这与国内大学的大环境有关。学习硬件设计需要很好的外部条件,包括高端设备和项目。在国内,很遗憾,这些都不具备。
选择软件,道路就会完全不同。在软件技术上,很容易追随国外最尖端的技术热点。也更容易实现技术突破和创新。
如果照着目前的道路走下去,我会成为一名工程师,而离研究型的专家越来越远。怎样改变这一点,我还没有找到答案。
February 07

Firefox 开发者插件

这些插件是专为开发者设计,有了这些工具,总算能稍微轻松一点。呼唤IDE!

1、Firebug
极品插件,动态查看各种元素的所有属性,执行JavaScript,查看CSS,开发必备。
2、Dom Inspector
浏览DOM结构,比较清晰
3、Locale Swticher
可以在安装的多个语言的Firefox中切换,方便软件翻译测试
4、Venkman JavaScript Debuger
似乎很强大,但是运行很缓慢
5、RDF Viewer
浏览RDF数据库结构,小巧方便,而且是我亲自操刀的。呵呵。
February 06

第一个成功的Firefox插件

在第一次尝试写插件可惜的失败后,费了一天的功夫,终于写出一个像样的插件。这里面融合了第一次尝试的许多成果。可是还是为了许多细节问题大费周章。比方说(该问题浪费我两小时):
.properties 必须以#COMMON打头,必须是一种特殊的utf-8格式。这种格式在Windows环境下很难生成。以上描述可能不够准确,可我也不想去细究了。以后有空再说吧。这几句话可使我经过上千次实验才得出的,因为我没有找到任何文档提及到这几点。唉!Mozilla 还有很多地方的改进阿。

我写的这个插件,可以以树状结构浏览RDF文件,可以展示RDF的全部内部结构。现在正交由Mozilla得人审查。

希望Bug不要太多!
February 05

在Firefox中打开一个新标签页

要实现的功能为,若当前标签页为空白页,则在当前页打开,否则新建一个标签页。该功能仅在XUL插件内有效。

        var browser=document.getElementById("content");
        if(browser.currentURI.path=="blank")
        {
            browser.loadURI(url);
        }
        else
        {
            var tab = browser.addTab(url);
            browser.selectedTab=tab;
        }

browser是一个XUL对象,browser.currentURI是一个XPCOM对象。
February 04

XULRunner

上次说到Mozilla想做开发平台,这次他真的放出来一个XULRunner,也就是一个独立的XUL运行平台,不依赖于Firefox。
虽然有了一点Firefox Extension的开发经验,可这次还是把我折腾得够呛。经常由于编码、空格、中英文标点方便的错误调试半天,因为不管是Firefox还是XULRunner,一点错误提示都不给。

一个最简单的XUL独立应用程序如下:
要建立如下目录结构
/AppName
   application.ini
   /chrome
        chrome.manifest
        /AppContent
   /defauls
        /preferences
             prefs.js

其中,chrome目录下的内容和Firefox插件的内容差不多。重点是application.ini。

Application.ini:

[App]
Name=HelloWorld
BuildID=2005041916
[Gecko]
MinVersion=1.8
MaxVersion=1.9a1

所必需的只有这四个字段。注意行末千万不能有空格,否则什么都不会有!Mozilla的容错性也太差了。

对于prefs.js,也只有一行:
pref("toolkit.defaultChromeURI", "chrome://exch/content/app.xul");

其中,app.xul是你的应用程序的主界面。

试试用xulrunner application.ini来运行吧。

February 01

我所掌握的编程语言

没想过竟然学过这么多东西,可惜不常用的都忘记了。
1、汇编类:
arm,SPCE061,C51,TMS320C54xx,x86
2、C,C++:
MFC,Qt,Win32
3、托管类:
C#,Java
4、脚本类:
Bash,JavaScript,VBA,perl,PHP
6、描述类:
XML,DHTML,XUL
7、数学类:
Mathmatics,Matlab

这么多语言,大部分今天仍在使用,每天还有新的语言冒出来。创新无止境阿,唉!

Mozilla 的架构

阅读了一下Mozilla的开发文档,对Mozilla的架构有了一定了解。
一般人都认为Firefox的核心是Gecko引擎。其实Gecko只不过是一个呈现或渲染引擎,它的重要性远在其他结构之下。因为,现在所存在的呈现引擎已有很多种。
作为Mozilla最底层的部分,是XPCOM。它和MS的COM技术很类似,都给予组件模型,都基于接口和约定,甚至连GUID和引用计数这样的实现细节都很相似。所不同的是,XPCOM是跨平台的,它支持Unix,MaxOS,Win32这三大类平台。这是它具有很大的优势。
XPCOM是用C++写成的,这是项目中符合传统的部分。
在这之上,Mozilla有一项很有新意的技术,它将类似于DHTML界面描述和实现方式应用到了桌面应用程序的开发。这就是XUL。它和XBL,CSS,JavaScript,DOM等,以期形成了一个完全的体系。我发现Mozilla的野心相当大,它所做的不是一个浏览器,而是一个开发平台。在这个平台上,完全可以开发各种甚至是与网络无关的应用程序。这是相当大胆而有新意的。虽然这个平台还没有完全成熟,但它给出了除Java外开发跨平台应用程序的有一个选择。
January 31

编写 Firefox Extension

为Firefox编写插件很有意思,却又很费力气,因为调试手段太缺乏。

由于Firefox在版本升级中,插件的结构发生了一定变化,而Mozila的文档对这些变化显得很不统一,也造成了一些困扰。以下所有内容,只在Firefox 1.5.*上得到验证。

一个打包好的Firefox插件是一个扩展名为xpi的zip文件,它包括以下几个部分:
1、chrome.manifest
这是核心配置文件,是它指导Firefox内核把插件的各个模块配置并组装起来,安放到指定的位置。

2、install.rdf
这一个安装和卸载是使用的描述文件,包含大量的字符串,主要供Extension Manger获取文字性的描述信息。

3、chrome/your-name.jar
这也是一个zip文件,它将会被chrome.manifest引用。

这个your-name.jar将大部分插件的内容打包,其中又包含三个文件夹
1、content
这个文件夹中包含界面描述文件XUL,JavaScript,以及资源文件。
2、locale
这个文件夹中包含为各地区和语言定制的字符串资源,可供界面文件等引用。它们应使用UTF-8编码。
3、skin
这个文件夹包含CSS样式表,可用来修饰界面文件

Firefox对所有这些文件的要求都很严格,一个细小的错误就会造成整个程序的功能错误。因此,编写时必须十分小心。

J2ME 游戏引擎设计(2)

怎样具体的实现一个游戏引擎呢?

首先来设计程序的结构。

一般说来,一个J2ME包含一个MIDlet类,一个或多个Canvas类。MIDlet类不包含太多具体功能,只起一个入口点作用(作为内部事件机制的一个接口)。Canvas类实现绝大多数功能,包括绘制用户界面,实现界面逻辑,实现用户逻辑等等,基本囊括了所有东西。对于一个游戏引擎来说,虽然也可以采用这种方法,但由于游戏引擎的复杂程度大,所以这种实现结构太不清晰。首先还是采用经典的MVC方式,将引擎分为三部分:

Canvas类:他继承自GameCanvas类,处理游戏界面的绘制。

Engine类:他处理工作线程的创建和中止,处理虚拟时间的流逝,读取用户输入,并交由其他类处理。他还要处理各类定时器事件。这是最难设计的部分。

Document类:他包含游戏的模型,包含游戏本身的各种功能。他提供一个接口给Canvas类,交由其获取游戏状态;又提供另一个接口给Engine类,供其调用,以处理各种输入和事件。
January 30

我常用的Firefox插件

没装插件的Firefox没法用,装得太多又太耗内存。而且个个都不可或缺,难以取舍,唉。以下以字母为序
1、Flashgot
2、Adblock
默认竟然没有规则,要手动添加,太不方便了
3、Tab Mix Plus
还有几个类似的,这个整合得较好
4、Google Toolbar
5、Fasterfox
难以定量衡量他的作用
6、IE tab
也应该有些默认规则才好
7、Yonoo
网络收藏夹同步
8、xyzproxy
9、Furl Tools
网摘工具

在线书签工具比较

一直在寻找一个合适的在线书签工具,能让我随时随地的修改和访问我的收藏夹。可是每个工具都多多少少有些不足,令人遗憾!但愿开发者能看到,早日改进。
1、www.spurl.net
这个网站使用相当方便,最特别的是支持Firefox 侧边拦,可以在侧边栏中显示你的收藏夹。这实际上是为侧边栏定做的一个网页。他还支持网页Cache,遗憾的是,Cached中的中文是乱码,且无法修正。

2、del.icio.us
不支持侧边栏,不支持快照。

3、furl.net
支持快照!使用也较方便,我现在正在使用。

4、google的定制主页
使用较麻烦,得手动添加。

综上,一个好的在线收藏夹,得有以下几个基本功能:访问容易(无需打开他的主页就可访问),支持快照,支持多种浏览器,支持导入导出。

什么时候Windows Live 才能完工呢?
January 27

近期电影一览之(一)无极

无法为每部影片多写几笔, 能够在这里留下印迹的,也算是今年电影中难得有幸的了。
<<无极>>
简而言之,我不相信这是陈凯歌的作品。
我很喜欢陈凯歌这个导演,第五代导演中很有个性的一位。低调而独行,拍一些小众化的电影。当年的<<霸王别姬>>已是经典,而《荆轲刺秦王》我也以为在张艺谋得同类作品之上。<<和你在一起>>更是一部外行不知,内行决津津乐道的片子。所以,当我尚未看到这部片子,而各种负面影评铺天盖地时,我很为其不平。因此当我看过这部片子后,我的结论是:这不是陈凯歌的作品,明显为某个香港三流导演之作,因为它的烂已经超出了陈凯歌的底线。国产电影近年来很有起色,大陆导演佳片迭出,在这样一个被背景下,这部电影也明显不像大陆所为。
为避免言之无物,列举如下:
1、剧情混乱,毫无逻辑可言。编剧欲以无极概括,须知无极不是无稽。魔幻题材的电影最忌两个方面:一是想象力缺乏,二是想象力过度。想象力缺乏则无趣,想象力过度则"无极"了。其实想象力过度也是想象力缺乏的表现,因为编剧根本不知如何恰当的发展剧情,只有胡扯。这方便的佳作,有<<绿色奇迹>>、<<大鱼>>可供对照。
2、内容空洞。既然有一,必然有二。由于该片毫无内在逻辑,人物的所言所行也就毫无根据,更谈不上哲理。全局唯一的几句台词亮点,也被淹没在大量空洞的对白中。附带,没有武器的便是王,略有新意。
3、人物对白虚假,配音更是极差。本片的几个片断所应有的宏大和气势,全部让恶心的配音一扫而光。包括混杂中日韩口音的普通话和谢霆峰混合男女的口音。
4、特效堆叠。大部分特效没有起到烘托情节的作用。尤其以笼内追逐和鬼与无欢打斗两场。
写此文章,并非为声讨陈凯歌,因为我对他彻底失望。只是为了曾经的期待和浪费的两小时讨个公道。

中国的3G时代

作为电信的从业者,其实本应对3G失业还有无限的热情。因为无论这项工程是多么祸国殃民,对于电信业本身来说都是好事一桩。可是我也是一个消费者,也是电信这个国有垄断行业的被剥削者,所以站在另一个立场上,不能不有代表社会大众的看法。
中国电信改革的名义上的目标,是打破电信垄断,可实际上旧社会的普遍看法来说,垄断依旧。而拆分的结果,使大量的重复建设和相互间的恶性竞争。从2G的发展来看,国内先后新建了GSM,CDMA,PHP三个全国性的无线接入网,还有许多有小规模的地方网络,而每个网络的容量都没有得到充分的发挥。这样的直接结果,是大规模的重复投资,频带资源的浪费,以及相互之间通信的严重障碍。
3G的三个标准,其实并无所谓优劣之分,或者说都不足以成为取舍的举足轻重的依据。所谓争端,只不过是电信厂商之间的利益之争,这样的争端是很难调和的。如果放任市场去选择,必然形成3个网络各自建设,各自为政的局面。到时中国就有六个全国性的互不兼容的无线网络,这种浪费是惊人的。3G的投入费用比2G高得多,沿用2G时代本以错误的方式,是一种极其愚蠢的做法。
TD-SCDMA这种所谓的国际标准,其实从未在国际或国内真正成为标准。中国在制定这项标准时,竟然承诺若要建设网络,就必定三个都要建。这在我看来是一种极不负责任的做法,为了推行一个标准,必须付出如此高的代价,是得不偿失的。
依我看来,3G技术应该缓行甚至是取消掉。在现阶段,中国最应该大力发展的是以IP电话、IPTV为代表的IP网络和宽带骨干网的建设。这才是一个国家电信业的基础。而现有的无线网络在很长一段时间内都能够满足应用需求,降低费用才是发展的关键。等待4G技术成熟试试最好的选择。

Moto J2ME 的实现的Bug

其实是Moto公司的手机和J2ME模拟器的实现与标准不符。
在J2ME标准中,GameCanvas类的flushGraphic (int x, int y, int w, int h)方法,被定义为:
刷新缓冲区内(x,y,w,h)的矩形区域,到屏幕的对应区域内。缓冲区和屏幕间的像素是一一对应的。
而在Moto公司的实现中,该方法被定义为将缓冲区内(0,0,w,h)内的内容拷贝到屏幕的(x,y,w,h)区域内,与标准存在明显的不同。在标准环境下运行正常的程序在Moto环境下完全无法使用。
以上差异,在SUN的WTK2.2呵Moto的J2ME SDK 5.4及E680i手机上验证确实存在。令人差异的是,Moto的文档竟对此毫无说明!个人认为,Moto的开发技术支持是最差的公司之一。
一种解决方案为,使用translate函数对缓冲区做坐标变换,以实现与标准的相一致。(该方法未验证,仅供参考)

J2ME 游戏引擎设计(1)

不同的J2ME应用程序采用的是事件驱动模型,采用这种模型作为游戏引擎,需要采用定时器来作为事件输入。它的主要难题在于难于实现各事件间的全局同步,难于实现暂定与恢复。一个成熟的游戏引擎,应该实现以下几个功能:
1、能简化游戏的结构设计,尤其是简化游戏的状态管理
2、能实现开始、结束等各菜单界面
3、能实现随时的暂停和恢复
4、当有电话或其它异步事件发生时,能自动暂停游戏,并可恢复
5、可在游戏中调节游戏选项
6、支持各种游戏类型,包括实时的游戏进程,可自适应调整的人工智能,可处理多种用户输入等。