UP | HOME
جناوي

السيد مذهل
mr. fantastic

طالب هندسة برمجيات - مهتم بالرسوميات والهندسة الصوتية

Software engineering student - interested in graphics and audio engineering

رسم المتجهات بواسطة بوست سكريبت (PostScript)
نشر في Oct 14, 2020 بقلم السيد مذهل.

قائمة المحتويات

ما هو بوست سكريبت (Post Script) ولماذا؟

لغة برمحة أو صيغة بوست سكريبت (PostScript) هي لغة برمجة بسيطة لنطاق معين (domain-specific language (DSL)) وهو رسم المتجهات وما نعني بالمتجهات (Vector graphics) هي الصور التي ترسم بصيغة وصفية حيث مهما قمنا بتكبير الصورة لن تفقد جودتها على عكس الصور والرسوميات النقطية (Pixel-based) والعديد من المحررات وأدوات الرسم الرسومية قادرة على كتابة وتصدير هذه الصيغة ومنها أنكسكيب (Inkscape) و جيمب (Gimp) وغيرها الكثير الكثير.

ولكن ما دام بوست سكريبت مدعوماً من العديد من البرامج الرسومية لماذا نتعلمه إذاً؟

هذا سؤال وجيه وللأجابة عنه نستطيع أن نقول أن نموذج رسم بوست سكريبت (PostScript drawing model) نموذج منتشر بشكل كبير جداً بحيث أن حتى مكتبة GTK+3 الشهيرة للتطوير الواجهات الرسومبة تستخدم هذا النموذج لرسم القطعة الخاصة التي يطور المبرمج (Custom widgets) وهذه الصيغة مدعومة من كل الطابعات الحديثة وتتيح لنا رسم الأشكال البسيطة دون الحاجة للدخول لبرنامج متخصص برسم المتجهات كأنكسكيب أو رسم الأشكال التي تحتاج عمليات تكرارية وهندسة وما إلى هنالك مع العلم بأن أحد أهداف هذه المدونة المتواضعة هو طرح مواضيع متعلقة برسوميات الحاسوب وبرمجة هندسة الصوتيات.

الأدوات اللازمة

لأستخدام بوست سكريبت سنحتاج إلى تثبيت مفسر اللغة (Language interpreter) وهنا سنستخدم نسخة حرة وشهيرة تسمى Ghostscript ويمكن تنزيله من الموقع الرسمي والرجوع للوثائق رغم أن تثبيت غير لازم لأننا نستيطع أستخدام جيمب وأنكسكيب اللذان يملكان نسخة مضمنة فيهما من ما يتيح لهما فتح هكذا نوع من الملفات.

مستخدمين ويندوز يستطيع تنزيل المثبت وحتى مستخدمين التوزيعات الجناوية (GNU/Linux distributions) ولكن يفضل تنزيله من المستودعات الرسمية:

آرتش ومشتقاتها:

$ sudo pacman -S ghostscript

دبيان ومشتقاتها:

$ sudo apt-get install ghostscript

جنتو ومشتقاتها:

$ sudo emerge --ask app-text/ghostscript-gpl

ردهات وفيدورا ومشتقاتهما:

$ sudo dnf install ghostscript

وأما مستخدمين الماك فبأمكانهم أتباع هذا الشرح أو بناء الشفرة المصدرية وهذا قد يكون شيء جديد على بعض القراء لذلك لن أشرحه ولكن أضع ملاحظة صغيرة مفادها أن بناء الشفرة المصدرية للبرمجيات أسهل في أغلب الحالات عند أستخدام التوزيعات الجناوية ويليها الماك والأصعب هو ويندوز بالأخص إذا كان البرنامج متعدد الأنظمة وغير مخصص لويندوز.

ولإنشاء ملفات بوست سكريبت يمكننا أستخدام إي محرر نصوص وفي حالتي سوف أستخدام إيماكس لأنه يلون الشفرة المصدرية وفيه أختصار لعرض الرسم وكل هذا وزيادة دون إضافات ولكن بشرط توفر Ghostscript مثبت.

لنرسم

%!
%% comment line

50 50 moveto
200 200 lineto
stroke

showpage

أحفظ هذا النص داخل ملف drawing.ps وقم بإدخال هذا السطر الأتي في الطرفية (commandline):

للمبتدئين: عندما ترى علامة الدولار $ في الأوامر التي أنشرها لا تنسخها مع الأمر لأنها دلالة على أن الأمر يشغل كمستخدم عادي الصلاحيات

$ gs -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -dGraphicsAlphaBits=4 -sOutputFile=drawing.png drawing.ps

وستكون النتيجة رسم خط بالعرض الأفتراضي.

eg1.png

شكل 1: شاشة الضبط

أو يمكنك أستخدام إيماكس لعرض وتعديل ملف بوست سكريبت كما هو موضح بالصورة المتحركة أدناه:

ps-mode.gif

شكل 2: صورة متحركة توضح طريقة أستخدام إيماكس لعرض وتعديل ملفات بوست سكريبت

للأنتقال من وضع العرض لوضع التعديل والعكس أستعمل هذا الأختصار C-c C-c

وإيضاً هناك خيار خياران آخران أولهما هو فتح الملف بأستخدام برنامج يدعم صيغة بوست سكريبت كجيمب (Gimp) والآخر هو أستخدام المفسر (Interpreter) الذي يأتي مع ghostscript وهو gsx:

gsx.gif

شكل 3: طريقة أستخدام المفسر

مع العلم أن حجم الصفحة الأفتراضي يعتمد على النظام واللغة والبلد في حاسوبك ففي الكثير من الأحيان هو A4 ولكن ليس دوماً.

وأما الأن لنتفرغ لشرح ما جرى:

fig1.png

شكل 4: طريقة الترتيب العكسي

أولاً بوست سكريبت يستخدم طريقة الترتيب العكسي (Postfix) بحيث يضع خيارات الدالة (Function arguments) قبل أسم الدالة بدون أقواس وثانياً لا يمكننا أستخدام lineto أو curveto دون تحديد والترحك لموقع معين بأستخدام moveto التي تأخذ الأحداثيات x,y وثالثاً إذا لم تستعمل showpage إي أظهر الصفحة فلا شيء سيظهر وهذا أبسط مثال فبعدها ننتقل لنتعلم الدوال الشائعة الآخرى عبر الأمثلة.

نظام الأحداثيات في بوست سكريبت يبدأ من الزاوية اليسرى السفلى (وهنا أختلاف بينه وبين libcairo التي تبدأ من الزاوية اليسرى العلوية) واليمين هو محور x الموجب والأعلى هو محور y الموجب وما عكسهما هو السالب.

fig2.png

شكل 5: نظام أحداثيات بوست سكريبت

المثال الثاني:

% draw triangle
100 200 moveto
200 250 lineto
100 300 lineto
closepath

gsave
0.5 0.5 1 setrgbcolor
fill
grestore

10 setlinewidth
stroke

% draw unfilled rectangle
200 100 100 100 rectstroke
stroke

% draw filled unstroke rectangle
gsave
1 0 1 setrgbcolor
240 210 100 100 rectfill
stroke
grestore

% draw not completed circle (arc)
120 370 60 0 350 arc
stroke

showpage

eg2.png

شكل 6: المثال الثاني

لتوضيح بعض النقاط بالمثال الثاني:

  • أولاً عندما كنا نرسم المثلث لم نقم بوضع الأحداثيات للنقطة الأخيرة بل أستعملنا دالة closepath لغلق المسار وبعدها لم نقم برسم الخط مباشرة ولا ملء الشكل بإي لون مباشرة لأننا لو قمنا بأحد هذه العمليات سنفقد السيطرة على الشكل فلا يمكن ملء الشكل وبعدها رسم الخط بأستخدام stroke مباشرة لذلك أحتجنا لأن نحفظ الحالة (state) بأستخدام gsave و grestore ومن ثمة غيرنا اللون عبر setrgbcolor التي تأخذ قيم الألوان أحمر - أخضر - أزرق بالترتيب وبقيم كسرية ما بين الصفر والواحد وملأنا الشكل وبعدها عدنا للحالة الأولى ورسمنا الخط stroke.
  • ثانياً وضحنا طريقة أستخدام دالتين لرسم مستطيل وفي حالتنا كان المستطيل متوازي الأضلاع (مربع) وإيضاً وضحنا كيفية أستخدام دالة القوس arc ورسمنا بها دائرة غير مكتملة وهذه نماذج الدوال المذكورة:

x y radius angle1 angle2 arch

x y width height rectfill

x y width height rectstroke

المثال الأتي يشرح أنواع أغطية المسارات والوصلات وكيفية أستخدام الخطوط:

ملاحظة: لم أكتب النص بالمثال باللغة العربية لأن بوست سكريبت لا يدعمها وسنتكلم عن هذا لأحقاً في قسم ماذا بعد

/Times-Roman findfont
20 scalefont
setfont
newpath
100 200 moveto
(Happy, ) show

/Helvetica-BoldOblique findfont
20 scalefont
setfont
newpath
160 200 moveto
(Hacking) show

%% 1st linecap demo
100 100 moveto
100 0   rlineto
0 setgray
10 setlinewidth
0 setlinecap %% Focus here
stroke

100 100 moveto
100 0   rlineto
1 setgray
1 setlinewidth
stroke

%% 2nd linecap demo
100 80 moveto
100 0   rlineto
0 setgray
10 setlinewidth
1 setlinecap %% Focus here
stroke

100 80 moveto
100 0   rlineto
1 setgray
1 setlinewidth
stroke

%% 3rd linecap demo
100 60 moveto
100 0   rlineto
0 setgray
10 setlinewidth
2 setlinecap %% Focus here
stroke

100 60 moveto
100 0   rlineto
1 setgray
1 setlinewidth
stroke

0 setlinecap % rest to default line cap style, this could be avoided
             % by saving state with gsave, grestore

%%%%%%%%%%%%%%%%%%%%%%%
0 setgray
10 setlinewidth

%% 1st line joint style
280 220 moveto
70 0 rlineto
-70 70 rlineto
0 setlinejoin %% Focus here
stroke

%% 2nd line joint style
280 130 moveto
70 0 rlineto
-70 70 rlineto
1 setlinejoin %% Focus here
stroke

%% 3rd line joint style
280 35 moveto
70 0 rlineto
-70 70 rlineto
2 setlinejoin %% Focus here
stroke

showpage

eg3.png

شكل 7: المثال الثالث

الجدير بالذكر بالمثال أعلاه هو أستهخدامنا للأحداثيات المجاورة للنقطة الحالية بمعنى أن أنتقلنا أو سقنا خطاً للنقطة (100,100) وأستخدمنا rlineto بقيم x = 100 و y = 0 فهذا يعني تقدمنا مائة نقطة نحو محور x بالموجب فيكون موقعنا الدقيق حينها x = 200 و y = 100 مع العلم أن النقطة الواحدة ببوست سكريبت تمثل 1/72 بوصة (inch) وملاحظة هامة أخرى يجب الأنتباه لها هو أننا نكتب كل أمر في سطر وهذا لتسهيل قراءة الشفرة المصدرية ولكن هذا غير لازم فيسعنا أن نكتب كل الأوامر بسطر واحد أو أثنين.

إذا كنت تستخدم إيماكس وكنت تعدل ملف بوست سكريبت وأنت في وضع التعديل لا العرض يمكنك الذهاب للقائمة العلوية:

PostScript > Fonts (1)

أو

PostScript > Fonts (2)

لتجد قائمة بالخطوط المثبتة لبوست سكريبت في نظامك وهذه مجموعات الخطوطات الأساسية التي تأتي مع ghostscript:

* Fonts (1)
      1) Times-Roman
      2) Times-Bold
      3) Times-Italic
      4) Times-BoldItalic
      5) Helvetica
      6) Helvetica-Bold
      7) Helvetica-Oblique
      8) Helvetica-BoldOblique
      9) Courier
      10) Courier-Bold
      11) Courier-Oblique
      12) Courier-BoldOblique
      13) Symbol

* Fonts (2)             
      1) AvantGarde-Book
      2) AvantGarde-Demi
      3) AvantGarde-BookOblique 
      4) AvantGarde-DemiOblique 
      5) Bookman-Light 
      6) Bookman-Demi 
      7) Bookman-LightItalic
      8) Bookman-DemiItalic
      9) Helvetica-Narrow
      10) Helvetica-Narrow-Bold
      11) Helvetica-Narrow-Oblique
      12) Helvetica-Narrow-BoldOblique
      13) NewCenturySchlbk-Roman
      14) NewCenturySchlbk-Bold
      15) NewCenturySchlbk-Italic
      16) NewCenturySchlbk-BoldItalic
      17) Palatino-Roman
      18) Palatino-Bold
      19) Palatino-Italic
      20) Palatino-BoldItalic
      21) ZapfChancery-MediumItalic
      22) ZapfDingbats

هنا نوضح طريقة برمجة دالة تأخذ معطيات وأخرى لا تأخذ وإيضاً كيف نستخدم الحلقات التكرارية (loops):

/myshape {
    0 0 moveto
    -15 0 rlineto
    -15 10 -15 90 -5 100 rcurveto
    0 10 rlineto
    -5 0 rlineto
    0 10 rlineto
    25 0 rlineto
    0 -10 rlineto
    -5 0 rlineto
    0 -10 rlineto
    15 -10 15 -90 5 -100 rcurveto
    stroke
} def

/myshape_plus {
    /blue  exch def
    /green exch def
    /red   exch def
    gsave
    0 0 moveto
    -15 0 rlineto
    -15 10 -15 90 -5 100 rcurveto
    0 10 rlineto
    -5 0 rlineto
    0 10 rlineto
    25 0 rlineto
    0 -10 rlineto
    -5 0 rlineto
    0 -10 rlineto
    15 -10 15 -90 5 -100 rcurveto
    gsave
    red green blue setrgbcolor
    fill
    grestore
    stroke
    grestore
} def

100 100 translate

myshape

100 0 translate

1 0 0 myshape_plus

-40 180 translate

0 1 9 {
    /iter exch def
    iter 4 mul rotate
    30 30 translate
    myshape
} for

0 1 9 {
    /iter exch def
    iter 4 mul rotate
    30 30 translate
    0 1 0 myshape_plus
} for

showpage

eg4.png

شكل 8: نتيجة الدوال والدورة

بمثالنا أعلاه قمنا بتعريف دالتين كما مبين بالشفرة وهما myshape و myshape_plus وكما نلاحظ أن الأولى لا تأخذ عوامل وما فيها مجرد سرد لخطوات رسم المزهرية وأما الثانية تأخذ عوامل (Function arguments) وما يجب ملاحظته هنا هو أن العوامل بتعريف الدالة يجب أن تكتب بشكل عكسي وبالنسبة لتوضيح أستعمال الدورة (loop) فالقيم المعطاة كالأتي (القيم الأولية - الزبادة أو النقصان - الحد أو القيمة النهاية) ويوضع جسد الدورة داخل الأقواس العرجاء {} وبعدها مفردة for.

من الملاحظ أستعمالنا بالمثال السابق لعملية الضرب الرياضية mul التي تأخذ عددين فقط للضرب كعوامل وهكذا بقية العمليات الرياضية مثل الجمع add والطرح sub والقسمة div.

لا ننسى أستخدامنا لدالة الإزاحة translate وهذه الدالة تختلف عن دالة التحرك moveto ويمكن توضيحها وأخواتها من scale و rotate كما يلي:

fig3.png

شكل 9: سحب وتدوير وتحجيم المحور

مع العلم أن القيم الكسرية التي هي أقل من واحد تصغر المحور وما هو أكبر من واحد يكبر المحور في دالة التحجيم scale ودالة rotate تأخذ قيمة زاوية تتراوح ما بين 0 إلى 360 درجة فإذا كانت القيمة موجبة سيتم الدوران على عكس عقارب الساعة بينما إذا كانت سالبة سيتم الدوران حول عقارب الساعة.

الجمل الشرطية (if statement) والمتغيرات ذات النطاق المحلي (local variables) وكيفية تعريف متغير (variable):

/myshape {
    0 0 moveto
    -15 0 rlineto
    -15 10 -15 90 -5 100 rcurveto
    0 10 rlineto
    -5 0 rlineto
    0 10 rlineto
    25 0 rlineto
    0 -10 rlineto
    -5 0 rlineto
    0 -10 rlineto
    15 -10 15 -90 5 -100 rcurveto
    stroke
} def

/myshape_plus {
    3 dict begin
    /blue  exch def
    /green exch def
    /red   exch def
    gsave
    0 0 moveto
    -15 0 rlineto
    -15 10 -15 90 -5 100 rcurveto
    0 10 rlineto
    -5 0 rlineto
    0 10 rlineto
    25 0 rlineto
    0 -10 rlineto
    -5 0 rlineto
    0 -10 rlineto
    15 -10 15 -90 5 -100 rcurveto
    gsave
    red green blue setrgbcolor
    fill
    grestore
    stroke
    grestore
    end % end dict begin
} def

100 100 translate

myshape

100 0 translate

1 0 0 myshape_plus

-40 180 translate

0 1 18 {
    /iter exch def
    iter 4 mul rotate
    30 30 translate
    iter 2 mod 0 eq {
        myshape
    } {
        1 0.5 0.5 myshape_plus
    } ifelse
} for

/pi 3.1416 def % define variable

showpage

eg10.png

كما هو موضح بالمثال أعلاه فأننا قمنا بأستخدام جملة ifelse الشرطية التي تقوم بشيء في حالة تحقق الشرط وإلا تنتقل إلى جسد القوسان التاليان وهناك جملة شرطية آخرى ببوست سكربت وهي الأبسط if فيها فقط قوسان وليس أربعة وأما لإيضاح الشرط فيجب أن يتكون الشرط من مقارنة منطقية بأستخدام شرط من الشروط مثل يساوي eq, لا يساوي ne, أكبر من gt, أكبر من أو يساوي ge, أصغر من lt, أصغر من أو يساوي le ومن الملاحط أستعمالي لدالة باقي القسمة mod حتى أحقق تفاوت في الرسم عبر رسم ما باقي قسمته على أثنين يساوي صفر بلا لون وما لا يساوي صفر بلون.

رغم أنني لم أستخدام بعض رموز الأحتمال والمنطق لكن سأشير إليها إشارة سريعة: «و» المنطقية and, «أو» or, «أو الحصرية» xor, صحيح true, غير صحيح false, ليس not.

لتعريف المتغيرات ذات النطاق المحلي علينا إنشاء قاموس يضمها وذلك عبر تحدديد عددهم ووضعهم داخل جملتين n dict begin وختمها بـ end حيث n هو عدد المتغيرات.

المزيد من الوصفات

غلاف كتاب:

% the trick is to draw our object in the center point and then translate it because if we rotate
% our object far from the center point the object would move of y and x axis's

/ara_zahrafa {
    10 dict begin
    /y exch def
    /x exch def
    /lwidth 10 def
gsave
    lwidth setlinewidth
    x y translate
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    gsave
    0 1 0 setrgbcolor
    fill
    grestore
    stroke

    45 rotate
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    gsave
    0 0 1 setrgbcolor
    fill
    grestore
    stroke

    %%%%%%%%%%%%%%%%%%%%%%%%%%%% second stage (inner area)
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    clip

    newpath
    45 rotate
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    gsave
    1 0 0 setrgbcolor
    fill
    grestore
    stroke

    %%%%%%%%%%%%%%%%%%%% Making the inner borders looks nice
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    clip

    newpath

    45 rotate
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    stroke
grestore
} def

0.5 0.5 scale

0 1 5 {
    /iter0 exch def
    0 1 4 {
        /iter exch def
        gsave
        iter 300 mul
        iter0 300 mul ara_zahrafa
        grestore
    } for
} for

1 setgray
100 100 1000 1300 rectfill

10 setlinewidth
0 setgray
100 100 1000 1300 rectstroke

/Times-Roman findfont
200 scalefont
setfont
newpath
200 1000 moveto
(The Book) show


/Times-Roman findfont
50 scalefont
setfont
newpath
340 900 moveto
(On Explaining Something) show


/Times-Roman findfont
50 scalefont
setfont
newpath
230 500 moveto
(Eng. Mr. Sci. Gen. Author Ibn Author) show


/Times-Roman findfont
50 scalefont
setfont
newpath
380 200 moveto
(Happy Hacking Press) show

showpage

eg5.png

قف:

0 0 900 900 rectfill % black background

/stop_sign {
    10 dict begin
    /y exch def
    /x exch def
    /lwidth 10 def
gsave
    lwidth setlinewidth
    1 setgray
    x y translate
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    clip

    newpath
    45 rotate
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    gsave
    1 0 0 setrgbcolor
    fill
    grestore
    stroke

    %%%%%%%%%%%%%%%%%%%%%%%
    newpath
    lwidth setlinewidth
    -100 -100 moveto
    200 0 rlineto
    0 200 rlineto
    -200 0 rlineto
    closepath
    clip

    45 rotate
    -100 lwidth 2 div add 1 sub
    -100 lwidth 2 div add 1 sub
    200 lwidth sub 2 add 200 lwidth sub 2 add
    rectstroke

    -90 rotate
    /Times-Roman findfont
    75 scalefont
    setfont
    newpath
    -90 -29 moveto
    (STOP) show
    stroke
grestore
    end
} def

0 1 4 {
    /iter0 exch def
    0 1 4 {
        /iter exch def
        gsave
        1 1 1 setrgbcolor
        iter 200 mul
        iter0 200 mul stop_sign
        grestore
    } for
} for

showpage

eg6.png

لوحة مفاتيح:

<< /PageSize [842 1191] >> setpagedevice

% height width corner text fontsize
/key {
    9 dict begin
    /fontsize exch def
    /text exch def
    /corner exch def
    /width exch def
    /height exch def
    %    gsave

    newpath
    width 2 div height 2 div corner 0 90 arc
    width neg 0 rlineto
    width 2 div neg height 2 div corner 90 -180 arc
    0 height neg rlineto
    width 2 div neg height 2 div neg corner -180 -90 arc
    width 0 rlineto
    width 2 div height 2 div neg corner -90 0 arc
    %    0 height rlineto
    closepath
    stroke

    /Times-Roman findfont
    fontsize scalefont
    setfont
    newpath
    width 3 div neg 0 moveto
    text show
    end
} def

% height width corner text fontsize space
/insert {
    9 dict begin
    /space exch def
    /fontsize exch def
    /text exch def
    /corner exch def
    /width exch def
    /height exch def

    height width corner text fontsize key
    width corner 2 mul add space add 0 translate
    end
} def

0.49 0.49 scale

gsave % BEGIN 1 row
50 500 translate
50 50 10 (Esc) 25 90 insert

50 50 10 (F1) 25 5 insert
50 50 10 (F2) 25 5 insert
50 50 10 (F3) 25 5 insert
50 50 10 (F4) 25 50 insert

50 50 10 (F5) 25 5 insert
50 50 10 (F6) 25 5 insert
50 50 10 (F7) 25 5 insert
50 50 10 (F8) 25 50 insert

50 50 10 (F9) 25 5 insert
50 50 10 (F10) 25 5 insert
50 50 10 (F11) 25 5 insert
50 50 10 (F12) 25 20 insert

50 50 10 () 20 5 insert
-105 20 moveto
(Print) show
-105 0 moveto
(Scrn) show
-105 -5 moveto
(_____) show
-105 -25 moveto
(Sys Rq) show

50 50 10 () 25 5 insert
-105 5 moveto
(Scroll) show
-105 -20 moveto
(Lock) show


50 50 10 () 20 5 insert
-100 10 moveto
(Pause) show
-100 0 moveto
(_____) show
-100 -20 moveto
(Sys Rq) show
grestore % END 1 row

gsave % BEGIN 2 row

50 410 translate

50 50 10 (~) 25 5 insert
50 50 10 (1) 25 5 insert
50 50 10 (2) 25 5 insert
50 50 10 (3) 25 5 insert
50 50 10 (4) 25 5 insert
50 50 10 (5) 25 5 insert
50 50 10 (6) 25 5 insert
50 50 10 (7) 25 5 insert
50 50 10 (8) 25 5 insert
50 50 10 (9) 25 5 insert
50 50 10 (0) 25 5 insert
50 50 10 (-) 25 5 insert
50 50 10 (+) 25 55 insert

50 150 10 (<- Backspace) 25 0 insert
-30 0 translate

50 50 10 (Insert) 20 5 insert

50 50 10 (Home) 20 5 insert

50 50 10 () 20 20 insert
-100 10 moveto
(Page) show
-100 -20 moveto
(Up) show

50 50 10 () 20 5 insert
-100 10 moveto
(Num) show
-100 -20 moveto
(Lock) show

50 50 10 (/) 20 5 insert
50 50 10 (*) 20 5 insert
50 50 10 (-) 20 5 insert

grestore % END 2 row


gsave % BEGIN 3 row

75 335 translate

50 100 10 (Tab) 25 0 insert
-110 10 moveto
(|<--) show
-110 -20 moveto
(-->|) show
-20 0 translate

50 50 10 (q) 25 5 insert
50 50 10 (w) 25 5 insert
50 50 10 (e) 25 5 insert
50 50 10 (r) 25 5 insert
50 50 10 (t) 25 5 insert
50 50 10 (y) 25 5 insert
50 50 10 (u) 25 5 insert
50 50 10 (i) 25 5 insert
50 50 10 (o) 25 5 insert
50 50 10 (p) 25 5 insert
50 50 10 ({) 25 5 insert
50 50 10 (}) 25 30 insert

50 100 10 (|) 25 25 insert
-30 0 translate

50 50 10 (Delete) 20 5 insert

50 50 10 (End) 20 5 insert

50 50 10 () 20 20 insert
-100 10 moveto
(Page) show
-110 -20 moveto
(Down) show

50 50 10 (7) 20 5 insert
50 50 10 (8) 20 5 insert
50 50 10 (9) 20 5 insert

0 -38 translate
127 50 10 (+) 20 5 insert
grestore % END 3 row

gsave % BEGIN 4 row
75 260 translate

10 0 translate
50 120 10 (Caps) 25 0 insert
-180 -30 moveto
(Lock) show
-110 20 moveto
0 -40 rlineto
stroke
-30 0 translate

50 50 10 (a) 25 5 insert
50 50 10 (s) 25 5 insert
50 50 10 (d) 25 5 insert
50 50 10 (f) 25 5 insert
50 50 10 (g) 25 5 insert
50 50 10 (h) 25 5 insert
50 50 10 (j) 25 5 insert
50 50 10 (k) 25 5 insert
50 50 10 (l) 25 5 insert
50 50 10 (:) 25 5 insert
50 50 10 (") 25 58 insert

50 155 10 (<--| Enter) 25 207 insert

50 50 10 (4) 20 5 insert
50 50 10 (5) 20 5 insert
50 50 10 (6) 20 5 insert
grestore % END 4 row

gsave % BEGIN 5 row
75 185 translate
15 0 translate
20 0 translate
50 175 10 (/|\\ Shift) 25 0 insert
-55 0 translate

50 50 10 (z) 25 5 insert
50 50 10 (x) 25 5 insert
50 50 10 (c) 25 5 insert
50 50 10 (v) 25 5 insert
50 50 10 (b) 25 5 insert
50 50 10 (n) 25 5 insert
50 50 10 (m) 25 5 insert
50 50 10 (<) 25 5 insert
50 50 10 (>) 25 5 insert
50 50 10 (?) 25 68 insert

50 175 10 (/|\\ Shift) 25 20 15 add insert
50 50 10 (/|\\) 25 92 insert

50 50 10 (1) 20 5 insert
50 50 10 (2) 20 5 insert
50 50 10 (3) 20 5 insert

0 -40 translate
127 50 10 (Enter) 20 5 insert
grestore % END 5 row


gsave % BEGIN 6 row
70 110 translate
50 90 10 (Ctrl) 25 40 insert
-55 0 translate

50 60 10 (GNU) 25 0 insert
50 50 10 (Alt) 25 235 insert
50 510 10 (                        Space) 25 0 insert

-225 0 translate
50 50 10 (Alt) 25 5 insert
50 60 10 (GNU) 25 0 insert
50 50 10 (_=-) 25 25 insert
50 90 10 (Ctrl) 25 3 insert

50 50 10 (<) 25 5 insert
50 50 10 (\\|/) 25 5 insert
50 50 10 (>) 25 54 insert

50 125 10 (0) 20 0 insert
-32 0 translate
50 50 10 (.) 20 5 insert
grestore % END 6 row

showpage

eg7.png

زهور:

%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 595 842
%%Title: t.ps
%%Creator: Hacker
%%CreationDate: Wed Aug 26 00:19:36 2020
%%EndComments

64 dict begin

% xpos ypos scale
/tri-cir-symbol {
    64 dict begin
    /B exch def
    /G exch def
    /R exch def
    /xyscale exch def
    /ypos exch def
    /xpos exch def
    gsave
    xpos ypos translate

    10 setlinewidth

    xyscale xyscale scale

    0 45 360 {
        /iter exch def
        iter rotate
        200 0 83 -90 90 arc
        0 0 lineto
        closepath

        gsave
        R G B setrgbcolor
        fill
        grestore

        stroke
    } for
    grestore
    end
} def

gsave
0 0.5 0.5 setrgbcolor
0 0 1000 1000 rectfill
grestore

0 1 6 {
    /iter0 exch def
    0 1 6 {
        /iter1 exch def
        gsave
        120 iter1 mul 120 iter0 mul 0.2
        1 1 0
        tri-cir-symbol
        grestore
    } for
} for

0 1 6 {
    /iter0 exch def
    0 1 6 {
        /iter1 exch def
        gsave
        120 iter1 mul 120 iter0 mul 0.15
        0 1 0
        tri-cir-symbol
        grestore
    } for
} for

0 1 6 {
    /iter0 exch def
    0 1 6 {
        /iter1 exch def
        gsave
        120 iter1 mul 120 iter0 mul 0.09
        1 0 0
        tri-cir-symbol
        grestore
    } for
} for

end
showpage
%%EOF

eg8.png

الين واليان:

300 500 moveto

500 300
100 300
300 100 curveto
300 300 200 -90 90 arc
6 setlinewidth

gsave
fill
grestore
stroke

300 300 200 90 -90 arc
stroke

300 200 20 0 360 arc
1 setgray
fill

300 400 20 0 360 arc
0 setgray
fill

showpage

eg9.png

صفحات متعددة بأحجام وأستدارة مختلفة:

%!PS-Adobe-3.0
%%Title: landscape PDF example
%%Pages: 3
%%EndComments
%%BeginProlog
%%EndProlog
%%BeginSetup
% Document information
[/CreationDate (D:20040224)
/Creator (Hand crafted by Russell Lang)
/Title (landpdf.ps) % note that GS can get title from DSC %%Title
/Subject (Example of landscape and portrait pages)
/Keywords (landscape portrait example Ghostscript DOCINFO)
/Author (Ghostgum Software Pty Ltd)
/DOCINFO pdfmark

%%EndSetup
%%Page: 1 1
% Set the page size to A4
<< /PageSize [595 842] >> setpagedevice
/Helvetica findfont 100 scalefont setfont
100 200 moveto (1 portrait) show
showpage

%%Page: 2 2
%%PageOrientation: landscape
% Set the page size to A3
<< /PageSize [842 1191] /Orientation 3 >> setpagedevice
90 rotate 0 -842 translate
/Helvetica findfont 100 scalefont setfont
100 200 moveto (2 landscape) show
showpage

%%Page: 3 3
% Set the page size to A4
<< /PageSize [595 842] >> setpagedevice
/Helvetica findfont 100 scalefont setfont
100 200 moveto (3 portrait) show
showpage

%%Trailer
%%EOF

تهكيرات عجيبة

أشياء غير أعتيادية في بوست سكريبت لم يصمم بوست سكريبت لها:

  • لعبة الحياة كون وي (هذه ليست لعبة أصلاً هذه خوارزمية أبتكرها عالم الرياضيات جون كون وي ليصف تطور العناصر بشكل رياضي) مكتوبة ببوست سكريبت.
  • خادم (server) مكتوب بلغة بوست سكربت لم تتح لي فرصة تجربته لأنه يعتمد على برنامج inetd الخاص بالشبكات والذي تم أستبداله ببرنامج xinetd ولست خبيراً فيهما.

ماذا بعد

في هذه المقالة طرحنا الأساسيات فالخطوة التالية تكون بقراءة الدليل الرسمي1 الصادر بسنة 1985 وأخر نسخة بسنة 1999 وهنا إشارة لقدم هذه اللغة التي طورها مؤسسوا شركة أدوبي وقد أستعملت وما زالت تستعمل في الطباعة بشكل كبير.

ومن ناحية أخرى يمكنك الإطلاع على دليل ghostscript الرسمي للتعرف على خيارات هذا البرنامج وكما أنصح بالإطلاع على شرح Paul Bourke الممتاز لبوست سكريبت.

يمكنكم الإطلاع على هذا الرابط المحتوي على بعض الزخارف الهندسية والإسلامية المرسومة بواسطة بوست سكريبت وهذا الرابط الذي يحتوي على فركتولات مرسومة ببوست سكريبت وإيضاً هذا الرابط وكتاب وصفات بوست سكريبت.

وبما أننا بعد هذه المقالة تعلمنا نموذج بوست سكريبت (PostScript drawing model) فبأستطاعتنا تعلم مكتبة Cairo (القاهرة) لأستعمال لصنع القطع الخاصة (Custom widgets) في GTK3 أو أستخدامها لتطوير برنامج يصدر مستندات بشكل تلقائي أو محرر مستندات وذلك لأن مكتبة القاهرة البرمجية إذا ما أستعملت مع مكتبة بانغو (Pango) يمكنها دعم اللغة العربية وكل لغات العالم وتستطيع دعم العديد من المميزات للخطوط وهكذا تتخطى مشكلة بوست سكريبت مع الخطوط.

ونختم هذه المقالة بالقول أن هناك ما تزال بعض خوارزميات الضغط في بوست سكريبت خاضعة لبراءات الأختراع فوجب التنبيه.

comments . التعليقات

الهوامش: