UIBezierPath рендерит часть в прямоугольнике клипа только при рисовании из drawRect/draw представления (_:)?

Я работаю над тестовой программой для рисования рисунков произвольной формы, сглаженных с помощью сплайнов Catmull-Rom. (ссылка) См. "Поваренную книгу " Эрики Садун, разработанную Core iOS Developer для получения "рецепта", показывающего, как рисовать плавные кривые, используя сплайны Catmull-Rom. (Раскрытие информации: я был техническим обозревателем нескольких книг доктора Садуна.)

Образец кода доктора Садуна, написанный на Objective-C, рисует серию отрезков между точками ввода, когда пользователь проводит пальцем, и сглаживает кривую, только когда он отпускает палец.

Я переработал код в Swift 3.

Я также изменил алгоритм так, чтобы он генерировал плавные кривые "вживую", когда пользователь рисует. Выходные данные алгоритма сглаживания представляют собой серию точек, которые необходимо соединить с крошечными отрезками, чтобы создать вид плавной кривой.

Я преобразовываю полученную "полилинию" в UIBezierPath и рисую ее в методе drawRect моего пользовательского подкласса UIView.

Я обнаружил, что математика для создания плавных кривых на самом деле очень быстрая. То, что отнимает много времени, это рисование большого, сложного UIBezierPath, Когда вы добавляете новую точку в массив входных точек, которые сглаживаются, последняя часть кривой должна быть изменена, чтобы создать плавную кривую вокруг предыдущей контрольной точки, а не "излом".

В результате самое простое, что нужно сделать - просто нарисовать весь путь Безье в каждом вызове DrawRect. Тем не менее, по мере увеличения объекта Bezier Path приложение тратит все больше времени на обслуживание drawRect()и поэтому отслеживание пути пальца пользователя становится все более и более вялым, а точки, которые он регистрирует по движениям пользователя, становятся все дальше и дальше друг от друга.

Я реализовал ряд оптимизаций. Один из тех, чтобы позвонить setNeedsDisplayInRect() (Или скорее setNeedsDisplay(_:), поскольку это Swift 3), чтобы отметить только небольшую часть вида, которая фактически изменилась как нуждающаяся в перерисовке.

Я был удивлен, обнаружив, что мой drawRect() (Эр, draw(_:) функция теперь очень быстрая и больше не застревает.

Кажется, что рендеринг UIBezierPath Объекты в drawRect() оптимизированы так, что он пропускает части пути, которые находятся за пределами "грязной области" представления (области клипа, которая фактически нуждается в обновлении.)

Это удивило меня. Я ожидал отказаться от рисования с UIBezierPath и написать собственный код, который нашел части моего рисунка, которые пересекают текущую область клипа, но похоже, что мне не нужно будет этого делать.

Может кто-нибудь подтвердить, что рисование Quartz оптимизирует отрисовку UIBezierPaths внутри метода drawrect() представления, чтобы они эффективно отображали только части пути, которые пересекают текущую обтравочную маску?

0 ответов

Другие вопросы по тегам