Portable Document Format


Portable Document Format

A Portable Document Format is composed of objects. Each object in a PDF document has an ID. The ID of each object is an integer value as shown in the figure. The most popular object types are:
  • Catalog
  • Pages
  • Page
  • Font
  • FontDescriptor

El formato de documento portables está compuesto de objetos. Cada objeto en un documento de PDF tiene un ID. El ID de cada objeto es un número entero como se muestra en la figura de abajo. Los tipos de objetos más populares son:
  • Catalog
  • Pages
  • Page
  • Font
  • FontDescriptor

Object

Tip
The object begins with two integer values followed of the keyword obj. The first integer value is the ID of the object; the next integer (displayed in red) is the generation number which allows keeping track of the changes of the document. In this case, we will use a value of zero for the generation number. Inside each object there is a value and an optional data stream. To end an object the keyword endobjis used. Wintempla encapsulates the PDF object in the Pdf::Object class, and the value of the object in the Pdf::Value class.
Un objeto comienza con dos valores enteros seguidos de la palabra clave obj. El primer valor entero es el ID del objeto; el siguiente entero (mostrado en rojo) es el número de generación el cual permite mantener seguimiento de los cambios en el documento. En este caso, usaremos un valor de cero para el número de generación. Dentro de cada objeto hay un valor (value) y una fuente de datos opcional (data stream). Para terminar un objeto se usa la palabra clave endobj. Wintempla encapsula el objeto de PDF en la clase Pdf::Object, y el valor del objeto en la clase Pdf::Value.

ObjectDetail

Catalog

The main object in a PDF document is the Catalog. Basically, this node indicates how many pages the document has using the /Count keyword as shown below. In this case, the document has one page. The /Pages element in the Catalog object indicates that object 2 has information about the pages in the document. The letter R indicates that the number 2 is a reference to the object 2. In the same figure, the third object is used to store information about the author of the document, creation date, etc.
El objeto principal en un documento de PDF es el Catalog. Básicamente, este nodo indica cuantas páginas tiene el documento usando la palabra clave /Count como se muestra debajo. En este caso, el documento tiene una página. El elemento /Pages en el objeto de Catalog indica que el objeto 2 tiene información acerca de las páginas en el documento. La letra R indica que el número 2 es una referencia al objeto 2. En la misma figura, el tercer objeto es usado para almacenar información acerca del autor del documento, la fecha de creación, etc.

Structure

Pages

The figure below shows the object number 2 which is an object of type /Pages. This object has a /Kids element to indicate the ID of the object with information about the page. In this case, the object number 4 is an object of type /Page and the contents of the page is indicated by the /Contents element. The /Contents element indicates the number of the object with the content of the page, in this case object number 5 has the content of the page.
La figura de abajo muestra el objeto número 2 el cual es un objeto del tipo /Pages. Este objeto tiene un elemento /Kids para indicar el ID del objeto con información acerca de la página. En este caso, el objeto número 4 es un objeto del tipo /Page y el contenido de la página es indicado por el elemento /Contents. El elemento /Contents indica el número del objeto con el contenido de la página, en este caso el objeto número 5 tiene el contenido de la página.

Pages

Cross-Reference Table

This table is located after the last object in the PDF file as shown below. The cross-reference table is displayed in yellow and begins with the xref keyword. The figure illustrates a complete PDF document. Comments in a PDF document start with a percent sign, thus, at the beginning of the document the PDF version must be indicated as a comment. The second line is another comment that includes characters with a decimal value bigger than 128 (the first bit is one), this is used to indicate to email tools that the document must be transferred as binary. The document ends with %%EOF and before this, there is a number to indicate an offset to the beginning of the cross reference table. In this case, the number 1073 indicates that the cross reference table is located 1073 bytes from the beginning of the file. The cross-reference table has offsets to each of the objects in the document. For instance, object 1 is located at 540 bytes from the beginning of the document; the letter n at end indicates that this object is in used. The /Size element indicates that there are six objects including the cross-reference table. The /Info element indicates the object number 3 has information about the document. The keyword trailer indicates the end of the offset table. In PDF-1.6 and later, the cross-reference table may be stored in a stream at the beginning of the document.
Esta tabla está ubicada después del último objeto en el archivo de PDF como se muestra debajo. La tabla de referencia cruzada es mostrada en amarillo y comienza con la palabra clave xref. La figura ilustra un documento completo de PDF. Los comentarios en un documento de PDF comienzan con el signo de porcentaje, así, al principio del documento la versión de PDF debe ser indicada como un comentario. La segunda línea es otro comentario que incluye caracteres con un valor decimal mayor a 128 (el primer bit es uno), este es usado para indicar a las herramientas de correo electrónico que el documento debe ser transferido como binario. El documento termina con %%EOF y antes de este, hay un número 1073 para indicar que la tabla de referencia cruzada está ubicada 1073 bytes desde el inicio del archivo. La tabla de referencia cruzada tiene offsets a cada uno de los objetos en el documento. Por ejemplo, el objeto 1 está localizado a 540 bytes desde el inicio del documento; la letra n al final indica que le objeto está en uso. El elemento /Size indica que hay seis objetos incluyendo la tabla de referencia cruzada. El elemento /Info indica que el objeto número 3 tiene información acerca del documento. La palabra clave trailer indica el final de la tabla de los offsets. En PDF-1.6 y posterior, la tabla de referencias cruzadas puede estar almacenada en una stream al principio del documento.

Complete

Tip
Wintempla encapsulates a PDF document in the class Pdf::Document, you are invited to examine this class to learn more about how to create PDF documents. The table includes some of the most frequently used command to draw in a PDF document. These are very similar to the GDI commands of Microsoft Windows.
Wintempla encapsula un documento PDF en la clase Pdf::Document, usted está invitado a examinar esta clase para aprender más acerca de cómo crear documento de PDF. La tabla incluye algunos de los comandos más frecuentes para dibujar en un documento de PDF. Estos son muy semejantes a los comandos de GDI de Microsoft Windows.

PDF     Description  
bclosepath, fill,and stroke path.
Bfill and stroke path.
b*closepath, eofill,and stroke path.
B*eofill and stroke path.
BIbegin image.
BMCbegin marked content.
BTbegin text object.
BXbegin section allowing undefined operators.
ccurveto.
cmconcat. Concatenates the matrix to the current transform.
cssetcolorspace for fill.
CSsetcolorspace for stroke.
dsetdash.
Doexecute the named XObject.
DPmark a place in the content stream, with a dictionary.
EI end image.
EMCend marked content.
ETend text object.
EXend section that allows undefined operators.
ffill path.
f*eofill Even/odd fill path.
gsetgray (fill).
Gsetgray (stroke).
gsset parameters in the extended graphics state.
hclosepath.
isetflat.
IDbegin image data.
jsetlinejoin.
Jsetlinecap.
ksetcmykcolor (fill).
Ksetcmykcolor (stroke).
llineto.
mmoveto.
Msetmiterlimit.
nend path without fill or stroke.
qsave graphics state.
Qrestore graphics state.
rerectangle.
rgsetrgbcolor (fill).
RGsetrgbcolor (stroke).
sclosepath and stroke path.
Sstroke path.
scsetcolor (fill).
SCsetcolor (stroke).
shshfill (shaded fill).
Tcset character spacing.
Tdmove text current point.
TDmove text current point and set leading.
Tfset font name and size.
Tjshow text.
TJshow text, allowing individual character positioning.
TLset leading.
Tmset text matrix.
Trset text rendering mode.
Tsset super/subscripting text rise.
Twset word spacing.
Tzset horizontal scaling.
T*move to start of next line.
vcurveto.
wsetlinewidth.
Wclip.
ycurveto.

Coordinate System

The positive x axis extends horizontally to the right and the positive y axis vertically upward, as in standard mathematical practice (subject to alteration by the Rotate entry in the page dictionary).
El eje positivo x se extiende horizontalmente hacia la derecha y el eje positivo y se extiende verticalmente hacia arriba, como se usa en las matemáticas (sujeto a cambios por el comando Rotate de la página de diccionario),

Problem 1
Create Wintempla application called AdobeLine to create a PDF file with a line. You may search over the Internet for more information about the PDF format. For instance the Line Dash Pattern of [] 0 is used for a solid line.
Cree una aplicación de Wintempla llamada AdobeLine para crear un archivo de PDF con una línea. Usted puede buscar en la Internet más información del formato PDF. Por ejemplo el Line Dash Pattern of [] 0 es usado para líneas sólidas.

LineDashPattern

AdobeLine.cpp
...

void AdobeLine::Window_Open(Win::Event& e)
{
     Pdf::Document doc;
     doc.page.resize(1);
     //________________________________ Lines Setup
     doc.page[0].Concat(1, 0, 0, 1, 0, 0);
     doc.page[0].LineJoinStyleMiter();
     doc.page[0].LineCapStyle(0);
     doc.page[0].LineWidth(1.0);
     doc.page[0].MiterLimit(2.613125929752795);
     doc.page[0].LineDashPattern(L"[] 0");
     doc.page[0].StrokeColor(RGB(100, 0, 0));
     //_______________________________ Set line points
     doc.page[0].Line(125.6, 667.6, 365.2, 667.6);
     //_______________________________ Draw the line
     doc.page[0].CloseAndStrokePath();
     //
     if (doc.Save(L"AdobeLine.pdf") == false)
     {
          this->MessageBox(L"Error creating PDF", L"Wintempla Adobe Line", MB_OK | MB_ICONERROR);
     }
     this->Destroy();
}

AdobeLineRun

Line

To draw a line in a PDF document, you can use MoveTo to indicate the first point of the line, and LineTo to specify the second point of a line. Wintempla provides Line that internally calls MoveTo and LineTo. Note the neither MoveTo nor LineTo draw the line. To draw the line, you must use StrokePath.
Para dibujar una línea en un documento de PDF, usted puede usar MoveTo para indicar el primer punto de la línea, y LineTo para especificar el segundo punto de una línea. Wintempla proporciona Line que internamente llama MoveTo y LineTo. Observe que ni MoveTo ni LineTo dibujan la línea. Para dibujar la línea usted debe usar StrokePath.

Stroking and Filling functions

These functions draw the border of a path once several lines have been used to define this path. These functions can also be used to fill a path.
  • ClosePath: It closes a path. To draw the border call StrokePath. To fill the path call FillPath
  • CloseAndStrokePath: It closes and draws the border of the path
  • CloseFillAndStrokePath: It closes, draws the border and fill the path

Estas funciones permiten dibujar el borde de un path una vez varias líneas se han usado para describir este path. Estas funciones también pueden usarse para rellenar un path.
  • ClosePath: Cierre el path. Para dibujar el borde use StrokePath. Para rellenar el path use FillPath
  • CloseAndStrokePath: Cierra y dibuja el borde del path
  • CloseFillAndStrokePath: Cierra, dibuja el borde y rellena el path

Rectangle

To draw a rectangle (or other polygon) in a PDF document, you can use MoveTo to indicate the first point of the rectangle, and call LineTo three times to specify the other three points. Finally, to draw the rectangle you may use:
  • CloseAndStrokePath, or
  • CloseFillAndStrokePath, or
  • ClosePath followed of FillPath
Note that it is not possible to fill a path that is not closed.
Para dibujar un rectángulo (u otro polígono) en un documento de PDF, usted puede usar MoveTo para indicar el primer punto del rectángulo, y llamar LineTo tres veces para especificar los otros tres puntos. Finalmente, para dibujar el rectángulo usted puede usar:
  • CloseAndStrokePath, o
  • CloseFillAndStrokePath, o
  • ClosePath seguida de FillPath
Note que no es posible rellenar un path que no está cerrado.

Path

A path is a set of consecutive lines. To close a path, you can use the page.ClosePath command. To draw the path, you can use CloseAndStrokePath. In a PDF document, Stroke means draw the border of an object o draw the set of lines of a path.
Una path es un conjunto de líneas consecutivas. Para cerrar un path, usted puede usar el comando page.ClosePath. Para dibujar el path, usted puede usar CloseAndStrokePath. En un documento de PDF, Stroke quiere decir dibujar el borde un objeto o dibujar las líneas de un path.

Problem 2
Create Wintempla application called AdobeSpider to create a PDF file with the pattern shown. Use the page.GetWidth() and page.GetHeight() methods to know the size of the page.
Cree una aplicación de Wintempla llamada AdobeSpider para crear un archivo de PDF con el patrón mostrado. Use los métodos page.GetWidth() and page.GetHeight() para conocer el tamaño de la página.

AdobeSpiderRun

AdobeSpider.cpp
. . .
void AdobeSpider::Window_Open(Win::Event& e)
{
     Pdf::Document doc;
     doc.page.resize(1);
     //________________________________ Lines Setup
     doc.page[0].Concat(1, 0, 0, 1, 0, 0);
     doc.page[0].LineJoinStyleMiter();
     doc.page[0].LineCapStyle(0);
     doc.page[0].LineWidth(1.0);
     doc.page[0].MiterLimit(2.613125929752795);
     doc.page[0].LineDashPattern(L"[] 0");
     doc.page[0].StrokeColor(RGB(0, 0, 255));
     //_______________________________ Set line points
     const int lineCount = 50;
     const double deltaX = doc.page[0].GetWidth()/(double)lineCount;
     const double deltaY = doc.page[0].GetHeight()/(double)lineCount;
     . . .
}


Problem 3
Create Wintempla application called AdobeSweden to create a PDF file with the flag of Sweden.
Cree una aplicación de Wintempla llamada AdobeSweden para crear un archivo PDF con la bandera de Suecia.

AdobeSweden.cpp
void AdobeSweden::Window_Open(Win::Event& e)
{
     Pdf::Document doc;
     doc.page.resize(1);
     //
     doc.page[0].PageSetup(PDF_PAPER_SIZE_LETTER, false);
     const double pageWidth = doc.page[0].GetWidth();
     const double pageHeight = doc.page[0].GetHeight();
     //_______________________________ Blue Rectangle
     . . .
     //_______________________________ Yellow Rectangle 1
     . . .
     //_______________________________ Yellow Rectangle 2
     . . .


AdobeSwedenRun

CurveTo

Append a cubic Bezier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using (x1, y1) and (x2, y2) as the Bezier control points.
Le agrega una curva cúbica Bezier al path corriente. La curva se extenderá desde el punto corriente al punto (x3, y3), usando (x1, y1) y (x2, y2) como los puntos de control del Bezier.

Bezier

In PDF, curves including Circles and Ellipses are draw using CurveTo. First, you must call MoveTo to set the initial point of the curve, second a successive sequence of calls to CurveTo must be performed. CurveTo does not draw the curve; to draw the curve you must call: CloseAndStrokePath, CloseFillAndStrokePath, ClosePath followed of FillPath, etc. To draw ellipses and circles, Wintempla provide: page.Circle and page.Ellipse.
In PDF, las curvas incluyendo círculos y elipses son dibujadas usando CurveTo. Primero, usted debe llamar MoveTo para fijar el punto inicial de la curva, segundo una secuencia de llamadas sucesivas a CurveTo se debe realizar. CurveTo no dibuja la curva; para dibujar la curva usted debe usar:CloseAndStrokePath, CloseFillAndStrokePath, ClosePath seguido de FillPath, etc. Para dibujar elipses y círculos, Wintempla proporciona: page.Circle y page.Ellipse.

Problem 4
Create Wintempla application called AdobeTarget to create a PDF file with a target drawing.
Cree una aplicación de Wintempla llamada AdobeTarget para crear un archivo PDF con un dibujo de un tiro al blanco.

AdobeTargetRun

Text

In PDF, drawing text requires a perfect knowledge of the size of each character for the font type used in the document. This information is typically called Text Metrics or Outline Text Metrics. Wintempla provides the Sys::PdfFont class to get these metrics; for instance font.GetTextWidth can be used to compute the width of any text. Some functions to manipulate text are:
  • BeginText to initiate drawing text
  • EndText to end drawing text
  • MoveText to place the text at a specific position
  • Font to set the font name and size
  • ShowText to draw the actual text

En PDF, el dibujo de texto requiere un perfecto conocimiento del tamaño de cada carácter de la fuente usada en el documento. Esta información es típicamente llamada Text Metrics o Outline Text Metrics. Wintempla proporciona la clase Sys::PdfFont para obtener estas métricas; por ejemplo font.GetTextWidth() puede ser usada para calcular el ancho de cualquier texto. Algunas funciones para manipular texto son:
  • BeginText para iniciar el dibujo de texto
  • EndText para terminar el dibujo de texto
  • MoveText para colocar el texto en una posición específica
  • Font para fijar la fuente y su tamaño
  • ShowText para dibujar el texto

Problem 5
Create Wintempla application called AdobeHello to create a PDF file with the message shown.
Cree una aplicación de Wintempla llamada AdobeHello para crear un archivo de PDF con el mensaje mostrado.

AdobeHello.cpp
. . .

void AdobeHello::Window_Open(Win::Event& e)
{
     Pdf::Document doc;
     doc.page.resize(1);

     doc.page[0].Concat(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
     doc.page[0].FillColor(RGB(255, 0, 255));
     doc.page[0].BeginText();
     doc.page[0].MoveText(60.0, doc.page[0].GetHeight() - 60.0);
     doc.page[0].Font(PDF_FONT_ARIAL, 24.0);
     doc.page[0].ShowText(L"Hello PDF World");
     doc.page[0].EndText();
     //
     if (doc.Save(L"AdobeHello.pdf") == false)
     {
          this->MessageBox(L"Error creating PDF", L"Wintempla AdobeHello", MB_OK | MB_ICONERROR);
     }
     this->Destroy();
}


AdobeHelloRun

Tip
Text alignment (left, right, center) in PDF is handle using the text metrics of the font. Wintempla provides several metrics such as: Pdf::Font.GetAscent, Pdf::Font.GetDescent, Pdf::Font.GetLeading, Pdf::Font.GetCharWidth, Pdf::Font.GetTextWidth, etc.
El alineamiento del texto (a la izquierda, derecha o al centro) en PDF es manejado usando las métricas del la fuente. Wintempla proporciona varias métricas tales como: Pdf::Font.GetAscent, Pdf::Font.GetDescent, Pdf::Font.GetLeading, Pdf::Font.GetCharWidth, Pdf::Font.GetTextWidth, etc.

Problem 6
Create Wintempla application called AdobeEvenOdd to create a PDF file with a list of even and odd numbers as shown.
Cree una aplicación de Wintempla llamada AdobeEvenOdd para crear un archivo de PDF con la lista de los números pares e impares como se muestra.

AdobeEvenOdd.cpp
#include "stdafx.h" //________________________________________ AdobeEvenOdd.cpp
#include "AdobeEvenOdd.h"

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE , LPTSTR cmdLine, int cmdShow){
     AdobeEvenOdd app;
     return app.BeginDialog(IDI_ADOBEEVENODD, hInstance);
}

void AdobeEvenOdd::Window_Open(Win::Event& e)
{
     const double fontSize = 18.0;
     Pdf::Document doc;
     doc.page.resize(1);

     doc.page[0].Concat(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
     doc.page[0].StrokeColor(RGB(210, 210, 210));
     doc.page[0].FillColor(RGB(60, 60, 70));

     wstring text;
     const double lineSpace = doc.font[PDF_FONT_ARIAL].GetLeading(fontSize) + doc.font[PDF_FONT_ARIAL].GetHeight(fontSize);
     const double leading = doc.font[PDF_FONT_ARIAL].GetLeading(fontSize);
     double x, y;
     const double pageWidth = doc.page[0].GetWidth();
     const double pageHeight = doc.page[0].GetHeight();
     for(int i = 0; i < 23; i++)
     {
          y = . . .;
          //______________________________________ Line
          . . .
          //______________________________________ Left Column
          . . .
          doc.page[0].BeginText();
          . . .
          doc.page[0].EndText();
          //______________________________________ Right Column
          . . .
          doc.page[0].BeginText();
          . . .
          doc.page[0].EndText();
     }
     . . .
}


AdobeEvenOddRun

Problem 7
Create Wintempla application called Text90 to rotate text.
Cree una aplicación de Wintempla llamada Text90 to rotate text.

Adobe90

Text90.cpp

. . .

void Text90::Window_Open(Win::Event& e)
{
     const double fontSize = 18.0;
     Pdf::Document doc;
     doc.page.resize(1);
     //
     doc.page[0].Concat(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
     doc.page[0].StrokeColor(RGB(210, 210, 210));
     doc.page[0].FillColor(RGB(60, 60, 70));
     //
     const double pageWidth = doc.page[0].GetWidth();
     const double pageHeight = doc.page[0].GetHeight();
     //____________________________________________________________________ Vertical Line
     doc.page[0].Line(pageWidth/2.0, 0, pageWidth/2.0, pageHeight);
     doc.page[0].StrokePath();
     //____________________________________________________________________ Horizontal Line
     doc.page[0].Line(0, pageHeight/2, pageWidth, pageHeight/2);
     doc.page[0].StrokePath();
     //____________________________________________________________________ 45 degrees Text
     doc.page[0].BeginText();
     doc.page[0].TextMatrixRotation(45.0, pageWidth/2, pageHeight/2);
     doc.page[0].Font(PDF_FONT_ARIAL, fontSize);
     doc.page[0].ShowText(L"........................45");
     doc.page[0].EndText();
     //____________________________________________________________________ 90 degrees Text
     doc.page[0].BeginText();
     doc.page[0].TextMatrixRotation(90.0, pageWidth/2, pageHeight/2);
     doc.page[0].Font(PDF_FONT_ARIAL, fontSize);
     doc.page[0].ShowText(L"........................90");
     doc.page[0].EndText();
     //____________________________________________________________________ 135 degrees Text
     doc.page[0].BeginText();
     doc.page[0].TextMatrixRotation(135.0, pageWidth/2, pageHeight/2);
     doc.page[0].Font(PDF_FONT_ARIAL, fontSize);
     doc.page[0].ShowText(L".......................135");
     doc.page[0].EndText();
     //
     if (doc.Save(L"Adobe90.pdf") == false)
     {
          this->MessageBox(L"Error creating PDF", L"Text90", MB_OK | MB_ICONERROR);
     }
     this->Destroy();
}


Value

A PDF document has a collection of objects. An object may have values; Wintempla provides the Pdf::Object class to manipulate a PDF object, and the Pdf::Value class to manipulate the value store in the object. Each value is used to store (see figure):
  • A value: PDF_VALUE_DATA
  • A name: PDF_VALUE_NAME
  • A text string using a Literal String: PDF_VALUE_LITERALSTRING
  • A text string using an Hexadecimal String: PDF_VALUE_HEXSTRING
  • An array of values: PDF_VALUE_ARRAY
  • A reference to an object (Indirect Reference): PDF_VALUE_REFERENCE
  • A collection of pairs (name and value) using a Dictionary: PDF_VALUE_DICTIONARY
Note that PDF values can be nested, for instance a PDF array may store an array of PDF arrays creating a matrix of value. Elements in a PDF array can be of different type.
Un documento de PDF tiene una colección de objetos. Cada objeto puede tener valores, Wintempla proporciona la clase Pdf::Object para manipular objetos de PDF, y la clase Pdf::Value para manipular el valor almacenado en el objeto. Cada valor es usado para almacenar (ver figura):
  • Un valor: PDF_VALUE_DATA
  • Un nombre: PDF_VALUE_NAME
  • Una cadena de texto usando Literal String: PDF_VALUE_LITERALSTRING
  • Una cadena de texto usando Hexadecimal String: PDF_VALUE_HEXSTRING
  • Un arreglo (colección) de valores: PDF_VALUE_ARRAY
  • Una referencia a otro objeto (Indirect Reference): PDF_VALUE_REFERENCE
  • Una colección de pares (nombre y valor) usando un Dictionary: PDF_VALUE_DICTIONARY
Note que los valores de PDF pueden estar anidados, por ejemplo un arreglo PDF puede almacenar un arreglo de arreglos PDF creando una matriz de valores. Los elementos en un arreglo PDF pueden ser de distinto tipo.

Value

Problem 8
Create a Wintempla Dialog application called PdfLex to test the PDF lexical analyzer. Using Wintempla add one textbox called tbxOutput with the multi-line property, a vertical scrollbar and a horizontal scrollbar.

PdfLexRun

PdfLex.cpp
. . .
void PdfLex::Window_Open(Win::Event& e)
{
}

void PdfLex::btOpenFile_Click(Win::Event& e)
{
     Win::FileDlg dlg;
     dlg.Clear();
     dlg.SetFilter(L"PDF files (*.pdf)\0*.pdf\0\0", 0, L"pdf");
     if (dlg.BeginDialog(hWnd, L"Open", false))
     {
          Win::HourGlassCursor hgc(true);
          Pdf::LexicalAnalyzer lex;
          lex.Create(dlg.GetFileNameFullPath());
          //
          wstring output = L"Line\ttype\t\t\t\tdata\t\tLength(bytes)\r\n";
          Pdf::Token token;
          wstring text;
          wstring content;
          while(true)
          {
               lex.GetNextToken(token);
               if (token.type == LEX_END_OF_FILE) break;
               if (token.type == LEX_PDF_STREAM)
               {
                    content = L"stream";
               }
               else
               {
                    token.GetText(content);
               }
               Sys::Format(text, L"%d\t%s\t\t\t\t%s\t\t%d\r\n", token.line_number, Cpl::LexicalAnalyzer::GetTokenConstant(token.type), content.c_str(), token.length);
               output += text;
          }
          tbxOutput.Text = output;
     }



Tip
The table below shows some of the constants used to process PDF files using Wintempla.
La tabla de abajo muestra algunas de las constantes usadas para procesar archivos PDF usando Wintempla.

LEX_PDF_OBJ    obj  
LEX_PDF_ENDOBJendobj
LEX_PDF_STREAMstream
LEX_PDF_ENDSTREAMendstream
LEX_PDF_XREFxref
LEX_PDF_TRAILERtrailer
LEX_PDF_STARTXREFstartxref
LEX_PDF_BSLASH_BSLASH\\
LEX_PDF_BSLASH_LPARENTHESIS\\(
LEX_PDF_BSLASH_RPARENTHESIS\\)
LEX_PDF_BSLASH_LBRACKET\\[
LEX_PDF_BSLASH_RBRACKET\\]
LEX_PDF_BSLASH_LESS\\<
LEX_PDF_BSLASH_BIGGER\\>
LEX_PDF_BSLASH_DIAGONAL\\/
LEX_PDF_NAMEi.e. /Type
LEX_PDF_DATAData
LEX_INSERTION_OPERATOR<<
LEX_EXTRACTION_OPERATOR>>
LEX_IS_LESS<
LEX_IS_BIGGER>
LEX_LEFT_PARENTHESIS(
LEX_RIGHT_PARENTHESIS)
LEX_LEFT_BRACKET[
LEX_RIGHT_BRACKET]

Problem 9
Create a Wintempla dialog application called AdobeRead to load the objects of a PDF document. Using Wintempla GUI editor, add one textbox called tbxOutput with the multi-line property, a vertical scrollbar and a horizontal scrollbar.
Creer una aplicación de diálogo de Wintempla llamada AdobeRead para cargar los objetos de un documento PDF. Usando Wintempla GUI editor, agregue una caja de texto llamada tbxOutput con la propiedad de multi-línea, una barra de desplazamiento vertical y una barra de desplazamiento horizontal.

AdobeReadRun

AdobeRead.cpp
. . .
void AdobeRead::Window_Open(Win::Event& e)
{
     Pdf::Reader reader;
     if (reader.Load(L"C:\\selo\\google.pdf") == false)
     {
          this->MessageBox(L"Unable to open file", L"AdobeRead", MB_OK | MB_ICONERROR);
          //return;
     }
     wstring output;
     wchar_t text[1024];
     size_t object_count = reader.object.size();
     wstring content;
     for (size_t i = 0; i < object_count; i++)
     {
          reader.object[i].value.GetText(content);
          _snwprintf_s(text, 1024,
               _TRUNCATE, L"____________________________\r\n%d %d %s\r\n %s\r\n",
               reader.object[i].id, reader.object[i].generation_number,
               reader.object[i].value.GetText(), content.c_str());
          output += text;
     }
     tbxOutput.Text = output;
}


Images

Images are stored in a PDF by storing the color space and the binary pixel data. Each image in a PDF file must have a name, i.e., Im1, Im2, Im3, etc. To draw an image in a PDF document, you can use the commands
  • ID for inline images
  • Do for XObject images
as shown:

/Im1
Do
Las imágenes son almacenadas en un PDF almacenando el espacio de colores y los datos binarios de los pixeles. Cada imagen en un PDF debe tener un nombre, por ejemplo: Im1, Im2, Im3, etc. Para dibujar una imagen un documento de PDF, usted puede usar los comandos
  • ID para las imágenes in línea
  • Do para las imágenes usando XObjects
como se muestra:

/Im1
Do

Image object

The actual image is defined in a separated object, see example below for object 22.

22 0 obj <<
/Filter/DCTDecode
/Type/XObject
/Length 540000
/Width 620
/Height 290
/BitsPerComponent 8
/ColorSpace 17 0 R
/Subtype/Image
>>
stream (binary pixel data follows)

Additionally, the image object must be listed in the resource table

XObject<</Im1 22 0 R/Im2 23 0 R>>

La imagen está definida en un objeto por separado, vea el ejemplo debajo para el objeto 22. Adicionalmente, el objeto de imagen debe ser listado en la lista de recursos.

Tip
The following diagram shows how to insert an inline image in a PDF.
El siguiente diagrama muestra cómo insertar una imagen en línea en un PDF.

InlineImage

Tip
The following diagram shows how to insert an image using a XObject.
El siguiente diagrama muestra cómo insertar una imagen usando un XObject.

XObjectImage

FILTER

The Filter value in the Image Object indicates how the data is stored. For instance, a Filter with a value of DCTDecode is a JPG image. A Filter with a value of LZWDecode is the LZW (Lempel-Ziv-Welch) adaptive compression method. A Filter with a value of FlateDecode is a ZIP compression. Therefore, a JPG image can be stored in a PDF file without any additional processing by using the DCTDecode Filter. However, other image types such as GIF, BMP or PNG cannot be directly stored in the PDF, instead the image data must be compressed using JPG, LZW or ZIP to store the image in the PDF file.
El valor del Filter del Image Object indica como los datos están almacenados. Por ejemplo, un Filter con un valor de DCTDecode is una imagen JPG. Un Filtro con un valor de LZWDecode está comprimido usando el método de compresión adaptivo LZW (Lempel-Ziv-Welch). Un filtro con un valor de FlatDecode es una compresión ZIP. Por lo tanto, una imagen de JPG puede ser almacenada en un PDF sin ningún procesamiento adicional usando el Filter DCTDecode. Sin embargo, otras tipos de imágenes tales como GIF, BMP o PNG no pueden ser almacenados directamente en el PDF, en su lugar los datos de la imagen pueden ser comprimidos usando JPG, LZW o ZIP para ser almacenados dentro del archivo PDF.

ASCIIHexDecode

It decodes data encoded in an ASCII hexadecimal representation (Lossless).
Decodifica los datos codificados en una representación ASCII hexadecimal (sin pérdida).

ASCII85Decode

It decodes data encoded in an ASCII base 85 representation (Lossless).
Decodifica los datos codificados en una representación ASCII base 85 (sin pérdida).

LZWDecode

It decompresses data encoded using the LZW (Lempel-Ziv-Welch) adaptive compression method (Lossless).
Descomprime los datos codificados usando el algorithmo de Lempel-Ziv-Welch, LZW (sin pérdida).

FlateDecode

It decompresses data encoded using the zlib/deflate compression method (Lossless).
Descomprime los datos codificados usando la compression zlib/deflate (sin pérdida).

DCTDecode

It decompresses data encoded using a DCT (discrete cosine transform) technique based on the JPEG standard (Loos less).
Descomprime los datos codificados usando la transforma coseno dicreate DCT que se base en el estandar de JPEG (sin pérdida).

Hint
To reduce the size of the PDF document, you may try to use other filters instead of /ASCIIHexDecode. In this case, you will need to provide the pixels of the bitmap in the specified filter format, that is, you will need to compress the pixels to ZIP, LZW or JPG.
Para reducir el tamaño del documento de PDF, usted puede trata de usar otros filtros en lugar de /ASCIIHexDecode. En este caso, usted necesitará proporcionar los pixeles del mapa de bits en el formato del filtro especificado, esto es, usted necesitará comprimir los pixeles a ZIP, LZW o JPG.

Problem 10
Create a Wintempla dialog application called PortraitPdf to test bitmaps in PDF documents. You will need an uncompressed bitmap with a color depth of 24 bits. You can place the bitmap where your CPP files are, or you can specify the full path of the bitmap file.
Creer una aplicación de diálogo de Wintempla llamada PortraitPdf para probar los mapas de bits en los documentos de PDF. Usted necesitará un bitmap sin comprimir con una profundidad de color de 24 bits. Usted puede colocar el bitmap dónde están los archivos CPP, o usted puede especificar la ruta completa del archivo de mapa de bits.

PortraitPdfRun

PortraitPdf.cpp
. . .
void PortraitPdf::Window_Open(Win::Event& e)
{
     //_______________________________________________________________ 1. Create a PDF document with one page
     Pdf::Document doc;
     doc.page.resize(1);
     //_______________________________________________________________ 2. Read a bitmap file
     CG::DIBitmap bitmap;
     const wchar_t * error = bitmap.Load(L"louise.bmp");
     if (error != NULL)
     {
          this->MessageBox(error, L"Loading BMP", MB_OK | MB_ICONERROR);
          return;
     }
     //_______________________________________________________________ 3. Add an image to the PDF page
     Pdf::Image image;
     image.width = bitmap.GetWidth();
     image.height = bitmap.GetHeight();
     image.isColor = true;
     image.bitsPerComponent = 8;
     image.filter = "/ASCIIHexDecode";
     bitmap.GetASCIIHexDecode(image.data);
     doc.page[0].AddImage(image);
     //_______________________________________________________________ 4. Draw the image
     const double imageWidth = doc.page.back().GetWidth();
     const double imageHeight = (imageWidth*bitmap.GetHeight())/bitmap.GetWidth();
     doc.page.back().DrawImage(image, 0.0, doc.page.back().GetHeight() - imageHeight, imageWidth, imageHeight);
     //_______________________________________________________________ 5. Save the PDF file
     if (doc.Save(L"Portrait.pdf") == false)
     {
          this->MessageBox(L"Error creating PDF", L"Wintempla PortraitPdf", MB_OK | MB_ICONERROR);
     }
     this->Destroy();
}


GIF and PDF

A GIF image can produce very compact PDF files when LZWDecode is used. The following code shows how to insert a GIF image in a PDF file.
Una imagen GIF puede producir archivos PDF muy compactos cuando se usa LZWDecode. El código siguiente muestra como inserta una imagen GIF un archivo PDF.

PortraitPdf.cpp
. . .
void PortraitPdf::Window_Open(Win::Event& e)
{
     //_______________________________________________________________ 1. Create a PDF document with one page
     Pdf::Document doc;
     doc.page.resize(1);
     //_______________________________________________________________ 2. Read a bitmap file
     CG::DIBitmap bitmap;
     const wchar_t * error = bitmap.Load(L"louise.gif");
     if (error != NULL)
     {
          this->MessageBox(error, L"Loading GIF", MB_OK | MB_ICONERROR);
          return;
     }
     //_______________________________________________________________ 3. Add an image to the PDF page
     Pdf::Image image;
     image.width = bitmap.GetWidth();
     image.height = bitmap.GetHeight();
     image.isColor = true;
     image.bitsPerComponent = 8;
     image.filter = "[/LZWDecode ]";
     bitmap.GetLZWDecode(image.data);
     bitmap.GetColorTable(image.colorTable);
     doc.page[0].AddImage(image);
     //_______________________________________________________________ 4. Draw the image
     const double imageWidth = doc.page.back().GetWidth();
     const double imageHeight = (imageWidth*bitmap.GetHeight())/bitmap.GetWidth();
     doc.page.back().DrawImage(image, 0.0, doc.page.back().GetHeight() - imageHeight, imageWidth, imageHeight);
     //_______________________________________________________________ 5. Save the PDF file
     if (doc.Save(L"Portrait.pdf") == false)
     {
          this->MessageBox(L"Error creating PDF", L"Wintempla PortraitPdf", MB_OK | MB_ICONERROR);
     }
     this->Destroy();
}


Problem 11
Create a Wintempla dialog application called AdobePara to test text paragraphs in PDF documents.
Creer una aplicación de diálogo de Wintempla llamada AdobePara para probar párrafos de texto en los documentos de PDF.

AdobeParaRun

AdobePara.cpp
. . .
void AdobePara::Window_Open(Win::Event& e)
{
     wstring text = L"Adobe bricks are rectangular prisms small enough that they can quickly air dry individually without cracking. ";
     text += L"They can be subsequently assembled, with the application of adobe mud to bond the individual bricks into a structure. ";
     text += L"There is no standard size, with substantial variations over the years and in different regions. In some areas a popular size ";
     text += L"measured 8 by 4 by 12 inches (20 cm × 10 cm × 30 cm) weighing about 25 pounds (11 kg); in other contexts the size is 10 by 4 by ";
     text += L"14 inches (25 cm × 10 cm × 36 cm) weighing about 35 pounds (16 kg). The maximum sizes can reach up to 100 pounds (45 kg); ";
     text += L"above this weight it becomes difficult to move the pieces, and it is preferred to ram the mud in situ, resulting in a different typology ";
     text += L"known as rammed earth.\r\n\r\n";
     text += L"In dry climates, adobe structures are extremely durable, and account for some of the oldest existing buildings in the world. ";
     text += L"Adobe buildings offer significant advantages due to their greater thermal mass, but they are known to be particularly susceptible ";
     text += L"to earthquake damage if they are not somehow reinforced. Cases where adobe structures were widely damaged during ";
     text += L"earthquakes include the 1976 Guatemala earthquake, the 2003 Bam earthquake, and the 2010 Chile earthquake.\r\n\r\n";
     text += L"Buildings made of sun-dried earth are common throughout the world (Middle East, Western Asia, North Africa, West ";
     text += L"Africa, South America, southwestern North America, Spain, and Eastern Europe.)[5] Adobe had been in use by indigenous ";
     text += L"peoples of the Americas in the Southwestern United States, Mesoamerica, and the Andes for several thousand years. Puebloan ";
     text += L"peoples built their adobe structures with handsful or basketsful of adobe, until the Spanish introduced them to making bricks. ";
     text += L"Adobe bricks were used in Spain from the Late Bronze and Iron Ages (eighth century BCE onwards).[7] Its wide use can be ";
     text += L"attributed to its simplicity of design and manufacture, and economics.";

     const double fontSize = 12.0;
     Pdf::Document doc;
     doc.AddPage(PDF_PAPER_SIZE_LETTER, true);
     doc.page.back();
     //
     doc.page.back().Concat(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
     doc.page.back().StrokeColor(RGB(210, 210, 210));
     doc.page.back().FillColor(RGB(0, 0, 0));
     //
     const double lineSpace = doc.font[PDF_FONT_ARIAL].GetLeading(fontSize) + doc.font[PDF_FONT_ARIAL].GetHeight(fontSize);
     const double leading = doc.font[PDF_FONT_ARIAL].GetLeading(fontSize);
     const double margin = 60;
     const double pageWidth = doc.page.back().GetWidth() - 2*margin;
     const double pageHeight = doc.page.back().GetHeight();
     vector<vector<Pdf::TextGroup> > tx;
     doc.Paragraph(text.c_str(), PDF_FONT_ARIAL, fontSize, pageWidth, tx);
     const size_t rowCount = tx.size();
     size_t colCount;
     size_t i, j;
     double x = margin;
     double y = margin;
     double space = 0.0;
     double actualWidth = 0.0;
     double extra = 0.0;
     bool paragraphEnd;
     y = pageHeight - lineSpace - margin;
     for(i = 0; i < rowCount; i++)
     {
          colCount = tx[i].size();
          //_________________________________________________________ 1. Compute actual text width
          actualWidth = 0.0;
          for (j = 0; j < colCount; j++) actualWidth += tx[i][j].width;
          extra = (pageWidth - actualWidth)/(colCount -1);
          //_________________________________________________________ 2. Text
          x = margin;
          paragraphEnd = (i+1<rowCount) ? (tx[i+1].size() == 0) : true;
          for (j = 0; j < colCount; j++)
          {
               doc.page.back().BeginText();
               doc.page.back().MoveText(x, y);
               doc.page.back().Font(PDF_FONT_ARIAL, fontSize);
               doc.page.back().ShowText(tx[i][j].text);
               doc.page.back().EndText();
               //_______________________________________________________ 3. Fill line justification
               if (paragraphEnd)
               {
                    x += tx[i][j].width; // Do not fill line
               }
               else
               {
                    x += (tx[i][j].width + extra); // Add extra space
               }
          }
          //_________________________________________________________ 4. Add a new page
          if (y < margin)
          {
               doc.AddPage(PDF_PAPER_SIZE_LETTER, true);
               y = pageHeight - lineSpace - margin;
          }
          else
          {
               y -= lineSpace;
          }
     }
     if (doc.Save(L"AdobeParagraph.pdf") == false)
     {
          this->MessageBox(L"Error creating PDF", L"AdobePara", MB_OK | MB_ICONERROR);
     }
     this->Destroy();
}


Problem 12
Create a Wintempla dialog application called AdobeSQL to create a PDF document from an SQL query. For this exercise we will use the ford database described in Wintempla > SQL > Sample data bases. After creating the application, edit the string connection in the stdafx.h file as shown.
Creer una aplicación de diálogo de Wintempla llamada AdobeSQL para crear un documento de PDF desde una consulta de SQL. Para este ejercicio usaremos la base de datos de ford que es descrita en Wintempla > SQL > Sample data bases. Edite la cadena de conexión en el archivo stdafx.h cómo se muestra.

AdobeSQLRun

stdafx.h
. . .
//Control Panel>Administrative Tools>Data Sources (ODBC)>System DSN>Add>SQL Native Client>Server: computer_name\SQLExpress
. . .
#define CONNECTION_STRING L"DRIVER={SQL Server};server=localhost\\SQLEXPRESS;database=ford;Trusted_Connection=yes"


AdobeSQL.cpp
. . .
void AdobeSQL::Window_Open(Win::Event& e)
{
     COLORREF colorHeaderText = RGB(0, 0, 200);
     COLORREF colorHeaderBack = RGB(235, 235, 255);
     //_____________________________________________________________ 1. Document setup
     const double fontSize = 12.0;
     Pdf::Document doc;
     doc.AddPage(PDF_PAPER_SIZE_LETTER, true);
     doc.page.back();
     doc.page.back().Concat(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
     doc.page.back().StrokeColor(colorHeaderBack);
     //_____________________________________________________________ 2. Compute dimensions
     const double lineSpace = doc.font[PDF_FONT_ARIAL].GetLeading(fontSize) + doc.font[PDF_FONT_ARIAL].GetHeight(fontSize);
     const double leading = doc.font[PDF_FONT_ARIAL].GetLeading(fontSize);
     const double margin = 60;
     const double pageWidth = doc.page.back().GetWidth() - 2*margin;
     const double pageHeight = doc.page.back().GetHeight();
     Sql::SqlConnection conn;
     wstring cmd;
     int employee_id = 0;
     wchar_t name[64], address[64], city[64], state[32], zip[16], phone[16];
     double nameWidth = 0.25*pageWidth;
     double addressWidth = 0.2*pageWidth;
     double cityWidth = 0.15*pageWidth;
     double stateWidth = 0.1*pageWidth;
     double zipWidth = 0.1*pageWidth;
     double phoneWidth = 0.2*pageWidth;
     double x;
     double y = pageHeight - lineSpace - margin;
     double offsetX = 0.2*fontSize;
     double offsetY = 0.3*fontSize;
     wstring cutText;
     //_____________________________________________________________ 2. Header
     x = margin;
     //___________________________________ 2.1. name
     doc.page.back().FillColor(colorHeaderBack);
     doc.page.back().Rectangle(x, y-offsetY, x+nameWidth-offsetX, y-offsetY+lineSpace);
     doc.page.back().FillAndStrokePath();
     //
     doc.page.back().FillColor(colorHeaderText);
     doc.page.back().BeginText();
     doc.page.back().MoveText(x, y);
     doc.page.back().Font(PDF_FONT_ARIAL_BOLD, fontSize);
     doc.page.back().ShowText(L"Name");
     doc.page.back().EndText();
     x += nameWidth;
     //___________________________________ 2.2. address
     doc.page.back().FillColor(colorHeaderBack);
     doc.page.back().Rectangle(x, y-offsetY, x+addressWidth-offsetX, y-offsetY+lineSpace);
     doc.page.back().FillAndStrokePath();
     //
     doc.page.back().FillColor(colorHeaderText);
     doc.page.back().BeginText();
     doc.page.back().MoveText(x, y);
     doc.page.back().Font(PDF_FONT_ARIAL_BOLD, fontSize);
     doc.page.back().ShowText(L"Address");
     doc.page.back().EndText();
     x += addressWidth;
     //___________________________________ 2.3. city
     doc.page.back().FillColor(colorHeaderBack);
     doc.page.back().Rectangle(x, y-offsetY, x+cityWidth-offsetX, y-offsetY+lineSpace);
     doc.page.back().FillAndStrokePath();
     //
     doc.page.back().FillColor(colorHeaderText);
     doc.page.back().BeginText();
     doc.page.back().MoveText(x, y);
     doc.page.back().Font(PDF_FONT_ARIAL_BOLD, fontSize);
     doc.page.back().ShowText(L"City");
     doc.page.back().EndText();
     x += cityWidth;
     //___________________________________ 2.4. state
     doc.page.back().FillColor(colorHeaderBack);
     doc.page.back().Rectangle(x, y-offsetY, x+stateWidth-offsetX, y-offsetY+lineSpace);
     doc.page.back().FillAndStrokePath();
     //
     doc.page.back().FillColor(colorHeaderText);
     doc.page.back().BeginText();
     doc.page.back().MoveText(x, y);
     doc.page.back().Font(PDF_FONT_ARIAL_BOLD, fontSize);
     doc.page.back().ShowText(L"State");
     doc.page.back().EndText();
     x += stateWidth;
     //___________________________________ 2.5. zip
     doc.page.back().FillColor(colorHeaderBack);
     doc.page.back().Rectangle(x, y-offsetY, x+zipWidth-offsetX, y-offsetY+lineSpace);
     doc.page.back().FillAndStrokePath();
     //
     doc.page.back().FillColor(colorHeaderText);
     doc.page.back().BeginText();
     doc.page.back().MoveText(x, y);
     doc.page.back().Font(PDF_FONT_ARIAL_BOLD, fontSize);
     doc.page.back().ShowText(L"ZIP");
     doc.page.back().EndText();
     x += zipWidth;
     //___________________________________ 2.6. phone
     doc.page.back().FillColor(colorHeaderBack);
     doc.page.back().Rectangle(x, y-offsetY, x+phoneWidth-offsetX, y-offsetY+lineSpace);
     doc.page.back().FillAndStrokePath();
     //
     doc.page.back().FillColor(colorHeaderText);
     doc.page.back().BeginText();
     doc.page.back().MoveText(x, y);
     doc.page.back().Font(PDF_FONT_ARIAL_BOLD, fontSize);
     doc.page.back().ShowText(L"Phone");
     doc.page.back().EndText();
     x += phoneWidth;
     y -= lineSpace;
     //_____________________________________________________________ 4. SQL connect and fetch
     doc.page.back().StrokeColor(RGB(210, 210, 210));
     doc.page.back().FillColor(RGB(0, 0, 0));
     try
     {
          conn.OpenSession(hWnd, CONNECTION_STRING);
          conn.ExecuteSelect(L"SELECT name, address, city, state, zip, phone FROM store;");
          conn.BindColumn(1, name, 64);
          conn.BindColumn(2, address, 64);
          conn.BindColumn(3, city, 64);
          conn.BindColumn(4, state, 32);
          conn.BindColumn(5, zip, 16);
          conn.BindColumn(6, phone, 16);
          while (conn.Fetch() == true)
          {
               x = margin;
               //___________________________________ 4.1. name
               doc.CutToFitWidth(name, PDF_FONT_ARIAL, fontSize, nameWidth, cutText);
               doc.page.back().BeginText();
               doc.page.back().MoveText(x, y);
               doc.page.back().Font(PDF_FONT_ARIAL, fontSize);
               doc.page.back().ShowText(cutText);
               doc.page.back().EndText();
               x += nameWidth;
               //___________________________________ 4.2. address
               doc.CutToFitWidth(address, PDF_FONT_ARIAL, fontSize, addressWidth, cutText);
               doc.page.back().BeginText();
               doc.page.back().MoveText(x, y);
               doc.page.back().Font(PDF_FONT_ARIAL, fontSize);
               doc.page.back().ShowText(cutText);
               doc.page.back().EndText();
               x += addressWidth;
               //___________________________________ 4.3. city
               doc.CutToFitWidth(city, PDF_FONT_ARIAL, fontSize, cityWidth, cutText);
               doc.page.back().BeginText();
               doc.page.back().MoveText(x, y);
               doc.page.back().Font(PDF_FONT_ARIAL, fontSize);
               doc.page.back().ShowText(cutText);
               doc.page.back().EndText();
               x += cityWidth;
               //___________________________________ 4.4. state
               doc.CutToFitWidth(state, PDF_FONT_ARIAL, fontSize, stateWidth, cutText);
               doc.page.back().BeginText();
               doc.page.back().MoveText(x, y);
               doc.page.back().Font(PDF_FONT_ARIAL, fontSize);
               doc.page.back().ShowText(cutText);
               doc.page.back().EndText();
               x += stateWidth;
               //___________________________________ 4.5. zip
               doc.CutToFitWidth(zip, PDF_FONT_ARIAL, fontSize, zipWidth, cutText);
               doc.page.back().BeginText();
               doc.page.back().MoveText(x, y);
               doc.page.back().Font(PDF_FONT_ARIAL, fontSize);
               doc.page.back().ShowText(cutText);
               doc.page.back().EndText();
               x += zipWidth;
               //___________________________________ 4.6. phone
               doc.CutToFitWidth(phone, PDF_FONT_ARIAL, fontSize, phoneWidth, cutText);
               doc.page.back().BeginText();
               doc.page.back().MoveText(x, y);
               doc.page.back().Font(PDF_FONT_ARIAL, fontSize);
               doc.page.back().ShowText(cutText);
               doc.page.back().EndText();
               x += phoneWidth;
               //_____________________________________________________________ 5. Add a new page
               if (y < margin)
               {
                    doc.AddPage(PDF_PAPER_SIZE_LETTER, true);
                    y = pageHeight - lineSpace - margin;
               }
               else
               {
                    y -= lineSpace;
               }
          }
     }
     catch (Sql::SqlException e)
     {
          this->MessageBox(e.GetDescription(), L"AdobeSQL", MB_OK | MB_ICONERROR);
     }
     //_____________________________________________________________ 6. Save the document
     if (doc.Save(L"AdobeFord.pdf") == false)
     {
          this->MessageBox(L"Error creating PDF", L"AdobeSQL", MB_OK | MB_ICONERROR);
     }
     this->Destroy();
}


© Copyright 2000-2021 Wintempla selo. All Rights Reserved. Jul 22 2021. Home