Chromium中添加pak资源

来源:互联网 发布:知微公司 编辑:程序博客网 时间:2024/05/29 18:59

一 综述

  Chromium是支持各国语言的,那么这就涉及到国际化问题,chrome_string 是关于国际化的项目(Project),chrome_string 会在 chrome 编译之前编译,它将国际化定义的文件转换成资源文件(.pak)和 C++ 头文件,C++ 头文件将作为源代码在编译 chrome 时一起被编译。通过分析chromium的国际化流程,我们可以把自己的资源(图片,jscsshtml等)文件压缩成.pak资源文件。Chromium的国际化语言包编译过程流程大概如图1所示。


图1 语言包编译过程(图来自http://onthink.com/post/chromium-grit.html)

  因此,添加自己的.pak文件,首先需要源文件,grdgrit等。下面会一一介绍。

 grd 文件格式

  先来看看grd文件的格式是啥样的,那chromiumcontent_resources.grd为例,如图2所示,图中可见,一个grd文件可以包含htmlcssjs以及png等各种各样的文件。

  

图2 content_resources.grd

grd xml的格式,它有三个部分: outputstranslationsrelease

 #1 outputs 中定义编译出的C++头文件的位置和.pak资源文件的位置,默认是在 src/build/Debug 或 Release/obj/global_intermediate/chrome/,当然具体文件位置可以自己设定;

 #2 translations中定义了多语言的定义文件的位置,每一种支持的语言都应该有一个翻译文件,这些文件将作为输入,例如要定义中文资源如下所示:

<translations>

    <file path="resources/google_chrome_strings_zh-CN.xtb" lang="zh-CN" />

    …

</translations>

如果这里并不是语言文件,而是其他文件资源,那么如图2所示那样,translations空着就可以了;

 #3 release includesgrd文件包含的所有文件,name属性定义了文件资源的唯一IDfile属性指定了具体源文件位置,type属性定义了文件具体格式,如图2所示。如果grd文件是为支持多语言,那么还有更多的其他属性, messages 定义的是默认语言的定义,当程序找不到合适的语言显示时,将使用默认语言中的定义。 message 的属性如下: - name:标识一个字符串的变量名 - desc:该变量的介绍 - translateable:是否使用翻译,默认true - use_name_for_id:是否使用name作为翻译的id标识。默认是false,翻译文件(xtb)中的id使用转换后的数字做映射;如果true,则使用 name 的值来和 grd 文件中的记录来映射。

  在src/tools/grit/node/mapping.py中定义了grd文件中的资源节点类型,其中,identifiers是在grd文件中的xml节点名,empty.IdentifiersNode即是其通过grit生成的python对象,如下图3所示:

 

图3 Element to class

三 grit工具

  gritGoogle Resource and Internationalization Tool)是一个python开源工具,主要用来打包生成程序需要的资源,如图片资源、字符串资源等,尤其是字符串资源,用于支持多国际化,位于 src/tools/grit 目录下。chrome_string 编译时会执行 grit.py 可以,然后由grit工具将grdxtb文件编译成pak资源文件。Chromium为需要的资源创建单独的项目工程,工程类型为实用工具,自定义工程的生成事件,在build里调用grit命令,根据grd资源描述文件生成.h.rc.pak等文件资源。如chrome_strings工程生成国际化字符串资源、content_resources工程生成除字符串以外的资源,比如图片、htmlCSSJS等文件资源。

  关于grit,因为官方没有发布什么文档,grit工具如图4所示,通过运行程序调出的关于grit的相关信息。另外,由于grit是在build脚本里会调用它,所以,当只是添加一些文件资源时,可以无需过多关注它。


4 grit工具

  另外,需要注意的事,每个grd文件都需要有一个唯一的标识即id,这个是在resource_ids中定义的,是在src/tools/gritsettings/resource_ids中。之前例子中的content_resources.grd在这里的定义是:

"content/app/resources/content_resources.grd": {

    "structures": [4700],

  },

其中有这样的注释,# Resource ids starting at 31000 are reserved for projects built on Chromium.。所以,我们定义的grd的文件id号应该在31000之后。

四 GYP

  准备好源文件和grd文件后,就需要在相关gyp文件中,在编译之前通过grit工具将其生成.h.pak以及.rc文件,以content_resources.gyp为例如图5所示,在src/content/app/resources/目录下。grit_out_dir定义了.pak等生成文件存放目录,grit_grd_file定义了上面所说的grd文件,includes中的grit_action.gypi和grit_target.gypi是在build时调用的grit工具。

 

图5 content_resources.gyp

五 .pak文件读取

  经过以上几个步骤,就可以把图片,htmlCSS以及JS等文件,通过grit工具生成.h.rc以及.pak等资源文件了。那么在程序中如何进行读取呢?在chromium中有ResourceBundleDataPack类,它们可以用来读取pak等文件,这里要分两步,#1 文件加载;#2 文件读取。

#1 文件加载

ResourceBundle可以是单例模式,有一个g_shared_instance.pak资源文件在读取前首先要将其加载到内存中,也就是加载到g_shared_instance中,然后在需要读取的地方,直接读即可以。资源加载有两种方式:

###1####

      int pak_fd = 0;

      int64 pak_off = 0;

      int64 pak_len = 0;

      // Open pak file, get value of pak_fd, pak_off  and pak_len

      ........

      // Add data  

      ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(

          base::File(pak_fd),

          base::MemoryMappedFile::Region(pak_off, pak_len),

          ui::SCALE_FACTOR_NONE);

###2####

      base::FilePath pak_path;

      PathService::Get(ui::DIR_RESOURCE_PAKS, &pak_path);

      ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(

          pak_path.AppendASCII("example.pak"), ui::SCALE_FACTOR_NONE);

#2 文件读取

当资源已经加载到ui::ResourceBundle::GetSharedInstance()后,读取是非常方便的,只需要调用一下函数即可,

ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(resource_id, sacle_factor)  or GetRawDataResource(resource_id)

需要注意的是返回是base::StringPiece类型结果。

 

参考文献:

http://onthink.com/post/chromium-grit.html

http://onthink.com/post/chromium-grit-2.html

https://ftagada.wordpress.com/2011/01/08/chromium-translations-explained-part-1/

http://www.cnblogs.com/fangkm/p/3405959.html

 

 

 

1 0