Middleware, development tools, realtime operating system
software and services for superior embedded design


Home
QNX Community Resources
QNX Documentation Library
PfExtentTextCharPositions, PfExtentTextCharPositionsCx

PfExtentTextCharPositions, PfExtentTextCharPositionsCx

QNX Software Systems
Developer Resources
Blogs
Board support packages
Foundry27 projects
Forums
Hardware support listing
Online video tutorials
Product documentation
Technical Articles

PfExtentTextCharPositions(), PfExtentTextCharPositionsCx()

Calculate individual character positions

Synopsis:

#include <photon/Pf.h>
int PfExtentTextCharPositions(
        PhRect_t * ptsExtent,
        PhPoint_t * ptsPos,
        char * psz,
        const char * pckFont,
        int32_t * piIndices,
        int32_t * piPenPositions,
        int32_t iArrayLen,
        uint32_t ulFlags,
        int32_t iBytes,
        uint32_t uiExtentLen,
        PhRect_t const * pktsClip );

#include <photon/Pf.h>
int PfExtentTextCharPositionsCx(
       struct _Pf_ctrl *context,
       PhRect_t *ptsExtent,
       PhPoint_t *ptsPos,
       char *psz,
       const char *pckFont,
       long adata,
       long bdata,
       int32_t *piIndices,
       int32_t *piPenPositions,
       int32_t iArrayLen,
       uint32_t ulFlags,
       int32_t iBytes,
       uint32_t uiExtentLen,
       PhRect_t const *pktsClip );

Arguments:

context
(PfExtentTextCharPositionsCx() only) A pointer to the font context to use, returned by PfAttachCx() or PfAttachDllCx().
ptsExtent
A pointer to a PhRect_t structure that's used to store the extent of the string.
ptsPos
A pointer to a PhPoint_t structure that's used as an offset to apply against the extent. If NULL, no offset is added to the extent values.
psz
A pointer to a NUL-terminated character string.
pckFont
The font name, as created by PfGenerateFontName().
adata
(PfExtentTextCharPositionsCx() only) The horizontal fractional point size, if you set PF_FRACTIONAL in the flags argument.
bdata
(PfExtentTextCharPositionsCx() only) The vertical fractional point size, if you set PF_FRACTIONAL in the flags argument.
iArrayLen
The number of integer entries in the piIndices and piPenPositions arrays.
piIndices
A pointer to an integer array of length iArrayLen. An index corresponds to a location within the string pointed to by psz.

For example, index 0 relates to the pen's x position at the start of the string, index 1 corresponds to the pen's x position after character 1, index 2 corresponds to the pen's x position after character 2, and so on.

In order to function as expected, the indexes must be in numerical order.

piPositions
A pointer to an integer array of length iArrayLen. This array contains the resulting pen x values (in pixels) for each index.
ulFlags
A 32-bit value used for flags. Values that can be ORed in are:
  • PF_WIDE_CHARS -- the characters pointed to by psz are an array of wchar_t characters. By default, the function assumes the characters are multibyte.

    Note: This function assumes each character is represented by 2 bytes that conform to the ISO/IEC 10646-1 UCS-2 double-byte format.


  • PF_CHAR_DRAW_POSITIONS -- if turned on, the bearing x value of the next symbols aren't applied to the returned pen x positions. This is useful when placing cursors:

    Positions without bearing x

    If this bit isn't set, the bearing x value of the next symbols are applied to the pen x positions. This is useful when drawing symbols individually, when you need to know where to place the x origin of each symbol:

    Positions with bearing x

iBytes
The number of bytes in the string. If this is 0, the function assumes that the number of bytes is:
strlen( psz ) / wstrlen( psz )
  
uiExtentLen
The number of characters from the beginning of the string to include in the extent. If 0, the entire string is extented, as permitted by the clipping rectangle.
pktsClip
A clipping rectangle to be used to reduce processing, depending on the value of pktsClip->lr.x (in pixels). If pktsClip is NULL, no clipping is applied.

Library:

PfExtentTextCharPositions()
ph
PfExtentTextCharPositionsCx()
font

Description:

These functions calculate the extent up to uiExtentLen code points. They record horizontal pen positions for each code point referenced in piIndices, and continue processing until pktsClip, if defined, or to the end of the input string psz.

Returns:

0
Success.
-1
An error occurred; errno is set.

Errors:

PfExtentTextCharPositions():

ERANGE
The font manager couldn't fulfill the request; one of the following is true:
  • The iArrayLen argument is larger than strlen(psz).
  • If index 0 is requested, then iArrayLen is larger than strlen(psz) + 1.
  • The iArrayLen argument is less than or equal to 0.
  • An index in piIndices references a character greater than strlen(psz).
EFAULT
One of ptsExtent, piIndices, piPenPositions, pckFont, or psz is NULL.
EINVAL
The font is fixed-width, and an error occurred when trying to retrieve the common width of all characters in that particular font.
EMORE
Something unexpected occurred while processing a run of characters.

PfExtentTextCharPositionsCx():

EBADF
Connection has gone stale, or device error occurred.
ENETUNREACH
Bad message buffer.
ELIBACC
Unable to locate render plugin for specified font.
EFAULT
Unable to locate font description.
ENOENT
Unable to locate suitable base font entry.
ENOMEM
Insufficient memory to allocate scaling resources.
EINVAL
Fixed width font has invalid size.
EINVAL
Failure to load resources for specified font.

Examples:

PfExtentTextCharPositionsCx():

/* Typographic positioning example.  Demonstrates how to manipulate
 * characters, and sub-strings properly at a typographic pen level.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Ph.h>
#include <Pt.h>
#include <errno.h>
#include <font_api.h>

int draw( PtWidget_t * ptsWidget, PhTile_t * ptsDamage );

#define FALSE 0
#define __WIN_SIZE_X_ 1000

extern struct _Ph_ctrl *_Ph_;

int main (int argc, char *argv[])
{   PtArg_t args[8];
    PhPoint_t win_size, pntPOS, pntDIM;
    int i = 0;
    PtWidget_t * win = NULL;

    fprintf(stderr, "POINT : Pen.\n");

    if(PtInit (NULL) == -1)
    {  fprintf(stderr, "NOTE : PtInit failed, errno %d.\n", errno);
       fprintf(stderr, "FAIL : Pen.\n");
       exit(EXIT_FAILURE);
    }

    //  set base win parms
    win_size.x = 800;
    win_size.y = 600;

    PtSetArg(&args[i++],Pt_ARG_DIM, &win_size, 0);
    // window title = name  of program
    PtSetArg(&args[i++],Pt_ARG_WINDOW_TITLE, "Pen Test Suite", 0);


    if((win = PtCreateWidget (PtWindow, NULL, i, args)) == NULL)
    {  fprintf(stderr, "NOTE : Unable to create main window, errno %d.\n", errno);
       fprintf(stderr, "FAIL : Pen.\n");
       exit(EXIT_FAILURE);
    }

    i = 0;
    pntPOS.y = 100;
    pntPOS.x = 75;
    pntDIM.x = __WIN_SIZE_X_ - 75 - 10;
    pntDIM.y = 300;
    PtSetArg(&args[i++], Pt_ARG_POS, &pntPOS, 0);
    PtSetArg(&args[i++], Pt_ARG_DIM, &pntDIM, 0);
    PtSetArg(&args[i++], Pt_ARG_RAW_DRAW_F, draw, 0L);
    PtSetArg(&args[i++], Pt_ARG_POINTER, "Hello, this is big Bobby!!", 0L);

    if(PtCreateWidget(PtRaw, win, i, args) == NULL)
    {  fprintf(stderr, "NOTE : Unable to create raw canvas, errno %d.\n", errno);
       fprintf(stderr, "FAIL : Pen.\n");
       exit(EXIT_FAILURE);
    }

    PtRealizeWidget(win);
    PtMainLoop ();
    return(0);
}

int draw( PtWidget_t * ptsWidget, PhTile_t * ptsDamage )
{   char const * text;

    if(PtGetResource(ptsWidget, Pt_ARG_POINTER, &text, 0L) == 0)
    {  FontName pucFont;
       struct _Pf_ctrl * ctx = _Ph_->font;

       if(PfGenerateFontNameCx(ctx, "PrimaSans BT", 0L, 12L, pucFont) != NULL)
       {  int * piIndx = NULL;
          int * piPos = NULL;
          PhPoint_t pnt;
          pf_point_t tsPos = {0, 0};
          pf_rect_t tsExtent;
          short n = 0, m = 0;
          PgColor_t old;
          PhRect_t tsClip;
          int len = strlen(text);
          char const * str = text;
          int max_chars = 0;

          if((piIndx = (int *)calloc(50, sizeof(int))) == NULL)
          {  fprintf(stderr, "NOTE : Unable to alloc indices, errno %d.\n", errno);
             fprintf(stderr, "FAIL : Pen.\n");
             exit(EXIT_FAILURE);
          }

          if((piPos = (int *)calloc(50, sizeof(int))) == NULL)
          {  fprintf(stderr, "NOTE : Unable to alloc positions, errno %d.\n", errno);
             fprintf(stderr, "FAIL : Pen.\n");
             exit(EXIT_FAILURE);
          }

          PtCalcCanvas(ptsWidget, &tsClip);
          PtClipAdd(ptsWidget, &tsClip);
          PtSuperClassDraw( PtBasic, ptsWidget, ptsDamage );
          tsClip.ul.x += 2;
          tsClip.ul.y += 10;
          PgSetTranslation (&tsClip.ul, Pg_RELATIVE);

          while(len > 0)
          {  wchar_t wc;
             int cl;

             if((cl = mbtowc(&wc, str, MB_CUR_MAX)) <= 0)
             {  --len, ++str;

                if (cl) continue;
                wc = 0;
             }
             else
             {  len -= cl, str += cl;
                max_chars++;
             }
          }
          len = strlen(text);

          for(n = 0; n < max_chars; n++)
            piIndx[n] = n + 1;

          old = PgSetStrokeColor(Pg_BLACK);
          PgSetFont(pucFont);
          PgSetTextColor(Pg_BLACK);

          if(PfExtentCx(ctx, &tsExtent, &tsPos, pucFont, 0L, 0L, text, len, 0,
                        NULL) == 0)
          {  //__STRING_DRAW_
             fprintf(stderr, "NOTE : start Draw text string.\n");
             pnt.x = 10 + tsClip.ul.x;
             pnt.y = 10 + tsClip.ul.y;

             PgDrawIRect(tsExtent.ul.x + pnt.x, tsExtent.ul.y + pnt.y,
                         (tsExtent.lr.x - min(tsExtent.ul.x, 0) + 1) + pnt.x,
                         tsExtent.lr.y + pnt.y, Pg_DRAW_STROKE);
             PgDrawText(text, len, &pnt, 0);
             PgFlush();

             printf("EXTENT_NORMAL:  ul.x:  %d ul.y:  %d lr.x:  %d lr.y:  %d\n",
                    tsExtent.ul.x, tsExtent.ul.y, tsExtent.lr.x, tsExtent.lr.y);
             printf("POSITIONS:  ");

             if(PfExtentTextCharPositionsCx(ctx, &tsExtent, &tsPos, text, pucFont,
                   0L, 0L, piIndx, piPos, len, 0L, 0, 0, NULL) == 0)
             {  for(n = 0; n < max_chars; n++)
                  printf("%d ", piPos[n]);

                printf("\n");
                printf("EXTENT_POS:  ul.x:  %d ul.y:  %d lr.x:  %d lr.y:  %d\n",
                       tsExtent.ul.x, tsExtent.ul.y, tsExtent.lr.x, tsExtent.lr.y);
             }
             else
             {  fprintf(stderr, "NOTE : PfExtentTextCharPositions failed, errno %d.\n",
                        errno);
                fprintf(stderr, "FAIL : Pen.\n");
                exit(EXIT_FAILURE);
             }

             fprintf(stderr, "NOTE : end Draw text string.\n");

             //__SINGLE_CHAR_DRAW_
             for(n = 0; n < max_chars; n++)
               piIndx[n] = n + 1;

             fprintf(stderr,
                     "NOTE : start Draw the string, one character at a time.\n");

             if(PfExtentTextCharPositionsCx(ctx, &tsExtent, &tsPos, text, pucFont,
                   0L, 0L, piIndx, piPos, len, 0L, 0, 0, NULL) == -1)
             {  fprintf(stderr,
                        "NOTE : PfExtentTextCharPositions failed, errno %d.\n",
                        errno);
                fprintf(stderr, "FAIL : Pen.\n");
                exit(EXIT_FAILURE);
             }

             pnt.x = 10 + tsClip.ul.x;
             pnt.y = 50 + tsClip.ul.y;

             PgDrawIRect(tsExtent.ul.x + pnt.x, tsExtent.ul.y + pnt.y,
                         (tsExtent.lr.x - min(tsExtent.ul.x, 0) + 1) + pnt.x,
                         tsExtent.lr.y + pnt.y, Pg_DRAW_STROKE);

             for(n = 0; n < max_chars; n++)
             {  PgDrawText(text + n, 1, &pnt, 0);
                PgFlush();
                pnt.x = 10 + tsClip.ul.x + piPos[n];
                fprintf(stderr, "NOTE : Single[%d]:  %d\n", n, piPos[n]);
             }

             fprintf(stderr,
                     "NOTE : end Draw the string, one character at a time.\n");

             //__TWO_CHUNK_DRAW_
             fprintf(stderr, "NOTE : start Draw the string in two chunks.\n");
             pnt.x = 10 + tsClip.ul.x;
             pnt.y = 100 + tsClip.ul.y;

             PgDrawText(text, 2, &pnt, 0);
             PgFlush();
             sleep(1);
             pnt.x = 10 + tsClip.ul.x + piPos[1];
             PgDrawText(text + 2, len - 2, &pnt, 0);
             PgFlush();
             fprintf(stderr, "NOTE : end Draw the string in two chunks.\n");

             //__PRINT_POSITIONS_
             fprintf(stderr, "NOTE : start print positions.\n");

             for(n = max_chars - 1; n >= 0; n--)
             {  piIndx[0] = n + 1;

                if(PfExtentTextCharPositionsCx(ctx, &tsExtent, &tsPos, text, pucFont,
                      0L, 0L, piIndx, piPos, 1, 0L, 0, 0, NULL) == 0)
                {  for(m = 0; m < 1; m++)
                   fprintf(stderr, "NOTE : Position:  %d\n", piPos[m]);
                   fprintf(stderr,
                      "NOTE : EXTENT_POS ul.x:  %d ul.y:  %d lr.x:  %d lr.y:  %d\n",
                      tsExtent.ul.x, tsExtent.ul.y, tsExtent.lr.x, tsExtent.lr.y);
                }
                else
                {  fprintf(stderr,
                      "NOTE : PfExtentTextCharPositions failed, errno %d.\n",
                      errno);
                   fprintf(stderr, "FAIL : Pen.\n");
                   exit(EXIT_FAILURE);
                }
             }
             fprintf(stderr, "NOTE : end print positions.\n");

             //__DRAW_OVERLAY_
             fprintf(stderr,
                "NOTE : start Draw string, then overlay individual characters on \
 top from right to left.\n");

             if(PfExtentCx(ctx, &tsExtent, &tsPos, pucFont, 0L, 0L, text, len, 0,
                           NULL) == 0)
             {  pnt.x = 10 + tsClip.ul.x;
                pnt.y = 150 + tsClip.ul.y;

                PgDrawIRect(tsExtent.ul.x + pnt.x, tsExtent.ul.y + pnt.y,
                            (tsExtent.lr.x - min(tsExtent.ul.x, 0) + 1)
                            + pnt.x, tsExtent.lr.y + pnt.y, Pg_DRAW_STROKE);

                for(n = max_chars - 1; n >= 0; n--)
                {  switch(n)
                   {  case 0:  pnt.x = 10 + tsClip.ul.x;
                               PgDrawText(text + 0, len, &pnt, 0);
                               PgFlush();
                               break;

                      default: piIndx[0] = n;

                               if(PfExtentTextCharPositionsCx(
                                     ctx, &tsExtent, &tsPos, text,
                                     pucFont, 0L, 0L, piIndx, piPos,
                                     1, 0L, 0, 0, NULL) == -1)
                               {  fprintf(stderr,
                                     "NOTE : PfExtentTextCharPositions failed, \
 errno %d.\n", errno);
                                  fprintf(stderr, "FAIL : Pen.\n");
                                  exit(EXIT_FAILURE);
                               }
                               else
                               {  fprintf(stderr, "NOTE : Position:  %d\n", piPos[0]);
                                  pnt.x = 10 + tsClip.ul.x + piPos[0];
                                  PgDrawText(text + n, len - n, &pnt, 0);
                                  PgFlush();
                               }
                               break;
                   }
                }
             }
             else
             {  fprintf(stderr, "NOTE : PfExtentText failed, errno %d.\n", errno);
                fprintf(stderr, "FAIL : Pen.\n");
                exit(EXIT_FAILURE);
             }
             fprintf(stderr,
                "NOTE : end Draw string, then overlay individual characters on \
 top from right to left.\n");

             //__TEST_OUTORDER_
             fprintf(stderr, "NOTE : start Test indices which are non-sequential.\n");
             for(n = 0; n < 4; n++)
             {  struct element
                {  int first;
                   int second;
                };

                struct element times[4] = { { 1, 5 }, { 2, 4 }, { 3, 5 }, { 2, 5} };
                piIndx[0] = times[n].first;
                piIndx[1] = times[n].second;

                if(PfExtentTextCharPositionsCx(ctx, &tsExtent, &tsPos, text,
                      pucFont, 0L, 0L, piIndx, piPos, 2, 0L, 0, 0, NULL) == -1)
                {  fprintf(stderr,
                      "NOTE : PfExtentTextCharPositions failed, errno %d.\n",
                      errno);
                   fprintf(stderr, "FAIL : Pen.\n");
                   exit(EXIT_FAILURE);
                }
                else
                {  fprintf(stderr, "NOTE : Position[%d]:  %d\n", times[n].first,
                           piPos[0]);
                   fprintf(stderr, "NOTE : Position[%d]:  %d\n", times[n].second,
                           piPos[1]);
                }
             }
             fprintf(stderr, "NOTE : end Test indices which are non-sequential.\n");
          }
          else
          {  fprintf(stderr, "NOTE : PfExtentText failed, errno %d.\n", errno);
             fprintf(stderr, "FAIL : Pen.\n");
             exit(EXIT_FAILURE);
          }

          PgSetStrokeColor(old);
          free(piPos);
          free(piIndx);

          tsClip.ul.x *= -1;
          tsClip.ul.y *= -1;
          PgSetTranslation (&tsClip.ul, Pg_RELATIVE);
          PtClipRemove();
       }
       else
       {  fprintf(stderr, "NOTE : Unable to create raw canvas, errno %d.\n", errno);
          fprintf(stderr, "FAIL : Pen.\n");
          exit(EXIT_FAILURE);
       }
   }
   else
   {  fprintf(stderr, "NOTE : Unable to create raw canvas, errno %d.\n", errno);
      fprintf(stderr, "FAIL : Pen.\n");
      exit(EXIT_FAILURE);
   }

   fprintf(stderr, "PASS : Pen.\n");
   exit(EXIT_SUCCESS);
   return( Pt_CONTINUE );
}

PfExtentTextCharPositions():

#define MAX_INDICES 5
#define FALSE 0

int iaIndex[MAX_INDICES] = {0, 1, 2, 3, 4};
int iaPosition[MAX_INDICES];
PhRect_t tsExtent;
char caBuff[MAX_FONT_TAG];

PfGenerateFontName("Helvetica", 0, 24, caBuff);

if( PfExtentTextCharPositions( &tsExtent, NULL,
       "Lucy", caBuff, iaIndex, iaPositon,
        MAX_INDICES, 0L, 0, 0, NULL) != EOK)
  printf("Error in PfExtentTextCharPositions().\n");
else
  printf("Pixel penx positions after each character \
in string %s, are as follows: %d %d %d %d %d.\n",
         "Lucy", iaPosition[0], iaPosition[1],
         iaPosition[2], iaPosition[3],
         iaPositionArray[4]);

The pixel pen x positions for each character in the string Lucy are placed in the integer array iaPos, according to the indexes specified in iaIndex. Index 0 corresponds to the position before symbol L, index 1 corresponds to the position after L, index 2 corresponds to the position after u, and so on.

Classification:

Photon

Safety:
Interrupt handler No
Signal handler No
Thread No

See also:

PfExtent(), PfExtentCx(), PfExtentText(), PfExtentTextCharPositionsCx(), PfExtentTextToRect(), PfExtentFractTextCharPositions(), PfFractionalExtentText(), PfGenerateFontName(), PfGenerateFontNameCx(), PhPoint_t, PhRect_t

Fonts chapter of the Photon Programmer's Guide