Windows с C++

Рисование с Direct2D

Кенни Керр (Kenny Kerr)

В июня выпуске журнала MSDN Magazine (msdn.microsoft.com/magazine/dd861344.aspx), представленные Direct2D, новой ДВУМЕРНАЯ графика API предназначены для поддержки наиболее ресурсоемких и визуально форматированного настольных приложений с наиболее возможную производительность. В этой статье я описал, где Direct2D поместился в среди различных графических API Windows, его архитектуру и принципы. В частности я подробно описаны основы использования Direct2D надежно и эффективно для отрисовки внутри окна. Включить создание ресурсов для конкретных устройств, а также аппаратно независимых ресурсов и их соответствующих жизненных циклов. Если вы еще не сделано, я бы рекомендую прочитать статью перед продолжением работы здесь, как в этой статье многом построение после основой определены извлечение существует.

Отображение и управление

Полезно подумать о Direct2D как аппаратным ускорением отрисовка 2-D API. Конечно поддерживает возврата программного обеспечения, но момент здесь является Direct2D о визуализации. В отличие от других рисунков API Windows Direct2D использует компонентную подход к рисункам. Он не предоставляет собственной API для кодирования и декодирования точечные рисунки, макет текста, управления шрифтов, анимации, объем и т. д. Вместо этого уделяется визуализации и контролировать обработки графики (GPU) обеспечивая первым классом ловит другие API, сосредоточиться на макет текста и изображений. Direct2D однако, обеспечить примитивы для представления различных типов кистей, а также простые и сложные фигуры, строительные блоки для любого приложения ДВУМЕРНАЯ графика.

В этой статье я собираюсь показать, как рисовать Direct2D. Я будет начинаться путем введения структуры цвет Direct2D и продемонстрировать способы создания различных типов кистей. В отличие от большинства других графических интерфейсов API Windows Direct2D не предоставляет "Перо"простые, поэтому кисти важны довольно используемые для всех задач контура и заполнения. С этим в сторону, я покажу, как Рисование простых фигур.

Цвета

Direct2D использует простую структуру, представляющий цвета с компонентами цвета с плавающей запятой. Тип D2D1_COLOR_F является typedef для структуры D3DCOLORVALUE, используемое Direct3D для описания значения цвета. Он включает отдельные значения с плавающей запятой для красного, зеленого, синего и альфа-каналов. Значения в диапазоне от 0.0 до 1.0 с 0.0 черные цветовые каналы и полностью прозрачным для альфа-канала.

Вот как выглядит:

struct D3DCOLORVALUE
{
FLOAT r;
FLOAT g;
FLOAT b;
FLOAT a;
};

Direct2D предоставляет вспомогательный класс ColorF D2D1 пространства имен, наследует D2D1_COLOR_F и определяет некоторые общие константы цвета, но важнее предоставляет несколько полезных конструкторы, инициализировать структуру D2D1_COLOR_F. Можно, например, определить красный следующим образом:

const D2D1_COLOR_F red = D2D1::ColorF(1.0f, 0.0f, 0.0f);

Другой конструктор принимает упакованный RGB-значение и преобразует его отдельные цветовые каналы. Вот красный снова:

D2D1::ColorF(0xFF0000)

Это именно то же самое как с помощью следующие значения перечисления:

D2D1::ColorF(D2D1::ColorF::Red)

Хотя краткая, используя упакованный представление RGB съесть вверх небольшое больше циклов ПРОЦЕССОРА необходимости различные цветовые каналы для извлечения и преобразуется в их перемещаемые точки эквиваленты, поэтому использовать его с осторожностью.

Все конструкторы принимать дополнительное альфа-значение, которое по умолчанию 1.0, или полностью непрозрачным. Таким образом полупрозрачным синего цвета можно выразить следующим образом:

D2D1::ColorF(0.0f, 0.0f, 1.0f, 0.5f)

Помимо очистки целевого буфера визуализации области рисования, однако есть немного можно сделать с помощью цвета непосредственно. Что необходимо являются кисти.

Кисти

В отличие от структур простой цвет кисти являются ресурсами, через интерфейсы. Они используются для рисования линий, для рисования и заполнения фигур и рисования текста. Интерфейсы, которые являются производными от ID2D1Brush представляют различные типы кистей, предоставляемых Direct2D. Сам интерфейс ID2D1Brush позволяет управления непрозрачности кисти как единое целое, а не изменение альфа-канала цвета кисти. Это может быть особенно полезно с некоторыми интереснее типов кистей.

Вот как может Установите непрозрачность кисти на 50 процентов.

CComPtr<ID2D1Brush> brush;
// Create brush here...
brush->SetOpacity(0.5f);

ID2D1Brush также позволяет управлять преобразование, применяемое к кисти с момента, в отличие от Windows Presentation Foundation (WPF), кисти адаптировать система координат целевого буфера визуализации, а не с определенной фигуры, они могут рисования.

Различные методы целевого визуализации для создания кисти все принимают структуру необязательных D2D1_BRUSH_PROPERTIES, которые могут использоваться для задания начального непрозрачности и преобразования.

Все кистей, предоставляемых Direct2D, изменяемых и эффективно можно изменить их характеристики, поэтому не нужно создать новый кисти с разными характеристиками. Помните об этом при разработке приложения. Кисти также являются аппаратно зависимые ресурсы, поэтому они привязаны, время существования целевого буфера визуализации которых они созданы. Другими словами можно повторно использовать определенный кисти для, пока его рендеринга допустима, но необходимо освободить при отпускании целевого буфера визуализации.

Как его названию, интерфейс ID2D1SolidColorBrush представляет сплошной цветной кисти. Он добавляет методы для управления цветом, используемым кисти. Сплошной цветной кисти создается с помощью метода CreateSolidColorBrush целевого буфера визуализации:

CComPtr<ID2D1RenderTarget> m_target;
// Create render target here...
const D2D1_COLOR_F color = D2D1::ColorF(D2D1::ColorF::Red);
CComPtr<ID2D1SolidColorBrush> m_brush;
HR(m_target->CreateSolidColorBrush(color, &m_brush));
This brush's initial color can also easily be changed using the SetColor method:
m_brush->SetColor(differentColor);

Я собираюсь оставить полное обсуждение фигуры для следующего раздела, но в целях обеспечения необходимости что-нибудь для просмотра, я будет просто заполнения целевого буфера визуализации в окне с помощью прямоугольника, на основе размера целевого буфера визуализации. Следует помнить, что Direct2D использует аппаратно независимых точек (DIPs). Как следствие размер, сообщенные конкретного устройства, например клиентской области окна рабочего стола, может не соответствовать размера целевого буфера визуализации. К счастью очень легко получить размер целевого буфера визуализации в с помощью метода GetSize DIPs. Возвращает GetSize D2D1_SIZE_F структуры, Direct2D используется для представления размеры с двумя с плавающей запятой указывать значения ширины и высоты. Затем я может предоставить описание области для заполнения с помощью вспомогательная функция RectF и подключить сообщенные целевого буфера визуализации размер переменной D2D1_RECT_F. И, наконец, я могу использовать метод FillRectangle целевого буфера визуализации выполнить фактическое рисунка.

Вот как выглядит код:

const D2D1_SIZE_F size = m_target->GetSize();
const D2D1_RECT_F rect = D2D1::RectF(0, 0, size.width, size.height);
m_target->FillRectangle(rect, m_brush);

На рис. 1 показано окно как выглядит сплошной зеленой кистью. Очень интересные действительно!

Direct2D также поддерживает два типа градиентные кисти. Кисти градиента является, заполняет область цвета смешением вдоль оси. Кисти линейного градиента определяет ось как прямую линию с начальной и конечной точки. Кисти радиального градиента определяет ось как эллипса, где цвета radiate наружу из некоторые точки относительно центра эллипса.

Градиент определяется как последовательность относительные позиции от 0,0 до 1,0. Каждый имеет собственный цвет и вызывается ограничителя градиента. Имеется возможность использовать позиций за пределами этого диапазона для создания различных эффектов. Чтобы создать градиентную кисть, сначала необходимо создать коллекцию ограничителя градиента. Начните определение массива структур D2D1_GRADIENT_STOP.

Приведем пример:

const D2D1_GRADIENT_STOP gradientStops[] =
{
{ 0.0f, color1 },
{ 0.2f, color2 },
{ 0.3f, color3 },
{ 1.0f, color4 }
};

Далее вызовите метод CreateGradientStopCollection целевого буфера визуализации для создания объекта коллекции зависимости массив позициями градиента:

CComPtr<ID2D1GradientStopCollection> gradientStopsCollection;

HR(m_target->CreateGradientStopCollection(gradientStops,
_countof(gradientStops),
&gradientStopsCollection));

Первый параметр — указатель на массив и второй параметр предоставляет размер массива. Здесь я просто использую макрос стандартных _countof. Метод CreateGradientStopCollection возвращает новой коллекции. Для создания кисти линейного градиента, необходимо также обеспечивают структуру D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES для указания начала и конечная точка оси градиента. В отличие от позиции градиента эти точки находятся в пространстве координат кисть, которая обычно это для целевого буфера визуализации Если преобразование не установлен на кисти. Например можно создать кисть с ось, которая следующим запускается из верхнего левого угла целевого буфера визуализации нижний правый угол:

const D2D1_SIZE_F size = m_target->GetSize();
const D2D1_POINT_2F start = D2D1::Point2F(0.0f, 0.0f);
const D2D1_POINT_2F end = D2D1::Point2F(size.width, size.height);
const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES properties = D2D1::LinearGradientBrushProperties(start, end);
HR(m_target->CreateLinearGradientBrush(properties,
gradientStopsCollection,
&m_brush));

LinearGradientBrushProperties является другой функцией вспомогательный, предоставляемые Direct2D инициализировать структуру D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES. Метод CreateLinearGradientBrush принимает это вместе с коллекцией градиента, показанного выше и возвращает указатель интерфейса ID2D1LinearGradientBrush, представляющий новой кисти.

Конечно кисть не известно, при изменении размера целевого буфера визуализации. При желании конечная точка оси, чтобы изменить как изменить размер окна так легко можно сделать с помощью метода SetEndPoint кисти. Аналогично можно изменить на осьв начале точки метод SetStartPoint.

Вот как выглядит код прорисовки.

const D2D1_SIZE_F size = m_target->GetSize();
const D2D1_RECT_F rect = D2D1::RectF(0, 0, size.width, size.height);

m_brush->SetEndPoint(D2D1::Point2F(size.width, size.height));
m_target->FillRectangle(rect, m_brush);

На рис. 2 показано окно как выглядит с помощью кисти линейного градиента.

Для создания кисти радиального градиента, необходимо предоставить структуру D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES. Эта структура определяет эллипса, а также смещением относительно центра эллипса, представляющий начало координат, из которых кисть "излучает"цвет, в зависимости от коллекции ограничителя градиента. Следующий пример формирует эллипс, центрируется целевого буфера визуализации, имеет X и Y radius в соответствии с целевого буфера рендеринга и происхождение половину способ сторону нижний правый угол:

const D2D1_SIZE_F size = m_target->GetSize();

const D2D1_POINT_2F center = D2D1::Point2F(size.width / 2.0f, size.height / 2.0f);
const D2D1_POINT_2F offset = D2D1::Point2F(size.width * 0.25f, size.height * 0.25f);
const float radiusX = size.width / 2.0f;
const float radiusY = size.height / 2.0f;

const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES properties = D2D1::RadialGradientBrushProperties(center,

offset,

radiusX,

radiusY);

HR(m_target->CreateRadialGradientBrush(properties,
gradientStopsCollection,
&m_brush));

RadialGradientBrushProperties является другой функцией вспомогательный, предоставляемые Direct2D инициализировать структуру D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES. Метод CreateRadialGradientBrush принимает это вместе с коллекцией градиента, показанного выше и возвращает указатель интерфейса ID2D1RadialGradientBrush, представляющий новой кисти.

Можно также изменить эллипс и происхождение кисти в любое время следующим образом:

m_brush->SetCenter(center);
m_brush->SetGradientOriginOffset(offset);
m_brush->SetRadiusX(radiusX);
m_brush->SetRadiusY(radiusY);

На рис. 3 показано кисти радиального градиента.

Direct2D также предоставляет кисти точечного рисунка, но Оставим обсуждение Direct2D точечные рисунки для будущей статьи.

Фигуры

До сих я показал, можно только способы заливки прямоугольника, так что МНЕ удалось сосредоточиться на кисти, но Direct2D сделать так много более простой прямоугольников. Новичкам следует иметь в виду прямоугольники, закругленные прямоугольники и эллипсы предоставляются примитивов. По примитивы я просто значит является обычный старую структуру данных для каждого из этих.

D2D1_RECT_F представляет прямоугольник с плавающей запятой и сам является typedef D2D_RECT_F:

struct D2D_RECT_F
{
FLOAT left;
FLOAT top;
FLOAT right;
FLOAT bottom;
};

D2D1_ROUNDED_RECT представляет Скругленный прямоугольник и определен с radiuses, определение эллипсы квартал, который будет использоваться для рисования углы следующим образом:

struct D2D1_ROUNDED_RECT
{
D2D1_RECT_F rect;
FLOAT radiusX;
FLOAT radiusY;
};

D2D1_ELLIPSE представляет эллипса и определен с центральной точки, а также radiuses:

struct D2D1_ELLIPSE
{
D2D1_POINT_2F point;
FLOAT radiusX;
FLOAT radiusY;
};

Хотя эти структуры может показаться не слишком интересными, существуют две причины их упомянуть заранее. Во-первых они используются для создания более сложных объектов геометрии. Во-вторых Если необходимо заполнить или один из этих примитивов рисования, вы должны придерживаться с ними как обычно возникнет лучшую производительность, если избежать геометрических объектов.

Целевые буферы визуализации предоставляют набор из заполнения действия методы и для заполнения и структура этих примитивов. Пока я показал как использовать метод FillRectangle. Я не расточки, с примерами FillRoundedRectangle и FillEllipse методов, как они работают точно так же. В отличие от для методов заливки методы рисования может использоваться для структуры конкретной фигуры и являются весьма гибким. Как методов заливки действия методы, охватывающие все три примитивов работать в точно так же, поэтому расскажу только метод DrawRectangle.

В простейшем виде можно нарисовать контур прямоугольника следующим образом:

m_target->DrawRectangle(rect,
m_brush,
20.0f);

Третий параметр указывает ширину штрих, который рисуется контур прямоугольника. Штриха сам центрируется на прямоугольник, если заполнено этот же прямоугольник будет видно штриха и заливки перекрываются по 10.0 DIPs. Дополнительный четвертый параметр может быть предоставлено для управления стиль штрих, который рисуется. Это полезно, если требуется Рисование пунктирной линии или просто хотите управлять типом соединения с вершины фигуры.

Сведения о стиле штриха представляется интерфейса ID2D1StrokeStyle. Объекты стиля штриха являются аппаратно независимых ресурсов, что означает, что им не нужно заново при каждом целевого буфера визуализации является недействительным. В этом случае создается новый объект стиля штриха с помощью метод объекта фабрики Direct2D CreateStrokeStyle.

Если требуется просто штриха использовать определенный тип соединения, можно создать стиль штриха следующим образом:

D2D1_STROKE_STYLE_PROPERTIES properties = D2D1::StrokeStyleProperties();
properties.lineJoin = D2D1_LINE_JOIN_BEVEL;

HR(m_factory->CreateStrokeStyle(properties,
0, // dashes
0, // dash count
&m_strokeStyle));

Структура D2D1_STROKE_STYLE_PROPERTIES предоставляет множество элементов управления различными аспектами стиля штриха, в частности фигуры или отрезка на каждом конце структуры или тире, а также сам стиль тире. Второй и третий параметр для метода CreateStrokeStyle являются необязательными и необходимо предоставить их только при определении стиля пользовательские пунктирной штриха. Чтобы определить стиль штрихов пунктирной линией, убедитесь, в пары указан тире. Первый элемент в каждой паре равна длине дефиса, а второй — длина пробел перед следующей тире. Сами значения умножаются ширина штриха. Можно задать столько пар при необходимости произвести нужный шаблон. Приведем пример:

D2D1_STROKE_STYLE_PROPERTIES properties = D2D1::StrokeStyleProperties();
properties.dashStyle = D2D1_DASH_STYLE_CUSTOM;

float dashes[] =
{
2.0f, 1.0f,
3.0f, 1.0f,
};

HR(m_factory->CreateStrokeStyle(properties,
dashes,
_countof(dashes),
&m_strokeStyle));

Можно выбрать любой из количество различных тире стилей из перечисления D2D1_DASH_STYLE вместо определения собственных. На рис. 4 показан некоторые стили, различные штрих на работе. Если внимательно посмотрите вы увидите, что переходит Direct2D автоматически альфа-сглаживание примитива для лучше выглядящие результатов.

Вот поэтому гораздо больше, Direct2D можно выполнить, из сложных геометрических объектов и преобразований, для рисования текста и рисунков и многое другое. Надеюсь, что рассмотрены эти и несколько столбцов в будущем.

KENNY KERR специалист в области разработки программного обеспечения для Windows. Он имеет страсть написание и обучение разработчиков программирование и программное обеспечение. Достичь ему на weblogs.asp.net/kennykerr.