Базовое графическое получение уровня
Объекты CGLayer (CGLayerRef
тип данных), позволяют Вашему приложению использовать уровни для рисования.
Уровни подходят для следующего:
Высококачественный внеэкранный рендеринг рисования этого Вы планируете снова использовать. Например, Вы могли бы создавать сцену и план снова использовать тот же фон. Нарисуйте фоновую сцену к уровню и затем нарисуйте уровень каждый раз, когда Вам нужен он. Одно дополнительное преимущество - то, что Вы не должны знать, что цветовое пространство или зависящая от устройств информация рисуют к уровню.
Повторное получение. Например, Вы могли бы хотеть создать образец, состоящий из того же элемента, нарисованного много раз. Нарисуйте элемент к уровню и затем неоднократно рисуйте уровень, как показано на рисунке 12-1. Любой Кварцевый объект, который Вы неоднократно рисуете — включая CGPath, CGShading и объекты CGPDFPage — получает преимущества от улучшенной производительности при рисовании его к CGLayer. Обратите внимание на то, что уровень не только для экранного получения; можно использовать его для графических контекстов, не ориентированных на экран, такие как контекст графики PDF.
Буферизация. Несмотря на то, что можно использовать уровни с этой целью, Вам не должно быть нужно к тому, потому что Кварцевый Наборщик делает буферизацию с Вашей стороны ненужной. Если необходимо нарисовать к буферу, используйте уровень вместо контекста растрового изображения.
Объекты CGLayer и слои прозрачности параллельны объектам CGPath и путям, создаваемым функциями CGContext. В случае CGLayer или объекта CGPath, Вы красите абстрактному месту назначения и можете тогда позже нарисовать полное рисование другому месту назначения, такому как дисплей или PDF. Когда Вы красите к слою прозрачности или используете функции CGContext, рисующие пути, Вы рисуете непосредственно месту назначения, представленному графическим контекстом. Нет никакого промежуточного абстрактного места назначения для сборки рисования.
Как работает рисование уровня
Уровень, представленный CGLayerRef
тип данных, спроектирован для оптимальной производительности. Когда возможно, Кварц кэширует объект CGLayer использование механизма, надлежащего типу Кварцевого контекста графики, с которым это связано. Например, графический контекст, связанный с видеокартой, мог бы кэшировать уровень на видеокарте, делающей рисование содержания, это находится в уровне намного быстрее, чем рендеринг подобного изображения, это создается из контекста растрового изображения. Поэтому уровень обычно является лучшим выбором для внеэкранного получения, чем контекст растрового изображения.
Все Кварцевые функции рисования рисуют к графическому контексту. Графический контекст обеспечивает абстракцию места назначения, освобождая Вас от подробных данных места назначения, таких как ее разрешение. Вы работаете в пространстве пользователя, и Кварц выполняет необходимые трансформации для рендеринга получения правильно месту назначения. При использовании объекта CGLayer для рисования Вы также рисуете к графическому контексту. Рисунок 12-1 иллюстрирует необходимые шаги для получения уровня.
Все получение уровня запускается с графического контекста, из которого Вы создаете объект CGLayer использование функции CGLayerCreateWithContext
. Графический контекст, используемый для создания объекта CGLayer, обычно является контекстом графики окна. Кварц создает уровень так, чтобы он имел все характеристики графического контекста — его разрешение, цветовое пространство и настройки состояния графики. Если Вы не хотите использовать размер графического контекста, можно обеспечить размер для уровня. На рисунке 12-2 левая сторона показывает, что графический контекст раньше создавал уровень. Серая часть поля на правой стороне, маркированном объекте CGLayer, представляет недавно создаваемый уровень.
Прежде чем можно будет нарисовать к уровню, необходимо получить графический контекст, это связано с уровнем путем вызывания функции CGLayerGetContext
. Этот графический контекст является той же разновидностью, как графический контекст раньше создавал уровень. Пока графический контекст, используемый для создания уровня, является контекстом графики окна, тогда графический контекст CGLayer кэшируется к GPU если вообще возможный. Белая часть поля на правой стороне рисунка 12-2 представляет недавно создаваемый контекст графики уровня.
Вы рисуете к графическому контексту уровня, как Вы нарисовали бы к любому графическому контексту, передав графический контекст уровня функции получения. Рисунок 12-2 показывает, что лист формирует нарисованный к контексту уровня.
Когда Вы готовы использовать содержание уровня, можно вызвать функции CGContextDrawLayerInRect
или CGContextDrawLayerAtPoint
, вовлекать уровень в графический контекст. Обычно Вы нарисовали бы к тому же графическому контексту, что Вы раньше создавали расположенный на слое объект, но Вы не обязаны. Можно нарисовать уровень к любому графическому контексту, имея в виду, что получение уровня имеет характеристики графического контекста, используемого для создания расположенного на слое объекта, который мог наложить определенные ограничения (производительность или разрешение, например). Например, уровень, связанный с экраном, может кэшироваться в видеооборудовании. Если целевой контекст является печатью или контекстом PDF, он, возможно, должен быть выбран от аппаратного обеспечения машинной графики до памяти, приводящей к низкой производительности.
Рисунок 12-2 показывает содержание уровня — лист — рисовавшийся неоднократно к графическому контексту раньше создавал расположенный на слое объект. Можно снова использовать получение, это находится в уровне так много раз, как Вы хотели бы прежде, чем выпустить объект CGLayer.
Рисование с уровнем
Необходимо выполнить задачи, описанные в следующем разделе для рисования использования объекта CGLayer:
Посмотрите Пример: Используя Многократные Объекты CGLayer Нарисовать Флаг для подробного примера кода.
Создайте объект CGLayer, инициализированный с существующим графическим контекстом
Функция CGLayerCreateWithContext
возвращает уровень, инициализирующийся с существующим графическим контекстом. Уровень наследовал все характеристики графического контекста, включая цветовое пространство, размер, разрешение и формат пикселя. Позже, когда Вы рисуете уровень месту назначения, Кварц автоматически окрашивают соответствия уровнем к целевому контексту.
Функция CGLayerCreateWithContext
берет три параметра:
Графический контекст для создания уровня из. Обычно Вы передаете контекст графики окна так, чтобы можно было позже нарисовать уровень на экране.
Размер уровня относительно графического контекста. Уровень может быть тем же размером как графический контекст или меньший. Если необходимо получить размер уровня позже, можно вызвать функцию
CGLayerGetSize
.Вспомогательный словарь. Этот параметр в настоящее время не использован, так передача
NULL
.
Получите графический контекст для уровня
Кварц всегда рисует к графическому контексту. Теперь, когда у Вас есть уровень, необходимо создать графический контекст, связанный с уровнем. Что-либо Вы вовлекаете контекст графики уровня, является частью уровня.
Функция CGLayerGetContext
берет уровень в качестве параметра и возвращает графический контекст, связанный с уровнем.
Нарисуйте к графическому контексту CGLayer
После получения графического контекста, связанного с уровнем можно выполнить любое получение, которое Вы хотели бы к контексту графики уровня. Можно открыть файл PDF или файл образа и нарисовать содержание файла к уровню. Можно использовать любой Кварц 2D функции для рисования прямоугольников, строк и других примитивов получения. Рисунок 12-3 показывает пример рисования прямоугольников и строк к уровню.
Например, для рисования заполненного прямоугольника к графическому контексту CGLayer Вы вызываете функцию CGContextFillRect
, предоставление графического контекста Вы получили из функции CGLayerGetContext
. Если называют графический контекст myLayerContext
, вызов функции похож на это:
CGContextFillRect (myLayerContext, myRect)
Нарисуйте уровень к целевому графическому контексту
Когда Вы готовы нарисовать уровень к его целевому графическому контексту, можно использовать любую из следующих функций:
CGContextDrawLayerInRect
, который рисует уровень к графическому контексту в указанном прямоугольнике.CGContextDrawLayerAtPoint
, который рисует уровень к графическому контексту в указанной точке.
Обычно целевой графический контекст, который Вы предоставляете, является контекстом графики окна, и это - тот же графический контекст, который Вы используете для создания уровня. Рисунок 12-4 показывает результат повторного рисования получения уровня, показанного на рисунке 12-3. Для достижения шаблонного эффекта Вы вызываете любую из функций рисования уровня неоднократно —CGContextDrawLayerAtPoint
или CGContextDrawLayerInRect
— изменение смещения каждый раз. Например, можно вызвать функцию CGContextTranslateCTM
для изменения источника координатного пространства каждый раз, Вы рисуете уровень.
Пример: Используя многократный CGLayer возражает для рисования флага
Этот раздел показывает, как использовать два объекта CGLayer нарисовать флаг, показанный на рисунке 12-5 на экране. Сначала Вы будете видеть, как сократить флаг до простых примитивов получения, тогда Вы будете смотреть на код, должен был выполнить получение.
С точки зрения рисования его на экране, флаг имеет три части:
Образец красных и белых дорожек. Можно сократить образец до единственной красной дорожки, потому что для экранного получения можно принять белый фон. Вы создаете единственный красный прямоугольник, тогда неоднократно рисуете прямоугольник при различных смещениях для создания семи красных дорожек, необходимых для флага США. Уровень идеален для повторного получения. Вы рисуете красный прямоугольник к уровню, затем рисуете уровень на экране семь раз.
Синий прямоугольник. Вам нужен синий прямоугольник один раз, так использование уровня не имеет никакого преимущества. Когда это прибудет время для рисования синего прямоугольника, нарисуйте его непосредственно на экране.
Образец 50 белых звезд. Как красная дорожка, уровень идеален для рисования звезд. Вы создаете путь, обрисовывающий в общих чертах форму звезды, и затем заполните путь белым. Нарисуйте одну звезду к уровню, затем нарисуйте времена уровня 50, корректируя смещение каждый раз для получения надлежащего интервала.
Код на рисунке 12-2 производит вывод, показанный на рисунке 12-5. Подробное объяснение каждой пронумерованной строки кода появляется после перечисления. Перечисление довольно долго, таким образом, Вы могли бы хотеть распечатать объяснение так, чтобы можно было считать его, поскольку Вы смотрите на код. myDrawFlag
подпрограмму вызывают из приложения Какао. Приложение передает контекст графики окна и прямоугольник, указывающий размер представления, связанного с контекстом графики окна.
Код перечисления 12-1, использующий уровни для рисования флага
void myDrawFlag (CGContextRef context, CGRect* contextRect) |
{ |
int i, j, |
num_six_star_rows = 5, |
num_five_star_rows = 4; |
CGFloat start_x = 5.0,// 1 |
start_y = 108.0,// 2 |
red_stripe_spacing = 34.0,// 3 |
h_spacing = 26.0,// 4 |
v_spacing = 22.0;// 5 |
CGContextRef myLayerContext1, |
myLayerContext2; |
CGLayerRef stripeLayer, |
starLayer; |
CGRect myBoundingBox,// 6 |
stripeRect, |
starField; |
// ***** Setting up the primitives ***** |
const CGPoint myStarPoints[] = {{ 5, 5}, {10, 15},// 7 |
{10, 15}, {15, 5}, |
{15, 5}, {2.5, 11}, |
{2.5, 11}, {16.5, 11}, |
{16.5, 11},{5, 5}}; |
stripeRect = CGRectMake (0, 0, 400, 17); // stripe// 8 |
starField = CGRectMake (0, 102, 160, 119); // star field// 9 |
myBoundingBox = CGRectMake (0, 0, contextRect->size.width, // 10 |
contextRect->size.height); |
// ***** Creating layers and drawing to them ***** |
stripeLayer = CGLayerCreateWithContext (context, // 11 |
stripeRect.size, NULL); |
myLayerContext1 = CGLayerGetContext (stripeLayer);// 12 |
CGContextSetRGBFillColor (myLayerContext1, 1, 0 , 0, 1);// 13 |
CGContextFillRect (myLayerContext1, stripeRect);// 14 |
starLayer = CGLayerCreateWithContext (context, |
starField.size, NULL);// 15 |
myLayerContext2 = CGLayerGetContext (starLayer);// 16 |
CGContextSetRGBFillColor (myLayerContext2, 1.0, 1.0, 1.0, 1);// 17 |
CGContextAddLines (myLayerContext2, myStarPoints, 10);// 18 |
CGContextFillPath (myLayerContext2); // 19 |
// ***** Drawing to the window graphics context ***** |
CGContextSaveGState(context); // 20 |
for (i=0; i< 7; i++) // 21 |
{ |
CGContextDrawLayerAtPoint (context, CGPointZero, stripeLayer);// 22 |
CGContextTranslateCTM (context, 0.0, red_stripe_spacing);// 23 |
} |
CGContextRestoreGState(context);// 24 |
CGContextSetRGBFillColor (context, 0, 0, 0.329, 1.0);// 25 |
CGContextFillRect (context, starField);// 26 |
CGContextSaveGState (context); // 27 |
CGContextTranslateCTM (context, start_x, start_y); // 28 |
for (j=0; j< num_six_star_rows; j++) // 29 |
{ |
for (i=0; i< 6; i++) |
{ |
CGContextDrawLayerAtPoint (context,CGPointZero, |
starLayer);// 30 |
CGContextTranslateCTM (context, h_spacing, 0);// 31 |
} |
CGContextTranslateCTM (context, (-i*h_spacing), v_spacing); // 32 |
} |
CGContextRestoreGState(context); |
CGContextSaveGState(context); |
CGContextTranslateCTM (context, start_x + h_spacing/2, // 33 |
start_y + v_spacing/2); |
for (j=0; j< num_five_star_rows; j++) // 34 |
{ |
for (i=0; i< 5; i++) |
{ |
CGContextDrawLayerAtPoint (context, CGPointZero, |
starLayer);// 35 |
CGContextTranslateCTM (context, h_spacing, 0);// 36 |
} |
CGContextTranslateCTM (context, (-i*h_spacing), v_spacing);// 37 |
} |
CGContextRestoreGState(context); |
CGLayerRelease(stripeLayer);// 38 |
CGLayerRelease(starLayer); // 39 |
} |
Вот то, что делает код:
Объявляет переменную для горизонтального расположения первой звезды.
Объявляет переменную для вертикального расположения первой звезды.
Объявляет переменную для интервала между красными дорожками на флаге.
Объявляет переменную для пространства по горизонтали между звездами на флаге.
Объявляет переменную для пространства по вертикали между звездами на флаге.
Объявляет прямоугольники, указывающие, где нарисовать флаг к (ограничительной рамке), уровню дорожки и звездообразному полю.
Объявляет массив точек, указывающих строки, прослеживающие одну звезду.
Создает прямоугольник, который является формой единственной дорожки.
Создает прямоугольник, который является формой звездообразного поля.
Создает ограничительную рамку, которая является тем же размером, как контекст графики окна передал
myDrawFlag
подпрограмма.Создает уровень, инициализирующийся с контекстом графики окна, переданным
myDrawFlag
подпрограмма.Связали графический контекст с тем уровнем. Вы будете использовать этот уровень для получения дорожки.
Устанавливает цвет заливки в непрозрачный красный для графического контекста, связанного с уровнем дорожки.
Заполняет прямоугольник, представляющий одну красную дорожку.
Создает другой уровень, инициализирующийся с контекстом графики окна, переданным
myDrawFlag
подпрограмма.Связали графический контекст с тем уровнем. Вы будете использовать этот уровень для звездообразного получения.
Устанавливает цвет заливки в непрозрачного белого для графического контекста, связанного со звездообразным уровнем.
Добавляют эти 10 строк, определенных
myStarPoints
выстройте к контексту, связанному со звездообразным уровнем.Заполняет путь, состоящий из этих 10 строк, которые Вы просто добавили.
Сохраняет состояние графики контекста графики окон. Необходимо сделать это, потому что Вы будете неоднократно рисовать ту же дорожку, но в различных расположениях.
Устанавливает цикл, выполняющий итерации 7 раз, один раз для каждой красной дорожки на флаге.
Рисует уровень дорожки (который состоит из единственной красной дорожки).
Переводит текущую матрицу преобразования так, чтобы источник был расположен в расположение, где должна быть нарисована следующая красная дорожка.
Восстанавливает состояние графики к тому, что, был до рисования дорожек.
Устанавливает цвет заливки в надлежащий оттенок синего цвета для звездообразного поля. Обратите внимание на то, что этот цвет имеет непрозрачность 1,0. Несмотря на то, что все цвета в этом примере непрозрачны, они не должны быть. Можно создать хорошие эффекты с многоуровневым получением при помощи частично прозрачных цветов. Вспомните, что альфа-значение 0,0 указывает прозрачный цвет.
Заполняет звездообразный полевой прямоугольник синим. Вы рисуете этот прямоугольник непосредственно к контексту графики окна. Не используйте уровни при рисовании чего-то только один раз.
Сохраняет состояние графики для контекста графики окна, потому что Вы будете преобразовывать CTM для расположения звезд должным образом.
Переводит CTM так, чтобы источник нашелся в звездообразном поле, расположенном для первой звезды (левая сторона) в первом (нижняя часть) строка.
Это и следующее для цикла устанавливают код для повторного рисования звездообразного уровня так пять нечетных строк на флаге, каждый содержит шесть звезд.
Рисует звездообразный уровень к контексту графики окна. Вспомните, что звездообразный уровень содержит одну белую звезду.
Располагает CTM так, чтобы источник был перемещен вправо в подготовке к рисованию следующей звезды.
Располагает CTM так, чтобы источник был перемещен вверх в подготовке к рисованию следующей строки звезд.
Переводит CTM так, чтобы источник нашелся в звездообразном поле, расположенном для первой звезды (левая сторона) во второй строке от нижней части. Обратите внимание на то, что ровные строки смещаются относительно нечетных строк.
Это и следующее для цикла устанавливают код для повторного рисования звездообразного уровня так четыре даже строки на флаге, каждый содержит пять звезд.
Рисует звездообразный уровень к контексту графики окна.
Располагает CTM так, чтобы источник был перемещен вправо в подготовке к рисованию следующей звезды.
Располагает CTM так, чтобы источник снизился и налево в подготовке к рисованию следующей строки звезд.
Выпускает уровень дорожки.
Выпускает звездообразный уровень.