天天看點

Windows列印體系結構之列印驅動架構

廬山煙雨浙江潮,未到千般恨不消。到得原來無别事,廬山煙雨浙江潮。

Windows的列印驅動從總體架構上來說,包括一個渲染元件和一個配置元件。我們可以回想一下最開始的總體架構圖。

渲染元件就是負責将應用程式傳來的每一頁的繪制指令(GDI指令)轉換成列印機用來渲染的指令資料(列印機才能識别的指令)發送到列印機中。

配置元件又包含一個可以讓使用者進行打選項配置的使用者接口元件和一個将列印機的配置和特征傳遞給應用程式的程式接口。

而相較于Windows的其他硬體裝置,比較特殊的情況是,列印機的驅動程式并不直接通路和操縱硬體裝置,而是把經過處理的二進制指令流和資料流發送給假脫機系統,由假脫機系統負責在合适的時間将列印資料發送至列印機裝置所在的端口,完成列印任務。

而列印機驅動在這裡也細分成兩個大的架構:GDI架構與XPS架構。

GDI 列印驅動程式由以下2個元件組成【https://msdn.microsoft.com/en-us/library/windows/hardware/ff549558(v=vs.85).aspx】:

列印圖形DLL:輔助 GDI 繪制列印作業,并将繪制後的資料流傳送到列印假脫機程式。

列印接口DLL:為列印配置選項導出一個使用者接口,同時導出假脫機可以調用以通知驅動程式與列印相關的系統事件的接口。

渲染元件:列印圖形 DLL:【https://msdn.microsoft.com/en-us/library/windows/hardware/ff551757(v=vs.85).aspx】

這裡的列印圖形DLL其實就是一個渲染元件。列印圖形DLL實作Drv為字首的圖形DDI(Device Driver Interface,圖形驅動接口)【後面說明】函數,這些函數有如下兩個方面的作用:

1)輔助GDI完成列印任務。當一個繪制操作必須以裝置指定的方式來繪制或者要執行一些GDI引擎不支援的繪制操作時,列印圖形DLL可以提供圖形DDI函數來處理那些必須按照特定于裝置的方式執行和那些不能由GD繪制引擎單獨完成的繪制操作。

2)将繪制後的資料流傳送到假脫機系統。列印圖形DLL通常以RAW資料類型(包括指令序列)【後面說明】産生一個輸出流,假脫機可以通過列印螢幕将該輸出流傳送到列印機硬體。

首先我們來說明什麼是圖形DDI(Device DriverInterface,圖形驅動接口)?GDI是圖形引擎,其和圖形裝置驅動程式之間的接口協定就是裝置驅動程式接口(DDI)。需要注意的是,DDI是Device DriverInterface,中文字面意思是裝置驅動程式接口,正确的寫法其實前面還應該加上圖形的英文,這樣才沒有歧義。圖形裝置驅動程式一般是核心模式DLL,被加載到核心位址空間。它負責在硬體裝置上最終實作使用者應用程式的繪制調用。

另外一個需要說明的是RAW資料類型,Windows 列印程序通常支援五種資料類型。最常用的兩種資料類型是增強型圖元檔案 (EMF) 和列印就緒 (RAW)。

EMF,即增強型圖元檔案,是大多數Windows應用程式的預設資料類型。使用EMF,系統會将要列印的文檔更改為比RAW檔案更易于移植并通常可以在任意列印機上列印的圖元檔案格式。

RAW是使用非Windows程式的用戶端的預設資料類型。RAW資料類型通知背景處理程式在列印之前不要更改列印作業。使用這種資料類型,準備列印作業的整個過程是在用戶端計算機上完成的。RAW資料格式是列印機語言PDL的資料格式。PCL和PostScript都是RAW資料,列印引擎可以直接處理。

EMF(Enhanced MetaFile)和RAW處理方式和功能有所不同。

資料類型設定為EMF時,Windows系統生成一個包含GDI功能調用的列印處理檔案,此功能調用生成一個組指令以形成應用程式的對象,在設定檔案的讀取和傳輸過程中完成對列印設定檔案的解釋。是以,EMF資料格式的處理方式能夠使傳回應用程式的時間加快。

使用RAW資料類型時,在寫入設定檔案之前,列印任務被傳輸到驅動程式進行解釋,圖像處理和資料解包。是以,使用RAW資料格式比使用EMF格式列印速度慢。

配置元件:列印接口DLL【https://msdn.microsoft.com/en-us/library/windows/hardware/ff551764(v=vs.85).aspx】

這個列印接口DLL就是驅動程式架構的配置元件,列印驅動程式通常給使用者提供很多可修改列印配置的選項,這些選項可以在每一個要列印的文檔中被修改。如列印的份數、雙面列印、紙張大小、紙張來源、色彩模式、列印分辨率、方向和縮放等,這些選項可以通過由應用程式所調用的使用者接口來實作。

列印接口DLL負責為列印配置選項導出一個使用者接口。通過為列印機建立屬性表單頁來提供這一使用者接口。應用程式(如Word等)通過調用由假脫機導出的Win32函數顯示這個接口,假脫機系統轉而又可以調用由列印接口DLL定義的函數。

列印接口DLL不僅為列印配置選項提供使用者接口,還導出一些函數。這些函數被假脫機調用以通知驅動程式與列印相關的系統事件,例如驅動程式的安裝和更新、列印機的添加和連接配接等。

列印圖形DLL提供的繪制函數是基于特定裝置的,取決于硬體的繪制能力來決定其所處的工作模式。這裡說的繪制其實就是渲染。包括如下3種情況:

列印圖形DLL可以選擇全部提供DDI繪制函數(RAW模式);

部分提供DDI繪制函數(回調模式);

不提供DDI繪制函數(EMF模式)。

下圖是MSDN上對于GDI架構的說明。

Windows列印體系結構之列印驅動架構

上圖說明了應用程式使用GDI建立列印作業時的資料流。資料流傳送至列印機硬體之前,并不是列印圖形DLL會之後直接傳送,而是先傳回至假脫機,再由假脫機傳送至一個螢幕而後同過本地或網絡端口傳送至列印機硬體。

RAW模式:

在RAW模式下,應用可以直接調用驅動所提供的接口直接生成列印機所能處理的Raw檔案并直接通過端口螢幕發給實體列印機進行列印。這個驅動可以是微軟的通用驅動程式也可以是廠商自己編寫的驅動程式。

回調模式:

回調模式下,由應用發起的列印檔案的部分可能無法使用GDI本身的API來完成了,但是大部分工作是可以之間生成對應的EMF檔案的,小部分檔案必須調用DDI的繪制函數來進行,生成Raw檔案送出給列印處理器,列印處理器會将其進行處理,比如生成EMF檔案,送出給GDI User-Mode Client,然後合并為一個完整的EMF檔案,最後送出給列印處理器進行處理。列印處理器會講EMF檔案解析為列印機可以處理的Raw檔案,并通過端口螢幕發給列印機進行列印。

EMF模式:

在EMF模式中,應用通過調用GDI提供的接口而生成用于列印的通用中間檔案(EMF檔案)。再由列印假脫機隊列服務調用列印機驅動的接口将這個EMF檔案解析為列印機可以處理的Raw檔案,并通過端口服務發給列印機進行列印。

經過上述的說明,也許有人會産生疑問,為什麼生成EMF檔案不需要去調用DDI就可以生成EMF檔案?簡要來說,這是由Windows決定的,EMF檔案是通過Windows的GDI函數集來描述圖像的。我們可以把EMF檔案了解為是GDI的指針或者Metafile。EMF格式裡面标記的每個含義或者鍵值和GDI裡面的某一類進行一一對應,當需要解析EMF檔案時,隻需要讀取相應的鍵值就可以知道相應的GDI圖像顯示的動作是什麼。

同時,還有一個疑問:為什麼最後都是生成Raw檔案發送到列印機?先說說這得從列印背景列印資料格式說起,一般的列印機背景格式有多種,如RAW、EMF...,但RAW格式是唯一被全部列印機所支援。而且在遠端列印中,隻有RAW格式是被Windows支援的,這可以在MSDN中查到。另外,如果列印圖像,除DIB圖像外,部分列印機在采用EMF格式時無法列印,如HP LaserJet 1100。當然,如果采用GDIPLUS技術列印,在400DPI下也是可以正常列印的,但當DPI大于400(具體上限沒有測試),圖像依然無法列印。

這裡出現的DPI指的是顯示的分辨率。現在我們通常講的列印機分辨率是多少 dpi,指的是“在該列印機最高分辨率模式下,每英寸所能列印的最多理論墨點數”。更加合理的對于dpi 的解釋是這樣的:如果一台列印機的分辨率是4800×1200 dpi,那麼意味着在X方向(橫向)上,兩個墨點最近的距離可以達到1/4800英寸;在Y方向(縱向)上,兩個墨點的距離可以達到1/1200英寸。

最後在MSDN上面還有一副關于GDI模式的圖:

Windows列印體系結構之列印驅動架構

這幅圖表示的是GDI模式下列印驅動位于核心态的工作模型,由于XP以後的列印機驅動都為使用者态,核心态的列印機驅動基本不再使用,就不另加說明了。

總結一下:當GDI程式執行列印時,通過調用API來傳遞GDI繪圖指令到繪圖引擎,繪圖引擎要麼和列印驅動一起合作來緩存這些繪制指定到一個EMF檔案中,要麼直接渲染成一個可列印的圖檔發送到列印假脫機隊列服務spooler中。列印假脫機隊列服務Spooler解釋EMF檔案,并将頁面布局和作業控制指令資訊插入到資料流中,然後發送這些資料裡到序列化、并行化或者網絡形式的列印機關聯的端口上。

由于列印假脫機隊列服務Spooler和列印驅動都是可以被單獨取代,是以硬體廠商們可以很容易的增加對新硬體的支援。當需要增加對新款列印機的支援時,通常隻需要建立根據微軟所提供的列印驅動類型中相關聯的資料類型就可以了。

XPSDrv列印驅動程式體系結構基于新一代文檔格式XPS。XML PaPer Specification(XML檔案規格,簡稱XPS)。這是一種可直接列印的通用電子文檔格式,和PDF一樣可以由其他任何格式轉化。XPS是Windows内部一個完全可以重複書寫的列印子系統,列印機可以根據工作類型的不同來接收這種電子檔案,包括Microsoft Publisher和Microsoft Office檔案等的檔案皆可自由轉化為XPS電子文檔格式進行列印。

XPS不僅僅是一種文檔格式,它還是一種實體存儲結構上基于OPC,顯示技術上基于WPF技術,并且将它們與列印子系統結合的産物。

Windows列印體系結構之列印驅動架構

如上圖所示,一個XPS驅動體系的主要元件包括:

過濾器(Filter);

過濾管道(Filter pipeline);

過濾器管道管理器(Filter Pipeline Manager);

過濾器配置檔案(Filter ConfigurationFile);

XPS Spooler Process

WPF應用程式。

其中過濾器(Filter),官方翻譯為篩選器,意思差不多。過濾器配置檔案和配置子產品又稱為XPSDrv。相較于 GDI 列印驅動程式體系結構,XPSDrv 列印驅動程式體系結構采用了過濾器的方式,可以提供更具彈性的列印途徑。XPS 列印機驅動程式 (XPSDrv) 過濾器管道設計用于啟用直接和可縮放的XPS文檔列印。

首先由應用程式發出列印請求,如果發出的請求是WPF形式的列印請求那麼就将進入XPS交換流管道Spooler Process。XPSDrv是XPS列印管道的核心,它包括一個調用過濾器的列印程序子產品的設定檔案,描述了列印驅動是如何被加載調用的,以及不同的過濾器之間的資料是如何通信的。(這部分在XPSDrv裡叫做IFC)。另外圖中Print Pipeline Filter的配置檔案(XML)定義了:過濾器的分類,過濾器的接口以及每個過濾器的輸入輸出格式。

在圖中,列印作業通過WPF,以XPS流檔案的格式進入系統驅動,通過驅動的Ul設定,可以配置給過濾器列印時需要的資訊來進行列印操作,然後scheduler通知過濾器管道管理器(Filter pipeline manager),下面過濾器管道管理器(Filter pipeline manager)開始按照過濾器配置檔案(Filter ConfigurationFile)配置檔案來處理這些作業,過濾器管道管理器(Filter pipeline manager)通過調用配置檔案來建立過濾管道(Filter pipeline),當過濾管道(Filter pipeline)被建立完成和初始化後,濾器管道管理器(Filter pipeline manager)就打開過濾管道(Filter pipeline)讀取XPS流檔案的内容。同時,在各個過濾器之間,使用Stream或Doculnent類型進行資料交換。XPS檔案流通過WPF形式傳送給Spooler,同時在不同的過濾器之間通過一個XML配置檔案進行管理,Ul可以通過DevMode寫入Prinit Ticket進而對驅動過濾器進行設定控制。最終,檔案通過CsxPStops這個過濾器轉化為目前大部分列印機可識别的PS或PCL語言,最後通過列印流接口,将PDL資料傳遞列印機列印。

下圖描述了列印子系統(XPSDrv)的工作流程,其中,淺藍色的部分是Microsoft 提供的,淺×××的部分是有軟體供應商提供的軟體和應用程式,×××的是硬體列印機供應商(比如HP)提供的部分。

Windows列印體系結構之列印驅動架構

在XPS架構下,隻有XPS一種工作模式。應用程式将不會直接調用驅動,列印的資料都會通過作業系統的XPS服務而生成一個用于列印的通用XPS檔案。再由列印假脫機隊列服務調用列印機驅動的各種過濾器修改生成的XPS檔案并最終生成列印機可以處理的檔案(可以是XPS檔案,也可以是Raw檔案),再通過端口螢幕發給列印機進行列印。而XPS驅動體系為了相容以前的系統,提供了兩條印刷路徑:一條是通過将XPS轉化為傳統的EMF檔案流,再通過傳統的GDI印刷路徑列印;而另一種列印路徑是XPS檔案通過一系列過濾器過濾,最後生成列印機能識别的PDL格式檔案。這樣既可以在新版本的作業系統環境下使用原有的列印技術,也可以在XP作業系統裡用XPS列印路徑。XPSDrv模型裡提供從 XPS到GDI格式的轉換器,用來實作Win32應用程式能夠列印XPS文檔。如果說WPF應用程式在進行寫操作的目标列印隊列沒有XPSDrv驅動程式,那麼該轉換器就會自動完成從XPS到GDI格式的轉換。

下圖分别展現了GDI驅動體系和XPS驅動體系的工作流程圖:

Windows列印體系結構之列印驅動架構

接下來我們需要看看Windows系統上都有哪些列印機的驅動。目前Windows Server 2012上擁有以下列印機驅動程式:

V4列印機驅動程式(V4 Printer Driver)

對于OpenXPS驅動程式支援

XPS列印機驅動程式(XPSDrv)

微軟通用列印機驅動程式(Microsoft UniversalPrinter Driver)

微軟PostScript列印機驅動程式(Microsoft PostScriptPrinter Driver)

微軟繪圖儀驅動程式(Microsoft PlotterDriver)

V4版本的驅動程式架構主要在WindowServer 2012和Windows 8上出現,但是現在基于這樣的列印機以及列印驅動還不是市場的主流,相信進過一段時間的推廣和發展,今後我們就看V4版本的驅動架構了。

繼續閱讀