소개 .NET Compact Framework는 최고는 아니지만 탁월한 모바일 장치용 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는 2차원 그래픽에는 적합하지 않습니다. 일반 응용 프로그램에서 사용하기에는 너무 복잡합니다.
우리에게 필요한 것은 GDI+와 같은 강력하고 사용하기 쉬운 2D 그래픽 엔진입니다. 그래서 XrossOne GDI+ 프로젝트를 처음부터 개발하게 되었습니다. 이는 전적으로 C# 관리 코드로 작성되었으며 기본 코드나 안전하지 않은 코드를 포함하지 않습니다. 몇 달 간의 노력 끝에 마침내 이 기사의 시작 부분에서 다운로드 가능한 원본 버전을 제공할 수 있게 되었습니다.
시작하기 이 프로젝트 시작부터 XrossOne GDI+ 엔진은 다양한 휴대용 장치와 플랫폼에서 중립적이어야 한다는 것이 항상 내 마음 속에 있었습니다. 결과적으로 Pocket PC, Windows CE, 스마트폰, Windows .NET 및 Mono와 호환됩니다. 동일한 런타임을 다른 대상에 복사해도 여전히 잘 작동합니다.
다음 표에는 전체 아키텍처가 요약되어 있습니다.
레이어 네임스페이스XrossOne GDI+ API XrossOne.드로잉
고정점 기반 2차원 그래픽 엔진 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 고정 소수점 숫자에 대한 도우미 클래스입니다. 고정 소수점 유형과 표준 유형(int, float, string) 간의 변환에 편의성을 제공합니다. MatrixFP는 고정 소수점 2D 변환을 위해 작성되었습니다. 고정 소수점 계산은 덜 정확하기 때문에 계단식 변환을 사용하면 일부 정확도가 손실될 수 있습니다. 예를 들어 대부분의 경우 두 가지 반전 작업으로는 원래 행렬을 복원할 수 없습니다. DoubleFP는 라이브러리를 완성하기 위해 존재하지만 아직 사용되지는 않습니다.
XrossOne GDI+의 핵심은 "고정 소수점 기반 2차원 그래픽 엔진"입니다. 앤티앨리어싱 그리기, 라인 캡/조인트 장식, 2D 변환, 그래디언트 채우기, 알파 채널 합성 등과 같은 많은 복잡한 벡터 그래픽 알고리즘을 구현합니다. 기본 GDI+의 고급 기능 대부분은 여기에서 찾을 수 있습니다. 그러나 고정 소수점 기반 인터페이스가 프로그래머에게 친숙하지 않기 때문에 몇 가지 경우에만 직접 사용해야 하지만 이 상황에 대해 너무 걱정하지 마십시오. 잘 캡슐화된 API를 사용할 수 있습니다. XrossOne.드로잉 네임스페이스에서 찾을 수 있습니다. XrossOne.드로잉의 클래스는 각 클래스 끝에 "X"가 있다는 점을 제외하면 System.드로잉의 클래스와 매우 유사합니다. 예를 들어 XrossOne.드로잉.PenX 클래스는 System.드로잉.Pen과 동일합니다. GDI+ 프로그램을 XrossOne GDI+로 변환하는 데는 약간의 요령이 있습니다. using 섹션에서 XrossOne GDI+ 클래스의 이름을 해당 클래스로 바꿉니다. 예:
Pen = XrossOne.드로잉.PenX 사용;
LinearGradientBrush = XrossOne.드로잉.LinearGradientBrushX 사용;
Matrix = XrossOne.드로잉.MatrixX 사용;
주요 기능 앤티앨리어싱 벡터 그래픽 드로잉
선분, 직사각형, 다각형, 타원, 섹터, 베지어 스플라인, 기본 스플라인 등과 같은 모든 종류의 2차원 기하학적 모양을 XrossOne Mobile GDI+를 통해 렌더링할 수 있습니다. 그러나 섹터, 베지어 스플라인 및 기수 스플라인은 .NET Compact Framework에서 사용할 수 없습니다. 또한 모든 그래픽은 렌더링 시 자동으로 앤티앨리어싱됩니다. 이는 매우 부드러운 품질을 달성하는 데 도움이 됩니다. .NET Compact Framework에서는 브러시 너비가 1픽셀로 고정됩니다. XrossOne GDI+에는 이 제한이 없습니다. 그림 1과 같이 다양한 크기의 브러시를 모든 모양의 윤곽선에 적용할 수 있습니다.
그림 1. 앤티앨리어싱된 벡터 그래픽 드로잉
코드 예시 1
//배경을 지우고 변환 상태를 재설정합니다.
gx.Clear(Color.White);
gx.ResetTransform();
//뒤틀린 그리드를 배경으로 그립니다.
PenX 펜 = new PenX(Utils.FromArgb(0x40, Color.LightGray), 5);
for (int i = -높이; i < 너비 + 높이; i+=20)
{
gx.DrawLine(pen, i, 0, i + 높이, 높이);
gx.DrawLine(pen, i, 0, i - 높이, 높이);
}
//10.5픽셀 펜을 사용하여 DarkMagenta 직사각형을 그립니다.
색상 c = Utils.FromArgb(0x80, Color.DarkMagenta);
펜 = 새로운 PenX(c, 10.5f);
gx.DrawRectangle(펜, 50, 20, 150, 200);
//GreenYellow 직사각형 채우기
c = Utils.FromArgb(0xA0, Color.GreenYellow);
BrushX 브러시 = 새로운 SolidBrushX(c);
gx.FillRectangle(브러쉬, 120, 50, 90, 150);
//10.5픽셀 펜으로 BlueViolet 타원 그리기
c = Utils.FromArgb(0x80, Color.BlueViolet);
펜 = 새로운 PenX(c, 10.5f);
gx.DrawEllipse(펜, 50, 20, 150, 80);
//빨간색 타원 채우기
c = Utils.FromArgb(0xA0, Color.Red);
브러시 = 새로운 SolidBrushX(c);
gx.FillEllipse(브러쉬, 20, 50, 80, 150);
//156.5도에서 -280.9도까지 HotPink 파이를 그립니다.
pen.Color = Utils.FromArgb(0xA0, Color.HotPink);
gx.DrawPie(펜, 3.6f, 120.3f, 200.8f, 130.1f, 156.5f, -280.9f);
//주황색 베지어 곡선 그리기
c = Utils.FromArgb(0xA0, Color.Orange);
펜 = 새로운 PenX(c, 16);
포인트 시작 = new Point(70, 100);
포인트 제어1 = new Point(100, 10);
포인트 컨트롤2 = new Point(150, 50);
포인트 end1 = new Point(200, 200);
포인트 컨트롤3 = new Point(100, 150);
포인트 제어4 = new Point(50, 200);
포인트 end2 = new Point(10, 150);
Point[] bezierPoints ={start, control1, control2, end1, control3, control4, end2};
pen.EndCap = LineCapX.Round;
gx.DrawBeziers(pen, bezierPoints);
//새로 고치다
무효화();
XrossOne GDI+와 기본 GDI+의 벡터 그래픽 출력은 기수 스플라인을 제외하고 동일합니다. 내 알고리즘은 Jean-Yves Queinec의 베지어 곡선을 사용한 평활화 알고리즘 기사에서 가져왔습니다. 따라서 아래 그림 2와 같이 출력 간에 약간의 차이점이 있을 수 있습니다.
그림 2. DrawCurve/DrawClosedCurve의 출력
대부분의 벡터 그래픽 렌더링 기능이 구현되었지만 아직 수행해야 할 작업이 몇 가지 있습니다. 일부 기능(DrawString, DrawImage, DrawPath 등)은 다음 버전까지 사용할 수 없습니다.
그라데이션 채우기
기본 GDI+에는 SolidBrush, LinearGradientBrush, PathGradientBrush, TextureBrush 및 HatchBrush 등 5개의 브러시가 있습니다. 그러나 이 버전에서는 SolidBrush와 LinearGradientBrush만 사용할 수 있습니다. XrossOne GDI+는 RadialGradientBrush를 지원하지만 PathGradientBrush는 지원하지 않습니다. 아래 그림 5에서는 그라데이션 채우기를 보여줍니다.
그림 5. 그라데이션 채우기
코드 예시 4
//배경을 지우고 변환 상태를 재설정합니다.
gx.Clear(Color.White);
gx.ResetTransform();
//흑백 LinearGradientBrushX로 직사각형 채우기
직사각형 r = new Rectangle(20, 50, 300, 100);
색상 c1 = 색상.검정색;
색상 c2 = 색상.흰색;
BrushX Brush1 = new LinearGradientBrushX(r, c1, c2, 30F);
gx.FillRectangle(brush1, r);
//7색 LinearGradientBrushX로 직사각형 채우기
r = 새로운 직사각형(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.위치[i++]=f;
cb.Colors=새 색상[]
{색상.빨간색,색상.주황색,색상.노란색,색상.녹색,색상.파란색,색상.인디고,색상.보라색};
br.InterpolationColors=cb;
gx.TranslateTransform(160, 10);
gx.RotateTransform(60F);
gx.FillRectangle(br, r);
//7색 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);
//새로 고치다
무효화();
알파 채널 합성
System.드로잉 네임스페이스의 Color 구조는 .NET Framework와 .NET Compact Framework 모두에서 사용할 수 있습니다. 차이점은 알파 구성 요소가 비활성화되어 있고 HSB(색조-채도-밝기) 값을 .NET Compact Framework에서 사용할 수 없다는 것입니다. 다행히도 알파 채널 합성은 XrossOne GDI+에서 완벽하게 작동합니다(이전 그래픽 예제에서 추론할 수 있음).
성능 3.505ms 1.602ms 118.8 % DrawCurve 4.006ms 1.402 ms 185.7 % DrawPie 6.810ms 2.003ms 240.0 % TranslateTransform 10.615ms 3.405ms 211.7 % ScaleTransform 4 0.801ms 412.6 % RotateTransform 7.811ms 1.803ms 333.2% 선형 그라데이션(1) 9.013ms 2.103ms 328.6% 선형 그라데이션(2) 8.012ms 1.803ms 344.4%
휴대용 PC CPU가 표준 PC CPU보다 성능이 훨씬 떨어지는 경우가 많은 것은 사실입니다. 과도한 계산으로 인해 휴대용 장치의 반응성이 저하되어 사용자가 좌절감을 느낄 수 있습니다. 즉, 휴대용 장치 소프트웨어에서는 성능이 매우 중요합니다. 따라서 중요한 상황에서 XrossOne Mobile GDI+를 사용하기 전에 전체적인 성능을 분석해 보시는 것이 좋을 것 같습니다. .NET Compact Framework용 GDI+의 해당 기능 대부분을 사용할 수 없기 때문에 벤치마크는 XrossOne Mobile GDI+와 .NET Framework용 GDI+ 간에 수행되었습니다. 테스트는 벡터 그래픽 렌더링, 2D 변환 및 그라데이션 채우기 범주에서 수행되었습니다. 테스트 시나리오는 동일한 조건에서 실행되었습니다. 다운로드 패키지에서 벤치마크 프로그램을 찾을 수 있으며 http://www.xrossone.com/projects.php?menu=4에서 그래픽 출력을 빠르게 볼 수 있습니다.
XrossOne Mobile GDI+는 전적으로 C# 관리 코드로 작성되었으며 전반적인 성능은 허용 가능하지만(아래 표 참조) 2D 변환 및 그래디언트 채우기는 향후 버전에서 추가 최적화가 필요합니다.
솔루션 66.7 % DrawBezier .106ms