גרפיקת ווקטור: Cairo ו־SVG#

כלי רסטר מתחייבים לרזולוציה; כלי ווקטור מתארים צורות ומחליטים על הפיקסלים מאוחר יותר, או לעולם לא. פרק זה מכסה את שני נתיבי הווקטור ב־Perl. Cairo הוא מנוע דו־ממד מלא מוחלק־קצוות המרסטר נתיבים למשטח פיקסלים (או ל־PDF ו־SVG): אתם מציירים בקואורדינטות של מספרים ממשיים והוא מחשב את הכיסוי. SVG מחולל תגיות SVG, תיאור טקסטואלי של צורות שדפדפן או מרַנדֵר מצייר מאוחר יותר בכל גודל שירצה. השתמשו ב־Cairo כשאתם זקוקים לפיקסלים עכשיו באיכות של רסטרייזר ראוי; השתמשו ב־SVG כשאתם רוצים פלט בלתי־תלוי־רזולוציה כקובץ שכלים אחרים צורכים.

Cairo שב גם בפרק 9: pperl שולח מימוש מחדש מובנה שלו, כך שאותו קוד רץ בלי Cairo של CPAN מותקן, ואותו פרק מראה כיצד הכריכה המובנית עובדת. כאן זהו מודול ה־CPAN הרגיל.

Cairo: נתיבים ומודל הציור#

המודל של Cairo הוא נתיב הנבנה ממקטעים, ואז או מקווקו (המתאר מצויר) או ממולא (הפנים נצבע). אתם קובעים צבע מקור, בונים נתיב עם move_to ו־line_to ועקומות, ומבצעים אותו. צבעים הם מספרי נקודה־צפה ב־0 .. 1, לא 0 .. 255.

use Cairo;

# an ARGB surface is a pixel buffer with alpha
my $surface = Cairo::ImageSurface->create('argb32', 200, 200);
my $cr = Cairo::Context->create($surface);

# paint a white background: set source, then paint fills everything
$cr->set_source_rgb(1, 1, 1);
$cr->paint;

# a stroked path
$cr->set_source_rgb(0, 0, 0);
$cr->set_line_width(3);
$cr->move_to(20, 20);
$cr->line_to(180, 20);
$cr->curve_to(180, 100, 20, 100, 20, 180);   # a bezier curve
$cr->stroke;

# a filled, semi-transparent circle (arc angles are in radians)
$cr->arc(100, 100, 40, 0, 6.28318);          # full circle = 2*pi
$cr->set_source_rgba(1, 0, 0, 0.5);           # red at 50% alpha
$cr->fill;

$surface->write_to_png('output.png');

שלושה דברים להפנים. קואורדינטות הן מספרים ממשיים, ולכן move_to(100.5, 47.25) הוא בעל משמעות והיסט חצי־הפיקסל מפרק היסודות הוא כיצד מקבלים קווים דקים וחדים. זוויות קשת הן ברדיאנים, לא במעלות, ולכן מעגל שלם הוא 2 * pi. והאלפא של set_source_rgba נותן לכם את ההרכבה בחינם: מלאו או קווקוו עם אלפא מתחת ל־1 ו־Cairo מערבב מעל מה שכבר נמצא שם.

stroke ו־fill צורכים את הנתיב הנוכחי. אם אתם רוצים גם למלא וגם לקווקו את אותה צורה, השתמשו ב־fill_preserve (או stroke_preserve), השומר את הנתיב לפעולה שנייה:

$cr->arc(100, 100, 40, 0, 6.28318);
$cr->set_source_rgb(0.4, 0.8, 1);
$cr->fill_preserve;                 # fill, but keep the path
$cr->set_source_rgb(0, 0, 0);
$cr->set_line_width(2);
$cr->stroke;                        # now outline the same circle

אלפא מוכפלת־מראש#

משטח ה־argb32 מאחסן פיקסלים עם אלפא מוכפלת־מראש: כל ערוץ צבע כבר מוכפל באלפא שלו. זה בלתי־נראה כשמציירים דרך ה־API של Cairo, אך זה חשוב ברגע שקוראים בתי פיקסל גולמיים מן המשטח או מזינים את החוצץ של Cairo לספרייה אחרת, מפני שהבתים אינם ה־RGBA הישיר שאתם עשויים להניח. כשחוצים את הגבול הזה, בטלו את ההכפלה תחילה. בתוך הציור של Cairo עצמו זה לעולם אינו עולה.

SVG: תגיות, לא פיקסלים#

SVG הוא Perl טהור ועושה משהו שונה: הוא בונה מסמך XML המתאר צורות, ומפיק טקסט. שום דבר אינו מרוסטר; הצרכן (דפדפן, Inkscape, ממיר PDF) מצייר אותו. זה הופך אותו למושלם לפלט שחייב להישאר חד בכל זום, או שכלים אחרים יעבדו הלאה.

use SVG;

my $svg = SVG->new(width => 200, height => 200);

# a group carries shared style; children inherit it
my $g = $svg->group(id => 'shapes',
                    style => { stroke => 'black', fill => 'none' });

$g->line(x1 => 0, y1 => 0, x2 => 200, y2 => 200);
$g->circle(cx => 100, cy => 100, r => 50, style => { fill => 'skyblue' });
$g->rect(x => 10, y => 10, width => 40, height => 40);
$g->path(d => 'M10 190 L100 100 L190 190 Z');   # a triangle via path data

$svg->text(x => 60, y => 110)->cdata('Hello');

print $svg->xmlify;

ה־hash של הסגנון ממופה לתכונות התצוגה של SVG: stroke, fill, stroke-width, opacity והשאר. group (בכינוי g) עם סגנון הוא כיצד אתם נמנעים מחזרה על תכונות בכל אלמנט; ילדים יורשים ויכולים לדרוס. טקסט מצורף עם cdata משורשר מפני שתוכן התו הוא צומת־ילד, לא תכונה.

עבור מצולע מנקודות מחושבות, get_path מרכיב עבורכם את מחרוזת הנקודות:

my @x = (50, 150, 100);
my @y = (10, 10, 90);
my $points = $svg->get_path(x => \@x, y => \@y, -type => 'polygon');
$g->polygon(%$points, style => { fill => 'coral' });

xmlify (מאוית גם to_xml או render) מחזיר את המסמך הגמור כמחרוזת. כתבו אותו לקובץ .svg והוא נפתח בכל דפדפן; מסרו אותו לממיר עבור PDF או PNG.

Cairo או SVG?#

אתם רוצים …

פנו אל

פיקסלים עכשיו, מוחלקי־קצוות, מקואורדינטות של מספרים ממשיים

Cairo

פלט ווקטור כקובץ עבור דפדפנים או כלים אחרים

SVG

לרנדר את אותו ציור ל־PNG, PDF ו־SVG מ־API אחד

Cairo

ללא תלות מהודרת כלל (Perl טהור)

SVG

השניים גם מתחברים: חוללו מבנה כתגיות SVG, ואז רנדרו אותו לפיקסלים עם רסטרייזר כשאתם זקוקים ל־bitmap. עבור פלט ווקטור יישומי בצורה הספציפית של תרשימים וגרפים, ועבור קריאת המטא־נתונים שכבר בתוך קובצי תמונה, הפרק הבא מכסה את תומכי־הספרים המעשיים של עבודת רסטר וווקטור.