Lulucat

Dua Pemadam, dan Mengapa Pemadaman Milik Sapuan

Gaoge ZhangGaoge Zhang

Menjadikan sapuan pemadam sebagai elemen tersendiri nampak jelas, tetapi pergerakan objek merosakkannya. Dalam Lulucat Notes, pemadaman dimiliki oleh sapuan yang dakwatnya dipadam.

Dikemas kini

Apabila orang memadam dalam buku nota, mereka boleh bermaksud dua perkara yang berbeza. Kadangkala sesuatu tanda itu salah dan seluruh tanda tersebut perlu dibuang: garis panduan, perkataan yang dicoret, atau sapuan tersasar daripada tapak tangan yang sedang bersandar. Kadangkala hanya sebahagian tanda yang salah: separuh aksara, satu cabang gambar rajah, atau ekor sapuan penyerlah yang terlanjur melepasi ayat. Kini Lulucat Notes menyediakan kedua-duanya sebagai dua alat yang berasingan.

Soalan reka bentuk yang lebih sukar ialah di manakah pemadaman itu berada.

Pemadam sapuan muncul dahulu

Pemadam pertama membuang seluruh sapuan. Setiap sentuhan menguji semua sapuan: kotak sempadan menolak hampir kesemuanya, dan sapuan yang terselamat menjalani ujian jarak kuasa dua titik-ke-segmen terhadap jejari pemadam ditambah jejari sapuan yang diinterpolasi sepanjang segmen itu. Lebar berubah mengikut tekanan, jadi satu lebar nominal akan membuang sapuan nipis yang tidak disentuh pengguna dan terlepas daripada sapuan tebal yang disentuhnya.

Satu gerak digabungkan menjadi satu entri buat asal, dan entri itu menyimpan setiap sapuan yang dibuang bersama indeks asalnya. Buat asal memasukkannya semula dalam susunan terbalik, jadi susunan tindanan kembali tepat seperti asal.

Pemadam ini pantas, boleh dijangka, tetapi tidak mampu membuang separuh perkataan.

MaLiang menjadikan pemadam sebuah berus

MaLiang, rangka kerja lukisan berlesen MIT yang model cap penyerlahnya telah kami pinjam sebelum ini, menyelesaikan pemadaman separa dalam 24 baris. Eraser ialah subkelas Brush yang mengatasi satu perkara sahaja, iaitu pilihan pengadunan, untuk menolak dan bukannya menambah. Sapuan pemadam ialah satu elemen dalam senarai yang sama dengan setiap sapuan lain. Buat asal membuang elemen tersebut. Tiada sapuan sedia ada diubah, kerana pemadaman hanya berlaku semasa main semula mengikut susunan senarai.

Kami menghantar model itu, lalu dua sesi pada peranti membuatnya gagal.

Pergerakan objek mendedahkan pemilik yang hilang

Laporan pertama: pilih sapuan dengan laso, seret sapuan itu, dan lubangnya kekal di belakang.

Empat panel membandingkan dua model pemadam sebelum dan selepas sapuan digerakkan. Apabila pemadam ialah elemennya sendiri, jurang kekal pada kedudukan lama; apabila pemadaman dimiliki oleh sapuan, jurang bergerak bersama dakwat.

Sapuan yang sama dan telah dipadam, digerakkan ke kanan. Atas: pemadam ialah elemennya sendiri. Bawah: pemadaman milik sapuan.

Pemilihan menjadikannya lebih buruk. Sapuan yang dipilih dikeluarkan daripada bitmap ke dalam tindanan yang melukisnya terus, tanpa elemen pemadam, jadi sebaik sahaja anda memilih sapuan yang telah dipadam, sapuan itu kelihatan utuh semula.

Laporan kedua: pemadam terapung di atas penyerlah. Perender kami memainkan semula dalam dua pas, penyerlah dahulu dan pen kedua, kerana dakwat penyerlah mesti berada di bawah dakwat. Elemen pemadam perlu menyertai kedua-dua pas, jika tidak ia tidak dapat memadam kedua-dua jenis dakwat. Menyertai pas pen bermakna ia berjalan selepas setiap penyerlah dilukis, jadi pemadam turut memotong sapuan penyerlah yang dilukis kemudian mengikut masa.

Kedua-dua kegagalan itu berpunca daripada perkara yang sama. MaLiang tidak mempunyai laso, pergerakan atau susunan lapisan antara berus, jadi elemen tanpa pemilik sudah memadai di situ. Kanvas kami mempunyai ketiga-tiganya, dan pemadaman tanpa pemilik tidak mempunyai jawapan yang ditakrifkan untuk soalan “apa yang berlaku apabila dakwat bergerak” atau “lapisan manakah yang sedang dikendalikan.”

Pemadaman dimiliki oleh sapuan

Setiap Stroke kini membawa laluan pemadamannya sendiri. Pemadam menguji sapuan mana yang disentuhnya lalu menambahkan satu laluan pada setiap sapuan itu, dalam koordinat kanvas. Apabila satu sapuan dirender, dakwatnya dan pemadamannya sendiri dilukis di dalam lapisan ketelusan:

context.beginTransparencyLayer(auxiliaryInfo: nil)
drawInk(stroke, in: context, clip: clip, colorOverride: colorOverride)
context.setBlendMode(.destinationOut)
for path in stroke.erasePaths { fillErasePath(path, in: context) }
context.endTransparencyLayer()

Destination-out mengekalkan destinasi dan membuangnya mengikut kadar alfa sumber:

Di dalam lapisan ketelusan, destinasi ialah sapuan itu sahaja, jadi operasi ini tidak dapat mencapai kertas, sapuan di bawahnya atau sapuan yang dilukis kemudian. Lapisan itu tidak menambah kos bagi sapuan tanpa pemadaman, iaitu hampir semuanya: sapuan tersebut menggunakan laluan asal.

Pemilikan menjawab kedua-dua kegagalan itu secara langsung. Translasi menggerakkan laluan pemadaman bersama titik sampel, jadi sapuan yang digerakkan membawa jurangnya. Tindanan pilihan melukis objek sapuan yang sama, jadi sapuan yang dipilih menunjukkan jurang yang sama. Susunan lapisan tidak lagi penting, kerana pemadaman tidak pernah dikenakan pada apa-apa selain sapuannya sendiri.

Buat asal berfungsi pada tahap gerak: satu entri menyenaraikan setiap pasangan (stroke, path) yang dihasilkan oleh gerak tersebut, buat asal membuang laluan itu dan buat semula menambahkannya sekali lagi. Dakwat di bawah pemadaman tidak pernah disunting, jadi tiada apa-apa yang perlu dibina semula.

Maklum balas langsung melalui bitmap tile

Sapuan yang sedang dilukis biasanya dirender sebagai tindanan di atas halaman yang telah dikompositkan. Pemadaman tidak boleh berfungsi di situ, kerana tindanan itu berada di atas kertas dan dakwat, dan destination-out akan menebuk kertas.

Jadi pemadam menulis terus ke dalam sapuan, dan setiap kelompok sampel baharu mencetuskan main semula setempat hanya bagi segi empat tepat yang terjejas. Tile pipeline sudah mengosongkan satu segi empat tepat dan memainkan semula sapuan yang bersilang dengannya; pemadam menggunakan semula laluan itu dan tidak menambah semantik lukisan kedua.

Kedua-dua pemadam, bersebelahan

Bar alat mempunyai dua butang pemadam, bukannya satu butang dengan mod tersembunyi. Pemadam separa membuang sebahagian sapuan. Pemadam sapuan membuang seluruh sapuan apabila bersentuhan. Jejari kedua-duanya ialah pemalar berasingan, dan kedua-duanya kini 4 points.

Memadam seluruh sapuan turut membawa keluar laluan pemadamannya kerana laluan itu sebahagian daripada sapuan tersebut, dan buat asal mengembalikan kedua-duanya bersama. Laluan pemadaman juga sebahagian daripada fail yang disimpan, dikuantiskan seperti segala yang lain: jejari dan koordinat dalam persepuluh point.

Satu batasan masih ada. Sapuan yang dipadam sehingga tiada apa-apa masih wujud sebagai data. Ia dirender sebagai tiada apa-apa, tetapi laso masih boleh memilihnya dan pemadam sapuan masih boleh memadamnya, dan ia masih menggunakan ruang dalam dokumen. Mengumpulkan sapuan yang dipadam sepenuhnya memerlukan ujian liputan yang belum kami tulis, jadi buat masa ini sapuan itu dikekalkan.

Apabila model daripada projek lain berhenti berfungsi dalam projek anda, perbezaannya biasanya bukan pada kod yang anda salin. Perbezaannya terletak pada ciri-ciri yang tidak dimiliki oleh projek tersebut.