3 पॉइंट द्वारा GN⁺ 2024-03-22 | 3 टिप्पणियां | WhatsApp पर शेयर करें
  • Dropflow एक CSS layout engine है, जिसे बुनियादी CSS standards जैसे inline, block, float, positioning, और आगे चलकर table को explore करने के लिए बनाया गया है; flexbox और grid इसका लक्ष्य नहीं हैं
  • इसे Node और node-canvas के साथ backend में PDF·image generation के लिए इस्तेमाल किया जा सकता है, और browser में canvas पर line-wrapping rich text render किया जा सकता है
  • Text layout में bidirectional·RTL text, grapheme-level font fallback, रंगीन diacritics, OpenType/TrueType font registration, और HarfBuzz-आधारित shaping का support है
  • CSS support 30 से अधिक properties तक फैला है, जिनमें float, clear, display: inline-block, position: relative, overflow, z-index, zoom काम करते हैं, और table, absolute, fixed, transform आदि planning stage में हैं
  • सबसे अच्छी performance hyperscript API और reusable style objects से मिलती है, जो HTML/CSS parsing को skip करती है; 2019 MacBook Pro पर 500 से अधिक paragraphs वाले The Little Prince को HTML से image में 160ms से कम समय में बदल देता है

Dropflow किस CSS layout दायरे को कवर करता है

  • Dropflow एक CSS layout engine है, जिसे foundational CSS standards के दायरे को explore करने के लिए बनाया गया है
    • इसका फोकस inline, block, float, positioning, और आगे चलकर tables पर है
    • flexbox और grid इसका लक्ष्य नहीं हैं
  • इसमें high-quality text layout implementation है, जो दुनिया की कई भाषाओं को दिखा सकती है
  • इसके दो उपयोग बताए गए हैं
    • Node और node-canvas का उपयोग करके backend में PDF या image generation
    • browser में canvas पर line-wrapping rich text rendering

मुख्य फीचर्स

  • यह 30 से अधिक CSS properties को support करता है, जिनमें float जैसी जटिल properties भी शामिल हैं
  • Text से जुड़े फीचर्स काफी व्यापक हैं
    • bidirectional text और RTL text
    • grapheme-level font fallback
    • रंगीन diacritics
    • बेहतर line breaking, जैसे शुरुआती padding को अगली line तक ले जाना
    • optimized shaping
  • Input method के रूप में HTML/CSS के अलावा styles को object के रूप में देने वाला hyperscript h() API भी support करता है
  • OpenType/TrueType buffers register किए जा सकते हैं, और registration आवश्यक है
  • <img> JPEG, BMP, PNG, GIF को support करता है, लेकिन backend के अनुसार support अलग हो सकता है
  • Inherited और cascaded styles को दोबारा calculate नहीं किया जाता
  • इसका लक्ष्य complete typing, भरपूर tests, और तेज़ execution है

CSS support की स्थिति

  • Inline formatting में काम करने वाली चीज़ों में color, direction, font-family, font-size, font-stretch, font-style, font-weight, line-height, text-align, vertical-align, white-space, word-break, overflow-wrap, word-wrap, word-spacing आदि शामिल हैं
  • Inline formatting में font-variant, letter-spacing, tab-size, text-decoration, unicode-bidi planned स्थिति में हैं
  • Block formatting में clear और float काम करते हैं
    • writing-mode के horizontal-tb, vertical-lr, vertical-rl आंशिक रूप से implemented हैं
    • BFC में implemented हैं, लेकिन IFC में अभी नहीं
  • Boxes and positioning में कई box और placement properties काम करती हैं
    • background-clip, background-color, border-color, border-style, border-width
    • top, right, bottom, left
    • box-sizing
    • display: block, inline, inline-block, flow-root, none
    • height, margin, padding, overflow, width, z-index, zoom
    • position: relative
  • Boxes and positioning में display: table, min/max-height, min/max-width, position: absolute, position: fixed, transform planned स्थिति में हैं

बुनियादी उपयोग प्रवाह

  • Dropflow browser की तरह inherited·computed styles वाले DOM पर काम करता है
  • सामान्य flow इस प्रकार है
    • layout से पहले FontFace से fonts register करें
    • flow.style() से style object बनाएं
    • flow.h() से DOM बनाएं
    • flow.dom() से render होने वाला tree तैयार करें
    • renderToCanvas() से पूरे canvas पर layout और paint चलाएँ
  • HTML API भी दिया गया है, लेकिन इसे केवल तब सुझाया गया है जब performance महत्वपूर्ण न हो या सीखने के उद्देश्य से इस्तेमाल किया जा रहा हो
    • parsing अतिरिक्त समय लेती है और bundle size बढ़ाती है
    • HTML parsing को @fb55 की वजह से तेज़ बताया गया है
    • अभी केवल style HTML attribute support है, class अभी काम नहीं करता

Performance विशेषताएँ

  • Performance सबसे ऊँची प्राथमिकता है, और correctness के बाद सबसे महत्वपूर्ण है
  • उदाहरण-आधारित performance numbers दिए गए हैं
    • कई inline span और अलग fonts वाले 8 paragraphs को HTML से image में बदलने में 2019 MacBook Pro पर 9ms, 2012 MacBook Pro पर 13ms
    • 500 से अधिक paragraphs वाले The Little Prince को HTML से image में बदलने में 2019 MacBook Pro पर 160ms से कम, 2012 MacBook Pro पर 250ms से कम
    • 10-अक्षर वाले शब्द को generate करके केवल layout करने में 2019 MacBook Pro पर 25µs से कम, 2012 MacBook Pro पर 50µs से कम
  • सबसे तेज़ performance तब मिलती है जब hyperscript API से सीधे DOM बनाया जाए और सामान्य HTML/CSS parsing चरण को skip किया जाए
  • Style objects को reuse करने से और अधिक लाभ मिलता है
  • अलग width पर reflow करना layout tree दोबारा बनाने की तुलना में तेज़ है

API संरचना

  • बुनियादी steps दो हैं
    • font registration
    • Hyperscript API या Parse API से DOM creation
  • सरल उपयोग में DOM को सीधे canvas पर render किया जा सकता है
    • renderToCanvas(el, canvas) canvas की width और height को viewport size मानकर पूरा layout render करता है
  • अधिक low-level API इस्तेमाल करने पर layout को संरक्षित रखा जा सकता है
    • dependent resources load करना
    • DOM का layout बनाना
    • layout reflow
    • HTML5 canvas जैसे target पर paint
  • इस तरीके का उपयोग अलग size पर reflow करने, दिख न रहे layout को paint न करने, या intrinsics पाने के लिए किया जा सकता है

Font handling

  • Dropflow प्रोग्राम का पहला step उन fonts को register करना है जिन्हें CSS font properties से चुना जाएगा
  • Dropflow system fonts को खोजता नहीं है, इसलिए कम से कम एक बार FontFace बनाकर जोड़ना ज़रूरी है
  • Font registration API, CSS Font Loading API के subset को implement करता है, और non-standard loadSync method जोड़ता है
  • Server side में file:/// URL को readFileSync से synchronously load किया जा सकता है
  • ArrayBuffer browser की तरह constructor में तुरंत load हो जाता है
  • registerNotoFonts सभी Noto Sans font families को register करता है
    • Fonts को FontSource distribute करता है और jsDelivr host करता है
    • Noto Sans fonts 200 से अधिक हैं, और CJK fonts की unicodeRange strings बड़ी होने के कारण यह बड़ा import है
    • browser production use में individual fonts register करना बेहतर बताया गया है
    • Latin के लिए italic fonts register होते हैं, और सभी scripts के लिए normal 400 और bold 700 register होते हैं
  • Chinese·Korean·Japanese एक जैसे Unicode code points share करते हैं, लेकिन अक्षर अलग render हो सकते हैं, इसलिए जहाँ संभव हो language-specific fonts इस्तेमाल करना बेहतर है

Layout, reflow, paint

  • layout(el) box tree, fragmentation tree, और glyphs सहित layout बनाता है
    • box tree आम तौर पर DOM tree से मेल खाता है, लेकिन anonymous text content की वजह से अधिक boxes बन सकते हैं या display: none की वजह से कम हो सकते हैं
  • reflow(layout, width = 640, height = 480) boxes को place करता है, text को lines में तोड़ता है, और paint करने योग्य स्थिति में लाता है
    • block box का margin collapsing
    • HarfBuzz को text भेजना
    • font fallback loop
    • line breaks और break points के अनुसार reshaping
    • float placement और clear handling
    • direction और text direction के अनुसार shaped text spans और background placement
    • float, inline-block, absolute content की intrinsics calculation
    • normal flow के बाद position handling
  • Paint target के रूप में अभी Canvas और SVG support हैं
    • paintToCanvas browser canvas, node-canvas, और समान standard-compliant context पर paint करता है
    • paintToSvg SVG string बनाता है, और FontFace को दिए गए URL को refer करने वाले @font-face rules शामिल करता है
    • paintToSvgElements मौजूदा SVG के अंदर drawing के लिए <svg> और @font-face rules नहीं जोड़ता
    • paintToHtml absolute-positioned elements की flat list बनाता है; इसकी recommendation नहीं है, लेकिन development में उपयोगी हो सकता है

DOM API और environment hooks

  • Hyperscript और Parse API से प्राप्त root HTMLElement browser के querySelector जैसे methods देता है, जिनसे tag name, id, class से elements खोजे जा सकते हैं
    • query(selector) एक HTMLElement या null लौटाता है
    • queryAll(selector) HTMLElement[] लौटाता है
  • HTMLElement के साथ connected render boxes हो सकते हैं
    • आम तौर पर एक होता है, लेकिन inline और block content mix होने पर कई हो सकते हैं
    • BlockContainer absolute positioned element, floated element, inline-block, block-level element के लिए बनता है
    • ReplacedBox image के लिए बनता है
  • Dropflow को अलग-अलग environments के लिए adjust करने योग्य बनाया गया है
    • browser में fetch से fonts और images load किए जाते हैं, और font buffers को document.fonts में register किया जाता है
    • Nodejs में fs.readFileSync से fonts synchronously load किए जा सकते हैं
    • अगर canvas backend और node-canvas हो, तो node-canvas का registerFont call किया जाता है
    • node-canvas font buffer support नहीं करता, इसलिए file:// URL इस्तेमाल करना होता है
  • @napi-rs/canvas या skia-canvas इस्तेमाल करने के लिए flow.environment.registerFont को उनके font registration API से जोड़ने वाली कुछ lines of code चाहिए
  • Environment में 6 hooks हैं
    • wasmLocator
    • registerFont
    • resolveUrl
    • resolveUrlSync
    • createDecodedImage
    • destroyDecodedImage

HarfBuzz-आधारित text shaping

  • Glyph layout, WebAssembly में compile किए गए HarfBuzz से किया जाता है
  • इसका लक्ष्य वह accuracy है जिसे measureText API से text span positioning करने वाले तरीके से पाना मुश्किल है
  • उदाहरण के तौर पर, Google Sheets में "AV" में केवल "V" को अलग रंग देने पर kerning गायब हो जाता है और अक्षर पहले से अधिक दूर हो जाते हैं
    • क्योंकि दो बार measureText और fillText call करने पर per-letter contextual glyph advance खो जाता है
  • Dropflow रंग बदलने के point पर नहीं, बल्कि उससे अधिक coarse shaping boundary पर HarfBuzz का उपयोग करके fonts को अधिक सटीक रूप से support करता है
  • WebAssembly में compile किया गया HarfBuzz, CanvasRenderingContext2D के measureText जैसी performance metrics दे सकता है
    • इसे measureText जितना तेज़ नहीं, लेकिन बहुत धीमा भी नहीं बताया गया है
    • और दोनों को text layout stack का dominant bottleneck नहीं माना गया है
  • measureText-आधारित text layout को तेज़ चलाने के लिए word cache चाहिए, और बताया गया है कि GSuite apps यही तरीका इस्तेमाल करते हैं
    • word cache उन fonts को support नहीं कर सकता जिनका प्रभाव spaces के पार जाता है
    • ऐसे fonts को support करने के लिए paragraph के break index पर binary search चाहिए, और बताया गया है कि यह पूरे paragraph को HarfBuzz को देने से कहीं धीमा है
    • रंगीन diacritics measureText से संभव नहीं हैं

निर्भर परियोजनाएँ

  • Dropflow की package.json dependencies नहीं हैं, लेकिन यह कई projects के काम का उपयोग करता है
  • JavaScript dependencies project में check in की गई हैं, और focus बनाए रखने तथा dependency-of-dependency समस्याओं से बचने के लिए विभिन्न स्तरों पर modify की गई हैं
  • मुख्य projects इस प्रकार हैं
    • harfbuzz: font shaping और आवश्यक font API प्रदान करता है
    • Tehreer/SheenBidi: bidi boundary calculation
    • foliojs/linebreak: Unicode break index प्रदान करता है
    • peggyjs/peggy: CSS parser generation
    • fb55/htmlparser2: HTML parsing
    • google/emoji-segmenter: emoji segmenting
    • foliojs/grapheme-breaker: Unicode grapheme boundary प्रदान करता है, और Unicode 15 के लिए बड़े स्तर पर modify किया गया है
    • foliojs/unicode-trie: तेज़ Unicode data के लिए इस्तेमाल होता है, और unused हिस्से हटाने के लिए बड़े स्तर पर modify किया गया है

3 टिप्पणियां

 
winterjung 2024-03-23

मूल शीर्षक "Show HN: Dropflow, a CSS layout engine for node or <canvas>" था। अभी यह "GN⁺: HN परिचय: Node या <canvas> के लिए CSS layout engine, Dropflow</canvas>" के रूप में दर्ज है।

 
dlehals2 2024-03-22

शीर्षक में टैग हैं, इसलिए डिटेल पेज का title वाला हिस्सा टूट रहा है.. haha, escape करना चाहिए..

 
GN⁺ 2024-03-22
Hacker News की राय
  • आजकल backend पर सुंदर PDF बनाने का डिफ़ॉल्ट तरीका headless browser चलाना और browser API से HTML/CSS को PDF में बदलना है, लेकिन server पर browser instance चलाने और बड़े workload के हिसाब से scale करने की लागत काफ़ी ज़्यादा होती है
    यह game changer tool है; अब browser overhead के बिना भी HTML/CSS से PDF design और generate किए जा सकते हैं

    • यह देखकर हैरानी होती है कि web यहाँ तक पहुँच गया। सुंदर PDF document बनाने का सबसे अच्छा तरीका server पर पूरा web browser चलाना है—90s या 2000s में यह सोचना मुश्किल रहा होगा
    • browser इस्तेमाल करने का फायदा यह है कि generated PDF vector और fonts का उपयोग करता है। इसके उलट Canvas-based तरीका PDF के अंदर ज़्यादातर image बना देगा, हालांकि ज़्यादातर use cases में यह बड़ी समस्या नहीं हो सकती
    • https://ekoopmans.github.io/html2pdf.js/ इस्तेमाल किया है और यह काफ़ी अच्छा चला
    • थोड़ा confuse हूँ। side project backend में PDF generation के लिए काफ़ी समय से Prawn library इस्तेमाल कर रहा हूँ: https://github.com/prawnpdf/prawn
      हालांकि मैं जो PDF generate करता हूँ वे निश्चित रूप से सुंदर नहीं होते, तो फर्क शायद यही हो सकता है
    • कुछ clients के लिए PDF renderer बनाए हैं, और PDF में सबसे बड़ी requirement accessibility थी
      सभी को ADA compliance चाहिए था, इसलिए Canvas renderer पर जाना मुश्किल है। ऐसा करने पर accessibility खत्म हो जाती है
  • वाकई अच्छा लग रहा है। पिछली नौकरी में immersive online learning platform develop किया था, जिसमें Oculus Quest 2 पर रक्षा विभाग के लोगों को विदेशी भाषा की training दी जाती थी और WebXR, Three.js वगैरह इस्तेमाल होते थे
    Unity3D एक बार काफी था, और app store review से भी नहीं गुजरना चाहता था। हमारे पास अपनी device fleet थी, इसलिए ठीक था
    सबसे बड़ी चुनौतियों में से एक course content workflow बनाना था, और यह लगभग मुझे अकेले करना था। असली language instructors PowerPoint से PDF बनाते थे, फिर मेरे बनाए dedicated editor से PDF को content database में upload करके training environment में deploy किया जाता था, और PDFJS से Canvas element पर render करके 3D rectangle के texture की तरह इस्तेमाल किया जाता था
    अगर ऐसा tool होता, तो लोगों को content बनाने के लिए PowerPoint का bypass इस्तेमाल करने की जरूरत नहीं पड़ती। PowerPoint वाला तरीका, पहले Photoshop से images बनवाने की कोशिश की तुलना में workflow speed को काफी बेहतर बना चुका था, लेकिन अगर app के अंदर signage editor बना पाते, तो “environment में कैसा दिखेगा इसका अंदाज़ा लगाना → PDF export करना → DB upload करना → असली रूप देखना” वाला loop हट जाता और यह और बेहतर होता
    वैसे भी business development team या marketing team नहीं थी जो product नहीं, सिर्फ service बेचना जानती हो, इसलिए शायद इसका बहुत मतलब नहीं था

  • अपने project https://htwins.net/scale2 और SVG या Canvas इस्तेमाल करने वाले दूसरे कामों के लिए मैं ऐसा ही कुछ ढूँढ रहा था

    • इसे कैसे बनाया गया, इसकी making-of जरूर पढ़ना चाहूँगा
  • अगर Flexbox से परेशानी हो रही है, तो responsive layout बनाते समय कई properties की चिंता न करनी पड़े, इसके लिए process को simplify करने वाला tool इस्तेमाल कर सकते हैं: https://flexboxcss.com

    • यह पहला site है जिसे मैंने सच में neumorphic design इस्तेमाल करते देखा है। aesthetics अच्छी है, और इसे real-world में पहले नहीं देखा था
  • शानदार। ऐसे tools बहुत अहम हैं क्योंकि ये browser rendering engine नाम के magic box को समझने लायक बनाते हैं
    अगर HTML और CSS rendering के लिए पूरी तरह machine-readable specification बनाई जा सके, तो renderer generate किए जा सकते हैं। browser-specific quirks को उसके ऊपर extensions की तरह रखा जा सकता है। अच्छा होगा अगर https://github.com/tawesoft/html5spec जैसी चीज़ असली engines में इस्तेमाल होने वाले रूप में आ सके

    • इसे देखकर Ladybird याद आया, जो शुरुआत से लिखा जा रहा browser है, और वास्तव में specification में bugs हैं या नहीं, यह verify करने में भी काफी उपयोगी रहा
  • यह उन चीज़ों के काफी करीब है जिनके बारे में मैं इन दिनों सोच रहा था। सोच रहा था कि क्या CSS और SVG को graphics और UI libraries के ऊपर abstraction layer की तरह इस्तेमाल किया जा सकता है
    node-canvas के बारे में पहली बार सुना, और लगता है कि यह उसमें drawing वाला हिस्सा पूरा करता है। यह tool UI library से मुझे जो चाहिए—layout वाला हिस्सा—वह संभाल सकता है
    यह भी जानना चाहूँगा कि CSS implement करना कितना मुश्किल रहा होगा। सुना है यह काफी complex है

    • native graphics libraries को CSS से target करने वाला Sciter नाम का एक और project भी है: https://sciter.com
      CSS implementation मुश्किल था, लेकिन सबसे बड़ी बाधा यह थी कि knowledge आसानी से दिखाई नहीं देता था
      सबसे कठिन हिस्सा text layout है। glyphs handle करना और RTL के लिए reverse direction में traverse करना सिरदर्द है, और line breaking भी सचमुच complex हो जाती है। जरूरी knowledge एक जगह व्यवस्थित नहीं है, इसलिए यह और कठिन हो जाता है
      शुरुआत में block layout पूरा करने के बाद, कई साल तक हफ्ते में कुछ घंटे ही काम करते हुए text shaping और itemization की details, क्या करना है और क्या नहीं करना है, सीखना पड़ा। बहुत कुछ Pango [1] का source code पढ़कर सीखा, और बाकी Google search से जोड़-तोड़ कर निकाला
      बाकी मामलों में W3C specification लगभग सब कुछ cover करती है। CSS2 standard [2] मेरे अब तक पढ़े सबसे सुंदर documents में से एक था। यह internally consistent और concise है, और वर्षों के विचार व trial-and-error का परिणाम है। CSS3 भी शानदार है, लेकिन CSS2 ही सबकी नींव है
      [1] https://gitlab.gnome.org/GNOME/pango/
      [2] https://www.w3.org/TR/CSS22/
  • दुनिया के लिए बड़ा योगदान है। यह उस classic case जैसा दिखता है जहाँ हर कोई सोचता है “किसी को $X करना चाहिए”, लेकिन कोई करता नहीं
    layout के लिए CSS इस्तेमाल करना मुझे पसंद है, और आजकल मैं मुख्यतः Flexbox और Grid पर निर्भर हूँ। अभी support न होना पूरी तरह समझ में आता है, लेकिन जानना चाहूँगा कि क्या कभी support करने की योजना है। अगर है, तो दूसरे लोग कैसे मदद कर सकते हैं?

  • सच में कमाल है। HTML को programmatically PNG में बदलना कितना मुश्किल है, यह शायद ज़्यादातर लोगों को पता नहीं होगा
    Node और browser के फर्क, या HTML और Canvas के फर्क की वजह से ढेरों छोटी-छोटी समस्याएँ सामने आती हैं

  • उपयोगी लगता है। पहले CSS को समझना और उसके ऊपर layout engine बनाना—इसके लिए कितना काम चाहिए, इसकी कल्पना करना मुश्किल है