| 1 |
<?php |
| 2 |
|
| 3 |
if (!defined('ABSPATH')) { |
| 4 |
die('Access denied.'); |
| 5 |
} |
| 6 |
|
| 7 |
/** @license |
| 8 |
jSignature v2 SVG export plugin. |
| 9 |
Copyright (c) 2012 Willow Systems Corp http://willow-systems.com |
| 10 |
MIT License <http://www.opensource.org/licenses/mit-license.php> |
| 11 |
*/ |
| 12 |
class Helper_E2pdf_jSignature { |
| 13 |
|
| 14 |
// private $acceptedformat = 'image/jsignature;base30'; |
| 15 |
private $chunkSeparator = ''; |
| 16 |
private $charmap = array(); // {'1':'g','2':'h','3':'i','4':'j','5':'k','6':'l','7':'m','8':'n','9':'o','a':'p','b':'q','c':'r','d':'s','e':'t','f':'u','0':'v'} |
| 17 |
private $charmap_reverse = array(); // will be filled by 'uncompress*" function |
| 18 |
private $allchars = array(); |
| 19 |
private $bitness = 0; |
| 20 |
private $minus = ''; |
| 21 |
private $plus = ''; |
| 22 |
|
| 23 |
public function __construct() { |
| 24 |
global $bitness, $allchars, $charmap, $charmap_reverse, $minus, $plus, $chunkSeparator; |
| 25 |
$allchars = str_split('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX'); |
| 26 |
$bitness = sizeof($allchars) / 2; |
| 27 |
$minus = 'Z'; |
| 28 |
$plus = 'Y'; |
| 29 |
$chunkSeparator = '_'; |
| 30 |
for ($i = $bitness - 1; $i > -1; $i--) { |
| 31 |
$charmap[$allchars[$i]] = $allchars[$i + $bitness]; |
| 32 |
$charmap_reverse[$allchars[$i + $bitness]] = $allchars[$i]; |
| 33 |
} |
| 34 |
} |
| 35 |
|
| 36 |
/* |
| 37 |
Decompresses half of a stroke in a base30-encoded jSignature image. |
| 38 |
$c = new jSignature_base30(); |
| 39 |
$t = array(236, 233, 231, 229, 226, 224, 222, 216, 213, 210, 205, 202, 200, 198, 195, 193, 191, 189, 186, 183, 180, 178, 174, 172); |
| 40 |
$leg = '7UZ32232263353223222333242'; |
| 41 |
$a = $c->uncompress_stroke_leg($leg); |
| 42 |
$t == $a |
| 43 |
*/ |
| 44 |
|
| 45 |
private function uncompress_stroke_leg($datastring) { |
| 46 |
global $charmap, $charmap_reverse, $bitness, $minus, $plus; |
| 47 |
// we convert half-stroke (only 'x' series or only 'y' series of numbers) |
| 48 |
// datastring like this: |
| 49 |
// "5agm12100p1235584210m53" |
| 50 |
// is converted into this: |
| 51 |
// [517,516,514,513,513,513,514,516,519,524,529,537,541,543,544,544,539,536] |
| 52 |
// each number in the chain is converted such: |
| 53 |
// - digit char = start of new whole number. Alpha chars except "p","m" are numbers in hiding. |
| 54 |
// These consecutive digist expressed as alphas mapped back to digit char. |
| 55 |
// resurrected number is the diff between this point and prior coord. |
| 56 |
// - running polaritiy is attached to the number. |
| 57 |
// - we undiff (signed number + prior coord) the number. |
| 58 |
// - if char 'm','p', flip running polarity |
| 59 |
$answer = array(); |
| 60 |
$chars = str_split($datastring); |
| 61 |
$l = sizeof($chars); |
| 62 |
$ch = ''; |
| 63 |
$polarity = 1; |
| 64 |
$partial = array(); |
| 65 |
$preprewhole = 0; |
| 66 |
$prewhole = 0; |
| 67 |
for ($i = 0; $i < $l; $i++) { |
| 68 |
// echo "adding $i of $l to answer\n"; |
| 69 |
$ch = $chars[$i]; |
| 70 |
if (array_key_exists($ch, $charmap) || $ch == $minus || $ch == $plus) { |
| 71 |
|
| 72 |
// this is new number - start of a new whole number. |
| 73 |
// before we can deal with it, we need to flush out what we already |
| 74 |
// parsed out from string, but keep in limbo, waiting for this sign |
| 75 |
// that prior number is done. |
| 76 |
// we deal with 3 numbers here: |
| 77 |
// 1. start of this number - a diff from previous number to |
| 78 |
// whole, new number, which we cannot do anything with cause |
| 79 |
// we don't know its ending yet. |
| 80 |
// 2. number that we now realize have just finished parsing = prewhole |
| 81 |
// 3. number we keep around that came before prewhole = preprewhole |
| 82 |
if (sizeof($partial) != 0) { |
| 83 |
// yep, we have some number parts in there. |
| 84 |
$prewhole = intval(implode('', $partial), $bitness) * $polarity + $preprewhole; |
| 85 |
array_push($answer, $prewhole); |
| 86 |
$preprewhole = $prewhole; |
| 87 |
} |
| 88 |
if ($ch == $minus) { |
| 89 |
$polarity = -1; |
| 90 |
$partial = array(); |
| 91 |
} else if ($ch == $plus) { |
| 92 |
$polarity = 1; |
| 93 |
$partial = array(); |
| 94 |
} else { |
| 95 |
// now, let's start collecting parts for the new number: |
| 96 |
$partial = array($ch); |
| 97 |
} |
| 98 |
} else /* alphas replacing digits */ { |
| 99 |
// more parts for the new number |
| 100 |
array_push($partial, $charmap_reverse[$ch]); |
| 101 |
} |
| 102 |
} |
| 103 |
// we always will have something stuck in partial |
| 104 |
// because we don't have closing delimiter |
| 105 |
array_push($answer, intval(implode('', $partial), $bitness) * $polarity + $preprewhole); |
| 106 |
|
| 107 |
return $answer; |
| 108 |
} |
| 109 |
|
| 110 |
/* |
| 111 |
$c = new jSignature_base30(); |
| 112 |
$signature = "3E13Z5Y5_1O24Z66_1O1Z3_3E2Z4"; |
| 113 |
|
| 114 |
// This is exactly the same as "native" format within jSignature. |
| 115 |
$t = array( |
| 116 |
array( |
| 117 |
'x'=>array(100,101,104,99,104) |
| 118 |
,'y'=>array(50,52,56,50,44) |
| 119 |
) |
| 120 |
,array( |
| 121 |
'x'=>array(50,51,48) |
| 122 |
,'y'=>array(100,102,98) |
| 123 |
) |
| 124 |
); |
| 125 |
$a = $c->Base64ToNative($signature); |
| 126 |
$t == $a |
| 127 |
*/ |
| 128 |
|
| 129 |
public function Base64ToNative($datastring) { |
| 130 |
global $chunkSeparator; |
| 131 |
$data = array(); |
| 132 |
$chunks = explode($chunkSeparator, $datastring); |
| 133 |
$l = sizeof($chunks) / 2; |
| 134 |
for ($i = 0; $i < $l; $i++) { |
| 135 |
array_push($data, array( |
| 136 |
'x' => $this->uncompress_stroke_leg($chunks[$i * 2]) |
| 137 |
, 'y' => $this->uncompress_stroke_leg($chunks[$i * 2 + 1]) |
| 138 |
)); |
| 139 |
} |
| 140 |
return $data; |
| 141 |
} |
| 142 |
|
| 143 |
} |
| 144 |
|