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())

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

แม้ว่า StockBrushes จะมีชุดแปรงทั่วไปที่หลากหลาย แต่ Ink API ก็ยังมีเส้นทางขั้นสูงสำหรับการสร้างลักษณะการทำงานของแปรงใหม่ทั้งหมด เพื่อเอฟเฟกต์ศิลปะที่ไม่เหมือนใคร หรือเพื่อจำลองแปรงที่มีอยู่ เพื่อความเข้ากันได้แบบย้อนหลัง

ระบบจะโหลด BrushFamily ที่กำหนดเองจากรูปแบบที่แปลงเป็นอนุกรม รูปแบบที่จำเป็น คือการเข้ารหัสไบนารีที่บีบอัดด้วย gzip ของ บัฟเฟอร์โปรโตคอล BrushFamily ซึ่งจะช่วยให้คุณโหลดและใช้ ไฟล์แปรงที่กำหนดเองได้แล้ววันนี้ เมื่อเลิกซีเรียลไลซ์แล้ว คุณจะใช้ 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
)