Brush API

Brush API는 획의 시각적 스타일을 정의하는 도구를 제공합니다. 다양한 색상, 크기, 패밀리를 사용하여 브러시를 만들어 다양한 모양을 만들 수 있습니다.

브러시 만들기

브러시를 만들려면 Compose Brush 컴패니언 메서드를 Brush.Companion.createWithComposeColor과 같은 이름이 지정된 인수와 함께 사용합니다. 이 클래스를 사용하면 다음 속성을 설정할 수 있습니다.

  • family: 브러시의 스타일입니다. 텍스트의 서체 또는 글꼴과 유사합니다. 사용 가능한 BrushFamily 값은 StockBrushes을 참고하세요.
  • color: 브러시의 색상입니다. ColorLong를 사용하여 색상을 설정할 수 있습니다.
  • size: 브러시로 만든 획의 전체 두께입니다.
  • epsilon: 획 생성 도형 목적으로 두 점이 시각적으로 구별되는 것으로 간주되어야 하는 가장 작은 거리입니다. 엡실론과 획 포인트의 비율은 메모리 비용을 지불하고 아티팩트 없이 획을 얼마나 확대할 수 있는지를 제어합니다. 획 단위의 적절한 시작점은 1px이고, 입실론의 적절한 시작점은 0.1입니다. 엡실론 값이 높을수록 메모리 사용량이 줄어들지만 삼각형 아티팩트가 표시되기 전에 확대/축소할 수 있는 정도가 줄어듭니다. 실험을 통해 사용 사례에 적합한 값을 찾습니다.
val brush = Brush.createWithComposeColor(
  family = StockBrushes.pressure(),
  colorIntArgb = Color.Black,
  size = 5F,
  epsilon = 0.1F
)

브러시 속성 수정

copyWithComposeColor() 메서드를 사용하여 기존 브러시의 사본을 만들 수 있으며, 이를 통해 브러시의 속성을 변경할 수 있습니다.

val redBrush = Brush.createWithComposeColor(
  family = StockBrushes.pressurePen(),
  colorIntArgb = Color.RED,
  size = 5F,
  epsilon = 0.1F
)

val blueBrush = redBrush.copyWithComposeColor(color = Color.BLUE)

맞춤 브러시

虽然 StockBrushes 提供了一组通用的多功能笔刷,但 Ink API 还提供了一种高级方法,用于创建全新的笔刷行为,以实现独特的艺术效果,或复制特定的现有笔刷以实现向后兼容性。

自定义 BrushFamily 从其序列化格式加载。所需格式为 BrushFamily 协议缓冲区的 gzip 压缩二进制编码。这样一来,您就可以立即加载和使用自定义笔刷文件。反序列化后,自定义 BrushFamily 可用于创建具有特定颜色和大小的新 Brush,就像任何 StockBrushes 系列一样。

class CustomBrushes(val context: Context) {

  private const val TAG = "CustomBrushes"

  val brushes by lazy { loadCustomBrushes(context) }

  @OptIn(ExperimentalInkCustomBrushApi::class)
  private fun loadCustomBrushes(): List<CustomBrush> {
    val brushFiles = mapOf(
        "Calligraphy" to (R.raw.calligraphy to R.drawable.draw_24px),
        "Flag Banner" to (R.raw.flag_banner to R.drawable.flag_24px),
        "Graffiti" to (R.raw.graffiti to R.drawable.format_paint_24px),
    // ...
    )

    val loadedBrushes = brushFiles.mapNotNull { (name, pair) ->
      val (resourceId, icon) = pair
      val brushFamily = context.resources.openRawResource(resourceId).use
      { inputStream ->
          BrushFamily.decode(inputStream)
      }
      CustomBrush(name, icon, brushFamily.copy(clientBrushFamilyId = name))     
    }
    return loadedBrushes
  }
}

data class CustomBrush(
  val name: String,
  val icon: Int,
  val brushFamily: BrushFamily
)