Calculate individual character positions
#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 );
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.
This function assumes each character is represented by 2 bytes that conform to the ISO/IEC 10646-1 UCS-2 double-byte format. |
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:
strlen( psz ) / wstrlen( psz )
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.
PfExtentTextCharPositions():
PfExtentTextCharPositionsCx():
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.
Photon
Safety: | |
---|---|
Interrupt handler | No |
Signal handler | No |
Thread | No |
Safety: | |
---|---|
Interrupt handler | No |
Signal handler | No |
Thread | Yes |
PfExtent(), PfExtentCx(), PfExtentText(), PfExtentTextCharPositionsCx(), PfExtentTextToRect(), PfExtentFractTextCharPositions(), PfFractionalExtentText(), PfGenerateFontName(), PfGenerateFontNameCx(), PhPoint_t, PhRect_t
Fonts chapter of the Photon Programmer's Guide