' 
' Starter sample for text shaping features
' Demonstrate text shaping for Arabic, Hebrew, and Devanagari scripts
' Right-to-left text is reordered according to the Bidi algorithm.
'
' Required data: suitable fonts for the scripts
'

Imports System
Imports System.Text
Imports PDFlib_dotnet

Structure shaping
    Public fontopt As String          ' fontname and other font options
    Public optlist As String          ' text options
    Public textflow As Integer        ' can't use Textflow for Bidi text
    Public language As String         ' language name
    Public text As String             ' sample text
    ' Constructor:
    Public Sub New(ByVal s_fontopt As String, ByVal s_optlist As String, _
            ByVal s_textflow As Integer, _
            ByVal s_language As String, ByVal s_text As String)
        fontopt = s_fontopt
        optlist = s_optlist
        textflow = s_textflow
        language = s_language
        text = s_text
    End Sub
End Structure

Module starter_shaping
  Sub Main()
    ' This is where the data files are. Adjust as necessary.
    Dim searchpath As String = "../../../data"
    Dim outfile As String = "starter_shaping.pdf"

    Dim optlist As New StringBuilder()
    Dim p As PDFlib = Nothing
    Dim row, col, table, tf As Integer
    Dim llx As Double = 25
    Dim lly As Double = 25
    Dim urx As Double = 825
    Dim ury As Double = 550
    Dim result As String

    Dim header() As String = { _
            "Language", "Raw input", "Reordered and shaped output" _
    }
    Dim MAXCOL As Integer = header.Length

        Dim shapingsamples() As shaping = { _
        New shaping("", "", 0, "", ""), _
        New shaping("", "", 0, "", ""), _
 _
        New shaping("fontname=NotoNaskhArabic-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=arab", 0, "Arabic", _
        "&#x0627;&#x0644;&#x0639;&#x064E;&#x0631;&#x064E;&#x0628;&#x0650;" & _
        "&#x064A;&#x0629;"), _
 _
        New shaping("fontname=NotoNaskhArabic-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=arab", 0, "Arabic", _
        "&#x0645;&#x0631;&#x062D;&#x0628;&#x0627;! (Hello)" _
        ), _
 _
        New shaping("fontname=NotoNaskhArabic-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=arab", 0, "Arabic", _
        "&#xFEFF;&#x0627;&#x0644;&#x0645;&#x0627;&#x062F;&#x0629;&#x0020;" & _
        "&#x0031;&#x0020;&#x064A;&#x0648;&#x0644;&#x062F;&#x0020;&#x062C;" & _
        "&#x0645;&#x064A;&#x0639;&#x0020;&#x0627;&#x0644;&#x0646;&#x0627;" & _
        "&#x0633;&#x0020;&#x0623;&#x062D;&#x0631;&#x0627;&#x0631;&#x064B;" & _
        "&#x0627;&#x0020;&#x0645;&#x062A;&#x0633;&#x0627;&#x0648;&#x064A;" & _
        "&#x0646;&#x0020;&#x0641;&#x064A;&#x0020;&#x0627;&#x0644;&#x0643;" & _
        "&#x0631;&#x0627;&#x0645;&#x0629;&#x0020;&#x0648;&#x0627;&#x0644;" & _
        "&#x062D;&#x0642;&#x0648;&#x0642;&#x002E;&#x0020;" _
        ), _
 _
        New shaping("fontname=NotoNaskhArabic-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=arab", 0, "Arabic", _
        "&#x0648;&#x0642;&#x062F;&#x0020;&#x0648;&#x0647;&#x0628;&#x0648;" & _
        "&#x0627;&#x0020;&#x0639;&#x0642;&#x0644;&#x0627;&#x064B;&#x0020;" & _
        "&#x0648;&#x0636;&#x0645;&#x064A;&#x0631;&#x064B;&#x0627;&#x0020;" & _
        "&#x0648;&#x0639;&#x0644;&#x064A;&#x0647;&#x0645;&#x0020;&#x0623;" & _
        "&#x0646;&#x0020;&#x064A;&#x0639;&#x0627;&#x0645;&#x0644;&#x0020;" & _
        "&#x0628;&#x0639;&#x0636;&#x0647;&#x0645;&#x0020;&#x0628;&#x0639;" & _
        "&#x0636;&#x064B;&#x0627;&#x0020;&#x0628;&#x0631;&#x0648;&#x062D;" & _
        "&#x0020;&#x0627;&#x0644;&#x0625;&#x062E;&#x0627;&#x0621;&#x002E;" _
        ), _
 _
        New shaping("fontname=NotoSerifHebrew-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=hebr", 0, "Hebrew", _
          "&#x05E2;&#x05B4;&#x05D1;&#x05B0;&#x05E8;&#x05B4;&#x05D9;&#x05EA;" _
        ), _
 _
        New shaping("fontname=NotoSerifHebrew-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=hebr", 0, "Hebrew", _
        "&#x05E1;&#x05E2;&#x05D9;&#x05E3;&#x0020;&#x05D0;&#x002E;&#x0020;" & _
        "&#x05DB;&#x05DC;&#x0020;&#x05D1;&#x05E0;&#x05D9;&#x0020;&#x05D0;" & _
        "&#x05D3;&#x05DD;&#x0020;&#x05E0;&#x05D5;&#x05DC;&#x05D3;&#x05D5;" & _
        "&#x0020;&#x05D1;&#x05E0;&#x05D9;&#x0020;&#x05D7;&#x05D5;&#x05E8;" & _
        "&#x05D9;&#x05DF;&#x0020;&#x05D5;&#x05E9;&#x05D5;&#x05D5;&#x05D9;" & _
        "&#x05DD;&#x0020;&#x05D1;&#x05E2;&#x05E8;&#x05DB;&#x05DD;&#x0020;" & _
        "&#x05D5;&#x05D1;&#x05D6;&#x05DB;&#x05D5;&#x05D9;&#x05D5;&#x05EA;" & _
        "&#x05D9;&#x05D4;&#x05DD;&#x002E;&#x0020;" _
        ), _
 _
        New shaping("fontname=NotoSerifHebrew-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=hebr", 0, "Hebrew", _
        "&#x05DB;&#x05D5;&#x05DC;&#x05DD;&#x0020;&#x05D7;&#x05D5;&#x05E0;" & _
        "&#x05E0;&#x05D5;&#x0020;&#x05D1;&#x05EA;&#x05D1;&#x05D5;&#x05E0;" & _
        "&#x05D4;&#x0020;&#x05D5;&#x05D1;&#x05DE;&#x05E6;&#x05E4;&#x05D5;" & _
        "&#x05DF;&#x002C;&#x0020;" _
        ), _
 _
        New shaping("fontname=NotoSerifHebrew-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=hebr", 0, "Hebrew", _
        "&#x05DC;&#x05E4;&#x05D9;&#x05DB;&#x05DA;&#x0020;&#x05D7;&#x05D5;" & _
        "&#x05D1;&#x05D4;&#x0020;&#x05E2;&#x05DC;&#x05D9;&#x05D4;&#x05DD;" & _
        "&#x0020;&#x05DC;&#x05E0;&#x05D4;&#x05D5;&#x05D2;&#x0020;&#x05D0;" & _
        "&#x05D9;&#x05E9;&#x0020;&#x05D1;&#x05E8;&#x05E2;&#x05D4;&#x05D5;" & _
        "&#x0020;&#x05D1;&#x05E8;&#x05D5;&#x05D7;&#x0020;&#x05E9;&#x05DC;" & _
        "&#x0020;&#x05D0;&#x05D7;&#x05D5;&#x05D4;&#x002E;" _
        ), _
 _
        New shaping("fontname=NotoSerifDevanagari-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=deva", 1, "Hindi", _
          "&#x0939;&#x093F;&#x0928;&#x094D;&#x0926;&#x0940;" _
        ), _
 _
        New shaping("fontname=NotoSerifDevanagari-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=deva advancedlinebreak", 1, "Hindi", _
        "&#x0905;&#x0928;&#x0941;&#x091A;&#x094D;&#x091B;&#x0947;&#x0926;" & _
        "&#x0020;&#x0967;&#x002E;&#x0020;&#x0938;&#x092D;&#x0940;&#x0020;" & _
        "&#x092E;&#x0928;&#x0941;&#x0937;&#x094D;&#x092F;&#x094B;&#x0902;" & _
        "&#x0020;&#x0915;&#x094B;&#x0020;&#x0917;&#x094C;&#x0930;&#x0935;" & _
        "&#x0020;&#x0914;&#x0930;&#x0020;&#x0905;&#x0927;&#x093F;&#x0915;" & _
        "&#x093E;&#x0930;&#x094B;&#x0902;&#x0020;&#x0915;&#x0947;&#x0020;" & _
        "&#x092E;&#x093E;&#x092E;&#x0932;&#x0947;&#x0020;&#x092E;&#x0947;" & _
        "&#x0902;&#x0020;&#x091C;&#x0928;&#x094D;&#x092E;&#x091C;&#x093E;" & _
        "&#x0924;&#x0020;&#x0938;&#x094D;&#x0935;&#x0924;&#x0928;&#x094D;" & _
        "&#x0924;&#x094D;&#x0930;&#x0924;&#x093E;&#x0020;&#x0914;&#x0930;" & _
        "&#x0020;&#x0938;&#x092E;&#x093E;&#x0928;&#x0924;&#x093E;&#x0020;" & _
        "&#x092A;&#x094D;&#x0930;&#x093E;&#x092A;&#x094D;&#x0924;&#x0020;" & _
        "&#x0939;&#x0948;&#x0020;&#x0964;&#x0020;&#x0909;&#x0928;&#x094D;" & _
        "&#x0939;&#x0947;&#x0902;&#x0020;&#x092C;&#x0941;&#x0926;&#x094D;" & _
        "&#x0918;&#x093F;&#x0020;&#x0914;&#x0930;&#x0020;&#x0905;&#x0928;" & _
        "&#x094D;&#x0924;&#x0930;&#x093E;&#x0924;&#x094D;&#x092E;&#x093E;" & _
        "&#x0020;&#x0915;&#x0940;&#x0020;&#x0926;&#x0947;&#x0928;&#x0020;" & _
        "&#x092A;&#x094D;&#x0930;&#x093E;&#x092A;&#x094D;&#x0924;&#x0020;" & _
        "&#x0939;&#x0948;&#x0020;&#x0914;&#x0930;&#x0020;&#x092A;&#x0930;" & _
        "&#x0938;&#x094D;&#x092A;&#x0930;&#x0020;&#x0909;&#x0928;&#x094D;" & _
        "&#x0939;&#x0947;&#x0902;&#x0020;&#x092D;&#x093E;&#x0908;&#x091A;" & _
        "&#x093E;&#x0930;&#x0947;&#x0020;&#x0915;&#x0947;&#x0020;&#x092D;" & _
        "&#x093E;&#x0935;&#x0020;&#x0938;&#x0947;&#x0020;&#x092C;&#x0930;" & _
        "&#x094D;&#x0924;&#x093E;&#x0935;&#x0020;&#x0915;&#x0930;&#x0928;" & _
        "&#x093E;&#x0020;&#x091A;&#x093E;&#x0939;&#x093F;&#x090F;&#x0020;" & _
        "&#x0964;" _
        ), _
 _
        New shaping("fontname=NotoSerifDevanagari-Regular fallbackfonts={ {fontname=NotoSerif-Regular} }", "shaping script=deva", 1, "Sanskrit", _
        "&#x0938;&#x0902;&#x0938;&#x094D;&#x0915;&#x0943;&#x0924;&#x092E;" & _
        "&#x094D;" _
        ) _
 _
        }

    Dim MAXROW As Integer = shapingsamples.Length

    Try
        ' create a new PDFlib object
        p = New PDFlib()

	' Set the search path for fonts and PDF files 
	p.set_option("SearchPath={{" + searchpath + "}} charref=true")

        ' This means that formatting and other errors will raise an
        ' exception. This simplifies our sample code, but is not
        ' recommended for production code.
        '/
        p.set_option("errorpolicy=exception")

        ' Set an output path according to the name of the topic
        if (p.begin_document(outfile, "") = -1) Then
            Console.WriteLine("Error: {0}\n", p.get_errmsg())
            return
        End If

        p.set_info("Creator", "PDFlib starter sample")
        p.set_info("Title", "starter_shaping")

        table = -1

        ' Create table header
        row = 1
        For col=1 To MAXCOL Step 1
            optlist.Length = 0
            optlist.Append("fittextline={fontname=NotoSerif-Regular ")
            optlist.Append("fontsize=14} colwidth=")
            If (col = 1) Then
                optlist.Append("10%")
            Else
                optlist.Append("45%")
            End If
            table = p.add_table_cell(table, col, row, header(col-1), _
                                                    optlist.ToString())
        Next

        ' Create shaping samples
        For row=2 To  MAXROW - 1 Step 1
            col=1

            ' Column 1: language name
            optlist.Length = 0
                optlist.Append( _
            "fittextline={fontname=NotoSerif-Regular fontsize=12}")
            table = p.add_table_cell(table, col, row, _
                shapingsamples(row).language, optlist.ToString())
            col = col + 1

            ' Column 2: raw text
            optlist.Length = 0
                optlist.AppendFormat("{0} ", shapingsamples(row).fontopt)
            optlist.Append("fontsize=12 leading=150% alignment=left")
            tf = p.create_textflow(shapingsamples(row).text, optlist.ToString())
            optlist.Length = 0
            optlist.Append("margin=4 fittextflow={verticalalign=top} textflow=")
            optlist.AppendFormat( "{0}", tf)
            table = p.add_table_cell(table, col, row, "", optlist.ToString())
            col = col + 1

            ' Column 3: shaped and reordered text (Textline or Textflow)
            If (shapingsamples(row).textflow <> 0) Then
                optlist.Length = 0
                    optlist.AppendFormat("{0} ", shapingsamples(row).fontopt)
                optlist.AppendFormat("{0} ", shapingsamples(row).optlist)
                optlist.Append("fontsize=12 leading=150% alignment=left")
                tf = p.create_textflow(shapingsamples(row).text, optlist.ToString())
                optlist.Length = 0
                optlist.Append("margin=4 fittextflow={verticalalign=top} textflow=")
                optlist.AppendFormat("{0}", tf)
                table = p.add_table_cell(table, col, row, "", optlist.ToString())
                col = col + 1
            Else
                optlist.Length = 0
                optlist.Append("fittextline={ ")
                    optlist.AppendFormat("{0} ", shapingsamples(row).fontopt)
                optlist.AppendFormat("{0} ", shapingsamples(row).optlist)
                optlist.Append("fontsize=12 }")
                table = p.add_table_cell(table, col, row, _
                         shapingsamples(row).text, optlist.ToString())
                col = col + 1
            End If
        Next

        ' ---------- Place the table on one or more pages ----------
        '
        ' Loop until all of the table is placed; create new pages
        ' as long as more table instances need to be placed.
        '/
        do
            p.begin_page_ext(0, 0, "width=a4.height height=a4.width")

            ' Shade every other row; draw lines for all table cells.
            optlist.Length = 0
            optlist.Append( "header=1 fill={{area=rowodd " & _
                "fillcolor={gray 0.9}}} stroke={{line=other}} ")

            ' Place the table instance
            result = p.fit_table(table, llx, lly, urx, ury, optlist.ToString())

            if (result = "_error") Then
                Console.WriteLine("Couldn't place table: {0}\n", p.get_errmsg())
                return
            End If

            p.end_page_ext("")

        Loop While (result = "_boxfull")

            p.end_document("")

        Catch e As PDFlibException
            Console.Error.WriteLine("PDFlib exception occurred:")
            Console.Error.WriteLine("[{0}] {1}: {2}", e.get_errnum(), e.get_apiname(), e.get_errmsg)
        Catch e As Exception
            Console.Error.WriteLine(e.ToString())
        Finally
            If Not p Is Nothing Then
                p.Dispose()
                p = Nothing
            End If
        End Try
  End Sub
End Module
