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를 사용하여 StockBrushes 계열과 마찬가지로 특정 색상과 크기의 새 Brush를 만들 수 있습니다.
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
)