pdf:paintingapage
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
pdf:paintingapage [2015/04/01 12:18] – christian | pdf:paintingapage [2015/04/02 14:57] – [How does text get onto a PDF page] christian | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== How does text get onto a PDF page ====== | ====== How does text get onto a PDF page ====== | ||
- | A PDF page has a content stream (**/ | + | A PDF page has a content stream (**'' |
- | The operators in the contents stream have no way to reference PDF objects outside of the contents. With an important exception: complex objects like raster images or fonts are held separately in the **/ | + | The operators in the contents stream have no way to reference PDF objects outside of the contents. With an important exception: complex objects like raster images or fonts are held separately in the **'' |
<code pdf> | <code pdf> | ||
/Page << | /Page << | ||
Line 15: | Line 15: | ||
/F1 10 Tf | /F1 10 Tf | ||
10 5 Td | 10 5 Td | ||
- | (Hello) Tj | + | (Hello |
ET | ET | ||
endstream | endstream | ||
Line 21: | Line 21: | ||
</ | </ | ||
- | This paints the string ' | + | This paints the string |
To achieve this in Smalltalk you can write the following: | To achieve this in Smalltalk you can write the following: | ||
+ | <code smalltalk> | ||
+ | page := Page newInBounds: | ||
+ | renderer fillColor: CmykColor black. | ||
+ | renderer textObjectDo: | ||
+ | renderer setFont: #Helvetica size: 10. | ||
+ | renderer add: (NextLineRelative operands: #(10 5)). | ||
+ | renderer showString: 'Hello World' | ||
+ | </ | ||
+ | {{example01helloworld.pdf}} See the class method '' | ||
- | page := Page newInBounds: | + | You notice that I did not use the font ID **''/ |
- | renderer fillColor: CmykColor black. | + | |
- | renderer textObjectDo: | + | |
- | renderer setFont: | + | |
- | renderer add: (TextPositioningOperator Td operands: #(10 5)). | + | |
- | renderer | + | |
- | You notice that I did not use the font ID **/F1** but the font directly (referenced as the global # | + | The renderer you get when creating a Page takes care of the **'' |
- | The renderer | + | Common operators are implemented as renderer |
- | Common operators are implemented as renderer methods like **fillColor:** and **showString: | + | **'' |
- | The reason why **Td** is not covered is that there are several ways to put text on a page - and using **Td** is not a very practical one. | + | ===== Painting Text ===== |
- | + | ||
- | ==== Painting Text ==== | + | |
Line 46: | Line 48: | ||
* set the relevant graphics state parameters including the font | * set the relevant graphics state parameters including the font | ||
- | |||
* set the position/ | * set the position/ | ||
- | |||
* show the string | * show the string | ||
- | While the state parameters are straight forward (see list below), positioning the string is best done using a matrix. The text matrix is set by **Tm** with 6 numbers as parameters. | + | While the state parameters are straight forward (see list below), positioning the string is best done using a matrix. The text matrix is set by **'' |
- | + | <code smalltalk> | |
- | (TextPositioningOperator Tm operands: #(1 0 0 1 10 5)) | + | (SetTextMatrix |
+ | </ | ||
produces | produces | ||
- | 1 0 0 1 10 5 Tm | + | |
- | which sets the scaling to 1 horizontally and vertically and adds an offset to point 10@5, i.e. it does the same as `10 5 Td`. A transformation matrix can express scaling, rotation, skewing and translation at once. For example | + | which sets the scaling to 1 horizontally and vertically and adds an offset to point 10 @ 5, i.e. it does the same as '' |
- | 0.95 0 0 1 10 5 Tm | + | 0.95 0 0 1 10 5 Tm |
would compress the text horizonatally by 5%. | would compress the text horizonatally by 5%. | ||
For example Adobe Illustrator sets the font size always to 1 and uses the matrix to scale accordingly. | For example Adobe Illustrator sets the font size always to 1 and uses the matrix to scale accordingly. | ||
- | /F1 1 Tf | + | |
- | 9.5 0 0 10 10 5 Tm | + | 9.5 0 0 10 10 5 Tm |
- | The text state operators: | + | The text state operators |
- | + | * **'' | |
- | * **Tf** | + | * **'' |
- | + | * **'' | |
- | * **Tr** | + | * **'' |
- | + | * **'' | |
- | * **Tc** | + | * **'' |
- | + | * **'' | |
- | * **Tw** | + | |
- | + | ||
- | * **TL** | + | |
- | + | ||
- | * **Ts** | + | |
- | + | ||
- | * **Th** | + | |
The two relevant text showing operators are: | The two relevant text showing operators are: | ||
- | * **Tj** | + | * **'' |
- | + | * **'' | |
- | * **TJ** show string with individual character positioning | + | |
There are no high-level operations for word wrapping, automatic kerning, hyphenization or even simple justification. This is only about putting characters at specific positions. How you get these positions is up to you or your layout program. | There are no high-level operations for word wrapping, automatic kerning, hyphenization or even simple justification. This is only about putting characters at specific positions. How you get these positions is up to you or your layout program. | ||
For justification, | For justification, | ||
- | aFont stringWidthOf: | + | <code smalltalk> |
+ | aFont stringWidthOf: | ||
+ | </ | ||
Using our example you would write | Using our example you would write | ||
- | (Graphics.Fonts.Font fontAt: #Helvetica) stringWidthOf: | + | <code smalltalk> |
+ | (Graphics.Fonts.Font fontAt: #Helvetica) stringWidthOf: | ||
+ | </ | ||
returning 22.78 which is the width in PostScript points in an unscaled coordinate system. | returning 22.78 which is the width in PostScript points in an unscaled coordinate system. | ||
- | ==== Program design ==== | + | ===== Program design |
The implementation may look at bit clumsy. Why should you use | The implementation may look at bit clumsy. Why should you use | ||
- | renderer add: (TextPositioningOperator Td operands: #(10 5)) | + | <code smalltalk> |
- | to get the simple string | + | renderer add: (NextLineRelative |
- | + | </ | |
- | Firstly, I wanted operators as objects and not just as strings you write into the contents stream. The objects can be read from a PDF (try: from the PDFExplorer inspect a **/ | + | to get the simple string |
- | * check the consistency/ | + | Firstly, I wanted operators as objects and not just as strings you write into the contents stream. The objects can be read from a PDF (try: from the [[PDFExplorer]] inspect a **'' |
+ | * check the consistency/ | ||
* implement a GraphicsState object to track the changes to it. With this, unneccessary operators can be avoided (this is on my todo list). | * implement a GraphicsState object to track the changes to it. With this, unneccessary operators can be avoided (this is on my todo list). | ||
In any case, it is good to have operators referable in the development image. | In any case, it is good to have operators referable in the development image. | ||
- | Operators have a name and arguments, the operands. There are subclasses for each group of operators. They don't add state, but allow for different behavior (which is not exploited yet). An operator is created by sending the appropriate class message to the corresponding Operator class. | + | Secondly, this clumsy interface is meant to be used as backend by a higher level graphics framework. It is expected that you have an abstraction of **Text** which can render itself using the PDF primitives. In [[http:// |
- | TextPositioningOperator Td | + | <code smalltalk> |
- | The operands are added with | + | ChartText |
- | < | + | style: (Textstyle |
- | which returns a copy of the operator with the operands. | + | color: (CmykColor cyan: 1 magenta: 0.3 yellow: 0 black: 0.3) |
- | + | font: # | |
- | I am not sure that this design will stand the time. I will see when I use it in ernest. | + | size: 12 |
- | + | trackKerning: | |
- | Secondly, this clumsy interface is meant to be used as backend by a higher level graphics framework. It is expected that you have an abstraction of **Text** which can render itself using the PDF primitives. In '' | + | withoutLeftSideBearing: |
- | ChartText | + | scale: 0.95 @ 1) |
- | style: (Textstyle | + | string: ' |
- | color: (CmykColor cyan: 1 magenta: 0.3 yellow: 0 black: 0.3) | + | position: 10 @ 5 |
- | font: # | + | </ |
- | size: 12 | + | |
- | trackKerning: | + | |
- | withoutLeftSideBearing: | + | |
- | scale: 0.95 @ 1) | + | |
- | string: ' | + | |
- | position: 10 @ 5 | + | |
which renders itself as PDF with | which renders itself as PDF with | ||
- | ChartText>> | + | <code smalltalk> |
- | aPDFRenderer textRenderingMode: | + | ChartText>> |
- | aPDFRenderer fillColor: self style color. | + | aPDFRenderer textRenderingMode: |
- | aPDFRenderer textObjectDo: | + | aPDFRenderer fillColor: self style color. |
- | self style renderPDFOn: | + | aPDFRenderer textObjectDo: |
- | aPDFRenderer textMatrix: self pdfMatrixArray. | + | self style renderPDFOn: |
- | aPDFRenderer showString: (self pdfStringFor: | + | aPDFRenderer textMatrix: self pdfMatrixArray. |
+ | aPDFRenderer showString: (self pdfStringFor: | ||
+ | </ | ||
- | I did not open-source my graphics classes because they are specific to the needs of *smallCharts*. It does vector graphics and a bit of text as it is used for labels and such. For example | + | I did not open-source my graphics classes, because they are specific to the needs of smallCharts. It does vector graphics and a bit of text. For example, I have classes for horizontal and vertical lines, since charts use mostly those. My objects can only scale and translate, but not rotate - they don' |
I like to develop my abstractions from the bottom up and try to keep them as simple as possible. Maybe, over time, users will develop abstractions which are generally useful. In the end it should be a community discussion and consensus of what should be included. So far, only the bare metal on the spec will be available and you have to evolve your own abstractions. | I like to develop my abstractions from the bottom up and try to keep them as simple as possible. Maybe, over time, users will develop abstractions which are generally useful. In the end it should be a community discussion and consensus of what should be included. So far, only the bare metal on the spec will be available and you have to evolve your own abstractions. | ||
- | === Comments === | + | ===== Comments |
- | == Higher level abstractions == | + | ==== Higher level abstractions |
Submitted by bobcalco on Tue, 2012-01-24 10:32. | Submitted by bobcalco on Tue, 2012-01-24 10:32. | ||
Line 155: | Line 149: | ||
I know about this because I used an earlier version of Prawn to code a PDF generation feature of a content delivery system, which I am now needing to replace in Smalltalk, having decided to make the switch. I am a bit sad at the state of PDF generation in Smalltalk. There are so many other strengths in Smalltalk for the kind of distributed system I am building that wooed me over, but this deficiency is going to cost me some late nights and lamp oil. | I know about this because I used an earlier version of Prawn to code a PDF generation feature of a content delivery system, which I am now needing to replace in Smalltalk, having decided to make the switch. I am a bit sad at the state of PDF generation in Smalltalk. There are so many other strengths in Smalltalk for the kind of distributed system I am building that wooed me over, but this deficiency is going to cost me some late nights and lamp oil. | ||
- | == Here is a PDF manual == | + | ==== Here is a PDF manual |
Submitted by bobcalco on Tue, 2012-01-24 12:03. | Submitted by bobcalco on Tue, 2012-01-24 12:03. | ||
Line 163: | Line 157: | ||
http:// | http:// | ||
- | == Re: Higher level abstractions == | + | ==== Re: Higher level abstractions |
Submitted by ChristianHaider on Tue, 2012-01-24 11:58. | Submitted by ChristianHaider on Tue, 2012-01-24 11:58. | ||
Line 169: | Line 163: | ||
Interesting. I am curious what experiences you have while porting from Prawn to PDF4Smalltalk. Maybe some good concepts can be integrated... If you have any questions, please ask in the forum - sometimes I am responsive :-) | Interesting. I am curious what experiences you have while porting from Prawn to PDF4Smalltalk. Maybe some good concepts can be integrated... If you have any questions, please ask in the forum - sometimes I am responsive :-) | ||
- | == Thanks! == | + | ==== Thanks! |
Submitted by bobcalco on Tue, 2012-01-24 12:06. | Submitted by bobcalco on Tue, 2012-01-24 12:06. |
/var/www/virtual/code4hl/html/dokuwiki/data/pages/pdf/paintingapage.txt · Last modified: 2016/02/24 17:49 by christian