DWG的时间奇点 AutoCAD(Auto Computer Aided Design)是美国Autodesk公司首次于1982年生产的自动计算机辅助设计软件,用于二维绘图、详细绘制、设计文档和基本三维设计。现已经成为国际上广为流行的绘图工具。CAD技术不是AutoDesk公司的专利, 同样CAD在计算机上的应用, 也不是AutoDesk公司开的先河. 在AutoCAD出现之前, 已经有了一家叫做VersaCAD的公司制作的同名软件出现在市场上. 由于VersaCAD很强大也很贵, 所以AutoDesk在一开始选择了一条聪明的道路, 免费及开放, 这使得AutoCAD得以迅速传播和升级. 借助于AutoCAD的东风, DWG文件格式成为事实上的二维设计绘图的标准格式, 这是其一. 前期的开放也为后来发生的事情埋下了引线, 这是其二. 但是历史在小局部偶尔也会开一下倒车. 在AutoCAD发展的过程中, 它逐步的转向了收费, 并且DWG文件成为了一个封闭的标准! 直到今天, 互联网上依然无法得到一份完整的, 关于某个DWG文件格式版本的技术文档. AutoDesk利用AutoCAD的影响力给自己构建了一个帝国, 在赚取大把美钞的同时, 也关闭了DWG格式标准与其他软件系统互通的大门. 我们现在仅仅直到一点点朦胧的东西, 比如: DWG格式的组织形式基于二进制编码; DWG格式具有自关联的压缩技术; DWG文件能够自验证等. 但也是仅仅如此而已, 没有任何细节可言. 同时, 基于AutoCAD这个庞大平台的二次开发也从未停止过. AutoLisp和ADS成为早期的主力. 后来AutoCAD发布了基于C++语言的二次开发包-ObjectARX. 至此, 基于AutoCAD的二次开发行为第一次被明确定义了(至少笔者是这么认为). 这一开发行为的流程图大概看起来如左: ObjectARX作为类库提供相关功能, 开发人员可以在任何编辑器中编辑二次开发代码; 通过C++编译器编译和链接; 最终生成动态链接库载入到AutoCAD中实现功能扩展. 即使后来出现了ObjectARX面向其他语言比如C#语言的版本, 这一基本方式还是在本质上得到了保留. 互操作成为部分可能, 虽然不是直接实现. 工程人员在AutoCAD软件内打开对应的DWG文件后, 可以通过二次开发的功能扩展, 使DWG格式内容转化为可被其他系统认可的数据. "AutoCAD在地上划了一个圈, 逼迫所有人把东西放到这个圈子里." 反抗者的步伐 中国有句话, 叫"哪里有压迫, 哪里就有反抗." 在AutoCAD的压迫下, 第一个揭竿而起的不是某个谁, 而是一个组织. 这个组织的名字叫做 "Open Design Alliance", 简称ODA. ODA是在一个月黑风高的晚上带着武器来的, 这个武器就是著名的 OpenDWG文档和 DWGDirect开放类库. 前文说到AutoDesk初期的开放策略给自己埋下了隐患,这个隐患现在被ODA利用了. ODA在最初的DWG版本基础上, 通过类似于破解的方式, 获取了DWG格式的大部分技术细节. ODA收取少量的注册费用以维持运营, 并且以开放的姿态发布了 DWGDirect - 面向C++语言, DWGDirectX - 面向ActiveX控件, DWGDirect.NET - 面向.NET. ODA承诺, 面对AutoCAD的版本升级, 将以最快的速度更新这些类库. 实际上它做到了: 现在, DWGDirect类库已经声称支持DWG/DXF/BDXF等格式最新的2010版本的读写. ODA的行为从根本上动摇了AutoDesk的根基. 2006 年11月22日 Autodesk 对 Open Design Alliance 提出了诉讼. 下面这一段是AutoDesk公司对于诉讼的官方声明: "The ODA software libraries contain technology that falsely identifies customer data files their software creates as Autodesk-created files. We have the right to control the use of our trademark and we depend on that right in informing customers of the source of the files they are introducing in their CAD environments. The ODA interfered with our ability to do that. The ODA failed to respond to our reasonable request to stop violating our rights. As a result Autodesk is suing the ODA in order to defend its ability, through TrustedDWG, to assure our customers of the source of customer data files and make sure the origin of the files is not falsely attributed. The ODA’s latest software libraries mimic TrustedDWG and defeat the very purpose of the program. We are relying on trademark laws to protect our ability to inform customers of the source of customer data files." 诉讼还在继续, 走向也不得而知, 我们能确定的是, AutoDesk和ODA到现在都活得很好. 不过作为系统开发人员, 我们似乎更应该关注OpenDWG文档和DWGDirect潜在的风险: - OpenDWG文档是以一种近似于破解的方式获取了DWG格式的细节. 这将会给使用DWGDirect的开发人员带来法律上的风险.
- OpenDWG文档不是一个对DWG所有版本的完整描述. 它仅仅支持到2004, 并且部分支持2007.
- 甚至于在某一特定版本内部, OpenDWG文档至今还未破解部分字节的含义.
笔者不是ODA的粉丝. 恰恰相反, 笔者对于这种破解的行为持怀疑和否定的态度. 但是毫无疑问, OpenDWG文档和DWGDirect类库重新定义了二次开发的流程, 使在AutoCAD平台外使用和修改DWG文件成为现实. 事实上, 国内很多公司在使用OpenDWG. 现在, 由于OpenDWG文档和DWGDirect的流行, 二次开发的流程被重新修订为: - 使用AutoCAD制作DWG文件
- 向外部系统传递DWG文件
- 外部系统利用DWGDirect读取数据.
ODA开了掘墓的先河, 后来者自然蜂拥而上. 现在在互联网上, 基于OpenDWG的各种类库琳琅满目, 凡此种种, 却已不足道也. 强者的联姻 外部世界对于AutoDesk来说有点风雨欲来的味道. 互操作的群众呼声越来越大, OpenDWG越来越让它头疼. 到了二十一世纪第一个十年的末期, 系统软件理论及实践都攀升至一个前所未有的高度, 系统开发人员们越来越清楚地认识到DWG格式的封闭和对于互操作支持的匮乏, 严重影响了一些自动化系统对于DWG工程图的使用. 在这样的背景下, 为了应对图形输出,发布,共享和互联的呼声, AutoCAD 2009开始声称支持一种新的文件格式DWFx. DWFx基于标准ISO/IEC 29500-2:2008 Open Packaging Conventions (OPC, Office Open XML文档标准的一部分), 可以看成是一种XPS兼容格式. DWFx格式基于平文组织, 和所有的xps文档一样, 它其实是一个zip包, 里面包含了图形信息, 对象定义等内容. 现在AutoDesk终于迈出了在开放道路上的第二步, 和另一个软件巨头微软站到了一起. DWG文件可以发布为DWFx格式, 并且使用Office Visio(可以查看XPS文档)直接打开观看; 另外, 在.NET类库中, 可以直接使用DocumentViewer来查看DWFx文档. 虽然依然无法修改DWG文件, 但是毕竟可以在外部系统中直接现实工程图文件了. 尾声 "青山遮不住,毕竟东流去." 认清形势总是一个比较痛苦的过程, 也来得比较缓慢. 但是我们还是希望, AutoDesk在互联共享的道路上能更进一步. 现状是, ObjectARX如入中天, 是绝对的主流; OpenDWG如火如荼, 却暗藏隐患; DWFx完成了读工程图的大部分功能(有些数据内容在从DWG到DWFx的转换过程中被忽略掉了), 在写的道路上裹足不前(这在很大程度上取决于AutoDesk的意愿). DWFx还是有些意思的. 对于一些特定的需求, DWFx更轻型更快捷. 这个系列的下一节, 准备仔细地剖析DWFx文件格式及.NET应用, 最后一节将发布一个笔者写的完全基于C#的, 在部分功能上能操作DWFx内容的DWFx类库.
什么是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文件只有一个引用记录, 例如:
- <font style="font-family: 'Microsoft Yahei', Simsun; "><font face="verdana, ����, Arial">FixedDocSeq.fdseq
- <ul type="1" class="litype_1" style="margin-left: 14px; "><li style="list-style-position: initial; list-style-image: initial; "><font style="color: rgb(64, 196, 255); "><FixedDocumentSequence </font><font style="color: rgb(237, 218, 192); ">xmlns</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"http://schemas.microsoft.com/xps/2005/06"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "><font style="color: rgb(64, 196, 255); "><DocumentReference </font><font style="color: rgb(237, 218, 192); ">Source</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Documents/1/FixedDoc.fdoc"</font><font style="color: rgb(64, 196, 255); ">/></font></li><li style="list-style-position: initial; list-style-image: initial; "><font style="color: rgb(64, 196, 255); "></FixedDocumentSequence></font></li></ul></font></font>
复制代码
docProps目录 - 这个目录主要用来保存和文档属性有关的内容, 比如文档的缩略图, 文档的创建/修改时间等. Resources目录 - 这个目录主要保存多媒体信息, 比如文档中插入的图像, 比如文档中使用的字体. 我建议你自己打开看一看, 因为字体比较有趣, 不是我们常见的那种Truetype字体或者点阵字体, 而是后缀名.odttf的被混淆的字体. 这是个相当有趣的话题, 如果有兴趣, 大家可以深入研究一下undefined Documents目录 - 这个目录是最重要的, 它存放了大部分和XPS内容呈现有关的材料, 比如文档信息, 页面信息, 文档结构等.这个目录的下一级是一个以序号命名的目录. 序号目录的下一级, 是FixedDoc.fdoc/Pages目录/Structure目录. FixedDoc.fdoc指向了文档显示的具体页面(Page), Pages目录里面保存了所有的页面, Structure目录保存了说明文档结构的.struct文件. 事实上, Page就是直接作为渲染源, 通过诸如XPS Viewer等查看工具, 直接被呈现在你眼前的文档内容. FixedDoc.fdoc文件的内容大多比较简单, 比如本例中: FixedDoc.fdoc
- <undefinedageContent Source="undefinedages/1.fpage"></PageContent>
FixedPage.fpage的内容则相当丰富, 因为它关系到绝大部分的内容呈现:
Fixed Page
- <ul type="1" class="litype_1" style="margin-left: 14px; "><li style="list-style-position: initial; list-style-image: initial; "><font style="color: rgb(64, 196, 255); "><FixedPage </font><font style="color: rgb(237, 218, 192); ">xmlns</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"http://schemas.microsoft.com/xps/2005/06"</font>
- <font style="color: rgb(237, 218, 192); ">Width</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"794"</font></li><li style="list-style-position: initial; list-style-image: initial; "><font style="color: rgb(237, 218, 192); ">Height</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"1123"</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"zh-CN"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Canvas></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Canvas.RenderTransform></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><MatrixTransform </font><font style="color: rgb(237, 218, 192); ">Matrix</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"1.333333333,0,0,1.333333333,0,0"</font><font style="color: rgb(64, 196, 255); ">/></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Canvas.RenderTransform></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a0"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"90.125"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"83.325"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"X"</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">""</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a1"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"95.375"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"83.325"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"ps "</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">",50;,35.714;"</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a2"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"107.37"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"83.325"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"demo"</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">",50;,50;,78.571;"</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a3"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"132.18"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"83.325"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">" "</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">""</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a4"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"501.63"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"415.13"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">" "</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">""</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a5"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"90.125"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"427.13"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"X"</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">""</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a6"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"95.375"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"427.13"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"ps "</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">",50;,35.714;"</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a7"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"106.62"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"427.13"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"end"</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">",57.143;,50;"</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><Glyphs </font><font style="color: rgb(237, 218, 192); ">Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"a8"</font>
- <font style="color: rgb(237, 218, 192); ">BidiLevel</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0"</font>
- <font style="color: rgb(237, 218, 192); ">Fill</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"#FF000000"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontUri</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/30AC4461-3665-645B-4B00-7251C76B5C3D.odttf"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">FontRenderingEmSize</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"10.5"</font>
- <font style="color: rgb(237, 218, 192); ">StyleSimulations</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">OriginX</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"123.9"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">OriginY</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"427.13"</font>
- <font style="color: rgb(237, 218, 192); ">UnicodeString</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">" "</font>
- <font style="color: rgb(237, 218, 192); ">Indices</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">""</font>
- <font style="color: rgb(237, 218, 192); ">xml:lang</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"en-US"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Glyphs></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><<img src="http://bimcad.org/static/image/smiley/default/titter.gif" smilieid="9" border="0" alt="">ath </font><font style="color: rgb(237, 218, 192); ">Data</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"M 91.5,88.25 L 500.31,88.25 L 500.31,414.55 L 91.5,414.55 Z"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">Clip</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"M -0.000000465,87.75 L 595.5,87.75 L 595.5,415.5 L -0.000000465,415.5 Z "</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">AutomationProperties.HelpText</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"Capture3.PNG"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><<img src="http://bimcad.org/static/image/smiley/default/titter.gif" smilieid="9" border="0" alt="">ath.Fill></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><ImageBrush </font><font style="color: rgb(237, 218, 192); ">ImageSource</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"/Resources/Images/image_0.jpg"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">Viewbox</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0,0,545.08,435.06"</font>
- <font style="color: rgb(237, 218, 192); ">TileMode</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"None"</font>
- <font style="color: rgb(237, 218, 192); ">ViewboxUnits</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"Absolute"</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(237, 218, 192); ">ViewportUnits</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"Absolute"</font>
- <font style="color: rgb(237, 218, 192); ">Viewport</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"0,0,1,1"</font><font style="color: rgb(64, 196, 255); ">></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><ImageBrush.Transform></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "><MatrixTransform </font><font style="color: rgb(237, 218, 192); ">Matrix</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"408.81,0,0,326.3,91.5,88.25"</font><font style="color: rgb(64, 196, 255); ">/></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></ImageBrush.Transform></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></ImageBrush></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Path.Fill></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Path></font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(64, 196, 255); "></Canvas></font></li><li style="list-style-position: initial; list-style-image: initial; "><font style="color: rgb(64, 196, 255); "></FixedPage></font>
- </li></ul>
复制代码 这个文档的内容让我们相当兴奋, 因为它是和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文件亲自看一看, 这样印象可能更深刻些. 这个图下面是目录级别示意图.
哇, 这么多文件和目录啊, 那么这些文件和目录都是什么意思呢? 哪些对我来说有意义? 我简单总结了一下, 并且画了下面这个说明表: | | | 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. | | 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”… | | 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文件的核心数据部分. 而它们又是互相联系的. 这个联系的示意图如下: DocumentViewer 其实复杂的事情原本可以很简单. 你想要的那个轮子, 也许别人早就为你造好了. 在这里也是如此. 比如全部你想要的, 就是在你的系统前端可以直接查看DWG文件, 那么全部需要做的, 仅仅是简单的从DWG导出为DWFx文件, 然后使用WPF的DocumentViewer控件打开这个文件就可以了. 这个示例程序可以从这里获取.XAML- <font><font face="verdana, ����, Arial">
- <ul type="1" class="litype_1" style="margin-left: 14px; "><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(64, 196, 255); "><DocumentViewer</font><font style="color: rgb(237, 218, 192); "> Name</font><font style="color: rgb(64, 196, 255); ">=</font><font style="color: rgb(255, 128, 255); ">"docViewer"</font><font style="color: rgb(64, 196, 255); "> /></font>
- </li></ul>
- </font></font>
- <font><font face="verdana, ����, Arial">Code-Behind : Load DWFx
- <ul type="1" class="litype_1" style="margin-left: 14px; "><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(0, 255, 255); ">XpsDocument</font>
- <font style="color: rgb(255, 192, 162); ">xpsDocument</font>
- <font style="color: rgb(192, 192, 192); ">=</font>
- <font style="color: rgb(64, 196, 255); ">null</font><font style="color: rgb(224, 224, 224); ">;</font></li><li style="list-style-position: initial; list-style-image: initial; "></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(64, 196, 255); ">if</font><font style="color: rgb(224, 224, 224); "> (</font><font style="color: rgb(255, 192, 162); ">dlg</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">ShowDialog</font><font style="color: rgb(224, 224, 224); ">() </font><font style="color: rgb(192, 192, 192); ">==</font>
- <font style="color: rgb(255, 192, 162); ">System</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">Windows</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">Forms</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(0, 255, 255); ">DialogResult</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">OK</font><font style="color: rgb(224, 224, 224); ">)</font></li><li style="list-style-position: initial; list-style-image: initial; "><font style="color: rgb(224, 224, 224); ">{</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// If there's an existing document open, close it.</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(64, 196, 255); ">if</font><font style="color: rgb(224, 224, 224); "> (</font><font style="color: rgb(255, 192, 162); ">xpsDocument</font>
- <font style="color: rgb(192, 192, 192); ">!=</font>
- <font style="color: rgb(64, 196, 255); ">null</font><font style="color: rgb(224, 224, 224); ">)</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(255, 192, 162); ">xpsDocument</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">Close</font><font style="color: rgb(224, 224, 224); ">();</font></li><li style="list-style-position: initial; list-style-image: initial; "></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// Create an XpsDocument for the file specified by the user.</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(64, 196, 255); ">try</font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(224, 224, 224); ">{</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(255, 192, 162); ">xpsDocument</font>
- <font style="color: rgb(192, 192, 192); ">=</font>
- <font style="color: rgb(64, 196, 255); ">new</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(0, 255, 255); ">XpsDocument</font><font style="color: rgb(224, 224, 224); ">(</font><font style="color: rgb(255, 192, 162); ">dlg</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">FileName</font><font style="color: rgb(224, 224, 224); ">, </font><font style="color: rgb(255, 192, 162); ">System</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">IO</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(0, 255, 255); ">FileAccess</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">Read</font><font style="color: rgb(224, 224, 224); ">);</font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(224, 224, 224); ">}</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(64, 196, 255); ">catch</font><font style="color: rgb(224, 224, 224); "> (</font><font style="color: rgb(0, 255, 255); ">UnauthorizedAccessException</font><font style="color: rgb(224, 224, 224); ">)</font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(224, 224, 224); ">{</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(255, 192, 162); ">System</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">Windows</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(0, 255, 255); ">MessageBox</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">Show</font><font style="color: rgb(224, 224, 224); ">(</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(0, 255, 255); ">String</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">Format</font><font style="color: rgb(224, 224, 224); ">(</font><font style="color: rgb(255, 128, 255); ">"Unable to access {0}"</font><font style="color: rgb(224, 224, 224); ">, </font><font style="color: rgb(255, 192, 162); ">dlg</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">FileName</font><font style="color: rgb(224, 224, 224); "> ) );</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(64, 196, 255); ">return</font><font style="color: rgb(224, 224, 224); ">;</font></li><li style="list-style-position: initial; list-style-image: initial; "> <font style="color: rgb(224, 224, 224); ">}</font></li><li style="list-style-position: initial; list-style-image: initial; "></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// For optimal performance the XPS document should be remain</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// open while its FixedDocumentSequence is active in the</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// DocumentViewer control. When the XPS document is opened</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// with the XpsDocument constructor ("new XpsDocument" above) a</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// reference to it is automatically added to the PackageStore.</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// The PackStore is a static application collection that contains</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// a reference to each open package along the package's URI as</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// a key. Adding a reference of the XPS package to the</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// PackageStore keeps the package open and avoids repeated opens</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// and closes while the document content is being accessed by</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// DocumentViewer control. The XpsDocument.Dispose() method</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// automatically removes the package from the PackageStore after</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// the document is removed from the DocumentViewer control and</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(124, 252, 0); ">// is no longer in use.</font></li><li style="list-style-position: initial; list-style-image: initial; ">
- <font style="color: rgb(255, 192, 162); ">docViewer</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">Document</font>
- <font style="color: rgb(192, 192, 192); ">=</font>
- <font style="color: rgb(255, 192, 162); ">xpsDocument</font><font style="color: rgb(192, 192, 192); ">.</font><font style="color: rgb(255, 192, 162); ">GetFixedDocumentSequence</font><font style="color: rgb(224, 224, 224); ">();</font></li></ul></font></font>
复制代码
DocumentViewer是WPF专为呈现XPS文件内容准备的控件. 它所呈现的内容叫做FixedDocument, 这完全符合XPS的标准. 我们的DWFx格式文件是与XPS兼容的, 所以也可以被DocumentViewer直接载入和显示.我们用DocumentViewer直接打开一个DWFx文件并仔细对比, 你会发现它所呈现出来的内容和在AutoCAD中精确地相同. 这一特点, 取决于DWG文件导出到DWFx文件的过程中所采取的处理方式. 在转化的过程中, 所有的图形地理信息, 包括直接描述和图块信息引用, 都被原地还原被进行相应的变换(比如旋转, 缩放), 然后将最终的图形信息全部写入到FixedPage文件中. 采取这样的行为, 保证了转换前后的呈现精确问题, 并且这种精确性的实现不依赖于转换后容器的特性. 凡事有一利必有一弊. 这里面有个问题. 我们知道, 如果我们手里有图形的原信息, 有变换公式, 那么我们很容易就能得到变换后的图形. 反之, 如果我们有变换后的图形和变换公式, 虽然可能麻烦一些, 但是大多数情况下我们能得到图形的源信息. 但是, 如果我们有图形的源信息和变换后的图形, 那么在大多数情况下猜测变换公式是极其困难的; 如果我们仅有变换后的图形, 那么还愿图块的图形信息引用, 是根本不可能的. 现在我们得到的DWFx这个包, 就让我们处在了这个比较囧的处境中 - 我们有变换后的图形信息(都在FixedPage中), 除此之外, 关于图形的一切其他细节, 比如它是经过什么变换来的, 它和另外一个图块是不是同一类图形等这些信息, 什么都没有了.好吧, 这实在是够麻烦的. 不过我们可以有一些折中的办法, 比如, 在设计时, 相同的图块, 我们给它定义一些自定义属性,来标记这些图块原本指代了同一类实体, 比如都指代了电脑. 我们有这些自定义属性就够了. 自定义的属性是可以被获得的, 这些属性都保存在DWFx包中的Object definition file文件中.自定义属性才是这个系统能够自动化的关键! 比如我们要建设一个网吧自动管理系统. 我们的DWG文件就是包括电脑摆放位置在内的网吧布局设计. 我们的期待能交互的实体是DWG文件中摆放的一台台电脑. 我们期待这个管理系统能自动读入DWG/DWFx文件来表示网吧电脑的陈列位置, 然后我能在这些电脑上点击选择操作, 比如杀毒, 比如下载设置文件等. 要达到这个目的, 我们依赖自定义属性就可以了. 我们可以要求设计厂商在DWG文件中对每一台电脑加上一个电脑编号. 到我们的系统中, 我们可以读出这个自定义属性, 从而实现自动化. DWG/DWFx文件标示了实体的位置, 自定义属性标示了实体的唯一标记并实现系统的互动. 上一篇文章已经详细分析了DWFx包内各个文件的含义. 所以读取这些文件的内容是相对容易的. 不过看起来, 我们首先需要一个标尺类库, 来标示我们应该如何去读取,怎么读.XPS Packaging类库 .NET Framework在System.Windows.Xps.Packaging命名空间下, 提供了一系列的类型和方法来帮助我们显示和操作XPS文档. 虽然我们的DWFx文件格式上兼容XPS, 但是显然XPS Packaging这个类库是Generic的, 是为所有的XPS文件设计的, 所以不太可能使用这个类库来直接操作我们的DWFx文件内容(从上文的文件内部组织形式也能体现这种差异). 不过作为微软提供的类库, 它应该是我们想要实现的DWFx类库的最好的标杆. 您可以从这个链接来查看和学习XPS Packaging类库: http://msdn.microsoft.com/en-us/library/system.windows.xps.packaging.aspx. 可以注意的几个类是XPSDocument, xxxSequenceReader/Writer, xxxDocumentReader/Writer, xxxPageReader/Writer. 聪明的你一定注意到了, 这几个类的名字几乎正好对应了上文分析的XPS文档的组织形式. 所以如果我们来写DWFx Packaging Library, 也要清楚的显示出DWFx文件内部的层次形式.DWFx Packaging & Converting Library的实现
这个类库一共包含了4个项目:JeffreySun.Dwfx : 基础项目, 包含了一些DWFx的基本信息, 以及错误处理等;JeffreySun.Dwfx.Packing : Packaging类库, 实现读取DWFx文件包内容的功能;JeffreySun.Dwfx.Converting : Converting类库, 将读取的DWFx文件包内容链接并转化为XAML + 自定义属性JeffreySun.DWFX2XAMLConverter : 一个简单的示例程序. 您一定要注意这段重要声明! 这一类库仅以学习目的发布, 你可以在你的项目中直接使用, 但是作者不保证该类库的完整性, 也不保证该类库中没有问题, 并且不提供任何技术支持. 作者强烈建议您在研究DWFx格式规范后实现自己的DWFx类库.
|