从DWG到XAML (II) - DWFx格式解析及其和XPS的关系
导读
第一篇: 从DWG到 XAML (I) - 浅谈DWG历史,现状及方向
第三篇: 从DWG到XAML (III) – .NET中的 XPS Packaging类库及一个DWFx Packaging类库的实现 (源码)
上一篇文章简单介绍了DWG格式的历史, 现状, 以及互操作的选择. 那么, AutoDesk宣称AutoCAD与XPS文件格式兼容, 究竟意味着什么呢? 这一切, 得从XPS文件格式说起.
什么是XPS
XPS 是 XML Paper Specification 的简称. 它诞生于2006年下半年, 跟随Windows Vista发布并且在Vista平台上应用颇多, 是微软开发的一种文档保存与查看的规范。这个规范本身描述了这种格式以及分发、归档、显示以及处理 XPS 文档所遵循的规则。最为显著的特点是,XPS 所用的置标语言(Markup Language)是 WPF 所用的 XAML 的一个子集,因此显示 Windows 应用程序所用的方法可以用于 XPS 文档。
为了推广这种格式,微软公司遵循免收专利费的授权方式发布 XPS,允许用户在特定场合创建自己的读、写以及显示 XPS 文件的实现方法。其规范本身也遵循免收专利费的方式发布,并且允许自由分发. 如果您有兴趣, 现在依旧可以从微软的站点上自由下载XPS的技术规范. 这是一个600多页的技术文档, 详细说明了XPS的方方面面, 包括XPS文件的组织形式, 图像/字体以及版权管理等内容.
现在我们知道, 类似于Open XML (Office 2007的基本组织形式), XPS 文件实际上也是一个包含组成文档的各个文件的ZIP文档. 微软公司给我们提供了XPS的示例文档,我们可以从这里获取. 如果你觉得这个示例文档包太大, 我们也可以尝试最简单的办法.
- 打开Word 2007
- 随便写几个字, 或者插入几张图片
- 另存为XPS
- XPS Viewer会启动并显示生成的XPS文件.
XPS Viewer是从Vista时代就捆绑到操作系统中的. 不过这不重要, 我们关注的不是XPS Viewer而是XPS文档内部结构. 现在, 我这里已经有了一个XPS示例文档, 如果您有兴趣, 可以下载并自行查看.
XPS的组织结构
如果600多页的技术规范让您感到厌倦, 那么你不妨试试继续读以下内容. 这会提供给你一个关于XPS大体框架以及各部分功能的一个概述. 如果您觉得我说的不够详细, 那么那时候您可以在这个基本印象的基础上对应查阅XPS技术规格文档的对应章节.
我们先解剖一下xps文件. 将XPS文件后缀名改为.zip并解压缩, 我们就得到了以XPS文件名为目录名的一个目录. 这个根目录下的文件如图所示.
就想你心中揣测的一样. 是的, 你猜对了, 这个图暗示了这样的信息:
FixedDocSeq.fdseq文件 - 必须是同文件名,同后缀名, 这是XPS技术规范所规定的, 是整个XPS文档的入口. 如果没有这个文件, XPS文档将不可以被识别和操作. 事实上, 这个文件的内容是一写指向具体文档的引用. 多文档XPS文件, 会有多个引用记录;单文档XPS文件只有一个引用记录, 例如:
- <FixedDocumentSequence xmlns="http://schemas.microsoft.com/xps/2005/06">
- <DocumentReference Source="/Documents/1/FixedDoc.fdoc"/>
- </FixedDocumentSequence>
docProps目录 - 这个目录主要用来保存和文档属性有关的内容, 比如文档的缩略图, 文档的创建/修改时间等.
Resources目录 - 这个目录主要保存多媒体信息, 比如文档中插入的图像, 比如文档中使用的字体. 我建议你自己打开看一看, 因为字体比较有趣, 不是我们常见的那种Truetype字体或者点阵字体, 而是后缀名.odttf的被混淆的字体. 这是个相当有趣的话题, 如果有兴趣, 大家可以深入研究一下:)
Documents目录 - 这个目录是最重要的, 它存放了大部分和XPS内容呈现有关的材料, 比如文档信息, 页面信息, 文档结构等.这个目录的下一级是一个以序号命名的目录. 序号目录的下一级, 是FixedDoc.fdoc/Pages目录/Structure目录. FixedDoc.fdoc指向了文档显示的具体页面(Page), Pages目录里面保存了所有的页面, Structure目录保存了说明文档结构的.struct文件. 事实上, Page就是直接作为渲染源, 通过诸如XPS Viewer等查看工具, 直接被呈现在你眼前的文档内容. FixedDoc.fdoc文件的内容大多比较简单, 比如本例中:
- <PageContent Source="Pages/1.fpage"></PageContent>
FixedPage.fpage的内容则相当丰富, 因为它关系到绝大部分的内容呈现:
- <FixedPage xmlns="http://schemas.microsoft.com/xps/2005/06" Width="794"
- Height="1123" xml:lang="zh-CN">
- <Canvas>
- <Canvas.RenderTransform>
- <MatrixTransform Matrix="1.333333333,0,0,1.333333333,0,0"/>
- </Canvas.RenderTransform>
- <Glyphs Name="a0" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="90.125"
- OriginY="83.325" UnicodeString="X" Indices="" xml:lang="en-US">
- </Glyphs>
- <Glyphs Name="a1" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="95.375"
- OriginY="83.325" UnicodeString="ps " Indices=",50;,35.714;" xml:lang="en-US">
- </Glyphs>
- <Glyphs Name="a2" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="107.37"
- OriginY="83.325" UnicodeString="demo" Indices=",50;,50;,78.571;" xml:lang="en-US">
- </Glyphs>
- <Glyphs Name="a3" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="132.18"
- OriginY="83.325" UnicodeString=" " Indices="" xml:lang="en-US">
- </Glyphs>
- <Glyphs Name="a4" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="501.63"
- OriginY="415.13" UnicodeString=" " Indices="" xml:lang="en-US">
- </Glyphs>
- <Glyphs Name="a5" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="90.125"
- OriginY="427.13" UnicodeString="X" Indices="" xml:lang="en-US">
- </Glyphs>
- <Glyphs Name="a6" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="95.375"
- OriginY="427.13" UnicodeString="ps " Indices=",50;,35.714;" xml:lang="en-US">
- </Glyphs>
- <Glyphs Name="a7" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="106.62"
- OriginY="427.13" UnicodeString="end" Indices=",57.143;,50;" xml:lang="en-US">
- </Glyphs>
- <Glyphs Name="a8" BidiLevel="0" Fill="#FF000000"
- FontUri="/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"
- FontRenderingEmSize="10.5" StyleSimulations="None" OriginX="123.9"
- OriginY="427.13" UnicodeString=" " Indices="" xml:lang="en-US">
- </Glyphs>
- <Path Data="M 91.5,88.25 L 500.31,88.25 L 500.31,414.55 L 91.5,414.55 Z"
- Clip="M -0.000000465,87.75 L 595.5,87.75 L 595.5,415.5 L -0.000000465,415.5 Z "
- AutomationProperties.HelpText="Capture3.PNG">
- <Path.Fill>
- <ImageBrush ImageSource="/Resources/Images/image_0.jpg"
- Viewbox="0,0,545.08,435.06" TileMode="None" ViewboxUnits="Absolute"
- ViewportUnits="Absolute" Viewport="0,0,1,1">
- <ImageBrush.Transform>
- <MatrixTransform Matrix="408.81,0,0,326.3,91.5,88.25"/>
- </ImageBrush.Transform>
- </ImageBrush>
- </Path.Fill>
- </Path>
- </Canvas>
- </FixedPage>
这个文档的内容让我们相当兴奋, 因为它是和WPF XAML规格直接兼容的(除了字体)! 虽然这是一个普通的由word生成的XPS文档, 而非一个由DWG转化而成的DWFx文档, 但是既然DWFx宣称兼容XPS, 那么它在WPF中呈现肯定不是问题了.
所以, 总结起来说, XPS主要元素的组织形式, 大概可以是如右图, 当然这仅仅是个为了加深印象的示意图, 实际上fpage文件引用了字体文件和图像文件.
好吧,我们有点迫不及待的想知道DWFx格式的内幕了. DWFx文件就是一个平凡意义上的XPS吗? 它有自己特有的元素吗? 除了呈现, 我们还有操作DWFx内容的可能吗?
从DWG到DWFx
当然, 为了从DWG文件获得XAML, 这是最重要的一步, 从DWG文件转化为DWFx文件. 这在很多人看来是个很简单的事情 - 如果安装了AutoCAD, 那么直接文件另存为就可以了. 可是事情往往不是这么简单. 首先你发现另存为DWFx以后再次打开, 内容有可能变了, 这说明默认格式转换的配置文件有些问题; 其实你发现AutoCAD太贵了, 你买不起或者你的客户不愿意投资.
所以我们首先需要的是另外一个工具, 这个工具既可以将DWG文件转换为DWFx文件, 又必须是免费的. 有这种工具么? 是的, 而且是AutoDesk官方出品的工具 – DWG TrueView. 点击链接注册后可以下载. 运行这个软件, 你可以先尝尝鲜看看.
其实从DWG文件转化为DWFx的步骤相当简单, 只需要对其中一点注意即可:
1.用TrueView打开待转换的DWG文件;
2.点击"主菜单"图标, 打开Export子菜单, 你可以看到TrueView支持将DWG文件转化为DWF文件,DWFx文件,以及PDF文件.
3.点击"DWFx"菜单, 打开"Save As DWFx"对话框
4.点击"option"按钮. 这就是需要注意的一步了, 如果你想保留尽可能多的DWG文件信息, 比如Block信息, 你需要这一步来设置导出文件内容.
5.在上一步弹出的菜单中选择"包含Block", 并扫描创建新的Block模板.
6.保存模板. 点击确定回到"Save As DWFx"对话框.小心选择"Export"选项, 一般这个选项有"Window"/"Display"/"Extent". 选择"Display"是当前可见部分, 选择"Window"是当前窗口部分, 选择"Extent"是拉伸后的整个图即原图. 一般选择"Extent"就可以了.
7.点击去顶就开始了导出过程.
8.最终得到我们的DWFx文件.
从XPS到DWFx
现在我们可以继续解剖工作了. 这次的解剖对象是一个DWFx文件, 你可以在这里获得它. 因为DWFx兼容XPS规范, 所以我们同样改掉后缀名为zip然后解压缩打开, 得到了如右示意图这样一个目录结构. 这个示意图标出了对于DWG普通意义上来说比较重要的部分. 如果你对DWFx感兴趣, 我还是推荐你拿一个DWFx文件亲自看一看, 这样印象可能更深刻些. 这个图下面是目录级别示意图.
哇, 这么多文件和目录啊, 那么这些文件和目录都是什么意思呢? 哪些对我来说有意义?
我简单总结了一下, 并且画了下面这个说明表:
Name |
Comment |
[Content_Types].xml: |
It a Type-Content pair dictionary. We need this file to locate the appropriate content by types. |
DWFDocumentSequence.dwfseq |
This file is used to locate the manifest.xml file of a DWFx package. |
Manifest.xml |
This file is the core file of a DWFx package. It shows how the DWFx package is organized, and shows how to reach the functional parts of a DWFx package, including “2d graphics dictionary”, “2d graphics extension”, “object definition”, “thumbnail”… |
Object definition file |
This file defines the Properties, Objects and instance as well as the unit information. The customized properties in DWG file are convert into this file. The object definition in this file indicates its id and its property group. The instance definition in this file indicates the object id and its corresponding node id. |
2d streaming graphics file |
This file refers to the path definition part of FixedPage.fpage, which contains the graphics information converted from DWG file, i.e. Line definition. |
2d graphics extension file |
This file contains the information to connect the 2d streaming graphics file with the Object definition file. |
看完这个表, 你大概应该知道, DWFx里面的"2d streaming graphics file"大概对应了XPS里面的FixedPage. 它就是显示DWFx与XPS兼容性的地方. 对于这个包的入口, DWFx也兼容XPS, 但是它又有自己完全独立的入口, 叫做"DWFDocumentSequence.dwfseq". 从它开始深入下去, 能获得从XPS规格无法取得的额外信息, 比如Block, 比如Layer等.
另外这个表的最后三行, 恰恰是DWFx文件的核心数据部分. 而它们又是互相联系的. 这个联系的示意图如下:
好了, 我们应该到此打住了. 更深入的发现, 等着聪明的你继续深入下去:)
下一节, 也是这个系列的最后一节, 将讲述三个方面的问题, 即:
- 如何在WPF里面呈现DWFx文件
- .NET程序集对于XPS包的支持
- 如何在本节的基础上, 对DWFx的内容进行操作.
另: 文中提到的所有文件, 除了明显给出链接的之外, 我打了一个包, 可以从这里下载.
作者:Jeffrey Sun
出处:http://sun.cnblogs.com/
本文以“现状”提供且没有任何担保,同时也没有授予任何权利。本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。