Skip to content

Text Flow

shaehn edited this page Dec 20, 2019 · 1 revision

Text Flow

Normally, each call to the text interface will produce a separate text box. However, with the addition of the flow option, multiple calls to text can be used to construct a more elaborate text box layout; one with differing characteristics for the text submitted with each call. This gives rise to the concept of text segments, where text keeps track of the position of the given segments, gluing them together.

The text flow mechanism can be activated using the flow:true option, or by not specifying position coordinates when making the text call. Termination of text segment gathering is done by supplying a flow:false value to the last text segment call, which may be an empty segment, or by making another text call with a new set of position coordinates. (Of course, if this newly positioned text is to also be using text flow, flow:false should be used to terminate the previous flow.) One important thing to remember is that the text characteristics are inheritable. For example, if the first text segment starts with red colored text, all subsequent calls will also use red text unless it is changed in the subsequent call(s).

Text Flow Examples

The following code will produce a paragraph of text on a letter sized document called flow-text.pdf (see picture below). The text is broken into 3 separate segments, coloring the separate segments differently and illustrating the default text background hiliting. Notice that no position coordinates are given to the text calls. When no initial positioning information is given, the default is to start and end at the document margins.

const HummusRecipe = require('hummus-recipe');
const recipe = new HummusRecipe('new', 'flow-text.pdf');
const lorem = 'Lorem ipsum dolor sit amet, ...';  // Not all shown here for simplicity.

recipe
   .createPage('letter')

   .line([[540,10],[540,300]], {lineWidth:.5})  // right margin marker
   .line([[72,72],[560,72]],   {lineWidth:.5})  // top margin marker

   .text(lorem.slice(0, 500))
   .text(lorem.slice(500,510), {color:'red', hilite:true})
   .text(lorem.slice(510),     {color:'green', hilite:false})  // turn off or it will continue
   .text('',{flow:false})      // stopping text flow

   .text('Simple Text Flow, 3 segments, showing color change and hilite',72,52,{color:'#000000'})
   .endPage()
   .endPDF();

Results in the contents of the file, flow-text.pdf, looking like :

Movedown, Hilite and BorderRadius

Following is a more complicated text flow example which produces an enclosed box. It shows how to produce line spacing gaps using the movedown interface, change the default hilite background color, font size and text colors.

Think of the movedown interface as a way of producing a newline character, setting the next text position to be on the following line starting at the first character position of the line. Without arguments, it assumes the positioning down 1 line (the next line). To produce a blank line between two paragraphs of text, use movedown(2), where the argument specifies the number of lines down the positioning is to occur.

Notice in the example that the hilite option can be given a non-boolean argument value to allow the user to change the color and opacity of the applied hilite.

Typically, the text box enclosure is a simple rectangle. With the borderRadius option, the enclosure can now be a rounded rectangular border. In general, the simple usage borderRadius:true is all that most would want to use. It automatically sets the borderRadius to a value of 5. However, there are other allowable values to control the 'roundness' of the corners. A simple numeric value will set the border radius to that value to be applied to all four corners. Alternatively, one could supply an array value of 4 numbers, one value for each corner indicating unique values for each corner. (Overkill, I am sure, but this feature is using the internal rectangle call to provide the drawing mechanism)

const HummusRecipe = require('hummus-recipe');
const recipe = new HummusRecipe('new', 'flow-textbox.pdf');

let x = 72;
let y = 300;
let w = 200;
let p = 4;    // text box padding
recipe
   .text(`This is a text box with a padding of ${p}, `, x, y, 
         {flow:true, hilite:true, textBox:{padding:p ,width: w, textAlign:'center'}})
   .text('with round box corners (standard radius is 5) ', 
         {color:'red', hilite:false})
   .movedown(2)
   .text('Did a movedown(2) to get ', {color:'blue', hilite:true})
   .text('text to this spot in box. Notice the text hiliting, which is different from "fill" for the text box. ', 
         {color:'green', size:14})
   .text('It can have different colors, with yellow being the default at opacity .5. See blue higlight below')
   .movedown(2)
   .text('Box was constructed with multiple text statements without specifying any x,y coordinates. ',
         {color:'blue', hilite:{color:"#81e6ff", opacity:.5}})
   .movedown()
   .text('Notice, here is a change in font size. ', {size:20,color:'#ff00ff',hilite:false})
   .text('',{flow:false, textBox:{style:{lineWidth:1, stroke:'red', borderRadius:true}}})
   .endPage()
   .endPDF();

Rotation and Fill still available

This example shows that the expected rotation and fill color mechanism still work for text boxes created with the 'flow' mechanism.

const HummusRecipe = require('hummus-recipe');
const recipe = new HummusRecipe('new', 'flow-textbox-rotated.pdf');

recipe
   .text('We can still handle rotation along',350, 375, 
        {hilite:{opacity:.9}, rotation:-30, flow:true, 
        textBox:{padding:5,width:100, textAlign:'center', 
        style:{stroke:'black', fill:'#9de3f2', borderRadius:true}}})
   .text('with text background fill coloring, and text centering.', {hilite:false})
   .text('', {flow:false});
   .endPage()
   .endPDF();