Using the layout functions

This section contains examples to illustrate how to call the BIDI layout engine. Note that to use the Bidi roundtrip algorithm, the option must be enabled in both legs of a layout transformation.

The example in Figure 1 sets the option using a layout string modifier.
Figure 1. Example of using a layout string modifier
Layout Transformation #1:
-------------------------
"@ls orientation=ltr:ltr, typeoftext=visual:implicit,
bidiroundtrip=true"

Layout Transformation #2:
-------------------------
"@ls orientation=ltr:ltr, typeoftext=implicit:visual,
bidiroundtrip=true"
Figure 2 demonstrates how to use the m_setvalues_layout() function to set the option.
Figure 2. Example of using the m_setvalues_layout() function
LayoutValues layout = (LayoutValues)
calloc(2,sizeof(LayoutValueRec));
layout 0 .name  = BidiRoundTrip;
layout 0 .value = (void *) BIDIROUNDTRIP_ON;
layout 1 .name  = 0;

To use the layout functions, perform the following steps.

  1. Include the sys/layout.h header file to define the values and function prototypes.
    #include <sys/layout.h>
  2. Declare the program variables.
    LayoutObject plh;
    int error = 0, index;
    size_t insize = 9, outsize;
    LayoutValues layout;
    LayoutTextDescriptor set_desc;
    
    char *inbuffer;
    char *outbuffer;
    char *inShape;
    char *outShape;
    char *myModifier=
         "@lstypeoftext=implicit:visual,shaping=nominal:shaped,orientation=ltr:rtl";

    In the first line, declare a LayoutObject called "plh". This is the layout object that m_create_layout() creates later when invoked. index is the index of the returned error. insize is the size of the input buffer,and outsize is the size of the output buffer. The four integer variables in the second and third lines will be used later in the call of m_setvalues_layout( ) and m_transform_layout( ). In the fourth line, declare a LayoutValues variable called "layout" and in the fifth line declare a LayoutTextDescriptor called "set_desc". These two variables are very important. They will be used with m_setvalues_layout() in the form of input/output pairs to specify new input and output values for each one of the specified attributes. The next two lines add four strings (char *), that will be used as the input buffer, output buffer, input code page and, finally, the output code page. The last line adds a string that specifies the modifier to be used as specified earlier in the m_create_layout() function to create the layout object.

  3. Allocate memory to the declared strings, layout values, layout text descriptor, and write the contents of the input buffer.
    inbuffer =(char *)malloc(insize*sizeof(char));
    outbuffer=(char *)malloc(outsize*sizeof(char));
    layout   = (LayoutValues)malloc(6*sizeof(LayoutValueRec));
    set_desc = (LayoutTextDescriptor)malloc(3*sizeof(LayoutTextDescriptorRec));
    inShape = (char*) malloc(20 * sizeof(char));
    outShape = (char*) malloc(20 * sizeof(char));
    inbuffer[0]   = 0xB0;
    inbuffer[1]   = 0xB1;
    inbuffer[2]   = 0xB2;
    inbuffer[3]   = 0xBF;
    inbuffer[4]   = 0x40;
    inbuffer[5]   = 0x9A;
    inbuffer[6]   = 0x75;
    inbuffer[7]   = 0x58;
    inbuffer[8]   = 0xDC;

    The values of the input buffer are added one by one as an array of characters, but several alternatives could be used. For example, you can read the input buffer as a string from a file, or get it from another application.

  4. Call the m_create_layout() function to create a layout object "plh".
    plh = m_create_layout("Ar_AA",myModifier);

    In the preceding example, the layout object "plh" is created with the locale Ar_AA with the modifier myModifier.

  5. At this point of the program, there are two options: call m_setvalues_layout() or call the m_transform_layout() (or m_wtransform_layout()) directly.
    Specify the input/output layout values. The first two lines below specify the two strings used as the input and output code pages. These two strings will be used by the other functions to specify the input code page for the input buffer and the output code page for the output buffer.
    strcpy(outShape,"ibm-420");
    strcpy(inShape,"ibm-425");
    
    set_desc[0].inp = ORIENTATION_LTR;
    set_desc[0].out = ORIENTATION_LTR;
    set_desc[1].inp = TEXT_IMPLICIT;
    set_desc[1].out = TEXT_VISUAL;
    set_desc[2].inp = TEXT_NOMINAL;
    set_desc[2].out = TEXT_SHAPED;
    Add the input/output layout text descriptor pairs. These pairs are in the form of input descriptor and output descriptor; for example, the first statement specifies that the input orientation will be "orientation-left-to-right" and the second statement specifies that the output orientation will be also "orientation-left-to-right". All the above pairs follow the same rule to define the input/output pairs.
     layout[0].name  = ShapeCharset;
     layout[0].value = (char *)outShape;
    
     layout[1].name  = InputCharset;
     layout[1].value = (char *)inShape;
    
     layout[2].name  = Orientation;
     layout[2].value = (LayoutTextDescriptor)&set_desc[0];
    
     layout[3].name  = TypeOfText;
     layout[3].value = (LayoutTextDescriptor)&set_desc[1];
    
     layout[4].name  = TextShaping;
     layout[4].value = (LayoutTextDescriptor)&set_desc[2];
    
     layout[5].name = 0;

    In the preceding lines, "set_desc" pairs create the new layout values attributes. Each one of these statements will be in the form of attribute_name/attribute_value pairs, for example in the fifth and sixth statements "Orientation" is the attribute name and set_desc[0] (as defined above) is the attribute value. The first two statements are used to declare the output code page and the following two lines are used to specify the input code page.

    Call the m_setvalues_layout() function.
    if((error =m_setvalues_layout(plh,layout,&index)))
    printf("\n An error %d occurred in setting the value number %d\n",error,index);

    Invoke m_setvalues_layout() using the layout object "plh", the layout values "layout" and an integer "index". If m_setvalues_layout() could not set any one of the layout values attributes, it will return -1 in the integer variable called "error", and also return the index of the layout value that caused the problem.

  6. Call the m_transform_layout() function. The m_transform_layout() and m_wtransform_layout() functions are the same, except that m_wtransform_layout() is used for wide character (wchar_t). Both functions will do the actual reordering and shaping of the input buffer using the layout object (plh) created in step 4.
    m_transform_layout(plh,inbuffer,insize,outbuffer,&outsize,NULL,
    NULL,NULL,NULL);
    plh
    The Layout Object returned by m_create_layout().
    inbuffer
    Corresponds to the input string to the function that the layout functions will process.
    insize
    Gives the input size of the input string specified by the Input Buffer argument.
    outbuffer
    Any transformed data is stored here. This buffer will contain the data after converting it to the specified output code page.
    outsize
    Gives the number of bytes in the Output Buffer.

    The last four parameters are given here as NULL and they represent Input To Output Mapping, Output To Input Mapping, Property and Input Buffer Index as described above in the Overview of the Layout Functions. Each of these output arguments may be NULL to specify that no output is desired for the specific argument.

  7. Call the m_destroy_layout() function. This function must be called at the end of the program to destroy the layout object or to free up the allocated memory used by the layout object.
     m_destroy_layout(plh);

Finally, Figure 3 is sample program (CCNGBID1) that shows how the bidirectional layout API are used.