HTML चे PDF मध्ये रूपांतर करणे कागदावर सोपे वाटते. तुम्ही एक पॉलिश केलेला टेम्पलेट तयार करता, त्यात तुमचा डेटा टाकता आणि वेब पेजप्रमाणेच पिक्सेल-टू-पिक्सेल दिसणारा दस्तऐवज मिळण्याची अपेक्षा करता. वास्तवात, ही पाइपलाइन अनेकदा क्रॅश, गहाळ झालेली ग्लिफ्स (glyphs) आणि व्हिज्युअल करप्शन (visual corruption) विरुद्धचा दैनंदिन लढा बनून जाते. एका अलीकडील प्रकल्पादरम्यान, तीन समस्या वारंवार समोर येत होत्या: काही विशिष्ट SVG ग्राफिक्स आल्यावर iText पूर्णपणे क्रॅश व्हायचे, इमोजी गायब होऊन पांढऱ्या चौकटींमध्ये बदलले जायचे आणि सूक्ष्म पारदर्शक बॅकग्राउंड्स (transparent backgrounds) गडद काळ्या ब्लॉक्समध्ये रूपांतरित व्हायचे. प्रत्येक अपयशाचे एक वेगळे कारण होते आणि या तिन्ही समस्या सोडवण्यासाठी, PDF इंजिनला मजकूर दिसण्यापूर्वी ॲप्लिकेशनने तो कसा तयार केला, यावर पुन्हा विचार करणे आवश्यक होते.
जेव्हा SVG मुळे पाइपलाइनमध्ये अडथळा येतो
सोयीसाठी iText सोबत एक अंतर्गत SVG रेंडरर येतो, परंतु हे एकत्रीकरण एक गंभीर त्रुटी लपवून ठेवते. जेव्हा एखाद्या SVG मध्ये जटिल पाथ्स (complex paths), जड CSS स्टाईलिंग किंवा काही विशिष्ट कोऑर्डिनेट ट्रान्सफॉर्मेशन्स असतात, तेव्हा एम्बेडेड पार्सर कोणतीही स्पष्ट exception न दाखवता थांबत नाही. तो पूर्णपणे क्रॅश होतो. हे पूर्ण सिस्टम क्रॅश असतात जे कोणतीही पूर्वसूचना न देता PDF जनरेशन थ्रेड थांबवतात, ज्यामुळे तुमच्याकडे एक अपूर्ण फाईल उरते आणि स्टॅक ट्रेस (stack trace) वेक्टर पार्सरच्या खोलवर कुठेतरी निर्देश करतो.
यावर खात्रीशीर उपाय म्हणजे iText ला SVG रेंडर करण्यास सांगणे पूर्णपणे थांबवणे. त्याऐवजी, हे काम स्टँडअलोन मोडमध्ये चालणाऱ्या Apache Batik कडे सोपवा. Batik तेच जटिल पाथ्स आणि CSS नियम तितक्या सहजतेने हाताळते आणि ते वेगळे ठेवल्यामुळे तुमचे PDF इंजिन ग्राफिक्सशी संबंधित अस्थिरतेपासून सुरक्षित राहते. ही कार्यपद्धती सोपी आहे: दस्तऐवज तयार करण्यापूर्वी, SVG ला Batik मधून चालवून एक PNG data URL तयार करा. कच्च्या वेक्टर मार्कअपऐवजी ती रॅस्टर इमेज iText मध्ये पास करा. स्टँडअलोन Batik हे मोठ्या लायब्ररीमध्ये समाविष्ट असलेल्या आणि स्थिर असलेल्या एम्बेडेड रेंडररपेक्षा SVG स्पेसिफिकेशनचे अधिक जवळून पालन करते, आणि या विलगीकरणामुळे (isolation) एखादा दोषपूर्ण ग्राफिक संपूर्ण दस्तऐवज रूपांतरण प्रक्रिया थांबवू शकत नाही.
एक लहान तपशील ठरवतो की तुमचा चार्ट व्यावसायिक दिसेल की एखाद्या बग रिपोर्टसारखा. SVG त्याच्या कोऑर्डिनेट सिस्टम आणि स्केलिंग वर्तनासाठी viewBox ॲट्रिब्युटवर अवलंबून असते. जर तुमच्या रूपांतरण कोडने viewBox कडे दुर्लक्ष केले, तर एक अगदी योग्य चार्ट वाचता न येण्याइतपत लहान होऊ शकतो किंवा विद्रूप होऊन पसरू शकतो. हा ॲट्रिब्युट स्पष्टपणे पार्स करा आणि त्या परिमाणांना (dimensions) तुमच्या आउटपुट आकारानुसार मॅप करा. या पायरीकडे दुर्लक्ष केल्यास लेआउटच्या समस्येमुळे तासनतास डीबगिंग करावे लागते, ज्याचा रेंडरिंग गुणवत्तेशी काहीही संबंध नसतो, तर केवळ कोऑर्डिनेट डिक्लेरेशनच्या अभावाशी संबंध असतो.
अदृश्य शाईची समस्या
जिथे इमोजी असायला हवेत तिथे दिसणाऱ्या रिकाम्या चौकटी एक साधी गोष्ट सांगतात: सध्याचा फॉन्ट ती भाषा बोलत नाही. Helvetica आणि इतर मानक PDF फॉन्ट्स हे इमोजीच्या व्यापक वापरापूर्वीचे आहेत. त्यामध्ये इमोजी Unicode रेंजसाठी ग्लिफ्स समाविष्ट नसतात, त्यामुळे जेव्हा iText ला ते कोड पॉइंट्स आढळतात, तेव्हा ते काहीही रेंडर करत नाही आणि पुढे जाते. परिणामी दस्तऐवज रिकाम्या बॉक्सने भरलेला दिसतो, ज्यामुळे सोशल सेंटीमेंट रिपोर्ट्स किंवा युजर फीडबॅक एक्सपोर्ट्स खराब दिसतात.
ही तफावत भरून काढण्यासाठी तुम्ही क्लायंट ऑपरेटिंग सिस्टमवर अवलंबून राहू शकत नाही. PDF मध्ये स्वतःची फॉन्ट संसाधने असतात आणि एकदा फाईल तुमच्या सिस्टम फॉन्ट्सपासून वेगळी झाली की ब्राउझरमध्ये जे बरोबर दिसते त्याला काही अर्थ उरत नाही. उपाय म्हणजे एक स्पष्ट फॉन्ट राउटिंग लेयर तयार करणे. Symbola सारखा समर्पित इमोजी-सक्षम फॉन्ट रजिस्टर करा, जो इमोजी Unicode ब्लॉक्स कव्हर करणारे मोनोक्रोम सिम्बॉल्स प्रदान करतो. काळ्या-पांढऱ्या रंगाचे हृदय किंवा चेतावणी चिन्ह (warning symbol) ग्लॉसी कलर ग्लिफ सेटसारखे पॉलिश नसेल, तरीही ते अर्थ स्पष्ट करते. रिकामी आयत (rectangle) अपयशाचे संकेत देते. PDF व्ह्यूअर्समध्ये फुल-कलर इमोजी फॉन्ट्स सातत्याने रेंडर करणे कठीण असते आणि कलर सपोर्ट मिळवण्याच्या प्रयत्नात अनेकदा समस्या सुटण्याऐवजी अधिक सुसंगततेच्या (compatibility) समस्या निर्माण होतात.
iText लाईन ब्रेकिंगद्वारे दुसरी, अधिक कठीण समस्या निर्माण करते. लायब्ररी इमोजी सरोगेट पेअर्सना (surrogate pairs) चुकीच्या सीमेवर विभागू शकते, ज्यामुळे एक सिंगल कॅरेक्टर दोन अवैध भागांमध्ये विभागले जाते. जेव्हा असे घडते, तेव्हा टेक्स्ट स्ट्रीम करप्ट होतो आणि जिथे एक सिंगल ग्लिफ असायला हवा तिथे तुम्हाला वाचता न येणारे तुकडे मिळतात. हे रोखण्यासाठी, एक कस्टम ISplitCharacter लागू करा जो सरोगेट पेअर्स ओळखतो आणि त्यांना अॅटॉमिक युनिट्स (atomic units) म्हणून मानतो. यामुळे लेआउट इंजिन इमोजीच्या मध्ये लाईन ब्रेक टाकत नाही आणि मजकुराची अखंडता टिकून राहते.
जेव्हा पारदर्शकता काळी होते
सॉफ्ट rgba बॅकग्राउंड किंवा लेअर्ड fill-opacity इफेक्ट असलेला SVG ब्राउझरमध्ये उत्कृष्ट दिसतो. तोच मार्कअप iText मध्ये वापरला की, पारदर्शकता अनेकदा एका गडद काळ्या आयतात रूपांतरित होते. इंजिन CSS कलर फंक्शन्स आणि opacity ॲट्रिब्युट्स चुकीच्या पद्धतीने हाताळते आणि opacity च्या जागी पूर्ण घनतेची शाई (full-density ink) वापरते.
कन्व्हर्टरपर्यंत पोहोचण्यापूर्वी SVG चे प्री-प्रोसेसिंग करणे हा एकमेव विश्वासार्ह बचाव आहे. अल्फा ब्लेंडिंगवर (alpha blending) अवलंबून असलेले कोणतेही घटक काढून टाका किंवा बदला. rgba() व्हॅल्यूजचे रूपांतर सॉलिड rgb() रंगांमध्ये करा. जर तुम्हाला ओपॅसिटीचा (opacity) काही अंश राखून ठेवायचा असेल, तर त्या व्हॅल्यूज CSS शॉर्टहँडमधून काढून मानक ओपॅसिटी ॲट्रिब्युट्समध्ये (standard opacity attributes) हलवा, तरीही पारदर्शकता (transparency) पूर्णपणे काढून टाकणे हा सर्वात सुरक्षित पर्याय आहे. हे बदल वेब डिझाइनसाठी मागे जाण्यासारखे वाटू शकतात, परंतु PDF एक वेगळे इमेजिंग मॉडेल वापरते जे आधुनिक CSS पारदर्शकतेच्या आधीचे आहे. हे फॉरमॅट ठोस रंगांच्या व्हॅल्यूजची अपेक्षा करते, आणि त्याला अस्पष्ट व्हॅल्यूज दिल्यास समस्या निर्माण होऊ शकतात.
तुम्ही मार्कअप सॅनिटाइझ (sanitizing) करत असताना, प्रत्येक SVG मध्ये योग्य xmlns नेमस्पेस डिक्लेरेशन (namespace declaration) आहे की नाही याची खात्री करून घ्या. जनरेट केलेले HTML आणि टेम्पलेट इंजिन्स अनेकदा मिनिफिकेशन (minification) किंवा DOM सिरियलायझेशन (serialization) दरम्यान नेमस्पेस ॲट्रिब्युट्स काढून टाकतात. त्या नेमस्पेसशिवाय, SVG पार्सर घटक चुकीचे ओळखू शकतो किंवा शांतपणे अयशस्वी होऊ शकतो, ज्यामुळे एकतर पार्सर एरर येईल किंवा सदोष वेक्टर डेटा तयार होईल जो पेजवर कधीच पोहोचणार नाही. ही एक मूलभूत तपासणी आहे ज्यासाठी काही सेकंद लागतात आणि यामुळे तासनतास वाचतात.
एक टेम्पलेट, दोन जग
सर्वात वाईट दीर्घकालीन उपाय म्हणजे ब्राउझर आणि PDF साठी वेगळे HTML टेम्पलेट्स ठेवणे. लेबल्स बदलतात, मार्जिन बदलतात आणि लवकरच एक्सपोर्ट केलेला रिपोर्ट डॅशबोर्डशी जुळत नाही. एक स्वच्छ आर्किटेक्चर एकाच टेम्पलेटवर अवलंबून असते आणि context.isForPdf() सारख्या एका सिंगल फ्लॅगद्वारे रेंडरिंग लॉजिकचे विभाजन करते.
जेव्हा तो फ्लॅग 'false' असतो, तेव्हा टेम्पलेट पूर्ण ब्राउझर अनुभव प्रदान करते. ते इन्फिनिट झूमसाठी नेटिव्ह SVG, आधुनिक CSS आणि ब्राउझरला सपोर्ट असलेल्या रंगांच्या ॲसेट्सचा वापर करते. जेव्हा फ्लॅग 'true' असतो, तेव्हा तेच टेम्पलेट SVG ॲसेट्सच्या जागी प्री-रेंडर केलेले PNGs वापरते, इमोजी-सेफ फॉन्ट स्टॅक (emoji-safe font stack) सक्रिय करते आणि कोणतेही अनसपोर्टेड ट्रान्सपरन्सी इफेक्ट्स काढून टाकते. मजकूर आणि रचना बदलत नाही; फक्त ॲसेट पाईपलाईन आणि स्टाईलिंग नियम लक्ष्यित माध्यमासाठी (target medium) अनुकूल होतात.
हा दुहेरी-मार्ग (dual-path) दृष्टिकोन कोडबेस अचूक ठेवतो. तुम्ही एकाच ठिकाणी मजकूर अपडेट करता आणि राउटिंग लेयर स्क्रीन आणि कागद यामधील तांत्रिक फरक हाताळते. यामुळे टेस्टिंग देखील सोपे होते. तुम्ही पूर्ण डेव्हलपर टूल्ससह ब्राउझरमध्ये टेम्पलेट लॉजिक तपासू शकता, त्यानंतर PDF फ्लॅग सक्रिय करून हे सुनिश्चित करू शकता की तोच डेटा कन्व्हर्टर क्रॅश न होता एक स्वच्छ दस्तऐवज तयार करतो.
PDF जनरेशनबद्दलचे कडू सत्य
PDF कधीही ब्राउझरसारखे वागणार नाही. रेंडरिंग मॉडेल्स मूलभूतपणे भिन्न आहेत आणि iText सारखी लायब्ररी वेग, फाईल आकार आणि स्पेसिफिकेशन अनुपालनामध्ये (specification compliance) जाणीवपूर्वक तडजोड करतात. यश हे इंजिनशी लढून आणि सर्वोत्तम गोष्टीची आशा करून मिळत नाही. ते मर्यादा लवकर स्वीकारून आणि त्यांच्याभोवती पाईपलाईन डिझाइन करून मिळते.
PDF टप्प्यापूर्वी तुमचे वेक्टर्स कन्व्हर्ट करा. तुमचे फॉन्ट्स स्पष्टपणे राउट करा जेणेकरून प्रत्येक ग्लिफला (glyph) फॉलबॅक मिळेल. पारदर्शकता काढून टाकून सॉलिड रंगांचा वापर करा. तुमच्या टेम्पलेट्सना ते कोणत्या जगासाठी रेंडर करत आहेत हे समजण्यासाठी आवश्यक असलेला संदर्भ (context) द्या. हे सातत्याने करा, आणि तुमचे दस्तऐवज रेंडररशी संघर्ष करणे थांबवतील आणि तुम्ही ठरवल्याप्रमाणेच दिसू लागतील.
