Как части конвейера рисования холста Android (2D) подходят друг к другу?


Я хотел бы иметь лучшее понимание того, как компоненты Android (2D) Canvas drawing pipeline подходят друг к другу.

например, как XferMode,шейдер,MaskFilter и ColorFilter взаимодействовать? Справочные документы для этих классов довольно редки, а документы для холст и краски не добавляйте никаких полезных объяснений.

Это тоже не совсем мне ясно, как рисовать операции, которые имеют внутренние цвета (например:drawBitmap, против" векторных " примитивов, таких как drawRect) вписывается во все это ... они всегда игнорируют Paintцвет и использование используйте их внутренний цвет вместо этого?

Я также был удивлен тем, что можно сделать что-то вроде этого:

Paint eraser = new Paint();
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawOval(rectF, eraser);

это стирает овал. Прежде чем я заметил это, моя ментальная модель заключалась в том, что рисунок на холсте (концептуально) рисует отдельный "слой", а затем этот слой состоит из растрового изображения холста с использованием режима переноса краски. Если бы это было так просто, то приведенный выше код стирал бы все растровое изображение (в пределах области отсечения) как CLEAR всегда устанавливает цвет (и Альфа) в 0 независимо от источника Альфа. Таким образом, это означает, что существует дополнительный вид маскировки, чтобы ограничить стирание до овала.

я нашел API demos но каждая демонстрация работает "в вакууме" и не показывает, как то, на чем он фокусируется (например: XferModes), взаимодействует с другими вещами (например: ColorFilters).

С достаточным количеством времени и усилий я мог бы эмпирически выяснить, как эти части связаны или идут расшифровать источник, но я надеюсь, что кто-то уже разработал это, или еще лучше, что есть какая-то фактическая документация трубопровода/чертежной модели, которую я пропустил.

этот вопрос был вдохновлен, увидев код в этом ответе на другой так вопрос.

обновление

пока я искал какую-то документацию, мне пришло в голову, что, поскольку многое из того, что меня интересует здесь, кажется довольно тонким шпоном поверх skia, может быть, есть какая-то документация skia, которая была бы полезна. Лучшее, что я мог найти это документация SkPaint он говорит:

есть 6 типов эффектов, которые могут назначается краска:

  • SkPathEffect-изменения геометрии (пути) перед ее созданием Альфа-Маска (например, лихой)
  • SkRasterizer-создание пользовательских слоев маски (например, тени)
  • SkMaskFilter-модификации Альфа-маски перед ее раскрашиванием и нарисовано (например, размытие, тиснение)
  • SkShader - например, градиенты (линейные, радиальные, развертки), растровые узоры (зажим, повтор, зеркало)
  • SkColorFilter-изменить исходный цвет(ы) перед применением xfermode (например, цветовая матрица)
  • SkXfermode-например, porter-duff transfermodes, режимы наложения

это не указано явно, но я предполагаю, что порядок эффектов здесь-это порядок, в котором они появляются в конвейере.

3 59

3 ответа:

как сказал Ромен Гай,"на этот вопрос трудно ответить на StackOverflow". На самом деле не было никакой полной документации, и полная документация была бы довольно большой, чтобы включить здесь.

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

а также эта схема:

http://xenomachina.com/android-canvas-pipeline.png

это "неофициально", очевидно, поэтому применяются обычные предостережения.

на основании вышеизложенного, вот ответы на некоторые из "под-вопросов":

мне тоже не совсем понятно как операции рисования, которые имеют встроенную цвета (например: drawBitmap против "векторные" примитивы вроде drawRect) вписывается во все это ... они всегда игнорируйте Paint'ы цвет и использовать их внутренний цвет вместо этого?

"исходные цвета" исходят от Shader. В drawBitmap the Shader временно заменить на BitmapShader, если неALPHA_8 это. В других случаях, если нет Shader не указан Shader это просто создает сплошной цвет,Paint ' S цвет, используется.

меня тоже удивил тот факт, что можно сделать что-то вроде этого:

Paint eraser = new Paint();
eraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawOval(rectF, eraser);

это стирает овал. Прежде чем я заметил это моя ментальная модель была тем рисунком к холсту (концептуально) обращается к отдельный "слой", а затем этот слой состоит из растрового изображения холста использование режима переноса краски. Если это были так же просто, как и выше код будет стереть все растровое изображение (в пределах области отсечения) как ясно всегда устанавливает цвет (и Альфа) в 0 независимо от источника альфа. Так это означает, что есть дополнительный вид маскировки продолжается ограничьте стирание до овала.

The XferMode применяется к "исходные цвета" (от Shader) и "цвета назначения" (от Canvas ' s Bitmap). Затем результат смешивается с назначением, используя маску, вычисленную в растеризации. См. этап передачи в вышеуказанном документе для получения более подробной информации.

на этот вопрос трудно ответить на StackOverflow. Однако прежде чем я начну, обратите внимание, что фигуры (например, drawRect ()) не имеют внутреннего цвета. Информация о цвете всегда исходит от объекта Paint.

Это стирает овал. Прежде чем я заметил это моя ментальная модель была тем рисунком к холсту (концептуально) обращается к отдельный "слой", а затем этот слой состоит из растрового изображения холста использование переноса краски режим. Если это были так же просто, как и выше код будет стереть все растровое изображение (в пределах области отсечения) как ясно всегда устанавливает цвет (и Альфа) в 0 независимо от источника Альфа. Так это означает, что есть дополнительный вид маскировки продолжается ограничьте стирание до овала.

ваша модель немного. Овал не рисуется в отдельный слой (если только вы не вызываете Canvas.saveLayer ()), он нарисован непосредственно на подложке холста растровый. Режим переноса краски применяется к каждому пикселю, нарисованному примитивом. В этом случае на растровое изображение влияет только результат растеризации овала. Там нет никакой специальной маскировки происходит, сам овал и маска.

во всяком случае, вот упрощенный вид конвейера:

  1. примитив (прямоугольник, овал, дорожка, так далее.)
  2. PathEffect
  3. растеризация
  4. MaskFilter
  5. Color / Shader / ColorFilter
  6. Xfermode

(Я только что видел ваше обновление и да, то, что вы нашли, описывает этапы конвейера по порядку.)

конвейер становится немного сложнее при использовании слоев (холст.saveLayer ()), так как трубопровод удваивается. Сначала вы проходите по конвейеру, чтобы отобразить свой примитив(ы) внутри закадровое растровое изображение (слой), а затем закадровое растровое изображение применяется к холсту, проходя через конвейер.

SkPathEffect-изменения геометрии (пути) перед созданием Альфа-маски (например, dashing) SkRasterizer-создание пользовательских слоев масок (например, теней) SkMaskFilter-модификации Альфа-маски перед ее раскрашиванием и отрисовкой (например, размытие) SkShader - например, градиенты (линейные, радиальные, развертки), растровые узоры (зажим, повтор, зеркало) SkColorFilter-измените исходный цвет(ы) перед применением xfermode (например, цветовая матрица) SkXfermode-например, porter-duff transfermodes, blend режимы

http://imgur.com/0X5Yqod