Flow layout API

Revision as of 16:17, 5 June 2018 by Adminko (talk | contribs) (Available style properties)
Jump to: navigation, search


This API provides a new way to generate PDF files programmatically. In opposite to Fixed layout API, designed to be as close as possible to PDF specification, Flow layout API provides you with a number of high-level content building blocks e.g. TextBlock, Grid, Image which can be placed on a page and automatically positioned using so-called layout rules. The layout engine analyzes various properties of these content elements and then logically processes them according to the layout rules generating the resulting PDF document. Properties of these content elements can be assigned directly or defined by styles, thus it becomes possible to easily manage groups of objects with similar properties by changing corresponding style objects.

A process called style matching assigns a style to a particular object(content building block) based on style selector – a rule that defines which elements should be affected by this style. It works similar to HTML+CSS and one familiar with the latter can easily use one's experience and build PDF documents within a minute or even quicker. Actually, styles and content element are so native and easy to work with that we would recommend using it for generating of quickly changing and repetitive content, e.g. invoices, bills, reports, forms etc.

A list of supported features is rather big and we’d recommend checking code samples included along with the download package and showing the full power of Apitron PDF Kit and its Flow layout API in action. To name a few, it supports floating text, automatic pagination of grids and sections, ordered and unordered lists with various types of markers (including nested lists), text justification, dynamic content generation, automatic links and bookmarks creation and much more. It can even be mixed with elements from Fixed layout API.

This API is built around FlowDocument class and it’s possible to save created layout as XML template and load from it. It separates document design from actual processing and can be used to alter document appearance and introduce future changes without(!) recompiling the application.

Creating simple PDF document

Let's see how to create a simple PDF document with “Hello world” message on the first page using Flow layout API.

Consider the following code:

// create output file
using (Stream outputStream = File.Create("hello_world.pdf"))
    // create new document
    FlowDocument document = new FlowDocument()
    // add textual content element
    document.Add(new TextBlock("Hello world using flow layout API"));

    // save to output stream with page size A4
    document.Write(outputStream,new ResourceManager(), new PageBoundary(Boundaries.A4));    

Here you can see the basics of flow layout workflow, we create FlowDocument instance first, then we fill it with some content (simple TextBlock is used in this sample) and at the end we write it as PDF document to the output stream.

For writing we need an output stream, a ResourceManager instance that holds all resource objects used in the document (empty in our case) and PageBoundary object describing page dimensions. All pages in the target document will have the same dimensions unless they’re explicitly adjusted using techniques described in the article change page size and styles on the fly. As you can see, there is no notion of any style object or explicit property usage in this code sample. It was made intentionally to give you a very brief overview and a valid PDF document before moving on to more advanced topics.

And the results of the execution can be seen on the image below:

Create simple PDF file using flow layout API

Box model and layout basics

Flow Layout API uses a slightly modified traditional box model to define its content elements. Vertically infinite canvas limited by page width in horizontal dimension is used to layout them and to form the content of the resulting PDF document. The box model used by the Flow layout API assumes that margin, border and padding are inside the box defined by the element's width and height. See the image below:

Box model used by the Flow layout API

A content element gets rendered within its box and later placed on a page according to the layout rules and corresponding properties. It’s important to note that every element will always have implicit box even if you don’t specify its dimensions. One of the important properties, affecting the layout of the element, is Display. It specifies whether the element should be processed as:

  • Block – creating a line break before and after
  • Inline – added to the current line
  • InlineBlock – a special kind of Block element that doesn’t create line breaks
  • None - shouldn’t be processed at all

The main difference between Block, InlineBlock and Inline elements is that pure inline elements can’t be sized explicitly by setting their dimensions. It will be ignored the same way as HTML processors do. In addition several style properties can be inherited only by Block elements (actually a very few of them) and it will be discussed later in section Available style properties.

Main type used for specifying various elements' dimensions in Flow layout API is Length. Its constructor accepts values given in points, pixels, centimeters, inches, %'s and a special value Auto that depends on the context where it's used.

Style system

Style definition

Every content element or control element in Flow layout API has the same set of properties affecting its appearance and behavior at the time of processing. This set is called a style and can be of two kinds:

  • Internal style, holding the properties you can set directly using the object's instance. (inline styles are the closest alternative from the HTML/CSS world)
  • Matched style, provided by the style manager owned by the FlowDocument object instance and assigned using the specific selector

Style and StyleManager relationship

A Style class works as properties container and StyleManager class as document's style manager. FlowDocument class has a special property called StyleManager and all necessary styles should be added by means of this property.

A style however doesn’t come alone. It has a linked selector, an object that describes which elements should be affected by this particular style. In our case, a selector is a string written using the special syntax that defines which elements to match. If you ever worked with HTML and CSS then the syntax of these selectors will look familiar to you.

In short, the workflow is as follows:

  • Define styles and content elements that should be matched
  • Add styles to the flow document's StyleManager
  • Add content elements to the FlowDocument object
  • Save the result as PDF document or convert to FixedDocument instance if needed for further processing

It saves lots of time and code, and is a straightforward way to generate complex PDF content very quickly.

Selectors and style matching

Selector – is a rule that defines which elements should be matched and styled using the given style, it looks very similar to the notation used for CSS and is linked to a property set defined by the accompanying Style object.

Supported selectors:

  • Universal selector (“*”), selects all elements in a document or all children of a given element if used with child selector
  • Type selector (“_typename_”), selects all elements of the given type. E.g. “textbox”. It's possible to list several types using a comma, e.g. "textbox, section, image"
  • Class selector (“.classname”), selects all elements that belong to a specific class. E.g. “*.myclass” selects all elements with class “myclass”. Because element can have multiple classes set, it is possible to specify several classes in one selector, for example “*.myclass1.myclass2”
  • Id selector (“#elementID”). An element can have an id set - a special property usually used as a unique tag, and this selector matches the element with specific id.
    “texbox#help”, selects the textbox element with Id=“help”
  • Child selector (“[ancestor]>child”), selects all elements which are immediate children of specied ancestor element, square brackets indicate optionality of the ancestor, in case of absence it will behave as if a universal selector(“*”) was used instead
    “> textbox” – same as “textbox”, selects all textboxes which are children of any element,
    “section > textbox ” – select all textboxes which are placed in sections,
    “flowdocument > section> textbox.subheader” – selects all textboxes with the class ”subheader” set, nested in any section that is an immediate child of the document element(root)
  • Descendant selector (“element_1 element_2”) selects all elements which are descendants of a given element
    “section#header image” – selects all images in section with ID=”header” regardless of the inclusion level
  • Adjacent element selector (“predessor + element”), selects the element that precedes some element
    “image + textbox” – selects all images that precede a textbox.

How the styles are being resolved (rules of style matching):

  1. Directly assigned value is requested first. It's the value you set using any arbitrary property of the content element.
  2. If no value is set using p.1, the system tries to find the value using the registered selectors and styles
    1. look for all selectors that match given element
    2. select value according to matching rules (these rules are: specificity of the selector and order of addition, if specificity is the same, order is used)
  3. Request parent's value if property is inheritable using the same scheme

In general, this style system is close to CSS used with HTML, so one familiar with the latter can easily find similarities.

Available style properties

There are 36 different properties defined in Style class, plus some of the content elements may have their own specific properties which are not necessary related to style system but can be used to control their layout. It provides great flexibility and provides endless ways for the generation of PDF documents.

Each property defined in the Style class is explained below to give you an overview of the style system and how this properties interact with it, while custom content elements' properties are desctibed in the section Content elements and controls.

Layout-specific properties

  • Align - gets or sets the horizontal alignment of the element content, it can be Left, Right, Center or Justified. Only acceptable for block elements, this property will be ignored if the element is not a block-level element. Left, Right and Center values are supported by all elements. In case of Justify is used – only text elements will be affected. All elements inherit value from their block containers; only block elements can override parent's Align setting.
  • Clear - gets or sets the clear flag for the element indicating whether it should ignore floating elements (if any) and start a new line. Not inheritable.
  • Float - gets or sets the value indicating that element can float. Not inheritable.
  • Display - gets or sets the display setting for the element. Not inheritable.
  • Height - gets or sets the height of the element. Not inheritable.
  • Width - gets or sets the width of the element. Not inheritable.
  • LineHeight - gets or sets the height of the for the container line. For a block container element with content composed of inline-level elements, 'line-height' specifies the minimal height of line boxes within the element. On a non-inline element, 'line-height' specifies the height that is used in the calculation of the line box height. Inheritable.
  • Margin - gets or sets the margin around the element. Not inheritable.
  • Padding - gets or sets the padding. Not inheritable.
  • VerticalAlign - gets or sets the vertical align. Not inheritable.

Text-specific properties

  • Color - gets or sets the foreground color for the element. Inheritable.
  • CharacterSpacing - gets or sets the character spacing. Inheritable.
  • Font - gets or sets the font for the element. Inheritable.
  • ScriptLevel - gets or sets the value used to create subscripting or superscripting effect. It defines the level of effect, zero can be used for normal scripting, positive values are for superscripting, negative for subscripting. Affects textual elements. Not inheritable.
  • TextDecoration - gets or sets the text decoration. Inheritable.
  • TextIndent - gets or sets the text indent. Inheritable.
  • TextRenderingMode - gets or sets the text rendering mode used to draw textual elements. By default all text is being drawn using Fill setting. Inheritable.
  • WordSpacing - gets or sets the word spacing. Inheritable.

Background-specific properties

  • Background - gets or sets the background color. Not inheritable.
  • BackgroundImage - gets or sets the background image for the element. The background area of an element takes the total space occupied by the element content, including padding (but not the margin and border). By default, a background-image is placed at the top-left corner of the element, and repeated both vertically and horizontally. Not inheritable.
  • BackgroundPosition - gets or sets the background position value for the element. The background position property sets the starting position of a background image. Not inheritable.
  • BackgroundRepeat - gets or sets the background repeat value for the element. The background repeat property sets if/how a background image will be repeated. By default, background image is repeated both vertically and horizontally. Not inheritable.

Grid-specific properties

  • CellPadding - gets or sets the cell padding, affects only Grid elements. Not inheritable.
  • InnerBorder - gets or sets the inner border, affects only Grid elements. Not inheritable.
  • InnerBorderColor - gets or sets the color of the inner border affects only Grid elements. Not inheritable.

List-specific properties

  • ListCounter - gets or sets the list counter. Not inheritable.
  • ListMarker - gets or sets the list marker appearance. Inheritable.
  • ListMarkerPadding - gets or sets the list marker padding. Inheritable.
  • ListStyle - gets or sets the list style. Not inheritable.

Use type selector to style a text block

This code sample demonstrates basic usage of style system and assigns the same style to all textblocks in a flow document using the type selector:

// create output file
using (Stream outputStream = File.Create("selectors.pdf"))
    // create new document
    FlowDocument document = new FlowDocument();
    // register style that matches all textblocks and sets their text color
    document.StyleManager.RegisterStyle("textblock", new Style(){Color = RgbColors.Red});
    // add textual content element
    document.Add(new TextBlock("A textblock with red text"));
    // add textual content element and directly set its property overriding the matched style
    document.Add(new TextBlock("A textblock with black text"){Color = RgbColors.Black});
    // save to output stream with page size A4
    document.Write(outputStream, new ResourceManager(), new PageBoundary(Boundaries.A4));

You see from the code that we defined a type selector that matches all textblocks in the document. But according to the Rule #1 of style matching (see selectors and style matching) the second text box will have its color assigned to black, because any direct property assignment overrides the value provided by a matching style.

The results are shown on the image below:

Text block styled using type selector

Content elements and controls

Content elements, as the name suggests, are the building blocks for the flow document's content. They all have the same set of properties, but may handle them differently depending on their nature. All content elements are inherited from a single base class ContentElement.

The following content elements are supported at the moment:

  • Textblock – for adding textual content
  • Image – for adding images
  • Br – indicates that line break should be created between the elements
  • Hr – creates a horizontal line much like in HTML
  • Section – container, for grouping elements together and creating lists
  • Grid - for a creation of grids, support column and row spans
  • PageCount – control that displays a number of pages in the document
  • PageBreak – indicates that a page break needs to be generated
  • ContentReference – used to place reusable pieces of content created with FlowContent, FixedContent or Image resource objects

Control elements, or simply controls are special content elements designed to build forms. From the PDF point of view, they produce widget annotation objects (see this article describing interactive forms for the details) and should have backing fields created for them. But you don’t have to worry about how content elements or controls are being wrapped to PDF entities, because almost all PDF specific operations are implemented under the hood and managed by the Apitron PDF Kit library automatically.

The following control elements are supported at the moment:

  • TextBox – used to create editable text fields that user can use for entering text
  • PushButton – a button that can have various Actions assigned (see Actions article to know more)
  • RadioButton – a control providing a way to choose a single item from a group
  • Choice – works much like a combo box or a list box depending on its properties
  • CheckBox – provides a way to create various check boxes in PDF form
  • SignatureControl – can be used to provide a visual representation for a signature field in Flow layout API context, see also this code sample explaining how signature mechanics are working implemented using Fixed layout API)