logo
Литература_1 / photon_old

Исправление повреждений в случае пропорционального шрифта текста

При действии с пропорциональными шрифтами, иногда векторы одного глифа попадают на векторы другого. Это особенно видно, когда используются такие шрифты, как Nuptial BT. Чтобы исправлять повреждения в случае таких шрифтов, необходимо применять особые меры.

Для этого предназначена функция PfExtentTextCharPositions(). Вы можете использовать её, чтобы получить позицию после каждого символа, включая выноску по х следущего символа. Эта позиция – та, где Вы должны рисовать следующий символ. Если Вы используете флаг PF_CHAR_DRAW_POSITIONS, выноска по х следующего символа не добавляется, что полезно, когда Вы позиционируете курсор.

Например:

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

#include <Ap.h>

#include <Ph.h>

#include <Pt.h>

#include <errno.h>

PtWidget_t * pwndMain = NULL,

* pbtn = NULL,

* pobjRaw = NULL,

* pobjLabel = NULL;

char ** ppcData = NULL;

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

#define FALSE 0

#define __WIN_SIZE_X_ 1000

FontName szFont;

int main (int argc, char *argv[]) {

PtArg_t args[8];

PhPoint_t win_size, pntPOS, pntDIM;

short nArgs = 0;

char caTitle[50];

if (argc < 2) {

printf("Usage: pen text_string\n");

exit(EXIT_FAILURE);

}

PtInit (NULL);

ppcData = argv;

PfGenerateFontName("TextFont", 0, 9, szFont);

/* Установка базовых параметров pwndMain */

win_size.x = 800;

win_size.y = 600;

sprintf(caTitle, "Получение позиции пера");

PtSetArg(&args[0],Pt_ARG_DIM, &win_size, 0);

PtSetArg(&args[1],Pt_ARG_WINDOW_TITLE, caTitle, 0);

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

nArgs = 0;

pntDIM.x = 80;

pntDIM.y = 20;

PtSetArg(&args[nArgs], Pt_ARG_DIM, &pntDIM, 0);

nArgs++;

pntPOS.x = 100;

pntPOS.y = 10;

PtSetArg(&args[nArgs], Pt_ARG_POS, &pntPOS, 0);

nArgs++;

PtSetArg(&args[nArgs], Pt_ARG_TEXT_STRING, argv[1], NULL);

nArgs++;

pbtn = PtCreateWidget(PtButton, pwndMain, nArgs, args);

PtRealizeWidget(pbtn);

nArgs = 0;

pntDIM.x = 80;

pntDIM.y = 20;

PtSetArg(&args[nArgs], Pt_ARG_DIM, &pntDIM, 0);

nArgs++;

pntPOS.x = 100;

pntPOS.y = 600;

PtSetArg(&args[nArgs], Pt_ARG_POS, &pntPOS, 0);

nArgs++;

PtSetArg(&args[nArgs], Pt_ARG_TEXT_STRING, argv[1], NULL);

nArgs++;

PtSetArg(&args[nArgs], Pt_ARG_RESIZE_FLAGS,

Pt_RESIZE_XY_ALWAYS, Pt_RESIZE_XY_ALWAYS);

nArgs++;

PtSetArg(&args[nArgs], Pt_ARG_BORDER_WIDTH, 0L, 0L);

nArgs++;

PtSetArg(&args[nArgs], Pt_ARG_MARGIN_LEFT, 0L, 0L);

nArgs++;

PtSetArg(&args[nArgs], Pt_ARG_MARGIN_RIGHT, 0L, 0L);

nArgs++;

pobjLabel = PtCreateWidget(PtLabel, pwndMain, nArgs, args);

PtRealizeWidget(pobjLabel);

pntPOS.y = 100;

pntPOS.x = 75;

pntDIM.x = __WIN_SIZE_X_ - 75 - 10;

pntDIM.y = 300;

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);

(void) PtRealizeWidget(pwndMain);

PtMainLoop ();

return(0);

} // main()

int fnDrawCanvas( PtWidget_t * ptsWidget, PhTile_t * ptsDamage ) {

unsigned char const * pucFont = NULL;

int * piIndx = NULL;

int * piPos = NULL;

char ** argv = (char **)ppcData;

PhRect_t rect;

PhPoint_t pnt;

PhPoint_t tsPos = {0, 0};

PhRect_t tsExtent;

short n = 0;

char * pc = NULL;

PgColor_t old;

pucFont = szFont;

pc = argv[1];

piIndx = (int *)calloc(50, sizeof(int));

piPos = (int *)calloc(50, sizeof(int));

if (strlen(pc) < 4) {

printf("Выберите строку подлиннее, она должна быть не менее 4 символов\n");

exit(EXIT_SUCCESS);

}

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

/* Находим наш холст */

PtBasicWidgetCanvas(pobjRaw, &rect);

old = PgSetStrokeColor(Pg_BLACK);

PfExtentText(&tsExtent, &tsPos, pucFont, pc, strlen(pc));

PgSetFont(pucFont);

PgSetTextColor(Pg_BLACK);

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

/* Рисуем строку по символу за один раз */

PfExtentTextCharPositions(&tsExtent, &tsPos, pc, pucFont, piIndx, piPos,

strlen(pc), 0L, 0, 0, NULL);

pnt.x = 10 + rect.ul.x;

pnt.y = 200 + rect.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 < strlen(pc); n++) {

PgDrawText(pc + n, 1, &pnt, 0);

pnt.x = 10 + rect.ul.x + piPos[n];

printf("Один[%d]: %d\n", n, piPos[n]);

}

/* Конец рисования одного символа за раз */

/* Рисование строки, затем перекрытие отдельных символов

сверху - справа налево */

printf("Проверка перекрытия\n");

PfExtentText(&tsExtent, &tsPos, pucFont, pc, strlen(pc));

pnt.x = 10 + rect.ul.x;

pnt.y = 400 + rect.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);

PgSetFont(pucFont);

PgSetTextColor(Pg_BLACK);

PgDrawText(pc, strlen(pc), &pnt, 0);

for (n = strlen(pc) - 1; n >= 0; n--) {

switch(n) {

case 0:

pnt.x = 10 + rect.ul.x;

PgDrawText(pc + 0, strlen(pc), &pnt, 0);

break;

default:

piIndx[0] = n;

PfExtentTextCharPositions(&tsExtent, &tsPos, pc, pucFont, piIndx, piPos, 1, 0L, 0, 0, NULL);

printf("Позиция: %d\n", piPos[0]);

pnt.x = 10 + rect.ul.x + piPos[0];

PgDrawText(pc + n, strlen(pc) - n, &pnt, 0);

PgFlush();

sleep(1);

break;

}

}

/* Завершаем рисования строки, затем перекрываем отдельные символы

End draw string, then overlay individual characters

сверху – справа налево */

PgSetStrokeColor(old);

free(piPos);

free(piIndx);

return( Pt_CONTINUE );

} // функция fnDrawCanvas()

Yandex.RTB R-A-252273-3
Yandex.RTB R-A-252273-4