QNX Developer Support
![]() |
![]() |
![]() |
![]() |
PfExtent(), PfExtentCx()
Calculate the extent rectangle of a text string
Synopsis:
#include <photon/Pf.h>
int PfExtent( PhRect_t *extent,
PhPoint_t const *pos,
const char *font,
long adata,
long bdata,
const char *str,
int len,
int flags,
PhRect_t const *clip );
#include <font_api.h>
int PfExtentCx( struct _Pf_ctrl *context,
PhRect_t *extent,
PhPoint_t const *pos,
const char *font,
long adata,
long bdata,
const char *str,
int len,
int flags,
PhRect_t const *clip );
Arguments:
- context
- (PfExtentCx() only) A pointer to the font context to use, returned by PfAttachCx() or PfAttachDllCx().
- extent
- A pointer to a
PhRect_t
structure where the function stores the calculated extent.
The members are:
- ul.x
- the left bearing.
- lr.x
- the maximum x distance.
- ul.y
- the ascender.
- lr.y
- the descender.
The baseline of the font is at position y=0; the width of the string is:
lr.x - min(ul.x, 0) + 1
The height of the string is:
lr.y - ul.y + 1
- pos
- A pointer to a PhPoint_t structure that specifies an offset to apply to the extent. If pos is NULL, no offset is applied.
- font
- The base font, which you should create by calling PfGenerateFontName().
- adata
- The horizontal fractional point size, if you set PF_FRACTIONAL in the flags argument.
- bdata
- The vertical fractional point size, if you set PF_FRACTIONAL in the flags argument.
- str
- The string whose extent you want to calculate. The string is a UTF-8 multibyte one by default.
- len
- The length of the string, str, in bytes. If len is 0, the function uses strlen(str).
- flags
- Flags that affect the behavior of the function. You can set up to one of the following to indicate the format of
the string:
- PF_WIDE_CHARS -- the string is composed of 16-bit wide characters. If you set this flag, the function assumes that each character is represented by 2 bytes that conform to the ISO/IEC 10646-1 UCS-2 double-byte format.
- PF_WIDE_CHAR32 -- the string is composed of 32-bit
wide characters.
If you set this flag, the function assumes that each character is
represented by 4 bytes that conform to the ISO/IEC 10646-1 UCS-4
four-byte format.

Although this flag allows for 32-bit wide characters, the underlying font system currently supports only characters up to Unicode U+FFFE.
If you don't set either of the above, the function assumes that the string is composed of UTF-8 multibyte characters.
You can OR in any of these flags:
- PF_FRACTIONAL -- use a fractional 16.16 point size. If you set this flag, use the adata argument to specify the horizontal fractional point size, and bdata to specify the vertical fractional point size.
- PF_RECT -- make the function behave like PfExtentTextToRect(). If you set this flag, use the clip argument to specify the rectangle to extent within. If successful, the function returns the number of characters that fit within the rectangle.
- clip
- A pointer to a PhRect_t structure that's a suggested clipping rectangle for the font manager to abide by.
Library:
- PfExtent()
- ph
- PfExtentCx()
- font
Description:
These functions calculate the extent rectangle of a text string. The base font determines the ascender and descender values of the extent. The width depends on the string; the actual font used by characters within the string may differ from this base font (as specified in the fontext and fontmap files).
The difference between PfExtent() and PfExtentCx() is that PfExtentCx() lets you specify the font context to use.
If metrics for the base font have been loaded locally (see PfLoadMetrics()), the extent is calculated internally; otherwise, a request is sent to the font server.
The generic design of these routines allows for future expansion.
Returns:
If you set PF_RECT in the flags argument, PfExtent() and PfExtentCx() return the number of characters that fit within the rectangle specified by clip, or -1 if an error occurred.
If you don't set PF_RECT in the flags argument, these functions return 0 on success, or -1 if an error occurred.
Examples:
PfExtentCx():
/* This example demonstrates a straight forward method of
* using fractional processing to fit text within a given
* canvas size, without using floating point. Fractional
* processing is performed using a 16.16 integer format, for
* example, 1 point size is represented as 1 << 16. Therefore,
* 0.1 of a point size would be (1 << 16) / 10. This example
* could be further enhanced by using 0.1 of a point size to
* further fine tune the fitting of text within the canvas size.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <Ph.h>
#include <Pt.h>
#include <errno.h>
/* Define the image modules. */
#define PX_IMAGE_MODULES
#define PX_BMP_SUPPORT
#include <photon/PxImage.h>
#define NUM_LINES 4
char const * text[] = { "Hello Bob",
"How are you doing?",
"I hope you have a good day.",
"Bye for now." };
void raw_draw(PtWidget_t * widget, void * data, PhTile_t * damage);
void draw_cb(void * ctx, const pf_point_t * pnt, const FontRender * render);
int main(int argc, char *argv[])
{
if(PtInit (NULL) == 0);
{ struct _Pf_ctrl * pf;
if((pf = PfAttachCx("/dev/phfont32", 320000)) != NULL)
{ FontName font;
if(PfGenerateFontNameCx(pf, "Swis721 BT", 0, 14, font) != NULL)
{ short nArgs = 0;
PhDim_t win_size;
PtArg_t tsArg[7];
PtWidget_t * wnd;
win_size.w = 450;
win_size.h = 450;
nArgs = 0;
PtSetArg(&tsArg[nArgs++],Pt_ARG_DIM, &win_size, 0L);
PtSetArg(&tsArg[nArgs++],Pt_ARG_WINDOW_TITLE, "fractional", 0L);
if((wnd = PtCreateWidget (PtWindow, NULL, nArgs, tsArg)) != NULL)
{ PhRect_t canvas;
PhDim_t dim;
long flags;
PtWidget_t * raw;
PtExtentWidget(wnd);
PtCalcCanvas(wnd, &canvas);
nArgs = 0;
dim.w = canvas.lr.x - canvas.ul.x;
dim.h = canvas.lr.y - canvas.ul.y;
PtSetArg(&tsArg[nArgs++], Pt_ARG_DIM, &dim, 0L);
PtSetArg(&tsArg[nArgs++], Pt_ARG_RAW_DRAW_F, raw_draw, 0L);
PtSetArg(&tsArg[nArgs++], Pt_ARG_FILL_COLOR, Pg_WHITE, 0L);
flags = Pt_RIGHT_ANCHORED_RIGHT | Pt_LEFT_ANCHORED_LEFT
| Pt_TOP_ANCHORED_TOP | Pt_BOTTOM_ANCHORED_BOTTOM;
PtSetArg(&tsArg[nArgs++], Pt_ARG_ANCHOR_FLAGS, flags, flags);
PtSetArg(&tsArg[nArgs++], Pt_ARG_POINTER, pf, 0L);
PtSetArg(&tsArg[nArgs++], Pt_ARG_USER_DATA, &font, sizeof(font));
if((raw = PtCreateWidget(PtRaw, wnd, nArgs, tsArg)) != NULL)
{ PtRealizeWidget(wnd);
PtMainLoop ();
}
}
}
}
}
return(0);
}
void raw_draw(PtWidget_t * widget, void * data, PhTile_t * damage)
{ pf_point_t pos = {0, 0};
struct _Pf_ctrl * pf;
char const * font;
PgColor_t old1, old2;
PhRect_t clip;
PhDim_t dim;
int i = 0;
PtGetResource(widget, Pt_ARG_POINTER, &pf, 0L);
PtGetResource(widget, Pt_ARG_USER_DATA, &font, 0L);
PtSuperClassDraw( PtBasic, widget, damage );
PtCalcCanvas(widget, &clip);
PtClipAdd(widget, &clip);
dim.w = clip.lr.x - clip.ul.x + 1;
dim.h = clip.lr.y - clip.ul.y + 1;
PgSetFont(font);
old1 = PgSetTextColor(Pg_BLACK);
old2 = PgSetFillColor(Pg_WHITE);
do
{ pf_rect_t extent;
int xsize;
int ysize;
int xtoggle;
int ytoggle;
xsize = 12 << 16;
ysize = 12 << 16;
pos.x = clip.ul.x;
xtoggle = 0;
ytoggle = 0;
do
{
if(PfExtentCx(pf, &extent, NULL, font, xsize, ysize, text[i],
strlen(text[i]), PF_FRACTIONAL, NULL) == 0)
{ int ok_w = 0, ok_h = 0, diff;
if((extent.lr.x - extent.ul.x + 1) <= dim.w)
{ diff = (dim.w - (extent.lr.x - extent.ul.x + 1)) << 16;
if(diff > 65536)
{ xsize += 65536;
xtoggle++;
if((xtoggle >= 2) && (diff < (65536 * 2)))
ok_w = 1;
}
else
ok_w = 1;
}
else
{ xsize -= 65536;
xtoggle++;
if((xtoggle >= 2) && (diff < (65536 * 2)))
ok_w = 1;
}
if((extent.lr.y - extent.ul.y + 1) <= (dim.h / NUM_LINES))
{ diff = ((dim.h / NUM_LINES) -
(extent.lr.y - extent.ul.y + 1)) << 16;
if(diff > 65536)
{ ysize += 65536;
ytoggle++;
if((ytoggle >= 2) && (diff < (65536 * 2)))
ok_h = 1;
}
else
ok_h = 1;
}
else
{ ysize -= 65536;
ytoggle++;
if((ytoggle >= 2) && (diff < (65536 * 2)))
ok_h = 1;
}
if(ok_w && ok_h)
{ if(PfRenderCx(pf, &extent, font, xsize, ysize, text[i],
strlen(text[i]), PF_FRACTIONAL, &pos, NULL, draw_cb) == -1)
{ perror("");
printf("errno == %d\n", errno);
}
pos.y += extent.lr.y - extent.ul.y + 1;
break;
}
}
}
while(1);
i++;
}
while(i < NUM_LINES);
PgSetTextColor(old1);
PgSetFillColor(old2);
PtClipRemove();
return;
}
void draw_cb(void * ctx, const pf_point_t * pnt, const FontRender * render)
{ PhImage_t tsImage;
PgColor_t palette[2] = { Pg_WHITE, Pg_BLACK };
memset(&tsImage, 0x00, sizeof(PhImage_t));
tsImage.size.w = render->size.x;
tsImage.size.h = render->size.y;
tsImage.bpl = render->bpl;
tsImage.image = render->bmptr;
tsImage.palette = palette;
tsImage.colors = 2;
if(render->bpp == 1)
{ tsImage.palette = NULL;
tsImage.type = Pg_BITMAP_BACKFILL;
}
else if(render->bpp == 4)
{ palette[0] = Pg_WHITE;
palette[1] = Pg_BLACK;
tsImage.type = Pg_IMAGE_GRADIENT_NIBBLE;
}
else if(render->bpp == 8)
{ if(render->flags & FONTRENDER_RGB_PIXMAP)
{ tsImage.palette = NULL;
tsImage.type = Pg_IMAGE_DIRECT_888;
}
else
{ palette[0] = Pg_WHITE;
palette[1] = Pg_BLACK;
tsImage.type = Pg_IMAGE_GRADIENT_BYTE;
}
}
if(PgDrawPhImagemx(pnt, &tsImage, 0x00) == -1)
{ printf("Ouch!!\n");
}
PgFFlush(1);
return;
}
Classification:
Photon
| Safety: | |
|---|---|
| Interrupt handler | No |
| Signal handler | No |
| Thread | No |
See also:
PfAttach(), PfAttachCx(), PfDetach(), PfDetachCx(), PfExtentComponents(), PfExtentComponentsCx(), PfExtentFractTextCharPositions(), PfExtentText(), PfExtentTextCharPositions(), PfExtentTextCharPositionsCx(), PfExtentTextToRect(), PfExtentWideText(), PfFractionalExtentText(), PfGenerateFontName(), PfGenerateFontNameCx(), PfLoadMetrics(), PfLoadMetricsCx(), PhPoint_t, PhRect_t
![]() |
![]() |
![]() |
![]() |

![[Previous]](../prev.gif)
![[Contents]](../contents.gif)
![[Index]](../keyword_index.gif)
![[Next]](../next.gif)
