> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/ar/mqalat-mtamqh/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md).

# نظرة عامة على التقنيات الداعمة لاستخدام خطوط الإيموجي الملونة في LaTeX

## مقدمة

تقدّم هذه المقالة نظرة عامة على مختلف [الموضوعات الأساسية](#which-topics-do-we-cover) المتعلقة باستخدام خطوط OpenType الملوّنة لتنسيق الرموز التعبيرية الملوّنة في LaTeX. لقد حاولنا تقديم مجموعة واسعة من المواد، بما يلبي طيفًا واسعًا من الاهتمامات والخبرات. ولإبقاء المقالة قابلة للإدارة، فإن تغطيتنا لبعض الموضوعات تحذف كثيرًا من التفاصيل التقنية، لكننا نأمل أن يكون هناك ما يكفي من المواد لتوجيه استكشافك لتنسيق الرموز التعبيرية الملوّنة في LaTeX.

**تحديث (يوليو 2023)**: نُشر هذا المقال لأول مرة في أغسطس 2021 ونُقِّح في يوليو 2023 لتحديث القسم الخاص بـ [استخدام خطوط OpenType الملوّنة المعتمدة على SVG مع LuaHBTeX](#using-svg-based-opentype-color-fonts-with-luahbtex).

### ما الموضوعات التي نغطيها؟

تغطي هذه المقالة الموضوعات العامة التالية:

* يونيكود: المعيار الذي يرمّز الرموز التعبيرية على أنها محارف ويُقنّن سلوكها المتوقع في تطبيقات معالجة النصوص والتنضيد.
* خطوط OpenType الملوّنة: خطوط متخصصة توفّر تمثيلات ملوّنة للمحارف التعبيرية المعروضة في مستند LaTeX الخاص بك.
* تشكيل النص: تقديم مكوّن أساسي في تنضيد اللغات ذات الخطوط المعقدة والرموز التعبيرية.
* HarfBuzz: المكوّن في LuaHBTeX الذي يتيح التنضيد متعدد اللغات المتقدم واستخدام خطوط OpenType الملوّنة لتنضيد الرموز التعبيرية في LaTeX.
* محركات TeX المختلفة: استكشاف دعمها لخطوط OpenType الملوّنة واختيار محرك TeX المستخدم.
* واجهة HarfBuzz البرمجية في LuaHBTeX: مقدمة إلى «السحر» الكامن وراء [تشكيل النص](#the-concept-of-text-shaping) في LuaHBTeX.

### ثلاث طرق لتنضيد الرموز التعبيرية الملوّنة

يمكن تنضيد الرموز التعبيرية الملوّنة باستخدام LaTeX عبر ثلاث طرق رئيسية:

1. استخدام أدوات رسومات LaTeX القياسية مثل TikZ أو MetaPost أو Asymptote لرسم الرموز التعبيرية.
2. إدراج الرموز التعبيرية باستخدام رسومات رموز تعبيرية مُعدّة مسبقًا ومخزنة في ملفات خارجية.
3. التعامل مع الرموز التعبيرية على أنها نص مشفّر بيونيكود واستخدام [تشكيل النص](#the-concept-of-text-shaping) مع [خطوط OpenType الملوّنة](#opentype-color-fonts) لتنضيدها.

تعتمد الخيارات العملية لإدراج الرموز التعبيرية الملوّنة في مستند LaTeX الخاص بك على محرك TeX المستخدم في ترجمة ذلك المستند؛ أي ما إذا كنت تستخدم:

* pdfLaTeX: محرك pdfTeX + LaTeX؛
* XeLaTeX: محرك XeTeX + LaTeX؛
* LuaLaTeX: محرك LuaHBTeX (بدءًا من TeX Live 2020) + LaTeX.

يمكن لجميع محركات TeX الثلاثة هذه استخدام أدوات أو حزم LaTeX لرسم الرموز التعبيرية أو استخدام `\includegraphics{...}` لإدراج الرموز التعبيرية المخزنة في ملفات رسومية خارجية. إن رسم الرسومات أو استيرادها من التقنيات المثالية لتنضيد الرموز التعبيرية عندما تحتاج إلى حل لا يعتمد على محرك TeX المستخدم لترجمة مستند LaTeX.

ومع ذلك، إذا كان سير عملك يوفّر المرونة لاختيار محرك TeX معيّن، وكنت تفضّل استخدام خطوط OpenType الملوّنة والمعالجة النصية المعتمدة على يونيكود، فإن أحدث إصدار من LuaTeX، المسمّى LuaHBTeX، هو ما تحتاج إليه. وبدءًا من TeX Live 2020، يُستخدم LuaHBTeX لترجمة مستندات LaTeX المبنية على صيغة LuaLaTeX.

## خلفية عن يونيكود ومحارف الرموز التعبيرية

### ترميزات المحارف

تخزن الحواسيب النصوص وتنقلها وتعالجها باستخدام تسلسل من القيم الرقمية (الصحيحة) التي تمثل *محارف*النص المكوِّنة. وتتطلب المعالجة النصية الموثوقة أن يتفق منتجو النصوص ومستعملوها على القيم الصحيحة التي ينبغي استخدامها لتمثيل المحارف الفردية ضمن تيار النص. وبعبارة أخرى، ما هو *الحرف* *ترميز ذلك النص؟* الترميز هو مجموعة القيم الصحيحة المتفق عليها والمُخصَّصة لتمثيل مجموعة معينة من المحارف: إذ يمثَّل كل محرف بقيمة صحيحة ضمن الترميز المستخدم.

### أدخل يونيكود

تاريخيًا، في عصر النصوص ذات 8 بت، استُخدمت ترميزات محارف مختلفة كثيرة، وكان ذلك يثير دائمًا شبح *عدم تطابق الترميزات*؛ أي إن منتجي النصوص ومستعمليه يفترضون بالخطأ ترميزات مختلفة، مما يؤدي إلى أخطاء في معالجة النصوص. ومن عمل مع TeX/LaTeX لسنوات عديدة قد يكون واجه عدم تطابق الترميزات بين نص الإدخال والخطوط المستخدمة لتنضيد مستند. وإذا كانت خطوط المستند مهيأة لاستخدام ترميز يختلف عن ترميز النص، فغالبًا ما ينتج عن ذلك محارف مفقودة أو خاطئة في ملف PDF المنضد.

يمكن حل هذه المشكلات التاريخية في الترميز باستخدام معيار دولي يرمّز جميع محارف العالم: يونيكود. معيار يونيكود ليس ثابتًا بل يُحدَّث دوريًا ليشمل محارف ونظم كتابة (أنظمة كتابة) إضافية ضمن مخطط الترميز الخاص به. وهناك [عملية مراجعة رسمية لاقتراح محارف جديدة](http://www.unicode.org/pending/proposals.html) مع [مخطط محدد لمحارف الرموز التعبيرية الجديدة](https://www.unicode.org/emoji/proposals.html).

### كم عدد محارف يونيكود؟

يرمّز يونيكود حدًا أقصى نظريًا يبلغ 1,114,112 محرفًا. ويُسمّى كل واحد من القيم الصحيحة البالغة 1,114,112 *نقطة ترميز*؛ أي القيمة الصحيحة المُخصَّصة لتحديد كل محرف. ومع ذلك، ولأسباب تقنية مختلفة، لا يمكن تخصيص سوى [1,112,064 نقطة ترميز](https://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology) للمحارف الفعلية: فهناك 2048 نقطة ترميز غير قابلة للتخصيص وممنوعة من الاستخدام داخل النص المتوافق مع يونيكود.

في وقت كتابة هذا النص (الإصدار الأول من هذه المقالة)، كان الإصدار 13 من معيار يونيكود قد خصص ما مجموعه 143,859 نقطة ترميز للمحارف الفعلية، بما في ذلك [3304 محارف مُرمّزة الآن على أنها رموز تعبيرية](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) (انظر الصفحة 2 من ذلك المستند). إن نمو عدد المحارف المرمّزة بواسطة يونيكود موثّق جيدًا في المقالة [كم عدد محارف يونيكود الموجودة؟](https://www.babelstone.co.uk/Unicode/HowMany.html) وفي [مدخل في ويكيبيديا](https://en.wikipedia.org/wiki/Unicode#Versions).

### مستويات يونيكود

تُقسَّم المجموعة الكاملة المؤلفة من 1,114,112 نقطة ترميز في يونيكود إلى 17 ما يُسمّى بالمستويات: المستوى 0 إلى المستوى 16، ويحتوي كلٌّ منها على 65536 قيمة لنقطة الترميز، مما يعطي مجموعًا قدره $$17\times2^{16} = 1,114,112$$ محرفًا. ويُسمّى المستوى 0 [المستوى الأساسي متعدد اللغات](https://en.wikipedia.org/wiki/Plane_\(Unicode\)#Basic_Multilingual_Plane)، وهو يرمّز المحارف الأكثر استخدامًا. أما المستويات 1–16 فتُسمّى [المستويات التكميلية](http://unicode.org/glossary/#supplementary_planes).

### صعود الرموز التعبيرية

تنشأ محارف جديدة عبر تغيّر أساليب التواصل البشري، وقد أتاح تكنولوجيا الهاتف المحمول ظهور مجموعة من هذه المحارف: الرموز التعبيرية، التي تطورت في اليابان خلال أواخر تسعينيات القرن العشرين. وليس من المستغرب أن [الأسئلة الشائعة حول الرموز التعبيرية في يونيكود](https://unicode.org/faq/emoji_dingbats.html) تذكر

> «تأتي كلمة emoji من اليابانية [絵](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E7%B5%B5) (e ≅ صورة) + [文字](http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=%E6%96%87) (moji ≅ محرف مكتوب).»

قد يجد القرّاء المهتمون بالخلفية والتطور التاريخي للرموز التعبيرية فائدة في هذا [مقدمة إلى يونيكود](https://unicode.org/reports/tr51/#Introduction) أو المقالة [I second that emoji: The standards, structures, and social production of emoji](https://firstmonday.org/ojs/index.php/fm/article/view/9381).

لم يكن حتى عام 2010، مع إصدار [الإصدار 6.0 من معيار يونيكود](https://www.unicode.org/versions/Unicode6.0.0/)، أن كثيرًا من الرموز التعبيرية تم الاعتراف بها رسميًا *محارف* في حد ذاتها. وقد رمّز يونيكود 13.0 [3304 محرفًا على أنها رموز تعبيرية](https://www.unicode.org/L2/L2020/20114r-family-emoji-explor.pdf) (انظر الصفحة 2 من ذلك المستند)، بينما يسرد يونيكود 13.1 [يسرد 3521 رمزًا تعبيريًا](https://unicode.org/emoji/charts/emoji-counts.html).

### الرموز التعبيرية تعيش على مستوى أعلى

خصّص يونيكود العديد من محارف الرموز التعبيرية لنقاط ترميز خارج المستوى الأساسي متعدد اللغات (BMP)، مرمّزة [في المستوى 1](https://en.wikibooks.org/wiki/Unicode/Character_reference/1F000-1FFFF) بنقاط ترميز تقع في النطاق 1F000–1FFFF، وهو ما يترتب عليه أثر مهم لكل من يرغب في *النسخ واللصق* لمحارف الرموز التعبيرية داخل محررات Overleaf (محرر الشيفرة أو المحرر المرئي). يمكن لمحررات Overleaf النصية التعامل فقط مع المحارف داخل المستوى الأساسي متعدد اللغات، وإن كنا نأمل أن تُدخل الترقيات المستقبلية دعمًا للمحارف خارج BMP. لاحظ أن هذا القيد يؤثر فقط في المحارف غير التابعة لـBMP ضمن النص الذي يتم لصقه في ملفات يُراد تحريرها عبر محررات Overleaf. وهناك طرق أخرى للوصول إلى محارف الرموز التعبيرية:

* استخدام الأوامر البدائية `\char"<نقطة ترميز>` أو `\Uchar"<نقطة ترميز>` (انظر [هذا القسم](#optional-detail-luatexluahbtex-char-vs-uchar) من المقالة).
* استخدام ملفات نصية إدخال تحتوي على محارف رموز تعبيرية بتنسيق UTF-8.
* استخدام أوامر LaTeX (ماكروهات) تُدرج محارف رموز تعبيرية.

#### لصق الرموز التعبيرية والمحارف الأخرى غير التابعة لـBMP في Overleaf

إذا لصقت رمزًا تعبيريًا، مثلًا 😀، في محرر الشيفرة في Overleaf، فسيُحوَّل في الوقت الحالي إلى المحرفين ��.

![خطأ ناتج عن النسخ + اللصق لمحارف غير BMP في محررات Overleaf](/files/1f54d27f649c531efc4306571ef1ea9be18ad2a6)

المحرف � له نقطة ترميز يونيكود FFFD واسمه الرسمي هو REPLACEMENT CHARACTER ويُستخدم لـ «[استبدال محرف غير معروف أو غير معرّف أو غير قابل للتمثيل](https://en.wikipedia.org/wiki/Specials_\(Unicode_block\))”.

### استخدام نقاط ترميز يونيكود (U+) في LuaLaTeX

تمثل وثائق يونيكود قيم نقاط الترميز باستخدام الصيغة `U+<قيمة سداسية عشرية>`—مثل `U+1F600`، حيث `1F600` هو `<قيمة سداسية عشرية>` لنقطة ترميز يونيكود الخاصة بالرمز التعبيري 😀. وللاستخدام هذه القيم في LuaLaTeX، تحذف `U+` وتكتب `\char"<قيمة سداسية عشرية>` أو `\Uchar"<قيمة سداسية عشرية>`. الحزمة `"` المحرف يخبر محرك TeX أن العدد المقدم محدد بالنظام السداسي العشري. على سبيل المثال، لاستخدام الرمز التعبيري 😀، ستكتب `\char"1F600` أو `\Uchar"1F600`—باستخدام خط قادر على تنضيده.

مثال LuaLaTeX بسيط يستخدم `\char` و `\Uchar` لتنضيد الرمز التعبيري 😀 قد يكون كما يلي:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz]{NotoColorEmoji.ttf}
%استخدم \emojifont ضمن مجموعة لإبقاء تأثيراتها محلية
{\emojifont
\Uchar"1F600
\char"1F600}
\end{document}
```

[افتح مثال LuaLaTeX هذا في Overleaf](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Test+using+LuaLaTeX\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%5D%7BNotoColorEmoji.ttf%7D%0A%25Use+%5Cemojifont+in+a+group+to+keep+its+effects+local%0A%7B%5Cemojifont+%0A%5CUchar%221F600%0A%5Cchar%221F600%7D%0A%5Cend%7Bdocument%7D)

**(تفصيل اختياري) LuaTeX/LuaHBTeX: \char مقابل \Uchar**

إضافةً إلى `\char<رمز محرف>` الأمر التقليدي لتنضيد محرف محدد `<رمز محرف>`، توفّر أيضًا محركات LuaTeX وLuaHBTeX وXeTeX `\Uchar<رمز محرف>` الأمر. ومن منظور المستخدم، تبدو نتيجة `\char` و `\Uchar` متشابهة، لكن هناك فرقًا دقيقًا في كيفية عمل هذه الأوامر، كما نذكر أدناه.

**الفرق الأساسي: التوسّع**

`\Uchar` هو ما يُسمّى [أمر قابل للتوسّع](/latex/ar/mqalat-mtamqh/22-how-does-expandafter-work-the-meaning-of-expansion.md#expansion-a-general-term-for-a-set-of-operations) بينما `\char` ليس قابلاً للتوسّع. وعندما يكون `\char<رمز محرف>` أو `\Uchar<رمز محرف>` الأمر قيد «التنفيذ»—أي إن الأمر لا يُخزَّن كجزء من ماكرو أو أي قائمة رموز أخرى—فإن الإجراءات التالية تحدث داخل محرك TeX:

* **`\char<رمز محرف>`** يأمر محرك TeX بإدراج رمز محرف فورًا، يمثّل `<رمز محرف>`، في أي جزء من المحتوى يقوم بتنضيده حاليًا.
* في المقابل، **`\Uchar<رمز محرف>`** له خطوتا معالجة متميزتان:

1. ال `\Uchar<رمز محرف>` الأمر هو *توسعيه*، و `<رمز محرف>` يُحوَّل إلى قائمة رموز مؤقتة تحتوي على رمز واحد [رمزًا مميزًا للحرف](/latex/ar/mqalat-mtamqh/19-how-does-expandafter-work-an-introduction-to-tex-tokens.md#tex-tokens-101-28and-notions-of-expansion29) الذي يمثّل `<رمز محرف>`.
2. أصبحت قائمة الرموز أحادية المحرف الآن *متاحة* لمحرك TeX بوصفها مصدر إدخاله التالي. وعمليًا، «يحوّل محرك TeX نظره مؤقتًا» لاستخدام تلك القائمة أحادية الرمز باعتبارها موضع عنصر الإدخال التالي (رمزًا). وبشكل افتراضي، يعود محرك TeX ببساطة لقراءة ذلك الرمز (إدخاله) وتنضيد المحرف المقابل، مع إعادة إنتاج سلوك `\char` الأمر. **ومع ذلك**، لأن ذلك `<رمز محرف>` لم يُنسَّق على الفور، بل جرى مؤقتًا *مخزنة* (حفظه) على هيئة رمز واحد، فإن أوامر TeX البدائية أو ماكروهات LaTeX يمكنها استخدام ذلك الرمز (استيعابه) — فلا يلزم تنسيقه مباشرة، بل يمكن استخدامه في مزيد من المعالجة حسب الحاجة.

فعليًا، `\char<رمز محرف>` يقول «نسّق هذا `<رمز محرف>` الآن»، بينما `\Uchar<رمز محرف>` له شكل من «الفعل المؤجل» عبر إنشاء رمز محرف مخزن وجعله متاحًا بوصفه عنصر الإدخال التالي (رمزًا). ويمكن استخدام ذلك الرمز (استيعابه) إما بواسطة أوامر TeX وماكروهاته أو إعادة قراءته بواسطة محرك TeX وتنضيده.

### يونيكود (الترميز) ليس القصة كاملة

إن القدرة على استخدام محارف الرموز التعبيرية ضمن نص مُرمَّز بيونيكود ليست سوى جزء من قصة نجاح الرموز التعبيرية. وقد ساعد على الزيادة الكبيرة في استخدام الرموز التعبيرية أيضًا التطور في [تقنية خطوط OpenType](https://learn.microsoft.com/en-us/typography/opentype/)—خطوط يمكن أن تحتوي بيانات الغليفات الخاصة بها (تصاميم المحارف) على [بيانات ألوان](https://learn.microsoft.com/en-us/typography/opentype/spec/colr)؛ أي [خطوط OpenType الملوّنة](#opentype-color-fonts).

إلى جانب الخطوط المناسبة، يتطلب استخدام الرموز التعبيرية الملوّنة مكوّنات برمجية إضافية تشمل مهامها:

* المعالجة المسبقة («[تشكيل](#the-concept-of-text-shaping)») للنص المشفّر بيونيكود، *تهيئته* للإظهار باستخدام خط معيّن؛
* *عرض وتظهير* الرموز التعبيرية الملوّنة الخاصة بخط ما *الغليفات* على شاشة الجهاز.

#### الغليف مقابل المحرف: أليسا الشيء نفسه؟

غالبًا ما يُستخدم المصطلحان «غليف» و«محرف» كما لو كانا قابلين للتبادل—إذ يشيران إلى المفهوم الأساسي نفسه—لكن هناك فرقًا دقيقًا، وإن كان مهمًا، في معناهما.

يونيكود [يعرّف مصطلح «محرف»](http://www.unicode.org/glossary/#character) على أنه:

> «أصغر مكوّن في اللغة المكتوبة له قيمة دلالية؛ ويشير إلى المعنى المجرد و/أو الشكل، لا إلى شكل محدد… »

في المقابل، فإن «الغليف» هو *تمثيل* *الشكل* (تصميم) *مرئي* لمحرف معيّن. *الحرف*.

تظهر مسألة المحرف مقابل الغليف بوضوح عندما يُعرض نص مليء بالرموز التعبيرية على أنظمة/منصات برمجية مختلفة، مثل قراءة النص نفسه على هاتفك المحمول بنظام iOS أو Android أو على حاسوب مكتبي يعمل بنظام Windows. أيًا يكن الجهاز أو المنصة المستخدمة، فإن النص الأساسي (تسلسل المحارف) سيحتوي على نفس *الرموز التعبيرية* *محارف*. إن القدرات الخاصة بالجهاز المتعلقة بـ *المعالجة المسبقة* ذلك النص ثم *عرض* و *العرضية* النتائج، ربما باستخدام خطوط خاصة بالجهاز، هي التي تنتج غليفات مختلفة (تصاميم محارف) لتمثيل المحارف التعبيرية نفسها.

قائمة [الرموز التعبيرية الكاملة](https://unicode.org/emoji/charts/full-emoji-list.html) توفّر صورًا نموذجية تمثّل كل محرف تعبيري في يونيكود—مبيّنةً الغليفات المختلفة التي تستخدمها شركات التقنية المختلفة. ولا يقتصر الأمر على أن مصممي الخطوط يعتمدون تصاميمهم الخاصة (الغليفات) لتمثيل المحارف التعبيرية، بل إن الخطوط الفردية تختلف أيضًا في عدد المحارف التعبيرية التي تدعمها (التي تحتوي على غليفات لها)، وقد تحتوي أو لا تحتوي على الخصائص الأكثر تقدمًا في معالجة نصوص الرموز التعبيرية المدرجة في مواصفات يونيكود للرموز التعبيرية.

إن مفهوم المحارف وفكرتها، ودلالتها وترميزها، تشكّل الأساس لعالم يونيكود: فهو يتعامل مع المحارف. أما تصميم المحارف الفردية وتمثيلها المرئي بوصفها غليفات، فينتمي إلى تقنيات الخطوط وفن تصميم الخطوط.

#### الرموز التعبيرية في يونيكود: أكثر بكثير من مجرد ترميز نصي

يتمثل الدور الأساسي ليونيكود في توفير معيار ترميز عالمي يحدد القيمة الصحيحة التي تُسمّى *نقطة ترميز،* والتي ينبغي استخدامها لتمثيل كل محرف، بما في ذلك الرموز التعبيرية، ضمن تيار من النص المشفّر بيونيكود.

كما تحدد مواصفة يونيكود الخاصة بالرموز التعبيرية أيضًا *سلوكيات المعالجة* لبعض *سلاسل* تسلسلات الرموز التعبيرية التي تظهر ضمن تيار من النص المشفّر بيونيكود. ويمكن «دمج» تسلسلات محددة من الرموز التعبيرية عبر عملية تُسمّى [تشكيل النص](#the-concept-of-text-shaping) لإنتاج غليف رموز تعبيرية واحد ناتج («مركب») — وسيستخدم نظام تشغيل الجهاز ذلك الغليف الواحد لتمثيل تسلسل المحارف الأصلي الموجود في النص.

التقرير التقني ليونيكود بشأن [رموز يونيكود التعبيرية](https://unicode.org/reports/tr51/) يوثّق المجموعة الغنية من الخصائص المتاحة للبرمجيات التي ترغب في توفير معالجة متوافقة مع يونيكود لمحارف الرموز التعبيرية. على سبيل المثال، يعرّف يونيكود (يرمّز) محارف تُسمّى [معدِّلات الرموز التعبيرية](http://www.unicode.org/reports/tr51/#Emoji_Modifiers_Table) يمكن استخدامها لإنتاج *تنويعات* للمحارف التعبيرية «الأساسية»، مثل تنويعات في [لون البشرة استنادًا إلى مقياس فيتزباتريك](http://www.unicode.org/reports/tr51/#Diversity). لاحظ أن مجموعة محارف الرموز التعبيرية الأساسية والمعدلات القابلة للتطبيق تُعرّف كجزء من معيار [يونيكود العام للرموز التعبيرية](http://www.unicode.org/reports/tr51).

تقدّم صفحة يونيكود [تسلسلات الرموز التعبيرية](http://unicode.org/emoji/charts/emoji-sequences.html) مخططًا للتسلسلات المتاحة حاليًا وفق مواصفة يونيكود. ضع مؤشر الفأرة فوق أي من صور غليفات الرموز التعبيرية لترى تلميحًا صغيرًا منبثقًا يوضح لك تسلسل محارف الرموز التعبيرية الأساسي الذي ينتج ذلك الغليف:

![EmojiSequenceChart.png](/files/156ca5b46335936fb5c1ac556477587aafd4babb)

على سبيل المثال، غليف الرمز التعبيري:

![HandMediumSkinTone.png](/files/dbd15e918c055c8c67760be8099c3f699206e77b)

مُدرَج في [قسم تسلسلات المعدِّلات](http://unicode.org/emoji/charts/emoji-sequences.html#modifier_sequences) ويُنتَج بواسطة التسلسل ذي المحرفين U+1F44B U+1F3FD. والمحرفان المكوِّنان هما:

U+1F44B:![UnicodeWavingHandDefault.png](/files/ae34bc2f8b17607c44eaca5b8bb049ee637693be) (يد ملوّحة)

U+1F3FD:![FitzPatrick3.png](/files/0fc3f9e859b9f7cc5a9cbebc8af99e1a0ffd91e3) (معدِّل الرموز التعبيرية فيتزباتريك النوع 4)

**استخدام معدلات لون البشرة في LuaHBTeX**

يستخدم المثال التالي LuaHBTeX لتوضيح استخدام معدلات الرموز التعبيرية:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont[Renderer=HarfBuzz,SizeFeatures={Size=20}]{NotoColorEmoji.ttf}
يد ملوّحة منفصلة: {\emojifont\Uchar"1F44B}\par
المعدِّل منفصل: {\emojifont\Uchar"1F3FD}\par
النتيجة المدمجة: {\emojifont\Uchar"1F44B\Uchar"1F3FD}
\end{document}
```

[افتح مثال معدلات الرموز التعبيرية في LuaLaTeX هذا في Overleaf](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Emoji+modifiers+using+LuaLaTeX\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfBuzz%2CSizeFeatures%3D%7BSize%3D20%7D%5D%7BNotoColorEmoji.ttf%7D%0AIsolated+waving+hand%3A+%7B%5Cemojifont%5CUchar%221F44B%7D%5Cpar%0AIsolated+modifier%3A+%7B%5Cemojifont%5CUchar%221F3FD%7D%5Cpar+%0ACombined+result%3A+%7B%5Cemojifont%5CUchar%221F44B%5CUchar%221F3FD%7D%0A%5Cend%7Bdocument%7D)

ينتج هذا المثال المخرجات التالية:

![ModifiersInLuaHBTeX.png](/files/d17c58c6faf91879eca34c8e6c972837055023e5)

#### UTF-8: دوره في تخزين نص يونيكود

سيُخزَّن أي نص أو شيفرة تكتبها أو تلصقها في محرر الشيفرة في Overleaf (أو المحرر المرئي) بتنسيق UTF-8، لذا سنراجع بإيجاز ما الذي يعنيه UTF-8 فعليًا. يرمز UTF إلى Unicode Transformation Format، ويُشار إلى دور UTF-8 في تخزين أو نقل النص المشفّر بيونيكود بعبارة «Transformation *Format*».

تتراوح قيم نقاط ترميز يونيكود من 0 إلى حد أقصى يبلغ 1,114,111، لذا يستحيل تمثيل جميع قيم محارف يونيكود باستخدام بايت واحد 8-بت، الذي لا يمكنه تخزين أكثر من 256 قيمة مختلفة: من 0 إلى 255. ومع ذلك، يمكن تمثيل أي عدد صحيح لنقطة ترميز يونيكود باستخدام *تسلسل متتالٍ* من القيم بحجم بايت، وهو المبدأ الكامن وراء UTF-8.

توفر UFT-8 «وصفة» لـ *تحويل* (أي «ترميز» أو «تحويل») قيمة عدد صحيح لنقطة ترميز يونيكود إلى تسلسل فريد من 1 إلى 4 أعداد صحيحة متتالية بحجم بايت: ويعتمد عدد البايتات المتتالية المطلوبة على قيمة عدد نقطة الترميز. وبالتالي، قد تقرأ عن UTF-8 على أنه يخزن محارف يونيكود على هيئة *تسلسلات متعددة البايت* لأن محرف يونيكود واحدًا (عدد نقطة ترميز صحيح) يُمثَّل في UTF-8 كتسلسل من 1 إلى 4 بايتات متتالية.

وبطبيعة الحال، يمكن تحويل النص المخزن في UTF-8 إلى تسلسله الأصلي من قيم نقاط ترميز يونيكود الصحيحة — وهذا ما يجب على XeTeX أو LuaTeX/LuaHBTeX فعله عند قراءة ملف إدخال LaTeX مخزن بتنسيق UTF-8. وتحتاج محركات TeX تلك إلى معرفة قيم محارف يونيكود (نقاط الترميز) في الإدخال قبل أن تتمكن من تنضيد النص. لاحظ أن pdfTeX لا يمتلك قدرة مدمجة على فك ترميز UTF-8، لذلك عليه الاعتماد على ماكروهات TeX لمعالجة نص الإدخال المنسق بـUTF-8 (وفك ترميزه).

**بعض أمثلة UTF-8**

* المحرف العربي ش («شين») له نقطة ترميز يونيكود 0634 في النظام السداسي العشري (الأساس 16) أو 1588 في النظام العشري (الأساس 10). وفي UTF-8 يُمثَّل ش بقيمتين (سداسيتين عشريتين) هما D8 وB4، لذا فإن المحرف ش سيُخزَّن على هيئة البايتين المتتاليين D8B4 ضمن نص مشفّر بـUTF-8.
* محرف الرمز التعبيري 😀 له نقطة ترميز يونيكود 1F600 في النظام السداسي العشري (الأساس 16) أو 128512 في النظام العشري (الأساس 10). وفي UTF-8 يُمثَّل 😀 بأربع قيم (سداسية عشرية) هي F0 و9F و98 و80، لذا سيُخزَّن الرمز التعبيري 😀 على هيئة البايتات الأربعة المتتالية F09F9880 داخل ملف نصي UTF-8.

#### المحارف الخاصة المستخدمة في معالجة النص الرمزي التعبيري المبني على يونيكود

ليس كل محرف مُرمَّز داخل يونيكود مخصصًا للعرض المرئي عبر الغليفات داخل خط ما: فبعض المحارف المرمّزة تُصنَّف على أنها *محارف غير قابلة للطباعة* والتي يهدفها مساعدة وظائف معالجة نصية متخصصة (داخل البرمجيات الداعمة). وتوفّر التطبيقات البرمجية المختلفة مستويات متفاوتة من الدعم للمحارف غير القابلة للطباعة المرمّزة في يونيكود، لذا ستعتمد النتيجة على بيئة البرمجيات — التطبيقات والخطوط — المستخدمة.

**محرفان غير قابلين للطباعة ينبغي معرفتهما**

* **واصلة عديمة العرض (ZWJ)**، نقطة الترميز 200D (سداسي عشري)، صُمِّمت، كما يوحي اسمها، لتحفيز «سلوك الوصل» للمحارف المدخلة — ولكن فقط إذا كانت تلك المحارف المدخلة *تملك* سلوك وصل محددًا.
* **فاصلة غير واصلة عديمة العرض (ZWNJ)**، نقطة الترميز 200C (سداسي عشري)، صُمِّمت لـ *منع* تعطيل

نشر يونيكود قائمةً من [تسلسلات ZWJ الموصى بها للرموز التعبيرية](https://unicode.org/emoji/charts/emoji-zwj-sequences.html) التي تستخدم U+200D ZERO WIDTH JOINER (ZWJ) لدمج تسلسلات محارف الرموز التعبيرية في غليف رمزي تعبيري مركب واحد — إذا كان متاحًا ضمن الخطوط المستخدمة.

**مثال على استخدام الفاصلة غير الواصلة عديمة العرض**

يستخدم المقتطف البرمجي الأدنى التالي خط OpenType Scheherazade، المضمَّن في TeX Live، لتعريف خط LaTeX يُسمّى `\arabicfont` يمكننا استخدامه لتنضيد بعض العربية. ويستخدم السطر

```latex
{\arabicfont Non-joining:\textdir TRT\Uchar"0644\Uchar"200C\Uchar"0627}
```

محرف فاصلة غير واصلة عديمة العرض، عبر `\Uchar"200C`، لمنع سلوك الوصل الطبيعي للحرفين العربيين ل (لام) و ا (ألف). لاحظ استخدام `\textdir TRT` لتعيين اتجاه النص من اليمين إلى اليسار:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\arabicfont[Script=Arabic,Renderer=Harfbuzz,SizeFeatures={Size=40}]{Scheherazade}
{\arabicfont Joining:\textdir TRT\Uchar"0644\Uchar"0627}\par
{\arabicfont Non-joining:\textdir TRT\Uchar"0644\Uchar"200C\Uchar"0627}
\end{document}
```

[افتح مثال LuaLaTeX هذا في Overleaf](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Zero+width+non-joiner+using+LuaLaTeX\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Carabicfont%5BScript%3DArabic%2CRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D40%7D%5D%7BScheherazade%7D%0A%7B%5Carabicfont+Joining%3A%5Ctextdir+TRT%5CUchar%220644%5CUchar%220627%7D%5Cpar%0A%7B%5Carabicfont+Non-joining%3A%5Ctextdir+TRT%5CUchar%220644%5CUchar%22200C%5CUchar%220627%7D%0A%5Cend%7Bdocument%7D)

ينتج هذا المثال المخرجات التالية:

![NonJoiner.png](/files/8fa6f5bc88fd34897c23cb69379699eda377e88b)

## مفهوم «تشكيل النص»

لنبدأ بمثال بصري باستخدام ترجمة بالأردية لكلمة «تعليمي». قد يُكتب نص الترجمة الأردية على لوحة مفاتيح أو على جهاز شاشة لمس، وسيُنشأ كتسلسل خطي بسيط من محارف العربية في يونيكود. ومع ذلك، عندما يُنضَّد ذلك النص، أو يُعرض على شاشة جهاز في [أسلوب النستعليق](https://en.wikipedia.org/wiki/Nastaliq)، تكون النتيجة ترتيبًا ثنائي الأبعاد معقدًا من الغليفات.

وباستخدام مثالنا بالأردية، تقارن الصورة التالية الإدخال الخطي لمحارف العربية في يونيكود *محارف* بالناتج المنسّق بأسلوب النستعليق، والذي يتألف من ترتيب ثنائي الأبعاد لـ *الغليفات* الموجودة في الخط (المجاني) [عوامي نستعليق](https://software.sil.org/awami/download/):

![](/files/5cd64da0c4edea976056c569b10e3594d4cc4c83)

تُسمّى عملية «ترجمة» محارف الإدخال إلى مجموعة من الغليفات الموضوعة في مواقعها الصحيحة *تشكيل النص*تشكيل النص

يُعد تشكيل النص ضروريًا عند استخدام أنظمة الكتابة مثل [العربية](https://en.wikipedia.org/wiki/Arabic), [العبرية](https://en.wikipedia.org/wiki/Hebrew_language), [الديفاناغارية](https://en.wikipedia.org/wiki/Devanagari) أو [المالايالامية](https://en.wikipedia.org/wiki/Malayalam)، وهي أربعة أمثلة فقط مما يُسمّى *الأنظمة الكتابية المعقدة*. ولضمان العرض الصحيح للنص في تلك الأنظمة، واللغات التي تستخدمها، يجب أن تعالج عملية التشكيل بعناية أي قواعد تشكيل ودقائق موجودة في مزيج النظام الكتابي واللغة المحدد. فعلى سبيل المثال، تتطلب بعض اللغات عدة محارف إدخال لتوليد غليف إخراج معيّن، أو قد تكون هناك متطلبات معقدة لوضع العلامات التشكيلية بعناية، وإعادة ترتيب الغليفات لضمان تموضع الغليفات الفردية بشكل صحيح (نسبيًا بعضها إلى بعض).

وعمومًا، يتطلب تشكيل قطعة من النص عدة عناصر من المعلومات:

* نظام الكتابة أو *كتابة* اللغة التي كُتب بها النص.
* الخطّ المحدد *اللغة* المستخدم. قد تُستخدم البرامج النصية الفردية لعدة لغات، مع امتلاك كل تركيبة من البرنامج النصي واللغة فروقًا/دقائق تشكيل خاصة بها.
* الكتابة *الاتجاه* لنصّ—مثل من اليمين إلى اليسار أو من اليسار إلى اليمين.
* مشروع *خطًا* الذي يوفّر الرموز الرسومية اللازمة لتمثيل النص المُشكَّل، ويحتوي، اختياريًا، على «قواعد تشكيل» إضافية ترشد عملية تشكيل النص.

قد تكون متطلبات تشكيل النص، ولا سيما للأنظمة الكتابية المعقدة واللغات المرتبطة بها، شديدة التفصيل والدقة، مما يشير إلى الحاجة إلى برمجيات متخصصة يمكنها تطبيق «قواعد» تشكيل نص قد تكون شديدة التعقيد. وليس من المستغرب أن هذه البرمجيات موجودة ويُشار إليها باسم *محرك تشكيل النص*؛ والمحرك الذي سنناقشه يُسمّى [HarfBuzz](https://en.wikipedia.org/wiki/HarfBuzz)، وتستحق وثائقُه القراءة—على سبيل المثال [لماذا أحتاج إلى محرك تشكيل؟](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html).

**قراءات إضافية حول تشكيل النص**

نوصي بشدة بهذه المقدمات القصيرة:

* [ما هو تشكيل النص؟](https://harfbuzz.github.io/what-is-harfbuzz.html#what-is-text-shaping)
* [لماذا أحتاج إلى محرك تشكيل؟](https://harfbuzz.github.io/why-do-i-need-a-shaping-engine.html)

**ملاحظة تيكسيّة: تقنيات تشكيل متعددة (نماذج)**

يدعم محرك تشكيل النص HarfBuzz عدة «تقنيات تشكيل» تختلف في كيفية تنفيذها لعملية التشكيل—ويُشار إلى كل تنفيذ منها باسم *مُشكِّل*، بما في ذلك ضمن وثائق `luaotfload` . تتمحور هذه المقالة أساسًا حول تشكيل OpenType، ولكن هناك تقنية بديلة مجانية الاستخدام هي [Graphite](https://scripts.sil.org/cms/scripts/page.php?site_id=projects\&item_id=graphite_aboutOT)، التي طورتها [SIL International](https://www.sil.org/). وهناك نموذج تشكيل آخر يدعمه HarfBuzz هو [الطباعية المتقدمة من Apple (AAT)](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6AATIntro.html)—وتُستخدم الخطوط التي تدعم AAT عمومًا على منصات تقنية Apple.

**مثال باستخدام مُشكِّل Graphite**

يضبط المثال التالي بعض النصوص الأوردية باستخدام خط يُسمّى [عوامي نستعليق](https://software.sil.org/awami/download/)، الذي يدعم تشكيل Graphite وهو متاح على Overleaf. وقد أُنشئ Awami Nastaliq بواسطة [SIL International](https://www.sil.org/)، وهي المنظمة المسؤولة عن تطوير تقنية Graphite.

يوضح المثال التالي قدرة التشكيل المتقدمة للخطوط القائمة على Graphite—لاحظ كيف أن `luaotfload` إعلان الخط يختار تشكيل Graphite باستخدام `shaper=graphite2`.

```latex
\documentclass{article}
\usepackage{luaotfload}
\begin{document}

\font\urdutest={file:AwamiNastaliq-Regular.ttf:mode=harf;shaper=graphite2} at 100bp
% التكنولوجيا
\pardir TRT\textdir TRT \urdutest ٹیکنالوجی

\vskip 75bp

% تعليمي
\pardir TRT\textdir TRT \urdutest تعلیمی
\end{document}
```

[افتح هذا المثال في Overleaf.](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+Urdu+using+the+Graphite+shaper\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bluaotfload%7D%0A%5Cbegin%7Bdocument%7D%0A%0A%5Cfont%5Curdutest%3D%7Bfile%3AAwamiNastaliq-Regular.ttf%3Amode%3Dharf%3Bshaper%3Dgraphite2%7D+at+100bp%0A%25+Technology%0A%5Cpardir+TRT%5Ctextdir+TRT+%5Curdutest+%D9%B9%DB%8C%DA%A9%D9%86%D8%A7%D9%84%D9%88%D8%AC%DB%8C%0A%0A%5Cvskip+75bp%0A%0A%25+Educational%0A%5Cpardir+TRT%5Ctextdir+TRT+%5Curdutest+%D8%AA%D8%B9%D9%84%DB%8C%D9%85%DB%8C%0A%5Cend%7Bdocument%7D)

ينتج هذا المثال المخرجات التالية:

![](/files/c541edf05d50e4d386c3683e5303e3bad8fdc4d8)

#### الإيموجي وتشكيل النص

لقد قُدِّم تشكيل النص باستخدام أمثلة من لغة ذات نظام كتابي معقد، وهي الأردية. ومع ذلك، قد يكون من المفاجئ أن عرض الرموز الرسومية الصحيحة للإيموجي يتطلب تطبيق تشكيل النص على نص يونيكود يحتوي على سلاسل من رموز الإيموجي—[كما أشار المطور الرئيسي لـ HarfBuzz](https://github.com/harfbuzz/harfbuzz/issues/2428#issuecomment-639108677):

> …إن تشكيل الإيموجي باستخدام HarfBuzz يقع بالكامل ضمن النطاق وهو ضروري بالفعل للحصول على إيموجي العائلة ولون البشرة، إلخ.

سننظر في أمثلة على ذلك.

### تقاسم المسؤولية: محرك تشكيل النص + خطوط OpenType

عمليًا، يُعد تشكيل النص «عملية مشتركة»، أو تقسيمًا للعمل، بين المنطق والقواعد المدمجين في محرك تشكيل النص وقواعد وبيانات التشكيل الإضافية المدمجة في الخطوط المستخدمة—ومن الآن فصاعدًا سنغطي التشكيل القائم على OpenType *فقط*.

لإجراء التشكيل، يُزوَّد محرك تشكيل النص عادةً ببعض نص Unicode، وببرنامج نصي ولغة محددين، وربما باتجاه كتابة، والأهم من ذلك، بخط OpenType لاستخدامه أثناء عملية التشكيل—سيُوفّر الخط الناتج: مجموعة من الرموز الرسومية وبيانات التموضع. وإذا طُلب ذلك، يمكن لمحرك التشكيل تطبيق قواعد إضافية ([ميزات OpenType](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features)) الموجودة في خط OpenType المستخدم—وتكون القواعد المطلوب تطبيقها عادةً قابلة للاختيار من قبل المستخدم من قائمة الميزات التي يدعمها الخط.

نتيجة عملية التشكيل هي *قائمة من الرموز الرسومية* موجودة في خط OpenType، مع *بين-الرموز الرسومية* بيانات التموضع. تتعلق تلك البيانات بـ *التموضع النسبي للرموز الرسومية المُشكَّلة*؛ ولا تشير إلى التموضع المطلق داخل الصفحة المطبوعة أو وسائط/محتوى آخر مثل صفحة ويب أو تغريدة، إلخ. تستخدم برامج العرض (محرك التنضيد، متصفح الويب، إلخ) معلومات التموضع بين الرموز الرسومية لضمان تموضع الرموز الرسومية بشكل صحيح نسبةً بعضها إلى بعض بعد تجميعها وإدراجها في الناتج النهائي.

#### ما هي قائمة الرموز الرسومية؟

داخليًا، يُخصَّص لكل رمز رسومي داخل خط OpenType معرّف رقمي، وهو قيمة صحيحة تُسمّى فهرس الرمز الرسومي—ويُسمّى أيضًا معرّف الرمز الرسومي أو GID. وبعد إتمام مهمة التشكيل، سيعيد محرك تشكيل النص نتائجه على هيئة *قائمة معرّفات الرموز الرسومية* مع *بيانات التموضع* لتلك الرموز الرسومية.

تُخصَّص الفهارس (المعرّفات) للرموز الرسومية الفردية داخل خطوط OpenType بواسطة مُنشئ الخط، مما يجعلها قيمة خاصة جدًا بالخط وتعسفية إلى حد كبير—وقد تختلف أيضًا بين إصدارات الخط نفسه. لا ينبغي أبدًا افتراض أن قيمة GID نفسها ستنطبق على الرموز الرسومية «المتشابهة» في خطوط مختلفة؛ فغالبًا لن يحدث ذلك. إذا كانت لديك قائمة بمعرّفات الرموز الرسومية مقدمة من محرك تشكيل، فلا يمكنك استخدامها إلا للوصول إلى الرموز الرسومية في الخط الذي استُخلصت منه.

#### ما هي خطوط OpenType؟

الويب *مفعم* بالشروحات والتفاصيل حول خطوط OpenType، لذا سنقتصر على وصف قصير. إن [مواصفة OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/) وثيقة معقدة مصممة للمطورين، لكنها في جوهرها تحدد صيغة ملف، أو حاوية، لبيانات الخط. يحتوي خط OpenType على بيانات تصف أشكال الرموز الرسومية، إلى جانب معلومات عن البرامج النصية واللغات المدعومة، وبيانات وصفية حول الخط، ومختلف «الجداول» التي تحدد [الميزات الطباعية](https://en.wikipedia.org/wiki/List_of_typographic_features#OpenType_typographic_features) التي يدعمها الخط.

يمكن عادةً أن يُطلب من محرك تشكيل النص تطبيق ميزات الخط بشكل انتقائي (استخدامها) أثناء عملية التشكيل، مع تطبيق تأثيرات طباعية محددة («قواعد») تختار المجموعة المناسبة من الرموز الرسومية الموجودة في الخط. سيحتاج الخط المختار إلى دعم أي ميزات يُطلب من محرك تشكيل النص تطبيقها، وتوفير الرموز الرسومية الخاصة بها.

#### الرموز الرسومية المشفّرة وغير المشفّرة

تتضمن خطوط OpenType جدول بيانات يُسمّى [cmap](https://docs.microsoft.com/en-us/typography/opentype/spec/cmap) (Character to Glyph Index Mapping) الذي يربط مجموعة أحرف Unicode المدعومة من الخط بفهرس الرمز الرسومي المقابل في ذلك الخط. يقدّم الفيديو التالي لمحة موجزة عن جدول cmap الموجود في خط يُسمّى `lmmono10-regiular.otf` (المضمّن في TeX Live).

{% embed url="<https://videos.ctfassets.net/nrgyaltdicpt/2537Y9gOUMWgd0t1guqt0X/482c53a9d8112ecae3d622aa7e00eef8/openType_cmap.mp4>" %}

ومع ذلك، تتضمن الخطوط عادةً العديد من الرموز الرسومية التي لا تمثل حرف Unicode محددًا ولا تُدرج ضمن جدول cmap هذا. وبالتالي يمكن تقسيم مجموعة الرموز الرسومية الموجودة داخل خط OpenType إلى مجموعتين رئيسيتين:

* رموز رسومية مشفّرة تمثل أحرف Unicode؛
* رموز رسومية غير مشفّرة لا تمثل أحرف Unicode.

يمكن الوصول إلى الرموز الرسومية المشفّرة بإدخال حرف Unicode المناسب في النص—ولكن ماذا عن الرموز الرسومية غير المشفّرة، كيف تُستخدم/يُوصَل إليها؟ تُستخدم تلك الرموز عادةً لتوفير ناتج عمليات تشكيل النص، بما في ذلك تطبيق ميزات الخط لإنتاج تأثيرات بصرية/طباعية محددة.

### خطوط OpenType الملوّنة

من المتوقع أن تُعرَض/تُظهَر رموز الإيموجي بالألوان الكاملة—فالإيموجي بالأبيض والأسود لا يقدّم تمامًا «تجربة الإيموجي الكاملة». ومع ذلك، عند الترميز الأولي للإيموجي في Unicode، لم تكن مواصفة خط OpenType [مواصفة خط OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/) بيانات -glyph داخل خطوط OpenType. *colorful*وقد دفعت هذه «الفجوة» في OpenType كبار موردي التكنولوجيا/المنصات إلى البحث عن حلول، وأفضت «السباق» الذي تلا ذلك إلى [مقترحات مختلفة لتوسيع OpenType](https://www.fontlab.com/news/color-font-format-proposals/) لدعم خطوط OpenType الملونة—ليس فقط لعرض رموز الإيموجي الملونة (الرموز الرسومية) بل لعرض أي رمز رسومي بالألوان.

#### أربعة أنواع من خط OpenType الملون

[قدّم كل من Adobe وMicrosoft وGoogle وApple مقترحات](https://www.fontlab.com/news/color-font-format-proposals/) لتوسيع OpenType لدعم خطوط OpenType كاملة الألوان، وفي نهاية المطاف، تم اعتماد أربعة مقترحات وأُدرجت في مواصفة OpenType الرسمية. وللتسهيل، يمكننا تجميع تلك المتغيرات الأربع بشكل عام إلى قائمة معتمدة على المتجهات وقائمة معتمدة على الصور النقطية—ولكن كما يُبيّن هذا [مستودع GitHub](https://github.com/simoncozens/test-fonts)، فإن مواصفة OpenType مرنة بما يكفي لدعم ملفات خطوط OpenType الملونة التي تجمع بين هذه التقنيات الأساسية الأربع.

* **خطوط OpenType المعتمدة على المتجهات:**
* **Microsoft**: تُوصَف أشكال الرموز الرسومية باستخدام شكل من أشكال المتجهات اللونية الطبقية ([COLR](https://docs.microsoft.com/en-us/typography/opentype/spec/colr) و [CPAL](https://docs.microsoft.com/en-us/typography/opentype/spec/cpal) الجداول).
* [**Adobe وMozilla**](https://www.w3.org/2013/10/SVG_in_OpenType/) ([جدول SVG](https://docs.microsoft.com/en-us/typography/opentype/spec/svg)): تُرسم أشكال الرموز الرسومية باستخدام SVG، الذي يدعم رموزًا رسومية مُنشأة من متجهات *وصور نقطية*. انظر أيضًا [دليل المستخدم من Adobe حول خطوط SVG](https://helpx.adobe.com/fonts/user-guide.html/fonts/using/ot-svg-color-fonts.ug.html).
* **خطوط OpenType المعتمدة على الصور النقطية:**
* **Google**: تُعرض الرموز الرسومية بواسطة صور PNG ملونة مضمّنة في الخط ([CBDT](https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt) و [CBLC](https://docs.microsoft.com/en-us/typography/opentype/spec/cblc) الجداول).
* **Apple**: تُعرض الرموز الرسومية أيضًا بواسطة صور ملونة مضمّنة في الخط. وبالإضافة إلى PNG، تدعم آلية Apple ([جدول sbix](https://docs.microsoft.com/en-us/typography/opentype/spec/colr)) أيضًا JPEG وTIFF.

وعليه، تحتاج أنظمة التشغيل وبرمجيات التطبيقات التي تدعم خطوط OpenType الملونة إلى التعامل مع المشهد المختلط التقني اليوم. علاوة على ذلك، ينبغي أن تدرك أن خطوط OpenType الملونة الفردية—و *إصدارات* الخط نفسه—ستكون:

* ذات تغطية مختلفة للمجموعة الكاملة من [أحرف إيموجي Unicode](https://unicode.org/emoji/charts/emoji-list.html)—أي عدد أحرف الإيموجي التي يوفّر الخط رموزًا رسومية لها؛
* تستخدم تصاميم رموز رسومية مختلفة لتمثيل أحرف الإيموجي الفردية؛
* تختلف في الميزات التي توفرها لدعم الاستخدامات الأكثر تقدمًا لمعايير Unicode، مثل [معدِّلات الرموز التعبيرية](https://unicode.org/reports/tr51/#Emoji_Modifiers_Table)، وغيرها من قدرات معالجة نص الإيموجي الموصوفة في [المعيار التقني Unicode رقم 51: Unicode Emoji](https://unicode.org/reports/tr51/).

#### الضجة حول HarfBuzz

لقد ألمحنا إلى الحاجة إلى *محرك تشكيل النص*؛ برمجية تأخذ بعض نص Unicode المُدخل، المكتوب باستخدام تركيبة معينة من البرنامج النصي واللغة، وتستخدم خطًا محددًا، ثم تُشكِّل ذلك النص إلى سلسلة من الرموز الرسومية، مع بيانات التموضع، يمكن استخدامها لتنضيد النص الأصلي المُدخل.

[HarfBuzz](https://harfbuzz.github.io/) هو أحد محركات تشكيل النص هذه: إنه [مكتبة برمجية مفتوحة المصدر](https://github.com/harfbuzz/harfbuzz) وهو نتاج أكثر من عقد من البحث والتطوير—ولا يزال قيد التطوير والنشر النشطين كجزء من العديد من المنتجات البرمجية. لا يقوم HarfBuzz نفسه بعملية «التنضيد»، لكنه يوفّر «خدمات تشكيل النص» للبرمجيات التي تختار دمجه، بما في ذلك XeTeX وLuaHBTeX و [Adobe PhotoShop وAdobe InDesign](https://en.wikipedia.org/wiki/HarfBuzz).

من خلال دمج HarfBuzz، يمكن لمحركات TeX الاستفادة من قدراته المتقدمة في تشكيل النص لتوفير تنضيد متعدد اللغات شديد التطور، ولا سيما للأنظمة الكتابية المعقدة مثل العربية والعبرية والديفاناغاري والعديد غيرها. ولاحظ أيضًا أن HarfBuzz يُستخدم لمعالجة وتشكيل أحرف نص الإيموجي في Unicode، وهو ما سنستكشفه بمزيد من التفصيل.

يلخّص الرسم البياني التالي الدور الذي يؤديه HarfBuzz عند دمجه مع برمجيات مثل XeTeX أو LuaHBTeX أثناء تنضيد نص مكتوب بنظام كتابي معقد، مثل العربية:

![نظرة عامة على تشكيل النص العربي باستخدام HarfBuzz](/files/e498a57a614291e5be511c171df203a93a78a1e1)

**استكشاف HarfBuzz**

يمكن لأي شخص يرغب في معرفة المزيد عن HarfBuzz وخدمات تشكيل OpenType التي يوفّرها لـ XeTeX وLuaHBTeX أن [ينزّل توزيعة ثنائية لـ HarfBuzz](https://github.com/harfbuzz/harfbuzz/releases) تتضمن مكتبة HarfBuzz (للمبرمجين) وأدوات سطر الأوامر `hb-view` و `hb-shape`.

**مثال: كيفية استخدام hb-view**

أنشئ ملفًا جديدًا في محرر النصوص المفضل لديك الداعم لـ UTF-8 وانسخ/الصق الأحرف الستة التالية من الإيموجي 👋👋🏻👋🏼👋🏽👋🏾👋🏿 في ذلك الملف النصي، ثم احفظه بصيغة UTF-8 في ملف يُسمّى، على سبيل المثال، `emoji.txt`.

لاحظ أن محرر النصوص لديك قد يعرض (بديلًا) نسخًا بالأبيض والأسود من الإيموجي لأنه غير قادر (مُبرمج) على عرض الرموز الرسومية الملونة. بمجرد حفظ هذه الإيموجيات الست، يجب أن يحتوي الملف `emoji.txt` على بيانات UTF-8 للتسلسل التالي من أحرف الإيموجي في Unicode—لقد فصلنا معدلات الإيموجي بفواصل من أجل *سهولة القراءة فقط*:

* `1F44B` لإنتاج 👋
* `1F44B`, `1F3FB` لإنتاج 👋🏻
* `1F44B`, `1F3FC` لإنتاج 👋🏼
* `1F44B`, `1F3FD` لإنتاج 👋🏽
* `1F44B`, `1F3FE` لإنتاج 👋🏾
* `1F44B`, `1F3FF` لإنتاج 👋🏿

يجب أن يكون هناك إجمالي قدره **11** أحرف Unicode، يولّد كل منها 4 بايت من بيانات UTF-8، لذا يجب أن يكون `emoji.txt` طول الملف 44 بايتًا، باستثناء أي علامات نهاية السطر المستخدمة في نهاية السطر الذي يحتوي على الإيموجي.

ال `hb-view` الأداة يمكنها استخدام الملف `emoji.txt`، مع خط OpenType ملون مناسب من اختيارك، مثل `NotoColorEmoji.ttf`، لتوليد ملف SVG لمخرجات HarfBuzz المُشكَّلة. ويجب أن يكون مثال سطر الأوامر التالي **مكتوبًا في سطر واحد** في الطرفية لديك، وسيولّد ملف SVG `emoji.svg`:

```latex
hb-view --font-size=20 --output-file="emoji.svg"
--output-format=svg --text-file=emoji.txt
--font-file=NotoColorEmoji.ttf
```

عند التنفيذ الناجح، يمكن فتح الملف `emoji.svg`، الذي تم إنشاؤه بواسطة `hb-view`، في Inkscape وينبغي أن يبدو شيئًا مثل هذا:

![Hbvieemoji.png](/files/5bd7e48eaf0688839de84c2cdcf05cdc424f567f)

`hb-view` يمكن استخدامه لاستكشاف تشكيل HarfBuzz لأي ملف نص Unicode مناسب وأي خط OpenType—وهو بالتأكيد لا يقتصر على الاستخدام مع الإيموجي! اكتب

```latex
hb-view --help-all
```

لرؤية الكم الهائل من خيارات سطر الأوامر لهذه الأداة القوية والعملية. تشكيلًا سعيدًا!

## تشكيل النص ومحركات TeX

هنا سنراجع قدرات تشكيل النص في XeTeX وعائلة محركات TeX من LuaTeX.

### XeTeX

طُوّر XeTeX في أوائل العقد الأول من القرن الحادي والعشرين وكان رائدًا لعدة ابتكارات في التنضيد القائم على TeX، وأبرزها *الدعم* المضمّن لـ:

* قراءة نص Unicode بصيغة UTF-8؛
* استخدام خطوط OpenType؛
* تشكيل النص للتنضيد متعدد اللغات؛
* التنضيد الرياضي القائم على OpenType.

تعود قدرة XeTeX على تنضيد اللغات ذات الأنظمة الكتابية المعقدة بسهولة ويسر إلى قدراته المضمّنة في تشكيل النص—والتي كانت تستند في الأصل إلى، والآن أصبحت مهملة، [ICU LayoutEngine](http://userguide.icu-project.org/layoutengine). وبفضل عمل خالد حسني، انتقل XeTeX إلى استخدام HarfBuzz لتشكيل النص، كما ورد في إعلان من [مارس 2013](https://tug.org/pipermail/xetex/2013-March/024118.html). ولكل من يرغب في تنضيد نص متعدد اللغات، يُذكر XeTeX عادةً بوصفه محرك TeX المفضل—لكن هناك الآن خيار آخر، وهو LuaHBTeX، الذي سنستكشفه.

### LuaTeX وLuaHBTeX

بدأ تطوير LuaTeX حوالي عام 2005، لكنه اتبع فلسفة تصميم مختلفة تمامًا عن XeTeX، الذي أدرج ميزات جديدة *مباشرةً في* برنامج XeTeX. وعلى خلاف XeTeX، اختار مطورو LuaTeX أن «...يوفّروا مجموعة أدوات دنيا ومن دون حلول.» (انظر [الدليل المرجعي لـ LuaTeX](https://www.pragma-ade.com/general/manuals/luatex.pdf)). وبدلًا من توفير مجموعة من الميزات الإضافية *المضمّنة في* محركات LuaTeX، تُفتح الآليات الداخلية لمحركات LuaTeX بحيث يمكن للمطورين والمستخدمين المتمرسين الاستفادة من لغة البرمجة Lua المدمجة لبناء حلولهم الخاصة.

فعلى سبيل المثال، وعلى خلاف XeTeX، لا يمكن لمحرك LuaTeX *تحرير* استخدام خطوط OpenType؛ بل يجب تحميل خطوط OpenType و«تهيئتها للاستخدام» من خلال دوال تحميل الخطوط المكتوبة بلغة Lua. وتُسمّى تلك الدوال *ردّ* دوال: أي كود Lua سيستدعيه LuaTeX («ينفذه») عند طلب تحميل خط.

وبالإضافة إلى ذلك، لا يوفّر محرك LuaTeX أي *الدعم* قدرات تشكيل نص—يجب أيضًا أن توفرها برمجية خارجية يستطيع LuaTeX استدعاءها لتزويده بخدمات تشكيل النص. ومرة أخرى، يختلف هذا عن محرك XeTeX، الذي أدرج قدرات تشكيل النص ضمن البرنامج الأساسي.

#### luaotfload: أساسي لاستخدام خطوط OpenType في LuaTeX/LuaHBTeX

يوفّر آلية الـ callback في LuaTeX لتحميل الخطوط قدرًا كبيرًا من المرونة، وإن كان ذلك «على حساب» برمجة إضافية. ولحسن الحظ لمستخدمي LuaLaTeX، طوّر مجتمع TeX حزمة تُسمّى `luaotfload`، وهي جزء من [الإصدار السنوي من TeX Live](https://www.tug.org/texlive/) وهي بالطبع متاحة لمستخدمي Overleaf.

`luaotfload` هو [متاح على CTAN](https://ctan.org/pkg/luaotfload?lang=en) ولها [مستودع تطوير على GitHub](https://github.com/latex3/luaotfload) حيث يمكنك متابعة أحدث التطورات و [الإصدارات الجديدة](https://github.com/latex3/luaotfload/releases).

`luaotfload` يمكن تحميلها مباشرةً في مقدمة مستند LaTeX عبر

```latex
\usepackage{luaotfload}
```

لاحظ أن `luaotfload` هو اسم حزمة LaTeX *الحزمة*، ما يعني أن اسم ملفها هو `luaotfload.sty`. وإذا أردت استخدام `luaotfload` مع plain TeX، فيمكنك فعل ذلك بإضافة السطر

```latex
\input luaotfload.sty
```

إلى مستند plain TeX لديك.

عادةً، لا يحتاج مستخدمو LuaLaTeX—أي أولئك الذين يُنضّدون LaTeX باستخدام LuaTeX/LuaHBTeX—إلى التعامل مباشرةً مع `luaotfload` لأن [`fontspec` الحزمة](https://ctan.org/pkg/fontspec) سيحمّل `luaotfload` الحزمة نيابةً عنك، ويتكفل بالعديد من التفاصيل منخفضة المستوى عبر أوامر على مستوى المستخدم يوفرها `fontspec` الحزمة.

### LuaHBTeX: خيارات جديدة لتشكيل النص

`luaotfload` هي مكتبة Lua ناضجة وقوية توفّر معالجة LuaTeX لخطوط OpenType—إلى جانب توفير خدمات تشكيل النص لمجموعة من اللغات والأنظمة الكتابية. في الأصل، كانت دوال تشكيل النص في `luaotfload` مُنفّذة بلغة Lua خالصة، لكن إصدار TeX Live 2020 جلب خيارًا سائدًا آخر لتشكيل النص—وهو محرك جديد قائم على LuaTeX يُسمّى LuaHBTeX.

يرمز «HB» في LuaHBTeX إلى HarfBuzz—وفي الجوهر، فإن LuaHBTeX هو محرك LuaTeX الأصلي *مع* مع محرك تشكيل نص HarfBuzz مدمج. وامتثالًا لفلسفة تصميم LuaTeX، فإن توفر HarfBuzz لا *يضمن تلقائيًا* أن النص سيُشكَّل بواسطة LuaHBTeX: HarfBuzz مجرد أداة أخرى يمكن استخدامها لبناء حلول تشكيل النص.

إن دمج HarfBuzz في LuaHBTeX [قابل للبرمجة عبر كود Lua](#introduction-to-the-luahbtex-harfbuzz-api)، مما مكّن مطوري `luaotfload`من إضافة حلول تشكيل نص قائمة على HarfBuzz. وبالتالي، [بدءًا من الإصدار 3.1، الصادر في 5 نوفمبر 2019](https://github.com/latex3/luaotfload/releases/tag/v3.1), `luaotfload` تم تحسينه للاستفادة من HarfBuzz—مما يجعل قدرات تشكيل النص لدى HarfBuzz سهلة الوصول للمستخدم العام.

يمكن للقراء المهتمين بالتفاصيل التقنية لدمج HarfBuzz مع LuaTeX قراءة هذه [الورقة التي كتبها خالد حسني](https://www.tug.org/TUGboat/tb40-1/tb124hosny-harfbuzz.pdf).

### luaotfload: خياران لتشكيل النص (متى نستخدم HarfBuzz؟)

أمام مستخدمي LuaLaTeX الآن خياران لتشكيل النص:

* `luaotfload`تنفيذ luaotfload الأصلي (القائم على العقد) لتشكيل النص، والمكتوب بالكامل بلغة Lua؛
* `luaotfload`التشكيل القائم على HarfBuzz في luaotfload—يُتاح عبر كود Lua الذي يستدعي دوال تشكيل النص في HarfBuzz.

`luaotfload` يوفّر الوصول إلى هذين النظامين للتشكيل عبر معامل «`mode`»—على الرغم من أن معظم المستخدمين سيستخدمون الخيار المكافئ `fontspec` “`Renderer`» بدلًا من استخدام الدوال منخفضة المستوى في luaotfload مباشرةً. `luaotfload`.

لكلٍّ من `luaotfload`حلول تشكيل النص مزاياه و(نقاط ضعفه الحالية) لكن أيّها ينبغي أن تستخدم، ومتى؟ إليك بعض النقاط التي ينبغي النظر فيها:

* `luaotfload`قد تكون معالجة luaotfload الأصلية القائمة على العقد كثيفة الذاكرة، خاصةً مع خطوط OpenType كبيرة من CJK. ويمكن أن يؤدي استخدام HarfBuzz لتشكيل نصوص CJK إلى تحسينات في السرعة وتقليلًا في استخدام الذاكرة.
* استخدم HarfBuzz للأنظمة الكتابية المعقدة لأنه «...يحسن كثيرًا عرض الأنظمة الكتابية الهندية والعربية ويُنصح به بشدة لمثل هذه الأنظمة.» (انظر `luaotfload` الدليل).
* إن دمج HarfBuzz في `luaotfload` لا يزال جديدًا نسبيًا ويخضع لمزيد من التطوير. في وقت كتابة هذا النص (يوليو 2021)، يُنصح باستخدام التشكيل المضمّن في luaotfload (بتعيين `mode=node`) لخطوط المستند الرئيسية، ولا سيما إذا كان مستندك يستخدم النص اللاتيني. انظر هذه [مشكلة GitHub](https://github.com/latex3/luaotfload/issues/175#issue-801120377)، التي تلخص المشكلات والمناقشات. وإذا أردت التجربة، يمكنك استخدام `luaotfload` لتحميل ملف خط وإنشاء خطين في LaTeX: أحدهما يستخدم تشكيلًا قائمًا على HarfBuzz والآخر يستخدم تشكيلًا قائمًا على Lua. وقد أنشأت Overleaf [مشروعًا نموذجيًا](#sample-project-arabic-shaping)، يوضح ذلك.
* لا تستخدم HarfBuzz للتعامل مع الخطوط الرياضية. وكما ناقش المطورون على tex.stackexchange، فإن HarfBuzz [غير مصمم للتعامل مع الخطوط الخاصة بالتنضيد الرياضي](https://tex.stackexchange.com/questions/544881/does-luahbtex-with-harfbuzz-renderer-completely-supports-math-formating) لذا لا تستخدمه لهذا الغرض.

**مشروع نموذجي: تشكيل العربية**

إليك مشروعًا على Overleaf يستخدم عدة خطوط عربية عالية الجودة لمقارنة `luaotfload`خدمات تشكيل النص القائمة على العقد في`mode=node`مع خدمات HarfBuzz (`mode=harf`):

* <https://www.overleaf.com/latex/examples/complex-script-shaping-using-luaotfload-and-harfbuzz/gfssprnhfddn>

يتضمن هذا المشروع المخرجات الموضحة في الصورة التالية:

![تنضيد العربية](/files/61aff244e6845903725bbd6361a502296ccb9ba7)

### اختيار «Renderer» في fontspec

كما ذُكر في [الوثائق](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf), `fontspec` «...تسمح لمستخدمي XeTeX أو LuaTeX بتحميل خطوط OpenType في مستند LaTeX». إذا كنت تستخدم محركي LuaTeX أو LuaHBTeX، `fontspec` سيحمّل `luaotfload` المكتبة نيابةً عنك، وإضافةً إلى ذلك، يوفّر مجموعة من أوامر المستخدم الملائمة التي تخفف الحاجة إلى التعامل مع `luaotfload`الوظائف منخفضة المستوى في

فكيف تختار بين تشكيل HarfBuzz أو التشكيل المضمّن الذي يوفره `luaotfload`؟ الإجابة موجودة في [`fontspec` الوثائق](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf)الدليل الممتاز `fontspec` يوفّر إعدادًا يُسمّى `Renderer` يمكن ضبطه عند تعريف الخط عبر `fontspec`. `Renderer` يتحكم في المعالجة منخفضة المستوى للخط. والخياران محل الاهتمام هما

* `Renderer = Node`: الوضع الافتراضي لتنضيد خطوط OpenType—وهذا يستخدم `luaotfload`دوال تشكيل النص في luaotfload المُنفّذة بلغة Lua خالصة.
* `Renderer = Harfbuzz`: هذا «الوضع» يعرّف/يحمّل الخط للاستخدام مع محرك تشكيل النص HarfBuzz. `luaotfload` يستخدم واجهة LuaHBTeX البرمجية لاستدعاء دوال في HarfBuzz.

لمزيد من المعلومات انظر [`fontspec` الوثائق](https://mirror.ox.ac.uk/sites/ctan.org/macros/unicodetex/latex/fontspec/fontspec.pdf).

## محركات TeX وHarfBuzz والإيموجي الملون

على الرغم من أن XeTeX وLuaHBTeX يدمجان HarfBuzz، فإنهما يقدمان مستويات مختلفة من الدعم لبعض الميزات الأكثر تقدمًا في HarfBuzz—وأبرزها تحميل خطوط OpenType الملونة واستخدامها.

### XeTeX وخطوط OpenType الملونة

كما ذُكر، هناك فئتان من خطوط OpenType الملونة بناءً على صيغة البيانات المستخدمة لتخزين الرموز الرسومية للخط: المعتمدة على المتجهات والمعتمدة على الصور النقطية.

#### XeTeX وخطوط OpenType الملونة المعتمدة على الصور النقطية

لا يمكن لـ XeTeX تحميل خطوط OpenType الملوّنة المعتمدة على الصور النقطية — مثل خطوط Google [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/) المرفقة مع TeX Live 2020. على سبيل المثال، إذا حاولت تحميل Noto Color Emoji (NotoColorEmoji.ttf) فسيفشل XeLaTeX مع رسالة خطأ قد تكون مضللة وتدّعي أن Noto Color Emoji «لا يمكن العثور عليه». الشيفرة التالية في LaTeX، عند تنضيدها باستخدام XeLaTeX، *لا تعمل*:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{NotoColorEmoji.ttf}
\newcommand{\smiley}{{\emojifont\char"1F600}}
\smiley
\end{document}
```

[افتح شيفرة XeLaTeX هذه في Overleaf (إنها ***لا*** تعمل).](https://www.overleaf.com/docs?engine=xelatex\&snip_name=XeTeX+failure\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BNotoColorEmoji.ttf%7D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0A%5Csmiley%0A%5Cend%7Bdocument%7D)

تفشل مع الخطأ:

```
! خطأ Package fontspec: لا يمكن العثور على الخط "NotoColorEmoji".
```

وبالمثل، فإن مثالًا بسيطًا من Plain TeX تتم معالجته بواسطة XeTeX يفشل أيضًا

```latex
\font\emojifont="[NotoColorEmoji.ttf]" at 12pt
\emojifont \char"1F600
\bye
```

[افتح مثال Plain TeX (XeTeX) هذا في Overleaf (إنه ***لا*** تعمل).](https://www.overleaf.com/docs?engine=latex_dvipdf\&snip_name\[]=main.tex\&snip\[]=%25%5Ctitle%7Bdummy+title%7D%0A%5Cfont%5Cemojifont%3D%22%5BNotoColorEmoji.ttf%5D%22+at+12pt%0A%5Cemojifont+%5Cchar%221F600%0A%5Cbye\&snip_name\[]=readme\&snip\[]=This+project+uses+a+latexmkrc+file+to+run+xetex+not+xelatex\&snip_name\[]=latexmkrc\&snip\[]=%24latex+%3D+%27xetex%25O+%25S%27%3B+%23+to+use+the+xetex+engine\&main_document=main.tex)

يُظهر مثال Plain TeX رسالة خطأ مشابهة، لكنها مختلفة:

```
! الخط \emojifont=[NotoColorEmoji.ttf] عند 12.0pt غير قابل للتحميل: ملف Metric (TFM) fil
e أو الخط المثبّت غير موجود.
l.1 \font\emojifont="[NotoColorEmoji.ttf]" at 12pt

لم أتمكن من قراءة بيانات الحجم لهذا الخط،
لذا سأتجاهل مواصفات الخط.
[يمكن للسحرة إصلاح ملفات TFM باستخدام TFtoPL/PLtoTF.]
يمكنك محاولة إدراج مواصفة خط مختلفة؛
مثلاً، اكتب `I\font<same font id>=<substitute font name>'.
```

**مثال Plain LuaHBTeX**

للمقارنة، إليك مثالًا بسيطًا من Plain TeX تم تجميعه باستخدام LuaHBTeX

```latex
\input luaotfload.sty
\font\emojifont=NotoColorEmoji.ttf:mode=harf at 12pt
\emojifont \Uchar"1F600
\bye
```

[افتح مثال Plain TeX (LuaHBTeX) هذا في Overleaf (يُجمَّع بنجاح).](https://www.overleaf.com/docs?engine=latex_dvipdf\&snip_name\[]=main.tex\&snip\[]=%25%5Ctitle%7BPlain+TeX+with+LuaHBTeX%7D%0A%5Cinput+luaotfload.sty%0A%5Cfont%5Cemojifont%3DNotoColorEmoji.ttf%3Amode%3Dharf+at+12pt%0A%5Cemojifont+%5CUchar%221F600%0A%5Cbye\&snip_name\[]=readme\&snip\[]=This+project+uses+a+latexmkrc+file+to+run+luahbtex+not+lualatex\&snip_name\[]=latexmkrc\&snip\[]=%24latex+%3D+%27luahbtex+%25O+%25S%27%3B+%23+to+use+the+luahbtex+engine\&main_document=main.tex)

#### السبب الحقيقي لفشل XeTeX

رسائل الخطأ التي يقدمها XeTeX تحجب جزئيًا السبب الفعلي للمشكلة: خطوط OpenType الملوّنة، ولا سيما الأنواع المعتمدة على الصور النقطية، *تحتوي* مدعومة بواسطة XeTeX. في الواقع، يمكن لـ XeTeX (Kpathsea) *العثور على* خط Noto Color Emoji، لكن XeTeX لا يستطيع بالكامل *تحميل* ذلك الخط، ولا يستطيع تهيئة جداول بيانات الخط الداخلية اللازمة لاستخدام ذلك الخط في التنضيد. داخليًا، يقوم XeTeX *تبدأ البيئة* بعملية تحميل الخط ويختبره من حيث «قابلية التحجيم» (باستخدام تعريف FreeType لـ«قابلية التحجيم»)، لكن هذا الاختبار يفشل، ويصدر XeTeX رسالة خطأ معيارية لمحرك TeX قد تكون مضللة.

**ملاحظة تقنية**

تمت دراسة معالجة XeTeX لملف NotoColorEmoji.ttf عبر تجميع نسخة تصحيحية من الملف التنفيذي لـ XeTeX. واستُخدمت بيئة Eclipse IDE لوضع نقطة توقف على دالة XeTeX `creatFontFromFile(filename, index, pointsize)`، ثم تتبع الشيفرة خطوة بخطوة لملاحظة المعالجة اللاحقة.

#### XeTeX وخطوط OpenType الملوّنة المعتمدة على المتجهات

يمكن لـ XeTeX أن *تحميل* خطوط OpenType الملوّنة المعتمدة على المتجهات، لكنه لن ينتج رموزًا تعبيرية ملوّنة في ملف PDF الناتج—إذا كان XeTeX سينتج ملف PDF أصلًا. وعلى عكس LuaTeX وLuaHBTeX وpdfTeX، فإن XeTeX لا *تحرير* يُخرج المستندات المنضدة بصيغة PDF. وبدلًا من ذلك، يُخرج XeTeX صيغة وسيطة `.xdv` (e**x**موسّع **تنسيق ملف i) الذي يتم تحويله إلى PDF بواسطة أداة تُسمّى**xdvipdfmx `. وفي وقت كتابة هذا النص،`لا يستطيع تضمين بيانات الرموز الملونة التعبيرية المناسبة في ملف PDF، لذا سترى، في أفضل الأحوال، رموزًا تعبيرية أحادية اللون—وهي نتيجة «الاحتياط»—في ملف PDF، أو ربما لا ترى شيئًا على الإطلاق، وذلك اعتمادًا على الخط المستخدم. `. وفي وقت كتابة هذا النص،` فيما يلي مثال XeLaTeX يستخدم خط OpenType الملوّن

TwemojiMozilla.ttf [، والمتاح في TeX Live. يستخدم TwemojiMozilla.ttf تنسيق المتجهات COLR/CPAL من Microsoft لتخزين الرموز الطباعية الملوّنة، وهو مرفق مع TeX Live 2020. في هذا المثال، يستطيع XeTeX تحميل الخط وتوليد](https://ctan.org/tex-archive/fonts/twemoji-colr)ملف وPDF، لكن الرمز التعبيري غير موجود في ملف PDF المنضد: `.xdv` \newfontfamily\emojifont{TwemojiMozilla.ttf}

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
إليك وجهًا مبتسمًا: \smiley
\newcommand{\smiley}{{\emojifont\char"1F600}}
افتح شيفرة XeLaTeX هذه في Overleaf (إنها تفشل في العمل).
\end{document}
```

[وعلى النقيض، تعمل الشيفرة أعلاه مع LuaLaTeX إذا عرّفت](https://www.overleaf.com/docs?engine=xelatex\&snip_name=XeTeX+failure\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BTwemojiMozilla.ttf%7D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0AHere+is+a+smiley%3A+%5Csmiley%0A%5Cend%7Bdocument%7D)

\emojifont `الإعداد` باستخدام `fontspec` \[Renderer=HarfBuzz] `[Renderer=HarfBuzz]`:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emojifont{TwemojiMozilla.ttf}[Renderer=HarfBuzz]
\newcommand{\smiley}{{\emojifont\char"1F600}}
افتح شيفرة XeLaTeX هذه في Overleaf (إنها تفشل في العمل).
\end{document}
```

[افتح شيفرة LuaLaTeX هذه في Overleaf (إنها تعمل).](https://www.overleaf.com/docs?engine=lualatex\&snip_name=LuaLaTeX+emoji+example\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%7BTwemojiMozilla.ttf%7D%5BRenderer%3DHarfBuzz%5D%0A%5Cnewcommand%7B%5Csmiley%7D%7B%7B%5Cemojifont%5Cchar%221F600%7D%7D%0AHere+is+a+smiley%3A+%5Csmiley%0A%5Cend%7Bdocument%7D)

### LuaHBTeX وخطوط OpenType الملوّنة

من خلال محرك تشكيل HarfBuzz المدمج و `luaoftload` المكتبة، يوفّر LuaHBTeX دعمًا لجميع الأنواع الأربعة من خطوط OpenType الملوّنة. ويمكن لمستخدمي LuaLaTeX الاستفادة الكاملة من المعالجة القائمة على Unicode للنص الذي يحتوي على رموز تعبيرية، أو ببساطة تزيين مستنداتهم بنص شديد الألوان باستخدام خطوط OpenType الملوّنة.

كما ذُكر سابقًا، يمكن تصنيف الأنواع الأربعة من خطوط OpenType الملوّنة إلى مجموعتين:

* التي تحتوي على رموز طباعية بتنسيقات صور نقطية، مثل PNG؛
* وأخرى تستخدم تنسيقات متجهية مثل SVG أو آلية Microsoft COLR/CPAL.

لتنسيقات الرموز المعتمدة على المتجهات ميزة القابلية للتحجيم: إذ تنتج رسومات رمزية حادة بأي حجم نقطي.

**استخدام خطوط Microsoft COLR/CPAL الملوّنة مع LuaHBTeX**

إذا كنت تريد استخدام تنسيق متجهي لخطوط الرموز التعبيرية الملونة بصيغة OpenType، فاطّلع على الخط [، والمتاح في TeX Live. يستخدم TwemojiMozilla.ttf تنسيق المتجهات COLR/CPAL من Microsoft لتخزين الرموز الطباعية الملوّنة، وهو مرفق مع TeX Live 2020. في هذا المثال، يستطيع XeTeX تحميل الخط وتوليد](https://ctan.org/tex-archive/fonts/twemoji-colr?lang=en)، الذي يعتمد على تنسيق Microsoft COLR/CPAL. يُضمَّن TwemojiMozilla.ttf مع TeX Live، لكن يمكنك الحصول على أحدث إصدار من [مستودع GitHub](https://github.com/mozilla/twemoji-colr/releases) ورفعه إلى مشروعك في Overleaf.

إليك مثالًا صغيرًا، `fontspec`-معتمد على، يستخدم `Renderer=Harfbuzz`، والذي ينضد بطة تعبيرية كبيرة (متجهية):

```latex
\documentclass{article}
\usepackage{fontspec}
\title{Duck demo}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz,SizeFeatures={Size=400}]{TwemojiMozilla.ttf}
\emojifont\Uchar"1F986
\end{document}
```

[افتح مثال LuaLaTeX هذا لتنضيد بطة متجهية.](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+an+emoji+duck\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Ctitle%7BDuck+demo%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D400%7D%5D%7BTwemojiMozilla.ttf%7D%0A%5Cemojifont%5CUchar%221F986%0A%5Cend%7Bdocument%7D)

هذه هي البطة (المتجهية) الناتجة عن المثال أعلاه:

![](/files/226ad89ca0cafa42b5ec37dd74e7f64783b355d1)

#### استخدام خطوط OpenType الملوّنة المعتمدة على SVG مع LuaHBTeX

في وقت تحديث هذا المقال (يوليو 2023)، لا يوجد سوى القليل من التوثيق الرسمي حول استخدام خطوط OpenType الملوّنة بنكهة SVG مع LuaLaTeX. بعض [التعليقات الواردة في النقاشات عبر الإنترنت](https://github.com/latex3/luaotfload/issues/96) تقترح استخدام `fontspec`لـ `RawFeature`، كما هو موضح في الشيفرة شبهية أدناه. استبدل `*اسم ملف خط SVG الخاص بك هنا*` باسم ملف خط قائم على SVG يمكن الوصول إليه من شيفرة LaTeX الخاصة بك:

```latex
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\newfontfamily\emoji[RawFeature={+svg},SizeFeatures={Size=20}]{your SVG font file name here}
\emoji الرمز التعبيري الخاص بك هنا...
\end{document}
```

إذا حذفت `fontspec` وقمت بالتحميل `luaotfload` مباشرةً، فقد تحتاج إلى التصريح عن خط وتحديده بالطريقة التالية—وتشير تجاربنا إلى أنك تحتاج إلى حذف `mode=harf` الخيار حتى يعمل ذلك:

```latex
\font\emoji=[your SVG font file name here]:+svg;
```

**بعض ملاحظات الحذر**

على القراء الراغبين في استخدام خطوط OpenType الملوّنة بنكهة SVG أن يلاحظوا ما يلي:

* يمكن لخطوط OpenType بنكهة SVG التي تحتوي على عدد كبير من الرموز الطباعية أن تكون [مكلفة حاسوبيًا لـ LuaLaTeX](#processing-svg-glyph-data) عند معالجتها، مما قد يؤدي إلى [انتهاء مهلة Overleaf](/latex/ar/qaadh-almarfh/038-fixing-and-preventing-compile-timeouts.md).
* قد يكون دعم LuaLaTeX لهذه الخطوط [مُعتبرًا تجريبيًا](https://github.com/latex3/luaotfload/issues/96#issuecomment-530317399)؛ قد تختلف النتائج وفقًا لإصدار TeX Live المستخدم في مشروعك؛ لذلك يُنصح بالتجربة والمضيّ بحذر.

**معالجة بيانات الرموز الطباعية بصيغة SVG**

يتيح SVG للمصممين إنتاج تصاميم معقدة وملونة تمثل رموز الخط الطباعية—مع الخضوع لبعض قيود SVG [الموثقة في مواصفة OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/svg). ومع ذلك، لا يمكن لمحركات TeX، بما فيها LuaHBTeX، استيراد (استخدام) ملفات SVG أو بياناتها مباشرة—مثل بيانات SVG المستخدمة لوصف أشكال الرموز الطباعية داخل خطوط OpenType الملوّنة بنكهة SVG. يجب تحويل بيانات SVG الخاصة بالرمز الطباعي إلى صيغة PDF لأن LuaHBTeX يستطيع استخدامها لتنضيد الرمز الطباعي وإنتاج مستند PDF النهائي. ويتولى شيفرة Lua داخل `luaoftload`؛ إذ تُستخرج بيانات SVG الخاصة بكل رمز طباعي من ملف الخط، وتُحفظ في ملف مؤقت `.svg` ثم تُحوَّل إلى PDF باستخدام Inkscape عبر سطر الأوامر. إن استخراج بيانات SVG وتحويلها إلى PDF يضيف بعض العبء المعالجي، مما قد يؤدي إلى أزمنة تجميع طويلة للمستند—لا سيما المستندات التي تستخدم خطوط SVG كبيرة تحتوي على آلاف الرموز التعبيرية.

#### خطوط OpenType الملوّنة المعتمدة على الصور النقطية

**استخدام تنسيق خطوط OpenType الملوّنة CBDT/CBLC من Google مع LuaHBTeX**

[Noto Color Emoji](https://fonts.google.com/noto/specimen/Noto+Color+Emoji) هو خط OpenType ملوّن مُضمَّن مع TeX Live، مما يجعله سهل الاستخدام في مشروع Overleaf. ولأن Noto Color Emoji يستخدم رسومات بصيغة PNG لتمثيل الرموز التعبيرية الطباعية، فيمكننا استخدامه لتنضيد بطة تعبيرية كبيرة (نقطية)—كما يوضح المثال التالي. لاحظ مرة أخرى أن `fontspec` تصريح الخط (`الإعداد`) يستخدم `Renderer=Harfbuzz`.

```latex
\documentclass{article}
\usepackage{fontspec}
\title{Duck demo}
\begin{document}
\newfontfamily\emojifont[Renderer=Harfbuzz,SizeFeatures={Size=400}]{NotoColorEmoji.ttf}
\emojifont\Uchar"1F986
\end{document}
```

[افتح مثال LuaLaTeX هذا لتنضيد بطة نقطية.](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Typesetting+a+large+raster+duck\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bfontspec%7D%0A%5Ctitle%7BDuck+demo%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewfontfamily%5Cemojifont%5BRenderer%3DHarfbuzz%2CSizeFeatures%3D%7BSize%3D400%7D%5D%7BNotoColorEmoji.ttf%7D%0A%5Cemojifont%5CUchar%221F986%0A%5Cend%7Bdocument%7D)

هذه هي البطة النقطية الناتجة عن المثال أعلاه:

![رمز تعبيري لبطة نقطية مُنضَّد بواسطة LaTeX](/files/0af1b9d95f1452ed93271757efb0ac245cd83b86)

إذا حاولت استخدام `NotoColorEmoji.ttf` لكن تحذف `[Renderer=Harfbuzz]` من `fontspec` التصريح، فسيفشل LuaHBTeX ويصدر رسالة خطأ عندما يحاول كتابة ملف PDF:

```latex
! خطأ: (file /usr/local/texlive/2020/texmf-dist/fonts/truetype/google/noto-em
oji/NotoColorEmoji.ttf) (ttf): لم يتم العثور على جدول loca
```

السبب وراء هذا الخطأ في [جدول loca](https://docs.microsoft.com/en-us/typography/opentype/spec/loca) هو [مُوضَّح على GitHub](https://github.com/latex3/luaotfload/issues/98#issuecomment-531610153).

**استخدام تنسيق خطوط OpenType الملوّنة sbix من Apple مع LuaHBTeX**

تُظهر الاختبارات غير المتصلة أن LuaHBTeX يدعم `sbix` النسخة من خط OpenType الملوّن، لكن حتى وقت كتابة هذا المقال، لم نتمكن من العثور على `sbix`-خط رموز تعبيرية ملوّن من تلك الفئة لعرض تنضيد بطة. يُرجى [الاتصال بنا](https://www.overleaf.com/contact) إخبارنا إن كنت تعرف واحدًا، وسنحدّث هذا المقال بسرعة لاستخدامه.

## مقدمة إلى واجهة LuaHBTeX HarfBuzz API

![Db.gif](/files/d5be0ada5fd531d0298ce02416c7847c7a9b41cf) ![Db.gif](/files/d5be0ada5fd531d0298ce02416c7847c7a9b41cf)

تشكيل النص، ولا سيما للغات ذات الكتابة المعقدة، وحتى الرموز التعبيرية، مهمة صعبة بطبيعتها، ولذلك ليس من المستغرب أن يكون HarfBuzz مكتبة متقدمة قد يكون التعامل معها صعبًا—ما لم تكن على دراية مسبقة بعمليات تشكيل النص. في هذا القسم الأخير، ننظر إلى تكامل LuaHBTeX مع HarfBuzz وكيفية الوصول إليه عبر شيفرة Lua داخل `\directlua`.

يستخدم مثالنا شيفرة أساسية إلى حدّ ما لعرض واجهة LuaHBTeX HarfBuzz API. وهو مثال مصطنع إلى حد ما، وليس بجودة إنتاجية، ولا عمليًا جدًا لأن الغرض الوحيد منه هو تقديم بعض الأفكار الأساسية. لقد قسمنا شيفرة Lua إلى جزأين `\directlua` مقاطع: الأول يحمّل `luaharfbuzz` المكتبة وينشئ بعض المتغيرات العالمية التي سنستخدمها ضمن الجزء الثاني `\directlua` من الشيفرة، حيث نعرّف ماكرو يُدعى `\codestoemoji`.

يبدو من المناسب تكرار استخدام كنُوث لرمزي الانعطاف الخطير المزدوجين (الصورة بإذن من [هذا الموقع](http://www.truetex.com/db.htm)) لأن المحتوى منخفض المستوى إلى حد ما و«ينظر تحت الغطاء»—على الرغم من أننا نأمل أن يكون ذا اهتمام للقارئ الأكثر جرأة. إن تكامل HarfBuzz في LuaHBTeX مستمد من [مشروع luaharfbuzz على GitHub](https://github.com/ufyTeX/luaharfbuzz/wiki#projects-using-luaharfbuzz) حيث يمكنك العثور على [مقدمة إلى المشروع](https://github.com/ufyTeX/luaharfbuzz/wiki) إلى جانب [قائمة بواجهة luaharfbuzz API](http://ufytex.github.io/luaharfbuzz/).

### الخطوات الأولى: تحميل مكتبة luaharfbuzz والعثور على خط

لاستخدام واجهة HarfBuzz في LuaHBTeX، نحتاج أولًا إلى تحميل المكتبة (الوحدة) المسماة `luaharfbuzz`، المضمنة في LuaHBTeX، وحفظ الجدول المُعاد في متغير (عالمي) سنسميه `hblib`:

```latex
hblib=require("luaharfbuzz")
```

بعد ذلك، نحتاج إلى تحديد موقع خط OpenType ملوّن مناسب للرموز التعبيرية: سنستخدم Noto Color Emoji—لاحظ أننا نتكاسل كثيرًا ولا نقوم بأي فحص للأخطاء في حال لم نعثر عليه! وللعثور عليه، سنستخدم مكتبة `kpse` (Kpathsea)، وهي أيضًا جزء من LuaTeX/LuaHBTeX:

```latex
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")
```

الآن بعد أن أصبح لدينا وصول إلى مكتبة HarfBuzz عبر المتغير `hblib`، والمسار إلى خط مناسب (`pathtofontfile`، يمكننا البدء في استخدام `hblib`. `\directlua` مقطع الشيفرة الذي نعرّف فيه الماكرو.

```latex
%إنشاء HarfBuzz face وHarfBuzz font من Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)
```

#### HarfBuzz font وHarfBuzz face: ما هما؟

مشروع [كائن HarfBuzz face](https://harfbuzz.github.io/fonts-and-faces.html) يمثل تصميم خط محمّل من ملف خط، ولكن من دون تعيين معاملات محددة (مثل الحجم). [كائن HarfBuzz font](https://harfbuzz.github.io/fonts-and-faces.html) يمثل *مثالًا محددًا* من HarfBuzz face؛ وبالتالي يمكن اشتقاق كائنات HarfBuzz font مختلفة من HarfBuzz face واحد: يمكن ضبط خصائص كل HarfBuzz font، مثل الحجم، على قيم مختلفة. إن HarfBuzz face مستوى تجريد أعلى من HarfBuzz font.

### استخدام رموز الخط الطباعية لإنشاء ملفات PNG

الجزء الأخير من أول `\directlua` مقطع هو دالة تُدعى `writePNGglyph(hbfontobject, glyphID)` التي نستخدمها لإظهار أن بعض خطوط OpenType الملوّنة، مثل Noto Color Emoji، تستخدم رسومات PNG لتمثيل الرموز التعبيرية الطباعية التي تحتويها.

تستخدم هذه الدالة واجهة HarfBuzz في LuaHBTeX لاستخراج بيانات PNG من الرموز الطباعية وكتابة تلك البيانات إلى ملف `.png` ملف باسم `Graphics<glyphID>.png`. ويُعاد اسم ذلك `.png` الملف لاستخدامه بواسطة `\includegraphics` لتضمين صور PNG الرمزية في ملف PDF المنضد لدينا.

مع وجود `writePNGglyph(hbfontobject, glyphID)` في مكانه، فإن أول `\directlua` مقطع شيفرة يبدو كما يلي:

```latex
\directlua{

% تحميل مكتبة luaharfbuzz من LuaHBTeX
hblib=require("luaharfbuzz")

% تحديد موقع خط Noto Color Emoji على خادم Overleaf
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% إنشاء HarfBuzz face وHarfBuzz font من Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% تقبل هذه الدالة خطًا ومعرّف رمز طباعي:
% تستخرج بيانات PNG للرموز الطباعية وتكتب
%ها إلى ملف .png

function writePNGglyph(hbfontobject, glyphID)

    % الحصول على بيانات PNG للرمز الطباعي
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % إنشاء اسم ملف لملف .png الخاص بنا
    local fname="Glyph"..glyphID..".png"

    % كتابة ملف .png وإرجاع اسم الملف
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % إرجاع اسم الملف لاستخدامه بواسطة \includegraphics
    return fname
end
}
```

### مقطع \directlua الثاني: إنشاء الماكرو \codestoemoji

الهدف هو تعريف ماكرو `\codestoemoji` يمكننا استدعاؤه بقطعة نص تحتوي على رموز أحرف تعبيرية نريد من HarfBuzz تشكيلها. وعلى وجه التحديد، سنستخدم `\Uchar<رمز محرف>` لتمثيل كل حرف تعبيري؛ على سبيل المثال:

```latex
\codestoemoji{\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
```

هناك الكثير مما يحدث ضمن تعريف `\codestoemoji` وسنشرحه أدناه، لكن التعريف يبدو كالتالي:

```latex
\newcommand{\codestoemoji}[1]{%
\directlua{

local str="#1"
local hbbuffer = hblib.Buffer.new()
hbbuffer:add_utf8(str)

hbbuffer:set_direction(hblib.Direction.new("ltr"))
local res = hblib.shape_full(hbfont, hbbuffer, {},{})

if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % جدول الرموز الطباعية، hbglyphs، يبدأ فهرسه من 1
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % تقليل حجم صور PNG المستوردة لدينا
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}
```

#### فهم تعريف الماكرو \codestoemoji

ال `\codestoemoji` الماكرو هو في الغالب شيفرة Lua موجودة داخل `\directlua`، لذا إذا أردت معرفة المزيد عن *كيف* `\directlua` كيفية العمل، فاطّلع على مقال Overleaf [فهم `\directlua`](/latex/ar/mqalat-mtamqh/09-an-introduction-to-luatex-part-2-understanding-directlua.md)، فهو يشرح كيف يعالج LuaTeX وLuaHBTeX `\directlua` عندما تُدرج أوامر TeX/LaTeX في شيفرة Lua، وبالأخص الحاجة إلى استخدام `\noexpand` و `\unexpanded`.

**التعامل مع معامل الماكرو: "#1"**

يبدأ الماكرو بهذه الأسطر الثلاثة:

```latex
local str="#1"
local hbbuffer = hblib.Buffer.new()
hbbuffer:add_utf8(str)
```

التي تؤدي المهام التالية:

* `local str="#1"`؛ فهذا ينشئ سلسلة Lua من المدخلات الممرَّرة بواسطة الماكرو؛
* `local hbbuffer = hblib.Buffer.new()`؛ فهذا يستخدم واجهة HarfBuzz لإنشاء مخزن مؤقت يحتفظ بالنص الذي نريد من HarfBuzz تشكيله؛
* `hbbuffer:add_utf8(str)`؛ فهذا يضيف سلسلة نصية بتنسيق UTF-8، منشأة من مدخلات الماكرو، إلى مخزن HarfBuzz المؤقت.

السطر الأول من الشيفرة

```latex
local str="#1"
```

يبدو بسيطًا جدًا، لكن عمله ينطوي على قدر غير قليل من التعقيد، وهو ما يستحق الاستكشاف بمزيد من التفصيل.

إذا نظرنا إلى السطر الثالث من الشيفرة

```latex
hbbuffer:add_utf8(str)
```

نرى أنه يستخدم `str` لإمداد مخزن HarfBuzz المؤقت بسلسلة Unicode منسقة بصيغة UTF-8. ولكي يعمل ذلك، يجب أن يحتوي المتغير `str` ذاته على نص Unicode منسق بصيغة UTF-8؛ ومن ثم يبرز السؤال: *كيف* هل قام LuaHBTeX «بتحويل» وسيطة الماكرو `"#1"`، والتي تحتوي على `\Uchar` أوامر، إلى متغير سلسلة Lua `str` يحتوي على نص UTF-8 لـ HarfBuzz؟

إذا نظرنا إلى الاستخدام المقصود لـ `\codestoemoji` الماكرو:

```latex
\codestoemoji{\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
```

فالمدخلات، مثل `\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065...`، لا تبدو على الإطلاق كسلسلة من الأحرف التعبيرية المشفّرة بصيغة UTF-8. علاوة على ذلك، لا يعرف HarfBuzz شيئًا عن أوامر TeX. ومع ذلك، فإن إدخال TeX الخام المكوَّن من `\Uchar` أوامر يتحول إلى أحرف Unicode مشفّرة بصيغة UTF-8 يمكن لـ HarfBuzz استخدامها، لكن *كيف*?

تكمن الإجابة في سلوك `\Uchar` الأمر: إن محاولة استدعاء `\codestoemoji` باستخدام `\char` بدلاً من `\Uchar` ستفشل، لكن *لماذا*?

**\Uchar: التوسيع في \directlua**

عندما `\codestoemoji` يُستدعى الماكرو، فإن `\directlua` الأمر، المخزَّن داخل تعريف الماكرو، يجب أن يهيئ شيفرة Lua لإرسالها إلى مفسر Lua المدمج في LuaHBTeX. وجزء من عملية إعداد الشيفرة هذه هو توسيع أي أوامر TeX/LaTeX موجودة في شيفرة Lua الأصلية ضمن تعريف الماكرو، إلى جانب توسيع أي وسائط للماكرو يقدّمها المستخدم. وتنتج عن عملية التوسيع قائمة رموز مميزة تُحوَّل لاحقًا مرة أخرى إلى نص، مما يولّد شيفرة Lua المرسلة إلى المفسر. وللتسهيل، نعيد هنا رسمًا توضيحيًا من مقال Overleaf [فهم `\directlua`](/latex/ar/mqalat-mtamqh/09-an-introduction-to-luatex-part-2-understanding-directlua.md):

![آلية عمل \directlua](/files/75d7f8a80dbb3c463fc391a4301ce65f12a6f60d)

الماكرو `\codestoemoji` مقصود استدعاؤه باستخدام `\Uchar` أوامر، و [كما ذُكر سابقًا في المقال](#the-key-difference-expansion), `\Uchar` هو أمر قابل للتوسيع ينتج عن توسيعه رمزًا حرفيًا. ضمن عمليات المعالجة الخاصة بـ `\directlua`، يقوم LuaHBTeX بتوسيع كل `\Uchar<رمز محرف>` أمر حيث *يزيل* كل `\Uchar<رمز محرف>` يُزال من الإدخال و *يستبدله* يستبدله بقيمة التوسيع المقابلة: رمز حرفي يمثل `<رمز محرف>`.

في المرحلة النهائية من المعالجة، تُحوَّل قائمة الرموز الأولية المولدة بواسطة `\directlua` إلى *مرة أخرى إلى نص* لتصبح شيفرة Lua الموجَّهة إلى مفسر Lua (انظر الرسم أعلاه). وتُحوَّل أيضًا جميع الرموز الحرفية الناتجة عن توسع `\Uchar` إلى *نص مرة أخرى*؛ فذلك التحويل للرموز الحرفية إلى نص يولّد تمثيلات UTF-8 الأصلية لـ `<رمز محرف>` القيم.

في مثالنا، بحلول الوقت الذي تُولَّد فيه شيفرة Lua وتصبح جاهزة لمفسر Lua، تكون مدخلات الماكرو الخاصة بـ "#1" قد تحولت إلى سلسلة من نص UTF-8: `str` ويصبح المتغير الآن سلسلة نصية UTF-8 يمكن إضافتها بأمان إلى مخزن HarfBuzz المؤقت.

**لماذا لا يعمل \char؟**

الإجابة المباشرة هي لأن `\char` هو *تحتوي* أمر قابل للتوسيع. وعلى عكس `\Uchar` الأوامر، `\char` الأوامر *لا تُزال* من المُدخل أثناء `\directlua`المعالجة الأولية لإنشاء قائمة رموز، فإنها «تمر عبر» لتُدمَج في قائمة الرموز الجاري إنشاؤها بواسطة `\directlua`. على سبيل المثال، إذا كانت الوسيطة إلى `\codestoemoji` تحتوي على `\char"1F3F4` فإن LuaHBTeX سيحوّل ذلك إلى تسلسل من الرموز ويخزنها كجزء من قائمة الرموز الكلية الجاري إنشاؤها.

في المرحلة التالية من المعالجة، عند تحويل الرموز مرة أخرى إلى نص، سيحتوي كود Lua الناتج على *السلسلة الحرفية* `\char"1F3F4` ضمن النص المستخدم لتعريف المتغير الخاص بنا `str`. عندما يُضاف محتوى `str` إلى مخزن HarfBuzz، فلن يحتوي على تسلسل مُرمَّز بـ UTF-8 يمثل رمز الإيموجي "1F3F4، بل سيحتوي على السلسلة الحرفية `\char"1F3F4`، والتي سيحاول HarfBuzz تشكيلها، وبالنسبة لغرضنا هذا، لن تنتج رمز إيموجي. وبالمصادفة، فإن السلسلة `\char"1F3F4` ستُنتج أيضًا أخطاء صياغة في Lua ما لم تُنشأ على هيئة «سلسلة ذات أقواس طويلة» — انظر [ما هي تسلسلات الهروب في Lua](/latex/ar/mqalat-mtamqh/09-an-introduction-to-luatex-part-2-understanding-directlua.md#what-are-e2809clua-escape-sequencese2809d3f) للحصول على خلفية حول هذه المشكلة.

إذا حاولنا استخدام `\codestoemoji` بـ `\char` أمرًا، مثل هذا:

```latex
\codestoemoji{\char"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
```

سيفشل LuaHBTeX ويبلّغ عن خطأ صياغة يشبه هذا:

```latex
[\directlua]:1: invalid escape sequence near '"\c'.
\codestoemoji ...ing \includegraphics }.}]]) end }

l.75 ...r"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}

واجه مفسّر lua مشكلة، لذا سيتم تجاهل
بقية هذه القطعة من lua.
```

#### استدعاء دالة تشكيل HarfBuzz

**تعيين معاملات المخزن**

يحتاج HarfBuzz أحيانًا إلى معلومات إضافية عن النص الذي يُطلب منه تشكيله. يمكنك توفير تلك المعلومات عن طريق تهيئة `<buffer variable>` باستخدام *طرق المخزن*، مثل:

* `<buffer variable>:set_direction(*HarfBuzz direction*)`;
* `<buffer variable>:set_language(*HarfBuzz language*)`;
* `<buffer variable>:set_script(*HarfBuzz script*)`.

على سبيل المثال، نحتاج إلى إبلاغ HarfBuzz بأن اتجاه نص الإيموجي لدينا سيكون من اليسار إلى اليمين. وللقيام بذلك، نستخدم `set_direction()` الطريقة على `<buffer variable>` المخزن الخاص بنا (المسمّى `hbbuffer`) بكتابة:

```latex
hbbuffer:set_direction(hblib.Direction.new("ltr"))
```

حيث `hblib.Direction.new("ltr")` تنشئ «كائن اتجاه» مناسبًا لتمريره إلى محرّك HarfBuzz عبر Lua.

**تنفيذ التشكيل**

بعد تهيئة المخزن على النحو المناسب، يمكننا أن نطلب من HarfBuzz إجراء التشكيل الفعلي عبر الدالة `shape_full()`. في مثالنا نكتب:

```latex
local res = hblib.shape_full(hbfont, hbbuffer, {},{})
```

تحتاج الوسيطتان الثالثة والرابعة من `shape_full()` الدالة إلى أن تكونا جداول Lua — وقد استخدمنا جداول فارغة «`{}`» لكلا الوسيطتين. والصيغة العامة لـ `shape_full()` هي:

```latex
shape_full(Harfbuzz font, Harfbuzz buffer, {font features}, {"shaper"}
```

* **`{"shaper"}`**: لا تحتاج عادةً إلى تعيينها، لكن الخيارات هي `{"ot"}` أو `{"graphite2"}`. يمكن العثور على مزيد من المعلومات حول مفهوم «shaper» في [توثيق HarfBuzz](https://harfbuzz.github.io/shaping-and-shape-plans.html)—لاحظ أن هذا يوثّق واجهة برمجة التطبيقات C منخفضة المستوى، وليس `luaharfbuzz` الربط القائم على Lua (التنفيذ).
* **`{font features}`**: هذا جدول يسرد [ميزات OpenType](https://docs.microsoft.com/en-us/typography/opentype/spec/featurelist)—المدعومة من الخط— التي تريد من HarfBuzz تطبيقها أثناء التشكيل.

أي ميزة خط تريد استخدامها تحتاج إلى إنشائها باستخدام `luaharfbuzz` دالة المكتبة

```latex
library_instance.Feature.new(feature_string)
```

حيث

* `library_instance` هو `luaharfbuzz` متغير مثيل المكتبة الخاص بك (`hblib` في مثالنا);
* `feature_string` يستخدم [صياغة لتعريف الميزات](https://github.com/ufytex/luaharfbuzz/wiki/Feature-Strings). ومن أمثلة ذلك `+smcp` لتفعيل الأحرف الكبيرة الصغيرة أو `-kern` لتعطيل التباعد الحرفي.

على سبيل المثال:

```latex
local dosmcp = hblib.Feature.new("+smcp")
local nokern = hblib.Feature.new("-kern")
% استخدم ميزات الخط الخاص بك بهذه الطريقة
local res = hblib.shape_full(hbfont, hbbuffer, {dosmcp,nokern},{})
```

#### الوصول إلى النتيجة: الحصول على الرموز الطباعية

وأخيرًا، إذا نجحت عملية التشكيل، فسيتم إرجاع الرموز الطباعية المشكّلة في متغير المخزن `hbbuffer` الذي أنشأناه سابقًا في الشيفرة.

نصل إلى الرموز الطباعية عبر طريقة المخزن `get_glyphs()` ونستخدم حلقة للحصول على كل رمز طباعي على حدة. لاحظ أن جدول Lua الذي يحتوي على الرموز الطباعية، `hbglyphs` في مثالنا، مفهرس ابتداءً من 1، وليس 0.

معرّف كل رمز طباعي *الطباعي* (ويُسمّى بشكل مُربك `codepoint`)، وخط HarfBuzz (`hbfont`)، يُمرَّر إلى `writePNGglyph()` الدالة التي تنشئ ملف PNG باستخدام التمثيل الصوري للرستر الخاص بالخط لذلك الرمز الطباعي.

`writePNGglyph()` تكتب ملف PNG وتعيد اسم ملف PNG، الذي يُستخدم لاستيراد ملف PNG (المُحجَّم) إلى مستند LaTeX الخاص بنا عبر `\includegraphics[scale=0.75]{<fname>}`. لاحظ كيف يمكننا استخدام `\includegraphics` مباشرةً داخل كود Lua.

```latex
if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % جدول الرموز الطباعية، hbglyphs، يبدأ فهرسه من 1
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % تقليل حجم صور PNG المستوردة لدينا
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
```

### الشيفرة الكاملة التي يمكنك فتحها في Overleaf

```latex
\documentclass{article}
\usepackage{graphicx}
\begin{document}
\directlua{

% تحميل مكتبة luaharfbuzz من LuaHBTeX
hblib=require("luaharfbuzz")

% حدّد موقع خط Noto Color Emoji على خادم Overleaf
pathtofontfile=kpse.find_file("NotoColorEmoji.ttf","truetype fonts")

% إنشاء HarfBuzz face وHarfBuzz font من Noto Color Emoji
hbface = hblib.Face.new(pathtofontfile)
hbfont = hblib.Font.new(hbface)

% تقبل هذه الدالة خطًا ومعرّف رمز طباعي:
% يستخرج بيانات PNG الخاصة بالرموز الطباعية ويكتب
%ها إلى ملف .png

function writePNGglyph(hbfontobject, glyphID)

    % الحصول على بيانات PNG للرمز الطباعي
    local pngblob=hbfontobject:ot_color_glyph_get_png(glyphID)
    local pngdata=pngblob:get_data()

    % إنشاء اسم ملف لملف .png الخاص بنا
    local fname="Glyph"..glyphID..".png"

    % كتابة ملف .png وإرجاع اسم الملف
    local output = assert(io.open(fname, "wb"))
    output:write(pngdata)
    output:close()

    % إرجاع اسم الملف لاستخدامه بواسطة \includegraphics
    return fname
end
}

\newcommand{\codestoemoji}[1]{%
\directlua{

local str="#1"
local hbbuffer = hblib.Buffer.new()
hbbuffer:add_utf8(str)

hbbuffer:set_direction(hblib.Direction.new("ltr"))
local res = hblib.shape_full(hbfont, hbbuffer, {},{})

if (res) then
    local hbglyphs=hbbuffer:get_glyphs()
    % جدول الرموز الطباعية، hbglyphs، مفهرس ابتداءً من 1.
    local i = 1
    while hbglyphs[i] \noexpand~= nil do
        local glyph = hbglyphs[i]
        i = i + 1
        local fname=writePNGglyph(hbfont, glyph.codepoint)
        % تقليل حجم صور PNG المستوردة لدينا
        local s = 0.75
        local scal="[scale="..tostring(s).."]"
        tex.print([[\noexpand\includegraphics]]..scal..[[{]]..fname..[[}]])
     end
end
}}

بطة: \codestoemoji{\Uchar"1F986}

علم: \codestoemoji{\Uchar"1F3F4\Uchar"E0067\Uchar"E0062\Uchar"E0065\Uchar"E006E\Uchar"E0067\Uchar"E007F}
\end{document}
```

[افتح مثال luaharfbuzz API هذا في Overleaf.](/latex/ar/mqalat-mtamqh/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md)

ينتج هذا المثال المخرجات التالية:

![Harfbuzzexample.png](/files/d5ddaab2ab272eae749c141d5a29c9dff714605b)

## قسم إضافي: متعة مع رياضيات الإيموجي

ولإنهاء المقالة بنبرة خفيفة، استخدم أحد أعضاء فريق Overleaf [`الرموز التعبيرية` لحزمة LaTeX](https://ctan.org/pkg/emoji?lang=en) لإنشاء مثال ممتع:

```latex
\documentclass{article}
\usepackage{emoji}
\usepackage{unicode-math,fontspec}
\setmainfont{STIX}
\setmathfont{STIX Two Math}
\begin{document}
\newcommand{\emomath}[1]{\text{\emoji{#1}}}
\[
e^{\emomath{droplet} \ln\emomath{smile}}=\emomath{sweat-smile}
\]
\[
e^{\emomath{eye}\emomath{pie}}=-1
\]
\end{document}
```

[افتح هذا المثال الممتع في Overleaf](https://www.overleaf.com/docs?engine=lualatex\&snip_name=Fun+with+emoji+math\&snip=%5Cdocumentclass%7Barticle%7D%0A%5Cusepackage%7Bemoji%7D%0A%5Cusepackage%7Bunicode-math%2Cfontspec%7D%0A%5Csetmainfont%7BSTIX%7D%0A%5Csetmathfont%7BSTIX+Two+Math%7D%0A%5Cbegin%7Bdocument%7D%0A%5Cnewcommand%7B%5Cemomath%7D%5B1%5D%7B%5Ctext%7B%5Cemoji%7B%231%7D%7D%7D%0A%5C%5B%0Ae%5E%7B%5Cemomath%7Bdroplet%7D+%5Cln%5Cemomath%7Bsmile%7D%7D%3D%5Cemomath%7Bsweat-smile%7D%0A%5C%5D%0A%5C%5B%0Ae%5E%7B%5Cemomath%7Beye%7D%5Cemomath%7Bpie%7D%7D%3D-1%0A%5C%5D%0A%5Cend%7Bdocument%7D)

ينتج هذا المثال المخرجات التالية:

![Emojimath2.png](/files/9fbc9dce8c2a64ed3fda49ac446ffc5b5a144c90)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/ar/mqalat-mtamqh/10-an-overview-of-technologies-supporting-the-use-of-colour-emoji-fonts-in-latex.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
