|
|
|
""" |
|
وحدة تكوين الخطوط العربية |
|
|
|
هذا الملف يحتوي على أدوات لتكوين وإدارة الخطوط العربية للرسوم البيانية |
|
""" |
|
|
|
import os |
|
import sys |
|
import matplotlib.font_manager as fm |
|
import matplotlib.pyplot as plt |
|
import arabic_reshaper |
|
from bidi.algorithm import get_display |
|
import json |
|
import glob |
|
|
|
class ArabicFontManager: |
|
"""مدير الخطوط العربية للرسوم البيانية""" |
|
|
|
def __init__(self): |
|
"""تهيئة مدير الخطوط العربية""" |
|
|
|
self.known_font_paths = { |
|
'Amiri': '/usr/share/fonts/truetype/hosny-amiri/', |
|
'Lateef': '/usr/share/fonts/truetype/sil/', |
|
'Scheherazade': '/usr/share/fonts/truetype/sil/', |
|
'KACST': '/usr/share/fonts/truetype/kacst/', |
|
'Noto Naskh Arabic': '/usr/share/fonts/truetype/noto/', |
|
'Harmattan': '/usr/share/fonts/truetype/sil/', |
|
'Alkalami': '/usr/share/fonts/truetype/sil/' |
|
} |
|
|
|
|
|
self.available_fonts = {} |
|
|
|
|
|
self.scan_available_fonts() |
|
|
|
def scan_available_fonts(self): |
|
"""البحث عن الخطوط العربية المتاحة في النظام""" |
|
|
|
for font_family, font_path in self.known_font_paths.items(): |
|
if os.path.exists(font_path): |
|
font_files = [] |
|
|
|
for font_file in os.listdir(font_path): |
|
if font_file.endswith('.ttf') or font_file.endswith('.otf'): |
|
full_path = os.path.join(font_path, font_file) |
|
font_files.append(full_path) |
|
|
|
if font_files: |
|
self.available_fonts[font_family] = font_files |
|
|
|
|
|
additional_paths = [ |
|
'/usr/share/fonts/', |
|
'/usr/local/share/fonts/', |
|
os.path.expanduser('~/.fonts/') |
|
] |
|
|
|
|
|
font_list = fm.findSystemFonts() |
|
arabic_fonts = [] |
|
|
|
|
|
for font_path in font_list: |
|
try: |
|
font_name = os.path.basename(font_path).split('.')[0] |
|
if 'arab' in font_name.lower() or 'naskh' in font_name.lower() or 'kufi' in font_name.lower(): |
|
if font_name not in self.available_fonts: |
|
self.available_fonts[font_name] = [] |
|
self.available_fonts[font_name].append(font_path) |
|
except Exception as e: |
|
print(f"خطأ في معالجة الخط {font_path}: {e}") |
|
|
|
def configure_matplotlib(self, preferred_font=None): |
|
""" |
|
تكوين matplotlib لاستخدام الخطوط العربية |
|
|
|
المعلمات: |
|
preferred_font: اسم الخط المفضل (اختياري) |
|
|
|
العوائد: |
|
قائمة بأسماء الخطوط العربية المتاحة |
|
""" |
|
|
|
if preferred_font and preferred_font in self.available_fonts: |
|
primary_font = preferred_font |
|
elif 'NotoNaskhArabic-Regular' in self.available_fonts: |
|
primary_font = 'NotoNaskhArabic-Regular' |
|
elif 'NotoSansArabic-Regular' in self.available_fonts: |
|
primary_font = 'NotoSansArabic-Regular' |
|
elif len(self.available_fonts) > 0: |
|
primary_font = list(self.available_fonts.keys())[0] |
|
else: |
|
primary_font = 'sans-serif' |
|
|
|
|
|
font_list = [primary_font] + list(self.available_fonts.keys()) + ['sans-serif'] |
|
plt.rcParams['font.family'] = ', '.join(font_list) |
|
|
|
return list(self.available_fonts.keys()) |
|
|
|
def get_font_list(self): |
|
""" |
|
الحصول على قائمة بالخطوط العربية المتاحة |
|
|
|
العوائد: |
|
قائمة بأسماء الخطوط العربية المتاحة |
|
""" |
|
return list(self.available_fonts.keys()) |
|
|
|
def get_best_font(self): |
|
""" |
|
الحصول على أفضل خط عربي متاح |
|
|
|
العوائد: |
|
اسم أفضل خط عربي متاح |
|
""" |
|
preferred_fonts = [ |
|
'NotoNaskhArabic-Regular', |
|
'NotoSansArabic-Regular', |
|
'Amiri', |
|
'Scheherazade', |
|
'Lateef', |
|
'KACST' |
|
] |
|
|
|
for font in preferred_fonts: |
|
if font in self.available_fonts: |
|
return font |
|
|
|
if len(self.available_fonts) > 0: |
|
return list(self.available_fonts.keys())[0] |
|
|
|
return 'sans-serif' |
|
|
|
def save_font_config(self, config_file='arabic_font_config.json'): |
|
""" |
|
حفظ تكوين الخطوط العربية إلى ملف |
|
|
|
المعلمات: |
|
config_file: اسم ملف التكوين |
|
""" |
|
config = { |
|
'available_fonts': {k: v for k, v in self.available_fonts.items()}, |
|
'best_font': self.get_best_font() |
|
} |
|
|
|
with open(config_file, 'w', encoding='utf-8') as f: |
|
json.dump(config, f, ensure_ascii=False, indent=4) |
|
|
|
def load_font_config(self, config_file='arabic_font_config.json'): |
|
""" |
|
تحميل تكوين الخطوط العربية من ملف |
|
|
|
المعلمات: |
|
config_file: اسم ملف التكوين |
|
|
|
العوائد: |
|
True إذا تم تحميل التكوين بنجاح، False خلاف ذلك |
|
""" |
|
if not os.path.exists(config_file): |
|
return False |
|
|
|
try: |
|
with open(config_file, 'r', encoding='utf-8') as f: |
|
config = json.load(f) |
|
|
|
if 'available_fonts' in config: |
|
self.available_fonts = config['available_fonts'] |
|
return True |
|
except Exception as e: |
|
print(f"خطأ في تحميل ملف التكوين: {e}") |
|
|
|
return False |
|
|
|
def get_display_arabic(text): |
|
""" |
|
تحويل النص العربي للعرض الصحيح في الرسوم البيانية |
|
|
|
المعلمات: |
|
text: النص العربي المراد تحويله |
|
|
|
العوائد: |
|
النص بعد المعالجة للعرض الصحيح |
|
""" |
|
|
|
if not text: |
|
return text |
|
|
|
|
|
try: |
|
reshaped_text = arabic_reshaper.reshape(text) |
|
bidi_text = get_display(reshaped_text) |
|
return bidi_text |
|
except Exception as e: |
|
print(f"خطأ في معالجة النص العربي: {e}") |
|
return text |
|
|
|
def setup_arabic_fonts(preferred_font=None): |
|
""" |
|
إعداد الخطوط العربية لاستخدامها في matplotlib |
|
|
|
المعلمات: |
|
preferred_font: اسم الخط المفضل (اختياري) |
|
|
|
العوائد: |
|
قائمة بأسماء الخطوط العربية المتاحة |
|
""" |
|
font_manager = ArabicFontManager() |
|
return font_manager.configure_matplotlib(preferred_font) |
|
|
|
def test_arabic_fonts(): |
|
""" |
|
اختبار الخطوط العربية المتاحة |
|
|
|
هذه الدالة تقوم بإنشاء رسم بياني لاختبار الخطوط العربية المتاحة |
|
""" |
|
|
|
font_manager = ArabicFontManager() |
|
available_fonts = font_manager.configure_matplotlib() |
|
|
|
if not available_fonts: |
|
print("لا توجد خطوط عربية متاحة!") |
|
return |
|
|
|
|
|
test_text = "هذا نص عربي لاختبار الخطوط: أبجد هوز حطي كلمن" |
|
|
|
|
|
test_fonts = available_fonts[:5] if len(available_fonts) > 5 else available_fonts |
|
|
|
|
|
fig, axes = plt.subplots(len(test_fonts), 1, figsize=(10, len(test_fonts) * 1.5)) |
|
|
|
if len(test_fonts) == 1: |
|
axes = [axes] |
|
|
|
for i, font in enumerate(test_fonts): |
|
axes[i].text(0.5, 0.5, get_display_arabic(test_text), |
|
fontfamily=font, fontsize=14, ha='center', va='center') |
|
axes[i].set_title(f"Font: {font}", fontsize=10) |
|
axes[i].axis('off') |
|
|
|
plt.tight_layout() |
|
plt.savefig("arabic_fonts_test.png", dpi=150) |
|
print(f"تم إنشاء صورة اختبار الخطوط العربية: arabic_fonts_test.png") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
font_manager = ArabicFontManager() |
|
|
|
|
|
available_fonts = font_manager.get_font_list() |
|
|
|
print("الخطوط العربية المتاحة:") |
|
for font in available_fonts: |
|
print(f" - {font}") |
|
|
|
|
|
font_manager.save_font_config() |
|
|
|
|
|
try: |
|
test_arabic_fonts() |
|
except Exception as e: |
|
print(f"خطأ في اختبار الخطوط العربية: {e}") |
|
|
|
print("أفضل خط عربي متاح:", font_manager.get_best_font()) |
|
|