View Source

<h1>Introduction.</h1>

<p>There was a lot of requests for tables, text blocks, headers, footnotes and other text decoration Zend_Pdf functionality in ZF mailing lists. </p>

<p>Some abstract document model has to be developed to make all these functionality consistent and completed.</p>

<p>Good candidate is a document model lain under XSL-FO standard (<a href="http://www.w3.org/TR/xsl/">http://www.w3.org/TR/xsl/</a>).</p>


<p>The idea is not just to implement XSL-FO =&gt; PDF transformation, but to develop an API which utilizes XSL-FO document model features.</p>

<p>Such API should be extended step by step to completely cover XSL-FO standard, but it's a question of future development. First goal is to provide standard text decoration functionality.</p>


<p>Here is a draft of the API, which is intended for discussion.</p>


<h1>Base concepts.</h1>

<p>Abstract document model doesn't depend on Zend_Pdf implementation and in principle may be taken out into a separate module (Zend_Document ???).<br />
Nevertheless it may use some Zend_Pdf objects as an input. Ex. fonts may be specified by name (<em>'Helvetica'</em>) or by font object (<em>Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA)</em>)</p>

<p>Drawing output is organized into sequenced <strong>pages</strong>.</p>

<p><strong>Output pages</strong> may be directly transformed into Zend_Pdf_Page objects and attached to PDF document (Zend_Pdf object)<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{footnote}Zend_Pdf has to be extended with possibility to redraw one existing page into some area of another page. It's easy to implement using PDF canvases. It will allow to use existing page as a drawing output.{footnote}]]></ac:plain-text-body></ac:macro>.</p>

<p>Each <strong>output page</strong> is constructed using named <strong>page template</strong> and <strong>content</strong>.</p>

<p>There are two types of <strong>page templates</strong>: <strong>simple page layout</strong> (corresponds to '<a href="http://www.w3.org/TR/2006/REC-xsl11-20061205/#fo_simple-page-master">/fo:root/fo:o:layout-master-set/fo:simple-page-master</a>' objects) and <strong>page sequence layout</strong> (corresponds to '<a href="http://www.w3.org/TR/2006/REC-xsl11-20061205/#fo_page-sequence-master">/fo:root/fo:o:layout-master-set/fo:page-sequence-master</a>' objects).</p>

<p><strong>Simple page layout</strong> templates define pages size, orientation, regions (see <a href="http://www.w3.org/TR/2006/REC-xsl11-20061205/#fo_simple-page-master">fo:simple-page-master</a> and <a href="http://www.w3.org/TR/2006/REC-xsl11-20061205/#fo_region-body">fo:region-body</a> descriptions), margins, number of columns in the body region and so on. <br />
<strong>Page sequence layout</strong> templates allow to construct sequences of pages with a special layout for first N pages, odd/even pages, blank pages and so on.</p>


<p><strong>Content</strong> is organized into pages using specified <strong>page layout</strong>. The result is a <strong>sequence</strong> of <strong>output pages</strong>.<br />
There are two types of the content:</p>
<ul>
<li><strong>static</strong> content is applied to all pages in a <strong>sequence</strong> containing specified <strong>region</strong><ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{footnote}It allows to specify different static content to different pages in a sequence.{footnote}]]></ac:plain-text-body></ac:macro>.</li>
<li><strong>content flow</strong> is a common content which is written to the specified region.</li>
</ul>


<p><strong>Content</strong> consists of a sequence of <strong>text blocks</strong> (<strong>paragraphs</strong>), <strong>tables</strong> or <strong>list blocks</strong>.<br />
Each <strong>block</strong> has a common set of text decoration options: font, font size, font style, alignment, color, line spaces and so on. Take a look at <a href="http://www.w3.org/TR/2006/REC-xsl11-20061205/#fo_block">fo:block</a> to see full list of allowed properties.</p>

<p><strong>Blocks</strong> may be organized into <strong>block containers</strong> (<a href="http://www.w3.org/TR/2006/REC-xsl11-20061205/#fo_block">fo:block-container</a>). <strong>Block container</strong> may also be absolutely positioned on a page.</p>

<p>Each <strong>block</strong> may contain plain text as well as other block level formatting objects (separate <strong>characters</strong>, <strong>images</strong>, <strong>inline areas</strong> and so on, take a look at <a href="http://www.w3.org/TR/2006/REC-xsl11-20061205/#d0e9759">Inline-level Formatting Objects</a> for more details).</p>


<h1>API</h1>
<p>It's a draft version of class skeletons, and it's intended to be discussed</p>

<ac:macro ac:name="code"><ac:plain-text-body><![CDATA[
/**
* fo:block object
* ...
*/
class Zend_Pdf_ContentBlock
{
/**
* $style parameter is an optional properties array
*
* @param array|null $style
*/
public function __constructor($style = null);

/**
* $style parameter is an optional properties array
*
* @param string|Zend_Pdf_InlineContent $inlineContent
*/
public function draw($inlineContent);
}


/**
* fo:block-container object
* ...
*/
class Zend_Pdf_ContentBlockContainer
{
/**
* $style parameter is an optional properties array
*
* @param array|null $style
*/
public function __constructor($style = null);

/**
* @param Zend_Pdf_ContentBlock $block
*/
public function addBlock(Zend_Pdf_ContentBlock $block);
}


/**
* Page layout
* ...
*/
class Zend_Pdf_ContentPageLayout
{
/**
* $layout parameter is an associative array of regions options:
* array( 'region-body' => array('margin' => '1in 1.5in',
* 'column-count => '2',
* 'column-gap' => '0.5in'),
* 'region-start' => array('extent' => '1.5in',
* 'region-name' => 'my-left-sidebar',
* 'padding' => '6pt 1in')
* )
*
* @param array $layout
*/
public function __constructor($layout);
}

/**
* Page sequence layout
* ...
*/
class Zend_Pdf_ContentPageLayout_Sequence extends Zend_Pdf_ContentPageLayout
{
public function __constructor();

public function addSinglePageLayput(Zend_Pdf_ContentPageLayout $template);

public function addRepeatablePageLayout(Zend_Pdf_ContentPageLayout $template);

/**
* $alternatives parameter is an associative array of alternative layouts:
* array( 'odd' => new Zend_Pdf_ContentPageLayout($oddPageLayout),
* 'even' => new Zend_Pdf_ContentPageLayout($evenPageLayout),
* )
*
* @param array $alternatives
*/
public function addRepeatablePageLayoutAlternatives($alternatives);
}


/**
* Content flow
* ...
*/
class Zend_Pdf_ContentFlow
{
public function __constructor();

public function addBlock(Zend_Pdf_ContentBlock $block);

public function addBlockContainer(Zend_Pdf_ContentBlockContainer $blockContainer);

public function addTable(Zend_Pdf_ContentTable $table}

public function addListBlockContainer(Zend_Pdf_ContentListBlock $blockContainer);
}

/**
* Page drawing class
* ...
*/
class Zend_Pdf_ContentPageSequence
{
public function __constructor(Zend_Pdf_ContentPageLayout $layout);

public function setStaticContent($regionName, Zend_Pdf_ContentBlock $block);

public function addFlow($regionName, Zend_Pdf_ContentFlow $contentFlow);

/**
* Performs drawing
*
* Returns an array of Zend_Pdf_Page objects
*
* @return array
*/
public function generate();
}

]]></ac:plain-text-body></ac:macro>


<h1>Use cases</h1>

<p>To be continued...</p>

<p>------------------------------------------------</p>
<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac:plain-text-body><![CDATA[{display-footnotes}]]></ac:plain-text-body></ac:macro>