مقال تقني

استيراد متجهات EMF على Free Pascal مع PDFlibPas

يحوّل PDFlibPas الملفات التعريفية المحسنة إلى محتوى صفحات PDF حقيقي سجلا بسجل بدل تحويلها إلى صور نقطية، وهو ما يحافظ على حدة المخطط المستورد أو رسم CAD عند أي تكبير. ذلك المحول يبلغ نحو 6500 سطر وقد كُتب مقابل VCL، فلما حصلت المكتبة على هدف Free Pascal صُنف على أنه غير قابل للنقل واستُبدل بـ stub يرمي استثناء. هذا التصنيف كان خاطئا، وطريقته في الخطأ درس مفيد في كيفية تدقيق اعتمادية قبل أن تقرر إعادة الكتابة حولها

تبيّن أن السطح الفعلي لـ VCL في تلك الأسطر الـ 6500 صغير: صنف bitmap يُستخدم من أجل صيغة بكسله والحفظ في مسار ومقبضه ولوحة رسمه وخطوط مسحه؛ وصنف ملف تعريفي يُستخدم من أجل عرضه وارتفاعه ومقبضه؛ ونوع اللون مع ثابتين. وكل واحد من ذلك كانت وحدة الرسوميات الخاصة بالمكتبة توفره أصلا، وهي موجودة تحديدا كي يكون للبناء غير المعتمد على VCL مكافئات. المحول لم يكن معطلا بسبب VCL إطلاقا، بل بسبب وحدة Windows في Free Pascal

قسّم على المحور الذي يعتمد عليه الكود فعلا

فلم يكن التغيير إعادة تنفيذا. كان شرطا تجميعيا واحدا: من «ترجم الـ stub عند البناء دون VCL» إلى «ترجم الـ stub عند عدم البناء لـ Windows». هذا هو المحور الصحيح، وذكر السبب يجعل الفرق بديهيا. الملف التعريفي المحسن حاوية Windows، والمحول محلل لسجلات GDI الخاصة بـ Windows من أوله إلى آخره. أما كون التطبيق المضيف يستخدم VCL أو مجموعة أدوات واجهة أخرى أو لا يستخدم شيئا منها فلا علاقة له بإمكانية تفسير تلك السجلات؛ وكون الهدف Windows له كل العلاقة بذلك

وعواقب اختيار المحور الصحيح تأتي مجانا. بناءات C++Builder، التي تلغي تعريف رمز منصة Windows في هذه المكتبة، تحتفظ بالـ stub الرامي لاستثناء وتتصرف تماما كما كانت. وmacOS تحتفظ بالـ stub، وهو الصحيح، لأنه لا توجد هناك سجلات GDI لتحليلها. وبناءات Delphi VCL لا تمس. أما بناء Windows بمجموعة أدوات واجهة غير VCL فيكسب استيراد EMF المتجهي كأثر جانبي لم يضطر أحد إلى تنفيذه. الشرط المتوافق مع الاعتمادية الحقيقية يحول عمل المنصات إلى تغيير من سطر واحد؛ والشرط المتوافق مع اعتمادية خاطئة يحوله إلى إعادة كتابة لا تصل إلى جدول الأعمال أبدا

إعادة توجيه شرط استيراد EMF من الانتماء إلى VCL إلى منصة Windows، مع إبقاء الـ stub في الأماكن الأخرى ومنح بناءات Windows غير VCL استيرادا متجهيا
إعادة توجيه شرط الـ stub إلى منصة Windows يحافظ على سلوك كل البناءات القائمة ويمنح أهداف Windows غير VCL استيراد EMF المتجهي مجانا

فجوة Free Pascal كانت تعريفات لا منطقا

المفقود فعلا كان تعريفات Win32 التي توفرها وحدة Windows في Delphi ولا توفرها نظيرتها في Free Pascal. وجمعها في وحدة توافق واحدة بدل نثر شروط تجميعية في المحول أبقى المحلل مقروءا. القائمة مفيدة لأنها تبين مدى تفاوت تغطية الترويسات بين بيئتي التشغيل: 113 ثابتا لأنواع سجلات الملف التعريفي، وعلمان لخرج النص الموسع، وثلاثة ثوابت لوضع التعبئة المتدرجة، ونوع مؤشر لجدول المقابض، وأسماء بديلة لسجلات رؤوس التدرج والعناصر الأولية، وثلاثة أنواع سجلات لا يصرح بها Free Pascal إطلاقا، تغطي المزج ألفا والنقل الشفاف ووضع إدارة الألوان

لا شيء من ذلك مثير بافرادها. لكن جميعها يجب أن يكون صحيحا قبل أن يترجم المحلل، ووحدة التوافق هي الموطن الطبيعي لأنه يمكن إجراء مقارنة فرقية لها مقابل وثائق الترويسات كوحدة واحدة

تعريفات Win32 المفقودة من وحدة Windows في Free Pascal، مجتمعة في وحدة توافق واحدة لمحول EMF المتجهي إلى PDF
ثوابت السجلات والأعلام والأسماء البديلة وثلاثة أنواع سجلات غائبة كلها في وحدة توافق واحدة يمكن مقارنتها فرقيا مقابل وثائق الترويسات

البند الذي يرسم الصورة الخاطئة بصمت

اثنان من تلك التعريفات ليسا مفقودين فحسب، بل موجودان وغير صحيحين لهذا الغرض، وهذه هي الجزئية الجديرة بالتذكر حتى لو لم تلمس ملفا تعريفيا أبدا

يعرّف Free Pascal سجل إنشاء الفرشاة ببنية الفرشاة زمن التشغيل مدمجة فيه، وسجل القلم الموسع ببنية القلم زمن التشغيل مدمجة فيه. وكلا البنيتين زمن التشغيل تعلنان عضو hatch لديهما كعدد صحيح بحجم المؤشر، لأن العضو في نداء GDI حقيقي قد يحمل مقبضا. أما الملف التعريفي فيخزن دائما الصيغة ذات 32 بت، لأن تخطيط السجل جزء من صيغة الملف المتسلسلة ولا يتغير بتغيير عرض بتات العملية

في البناءات ذات 32 بت يتطابق الطرفان ولا شيء يحدث. وفي Win64 يكون العضو ذو حجم المؤشر ثمانية بايتات بينما الملف يضع أربعة، فيقرأ كل حقل بعد عضو hatch من إزاحة خاطئة. لا استثناء، ولا خطأ تحليل، ولا تحذير. الملف التعريفي يُرسم خطأ فحسب: ألوان من بايتات خاطئة، وعرض أقلام من بايتات خاطئة، وصورة تبدو كعيب في الرسم لا كعيب في تخطيط بنية. ويشحن Delphi صيغا صريحة ذات 32 بت للبنيتين لهذا السبب تحديدا، ووحدة التوافق تعيد إعلانهما بالطريقة نفسها

تخطيط بايتات سجل الفرشاة في EMF يظهر حقل hatch بحجم مؤشر يزيح الحقول اللاحقة أربعة بايتات على Win64 مقابل التخطيط الثابت ذي 32 بت
السجل المتسلسل يخزن دائما hatch بأربعة بايتات، فبنية زمن التشغيل ذات حجم المؤشر تقرأ خطأ وبصمت كل حقل لاحق على Win64
// خاطئ على Win64: Hatch بحجم المؤشر، والملف يخزن 32 بتا،
// وكل حقل لاحق يزيح أربعة بايتات دون أي خطأ
type
  TLogBrushRuntime = record
    lbStyle: UINT;
    lbColor: COLORREF;
    lbHatch: ULONG_PTR;      // 8 بايتات في عملية ذات 64 بت
  end;

// صحيح: التخطيط المتسلسل، عرض ثابت بغض النظر عن عرض البتات
type
  TLogBrush32 = record
    lbStyle: UINT;
    lbColor: COLORREF;
    lbHatch: DWORD;          // 4 بايتات دائما، كما يخزن في الملف التعريفي
  end;

القاعدة العامة: أي بنية تظهر معا كوسيط واجهة برمجية زمن التشغيل وكتخطيط حقول متسلسل تحتاج تعريفين، ويجب أن يستخدم المتسلسل أنواعا ثابتة العرض في كل أجزائه. الأعضاء بحجم المؤشر في صيغة ملف هي دائما عيب ينتظر بناء ذات 64 بت

اختلافات التواقيع تنتمي إلى غلاف واحد لا إلى كل موقع استدعاء

كانت الاختلافات المتبقية تفاوتات توقيع عادية، وطريقة امتصاصها غلاف تحويلي لا شرط تجميعي في كل موقع استدعاء. دالة دمج التحويلات تأخذ مؤشرات في Free Pascal حيث تأخذ Delphi معاملات مرجعية، فيأخذ الغلاف المراجع ويمرر العناوين. وهو أيضا ينسخ كلا الوسيطين المصدرين إلى متغيرات محلية أولا، لأن المحول يملك مواقع استدعاء تكون فيها مصفوفة الوجهة في الوقت نفسه أحد المصادر، وتمرير العنوان نفسه مرتين إلى دالة تكتب أثناء قراءتها ينتج تحويلا خاطئا بخفة تظهر فقط على المحتوى المدوّر

function CombineTransformCompat(var Dest: TXForm;
  const A, B: TXForm): BOOL;
var
  SrcA, SrcB: TXForm;
begin
  // انسخ أولا: قد يمرر المستدعون Dest بشكل مشروع بديلا عن A أو B
  SrcA := A;
  SrcB := B;
{$IFDEF FPC}
  Result := Windows.CombineTransform(@Dest, @SrcA, @SrcB);
{$ELSE}
  Result := Windows.CombineTransform(Dest, SrcA, SrcB);
{$ENDIF}
end;

أنواع المستطيل والنقطة هي الحالة الأخرى. يعامل Free Pascal سجلي المستطيل والنقطة في الملف التعريفي كنوعين منفصلين عن نظيريهما الرسوميين العامين، فاحتاجت ثمانية مواقع إسناد تحويلا صريحا بين سجلات تخطيطها متطابق. وكلا المترجمين يقبل شكل التحويل ذاك، فلا تحمل تلك المواقع أي شرط تجميعي، وهو ما يستحق قليلا من القبح

ما يغيره هذا لنشر يعتمد على Free Pascal

استيراد EMF المتجهي يعمل على Windows تحت Free Pascal منتجا محتوى الصفحة نفسه الذي ينتجه بناء Delphi: المسارات مسارات، والتدرجات محتوى نقوش، والنص نصا. وخارج Windows يظل المسار النقطي هو الحل، وذلك قيد في الصيغة لا في النقل. حالة الإحداثيات والقص التي يغذيها المحول موصوفة في مقال متعقب CTM والقص في مسار المحتوى، والعناصر الأولية المتجهية التي يصدرها مشمولة في الرسم المتجهي والتظليلات والتدرجات

إن كنت تدقق قاعدة كودك بحثا عن الفرصة نفسها، فالتمرين المفيد هو الذي بدأ هذا كل شيء: اذكر الأعضاء الذين تستخدمهم فعلا من الإطار الذي تظن أنك تعتمد عليه. الجواب غالبا أقصر بكثير مما توحي به قائمة الاستيراد، والقيد الحقيقي يكون عادة في مكان آخر كليا. مسارات الاستيراد المبنية على سياق الجهاز موصوفة عموما في مقال معاينة الطباعة وسياق الجهاز، وتغطية المنصات وسلاسل الأدوات مدرجة في صفحة منتج losLab PDF Developer Library