<?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//
 * @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;
    }
}
?>
