مرحبًا بك في الجزء الأول من تطبيق Linux Linux Rendering. في كل مقال في هذه السلسلة ، سنقوم بتطوير برنامج C قائم بذاته لتصور شخصية أو تسلسل أحرف. سيقوم كل من هذه البرامج بتنفيذ وظيفة أرى أنها ضرورية لتقديم النص الحديث.
في الجزء الأول ، سنقوم بتكوين FreeType وكتابة عارض رمز بسيط في وحدة التحكم.

هذا هو ما سنكتب.
وهنا هو الرمز.
إعداد النظام
- نظام التشغيل الخاص بي:
Ubuntu 18.04.2 LTS (bionic)
- برنامج التحويل البرمجي C:
clang version 6.0.0-1ubuntu2
تثبيت FreeType
على Ubuntu ، تحتاج إلى تثبيت FreeType و libpng.
$ sudo apt install libfreetype6 libfreetype6-dev $ sudo apt install libpng16-16 libpng-dev
- لدي إصدار FreeType
2.8.1-2ubuntu2
، على الرغم من أنه في وقت كتابة هذا التقرير ، كان أحدث إصدار من FreeType-2.10.1
، كما أنه يعمل أيضًا.
- نسخة libpng
(1.6.34-1ubuntu0.18.04.2)
عارض وحدة التحكم
إنشاء ملف C ( main.c
في حالتي)
#include <stdio.h> int main() { printf("Hello, world\n"); return 0; }
$ clang -Wall -Werror -o main main.c $ ./main Hello, world
نحن نربط مكتبات FreeType
للبحث عن مسار التضمين (أي الدلائل التي يمر بها المترجم عند البحث عن الملفات في
#include
) لـ FreeType ، قم بتشغيل:
$ pkg-config --cflags freetype2 -I/usr/include/freetype2 -I/usr/include/libpng16
يحتوي السطر
-I/usr/include/freetype2 -I/usr/include/libpng16
على أعلام تجميع ضرورية لتمكين FreeType في برنامج C.
#include <stdio.h> #include <freetype2/ft2build.h> #include FT_FREETYPE_H int main() { printf("Hello, world\n"); return 0; }
$ clang -I/usr/include/freetype2 \ -I/usr/include/libpng16 \ -Wall -Werror \ -o main \ main.c $ ./main Hello, world
نحن طباعة نسخة من FreeType
بداخل
main()
بتهيئة FreeType باستخدام
FT_Init_FreeType(&ft)
وتحقق من الأخطاء (ترجع وظائف FreeType 0 إذا نجحت).
(من الآن فصاعدًا ، جميع الوظائف التي
سأستخدمها مأخوذة من
مساعدة واجهة برمجة تطبيقات FreeType ).
FT_Library ft; FT_Error err = FT_Init_FreeType(&ft); if (err != 0) { printf("Failed to initialize FreeType\n"); exit(EXIT_FAILURE); }
ثم باستخدام FT_Library_Version نحصل على رقم الإصدار.
FT_Int major, minor, patch; FT_Library_Version(ft, &major, &minor, &patch); printf("FreeType's version is %d.%d.%d\n", major, minor, patch);
إذا تم تجميعها باستخدام الأمر الأخير ، فسيظهر خطأ رابط:
/tmp/main-d41304.o: In function `main': main.c:(.text+0x14): undefined reference to `FT_Init_FreeType' main.c:(.text+0x54): undefined reference to `FT_Library_Version' clang: error: linker command failed with exit code 1 (use -v to see invocation)
لإصلاح ذلك ، أضف
-lfreetype
.
$ clang -I/usr/include/freetype2 \ -I/usr/include/libpng16 \ -Wall -Werror \ -o main \ -lfreetype \ main.c $ ./main FreeType's version is 2.8.1
تحميل الخط
الخطوة الأولى لعرض الحرف هي تنزيل ملف خط. أنا أستخدم
أوبونتو مونو .
لفهم الفرق الدقيق بين بنية وجه الخط وعائلة الخطوط والخطوط الفردية ، راجع
وثائق FreeType .
الوسيطة الثالثة تسمى
مؤشر الوجه . وهو مصمم للسماح لمنشئي الخطوط بإدراج وجوه متعددة في نفس حجم الخط. نظرًا لأن كل خط له وجه واحد على الأقل ، فستعمل دائمًا قيمة 0 ، مع تحديد الخيار الأول.
FT_Face face; err = FT_New_Face(ft, "./UbuntuMono.ttf", 0, &face); if (err != 0) { printf("Failed to load face\n"); exit(EXIT_FAILURE); }
ضبط حجم بكسل للوجه
باستخدام هذا الإرشادات ، نقول لـ FreeType العرض والارتفاع المطلوبين للأحرف المعروضة.
إذا تجاوزت الصفر للعرض ، فسوف يفسر FreeType هذا كـ "مثل الآخرين" ، في هذه الحالة 32 بكسل. يمكن استخدام هذا لعرض حرف ، على سبيل المثال ، بعرض 10 بكسل وارتفاع 16 بكسل.
قد تفشل هذه العملية على خط بحجم ثابت ، كما في حالة رمز تعبيري.
err = FT_Set_Pixel_Sizes(face, 0, 32); if (err != 0) { printf("Failed to set pixel size\n"); exit(EXIT_FAILURE); }
الحصول على مؤشر للشخصية
بادئ ذي بدء ، العودة إلى
وثائق FreeType وإنشاء اصطلاح تسمية. الرمز ليس هو نفس
الصورة الرمزية . الحرف هو ما يقوله
char
، والصورة الرمزية هي صورة مرتبطة بطريقة ما بتلك الشخصية. هذه العلاقة معقدة إلى حد ما لأن char يمكن أن تتوافق مع العديد من الحروف الرسومية: مثل اللهجات. يمكن أن تتوافق الصورة الرمزية مع العديد من الأحرف: أي الحروف المركبة ، حيث -> يتم تمثيلها كصورة واحدة.
للحصول على فهرس الحروف الرسومية المطابق للحرف ، نستخدم
FT_Get_Char_Index
. كما يمكنك أن تفهم ، فإن هذا يتضمن مطابقة الحروف والرموز واحدًا إلى واحد. في مقال مقبل في هذه السلسلة ، سنحل المشكلة باستخدام مكتبة
HarfBuzz .
FT_UInt glyph_index = FT_Get_Char_Index(face, 'a');
تحميل الصورة الرمزية من الوجه
بعد تلقي glyph_index ، يمكننا تحميل الصورة الرمزية المقابلة من وجهنا.
في إصدار مستقبلي ، سنناقش بالتفصيل أعلام التنزيل المختلفة وكيف تسمح لك باستخدام ميزات مثل التلميح وخطوط الصورة النقطية.
FT_Int32 load_flags = FT_LOAD_DEFAULT; err = FT_Load_Glyph(face, glyph_index, load_flags); if (err != 0) { printf("Failed to load glyph\n"); exit(EXIT_FAILURE); }
عرض حرف رسومي في الحاوية (فتحة الصورة الرمزية)
الآن يمكننا أخيرًا عرض الصورة الرمزية الخاصة بنا في الحاوية (الفتحة) المحددة في
face->glyph
.
سنناقش أيضًا تقديم العلامات في المستقبل ، لأنها تتيح لنا استخدام عرض LCD (أو البكسل الفرعي) وإظهار الحواف الرمادية.
FT_Int32 render_flags = FT_RENDER_MODE_NORMAL; err = FT_Render_Glyph(face->glyph, render_flags); if (err != 0) { printf("Failed to render the glyph\n"); exit(EXIT_FAILURE); }
إخراج الحرف إلى وحدة التحكم
يمكن الحصول على الصورة النقطية
face->glyph->bitmap.buffer
الرمزية المقدمة من
face->glyph->bitmap.buffer
الصورة الرمزية
face->glyph->bitmap.buffer
، حيث يتم تقديمها كصفيف من قيم char غير الموقعة ، وبالتالي تتراوح قيمها من 0 إلى 255.
يتم إرجاع المخزن المؤقت كصفيف أحادي البعد ، ولكن هو صورة ثنائية الأبعاد. للوصول إلى الصف الأول من العمود j-th ، نحسب
column * row_width + row
، كما هو الحال في
bitmap.buffer[i * face->glyph->bitmap.pitch + j]
.
يمكنك أن ترى أنه عند الوصول إلى الصفيف ، استخدمنا
bitmap.width
في حلقة و
bitmap.pitch
، لأن طول كل سطر من وحدات البكسل يساوي
bitmap.width
، لكن "عرض" المخزن المؤقت هو
bitmap.pitch
.
في التعليمة البرمجية التالية ، يتم فرز جميع الصفوف والأعمدة ، ويتم رسم أحرف مختلفة حسب سطوع البكسل.
for (size_t i = 0; i < face->glyph->bitmap.rows; i++) { for (size_t j = 0; j < face->glyph->bitmap.width; j++) { unsigned char pixel_brightness = face->glyph->bitmap.buffer[i * face->glyph->bitmap.pitch + j]; if (pixel_brightness > 169) { printf("*"); } else if (pixel_brightness > 84) { printf("."); } else { printf(" "); } } printf("\n"); }
إخراج وحدة التحكم.
$ clang -I/usr/include/freetype2 \ -I/usr/include/libpng16 \ -Wall -Werror \ -o main \ -lfreetype \ main.c && ./main FreeType's version is 2.8.1 .*****. .********. .********* . ***. *** *** .******** *********** .**. *** *** *** *** *** ***. *** .*********** *********** .*******..
→ يمكن رؤية الرمز الكامل
هنااستنتاج
لقد أنشأنا عارض الشخصيات الأساسية في وحدة التحكم. يمكن توسيع هذا المثال (وسوف) لتجسيد الأحرف في مواد OpenGL لدعم رموز تعبيرية ، تجسيد البكسل الفرعي ، الحروف المركبة ، والمزيد. في الجزء التالي ، سنتحدث عن تجانس البكسل الفرعي لشاشة LCD مقارنة بظلال اللون الرمادي وإيجابياتهم وسلبياتهم.
اراك قريبا