簡介對於行動裝置而言,.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 XrossOne.Drawing
基於定點的二維圖形引擎XrossOne.DrawingFP
16.16 定點計算引擎XrossOne.FixedPoint
XrossOne GDI+ 中有三個層。最低層為「16.16 定點計算引擎」。其中一個主類— MathFP — 是從Beartronics J2ME 庫改編而來的。一些函數已經進行了最佳化,其中包括sqrt、atan 和PointFP.Distancecalculation。在命名空間XrossOne.FixedPoint 下面,還有其他三個類別:SingleFP、DoubleFP 和MatrixFP。 SingleFP 是一個用於16.16 定點數的Helper 類別。它為在定點類型和標準類型(int、float、string)之間進行轉換提供了方便。 MatrixFP 是為定點二維變換編寫的。因為定點計算的精度較低,所以級聯變換可能會損失一些精確性。例如,在大多數情況下,兩次求逆運算無法還原原始矩陣。 DoubleFP 的存在是為了讓該函式庫完備,但尚未使用。
「基於定點的二維圖形引擎」是XrossOne GDI+ 的核心。它實現了許多複雜的向量圖形演算法,例如,反鋸齒繪圖、線帽/聯接裝飾、二維變換、漸變填充、Alpha 通道合成等等。這裡可以找到本機GDI+ 中的大多數進階功能。但是,您只應在少數情況下直接使用它,因為它的基於定點的介面對於程式設計師而言不夠友好,但是不必過分擔心這種情況。有一個封裝良好的API 可供使用。您可以在XrossOne.Drawing 命名空間中找到它們。 XrossOne.Drawing 中的類別非常類似於System.Drawing 中的類,不同之處在於每個類別的末尾都有一個字母「X」。例如,XrossOne.Drawing.PenX 類別等效於System.Drawing.Pen。有一個用於將GDI+ 程式轉換到XrossOne GDI+ 的小技巧。在using 節中,將XrossOne GDI+ 類別重新命名為它們的等效類別。例如:
using Pen = XrossOne.Drawing.PenX;
using LinearGradientBrush = XrossOne.Drawing. LinearGradientBrushX;
using Matrix = XrossOne.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(Color.White);
gx.ResetTransform();
//Draw skew grid as the background
PenX pen = new PenX(Utils.FromArgb(0x40, Color.LightGray), 5);
for (int i = -Height; i < Width + Height; i+=20)
{
gx.DrawLine(pen, i, 0, i + Height, Height);
gx.DrawLine(pen, i, 0, i - Height, Height);
}
//Draw a DarkMagenta rectangle with a 10.5-pixel pen
Color c = Utils.FromArgb(0x80, Color.DarkMagenta);
pen = new PenX(c, 10.5f);
gx.DrawRectangle(pen, 50, 20, 150, 200);
//Fill a GreenYellow rectangle
c = Utils.FromArgb(0xA0, Color.GreenYellow);
BrushX brush = new SolidBrushX(c);
gx.FillRectangle(brush, 120, 50, 90, 150);
//Draw a BlueViolet ellipse with a 10.5-pixel pen
c = Utils.FromArgb(0x80, Color.BlueViolet);
pen = new PenX(c, 10.5f);
gx.DrawEllipse(pen, 50, 20, 150, 80);
//Fill a Red ellipse
c = Utils.FromArgb(0xA0, Color.Red);
brush = new SolidBrushX(c);
gx.FillEllipse(brush, 20, 50, 80, 150);
//Draw a HotPink pie from 156.5 degree to -280.9 degree
pen.Color = Utils.FromArgb(0xA0, Color.HotPink);
gx.DrawPie(pen, 3.6f, 120.3f, 200.8f, 130.1f, 156.5f, -280.9f);
//Draw Orange Bezier curves
c = Utils.FromArgb(0xA0, Color.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};
pen.EndCap = LineCapX.Round;
gx.DrawBeziers(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(Color.White);
gx.ResetTransform();
//Fill a rectangle with a black-white LinearGradientBrushX
Rectangle r = new Rectangle(20, 50, 300, 100);
Color c1 = Color.Black;
Color c2 = Color.White;
BrushX brush1 = new LinearGradientBrushX(r, c1, c2, 30F);
gx.FillRectangle(brush1, r);
//Fill a rectangle with a 7-color LinearGradientBrushX
r = new Rectangle(90, 100, 150, 100);
LinearGradientBrushX br = new LinearGradientBrushX(r,Color.Black,Color.Black, 60F);
ColorBlendX cb = new ColorBlendX();
cb.Positions=new float[7];
int i=0;
for(float f=0;f<=1;f+=1.0f/6)
cb.Positions[i++]=f;
cb.Colors=new Color[]
{Color.Red,Color.Orange,Color.Yellow,Color.Green,Color.Blue,Color.Indigo,Color.Violet};
br.InterpolationColors=cb;
gx.TranslateTransform(160, 10);
gx.RotateTransform(60F);
gx.FillRectangle(br, r);
//Fill a rectangle with a 7-color RadialGradientBrushX
rY += 50;
RadialGradientBrushX brush2 = new RadialGradientBrushX(r, Color.Black,Color.Black, 220F);
brush2.InterpolationColors = cb;
gx.RotateTransform(-45F);
gx.TranslateTransform(-200, -170);
gx.FillRectangle(brush2, r);
//Refresh
Invalidate();
Alpha 通道合成
System.Drawing 命名空間中的Color 結構在.NET Framework 和.NET Compact Framework 中都可使用。差異在於.NET Compact Framework 中禁用了alpha 成分且色調-飽和度-亮度(HSB) 值不可用。幸運的是,alpha 通道合成可以完美地與XrossOne GDI+ 協同工作(您可能已經從前面的圖形範例中推斷出這一點)。
效能 DrawLine 2.604 ms 0.901 ms 189.0% DrawRect 3.705 ms 1.602 ms 131.3 % DrawPolygon 03 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 211.7% ScaleTransform 4.106 ms 0.801 ms 412.6 . ient (1) 9.013 ms 2.103 ms 328.6% LinearGradient (2) 8.012 ms 1.803 ms 344.4 %
手持PC 的CPU 的功能確實通常比標準PC 的CPU 差很多。繁重的計算可能使手持設備的反應速度降低,從而可能使用戶變得不勝其煩。換句話說,效能對於手持裝置軟體至關重要。因此,在重大場合下使用XrossOne Mobile GDI+ 之前,您可能會想要分析它的整體表現。因為GDI+ 中大多數對應於.NET Compact Framework 的等效函數都不可用,所以基準測試是針對.NET Framework 在XrossOne Mobile GDI+ 和GDI+ 之間進行的。測試是在下列類別中執行的:向量圖形呈現、二維變換和漸變填充。測試方案在相同的條件下執行。您可以在下載軟體包中找到基準測試程序,並且可以在http://www.xrossone.com/projects.php?menu=4 快速查看它們的圖形輸出。
XrossOne Mobile GDI+ 完全是用C# 託管程式碼編寫的,它的整體效能可以接受(請參閱下表),儘管二維變換和漸變填充需要在以後的版本中進一步優化。
方案 XrossOne Mobile GDI+ GDI+ for .NET Framework 系統開銷 3.205 lipms. % ScaleTransform 3%