什么是代理和存根 

      

       打个比方,你到自动取款机上去取款;你就是客户,取款机就是你的代理;你不会在乎

钱具体放在那里,你只想看到足够或更多的钱从出口出来(这就是com的透明性)。你同银行之间的操作完全是取款机代理实现。  你的取款请求通过取款机,传到另一头,银行的服务器,他也没有必要知道你在哪儿取钱,他所关心的是你的身份,和你取款多少。当他确认你的权限,就进行相应的操作,返回操作结果给取款机,取款机根据服务器返回结果,从保险柜里取出相应数量的钱给你。你取出卡后,操作完成。  取款机不是直接同服务器连接的,他们之间还有一个“存根”,取款机与存根通信,服务器与存根通信。从某种意义上说存根就是服务器的代理。

图1 组件间通信

       如上图两个组件之间不是直接通信,而是通过代理和存根来之间的通信来间接实现的。图中的channelcom库的一部分。

       COM里,只有进程外组件才会用到代理(proxy)和存根(stub)。

       代理在客户的进程内创建,存根在组件com对象的进程中创建。 每个接口的每个函数都有自己的代理和存根。

 

为什么要用代理和存根 

      

       客户为什么要用代理和存根,而不直接同对象连接呢? 给你一个理由,对客户来说,他与所有com对象的连接都是通过指针来调用的, 而对服务来说,调用对象的接口函数也是通过指针来完成的,然而,指针只有在同一进程内才会有效。这样,代理和存根为了完成这个使命也就产生了。

       代理和存根的作用不只这些,他还要打包所有的参数(包括接口指针),产生 RPC(远程进程调用),通向另一个进程,或者对象运行所在的另一台机器。

 

图2  代理的结构

       上图所显示的代理结构支持参数的标准列集。每个接口的代理实现了IRpcProxyBuffer接口,用于内聚各个部分之间的相互通信。当代理准备把已列集的参数传递过进程边界时,他调用IRpcChannelBuffer 接口的方法(该接口由channel实现)。channel调用RPC运行库使数据传输到目的地。

存根的结构

       如上图所示,每个接口的存根被连接到对象的相应接口上。chnnel分发传入的消息到适当的接口的存根。所有的组件通过IRpcChannelBuffer接口与chnnel交流,这个接口提供了与RPC运行库的连接。

 

列集(marshalling

       说到代理和存根,自然少不了列集,什么是列集?

       列集,对函数参数进行打包处理得过程,因为指针等数据,必须通过一定得转换,才能被另一组件所理解,列集完成后,RPC调用就会产生。可以说列集是一种数据格式的转换方法。

列集有3种方式:

1. 类型库列集

       它可以列集与OLEAUTOMATION兼容的任何接口,意思是你的接口的返回值必须是HRESULT,所使用的参数的类型也应该是与C++VARIANT结构兼容。

2. 通过创建Stub / proxy DLL

       这个DLL的源代由MIDL产生。你必须在服务器和客户机上都注册这个DLL(这是标准的marshal 方式)使用吃方法时,最好把stub / proxy代码编译作为一个独立的组件。

3. 自定义marshaling

       自定义marshal要求在你的组件中必须实现IMarshal接口。当COM需要marchal时,他首先通过QueryInterface看你是否支持IMarshal接口,如果你实现了该接口,也就是说,由你控制了你的COM的所有参数和返回值的打包、解包的方法模式。

 

代理和存根dll的建立

       使用工具MIDL,对一个IDL文件,MIDL会分析自动产生相应的代理/存根 DLL的相关文件。

怎么使用代理和存根

       对于你来说代理和存根的使用是透明的,你根本不用去关心如何使用他们,com库会知道怎么做。

Webkit的手机浏览器MaCross Mobile 1.1.4 beta版本发布。

这个版本主要是修正bug为下一个较大版本作准备。修正了表单管理器和自动填表功能的问题,解决了有些网站不能填充的问题。增强的安全加密功能, 将用户的隐私存放在经过加密的数据库文件中,保证数据安全。 增强了文件上传功能,使用户可以随时用手机浏览器在微博发布照片。修正了网络连接的问题,如联通uniwap和3g网络不能连接的问题。

更新列表:
[功能]
+ 增强了自动填表的准确度问题。
+ 增强了密码保存的安全性问题。
+ 增强了网络连接自动选择的准确度。
+ 修改了网络连接策略。
[Bug修正]。
+ 修正了网络不能连接的问题。
+ 修正了焦点错误的问题。
+ 修正了字体显示问题。

下载地址: http://www.zncsoft.com/down.html

《Understanding Hardware Acceleration on Mobile Browsers》这篇文章介绍了移动平台浏览器的2D绘图加速的现状和一些相关的概念,基本上也适用于GUI框架本身。

* Accelerating Primitive Drawing 基本图元绘制加速

在 iOS上的2D绘图引擎CoreGraphics一直是通过GPU进行基本图元绘制,而Android使用的Skia绘图引擎在3.0之前都只是通过 CPU进行基本图元的绘制,据说Android团队这样选择的原因在于:1)Skia引擎的效率很高,通过CPU绘制性能跟GPU绘制基本相当(当时移动平台的GPU性能可能比较一般) 2)Android本身不像iOS是绑定特定硬件,不能直接依赖于专有硬件的实现;不过在Android 3.0后,Skia已经实现通过使用Open ES GL作为backend,把大部分的基本图元绘制都通过GPU来进行,毕竟第1:GPU的硬件已经飞速发展;第2:GPU绘图比CPU更省电;第3:可以同时使用GPU和CPU进行并行绘图(通过RenderScript)

* (Tiled)Backing Store (分块)后台离屏位图

这个可以看作是后面的Layer的一个特例,主要针对较大的视图如网页的绘制,通过使用分块离屏位图和多线程后台绘制的技巧,在用户对网页进行滚动或者缩放时,一边使用当前的离屏位图块即时响应用户的操作,一边在后台绘制需要的新的离屏位图块,如果用户操作速度太快,后台更新跟不上,就有可能看到还未更新的空白区域,像iOS上Safari,如果快速滚动一个很大的网页,就会看到后面都是空白的区域。

Tiled Backing Store在CoreGraphics已经有相应的API提供支持,Safari上也应用了这项技术。Android上貌似没有这样的API,Chrome Lite也未应用上。

* Layer and Compositing
将上面的Backing Store的概念扩展应用于一颗渲染树(网页)或者UI组件树(窗口系统)的每一个节点,Layer可以看作是这些节点的离屏缓冲,通过使用Layer,可以在大部分情况下减少对这个节点或者这个节点以下的整个分支的实际绘制(只需要使用现成的Layer进行Compositing),特别对这个节点(及其所在的分支)进行启动一个几何变换动画时(位移,拉伸,旋转…)。因为Layer会耗费内存,所以每个节点都开启是不可能的,实际上也是需要时才开启特定节点的Layer(启动动画),不需要时则将其关闭(动画结束)。

iOS的GUI框架已经完全支持Layer,它的动画模块CoreAnimation也充分利用Layer来获得较高的动画帧数,而在Android上也是直到3.0才提供相应的支持。

从上面的说明可以获得一些结论:

1. Android平台的2D绘图技术还是落后于iOS平台,3.0以前的纯CPU的实现也带来性能问题和耗电问题
2. Android3.0在2D绘图上有巨大的飞跃,正在逐步接近甚至部分赶超iOS平台

原文:

 

Understanding Hardware Acceleration on Mobile Browsers

There has been a lot of mentions of the use of GPU (graphics processing unit) hardware acceleration in smartphone and tablet web browsers. So far, the content has been pretty general and hasn’t provided much technical direction apart from simple advice such as “use CSS translate3d”. This blog article tries to shed some more light on browser interactions with the GPU and explain what happens behind the scenes.

Accelerating Primitive Drawing

A web rendering engine, such as WebKit, takes a web page that is described structurally using HTML and a DOM and visually using CSS and transforms it into a series of painting commands and then passes these commands to the graphics stack. In WebKit specifically, WebKit talks to an abstract interface called GraphicsContext. There are different implementations of GraphicsContext depending on the underlying platform. For example, on iOS the GraphicsContext is bound to CoreGraphics. On Android, GraphicContext uses the Skia graphics engine.

A major responsibility of the graphics stack is rasterization: converting vector painting commands into color pixels on a screen. Rasterization also applies to text display. A single letter can consist of a chain of hundreds of curves. Rasterization produces a matrix of pixels of varying colors that gives users the impression of smoothly drawn text. The following picture shows the enlarged portion of a letter displayed on the screen:

Graphic showing letter 'A' and the zoomed in pixels thereof

The most common mobile graphics API is OpenGL for Embedded System, shortened as OpenGL ES, which operates quite similarly to its desktop OpenGL counterpart. A modern GPU has the power to carry out a lot of primitive drawing, from textured triangles to anti-aliased polygons, with massively paralleled implementation of various graphics algorithm. This is, of course, evidenced by a lot of graphics-intensive games which run smoothly – often achieving the ultimate goal of 60 fps on even highly complex scenes.

If you’re building a browser, it makes sense to reduce the burden of the CPU and to delegate most of the primitive drawing (such as images, curves, gradients, and so on) to the GPU. This is one way that the GPU accelerates performance and it is very often taken care of automatically by the graphics stack. On iOS, CoreGraphics leverages many different GPU features for difficult drawing operations, leveraging its Mac OS X experience. On Android (since Honeycomb), Skia also has a full-featured OpenGL ES back-end which fits nicely with NVIDIA Tegra2 GPUs.

Backing Store

It is important to note here that GPUs were originally designed to tackle heavy-duty operations needed in engineering applications (CAD/CAM) and graphics-intensive games. But optimizing the primitive drawing typically found in a web page is very different than making game graphics fast. For a start, most web pages consist of a lot of text and an occasional image. Most web page user-interface elements have solid colors, with some gradients and rounded corners here and there. In contrast, top-selling games like Angry Birds, Need for Speed, and Quake hardly contain any text and almost everything in the game world is an object with a texture. In addition, 3-D models with photo-realistic appearances are pretty common in such games.

Since the GPU is optimized for complex use-cases, it does not always come as a surprise that simply asking a GPU to draw images, curves, text glyphs, and other content, does not magically translate into a fluid 60 frames/second for web page rendering. In addition, unlike games, web content can’t be predicted by the browser. A web page can be as simple as a Bing search page or as complicated as the New York Times front page. To achieve a really smooth browsing experience, user interactions with the browser should not be limited by the complexity of the page. In other words, even if the browser is busy loading images and rendering the page, the user should still be able to scroll around and zoom in/out as she wants.

Modern mobile browsers adopt an off-screen buffer approach to decouple the complexity of displaying a web page from the user interaction. Usually the web rendering engine, (WebKit for example), draws into the buffer instead of straight to the display. This buffer, often called the backing store, will be shown on screen based on user activity. When the web page is quite complicated and the user scrolls and zooms quickly, the backing store is often not filled fast enough. This is the reason why on an iPhone or iPad, the checkerboard pattern is visible; it serves as a placeholder for the region of the buffer that is not fully rendered yet. This way, the web page can be scrolled around or zoomed in/out as fast as the user wants. The rendering process (which fills the backing store) may lag user interactions but since it is in a separate thread, it does not block any user interactions occurring in the main UI thread.

Another side effect of using a backing store is progressive rendering when the user zooms in and out. A backing store is nothing but a rectangle with a texture. For efficiency, the backing store is usually tiled, i.e. it comprises several small textured rectangles instead of a giant one. During pinching, all the browser does is scale the backing store up and down, thus giving an enlarged but blurry version of the web page. Since pinching typically happens in a few hundred milliseconds, there is no use of faithful high-resolution rendering. Once the user is done with pinching, or when there is an idle moment, the backing store is updated with the correct resolution web page rendering.

Graphic showing blurry SVG vs sharp SVG, side by side

One of the disadvantages of using a backing store per page (regardless whether it is tiled or not) is that is causes difficulty in implementing support for overflow:scroll and position:fixed. The main reason is that the panning and zooming actions from the user modify only the transformation matrix of the backing store, but do not update the backing store. For these two CSS features to work, the handling of the backing store has to be improved to account for content movement within the display.

Layer and Compositing

For web applications which have more dynamic content, including for example CSS animations, having a static off-screen buffer does not really help. However, the same backing store concept can be extended further. Instead of one giant backing store for the entire page, we can have multiple smaller backing stores, each associated with an animated element.

Take for example the famous falling leaves demo from WebKit. This demo really shows how creating backing stores at a more granular level can improve the frame rate. Rather than drawing the leaves (with different rotation and position) for each animation step, WebKit creates a small layer for each leaf, sends those layers to the GPU once, and performs the animation by varying the transformation matrix and opacity of every layer (and thus also the corresponding leaf thereof). Effectively, this creates a really smooth animation because (1) the CPU does not need to do anything beside the initial animation setup and (2) the GPU is only responsible for compositing different layers during the entire animation process. As evidenced from 60 fps performance of many graphics-intensive mobile games, compositing such a rather simple collection of layers is a piece of cake for modern GPU nowadays.

Graphic outlining the layers in the falling leaves demo

The best practice of setting the CSS transformation matrix to translate3d or scale3d (even though there is no 3-D involved) comes from the fact that those types of matrix will switch the animated element to have its own layer which will then be composited together with the rest of the web page and other layers. But you should note that creating and compositing layers come with a price, namely memory allocation. It is not wise to blindly composite every little element in the web page for the sake of hardware acceleration, you’ll eat memory.

Conclusion

In short, making a web browser take advantage of GPU hardware acceleration is far from trivial. It involves making lots of changes at multiple levels, from primitive drawing acceleration, to textured backing store, and layer compositing. But the best possible performance can be achieved when all of these work in harmony.

又一轮开发与测试结束了,Webkit的手机浏览器MaCross Mobile 1.1.2 beta版本发布。

这个版本主要是增加新的功能,方便用户使用。增加了表单管理器和自动填表功能,使用户不必每次登陆时都要重复输入用户名和密码。新的安全加密功能,将用户的隐私存放在经过加密的数据库文件中,保证数据安全。增加了缓存管理和Cookie管理的功能,使用户可以手动清除浏览器缓存,减少闪存空间占用。增加了文件上传功能,使用户可以随时用手机浏览器在微博发布照片。调整了网络任务调度策略,缩短响应时间。调整了事件循环系统,使界面更为流畅。

更新列表:
[界面]
+  修改事件分发循环,提高界面响应速度。
+  增加缓存,Cookie,表单清除功能。
+  增加文件打开对话框功能。
+  增加表单保存功能。
[功能]
+ 增加密码管理功能。
+ 增加自动填表功能。
+ 增加文件上传功能。
+ 增加缓存管理功能。
[Bug修正]
+ 修正地址栏字体显示越界问题。
+ 修正页面管理器不显示标题的问题。
+ 修正文本框显示越界问题。
+ 修正网络连接慢的问题。

下载地址: http://www.zncsoft.com/down.html

本文翻译自 Google 的开源 Javascript 引擎 V8 的在线文档。 其实我都没有真正翻译过什么东西,本来我的英文就比较一般,中文语言组织也很弱。而且许多文档(比如这篇)基本上如果是对此感兴趣的人,直接阅读英文原文 文档肯定都是没有问题的。不过既然突然心血来潮,就试一试吧,能力总是要锻炼才会有的。我自己对 Language VM 比较感兴趣,V8 其实并不是一个 VM ,因为它是直接编译为本地机器码执行的,但是也有不少相通的地方。废话少说,下面是译文。

Netscape Navigator 在 90 在年代中期对 JavaScript 进行了集成,这让网页开发人员对 HTML 页面中诸如 form 、frame 和 image 之类的元素的访问变得非常容易。由此 JavaScript 很快成为了用于定制控件和添加动画的工具,到 90 年代后期的时候,大部分的 JavaScript 脚本仅仅完成像“根据用户的鼠标动作把一幅图换成另一幅图”这样简单的功能。

随 着最近 AJAX 技术的兴起,JavaScript 现在已经变成了实现基于 web 的应用程序(例如我们自己的 Gmail)的核心技术。JavaScript 程序从聊聊几行变成数百 KB 的代码。JavaScript 被设计于完成一些特定的任务,虽然 JavaScript 在做这些事情的时候通常都很高效,但是性能已经逐渐成为进一步用 JavaScript 开发复杂的基于 web 的应用程序的瓶颈。

V8 是一个全新的 JavaScript 引擎,它在设计之初就以高效地执行大型的 JavaScript 应用程序为目的。在一些性能测试中,V8 比 Internet Explorer 的 JScript 、Firefox 中的 SpiderMonkey 以及 Safari 中的 JavaScriptCore 要快上数倍。如果你的 web 程序的瓶颈在于 JavaScript 的运行效率,用 V8 代替你现在的 JavaScript 引擎很可能可以提升你的程序的运行效率。具体会有多大的性能提升依赖于程序执行了多少 JavaScript 代码以及这些代码本身的性质。比如,如果你的程序中的函数会被反复执行很多遍的话,性能提升通常会比较大,反过来,如果代码中有很多不同的函数并且都只会 被调用一次左右,那么性能提升就不会那么明显了。其中的原因在你读过这份文档余下的部分之后就会明白了。

V8 的性能提升主要来自三个关键部分:

快速属性访问

JavaScript 是一门动态语言,属性可以在运行时添加到或从对象中删除。这意味着对象的属性经常会发生变化。大部分 JavaScript 引擎都使用一个类似于字典的数据结构来存储对象的属性,这样每次访问对象的属性都需要进行一次动态的字典查找来获取属性在内存中的位置。这种实现方式让 JavaScript 中属性的访问比诸如 Java 和 Smalltalk 这样的语言中的成员变量的访问慢了许多。成员变量在内存中的位置离对象的地址的距离是固定的,这个偏移量由编译器在编译的时候根据对象的类的定义决定下 来。因此对成员变量的访问只是一个简单的内存读取或写入的操作,通常只需要一条指令即可。

为了减少 JavaScript 中访问属性所花的时间,V8 采用了和动态查找完全不同的技术来实现属性的访问:动态地为对象创建隐藏类。这并不是什么新的想法,基于原型的编程语言 Self 就用 map 来实现了类似的功能(参见 An Efficient Implementation of Self, a Dynamically-Typed Object-Oriented Language Based on Prototypes )。在 V8 里,当一个新的属性被添加到对象中时,对象所对应的隐藏类会随之改变。

下面我们用一个简单的 JavaScript 函数来加以说明:

function Point(x, y) {
    this.x = x;
    this.y = y;
}

当 new Point(x, y) 执行的时候,一个新的 Point 对象会被创建出来。如果这是 Point 对象第一次被创建,V8 会为它初始化一个隐藏类,不妨称作 C0。因为这个对象还没有定义任何属性,所以这个初始类是一个空类。到这个时候为止,对象 Point 的隐藏类是 C0

map_trans_a

执行函数 Point 中的第一条语句(this.x = x;)会为对象 Point 创建一个新的属性 x。此时,V8 会:

  • 在 C0 的基础上创建另一个隐藏类 C1,并将属性 x 的信息添加到 C1 中:这个属性的值会被存储在距 Point 对象的偏移量为 0 的地方。
  • 在 C0 中添加适当的类转移信息,使得当有另外的以其为隐藏类的对象在添加了属性 x 之后能够找到 C1 作为新的隐藏类。此时对象 Point 的隐藏类被更新为 C1

map_trans_b

执行函数 Point 中的第二条语句(this.y = y;)会添加一个新的属性 y 到对象 Point 中。同理,此时 V8 会:

  • 在 C1 的基础上创建另一个隐藏类 C2,并在 C2 中添加关于属性 y 的信息:这个属性将被存储在内存中离 Point 对象的偏移量为 1 的地方。
  • 在 C1 中添加适当的类转移信息,使得当有另外的以其为隐藏类的对象在添加了属性 y 之后能够找到 C2 作为新的隐藏类。此时对象 Point 的隐藏类被更新为 C2

map_trans_c

咋一看似乎每次添加一个属性都创建一个新的隐藏类非常低效。实际上,利用类转移信息,隐藏类可以被重用。下次创建一个 Point 对象的时候,就可以直接共享由最初那个 Point 对象所创建出来的隐藏类。例如,如果又一个 Point 对象被创建出来了:

  • 一开始 Point 对象没有任何属性,它的隐藏类将会被设置为 C0
  • 当属性 x 被添加到对象中的时候,V8 通过 C0 到 C1 的类转移信息将对象的隐藏类更新为 C1 ,并直接将 x 的属性值写入到由 C1 所指定的位置(偏移量 0)。
  • 当属性 y 被添加到对象中的时候,V8 又通过 C1 到 C2 的类转移信息将对象的隐藏类更新为 C2,并直接将 y 的属性值写入到由 C2 所指定的位置(偏移量 1)。

尽 管 JavaScript 比通常的面向对象的编程语言都要更加动态一些,然而大部分的 JavaScript 程序都会表现出像上述描述的那样的运行时高度结构重用的行为特征来。使用隐藏类主要有两个好处:属性访问不再需要动态字典查找了;为 V8 使用经典的基于类的优化和内联缓存技术创造了条件。关于内联缓存的更多信息可以参考 Efficient Implementation of the Smalltalk-80 System 这篇论文。

动态机器码生成

V8 在第一次执行 JavaScript 代码的时候会将其直接编译为本地机器码,而不是使用中间字节码的形式,因此也没有解释器的存在。属性访问由内联缓存代码来完成,这些代码通常会在运行时由 V8 修改为合适的机器指令。

在 第一次执行到访问某个对象的属性的代码时,V8 会找出对象当前的隐藏类。同时,V8 会假设在相同代码段里的其他所有对象的属性访问都由这个隐藏类进行描述,并修改相应的内联代码让他们直接使用这个隐藏类。当 V8 预测正确的时候,属性值的存取仅需一条指令即可完成。如果预测失败了,V8 会再次修改内联代码并移除刚才加入的内联优化。

例如,访问一个 Point 对象的 x 属性的代码如下:

point.x

在 V8 中,对应生成的机器码如下:

; ebx = the point object
cmp [ebx, <hidden class offset>], <cached hidden class>
jne <inline cache miss>
mov eax, [ebx, <cached x offset>]

如果对象的隐藏类和缓存的隐藏类不一样,执行会跳转到 V8 运行系统中处理内联缓存预测失败的地方,在那里原来的内联代码会被修改以移除相应的内联缓存优化。如果预测成功了,属性 x 的值会被直接读出来。

当有许多对象共享同一个隐藏类的时候,这样的实现方式下属性的访问速度可以接近大多数动态语言。使用内联缓存代码和隐藏类实现属性访问的方式和动态代码生成和优化的方式结合起来,让大部分 JavaScript 代码的运行效率得以大幅提升。

高效的垃圾收集

V8 会自动回收不再被对象使用的内存,这个过程通常被称为“垃圾收集(Garbage Collection)”。为了保证快速的对象分配和缩短由垃圾收集造成的停顿,并杜绝内存碎片,V8 使用了一个 stop-the-world, generational, accurate 的垃圾收集器,换句话说,V8 的垃圾收集器:

  • 在执行垃圾回收的时候会中断程序的执行。
  • 大部分情况下,每个垃圾收集周期只处理整个对象堆的一部分,这让程序中断造成的影响得以减轻。
  • 总是知道内存中所有的对象和指针所在的位置,这避免了非 accurate 的垃圾收集器中普遍存在的由于错误地把对象当作指针而造成的内存溢出的情况。

在 V8 中,对象堆被分成两部分:用于为新创建的对象分配空间的部分和用于存放在垃圾收集周期中生存下来的那些老的对象的部分。如果一个对象在垃圾收集的过程中被移动了,V8 会更新所有指向这个对象的指针到新的地址。

经过三个月的开发与测试基于Webkit的手机浏览器MaCross Mobile 1.1.0 beta版本终于发布了。

这个版本进行了重大的功能改进和性能改善。实现了http代理功能,完全解决了中国移动cmwap连接方式不能连接网络的问题。完整实现了http 1.1标准的文件缓存系统和cookie缓存系统,有效降低网络流量。实现了多线程网络请求功能,大幅提升了网络性能。改进的平滑滚动和方向键导航,更易于操作。增加焦点切换功能,和网络连接自动识别功能,方便用户使用。

更新列表:
[界面]
+  增加了方向键导航功能。
+  修改了输入法激活控制条。
+  提升了平滑滚动速度。
[功能]
+  增加了网络连接自动识别功能。
+  增加了代理自动检测和连接功能。
+  增加了http 磁盘文件系统缓存功能。
+ 增加cookie自动管理功能。
[Bug修正]
+  修正了中国移动cmwap连接方式不能访问的问题。
+  修正了系统状态栏隐藏问题。
+  修正了密码输入框不能显示“*”的问题。
+  修正了网络重复请求的问题。

下载地址: http://www.zncsoft.com/down.html

    画布(Canvas) 对象是Picasso图形系统中最基本也是最重要的对象。画布(Canvas)对象是对图形输出缓冲区的抽象封装。Picasso可以将任意内存连续区域作为图形输出的地址对待,可以是Windows系统中 Bitmap结构里的 bmBits 域,可以是Linux系统上的FrameBuffer设备的显存地址,也可以是Gtk图型界面库中的pixmap对象。Picasso将它们当成统一的光栅设备对待,以同样的方式输出光栅化后的数据。

Figure1.1

    

画布(Canvas)对象主要包含四个重要的属性,他们是画布的宽度(Width),高度(Height),扫描线宽度(Pitch)以及画布包含的像素格式(Pixel Format)。画布(Canvas)对象一旦创建,所有的属性就不能再改变。宽度(Width)和高度(Height)是指画布(Canvas)对象在水平方向和垂直方向上包含的像素个数。如果宽度值为240,说明画布的每一条水平扫描线包含240个像素,其所占内存大小与像素格式有关。扫描线宽度(Pitch)值是指每条扫描线所占的实际内存大小,单位是字节。它们的关系如下:

扫面线宽度(Pitch)  >=   画布宽度(Width)   *  每像素所占字节数(BytesPrePixel)

之所以会出现大于的情况,主要是因为某些系统要求内存访问对齐的缘故。像素格式(Pixel Format)是指在画布中存储的像素数据的所占用的字节数和排列顺序。如果像素格式为32位 ABGR 形式,则每个像素包含4个字节,包括一个字节的alpha分量,一个字节的蓝色分量,一个字节绿色分量和一个字节的红色分量。如果像素格式为16位RGB565形式,则每个像素只包含2个字节,其中5位为红色分量,6位为绿色分量,5为位蓝色分量。16位像素格式中不包含alpha分量,通常使用全局alpha通道来处理诸如透明或半透明等alpha运算。像素格式的形式如下图所示:

Figure 1.2

16位像素格式通常称为增强色。它的特点是占用更少的内存空间,每个像素只占用2个字节,但所支持的颜色数量有限,常被用在嵌入式系统中。32位像素格式称为真彩色,每个像素包含一个alpha分量,能对图像实行逼真的还原效果,是目前家用电脑最常使用的图像格式。Picasso目前支持常用的6种像素格式,4种32位格式,2种24位格式,2种16位格式,可以满足大多数常用系统的需求。

    

画布(Canvas)对象中另外一个重要的概念是像素坐标系(Coordinate System)。每一个像素的坐标是指像素与坐标系原点的水平和垂直距离,单位是像素数。例如坐标(10,20)是指像素距离坐标系原点的水平距离是10个像素,垂直距离是20个像素。不同的图形系统中所使用的坐标系是不同的,例如苹果(Apple)电脑上的QuackDraw绘图系统使用的坐标系以左下角为坐标原点(0,0),而最常用的Windows系统上的DC坐标系统,使用左上角作为坐标原点(0,0)。Picasso遵循了人们常用的习惯,画布的坐标系统同样使用左上角为坐标原点(0,0)。

Figure 1.3

    

画布(Canvas)对象除了可以作为绘图目标以外,还可以作为图元的纹理来使用。想象一下这样的应用场景:首先创建一个小的画布(Canvas)对象,在上面绘制一个图元。然后把这个小的画布作为填充源绘制到一个大的画布(Canvas)对象上作为填充的图案来使用。

Figure 1.4

    

出于性能和灵活性方面的原因,画布(Canvas)对象不是线程安全的。这意味着同一个画布(Canvas)对象不能同时被两个或多个线程同时使用,但一个线程中可以创建多个画布对象。如果需要在多个线程中同时访问同一个画布(Canvas)对象,用户需要自己实现同步锁定机制。

Read the rest of this entry

     Picasso 是一款跨平台的高级二维矢量绘图引擎。Picasso提供平台无关的图形渲染技术,使它可以运行在几乎所有操作系统平台。目前支持的平台包括Windows 、 WindowsCE、 Linux。Picasso提供低层次,轻量级的二维矢量图形渲染技术,可以为不同是设备提供一致的图形输出质量。Picasso的API非常简单并且易于使用,可以支持很多高级二维图形操作,包括 Path, Transform, Gradient, Pattern, Image 和 Truetype 字体等功能,支持多种颜色模式和混合方式, 可以用在需要矢量图形操作的软件里。

    矢量图形渲染是目前发展最快的图形软件渲染技术。目前最为先进的矢量图形软件开发包是美国微软公司(Microsoft)在Windows 7操作系统中提供的Direct2D图形库。Direct2D 使用Direct3D 提供的硬件加速能力,可以获得非常高的性能,配合DirectWrite文字渲染技术,构造出了Windows7上无比华丽的用户体验。类似的技术还有美国苹果公司(Apple)为其MacOSX 操作系统开发的Quartz2D图形库,基于OpenGL硬件加速技术,也能实现非常华丽的用户界面。此外还有WindowsXP操作系统上提供的GDI+开发包,Linux系统上普遍使用的Cairo软件包等等,都是典型的矢量图形引擎。在互联网领域,矢量图形也是未来发展的方向。使用最为广泛的Flash (Adobe)是最常见的矢量图形动画技术,此外 还有 Sliverlight (Microsoft),SVG (w3c)等互联网图形动画技术。最新的HTML5 标准已经直接将矢量图形绘制作为基本功能提供给网页开发者,<canvas>标签可以包含一段图形绘制代码,直接内嵌在网页里。

    Picasso在设计上参考了Cairo 软件和Quartz2D图形库,吸收了两者的优点。 同样基于PDF模型的绘制方式,提供了简单易用的API。Picasso将任何输出目标当作画布(canvas 对象)来对待,画布的类型并不重要,可以是Windows上的Bitmap对象, 可以是 Linux/Qt上的Image对象, 可以是显存的FrameBuffer地址或是OpenGL表面等等。Picasso将它们当作光栅设备(Raster)来对待,将光栅化后的图形按照设定的像素格式输出到画布对应的地址。如下图所示:

Figure 1.1

要绘制的图元描述和绘图属性保存在一个状态机里,这里称为上下文 (context对象),然后可以对图元进行变换 (transform),裁剪 (clipping)等操作,最后一步光栅化成为像素矩阵输出到画布(canvas对象)上。  Picasso 中只包含了两种最基本的绘图操作,描线 (Stroke)  和 填充 (Fill),所有的图形操作最后都由这两种方法来结束。Picasso还提供了一个绘制函数(Paint) 其实只是先填充再描线 (Fill + Stroke),提供这个方法是为了不必两次创建同一个图元,提高效率。 如下图所示:

Figure 1.2

下面来看一个简单的例子:


#define WIDTH 320
#define HEIGHT 240
#define COLOR_BITS 32
......
// Create Canvas object on draw_addr
ps_canvas* canvas = ps_canvas_create_with_data(draw_addr, COLOR_FORMAT_BGRA, WIDTH, HEIGHT, WIDTH*4);
ps_context* context = ps_context_create(canvas);
......
// Create Shap
ps_rect rc1 = {20, 20, 40, 40};
ps_rect rc2 = {80, 20, 40, 40};
ps_color c1 = {0, 0, 1, 1};
ps_color c2 = {1, 0, 0, 1};
// Stroke a blue rectangle
ps_rectangle(context, &rc1);
ps_set_stroke_color(context, &c1);
ps_stroke(context);
// Fill a red ellipse
ps_ellipse(context, &rc2);
ps_set_source_color(context, &c2);
ps_fill(context);
......
ps_context_unref(context);
ps_canvas_unref(canvas);

    这个程序片段演示了Picasso的基本绘图方式,首先创建了一个画布对象 canvas 在输出地址 draw_addr处,画布的大小是 320×240,颜色位数是32位。然后创建一个绘图上下文对象 context 绑定到画布上。 利用绘图API在画布的位置坐标 (20, 20)处 绘制了一个(40×40)的矩形图元, 设置画笔颜色为蓝色,调用stroke方法输出一个矩形框。  在画布坐标 (80,20)处绘制一个圆形,设置填充颜色为红色, 调用 fill 填充图元。 最后得到的绘制效果如下图所示:

Figure 1.3

    Picasso 图形库中包含了近 200个功能函数,几乎涉及到二维图形绘制的各个方面。作为一款通用图形绘制工具,Picasso 不依赖于系统特性,可以与任何软件无缝集成在一起,在以后的文章中,我会详细介绍Picasso的各个方面的内容。

需要获得Picasso SDK的最新版二进制开发包,请访问

http://www.zncsoft.com/down.html

关于作者

基于Webkit的手机浏览器MaCross Mobile 1.0.10 alpha版本发布。这个版本引入了一项新的字体渲染技术,可以对大字体提供反锯齿功能,使字体显示更加平滑。更新了图形引擎,采用最新的picasso 1.0 public版本,带来3到5倍的性能提升,重构的pixel shader带来更高性能的图像解码速度。 全新的异步事件处理架构,使界面响应更为流畅。
更新列表:
[界面]
+ 增加了postEvent异步事件处理功能。
+ 重构了ScrollView 处理滚动处理模型。
+ 修改了页面滚动和惯性处理方式。
[功能]
+ 增加了大字体反锯齿和平滑功能。
+ 增加了异步事件处理模型。
+ 增加了pixel shader 处理像素解码。
[Bug修正]
+ 修正了界面反应同步问题。
+ 修正了放大缩小导致页面尺寸问题。
+ 修正了图片显示慢的问题。

下载地址: http://www.zncsoft.com/down.html

易观分析显示,近一年中国手机浏览器市场获得了快速的发展,在用户体验及赢利模式方面都有了良好的探索。但手机浏览器在未来的发展过程中仍将面临三大问题。

  首先,“通道”还是“平台”的选择。手机浏览器作为现在移动互联网最为主要的应用入口,在积累了足够用户及流量的基础上,借由手机端操作不便以及现阶段用户需求较为集中的特点,可以选择在手机浏览器应用前端整合后端网络内容及应用,进而塑造平台化的网络入口。这种发展模式适用于移动互联网发展前端的用户需求,也可以给手机浏览器厂商带来直观的赢利模式及现金收入。但是基于浏览器应用本身的特性来说,工具型的应用更应长期专注于用户使用体验及网络使用通道便利性等根本性因素上来。对于用户接入内容的推荐及引导不会是手机浏览器发展及赢利的方向。

  其次,手机浏览器市场未来竞争焦点的确定。手机浏览器市场现阶段的竞争焦点在于两方面,一方面是用户体验的完善,另一方面是内容及应用资源的聚合。随着未来市场的逐渐发展,手机浏览器厂商之间的竞争更应基于手机浏览器的本质层面,也就是围绕着用户接入网络便利性以及使用应用体验两方面上来。但是现阶段手机浏览器厂商对于内容及应用渠道的建立以及未来平台化发展的定位,也将是未来手机浏览器厂商重新树立应用定位及确定自身发展方向的主要阻力来源。

  还有,手机浏览器未来赢利模式的确定。手机浏览器作为使用网络的工具型应用,其截留并引导用户流量的商业模式将会逐渐退出市场,手机浏览器未来的发展一定在于更好的优化用户使用体验并最大化满足用户自由调用网络内容的需求,对于用户使用网络的干扰将会阻碍手机浏览器应用的发展。基于这种市场发展趋势,现有的手机浏览器厂商如何提前定位未来发展方向及提前规划未来的赢利模式将成为决定手机浏览器厂商竞争成功与否的主要因素之一。

  对此,易观分析师建议,手机浏览器厂商现阶段仍以聚集内容及应用并优化用户体验为主要方式,快速的积累用户。在现阶段就以用户需求为主要导向,致力于建设鼓励并满足用户自发、自由调用网络内容的应用体系及使用体验。并在适当的时候主动撤出引导用户流量的设置,把网络使用权真正的交还用户。

普人特福的博客cnzz&51la for wordpress,cnzz for wordpress,51la for wordpress