网站首页 > 网络编程教程 > ASP.NET教程 > 用于.NET Compact Framework的强大二维图形引擎

用于.NET Compact Framework的强大二维图形引擎

  • 作者:互联网
  • 时间:2009-06-30 15:39:04

简介
  对于移动设备而言,.NET Compact Framework 即使不是最佳的 API,也是极好的 API。它的图形引擎受到很大的限制,以便提高呈现速度和降低内存消耗。但是,它似乎远远无法满足用户日益增长的对更好的图形体验的要求。尝试去获得 .NET Compact Framework 中的一些高级矢量图形呈现功能可能是一项乏味的任务。开发人员具有两个选择:

  1.求助于本机代码。例如,Pocket PC Game API 可能是一项不错的选择。它的性能令人印象深刻。有关详细信息,请参阅位于以下位置的一篇非常全面的文章:http://msdn.microsoft.com/mobility/samples/default.aspx?pull=/library/en-us/dnnetcomp/html/gmangame.asp。问题在于本机代码不支持矢量图形呈现,并且与某些设备不兼容。此外,它可能无法与 Pocket PC 仿真程序协同工作。您可以想象调试这样的程序有多么困难。

  2.请等待下一代移动图形引擎问世。据我所知,Windows CE 5 中将包含一个强大的 Direct3D Mobile引擎。这对于移动游戏开发人员来说是一个好消息,但是 Direct3D 不适合于二维图形。它太复杂了,因而无法在一般应用程序中应用。

  我们所需要的是像 GDI+ 这样强大而易于使用的二维图形引擎。因此,我从零开始开发 XrossOne GDI+ 项目。它完全是用 C# 托管代码编写的,不包含任何本机代码或不安全的代码。经过几个月的艰苦工作之后,我终于可以在本文开头提供可下载的原始版本。

开始工作
  从该项目一开始,我就一直铭记 XrossOne GDI+ 引擎应当对不同的手持设备和平台保持中立。结果,它可以与 Pocket PC、Windows CE、Smartphones、Windows .NET 和 Mono 兼容。您可以将同一个运行库复制到不同的目标,而它仍然可以正常工作。

下表概括了总体体系结构。

      层             命名空间
  XrossOne GDI+ API       Xr***One.Drawing
  基于定点的二维图形引擎    Xr***One.DrawingFP
 16.16 定点计算引擎       Xr***One.FixedPoint

  XrossOne GDI+ 中有三个层。最低层为“16.16 定点计算引擎”。其中一个主类 — MathFP — 是从 Beartronics J2ME 库 改编而来的。一些函数已经进行了优化,其中包括 sqrt、atan 和 Po***FP.Distancecalculation。在命名空间 Xr***One.FixedPoint 下面,有其他三个类:SingleFP、DoubleFP 和 MatrixFP。SingleFP 是一个用于 16.16 定点数的 Helper 类。它为在定点类型和标准类型(int、float、string)之间进行转换提供了方便。MatrixFP 是为定点二维变换编写的。因为定点计算的精度较低,所以级联变换可能会损失一些精确性。例如,在大多数情况下,两次求逆运算无法还原原始矩阵。DoubleFP 的存在是为了使该库完备,但尚未使用。

  “基于定点的二维图形引擎”是 XrossOne GDI+ 的内核。它实现了很多复杂的矢量图形算法,例如,反锯齿绘图、线帽/联接装饰、二维变换、渐变填充、Alpha 通道合成等等。这里可以找到本机 GDI+ 中的大多数高级功能。但是,您只应在少数情况下直接使用它,因为它的基于定点的接口对于程序员而言不够友好,但是不必过分担心这种情况。有一个封装良好的 API 可供使用。您可以在 Xr***One.Drawing 命名空间中找到它们。Xr***One.Drawing 中的类非常类似于 Sy***m.Drawing 中的类,不同之处在于每个类的末尾有一个字母“X”。例如,Xr***One.Drawing.PenX 类等效于 Sy***m.Drawing.Pen。有一个用于将 GDI+ 程序转换到 XrossOne GDI+ 的小窍门。在 using 节中,将 XrossOne GDI+ 类重命名为它们的等效类。例如:

using Pen = Xr***One.Drawing.PenX;
using LinearGradientBrush = Xr***One.Drawing. LinearGradientBrushX;
using Matrix = Xr***One.Drawing.MatrixX;
主要功能
反锯齿矢量图形绘图

  通过 XrossOne Mobile GDI+ 可以呈现所有种类的二维几何图形,例如,线段、矩形、多边形、椭圆、扇形、贝塞尔样条曲线、基数样条曲线等等。但是,扇形、贝塞尔样条曲线和基数样条曲线在 .NET Compact Framework 中不可用。此外,所有图形在呈现时都自动进行反锯齿处理。这有助于获得超级平滑质量。在 .NET Compact Framework 中,画笔的宽度被固定为 1 个像素。这一限制在 XrossOne GDI+ 中不存在。画笔的不同大小可以应用于所有图形的轮廓,如图 1 所示。


图 1. 反锯齿矢量图形绘图



  代码示例 1

//Clear the background and reset the transform state
gx.Clear(Co***.White);
gx***setTransform();
//Draw skew grid as the background
PenX pen = new PenX(Ut***.FromArgb(0x40, Co***.LightGray), 5);
for (int i = -Height; i < Width + Height; i+=20)
{
gx***awLine(pen, i, 0, i + Height, Height);
gx***awLine(pen, i, 0, i - Height, Height);
}

//Draw a DarkMagenta rectangle with a 10***pixel pen
Color c = Ut***.FromArgb(0x80, Co***.DarkMagenta);
pen = new PenX(c, 10.5f);
gx***awRectangle(pen, 50, 20, 150, 200);

//Fill a GreenYellow rectangle
c = Ut***.FromArgb(0xA0, Co***.GreenYellow);
BrushX brush = new SolidBrushX(c);
gx***llRectangle(brush, 120, 50, 90, 150);

//Draw a BlueViolet ellipse with a 10***pixel pen
c = Ut***.FromArgb(0x80, Co***.BlueViolet);
pen = new PenX(c, 10.5f);
gx***awEllipse(pen, 50, 20, 150, 80);

//Fill a Red ellipse
c = Ut***.FromArgb(0xA0, Co***.Red);
brush = new SolidBrushX(c);
gx***llEllipse(brush, 20, 50, 80, 150);

//Draw a HotPink pie from 156.5 degree to -280.9 degree
pe***olor = Ut***.FromArgb(0xA0, Co***.HotPink);
gx***awPie(pen, 3.6f, 120.3f, 200.8f, 130.1f, 156.5f, -280.9f);

//Draw Orange Bezier curves
c = Ut***.FromArgb(0xA0, Co***.Orange);
pen = new PenX(c, 16);
Point start = new Point(70, 100);
Point control1 = new Point(100, 10);
Point control2 = new Point(150, 50);
Point end1 = new Point(200, 200);
Point control3 = new Point(100, 150);
Point control4 = new Point(50, 200);
Point end2 = new Point(10, 150);
Point[] bezierPoints ={start, control1, control2, end1, control3, control4, end2};
pe***ndCap = Li***apX.Round;
gx***awBeziers(pen, bezierPoints);

//Refresh
Invalidate();



  XrossOne GDI+ 和本机 GDI+ 的矢量图形输出是相同的,但基数样条曲线除外。我的算法取自 Jean-Yves Queinec 撰写的文章 Smoothing Algorithm Using Bezier Curves。因此,您可能发现在它们的输出之间存在一些差异,如下面的图 2 所示。


图 2. DrawCurve/DrawClosedCurve 的输出



  尽管大多数矢量图形呈现函数都已经得到实现,但仍然有一些工作需要完成。某些函数(DrawString、DrawImage、DrawPath 等等)直到下一个版本才可用。

渐变填充

  在本机 GDI+ 中有五种画刷 — SolidBrush、LinearGradientBrush、PathGradientBrush、TextureBrush 和 HatchBrush。但是,在该版本中,只有 SolidBrush 和 LinearGradientBrush 可用。XrossOne GDI+ 支持 RadialGradientBrush 而不是 PathGradientBrush。下面的图 5 演示了渐变填充。


图 5. 渐变填充



  代码示例 4

//Clear the background and reset the transform state
gx.Clear(Co***.White);
gx***setTransform();

//Fill a rectangle with a black-white LinearGradientBrushX
Rectangle r = new Rectangle(20, 50, 300, 100);
Color c1 = Co***.Black;
Color c2 = Co***.White;
BrushX brush1 = new LinearGradientBrushX(r, c1, c2, 30F);
gx***llRectangle(brush1, r);

//Fill a rectangle with a 7-color LinearGradientBrushX
r = new Rectangle(90, 100, 150, 100);
LinearGradientBrushX br = new LinearGradientBrushX(r,Co***.Black,Co***.Black, 60F);
ColorBlendX cb = new ColorBlendX();
cb***sitions=new float[7];
int i=0;
for(float f=0;f<=1;f+=1.0f/6)
cb***sitions[i++]=f;
cb***lors=new Color[]
{Co***.Red,Co***.Orange,Co***.Yellow,Co***.Green,Co***.Blue,Co***.Indigo,Co***.Violet};
br***terpolationColors=cb;
gx***anslateTransform(160, 10);
gx***tateTransform(60F);
gx***llRectangle(br, r);

//Fill a rectangle with a 7-color RadialGradientBrushX
r.Y += 50;
RadialGradientBrushX brush2 = new RadialGradientBrushX(r, Co***.Black,Co***.Black, 220F);
br***2.InterpolationColors = cb;
gx***tateTransform(-45F);
gx***anslateTransform(-200, -170);
gx***llRectangle(brush2, r);

//Refresh
Invalidate();



Alpha 通道合成

  Sy***m.Drawing 命名空间中的 Color 结构在 .NET Framework 和 .NET Compact Framework 中都可用。区别在于 .NET Compact Framework 中禁用了 alpha 成分并且色调-饱和度-亮度 (HSB) 值不可用。幸运的是,alpha 通道合成可以完美地与 XrossOne GDI+ 协同工作(您可能已经从前面的图形示例中推断出这一点)。

性能
  手持 PC 的 CPU 的功能确实通常要比标准 PC 的 CPU 差很多。繁重的计算可能使手持设备的响应速度降低,从而可能使用户变得不胜其烦。换句话说,性能对于手持设备软件而言至关重要。因此,在重大场合下使用 XrossOne Mobile GDI+ 之前,您可能希望分析它的总体性能。因为 GDI+ 中大多数对应于 .NET Compact Framework 的等效函数都不可用,所以基准测试是针对 .NET Framework 在 XrossOne Mobile GDI+ 和 GDI+ 之间进行的。测试是在下列类别中执行的:矢量图形呈现、二维变换和渐变填充。测试方案在相同的条件下执行。您可以在下载软件包中找到基准测试程序,并且可以在 http://ww***ossone.com/projects.php?menu=4 快速查看它们的图形输出。

  XrossOne Mobile GDI+ 完全是用 C# 托管代码编写的,它的总体性能可以接受(参见下表),尽管二维变换和渐变填充需要在以后的版本中进一步优化。

方案 XrossOne Mobile GDI+ GDI+ for .NET Framework 系统开销

DrawLine

2.604 ms

0.901 ms

189.0%

DrawRect

3.705 ms

1.602 ms

131.3%

DrawPolygon

3.205 ms

1.502 ms

113.4%

DrawEllipse

6.409 ms

2.403 ms

166.7%

DrawBezier

3.505 ms

1.602 ms

118.8%

DrawCurve

4.006 ms

1.402 ms

185.7%

DrawPie

6.810 ms

2.003 ms

240.0%

TranslateTransform

10.615 ms

3.405 ms

211.7%

ScaleTransform

4.106 ms

0.801 ms

412.6%

RotateTransform

7.811 ms

1.803 ms

333.2%

LinearGradient (1)

9.013 ms

2.103 ms

328.6%

LinearGradient (2)

8.012 ms

1.803 ms

344.4%


缺少的功能
  在上述部分中,我们已经演示了 XrossOne Mobile GDI+ 的一些令人兴奋的功能。但是,该版本中仍然缺少一些功能:

  • 文本输出

  • 光栅输出

  • 虚线样式支持

  • HatchBrush、PathGradiantBrush、TextureBrush

  • Pe***ustomStartCapPe***ustomEndCap

小结
  我们相信 XrossOne Mobile GDI+ 可以帮助 .NET Compact Framework 开发人员创建更加引人注目的图形接口。考虑到它的小内存足迹 (72kb),它的功能已经相当丰富了。而且,它的性能对于一般应用程序而言已经足够了。此外,多亏它的纯粹托管代码设计,XrossOne GDI+ 是一个跨平台、跨设备的二维图形引擎。