可打印页的大小和分辨率 彩色调色板和灰度比例信息 字体和文本性能 过渡调色支持 样式步号 驱动程序只填充它支持的域而忽略其余部分。 驱动程序用标志在 GDIINFO结构中填充,描述这个PDEV的图形性能。在几乎所有的 情况下, GDIINFO的信息告诉GDⅠ驱动程序能提供的图形支持的级别。例如,如果需要绘制 个三角记号, GDIINFO中的信息告诉GDⅠ是否驱动程序能处理贝塞尔曲线或者是否GDI必 须发送多条直线线段。驱动程序要填充它支持的所有域,而不涉及其他的域。 驱动程序必须提供的另一条重要的信息是一个指针( phsurfpatterns),指向用表面 的句柄填充的缓冲区,表示标准的填充模式。除了标准的填充模式以外, phsurfpatterns 能包括空(nul1),这将导致GDI根据设备分辨率和像素大小自动创建模式表面。当GDI被 调用,用标准模式实现一个画刷,它调用 Dry Realizebrush函数实现为请求的模式定义的画 GDI为支持设备的核心驱动程序传递给 Dry Enablepdev一个句柄, dRiver。对于一个 打印机驱动程序, dRiver提供句柄给打印机并在假脱机的调用中使用,如 EngWritePrintero 无论何时GDI调用 Dry Enablepdev,驱动程序必须分配存储器,用以支持创建的PDEV, 即使调用 Dry Enablepdev用来为不同的模式创建其他的PDEV。(一个驱动程序可能有几个激 活的PDEV,虽然在一个时刻只有一个能被启用。)然而,直到GDI调用 Dry EnableSurface, 不支持一个实际的表面。 如果设备表面请求位图的分配,直到表面启用为止分配是不必要的(通常在 Dry Enablesurface函数中)。虽然在实际写到设备之前应用常请求设备信息,等待分配一个 大的位图能保存有价值的资源,并在系统初始化时改进驱动程序的性能 DEV的初始化完成时,GDⅠ调用 DrvCompletePDEV函数通知驱动程序物理设备的安装 已经完成。这个函数也给驱动程序提供到PDEV的GDI的逻辑句柄,驱动程序在调用GDI函 数中使用。 对驱动程序的 DryDisablepdel函数的调用指示给定的物理设备不再需要。在这个函 数中,驱动程序要释放物理设备使用的所有存储器和资源。 3.2.3启用和禁止表面 在初始化阶段的最后,GDI调用 DryEnablesurface使驱动程序为一个存在的PDEV启 用一个表面。 DryEnablesurface必须通过调用相应的GDI服务指定表面的类型来创建它。 就像第2章ωDⅠ对表面的支持中描述的,以及依据设备和环境,驱动程序能从 Dry Enablesurface中调用合适的GDI服务创建表面 对设备管理的表面,驱动程序调用 EngCreateDeviceSurface函数得到表面的句柄 为创建一个GDI能完全管理的标准格式(DIB)位图,包括所有绘图操作的性能,驱 动程序要调用巸 nfCreateBi tmap函数。驱动程序能钩住它能优化的所有的绘图操作。驱动程 序也能使GDⅠ为每个像素分配空间或为自身提供空间,虽然后一个选项通常只由打印机或帧 缓冲区使用。 DryEnablesurface返回一个有效的表面句柄作为返回值
21 ▪ 可打印页的大小和分辨率 ▪ 彩色调色板和灰度比例信息 ▪ 字体和文本性能 ▪ 过渡调色支持 ▪ 样式步号 驱动程序只填充它支持的域而忽略其余部分。 驱动程序用标志在 GDIINFO 结构中填充,描述这个 PDEV 的图形性能。在几乎所有的 情况下,GDIINFO 的信息告诉 GDI 驱动程序能提供的图形支持的级别。例如,如果需要绘制 一个三角记号,GDIINFO 中的信息告诉 GDI 是否驱动程序能处理贝塞尔曲线或者是否 GDI 必 须发送多条直线线段。驱动程序要填充它支持的所有域,而不涉及其他的域。 驱动程序必须提供的另一条重要的信息是一个指针(phsurfPatterns),指向用表面 的句柄填充的缓冲区,表示标准的填充模式。除了标准的填充模式以外,phsurfPatterns 能包括空(null),这将导致 GDI 根据设备分辨率和像素大小自动创建模式表面。当 GDI 被 调用,用标准模式实现一个画刷,它调用 DrvRealizeBrush 函数实现为请求的模式定义的画 刷。 GDI 为支持设备的核心驱动程序传递给 DrvEnablePDEV 一个句柄,hDriver。对于一个 打印机驱动程序, hDriver 提 供 句 柄 给 打 印 机 并 在 假 脱 机 的 调 用 中 使 用 , 如 EngWritePrinter。 无论何时 GDI 调用 DrvEnablePDEV,驱动程序必须分配存储器,用以支持创建的 PDEV, 即使调用 DrvEnablePDEV 用来为不同的模式创建其他的 PDEV。(一个驱动程序可能有几个激 活的 PDEV,虽然在一个时刻只有一个能被启用。)然而,直到 GDI 调用 DrvEnableSurface, 不支持一个实际的表面。 如果设备表面请求位图的分配,直到表面启用为止分配是不必要的(通常在 DrvEnableSurface 函数中)。虽然在实际写到设备之前应用常请求设备信息,等待分配一个 大的位图能保存有价值的资源,并在系统初始化时改进驱动程序的性能。 PDEV 的初始化完成时,GDI 调用 DrvCompletePDEV 函数通知驱动程序物理设备的安装 已经完成。这个函数也给驱动程序提供到 PDEV 的 GDI 的逻辑句柄,驱动程序在调用 GDI 函 数中使用。 对驱动程序的 DrvDisablePDEV 函数的调用指示给定的物理设备不再需要。在这个函 数中,驱动程序要释放物理设备使用的所有存储器和资源。 3.2.3 启用和禁止表面 在初始化阶段的最后,GDI 调用 DrvEnableSurface 使驱动程序为一个存在的 PDEV 启 用一个表面。DrvEnableSurface 必须通过调用相应的 GDI 服务指定表面的类型来创建它。 就像第 2 章 GDI 对表面的支持中描述的,以及依据设备和环境,驱动程序能从 DrvEnableSurface 中调用合适的 GDI 服务创建表面: 对设备管理的表面,驱动程序调用 EngCreateDeviceSurface 函数得到表面的句柄。 为创建一个 GDI 能完全管理的标准格式(DIB)位图,包括所有绘图操作的性能,驱 动程序要调用 EnfCreateBitmap 函数。驱动程序能钩住它能优化的所有的绘图操作。驱动程 序也能使 GDI 为每个像素分配空间或为自身提供空间,虽然后一个选项通常只由打印机或帧 缓冲区使用。 DrvEnableSurface 返回一个有效的表面句柄作为返回值
随着表面的创建,驱动程序必须通过调用GDI的 EngAssociateSurface服务使表面与 一个PDEV相关。这个调用也告诉GDI驱动程序为表面挂上了哪个绘图函数。 GDI调用 DryDisablesurface函数通知驱动程序不再请求由 Dry Enablesurface为PDEV 创建的当前的表面。驱动程序必须释放在执行 Drv Enablesurface期间分配的所有的存储器 和资源。如果PDEV有一个启用的表面, Drydisablesurface总是在 Dry sablepdev之前调 用 表面一旦创建,当它不再使用时必须删除。不能正确匹配表面创建的删除将导致无用 对象的累积并使系统性能下降 3.3创建设备相关位图 当应用请求位图的创建,驱动程序通过支持 DrvCreateDeviceBitmap函数能创建和管 理DB。当这样一个驱动程序创建了位图,它能用任何格式存储位图。驱动程序检查传递的 参数,并用至少是请求的每个像素的位数提供位图。 注意图形驱动程序通过在屏幕外的存储器支持位图和使用硬件绘制位图能提高性 能。这方面的一个例子是 Permedia显示器驱动程序的例子 在 DrvCreateDeviceBitmap中,驱动程序调用GDI的 EngCreateDeviceBi tmap服务使 GDI为设备位图创建一个句柄 如果驱动程序支持 DrvCreateDeviceBi tmap,它创建一个DDB,定义其格式,并返回 个它的句柄。驱动程序控制位图用什么格式在哪里存储。驱动程序要支持最接近匹配其设 备表面的颜色格式 位图的内容在创建之后不能定义。如果驱动程序返回NULL,它不能创建和管理位图 而由GDI替代执行这些任务。 如果驱动程序创建了位图,也必须能通过执行 DrvDeleteDeviceBitmap函数删除它 3.4支持图形输出 驱动程序处理的特殊图形操作依赖于绘图表面和硬件的能力。如果表面是一个标准格 式的DIB,GDⅠ处理所有驱动程序不支持的绘图操作。驱动程序能hook任意的绘图函数并实 现它们,得到硬件支持的优势 对于设备管理的表面,驱动程序最少必须支持图形输出函数 DrvCopyBits、 DrvTextOut 和 DryStrokepath。它也能可选支持任何其他的图形输出函数,例如支持 DryBitblt,能提 高性能。有些函数要求确定的能力级别,而其他的允许设备通过在 DEVINFO结构中设置相应 的 GCAPS标志指示其性能。 对驱动程序的所有的绘图调用都是单线程的,而不关心表面的类型。 下面的部分描述驱动程序如何实现下列操作 绘制直线和曲线 绘制和填充路径 拷贝位图 过渡调色技术 图象颜色管理
22 随着表面的创建,驱动程序必须通过调用 GDI 的 EngAssociateSurface 服务使表面与 一个 PDEV 相关。这个调用也告诉 GDI 驱动程序为表面挂上了哪个绘图函数。 GDI调用DrvDisableSurface函数通知驱动程序不再请求由DrvEnableSurface为PDEV 创建的当前的表面。驱动程序必须释放在执行 DrvEnableSurface 期间分配的所有的存储器 和资源。如果 PDEV 有一个启用的表面,DrvDisableSurface 总是在 DrvDisablePDEV 之前调 用。 表面一旦创建,当它不再使用时必须删除。不能正确匹配表面创建的删除将导致无用 对象的累积并使系统性能下降。 3.3 创建设备相关位图 当应用请求位图的创建,驱动程序通过支持 DrvCreateDeviceBitmap 函数能创建和管 理 DDB。当这样一个驱动程序创建了位图,它能用任何格式存储位图。驱动程序检查传递的 参数,并用至少是请求的每个像素的位数提供位图。 注意 图形驱动程序通过在屏幕外的存储器支持位图和使用硬件绘制位图能提高性 能。这方面的一个例子是 Permedia 显示器驱动程序的例子。 在 DrvCreateDeviceBitmap 中,驱动程序调用 GDI 的 EngCreateDeviceBitmap 服务使 GDI 为设备位图创建一个句柄。 如果驱动程序支持 DrvCreateDeviceBitmap,它创建一个 DDB,定义其格式,并返回 一个它的句柄。驱动程序控制位图用什么格式在哪里存储。驱动程序要支持最接近匹配其设 备表面的颜色格式。 位图的内容在创建之后不能定义。如果驱动程序返回 NULL,它不能创建和管理位图; 而由 GDI 替代执行这些任务。 如果驱动程序创建了位图,也必须能通过执行 DrvDeleteDeviceBitmap 函数删除它。 3.4 支持图形输出 驱动程序处理的特殊图形操作依赖于绘图表面和硬件的能力。如果表面是一个标准格 式的 DIB,GDI 处理所有驱动程序不支持的绘图操作。驱动程序能 hook 任意的绘图函数并实 现它们,得到硬件支持的优势。 对于设备管理的表面,驱动程序最少必须支持图形输出函数 DrvCopyBits、DrvTextOut 和 DrvStrokePath。它也能可选支持任何其他的图形输出函数,例如支持 DrvBitBlt,能提 高性能。有些函数要求确定的能力级别,而其他的允许设备通过在 DEVINFO 结构中设置相应 的 GCAPS 标志指示其性能。 对驱动程序的所有的绘图调用都是单线程的,而不关心表面的类型。 下面的部分描述驱动程序如何实现下列操作: ▪ 绘制直线和曲线 ▪ 绘制和填充路径 ▪ 拷贝位图 ▪ 过渡调色技术 ▪ 图象颜色管理
3.4.1绘制直线和曲线 包括在图象输出中的直线和曲线类型是几何直线、装饰直线和贝塞尔曲线 对于直线和曲线输出,驱动程序能支持 DryStrokepath、 DryFillPath和 DryStrokeAndfillpath函数。如果表面是设备管理的,驱动程序必须支持 DryStrokepath 绘制直线:驱动程序不要求支持曲线 当GDI用任意的属性集绘制直线或曲线,GDI调用 Dry Strokepath。至少 Dry Strokepath函数必须支持用实色画刷和任意的裁剪绘制实线和样式装饰线。为实现这一 点,GDI的 PATHOBJ Xxx和 CLIPOBJ XxX服务函数通过预先计算的裁剪把这些直线分割成 个像素宽的线段的集合。 DryStrokePath提供一个指针, plineattrs,指向定义不同直线属 性的 LINEATTRS结构。 当路径或裁剪对于驱动程序在设备上的过程过于复杂,驱动程序能通过调用 EngStrokePath函数把回调函数punt到GDI。对这种情况,GDI能把对 DryStrokepath的调 用分割成用预先计算的裁剪得到的一个像素宽的线段的集合。 通过调用GDI的 CLIPOBJ XxX服务,驱动程序能使GD计算在路径中的所有的直线, 并执行所有的直线裁剪计算。另外,驱动程序可以使用 PATHOBJ Xxx、 CLIPOBJ Xxx或 XFORMOBJ XxX服务简化图形操作。例如,驱动程序能使用 CLIPOBJ cEnumStart和 CLIPOBJ eNum计算在一个裁剪区域内的矩形,发送这个区域到打印机,以及裁剪它。驱动 程序也能使用 PATHOBJ cEnumStart和 PATHOBJ eNum计算路径中的直线或曲线。然后它能 把路径发送到设备并绘制它 3.4.1.1装饰线 装饰线通常是一个像素宽并使用实色画刷绘制。它按照网格交叉点量化(GIQ)菱形 约定绘制,这种方法确定装饰线上哪个像素要被绘制 图3.1显示了一条直线置于一个矩形网格上,像素定位在网格交叉点上。为确定哪个 像素将被点亮,想象一个菱形在直线中间并沿直线滑动。菱形的宽度和高度恰好等于两个相 邻像素中心的距离。当菱形沿着直线移动,中心完全被菱形覆盖的像素被选中。如果直线穿 过的一个点在两个相邻像素的中间,被点亮的像素取决直线的斜度和相邻像素的走向:水平 的或是垂直的。 下表概括了这些情况。 直线的斜率(绝对值)相邻像素的走向 斜率<1或斜率》1 水平的 点亮菱形左顶点的像素 斜率<1或斜率》1 垂直的 点亮菱形上顶点的像素 斜率=1 水平的 点亮菱形上顶点的像素 斜率=1 垂直的 亮菱形右顶点的像素 菱形协议使斜率在-1和1之间的直线上每一列有一个像素点亮,使斜率的绝对值比 大的直线上每一行里有一个像素点亮。用这种方式,装饰线能没有间隙地绘制 装饰线的首尾像素也由菱形协议确定。装饰线是首像素包含而末像素不包含的:即如果 直线起始于菱形内的一个像素,这个像素变亮。类似地,如果直线结束于菱形内的一个像素 这个像素不变亮,如图3.1显示
23 3.4.1 绘制直线和曲线 包括在图象输出中的直线和曲线类型是几何直线、装饰直线和贝塞尔曲线。 对 于 直 线 和 曲 线 输 出 , 驱 动 程 序 能 支 持 DrvStrokePath 、 DrvFillPath 和 DrvStrokeAndFillPath 函数。如果表面是设备管理的,驱动程序必须支持 DrvStrokePath 绘制直线;驱动程序不要求支持曲线。 当 GDI 用任意的属性集绘制直线或曲线,GDI 调用 DrvStrokePath。至少, DrvStrokePath 函数必须支持用实色画刷和任意的裁剪绘制实线和样式装饰线。为实现这一 点,GDI 的 PATHOBJ_Xxx 和 CLIPOBJ_Xxx 服务函数通过预先计算的裁剪把这些直线分割成一 个像素宽的线段的集合。DrvStrokePath 提供一个指针,plineattrs,指向定义不同直线属 性的 LINEATTRS 结构。 当路径或裁剪对于驱动程序在设备上的过程过于复杂,驱动程序能通过调用 EngStrokePath 函数把回调函数 punt 到 GDI。对这种情况,GDI 能把对 DrvStrokePath 的调 用分割成用预先计算的裁剪得到的一个像素宽的线段的集合。 通过调用 GDI 的 CLIPOBJ_Xxx 服务,驱动程序能使 GDI 计算在路径中的所有的直线, 并执行所有的直线裁剪计算。另外,驱动程序可以使用 PATHOBJ_Xxx、CLIPOBJ_Xxx 或 XFORMOBJ_Xxx 服务简化图形操作。例如,驱动程序能使用 CLIPOBJ_cEnumStart 和 CLIPOBJ_cEnum 计算在一个裁剪区域内的矩形,发送这个区域到打印机,以及裁剪它。驱动 程序也能使用 PATHOBJ_cEnumStart 和 PATHOBJ_cEnum 计算路径中的直线或曲线。然后它能 把路径发送到设备并绘制它。 3.4.1.1 装饰线 装饰线通常是一个像素宽并使用实色画刷绘制。它按照网格交叉点量化(GIQ)菱形 约定绘制,这种方法确定装饰线上哪个像素要被绘制。 图 3.1 显示了一条直线置于一个矩形网格上,像素定位在网格交叉点上。为确定哪个 像素将被点亮,想象一个菱形在直线中间并沿直线滑动。菱形的宽度和高度恰好等于两个相 邻像素中心的距离。当菱形沿着直线移动,中心完全被菱形覆盖的像素被选中。如果直线穿 过的一个点在两个相邻像素的中间,被点亮的像素取决直线的斜度和相邻像素的走向:水平 的或是垂直的。 下表概括了这些情况。 直线的斜率(绝对值) 相邻像素的走向 结果 斜率<1 或斜率>1 水平的 点亮菱形左顶点的像素 斜率<1 或斜率>1 垂直的 点亮菱形上顶点的像素 斜率=1 水平的 点亮菱形上顶点的像素 斜率=1 垂直的 点亮菱形右顶点的像素 菱形协议使斜率在-1 和 1 之间的直线上每一列有一个像素点亮,使斜率的绝对值比 1 大的直线上每一行里有一个像素点亮。用这种方式,装饰线能没有间隙地绘制。 装饰线的首尾像素也由菱形协议确定。装饰线是首像素包含而末像素不包含的;即如果 直线起始于菱形内的一个像素,这个像素变亮。类似地,如果直线结束于菱形内的一个像素, 这个像素不变亮,如图 3.1 显示
图3.1装饰线的菱形协议 为了着色装饰线, DryStrokePath函数遵循GIQ菱形协议。 Drvlineto函数是一个可 选入口点,驱动程序能够为应用调用 Microsoft③Win32 Lineto函数提供优化。 Drvlineto 比 Drv StrokePath简单,因为它仅支持整数端点和实心装饰线 对于支持R2NoT混合模式的光栅设备,二进制光栅操作改变目标颜色为相反色,驱 动程序必须使用精确的着色。对于要求GDI和驱动程序两者绘图的设备,着色也必须是精确 的。这包括GD在一些位图上绘图的设备以及驱动程序在其他表面上绘图的设备(除非像素 太小不能产生可视的差异)。这也包括请求GDⅠI处理复杂裁剪的设备。 3.4.1.2几何宽度直线( Geometric wide line) 几何直线的形状是由宽度、连接类型、画刷端点类型以及在 XFORMOBJ结构里当前区 域至设备转换来确定的。能够使用实心的或非实心的画刷绘制直线 更高级的硬件设备驱动程序可以支持 DryStrokepath函数中的几何宽度直线。在调用 Dry Enablepdev返回的 DEVINFO结构里测试 GCAPS GEOMETRICWIDE性能标志位,GDI确定驱 动程序是否能够绘制包括几何直线的路径。如果驱动程序没有这个能力,或者因为路径或裁 剪对设备过于复杂,而使函数处理此操作失败,GDI自动转换调用较简单的 DryfillPath函 几何宽度直线对显示器驱动程序图形函数有特殊的含义。包含设备坐标的路径使用当 前转换的逆转换变成世界坐标。具有指定宽度的几何结构获得加宽的路径,考虑连接和端点。 这个路径又转换成设备坐标并用指定的画刷填充 几何宽度直线的线型是由浮点数数组确定的。数组是定长的,但好象能无限重复使用。 在世界坐标里,第一个数组条目指定第一个短线的长度;下一个条目指定第一个间隙的长度。 在这以后,短线和间隙的长度交替。例如,线型数组{3.0,1.0,1.0,1.0}可绘制长短线交替 的直线 当驱动程序沿着加宽前的路径移动,可以考虑线型,“擦除”路径对应于间隙的部分。 这将路径分割成许多子路径。然后分割开的路径被加宽,就像它没有线型,照常应用端点盖 住和连接。线型数组可以是不定长的。例如,线型数组{1,0}使驱动程序用交替的短线绘制 条直线。线型状态(定义当前的距离到线型数组)在路径中第一个子路径的开头提供。在 每个后来的子路径的开始考虑重置为0.0,这在任何Win32 MoveToEx操作后出现。 3.4.1.3花式装饰直线( Sty led Cosmetic Line) DryStrokepath函数必须支持用实色画刷绘制的带任意裁剪的装饰线。驱动程序能够进 行一个到GDI的 PATHOBJ vEnumStartCliplines的调用来预先计算裁剪 装饰线的线型类似于几何宽度直线,因为它由一个重复的数组指定。对于一条造型的装 饰线,数组条目是LONG类型的值,包含类型步的长度。类型步和像素的关系由 Dry Enablepdev 函数返回的 GDIINFO结构的 xStylestep、 yStylestep和 DenStylestep字段定义。 当驱动程序通过复杂的裁剪调用 PATHOBJ vEnumStartCliplines处理装饰线,GDI修改
24 图 3.1 装饰线的菱形协议 为了着色装饰线,DrvStrokePath 函数遵循 GIQ 菱形协议。DrvLineTo 函数是一个可 选入口点,驱动程序能够为应用调用 Microsoft® Win32 LineTo 函数提供优化。DrvLineTo 比 DrvStrokePath 简单,因为它仅支持整数端点和实心装饰线。 对于支持 R2_NOT 混合模式的光栅设备,二进制光栅操作改变目标颜色为相反色,驱 动程序必须使用精确的着色。对于要求 GDI 和驱动程序两者绘图的设备,着色也必须是精确 的。这包括 GDI 在一些位图上绘图的设备以及驱动程序在其他表面上绘图的设备(除非像素 太小不能产生可视的差异)。这也包括请求 GDI 处理复杂裁剪的设备。 3.4.1.2 几何宽度直线(Geometric Wide Line) 几何直线的形状是由宽度、连接类型、画刷端点类型以及在 XFORMOBJ 结构里当前区 域至设备转换来确定的。能够使用实心的或非实心的画刷绘制直线。 更高级的硬件设备驱动程序可以支持 DrvStrokePath 函数中的几何宽度直线。在调用 DrvEnablePDEV 返回的 DEVINFO 结构里测试 GCAPS_GEOMETRICWIDE 性能标志位,GDI 确定驱 动程序是否能够绘制包括几何直线的路径。如果驱动程序没有这个能力,或者因为路径或裁 剪对设备过于复杂,而使函数处理此操作失败,GDI 自动转换调用较简单的 DrvFillPath 函 数。 几何宽度直线对显示器驱动程序图形函数有特殊的含义。包含设备坐标的路径使用当 前转换的逆转换变成世界坐标。具有指定宽度的几何结构获得加宽的路径,考虑连接和端点。 这个路径又转换成设备坐标并用指定的画刷填充。 几何宽度直线的线型是由浮点数数组确定的。数组是定长的,但好象能无限重复使用。 在世界坐标里,第一个数组条目指定第一个短线的长度;下一个条目指定第一个间隙的长度。 在这以后,短线和间隙的长度交替。例如,线型数组3.0,1.0,1.0,1.0可绘制长短线交替 的直线。 当驱动程序沿着加宽前的路径移动,可以考虑线型,“擦除”路径对应于间隙的部分。 这将路径分割成许多子路径。然后分割开的路径被加宽,就像它没有线型,照常应用端点盖 住和连接。线型数组可以是不定长的。例如,线型数组{1,0}使驱动程序用交替的短线绘制 一条直线。线型状态(定义当前的距离到线型数组)在路径中第一个子路径的开头提供。在 每个后来的子路径的开始考虑重置为 0.0,这在任何 Win32 MoveToEx 操作后出现。 3.4.1.3 花式装饰直线(Styled Cosmetic Line) DrvStrokePath 函数必须支持用实色画刷绘制的带任意裁剪的装饰线。驱动程序能够进 行一个到 GDI 的 PATHOBJ_vEnumStartClipLines 的调用来预先计算裁剪。 装饰线的线型类似于几何宽度直线,因为它由一个重复的数组指定。对于一条造型的装 饰线,数组条目是 LONG 类型的值,包含类型步的长度。类型步和像素的关系由 DrvEnablePDEV 函数返回的 GDIINFO 结构的 xStyleStep、yStyleStep 和 DenStyleStep 字段定义。 当驱动程序通过复杂的裁剪调用 PATHOBJ_vEnumStartClipLines 处理装饰线,GDI 修改
CLIPLINE结构的 iStylestate成员来表示线型状态。线型状态是回到线段的第一个像素的 偏移,即如果直线没有被裁剪,将绘制第一个像素。线型状态由压缩到一个 ULONG值中的两 个16位值组成。如果HGH和LoW是线型状态的高序(high- order)和低序( low-order) 的16位值,线型状态的分数版,称作线型位置,可计算为: style position HIGH LOW/denStyleStep 例如,如果在 iStylestate中的值是1和2, denStylestep是3, style position是5/3 为精确确定在线型数组中线型从哪里开始绘制,计算乘积 style position denStylestep 在这个例子中, denStylestep的值是3,绘图位置计算不包括线型数组的前5个像素 (5/3*3)。即这条裁剪线从线型数组中的第6个像素开始绘制。 有y线型的装饰线和x线型的装饰线。如果一条线在x方向扩展dx个设备单元,在y 方向扩展dy个设备单元,当下列条件为真直线是y型的: (dy k yStyleStep)>(dx xStyleStep) 在这种情况下,对每个像素在y方向的前进,线型位置的前进由 yStylestep/ den Stylestep计算 反过来,直线是x线型的,当下式为真时,对每个像素在x方向的前进,线型位置的前 进由 xStylestep/ denStylestep计算 (dx s yStylestep)>(dy xStyleStep) 当线型位置前进到一个新的整数时,在线型数组中线型步前进一个单元。 图3.2显示不同斜率的几条装饰线。像素网格显示不是方的:它就像在EGA显示器中显 示的那样,在x方向的4个像素与y方向的3个像素表示相同的距离。在这个图示中,线型 数组(由 LINEATTRS结构的 style成员定义)是{1,1},它把直线分割成相等大小的点和 间隙。驱动程序的 x Stylestep的值是3, yStylestep的值是4, denStylestep是12 为进一步说明,假设一个点阵打印机有144dpi的水平分辨率和72dpi的垂直分辨率 另外,假设最小点的长度是1/24英寸。为支持这个打印机,要选择能补偿打印机的方式比 的最小的 xStylestep和 yStylestep值,如 xStylestep为1, yStylestep为2(144/72), denStyleStep *6(144/24) 图3.2花式装饰线的例子 如果 LINEATTRS结构里标志的 LA ALTERNATE位置1,装饰线使用了指定的线型。在这种 情况下,其他每个像素都选中,而不管方向或方式比。线型状态返回,好像线型数组是{1, l}, x Stylestep、 yStylestep和 denStylestep都是一个。换句话说,如果 Istylestate是 0,第一个像素点亮; Istylestate是1,第一个像素不亮。 如果 LINEATTRS结构里标志的 LA STAARTGAP位置1,在线型数组里元素的检测是相反的 第一个数组条目指定第一个间隙的长度,第二个条目指定第一个短线的长度,如此下去 3.4.1.4贝塞尔曲线 些高级硬件设备能够绘制包含贝塞尔曲线的路径,是一般作用的曲线图元。如果这样, 在 DryStrokePath函数中驱动程序包含对这些曲线的支持 当GDⅠI必须在设备管理的表面绘制贝塞尔曲线路径,它测试 GCAPS BEZIERS标志(在 DEVINFO结构中)确定是否调用 DryStrokePath。如果调用,这个函数执行执行请求操作或
25 CLIPLINE 结构的 iStyleState 成员来表示线型状态。线型状态是回到线段的第一个像素的 偏移,即如果直线没有被裁剪,将绘制第一个像素。线型状态由压缩到一个 ULONG 值中的两 个 16 位值组成。如果 HIGH 和 LOW 是线型状态的高序(high-order)和低序(low-order) 的 16 位值,线型状态的分数版,称作线型位置,可计算为: style position = HIGH + LOW/denStyleStep 例如,如果在 iStyleState 中的值是 1 和 2,denStyleStep 是 3,style position 是 5/3。 为精确确定在线型数组中线型从哪里开始绘制,计算乘积: style position * denStyleStep 在这个例子中,denStyleStep 的值是 3,绘图位置计算不包括线型数组的前 5 个像素 (5/3*3)。即这条裁剪线从线型数组中的第 6 个像素开始绘制。 有 y 线型的装饰线和 x 线型的装饰线。如果一条线在 x 方向扩展 dx 个设备单元,在 y 方向扩展 dy 个设备单元,当下列条件为真直线是 y 型的: (dy * yStyleStep) ≥ (dx * xStyleStep) 在这种情况下,对每个像素在 y 方向的前进,线型位置的前进由 yStyleStep/ denStyleStep 计算。 反过来,直线是 x 线型的,当下式为真时,对每个像素在 x 方向的前进,线型位置的前 进由 xStyleStep/ denStyleStep 计算: (dx * yStyleStep) > (dy * xStyleStep) 当线型位置前进到一个新的整数时,在线型数组中线型步前进一个单元。 图 3.2 显示不同斜率的几条装饰线。像素网格显示不是方的;它就像在 EGA 显示器中显 示的那样,在 x 方向的 4 个像素与 y 方向的 3 个像素表示相同的距离。在这个图示中,线型 数组(由 LINEATTRS 结构的 pstyle 成员定义)是{1,1},它把直线分割成相等大小的点和 间隙。驱动程序的 xStyleStep 的值是 3,yStyleStep 的值是 4,denStyleStep 是 12。 为进一步说明,假设一个点阵打印机有 144dpi 的水平分辨率和 72 dpi 的垂直分辨率。 另外,假设最小点的长度是 1/24 英寸。为支持这个打印机,要选择能补偿打印机的方式比 的最小的 xStyleStep 和 yStyleStep 值,如 xStyleStep 为 1,yStyleStep 为 2(144/72), denStyleStep 为 6(144/24)。 图 3.2 花式装饰线的例子 如果 LINEATTRS 结构里标志的 LA_ALTERNATE 位置 1,装饰线使用了指定的线型。在这种 情况下,其他每个像素都选中,而不管方向或方式比。线型状态返回,好像线型数组是{1, 1},xStyleStep、yStyleStep 和 denStyleStep 都是一个。换句话说,如果 IstyleState 是 0,第一个像素点亮;IstyleState 是 1,第一个像素不亮。 如果LINEATTRS结构里标志的LA_STAARTGAP位置1,在线型数组里元素的检测是相反的。 第一个数组条目指定第一个间隙的长度,第二个条目指定第一个短线的长度,如此下去。 3.4.1.4 贝塞尔曲线 一些高级硬件设备能够绘制包含贝塞尔曲线的路径,是一般作用的曲线图元。如果这样, 在 DrvStrokePath 函数中驱动程序包含对这些曲线的支持。 当 GDI 必须在设备管理的表面绘制贝塞尔曲线路径,它测试 GCAPS_BEZIERS 标志(在 DEVINFO 结构中)确定是否调用 DrvStrokePath。如果调用,这个函数执行执行请求操作或