Get individual point information for a glyph outline
#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 );
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)
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:
Your application must free the memory pointed to by pptsPoints and ppiLoops. |
PfGetOutlineCx() is similar to PfGetOutline(), but lets you specify the font context.
The number of contours that make up the outline, or -1 if an error occurred (errno is set).
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); }
Photon
Safety: | |
---|---|
Interrupt handler | No |
Signal handler | No |
Thread | No |
Safety: | |
---|---|
Interrupt handler | No |
Signal handler | No |
Thread | Yes |
PfAttachCx(), PfDetach(), PfDetachCx(), PfGlyph(), PfGlyphCx(), PfGenerateFontName(), PfGenerateFontNameCx(), PhPoint_t
Fonts chapter of the Photon Programmer's Guide