Browse Source

Zend_Pdf: Ascii85 filter encoding/decoding support. ZF-8581.

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@19745 44c647ce-9c0f-0410-b52a-842ac1e357ba
alexander 16 years ago
parent
commit
9307b70488

+ 123 - 4
library/Zend/Pdf/Filter/Ascii85.php

@@ -42,8 +42,65 @@ class Zend_Pdf_Filter_Ascii85 implements Zend_Pdf_Filter_Interface
      */
     public static function encode($data, $params = null)
     {
-        require_once 'Zend/Pdf/Exception.php';
-        throw new Zend_Pdf_Exception('Not implemented yet');
+        $output = '';
+        $dataLength = strlen($data);
+
+        for ($i = 0; $i < $dataLength; $i += 4) {
+            //convert the 4 characters into a 32-bit number
+            $chunk = substr($data, $i, 4);
+
+            if (strlen($chunk) < 4) {
+                //partial chunk
+                break;
+            }
+
+            $b = unpack("N", $chunk);
+            $b = $b[1];
+
+            //special char for all 4 bytes = 0
+            if ($b == 0) {
+                $output .= 'z';
+                continue;
+            }
+
+            //encode into 5 bytes
+            for ($j = 4; $j >= 0; $j--) {
+                $foo = (int) (($b / pow(85,$j)) + 33);
+                $b %= pow(85,$j);
+                $output .= chr($foo);
+            }
+        }
+
+        //encode partial chunk
+        if ($i < $dataLength) {
+            $n = $dataLength - $i;
+            $chunk = substr($data, -$n);
+
+            //0 pad the rest
+            for ($j = $n;$j < 4;$j++) {
+                $chunk .= chr(0);
+            }
+
+            $b = unpack("N", $chunk);
+            $b = $b[1];
+
+            //encode just $n + 1
+            for ($j = 4; $j >= (4 - $n); $j--) {
+                $foo = (int) (($b / pow(85,$j)) + 33);
+                $b %= pow(85,$j);
+                $output .= chr($foo);
+            }
+        }
+
+        //EOD
+        $output .= '~>';
+
+        //make sure lines are split
+        $output = chunk_split($output, 76, "\n");
+
+        //get rid of new line at the end
+        $output = substr($output, 0, -1);
+        return $output;
     }
 
     /**
@@ -56,7 +113,69 @@ class Zend_Pdf_Filter_Ascii85 implements Zend_Pdf_Filter_Interface
      */
     public static function decode($data, $params = null)
     {
-        require_once 'Zend/Pdf/Exception.php';
-        throw new Zend_Pdf_Exception('Not implemented yet');
+        $output = '';
+
+        //get rid of the whitespaces
+        $whiteSpace = array("\x00", "\x09", "\x0A", "\x0C", "\x0D", "\x20");
+        $data = str_replace($whiteSpace, '', $data);
+
+        if (substr($data, -2) != '~>') {
+            require_once 'Zend/Pdf/Exception.php';
+            throw new Zend_Pdf_Exception('Invalid EOF marker');
+            return '';
+        }
+
+        $data = substr($data, 0, (strlen($data) - 2));
+        $dataLength = strlen($data);
+
+        for ($i = 0; $i < $dataLength; $i += 5) {
+            $b = 0;
+
+            if (substr($data, $i, 1) == "z") {
+                $i -= 4;
+                $output .= pack("N", 0);
+                next;
+            }
+
+            $c = substr($data, $i, 5);
+
+            if(strlen($c) < 5) {
+                //partial chunk
+                break;
+            }
+
+            $c = unpack('C5', $c);
+            $value = 0;
+
+            for ($j = 1; $j <= 5; $j++) {
+                $value += (($c[$j] - 33) * pow(85, (5 - $j)));
+            }
+
+            $output .= pack("N", $value);
+        }
+
+        //decode partial
+        if ($i < $dataLength) {
+            $value = 0;
+            $chunk = substr($data, $i);
+            $partialLength = strlen($chunk);
+
+            //pad the rest of the chunk with u's
+            //until the lenght of the chunk is 5
+            for ($j = 0; $j < (5 - $partialLength); $j++) {
+                $chunk .= 'u';
+            }
+
+            $c = unpack('C5', $chunk);
+
+            for ($j = 1; $j <= 5; $j++) {
+                $value += (($c[$j] - 33) * pow(85, (5 - $j)));
+            }
+
+            $foo = pack("N", $value);
+            $output .= substr($foo, 0, ($partialLength - 1));
+        }
+
+        return $output;
     }
 }

+ 2 - 0
tests/Zend/Pdf/Filter/AllTests.php

@@ -26,6 +26,7 @@ if (!defined('PHPUnit_MAIN_METHOD')) {
 require_once 'PHPUnit/Framework/TestSuite.php';
 require_once 'PHPUnit/TextUI/TestRunner.php';
 
+require_once 'Zend/Pdf/Filter/Ascii85Test.php';
 require_once 'Zend/Pdf/Filter/RunLengthTest.php';
 
 /**
@@ -47,6 +48,7 @@ class Zend_Pdf_Filter_AllTests
     {
         $suite = new PHPUnit_Framework_TestSuite('Zend Framework - Zend_Pdf_Filter');
 
+        $suite->addTestSuite('Zend_Pdf_Filter_Ascii85Test');
         $suite->addTestSuite('Zend_Pdf_Filter_RunLengthTest');
 
         return $suite;

+ 75 - 0
tests/Zend/Pdf/Filter/Ascii85Test.php

@@ -0,0 +1,75 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Pdf
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Zend_Pdf_Filter_Ascii85
+ */
+require_once 'Zend/Pdf/Filter/Ascii85.php';
+
+/**
+ * PHPUnit Test Case
+ */
+require_once 'PHPUnit/Framework/TestCase.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Pdf
+ * @subpackage UnitTests
+ * @copyright  Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @group      Zend_Pdf
+ */
+class Zend_Pdf_Filter_Ascii85Test extends PHPUnit_Framework_TestCase
+{
+    public function testStringDivisibleBy4Encode()
+    {
+        $decodedContents = "Lorem ipsum dolor sit amet orci aliquam.";
+        $encodedContents = Zend_Pdf_Filter_Ascii85::encode($decodedContents);
+        $testString = "9Q+r_D'3P3F*2=BA8c:&EZfF;F<G\"/ATT&5Earf+@;KXtF^],>~>";
+        $this->assertEquals($encodedContents, $testString);
+    }
+
+    public function testStringDivisibleBy4Decode()
+    {
+        $encodedContents = "9Q+r_D'3P3F*2=BA8c:&EZfF;F<G\"/ATT&5Earf+@;KXtF^],>~>";
+        $decodedContents = Zend_Pdf_Filter_Ascii85::decode($encodedContents);
+        $testString = 'Lorem ipsum dolor sit amet orci aliquam.';
+        $this->assertEquals($decodedContents, $testString);
+    }
+
+    public function testStringNotDivisibleBy4Encode()
+    {
+        $decodedContents = 'Lorem ipsum dolor sit amet, consectetur cras amet.';
+        $encodedContents = Zend_Pdf_Filter_Ascii85::encode($decodedContents);
+        $testString  = "9Q+r_D'3P3F*2=BA8c:&EZfF;F<G\"/ATTIG@rH7+ARfgn"
+                     . "FEMUH@rc\"!+CT+uF=m~>";
+        $this->assertEquals($encodedContents, $testString);
+    }
+
+    public function testStringNotDivisibleBy4Decode()
+    {
+        $encodedContents = "9Q+r_D'3P3F*2=BA8c:&EZfF;F<G\"/ATTIG@rH7+ARfgn"
+                         . "FEMUH@rc\"!+CT+uF=m~>";
+        $decodedContents = Zend_Pdf_Filter_Ascii85::decode($encodedContents);
+        $testString = 'Lorem ipsum dolor sit amet, consectetur cras amet.';
+        $this->assertEquals($decodedContents, $testString);
+    }
+}