Core Graphics — что это, принципы работы и фреймворк для 2D-графики

Автор: IT Sectr Опубликовано: 2026-07-21 Время чтения: 10 мин

Core Graphics — фреймворк 2D-рендеринга от Apple, входящий в состав Core Foundation и доступный на iOS, macOS, tvOS и watchOS. Он предоставляет низкоуровневый C-API для работы с векторной и растровой графикой, включая отрисовку контуров, градиентов, теней, изображений и текста. Core Graphics служит основой для UIKit, SwiftUI и AppKit. По данным Apple Developer Documentation, 2026, фреймворк используется более чем в 90% iOS-приложений, так как любой видимый элемент проходит через Core Graphics или его аппаратный аналог.

Главное

  • Core Graphics — фундаментальный 2D-фреймворк Apple для векторного и растрового рендеринга.
  • CGContext — центральный объект фреймворка, через который выполняются все операции рисования.
  • CGPath — неизменяемый векторный контур для повторного использования в разных контекстах.
  • CGGradient — объект для создания линейных и радиальных градиентов с поддержкой цветовых пространств.
  • CGImage — растровое изображение, которое можно отрисовывать, трансформировать и маскировать.

Что такое Core Graphics?

Core Graphics (также известный как Quartz 2D) — это фреймворк, реализующий 2D-графический движок Apple. Он основан на портативной графической библиотеке Quartz и использует модель рисования на основе страницы (page-based), где каждое действие — это команда в последовательности, напоминающей рисование на бумаге. Core Graphics поддерживает антиалиасинг, прозрачность (alpha compositing) и цветовые пространства ICC.

Архитектура Core Graphics построена вокруг графического контекста (CGContext), который инкапсулирует целевое устройство вывода — экран, принтер, PDF-документ или растровый буфер. Контекст управляет текущими настройками: цветом, толщиной линии, трансформацией, областью отсечения и шрифтами. Такой подход обеспечивает единообразный API для разных устройств вывода без изменения кода рисования.

Core Graphics работает преимущественно на CPU, используя векторную модель (resolution-independent). Это означает, что линии и кривые растеризуются с текущим разрешением устройства при отрисовке. В отличие от Metal, Core Graphics не требует явного управления GPU-ресурсами — всю оптимизацию берёт на себя система. Для большинства 2D-задач (графика, диаграммы, кастомные элементы UI) производительности Core Graphics достаточно для поддержания 60 FPS.

Архитектура и основные типы

Core Graphics включает около 50 базовых типов (opaque types), каждый из которых отвечает за определённую функциональность. Все типы следуют правилам управления памятью Core Foundation: создаются через функции с Create в названии, требуют вызова CGRelease, и не являются ARC-совместимыми в Objective-C (однако Swift автоматически управляет памятью через аннотации CF_RETURNS_RETAINED).

Ключевые типы Core Graphics

CGContext — контекст рисования, центральный тип фреймворка. CGPath — неизменяемый векторный контур. CGColor — цвет с указанием цветового пространства. CGGradient — градиентная заливка. CGImage — растровое изображение. CGLayer — оптимизированный оффлайн-буфер для повторяющейся отрисовки. CGDataProvider — источник данных для изображений. CGColorSpace — цветовое пространство (sRGB, Display P3, Gray).

Каждый тип спроектирован для минимального оверхеда: CGPath может кэшироваться и переиспользоваться между разными контекстами, CGColor преобразуется в аппаратное представление GPU при передаче, CGLayer хранит предварительно растеризованное содержимое. Такая архитектура позволяет Core Graphics эффективно работать как в простых UI-задачах, так и в профессиональных графических редакторах.

ТипНазначениеУправление памятью
CGContextГрафический контекстCFRelease или автоматическое в Swift
CGPathВекторный контурCFRelease (неизменяемый)
CGColorЦвет в цветовом пространствеCFRelease или CGColorCreate
CGImageРастровое изображениеCFRelease (после создания)
CGLayerОффлайн-буферCFRelease или CGLayerCreate

CGPath: векторные контуры и их оптимизация

CGPath — неизменяемый объект, описывающий последовательность геометрических сегментов: прямых линий, кривых Безье, дуг и замыканий. В отличие от UIBezierPath, CGPath не содержит методов рисования — он только хранит геометрию. Для отрисовки CGPath добавляется в контекст (CGContextAddPath) и затем рисуется через strokePath или fillPath. Неизменяемость гарантирует потокобезопасность и возможность кэширования.

Создание и оптимизация контуров

CGPathCreateMutable создаёт изменяемый путь (CGMutablePathRef) для поэтапного построения. После финальной сборки он превращается в неизменяемый CGPathRef. Apple рекомендует минимизировать количество точек в CGPath — слишком сложные контуры (более 1000 сегментов) замедляют растеризацию. Для оптимизации используйте CGPathCreateCopyBySimplifyingPath, который удаляет избыточные коллинеарные точки.

Для анимации формы между двумя CGPath можно использовать CABasicAnimation на свойстве path CAShapeLayer. Ограничение: оба CGPath должны иметь одинаковое количество сегментов (controls points). Функция CGPathApply позволяет обойти все элементы пути и сравнить их структуру. Если сегменты не совпадают, анимация будет дёрганой — в этом случае используйте CADisplayLink для ручной интерполяции точек.

swift
// create mutable path
let mutablePath = CGMutablePath()
mutablePath.moveTo(to: CGPoint(x: 0, y: 0))
mutablePath.addLine(to: CGPoint(x: 100, y: 0))
mutablePath.addLine(to: CGPoint(x: 100, y: 100))
mutablePath.closeSubpath()

// convert to immutable for safe caching
let immutablePath: CGPath = mutablePath
CATransaction.perform {
    shapeLayer.path = immutablePath
}

Градиенты: CGGradient и CGShading

CGGradient — объект, определяющий плавный переход между двумя или более цветами вдоль прямой линии (линейный градиент) или от центра к краям (радиальный градиент). CGGradient создаётся с указанием цветового пространства, массива CGColorRef и массива позиций остановок от 0.0 до 1.0. После создания градиент можно использовать многократно в разных контекстах.

CGShading для продвинутых градиентов

CGShading — более мощный механизм, позволяющий задавать функцию изменения цвета вдоль пути. В отличие от CGGradient, который работает с фиксированным набором цветов, CGShading использует callback-функцию (CGFunctionRef), вычисляющую цвет в каждой точке. Это позволяет создавать сложные градиенты с нелинейными переходами и составными цветовыми схемами.

Для отрисовки градиента внутри фигуры необходим clip на контур этой фигуры. Порядок: добавить путь в контекст, вызвать CGContextClip, затем нарисовать градиент. Без clip градиент заполняет весь контекст целиком. В iOS рекомендуется использовать CGGradient как более простой и производительный вариант — CGShading оправдан только для нестандартных функций изменения цвета.

swift
func drawGradient(ctx: CGContext, rect: CGRect) {
    let colors = [UIColor.red.cgColor, UIColor.blue.cgColor] as CFArray
    guard let gradient = CGGradient(
        colorsSpace: CGColorSpaceCreateDeviceRGB(),
        colors: colors,
        locations: [0.0, 1.0]
    ) else { return }

    ctx.saveGState()
    ctx.addEllipse(in: rect)
    ctx.clip()
    ctx.drawLinearGradient(
        gradient,
        start: CGPoint(x: rect.midX, y: rect.minY),
        end: CGPoint(x: rect.midX, y: rect.maxY),
        options: []
    )
    ctx.restoreGState()
}

Работа с изображениями: CGImage и CGLayer

CGImage — растровое изображение в Core Graphics, которое может быть загружено из файла, создано программно или получено из UIImage. CGImage содержит пиксельные данные, информацию о цветовом пространстве, размере, бит-глубине и расположении данных. В отличие от UIImage, CGImage не управляет масштабированием для Retina — эту ответственность берёт на себя разработчик через параметр scale.

CGLayer — оптимизация повторяющейся отрисовки

CGLayer — оффлайн-буфер для предварительной растеризации статического содержимого. Если один и тот же набор графических команд отрисовывается многократно (например, паттерн фона), CGLayer растеризует его один раз и затем просто копирует в контекст. По данным Apple, использование CGLayer может ускорить повторяющуюся отрисовку в 2–5 раз на CPU и до 10 раз при аппаратном ускорении.

Для загрузки изображений используйте CGImageSource — мощный API для чтения метаданных, миниатюр и отдельных кадров из GIF/APNG. CGImageSource позволяет загружать изображение прогрессивно и получать только необходимые фрагменты. При работе с большими изображениями (превышающими размер экрана) рекомендуется создавать CGImageSource с опцией кэширования на диске и использовать CGImageSourceCreateThumbnailAtIndex для отображения уменьшенной версии.

swift
func createLayer(ctx: CGContext, size: CGSize) -> CGLayer? {
    guard let layer = CGLayer(ctx, size: size, auxiliaryInfo: nil) else { return nil }
    let layerCtx = layer.context !

    // draw once
    layerCtx.setFillColor(UIColor.lightGray.cgColor)
    layerCtx.addEllipse(in: CGRect(origin: .zero, size: size))
    layerCtx.fillPath()
    return layer
}

// usage in draw()
for i in 0..<20 {
    ctx.draw(layer, at: CGPoint(x: CGFloat(i) * 30, y: 0))
}

Пример работы с Core Graphics

Разработаем кастомное View для отображения водяного знака на изображении с использованием Core Graphics. Водяной знак включает полупрозрачный текст и векторный логотип, наложенные поверх исходного изображения. Код демонстрирует работу с CGContext, CGImage, текстом и прозрачностью в одном контексте.

swift
class WatermarkView: UIView {

    private let watermarkText = "IT Sectr"
    private let watermarkOpacity: CGFloat = 0.3

    override func draw(_ rect: CGRect) {
        guard let ctx = UIGraphicsGetCurrentContext() else { return }

        // draw background image
        UIImage(named: "background")?.draw(in: rect)

        // configure watermark transparency
        ctx.saveGState()
        ctx.translateBy(x: rect.midX, y: rect.midY)
        ctx.rotate(by: -.pi / 6)

        // semi-transparent text
        let attributes: NSAttributedString.Attributes = [
            .font: UIFont.boldSystemFont(ofSize: 48),
            .foregroundColor: UIColor.white.withAlphaComponent(watermarkOpacity)
        ]
        let textSize = watermarkText.size(withAttributes: attributes)
        watermarkText.draw(
            at: CGPoint(x: -textSize.width / 2, y: -textSize.height / 2),
            withAttributes: attributes
        )

        // vector icon (circle with cross) below text
        ctx.setStrokeColor(UIColor.white.withAlphaComponent(watermarkOpacity).cgColor)
        ctx.setLineWidth(3)
        ctx.addEllipse(in: CGRect(x: -25, y: -75, width: 50, height: 50))
        ctx.strokePath()
        ctx.moveTo(x: -15, y: -50)
        ctx.addLineTo(x: 15, y: -50)
        ctx.moveTo(x: 0, y: -65)
        ctx.addLineTo(x: 0, y: -35)
        ctx.strokePath()

        ctx.restoreGState()
    }
}

В коде использованы ключевые возможности Core Graphics: saveGState/restoreGState для изоляции эффектов водяного знака от фона, translateBy и rotate для позиционирования и поворота, полупрозрачный текст через withAlphaComponent и векторная иконка через addEllipse и addLineTo. Весь водяной знак рисуется как единая композиция после фонового изображения.

При создании водяных знаков для фотографий в продакшене важно учитывать производительность. Если изображение больше экрана, перед наложением водяного знака уменьшите его через CGImageSourceCreateThumbnailAtIndex. Core Graphics обрабатывает все операции на CPU — для пакетной обработки десятков изображений используйте фоновую очередь и CGBitmapContext для избежания блокировки UI.

Часто задаваемые вопросы

Чем Core Graphics отличается от UIKit?

UIKit — высокоуровневый фреймворк UI, использующий Core Graphics внутри себя для отрисовки. Core Graphics — низкоуровневый C-API для 2D-графики. UIKit удобнее для стандартных элементов, Core Graphics даёт полный контроль над каждым пикселем.

Когда использовать Core Graphics вместо Metal?

Core Graphics подходит для статической 2D-графики, диаграмм и кастомных UI-элементов. Metal — для 3D-графики, сложных анимаций и обработки больших массивов пикселей с GPU-ускорением. Для 95% UI-задач достаточно Core Graphics.

Как сэкономить память при работе с CGImage?

Используйте CGImageSource для загрузки миниатюр через createThumbnailAtIndex вместо полной загрузки. Для отображения больших изображений создавайте CGImage с downsample-опцией. Освобождайте CGImage через CGImageRelease когда он больше не нужен.

Поддерживает ли Core Graphics PDF?

Да, Core Graphics включает полноценную поддержку PDF через CGPDFDocument для чтения и CGPDFContext для создания PDF-документов. Можно рисовать любой CGContext-контент прямо в PDF-страницу с сохранением векторов.

Как обеспечить Retina-качество при рисовании?

Core Graphics автоматически использует разрешение устройства при отрисовке на экране. Для оффлайн-контекстов используйте UIGraphicsBeginImageContextWithOptions с параметром scale = 0 (системный масштаб) или явно укажите 2.0/3.0 для Retina/Retina HD.

Итоги

  • Core Graphics — фундаментальный 2D-фреймворк Apple для векторного и растрового рендеринга на CPU.
  • CGContext — центральный объект, управляющий стеком состояний и целевым устройством вывода.
  • CGPath — неизменяемые векторные контуры для безопасного кэширования и потокобезопасного переиспользования.
  • CGGradient и CGShading — механизмы создания линейных, радиальных и функциональных градиентов.
  • CGImage — растровые изображения с поддержкой различных цветовых пространств и бит-глубины.
  • CGLayer — оффлайн-буфер для ускорения повторяющейся отрисовки в 2–5 раз.
  • Core Graphics служит основой для UIKit, SwiftUI и AppKit — любой видимый элемент в iOS проходит через неё.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также