Platforms to show: All Mac Windows Linux Cross-Platform
/DynaPDF/Create PDF with Arabic
Function:
Required plugins for this example: MBS DynaPDF Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /DynaPDF/Create PDF with Arabic
This example is the version from Sun, 23th Sep 2017.
Function:
Required plugins for this example: MBS DynaPDF Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /DynaPDF/Create PDF with Arabic
This example is the version from Sun, 23th Sep 2017.
Project "Create PDF with Arabic.xojo_binary_project"
FileTypes
Filetype text
End FileTypes
MenuBar MenuBar1
MenuItem UntitledMenu1 = ""
MenuItem FileMenu = "&File"
MenuItem FileQuit = "Quit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem UntitledMenu0 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "Clear"
End MenuBar
Class App Inherits Application
EventHandler Sub Open()
dim pdf as new MyDynapdfMBS
dim d as new date
pdf.SetLicenseKey "Starter" // For this example you can use a Starter, Lite, Pro or Enterprise License
dim f as FolderItem = SpecialFolder.Desktop.Child("Create PDF with Arabic.pdf")
call pdf.CreateNewPDF f
call pdf.SetDocInfo pdf.kdiSubject, "My first Xojo output"
call pdf.SetDocInfo pdf.kdiProducer, "Xojo test application"
call pdf.SetDocInfo pdf.kdiTitle, "My first Xojo output"
// We want to use top-down coordinates
call pdf.SetPageCoords pdf.kpcTopDown
call pdf.Append
dim text as string = "مرحبا العالم"
// todo: convert from unicode text into right glyph
dim glyphs() as integer
glyphs.Append &hFEE3
glyphs.Append &hFEAE
glyphs.Append &hFEA3
glyphs.Append &hFE92
glyphs.Append &hFE8E
glyphs.Append 32 // space
glyphs.Append &h0627
glyphs.Append &hFEDF
glyphs.Append &hFECC
glyphs.Append &hFE8E
glyphs.Append &hFEDF
glyphs.Append &hFEE2
dim Text3 as string = ""
for each g as integer in glyphs
text3 = text3 + encodings.UTF16.Chr(g)
next
'
'// reverse it
'
'dim text2 as string
'for i as integer = len(text) downto 1
'text2 = text2 + mid(text, i, 1)
'next
// and put ob page
call pdf.SetFont "Helvetica", pdf.kfsNone, 20.0, true, pdf.kcpUnicode
call pdf.WriteFTextex 100, 350, 300, 300, pdf.ktaCenter, "Original Text"
call pdf.SetFont "Baghdad", pdf.kfsNone, 40.0, true, pdf.kcpUnicode
call pdf.WriteFTextex 100, 300, 300, 300, pdf.ktaCenter, text
// this is convert method we tried
// not 100% perfect yet
dim textCorrected as string = ArabicConverterModule.Convert(text)
call pdf.SetFont "Helvetica", pdf.kfsNone, 20.0, true, pdf.kcpUnicode
call pdf.WriteFTextex 100, 250, 300, 300, pdf.ktaCenter, "Converted Text"
call pdf.SetFont "Baghdad", pdf.kfsNone, 40.0, true, pdf.kcpUnicode
call pdf.WriteFTextEx 100, 200, 300, 300, pdf.ktaCenter, textCorrected
// reverse it
for i as integer = 1 to len(textCorrected)
System.DebugLog str(asc(mid(textCorrected, i, 1)))
next
dim text2 as string
for i as integer = len(textCorrected) downto 1
text2 = text2 + mid(textCorrected, i, 1)
next
call pdf.SetFont "Helvetica", pdf.kfsNone, 20.0, true, pdf.kcpUnicode
call pdf.WriteFTextex 100, 150, 300, 300, pdf.ktaCenter, "Convert & Reverse Text"
call pdf.SetFont "Baghdad", pdf.kfsNone, 40.0, true, pdf.kcpUnicode
call pdf.WriteFTextEx 100, 100, 300, 300, pdf.ktaCenter, text2
call pdf.SetFont "Helvetica", pdf.kfsNone, 20.0, true, pdf.kcpUnicode
call pdf.WriteFTextex 100, 450, 300, 300, pdf.ktaCenter, "Text with Glypths"
call pdf.SetFont "Baghdad", pdf.kfsNone, 40.0, true, pdf.kcpUnicode
call pdf.WriteFTextEx 100, 400, 300, 300, pdf.ktaCenter, text3
call pdf.EndPage
call pdf.CloseFile
f.Launch
quit
End EventHandler
End Class
Class MyDynaPDFMBS Inherits DynaPDFMBS
EventHandler Function Error(ErrorCode as integer, ErrorMessage as string, ErrorType as integer) As integer
// output all messages on the console:
System.DebugLog str(ErrorCode)+": "+ErrorMessage
// and display dialog:
Dim d as New MessageDialog //declare the MessageDialog object
Dim b as MessageDialogButton //for handling the result
d.icon=MessageDialog.GraphicCaution //display warning icon
d.ActionButton.Caption="Continue"
d.CancelButton.Visible=True //show the Cancel button
// a warning or an error?
if BitAnd(ErrorType, me.kE_WARNING) = me.kE_WARNING then
// if user decided to ignore, we'll ignore
if IgnoreWarnings then Return 0
d.Message="A warning occurred while processing your PDF code."
// we add a third button to display all warnings
d.AlternateActionButton.Caption = "Ignore warnings"
d.AlternateActionButton.Visible = true
else
d.Message="An error occurred while processing your PDF code."
end if
d.Explanation = str(ErrorCode)+": "+ErrorMessage
b=d.ShowModal //display the dialog
Select Case b //determine which button was pressed.
Case d.ActionButton
Return 0 // ignore
Case d.AlternateActionButton
IgnoreWarnings = true
Return 0 // ignore
Case d.CancelButton
Return -1 // stop
End select
End EventHandler
Property IgnoreWarnings As Boolean
End Class
Module ArabicConverterModule
Private Function CharacterMapContains(c as integer) As Boolean
for each ch as charRep in charsMap
if ch.code = c then
Return true
end if
next
End Function
Function Convert(s as string) As string
Init
dim result as string
dim normal as string = ConvertEncoding(s, encodings.UTF16)
dim len as integer = len(normal)
for i as integer = 1 to len
dim current as integer = asc(mid(normal, i, 1))
if CharacterMapContains(current) then
dim prevChar, nextChar as integer
dim prevID as integer = i - 1
dim nextID as integer = i + 1
dim crep as CharRep
// Transparent characters have no effect in the shaping process.
// So, ignore all the transparent characters that are BEFORE the
// current character.
while (prevID >= 1)
dim c as integer = asc(mid(normal, prevID, 1))
if not IsTransparent(c) then
exit
end if
prevID = prevID - 1
wend
prevChar = asc(mid(normal, prevID, 1))
crep = GetCharRep(prevChar)
if ((prevID < 1) or (not CharacterMapContains(prevChar)) or (not (crep.Initial <> 0) and not (crep.Medial <> 0))) then
prevChar = 0
end if
// Transparent characters have no effect in the shaping process.
// So, ignore all the transparent characters that are AFTER the
// current character.
while nextID <= len
dim c as integer = asc(mid(normal, nextID, 1))
if not IsTransparent(c) then
exit
end if
nextID = nextID + 1
wend
nextChar = asc(mid(normal, nextID, 1))
crep = GetCharRep(nextChar)
if ((nextID > len) or not CharacterMapContains(nextChar) or (not (crep.Medial <> 0) and not (crep.Final <> 0) and (nextChar <> &h0640))) then
nextChar = 0
end if
// Combinations
if (current = &h0644 and nextChar <> 0 and (nextChar = &h0622 or nextChar = &h0623 or nextChar = &h0625 or nextChar = &h0627)) then
dim combcrep as CombCharRep = GetCombCharRep(current, nextChar)
if prevChar <> 0 then
result = result + encodings.UTF16.chr(combcrep.Final)
else
result = result + encodings.UTF16.chr(combcrep.Isolated)
end if
i = i + 1
continue
end if
crep = GetCharRep(current)
// Medial
if (prevChar <> 0 and nextChar <> 0 and crep.Medial <> 0) then
result = result + encodings.UTF16.chr( crep.Medial)
continue
// Final
elseif (prevChar <> 0 and crep.Final <> 0) then
result = result + encodings.UTF16.chr( crep.Final)
continue
// Initial
elseif (nextChar <> 0 and crep.Initial <> 0) then
result = result + encodings.UTF16.chr( crep.Initial)
continue
end if
// Isolated
result = result + encodings.UTF16.chr( crep.Isolated)
else
result = result + encodings.UTF16.chr(current)
end if
next
Return result
End Function
Private Function GetCharRep(c as integer) As charRep
for each ch as CharRep in charsMap
if ch.Code = c then
Return ch
end if
next
// return dummy one
static n as new CharRep
Return n
End Function
Private Function GetCombCharRep(c0 as integer, c1 as integer) As CombCharRep
for each ch as CombCharRep in combCharsMap
if ch.Code0 = c0 and ch.Code1 = C1 then
Return ch
end if
next
// return dummy
static n as new CombCharRep
Return n
End Function
Private Sub Init()
if inited then Return
inited = true
charsMap.Append new CharRep( &h0621, &hFE80, 0, 0, 0 ) // HAMZA
charsMap.Append new CharRep( &h0622, &hFE81, 0, 0, &hFE82 ) // ALEF_MADDA
charsMap.Append new CharRep( &h0623, &hFE83, 0, 0, &hFE84 ) // ALEF_HAMZA_ABOVE
charsMap.Append new CharRep( &h0624, &hFE85, 0, 0, &hFE86 ) // WAW_HAMZA
charsMap.Append new CharRep( &h0625, &hFE87, 0, 0, &hFE88 ) // ALEF_HAMZA_BELOW
charsMap.Append new CharRep( &h0626, &hFE89, &hFE8B, &hFE8C, &hFE8A ) // YEH_HAMZA
charsMap.Append new CharRep( &h0627, &hFE8D, 0, 0, &hFE8E ) // ALEF
charsMap.Append new CharRep( &h0628, &hFE8F, &hFE91, &hFE92, &hFE90 ) // BEH
charsMap.Append new CharRep( &h0629, &hFE93, 0, 0, &hFE94 ) // TEH_MARBUTA
charsMap.Append new CharRep( &h062A, &hFE95, &hFE97, &hFE98, &hFE96 ) // TEH
charsMap.Append new CharRep( &h062B, &hFE99, &hFE9B, &hFE9C, &hFE9A ) // THEH
charsMap.Append new CharRep( &h062C, &hFE9D, &hFE9F, &hFEA0, &hFE9E ) // JEEM
charsMap.Append new CharRep( &h062D, &hFEA1, &hFEA3, &hFEA4, &hFEA2 ) // HAH
charsMap.Append new CharRep( &h062E, &hFEA5, &hFEA7, &hFEA8, &hFEA6 ) // KHAH
charsMap.Append new CharRep( &h062F, &hFEA9, 0, 0, &hFEAA ) // DAL
charsMap.Append new CharRep( &h0630, &hFEAB, 0, 0, &hFEAC ) // THAL
charsMap.Append new CharRep( &h0631, &hFEAD, 0, 0, &hFEAE ) // REH
charsMap.Append new CharRep( &h0632, &hFEAF, 0, 0, &hFEB0 ) // ZAIN
charsMap.Append new CharRep( &h0633, &hFEB1, &hFEB3, &hFEB4, &hFEB2 ) // SEEN
charsMap.Append new CharRep( &h0634, &hFEB5, &hFEB7, &hFEB8, &hFEB6 ) // SHEEN
charsMap.Append new CharRep( &h0635, &hFEB9, &hFEBB, &hFEBC, &hFEBA ) // SAD
charsMap.Append new CharRep( &h0636, &hFEBD, &hFEBF, &hFEC0, &hFEBE ) // DAD
charsMap.Append new CharRep( &h0637, &hFEC1, &hFEC3, &hFEC4, &hFEC2 ) // TAH
charsMap.Append new CharRep( &h0638, &hFEC5, &hFEC7, &hFEC8, &hFEC6 ) // ZAH
charsMap.Append new CharRep( &h0639, &hFEC9, &hFECB, &hFECC, &hFECA ) // AIN
charsMap.Append new CharRep( &h063A, &hFECD, &hFECF, &hFED0, &hFECE ) // GHAIN
charsMap.Append new CharRep( &h0640, &h0640, 0, 0, 0 ) // TATWEEL
charsMap.Append new CharRep( &h0641, &hFED1, &hFED3, &hFED4, &hFED2 ) // FEH
charsMap.Append new CharRep( &h0642, &hFED5, &hFED7, &hFED8, &hFED6 ) // QAF
charsMap.Append new CharRep( &h0643, &hFED9, &hFEDB, &hFEDC, &hFEDA ) // KAF
charsMap.Append new CharRep( &h0644, &hFEDD, &hFEDF, &hFEE0, &hFEDE ) // LAM
charsMap.Append new CharRep( &h0645, &hFEE1, &hFEE3, &hFEE4, &hFEE2 ) // MEEM
charsMap.Append new CharRep( &h0646, &hFEE5, &hFEE7, &hFEE8, &hFEE6 ) // NOON
charsMap.Append new CharRep( &h0647, &hFEE9, &hFEEB, &hFEEC, &hFEEA ) // HEH
charsMap.Append new CharRep( &h0648, &hFEED, 0, 0, &hFEEE ) // WAW
//charsMap.Append new CharRep( &h0649, &hFEEF, &hFBE8, &hFBE9, &hFEF0 ) // ALEF_MAKSURA
charsMap.Append new CharRep( &h0649, &hFEEF, 0, 0, &hFEF0 ) // ALEF_MAKSURA
charsMap.Append new CharRep( &h064A, &hFEF1, &hFEF3, &hFEF4, &hFEF2 ) // YEH
combCharsMap.Append new CombCharRep( &h0644, &h0622, &hFEF5, 0, 0, &hFEF6 ) // LAM_ALEF_MADDA
combCharsMap.Append new CombCharRep( &h0644, &h0623, &hFEF7, 0, 0, &hFEF8 ) // LAM_ALEF_HAMZA_ABOVE
combCharsMap.Append new CombCharRep( &h0644, &h0625, &hFEF9, 0, 0, &hFEFA ) // LAM_ALEF_HAMZA_BELOW
combCharsMap.Append new CombCharRep( &h0644, &h0627, &hFEFB, 0, 0, &hFEFC ) // LAM_ALEF
transChars = new Dictionary
transChars.value(&h0610) = nil // ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM
transChars.value(&h0612) = nil // ARABIC SIGN ALAYHE ASSALLAM
transChars.value(&h0613) = nil // ARABIC SIGN RADI ALLAHOU ANHU
transChars.value(&h0614) = nil // ARABIC SIGN TAKHALLUS
transChars.value(&h0615) = nil // ARABIC SMALL HIGH TAH
transChars.value(&h064B) = nil // ARABIC FATHATAN
transChars.value(&h064C) = nil // ARABIC DAMMATAN
transChars.value(&h064D) = nil // ARABIC KASRATAN
transChars.value(&h064E) = nil // ARABIC FATHA
transChars.value(&h064F) = nil // ARABIC DAMMA
transChars.value(&h0650) = nil // ARABIC KASRA
transChars.value(&h0651) = nil // ARABIC SHADDA
transChars.value(&h0652) = nil // ARABIC SUKUN
transChars.value(&h0653) = nil // ARABIC MADDAH ABOVE
transChars.value(&h0654) = nil // ARABIC HAMZA ABOVE
transChars.value(&h0655) = nil // ARABIC HAMZA BELOW
transChars.value(&h0656) = nil // ARABIC SUBSCRIPT ALEF
transChars.value(&h0657) = nil // ARABIC INVERTED DAMMA
transChars.value(&h0658) = nil // ARABIC MARK NOON GHUNNA
transChars.value(&h0670) = nil // ARABIC LETTER SUPERSCRIPT ALEF
transChars.value(&h06D6) = nil // ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA
transChars.value(&h06D7) = nil // ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA
transChars.value(&h06D8) = nil // ARABIC SMALL HIGH MEEM INITIAL FORM
transChars.value(&h06D9) = nil // ARABIC SMALL HIGH LAM ALEF
transChars.value(&h06DA) = nil // ARABIC SMALL HIGH JEEM
transChars.value(&h06DB) = nil // ARABIC SMALL HIGH THREE DOTS
transChars.value(&h06DC) = nil // ARABIC SMALL HIGH SEEN
transChars.value(&h06DF) = nil // ARABIC SMALL HIGH ROUNDED ZERO
transChars.value(&h06E0) = nil // ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO
transChars.value(&h06E1) = nil // ARABIC SMALL HIGH DOTLESS HEAD OF KHAH
transChars.value(&h06E2) = nil // ARABIC SMALL HIGH MEEM ISOLATED FORM
transChars.value(&h06E3) = nil // ARABIC SMALL LOW SEEN
transChars.value(&h06E4) = nil // ARABIC SMALL HIGH MADDA
transChars.value(&h06E7) = nil // ARABIC SMALL HIGH YEH
transChars.value(&h06E8) = nil // ARABIC SMALL HIGH NOON
transChars.value(&h06EA) = nil // ARABIC EMPTY CENTRE LOW STOP
transChars.value(&h06EB) = nil // ARABIC EMPTY CENTRE HIGH STOP
transChars.value(&h06EC) = nil // ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE
transChars.value(&h06ED) = nil // ARABIC SMALL LOW MEEM
End Sub
Private Function IsTransparent(c as integer) As Boolean
Return transChars.HasKey(c)
End Function
Note "Note"
based on
https://github.com/Accorpa/Arabic-Converter-From-and-To-Arabic-Presentation-Forms-B
but we give you this code with BSD license.
Property Private Inited As Boolean
Property Private charsMap() As CharRep
Property Private combCharsMap() As CombCharRep
Property Private transChars As Dictionary
End Module
Class CombCharRep
Sub Constructor()
End Sub
Sub Constructor(c0 as integer, c1 as integer, iso as integer, ini as integer, med as integer, fin as integer)
code0 = c0
code1 = c1
Isolated = iso
Initial = ini
Medial = med
final = fin
End Sub
Property Code0 As Integer
Property Code1 As Integer
Property Final As Integer
Property Initial As Integer
Property Isolated As Integer
Property Medial As Integer
End Class
Class CharRep
Sub Constructor()
End Sub
Sub Constructor(cod as integer, iso as integer, ini as integer, med as integer, fin as integer)
code = cod
Isolated = iso
Initial = ini
Medial = med
final = fin
End Sub
Property Code As Integer
Property Final As Integer
Property Initial As Integer
Property Isolated As Integer
Property Medial As Integer
End Class
End Project
See also:
- /DynaPDF/Create PDF and sign
- /DynaPDF/Create PDF with centimeters
- /DynaPDF/Create PDF with Circle
- /DynaPDF/Create PDF with gradients, overprint and device N colorspace
- /DynaPDF/Create PDF with hidden data
- /DynaPDF/Create PDF with over 2 GB size
- /DynaPDF/Create PDF with Picture and Mask
- /DynaPDF/Create PDF with PictureMBS
- /DynaPDF/Create PDF with Trace
- /DynaPDF/Create PDF with transparency
The items on this page are in the following plugins: MBS DynaPDF Plugin.
