免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 876 | 回复: 0
打印 上一主题 下一主题

嵌入式浏览器开发(二) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-22 08:51 |只看该作者 |倒序浏览
等元素则意味着需要换行。而在HTML中,在无<PRE>这种特殊情况时,回车都是忽略不记的。这就造成了矛盾。使用常规的简单算法进行HTML到TXT的转换无法解决这些问题。造成转换后的版式“失真“。而“HTML智能分析”却能很好的解决。

 

由于“HTML智能分析”使用了底层的词法分析技术,还可以很容易的过滤掉<SCRIPT>与<STYLE>(样式表)。并可以对网页中的元素进行统计和语法校验。

 

以下是该程序的片断:

    pTtokenList=global_cx->tokenList; //取首节点

    while(pTtokenList!=NULL) //循环直至处理完所有节点

    {

     switch(pTtokenList->token->type)

        {//根据节点类型,做不同的处理

          case HTML_TITLE: ……

          case HTML_TEXT:  ……

          default:   ……

        } //switch

    pTtokenList=pTtokenList->next; //取下一个节点

    } //while

这段程序实际上就是一个简单的语法分析和布局的过程。

 

2.5.2  Bit Token在应用中存在的问题及修改意见

由于HTML的标记多是成对出现的,并且存在<SCRIPT>这样的特殊元素,其内容为Javascript程序,函数的字符串参数等可能包含其它的元素标记。例如语句:Alert(“<font> is a tag”);

 

因此,在词法分析时要对<SCRIPT>标记进行特殊处理,遇到<SCRIPT>就应逐字符读入后面的内容,直到遇到下一个</SCRIPT>标记。目前的Bit Token由于开发时间所限,未对其加以特殊处理,存在一些问题,但由于浏览器对Javascript的支持是较复杂的工作,目前的Netbit Browser尚不予实现,因而没有导致明显问题,而“HTML智能分析”这个软件只是需要对Javascript进行删除操作,也不会造成影响。尽管如此,对<SCRIPT>的特殊处理还是有待完善,尽管这同时也会带来一些问题,需要进行大量的测试,来保证新加入代码的稳定性。

 

正如前面所述,HTML词法分析是浏览器设计的基础环节之一,但并非最重要和最具难度的环节,若想开发出效果较好的浏览器产品,还要在布局和GUI设计上多下功夫。

 


第三章 浏览器JavaScript支持的实现

 

本部份主要针对Mozilla和Netscape浏览器源代码的JavaScript部份进行了分析,阐述了浏览器Javascript实现的机制。

3.1基本的JavaScript 开发环境

JavaScript Reference与JavaScript API:

JavaScript Reference是Mozilla所使用JavaScript开发环境,是使用ANSI C的独立的开发包,据Mozilla文档介绍,该开发包涉及到超过160家公司的版权。而且被广泛使用,实际已成为了进行JavaScript应用开发的标准平台。

 

JavaScript Reference可以用于建立包含JavaScript runtime的Library或 DLL。既可以编译成小的 "shell" 程序(像早期的BASIC),又连接Library后生成交互式的JavaScript解释器,也可以用来解释.js 文件。由于使用了ANSI C编程,可以用VC、GCC等编译器在不同平台下编译。

 

生成的"shell" 程序,对比浏览器对JavaScript的支持,相同之处是使用相同的包含JavaScript runtime的Library 或 DLL,我们把这部份相同的Library或 DLL称为JavaScript API我们实际开发JavaScript应用,也是在JavaScript API基础上工作,而不用过多考虑其内部的实现。关于JavaScript API,参见JavaScript API详解。JavaScript API实际就是Javscript解释器的对外接口函数库。

 

3.2        JavaScript Engine

JavaScript Engine是浏览器开发者为了利用JavaScript API来实现实际应用而设立的中间层,用于初始化JavaScript环境,提供对JavaScript解释、执行的接口。浏览器主体程序的设计者可以通过JavaScript Engine,方便的实现各种应用,毕竟JavaScript API太基础了,直接使用不太方便。

 

下面介绍JavaScript Engine的主要功能和实现方法。这也包含了利用JavaScript API进行应用的基本思路。

 

(1) 初始化:

内存分配:rt=JS_Init(10000L);

初始化cx:cx = JS_NewContext(rt, STACK_CHUNK_SIZE);

初始化globalObj:globalObj = JS_NewObject(cx, &globalClass, 0, 0);

定义标准类:JS_InitStandardClasses(cx, globalObj);

定义系统函数:JS_DefineFunctions(cx, globalObj, g_functions);

定义报错函数:JS_SetErrorReporter(cx,JS_ErrorReporter);

注册其它类:

RegisterClassPoint       (cx,globalObj);

RegisterClassSize    (cx,globalObj);

RegisterClassRect    (cx,globalObj);

RegisterClassPolygon (cx,globalObj);

RegisterClassColorKey    (cx,globalObj);

RegisterClassTDTimer (cx,globalObj);

初始化定时器:TDTimerListInit();

 

(2) 提供对JavaScript解释、执行的接口函数:

TD_EvaluateScript(JSContext *cx,JSObject *obj, const char *bytes, uintN length,const char *filename, uintN lineno,jsval *rval)

 

3.3        JavaScript与浏览器接合

基本概念:JavaScript操作HTML元素的常见方式

例:

<html><head>

<script><!--

function ChangeImage(index)

{image0.src="a"+index+".gif";}

--></script>

</head>

<a onmouseover="ChangeImage(0);">军人</a><br>

<a onmouseover="ChangeImage(1);">眼睛</a><br>

<img id="image0" src="a0.gif"></img>

</html>

当鼠标移到文字上时,触发事件mouseover,调用ChangeImage()函数,使得图像源(SRC)发生变化,重新调入新图片。

 

由此产生两个关键问题:

1.   javascript如何获取HTML元素的名称和属性

2.   javascript如何改变HTML元素的属性,并操作WIDGET重画

 

下面分别阐述这两个问题:

首先介绍涉及到的浏览器流程:

1.4.1  确定要实现的基本功能

鉴于对浏览器开发难度的充分考虑,以及现有人员的水平,拟定实现以下功能,以及需要考虑但暂不予实现的功能。

需要实现的包括:

(1) 界面:包括窗口,菜单,输入框,工具条,滚动条等的支持。

(2) 词法分析:必须实现实用的HTML词法分析,支持HTML4.0全部元素。

(3) 实现简单网页的布局:实现对简单网页的查看。

(4) 支持基本IO,支持采用线程的网络传输。

需要考虑的功能:

(1) JavaScript支持

(2) 汉字支持

(3) 图片格式支持

(4) 表单支持

(5) 页面元素的消息响应

1.4.2  人员分工

由于情况的变动,造成了人员比较紧张,在前期准备工作中,人力充沛,使得收集的资料比较完备,打下了较好的基础。在后期简化了目标,虽然人员减少,但也能够实现主要的工作。考虑到网络是比较独立的部份,把它分出去由专人负责。


 

第二章 HTML词法分析器的设计及其应用

 

HTML词法分析是浏览器设计的基础环节之一,也是整个设计过程中重要的前端工作,其数据结构的拟定与接下来的语法分析和布局算法密切相关,词法分析的效率与准确性、容错性也关系到整个浏览器设计的质量。

 

下面将介绍一个HTML词法分析器——Bit Token的设计思路。

 

Bit Token是Netbit Browser的HTML词法分析器,使用标准C编程,Netbit Browser是基于Linux/Gtk的浏览器,开放源码项目,

 

2.1            Bit Token的组成及其功能

Bit Token作为Netbit Browser的词法分析部份,负责对接收的HTML代码进行词法分析,主要的目的是提取网页中元素的名称及其属性,并以恰当的形式(即按一定的数据结构)加以保存,也就是完成了将数据流离散化、结构化的过程。

 

主要由以下几个部分组成:

1、初始化:完成对数据结构的初始化,主要是分配内存,变量赋初值。

2、主体的数据流分析:逐字符的进行判断,确定数据的归属类型。

3、元素的分析:提取元素的名称、属性和值域。

4、释放:主要是对内存的释放。

2.2            数据结构

typedef struct BitTokenContext

{char * strBuffer;         //当前正在处理的HTML代码

int    bufferLength;

int    curPosition;

char * global_strBuffer;    //全局HTML代码

int    global_bufferLength;

int    global_curPosition;

BitTokenList *tokenList;    //元素节点链表

BitTokenList *tokenList_tail;

BitPTagList pTagList;       //元素名称表,指向静态数据

}BitTokenContext,*BitPTokenContext;

 

BitTokenContext是用于存储当前待分析网页全局属性的数据结构,其中TokenList是核心的元素节点链表。词法分析的目的就是生成这样一个链表。下面给出该链表的数据结构,是很简单的双向链表。

 

typedef struct TokenList

{ BitToken *token;  //元素节点

 struct TokenList *priou;

 struct TokenList *next;

}BitTokenList,*BitPTokenList;

 

以下是元素节点的数据结构:

 

typedef struct BitToken

{int type;  //节点类型,如定义的HTML_BODY,HTML_TXT等。

char *pData; //如果是HTML_TXT型元素,则为其内容,否则为空

BOOL end;    //是否是结束元素,如</body>

BitTokenAttrList *attrList; //元素属性链表,因为可能有多个属性,所以使用链表存储

BitTokenAttrList *attrList_tail;

}BitToken,*BitPToken;

 

请注意,以上出现tail标记的指针变量,如BitTokenList * tokenList_tail等,其作用是用于保存链表结尾节点指针,便于在释放内存时,直接找到链尾,提高了算法的效率。

 

2.3            算法

2.3.1 基本算法:

 

首先介绍基本的算法:

(1) 从存储网页的字符串中,顺序读入一个字符

 

(2) 如果遇到 < ,认为遇到TAG(元素),处理该元素,使用函数Token_ConsumTag(),处理完毕后,指针移到该元素尾。

   

(3) 如果遇到回车、空格,则跳过。

 

(4) 如果遇到 > ,则跳过(不应该出现此情况,为了容错)。

   

(5) 如果非以上情况,则认为遇到文字,处理这段文字,使用函数Token_Consum_PlainText()。处理完毕,指针指向下一个元素首。

 

(6) 循环以上操作,直到该网页分析完毕。

   

由此看来,主算法十分简单而清晰,主要是Token_ConsumTag()和Token_Consum_PlainText()这两个函数起关键作用,由于其中涉及到许多细节问题,此处不予详述。

 

2.3.2 算法效率与改进:

采用以上的基本算法,是可用的,但当网页比较大的时候,比如600K,该算法的效率成倍下降,这主要是由于要处理的字符串太大,在内存中完成查找、替换、复制、移动等操作,响应时间明显下降。对此的改进办法就是分段进行词法分析,不仅极大的提高了效率(在某些情况下约提高30倍),也有利于浏览器整体设计,因为当网页较大时,若等待全部内容传输完毕,再一次性完成词法分析和布局,用户会感到等待时间过长,一般现在成熟的浏览器都采用边传输,边分析,边显示。

 

分段进行词法分析的算法复杂度明显增加,比如,当每段定为1024字节,在第1024字节处,可能正好将一个完整元素截断,按常规分析方法会造成错误。解决的办法是,采用回溯,确认要分析的部份至少包含1个完整元素。

具体做法是:判断1024字节处是否为元素结束字符 ‘>’,如果不是,则判断前一个字节,直到找到元素结束字符为止,这样可保证至少包含一个元素。

 

采用分段进行词法分析,实际每次分析的代码会不足1024字节,余下的部份汇入到下一段的分析过程即可,直到所有内容被分析完毕。

 

2.4词法分析的结果

下面是一段很简单的HTML代码。

<html>

<img src=“go.gif” width=200 height=100>

<a HREF="http://www.263.net">首都在线</a>

</html>

分析后,数据存储结构如下

<img>

<a>

text

</a>

src

go.gif

width

200

height

100

href

http://www.263.net

data

首都在线


可以看到,词法分析的结果是一个元素节点链表,每个节点的属性也形成了一个链表,元素节点是有先后顺序的,元素属性的先后顺序是无所谓的。

 

词法分析将网页的文本数据流以清晰的结构表现出来,这样,在后面的应用中就可以很容易的遍历各节点,并轻松地获得各元素节点的属性。

2.5 HTML词法分析的应用

2.5.1 应用举例:

HTML词法分析程序通常应用于浏览器设计、网页制作软件设计等领域,本人以一个使用VC开发的软件“HTML智能分析”来举例说明,下载网址:

http://netbit_browser.myetang.com/introduce.html

 

“HTML智能分析”同样使用Bit Token词法分析器,“HTML智能分析”是一个网页信息提取、处理软件。

 

具有以下主要功能:

1、智能提取网页中的文字信息,智能排版,并可在进行编辑后保存。

2、统计网页的有关信息。

3、根据用户设置的版式,将分析和编辑的结果,自动生成新的网页。

 

用户可使用该软件来将HTML转为TXT格式,其对HTML中文字内容的提取准确、快速、不含冗余信息,版式工整清晰,保持本来面貌。

 

其主要设计思路是,在Bit Token词法分析器的基础上,结合浏览器布局的基本算法,对影响到TXT版面效果的元素进行处理。

 

比如<PRE>标记,代表所包含的内容浏览器应不予分析,按TXT格式输出,而如表格

PARSE

Tokenize

BuildModel

BuildPres

ProcessElement

WidgetPaint

 

 

 

 

 

 

 

 

 

 

 

 

 

 


问题1解决:HTML元素作为Javascript对象进行注册

注册过程在BuildModel中进行。BuildModel的首要任务是将Token后的结点按包含关系展成一棵树。其次就是要将某些结点注册为JavaScript对象。

 

注册的过程是:

定义新对象:JSObject *proto;

 

初始化该对象

TD_JSXMLElementClassInit(JS_GetGlobalContext(),

 (void **)&proto))

 

使用JS_DefineObject或JS_NewObject定义对象属性

根据是否定义了该元素的名称区别对待:

if(TD_XMLContentIsNamedItem(aElement,&aName))

{   parent = js_GetGlobalObject();

*aReturn=JS_DefineObject(JS_GetGlobalContext(),js_GetGlobalObject(),aName->mStr,&ElementClass,proto,JSPROP_ENUMERATE);

}

else

{   parent=aElement->parent->mScriptObject;

*aReturn = JS_NewObject(JS_GetGlobalContext(), &ElementClass, proto, parent);

}

将对象加入

JS_SetPrivate(JS_GetGlobalContext(), (JSObject *)*aReturn, aElement);这样,在编译时,HTML元素的标识就能被Javascript编译器识别,否则会报错变量未定义。

 

问题2解决:利用注册给对象的函数实现操作符的功能化

具体可理解为:当image0.src=”1.gif”被执行时,相当于为对象设置或改变属性,此时SetElementProperty函数被调用(该函数在注册该对象时由JSXMLElementClassInit捆绑给该对象,其内容由用户自己定义),SetElementProperty通过函数指针调用函数TD_JSXMLSetAtrByID,改变结点树上结点属性,并重新生成该节点对应的widget,重画界面。

 

问题3:如何建立Javascript对象与结点树上结点的对应?

解决: Javascript对象与结点树是同时生成的,它们的共同性质是结点具有相同属性,Javascript对象根据ID属性查找树,找到要操作的对应结点。

 

3.4        浏览器消息响应

在主消息循环中调用TDWidgetProcessMsg,处理与widget有关消息。

首先:取得当前焦点所在的widget

pWidget=TDWidgetGetAtPoint(pThis->baseDoc.base.mWidget,pt,&index);

处理该widget对该消息的响应。

 

最后一般为调用JavaScript执行,实现实际响应。

TDVOID  TDWidgetDoAction(TDPWidgetAction pAnchor)

{

    jsval jval;

    if(pAnchor)

        TD_EvaluateScript(JS_GetGlobalContext(),js_GetGlobalObject(),pAnchor->mAction.mStr,pAnchor->mAction.mLength,TDNULL,0,&jval);

}

其中pAnchor->mAction.mStr即为界面对象(widget)对应的JavaScript源码,解释执行的结果就是调用为该对象注册的函数来重画该widget,从而实现动态效果。

 

返回列表 发新帖
Chinaunix 论坛 操作系统 移动操作系统 嵌入式浏览器开发(二)
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP