PfGetOutline(), PfGetOutlineCx()

Get individual point information for a glyph outline

Synopsis:

#include <photon/Pf.h>
long PfGetOutline( char const *pkucFont,
                   unsigned long ulSymbol,
                   PHFONT_METRICS *ptsMetrics,
                   PhPoint_t **pptsPoints,
                   int **ppiLoops );

#include <font_api.h>
long PfGetOutlineCx( struct _Pf_ctrl *context,
                     char const *pkucFont,
                     unsigned long ulSymbol,
                     PHFONT_METRICS *ptsMetrics,
                     PhPoint_t **pptsPoints,
                     int **ppiLoops );

Arguments:

context
(PfGetOutlineCx() only) A pointer to the font context to use, returned by PfAttachCx() or PfAttachDllCx().
pckFont
The font name, as created by PfGenerateFontName() or PfGenerateFontNameCx().
ulSymbol
The Unicode value of the glyph whose outline is to be determined. Valid values are 0x0000 to 0xFFFF.
ptsMetrics
A pointer to a structure of type PHFONT_METRICS, which contains at least the following members:
int32_t Advance;  // 16.16 format
int32_t BearingX; // 16.16 format
int32_t BearingY; // 16.16 format
int32_t MaxX;     // 16.16 format
int32_t Height;   // 1.1 format (pixel)
int32_t Width;    // 1.1 format (pixel)
  
pptsPoints
A pointer to a pointer of type PhPoint_t. The function allocates memory and stores the returned outline points within this memory.
ppiLoops
A pointer to a pointer of type int. The function allocates memory and stores the number of loop iterations per contour within this memory.

Library:

PfGetOutline()
ph
PfGetOutlineCx()
font

Description:

These functions provide individual point information, in pixel coordinates, for a glyph outline. These points can be transformed in any way desired. In order to fill the resultant outlines, there are several possible routes:


Note: Your application must free the memory pointed to by pptsPoints and ppiLoops.

PfGetOutlineCx() is similar to PfGetOutline(), but lets you specify the font context.

Returns:

The number of contours that make up the outline, or -1 if an error occurred (errno is set).

Examples:

PfGetOutlineCx():

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>

#include <Ph.h>
#include <Pt.h>

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

#define DESC_FONT "PrimaSans BT"

int main(int argc, char *argv[])
{  PtArg_t args[4];
   PhPoint_t win_size, pos, dim;
   PtWidget_t * wnd, * raw;
   FontName font;
   PhRect_t extent;
   long lAscender = 0L;

   PtInit (NULL);

   //  set base pwndMain parms
   win_size.x = 400;
   win_size.y = 400;

   PtSetArg(&args[0],Pt_ARG_DIM, &win_size, 0);
   PtSetArg(&args[1],Pt_ARG_WINDOW_TITLE, (long)"Outline Test", 0);

   wnd = PtCreateWidget (PtWindow, Pt_NO_PARENT, 2, args);

   if(PfGenerateFontName(DESC_FONT, 0, 36, font) == NULL)
     return(Pt_CONTINUE);

   PfExtentText(&extent, NULL, font, "M", 0);

   lAscender = 200;

   pos.y = 0;
   pos.x = 0;
   dim.x = 400;
   dim.y = (lAscender + (-extent.ul.y));
   PtSetArg(&args[0], Pt_ARG_POS, &pos, 0);
   PtSetArg(&args[1], Pt_ARG_DIM, &dim, 0);
   PtSetArg(&args[2], Pt_ARG_RAW_DRAW_F, draw_canvas, 0L);
   PtSetArg(&args[3], Pt_ARG_POINTER, font, 0L);

   raw = PtCreateWidget(PtRaw, wnd, 4, args);
   PtRealizeWidget(wnd);
   PtMainLoop ();
   return(EXIT_SUCCESS);
}

long s_lAdvanceY = 0L;

int * loops;

int draw_canvas( PtWidget_t * widget, PhTile_t * damage )
{  PgColor_t old;
   pf_point_t * pnt = NULL;
   pf_metrics_t metrics;
   long contours = 0L;
   struct _Pf_ctrl * pf;
   PhRect_t rect;

   s_lAdvanceY = 0L;

   // find our canvas
   PtCalcCanvas(widget, &rect);
   PtSuperClassDraw( PtBasic, widget, damage );

   old = PgSetStrokeColor(Pg_BLACK);

   if((pf = PfAttachCx(NULL, 0)) != NULL)
   {  char const * pfont;
      PtGetResource(widget, Pt_ARG_POINTER, &pfont, 0L);

      if((contours = PfGetOutlineCx(pf, pfont, 'i', &metrics, &pnt, &loops)) == -1L)
        return(Pt_CONTINUE);
      else
      {  PhPoint_t pos;
         long ii;
         int offset = 0;

         pos.x = (-metrics.BearingX >> 16) + rect.ul.x;
         pos.y = (metrics.BearingY >> 16) + rect.ul.y;

         for(ii = 0L; ii < contours; ii++)
         {  PgDrawPolygon(pnt + offset, loops[ii], &pos, Pg_DRAW_STROKE);
            offset += loops[ii];
         }

         free(pnt);
         free(loops);
      }

      PfDetachCx(pf);
   }

   PgSetStrokeColor(old);
   return( Pt_CONTINUE );
}

PfGetOutline():

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>

#include <Ph.h>
#include <Pt.h>

int DrawOutline( PhPoint_t * pnt, long ContourCount,
                 PhRect_t * rect, long lAscender);
int fnDrawCanvas( PtWidget_t * ptsWidget,
                  PhTile_t * ptsDamage );

PtWidget_t * pwndMain = NULL, * pobjRaw = NULL;

PhRect_t rect;

#define DESC_FONT "PrimaSans BT"

PhRect_t tsExtent;
FontName szFont;

long lAscender = 0;
int bDrawLine = 0;

int main(int argc, char *argv[])
{   PtArg_t args[4];
    PhPoint_t win_size, pntPOS, pntDIM;

    PtInit (NULL);

    if(argc > 1)
      bDrawLine = 1;

    //  set base pwndMain parms
    win_size.x = 400;
    win_size.y = 400;

    PtSetArg(&args[0],Pt_ARG_DIM, &win_size, 0);
    // window title = name  of program
    PtSetArg(&args[1],Pt_ARG_WINDOW_TITLE,
             (long)"Outline Test", 0);

    pwndMain = PtCreateWidget (PtWindow, Pt_NO_PARENT,
                               2, args);

    if(PfGenerateFontName(DESC_FONT, 0, 36,
                          szFont) == NULL)
      return(Pt_CONTINUE);

    PfExtentText(&tsExtent, NULL, szFont, "M", 0);

    lAscender = 200;

    pntPOS.y = 0;
    pntPOS.x = 0;
    pntDIM.x = 400;
    pntDIM.y = (lAscender + (-tsExtent.ul.y));
    PtSetArg(&args[0], Pt_ARG_POS, &pntPOS, 0);
    PtSetArg(&args[1], Pt_ARG_DIM, &pntDIM, 0);
    PtSetArg(&args[2], Pt_ARG_RAW_DRAW_F,
             fnDrawCanvas, 0L);
    pobjRaw = PtCreateWidget(PtRaw, pwndMain,
                             3, args);

    PtRealizeWidget(pwndMain);

    PtMainLoop ();

    return(EXIT_SUCCESS);
}

long s_lAdvanceX = 0L;
long s_lAdvanceY = 0L;

int * loops;

int fnDrawCanvas( PtWidget_t * ptsWidget,
                  PhTile_t * ptsDamage )
{   PgColor_t old;
    PhPoint_t * pnt = NULL;
    PHFONT_METRICS tsMetrics;
    long lNumContours = 0L;

    s_lAdvanceY = 0L;
    s_lAdvanceX = 0L;

    // find our canvas
    PtCalcCanvas(pobjRaw, &rect);

    PtSuperClassDraw( PtBasic, ptsWidget, ptsDamage );

    old = PgSetStrokeColor(Pg_BLACK);

    if((lNumContours =
           PfGetOutline(szFont, 'i', &tsMetrics,
                        &pnt, &loops)) == -1L)
      return(Pt_CONTINUE);

    if(tsMetrics.BearingX < 0)
      s_lAdvanceX += (-tsMetrics.BearingX +
                      0xFFFFL) >> 16;

    DrawOutline(pnt, lNumContours, &rect,
                lAscender);

    free(pnt);
    free(loops);

    s_lAdvanceX += (tsMetrics.Advance +
                    0xFFFFL) >> 16;

    if((lNumContours =
           PfGetOutline(szFont, 'o', &tsMetrics,
                        &pnt, &loops)) == -1L)
      return(Pt_CONTINUE);

    DrawOutline(pnt, lNumContours, &rect,
                lAscender);

    free(pnt);
    free(loops);

    s_lAdvanceX += (tsMetrics.Advance +
                    0xFFFFL) >> 16;

    if((lNumContours =
           PfGetOutline(szFont, 'u', &tsMetrics,
                        &pnt, &loops)) == -1L)
      return(Pt_CONTINUE);

    DrawOutline(pnt, lNumContours, &rect,
                lAscender);

    free(pnt);
    free(loops);

    s_lAdvanceX += (tsMetrics.Advance +
                    0xFFFFL) >> 16;

    if((lNumContours =
           PfGetOutline(szFont, 0x5EB3, &tsMetrics,
                        &pnt, &loops)) == -1L)
    {  printf("return failed\n");
       return(Pt_CONTINUE);
    }

    DrawOutline(pnt, lNumContours, &rect,
                lAscender);

    free(pnt);
    free(loops);

    s_lAdvanceX += (tsMetrics.Advance +
                    0xFFFFL) >> 16;

    if((lNumContours =
           PfGetOutline(szFont, 'A', &tsMetrics,
                        &pnt, &loops)) == -1L)
    {  printf("return failed\n");
       return(Pt_CONTINUE);
    }

    DrawOutline(pnt, lNumContours, &rect,
                lAscender);

    free(pnt);
    free(loops);

    PgSetStrokeColor(old);

    return( Pt_CONTINUE );
}

int DrawOutline( PhPoint_t * pnt, long ContourCount,
                 PhRect_t * rect, long lAscender)
{  unsigned long ul2 = 1L, ul1 = 0L;
   long ii = 0L, jj = 0L;
   PhPoint_t pos = { s_lAdvanceX + rect->ul.x,
                    (rect->lr.y - lAscender) };
   int offset = 0;
   PgColor_t old = PgSetFillColor(Pg_BLACK);

   for(ii = 0L; ii < ContourCount; ii++)
   {
      if(!bDrawLine)
      {  printf("PgDrawPolygon()\n");

         PgDrawPolygon(pnt + offset, loops[ii],
                       &pos, Pg_DRAW_STROKE);

         offset += loops[ii];
      }
      else if(bDrawLine)
           {  printf("PgDrawLine()\n");

              for(jj = 0; jj < loops[ii] - 1; jj++)
              {
                 PgDrawILine(pos.x + pnt[ul1].x,
                             pos.y + pnt[ul1].y,
                             pos.x + pnt[ul2].x,
                             pos.y + pnt[ul2].y);
                 ul1++, ul2++;
              }

              ul1++, ul2++;
           }
   }

   PgSetFillColor(old);

   return(0);
}

Classification:

Photon

PfGetOutline()

Safety:
Interrupt handler No
Signal handler No
Thread No

PfGetOutlineCx()

Safety:
Interrupt handler No
Signal handler No
Thread Yes

See also:

PfAttachCx(), PfDetach(), PfDetachCx(), PfGlyph(), PfGlyphCx(), PfGenerateFontName(), PfGenerateFontNameCx(), PhPoint_t

Fonts chapter of the Photon Programmer's Guide