Brush API

API ของ Ink Brush ช่วยให้คุณสร้างและปรับแต่งพู่กันเพื่อวาดบน Canvas ได้

สร้างแปรง

หากต้องการสร้างแปรง ให้ใช้เมธอดของ Factory Brush พร้อมอาร์กิวเมนต์ที่มีชื่อ เช่น Brush.createWithColorLong() คลาสนี้ ช่วยให้คุณตั้งค่าพร็อพเพอร์ตี้ต่อไปนี้ได้

  • family: รูปแบบของแปรง ซึ่งคล้ายกับแบบตัวพิมพ์หรือแบบอักษรในข้อความ ดูค่า StockBrushes ที่ใช้ได้ของ BrushFamily
  • color: สีของแปรง คุณตั้งค่าสีได้โดยใช้ ColorLong
  • size: ความหนาพื้นฐานของเส้นที่สร้างด้วยแปรง
  • epsilon: ระยะทางที่สั้นที่สุดซึ่งจุด 2 จุดในเส้นต้องถือว่าแตกต่างกัน ซึ่งควบคุมระดับรายละเอียดหรือความเที่ยงตรงของรูปทรงของเส้น
    • ค่าที่สูงขึ้นจะทำให้เส้นเรียบง่ายขึ้น ซึ่งใช้หน่วยความจำน้อยลงและแสดงผล เร็วขึ้น แต่อาจทำให้เกิดอาร์ติแฟกต์ที่มองเห็นได้ เช่น ขอบหยัก เมื่อซูม เข้า
    • ค่าที่ต่ำกว่าจะคงรายละเอียดไว้มากขึ้นสำหรับการซูมคุณภาพสูง แต่จะเพิ่ม การใช้หน่วยความจำ
    • สำหรับต้นแบบที่มีมาตราส่วนหน่วย 1 พิกเซล จุดเริ่มต้นที่ดีคือ 0.1 สำหรับแอปเวอร์ชันที่ใช้งานจริงซึ่งรองรับความหนาแน่นของหน้าจอต่างๆ ให้ใช้หน่วยที่ไม่ขึ้นกับความหนาแน่น (เช่น dp) และปรับค่าเอปซิลอนตามนั้น
val redBrush = Brush.createWithColorLong(
  family = StockBrushes.pressurePen(),
  colorLong = Color.RED.pack(),
  size = 5F,
  epsilon = 0.1F
)

แก้ไขพร็อพเพอร์ตี้ของแปรง

คุณสามารถสร้างสำเนาของแปรงที่มีอยู่ได้โดยใช้วิธีcopy() วิธีนี้ช่วยให้คุณเปลี่ยนพร็อพเพอร์ตี้ใดก็ได้ ของแปรง

val blueBrush = redBrush.copy(colorLong = Color.BLUE.pack())

แปรงที่กำหนดเอง

While StockBrushes provides a versatile set of common brushes, Ink API also offers an advanced path for creating entirely new brush behaviors for unique artistic effects or to replicate specific existing brushes for backward compatibility.

A custom BrushFamily is loaded from its serialized format. The required format is the gzipped binary encoding of the BrushFamily protocol buffer. This lets you load and use custom brush files today. Once deserialized, the custom BrushFamily can be used to create a new Brush with a specific color and size, just like any of the StockBrushes families.

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
)