<?php
/**
 * File containing the ezcDocumentPdfTextBoxRenderer class
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 * @package Document
 * @version //autogen//
 * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 * @access private
 */

/**
 * Renders a single text box
 *
 * Tries to render a single text box into the available space, and aborts if
 * not possible.
 *
 * Implements the basic methods for tokenizing the text, style based text 
 * fitting into lines, etc. Should be extended by all classes implementing more 
 * specific text rendering algorithms, since those base methods are implemented 
 * generally enough to be reused.
 *
 * @package Document
 * @access private
 * @version //autogen//
 */
class ezcDocumentPdfTextBoxRenderer extends ezcDocumentPdfBlockRenderer
{
    /**
     * Render a single text box
     *
     * All markup inside of the given string is considered inline markup (in
     * CSS terms). Inline markup should be given as common docbook inline
     * markup, like <emphasis>.
     *
     * Returns a boolean indicator whether the rendering of the full text
     * in the available space succeeded or not.
     *
     * @param ezcDocumentPdfPage $page 
     * @param ezcDocumentPdfHyphenator $hyphenator 
     * @param ezcDocumentPdfTokenizer $tokenizer 
     * @param ezcDocumentLocateableDomElement $text 
     * @param ezcDocumentPdfMainRenderer $mainRenderer 
     * @return bool
     */
    public function renderNode( ezcDocumentPdfPage $page, ezcDocumentPdfHyphenator $hyphenator, ezcDocumentPdfTokenizer $tokenizer, ezcDocumentLocateableDomElement $text, ezcDocumentPdfMainRenderer $mainRenderer )
    {
        // Inference page styles
        $styles = $this->styles->inferenceFormattingRules( $text );
        $width  = $page->innerWidth / $styles['text-columns']->value -
            ( $styles['text-column-spacing']->value * ( $styles['text-columns']->value - 1 ) );

        // Evaluate available space
        if ( ( $space = $this->evaluateAvailableBoundingBox( $page, $styles, $width ) ) === false )
        {
            return false;
        }

        // Iterate over tokens and try to fit them in the current line, use
        // hyphenator to split words.
        $tokens = $this->tokenize( $text, $tokenizer );
        $lines  = $this->fitTokensInLines( $tokens, $hyphenator, $space->width );

        // Evaluate required space by text box
        $required = 0;
        foreach ( $lines as $line )
        {
            $required += $line['height'] * $styles['line-height']->value;
        }

        // Check that enough space is available to render text box
        if ( $required > $space->height )
        {
            return false;
        }
        $space->height = $required;

        $this->renderBoxBackground( $space, $styles );
        $this->renderBoxBorder( $space, $styles );
        $this->renderTextBox( $lines, $space, $styles );
        $this->setBoxCovered( $page, $space, $styles );
        return true;
    }

    /**
     * Render text box
     *
     * Render a single text box, specified by the given lines array,
     * containing tokens and their styles, the available space and
     * the styles array for the currently rendered element.
     *
     * Returns false, if the box size was not sufficant for the
     * given text, and the covered vertical area otherwise.
     *
     * @param array $lines
     * @param ezcDocumentPdfBoundingBox $space
     * @param array $styles
     * @return boolean
     */
    protected function renderTextBox( array $lines, ezcDocumentPdfBoundingBox $space, array $styles )
    {
        $yPos = $space->y;
        foreach ( $lines as $nr => $line )
        {
            $yPos += $this->renderLine( $yPos, $nr, $line, $space, $styles ) * $styles['line-height']->value;

            // Check if we run out of vertical space
            if ( $yPos > ( $space->y + $space->height ) )
            {
                return false;
            }
        }

        return $yPos - $space->y;
    }

    /**
     * Reverses a string
     *
     * Similar to PHPs strrev() function, but also works for UTF-8 strings.
     * 
     * @param string $string 
     * @return string
     */
    protected function strrev( $string )
    {
        if ( !is_string( $string ) || empty( $string ) )
        {
            return $string;
        }

        if ( strlen( $string ) === ( $length = iconv_strlen( $string, 'UTF-8' ) ) )
        {
            // String only contains of single-byte characters
            return strrev( $string );
        }

        $reverted = '';
        for ( $c = $length; $c > 0; --$c )
        {
            $reverted .= iconv_substr( $string, $c - 1, 1, 'UTF-8' );
        }
        return $reverted;
    }

    /**
     * Render a single line and return the used height
     *
     * @param float $position
     * @param int $number
     * @param array $line
     * @param ezcDocumentPdfBoundingBox $space
     * @param array $styles
     * @return void
     */
    protected function renderLine( $position, $number, array $line, ezcDocumentPdfBoundingBox $space, array $styles )
    {
        $spaceWidth = $this->driver->calculateWordWidth( ' ' );
        $lineWidth = 0;
        foreach ( $line['tokens'] as $token )
        {
            if ( !is_int( $token['word'] ) )
            {
                $lineWidth += $token['width'];
            }
        }

        // Reverse alignement, if direction is set to "right-to-left"
        $align = $styles['text-align']->value;
        if ( $styles['direction']->value === 'rtl' )
        {
            switch ( $align )
            {
                case 'right':
                    $align = 'left';
                default:
                    $align = 'right';
            }
        }

        switch ( $align )
        {
            case 'center':
                $offset = ( $space->width - $lineWidth - ( $line['spaces'] * $spaceWidth ) ) / 2;
                break;
            case 'right':
                $offset = $space->width - $lineWidth - ( $line['spaces'] * $spaceWidth );
                break;
            case 'justify':
                $offset = 0;
                switch ( true )
                {
                    case $number === $line['words']:
                        // Just use common space width in last line of a
                        // paragraph
                        $spaceWidth = $this->driver->calculateWordWidth( ' ' );
                        break;
                    case $line['words'] <= 1:
                        // Space width is irrelevant, if only one token is
                        // in the line
                        break;
                    default:
                        $spaceWidth = ( $space->width - $lineWidth ) / ( $line['spaces'] - 1 );
                }
            default:
                $offset = 0;
        }

        // Reverse tokens and words, if direction is set to "right-to-left"
        $tokens = $line['tokens'];
        if ( $styles['direction']->value === 'rtl' )
        {
            $tokens = array_reverse( $tokens );
            foreach ( $tokens as $nr => $token )
            {
                if ( is_string( $token['word'] ) )
                {
                    $tokens[$nr]['word'] = $this->strrev( $token['word'] );
                }
            }
        }

        // Default to left alignement
        $xPos = $space->x + $offset;
        foreach ( $tokens as $token )
        {
            if ( $token['word'] === ezcDocumentPdfTokenizer::SPACE )
            {
                $this->renderTextDecoration( $token['style'], $xPos, $position, $spaceWidth, $line['height'] );
                $this->handleLinks( $token, $xPos, $position, $spaceWidth, $line['height'] );

                $xPos += $spaceWidth;
            }
            else if ( is_string( $token['word'] ) )
            {
                $this->renderTextDecoration( $token['style'], $xPos, $position, $token['width'], $line['height'] );

                // Apply current styles
                foreach ( $token['style'] as $style => $value )
                {
                    $this->driver->setTextFormatting( $style, $value->value );
                }

                // Render word
                $this->driver->drawWord( $xPos, $position + $line['height'], $token['word'] );
                $this->handleLinks( $token, $xPos, $position, $token['width'], $line['height'] );
                $xPos += $token['width'];
            }
        }

        return $line['height'];
    }

    /**
     * Handle links
     *
     * Handle embedded link markup for current token and perform the
     * appropriate calls to the driver.
     * 
     * @param array $token 
     * @param float $x 
     * @param float $y 
     * @param float $width 
     * @param float $height 
     * @return void
     */
    protected function handleLinks( array $token, $x, $y, $width, $height )
    {
        if ( $token['url'] !== null )
        {
            $this->driver->addExternalLink( $x, $y, $width, $height * 1.1, $token['url'] );
        }

        if ( $token['target'] !== null )
        {
            $this->driver->addInternalLink( $x, $y, $width, $height * 1.1, $token['target'] );
        }
    }

    /**
     * Render text decoration
     *
     * Render text decoration, like by a assigned text-decoration setting, or
     * background-colors, and similar.
     * 
     * @param array $styles 
     * @param float $x 
     * @param float $y 
     * @param float $width 
     * @param float $height 
     * @return void
     */
    protected function renderTextDecoration( array $styles, $x, $y, $width, $height )
    {
        // Directly exit, if there are no decorations to render
        if ( ( $styles['text-decoration']->value === 'none' ) &&
             ( !isset( $styles['background-color'] ) ||
               ( $styles['background-color']->value['alpha'] >= 1 ) ) )
        {
            return;
        }

        if ( isset( $styles['background-color'] ) &&
             ( $styles['background-color']->value['alpha'] < 1 ) )
        {
            $this->driver->drawPolygon(
                array(
                    array( $x, $y ),
                    array( $x + $width, $y ),
                    array( $x + $width, $y + $height * $styles['line-height']->value ),
                    array( $x, $y + $height * $styles['line-height']->value ),
                ),
                $styles['background-color']->value
            );
        }

        if ( strpos( $styles['text-decoration'], 'line-through' ) !== false )
        {
            $this->driver->drawPolyline(
                array(
                    array( $x, $y + $height - $styles['font-size']->value / 3 ),
                    array( $x + $width, $y + $height - $styles['font-size']->value / 3 ),
                ),
                $styles['color']->value,
                // @todo: How thick should line-throughs be?
                ezcDocumentPcssMeasure::create( '1px' )->get(),
                false
            );
        }

        if ( strpos( $styles['text-decoration'], 'overline' ) !== false )
        {
            $this->driver->drawPolyline(
                array(
                    array( $x, $y ),
                    array( $x + $width, $y ),
                ),
                $styles['color']->value,
                // @todo: How thick should overlines be?
                ezcDocumentPcssMeasure::create( '1px' )->get(),
                false
            );
        }

        if ( strpos( $styles['text-decoration'], 'underline' ) !== false )
        {
            $this->driver->drawPolyline(
                array(
                    array( $x, $y + $height * 1.1 ),
                    array( $x + $width, $y + $height * 1.1 ),
                ),
                $styles['color']->value,
                // @todo: How thick should underlines be?
                ezcDocumentPcssMeasure::create( '1px' )->get(),
                false
            );
        }
    }

    /**
     * Tokenize the input string
     *
     * For proper word wrapping in the paragraph the strng needs to be
     * tokenized, while each token has to maintain its stack of assigned
     * formats.
     *
     * This method should return an array of tokens, also maintaining the
     * included whitespace characters, each associated with its markup
     * elements.
     *
     * @param ezcDocumentLocateableDomElement $element
     * @param ezcDocumentPdfTokenizer $tokenizer
     * @param bool $recursed
     * @return array
     */
    protected function tokenize( ezcDocumentLocateableDomElement $element, ezcDocumentPdfTokenizer $tokenizer, $recursed = false )
    {
        $tokens = array();
        $rules  = $this->styles->inferenceFormattingRules( $element, ezcDocumentPcssStyleInferencer::TEXT );

        // Do not inherit background and border rules from paragraph
        if ( !$recursed )
        {
            $rules = array_diff_key( $rules, array(
                'background-color' => true,
                'border'           => true,
            ) );
        }

        $url    = $element->tagName === 'ulink' && $element->hasAttribute( 'url'    ) ? $element->getAttribute( 'url'    ) : null;
        $target = $element->tagName === 'link'  && $element->hasAttribute( 'linked' ) ? $element->getAttribute( 'linked' ) : null;

        foreach ( $element->childNodes as $child )
        {
            switch ( $child->nodeType )
            {
                // case XML_CDATA_SECTION_NODE:
                case XML_TEXT_NODE:
                    $words = $tokenizer->tokenize( $child->textContent );
                    foreach ( $words as $word )
                    {
                        $tokens[] = array(
                            'word'   => $word,
                            'style'  => $rules,
                            'url'    => $url,
                            'target' => $target,
                        );
                    }
                    break;

                case XML_ELEMENT_NODE:
                    $tokens = array_merge(
                        $tokens,
                        $this->tokenize( $child, $tokenizer, true )
                    );
                    break;
            }
        }

        if ( !$recursed )
        {
            // Remove double spaces
            foreach ( $tokens as $nr => $token )
            {
                if ( ( $token['word'] === ezcDocumentPdfTokenizer::SPACE ) &&
                     isset( $tokens[$nr + 1] ) &&
                     ( $tokens[$nr + 1]['word'] === ezcDocumentPdfTokenizer::SPACE ) )
                {
                    $i = 1;
                    do {
                        unset( $tokens[$nr + $i] );
                    } while ( isset( $tokens[$nr + ( ++$i )] ) &&
                              ( $tokens[$nr + $i]['word'] === ezcDocumentPdfTokenizer::SPACE ) );
                }
            }
            $tokens = array_values( $tokens );

            // Remove optional starting spaces
            if ( count( $tokens ) &&
                 ( $tokens[0]['word'] === ezcDocumentPdfTokenizer::SPACE ) )
            {
                $tokens = array_slice( $tokens, 1 );
            }
        }

        return $tokens;
    }

    /**
     * Force split a word.
     *
     * Force the splitting of a word, which did not fit in a line alone and
     * could not be splitted using the hyphenator. We just search for the
     * maximum word part length which fits the available space.
     *
     * Could be improved to use a binary search on the word length, but this
     * shouldn't happen too often anyways.
     * 
     * @param string $word 
     * @param float $available 
     * @return array
     */
    protected function forceSplit( $word, $available )
    {
        $length = iconv_strlen( $word ) - 1;
        while ( $this->driver->calculateWordWidth( iconv_substr( $word, 0, $length ) ) > $available )
        {
            --$length;
        }

        return array(
            iconv_substr( $word, 0, $length ),
            iconv_substr( $word, $length )
        );
    }

    /**
     * Try to match tokens into lines
     *
     * Try to match tokens into lines of the given width. Returns an array with
     * words for each line. The words might already be split up by the
     * hyphenator.
     *
     * @param array $tokens
     * @param ezcDocumentPdfHyphenator $hyphenator
     * @param float $available
     * @return array
     */
    protected function fitTokensInLines( array $tokens, ezcDocumentPdfHyphenator $hyphenator, $available )
    {
        $lines    = array( array(
            'tokens' => array(),
            'height' => 0,
            'words'  => 0,
            'spaces' => 0,
        ) );
        $line     = 0;
        $consumed = 0;
        while ( $token = array_shift( $tokens ) )
        {
            // Handle forced line breaks
            if ( $token['word'] === ezcDocumentPdfTokenizer::FORCED )
            {
                // Continue rendering in next line
                $consumed = 0;
                $lines[++$line] = array(
                    'tokens' => array(),
                    'height' => 0,
                    'words'  => 0,
                    'spaces' => 0,
                );
                continue;
            }

            // Pure wrapping tokens are irrleveant to width calculation
            if ( $token['word'] === ezcDocumentPdfTokenizer::WRAP )
            {
                continue;
            }

            // Apply current styles
            foreach ( $token['style'] as $style => $value )
            {
                // Only pass whitelist of properties to the backend. This is not really 
                // the right place to do this, but it reduces the amount of calls to 
                // the backend and the size of the call log massively.
                if ( !( ( $style === 'font-style' ) ||
                        ( $style === 'font-weight' ) ||
                        ( $style === 'color' ) ||
                        ( $style === 'font-size' ) ||
                        ( $style === 'font-family' ) ) )
                {
                    continue;
                }

                $this->driver->setTextFormatting( $style, $value->value );
            }

            // Just add space to consumed wird width
            if ( $token['word'] === ezcDocumentPdfTokenizer::SPACE )
            {
                if ( $consumed > 0 )
                {
                    $consumed += $width = $this->driver->calculateWordWidth( ' ' );
                    $token['width']           = $width;
                    $lines[$line]['tokens'][] = $token;
                    $lines[$line]['spaces']++;
                }
                continue;
            }

            $wordStack = array(
                'tokens' => array(),
                'height' => 0,
                'words'  => 0,
                'spaces' => 0,
            );
            $wConsumed = 0;
            do {
                if ( ( $consumed + $wConsumed + ( $width = $this->driver->calculateWordWidth( $token['word'] ) ) ) < $available )
                {
                    // The word just fits into the current line
                    $token['width']        = $width;
                    $wordStack['tokens'][] = $token;
                    $wordStack['height']   = max( $lines[$line]['height'], $this->driver->getCurrentLineHeight() );
                    $wordStack['words']++;
                    $wConsumed            += $width;
                    
                    if ( !isset( $tokens[0] ) ||
                         ( $tokens[0]['word'] === ezcDocumentPdfTokenizer::WRAP ) ||
                         ( $tokens[0]['word'] === ezcDocumentPdfTokenizer::FORCED ) ||
                         ( $tokens[0]['word'] === ezcDocumentPdfTokenizer::SPACE ) )
                    {
                        // We are allowed to wrap, so we can continue with the
                        // next iteration and merge the current word stack with
                        // the line array.
                        $lines[$line]['tokens'] = array_merge( $lines[$line]['tokens'], $wordStack['tokens'] );
                        $lines[$line]['height'] = max( $lines[$line]['height'], $wordStack['height'] );
                        $lines[$line]['words'] += $wordStack['words'];
                        $consumed              += $wConsumed;
                        continue 2;
                    }

                    continue;
                }

                // Try to hyphenate the current word
                $hyphens = array_reverse( $hyphenator->splitWord( $token['word'] ) );
                foreach ( $hyphens as $hyphen )
                {
                    if ( ( $consumed + $wConsumed + ( $width = $this->driver->calculateWordWidth( $hyphen[0] ) ) ) < $available )
                    {
                        $second         = $token;
                        $second['word'] = $hyphen[1];
                        array_unshift( $tokens, $second );

                        $token['width']           = $width;
                        $token['word']            = $hyphen[0];
                        $lines[$line]['tokens'] = array_merge( $lines[$line]['tokens'], $wordStack['tokens'], array( $token ) );
                        $lines[$line]['height'] = max( $lines[$line]['height'], $wordStack['height'], $this->driver->getCurrentLineHeight() );
                        $lines[$line]['words'] += $wordStack['words'] + 1;

                        // Continue rendering in next line
                        $consumed = 0;
                        $lines[++$line] = array(
                            'tokens' => array(),
                            'height' => 0,
                            'words'  => 0,
                            'spaces' => 0,
                        );
                        continue 3;
                    }
                }

                if ( ( $consumed + $wConsumed ) <= 0 )
                {
                    // If we are already at the beginning of the line, and the
                    // word does still not fit, we forcefully split the word.
                    $hyphen = $this->forceSplit( $token['word'], $available );

                    $second         = $token;
                    $second['word'] = $hyphen[1];
                    array_unshift( $tokens, $second );

                    $token['width']         = $this->driver->calculateWordWidth( $hyphen[0] );
                    $token['word']          = $hyphen[0];
                    $lines[$line]['tokens'] = array( $token );
                    $lines[$line]['height'] = $this->driver->getCurrentLineHeight();
                    $lines[$line]['words']  = 1;

                    // Continue rendering in next line
                    $consumed = 0;
                    $lines[++$line] = array(
                        'tokens' => array(),
                        'height' => 0,
                        'words'  => 0,
                        'spaces' => 0,
                    );
                    continue 2;
                }

                // Did not fit using hyphenation, so retry after wrapping
                // the current word stack into the next line.
                array_unshift( $tokens, $token );

                // Still does not fit, move whole word stack into the next line
                // and try again
                $token['width'] = $width = $this->driver->calculateWordWidth( $token['word'] );
                $lines[++$line] = $wordStack;
                $consumed       = $wConsumed;
                continue 2;
            } while ( $token = array_shift( $tokens ) );
        }

        return $lines;
    }
}
?>
