4 puan yazan GN⁺ 2024-12-04 | 1 yorum | WhatsApp'ta paylaş
  • Skia Canvas, Node.js’te HTML Canvas çizim API’sinin ekranda ve ekran dışında render edilmesini sağlar; Google Skia tabanlı olduğu için Chrome <canvas> ile çok benzer çıktılar üretir
  • Çıktılar PDF·SVG gibi vektör ve JPEG·PNG·WEBP gibi bitmap formatlarında dışa aktarılabilir; dosya·dataURL·Buffer·Sharp nesnesi olarak kullanılabilir
  • Tarayıcı Canvas’ının ötesindeki alanları da kapsar; GUI Window render etme, olay çerçevesi, çok sayfalı Canvas, yol işlemleri, 3D perspektif dönüşümleri, CSS filter, gelişmiş tipografi denetimi sunar
  • Asenkron render alma ve dosya G/Ç işlemleri, kullanıcının yapılandırdığı worker pool içindeki yerel iş parçacıklarında yürütülür; bu da sunucu tarafı görsel üretimi ve serverless ortamlar için uygundur
  • Benchmark’lar serial ve async modlarını ayrı ölçer; async modunda birden çok tekrar görevi aynı anda başlatılarak multithreading etkisi karşılaştırılır

Node.js’te kullanılan Canvas uygulaması

  • Skia Canvas, Node.js için bir HTML Canvas çizim API’si uygulamasıdır ve hem ekranda hem ekran dışında render almayı destekler
  • Google’ın Skia grafik motorunu kullanarak Chrome <canvas> öğesine çok benzer sonuçlar üretir
  • Tarayıcı Canvas’ının henüz sunmadığı özellikleri de içerir

Çıktı biçimleri ve dışa aktarma yöntemleri

  • Görsel çıktıda hem vektör formatları hem de bitmap formatları desteklenir
    • Vektör: PDF, SVG
    • Bitmap: JPEG, PNG, WEBP
  • Canvas sonucu farklı hedeflere gönderilebilir
  • Etkileşimli GUI Window üzerine doğrudan çizim yapılabilir ve tarayıcıya benzer bir event çerçevesi sunulur

Asenkron render alma ve çoklu sayfa

  • Render alma ve dosya G/Ç, yerel iş parçacıkları kullanan bir worker pool içinde asenkron olarak çalıştırılır
  • Tek bir Canvas içinde birden fazla sayfa oluşturulabilir
    • Tek bir çok sayfalı PDF olarak çıktı alınabilir
    • Birden fazla dosyaya bölünen görsel dizisi olarak da kaydedilebilir

Tarayıcı Canvas’ının ötesine geçen grafik özellikleri

Tipografi denetimi

  • Metin render etme, çok satırlı metni ve otomatik satır kaydırmayı işler
  • Satır bazında metin metrikleri sunar
  • small-caps, ligature gibi OpenType özellikleri standart font-variant söz dizimiyle kullanılabilir
  • Harf aralığı, kelime aralığı ve leading orantılı olarak denetlenebilir
  • variable fonts desteklenir ve weight değerleri şeffaf biçimde eşlenir
  • Yerel dosyalardan yüklenen sistem dışı fontlar da kullanılabilir

Kullanım örnekleri

  • Görsel dosyası oluşturma örneğinde Canvas oluşturulup getContext("2d") ile 2D context alındıktan sonra, konik gradient stroke stili olarak kullanılarak bir dikdörtgen çizilir
    • saveAs("rainbox.png", {density:2}) ile yüksek yoğunluklu görsel kaydedilir
    • canvas.png, canvas.toBuffer("png") için kısaltma olarak kullanılır
    • toDataURL("png") sonucu HTML dizesi içine yerleştirilebilir
    • saveAsSync("rainbox.pdf") ile ana iş parçacığında senkron kayıt da mümkündür
  • Çok sayfalı dizi örneğinde canvas.newPage() ile farklı renklerde sayfalar oluşturulup kaydedilir
    • all-pages.pdf olarak çok sayfalı PDF kaydedilir
    • page-{2}.png deseniyle page-01.png, page-02.png gibi birden çok dosya üretilir
  • Window render örneğinde Window(300, 300) oluşturulur ve draw event’inde frame değerine göre çizgi kalınlığı değişen bir daire çizilir
  • Sharp.js entegrasyon örneği, Canvas sonucunu Sharp nesnesine dönüştürerek sonradan işlemeyi ya da Sharp ile üretilen görselin loadImage ile Canvas üzerine çizilmesini gösterir

Benchmark yöntemi ve sonuçlar

  • Benchmark’lar Skia Canvas’ı iki modda test eder
    • serial: Her render görevini bekledikten sonra bir sonraki tekrara geçilir
    • async: Tüm test tekrarları tek seferde başlatılır ve multithreading desteğiyle paralel yürütülür
  • Tüm sonuçlar canvas-benchmarks sonuç sayfasında görülebilir
  • Başlangıç gecikmesi testinde, 100 tekrar ölçümünde skia-canvas tekrar başına 1ms’nin altında ve toplam 33ms kaydetti
    • canvaskit-wasm: tekrar başına 25ms, toplam 2.47 saniye
    • canvas: tekrar başına 88ms, toplam 8.77 saniye
    • @napi-rs/canvas: tekrar başına 69ms, toplam 6.87 saniye
  • Bézier curves testinde, 20 tekrar ölçümünde async moddaki paralel işleme farkı belirginleşti
    • skia-canvas serial: tekrar başına 137ms, toplam 2.74 saniye
    • skia-canvas async: tekrar başına 28ms, toplam 558ms
    • Karşılaştırma için canvaskit-wasm 790ms, canvas 486ms, @napi-rs/canvas 230ms idi
  • SVG to PNG testinde, 100 tekrar ölçümünde canvaskit-wasm bunu desteklemedi; skia-canvas serial modda tekrar başına 58ms, async modda tekrar başına 11ms kaydetti
    • skia-canvas serial: toplam 5.83 saniye
    • skia-canvas async: toplam 1.08 saniye
  • Görsel ölçekleme·döndürme testinde 50 tekrar sonucu
    • skia-canvas serial: tekrar başına 100ms, toplam 5.00 saniye
    • skia-canvas async: tekrar başına 19ms, toplam 935ms
  • Temel metin testinde 200 tekrar sonucu
    • skia-canvas serial: tekrar başına 21ms, toplam 4.26 saniye
    • skia-canvas async: tekrar başına 4ms, toplam 819ms

1 yorum

 
GN⁺ 2024-12-04
Hacker News yorumları
  • https://windowjs.org da çok benzer bir konsept
    Skia'yı sarmalayıp Canvas API olarak sunuyor, ancak Node yerine v8'i gömülü kullanarak çok küçük bir runtime ile çalışıyor
    Yaklaşık 3 yıl önce yayımladığım ilk açık kaynak projemdi; WebGL, ses vb. özellikleri sunup masaüstü için bir JavaScript oyun platformuna dönüştürme planım da vardı, ancak başka işler ve projeler yüzünden geliştirme durdu
    Canvas'ı tarayıcı dışında da kullanılabilir kılan böyle projelerin çıkmasına seviniyorum

    • Oldukça havalı, ama izolasyon özellikle gerekmiyorsa yalnızca v8 olan bir ortam biraz yetersiz kalıyor
      Bazen sadece ağ isteği yapmak isteyebiliyorsunuz
    • Harika bir proje
      Node.js yerine yalnızca V8 gömülü olunca ikili dosya boyutunun ne kadar küçüldüğünü merak ediyorum
      Node.js de V8 kullanıyor; Node ikili dosyasının boyutunun büyük kısmı V8'den değil de runtime'dan mı geliyor, onu da merak ediyorum
      Web sitesine ve GitHub deposuna baktım ama Window.js ikili dosyasının genelde kaç kB ya da MB olduğunu bulamadım
  • Meraktan soruyorum, bu tür kütüphaneler nerede kullanılıyor acaba
    Masaüstünde şekil çizmek için daha iyi yerel kütüphaneler yok mu diye düşünüyorum

    • Soundslice'ta frontend JavaScript/Canvas ile yapılmış özel bir nota render grafik kütüphanesi kullanıyoruz
      Sunucu tarafında da vektörel PDF üretmemiz gerektiği için HTML Canvas API'sini kullanıp PDF oluşturabilen bir Node kütüphanesi kullanıyoruz
      Bu sayede sonuçların web tarayıcısında render edilen notalarla birebir aynı olması güzel oluyor
      Sonuç olarak bu tür kütüphaneler, tarayıcı dışı ortamlarda da kodun yeniden kullanılmasını sağlıyor
    • 2D çizimde Skia kadar güçlü olup yaygın biçimde “yerel” denebilecek şeyler aslında çok fazla değil
      Skia'nın en büyük avantajı yerel grafikleri etkili biçimde kullanmasında ve zaten tarayıcı motorlarında kullanılmasının nedeni de bu
      Üstelik hedef API'nin tek olması da bir avantaj
    • Avantajı taşınabilirlik değil mi? GPU hızlandırmalı 2D render kütüphaneleri arasında başka neler var, merak ediyorum
      Bir yandan bu daha düşük seviyeli, ama diğer yandan Puppeteer'ı 2D grafik kütüphanesi gibi kullandığım da oldu
      Canvas 2D, WebGL, WebGPU ve HTML/CSS'in tamamını elde ediyorsunuz; metin efektleri, arka plan görselleri ve CSS dönüşümlerini de kullanabiliyorsunuz
      Görsel ve video yüklemek de mümkün; ekran görüntüsü özelliğiyle birleştirdiğiniz sonucu görsele dönüştürebiliyorsunuz
      Abartılı ama benim kullanımım için sorun değildi; çalışıyor, çapraz platform ve problemi çözüyor
    • Canvas'tan daha iyi bir 2D grafik çizim API'si olan bir platform gösterebilirsen şaşırırım
      Skia, Direct2D'den biraz daha hızlı ve Cairo'dan çok daha hızlı
      Son derece optimize edilmiş durumda ve GPU hızlandırmalı backend'leri de var
    • Aynı kodu birden fazla platformda çalıştırabilmek büyük bir artı
      Canvas aynı zamanda çok yaygın bir 2D çizim API'si
      iOS'ta da yerel bir sürümü var, Android'de de yerel bir sürümü var; çizim işlemleri de genel olarak benzer
      Bundan yararlanarak çok şey kazanılabiliyor
  • Skia'da Node'u destekleyen bir WASM derlemesi olan CanvasKit de var: https://www.npmjs.com/package/canvaskit-wasm; bu modül ise bir Rust binding'i gibi görünüyor
    İki yaklaşımın artı ve eksilerini merak ediyorum

    • “Rust binding'i”nden ziyade önceden derlenmiş bir Node ikili dosyasına daha yakın
      Sadece içerde Rust/C++ karışık bir kod tabanından üretilmiş
      Dolayısıyla temel fark, WASM'in ayrı bir runtime'a ihtiyaç duyması, Node ikili dosyasının ise duymaması
  • Bu, Rust crate'ini saran bir wrapper gibi bir şey mi?
    https://rust-skia.github.io/doc/skia_safe/canvas/struct.Canvas.html

    • Skia Canvas'ın, binding olduğu sürece neredeyse her programlama dilinde çalışabileceğini anlıyorum https://www.swig.org/
      Node'a özel pek bir şey göremiyorum
    • Doğru, napi-rs ile üretilmiş
  • Bunu uzun zamandır bekliyordum
    Daha önce benzer şeyler yapmaya çalışan girişimler Node-Gyp kurulumu gerektiriyordu ve gerçekten kâbus gibiydi

  • Basit bir render API'sinden fazlasıymış: “OS'in yerel grafik pipeline'ı ile pencerelere render edebiliyor ve tarayıcı benzeri bir UI olay framework'ü sağlıyor” diye bir ifade var
    WebGPU desteği için wgpu, WebGL desteği için de ANGLE eklenebilir gibi

    • Skia yaygın kullanılan bir kütüphane; aklıma gelenler arasında Chrome, Firefox ve LibreOffice kullanıyor
      WebGPU ve ANGLE dahil pek çok render hedefini destekliyor
    • Qt'nin zaten sunduklarına oldukça benziyor
      QPainter ham görselleri ve pencereleri ele alıyor; olay desteği olan daha gelişmiş widget'lar da var
      Ayrıca bir süredir aradığım bir özellik olarak, Qt'de pencereden daha büyük bir grafik düzleminde milyonlarca nesneyi çözünürlükten bağımsız biçimde render edip olayları da işleyebilen graphicsview var
  • Node uyumlu Canvas implementasyonlarıyla ilgileniyorsanız birkaç seçenek var
    Skia projesindeki canvaskit-wasm GPU hızlandırmalı değil gibi görünüyor: https://github.com/google/skia/tree/main/modules/canvaskit/npm_build
    @napi-rs/canvas en hızlı binding: https://github.com/Brooooooklyn/canvas?tab=readme-ov-file#performance
    node-canvas ise Skia yerine Cairo kullanıyor: https://github.com/Automattic/node-canvas

  • Advent of Code'da basit bir grafik penceresine ihtiyaç duyduğumda şu anda Deno ile birlikte kullanıyorum
    window-example da var: https://skia-canvas.org/#rendering-to-a-window
    deno add npm:skia-canvas ile ekleyip, deno.json içine "nodeModulesDir": "auto" koyduktan sonra deno install --allow-scripts çalıştırmanız yeterli

  • Bunu görünce gerçekten heyecanlandım
    Hem bağımsız çalışabilen hem de web ile uyumlu grafikleri çok daha rahat yazmayı sağlayacak gibi görünüyor
    İlk betik dili için bir kütüphaneyi derlemek üzere ikinci bir betik diliyle kaynaktan build edip kod üretmeye de gerek kalmayacak
    VS Code gibi yerlerde Canvas kodunu gerçek zamanlı render etmek ya da web Canvas'ta çalıştırmak için dönüşüm katmanı olan kodları çalıştırmak açısından ne kadar uygun olacağını görmek de ilginç olacak