Руководство программиста в Photon (1037671), страница 55
Текст из файла (страница 55)
PtArg_t args[4];
PhPoint_t win_size, pntPOS, pntDIM;
short nArgs = 0;
if ((pmbGB = calloc(BUFFER_SIZE, sizeof(char))) = = NULL) return(EXIT_FAILURE);
PtInit (NULL);
if (argc > 1) {
if(PfGenerateFontName(argv[1], 0, 9, szFont) = = NULL)
PfGenerateFontName("TextFont", 0, 9, szFont);
}
else PfGenerateFontName("TextFont", 0, 9, szFont);
if ((ptsTrans = PxTranslateSet(NULL, "GB2312-80")) = = NULL) return(EXIT_FAILURE);
if (PxTranslateToUTF(ptsTrans, pcGB, 4, &iTemp1, pmbGB, BUFFER_SIZE, &iTemp2) = = -1)
printf("Не получается перевести из GB в UTF.\n");
if(argc > 2) pcText = pmbGB;
/* Установка базовых параметров pwndMain */
win_size.x = 450;
win_size.y = 450;
PtSetArg(&args[0],Pt_ARG_DIM, &win_size, 0);
PtSetArg(&args[1],Pt_ARG_WINDOW_TITLE, "PfExtentTextToRect", 0);
pwndMain = PtCreateWidget (PtWindow, Pt_NO_PARENT, 2, args);
nArgs = 0;
pntPOS.x = 100;
pntPOS.y = 10;
PtSetArg(&args[nArgs], Pt_ARG_POS, &pntPOS, 0);
nArgs++;
PtSetArg(&args[nArgs], Pt_ARG_TEXT_STRING, pcText, NULL);
nArgs++;
PtSetArg(&args[nArgs], Pt_ARG_TEXT_FONT, szFont, NULL);
nArgs++;
pbtn = PtCreateWidget(PtButton, pwndMain, nArgs, args);
PtRealizeWidget(pbtn);
pntPOS.y = 100;
pntPOS.x = 75;
pntDIM.x = 300;
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);
PtRealizeWidget(pwndMain);
PtMainLoop ();
return(0);
} // main()
#define ASCENDER tsExtent.ul.y
#define DESCENDER tsExtent.lr.y
int fnDrawCanvas( PtWidget_t * ptsWidget, PhTile_t * ptsDamage ) {
PhRect_t tsExtentClip;
PhRect_t rect;
PhPoint_t pnt;
PhRect_t tsExtent;
PgColor_t old;
PhPoint_t pnt2;
PhPoint_t tsPos = {0, 0};
int iRet = 0;
int iBytes = 0;
/* Находим наш холст */
PtBasicWidgetCanvas(pobjRaw, &rect);
old = PgSetStrokeColor(Pg_BLACK);
PfExtentText(&tsExtent, &tsPos, szFont, pcText, strlen(pcText));
/* Рисуем текст */
pnt.x = 10 + rect.ul.x;
pnt.y = 100 + rect.ul.y;
PgSetFont(szFont);
PgSetTextColor(Pg_BLACK);
PgDrawText(pcText, strlen(pcText), &pnt, 0);
pnt.x -= 10;
pnt2.x = pnt.x + tsExtent.lr.x + 20;
pnt2.y = pnt.y;
PgSetStrokeColor(Pg_BLUE);
PgDrawLine(&pnt, &pnt2);
pnt.x = 10 + rect.ul.x;
pnt.y = 100 + rect.ul.y;
PgSetStrokeColor(Pg_RED);
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);
if ((iRet = PfExtentTextToRect(&tsExtentClip, szFont, &tsExtent, pcText, strlen(pcText))) = = -1)
printf("PfExtentTextToRect неудача 1.\n");
else {
printf("lrx = = %d, %d символов в строке.\n", tsExtent.lr.x, utf8strlen(pcText, &iBytes));
printf("PfExtentTextToRect lrx = = %d, %d символов разместятся в обрезке %d.\n",
tsExtentClip.lr.x, iRet, tsExtent.lr.x);
}
tsExtent.lr.x /= 2;
if ((iRet = PfExtentTextToRect(&tsExtentClip, szFont, &tsExtent, pcText, strlen(pcText))) = = -1)
printf("PfExtentTextToRect неудача 2.\n");
else {
printf("lrx == %d, %d символов в строке.\n", tsExtent.lr.x, utf8strlen(pcText, &iBytes));
printf("PfExtentTextToRect lrx == %d, %d символов разместятся в обрезке %d.\n",
tsExtentClip.lr.x, iRet, tsExtent.lr.x);
}
pnt.x = 10 + rect.ul.x;
pnt.y = 150 + rect.ul.y;
PgDrawText(pcText, iRet, &pnt, 0);
PgDrawIRect(tsExtentClip.ul.x + pnt.x,
tsExtentClip.ul.y + pnt.y,
(tsExtentClip.lr.x - min(tsExtentClip.ul.x, 0) + 1) + pnt.x,
tsExtentClip.lr.y + pnt.y,
Pg_DRAW_STROKE);
tsExtent.lr.x /= 2;
if ((iRet = PfExtentTextToRect(&tsExtentClip, szFont, &tsExtent, pcText, strlen(pcText))) = = -1)
printf("PfExtentTextToRect неудача 3.\n");
else {
printf("lrx == %d, %d символов в строке.\n", tsExtent.lr.x, utf8strlen(pcText, &iBytes));
printf("PfExtentTextToRect lrx == %d, %d символов разместятся в обрезке %d.\n",
tsExtentClip.lr.x, iRet, tsExtent.lr.x);
}
pnt.x = 10 + rect.ul.x;
pnt.y = 200 + rect.ul.y;
PgDrawText(pcText, iRet, &pnt, 0);
PgDrawIRect(tsExtentClip.ul.x + pnt.x, tsExtentClip.ul.y + pnt.y,
(tsExtentClip.lr.x - min(tsExtentClip.ul.x, 0) + 1) + pnt.x,
tsExtentClip.lr.y + pnt.y,
Pg_DRAW_STROKE);
PgSetStrokeColor(old);
return( Pt_CONTINUE );
}
Исправление повреждений в случае пропорционального шрифта текста
При действии с пропорциональными шрифтами, иногда векторы одного глифа попадают на векторы другого. Это особенно видно, когда используются такие шрифты, как 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()
Глава 20. Печать
Эта глава включает:
-
Контекст печати
-
Запуск процесса печати
-
Печать требуемых виджетов
-
Приостановка и возобновление процесса печати
-
Прекращение процесса печати
-
Освобождение контекста печати
-
Пример
В Photon'е печать и прорисовка на экране – это одно и то же: разница зависит от контекста рисования – структуры данных, определяющих куда проходит поток рисования (т.е. события рисования):
-
по умолчанию, на графический драйвер для рисования на экране
или
-
на контекст памяти (или МС – memory context) для размещения в памяти для дальнейшего использования
или
-
на контекст печати (или PC – printing context) для печати. См. раздел "Контекст печати" ниже.
Чтобы напечатать в Photon'е, необходимо:
-
Вызвав функцию PpCreatePC(), создать контекст печати
-
Выполнить установку контекста печати – либо автоматически через виджет PtPrintSel, либо программно с помощью функции PpSetPC().
-
Инициализировать процесс печати, вызвав функцию PpStartJob().
-
В любой момент после того, как функция PpStartJob() была вызвана, сделать контекст печати "активным", вызвав функцию PpContinueJob(). Когда контекст печати активен, всё, что рисуется через вызовы PpPrintWidget() или Pg*, включая виджеты, направляется в файл, открытый контекстом печати при вызове функции PpStartJob().
-
Вставить, если необходимо, принудительный обрыв страницы, вызвав функцию PpPrintNewPage().
-
Контекст печати можно сделать неактивным без прерывания текущего процесса печати, вызвав функцию PpSuspendJob(), или вызвав функцию PpContinueJob() с другим контекстом печати. Чтобы возобновить процесс печати с того места, где он был остановлен, необходимо вызвать функцию PpContinueJob().
-
Завершить процесс печати путём вызова функции PpEndJob().
-
Когда Вашему приложению больше не понадобится что-либо печатать в дальнейшем, вызвать функцию PpReleasePC(), чтобы освободить контекст печати.
Контекст печати
Контекст печати представляет из себя структуру типа PpContext_t, члены которой управляют тем, как выполняется печать. Информация о том, что находится в контексте печати, см. в "Справочнике библиотечных функций Photon'а".
Никогда не обращайтесь напрямую к членам структуры PpPrintContext_t; используйте для извлечения членов функцию PpGetPC() и функцию PpSetPC() для их изменения.
Создание контекста печати
Первым шагом при выполнении печати в Photon'е является создание контекста печати с помощью функции PpCreatePC():