Введение .NET Compact Framework — отличный, если не лучший, API для мобильных устройств. Его графический движок сильно ограничен для увеличения скорости рендеринга и снижения потребления памяти. Однако, похоже, это далеко не отвечает растущим требованиям пользователей к улучшению качества графики. Попытка получить некоторые расширенные возможности рендеринга векторной графики в .NET Compact Framework может оказаться утомительной задачей. У разработчиков есть два варианта:
1. Перейти к нативному коду. Например, хорошим выбором может быть API игр для Pocket PC. Его производительность впечатляет. Дополнительную информацию см. в подробной статье по адресу: 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 не подходит для двухмерной графики. Он слишком сложен для использования в общих приложениях.
Нам нужен мощный и простой в использовании движок 2D-графики, такой как GDI+. Поэтому я разработал проект XrossOne GDI+ с нуля. Он полностью написан на управляемом коде C# и не содержит собственного или небезопасного кода. После месяцев напряженной работы я наконец могу предоставить загружаемую оригинальную версию в начале этой статьи.
Приступая к работе С самого начала этого проекта я всегда считал, что движок XrossOne GDI+ должен быть нейтральным для различных портативных устройств и платформ. В результате он совместим с Pocket PC, Windows CE, смартфонами, 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. Он обеспечивает удобство преобразования между типами с фиксированной точкой и стандартными типами (int, float, string). MatrixFP написан для двумерных преобразований с фиксированной точкой. Поскольку вычисления с фиксированной точкой менее точны, некоторая точность может быть потеряна при каскадных преобразованиях. Например, в большинстве случаев две операции обращения не могут восстановить исходную матрицу. DoubleFP существует для завершения библиотеки, но еще не используется.
«Двумерный графический движок на основе фиксированной точки» является ядром XrossOne GDI+. Он реализует множество сложных алгоритмов векторной графики, таких как сглаженное рисование, оформление границ линий/стыков, 2D-преобразования, градиентные заливки, композитинг альфа-каналов и многое другое. Большинство расширенных функций встроенного GDI+ можно найти здесь. Однако вам следует использовать его напрямую только в некоторых случаях, поскольку его интерфейс на основе фиксированной точки не удобен для программистов, но не беспокойтесь слишком сильно об этой ситуации. Доступен хорошо инкапсулированный API. Вы можете найти их в пространстве имен XrossOne.Drawing. Классы в XrossOne.Drawing очень похожи на классы в System.Drawing, за исключением того, что каждый класс имеет букву «X» в конце. Например, класс XrossOne.Drawing.PenX эквивалентен System.Drawing.Pen. Есть небольшая хитрость для конвертации программ GDI+ в XrossOne GDI+. В разделе «Использование» переименуйте классы XrossOne GDI+ в эквивалентные им классы. Например:
используя Pen = XrossOne.Drawing.PenX;
использование LinearGradientBrush = XrossOne.Drawing.LinearGradientBrushX;
используя Матрицу = XrossOne.Drawing.MatrixX;
Основные характеристики: Рисование векторной графики со сглаживанием
С помощью XrossOne Mobile GDI+ можно визуализировать все виды двумерных геометрических фигур, например отрезки линий, прямоугольники, многоугольники, эллипсы, сектора, сплайны Безье, кардинальные сплайны и т. д. Однако сектора, сплайны Безье и поразрядные сплайны недоступны в .NET Compact Framework. Кроме того, вся графика автоматически сглаживается при рендеринге. Это помогает добиться сверхгладкого качества. В .NET Compact Framework ширина кисти фиксирована и равна 1 пикселю. Этого ограничения нет в XrossOne GDI+. К контурам всех фигур можно применять кисти разных размеров, как показано на рисунке 1.
Рисунок 1. Рисунок векторной графики со сглаживанием.
Пример кода 1
//Очищаем фон и сбрасываем состояние преобразования
gx.Clear(Цвет.Белый);
gx.ResetTransform();
//Рисуем наклонную сетку в качестве фона
PenX pen = новый PenX(Utils.FromArgb(0x40, Color.LightGray), 5);
for (int i = -Height; i < Ширина + Высота; i+=20)
{
gx.DrawLine(pen, i, 0, i + Height, Height);
gx.DrawLine(pen, i, 0, i - Высота, Высота);
}
//Рисуем прямоугольник DarkMagenta ручкой размером 10,5 пикселей.
Цвет c = Utils.FromArgb(0x80, Color.DarkMagenta);
ручка = новый PenX(c, 10.5f);
gx.DrawRectangle(pen, 50, 20, 150, 200);
//Заливаем зелено-желтый прямоугольник
c = Utils.FromArgb(0xA0, Color.GreenYellow);
Кисть BrushX = новая SolidBrushX(c);
gx.FillRectangle(кисть, 120, 50, 90, 150);
//Рисуем сине-фиолетовый эллипс ручкой размером 10,5 пикселей.
c = Utils.FromArgb(0x80, Color.BlueViolet);
ручка = новый PenX(c, 10.5f);
gx.DrawEllipse(pen, 50, 20, 150, 80);
//Заполняем красный эллипс
c = Utils.FromArgb(0xA0, Color.Red);
кисть = новый SolidBrushX (с);
gx.FillEllipse(кисть, 20, 50, 80, 150);
//Нарисуйте круговую диаграмму HotPink от 156,5 градусов до -280,9 градусов
pen.Color = Utils.FromArgb(0xA0, Color.HotPink);
gx.DrawPie(pen, 3.6f, 120.3f, 200.8f, 130.1f, 156.5f, -280.9f);
//Рисуем оранжевые кривые Безье
c = Utils.FromArgb(0xA0, Color.Orange);
ручка = новый PenX(c, 16);
Начало точки = новая точка(70, 100);
Point control1 = новая точка(100, 10);
Point control2 = новая точка(150, 50);
Конец точки1 = новая точка(200, 200);
Point control3 = новая точка(100, 150);
Point control4 = новая точка(50, 200);
Конец точки2 = новая точка(10, 150);
Point[] bezierPoints = {start, control1, control2, end1, control3, control4, end2};
pen.EndCap = LineCapX.Round;
gx.DrawBeziers(pen, bezierPoints);
//Обновить
Недействителен();
Вывод векторной графики XrossOne GDI+ и собственного GDI+ идентичен, за исключением поразрядных сплайнов. Мой алгоритм взят из статьи Жан-Ива Кенека «Алгоритм сглаживания с использованием кривых Безье». Поэтому вы можете обнаружить некоторые различия между их выходными данными, как показано на рисунке 2 ниже.
Рисунок 2. Вывод DrawCurve/DrawClosedCurve
Хотя большинство функций рендеринга векторной графики уже реализовано, еще предстоит проделать некоторую работу. Некоторые функции (DrawString, DrawImage, DrawPath и т. д.) не будут доступны до следующей версии.
градиентная заливка
В встроенном GDI+ имеется пять кистей — SolidBrush, LinearGradientBrush, PathGradientBrush, TextureBrush и HatchBrush. Однако в этой версии доступны только SolidBrush и LinearGradientBrush. XrossOne GDI+ поддерживает RadialGradientBrush, но не PathGradientBrush. На рисунке 5 ниже показана градиентная заливка.
Рисунок 5. Градиентная заливка
Пример кода 4
//Очищаем фон и сбрасываем состояние преобразования
gx.Clear(Цвет.Белый);
gx.ResetTransform();
//Заливаем прямоугольник черно-белой кистью LinearGradientBrushX
Прямоугольник r = новый прямоугольник (20, 50, 300, 100);
Цвет c1 = Цвет.Черный;
Цвет c2 = Цвет.Белый;
BrushX кисть1 = новая LinearGradientBrushX(r, c1, c2, 30F);
gx.FillRectangle(кисть1, r);
//Заливаем прямоугольник 7-цветной кистью LinearGradientBrushX
г = новый прямоугольник (90, 100, 150, 100);
LinearGradientBrushX br = новая LinearGradientBrushX(r,Color.Black,Color.Black, 60F);
ColorBlendX cb = новый ColorBlendX();
cb.Positions=новое число с плавающей запятой[7];
интервал я = 0;
for(float f=0;f<=1;f+=1.0f/6)
cb.Positions[i++]=f;
cb.Colors=новый цвет[]
{Цвет.Красный,Цвет.Оранжевый,Цвет.Желтый,Цвет.Зеленый,Цвет.Синий,Цвет.Индиго,Цвет.Фиолетовый};
br.InterpolationColors=cb;
gx.TranslateTransform(160, 10);
gx.RotateTransform(60F);
gx.FillRectangle(br, r);
//Заливаем прямоугольник 7-цветной кистью RadialGradientBrushX
гY += 50;
RadialGradientBrushX кисть2 = новая RadialGradientBrushX(r, Color.Black,Color.Black, 220F);
кисть2.InterpolationColors = cb;
gx.RotateTransform(-45F);
gx.TranslateTransform(-200, -170);
gx.FillRectangle(кисть2, г);
//Обновить
Недействителен();
Композитинг альфа-канала
Структура Color в пространстве имен System.Drawing доступна как в .NET Framework, так и в .NET Compact Framework. Разница в том, что альфа-компонент отключен, а значение «Цветовой тон-Насыщенность-Яркость» (HSB) недоступно в .NET Compact Framework. К счастью, композитинг альфа-каналов прекрасно работает с XrossOne GDI+ (как вы, возможно, поняли из предыдущего графического примера).
производительность 3,505 мс 1,602 мс 118,8 % DrawCurve 4,006 мс 1,402 мс 185,7% DrawPie 6,810 мс 2,003 мс 240,0% TranslateTransform 10,615 мс 3,405 мс 21 1,7% ScaleTransform 4,106 мс 0,801 мс 412,6 % RotateTransform 7,811 мс 1,803 мс 333,2% LinearGradient ( 1) 9,013 мс 2,103 мс 328,6% LinearGradient (2) 8,012 мс 1,803 мс 344,4 %
Это правда, что процессоры портативных ПК зачастую намного менее мощны, чем процессоры стандартных ПК. Тяжелые вычисления могут сделать портативные устройства менее отзывчивыми, что может разочаровать пользователей. Другими словами, производительность имеет решающее значение для программного обеспечения портативных устройств. Поэтому, прежде чем использовать XrossOne Mobile GDI+ в серьезной ситуации, вы можете проанализировать его общую производительность. Поскольку большинство эквивалентных функций в GDI+ для .NET Compact Framework недоступны, тесты проводились между XrossOne Mobile GDI+ и GDI+ для .NET Framework. Тесты проводились в следующих категориях: рендеринг векторной графики, 2D-преобразования и градиентные заливки. Тестовые сценарии выполнялись в одинаковых условиях. Вы можете найти тестовые программы в пакете загрузки и быстро просмотреть их графический результат на http://www.xrossone.com/projects.php?menu=4.
XrossOne Mobile GDI+ полностью написан на управляемом коде C#, и его общая производительность приемлема (см. таблицу ниже), хотя 2D-преобразования и градиентные заливки потребуют дальнейшей оптимизации в будущих версиях.
Решение 66,7 % DrawBezier