2009-02-17 4 views
3

Я хочу написать арабский текст в моей программе opengl, используя freetype 2, как я могу это сделать, любой может отправить мне исходный код или показать мне способ или даже любую модификацию на уроке 43, чтобы написать арабский текст в OpenGL, которые объясняют с помощью FreeType для отображения арабского текстаписать арабский текст в opengl


Я видел урок 13 и урока 43 до, но проблема в том, когда я сделать это, он показывает мне только прямоугольные границы без арабского письма, и я использовал glUseOutline и он показывает мне буквы слева направо и не связывая их вместе, проблемы в арабском письме состоят в том, что есть несколько букв, которые должны учитывать его положение, такое как буква (ب) , когда это письмо находится в точке t он начинает слово (строка), у него есть собственная форма, а также в середине и в конце, поэтому, если есть исходный код, специально написанный для него, это будет очень хорошо, например, пример: بيع письмо ب находится в начале يبيع письмо ب находится в среднем ريب письма ب в конце

+0

Ваш вопрос не показывает вам никаких усилий, которые вы вложили в это до сих пор, или о тех проблемах, с которыми вы столкнулись. Если вы хотите, чтобы на ваш вопрос был дан ответ, убедитесь, что вы прилагаете к нему больше усилий и предоставляете больше контекста. –

+0

Это может быть слишком строгим ... У меня нет проблемы с вопросом, если ответы одинаково расплывчаты, например, DrJokepu ниже. – alphadogg

+1

Согласен с alphadogg. Иногда нам нужна первая точка в правильном направлении ... –

ответ

3

Отъезд NeHe tutorial 13 about rendering Bitmap fonts with OpenGL. Вероятно, вы хотите использовать широкие символы вместо 8-битных, если хотите представить арабский текст. Есть несколько примеров, некоторые из них используют Linux и FreeType. У Freetype не должно быть проблем с отображением символов Unicode. Это может помочь учебник FreeType.

0

Возможно, вы захотите использовать промежуточное представление, чтобы все четыре формы символов были преобразованы в одну форму на входе. Затем, если вы сделаете массив классов/структур, содержащих ссылки на каждый из четырех форматов правильных кодов символов, вы можете изменить строку как прочитанную средством визуализации текста так, чтобы он выбирал правильный с какой-то логикой, подобной этому psuedocode:

for each character in the input string 

    find its entry in the array containing the character codes for the four forms 

    if this is the first character 
    if the next character is a space then 
     use the isolated form in the output string 
    else 
     use the initial form in the output string 
    else 
    if the preceeding character is a space and the next character is a space then 
     use the isolated form in the output string 
    else if the preceeding character is a space then use 
     the initial form in the output string 
    else if the next character is a space then 
     use the terminal form in the output string 
    else 
     use the medial form in the output string 
1

Взгляните на نصوص عربية في أوبن جي إل (арабский), это обсуждение на арабском форуме, на котором рассматриваются все проблемы, с которыми вам придется столкнуться при предоставлении арабского текста в OpenGL, даже в расширенных.

Я не знаю, если вы будете говорить на арабском языке или нет, но на второй странице, вы найдете пример кода, который рассказывает, как писать арабский текст с помощью GDI +:

// مثال عن كود برمجي يقوم برسم النصوص على سطوح دايركت ثري دي 
// لغة البرمجة هي دوت نيت مع 
// C++/CLI 
// ونستخدم مكتبة 
// GDI+ 
// لكتابة النصوص 
// تقديم: وسام البهنسي 
// الشبكة العربية لمطوري الألعاب 
// http://www.agdn-online.com 
// رداً على الموضوع: 
// http://www.agdn-online.com/communities.aspx?view=posts&threadid=544 

// يقوم هذا الكلاس بإدارة الموارد اللازمة لرسم النصوص العربية 
private ref class ArabicTextRenderer 
{ 
public: 
ArabicTextRenderer() : 
    m_NativeData(0) 
{ 
    // أنشئ صورة بأبعاد تتسع لأكبر جملة نصية تتوقع كتابتها بضربة واحدة 
    // لاحظ أن هيئة البكسلات مهمة جداً، ويجب أن توافق هيئة السطح في محرك الرسم 
    // وذلك لتفادي أي عمليات تحويل بطيئة 
    m_Bitmap = gcnew Bitmap(256, 128, PixelFormat::Format32bppRgb); // كل بكسل 32 بت. لا يهمنا قناة ألفا 
    m_BitmapData = gcnew BitmapData(); 
    m_Graphics = Graphics::FromImage(m_Bitmap); 

    // حدد خواص الكتابة. تنسيق يمين-يسار 
    m_Format = gcnew StringFormat(); 
    m_Format->FormatFlags = StringFormatFlags::NoClip | StringFormatFlags::DirectionRightToLeft; 
    m_Format->Alignment = StringAlignment::Near; 
    m_Format->HotkeyPrefix = HotkeyPrefix::None; 
    m_Format->LineAlignment = StringAlignment::Near; 
    m_Format->Trimming = StringTrimming::None; 

    // معلومات عن كيفية حفظ الصورة في الذاكرة. كي نستطيع قراءتها دون تحويلات مكلفة 
    m_Stride = (m_Bitmap->Width * Bitmap::GetPixelFormatSize(m_Bitmap->PixelFormat))/8; // عرض الصورة بالبايت 
    int iBytesCount = m_Bitmap->Height * m_Stride; // حجم الصورة ككل بالبايت 
    m_NativeData = new char[iBytesCount]; // المصفوفة الوسيطة التي ستستلم القيم اللونية للصورة 

    // تجهيز معلومات الصورة لإجراء القفل 
    m_BitmapData->Width = m_Bitmap->Width; 
    m_BitmapData->Height = m_Bitmap->Height; 
    m_BitmapData->PixelFormat = m_Bitmap->PixelFormat; 
    m_BitmapData->Stride = m_Stride; 
    m_BitmapData->Scan0 = (IntPtr)m_NativeData; 
} 

~ArabicTextRenderer() 
{ 
    // حرر الذاكرة التي حجزناها بأنفسنا 
    delete [] m_NativeData; 
} 

// إجراءات لتسهيل الوصول إلى أعضاء الكلاس 
property Bitmap^ TextBitmap { Bitmap^ get(void) { return m_Bitmap; } } 
property BitmapData^ TextBitmapData { BitmapData^ get(void) { return m_BitmapData; } } 
property Graphics^ TextGraphics { Graphics^ get(void) { return m_Graphics; } } 
property StringFormat^ TextFormat { StringFormat^ get(void) { return m_Format; } } 
property int Stride { int get(void) { return m_Stride; } } 
property void* NativeData { void* get(void) { return m_NativeData; } } 

private: 
Graphics ^m_Graphics; // جهاز الرسم بجي دي آي بلس 
Bitmap ^m_Bitmap; // الصورة التي سيتم الرسم عليها 
BitmapData ^m_BitmapData; // معلومات القفل والتعبئة 
StringFormat ^m_Format; // خواص الكتابة 
int m_Stride; // عرض الصورة بالبايت. انتبه، قد يكون أكبر من عدد البكسلات مضروباً بحجم كل منها 
void *m_NativeData; // مؤشر إلى القيم اللونية للصورة 
}; 


// إجراء الكتابة على صورة وتحويلها إلى بايتات يمكن إرسالها إلى أي محرك رسم 
// البارامتر الأول هو النص المرغوب كتابته 
// البارامتر الثاني هو الخط المرغوب للكتابة 
// البارامتر الثالث هو كلاس الكتابة بالعربية والذي يجب أن يكون قد تم إنشاؤه من قبل 
// البارامتر الأخير هو سطح دايركت ثري الذي ترغب بالرسم عليه 
void SetText(String ^text, Font ^font, ArabicTextRenderer^ renderer, IDirect3DSurface9* D3DSurface) 
{ 
Bitmap ^bmp = renderer->TextBitmap; 
Graphics ^gfx = renderer->TextGraphics; 

// أولاً نقوم بمسح محتويات الصورة كي نتخلص من أي بقايا من المرة الماضية 
gfx->Clear(System::Drawing::Color::Transparent); 

// يجب علينا أن نقيس النص كي نستطيع توضيعه بشكل صحيح في الصورة 
SizeF sizef = gfx->MeasureString(text, font, PointF(0,0), renderer->TextFormat); 
short width = (short)sizef.Width; 
short height = (short)sizef.Height+2; // ضع هامشاً بمقدار بكسل واحد كارتفاع 
float yo = 1; // الإزاحة من أعلى الصورة 

// ارسم النص بدءاً من النقطة المحددة 
// لاحظ أن نقطة الكتابة هي الزاوية العليا اليمنى للنص لأننا نكتب بالعربية، 
// وبالتالي نحن بحاجة إلى وضع هذه النقطة على أقصى يمين الصورة 
gfx->DrawString(text, font, Brushes::White, width , yo, renderer->TextFormat); 

// يمكنك رسم إطار حول النص لو أردت التحقق من صحة الحسابات 
//gfx->DrawRectangle(Pens::White, 0, 0, width-1, height-1); 

// المستطيل الذي يحدد المنطقة التي نود قفلها من الصورة. عملياً كل الصورة 
Rectangle rc(0,0,bmp->Width,bmp->Height); 

// نقل القيم اللونية من الصورة إلى المؤشر الخاص بنا 
// هذه العملية تتم بمجرد قفل بتات الصورة، وذلك وفقاً للبارامترات التي نمررها 
// لإجراء القفل. هذه العملية سريعة نسبياً لأننا نسحب المعلومات بدون أي تحويل. 
bmp->LockBits(rc,ImageLockMode::ReadOnly|ImageLockMode::UserInputBuffer, 
       bmp->PixelFormat,renderer->TextBitmapData); 
bmp->UnlockBits(renderer->TextBitmapData); 

// الآن لدينا كل ما يلزم لوضع البكسلات في محرك الرسم 
// الإجراء التالي يضع البكسلات في سطح دايركت ثري دي كمثال 
CopyImageToD3DSurface(D3DSurface, renderer->NativeData, renderer->Stride, width, height); 

//bmp->Save(L"C:\\صورة.png"); // احفظ الصورة للتحقق 
} 


// إجراء تعبئة سطح دايركت ثري دي بقيم لونية من مصفوفة ما. أي محرك رسم يجب أن يقدم إجراءً مماثلاً 
// البارامتر الأول هو السطح المرغوب تعبئته 
// البارامتر الثاني هو مصفوفة القيم اللونية التي تريد نسخها على السطح 
// البارامتر الثالث هو عرض مصفوفة القيم اللونية بالبايت، وليس بالبكسل 
// البارامتر الرابع والخامس هما أبعاد مصفوفة القيم اللونية بالبكسل. العرض والارتفاع على الترتيب 
void CopyImageToD3DSurface(IDirect3DSurface9* D3DSurface, void* sourcePixels, 
          int stride, int width, int height) 
{ 
// هناك عدة افتراضات هنا لتبسيط الكود للمتعلم: 
// حجم السطح أكبر من أو يساوي أبعاد مصفوفة القيم اللونية 
// هيئة السطح هي ذاتها هيئة مصفوفة القيم اللونية. بمعنى آخر، لو كانت القيمة 
// اللونية مؤلفة من 4 بايتات، كل منها قناة لونية أحمر، أخضر، أزرق، ألفا 
// فإن سطح دايركت ثري دي يجب أن يكون من الهيئة: 
// D3DFMT_A8R8G8B8 أو D3DFMT_X8R8G8B8 

// انسخ القيم اللونية من كامل المصفوفة 
RECT srcRect = {0, 0, height, width}; 

// انسخ القيم اللونية إلى الزاوية العليا اليسارية من السطح 
RECT destRect = {0, 0, height, width}; 

// إجراء تعبئة السطح من مصفوفة قيم لونية مقدم من مكتبة دايركت ثري دي الإضافية 
D3DXLoadSurfaceFromMemory(
    D3DSurface, // السطح الذي يتم تعبئته 
    NULL, // مصفوفة بجدول الألوان. لا نستخدم هذه الميزة 
    &destRect, // المستطيل الذي سيتم تعبئته بالقيم اللونية في الصورة 
    sourcePixels, // مصفوفة القيم اللونية التي سيتم النسخ منها 
    D3DFMT_X8R8G8B8, // هيئة القيم اللونية. 32 بت وقناة ألفا غير مهمة 
    stride, // عرض مصفوفة القيم اللونية بالبايت 
    NULL, // مصفوفة بجدول الألوان في مصفوفة القيم اللونية. لا نستخدم هذه الميزة 
    &srcRect, // المستطيل الذي يعبر عن مكان النسخ من مصفوفة القيم اللونية 
    D3DX_FILTER_NONE, // طريقة الترشيح في حال عدم تطابق الأبعاد. لا نريد أي ترشيح 
    0); // اللون المفتاحي. سيتم استبدال جميع القيم اللونية المطابقة لهذا اللون باللون الشفاف 
} 

Другой член изменен код для работы с OpenGL, и результат был успешным: alt text http://www.agdn-online.com/postfiles/post3377_52D08C99.jpg

Вы можете скачать код here.

-3

Как разместить арабскую поддержку в этом коде?

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) 
    Call SaveSetting(My.Application.Info.ProductName, "Base", "LastText", Me.RichTextBox1.Rtf) 
End Sub 


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) 
    Me.RichTextBox1.Rtf = GetSetting(My.Application.Info.ProductName, "Base", "LastText", "") 
    If Me.RichTextBox1.TextLength = 0 Then Me.RichTextBox1.LoadFile("info.rtf") 

End Sub 


Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) 
    Me.Timer1.Enabled = True 
End Sub 

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick 
    Me.Timer1.Enabled = False 


    Dim b As New Bitmap(Me.PictureBox1.Width, Me.PictureBox1.Height) 
    Me.PictureBox1.Image = b 
    Me.PictureBox1.Image = Image.FromFile(CurDir() & "\allpic\OperaDe1AFace.jpg") 
    Rtb.RichTextBoxToBitmap(Me.RichTextBox1, Me.PictureBox1.Image) 


End Sub 

Private Sub RichTextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RichTextBox1.TextChanged 
    Me.Timer1.Enabled = True 
End Sub 

Private Sub Form1_Load_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 

End Sub 

Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 

End Sub 

Private Sub PictureBox2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 

End Sub 

Private Sub PictureBox1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) 

End Sub 

Private Sub NewToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NewToolStripMenuItem.Click 

End Sub 





Private Sub PictureBox1_Click_2(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click 

End Sub 

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown 
    StartPoint = PictureBox1.PointToScreen(New Point(e.X, e.Y)) 
    IsDragging = True 
End Sub 

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove 
    If IsDragging Then 
     Dim EndPoint As Point = PictureBox1.PointToScreen(New Point(e.X, e.Y)) 
     PictureBox1.Left += (EndPoint.X - StartPoint.X) 
     PictureBox1.Top += (EndPoint.Y - StartPoint.Y) 
     StartPoint = EndPoint 
    End If 
End Sub 

Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp 
    IsDragging = False 
End Sub 

End Class

+0

Если это ответ на проблему OP, было бы полезно, если бы вы исправили код до фактического бита, который решает их проблему, не сбрасывая стену кода. –

2

Это похоже на то, что должно работать: https://github.com/Accorpa/Arabic-Converter-From-and-To-Arabic-Presentation-Forms-B/blob/master/ArabicConverter.m

арабские символы преобразуются в соответствующие представления формы B и должны корректно отображать, иначе правильно присоединился. По внешнему виду он использует псевдокод jheriko сверху.

EDIT (26 сентября 2016 года): Я знаю, что давным-давно я опубликовал оригинальный ответ. Хотя не так, тем временем я использовал следующий код для преобразования арабских букв. Это очень простое решение для получения форм презентации для арабских букв. https://github.com/eloraiby/arabtype/blob/master/arabtype.c

.

+0

Это то, что я сделал - и это работает! Пришлось предварительно преобразовать этот код в обычный C. –