PKa\.datamatrix.phpnuW+A. // // See LICENSE.TXT file for more information. // ------------------------------------------------------------------- // // DESCRIPTION : // // Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. // DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. //============================================================+ /** * @file * Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. * DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. * * @package com.tecnick.tcpdf * @author Nicola Asuni * @version 1.0.001 */ // custom definitions if (!defined('DATAMATRIXDEFS')) { /** * Indicate that definitions for this class are set */ define('DATAMATRIXDEFS', true); // ----------------------------------------------------- } // end of custom definitions // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# /** * ASCII encoding: ASCII character 0 to 127 (1 byte per CW) */ define('ENC_ASCII', 0); /** * C40 encoding: Upper-case alphanumeric (3/2 bytes per CW) */ define('ENC_C40', 1); /** * TEXT encoding: Lower-case alphanumeric (3/2 bytes per CW) */ define('ENC_TXT', 2); /** * X12 encoding: ANSI X12 (3/2 byte per CW) */ define('ENC_X12', 3); /** * EDIFACT encoding: ASCII character 32 to 94 (4/3 bytes per CW) */ define('ENC_EDF', 4); /** * BASE 256 encoding: ASCII character 0 to 255 (1 byte per CW) */ define('ENC_BASE256', 5); /** * ASCII extended encoding: ASCII character 128 to 255 (1/2 byte per CW) */ define('ENC_ASCII_EXT', 6); /** * ASCII number encoding: ASCII digits (2 bytes per CW) */ define('ENC_ASCII_NUM', 7); /** * @class Datamatrix * Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. * DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. * * @package com.tecnick.tcpdf * @author Nicola Asuni * @version 1.0.001 */ class Datamatrix { /** * Barcode array to be returned which is readable by TCPDF. * @protected */ protected $barcode_array = array(); /** * Store last used encoding for data codewords. * @protected */ protected $last_enc = ENC_ASCII; /** * Table of Data Matrix ECC 200 Symbol Attributes: * @protected */ protected $symbattr = array( // square form --------------------------------------------------------------------------------------- array(0x00a,0x00a,0x008,0x008,0x00a,0x00a,0x008,0x008,0x001,0x001,0x001,0x003,0x005,0x001,0x003,0x005), // 10x10 array(0x00c,0x00c,0x00a,0x00a,0x00c,0x00c,0x00a,0x00a,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 12x12 array(0x00e,0x00e,0x00c,0x00c,0x00e,0x00e,0x00c,0x00c,0x001,0x001,0x001,0x008,0x00a,0x001,0x008,0x00a), // 14x14 array(0x010,0x010,0x00e,0x00e,0x010,0x010,0x00e,0x00e,0x001,0x001,0x001,0x00c,0x00c,0x001,0x00c,0x00c), // 16x16 array(0x012,0x012,0x010,0x010,0x012,0x012,0x010,0x010,0x001,0x001,0x001,0x012,0x00e,0x001,0x012,0x00e), // 18x18 array(0x014,0x014,0x012,0x012,0x014,0x014,0x012,0x012,0x001,0x001,0x001,0x016,0x012,0x001,0x016,0x012), // 20x20 array(0x016,0x016,0x014,0x014,0x016,0x016,0x014,0x014,0x001,0x001,0x001,0x01e,0x014,0x001,0x01e,0x014), // 22x22 array(0x018,0x018,0x016,0x016,0x018,0x018,0x016,0x016,0x001,0x001,0x001,0x024,0x018,0x001,0x024,0x018), // 24x24 array(0x01a,0x01a,0x018,0x018,0x01a,0x01a,0x018,0x018,0x001,0x001,0x001,0x02c,0x01c,0x001,0x02c,0x01c), // 26x26 array(0x020,0x020,0x01c,0x01c,0x010,0x010,0x00e,0x00e,0x002,0x002,0x004,0x03e,0x024,0x001,0x03e,0x024), // 32x32 array(0x024,0x024,0x020,0x020,0x012,0x012,0x010,0x010,0x002,0x002,0x004,0x056,0x02a,0x001,0x056,0x02a), // 36x36 array(0x028,0x028,0x024,0x024,0x014,0x014,0x012,0x012,0x002,0x002,0x004,0x072,0x030,0x001,0x072,0x030), // 40x40 array(0x02c,0x02c,0x028,0x028,0x016,0x016,0x014,0x014,0x002,0x002,0x004,0x090,0x038,0x001,0x090,0x038), // 44x44 array(0x030,0x030,0x02c,0x02c,0x018,0x018,0x016,0x016,0x002,0x002,0x004,0x0ae,0x044,0x001,0x0ae,0x044), // 48x48 array(0x034,0x034,0x030,0x030,0x01a,0x01a,0x018,0x018,0x002,0x002,0x004,0x0cc,0x054,0x002,0x066,0x02a), // 52x52 array(0x040,0x040,0x038,0x038,0x010,0x010,0x00e,0x00e,0x004,0x004,0x010,0x118,0x070,0x002,0x08c,0x038), // 64x64 array(0x048,0x048,0x040,0x040,0x012,0x012,0x010,0x010,0x004,0x004,0x010,0x170,0x090,0x004,0x05c,0x024), // 72x72 array(0x050,0x050,0x048,0x048,0x014,0x014,0x012,0x012,0x004,0x004,0x010,0x1c8,0x0c0,0x004,0x072,0x030), // 80x80 array(0x058,0x058,0x050,0x050,0x016,0x016,0x014,0x014,0x004,0x004,0x010,0x240,0x0e0,0x004,0x090,0x038), // 88x88 array(0x060,0x060,0x058,0x058,0x018,0x018,0x016,0x016,0x004,0x004,0x010,0x2b8,0x110,0x004,0x0ae,0x044), // 96x96 array(0x068,0x068,0x060,0x060,0x01a,0x01a,0x018,0x018,0x004,0x004,0x010,0x330,0x150,0x006,0x088,0x038), // 104x104 array(0x078,0x078,0x06c,0x06c,0x014,0x014,0x012,0x012,0x006,0x006,0x024,0x41a,0x198,0x006,0x0af,0x044), // 120x120 array(0x084,0x084,0x078,0x078,0x016,0x016,0x014,0x014,0x006,0x006,0x024,0x518,0x1f0,0x008,0x0a3,0x03e), // 132x132 array(0x090,0x090,0x084,0x084,0x018,0x018,0x016,0x016,0x006,0x006,0x024,0x616,0x26c,0x00a,0x09c,0x03e), // 144x144 // rectangular form (currently unused) --------------------------------------------------------------------------- array(0x008,0x012,0x006,0x010,0x008,0x012,0x006,0x010,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 8x18 array(0x008,0x020,0x006,0x01c,0x008,0x010,0x006,0x00e,0x001,0x002,0x002,0x00a,0x00b,0x001,0x00a,0x00b), // 8x32 array(0x00c,0x01a,0x00a,0x018,0x00c,0x01a,0x00a,0x018,0x001,0x001,0x001,0x010,0x00e,0x001,0x010,0x00e), // 12x26 array(0x00c,0x024,0x00a,0x020,0x00c,0x012,0x00a,0x010,0x001,0x002,0x002,0x00c,0x012,0x001,0x00c,0x012), // 12x36 array(0x010,0x024,0x00e,0x020,0x010,0x012,0x00e,0x010,0x001,0x002,0x002,0x020,0x018,0x001,0x020,0x018), // 16x36 array(0x010,0x030,0x00e,0x02c,0x010,0x018,0x00e,0x016,0x001,0x002,0x002,0x031,0x01c,0x001,0x031,0x01c) // 16x48 ); /** * Map encodation modes whit character sets. * @protected */ protected $chset_id = array(ENC_C40 => 'C40', ENC_TXT => 'TXT', ENC_X12 =>'X12'); /** * Basic set of charactes for each encodation mode. * @protected */ protected $chset = array( 'C40' => array( // Basic set for C40 ---------------------------------------------------------------------------- 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, // 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, // 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27),// 'TXT' => array( // Basic set for TEXT --------------------------------------------------------------------------- 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x61=>0x0e,0x62=>0x0f,0x63=>0x10,0x64=>0x11,0x65=>0x12,0x66=>0x13, // 0x67=>0x14,0x68=>0x15,0x69=>0x16,0x6a=>0x17,0x6b=>0x18,0x6c=>0x19,0x6d=>0x1a,0x6e=>0x1b,0x6f=>0x1c,0x70=>0x1d, // 0x71=>0x1e,0x72=>0x1f,0x73=>0x20,0x74=>0x21,0x75=>0x22,0x76=>0x23,0x77=>0x24,0x78=>0x25,0x79=>0x26,0x7a=>0x27),// 'SH1' => array( // Shift 1 set ---------------------------------------------------------------------------------- 0x00=>0x00,0x01=>0x01,0x02=>0x02,0x03=>0x03,0x04=>0x04,0x05=>0x05,0x06=>0x06,0x07=>0x07,0x08=>0x08,0x09=>0x09, // 0x0a=>0x0a,0x0b=>0x0b,0x0c=>0x0c,0x0d=>0x0d,0x0e=>0x0e,0x0f=>0x0f,0x10=>0x10,0x11=>0x11,0x12=>0x12,0x13=>0x13, // 0x14=>0x14,0x15=>0x15,0x16=>0x16,0x17=>0x17,0x18=>0x18,0x19=>0x19,0x1a=>0x1a,0x1b=>0x1b,0x1c=>0x1c,0x1d=>0x1d, // 0x1e=>0x1e,0x1f=>0x1f), // 'SH2' => array( // Shift 2 set ---------------------------------------------------------------------------------- 0x21=>0x00,0x22=>0x01,0x23=>0x02,0x24=>0x03,0x25=>0x04,0x26=>0x05,0x27=>0x06,0x28=>0x07,0x29=>0x08,0x2a=>0x09, // 0x2b=>0x0a,0x2c=>0x0b,0x2d=>0x0c,0x2e=>0x0d,0x2f=>0x0e,0x3a=>0x0f,0x3b=>0x10,0x3c=>0x11,0x3d=>0x12,0x3e=>0x13, // 0x3f=>0x14,0x40=>0x15,0x5b=>0x16,0x5c=>0x17,0x5d=>0x18,0x5e=>0x19,0x5f=>0x1a,'F1'=>0x1b,'US'=>0x1e), // 'S3C' => array( // Shift 3 set for C40 -------------------------------------------------------------------------- 0x60=>0x00,0x61=>0x01,0x62=>0x02,0x63=>0x03,0x64=>0x04,0x65=>0x05,0x66=>0x06,0x67=>0x07,0x68=>0x08,0x69=>0x09, // 0x6a=>0x0a,0x6b=>0x0b,0x6c=>0x0c,0x6d=>0x0d,0x6e=>0x0e,0x6f=>0x0f,0x70=>0x10,0x71=>0x11,0x72=>0x12,0x73=>0x13, // 0x74=>0x14,0x75=>0x15,0x76=>0x16,0x77=>0x17,0x78=>0x18,0x79=>0x19,0x7a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, // 0x7e=>0x1e,0x7f=>0x1f), 'S3T' => array( // Shift 3 set for TEXT ------------------------------------------------------------------------- 0x60=>0x00,0x41=>0x01,0x42=>0x02,0x43=>0x03,0x44=>0x04,0x45=>0x05,0x46=>0x06,0x47=>0x07,0x48=>0x08,0x49=>0x09, // 0x4a=>0x0a,0x4b=>0x0b,0x4c=>0x0c,0x4d=>0x0d,0x4e=>0x0e,0x4f=>0x0f,0x50=>0x10,0x51=>0x11,0x52=>0x12,0x53=>0x13, // 0x54=>0x14,0x55=>0x15,0x56=>0x16,0x57=>0x17,0x58=>0x18,0x59=>0x19,0x5a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, // 0x7e=>0x1e,0x7f=>0x1f), // 'X12' => array( // Set for X12 ---------------------------------------------------------------------------------- 0x0d=>0x00,0x2a=>0x01,0x3e=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, // 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, // 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27) // ); // ----------------------------------------------------------------------------- /** * This is the class constructor. * Creates a datamatrix object * @param $code (string) Code to represent using Datamatrix. * @public */ public function __construct($code) { $barcode_array = array(); if ((is_null($code)) OR ($code == '\0') OR ($code == '')) { return false; } // get data codewords $cw = $this->getHighLevelEncoding($code); // number of data codewords $nd = count($cw); // check size if ($nd > 1558) { return false; } // get minimum required matrix size. foreach ($this->symbattr as $params) { if ($params[11] >= $nd) { break; } } if ($params[11] < $nd) { // too much data return false; } elseif ($params[11] > $nd) { // add padding if ($this->last_enc == ENC_EDF) { // switch to ASCII encoding $cw[] = 124; ++$nd; } elseif (($this->last_enc != ENC_ASCII) AND ($this->last_enc != ENC_BASE256)) { // switch to ASCII encoding $cw[] = 254; ++$nd; } if ($params[11] > $nd) { // add first pad $cw[] = 129; ++$nd; // add remaining pads for ($i = $nd; $i <= $params[11]; ++$i) { $cw[] = $this->get253StateCodeword(129, $i); } } } // add error correction codewords $cw = $this->getErrorCorrection($cw, $params[13], $params[14], $params[15]); // initialize empty arrays $grid = array_fill(0, ($params[2] * $params[3]), 0); // get placement map $places = $this->getPlacemetMap($params[2], $params[3]); // fill the grid with data $grid = array(); $i = 0; // region data row max index $rdri = ($params[4] - 1); // region data column max index $rdci = ($params[5] - 1); // for each vertical region for ($vr = 0; $vr < $params[9]; ++$vr) { // for each row on region for ($r = 0; $r < $params[4]; ++$r) { // get row $row = (($vr * $params[4]) + $r); // for each horizontal region for ($hr = 0; $hr < $params[8]; ++$hr) { // for each column on region for ($c = 0; $c < $params[5]; ++$c) { // get column $col = (($hr * $params[5]) + $c); // braw bits by case if ($r == 0) { // top finder pattern if ($c % 2) { $grid[$row][$col] = 0; } else { $grid[$row][$col] = 1; } } elseif ($r == $rdri) { // bottom finder pattern $grid[$row][$col] = 1; } elseif ($c == 0) { // left finder pattern $grid[$row][$col] = 1; } elseif ($c == $rdci) { // right finder pattern if ($r % 2) { $grid[$row][$col] = 1; } else { $grid[$row][$col] = 0; } } else { // data bit if ($places[$i] < 2) { $grid[$row][$col] = $places[$i]; } else { // codeword ID $cw_id = (floor($places[$i] / 10) - 1); // codeword BIT mask $cw_bit = pow(2, (8 - ($places[$i] % 10))); $grid[$row][$col] = (($cw[$cw_id] & $cw_bit) == 0) ? 0 : 1; } ++$i; } } } } } $this->barcode_array['num_rows'] = $params[0]; $this->barcode_array['num_cols'] = $params[1]; $this->barcode_array['bcode'] = $grid; } /** * Returns a barcode array which is readable by TCPDF * @return array barcode array readable by TCPDF; * @public */ public function getBarcodeArray() { return $this->barcode_array; } /** * Product of two numbers in a Power-of-Two Galois Field * @param $a (int) first number to multiply. * @param $b (int) second number to multiply. * @param $log (array) Log table. * @param $alog (array) Anti-Log table. * @param $gf (array) Number of Factors of the Reed-Solomon polynomial. * @return int product * @protected */ protected function getGFProduct($a, $b, $log, $alog, $gf) { if (($a == 0) OR ($b == 0)) { return 0; } return $alog[($log[$a] + $log[$b]) % ($gf - 1)]; } /** * Add error correction codewords to data codewords array (ANNEX E). * @param $wd (array) Array of datacodewords. * @param $nb (int) Number of blocks. * @param $nd (int) Number of data codewords per block. * @param $nc (int) Number of correction codewords per block. * @param $gf (int) numner of fields on log/antilog table (power of 2). * @param $pp (int) The value of its prime modulus polynomial (301 for ECC200). * @return array data codewords + error codewords * @protected */ protected function getErrorCorrection($wd, $nb, $nd, $nc, $gf=256, $pp=301) { // generate the log ($log) and antilog ($alog) tables $log[0] = 0; $alog[0] = 1; for ($i = 1; $i < $gf; ++$i) { $alog[$i] = ($alog[($i - 1)] * 2); if ($alog[$i] >= $gf) { $alog[$i] ^= $pp; } $log[$alog[$i]] = $i; } ksort($log); // generate the polynomial coefficients (c) $c = array_fill(0, ($nc + 1), 0); $c[0] = 1; for ($i = 1; $i <= $nc; ++$i) { $c[$i] = $c[($i-1)]; for ($j = ($i - 1); $j >= 1; --$j) { $c[$j] = $c[($j - 1)] ^ $this->getGFProduct($c[$j], $alog[$i], $log, $alog, $gf); } $c[0] = $this->getGFProduct($c[0], $alog[$i], $log, $alog, $gf); } ksort($c); // total number of data codewords $num_wd = ($nb * $nd); // total number of error codewords $num_we = ($nb * $nc); // for each block for ($b = 0; $b < $nb; ++$b) { // create interleaved data block $block = array(); for ($n = $b; $n < $num_wd; $n += $nb) { $block[] = $wd[$n]; } // initialize error codewords $we = array_fill(0, ($nc + 1), 0); // calculate error correction codewords for this block for ($i = 0; $i < $nd; ++$i) { $k = ($we[0] ^ $block[$i]); for ($j = 0; $j < $nc; ++$j) { $we[$j] = ($we[($j + 1)] ^ $this->getGFProduct($k, $c[($nc - $j - 1)], $log, $alog, $gf)); } } // add error codewords at the end of data codewords $j = 0; for ($i = $b; $i < $num_we; $i += $nb) { $wd[($num_wd + $i)] = $we[$j]; ++$j; } } // reorder codewords ksort($wd); return $wd; } /** * Return the 253-state codeword * @param $cwpad (int) Pad codeword. * @param $cwpos (int) Number of data codewords from the beginning of encoded data. * @return pad codeword * @protected */ protected function get253StateCodeword($cwpad, $cwpos) { $pad = ($cwpad + (((149 * $cwpos) % 253) + 1)); if ($pad > 254) { $pad -= 254; } return $pad; } /** * Return the 255-state codeword * @param $cwpad (int) Pad codeword. * @param $cwpos (int) Number of data codewords from the beginning of encoded data. * @return pad codeword * @protected */ protected function get255StateCodeword($cwpad, $cwpos) { $pad = ($cwpad + (((149 * $cwpos) % 255) + 1)); if ($pad > 255) { $pad -= 256; } return $pad; } /** * Returns true if the char belongs to the selected mode * @param $chr (int) Character (byte) to check. * @param $mode (int) Current encoding mode. * @return boolean true if the char is of the selected mode. * @protected */ protected function isCharMode($chr, $mode) { $status = false; switch ($mode) { case ENC_ASCII: { // ASCII character 0 to 127 $status = (($chr >= 0) AND ($chr <= 127)); break; } case ENC_C40: { // Upper-case alphanumeric $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 65) AND ($chr <= 90))); break; } case ENC_TXT: { // Lower-case alphanumeric $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 97) AND ($chr <= 122))); break; } case ENC_X12: { // ANSI X12 $status = (($chr == 13) OR ($chr == 42) OR ($chr == 62)); break; } case ENC_EDF: { // ASCII character 32 to 94 $status = (($chr >= 32) AND ($chr <= 94)); break; } case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page) $status = (($chr == 232) OR ($chr == 233) OR ($chr == 234) OR ($chr == 241)); break; } case ENC_ASCII_EXT: { // ASCII character 128 to 255 $status = (($chr >= 128) AND ($chr <= 255)); break; } case ENC_ASCII_NUM: { // ASCII digits $status = (($chr >= 48) AND ($chr <= 57)); break; } } return $status; } /** * The look-ahead test scans the data to be encoded to find the best mode (Annex P - steps from J to S). * @param $data (string) data to encode * @param $pos (int) current position * @param $mode (int) current encoding mode * @return int encoding mode * @protected */ protected function lookAheadTest($data, $pos, $mode) { $data_length = strlen($data); if ($pos >= $data_length) { return $mode; } $charscount = 0; // count processed chars // STEP J if ($mode == ENC_ASCII) { $numch = array(0, 1, 1, 1, 1, 1.25); } else { $numch = array(1, 2, 2, 2, 2, 2.25); $numch[$mode] = 0; } while (true) { // STEP K if (($pos + $charscount) == $data_length) { if ($numch[ENC_ASCII] <= ceil(min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) { return ENC_ASCII; } if ($numch[ENC_BASE256] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) { return ENC_BASE256; } if ($numch[ENC_EDF] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256]))) { return ENC_EDF; } if ($numch[ENC_TXT] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) { return ENC_TXT; } if ($numch[ENC_X12] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256]))) { return ENC_X12; } return ENC_C40; } // get char $chr = ord($data{($pos + $charscount)}); $charscount++; // STEP L if ($this->isCharMode($chr, ENC_ASCII_NUM)) { $numch[ENC_ASCII] += (1 / 2); } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]); $numch[ENC_ASCII] += 2; } else { $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]); $numch[ENC_ASCII] += 1; } // STEP M if ($this->isCharMode($chr, ENC_C40)) { $numch[ENC_C40] += (2 / 3); } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { $numch[ENC_C40] += (8 / 3); } else { $numch[ENC_C40] += (4 / 3); } // STEP N if ($this->isCharMode($chr, ENC_TXT)) { $numch[ENC_TXT] += (2 / 3); } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { $numch[ENC_TXT] += (8 / 3); } else { $numch[ENC_TXT] += (4 / 3); } // STEP O if ($this->isCharMode($chr, ENC_X12) OR $this->isCharMode($chr, ENC_C40)) { $numch[ENC_X12] += (2 / 3); } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { $numch[ENC_X12] += (13 / 3); } else { $numch[ENC_X12] += (10 / 3); } // STEP P if ($this->isCharMode($chr, ENC_EDF)) { $numch[ENC_EDF] += (3 / 4); } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { $numch[ENC_EDF] += (17 / 4); } else { $numch[ENC_EDF] += (13 / 4); } // STEP Q if ($this->isCharMode($chr, ENC_BASE256)) { $numch[ENC_BASE256] += 4; } else { $numch[ENC_BASE256] += 1; } // STEP R if ($charscount >= 4) { if (($numch[ENC_ASCII] + 1) <= min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) { return ENC_ASCII; } if ((($numch[ENC_BASE256] + 1) <= $numch[ENC_ASCII]) OR (($numch[ENC_BASE256] + 1) < min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) { return ENC_BASE256; } if (($numch[ENC_EDF] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256])) { return ENC_EDF; } if (($numch[ENC_TXT] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) { return ENC_TXT; } if (($numch[ENC_X12] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) { return ENC_X12; } if (($numch[ENC_C40] + 1) < min($numch[ENC_ASCII], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) { if ($numch[ENC_C40] < $numch[ENC_X12]) { return ENC_C40; } if ($numch[ENC_C40] == $numch[ENC_X12]) { $k = ($pos + $charscount + 1); while ($k < $data_length) { $tmpchr = ord($data{$k}); if ($this->isCharMode($tmpchr, ENC_X12)) { return ENC_X12; } elseif (!($this->isCharMode($tmpchr, ENC_X12) OR $this->isCharMode($tmpchr, ENC_C40))) { break; } ++$k; } return ENC_C40; } } } } // end of while } /** * Get the switching codeword to a new encoding mode (latch codeword) * @param $mode (int) New encoding mode. * @return (int) Switch codeword. * @protected */ protected function getSwitchEncodingCodeword($mode) { switch ($mode) { case ENC_ASCII: { // ASCII character 0 to 127 $cw = 254; break; } case ENC_C40: { // Upper-case alphanumeric $cw = 230; break; } case ENC_TXT: { // Lower-case alphanumeric $cw = 239; break; } case ENC_X12: { // ANSI X12 $cw = 238; break; } case ENC_EDF: { // ASCII character 32 to 94 $cw = 240; break; } case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page) $cw = 231; break; } } return $cw; } /** * Choose the minimum matrix size and return the max number of data codewords. * @param $numcw (int) Number of current codewords. * @return number of data codewords in matrix * @protected */ protected function getMaxDataCodewords($numcw) { foreach ($this->symbattr as $key => $matrix) { if ($matrix[11] >= $numcw) { return $matrix[11]; } } return 0; } /** * Get high level encoding using the minimum symbol data characters for ECC 200 * @param $data (string) data to encode * @return array of codewords * @protected */ protected function getHighLevelEncoding($data) { // STEP A. Start in ASCII encodation. $enc = ENC_ASCII; // current encoding mode $pos = 0; // current position $cw = array(); // array of codewords to be returned $cw_num = 0; // number of data codewords $data_lenght = strlen($data); // number of chars while ($pos < $data_lenght) { switch ($enc) { case ENC_ASCII: { // STEP B. While in ASCII encodation if (($data_lenght > 1) AND ($pos < ($data_lenght - 1)) AND ($this->isCharMode(ord($data{($pos)}), ENC_ASCII_NUM) AND $this->isCharMode(ord($data{($pos + 1)}), ENC_ASCII_NUM))) { // 1. If the next data sequence is at least 2 consecutive digits, encode the next two digits as a double digit in ASCII mode. $cw[] = (intval(substr($data, $pos, 2)) + 130); ++$cw_num; $pos += 2; } else { // 2. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. $newenc = $this->lookAheadTest($data, $pos, $enc); if ($newenc != $enc) { // switch to new encoding $enc = $newenc; $cw[] = $this->getSwitchEncodingCodeword($enc); ++$cw_num; } else { // get new byte $chr = ord($data{($pos)}); ++$pos; if ($this->isCharMode($chr, ENC_ASCII_EXT)) { // 3. If the next data character is extended ASCII (greater than 127) encode it in ASCII mode first using the Upper Shift (value 235) character. $cw[] = 235; $cw[] = ($chr - 127); $cw_num += 2; } else { // 4. Otherwise process the next data character in ASCII encodation. $cw[] = ($chr + 1); ++$cw_num; } } } break; } case ENC_C40 : // Upper-case alphanumeric case ENC_TXT : // Lower-case alphanumeric case ENC_X12 : { // ANSI X12 $temp_cw = array(); $p = 0; $epos = $pos; // get charset ID $set_id = $this->chset_id[$enc]; // get basic charset for current encoding $charset = $this->chset[$set_id]; do { // 2. process the next character in C40 encodation. $chr = ord($data{($epos)}); ++$epos; // check for extended character if ($chr & 0x80) { if ($enc == ENC_X12) { return false; } $chr = ($chr & 0x7f); $temp_cw[] = 1; // shift 2 $temp_cw[] = 30; // upper shift $p += 2; } if (isset($charset[$chr])) { $temp_cw[] = $charset[$chr]; ++$p; } else { if (isset($this->chset['SH1'][$chr])) { $temp_cw[] = 0; // shift 1 $shiftset = $this->chset['SH1']; } elseif (isset($chr, $this->chset['SH2'][$chr])) { $temp_cw[] = 1; // shift 2 $shiftset = $this->chset['SH2']; } elseif (($enc == ENC_C40) AND isset($this->chset['S3C'][$chr])) { $temp_cw[] = 2; // shift 3 $shiftset = $this->chset['S3C']; } elseif (($enc == ENC_TXT) AND isset($this->chset['S3T'][$chr])) { $temp_cw[] = 2; // shift 3 $shiftset = $this->chset['S3T']; } else { return false; } $temp_cw[] = $shiftset[$chr]; $p += 2; } if ($p >= 3) { $c1 = array_shift($temp_cw); $c2 = array_shift($temp_cw); $c3 = array_shift($temp_cw); $p -= 3; $tmp = ((1600 * $c1) + (40 * $c2) + $c3 + 1); $cw[] = ($tmp >> 8); $cw[] = ($tmp % 256); $cw_num += 2; $pos = $epos; // 1. If the C40 encoding is at the point of starting a new double symbol character and if the look-ahead test (starting at step J) indicates another mode, switch to that mode. $newenc = $this->lookAheadTest($data, $pos, $enc); if ($newenc != $enc) { $enc = $newenc; $cw[] = $this->getSwitchEncodingCodeword($enc); ++$cw_num; break; } } } while (($p > 0) AND ($epos < $data_lenght)); // process last data (if any) if ($p > 0) { // get remaining number of data symbols $cwr = ($this->getMaxDataCodewords($cw_num + 2) - $cw_num); if (($cwr == 1) AND ($p == 1)) { // d. If one symbol character remains and one C40 value (data character) remains to be encoded $c1 = array_shift($temp_cw); --$p; $cw[] = ($c1 + 1); ++$cw_num; } elseif (($cwr == 2) AND ($p == 1)) { // c. If two symbol characters remain and only one C40 value (data character) remains to be encoded $c1 = array_shift($temp_cw); --$p; $cw[] = 254; $cw[] = ($c1 + 1); $cw_num += 2; } elseif (($cwr == 2) AND ($p == 2)) { // b. If two symbol characters remain and two C40 values remain to be encoded $c1 = array_shift($temp_cw); $c2 = array_shift($temp_cw); $p -= 2; $tmp = ((1600 * $c1) + (40 * $c2) + 1); $cw[] = ($tmp >> 8); $cw[] = ($tmp % 256); $cw_num += 2; } else { // switch to ASCII encoding $enc = ENC_ASCII; $cw[] = $this->getSwitchEncodingCodeword($enc); ++$cw_num; } } break; } case ENC_EDF: { // F. While in EDIFACT (EDF) encodation // initialize temporary array with 0 lenght $temp_cw = array(); $epos = $pos; $field_lenght = 0; while ($epos < $data_lenght) { // 2. process the next character in EDIFACT encodation. $chr = ord($data{($epos)}); ++$epos; $temp_cw[] = $chr; ++$field_lenght; if (($field_lenght == 4) OR ($epos == $data_lenght)) { if ($field_lenght < 4) { // set unlatch character $temp_cw[] = 0x1f; ++$field_lenght; $enc = ENC_ASCII; // fill empty characters for ($i = $field_lenght; $i < 4; ++$i) { $temp_cw[] = 0; } } // encodes four data characters in three codewords $cw[] = (($temp_cw[0] & 0x3F) << 2) + (($temp_cw[1] & 0x30) >> 4); $cw[] = (($temp_cw[1] & 0x0F) << 4) + (($temp_cw[2] & 0x3C) >> 2); $cw[] = (($temp_cw[2] & 0x03) << 6) + ($temp_cw[3] & 0x3F); $cw_num += 3; $temp_cw = array(); $pos = $epos; $field_lenght = 0; } // 1. If the EDIFACT encoding is at the point of starting a new triple symbol character and if the look-ahead test (starting at step J) indicates another mode, switch to that mode. if ($field_lenght == 0) { // get remaining number of data symbols $cwr = ($this->getMaxDataCodewords($cw_num + 2) - $cw_num); if ($cwr < 3) { // return to ascii without unlatch $enc = ENC_ASCII; break; // exit from EDIFACT mode } else { $newenc = $this->lookAheadTest($data, $pos, $enc); if ($newenc != $enc) { // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. $enc = $newenc; $cw[] = $this->getSwitchEncodingCodeword($enc); ++$cw_num; break; // exit from EDIFACT mode } } } } break; } case ENC_BASE256: { // G. While in Base 256 (B256) encodation // initialize temporary array with 0 lenght $temp_cw = array(); $field_lenght = 0; while (($pos < $data_lenght) AND ($field_lenght <= 1555)) { $newenc = $this->lookAheadTest($data, $pos, $enc); if ($newenc != $enc) { // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. $enc = $newenc; $cw[] = $this->getSwitchEncodingCodeword($enc); ++$cw_num; break; // exit from B256 mode } else { // 2. Otherwise, process the next character in Base 256 encodation. $chr = ord($data{($pos)}); ++$pos; $temp_cw[] = $chr; ++$field_lenght; } } // set field lenght if ($field_lenght <= 249) { $cw[] = $field_lenght; ++$cw_num; } else { $cw[] = (floor($field_lenght / 250) + 249); $cw[] = ($field_lenght % 250); $cw_num += 2; } if (!empty($temp_cw)) { // add B256 field foreach ($temp_cw as $p => $cht) { $cw[] = $this->get255StateCodeword($chr, ($cw_num + $p)); } } break; } } // end of switch enc } // end of while // set last used encoding $this->last_enc = $enc; return $cw; } /** * Places "chr+bit" with appropriate wrapping within array[]. * (Annex F - ECC 200 symbol character placement) * @param $marr (array) Array of symbols. * @param $nrow (int) Number of rows. * @param $ncol (int) Number of columns. * @param $row (int) Row number. * @param $col (int) Column number. * @param $chr (int) Char byte. * @param $bit (int) Bit. * @return array * @protected */ protected function placeModule($marr, $nrow, $ncol, $row, $col, $chr, $bit) { if ($row < 0) { $row += $nrow; $col += (4 - (($nrow + 4) % 8)); } if ($col < 0) { $col += $ncol; $row += (4 - (($ncol + 4) % 8)); } $marr[(($row * $ncol) + $col)] = ((10 * $chr) + $bit); return $marr; } /** * Places the 8 bits of a utah-shaped symbol character. * (Annex F - ECC 200 symbol character placement) * @param $marr (array) Array of symbols. * @param $nrow (int) Number of rows. * @param $ncol (int) Number of columns. * @param $row (int) Row number. * @param $col (int) Column number. * @param $chr (int) Char byte. * @return array * @protected */ protected function placeUtah($marr, $nrow, $ncol, $row, $col, $chr) { $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-2, $chr, 1); $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-1, $chr, 2); $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-2, $chr, 3); $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-1, $chr, 4); $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col, $chr, 5); $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-2, $chr, 6); $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-1, $chr, 7); $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col, $chr, 8); return $marr; } /** * Places the 8 bits of the first special corner case. * (Annex F - ECC 200 symbol character placement) * @param $marr (array) Array of symbols. * @param $nrow (int) Number of rows. * @param $ncol (int) Number of columns. * @param $chr (int) Char byte. * @return array * @protected */ protected function placeCornerA($marr, $nrow, $ncol, $chr) { $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1); $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 1, $chr, 2); $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 2, $chr, 3); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6); $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7); $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8); return $marr; } /** * Places the 8 bits of the second special corner case. * (Annex F - ECC 200 symbol character placement) * @param $marr (array) Array of symbols. * @param $nrow (int) Number of rows. * @param $ncol (int) Number of columns. * @param $chr (int) Char byte. * @return array * @protected */ protected function placeCornerB($marr, $nrow, $ncol, $chr) { $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1); $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2); $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-4, $chr, 4); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 5); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 6); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 7); $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8); return $marr; } /** * Places the 8 bits of the third special corner case. * (Annex F - ECC 200 symbol character placement) * @param $marr (array) Array of symbols. * @param $nrow (int) Number of rows. * @param $ncol (int) Number of columns. * @param $chr (int) Char byte. * @return array * @protected */ protected function placeCornerC($marr, $nrow, $ncol, $chr) { $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1); $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2); $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6); $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7); $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8); return $marr; } /** * Places the 8 bits of the fourth special corner case. * (Annex F - ECC 200 symbol character placement) * @param $marr (array) Array of symbols. * @param $nrow (int) Number of rows. * @param $ncol (int) Number of columns. * @param $chr (int) Char byte. * @return array * @protected */ protected function placeCornerD($marr, $nrow, $ncol, $chr) { $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1); $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, $ncol-1, $chr, 2); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 3); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-3, $chr, 6); $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-2, $chr, 7); $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8); return $marr; } /** * Build a placement map. * (Annex F - ECC 200 symbol character placement) * @param $nrow (int) Number of rows. * @param $ncol (int) Number of columns. * @return array * @protected */ protected function getPlacemetMap($nrow, $ncol) { // initialize array with zeros $marr = array_fill(0, ($nrow * $ncol), 0); // set starting values $chr = 1; $row = 4; $col = 0; do { // repeatedly first check for one of the special corner cases, then if (($row == $nrow) AND ($col == 0)) { $marr = $this->placeCornerA($marr, $nrow, $ncol, $chr); ++$chr; } if (($row == ($nrow - 2)) AND ($col == 0) AND ($ncol % 4)) { $marr = $this->placeCornerB($marr, $nrow, $ncol, $chr); ++$chr; } if (($row == ($nrow - 2)) AND ($col == 0) AND (($ncol % 8) == 4)) { $marr = $this->placeCornerC($marr, $nrow, $ncol, $chr); ++$chr; } if (($row == ($nrow + 4)) AND ($col == 2) AND (!($ncol % 8))) { $marr = $this->placeCornerD($marr, $nrow, $ncol, $chr); ++$chr; } // sweep upward diagonally, inserting successive characters, do { if (($row < $nrow) AND ($col >= 0) AND (!$marr[(($row * $ncol) + $col)])) { $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr); ++$chr; } $row -= 2; $col += 2; } while (($row >= 0) AND ($col < $ncol)); ++$row; $col += 3; // & then sweep downward diagonally, inserting successive characters,... do { if (($row >= 0) AND ($col < $ncol) AND (!$marr[(($row * $ncol) + $col)])) { $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr); ++$chr; } $row += 2; $col -= 2; } while (($row < $nrow) AND ($col >= 0)); $row += 3; ++$col; // ... until the entire array is scanned } while (($row < $nrow) OR ($col < $ncol)); // lastly, if the lower righthand corner is untouched, fill in fixed pattern if (!$marr[(($nrow * $ncol) - 1)]) { $marr[(($nrow * $ncol) - 1)] = 1; $marr[(($nrow * $ncol) - $ncol - 2)] = 1; } return $marr; } } // end DataMatrix class //============================================================+ // END OF FILE //============================================================+ PKa\&|3?3?tcpdf_parser.phpnuW+A. // // See LICENSE.TXT file for more information. // ------------------------------------------------------------------- // // Description : This is a PHP class for parsing PDF documents. // //============================================================+ /** * @file * This is a PHP class for parsing PDF documents.
* @package com.tecnick.tcpdf * @author Nicola Asuni * @version 1.0.000 */ // include class for decoding filters require_once(dirname(__FILE__).'/tcpdf_filters.php'); /** * @class TCPDF_PARSER * This is a PHP class for parsing PDF documents.
* @package com.tecnick.tcpdf * @brief This is a PHP class for parsing PDF documents.. * @version 1.0.000 * @author Nicola Asuni - info@tecnick.com */ class TCPDF_PARSER { /** * Raw content of the PDF document. * @private */ private $pdfdata = ''; /** * XREF data. * @protected */ protected $xref = array(); /** * Array of PDF objects. * @protected */ protected $objects = array(); /** * Class object for decoding filters. * @private */ private $FilterDecoders; // ----------------------------------------------------------------------------- /** * Parse a PDF document an return an array of objects. * @param $data (string) PDF data to parse. * @public * @since 1.0.000 (2011-05-24) */ public function __construct($data) { if (empty($data)) { $this->Error('Empty PDF data.'); } $this->pdfdata = $data; // get length $pdflen = strlen($this->pdfdata); // initialize class for decoding filters $this->FilterDecoders = new TCPDF_FILTERS(); // get xref and trailer data $this->xref = $this->getXrefData(); // parse all document objects $this->objects = array(); foreach ($this->xref['xref'] as $obj => $offset) { if (!isset($this->objects[$obj])) { $this->objects[$obj] = $this->getIndirectObject($obj, $offset, true); } } // release some memory unset($this->pdfdata); $this->pdfdata = ''; } /** * Return an array of parsed PDF document objects. * @return (array) Array of parsed PDF document objects. * @public * @since 1.0.000 (2011-06-26) */ public function getParsedData() { return array($this->xref, $this->objects); } /** * Get xref (cross-reference table) and trailer data from PDF document data. * @param $offset (int) xref offset (if know). * @param $xref (array) previous xref array (if any). * @return Array containing xref and trailer data. * @protected * @since 1.0.000 (2011-05-24) */ protected function getXrefData($offset=0, $xref=array()) { // find last startxref if (preg_match_all('/[\r\n]startxref[\s]*[\r\n]+([0-9]+)[\s]*[\r\n]+%%EOF/i', $this->pdfdata, $matches, PREG_SET_ORDER, $offset) == 0) { $this->Error('Unable to find startxref'); } $matches = array_pop($matches); $startxref = $matches[1]; // check xref position if (strpos($this->pdfdata, 'xref', $startxref) != $startxref) { $this->Error('Unable to find xref'); } // extract xref data (object indexes and offsets) $offset = $startxref + 5; // initialize object number $obj_num = 0; while (preg_match('/^([0-9]+)[\s]([0-9]+)[\s]?([nf]?)/im', $this->pdfdata, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) { $offset = (strlen($matches[0][0]) + $matches[0][1]); if ($matches[3][0] == 'n') { // create unique object index: [object number]_[generation number] $index = $obj_num.'_'.intval($matches[2][0]); // check if object already exist if (!isset($xref['xref'][$index])) { // store object offset position $xref['xref'][$index] = intval($matches[1][0]); } ++$obj_num; $offset += 2; } elseif ($matches[3][0] == 'f') { ++$obj_num; $offset += 2; } else { // object number (index) $obj_num = intval($matches[1][0]); } } // get trailer data if (preg_match('/trailer[\s]*<<(.*)>>[\s]*[\r\n]+startxref[\s]*[\r\n]+/isU', $this->pdfdata, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) { $trailer_data = $matches[1][0]; if (!isset($xref['trailer'])) { // get only the last updated version $xref['trailer'] = array(); // parse trailer_data if (preg_match('/Size[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { $xref['trailer']['size'] = intval($matches[1]); } if (preg_match('/Root[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['root'] = intval($matches[1]).'_'.intval($matches[2]); } if (preg_match('/Encrypt[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['encrypt'] = intval($matches[1]).'_'.intval($matches[2]); } if (preg_match('/Info[\s]+([0-9]+)[\s]+([0-9]+)[\s]+R/i', $trailer_data, $matches) > 0) { $xref['trailer']['info'] = intval($matches[1]).'_'.intval($matches[2]); } if (preg_match('/ID[\s]*[\[][\s]*[<]([^>]*)[>][\s]*[<]([^>]*)[>]/i', $trailer_data, $matches) > 0) { $xref['trailer']['id'] = array(); $xref['trailer']['id'][0] = $matches[1]; $xref['trailer']['id'][1] = $matches[2]; } } if (preg_match('/Prev[\s]+([0-9]+)/i', $trailer_data, $matches) > 0) { // get previous xref $xref = getXrefData(substr($this->pdfdata, 0, $startxref), intval($matches[1]), $xref); } } else { $this->Error('Unable to find trailer'); } return $xref; } /** * Get object type, raw value and offset to next object * @param $offset (int) Object offset. * @return array containing object type, raw value and offset to next object * @protected * @since 1.0.000 (2011-06-20) */ protected function getRawObject($offset=0) { $objtype = ''; // object type to be returned $objval = ''; // object value to be returned // skip initial white space chars: \x00 null (NUL), \x09 horizontal tab (HT), \x0A line feed (LF), \x0C form feed (FF), \x0D carriage return (CR), \x20 space (SP) $offset += strspn($this->pdfdata, "\x00\x09\x0a\x0c\x0d\x20", $offset); // get first char $char = $this->pdfdata{$offset}; // get object type switch ($char) { case '%': { // \x25 PERCENT SIGN // skip comment and search for next token $next = strcspn($this->pdfdata, "\r\n", $offset); if ($next > 0) { $offset += $next; return $this->getRawObject($this->pdfdata, $offset); } break; } case '/': { // \x2F SOLIDUS // name object $objtype = $char; ++$offset; if (preg_match('/^([^\x00\x09\x0a\x0c\x0d\x20\s\x28\x29\x3c\x3e\x5b\x5d\x7b\x7d\x2f\x25]+)/', substr($this->pdfdata, $offset, 256), $matches) == 1) { $objval = $matches[1]; // unescaped value $offset += strlen($objval); } break; } case '(': // \x28 LEFT PARENTHESIS case ')': { // \x29 RIGHT PARENTHESIS // literal string object $objtype = $char; ++$offset; $strpos = $offset; if ($char == '(') { $open_bracket = 1; while ($open_bracket > 0) { if (!isset($this->pdfdata{$strpos})) { break; } $ch = $this->pdfdata{$strpos}; switch ($ch) { case '\\': { // REVERSE SOLIDUS (5Ch) (Backslash) // skip next character ++$strpos; break; } case '(': { // LEFT PARENHESIS (28h) ++$open_bracket; break; } case ')': { // RIGHT PARENTHESIS (29h) --$open_bracket; break; } } ++$strpos; } $objval = substr($this->pdfdata, $offset, ($strpos - $offset - 1)); $offset = $strpos; } break; } case '[': // \x5B LEFT SQUARE BRACKET case ']': { // \x5D RIGHT SQUARE BRACKET // array object $objtype = $char; ++$offset; if ($char == '[') { // get array content $objval = array(); do { // get element $element = $this->getRawObject($offset); $offset = $element[2]; $objval[] = $element; } while ($element[0] != ']'); // remove closing delimiter array_pop($objval); } break; } case '<': // \x3C LESS-THAN SIGN case '>': { // \x3E GREATER-THAN SIGN if (isset($this->pdfdata{($offset + 1)}) AND ($this->pdfdata{($offset + 1)} == $char)) { // dictionary object $objtype = $char.$char; $offset += 2; if ($char == '<') { // get array content $objval = array(); do { // get element $element = $this->getRawObject($offset); $offset = $element[2]; $objval[] = $element; } while ($element[0] != '>>'); // remove closing delimiter array_pop($objval); } } else { // hexadecimal string object $objtype = $char; ++$offset; if (($char == '<') AND (preg_match('/^([0-9A-Fa-f]+)[>]/iU', substr($this->pdfdata, $offset), $matches) == 1)) { $objval = $matches[1]; $offset += strlen($matches[0]); } } break; } default: { if (substr($this->pdfdata, $offset, 6) == 'endobj') { // indirect object $objtype = 'endobj'; $offset += 6; } elseif (substr($this->pdfdata, $offset, 4) == 'null') { // null object $objtype = 'null'; $offset += 4; $objval = 'null'; } elseif (substr($this->pdfdata, $offset, 4) == 'true') { // boolean true object $objtype = 'boolean'; $offset += 4; $objval = 'true'; } elseif (substr($this->pdfdata, $offset, 5) == 'false') { // boolean false object $objtype = 'boolean'; $offset += 5; $objval = 'false'; } elseif (substr($this->pdfdata, $offset, 6) == 'stream') { // start stream object $objtype = 'stream'; $offset += 6; if (preg_match('/^[\r\n]+(.*)[\r\n]*endstream/isU', substr($this->pdfdata, $offset), $matches) == 1) { $objval = $matches[1]; $offset += strlen($matches[0]); } } elseif (substr($this->pdfdata, $offset, 9) == 'endstream') { // end stream object $objtype = 'endstream'; $offset += 9; } elseif (preg_match('/^([0-9]+)[\s]+([0-9]+)[\s]+R/iU', substr($this->pdfdata, $offset, 33), $matches) == 1) { // indirect object reference $objtype = 'ojbref'; $offset += strlen($matches[0]); $objval = intval($matches[1]).'_'.intval($matches[2]); } elseif (preg_match('/^([0-9]+)[\s]+([0-9]+)[\s]+obj/iU', substr($this->pdfdata, $offset, 33), $matches) == 1) { // object start $objtype = 'ojb'; $objval = intval($matches[1]).'_'.intval($matches[2]); $offset += strlen ($matches[0]); } elseif (($numlen = strspn($this->pdfdata, '+-.0123456789', $offset)) > 0) { // numeric object $objtype = 'numeric'; $objval = substr($this->pdfdata, $offset, $numlen); $offset += $numlen; } break; } } return array($objtype, $objval, $offset); } /** * Get content of indirect object. * @param $obj_ref (string) Object number and generation number separated by underscore character. * @param $offset (int) Object offset. * @param $decoding (boolean) If true decode streams. * @return array containing object data. * @protected * @since 1.0.000 (2011-05-24) */ protected function getIndirectObject($obj_ref, $offset=0, $decoding=true) { $obj = explode('_', $obj_ref); if (($obj === false) OR (count($obj) != 2)) { $this->Error('Invalid object reference: '.$obj); return; } $objref = $obj[0].' '.$obj[1].' obj'; if (strpos($this->pdfdata, $objref, $offset) != $offset) { // an indirect reference to an undefined object shall be considered a reference to the null object return array('null', 'null', $offset); } // starting position of object content $offset += strlen($objref); // get array of object content $objdata = array(); $i = 0; // object main index do { // get element $element = $this->getRawObject($offset); $offset = $element[2]; // decode stream using stream's dictionary information if ($decoding AND ($element[0] == 'stream') AND (isset($objdata[($i - 1)][0])) AND ($objdata[($i - 1)][0] == '<<')) { $element[3] = $this->decodeStream($objdata[($i - 1)][1], $element[1]); } $objdata[$i] = $element; ++$i; } while ($element[0] != 'endobj'); // remove closing delimiter array_pop($objdata); // return raw object content return $objdata; } /** * Get the content of object, resolving indect object reference if necessary. * @param $obj (string) Object value. * @return array containing object data. * @protected * @since 1.0.000 (2011-06-26) */ protected function getObjectVal($obj) { if ($obj[0] == 'objref') { // reference to indirect object if (isset($this->objects[$obj[1]])) { // this object has been already parsed return $this->objects[$obj[1]]; } elseif (isset($this->xref[$obj[1]])) { // parse new object $this->objects[$obj[1]] = $this->getIndirectObject($obj[1], $this->xref[$obj[1]], false); return $this->objects[$obj[1]]; } } return $obj; } /** * Decode the specified stream. * @param $sdic (array) Stream's dictionary array. * @param $stream (string) Stream to decode. * @return array containing decoded stream data and remaining filters. * @protected * @since 1.0.000 (2011-06-22) */ protected function decodeStream($sdic, $stream) { // get stream lenght and filters $slength = strlen($stream); $filters = array(); foreach ($sdic as $k => $v) { if ($v[0] == '/') { if (($v[1] == 'Length') AND (isset($sdic[($k + 1)])) AND ($sdic[($k + 1)][0] == 'numeric')) { // get declared stream lenght $declength = intval($sdic[($k + 1)][1]); if ($declength < $slength) { $stream = substr($stream, 0, $declength); $slength = $declength; } } elseif (($v[1] == 'Filter') AND (isset($sdic[($k + 1)]))) { // resolve indirect object $objval = $this->getObjectVal($sdic[($k + 1)]); if ($objval[0] == '/') { // single filter $filters[] = $objval[1]; } elseif ($objval[0] == '[') { // array of filters foreach ($objval[1] as $flt) { if ($flt[0] == '/') { $filters[] = $flt[1]; } } } } } } // decode the stream $remaining_filters = array(); foreach ($filters as $filter) { if (in_array($filter, $this->FilterDecoders->getAvailableFilters())) { $stream = $this->FilterDecoders->decodeFilter($filter, $stream); } else { // add missing filter to array $remaining_filters[] = $filter; } } return array($stream, $remaining_filters); } /** * This method is automatically called in case of fatal error; it simply outputs the message and halts the execution. * @param $msg (string) The error message * @public * @since 1.0.000 (2011-05-23) */ public function Error($msg) { // exit program and print error die('TCPDF_PARSER ERROR: '.$msg); } } // END OF TCPDF_PARSER CLASS //============================================================+ // END OF FILE //============================================================+ PKa\8 tcpdf.phpnuW+A. // // See LICENSE.TXT file for more information. // ------------------------------------------------------------------- // // Description : // This is a PHP class for generating PDF documents without requiring external extensions. // // NOTE: // This class was originally derived in 2002 from the Public // Domain FPDF class by Olivier Plathey (http://www.fpdf.org), // but now is almost entirely rewritten and contains thousands of // new lines of code and hundreds new features. // // Main features: // * no external libraries are required for the basic functions; // * all standard page formats, custom page formats, custom margins and units of measure; // * UTF-8 Unicode and Right-To-Left languages; // * TrueTypeUnicode, TrueType, Type1 and CID-0 fonts; // * font subsetting; // * methods to publish some XHTML + CSS code, Javascript and Forms; // * images, graphic (geometric figures) and transformation methods; // * supports JPEG, PNG and SVG images natively, all images supported by GD (GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM) and all images supported via ImagMagick (http://www.imagemagick.org/www/formats.html) // * 1D and 2D barcodes: CODE 39, ANSI MH10.8M-1983, USD-3, 3 of 9, CODE 93, USS-93, Standard 2 of 5, Interleaved 2 of 5, CODE 128 A/B/C, 2 and 5 Digits UPC-Based Extention, EAN 8, EAN 13, UPC-A, UPC-E, MSI, POSTNET, PLANET, RMS4CC (Royal Mail 4-state Customer Code), CBC (Customer Bar Code), KIX (Klant index - Customer index), Intelligent Mail Barcode, Onecode, USPS-B-3200, CODABAR, CODE 11, PHARMACODE, PHARMACODE TWO-TRACKS, Datamatrix, QR-Code, PDF417; // * JPEG and PNG ICC profiles, Grayscale, RGB, CMYK, Spot Colors and Transparencies; // * automatic page header and footer management; // * document encryption up to 256 bit and digital signature certifications; // * transactions to UNDO commands; // * PDF annotations, including links, text and file attachments; // * text rendering modes (fill, stroke and clipping); // * multiple columns mode; // * no-write page regions; // * bookmarks, named destinations and table of content; // * text hyphenation; // * text stretching and spacing (tracking/kerning); // * automatic page break, line break and text alignments including justification; // * automatic page numbering and page groups; // * move and delete pages; // * page compression (requires php-zlib extension); // * XOBject Templates; // * Layers and object visibility. // * PDF/A-1b support. // // ----------------------------------------------------------- // THANKS TO: // // Olivier Plathey (http://www.fpdf.org) for original FPDF. // Efthimios Mavrogeorgiadis (emavro@yahoo.com) for suggestions on RTL language support. // Klemen Vodopivec (http://www.fpdf.de/downloads/addons/37/) for Encryption algorithm. // Warren Sherliker (wsherliker@gmail.com) for better image handling. // dullus for text Justification. // Bob Vincent (pillarsdotnet@users.sourceforge.net) for
  • value attribute. // Patrick Benny for text stretch suggestion on Cell(). // Johannes Güntert for JavaScript support. Encoded to utf-8 by redcocker 2011/12/31 // Denis Van Nuffelen for Dynamic Form. // Jacek Czekaj for multibyte justification // Anthony Ferrara for the reintroduction of legacy image methods. // Sourceforge user 1707880 (hucste) for line-trough mode. // Larry Stanbery for page groups. // Martin Hall-May for transparency. // Aaron C. Spike for Polycurve method. // Mohamad Ali Golkar, Saleh AlMatrafe, Charles Abbott for Arabic and Persian support. // Moritz Wagner and Andreas Wurmser for graphic functions. // Andrew Whitehead for core fonts support. // Esteban Jo・ Mar匤 for OpenType font conversion. // Teus Hagen for several suggestions and fixes. // Yukihiro Nakadaira for CID-0 CJK fonts fixes. // Kosmas Papachristos for some CSS improvements. // Marcel Partap for some fixes. // Won Kyu Park for several suggestions, fixes and patches. // Dominik Dzienia for QR-code support. // Laurent Minguet for some suggestions. // Christian Deligant for some suggestions and fixes. // Travis Harris for crop mark suggestion. // Anyone that has reported a bug or sent a suggestion. //============================================================+ /** * @file * This is a PHP class for generating PDF documents without requiring external extensions.
    * TCPDF project (http://www.tcpdf.org) was originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.
    *

    TCPDF main features are:

    * * Tools to encode your unicode fonts are on fonts/utils directory.

    * @package com.tecnick.tcpdf * @author Nicola Asuni * @version 5.9.149 */ // Main configuration file. Define the K_TCPDF_EXTERNAL_CONFIG constant to skip this file. require_once(dirname(__FILE__).'/config/tcpdf_config.php'); /** * @class TCPDF * PHP class for generating PDF documents without requiring external extensions. * TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.
    * @package com.tecnick.tcpdf * @brief PHP class for generating PDF documents without requiring external extensions. * @version 5.9.149 * @author Nicola Asuni - info@tecnick.com */ class TCPDF { // private properties /** * Current TCPDF version. * @private */ private $tcpdf_version = '5.9.149'; // Protected properties /** * Current page number. * @protected */ protected $page; /** * Current object number. * @protected */ protected $n; /** * Array of object offsets. * @protected */ protected $offsets; /** * Buffer holding in-memory PDF. * @protected */ protected $buffer; /** * Array containing pages. * @protected */ protected $pages = array(); /** * Current document state. * @protected */ protected $state; /** * Compression flag. * @protected */ protected $compress; /** * Current page orientation (P = Portrait, L = Landscape). * @protected */ protected $CurOrientation; /** * Page dimensions. * @protected */ protected $pagedim = array(); /** * Scale factor (number of points in user unit). * @protected */ protected $k; /** * Width of page format in points. * @protected */ protected $fwPt; /** * Height of page format in points. * @protected */ protected $fhPt; /** * Current width of page in points. * @protected */ protected $wPt; /** * Current height of page in points. * @protected */ protected $hPt; /** * Current width of page in user unit. * @protected */ protected $w; /** * Current height of page in user unit. * @protected */ protected $h; /** * Left margin. * @protected */ protected $lMargin; /** * Top margin. * @protected */ protected $tMargin; /** * Right margin. * @protected */ protected $rMargin; /** * Page break margin. * @protected */ protected $bMargin; /** * Array of cell internal paddings ('T' => top, 'R' => right, 'B' => bottom, 'L' => left). * @since 5.9.000 (2010-10-03) * @protected */ protected $cell_padding = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0); /** * Array of cell margins ('T' => top, 'R' => right, 'B' => bottom, 'L' => left). * @since 5.9.000 (2010-10-04) * @protected */ protected $cell_margin = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0); /** * Current horizontal position in user unit for cell positioning. * @protected */ protected $x; /** * Current vertical position in user unit for cell positioning. * @protected */ protected $y; /** * Height of last cell printed. * @protected */ protected $lasth; /** * Line width in user unit. * @protected */ protected $LineWidth; /** * Array of standard font names. * @protected */ protected $CoreFonts; /** * Array of used fonts. * @protected */ protected $fonts = array(); /** * Array of font files. * @protected */ protected $FontFiles = array(); /** * Array of encoding differences. * @protected */ protected $diffs = array(); /** * Array of used images. * @protected */ protected $images = array(); /** * Array of Annotations in pages. * @protected */ protected $PageAnnots = array(); /** * Array of internal links. * @protected */ protected $links = array(); /** * Current font family. * @protected */ protected $FontFamily; /** * Current font style. * @protected */ protected $FontStyle; /** * Current font ascent (distance between font top and baseline). * @protected * @since 2.8.000 (2007-03-29) */ protected $FontAscent; /** * Current font descent (distance between font bottom and baseline). * @protected * @since 2.8.000 (2007-03-29) */ protected $FontDescent; /** * Underlining flag. * @protected */ protected $underline; /** * Overlining flag. * @protected */ protected $overline; /** * Current font info. * @protected */ protected $CurrentFont; /** * Current font size in points. * @protected */ protected $FontSizePt; /** * Current font size in user unit. * @protected */ protected $FontSize; /** * Commands for drawing color. * @protected */ protected $DrawColor; /** * Commands for filling color. * @protected */ protected $FillColor; /** * Commands for text color. * @protected */ protected $TextColor; /** * Indicates whether fill and text colors are different. * @protected */ protected $ColorFlag; /** * Automatic page breaking. * @protected */ protected $AutoPageBreak; /** * Threshold used to trigger page breaks. * @protected */ protected $PageBreakTrigger; /** * Flag set when processing page header. * @protected */ protected $InHeader = false; /** * Flag set when processing page footer. * @protected */ protected $InFooter = false; /** * Zoom display mode. * @protected */ protected $ZoomMode; /** * Layout display mode. * @protected */ protected $LayoutMode; /** * If true set the document information dictionary in Unicode. * @protected */ protected $docinfounicode = true; /** * Document title. * @protected */ protected $title = ''; /** * Document subject. * @protected */ protected $subject = ''; /** * Document author. * @protected */ protected $author = ''; /** * Document keywords. * @protected */ protected $keywords = ''; /** * Document creator. * @protected */ protected $creator = ''; /** * Starting page number. * @protected */ protected $starting_page_number = 1; /** * String alias for total number of pages. * @protected */ protected $alias_tot_pages = '{:ptp:}'; /** * String alias for page number. * @protected */ protected $alias_num_page = '{:pnp:}'; /** * String alias for total number of pages in a single group. * @protected */ protected $alias_group_tot_pages = '{:ptg:}'; /** * String alias for group page number. * @protected */ protected $alias_group_num_page = '{:png:}'; /** * String alias for right shift compensation used to correctly align page numbers on the right. * @protected */ protected $alias_right_shift = '{rsc:'; /** * The right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image. * @since 2002-07-31 * @author Nicola Asuni * @protected */ protected $img_rb_x; /** * The right-bottom corner Y coordinate of last inserted image. * @since 2002-07-31 * @author Nicola Asuni * @protected */ protected $img_rb_y; /** * Adjusting factor to convert pixels to user units. * @since 2004-06-14 * @author Nicola Asuni * @protected */ protected $imgscale = 1; /** * Boolean flag set to true when the input text is unicode (require unicode fonts). * @since 2005-01-02 * @author Nicola Asuni * @protected */ protected $isunicode = false; /** * Object containing unicode data. * @since 5.9.004 (2010-10-18) * @author Nicola Asuni * @protected */ protected $unicode; /** * Object containing font encoding maps. * @since 5.9.123 (2011-10-01) * @author Nicola Asuni * @protected */ protected $encmaps; /** * PDF version. * @since 1.5.3 * @protected */ protected $PDFVersion = '1.7'; /** * ID of the stored default header template (-1 = not set). * @protected */ protected $header_xobjid = -1; /** * If true reset the Header Xobject template at each page * @protected */ protected $header_xobj_autoreset = false; /** * Minimum distance between header and top page margin. * @protected */ protected $header_margin; /** * Minimum distance between footer and bottom page margin. * @protected */ protected $footer_margin; /** * Original left margin value. * @protected * @since 1.53.0.TC013 */ protected $original_lMargin; /** * Original right margin value. * @protected * @since 1.53.0.TC013 */ protected $original_rMargin; /** * Default font used on page header. * @protected */ protected $header_font; /** * Default font used on page footer. * @protected */ protected $footer_font; /** * Language templates. * @protected */ protected $l; /** * Barcode to print on page footer (only if set). * @protected */ protected $barcode = false; /** * Boolean flag to print/hide page header. * @protected */ protected $print_header = true; /** * Boolean flag to print/hide page footer. * @protected */ protected $print_footer = true; /** * Header image logo. * @protected */ protected $header_logo = ''; /** * Width of header image logo in user units. * @protected */ protected $header_logo_width = 30; /** * Title to be printed on default page header. * @protected */ protected $header_title = ''; /** * String to pring on page header after title. * @protected */ protected $header_string = ''; /** * Default number of columns for html table. * @protected */ protected $default_table_columns = 4; // variables for html parser /** * HTML PARSER: array to store current link and rendering styles. * @protected */ protected $HREF = array(); /** * List of available fonts on filesystem. * @protected */ protected $fontlist = array(); /** * Current foreground color. * @protected */ protected $fgcolor; /** * HTML PARSER: array of boolean values, true in case of ordered list (OL), false otherwise. * @protected */ protected $listordered = array(); /** * HTML PARSER: array count list items on nested lists. * @protected */ protected $listcount = array(); /** * HTML PARSER: current list nesting level. * @protected */ protected $listnum = 0; /** * HTML PARSER: indent amount for lists. * @protected */ protected $listindent = 0; /** * HTML PARSER: current list indententation level. * @protected */ protected $listindentlevel = 0; /** * Current background color. * @protected */ protected $bgcolor; /** * Temporary font size in points. * @protected */ protected $tempfontsize = 10; /** * Spacer string for LI tags. * @protected */ protected $lispacer = ''; /** * Default encoding. * @protected * @since 1.53.0.TC010 */ protected $encoding = 'UTF-8'; /** * PHP internal encoding. * @protected * @since 1.53.0.TC016 */ protected $internal_encoding; /** * Boolean flag to indicate if the document language is Right-To-Left. * @protected * @since 2.0.000 */ protected $rtl = false; /** * Boolean flag used to force RTL or LTR string direction. * @protected * @since 2.0.000 */ protected $tmprtl = false; // --- Variables used for document encryption: /** * IBoolean flag indicating whether document is protected. * @protected * @since 2.0.000 (2008-01-02) */ protected $encrypted; /** * Array containing encryption settings. * @protected * @since 5.0.005 (2010-05-11) */ protected $encryptdata = array(); /** * Last RC4 key encrypted (cached for optimisation). * @protected * @since 2.0.000 (2008-01-02) */ protected $last_enc_key; /** * Last RC4 computed key. * @protected * @since 2.0.000 (2008-01-02) */ protected $last_enc_key_c; /** * Encryption padding string. * @protected */ protected $enc_padding = "\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A"; /** * File ID (used on document trailer). * @protected * @since 5.0.005 (2010-05-12) */ protected $file_id; // --- bookmark --- /** * Outlines for bookmark. * @protected * @since 2.1.002 (2008-02-12) */ protected $outlines = array(); /** * Outline root for bookmark. * @protected * @since 2.1.002 (2008-02-12) */ protected $OutlineRoot; // --- javascript and form --- /** * Javascript code. * @protected * @since 2.1.002 (2008-02-12) */ protected $javascript = ''; /** * Javascript counter. * @protected * @since 2.1.002 (2008-02-12) */ protected $n_js; /** * line trough state * @protected * @since 2.8.000 (2008-03-19) */ protected $linethrough; /** * Array with additional document-wide usage rights for the document. * @protected * @since 5.8.014 (2010-08-23) */ protected $ur = array(); /** * DPI (Dot Per Inch) Document Resolution (do not change). * @protected * @since 3.0.000 (2008-03-27) */ protected $dpi = 72; /** * Array of page numbers were a new page group was started (the page numbers are the keys of the array). * @protected * @since 3.0.000 (2008-03-27) */ protected $newpagegroup = array(); /** * Array that contains the number of pages in each page group. * @protected * @since 3.0.000 (2008-03-27) */ protected $pagegroups = array(); /** * Current page group number. * @protected * @since 3.0.000 (2008-03-27) */ protected $currpagegroup = 0; /** * Array of transparency objects and parameters. * @protected * @since 3.0.000 (2008-03-27) */ protected $extgstates; /** * Set the default JPEG compression quality (1-100). * @protected * @since 3.0.000 (2008-03-27) */ protected $jpeg_quality; /** * Default cell height ratio. * @protected * @since 3.0.014 (2008-05-23) */ protected $cell_height_ratio = K_CELL_HEIGHT_RATIO; /** * PDF viewer preferences. * @protected * @since 3.1.000 (2008-06-09) */ protected $viewer_preferences; /** * A name object specifying how the document should be displayed when opened. * @protected * @since 3.1.000 (2008-06-09) */ protected $PageMode; /** * Array for storing gradient information. * @protected * @since 3.1.000 (2008-06-09) */ protected $gradients = array(); /** * Array used to store positions inside the pages buffer (keys are the page numbers). * @protected * @since 3.2.000 (2008-06-26) */ protected $intmrk = array(); /** * Array used to store positions inside the pages buffer (keys are the page numbers). * @protected * @since 5.7.000 (2010-08-03) */ protected $bordermrk = array(); /** * Array used to store page positions to track empty pages (keys are the page numbers). * @protected * @since 5.8.007 (2010-08-18) */ protected $emptypagemrk = array(); /** * Array used to store content positions inside the pages buffer (keys are the page numbers). * @protected * @since 4.6.021 (2009-07-20) */ protected $cntmrk = array(); /** * Array used to store footer positions of each page. * @protected * @since 3.2.000 (2008-07-01) */ protected $footerpos = array(); /** * Array used to store footer length of each page. * @protected * @since 4.0.014 (2008-07-29) */ protected $footerlen = array(); /** * Boolean flag to indicate if a new line is created. * @protected * @since 3.2.000 (2008-07-01) */ protected $newline = true; /** * End position of the latest inserted line. * @protected * @since 3.2.000 (2008-07-01) */ protected $endlinex = 0; /** * PDF string for width value of the last line. * @protected * @since 4.0.006 (2008-07-16) */ protected $linestyleWidth = ''; /** * PDF string for CAP value of the last line. * @protected * @since 4.0.006 (2008-07-16) */ protected $linestyleCap = '0 J'; /** * PDF string for join value of the last line. * @protected * @since 4.0.006 (2008-07-16) */ protected $linestyleJoin = '0 j'; /** * PDF string for dash value of the last line. * @protected * @since 4.0.006 (2008-07-16) */ protected $linestyleDash = '[] 0 d'; /** * Boolean flag to indicate if marked-content sequence is open. * @protected * @since 4.0.013 (2008-07-28) */ protected $openMarkedContent = false; /** * Count the latest inserted vertical spaces on HTML. * @protected * @since 4.0.021 (2008-08-24) */ protected $htmlvspace = 0; /** * Array of Spot colors. * @protected * @since 4.0.024 (2008-09-12) */ protected $spot_colors = array(); /** * Symbol used for HTML unordered list items. * @protected * @since 4.0.028 (2008-09-26) */ protected $lisymbol = ''; /** * String used to mark the beginning and end of EPS image blocks. * @protected * @since 4.1.000 (2008-10-18) */ protected $epsmarker = 'x#!#EPS#!#x'; /** * Array of transformation matrix. * @protected * @since 4.2.000 (2008-10-29) */ protected $transfmatrix = array(); /** * Current key for transformation matrix. * @protected * @since 4.8.005 (2009-09-17) */ protected $transfmatrix_key = 0; /** * Booklet mode for double-sided pages. * @protected * @since 4.2.000 (2008-10-29) */ protected $booklet = false; /** * Epsilon value used for float calculations. * @protected * @since 4.2.000 (2008-10-29) */ protected $feps = 0.005; /** * Array used for custom vertical spaces for HTML tags. * @protected * @since 4.2.001 (2008-10-30) */ protected $tagvspaces = array(); /** * HTML PARSER: custom indent amount for lists. Negative value means disabled. * @protected * @since 4.2.007 (2008-11-12) */ protected $customlistindent = -1; /** * Boolean flag to indicate if the border of the cell sides that cross the page should be removed. * @protected * @since 4.2.010 (2008-11-14) */ protected $opencell = true; /** * Array of files to embedd. * @protected * @since 4.4.000 (2008-12-07) */ protected $embeddedfiles = array(); /** * Boolean flag to indicate if we are inside a PRE tag. * @protected * @since 4.4.001 (2008-12-08) */ protected $premode = false; /** * Array used to store positions of graphics transformation blocks inside the page buffer. * keys are the page numbers * @protected * @since 4.4.002 (2008-12-09) */ protected $transfmrk = array(); /** * Default color for html links. * @protected * @since 4.4.003 (2008-12-09) */ protected $htmlLinkColorArray = array(0, 0, 255); /** * Default font style to add to html links. * @protected * @since 4.4.003 (2008-12-09) */ protected $htmlLinkFontStyle = 'U'; /** * Counts the number of pages. * @protected * @since 4.5.000 (2008-12-31) */ protected $numpages = 0; /** * Array containing page lengths in bytes. * @protected * @since 4.5.000 (2008-12-31) */ protected $pagelen = array(); /** * Counts the number of pages. * @protected * @since 4.5.000 (2008-12-31) */ protected $numimages = 0; /** * Store the image keys. * @protected * @since 4.5.000 (2008-12-31) */ protected $imagekeys = array(); /** * Length of the buffer in bytes. * @protected * @since 4.5.000 (2008-12-31) */ protected $bufferlen = 0; /** * If true enables disk caching. * @protected * @since 4.5.000 (2008-12-31) */ protected $diskcache = false; /** * Counts the number of fonts. * @protected * @since 4.5.000 (2009-01-02) */ protected $numfonts = 0; /** * Store the font keys. * @protected * @since 4.5.000 (2009-01-02) */ protected $fontkeys = array(); /** * Store the font object IDs. * @protected * @since 4.8.001 (2009-09-09) */ protected $font_obj_ids = array(); /** * Store the fage status (true when opened, false when closed). * @protected * @since 4.5.000 (2009-01-02) */ protected $pageopen = array(); /** * Default monospace font. * @protected * @since 4.5.025 (2009-03-10) */ protected $default_monospaced_font = 'courier'; /** * Cloned copy of the current class object. * @protected * @since 4.5.029 (2009-03-19) */ protected $objcopy; /** * Array used to store the lengths of cache files. * @protected * @since 4.5.029 (2009-03-19) */ protected $cache_file_length = array(); /** * Table header content to be repeated on each new page. * @protected * @since 4.5.030 (2009-03-20) */ protected $thead = ''; /** * Margins used for table header. * @protected * @since 4.5.030 (2009-03-20) */ protected $theadMargins = array(); /** * Cache array for UTF8StringToArray() method. * @protected * @since 4.5.037 (2009-04-07) */ protected $cache_UTF8StringToArray = array(); /** * Maximum size of cache array used for UTF8StringToArray() method. * @protected * @since 4.5.037 (2009-04-07) */ protected $cache_maxsize_UTF8StringToArray = 8; /** * Current size of cache array used for UTF8StringToArray() method. * @protected * @since 4.5.037 (2009-04-07) */ protected $cache_size_UTF8StringToArray = 0; /** * Boolean flag to enable document digital signature. * @protected * @since 4.6.005 (2009-04-24) */ protected $sign = false; /** * Digital signature data. * @protected * @since 4.6.005 (2009-04-24) */ protected $signature_data = array(); /** * Digital signature max length. * @protected * @since 4.6.005 (2009-04-24) */ protected $signature_max_length = 11742; /** * Data for digital signature appearance. * @protected * @since 5.3.011 (2010-06-16) */ protected $signature_appearance = array('page' => 1, 'rect' => '0 0 0 0'); /** * Array of empty digital signature appearances. * @protected * @since 5.9.101 (2011-07-06) */ protected $empty_signature_appearance = array(); /** * Regular expression used to find blank characters (required for word-wrapping). * @protected * @since 4.6.006 (2009-04-28) */ protected $re_spaces = '/[^\S\xa0]/'; /** * Array of $re_spaces parts. * @protected * @since 5.5.011 (2010-07-09) */ protected $re_space = array('p' => '[^\S\xa0]', 'm' => ''); /** * Digital signature object ID. * @protected * @since 4.6.022 (2009-06-23) */ protected $sig_obj_id = 0; /** * ByteRange placemark used during digital signature process. * @protected * @since 4.6.028 (2009-08-25) */ protected $byterange_string = '/ByteRange[0 ********** ********** **********]'; /** * Placemark used during digital signature process. * @protected * @since 4.6.028 (2009-08-25) */ protected $sig_annot_ref = '***SIGANNREF*** 0 R'; /** * ID of page objects. * @protected * @since 4.7.000 (2009-08-29) */ protected $page_obj_id = array(); /** * List of form annotations IDs. * @protected * @since 4.8.000 (2009-09-07) */ protected $form_obj_id = array(); /** * Deafult Javascript field properties. Possible values are described on official Javascript for Acrobat API reference. Annotation options can be directly specified using the 'aopt' entry. * @protected * @since 4.8.000 (2009-09-07) */ protected $default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128)); /** * Javascript objects array. * @protected * @since 4.8.000 (2009-09-07) */ protected $js_objects = array(); /** * Current form action (used during XHTML rendering). * @protected * @since 4.8.000 (2009-09-07) */ protected $form_action = ''; /** * Current form encryption type (used during XHTML rendering). * @protected * @since 4.8.000 (2009-09-07) */ protected $form_enctype = 'application/x-www-form-urlencoded'; /** * Current method to submit forms. * @protected * @since 4.8.000 (2009-09-07) */ protected $form_mode = 'post'; /** * List of fonts used on form fields (fontname => fontkey). * @protected * @since 4.8.001 (2009-09-09) */ protected $annotation_fonts = array(); /** * List of radio buttons parent objects. * @protected * @since 4.8.001 (2009-09-09) */ protected $radiobutton_groups = array(); /** * List of radio group objects IDs. * @protected * @since 4.8.001 (2009-09-09) */ protected $radio_groups = array(); /** * Text indentation value (used for text-indent CSS attribute). * @protected * @since 4.8.006 (2009-09-23) */ protected $textindent = 0; /** * Store page number when startTransaction() is called. * @protected * @since 4.8.006 (2009-09-23) */ protected $start_transaction_page = 0; /** * Store Y position when startTransaction() is called. * @protected * @since 4.9.001 (2010-03-28) */ protected $start_transaction_y = 0; /** * True when we are printing the thead section on a new page. * @protected * @since 4.8.027 (2010-01-25) */ protected $inthead = false; /** * Array of column measures (width, space, starting Y position). * @protected * @since 4.9.001 (2010-03-28) */ protected $columns = array(); /** * Number of colums. * @protected * @since 4.9.001 (2010-03-28) */ protected $num_columns = 1; /** * Current column number. * @protected * @since 4.9.001 (2010-03-28) */ protected $current_column = 0; /** * Starting page for columns. * @protected * @since 4.9.001 (2010-03-28) */ protected $column_start_page = 0; /** * Maximum page and column selected. * @protected * @since 5.8.000 (2010-08-11) */ protected $maxselcol = array('page' => 0, 'column' => 0); /** * Array of: X difference between table cell x start and starting page margin, cellspacing, cellpadding. * @protected * @since 5.8.000 (2010-08-11) */ protected $colxshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0)); /** * Text rendering mode: 0 = Fill text; 1 = Stroke text; 2 = Fill, then stroke text; 3 = Neither fill nor stroke text (invisible); 4 = Fill text and add to path for clipping; 5 = Stroke text and add to path for clipping; 6 = Fill, then stroke text and add to path for clipping; 7 = Add text to path for clipping. * @protected * @since 4.9.008 (2010-04-03) */ protected $textrendermode = 0; /** * Text stroke width in doc units. * @protected * @since 4.9.008 (2010-04-03) */ protected $textstrokewidth = 0; /** * Current stroke color. * @protected * @since 4.9.008 (2010-04-03) */ protected $strokecolor; /** * Default unit of measure for document. * @protected * @since 5.0.000 (2010-04-22) */ protected $pdfunit = 'mm'; /** * Boolean flag true when we are on TOC (Table Of Content) page. * @protected */ protected $tocpage = false; /** * Boolean flag: if true convert vector images (SVG, EPS) to raster image using GD or ImageMagick library. * @protected * @since 5.0.000 (2010-04-26) */ protected $rasterize_vector_images = false; /** * Boolean flag: if true enables font subsetting by default. * @protected * @since 5.3.002 (2010-06-07) */ protected $font_subsetting = true; /** * Array of default graphic settings. * @protected * @since 5.5.008 (2010-07-02) */ protected $default_graphic_vars = array(); /** * Array of XObjects. * @protected * @since 5.8.014 (2010-08-23) */ protected $xobjects = array(); /** * Boolean value true when we are inside an XObject. * @protected * @since 5.8.017 (2010-08-24) */ protected $inxobj = false; /** * Current XObject ID. * @protected * @since 5.8.017 (2010-08-24) */ protected $xobjid = ''; /** * Percentage of character stretching. * @protected * @since 5.9.000 (2010-09-29) */ protected $font_stretching = 100; /** * Increases or decreases the space between characters in a text by the specified amount (tracking/kerning). * @protected * @since 5.9.000 (2010-09-29) */ protected $font_spacing = 0; /** * Array of no-write regions. * ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right) * @protected * @since 5.9.003 (2010-10-14) */ protected $page_regions = array(); /** * Array containing HTML color names and values. * @protected * @since 5.9.004 (2010-10-18) */ protected $webcolor = array(); /** * Array containing spot color names and values. * @protected * @since 5.9.012 (2010-11-11) */ protected $spotcolor = array(); /** * Array of PDF layers data. * @protected * @since 5.9.102 (2011-07-13) */ protected $pdflayers = array(); /** * A dictionary of names and corresponding destinations (Dests key on document Catalog). * @protected * @since 5.9.097 (2011-06-23) */ protected $dests = array(); /** * Object ID for Named Destinations * @protected * @since 5.9.097 (2011-06-23) */ protected $n_dests; /** * Directory used for the last SVG image. * @protected * @since 5.0.000 (2010-05-05) */ protected $svgdir = ''; /** * Deafult unit of measure for SVG. * @protected * @since 5.0.000 (2010-05-02) */ protected $svgunit = 'px'; /** * Array of SVG gradients. * @protected * @since 5.0.000 (2010-05-02) */ protected $svggradients = array(); /** * ID of last SVG gradient. * @protected * @since 5.0.000 (2010-05-02) */ protected $svggradientid = 0; /** * Boolean value true when in SVG defs group. * @protected * @since 5.0.000 (2010-05-02) */ protected $svgdefsmode = false; /** * Array of SVG defs. * @protected * @since 5.0.000 (2010-05-02) */ protected $svgdefs = array(); /** * Boolean value true when in SVG clipPath tag. * @protected * @since 5.0.000 (2010-04-26) */ protected $svgclipmode = false; /** * Array of SVG clipPath commands. * @protected * @since 5.0.000 (2010-05-02) */ protected $svgclippaths = array(); /** * Array of SVG clipPath tranformation matrix. * @protected * @since 5.8.022 (2010-08-31) */ protected $svgcliptm = array(); /** * ID of last SVG clipPath. * @protected * @since 5.0.000 (2010-05-02) */ protected $svgclipid = 0; /** * SVG text. * @protected * @since 5.0.000 (2010-05-02) */ protected $svgtext = ''; /** * SVG text properties. * @protected * @since 5.8.013 (2010-08-23) */ protected $svgtextmode = array(); /** * Array of hinheritable SVG properties. * @protected * @since 5.0.000 (2010-05-02) */ protected $svginheritprop = array('clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'fill', 'fill-opacity', 'fill-rule', 'font', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'marker', 'marker-end', 'marker-mid', 'marker-start', 'pointer-events', 'shape-rendering', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-rendering', 'visibility', 'word-spacing', 'writing-mode'); /** * Array of SVG properties. * @protected * @since 5.0.000 (2010-05-02) */ protected $svgstyles = array(array( 'alignment-baseline' => 'auto', 'baseline-shift' => 'baseline', 'clip' => 'auto', 'clip-path' => 'none', 'clip-rule' => 'nonzero', 'color' => 'black', 'color-interpolation' => 'sRGB', 'color-interpolation-filters' => 'linearRGB', 'color-profile' => 'auto', 'color-rendering' => 'auto', 'cursor' => 'auto', 'direction' => 'ltr', 'display' => 'inline', 'dominant-baseline' => 'auto', 'enable-background' => 'accumulate', 'fill' => 'black', 'fill-opacity' => 1, 'fill-rule' => 'nonzero', 'filter' => 'none', 'flood-color' => 'black', 'flood-opacity' => 1, 'font' => '', 'font-family' => 'helvetica', 'font-size' => 'medium', 'font-size-adjust' => 'none', 'font-stretch' => 'normal', 'font-style' => 'normal', 'font-variant' => 'normal', 'font-weight' => 'normal', 'glyph-orientation-horizontal' => '0deg', 'glyph-orientation-vertical' => 'auto', 'image-rendering' => 'auto', 'kerning' => 'auto', 'letter-spacing' => 'normal', 'lighting-color' => 'white', 'marker' => '', 'marker-end' => 'none', 'marker-mid' => 'none', 'marker-start' => 'none', 'mask' => 'none', 'opacity' => 1, 'overflow' => 'auto', 'pointer-events' => 'visiblePainted', 'shape-rendering' => 'auto', 'stop-color' => 'black', 'stop-opacity' => 1, 'stroke' => 'none', 'stroke-dasharray' => 'none', 'stroke-dashoffset' => 0, 'stroke-linecap' => 'butt', 'stroke-linejoin' => 'miter', 'stroke-miterlimit' => 4, 'stroke-opacity' => 1, 'stroke-width' => 1, 'text-anchor' => 'start', 'text-decoration' => 'none', 'text-rendering' => 'auto', 'unicode-bidi' => 'normal', 'visibility' => 'visible', 'word-spacing' => 'normal', 'writing-mode' => 'lr-tb', 'text-color' => 'black', 'transfmatrix' => array(1, 0, 0, 1, 0, 0) )); /** * If true force sRGB color profile for all document. * @protected * @since 5.9.121 (2011-09-28) */ protected $force_srgb = false; /** * If true set the document to PDF/A mode. * @protected * @since 5.9.121 (2011-09-27) */ protected $pdfa_mode = false; /** * Document creation date * @protected * @since 5.9.121 (2011-09-28) */ protected $doc_date; /** * Custom XMP data. * @protected * @since 5.9.128 (2011-10-06) */ protected $custom_xmp = ''; //------------------------------------------------------------ // METHODS //------------------------------------------------------------ /** * This is the class constructor. * It allows to set up the page format, the orientation and the measure unit used in all the methods (except for the font sizes). * @param $orientation (string) page orientation. Possible values are (case insensitive): * @param $unit (string) User measure unit. Possible values are:
    A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit. * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). * @param $unicode (boolean) TRUE means that the input text is unicode (default = true) * @param $encoding (string) Charset encoding; default is UTF-8. * @param $diskcache (boolean) If TRUE reduce the RAM memory usage by caching temporary data on filesystem (slower). * @param $pdfa (boolean) If TRUE set the document to PDF/A mode. * @public * @see getPageSizeFromFormat(), setPageFormat() */ public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) { /* Set internal character encoding to ASCII */ if (function_exists('mb_internal_encoding') AND mb_internal_encoding()) { $this->internal_encoding = mb_internal_encoding(); mb_internal_encoding('ASCII'); } // get array of HTML colors require(dirname(__FILE__).'/htmlcolors.php'); $this->webcolor = $webcolor; // get array of custom spot colors if (file_exists(dirname(__FILE__).'/spotcolors.php')) { require(dirname(__FILE__).'/spotcolors.php'); $this->spotcolor = $spotcolor; } else { $this->spotcolor = array(); } require_once(dirname(__FILE__).'/unicode_data.php'); $this->unicode = new TCPDF_UNICODE_DATA(); require_once(dirname(__FILE__).'/encodings_maps.php'); $this->encmaps = new TCPDF_ENCODING_MAPS(); $this->font_obj_ids = array(); $this->page_obj_id = array(); $this->form_obj_id = array(); // set pdf/a mode $this->pdfa_mode = $pdfa; $this->force_srgb = false; // set disk caching $this->diskcache = $diskcache ? true : false; // set language direction $this->rtl = false; $this->tmprtl = false; // some checks $this->_dochecks(); // initialization of properties $this->isunicode = $unicode; $this->page = 0; $this->transfmrk[0] = array(); $this->pagedim = array(); $this->n = 2; $this->buffer = ''; $this->pages = array(); $this->state = 0; $this->fonts = array(); $this->FontFiles = array(); $this->diffs = array(); $this->images = array(); $this->links = array(); $this->gradients = array(); $this->InFooter = false; $this->lasth = 0; $this->FontFamily = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica'; $this->FontStyle = ''; $this->FontSizePt = 12; $this->underline = false; $this->overline = false; $this->linethrough = false; $this->DrawColor = '0 G'; $this->FillColor = '0 g'; $this->TextColor = '0 g'; $this->ColorFlag = false; $this->pdflayers = array(); // encryption values $this->encrypted = false; $this->last_enc_key = ''; // standard Unicode fonts $this->CoreFonts = array( 'courier'=>'Courier', 'courierB'=>'Courier-Bold', 'courierI'=>'Courier-Oblique', 'courierBI'=>'Courier-BoldOblique', 'helvetica'=>'Helvetica', 'helveticaB'=>'Helvetica-Bold', 'helveticaI'=>'Helvetica-Oblique', 'helveticaBI'=>'Helvetica-BoldOblique', 'times'=>'Times-Roman', 'timesB'=>'Times-Bold', 'timesI'=>'Times-Italic', 'timesBI'=>'Times-BoldItalic', 'symbol'=>'Symbol', 'zapfdingbats'=>'ZapfDingbats' ); // set scale factor $this->setPageUnit($unit); // set page format and orientation $this->setPageFormat($format, $orientation); // page margins (1 cm) $margin = 28.35 / $this->k; $this->SetMargins($margin, $margin); // internal cell padding $cpadding = $margin / 10; $this->setCellPaddings($cpadding, 0, $cpadding, 0); // cell margins $this->setCellMargins(0, 0, 0, 0); // line width (0.2 mm) $this->LineWidth = 0.57 / $this->k; $this->linestyleWidth = sprintf('%.2F w', ($this->LineWidth * $this->k)); $this->linestyleCap = '0 J'; $this->linestyleJoin = '0 j'; $this->linestyleDash = '[] 0 d'; // automatic page break $this->SetAutoPageBreak(true, (2 * $margin)); // full width display mode $this->SetDisplayMode('fullwidth'); // compression $this->SetCompression(); // set default PDF version number $this->setPDFVersion(); $this->encoding = $encoding; $this->HREF = array(); $this->getFontsList(); $this->fgcolor = array('R' => 0, 'G' => 0, 'B' => 0); $this->strokecolor = array('R' => 0, 'G' => 0, 'B' => 0); $this->bgcolor = array('R' => 255, 'G' => 255, 'B' => 255); $this->extgstates = array(); // user's rights $this->sign = false; $this->ur['enabled'] = false; $this->ur['document'] = '/FullSave'; $this->ur['annots'] = '/Create/Delete/Modify/Copy/Import/Export'; $this->ur['form'] = '/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate'; $this->ur['signature'] = '/Modify'; $this->ur['ef'] = '/Create/Delete/Modify/Import'; $this->ur['formex'] = ''; $this->signature_appearance = array('page' => 1, 'rect' => '0 0 0 0'); $this->empty_signature_appearance = array(); // set default JPEG quality $this->jpeg_quality = 75; // initialize some settings $this->utf8Bidi(array(''), ''); // set default font $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt); // check if PCRE Unicode support is enabled if ($this->isunicode AND (@preg_match('/\pL/u', 'a') == 1)) { // PCRE unicode support is turned ON // \p{Z} or \p{Separator}: any kind of Unicode whitespace or invisible separator. // \p{Lo} or \p{Other_Letter}: a Unicode letter or ideograph that does not have lowercase and uppercase variants. // \p{Lo} is needed because Chinese characters are packed next to each other without spaces in between. //$this->setSpacesRE('/[^\S\P{Z}\P{Lo}\xa0]/u'); $this->setSpacesRE('/[^\S\P{Z}\xa0]/u'); } else { // PCRE unicode support is turned OFF $this->setSpacesRE('/[^\S\xa0]/'); } $this->default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128)); // set file ID for trailer $this->file_id = md5($this->getRandomSeed('TCPDF'.$orientation.$unit.$format.$encoding)); // set document date $this->doc_date = substr_replace(date('YmdHisO'), '\'', (0 - 2), 0).'\''; // get default graphic vars $this->default_graphic_vars = $this->getGraphicVars(); $this->header_xobj_autoreset = false; $this->custom_xmp = ''; } /** * Default destructor. * @public * @since 1.53.0.TC016 */ public function __destruct() { // restore internal encoding if (isset($this->internal_encoding) AND !empty($this->internal_encoding)) { mb_internal_encoding($this->internal_encoding); } // unset all class variables $this->_destroy(true); } /** * Return the current TCPDF version. * @return TCPDF version string * @public * @since 5.9.012 (2010-11-10) */ public function getTCPDFVersion() { return $this->tcpdf_version; } /** * Wrapper for file_exists. * Checks whether a file or directory exists. * Only allows some protocols and local files. * @param filename (string) Path to the file or directory. * @return Returns TRUE if the file or directory specified by filename exists; FALSE otherwise. * @public static */ public function file_exists($filename) { if (strpos($filename, '://') > 0) { $wrappers = stream_get_wrappers(); foreach ($wrappers as $wrapper) { if (($wrapper === 'http') || ($wrapper === 'https')) { continue; } if (stripos($filename, $wrapper.'://') === 0) { return false; } } } return @file_exists($filename); } /** * Set the units of measure for the document. * @param $unit (string) User measure unit. Possible values are:
    A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit. * @public * @since 3.0.015 (2008-06-06) */ public function setPageUnit($unit) { $unit = strtolower($unit); //Set scale factor switch ($unit) { // points case 'px': case 'pt': { $this->k = 1; break; } // millimeters case 'mm': { $this->k = $this->dpi / 25.4; break; } // centimeters case 'cm': { $this->k = $this->dpi / 2.54; break; } // inches case 'in': { $this->k = $this->dpi; break; } // unsupported unit default : { $this->Error('Incorrect unit: '.$unit); break; } } $this->pdfunit = $unit; if (isset($this->CurOrientation)) { $this->setPageOrientation($this->CurOrientation); } } /** * Get page dimensions from format name. * @param $format (mixed) The format name. It can be: * @return array containing page width and height in points * @public * @since 5.0.010 (2010-05-17) */ public function getPageSizeFromFormat($format) { // Paper cordinates are calculated in this way: (inches * 72) where (1 inch = 25.4 mm) switch (strtoupper($format)) { // ISO 216 A Series + 2 SIS 014711 extensions case 'A0' : {$pf = array( 2383.937, 3370.394); break;} case 'A1' : {$pf = array( 1683.780, 2383.937); break;} case 'A2' : {$pf = array( 1190.551, 1683.780); break;} case 'A3' : {$pf = array( 841.890, 1190.551); break;} case 'A4' : {$pf = array( 595.276, 841.890); break;} case 'A5' : {$pf = array( 419.528, 595.276); break;} case 'A6' : {$pf = array( 297.638, 419.528); break;} case 'A7' : {$pf = array( 209.764, 297.638); break;} case 'A8' : {$pf = array( 147.402, 209.764); break;} case 'A9' : {$pf = array( 104.882, 147.402); break;} case 'A10': {$pf = array( 73.701, 104.882); break;} case 'A11': {$pf = array( 51.024, 73.701); break;} case 'A12': {$pf = array( 36.850, 51.024); break;} // ISO 216 B Series + 2 SIS 014711 extensions case 'B0' : {$pf = array( 2834.646, 4008.189); break;} case 'B1' : {$pf = array( 2004.094, 2834.646); break;} case 'B2' : {$pf = array( 1417.323, 2004.094); break;} case 'B3' : {$pf = array( 1000.630, 1417.323); break;} case 'B4' : {$pf = array( 708.661, 1000.630); break;} case 'B5' : {$pf = array( 498.898, 708.661); break;} case 'B6' : {$pf = array( 354.331, 498.898); break;} case 'B7' : {$pf = array( 249.449, 354.331); break;} case 'B8' : {$pf = array( 175.748, 249.449); break;} case 'B9' : {$pf = array( 124.724, 175.748); break;} case 'B10': {$pf = array( 87.874, 124.724); break;} case 'B11': {$pf = array( 62.362, 87.874); break;} case 'B12': {$pf = array( 42.520, 62.362); break;} // ISO 216 C Series + 2 SIS 014711 extensions + 2 EXTENSION case 'C0' : {$pf = array( 2599.370, 3676.535); break;} case 'C1' : {$pf = array( 1836.850, 2599.370); break;} case 'C2' : {$pf = array( 1298.268, 1836.850); break;} case 'C3' : {$pf = array( 918.425, 1298.268); break;} case 'C4' : {$pf = array( 649.134, 918.425); break;} case 'C5' : {$pf = array( 459.213, 649.134); break;} case 'C6' : {$pf = array( 323.150, 459.213); break;} case 'C7' : {$pf = array( 229.606, 323.150); break;} case 'C8' : {$pf = array( 161.575, 229.606); break;} case 'C9' : {$pf = array( 113.386, 161.575); break;} case 'C10': {$pf = array( 79.370, 113.386); break;} case 'C11': {$pf = array( 56.693, 79.370); break;} case 'C12': {$pf = array( 39.685, 56.693); break;} case 'C76': {$pf = array( 229.606, 459.213); break;} case 'DL' : {$pf = array( 311.811, 623.622); break;} // SIS 014711 E Series case 'E0' : {$pf = array( 2491.654, 3517.795); break;} case 'E1' : {$pf = array( 1757.480, 2491.654); break;} case 'E2' : {$pf = array( 1247.244, 1757.480); break;} case 'E3' : {$pf = array( 878.740, 1247.244); break;} case 'E4' : {$pf = array( 623.622, 878.740); break;} case 'E5' : {$pf = array( 439.370, 623.622); break;} case 'E6' : {$pf = array( 311.811, 439.370); break;} case 'E7' : {$pf = array( 221.102, 311.811); break;} case 'E8' : {$pf = array( 155.906, 221.102); break;} case 'E9' : {$pf = array( 110.551, 155.906); break;} case 'E10': {$pf = array( 76.535, 110.551); break;} case 'E11': {$pf = array( 53.858, 76.535); break;} case 'E12': {$pf = array( 36.850, 53.858); break;} // SIS 014711 G Series case 'G0' : {$pf = array( 2715.591, 3838.110); break;} case 'G1' : {$pf = array( 1919.055, 2715.591); break;} case 'G2' : {$pf = array( 1357.795, 1919.055); break;} case 'G3' : {$pf = array( 958.110, 1357.795); break;} case 'G4' : {$pf = array( 677.480, 958.110); break;} case 'G5' : {$pf = array( 479.055, 677.480); break;} case 'G6' : {$pf = array( 337.323, 479.055); break;} case 'G7' : {$pf = array( 238.110, 337.323); break;} case 'G8' : {$pf = array( 167.244, 238.110); break;} case 'G9' : {$pf = array( 119.055, 167.244); break;} case 'G10': {$pf = array( 82.205, 119.055); break;} case 'G11': {$pf = array( 59.528, 82.205); break;} case 'G12': {$pf = array( 39.685, 59.528); break;} // ISO Press case 'RA0': {$pf = array( 2437.795, 3458.268); break;} case 'RA1': {$pf = array( 1729.134, 2437.795); break;} case 'RA2': {$pf = array( 1218.898, 1729.134); break;} case 'RA3': {$pf = array( 864.567, 1218.898); break;} case 'RA4': {$pf = array( 609.449, 864.567); break;} case 'SRA0': {$pf = array( 2551.181, 3628.346); break;} case 'SRA1': {$pf = array( 1814.173, 2551.181); break;} case 'SRA2': {$pf = array( 1275.591, 1814.173); break;} case 'SRA3': {$pf = array( 907.087, 1275.591); break;} case 'SRA4': {$pf = array( 637.795, 907.087); break;} // German DIN 476 case '4A0': {$pf = array( 4767.874, 6740.787); break;} case '2A0': {$pf = array( 3370.394, 4767.874); break;} // Variations on the ISO Standard case 'A2_EXTRA' : {$pf = array( 1261.417, 1754.646); break;} case 'A3+' : {$pf = array( 932.598, 1369.134); break;} case 'A3_EXTRA' : {$pf = array( 912.756, 1261.417); break;} case 'A3_SUPER' : {$pf = array( 864.567, 1440.000); break;} case 'SUPER_A3' : {$pf = array( 864.567, 1380.472); break;} case 'A4_EXTRA' : {$pf = array( 666.142, 912.756); break;} case 'A4_SUPER' : {$pf = array( 649.134, 912.756); break;} case 'SUPER_A4' : {$pf = array( 643.465, 1009.134); break;} case 'A4_LONG' : {$pf = array( 595.276, 986.457); break;} case 'F4' : {$pf = array( 595.276, 935.433); break;} case 'SO_B5_EXTRA': {$pf = array( 572.598, 782.362); break;} case 'A5_EXTRA' : {$pf = array( 490.394, 666.142); break;} // ANSI Series case 'ANSI_E': {$pf = array( 2448.000, 3168.000); break;} case 'ANSI_D': {$pf = array( 1584.000, 2448.000); break;} case 'ANSI_C': {$pf = array( 1224.000, 1584.000); break;} case 'ANSI_B': {$pf = array( 792.000, 1224.000); break;} case 'ANSI_A': {$pf = array( 612.000, 792.000); break;} // Traditional 'Loose' North American Paper Sizes case 'USLEDGER': case 'LEDGER' : {$pf = array( 1224.000, 792.000); break;} case 'ORGANIZERK': case 'BIBLE': case 'USTABLOID': case 'TABLOID': {$pf = array( 792.000, 1224.000); break;} case 'ORGANIZERM': case 'USLETTER': case 'LETTER' : {$pf = array( 612.000, 792.000); break;} case 'USLEGAL': case 'LEGAL' : {$pf = array( 612.000, 1008.000); break;} case 'GOVERNMENTLETTER': case 'GLETTER': {$pf = array( 576.000, 756.000); break;} case 'JUNIORLEGAL': case 'JLEGAL' : {$pf = array( 576.000, 360.000); break;} // Other North American Paper Sizes case 'QUADDEMY': {$pf = array( 2520.000, 3240.000); break;} case 'SUPER_B': {$pf = array( 936.000, 1368.000); break;} case 'QUARTO': {$pf = array( 648.000, 792.000); break;} case 'GOVERNMENTLEGAL': case 'FOLIO': {$pf = array( 612.000, 936.000); break;} case 'MONARCH': case 'EXECUTIVE': {$pf = array( 522.000, 756.000); break;} case 'ORGANIZERL': case 'STATEMENT': case 'MEMO': {$pf = array( 396.000, 612.000); break;} case 'FOOLSCAP': {$pf = array( 595.440, 936.000); break;} case 'COMPACT': {$pf = array( 306.000, 486.000); break;} case 'ORGANIZERJ': {$pf = array( 198.000, 360.000); break;} // Canadian standard CAN 2-9.60M case 'P1': {$pf = array( 1587.402, 2437.795); break;} case 'P2': {$pf = array( 1218.898, 1587.402); break;} case 'P3': {$pf = array( 793.701, 1218.898); break;} case 'P4': {$pf = array( 609.449, 793.701); break;} case 'P5': {$pf = array( 396.850, 609.449); break;} case 'P6': {$pf = array( 303.307, 396.850); break;} // North American Architectural Sizes case 'ARCH_E' : {$pf = array( 2592.000, 3456.000); break;} case 'ARCH_E1': {$pf = array( 2160.000, 3024.000); break;} case 'ARCH_D' : {$pf = array( 1728.000, 2592.000); break;} case 'BROADSHEET': case 'ARCH_C' : {$pf = array( 1296.000, 1728.000); break;} case 'ARCH_B' : {$pf = array( 864.000, 1296.000); break;} case 'ARCH_A' : {$pf = array( 648.000, 864.000); break;} // --- North American Envelope Sizes --- // - Announcement Envelopes case 'ANNENV_A2' : {$pf = array( 314.640, 414.000); break;} case 'ANNENV_A6' : {$pf = array( 342.000, 468.000); break;} case 'ANNENV_A7' : {$pf = array( 378.000, 522.000); break;} case 'ANNENV_A8' : {$pf = array( 396.000, 584.640); break;} case 'ANNENV_A10' : {$pf = array( 450.000, 692.640); break;} case 'ANNENV_SLIM': {$pf = array( 278.640, 638.640); break;} // - Commercial Envelopes case 'COMMENV_N6_1/4': {$pf = array( 252.000, 432.000); break;} case 'COMMENV_N6_3/4': {$pf = array( 260.640, 468.000); break;} case 'COMMENV_N8' : {$pf = array( 278.640, 540.000); break;} case 'COMMENV_N9' : {$pf = array( 278.640, 638.640); break;} case 'COMMENV_N10' : {$pf = array( 296.640, 684.000); break;} case 'COMMENV_N11' : {$pf = array( 324.000, 746.640); break;} case 'COMMENV_N12' : {$pf = array( 342.000, 792.000); break;} case 'COMMENV_N14' : {$pf = array( 360.000, 828.000); break;} // - Catalogue Envelopes case 'CATENV_N1' : {$pf = array( 432.000, 648.000); break;} case 'CATENV_N1_3/4' : {$pf = array( 468.000, 684.000); break;} case 'CATENV_N2' : {$pf = array( 468.000, 720.000); break;} case 'CATENV_N3' : {$pf = array( 504.000, 720.000); break;} case 'CATENV_N6' : {$pf = array( 540.000, 756.000); break;} case 'CATENV_N7' : {$pf = array( 576.000, 792.000); break;} case 'CATENV_N8' : {$pf = array( 594.000, 810.000); break;} case 'CATENV_N9_1/2' : {$pf = array( 612.000, 756.000); break;} case 'CATENV_N9_3/4' : {$pf = array( 630.000, 810.000); break;} case 'CATENV_N10_1/2': {$pf = array( 648.000, 864.000); break;} case 'CATENV_N12_1/2': {$pf = array( 684.000, 900.000); break;} case 'CATENV_N13_1/2': {$pf = array( 720.000, 936.000); break;} case 'CATENV_N14_1/4': {$pf = array( 810.000, 882.000); break;} case 'CATENV_N14_1/2': {$pf = array( 828.000, 1044.000); break;} // Japanese (JIS P 0138-61) Standard B-Series case 'JIS_B0' : {$pf = array( 2919.685, 4127.244); break;} case 'JIS_B1' : {$pf = array( 2063.622, 2919.685); break;} case 'JIS_B2' : {$pf = array( 1459.843, 2063.622); break;} case 'JIS_B3' : {$pf = array( 1031.811, 1459.843); break;} case 'JIS_B4' : {$pf = array( 728.504, 1031.811); break;} case 'JIS_B5' : {$pf = array( 515.906, 728.504); break;} case 'JIS_B6' : {$pf = array( 362.835, 515.906); break;} case 'JIS_B7' : {$pf = array( 257.953, 362.835); break;} case 'JIS_B8' : {$pf = array( 181.417, 257.953); break;} case 'JIS_B9' : {$pf = array( 127.559, 181.417); break;} case 'JIS_B10': {$pf = array( 90.709, 127.559); break;} case 'JIS_B11': {$pf = array( 62.362, 90.709); break;} case 'JIS_B12': {$pf = array( 45.354, 62.362); break;} // PA Series case 'PA0' : {$pf = array( 2381.102, 3174.803,); break;} case 'PA1' : {$pf = array( 1587.402, 2381.102); break;} case 'PA2' : {$pf = array( 1190.551, 1587.402); break;} case 'PA3' : {$pf = array( 793.701, 1190.551); break;} case 'PA4' : {$pf = array( 595.276, 793.701); break;} case 'PA5' : {$pf = array( 396.850, 595.276); break;} case 'PA6' : {$pf = array( 297.638, 396.850); break;} case 'PA7' : {$pf = array( 198.425, 297.638); break;} case 'PA8' : {$pf = array( 147.402, 198.425); break;} case 'PA9' : {$pf = array( 99.213, 147.402); break;} case 'PA10': {$pf = array( 73.701, 99.213); break;} // Standard Photographic Print Sizes case 'PASSPORT_PHOTO': {$pf = array( 99.213, 127.559); break;} case 'E' : {$pf = array( 233.858, 340.157); break;} case 'L': case '3R' : {$pf = array( 252.283, 360.000); break;} case 'KG': case '4R' : {$pf = array( 289.134, 430.866); break;} case '4D' : {$pf = array( 340.157, 430.866); break;} case '2L': case '5R' : {$pf = array( 360.000, 504.567); break;} case '8P': case '6R' : {$pf = array( 430.866, 575.433); break;} case '6P': case '8R' : {$pf = array( 575.433, 720.000); break;} case '6PW': case 'S8R' : {$pf = array( 575.433, 864.567); break;} case '4P': case '10R' : {$pf = array( 720.000, 864.567); break;} case '4PW': case 'S10R': {$pf = array( 720.000, 1080.000); break;} case '11R' : {$pf = array( 790.866, 1009.134); break;} case 'S11R': {$pf = array( 790.866, 1224.567); break;} case '12R' : {$pf = array( 864.567, 1080.000); break;} case 'S12R': {$pf = array( 864.567, 1292.598); break;} // Common Newspaper Sizes case 'NEWSPAPER_BROADSHEET': {$pf = array( 2125.984, 1700.787); break;} case 'NEWSPAPER_BERLINER' : {$pf = array( 1332.283, 892.913); break;} case 'NEWSPAPER_TABLOID': case 'NEWSPAPER_COMPACT' : {$pf = array( 1218.898, 793.701); break;} // Business Cards case 'CREDIT_CARD': case 'BUSINESS_CARD': case 'BUSINESS_CARD_ISO7810': {$pf = array( 153.014, 242.646); break;} case 'BUSINESS_CARD_ISO216' : {$pf = array( 147.402, 209.764); break;} case 'BUSINESS_CARD_IT': case 'BUSINESS_CARD_UK': case 'BUSINESS_CARD_FR': case 'BUSINESS_CARD_DE': case 'BUSINESS_CARD_ES' : {$pf = array( 155.906, 240.945); break;} case 'BUSINESS_CARD_CA': case 'BUSINESS_CARD_US' : {$pf = array( 144.567, 252.283); break;} case 'BUSINESS_CARD_JP' : {$pf = array( 155.906, 257.953); break;} case 'BUSINESS_CARD_HK' : {$pf = array( 153.071, 255.118); break;} case 'BUSINESS_CARD_AU': case 'BUSINESS_CARD_DK': case 'BUSINESS_CARD_SE' : {$pf = array( 155.906, 255.118); break;} case 'BUSINESS_CARD_RU': case 'BUSINESS_CARD_CZ': case 'BUSINESS_CARD_FI': case 'BUSINESS_CARD_HU': case 'BUSINESS_CARD_IL' : {$pf = array( 141.732, 255.118); break;} // Billboards case '4SHEET' : {$pf = array( 2880.000, 4320.000); break;} case '6SHEET' : {$pf = array( 3401.575, 5102.362); break;} case '12SHEET': {$pf = array( 8640.000, 4320.000); break;} case '16SHEET': {$pf = array( 5760.000, 8640.000); break;} case '32SHEET': {$pf = array(11520.000, 8640.000); break;} case '48SHEET': {$pf = array(17280.000, 8640.000); break;} case '64SHEET': {$pf = array(23040.000, 8640.000); break;} case '96SHEET': {$pf = array(34560.000, 8640.000); break;} // Old European Sizes // - Old Imperial English Sizes case 'EN_EMPEROR' : {$pf = array( 3456.000, 5184.000); break;} case 'EN_ANTIQUARIAN' : {$pf = array( 2232.000, 3816.000); break;} case 'EN_GRAND_EAGLE' : {$pf = array( 2070.000, 3024.000); break;} case 'EN_DOUBLE_ELEPHANT' : {$pf = array( 1926.000, 2880.000); break;} case 'EN_ATLAS' : {$pf = array( 1872.000, 2448.000); break;} case 'EN_COLOMBIER' : {$pf = array( 1692.000, 2484.000); break;} case 'EN_ELEPHANT' : {$pf = array( 1656.000, 2016.000); break;} case 'EN_DOUBLE_DEMY' : {$pf = array( 1620.000, 2556.000); break;} case 'EN_IMPERIAL' : {$pf = array( 1584.000, 2160.000); break;} case 'EN_PRINCESS' : {$pf = array( 1548.000, 2016.000); break;} case 'EN_CARTRIDGE' : {$pf = array( 1512.000, 1872.000); break;} case 'EN_DOUBLE_LARGE_POST': {$pf = array( 1512.000, 2376.000); break;} case 'EN_ROYAL' : {$pf = array( 1440.000, 1800.000); break;} case 'EN_SHEET': case 'EN_HALF_POST' : {$pf = array( 1404.000, 1692.000); break;} case 'EN_SUPER_ROYAL' : {$pf = array( 1368.000, 1944.000); break;} case 'EN_DOUBLE_POST' : {$pf = array( 1368.000, 2196.000); break;} case 'EN_MEDIUM' : {$pf = array( 1260.000, 1656.000); break;} case 'EN_DEMY' : {$pf = array( 1260.000, 1620.000); break;} case 'EN_LARGE_POST' : {$pf = array( 1188.000, 1512.000); break;} case 'EN_COPY_DRAUGHT' : {$pf = array( 1152.000, 1440.000); break;} case 'EN_POST' : {$pf = array( 1116.000, 1386.000); break;} case 'EN_CROWN' : {$pf = array( 1080.000, 1440.000); break;} case 'EN_PINCHED_POST' : {$pf = array( 1062.000, 1332.000); break;} case 'EN_BRIEF' : {$pf = array( 972.000, 1152.000); break;} case 'EN_FOOLSCAP' : {$pf = array( 972.000, 1224.000); break;} case 'EN_SMALL_FOOLSCAP' : {$pf = array( 954.000, 1188.000); break;} case 'EN_POTT' : {$pf = array( 900.000, 1080.000); break;} // - Old Imperial Belgian Sizes case 'BE_GRAND_AIGLE' : {$pf = array( 1984.252, 2948.031); break;} case 'BE_COLOMBIER' : {$pf = array( 1757.480, 2409.449); break;} case 'BE_DOUBLE_CARRE': {$pf = array( 1757.480, 2607.874); break;} case 'BE_ELEPHANT' : {$pf = array( 1746.142, 2182.677); break;} case 'BE_PETIT_AIGLE' : {$pf = array( 1700.787, 2381.102); break;} case 'BE_GRAND_JESUS' : {$pf = array( 1559.055, 2069.291); break;} case 'BE_JESUS' : {$pf = array( 1530.709, 2069.291); break;} case 'BE_RAISIN' : {$pf = array( 1417.323, 1842.520); break;} case 'BE_GRAND_MEDIAN': {$pf = array( 1303.937, 1714.961); break;} case 'BE_DOUBLE_POSTE': {$pf = array( 1233.071, 1601.575); break;} case 'BE_COQUILLE' : {$pf = array( 1218.898, 1587.402); break;} case 'BE_PETIT_MEDIAN': {$pf = array( 1176.378, 1502.362); break;} case 'BE_RUCHE' : {$pf = array( 1020.472, 1303.937); break;} case 'BE_PROPATRIA' : {$pf = array( 977.953, 1218.898); break;} case 'BE_LYS' : {$pf = array( 898.583, 1125.354); break;} case 'BE_POT' : {$pf = array( 870.236, 1088.504); break;} case 'BE_ROSETTE' : {$pf = array( 765.354, 983.622); break;} // - Old Imperial French Sizes case 'FR_UNIVERS' : {$pf = array( 2834.646, 3685.039); break;} case 'FR_DOUBLE_COLOMBIER' : {$pf = array( 2551.181, 3571.654); break;} case 'FR_GRANDE_MONDE' : {$pf = array( 2551.181, 3571.654); break;} case 'FR_DOUBLE_SOLEIL' : {$pf = array( 2267.717, 3401.575); break;} case 'FR_DOUBLE_JESUS' : {$pf = array( 2154.331, 3174.803); break;} case 'FR_GRAND_AIGLE' : {$pf = array( 2125.984, 3004.724); break;} case 'FR_PETIT_AIGLE' : {$pf = array( 1984.252, 2664.567); break;} case 'FR_DOUBLE_RAISIN' : {$pf = array( 1842.520, 2834.646); break;} case 'FR_JOURNAL' : {$pf = array( 1842.520, 2664.567); break;} case 'FR_COLOMBIER_AFFICHE': {$pf = array( 1785.827, 2551.181); break;} case 'FR_DOUBLE_CAVALIER' : {$pf = array( 1757.480, 2607.874); break;} case 'FR_CLOCHE' : {$pf = array( 1700.787, 2267.717); break;} case 'FR_SOLEIL' : {$pf = array( 1700.787, 2267.717); break;} case 'FR_DOUBLE_CARRE' : {$pf = array( 1587.402, 2551.181); break;} case 'FR_DOUBLE_COQUILLE' : {$pf = array( 1587.402, 2494.488); break;} case 'FR_JESUS' : {$pf = array( 1587.402, 2154.331); break;} case 'FR_RAISIN' : {$pf = array( 1417.323, 1842.520); break;} case 'FR_CAVALIER' : {$pf = array( 1303.937, 1757.480); break;} case 'FR_DOUBLE_COURONNE' : {$pf = array( 1303.937, 2040.945); break;} case 'FR_CARRE' : {$pf = array( 1275.591, 1587.402); break;} case 'FR_COQUILLE' : {$pf = array( 1247.244, 1587.402); break;} case 'FR_DOUBLE_TELLIERE' : {$pf = array( 1247.244, 1927.559); break;} case 'FR_DOUBLE_CLOCHE' : {$pf = array( 1133.858, 1700.787); break;} case 'FR_DOUBLE_POT' : {$pf = array( 1133.858, 1757.480); break;} case 'FR_ECU' : {$pf = array( 1133.858, 1474.016); break;} case 'FR_COURONNE' : {$pf = array( 1020.472, 1303.937); break;} case 'FR_TELLIERE' : {$pf = array( 963.780, 1247.244); break;} case 'FR_POT' : {$pf = array( 878.740, 1133.858); break;} // DEFAULT ISO A4 default: {$pf = array( 595.276, 841.890); break;} } return $pf; } /** * Change the format of the current page * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() documentation or an array of two numners (width, height) or an array containing the following measures and options: * @param $orientation (string) page orientation. Possible values are (case insensitive): * @protected * @since 3.0.015 (2008-06-06) * @see getPageSizeFromFormat() */ protected function setPageFormat($format, $orientation='P') { if (!empty($format) AND isset($this->pagedim[$this->page])) { // remove inherited values unset($this->pagedim[$this->page]); } if (is_string($format)) { // get page measures from format name $pf = $this->getPageSizeFromFormat($format); $this->fwPt = $pf[0]; $this->fhPt = $pf[1]; } else { // the boundaries of the physical medium on which the page shall be displayed or printed if (isset($format['MediaBox'])) { $this->setPageBoxes($this->page, 'MediaBox', $format['MediaBox']['llx'], $format['MediaBox']['lly'], $format['MediaBox']['urx'], $format['MediaBox']['ury'], false); $this->fwPt = (($format['MediaBox']['urx'] - $format['MediaBox']['llx']) * $this->k); $this->fhPt = (($format['MediaBox']['ury'] - $format['MediaBox']['lly']) * $this->k); } else { if (isset($format[0]) AND is_numeric($format[0]) AND isset($format[1]) AND is_numeric($format[1])) { $pf = array(($format[0] * $this->k), ($format[1] * $this->k)); } else { if (!isset($format['format'])) { // default value $format['format'] = 'A4'; } $pf = $this->getPageSizeFromFormat($format['format']); } $this->fwPt = $pf[0]; $this->fhPt = $pf[1]; $this->setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true); } // the visible region of default user space if (isset($format['CropBox'])) { $this->setPageBoxes($this->page, 'CropBox', $format['CropBox']['llx'], $format['CropBox']['lly'], $format['CropBox']['urx'], $format['CropBox']['ury'], false); } // the region to which the contents of the page shall be clipped when output in a production environment if (isset($format['BleedBox'])) { $this->setPageBoxes($this->page, 'BleedBox', $format['BleedBox']['llx'], $format['BleedBox']['lly'], $format['BleedBox']['urx'], $format['BleedBox']['ury'], false); } // the intended dimensions of the finished page after trimming if (isset($format['TrimBox'])) { $this->setPageBoxes($this->page, 'TrimBox', $format['TrimBox']['llx'], $format['TrimBox']['lly'], $format['TrimBox']['urx'], $format['TrimBox']['ury'], false); } // the page's meaningful content (including potential white space) if (isset($format['ArtBox'])) { $this->setPageBoxes($this->page, 'ArtBox', $format['ArtBox']['llx'], $format['ArtBox']['lly'], $format['ArtBox']['urx'], $format['ArtBox']['ury'], false); } // specify the colours and other visual characteristics that should be used in displaying guidelines on the screen for the various page boundaries if (isset($format['BoxColorInfo'])) { $this->pagedim[$this->page]['BoxColorInfo'] = $format['BoxColorInfo']; } if (isset($format['Rotate']) AND (($format['Rotate'] % 90) == 0)) { // The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90. $this->pagedim[$this->page]['Rotate'] = intval($format['Rotate']); } if (isset($format['PZ'])) { // The page's preferred zoom (magnification) factor $this->pagedim[$this->page]['PZ'] = floatval($format['PZ']); } if (isset($format['trans'])) { // The style and duration of the visual transition to use when moving from another page to the given page during a presentation if (isset($format['trans']['Dur'])) { // The page's display duration $this->pagedim[$this->page]['trans']['Dur'] = floatval($format['trans']['Dur']); } $stansition_styles = array('Split', 'Blinds', 'Box', 'Wipe', 'Dissolve', 'Glitter', 'R', 'Fly', 'Push', 'Cover', 'Uncover', 'Fade'); if (isset($format['trans']['S']) AND in_array($format['trans']['S'], $stansition_styles)) { // The transition style that shall be used when moving to this page from another during a presentation $this->pagedim[$this->page]['trans']['S'] = $format['trans']['S']; $valid_effect = array('Split', 'Blinds'); $valid_vals = array('H', 'V'); if (isset($format['trans']['Dm']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['Dm'], $valid_vals)) { $this->pagedim[$this->page]['trans']['Dm'] = $format['trans']['Dm']; } $valid_effect = array('Split', 'Box', 'Fly'); $valid_vals = array('I', 'O'); if (isset($format['trans']['M']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['M'], $valid_vals)) { $this->pagedim[$this->page]['trans']['M'] = $format['trans']['M']; } $valid_effect = array('Wipe', 'Glitter', 'Fly', 'Cover', 'Uncover', 'Push'); if (isset($format['trans']['Di']) AND in_array($format['trans']['S'], $valid_effect)) { if (((($format['trans']['Di'] == 90) OR ($format['trans']['Di'] == 180)) AND ($format['trans']['S'] == 'Wipe')) OR (($format['trans']['Di'] == 315) AND ($format['trans']['S'] == 'Glitter')) OR (($format['trans']['Di'] == 0) OR ($format['trans']['Di'] == 270))) { $this->pagedim[$this->page]['trans']['Di'] = intval($format['trans']['Di']); } } if (isset($format['trans']['SS']) AND ($format['trans']['S'] == 'Fly')) { $this->pagedim[$this->page]['trans']['SS'] = floatval($format['trans']['SS']); } if (isset($format['trans']['B']) AND ($format['trans']['B'] === true) AND ($format['trans']['S'] == 'Fly')) { $this->pagedim[$this->page]['trans']['B'] = 'true'; } } else { $this->pagedim[$this->page]['trans']['S'] = 'R'; } if (isset($format['trans']['D'])) { // The duration of the transition effect, in seconds $this->pagedim[$this->page]['trans']['D'] = floatval($format['trans']['D']); } else { $this->pagedim[$this->page]['trans']['D'] = 1; } } } $this->setPageOrientation($orientation); } /** * Set page boundaries. * @param $page (int) page number * @param $type (string) valid values are: * @param $llx (float) lower-left x coordinate in user units * @param $lly (float) lower-left y coordinate in user units * @param $urx (float) upper-right x coordinate in user units * @param $ury (float) upper-right y coordinate in user units * @param $points (boolean) if true uses user units as unit of measure, otherwise uses PDF points * @public * @since 5.0.010 (2010-05-17) */ public function setPageBoxes($page, $type, $llx, $lly, $urx, $ury, $points=false) { if (!isset($this->pagedim[$page])) { // initialize array $this->pagedim[$page] = array(); } $pageboxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox'); if (!in_array($type, $pageboxes)) { return; } if ($points) { $k = 1; } else { $k = $this->k; } $this->pagedim[$page][$type]['llx'] = ($llx * $k); $this->pagedim[$page][$type]['lly'] = ($lly * $k); $this->pagedim[$page][$type]['urx'] = ($urx * $k); $this->pagedim[$page][$type]['ury'] = ($ury * $k); } /** * Swap X and Y coordinates of page boxes (change page boxes orientation). * @param $page (int) page number * @protected * @since 5.0.010 (2010-05-17) */ protected function swapPageBoxCoordinates($page) { $pageboxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox'); foreach ($pageboxes as $type) { // swap X and Y coordinates if (isset($this->pagedim[$page][$type])) { $tmp = $this->pagedim[$page][$type]['llx']; $this->pagedim[$page][$type]['llx'] = $this->pagedim[$page][$type]['lly']; $this->pagedim[$page][$type]['lly'] = $tmp; $tmp = $this->pagedim[$page][$type]['urx']; $this->pagedim[$page][$type]['urx'] = $this->pagedim[$page][$type]['ury']; $this->pagedim[$page][$type]['ury'] = $tmp; } } } /** * Set page orientation. * @param $orientation (string) page orientation. Possible values are (case insensitive): * @param $autopagebreak (boolean) Boolean indicating if auto-page-break mode should be on or off. * @param $bottommargin (float) bottom margin of the page. * @public * @since 3.0.015 (2008-06-06) */ public function setPageOrientation($orientation, $autopagebreak='', $bottommargin='') { if (!isset($this->pagedim[$this->page]['MediaBox'])) { // the boundaries of the physical medium on which the page shall be displayed or printed $this->setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true); } if (!isset($this->pagedim[$this->page]['CropBox'])) { // the visible region of default user space $this->setPageBoxes($this->page, 'CropBox', $this->pagedim[$this->page]['MediaBox']['llx'], $this->pagedim[$this->page]['MediaBox']['lly'], $this->pagedim[$this->page]['MediaBox']['urx'], $this->pagedim[$this->page]['MediaBox']['ury'], true); } if (!isset($this->pagedim[$this->page]['BleedBox'])) { // the region to which the contents of the page shall be clipped when output in a production environment $this->setPageBoxes($this->page, 'BleedBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true); } if (!isset($this->pagedim[$this->page]['TrimBox'])) { // the intended dimensions of the finished page after trimming $this->setPageBoxes($this->page, 'TrimBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true); } if (!isset($this->pagedim[$this->page]['ArtBox'])) { // the page's meaningful content (including potential white space) $this->setPageBoxes($this->page, 'ArtBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true); } if (!isset($this->pagedim[$this->page]['Rotate'])) { // The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90. $this->pagedim[$this->page]['Rotate'] = 0; } if (!isset($this->pagedim[$this->page]['PZ'])) { // The page's preferred zoom (magnification) factor $this->pagedim[$this->page]['PZ'] = 1; } if ($this->fwPt > $this->fhPt) { // landscape $default_orientation = 'L'; } else { // portrait $default_orientation = 'P'; } $valid_orientations = array('P', 'L'); if (empty($orientation)) { $orientation = $default_orientation; } else { $orientation = strtoupper($orientation{0}); } if (in_array($orientation, $valid_orientations) AND ($orientation != $default_orientation)) { $this->CurOrientation = $orientation; $this->wPt = $this->fhPt; $this->hPt = $this->fwPt; } else { $this->CurOrientation = $default_orientation; $this->wPt = $this->fwPt; $this->hPt = $this->fhPt; } if ((abs($this->pagedim[$this->page]['MediaBox']['urx'] - $this->hPt) < $this->feps) AND (abs($this->pagedim[$this->page]['MediaBox']['ury'] - $this->wPt) < $this->feps)){ // swap X and Y coordinates (change page orientation) $this->swapPageBoxCoordinates($this->page); } $this->w = $this->wPt / $this->k; $this->h = $this->hPt / $this->k; if ($this->empty_string($autopagebreak)) { if (isset($this->AutoPageBreak)) { $autopagebreak = $this->AutoPageBreak; } else { $autopagebreak = true; } } if ($this->empty_string($bottommargin)) { if (isset($this->bMargin)) { $bottommargin = $this->bMargin; } else { // default value = 2 cm $bottommargin = 2 * 28.35 / $this->k; } } $this->SetAutoPageBreak($autopagebreak, $bottommargin); // store page dimensions $this->pagedim[$this->page]['w'] = $this->wPt; $this->pagedim[$this->page]['h'] = $this->hPt; $this->pagedim[$this->page]['wk'] = $this->w; $this->pagedim[$this->page]['hk'] = $this->h; $this->pagedim[$this->page]['tm'] = $this->tMargin; $this->pagedim[$this->page]['bm'] = $bottommargin; $this->pagedim[$this->page]['lm'] = $this->lMargin; $this->pagedim[$this->page]['rm'] = $this->rMargin; $this->pagedim[$this->page]['pb'] = $autopagebreak; $this->pagedim[$this->page]['or'] = $this->CurOrientation; $this->pagedim[$this->page]['olm'] = $this->original_lMargin; $this->pagedim[$this->page]['orm'] = $this->original_rMargin; } /** * Set regular expression to detect withespaces or word separators. * The pattern delimiter must be the forward-slash character "/". * Some example patterns are: *
    	 * Non-Unicode or missing PCRE unicode support: "/[^\S\xa0]/"
    	 * Unicode and PCRE unicode support: "/[^\S\P{Z}\xa0]/u"
    	 * Unicode and PCRE unicode support in Chinese mode: "/[^\S\P{Z}\P{Lo}\xa0]/u"
    	 * if PCRE unicode support is turned ON ("\P" is the negate class of "\p"):
    	 * "\p{Z}" or "\p{Separator}": any kind of Unicode whitespace or invisible separator.
    	 * "\p{Lo}" or "\p{Other_Letter}": a Unicode letter or ideograph that does not have lowercase and uppercase variants.
    	 * "\p{Lo}" is needed for Chinese characters because are packed next to each other without spaces in between.
    	 * 
    * @param $re (string) regular expression (leave empty for default). * @public * @since 4.6.016 (2009-06-15) */ public function setSpacesRE($re='/[^\S\xa0]/') { $this->re_spaces = $re; $re_parts = explode('/', $re); // get pattern parts $this->re_space = array(); if (isset($re_parts[1]) AND !empty($re_parts[1])) { $this->re_space['p'] = $re_parts[1]; } else { $this->re_space['p'] = '[\s]'; } // set pattern modifiers if (isset($re_parts[2]) AND !empty($re_parts[2])) { $this->re_space['m'] = $re_parts[2]; } else { $this->re_space['m'] = ''; } } /** * Enable or disable Right-To-Left language mode * @param $enable (Boolean) if true enable Right-To-Left language mode. * @param $resetx (Boolean) if true reset the X position on direction change. * @public * @since 2.0.000 (2008-01-03) */ public function setRTL($enable, $resetx=true) { $enable = $enable ? true : false; $resetx = ($resetx AND ($enable != $this->rtl)); $this->rtl = $enable; $this->tmprtl = false; if ($resetx) { $this->Ln(0); } } /** * Return the RTL status * @return boolean * @public * @since 4.0.012 (2008-07-24) */ public function getRTL() { return $this->rtl; } /** * Force temporary RTL language direction * @param $mode (mixed) can be false, 'L' for LTR or 'R' for RTL * @public * @since 2.1.000 (2008-01-09) */ public function setTempRTL($mode) { $newmode = false; switch (strtoupper($mode)) { case 'LTR': case 'L': { if ($this->rtl) { $newmode = 'L'; } break; } case 'RTL': case 'R': { if (!$this->rtl) { $newmode = 'R'; } break; } case false: default: { $newmode = false; break; } } $this->tmprtl = $newmode; } /** * Return the current temporary RTL status * @return boolean * @public * @since 4.8.014 (2009-11-04) */ public function isRTLTextDir() { return ($this->rtl OR ($this->tmprtl == 'R')); } /** * Set the last cell height. * @param $h (float) cell height. * @author Nicola Asuni * @public * @since 1.53.0.TC034 */ public function setLastH($h) { $this->lasth = $h; } /** * Reset the last cell height. * @public * @since 5.9.000 (2010-10-03) */ public function resetLastH() { $this->lasth = ($this->FontSize * $this->cell_height_ratio) + $this->cell_padding['T'] + $this->cell_padding['B']; } /** * Get the last cell height. * @return last cell height * @public * @since 4.0.017 (2008-08-05) */ public function getLastH() { return $this->lasth; } /** * Set the adjusting factor to convert pixels to user units. * @param $scale (float) adjusting factor to convert pixels to user units. * @author Nicola Asuni * @public * @since 1.5.2 */ public function setImageScale($scale) { $this->imgscale = $scale; } /** * Returns the adjusting factor to convert pixels to user units. * @return float adjusting factor to convert pixels to user units. * @author Nicola Asuni * @public * @since 1.5.2 */ public function getImageScale() { return $this->imgscale; } /** * Returns an array of page dimensions: * * @param $pagenum (int) page number (empty = current page) * @return array of page dimensions. * @author Nicola Asuni * @public * @since 4.5.027 (2009-03-16) */ public function getPageDimensions($pagenum='') { if (empty($pagenum)) { $pagenum = $this->page; } return $this->pagedim[$pagenum]; } /** * Returns the page width in units. * @param $pagenum (int) page number (empty = current page) * @return int page width. * @author Nicola Asuni * @public * @since 1.5.2 * @see getPageDimensions() */ public function getPageWidth($pagenum='') { if (empty($pagenum)) { return $this->w; } return $this->pagedim[$pagenum]['w']; } /** * Returns the page height in units. * @param $pagenum (int) page number (empty = current page) * @return int page height. * @author Nicola Asuni * @public * @since 1.5.2 * @see getPageDimensions() */ public function getPageHeight($pagenum='') { if (empty($pagenum)) { return $this->h; } return $this->pagedim[$pagenum]['h']; } /** * Returns the page break margin. * @param $pagenum (int) page number (empty = current page) * @return int page break margin. * @author Nicola Asuni * @public * @since 1.5.2 * @see getPageDimensions() */ public function getBreakMargin($pagenum='') { if (empty($pagenum)) { return $this->bMargin; } return $this->pagedim[$pagenum]['bm']; } /** * Returns the scale factor (number of points in user unit). * @return int scale factor. * @author Nicola Asuni * @public * @since 1.5.2 */ public function getScaleFactor() { return $this->k; } /** * Defines the left, top and right margins. * @param $left (float) Left margin. * @param $top (float) Top margin. * @param $right (float) Right margin. Default value is the left one. * @param $keepmargins (boolean) if true overwrites the default page margins * @public * @since 1.0 * @see SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak() */ public function SetMargins($left, $top, $right=-1, $keepmargins=false) { //Set left, top and right margins $this->lMargin = $left; $this->tMargin = $top; if ($right == -1) { $right = $left; } $this->rMargin = $right; if ($keepmargins) { // overwrite original values $this->original_lMargin = $this->lMargin; $this->original_rMargin = $this->rMargin; } } /** * Defines the left margin. The method can be called before creating the first page. If the current abscissa gets out of page, it is brought back to the margin. * @param $margin (float) The margin. * @public * @since 1.4 * @see SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins() */ public function SetLeftMargin($margin) { //Set left margin $this->lMargin = $margin; if (($this->page > 0) AND ($this->x < $margin)) { $this->x = $margin; } } /** * Defines the top margin. The method can be called before creating the first page. * @param $margin (float) The margin. * @public * @since 1.5 * @see SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins() */ public function SetTopMargin($margin) { //Set top margin $this->tMargin = $margin; if (($this->page > 0) AND ($this->y < $margin)) { $this->y = $margin; } } /** * Defines the right margin. The method can be called before creating the first page. * @param $margin (float) The margin. * @public * @since 1.5 * @see SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins() */ public function SetRightMargin($margin) { $this->rMargin = $margin; if (($this->page > 0) AND ($this->x > ($this->w - $margin))) { $this->x = $this->w - $margin; } } /** * Set the same internal Cell padding for top, right, bottom, left- * @param $pad (float) internal padding. * @public * @since 2.1.000 (2008-01-09) * @see getCellPaddings(), setCellPaddings() */ public function SetCellPadding($pad) { if ($pad >= 0) { $this->cell_padding['L'] = $pad; $this->cell_padding['T'] = $pad; $this->cell_padding['R'] = $pad; $this->cell_padding['B'] = $pad; } } /** * Set the internal Cell paddings. * @param $left (float) left padding * @param $top (float) top padding * @param $right (float) right padding * @param $bottom (float) bottom padding * @public * @since 5.9.000 (2010-10-03) * @see getCellPaddings(), SetCellPadding() */ public function setCellPaddings($left='', $top='', $right='', $bottom='') { if (($left !== '') AND ($left >= 0)) { $this->cell_padding['L'] = $left; } if (($top !== '') AND ($top >= 0)) { $this->cell_padding['T'] = $top; } if (($right !== '') AND ($right >= 0)) { $this->cell_padding['R'] = $right; } if (($bottom !== '') AND ($bottom >= 0)) { $this->cell_padding['B'] = $bottom; } } /** * Get the internal Cell padding array. * @return array of padding values * @public * @since 5.9.000 (2010-10-03) * @see setCellPaddings(), SetCellPadding() */ public function getCellPaddings() { return $this->cell_padding; } /** * Set the internal Cell margins. * @param $left (float) left margin * @param $top (float) top margin * @param $right (float) right margin * @param $bottom (float) bottom margin * @public * @since 5.9.000 (2010-10-03) * @see getCellMargins() */ public function setCellMargins($left='', $top='', $right='', $bottom='') { if (($left !== '') AND ($left >= 0)) { $this->cell_margin['L'] = $left; } if (($top !== '') AND ($top >= 0)) { $this->cell_margin['T'] = $top; } if (($right !== '') AND ($right >= 0)) { $this->cell_margin['R'] = $right; } if (($bottom !== '') AND ($bottom >= 0)) { $this->cell_margin['B'] = $bottom; } } /** * Get the internal Cell margin array. * @return array of margin values * @public * @since 5.9.000 (2010-10-03) * @see setCellMargins() */ public function getCellMargins() { return $this->cell_margin; } /** * Adjust the internal Cell padding array to take account of the line width. * @param $brd (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @return array of adjustments * @public * @since 5.9.000 (2010-10-03) */ protected function adjustCellPadding($brd=0) { if (empty($brd)) { return; } if (is_string($brd)) { // convert string to array $slen = strlen($brd); $newbrd = array(); for ($i = 0; $i < $slen; ++$i) { $newbrd[$brd[$i]] = true; } $brd = $newbrd; } elseif (($brd === 1) OR ($brd === true) OR (is_numeric($brd) AND (intval($brd) > 0))) { $brd = array('LRTB' => true); } if (!is_array($brd)) { return; } // store current cell padding $cp = $this->cell_padding; // select border mode if (isset($brd['mode'])) { $mode = $brd['mode']; unset($brd['mode']); } else { $mode = 'normal'; } // process borders foreach ($brd as $border => $style) { $line_width = $this->LineWidth; if (is_array($style) AND isset($style['width'])) { // get border width $line_width = $style['width']; } $adj = 0; // line width inside the cell switch ($mode) { case 'ext': { $adj = 0; break; } case 'int': { $adj = $line_width; break; } case 'normal': default: { $adj = ($line_width / 2); break; } } // correct internal cell padding if required to avoid overlap between text and lines if ((strpos($border,'T') !== false) AND ($this->cell_padding['T'] < $adj)) { $this->cell_padding['T'] = $adj; } if ((strpos($border,'R') !== false) AND ($this->cell_padding['R'] < $adj)) { $this->cell_padding['R'] = $adj; } if ((strpos($border,'B') !== false) AND ($this->cell_padding['B'] < $adj)) { $this->cell_padding['B'] = $adj; } if ((strpos($border,'L') !== false) AND ($this->cell_padding['L'] < $adj)) { $this->cell_padding['L'] = $adj; } } return array('T' => ($this->cell_padding['T'] - $cp['T']), 'R' => ($this->cell_padding['R'] - $cp['R']), 'B' => ($this->cell_padding['B'] - $cp['B']), 'L' => ($this->cell_padding['L'] - $cp['L'])); } /** * Enables or disables the automatic page breaking mode. When enabling, the second parameter is the distance from the bottom of the page that defines the triggering limit. By default, the mode is on and the margin is 2 cm. * @param $auto (boolean) Boolean indicating if mode should be on or off. * @param $margin (float) Distance from the bottom of the page. * @public * @since 1.0 * @see Cell(), MultiCell(), AcceptPageBreak() */ public function SetAutoPageBreak($auto, $margin=0) { $this->AutoPageBreak = $auto ? true : false; $this->bMargin = $margin; $this->PageBreakTrigger = $this->h - $margin; } /** * Return the auto-page-break mode (true or false). * @return boolean auto-page-break mode * @public * @since 5.9.088 */ public function getAutoPageBreak() { return $this->AutoPageBreak; } /** * Defines the way the document is to be displayed by the viewer. * @param $zoom (mixed) The zoom to use. It can be one of the following string values or a number indicating the zooming factor to use. * @param $layout (string) The page layout. Possible values are: * @param $mode (string) A name object specifying how the document should be displayed when opened: * @public * @since 1.2 */ public function SetDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') { if (($zoom == 'fullpage') OR ($zoom == 'fullwidth') OR ($zoom == 'real') OR ($zoom == 'default') OR (!is_string($zoom))) { $this->ZoomMode = $zoom; } else { $this->Error('Incorrect zoom display mode: '.$zoom); } switch ($layout) { case 'default': case 'single': case 'SinglePage': { $this->LayoutMode = 'SinglePage'; break; } case 'continuous': case 'OneColumn': { $this->LayoutMode = 'OneColumn'; break; } case 'two': case 'TwoColumnLeft': { $this->LayoutMode = 'TwoColumnLeft'; break; } case 'TwoColumnRight': { $this->LayoutMode = 'TwoColumnRight'; break; } case 'TwoPageLeft': { $this->LayoutMode = 'TwoPageLeft'; break; } case 'TwoPageRight': { $this->LayoutMode = 'TwoPageRight'; break; } default: { $this->LayoutMode = 'SinglePage'; } } switch ($mode) { case 'UseNone': { $this->PageMode = 'UseNone'; break; } case 'UseOutlines': { $this->PageMode = 'UseOutlines'; break; } case 'UseThumbs': { $this->PageMode = 'UseThumbs'; break; } case 'FullScreen': { $this->PageMode = 'FullScreen'; break; } case 'UseOC': { $this->PageMode = 'UseOC'; break; } case '': { $this->PageMode = 'UseAttachments'; break; } default: { $this->PageMode = 'UseNone'; } } } /** * Activates or deactivates page compression. When activated, the internal representation of each page is compressed, which leads to a compression ratio of about 2 for the resulting document. Compression is on by default. * Note: the Zlib extension is required for this feature. If not present, compression will be turned off. * @param $compress (boolean) Boolean indicating if compression must be enabled. * @public * @since 1.4 */ public function SetCompression($compress=true) { if (function_exists('gzcompress')) { $this->compress = $compress ? true : false; } else { $this->compress = false; } } /** * Set flag to force sRGB_IEC61966-2.1 black scaled ICC color profile for the whole document. * @param $mode (boolean) If true force sRGB output intent. * @public * @since 5.9.121 (2011-09-28) */ public function setSRGBmode($mode=false) { $this->force_srgb = $mode ? true : false; } /** * Turn on/off Unicode mode for document information dictionary (meta tags). * This has effect only when unicode mode is set to false. * @param $unicode (boolean) if true set the meta information in Unicode * @since 5.9.027 (2010-12-01) * @public */ public function SetDocInfoUnicode($unicode=true) { $this->docinfounicode = $unicode ? true : false; } /** * Defines the title of the document. * @param $title (string) The title. * @public * @since 1.2 * @see SetAuthor(), SetCreator(), SetKeywords(), SetSubject() */ public function SetTitle($title) { $this->title = $title; } /** * Defines the subject of the document. * @param $subject (string) The subject. * @public * @since 1.2 * @see SetAuthor(), SetCreator(), SetKeywords(), SetTitle() */ public function SetSubject($subject) { $this->subject = $subject; } /** * Defines the author of the document. * @param $author (string) The name of the author. * @public * @since 1.2 * @see SetCreator(), SetKeywords(), SetSubject(), SetTitle() */ public function SetAuthor($author) { $this->author = $author; } /** * Associates keywords with the document, generally in the form 'keyword1 keyword2 ...'. * @param $keywords (string) The list of keywords. * @public * @since 1.2 * @see SetAuthor(), SetCreator(), SetSubject(), SetTitle() */ public function SetKeywords($keywords) { $this->keywords = $keywords; } /** * Defines the creator of the document. This is typically the name of the application that generates the PDF. * @param $creator (string) The name of the creator. * @public * @since 1.2 * @see SetAuthor(), SetKeywords(), SetSubject(), SetTitle() */ public function SetCreator($creator) { $this->creator = $creator; } /** * This method is automatically called in case of fatal error; it simply outputs the message and halts the execution. An inherited class may override it to customize the error handling but should always halt the script, or the resulting document would probably be invalid. * 2004-06-11 :: Nicola Asuni : changed bold tag with strong * @param $msg (string) The error message * @public * @since 1.0 */ public function Error($msg) { // unset all class variables $this->_destroy(true); // exit program and print error die('TCPDF ERROR: '.$msg); } /** * This method begins the generation of the PDF document. * It is not necessary to call it explicitly because AddPage() does it automatically. * Note: no page is created by this method * @public * @since 1.0 * @see AddPage(), Close() */ public function Open() { $this->state = 1; } /** * Terminates the PDF document. * It is not necessary to call this method explicitly because Output() does it automatically. * If the document contains no page, AddPage() is called to prevent from getting an invalid document. * @public * @since 1.0 * @see Open(), Output() */ public function Close() { if ($this->state == 3) { return; } if ($this->page == 0) { $this->AddPage(); } $this->endLayer(); // save current graphic settings $gvars = $this->getGraphicVars(); $this->setEqualColumns(); $this->lastpage(true); $this->SetAutoPageBreak(false); $this->x = 0; $this->y = $this->h - (1 / $this->k); $this->lMargin = 0; $this->_out('q'); $font = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica'; $this->SetFont($font, '', 1); $this->setTextRenderingMode(0, false, false); $msg = "\x50\x6f\x77\x65\x72\x65\x64\x20\x62\x79\x20\x54\x43\x50\x44\x46\x20\x28\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29"; $lnk = "\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67"; $this->Cell(0, 0, $msg, 0, 0, 'L', 0, $lnk, 0, false, 'D', 'B'); $this->_out('Q'); // restore graphic settings $this->setGraphicVars($gvars); // close page $this->endPage(); // close document $this->_enddoc(); // unset all class variables (except critical ones) $this->_destroy(false); } /** * Move pointer at the specified document page and update page dimensions. * @param $pnum (int) page number (1 ... numpages) * @param $resetmargins (boolean) if true reset left, right, top margins and Y position. * @public * @since 2.1.000 (2008-01-07) * @see getPage(), lastpage(), getNumPages() */ public function setPage($pnum, $resetmargins=false) { if (($pnum == $this->page) AND ($this->state == 2)) { return; } if (($pnum > 0) AND ($pnum <= $this->numpages)) { $this->state = 2; // save current graphic settings //$gvars = $this->getGraphicVars(); $oldpage = $this->page; $this->page = $pnum; $this->wPt = $this->pagedim[$this->page]['w']; $this->hPt = $this->pagedim[$this->page]['h']; $this->w = $this->pagedim[$this->page]['wk']; $this->h = $this->pagedim[$this->page]['hk']; $this->tMargin = $this->pagedim[$this->page]['tm']; $this->bMargin = $this->pagedim[$this->page]['bm']; $this->original_lMargin = $this->pagedim[$this->page]['olm']; $this->original_rMargin = $this->pagedim[$this->page]['orm']; $this->AutoPageBreak = $this->pagedim[$this->page]['pb']; $this->CurOrientation = $this->pagedim[$this->page]['or']; $this->SetAutoPageBreak($this->AutoPageBreak, $this->bMargin); // restore graphic settings //$this->setGraphicVars($gvars); if ($resetmargins) { $this->lMargin = $this->pagedim[$this->page]['olm']; $this->rMargin = $this->pagedim[$this->page]['orm']; $this->SetY($this->tMargin); } else { // account for booklet mode if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) { $deltam = $this->pagedim[$this->page]['olm'] - $this->pagedim[$this->page]['orm']; $this->lMargin += $deltam; $this->rMargin -= $deltam; } } } else { $this->Error('Wrong page number on setPage() function: '.$pnum); } } /** * Reset pointer to the last document page. * @param $resetmargins (boolean) if true reset left, right, top margins and Y position. * @public * @since 2.0.000 (2008-01-04) * @see setPage(), getPage(), getNumPages() */ public function lastPage($resetmargins=false) { $this->setPage($this->getNumPages(), $resetmargins); } /** * Get current document page number. * @return int page number * @public * @since 2.1.000 (2008-01-07) * @see setPage(), lastpage(), getNumPages() */ public function getPage() { return $this->page; } /** * Get the total number of insered pages. * @return int number of pages * @public * @since 2.1.000 (2008-01-07) * @see setPage(), getPage(), lastpage() */ public function getNumPages() { return $this->numpages; } /** * Adds a new TOC (Table Of Content) page to the document. * @param $orientation (string) page orientation. * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). * @param $keepmargins (boolean) if true overwrites the default page margins with the current margins * @public * @since 5.0.001 (2010-05-06) * @see AddPage(), startPage(), endPage(), endTOCPage() */ public function addTOCPage($orientation='', $format='', $keepmargins=false) { $this->AddPage($orientation, $format, $keepmargins, true); } /** * Terminate the current TOC (Table Of Content) page * @public * @since 5.0.001 (2010-05-06) * @see AddPage(), startPage(), endPage(), addTOCPage() */ public function endTOCPage() { $this->endPage(true); } /** * Adds a new page to the document. If a page is already present, the Footer() method is called first to output the footer (if enabled). Then the page is added, the current position set to the top-left corner according to the left and top margins (or top-right if in RTL mode), and Header() is called to display the header (if enabled). * The origin of the coordinate system is at the top-left corner (or top-right for RTL) and increasing ordinates go downwards. * @param $orientation (string) page orientation. Possible values are (case insensitive): * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). * @param $keepmargins (boolean) if true overwrites the default page margins with the current margins * @param $tocpage (boolean) if true set the tocpage state to true (the added page will be used to display Table Of Content). * @public * @since 1.0 * @see startPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat() */ public function AddPage($orientation='', $format='', $keepmargins=false, $tocpage=false) { if ($this->inxobj) { // we are inside an XObject template return; } if (!isset($this->original_lMargin) OR $keepmargins) { $this->original_lMargin = $this->lMargin; } if (!isset($this->original_rMargin) OR $keepmargins) { $this->original_rMargin = $this->rMargin; } // terminate previous page $this->endPage(); // start new page $this->startPage($orientation, $format, $tocpage); } /** * Terminate the current page * @param $tocpage (boolean) if true set the tocpage state to false (end the page used to display Table Of Content). * @public * @since 4.2.010 (2008-11-14) * @see AddPage(), startPage(), addTOCPage(), endTOCPage() */ public function endPage($tocpage=false) { // check if page is already closed if (($this->page == 0) OR ($this->numpages > $this->page) OR (!$this->pageopen[$this->page])) { return; } // print page footer $this->setFooter(); // close page $this->_endpage(); // mark page as closed $this->pageopen[$this->page] = false; if ($tocpage) { $this->tocpage = false; } } /** * Starts a new page to the document. The page must be closed using the endPage() function. * The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards. * @param $orientation (string) page orientation. Possible values are (case insensitive): * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). * @param $tocpage (boolean) if true the page is designated to contain the Table-Of-Content. * @since 4.2.010 (2008-11-14) * @see AddPage(), endPage(), addTOCPage(), endTOCPage(), getPageSizeFromFormat(), setPageFormat() * @public */ public function startPage($orientation='', $format='', $tocpage=false) { if ($tocpage) { $this->tocpage = true; } // move page numbers of documents to be attached if ($this->tocpage) { // move reference to unexistent pages (used for page attachments) // adjust outlines $tmpoutlines = $this->outlines; foreach ($tmpoutlines as $key => $outline) { if ($outline['p'] > $this->numpages) { $this->outlines[$key]['p'] = ($outline['p'] + 1); } } // adjust dests $tmpdests = $this->dests; foreach ($tmpdests as $key => $dest) { if ($dest['p'] > $this->numpages) { $this->dests[$key]['p'] = ($dest['p'] + 1); } } // adjust links $tmplinks = $this->links; foreach ($tmplinks as $key => $link) { if ($link[0] > $this->numpages) { $this->links[$key][0] = ($link[0] + 1); } } } if ($this->numpages > $this->page) { // this page has been already added $this->setPage($this->page + 1); $this->SetY($this->tMargin); return; } // start a new page if ($this->state == 0) { $this->Open(); } ++$this->numpages; $this->swapMargins($this->booklet); // save current graphic settings $gvars = $this->getGraphicVars(); // start new page $this->_beginpage($orientation, $format); // mark page as open $this->pageopen[$this->page] = true; // restore graphic settings $this->setGraphicVars($gvars); // mark this point $this->setPageMark(); // print page header $this->setHeader(); // restore graphic settings $this->setGraphicVars($gvars); // mark this point $this->setPageMark(); // print table header (if any) $this->setTableHeader(); // set mark for empty page check $this->emptypagemrk[$this->page]= $this->pagelen[$this->page]; } /** * Set start-writing mark on current page stream used to put borders and fills. * Borders and fills are always created after content and inserted on the position marked by this method. * This function must be called after calling Image() function for a background image. * Background images must be always inserted before calling Multicell() or WriteHTMLCell() or WriteHTML() functions. * @public * @since 4.0.016 (2008-07-30) */ public function setPageMark() { $this->intmrk[$this->page] = $this->pagelen[$this->page]; $this->bordermrk[$this->page] = $this->intmrk[$this->page]; $this->setContentMark(); } /** * Set start-writing mark on selected page. * Borders and fills are always created after content and inserted on the position marked by this method. * @param $page (int) page number (default is the current page) * @protected * @since 4.6.021 (2009-07-20) */ protected function setContentMark($page=0) { if ($page <= 0) { $page = $this->page; } if (isset($this->footerlen[$page])) { $this->cntmrk[$page] = $this->pagelen[$page] - $this->footerlen[$page]; } else { $this->cntmrk[$page] = $this->pagelen[$page]; } } /** * Set header data. * @param $ln (string) header image logo * @param $lw (string) header image logo width in mm * @param $ht (string) string to print as title on document header * @param $hs (string) string to print on document header * @public */ public function setHeaderData($ln='', $lw=0, $ht='', $hs='') { $this->header_logo = $ln; $this->header_logo_width = $lw; $this->header_title = $ht; $this->header_string = $hs; } /** * Returns header data: * * @return array() * @public * @since 4.0.012 (2008-07-24) */ public function getHeaderData() { $ret = array(); $ret['logo'] = $this->header_logo; $ret['logo_width'] = $this->header_logo_width; $ret['title'] = $this->header_title; $ret['string'] = $this->header_string; return $ret; } /** * Set header margin. * (minimum distance between header and top page margin) * @param $hm (int) distance in user units * @public */ public function setHeaderMargin($hm=10) { $this->header_margin = $hm; } /** * Returns header margin in user units. * @return float * @since 4.0.012 (2008-07-24) * @public */ public function getHeaderMargin() { return $this->header_margin; } /** * Set footer margin. * (minimum distance between footer and bottom page margin) * @param $fm (int) distance in user units * @public */ public function setFooterMargin($fm=10) { $this->footer_margin = $fm; } /** * Returns footer margin in user units. * @return float * @since 4.0.012 (2008-07-24) * @public */ public function getFooterMargin() { return $this->footer_margin; } /** * Set a flag to print page header. * @param $val (boolean) set to true to print the page header (default), false otherwise. * @public */ public function setPrintHeader($val=true) { $this->print_header = $val ? true : false; } /** * Set a flag to print page footer. * @param $val (boolean) set to true to print the page footer (default), false otherwise. * @public */ public function setPrintFooter($val=true) { $this->print_footer = $val ? true : false; } /** * Return the right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image * @return float * @public */ public function getImageRBX() { return $this->img_rb_x; } /** * Return the right-bottom (or left-bottom for RTL) corner Y coordinate of last inserted image * @return float * @public */ public function getImageRBY() { return $this->img_rb_y; } /** * Reset the xobject template used by Header() method. * @public */ public function resetHeaderTemplate() { $this->header_xobjid = -1; } /** * Set a flag to automatically reset the xobject template used by Header() method at each page. * @param $val (boolean) set to true to reset Header xobject template at each page, false otherwise. * @public */ public function setHeaderTemplateAutoreset($val=true) { $this->header_xobj_autoreset = $val ? true : false; } /** * This method is used to render the page header. * It is automatically called by AddPage() and could be overwritten in your own inherited class. * @public */ public function Header() { if ($this->header_xobjid < 0) { // start a new XObject Template $this->header_xobjid = $this->startTemplate($this->w, $this->tMargin); $headerfont = $this->getHeaderFont(); $headerdata = $this->getHeaderData(); $this->y = $this->header_margin; if ($this->rtl) { $this->x = $this->w - $this->original_rMargin; } else { $this->x = $this->original_lMargin; } if (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) { $imgtype = $this->getImageFileType(K_PATH_IMAGES.$headerdata['logo']); if (($imgtype == 'eps') OR ($imgtype == 'ai')) { $this->ImageEps(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); } elseif ($imgtype == 'svg') { $this->ImageSVG(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); } else { $this->Image(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']); } $imgy = $this->getImageRBY(); } else { $imgy = $this->y; } $cell_height = round(($this->cell_height_ratio * $headerfont[2]) / $this->k, 2); // set starting margin for text data cell if ($this->getRTL()) { $header_x = $this->original_rMargin + ($headerdata['logo_width'] * 1.1); } else { $header_x = $this->original_lMargin + ($headerdata['logo_width'] * 1.1); } $cw = $this->w - $this->original_lMargin - $this->original_rMargin - ($headerdata['logo_width'] * 1.1); $this->SetTextColor(0, 0, 0); // header title $this->SetFont($headerfont[0], 'B', $headerfont[2] + 1); $this->SetX($header_x); $this->Cell($cw, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0); // header string $this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]); $this->SetX($header_x); $this->MultiCell($cw, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false, true, 0, 'T', false); // print an ending header line $this->SetLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); $this->SetY((2.835 / $this->k) + max($imgy, $this->y)); if ($this->rtl) { $this->SetX($this->original_rMargin); } else { $this->SetX($this->original_lMargin); } $this->Cell(($this->w - $this->original_lMargin - $this->original_rMargin), 0, '', 'T', 0, 'C'); $this->endTemplate(); } // print header template $x = 0; $dx = 0; if ($this->booklet AND (($this->page % 2) == 0)) { // adjust margins for booklet mode $dx = ($this->original_lMargin - $this->original_rMargin); } if ($this->rtl) { $x = $this->w + $dx; } else { $x = 0 + $dx; } $this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false); if ($this->header_xobj_autoreset) { // reset header xobject template at each page $this->header_xobjid = -1; } } /** * This method is used to render the page footer. * It is automatically called by AddPage() and could be overwritten in your own inherited class. * @public */ public function Footer() { $cur_y = $this->y; $this->SetTextColor(0, 0, 0); //set style for cell border $line_width = 0.85 / $this->k; $this->SetLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))); //print document barcode $barcode = $this->getBarcode(); if (!empty($barcode)) { $this->Ln($line_width); $barcode_width = round(($this->w - $this->original_lMargin - $this->original_rMargin) / 3); $style = array( 'position' => $this->rtl?'R':'L', 'align' => $this->rtl?'R':'L', 'stretch' => false, 'fitwidth' => true, 'cellfitalign' => '', 'border' => false, 'padding' => 0, 'fgcolor' => array(0,0,0), 'bgcolor' => false, 'text' => false ); $this->write1DBarcode($barcode, 'C128', '', $cur_y + $line_width, '', (($this->footer_margin / 3) - $line_width), 0.3, $style, ''); } if (empty($this->pagegroups)) { $pagenumtxt = $this->l['w_page'].' '.$this->getAliasNumPage().' / '.$this->getAliasNbPages(); } else { $pagenumtxt = $this->l['w_page'].' '.$this->getPageNumGroupAlias().' / '.$this->getPageGroupAlias(); } $this->SetY($cur_y); //Print page number if ($this->getRTL()) { $this->SetX($this->original_rMargin); $this->Cell(0, 0, $pagenumtxt, 'T', 0, 'L'); } else { $this->SetX($this->original_lMargin); $this->Cell(0, 0, $this->getAliasRightShift().$pagenumtxt, 'T', 0, 'R'); } } /** * This method is used to render the page header. * @protected * @since 4.0.012 (2008-07-24) */ protected function setHeader() { if (!$this->print_header) { return; } $this->InHeader = true; $this->setGraphicVars($this->default_graphic_vars); $temp_thead = $this->thead; $temp_theadMargins = $this->theadMargins; $lasth = $this->lasth; $this->_out('q'); $this->rMargin = $this->original_rMargin; $this->lMargin = $this->original_lMargin; $this->SetCellPadding(0); //set current position if ($this->rtl) { $this->SetXY($this->original_rMargin, $this->header_margin); } else { $this->SetXY($this->original_lMargin, $this->header_margin); } $this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]); $this->Header(); //restore position if ($this->rtl) { $this->SetXY($this->original_rMargin, $this->tMargin); } else { $this->SetXY($this->original_lMargin, $this->tMargin); } $this->_out('Q'); $this->lasth = $lasth; $this->thead = $temp_thead; $this->theadMargins = $temp_theadMargins; $this->newline = false; $this->InHeader = false; } /** * This method is used to render the page footer. * @protected * @since 4.0.012 (2008-07-24) */ protected function setFooter() { //Page footer $this->InFooter = true; // save current graphic settings $gvars = $this->getGraphicVars(); // mark this point $this->footerpos[$this->page] = $this->pagelen[$this->page]; $this->_out("\n"); if ($this->print_footer) { $this->setGraphicVars($this->default_graphic_vars); $this->current_column = 0; $this->num_columns = 1; $temp_thead = $this->thead; $temp_theadMargins = $this->theadMargins; $lasth = $this->lasth; $this->_out('q'); $this->rMargin = $this->original_rMargin; $this->lMargin = $this->original_lMargin; $this->SetCellPadding(0); //set current position $footer_y = $this->h - $this->footer_margin; if ($this->rtl) { $this->SetXY($this->original_rMargin, $footer_y); } else { $this->SetXY($this->original_lMargin, $footer_y); } $this->SetFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]); $this->Footer(); //restore position if ($this->rtl) { $this->SetXY($this->original_rMargin, $this->tMargin); } else { $this->SetXY($this->original_lMargin, $this->tMargin); } $this->_out('Q'); $this->lasth = $lasth; $this->thead = $temp_thead; $this->theadMargins = $temp_theadMargins; } // restore graphic settings $this->setGraphicVars($gvars); $this->current_column = $gvars['current_column']; $this->num_columns = $gvars['num_columns']; // calculate footer length $this->footerlen[$this->page] = $this->pagelen[$this->page] - $this->footerpos[$this->page] + 1; $this->InFooter = false; } /** * Check if we are on the page body (excluding page header and footer). * @return true if we are not in page header nor in page footer, false otherwise. * @protected * @since 5.9.091 (2011-06-15) */ protected function inPageBody() { return (($this->InHeader === false) AND ($this->InFooter === false)); } /** * This method is used to render the table header on new page (if any). * @protected * @since 4.5.030 (2009-03-25) */ protected function setTableHeader() { if ($this->num_columns > 1) { // multi column mode return; } if (isset($this->theadMargins['top'])) { // restore the original top-margin $this->tMargin = $this->theadMargins['top']; $this->pagedim[$this->page]['tm'] = $this->tMargin; $this->y = $this->tMargin; } if (!$this->empty_string($this->thead) AND (!$this->inthead)) { // set margins $prev_lMargin = $this->lMargin; $prev_rMargin = $this->rMargin; $prev_cell_padding = $this->cell_padding; $this->lMargin = $this->theadMargins['lmargin'] + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$this->theadMargins['page']]['olm']); $this->rMargin = $this->theadMargins['rmargin'] + ($this->pagedim[$this->page]['orm'] - $this->pagedim[$this->theadMargins['page']]['orm']); $this->cell_padding = $this->theadMargins['cell_padding']; if ($this->rtl) { $this->x = $this->w - $this->rMargin; } else { $this->x = $this->lMargin; } // account for special "cell" mode if ($this->theadMargins['cell']) { if ($this->rtl) { $this->x -= $this->cell_padding['R']; } else { $this->x += $this->cell_padding['L']; } } // print table header $this->writeHTML($this->thead, false, false, false, false, ''); // set new top margin to skip the table headers if (!isset($this->theadMargins['top'])) { $this->theadMargins['top'] = $this->tMargin; } // store end of header position if (!isset($this->columns[0]['th'])) { $this->columns[0]['th'] = array(); } $this->columns[0]['th']['\''.$this->page.'\''] = $this->y; $this->tMargin = $this->y; $this->pagedim[$this->page]['tm'] = $this->tMargin; $this->lasth = 0; $this->lMargin = $prev_lMargin; $this->rMargin = $prev_rMargin; $this->cell_padding = $prev_cell_padding; } } /** * Returns the current page number. * @return int page number * @public * @since 1.0 * @see getAliasNbPages() */ public function PageNo() { return $this->page; } /** * Defines a new spot color. * It can be expressed in RGB components or gray scale. * The method can be called before the first page is created and the value is retained from page to page. * @param $name (string) Full name of the spot color. * @param $c (float) Cyan color for CMYK. Value between 0 and 100. * @param $m (float) Magenta color for CMYK. Value between 0 and 100. * @param $y (float) Yellow color for CMYK. Value between 0 and 100. * @param $k (float) Key (Black) color for CMYK. Value between 0 and 100. * @public * @since 4.0.024 (2008-09-12) * @see SetDrawSpotColor(), SetFillSpotColor(), SetTextSpotColor() */ public function AddSpotColor($name, $c, $m, $y, $k) { if (!isset($this->spot_colors[$name])) { $i = (1 + count($this->spot_colors)); $this->spot_colors[$name] = array('C' => $c, 'M' => $m, 'Y' => $y, 'K' => $k, 'name' => $name, 'i' => $i); } } /** * Return the Spot color array. * @param $name (string) Name of the spot color. * @return (array) Spot color array or false if not defined. * @public * @since 5.9.125 (2011-10-03) */ public function getSpotColor($name) { if (isset($this->spot_colors[$name])) { return $this->spot_colors[$name]; } $color = preg_replace('/[\s]*/', '', $name); // remove extra spaces $color = strtolower($color); if (isset($this->spotcolor[$color])) { $this->AddSpotColor($this->spotcolor[$color][4], $this->spotcolor[$color][0], $this->spotcolor[$color][1], $this->spotcolor[$color][2], $this->spotcolor[$color][3]); return $this->spot_colors[$this->spotcolor[$color][4]]; } return false; } /** * Set the spot color for the specified type ('draw', 'fill', 'text'). * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text'). * @param $name (string) Name of the spot color. * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default). * @return (string) PDF color command. * @public * @since 5.9.125 (2011-10-03) */ public function setSpotColor($type, $name, $tint=100) { $spotcolor = $this->getSpotColor($name); if ($spotcolor === false) { $this->Error('Undefined spot color: '.$name.', you must add it on the spotcolors.php file.'); } $tint = (max(0, min(100, $tint)) / 100); $pdfcolor = sprintf('/CS%d ', $this->spot_colors[$name]['i']); switch ($type) { case 'draw': { $pdfcolor .= sprintf('CS %.3F SCN', $tint); $this->DrawColor = $pdfcolor; $this->strokecolor = $spotcolor; break; } case 'fill': { $pdfcolor .= sprintf('cs %.3F scn', $tint); $this->FillColor = $pdfcolor; $this->bgcolor = $spotcolor; break; } case 'text': { $pdfcolor .= sprintf('cs %.3F scn', $tint); $this->TextColor = $pdfcolor; $this->fgcolor = $spotcolor; break; } } $this->ColorFlag = ($this->FillColor != $this->TextColor); if ($this->page > 0) { $this->_out($pdfcolor); } if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['spot_colors'][$name] = $this->spot_colors[$name]; } return $pdfcolor; } /** * Defines the spot color used for all drawing operations (lines, rectangles and cell borders). * @param $name (string) Name of the spot color. * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default). * @public * @since 4.0.024 (2008-09-12) * @see AddSpotColor(), SetFillSpotColor(), SetTextSpotColor() */ public function SetDrawSpotColor($name, $tint=100) { $this->setSpotColor('draw', $name, $tint); } /** * Defines the spot color used for all filling operations (filled rectangles and cell backgrounds). * @param $name (string) Name of the spot color. * @param $tint (float) Intensity of the color (from 0 to 100 ; 100 = full intensity by default). * @public * @since 4.0.024 (2008-09-12) * @see AddSpotColor(), SetDrawSpotColor(), SetTextSpotColor() */ public function SetFillSpotColor($name, $tint=100) { $this->setSpotColor('fill', $name, $tint); } /** * Defines the spot color used for text. * @param $name (string) Name of the spot color. * @param $tint (int) Intensity of the color (from 0 to 100 ; 100 = full intensity by default). * @public * @since 4.0.024 (2008-09-12) * @see AddSpotColor(), SetDrawSpotColor(), SetFillSpotColor() */ public function SetTextSpotColor($name, $tint=100) { $this->setSpotColor('text', $name, $tint); } /** * Set the color array for the specified type ('draw', 'fill', 'text'). * It can be expressed in RGB, CMYK or GRAY SCALE components. * The method can be called before the first page is created and the value is retained from page to page. * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text'). * @param $color (array) Array of colors (1=gray, 3=RGB, 4=CMYK or 5=spotcolor=CMYK+name values). * @param $ret (boolean) If true do not send the PDF command. * @return (string) The PDF command or empty string. * @public * @since 3.1.000 (2008-06-11) */ public function setColorArray($type, $color, $ret=false) { if (is_array($color)) { $color = array_values($color); // component: grey, RGB red or CMYK cyan $c = isset($color[0]) ? $color[0] : -1; // component: RGB green or CMYK magenta $m = isset($color[1]) ? $color[1] : -1; // component: RGB blue or CMYK yellow $y = isset($color[2]) ? $color[2] : -1; // component: CMYK black $k = isset($color[3]) ? $color[3] : -1; // color name $name = isset($color[4]) ? $color[4] : ''; if ($c >= 0) { return $this->setColor($type, $c, $m, $y, $k, $ret, $name); } } return ''; } /** * Defines the color used for all drawing operations (lines, rectangles and cell borders). * It can be expressed in RGB, CMYK or GRAY SCALE components. * The method can be called before the first page is created and the value is retained from page to page. * @param $color (array) Array of colors (1, 3 or 4 values). * @param $ret (boolean) If true do not send the PDF command. * @return string the PDF command * @public * @since 3.1.000 (2008-06-11) * @see SetDrawColor() */ public function SetDrawColorArray($color, $ret=false) { return $this->setColorArray('draw', $color, $ret); } /** * Defines the color used for all filling operations (filled rectangles and cell backgrounds). * It can be expressed in RGB, CMYK or GRAY SCALE components. * The method can be called before the first page is created and the value is retained from page to page. * @param $color (array) Array of colors (1, 3 or 4 values). * @param $ret (boolean) If true do not send the PDF command. * @public * @since 3.1.000 (2008-6-11) * @see SetFillColor() */ public function SetFillColorArray($color, $ret=false) { return $this->setColorArray('fill', $color, $ret); } /** * Defines the color used for text. It can be expressed in RGB components or gray scale. * The method can be called before the first page is created and the value is retained from page to page. * @param $color (array) Array of colors (1, 3 or 4 values). * @param $ret (boolean) If true do not send the PDF command. * @public * @since 3.1.000 (2008-6-11) * @see SetFillColor() */ public function SetTextColorArray($color, $ret=false) { return $this->setColorArray('text', $color, $ret); } /** * Defines the color used by the specified type ('draw', 'fill', 'text'). * @param $type (string) Type of object affected by this color: ('draw', 'fill', 'text'). * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). * @param $col4 (float) KEY (BLACK) color for CMYK (0-100). * @param $ret (boolean) If true do not send the command. * @param $name (string) spot color name (if any) * @return (string) The PDF command or empty string. * @public * @since 5.9.125 (2011-10-03) */ public function setColor($type, $col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { // set default values if (!is_numeric($col1)) { $col1 = 0; } if (!is_numeric($col2)) { $col2 = -1; } if (!is_numeric($col3)) { $col3 = -1; } if (!is_numeric($col4)) { $col4 = -1; } // set color by case $suffix = ''; if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) { // Grey scale $col1 = max(0, min(255, $col1)); $intcolor = array('G' => $col1); $pdfcolor = sprintf('%.3F ', ($col1 / 255)); $suffix = 'g'; } elseif ($col4 == -1) { // RGB $col1 = max(0, min(255, $col1)); $col2 = max(0, min(255, $col2)); $col3 = max(0, min(255, $col3)); $intcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3); $pdfcolor = sprintf('%.3F %.3F %.3F ', ($col1 / 255), ($col2 / 255), ($col3 / 255)); $suffix = 'rg'; } else { $col1 = max(0, min(100, $col1)); $col2 = max(0, min(100, $col2)); $col3 = max(0, min(100, $col3)); $col4 = max(0, min(100, $col4)); if (empty($name)) { // CMYK $intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4); $pdfcolor = sprintf('%.3F %.3F %.3F %.3F ', ($col1 / 100), ($col2 / 100), ($col3 / 100), ($col4 / 100)); $suffix = 'k'; } else { // SPOT COLOR $intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4, 'name' => $name); $this->AddSpotColor($name, $col1, $col2, $col3, $col4); $pdfcolor = $this->setSpotColor($type, $name, 100); } } switch ($type) { case 'draw': { $pdfcolor .= strtoupper($suffix); $this->DrawColor = $pdfcolor; $this->strokecolor = $intcolor; break; } case 'fill': { $pdfcolor .= $suffix; $this->FillColor = $pdfcolor; $this->bgcolor = $intcolor; break; } case 'text': { $pdfcolor .= $suffix; $this->TextColor = $pdfcolor; $this->fgcolor = $intcolor; break; } } $this->ColorFlag = ($this->FillColor != $this->TextColor); if (($type != 'text') AND ($this->page > 0)) { if (!$ret) { $this->_out($pdfcolor); } return $pdfcolor; } return ''; } /** * Convert a color array into a string representation. * @param $c (array) Array of colors. * @return (string) The color array representation. * @protected * @since 5.9.137 (2011-12-01) */ protected function getColorStringFromArray($c) { $c = array_values($c); $color = '['; switch (count($c)) { case 4: { // CMYK $color .= sprintf('%.3F %.3F %.3F %.3F', (max(0, min(100, floatval($c[0]))) / 100), (max(0, min(100, floatval($c[1]))) / 100), (max(0, min(100, floatval($c[2]))) / 100), (max(0, min(100, floatval($c[3]))) / 100)); break; } case 3: { // RGB $color .= sprintf('%.3F %.3F %.3F', (max(0, min(255, floatval($c[0]))) / 255), (max(0, min(255, floatval($c[1]))) / 255), (max(0, min(255, floatval($c[2]))) / 255)); break; } case 1: { // grayscale $color .= sprintf('%.3F', (max(0, min(255, floatval($c[0]))) / 255)); break; } } $color .= ']'; return $color; } /** * Defines the color used for all drawing operations (lines, rectangles and cell borders). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). * @param $col4 (float) KEY (BLACK) color for CMYK (0-100). * @param $ret (boolean) If true do not send the command. * @param $name (string) spot color name (if any) * @return string the PDF command * @public * @since 1.3 * @see SetDrawColorArray(), SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell() */ public function SetDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { return $this->setColor('draw', $col1, $col2, $col3, $col4, $ret, $name); } /** * Defines the color used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). * @param $col4 (float) KEY (BLACK) color for CMYK (0-100). * @param $ret (boolean) If true do not send the command. * @param $name (string) Spot color name (if any). * @return (string) The PDF command. * @public * @since 1.3 * @see SetFillColorArray(), SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell() */ public function SetFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { return $this->setColor('fill', $col1, $col2, $col3, $col4, $ret, $name); } /** * Defines the color used for text. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page. * @param $col1 (float) GRAY level for single color, or Red color for RGB (0-255), or CYAN color for CMYK (0-100). * @param $col2 (float) GREEN color for RGB (0-255), or MAGENTA color for CMYK (0-100). * @param $col3 (float) BLUE color for RGB (0-255), or YELLOW color for CMYK (0-100). * @param $col4 (float) KEY (BLACK) color for CMYK (0-100). * @param $ret (boolean) If true do not send the command. * @param $name (string) Spot color name (if any). * @return (string) Empty string. * @public * @since 1.3 * @see SetTextColorArray(), SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell() */ public function SetTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') { return $this->setColor('text', $col1, $col2, $col3, $col4, $ret, $name); } /** * Returns the length of a string in user unit. A font must be selected.
    * @param $s (string) The string whose length is to be computed * @param $fontname (string) Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained. * @param $fontstyle (string) Font style. Possible values are (case insensitive): or any combination. The default value is regular. * @param $fontsize (float) Font size in points. The default value is the current size. * @param $getarray (boolean) if true returns an array of characters widths, if false returns the total length. * @return mixed int total string length or array of characted widths * @author Nicola Asuni * @public * @since 1.2 */ public function GetStringWidth($s, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) { return $this->GetArrStringWidth($this->utf8Bidi($this->UTF8StringToArray($s), $s, $this->tmprtl), $fontname, $fontstyle, $fontsize, $getarray); } /** * Returns the string length of an array of chars in user unit or an array of characters widths. A font must be selected.
    * @param $sa (string) The array of chars whose total length is to be computed * @param $fontname (string) Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained. * @param $fontstyle (string) Font style. Possible values are (case insensitive): or any combination. The default value is regular. * @param $fontsize (float) Font size in points. The default value is the current size. * @param $getarray (boolean) if true returns an array of characters widths, if false returns the total length. * @return mixed int total string length or array of characted widths * @author Nicola Asuni * @public * @since 2.4.000 (2008-03-06) */ public function GetArrStringWidth($sa, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) { // store current values if (!$this->empty_string($fontname)) { $prev_FontFamily = $this->FontFamily; $prev_FontStyle = $this->FontStyle; $prev_FontSizePt = $this->FontSizePt; $this->SetFont($fontname, $fontstyle, $fontsize, '', 'default', false); } // convert UTF-8 array to Latin1 if required $sa = $this->UTF8ArrToLatin1($sa); $w = 0; // total width $wa = array(); // array of characters widths foreach ($sa as $ck => $char) { // character width $cw = $this->GetCharWidth($char, isset($sa[($ck + 1)])); $wa[] = $cw; $w += $cw; } // restore previous values if (!$this->empty_string($fontname)) { $this->SetFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt, '', 'default', false); } if ($getarray) { return $wa; } return $w; } /** * Returns the length of the char in user unit for the current font considering current stretching and spacing (tracking/kerning). * @param $char (int) The char code whose length is to be returned * @param $notlast (boolean) set to false for the latest character on string, true otherwise (default) * @return float char width * @author Nicola Asuni * @public * @since 2.4.000 (2008-03-06) */ public function GetCharWidth($char, $notlast=true) { // get raw width $chw = $this->getRawCharWidth($char); if (($this->font_spacing != 0) AND $notlast) { // increase/decrease font spacing $chw += $this->font_spacing; } if ($this->font_stretching != 100) { // fixed stretching mode $chw *= ($this->font_stretching / 100); } return $chw; } /** * Returns the length of the char in user unit for the current font. * @param $char (int) The char code whose length is to be returned * @return float char width * @author Nicola Asuni * @public * @since 5.9.000 (2010-09-28) */ public function getRawCharWidth($char) { if ($char == 173) { // SHY character will not be printed return (0); } if (isset($this->CurrentFont['cw'][$char])) { $w = $this->CurrentFont['cw'][$char]; } elseif (isset($this->CurrentFont['dw'])) { // default width $w = $this->CurrentFont['dw']; } elseif (isset($this->CurrentFont['cw'][32])) { // default width $w = $this->CurrentFont['cw'][32]; } else { $w = 600; } return ($w * $this->FontSize / 1000); } /** * Returns the numbero of characters in a string. * @param $s (string) The input string. * @return int number of characters * @public * @since 2.0.0001 (2008-01-07) */ public function GetNumChars($s) { if ($this->isUnicodeFont()) { return count($this->UTF8StringToArray($s)); } return strlen($s); } /** * Fill the list of available fonts ($this->fontlist). * @protected * @since 4.0.013 (2008-07-28) */ protected function getFontsList() { $fontsdir = opendir($this->_getfontpath()); while (($file = readdir($fontsdir)) !== false) { if (substr($file, -4) == '.php') { array_push($this->fontlist, strtolower(basename($file, '.php'))); } } closedir($fontsdir); } /** * Imports a TrueType, Type1, core, or CID0 font and makes it available. * It is necessary to generate a font definition file first (read /fonts/utils/README.TXT). * The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by K_PATH_FONTS if the constant is defined. If it could not be found, the error "Could not include font definition file" is generated. * @param $family (string) Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font. * @param $style (string) Font style. Possible values are (case insensitive): * @param $fontfile (string) The font definition file. By default, the name is built from the family and style, in lower case with no spaces. * @return array containing the font data, or false in case of error. * @param $subset (mixed) if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font. * @public * @since 1.5 * @see SetFont(), setFontSubsetting() */ public function AddFont($family, $style='', $fontfile='', $subset='default') { if ($subset === 'default') { $subset = $this->font_subsetting; } if ($this->pdfa_mode) { $subset = false; } if ($this->empty_string($family)) { if (!$this->empty_string($this->FontFamily)) { $family = $this->FontFamily; } else { $this->Error('Empty font family'); } } // move embedded styles on $style if (substr($family, -1) == 'I') { $style .= 'I'; $family = substr($family, 0, -1); } if (substr($family, -1) == 'B') { $style .= 'B'; $family = substr($family, 0, -1); } // normalize family name $family = strtolower($family); if ((!$this->isunicode) AND ($family == 'arial')) { $family = 'helvetica'; } if (($family == 'symbol') OR ($family == 'zapfdingbats')) { $style = ''; } if ($this->pdfa_mode AND (isset($this->CoreFonts[$family]))) { // all fonts must be embedded $family = 'pdfa'.$family; } $tempstyle = strtoupper($style); $style = ''; // underline if (strpos($tempstyle, 'U') !== false) { $this->underline = true; } else { $this->underline = false; } // line-through (deleted) if (strpos($tempstyle, 'D') !== false) { $this->linethrough = true; } else { $this->linethrough = false; } // overline if (strpos($tempstyle, 'O') !== false) { $this->overline = true; } else { $this->overline = false; } // bold if (strpos($tempstyle, 'B') !== false) { $style .= 'B'; } // oblique if (strpos($tempstyle, 'I') !== false) { $style .= 'I'; } $bistyle = $style; $fontkey = $family.$style; $font_style = $style.($this->underline ? 'U' : '').($this->linethrough ? 'D' : '').($this->overline ? 'O' : ''); $fontdata = array('fontkey' => $fontkey, 'family' => $family, 'style' => $font_style); // check if the font has been already added $fb = $this->getFontBuffer($fontkey); if ($fb !== false) { if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $fb['i']; } return $fontdata; } if (isset($type)) { unset($type); } if (isset($cw)) { unset($cw); } // get specified font directory (if any) $fontdir = false; if (!$this->empty_string($fontfile)) { $fontdir = dirname($fontfile); if ($this->empty_string($fontdir) OR ($fontdir == '.')) { $fontdir = ''; } else { $fontdir .= '/'; } } $missing_style = false; // true when the font style variation is missing // search and include font file if ($this->empty_string($fontfile) OR (!$this->file_exists($fontfile))) { // build a standard filenames for specified font $tmp_fontfile = str_replace(' ', '', $family).strtolower($style).'.php'; // search files on various directories if (($fontdir !== false) AND $this->file_exists($fontdir.$tmp_fontfile)) { $fontfile = $fontdir.$tmp_fontfile; } elseif ($this->file_exists($this->_getfontpath().$tmp_fontfile)) { $fontfile = $this->_getfontpath().$tmp_fontfile; } elseif ($this->file_exists($tmp_fontfile)) { $fontfile = $tmp_fontfile; } elseif (!$this->empty_string($style)) { $missing_style = true; // try to remove the style part $tmp_fontfile = str_replace(' ', '', $family).'.php'; if (($fontdir !== false) AND $this->file_exists($fontdir.$tmp_fontfile)) { $fontfile = $fontdir.$tmp_fontfile; } elseif ($this->file_exists($this->_getfontpath().$tmp_fontfile)) { $fontfile = $this->_getfontpath().$tmp_fontfile; } else { $fontfile = $tmp_fontfile; } } } // include font file if ($this->file_exists($fontfile)) { include($fontfile); } else { $this->Error('Could not include font definition file: '.$family.''); } // check font parameters if ((!isset($type)) OR (!isset($cw))) { $this->Error('The font definition file has a bad format: '.$fontfile.''); } // SET default parameters if (!isset($file) OR $this->empty_string($file)) { $file = ''; } if (!isset($enc) OR $this->empty_string($enc)) { $enc = ''; } if (!isset($cidinfo) OR $this->empty_string($cidinfo)) { $cidinfo = array('Registry'=>'Adobe', 'Ordering'=>'Identity', 'Supplement'=>0); $cidinfo['uni2cid'] = array(); } if (!isset($ctg) OR $this->empty_string($ctg)) { $ctg = ''; } if (!isset($desc) OR $this->empty_string($desc)) { $desc = array(); } if (!isset($up) OR $this->empty_string($up)) { $up = -100; } if (!isset($ut) OR $this->empty_string($ut)) { $ut = 50; } if (!isset($cw) OR $this->empty_string($cw)) { $cw = array(); } if (!isset($dw) OR $this->empty_string($dw)) { // set default width if (isset($desc['MissingWidth']) AND ($desc['MissingWidth'] > 0)) { $dw = $desc['MissingWidth']; } elseif (isset($cw[32])) { $dw = $cw[32]; } else { $dw = 600; } } ++$this->numfonts; if ($type == 'core') { $name = $this->CoreFonts[$fontkey]; $subset = false; } elseif (($type == 'TrueType') OR ($type == 'Type1')) { $subset = false; } elseif ($type == 'TrueTypeUnicode') { $enc = 'Identity-H'; } elseif ($type == 'cidfont0') { if ($this->pdfa_mode) { $this->Error('All fonts must be embedded in PDF/A mode!'); } } else { $this->Error('Unknow font type: '.$type.''); } // set name if unset if (!isset($name) OR empty($name)) { $name = $fontkey; } // create artificial font style variations if missing (only works with non-embedded fonts) if (($type != 'core') AND $missing_style) { // style variations $styles = array('' => '', 'B' => ',Bold', 'I' => ',Italic', 'BI' => ',BoldItalic'); $name .= $styles[$bistyle]; // artificial bold if (strpos($bistyle, 'B') !== false) { if (isset($desc['StemV'])) { // from normal to bold $desc['StemV'] = round($desc['StemV'] * 1.75); } else { // bold $desc['StemV'] = 123; } } // artificial italic if (strpos($bistyle, 'I') !== false) { if (isset($desc['ItalicAngle'])) { $desc['ItalicAngle'] -= 11; } else { $desc['ItalicAngle'] = -11; } if (isset($desc['Flags'])) { $desc['Flags'] |= 64; //bit 7 } else { $desc['Flags'] = 64; } } } // initialize subsetchars to contain default ASCII values (0-255) $subsetchars = array_fill(0, 256, true); $this->setFontBuffer($fontkey, array('fontkey' => $fontkey, 'i' => $this->numfonts, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'dw' => $dw, 'enc' => $enc, 'cidinfo' => $cidinfo, 'file' => $file, 'ctg' => $ctg, 'subset' => $subset, 'subsetchars' => $subsetchars)); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['fonts'][$fontkey] = $this->numfonts; } if (isset($diff) AND (!empty($diff))) { //Search existing encodings $d = 0; $nb = count($this->diffs); for ($i=1; $i <= $nb; ++$i) { if ($this->diffs[$i] == $diff) { $d = $i; break; } } if ($d == 0) { $d = $nb + 1; $this->diffs[$d] = $diff; } $this->setFontSubBuffer($fontkey, 'diff', $d); } if (!$this->empty_string($file)) { if (!isset($this->FontFiles[$file])) { if ((strcasecmp($type,'TrueType') == 0) OR (strcasecmp($type, 'TrueTypeUnicode') == 0)) { $this->FontFiles[$file] = array('length1' => $originalsize, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey)); } elseif ($type != 'core') { $this->FontFiles[$file] = array('length1' => $size1, 'length2' => $size2, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey)); } } else { // update fontkeys that are sharing this font file $this->FontFiles[$file]['subset'] = ($this->FontFiles[$file]['subset'] AND $subset); if (!in_array($fontkey, $this->FontFiles[$file]['fontkeys'])) { $this->FontFiles[$file]['fontkeys'][] = $fontkey; } } } return $fontdata; } /** * Sets the font used to print character strings. * The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe). * The method can be called before the first page is created and the font is retained from page to page. * If you just wish to change the current font size, it is simpler to call SetFontSize(). * Note: for the standard fonts, the font metric files must be accessible. There are three possibilities for this:
    * @param $family (string) Family font. It can be either a name defined by AddFont() or one of the standard Type1 families (case insensitive): It is also possible to pass an empty string. In that case, the current family is retained. * @param $style (string) Font style. Possible values are (case insensitive): or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats basic fonts or other fonts when not defined. * @param $size (float) Font size in points. The default value is the current size. If no size has been specified since the beginning of the document, the value taken is 12 * @param $fontfile (string) The font definition file. By default, the name is built from the family and style, in lower case with no spaces. * @param $subset (mixed) if true embedd only a subset of the font (stores only the information related to the used characters); if false embedd full font; if 'default' uses the default value set using setFontSubsetting(). This option is valid only for TrueTypeUnicode fonts. If you want to enable users to change the document, set this parameter to false. If you subset the font, the person who receives your PDF would need to have your same font in order to make changes to your PDF. The file size of the PDF would also be smaller because you are embedding only part of a font. * @param $out (boolean) if true output the font size command, otherwise only set the font properties. * @author Nicola Asuni * @public * @since 1.0 * @see AddFont(), SetFontSize() */ public function SetFont($family, $style='', $size=0, $fontfile='', $subset='default', $out=true) { //Select a font; size given in points if ($size == 0) { $size = $this->FontSizePt; } // try to add font (if not already added) $fontdata = $this->AddFont($family, $style, $fontfile, $subset); $this->FontFamily = $fontdata['family']; $this->FontStyle = $fontdata['style']; $this->CurrentFont = $this->getFontBuffer($fontdata['fontkey']); $this->SetFontSize($size, $out); } /** * Defines the size of the current font. * @param $size (float) The font size in points. * @param $out (boolean) if true output the font size command, otherwise only set the font properties. * @public * @since 1.0 * @see SetFont() */ public function SetFontSize($size, $out=true) { // font size in points $this->FontSizePt = $size; // font size in user units $this->FontSize = $size / $this->k; // calculate some font metrics if (isset($this->CurrentFont['desc']['FontBBox'])) { $bbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1)); $font_height = ((intval($bbox[3]) - intval($bbox[1])) * $size / 1000); } else { $font_height = $size * 1.219; } if (isset($this->CurrentFont['desc']['Ascent']) AND ($this->CurrentFont['desc']['Ascent'] > 0)) { $font_ascent = ($this->CurrentFont['desc']['Ascent'] * $size / 1000); } if (isset($this->CurrentFont['desc']['Descent']) AND ($this->CurrentFont['desc']['Descent'] <= 0)) { $font_descent = (- $this->CurrentFont['desc']['Descent'] * $size / 1000); } if (!isset($font_ascent) AND !isset($font_descent)) { // core font $font_ascent = 0.76 * $font_height; $font_descent = $font_height - $font_ascent; } elseif (!isset($font_descent)) { $font_descent = $font_height - $font_ascent; } elseif (!isset($font_ascent)) { $font_ascent = $font_height - $font_descent; } $this->FontAscent = ($font_ascent / $this->k); $this->FontDescent = ($font_descent / $this->k); if ($out AND ($this->page > 0) AND (isset($this->CurrentFont['i']))) { $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt)); } } /** * Return the font descent value * @param $font (string) font name * @param $style (string) font style * @param $size (float) The size (in points) * @return int font descent * @public * @author Nicola Asuni * @since 4.9.003 (2010-03-30) */ public function getFontDescent($font, $style='', $size=0) { $fontdata = $this->AddFont($font, $style); $fontinfo = $this->getFontBuffer($fontdata['fontkey']); if (isset($fontinfo['desc']['Descent']) AND ($fontinfo['desc']['Descent'] <= 0)) { $descent = (- $fontinfo['desc']['Descent'] * $size / 1000); } else { $descent = 1.219 * 0.24 * $size; } return ($descent / $this->k); } /** * Return the font ascent value * @param $font (string) font name * @param $style (string) font style * @param $size (float) The size (in points) * @return int font ascent * @public * @author Nicola Asuni * @since 4.9.003 (2010-03-30) */ public function getFontAscent($font, $style='', $size=0) { $fontdata = $this->AddFont($font, $style); $fontinfo = $this->getFontBuffer($fontdata['fontkey']); if (isset($fontinfo['desc']['Ascent']) AND ($fontinfo['desc']['Ascent'] > 0)) { $ascent = ($fontinfo['desc']['Ascent'] * $size / 1000); } else { $ascent = 1.219 * 0.76 * $size; } return ($ascent / $this->k); } /** * Defines the default monospaced font. * @param $font (string) Font name. * @public * @since 4.5.025 */ public function SetDefaultMonospacedFont($font) { $this->default_monospaced_font = $font; } /** * Creates a new internal link and returns its identifier. An internal link is a clickable area which directs to another place within the document.
    * The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is defined with SetLink(). * @public * @since 1.5 * @see Cell(), Write(), Image(), Link(), SetLink() */ public function AddLink() { //Create a new internal link $n = count($this->links) + 1; $this->links[$n] = array(0, 0); return $n; } /** * Defines the page and position a link points to. * @param $link (int) The link identifier returned by AddLink() * @param $y (float) Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page) * @param $page (int) Number of target page; -1 indicates the current page. This is the default value * @public * @since 1.5 * @see AddLink() */ public function SetLink($link, $y=0, $page=-1) { if ($y == -1) { $y = $this->y; } if ($page == -1) { $page = $this->page; } $this->links[$link] = array($page, $y); } /** * Puts a link on a rectangular area of the page. * Text or image links are generally put via Cell(), Write() or Image(), but this method can be useful for instance to define a clickable area inside an image. * @param $x (float) Abscissa of the upper-left corner of the rectangle * @param $y (float) Ordinate of the upper-left corner of the rectangle * @param $w (float) Width of the rectangle * @param $h (float) Height of the rectangle * @param $link (mixed) URL or identifier returned by AddLink() * @param $spaces (int) number of spaces on the text to link * @public * @since 1.5 * @see AddLink(), Annotation(), Cell(), Write(), Image() */ public function Link($x, $y, $w, $h, $link, $spaces=0) { $this->Annotation($x, $y, $w, $h, $link, array('Subtype'=>'Link'), $spaces); } /** * Puts a markup annotation on a rectangular area of the page. * !!!!THE ANNOTATION SUPPORT IS NOT YET FULLY IMPLEMENTED !!!! * @param $x (float) Abscissa of the upper-left corner of the rectangle * @param $y (float) Ordinate of the upper-left corner of the rectangle * @param $w (float) Width of the rectangle * @param $h (float) Height of the rectangle * @param $text (string) annotation text or alternate content * @param $opt (array) array of options (see section 8.4 of PDF reference 1.7). * @param $spaces (int) number of spaces on the text to link * @public * @since 4.0.018 (2008-08-06) */ public function Annotation($x, $y, $w, $h, $text, $opt=array('Subtype'=>'Text'), $spaces=0) { if ($this->inxobj) { // store parameters for later use on template $this->xobjects[$this->xobjid]['annotations'][] = array('x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'text' => $text, 'opt' => $opt, 'spaces' => $spaces); return; } if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); // recalculate coordinates to account for graphic transformations if (isset($this->transfmatrix) AND !empty($this->transfmatrix)) { for ($i=$this->transfmatrix_key; $i > 0; --$i) { $maxid = count($this->transfmatrix[$i]) - 1; for ($j=$maxid; $j >= 0; --$j) { $ctm = $this->transfmatrix[$i][$j]; if (isset($ctm['a'])) { $x = $x * $this->k; $y = ($this->h - $y) * $this->k; $w = $w * $this->k; $h = $h * $this->k; // top left $xt = $x; $yt = $y; $x1 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e']; $y1 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f']; // top right $xt = $x + $w; $yt = $y; $x2 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e']; $y2 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f']; // bottom left $xt = $x; $yt = $y - $h; $x3 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e']; $y3 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f']; // bottom right $xt = $x + $w; $yt = $y - $h; $x4 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e']; $y4 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f']; // new coordinates (rectangle area) $x = min($x1, $x2, $x3, $x4); $y = max($y1, $y2, $y3, $y4); $w = (max($x1, $x2, $x3, $x4) - $x) / $this->k; $h = ($y - min($y1, $y2, $y3, $y4)) / $this->k; $x = $x / $this->k; $y = $this->h - ($y / $this->k); } } } } if ($this->page <= 0) { $page = 1; } else { $page = $this->page; } if (!isset($this->PageAnnots[$page])) { $this->PageAnnots[$page] = array(); } ++$this->n; $this->PageAnnots[$page][] = array('n' => $this->n, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'txt' => $text, 'opt' => $opt, 'numspaces' => $spaces); if (!$this->pdfa_mode) { if ((($opt['Subtype'] == 'FileAttachment') OR ($opt['Subtype'] == 'Sound')) AND (!$this->empty_string($opt['FS'])) AND $this->file_exists($opt['FS']) AND (!isset($this->embeddedfiles[basename($opt['FS'])]))) { ++$this->n; $this->embeddedfiles[basename($opt['FS'])] = array('n' => $this->n, 'file' => $opt['FS']); } } // Add widgets annotation's icons if (isset($opt['mk']['i']) AND $this->file_exists($opt['mk']['i'])) { $this->Image($opt['mk']['i'], '', '', 10, 10, '', '', '', false, 300, '', false, false, 0, false, true); } if (isset($opt['mk']['ri']) AND $this->file_exists($opt['mk']['ri'])) { $this->Image($opt['mk']['ri'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true); } if (isset($opt['mk']['ix']) AND $this->file_exists($opt['mk']['ix'])) { $this->Image($opt['mk']['ix'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true); } } /** * Embedd the attached files. * @since 4.4.000 (2008-12-07) * @protected * @see Annotation() */ protected function _putEmbeddedFiles() { if ($this->pdfa_mode) { // embedded files are not allowed in PDF/A mode return; } reset($this->embeddedfiles); foreach ($this->embeddedfiles as $filename => $filedata) { $data = file_get_contents($filedata['file']); $filter = ''; if ($this->compress) { $data = gzcompress($data); $filter = ' /Filter /FlateDecode'; } $stream = $this->_getrawstream($data, $filedata['n']); $out = $this->_getobj($filedata['n'])."\n"; $out .= '<< /Type /EmbeddedFile'.$filter.' /Length '.strlen($stream).' >>'; $out .= ' stream'."\n".$stream."\n".'endstream'; $out .= "\n".'endobj'; $this->_out($out); } } /** * Prints a text cell at the specified position. * This method allows to place a string precisely on the page. * @param $x (float) Abscissa of the cell origin * @param $y (float) Ordinate of the cell origin * @param $txt (string) String to print * @param $fstroke (int) outline size in user units (false = disable) * @param $fclip (boolean) if true activate clipping mode (you must call StartTransform() before this function and StopTransform() to stop the clipping tranformation). * @param $ffill (boolean) if true fills the text * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $ln (int) Indicates where the current position should go after the call. Possible values are:Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. * @param $align (string) Allows to center or align the text. Possible values are: * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). * @param $link (mixed) URL or identifier returned by AddLink(). * @param $stretch (int) font stretch mode: General font stretching and scaling values will be preserved when possible. * @param $ignore_min_height (boolean) if true ignore automatic minimum height value. * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are: * @param $valign (string) text vertical alignment inside the cell. Possible values are: * @param $rtloff (boolean) if true uses the page top-left corner as origin of axis for $x and $y initial position. * @public * @since 1.0 * @see Cell(), Write(), MultiCell(), WriteHTML(), WriteHTMLCell() */ public function Text($x, $y, $txt, $fstroke=false, $fclip=false, $ffill=true, $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M', $rtloff=false) { $textrendermode = $this->textrendermode; $textstrokewidth = $this->textstrokewidth; $this->setTextRenderingMode($fstroke, $ffill, $fclip); $this->SetXY($x, $y, $rtloff); $this->Cell(0, 0, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height, $calign, $valign); // restore previous rendering mode $this->textrendermode = $textrendermode; $this->textstrokewidth = $textstrokewidth; } /** * Whenever a page break condition is met, the method is called, and the break is issued or not depending on the returned value. * The default implementation returns a value according to the mode selected by SetAutoPageBreak().
    * This method is called automatically and should not be called directly by the application. * @return boolean * @public * @since 1.4 * @see SetAutoPageBreak() */ public function AcceptPageBreak() { if ($this->num_columns > 1) { // multi column mode if ($this->current_column < ($this->num_columns - 1)) { // go to next column $this->selectColumn($this->current_column + 1); } else { // add a new page $this->AddPage(); // set first column $this->selectColumn(0); } // avoid page breaking from checkPageBreak() return false; } return $this->AutoPageBreak; } /** * Add page if needed. * @param $h (float) Cell height. Default value: 0. * @param $y (mixed) starting y position, leave empty for current position. * @param $addpage (boolean) if true add a page, otherwise only return the true/false state * @return boolean true in case of page break, false otherwise. * @since 3.2.000 (2008-07-01) * @protected */ protected function checkPageBreak($h=0, $y='', $addpage=true) { if ($this->empty_string($y)) { $y = $this->y; } $current_page = $this->page; if ((($y + $h) > $this->PageBreakTrigger) AND ($this->inPageBody()) AND ($this->AcceptPageBreak())) { if ($addpage) { //Automatic page break $x = $this->x; $this->AddPage($this->CurOrientation); $this->y = $this->tMargin; $oldpage = $this->page - 1; if ($this->rtl) { if ($this->pagedim[$this->page]['orm'] != $this->pagedim[$oldpage]['orm']) { $this->x = $x - ($this->pagedim[$this->page]['orm'] - $this->pagedim[$oldpage]['orm']); } else { $this->x = $x; } } else { if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) { $this->x = $x + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$oldpage]['olm']); } else { $this->x = $x; } } } return true; } if ($current_page != $this->page) { // account for columns mode return true; } return false; } /** * Removes SHY characters from text. * Unicode Data: * @param $txt (string) input string * @return string without SHY characters. * @public * @since (4.5.019) 2009-02-28 */ public function removeSHY($txt='') { $txt = preg_replace('/([\\xc2]{1}[\\xad]{1})/', '', $txt); if (!$this->isunicode) { $txt = preg_replace('/([\\xad]{1})/', '', $txt); } return $txt; } /** * Prints a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.
    * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting. * @param $w (float) Cell width. If 0, the cell extends up to the right margin. * @param $h (float) Cell height. Default value: 0. * @param $txt (string) String to print. Default value: empty string. * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $ln (int) Indicates where the current position should go after the call. Possible values are: Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. * @param $align (string) Allows to center or align the text. Possible values are: * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). * @param $link (mixed) URL or identifier returned by AddLink(). * @param $stretch (int) font stretch mode: General font stretching and scaling values will be preserved when possible. * @param $ignore_min_height (boolean) if true ignore automatic minimum height value. * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are: * @param $valign (string) text vertical alignment inside the cell. Possible values are: * @public * @since 1.0 * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak() */ public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') { $prev_cell_margin = $this->cell_margin; $prev_cell_padding = $this->cell_padding; $this->adjustCellPadding($border); if (!$ignore_min_height) { $min_cell_height = ($this->FontSize * $this->cell_height_ratio) + $this->cell_padding['T'] + $this->cell_padding['B']; if ($h < $min_cell_height) { $h = $min_cell_height; } } $this->checkPageBreak($h + $this->cell_margin['T'] + $this->cell_margin['B']); $this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, true, $calign, $valign)); $this->cell_padding = $prev_cell_padding; $this->cell_margin = $prev_cell_margin; } /** * Returns the PDF string code to print a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text.
    * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting. * @param $w (float) Cell width. If 0, the cell extends up to the right margin. * @param $h (float) Cell height. Default value: 0. * @param $txt (string) String to print. Default value: empty string. * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $ln (int) Indicates where the current position should go after the call. Possible values are:Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. * @param $align (string) Allows to center or align the text. Possible values are: * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). * @param $link (mixed) URL or identifier returned by AddLink(). * @param $stretch (int) font stretch mode: General font stretching and scaling values will be preserved when possible. * @param $ignore_min_height (boolean) if true ignore automatic minimum height value. * @param $calign (string) cell vertical alignment relative to the specified Y value. Possible values are: * @param $valign (string) text vertical alignment inside the cell. Possible values are: * @return string containing cell code * @protected * @since 1.0 * @see Cell() */ protected function getCellCode($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') { // replace 'NO-BREAK SPACE' (U+00A0) character with a simple space $txt = str_replace($this->unichr(160), ' ', $txt); $prev_cell_margin = $this->cell_margin; $prev_cell_padding = $this->cell_padding; $txt = $this->removeSHY($txt); $rs = ''; //string to be returned $this->adjustCellPadding($border); if (!$ignore_min_height) { $min_cell_height = ($this->FontSize * $this->cell_height_ratio) + $this->cell_padding['T'] + $this->cell_padding['B']; if ($h < $min_cell_height) { $h = $min_cell_height; } } $k = $this->k; // check page for no-write regions and adapt page margins if necessary list($this->x, $this->y) = $this->checkPageRegions($h, $this->x, $this->y); if ($this->rtl) { $x = $this->x - $this->cell_margin['R']; } else { $x = $this->x + $this->cell_margin['L']; } $y = $this->y + $this->cell_margin['T']; $prev_font_stretching = $this->font_stretching; $prev_font_spacing = $this->font_spacing; // cell vertical alignment switch ($calign) { case 'A': { // font top switch ($valign) { case 'T': { // top $y -= $this->cell_padding['T']; break; } case 'B': { // bottom $y -= ($h - $this->cell_padding['B'] - $this->FontAscent - $this->FontDescent); break; } default: case 'C': case 'M': { // center $y -= (($h - $this->FontAscent - $this->FontDescent) / 2); break; } } break; } case 'L': { // font baseline switch ($valign) { case 'T': { // top $y -= ($this->cell_padding['T'] + $this->FontAscent); break; } case 'B': { // bottom $y -= ($h - $this->cell_padding['B'] - $this->FontDescent); break; } default: case 'C': case 'M': { // center $y -= (($h + $this->FontAscent - $this->FontDescent) / 2); break; } } break; } case 'D': { // font bottom switch ($valign) { case 'T': { // top $y -= ($this->cell_padding['T'] + $this->FontAscent + $this->FontDescent); break; } case 'B': { // bottom $y -= ($h - $this->cell_padding['B']); break; } default: case 'C': case 'M': { // center $y -= (($h + $this->FontAscent + $this->FontDescent) / 2); break; } } break; } case 'B': { // cell bottom $y -= $h; break; } case 'C': case 'M': { // cell center $y -= ($h / 2); break; } default: case 'T': { // cell top break; } } // text vertical alignment switch ($valign) { case 'T': { // top $yt = $y + $this->cell_padding['T']; break; } case 'B': { // bottom $yt = $y + $h - $this->cell_padding['B'] - $this->FontAscent - $this->FontDescent; break; } default: case 'C': case 'M': { // center $yt = $y + (($h - $this->FontAscent - $this->FontDescent) / 2); break; } } $basefonty = $yt + $this->FontAscent; if ($this->empty_string($w) OR ($w <= 0)) { if ($this->rtl) { $w = $x - $this->lMargin; } else { $w = $this->w - $this->rMargin - $x; } } $s = ''; // fill and borders if (is_string($border) AND (strlen($border) == 4)) { // full border $border = 1; } if ($fill OR ($border == 1)) { if ($fill) { $op = ($border == 1) ? 'B' : 'f'; } else { $op = 'S'; } if ($this->rtl) { $xk = (($x - $w) * $k); } else { $xk = ($x * $k); } $s .= sprintf('%.2F %.2F %.2F %.2F re %s ', $xk, (($this->h - $y) * $k), ($w * $k), (-$h * $k), $op); } // draw borders $s .= $this->getCellBorder($x, $y, $w, $h, $border); if ($txt != '') { $txt2 = $txt; if ($this->isunicode) { if (($this->CurrentFont['type'] == 'core') OR ($this->CurrentFont['type'] == 'TrueType') OR ($this->CurrentFont['type'] == 'Type1')) { $txt2 = $this->UTF8ToLatin1($txt2); } else { $unicode = $this->UTF8StringToArray($txt); // array of UTF-8 unicode values $unicode = $this->utf8Bidi($unicode, '', $this->tmprtl); if (defined('K_THAI_TOPCHARS') AND (K_THAI_TOPCHARS == true)) { // ---- Fix for bug #2977340 "Incorrect Thai characters position arrangement" ---- // NOTE: this doesn't work with HTML justification // Symbols that could overlap on the font top (only works in LTR) $topchar = array(3611, 3613, 3615, 3650, 3651, 3652); // chars that extends on top $topsym = array(3633, 3636, 3637, 3638, 3639, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662); // symbols with top position $numchars = count($unicode); // number of chars $unik = 0; $uniblock = array(); $uniblock[$unik] = array(); $uniblock[$unik][] = $unicode[0]; // resolve overlapping conflicts by splitting the string in several parts for ($i = 1; $i < $numchars; ++$i) { // check if symbols overlaps at top if (in_array($unicode[$i], $topsym) AND (in_array($unicode[($i - 1)], $topsym) OR in_array($unicode[($i - 1)], $topchar))) { // move symbols to another array ++$unik; $uniblock[$unik] = array(); $uniblock[$unik][] = $unicode[$i]; ++$unik; $uniblock[$unik] = array(); $unicode[$i] = 0x200b; // Unicode Character 'ZERO WIDTH SPACE' (DEC:8203, U+200B) } else { $uniblock[$unik][] = $unicode[$i]; } } // ---- END OF Fix for bug #2977340 } $txt2 = $this->arrUTF8ToUTF16BE($unicode, false); } } $txt2 = $this->_escape($txt2); // get current text width (considering general font stretching and spacing) $txwidth = $this->GetStringWidth($txt); $width = $txwidth; // check for stretch mode if ($stretch > 0) { // calculate ratio between cell width and text width if ($width <= 0) { $ratio = 1; } else { $ratio = (($w - $this->cell_padding['L'] - $this->cell_padding['R']) / $width); } // check if stretching is required if (($ratio < 1) OR (($ratio > 1) AND (($stretch % 2) == 0))) { // the text will be stretched to fit cell width if ($stretch > 2) { // set new character spacing $this->font_spacing += ($w - $this->cell_padding['L'] - $this->cell_padding['R'] - $width) / (max(($this->GetNumChars($txt) - 1), 1) * ($this->font_stretching / 100)); } else { // set new horizontal stretching $this->font_stretching *= $ratio; } // recalculate text width (the text fills the entire cell) $width = $w - $this->cell_padding['L'] - $this->cell_padding['R']; // reset alignment $align = ''; } } if ($this->font_stretching != 100) { // apply font stretching $rs .= sprintf('BT %.2F Tz ET ', $this->font_stretching); } if ($this->font_spacing != 0) { // increase/decrease font spacing $rs .= sprintf('BT %.2F Tc ET ', ($this->font_spacing * $this->k)); } if ($this->ColorFlag AND ($this->textrendermode < 4)) { $s .= 'q '.$this->TextColor.' '; } // rendering mode $s .= sprintf('BT %d Tr %.2F w ET ', $this->textrendermode, $this->textstrokewidth); // count number of spaces $ns = substr_count($txt, chr(32)); // Justification $spacewidth = 0; if (($align == 'J') AND ($ns > 0)) { if ($this->isUnicodeFont()) { // get string width without spaces $width = $this->GetStringWidth(str_replace(' ', '', $txt)); // calculate average space width $spacewidth = -1000 * ($w - $width - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1) / $this->FontSize; if ($this->font_stretching != 100) { // word spacing is affected by stretching $spacewidth /= ($this->font_stretching / 100); } // set word position to be used with TJ operator $txt2 = str_replace(chr(0).chr(32), ') '.sprintf('%.3F', $spacewidth).' (', $txt2); $unicode_justification = true; } else { // get string width $width = $txwidth; // new space width $spacewidth = (($w - $width - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1)) * $this->k; if ($this->font_stretching != 100) { // word spacing (Tw) is affected by stretching $spacewidth /= ($this->font_stretching / 100); } // set word spacing $rs .= sprintf('BT %.3F Tw ET ', $spacewidth); } $width = $w - $this->cell_padding['L'] - $this->cell_padding['R']; } // replace carriage return characters $txt2 = str_replace("\r", ' ', $txt2); switch ($align) { case 'C': { $dx = ($w - $width) / 2; break; } case 'R': { if ($this->rtl) { $dx = $this->cell_padding['R']; } else { $dx = $w - $width - $this->cell_padding['R']; } break; } case 'L': { if ($this->rtl) { $dx = $w - $width - $this->cell_padding['L']; } else { $dx = $this->cell_padding['L']; } break; } case 'J': default: { if ($this->rtl) { $dx = $this->cell_padding['R']; } else { $dx = $this->cell_padding['L']; } break; } } if ($this->rtl) { $xdx = $x - $dx - $width; } else { $xdx = $x + $dx; } $xdk = $xdx * $k; // print text $s .= sprintf('BT %.2F %.2F Td [(%s)] TJ ET', $xdk, (($this->h - $basefonty) * $k), $txt2); if (isset($uniblock)) { // print overlapping characters as separate string $xshift = 0; // horizontal shift $ty = (($this->h - $basefonty + (0.2 * $this->FontSize)) * $k); $spw = (($w - $txwidth - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1)); foreach ($uniblock as $uk => $uniarr) { if (($uk % 2) == 0) { // x space to skip if ($spacewidth != 0) { // justification shift $xshift += (count(array_keys($uniarr, 32)) * $spw); } $xshift += $this->GetArrStringWidth($uniarr); // + shift justification } else { // character to print $topchr = $this->arrUTF8ToUTF16BE($uniarr, false); $topchr = $this->_escape($topchr); $s .= sprintf(' BT %.2F %.2F Td [(%s)] TJ ET', ($xdk + ($xshift * $k)), $ty, $topchr); } } } if ($this->underline) { $s .= ' '.$this->_dounderlinew($xdx, $basefonty, $width); } if ($this->linethrough) { $s .= ' '.$this->_dolinethroughw($xdx, $basefonty, $width); } if ($this->overline) { $s .= ' '.$this->_dooverlinew($xdx, $basefonty, $width); } if ($this->ColorFlag AND ($this->textrendermode < 4)) { $s .= ' Q'; } if ($link) { $this->Link($xdx, $yt, $width, ($this->FontAscent + $this->FontDescent), $link, $ns); } } // output cell if ($s) { // output cell $rs .= $s; if ($this->font_spacing != 0) { // reset font spacing mode $rs .= ' BT 0 Tc ET'; } if ($this->font_stretching != 100) { // reset font stretching mode $rs .= ' BT 100 Tz ET'; } } // reset word spacing if (!$this->isUnicodeFont() AND ($align == 'J')) { $rs .= ' BT 0 Tw ET'; } // reset stretching and spacing $this->font_stretching = $prev_font_stretching; $this->font_spacing = $prev_font_spacing; $this->lasth = $h; if ($ln > 0) { //Go to the beginning of the next line $this->y = $y + $h + $this->cell_margin['B']; if ($ln == 1) { if ($this->rtl) { $this->x = $this->w - $this->rMargin; } else { $this->x = $this->lMargin; } } } else { // go left or right by case if ($this->rtl) { $this->x = $x - $w - $this->cell_margin['L']; } else { $this->x = $x + $w + $this->cell_margin['R']; } } $gstyles = ''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor."\n"; $rs = $gstyles.$rs; $this->cell_padding = $prev_cell_padding; $this->cell_margin = $prev_cell_margin; return $rs; } /** * Returns the code to draw the cell border * @param $x (float) X coordinate. * @param $y (float) Y coordinate. * @param $w (float) Cell width. * @param $h (float) Cell height. * @param $brd (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @return string containing cell border code * @protected * @see SetLineStyle() * @since 5.7.000 (2010-08-02) */ protected function getCellBorder($x, $y, $w, $h, $brd) { $s = ''; // string to be returned if (empty($brd)) { return $s; } if ($brd == 1) { $brd = array('LRTB' => true); } // calculate coordinates for border $k = $this->k; if ($this->rtl) { $xeL = ($x - $w) * $k; $xeR = $x * $k; } else { $xeL = $x * $k; $xeR = ($x + $w) * $k; } $yeL = (($this->h - ($y + $h)) * $k); $yeT = (($this->h - $y) * $k); $xeT = $xeL; $xeB = $xeR; $yeR = $yeT; $yeB = $yeL; if (is_string($brd)) { // convert string to array $slen = strlen($brd); $newbrd = array(); for ($i = 0; $i < $slen; ++$i) { $newbrd[$brd[$i]] = array('cap' => 'square', 'join' => 'miter'); } $brd = $newbrd; } if (isset($brd['mode'])) { $mode = $brd['mode']; unset($brd['mode']); } else { $mode = 'normal'; } foreach ($brd as $border => $style) { if (is_array($style) AND !empty($style)) { // apply border style $prev_style = $this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '; $s .= $this->SetLineStyle($style, true)."\n"; } switch ($mode) { case 'ext': { $off = (($this->LineWidth / 2) * $k); $xL = $xeL - $off; $xR = $xeR + $off; $yT = $yeT + $off; $yL = $yeL - $off; $xT = $xL; $xB = $xR; $yR = $yT; $yB = $yL; $w += $this->LineWidth; $h += $this->LineWidth; break; } case 'int': { $off = ($this->LineWidth / 2) * $k; $xL = $xeL + $off; $xR = $xeR - $off; $yT = $yeT - $off; $yL = $yeL + $off; $xT = $xL; $xB = $xR; $yR = $yT; $yB = $yL; $w -= $this->LineWidth; $h -= $this->LineWidth; break; } case 'normal': default: { $xL = $xeL; $xT = $xeT; $xB = $xeB; $xR = $xeR; $yL = $yeL; $yT = $yeT; $yB = $yeB; $yR = $yeR; break; } } // draw borders by case if (strlen($border) == 4) { $s .= sprintf('%.2F %.2F %.2F %.2F re S ', $xT, $yT, ($w * $k), (-$h * $k)); } elseif (strlen($border) == 3) { if (strpos($border,'B') === false) { // LTR $s .= sprintf('%.2F %.2F m ', $xL, $yL); $s .= sprintf('%.2F %.2F l ', $xT, $yT); $s .= sprintf('%.2F %.2F l ', $xR, $yR); $s .= sprintf('%.2F %.2F l ', $xB, $yB); $s .= 'S '; } elseif (strpos($border,'L') === false) { // TRB $s .= sprintf('%.2F %.2F m ', $xT, $yT); $s .= sprintf('%.2F %.2F l ', $xR, $yR); $s .= sprintf('%.2F %.2F l ', $xB, $yB); $s .= sprintf('%.2F %.2F l ', $xL, $yL); $s .= 'S '; } elseif (strpos($border,'T') === false) { // RBL $s .= sprintf('%.2F %.2F m ', $xR, $yR); $s .= sprintf('%.2F %.2F l ', $xB, $yB); $s .= sprintf('%.2F %.2F l ', $xL, $yL); $s .= sprintf('%.2F %.2F l ', $xT, $yT); $s .= 'S '; } elseif (strpos($border,'R') === false) { // BLT $s .= sprintf('%.2F %.2F m ', $xB, $yB); $s .= sprintf('%.2F %.2F l ', $xL, $yL); $s .= sprintf('%.2F %.2F l ', $xT, $yT); $s .= sprintf('%.2F %.2F l ', $xR, $yR); $s .= 'S '; } } elseif (strlen($border) == 2) { if ((strpos($border,'L') !== false) AND (strpos($border,'T') !== false)) { // LT $s .= sprintf('%.2F %.2F m ', $xL, $yL); $s .= sprintf('%.2F %.2F l ', $xT, $yT); $s .= sprintf('%.2F %.2F l ', $xR, $yR); $s .= 'S '; } elseif ((strpos($border,'T') !== false) AND (strpos($border,'R') !== false)) { // TR $s .= sprintf('%.2F %.2F m ', $xT, $yT); $s .= sprintf('%.2F %.2F l ', $xR, $yR); $s .= sprintf('%.2F %.2F l ', $xB, $yB); $s .= 'S '; } elseif ((strpos($border,'R') !== false) AND (strpos($border,'B') !== false)) { // RB $s .= sprintf('%.2F %.2F m ', $xR, $yR); $s .= sprintf('%.2F %.2F l ', $xB, $yB); $s .= sprintf('%.2F %.2F l ', $xL, $yL); $s .= 'S '; } elseif ((strpos($border,'B') !== false) AND (strpos($border,'L') !== false)) { // BL $s .= sprintf('%.2F %.2F m ', $xB, $yB); $s .= sprintf('%.2F %.2F l ', $xL, $yL); $s .= sprintf('%.2F %.2F l ', $xT, $yT); $s .= 'S '; } elseif ((strpos($border,'L') !== false) AND (strpos($border,'R') !== false)) { // LR $s .= sprintf('%.2F %.2F m ', $xL, $yL); $s .= sprintf('%.2F %.2F l ', $xT, $yT); $s .= 'S '; $s .= sprintf('%.2F %.2F m ', $xR, $yR); $s .= sprintf('%.2F %.2F l ', $xB, $yB); $s .= 'S '; } elseif ((strpos($border,'T') !== false) AND (strpos($border,'B') !== false)) { // TB $s .= sprintf('%.2F %.2F m ', $xT, $yT); $s .= sprintf('%.2F %.2F l ', $xR, $yR); $s .= 'S '; $s .= sprintf('%.2F %.2F m ', $xB, $yB); $s .= sprintf('%.2F %.2F l ', $xL, $yL); $s .= 'S '; } } else { // strlen($border) == 1 if (strpos($border,'L') !== false) { // L $s .= sprintf('%.2F %.2F m ', $xL, $yL); $s .= sprintf('%.2F %.2F l ', $xT, $yT); $s .= 'S '; } elseif (strpos($border,'T') !== false) { // T $s .= sprintf('%.2F %.2F m ', $xT, $yT); $s .= sprintf('%.2F %.2F l ', $xR, $yR); $s .= 'S '; } elseif (strpos($border,'R') !== false) { // R $s .= sprintf('%.2F %.2F m ', $xR, $yR); $s .= sprintf('%.2F %.2F l ', $xB, $yB); $s .= 'S '; } elseif (strpos($border,'B') !== false) { // B $s .= sprintf('%.2F %.2F m ', $xB, $yB); $s .= sprintf('%.2F %.2F l ', $xL, $yL); $s .= 'S '; } } if (is_array($style) AND !empty($style)) { // reset border style to previous value $s .= "\n".$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor."\n"; } } return $s; } /** * This method allows printing text with line breaks. * They can be automatic (as soon as the text reaches the right border of the cell) or explicit (via the \n character). As many cells as necessary are output, one below the other.
    * Text can be aligned, centered or justified. The cell block can be framed and the background painted. * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page. * @param $h (float) Cell minimum height. The cell extends automatically if needed. * @param $txt (string) String to print * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $align (string) Allows to center or align the text. Possible values are: * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). * @param $ln (int) Indicates where the current position should go after the call. Possible values are: * @param $x (float) x position in user units * @param $y (float) y position in user units * @param $reseth (boolean) if true reset the last cell height (default true). * @param $stretch (int) font stretch mode: General font stretching and scaling values will be preserved when possible. * @param $ishtml (boolean) INTERNAL USE ONLY -- set to true if $txt is HTML content (default = false). Never set this parameter to true, use instead writeHTMLCell() or writeHTML() methods. * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width. * @param $maxh (float) maximum height. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. This feature works only when $ishtml=false. * @param $valign (string) Vertical alignment of text (requires $maxh = $h > 0). Possible values are:. This feature works only when $ishtml=false and the cell must fit in a single page. * @param $fitcell (boolean) if true attempt to fit all the text within the cell by reducing the font size (do not work in HTML mode). * @return int Return the number of cells or 1 for html mode. * @public * @since 1.3 * @see SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), Cell(), Write(), SetAutoPageBreak() */ public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0, $valign='T', $fitcell=false) { $prev_cell_margin = $this->cell_margin; $prev_cell_padding = $this->cell_padding; // adjust internal padding $this->adjustCellPadding($border); $mc_padding = $this->cell_padding; $mc_margin = $this->cell_margin; $this->cell_padding['T'] = 0; $this->cell_padding['B'] = 0; $this->setCellMargins(0, 0, 0, 0); if ($this->empty_string($this->lasth) OR $reseth) { // reset row height $this->resetLastH(); } if (!$this->empty_string($y)) { $this->SetY($y); } else { $y = $this->GetY(); } $resth = 0; if (($h > 0) AND $this->inPageBody() AND (($y + $h + $mc_margin['T'] + $mc_margin['B']) > $this->PageBreakTrigger)) { // spit cell in more pages/columns $newh = ($this->PageBreakTrigger - $y); $resth = ($h - $newh); // cell to be printed on the next page/column $h = $newh; } // get current page number $startpage = $this->page; // get current column $startcolumn = $this->current_column; if (!$this->empty_string($x)) { $this->SetX($x); } else { $x = $this->GetX(); } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions(0, $x, $y); // apply margins $oy = $y + $mc_margin['T']; if ($this->rtl) { $ox = $this->w - $x - $mc_margin['R']; } else { $ox = $x + $mc_margin['L']; } $this->x = $ox; $this->y = $oy; // set width if ($this->empty_string($w) OR ($w <= 0)) { if ($this->rtl) { $w = $this->x - $this->lMargin - $mc_margin['L']; } else { $w = $this->w - $this->x - $this->rMargin - $mc_margin['R']; } } // store original margin values $lMargin = $this->lMargin; $rMargin = $this->rMargin; if ($this->rtl) { $this->rMargin = $this->w - $this->x; $this->lMargin = $this->x - $w; } else { $this->lMargin = $this->x; $this->rMargin = $this->w - $this->x - $w; } if ($autopadding) { // add top padding $this->y += $mc_padding['T']; } if ($ishtml) { // ******* Write HTML text $this->writeHTML($txt, true, false, $reseth, true, $align); $nl = 1; } else { // ******* Write simple text $prev_FontSizePt = $this->FontSizePt; // vertical alignment if ($maxh > 0) { // get text height $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border); if ($fitcell) { // try to reduce font size to fit text on cell (use a quick search algorithm) $fmin = 1; $fmax = $this->FontSizePt; $prev_text_height = $text_height; $maxit = 100; // max number of iterations while ($maxit > 0) { $fmid = (($fmax + $fmin) / 2); $this->SetFontSize($fmid, false); $this->resetLastH(); $text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border); if (($text_height == $maxh) OR (($text_height < $maxh) AND ($fmin >= ($fmax - 0.01)))) { break; } elseif ($text_height < $maxh) { $fmin = $fmid; } else { $fmax = $fmid; } --$maxit; } $this->SetFontSize($this->FontSizePt); } if ($text_height < $maxh) { if ($valign == 'M') { // text vertically centered $this->y += (($maxh - $text_height) / 2); } elseif ($valign == 'B') { // text vertically aligned on bottom $this->y += ($maxh - $text_height); } } } $nl = $this->Write($this->lasth, $txt, '', 0, $align, true, $stretch, false, true, $maxh, 0, $mc_margin); if ($fitcell) { // restore font size $this->SetFontSize($prev_FontSizePt); } } if ($autopadding) { // add bottom padding $this->y += $mc_padding['B']; } // Get end-of-text Y position $currentY = $this->y; // get latest page number $endpage = $this->page; if ($resth > 0) { $skip = ($endpage - $startpage); $tmpresth = $resth; while ($tmpresth > 0) { if ($skip <= 0) { // add a page (or trig AcceptPageBreak() for multicolumn mode) $this->checkPageBreak($this->PageBreakTrigger + 1); } if ($this->num_columns > 1) { $tmpresth -= ($this->h - $this->y - $this->bMargin); } else { $tmpresth -= ($this->h - $this->tMargin - $this->bMargin); } --$skip; } $currentY = $this->y; $endpage = $this->page; } // get latest column $endcolumn = $this->current_column; if ($this->num_columns == 0) { $this->num_columns = 1; } // get border modes $border_start = $this->getBorderMode($border, $position='start'); $border_end = $this->getBorderMode($border, $position='end'); $border_middle = $this->getBorderMode($border, $position='middle'); // design borders around HTML cells. for ($page = $startpage; $page <= $endpage; ++$page) { // for each page $ccode = ''; $this->setPage($page); if ($this->num_columns < 2) { // single-column mode $this->SetX($x); $this->y = $this->tMargin; } // account for margin changes if ($page > $startpage) { if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) { $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']); } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) { $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']); } } if ($startpage == $endpage) { // single page for ($column = $startcolumn; $column <= $endcolumn; ++$column) { // for each column $this->selectColumn($column); if ($this->rtl) { $this->x -= $mc_margin['R']; } else { $this->x += $mc_margin['L']; } if ($startcolumn == $endcolumn) { // single column $cborder = $border; $h = max($h, ($currentY - $oy)); $this->y = $oy; } elseif ($column == $startcolumn) { // first column $cborder = $border_start; $this->y = $oy; $h = $this->h - $this->y - $this->bMargin; } elseif ($column == $endcolumn) { // end column $cborder = $border_end; $h = $currentY - $this->y; if ($resth > $h) { $h = $resth; } } else { // middle column $cborder = $border_middle; $h = $this->h - $this->y - $this->bMargin; $resth -= $h; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } elseif ($page == $startpage) { // first page for ($column = $startcolumn; $column < $this->num_columns; ++$column) { // for each column $this->selectColumn($column); if ($this->rtl) { $this->x -= $mc_margin['R']; } else { $this->x += $mc_margin['L']; } if ($column == $startcolumn) { // first column $cborder = $border_start; $this->y = $oy; $h = $this->h - $this->y - $this->bMargin; } else { // middle column $cborder = $border_middle; $h = $this->h - $this->y - $this->bMargin; $resth -= $h; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } elseif ($page == $endpage) { // last page for ($column = 0; $column <= $endcolumn; ++$column) { // for each column $this->selectColumn($column); if ($this->rtl) { $this->x -= $mc_margin['R']; } else { $this->x += $mc_margin['L']; } if ($column == $endcolumn) { // end column $cborder = $border_end; $h = $currentY - $this->y; if ($resth > $h) { $h = $resth; } } else { // middle column $cborder = $border_middle; $h = $this->h - $this->y - $this->bMargin; $resth -= $h; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } else { // middle page for ($column = 0; $column < $this->num_columns; ++$column) { // for each column $this->selectColumn($column); if ($this->rtl) { $this->x -= $mc_margin['R']; } else { $this->x += $mc_margin['L']; } $cborder = $border_middle; $h = $this->h - $this->y - $this->bMargin; $resth -= $h; $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } if ($cborder OR $fill) { $offsetlen = strlen($ccode); // draw border and fill if ($this->inxobj) { // we are inside an XObject template if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) { $pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']); $pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey]; $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen; } else { $pagemark = $this->xobjects[$this->xobjid]['intmrk']; $this->xobjects[$this->xobjid]['intmrk'] += $offsetlen; } $pagebuff = $this->xobjects[$this->xobjid]['outdata']; $pstart = substr($pagebuff, 0, $pagemark); $pend = substr($pagebuff, $pagemark); $this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend; } else { if (end($this->transfmrk[$this->page]) !== false) { $pagemarkkey = key($this->transfmrk[$this->page]); $pagemark = $this->transfmrk[$this->page][$pagemarkkey]; $this->transfmrk[$this->page][$pagemarkkey] += $offsetlen; } elseif ($this->InFooter) { $pagemark = $this->footerpos[$this->page]; $this->footerpos[$this->page] += $offsetlen; } else { $pagemark = $this->intmrk[$this->page]; $this->intmrk[$this->page] += $offsetlen; } $pagebuff = $this->getPageBuffer($this->page); $pstart = substr($pagebuff, 0, $pagemark); $pend = substr($pagebuff, $pagemark); $this->setPageBuffer($this->page, $pstart.$ccode.$pend); } } } // end for each page // Get end-of-cell Y position $currentY = $this->GetY(); // restore previous values if ($this->num_columns > 1) { $this->selectColumn(); } else { // restore original margins $this->lMargin = $lMargin; $this->rMargin = $rMargin; if ($this->page > $startpage) { // check for margin variations between pages (i.e. booklet mode) $dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$startpage]['olm']); $dr = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$startpage]['orm']); if (($dl != 0) OR ($dr != 0)) { $this->lMargin += $dl; $this->rMargin += $dr; } } } if ($ln > 0) { //Go to the beginning of the next line $this->SetY($currentY + $mc_margin['B']); if ($ln == 2) { $this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']); } } else { // go left or right by case $this->setPage($startpage); $this->y = $y; $this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']); } $this->setContentMark(); $this->cell_padding = $prev_cell_padding; $this->cell_margin = $prev_cell_margin; return $nl; } /** * Get the border mode accounting for multicell position (opens bottom side of multicell crossing pages) * @param $brd (mixed) Indicates if borders must be drawn around the cell block. The value can be a number:or a string containing some or all of the following characters (in any order): or an array of line styles for each border group: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $position (string) multicell position: 'start', 'middle', 'end' * @return border mode array * @protected * @since 4.4.002 (2008-12-09) */ protected function getBorderMode($brd, $position='start') { if ((!$this->opencell) OR empty($brd)) { return $brd; } if ($brd == 1) { $brd = 'LTRB'; } if (is_string($brd)) { // convert string to array $slen = strlen($brd); $newbrd = array(); for ($i = 0; $i < $slen; ++$i) { $newbrd[$brd[$i]] = array('cap' => 'square', 'join' => 'miter'); } $brd = $newbrd; } foreach ($brd as $border => $style) { switch ($position) { case 'start': { if (strpos($border, 'B') !== false) { // remove bottom line $newkey = str_replace('B', '', $border); if (strlen($newkey) > 0) { $brd[$newkey] = $style; } unset($brd[$border]); } break; } case 'middle': { if (strpos($border, 'B') !== false) { // remove bottom line $newkey = str_replace('B', '', $border); if (strlen($newkey) > 0) { $brd[$newkey] = $style; } unset($brd[$border]); $border = $newkey; } if (strpos($border, 'T') !== false) { // remove bottom line $newkey = str_replace('T', '', $border); if (strlen($newkey) > 0) { $brd[$newkey] = $style; } unset($brd[$border]); } break; } case 'end': { if (strpos($border, 'T') !== false) { // remove bottom line $newkey = str_replace('T', '', $border); if (strlen($newkey) > 0) { $brd[$newkey] = $style; } unset($brd[$border]); } break; } } } return $brd; } /** * This method return the estimated number of lines for print a simple text string using Multicell() method. * @param $txt (string) String for calculating his height * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page. * @param $reseth (boolean) if true reset the last cell height (default false). * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width (default true). * @param $cellpadding (float) Internal cell padding, if empty uses default cell padding. * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @return float Return the minimal height needed for multicell method for printing the $txt param. * @author Alexander Escalona Fern疣dez, Nicola Asuni * @public * @since 4.5.011 */ public function getNumLines($txt, $w=0, $reseth=false, $autopadding=true, $cellpadding='', $border=0) { if ($txt === '') { // empty string return 1; } // adjust internal padding $prev_cell_padding = $this->cell_padding; $prev_lasth = $this->lasth; if (is_array($cellpadding)) { $this->cell_padding = $cellpadding; } $this->adjustCellPadding($border); if ($this->empty_string($w) OR ($w <= 0)) { if ($this->rtl) { $w = $this->x - $this->lMargin; } else { $w = $this->w - $this->rMargin - $this->x; } } $wmax = $w - $this->cell_padding['L'] - $this->cell_padding['R']; if ($reseth) { // reset row height $this->resetLastH(); } $lines = 1; $sum = 0; $chars = $this->utf8Bidi($this->UTF8StringToArray($txt), $txt, $this->tmprtl); $charsWidth = $this->GetArrStringWidth($chars, '', '', 0, true); $length = count($chars); $lastSeparator = -1; for ($i = 0; $i < $length; ++$i) { $charWidth = $charsWidth[$i]; if (preg_match($this->re_spaces, $this->unichr($chars[$i]))) { $lastSeparator = $i; } if ((($sum + $charWidth) > $wmax) OR ($chars[$i] == 10)) { ++$lines; if ($chars[$i] == 10) { $lastSeparator = -1; $sum = 0; } elseif ($lastSeparator != -1) { $i = $lastSeparator; $lastSeparator = -1; $sum = 0; } else { $sum = $charWidth; } } else { $sum += $charWidth; } } if ($chars[($length - 1)] == 10) { --$lines; } $this->cell_padding = $prev_cell_padding; $this->lasth = $prev_lasth; return $lines; } /** * This method return the estimated height needed for printing a simple text string using the Multicell() method. * Generally, if you want to know the exact height for a block of content you can use the following alternative technique: * @pre * // store current object * $pdf->startTransaction(); * // store starting values * $start_y = $pdf->GetY(); * $start_page = $pdf->getPage(); * // call your printing functions with your parameters * // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * $pdf->MultiCell($w=0, $h=0, $txt, $border=1, $align='L', $fill=false, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0); * // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * // get the new Y * $end_y = $pdf->GetY(); * $end_page = $pdf->getPage(); * // calculate height * $height = 0; * if ($end_page == $start_page) { * $height = $end_y - $start_y; * } else { * for ($page=$start_page; $page <= $end_page; ++$page) { * $this->setPage($page); * if ($page == $start_page) { * // first page * $height = $this->h - $start_y - $this->bMargin; * } elseif ($page == $end_page) { * // last page * $height = $end_y - $this->tMargin; * } else { * $height = $this->h - $this->tMargin - $this->bMargin; * } * } * } * // restore previous object * $pdf = $pdf->rollbackTransaction(); * * @param $w (float) Width of cells. If 0, they extend up to the right margin of the page. * @param $txt (string) String for calculating his height * @param $reseth (boolean) if true reset the last cell height (default false). * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width (default true). * @param $cellpadding (float) Internal cell padding, if empty uses default cell padding. * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @return float Return the minimal height needed for multicell method for printing the $txt param. * @author Nicola Asuni, Alexander Escalona Fern疣dez * @public */ public function getStringHeight($w, $txt, $reseth=false, $autopadding=true, $cellpadding='', $border=0) { // adjust internal padding $prev_cell_padding = $this->cell_padding; $prev_lasth = $this->lasth; if (is_array($cellpadding)) { $this->cell_padding = $cellpadding; } $this->adjustCellPadding($border); $lines = $this->getNumLines($txt, $w, $reseth, $autopadding, $cellpadding, $border); $height = $lines * ($this->FontSize * $this->cell_height_ratio); if ($autopadding) { // add top and bottom padding $height += ($this->cell_padding['T'] + $this->cell_padding['B']); } $this->cell_padding = $prev_cell_padding; $this->lasth = $prev_lasth; return $height; } /** * This method prints text from the current position.
    * @param $h (float) Line height * @param $txt (string) String to print * @param $link (mixed) URL or identifier returned by AddLink() * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). * @param $align (string) Allows to center or align the text. Possible values are: * @param $ln (boolean) if true set cursor at the bottom of the line, otherwise set cursor at the top of the line. * @param $stretch (int) font stretch mode: General font stretching and scaling values will be preserved when possible. * @param $firstline (boolean) if true prints only the first line and return the remaining string. * @param $firstblock (boolean) if true the string is the starting of a line. * @param $maxh (float) maximum height. The remaining unprinted text will be returned. It should be >= $h and less then remaining space to the bottom of the page, or 0 for disable this feature. * @param $wadj (float) first line width will be reduced by this amount (used in HTML mode). * @param $margin (array) margin array of the parent container * @return mixed Return the number of cells or the remaining string if $firstline = true. * @public * @since 1.5 */ public function Write($h, $txt, $link='', $fill=false, $align='', $ln=false, $stretch=0, $firstline=false, $firstblock=false, $maxh=0, $wadj=0, $margin='') { // check page for no-write regions and adapt page margins if necessary list($this->x, $this->y) = $this->checkPageRegions($h, $this->x, $this->y); if (strlen($txt) == 0) { // fix empty text $txt = ' '; } if ($margin === '') { // set default margins $margin = $this->cell_margin; } // remove carriage returns $s = str_replace("\r", '', $txt); // check if string contains arabic text if (preg_match($this->unicode->uni_RE_PATTERN_ARABIC, $s)) { $arabic = true; } else { $arabic = false; } // check if string contains RTL text if ($arabic OR ($this->tmprtl == 'R') OR preg_match($this->unicode->uni_RE_PATTERN_RTL, $s)) { $rtlmode = true; } else { $rtlmode = false; } // get a char width $chrwidth = $this->GetCharWidth(46); // dot character // get array of unicode values $chars = $this->UTF8StringToArray($s); // get array of chars $uchars = $this->UTF8ArrayToUniArray($chars); // get the number of characters $nb = count($chars); // replacement for SHY character (minus symbol) $shy_replacement = 45; $shy_replacement_char = $this->unichr($shy_replacement); // widht for SHY replacement $shy_replacement_width = $this->GetCharWidth($shy_replacement); // max Y $maxy = $this->y + $maxh - $h - $this->cell_padding['T'] - $this->cell_padding['B']; // page width $pw = $w = $this->w - $this->lMargin - $this->rMargin; // calculate remaining line width ($w) if ($this->rtl) { $w = $this->x - $this->lMargin; } else { $w = $this->w - $this->rMargin - $this->x; } // max column width $wmax = $w - $wadj; if (!$firstline) { $wmax -= ($this->cell_padding['L'] + $this->cell_padding['R']); } if ((!$firstline) AND (($chrwidth > $wmax) OR ($this->GetCharWidth($chars[0]) > $wmax))) { // a single character do not fit on column return ''; } // minimum row height $row_height = max($h, $this->FontSize * $this->cell_height_ratio); $start_page = $this->page; $i = 0; // character position $j = 0; // current starting position $sep = -1; // position of the last blank space $shy = false; // true if the last blank is a soft hypen (SHY) $l = 0; // current string length $nl = 0; //number of lines $linebreak = false; $pc = 0; // previous character // for each character while ($i < $nb) { if (($maxh > 0) AND ($this->y >= $maxy) ) { break; } //Get the current character $c = $chars[$i]; if ($c == 10) { // 10 = "\n" = new line //Explicit line break if ($align == 'J') { if ($this->rtl) { $talign = 'R'; } else { $talign = 'L'; } } else { $talign = $align; } $tmpstr = $this->UniArrSubString($uchars, $j, $i); if ($firstline) { $startx = $this->x; $tmparr = array_slice($chars, $j, ($i - $j)); if ($rtlmode) { $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl); } $linew = $this->GetArrStringWidth($tmparr); unset($tmparr); if ($this->rtl) { $this->endlinex = $startx - $linew; } else { $this->endlinex = $startx + $linew; } $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { $this->SetCellPadding(0); } } if ($firstblock AND $this->isRTLTextDir()) { $tmpstr = $this->stringRightTrim($tmpstr); } // Skip newlines at the begining of a page or column if (!empty($tmpstr) OR ($this->y < ($this->PageBreakTrigger - $row_height))) { $this->Cell($w, $h, $tmpstr, 0, 1, $talign, $fill, $link, $stretch); } unset($tmpstr); if ($firstline) { $this->cell_padding = $tmpcellpadding; return ($this->UniArrSubString($uchars, $i)); } ++$nl; $j = $i + 1; $l = 0; $sep = -1; $shy = false; // account for margin changes if ((($this->y + $this->lasth) > $this->PageBreakTrigger) AND ($this->inPageBody())) { $this->AcceptPageBreak(); if ($this->rtl) { $this->x -= $margin['R']; } else { $this->x += $margin['L']; } $this->lMargin += $margin['L']; $this->rMargin += $margin['R']; } $w = $this->getRemainingWidth(); $wmax = $w - $this->cell_padding['L'] - $this->cell_padding['R']; } else { // 160 is the non-breaking space. // 173 is SHY (Soft Hypen). // \p{Z} or \p{Separator}: any kind of Unicode whitespace or invisible separator. // \p{Lo} or \p{Other_Letter}: a Unicode letter or ideograph that does not have lowercase and uppercase variants. // \p{Lo} is needed because Chinese characters are packed next to each other without spaces in between. if (($c != 160) AND (($c == 173) OR preg_match($this->re_spaces, $this->unichr($c)))) { // update last blank space position $sep = $i; // check if is a SHY if ($c == 173) { $shy = true; if ($pc == 45) { $tmp_shy_replacement_width = 0; $tmp_shy_replacement_char = ''; } else { $tmp_shy_replacement_width = $shy_replacement_width; $tmp_shy_replacement_char = $shy_replacement_char; } } else { $shy = false; } } // update string length if ($this->isUnicodeFont() AND ($arabic)) { // with bidirectional algorithm some chars may be changed affecting the line length // *** very slow *** $l = $this->GetArrStringWidth($this->utf8Bidi(array_slice($chars, $j, ($i - $j)), '', $this->tmprtl)); } else { $l += $this->GetCharWidth($c); } if (($l > $wmax) OR (($c == 173) AND (($l + $tmp_shy_replacement_width) > $wmax)) ) { // we have reached the end of column if ($sep == -1) { // check if the line was already started if (($this->rtl AND ($this->x <= ($this->w - $this->rMargin - $chrwidth))) OR ((!$this->rtl) AND ($this->x >= ($this->lMargin + $chrwidth)))) { // print a void cell and go to next line $this->Cell($w, $h, '', 0, 1); $linebreak = true; if ($firstline) { return ($this->UniArrSubString($uchars, $j)); } } else { // truncate the word because do not fit on column $tmpstr = $this->UniArrSubString($uchars, $j, $i); if ($firstline) { $startx = $this->x; $tmparr = array_slice($chars, $j, ($i - $j)); if ($rtlmode) { $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl); } $linew = $this->GetArrStringWidth($tmparr); unset($tmparr); if ($this->rtl) { $this->endlinex = $startx - $linew; } else { $this->endlinex = $startx + $linew; } $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { $this->SetCellPadding(0); } } if ($firstblock AND $this->isRTLTextDir()) { $tmpstr = $this->stringRightTrim($tmpstr); } $this->Cell($w, $h, $tmpstr, 0, 1, $align, $fill, $link, $stretch); unset($tmpstr); if ($firstline) { $this->cell_padding = $tmpcellpadding; return ($this->UniArrSubString($uchars, $i)); } $j = $i; --$i; } } else { // word wrapping if ($this->rtl AND (!$firstblock) AND ($sep < $i)) { $endspace = 1; } else { $endspace = 0; } // check the length of the next string $strrest = $this->UniArrSubString($uchars, ($sep + $endspace)); $nextstr = preg_split('/'.$this->re_space['p'].'/'.$this->re_space['m'], $this->stringTrim($strrest)); if (isset($nextstr[0]) AND ($this->GetStringWidth($nextstr[0]) > $pw)) { // truncate the word because do not fit on a full page width $tmpstr = $this->UniArrSubString($uchars, $j, $i); if ($firstline) { $startx = $this->x; $tmparr = array_slice($chars, $j, ($i - $j)); if ($rtlmode) { $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl); } $linew = $this->GetArrStringWidth($tmparr); unset($tmparr); if ($this->rtl) { $this->endlinex = $startx - $linew; } else { $this->endlinex = $startx + $linew; } $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { $this->SetCellPadding(0); } } if ($firstblock AND $this->isRTLTextDir()) { $tmpstr = $this->stringRightTrim($tmpstr); } $this->Cell($w, $h, $tmpstr, 0, 1, $align, $fill, $link, $stretch); unset($tmpstr); if ($firstline) { $this->cell_padding = $tmpcellpadding; return ($this->UniArrSubString($uchars, $i)); } $j = $i; --$i; } else { // word wrapping if ($shy) { // add hypen (minus symbol) at the end of the line $shy_width = $tmp_shy_replacement_width; if ($this->rtl) { $shy_char_left = $tmp_shy_replacement_char; $shy_char_right = ''; } else { $shy_char_left = ''; $shy_char_right = $tmp_shy_replacement_char; } } else { $shy_width = 0; $shy_char_left = ''; $shy_char_right = ''; } $tmpstr = $this->UniArrSubString($uchars, $j, ($sep + $endspace)); if ($firstline) { $startx = $this->x; $tmparr = array_slice($chars, $j, (($sep + $endspace) - $j)); if ($rtlmode) { $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl); } $linew = $this->GetArrStringWidth($tmparr); unset($tmparr); if ($this->rtl) { $this->endlinex = $startx - $linew - $shy_width; } else { $this->endlinex = $startx + $linew + $shy_width; } $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { $this->SetCellPadding(0); } } // print the line if ($firstblock AND $this->isRTLTextDir()) { $tmpstr = $this->stringRightTrim($tmpstr); } $this->Cell($w, $h, $shy_char_left.$tmpstr.$shy_char_right, 0, 1, $align, $fill, $link, $stretch); unset($tmpstr); if ($firstline) { // return the remaining text $this->cell_padding = $tmpcellpadding; return ($this->UniArrSubString($uchars, ($sep + $endspace))); } $i = $sep; $sep = -1; $shy = false; $j = ($i+1); } } // account for margin changes if ((($this->y + $this->lasth) > $this->PageBreakTrigger) AND ($this->inPageBody())) { $this->AcceptPageBreak(); if ($this->rtl) { $this->x -= $margin['R']; } else { $this->x += $margin['L']; } $this->lMargin += $margin['L']; $this->rMargin += $margin['R']; } $w = $this->getRemainingWidth(); $wmax = $w - $this->cell_padding['L'] - $this->cell_padding['R']; if ($linebreak) { $linebreak = false; } else { ++$nl; $l = 0; } } } // save last character $pc = $c; ++$i; } // end while i < nb // print last substring (if any) if ($l > 0) { switch ($align) { case 'J': case 'C': { $w = $w; break; } case 'L': { if ($this->rtl) { $w = $w; } else { $w = $l; } break; } case 'R': { if ($this->rtl) { $w = $l; } else { $w = $w; } break; } default: { $w = $l; break; } } $tmpstr = $this->UniArrSubString($uchars, $j, $nb); if ($firstline) { $startx = $this->x; $tmparr = array_slice($chars, $j, ($nb - $j)); if ($rtlmode) { $tmparr = $this->utf8Bidi($tmparr, $tmpstr, $this->tmprtl); } $linew = $this->GetArrStringWidth($tmparr); unset($tmparr); if ($this->rtl) { $this->endlinex = $startx - $linew; } else { $this->endlinex = $startx + $linew; } $w = $linew; $tmpcellpadding = $this->cell_padding; if ($maxh == 0) { $this->SetCellPadding(0); } } if ($firstblock AND $this->isRTLTextDir()) { $tmpstr = $this->stringRightTrim($tmpstr); } $this->Cell($w, $h, $tmpstr, 0, $ln, $align, $fill, $link, $stretch); unset($tmpstr); if ($firstline) { $this->cell_padding = $tmpcellpadding; return ($this->UniArrSubString($uchars, $nb)); } ++$nl; } if ($firstline) { return ''; } return $nl; } /** * Returns the remaining width between the current position and margins. * @return int Return the remaining width * @protected */ protected function getRemainingWidth() { list($this->x, $this->y) = $this->checkPageRegions(0, $this->x, $this->y); if ($this->rtl) { return ($this->x - $this->lMargin); } else { return ($this->w - $this->rMargin - $this->x); } } /** * Extract a slice of the $strarr array and return it as string. * @param $strarr (string) The input array of characters. * @param $start (int) the starting element of $strarr. * @param $end (int) first element that will not be returned. * @return Return part of a string * @public */ public function UTF8ArrSubString($strarr, $start='', $end='') { if (strlen($start) == 0) { $start = 0; } if (strlen($end) == 0) { $end = count($strarr); } $string = ''; for ($i=$start; $i < $end; ++$i) { $string .= $this->unichr($strarr[$i]); } return $string; } /** * Extract a slice of the $uniarr array and return it as string. * @param $uniarr (string) The input array of characters. * @param $start (int) the starting element of $strarr. * @param $end (int) first element that will not be returned. * @return Return part of a string * @public * @since 4.5.037 (2009-04-07) */ public function UniArrSubString($uniarr, $start='', $end='') { if (strlen($start) == 0) { $start = 0; } if (strlen($end) == 0) { $end = count($uniarr); } $string = ''; for ($i=$start; $i < $end; ++$i) { $string .= $uniarr[$i]; } return $string; } /** * Convert an array of UTF8 values to array of unicode characters * @param $ta (string) The input array of UTF8 values. * @return Return array of unicode characters * @public * @since 4.5.037 (2009-04-07) */ public function UTF8ArrayToUniArray($ta) { return array_map(array($this, 'unichr'), $ta); } /** * Returns the unicode caracter specified by UTF-8 value * @param $c (int) UTF-8 value * @return Returns the specified character. * @author Miguel Perez, Nicola Asuni * @public * @since 2.3.000 (2008-03-05) */ public function unichr($c) { if (!$this->isunicode) { return chr($c); } elseif ($c <= 0x7F) { // one byte return chr($c); } elseif ($c <= 0x7FF) { // two bytes return chr(0xC0 | $c >> 6).chr(0x80 | $c & 0x3F); } elseif ($c <= 0xFFFF) { // three bytes return chr(0xE0 | $c >> 12).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); } elseif ($c <= 0x10FFFF) { // four bytes return chr(0xF0 | $c >> 18).chr(0x80 | $c >> 12 & 0x3F).chr(0x80 | $c >> 6 & 0x3F).chr(0x80 | $c & 0x3F); } else { return ''; } } /** * Return the image type given the file name or array returned by getimagesize() function. * @param $imgfile (string) image file name * @param $iminfo (array) array of image information returned by getimagesize() function. * @return string image type * @since 4.8.017 (2009-11-27) */ public function getImageFileType($imgfile, $iminfo=array()) { $type = ''; if (isset($iminfo['mime']) AND !empty($iminfo['mime'])) { $mime = explode('/', $iminfo['mime']); if ((count($mime) > 1) AND ($mime[0] == 'image') AND (!empty($mime[1]))) { $type = strtolower(trim($mime[1])); } } if (empty($type)) { $fileinfo = pathinfo($imgfile); if (isset($fileinfo['extension']) AND (!$this->empty_string($fileinfo['extension']))) { $type = strtolower(trim($fileinfo['extension'])); } } if ($type == 'jpg') { $type = 'jpeg'; } return $type; } /** * Set the block dimensions accounting for page breaks and page/column fitting * @param $w (float) width * @param $h (float) height * @param $x (float) X coordinate * @param $y (float) Y coodiante * @param $fitonpage (boolean) if true the block is resized to not exceed page dimensions. * @return array($w, $h, $x, $y) * @protected * @since 5.5.009 (2010-07-05) */ protected function fitBlock($w, $h, $x, $y, $fitonpage=false) { if ($w <= 0) { // set maximum width $w = ($this->w - $this->lMargin - $this->rMargin); } if ($h <= 0) { // set maximum height $h = ($this->PageBreakTrigger - $this->tMargin); } // resize the block to be vertically contained on a single page or single column if ($fitonpage OR $this->AutoPageBreak) { $ratio_wh = ($w / $h); if ($h > ($this->PageBreakTrigger - $this->tMargin)) { $h = $this->PageBreakTrigger - $this->tMargin; $w = ($h * $ratio_wh); } // resize the block to be horizontally contained on a single page or single column if ($fitonpage) { $maxw = ($this->w - $this->lMargin - $this->rMargin); if ($w > $maxw) { $w = $maxw; $h = ($w / $ratio_wh); } } } // Check whether we need a new page or new column first as this does not fit $prev_x = $this->x; $prev_y = $this->y; if ($this->checkPageBreak($h, $y) OR ($this->y < $prev_y)) { $y = $this->y; if ($this->rtl) { $x += ($prev_x - $this->x); } else { $x += ($this->x - $prev_x); } $this->newline = true; } // resize the block to be contained on the remaining available page or column space if ($fitonpage) { $ratio_wh = ($w / $h); if (($y + $h) > $this->PageBreakTrigger) { $h = $this->PageBreakTrigger - $y; $w = ($h * $ratio_wh); } if ((!$this->rtl) AND (($x + $w) > ($this->w - $this->rMargin))) { $w = $this->w - $this->rMargin - $x; $h = ($w / $ratio_wh); } elseif (($this->rtl) AND (($x - $w) < ($this->lMargin))) { $w = $x - $this->lMargin; $h = ($w / $ratio_wh); } } return array($w, $h, $x, $y); } /** * Puts an image in the page. * The upper-left corner must be given. * The dimensions can be specified in different ways: * Supported formats are JPEG and PNG images whitout GD library and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM; * The format can be specified explicitly or inferred from the file extension.
    * It is possible to put a link on the image.
    * Remark: if an image is used several times, only one copy will be embedded in the file.
    * @param $file (string) Name of the file containing the image or a '@' character followed by the image data string. To link an image without embedding it on the document, set an asterisk character before the URL (i.e.: '*http://www.example.com/image.jpg'). * @param $x (float) Abscissa of the upper-left corner (LTR) or upper-right corner (RTL). * @param $y (float) Ordinate of the upper-left corner (LTR) or upper-right corner (RTL). * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated. * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated. * @param $type (string) Image format. Possible values are (case insensitive): JPEG and PNG (whitout GD library) and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;. If not specified, the type is inferred from the file extension. * @param $link (mixed) URL or identifier returned by AddLink(). * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be: * @param $resize (mixed) If true resize (reduce) the image to fit $w and $h (requires GD or ImageMagick library); if false do not resize; if 2 force resize in all cases (upscaling and downscaling). * @param $dpi (int) dot-per-inch resolution used on resize * @param $palign (string) Allows to center or align the image on the current line. Possible values are: * @param $ismask (boolean) true if this image is a mask, false otherwise * @param $imgmask (mixed) image object returned by this function or false * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number: or a string containing some or all of the following characters (in any order): or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $fitbox (mixed) If not false scale image dimensions proportionally to fit within the ($w, $h) box. $fitbox can be true or a 2 characters string indicating the image alignment inside the box. The first character indicate the horizontal alignment (L = left, C = center, R = right) the second character indicate the vertical algnment (T = top, M = middle, B = bottom). * @param $hidden (boolean) If true do not display the image. * @param $fitonpage (boolean) If true the image is resized to not exceed page dimensions. * @param $alt (boolean) If true the image will be added as alternative and not directly printed (the ID of the image will be returned). * @param $altimgs (array) Array of alternate images IDs. Each alternative image must be an array with two values: an integer representing the image ID (the value returned by the Image method) and a boolean value to indicate if the image is the default for printing. * @return image information * @public * @since 1.1 */ public function Image($file, $x='', $y='', $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0, $fitbox=false, $hidden=false, $fitonpage=false, $alt=false, $altimgs=array()) { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); $cached_file = false; // true when the file is cached $exurl = ''; // external streams // check if we are passing an image as file or string if ($file[0] === '@') { // image from string $imgdata = substr($file, 1); $file = K_PATH_CACHE.'img_'.md5($imgdata); $fp = fopen($file, 'w'); fwrite($fp, $imgdata); fclose($fp); unset($imgdata); $cached_file = true; $imsize = @getimagesize($file); if ($imsize === FALSE) { unlink($file); $cached_file = false; } } else { // image file if ($file{0} === '*') { // image as external stream $file = substr($file, 1); $exurl = $file; } // check if is local file if (!@$this->file_exists($file)) { // encode spaces on filename (file is probably an URL) $file = str_replace(' ', '%20', $file); } if (@$this->file_exists($file)) { // get image dimensions $imsize = @getimagesize($file); } else { $imsize = false; } if ($imsize === FALSE) { if (function_exists('curl_init')) { // try to get remote file data using cURL $cs = curl_init(); // curl session curl_setopt($cs, CURLOPT_URL, $file); curl_setopt($cs, CURLOPT_BINARYTRANSFER, true); curl_setopt($cs, CURLOPT_FAILONERROR, true); curl_setopt($cs, CURLOPT_RETURNTRANSFER, true); // Modified by redcocker This code is provided by Michael Starke //curl_setopt($cs, CURLOPT_FOLLOWLOCATION, true); if(!ini_get("open_basedir")) { curl_setopt($cs, CURLOPT_FOLLOWLOCATION, true); } curl_setopt($cs, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($cs, CURLOPT_TIMEOUT, 30); curl_setopt($cs, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($cs, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($cs, CURLOPT_USERAGENT, 'TCPDF'); $imgdata = curl_exec($cs); curl_close($cs); if ($imgdata !== FALSE) { // copy image to cache $file = K_PATH_CACHE.'img_'.md5($imgdata); $fp = fopen($file, 'w'); fwrite($fp, $imgdata); fclose($fp); unset($imgdata); $cached_file = true; $imsize = @getimagesize($file); if ($imsize === FALSE) { unlink($file); $cached_file = false; } } } elseif (($w > 0) AND ($h > 0)) { // get measures from specified data $pw = $this->getHTMLUnitToUnits($w, 0, $this->pdfunit, true) * $this->imgscale * $this->k; $ph = $this->getHTMLUnitToUnits($h, 0, $this->pdfunit, true) * $this->imgscale * $this->k; $imsize = array($pw, $ph); } } } if ($imsize === FALSE) { if (substr($file, 0, -34) == K_PATH_CACHE.'msk') { // mask file // get measures from specified data $pw = $this->getHTMLUnitToUnits($w, 0, $this->pdfunit, true) * $this->imgscale * $this->k; $ph = $this->getHTMLUnitToUnits($h, 0, $this->pdfunit, true) * $this->imgscale * $this->k; $imsize = array($pw, $ph); } else { $this->Error('[Image] Unable to get image: '.$file); } } // file hash $filehash = md5($file); // get original image width and height in pixels list($pixw, $pixh) = $imsize; // calculate image width and height on document if (($w <= 0) AND ($h <= 0)) { // convert image size to document unit $w = $this->pixelsToUnits($pixw); $h = $this->pixelsToUnits($pixh); } elseif ($w <= 0) { $w = $h * $pixw / $pixh; } elseif ($h <= 0) { $h = $w * $pixh / $pixw; } elseif (($fitbox !== false) AND ($w > 0) AND ($h > 0)) { if (strlen($fitbox) !== 2) { // set default alignment $fitbox = '--'; } // scale image dimensions proportionally to fit within the ($w, $h) box if ((($w * $pixh) / ($h * $pixw)) < 1) { // store current height $oldh = $h; // calculate new height $h = $w * $pixh / $pixw; // height difference $hdiff = ($oldh - $h); // vertical alignment switch (strtoupper($fitbox{1})) { case 'T': { break; } case 'M': { $y += ($hdiff / 2); break; } case 'B': { $y += $hdiff; break; } } } else { // store current width $oldw = $w; // calculate new width $w = $h * $pixw / $pixh; // width difference $wdiff = ($oldw - $w); // horizontal alignment switch (strtoupper($fitbox{0})) { case 'L': { if ($this->rtl) { $x -= $wdiff; } break; } case 'C': { if ($this->rtl) { $x -= ($wdiff / 2); } else { $x += ($wdiff / 2); } break; } case 'R': { if (!$this->rtl) { $x += $wdiff; } break; } } } } // fit the image on available space list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage); // calculate new minimum dimensions in pixels $neww = round($w * $this->k * $dpi / $this->dpi); $newh = round($h * $this->k * $dpi / $this->dpi); // check if resize is necessary (resize is used only to reduce the image) $newsize = ($neww * $newh); $pixsize = ($pixw * $pixh); if (intval($resize) == 2) { $resize = true; } elseif ($newsize >= $pixsize) { $resize = false; } // check if image has been already added on document $newimage = true; if (in_array($file, $this->imagekeys)) { $newimage = false; // get existing image data $info = $this->getImageBuffer($file); if (substr($file, 0, -34) != K_PATH_CACHE.'msk') { // check if the newer image is larger $oldsize = ($info['w'] * $info['h']); if ((($oldsize < $newsize) AND ($resize)) OR (($oldsize < $pixsize) AND (!$resize))) { $newimage = true; } } } elseif (substr($file, 0, -34) != K_PATH_CACHE.'msk') { // check for cached images with alpha channel $tempfile_plain = K_PATH_CACHE.'mskp_'.$filehash; $tempfile_alpha = K_PATH_CACHE.'mska_'.$filehash; if (in_array($tempfile_plain, $this->imagekeys)) { // get existing image data $info = $this->getImageBuffer($tempfile_plain); // check if the newer image is larger $oldsize = ($info['w'] * $info['h']); if ((($oldsize < $newsize) AND ($resize)) OR (($oldsize < $pixsize) AND (!$resize))) { $newimage = true; } else { $newimage = false; // embed mask image $imgmask = $this->Image($tempfile_alpha, $x, $y, $w, $h, 'PNG', '', '', $resize, $dpi, '', true, false); // embed image, masked with previously embedded mask return $this->Image($tempfile_plain, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, false, $imgmask); } } } if ($newimage) { //First use of image, get info $type = strtolower($type); if ($type == '') { $type = $this->getImageFileType($file, $imsize); } elseif ($type == 'jpg') { $type = 'jpeg'; } $mqr = $this->get_mqr(); $this->set_mqr(false); // Specific image handlers $mtd = '_parse'.$type; // GD image handler function $gdfunction = 'imagecreatefrom'.$type; $info = false; if ((method_exists($this, $mtd)) AND (!($resize AND (function_exists($gdfunction) OR extension_loaded('imagick'))))) { // TCPDF image functions $info = $this->$mtd($file); if ($info == 'pngalpha') { return $this->ImagePngAlpha($file, $x, $y, $pixw, $pixh, $w, $h, 'PNG', $link, $align, $resize, $dpi, $palign, $filehash); } } if (!$info) { if (function_exists($gdfunction)) { // GD library $img = $gdfunction($file); if ($resize) { $imgr = imagecreatetruecolor($neww, $newh); if (($type == 'gif') OR ($type == 'png')) { $imgr = $this->_setGDImageTransparency($imgr, $img); } imagecopyresampled($imgr, $img, 0, 0, 0, 0, $neww, $newh, $pixw, $pixh); if (($type == 'gif') OR ($type == 'png')) { $info = $this->_toPNG($imgr); } else { $info = $this->_toJPEG($imgr); } } else { if (($type == 'gif') OR ($type == 'png')) { $info = $this->_toPNG($img); } else { $info = $this->_toJPEG($img); } } } elseif (extension_loaded('imagick')) { // ImageMagick library $img = new Imagick(); if ($type == 'SVG') { // get SVG file content $svgimg = file_get_contents($file); // get width and height $regs = array(); if (preg_match('/]*)>/si', $svgimg, $regs)) { $svgtag = $regs[1]; $tmp = array(); if (preg_match('/[\s]+width[\s]*=[\s]*"([^"]*)"/si', $svgtag, $tmp)) { $ow = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false); $owu = sprintf('%.3F', ($ow * $dpi / 72)).$this->pdfunit; $svgtag = preg_replace('/[\s]+width[\s]*=[\s]*"[^"]*"/si', ' width="'.$owu.'"', $svgtag, 1); } else { $ow = $w; } $tmp = array(); if (preg_match('/[\s]+height[\s]*=[\s]*"([^"]*)"/si', $svgtag, $tmp)) { $oh = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false); $ohu = sprintf('%.3F', ($oh * $dpi / 72)).$this->pdfunit; $svgtag = preg_replace('/[\s]+height[\s]*=[\s]*"[^"]*"/si', ' height="'.$ohu.'"', $svgtag, 1); } else { $oh = $h; } $tmp = array(); if (!preg_match('/[\s]+viewBox[\s]*=[\s]*"[\s]*([0-9\.]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]*"/si', $svgtag, $tmp)) { $vbw = ($ow * $this->imgscale * $this->k); $vbh = ($oh * $this->imgscale * $this->k); $vbox = sprintf(' viewBox="0 0 %.3F %.3F" ', $vbw, $vbh); $svgtag = $vbox.$svgtag; } $svgimg = preg_replace('/]*)>/si', '', $svgimg, 1); } $img->readImageBlob($svgimg); } else { $img->readImage($file); } if ($resize) { $img->resizeImage($neww, $newh, 10, 1, false); } $img->setCompressionQuality($this->jpeg_quality); $img->setImageFormat('jpeg'); $tempname = tempnam(K_PATH_CACHE, 'jpg_'); $img->writeImage($tempname); $info = $this->_parsejpeg($tempname); unlink($tempname); $img->destroy(); } else { return; } } if ($info === false) { //If false, we cannot process image return; } $this->set_mqr($mqr); if ($ismask) { // force grayscale $info['cs'] = 'DeviceGray'; } $info['i'] = $this->numimages; if (!in_array($file, $this->imagekeys)) { ++$info['i']; } if ($imgmask !== false) { $info['masked'] = $imgmask; } if (!empty($exurl)) { $info['exurl'] = $exurl; } // array of alternative images $info['altimgs'] = $altimgs; // add image to document $this->setImageBuffer($file, $info); } if ($cached_file) { // remove cached file unlink($file); } // set alignment $this->img_rb_y = $y + $h; // set alignment if ($this->rtl) { if ($palign == 'L') { $ximg = $this->lMargin; } elseif ($palign == 'C') { $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($palign == 'R') { $ximg = $this->w - $this->rMargin - $w; } else { $ximg = $x - $w; } $this->img_rb_x = $ximg; } else { if ($palign == 'L') { $ximg = $this->lMargin; } elseif ($palign == 'C') { $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($palign == 'R') { $ximg = $this->w - $this->rMargin - $w; } else { $ximg = $x; } $this->img_rb_x = $ximg + $w; } if ($ismask OR $hidden) { // image is not displayed return $info['i']; } $xkimg = $ximg * $this->k; if (!$alt) { // only non-alternative immages will be set $this->_out(sprintf('q %.2F 0 0 %.2F %.2F %.2F cm /I%u Do Q', ($w * $this->k), ($h * $this->k), $xkimg, (($this->h - ($y + $h)) * $this->k), $info['i'])); } if (!empty($border)) { $bx = $this->x; $by = $this->y; $this->x = $ximg; if ($this->rtl) { $this->x += $w; } $this->y = $y; $this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true); $this->x = $bx; $this->y = $by; } if ($link) { $this->Link($ximg, $y, $w, $h, $link, 0); } // set pointer to align the next text/objects switch($align) { case 'T': { $this->y = $y; $this->x = $this->img_rb_x; break; } case 'M': { $this->y = $y + round($h/2); $this->x = $this->img_rb_x; break; } case 'B': { $this->y = $this->img_rb_y; $this->x = $this->img_rb_x; break; } case 'N': { $this->SetY($this->img_rb_y); break; } default:{ break; } } $this->endlinex = $this->img_rb_x; if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['images'][] = $info['i']; } return $info['i']; } /** * Sets the current active configuration setting of magic_quotes_runtime (if the set_magic_quotes_runtime function exist) * @param $mqr (boolean) FALSE for off, TRUE for on. * @since 4.6.025 (2009-08-17) */ public function set_mqr($mqr) { if (!defined('PHP_VERSION_ID')) { $version = PHP_VERSION; define('PHP_VERSION_ID', (($version{0} * 10000) + ($version{2} * 100) + $version{4})); } if (PHP_VERSION_ID < 50300) { @set_magic_quotes_runtime($mqr); } } /** * Gets the current active configuration setting of magic_quotes_runtime (if the get_magic_quotes_runtime function exist) * @return Returns 0 if magic quotes runtime is off or get_magic_quotes_runtime doesn't exist, 1 otherwise. * @since 4.6.025 (2009-08-17) */ public function get_mqr() { if (!defined('PHP_VERSION_ID')) { $version = PHP_VERSION; define('PHP_VERSION_ID', (($version{0} * 10000) + ($version{2} * 100) + $version{4})); } if (PHP_VERSION_ID < 50300) { return @get_magic_quotes_runtime(); } return 0; } /** * Convert the loaded image to a JPEG and then return a structure for the PDF creator. * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant. * @param $image (image) Image object. * return image JPEG image object. * @protected */ protected function _toJPEG($image) { $tempname = tempnam(K_PATH_CACHE, 'jpg_'); imagejpeg($image, $tempname, $this->jpeg_quality); imagedestroy($image); $retvars = $this->_parsejpeg($tempname); // tidy up by removing temporary image unlink($tempname); return $retvars; } /** * Convert the loaded image to a PNG and then return a structure for the PDF creator. * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant. * @param $image (image) Image object. * return image PNG image object. * @protected * @since 4.9.016 (2010-04-20) */ protected function _toPNG($image) { // set temporary image file name $tempname = tempnam(K_PATH_CACHE, 'jpg_'); // turn off interlaced mode imageinterlace($image, 0); // create temporary PNG image imagepng($image, $tempname); // remove image from memory imagedestroy($image); // get PNG image data $retvars = $this->_parsepng($tempname); // tidy up by removing temporary image unlink($tempname); return $retvars; } /** * Set the transparency for the given GD image. * @param $new_image (image) GD image object * @param $image (image) GD image object. * return GD image object. * @protected * @since 4.9.016 (2010-04-20) */ protected function _setGDImageTransparency($new_image, $image) { // transparency index $tid = imagecolortransparent($image); // default transparency color $tcol = array('red' => 255, 'green' => 255, 'blue' => 255); if ($tid >= 0) { // get the colors for the transparency index $tcol = imagecolorsforindex($image, $tid); } $tid = imagecolorallocate($new_image, $tcol['red'], $tcol['green'], $tcol['blue']); imagefill($new_image, 0, 0, $tid); imagecolortransparent($new_image, $tid); return $new_image; } /** * Extract info from a JPEG file without using the GD library. * @param $file (string) image file to parse * @return array structure containing the image data * @protected */ protected function _parsejpeg($file) { $a = getimagesize($file); if (empty($a)) { $this->Error('Missing or incorrect image file: '.$file); } if ($a[2] != 2) { $this->Error('Not a JPEG file: '.$file); } // bits per pixel $bpc = isset($a['bits']) ? intval($a['bits']) : 8; // number of image channels if (!isset($a['channels'])) { $channels = 3; } else { $channels = intval($a['channels']); } // default colour space switch ($channels) { case 1: { $colspace = 'DeviceGray'; break; } case 3: { $colspace = 'DeviceRGB'; break; } case 4: { $colspace = 'DeviceCMYK'; break; } default: { $channels = 3; $colspace = 'DeviceRGB'; break; } } // get file content $data = file_get_contents($file); // check for embedded ICC profile $icc = array(); $offset = 0; while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) { // get ICC sequence length $length = ($this->_getUSHORT($data, ($pos - 2)) - 16); // marker sequence number $msn = max(1, ord($data[($pos + 12)])); // number of markers (total of APP2 used) $nom = max(1, ord($data[($pos + 13)])); // get sequence segment $icc[($msn - 1)] = substr($data, ($pos + 14), $length); // move forward to next sequence $offset = ($pos + 14 + $length); } // order and compact ICC segments if (count($icc) > 0) { ksort($icc); $icc = implode('', $icc); if ((ord($icc{36}) != 0x61) OR (ord($icc{37}) != 0x63) OR (ord($icc{38}) != 0x73) OR (ord($icc{39}) != 0x70)) { // invalid ICC profile $icc = false; } } else { $icc = false; } return array('w' => $a[0], 'h' => $a[1], 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data); } /** * Extract info from a PNG file without using the GD library. * @param $file (string) image file to parse * @return array structure containing the image data * @protected */ protected function _parsepng($file) { $f = fopen($file, 'rb'); if ($f === false) { $this->Error('Can\'t open image file: '.$file); } //Check signature if (fread($f, 8) != chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) { $this->Error('Not a PNG file: '.$file); } //Read header chunk fread($f, 4); if (fread($f, 4) != 'IHDR') { $this->Error('Incorrect PNG file: '.$file); } $w = $this->_freadint($f); $h = $this->_freadint($f); $bpc = ord(fread($f, 1)); if ($bpc > 8) { //$this->Error('16-bit depth not supported: '.$file); fclose($f); return false; } $ct = ord(fread($f, 1)); if ($ct == 0) { $colspace = 'DeviceGray'; } elseif ($ct == 2) { $colspace = 'DeviceRGB'; } elseif ($ct == 3) { $colspace = 'Indexed'; } else { // alpha channel fclose($f); return 'pngalpha'; } if (ord(fread($f, 1)) != 0) { //$this->Error('Unknown compression method: '.$file); fclose($f); return false; } if (ord(fread($f, 1)) != 0) { //$this->Error('Unknown filter method: '.$file); fclose($f); return false; } if (ord(fread($f, 1)) != 0) { //$this->Error('Interlacing not supported: '.$file); fclose($f); return false; } fread($f, 4); $channels = ($ct == 2 ? 3 : 1); $parms = '/DecodeParms << /Predictor 15 /Colors '.$channels.' /BitsPerComponent '.$bpc.' /Columns '.$w.' >>'; //Scan chunks looking for palette, transparency and image data $pal = ''; $trns = ''; $data = ''; $icc = false; do { $n = $this->_freadint($f); $type = fread($f, 4); if ($type == 'PLTE') { // read palette $pal = $this->rfread($f, $n); fread($f, 4); } elseif ($type == 'tRNS') { // read transparency info $t = $this->rfread($f, $n); if ($ct == 0) { $trns = array(ord($t{1})); } elseif ($ct == 2) { $trns = array(ord($t{1}), ord($t{3}), ord($t{5})); } else { $pos = strpos($t, chr(0)); if ($pos !== false) { $trns = array($pos); } } fread($f, 4); } elseif ($type == 'IDAT') { // read image data block $data .= $this->rfread($f, $n); fread($f, 4); } elseif ($type == 'iCCP') { // skip profile name and null separator $len = 0; while ((ord(fread($f, 1)) > 0) AND ($len < 80)) { ++$len; } // get compression method if (ord(fread($f, 1)) != 0) { //$this->Error('Unknown filter method: '.$file); fclose($f); return false; } // read ICC Color Profile $icc = $this->rfread($f, ($n - $len - 2)); // decompress profile $icc = gzuncompress($icc); fread($f, 4); } elseif ($type == 'IEND') { break; } else { $this->rfread($f, $n + 4); } } while ($n); if (($colspace == 'Indexed') AND (empty($pal))) { //$this->Error('Missing palette in '.$file); fclose($f); return false; } fclose($f); return array('w' => $w, 'h' => $h, 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data); } /** * Binary-safe and URL-safe file read. * Reads up to length bytes from the file pointer referenced by handle. Reading stops as soon as one of the following conditions is met: length bytes have been read; EOF (end of file) is reached. * @param $handle (resource) * @param $length (int) * @return Returns the read string or FALSE in case of error. * @author Nicola Asuni * @protected * @since 4.5.027 (2009-03-16) */ protected function rfread($handle, $length) { $data = fread($handle, $length); if ($data === false) { return false; } $rest = $length - strlen($data); if ($rest > 0) { $data .= $this->rfread($handle, $rest); } return $data; } /** * Extract info from a PNG image with alpha channel using the GD library. * @param $file (string) Name of the file containing the image. * @param $x (float) Abscissa of the upper-left corner. * @param $y (float) Ordinate of the upper-left corner. * @param $wpx (float) Original width of the image in pixels. * @param $hpx (float) original height of the image in pixels. * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated. * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated. * @param $type (string) Image format. Possible values are (case insensitive): JPEG and PNG (whitout GD library) and all images supported by GD: GD, GD2, GD2PART, GIF, JPEG, PNG, BMP, XBM, XPM;. If not specified, the type is inferred from the file extension. * @param $link (mixed) URL or identifier returned by AddLink(). * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
    • T: top-right for LTR or top-left for RTL
    • M: middle-right for LTR or middle-left for RTL
    • B: bottom-right for LTR or bottom-left for RTL
    • N: next line
    * @param $resize (boolean) If true resize (reduce) the image to fit $w and $h (requires GD library). * @param $dpi (int) dot-per-inch resolution used on resize * @param $palign (string) Allows to center or align the image on the current line. Possible values are:
    • L : left align
    • C : center
    • R : right align
    • '' : empty string : left for LTR or right for RTL
    * @param $filehash (string) File hash used to build unique file names. * @author Nicola Asuni * @protected * @since 4.3.007 (2008-12-04) * @see Image() */ protected function ImagePngAlpha($file, $x, $y, $wpx, $hpx, $w, $h, $type, $link, $align, $resize, $dpi, $palign, $filehash='') { if (empty($filehash)) { $filehash = md5($file); } // create temp image file (without alpha channel) $tempfile_plain = K_PATH_CACHE.'mskp_'.$filehash; // create temp alpha file $tempfile_alpha = K_PATH_CACHE.'mska_'.$filehash; if (extension_loaded('imagick')) { // ImageMagick extension // ImageMagick library $img = new Imagick(); $img->readImage($file); // clone image object $imga = $img->clone(); // extract alpha channel $img->separateImageChannel(8); // 8 = (imagick::CHANNEL_ALPHA | imagick::CHANNEL_OPACITY | imagick::CHANNEL_MATTE); $img->negateImage(true); $img->setImageFormat('png'); $img->writeImage($tempfile_alpha); // remove alpha channel $imga->separateImageChannel(39); // 39 = (imagick::CHANNEL_ALL & ~(imagick::CHANNEL_ALPHA | imagick::CHANNEL_OPACITY | imagick::CHANNEL_MATTE)); $imga->setImageFormat('png'); $imga->writeImage($tempfile_plain); } elseif (function_exists('imagecreatefrompng')) { // GD extension // generate images $img = imagecreatefrompng($file); $imgalpha = imagecreate($wpx, $hpx); // generate gray scale palette (0 -> 255) for ($c = 0; $c < 256; ++$c) { ImageColorAllocate($imgalpha, $c, $c, $c); } // extract alpha channel for ($xpx = 0; $xpx < $wpx; ++$xpx) { for ($ypx = 0; $ypx < $hpx; ++$ypx) { $color = imagecolorat($img, $xpx, $ypx); $alpha = ($color >> 24); // shifts off the first 24 bits (where 8x3 are used for each color), and returns the remaining 7 allocated bits (commonly used for alpha) $alpha = (((127 - $alpha) / 127) * 255); // GD alpha is only 7 bit (0 -> 127) $alpha = $this->getGDgamma($alpha); // correct gamma imagesetpixel($imgalpha, $xpx, $ypx, $alpha); } } imagepng($imgalpha, $tempfile_alpha); imagedestroy($imgalpha); // extract image without alpha channel $imgplain = imagecreatetruecolor($wpx, $hpx); imagecopy($imgplain, $img, 0, 0, 0, 0, $wpx, $hpx); imagepng($imgplain, $tempfile_plain); imagedestroy($imgplain); } else { $this->Error('TCPDF requires the Imagick or GD extension to handle PNG images with alpha channel.'); } // embed mask image $imgmask = $this->Image($tempfile_alpha, $x, $y, $w, $h, 'PNG', '', '', $resize, $dpi, '', true, false); // embed image, masked with previously embedded mask $this->Image($tempfile_plain, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, false, $imgmask); // remove temp files unlink($tempfile_alpha); unlink($tempfile_plain); } /** * Correct the gamma value to be used with GD library * @param $v (float) the gamma value to be corrected * @protected * @since 4.3.007 (2008-12-04) */ protected function getGDgamma($v) { return (pow(($v / 255), 2.2) * 255); } /** * Performs a line break. * The current abscissa goes back to the left margin and the ordinate increases by the amount passed in parameter. * @param $h (float) The height of the break. By default, the value equals the height of the last printed cell. * @param $cell (boolean) if true add the current left (or right o for RTL) padding to the X coordinate * @public * @since 1.0 * @see Cell() */ public function Ln($h='', $cell=false) { if (($this->num_columns > 1) AND ($this->y == $this->columns[$this->current_column]['y']) AND isset($this->columns[$this->current_column]['x']) AND ($this->x == $this->columns[$this->current_column]['x'])) { // revove vertical space from the top of the column return; } if ($cell) { if ($this->rtl) { $cellpadding = $this->cell_padding['R']; } else { $cellpadding = $this->cell_padding['L']; } } else { $cellpadding = 0; } if ($this->rtl) { $this->x = $this->w - $this->rMargin - $cellpadding; } else { $this->x = $this->lMargin + $cellpadding; } if (is_string($h)) { $this->y += $this->lasth; } else { $this->y += $h; } $this->newline = true; } /** * Returns the relative X value of current position. * The value is relative to the left border for LTR languages and to the right border for RTL languages. * @return float * @public * @since 1.2 * @see SetX(), GetY(), SetY() */ public function GetX() { //Get x position if ($this->rtl) { return ($this->w - $this->x); } else { return $this->x; } } /** * Returns the absolute X value of current position. * @return float * @public * @since 1.2 * @see SetX(), GetY(), SetY() */ public function GetAbsX() { return $this->x; } /** * Returns the ordinate of the current position. * @return float * @public * @since 1.0 * @see SetY(), GetX(), SetX() */ public function GetY() { return $this->y; } /** * Defines the abscissa of the current position. * If the passed value is negative, it is relative to the right of the page (or left if language is RTL). * @param $x (float) The value of the abscissa. * @param $rtloff (boolean) if true always uses the page top-left corner as origin of axis. * @public * @since 1.2 * @see GetX(), GetY(), SetY(), SetXY() */ public function SetX($x, $rtloff=false) { if (!$rtloff AND $this->rtl) { if ($x >= 0) { $this->x = $this->w - $x; } else { $this->x = abs($x); } } else { if ($x >= 0) { $this->x = $x; } else { $this->x = $this->w + $x; } } if ($this->x < 0) { $this->x = 0; } if ($this->x > $this->w) { $this->x = $this->w; } } /** * Moves the current abscissa back to the left margin and sets the ordinate. * If the passed value is negative, it is relative to the bottom of the page. * @param $y (float) The value of the ordinate. * @param $resetx (bool) if true (default) reset the X position. * @param $rtloff (boolean) if true always uses the page top-left corner as origin of axis. * @public * @since 1.0 * @see GetX(), GetY(), SetY(), SetXY() */ public function SetY($y, $resetx=true, $rtloff=false) { if ($resetx) { //reset x if (!$rtloff AND $this->rtl) { $this->x = $this->w - $this->rMargin; } else { $this->x = $this->lMargin; } } if ($y >= 0) { $this->y = $y; } else { $this->y = $this->h + $y; } if ($this->y < 0) { $this->y = 0; } if ($this->y > $this->h) { $this->y = $this->h; } } /** * Defines the abscissa and ordinate of the current position. * If the passed values are negative, they are relative respectively to the right and bottom of the page. * @param $x (float) The value of the abscissa. * @param $y (float) The value of the ordinate. * @param $rtloff (boolean) if true always uses the page top-left corner as origin of axis. * @public * @since 1.2 * @see SetX(), SetY() */ public function SetXY($x, $y, $rtloff=false) { $this->SetY($y, false, $rtloff); $this->SetX($x, $rtloff); } /** * Ouput input data and compress it if possible. * @param $data (string) Data to output. * @param $length (int) Data length in bytes. * @protected * @since 5.9.086 */ protected function sendOutputData($data, $length) { if (!isset($_SERVER['HTTP_ACCEPT_ENCODING']) OR empty($_SERVER['HTTP_ACCEPT_ENCODING'])) { // the content length may vary if the server is using compression header('Content-Length: '.$length); } echo $data; } /** * Send the document to a given destination: string, local file or browser. * In the last case, the plug-in may be used (if present) or a download ("Save as" dialog box) may be forced.
    * The method first calls Close() if necessary to terminate the document. * @param $name (string) The name of the file when saved. Note that special characters are removed and blanks characters are replaced with the underscore character. * @param $dest (string) Destination where to send the document. It can take one of the following values:
    • I: send the file inline to the browser (default). The plug-in is used if available. The name given by name is used when one selects the "Save as" option on the link generating the PDF.
    • D: send to the browser and force a file download with the name given by name.
    • F: save to a local server file with the name given by name.
    • S: return the document as a string (name is ignored).
    • FI: equivalent to F + I option
    • FD: equivalent to F + D option
    • E: return the document as base64 mime multi-part email attachment (RFC 2045)
    * @public * @since 1.0 * @see Close() */ public function Output($name='doc.pdf', $dest='I') { //Output PDF to some destination //Finish document if necessary if ($this->state < 3) { $this->Close(); } //Normalize parameters if (is_bool($dest)) { $dest = $dest ? 'D' : 'F'; } $dest = strtoupper($dest); if ($dest{0} != 'F') { $name = preg_replace('/[\s]+/', '_', $name); $name = preg_replace('/[^a-zA-Z0-9_\.-]/', '', $name); } if ($this->sign) { // *** apply digital signature to the document *** // get the document content $pdfdoc = $this->getBuffer(); // remove last newline $pdfdoc = substr($pdfdoc, 0, -1); // Remove the original buffer if (isset($this->diskcache) AND $this->diskcache) { // remove buffer file from cache unlink($this->buffer); } unset($this->buffer); // remove filler space $byterange_string_len = strlen($this->byterange_string); // define the ByteRange $byte_range = array(); $byte_range[0] = 0; $byte_range[1] = strpos($pdfdoc, $this->byterange_string) + $byterange_string_len + 10; $byte_range[2] = $byte_range[1] + $this->signature_max_length + 2; $byte_range[3] = strlen($pdfdoc) - $byte_range[2]; $pdfdoc = substr($pdfdoc, 0, $byte_range[1]).substr($pdfdoc, $byte_range[2]); // replace the ByteRange $byterange = sprintf('/ByteRange[0 %u %u %u]', $byte_range[1], $byte_range[2], $byte_range[3]); $byterange .= str_repeat(' ', ($byterange_string_len - strlen($byterange))); $pdfdoc = str_replace($this->byterange_string, $byterange, $pdfdoc); // write the document to a temporary folder $tempdoc = tempnam(K_PATH_CACHE, 'tmppdf_'); $f = fopen($tempdoc, 'wb'); if (!$f) { $this->Error('Unable to create temporary file: '.$tempdoc); } $pdfdoc_length = strlen($pdfdoc); fwrite($f, $pdfdoc, $pdfdoc_length); fclose($f); // get digital signature via openssl library $tempsign = tempnam(K_PATH_CACHE, 'tmpsig_'); if (empty($this->signature_data['extracerts'])) { openssl_pkcs7_sign($tempdoc, $tempsign, $this->signature_data['signcert'], array($this->signature_data['privkey'], $this->signature_data['password']), array(), PKCS7_BINARY | PKCS7_DETACHED); } else { openssl_pkcs7_sign($tempdoc, $tempsign, $this->signature_data['signcert'], array($this->signature_data['privkey'], $this->signature_data['password']), array(), PKCS7_BINARY | PKCS7_DETACHED, $this->signature_data['extracerts']); } unlink($tempdoc); // read signature $signature = file_get_contents($tempsign); unlink($tempsign); // extract signature $signature = substr($signature, $pdfdoc_length); $signature = substr($signature, (strpos($signature, "%%EOF\n\n------") + 13)); $tmparr = explode("\n\n", $signature); $signature = $tmparr[1]; unset($tmparr); // decode signature $signature = base64_decode(trim($signature)); // convert signature to hex $signature = current(unpack('H*', $signature)); $signature = str_pad($signature, $this->signature_max_length, '0'); // disable disk caching $this->diskcache = false; // Add signature to the document $this->buffer = substr($pdfdoc, 0, $byte_range[1]).'<'.$signature.'>'.substr($pdfdoc, $byte_range[1]); $this->bufferlen = strlen($this->buffer); } switch($dest) { case 'I': { // Send PDF to the standard output if (ob_get_contents()) { $this->Error('Some data has already been output, can\'t send PDF file'); } if (php_sapi_name() != 'cli') { // send output to a browser header('Content-Type: application/pdf'); if (headers_sent()) { $this->Error('Some data has already been output to browser, can\'t send PDF file'); } header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); //header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 header('Pragma: public'); header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); header('Content-Disposition: inline; filename="'.basename($name).'";'); $this->sendOutputData($this->getBuffer(), $this->bufferlen); } else { echo $this->getBuffer(); } break; } case 'D': { // download PDF as file if (ob_get_contents()) { $this->Error('Some data has already been output, can\'t send PDF file'); } header('Content-Description: File Transfer'); if (headers_sent()) { $this->Error('Some data has already been output to browser, can\'t send PDF file'); } header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); //header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 header('Pragma: public'); header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // force download dialog if (strpos(php_sapi_name(), 'cgi') === false) { header('Content-Type: application/force-download'); header('Content-Type: application/octet-stream', false); header('Content-Type: application/download', false); header('Content-Type: application/pdf', false); } else { header('Content-Type: application/pdf'); } // use the Content-Disposition header to supply a recommended filename header('Content-Disposition: attachment; filename="'.basename($name).'";'); header('Content-Transfer-Encoding: binary'); $this->sendOutputData($this->getBuffer(), $this->bufferlen); break; } case 'F': case 'FI': case 'FD': { // save PDF to a local file if ($this->diskcache) { copy($this->buffer, $name); } else { $f = fopen($name, 'wb'); if (!$f) { $this->Error('Unable to create output file: '.$name); } fwrite($f, $this->getBuffer(), $this->bufferlen); fclose($f); } if ($dest == 'FI') { // send headers to browser header('Content-Type: application/pdf'); header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); //header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1 header('Pragma: public'); header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); header('Content-Disposition: inline; filename="'.basename($name).'";'); $this->sendOutputData(file_get_contents($name), filesize($name)); } elseif ($dest == 'FD') { // send headers to browser if (ob_get_contents()) { $this->Error('Some data has already been output, can\'t send PDF file'); } header('Content-Description: File Transfer'); if (headers_sent()) { $this->Error('Some data has already been output to browser, can\'t send PDF file'); } header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1'); header('Pragma: public'); header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); // force download dialog if (strpos(php_sapi_name(), 'cgi') === false) { header('Content-Type: application/force-download'); header('Content-Type: application/octet-stream', false); header('Content-Type: application/download', false); header('Content-Type: application/pdf', false); } else { header('Content-Type: application/pdf'); } // use the Content-Disposition header to supply a recommended filename header('Content-Disposition: attachment; filename="'.basename($name).'";'); header('Content-Transfer-Encoding: binary'); $this->sendOutputData(file_get_contents($name), filesize($name)); } break; } case 'E': { // return PDF as base64 mime multi-part email attachment (RFC 2045) $retval = 'Content-Type: application/pdf;'."\r\n"; $retval .= ' name="'.$name.'"'."\r\n"; $retval .= 'Content-Transfer-Encoding: base64'."\r\n"; $retval .= 'Content-Disposition: attachment;'."\r\n"; $retval .= ' filename="'.$name.'"'."\r\n\r\n"; $retval .= chunk_split(base64_encode($this->getBuffer()), 76, "\r\n"); return $retval; } case 'S': { // returns PDF as a string return $this->getBuffer(); } default: { $this->Error('Incorrect output destination: '.$dest); } } return ''; } /** * Unset all class variables except the following critical variables: internal_encoding, state, bufferlen, buffer and diskcache. * @param $destroyall (boolean) if true destroys all class variables, otherwise preserves critical variables. * @param $preserve_objcopy (boolean) if true preserves the objcopy variable * @public * @since 4.5.016 (2009-02-24) */ public function _destroy($destroyall=false, $preserve_objcopy=false) { if ($destroyall AND isset($this->diskcache) AND $this->diskcache AND (!$preserve_objcopy) AND (!$this->empty_string($this->buffer))) { // remove buffer file from cache unlink($this->buffer); } foreach (array_keys(get_object_vars($this)) as $val) { if ($destroyall OR ( ($val != 'internal_encoding') AND ($val != 'state') AND ($val != 'bufferlen') AND ($val != 'buffer') AND ($val != 'diskcache') AND ($val != 'sign') AND ($val != 'signature_data') AND ($val != 'signature_max_length') AND ($val != 'byterange_string') )) { if ((!$preserve_objcopy OR ($val != 'objcopy')) AND isset($this->$val)) { unset($this->$val); } } } } /** * Check for locale-related bug * @protected */ protected function _dochecks() { //Check for locale-related bug if (1.1 == 1) { $this->Error('Don\'t alter the locale before including class file'); } //Check for decimal separator if (sprintf('%.1F', 1.0) != '1.0') { setlocale(LC_NUMERIC, 'C'); } } /** * Return fonts path * @return string * @protected */ protected function _getfontpath() { if (!defined('K_PATH_FONTS') AND is_dir(dirname(__FILE__).'/fonts')) { define('K_PATH_FONTS', dirname(__FILE__).'/fonts/'); } return defined('K_PATH_FONTS') ? K_PATH_FONTS : ''; } /** * Return an array containing variations for the basic page number alias. * @param $a (string) Base alias. * @return array of page number aliases * @protected */ protected function getInternalPageNumberAliases($a= '') { $alias = array(); // build array of Unicode + ASCII variants (the order is important) $alias = array('u' => array(), 'a' => array()); $u = '{'.$a.'}'; $alias['u'][] = $this->_escape($u); if ($this->isunicode) { $alias['u'][] = $this->_escape($this->UTF8ToLatin1($u)); $alias['u'][] = $this->_escape($this->utf8StrRev($u, false, $this->tmprtl)); $alias['a'][] = $this->_escape($this->UTF8ToLatin1($a)); $alias['a'][] = $this->_escape($this->utf8StrRev($a, false, $this->tmprtl)); } $alias['a'][] = $this->_escape($a); return $alias; } /** * Return an array containing all internal page aliases. * @return array of page number aliases * @protected */ protected function getAllInternalPageNumberAliases() { $basic_alias = array($this->alias_tot_pages, $this->alias_num_page, $this->alias_group_tot_pages, $this->alias_group_num_page, $this->alias_right_shift); $pnalias = array(); foreach($basic_alias as $k => $a) { $pnalias[$k] = $this->getInternalPageNumberAliases($a); } return $pnalias; } /** * Replace page number aliases with number. * @param $page (string) Page content. * @param $replace (array) Array of replacements (array keys are replacement strings, values are alias arrays). * @param $diff (int) If passed, this will be set to the total char number difference between alias and replacements. * @return replaced page content and updated $diff parameter as array. * @protected */ protected function replacePageNumAliases($page, $replace, $diff=0) { foreach ($replace as $rep) { foreach ($rep[3] as $a) { if (strpos($page, $a) !== false) { $page = str_replace($a, $rep[0], $page); $diff += ($rep[2] - $rep[1]); } } } return array($page, $diff); } /** * Replace right shift page number aliases with spaces to correct right alignment. * This works perfectly only when using monospaced fonts. * @param $page (string) Page content. * @param $aliases (array) Array of page aliases. * @param $diff (int) initial difference to add. * @return replaced page content. * @protected */ protected function replaceRightShiftPageNumAliases($page, $aliases, $diff) { foreach ($aliases as $type => $alias) { foreach ($alias as $a) { // find position of compensation factor $startnum = (strpos($a, ':') + 1); $a = substr($a, 0, $startnum); if (($pos = strpos($page, $a)) !== false) { // end of alias $endnum = strpos($page, '}', $pos); // string to be replaced $aa = substr($page, $pos, ($endnum - $pos + 1)); // get compensation factor $ratio = substr($page, ($pos + $startnum), ($endnum - $pos - $startnum)); $ratio = preg_replace('/[^0-9\.]/', '', $ratio); $ratio = floatval($ratio); if ($type == 'u') { $chrdiff = floor(($diff + 12) * $ratio); $shift = str_repeat(' ', $chrdiff); $shift = $this->UTF8ToUTF16BE($shift, false); } else { $chrdiff = floor(($diff + 11) * $ratio); $shift = str_repeat(' ', $chrdiff); } $page = str_replace($aa, $shift, $page); } } } return $page; } /** * Output pages (and replace page number aliases). * @protected */ protected function _putpages() { $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; // get internal aliases for page numbers $pnalias = $this->getAllInternalPageNumberAliases(); $num_pages = $this->numpages; $ptpa = $this->formatPageNumber(($this->starting_page_number + $num_pages - 1)); $ptpu = $this->UTF8ToUTF16BE($ptpa, false); $ptp_num_chars = $this->GetNumChars($ptpa); $pagegroupnum = 0; $groupnum = 0; $ptgu = 1; $ptga = 1; for ($n = 1; $n <= $num_pages; ++$n) { // get current page $temppage = $this->getPageBuffer($n); $pagelen = strlen($temppage); // set replacements for total pages number $pnpa = $this->formatPageNumber(($this->starting_page_number + $n - 1)); $pnpu = $this->UTF8ToUTF16BE($pnpa, false); $pnp_num_chars = $this->GetNumChars($pnpa); $pdiff = 0; // difference used for right shift alignment of page numbers $gdiff = 0; // difference used for right shift alignment of page group numbers if (!empty($this->pagegroups)) { if (isset($this->newpagegroup[$n])) { $pagegroupnum = 0; ++$groupnum; $ptga = $this->formatPageNumber($this->pagegroups[$groupnum]); $ptgu = $this->UTF8ToUTF16BE($ptga, false); $ptg_num_chars = $this->GetNumChars($ptga); } ++$pagegroupnum; $pnga = $this->formatPageNumber($pagegroupnum); $pngu = $this->UTF8ToUTF16BE($pnga, false); $png_num_chars = $this->GetNumChars($pnga); // replace page numbers $replace = array(); $replace[] = array($ptgu, $ptg_num_chars, 9, $pnalias[2]['u']); $replace[] = array($ptga, $ptg_num_chars, 7, $pnalias[2]['a']); $replace[] = array($pngu, $png_num_chars, 9, $pnalias[3]['u']); $replace[] = array($pnga, $png_num_chars, 7, $pnalias[3]['a']); list($temppage, $gdiff) = $this->replacePageNumAliases($temppage, $replace, $gdiff); } // replace page numbers $replace = array(); $replace[] = array($ptpu, $ptp_num_chars, 9, $pnalias[0]['u']); $replace[] = array($ptpa, $ptp_num_chars, 7, $pnalias[0]['a']); $replace[] = array($pnpu, $pnp_num_chars, 9, $pnalias[1]['u']); $replace[] = array($pnpa, $pnp_num_chars, 7, $pnalias[1]['a']); list($temppage, $pdiff) = $this->replacePageNumAliases($temppage, $replace, $pdiff); // replace right shift alias $temppage = $this->replaceRightShiftPageNumAliases($temppage, $pnalias[4], max($pdiff, $gdiff)); // replace EPS marker $temppage = str_replace($this->epsmarker, '', $temppage); //Page $this->page_obj_id[$n] = $this->_newobj(); $out = '<<'; $out .= ' /Type /Page'; $out .= ' /Parent 1 0 R'; $out .= ' /LastModified '.$this->_datestring(); $out .= ' /Resources 2 0 R'; $boxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox'); foreach ($boxes as $box) { $out .= ' /'.$box; $out .= sprintf(' [%.2F %.2F %.2F %.2F]', $this->pagedim[$n][$box]['llx'], $this->pagedim[$n][$box]['lly'], $this->pagedim[$n][$box]['urx'], $this->pagedim[$n][$box]['ury']); } if (isset($this->pagedim[$n]['BoxColorInfo']) AND !empty($this->pagedim[$n]['BoxColorInfo'])) { $out .= ' /BoxColorInfo <<'; foreach ($boxes as $box) { if (isset($this->pagedim[$n]['BoxColorInfo'][$box])) { $out .= ' /'.$box.' <<'; if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['C'])) { $color = $this->pagedim[$n]['BoxColorInfo'][$box]['C']; $out .= ' /C ['; $out .= sprintf(' %.3F %.3F %.3F', $color[0]/255, $color[1]/255, $color[2]/255); $out .= ' ]'; } if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['W'])) { $out .= ' /W '.($this->pagedim[$n]['BoxColorInfo'][$box]['W'] * $this->k); } if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['S'])) { $out .= ' /S /'.$this->pagedim[$n]['BoxColorInfo'][$box]['S']; } if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['D'])) { $dashes = $this->pagedim[$n]['BoxColorInfo'][$box]['D']; $out .= ' /D ['; foreach ($dashes as $dash) { $out .= sprintf(' %.3F', ($dash * $this->k)); } $out .= ' ]'; } $out .= ' >>'; } } $out .= ' >>'; } $out .= ' /Contents '.($this->n + 1).' 0 R'; $out .= ' /Rotate '.$this->pagedim[$n]['Rotate']; if (!$this->pdfa_mode) { $out .= ' /Group << /Type /Group /S /Transparency /CS /DeviceRGB >>'; } if (isset($this->pagedim[$n]['trans']) AND !empty($this->pagedim[$n]['trans'])) { // page transitions if (isset($this->pagedim[$n]['trans']['Dur'])) { $out .= ' /Dur '.$this->pagedim[$n]['trans']['Dur']; } $out .= ' /Trans <<'; $out .= ' /Type /Trans'; if (isset($this->pagedim[$n]['trans']['S'])) { $out .= ' /S /'.$this->pagedim[$n]['trans']['S']; } if (isset($this->pagedim[$n]['trans']['D'])) { $out .= ' /D '.$this->pagedim[$n]['trans']['D']; } if (isset($this->pagedim[$n]['trans']['Dm'])) { $out .= ' /Dm /'.$this->pagedim[$n]['trans']['Dm']; } if (isset($this->pagedim[$n]['trans']['M'])) { $out .= ' /M /'.$this->pagedim[$n]['trans']['M']; } if (isset($this->pagedim[$n]['trans']['Di'])) { $out .= ' /Di '.$this->pagedim[$n]['trans']['Di']; } if (isset($this->pagedim[$n]['trans']['SS'])) { $out .= ' /SS '.$this->pagedim[$n]['trans']['SS']; } if (isset($this->pagedim[$n]['trans']['B'])) { $out .= ' /B '.$this->pagedim[$n]['trans']['B']; } $out .= ' >>'; } $out .= $this->_getannotsrefs($n); $out .= ' /PZ '.$this->pagedim[$n]['PZ']; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); //Page content $p = ($this->compress) ? gzcompress($temppage) : $temppage; $this->_newobj(); $p = $this->_getrawstream($p); $this->_out('<<'.$filter.'/Length '.strlen($p).'>> stream'."\n".$p."\n".'endstream'."\n".'endobj'); if ($this->diskcache) { // remove temporary files unlink($this->pages[$n]); } } //Pages root $out = $this->_getobj(1)."\n"; $out .= '<< /Type /Pages /Kids ['; foreach($this->page_obj_id as $page_obj) { $out .= ' '.$page_obj.' 0 R'; } $out .= ' ] /Count '.$num_pages.' >>'; $out .= "\n".'endobj'; $this->_out($out); } /** * Output references to page annotations * @param $n (int) page number * @protected * @author Nicola Asuni * @since 4.7.000 (2008-08-29) * @deprecated */ protected function _putannotsrefs($n) { $this->_out($this->_getannotsrefs($n)); } /** * Get references to page annotations. * @param $n (int) page number * @return string * @protected * @author Nicola Asuni * @since 5.0.010 (2010-05-17) */ protected function _getannotsrefs($n) { if (!(isset($this->PageAnnots[$n]) OR ($this->sign AND isset($this->signature_data['cert_type'])))) { return ''; } $out = ' /Annots ['; if (isset($this->PageAnnots[$n])) { foreach ($this->PageAnnots[$n] as $key => $val) { if (!in_array($val['n'], $this->radio_groups)) { $out .= ' '.$val['n'].' 0 R'; } } // add radiobutton groups if (isset($this->radiobutton_groups[$n])) { foreach ($this->radiobutton_groups[$n] as $key => $data) { if (isset($data['n'])) { $out .= ' '.$data['n'].' 0 R'; } } } } if ($this->sign AND ($n == $this->signature_appearance['page']) AND isset($this->signature_data['cert_type'])) { // set reference for signature object $out .= ' '.$this->sig_obj_id.' 0 R'; } if (!empty($this->empty_signature_appearance)) { foreach ($this->empty_signature_appearance as $esa) { if ($esa['page'] == $n) { // set reference for empty signature objects $out .= ' '.$esa['objid'].' 0 R'; } } } $out .= ' ]'; return $out; } /** * Output annotations objects for all pages. * !!! THIS METHOD IS NOT YET COMPLETED !!! * See section 12.5 of PDF 32000_2008 reference. * @protected * @author Nicola Asuni * @since 4.0.018 (2008-08-06) */ protected function _putannotsobjs() { // reset object counter for ($n=1; $n <= $this->numpages; ++$n) { if (isset($this->PageAnnots[$n])) { // set page annotations foreach ($this->PageAnnots[$n] as $key => $pl) { $annot_obj_id = $this->PageAnnots[$n][$key]['n']; // create annotation object for grouping radiobuttons if (isset($this->radiobutton_groups[$n][$pl['txt']]) AND is_array($this->radiobutton_groups[$n][$pl['txt']])) { $radio_button_obj_id = $this->radiobutton_groups[$n][$pl['txt']]['n']; $annots = '<<'; $annots .= ' /Type /Annot'; $annots .= ' /Subtype /Widget'; $annots .= ' /Rect [0 0 0 0]'; if ($this->radiobutton_groups[$n][$pl['txt']]['#readonly#']) { // read only $annots .= ' /F 68'; $annots .= ' /Ff 49153'; } else { $annots .= ' /F 4'; // default print for PDF/A $annots .= ' /Ff 49152'; } $annots .= ' /T '.$this->_datastring($pl['txt'], $radio_button_obj_id); $annots .= ' /FT /Btn'; $annots .= ' /Kids ['; $defval = ''; foreach ($this->radiobutton_groups[$n][$pl['txt']] as $key => $data) { if (isset($data['kid'])) { $annots .= ' '.$data['kid'].' 0 R'; if ($data['def'] !== 'Off') { $defval = $data['def']; } } } $annots .= ' ]'; if (!empty($defval)) { $annots .= ' /V /'.$defval; } $annots .= ' >>'; $this->_out($this->_getobj($radio_button_obj_id)."\n".$annots."\n".'endobj'); $this->form_obj_id[] = $radio_button_obj_id; // store object id to be used on Parent entry of Kids $this->radiobutton_groups[$n][$pl['txt']] = $radio_button_obj_id; } $formfield = false; $pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER); $a = $pl['x'] * $this->k; $b = $this->pagedim[$n]['h'] - (($pl['y'] + $pl['h']) * $this->k); $c = $pl['w'] * $this->k; $d = $pl['h'] * $this->k; $rect = sprintf('%.2F %.2F %.2F %.2F', $a, $b, $a+$c, $b+$d); // create new annotation object $annots = '<_textstring($pl['txt'], $annot_obj_id); $annots .= ' /P '.$this->page_obj_id[$n].' 0 R'; $annots .= ' /NM '.$this->_datastring(sprintf('%04u-%04u', $n, $key), $annot_obj_id); $annots .= ' /M '.$this->_datestring($annot_obj_id); if (isset($pl['opt']['f'])) { $fval = 0; if (is_array($pl['opt']['f'])) { foreach ($pl['opt']['f'] as $f) { switch (strtolower($f)) { case 'invisible': { $fval += 1 << 0; break; } case 'hidden': { $fval += 1 << 1; break; } case 'print': { $fval += 1 << 2; break; } case 'nozoom': { $fval += 1 << 3; break; } case 'norotate': { $fval += 1 << 4; break; } case 'noview': { $fval += 1 << 5; break; } case 'readonly': { $fval += 1 << 6; break; } case 'locked': { $fval += 1 << 8; break; } case 'togglenoview': { $fval += 1 << 9; break; } case 'lockedcontents': { $fval += 1 << 10; break; } default: { break; } } } } else { $fval = intval($pl['opt']['f']); } } else { $fval = 4; } if ($this->pdfa_mode) { // force print flag for PDF/A mode $fval |= 4; } $annots .= ' /F '.intval($fval); if (isset($pl['opt']['as']) AND is_string($pl['opt']['as'])) { $annots .= ' /AS /'.$pl['opt']['as']; } if (isset($pl['opt']['ap'])) { // appearance stream $annots .= ' /AP <<'; if (is_array($pl['opt']['ap'])) { foreach ($pl['opt']['ap'] as $apmode => $apdef) { // $apmode can be: n = normal; r = rollover; d = down; $annots .= ' /'.strtoupper($apmode); if (is_array($apdef)) { $annots .= ' <<'; foreach ($apdef as $apstate => $stream) { // reference to XObject that define the appearance for this mode-state $apsobjid = $this->_putAPXObject($c, $d, $stream); $annots .= ' /'.$apstate.' '.$apsobjid.' 0 R'; } $annots .= ' >>'; } else { // reference to XObject that define the appearance for this mode $apsobjid = $this->_putAPXObject($c, $d, $apdef); $annots .= ' '.$apsobjid.' 0 R'; } } } else { $annots .= $pl['opt']['ap']; } $annots .= ' >>'; } if (isset($pl['opt']['bs']) AND (is_array($pl['opt']['bs']))) { $annots .= ' /BS <<'; $annots .= ' /Type /Border'; if (isset($pl['opt']['bs']['w'])) { $annots .= ' /W '.intval($pl['opt']['bs']['w']); } $bstyles = array('S', 'D', 'B', 'I', 'U'); if (isset($pl['opt']['bs']['s']) AND in_array($pl['opt']['bs']['s'], $bstyles)) { $annots .= ' /S /'.$pl['opt']['bs']['s']; } if (isset($pl['opt']['bs']['d']) AND (is_array($pl['opt']['bs']['d']))) { $annots .= ' /D ['; foreach ($pl['opt']['bs']['d'] as $cord) { $annots .= ' '.intval($cord); } $annots .= ']'; } $annots .= ' >>'; } else { $annots .= ' /Border ['; if (isset($pl['opt']['border']) AND (count($pl['opt']['border']) >= 3)) { $annots .= intval($pl['opt']['border'][0]).' '; $annots .= intval($pl['opt']['border'][1]).' '; $annots .= intval($pl['opt']['border'][2]); if (isset($pl['opt']['border'][3]) AND is_array($pl['opt']['border'][3])) { $annots .= ' ['; foreach ($pl['opt']['border'][3] as $dash) { $annots .= intval($dash).' '; } $annots .= ']'; } } else { $annots .= '0 0 0'; } $annots .= ']'; } if (isset($pl['opt']['be']) AND (is_array($pl['opt']['be']))) { $annots .= ' /BE <<'; $bstyles = array('S', 'C'); if (isset($pl['opt']['be']['s']) AND in_array($pl['opt']['be']['s'], $markups)) { $annots .= ' /S /'.$pl['opt']['bs']['s']; } else { $annots .= ' /S /S'; } if (isset($pl['opt']['be']['i']) AND ($pl['opt']['be']['i'] >= 0) AND ($pl['opt']['be']['i'] <= 2)) { $annots .= ' /I '.sprintf(' %.4F', $pl['opt']['be']['i']); } $annots .= '>>'; } if (isset($pl['opt']['c']) AND (is_array($pl['opt']['c'])) AND !empty($pl['opt']['c'])) { $annots .= ' /C '.$this->getColorStringFromArray($pl['opt']['c']); } //$annots .= ' /StructParent '; //$annots .= ' /OC '; $markups = array('text', 'freetext', 'line', 'square', 'circle', 'polygon', 'polyline', 'highlight', 'underline', 'squiggly', 'strikeout', 'stamp', 'caret', 'ink', 'fileattachment', 'sound'); if (in_array(strtolower($pl['opt']['subtype']), $markups)) { // this is a markup type if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) { $annots .= ' /T '.$this->_textstring($pl['opt']['t'], $annot_obj_id); } //$annots .= ' /Popup '; if (isset($pl['opt']['ca'])) { $annots .= ' /CA '.sprintf('%.4F', floatval($pl['opt']['ca'])); } if (isset($pl['opt']['rc'])) { $annots .= ' /RC '.$this->_textstring($pl['opt']['rc'], $annot_obj_id); } $annots .= ' /CreationDate '.$this->_datestring($annot_obj_id); //$annots .= ' /IRT '; if (isset($pl['opt']['subj'])) { $annots .= ' /Subj '.$this->_textstring($pl['opt']['subj'], $annot_obj_id); } //$annots .= ' /RT '; //$annots .= ' /IT '; //$annots .= ' /ExData '; } $lineendings = array('Square', 'Circle', 'Diamond', 'OpenArrow', 'ClosedArrow', 'None', 'Butt', 'ROpenArrow', 'RClosedArrow', 'Slash'); // Annotation types switch (strtolower($pl['opt']['subtype'])) { case 'text': { if (isset($pl['opt']['open'])) { $annots .= ' /Open '. (strtolower($pl['opt']['open']) == 'true' ? 'true' : 'false'); } $iconsapp = array('Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph'); if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) { $annots .= ' /Name /'.$pl['opt']['name']; } else { $annots .= ' /Name /Note'; } $statemodels = array('Marked', 'Review'); if (isset($pl['opt']['statemodel']) AND in_array($pl['opt']['statemodel'], $statemodels)) { $annots .= ' /StateModel /'.$pl['opt']['statemodel']; } else { $pl['opt']['statemodel'] = 'Marked'; $annots .= ' /StateModel /'.$pl['opt']['statemodel']; } if ($pl['opt']['statemodel'] == 'Marked') { $states = array('Accepted', 'Unmarked'); } else { $states = array('Accepted', 'Rejected', 'Cancelled', 'Completed', 'None'); } if (isset($pl['opt']['state']) AND in_array($pl['opt']['state'], $states)) { $annots .= ' /State /'.$pl['opt']['state']; } else { if ($pl['opt']['statemodel'] == 'Marked') { $annots .= ' /State /Unmarked'; } else { $annots .= ' /State /None'; } } break; } case 'link': { if (is_string($pl['txt'])) { // external URI link $annots .= ' /A <_datastring($this->unhtmlentities($pl['txt']), $annot_obj_id).'>>'; } else { // internal link $l = $this->links[$pl['txt']]; if (isset($this->page_obj_id[($l[0])])) { $annots .= sprintf(' /Dest [%u 0 R /XYZ 0 %.2F null]', $this->page_obj_id[($l[0])], ($this->pagedim[$l[0]]['h'] - ($l[1] * $this->k))); } } $hmodes = array('N', 'I', 'O', 'P'); if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmodes)) { $annots .= ' /H /'.$pl['opt']['h']; } else { $annots .= ' /H /I'; } //$annots .= ' /PA '; //$annots .= ' /Quadpoints '; break; } case 'freetext': { if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) { $annots .= ' /DA ('.$pl['opt']['da'].')'; } if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) { $annots .= ' /Q '.intval($pl['opt']['q']); } if (isset($pl['opt']['rc'])) { $annots .= ' /RC '.$this->_textstring($pl['opt']['rc'], $annot_obj_id); } if (isset($pl['opt']['ds'])) { $annots .= ' /DS '.$this->_textstring($pl['opt']['ds'], $annot_obj_id); } if (isset($pl['opt']['cl']) AND is_array($pl['opt']['cl'])) { $annots .= ' /CL ['; foreach ($pl['opt']['cl'] as $cl) { $annots .= sprintf('%.4F ', $cl * $this->k); } $annots .= ']'; } $tfit = array('FreeText', 'FreeTextCallout', 'FreeTextTypeWriter'); if (isset($pl['opt']['it']) AND in_array($pl['opt']['it'], $tfit)) { $annots .= ' /IT /'.$pl['opt']['it']; } if (isset($pl['opt']['rd']) AND is_array($pl['opt']['rd'])) { $l = $pl['opt']['rd'][0] * $this->k; $r = $pl['opt']['rd'][1] * $this->k; $t = $pl['opt']['rd'][2] * $this->k; $b = $pl['opt']['rd'][3] * $this->k; $annots .= ' /RD ['.sprintf('%.2F %.2F %.2F %.2F', $l, $r, $t, $b).']'; } if (isset($pl['opt']['le']) AND in_array($pl['opt']['le'], $lineendings)) { $annots .= ' /LE /'.$pl['opt']['le']; } break; } case 'line': { break; } case 'square': { break; } case 'circle': { break; } case 'polygon': { break; } case 'polyline': { break; } case 'highlight': { break; } case 'underline': { break; } case 'squiggly': { break; } case 'strikeout': { break; } case 'stamp': { break; } case 'caret': { break; } case 'ink': { break; } case 'popup': { break; } case 'fileattachment': { if ($this->pdfa_mode) { // embedded files are not allowed in PDF/A mode break; } if (!isset($pl['opt']['fs'])) { break; } $filename = basename($pl['opt']['fs']); if (isset($this->embeddedfiles[$filename]['n'])) { $annots .= ' /FS <_datastring($filename, $annot_obj_id).' /EF <embeddedfiles[$filename]['n'].' 0 R>> >>'; $iconsapp = array('Graph', 'Paperclip', 'PushPin', 'Tag'); if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) { $annots .= ' /Name /'.$pl['opt']['name']; } else { $annots .= ' /Name /PushPin'; } } break; } case 'sound': { if (!isset($pl['opt']['fs'])) { break; } $filename = basename($pl['opt']['fs']); if (isset($this->embeddedfiles[$filename]['n'])) { // ... TO BE COMPLETED ... // /R /C /B /E /CO /CP $annots .= ' /Sound <_datastring($filename, $annot_obj_id).' /EF <embeddedfiles[$filename]['n'].' 0 R>> >>'; $iconsapp = array('Speaker', 'Mic'); if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) { $annots .= ' /Name /'.$pl['opt']['name']; } else { $annots .= ' /Name /Speaker'; } } break; } case 'movie': { break; } case 'widget': { $hmode = array('N', 'I', 'O', 'P', 'T'); if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmode)) { $annots .= ' /H /'.$pl['opt']['h']; } if (isset($pl['opt']['mk']) AND (is_array($pl['opt']['mk'])) AND !empty($pl['opt']['mk'])) { $annots .= ' /MK <<'; if (isset($pl['opt']['mk']['r'])) { $annots .= ' /R '.$pl['opt']['mk']['r']; } if (isset($pl['opt']['mk']['bc']) AND (is_array($pl['opt']['mk']['bc']))) { $annots .= ' /BC '.$this->getColorStringFromArray($pl['opt']['mk']['bc']); } if (isset($pl['opt']['mk']['bg']) AND (is_array($pl['opt']['mk']['bg']))) { $annots .= ' /BG '.$this->getColorStringFromArray($pl['opt']['mk']['bg']); } if (isset($pl['opt']['mk']['ca'])) { $annots .= ' /CA '.$pl['opt']['mk']['ca']; } if (isset($pl['opt']['mk']['rc'])) { $annots .= ' /RC '.$pl['opt']['mk']['rc']; } if (isset($pl['opt']['mk']['ac'])) { $annots .= ' /AC '.$pl['opt']['mk']['ac']; } if (isset($pl['opt']['mk']['i'])) { $info = $this->getImageBuffer($pl['opt']['mk']['i']); if ($info !== false) { $annots .= ' /I '.$info['n'].' 0 R'; } } if (isset($pl['opt']['mk']['ri'])) { $info = $this->getImageBuffer($pl['opt']['mk']['ri']); if ($info !== false) { $annots .= ' /RI '.$info['n'].' 0 R'; } } if (isset($pl['opt']['mk']['ix'])) { $info = $this->getImageBuffer($pl['opt']['mk']['ix']); if ($info !== false) { $annots .= ' /IX '.$info['n'].' 0 R'; } } if (isset($pl['opt']['mk']['if']) AND (is_array($pl['opt']['mk']['if'])) AND !empty($pl['opt']['mk']['if'])) { $annots .= ' /IF <<'; $if_sw = array('A', 'B', 'S', 'N'); if (isset($pl['opt']['mk']['if']['sw']) AND in_array($pl['opt']['mk']['if']['sw'], $if_sw)) { $annots .= ' /SW /'.$pl['opt']['mk']['if']['sw']; } $if_s = array('A', 'P'); if (isset($pl['opt']['mk']['if']['s']) AND in_array($pl['opt']['mk']['if']['s'], $if_s)) { $annots .= ' /S /'.$pl['opt']['mk']['if']['s']; } if (isset($pl['opt']['mk']['if']['a']) AND (is_array($pl['opt']['mk']['if']['a'])) AND !empty($pl['opt']['mk']['if']['a'])) { $annots .= sprintf(' /A [%.2F %.2F]', $pl['opt']['mk']['if']['a'][0], $pl['opt']['mk']['if']['a'][1]); } if (isset($pl['opt']['mk']['if']['fb']) AND ($pl['opt']['mk']['if']['fb'])) { $annots .= ' /FB true'; } $annots .= '>>'; } if (isset($pl['opt']['mk']['tp']) AND ($pl['opt']['mk']['tp'] >= 0) AND ($pl['opt']['mk']['tp'] <= 6)) { $annots .= ' /TP '.intval($pl['opt']['mk']['tp']); } $annots .= '>>'; } // end MK // --- Entries for field dictionaries --- if (isset($this->radiobutton_groups[$n][$pl['txt']])) { // set parent $annots .= ' /Parent '.$this->radiobutton_groups[$n][$pl['txt']].' 0 R'; } if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) { $annots .= ' /T '.$this->_datastring($pl['opt']['t'], $annot_obj_id); } if (isset($pl['opt']['tu']) AND is_string($pl['opt']['tu'])) { $annots .= ' /TU '.$this->_datastring($pl['opt']['tu'], $annot_obj_id); } if (isset($pl['opt']['tm']) AND is_string($pl['opt']['tm'])) { $annots .= ' /TM '.$this->_datastring($pl['opt']['tm'], $annot_obj_id); } if (isset($pl['opt']['ff'])) { if (is_array($pl['opt']['ff'])) { // array of bit settings $flag = 0; foreach($pl['opt']['ff'] as $val) { $flag += 1 << ($val - 1); } } else { $flag = intval($pl['opt']['ff']); } $annots .= ' /Ff '.$flag; } if (isset($pl['opt']['maxlen'])) { $annots .= ' /MaxLen '.intval($pl['opt']['maxlen']); } if (isset($pl['opt']['v'])) { $annots .= ' /V'; if (is_array($pl['opt']['v'])) { foreach ($pl['opt']['v'] AS $optval) { if (is_float($optval)) { $optval = sprintf('%.2F', $optval); } $annots .= ' '.$optval; } } else { $annots .= ' '.$this->_textstring($pl['opt']['v'], $annot_obj_id); } } if (isset($pl['opt']['dv'])) { $annots .= ' /DV'; if (is_array($pl['opt']['dv'])) { foreach ($pl['opt']['dv'] AS $optval) { if (is_float($optval)) { $optval = sprintf('%.2F', $optval); } $annots .= ' '.$optval; } } else { $annots .= ' '.$this->_textstring($pl['opt']['dv'], $annot_obj_id); } } if (isset($pl['opt']['rv'])) { $annots .= ' /RV'; if (is_array($pl['opt']['rv'])) { foreach ($pl['opt']['rv'] AS $optval) { if (is_float($optval)) { $optval = sprintf('%.2F', $optval); } $annots .= ' '.$optval; } } else { $annots .= ' '.$this->_textstring($pl['opt']['rv'], $annot_obj_id); } } if (isset($pl['opt']['a']) AND !empty($pl['opt']['a'])) { $annots .= ' /A << '.$pl['opt']['a'].' >>'; } if (isset($pl['opt']['aa']) AND !empty($pl['opt']['aa'])) { $annots .= ' /AA << '.$pl['opt']['aa'].' >>'; } if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) { $annots .= ' /DA ('.$pl['opt']['da'].')'; } if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) { $annots .= ' /Q '.intval($pl['opt']['q']); } if (isset($pl['opt']['opt']) AND (is_array($pl['opt']['opt'])) AND !empty($pl['opt']['opt'])) { $annots .= ' /Opt ['; foreach($pl['opt']['opt'] AS $copt) { if (is_array($copt)) { $annots .= ' ['.$this->_textstring($copt[0], $annot_obj_id).' '.$this->_textstring($copt[1], $annot_obj_id).']'; } else { $annots .= ' '.$this->_textstring($copt, $annot_obj_id); } } $annots .= ']'; } if (isset($pl['opt']['ti'])) { $annots .= ' /TI '.intval($pl['opt']['ti']); } if (isset($pl['opt']['i']) AND (is_array($pl['opt']['i'])) AND !empty($pl['opt']['i'])) { $annots .= ' /I ['; foreach($pl['opt']['i'] AS $copt) { $annots .= intval($copt).' '; } $annots .= ']'; } break; } case 'screen': { break; } case 'printermark': { break; } case 'trapnet': { break; } case 'watermark': { break; } case '3d': { break; } default: { break; } } $annots .= '>>'; // create new annotation object $this->_out($this->_getobj($annot_obj_id)."\n".$annots."\n".'endobj'); if ($formfield AND !isset($this->radiobutton_groups[$n][$pl['txt']])) { // store reference of form object $this->form_obj_id[] = $annot_obj_id; } } } } // end for each page } /** * Put appearance streams XObject used to define annotation's appearance states. * @param $w (int) annotation width * @param $h (int) annotation height * @param $stream (string) appearance stream * @return int object ID * @protected * @since 4.8.001 (2009-09-09) */ protected function _putAPXObject($w=0, $h=0, $stream='') { $stream = trim($stream); $out = $this->_getobj()."\n"; $this->xobjects['AX'.$this->n] = array('n' => $this->n); $out .= '<<'; $out .= ' /Type /XObject'; $out .= ' /Subtype /Form'; $out .= ' /FormType 1'; if ($this->compress) { $stream = gzcompress($stream); $out .= ' /Filter /FlateDecode'; } $rect = sprintf('%.2F %.2F', $w, $h); $out .= ' /BBox [0 0 '.$rect.']'; $out .= ' /Matrix [1 0 0 1 0 0]'; $out .= ' /Resources 2 0 R'; $stream = $this->_getrawstream($stream); $out .= ' /Length '.strlen($stream); $out .= ' >>'; $out .= ' stream'."\n".$stream."\n".'endstream'; $out .= "\n".'endobj'; $this->_out($out); return $this->n; } /** * Get ULONG from string (Big Endian 32-bit unsigned integer). * @param $str (string) string from where to extract value * @param $offset (int) point from where to read the data * @return int 32 bit value * @author Nicola Asuni * @protected * @since 5.2.000 (2010-06-02) */ protected function _getULONG($str, $offset) { $v = unpack('Ni', substr($str, $offset, 4)); return $v['i']; } /** * Get USHORT from string (Big Endian 16-bit unsigned integer). * @param $str (string) string from where to extract value * @param $offset (int) point from where to read the data * @return int 16 bit value * @author Nicola Asuni * @protected * @since 5.2.000 (2010-06-02) */ protected function _getUSHORT($str, $offset) { $v = unpack('ni', substr($str, $offset, 2)); return $v['i']; } /** * Get SHORT from string (Big Endian 16-bit signed integer). * @param $str (string) string from where to extract value * @param $offset (int) point from where to read the data * @return int 16 bit value * @author Nicola Asuni * @protected * @since 5.2.000 (2010-06-02) */ protected function _getSHORT($str, $offset) { $v = unpack('si', substr($str, $offset, 2)); return $v['i']; } /** * Get FWORD from string (Big Endian 16-bit signed integer). * @param $str (string) string from where to extract value * @param $offset (int) point from where to read the data * @return int 16 bit value * @author Nicola Asuni * @protected * @since 5.9.123 (2011-09-30) */ protected function _getFWORD($str, $offset) { $v = $this->_getUSHORT($str, $offset); if ($v > 0x7fff) { $v -= 0x10000; } return $v; } /** * Get UFWORD from string (Big Endian 16-bit unsigned integer). * @param $str (string) string from where to extract value * @param $offset (int) point from where to read the data * @return int 16 bit value * @author Nicola Asuni * @protected * @since 5.9.123 (2011-09-30) */ protected function _getUFWORD($str, $offset) { $v = $this->_getUSHORT($str, $offset); return $v; } /** * Get FIXED from string (32-bit signed fixed-point number (16.16). * @param $str (string) string from where to extract value * @param $offset (int) point from where to read the data * @return int 16 bit value * @author Nicola Asuni * @protected * @since 5.9.123 (2011-09-30) */ protected function _getFIXED($str, $offset) { // mantissa $m = $this->_getFWORD($str, $offset); // fraction $f = $this->_getUSHORT($str, ($offset + 2)); $v = floatval(''.$m.'.'.$f.''); return $v; } /** * Get BYTE from string (8-bit unsigned integer). * @param $str (string) String from where to extract value. * @param $offset (int) Point from where to read the data. * @return int 8 bit value * @author Nicola Asuni * @protected * @since 5.2.000 (2010-06-02) */ protected function _getBYTE($str, $offset) { $v = unpack('Ci', substr($str, $offset, 1)); return $v['i']; } /** * Update the CIDToGIDMap string with a new value. * @param $map (string) CIDToGIDMap. * @param $cid (int) CID value. * @param $gid (int) GID value. * @return (string) CIDToGIDMap. * @author Nicola Asuni * @protected * @since 5.9.123 (2011-09-29) */ protected function updateCIDtoGIDmap($map, $cid, $gid) { if (($cid >= 0) AND ($cid <= 0xFFFF) AND ($gid >= 0)) { if ($gid > 0xFFFF) { $gid -= 0x10000; } $map[($cid * 2)] = chr($gid >> 8); $map[(($cid * 2) + 1)] = chr($gid & 0xFF); } return $map; } /** * Convert and add the selected TrueType or Type1 font to the fonts folder (that must be writeable). * @param $fontfile (string) TrueType or Type1 font file (full path). * @param $fonttype (string) Font type. Leave empty for autodetect mode. Valid values are: TrueTypeUnicode, TrueType, Type1, CID0JP = CID-0 Japanese, CID0KR = CID-0 Korean, CID0CS = CID-0 Chinese Simplified, CID0CT = CID-0 Chinese Traditional. * @param $enc (string) Name of the encoding table to use. Leave empty for default mode. Omit this parameter for TrueType Unicode and symbolic fonts like Symbol or ZapfDingBats. * @param $flags (int) Unsigned 32-bit integer containing flags specifying various characteristics of the font (PDF32000:2008 - 9.8.2 Font Descriptor Flags): +1 for fixed font; +4 for symbol or +32 for non-symbol; +64 for italic. Fixed and Italic mode are generally autodetected so you have to set it to 32 = non-symbolic font (default) or 4 = symbolic font. * @param $outpath (string) Output path for generated font files (must be writeable by the web server). Leave empty for default font folder. * @return (string) TCPDF font name. * @author Nicola Asuni * @public * @since 5.9.123 (2010-09-30) */ public function addTTFfont($fontfile, $fonttype='', $enc='', $flags=32, $outpath='') { if (!$this->file_exists($fontfile)) { $this->Error('Could not find file: '.$fontfile.''); } // font metrics $fmetric = array(); // build new font name for TCPDF compatibility $font_path_parts = pathinfo($fontfile); if (!isset($font_path_parts['filename'])) { $font_path_parts['filename'] = substr($font_path_parts['basename'], 0, -(strlen($font_path_parts['extension']) + 1)); } $font_name = strtolower($font_path_parts['filename']); $font_name = preg_replace('/[^a-z0-9_]/', '', $font_name); $search = array('bold', 'oblique', 'italic', 'regular'); $replace = array('b', 'i', 'i', ''); $font_name = str_replace($search, $replace, $font_name); if (empty($font_name)) { // set generic name $font_name = 'tcpdffont'; } // set output path if (empty($outpath)) { $outpath = $this->_getfontpath(); } // check if this font already exist if ($this->file_exists($outpath.$font_name.'.php')) { // this font already exist (delete it from fonts folder to rebuild it) return $font_name; } $fmetric['file'] = $font_name.'.z'; $fmetric['ctg'] = $font_name.'.ctg.z'; // get font data $font = file_get_contents($fontfile); $fmetric['originalsize'] = strlen($font); // autodetect font type if (empty($fonttype)) { if ($this->_getULONG($font, 0) == 0x10000) { // True Type (Unicode or not) $fonttype = 'TrueTypeUnicode'; } elseif (substr($font, 0, 4) == 'OTTO') { // Open Type (Unicode or not) $this->Error('Unsupported font format: OpenType with CFF data.'); } else { // Type 1 $fonttype = 'Type1'; } } // set font type switch ($fonttype) { case 'CID0CT': case 'CID0CS': case 'CID0KR': case 'CID0JP': { $fmetric['type'] = 'cidfont0'; break; } case 'Type1': { $fmetric['type'] = 'Type1'; if (empty($enc) AND (($flags & 4) == 0)) { $enc = 'cp1252'; } break; } case 'TrueType': { $fmetric['type'] = 'TrueType'; break; } case 'TrueTypeUnicode': default: { $fmetric['type'] = 'TrueTypeUnicode'; break; } } // set encoding maps (if any) $fmetric['enc'] = preg_replace('/[^A-Za-z0-9_\-]/', '', $enc); $fmetric['diff'] = ''; if (($fmetric['type'] == 'TrueType') OR ($fmetric['type'] == 'Type1')) { if (!empty($enc) AND ($enc != 'cp1252') AND isset($this->encmaps->encmap[$enc])) { // build differences from reference encoding $enc_ref = $this->encmaps->encmap['cp1252']; $enc_target = $this->encmaps->encmap[$enc]; $last = 0; for ($i = 32; $i <= 255; ++$i) { if ($enc_target != $enc_ref[$i]) { if ($i != ($last + 1)) { $fmetric['diff'] .= $i.' '; } $last = $i; $fmetric['diff'] .= '/'.$enc_target[$i].' '; } } } } // parse the font by type if ($fmetric['type'] == 'Type1') { // ---------- TYPE 1 ---------- // read first segment $a = unpack('Cmarker/Ctype/Vsize', substr($font, 0, 6)); if ($a['marker'] != 128) { $this->Error('Font file is not a valid binary Type1'); } $fmetric['size1'] = $a['size']; $data = substr($font, 6, $fmetric['size1']); // read second segment $a = unpack('Cmarker/Ctype/Vsize', substr($font, (6 + $fmetric['size1']), 6)); if ($a['marker'] != 128) { $this->Error('Font file is not a valid binary Type1'); } $fmetric['size2'] = $a['size']; $encrypted = substr($font, (12 + $fmetric['size1']), $fmetric['size2']); $data .= $encrypted; // store compressed font $fp = fopen($outpath.$fmetric['file'], 'wb'); fwrite($fp, gzcompress($data)); fclose($fp); // get font info $fmetric['Flags'] = $flags; preg_match ('#/FullName[\s]*\(([^\)]*)#', $font, $matches); $fmetric['name'] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $matches[1]); preg_match('#/FontBBox[\s]*{([^}]*)#', $font, $matches); $fmetric['bbox'] = trim($matches[1]); $bv = explode(' ', $fmetric['bbox']); $fmetric['Ascent'] = intval($bv[3]); $fmetric['Descent'] = intval($bv[1]); preg_match('#/ItalicAngle[\s]*([0-9\+\-]*)#', $font, $matches); $fmetric['italicAngle'] = intval($matches[1]); if ($fmetric['italicAngle'] != 0) { $fmetric['Flags'] |= 64; } preg_match('#/UnderlinePosition[\s]*([0-9\+\-]*)#', $font, $matches); $fmetric['underlinePosition'] = intval($matches[1]); preg_match('#/UnderlineThickness[\s]*([0-9\+\-]*)#', $font, $matches); $fmetric['underlineThickness'] = intval($matches[1]); preg_match('#/isFixedPitch[\s]*([^\s]*)#', $font, $matches); if ($matches[1] == 'true') { $fmetric['Flags'] |= 1; } // get internal map $imap = array(); if (preg_match_all('#dup[\s]([0-9]+)[\s]*/([^\s]*)[\s]put#sU', $font, $fmap, PREG_SET_ORDER) > 0) { foreach ($fmap as $v) { $imap[$v[2]] = $v[1]; } } // decrypt eexec encrypted part $r = 55665; // eexec encryption constant $c1 = 52845; $c2 = 22719; $elen = strlen($encrypted); $eplain = ''; for ($i = 0; $i < $elen; ++$i) { $chr = ord($encrypted[$i]); $eplain .= chr($chr ^ ($r >> 8)); $r = ((($chr + $r) * $c1 + $c2) % 65536); } if (preg_match('#/ForceBold[\s]*([^\s]*)#', $eplain, $matches) > 0) { if ($matches[1] == 'true') { $fmetric['Flags'] |= 0x40000; } } if (preg_match('#/StdVW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) { $fmetric['StemV'] = intval($matches[1]); } else { $fmetric['StemV'] = 70; } if (preg_match('#/StdHW[\s]*\[([^\]]*)#', $eplain, $matches) > 0) { $fmetric['StemH'] = intval($matches[1]); } else { $fmetric['StemH'] = 30; } if (preg_match('#/BlueValues[\s]*\[([^\]]*)#', $eplain, $matches) > 0) { $bv = explode(' ', $matches[1]); if (count($bv) >= 6) { $v1 = intval($bv[2]); $v2 = intval($bv[4]); if ($v1 <= $v2) { $fmetric['XHeight'] = $v1; $fmetric['CapHeight'] = $v2; } else { $fmetric['XHeight'] = $v2; $fmetric['CapHeight'] = $v1; } } else { $fmetric['XHeight'] = 450; $fmetric['CapHeight'] = 700; } } else { $fmetric['XHeight'] = 450; $fmetric['CapHeight'] = 700; } // get the number of random bytes at the beginning of charstrings if (preg_match('#/lenIV[\s]*([0-9]*)#', $eplain, $matches) > 0) { $lenIV = intval($matches[1]); } else { $lenIV = 4; } $fmetric['Leading'] = 0; // get charstring data $eplain = substr($eplain, (strpos($eplain, '/CharStrings') + 1)); preg_match_all('#/([A-Za-z0-9\.]*)[\s][0-9]+[\s]RD[\s](.*)[\s]ND#sU', $eplain, $matches, PREG_SET_ORDER); if (!empty($enc) AND isset($this->encmaps->encmap[$enc])) { $enc_map = $this->encmaps->encmap[$enc]; } else { $enc_map = false; } $fmetric['cw'] = ''; $fmetric['MaxWidth'] = 0; $cwidths = array(); foreach ($matches as $k => $v) { $cid = 0; if (isset($imap[$v[1]])) { $cid = $imap[$v[1]]; } elseif ($enc_map !== false) { $cid = array_search($v[1], $enc_map); if ($cid === false) { $cid = 0; } elseif ($cid > 1000) { $cid -= 1000; } } // decrypt charstring encrypted part $r = 4330; // charstring encryption constant $c1 = 52845; $c2 = 22719; $cd = $v[2]; $clen = strlen($cd); $ccom = array(); for ($i = 0; $i < $clen; ++$i) { $chr = ord($cd[$i]); $ccom[] = ($chr ^ ($r >> 8)); $r = ((($chr + $r) * $c1 + $c2) % 65536); } // decode numbers $cdec = array(); $ck = 0; $i = $lenIV; while ($i < $clen) { if ($ccom[$i] < 32) { $cdec[$ck] = $ccom[$i]; if (($ck > 0) AND ($cdec[$ck] == 13)) { // hsbw command: update width $cwidths[$cid] = $cdec[($ck - 1)]; } ++$i; } elseif (($ccom[$i] >= 32) AND ($ccom[$i] <= 246)) { $cdec[$ck] = ($ccom[$i] - 139); ++$i; } elseif (($ccom[$i] >= 247) AND ($ccom[$i] <= 250)) { $cdec[$ck] = ((($ccom[$i] - 247) * 256) + $ccom[($i + 1)] + 108); $i += 2; } elseif (($ccom[$i] >= 251) AND ($ccom[$i] <= 254)) { $cdec[$ck] = ((-($ccom[$i] - 251) * 256) - $ccom[($i + 1)] - 108); $i += 2; } elseif ($ccom[$i] == 255) { $sval = chr($ccom[($i + 1)]).chr($ccom[($i + 2)]).chr($ccom[($i + 3)]).chr($ccom[($i + 4)]); $vsval = unpack('li', $sval); $cdec[$ck] = $vsval['i']; $i += 5; } ++$ck; } } // end for each matches $fmetric['MissingWidth'] = $cwidths[0]; $fmetric['MaxWidth'] = $fmetric['MissingWidth']; $fmetric['AvgWidth'] = 0; // set chars widths for ($cid = 0; $cid <= 255; ++$cid) { if (isset($cwidths[$cid])) { if ($cwidths[$cid] > $fmetric['MaxWidth']) { $fmetric['MaxWidth'] = $cwidths[$cid]; } $fmetric['AvgWidth'] += $cwidths[$cid]; $fmetric['cw'] .= ','.$cid.'=>'.$cwidths[$cid]; } else { $fmetric['cw'] .= ','.$cid.'=>'.$fmetric['MissingWidth']; } } $fmetric['AvgWidth'] = round($fmetric['AvgWidth'] / count($cwidths)); } else { // ---------- TRUE TYPE ---------- if ($fmetric['type'] != 'cidfont0') { // store compressed font $fp = fopen($outpath.$fmetric['file'], 'wb'); fwrite($fp, gzcompress($font)); fclose($fp); } $offset = 0; // offset position of the font data if ($this->_getULONG($font, $offset) != 0x10000) { // sfnt version must be 0x00010000 for TrueType version 1.0. return $font; } $offset += 4; // get number of tables $numTables = $this->_getUSHORT($font, $offset); $offset += 2; // skip searchRange, entrySelector and rangeShift $offset += 6; // tables array $table = array(); // ---------- get tables ---------- for ($i = 0; $i < $numTables; ++$i) { // get table info $tag = substr($font, $offset, 4); $offset += 4; $table[$tag] = array(); $table[$tag]['checkSum'] = $this->_getULONG($font, $offset); $offset += 4; $table[$tag]['offset'] = $this->_getULONG($font, $offset); $offset += 4; $table[$tag]['length'] = $this->_getULONG($font, $offset); $offset += 4; } // check magicNumber $offset = $table['head']['offset'] + 12; if ($this->_getULONG($font, $offset) != 0x5F0F3CF5) { // magicNumber must be 0x5F0F3CF5 return $font; } $offset += 4; $offset += 2; // skip flags // get FUnits $fmetric['unitsPerEm'] = $this->_getUSHORT($font, $offset); $offset += 2; // units ratio constant $urk = (1000 / $fmetric['unitsPerEm']); $offset += 16; // skip created, modified $xMin = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; $yMin = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; $xMax = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; $yMax = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; $fmetric['bbox'] = ''.$xMin.' '.$yMin.' '.$xMax.' '.$yMax.''; $macStyle = $this->_getUSHORT($font, $offset); $offset += 2; // PDF font flags $fmetric['Flags'] = $flags; if (($macStyle & 2) == 2) { // italic flag $fmetric['Flags'] |= 64; } // get offset mode (indexToLocFormat : 0 = short, 1 = long) $offset = $table['head']['offset'] + 50; $short_offset = ($this->_getSHORT($font, $offset) == 0); $offset += 2; // get the offsets to the locations of the glyphs in the font, relative to the beginning of the glyphData table $indexToLoc = array(); $offset = $table['loca']['offset']; if ($short_offset) { // short version $tot_num_glyphs = ($table['loca']['length'] / 2); // numGlyphs + 1 for ($i = 0; $i < $tot_num_glyphs; ++$i) { $indexToLoc[$i] = $this->_getUSHORT($font, $offset) * 2; $offset += 2; } } else { // long version $tot_num_glyphs = ($table['loca']['length'] / 4); // numGlyphs + 1 for ($i = 0; $i < $tot_num_glyphs; ++$i) { $indexToLoc[$i] = $this->_getULONG($font, $offset); $offset += 4; } } // get glyphs indexes of chars from cmap table $offset = $table['cmap']['offset'] + 2; $numEncodingTables = $this->_getUSHORT($font, $offset); $offset += 2; $encodingTables = array(); for ($i = 0; $i < $numEncodingTables; ++$i) { $encodingTables[$i]['platformID'] = $this->_getUSHORT($font, $offset); $offset += 2; $encodingTables[$i]['encodingID'] = $this->_getUSHORT($font, $offset); $offset += 2; $encodingTables[$i]['offset'] = $this->_getULONG($font, $offset); $offset += 4; } // ---------- get os/2 metrics ---------- $offset = $table['OS/2']['offset']; $offset += 2; // skip version // xAvgCharWidth $fmetric['AvgWidth'] = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; // usWeightClass $usWeightClass = round($this->_getUFWORD($font, $offset) * $urk); // estimate StemV and StemH (400 = usWeightClass for Normal - Regular font) $fmetric['StemV'] = round((70 * $usWeightClass) / 400); $fmetric['StemH'] = round((30 * $usWeightClass) / 400); $offset += 2; $offset += 2; // usWidthClass $fsType = $this->_getSHORT($font, $offset); $offset += 2; if ($fsType == 2) { $this->Error('This Font cannot be modified, embedded or exchanged in any manner without first obtaining permission of the legal owner.'); } // ---------- get font name ---------- $fmetric['name'] = ''; $offset = $table['name']['offset']; $offset += 2; // skip Format selector (=0). // Number of NameRecords that follow n. $numNameRecords = $this->_getUSHORT($font, $offset); $offset += 2; // Offset to start of string storage (from start of table). $stringStorageOffset = $this->_getUSHORT($font, $offset); $offset += 2; for ($i = 0; $i < $numNameRecords; ++$i) { $offset += 6; // skip Platform ID, Platform-specific encoding ID, Language ID. // Name ID. $nameID = $this->_getUSHORT($font, $offset); $offset += 2; if ($nameID == 6) { // String length (in bytes). $stringLength = $this->_getUSHORT($font, $offset); $offset += 2; // String offset from start of storage area (in bytes). $stringOffset = $this->_getUSHORT($font, $offset); $offset += 2; $offset = ($table['name']['offset'] + $stringStorageOffset + $stringOffset); $fmetric['name'] = substr($font, $offset, $stringLength); $fmetric['name'] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $fmetric['name']); break; } else { $offset += 4; // skip String length, String offset } } if (empty($fmetric['name'])) { $fmetric['name'] = $font_name; } // ---------- get post data ---------- $offset = $table['post']['offset']; $offset += 4; // skip Format Type $fmetric['italicAngle'] = $this->_getFIXED($font, $offset); $offset += 4; $fmetric['underlinePosition'] = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; $fmetric['underlineThickness'] = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; $isFixedPitch = ($this->_getULONG($font, $offset) == 0) ? false : true; $offset += 2; if ($isFixedPitch) { $fmetric['Flags'] |= 1; } // ---------- get hhea data ---------- $offset = $table['hhea']['offset']; $offset += 4; // skip Table version number // Ascender $fmetric['Ascent'] = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; // Descender $fmetric['Descent'] = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; // LineGap $fmetric['Leading'] = round($this->_getFWORD($font, $offset) * $urk); $offset += 2; // advanceWidthMax $fmetric['MaxWidth'] = round($this->_getUFWORD($font, $offset) * $urk); $offset += 2; $offset += 22; // skip some values // get the number of hMetric entries in hmtx table $numberOfHMetrics = $this->_getUSHORT($font, $offset); // ---------- get maxp data ---------- $offset = $table['maxp']['offset']; $offset += 4; // skip Table version number // get the the number of glyphs in the font. $numGlyphs = $this->_getUSHORT($font, $offset); // ---------- get CIDToGIDMap ---------- $ctg = array(); foreach ($encodingTables as $enctable) { if (($enctable['platformID'] == 3) AND ($enctable['encodingID'] == 0)) { $modesymbol = true; } else { $modesymbol = false; } $offset = $table['cmap']['offset'] + $enctable['offset']; $format = $this->_getUSHORT($font, $offset); $offset += 2; switch ($format) { case 0: { // Format 0: Byte encoding table $offset += 4; // skip length and version/language for ($c = 0; $c < 256; ++$c) { $g = $this->_getBYTE($font, $offset); $ctg[$c] = $g; ++$offset; } break; } case 2: { // Format 2: High-byte mapping through table $offset += 4; // skip length and version/language $numSubHeaders = 0; for ($i = 0; $i < 256; ++$i) { // Array that maps high bytes to subHeaders: value is subHeader index * 8. $subHeaderKeys[$i] = ($this->_getUSHORT($font, $offset) / 8); $offset += 2; if ($numSubHeaders < $subHeaderKeys[$i]) { $numSubHeaders = $subHeaderKeys[$i]; } } // the number of subHeaders is equal to the max of subHeaderKeys + 1 ++$numSubHeaders; // read subHeader structures $subHeaders = array(); $numGlyphIndexArray = 0; for ($k = 0; $k < $numSubHeaders; ++$k) { $subHeaders[$k]['firstCode'] = $this->_getUSHORT($font, $offset); $offset += 2; $subHeaders[$k]['entryCount'] = $this->_getUSHORT($font, $offset); $offset += 2; $subHeaders[$k]['idDelta'] = $this->_getSHORT($font, $offset); $offset += 2; $subHeaders[$k]['idRangeOffset'] = $this->_getUSHORT($font, $offset); $offset += 2; $subHeaders[$k]['idRangeOffset'] -= (2 + (($numSubHeaders - $k - 1) * 8)); $subHeaders[$k]['idRangeOffset'] /= 2; $numGlyphIndexArray += $subHeaders[$k]['entryCount']; } for ($k = 0; $k < $numGlyphIndexArray; ++$k) { $glyphIndexArray[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } for ($i = 0; $i < 256; ++$i) { $k = $subHeaderKeys[$i]; if ($k == 0) { // one byte code $c = $i; $g = $glyphIndexArray[0]; $ctg[$c] = $g; } else { // two bytes code $start_byte = $subHeaders[$k]['firstCode']; $end_byte = $start_byte + $subHeaders[$k]['entryCount']; for ($j = $start_byte; $j < $end_byte; ++$j) { // combine high and low bytes $c = (($i << 8) + $j); $idRangeOffset = ($subHeaders[$k]['idRangeOffset'] + $j - $subHeaders[$k]['firstCode']); $g = $glyphIndexArray[$idRangeOffset]; $g += ($idDelta[$k] - 65536); if ($g < 0) { $g = 0; } $ctg[$c] = $g; } } } break; } case 4: { // Format 4: Segment mapping to delta values $length = $this->_getUSHORT($font, $offset); $offset += 2; $offset += 2; // skip version/language $segCount = ($this->_getUSHORT($font, $offset) / 2); $offset += 2; $offset += 6; // skip searchRange, entrySelector, rangeShift $endCount = array(); // array of end character codes for each segment for ($k = 0; $k < $segCount; ++$k) { $endCount[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } $offset += 2; // skip reservedPad $startCount = array(); // array of start character codes for each segment for ($k = 0; $k < $segCount; ++$k) { $startCount[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } $idDelta = array(); // delta for all character codes in segment for ($k = 0; $k < $segCount; ++$k) { $idDelta[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } $idRangeOffset = array(); // Offsets into glyphIdArray or 0 for ($k = 0; $k < $segCount; ++$k) { $idRangeOffset[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } $gidlen = ($length / 2) - 8 - (4 * $segCount); $glyphIdArray = array(); // glyph index array for ($k = 0; $k < $gidlen; ++$k) { $glyphIdArray[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } for ($k = 0; $k < $segCount; ++$k) { for ($c = $startCount[$k]; $c <= $endCount[$k]; ++$c) { if ($idRangeOffset[$k] == 0) { $g = $c; } else { $gid = (($idRangeOffset[$k] / 2) + ($c - $startCount[$k]) - ($segCount - $k)); $g = $glyphIdArray[$gid]; } $g += ($idDelta[$k] - 65536); if ($g < 0) { $g = 0; } $ctg[$c] = $g; } } break; } case 6: { // Format 6: Trimmed table mapping $offset += 4; // skip length and version/language $firstCode = $this->_getUSHORT($font, $offset); $offset += 2; $entryCount = $this->_getUSHORT($font, $offset); $offset += 2; for ($k = 0; $k < $entryCount; ++$k) { $c = ($k + $firstCode); $g = $this->_getUSHORT($font, $offset); $ctg[$c] = $g; $offset += 2; } break; } case 8: { // Format 8: Mixed 16-bit and 32-bit coverage $offset += 10; // skip reserved, length and version/language for ($k = 0; $k < 8192; ++$k) { $is32[$k] = $this->_getBYTE($font, $offset); ++$offset; } $nGroups = $this->_getULONG($font, $offset); $offset += 4; for ($i = 0; $i < $nGroups; ++$i) { $startCharCode = $this->_getULONG($font, $offset); $offset += 4; $endCharCode = $this->_getULONG($font, $offset); $offset += 4; $startGlyphID = $this->_getULONG($font, $offset); $offset += 4; for ($k = $startCharCode; $k <= $endCharCode; ++$k) { $is32idx = floor($c / 8); if ((isset($is32[$is32idx])) AND (($is32[$is32idx] & (1 << (7 - ($c % 8)))) == 0)) { $c = $k; } else { // 32 bit format // convert to decimal (http://www.unicode.org/faq//utf_bom.html#utf16-4) //LEAD_OFFSET = (0xD800 - (0x10000 >> 10)) = 55232 //SURROGATE_OFFSET = (0x10000 - (0xD800 << 10) - 0xDC00) = -56613888 $c = ((55232 + ($k >> 10)) << 10) + (0xDC00 + ($k & 0x3FF)) -56613888; } $ctg[$c] = $g; ++$startGlyphID; } } break; } case 10: { // Format 10: Trimmed array $offset += 10; // skip reserved, length and version/language $startCharCode = $this->_getULONG($font, $offset); $offset += 4; $numChars = $this->_getULONG($font, $offset); $offset += 4; for ($k = 0; $k < $numChars; ++$k) { $c = ($k + $startCharCode); $g = $this->_getUSHORT($font, $offset); $ctg[$c] = $g; $offset += 2; } break; } case 12: { // Format 12: Segmented coverage $offset += 10; // skip length and version/language $nGroups = $this->_getULONG($font, $offset); $offset += 4; for ($k = 0; $k < $nGroups; ++$k) { $startCharCode = $this->_getULONG($font, $offset); $offset += 4; $endCharCode = $this->_getULONG($font, $offset); $offset += 4; $startGlyphCode = $this->_getULONG($font, $offset); $offset += 4; for ($c = $startCharCode; $c <= $endCharCode; ++$c) { $ctg[$c] = $startGlyphCode; ++$startGlyphCode; } } break; } case 13: { // Format 13: Many-to-one range mappings // to be implemented ... break; } case 14: { // Format 14: Unicode Variation Sequences // to be implemented ... break; } } } if (!isset($ctg[0])) { $ctg[0] = 0; } // get xHeight (height of x) $offset = ($table['glyf']['offset'] + $indexToLoc[$ctg[120]] + 4); $yMin = $this->_getFWORD($font, $offset); $offset += 4; $yMax = $this->_getFWORD($font, $offset); $offset += 2; $fmetric['XHeight'] = round(($yMax - $yMin) * $urk); // get CapHeight (height of H) $offset = ($table['glyf']['offset'] + $indexToLoc[$ctg[72]] + 4); $yMin = $this->_getFWORD($font, $offset); $offset += 4; $yMax = $this->_getFWORD($font, $offset); $offset += 2; $fmetric['CapHeight'] = round(($yMax - $yMin) * $urk); // ceate widths array $cw = array(); $offset = $table['hmtx']['offset']; for ($i = 0 ; $i < $numberOfHMetrics; ++$i) { $cw[$i] = round($this->_getUFWORD($font, $offset) * $urk); $offset += 4; // skip lsb } if ($numberOfHMetrics < $numGlyphs) { // fill missing widths with the last value $cw = array_pad($cw, $numGlyphs, $cw[($numberOfHMetrics - 1)]); } $fmetric['MissingWidth'] = $cw[0]; $fmetric['cw'] = ''; for ($cid = 0; $cid <= 65535; ++$cid) { if (isset($ctg[$cid]) AND isset($cw[$ctg[$cid]])) { $fmetric['cw'] .= ','.$cid.'=>'.$cw[$ctg[$cid]]; } } } // end of true type if (($fmetric['type'] == 'TrueTypeUnicode') AND (count($ctg) == 256)) { $fmetric['type'] == 'TrueType'; } // ---------- create php font file ---------- $pfile = '<'.'?'.'php'."\n"; $pfile .= '// TCPDF FONT FILE DESCRIPTION'."\n"; $pfile .= '$type=\''.$fmetric['type'].'\';'."\n"; $pfile .= '$name=\''.$fmetric['name'].'\';'."\n"; $pfile .= '$up='.$fmetric['underlinePosition'].';'."\n"; $pfile .= '$ut='.$fmetric['underlineThickness'].';'."\n"; if ($fmetric['MissingWidth'] > 0) { $pfile .= '$dw='.$fmetric['MissingWidth'].';'."\n"; } else { $pfile .= '$dw='.$fmetric['AvgWidth'].';'."\n"; } $pfile .= '$diff=\''.$fmetric['diff'].'\';'."\n"; if ($fmetric['type'] == 'Type1') { // Type 1 $pfile .= '$enc=\''.$fmetric['enc'].'\';'."\n"; $pfile .= '$file=\''.$fmetric['file'].'\';'."\n"; $pfile .= '$size1='.$fmetric['size1'].';'."\n"; $pfile .= '$size2='.$fmetric['size2'].';'."\n"; } else { $pfile .= '$originalsize='.$fmetric['originalsize'].';'."\n"; if ($fmetric['type'] == 'cidfont0') { // CID-0 switch ($fonttype) { case 'CID0JP': { $pfile .= '// Japanese'."\n"; $pfile .= '$enc=\'UniJIS-UTF16-H\';'."\n"; $pfile .= '$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'Japan1\',\'Supplement\'=>5);'."\n"; $pfile .= 'include(dirname(__FILE__).\'/uni2cid_aj16.php\');'."\n"; break; } case 'CID0KR': { $pfile .= '// Korean'."\n"; $pfile .= '$enc=\'UniKS-UTF16-H\';'."\n"; $pfile .= '$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'Korea1\',\'Supplement\'=>0);'."\n"; $pfile .= 'include(dirname(__FILE__).\'/uni2cid_ak12.php\');'."\n"; break; } case 'CID0CS': { $pfile .= '// Chinese Simplified'."\n"; $pfile .= '$enc=\'UniGB-UTF16-H\';'."\n"; $pfile .= '$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'GB1\',\'Supplement\'=>2);'."\n"; $pfile .= 'include(dirname(__FILE__).\'/uni2cid_ag15.php\');'."\n"; break; } case 'CID0CT': default: { $pfile .= '// Chinese Traditional'."\n"; $pfile .= '$enc=\'UniCNS-UTF16-H\';'."\n"; $pfile .= '$cidinfo=array(\'Registry\'=>\'Adobe\', \'Ordering\'=>\'CNS1\',\'Supplement\'=>0);'."\n"; $pfile .= 'include(dirname(__FILE__).\'/uni2cid_aj16.php\');'."\n"; break; } } } else { // TrueType $pfile .= '$enc=\''.$fmetric['enc'].'\';'."\n"; $pfile .= '$file=\''.$fmetric['file'].'\';'."\n"; $pfile .= '$ctg=\''.$fmetric['ctg'].'\';'."\n"; // create CIDToGIDMap $cidtogidmap = str_pad('', 131072, "\x00"); // (256 * 256 * 2) = 131072 foreach ($ctg as $cid => $gid) { $cidtogidmap = $this->updateCIDtoGIDmap($cidtogidmap, $cid, $ctg[$cid]); } // store compressed CIDToGIDMap $fp = fopen($outpath.$fmetric['ctg'], 'wb'); fwrite($fp, gzcompress($cidtogidmap)); fclose($fp); } } $pfile .= '$desc=array('; $pfile .= '\'Flags\'=>'.$fmetric['Flags'].','; $pfile .= '\'FontBBox\'=>\'['.$fmetric['bbox'].']\','; $pfile .= '\'ItalicAngle\'=>'.$fmetric['italicAngle'].','; $pfile .= '\'Ascent\'=>'.$fmetric['Ascent'].','; $pfile .= '\'Descent\'=>'.$fmetric['Descent'].','; $pfile .= '\'Leading\'=>'.$fmetric['Leading'].','; $pfile .= '\'CapHeight\'=>'.$fmetric['CapHeight'].','; $pfile .= '\'XHeight\'=>'.$fmetric['XHeight'].','; $pfile .= '\'StemV\'=>'.$fmetric['StemV'].','; $pfile .= '\'StemH\'=>'.$fmetric['StemH'].','; $pfile .= '\'AvgWidth\'=>'.$fmetric['AvgWidth'].','; $pfile .= '\'MaxWidth\'=>'.$fmetric['MaxWidth'].','; $pfile .= '\'MissingWidth\'=>'.$fmetric['MissingWidth'].''; $pfile .= ');'."\n"; $pfile .= '$cw=array('.substr($fmetric['cw'], 1).');'."\n"; $pfile .= '// --- EOF ---'."\n"; // store file $fp = fopen($outpath.$font_name.'.php', 'w'); fwrite($fp, $pfile); fclose($fp); // return TCPDF font name return $font_name; } /** * Returns a subset of the TrueType font data without the unused glyphs. * @param $font (string) TrueType font data. * @param $subsetchars (array) Array of used characters (the glyphs to keep). * @return (string) A subset of TrueType font data without the unused glyphs. * @author Nicola Asuni * @protected * @since 5.2.000 (2010-06-02) */ protected function _getTrueTypeFontSubset($font, $subsetchars) { ksort($subsetchars); $offset = 0; // offset position of the font data if ($this->_getULONG($font, $offset) != 0x10000) { // sfnt version must be 0x00010000 for TrueType version 1.0. return $font; } $offset += 4; // get number of tables $numTables = $this->_getUSHORT($font, $offset); $offset += 2; // skip searchRange, entrySelector and rangeShift $offset += 6; // tables array $table = array(); // for each table for ($i = 0; $i < $numTables; ++$i) { // get table info $tag = substr($font, $offset, 4); $offset += 4; $table[$tag] = array(); $table[$tag]['checkSum'] = $this->_getULONG($font, $offset); $offset += 4; $table[$tag]['offset'] = $this->_getULONG($font, $offset); $offset += 4; $table[$tag]['length'] = $this->_getULONG($font, $offset); $offset += 4; } // check magicNumber $offset = $table['head']['offset'] + 12; if ($this->_getULONG($font, $offset) != 0x5F0F3CF5) { // magicNumber must be 0x5F0F3CF5 return $font; } $offset += 4; // get offset mode (indexToLocFormat : 0 = short, 1 = long) $offset = $table['head']['offset'] + 50; $short_offset = ($this->_getSHORT($font, $offset) == 0); $offset += 2; // get the offsets to the locations of the glyphs in the font, relative to the beginning of the glyphData table $indexToLoc = array(); $offset = $table['loca']['offset']; if ($short_offset) { // short version $tot_num_glyphs = ($table['loca']['length'] / 2); // numGlyphs + 1 for ($i = 0; $i < $tot_num_glyphs; ++$i) { $indexToLoc[$i] = $this->_getUSHORT($font, $offset) * 2; $offset += 2; } } else { // long version $tot_num_glyphs = ($table['loca']['length'] / 4); // numGlyphs + 1 for ($i = 0; $i < $tot_num_glyphs; ++$i) { $indexToLoc[$i] = $this->_getULONG($font, $offset); $offset += 4; } } // get glyphs indexes of chars from cmap table $subsetglyphs = array(); // glyph IDs on key $subsetglyphs[0] = true; // character codes that do not correspond to any glyph in the font should be mapped to glyph index 0 $offset = $table['cmap']['offset'] + 2; $numEncodingTables = $this->_getUSHORT($font, $offset); $offset += 2; $encodingTables = array(); for ($i = 0; $i < $numEncodingTables; ++$i) { $encodingTables[$i]['platformID'] = $this->_getUSHORT($font, $offset); $offset += 2; $encodingTables[$i]['encodingID'] = $this->_getUSHORT($font, $offset); $offset += 2; $encodingTables[$i]['offset'] = $this->_getULONG($font, $offset); $offset += 4; } foreach ($encodingTables as $enctable) { if (($enctable['platformID'] == 3) AND ($enctable['encodingID'] == 0)) { $modesymbol = true; } else { $modesymbol = false; } $offset = $table['cmap']['offset'] + $enctable['offset']; $format = $this->_getUSHORT($font, $offset); $offset += 2; switch ($format) { case 0: { // Format 0: Byte encoding table $offset += 4; // skip length and version/language for ($c = 0; $c < 256; ++$c) { if (isset($subsetchars[$c])) { $g = $this->_getBYTE($font, $offset); $subsetglyphs[$g] = true; } ++$offset; } break; } case 2: { // Format 2: High-byte mapping through table $offset += 4; // skip length and version/language $numSubHeaders = 0; for ($i = 0; $i < 256; ++$i) { // Array that maps high bytes to subHeaders: value is subHeader index * 8. $subHeaderKeys[$i] = ($this->_getUSHORT($font, $offset) / 8); $offset += 2; if ($numSubHeaders < $subHeaderKeys[$i]) { $numSubHeaders = $subHeaderKeys[$i]; } } // the number of subHeaders is equal to the max of subHeaderKeys + 1 ++$numSubHeaders; // read subHeader structures $subHeaders = array(); $numGlyphIndexArray = 0; for ($k = 0; $k < $numSubHeaders; ++$k) { $subHeaders[$k]['firstCode'] = $this->_getUSHORT($font, $offset); $offset += 2; $subHeaders[$k]['entryCount'] = $this->_getUSHORT($font, $offset); $offset += 2; $subHeaders[$k]['idDelta'] = $this->_getSHORT($font, $offset); $offset += 2; $subHeaders[$k]['idRangeOffset'] = $this->_getUSHORT($font, $offset); $offset += 2; $subHeaders[$k]['idRangeOffset'] -= (2 + (($numSubHeaders - $k - 1) * 8)); $subHeaders[$k]['idRangeOffset'] /= 2; $numGlyphIndexArray += $subHeaders[$k]['entryCount']; } for ($k = 0; $k < $numGlyphIndexArray; ++$k) { $glyphIndexArray[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } for ($i = 0; $i < 256; ++$i) { $k = $subHeaderKeys[$i]; if ($k == 0) { // one byte code $c = $i; if (isset($subsetchars[$c])) { $g = $glyphIndexArray[0]; $subsetglyphs[$g] = true; } } else { // two bytes code $start_byte = $subHeaders[$k]['firstCode']; $end_byte = $start_byte + $subHeaders[$k]['entryCount']; for ($j = $start_byte; $j < $end_byte; ++$j) { // combine high and low bytes $c = (($i << 8) + $j); if (isset($subsetchars[$c])) { $idRangeOffset = ($subHeaders[$k]['idRangeOffset'] + $j - $subHeaders[$k]['firstCode']); $g = $glyphIndexArray[$idRangeOffset]; $g += ($idDelta[$k] - 65536); if ($g < 0) { $g = 0; } $subsetglyphs[$g] = true; } } } } break; } case 4: { // Format 4: Segment mapping to delta values $length = $this->_getUSHORT($font, $offset); $offset += 2; $offset += 2; // skip version/language $segCount = ($this->_getUSHORT($font, $offset) / 2); $offset += 2; $offset += 6; // skip searchRange, entrySelector, rangeShift $endCount = array(); // array of end character codes for each segment for ($k = 0; $k < $segCount; ++$k) { $endCount[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } $offset += 2; // skip reservedPad $startCount = array(); // array of start character codes for each segment for ($k = 0; $k < $segCount; ++$k) { $startCount[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } $idDelta = array(); // delta for all character codes in segment for ($k = 0; $k < $segCount; ++$k) { $idDelta[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } $idRangeOffset = array(); // Offsets into glyphIdArray or 0 for ($k = 0; $k < $segCount; ++$k) { $idRangeOffset[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } $gidlen = ($length / 2) - 8 - (4 * $segCount); $glyphIdArray = array(); // glyph index array for ($k = 0; $k < $gidlen; ++$k) { $glyphIdArray[$k] = $this->_getUSHORT($font, $offset); $offset += 2; } for ($k = 0; $k < $segCount; ++$k) { for ($c = $startCount[$k]; $c <= $endCount[$k]; ++$c) { if (isset($subsetchars[$c])) { if ($idRangeOffset[$k] == 0) { $g = $c; } else { $gid = (($idRangeOffset[$k] / 2) + ($c - $startCount[$k]) - ($segCount - $k)); $g = $glyphIdArray[$gid]; } $g += ($idDelta[$k] - 65536); if ($g < 0) { $g = 0; } $subsetglyphs[$g] = true; } } } break; } case 6: { // Format 6: Trimmed table mapping $offset += 4; // skip length and version/language $firstCode = $this->_getUSHORT($font, $offset); $offset += 2; $entryCount = $this->_getUSHORT($font, $offset); $offset += 2; for ($k = 0; $k < $entryCount; ++$k) { $c = ($k + $firstCode); if (isset($subsetchars[$c])) { $g = $this->_getUSHORT($font, $offset); $subsetglyphs[$g] = true; } $offset += 2; } break; } case 8: { // Format 8: Mixed 16-bit and 32-bit coverage $offset += 10; // skip reserved, length and version/language for ($k = 0; $k < 8192; ++$k) { $is32[$k] = $this->_getBYTE($font, $offset); ++$offset; } $nGroups = $this->_getULONG($font, $offset); $offset += 4; for ($i = 0; $i < $nGroups; ++$i) { $startCharCode = $this->_getULONG($font, $offset); $offset += 4; $endCharCode = $this->_getULONG($font, $offset); $offset += 4; $startGlyphID = $this->_getULONG($font, $offset); $offset += 4; for ($k = $startCharCode; $k <= $endCharCode; ++$k) { $is32idx = floor($c / 8); if ((isset($is32[$is32idx])) AND (($is32[$is32idx] & (1 << (7 - ($c % 8)))) == 0)) { $c = $k; } else { // 32 bit format // convert to decimal (http://www.unicode.org/faq//utf_bom.html#utf16-4) //LEAD_OFFSET = (0xD800 - (0x10000 >> 10)) = 55232 //SURROGATE_OFFSET = (0x10000 - (0xD800 << 10) - 0xDC00) = -56613888 $c = ((55232 + ($k >> 10)) << 10) + (0xDC00 + ($k & 0x3FF)) -56613888; } if (isset($subsetchars[$c])) { $subsetglyphs[$startGlyphID] = true; } ++$startGlyphID; } } break; } case 10: { // Format 10: Trimmed array $offset += 10; // skip reserved, length and version/language $startCharCode = $this->_getULONG($font, $offset); $offset += 4; $numChars = $this->_getULONG($font, $offset); $offset += 4; for ($k = 0; $k < $numChars; ++$k) { $c = ($k + $startCharCode); if (isset($subsetchars[$c])) { $g = $this->_getUSHORT($font, $offset); $subsetglyphs[$g] = true; } $offset += 2; } break; } case 12: { // Format 12: Segmented coverage $offset += 10; // skip length and version/language $nGroups = $this->_getULONG($font, $offset); $offset += 4; for ($k = 0; $k < $nGroups; ++$k) { $startCharCode = $this->_getULONG($font, $offset); $offset += 4; $endCharCode = $this->_getULONG($font, $offset); $offset += 4; $startGlyphCode = $this->_getULONG($font, $offset); $offset += 4; for ($c = $startCharCode; $c <= $endCharCode; ++$c) { if (isset($subsetchars[$c])) { $subsetglyphs[$startGlyphCode] = true; } ++$startGlyphCode; } } break; } case 13: { // Format 13: Many-to-one range mappings // to be implemented ... break; } case 14: { // Format 14: Unicode Variation Sequences // to be implemented ... break; } } } // include all parts of composite glyphs $new_sga = $subsetglyphs; while (!empty($new_sga)) { $sga = $new_sga; $new_sga = array(); foreach ($sga as $key => $val) { if (isset($indexToLoc[$key])) { $offset = ($table['glyf']['offset'] + $indexToLoc[$key]); $numberOfContours = $this->_getSHORT($font, $offset); $offset += 2; if ($numberOfContours < 0) { // composite glyph $offset += 8; // skip xMin, yMin, xMax, yMax do { $flags = $this->_getUSHORT($font, $offset); $offset += 2; $glyphIndex = $this->_getUSHORT($font, $offset); $offset += 2; if (!isset($subsetglyphs[$glyphIndex])) { // add missing glyphs $new_sga[$glyphIndex] = true; } // skip some bytes by case if ($flags & 1) { $offset += 4; } else { $offset += 2; } if ($flags & 8) { $offset += 2; } elseif ($flags & 64) { $offset += 4; } elseif ($flags & 128) { $offset += 8; } } while ($flags & 32); } } } $subsetglyphs += $new_sga; } // sort glyphs by key (and remove duplicates) ksort($subsetglyphs); // build new glyf and loca tables $glyf = ''; $loca = ''; $offset = 0; $glyf_offset = $table['glyf']['offset']; for ($i = 0; $i < $tot_num_glyphs; ++$i) { if (isset($subsetglyphs[$i])) { $length = ($indexToLoc[($i + 1)] - $indexToLoc[$i]); $glyf .= substr($font, ($glyf_offset + $indexToLoc[$i]), $length); } else { $length = 0; } if ($short_offset) { $loca .= pack('n', ($offset / 2)); } else { $loca .= pack('N', $offset); } $offset += $length; } // array of table names to preserve (loca and glyf tables will be added later) // the cmap table is not needed and shall not be present, since the mapping from character codes to glyph descriptions is provided separately $table_names = array ('head', 'hhea', 'hmtx', 'maxp', 'cvt ', 'fpgm', 'prep'); // minimum required table names // get the tables to preserve $offset = 12; foreach ($table as $tag => $val) { if (in_array($tag, $table_names)) { $table[$tag]['data'] = substr($font, $table[$tag]['offset'], $table[$tag]['length']); if ($tag == 'head') { // set the checkSumAdjustment to 0 $table[$tag]['data'] = substr($table[$tag]['data'], 0, 8)."\x0\x0\x0\x0".substr($table[$tag]['data'], 12); } $pad = 4 - ($table[$tag]['length'] % 4); if ($pad != 4) { // the length of a table must be a multiple of four bytes $table[$tag]['length'] += $pad; $table[$tag]['data'] .= str_repeat("\x0", $pad); } $table[$tag]['offset'] = $offset; $offset += $table[$tag]['length']; // check sum is not changed (so keep the following line commented) //$table[$tag]['checkSum'] = $this->_getTTFtableChecksum($table[$tag]['data'], $table[$tag]['length']); } else { unset($table[$tag]); } } // add loca $table['loca']['data'] = $loca; $table['loca']['length'] = strlen($loca); $pad = 4 - ($table['loca']['length'] % 4); if ($pad != 4) { // the length of a table must be a multiple of four bytes $table['loca']['length'] += $pad; $table['loca']['data'] .= str_repeat("\x0", $pad); } $table['loca']['offset'] = $offset; $table['loca']['checkSum'] = $this->_getTTFtableChecksum($table['loca']['data'], $table['loca']['length']); $offset += $table['loca']['length']; // add glyf $table['glyf']['data'] = $glyf; $table['glyf']['length'] = strlen($glyf); $pad = 4 - ($table['glyf']['length'] % 4); if ($pad != 4) { // the length of a table must be a multiple of four bytes $table['glyf']['length'] += $pad; $table['glyf']['data'] .= str_repeat("\x0", $pad); } $table['glyf']['offset'] = $offset; $table['glyf']['checkSum'] = $this->_getTTFtableChecksum($table['glyf']['data'], $table['glyf']['length']); // rebuild font $font = ''; $font .= pack('N', 0x10000); // sfnt version $numTables = count($table); $font .= pack('n', $numTables); // numTables $entrySelector = floor(log($numTables, 2)); $searchRange = pow(2, $entrySelector) * 16; $rangeShift = ($numTables * 16) - $searchRange; $font .= pack('n', $searchRange); // searchRange $font .= pack('n', $entrySelector); // entrySelector $font .= pack('n', $rangeShift); // rangeShift $offset = ($numTables * 16); foreach ($table as $tag => $data) { $font .= $tag; // tag $font .= pack('N', $data['checkSum']); // checkSum $font .= pack('N', ($data['offset'] + $offset)); // offset $font .= pack('N', $data['length']); // length } foreach ($table as $data) { $font .= $data['data']; } // set checkSumAdjustment on head table $checkSumAdjustment = 0xB1B0AFBA - $this->_getTTFtableChecksum($font, strlen($font)); $font = substr($font, 0, $table['head']['offset'] + 8).pack('N', $checkSumAdjustment).substr($font, $table['head']['offset'] + 12); return $font; } /** * Returs the checksum of a TTF table. * @param $table (string) table to check * @param $length (int) length of table in bytes * @return int checksum * @author Nicola Asuni * @protected * @since 5.2.000 (2010-06-02) */ protected function _getTTFtableChecksum($table, $length) { $sum = 0; $tlen = ($length / 4); $offset = 0; for ($i = 0; $i < $tlen; ++$i) { $v = unpack('Ni', substr($table, $offset, 4)); $sum += $v['i']; $offset += 4; } $sum = unpack('Ni', pack('N', $sum)); return $sum['i']; } /** * Outputs font widths * @param $font (array) font data * @param $cidoffset (int) offset for CID values * @return PDF command string for font widths * @author Nicola Asuni * @protected * @since 4.4.000 (2008-12-07) */ protected function _putfontwidths($font, $cidoffset=0) { ksort($font['cw']); $rangeid = 0; $range = array(); $prevcid = -2; $prevwidth = -1; $interval = false; // for each character foreach ($font['cw'] as $cid => $width) { $cid -= $cidoffset; if ($font['subset'] AND ($cid > 255) AND (!isset($font['subsetchars'][$cid]))) { // ignore the unused characters (font subsetting) continue; } if ($width != $font['dw']) { if ($cid == ($prevcid + 1)) { // consecutive CID if ($width == $prevwidth) { if ($width == $range[$rangeid][0]) { $range[$rangeid][] = $width; } else { array_pop($range[$rangeid]); // new range $rangeid = $prevcid; $range[$rangeid] = array(); $range[$rangeid][] = $prevwidth; $range[$rangeid][] = $width; } $interval = true; $range[$rangeid]['interval'] = true; } else { if ($interval) { // new range $rangeid = $cid; $range[$rangeid] = array(); $range[$rangeid][] = $width; } else { $range[$rangeid][] = $width; } $interval = false; } } else { // new range $rangeid = $cid; $range[$rangeid] = array(); $range[$rangeid][] = $width; $interval = false; } $prevcid = $cid; $prevwidth = $width; } } // optimize ranges $prevk = -1; $nextk = -1; $prevint = false; foreach ($range as $k => $ws) { $cws = count($ws); if (($k == $nextk) AND (!$prevint) AND ((!isset($ws['interval'])) OR ($cws < 4))) { if (isset($range[$k]['interval'])) { unset($range[$k]['interval']); } $range[$prevk] = array_merge($range[$prevk], $range[$k]); unset($range[$k]); } else { $prevk = $k; } $nextk = $k + $cws; if (isset($ws['interval'])) { if ($cws > 3) { $prevint = true; } else { $prevint = false; } unset($range[$k]['interval']); --$nextk; } else { $prevint = false; } } // output data $w = ''; foreach ($range as $k => $ws) { if (count(array_count_values($ws)) == 1) { // interval mode is more compact $w .= ' '.$k.' '.($k + count($ws) - 1).' '.$ws[0]; } else { // range mode $w .= ' '.$k.' [ '.implode(' ', $ws).' ]'; } } return '/W ['.$w.' ]'; } /** * Output fonts. * @author Nicola Asuni * @protected */ protected function _putfonts() { $nf = $this->n; foreach ($this->diffs as $diff) { //Encodings $this->_newobj(); $this->_out('<< /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.'] >>'."\n".'endobj'); } $mqr = $this->get_mqr(); $this->set_mqr(false); foreach ($this->FontFiles as $file => $info) { // search and get font file to embedd $fontdir = $info['fontdir']; $file = strtolower($file); $fontfile = ''; // search files on various directories if (($fontdir !== false) AND $this->file_exists($fontdir.$file)) { $fontfile = $fontdir.$file; } elseif ($this->file_exists($this->_getfontpath().$file)) { $fontfile = $this->_getfontpath().$file; } elseif ($this->file_exists($file)) { $fontfile = $file; } if (!$this->empty_string($fontfile)) { $font = file_get_contents($fontfile); $compressed = (substr($file, -2) == '.z'); if ((!$compressed) AND (isset($info['length2']))) { $header = (ord($font{0}) == 128); if ($header) { // strip first binary header $font = substr($font, 6); } if ($header AND (ord($font[$info['length1']]) == 128)) { // strip second binary header $font = substr($font, 0, $info['length1']).substr($font, ($info['length1'] + 6)); } } elseif ($info['subset'] AND ((!$compressed) OR ($compressed AND function_exists('gzcompress')))) { if ($compressed) { // uncompress font $font = gzuncompress($font); } // merge subset characters $subsetchars = array(); // used chars foreach ($info['fontkeys'] as $fontkey) { $fontinfo = $this->getFontBuffer($fontkey); $subsetchars += $fontinfo['subsetchars']; } // rebuild a font subset $font = $this->_getTrueTypeFontSubset($font, $subsetchars); // calculate new font length $info['length1'] = strlen($font); if ($compressed) { // recompress font $font = gzcompress($font); } } $this->_newobj(); $this->FontFiles[$file]['n'] = $this->n; $stream = $this->_getrawstream($font); $out = '<< /Length '.strlen($stream); if ($compressed) { $out .= ' /Filter /FlateDecode'; } $out .= ' /Length1 '.$info['length1']; if (isset($info['length2'])) { $out .= ' /Length2 '.$info['length2'].' /Length3 0'; } $out .= ' >>'; $out .= ' stream'."\n".$stream."\n".'endstream'; $out .= "\n".'endobj'; $this->_out($out); } } $this->set_mqr($mqr); foreach ($this->fontkeys as $k) { //Font objects $font = $this->getFontBuffer($k); $type = $font['type']; $name = $font['name']; if ($type == 'core') { // standard core font $out = $this->_getobj($this->font_obj_ids[$k])."\n"; $out .= '<annotation_fonts[$k] = $font['i']; } $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } elseif (($type == 'Type1') OR ($type == 'TrueType')) { // additional Type1 or TrueType font $out = $this->_getobj($this->font_obj_ids[$k])."\n"; $out .= '<n + 1).' 0 R'; $out .= ' /FontDescriptor '.($this->n + 2).' 0 R'; if ($font['enc']) { if (isset($font['diff'])) { $out .= ' /Encoding '.($nf + $font['diff']).' 0 R'; } else { $out .= ' /Encoding /WinAnsiEncoding'; } } $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); // Widths $this->_newobj(); $s = '['; for ($i = 32; $i < 256; ++$i) { $s .= $font['cw'][$i].' '; } $s .= ']'; $s .= "\n".'endobj'; $this->_out($s); //Descriptor $this->_newobj(); $s = '< $fdv) { if (is_float($fdv)) { $fdv = sprintf('%.3F', $fdv); } $s .= ' /'.$fdk.' '.$fdv.''; } if (!$this->empty_string($font['file'])) { $s .= ' /FontFile'.($type == 'Type1' ? '' : '2').' '.$this->FontFiles[$font['file']]['n'].' 0 R'; } $s .= '>>'; $s .= "\n".'endobj'; $this->_out($s); } else { // additional types $mtd = '_put'.strtolower($type); if (!method_exists($this, $mtd)) { $this->Error('Unsupported font type: '.$type); } $this->$mtd($font); } } } /** * Adds unicode fonts.
    * Based on PDF Reference 1.3 (section 5) * @param $font (array) font data * @protected * @author Nicola Asuni * @since 1.52.0.TC005 (2005-01-05) */ protected function _puttruetypeunicode($font) { $fontname = ''; if ($font['subset']) { // change name for font subsetting $subtag = sprintf('%06u', $font['i']); $subtag = strtr($subtag, '0123456789', 'ABCDEFGHIJ'); $fontname .= $subtag.'+'; } $fontname .= $font['name']; // Type0 Font // A composite font composed of other fonts, organized hierarchically $out = $this->_getobj($this->font_obj_ids[$font['fontkey']])."\n"; $out .= '<< /Type /Font'; $out .= ' /Subtype /Type0'; $out .= ' /BaseFont /'.$fontname; $out .= ' /Name /F'.$font['i']; $out .= ' /Encoding /'.$font['enc']; $out .= ' /ToUnicode '.($this->n + 1).' 0 R'; $out .= ' /DescendantFonts ['.($this->n + 2).' 0 R]'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); // ToUnicode map for Identity-H $stream = "/CIDInit /ProcSet findresource begin\n"; $stream .= "12 dict begin\n"; $stream .= "begincmap\n"; $stream .= "/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n"; $stream .= "/CMapName /Adobe-Identity-UCS def\n"; $stream .= "/CMapType 2 def\n"; $stream .= "/WMode 0 def\n"; $stream .= "1 begincodespacerange\n"; $stream .= "<0000> \n"; $stream .= "endcodespacerange\n"; $stream .= "100 beginbfrange\n"; $stream .= "<0000> <00ff> <0000>\n"; $stream .= "<0100> <01ff> <0100>\n"; $stream .= "<0200> <02ff> <0200>\n"; $stream .= "<0300> <03ff> <0300>\n"; $stream .= "<0400> <04ff> <0400>\n"; $stream .= "<0500> <05ff> <0500>\n"; $stream .= "<0600> <06ff> <0600>\n"; $stream .= "<0700> <07ff> <0700>\n"; $stream .= "<0800> <08ff> <0800>\n"; $stream .= "<0900> <09ff> <0900>\n"; $stream .= "<0a00> <0aff> <0a00>\n"; $stream .= "<0b00> <0bff> <0b00>\n"; $stream .= "<0c00> <0cff> <0c00>\n"; $stream .= "<0d00> <0dff> <0d00>\n"; $stream .= "<0e00> <0eff> <0e00>\n"; $stream .= "<0f00> <0fff> <0f00>\n"; $stream .= "<1000> <10ff> <1000>\n"; $stream .= "<1100> <11ff> <1100>\n"; $stream .= "<1200> <12ff> <1200>\n"; $stream .= "<1300> <13ff> <1300>\n"; $stream .= "<1400> <14ff> <1400>\n"; $stream .= "<1500> <15ff> <1500>\n"; $stream .= "<1600> <16ff> <1600>\n"; $stream .= "<1700> <17ff> <1700>\n"; $stream .= "<1800> <18ff> <1800>\n"; $stream .= "<1900> <19ff> <1900>\n"; $stream .= "<1a00> <1aff> <1a00>\n"; $stream .= "<1b00> <1bff> <1b00>\n"; $stream .= "<1c00> <1cff> <1c00>\n"; $stream .= "<1d00> <1dff> <1d00>\n"; $stream .= "<1e00> <1eff> <1e00>\n"; $stream .= "<1f00> <1fff> <1f00>\n"; $stream .= "<2000> <20ff> <2000>\n"; $stream .= "<2100> <21ff> <2100>\n"; $stream .= "<2200> <22ff> <2200>\n"; $stream .= "<2300> <23ff> <2300>\n"; $stream .= "<2400> <24ff> <2400>\n"; $stream .= "<2500> <25ff> <2500>\n"; $stream .= "<2600> <26ff> <2600>\n"; $stream .= "<2700> <27ff> <2700>\n"; $stream .= "<2800> <28ff> <2800>\n"; $stream .= "<2900> <29ff> <2900>\n"; $stream .= "<2a00> <2aff> <2a00>\n"; $stream .= "<2b00> <2bff> <2b00>\n"; $stream .= "<2c00> <2cff> <2c00>\n"; $stream .= "<2d00> <2dff> <2d00>\n"; $stream .= "<2e00> <2eff> <2e00>\n"; $stream .= "<2f00> <2fff> <2f00>\n"; $stream .= "<3000> <30ff> <3000>\n"; $stream .= "<3100> <31ff> <3100>\n"; $stream .= "<3200> <32ff> <3200>\n"; $stream .= "<3300> <33ff> <3300>\n"; $stream .= "<3400> <34ff> <3400>\n"; $stream .= "<3500> <35ff> <3500>\n"; $stream .= "<3600> <36ff> <3600>\n"; $stream .= "<3700> <37ff> <3700>\n"; $stream .= "<3800> <38ff> <3800>\n"; $stream .= "<3900> <39ff> <3900>\n"; $stream .= "<3a00> <3aff> <3a00>\n"; $stream .= "<3b00> <3bff> <3b00>\n"; $stream .= "<3c00> <3cff> <3c00>\n"; $stream .= "<3d00> <3dff> <3d00>\n"; $stream .= "<3e00> <3eff> <3e00>\n"; $stream .= "<3f00> <3fff> <3f00>\n"; $stream .= "<4000> <40ff> <4000>\n"; $stream .= "<4100> <41ff> <4100>\n"; $stream .= "<4200> <42ff> <4200>\n"; $stream .= "<4300> <43ff> <4300>\n"; $stream .= "<4400> <44ff> <4400>\n"; $stream .= "<4500> <45ff> <4500>\n"; $stream .= "<4600> <46ff> <4600>\n"; $stream .= "<4700> <47ff> <4700>\n"; $stream .= "<4800> <48ff> <4800>\n"; $stream .= "<4900> <49ff> <4900>\n"; $stream .= "<4a00> <4aff> <4a00>\n"; $stream .= "<4b00> <4bff> <4b00>\n"; $stream .= "<4c00> <4cff> <4c00>\n"; $stream .= "<4d00> <4dff> <4d00>\n"; $stream .= "<4e00> <4eff> <4e00>\n"; $stream .= "<4f00> <4fff> <4f00>\n"; $stream .= "<5000> <50ff> <5000>\n"; $stream .= "<5100> <51ff> <5100>\n"; $stream .= "<5200> <52ff> <5200>\n"; $stream .= "<5300> <53ff> <5300>\n"; $stream .= "<5400> <54ff> <5400>\n"; $stream .= "<5500> <55ff> <5500>\n"; $stream .= "<5600> <56ff> <5600>\n"; $stream .= "<5700> <57ff> <5700>\n"; $stream .= "<5800> <58ff> <5800>\n"; $stream .= "<5900> <59ff> <5900>\n"; $stream .= "<5a00> <5aff> <5a00>\n"; $stream .= "<5b00> <5bff> <5b00>\n"; $stream .= "<5c00> <5cff> <5c00>\n"; $stream .= "<5d00> <5dff> <5d00>\n"; $stream .= "<5e00> <5eff> <5e00>\n"; $stream .= "<5f00> <5fff> <5f00>\n"; $stream .= "<6000> <60ff> <6000>\n"; $stream .= "<6100> <61ff> <6100>\n"; $stream .= "<6200> <62ff> <6200>\n"; $stream .= "<6300> <63ff> <6300>\n"; $stream .= "endbfrange\n"; $stream .= "100 beginbfrange\n"; $stream .= "<6400> <64ff> <6400>\n"; $stream .= "<6500> <65ff> <6500>\n"; $stream .= "<6600> <66ff> <6600>\n"; $stream .= "<6700> <67ff> <6700>\n"; $stream .= "<6800> <68ff> <6800>\n"; $stream .= "<6900> <69ff> <6900>\n"; $stream .= "<6a00> <6aff> <6a00>\n"; $stream .= "<6b00> <6bff> <6b00>\n"; $stream .= "<6c00> <6cff> <6c00>\n"; $stream .= "<6d00> <6dff> <6d00>\n"; $stream .= "<6e00> <6eff> <6e00>\n"; $stream .= "<6f00> <6fff> <6f00>\n"; $stream .= "<7000> <70ff> <7000>\n"; $stream .= "<7100> <71ff> <7100>\n"; $stream .= "<7200> <72ff> <7200>\n"; $stream .= "<7300> <73ff> <7300>\n"; $stream .= "<7400> <74ff> <7400>\n"; $stream .= "<7500> <75ff> <7500>\n"; $stream .= "<7600> <76ff> <7600>\n"; $stream .= "<7700> <77ff> <7700>\n"; $stream .= "<7800> <78ff> <7800>\n"; $stream .= "<7900> <79ff> <7900>\n"; $stream .= "<7a00> <7aff> <7a00>\n"; $stream .= "<7b00> <7bff> <7b00>\n"; $stream .= "<7c00> <7cff> <7c00>\n"; $stream .= "<7d00> <7dff> <7d00>\n"; $stream .= "<7e00> <7eff> <7e00>\n"; $stream .= "<7f00> <7fff> <7f00>\n"; $stream .= "<8000> <80ff> <8000>\n"; $stream .= "<8100> <81ff> <8100>\n"; $stream .= "<8200> <82ff> <8200>\n"; $stream .= "<8300> <83ff> <8300>\n"; $stream .= "<8400> <84ff> <8400>\n"; $stream .= "<8500> <85ff> <8500>\n"; $stream .= "<8600> <86ff> <8600>\n"; $stream .= "<8700> <87ff> <8700>\n"; $stream .= "<8800> <88ff> <8800>\n"; $stream .= "<8900> <89ff> <8900>\n"; $stream .= "<8a00> <8aff> <8a00>\n"; $stream .= "<8b00> <8bff> <8b00>\n"; $stream .= "<8c00> <8cff> <8c00>\n"; $stream .= "<8d00> <8dff> <8d00>\n"; $stream .= "<8e00> <8eff> <8e00>\n"; $stream .= "<8f00> <8fff> <8f00>\n"; $stream .= "<9000> <90ff> <9000>\n"; $stream .= "<9100> <91ff> <9100>\n"; $stream .= "<9200> <92ff> <9200>\n"; $stream .= "<9300> <93ff> <9300>\n"; $stream .= "<9400> <94ff> <9400>\n"; $stream .= "<9500> <95ff> <9500>\n"; $stream .= "<9600> <96ff> <9600>\n"; $stream .= "<9700> <97ff> <9700>\n"; $stream .= "<9800> <98ff> <9800>\n"; $stream .= "<9900> <99ff> <9900>\n"; $stream .= "<9a00> <9aff> <9a00>\n"; $stream .= "<9b00> <9bff> <9b00>\n"; $stream .= "<9c00> <9cff> <9c00>\n"; $stream .= "<9d00> <9dff> <9d00>\n"; $stream .= "<9e00> <9eff> <9e00>\n"; $stream .= "<9f00> <9fff> <9f00>\n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= "endbfrange\n"; $stream .= "56 beginbfrange\n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= " \n"; $stream .= "endbfrange\n"; $stream .= "endcmap\n"; $stream .= "CMapName currentdict /CMap defineresource pop\n"; $stream .= "end\n"; $stream .= "end"; // ToUnicode Object $this->_newobj(); $stream = ($this->compress) ? gzcompress($stream) : $stream; $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; $stream = $this->_getrawstream($stream); $this->_out('<<'.$filter.'/Length '.strlen($stream).'>> stream'."\n".$stream."\n".'endstream'."\n".'endobj'); // CIDFontType2 // A CIDFont whose glyph descriptions are based on TrueType font technology $oid = $this->_newobj(); $out = '<< /Type /Font'; $out .= ' /Subtype /CIDFontType2'; $out .= ' /BaseFont /'.$fontname; // A dictionary containing entries that define the character collection of the CIDFont. $cidinfo = '/Registry '.$this->_datastring($font['cidinfo']['Registry'], $oid); $cidinfo .= ' /Ordering '.$this->_datastring($font['cidinfo']['Ordering'], $oid); $cidinfo .= ' /Supplement '.$font['cidinfo']['Supplement']; $out .= ' /CIDSystemInfo << '.$cidinfo.' >>'; $out .= ' /FontDescriptor '.($this->n + 1).' 0 R'; $out .= ' /DW '.$font['dw']; // default width $out .= "\n".$this->_putfontwidths($font, 0); if (isset($font['ctg']) AND (!$this->empty_string($font['ctg']))) { $out .= "\n".'/CIDToGIDMap '.($this->n + 2).' 0 R'; } $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); // Font descriptor // A font descriptor describing the CIDFont default metrics other than its glyph widths $this->_newobj(); $out = '<< /Type /FontDescriptor'; $out .= ' /FontName /'.$fontname; foreach ($font['desc'] as $key => $value) { if (is_float($value)) { $value = sprintf('%.3F', $value); } $out .= ' /'.$key.' '.$value; } $fontdir = false; if (!$this->empty_string($font['file'])) { // A stream containing a TrueType font $out .= ' /FontFile2 '.$this->FontFiles[$font['file']]['n'].' 0 R'; $fontdir = $this->FontFiles[$font['file']]['fontdir']; } $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); if (isset($font['ctg']) AND (!$this->empty_string($font['ctg']))) { $this->_newobj(); // Embed CIDToGIDMap // A specification of the mapping from CIDs to glyph indices // search and get CTG font file to embedd $ctgfile = strtolower($font['ctg']); // search and get ctg font file to embedd $fontfile = ''; // search files on various directories if (($fontdir !== false) AND $this->file_exists($fontdir.$ctgfile)) { $fontfile = $fontdir.$ctgfile; } elseif ($this->file_exists($this->_getfontpath().$ctgfile)) { $fontfile = $this->_getfontpath().$ctgfile; } elseif ($this->file_exists($ctgfile)) { $fontfile = $ctgfile; } if ($this->empty_string($fontfile)) { $this->Error('Font file not found: '.$ctgfile); } $stream = $this->_getrawstream(file_get_contents($fontfile)); $out = '<< /Length '.strlen($stream).''; if (substr($fontfile, -2) == '.z') { // check file extension // Decompresses data encoded using the public-domain // zlib/deflate compression method, reproducing the // original text or binary data $out .= ' /Filter /FlateDecode'; } $out .= ' >>'; $out .= ' stream'."\n".$stream."\n".'endstream'; $out .= "\n".'endobj'; $this->_out($out); } } /** * Output CID-0 fonts. * A Type 0 CIDFont contains glyph descriptions based on the Adobe Type 1 font format * @param $font (array) font data * @protected * @author Andrew Whitehead, Nicola Asuni, Yukihiro Nakadaira * @since 3.2.000 (2008-06-23) */ protected function _putcidfont0($font) { $cidoffset = 0; if (!isset($font['cw'][1])) { $cidoffset = 31; } if (isset($font['cidinfo']['uni2cid'])) { // convert unicode to cid. $uni2cid = $font['cidinfo']['uni2cid']; $cw = array(); foreach ($font['cw'] as $uni => $width) { if (isset($uni2cid[$uni])) { $cw[($uni2cid[$uni] + $cidoffset)] = $width; } elseif ($uni < 256) { $cw[$uni] = $width; } // else unknown character } $font = array_merge($font, array('cw' => $cw)); } $name = $font['name']; $enc = $font['enc']; if ($enc) { $longname = $name.'-'.$enc; } else { $longname = $name; } $out = $this->_getobj($this->font_obj_ids[$font['fontkey']])."\n"; $out .= '<n + 1).' 0 R]'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); $oid = $this->_newobj(); $out = '<_datastring($font['cidinfo']['Registry'], $oid); $cidinfo .= ' /Ordering '.$this->_datastring($font['cidinfo']['Ordering'], $oid); $cidinfo .= ' /Supplement '.$font['cidinfo']['Supplement']; $out .= ' /CIDSystemInfo <<'.$cidinfo.'>>'; $out .= ' /FontDescriptor '.($this->n + 1).' 0 R'; $out .= ' /DW '.$font['dw']; $out .= "\n".$this->_putfontwidths($font, $cidoffset); $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); $this->_newobj(); $s = '< $v) { if ($k != 'Style') { if (is_float($v)) { $v = sprintf('%.3F', $v); } $s .= ' /'.$k.' '.$v.''; } } $s .= '>>'; $s .= "\n".'endobj'; $this->_out($s); } /** * Output images. * @protected */ protected function _putimages() { $filter = ($this->compress) ? '/Filter /FlateDecode ' : ''; foreach ($this->imagekeys as $file) { $info = $this->getImageBuffer($file); // set object for alternate images array if ((!$this->pdfa_mode) AND isset($info['altimgs']) AND !empty($info['altimgs'])) { $altoid = $this->_newobj(); $out = '['; foreach ($info['altimgs'] as $altimage) { if (isset($this->xobjects['I'.$altimage[0]]['n'])) { $out .= ' << /Image '.$this->xobjects['I'.$altimage[0]]['n'].' 0 R'; $out .= ' /DefaultForPrinting'; if ($altimage[1] === true) { $out .= ' true'; } else { $out .= ' false'; } $out .= ' >>'; } } $out .= ' ]'; $out .= "\n".'endobj'; $this->_out($out); } // set image object $oid = $this->_newobj(); $this->xobjects['I'.$info['i']] = array('n' => $oid); $this->setImageSubBuffer($file, 'n', $this->n); $out = '<n - 1).' 0 R'; } // set color space $icc = false; if (isset($info['icc']) AND ($info['icc'] !== false)) { // ICC Colour Space $icc = true; $out .= ' /ColorSpace [/ICCBased '.($this->n + 1).' 0 R]'; } elseif ($info['cs'] == 'Indexed') { // Indexed Colour Space $out .= ' /ColorSpace [/Indexed /DeviceRGB '.((strlen($info['pal']) / 3) - 1).' '.($this->n + 1).' 0 R]'; } else { // Device Colour Space $out .= ' /ColorSpace /'.$info['cs']; } if ($info['cs'] == 'DeviceCMYK') { $out .= ' /Decode [1 0 1 0 1 0 1 0]'; } $out .= ' /BitsPerComponent '.$info['bpc']; if (isset($altoid) AND ($altoid > 0)) { // reference to alternate images dictionary $out .= ' /Alternates '.$altoid.' 0 R'; } if (isset($info['exurl']) AND !empty($info['exurl'])) { // external stream $out .= ' /Length 0'; $out .= ' /F << /FS /URL /F '.$this->_datastring($info['exurl'], $oid).' >>'; if (isset($info['f'])) { $out .= ' /FFilter /'.$info['f']; } $out .= ' >>'; $out .= ' stream'."\n".'endstream'; } else { if (isset($info['f'])) { $out .= ' /Filter /'.$info['f']; } if (isset($info['parms'])) { $out .= ' '.$info['parms']; } if (isset($info['trns']) AND is_array($info['trns'])) { $trns = ''; $count_info = count($info['trns']); for ($i=0; $i < $count_info; ++$i) { $trns .= $info['trns'][$i].' '.$info['trns'][$i].' '; } $out .= ' /Mask ['.$trns.']'; } $stream = $this->_getrawstream($info['data']); $out .= ' /Length '.strlen($stream).' >>'; $out .= ' stream'."\n".$stream."\n".'endstream'; } $out .= "\n".'endobj'; $this->_out($out); if ($icc) { // ICC colour profile $this->_newobj(); $icc = ($this->compress) ? gzcompress($info['icc']) : $info['icc']; $icc = $this->_getrawstream($icc); $this->_out('<> stream'."\n".$icc."\n".'endstream'."\n".'endobj'); } elseif ($info['cs'] == 'Indexed') { // colour palette $this->_newobj(); $pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal']; $pal = $this->_getrawstream($pal); $this->_out('<<'.$filter.'/Length '.strlen($pal).'>> stream'."\n".$pal."\n".'endstream'."\n".'endobj'); } } } /** * Output Form XObjects Templates. * @author Nicola Asuni * @since 5.8.017 (2010-08-24) * @protected * @see startTemplate(), endTemplate(), printTemplate() */ protected function _putxobjects() { foreach ($this->xobjects as $key => $data) { if (isset($data['outdata'])) { $stream = trim($data['outdata']); $out = $this->_getobj($data['n'])."\n"; $out .= '<<'; $out .= ' /Type /XObject'; $out .= ' /Subtype /Form'; $out .= ' /FormType 1'; if ($this->compress) { $stream = gzcompress($stream); $out .= ' /Filter /FlateDecode'; } $out .= sprintf(' /BBox [%.2F %.2F %.2F %.2F]', ($data['x'] * $this->k), (-$data['y'] * $this->k), (($data['w'] + $data['x']) * $this->k), (($data['h'] - $data['y']) * $this->k)); $out .= ' /Matrix [1 0 0 1 0 0]'; $out .= ' /Resources <<'; $out .= ' /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'; if (!$this->pdfa_mode) { // transparency if (isset($data['extgstates']) AND !empty($data['extgstates'])) { $out .= ' /ExtGState <<'; foreach ($data['extgstates'] as $k => $extgstate) { if (isset($this->extgstates[$k]['name'])) { $out .= ' /'.$this->extgstates[$k]['name']; } else { $out .= ' /GS'.$k; } $out .= ' '.$this->extgstates[$k]['n'].' 0 R'; } $out .= ' >>'; } if (isset($data['gradients']) AND !empty($data['gradients'])) { $gp = ''; $gs = ''; foreach ($data['gradients'] as $id => $grad) { // gradient patterns $gp .= ' /p'.$id.' '.$this->gradients[$id]['pattern'].' 0 R'; // gradient shadings $gs .= ' /Sh'.$id.' '.$this->gradients[$id]['id'].' 0 R'; } $out .= ' /Pattern <<'.$gp.' >>'; $out .= ' /Shading <<'.$gs.' >>'; } } // spot colors if (isset($data['spot_colors']) AND !empty($data['spot_colors'])) { $out .= ' /ColorSpace <<'; foreach ($data['spot_colors'] as $name => $color) { $out .= ' /CS'.$color['i'].' '.$this->spot_colors[$name]['n'].' 0 R'; } $out .= ' >>'; } // fonts if (!empty($data['fonts'])) { $out .= ' /Font <<'; foreach ($data['fonts'] as $fontkey => $fontid) { $out .= ' /F'.$fontid.' '.$this->font_obj_ids[$fontkey].' 0 R'; } $out .= ' >>'; } // images or nested xobjects if (!empty($data['images']) OR !empty($data['xobjects'])) { $out .= ' /XObject <<'; foreach ($data['images'] as $imgid) { $out .= ' /I'.$imgid.' '.$this->xobjects['I'.$imgid]['n'].' 0 R'; } foreach ($data['xobjects'] as $sub_id => $sub_objid) { $out .= ' /'.$sub_id.' '.$sub_objid['n'].' 0 R'; } $out .= ' >>'; } $out .= ' >>'; //end resources if (isset($data['group']) AND ($data['group'] !== false)) { // set transparency group $out .= ' /Group << /Type /Group /S /Transparency'; if (is_array($data['group'])) { if (isset($data['group']['CS']) AND !empty($data['group']['CS'])) { $out .= ' /CS /'.$data['group']['CS']; } if (isset($data['group']['I'])) { $out .= ' /I /'.($data['group']['I']===true?'true':'false'); } if (isset($data['group']['K'])) { $out .= ' /K /'.($data['group']['K']===true?'true':'false'); } } $out .= ' >>'; } $stream = $this->_getrawstream($stream, $data['n']); $out .= ' /Length '.strlen($stream); $out .= ' >>'; $out .= ' stream'."\n".$stream."\n".'endstream'; $out .= "\n".'endobj'; $this->_out($out); } } } /** * Output Spot Colors Resources. * @protected * @since 4.0.024 (2008-09-12) */ protected function _putspotcolors() { foreach ($this->spot_colors as $name => $color) { $this->_newobj(); $this->spot_colors[$name]['n'] = $this->n; $out = '[/Separation /'.str_replace(' ', '#20', $name); $out .= ' /DeviceCMYK <<'; $out .= ' /Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0]'; $out .= ' '.sprintf('/C1 [%.4F %.4F %.4F %.4F] ', ($color['C'] / 100), ($color['M'] / 100), ($color['Y'] / 100), ($color['K'] / 100)); $out .= ' /FunctionType 2 /Domain [0 1] /N 1>>]'; $out .= "\n".'endobj'; $this->_out($out); } } /** * Return XObjects Dictionary. * @return string XObjects dictionary * @protected * @since 5.8.014 (2010-08-23) */ protected function _getxobjectdict() { $out = ''; foreach ($this->xobjects as $id => $objid) { $out .= ' /'.$id.' '.$objid['n'].' 0 R'; } return $out; } /** * Output Resources Dictionary. * @protected */ protected function _putresourcedict() { $out = $this->_getobj(2)."\n"; $out .= '<< /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]'; $out .= ' /Font <<'; foreach ($this->fontkeys as $fontkey) { $font = $this->getFontBuffer($fontkey); $out .= ' /F'.$font['i'].' '.$font['n'].' 0 R'; } $out .= ' >>'; $out .= ' /XObject <<'; $out .= $this->_getxobjectdict(); $out .= ' >>'; // layers if (!empty($this->pdflayers)) { $out .= ' /Properties <<'; foreach ($this->pdflayers as $layer) { $out .= ' /'.$layer['layer'].' '.$layer['objid'].' 0 R'; } $out .= ' >>'; } if (!$this->pdfa_mode) { // transparency if (isset($this->extgstates) AND !empty($this->extgstates)) { $out .= ' /ExtGState <<'; foreach ($this->extgstates as $k => $extgstate) { if (isset($extgstate['name'])) { $out .= ' /'.$extgstate['name']; } else { $out .= ' /GS'.$k; } $out .= ' '.$extgstate['n'].' 0 R'; } $out .= ' >>'; } if (isset($this->gradients) AND !empty($this->gradients)) { $gp = ''; $gs = ''; foreach ($this->gradients as $id => $grad) { // gradient patterns $gp .= ' /p'.$id.' '.$grad['pattern'].' 0 R'; // gradient shadings $gs .= ' /Sh'.$id.' '.$grad['id'].' 0 R'; } $out .= ' /Pattern <<'.$gp.' >>'; $out .= ' /Shading <<'.$gs.' >>'; } } // spot colors if (isset($this->spot_colors) AND !empty($this->spot_colors)) { $out .= ' /ColorSpace <<'; foreach ($this->spot_colors as $color) { $out .= ' /CS'.$color['i'].' '.$color['n'].' 0 R'; } $out .= ' >>'; } $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } /** * Output Resources. * @protected */ protected function _putresources() { $this->_putextgstates(); $this->_putocg(); $this->_putfonts(); $this->_putimages(); $this->_putspotcolors(); $this->_putshaders(); $this->_putxobjects(); $this->_putresourcedict(); $this->_putdests(); $this->_putbookmarks(); $this->_putEmbeddedFiles(); $this->_putannotsobjs(); $this->_putjavascript(); $this->_putencryption(); } /** * Adds some Metadata information (Document Information Dictionary) * (see Chapter 14.3.3 Document Information Dictionary of PDF32000_2008.pdf Reference) * @return int object id * @protected */ protected function _putinfo() { $oid = $this->_newobj(); $out = '<<'; // store current isunicode value $prev_isunicode = $this->isunicode; if ($this->docinfounicode) { $this->isunicode = true; } if (!$this->empty_string($this->title)) { // The document's title. $out .= ' /Title '.$this->_textstring($this->title, $oid); } if (!$this->empty_string($this->author)) { // The name of the person who created the document. $out .= ' /Author '.$this->_textstring($this->author, $oid); } if (!$this->empty_string($this->subject)) { // The subject of the document. $out .= ' /Subject '.$this->_textstring($this->subject, $oid); } if (!$this->empty_string($this->keywords)) { // Keywords associated with the document. $out .= ' /Keywords '.$this->_textstring($this->keywords.' TCPDF', $oid); } if (!$this->empty_string($this->creator)) { // If the document was converted to PDF from another format, the name of the conforming product that created the original document from which it was converted. $out .= ' /Creator '.$this->_textstring($this->creator, $oid); } // restore previous isunicode value $this->isunicode = $prev_isunicode; // default producer $out .= ' /Producer '.$this->_textstring("\x54\x43\x50\x44\x46\x20".$this->tcpdf_version."\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29", $oid); // The date and time the document was created, in human-readable form $out .= ' /CreationDate '.$this->_datestring(); // The date and time the document was most recently modified, in human-readable form $out .= ' /ModDate '.$this->_datestring(); // A name object indicating whether the document has been modified to include trapping information $out .= ' /Trapped /False'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); return $oid; } /** * Set additional XMP data to be added on the default XMP data just before the end of "x:xmpmeta" tag. * IMPORTANT: This data is added as-is without controls, so you have to validate your data before using this method! * @param $xmp (string) Custom XMP data. * @since 5.9.128 (2011-10-06) * @public */ public function setExtraXMP($xmp) { $this->custom_xmp = $xmp; } /** * Put XMP data object and return ID. * @return (int) The object ID. * @since 5.9.121 (2011-09-28) * @protected */ protected function _putXMP() { $oid = $this->_newobj(); // store current isunicode value $prev_isunicode = $this->isunicode; $this->isunicode = true; $prev_encrypted = $this->encrypted; $this->encrypted = false; // set XMP data $xmp = 'unichr(0xfeff).'" id="W5M0MpCehiHzreSzNTczkc9d"?>'."\n"; $xmp .= ''."\n"; $xmp .= "\t".''."\n"; $xmp .= "\t\t".''."\n"; $xmp .= "\t\t\t".'application/pdf'."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''.$this->_escapeXML($this->title).''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''.$this->_escapeXML($this->author).''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''.$this->_escapeXML($this->subject).''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''.$this->_escapeXML($this->keywords).''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t".''."\n"; // convert date format $docdate = substr($this->doc_date, 0, 4).'-'.substr($this->doc_date, 4, 2).'-'.substr($this->doc_date, 6, 2); $docdate .= 'T'.substr($this->doc_date, 8, 2).':'.substr($this->doc_date, 10, 2).':'.substr($this->doc_date, 12, 2); $docdate .= '+'.substr($this->doc_date, 15, 2).':'.substr($this->doc_date, 18, 2); $docdate = $this->_escapeXML($docdate); $xmp .= "\t\t".''."\n"; $xmp .= "\t\t\t".''.$docdate.''."\n"; $xmp .= "\t\t\t".''.$this->creator.''."\n"; $xmp .= "\t\t\t".''.$docdate.''."\n"; $xmp .= "\t\t\t".''.$docdate.''."\n"; $xmp .= "\t\t".''."\n"; $xmp .= "\t\t".''."\n"; $xmp .= "\t\t\t".''.$this->_escapeXML($this->keywords).' TCPDF'."\n"; $xmp .= "\t\t\t".''.$this->_escapeXML("\x54\x43\x50\x44\x46\x20".$this->tcpdf_version."\x20\x28\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29").''."\n"; $xmp .= "\t\t".''."\n"; $xmp .= "\t\t".''."\n"; $uuid = 'uuid:'.substr($this->file_id, 0, 8).'-'.substr($this->file_id, 8, 4).'-'.substr($this->file_id, 12, 4).'-'.substr($this->file_id, 16, 4).'-'.substr($this->file_id, 20, 12); $xmp .= "\t\t\t".''.$uuid.''."\n"; $xmp .= "\t\t\t".''.$uuid.''."\n"; $xmp .= "\t\t".''."\n"; if ($this->pdfa_mode) { $xmp .= "\t\t".''."\n"; $xmp .= "\t\t\t".'1'."\n"; $xmp .= "\t\t\t".'B'."\n"; $xmp .= "\t\t".''."\n"; } // XMP extension schemas $xmp .= "\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t".'http://ns.adobe.com/pdf/1.3/'."\n"; $xmp .= "\t\t\t\t\t\t".'pdf'."\n"; $xmp .= "\t\t\t\t\t\t".'Adobe PDF Schema'."\n"; $xmp .= "\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t".'http://ns.adobe.com/xap/1.0/mm/'."\n"; $xmp .= "\t\t\t\t\t\t".'xmpMM'."\n"; $xmp .= "\t\t\t\t\t\t".'XMP Media Management Schema'."\n"; $xmp .= "\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'internal'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'UUID based identifier for specific incarnation of a document'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'InstanceID'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'URI'."\n"; $xmp .= "\t\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t".'http://www.aiim.org/pdfa/ns/id/'."\n"; $xmp .= "\t\t\t\t\t\t".'pdfaid'."\n"; $xmp .= "\t\t\t\t\t\t".'PDF/A ID Schema'."\n"; $xmp .= "\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'internal'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'Part of PDF/A standard'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'part'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'Integer'."\n"; $xmp .= "\t\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'internal'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'Amendment of PDF/A standard'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'amd'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'Text'."\n"; $xmp .= "\t\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'internal'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'Conformance level of PDF/A standard'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'conformance'."\n"; $xmp .= "\t\t\t\t\t\t\t\t\t".'Text'."\n"; $xmp .= "\t\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t\t".''."\n"; $xmp .= "\t\t\t\t".''."\n"; $xmp .= "\t\t\t".''."\n"; $xmp .= "\t\t".''."\n"; $xmp .= "\t".''."\n"; $xmp .= $this->custom_xmp; $xmp .= ''."\n"; $xmp .= ''; $out = '<< /Type /Metadata /Subtype /XML /Length '.strlen($xmp).' >> stream'."\n".$xmp."\n".'endstream'."\n".'endobj'; // restore previous isunicode value $this->isunicode = $prev_isunicode; $this->encrypted = $prev_encrypted; $this->_out($out); return $oid; } /** * Output Catalog. * @return int object id * @protected */ protected function _putcatalog() { // put XMP $xmpobj = $this->_putXMP(); // if required, add standard sRGB_IEC61966-2.1 blackscaled ICC colour profile if ($this->pdfa_mode OR $this->force_srgb) { $iccobj = $this->_newobj(); $icc = file_get_contents(dirname(__FILE__).'/sRGB.icc'); $filter = ''; if ($this->compress) { $filter = ' /Filter /FlateDecode'; $icc = gzcompress($icc); } $icc = $this->_getrawstream($icc); $this->_out('<> stream'."\n".$icc."\n".'endstream'."\n".'endobj'); } // start catalog $oid = $this->_newobj(); $out = '<< /Type /Catalog'; $out .= ' /Version /'.$this->PDFVersion; //$out .= ' /Extensions <<>>'; $out .= ' /Pages 1 0 R'; //$out .= ' /PageLabels ' //...; $out .= ' /Names <<'; if ((!$this->pdfa_mode) AND ((!empty($this->javascript)) OR (!empty($this->js_objects)))) { $out .= ' /JavaScript '.($this->n_js).' 0 R'; } $out .= ' >>'; if (!empty($this->dests)) { $out .= ' /Dests '.$this->n_dests.' 0 R'; } $out .= $this->_putviewerpreferences(); if (isset($this->LayoutMode) AND (!$this->empty_string($this->LayoutMode))) { $out .= ' /PageLayout /'.$this->LayoutMode; } if (isset($this->PageMode) AND (!$this->empty_string($this->PageMode))) { $out .= ' /PageMode /'.$this->PageMode; } if (count($this->outlines) > 0) { $out .= ' /Outlines '.$this->OutlineRoot.' 0 R'; $out .= ' /PageMode /UseOutlines'; } //$out .= ' /Threads []'; if ($this->ZoomMode == 'fullpage') { $out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /Fit]'; } elseif ($this->ZoomMode == 'fullwidth') { $out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /FitH null]'; } elseif ($this->ZoomMode == 'real') { $out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null 1]'; } elseif (!is_string($this->ZoomMode)) { $out .= sprintf(' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null %.2F]', ($this->ZoomMode / 100)); } //$out .= ' /AA <<>>'; //$out .= ' /URI <<>>'; $out .= ' /Metadata '.$xmpobj.' 0 R'; //$out .= ' /StructTreeRoot <<>>'; //$out .= ' /MarkInfo <<>>'; if (isset($this->l['a_meta_language'])) { $out .= ' /Lang '.$this->_textstring($this->l['a_meta_language'], $oid); } //$out .= ' /SpiderInfo <<>>'; // set OutputIntent to sRGB IEC61966-2.1 if required if ($this->pdfa_mode OR $this->force_srgb) { $out .= ' /OutputIntents [<<'; $out .= ' /Type /OutputIntent'; $out .= ' /S /GTS_PDFA1'; $out .= ' /OutputCondition '.$this->_textstring('sRGB IEC61966-2.1', $oid); $out .= ' /OutputConditionIdentifier '.$this->_textstring('sRGB IEC61966-2.1', $oid); $out .= ' /RegistryName '.$this->_textstring('http://www.color.org', $oid); $out .= ' /Info '.$this->_textstring('sRGB IEC61966-2.1', $oid); $out .= ' /DestOutputProfile '.$iccobj.' 0 R'; $out .= ' >>]'; } //$out .= ' /PieceInfo <<>>'; if (!empty($this->pdflayers)) { $lyrobjs = ''; $lyrobjs_print = ''; $lyrobjs_view = ''; foreach ($this->pdflayers as $layer) { $lyrobjs .= ' '.$layer['objid'].' 0 R'; if ($layer['print']) { $lyrobjs_print .= ' '.$layer['objid'].' 0 R'; } if ($layer['view']) { $lyrobjs_view .= ' '.$layer['objid'].' 0 R'; } } $out .= ' /OCProperties << /OCGs ['.$lyrobjs.']'; $out .= ' /D <<'; $out .= ' /Name '.$this->_textstring('Layers', $oid); $out .= ' /Creator '.$this->_textstring('TCPDF', $oid); $out .= ' /BaseState /ON'; $out .= ' /ON ['.$lyrobjs_print.']'; $out .= ' /OFF ['.$lyrobjs_view.']'; $out .= ' /Intent /View'; $out .= ' /AS ['; $out .= ' << /Event /Print /OCGs ['.$lyrobjs.'] /Category [/Print] >>'; $out .= ' << /Event /View /OCGs ['.$lyrobjs.'] /Category [/View] >>'; $out .= ' ]'; $out .= ' /Order ['.$lyrobjs.']'; $out .= ' /ListMode /AllPages'; //$out .= ' /RBGroups ['..']'; //$out .= ' /Locked ['..']'; $out .= ' >>'; $out .= ' >>'; } // AcroForm if (!empty($this->form_obj_id) OR ($this->sign AND isset($this->signature_data['cert_type']))) { $out .= ' /AcroForm <<'; $objrefs = ''; if ($this->sign AND isset($this->signature_data['cert_type'])) { // set reference for signature object $objrefs .= $this->sig_obj_id.' 0 R'; } if (!empty($this->empty_signature_appearance)) { foreach ($this->empty_signature_appearance as $esa) { // set reference for empty signature objects $objrefs .= ' '.$esa['objid'].' 0 R'; } } if (!empty($this->form_obj_id)) { foreach($this->form_obj_id as $objid) { $objrefs .= ' '.$objid.' 0 R'; } } $out .= ' /Fields ['.$objrefs.']'; // It's better to turn off this value and set the appearance stream for each annotation (/AP) to avoid conflicts with signature fields. $out .= ' /NeedAppearances false'; if ($this->sign AND isset($this->signature_data['cert_type'])) { if ($this->signature_data['cert_type'] > 0) { $out .= ' /SigFlags 3'; } else { $out .= ' /SigFlags 1'; } } //$out .= ' /CO '; if (isset($this->annotation_fonts) AND !empty($this->annotation_fonts)) { $out .= ' /DR <<'; $out .= ' /Font <<'; foreach ($this->annotation_fonts as $fontkey => $fontid) { $out .= ' /F'.$fontid.' '.$this->font_obj_ids[$fontkey].' 0 R'; } $out .= ' >> >>'; } $font = $this->getFontBuffer('helvetica'); $out .= ' /DA (/F'.$font['i'].' 0 Tf 0 g)'; $out .= ' /Q '.(($this->rtl)?'2':'0'); //$out .= ' /XFA '; $out .= ' >>'; // signatures if ($this->sign AND isset($this->signature_data['cert_type'])) { if ($this->signature_data['cert_type'] > 0) { $out .= ' /Perms << /DocMDP '.($this->sig_obj_id + 1).' 0 R >>'; } else { $out .= ' /Perms << /UR3 '.($this->sig_obj_id + 1).' 0 R >>'; } } } //$out .= ' /Legal <<>>'; //$out .= ' /Requirements []'; //$out .= ' /Collection <<>>'; //$out .= ' /NeedsRendering true'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); return $oid; } /** * Output viewer preferences. * @return string for viewer preferences * @author Nicola asuni * @since 3.1.000 (2008-06-09) * @protected */ protected function _putviewerpreferences() { $out = ' /ViewerPreferences <<'; if ($this->rtl) { $out .= ' /Direction /R2L'; } else { $out .= ' /Direction /L2R'; } if (isset($this->viewer_preferences['HideToolbar']) AND ($this->viewer_preferences['HideToolbar'])) { $out .= ' /HideToolbar true'; } if (isset($this->viewer_preferences['HideMenubar']) AND ($this->viewer_preferences['HideMenubar'])) { $out .= ' /HideMenubar true'; } if (isset($this->viewer_preferences['HideWindowUI']) AND ($this->viewer_preferences['HideWindowUI'])) { $out .= ' /HideWindowUI true'; } if (isset($this->viewer_preferences['FitWindow']) AND ($this->viewer_preferences['FitWindow'])) { $out .= ' /FitWindow true'; } if (isset($this->viewer_preferences['CenterWindow']) AND ($this->viewer_preferences['CenterWindow'])) { $out .= ' /CenterWindow true'; } if (isset($this->viewer_preferences['DisplayDocTitle']) AND ($this->viewer_preferences['DisplayDocTitle'])) { $out .= ' /DisplayDocTitle true'; } if (isset($this->viewer_preferences['NonFullScreenPageMode'])) { $out .= ' /NonFullScreenPageMode /'.$this->viewer_preferences['NonFullScreenPageMode']; } if (isset($this->viewer_preferences['ViewArea'])) { $out .= ' /ViewArea /'.$this->viewer_preferences['ViewArea']; } if (isset($this->viewer_preferences['ViewClip'])) { $out .= ' /ViewClip /'.$this->viewer_preferences['ViewClip']; } if (isset($this->viewer_preferences['PrintArea'])) { $out .= ' /PrintArea /'.$this->viewer_preferences['PrintArea']; } if (isset($this->viewer_preferences['PrintClip'])) { $out .= ' /PrintClip /'.$this->viewer_preferences['PrintClip']; } if (isset($this->viewer_preferences['PrintScaling'])) { $out .= ' /PrintScaling /'.$this->viewer_preferences['PrintScaling']; } if (isset($this->viewer_preferences['Duplex']) AND (!$this->empty_string($this->viewer_preferences['Duplex']))) { $out .= ' /Duplex /'.$this->viewer_preferences['Duplex']; } if (isset($this->viewer_preferences['PickTrayByPDFSize'])) { if ($this->viewer_preferences['PickTrayByPDFSize']) { $out .= ' /PickTrayByPDFSize true'; } else { $out .= ' /PickTrayByPDFSize false'; } } if (isset($this->viewer_preferences['PrintPageRange'])) { $PrintPageRangeNum = ''; foreach ($this->viewer_preferences['PrintPageRange'] as $k => $v) { $PrintPageRangeNum .= ' '.($v - 1).''; } $out .= ' /PrintPageRange ['.substr($PrintPageRangeNum,1).']'; } if (isset($this->viewer_preferences['NumCopies'])) { $out .= ' /NumCopies '.intval($this->viewer_preferences['NumCopies']); } $out .= ' >>'; return $out; } /** * Output PDF File Header (7.5.2). * @protected */ protected function _putheader() { $this->_out('%PDF-'.$this->PDFVersion); $this->_out('%'.chr(0xe2).chr(0xe3).chr(0xcf).chr(0xd3)); } /** * Output end of document (EOF). * @protected */ protected function _enddoc() { $this->state = 1; $this->_putheader(); $this->_putpages(); $this->_putresources(); // empty signature fields if (!empty($this->empty_signature_appearance)) { foreach ($this->empty_signature_appearance as $key => $esa) { // widget annotation for empty signature $out = $this->_getobj($esa['objid'])."\n"; $out .= '<< /Type /Annot'; $out .= ' /Subtype /Widget'; $out .= ' /Rect ['.$esa['rect'].']'; $out .= ' /P '.$this->page_obj_id[($esa['page'])].' 0 R'; // link to signature appearance page $out .= ' /F 4'; $out .= ' /FT /Sig'; $signame = sprintf('Signature_%03d', ($key + 1)); $out .= ' /T '.$this->_textstring($signame, $esa['objid']); $out .= ' /Ff 0'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } } // Signature if ($this->sign AND isset($this->signature_data['cert_type'])) { // widget annotation for signature $out = $this->_getobj($this->sig_obj_id)."\n"; $out .= '<< /Type /Annot'; $out .= ' /Subtype /Widget'; $out .= ' /Rect ['.$this->signature_appearance['rect'].']'; $out .= ' /P '.$this->page_obj_id[($this->signature_appearance['page'])].' 0 R'; // link to signature appearance page $out .= ' /F 4'; $out .= ' /FT /Sig'; $out .= ' /T '.$this->_textstring('Signature_000', $this->sig_obj_id); $out .= ' /Ff 0'; $out .= ' /V '.($this->sig_obj_id + 1).' 0 R'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); // signature $this->_putsignature(); } // Info $objid_info = $this->_putinfo(); // Catalog $objid_catalog = $this->_putcatalog(); // Cross-ref $o = $this->bufferlen; // XREF section $this->_out('xref'); $this->_out('0 '.($this->n + 1)); $this->_out('0000000000 65535 f '); for ($i=1; $i <= $this->n; ++$i) { if (!isset($this->offsets[$i]) AND ($i > 1)) { $this->offsets[$i] = $this->offsets[($i - 1)]; } $this->_out(sprintf('%010d 00000 n ', $this->offsets[$i])); } // TRAILER $out = 'trailer'."\n"; $out .= '<<'; $out .= ' /Size '.($this->n + 1); $out .= ' /Root '.$objid_catalog.' 0 R'; $out .= ' /Info '.$objid_info.' 0 R'; if ($this->encrypted) { $out .= ' /Encrypt '.$this->encryptdata['objid'].' 0 R'; } $out .= ' /ID [ <'.$this->file_id.'> <'.$this->file_id.'> ]'; $out .= ' >>'; $this->_out($out); $this->_out('startxref'); $this->_out($o); $this->_out('%%EOF'); $this->state = 3; // end-of-doc if ($this->diskcache) { // remove temporary files used for images foreach ($this->imagekeys as $key) { // remove temporary files unlink($this->images[$key]); } foreach ($this->fontkeys as $key) { // remove temporary files unlink($this->fonts[$key]); } } } /** * Initialize a new page. * @param $orientation (string) page orientation. Possible values are (case insensitive):
    • P or PORTRAIT (default)
    • L or LANDSCAPE
    * @param $format (mixed) The format used for pages. It can be either: one of the string values specified at getPageSizeFromFormat() or an array of parameters specified at setPageFormat(). * @protected * @see getPageSizeFromFormat(), setPageFormat() */ protected function _beginpage($orientation='', $format='') { ++$this->page; $this->setPageBuffer($this->page, ''); // initialize array for graphics tranformation positions inside a page buffer $this->transfmrk[$this->page] = array(); $this->state = 2; if ($this->empty_string($orientation)) { if (isset($this->CurOrientation)) { $orientation = $this->CurOrientation; } elseif ($this->fwPt > $this->fhPt) { // landscape $orientation = 'L'; } else { // portrait $orientation = 'P'; } } if ($this->empty_string($format)) { $this->pagedim[$this->page] = $this->pagedim[($this->page - 1)]; $this->setPageOrientation($orientation); } else { $this->setPageFormat($format, $orientation); } if ($this->rtl) { $this->x = $this->w - $this->rMargin; } else { $this->x = $this->lMargin; } $this->y = $this->tMargin; if (isset($this->newpagegroup[$this->page])) { // start a new group $this->currpagegroup = $this->newpagegroup[$this->page]; $this->pagegroups[$this->currpagegroup] = 1; } elseif (isset($this->currpagegroup) AND ($this->currpagegroup > 0)) { ++$this->pagegroups[$this->currpagegroup]; } } /** * Mark end of page. * @protected */ protected function _endpage() { $this->setVisibility('all'); $this->state = 1; } /** * Begin a new object and return the object number. * @return int object number * @protected */ protected function _newobj() { $this->_out($this->_getobj()); return $this->n; } /** * Return the starting object string for the selected object ID. * @param $objid (int) Object ID (leave empty to get a new ID). * @return string the starting object string * @protected * @since 5.8.009 (2010-08-20) */ protected function _getobj($objid='') { if ($objid === '') { ++$this->n; $objid = $this->n; } $this->offsets[$objid] = $this->bufferlen; return $objid.' 0 obj'; } /** * Underline text. * @param $x (int) X coordinate * @param $y (int) Y coordinate * @param $txt (string) text to underline * @protected */ protected function _dounderline($x, $y, $txt) { $w = $this->GetStringWidth($txt); return $this->_dounderlinew($x, $y, $w); } /** * Underline for rectangular text area. * @param $x (int) X coordinate * @param $y (int) Y coordinate * @param $w (int) width to underline * @protected * @since 4.8.008 (2009-09-29) */ protected function _dounderlinew($x, $y, $w) { $linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt; return sprintf('%.2F %.2F %.2F %.2F re f', $x * $this->k, ((($this->h - $y) * $this->k) + $linew), $w * $this->k, $linew); } /** * Line through text. * @param $x (int) X coordinate * @param $y (int) Y coordinate * @param $txt (string) text to linethrough * @protected */ protected function _dolinethrough($x, $y, $txt) { $w = $this->GetStringWidth($txt); return $this->_dolinethroughw($x, $y, $w); } /** * Line through for rectangular text area. * @param $x (int) X coordinate * @param $y (int) Y coordinate * @param $w (int) line length (width) * @protected * @since 4.9.008 (2009-09-29) */ protected function _dolinethroughw($x, $y, $w) { $linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt; return sprintf('%.2F %.2F %.2F %.2F re f', $x * $this->k, ((($this->h - $y) * $this->k) + $linew + ($this->FontSizePt / 3)), $w * $this->k, $linew); } /** * Overline text. * @param $x (int) X coordinate * @param $y (int) Y coordinate * @param $txt (string) text to overline * @protected * @since 4.9.015 (2010-04-19) */ protected function _dooverline($x, $y, $txt) { $w = $this->GetStringWidth($txt); return $this->_dooverlinew($x, $y, $w); } /** * Overline for rectangular text area. * @param $x (int) X coordinate * @param $y (int) Y coordinate * @param $w (int) width to overline * @protected * @since 4.9.015 (2010-04-19) */ protected function _dooverlinew($x, $y, $w) { $linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt; return sprintf('%.2F %.2F %.2F %.2F re f', $x * $this->k, (($this->h - $y + $this->FontAscent) * $this->k) - $linew, $w * $this->k, $linew); } /** * Read a 4-byte (32 bit) integer from file. * @param $f (string) file name. * @return 4-byte integer * @protected */ protected function _freadint($f) { $a = unpack('Ni', fread($f, 4)); return $a['i']; } /** * Add "\" before "\", "(" and ")" * @param $s (string) string to escape. * @return string escaped string. * @protected */ protected function _escape($s) { // the chr(13) substitution fixes the Bugs item #1421290. return strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\', chr(13) => '\r')); } /** * Format a data string for meta information * @param $s (string) data string to escape. * @param $n (int) object ID * @return string escaped string. * @protected */ protected function _datastring($s, $n=0) { if ($n == 0) { $n = $this->n; } $s = $this->_encrypt_data($n, $s); return '('. $this->_escape($s).')'; } /** * Returns a formatted date for meta information * @param $n (int) object ID * @return string escaped date string. * @protected * @since 4.6.028 (2009-08-25) */ protected function _datestring($n=0) { return $this->_datastring('D:'.$this->doc_date, $n); } /** * Format a text string for meta information * @param $s (string) string to escape. * @param $n (int) object ID * @return string escaped string. * @protected */ protected function _textstring($s, $n=0) { if ($this->isunicode) { //Convert string to UTF-16BE $s = $this->UTF8ToUTF16BE($s, true); } return $this->_datastring($s, $n); } /** * THIS METHOD IS DEPRECATED * Format a text string * @param $s (string) string to escape. * @return string escaped string. * @protected * @deprecated */ protected function _escapetext($s) { if ($this->isunicode) { if (($this->CurrentFont['type'] == 'core') OR ($this->CurrentFont['type'] == 'TrueType') OR ($this->CurrentFont['type'] == 'Type1')) { $s = $this->UTF8ToLatin1($s); } else { //Convert string to UTF-16BE and reverse RTL language $s = $this->utf8StrRev($s, false, $this->tmprtl); } } return $this->_escape($s); } /** * Escape some special characters (< > &) for XML output. * @param $str (string) Input string to convert. * @return converted string * @since 5.9.121 (2011-09-28) * @protected */ protected function _escapeXML($str) { $replaceTable = array("\0" => '', '&' => '&', '<' => '<', '>' => '>'); $str = strtr($str, $replaceTable); return $str; } /** * get raw output stream. * @param $s (string) string to output. * @param $n (int) object reference for encryption mode * @protected * @author Nicola Asuni * @since 5.5.000 (2010-06-22) */ protected function _getrawstream($s, $n=0) { if ($n <= 0) { // default to current object $n = $this->n; } return $this->_encrypt_data($n, $s); } /** * Format output stream (DEPRECATED). * @param $s (string) string to output. * @param $n (int) object reference for encryption mode * @protected * @deprecated */ protected function _getstream($s, $n=0) { return 'stream'."\n".$this->_getrawstream($s, $n)."\n".'endstream'; } /** * Output a stream (DEPRECATED). * @param $s (string) string to output. * @param $n (int) object reference for encryption mode * @protected * @deprecated */ protected function _putstream($s, $n=0) { $this->_out($this->_getstream($s, $n)); } /** * Output a string to the document. * @param $s (string) string to output. * @protected */ protected function _out($s) { if ($this->state == 2) { if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['outdata'] .= $s."\n"; } elseif ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) { // puts data before page footer $pagebuff = $this->getPageBuffer($this->page); $page = substr($pagebuff, 0, -$this->footerlen[$this->page]); $footer = substr($pagebuff, -$this->footerlen[$this->page]); $this->setPageBuffer($this->page, $page.$s."\n".$footer); // update footer position $this->footerpos[$this->page] += strlen($s."\n"); } else { $this->setPageBuffer($this->page, $s."\n", true); } } else { $this->setBuffer($s."\n"); } } /** * Converts UTF-8 strings to codepoints array.
    * Invalid byte sequences will be replaced with 0xFFFD (replacement character)
    * Based on: http://www.faqs.org/rfcs/rfc3629.html *
    	 *    Char. number range  |        UTF-8 octet sequence
    	 *       (hexadecimal)    |              (binary)
    	 *    --------------------+-----------------------------------------------
    	 *    0000 0000-0000 007F | 0xxxxxxx
    	 *    0000 0080-0000 07FF | 110xxxxx 10xxxxxx
    	 *    0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
    	 *    0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    	 *    ---------------------------------------------------------------------
    	 *
    	 *   ABFN notation:
    	 *   ---------------------------------------------------------------------
    	 *   UTF8-octets = *( UTF8-char )
    	 *   UTF8-char   = UTF8-1 / UTF8-2 / UTF8-3 / UTF8-4
    	 *   UTF8-1      = %x00-7F
    	 *   UTF8-2      = %xC2-DF UTF8-tail
    	 *
    	 *   UTF8-3      = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
    	 *                 %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
    	 *   UTF8-4      = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
    	 *                 %xF4 %x80-8F 2( UTF8-tail )
    	 *   UTF8-tail   = %x80-BF
    	 *   ---------------------------------------------------------------------
    	 * 
    * @param $str (string) string to process. * @return array containing codepoints (UTF-8 characters values) * @protected * @author Nicola Asuni * @since 1.53.0.TC005 (2005-01-05) */ protected function UTF8StringToArray($str) { // build a unique string key $strkey = md5($str); if (isset($this->cache_UTF8StringToArray[$strkey])) { // return cached value $chrarray = $this->cache_UTF8StringToArray[$strkey]['s']; if (!isset($this->cache_UTF8StringToArray[$strkey]['f'][$this->CurrentFont['fontkey']])) { if ($this->isunicode) { foreach ($chrarray as $chr) { // store this char for font subsetting $this->CurrentFont['subsetchars'][$chr] = true; } // update font subsetchars $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']); } $this->cache_UTF8StringToArray[$strkey]['f'][$this->CurrentFont['fontkey']] = true; } return $chrarray; } // check cache size if ($this->cache_size_UTF8StringToArray >= $this->cache_maxsize_UTF8StringToArray) { // remove first element array_shift($this->cache_UTF8StringToArray); } // new cache array for selected string $this->cache_UTF8StringToArray[$strkey] = array('s' => array(), 'f' => array()); ++$this->cache_size_UTF8StringToArray; if (!$this->isunicode) { // split string into array of equivalent codes $strarr = array(); $strlen = strlen($str); for ($i=0; $i < $strlen; ++$i) { $strarr[] = ord($str[$i]); } // insert new value on cache $this->cache_UTF8StringToArray[$strkey]['s'] = $strarr; $this->cache_UTF8StringToArray[$strkey]['f'][$this->CurrentFont['fontkey']] = true; return $strarr; } $unichar = -1; // last unicode char $unicode = array(); // array containing unicode values $bytes = array(); // array containing single character byte sequences $numbytes = 1; // number of octetc needed to represent the UTF-8 character $str .= ''; // force $str to be a string $length = strlen($str); for ($i = 0; $i < $length; ++$i) { $char = ord($str[$i]); // get one string character at time if (count($bytes) == 0) { // get starting octect if ($char <= 0x7F) { $unichar = $char; // use the character "as is" because is ASCII $numbytes = 1; } elseif (($char >> 0x05) == 0x06) { // 2 bytes character (0x06 = 110 BIN) $bytes[] = ($char - 0xC0) << 0x06; $numbytes = 2; } elseif (($char >> 0x04) == 0x0E) { // 3 bytes character (0x0E = 1110 BIN) $bytes[] = ($char - 0xE0) << 0x0C; $numbytes = 3; } elseif (($char >> 0x03) == 0x1E) { // 4 bytes character (0x1E = 11110 BIN) $bytes[] = ($char - 0xF0) << 0x12; $numbytes = 4; } else { // use replacement character for other invalid sequences $unichar = 0xFFFD; $bytes = array(); $numbytes = 1; } } elseif (($char >> 0x06) == 0x02) { // bytes 2, 3 and 4 must start with 0x02 = 10 BIN $bytes[] = $char - 0x80; if (count($bytes) == $numbytes) { // compose UTF-8 bytes to a single unicode value $char = $bytes[0]; for ($j = 1; $j < $numbytes; ++$j) { $char += ($bytes[$j] << (($numbytes - $j - 1) * 0x06)); } if ((($char >= 0xD800) AND ($char <= 0xDFFF)) OR ($char >= 0x10FFFF)) { /* The definition of UTF-8 prohibits encoding character numbers between U+D800 and U+DFFF, which are reserved for use with the UTF-16 encoding form (as surrogate pairs) and do not directly represent characters. */ $unichar = 0xFFFD; // use replacement character } else { $unichar = $char; // add char to array } // reset data for next char $bytes = array(); $numbytes = 1; } } else { // use replacement character for other invalid sequences $unichar = 0xFFFD; $bytes = array(); $numbytes = 1; } if ($unichar >= 0) { // insert unicode value into array $unicode[] = $unichar; // store this char for font subsetting $this->CurrentFont['subsetchars'][$unichar] = true; $unichar = -1; } } // update font subsetchars $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']); // insert new value on cache $this->cache_UTF8StringToArray[$strkey]['s'] = $unicode; $this->cache_UTF8StringToArray[$strkey]['f'][$this->CurrentFont['fontkey']] = true; return $unicode; } /** * Converts UTF-8 strings to UTF16-BE.
    * @param $str (string) string to process. * @param $setbom (boolean) if true set the Byte Order Mark (BOM = 0xFEFF) * @return string * @author Nicola Asuni * @since 1.53.0.TC005 (2005-01-05) * @see UTF8StringToArray(), arrUTF8ToUTF16BE() * @protected */ protected function UTF8ToUTF16BE($str, $setbom=false) { if (!$this->isunicode) { return $str; // string is not in unicode } $unicode = $this->UTF8StringToArray($str); // array containing UTF-8 unicode values return $this->arrUTF8ToUTF16BE($unicode, $setbom); } /** * Converts UTF-8 strings to Latin1 when using the standard 14 core fonts.
    * @param $str (string) string to process. * @return string * @author Andrew Whitehead, Nicola Asuni * @protected * @since 3.2.000 (2008-06-23) */ protected function UTF8ToLatin1($str) { if (!$this->isunicode) { return $str; // string is not in unicode } $outstr = ''; // string to be returned $unicode = $this->UTF8StringToArray($str); // array containing UTF-8 unicode values foreach ($unicode as $char) { if ($char < 256) { $outstr .= chr($char); } elseif (array_key_exists($char, $this->unicode->uni_utf8tolatin)) { // map from UTF-8 $outstr .= chr($this->unicode->uni_utf8tolatin[$char]); } elseif ($char == 0xFFFD) { // skip } else { $outstr .= '?'; } } return $outstr; } /** * Converts UTF-8 characters array to array of Latin1 characters
    * @param $unicode (array) array containing UTF-8 unicode values * @return array * @author Nicola Asuni * @protected * @since 4.8.023 (2010-01-15) */ protected function UTF8ArrToLatin1($unicode) { if ((!$this->isunicode) OR $this->isUnicodeFont()) { return $unicode; } $outarr = array(); // array to be returned foreach ($unicode as $char) { if ($char < 256) { $outarr[] = $char; } elseif (array_key_exists($char, $this->unicode->uni_utf8tolatin)) { // map from UTF-8 $outarr[] = $this->unicode->uni_utf8tolatin[$char]; } elseif ($char == 0xFFFD) { // skip } else { $outarr[] = 63; // '?' character } } return $outarr; } /** * Converts array of UTF-8 characters to UTF16-BE string.
    * Based on: http://www.faqs.org/rfcs/rfc2781.html *
    	 *   Encoding UTF-16:
    	 *
    	 *   Encoding of a single character from an ISO 10646 character value to
    	 *    UTF-16 proceeds as follows. Let U be the character number, no greater
    	 *    than 0x10FFFF.
    	 *
    	 *    1) If U < 0x10000, encode U as a 16-bit unsigned integer and
    	 *       terminate.
    	 *
    	 *    2) Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,
    	 *       U' must be less than or equal to 0xFFFFF. That is, U' can be
    	 *       represented in 20 bits.
    	 *
    	 *    3) Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
    	 *       0xDC00, respectively. These integers each have 10 bits free to
    	 *       encode the character value, for a total of 20 bits.
    	 *
    	 *    4) Assign the 10 high-order bits of the 20-bit U' to the 10 low-order
    	 *       bits of W1 and the 10 low-order bits of U' to the 10 low-order
    	 *       bits of W2. Terminate.
    	 *
    	 *    Graphically, steps 2 through 4 look like:
    	 *    U' = yyyyyyyyyyxxxxxxxxxx
    	 *    W1 = 110110yyyyyyyyyy
    	 *    W2 = 110111xxxxxxxxxx
    	 * 
    * @param $unicode (array) array containing UTF-8 unicode values * @param $setbom (boolean) if true set the Byte Order Mark (BOM = 0xFEFF) * @return string * @protected * @author Nicola Asuni * @since 2.1.000 (2008-01-08) * @see UTF8ToUTF16BE() */ protected function arrUTF8ToUTF16BE($unicode, $setbom=false) { $outstr = ''; // string to be returned if ($setbom) { $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM) } foreach ($unicode as $char) { if ($char == 0x200b) { // skip Unicode Character 'ZERO WIDTH SPACE' (DEC:8203, U+200B) } elseif ($char == 0xFFFD) { $outstr .= "\xFF\xFD"; // replacement character } elseif ($char < 0x10000) { $outstr .= chr($char >> 0x08); $outstr .= chr($char & 0xFF); } else { $char -= 0x10000; $w1 = 0xD800 | ($char >> 0x0a); $w2 = 0xDC00 | ($char & 0x3FF); $outstr .= chr($w1 >> 0x08); $outstr .= chr($w1 & 0xFF); $outstr .= chr($w2 >> 0x08); $outstr .= chr($w2 & 0xFF); } } return $outstr; } // ==================================================== /** * Set header font. * @param $font (array) font * @public * @since 1.1 */ public function setHeaderFont($font) { $this->header_font = $font; } /** * Get header font. * @return array() * @public * @since 4.0.012 (2008-07-24) */ public function getHeaderFont() { return $this->header_font; } /** * Set footer font. * @param $font (array) font * @public * @since 1.1 */ public function setFooterFont($font) { $this->footer_font = $font; } /** * Get Footer font. * @return array() * @public * @since 4.0.012 (2008-07-24) */ public function getFooterFont() { return $this->footer_font; } /** * Set language array. * @param $language (array) * @public * @since 1.1 */ public function setLanguageArray($language) { $this->l = $language; if (isset($this->l['a_meta_dir'])) { $this->rtl = $this->l['a_meta_dir']=='rtl' ? true : false; } else { $this->rtl = false; } } /** * Returns the PDF data. * @public */ public function getPDFData() { if ($this->state < 3) { $this->Close(); } return $this->buffer; } /** * Output anchor link. * @param $url (string) link URL or internal link (i.e.: <a href="#23,4.5">link to page 23 at 4.5 Y position</a>) * @param $name (string) link name * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). * @param $firstline (boolean) if true prints only the first line and return the remaining string. * @param $color (array) array of RGB text color * @param $style (string) font style (U, D, B, I) * @param $firstblock (boolean) if true the string is the starting of a line. * @return the number of cells used or the remaining text if $firstline = true; * @public */ public function addHtmlLink($url, $name, $fill=false, $firstline=false, $color='', $style=-1, $firstblock=false) { if (!$this->empty_string($url) AND ($url{0} == '#')) { // convert url to internal link $lnkdata = explode(',', $url); if (isset($lnkdata[0])) { $page = intval(substr($lnkdata[0], 1)); if (empty($page) OR ($page <= 0)) { $page = $this->page; } if (isset($lnkdata[1]) AND (strlen($lnkdata[1]) > 0)) { $lnky = floatval($lnkdata[1]); } else { $lnky = 0; } $url = $this->AddLink(); $this->SetLink($url, $lnky, $page); } } // store current settings $prevcolor = $this->fgcolor; $prevstyle = $this->FontStyle; if (empty($color)) { $this->SetTextColorArray($this->htmlLinkColorArray); } else { $this->SetTextColorArray($color); } if ($style == -1) { $this->SetFont('', $this->FontStyle.$this->htmlLinkFontStyle); } else { $this->SetFont('', $this->FontStyle.$style); } $ret = $this->Write($this->lasth, $name, $url, $fill, '', false, 0, $firstline, $firstblock, 0); // restore settings $this->SetFont('', $prevstyle); $this->SetTextColorArray($prevcolor); return $ret; } /** * Returns an array (RGB or CMYK) from an html color name, or a six-digit (i.e. #3FE5AA), or three-digit (i.e. #7FF) hexadecimal color, or a javascript color array, or javascript color name. * @param $hcolor (string) HTML color. * @param $defcol (array) Color to return in case of error. * @return array RGB or CMYK color, or false in case of error. * @public */ public function convertHTMLColorToDec($hcolor='#FFFFFF', $defcol=array('R'=>128,'G'=>128,'B'=>128)) { $color = preg_replace('/[\s]*/', '', $hcolor); // remove extra spaces $color = strtolower($color); // check for javascript color array syntax if (strpos($color, '[') !== false) { if (preg_match('/[\[][\"\'](t|g|rgb|cmyk)[\"\'][\,]?([0-9\.]*)[\,]?([0-9\.]*)[\,]?([0-9\.]*)[\,]?([0-9\.]*)[\]]/', $color, $m) > 0) { $returncolor = array(); switch ($m[1]) { case 'cmyk': { // RGB $returncolor['C'] = max(0, min(100, (floatval($m[2]) * 100))); $returncolor['M'] = max(0, min(100, (floatval($m[3]) * 100))); $returncolor['Y'] = max(0, min(100, (floatval($m[4]) * 100))); $returncolor['K'] = max(0, min(100, (floatval($m[5]) * 100))); break; } case 'rgb': { // RGB $returncolor['R'] = max(0, min(255, (floatval($m[2]) * 255))); $returncolor['G'] = max(0, min(255, (floatval($m[3]) * 255))); $returncolor['B'] = max(0, min(255, (floatval($m[4]) * 255))); break; } case 'g': { // grayscale $returncolor['G'] = max(0, min(255, (floatval($m[2]) * 255))); break; } case 't': default: { // transparent (empty array) break; } } return $returncolor; } } elseif (($dotpos = strpos($color, '.')) !== false) { // remove class parent (i.e.: color.red) $color = substr($color, ($dotpos + 1)); if ($color == 'transparent') { // transparent (empty array) return array(); } } if (strlen($color) == 0) { return $defcol; } // RGB ARRAY if (substr($color, 0, 3) == 'rgb') { $codes = substr($color, 4); $codes = str_replace(')', '', $codes); $returncolor = explode(',', $codes); foreach ($returncolor as $key => $val) { if (strpos($val, '%') > 0) { // percentage $returncolor[$key] = (255 * intval($val) / 100); } else { $returncolor[$key] = intval($val); } // normalize value $returncolor[$key] = max(0, min(255, $returncolor[$key])); } return $returncolor; } // CMYK ARRAY if (substr($color, 0, 4) == 'cmyk') { $codes = substr($color, 5); $codes = str_replace(')', '', $codes); $returncolor = explode(',', $codes); foreach ($returncolor as $key => $val) { if (strpos($val, '%') !== false) { // percentage $returncolor[$key] = (100 * intval($val) / 100); } else { $returncolor[$key] = intval($val); } // normalize value $returncolor[$key] = max(0, min(100, $returncolor[$key])); } return $returncolor; } if ($color{0} != '#') { // COLOR NAME if (isset($this->webcolor[$color])) { // web color $color_code = $this->webcolor[$color]; } else { // spot color $returncolor = $this->getSpotColor($color); if ($returncolor === false) { $returncolor = $defcol; } return $returncolor; } } else { $color_code = substr($color, 1); } // HEXADECIMAL REPRESENTATION switch (strlen($color_code)) { case 3: { // 3-digit RGB hexadecimal representation $r = substr($color_code, 0, 1); $g = substr($color_code, 1, 1); $b = substr($color_code, 2, 1); $returncolor = array(); $returncolor['R'] = max(0, min(255, hexdec($r.$r))); $returncolor['G'] = max(0, min(255, hexdec($g.$g))); $returncolor['B'] = max(0, min(255, hexdec($b.$b))); break; } case 6: { // 6-digit RGB hexadecimal representation $returncolor = array(); $returncolor['R'] = max(0, min(255, hexdec(substr($color_code, 0, 2)))); $returncolor['G'] = max(0, min(255, hexdec(substr($color_code, 2, 2)))); $returncolor['B'] = max(0, min(255, hexdec(substr($color_code, 4, 2)))); break; } case 8: { // 8-digit CMYK hexadecimal representation $returncolor = array(); $returncolor['C'] = max(0, min(100, round(hexdec(substr($color_code, 0, 2)) / 2.55))); $returncolor['M'] = max(0, min(100, round(hexdec(substr($color_code, 2, 2)) / 2.55))); $returncolor['Y'] = max(0, min(100, round(hexdec(substr($color_code, 4, 2)) / 2.55))); $returncolor['K'] = max(0, min(100, round(hexdec(substr($color_code, 6, 2)) / 2.55))); break; } default: { $returncolor = $defcol; break; } } return $returncolor; } /** * Converts pixels to User's Units. * @param $px (int) pixels * @return float value in user's unit * @public * @see setImageScale(), getImageScale() */ public function pixelsToUnits($px) { return ($px / ($this->imgscale * $this->k)); } /** * Reverse function for htmlentities. * Convert entities in UTF-8. * @param $text_to_convert (string) Text to convert. * @return string converted text string * @public */ public function unhtmlentities($text_to_convert) { return @html_entity_decode($text_to_convert, ENT_QUOTES, $this->encoding); } // ENCRYPTION METHODS ---------------------------------- /** * Returns a string containing random data to be used as a seed for encryption methods. * @param $seed (string) starting seed value * @return string containing random data * @author Nicola Asuni * @since 5.9.006 (2010-10-19) * @protected */ protected function getRandomSeed($seed='') { $seed .= microtime(); if (function_exists('openssl_random_pseudo_bytes') AND (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // this is not used on windows systems because it is very slow for a know bug $seed .= openssl_random_pseudo_bytes(512); } else { for ($i = 0; $i < 23; ++$i) { $seed .= uniqid('', true); } } $seed .= uniqid('', true); $seed .= rand(); // Modified by redcocker This code is provided by Michael Stark //$seed .= getmypid(); $seed .= uniqid('', true); $seed .= __FILE__; $seed .= $this->bufferlen; if (isset($_SERVER['REMOTE_ADDR'])) { $seed .= $_SERVER['REMOTE_ADDR']; } if (isset($_SERVER['HTTP_USER_AGENT'])) { $seed .= $_SERVER['HTTP_USER_AGENT']; } if (isset($_SERVER['HTTP_ACCEPT'])) { $seed .= $_SERVER['HTTP_ACCEPT']; } if (isset($_SERVER['HTTP_ACCEPT_ENCODING'])) { $seed .= $_SERVER['HTTP_ACCEPT_ENCODING']; } if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $seed .= $_SERVER['HTTP_ACCEPT_LANGUAGE']; } if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) { $seed .= $_SERVER['HTTP_ACCEPT_CHARSET']; } $seed .= rand(); $seed .= uniqid('', true); $seed .= microtime(); return $seed; } /** * Compute encryption key depending on object number where the encrypted data is stored. * This is used for all strings and streams without crypt filter specifier. * @param $n (int) object number * @return int object key * @protected * @author Nicola Asuni * @since 2.0.000 (2008-01-02) */ protected function _objectkey($n) { $objkey = $this->encryptdata['key'].pack('VXxx', $n); if ($this->encryptdata['mode'] == 2) { // AES-128 // AES padding $objkey .= "\x73\x41\x6C\x54"; // sAlT } $objkey = substr($this->_md5_16($objkey), 0, (($this->encryptdata['Length'] / 8) + 5)); $objkey = substr($objkey, 0, 16); return $objkey; } /** * Encrypt the input string. * @param $n (int) object number * @param $s (string) data string to encrypt * @return encrypted string * @protected * @author Nicola Asuni * @since 5.0.005 (2010-05-11) */ protected function _encrypt_data($n, $s) { if (!$this->encrypted) { return $s; } switch ($this->encryptdata['mode']) { case 0: // RC4-40 case 1: { // RC4-128 $s = $this->_RC4($this->_objectkey($n), $s); break; } case 2: { // AES-128 $s = $this->_AES($this->_objectkey($n), $s); break; } case 3: { // AES-256 $s = $this->_AES($this->encryptdata['key'], $s); break; } } return $s; } /** * Put encryption on PDF document. * @protected * @author Nicola Asuni * @since 2.0.000 (2008-01-02) */ protected function _putencryption() { if (!$this->encrypted) { return; } $this->encryptdata['objid'] = $this->_newobj(); $out = '<<'; if (!isset($this->encryptdata['Filter']) OR empty($this->encryptdata['Filter'])) { $this->encryptdata['Filter'] = 'Standard'; } $out .= ' /Filter /'.$this->encryptdata['Filter']; if (isset($this->encryptdata['SubFilter']) AND !empty($this->encryptdata['SubFilter'])) { $out .= ' /SubFilter /'.$this->encryptdata['SubFilter']; } if (!isset($this->encryptdata['V']) OR empty($this->encryptdata['V'])) { $this->encryptdata['V'] = 1; } // V is a code specifying the algorithm to be used in encrypting and decrypting the document $out .= ' /V '.$this->encryptdata['V']; if (isset($this->encryptdata['Length']) AND !empty($this->encryptdata['Length'])) { // The length of the encryption key, in bits. The value shall be a multiple of 8, in the range 40 to 256 $out .= ' /Length '.$this->encryptdata['Length']; } else { $out .= ' /Length 40'; } if ($this->encryptdata['V'] >= 4) { if (!isset($this->encryptdata['StmF']) OR empty($this->encryptdata['StmF'])) { $this->encryptdata['StmF'] = 'Identity'; } if (!isset($this->encryptdata['StrF']) OR empty($this->encryptdata['StrF'])) { // The name of the crypt filter that shall be used when decrypting all strings in the document. $this->encryptdata['StrF'] = 'Identity'; } // A dictionary whose keys shall be crypt filter names and whose values shall be the corresponding crypt filter dictionaries. if (isset($this->encryptdata['CF']) AND !empty($this->encryptdata['CF'])) { $out .= ' /CF <<'; $out .= ' /'.$this->encryptdata['StmF'].' <<'; $out .= ' /Type /CryptFilter'; if (isset($this->encryptdata['CF']['CFM']) AND !empty($this->encryptdata['CF']['CFM'])) { // The method used $out .= ' /CFM /'.$this->encryptdata['CF']['CFM']; if ($this->encryptdata['pubkey']) { $out .= ' /Recipients ['; foreach ($this->encryptdata['Recipients'] as $rec) { $out .= ' <'.$rec.'>'; } $out .= ' ]'; if (isset($this->encryptdata['CF']['EncryptMetadata']) AND (!$this->encryptdata['CF']['EncryptMetadata'])) { $out .= ' /EncryptMetadata false'; } else { $out .= ' /EncryptMetadata true'; } } } else { $out .= ' /CFM /None'; } if (isset($this->encryptdata['CF']['AuthEvent']) AND !empty($this->encryptdata['CF']['AuthEvent'])) { // The event to be used to trigger the authorization that is required to access encryption keys used by this filter. $out .= ' /AuthEvent /'.$this->encryptdata['CF']['AuthEvent']; } else { $out .= ' /AuthEvent /DocOpen'; } if (isset($this->encryptdata['CF']['Length']) AND !empty($this->encryptdata['CF']['Length'])) { // The bit length of the encryption key. $out .= ' /Length '.$this->encryptdata['CF']['Length']; } $out .= ' >> >>'; } // The name of the crypt filter that shall be used by default when decrypting streams. $out .= ' /StmF /'.$this->encryptdata['StmF']; // The name of the crypt filter that shall be used when decrypting all strings in the document. $out .= ' /StrF /'.$this->encryptdata['StrF']; if (isset($this->encryptdata['EFF']) AND !empty($this->encryptdata['EFF'])) { // The name of the crypt filter that shall be used when encrypting embedded file streams that do not have their own crypt filter specifier. $out .= ' /EFF /'.$this->encryptdata['']; } } // Additional encryption dictionary entries for the standard security handler if ($this->encryptdata['pubkey']) { if (($this->encryptdata['V'] < 4) AND isset($this->encryptdata['Recipients']) AND !empty($this->encryptdata['Recipients'])) { $out .= ' /Recipients ['; foreach ($this->encryptdata['Recipients'] as $rec) { $out .= ' <'.$rec.'>'; } $out .= ' ]'; } } else { $out .= ' /R'; if ($this->encryptdata['V'] == 5) { // AES-256 $out .= ' 5'; $out .= ' /OE ('.$this->_escape($this->encryptdata['OE']).')'; $out .= ' /UE ('.$this->_escape($this->encryptdata['UE']).')'; $out .= ' /Perms ('.$this->_escape($this->encryptdata['perms']).')'; } elseif ($this->encryptdata['V'] == 4) { // AES-128 $out .= ' 4'; } elseif ($this->encryptdata['V'] < 2) { // RC-40 $out .= ' 2'; } else { // RC-128 $out .= ' 3'; } $out .= ' /O ('.$this->_escape($this->encryptdata['O']).')'; $out .= ' /U ('.$this->_escape($this->encryptdata['U']).')'; $out .= ' /P '.$this->encryptdata['P']; if (isset($this->encryptdata['EncryptMetadata']) AND (!$this->encryptdata['EncryptMetadata'])) { $out .= ' /EncryptMetadata false'; } else { $out .= ' /EncryptMetadata true'; } } $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } /** * Returns the input text encrypted using RC4 algorithm and the specified key. * RC4 is the standard encryption algorithm used in PDF format * @param $key (string) encryption key * @param $text (String) input text to be encrypted * @return String encrypted text * @protected * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec, Nicola Asuni */ protected function _RC4($key, $text) { if (function_exists('mcrypt_decrypt') AND ($out = @mcrypt_decrypt(MCRYPT_ARCFOUR, $key, $text, MCRYPT_MODE_STREAM, ''))) { // try to use mcrypt function if exist return $out; } if ($this->last_enc_key != $key) { $k = str_repeat($key, ((256 / strlen($key)) + 1)); $rc4 = range(0, 255); $j = 0; for ($i = 0; $i < 256; ++$i) { $t = $rc4[$i]; $j = ($j + $t + ord($k[$i])) % 256; $rc4[$i] = $rc4[$j]; $rc4[$j] = $t; } $this->last_enc_key = $key; $this->last_enc_key_c = $rc4; } else { $rc4 = $this->last_enc_key_c; } $len = strlen($text); $a = 0; $b = 0; $out = ''; for ($i = 0; $i < $len; ++$i) { $a = ($a + 1) % 256; $t = $rc4[$a]; $b = ($b + $t) % 256; $rc4[$a] = $rc4[$b]; $rc4[$b] = $t; $k = $rc4[($rc4[$a] + $rc4[$b]) % 256]; $out .= chr(ord($text[$i]) ^ $k); } return $out; } /** * Returns the input text exrypted using AES algorithm and the specified key. * This method requires openssl or mcrypt. Text is padded to 16bytes blocks * @param $key (string) encryption key * @param $text (String) input text to be encrypted * @return String encrypted text * @protected * @author Nicola Asuni * @since 5.0.005 (2010-05-11) */ protected function _AES($key, $text) { // padding (RFC 2898, PKCS #5: Password-Based Cryptography Specification Version 2.0) $padding = 16 - (strlen($text) % 16); $text .= str_repeat(chr($padding), $padding); if (extension_loaded('openssl')) { $iv = openssl_random_pseudo_bytes (openssl_cipher_iv_length('aes-256-cbc')); $text = openssl_encrypt($text, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); return $iv.substr($text, 0, -16); } if (extension_loaded('mcrypt')) { $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND); $text = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv); $text = $iv.$text; return $text; } } /** * Encrypts a string using MD5 and returns it's value as a binary string. * @param $str (string) input string * @return String MD5 encrypted binary string * @protected * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec */ protected function _md5_16($str) { return pack('H*', md5($str)); } /** * Compute U value (used for encryption) * @return string U value * @protected * @since 2.0.000 (2008-01-02) * @author Nicola Asuni */ protected function _Uvalue() { if ($this->encryptdata['mode'] == 0) { // RC4-40 return $this->_RC4($this->encryptdata['key'], $this->enc_padding); } elseif ($this->encryptdata['mode'] < 3) { // RC4-128, AES-128 $tmp = $this->_md5_16($this->enc_padding.$this->encryptdata['fileid']); $enc = $this->_RC4($this->encryptdata['key'], $tmp); $len = strlen($tmp); for ($i = 1; $i <= 19; ++$i) { $ek = ''; for ($j = 0; $j < $len; ++$j) { $ek .= chr(ord($this->encryptdata['key'][$j]) ^ $i); } $enc = $this->_RC4($ek, $enc); } $enc .= str_repeat("\x00", 16); return substr($enc, 0, 32); } elseif ($this->encryptdata['mode'] == 3) { // AES-256 $seed = $this->_md5_16($this->getRandomSeed()); // User Validation Salt $this->encryptdata['UVS'] = substr($seed, 0, 8); // User Key Salt $this->encryptdata['UKS'] = substr($seed, 8, 16); return hash('sha256', $this->encryptdata['user_password'].$this->encryptdata['UVS'], true).$this->encryptdata['UVS'].$this->encryptdata['UKS']; } } /** * Returns the input text exrypted using AES algorithm and the specified key. * This method requires openssl or mcrypt. Text is not padded * @param $key (string) encryption key * @param $text (String) input text to be encrypted * @return String encrypted text * @author Nicola Asuni * @since TODO * @protected */ protected function _AESnopad($key, $text) { if (extension_loaded('openssl')) { $iv = str_repeat("\x00", openssl_cipher_iv_length('aes-256-cbc')); $text = openssl_encrypt($text, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); return substr($text, 0, -16); } if (extension_loaded('mcrypt')) { $iv = str_repeat("\x00", mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC)); $text = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv); return $text; } } /** * Compute UE value (used for encryption) * @return string UE value * @protected * @since 5.9.006 (2010-10-19) * @author Nicola Asuni */ protected function _UEvalue() { $hashkey = hash('sha256', $this->encryptdata['user_password'].$this->encryptdata['UKS'], true); return $this->_AESnopad($hashkey, $this->encryptdata['key']); } /** * Compute O value (used for encryption) * @return string O value * @protected * @since 2.0.000 (2008-01-02) * @author Nicola Asuni */ protected function _Ovalue() { if ($this->encryptdata['mode'] < 3) { // RC4-40, RC4-128, AES-128 $tmp = $this->_md5_16($this->encryptdata['owner_password']); if ($this->encryptdata['mode'] > 0) { for ($i = 0; $i < 50; ++$i) { $tmp = $this->_md5_16($tmp); } } $owner_key = substr($tmp, 0, ($this->encryptdata['Length'] / 8)); $enc = $this->_RC4($owner_key, $this->encryptdata['user_password']); if ($this->encryptdata['mode'] > 0) { $len = strlen($owner_key); for ($i = 1; $i <= 19; ++$i) { $ek = ''; for ($j = 0; $j < $len; ++$j) { $ek .= chr(ord($owner_key[$j]) ^ $i); } $enc = $this->_RC4($ek, $enc); } } return $enc; } elseif ($this->encryptdata['mode'] == 3) { // AES-256 $seed = $this->_md5_16($this->getRandomSeed()); // Owner Validation Salt $this->encryptdata['OVS'] = substr($seed, 0, 8); // Owner Key Salt $this->encryptdata['OKS'] = substr($seed, 8, 16); return hash('sha256', $this->encryptdata['owner_password'].$this->encryptdata['OVS'].$this->encryptdata['U'], true).$this->encryptdata['OVS'].$this->encryptdata['OKS']; } } /** * Compute OE value (used for encryption) * @return string OE value * @protected * @since 5.9.006 (2010-10-19) * @author Nicola Asuni */ protected function _OEvalue() { $hashkey = hash('sha256', $this->encryptdata['owner_password'].$this->encryptdata['OKS'].$this->encryptdata['U'], true); return $this->_AESnopad($hashkey, $this->encryptdata['key']); } /** * Convert password for AES-256 encryption mode * @param $password (string) password * @return string password * @protected * @since 5.9.006 (2010-10-19) * @author Nicola Asuni */ protected function _fixAES256Password($password) { $psw = ''; // password to be returned $psw_array = $this->utf8Bidi($this->UTF8StringToArray($password), $password, $this->rtl); foreach ($psw_array as $c) { $psw .= $this->unichr($c); } return substr($psw, 0, 127); } /** * Compute encryption key * @protected * @since 2.0.000 (2008-01-02) * @author Nicola Asuni */ protected function _generateencryptionkey() { $keybytelen = ($this->encryptdata['Length'] / 8); if (!$this->encryptdata['pubkey']) { // standard mode if ($this->encryptdata['mode'] == 3) { // AES-256 // generate 256 bit random key $this->encryptdata['key'] = substr(hash('sha256', $this->getRandomSeed(), true), 0, $keybytelen); // truncate passwords $this->encryptdata['user_password'] = $this->_fixAES256Password($this->encryptdata['user_password']); $this->encryptdata['owner_password'] = $this->_fixAES256Password($this->encryptdata['owner_password']); // Compute U value $this->encryptdata['U'] = $this->_Uvalue(); // Compute UE value $this->encryptdata['UE'] = $this->_UEvalue(); // Compute O value $this->encryptdata['O'] = $this->_Ovalue(); // Compute OE value $this->encryptdata['OE'] = $this->_OEvalue(); // Compute P value $this->encryptdata['P'] = $this->encryptdata['protection']; // Computing the encryption dictionary's Perms (permissions) value $perms = $this->getEncPermissionsString($this->encryptdata['protection']); // bytes 0-3 $perms .= chr(255).chr(255).chr(255).chr(255); // bytes 4-7 if (isset($this->encryptdata['CF']['EncryptMetadata']) AND (!$this->encryptdata['CF']['EncryptMetadata'])) { // byte 8 $perms .= 'F'; } else { $perms .= 'T'; } $perms .= 'adb'; // bytes 9-11 $perms .= 'nick'; // bytes 12-15 $this->encryptdata['perms'] = $this->_AESnopad($this->encryptdata['key'], $perms); } else { // RC4-40, RC4-128, AES-128 // Pad passwords $this->encryptdata['user_password'] = substr($this->encryptdata['user_password'].$this->enc_padding, 0, 32); $this->encryptdata['owner_password'] = substr($this->encryptdata['owner_password'].$this->enc_padding, 0, 32); // Compute O value $this->encryptdata['O'] = $this->_Ovalue(); // get default permissions (reverse byte order) $permissions = $this->getEncPermissionsString($this->encryptdata['protection']); // Compute encryption key $tmp = $this->_md5_16($this->encryptdata['user_password'].$this->encryptdata['O'].$permissions.$this->encryptdata['fileid']); if ($this->encryptdata['mode'] > 0) { for ($i = 0; $i < 50; ++$i) { $tmp = $this->_md5_16(substr($tmp, 0, $keybytelen)); } } $this->encryptdata['key'] = substr($tmp, 0, $keybytelen); // Compute U value $this->encryptdata['U'] = $this->_Uvalue(); // Compute P value $this->encryptdata['P'] = $this->encryptdata['protection']; } } else { // Public-Key mode // random 20-byte seed $seed = sha1($this->getRandomSeed(), true); $recipient_bytes = ''; foreach ($this->encryptdata['pubkeys'] as $pubkey) { // for each public certificate if (isset($pubkey['p'])) { $pkprotection = $this->getUserPermissionCode($pubkey['p'], $this->encryptdata['mode']); } else { $pkprotection = $this->encryptdata['protection']; } // get default permissions (reverse byte order) $pkpermissions = $this->getEncPermissionsString($pkprotection); // envelope data $envelope = $seed.$pkpermissions; // write the envelope data to a temporary file $tempkeyfile = tempnam(K_PATH_CACHE, 'tmpkey_'); $f = fopen($tempkeyfile, 'wb'); if (!$f) { $this->Error('Unable to create temporary key file: '.$tempkeyfile); } $envelope_length = strlen($envelope); fwrite($f, $envelope, $envelope_length); fclose($f); $tempencfile = tempnam(K_PATH_CACHE, 'tmpenc_'); if (!openssl_pkcs7_encrypt($tempkeyfile, $tempencfile, $pubkey['c'], array(), PKCS7_BINARY | PKCS7_DETACHED)) { $this->Error('Unable to encrypt the file: '.$tempkeyfile); } unlink($tempkeyfile); // read encryption signature $signature = file_get_contents($tempencfile, false, null, $envelope_length); unlink($tempencfile); // extract signature $signature = substr($signature, strpos($signature, 'Content-Disposition')); $tmparr = explode("\n\n", $signature); $signature = trim($tmparr[1]); unset($tmparr); // decode signature $signature = base64_decode($signature); // convert signature to hex $hexsignature = current(unpack('H*', $signature)); // store signature on recipients array $this->encryptdata['Recipients'][] = $hexsignature; // The bytes of each item in the Recipients array of PKCS#7 objects in the order in which they appear in the array $recipient_bytes .= $signature; } // calculate encryption key if ($this->encryptdata['mode'] == 3) { // AES-256 $this->encryptdata['key'] = substr(hash('sha256', $seed.$recipient_bytes, true), 0, $keybytelen); } else { // RC4-40, RC4-128, AES-128 $this->encryptdata['key'] = substr(sha1($seed.$recipient_bytes, true), 0, $keybytelen); } } } /** * Return the premission code used on encryption (P value). * @param $permissions (Array) the set of permissions (specify the ones you want to block). * @param $mode (int) encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit. * @protected * @since 5.0.005 (2010-05-12) * @author Nicola Asuni */ protected function getUserPermissionCode($permissions, $mode=0) { $options = array( 'owner' => 2, // bit 2 -- inverted logic: cleared by default 'print' => 4, // bit 3 'modify' => 8, // bit 4 'copy' => 16, // bit 5 'annot-forms' => 32, // bit 6 'fill-forms' => 256, // bit 9 'extract' => 512, // bit 10 'assemble' => 1024,// bit 11 'print-high' => 2048 // bit 12 ); $protection = 2147422012; // 32 bit: (01111111 11111111 00001111 00111100) foreach ($permissions as $permission) { if (!isset($options[$permission])) { $this->Error('Incorrect permission: '.$permission); } if (($mode > 0) OR ($options[$permission] <= 32)) { // set only valid permissions if ($options[$permission] == 2) { // the logic for bit 2 is inverted (cleared by default) $protection += $options[$permission]; } else { $protection -= $options[$permission]; } } } return $protection; } /** * Set document protection * Remark: the protection against modification is for people who have the full Acrobat product. * If you don't set any password, the document will open as usual. If you set a user password, the PDF viewer will ask for it before displaying the document. The master password, if different from the user one, can be used to get full access. * Note: protecting a document requires to encrypt it, which increases the processing time a lot. This can cause a PHP time-out in some cases, especially if the document contains images or fonts. * @param $permissions (Array) the set of permissions (specify the ones you want to block):
    • print : Print the document;
    • modify : Modify the contents of the document by operations other than those controlled by 'fill-forms', 'extract' and 'assemble';
    • copy : Copy or otherwise extract text and graphics from the document;
    • annot-forms : Add or modify text annotations, fill in interactive form fields, and, if 'modify' is also set, create or modify interactive form fields (including signature fields);
    • fill-forms : Fill in existing interactive form fields (including signature fields), even if 'annot-forms' is not specified;
    • extract : Extract text and graphics (in support of accessibility to users with disabilities or for other purposes);
    • assemble : Assemble the document (insert, rotate, or delete pages and create bookmarks or thumbnail images), even if 'modify' is not set;
    • print-high : Print the document to a representation from which a faithful digital copy of the PDF content could be generated. When this is not set, printing is limited to a low-level representation of the appearance, possibly of degraded quality.
    • owner : (inverted logic - only for public-key) when set permits change of encryption and enables all other permissions.
    * @param $user_pass (String) user password. Empty by default. * @param $owner_pass (String) owner password. If not specified, a random value is used. * @param $mode (int) encryption strength: 0 = RC4 40 bit; 1 = RC4 128 bit; 2 = AES 128 bit; 3 = AES 256 bit. * @param $pubkeys (String) array of recipients containing public-key certificates ('c') and permissions ('p'). For example: array(array('c' => 'file://../tcpdf.crt', 'p' => array('print'))) * @public * @since 2.0.000 (2008-01-02) * @author Nicola Asuni */ public function SetProtection($permissions=array('print', 'modify', 'copy', 'annot-forms', 'fill-forms', 'extract', 'assemble', 'print-high'), $user_pass='', $owner_pass=null, $mode=0, $pubkeys=null) { if ($this->pdfa_mode) { // encryption is not allowed in PDF/A mode return; } $this->encryptdata['protection'] = $this->getUserPermissionCode($permissions, $mode); if (($pubkeys !== null) AND (is_array($pubkeys))) { // public-key mode $this->encryptdata['pubkeys'] = $pubkeys; if ($mode == 0) { // public-Key Security requires at least 128 bit $mode = 1; } if (!function_exists('openssl_pkcs7_encrypt')) { $this->Error('Public-Key Security requires openssl library.'); } // Set Public-Key filter (availabe are: Entrust.PPKEF, Adobe.PPKLite, Adobe.PubSec) $this->encryptdata['pubkey'] = true; $this->encryptdata['Filter'] = 'Adobe.PubSec'; $this->encryptdata['StmF'] = 'DefaultCryptFilter'; $this->encryptdata['StrF'] = 'DefaultCryptFilter'; } else { // standard mode (password mode) $this->encryptdata['pubkey'] = false; $this->encryptdata['Filter'] = 'Standard'; $this->encryptdata['StmF'] = 'StdCF'; $this->encryptdata['StrF'] = 'StdCF'; } if ($mode > 1) { // AES if (!extension_loaded('openssl') && !extension_loaded('mcrypt')) { $this->Error('AES encryption requires openssl or mcrypt extension (http://www.php.net/manual/en/mcrypt.requirements.php).'); } if (extension_loaded('openssl') && !in_array('aes-256-cbc', openssl_get_cipher_methods())) { $this->Error('AES encryption requires openssl/aes-256-cbc cypher.'); } if (extension_loaded('mcrypt') && mcrypt_get_cipher_name(MCRYPT_RIJNDAEL_128) === false) { $this->Error('AES encryption requires MCRYPT_RIJNDAEL_128 cypher.'); } if (($mode == 3) AND !function_exists('hash')) { // the Hash extension requires no external libraries and is enabled by default as of PHP 5.1.2. $this->Error('AES 256 encryption requires HASH Message Digest Framework (http://www.php.net/manual/en/book.hash.php).'); } } if ($owner_pass === null) { $owner_pass = md5($this->getRandomSeed()); } $this->encryptdata['user_password'] = $user_pass; $this->encryptdata['owner_password'] = $owner_pass; $this->encryptdata['mode'] = $mode; switch ($mode) { case 0: { // RC4 40 bit $this->encryptdata['V'] = 1; $this->encryptdata['Length'] = 40; $this->encryptdata['CF']['CFM'] = 'V2'; break; } case 1: { // RC4 128 bit $this->encryptdata['V'] = 2; $this->encryptdata['Length'] = 128; $this->encryptdata['CF']['CFM'] = 'V2'; if ($this->encryptdata['pubkey']) { $this->encryptdata['SubFilter'] = 'adbe.pkcs7.s4'; $this->encryptdata['Recipients'] = array(); } break; } case 2: { // AES 128 bit $this->encryptdata['V'] = 4; $this->encryptdata['Length'] = 128; $this->encryptdata['CF']['CFM'] = 'AESV2'; $this->encryptdata['CF']['Length'] = 128; if ($this->encryptdata['pubkey']) { $this->encryptdata['SubFilter'] = 'adbe.pkcs7.s5'; $this->encryptdata['Recipients'] = array(); } break; } case 3: { // AES 256 bit $this->encryptdata['V'] = 5; $this->encryptdata['Length'] = 256; $this->encryptdata['CF']['CFM'] = 'AESV3'; $this->encryptdata['CF']['Length'] = 256; if ($this->encryptdata['pubkey']) { $this->encryptdata['SubFilter'] = 'adbe.pkcs7.s5'; $this->encryptdata['Recipients'] = array(); } break; } } $this->encrypted = true; $this->encryptdata['fileid'] = $this->convertHexStringToString($this->file_id); $this->_generateencryptionkey(); } /** * Convert hexadecimal string to string * @param $bs (string) byte-string to convert * @return String * @protected * @since 5.0.005 (2010-05-12) * @author Nicola Asuni */ protected function convertHexStringToString($bs) { $string = ''; // string to be returned $bslength = strlen($bs); if (($bslength % 2) != 0) { // padding $bs .= '0'; ++$bslength; } for ($i = 0; $i < $bslength; $i += 2) { $string .= chr(hexdec($bs[$i].$bs[($i + 1)])); } return $string; } /** * Convert string to hexadecimal string (byte string) * @param $s (string) string to convert * @return byte string * @protected * @since 5.0.010 (2010-05-17) * @author Nicola Asuni */ protected function convertStringToHexString($s) { $bs = ''; $chars = preg_split('//', $s, -1, PREG_SPLIT_NO_EMPTY); foreach ($chars as $c) { $bs .= sprintf('%02s', dechex(ord($c))); } return $bs; } /** * Convert encryption P value to a string of bytes, low-order byte first. * @param $protection (string) 32bit encryption permission value (P value) * @return String * @protected * @since 5.0.005 (2010-05-12) * @author Nicola Asuni */ protected function getEncPermissionsString($protection) { $binprot = sprintf('%032b', $protection); $str = chr(bindec(substr($binprot, 24, 8))); $str .= chr(bindec(substr($binprot, 16, 8))); $str .= chr(bindec(substr($binprot, 8, 8))); $str .= chr(bindec(substr($binprot, 0, 8))); return $str; } // END OF ENCRYPTION FUNCTIONS ------------------------- // START TRANSFORMATIONS SECTION ----------------------- /** * Starts a 2D tranformation saving current graphic state. * This function must be called before scaling, mirroring, translation, rotation and skewing. * Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior. * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function StartTransform() { $this->_out('q'); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['transfmrk'][] = strlen($this->xobjects[$this->xobjid]['outdata']); } else { $this->transfmrk[$this->page][] = $this->pagelen[$this->page]; } ++$this->transfmatrix_key; $this->transfmatrix[$this->transfmatrix_key] = array(); } /** * Stops a 2D tranformation restoring previous graphic state. * This function must be called after scaling, mirroring, translation, rotation and skewing. * Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior. * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function StopTransform() { $this->_out('Q'); if (isset($this->transfmatrix[$this->transfmatrix_key])) { array_pop($this->transfmatrix[$this->transfmatrix_key]); --$this->transfmatrix_key; } if ($this->inxobj) { // we are inside an XObject template array_pop($this->xobjects[$this->xobjid]['transfmrk']); } else { array_pop($this->transfmrk[$this->page]); } } /** * Horizontal Scaling. * @param $s_x (float) scaling factor for width as percent. 0 is not allowed. * @param $x (int) abscissa of the scaling center. Default is current x position * @param $y (int) ordinate of the scaling center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function ScaleX($s_x, $x='', $y='') { $this->Scale($s_x, 100, $x, $y); } /** * Vertical Scaling. * @param $s_y (float) scaling factor for height as percent. 0 is not allowed. * @param $x (int) abscissa of the scaling center. Default is current x position * @param $y (int) ordinate of the scaling center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function ScaleY($s_y, $x='', $y='') { $this->Scale(100, $s_y, $x, $y); } /** * Vertical and horizontal proportional Scaling. * @param $s (float) scaling factor for width and height as percent. 0 is not allowed. * @param $x (int) abscissa of the scaling center. Default is current x position * @param $y (int) ordinate of the scaling center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function ScaleXY($s, $x='', $y='') { $this->Scale($s, $s, $x, $y); } /** * Vertical and horizontal non-proportional Scaling. * @param $s_x (float) scaling factor for width as percent. 0 is not allowed. * @param $s_y (float) scaling factor for height as percent. 0 is not allowed. * @param $x (int) abscissa of the scaling center. Default is current x position * @param $y (int) ordinate of the scaling center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function Scale($s_x, $s_y, $x='', $y='') { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } if (($s_x == 0) OR ($s_y == 0)) { $this->Error('Please do not use values equal to zero for scaling'); } $y = ($this->h - $y) * $this->k; $x *= $this->k; //calculate elements of transformation matrix $s_x /= 100; $s_y /= 100; $tm = array(); $tm[0] = $s_x; $tm[1] = 0; $tm[2] = 0; $tm[3] = $s_y; $tm[4] = $x * (1 - $s_x); $tm[5] = $y * (1 - $s_y); //scale the coordinate system $this->Transform($tm); } /** * Horizontal Mirroring. * @param $x (int) abscissa of the point. Default is current x position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function MirrorH($x='') { $this->Scale(-100, 100, $x); } /** * Verical Mirroring. * @param $y (int) ordinate of the point. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function MirrorV($y='') { $this->Scale(100, -100, '', $y); } /** * Point reflection mirroring. * @param $x (int) abscissa of the point. Default is current x position * @param $y (int) ordinate of the point. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function MirrorP($x='',$y='') { $this->Scale(-100, -100, $x, $y); } /** * Reflection against a straight line through point (x, y) with the gradient angle (angle). * @param $angle (float) gradient angle of the straight line. Default is 0 (horizontal line). * @param $x (int) abscissa of the point. Default is current x position * @param $y (int) ordinate of the point. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function MirrorL($angle=0, $x='',$y='') { $this->Scale(-100, 100, $x, $y); $this->Rotate(-2*($angle-90), $x, $y); } /** * Translate graphic object horizontally. * @param $t_x (int) movement to the right (or left for RTL) * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function TranslateX($t_x) { $this->Translate($t_x, 0); } /** * Translate graphic object vertically. * @param $t_y (int) movement to the bottom * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function TranslateY($t_y) { $this->Translate(0, $t_y); } /** * Translate graphic object horizontally and vertically. * @param $t_x (int) movement to the right * @param $t_y (int) movement to the bottom * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function Translate($t_x, $t_y) { //calculate elements of transformation matrix $tm = array(); $tm[0] = 1; $tm[1] = 0; $tm[2] = 0; $tm[3] = 1; $tm[4] = $t_x * $this->k; $tm[5] = -$t_y * $this->k; //translate the coordinate system $this->Transform($tm); } /** * Rotate object. * @param $angle (float) angle in degrees for counter-clockwise rotation * @param $x (int) abscissa of the rotation center. Default is current x position * @param $y (int) ordinate of the rotation center. Default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function Rotate($angle, $x='', $y='') { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } $y = ($this->h - $y) * $this->k; $x *= $this->k; //calculate elements of transformation matrix $tm = array(); $tm[0] = cos(deg2rad($angle)); $tm[1] = sin(deg2rad($angle)); $tm[2] = -$tm[1]; $tm[3] = $tm[0]; $tm[4] = $x + ($tm[1] * $y) - ($tm[0] * $x); $tm[5] = $y - ($tm[0] * $y) - ($tm[1] * $x); //rotate the coordinate system around ($x,$y) $this->Transform($tm); } /** * Skew horizontally. * @param $angle_x (float) angle in degrees between -90 (skew to the left) and 90 (skew to the right) * @param $x (int) abscissa of the skewing center. default is current x position * @param $y (int) ordinate of the skewing center. default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function SkewX($angle_x, $x='', $y='') { $this->Skew($angle_x, 0, $x, $y); } /** * Skew vertically. * @param $angle_y (float) angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) * @param $x (int) abscissa of the skewing center. default is current x position * @param $y (int) ordinate of the skewing center. default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function SkewY($angle_y, $x='', $y='') { $this->Skew(0, $angle_y, $x, $y); } /** * Skew. * @param $angle_x (float) angle in degrees between -90 (skew to the left) and 90 (skew to the right) * @param $angle_y (float) angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) * @param $x (int) abscissa of the skewing center. default is current x position * @param $y (int) ordinate of the skewing center. default is current y position * @public * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ public function Skew($angle_x, $angle_y, $x='', $y='') { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } if (($angle_x <= -90) OR ($angle_x >= 90) OR ($angle_y <= -90) OR ($angle_y >= 90)) { $this->Error('Please use values between -90 and +90 degrees for Skewing.'); } $x *= $this->k; $y = ($this->h - $y) * $this->k; //calculate elements of transformation matrix $tm = array(); $tm[0] = 1; $tm[1] = tan(deg2rad($angle_y)); $tm[2] = tan(deg2rad($angle_x)); $tm[3] = 1; $tm[4] = -$tm[2] * $y; $tm[5] = -$tm[1] * $x; //skew the coordinate system $this->Transform($tm); } /** * Apply graphic transformations. * @param $tm (array) transformation matrix * @protected * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ protected function Transform($tm) { $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5])); // add tranformation matrix $this->transfmatrix[$this->transfmatrix_key][] = array('a' => $tm[0], 'b' => $tm[1], 'c' => $tm[2], 'd' => $tm[3], 'e' => $tm[4], 'f' => $tm[5]); // update transformation mark if ($this->inxobj) { // we are inside an XObject template if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) { $key = key($this->xobjects[$this->xobjid]['transfmrk']); $this->xobjects[$this->xobjid]['transfmrk'][$key] = strlen($this->xobjects[$this->xobjid]['outdata']); } } elseif (end($this->transfmrk[$this->page]) !== false) { $key = key($this->transfmrk[$this->page]); $this->transfmrk[$this->page][$key] = $this->pagelen[$this->page]; } } // END TRANSFORMATIONS SECTION ------------------------- // START GRAPHIC FUNCTIONS SECTION --------------------- // The following section is based on the code provided by David Hernandez Sanz /** * Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page. * @param $width (float) The width. * @public * @since 1.0 * @see Line(), Rect(), Cell(), MultiCell() */ public function SetLineWidth($width) { //Set line width $this->LineWidth = $width; $this->linestyleWidth = sprintf('%.2F w', ($width * $this->k)); if ($this->page > 0) { $this->_out($this->linestyleWidth); } } /** * Returns the current the line width. * @return int Line width * @public * @since 2.1.000 (2008-01-07) * @see Line(), SetLineWidth() */ public function GetLineWidth() { return $this->LineWidth; } /** * Set line style. * @param $style (array) Line style. Array with keys among the following: *
      *
    • width (float): Width of the line in user units.
    • *
    • cap (string): Type of cap to put on the line. Possible values are: * butt, round, square. The difference between "square" and "butt" is that * "square" projects a flat end past the end of the line.
    • *
    • join (string): Type of join. Possible values are: miter, round, * bevel.
    • *
    • dash (mixed): Dash pattern. Is 0 (without dash) or string with * series of length values, which are the lengths of the on and off dashes. * For example: "2" represents 2 on, 2 off, 2 on, 2 off, ...; "2,1" is 2 on, * 1 off, 2 on, 1 off, ...
    • *
    • phase (integer): Modifier on the dash pattern which is used to shift * the point at which the pattern starts.
    • *
    • color (array): Draw color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K).
    • *
    * @param $ret (boolean) if true do not send the command. * @return string the PDF command * @public * @since 2.1.000 (2008-01-08) */ public function SetLineStyle($style, $ret=false) { $s = ''; // string to be returned if (!is_array($style)) { return; } if (isset($style['width'])) { $this->LineWidth = $style['width']; $this->linestyleWidth = sprintf('%.2F w', ($style['width'] * $this->k)); $s .= $this->linestyleWidth.' '; } if (isset($style['cap'])) { $ca = array('butt' => 0, 'round'=> 1, 'square' => 2); if (isset($ca[$style['cap']])) { $this->linestyleCap = $ca[$style['cap']].' J'; $s .= $this->linestyleCap.' '; } } if (isset($style['join'])) { $ja = array('miter' => 0, 'round' => 1, 'bevel' => 2); if (isset($ja[$style['join']])) { $this->linestyleJoin = $ja[$style['join']].' j'; $s .= $this->linestyleJoin.' '; } } if (isset($style['dash'])) { $dash_string = ''; if ($style['dash']) { if (preg_match('/^.+,/', $style['dash']) > 0) { $tab = explode(',', $style['dash']); } else { $tab = array($style['dash']); } $dash_string = ''; foreach ($tab as $i => $v) { if ($i) { $dash_string .= ' '; } $dash_string .= sprintf('%.2F', $v); } } if (!isset($style['phase']) OR !$style['dash']) { $style['phase'] = 0; } $this->linestyleDash = sprintf('[%s] %.2F d', $dash_string, $style['phase']); $s .= $this->linestyleDash.' '; } if (isset($style['color'])) { $s .= $this->SetDrawColorArray($style['color'], true).' '; } if (!$ret) { $this->_out($s); } return $s; } /** * Begin a new subpath by moving the current point to coordinates (x, y), omitting any connecting line segment. * @param $x (float) Abscissa of point. * @param $y (float) Ordinate of point. * @protected * @since 2.1.000 (2008-01-08) */ protected function _outPoint($x, $y) { $this->_out(sprintf('%.2F %.2F m', $x * $this->k, ($this->h - $y) * $this->k)); } /** * Append a straight line segment from the current point to the point (x, y). * The new current point shall be (x, y). * @param $x (float) Abscissa of end point. * @param $y (float) Ordinate of end point. * @protected * @since 2.1.000 (2008-01-08) */ protected function _outLine($x, $y) { $this->_out(sprintf('%.2F %.2F l', $x * $this->k, ($this->h - $y) * $this->k)); } /** * Append a rectangle to the current path as a complete subpath, with lower-left corner (x, y) and dimensions widthand height in user space. * @param $x (float) Abscissa of upper-left corner. * @param $y (float) Ordinate of upper-left corner. * @param $w (float) Width. * @param $h (float) Height. * @param $op (string) options * @protected * @since 2.1.000 (2008-01-08) */ protected function _outRect($x, $y, $w, $h, $op) { $this->_out(sprintf('%.2F %.2F %.2F %.2F re %s', $x * $this->k, ($this->h - $y) * $this->k, $w * $this->k, -$h * $this->k, $op)); } /** * Append a cubic B騷ier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using (x1, y1) and (x2, y2) as the B騷ier control points. * The new current point shall be (x3, y3). * @param $x1 (float) Abscissa of control point 1. * @param $y1 (float) Ordinate of control point 1. * @param $x2 (float) Abscissa of control point 2. * @param $y2 (float) Ordinate of control point 2. * @param $x3 (float) Abscissa of end point. * @param $y3 (float) Ordinate of end point. * @protected * @since 2.1.000 (2008-01-08) */ protected function _outCurve($x1, $y1, $x2, $y2, $x3, $y3) { $this->_out(sprintf('%.2F %.2F %.2F %.2F %.2F %.2F c', $x1 * $this->k, ($this->h - $y1) * $this->k, $x2 * $this->k, ($this->h - $y2) * $this->k, $x3 * $this->k, ($this->h - $y3) * $this->k)); } /** * Append a cubic B騷ier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using the current point and (x2, y2) as the B騷ier control points. * The new current point shall be (x3, y3). * @param $x2 (float) Abscissa of control point 2. * @param $y2 (float) Ordinate of control point 2. * @param $x3 (float) Abscissa of end point. * @param $y3 (float) Ordinate of end point. * @protected * @since 4.9.019 (2010-04-26) */ protected function _outCurveV($x2, $y2, $x3, $y3) { $this->_out(sprintf('%.2F %.2F %.2F %.2F v', $x2 * $this->k, ($this->h - $y2) * $this->k, $x3 * $this->k, ($this->h - $y3) * $this->k)); } /** * Append a cubic B騷ier curve to the current path. The curve shall extend from the current point to the point (x3, y3), using (x1, y1) and (x3, y3) as the B騷ier control points. * The new current point shall be (x3, y3). * @param $x1 (float) Abscissa of control point 1. * @param $y1 (float) Ordinate of control point 1. * @param $x3 (float) Abscissa of end point. * @param $y3 (float) Ordinate of end point. * @protected * @since 2.1.000 (2008-01-08) */ protected function _outCurveY($x1, $y1, $x3, $y3) { $this->_out(sprintf('%.2F %.2F %.2F %.2F y', $x1 * $this->k, ($this->h - $y1) * $this->k, $x3 * $this->k, ($this->h - $y3) * $this->k)); } /** * Draws a line between two points. * @param $x1 (float) Abscissa of first point. * @param $y1 (float) Ordinate of first point. * @param $x2 (float) Abscissa of second point. * @param $y2 (float) Ordinate of second point. * @param $style (array) Line style. Array like for SetLineStyle(). Default value: default line style (empty array). * @public * @since 1.0 * @see SetLineWidth(), SetDrawColor(), SetLineStyle() */ public function Line($x1, $y1, $x2, $y2, $style=array()) { if (is_array($style)) { $this->SetLineStyle($style); } $this->_outPoint($x1, $y1); $this->_outLine($x2, $y2); $this->_out('S'); } /** * Draws a rectangle. * @param $x (float) Abscissa of upper-left corner. * @param $y (float) Ordinate of upper-left corner. * @param $w (float) Width. * @param $h (float) Height. * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $border_style (array) Border style of rectangle. Array with keys among the following: *
      *
    • all: Line style of all borders. Array like for SetLineStyle().
    • *
    • L, T, R, B or combinations: Line style of left, top, right or bottom border. Array like for SetLineStyle().
    • *
    * If a key is not present or is null, not draws the border. Default value: default line style (empty array). * @param $border_style (array) Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). * @public * @since 1.0 * @see SetLineStyle() */ public function Rect($x, $y, $w, $h, $style='', $border_style=array(), $fill_color=array()) { if (!(false === strpos($style, 'F')) AND !empty($fill_color)) { $this->SetFillColorArray($fill_color); } $op = $this->getPathPaintOperator($style); if ((!$border_style) OR (isset($border_style['all']))) { if (isset($border_style['all']) AND $border_style['all']) { $this->SetLineStyle($border_style['all']); $border_style = array(); } } $this->_outRect($x, $y, $w, $h, $op); if ($border_style) { $border_style2 = array(); foreach ($border_style as $line => $value) { $length = strlen($line); for ($i = 0; $i < $length; ++$i) { $border_style2[$line[$i]] = $value; } } $border_style = $border_style2; if (isset($border_style['L']) AND $border_style['L']) { $this->Line($x, $y, $x, $y + $h, $border_style['L']); } if (isset($border_style['T']) AND $border_style['T']) { $this->Line($x, $y, $x + $w, $y, $border_style['T']); } if (isset($border_style['R']) AND $border_style['R']) { $this->Line($x + $w, $y, $x + $w, $y + $h, $border_style['R']); } if (isset($border_style['B']) AND $border_style['B']) { $this->Line($x, $y + $h, $x + $w, $y + $h, $border_style['B']); } } } /** * Draws a Bezier curve. * The Bezier curve is a tangent to the line between the control points at * either end of the curve. * @param $x0 (float) Abscissa of start point. * @param $y0 (float) Ordinate of start point. * @param $x1 (float) Abscissa of control point 1. * @param $y1 (float) Ordinate of control point 1. * @param $x2 (float) Abscissa of control point 2. * @param $y2 (float) Ordinate of control point 2. * @param $x3 (float) Abscissa of end point. * @param $y3 (float) Ordinate of end point. * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $line_style (array) Line style of curve. Array like for SetLineStyle(). Default value: default line style (empty array). * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). * @public * @see SetLineStyle() * @since 2.1.000 (2008-01-08) */ public function Curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3, $style='', $line_style=array(), $fill_color=array()) { if (!(false === strpos($style, 'F')) AND isset($fill_color)) { $this->SetFillColorArray($fill_color); } $op = $this->getPathPaintOperator($style); if ($line_style) { $this->SetLineStyle($line_style); } $this->_outPoint($x0, $y0); $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3); $this->_out($op); } /** * Draws a poly-Bezier curve. * Each Bezier curve segment is a tangent to the line between the control points at * either end of the curve. * @param $x0 (float) Abscissa of start point. * @param $y0 (float) Ordinate of start point. * @param $segments (float) An array of bezier descriptions. Format: array(x1, y1, x2, y2, x3, y3). * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $line_style (array) Line style of curve. Array like for SetLineStyle(). Default value: default line style (empty array). * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). * @public * @see SetLineStyle() * @since 3.0008 (2008-05-12) */ public function Polycurve($x0, $y0, $segments, $style='', $line_style=array(), $fill_color=array()) { if (!(false === strpos($style, 'F')) AND isset($fill_color)) { $this->SetFillColorArray($fill_color); } $op = $this->getPathPaintOperator($style); if ($op == 'f') { $line_style = array(); } if ($line_style) { $this->SetLineStyle($line_style); } $this->_outPoint($x0, $y0); foreach ($segments as $segment) { list($x1, $y1, $x2, $y2, $x3, $y3) = $segment; $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3); } $this->_out($op); } /** * Draws an ellipse. * An ellipse is formed from n Bezier curves. * @param $x0 (float) Abscissa of center point. * @param $y0 (float) Ordinate of center point. * @param $rx (float) Horizontal radius. * @param $ry (float) Vertical radius (if ry = 0 then is a circle, see Circle()). Default value: 0. * @param $angle: (float) Angle oriented (anti-clockwise). Default value: 0. * @param $astart: (float) Angle start of draw line. Default value: 0. * @param $afinish: (float) Angle finish of draw line. Default value: 360. * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $line_style (array) Line style of ellipse. Array like for SetLineStyle(). Default value: default line style (empty array). * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). * @param $nc (integer) Number of curves used to draw a 90 degrees portion of ellipse. * @author Nicola Asuni * @public * @since 2.1.000 (2008-01-08) */ public function Ellipse($x0, $y0, $rx, $ry='', $angle=0, $astart=0, $afinish=360, $style='', $line_style=array(), $fill_color=array(), $nc=2) { if ($this->empty_string($ry) OR ($ry == 0)) { $ry = $rx; } if (!(false === strpos($style, 'F')) AND isset($fill_color)) { $this->SetFillColorArray($fill_color); } $op = $this->getPathPaintOperator($style); if ($op == 'f') { $line_style = array(); } if ($line_style) { $this->SetLineStyle($line_style); } $this->_outellipticalarc($x0, $y0, $rx, $ry, $angle, $astart, $afinish, false, $nc, true, true, false); $this->_out($op); } /** * Append an elliptical arc to the current path. * An ellipse is formed from n Bezier curves. * @param $xc (float) Abscissa of center point. * @param $yc (float) Ordinate of center point. * @param $rx (float) Horizontal radius. * @param $ry (float) Vertical radius (if ry = 0 then is a circle, see Circle()). Default value: 0. * @param $xang: (float) Angle between the X-axis and the major axis of the ellipse. Default value: 0. * @param $angs: (float) Angle start of draw line. Default value: 0. * @param $angf: (float) Angle finish of draw line. Default value: 360. * @param $pie (boolean) if true do not mark the border point (used to draw pie sectors). * @param $nc (integer) Number of curves used to draw a 90 degrees portion of ellipse. * @param $startpoint (boolean) if true output a starting point. * @param $ccw (boolean) if true draws in counter-clockwise. * @param $svg (boolean) if true the angles are in svg mode (already calculated). * @return array bounding box coordinates (x min, y min, x max, y max) * @author Nicola Asuni * @protected * @since 4.9.019 (2010-04-26) */ protected function _outellipticalarc($xc, $yc, $rx, $ry, $xang=0, $angs=0, $angf=360, $pie=false, $nc=2, $startpoint=true, $ccw=true, $svg=false) { $k = $this->k; if ($nc < 2) { $nc = 2; } $xmin = 2147483647; $ymin = 2147483647; $xmax = 0; $ymax = 0; if ($pie) { // center of the arc $this->_outPoint($xc, $yc); } $xang = deg2rad((float) $xang); $angs = deg2rad((float) $angs); $angf = deg2rad((float) $angf); if ($svg) { $as = $angs; $af = $angf; } else { $as = atan2((sin($angs) / $ry), (cos($angs) / $rx)); $af = atan2((sin($angf) / $ry), (cos($angf) / $rx)); } if ($as < 0) { $as += (2 * M_PI); } if ($af < 0) { $af += (2 * M_PI); } if ($ccw AND ($as > $af)) { // reverse rotation $as -= (2 * M_PI); } elseif (!$ccw AND ($as < $af)) { // reverse rotation $af -= (2 * M_PI); } $total_angle = ($af - $as); if ($nc < 2) { $nc = 2; } // total arcs to draw $nc *= (2 * abs($total_angle) / M_PI); $nc = round($nc) + 1; // angle of each arc $arcang = ($total_angle / $nc); // center point in PDF coordinates $x0 = $xc; $y0 = ($this->h - $yc); // starting angle $ang = $as; $alpha = sin($arcang) * ((sqrt(4 + (3 * pow(tan(($arcang) / 2), 2))) - 1) / 3); $cos_xang = cos($xang); $sin_xang = sin($xang); $cos_ang = cos($ang); $sin_ang = sin($ang); // first arc point $px1 = $x0 + ($rx * $cos_xang * $cos_ang) - ($ry * $sin_xang * $sin_ang); $py1 = $y0 + ($rx * $sin_xang * $cos_ang) + ($ry * $cos_xang * $sin_ang); // first Bezier control point $qx1 = ($alpha * ((-$rx * $cos_xang * $sin_ang) - ($ry * $sin_xang * $cos_ang))); $qy1 = ($alpha * ((-$rx * $sin_xang * $sin_ang) + ($ry * $cos_xang * $cos_ang))); if ($pie) { // line from center to arc starting point $this->_outLine($px1, $this->h - $py1); } elseif ($startpoint) { // arc starting point $this->_outPoint($px1, $this->h - $py1); } // draw arcs for ($i = 1; $i <= $nc; ++$i) { // starting angle $ang = $as + ($i * $arcang); if ($i == $nc) { $ang = $af; } $cos_ang = cos($ang); $sin_ang = sin($ang); // second arc point $px2 = $x0 + ($rx * $cos_xang * $cos_ang) - ($ry * $sin_xang * $sin_ang); $py2 = $y0 + ($rx * $sin_xang * $cos_ang) + ($ry * $cos_xang * $sin_ang); // second Bezier control point $qx2 = ($alpha * ((-$rx * $cos_xang * $sin_ang) - ($ry * $sin_xang * $cos_ang))); $qy2 = ($alpha * ((-$rx * $sin_xang * $sin_ang) + ($ry * $cos_xang * $cos_ang))); // draw arc $cx1 = ($px1 + $qx1); $cy1 = ($this->h - ($py1 + $qy1)); $cx2 = ($px2 - $qx2); $cy2 = ($this->h - ($py2 - $qy2)); $cx3 = $px2; $cy3 = ($this->h - $py2); $this->_outCurve($cx1, $cy1, $cx2, $cy2, $cx3, $cy3); // get bounding box coordinates $xmin = min($xmin, $cx1, $cx2, $cx3); $ymin = min($ymin, $cy1, $cy2, $cy3); $xmax = max($xmax, $cx1, $cx2, $cx3); $ymax = max($ymax, $cy1, $cy2, $cy3); // move to next point $px1 = $px2; $py1 = $py2; $qx1 = $qx2; $qy1 = $qy2; } if ($pie) { $this->_outLine($xc, $yc); // get bounding box coordinates $xmin = min($xmin, $xc); $ymin = min($ymin, $yc); $xmax = max($xmax, $xc); $ymax = max($ymax, $yc); } return array($xmin, $ymin, $xmax, $ymax); } /** * Draws a circle. * A circle is formed from n Bezier curves. * @param $x0 (float) Abscissa of center point. * @param $y0 (float) Ordinate of center point. * @param $r (float) Radius. * @param $angstr: (float) Angle start of draw line. Default value: 0. * @param $angend: (float) Angle finish of draw line. Default value: 360. * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $line_style (array) Line style of circle. Array like for SetLineStyle(). Default value: default line style (empty array). * @param $fill_color (array) Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @param $nc (integer) Number of curves used to draw a 90 degrees portion of circle. * @public * @since 2.1.000 (2008-01-08) */ public function Circle($x0, $y0, $r, $angstr=0, $angend=360, $style='', $line_style=array(), $fill_color=array(), $nc=2) { $this->Ellipse($x0, $y0, $r, $r, 0, $angstr, $angend, $style, $line_style, $fill_color, $nc); } /** * Draws a polygonal line * @param $p (array) Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $line_style (array) Line style of polygon. Array with keys among the following: *
      *
    • all: Line style of all lines. Array like for SetLineStyle().
    • *
    • 0 to ($np - 1): Line style of each line. Array like for SetLineStyle().
    • *
    * If a key is not present or is null, not draws the line. Default value is default line style (empty array). * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). * @since 4.8.003 (2009-09-15) * @public */ public function PolyLine($p, $style='', $line_style=array(), $fill_color=array()) { $this->Polygon($p, $style, $line_style, $fill_color, false); } /** * Draws a polygon. * @param $p (array) Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $line_style (array) Line style of polygon. Array with keys among the following: *
      *
    • all: Line style of all lines. Array like for SetLineStyle().
    • *
    • 0 to ($np - 1): Line style of each line. Array like for SetLineStyle().
    • *
    * If a key is not present or is null, not draws the line. Default value is default line style (empty array). * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). * @param $closed (boolean) if true the polygon is closes, otherwise will remain open * @public * @since 2.1.000 (2008-01-08) */ public function Polygon($p, $style='', $line_style=array(), $fill_color=array(), $closed=true) { $nc = count($p); // number of coordinates $np = $nc / 2; // number of points if ($closed) { // close polygon by adding the first 2 points at the end (one line) for ($i = 0; $i < 4; ++$i) { $p[$nc + $i] = $p[$i]; } // copy style for the last added line if (isset($line_style[0])) { $line_style[$np] = $line_style[0]; } $nc += 4; } if (!(false === strpos($style, 'F')) AND isset($fill_color)) { $this->SetFillColorArray($fill_color); } $op = $this->getPathPaintOperator($style); if ($op == 'f') { $line_style = array(); } $draw = true; if ($line_style) { if (isset($line_style['all'])) { $this->SetLineStyle($line_style['all']); } else { $draw = false; if ($op == 'B') { // draw fill $op = 'f'; $this->_outPoint($p[0], $p[1]); for ($i = 2; $i < $nc; $i = $i + 2) { $this->_outLine($p[$i], $p[$i + 1]); } $this->_out($op); } // draw outline $this->_outPoint($p[0], $p[1]); for ($i = 2; $i < $nc; $i = $i + 2) { $line_num = ($i / 2) - 1; if (isset($line_style[$line_num])) { if ($line_style[$line_num] != 0) { if (is_array($line_style[$line_num])) { $this->_out('S'); $this->SetLineStyle($line_style[$line_num]); $this->_outPoint($p[$i - 2], $p[$i - 1]); $this->_outLine($p[$i], $p[$i + 1]); $this->_out('S'); $this->_outPoint($p[$i], $p[$i + 1]); } else { $this->_outLine($p[$i], $p[$i + 1]); } } } else { $this->_outLine($p[$i], $p[$i + 1]); } } $this->_out($op); } } if ($draw) { $this->_outPoint($p[0], $p[1]); for ($i = 2; $i < $nc; $i = $i + 2) { $this->_outLine($p[$i], $p[$i + 1]); } $this->_out($op); } } /** * Draws a regular polygon. * @param $x0 (float) Abscissa of center point. * @param $y0 (float) Ordinate of center point. * @param $r: (float) Radius of inscribed circle. * @param $ns (integer) Number of sides. * @param $angle (float) Angle oriented (anti-clockwise). Default value: 0. * @param $draw_circle (boolean) Draw inscribed circle or not. Default value: false. * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $line_style (array) Line style of polygon sides. Array with keys among the following: *
      *
    • all: Line style of all sides. Array like for SetLineStyle().
    • *
    • 0 to ($ns - 1): Line style of each side. Array like for SetLineStyle().
    • *
    * If a key is not present or is null, not draws the side. Default value is default line style (empty array). * @param $fill_color (array) Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @param $circle_style (string) Style of rendering of inscribed circle (if draws). Possible values are: *
      *
    • D or empty string: Draw (default).
    • *
    • F: Fill.
    • *
    • DF or FD: Draw and fill.
    • *
    • CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).
    • *
    • CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).
    • *
    * @param $circle_outLine_style (array) Line style of inscribed circle (if draws). Array like for SetLineStyle(). Default value: default line style (empty array). * @param $circle_fill_color (array) Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). * @public * @since 2.1.000 (2008-01-08) */ public function RegularPolygon($x0, $y0, $r, $ns, $angle=0, $draw_circle=false, $style='', $line_style=array(), $fill_color=array(), $circle_style='', $circle_outLine_style=array(), $circle_fill_color=array()) { if (3 > $ns) { $ns = 3; } if ($draw_circle) { $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color); } $p = array(); for ($i = 0; $i < $ns; ++$i) { $a = $angle + ($i * 360 / $ns); $a_rad = deg2rad((float) $a); $p[] = $x0 + ($r * sin($a_rad)); $p[] = $y0 + ($r * cos($a_rad)); } $this->Polygon($p, $style, $line_style, $fill_color); } /** * Draws a star polygon * @param $x0 (float) Abscissa of center point. * @param $y0 (float) Ordinate of center point. * @param $r (float) Radius of inscribed circle. * @param $nv (integer) Number of vertices. * @param $ng (integer) Number of gap (if ($ng % $nv = 1) then is a regular polygon). * @param $angle: (float) Angle oriented (anti-clockwise). Default value: 0. * @param $draw_circle: (boolean) Draw inscribed circle or not. Default value is false. * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $line_style (array) Line style of polygon sides. Array with keys among the following: *
      *
    • all: Line style of all sides. Array like for * SetLineStyle().
    • *
    • 0 to (n - 1): Line style of each side. Array like for SetLineStyle().
    • *
    * If a key is not present or is null, not draws the side. Default value is default line style (empty array). * @param $fill_color (array) Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @param $circle_style (string) Style of rendering of inscribed circle (if draws). Possible values are: *
      *
    • D or empty string: Draw (default).
    • *
    • F: Fill.
    • *
    • DF or FD: Draw and fill.
    • *
    • CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).
    • *
    • CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).
    • *
    * @param $circle_outLine_style (array) Line style of inscribed circle (if draws). Array like for SetLineStyle(). Default value: default line style (empty array). * @param $circle_fill_color (array) Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). * @public * @since 2.1.000 (2008-01-08) */ public function StarPolygon($x0, $y0, $r, $nv, $ng, $angle=0, $draw_circle=false, $style='', $line_style=array(), $fill_color=array(), $circle_style='', $circle_outLine_style=array(), $circle_fill_color=array()) { if ($nv < 2) { $nv = 2; } if ($draw_circle) { $this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color); } $p2 = array(); $visited = array(); for ($i = 0; $i < $nv; ++$i) { $a = $angle + ($i * 360 / $nv); $a_rad = deg2rad((float) $a); $p2[] = $x0 + ($r * sin($a_rad)); $p2[] = $y0 + ($r * cos($a_rad)); $visited[] = false; } $p = array(); $i = 0; do { $p[] = $p2[$i * 2]; $p[] = $p2[($i * 2) + 1]; $visited[$i] = true; $i += $ng; $i %= $nv; } while (!$visited[$i]); $this->Polygon($p, $style, $line_style, $fill_color); } /** * Draws a rounded rectangle. * @param $x (float) Abscissa of upper-left corner. * @param $y (float) Ordinate of upper-left corner. * @param $w (float) Width. * @param $h (float) Height. * @param $r (float) the radius of the circle used to round off the corners of the rectangle. * @param $round_corner (string) Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top left, top right, bottom right and bottom left. Default value: all rounded corner ("1111"). * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $border_style (array) Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). * @public * @since 2.1.000 (2008-01-08) */ public function RoundedRect($x, $y, $w, $h, $r, $round_corner='1111', $style='', $border_style=array(), $fill_color=array()) { $this->RoundedRectXY($x, $y, $w, $h, $r, $r, $round_corner, $style, $border_style, $fill_color); } /** * Draws a rounded rectangle. * @param $x (float) Abscissa of upper-left corner. * @param $y (float) Ordinate of upper-left corner. * @param $w (float) Width. * @param $h (float) Height. * @param $rx (float) the x-axis radius of the ellipse used to round off the corners of the rectangle. * @param $ry (float) the y-axis radius of the ellipse used to round off the corners of the rectangle. * @param $round_corner (string) Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top left, top right, bottom right and bottom left. Default value: all rounded corner ("1111"). * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $border_style (array) Border style of rectangle. Array like for SetLineStyle(). Default value: default line style (empty array). * @param $fill_color (array) Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). * @public * @since 4.9.019 (2010-04-22) */ public function RoundedRectXY($x, $y, $w, $h, $rx, $ry, $round_corner='1111', $style='', $border_style=array(), $fill_color=array()) { if (($round_corner == '0000') OR (($rx == $ry) AND ($rx == 0))) { // Not rounded $this->Rect($x, $y, $w, $h, $style, $border_style, $fill_color); return; } // Rounded if (!(false === strpos($style, 'F')) AND isset($fill_color)) { $this->SetFillColorArray($fill_color); } $op = $this->getPathPaintOperator($style); if ($op == 'f') { $border_style = array(); } if ($border_style) { $this->SetLineStyle($border_style); } $MyArc = 4 / 3 * (sqrt(2) - 1); $this->_outPoint($x + $rx, $y); $xc = $x + $w - $rx; $yc = $y + $ry; $this->_outLine($xc, $y); if ($round_corner[0]) { $this->_outCurve($xc + ($rx * $MyArc), $yc - $ry, $xc + $rx, $yc - ($ry * $MyArc), $xc + $rx, $yc); } else { $this->_outLine($x + $w, $y); } $xc = $x + $w - $rx; $yc = $y + $h - $ry; $this->_outLine($x + $w, $yc); if ($round_corner[1]) { $this->_outCurve($xc + $rx, $yc + ($ry * $MyArc), $xc + ($rx * $MyArc), $yc + $ry, $xc, $yc + $ry); } else { $this->_outLine($x + $w, $y + $h); } $xc = $x + $rx; $yc = $y + $h - $ry; $this->_outLine($xc, $y + $h); if ($round_corner[2]) { $this->_outCurve($xc - ($rx * $MyArc), $yc + $ry, $xc - $rx, $yc + ($ry * $MyArc), $xc - $rx, $yc); } else { $this->_outLine($x, $y + $h); } $xc = $x + $rx; $yc = $y + $ry; $this->_outLine($x, $yc); if ($round_corner[3]) { $this->_outCurve($xc - $rx, $yc - ($ry * $MyArc), $xc - ($rx * $MyArc), $yc - $ry, $xc, $yc - $ry); } else { $this->_outLine($x, $y); $this->_outLine($x + $rx, $y); } $this->_out($op); } /** * Draws a grahic arrow. * @param $x0 (float) Abscissa of first point. * @param $y0 (float) Ordinate of first point. * @param $x1 (float) Abscissa of second point. * @param $y1 (float) Ordinate of second point. * @param $head_style (int) (0 = draw only arrowhead arms, 1 = draw closed arrowhead, but no fill, 2 = closed and filled arrowhead, 3 = filled arrowhead) * @param $arm_size (float) length of arrowhead arms * @param $arm_angle (int) angle between an arm and the shaft * @author Piotr Galecki, Nicola Asuni, Andy Meier * @since 4.6.018 (2009-07-10) */ public function Arrow($x0, $y0, $x1, $y1, $head_style=0, $arm_size=5, $arm_angle=15) { // getting arrow direction angle // 0 deg angle is when both arms go along X axis. angle grows clockwise. $dir_angle = atan2(($y0 - $y1), ($x0 - $x1)); if ($dir_angle < 0) { $dir_angle += (2 * M_PI); } $arm_angle = deg2rad($arm_angle); $sx1 = $x1; $sy1 = $y1; if ($head_style > 0) { // calculate the stopping point for the arrow shaft $sx1 = $x1 + (($arm_size - $this->LineWidth) * cos($dir_angle)); $sy1 = $y1 + (($arm_size - $this->LineWidth) * sin($dir_angle)); } // main arrow line / shaft $this->Line($x0, $y0, $sx1, $sy1); // left arrowhead arm tip $x2L = $x1 + ($arm_size * cos($dir_angle + $arm_angle)); $y2L = $y1 + ($arm_size * sin($dir_angle + $arm_angle)); // right arrowhead arm tip $x2R = $x1 + ($arm_size * cos($dir_angle - $arm_angle)); $y2R = $y1 + ($arm_size * sin($dir_angle - $arm_angle)); $mode = 'D'; $style = array(); switch ($head_style) { case 0: { // draw only arrowhead arms $mode = 'D'; $style = array(1, 1, 0); break; } case 1: { // draw closed arrowhead, but no fill $mode = 'D'; break; } case 2: { // closed and filled arrowhead $mode = 'DF'; break; } case 3: { // filled arrowhead $mode = 'F'; break; } } $this->Polygon(array($x2L, $y2L, $x1, $y1, $x2R, $y2R), $mode, $style, array()); } // END GRAPHIC FUNCTIONS SECTION ----------------------- // BIDIRECTIONAL TEXT SECTION -------------------------- /** * Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). * @param $str (string) string to manipulate. * @param $setbom (bool) if true set the Byte Order Mark (BOM = 0xFEFF) * @param $forcertl (bool) if true forces RTL text direction * @return string * @protected * @author Nicola Asuni * @since 2.1.000 (2008-01-08) */ protected function utf8StrRev($str, $setbom=false, $forcertl=false) { return $this->utf8StrArrRev($this->UTF8StringToArray($str), $str, $setbom, $forcertl); } /** * Reverse the RLT substrings array using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). * @param $arr (array) array of unicode values. * @param $str (string) string to manipulate (or empty value). * @param $setbom (bool) if true set the Byte Order Mark (BOM = 0xFEFF) * @param $forcertl (bool) if true forces RTL text direction * @return string * @protected * @author Nicola Asuni * @since 4.9.000 (2010-03-27) */ protected function utf8StrArrRev($arr, $str='', $setbom=false, $forcertl=false) { return $this->arrUTF8ToUTF16BE($this->utf8Bidi($arr, $str, $forcertl), $setbom); } /** * Reverse the RLT substrings using the Bidirectional Algorithm (http://unicode.org/reports/tr9/). * @param $ta (array) array of characters composing the string. * @param $str (string) string to process * @param $forcertl (bool) if 'R' forces RTL, if 'L' forces LTR * @return array of unicode chars * @author Nicola Asuni * @protected * @since 2.4.000 (2008-03-06) */ protected function utf8Bidi($ta, $str='', $forcertl=false) { // paragraph embedding level $pel = 0; // max level $maxlevel = 0; if ($this->empty_string($str)) { // create string from array $str = $this->UTF8ArrSubString($ta); } // check if string contains arabic text if (preg_match($this->unicode->uni_RE_PATTERN_ARABIC, $str)) { $arabic = true; } else { $arabic = false; } // check if string contains RTL text if (!($forcertl OR $arabic OR preg_match($this->unicode->uni_RE_PATTERN_RTL, $str))) { return $ta; } // get number of chars $numchars = count($ta); if ($forcertl == 'R') { $pel = 1; } elseif ($forcertl == 'L') { $pel = 0; } else { // P2. In each paragraph, find the first character of type L, AL, or R. // P3. If a character is found in P2 and it is of type AL or R, then set the paragraph embedding level to one; otherwise, set it to zero. for ($i=0; $i < $numchars; ++$i) { $type = $this->unicode->uni_type[$ta[$i]]; if ($type == 'L') { $pel = 0; break; } elseif (($type == 'AL') OR ($type == 'R')) { $pel = 1; break; } } } // Current Embedding Level $cel = $pel; // directional override status $dos = 'N'; $remember = array(); // start-of-level-run $sor = $pel % 2 ? 'R' : 'L'; $eor = $sor; // Array of characters data $chardata = Array(); // X1. Begin by setting the current embedding level to the paragraph embedding level. Set the directional override status to neutral. Process each character iteratively, applying rules X2 through X9. Only embedding levels from 0 to 61 are valid in this phase. // In the resolution of levels in rules I1 and I2, the maximum embedding level of 62 can be reached. for ($i=0; $i < $numchars; ++$i) { if ($ta[$i] == $this->unicode->uni_RLE) { // X2. With each RLE, compute the least greater odd embedding level. // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral. // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. $next_level = $cel + ($cel % 2) + 1; if ($next_level < 62) { $remember[] = array('num' => $this->unicode->uni_RLE, 'cel' => $cel, 'dos' => $dos); $cel = $next_level; $dos = 'N'; $sor = $eor; $eor = $cel % 2 ? 'R' : 'L'; } } elseif ($ta[$i] == $this->unicode->uni_LRE) { // X3. With each LRE, compute the least greater even embedding level. // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to neutral. // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. $next_level = $cel + 2 - ($cel % 2); if ( $next_level < 62 ) { $remember[] = array('num' => $this->unicode->uni_LRE, 'cel' => $cel, 'dos' => $dos); $cel = $next_level; $dos = 'N'; $sor = $eor; $eor = $cel % 2 ? 'R' : 'L'; } } elseif ($ta[$i] == $this->unicode->uni_RLO) { // X4. With each RLO, compute the least greater odd embedding level. // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to right-to-left. // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. $next_level = $cel + ($cel % 2) + 1; if ($next_level < 62) { $remember[] = array('num' => $this->unicode->uni_RLO, 'cel' => $cel, 'dos' => $dos); $cel = $next_level; $dos = 'R'; $sor = $eor; $eor = $cel % 2 ? 'R' : 'L'; } } elseif ($ta[$i] == $this->unicode->uni_LRO) { // X5. With each LRO, compute the least greater even embedding level. // a. If this new level would be valid, then this embedding code is valid. Remember (push) the current embedding level and override status. Reset the current level to this new level, and reset the override status to left-to-right. // b. If the new level would not be valid, then this code is invalid. Do not change the current level or override status. $next_level = $cel + 2 - ($cel % 2); if ( $next_level < 62 ) { $remember[] = array('num' => $this->unicode->uni_LRO, 'cel' => $cel, 'dos' => $dos); $cel = $next_level; $dos = 'L'; $sor = $eor; $eor = $cel % 2 ? 'R' : 'L'; } } elseif ($ta[$i] == $this->unicode->uni_PDF) { // X7. With each PDF, determine the matching embedding or override code. If there was a valid matching code, restore (pop) the last remembered (pushed) embedding level and directional override. if (count($remember)) { $last = count($remember ) - 1; if (($remember[$last]['num'] == $this->unicode->uni_RLE) OR ($remember[$last]['num'] == $this->unicode->uni_LRE) OR ($remember[$last]['num'] == $this->unicode->uni_RLO) OR ($remember[$last]['num'] == $this->unicode->uni_LRO)) { $match = array_pop($remember); $cel = $match['cel']; $dos = $match['dos']; $sor = $eor; $eor = ($cel > $match['cel'] ? $cel : $match['cel']) % 2 ? 'R' : 'L'; } } } elseif (($ta[$i] != $this->unicode->uni_RLE) AND ($ta[$i] != $this->unicode->uni_LRE) AND ($ta[$i] != $this->unicode->uni_RLO) AND ($ta[$i] != $this->unicode->uni_LRO) AND ($ta[$i] != $this->unicode->uni_PDF)) { // X6. For all types besides RLE, LRE, RLO, LRO, and PDF: // a. Set the level of the current character to the current embedding level. // b. Whenever the directional override status is not neutral, reset the current character type to the directional override status. if ($dos != 'N') { $chardir = $dos; } else { if (isset($this->unicode->uni_type[$ta[$i]])) { $chardir = $this->unicode->uni_type[$ta[$i]]; } else { $chardir = 'L'; } } // stores string characters and other information $chardata[] = array('char' => $ta[$i], 'level' => $cel, 'type' => $chardir, 'sor' => $sor, 'eor' => $eor); } } // end for each char // X8. All explicit directional embeddings and overrides are completely terminated at the end of each paragraph. Paragraph separators are not included in the embedding. // X9. Remove all RLE, LRE, RLO, LRO, PDF, and BN codes. // X10. The remaining rules are applied to each run of characters at the same level. For each run, determine the start-of-level-run (sor) and end-of-level-run (eor) type, either L or R. This depends on the higher of the two levels on either side of the boundary (at the start or end of the paragraph, the level of the 'other' run is the base embedding level). If the higher level is odd, the type is R; otherwise, it is L. // 3.3.3 Resolving Weak Types // Weak types are now resolved one level run at a time. At level run boundaries where the type of the character on the other side of the boundary is required, the type assigned to sor or eor is used. // Nonspacing marks are now resolved based on the previous characters. $numchars = count($chardata); // W1. Examine each nonspacing mark (NSM) in the level run, and change the type of the NSM to the type of the previous character. If the NSM is at the start of the level run, it will get the type of sor. $prevlevel = -1; // track level changes $levcount = 0; // counts consecutive chars at the same level for ($i=0; $i < $numchars; ++$i) { if ($chardata[$i]['type'] == 'NSM') { if ($levcount) { $chardata[$i]['type'] = $chardata[$i]['sor']; } elseif ($i > 0) { $chardata[$i]['type'] = $chardata[($i-1)]['type']; } } if ($chardata[$i]['level'] != $prevlevel) { $levcount = 0; } else { ++$levcount; } $prevlevel = $chardata[$i]['level']; } // W2. Search backward from each instance of a European number until the first strong type (R, L, AL, or sor) is found. If an AL is found, change the type of the European number to Arabic number. $prevlevel = -1; $levcount = 0; for ($i=0; $i < $numchars; ++$i) { if ($chardata[$i]['char'] == 'EN') { for ($j=$levcount; $j >= 0; $j--) { if ($chardata[$j]['type'] == 'AL') { $chardata[$i]['type'] = 'AN'; } elseif (($chardata[$j]['type'] == 'L') OR ($chardata[$j]['type'] == 'R')) { break; } } } if ($chardata[$i]['level'] != $prevlevel) { $levcount = 0; } else { ++$levcount; } $prevlevel = $chardata[$i]['level']; } // W3. Change all ALs to R. for ($i=0; $i < $numchars; ++$i) { if ($chardata[$i]['type'] == 'AL') { $chardata[$i]['type'] = 'R'; } } // W4. A single European separator between two European numbers changes to a European number. A single common separator between two numbers of the same type changes to that type. $prevlevel = -1; $levcount = 0; for ($i=0; $i < $numchars; ++$i) { if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) { if (($chardata[$i]['type'] == 'ES') AND ($chardata[($i-1)]['type'] == 'EN') AND ($chardata[($i+1)]['type'] == 'EN')) { $chardata[$i]['type'] = 'EN'; } elseif (($chardata[$i]['type'] == 'CS') AND ($chardata[($i-1)]['type'] == 'EN') AND ($chardata[($i+1)]['type'] == 'EN')) { $chardata[$i]['type'] = 'EN'; } elseif (($chardata[$i]['type'] == 'CS') AND ($chardata[($i-1)]['type'] == 'AN') AND ($chardata[($i+1)]['type'] == 'AN')) { $chardata[$i]['type'] = 'AN'; } } if ($chardata[$i]['level'] != $prevlevel) { $levcount = 0; } else { ++$levcount; } $prevlevel = $chardata[$i]['level']; } // W5. A sequence of European terminators adjacent to European numbers changes to all European numbers. $prevlevel = -1; $levcount = 0; for ($i=0; $i < $numchars; ++$i) { if ($chardata[$i]['type'] == 'ET') { if (($levcount > 0) AND ($chardata[($i-1)]['type'] == 'EN')) { $chardata[$i]['type'] = 'EN'; } else { $j = $i+1; while (($j < $numchars) AND ($chardata[$j]['level'] == $prevlevel)) { if ($chardata[$j]['type'] == 'EN') { $chardata[$i]['type'] = 'EN'; break; } elseif ($chardata[$j]['type'] != 'ET') { break; } ++$j; } } } if ($chardata[$i]['level'] != $prevlevel) { $levcount = 0; } else { ++$levcount; } $prevlevel = $chardata[$i]['level']; } // W6. Otherwise, separators and terminators change to Other Neutral. $prevlevel = -1; $levcount = 0; for ($i=0; $i < $numchars; ++$i) { if (($chardata[$i]['type'] == 'ET') OR ($chardata[$i]['type'] == 'ES') OR ($chardata[$i]['type'] == 'CS')) { $chardata[$i]['type'] = 'ON'; } if ($chardata[$i]['level'] != $prevlevel) { $levcount = 0; } else { ++$levcount; } $prevlevel = $chardata[$i]['level']; } //W7. Search backward from each instance of a European number until the first strong type (R, L, or sor) is found. If an L is found, then change the type of the European number to L. $prevlevel = -1; $levcount = 0; for ($i=0; $i < $numchars; ++$i) { if ($chardata[$i]['char'] == 'EN') { for ($j=$levcount; $j >= 0; $j--) { if ($chardata[$j]['type'] == 'L') { $chardata[$i]['type'] = 'L'; } elseif ($chardata[$j]['type'] == 'R') { break; } } } if ($chardata[$i]['level'] != $prevlevel) { $levcount = 0; } else { ++$levcount; } $prevlevel = $chardata[$i]['level']; } // N1. A sequence of neutrals takes the direction of the surrounding strong text if the text on both sides has the same direction. European and Arabic numbers act as if they were R in terms of their influence on neutrals. Start-of-level-run (sor) and end-of-level-run (eor) are used at level run boundaries. $prevlevel = -1; $levcount = 0; for ($i=0; $i < $numchars; ++$i) { if (($levcount > 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) { if (($chardata[$i]['type'] == 'N') AND ($chardata[($i-1)]['type'] == 'L') AND ($chardata[($i+1)]['type'] == 'L')) { $chardata[$i]['type'] = 'L'; } elseif (($chardata[$i]['type'] == 'N') AND (($chardata[($i-1)]['type'] == 'R') OR ($chardata[($i-1)]['type'] == 'EN') OR ($chardata[($i-1)]['type'] == 'AN')) AND (($chardata[($i+1)]['type'] == 'R') OR ($chardata[($i+1)]['type'] == 'EN') OR ($chardata[($i+1)]['type'] == 'AN'))) { $chardata[$i]['type'] = 'R'; } elseif ($chardata[$i]['type'] == 'N') { // N2. Any remaining neutrals take the embedding direction $chardata[$i]['type'] = $chardata[$i]['sor']; } } elseif (($levcount == 0) AND (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] == $prevlevel)) { // first char if (($chardata[$i]['type'] == 'N') AND ($chardata[$i]['sor'] == 'L') AND ($chardata[($i+1)]['type'] == 'L')) { $chardata[$i]['type'] = 'L'; } elseif (($chardata[$i]['type'] == 'N') AND (($chardata[$i]['sor'] == 'R') OR ($chardata[$i]['sor'] == 'EN') OR ($chardata[$i]['sor'] == 'AN')) AND (($chardata[($i+1)]['type'] == 'R') OR ($chardata[($i+1)]['type'] == 'EN') OR ($chardata[($i+1)]['type'] == 'AN'))) { $chardata[$i]['type'] = 'R'; } elseif ($chardata[$i]['type'] == 'N') { // N2. Any remaining neutrals take the embedding direction $chardata[$i]['type'] = $chardata[$i]['sor']; } } elseif (($levcount > 0) AND ((($i+1) == $numchars) OR (($i+1) < $numchars) AND ($chardata[($i+1)]['level'] != $prevlevel))) { //last char if (($chardata[$i]['type'] == 'N') AND ($chardata[($i-1)]['type'] == 'L') AND ($chardata[$i]['eor'] == 'L')) { $chardata[$i]['type'] = 'L'; } elseif (($chardata[$i]['type'] == 'N') AND (($chardata[($i-1)]['type'] == 'R') OR ($chardata[($i-1)]['type'] == 'EN') OR ($chardata[($i-1)]['type'] == 'AN')) AND (($chardata[$i]['eor'] == 'R') OR ($chardata[$i]['eor'] == 'EN') OR ($chardata[$i]['eor'] == 'AN'))) { $chardata[$i]['type'] = 'R'; } elseif ($chardata[$i]['type'] == 'N') { // N2. Any remaining neutrals take the embedding direction $chardata[$i]['type'] = $chardata[$i]['sor']; } } elseif ($chardata[$i]['type'] == 'N') { // N2. Any remaining neutrals take the embedding direction $chardata[$i]['type'] = $chardata[$i]['sor']; } if ($chardata[$i]['level'] != $prevlevel) { $levcount = 0; } else { ++$levcount; } $prevlevel = $chardata[$i]['level']; } // I1. For all characters with an even (left-to-right) embedding direction, those of type R go up one level and those of type AN or EN go up two levels. // I2. For all characters with an odd (right-to-left) embedding direction, those of type L, EN or AN go up one level. for ($i=0; $i < $numchars; ++$i) { $odd = $chardata[$i]['level'] % 2; if ($odd) { if (($chardata[$i]['type'] == 'L') OR ($chardata[$i]['type'] == 'AN') OR ($chardata[$i]['type'] == 'EN')) { $chardata[$i]['level'] += 1; } } else { if ($chardata[$i]['type'] == 'R') { $chardata[$i]['level'] += 1; } elseif (($chardata[$i]['type'] == 'AN') OR ($chardata[$i]['type'] == 'EN')) { $chardata[$i]['level'] += 2; } } $maxlevel = max($chardata[$i]['level'],$maxlevel); } // L1. On each line, reset the embedding level of the following characters to the paragraph embedding level: // 1. Segment separators, // 2. Paragraph separators, // 3. Any sequence of whitespace characters preceding a segment separator or paragraph separator, and // 4. Any sequence of white space characters at the end of the line. for ($i=0; $i < $numchars; ++$i) { if (($chardata[$i]['type'] == 'B') OR ($chardata[$i]['type'] == 'S')) { $chardata[$i]['level'] = $pel; } elseif ($chardata[$i]['type'] == 'WS') { $j = $i+1; while ($j < $numchars) { if ((($chardata[$j]['type'] == 'B') OR ($chardata[$j]['type'] == 'S')) OR (($j == ($numchars-1)) AND ($chardata[$j]['type'] == 'WS'))) { $chardata[$i]['level'] = $pel; break; } elseif ($chardata[$j]['type'] != 'WS') { break; } ++$j; } } } // Arabic Shaping // Cursively connected scripts, such as Arabic or Syriac, require the selection of positional character shapes that depend on adjacent characters. Shaping is logically applied after the Bidirectional Algorithm is used and is limited to characters within the same directional run. if ($arabic) { $endedletter = array(1569,1570,1571,1572,1573,1575,1577,1583,1584,1585,1586,1608,1688); $alfletter = array(1570,1571,1573,1575); $chardata2 = $chardata; $laaletter = false; $charAL = array(); $x = 0; for ($i=0; $i < $numchars; ++$i) { if (($this->unicode->uni_type[$chardata[$i]['char']] == 'AL') OR ($chardata[$i]['char'] == 32) OR ($chardata[$i]['char'] == 8204)) { $charAL[$x] = $chardata[$i]; $charAL[$x]['i'] = $i; $chardata[$i]['x'] = $x; ++$x; } } $numAL = $x; for ($i=0; $i < $numchars; ++$i) { $thischar = $chardata[$i]; if ($i > 0) { $prevchar = $chardata[($i-1)]; } else { $prevchar = false; } if (($i+1) < $numchars) { $nextchar = $chardata[($i+1)]; } else { $nextchar = false; } if ($this->unicode->uni_type[$thischar['char']] == 'AL') { $x = $thischar['x']; if ($x > 0) { $prevchar = $charAL[($x-1)]; } else { $prevchar = false; } if (($x+1) < $numAL) { $nextchar = $charAL[($x+1)]; } else { $nextchar = false; } // if laa letter if (($prevchar !== false) AND ($prevchar['char'] == 1604) AND (in_array($thischar['char'], $alfletter))) { $arabicarr = $this->unicode->uni_laa_array; $laaletter = true; if ($x > 1) { $prevchar = $charAL[($x-2)]; } else { $prevchar = false; } } else { $arabicarr = $this->unicode->uni_arabicsubst; $laaletter = false; } if (($prevchar !== false) AND ($nextchar !== false) AND (($this->unicode->uni_type[$prevchar['char']] == 'AL') OR ($this->unicode->uni_type[$prevchar['char']] == 'NSM')) AND (($this->unicode->uni_type[$nextchar['char']] == 'AL') OR ($this->unicode->uni_type[$nextchar['char']] == 'NSM')) AND ($prevchar['type'] == $thischar['type']) AND ($nextchar['type'] == $thischar['type']) AND ($nextchar['char'] != 1567)) { if (in_array($prevchar['char'], $endedletter)) { if (isset($arabicarr[$thischar['char']][2])) { // initial $chardata2[$i]['char'] = $arabicarr[$thischar['char']][2]; } } else { if (isset($arabicarr[$thischar['char']][3])) { // medial $chardata2[$i]['char'] = $arabicarr[$thischar['char']][3]; } } } elseif (($nextchar !== false) AND (($this->unicode->uni_type[$nextchar['char']] == 'AL') OR ($this->unicode->uni_type[$nextchar['char']] == 'NSM')) AND ($nextchar['type'] == $thischar['type']) AND ($nextchar['char'] != 1567)) { if (isset($arabicarr[$chardata[$i]['char']][2])) { // initial $chardata2[$i]['char'] = $arabicarr[$thischar['char']][2]; } } elseif ((($prevchar !== false) AND (($this->unicode->uni_type[$prevchar['char']] == 'AL') OR ($this->unicode->uni_type[$prevchar['char']] == 'NSM')) AND ($prevchar['type'] == $thischar['type'])) OR (($nextchar !== false) AND ($nextchar['char'] == 1567))) { // final if (($i > 1) AND ($thischar['char'] == 1607) AND ($chardata[$i-1]['char'] == 1604) AND ($chardata[$i-2]['char'] == 1604)) { //Allah Word // mark characters to delete with false $chardata2[$i-2]['char'] = false; $chardata2[$i-1]['char'] = false; $chardata2[$i]['char'] = 65010; } else { if (($prevchar !== false) AND in_array($prevchar['char'], $endedletter)) { if (isset($arabicarr[$thischar['char']][0])) { // isolated $chardata2[$i]['char'] = $arabicarr[$thischar['char']][0]; } } else { if (isset($arabicarr[$thischar['char']][1])) { // final $chardata2[$i]['char'] = $arabicarr[$thischar['char']][1]; } } } } elseif (isset($arabicarr[$thischar['char']][0])) { // isolated $chardata2[$i]['char'] = $arabicarr[$thischar['char']][0]; } // if laa letter if ($laaletter) { // mark characters to delete with false $chardata2[($charAL[($x-1)]['i'])]['char'] = false; } } // end if AL (Arabic Letter) } // end for each char /* * Combining characters that can occur with Arabic Shadda (0651 HEX, 1617 DEC) are replaced. * Putting the combining mark and shadda in the same glyph allows us to avoid the two marks overlapping each other in an illegible manner. */ for ($i = 0; $i < ($numchars-1); ++$i) { if (($chardata2[$i]['char'] == 1617) AND (isset($this->unicode->uni_diacritics[($chardata2[$i+1]['char'])]))) { // check if the subtitution font is defined on current font if (isset($this->CurrentFont['cw'][($this->unicode->uni_diacritics[($chardata2[$i+1]['char'])])])) { $chardata2[$i]['char'] = false; $chardata2[$i+1]['char'] = $this->unicode->uni_diacritics[($chardata2[$i+1]['char'])]; } } } // remove marked characters foreach ($chardata2 as $key => $value) { if ($value['char'] === false) { unset($chardata2[$key]); } } $chardata = array_values($chardata2); $numchars = count($chardata); unset($chardata2); unset($arabicarr); unset($laaletter); unset($charAL); } // L2. From the highest level found in the text to the lowest odd level on each line, including intermediate levels not actually present in the text, reverse any contiguous sequence of characters that are at that level or higher. for ($j=$maxlevel; $j > 0; $j--) { $ordarray = Array(); $revarr = Array(); $onlevel = false; for ($i=0; $i < $numchars; ++$i) { if ($chardata[$i]['level'] >= $j) { $onlevel = true; if (isset($this->unicode->uni_mirror[$chardata[$i]['char']])) { // L4. A character is depicted by a mirrored glyph if and only if (a) the resolved directionality of that character is R, and (b) the Bidi_Mirrored property value of that character is true. $chardata[$i]['char'] = $this->unicode->uni_mirror[$chardata[$i]['char']]; } $revarr[] = $chardata[$i]; } else { if ($onlevel) { $revarr = array_reverse($revarr); $ordarray = array_merge($ordarray, $revarr); $revarr = Array(); $onlevel = false; } $ordarray[] = $chardata[$i]; } } if ($onlevel) { $revarr = array_reverse($revarr); $ordarray = array_merge($ordarray, $revarr); } $chardata = $ordarray; } $ordarray = array(); for ($i=0; $i < $numchars; ++$i) { $ordarray[] = $chardata[$i]['char']; // store char values for subsetting $this->CurrentFont['subsetchars'][$chardata[$i]['char']] = true; } // update font subsetchars $this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']); return $ordarray; } // END OF BIDIRECTIONAL TEXT SECTION ------------------- /** * Encode a name object. * @param $name (string) Name object to encode. * @return (string) Encoded name object. * @protected * @author Nicola Asuni * @since 5.9.097 (2011-06-23) */ protected function encodeNameObject($name) { $escname = ''; $length = strlen($name); for ($i = 0; $i < $length; ++$i) { $chr = $name[$i]; if (preg_match('/[0-9a-zA-Z]/', $chr) == 1) { $escname .= $chr; } else { $escname .= sprintf('#%02X', ord($chr)); } } return $escname; } /** * Add a Named Destination. * NOTE: destination names are unique, so only last entry will be saved. * @param $name (string) Destination name. * @param $y (float) Y position in user units of the destiantion on the selected page (default = -1 = current position; 0 = page start;). * @param $page (int) Target page number (leave empty for current page). * @return (string) Stripped named destination identifier or false in case of error. * @public * @author Christian Deligant, Nicola Asuni * @since 5.9.097 (2011-06-23) */ public function setDestination($name, $y=-1, $page='') { // remove unsupported characters $name = $this->encodeNameObject($name); if ($this->empty_string($name)) { return false; } if ($y == -1) { $y = $this->GetY(); } if (empty($page)) { $page = $this->PageNo(); if (empty($page)) { return; } } $this->dests[$name] = array('y' => $y, 'p' => $page); return $name; } /** * Return the Named Destination array. * @return (array) Named Destination array. * @public * @author Nicola Asuni * @since 5.9.097 (2011-06-23) */ public function getDestination() { return $this->dests; } /** * Create a javascript PDF string. * @protected * @author Johannes G・tert, Nicola Asuni * @since 5.9.098 (2011-06-23) */ protected function _putdests() { if (empty($this->dests)) { return; } $this->n_dests = $this->_newobj(); $out = ' <<'; foreach($this->dests as $name => $o) { $out .= ' /'.$name.' '.sprintf('[%u 0 R /XYZ 0 %.2F null]', $this->page_obj_id[($o['p'])], ($this->pagedim[$o['p']]['h'] - ($o['y'] * $this->k))); } $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } /** * Adds a bookmark - alias for Bookmark(). * @param $txt (string) Bookmark description. * @param $level (int) Bookmark level (minimum value is 0). * @param $y (float) Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;). * @param $page (int) Target page number (leave empty for current page). * @param $style (string) Font style: B = Bold, I = Italic, BI = Bold + Italic. * @param $color (array) RGB color array (values from 0 to 255). * @public */ public function setBookmark($txt, $level=0, $y=-1, $page='', $style='', $color=array(0,0,0)) { $this->Bookmark($txt, $level, $y, $page, $style, $color); } /** * Adds a bookmark. * @param $txt (string) Bookmark description. * @param $level (int) Bookmark level (minimum value is 0). * @param $y (float) Y position in user units of the bookmark on the selected page (default = -1 = current position; 0 = page start;). * @param $page (int) Target page number (leave empty for current page). * @param $style (string) Font style: B = Bold, I = Italic, BI = Bold + Italic. * @param $color (array) RGB color array (values from 0 to 255). * @public * @author Olivier Plathey, Nicola Asuni * @since 2.1.002 (2008-02-12) */ public function Bookmark($txt, $level=0, $y=-1, $page='', $style='', $color=array(0,0,0)) { if ($level < 0) { $level = 0; } if (isset($this->outlines[0])) { $lastoutline = end($this->outlines); $maxlevel = $lastoutline['l'] + 1; } else { $maxlevel = 0; } if ($level > $maxlevel) { $level = $maxlevel; } if ($y == -1) { $y = $this->GetY(); } if (empty($page)) { $page = $this->PageNo(); if (empty($page)) { return; } } $this->outlines[] = array('t' => $txt, 'l' => $level, 'y' => $y, 'p' => $page, 's' => strtoupper($style), 'c' => $color); } /** * Sort bookmarks for page and key. * @protected * @since 5.9.119 (2011-09-19) */ protected function sortBookmarks() { // get sorting columns $outline_p = array(); $outline_y = array(); foreach ($this->outlines as $key => $row) { $outline_p[$key] = $row['p']; $outline_k[$key] = $key; } // sort outlines by page and original position array_multisort($outline_p, SORT_NUMERIC, SORT_ASC, $outline_k, SORT_NUMERIC, SORT_ASC, $this->outlines); } /** * Create a bookmark PDF string. * @protected * @author Olivier Plathey, Nicola Asuni * @since 2.1.002 (2008-02-12) */ protected function _putbookmarks() { $nb = count($this->outlines); if ($nb == 0) { return; } // sort bookmarks $this->sortBookmarks(); $lru = array(); $level = 0; foreach ($this->outlines as $i => $o) { if ($o['l'] > 0) { $parent = $lru[($o['l'] - 1)]; //Set parent and last pointers $this->outlines[$i]['parent'] = $parent; $this->outlines[$parent]['last'] = $i; if ($o['l'] > $level) { //Level increasing: set first pointer $this->outlines[$parent]['first'] = $i; } } else { $this->outlines[$i]['parent'] = $nb; } if (($o['l'] <= $level) AND ($i > 0)) { //Set prev and next pointers $prev = $lru[$o['l']]; $this->outlines[$prev]['next'] = $i; $this->outlines[$i]['prev'] = $prev; } $lru[$o['l']] = $i; $level = $o['l']; } //Outline items $n = $this->n + 1; $nltags = '/|<\/(blockquote|dd|dl|div|dt|h1|h2|h3|h4|h5|h6|hr|li|ol|p|pre|ul|tcpdf|table|tr|td)>/si'; foreach ($this->outlines as $i => $o) { $oid = $this->_newobj(); // covert HTML title to string $title = preg_replace($nltags, "\n", $o['t']); $title = preg_replace("/[\r]+/si", '', $title); $title = preg_replace("/[\n]+/si", "\n", $title); $title = strip_tags($title); $title = $this->stringTrim($title); $out = '<_textstring($title, $oid); $out .= ' /Parent '.($n + $o['parent']).' 0 R'; if (isset($o['prev'])) { $out .= ' /Prev '.($n + $o['prev']).' 0 R'; } if (isset($o['next'])) { $out .= ' /Next '.($n + $o['next']).' 0 R'; } if (isset($o['first'])) { $out .= ' /First '.($n + $o['first']).' 0 R'; } if (isset($o['last'])) { $out .= ' /Last '.($n + $o['last']).' 0 R'; } if (isset($this->page_obj_id[($o['p'])])) { $out .= ' '.sprintf('/Dest [%u 0 R /XYZ 0 %.2F null]', $this->page_obj_id[($o['p'])], ($this->pagedim[$o['p']]['h'] - ($o['y'] * $this->k))); } // set font style $style = 0; if (!empty($o['s'])) { // bold if (strpos($o['s'], 'B') !== false) { $style |= 2; } // oblique if (strpos($o['s'], 'I') !== false) { $style |= 1; } } $out .= sprintf(' /F %d', $style); // set bookmark color if (isset($o['c']) AND is_array($o['c']) AND (count($o['c']) == 3)) { $color = array_values($o['c']); $out .= sprintf(' /C [%.3F %.3F %.3F]', ($color[0] / 255), ($color[1] / 255), ($color[2] / 255)); } else { // black $out .= ' /C [0.0 0.0 0.0]'; } $out .= ' /Count 0'; // normally closed item $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } //Outline root $this->OutlineRoot = $this->_newobj(); $this->_out('<< /Type /Outlines /First '.$n.' 0 R /Last '.($n + $lru[0]).' 0 R >>'."\n".'endobj'); } // --- JAVASCRIPT ------------------------------------------------------ /** * Adds a javascript * @param $script (string) Javascript code * @public * @author Johannes G・tert, Nicola Asuni * @since 2.1.002 (2008-02-12) */ public function IncludeJS($script) { $this->javascript .= $script; } /** * Adds a javascript object and return object ID * @param $script (string) Javascript code * @param $onload (boolean) if true executes this object when opening the document * @return int internal object ID * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ public function addJavascriptObject($script, $onload=false) { if ($this->pdfa_mode) { // javascript is not allowed in PDF/A mode return false; } ++$this->n; $this->js_objects[$this->n] = array('n' => $this->n, 'js' => $script, 'onload' => $onload); return $this->n; } /** * Create a javascript PDF string. * @protected * @author Johannes G・tert, Nicola Asuni * @since 2.1.002 (2008-02-12) */ protected function _putjavascript() { if ($this->pdfa_mode OR (empty($this->javascript) AND empty($this->js_objects))) { return; } if (strpos($this->javascript, 'this.addField') > 0) { if (!$this->ur['enabled']) { //$this->setUserRights(); } // the following two lines are used to avoid form fields duplication after saving // The addField method only works when releasing user rights (UR3) $jsa = sprintf("ftcpdfdocsaved=this.addField('%s','%s',%d,[%.2F,%.2F,%.2F,%.2F]);", 'tcpdfdocsaved', 'text', 0, 0, 1, 0, 1); $jsb = "getField('tcpdfdocsaved').value='saved';"; $this->javascript = $jsa."\n".$this->javascript."\n".$jsb; } $this->n_js = $this->_newobj(); $out = ' << /Names ['; if (!empty($this->javascript)) { $out .= ' (EmbeddedJS) '.($this->n + 1).' 0 R'; } if (!empty($this->js_objects)) { foreach ($this->js_objects as $key => $val) { if ($val['onload']) { $out .= ' (JS'.$key.') '.$key.' 0 R'; } } } $out .= ' ] >>'; $out .= "\n".'endobj'; $this->_out($out); // default Javascript object if (!empty($this->javascript)) { $obj_id = $this->_newobj(); $out = '<< /S /JavaScript'; $out .= ' /JS '.$this->_textstring($this->javascript, $obj_id); $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } // additional Javascript objects if (!empty($this->js_objects)) { foreach ($this->js_objects as $key => $val) { $out = $this->_getobj($key)."\n".' << /S /JavaScript /JS '.$this->_textstring($val['js'], $key).' >>'."\n".'endobj'; $this->_out($out); } } } /** * Convert color to javascript color. * @param $color (string) color name or "#RRGGBB" * @protected * @author Denis Van Nuffelen, Nicola Asuni * @since 2.1.002 (2008-02-12) */ protected function _JScolor($color) { static $aColors = array('transparent', 'black', 'white', 'red', 'green', 'blue', 'cyan', 'magenta', 'yellow', 'dkGray', 'gray', 'ltGray'); if (substr($color,0,1) == '#') { return sprintf("['RGB',%.3F,%.3F,%.3F]", hexdec(substr($color,1,2))/255, hexdec(substr($color,3,2))/255, hexdec(substr($color,5,2))/255); } if (!in_array($color,$aColors)) { $this->Error('Invalid color: '.$color); } return 'color.'.$color; } /** * Adds a javascript form field. * @param $type (string) field type * @param $name (string) field name * @param $x (int) horizontal position * @param $y (int) vertical position * @param $w (int) width * @param $h (int) height * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @protected * @author Denis Van Nuffelen, Nicola Asuni * @since 2.1.002 (2008-02-12) */ protected function _addfield($type, $name, $x, $y, $w, $h, $prop) { if ($this->rtl) { $x = $x - $w; } // the followind avoid fields duplication after saving the document $this->javascript .= "if (getField('tcpdfdocsaved').value != 'saved') {"; $k = $this->k; $this->javascript .= sprintf("f".$name."=this.addField('%s','%s',%u,[%.2F,%.2F,%.2F,%.2F]);", $name, $type, $this->PageNo()-1, $x*$k, ($this->h-$y)*$k+1, ($x+$w)*$k, ($this->h-$y-$h)*$k+1)."\n"; $this->javascript .= 'f'.$name.'.textSize='.$this->FontSizePt.";\n"; foreach($prop as $key => $val) { if (strcmp(substr($key, -5), 'Color') == 0) { $val = $this->_JScolor($val); } else { $val = "'".$val."'"; } $this->javascript .= 'f'.$name.'.'.$key.'='.$val.";\n"; } if ($this->rtl) { $this->x -= $w; } else { $this->x += $w; } $this->javascript .= '}'; } // --- FORM FIELDS ----------------------------------------------------- /** * Convert JavaScript form fields properties array to Annotation Properties array. * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @return array of annotation properties * @protected * @author Nicola Asuni * @since 4.8.000 (2009-09-06) */ protected function getAnnotOptFromJSProp($prop) { if (isset($prop['aopt']) AND is_array($prop['aopt'])) { // the annotation options area lready defined return $prop['aopt']; } $opt = array(); // value to be returned // alignment: Controls how the text is laid out within the text field. if (isset($prop['alignment'])) { switch ($prop['alignment']) { case 'left': { $opt['q'] = 0; break; } case 'center': { $opt['q'] = 1; break; } case 'right': { $opt['q'] = 2; break; } default: { $opt['q'] = ($this->rtl)?2:0; break; } } } // lineWidth: Specifies the thickness of the border when stroking the perimeter of a field's rectangle. if (isset($prop['lineWidth'])) { $linewidth = intval($prop['lineWidth']); } else { $linewidth = 1; } // borderStyle: The border style for a field. if (isset($prop['borderStyle'])) { switch ($prop['borderStyle']) { case 'border.d': case 'dashed': { $opt['border'] = array(0, 0, $linewidth, array(3, 2)); $opt['bs'] = array('w'=>$linewidth, 's'=>'D', 'd'=>array(3, 2)); break; } case 'border.b': case 'beveled': { $opt['border'] = array(0, 0, $linewidth); $opt['bs'] = array('w'=>$linewidth, 's'=>'B'); break; } case 'border.i': case 'inset': { $opt['border'] = array(0, 0, $linewidth); $opt['bs'] = array('w'=>$linewidth, 's'=>'I'); break; } case 'border.u': case 'underline': { $opt['border'] = array(0, 0, $linewidth); $opt['bs'] = array('w'=>$linewidth, 's'=>'U'); break; } case 'border.s': case 'solid': { $opt['border'] = array(0, 0, $linewidth); $opt['bs'] = array('w'=>$linewidth, 's'=>'S'); break; } default: { break; } } } if (isset($prop['border']) AND is_array($prop['border'])) { $opt['border'] = $prop['border']; } if (!isset($opt['mk'])) { $opt['mk'] = array(); } if (!isset($opt['mk']['if'])) { $opt['mk']['if'] = array(); } $opt['mk']['if']['a'] = array(0.5, 0.5); // buttonAlignX: Controls how space is distributed from the left of the button face with respect to the icon. if (isset($prop['buttonAlignX'])) { $opt['mk']['if']['a'][0] = $prop['buttonAlignX']; } // buttonAlignY: Controls how unused space is distributed from the bottom of the button face with respect to the icon. if (isset($prop['buttonAlignY'])) { $opt['mk']['if']['a'][1] = $prop['buttonAlignY']; } // buttonFitBounds: If true, the extent to which the icon may be scaled is set to the bounds of the button field. if (isset($prop['buttonFitBounds']) AND ($prop['buttonFitBounds'] == 'true')) { $opt['mk']['if']['fb'] = true; } // buttonScaleHow: Controls how the icon is scaled (if necessary) to fit inside the button face. if (isset($prop['buttonScaleHow'])) { switch ($prop['buttonScaleHow']) { case 'scaleHow.proportional': { $opt['mk']['if']['s'] = 'P'; break; } case 'scaleHow.anamorphic': { $opt['mk']['if']['s'] = 'A'; break; } } } // buttonScaleWhen: Controls when an icon is scaled to fit inside the button face. if (isset($prop['buttonScaleWhen'])) { switch ($prop['buttonScaleWhen']) { case 'scaleWhen.always': { $opt['mk']['if']['sw'] = 'A'; break; } case 'scaleWhen.never': { $opt['mk']['if']['sw'] = 'N'; break; } case 'scaleWhen.tooBig': { $opt['mk']['if']['sw'] = 'B'; break; } case 'scaleWhen.tooSmall': { $opt['mk']['if']['sw'] = 'S'; break; } } } // buttonPosition: Controls how the text and the icon of the button are positioned with respect to each other within the button face. if (isset($prop['buttonPosition'])) { switch ($prop['buttonPosition']) { case 0: case 'position.textOnly': { $opt['mk']['tp'] = 0; break; } case 1: case 'position.iconOnly': { $opt['mk']['tp'] = 1; break; } case 2: case 'position.iconTextV': { $opt['mk']['tp'] = 2; break; } case 3: case 'position.textIconV': { $opt['mk']['tp'] = 3; break; } case 4: case 'position.iconTextH': { $opt['mk']['tp'] = 4; break; } case 5: case 'position.textIconH': { $opt['mk']['tp'] = 5; break; } case 6: case 'position.overlay': { $opt['mk']['tp'] = 6; break; } } } // fillColor: Specifies the background color for a field. if (isset($prop['fillColor'])) { if (is_array($prop['fillColor'])) { $opt['mk']['bg'] = $prop['fillColor']; } else { $opt['mk']['bg'] = $this->convertHTMLColorToDec($prop['fillColor']); } } // strokeColor: Specifies the stroke color for a field that is used to stroke the rectangle of the field with a line as large as the line width. if (isset($prop['strokeColor'])) { if (is_array($prop['strokeColor'])) { $opt['mk']['bc'] = $prop['strokeColor']; } else { $opt['mk']['bc'] = $this->convertHTMLColorToDec($prop['strokeColor']); } } // rotation: The rotation of a widget in counterclockwise increments. if (isset($prop['rotation'])) { $opt['mk']['r'] = $prop['rotation']; } // charLimit: Limits the number of characters that a user can type into a text field. if (isset($prop['charLimit'])) { $opt['maxlen'] = intval($prop['charLimit']); } if (!isset($ff)) { $ff = 0; // default value } // readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it. if (isset($prop['readonly']) AND ($prop['readonly'] == 'true')) { $ff += 1 << 0; } // required: Specifies whether a field requires a value. if (isset($prop['required']) AND ($prop['required'] == 'true')) { $ff += 1 << 1; } // multiline: Controls how text is wrapped within the field. if (isset($prop['multiline']) AND ($prop['multiline'] == 'true')) { $ff += 1 << 12; } // password: Specifies whether the field should display asterisks when data is entered in the field. if (isset($prop['password']) AND ($prop['password'] == 'true')) { $ff += 1 << 13; } // NoToggleToOff: If set, exactly one radio button shall be selected at all times; selecting the currently selected button has no effect. if (isset($prop['NoToggleToOff']) AND ($prop['NoToggleToOff'] == 'true')) { $ff += 1 << 14; } // Radio: If set, the field is a set of radio buttons. if (isset($prop['Radio']) AND ($prop['Radio'] == 'true')) { $ff += 1 << 15; } // Pushbutton: If set, the field is a pushbutton that does not retain a permanent value. if (isset($prop['Pushbutton']) AND ($prop['Pushbutton'] == 'true')) { $ff += 1 << 16; } // Combo: If set, the field is a combo box; if clear, the field is a list box. if (isset($prop['Combo']) AND ($prop['Combo'] == 'true')) { $ff += 1 << 17; } // editable: Controls whether a combo box is editable. if (isset($prop['editable']) AND ($prop['editable'] == 'true')) { $ff += 1 << 18; } // Sort: If set, the field's option items shall be sorted alphabetically. if (isset($prop['Sort']) AND ($prop['Sort'] == 'true')) { $ff += 1 << 19; } // fileSelect: If true, sets the file-select flag in the Options tab of the text field (Field is Used for File Selection). if (isset($prop['fileSelect']) AND ($prop['fileSelect'] == 'true')) { $ff += 1 << 20; } // multipleSelection: If true, indicates that a list box allows a multiple selection of items. if (isset($prop['multipleSelection']) AND ($prop['multipleSelection'] == 'true')) { $ff += 1 << 21; } // doNotSpellCheck: If true, spell checking is not performed on this editable text field. if (isset($prop['doNotSpellCheck']) AND ($prop['doNotSpellCheck'] == 'true')) { $ff += 1 << 22; } // doNotScroll: If true, the text field does not scroll and the user, therefore, is limited by the rectangular region designed for the field. if (isset($prop['doNotScroll']) AND ($prop['doNotScroll'] == 'true')) { $ff += 1 << 23; } // comb: If set to true, the field background is drawn as series of boxes (one for each character in the value of the field) and each character of the content is drawn within those boxes. The number of boxes drawn is determined from the charLimit property. It applies only to text fields. The setter will also raise if any of the following field properties are also set multiline, password, and fileSelect. A side-effect of setting this property is that the doNotScroll property is also set. if (isset($prop['comb']) AND ($prop['comb'] == 'true')) { $ff += 1 << 24; } // radiosInUnison: If false, even if a group of radio buttons have the same name and export value, they behave in a mutually exclusive fashion, like HTML radio buttons. if (isset($prop['radiosInUnison']) AND ($prop['radiosInUnison'] == 'true')) { $ff += 1 << 25; } // richText: If true, the field allows rich text formatting. if (isset($prop['richText']) AND ($prop['richText'] == 'true')) { $ff += 1 << 25; } // commitOnSelChange: Controls whether a field value is committed after a selection change. if (isset($prop['commitOnSelChange']) AND ($prop['commitOnSelChange'] == 'true')) { $ff += 1 << 26; } $opt['ff'] = $ff; // defaultValue: The default value of a field - that is, the value that the field is set to when the form is reset. if (isset($prop['defaultValue'])) { $opt['dv'] = $prop['defaultValue']; } $f = 4; // default value for annotation flags // readonly: The read-only characteristic of a field. If a field is read-only, the user can see the field but cannot change it. if (isset($prop['readonly']) AND ($prop['readonly'] == 'true')) { $f += 1 << 6; } // display: Controls whether the field is hidden or visible on screen and in print. if (isset($prop['display'])) { if ($prop['display'] == 'display.visible') { // } elseif ($prop['display'] == 'display.hidden') { $f += 1 << 1; } elseif ($prop['display'] == 'display.noPrint') { $f -= 1 << 2; } elseif ($prop['display'] == 'display.noView') { $f += 1 << 5; } } $opt['f'] = $f; // currentValueIndices: Reads and writes single or multiple values of a list box or combo box. if (isset($prop['currentValueIndices']) AND is_array($prop['currentValueIndices'])) { $opt['i'] = $prop['currentValueIndices']; } // value: The value of the field data that the user has entered. if (isset($prop['value'])) { if (is_array($prop['value'])) { $opt['opt'] = array(); foreach ($prop['value'] AS $key => $optval) { // exportValues: An array of strings representing the export values for the field. if (isset($prop['exportValues'][$key])) { $opt['opt'][$key] = array($prop['exportValues'][$key], $prop['value'][$key]); } else { $opt['opt'][$key] = $prop['value'][$key]; } } } else { $opt['v'] = $prop['value']; } } // richValue: This property specifies the text contents and formatting of a rich text field. if (isset($prop['richValue'])) { $opt['rv'] = $prop['richValue']; } // submitName: If nonempty, used during form submission instead of name. Only applicable if submitting in HTML format (that is, URL-encoded). if (isset($prop['submitName'])) { $opt['tm'] = $prop['submitName']; } // name: Fully qualified field name. if (isset($prop['name'])) { $opt['t'] = $prop['name']; } // userName: The user name (short description string) of the field. if (isset($prop['userName'])) { $opt['tu'] = $prop['userName']; } // highlight: Defines how a button reacts when a user clicks it. if (isset($prop['highlight'])) { switch ($prop['highlight']) { case 'none': case 'highlight.n': { $opt['h'] = 'N'; break; } case 'invert': case 'highlight.i': { $opt['h'] = 'i'; break; } case 'push': case 'highlight.p': { $opt['h'] = 'P'; break; } case 'outline': case 'highlight.o': { $opt['h'] = 'O'; break; } } } // Unsupported options: // - calcOrderIndex: Changes the calculation order of fields in the document. // - delay: Delays the redrawing of a field's appearance. // - defaultStyle: This property defines the default style attributes for the form field. // - style: Allows the user to set the glyph style of a check box or radio button. // - textColor, textFont, textSize return $opt; } /** * Set default properties for form fields. * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-06) */ public function setFormDefaultProp($prop=array()) { $this->default_form_prop = $prop; } /** * Return the default properties for form fields. * @return array $prop javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-06) */ public function getFormDefaultProp() { return $this->default_form_prop; } /** * Creates a text field * @param $name (string) field name * @param $w (float) Width of the rectangle * @param $h (float) Height of the rectangle * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. * @param $x (float) Abscissa of the upper-left corner of the rectangle * @param $y (float) Ordinate of the upper-left corner of the rectangle * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ public function TextField($name, $w, $h, $prop=array(), $opt=array(), $x='', $y='', $js=false) { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); if ($js) { $this->_addfield('text', $name, $x, $y, $w, $h, $prop); return; } // get default style $prop = array_merge($this->getFormDefaultProp(), $prop); // get annotation data $popt = $this->getAnnotOptFromJSProp($prop); // set default appearance stream $this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i']; $fontstyle = sprintf('/F%d %.2F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor); $popt['da'] = $fontstyle; // build appearance stream $popt['ap'] = array(); $popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' '; $text = ''; if (isset($prop['value']) AND !empty($prop['value'])) { $text = $prop['value']; } elseif (isset($opt['v']) AND !empty($opt['v'])) { $text = $opt['v']; } $tmpid = $this->startTemplate($w, $h, false); $this->MultiCell($w, $h, $text, 0, '', false, 0, 0, 0, true, 0, false, true, 0, 'T', false); $this->endTemplate(); --$this->n; $popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata']; unset($this->xobjects[$tmpid]); $popt['ap']['n'] .= 'Q EMC'; // merge options $opt = array_merge($popt, $opt); // remove some conflicting options unset($opt['bs']); // set remaining annotation data $opt['Subtype'] = 'Widget'; $opt['ft'] = 'Tx'; $opt['t'] = $name; // Additional annotation's parameters (check _putannotsobj() method): //$opt['f'] //$opt['as'] //$opt['bs'] //$opt['be'] //$opt['c'] //$opt['border'] //$opt['h'] //$opt['mk']; //$opt['mk']['r'] //$opt['mk']['bc']; //$opt['mk']['bg']; unset($opt['mk']['ca']); unset($opt['mk']['rc']); unset($opt['mk']['ac']); unset($opt['mk']['i']); unset($opt['mk']['ri']); unset($opt['mk']['ix']); unset($opt['mk']['if']); //$opt['mk']['if']['sw']; //$opt['mk']['if']['s']; //$opt['mk']['if']['a']; //$opt['mk']['if']['fb']; unset($opt['mk']['tp']); //$opt['tu'] //$opt['tm'] //$opt['ff'] //$opt['v'] //$opt['dv'] //$opt['a'] //$opt['aa'] //$opt['q'] $this->Annotation($x, $y, $w, $h, $name, $opt, 0); if ($this->rtl) { $this->x -= $w; } else { $this->x += $w; } } /** * Creates a RadioButton field. * @param $name (string) Field name. * @param $w (int) Width or the radio button. * @param $prop (array) Javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @param $opt (array) Annotation parameters. Possible values are described on official PDF32000_2008 reference. * @param $onvalue (string) Value to be returned if selected. * @param $checked (boolean) Define the initial state. * @param $x (float) Abscissa of the upper-left corner of the rectangle * @param $y (float) Ordinate of the upper-left corner of the rectangle * @param $js (boolean) If true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ public function RadioButton($name, $w, $prop=array(), $opt=array(), $onvalue='On', $checked=false, $x='', $y='', $js=false) { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($w, $x, $y); if ($js) { $this->_addfield('radiobutton', $name, $x, $y, $w, $w, $prop); return; } if ($this->empty_string($onvalue)) { $onvalue = 'On'; } if ($checked) { $defval = $onvalue; } else { $defval = 'Off'; } // set font $font = 'zapfdingbats'; $this->AddFont($font); $tmpfont = $this->getFontBuffer($font); // set data for parent group if (!isset($this->radiobutton_groups[$this->page])) { $this->radiobutton_groups[$this->page] = array(); } if (!isset($this->radiobutton_groups[$this->page][$name])) { $this->radiobutton_groups[$this->page][$name] = array(); ++$this->n; $this->radiobutton_groups[$this->page][$name]['n'] = $this->n; $this->radio_groups[] = $this->n; } $kid = ($this->n + 1); // save object ID to be added on Kids entry on parent object $this->radiobutton_groups[$this->page][$name][] = array('kid' => $kid, 'def' => $defval); // get default style $prop = array_merge($this->getFormDefaultProp(), $prop); $prop['NoToggleToOff'] = 'true'; $prop['Radio'] = 'true'; $prop['borderStyle'] = 'inset'; // get annotation data $popt = $this->getAnnotOptFromJSProp($prop); // set additional default options $this->annotation_fonts[$tmpfont['fontkey']] = $tmpfont['i']; $fontstyle = sprintf('/F%d %.2F Tf %s', $tmpfont['i'], $this->FontSizePt, $this->TextColor); $popt['da'] = $fontstyle; // build appearance stream $popt['ap'] = array(); $popt['ap']['n'] = array(); $fy = (($w - ((($tmpfont['desc']['Ascent'] - $tmpfont['desc']['Descent']) * $this->FontSizePt / 1000) / $this->k)) * $this->k); $popt['ap']['n'][$onvalue] = sprintf('q %s BT /F%d %.2F Tf %.2F %.2F Td ('.chr(108).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, 0, $fy); $popt['ap']['n']['Off'] = sprintf('q %s BT /F%d %.2F Tf %.2F %.2F Td ('.chr(109).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, 0, $fy); if (!isset($popt['mk'])) { $popt['mk'] = array(); } $popt['mk']['ca'] = '(l)'; // merge options $opt = array_merge($popt, $opt); // set remaining annotation data $opt['Subtype'] = 'Widget'; $opt['ft'] = 'Btn'; if ($checked) { $opt['v'] = array('/'.$onvalue); $opt['as'] = $onvalue; } else { $opt['as'] = 'Off'; } // store readonly flag if (!isset($this->radiobutton_groups[$this->page][$name]['#readonly#'])) { $this->radiobutton_groups[$this->page][$name]['#readonly#'] = false; } $this->radiobutton_groups[$this->page][$name]['#readonly#'] |= ($opt['f'] & 64); $this->Annotation($x, $y, $w, $w, $name, $opt, 0); if ($this->rtl) { $this->x -= $w; } else { $this->x += $w; } } /** * Creates a List-box field * @param $name (string) field name * @param $w (int) width * @param $h (int) height * @param $values (array) array containing the list of values. * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. * @param $x (float) Abscissa of the upper-left corner of the rectangle * @param $y (float) Ordinate of the upper-left corner of the rectangle * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ public function ListBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x='', $y='', $js=false) { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); if ($js) { $this->_addfield('listbox', $name, $x, $y, $w, $h, $prop); $s = ''; foreach ($values as $value) { $s .= '\''.addslashes($value).'\','; } $this->javascript .= 'f'.$name.'.setItems(['.substr($s, 0, -1)."]);\n"; return; } // get default style $prop = array_merge($this->getFormDefaultProp(), $prop); // get annotation data $popt = $this->getAnnotOptFromJSProp($prop); // set additional default values $this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i']; $fontstyle = sprintf('/F%d %.2F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor); $popt['da'] = $fontstyle; // build appearance stream $popt['ap'] = array(); $popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' '; $text = ''; foreach($values as $item) { $text .= $item."\n"; } $tmpid = $this->startTemplate($w, $h, false); $this->MultiCell($w, $h, $text, 0, '', false, 0, 0, 0, true, 0, false, true, 0, 'T', false); $this->endTemplate(); --$this->n; $popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata']; unset($this->xobjects[$tmpid]); $popt['ap']['n'] .= 'Q EMC'; // merge options $opt = array_merge($popt, $opt); // set remaining annotation data $opt['Subtype'] = 'Widget'; $opt['ft'] = 'Ch'; $opt['t'] = $name; $opt['opt'] = $values; unset($opt['mk']['ca']); unset($opt['mk']['rc']); unset($opt['mk']['ac']); unset($opt['mk']['i']); unset($opt['mk']['ri']); unset($opt['mk']['ix']); unset($opt['mk']['if']); unset($opt['mk']['tp']); $this->Annotation($x, $y, $w, $h, $name, $opt, 0); if ($this->rtl) { $this->x -= $w; } else { $this->x += $w; } } /** * Creates a Combo-box field * @param $name (string) field name * @param $w (int) width * @param $h (int) height * @param $values (array) array containing the list of values. * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. * @param $x (float) Abscissa of the upper-left corner of the rectangle * @param $y (float) Ordinate of the upper-left corner of the rectangle * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ public function ComboBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x='', $y='', $js=false) { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); if ($js) { $this->_addfield('combobox', $name, $x, $y, $w, $h, $prop); $s = ''; foreach ($values as $value) { $s .= "'".addslashes($value)."',"; } $this->javascript .= 'f'.$name.'.setItems(['.substr($s, 0, -1)."]);\n"; return; } // get default style $prop = array_merge($this->getFormDefaultProp(), $prop); $prop['Combo'] = true; // get annotation data $popt = $this->getAnnotOptFromJSProp($prop); // set additional default options $this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i']; $fontstyle = sprintf('/F%d %.2F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor); $popt['da'] = $fontstyle; // build appearance stream $popt['ap'] = array(); $popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' '; $text = ''; foreach($values as $item) { $text .= $item[1]."\n"; } $tmpid = $this->startTemplate($w, $h, false); $this->MultiCell($w, $h, $text, 0, '', false, 0, 0, 0, true, 0, false, true, 0, 'T', false); $this->endTemplate(); --$this->n; $popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata']; unset($this->xobjects[$tmpid]); $popt['ap']['n'] .= 'Q EMC'; // merge options $opt = array_merge($popt, $opt); // set remaining annotation data $opt['Subtype'] = 'Widget'; $opt['ft'] = 'Ch'; $opt['t'] = $name; $opt['opt'] = $values; unset($opt['mk']['ca']); unset($opt['mk']['rc']); unset($opt['mk']['ac']); unset($opt['mk']['i']); unset($opt['mk']['ri']); unset($opt['mk']['ix']); unset($opt['mk']['if']); unset($opt['mk']['tp']); $this->Annotation($x, $y, $w, $h, $name, $opt, 0); if ($this->rtl) { $this->x -= $w; } else { $this->x += $w; } } /** * Creates a CheckBox field * @param $name (string) field name * @param $w (int) width * @param $checked (boolean) define the initial state. * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. * @param $onvalue (string) value to be returned if selected. * @param $x (float) Abscissa of the upper-left corner of the rectangle * @param $y (float) Ordinate of the upper-left corner of the rectangle * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ public function CheckBox($name, $w, $checked=false, $prop=array(), $opt=array(), $onvalue='Yes', $x='', $y='', $js=false) { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($w, $x, $y); if ($js) { $this->_addfield('checkbox', $name, $x, $y, $w, $w, $prop); return; } if (!isset($prop['value'])) { $prop['value'] = array('Yes'); } // get default style $prop = array_merge($this->getFormDefaultProp(), $prop); $prop['borderStyle'] = 'inset'; // get annotation data $popt = $this->getAnnotOptFromJSProp($prop); // set additional default options $font = 'zapfdingbats'; $this->AddFont($font); $tmpfont = $this->getFontBuffer($font); $this->annotation_fonts[$tmpfont['fontkey']] = $tmpfont['i']; $fontstyle = sprintf('/F%d %.2F Tf %s', $tmpfont['i'], $this->FontSizePt, $this->TextColor); $popt['da'] = $fontstyle; // build appearance stream $popt['ap'] = array(); $popt['ap']['n'] = array(); $fy = ((($tmpfont['desc']['Ascent'] + $tmpfont['desc']['Descent']) * $this->FontSizePt) / (1000 * $this->k)); $fy = (($w - ((($tmpfont['desc']['Ascent'] - $tmpfont['desc']['Descent']) * $this->FontSizePt / 1000) / $this->k)) * $this->k); $popt['ap']['n']['Yes'] = sprintf('q %s BT /F%d %.2F Tf %.2F %.2F Td ('.chr(110).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, 0, $fy); $popt['ap']['n']['Off'] = sprintf('q %s BT /F%d %.2F Tf %.2F %.2F Td ('.chr(111).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, 0, $fy); // merge options $opt = array_merge($popt, $opt); // set remaining annotation data $opt['Subtype'] = 'Widget'; $opt['ft'] = 'Btn'; $opt['t'] = $name; if ($this->empty_string($onvalue)) { $onvalue = 'Yes'; } $opt['opt'] = array($onvalue); if ($checked) { $opt['v'] = array('/Yes'); $opt['as'] = 'Yes'; } else { $opt['v'] = array('/Off'); $opt['as'] = 'Off'; } $this->Annotation($x, $y, $w, $w, $name, $opt, 0); if ($this->rtl) { $this->x -= $w; } else { $this->x += $w; } } /** * Creates a button field * @param $name (string) field name * @param $w (int) width * @param $h (int) height * @param $caption (string) caption. * @param $action (mixed) action triggered by pressing the button. Use a string to specify a javascript action. Use an array to specify a form action options as on section 12.7.5 of PDF32000_2008. * @param $prop (array) javascript field properties. Possible values are described on official Javascript for Acrobat API reference. * @param $opt (array) annotation parameters. Possible values are described on official PDF32000_2008 reference. * @param $x (float) Abscissa of the upper-left corner of the rectangle * @param $y (float) Ordinate of the upper-left corner of the rectangle * @param $js (boolean) if true put the field using JavaScript (requires Acrobat Writer to be rendered). * @public * @author Nicola Asuni * @since 4.8.000 (2009-09-07) */ public function Button($name, $w, $h, $caption, $action, $prop=array(), $opt=array(), $x='', $y='', $js=false) { if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); if ($js) { $this->_addfield('button', $name, $this->x, $this->y, $w, $h, $prop); $this->javascript .= 'f'.$name.".buttonSetCaption('".addslashes($caption)."');\n"; $this->javascript .= 'f'.$name.".setAction('MouseUp','".addslashes($action)."');\n"; $this->javascript .= 'f'.$name.".highlight='push';\n"; $this->javascript .= 'f'.$name.".print=false;\n"; return; } // get default style $prop = array_merge($this->getFormDefaultProp(), $prop); $prop['Pushbutton'] = 'true'; $prop['highlight'] = 'push'; $prop['display'] = 'display.noPrint'; // get annotation data $popt = $this->getAnnotOptFromJSProp($prop); $this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i']; $fontstyle = sprintf('/F%d %.2F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor); $popt['da'] = $fontstyle; // build appearance stream $popt['ap'] = array(); $popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' '; $tmpid = $this->startTemplate($w, $h, false); $bw = (2 / $this->k); // border width $border = array( 'L' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(231)), 'R' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(51)), 'T' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(231)), 'B' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(51))); $this->SetFillColor(204); $this->Cell($w, $h, $caption, $border, 0, 'C', true, '', 1, false, 'T', 'M'); $this->endTemplate(); --$this->n; $popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata']; unset($this->xobjects[$tmpid]); $popt['ap']['n'] .= 'Q EMC'; // set additional default options if (!isset($popt['mk'])) { $popt['mk'] = array(); } $ann_obj_id = ($this->n + 1); if (!empty($action) AND !is_array($action)) { $ann_obj_id = ($this->n + 2); } $popt['mk']['ca'] = $this->_textstring($caption, $ann_obj_id); $popt['mk']['rc'] = $this->_textstring($caption, $ann_obj_id); $popt['mk']['ac'] = $this->_textstring($caption, $ann_obj_id); // merge options $opt = array_merge($popt, $opt); // set remaining annotation data $opt['Subtype'] = 'Widget'; $opt['ft'] = 'Btn'; $opt['t'] = $caption; $opt['v'] = $name; if (!empty($action)) { if (is_array($action)) { // form action options as on section 12.7.5 of PDF32000_2008. $opt['aa'] = '/D <<'; $bmode = array('SubmitForm', 'ResetForm', 'ImportData'); foreach ($action AS $key => $val) { if (($key == 'S') AND in_array($val, $bmode)) { $opt['aa'] .= ' /S /'.$val; } elseif (($key == 'F') AND (!empty($val))) { $opt['aa'] .= ' /F '.$this->_datastring($val, $ann_obj_id); } elseif (($key == 'Fields') AND is_array($val) AND !empty($val)) { $opt['aa'] .= ' /Fields ['; foreach ($val AS $field) { $opt['aa'] .= ' '.$this->_textstring($field, $ann_obj_id); } $opt['aa'] .= ']'; } elseif (($key == 'Flags')) { $ff = 0; if (is_array($val)) { foreach ($val AS $flag) { switch ($flag) { case 'Include/Exclude': { $ff += 1 << 0; break; } case 'IncludeNoValueFields': { $ff += 1 << 1; break; } case 'ExportFormat': { $ff += 1 << 2; break; } case 'GetMethod': { $ff += 1 << 3; break; } case 'SubmitCoordinates': { $ff += 1 << 4; break; } case 'XFDF': { $ff += 1 << 5; break; } case 'IncludeAppendSaves': { $ff += 1 << 6; break; } case 'IncludeAnnotations': { $ff += 1 << 7; break; } case 'SubmitPDF': { $ff += 1 << 8; break; } case 'CanonicalFormat': { $ff += 1 << 9; break; } case 'ExclNonUserAnnots': { $ff += 1 << 10; break; } case 'ExclFKey': { $ff += 1 << 11; break; } case 'EmbedForm': { $ff += 1 << 13; break; } } } } else { $ff = intval($val); } $opt['aa'] .= ' /Flags '.$ff; } } $opt['aa'] .= ' >>'; } else { // Javascript action or raw action command $js_obj_id = $this->addJavascriptObject($action); $opt['aa'] = '/D '.$js_obj_id.' 0 R'; } } $this->Annotation($x, $y, $w, $h, $name, $opt, 0); if ($this->rtl) { $this->x -= $w; } else { $this->x += $w; } } // --- END FORMS FIELDS ------------------------------------------------ /** * Add certification signature (DocMDP or UR3) * You can set only one signature type * @protected * @author Nicola Asuni * @since 4.6.008 (2009-05-07) */ protected function _putsignature() { if ((!$this->sign) OR (!isset($this->signature_data['cert_type']))) { return; } $sigobjid = ($this->sig_obj_id + 1); $out = $this->_getobj($sigobjid)."\n"; $out .= '<< /Type /Sig'; $out .= ' /Filter /Adobe.PPKLite'; $out .= ' /SubFilter /adbe.pkcs7.detached'; $out .= ' '.$this->byterange_string; $out .= ' /Contents<'.str_repeat('0', $this->signature_max_length).'>'; $out .= ' /Reference ['; // array of signature reference dictionaries $out .= ' << /Type /SigRef'; if ($this->signature_data['cert_type'] > 0) { $out .= ' /TransformMethod /DocMDP'; $out .= ' /TransformParams <<'; $out .= ' /Type /TransformParams'; $out .= ' /P '.$this->signature_data['cert_type']; $out .= ' /V /1.2'; } else { $out .= ' /TransformMethod /UR3'; $out .= ' /TransformParams <<'; $out .= ' /Type /TransformParams'; $out .= ' /V /2.2'; if (!$this->empty_string($this->ur['document'])) { $out .= ' /Document['.$this->ur['document'].']'; } if (!$this->empty_string($this->ur['form'])) { $out .= ' /Form['.$this->ur['form'].']'; } if (!$this->empty_string($this->ur['signature'])) { $out .= ' /Signature['.$this->ur['signature'].']'; } if (!$this->empty_string($this->ur['annots'])) { $out .= ' /Annots['.$this->ur['annots'].']'; } if (!$this->empty_string($this->ur['ef'])) { $out .= ' /EF['.$this->ur['ef'].']'; } if (!$this->empty_string($this->ur['formex'])) { $out .= ' /FormEX['.$this->ur['formex'].']'; } } $out .= ' >>'; // close TransformParams // optional digest data (values must be calculated and replaced later) //$out .= ' /Data ********** 0 R'; //$out .= ' /DigestMethod/MD5'; //$out .= ' /DigestLocation[********** 34]'; //$out .= ' /DigestValue<********************************>'; $out .= ' >>'; $out .= ' ]'; // end of reference if (isset($this->signature_data['info']['Name']) AND !$this->empty_string($this->signature_data['info']['Name'])) { $out .= ' /Name '.$this->_textstring($this->signature_data['info']['Name'], $sigobjid); } if (isset($this->signature_data['info']['Location']) AND !$this->empty_string($this->signature_data['info']['Location'])) { $out .= ' /Location '.$this->_textstring($this->signature_data['info']['Location'], $sigobjid); } if (isset($this->signature_data['info']['Reason']) AND !$this->empty_string($this->signature_data['info']['Reason'])) { $out .= ' /Reason '.$this->_textstring($this->signature_data['info']['Reason'], $sigobjid); } if (isset($this->signature_data['info']['ContactInfo']) AND !$this->empty_string($this->signature_data['info']['ContactInfo'])) { $out .= ' /ContactInfo '.$this->_textstring($this->signature_data['info']['ContactInfo'], $sigobjid); } $out .= ' /M '.$this->_datestring($sigobjid); $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } /** * Set User's Rights for PDF Reader * WARNING: This is experimental and currently do not work. * Check the PDF Reference 8.7.1 Transform Methods, * Table 8.105 Entries in the UR transform parameters dictionary * @param $enable (boolean) if true enable user's rights on PDF reader * @param $document (string) Names specifying additional document-wide usage rights for the document. The only defined value is "/FullSave", which permits a user to save the document along with modified form and/or annotation data. * @param $annots (string) Names specifying additional annotation-related usage rights for the document. Valid names in PDF 1.5 and later are /Create/Delete/Modify/Copy/Import/Export, which permit the user to perform the named operation on annotations. * @param $form (string) Names specifying additional form-field-related usage rights for the document. Valid names are: /Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate * @param $signature (string) Names specifying additional signature-related usage rights for the document. The only defined value is /Modify, which permits a user to apply a digital signature to an existing signature form field or clear a signed signature form field. * @param $ef (string) Names specifying additional usage rights for named embedded files in the document. Valid names are /Create/Delete/Modify/Import, which permit the user to perform the named operation on named embedded files Names specifying additional embedded-files-related usage rights for the document. * @param $formex (string) Names specifying additional form-field-related usage rights. The only valid name is BarcodePlaintext, which permits text form field data to be encoded as a plaintext two-dimensional barcode. * @public * @author Nicola Asuni * @since 2.9.000 (2008-03-26) */ public function setUserRights( $enable=true, $document='/FullSave', $annots='/Create/Delete/Modify/Copy/Import/Export', $form='/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate', $signature='/Modify', $ef='/Create/Delete/Modify/Import', $formex='') { $this->ur['enabled'] = $enable; $this->ur['document'] = $document; $this->ur['annots'] = $annots; $this->ur['form'] = $form; $this->ur['signature'] = $signature; $this->ur['ef'] = $ef; $this->ur['formex'] = $formex; if (!$this->sign) { $this->setSignature('', '', '', '', 0, array()); } } /** * Enable document signature (requires the OpenSSL Library). * The digital signature improve document authenticity and integrity and allows o enable extra features on Acrobat Reader. * To create self-signed signature: openssl req -x509 -nodes -days 365000 -newkey rsa:1024 -keyout tcpdf.crt -out tcpdf.crt * To export crt to p12: openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12 * To convert pfx certificate to pem: openssl pkcs12 -in tcpdf.pfx -out tcpdf.crt -nodes * @param $signing_cert (mixed) signing certificate (string or filename prefixed with 'file://') * @param $private_key (mixed) private key (string or filename prefixed with 'file://') * @param $private_key_password (string) password * @param $extracerts (string) specifies the name of a file containing a bunch of extra certificates to include in the signature which can for example be used to help the recipient to verify the certificate that you used. * @param $cert_type (int) The access permissions granted for this document. Valid values shall be: 1 = No changes to the document shall be permitted; any change to the document shall invalidate the signature; 2 = Permitted changes shall be filling in forms, instantiating page templates, and signing; other changes shall invalidate the signature; 3 = Permitted changes shall be the same as for 2, as well as annotation creation, deletion, and modification; other changes shall invalidate the signature. * @param $info (array) array of option information: Name, Location, Reason, ContactInfo. * @public * @author Nicola Asuni * @since 4.6.005 (2009-04-24) */ public function setSignature($signing_cert='', $private_key='', $private_key_password='', $extracerts='', $cert_type=2, $info=array()) { // to create self-signed signature: openssl req -x509 -nodes -days 365000 -newkey rsa:1024 -keyout tcpdf.crt -out tcpdf.crt // to export crt to p12: openssl pkcs12 -export -in tcpdf.crt -out tcpdf.p12 // to convert pfx certificate to pem: openssl // OpenSSL> pkcs12 -in -out -nodes $this->sign = true; ++$this->n; $this->sig_obj_id = $this->n; // signature widget ++$this->n; // signature object ($this->sig_obj_id + 1) $this->signature_data = array(); if (strlen($signing_cert) == 0) { $signing_cert = 'file://'.dirname(__FILE__).'/tcpdf.crt'; $private_key_password = 'tcpdfdemo'; } if (strlen($private_key) == 0) { $private_key = $signing_cert; } $this->signature_data['signcert'] = $signing_cert; $this->signature_data['privkey'] = $private_key; $this->signature_data['password'] = $private_key_password; $this->signature_data['extracerts'] = $extracerts; $this->signature_data['cert_type'] = $cert_type; $this->signature_data['info'] = $info; } /** * Set the digital signature appearance (a cliccable rectangle area to get signature properties) * @param $x (float) Abscissa of the upper-left corner. * @param $y (float) Ordinate of the upper-left corner. * @param $w (float) Width of the signature area. * @param $h (float) Height of the signature area. * @param $page (int) option page number (if < 0 the current page is used). * @public * @author Nicola Asuni * @since 5.3.011 (2010-06-17) */ public function setSignatureAppearance($x=0, $y=0, $w=0, $h=0, $page=-1) { $this->signature_appearance = $this->getSignatureAppearanceArray($x, $y, $w, $h, $page); } /** * Add an empty digital signature appearance (a cliccable rectangle area to get signature properties) * @param $x (float) Abscissa of the upper-left corner. * @param $y (float) Ordinate of the upper-left corner. * @param $w (float) Width of the signature area. * @param $h (float) Height of the signature area. * @param $page (int) option page number (if < 0 the current page is used). * @public * @author Nicola Asuni * @since 5.9.101 (2011-07-06) */ public function addEmptySignatureAppearance($x=0, $y=0, $w=0, $h=0, $page=-1) { ++$this->n; $this->empty_signature_appearance[] = array('objid' => $this->n) + $this->getSignatureAppearanceArray($x, $y, $w, $h, $page); } /** * Get the array that defines the signature appearance (page and rectangle coordinates). * @param $x (float) Abscissa of the upper-left corner. * @param $y (float) Ordinate of the upper-left corner. * @param $w (float) Width of the signature area. * @param $h (float) Height of the signature area. * @param $page (int) option page number (if < 0 the current page is used). * @return (array) Array defining page and rectangle coordinates of signature appearance. * @protected * @author Nicola Asuni * @since 5.9.101 (2011-07-06) */ protected function getSignatureAppearanceArray($x=0, $y=0, $w=0, $h=0, $page=-1) { $sigapp = array(); if (($page < 1) OR ($page > $this->numpages)) { $sigapp['page'] = $this->page; } else { $sigapp['page'] = intval($page); } $a = $x * $this->k; $b = $this->pagedim[($sigapp['page'])]['h'] - (($y + $h) * $this->k); $c = $w * $this->k; $d = $h * $this->k; $sigapp['rect'] = sprintf('%.2F %.2F %.2F %.2F', $a, $b, ($a + $c), ($b + $d)); return $sigapp; } /** * Create a new page group. * NOTE: call this function before calling AddPage() * @param $page (int) starting group page (leave empty for next page). * @public * @since 3.0.000 (2008-03-27) */ public function startPageGroup($page='') { if (empty($page)) { $page = $this->page + 1; } $this->newpagegroup[$page] = sizeof($this->newpagegroup) + 1; } /** * This method is DEPRECATED and doesn't have any effect. * Please remove any reference to this method. * @param $s (string) Empty parameter. * @deprecated deprecated since version 5.9.089 (2011-06-13) * @public */ public function AliasNbPages($s='') {} /** * This method is DEPRECATED and doesn't have any effect. * Please remove any reference to this method. * @param $s (string) Empty parameter. * @deprecated deprecated since version 5.9.089 (2011-06-13) * @public */ public function AliasNumPage($s='') {} /** * Set the starting page number. * @param $num (int) Starting page number. * @since 5.9.093 (2011-06-16) * @public */ public function setStartingPageNumber($num=1) { $this->starting_page_number = max(0, intval($num)); } /** * Returns the string alias used right align page numbers. * If the current font is unicode type, the returned string wil contain an additional open curly brace. * @return string * @since 5.9.099 (2011-06-27) * @public */ public function getAliasRightShift() { // calculate aproximatively the ratio between widths of aliases and replacements. $ref = '{'.$this->alias_right_shift.'}{'.$this->alias_tot_pages.'}{'.$this->alias_num_page.'}'; $rep = str_repeat(' ', $this->GetNumChars($ref)); $wdiff = max(1, ($this->GetStringWidth($ref) / $this->GetStringWidth($rep))); $sdiff = sprintf('%.3F', $wdiff); $alias = $this->alias_right_shift.$sdiff.'}'; if ($this->isUnicodeFont()) { $alias = '{'.$alias; } return $alias; } /** * Returns the string alias used for the total number of pages. * If the current font is unicode type, the returned string is surrounded by additional curly braces. * This alias will be replaced by the total number of pages in the document. * @return string * @since 4.0.018 (2008-08-08) * @public */ public function getAliasNbPages() { if ($this->isUnicodeFont()) { return '{'.$this->alias_tot_pages.'}'; } return $this->alias_tot_pages; } /** * Returns the string alias used for the page number. * If the current font is unicode type, the returned string is surrounded by additional curly braces. * This alias will be replaced by the page number. * @return string * @since 4.5.000 (2009-01-02) * @public */ public function getAliasNumPage() { if ($this->isUnicodeFont()) { return '{'.$this->alias_num_page.'}'; } return $this->alias_num_page; } /** * Return the alias for the total number of pages in the current page group. * If the current font is unicode type, the returned string is surrounded by additional curly braces. * This alias will be replaced by the total number of pages in this group. * @return alias of the current page group * @public * @since 3.0.000 (2008-03-27) */ public function getPageGroupAlias() { if ($this->isUnicodeFont()) { return '{'.$this->alias_group_tot_pages.'}'; } return $this->alias_group_tot_pages; } /** * Return the alias for the page number on the current page group. * If the current font is unicode type, the returned string is surrounded by additional curly braces. * This alias will be replaced by the page number (relative to the belonging group). * @return alias of the current page group * @public * @since 4.5.000 (2009-01-02) */ public function getPageNumGroupAlias() { if ($this->isUnicodeFont()) { return '{'.$this->alias_group_num_page.'}'; } return $this->alias_group_num_page; } /** * Return the current page in the group. * @return current page in the group * @public * @since 3.0.000 (2008-03-27) */ public function getGroupPageNo() { return $this->pagegroups[$this->currpagegroup]; } /** * Returns the current group page number formatted as a string. * @public * @since 4.3.003 (2008-11-18) * @see PaneNo(), formatPageNumber() */ public function getGroupPageNoFormatted() { return $this->formatPageNumber($this->getGroupPageNo()); } /** * Format the page numbers. * This method can be overriden for custom formats. * @param $num (int) page number * @protected * @since 4.2.005 (2008-11-06) */ protected function formatPageNumber($num) { return number_format((float)$num, 0, '', '.'); } /** * Format the page numbers on the Table Of Content. * This method can be overriden for custom formats. * @param $num (int) page number * @protected * @since 4.5.001 (2009-01-04) * @see addTOC(), addHTMLTOC() */ protected function formatTOCPageNumber($num) { return number_format((float)$num, 0, '', '.'); } /** * Returns the current page number formatted as a string. * @public * @since 4.2.005 (2008-11-06) * @see PaneNo(), formatPageNumber() */ public function PageNoFormatted() { return $this->formatPageNumber($this->PageNo()); } /** * Put pdf layers. * @protected * @since 3.0.000 (2008-03-27) */ protected function _putocg() { if (empty($this->pdflayers)) { return; } foreach ($this->pdflayers as $key => $layer) { $this->pdflayers[$key]['objid'] = $this->_newobj(); $out = '<< /Type /OCG'; $out .= ' /Name '.$this->_textstring($layer['name'], $this->pdflayers[$key]['objid']); $out .= ' /Usage <<'; $out .= ' /Print <>'; $out .= ' /View <>'; $out .= ' >> >>'; $out .= "\n".'endobj'; $this->_out($out); } } /** * Start a new pdf layer. * @param $name (string) Layer name (only a-z letters and numbers). Leave empty for automatic name. * @param $print (boolean) Set to true to print this layer. * @param $view (boolean) Set to true to view this layer. * @public * @since 5.9.102 (2011-07-13) */ public function startLayer($name='', $print=true, $view=true) { $layer = sprintf('LYR%03d', (count($this->pdflayers) + 1)); if (empty($name)) { $name = $layer; } else { $name = preg_replace('/[^a-zA-Z0-9_\-]/', '', $name); } $this->pdflayers[] = array('layer' => $layer, 'name' => $name, 'print' => $print, 'view' => $view); $this->openMarkedContent = true; $this->_out('/OC /'.$layer.' BDC'); } /** * End the current PDF layer. * @public * @since 5.9.102 (2011-07-13) */ public function endLayer() { if ($this->openMarkedContent) { // close existing open marked-content layer $this->_out('EMC'); $this->openMarkedContent = false; } } /** * Set the visibility of the successive elements. * This can be useful, for instance, to put a background * image or color that will show on screen but won't print. * @param $v (string) visibility mode. Legal values are: all, print, screen or view. * @public * @since 3.0.000 (2008-03-27) */ public function setVisibility($v) { $this->endLayer(); switch($v) { case 'print': { $this->startLayer('Print', true, false); break; } case 'view': case 'screen': { $this->startLayer('View', false, true); break; } case 'all': { $this->_out(''); break; } default: { $this->Error('Incorrect visibility: '.$v); break; } } } /** * Add transparency parameters to the current extgstate * @param $parms (array) parameters * @return the number of extgstates * @protected * @since 3.0.000 (2008-03-27) */ protected function addExtGState($parms) { if ($this->pdfa_mode) { // transparencies are not allowed in PDF/A mode return; } // check if this ExtGState already exist foreach ($this->extgstates as $i => $ext) { if ($ext['parms'] == $parms) { if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['extgstates'][$i] = $ext; } // return reference to existing ExtGState return $i; } } $n = (count($this->extgstates) + 1); $this->extgstates[$n] = array('parms' => $parms); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['extgstates'][$n] = $this->extgstates[$n]; } return $n; } /** * Add an extgstate * @param $gs (array) extgstate * @protected * @since 3.0.000 (2008-03-27) */ protected function setExtGState($gs) { if ($this->pdfa_mode) { // transparency is not allowed in PDF/A mode return; } $this->_out(sprintf('/GS%d gs', $gs)); } /** * Put extgstates for object transparency * @protected * @since 3.0.000 (2008-03-27) */ protected function _putextgstates() { if ($this->pdfa_mode) { // transparencies are not allowed in PDF/A mode return; } foreach ($this->extgstates as $i => $ext) { $this->extgstates[$i]['n'] = $this->_newobj(); $out = '<< /Type /ExtGState'; foreach ($ext['parms'] as $k => $v) { if (is_float($v)) { $v = sprintf('%.2F', $v); } $out .= ' /'.$k.' '.$v; } $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } } /** * Set alpha for stroking (CA) and non-stroking (ca) operations. * @param $alpha (float) real value from 0 (transparent) to 1 (opaque) * @param $bm (string) blend mode, one of the following: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity * @public * @since 3.0.000 (2008-03-27) */ public function setAlpha($alpha, $bm='Normal') { if ($this->pdfa_mode) { // transparency is not allowed in PDF/A mode return; } $gs = $this->addExtGState(array('ca' => $alpha, 'CA' => $alpha, 'BM' => '/'.$bm, 'AIS' => 'false')); $this->setExtGState($gs); } /** * Set the default JPEG compression quality (1-100) * @param $quality (int) JPEG quality, integer between 1 and 100 * @public * @since 3.0.000 (2008-03-27) */ public function setJPEGQuality($quality) { if (($quality < 1) OR ($quality > 100)) { $quality = 75; } $this->jpeg_quality = intval($quality); } /** * Set the default number of columns in a row for HTML tables. * @param $cols (int) number of columns * @public * @since 3.0.014 (2008-06-04) */ public function setDefaultTableColumns($cols=4) { $this->default_table_columns = intval($cols); } /** * Set the height of the cell (line height) respect the font height. * @param $h (int) cell proportion respect font height (typical value = 1.25). * @public * @since 3.0.014 (2008-06-04) */ public function setCellHeightRatio($h) { $this->cell_height_ratio = $h; } /** * return the height of cell repect font height. * @public * @since 4.0.012 (2008-07-24) */ public function getCellHeightRatio() { return $this->cell_height_ratio; } /** * Set the PDF version (check PDF reference for valid values). * @param $version (string) PDF document version. * @public * @since 3.1.000 (2008-06-09) */ public function setPDFVersion($version='1.7') { if ($this->pdfa_mode) { // PDF/A mode $this->PDFVersion = '1.4'; } else { $this->PDFVersion = $version; } } /** * Set the viewer preferences dictionary controlling the way the document is to be presented on the screen or in print. * (see Section 8.1 of PDF reference, "Viewer Preferences"). *
    • HideToolbar boolean (Optional) A flag specifying whether to hide the viewer application's tool bars when the document is active. Default value: false.
    • HideMenubar boolean (Optional) A flag specifying whether to hide the viewer application's menu bar when the document is active. Default value: false.
    • HideWindowUI boolean (Optional) A flag specifying whether to hide user interface elements in the document's window (such as scroll bars and navigation controls), leaving only the document's contents displayed. Default value: false.
    • FitWindow boolean (Optional) A flag specifying whether to resize the document's window to fit the size of the first displayed page. Default value: false.
    • CenterWindow boolean (Optional) A flag specifying whether to position the document's window in the center of the screen. Default value: false.
    • DisplayDocTitle boolean (Optional; PDF 1.4) A flag specifying whether the window's title bar should display the document title taken from the Title entry of the document information dictionary (see Section 10.2.1, "Document Information Dictionary"). If false, the title bar should instead display the name of the PDF file containing the document. Default value: false.
    • NonFullScreenPageMode name (Optional) The document's page mode, specifying how to display the document on exiting full-screen mode:
      • UseNone Neither document outline nor thumbnail images visible
      • UseOutlines Document outline visible
      • UseThumbs Thumbnail images visible
      • UseOC Optional content group panel visible
      This entry is meaningful only if the value of the PageMode entry in the catalog dictionary (see Section 3.6.1, "Document Catalog") is FullScreen; it is ignored otherwise. Default value: UseNone.
    • ViewArea name (Optional; PDF 1.4) The name of the page boundary representing the area of a page to be displayed when viewing the document on the screen. Valid values are (see Section 10.10.1, "Page Boundaries").:
      • MediaBox
      • CropBox (default)
      • BleedBox
      • TrimBox
      • ArtBox
    • ViewClip name (Optional; PDF 1.4) The name of the page boundary to which the contents of a page are to be clipped when viewing the document on the screen. Valid values are (see Section 10.10.1, "Page Boundaries").:
      • MediaBox
      • CropBox (default)
      • BleedBox
      • TrimBox
      • ArtBox
    • PrintArea name (Optional; PDF 1.4) The name of the page boundary representing the area of a page to be rendered when printing the document. Valid values are (see Section 10.10.1, "Page Boundaries").:
      • MediaBox
      • CropBox (default)
      • BleedBox
      • TrimBox
      • ArtBox
    • PrintClip name (Optional; PDF 1.4) The name of the page boundary to which the contents of a page are to be clipped when printing the document. Valid values are (see Section 10.10.1, "Page Boundaries").:
      • MediaBox
      • CropBox (default)
      • BleedBox
      • TrimBox
      • ArtBox
    • PrintScaling name (Optional; PDF 1.6) The page scaling option to be selected when a print dialog is displayed for this document. Valid values are:
      • None, which indicates that the print dialog should reflect no page scaling
      • AppDefault (default), which indicates that applications should use the current print scaling
    • Duplex name (Optional; PDF 1.7) The paper handling option to use when printing the file from the print dialog. The following values are valid:
      • Simplex - Print single-sided
      • DuplexFlipShortEdge - Duplex and flip on the short edge of the sheet
      • DuplexFlipLongEdge - Duplex and flip on the long edge of the sheet
      Default value: none
    • PickTrayByPDFSize boolean (Optional; PDF 1.7) A flag specifying whether the PDF page size is used to select the input paper tray. This setting influences only the preset values used to populate the print dialog presented by a PDF viewer application. If PickTrayByPDFSize is true, the check box in the print dialog associated with input paper tray is checked. Note: This setting has no effect on Mac OS systems, which do not provide the ability to pick the input tray by size.
    • PrintPageRange array (Optional; PDF 1.7) The page numbers used to initialize the print dialog box when the file is printed. The first page of the PDF file is denoted by 1. Each pair consists of the first and last pages in the sub-range. An odd number of integers causes this entry to be ignored. Negative numbers cause the entire array to be ignored. Default value: as defined by PDF viewer application
    • NumCopies integer (Optional; PDF 1.7) The number of copies to be printed when the print dialog is opened for this file. Supported values are the integers 2 through 5. Values outside this range are ignored. Default value: as defined by PDF viewer application, but typically 1
    * @param $preferences (array) array of options. * @author Nicola Asuni * @public * @since 3.1.000 (2008-06-09) */ public function setViewerPreferences($preferences) { $this->viewer_preferences = $preferences; } /** * Paints color transition registration bars * @param $x (float) abscissa of the top left corner of the rectangle. * @param $y (float) ordinate of the top left corner of the rectangle. * @param $w (float) width of the rectangle. * @param $h (float) height of the rectangle. * @param $transition (boolean) if true prints tcolor transitions to white. * @param $vertical (boolean) if true prints bar vertically. * @param $colors (string) colors to print, one letter per color separated by comma (for example 'A,W,R,G,B,C,M,Y,K'): A=black, W=white, R=red, G=green, B=blue, C=cyan, M=magenta, Y=yellow, K=black. * @author Nicola Asuni * @since 4.9.000 (2010-03-26) * @public */ public function colorRegistrationBar($x, $y, $w, $h, $transition=true, $vertical=false, $colors='A,R,G,B,C,M,Y,K') { $bars = explode(',', $colors); $numbars = count($bars); // number of bars to print // set bar measures if ($vertical) { $coords = array(0, 0, 0, 1); $wb = $w / $numbars; // bar width $hb = $h; // bar height $xd = $wb; // delta x $yd = 0; // delta y } else { $coords = array(1, 0, 0, 0); $wb = $w; // bar width $hb = $h / $numbars; // bar height $xd = 0; // delta x $yd = $hb; // delta y } $xb = $x; $yb = $y; foreach ($bars as $col) { switch ($col) { // set transition colors case 'A': { // BLACK $col_a = array(255); $col_b = array(0); break; } case 'W': { // WHITE $col_a = array(0); $col_b = array(255); break; } case 'R': { // R $col_a = array(255,255,255); $col_b = array(255,0,0); break; } case 'G': { // G $col_a = array(255,255,255); $col_b = array(0,255,0); break; } case 'B': { // B $col_a = array(255,255,255); $col_b = array(0,0,255); break; } case 'C': { // C $col_a = array(0,0,0,0); $col_b = array(100,0,0,0); break; } case 'M': { // M $col_a = array(0,0,0,0); $col_b = array(0,100,0,0); break; } case 'Y': { // Y $col_a = array(0,0,0,0); $col_b = array(0,0,100,0); break; } case 'K': { // K $col_a = array(0,0,0,0); $col_b = array(0,0,0,100); break; } default: { // GRAY $col_a = array(255); $col_b = array(0); break; } } if ($transition) { // color gradient $this->LinearGradient($xb, $yb, $wb, $hb, $col_a, $col_b, $coords); } else { // color rectangle $this->SetFillColorArray($col_b); $this->Rect($xb, $yb, $wb, $hb, 'F', array()); } $xb += $xd; $yb += $yd; } } /** * Paints crop marks. * @param $x (float) abscissa of the crop mark center. * @param $y (float) ordinate of the crop mark center. * @param $w (float) width of the crop mark. * @param $h (float) height of the crop mark. * @param $type (string) type of crop mark, one symbol per type separated by comma: T = TOP, F = BOTTOM, L = LEFT, R = RIGHT, TL = A = TOP-LEFT, TR = B = TOP-RIGHT, BL = C = BOTTOM-LEFT, BR = D = BOTTOM-RIGHT. * @param $color (array) crop mark color (default black). * @author Nicola Asuni * @since 4.9.000 (2010-03-26) * @public */ public function cropMark($x, $y, $w, $h, $type='T,R,B,L', $color=array(0,0,0)) { $this->SetLineStyle(array('width' => (0.5 / $this->k), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $color)); $type = strtoupper($type); $type = preg_replace('/[^A-Z\-\,]*/', '', $type); // split type in single components $type = str_replace('-', ',', $type); $type = str_replace('TL', 'T,L', $type); $type = str_replace('TR', 'T,R', $type); $type = str_replace('BL', 'F,L', $type); $type = str_replace('BR', 'F,R', $type); $type = str_replace('A', 'T,L', $type); $type = str_replace('B', 'T,R', $type); $type = str_replace('T,RO', 'BO', $type); $type = str_replace('C', 'F,L', $type); $type = str_replace('D', 'F,R', $type); $crops = explode(',', strtoupper($type)); // remove duplicates $crops = array_unique($crops); $dw = ($w / 4); // horizontal space to leave before the intersection point $dh = ($h / 4); // vertical space to leave before the intersection point foreach ($crops as $crop) { switch ($crop) { case 'T': case 'TOP': { $x1 = $x; $y1 = ($y - $h); $x2 = $x; $y2 = ($y - $dh); break; } case 'F': case 'BOTTOM': { $x1 = $x; $y1 = ($y + $dh); $x2 = $x; $y2 = ($y + $h); break; } case 'L': case 'LEFT': { $x1 = ($x - $w); $y1 = $y; $x2 = ($x - $dw); $y2 = $y; break; } case 'R': case 'RIGHT': { $x1 = ($x + $dw); $y1 = $y; $x2 = ($x + $w); $y2 = $y; break; } } $this->Line($x1, $y1, $x2, $y2); } } /** * Paints a registration mark * @param $x (float) abscissa of the registration mark center. * @param $y (float) ordinate of the registration mark center. * @param $r (float) radius of the crop mark. * @param $double (boolean) if true print two concentric crop marks. * @param $cola (array) crop mark color (default black). * @param $colb (array) second crop mark color. * @author Nicola Asuni * @since 4.9.000 (2010-03-26) * @public */ public function registrationMark($x, $y, $r, $double=false, $cola=array(0,0,0), $colb=array(255,255,255)) { $line_style = array('width' => (0.5 / $this->k), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $cola); $this->SetFillColorArray($cola); $this->PieSector($x, $y, $r, 90, 180, 'F'); $this->PieSector($x, $y, $r, 270, 360, 'F'); $this->Circle($x, $y, $r, 0, 360, 'C', $line_style, array(), 8); if ($double) { $r2 = $r * 0.5; $this->SetFillColorArray($colb); $this->PieSector($x, $y, $r2, 90, 180, 'F'); $this->PieSector($x, $y, $r2, 270, 360, 'F'); $this->SetFillColorArray($cola); $this->PieSector($x, $y, $r2, 0, 90, 'F'); $this->PieSector($x, $y, $r2, 180, 270, 'F'); $this->Circle($x, $y, $r2, 0, 360, 'C', $line_style, array(), 8); } } /** * Paints a linear colour gradient. * @param $x (float) abscissa of the top left corner of the rectangle. * @param $y (float) ordinate of the top left corner of the rectangle. * @param $w (float) width of the rectangle. * @param $h (float) height of the rectangle. * @param $col1 (array) first color (Grayscale, RGB or CMYK components). * @param $col2 (array) second color (Grayscale, RGB or CMYK components). * @param $coords (array) array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg). The default value is from left to right (x1=0, y1=0, x2=1, y2=0). * @author Andreas W・mser, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function LinearGradient($x, $y, $w, $h, $col1=array(), $col2=array(), $coords=array(0,0,1,0)) { $this->Clip($x, $y, $w, $h); $this->Gradient(2, $coords, array(array('color' => $col1, 'offset' => 0, 'exponent' => 1), array('color' => $col2, 'offset' => 1, 'exponent' => 1)), array(), false); } /** * Paints a radial colour gradient. * @param $x (float) abscissa of the top left corner of the rectangle. * @param $y (float) ordinate of the top left corner of the rectangle. * @param $w (float) width of the rectangle. * @param $h (float) height of the rectangle. * @param $col1 (array) first color (Grayscale, RGB or CMYK components). * @param $col2 (array) second color (Grayscale, RGB or CMYK components). * @param $coords (array) array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1, (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg). (fx, fy) should be inside the circle, otherwise some areas will not be defined. * @author Andreas W・mser, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function RadialGradient($x, $y, $w, $h, $col1=array(), $col2=array(), $coords=array(0.5,0.5,0.5,0.5,1)) { $this->Clip($x, $y, $w, $h); $this->Gradient(3, $coords, array(array('color' => $col1, 'offset' => 0, 'exponent' => 1), array('color' => $col2, 'offset' => 1, 'exponent' => 1)), array(), false); } /** * Paints a coons patch mesh. * @param $x (float) abscissa of the top left corner of the rectangle. * @param $y (float) ordinate of the top left corner of the rectangle. * @param $w (float) width of the rectangle. * @param $h (float) height of the rectangle. * @param $col1 (array) first color (lower left corner) (RGB components). * @param $col2 (array) second color (lower right corner) (RGB components). * @param $col3 (array) third color (upper right corner) (RGB components). * @param $col4 (array) fourth color (upper left corner) (RGB components). * @param $coords (array)
    • for one patch mesh: array(float x1, float y1, .... float x12, float y12): 12 pairs of coordinates (normally from 0 to 1) which specify the Bezier control points that define the patch. First pair is the lower left edge point, next is its right control point (control point 2). Then the other points are defined in the order: control point 1, edge point, control point 2 going counter-clockwise around the patch. Last (x12, y12) is the first edge point's left control point (control point 1).
    • for two or more patch meshes: array[number of patches]: arrays with the following keys for each patch: f: where to put that patch (0 = first patch, 1, 2, 3 = right, top and left of precedent patch - I didn't figure this out completely - just try and error ;-) points: 12 pairs of coordinates of the Bezier control points as above for the first patch, 8 pairs of coordinates for the following patches, ignoring the coordinates already defined by the precedent patch (I also didn't figure out the order of these - also: try and see what's happening) colors: must be 4 colors for the first patch, 2 colors for the following patches
    * @param $coords_min (array) minimum value used by the coordinates. If a coordinate's value is smaller than this it will be cut to coords_min. default: 0 * @param $coords_max (array) maximum value used by the coordinates. If a coordinate's value is greater than this it will be cut to coords_max. default: 1 * @param $antialias (boolean) A flag indicating whether to filter the shading function to prevent aliasing artifacts. * @author Andreas W・mser, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function CoonsPatchMesh($x, $y, $w, $h, $col1=array(), $col2=array(), $col3=array(), $col4=array(), $coords=array(0.00,0.0,0.33,0.00,0.67,0.00,1.00,0.00,1.00,0.33,1.00,0.67,1.00,1.00,0.67,1.00,0.33,1.00,0.00,1.00,0.00,0.67,0.00,0.33), $coords_min=0, $coords_max=1, $antialias=false) { if ($this->pdfa_mode) { return; } $this->Clip($x, $y, $w, $h); $n = count($this->gradients) + 1; $this->gradients[$n] = array(); $this->gradients[$n]['type'] = 6; //coons patch mesh $this->gradients[$n]['coords'] = array(); $this->gradients[$n]['antialias'] = $antialias; $this->gradients[$n]['colors'] = array(); $this->gradients[$n]['transparency'] = false; //check the coords array if it is the simple array or the multi patch array if (!isset($coords[0]['f'])) { //simple array -> convert to multi patch array if (!isset($col1[1])) { $col1[1] = $col1[2] = $col1[0]; } if (!isset($col2[1])) { $col2[1] = $col2[2] = $col2[0]; } if (!isset($col3[1])) { $col3[1] = $col3[2] = $col3[0]; } if (!isset($col4[1])) { $col4[1] = $col4[2] = $col4[0]; } $patch_array[0]['f'] = 0; $patch_array[0]['points'] = $coords; $patch_array[0]['colors'][0]['r'] = $col1[0]; $patch_array[0]['colors'][0]['g'] = $col1[1]; $patch_array[0]['colors'][0]['b'] = $col1[2]; $patch_array[0]['colors'][1]['r'] = $col2[0]; $patch_array[0]['colors'][1]['g'] = $col2[1]; $patch_array[0]['colors'][1]['b'] = $col2[2]; $patch_array[0]['colors'][2]['r'] = $col3[0]; $patch_array[0]['colors'][2]['g'] = $col3[1]; $patch_array[0]['colors'][2]['b'] = $col3[2]; $patch_array[0]['colors'][3]['r'] = $col4[0]; $patch_array[0]['colors'][3]['g'] = $col4[1]; $patch_array[0]['colors'][3]['b'] = $col4[2]; } else { //multi patch array $patch_array = $coords; } $bpcd = 65535; //16 bits per coordinate //build the data stream $this->gradients[$n]['stream'] = ''; $count_patch = count($patch_array); for ($i=0; $i < $count_patch; ++$i) { $this->gradients[$n]['stream'] .= chr($patch_array[$i]['f']); //start with the edge flag as 8 bit $count_points = count($patch_array[$i]['points']); for ($j=0; $j < $count_points; ++$j) { //each point as 16 bit $patch_array[$i]['points'][$j] = (($patch_array[$i]['points'][$j] - $coords_min) / ($coords_max - $coords_min)) * $bpcd; if ($patch_array[$i]['points'][$j] < 0) { $patch_array[$i]['points'][$j] = 0; } if ($patch_array[$i]['points'][$j] > $bpcd) { $patch_array[$i]['points'][$j] = $bpcd; } $this->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] / 256)); $this->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] % 256)); } $count_cols = count($patch_array[$i]['colors']); for ($j=0; $j < $count_cols; ++$j) { //each color component as 8 bit $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['r']); $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['g']); $this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['b']); } } //paint the gradient $this->_out('/Sh'.$n.' sh'); //restore previous Graphic State $this->_out('Q'); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['gradients'][$n] = $this->gradients[$n]; } } /** * Set a rectangular clipping area. * @param $x (float) abscissa of the top left corner of the rectangle (or top right corner for RTL mode). * @param $y (float) ordinate of the top left corner of the rectangle. * @param $w (float) width of the rectangle. * @param $h (float) height of the rectangle. * @author Andreas W・mser, Nicola Asuni * @since 3.1.000 (2008-06-09) * @protected */ protected function Clip($x, $y, $w, $h) { if ($this->rtl) { $x = $this->w - $x - $w; } //save current Graphic State $s = 'q'; //set clipping area $s .= sprintf(' %.2F %.2F %.2F %.2F re W n', $x*$this->k, ($this->h-$y)*$this->k, $w*$this->k, -$h*$this->k); //set up transformation matrix for gradient $s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $w*$this->k, $h*$this->k, $x*$this->k, ($this->h-($y+$h))*$this->k); $this->_out($s); } /** * Output gradient. * @param $type (int) type of gradient (1 Function-based shading; 2 Axial shading; 3 Radial shading; 4 Free-form Gouraud-shaded triangle mesh; 5 Lattice-form Gouraud-shaded triangle mesh; 6 Coons patch mesh; 7 Tensor-product patch mesh). (Not all types are currently supported) * @param $coords (array) array of coordinates. * @param $stops (array) array gradient color components: color = array of GRAY, RGB or CMYK color components; offset = (0 to 1) represents a location along the gradient vector; exponent = exponent of the exponential interpolation function (default = 1). * @param $background (array) An array of colour components appropriate to the colour space, specifying a single background colour value. * @param $antialias (boolean) A flag indicating whether to filter the shading function to prevent aliasing artifacts. * @author Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function Gradient($type, $coords, $stops, $background=array(), $antialias=false) { if ($this->pdfa_mode) { return; } $n = count($this->gradients) + 1; $this->gradients[$n] = array(); $this->gradients[$n]['type'] = $type; $this->gradients[$n]['coords'] = $coords; $this->gradients[$n]['antialias'] = $antialias; $this->gradients[$n]['colors'] = array(); $this->gradients[$n]['transparency'] = false; // color space $numcolspace = count($stops[0]['color']); $bcolor = array_values($background); switch($numcolspace) { case 4: { // CMYK $this->gradients[$n]['colspace'] = 'DeviceCMYK'; if (!empty($background)) { $this->gradients[$n]['background'] = sprintf('%.3F %.3F %.3F %.3F', $bcolor[0]/100, $bcolor[1]/100, $bcolor[2]/100, $bcolor[3]/100); } break; } case 3: { // RGB $this->gradients[$n]['colspace'] = 'DeviceRGB'; if (!empty($background)) { $this->gradients[$n]['background'] = sprintf('%.3F %.3F %.3F', $bcolor[0]/255, $bcolor[1]/255, $bcolor[2]/255); } break; } case 1: { // Gray scale $this->gradients[$n]['colspace'] = 'DeviceGray'; if (!empty($background)) { $this->gradients[$n]['background'] = sprintf('%.3F', $bcolor[0]/255); } break; } } $num_stops = count($stops); $last_stop_id = $num_stops - 1; foreach ($stops as $key => $stop) { $this->gradients[$n]['colors'][$key] = array(); // offset represents a location along the gradient vector if (isset($stop['offset'])) { $this->gradients[$n]['colors'][$key]['offset'] = $stop['offset']; } else { if ($key == 0) { $this->gradients[$n]['colors'][$key]['offset'] = 0; } elseif ($key == $last_stop_id) { $this->gradients[$n]['colors'][$key]['offset'] = 1; } else { $offsetstep = (1 - $this->gradients[$n]['colors'][($key - 1)]['offset']) / ($num_stops - $key); $this->gradients[$n]['colors'][$key]['offset'] = $this->gradients[$n]['colors'][($key - 1)]['offset'] + $offsetstep; } } if (isset($stop['opacity'])) { $this->gradients[$n]['colors'][$key]['opacity'] = $stop['opacity']; if ((!$this->pdfa_mode) AND ($stop['opacity'] < 1)) { $this->gradients[$n]['transparency'] = true; } } else { $this->gradients[$n]['colors'][$key]['opacity'] = 1; } // exponent for the exponential interpolation function if (isset($stop['exponent'])) { $this->gradients[$n]['colors'][$key]['exponent'] = $stop['exponent']; } else { $this->gradients[$n]['colors'][$key]['exponent'] = 1; } // set colors $color = array_values($stop['color']); switch($numcolspace) { case 4: { // CMYK $this->gradients[$n]['colors'][$key]['color'] = sprintf('%.3F %.3F %.3F %.3F', $color[0]/100, $color[1]/100, $color[2]/100, $color[3]/100); break; } case 3: { // RGB $this->gradients[$n]['colors'][$key]['color'] = sprintf('%.3F %.3F %.3F', $color[0]/255, $color[1]/255, $color[2]/255); break; } case 1: { // Gray scale $this->gradients[$n]['colors'][$key]['color'] = sprintf('%.3F', $color[0]/255); break; } } } if ($this->gradients[$n]['transparency']) { // paint luminosity gradient $this->_out('/TGS'.$n.' gs'); } //paint the gradient $this->_out('/Sh'.$n.' sh'); //restore previous Graphic State $this->_out('Q'); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['gradients'][$n] = $this->gradients[$n]; } } /** * Output gradient shaders. * @author Nicola Asuni * @since 3.1.000 (2008-06-09) * @protected */ function _putshaders() { if ($this->pdfa_mode) { return; } $idt = count($this->gradients); //index for transparency gradients foreach ($this->gradients as $id => $grad) { if (($grad['type'] == 2) OR ($grad['type'] == 3)) { $fc = $this->_newobj(); $out = '<<'; $out .= ' /FunctionType 3'; $out .= ' /Domain [0 1]'; $functions = ''; $bounds = ''; $encode = ''; $i = 1; $num_cols = count($grad['colors']); $lastcols = $num_cols - 1; for ($i = 1; $i < $num_cols; ++$i) { $functions .= ($fc + $i).' 0 R '; if ($i < $lastcols) { $bounds .= sprintf('%.3F ', $grad['colors'][$i]['offset']); } $encode .= '0 1 '; } $out .= ' /Functions ['.trim($functions).']'; $out .= ' /Bounds ['.trim($bounds).']'; $out .= ' /Encode ['.trim($encode).']'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); for ($i = 1; $i < $num_cols; ++$i) { $this->_newobj(); $out = '<<'; $out .= ' /FunctionType 2'; $out .= ' /Domain [0 1]'; $out .= ' /C0 ['.$grad['colors'][($i - 1)]['color'].']'; $out .= ' /C1 ['.$grad['colors'][$i]['color'].']'; $out .= ' /N '.$grad['colors'][$i]['exponent']; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } // set transparency fuctions if ($grad['transparency']) { $ft = $this->_newobj(); $out = '<<'; $out .= ' /FunctionType 3'; $out .= ' /Domain [0 1]'; $functions = ''; $i = 1; $num_cols = count($grad['colors']); for ($i = 1; $i < $num_cols; ++$i) { $functions .= ($ft + $i).' 0 R '; } $out .= ' /Functions ['.trim($functions).']'; $out .= ' /Bounds ['.trim($bounds).']'; $out .= ' /Encode ['.trim($encode).']'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); for ($i = 1; $i < $num_cols; ++$i) { $this->_newobj(); $out = '<<'; $out .= ' /FunctionType 2'; $out .= ' /Domain [0 1]'; $out .= ' /C0 ['.$grad['colors'][($i - 1)]['opacity'].']'; $out .= ' /C1 ['.$grad['colors'][$i]['opacity'].']'; $out .= ' /N '.$grad['colors'][$i]['exponent']; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); } } } // set shading object $this->_newobj(); $out = '<< /ShadingType '.$grad['type']; if (isset($grad['colspace'])) { $out .= ' /ColorSpace /'.$grad['colspace']; } else { $out .= ' /ColorSpace /DeviceRGB'; } if (isset($grad['background']) AND !empty($grad['background'])) { $out .= ' /Background ['.$grad['background'].']'; } if (isset($grad['antialias']) AND ($grad['antialias'] === true)) { $out .= ' /AntiAlias true'; } if ($grad['type'] == 2) { $out .= ' '.sprintf('/Coords [%.3F %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]); $out .= ' /Domain [0 1]'; $out .= ' /Function '.$fc.' 0 R'; $out .= ' /Extend [true true]'; $out .= ' >>'; } elseif ($grad['type'] == 3) { //x0, y0, r0, x1, y1, r1 //at this this time radius of inner circle is 0 $out .= ' '.sprintf('/Coords [%.3F %.3F 0 %.3F %.3F %.3F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]); $out .= ' /Domain [0 1]'; $out .= ' /Function '.$fc.' 0 R'; $out .= ' /Extend [true true]'; $out .= ' >>'; } elseif ($grad['type'] == 6) { $out .= ' /BitsPerCoordinate 16'; $out .= ' /BitsPerComponent 8'; $out .= ' /Decode[0 1 0 1 0 1 0 1 0 1]'; $out .= ' /BitsPerFlag 8'; $stream = $this->_getrawstream($grad['stream']); $out .= ' /Length '.strlen($stream); $out .= ' >>'; $out .= ' stream'."\n".$stream."\n".'endstream'; } $out .= "\n".'endobj'; $this->_out($out); if ($grad['transparency']) { $shading_transparency = preg_replace('/\/ColorSpace \/[^\s]+/si', '/ColorSpace /DeviceGray', $out); $shading_transparency = preg_replace('/\/Function [0-9]+ /si', '/Function '.$ft.' ', $shading_transparency); } $this->gradients[$id]['id'] = $this->n; // set pattern object $this->_newobj(); $out = '<< /Type /Pattern /PatternType 2'; $out .= ' /Shading '.$this->gradients[$id]['id'].' 0 R'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); $this->gradients[$id]['pattern'] = $this->n; // set shading and pattern for transparency mask if ($grad['transparency']) { // luminosity pattern $idgs = $id + $idt; $this->_newobj(); $this->_out($shading_transparency); $this->gradients[$idgs]['id'] = $this->n; $this->_newobj(); $out = '<< /Type /Pattern /PatternType 2'; $out .= ' /Shading '.$this->gradients[$idgs]['id'].' 0 R'; $out .= ' >>'; $out .= "\n".'endobj'; $this->_out($out); $this->gradients[$idgs]['pattern'] = $this->n; // luminosity XObject $oid = $this->_newobj(); $this->xobjects['LX'.$oid] = array('n' => $oid); $filter = ''; $stream = 'q /a0 gs /Pattern cs /p'.$idgs.' scn 0 0 '.$this->wPt.' '.$this->hPt.' re f Q'; if ($this->compress) { $filter = ' /Filter /FlateDecode'; $stream = gzcompress($stream); } $stream = $this->_getrawstream($stream); $out = '<< /Type /XObject /Subtype /Form /FormType 1'.$filter; $out .= ' /Length '.strlen($stream); $rect = sprintf('%.2F %.2F', $this->wPt, $this->hPt); $out .= ' /BBox [0 0 '.$rect.']'; $out .= ' /Group << /Type /Group /S /Transparency /CS /DeviceGray >>'; $out .= ' /Resources <<'; $out .= ' /ExtGState << /a0 << /ca 1 /CA 1 >> >>'; $out .= ' /Pattern << /p'.$idgs.' '.$this->gradients[$idgs]['pattern'].' 0 R >>'; $out .= ' >>'; $out .= ' >> '; $out .= ' stream'."\n".$stream."\n".'endstream'; $out .= "\n".'endobj'; $this->_out($out); // SMask $this->_newobj(); $out = '<< /Type /Mask /S /Luminosity /G '.($this->n - 1).' 0 R >>'."\n".'endobj'; $this->_out($out); // ExtGState $this->_newobj(); $out = '<< /Type /ExtGState /SMask '.($this->n - 1).' 0 R /AIS false >>'."\n".'endobj'; $this->_out($out); $this->extgstates[] = array('n' => $this->n, 'name' => 'TGS'.$id); } } } /** * Draw the sector of a circle. * It can be used for instance to render pie charts. * @param $xc (float) abscissa of the center. * @param $yc (float) ordinate of the center. * @param $r (float) radius. * @param $a (float) start angle (in degrees). * @param $b (float) end angle (in degrees). * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $cw: (float) indicates whether to go clockwise (default: true). * @param $o: (float) origin of angles (0 for 3 o'clock, 90 for noon, 180 for 9 o'clock, 270 for 6 o'clock). Default: 90. * @author Maxime Delorme, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function PieSector($xc, $yc, $r, $a, $b, $style='FD', $cw=true, $o=90) { $this->PieSectorXY($xc, $yc, $r, $r, $a, $b, $style, $cw, $o); } /** * Draw the sector of an ellipse. * It can be used for instance to render pie charts. * @param $xc (float) abscissa of the center. * @param $yc (float) ordinate of the center. * @param $rx (float) the x-axis radius. * @param $ry (float) the y-axis radius. * @param $a (float) start angle (in degrees). * @param $b (float) end angle (in degrees). * @param $style (string) Style of rendering. See the getPathPaintOperator() function for more information. * @param $cw: (float) indicates whether to go clockwise. * @param $o: (float) origin of angles (0 for 3 o'clock, 90 for noon, 180 for 9 o'clock, 270 for 6 o'clock). * @param $nc (integer) Number of curves used to draw a 90 degrees portion of arc. * @author Maxime Delorme, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function PieSectorXY($xc, $yc, $rx, $ry, $a, $b, $style='FD', $cw=false, $o=0, $nc=2) { if ($this->rtl) { $xc = $this->w - $xc; } $op = $this->getPathPaintOperator($style); if ($op == 'f') { $line_style = array(); } if ($cw) { $d = $b; $b = 360 - $a + $o; $a = 360 - $d + $o; } else { $b += $o; $a += $o; } $this->_outellipticalarc($xc, $yc, $rx, $ry, 0, $a, $b, true, $nc); $this->_out($op); } /** * Embed vector-based Adobe Illustrator (AI) or AI-compatible EPS files. * NOTE: EPS is not yet fully implemented, use the setRasterizeVectorImages() method to enable/disable rasterization of vector images using ImageMagick library. * Only vector drawing is supported, not text or bitmap. * Although the script was successfully tested with various AI format versions, best results are probably achieved with files that were exported in the AI3 format (tested with Illustrator CS2, Freehand MX and Photoshop CS2). * @param $file (string) Name of the file containing the image or a '@' character followed by the EPS/AI data string. * @param $x (float) Abscissa of the upper-left corner. * @param $y (float) Ordinate of the upper-left corner. * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated. * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated. * @param $link (mixed) URL or identifier returned by AddLink(). * @param $useBoundingBox (boolean) specifies whether to position the bounding box (true) or the complete canvas (false) at location (x,y). Default value is true. * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
    • T: top-right for LTR or top-left for RTL
    • M: middle-right for LTR or middle-left for RTL
    • B: bottom-right for LTR or bottom-left for RTL
    • N: next line
    * @param $palign (string) Allows to center or align the image on the current line. Possible values are:
    • L : left align
    • C : center
    • R : right align
    • '' : empty string : left for LTR or right for RTL
    * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
    • 0: no border (default)
    • 1: frame
    or a string containing some or all of the following characters (in any order):
    • L: left
    • T: top
    • R: right
    • B: bottom
    or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $fitonpage (boolean) if true the image is resized to not exceed page dimensions. * @param $fixoutvals (boolean) if true remove values outside the bounding box. * @author Valentin Schmidt, Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function ImageEps($file, $x='', $y='', $w=0, $h=0, $link='', $useBoundingBox=true, $align='', $palign='', $border=0, $fitonpage=false, $fixoutvals=false) { if ($this->rasterize_vector_images AND ($w > 0) AND ($h > 0)) { // convert EPS to raster image using GD or ImageMagick libraries return $this->Image($file, $x, $y, $w, $h, 'EPS', $link, $align, true, 300, $palign, false, false, $border, false, false, $fitonpage); } if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); $k = $this->k; if ($file{0} === '@') { // image from string $data = substr($file, 1); } else { // EPS/AI file $data = file_get_contents($file); } if ($data === false) { $this->Error('EPS file not found: '.$file); } $regs = array(); // EPS/AI compatibility check (only checks files created by Adobe Illustrator!) preg_match("/%%Creator:([^\r\n]+)/", $data, $regs); # find Creator if (count($regs) > 1) { $version_str = trim($regs[1]); # e.g. "Adobe Illustrator(R) 8.0" if (strpos($version_str, 'Adobe Illustrator') !== false) { $versexp = explode(' ', $version_str); $version = (float)array_pop($versexp); if ($version >= 9) { $this->Error('This version of Adobe Illustrator file is not supported: '.$file); } } } // strip binary bytes in front of PS-header $start = strpos($data, '%!PS-Adobe'); if ($start > 0) { $data = substr($data, $start); } // find BoundingBox params preg_match("/%%BoundingBox:([^\r\n]+)/", $data, $regs); if (count($regs) > 1) { list($x1, $y1, $x2, $y2) = explode(' ', trim($regs[1])); } else { $this->Error('No BoundingBox found in EPS/AI file: '.$file); } $start = strpos($data, '%%EndSetup'); if ($start === false) { $start = strpos($data, '%%EndProlog'); } if ($start === false) { $start = strpos($data, '%%BoundingBox'); } $data = substr($data, $start); $end = strpos($data, '%%PageTrailer'); if ($end===false) { $end = strpos($data, 'showpage'); } if ($end) { $data = substr($data, 0, $end); } // calculate image width and height on document if (($w <= 0) AND ($h <= 0)) { $w = ($x2 - $x1) / $k; $h = ($y2 - $y1) / $k; } elseif ($w <= 0) { $w = ($x2-$x1) / $k * ($h / (($y2 - $y1) / $k)); } elseif ($h <= 0) { $h = ($y2 - $y1) / $k * ($w / (($x2 - $x1) / $k)); } // fit the image on available space list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage); if ($this->rasterize_vector_images) { // convert EPS to raster image using GD or ImageMagick libraries return $this->Image($file, $x, $y, $w, $h, 'EPS', $link, $align, true, 300, $palign, false, false, $border, false, false, $fitonpage); } // set scaling factors $scale_x = $w / (($x2 - $x1) / $k); $scale_y = $h / (($y2 - $y1) / $k); // set alignment $this->img_rb_y = $y + $h; // set alignment if ($this->rtl) { if ($palign == 'L') { $ximg = $this->lMargin; } elseif ($palign == 'C') { $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($palign == 'R') { $ximg = $this->w - $this->rMargin - $w; } else { $ximg = $x - $w; } $this->img_rb_x = $ximg; } else { if ($palign == 'L') { $ximg = $this->lMargin; } elseif ($palign == 'C') { $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($palign == 'R') { $ximg = $this->w - $this->rMargin - $w; } else { $ximg = $x; } $this->img_rb_x = $ximg + $w; } if ($useBoundingBox) { $dx = $ximg * $k - $x1; $dy = $y * $k - $y1; } else { $dx = $ximg * $k; $dy = $y * $k; } // save the current graphic state $this->_out('q'.$this->epsmarker); // translate $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F cm', 1, 0, 0, 1, $dx, $dy + ($this->hPt - (2 * $y * $k) - ($y2 - $y1)))); // scale if (isset($scale_x)) { $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F cm', $scale_x, 0, 0, $scale_y, $x1 * (1 - $scale_x), $y2 * (1 - $scale_y))); } // handle pc/unix/mac line endings $lines = preg_split('/[\r\n]+/si', $data, -1, PREG_SPLIT_NO_EMPTY); $u=0; $cnt = count($lines); for ($i=0; $i < $cnt; ++$i) { $line = $lines[$i]; if (($line == '') OR ($line{0} == '%')) { continue; } $len = strlen($line); // check for spot color names $color_name = ''; if (strcasecmp('x', substr(trim($line), -1)) == 0) { if (preg_match('/\([^\)]*\)/', $line, $matches) > 0) { // extract spot color name $color_name = $matches[0]; // remove color name from string $line = str_replace(' '.$color_name, '', $line); // remove pharentesis from color name $color_name = substr($color_name, 1, -1); } } $chunks = explode(' ', $line); $cmd = trim(array_pop($chunks)); // RGB if (($cmd == 'Xa') OR ($cmd == 'XA')) { $b = array_pop($chunks); $g = array_pop($chunks); $r = array_pop($chunks); $this->_out(''.$r.' '.$g.' '.$b.' '.($cmd=='Xa'?'rg':'RG')); //substr($line, 0, -2).'rg' -> in EPS (AI8): c m y k r g b rg! continue; } $skip = false; if ($fixoutvals) { // check for values outside the bounding box switch ($cmd) { case 'm': case 'l': case 'L': { // skip values outside bounding box foreach ($chunks as $key => $val) { if ((($key % 2) == 0) AND (($val < $x1) OR ($val > $x2))) { $skip = true; } elseif ((($key % 2) != 0) AND (($val < $y1) OR ($val > $y2))) { $skip = true; } } } } } switch ($cmd) { case 'm': case 'l': case 'v': case 'y': case 'c': case 'k': case 'K': case 'g': case 'G': case 's': case 'S': case 'J': case 'j': case 'w': case 'M': case 'd': case 'n': { if ($skip) { break; } $this->_out($line); break; } case 'x': {// custom fill color if (empty($color_name)) { // CMYK color list($col_c, $col_m, $col_y, $col_k) = $chunks; $this->_out(''.$col_c.' '.$col_m.' '.$col_y.' '.$col_k.' k'); } else { // Spot Color (CMYK + tint) list($col_c, $col_m, $col_y, $col_k, $col_t) = $chunks; $this->AddSpotColor($color_name, ($col_c * 100), ($col_m * 100), ($col_y * 100), ($col_k * 100)); $color_cmd = sprintf('/CS%d cs %.3F scn', $this->spot_colors[$color_name]['i'], (1 - $col_t)); $this->_out($color_cmd); } break; } case 'X': { // custom stroke color if (empty($color_name)) { // CMYK color list($col_c, $col_m, $col_y, $col_k) = $chunks; $this->_out(''.$col_c.' '.$col_m.' '.$col_y.' '.$col_k.' K'); } else { // Spot Color (CMYK + tint) list($col_c, $col_m, $col_y, $col_k, $col_t) = $chunks; $this->AddSpotColor($color_name, ($col_c * 100), ($col_m * 100), ($col_y * 100), ($col_k * 100)); $color_cmd = sprintf('/CS%d CS %.3F SCN', $this->spot_colors[$color_name]['i'], (1 - $col_t)); $this->_out($color_cmd); } break; } case 'Y': case 'N': case 'V': case 'L': case 'C': { if ($skip) { break; } $line[($len - 1)] = strtolower($cmd); $this->_out($line); break; } case 'b': case 'B': { $this->_out($cmd . '*'); break; } case 'f': case 'F': { if ($u > 0) { $isU = false; $max = min(($i + 5), $cnt); for ($j = ($i + 1); $j < $max; ++$j) { $isU = ($isU OR (($lines[$j] == 'U') OR ($lines[$j] == '*U'))); } if ($isU) { $this->_out('f*'); } } else { $this->_out('f*'); } break; } case '*u': { ++$u; break; } case '*U': { --$u; break; } } } // restore previous graphic state $this->_out($this->epsmarker.'Q'); if (!empty($border)) { $bx = $this->x; $by = $this->y; $this->x = $ximg; if ($this->rtl) { $this->x += $w; } $this->y = $y; $this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true); $this->x = $bx; $this->y = $by; } if ($link) { $this->Link($ximg, $y, $w, $h, $link, 0); } // set pointer to align the next text/objects switch($align) { case 'T':{ $this->y = $y; $this->x = $this->img_rb_x; break; } case 'M':{ $this->y = $y + round($h/2); $this->x = $this->img_rb_x; break; } case 'B':{ $this->y = $this->img_rb_y; $this->x = $this->img_rb_x; break; } case 'N':{ $this->SetY($this->img_rb_y); break; } default:{ break; } } $this->endlinex = $this->img_rb_x; } /** * Set document barcode. * @param $bc (string) barcode * @public */ public function setBarcode($bc='') { $this->barcode = $bc; } /** * Get current barcode. * @return string * @public * @since 4.0.012 (2008-07-24) */ public function getBarcode() { return $this->barcode; } /** * Print a Linear Barcode. * @param $code (string) code to print * @param $type (string) type of barcode (see barcodes.php for supported formats). * @param $x (int) x position in user units (empty string = current x position) * @param $y (int) y position in user units (empty string = current y position) * @param $w (int) width in user units (empty string = remaining page width) * @param $h (int) height in user units (empty string = remaining page height) * @param $xres (float) width of the smallest bar in user units (empty string = default value = 0.4mm) * @param $style (array) array of options:
      *
    • boolean $style['border'] if true prints a border
    • *
    • int $style['padding'] padding to leave around the barcode in user units (set to 'auto' for automatic padding)
    • *
    • int $style['hpadding'] horizontal padding in user units (set to 'auto' for automatic padding)
    • *
    • int $style['vpadding'] vertical padding in user units (set to 'auto' for automatic padding)
    • *
    • array $style['fgcolor'] color array for bars and text
    • *
    • mixed $style['bgcolor'] color array for background (set to false for transparent)
    • *
    • boolean $style['text'] if true prints text below the barcode
    • *
    • string $style['label'] override default label
    • *
    • string $style['font'] font name for text
    • int $style['fontsize'] font size for text
    • *
    • int $style['stretchtext']: 0 = disabled; 1 = horizontal scaling only if necessary; 2 = forced horizontal scaling; 3 = character spacing only if necessary; 4 = forced character spacing.
    • *
    • string $style['position'] horizontal position of the containing barcode cell on the page: L = left margin; C = center; R = right margin.
    • *
    • string $style['align'] horizontal position of the barcode on the containing rectangle: L = left; C = center; R = right.
    • *
    • string $style['stretch'] if true stretch the barcode to best fit the available width, otherwise uses $xres resolution for a single bar.
    • *
    • string $style['fitwidth'] if true reduce the width to fit the barcode width + padding. When this option is enabled the 'stretch' option is automatically disabled.
    • *
    • string $style['cellfitalign'] this option works only when 'fitwidth' is true and 'position' is unset or empty. Set the horizontal position of the containing barcode cell inside the specified rectangle: L = left; C = center; R = right.
    * @param $align (string) Indicates the alignment of the pointer next to barcode insertion relative to barcode height. The value can be:
    • T: top-right for LTR or top-left for RTL
    • M: middle-right for LTR or middle-left for RTL
    • B: bottom-right for LTR or bottom-left for RTL
    • N: next line
    * @author Nicola Asuni * @since 3.1.000 (2008-06-09) * @public */ public function write1DBarcode($code, $type, $x='', $y='', $w='', $h='', $xres='', $style='', $align='') { if ($this->empty_string(trim($code))) { return; } require_once(dirname(__FILE__).'/barcodes.php'); // save current graphic settings $gvars = $this->getGraphicVars(); // create new barcode object $barcodeobj = new TCPDFBarcode($code, $type); $arrcode = $barcodeobj->getBarcodeArray(); if ($arrcode === false) { $this->Error('Error in 1D barcode string'); } // set default values if (!isset($style['position'])) { $style['position'] = ''; } elseif ($style['position'] == 'S') { // keep this for backward compatibility $style['position'] = ''; $style['stretch'] = true; } if (!isset($style['fitwidth'])) { if (!isset($style['stretch'])) { $style['fitwidth'] = true; } else { $style['fitwidth'] = false; } } if ($style['fitwidth']) { // disable stretch $style['stretch'] = false; } if (!isset($style['stretch'])) { if (($w === '') OR ($w <= 0)) { $style['stretch'] = false; } else { $style['stretch'] = true; } } if (!isset($style['fgcolor'])) { $style['fgcolor'] = array(0,0,0); // default black } if (!isset($style['bgcolor'])) { $style['bgcolor'] = false; // default transparent } if (!isset($style['border'])) { $style['border'] = false; } $fontsize = 0; if (!isset($style['text'])) { $style['text'] = false; } if ($style['text'] AND isset($style['font'])) { if (isset($style['fontsize'])) { $fontsize = $style['fontsize']; } $this->SetFont($style['font'], '', $fontsize); } if (!isset($style['stretchtext'])) { $style['stretchtext'] = 4; } if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); if (($w === '') OR ($w <= 0)) { if ($this->rtl) { $w = $x - $this->lMargin; } else { $w = $this->w - $this->rMargin - $x; } } // padding if (!isset($style['padding'])) { $padding = 0; } elseif ($style['padding'] === 'auto') { $padding = 10 * ($w / ($arrcode['maxw'] + 20)); } else { $padding = floatval($style['padding']); } // horizontal padding if (!isset($style['hpadding'])) { $hpadding = $padding; } elseif ($style['hpadding'] === 'auto') { $hpadding = 10 * ($w / ($arrcode['maxw'] + 20)); } else { $hpadding = floatval($style['hpadding']); } // vertical padding if (!isset($style['vpadding'])) { $vpadding = $padding; } elseif ($style['vpadding'] === 'auto') { $vpadding = ($hpadding / 2); } else { $vpadding = floatval($style['vpadding']); } // calculate xres (single bar width) $max_xres = ($w - (2 * $hpadding)) / $arrcode['maxw']; if ($style['stretch']) { $xres = $max_xres; } else { if ($this->empty_string($xres)) { $xres = (0.141 * $this->k); // default bar width = 0.4 mm } if ($xres > $max_xres) { // correct xres to fit on $w $xres = $max_xres; } if ((isset($style['padding']) AND ($style['padding'] === 'auto')) OR (isset($style['hpadding']) AND ($style['hpadding'] === 'auto'))) { $hpadding = 10 * $xres; if (isset($style['vpadding']) AND ($style['vpadding'] === 'auto')) { $vpadding = ($hpadding / 2); } } } if ($style['fitwidth']) { $wold = $w; $w = (($arrcode['maxw'] * $xres) + (2 * $hpadding)); if (isset($style['cellfitalign'])) { switch ($style['cellfitalign']) { case 'L': { if ($this->rtl) { $x -= ($wold - $w); } break; } case 'R': { if (!$this->rtl) { $x += ($wold - $w); } break; } case 'C': { if ($this->rtl) { $x -= (($wold - $w) / 2); } else { $x += (($wold - $w) / 2); } break; } default : { break; } } } } $text_height = ($this->cell_height_ratio * $fontsize / $this->k); // height if (($h === '') OR ($h <= 0)) { // set default height $h = (($arrcode['maxw'] * $xres) / 3) + (2 * $vpadding) + $text_height; } $barh = $h - $text_height - (2 * $vpadding); if ($barh <=0) { // try to reduce font or padding to fit barcode on available height if ($text_height > $h) { $fontsize = (($h * $this->k) / (4 * $this->cell_height_ratio)); $text_height = ($this->cell_height_ratio * $fontsize / $this->k); $this->SetFont($style['font'], '', $fontsize); } if ($vpadding > 0) { $vpadding = (($h - $text_height) / 4); } $barh = $h - $text_height - (2 * $vpadding); } // fit the barcode on available space list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, false); // set alignment $this->img_rb_y = $y + $h; // set alignment if ($this->rtl) { if ($style['position'] == 'L') { $xpos = $this->lMargin; } elseif ($style['position'] == 'C') { $xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($style['position'] == 'R') { $xpos = $this->w - $this->rMargin - $w; } else { $xpos = $x - $w; } $this->img_rb_x = $xpos; } else { if ($style['position'] == 'L') { $xpos = $this->lMargin; } elseif ($style['position'] == 'C') { $xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($style['position'] == 'R') { $xpos = $this->w - $this->rMargin - $w; } else { $xpos = $x; } $this->img_rb_x = $xpos + $w; } $xpos_rect = $xpos; if (!isset($style['align'])) { $style['align'] = 'C'; } switch ($style['align']) { case 'L': { $xpos = $xpos_rect + $hpadding; break; } case 'R': { $xpos = $xpos_rect + ($w - ($arrcode['maxw'] * $xres)) - $hpadding; break; } case 'C': default : { $xpos = $xpos_rect + (($w - ($arrcode['maxw'] * $xres)) / 2); break; } } $xpos_text = $xpos; // barcode is always printed in LTR direction $tempRTL = $this->rtl; $this->rtl = false; // print background color if ($style['bgcolor']) { $this->Rect($xpos_rect, $y, $w, $h, $style['border'] ? 'DF' : 'F', '', $style['bgcolor']); } elseif ($style['border']) { $this->Rect($xpos_rect, $y, $w, $h, 'D'); } // set foreground color $this->SetDrawColorArray($style['fgcolor']); $this->SetTextColorArray($style['fgcolor']); // print bars foreach ($arrcode['bcode'] as $k => $v) { $bw = ($v['w'] * $xres); if ($v['t']) { // draw a vertical bar $ypos = $y + $vpadding + ($v['p'] * $barh / $arrcode['maxh']); $this->Rect($xpos, $ypos, $bw, ($v['h'] * $barh / $arrcode['maxh']), 'F', array(), $style['fgcolor']); } $xpos += $bw; } // print text if ($style['text']) { if (isset($style['label']) AND !$this->empty_string($style['label'])) { $label = $style['label']; } else { $label = $code; } $txtwidth = ($arrcode['maxw'] * $xres); if ($this->GetStringWidth($label) > $txtwidth) { $style['stretchtext'] = 2; } // print text $this->x = $xpos_text; $this->y = $y + $vpadding + $barh; $cellpadding = $this->cell_padding; $this->SetCellPadding(0); $this->Cell($txtwidth, '', $label, 0, 0, 'C', false, '', $style['stretchtext'], false, 'T', 'T'); $this->cell_padding = $cellpadding; } // restore original direction $this->rtl = $tempRTL; // restore previous settings $this->setGraphicVars($gvars); // set pointer to align the next text/objects switch($align) { case 'T':{ $this->y = $y; $this->x = $this->img_rb_x; break; } case 'M':{ $this->y = $y + round($h / 2); $this->x = $this->img_rb_x; break; } case 'B':{ $this->y = $this->img_rb_y; $this->x = $this->img_rb_x; break; } case 'N':{ $this->SetY($this->img_rb_y); break; } default:{ break; } } $this->endlinex = $this->img_rb_x; } /** * This function is DEPRECATED, please use the new write1DBarcode() function. * @param $x (int) x position in user units * @param $y (int) y position in user units * @param $w (int) width in user units * @param $h (int) height position in user units * @param $type (string) type of barcode * @param $style (string) barcode style * @param $font (string) font for text * @param $xres (int) x resolution * @param $code (string) code to print * @deprecated deprecated since version 3.1.000 (2008-06-10) * @public * @see write1DBarcode() */ public function writeBarcode($x, $y, $w, $h, $type, $style, $font, $xres, $code) { // convert old settings for the new write1DBarcode() function. $xres = 1 / $xres; $newstyle = array( 'position' => '', 'align' => '', 'stretch' => false, 'fitwidth' => false, 'cellfitalign' => '', 'border' => false, 'padding' => 0, 'fgcolor' => array(0,0,0), 'bgcolor' => false, 'text' => true, 'font' => $font, 'fontsize' => 8, 'stretchtext' => 4 ); if ($style & 1) { $newstyle['border'] = true; } if ($style & 2) { $newstyle['bgcolor'] = false; } if ($style & 4) { $newstyle['position'] = 'C'; } elseif ($style & 8) { $newstyle['position'] = 'L'; } elseif ($style & 16) { $newstyle['position'] = 'R'; } if ($style & 128) { $newstyle['text'] = true; } if ($style & 256) { $newstyle['stretchtext'] = 4; } $this->write1DBarcode($code, $type, $x, $y, $w, $h, $xres, $newstyle, ''); } /** * Print 2D Barcode. * @param $code (string) code to print * @param $type (string) type of barcode (see 2dbarcodes.php for supported formats). * @param $x (int) x position in user units * @param $y (int) y position in user units * @param $w (int) width in user units * @param $h (int) height in user units * @param $style (array) array of options:
      *
    • boolean $style['border'] if true prints a border around the barcode
    • *
    • int $style['padding'] padding to leave around the barcode in barcode units (set to 'auto' for automatic padding)
    • *
    • int $style['hpadding'] horizontal padding in barcode units (set to 'auto' for automatic padding)
    • *
    • int $style['vpadding'] vertical padding in barcode units (set to 'auto' for automatic padding)
    • *
    • int $style['module_width'] width of a single module in points
    • *
    • int $style['module_height'] height of a single module in points
    • *
    • array $style['fgcolor'] color array for bars and text
    • *
    • mixed $style['bgcolor'] color array for background or false for transparent
    • *
    • string $style['position'] barcode position on the page: L = left margin; C = center; R = right margin; S = stretch
    • $style['module_width'] width of a single module in points
    • *
    • $style['module_height'] height of a single module in points
    * @param $align (string) Indicates the alignment of the pointer next to barcode insertion relative to barcode height. The value can be:
    • T: top-right for LTR or top-left for RTL
    • M: middle-right for LTR or middle-left for RTL
    • B: bottom-right for LTR or bottom-left for RTL
    • N: next line
    * @param $distort (boolean) if true distort the barcode to fit width and height, otherwise preserve aspect ratio * @author Nicola Asuni * @since 4.5.037 (2009-04-07) * @public */ public function write2DBarcode($code, $type, $x='', $y='', $w='', $h='', $style='', $align='', $distort=false) { if ($this->empty_string(trim($code))) { return; } require_once(dirname(__FILE__).'/2dbarcodes.php'); // save current graphic settings $gvars = $this->getGraphicVars(); // create new barcode object $barcodeobj = new TCPDF2DBarcode($code, $type); $arrcode = $barcodeobj->getBarcodeArray(); if (($arrcode === false) OR empty($arrcode)) { $this->Error('Error in 2D barcode string'); } // set default values if (!isset($style['position'])) { $style['position'] = ''; } if (!isset($style['fgcolor'])) { $style['fgcolor'] = array(0,0,0); // default black } if (!isset($style['bgcolor'])) { $style['bgcolor'] = false; // default transparent } if (!isset($style['border'])) { $style['border'] = false; } // padding if (!isset($style['padding'])) { $style['padding'] = 0; } elseif ($style['padding'] === 'auto') { $style['padding'] = 4; } if (!isset($style['hpadding'])) { $style['hpadding'] = $style['padding']; } elseif ($style['hpadding'] === 'auto') { $style['hpadding'] = 4; } if (!isset($style['vpadding'])) { $style['vpadding'] = $style['padding']; } elseif ($style['vpadding'] === 'auto') { $style['vpadding'] = 4; } $hpad = (2 * $style['hpadding']); $vpad = (2 * $style['vpadding']); // cell (module) dimension if (!isset($style['module_width'])) { $style['module_width'] = 1; // width of a single module in points } if (!isset($style['module_height'])) { $style['module_height'] = 1; // height of a single module in points } if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); // number of barcode columns and rows $rows = $arrcode['num_rows']; $cols = $arrcode['num_cols']; // module width and height $mw = $style['module_width']; $mh = $style['module_height']; // get max dimensions if ($this->rtl) { $maxw = $x - $this->lMargin; } else { $maxw = $this->w - $this->rMargin - $x; } $maxh = ($this->h - $this->tMargin - $this->bMargin); $ratioHW = ((($rows * $mh) + $hpad) / (($cols * $mw) + $vpad)); $ratioWH = ((($cols * $mw) + $vpad) / (($rows * $mh) + $hpad)); if (!$distort) { if (($maxw * $ratioHW) > $maxh) { $maxw = $maxh * $ratioWH; } if (($maxh * $ratioWH) > $maxw) { $maxh = $maxw * $ratioHW; } } // set maximum dimesions if ($w > $maxw) { $w = $maxw; } if ($h > $maxh) { $h = $maxh; } // set dimensions if ((($w === '') OR ($w <= 0)) AND (($h === '') OR ($h <= 0))) { $w = ($cols + $hpad) * ($mw / $this->k); $h = ($rows + $vpad) * ($mh / $this->k); } elseif (($w === '') OR ($w <= 0)) { $w = $h * $ratioWH; } elseif (($h === '') OR ($h <= 0)) { $h = $w * $ratioHW; } // barcode size (excluding padding) $bw = ($w * $cols) / ($cols + $hpad); $bh = ($h * $rows) / ($rows + $vpad); // dimension of single barcode cell unit $cw = $bw / $cols; $ch = $bh / $rows; if (!$distort) { if (($cw / $ch) > ($mw / $mh)) { // correct horizontal distortion $cw = $ch * $mw / $mh; $bw = $cw * $cols; $style['hpadding'] = ($w - $bw) / (2 * $cw); } else { // correct vertical distortion $ch = $cw * $mh / $mw; $bh = $ch * $rows; $style['vpadding'] = ($h - $bh) / (2 * $ch); } } // fit the barcode on available space list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, false); // set alignment $this->img_rb_y = $y + $h; // set alignment if ($this->rtl) { if ($style['position'] == 'L') { $xpos = $this->lMargin; } elseif ($style['position'] == 'C') { $xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($style['position'] == 'R') { $xpos = $this->w - $this->rMargin - $w; } else { $xpos = $x - $w; } $this->img_rb_x = $xpos; } else { if ($style['position'] == 'L') { $xpos = $this->lMargin; } elseif ($style['position'] == 'C') { $xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($style['position'] == 'R') { $xpos = $this->w - $this->rMargin - $w; } else { $xpos = $x; } $this->img_rb_x = $xpos + $w; } $xstart = $xpos + ($style['hpadding'] * $cw); $ystart = $y + ($style['vpadding'] * $ch); // barcode is always printed in LTR direction $tempRTL = $this->rtl; $this->rtl = false; // print background color if ($style['bgcolor']) { $this->Rect($xpos, $y, $w, $h, $style['border'] ? 'DF' : 'F', '', $style['bgcolor']); } elseif ($style['border']) { $this->Rect($xpos, $y, $w, $h, 'D'); } // set foreground color $this->SetDrawColorArray($style['fgcolor']); // print barcode cells // for each row for ($r = 0; $r < $rows; ++$r) { $xr = $xstart; // for each column for ($c = 0; $c < $cols; ++$c) { if ($arrcode['bcode'][$r][$c] == 1) { // draw a single barcode cell $this->Rect($xr, $ystart, $cw, $ch, 'F', array(), $style['fgcolor']); } $xr += $cw; } $ystart += $ch; } // restore original direction $this->rtl = $tempRTL; // restore previous settings $this->setGraphicVars($gvars); // set pointer to align the next text/objects switch($align) { case 'T':{ $this->y = $y; $this->x = $this->img_rb_x; break; } case 'M':{ $this->y = $y + round($h/2); $this->x = $this->img_rb_x; break; } case 'B':{ $this->y = $this->img_rb_y; $this->x = $this->img_rb_x; break; } case 'N':{ $this->SetY($this->img_rb_y); break; } default:{ break; } } $this->endlinex = $this->img_rb_x; } /** * Returns an array containing current margins: *
    • $ret['left'] = left margin
    • $ret['right'] = right margin
    • $ret['top'] = top margin
    • $ret['bottom'] = bottom margin
    • $ret['header'] = header margin
    • $ret['footer'] = footer margin
    • $ret['cell'] = cell padding array
    • $ret['padding_left'] = cell left padding
    • $ret['padding_top'] = cell top padding
    • $ret['padding_right'] = cell right padding
    • $ret['padding_bottom'] = cell bottom padding
    • *
    * @return array containing all margins measures * @public * @since 3.2.000 (2008-06-23) */ public function getMargins() { $ret = array( 'left' => $this->lMargin, 'right' => $this->rMargin, 'top' => $this->tMargin, 'bottom' => $this->bMargin, 'header' => $this->header_margin, 'footer' => $this->footer_margin, 'cell' => $this->cell_padding, 'padding_left' => $this->cell_padding['L'], 'padding_top' => $this->cell_padding['T'], 'padding_right' => $this->cell_padding['R'], 'padding_bottom' => $this->cell_padding['B'] ); return $ret; } /** * Returns an array containing original margins: *
    • $ret['left'] = left margin
    • $ret['right'] = right margin
    • *
    * @return array containing all margins measures * @public * @since 4.0.012 (2008-07-24) */ public function getOriginalMargins() { $ret = array( 'left' => $this->original_lMargin, 'right' => $this->original_rMargin ); return $ret; } /** * Returns the current font size. * @return current font size * @public * @since 3.2.000 (2008-06-23) */ public function getFontSize() { return $this->FontSize; } /** * Returns the current font size in points unit. * @return current font size in points unit * @public * @since 3.2.000 (2008-06-23) */ public function getFontSizePt() { return $this->FontSizePt; } /** * Returns the current font family name. * @return string current font family name * @public * @since 4.3.008 (2008-12-05) */ public function getFontFamily() { return $this->FontFamily; } /** * Returns the current font style. * @return string current font style * @public * @since 4.3.008 (2008-12-05) */ public function getFontStyle() { return $this->FontStyle; } /** * Cleanup HTML code (requires HTML Tidy library). * @param $html (string) htmlcode to fix * @param $default_css (string) CSS commands to add * @param $tagvs (array) parameters for setHtmlVSpace method * @param $tidy_options (array) options for tidy_parse_string function * @return string XHTML code cleaned up * @author Nicola Asuni * @public * @since 5.9.017 (2010-11-16) * @see setHtmlVSpace() */ public function fixHTMLCode($html, $default_css='', $tagvs='', $tidy_options='') { // configure parameters for HTML Tidy if ($tidy_options === '') { $tidy_options = array ( 'clean' => 1, 'drop-empty-paras' => 0, 'drop-proprietary-attributes' => 1, 'fix-backslash' => 1, 'hide-comments' => 1, 'join-styles' => 1, 'lower-literals' => 1, 'merge-divs' => 1, 'merge-spans' => 1, 'output-xhtml' => 1, 'word-2000' => 1, 'wrap' => 0, 'output-bom' => 0, //'char-encoding' => 'utf8', //'input-encoding' => 'utf8', //'output-encoding' => 'utf8' ); } // clean up the HTML code $tidy = tidy_parse_string($html, $tidy_options); // fix the HTML $tidy->cleanRepair(); // get the CSS part $tidy_head = tidy_get_head($tidy); $css = $tidy_head->value; $css = preg_replace('/]+)>/ims', ''; // get the body part $tidy_body = tidy_get_body($tidy); $html = $tidy_body->value; // fix some self-closing tags $html = str_replace('
    ', '
    ', $html); // remove some empty tag blocks $html = preg_replace('/]*)><\/div>/', '', $html); $html = preg_replace('/]*)><\/p>/', '', $html); if ($tagvs !== '') { // set vertical space for some XHTML tags $this->setHtmlVSpace($tagvs); } // return the cleaned XHTML code + CSS return $css.$html; } /** * Extracts the CSS properties from a CSS string. * @param $cssdata (string) string containing CSS definitions. * @return An array where the keys are the CSS selectors and the values are the CSS properties. * @author Nicola Asuni * @since 5.1.000 (2010-05-25) * @protected */ protected function extractCSSproperties($cssdata) { if (empty($cssdata)) { return array(); } // remove comments $cssdata = preg_replace('/\/\*[^\*]*\*\//', '', $cssdata); // remove newlines and multiple spaces $cssdata = preg_replace('/[\s]+/', ' ', $cssdata); // remove some spaces $cssdata = preg_replace('/[\s]*([;:\{\}]{1})[\s]*/', '\\1', $cssdata); // remove empty blocks $cssdata = preg_replace('/([^\}\{]+)\{\}/', '', $cssdata); // replace media type parenthesis $cssdata = preg_replace('/@media[\s]+([^\{]*)\{/i', '@media \\1?', $cssdata); $cssdata = preg_replace('/\}\}/si', '}?', $cssdata); // trim string $cssdata = trim($cssdata); // find media blocks (all, braille, embossed, handheld, print, projection, screen, speech, tty, tv) $cssblocks = array(); $matches = array(); if (preg_match_all('/@media[\s]+([^\?]*)?([^?]*)?/i', $cssdata, $matches) > 0) { foreach ($matches[1] as $key => $type) { $cssblocks[$type] = $matches[2][$key]; } // remove media blocks $cssdata = preg_replace('/@media[\s]+([^\?]*)?([^?]*)?/i', '', $cssdata); } // keep 'all' and 'print' media, other media types are discarded if (isset($cssblocks['all']) AND !empty($cssblocks['all'])) { $cssdata .= $cssblocks['all']; } if (isset($cssblocks['print']) AND !empty($cssblocks['print'])) { $cssdata .= $cssblocks['print']; } // reset css blocks array $cssblocks = array(); $matches = array(); // explode css data string into array if (substr($cssdata, -1) == '}') { // remove last parethesis $cssdata = substr($cssdata, 0, -1); } $matches = explode('}', $cssdata); foreach ($matches as $key => $block) { // index 0 contains the CSS selector, index 1 contains CSS properties $cssblocks[$key] = explode('{', $block); if (!isset($cssblocks[$key][1])) { // remove empty definitions unset($cssblocks[$key]); } } // split groups of selectors (comma-separated list of selectors) foreach ($cssblocks as $key => $block) { if (strpos($block[0], ',') > 0) { $selectors = explode(',', $block[0]); foreach ($selectors as $sel) { $cssblocks[] = array(0 => trim($sel), 1 => $block[1]); } unset($cssblocks[$key]); } } // covert array to selector => properties $cssdata = array(); foreach ($cssblocks as $block) { $selector = $block[0]; // calculate selector's specificity $matches = array(); $a = 0; // the declaration is not from is a 'style' attribute $b = intval(preg_match_all('/[\#]/', $selector, $matches)); // number of ID attributes $c = intval(preg_match_all('/[\[\.]/', $selector, $matches)); // number of other attributes $c += intval(preg_match_all('/[\:]link|visited|hover|active|focus|target|lang|enabled|disabled|checked|indeterminate|root|nth|first|last|only|empty|contains|not/i', $selector, $matches)); // number of pseudo-classes $d = intval(preg_match_all('/[\>\+\~\s]{1}[a-zA-Z0-9]+/', ' '.$selector, $matches)); // number of element names $d += intval(preg_match_all('/[\:][\:]/', $selector, $matches)); // number of pseudo-elements $specificity = $a.$b.$c.$d; // add specificity to the beginning of the selector $cssdata[$specificity.' '.$selector] = $block[1]; } // sort selectors alphabetically to account for specificity ksort($cssdata, SORT_STRING); // return array return $cssdata; } /** * Returns true if the CSS selector is valid for the selected HTML tag * @param $dom (array) array of HTML tags and properties * @param $key (int) key of the current HTML tag * @param $selector (string) CSS selector string * @return true if the selector is valid, false otherwise * @protected * @since 5.1.000 (2010-05-25) */ protected function isValidCSSSelectorForTag($dom, $key, $selector) { $valid = false; // value to be returned $tag = $dom[$key]['value']; $class = array(); if (isset($dom[$key]['attribute']['class']) AND !empty($dom[$key]['attribute']['class'])) { $class = explode(' ', strtolower($dom[$key]['attribute']['class'])); } $id = ''; if (isset($dom[$key]['attribute']['id']) AND !empty($dom[$key]['attribute']['id'])) { $id = strtolower($dom[$key]['attribute']['id']); } $selector = preg_replace('/([\>\+\~\s]{1})([\.]{1})([^\>\+\~\s]*)/si', '\\1*.\\3', $selector); $matches = array(); if (preg_match_all('/([\>\+\~\s]{1})([a-zA-Z0-9\*]+)([^\>\+\~\s]*)/si', $selector, $matches, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE) > 0) { $parentop = array_pop($matches[1]); $operator = $parentop[0]; $offset = $parentop[1]; $lasttag = array_pop($matches[2]); $lasttag = strtolower(trim($lasttag[0])); if (($lasttag == '*') OR ($lasttag == $tag)) { // the last element on selector is our tag or 'any tag' $attrib = array_pop($matches[3]); $attrib = strtolower(trim($attrib[0])); if (!empty($attrib)) { // check if matches class, id, attribute, pseudo-class or pseudo-element switch ($attrib{0}) { case '.': { // class if (in_array(substr($attrib, 1), $class)) { $valid = true; } break; } case '#': { // ID if (substr($attrib, 1) == $id) { $valid = true; } break; } case '[': { // attribute $attrmatch = array(); if (preg_match('/\[([a-zA-Z0-9]*)[\s]*([\~\^\$\*\|\=]*)[\s]*["]?([^"\]]*)["]?\]/i', $attrib, $attrmatch) > 0) { $att = strtolower($attrmatch[1]); $val = $attrmatch[3]; if (isset($dom[$key]['attribute'][$att])) { switch ($attrmatch[2]) { case '=': { if ($dom[$key]['attribute'][$att] == $val) { $valid = true; } break; } case '~=': { if (in_array($val, explode(' ', $dom[$key]['attribute'][$att]))) { $valid = true; } break; } case '^=': { if ($val == substr($dom[$key]['attribute'][$att], 0, strlen($val))) { $valid = true; } break; } case '$=': { if ($val == substr($dom[$key]['attribute'][$att], -strlen($val))) { $valid = true; } break; } case '*=': { if (strpos($dom[$key]['attribute'][$att], $val) !== false) { $valid = true; } break; } case '|=': { if ($dom[$key]['attribute'][$att] == $val) { $valid = true; } elseif (preg_match('/'.$val.'[\-]{1}/i', $dom[$key]['attribute'][$att]) > 0) { $valid = true; } break; } default: { $valid = true; } } } } break; } case ':': { // pseudo-class or pseudo-element if ($attrib{1} == ':') { // pseudo-element // pseudo-elements are not supported! // (::first-line, ::first-letter, ::before, ::after) } else { // pseudo-class // pseudo-classes are not supported! // (:root, :nth-child(n), :nth-last-child(n), :nth-of-type(n), :nth-last-of-type(n), :first-child, :last-child, :first-of-type, :last-of-type, :only-child, :only-of-type, :empty, :link, :visited, :active, :hover, :focus, :target, :lang(fr), :enabled, :disabled, :checked) } break; } } // end of switch } else { $valid = true; } if ($valid AND ($offset > 0)) { $valid = false; // check remaining selector part $selector = substr($selector, 0, $offset); switch ($operator) { case ' ': { // descendant of an element while ($dom[$key]['parent'] > 0) { if ($this->isValidCSSSelectorForTag($dom, $dom[$key]['parent'], $selector)) { $valid = true; break; } else { $key = $dom[$key]['parent']; } } break; } case '>': { // child of an element $valid = $this->isValidCSSSelectorForTag($dom, $dom[$key]['parent'], $selector); break; } case '+': { // immediately preceded by an element for ($i = ($key - 1); $i > $dom[$key]['parent']; --$i) { if ($dom[$i]['tag'] AND $dom[$i]['opening']) { $valid = $this->isValidCSSSelectorForTag($dom, $i, $selector); break; } } break; } case '~': { // preceded by an element for ($i = ($key - 1); $i > $dom[$key]['parent']; --$i) { if ($dom[$i]['tag'] AND $dom[$i]['opening']) { if ($this->isValidCSSSelectorForTag($dom, $i, $selector)) { break; } } } break; } } } } } return $valid; } /** * Returns the styles array that apply for the selected HTML tag. * @param $dom (array) array of HTML tags and properties * @param $key (int) key of the current HTML tag * @param $css (array) array of CSS properties * @return array containing CSS properties * @protected * @since 5.1.000 (2010-05-25) */ protected function getCSSdataArray($dom, $key, $css) { $cssarray = array(); // style to be returned // get parent CSS selectors $selectors = array(); if (isset($dom[($dom[$key]['parent'])]['csssel'])) { $selectors = $dom[($dom[$key]['parent'])]['csssel']; } // get all styles that apply foreach($css as $selector => $style) { $pos = strpos($selector, ' '); // get specificity $specificity = substr($selector, 0, $pos); // remove specificity $selector = substr($selector, $pos); // check if this selector apply to current tag if ($this->isValidCSSSelectorForTag($dom, $key, $selector)) { if (!in_array($selector, $selectors)) { // add style if not already added on parent selector $cssarray[] = array('k' => $selector, 's' => $specificity, 'c' => $style); $selectors[] = $selector; } } } if (isset($dom[$key]['attribute']['style'])) { // attach inline style (latest properties have high priority) $cssarray[] = array('k' => '', 's' => '1000', 'c' => $dom[$key]['attribute']['style']); } // order the css array to account for specificity $cssordered = array(); foreach ($cssarray as $key => $val) { $skey = sprintf('%04d', $key); $cssordered[$val['s'].'_'.$skey] = $val; } // sort selectors alphabetically to account for specificity ksort($cssordered, SORT_STRING); return array($selectors, $cssordered); } /** * Compact CSS data array into single string. * @param $css (array) array of CSS properties * @return string containing merged CSS properties * @protected * @since 5.9.070 (2011-04-19) */ protected function getTagStyleFromCSSarray($css) { $tagstyle = ''; // value to be returned foreach ($css as $style) { // split single css commands $csscmds = explode(';', $style['c']); foreach ($csscmds as $cmd) { if (!empty($cmd)) { $pos = strpos($cmd, ':'); if ($pos !== false) { $cmd = substr($cmd, 0, ($pos + 1)); if (strpos($tagstyle, $cmd) !== false) { // remove duplicate commands (last commands have high priority) $tagstyle = preg_replace('/'.$cmd.'[^;]+/i', '', $tagstyle); } } } } $tagstyle .= ';'.$style['c']; } // remove multiple semicolons $tagstyle = preg_replace('/[;]+/', ';', $tagstyle); return $tagstyle; } /** * Returns the border width from CSS property * @param $width (string) border width * @return int with in user units * @protected * @since 5.7.000 (2010-08-02) */ protected function getCSSBorderWidth($width) { if ($width == 'thin') { $width = (2 / $this->k); } elseif ($width == 'medium') { $width = (4 / $this->k); } elseif ($width == 'thick') { $width = (6 / $this->k); } else { $width = $this->getHTMLUnitToUnits($width, 1, 'px', false); } return $width; } /** * Returns the border dash style from CSS property * @param $style (string) border style to convert * @return int sash style (return -1 in case of none or hidden border) * @protected * @since 5.7.000 (2010-08-02) */ protected function getCSSBorderDashStyle($style) { switch (strtolower($style)) { case 'none': case 'hidden': { $dash = -1; break; } case 'dotted': { $dash = 1; break; } case 'dashed': { $dash = 3; break; } case 'double': case 'groove': case 'ridge': case 'inset': case 'outset': case 'solid': default: { $dash = 0; break; } } return $dash; } /** * Returns the border style array from CSS border properties * @param $cssborder (string) border properties * @return array containing border properties * @protected * @since 5.7.000 (2010-08-02) */ protected function getCSSBorderStyle($cssborder) { $bprop = preg_split('/[\s]+/', trim($cssborder)); $border = array(); // value to be returned switch (count($bprop)) { case 3: { $width = $bprop[0]; $style = $bprop[1]; $color = $bprop[2]; break; } case 2: { $width = 'medium'; $style = $bprop[0]; $color = $bprop[1]; break; } case 1: { $width = 'medium'; $style = $bprop[0]; $color = 'black'; break; } default: { $width = 'medium'; $style = 'solid'; $color = 'black'; break; } } if ($style == 'none') { return array(); } $border['cap'] = 'square'; $border['join'] = 'miter'; $border['dash'] = $this->getCSSBorderDashStyle($style); if ($border['dash'] < 0) { return array(); } $border['width'] = $this->getCSSBorderWidth($width); $border['color'] = $this->convertHTMLColorToDec($color); return $border; } /** * Get the internal Cell padding from CSS attribute. * @param $csspadding (string) padding properties * @param $width (float) width of the containing element * @return array of cell paddings * @public * @since 5.9.000 (2010-10-04) */ public function getCSSPadding($csspadding, $width=0) { $padding = preg_split('/[\s]+/', trim($csspadding)); $cell_padding = array(); // value to be returned switch (count($padding)) { case 4: { $cell_padding['T'] = $padding[0]; $cell_padding['R'] = $padding[1]; $cell_padding['B'] = $padding[2]; $cell_padding['L'] = $padding[3]; break; } case 3: { $cell_padding['T'] = $padding[0]; $cell_padding['R'] = $padding[1]; $cell_padding['B'] = $padding[2]; $cell_padding['L'] = $padding[1]; break; } case 2: { $cell_padding['T'] = $padding[0]; $cell_padding['R'] = $padding[1]; $cell_padding['B'] = $padding[0]; $cell_padding['L'] = $padding[1]; break; } case 1: { $cell_padding['T'] = $padding[0]; $cell_padding['R'] = $padding[0]; $cell_padding['B'] = $padding[0]; $cell_padding['L'] = $padding[0]; break; } default: { return $this->cell_padding; } } if ($width == 0) { $width = $this->w - $this->lMargin - $this->rMargin; } $cell_padding['T'] = $this->getHTMLUnitToUnits($cell_padding['T'], $width, 'px', false); $cell_padding['R'] = $this->getHTMLUnitToUnits($cell_padding['R'], $width, 'px', false); $cell_padding['B'] = $this->getHTMLUnitToUnits($cell_padding['B'], $width, 'px', false); $cell_padding['L'] = $this->getHTMLUnitToUnits($cell_padding['L'], $width, 'px', false); return $cell_padding; } /** * Get the internal Cell margin from CSS attribute. * @param $cssmargin (string) margin properties * @param $width (float) width of the containing element * @return array of cell margins * @public * @since 5.9.000 (2010-10-04) */ public function getCSSMargin($cssmargin, $width=0) { $margin = preg_split('/[\s]+/', trim($cssmargin)); $cell_margin = array(); // value to be returned switch (count($margin)) { case 4: { $cell_margin['T'] = $margin[0]; $cell_margin['R'] = $margin[1]; $cell_margin['B'] = $margin[2]; $cell_margin['L'] = $margin[3]; break; } case 3: { $cell_margin['T'] = $margin[0]; $cell_margin['R'] = $margin[1]; $cell_margin['B'] = $margin[2]; $cell_margin['L'] = $margin[1]; break; } case 2: { $cell_margin['T'] = $margin[0]; $cell_margin['R'] = $margin[1]; $cell_margin['B'] = $margin[0]; $cell_margin['L'] = $margin[1]; break; } case 1: { $cell_margin['T'] = $margin[0]; $cell_margin['R'] = $margin[0]; $cell_margin['B'] = $margin[0]; $cell_margin['L'] = $margin[0]; break; } default: { return $this->cell_margin; } } if ($width == 0) { $width = $this->w - $this->lMargin - $this->rMargin; } $cell_margin['T'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['T']), $width, 'px', false); $cell_margin['R'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['R']), $width, 'px', false); $cell_margin['B'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['B']), $width, 'px', false); $cell_margin['L'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['L']), $width, 'px', false); return $cell_margin; } /** * Get the border-spacing from CSS attribute. * @param $cssbspace (string) border-spacing CSS properties * @param $width (float) width of the containing element * @return array of border spacings * @public * @since 5.9.010 (2010-10-27) */ public function getCSSBorderMargin($cssbspace, $width=0) { $space = preg_split('/[\s]+/', trim($cssbspace)); $border_spacing = array(); // value to be returned switch (count($space)) { case 2: { $border_spacing['H'] = $space[0]; $border_spacing['V'] = $space[1]; break; } case 1: { $border_spacing['H'] = $space[0]; $border_spacing['V'] = $space[0]; break; } default: { return array('H' => 0, 'V' => 0); } } if ($width == 0) { $width = $this->w - $this->lMargin - $this->rMargin; } $border_spacing['H'] = $this->getHTMLUnitToUnits($border_spacing['H'], $width, 'px', false); $border_spacing['V'] = $this->getHTMLUnitToUnits($border_spacing['V'], $width, 'px', false); return $border_spacing; } /** * Returns the letter-spacing value from CSS value * @param $spacing (string) letter-spacing value * @param $parent (float) font spacing (tracking/kerning) value of the parent element * @return float quantity to increases or decreases the space between characters in a text. * @protected * @since 5.9.000 (2010-10-02) */ protected function getCSSFontSpacing($spacing, $parent=0) { $val = 0; // value to be returned $spacing = trim($spacing); switch ($spacing) { case 'normal': { $val = 0; break; } case 'inherit': { if ($parent == 'normal') { $val = 0; } else { $val = $parent; } break; } default: { $val = $this->getHTMLUnitToUnits($spacing, 0, 'px', false); } } return $val; } /** * Returns the percentage of font stretching from CSS value * @param $stretch (string) stretch mode * @param $parent (float) stretch value of the parent element * @return float font stretching percentage * @protected * @since 5.9.000 (2010-10-02) */ protected function getCSSFontStretching($stretch, $parent=100) { $val = 100; // value to be returned $stretch = trim($stretch); switch ($stretch) { case 'ultra-condensed': { $val = 40; break; } case 'extra-condensed': { $val = 55; break; } case 'condensed': { $val = 70; break; } case 'semi-condensed': { $val = 85; break; } case 'normal': { $val = 100; break; } case 'semi-expanded': { $val = 115; break; } case 'expanded': { $val = 130; break; } case 'extra-expanded': { $val = 145; break; } case 'ultra-expanded': { $val = 160; break; } case 'wider': { $val = $parent + 10; break; } case 'narrower': { $val = $parent - 10; break; } case 'inherit': { if ($parent == 'normal') { $val = 100; } else { $val = $parent; } break; } default: { $val = $this->getHTMLUnitToUnits($stretch, 100, '%', false); } } return $val; } /** * Returns the HTML DOM array. * @param $html (string) html code * @return array * @protected * @since 3.2.000 (2008-06-20) */ protected function getHtmlDomArray($html) { // array of CSS styles ( selector => properties). $css = array(); // get CSS array defined at previous call $matches = array(); if (preg_match_all('/([^\<]*)<\/cssarray>/isU', $html, $matches) > 0) { if (isset($matches[1][0])) { $css = array_merge($css, unserialize($this->unhtmlentities($matches[1][0]))); } $html = preg_replace('/(.*?)<\/cssarray>/isU', '', $html); } // extract external CSS files $matches = array(); if (preg_match_all('/]*)>/isU', $html, $matches) > 0) { foreach ($matches[1] as $key => $link) { $type = array(); if (preg_match('/type[\s]*=[\s]*"text\/css"/', $link, $type)) { $type = array(); preg_match('/media[\s]*=[\s]*"([^"]*)"/', $link, $type); // get 'all' and 'print' media, other media types are discarded // (all, braille, embossed, handheld, print, projection, screen, speech, tty, tv) if (empty($type) OR (isset($type[1]) AND (($type[1] == 'all') OR ($type[1] == 'print')))) { $type = array(); if (preg_match('/href[\s]*=[\s]*"([^"]*)"/', $link, $type) > 0) { // read CSS data file $cssdata = file_get_contents(trim($type[1])); $css = array_merge($css, $this->extractCSSproperties($cssdata)); } } } } } // extract style tags $matches = array(); if (preg_match_all('/]*)>([^\<]*)<\/style>/isU', $html, $matches) > 0) { foreach ($matches[1] as $key => $media) { $type = array(); preg_match('/media[\s]*=[\s]*"([^"]*)"/', $media, $type); // get 'all' and 'print' media, other media types are discarded // (all, braille, embossed, handheld, print, projection, screen, speech, tty, tv) if (empty($type) OR (isset($type[1]) AND (($type[1] == 'all') OR ($type[1] == 'print')))) { $cssdata = $matches[2][$key]; $css = array_merge($css, $this->extractCSSproperties($cssdata)); } } } // create a special tag to contain the CSS array (used for table content) $csstagarray = ''.htmlentities(serialize($css)).''; // remove head and style blocks $html = preg_replace('/]*)>(.*?)<\/head>/siU', '', $html); $html = preg_replace('/]*)>([^\<]*)<\/style>/isU', '', $html); // define block tags $blocktags = array('blockquote','br','dd','dl','div','dt','h1','h2','h3','h4','h5','h6','hr','li','ol','p','pre','ul','tcpdf','table','tr','td'); // define self-closing tags $selfclosingtags = array('area','base','basefont','br','hr','input','img','link','meta'); // remove all unsupported tags (the line below lists all supported tags) $html = strip_tags($html, '




    1. ', $offset)) !== false) {
      			$html_a = substr($html, 0, $offset);
      			$html_b = substr($html, $offset, ($pos - $offset + 11));
      			while (preg_match("']*)>(.*?)\n(.*?)'si", $html_b)) {
      				// preserve newlines on 'si", "\\2\\3", $html_b);
      				$html_b = preg_replace("']*)>(.*?)[\"](.*?)'si", "\\2''\\3", $html_b);
      			}
      			$html = $html_a.$html_b.substr($html, $pos + 11);
      			$offset = strlen($html_a.$html_b);
      		}
      		$html = preg_replace('/([\s]*)', $html);
      		$offset = 0;
      		while (($offset < strlen($html)) AND ($pos = strpos($html, '', $offset)) !== false) {
      			$html_a = substr($html, 0, $offset);
      			$html_b = substr($html, $offset, ($pos - $offset + 9));
      			while (preg_match("']*)>(.*?)'si", $html_b)) {
      				$html_b = preg_replace("']*)>(.*?)'si", "\\2#!TaB!#\\4#!NwL!#", $html_b);
      				$html_b = preg_replace("']*)>(.*?)'si", "\\2#!NwL!#", $html_b);
      			}
      			$html = $html_a.$html_b.substr($html, $pos + 9);
      			$offset = strlen($html_a.$html_b);
      		}
      		if (preg_match("']*)>'si", "'si", "\" />", $html);
      		}
      		$html = str_replace("\n", ' ', $html);
      		// restore textarea newlines
      		$html = str_replace('', "\n", $html);
      		// remove extra spaces from code
      		$html = preg_replace('/[\s]+<\/(table|tr|ul|ol|dl)>/', '', $html);
      		$html = preg_replace('/'.$this->re_space['p'].'+<\/(td|th|li|dt|dd)>/'.$this->re_space['m'], '', $html);
      		$html = preg_replace('/[\s]+<(tr|td|th|li|dt|dd)/', '<\\1', $html);
      		$html = preg_replace('/'.$this->re_space['p'].'+<(ul|ol|dl|br)/'.$this->re_space['m'], '<\\1', $html);
      		$html = preg_replace('/<\/(table|tr|td|th|blockquote|dd|dt|dl|div|dt|h1|h2|h3|h4|h5|h6|hr|li|ol|ul|p)>[\s]+<', $html);
      		$html = preg_replace('/<\/(td|th)>/', '', $html);
      		$html = preg_replace('/<\/table>([\s]*)/', '', $html);
      		$html = preg_replace('/'.$this->re_space['p'].'+re_space['m'], chr(32).']*)>[\s]+([^\<])/xi', ' \\2', $html);
      		$html = preg_replace('/]*)>/xi', '', $html);
      		$html = preg_replace('/]*)>([^\<]*)<\/textarea>/xi', '', $html);
      		$html = preg_replace('/]*)><\/li>/', ' ', $html);
      		$html = preg_replace('/]*)>'.$this->re_space['p'].'*re_space['m'], ' \/]*)>[\s]/', '<\\1> ', $html); // preserve some spaces
      		$html = preg_replace('/[\s]<\/([^\>]*)>/', ' ', $html); // preserve some spaces
      		$html = preg_replace('/'.$this->re_space['p'].'+/'.$this->re_space['m'], chr(32), $html); // replace multiple spaces with a single space
      		// trim string
      		$html = $this->stringTrim($html);
      		// fix first image tag alignment
      		$html = preg_replace('/^
      FontFamily; $dom[$key]['fontstyle'] = $this->FontStyle; $dom[$key]['fontsize'] = $this->FontSizePt; $dom[$key]['font-stretch'] = $this->font_stretching; $dom[$key]['letter-spacing'] = $this->font_spacing; $dom[$key]['stroke'] = $this->textstrokewidth; $dom[$key]['fill'] = (($this->textrendermode % 2) == 0); $dom[$key]['clip'] = ($this->textrendermode > 3); $dom[$key]['line-height'] = $this->cell_height_ratio; $dom[$key]['bgcolor'] = false; $dom[$key]['fgcolor'] = $this->fgcolor; // color $dom[$key]['strokecolor'] = $this->strokecolor; $dom[$key]['align'] = ''; $dom[$key]['listtype'] = ''; $dom[$key]['text-indent'] = 0; $dom[$key]['border'] = array(); $dom[$key]['dir'] = $this->rtl?'rtl':'ltr'; $thead = false; // true when we are inside the THEAD tag ++$key; $level = array(); array_push($level, 0); // root while ($elkey < $maxel) { $dom[$key] = array(); $element = $a[$elkey]; $dom[$key]['elkey'] = $elkey; if (preg_match($tagpattern, $element)) { // html tag $element = substr($element, 1, -1); // get tag name preg_match('/[\/]?([a-zA-Z0-9]*)/', $element, $tag); $tagname = strtolower($tag[1]); // check if we are inside a table header if ($tagname == 'thead') { if ($element{0} == '/') { $thead = false; } else { $thead = true; } ++$elkey; continue; } $dom[$key]['tag'] = true; $dom[$key]['value'] = $tagname; if (in_array($dom[$key]['value'], $blocktags)) { $dom[$key]['block'] = true; } else { $dom[$key]['block'] = false; } if ($element{0} == '/') { // *** closing html tag $dom[$key]['opening'] = false; $dom[$key]['parent'] = end($level); array_pop($level); $dom[$key]['hide'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['hide']; $dom[$key]['fontname'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontname']; $dom[$key]['fontstyle'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontstyle']; $dom[$key]['fontsize'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontsize']; $dom[$key]['font-stretch'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['font-stretch']; $dom[$key]['letter-spacing'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['letter-spacing']; $dom[$key]['stroke'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['stroke']; $dom[$key]['fill'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fill']; $dom[$key]['clip'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['clip']; $dom[$key]['line-height'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['line-height']; $dom[$key]['bgcolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['bgcolor']; $dom[$key]['fgcolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fgcolor']; $dom[$key]['strokecolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['strokecolor']; $dom[$key]['align'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['align']; $dom[$key]['dir'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['dir']; if (isset($dom[($dom[($dom[$key]['parent'])]['parent'])]['listtype'])) { $dom[$key]['listtype'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['listtype']; } // set the number of columns in table tag if (($dom[$key]['value'] == 'tr') AND (!isset($dom[($dom[($dom[$key]['parent'])]['parent'])]['cols']))) { $dom[($dom[($dom[$key]['parent'])]['parent'])]['cols'] = $dom[($dom[$key]['parent'])]['cols']; } if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) { $dom[($dom[$key]['parent'])]['content'] = $csstagarray; for ($i = ($dom[$key]['parent'] + 1); $i < $key; ++$i) { $dom[($dom[$key]['parent'])]['content'] .= $a[$dom[$i]['elkey']]; } $key = $i; // mark nested tables $dom[($dom[$key]['parent'])]['content'] = str_replace('', '', $dom[($dom[$key]['parent'])]['content']); $dom[($dom[$key]['parent'])]['content'] = str_replace('', '', $dom[($dom[$key]['parent'])]['content']); } // store header rows on a new table if (($dom[$key]['value'] == 'tr') AND ($dom[($dom[$key]['parent'])]['thead'] === true)) { if ($this->empty_string($dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'])) { $dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] = $csstagarray.$a[$dom[($dom[($dom[$key]['parent'])]['parent'])]['elkey']]; } for ($i = $dom[$key]['parent']; $i <= $key; ++$i) { $dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] .= $a[$dom[$i]['elkey']]; } if (!isset($dom[($dom[$key]['parent'])]['attribute'])) { $dom[($dom[$key]['parent'])]['attribute'] = array(); } // header elements must be always contained in a single page $dom[($dom[$key]['parent'])]['attribute']['nobr'] = 'true'; } if (($dom[$key]['value'] == 'table') AND (!$this->empty_string($dom[($dom[$key]['parent'])]['thead']))) { // remove the nobr attributes from the table header $dom[($dom[$key]['parent'])]['thead'] = str_replace(' nobr="true"', '', $dom[($dom[$key]['parent'])]['thead']); $dom[($dom[$key]['parent'])]['thead'] .= ''; } } else { // *** opening or self-closing html tag $dom[$key]['opening'] = true; $dom[$key]['parent'] = end($level); if ((substr($element, -1, 1) == '/') OR (in_array($dom[$key]['value'], $selfclosingtags))) { // self-closing tag $dom[$key]['self'] = true; } else { // opening tag array_push($level, $key); $dom[$key]['self'] = false; } // copy some values from parent $parentkey = 0; if ($key > 0) { $parentkey = $dom[$key]['parent']; $dom[$key]['hide'] = $dom[$parentkey]['hide']; $dom[$key]['fontname'] = $dom[$parentkey]['fontname']; $dom[$key]['fontstyle'] = $dom[$parentkey]['fontstyle']; $dom[$key]['fontsize'] = $dom[$parentkey]['fontsize']; $dom[$key]['font-stretch'] = $dom[$parentkey]['font-stretch']; $dom[$key]['letter-spacing'] = $dom[$parentkey]['letter-spacing']; $dom[$key]['stroke'] = $dom[$parentkey]['stroke']; $dom[$key]['fill'] = $dom[$parentkey]['fill']; $dom[$key]['clip'] = $dom[$parentkey]['clip']; $dom[$key]['line-height'] = $dom[$parentkey]['line-height']; $dom[$key]['bgcolor'] = $dom[$parentkey]['bgcolor']; $dom[$key]['fgcolor'] = $dom[$parentkey]['fgcolor']; $dom[$key]['strokecolor'] = $dom[$parentkey]['strokecolor']; $dom[$key]['align'] = $dom[$parentkey]['align']; $dom[$key]['listtype'] = $dom[$parentkey]['listtype']; $dom[$key]['text-indent'] = $dom[$parentkey]['text-indent']; $dom[$key]['border'] = array(); $dom[$key]['dir'] = $dom[$parentkey]['dir']; } // get attributes preg_match_all('/([^=\s]*)[\s]*=[\s]*"([^"]*)"/', $element, $attr_array, PREG_PATTERN_ORDER); $dom[$key]['attribute'] = array(); // reset attribute array //while (list($id, $name) = each($attr_array[1])) { foreach( $attr_array[1] as $id => $name ) { $dom[$key]['attribute'][strtolower($name)] = $attr_array[2][$id]; } if (!empty($css)) { // merge CSS style to current style list($dom[$key]['csssel'], $dom[$key]['cssdata']) = $this->getCSSdataArray($dom, $key, $css); $dom[$key]['attribute']['style'] = $this->getTagStyleFromCSSarray($dom[$key]['cssdata']); } // split style attributes if (isset($dom[$key]['attribute']['style']) AND !empty($dom[$key]['attribute']['style'])) { // get style attributes preg_match_all('/([^;:\s]*):([^;]*)/', $dom[$key]['attribute']['style'], $style_array, PREG_PATTERN_ORDER); $dom[$key]['style'] = array(); // reset style attribute array //while (list($id, $name) = each($style_array[1])) { foreach( $style_array[1] as $id => $name ) { // in case of duplicate attribute the last replace the previous $dom[$key]['style'][strtolower($name)] = trim($style_array[2][$id]); } // --- get some style attributes --- // text direction if (isset($dom[$key]['style']['direction'])) { $dom[$key]['dir'] = $dom[$key]['style']['direction']; } // display if (isset($dom[$key]['style']['display'])) { $dom[$key]['hide'] = (trim(strtolower($dom[$key]['style']['display'])) == 'none'); } // font family if (isset($dom[$key]['style']['font-family'])) { $dom[$key]['fontname'] = $this->getFontFamilyName($dom[$key]['style']['font-family']); } // list-style-type if (isset($dom[$key]['style']['list-style-type'])) { $dom[$key]['listtype'] = trim(strtolower($dom[$key]['style']['list-style-type'])); if ($dom[$key]['listtype'] == 'inherit') { $dom[$key]['listtype'] = $dom[$parentkey]['listtype']; } } // text-indent if (isset($dom[$key]['style']['text-indent'])) { $dom[$key]['text-indent'] = $this->getHTMLUnitToUnits($dom[$key]['style']['text-indent']); if ($dom[$key]['text-indent'] == 'inherit') { $dom[$key]['text-indent'] = $dom[$parentkey]['text-indent']; } } // font size if (isset($dom[$key]['style']['font-size'])) { $fsize = trim($dom[$key]['style']['font-size']); switch ($fsize) { // absolute-size case 'xx-small': { $dom[$key]['fontsize'] = $dom[0]['fontsize'] - 4; break; } case 'x-small': { $dom[$key]['fontsize'] = $dom[0]['fontsize'] - 3; break; } case 'small': { $dom[$key]['fontsize'] = $dom[0]['fontsize'] - 2; break; } case 'medium': { $dom[$key]['fontsize'] = $dom[0]['fontsize']; break; } case 'large': { $dom[$key]['fontsize'] = $dom[0]['fontsize'] + 2; break; } case 'x-large': { $dom[$key]['fontsize'] = $dom[0]['fontsize'] + 4; break; } case 'xx-large': { $dom[$key]['fontsize'] = $dom[0]['fontsize'] + 6; break; } // relative-size case 'smaller': { $dom[$key]['fontsize'] = $dom[$parentkey]['fontsize'] - 3; break; } case 'larger': { $dom[$key]['fontsize'] = $dom[$parentkey]['fontsize'] + 3; break; } default: { $dom[$key]['fontsize'] = $this->getHTMLUnitToUnits($fsize, $dom[$parentkey]['fontsize'], 'pt', true); } } } // font-stretch if (isset($dom[$key]['style']['font-stretch'])) { $dom[$key]['font-stretch'] = $this->getCSSFontStretching($dom[$key]['style']['font-stretch'], $dom[$parentkey]['font-stretch']); } // letter-spacing if (isset($dom[$key]['style']['letter-spacing'])) { $dom[$key]['letter-spacing'] = $this->getCSSFontSpacing($dom[$key]['style']['letter-spacing'], $dom[$parentkey]['letter-spacing']); } // line-height if (isset($dom[$key]['style']['line-height'])) { $lineheight = trim($dom[$key]['style']['line-height']); switch ($lineheight) { // A normal line height. This is default case 'normal': { $dom[$key]['line-height'] = $dom[0]['line-height']; break; } default: { if (is_numeric($lineheight)) { $lineheight = $lineheight * 100; } $dom[$key]['line-height'] = $this->getHTMLUnitToUnits($lineheight, 1, '%', true); } } } // font style if (isset($dom[$key]['style']['font-weight'])) { if (strtolower($dom[$key]['style']['font-weight']{0}) == 'n') { if (strpos($dom[$key]['fontstyle'], 'B') !== false) { $dom[$key]['fontstyle'] = str_replace('B', '', $dom[$key]['fontstyle']); } } elseif (strtolower($dom[$key]['style']['font-weight']{0}) == 'b') { $dom[$key]['fontstyle'] .= 'B'; } } if (isset($dom[$key]['style']['font-style']) AND (strtolower($dom[$key]['style']['font-style']{0}) == 'i')) { $dom[$key]['fontstyle'] .= 'I'; } // font color if (isset($dom[$key]['style']['color']) AND (!$this->empty_string($dom[$key]['style']['color']))) { $dom[$key]['fgcolor'] = $this->convertHTMLColorToDec($dom[$key]['style']['color']); } elseif ($dom[$key]['value'] == 'a') { $dom[$key]['fgcolor'] = $this->htmlLinkColorArray; } // background color if (isset($dom[$key]['style']['background-color']) AND (!$this->empty_string($dom[$key]['style']['background-color']))) { $dom[$key]['bgcolor'] = $this->convertHTMLColorToDec($dom[$key]['style']['background-color']); } // text-decoration if (isset($dom[$key]['style']['text-decoration'])) { $decors = explode(' ', strtolower($dom[$key]['style']['text-decoration'])); foreach ($decors as $dec) { $dec = trim($dec); if (!$this->empty_string($dec)) { if ($dec{0} == 'u') { // underline $dom[$key]['fontstyle'] .= 'U'; } elseif ($dec{0} == 'l') { // line-trough $dom[$key]['fontstyle'] .= 'D'; } elseif ($dec{0} == 'o') { // overline $dom[$key]['fontstyle'] .= 'O'; } } } } elseif ($dom[$key]['value'] == 'a') { $dom[$key]['fontstyle'] = $this->htmlLinkFontStyle; } // check for width attribute if (isset($dom[$key]['style']['width'])) { $dom[$key]['width'] = $dom[$key]['style']['width']; } // check for height attribute if (isset($dom[$key]['style']['height'])) { $dom[$key]['height'] = $dom[$key]['style']['height']; } // check for text alignment if (isset($dom[$key]['style']['text-align'])) { $dom[$key]['align'] = strtoupper($dom[$key]['style']['text-align']{0}); } // check for CSS border properties if (isset($dom[$key]['style']['border'])) { $borderstyle = $this->getCSSBorderStyle($dom[$key]['style']['border']); if (!empty($borderstyle)) { $dom[$key]['border']['LTRB'] = $borderstyle; } } if (isset($dom[$key]['style']['border-color'])) { $brd_colors = preg_split('/[\s]+/', trim($dom[$key]['style']['border-color'])); if (isset($brd_colors[3])) { $dom[$key]['border']['L']['color'] = $this->convertHTMLColorToDec($brd_colors[3]); } if (isset($brd_colors[1])) { $dom[$key]['border']['R']['color'] = $this->convertHTMLColorToDec($brd_colors[1]); } if (isset($brd_colors[0])) { $dom[$key]['border']['T']['color'] = $this->convertHTMLColorToDec($brd_colors[0]); } if (isset($brd_colors[2])) { $dom[$key]['border']['B']['color'] = $this->convertHTMLColorToDec($brd_colors[2]); } } if (isset($dom[$key]['style']['border-width'])) { $brd_widths = preg_split('/[\s]+/', trim($dom[$key]['style']['border-width'])); if (isset($brd_widths[3])) { $dom[$key]['border']['L']['width'] = $this->getCSSBorderWidth($brd_widths[3]); } if (isset($brd_widths[1])) { $dom[$key]['border']['R']['width'] = $this->getCSSBorderWidth($brd_widths[1]); } if (isset($brd_widths[0])) { $dom[$key]['border']['T']['width'] = $this->getCSSBorderWidth($brd_widths[0]); } if (isset($brd_widths[2])) { $dom[$key]['border']['B']['width'] = $this->getCSSBorderWidth($brd_widths[2]); } } if (isset($dom[$key]['style']['border-style'])) { $brd_styles = preg_split('/[\s]+/', trim($dom[$key]['style']['border-style'])); if (isset($brd_styles[3])) { $dom[$key]['border']['L']['cap'] = 'square'; $dom[$key]['border']['L']['join'] = 'miter'; $dom[$key]['border']['L']['dash'] = $this->getCSSBorderDashStyle($brd_styles[3]); if ($dom[$key]['border']['L']['dash'] < 0) { $dom[$key]['border']['L'] = array(); } } if (isset($brd_styles[1])) { $dom[$key]['border']['R']['cap'] = 'square'; $dom[$key]['border']['R']['join'] = 'miter'; $dom[$key]['border']['R']['dash'] = $this->getCSSBorderDashStyle($brd_styles[1]); if ($dom[$key]['border']['R']['dash'] < 0) { $dom[$key]['border']['R'] = array(); } } if (isset($brd_styles[0])) { $dom[$key]['border']['T']['cap'] = 'square'; $dom[$key]['border']['T']['join'] = 'miter'; $dom[$key]['border']['T']['dash'] = $this->getCSSBorderDashStyle($brd_styles[0]); if ($dom[$key]['border']['T']['dash'] < 0) { $dom[$key]['border']['T'] = array(); } } if (isset($brd_styles[2])) { $dom[$key]['border']['B']['cap'] = 'square'; $dom[$key]['border']['B']['join'] = 'miter'; $dom[$key]['border']['B']['dash'] = $this->getCSSBorderDashStyle($brd_styles[2]); if ($dom[$key]['border']['B']['dash'] < 0) { $dom[$key]['border']['B'] = array(); } } } $cellside = array('L' => 'left', 'R' => 'right', 'T' => 'top', 'B' => 'bottom'); foreach ($cellside as $bsk => $bsv) { if (isset($dom[$key]['style']['border-'.$bsv])) { $borderstyle = $this->getCSSBorderStyle($dom[$key]['style']['border-'.$bsv]); if (!empty($borderstyle)) { $dom[$key]['border'][$bsk] = $borderstyle; } } if (isset($dom[$key]['style']['border-'.$bsv.'-color'])) { $dom[$key]['border'][$bsk]['color'] = $this->convertHTMLColorToDec($dom[$key]['style']['border-'.$bsv.'-color']); } if (isset($dom[$key]['style']['border-'.$bsv.'-width'])) { $dom[$key]['border'][$bsk]['width'] = $this->getCSSBorderWidth($dom[$key]['style']['border-'.$bsv.'-width']); } if (isset($dom[$key]['style']['border-'.$bsv.'-style'])) { $dom[$key]['border'][$bsk]['dash'] = $this->getCSSBorderDashStyle($dom[$key]['style']['border-'.$bsv.'-style']); if ($dom[$key]['border'][$bsk]['dash'] < 0) { $dom[$key]['border'][$bsk] = array(); } } } // check for CSS padding properties if (isset($dom[$key]['style']['padding'])) { $dom[$key]['padding'] = $this->getCSSPadding($dom[$key]['style']['padding']); } else { $dom[$key]['padding'] = $this->cell_padding; } foreach ($cellside as $psk => $psv) { if (isset($dom[$key]['style']['padding-'.$psv])) { $dom[$key]['padding'][$psk] = $this->getHTMLUnitToUnits($dom[$key]['style']['padding-'.$psv], 0, 'px', false); } } // check for CSS margin properties if (isset($dom[$key]['style']['margin'])) { $dom[$key]['margin'] = $this->getCSSMargin($dom[$key]['style']['margin']); } else { $dom[$key]['margin'] = $this->cell_margin; } foreach ($cellside as $psk => $psv) { if (isset($dom[$key]['style']['margin-'.$psv])) { $dom[$key]['margin'][$psk] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $dom[$key]['style']['margin-'.$psv]), 0, 'px', false); } } // check for CSS border-spacing properties if (isset($dom[$key]['style']['border-spacing'])) { $dom[$key]['border-spacing'] = $this->getCSSBorderMargin($dom[$key]['style']['border-spacing']); } // page-break-inside if (isset($dom[$key]['style']['page-break-inside']) AND ($dom[$key]['style']['page-break-inside'] == 'avoid')) { $dom[$key]['attribute']['nobr'] = 'true'; } // page-break-before if (isset($dom[$key]['style']['page-break-before'])) { if ($dom[$key]['style']['page-break-before'] == 'always') { $dom[$key]['attribute']['pagebreak'] = 'true'; } elseif ($dom[$key]['style']['page-break-before'] == 'left') { $dom[$key]['attribute']['pagebreak'] = 'left'; } elseif ($dom[$key]['style']['page-break-before'] == 'right') { $dom[$key]['attribute']['pagebreak'] = 'right'; } } // page-break-after if (isset($dom[$key]['style']['page-break-after'])) { if ($dom[$key]['style']['page-break-after'] == 'always') { $dom[$key]['attribute']['pagebreakafter'] = 'true'; } elseif ($dom[$key]['style']['page-break-after'] == 'left') { $dom[$key]['attribute']['pagebreakafter'] = 'left'; } elseif ($dom[$key]['style']['page-break-after'] == 'right') { $dom[$key]['attribute']['pagebreakafter'] = 'right'; } } } if (isset($dom[$key]['attribute']['display'])) { $dom[$key]['hide'] = (trim(strtolower($dom[$key]['attribute']['display'])) == 'none'); } if (isset($dom[$key]['attribute']['border']) AND ($dom[$key]['attribute']['border'] != 0)) { $borderstyle = $this->getCSSBorderStyle($dom[$key]['attribute']['border'].' solid black'); if (!empty($borderstyle)) { $dom[$key]['border']['LTRB'] = $borderstyle; } } // check for font tag if ($dom[$key]['value'] == 'font') { // font family if (isset($dom[$key]['attribute']['face'])) { $dom[$key]['fontname'] = $this->getFontFamilyName($dom[$key]['attribute']['face']); } // font size if (isset($dom[$key]['attribute']['size'])) { if ($key > 0) { if ($dom[$key]['attribute']['size']{0} == '+') { $dom[$key]['fontsize'] = $dom[($dom[$key]['parent'])]['fontsize'] + intval(substr($dom[$key]['attribute']['size'], 1)); } elseif ($dom[$key]['attribute']['size']{0} == '-') { $dom[$key]['fontsize'] = $dom[($dom[$key]['parent'])]['fontsize'] - intval(substr($dom[$key]['attribute']['size'], 1)); } else { $dom[$key]['fontsize'] = intval($dom[$key]['attribute']['size']); } } else { $dom[$key]['fontsize'] = intval($dom[$key]['attribute']['size']); } } } // force natural alignment for lists if ((($dom[$key]['value'] == 'ul') OR ($dom[$key]['value'] == 'ol') OR ($dom[$key]['value'] == 'dl')) AND (!isset($dom[$key]['align']) OR $this->empty_string($dom[$key]['align']) OR ($dom[$key]['align'] != 'J'))) { if ($this->rtl) { $dom[$key]['align'] = 'R'; } else { $dom[$key]['align'] = 'L'; } } if (($dom[$key]['value'] == 'small') OR ($dom[$key]['value'] == 'sup') OR ($dom[$key]['value'] == 'sub')) { if (!isset($dom[$key]['attribute']['size']) AND !isset($dom[$key]['style']['font-size'])) { $dom[$key]['fontsize'] = $dom[$key]['fontsize'] * K_SMALL_RATIO; } } if (($dom[$key]['value'] == 'strong') OR ($dom[$key]['value'] == 'b')) { $dom[$key]['fontstyle'] .= 'B'; } if (($dom[$key]['value'] == 'em') OR ($dom[$key]['value'] == 'i')) { $dom[$key]['fontstyle'] .= 'I'; } if ($dom[$key]['value'] == 'u') { $dom[$key]['fontstyle'] .= 'U'; } if (($dom[$key]['value'] == 'del') OR ($dom[$key]['value'] == 's') OR ($dom[$key]['value'] == 'strike')) { $dom[$key]['fontstyle'] .= 'D'; } if (!isset($dom[$key]['style']['text-decoration']) AND ($dom[$key]['value'] == 'a')) { $dom[$key]['fontstyle'] = $this->htmlLinkFontStyle; } if (($dom[$key]['value'] == 'pre') OR ($dom[$key]['value'] == 'tt')) { $dom[$key]['fontname'] = $this->default_monospaced_font; } if (($dom[$key]['value']{0} == 'h') AND (intval($dom[$key]['value']{1}) > 0) AND (intval($dom[$key]['value']{1}) < 7)) { // headings h1, h2, h3, h4, h5, h6 if (!isset($dom[$key]['attribute']['size']) AND !isset($dom[$key]['style']['font-size'])) { $headsize = (4 - intval($dom[$key]['value']{1})) * 2; $dom[$key]['fontsize'] = $dom[0]['fontsize'] + $headsize; } if (!isset($dom[$key]['style']['font-weight'])) { $dom[$key]['fontstyle'] .= 'B'; } } if (($dom[$key]['value'] == 'table')) { $dom[$key]['rows'] = 0; // number of rows $dom[$key]['trids'] = array(); // IDs of TR elements $dom[$key]['thead'] = ''; // table header rows } if (($dom[$key]['value'] == 'tr')) { $dom[$key]['cols'] = 0; if ($thead) { $dom[$key]['thead'] = true; // rows on thead block are printed as a separate table } else { $dom[$key]['thead'] = false; // store the number of rows on table element ++$dom[($dom[$key]['parent'])]['rows']; // store the TR elements IDs on table element array_push($dom[($dom[$key]['parent'])]['trids'], $key); } } if (($dom[$key]['value'] == 'th') OR ($dom[$key]['value'] == 'td')) { if (isset($dom[$key]['attribute']['colspan'])) { $colspan = intval($dom[$key]['attribute']['colspan']); } else { $colspan = 1; } $dom[$key]['attribute']['colspan'] = $colspan; $dom[($dom[$key]['parent'])]['cols'] += $colspan; } // text direction if (isset($dom[$key]['attribute']['dir'])) { $dom[$key]['dir'] = $dom[$key]['attribute']['dir']; } // set foreground color attribute if (isset($dom[$key]['attribute']['color']) AND (!$this->empty_string($dom[$key]['attribute']['color']))) { $dom[$key]['fgcolor'] = $this->convertHTMLColorToDec($dom[$key]['attribute']['color']); } elseif (!isset($dom[$key]['style']['color']) AND ($dom[$key]['value'] == 'a')) { $dom[$key]['fgcolor'] = $this->htmlLinkColorArray; } // set background color attribute if (isset($dom[$key]['attribute']['bgcolor']) AND (!$this->empty_string($dom[$key]['attribute']['bgcolor']))) { $dom[$key]['bgcolor'] = $this->convertHTMLColorToDec($dom[$key]['attribute']['bgcolor']); } // set stroke color attribute if (isset($dom[$key]['attribute']['strokecolor']) AND (!$this->empty_string($dom[$key]['attribute']['strokecolor']))) { $dom[$key]['strokecolor'] = $this->convertHTMLColorToDec($dom[$key]['attribute']['strokecolor']); } // check for width attribute if (isset($dom[$key]['attribute']['width'])) { $dom[$key]['width'] = $dom[$key]['attribute']['width']; } // check for height attribute if (isset($dom[$key]['attribute']['height'])) { $dom[$key]['height'] = $dom[$key]['attribute']['height']; } // check for text alignment if (isset($dom[$key]['attribute']['align']) AND (!$this->empty_string($dom[$key]['attribute']['align'])) AND ($dom[$key]['value'] !== 'img')) { $dom[$key]['align'] = strtoupper($dom[$key]['attribute']['align']{0}); } // check for text rendering mode (the following attributes do not exist in HTML) if (isset($dom[$key]['attribute']['stroke'])) { // font stroke width $dom[$key]['stroke'] = $this->getHTMLUnitToUnits($dom[$key]['attribute']['stroke'], $dom[$key]['fontsize'], 'pt', true); } if (isset($dom[$key]['attribute']['fill'])) { // font fill if ($dom[$key]['attribute']['fill'] == 'true') { $dom[$key]['fill'] = true; } else { $dom[$key]['fill'] = false; } } if (isset($dom[$key]['attribute']['clip'])) { // clipping mode if ($dom[$key]['attribute']['clip'] == 'true') { $dom[$key]['clip'] = true; } else { $dom[$key]['clip'] = false; } } } // end opening tag } else { // text $dom[$key]['tag'] = false; $dom[$key]['block'] = false; //$element = str_replace(' ', $this->unichr(160), $element); $dom[$key]['value'] = stripslashes($this->unhtmlentities($element)); $dom[$key]['parent'] = end($level); $dom[$key]['dir'] = $dom[$dom[$key]['parent']]['dir']; } ++$elkey; ++$key; } return $dom; } /** * Returns the string used to find spaces * @return string * @protected * @author Nicola Asuni * @since 4.8.024 (2010-01-15) */ protected function getSpaceString() { $spacestr = chr(32); if ($this->isUnicodeFont()) { $spacestr = chr(0).chr(32); } return $spacestr; } /** * Prints a cell (rectangular area) with optional borders, background color and html text string. * The upper-left corner of the cell corresponds to the current position. After the call, the current position moves to the right or to the next line.
      * If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting. * @param $w (float) Cell width. If 0, the cell extends up to the right margin. * @param $h (float) Cell minimum height. The cell extends automatically if needed. * @param $x (float) upper-left corner X coordinate * @param $y (float) upper-left corner Y coordinate * @param $html (string) html text to print. Default value: empty string. * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
      • 0: no border (default)
      • 1: frame
      or a string containing some or all of the following characters (in any order):
      • L: left
      • T: top
      • R: right
      • B: bottom
      or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $ln (int) Indicates where the current position should go after the call. Possible values are:
      • 0: to the right (or left for RTL language)
      • 1: to the beginning of the next line
      • 2: below
      Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0. * @param $fill (boolean) Indicates if the cell background must be painted (true) or transparent (false). * @param $reseth (boolean) if true reset the last cell height (default true). * @param $align (string) Allows to center or align the text. Possible values are:
      • L : left align
      • C : center
      • R : right align
      • '' : empty string : left for LTR or right for RTL
      * @param $autopadding (boolean) if true, uses internal padding and automatically adjust it to account for line width. * @see Multicell(), writeHTML() * @public */ public function writeHTMLCell($w, $h, $x, $y, $html='', $border=0, $ln=0, $fill=false, $reseth=true, $align='', $autopadding=true) { return $this->MultiCell($w, $h, $html, $border, $align, $fill, $ln, $x, $y, $reseth, 0, true, $autopadding, 0, 'T', false); } /** * Allows to preserve some HTML formatting (limited support).
      * IMPORTANT: The HTML must be well formatted - try to clean-up it using an application like HTML-Tidy before submitting. * Supported tags are: a, b, blockquote, br, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, img, li, ol, p, pre, small, span, strong, sub, sup, table, tcpdf, td, th, thead, tr, tt, u, ul * @param $html (string) text to display * @param $ln (boolean) if true add a new line after text (default = true) * @param $fill (boolean) Indicates if the background must be painted (true) or transparent (false). * @param $reseth (boolean) if true reset the last cell height (default false). * @param $cell (boolean) if true add the current left (or right for RTL) padding to each Write (default false). * @param $align (string) Allows to center or align the text. Possible values are:
      • L : left align
      • C : center
      • R : right align
      • '' : empty string : left for LTR or right for RTL
      * @public */ public function writeHTML($html, $ln=true, $fill=false, $reseth=false, $cell=false, $align='') { $gvars = $this->getGraphicVars(); // store current values $prev_cell_margin = $this->cell_margin; $prev_cell_padding = $this->cell_padding; $prevPage = $this->page; $prevlMargin = $this->lMargin; $prevrMargin = $this->rMargin; $curfontname = $this->FontFamily; $curfontstyle = $this->FontStyle; $curfontsize = $this->FontSizePt; $curfontascent = $this->getFontAscent($curfontname, $curfontstyle, $curfontsize); $curfontdescent = $this->getFontDescent($curfontname, $curfontstyle, $curfontsize); $curfontstretcing = $this->font_stretching; $curfontkerning = $this->font_spacing; $this->newline = true; $newline = true; $startlinepage = $this->page; $minstartliney = $this->y; $maxbottomliney = 0; $startlinex = $this->x; $startliney = $this->y; $yshift = 0; $loop = 0; $curpos = 0; $this_method_vars = array(); $undo = false; $fontaligned = false; $reverse_dir = false; // true when the text direction is reversed $this->premode = false; if ($this->inxobj) { // we are inside an XObject template $pask = count($this->xobjects[$this->xobjid]['annotations']); } elseif (isset($this->PageAnnots[$this->page])) { $pask = count($this->PageAnnots[$this->page]); } else { $pask = 0; } if ($this->inxobj) { // we are inside an XObject template $startlinepos = strlen($this->xobjects[$this->xobjid]['outdata']); } elseif (!$this->InFooter) { if (isset($this->footerlen[$this->page])) { $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page]; } else { $this->footerpos[$this->page] = $this->pagelen[$this->page]; } $startlinepos = $this->footerpos[$this->page]; } else { // we are inside the footer $startlinepos = $this->pagelen[$this->page]; } $lalign = $align; $plalign = $align; if ($this->rtl) { $w = $this->x - $this->lMargin; } else { $w = $this->w - $this->rMargin - $this->x; } $w -= ($this->cell_padding['L'] + $this->cell_padding['R']); if ($cell) { if ($this->rtl) { $this->x -= $this->cell_padding['R']; $this->lMargin += $this->cell_padding['R']; } else { $this->x += $this->cell_padding['L']; $this->rMargin += $this->cell_padding['L']; } } if ($this->customlistindent >= 0) { $this->listindent = $this->customlistindent; } else { $this->listindent = $this->GetStringWidth('000000'); } $this->listindentlevel = 0; // save previous states $prev_cell_height_ratio = $this->cell_height_ratio; $prev_listnum = $this->listnum; $prev_listordered = $this->listordered; $prev_listcount = $this->listcount; $prev_lispacer = $this->lispacer; $this->listnum = 0; $this->listordered = array(); $this->listcount = array(); $this->lispacer = ''; if (($this->empty_string($this->lasth)) OR ($reseth)) { // reset row height $this->resetLastH(); } $dom = $this->getHtmlDomArray($html); $maxel = count($dom); $key = 0; $hidden_node_key = -1; while ($key < $maxel) { if ($dom[$key]['tag']) { if ($dom[$key]['opening']) { if (($hidden_node_key <= 0) AND $dom[$key]['hide']) { // store the node key $hidden_node_key = $key; } } elseif (($hidden_node_key > 0) AND ($dom[$key]['parent'] == $hidden_node_key)) { // we have reached the closing tag of the hidden node $hidden_node_key = 0; } } if ($hidden_node_key >= 0) { // skip this node ++$key; if ($hidden_node_key == 0) { // reset hidden mode $hidden_node_key = -1; } continue; } if ($dom[$key]['tag'] AND isset($dom[$key]['attribute']['pagebreak'])) { // check for pagebreak if (($dom[$key]['attribute']['pagebreak'] == 'true') OR ($dom[$key]['attribute']['pagebreak'] == 'left') OR ($dom[$key]['attribute']['pagebreak'] == 'right')) { // add a page (or trig AcceptPageBreak() for multicolumn mode) $this->checkPageBreak($this->PageBreakTrigger + 1); $this->htmlvspace = ($this->PageBreakTrigger + 1); } if ((($dom[$key]['attribute']['pagebreak'] == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0)))) OR (($dom[$key]['attribute']['pagebreak'] == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) { // add a page (or trig AcceptPageBreak() for multicolumn mode) $this->checkPageBreak($this->PageBreakTrigger + 1); $this->htmlvspace = ($this->PageBreakTrigger + 1); } } if ($dom[$key]['tag'] AND $dom[$key]['opening'] AND isset($dom[$key]['attribute']['nobr']) AND ($dom[$key]['attribute']['nobr'] == 'true')) { if (isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) { $dom[$key]['attribute']['nobr'] = false; } else { // store current object $this->startTransaction(); // save this method vars $this_method_vars['html'] = $html; $this_method_vars['ln'] = $ln; $this_method_vars['fill'] = $fill; $this_method_vars['reseth'] = $reseth; $this_method_vars['cell'] = $cell; $this_method_vars['align'] = $align; $this_method_vars['gvars'] = $gvars; $this_method_vars['prevPage'] = $prevPage; $this_method_vars['prev_cell_margin'] = $prev_cell_margin; $this_method_vars['prev_cell_padding'] = $prev_cell_padding; $this_method_vars['prevlMargin'] = $prevlMargin; $this_method_vars['prevrMargin'] = $prevrMargin; $this_method_vars['curfontname'] = $curfontname; $this_method_vars['curfontstyle'] = $curfontstyle; $this_method_vars['curfontsize'] = $curfontsize; $this_method_vars['curfontascent'] = $curfontascent; $this_method_vars['curfontdescent'] = $curfontdescent; $this_method_vars['curfontstretcing'] = $curfontstretcing; $this_method_vars['curfontkerning'] = $curfontkerning; $this_method_vars['minstartliney'] = $minstartliney; $this_method_vars['maxbottomliney'] = $maxbottomliney; $this_method_vars['yshift'] = $yshift; $this_method_vars['startlinepage'] = $startlinepage; $this_method_vars['startlinepos'] = $startlinepos; $this_method_vars['startlinex'] = $startlinex; $this_method_vars['startliney'] = $startliney; $this_method_vars['newline'] = $newline; $this_method_vars['loop'] = $loop; $this_method_vars['curpos'] = $curpos; $this_method_vars['pask'] = $pask; $this_method_vars['lalign'] = $lalign; $this_method_vars['plalign'] = $plalign; $this_method_vars['w'] = $w; $this_method_vars['prev_cell_height_ratio'] = $prev_cell_height_ratio; $this_method_vars['prev_listnum'] = $prev_listnum; $this_method_vars['prev_listordered'] = $prev_listordered; $this_method_vars['prev_listcount'] = $prev_listcount; $this_method_vars['prev_lispacer'] = $prev_lispacer; $this_method_vars['fontaligned'] = $fontaligned; $this_method_vars['key'] = $key; $this_method_vars['dom'] = $dom; } } // print THEAD block if (($dom[$key]['value'] == 'tr') AND isset($dom[$key]['thead']) AND $dom[$key]['thead']) { if (isset($dom[$key]['parent']) AND isset($dom[$dom[$key]['parent']]['thead']) AND !$this->empty_string($dom[$dom[$key]['parent']]['thead'])) { $this->inthead = true; // print table header (thead) $this->writeHTML($this->thead, false, false, false, false, ''); // check if we are on a new page or on a new column if (($this->y < $this->start_transaction_y) OR ($this->checkPageBreak($this->lasth, '', false))) { // we are on a new page or on a new column and the total object height is less than the available vertical space. // restore previous object $this->rollbackTransaction(true); // restore previous values foreach ($this_method_vars as $vkey => $vval) { $$vkey = $vval; } // disable table header $tmp_thead = $this->thead; $this->thead = ''; // add a page (or trig AcceptPageBreak() for multicolumn mode) $pre_y = $this->y; if ((!$this->checkPageBreak($this->PageBreakTrigger + 1)) AND ($this->y < $pre_y)) { // fix for multicolumn mode $startliney = $this->y; } $this->start_transaction_page = $this->page; $this->start_transaction_y = $this->y; // restore table header $this->thead = $tmp_thead; // fix table border properties if (isset($dom[$dom[$key]['parent']]['attribute']['cellspacing'])) { $tmp_cellspacing = $this->getHTMLUnitToUnits($dom[$dom[$key]['parent']]['attribute']['cellspacing'], 1, 'px'); } elseif (isset($dom[$dom[$key]['parent']]['border-spacing'])) { $tmp_cellspacing = $dom[$dom[$key]['parent']]['border-spacing']['V']; } else { $tmp_cellspacing = 0; } $dom[$dom[$key]['parent']]['borderposition']['page'] = $this->page; $dom[$dom[$key]['parent']]['borderposition']['column'] = $this->current_column; $dom[$dom[$key]['parent']]['borderposition']['y'] = $this->y + $tmp_cellspacing; $xoffset = ($this->x - $dom[$dom[$key]['parent']]['borderposition']['x']); $dom[$dom[$key]['parent']]['borderposition']['x'] += $xoffset; $dom[$dom[$key]['parent']]['borderposition']['xmax'] += $xoffset; // print table header (thead) $this->writeHTML($this->thead, false, false, false, false, ''); } } // move $key index forward to skip THEAD block while ( ($key < $maxel) AND (!( ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'tr') AND (!isset($dom[$key]['thead']) OR !$dom[$key]['thead'])) OR ($dom[$key]['tag'] AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == 'table'))) )) { ++$key; } } if ($dom[$key]['tag'] OR ($key == 0)) { if ((($dom[$key]['value'] == 'table') OR ($dom[$key]['value'] == 'tr')) AND (isset($dom[$key]['align']))) { $dom[$key]['align'] = ($this->rtl) ? 'R' : 'L'; } // vertically align image in line if ((!$this->newline) AND ($dom[$key]['value'] == 'img') AND (isset($dom[$key]['height'])) AND ($dom[$key]['height'] > 0)) { // get image height $imgh = $this->getHTMLUnitToUnits($dom[$key]['height'], $this->lasth, 'px'); $autolinebreak = false; if (isset($dom[$key]['width']) AND ($dom[$key]['width'] > 0)) { $imgw = $this->getHTMLUnitToUnits($dom[$key]['width'], 1, 'px', false); if (($imgw <= ($this->w - $this->lMargin - $this->rMargin - $this->cell_padding['L'] - $this->cell_padding['R'])) AND ((($this->rtl) AND (($this->x - $imgw) < ($this->lMargin + $this->cell_padding['L']))) OR ((!$this->rtl) AND (($this->x + $imgw) > ($this->w - $this->rMargin - $this->cell_padding['R']))))) { // add automatic line break $autolinebreak = true; $this->Ln('', $cell); if ((!$dom[($key-1)]['tag']) AND ($dom[($key-1)]['value'] == ' ')) { // go back to evaluate this line break --$key; } } } if (!$autolinebreak) { if ($this->inPageBody()) { $pre_y = $this->y; // check for page break if ((!$this->checkPageBreak($imgh)) AND ($this->y < $pre_y)) { // fix for multicolumn mode $startliney = $this->y; } } if ($this->page > $startlinepage) { // fix line splitted over two pages if (isset($this->footerlen[$startlinepage])) { $curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; } // line to be moved one page forward $pagebuff = $this->getPageBuffer($startlinepage); $linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos)); $tstart = substr($pagebuff, 0, $startlinepos); $tend = substr($this->getPageBuffer($startlinepage), $curpos); // remove line from previous page $this->setPageBuffer($startlinepage, $tstart.''.$tend); $pagebuff = $this->getPageBuffer($this->page); $tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]); $tend = substr($pagebuff, $this->cntmrk[$this->page]); // add line start to current page $yshift = ($minstartliney - $this->y); if ($fontaligned) { $yshift += ($curfontsize / $this->k); } $try = sprintf('1 0 0 1 0 %.3F cm', ($yshift * $this->k)); $this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend); // shift the annotations and links if (isset($this->PageAnnots[$this->page])) { $next_pask = count($this->PageAnnots[$this->page]); } else { $next_pask = 0; } if (isset($this->PageAnnots[$startlinepage])) { foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) { if ($pak >= $pask) { $this->PageAnnots[$this->page][] = $pac; unset($this->PageAnnots[$startlinepage][$pak]); $npak = count($this->PageAnnots[$this->page]) - 1; $this->PageAnnots[$this->page][$npak]['y'] -= $yshift; } } } $pask = $next_pask; $startlinepos = $this->cntmrk[$this->page]; $startlinepage = $this->page; $startliney = $this->y; $this->newline = false; } $this->y += ((($curfontsize * $this->cell_height_ratio / $this->k) + $curfontascent - $curfontdescent) / 2) - $imgh; $minstartliney = min($this->y, $minstartliney); $maxbottomliney = ($startliney + ($this->FontSize * $this->cell_height_ratio)); } } elseif (isset($dom[$key]['fontname']) OR isset($dom[$key]['fontstyle']) OR isset($dom[$key]['fontsize']) OR isset($dom[$key]['line-height'])) { // account for different font size $pfontname = $curfontname; $pfontstyle = $curfontstyle; $pfontsize = $curfontsize; $fontname = isset($dom[$key]['fontname']) ? $dom[$key]['fontname'] : $curfontname; $fontstyle = isset($dom[$key]['fontstyle']) ? $dom[$key]['fontstyle'] : $curfontstyle; $fontsize = isset($dom[$key]['fontsize']) ? $dom[$key]['fontsize'] : $curfontsize; $fontascent = $this->getFontAscent($fontname, $fontstyle, $fontsize); $fontdescent = $this->getFontDescent($fontname, $fontstyle, $fontsize); if (($fontname != $curfontname) OR ($fontstyle != $curfontstyle) OR ($fontsize != $curfontsize) OR ($this->cell_height_ratio != $dom[$key]['line-height']) OR ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'li')) ) { if (($key < ($maxel - 1)) AND ( ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'li')) OR ($this->cell_height_ratio != $dom[$key]['line-height']) OR (!$this->newline AND is_numeric($fontsize) AND is_numeric($curfontsize) AND ($fontsize >= 0) AND ($curfontsize >= 0) AND ($fontsize != $curfontsize)) )) { if ($this->page > $startlinepage) { // fix lines splitted over two pages if (isset($this->footerlen[$startlinepage])) { $curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; } // line to be moved one page forward $pagebuff = $this->getPageBuffer($startlinepage); $linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos)); $tstart = substr($pagebuff, 0, $startlinepos); $tend = substr($this->getPageBuffer($startlinepage), $curpos); // remove line start from previous page $this->setPageBuffer($startlinepage, $tstart.''.$tend); $pagebuff = $this->getPageBuffer($this->page); $tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]); $tend = substr($pagebuff, $this->cntmrk[$this->page]); // add line start to current page $yshift = ($minstartliney - $this->y); $try = sprintf('1 0 0 1 0 %.3F cm', ($yshift * $this->k)); $this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend); // shift the annotations and links if (isset($this->PageAnnots[$this->page])) { $next_pask = count($this->PageAnnots[$this->page]); } else { $next_pask = 0; } if (isset($this->PageAnnots[$startlinepage])) { foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) { if ($pak >= $pask) { $this->PageAnnots[$this->page][] = $pac; unset($this->PageAnnots[$startlinepage][$pak]); $npak = count($this->PageAnnots[$this->page]) - 1; $this->PageAnnots[$this->page][$npak]['y'] -= $yshift; } } } $pask = $next_pask; $startlinepos = $this->cntmrk[$this->page]; $startlinepage = $this->page; $startliney = $this->y; } if (!isset($dom[$key]['line-height'])) { $dom[$key]['line-height'] = $this->cell_height_ratio; } if (!$dom[$key]['block']) { if (!(isset($dom[($key + 1)]) AND $dom[($key + 1)]['tag'] AND (!$dom[($key + 1)]['opening']) AND ($dom[($key + 1)]['value'] != 'li') AND $dom[$key]['tag'] AND (!$dom[$key]['opening']))) { $this->y += (((($curfontsize * $this->cell_height_ratio) - ($fontsize * $dom[$key]['line-height'])) / $this->k) + $curfontascent - $fontascent - $curfontdescent + $fontdescent) / 2; } if (($dom[$key]['value'] != 'sup') AND ($dom[$key]['value'] != 'sub')) { $current_line_align_data = array($key, $minstartliney, $maxbottomliney); if (isset($line_align_data) AND (($line_align_data[0] == ($key - 1)) OR (($line_align_data[0] == ($key - 2)) AND (isset($dom[($key - 1)])) AND (preg_match('/^([\s]+)$/', $dom[($key - 1)]['value']) > 0)))) { $minstartliney = min($this->y, $line_align_data[1]); $maxbottomliney = max(($this->y + (($fontsize * $this->cell_height_ratio) / $this->k)), $line_align_data[2]); } else { $minstartliney = min($this->y, $minstartliney); $maxbottomliney = max(($this->y + (($fontsize * $this->cell_height_ratio) / $this->k)), $maxbottomliney); } $line_align_data = $current_line_align_data; } } $this->cell_height_ratio = $dom[$key]['line-height']; $fontaligned = true; } $this->SetFont($fontname, $fontstyle, $fontsize); // reset row height $this->resetLastH(); $curfontname = $fontname; $curfontstyle = $fontstyle; $curfontsize = $fontsize; $curfontascent = $fontascent; $curfontdescent = $fontdescent; } } // set text rendering mode $textstroke = isset($dom[$key]['stroke']) ? $dom[$key]['stroke'] : $this->textstrokewidth; $textfill = isset($dom[$key]['fill']) ? $dom[$key]['fill'] : (($this->textrendermode % 2) == 0); $textclip = isset($dom[$key]['clip']) ? $dom[$key]['clip'] : ($this->textrendermode > 3); $this->setTextRenderingMode($textstroke, $textfill, $textclip); if (isset($dom[$key]['font-stretch']) AND ($dom[$key]['font-stretch'] !== false)) { $this->setFontStretching($dom[$key]['font-stretch']); } if (isset($dom[$key]['letter-spacing']) AND ($dom[$key]['letter-spacing'] !== false)) { $this->setFontSpacing($dom[$key]['letter-spacing']); } if (($plalign == 'J') AND $dom[$key]['block']) { $plalign = ''; } // get current position on page buffer $curpos = $this->pagelen[$startlinepage]; if (isset($dom[$key]['bgcolor']) AND ($dom[$key]['bgcolor'] !== false)) { $this->SetFillColorArray($dom[$key]['bgcolor']); $wfill = true; } else { $wfill = $fill | false; } if (isset($dom[$key]['fgcolor']) AND ($dom[$key]['fgcolor'] !== false)) { $this->SetTextColorArray($dom[$key]['fgcolor']); } if (isset($dom[$key]['strokecolor']) AND ($dom[$key]['strokecolor'] !== false)) { $this->SetDrawColorArray($dom[$key]['strokecolor']); } if (isset($dom[$key]['align'])) { $lalign = $dom[$key]['align']; } if ($this->empty_string($lalign)) { $lalign = $align; } } // align lines if ($this->newline AND (strlen($dom[$key]['value']) > 0) AND ($dom[$key]['value'] != 'td') AND ($dom[$key]['value'] != 'th')) { $newline = true; $fontaligned = false; // we are at the beginning of a new line if (isset($startlinex)) { $yshift = ($minstartliney - $startliney); if (($yshift > 0) OR ($this->page > $startlinepage)) { $yshift = 0; } $t_x = 0; // the last line must be shifted to be aligned as requested $linew = abs($this->endlinex - $startlinex); if ($this->inxobj) { // we are inside an XObject template $pstart = substr($this->xobjects[$this->xobjid]['outdata'], 0, $startlinepos); if (isset($opentagpos)) { $midpos = $opentagpos; } else { $midpos = 0; } if ($midpos > 0) { $pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos, ($midpos - $startlinepos)); $pend = substr($this->xobjects[$this->xobjid]['outdata'], $midpos); } else { $pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos); $pend = ''; } } else { $pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos); if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) { $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; $midpos = min($opentagpos, $this->footerpos[$startlinepage]); } elseif (isset($opentagpos)) { $midpos = $opentagpos; } elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) { $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; $midpos = $this->footerpos[$startlinepage]; } else { $midpos = 0; } if ($midpos > 0) { $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos)); $pend = substr($this->getPageBuffer($startlinepage), $midpos); } else { $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos); $pend = ''; } } if ((isset($plalign) AND ((($plalign == 'C') OR ($plalign == 'J') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl)))))) { // calculate shifting amount $tw = $w; if (($plalign == 'J') AND $this->isRTLTextDir() AND ($this->num_columns > 1)) { $tw += $this->cell_padding['R']; } if ($this->lMargin != $prevlMargin) { $tw += ($prevlMargin - $this->lMargin); } if ($this->rMargin != $prevrMargin) { $tw += ($prevrMargin - $this->rMargin); } $one_space_width = $this->GetStringWidth(chr(32)); $no = 0; // number of spaces on a line contained on a single block if ($this->isRTLTextDir()) { // RTL // remove left space if exist $pos1 = $this->revstrpos($pmid, '[('); if ($pos1 > 0) { $pos1 = intval($pos1); if ($this->isUnicodeFont()) { $pos2 = intval($this->revstrpos($pmid, '[('.chr(0).chr(32))); $spacelen = 2; } else { $pos2 = intval($this->revstrpos($pmid, '[('.chr(32))); $spacelen = 1; } if ($pos1 == $pos2) { $pmid = substr($pmid, 0, ($pos1 + 2)).substr($pmid, ($pos1 + 2 + $spacelen)); if (substr($pmid, $pos1, 4) == '[()]') { $linew -= $one_space_width; } elseif ($pos1 == strpos($pmid, '[(')) { $no = 1; } } } } else { // LTR // remove right space if exist $pos1 = $this->revstrpos($pmid, ')]'); if ($pos1 > 0) { $pos1 = intval($pos1); if ($this->isUnicodeFont()) { $pos2 = intval($this->revstrpos($pmid, chr(0).chr(32).')]')) + 2; $spacelen = 2; } else { $pos2 = intval($this->revstrpos($pmid, chr(32).')]')) + 1; $spacelen = 1; } if ($pos1 == $pos2) { $pmid = substr($pmid, 0, ($pos1 - $spacelen)).substr($pmid, $pos1); $linew -= $one_space_width; } } } $mdiff = ($tw - $linew); if ($plalign == 'C') { if ($this->rtl) { $t_x = -($mdiff / 2); } else { $t_x = ($mdiff / 2); } } elseif ($plalign == 'R') { // right alignment on LTR document $t_x = $mdiff; } elseif ($plalign == 'L') { // left alignment on RTL document $t_x = -$mdiff; } elseif (($plalign == 'J') AND ($plalign == $lalign)) { // Justification if ($this->isRTLTextDir()) { // align text on the left $t_x = -$mdiff; } $ns = 0; // number of spaces $pmidtemp = $pmid; // escape special characters $pmidtemp = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmidtemp); $pmidtemp = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmidtemp); // search spaces if (preg_match_all('/\[\(([^\)]*)\)\]/x', $pmidtemp, $lnstring, PREG_PATTERN_ORDER)) { $spacestr = $this->getSpaceString(); $maxkk = count($lnstring[1]) - 1; for ($kk=0; $kk <= $maxkk; ++$kk) { // restore special characters $lnstring[1][$kk] = str_replace('#!#OP#!#', '(', $lnstring[1][$kk]); $lnstring[1][$kk] = str_replace('#!#CP#!#', ')', $lnstring[1][$kk]); // store number of spaces on the strings $lnstring[2][$kk] = substr_count($lnstring[1][$kk], $spacestr); // count total spaces on line $ns += $lnstring[2][$kk]; $lnstring[3][$kk] = $ns; } if ($ns == 0) { $ns = 1; } // calculate additional space to add to each existing space $spacewidth = ($mdiff / ($ns - $no)) * $this->k; $spacewidthu = -1000 * ($mdiff + (($ns + $no) * $one_space_width)) / $ns / $this->FontSize; if ($this->font_spacing != 0) { // fixed spacing mode $osw = -1000 * $this->font_spacing / $this->FontSize; $spacewidthu += $osw; } $nsmax = $ns; $ns = 0; reset($lnstring); $offset = 0; $strcount = 0; $prev_epsposbeg = 0; $textpos = 0; if ($this->isRTLTextDir()) { $textpos = $this->wPt; } global $spacew; while (preg_match('/([0-9\.\+\-]*)[\s](Td|cm|m|l|c|re)[\s]/x', $pmid, $strpiece, PREG_OFFSET_CAPTURE, $offset) == 1) { // check if we are inside a string section '[( ... )]' $stroffset = strpos($pmid, '[(', $offset); if (($stroffset !== false) AND ($stroffset <= $strpiece[2][1])) { // set offset to the end of string section $offset = strpos($pmid, ')]', $stroffset); while (($offset !== false) AND ($pmid[($offset - 1)] == '\\')) { $offset = strpos($pmid, ')]', ($offset + 1)); } if ($offset === false) { $this->Error('HTML Justification: malformed PDF code.'); } continue; } if ($this->isRTLTextDir()) { $spacew = ($spacewidth * ($nsmax - $ns)); } else { $spacew = ($spacewidth * $ns); } $offset = $strpiece[2][1] + strlen($strpiece[2][0]); $epsposbeg = strpos($pmid, 'q'.$this->epsmarker, $offset); $epsposend = strpos($pmid, $this->epsmarker.'Q', $offset) + strlen($this->epsmarker.'Q'); if ((($epsposbeg > 0) AND ($epsposend > 0) AND ($offset > $epsposbeg) AND ($offset < $epsposend)) OR (($epsposbeg === false) AND ($epsposend > 0) AND ($offset < $epsposend))) { // shift EPS images $trx = sprintf('1 0 0 1 %.3F 0 cm', $spacew); $epsposbeg = strpos($pmid, 'q'.$this->epsmarker, ($prev_epsposbeg - 6)); $pmid_b = substr($pmid, 0, $epsposbeg); $pmid_m = substr($pmid, $epsposbeg, ($epsposend - $epsposbeg)); $pmid_e = substr($pmid, $epsposend); $pmid = $pmid_b."\nq\n".$trx."\n".$pmid_m."\nQ\n".$pmid_e; $offset = $epsposend; continue; } $prev_epsposbeg = $epsposbeg; $currentxpos = 0; // shift blocks of code switch ($strpiece[2][0]) { case 'Td': case 'cm': case 'm': case 'l': { // get current X position preg_match('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $xmatches); $currentxpos = $xmatches[1]; $textpos = $currentxpos; if (($strcount <= $maxkk) AND ($strpiece[2][0] == 'Td')) { $ns = $lnstring[3][$strcount]; if ($this->isRTLTextDir()) { $spacew = ($spacewidth * ($nsmax - $ns)); } ++$strcount; } // justify block /* $pmid = preg_replace_callback('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', create_function('$matches', 'global $spacew; $newx = sprintf("%.2F",(floatval($matches[1]) + $spacew)); return "".$newx." ".$matches[2]." x*#!#*x".$matches[3].$matches[4];'), $pmid, 1); */ $pmid = preg_replace_callback('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', function($matches) { global $spacew; $newx = sprintf("%.2F",(floatval($matches[1]) + $spacew)); return "".$newx." ".$matches[2]." x*#!#*x".$matches[3].$matches[4]; }, $pmid, 1); break; } case 're': { // justify block if (!$this->empty_string($this->lispacer)) { $this->lispacer = ''; break; } preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x', $pmid, $xmatches); $currentxpos = $xmatches[1]; global $x_diff, $w_diff; $x_diff = 0; $w_diff = 0; if ($this->isRTLTextDir()) { // RTL if ($currentxpos < $textpos) { $x_diff = ($spacewidth * ($nsmax - $lnstring[3][$strcount])); $w_diff = ($spacewidth * $lnstring[2][$strcount]); } else { if ($strcount > 0) { $x_diff = ($spacewidth * ($nsmax - $lnstring[3][($strcount - 1)])); $w_diff = ($spacewidth * $lnstring[2][($strcount - 1)]); } } } else { // LTR if ($currentxpos > $textpos) { if ($strcount > 0) { $x_diff = ($spacewidth * $lnstring[3][($strcount - 1)]); } $w_diff = ($spacewidth * $lnstring[2][$strcount]); } else { if ($strcount > 1) { $x_diff = ($spacewidth * $lnstring[3][($strcount - 2)]); } if ($strcount > 0) { $w_diff = ($spacewidth * $lnstring[2][($strcount - 1)]); } } } /* $pmid = preg_replace_callback('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x', create_function('$matches', 'global $x_diff, $w_diff; $newx = sprintf("%.2F",(floatval($matches[1]) + $x_diff)); $neww = sprintf("%.2F",(floatval($matches[3]) + $w_diff)); return "".$newx." ".$matches[2]." ".$neww." ".$matches[4]." x*#!#*x".$matches[5].$matches[6];'), $pmid, 1); */ $pmid = preg_replace_callback('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x', function($matches){ global $x_diff, $w_diff; $newx = sprintf("%.2F",(floatval($matches[1]) + $x_diff)); $neww = sprintf("%.2F",(floatval($matches[3]) + $w_diff)); return "".$newx." ".$matches[2]." ".$neww." ".$matches[4]." x*#!#*x".$matches[5].$matches[6]; }, $pmid, 1); break; } case 'c': { // get current X position preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x', $pmid, $xmatches); $currentxpos = $xmatches[1]; // justify block /* $pmid = preg_replace_callback('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$xmatches[4].')[\s]('.$xmatches[5].')[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x', create_function('$matches', 'global $spacew; $newx1 = sprintf("%.3F",(floatval($matches[1]) + $spacew)); $newx2 = sprintf("%.3F",(floatval($matches[3]) + $spacew)); $newx3 = sprintf("%.3F",(floatval($matches[5]) + $spacew)); return "".$newx1." ".$matches[2]." ".$newx2." ".$matches[4]." ".$newx3." ".$matches[6]." x*#!#*x".$matches[7].$matches[8];'), $pmid, 1); */ $pmid = preg_replace_callback('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$xmatches[4].')[\s]('.$xmatches[5].')[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x', function($matches) { global $spacew; $newx1 = sprintf("%.3F",(floatval($matches[1]) + $spacew)); $newx2 = sprintf("%.3F",(floatval($matches[3]) + $spacew)); $newx3 = sprintf("%.3F",(floatval($matches[5]) + $spacew)); return "".$newx1." ".$matches[2]." ".$newx2." ".$matches[4]." ".$newx3." ".$matches[6]." x*#!#*x".$matches[7].$matches[8]; }, $pmid, 1); break; } } // shift the annotations and links $cxpos = ($currentxpos / $this->k); $lmpos = ($this->lMargin + $this->cell_padding['L'] + $this->feps); if ($this->inxobj) { // we are inside an XObject template foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) { if (($pac['y'] >= $minstartliney) AND (($pac['x'] * $this->k) >= ($currentxpos - $this->feps)) AND (($pac['x'] * $this->k) <= ($currentxpos + $this->feps))) { if ($cxpos > $lmpos) { $this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += ($spacew / $this->k); $this->xobjects[$this->xobjid]['annotations'][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k); } else { $this->xobjects[$this->xobjid]['annotations'][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k); } break; } } } elseif (isset($this->PageAnnots[$this->page])) { foreach ($this->PageAnnots[$this->page] as $pak => $pac) { if (($pac['y'] >= $minstartliney) AND (($pac['x'] * $this->k) >= ($currentxpos - $this->feps)) AND (($pac['x'] * $this->k) <= ($currentxpos + $this->feps))) { if ($cxpos > $lmpos) { $this->PageAnnots[$this->page][$pak]['x'] += ($spacew / $this->k); $this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k); } else { $this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k); } break; } } } } // end of while // remove markers $pmid = str_replace('x*#!#*x', '', $pmid); if ($this->isUnicodeFont()) { // multibyte characters $spacew = $spacewidthu; if ($this->font_stretching != 100) { // word spacing is affected by stretching $spacew /= ($this->font_stretching / 100); } $pmidtemp = $pmid; // escape special characters $pmidtemp = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmidtemp); $pmidtemp = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmidtemp); /* $pmid = preg_replace_callback("/\[\(([^\)]*)\)\]/x", create_function('$matches', 'global $spacew; $matches[1] = str_replace("#!#OP#!#", "(", $matches[1]); $matches[1] = str_replace("#!#CP#!#", ")", $matches[1]); return "[(".str_replace(chr(0).chr(32), ") ".sprintf("%.3F", $spacew)." (", $matches[1]).")]";'), $pmidtemp); */ $pmid = preg_replace_callback("/\[\(([^\)]*)\)\]/x", function($matches){ global $spacew; $matches[1] = str_replace("#!#OP#!#", "(", $matches[1]); $matches[1] = str_replace("#!#CP#!#", ")", $matches[1]); return "[(".str_replace(chr(0).chr(32), ") ".sprintf("%.3F", $spacew)." (", $matches[1]).")]"; }, $pmidtemp); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['outdata'] = $pstart."\n".$pmid."\n".$pend; } else { $this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\n".$pend); } $endlinepos = strlen($pstart."\n".$pmid."\n"); } else { // non-unicode (single-byte characters) if ($this->font_stretching != 100) { // word spacing (Tw) is affected by stretching $spacewidth /= ($this->font_stretching / 100); } $rs = sprintf('%.3F Tw', $spacewidth); $pmid = preg_replace("/\[\(/x", $rs.' [(', $pmid); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['outdata'] = $pstart."\n".$pmid."\nBT 0 Tw ET\n".$pend; } else { $this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\nBT 0 Tw ET\n".$pend); } $endlinepos = strlen($pstart."\n".$pmid."\nBT 0 Tw ET\n"); } } } // end of J } // end if $startlinex if (($t_x != 0) OR ($yshift < 0)) { // shift the line $trx = sprintf('1 0 0 1 %.3F %.3F cm', ($t_x * $this->k), ($yshift * $this->k)); $pstart .= "\nq\n".$trx."\n".$pmid."\nQ\n"; $endlinepos = strlen($pstart); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['outdata'] = $pstart.$pend; foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) { if ($pak >= $pask) { $this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += $t_x; $this->xobjects[$this->xobjid]['annotations'][$pak]['y'] -= $yshift; } } } else { $this->setPageBuffer($startlinepage, $pstart.$pend); // shift the annotations and links if (isset($this->PageAnnots[$this->page])) { foreach ($this->PageAnnots[$this->page] as $pak => $pac) { if ($pak >= $pask) { $this->PageAnnots[$this->page][$pak]['x'] += $t_x; $this->PageAnnots[$this->page][$pak]['y'] -= $yshift; } } } } $this->y -= $yshift; } } $pbrk = $this->checkPageBreak($this->lasth); $this->newline = false; $startlinex = $this->x; $startliney = $this->y; if ($dom[$dom[$key]['parent']]['value'] == 'sup') { $startliney -= ((0.3 * $this->FontSizePt) / $this->k); } elseif ($dom[$dom[$key]['parent']]['value'] == 'sub') { $startliney -= (($this->FontSizePt / 0.7) / $this->k); } else { $minstartliney = $startliney; $maxbottomliney = ($this->y + (($fontsize * $this->cell_height_ratio) / $this->k)); } $startlinepage = $this->page; if (isset($endlinepos) AND (!$pbrk)) { $startlinepos = $endlinepos; } else { if ($this->inxobj) { // we are inside an XObject template $startlinepos = strlen($this->xobjects[$this->xobjid]['outdata']); } elseif (!$this->InFooter) { if (isset($this->footerlen[$this->page])) { $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page]; } else { $this->footerpos[$this->page] = $this->pagelen[$this->page]; } $startlinepos = $this->footerpos[$this->page]; } else { $startlinepos = $this->pagelen[$this->page]; } } unset($endlinepos); $plalign = $lalign; if (isset($this->PageAnnots[$this->page])) { $pask = count($this->PageAnnots[$this->page]); } else { $pask = 0; } if (!($dom[$key]['tag'] AND !$dom[$key]['opening'] AND ($dom[$key]['value'] == 'table') AND (isset($this->emptypagemrk[$this->page])) AND ($this->emptypagemrk[$this->page] == $this->pagelen[$this->page]))) { $this->SetFont($fontname, $fontstyle, $fontsize); if ($wfill) { $this->SetFillColorArray($this->bgcolor); } } } // end newline if (isset($opentagpos)) { unset($opentagpos); } if ($dom[$key]['tag']) { if ($dom[$key]['opening']) { // get text indentation (if any) if (isset($dom[$key]['text-indent']) AND $dom[$key]['block']) { $this->textindent = $dom[$key]['text-indent']; $this->newline = true; } // table if ($dom[$key]['value'] == 'table') { // available page width if ($this->rtl) { $wtmp = $this->x - $this->lMargin; } else { $wtmp = $this->w - $this->rMargin - $this->x; } // get cell spacing if (isset($dom[$key]['attribute']['cellspacing'])) { $clsp = $this->getHTMLUnitToUnits($dom[$key]['attribute']['cellspacing'], 1, 'px'); $cellspacing = array('H' => $clsp, 'V' => $clsp); } elseif (isset($dom[$key]['border-spacing'])) { $cellspacing = $dom[$key]['border-spacing']; } else { $cellspacing = array('H' => 0, 'V' => 0); } // table width if (isset($dom[$key]['width'])) { $table_width = $this->getHTMLUnitToUnits($dom[$key]['width'], $wtmp, 'px'); } else { $table_width = $wtmp; } $table_width -= (2 * $cellspacing['H']); if (!$this->inthead) { $this->y += $cellspacing['V']; } if ($this->rtl) { $cellspacingx = -$cellspacing['H']; } else { $cellspacingx = $cellspacing['H']; } // total table width without cellspaces $table_columns_width = ($table_width - ($cellspacing['H'] * ($dom[$key]['cols'] - 1))); // minimum column width $table_min_column_width = ($table_columns_width / $dom[$key]['cols']); // array of custom column widths $table_colwidths = array_fill(0, $dom[$key]['cols'], $table_min_column_width); } // table row if ($dom[$key]['value'] == 'tr') { // reset column counter $colid = 0; } // table cell if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) { $trid = $dom[$key]['parent']; $table_el = $dom[$trid]['parent']; if (!isset($dom[$table_el]['cols'])) { $dom[$table_el]['cols'] = $dom[$trid]['cols']; } // store border info $tdborder = 0; if (isset($dom[$key]['border']) AND !empty($dom[$key]['border'])) { $tdborder = $dom[$key]['border']; } $colspan = $dom[$key]['attribute']['colspan']; $old_cell_padding = $this->cell_padding; if (isset($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'])) { $crclpd = $this->getHTMLUnitToUnits($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'], 1, 'px'); $current_cell_padding = array('L' => $crclpd, 'T' => $crclpd, 'R' => $crclpd, 'B' => $crclpd); } elseif (isset($dom[($dom[$trid]['parent'])]['padding'])) { $current_cell_padding = $dom[($dom[$trid]['parent'])]['padding']; } else { $current_cell_padding = array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0); } $this->cell_padding = $current_cell_padding; if (isset($dom[$key]['height'])) { // minimum cell height $cellh = $this->getHTMLUnitToUnits($dom[$key]['height'], 0, 'px'); } else { $cellh = 0; } if (isset($dom[$key]['content'])) { $cell_content = stripslashes($dom[$key]['content']); } else { $cell_content = ' '; } $tagtype = $dom[$key]['value']; $parentid = $key; while (($key < $maxel) AND (!(($dom[$key]['tag']) AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == $tagtype) AND ($dom[$key]['parent'] == $parentid)))) { // move $key index forward ++$key; } if (!isset($dom[$trid]['startpage'])) { $dom[$trid]['startpage'] = $this->page; } else { $this->setPage($dom[$trid]['startpage']); } if (!isset($dom[$trid]['startcolumn'])) { $dom[$trid]['startcolumn'] = $this->current_column; } elseif ($this->current_column != $dom[$trid]['startcolumn']) { $tmpx = $this->x; $this->selectColumn($dom[$trid]['startcolumn']); $this->x = $tmpx; } if (!isset($dom[$trid]['starty'])) { $dom[$trid]['starty'] = $this->y; } else { $this->y = $dom[$trid]['starty']; } if (!isset($dom[$trid]['startx'])) { $dom[$trid]['startx'] = $this->x; $this->x += $cellspacingx; } else { $this->x += ($cellspacingx / 2); } if (isset($dom[$parentid]['attribute']['rowspan'])) { $rowspan = intval($dom[$parentid]['attribute']['rowspan']); } else { $rowspan = 1; } // skip row-spanned cells started on the previous rows if (isset($dom[$table_el]['rowspans'])) { $rsk = 0; $rskmax = count($dom[$table_el]['rowspans']); while ($rsk < $rskmax) { $trwsp = $dom[$table_el]['rowspans'][$rsk]; $rsstartx = $trwsp['startx']; $rsendx = $trwsp['endx']; // account for margin changes if ($trwsp['startpage'] < $this->page) { if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$trwsp['startpage']]['orm'])) { $dl = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$trwsp['startpage']]['orm']); $rsstartx -= $dl; $rsendx -= $dl; } elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$trwsp['startpage']]['olm'])) { $dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$trwsp['startpage']]['olm']); $rsstartx += $dl; $rsendx += $dl; } } if (($trwsp['rowspan'] > 0) AND ($rsstartx > ($this->x - $cellspacing['H'] - $current_cell_padding['L'] - $this->feps)) AND ($rsstartx < ($this->x + $cellspacing['H'] + $current_cell_padding['R'] + $this->feps)) AND (($trwsp['starty'] < ($this->y - $this->feps)) OR ($trwsp['startpage'] < $this->page) OR ($trwsp['startcolumn'] < $this->current_column))) { // set the starting X position of the current cell $this->x = $rsendx + $cellspacingx; // increment column indicator $colid += $trwsp['colspan']; if (($trwsp['rowspan'] == 1) AND (isset($dom[$trid]['endy'])) AND (isset($dom[$trid]['endpage'])) AND (isset($dom[$trid]['endcolumn'])) AND ($trwsp['endpage'] == $dom[$trid]['endpage']) AND ($trwsp['endcolumn'] == $dom[$trid]['endcolumn'])) { // set ending Y position for row $dom[$table_el]['rowspans'][$rsk]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']); $dom[$trid]['endy'] = $dom[$table_el]['rowspans'][$rsk]['endy']; } $rsk = 0; } else { ++$rsk; } } } if (isset($dom[$parentid]['width'])) { // user specified width $cellw = $this->getHTMLUnitToUnits($dom[$parentid]['width'], $table_columns_width, 'px'); $tmpcw = ($cellw / $colspan); for ($i = 0; $i < $colspan; ++$i) { $table_colwidths[($colid + $i)] = $tmpcw; } } else { // inherit column width $cellw = 0; for ($i = 0; $i < $colspan; ++$i) { $cellw += $table_colwidths[($colid + $i)]; } } $cellw += (($colspan - 1) * $cellspacing['H']); // increment column indicator $colid += $colspan; // add rowspan information to table element if ($rowspan > 1) { $trsid = array_push($dom[$table_el]['rowspans'], array('trid' => $trid, 'rowspan' => $rowspan, 'mrowspan' => $rowspan, 'colspan' => $colspan, 'startpage' => $this->page, 'startcolumn' => $this->current_column, 'startx' => $this->x, 'starty' => $this->y)); } $cellid = array_push($dom[$trid]['cellpos'], array('startx' => $this->x)); if ($rowspan > 1) { $dom[$trid]['cellpos'][($cellid - 1)]['rowspanid'] = ($trsid - 1); } // push background colors if (isset($dom[$parentid]['bgcolor']) AND ($dom[$parentid]['bgcolor'] !== false)) { $dom[$trid]['cellpos'][($cellid - 1)]['bgcolor'] = $dom[$parentid]['bgcolor']; } // store border info if (isset($tdborder) AND !empty($tdborder)) { $dom[$trid]['cellpos'][($cellid - 1)]['border'] = $tdborder; } $prevLastH = $this->lasth; // store some info for multicolumn mode if ($this->rtl) { $this->colxshift['x'] = $this->w - $this->x - $this->rMargin; } else { $this->colxshift['x'] = $this->x - $this->lMargin; } $this->colxshift['s'] = $cellspacing; $this->colxshift['p'] = $current_cell_padding; // ****** write the cell content ****** $this->MultiCell($cellw, $cellh, $cell_content, false, $lalign, false, 2, '', '', true, 0, true, true, 0, 'T', false); // restore some values $this->colxshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0)); $this->lasth = $prevLastH; $this->cell_padding = $old_cell_padding; $dom[$trid]['cellpos'][($cellid - 1)]['endx'] = $this->x; // update the end of row position if ($rowspan <= 1) { if (isset($dom[$trid]['endy'])) { if (($this->page == $dom[$trid]['endpage']) AND ($this->current_column == $dom[$trid]['endcolumn'])) { $dom[$trid]['endy'] = max($this->y, $dom[$trid]['endy']); } elseif (($this->page > $dom[$trid]['endpage']) OR ($this->current_column > $dom[$trid]['endcolumn'])) { $dom[$trid]['endy'] = $this->y; } } else { $dom[$trid]['endy'] = $this->y; } if (isset($dom[$trid]['endpage'])) { $dom[$trid]['endpage'] = max($this->page, $dom[$trid]['endpage']); } else { $dom[$trid]['endpage'] = $this->page; } if (isset($dom[$trid]['endcolumn'])) { $dom[$trid]['endcolumn'] = max($this->current_column, $dom[$trid]['endcolumn']); } else { $dom[$trid]['endcolumn'] = $this->current_column; } } else { // account for row-spanned cells $dom[$table_el]['rowspans'][($trsid - 1)]['endx'] = $this->x; $dom[$table_el]['rowspans'][($trsid - 1)]['endy'] = $this->y; $dom[$table_el]['rowspans'][($trsid - 1)]['endpage'] = $this->page; $dom[$table_el]['rowspans'][($trsid - 1)]['endcolumn'] = $this->current_column; } if (isset($dom[$table_el]['rowspans'])) { // update endy and endpage on rowspanned cells foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) { if ($trwsp['rowspan'] > 0) { if (isset($dom[$trid]['endpage'])) { if (($trwsp['endpage'] == $dom[$trid]['endpage']) AND ($trwsp['endcolumn'] == $dom[$trid]['endcolumn'])) { $dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']); } elseif (($trwsp['endpage'] < $dom[$trid]['endpage']) OR ($trwsp['endcolumn'] < $dom[$trid]['endcolumn'])) { $dom[$table_el]['rowspans'][$k]['endy'] = $dom[$trid]['endy']; $dom[$table_el]['rowspans'][$k]['endpage'] = $dom[$trid]['endpage']; $dom[$table_el]['rowspans'][$k]['endcolumn'] = $dom[$trid]['endcolumn']; } else { $dom[$trid]['endy'] = $this->pagedim[$dom[$trid]['endpage']]['hk'] - $this->pagedim[$dom[$trid]['endpage']]['bm']; } } } } } $this->x += ($cellspacingx / 2); } else { // opening tag (or self-closing tag) if (!isset($opentagpos)) { if ($this->inxobj) { // we are inside an XObject template $opentagpos = strlen($this->xobjects[$this->xobjid]['outdata']); } elseif (!$this->InFooter) { if (isset($this->footerlen[$this->page])) { $this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page]; } else { $this->footerpos[$this->page] = $this->pagelen[$this->page]; } $opentagpos = $this->footerpos[$this->page]; } } $dom = $this->openHTMLTagHandler($dom, $key, $cell); } } else { // closing tag $prev_numpages = $this->numpages; $old_bordermrk = $this->bordermrk[$this->page]; $dom = $this->closeHTMLTagHandler($dom, $key, $cell, $maxbottomliney); if ($this->bordermrk[$this->page] > $old_bordermrk) { $startlinepos += ($this->bordermrk[$this->page] - $old_bordermrk); } if ($prev_numpages > $this->numpages) { $startlinepage = $this->page; } } } elseif (strlen($dom[$key]['value']) > 0) { // print list-item if (!$this->empty_string($this->lispacer) AND ($this->lispacer != '^')) { $this->SetFont($pfontname, $pfontstyle, $pfontsize); $this->resetLastH(); $minstartliney = $this->y; $maxbottomliney = ($startliney + ($this->FontSize * $this->cell_height_ratio)); $this->putHtmlListBullet($this->listnum, $this->lispacer, $pfontsize); $this->SetFont($curfontname, $curfontstyle, $curfontsize); $this->resetLastH(); if (is_numeric($pfontsize) AND ($pfontsize > 0) AND is_numeric($curfontsize) AND ($curfontsize > 0) AND ($pfontsize != $curfontsize)) { $pfontascent = $this->getFontAscent($pfontname, $pfontstyle, $pfontsize); $pfontdescent = $this->getFontDescent($pfontname, $pfontstyle, $pfontsize); $this->y += ((($pfontsize - $curfontsize) * $this->cell_height_ratio / $this->k) + $pfontascent - $curfontascent - $pfontdescent + $curfontdescent) / 2; $minstartliney = min($this->y, $minstartliney); $maxbottomliney = max(($this->y + (($pfontsize * $this->cell_height_ratio) / $this->k)), $maxbottomliney); } } // text $this->htmlvspace = 0; if ((!$this->premode) AND $this->isRTLTextDir()) { // reverse spaces order $lsp = ''; // left spaces $rsp = ''; // right spaces if (preg_match('/^('.$this->re_space['p'].'+)/'.$this->re_space['m'], $dom[$key]['value'], $matches)) { $lsp = $matches[1]; } if (preg_match('/('.$this->re_space['p'].'+)$/'.$this->re_space['m'], $dom[$key]['value'], $matches)) { $rsp = $matches[1]; } $dom[$key]['value'] = $rsp.$this->stringTrim($dom[$key]['value']).$lsp; } if ($newline) { if (!$this->premode) { $prelen = strlen($dom[$key]['value']); if ($this->isRTLTextDir()) { // right trim except non-breaking space $dom[$key]['value'] = $this->stringRightTrim($dom[$key]['value']); } else { // left trim except non-breaking space $dom[$key]['value'] = $this->stringLeftTrim($dom[$key]['value']); } $postlen = strlen($dom[$key]['value']); if (($postlen == 0) AND ($prelen > 0)) { $dom[$key]['trimmed_space'] = true; } } $newline = false; $firstblock = true; } else { $firstblock = false; // replace empty multiple spaces string with a single space $dom[$key]['value'] = preg_replace('/^'.$this->re_space['p'].'+$/'.$this->re_space['m'], chr(32), $dom[$key]['value']); } $strrest = ''; if ($this->rtl) { $this->x -= $this->textindent; } else { $this->x += $this->textindent; } if (!isset($dom[$key]['trimmed_space']) OR !$dom[$key]['trimmed_space']) { $strlinelen = $this->GetStringWidth($dom[$key]['value']); if (!empty($this->HREF) AND (isset($this->HREF['url']))) { // HTML Link $hrefcolor = ''; if (isset($dom[($dom[$key]['parent'])]['fgcolor']) AND ($dom[($dom[$key]['parent'])]['fgcolor'] !== false)) { $hrefcolor = $dom[($dom[$key]['parent'])]['fgcolor']; } $hrefstyle = -1; if (isset($dom[($dom[$key]['parent'])]['fontstyle']) AND ($dom[($dom[$key]['parent'])]['fontstyle'] !== false)) { $hrefstyle = $dom[($dom[$key]['parent'])]['fontstyle']; } $strrest = $this->addHtmlLink($this->HREF['url'], $dom[$key]['value'], $wfill, true, $hrefcolor, $hrefstyle, true); } else { $wadj = 0; // space to leave for block continuity if ($this->rtl) { $cwa = $this->x - $this->lMargin; } else { $cwa = $this->w - $this->rMargin - $this->x; } if (($strlinelen < $cwa) AND (isset($dom[($key + 1)])) AND ($dom[($key + 1)]['tag']) AND (!$dom[($key + 1)]['block'])) { // check the next text blocks for continuity $nkey = ($key + 1); $write_block = true; $same_textdir = true; $tmp_fontname = $this->FontFamily; $tmp_fontstyle = $this->FontStyle; $tmp_fontsize = $this->FontSizePt; while ($write_block AND isset($dom[$nkey])) { if ($dom[$nkey]['tag']) { if ($dom[$nkey]['block']) { // end of block $write_block = false; } $tmp_fontname = isset($dom[$nkey]['fontname']) ? $dom[$nkey]['fontname'] : $this->FontFamily; $tmp_fontstyle = isset($dom[$nkey]['fontstyle']) ? $dom[$nkey]['fontstyle'] : $this->FontStyle; $tmp_fontsize = isset($dom[$nkey]['fontsize']) ? $dom[$nkey]['fontsize'] : $this->FontSizePt; $same_textdir = ($dom[$nkey]['dir'] == $dom[$key]['dir']); } else { $nextstr = preg_split('/'.$this->re_space['p'].'+/'.$this->re_space['m'], $dom[$nkey]['value']); if (isset($nextstr[0]) AND $same_textdir) { $wadj += $this->GetStringWidth($nextstr[0], $tmp_fontname, $tmp_fontstyle, $tmp_fontsize); } if (isset($nextstr[1])) { $write_block = false; } } ++$nkey; } } if (($wadj > 0) AND (($strlinelen + $wadj) >= $cwa)) { $wadj = 0; $nextstr = preg_split('/'.$this->re_space['p'].'/'.$this->re_space['m'], $dom[$key]['value']); $numblks = count($nextstr); if ($numblks > 1) { // try to split on blank spaces $wadj = ($cwa - $strlinelen + $this->GetStringWidth($nextstr[($numblks - 1)])); } } // check for reversed text direction if (($wadj > 0) AND (($this->rtl AND ($this->tmprtl === 'L')) OR (!$this->rtl AND ($this->tmprtl === 'R')))) { // LTR text on RTL direction or RTL text on LTR direction $reverse_dir = true; $this->rtl = !$this->rtl; $revshift = ($strlinelen + $wadj + 0.000001); // add little quantity for rounding problems if ($this->rtl) { $this->x += $revshift; } else { $this->x -= $revshift; } $xws = $this->x; } // ****** write only until the end of the line and get the rest ****** $strrest = $this->Write($this->lasth, $dom[$key]['value'], '', $wfill, '', false, 0, true, $firstblock, 0, $wadj); // restore default direction if ($reverse_dir AND ($wadj == 0)) { $this->x = $xws; $this->rtl = !$this->rtl; $reverse_dir = false; } } } $this->textindent = 0; if (strlen($strrest) > 0) { // store the remaining string on the previous $key position $this->newline = true; if ($strrest == $dom[$key]['value']) { // used to avoid infinite loop ++$loop; } else { $loop = 0; } $dom[$key]['value'] = $strrest; if ($cell) { if ($this->rtl) { $this->x -= $this->cell_padding['R']; } else { $this->x += $this->cell_padding['L']; } } if ($loop < 3) { --$key; } } else { $loop = 0; } } ++$key; if (isset($dom[$key]['tag']) AND $dom[$key]['tag'] AND (!isset($dom[$key]['opening']) OR !$dom[$key]['opening']) AND isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) { // check if we are on a new page or on a new column if ((!$undo) AND (($this->y < $this->start_transaction_y) OR (($dom[$key]['value'] == 'tr') AND ($dom[($dom[$key]['parent'])]['endy'] < $this->start_transaction_y)))) { // we are on a new page or on a new column and the total object height is less than the available vertical space. // restore previous object $this->rollbackTransaction(true); // restore previous values foreach ($this_method_vars as $vkey => $vval) { $$vkey = $vval; } // add a page (or trig AcceptPageBreak() for multicolumn mode) $pre_y = $this->y; if ((!$this->checkPageBreak($this->PageBreakTrigger + 1)) AND ($this->y < $pre_y)) { $startliney = $this->y; } $undo = true; // avoid infinite loop } else { $undo = false; } } } // end for each $key // align the last line if (isset($startlinex)) { $yshift = ($minstartliney - $startliney); if (($yshift > 0) OR ($this->page > $startlinepage)) { $yshift = 0; } $t_x = 0; // the last line must be shifted to be aligned as requested $linew = abs($this->endlinex - $startlinex); if ($this->inxobj) { // we are inside an XObject template $pstart = substr($this->xobjects[$this->xobjid]['outdata'], 0, $startlinepos); if (isset($opentagpos)) { $midpos = $opentagpos; } else { $midpos = 0; } if ($midpos > 0) { $pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos, ($midpos - $startlinepos)); $pend = substr($this->xobjects[$this->xobjid]['outdata'], $midpos); } else { $pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos); $pend = ''; } } else { $pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos); if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) { $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; $midpos = min($opentagpos, $this->footerpos[$startlinepage]); } elseif (isset($opentagpos)) { $midpos = $opentagpos; } elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) { $this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage]; $midpos = $this->footerpos[$startlinepage]; } else { $midpos = 0; } if ($midpos > 0) { $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos)); $pend = substr($this->getPageBuffer($startlinepage), $midpos); } else { $pmid = substr($this->getPageBuffer($startlinepage), $startlinepos); $pend = ''; } } if ((isset($plalign) AND ((($plalign == 'C') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl)))))) { // calculate shifting amount $tw = $w; if ($this->lMargin != $prevlMargin) { $tw += ($prevlMargin - $this->lMargin); } if ($this->rMargin != $prevrMargin) { $tw += ($prevrMargin - $this->rMargin); } $one_space_width = $this->GetStringWidth(chr(32)); $no = 0; // number of spaces on a line contained on a single block if ($this->isRTLTextDir()) { // RTL // remove left space if exist $pos1 = $this->revstrpos($pmid, '[('); if ($pos1 > 0) { $pos1 = intval($pos1); if ($this->isUnicodeFont()) { $pos2 = intval($this->revstrpos($pmid, '[('.chr(0).chr(32))); $spacelen = 2; } else { $pos2 = intval($this->revstrpos($pmid, '[('.chr(32))); $spacelen = 1; } if ($pos1 == $pos2) { $pmid = substr($pmid, 0, ($pos1 + 2)).substr($pmid, ($pos1 + 2 + $spacelen)); if (substr($pmid, $pos1, 4) == '[()]') { $linew -= $one_space_width; } elseif ($pos1 == strpos($pmid, '[(')) { $no = 1; } } } } else { // LTR // remove right space if exist $pos1 = $this->revstrpos($pmid, ')]'); if ($pos1 > 0) { $pos1 = intval($pos1); if ($this->isUnicodeFont()) { $pos2 = intval($this->revstrpos($pmid, chr(0).chr(32).')]')) + 2; $spacelen = 2; } else { $pos2 = intval($this->revstrpos($pmid, chr(32).')]')) + 1; $spacelen = 1; } if ($pos1 == $pos2) { $pmid = substr($pmid, 0, ($pos1 - $spacelen)).substr($pmid, $pos1); $linew -= $one_space_width; } } } $mdiff = ($tw - $linew); if ($plalign == 'C') { if ($this->rtl) { $t_x = -($mdiff / 2); } else { $t_x = ($mdiff / 2); } } elseif ($plalign == 'R') { // right alignment on LTR document $t_x = $mdiff; } elseif ($plalign == 'L') { // left alignment on RTL document $t_x = -$mdiff; } } // end if startlinex if (($t_x != 0) OR ($yshift < 0)) { // shift the line $trx = sprintf('1 0 0 1 %.3F %.3F cm', ($t_x * $this->k), ($yshift * $this->k)); $pstart .= "\nq\n".$trx."\n".$pmid."\nQ\n"; $endlinepos = strlen($pstart); if ($this->inxobj) { // we are inside an XObject template $this->xobjects[$this->xobjid]['outdata'] = $pstart.$pend; foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) { if ($pak >= $pask) { $this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += $t_x; $this->xobjects[$this->xobjid]['annotations'][$pak]['y'] -= $yshift; } } } else { $this->setPageBuffer($startlinepage, $pstart.$pend); // shift the annotations and links if (isset($this->PageAnnots[$this->page])) { foreach ($this->PageAnnots[$this->page] as $pak => $pac) { if ($pak >= $pask) { $this->PageAnnots[$this->page][$pak]['x'] += $t_x; $this->PageAnnots[$this->page][$pak]['y'] -= $yshift; } } } } $this->y -= $yshift; $yshift = 0; } } // restore previous values $this->setGraphicVars($gvars); if ($this->num_columns > 1) { $this->selectColumn(); } elseif ($this->page > $prevPage) { $this->lMargin = $this->pagedim[$this->page]['olm']; $this->rMargin = $this->pagedim[$this->page]['orm']; } // restore previous list state $this->cell_height_ratio = $prev_cell_height_ratio; $this->listnum = $prev_listnum; $this->listordered = $prev_listordered; $this->listcount = $prev_listcount; $this->lispacer = $prev_lispacer; if ($ln AND (!($cell AND ($dom[$key-1]['value'] == 'table')))) { $this->Ln($this->lasth); if ($this->y < $maxbottomliney) { $this->y = $maxbottomliney; } } unset($dom); } /** * Process opening tags. * @param $dom (array) html dom array * @param $key (int) current element id * @param $cell (boolean) if true add the default left (or right if RTL) padding to each new line (default false). * @return $dom array * @protected */ protected function openHTMLTagHandler($dom, $key, $cell) { $tag = $dom[$key]; $parent = $dom[($dom[$key]['parent'])]; $firsttag = ($key == 1); // check for text direction attribute if (isset($tag['dir'])) { $this->setTempRTL($tag['dir']); } else { $this->tmprtl = false; } if ($tag['block']) { $hbz = 0; // distance from y to line bottom $hb = 0; // vertical space between block tags // calculate vertical space for block tags if (isset($this->tagvspaces[$tag['value']][0]['h']) AND ($this->tagvspaces[$tag['value']][0]['h'] >= 0)) { $cur_h = $this->tagvspaces[$tag['value']][0]['h']; } elseif (isset($tag['fontsize'])) { $cur_h = ($tag['fontsize'] / $this->k) * $this->cell_height_ratio; } else { $cur_h = $this->FontSize * $this->cell_height_ratio; } if (isset($this->tagvspaces[$tag['value']][0]['n'])) { $n = $this->tagvspaces[$tag['value']][0]['n']; } elseif (preg_match('/[h][0-9]/', $tag['value']) > 0) { $n = 0.6; } else { $n = 1; } if ((!isset($this->tagvspaces[$tag['value']])) AND (in_array($tag['value'], array('div', 'dt', 'dd', 'li', 'br')))) { $hb = 0; } else { $hb = ($n * $cur_h); } if (($this->htmlvspace <= 0) AND ($n > 0)) { if (isset($parent['fontsize'])) { $hbz = (($parent['fontsize'] / $this->k) * $this->cell_height_ratio); } else { $hbz = $this->FontSize * $this->cell_height_ratio; } } } // Opening tag switch($tag['value']) { case 'table': { $cp = 0; $cs = 0; $dom[$key]['rowspans'] = array(); if (!isset($dom[$key]['attribute']['nested']) OR ($dom[$key]['attribute']['nested'] != 'true')) { // set table header if (!$this->empty_string($dom[$key]['thead'])) { // set table header $this->thead = $dom[$key]['thead']; if (!isset($this->theadMargins) OR (empty($this->theadMargins))) { $this->theadMargins = array(); $this->theadMargins['cell_padding'] = $this->cell_padding; $this->theadMargins['lmargin'] = $this->lMargin; $this->theadMargins['rmargin'] = $this->rMargin; $this->theadMargins['page'] = $this->page; $this->theadMargins['cell'] = $cell; } } } // store current margins and page $dom[$key]['old_cell_padding'] = $this->cell_padding; if (isset($tag['attribute']['cellpadding'])) { $pad = $this->getHTMLUnitToUnits($tag['attribute']['cellpadding'], 1, 'px'); $this->SetCellPadding($pad); } elseif (isset($tag['padding'])) { $this->cell_padding = $tag['padding']; } if (isset($tag['attribute']['cellspacing'])) { $cs = $this->getHTMLUnitToUnits($tag['attribute']['cellspacing'], 1, 'px'); } elseif (isset($tag['border-spacing'])) { $cs = $tag['border-spacing']['V']; } $prev_y = $this->y; if ($this->checkPageBreak(((2 * $cp) + (2 * $cs) + $this->lasth), '', false) OR ($this->y < $prev_y)) { $this->inthead = true; // add a page (or trig AcceptPageBreak() for multicolumn mode) $this->checkPageBreak($this->PageBreakTrigger + 1); } break; } case 'tr': { // array of columns positions $dom[$key]['cellpos'] = array(); break; } case 'hr': { if ((isset($tag['height'])) AND ($tag['height'] != '')) { $hrHeight = $this->getHTMLUnitToUnits($tag['height'], 1, 'px'); } else { $hrHeight = $this->GetLineWidth(); } $this->addHTMLVertSpace($hbz, ($hrHeight / 2), $cell, $firsttag); $x = $this->GetX(); $y = $this->GetY(); $wtmp = $this->w - $this->lMargin - $this->rMargin; if ($cell) { $wtmp -= ($this->cell_padding['L'] + $this->cell_padding['R']); } if ((isset($tag['width'])) AND ($tag['width'] != '')) { $hrWidth = $this->getHTMLUnitToUnits($tag['width'], $wtmp, 'px'); } else { $hrWidth = $wtmp; } $prevlinewidth = $this->GetLineWidth(); $this->SetLineWidth($hrHeight); $this->Line($x, $y, $x + $hrWidth, $y); $this->SetLineWidth($prevlinewidth); $this->addHTMLVertSpace(($hrHeight / 2), 0, $cell, !isset($dom[($key + 1)])); break; } case 'a': { if (array_key_exists('href', $tag['attribute'])) { $this->HREF['url'] = $tag['attribute']['href']; } break; } case 'img': { if (isset($tag['attribute']['src'])) { if ($tag['attribute']['src']{0} === '@') { // data stream $tag['attribute']['src'] = '@'.base64_decode(substr($tag['attribute']['src'], 1)); $type = ''; } else { // check for images without protocol if (preg_match('%^/{2}%', $tag['attribute']['src'])) { $tag['attribute']['src'] = 'http:'.$tag['attribute']['src']; } // replace relative path with real server path if (($tag['attribute']['src'][0] == '/') AND !empty($_SERVER['DOCUMENT_ROOT']) AND ($_SERVER['DOCUMENT_ROOT'] != '/')) { $findroot = strpos($tag['attribute']['src'], $_SERVER['DOCUMENT_ROOT']); if (($findroot === false) OR ($findroot > 1)) { if (substr($_SERVER['DOCUMENT_ROOT'], -1) == '/') { $tag['attribute']['src'] = substr($_SERVER['DOCUMENT_ROOT'], 0, -1).$tag['attribute']['src']; } else { $tag['attribute']['src'] = $_SERVER['DOCUMENT_ROOT'].$tag['attribute']['src']; } } } $tag['attribute']['src'] = htmlspecialchars_decode(urldecode($tag['attribute']['src'])); $type = $this->getImageFileType($tag['attribute']['src']); $testscrtype = @parse_url($tag['attribute']['src']); if (!isset($testscrtype['query']) OR empty($testscrtype['query'])) { // convert URL to server path $tag['attribute']['src'] = str_replace(K_PATH_URL, K_PATH_MAIN, $tag['attribute']['src']); } } if (!isset($tag['width'])) { $tag['width'] = 0; } if (!isset($tag['height'])) { $tag['height'] = 0; } //if (!isset($tag['attribute']['align'])) { // the only alignment supported is "bottom" // further development is required for other modes. $tag['attribute']['align'] = 'bottom'; //} switch($tag['attribute']['align']) { case 'top': { $align = 'T'; break; } case 'middle': { $align = 'M'; break; } case 'bottom': { $align = 'B'; break; } default: { $align = 'B'; break; } } $prevy = $this->y; $xpos = $this->x; $imglink = ''; if (isset($this->HREF['url']) AND !$this->empty_string($this->HREF['url'])) { $imglink = $this->HREF['url']; if ($imglink{0} == '#') { // convert url to internal link $lnkdata = explode(',', $imglink); if (isset($lnkdata[0])) { $page = intval(substr($lnkdata[0], 1)); if (empty($page) OR ($page <= 0)) { $page = $this->page; } if (isset($lnkdata[1]) AND (strlen($lnkdata[1]) > 0)) { $lnky = floatval($lnkdata[1]); } else { $lnky = 0; } $imglink = $this->AddLink(); $this->SetLink($imglink, $lnky, $page); } } } $border = 0; if (isset($tag['border']) AND !empty($tag['border'])) { // currently only support 1 (frame) or a combination of 'LTRB' $border = $tag['border']; } $iw = ''; if (isset($tag['width'])) { $iw = $this->getHTMLUnitToUnits($tag['width'], 1, 'px', false); } $ih = ''; if (isset($tag['height'])) { $ih = $this->getHTMLUnitToUnits($tag['height'], 1, 'px', false); } if (($type == 'eps') OR ($type == 'ai')) { $this->ImageEps($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, $imglink, true, $align, '', $border, true); } elseif ($type == 'svg') { $this->ImageSVG($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, $imglink, $align, '', $border, true); } else { $this->Image($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, '', $imglink, $align, false, 300, '', false, false, $border, false, false, true); } switch($align) { case 'T': { $this->y = $prevy; break; } case 'M': { $this->y = (($this->img_rb_y + $prevy - ($tag['fontsize'] / $this->k)) / 2) ; break; } case 'B': { $this->y = $this->img_rb_y - ($tag['fontsize'] / $this->k); break; } } } break; } case 'dl': { ++$this->listnum; if ($this->listnum == 1) { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); } else { $this->addHTMLVertSpace(0, 0, $cell, $firsttag); } break; } case 'dt': { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); break; } case 'dd': { if ($this->rtl) { $this->rMargin += $this->listindent; } else { $this->lMargin += $this->listindent; } ++$this->listindentlevel; $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); break; } case 'ul': case 'ol': { ++$this->listnum; if ($tag['value'] == 'ol') { $this->listordered[$this->listnum] = true; } else { $this->listordered[$this->listnum] = false; } if (isset($tag['attribute']['start'])) { $this->listcount[$this->listnum] = intval($tag['attribute']['start']) - 1; } else { $this->listcount[$this->listnum] = 0; } if ($this->rtl) { $this->rMargin += $this->listindent; $this->x -= $this->listindent; } else { $this->lMargin += $this->listindent; $this->x += $this->listindent; } ++$this->listindentlevel; if ($this->listnum == 1) { if ($key > 1) { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); } } else { $this->addHTMLVertSpace(0, 0, $cell, $firsttag); } break; } case 'li': { if ($key > 2) { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); } if ($this->listordered[$this->listnum]) { // ordered item if (isset($parent['attribute']['type']) AND !$this->empty_string($parent['attribute']['type'])) { $this->lispacer = $parent['attribute']['type']; } elseif (isset($parent['listtype']) AND !$this->empty_string($parent['listtype'])) { $this->lispacer = $parent['listtype']; } elseif (isset($this->lisymbol) AND !$this->empty_string($this->lisymbol)) { $this->lispacer = $this->lisymbol; } else { $this->lispacer = '#'; } ++$this->listcount[$this->listnum]; if (isset($tag['attribute']['value'])) { $this->listcount[$this->listnum] = intval($tag['attribute']['value']); } } else { // unordered item if (isset($parent['attribute']['type']) AND !$this->empty_string($parent['attribute']['type'])) { $this->lispacer = $parent['attribute']['type']; } elseif (isset($parent['listtype']) AND !$this->empty_string($parent['listtype'])) { $this->lispacer = $parent['listtype']; } elseif (isset($this->lisymbol) AND !$this->empty_string($this->lisymbol)) { $this->lispacer = $this->lisymbol; } else { $this->lispacer = '!'; } } break; } case 'blockquote': { if ($this->rtl) { $this->rMargin += $this->listindent; } else { $this->lMargin += $this->listindent; } ++$this->listindentlevel; $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); break; } case 'br': { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); break; } case 'div': { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); break; } case 'p': { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); break; } case 'pre': { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); $this->premode = true; break; } case 'sup': { $this->SetXY($this->GetX(), $this->GetY() - ((0.7 * $this->FontSizePt) / $this->k)); break; } case 'sub': { $this->SetXY($this->GetX(), $this->GetY() + ((0.3 * $this->FontSizePt) / $this->k)); break; } case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': { $this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag); break; } // Form fields (since 4.8.000 - 2009-09-07) case 'form': { if (isset($tag['attribute']['action'])) { $this->form_action = $tag['attribute']['action']; } else { $this->form_action = K_PATH_URL.$_SERVER['SCRIPT_NAME']; } if (isset($tag['attribute']['enctype'])) { $this->form_enctype = $tag['attribute']['enctype']; } else { $this->form_enctype = 'application/x-www-form-urlencoded'; } if (isset($tag['attribute']['method'])) { $this->form_mode = $tag['attribute']['method']; } else { $this->form_mode = 'post'; } break; } case 'input': { if (isset($tag['attribute']['name']) AND !$this->empty_string($tag['attribute']['name'])) { $name = $tag['attribute']['name']; } else { break; } $prop = array(); $opt = array(); if (isset($tag['attribute']['readonly']) AND !$this->empty_string($tag['attribute']['readonly'])) { $prop['readonly'] = true; } if (isset($tag['attribute']['value']) AND !$this->empty_string($tag['attribute']['value'])) { $value = $tag['attribute']['value']; } if (isset($tag['attribute']['maxlength']) AND !$this->empty_string($tag['attribute']['maxlength'])) { $opt['maxlen'] = intval($tag['attribute']['value']); } $h = $this->FontSize * $this->cell_height_ratio; if (isset($tag['attribute']['size']) AND !$this->empty_string($tag['attribute']['size'])) { $w = intval($tag['attribute']['size']) * $this->GetStringWidth(chr(32)) * 2; } else { $w = $h; } if (isset($tag['attribute']['checked']) AND (($tag['attribute']['checked'] == 'checked') OR ($tag['attribute']['checked'] == 'true'))) { $checked = true; } else { $checked = false; } if (isset($tag['align'])) { switch ($tag['align']) { case 'C': { $opt['q'] = 1; break; } case 'R': { $opt['q'] = 2; break; } case 'L': default: { break; } } } switch ($tag['attribute']['type']) { case 'text': { if (isset($value)) { $opt['v'] = $value; } $this->TextField($name, $w, $h, $prop, $opt, '', '', false); break; } case 'password': { if (isset($value)) { $opt['v'] = $value; } $prop['password'] = 'true'; $this->TextField($name, $w, $h, $prop, $opt, '', '', false); break; } case 'checkbox': { $this->CheckBox($name, $w, $checked, $prop, $opt, $value, '', '', false); break; } case 'radio': { $this->RadioButton($name, $w, $prop, $opt, $value, $checked, '', '', false); break; } case 'submit': { $w = $this->GetStringWidth($value) * 1.5; $h *= 1.6; $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255)); $action = array(); $action['S'] = 'SubmitForm'; $action['F'] = $this->form_action; if ($this->form_enctype != 'FDF') { $action['Flags'] = array('ExportFormat'); } if ($this->form_mode == 'get') { $action['Flags'] = array('GetMethod'); } $this->Button($name, $w, $h, $value, $action, $prop, $opt, '', '', false); break; } case 'reset': { $w = $this->GetStringWidth($value) * 1.5; $h *= 1.6; $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255)); $this->Button($name, $w, $h, $value, array('S'=>'ResetForm'), $prop, $opt, '', '', false); break; } case 'file': { $prop['fileSelect'] = 'true'; $this->TextField($name, $w, $h, $prop, $opt, '', '', false); if (!isset($value)) { $value = '*'; } $w = $this->GetStringWidth($value) * 2; $h *= 1.2; $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255)); $jsaction = 'var f=this.getField(\''.$name.'\'); f.browseForFileToSubmit();'; $this->Button('FB_'.$name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false); break; } case 'hidden': { if (isset($value)) { $opt['v'] = $value; } $opt['f'] = array('invisible', 'hidden'); $this->TextField($name, 0, 0, $prop, $opt, '', '', false); break; } case 'image': { // THIS TYPE MUST BE FIXED if (isset($tag['attribute']['src']) AND !$this->empty_string($tag['attribute']['src'])) { $img = $tag['attribute']['src']; } else { break; } $value = 'img'; //$opt['mk'] = array('i'=>$img, 'tp'=>1, 'if'=>array('sw'=>'A', 's'=>'A', 'fb'=>false)); if (isset($tag['attribute']['onclick']) AND !empty($tag['attribute']['onclick'])) { $jsaction = $tag['attribute']['onclick']; } else { $jsaction = ''; } $this->Button($name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false); break; } case 'button': { $w = $this->GetStringWidth($value) * 1.5; $h *= 1.6; $prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255)); if (isset($tag['attribute']['onclick']) AND !empty($tag['attribute']['onclick'])) { $jsaction = $tag['attribute']['onclick']; } else { $jsaction = ''; } $this->Button($name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false); break; } } break; } case 'textarea': { $prop = array(); $opt = array(); if (isset($tag['attribute']['readonly']) AND !$this->empty_string($tag['attribute']['readonly'])) { $prop['readonly'] = true; } if (isset($tag['attribute']['name']) AND !$this->empty_string($tag['attribute']['name'])) { $name = $tag['attribute']['name']; } else { break; } if (isset($tag['attribute']['value']) AND !$this->empty_string($tag['attribute']['value'])) { $opt['v'] = $tag['attribute']['value']; } if (isset($tag['attribute']['cols']) AND !$this->empty_string($tag['attribute']['cols'])) { $w = intval($tag['attribute']['cols']) * $this->GetStringWidth(chr(32)) * 2; } else { $w = 40; } if (isset($tag['attribute']['rows']) AND !$this->empty_string($tag['attribute']['rows'])) { $h = intval($tag['attribute']['rows']) * $this->FontSize * $this->cell_height_ratio; } else { $h = 10; } $prop['multiline'] = 'true'; $this->TextField($name, $w, $h, $prop, $opt, '', '', false); break; } case 'select': { $h = $this->FontSize * $this->cell_height_ratio; if (isset($tag['attribute']['size']) AND !$this->empty_string($tag['attribute']['size'])) { $h *= ($tag['attribute']['size'] + 1); } $prop = array(); $opt = array(); if (isset($tag['attribute']['name']) AND !$this->empty_string($tag['attribute']['name'])) { $name = $tag['attribute']['name']; } else { break; } $w = 0; if (isset($tag['attribute']['opt']) AND !$this->empty_string($tag['attribute']['opt'])) { $options = explode('#!NwL!#', $tag['attribute']['opt']); $values = array(); foreach ($options as $val) { if (strpos($val, '#!TaB!#') !== false) { $opts = explode('#!TaB!#', $val); $values[] = $opts; $w = max($w, $this->GetStringWidth($opts[1])); } else { $values[] = $val; $w = max($w, $this->GetStringWidth($val)); } } } else { break; } $w *= 2; if (isset($tag['attribute']['multiple']) AND ($tag['attribute']['multiple']='multiple')) { $prop['multipleSelection'] = 'true'; $this->ListBox($name, $w, $h, $values, $prop, $opt, '', '', false); } else { $this->ComboBox($name, $w, $h, $values, $prop, $opt, '', '', false); } break; } case 'tcpdf': { if (defined('K_TCPDF_CALLS_IN_HTML') AND (K_TCPDF_CALLS_IN_HTML === true)) { // Special tag used to call TCPDF methods if (isset($tag['attribute']['method'])) { $tcpdf_method = $tag['attribute']['method']; if (method_exists($this, $tcpdf_method)) { if (isset($tag['attribute']['params']) AND (!empty($tag['attribute']['params']))) { $params = unserialize(urldecode($tag['attribute']['params'])); call_user_func_array(array($this, $tcpdf_method), $params); } else { $this->$tcpdf_method(); } $this->newline = true; } } } break; } default: { break; } } // define tags that support borders and background colors $bordertags = array('blockquote','br','dd','dl','div','dt','h1','h2','h3','h4','h5','h6','hr','li','ol','p','pre','ul','tcpdf','table'); if (in_array($tag['value'], $bordertags)) { // set border $dom[$key]['borderposition'] = $this->getBorderStartPosition(); } if ($dom[$key]['self'] AND isset($dom[$key]['attribute']['pagebreakafter'])) { $pba = $dom[$key]['attribute']['pagebreakafter']; // check for pagebreak if (($pba == 'true') OR ($pba == 'left') OR ($pba == 'right')) { // add a page (or trig AcceptPageBreak() for multicolumn mode) $this->checkPageBreak($this->PageBreakTrigger + 1); } if ((($pba == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0)))) OR (($pba == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) { // add a page (or trig AcceptPageBreak() for multicolumn mode) $this->checkPageBreak($this->PageBreakTrigger + 1); } } return $dom; } /** * Process closing tags. * @param $dom (array) html dom array * @param $key (int) current element id * @param $cell (boolean) if true add the default left (or right if RTL) padding to each new line (default false). * @param $maxbottomliney (int) maximum y value of current line * @return $dom array * @protected */ protected function closeHTMLTagHandler($dom, $key, $cell, $maxbottomliney=0) { $tag = $dom[$key]; $parent = $dom[($dom[$key]['parent'])]; $lasttag = ((!isset($dom[($key + 1)])) OR ((!isset($dom[($key + 2)])) AND ($dom[($key + 1)]['value'] == 'marker'))); $in_table_head = false; // maximum x position (used to draw borders) if ($this->rtl) { $xmax = $this->w; } else { $xmax = 0; } if ($tag['block']) { $hbz = 0; // distance from y to line bottom $hb = 0; // vertical space between block tags // calculate vertical space for block tags if (isset($this->tagvspaces[$tag['value']][1]['h']) AND ($this->tagvspaces[$tag['value']][1]['h'] >= 0)) { $pre_h = $this->tagvspaces[$tag['value']][1]['h']; } elseif (isset($parent['fontsize'])) { $pre_h = (($parent['fontsize'] / $this->k) * $this->cell_height_ratio); } else { $pre_h = $this->FontSize * $this->cell_height_ratio; } if (isset($this->tagvspaces[$tag['value']][1]['n'])) { $n = $this->tagvspaces[$tag['value']][1]['n']; } elseif (preg_match('/[h][0-9]/', $tag['value']) > 0) { $n = 0.6; } else { $n = 1; } if ((!isset($this->tagvspaces[$tag['value']])) AND ($tag['value'] == 'div')) { $hb = 0; } else { $hb = ($n * $pre_h); } if ($maxbottomliney > $this->PageBreakTrigger) { $hbz = ($this->FontSize * $this->cell_height_ratio); } elseif ($this->y < $maxbottomliney) { $hbz = ($maxbottomliney - $this->y); } } // Closing tag switch($tag['value']) { case 'tr': { $table_el = $dom[($dom[$key]['parent'])]['parent']; if (!isset($parent['endy'])) { $dom[($dom[$key]['parent'])]['endy'] = $this->y; $parent['endy'] = $this->y; } if (!isset($parent['endpage'])) { $dom[($dom[$key]['parent'])]['endpage'] = $this->page; $parent['endpage'] = $this->page; } if (!isset($parent['endcolumn'])) { $dom[($dom[$key]['parent'])]['endcolumn'] = $this->current_column; $parent['endcolumn'] = $this->current_column; } // update row-spanned cells if (isset($dom[$table_el]['rowspans'])) { foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) { $dom[$table_el]['rowspans'][$k]['rowspan'] -= 1; if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) { if (($dom[$table_el]['rowspans'][$k]['endpage'] == $parent['endpage']) AND ($dom[$table_el]['rowspans'][$k]['endcolumn'] == $parent['endcolumn'])) { $dom[($dom[$key]['parent'])]['endy'] = max($dom[$table_el]['rowspans'][$k]['endy'], $parent['endy']); } elseif (($dom[$table_el]['rowspans'][$k]['endpage'] > $parent['endpage']) OR ($dom[$table_el]['rowspans'][$k]['endcolumn'] > $parent['endcolumn'])) { $dom[($dom[$key]['parent'])]['endy'] = $dom[$table_el]['rowspans'][$k]['endy']; $dom[($dom[$key]['parent'])]['endpage'] = $dom[$table_el]['rowspans'][$k]['endpage']; $dom[($dom[$key]['parent'])]['endcolumn'] = $dom[$table_el]['rowspans'][$k]['endcolumn']; } } } // report new endy and endpage to the rowspanned cells foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) { if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) { $dom[$table_el]['rowspans'][$k]['endpage'] = max($dom[$table_el]['rowspans'][$k]['endpage'], $dom[($dom[$key]['parent'])]['endpage']); $dom[($dom[$key]['parent'])]['endpage'] = $dom[$table_el]['rowspans'][$k]['endpage']; $dom[$table_el]['rowspans'][$k]['endcolumn'] = max($dom[$table_el]['rowspans'][$k]['endcolumn'], $dom[($dom[$key]['parent'])]['endcolumn']); $dom[($dom[$key]['parent'])]['endcolumn'] = $dom[$table_el]['rowspans'][$k]['endcolumn']; $dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$table_el]['rowspans'][$k]['endy'], $dom[($dom[$key]['parent'])]['endy']); $dom[($dom[$key]['parent'])]['endy'] = $dom[$table_el]['rowspans'][$k]['endy']; } } // update remaining rowspanned cells foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) { if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) { $dom[$table_el]['rowspans'][$k]['endpage'] = $dom[($dom[$key]['parent'])]['endpage']; $dom[$table_el]['rowspans'][$k]['endcolumn'] = $dom[($dom[$key]['parent'])]['endcolumn']; $dom[$table_el]['rowspans'][$k]['endy'] = $dom[($dom[$key]['parent'])]['endy']; } } } $this->setPage($dom[($dom[$key]['parent'])]['endpage']); if ($this->num_columns > 1) { $this->selectColumn($dom[($dom[$key]['parent'])]['endcolumn']); } $this->y = $dom[($dom[$key]['parent'])]['endy']; if (isset($dom[$table_el]['attribute']['cellspacing'])) { $this->y += $this->getHTMLUnitToUnits($dom[$table_el]['attribute']['cellspacing'], 1, 'px'); } elseif (isset($dom[$table_el]['border-spacing'])) { $this->y += $dom[$table_el]['border-spacing']['V']; } $this->Ln(0, $cell); if ($this->current_column == $parent['startcolumn']) { $this->x = $parent['startx']; } // account for booklet mode if ($this->page > $parent['startpage']) { if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$parent['startpage']]['orm'])) { $this->x -= ($this->pagedim[$this->page]['orm'] - $this->pagedim[$parent['startpage']]['orm']); } elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$parent['startpage']]['olm'])) { $this->x += ($this->pagedim[$this->page]['olm'] - $this->pagedim[$parent['startpage']]['olm']); } } break; } case 'tablehead': // closing tag used for the thead part $in_table_head = true; $this->inthead = false; case 'table': { $table_el = $parent; // set default border if (isset($table_el['attribute']['border']) AND ($table_el['attribute']['border'] > 0)) { // set default border $border = array('LTRB' => array('width' => $this->getCSSBorderWidth($table_el['attribute']['border']), 'cap'=>'square', 'join'=>'miter', 'dash'=> 0, 'color'=>array(0,0,0))); } else { $border = 0; } $default_border = $border; // fix bottom line alignment of last line before page break foreach ($dom[($dom[$key]['parent'])]['trids'] as $j => $trkey) { // update row-spanned cells if (isset($dom[($dom[$key]['parent'])]['rowspans'])) { foreach ($dom[($dom[$key]['parent'])]['rowspans'] as $k => $trwsp) { if ($trwsp['trid'] == $trkey) { $dom[($dom[$key]['parent'])]['rowspans'][$k]['mrowspan'] -= 1; } if (isset($prevtrkey) AND ($trwsp['trid'] == $prevtrkey) AND ($trwsp['mrowspan'] >= 0)) { $dom[($dom[$key]['parent'])]['rowspans'][$k]['trid'] = $trkey; } } } if (isset($prevtrkey) AND ($dom[$trkey]['startpage'] > $dom[$prevtrkey]['endpage'])) { $pgendy = $this->pagedim[$dom[$prevtrkey]['endpage']]['hk'] - $this->pagedim[$dom[$prevtrkey]['endpage']]['bm']; $dom[$prevtrkey]['endy'] = $pgendy; // update row-spanned cells if (isset($dom[($dom[$key]['parent'])]['rowspans'])) { foreach ($dom[($dom[$key]['parent'])]['rowspans'] as $k => $trwsp) { if (($trwsp['trid'] == $trkey) AND ($trwsp['mrowspan'] > 1) AND ($trwsp['endpage'] == $dom[$prevtrkey]['endpage'])) { $dom[($dom[$key]['parent'])]['rowspans'][$k]['endy'] = $pgendy; $dom[($dom[$key]['parent'])]['rowspans'][$k]['mrowspan'] = -1; } } } } $prevtrkey = $trkey; $table_el = $dom[($dom[$key]['parent'])]; } // for each row if (count($table_el['trids']) > 0) { unset($xmax); } foreach ($table_el['trids'] as $j => $trkey) { $parent = $dom[$trkey]; if (!isset($xmax)) { $xmax = $parent['cellpos'][(count($parent['cellpos']) - 1)]['endx']; } // for each cell on the row foreach ($parent['cellpos'] as $k => $cellpos) { if (isset($cellpos['rowspanid']) AND ($cellpos['rowspanid'] >= 0)) { $cellpos['startx'] = $table_el['rowspans'][($cellpos['rowspanid'])]['startx']; $cellpos['endx'] = $table_el['rowspans'][($cellpos['rowspanid'])]['endx']; $endy = $table_el['rowspans'][($cellpos['rowspanid'])]['endy']; $startpage = $table_el['rowspans'][($cellpos['rowspanid'])]['startpage']; $endpage = $table_el['rowspans'][($cellpos['rowspanid'])]['endpage']; $startcolumn = $table_el['rowspans'][($cellpos['rowspanid'])]['startcolumn']; $endcolumn = $table_el['rowspans'][($cellpos['rowspanid'])]['endcolumn']; } else { $endy = $parent['endy']; $startpage = $parent['startpage']; $endpage = $parent['endpage']; $startcolumn = $parent['startcolumn']; $endcolumn = $parent['endcolumn']; } if ($this->num_columns == 0) { $this->num_columns = 1; } if (isset($cellpos['border'])) { $border = $cellpos['border']; } if (isset($cellpos['bgcolor']) AND ($cellpos['bgcolor']) !== false) { $this->SetFillColorArray($cellpos['bgcolor']); $fill = true; } else { $fill = false; } $x = $cellpos['startx']; $y = $parent['starty']; $starty = $y; $w = abs($cellpos['endx'] - $cellpos['startx']); // get border modes $border_start = $this->getBorderMode($border, $position='start'); $border_end = $this->getBorderMode($border, $position='end'); $border_middle = $this->getBorderMode($border, $position='middle'); // design borders around HTML cells. for ($page = $startpage; $page <= $endpage; ++$page) { // for each page $ccode = ''; $this->setPage($page); if ($this->num_columns < 2) { // single-column mode $this->x = $x; $this->y = $this->tMargin; } // account for margin changes if ($page > $startpage) { if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) { $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']); } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) { $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']); } } if ($startpage == $endpage) { // single page $deltacol = 0; $deltath = 0; for ($column = $startcolumn; $column <= $endcolumn; ++$column) { // for each column $this->selectColumn($column); if ($startcolumn == $endcolumn) { // single column $cborder = $border; $h = $endy - $parent['starty']; $this->y = $y; $this->x = $x; } elseif ($column == $startcolumn) { // first column $cborder = $border_start; $this->y = $starty; $this->x = $x; $h = $this->h - $this->y - $this->bMargin; if ($this->rtl) { $deltacol = $this->x + $this->rMargin - $this->w; } else { $deltacol = $this->x - $this->lMargin; } } elseif ($column == $endcolumn) { // end column $cborder = $border_end; if (isset($this->columns[$column]['th']['\''.$page.'\''])) { $this->y = $this->columns[$column]['th']['\''.$page.'\'']; } $this->x += $deltacol; $h = $endy - $this->y; } else { // middle column $cborder = $border_middle; if (isset($this->columns[$column]['th']['\''.$page.'\''])) { $this->y = $this->columns[$column]['th']['\''.$page.'\'']; } $this->x += $deltacol; $h = $this->h - $this->y - $this->bMargin; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } elseif ($page == $startpage) { // first page $deltacol = 0; $deltath = 0; for ($column = $startcolumn; $column < $this->num_columns; ++$column) { // for each column $this->selectColumn($column); if ($column == $startcolumn) { // first column $cborder = $border_start; $this->y = $starty; $this->x = $x; $h = $this->h - $this->y - $this->bMargin; if ($this->rtl) { $deltacol = $this->x + $this->rMargin - $this->w; } else { $deltacol = $this->x - $this->lMargin; } } else { // middle column $cborder = $border_middle; if (isset($this->columns[$column]['th']['\''.$page.'\''])) { $this->y = $this->columns[$column]['th']['\''.$page.'\'']; } $this->x += $deltacol; $h = $this->h - $this->y - $this->bMargin; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } elseif ($page == $endpage) { // last page $deltacol = 0; $deltath = 0; for ($column = 0; $column <= $endcolumn; ++$column) { // for each column $this->selectColumn($column); if ($column == $endcolumn) { // end column $cborder = $border_end; if (isset($this->columns[$column]['th']['\''.$page.'\''])) { $this->y = $this->columns[$column]['th']['\''.$page.'\'']; } $this->x += $deltacol; $h = $endy - $this->y; } else { // middle column $cborder = $border_middle; if (isset($this->columns[$column]['th']['\''.$page.'\''])) { $this->y = $this->columns[$column]['th']['\''.$page.'\'']; } $this->x += $deltacol; $h = $this->h - $this->y - $this->bMargin; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } else { // middle page $deltacol = 0; $deltath = 0; for ($column = 0; $column < $this->num_columns; ++$column) { // for each column $this->selectColumn($column); $cborder = $border_middle; if (isset($this->columns[$column]['th']['\''.$page.'\''])) { $this->y = $this->columns[$column]['th']['\''.$page.'\'']; } $this->x += $deltacol; $h = $this->h - $this->y - $this->bMargin; $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } if ($cborder OR $fill) { $offsetlen = strlen($ccode); // draw border and fill if ($this->inxobj) { // we are inside an XObject template if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) { $pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']); $pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey]; $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen; } else { $pagemark = $this->xobjects[$this->xobjid]['intmrk']; $this->xobjects[$this->xobjid]['intmrk'] += $offsetlen; } $pagebuff = $this->xobjects[$this->xobjid]['outdata']; $pstart = substr($pagebuff, 0, $pagemark); $pend = substr($pagebuff, $pagemark); $this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend; } else { // draw border and fill if (end($this->transfmrk[$this->page]) !== false) { $pagemarkkey = key($this->transfmrk[$this->page]); $pagemark = $this->transfmrk[$this->page][$pagemarkkey]; $this->transfmrk[$this->page][$pagemarkkey] += $offsetlen; } elseif ($this->InFooter) { $pagemark = $this->footerpos[$this->page]; $this->footerpos[$this->page] += $offsetlen; } else { $pagemark = $this->intmrk[$this->page]; $this->intmrk[$this->page] += $offsetlen; } $pagebuff = $this->getPageBuffer($this->page); $pstart = substr($pagebuff, 0, $pagemark); $pend = substr($pagebuff, $pagemark); $this->setPageBuffer($this->page, $pstart.$ccode.$pend); } } } // end for each page // restore default border $border = $default_border; } // end for each cell on the row if (isset($table_el['attribute']['cellspacing'])) { $this->y += $this->getHTMLUnitToUnits($table_el['attribute']['cellspacing'], 1, 'px'); } elseif (isset($table_el['border-spacing'])) { $this->y += $table_el['border-spacing']['V']; } $this->Ln(0, $cell); $this->x = $parent['startx']; if ($endpage > $startpage) { if (($this->rtl) AND ($this->pagedim[$endpage]['orm'] != $this->pagedim[$startpage]['orm'])) { $this->x += ($this->pagedim[$endpage]['orm'] - $this->pagedim[$startpage]['orm']); } elseif ((!$this->rtl) AND ($this->pagedim[$endpage]['olm'] != $this->pagedim[$startpage]['olm'])) { $this->x += ($this->pagedim[$endpage]['olm'] - $this->pagedim[$startpage]['olm']); } } } if (!$in_table_head) { // we are not inside a thead section $this->cell_padding = $table_el['old_cell_padding']; // reset row height $this->resetLastH(); if (($this->page == ($this->numpages - 1)) AND ($this->pageopen[$this->numpages])) { $plendiff = ($this->pagelen[$this->numpages] - $this->emptypagemrk[$this->numpages]); if (($plendiff > 0) AND ($plendiff < 60)) { $pagediff = substr($this->getPageBuffer($this->numpages), $this->emptypagemrk[$this->numpages], $plendiff); if (substr($pagediff, 0, 5) == 'BT /F') { // the difference is only a font setting $plendiff = 0; } } if ($plendiff == 0) { // remove last blank page $this->deletePage($this->numpages); } } if (isset($this->theadMargins['top'])) { // restore top margin $this->tMargin = $this->theadMargins['top']; } if (!isset($table_el['attribute']['nested']) OR ($table_el['attribute']['nested'] != 'true')) { // reset main table header $this->thead = ''; $this->theadMargins = array(); $this->pagedim[$this->page]['tm'] = $this->tMargin; } } $parent = $table_el; break; } case 'a': { $this->HREF = ''; break; } case 'sup': { $this->SetXY($this->GetX(), $this->GetY() + ((0.7 * $parent['fontsize']) / $this->k)); break; } case 'sub': { $this->SetXY($this->GetX(), $this->GetY() - ((0.3 * $parent['fontsize'])/$this->k)); break; } case 'div': { $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); break; } case 'blockquote': { if ($this->rtl) { $this->rMargin -= $this->listindent; } else { $this->lMargin -= $this->listindent; } --$this->listindentlevel; $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); break; } case 'p': { $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); break; } case 'pre': { $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); $this->premode = false; break; } case 'dl': { --$this->listnum; if ($this->listnum <= 0) { $this->listnum = 0; $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); } else { $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); } $this->resetLastH(); break; } case 'dt': { $this->lispacer = ''; $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); break; } case 'dd': { $this->lispacer = ''; if ($this->rtl) { $this->rMargin -= $this->listindent; } else { $this->lMargin -= $this->listindent; } --$this->listindentlevel; $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); break; } case 'ul': case 'ol': { --$this->listnum; $this->lispacer = ''; if ($this->rtl) { $this->rMargin -= $this->listindent; } else { $this->lMargin -= $this->listindent; } --$this->listindentlevel; if ($this->listnum <= 0) { $this->listnum = 0; $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); } else { $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); } $this->resetLastH(); break; } case 'li': { $this->lispacer = ''; $this->addHTMLVertSpace(0, 0, $cell, false, $lasttag); break; } case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': { $this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag); break; } // Form fields (since 4.8.000 - 2009-09-07) case 'form': { $this->form_action = ''; $this->form_enctype = 'application/x-www-form-urlencoded'; break; } default : { break; } } // draw border and background (if any) $this->drawHTMLTagBorder($parent, $xmax); if (isset($dom[($dom[$key]['parent'])]['attribute']['pagebreakafter'])) { $pba = $dom[($dom[$key]['parent'])]['attribute']['pagebreakafter']; // check for pagebreak if (($pba == 'true') OR ($pba == 'left') OR ($pba == 'right')) { // add a page (or trig AcceptPageBreak() for multicolumn mode) $this->checkPageBreak($this->PageBreakTrigger + 1); } if ((($pba == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0)))) OR (($pba == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) { // add a page (or trig AcceptPageBreak() for multicolumn mode) $this->checkPageBreak($this->PageBreakTrigger + 1); } } $this->tmprtl = false; return $dom; } /** * Add vertical spaces if needed. * @param $hbz (string) Distance between current y and line bottom. * @param $hb (string) The height of the break. * @param $cell (boolean) if true add the default left (or right if RTL) padding to each new line (default false). * @param $firsttag (boolean) set to true when the tag is the first. * @param $lasttag (boolean) set to true when the tag is the last. * @protected */ protected function addHTMLVertSpace($hbz=0, $hb=0, $cell=false, $firsttag=false, $lasttag=false) { if ($firsttag) { $this->Ln(0, $cell); $this->htmlvspace = 0; return; } if ($lasttag) { $this->Ln($hbz, $cell); $this->htmlvspace = 0; return; } if ($hb < $this->htmlvspace) { $hd = 0; } else { $hd = $hb - $this->htmlvspace; $this->htmlvspace = $hb; } $this->Ln(($hbz + $hd), $cell); } /** * Return the starting coordinates to draw an html border * @return array containing top-left border coordinates * @protected * @since 5.7.000 (2010-08-03) */ protected function getBorderStartPosition() { if ($this->rtl) { $xmax = $this->lMargin; } else { $xmax = $this->w - $this->rMargin; } return array('page' => $this->page, 'column' => $this->current_column, 'x' => $this->x, 'y' => $this->y, 'xmax' => $xmax); } /** * Draw an HTML block border and fill * @param $tag (array) array of tag properties. * @param $xmax (int) end X coordinate for border. * @protected * @since 5.7.000 (2010-08-03) */ protected function drawHTMLTagBorder($tag, $xmax) { if (!isset($tag['borderposition'])) { // nothing to draw return; } $prev_x = $this->x; $prev_y = $this->y; $prev_lasth = $this->lasth; $border = 0; $fill = false; $this->lasth = 0; if (isset($tag['border']) AND !empty($tag['border'])) { // get border style $border = $tag['border']; if (!$this->empty_string($this->thead) AND (!$this->inthead)) { // border for table header $border = $this->getBorderMode($border, $position='middle'); } } if (isset($tag['bgcolor']) AND ($tag['bgcolor'] !== false)) { // get background color $old_bgcolor = $this->bgcolor; $this->SetFillColorArray($tag['bgcolor']); $fill = true; } if (!$border AND !$fill) { // nothing to draw return; } if (isset($tag['attribute']['cellspacing'])) { $clsp = $this->getHTMLUnitToUnits($tag['attribute']['cellspacing'], 1, 'px'); $cellspacing = array('H' => $clsp, 'V' => $clsp); } elseif (isset($tag['border-spacing'])) { $cellspacing = $tag['border-spacing']; } else { $cellspacing = array('H' => 0, 'V' => 0); } if (($tag['value'] != 'table') AND (is_array($border)) AND (!empty($border))) { // draw the border externally respect the sqare edge. $border['mode'] = 'ext'; } if ($this->rtl) { if ($xmax >= $tag['borderposition']['x']) { $xmax = $tag['borderposition']['xmax']; } $w = ($tag['borderposition']['x'] - $xmax); } else { if ($xmax <= $tag['borderposition']['x']) { $xmax = $tag['borderposition']['xmax']; } $w = ($xmax - $tag['borderposition']['x']); } if ($w <= 0) { return; } $w += $cellspacing['H']; $startpage = $tag['borderposition']['page']; $startcolumn = $tag['borderposition']['column']; $x = $tag['borderposition']['x']; $y = $tag['borderposition']['y']; $endpage = $this->page; $starty = $tag['borderposition']['y'] - $cellspacing['V']; $currentY = $this->y; $this->x = $x; // get latest column $endcolumn = $this->current_column; if ($this->num_columns == 0) { $this->num_columns = 1; } // get border modes $border_start = $this->getBorderMode($border, $position='start'); $border_end = $this->getBorderMode($border, $position='end'); $border_middle = $this->getBorderMode($border, $position='middle'); // temporary disable page regions $temp_page_regions = $this->page_regions; $this->page_regions = array(); // design borders around HTML cells. for ($page = $startpage; $page <= $endpage; ++$page) { // for each page $ccode = ''; $this->setPage($page); if ($this->num_columns < 2) { // single-column mode $this->x = $x; $this->y = $this->tMargin; } // account for margin changes if ($page > $startpage) { if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) { $this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']); } elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) { $this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']); } } if ($startpage == $endpage) { // single page for ($column = $startcolumn; $column <= $endcolumn; ++$column) { // for each column $this->selectColumn($column); if ($startcolumn == $endcolumn) { // single column $cborder = $border; $h = ($currentY - $y) + $cellspacing['V']; $this->y = $starty; } elseif ($column == $startcolumn) { // first column $cborder = $border_start; $this->y = $starty; $h = $this->h - $this->y - $this->bMargin; } elseif ($column == $endcolumn) { // end column $cborder = $border_end; $h = $currentY - $this->y; } else { // middle column $cborder = $border_middle; $h = $this->h - $this->y - $this->bMargin; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } elseif ($page == $startpage) { // first page for ($column = $startcolumn; $column < $this->num_columns; ++$column) { // for each column $this->selectColumn($column); if ($column == $startcolumn) { // first column $cborder = $border_start; $this->y = $starty; $h = $this->h - $this->y - $this->bMargin; } else { // middle column $cborder = $border_middle; $h = $this->h - $this->y - $this->bMargin; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } elseif ($page == $endpage) { // last page for ($column = 0; $column <= $endcolumn; ++$column) { // for each column $this->selectColumn($column); if ($column == $endcolumn) { // end column $cborder = $border_end; $h = $currentY - $this->y; } else { // middle column $cborder = $border_middle; $h = $this->h - $this->y - $this->bMargin; } $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } else { // middle page for ($column = 0; $column < $this->num_columns; ++$column) { // for each column $this->selectColumn($column); $cborder = $border_middle; $h = $this->h - $this->y - $this->bMargin; $ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n"; } // end for each column } if ($cborder OR $fill) { $offsetlen = strlen($ccode); // draw border and fill if ($this->inxobj) { // we are inside an XObject template if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) { $pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']); $pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey]; $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen; } else { $pagemark = $this->xobjects[$this->xobjid]['intmrk']; $this->xobjects[$this->xobjid]['intmrk'] += $offsetlen; } $pagebuff = $this->xobjects[$this->xobjid]['outdata']; $pstart = substr($pagebuff, 0, $pagemark); $pend = substr($pagebuff, $pagemark); $this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend; } else { if (end($this->transfmrk[$this->page]) !== false) { $pagemarkkey = key($this->transfmrk[$this->page]); $pagemark = $this->transfmrk[$this->page][$pagemarkkey]; $this->transfmrk[$this->page][$pagemarkkey] += $offsetlen; } elseif ($this->InFooter) { $pagemark = $this->footerpos[$this->page]; $this->footerpos[$this->page] += $offsetlen; } else { $pagemark = $this->intmrk[$this->page]; $this->intmrk[$this->page] += $offsetlen; } $pagebuff = $this->getPageBuffer($this->page); $pstart = substr($pagebuff, 0, $this->bordermrk[$this->page]); $pend = substr($pagebuff, $this->bordermrk[$this->page]); $this->setPageBuffer($this->page, $pstart.$ccode.$pend); $this->bordermrk[$this->page] += $offsetlen; $this->cntmrk[$this->page] += $offsetlen; } } } // end for each page // restore page regions $this->page_regions = $temp_page_regions; if (isset($old_bgcolor)) { // restore background color $this->SetFillColorArray($old_bgcolor); } // restore pointer position $this->x = $prev_x; $this->y = $prev_y; $this->lasth = $prev_lasth; } /** * Set the default bullet to be used as LI bullet symbol * @param $symbol (string) character or string to be used (legal values are: '' = automatic, '!' = auto bullet, '#' = auto numbering, 'disc', 'disc', 'circle', 'square', '1', 'decimal', 'decimal-leading-zero', 'i', 'lower-roman', 'I', 'upper-roman', 'a', 'lower-alpha', 'lower-latin', 'A', 'upper-alpha', 'upper-latin', 'lower-greek', 'img|type|width|height|image.ext') * @public * @since 4.0.028 (2008-09-26) */ public function setLIsymbol($symbol='!') { // check for custom image symbol if (substr($symbol, 0, 4) == 'img|') { $this->lisymbol = $symbol; return; } $symbol = strtolower($symbol); switch ($symbol) { case '!' : case '#' : case 'disc' : case 'circle' : case 'square' : case '1': case 'decimal': case 'decimal-leading-zero': case 'i': case 'lower-roman': case 'I': case 'upper-roman': case 'a': case 'lower-alpha': case 'lower-latin': case 'A': case 'upper-alpha': case 'upper-latin': case 'lower-greek': { $this->lisymbol = $symbol; break; } default : { $this->lisymbol = ''; } } } /** * Set the booklet mode for double-sided pages. * @param $booklet (boolean) true set the booklet mode on, false otherwise. * @param $inner (float) Inner page margin. * @param $outer (float) Outer page margin. * @public * @since 4.2.000 (2008-10-29) */ public function SetBooklet($booklet=true, $inner=-1, $outer=-1) { $this->booklet = $booklet; if ($inner >= 0) { $this->lMargin = $inner; } if ($outer >= 0) { $this->rMargin = $outer; } } /** * Swap the left and right margins. * @param $reverse (boolean) if true swap left and right margins. * @protected * @since 4.2.000 (2008-10-29) */ protected function swapMargins($reverse=true) { if ($reverse) { // swap left and right margins $mtemp = $this->original_lMargin; $this->original_lMargin = $this->original_rMargin; $this->original_rMargin = $mtemp; $deltam = $this->original_lMargin - $this->original_rMargin; $this->lMargin += $deltam; $this->rMargin -= $deltam; } } /** * Set the vertical spaces for HTML tags. * The array must have the following structure (example): * $tagvs = array('h1' => array(0 => array('h' => '', 'n' => 2), 1 => array('h' => 1.3, 'n' => 1))); * The first array level contains the tag names, * the second level contains 0 for opening tags or 1 for closing tags, * the third level contains the vertical space unit (h) and the number spaces to add (n). * If the h parameter is not specified, default values are used. * @param $tagvs (array) array of tags and relative vertical spaces. * @public * @since 4.2.001 (2008-10-30) */ public function setHtmlVSpace($tagvs) { $this->tagvspaces = $tagvs; } /** * Set custom width for list indentation. * @param $width (float) width of the indentation. Use negative value to disable it. * @public * @since 4.2.007 (2008-11-12) */ public function setListIndentWidth($width) { return $this->customlistindent = floatval($width); } /** * Set the top/bottom cell sides to be open or closed when the cell cross the page. * @param $isopen (boolean) if true keeps the top/bottom border open for the cell sides that cross the page. * @public * @since 4.2.010 (2008-11-14) */ public function setOpenCell($isopen) { $this->opencell = $isopen; } /** * Set the color and font style for HTML links. * @param $color (array) RGB array of colors * @param $fontstyle (string) additional font styles to add * @public * @since 4.4.003 (2008-12-09) */ public function setHtmlLinksStyle($color=array(0,0,255), $fontstyle='U') { $this->htmlLinkColorArray = $color; $this->htmlLinkFontStyle = $fontstyle; } /** * Convert HTML string containing value and unit of measure to user's units or points. * @param $htmlval (string) string containing values and unit * @param $refsize (string) reference value in points * @param $defaultunit (string) default unit (can be one of the following: %, em, ex, px, in, mm, pc, pt). * @param $points (boolean) if true returns points, otherwise returns value in user's units * @return float value in user's unit or point if $points=true * @public * @since 4.4.004 (2008-12-10) */ public function getHTMLUnitToUnits($htmlval, $refsize=1, $defaultunit='px', $points=false) { $supportedunits = array('%', 'em', 'ex', 'px', 'in', 'cm', 'mm', 'pc', 'pt'); $retval = 0; $value = 0; $unit = 'px'; $k = $this->k; if ($points) { $k = 1; } if (in_array($defaultunit, $supportedunits)) { $unit = $defaultunit; } if (is_numeric($htmlval)) { $value = floatval($htmlval); } elseif (preg_match('/([0-9\.\-\+]+)/', $htmlval, $mnum)) { $value = floatval($mnum[1]); if (preg_match('/([a-z%]+)/', $htmlval, $munit)) { if (in_array($munit[1], $supportedunits)) { $unit = $munit[1]; } } } switch ($unit) { // percentage case '%': { $retval = (($value * $refsize) / 100); break; } // relative-size case 'em': { $retval = ($value * $refsize); break; } // height of lower case 'x' (about half the font-size) case 'ex': { $retval = $value * ($refsize / 2); break; } // absolute-size case 'in': { $retval = ($value * $this->dpi) / $k; break; } // centimeters case 'cm': { $retval = ($value / 2.54 * $this->dpi) / $k; break; } // millimeters case 'mm': { $retval = ($value / 25.4 * $this->dpi) / $k; break; } // one pica is 12 points case 'pc': { $retval = ($value * 12) / $k; break; } // points case 'pt': { $retval = $value / $k; break; } // pixels case 'px': { $retval = $this->pixelsToUnits($value); break; } } return $retval; } /** * Returns the Roman representation of an integer number * @param $number (int) number to convert * @return string roman representation of the specified number * @since 4.4.004 (2008-12-10) * @public */ public function intToRoman($number) { $roman = ''; while ($number >= 1000) { $roman .= 'M'; $number -= 1000; } while ($number >= 900) { $roman .= 'CM'; $number -= 900; } while ($number >= 500) { $roman .= 'D'; $number -= 500; } while ($number >= 400) { $roman .= 'CD'; $number -= 400; } while ($number >= 100) { $roman .= 'C'; $number -= 100; } while ($number >= 90) { $roman .= 'XC'; $number -= 90; } while ($number >= 50) { $roman .= 'L'; $number -= 50; } while ($number >= 40) { $roman .= 'XL'; $number -= 40; } while ($number >= 10) { $roman .= 'X'; $number -= 10; } while ($number >= 9) { $roman .= 'IX'; $number -= 9; } while ($number >= 5) { $roman .= 'V'; $number -= 5; } while ($number >= 4) { $roman .= 'IV'; $number -= 4; } while ($number >= 1) { $roman .= 'I'; --$number; } return $roman; } /** * Output an HTML list bullet or ordered item symbol * @param $listdepth (int) list nesting level * @param $listtype (string) type of list * @param $size (float) current font size * @protected * @since 4.4.004 (2008-12-10) */ protected function putHtmlListBullet($listdepth, $listtype='', $size=10) { $size /= $this->k; $fill = ''; $bgcolor = $this->bgcolor; $color = $this->fgcolor; $strokecolor = $this->strokecolor; $width = 0; $textitem = ''; $tmpx = $this->x; $lspace = $this->GetStringWidth(' '); if ($listtype == '^') { // special symbol used for avoid justification of rect bullet $this->lispacer = ''; return; } elseif ($listtype == '!') { // set default list type for unordered list $deftypes = array('disc', 'circle', 'square'); $listtype = $deftypes[($listdepth - 1) % 3]; } elseif ($listtype == '#') { // set default list type for ordered list $listtype = 'decimal'; } elseif (substr($listtype, 0, 4) == 'img|') { // custom image type ('img|type|width|height|image.ext') $img = explode('|', $listtype); $listtype = 'img'; } switch ($listtype) { // unordered types case 'none': { break; } case 'disc': { $r = $size / 6; $lspace += (2 * $r); if ($this->rtl) { $this->x += $lspace; } else { $this->x -= $lspace; } $this->Circle(($this->x + $r), ($this->y + ($this->lasth / 2)), $r, 0, 360, 'F', array(), $color, 8); break; } case 'circle': { $r = $size / 6; $lspace += (2 * $r); if ($this->rtl) { $this->x += $lspace; } else { $this->x -= $lspace; } $prev_line_style = $this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor; $new_line_style = array('width' => ($r / 3), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'phase' => 0, 'color'=>$color); $this->Circle(($this->x + $r), ($this->y + ($this->lasth / 2)), ($r * (1 - (1/6))), 0, 360, 'D', $new_line_style, array(), 8); $this->_out($prev_line_style); // restore line settings break; } case 'square': { $l = $size / 3; $lspace += $l; if ($this->rtl) {; $this->x += $lspace; } else { $this->x -= $lspace; } $this->Rect($this->x, ($this->y + (($this->lasth - $l) / 2)), $l, $l, 'F', array(), $color); break; } case 'img': { // 1=>type, 2=>width, 3=>height, 4=>image.ext $lspace += $img[2]; if ($this->rtl) {; $this->x += $lspace; } else { $this->x -= $lspace; } $imgtype = strtolower($img[1]); $prev_y = $this->y; switch ($imgtype) { case 'svg': { $this->ImageSVG($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], '', 'T', '', 0, false); break; } case 'ai': case 'eps': { $this->ImageEps($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], '', true, 'T', '', 0, false); break; } default: { $this->Image($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], $img[1], '', 'T', false, 300, '', false, false, 0, false, false, false); break; } } $this->y = $prev_y; break; } // ordered types // $this->listcount[$this->listnum]; // $textitem case '1': case 'decimal': { $textitem = $this->listcount[$this->listnum]; break; } case 'decimal-leading-zero': { $textitem = sprintf('%02d', $this->listcount[$this->listnum]); break; } case 'i': case 'lower-roman': { $textitem = strtolower($this->intToRoman($this->listcount[$this->listnum])); break; } case 'I': case 'upper-roman': { $textitem = $this->intToRoman($this->listcount[$this->listnum]); break; } case 'a': case 'lower-alpha': case 'lower-latin': { $textitem = chr(97 + $this->listcount[$this->listnum] - 1); break; } case 'A': case 'upper-alpha': case 'upper-latin': { $textitem = chr(65 + $this->listcount[$this->listnum] - 1); break; } case 'lower-greek': { $textitem = $this->unichr(945 + $this->listcount[$this->listnum] - 1); break; } /* // Types to be implemented (special handling) case 'hebrew': { break; } case 'armenian': { break; } case 'georgian': { break; } case 'cjk-ideographic': { break; } case 'hiragana': { break; } case 'katakana': { break; } case 'hiragana-iroha': { break; } case 'katakana-iroha': { break; } */ default: { $textitem = $this->listcount[$this->listnum]; } } if (!$this->empty_string($textitem)) { // Check whether we need a new page or new column $prev_y = $this->y; $h = ($this->FontSize * $this->cell_height_ratio) + $this->cell_padding['T'] + $this->cell_padding['B']; if ($this->checkPageBreak($h) OR ($this->y < $prev_y)) { $tmpx = $this->x; } // print ordered item if ($this->rtl) { $textitem = '.'.$textitem; } else { $textitem = $textitem.'.'; } $lspace += $this->GetStringWidth($textitem); if ($this->rtl) { $this->x += $lspace; } else { $this->x -= $lspace; } $this->Write($this->lasth, $textitem, '', false, '', false, 0, false); } $this->x = $tmpx; $this->lispacer = '^'; // restore colors $this->SetFillColorArray($bgcolor); $this->SetDrawColorArray($strokecolor); $this->SettextColorArray($color); } /** * Returns current graphic variables as array. * @return array of graphic variables * @protected * @since 4.2.010 (2008-11-14) */ protected function getGraphicVars() { $grapvars = array( 'FontFamily' => $this->FontFamily, 'FontStyle' => $this->FontStyle, 'FontSizePt' => $this->FontSizePt, 'rMargin' => $this->rMargin, 'lMargin' => $this->lMargin, 'cell_padding' => $this->cell_padding, 'cell_margin' => $this->cell_margin, 'LineWidth' => $this->LineWidth, 'linestyleWidth' => $this->linestyleWidth, 'linestyleCap' => $this->linestyleCap, 'linestyleJoin' => $this->linestyleJoin, 'linestyleDash' => $this->linestyleDash, 'textrendermode' => $this->textrendermode, 'textstrokewidth' => $this->textstrokewidth, 'DrawColor' => $this->DrawColor, 'FillColor' => $this->FillColor, 'TextColor' => $this->TextColor, 'ColorFlag' => $this->ColorFlag, 'bgcolor' => $this->bgcolor, 'fgcolor' => $this->fgcolor, 'htmlvspace' => $this->htmlvspace, 'listindent' => $this->listindent, 'listindentlevel' => $this->listindentlevel, 'listnum' => $this->listnum, 'listordered' => $this->listordered, 'listcount' => $this->listcount, 'lispacer' => $this->lispacer, 'cell_height_ratio' => $this->cell_height_ratio, 'font_stretching' => $this->font_stretching, 'font_spacing' => $this->font_spacing, // extended 'lasth' => $this->lasth, 'tMargin' => $this->tMargin, 'bMargin' => $this->bMargin, 'AutoPageBreak' => $this->AutoPageBreak, 'PageBreakTrigger' => $this->PageBreakTrigger, 'x' => $this->x, 'y' => $this->y, 'w' => $this->w, 'h' => $this->h, 'wPt' => $this->wPt, 'hPt' => $this->hPt, 'fwPt' => $this->fwPt, 'fhPt' => $this->fhPt, 'page' => $this->page, 'current_column' => $this->current_column, 'num_columns' => $this->num_columns ); return $grapvars; } /** * Set graphic variables. * @param $gvars (array) array of graphic variablesto restore * @param $extended (boolean) if true restore extended graphic variables * @protected * @since 4.2.010 (2008-11-14) */ protected function setGraphicVars($gvars, $extended=false) { $this->FontFamily = $gvars['FontFamily']; $this->FontStyle = $gvars['FontStyle']; $this->FontSizePt = $gvars['FontSizePt']; $this->rMargin = $gvars['rMargin']; $this->lMargin = $gvars['lMargin']; $this->cell_padding = $gvars['cell_padding']; $this->cell_margin = $gvars['cell_margin']; $this->LineWidth = $gvars['LineWidth']; $this->linestyleWidth = $gvars['linestyleWidth']; $this->linestyleCap = $gvars['linestyleCap']; $this->linestyleJoin = $gvars['linestyleJoin']; $this->linestyleDash = $gvars['linestyleDash']; $this->textrendermode = $gvars['textrendermode']; $this->textstrokewidth = $gvars['textstrokewidth']; $this->DrawColor = $gvars['DrawColor']; $this->FillColor = $gvars['FillColor']; $this->TextColor = $gvars['TextColor']; $this->ColorFlag = $gvars['ColorFlag']; $this->bgcolor = $gvars['bgcolor']; $this->fgcolor = $gvars['fgcolor']; $this->htmlvspace = $gvars['htmlvspace']; $this->listindent = $gvars['listindent']; $this->listindentlevel = $gvars['listindentlevel']; $this->listnum = $gvars['listnum']; $this->listordered = $gvars['listordered']; $this->listcount = $gvars['listcount']; $this->lispacer = $gvars['lispacer']; $this->cell_height_ratio = $gvars['cell_height_ratio']; $this->font_stretching = $gvars['font_stretching']; $this->font_spacing = $gvars['font_spacing']; if ($extended) { // restore extended values $this->lasth = $gvars['lasth']; $this->tMargin = $gvars['tMargin']; $this->bMargin = $gvars['bMargin']; $this->AutoPageBreak = $gvars['AutoPageBreak']; $this->PageBreakTrigger = $gvars['PageBreakTrigger']; $this->x = $gvars['x']; $this->y = $gvars['y']; $this->w = $gvars['w']; $this->h = $gvars['h']; $this->wPt = $gvars['wPt']; $this->hPt = $gvars['hPt']; $this->fwPt = $gvars['fwPt']; $this->fhPt = $gvars['fhPt']; $this->page = $gvars['page']; $this->current_column = $gvars['current_column']; $this->num_columns = $gvars['num_columns']; } $this->_out(''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor.''); if (!$this->empty_string($this->FontFamily)) { $this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt); } } /** * Returns a temporary filename for caching object on filesystem. * @param $name (string) prefix to add to filename * @return string filename. * @since 4.5.000 (2008-12-31) * @protected */ protected function getObjFilename($name) { return tempnam(K_PATH_CACHE, $name.'_'); } /** * Writes data to a temporary file on filesystem. * @param $filename (string) file name * @param $data (mixed) data to write on file * @param $append (boolean) if true append data, false replace. * @since 4.5.000 (2008-12-31) * @protected */ protected function writeDiskCache($filename, $data, $append=false) { if ($append) { $fmode = 'ab+'; } else { $fmode = 'wb+'; } $f = @fopen($filename, $fmode); if (!$f) { $this->Error('Unable to write cache file: '.$filename); } else { fwrite($f, $data); fclose($f); } // update file length (needed for transactions) if (!isset($this->cache_file_length['_'.$filename])) { $this->cache_file_length['_'.$filename] = strlen($data); } else { $this->cache_file_length['_'.$filename] += strlen($data); } } /** * Read data from a temporary file on filesystem. * @param $filename (string) file name * @return mixed retrieved data * @since 4.5.000 (2008-12-31) * @protected */ protected function readDiskCache($filename) { return file_get_contents($filename); } /** * Set buffer content (always append data). * @param $data (string) data * @protected * @since 4.5.000 (2009-01-02) */ protected function setBuffer($data) { $this->bufferlen += strlen($data); if ($this->diskcache) { if (!isset($this->buffer) OR $this->empty_string($this->buffer)) { $this->buffer = $this->getObjFilename('buffer'); } $this->writeDiskCache($this->buffer, $data, true); } else { $this->buffer .= $data; } } /** * Replace the buffer content * @param $data (string) data * @protected * @since 5.5.000 (2010-06-22) */ protected function replaceBuffer($data) { $this->bufferlen = strlen($data); if ($this->diskcache) { if (!isset($this->buffer) OR $this->empty_string($this->buffer)) { $this->buffer = $this->getObjFilename('buffer'); } $this->writeDiskCache($this->buffer, $data, false); } else { $this->buffer = $data; } } /** * Get buffer content. * @return string buffer content * @protected * @since 4.5.000 (2009-01-02) */ protected function getBuffer() { if ($this->diskcache) { return $this->readDiskCache($this->buffer); } else { return $this->buffer; } } /** * Set page buffer content. * @param $page (int) page number * @param $data (string) page data * @param $append (boolean) if true append data, false replace. * @protected * @since 4.5.000 (2008-12-31) */ protected function setPageBuffer($page, $data, $append=false) { if ($this->diskcache) { if (!isset($this->pages[$page])) { $this->pages[$page] = $this->getObjFilename('page'.$page); } $this->writeDiskCache($this->pages[$page], $data, $append); } else { if ($append) { $this->pages[$page] .= $data; } else { $this->pages[$page] = $data; } } if ($append AND isset($this->pagelen[$page])) { $this->pagelen[$page] += strlen($data); } else { $this->pagelen[$page] = strlen($data); } } /** * Get page buffer content. * @param $page (int) page number * @return string page buffer content or false in case of error * @protected * @since 4.5.000 (2008-12-31) */ protected function getPageBuffer($page) { if ($this->diskcache) { return $this->readDiskCache($this->pages[$page]); } elseif (isset($this->pages[$page])) { return $this->pages[$page]; } return false; } /** * Set image buffer content. * @param $image (string) image key * @param $data (array) image data * @protected * @since 4.5.000 (2008-12-31) */ protected function setImageBuffer($image, $data) { if ($this->diskcache) { if (!isset($this->images[$image])) { $this->images[$image] = $this->getObjFilename('image'.$image); } $this->writeDiskCache($this->images[$image], serialize($data)); } else { $this->images[$image] = $data; } if (!in_array($image, $this->imagekeys)) { $this->imagekeys[] = $image; ++$this->numimages; } } /** * Set image buffer content for a specified sub-key. * @param $image (string) image key * @param $key (string) image sub-key * @param $data (array) image data * @protected * @since 4.5.000 (2008-12-31) */ protected function setImageSubBuffer($image, $key, $data) { if (!isset($this->images[$image])) { $this->setImageBuffer($image, array()); } if ($this->diskcache) { $tmpimg = $this->getImageBuffer($image); $tmpimg[$key] = $data; $this->writeDiskCache($this->images[$image], serialize($tmpimg)); } else { $this->images[$image][$key] = $data; } } /** * Get image buffer content. * @param $image (string) image key * @return string image buffer content or false in case of error * @protected * @since 4.5.000 (2008-12-31) */ protected function getImageBuffer($image) { if ($this->diskcache AND isset($this->images[$image])) { return unserialize($this->readDiskCache($this->images[$image])); } elseif (isset($this->images[$image])) { return $this->images[$image]; } return false; } /** * Set font buffer content. * @param $font (string) font key * @param $data (array) font data * @protected * @since 4.5.000 (2009-01-02) */ protected function setFontBuffer($font, $data) { if ($this->diskcache) { if (!isset($this->fonts[$font])) { $this->fonts[$font] = $this->getObjFilename('font'); } $this->writeDiskCache($this->fonts[$font], serialize($data)); } else { $this->fonts[$font] = $data; } if (!in_array($font, $this->fontkeys)) { $this->fontkeys[] = $font; // store object ID for current font ++$this->n; $this->font_obj_ids[$font] = $this->n; $this->setFontSubBuffer($font, 'n', $this->n); } } /** * Set font buffer content. * @param $font (string) font key * @param $key (string) font sub-key * @param $data (array) font data * @protected * @since 4.5.000 (2009-01-02) */ protected function setFontSubBuffer($font, $key, $data) { if (!isset($this->fonts[$font])) { $this->setFontBuffer($font, array()); } if ($this->diskcache) { $tmpfont = $this->getFontBuffer($font); $tmpfont[$key] = $data; $this->writeDiskCache($this->fonts[$font], serialize($tmpfont)); } else { $this->fonts[$font][$key] = $data; } } /** * Get font buffer content. * @param $font (string) font key * @return string font buffer content or false in case of error * @protected * @since 4.5.000 (2009-01-02) */ protected function getFontBuffer($font) { if ($this->diskcache AND isset($this->fonts[$font])) { return unserialize($this->readDiskCache($this->fonts[$font])); } elseif (isset($this->fonts[$font])) { return $this->fonts[$font]; } return false; } /** * Move a page to a previous position. * @param $frompage (int) number of the source page * @param $topage (int) number of the destination page (must be less than $frompage) * @return true in case of success, false in case of error. * @public * @since 4.5.000 (2009-01-02) */ public function movePage($frompage, $topage) { if (($frompage > $this->numpages) OR ($frompage <= $topage)) { return false; } if ($frompage == $this->page) { // close the page before moving it $this->endPage(); } // move all page-related states $tmppage = $this->getPageBuffer($frompage); $tmppagedim = $this->pagedim[$frompage]; $tmppagelen = $this->pagelen[$frompage]; $tmpintmrk = $this->intmrk[$frompage]; $tmpbordermrk = $this->bordermrk[$frompage]; $tmpcntmrk = $this->cntmrk[$frompage]; if (isset($this->footerpos[$frompage])) { $tmpfooterpos = $this->footerpos[$frompage]; } if (isset($this->footerlen[$frompage])) { $tmpfooterlen = $this->footerlen[$frompage]; } if (isset($this->transfmrk[$frompage])) { $tmptransfmrk = $this->transfmrk[$frompage]; } if (isset($this->PageAnnots[$frompage])) { $tmpannots = $this->PageAnnots[$frompage]; } if (isset($this->newpagegroup) AND !empty($this->newpagegroup)) { for ($i = $frompage; $i > $topage; --$i) { if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $frompage)) { --$this->pagegroups[$this->newpagegroup[$i]]; break; } } for ($i = $topage; $i > 0; --$i) { if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $topage)) { ++$this->pagegroups[$this->newpagegroup[$i]]; break; } } } for ($i = $frompage; $i > $topage; --$i) { $j = $i - 1; // shift pages down $this->setPageBuffer($i, $this->getPageBuffer($j)); $this->pagedim[$i] = $this->pagedim[$j]; $this->pagelen[$i] = $this->pagelen[$j]; $this->intmrk[$i] = $this->intmrk[$j]; $this->bordermrk[$i] = $this->bordermrk[$j]; $this->cntmrk[$i] = $this->cntmrk[$j]; if (isset($this->footerpos[$j])) { $this->footerpos[$i] = $this->footerpos[$j]; } elseif (isset($this->footerpos[$i])) { unset($this->footerpos[$i]); } if (isset($this->footerlen[$j])) { $this->footerlen[$i] = $this->footerlen[$j]; } elseif (isset($this->footerlen[$i])) { unset($this->footerlen[$i]); } if (isset($this->transfmrk[$j])) { $this->transfmrk[$i] = $this->transfmrk[$j]; } elseif (isset($this->transfmrk[$i])) { unset($this->transfmrk[$i]); } if (isset($this->PageAnnots[$j])) { $this->PageAnnots[$i] = $this->PageAnnots[$j]; } elseif (isset($this->PageAnnots[$i])) { unset($this->PageAnnots[$i]); } if (isset($this->newpagegroup[$j])) { $this->newpagegroup[$i] = $this->newpagegroup[$j]; unset($this->newpagegroup[$j]); } if ($this->currpagegroup == $j) { $this->currpagegroup = $i; } } $this->setPageBuffer($topage, $tmppage); $this->pagedim[$topage] = $tmppagedim; $this->pagelen[$topage] = $tmppagelen; $this->intmrk[$topage] = $tmpintmrk; $this->bordermrk[$topage] = $tmpbordermrk; $this->cntmrk[$topage] = $tmpcntmrk; if (isset($tmpfooterpos)) { $this->footerpos[$topage] = $tmpfooterpos; } elseif (isset($this->footerpos[$topage])) { unset($this->footerpos[$topage]); } if (isset($tmpfooterlen)) { $this->footerlen[$topage] = $tmpfooterlen; } elseif (isset($this->footerlen[$topage])) { unset($this->footerlen[$topage]); } if (isset($tmptransfmrk)) { $this->transfmrk[$topage] = $tmptransfmrk; } elseif (isset($this->transfmrk[$topage])) { unset($this->transfmrk[$topage]); } if (isset($tmpannots)) { $this->PageAnnots[$topage] = $tmpannots; } elseif (isset($this->PageAnnots[$topage])) { unset($this->PageAnnots[$topage]); } // adjust outlines $tmpoutlines = $this->outlines; foreach ($tmpoutlines as $key => $outline) { if (($outline['p'] >= $topage) AND ($outline['p'] < $frompage)) { $this->outlines[$key]['p'] = ($outline['p'] + 1); } elseif ($outline['p'] == $frompage) { $this->outlines[$key]['p'] = $topage; } } // adjust dests $tmpdests = $this->dests; foreach ($tmpdests as $key => $dest) { if (($dest['p'] >= $topage) AND ($dest['p'] < $frompage)) { $this->dests[$key]['p'] = ($dest['p'] + 1); } elseif ($dest['p'] == $frompage) { $this->dests[$key]['p'] = $topage; } } // adjust links $tmplinks = $this->links; foreach ($tmplinks as $key => $link) { if (($link[0] >= $topage) AND ($link[0] < $frompage)) { $this->links[$key][0] = ($link[0] + 1); } elseif ($link[0] == $frompage) { $this->links[$key][0] = $topage; } } // adjust javascript $tmpjavascript = $this->javascript; global $jfrompage, $jtopage; $jfrompage = $frompage; $jtopage = $topage; $this->javascript = preg_replace_callback('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/', function($matches){ global $jfrompage, $jtopage; $pagenum = intval($matches[3]) + 1; if (($pagenum >= $jtopage) AND ($pagenum < $jfrompage)) { $newpage = ($pagenum + 1); } elseif ($pagenum == $jfrompage) { $newpage = $jtopage; } else { $newpage = $pagenum; } --$newpage; return "this.addField(\'".$matches[1]."\',\'".$matches[2]."\',".$newpage.""; }, $tmpjavascript); // return to last page $this->lastPage(true); return true; } /** * Remove the specified page. * @param $page (int) page to remove * @return true in case of success, false in case of error. * @public * @since 4.6.004 (2009-04-23) */ public function deletePage($page) { if (($page < 1) OR ($page > $this->numpages)) { return false; } // delete current page unset($this->pages[$page]); unset($this->pagedim[$page]); unset($this->pagelen[$page]); unset($this->intmrk[$page]); unset($this->bordermrk[$page]); unset($this->cntmrk[$page]); if (isset($this->footerpos[$page])) { unset($this->footerpos[$page]); } if (isset($this->footerlen[$page])) { unset($this->footerlen[$page]); } if (isset($this->transfmrk[$page])) { unset($this->transfmrk[$page]); } if (isset($this->PageAnnots[$page])) { unset($this->PageAnnots[$page]); } if (isset($this->newpagegroup) AND !empty($this->newpagegroup)) { for ($i = $page; $i > 0; --$i) { if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $page)) { --$this->pagegroups[$this->newpagegroup[$i]]; break; } } } if (isset($this->pageopen[$page])) { unset($this->pageopen[$page]); } if ($page < $this->numpages) { // update remaining pages for ($i = $page; $i < $this->numpages; ++$i) { $j = $i + 1; // shift pages $this->setPageBuffer($i, $this->getPageBuffer($j)); $this->pagedim[$i] = $this->pagedim[$j]; $this->pagelen[$i] = $this->pagelen[$j]; $this->intmrk[$i] = $this->intmrk[$j]; $this->bordermrk[$i] = $this->bordermrk[$j]; $this->cntmrk[$i] = $this->cntmrk[$j]; if (isset($this->footerpos[$j])) { $this->footerpos[$i] = $this->footerpos[$j]; } elseif (isset($this->footerpos[$i])) { unset($this->footerpos[$i]); } if (isset($this->footerlen[$j])) { $this->footerlen[$i] = $this->footerlen[$j]; } elseif (isset($this->footerlen[$i])) { unset($this->footerlen[$i]); } if (isset($this->transfmrk[$j])) { $this->transfmrk[$i] = $this->transfmrk[$j]; } elseif (isset($this->transfmrk[$i])) { unset($this->transfmrk[$i]); } if (isset($this->PageAnnots[$j])) { $this->PageAnnots[$i] = $this->PageAnnots[$j]; } elseif (isset($this->PageAnnots[$i])) { unset($this->PageAnnots[$i]); } if (isset($this->newpagegroup[$j])) { $this->newpagegroup[$i] = $this->newpagegroup[$j]; unset($this->newpagegroup[$j]); } if ($this->currpagegroup == $j) { $this->currpagegroup = $i; } if (isset($this->pageopen[$j])) { $this->pageopen[$i] = $this->pageopen[$j]; } elseif (isset($this->pageopen[$i])) { unset($this->pageopen[$i]); } } // remove last page unset($this->pages[$this->numpages]); unset($this->pagedim[$this->numpages]); unset($this->pagelen[$this->numpages]); unset($this->intmrk[$this->numpages]); unset($this->bordermrk[$this->numpages]); unset($this->cntmrk[$this->numpages]); if (isset($this->footerpos[$this->numpages])) { unset($this->footerpos[$this->numpages]); } if (isset($this->footerlen[$this->numpages])) { unset($this->footerlen[$this->numpages]); } if (isset($this->transfmrk[$this->numpages])) { unset($this->transfmrk[$this->numpages]); } if (isset($this->PageAnnots[$this->numpages])) { unset($this->PageAnnots[$this->numpages]); } if (isset($this->newpagegroup[$this->numpages])) { unset($this->newpagegroup[$this->numpages]); } if ($this->currpagegroup == $this->numpages) { $this->currpagegroup = ($this->numpages - 1); } if (isset($this->pagegroups[$this->numpages])) { unset($this->pagegroups[$this->numpages]); } if (isset($this->pageopen[$this->numpages])) { unset($this->pageopen[$this->numpages]); } } --$this->numpages; $this->page = $this->numpages; // adjust outlines $tmpoutlines = $this->outlines; foreach ($tmpoutlines as $key => $outline) { if ($outline['p'] > $page) { $this->outlines[$key]['p'] = $outline['p'] - 1; } elseif ($outline['p'] == $page) { unset($this->outlines[$key]); } } // adjust dests $tmpdests = $this->dests; foreach ($tmpdests as $key => $dest) { if ($dest['p'] > $page) { $this->dests[$key]['p'] = $dest['p'] - 1; } elseif ($dest['p'] == $page) { unset($this->dests[$key]); } } // adjust links $tmplinks = $this->links; foreach ($tmplinks as $key => $link) { if ($link[0] > $page) { $this->links[$key][0] = $link[0] - 1; } elseif ($link[0] == $page) { unset($this->links[$key]); } } // adjust javascript $tmpjavascript = $this->javascript; global $jpage; $jpage = $page; $this->javascript = preg_replace_callback('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/', function($matches){ global $jpage; $pagenum = intval($matches[3]) + 1; if ($pagenum >= $jpage) { $newpage = ($pagenum - 1); } elseif ($pagenum == $jpage) { $newpage = 1; } else { $newpage = $pagenum; } --$newpage; return "this.addField(\'".$matches[1]."\',\'".$matches[2]."\',".$newpage.""; }, $tmpjavascript); // return to last page $this->lastPage(true); return true; } /** * Clone the specified page to a new page. * @param $page (int) number of page to copy (0 = current page) * @return true in case of success, false in case of error. * @public * @since 4.9.015 (2010-04-20) */ public function copyPage($page=0) { if ($page == 0) { // default value $page = $this->page; } if (($page < 1) OR ($page > $this->numpages)) { return false; } // close the last page $this->endPage(); // copy all page-related states ++$this->numpages; $this->page = $this->numpages; $this->setPageBuffer($this->page, $this->getPageBuffer($page)); $this->pagedim[$this->page] = $this->pagedim[$page]; $this->pagelen[$this->page] = $this->pagelen[$page]; $this->intmrk[$this->page] = $this->intmrk[$page]; $this->bordermrk[$this->page] = $this->bordermrk[$page]; $this->cntmrk[$this->page] = $this->cntmrk[$page]; $this->pageopen[$this->page] = false; if (isset($this->footerpos[$page])) { $this->footerpos[$this->page] = $this->footerpos[$page]; } if (isset($this->footerlen[$page])) { $this->footerlen[$this->page] = $this->footerlen[$page]; } if (isset($this->transfmrk[$page])) { $this->transfmrk[$this->page] = $this->transfmrk[$page]; } if (isset($this->PageAnnots[$page])) { $this->PageAnnots[$this->page] = $this->PageAnnots[$page]; } if (isset($this->newpagegroup[$page])) { // start a new group $this->newpagegroup[$this->page] = sizeof($this->newpagegroup) + 1; $this->currpagegroup = $this->newpagegroup[$this->page]; $this->pagegroups[$this->currpagegroup] = 1; } elseif (isset($this->currpagegroup) AND ($this->currpagegroup > 0)) { ++$this->pagegroups[$this->currpagegroup]; } // copy outlines $tmpoutlines = $this->outlines; foreach ($tmpoutlines as $key => $outline) { if ($outline['p'] == $page) { $this->outlines[] = array('t' => $outline['t'], 'l' => $outline['l'], 'y' => $outline['y'], 'p' => $this->page, 's' => $outline['s'], 'c' => $outline['c']); } } // copy links $tmplinks = $this->links; foreach ($tmplinks as $key => $link) { if ($link[0] == $page) { $this->links[] = array($this->page, $link[1]); } } // return to last page $this->lastPage(true); return true; } /** * Output a Table of Content Index (TOC). * This method must be called after all Bookmarks were set. * Before calling this method you have to open the page using the addTOCPage() method. * After calling this method you have to call endTOCPage() to close the TOC page. * You can override this method to achieve different styles. * @param $page (int) page number where this TOC should be inserted (leave empty for current page). * @param $numbersfont (string) set the font for page numbers (please use monospaced font for better alignment). * @param $filler (string) string used to fill the space between text and page number. * @param $toc_name (string) name to use for TOC bookmark. * @param $style (string) Font style for title: B = Bold, I = Italic, BI = Bold + Italic. * @param $color (array) RGB color array for bookmark title (values from 0 to 255). * @public * @author Nicola Asuni * @since 4.5.000 (2009-01-02) * @see addTOCPage(), endTOCPage(), addHTMLTOC() */ public function addTOC($page='', $numbersfont='', $filler='.', $toc_name='TOC', $style='', $color=array(0,0,0)) { $fontsize = $this->FontSizePt; $fontfamily = $this->FontFamily; $fontstyle = $this->FontStyle; $w = $this->w - $this->lMargin - $this->rMargin; $spacer = $this->GetStringWidth(chr(32)) * 4; $page_first = $this->getPage(); $lmargin = $this->lMargin; $rmargin = $this->rMargin; $x_start = $this->GetX(); $current_page = $this->page; $current_column = $this->current_column; if ($this->empty_string($numbersfont)) { $numbersfont = $this->default_monospaced_font; } if ($this->empty_string($filler)) { $filler = ' '; } if ($this->empty_string($page)) { $gap = ' '; } else { $gap = ''; if ($page < 1) { $page = 1; } } $this->SetFont($numbersfont, $fontstyle, $fontsize); $numwidth = $this->GetStringWidth('00000'); $maxpage = 0; //used for pages on attached documents foreach ($this->outlines as $key => $outline) { // check for extra pages (used for attachments) if (($this->page > $page_first) AND ($outline['p'] >= $this->numpages)) { $outline['p'] += ($this->page - $page_first); } if ($this->rtl) { $aligntext = 'R'; $alignnum = 'L'; } else { $aligntext = 'L'; $alignnum = 'R'; } if ($outline['l'] == 0) { $this->SetFont($fontfamily, $fontstyle.'B', $fontsize); } else { $this->SetFont($fontfamily, $fontstyle, $fontsize - $outline['l']); } // check for page break $this->checkPageBreak((2 * $this->FontSize * $this->cell_height_ratio)); // set margins and X position if (($this->page == $current_page) AND ($this->current_column == $current_column)) { $this->lMargin = $lmargin; $this->rMargin = $rmargin; } else { if ($this->current_column != $current_column) { if ($this->rtl) { $x_start = $this->w - $this->columns[$this->current_column]['x']; } else { $x_start = $this->columns[$this->current_column]['x']; } } $lmargin = $this->lMargin; $rmargin = $this->rMargin; $current_page = $this->page; $current_column = $this->current_column; } $this->SetX($x_start); $indent = ($spacer * $outline['l']); if ($this->rtl) { $this->x -= $indent; $this->rMargin = $this->w - $this->x; } else { $this->x += $indent; $this->lMargin = $this->x; } $link = $this->AddLink(); $this->SetLink($link, $outline['y'], $outline['p']); // write the text if ($this->rtl) { $txt = ' '.$outline['t']; } else { $txt = $outline['t'].' '; } $this->Write(0, $txt, $link, false, $aligntext, false, 0, false, false, 0, $numwidth, ''); if ($this->rtl) { $tw = $this->x - $this->lMargin; } else { $tw = $this->w - $this->rMargin - $this->x; } $this->SetFont($numbersfont, $fontstyle, $fontsize); if ($this->empty_string($page)) { $pagenum = $outline['p']; } else { // placemark to be replaced with the correct number $pagenum = '{#'.($outline['p']).'}'; if ($this->isUnicodeFont()) { $pagenum = '{'.$pagenum.'}'; } $maxpage = max($maxpage, $outline['p']); } $fw = ($tw - $this->GetStringWidth($pagenum.$filler)); $numfills = floor($fw / $this->GetStringWidth($filler)); if ($numfills > 0) { $rowfill = str_repeat($filler, $numfills); } else { $rowfill = ''; } if ($this->rtl) { $pagenum = $pagenum.$gap.$rowfill; } else { $pagenum = $rowfill.$gap.$pagenum; } // write the number $this->Cell($tw, 0, $pagenum, 0, 1, $alignnum, 0, $link, 0); } $page_last = $this->getPage(); $maxpage = max($maxpage, $page_last); $numpages = $page_last - $page_first + 1; if (!$this->empty_string($page)) { for ($p = $page_first; $p <= $page_last; ++$p) { // get page data $temppage = $this->getPageBuffer($p); for ($n = 1; $n <= $maxpage; ++$n) { // update page numbers $a = '{#'.$n.'}'; // get page number aliases $pnalias = $this->getInternalPageNumberAliases($a); // calculate replacement number if (($n >= $page) AND ($n <= $this->numpages)) { $np = $n + $numpages; } else { $np = $n; } $na = $this->formatTOCPageNumber(($this->starting_page_number + $np - 1)); $nu = $this->UTF8ToUTF16BE($na, false); // replace aliases with numbers foreach ($pnalias['u'] as $u) { $sfill = str_repeat($filler, max(0, (strlen($u) - strlen($nu.' ')))); if ($this->rtl) { $nr = $nu.$this->UTF8ToUTF16BE(' '.$sfill); } else { $nr = $this->UTF8ToUTF16BE($sfill.' ').$nu; } $temppage = str_replace($u, $nr, $temppage); } foreach ($pnalias['a'] as $a) { $sfill = str_repeat($filler, max(0, (strlen($a) - strlen($na.' ')))); if ($this->rtl) { $nr = $na.' '.$sfill; } else { $nr = $sfill.' '.$na; } $temppage = str_replace($a, $nr, $temppage); } } // save changes $this->setPageBuffer($p, $temppage); } // move pages $this->Bookmark($toc_name, 0, 0, $page_first, $style, $color); for ($i = 0; $i < $numpages; ++$i) { $this->movePage($page_last, $page); } } } /** * Output a Table Of Content Index (TOC) using HTML templates. * This method must be called after all Bookmarks were set. * Before calling this method you have to open the page using the addTOCPage() method. * After calling this method you have to call endTOCPage() to close the TOC page. * @param $page (int) page number where this TOC should be inserted (leave empty for current page). * @param $toc_name (string) name to use for TOC bookmark. * @param $templates (array) array of html templates. Use: "#TOC_DESCRIPTION#" for bookmark title, "#TOC_PAGE_NUMBER#" for page number. * @param $correct_align (boolean) if true correct the number alignment (numbers must be in monospaced font like courier and right aligned on LTR, or left aligned on RTL) * @param $style (string) Font style for title: B = Bold, I = Italic, BI = Bold + Italic. * @param $color (array) RGB color array for title (values from 0 to 255). * @public * @author Nicola Asuni * @since 5.0.001 (2010-05-06) * @see addTOCPage(), endTOCPage(), addTOC() */ public function addHTMLTOC($page='', $toc_name='TOC', $templates=array(), $correct_align=true, $style='', $color=array(0,0,0)) { $filler = ' '; $prev_htmlLinkColorArray = $this->htmlLinkColorArray; $prev_htmlLinkFontStyle = $this->htmlLinkFontStyle; // set new style for link $this->htmlLinkColorArray = array(); $this->htmlLinkFontStyle = ''; $page_first = $this->getPage(); // get the font type used for numbers in each template $current_font = $this->FontFamily; foreach ($templates as $level => $html) { $dom = $this->getHtmlDomArray($html); foreach ($dom as $key => $value) { if ($value['value'] == '#TOC_PAGE_NUMBER#') { $this->SetFont($dom[($key - 1)]['fontname']); $templates['F'.$level] = $this->isUnicodeFont(); } } } $this->SetFont($current_font); $maxpage = 0; //used for pages on attached documents foreach ($this->outlines as $key => $outline) { // get HTML template $row = $templates[$outline['l']]; if ($this->empty_string($page)) { $pagenum = $outline['p']; } else { // placemark to be replaced with the correct number $pagenum = '{#'.($outline['p']).'}'; if ($templates['F'.$outline['l']]) { $pagenum = '{'.$pagenum.'}'; } $maxpage = max($maxpage, $outline['p']); } // replace templates with current values $row = str_replace('#TOC_DESCRIPTION#', $outline['t'], $row); $row = str_replace('#TOC_PAGE_NUMBER#', $pagenum, $row); // add link to page $row = ''.$row.''; // write bookmark entry $this->writeHTML($row, false, false, true, false, ''); } // restore link styles $this->htmlLinkColorArray = $prev_htmlLinkColorArray; $this->htmlLinkFontStyle = $prev_htmlLinkFontStyle; // move TOC page and replace numbers $page_last = $this->getPage(); $maxpage = max($maxpage, $page_last); $numpages = $page_last - $page_first + 1; if (!$this->empty_string($page)) { for ($p = $page_first; $p <= $page_last; ++$p) { // get page data $temppage = $this->getPageBuffer($p); for ($n = 1; $n <= $maxpage; ++$n) { // update page numbers $a = '{#'.$n.'}'; // get page number aliases $pnalias = $this->getInternalPageNumberAliases($a); // calculate replacement number if ($n >= $page) { $np = $n + $numpages; } else { $np = $n; } $na = $this->formatTOCPageNumber(($this->starting_page_number + $np - 1)); $nu = $this->UTF8ToUTF16BE($na, false); // replace aliases with numbers foreach ($pnalias['u'] as $u) { if ($correct_align) { $sfill = str_repeat($filler, (strlen($u) - strlen($nu.' '))); if ($this->rtl) { $nr = $nu.$this->UTF8ToUTF16BE(' '.$sfill); } else { $nr = $this->UTF8ToUTF16BE($sfill.' ').$nu; } } else { $nr = $nu; } $temppage = str_replace($u, $nr, $temppage); } foreach ($pnalias['a'] as $a) { if ($correct_align) { $sfill = str_repeat($filler, (strlen($a) - strlen($na.' '))); if ($this->rtl) { $nr = $na.' '.$sfill; } else { $nr = $sfill.' '.$na; } } else { $nr = $na; } $temppage = str_replace($a, $nr, $temppage); } } // save changes $this->setPageBuffer($p, $temppage); } // move pages $this->Bookmark($toc_name, 0, 0, $page_first, $style, $color); for ($i = 0; $i < $numpages; ++$i) { $this->movePage($page_last, $page); } } } /** * Stores a copy of the current TCPDF object used for undo operation. * @public * @since 4.5.029 (2009-03-19) */ public function startTransaction() { if (isset($this->objcopy)) { // remove previous copy $this->commitTransaction(); } // record current page number and Y position $this->start_transaction_page = $this->page; $this->start_transaction_y = $this->y; // clone current object $this->objcopy = $this->objclone($this); } /** * Delete the copy of the current TCPDF object used for undo operation. * @public * @since 4.5.029 (2009-03-19) */ public function commitTransaction() { if (isset($this->objcopy)) { $this->objcopy->_destroy(true, true); unset($this->objcopy); } } /** * This method allows to undo the latest transaction by returning the latest saved TCPDF object with startTransaction(). * @param $self (boolean) if true restores current class object to previous state without the need of reassignment via the returned value. * @return TCPDF object. * @public * @since 4.5.029 (2009-03-19) */ public function rollbackTransaction($self=false) { if (isset($this->objcopy)) { if (isset($this->objcopy->diskcache) AND $this->objcopy->diskcache) { // truncate files to previous values foreach ($this->objcopy->cache_file_length as $file => $length) { $file = substr($file, 1); $handle = fopen($file, 'r+'); ftruncate($handle, $length); } } $this->_destroy(true, true); if ($self) { $objvars = get_object_vars($this->objcopy); foreach ($objvars as $key => $value) { $this->$key = $value; } } return $this->objcopy; } return $this; } /** * Creates a copy of a class object * @param $object (object) class object to be cloned * @return cloned object * @public * @since 4.5.029 (2009-03-19) */ public function objclone($object) { return @clone($object); } /** * Determine whether a string is empty. * @param $str (string) string to be checked * @return boolean true if string is empty * @public * @since 4.5.044 (2009-04-16) */ public function empty_string($str) { return (is_null($str) OR (is_string($str) AND (strlen($str) == 0))); } /** * Find position of last occurrence of a substring in a string * @param $haystack (string) The string to search in. * @param $needle (string) substring to search. * @param $offset (int) May be specified to begin searching an arbitrary number of characters into the string. * @return Returns the position where the needle exists. Returns FALSE if the needle was not found. * @public * @since 4.8.038 (2010-03-13) */ public function revstrpos($haystack, $needle, $offset = 0) { $length = strlen($haystack); $offset = ($offset > 0)?($length - $offset):abs($offset); $pos = strpos(strrev($haystack), strrev($needle), $offset); return ($pos === false)?false:($length - $pos - strlen($needle)); } // --- MULTI COLUMNS METHODS ----------------------- /** * Set multiple columns of the same size * @param $numcols (int) number of columns (set to zero to disable columns mode) * @param $width (int) column width * @param $y (int) column starting Y position (leave empty for current Y position) * @public * @since 4.9.001 (2010-03-28) */ public function setEqualColumns($numcols=0, $width=0, $y='') { $this->columns = array(); if ($numcols < 2) { $numcols = 0; $this->columns = array(); } else { // maximum column width $maxwidth = ($this->w - $this->original_lMargin - $this->original_rMargin) / $numcols; if (($width == 0) OR ($width > $maxwidth)) { $width = $maxwidth; } if ($this->empty_string($y)) { $y = $this->y; } // space between columns $space = (($this->w - $this->original_lMargin - $this->original_rMargin - ($numcols * $width)) / ($numcols - 1)); // fill the columns array (with, space, starting Y position) for ($i = 0; $i < $numcols; ++$i) { $this->columns[$i] = array('w' => $width, 's' => $space, 'y' => $y); } } $this->num_columns = $numcols; $this->current_column = 0; $this->column_start_page = $this->page; $this->selectColumn(0); } /** * Remove columns and reset page margins. * @public * @since 5.9.072 (2011-04-26) */ public function resetColumns() { $this->lMargin = $this->original_lMargin; $this->rMargin = $this->original_rMargin; $this->setEqualColumns(); } /** * Set columns array. * Each column is represented by an array of arrays with the following keys: (w = width, s = space between columns, y = column top position). * @param $columns (array) * @public * @since 4.9.001 (2010-03-28) */ public function setColumnsArray($columns) { $this->columns = $columns; $this->num_columns = count($columns); $this->current_column = 0; $this->column_start_page = $this->page; $this->selectColumn(0); } /** * Set position at a given column * @param $col (int) column number (from 0 to getNumberOfColumns()-1); empty string = current column. * @public * @since 4.9.001 (2010-03-28) */ public function selectColumn($col='') { if (is_string($col)) { $col = $this->current_column; } elseif ($col >= $this->num_columns) { $col = 0; } $xshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0)); $enable_thead = false; if ($this->num_columns > 1) { if ($col != $this->current_column) { // move Y pointer at the top of the column if ($this->column_start_page == $this->page) { $this->y = $this->columns[$col]['y']; } else { $this->y = $this->tMargin; } // Avoid to write table headers more than once if (($this->page > $this->maxselcol['page']) OR (($this->page == $this->maxselcol['page']) AND ($col > $this->maxselcol['column']))) { $enable_thead = true; $this->maxselcol['page'] = $this->page; $this->maxselcol['column'] = $col; } } $xshift = $this->colxshift; // set X position of the current column by case $listindent = ($this->listindentlevel * $this->listindent); // calculate column X position $colpos = 0; for ($i = 0; $i < $col; ++$i) { $colpos += ($this->columns[$i]['w'] + $this->columns[$i]['s']); } if ($this->rtl) { $x = $this->w - $this->original_rMargin - $colpos; $this->rMargin = ($this->w - $x + $listindent); $this->lMargin = ($x - $this->columns[$col]['w']); $this->x = $x - $listindent; } else { $x = $this->original_lMargin + $colpos; $this->lMargin = ($x + $listindent); $this->rMargin = ($this->w - $x - $this->columns[$col]['w']); $this->x = $x + $listindent; } $this->columns[$col]['x'] = $x; } $this->current_column = $col; // fix for HTML mode $this->newline = true; // print HTML table header (if any) if ((!$this->empty_string($this->thead)) AND (!$this->inthead)) { if ($enable_thead) { // print table header $this->writeHTML($this->thead, false, false, false, false, ''); $this->y += $xshift['s']['V']; // store end of header position if (!isset($this->columns[$col]['th'])) { $this->columns[$col]['th'] = array(); } $this->columns[$col]['th']['\''.$this->page.'\''] = $this->y; $this->lasth = 0; } elseif (isset($this->columns[$col]['th']['\''.$this->page.'\''])) { $this->y = $this->columns[$col]['th']['\''.$this->page.'\'']; } } // account for an html table cell over multiple columns if ($this->rtl) { $this->rMargin += $xshift['x']; $this->x -= ($xshift['x'] + $xshift['p']['R']); } else { $this->lMargin += $xshift['x']; $this->x += $xshift['x'] + $xshift['p']['L']; } } /** * Return the current column number * @return int current column number * @public * @since 5.5.011 (2010-07-08) */ public function getColumn() { return $this->current_column; } /** * Return the current number of columns. * @return int number of columns * @public * @since 5.8.018 (2010-08-25) */ public function getNumberOfColumns() { return $this->num_columns; } /** * Serialize an array of parameters to be used with TCPDF tag in HTML code. * @param $pararray (array) parameters array * @return sting containing serialized data * @public * @since 4.9.006 (2010-04-02) */ public function serializeTCPDFtagParameters($pararray) { return urlencode(serialize($pararray)); } /** * Set Text rendering mode. * @param $stroke (int) outline size in user units (0 = disable). * @param $fill (boolean) if true fills the text (default). * @param $clip (boolean) if true activate clipping mode * @public * @since 4.9.008 (2009-04-02) */ public function setTextRenderingMode($stroke=0, $fill=true, $clip=false) { // Ref.: PDF 32000-1:2008 - 9.3.6 Text Rendering Mode // convert text rendering parameters if ($stroke < 0) { $stroke = 0; } if ($fill === true) { if ($stroke > 0) { if ($clip === true) { // Fill, then stroke text and add to path for clipping $textrendermode = 6; } else { // Fill, then stroke text $textrendermode = 2; } $textstrokewidth = $stroke; } else { if ($clip === true) { // Fill text and add to path for clipping $textrendermode = 4; } else { // Fill text $textrendermode = 0; } } } else { if ($stroke > 0) { if ($clip === true) { // Stroke text and add to path for clipping $textrendermode = 5; } else { // Stroke text $textrendermode = 1; } $textstrokewidth = $stroke; } else { if ($clip === true) { // Add text to path for clipping $textrendermode = 7; } else { // Neither fill nor stroke text (invisible) $textrendermode = 3; } } } $this->textrendermode = $textrendermode; $this->textstrokewidth = $stroke * $this->k; } /** * Returns an array of chars containing soft hyphens. * @param $word (array) array of chars * @param $patterns (array) Array of hypenation patterns. * @param $dictionary (array) Array of words to be returned without applying the hyphenation algoritm. * @param $leftmin (int) Minimum number of character to leave on the left of the word without applying the hyphens. * @param $rightmin (int) Minimum number of character to leave on the right of the word without applying the hyphens. * @param $charmin (int) Minimum word length to apply the hyphenation algoritm. * @param $charmax (int) Maximum length of broken piece of word. * @return array text with soft hyphens * @author Nicola Asuni * @since 4.9.012 (2010-04-12) * @protected */ protected function hyphenateWord($word, $patterns, $dictionary=array(), $leftmin=1, $rightmin=2, $charmin=1, $charmax=8) { $hyphenword = array(); // hyphens positions $numchars = count($word); if ($numchars <= $charmin) { return $word; } $word_string = $this->UTF8ArrSubString($word); // some words will be returned as-is $pattern = '/^([a-zA-Z0-9_\.\-]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/'; if (preg_match($pattern, $word_string) > 0) { // email return $word; } $pattern = '/(([a-zA-Z0-9\-]+\.)?)((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/'; if (preg_match($pattern, $word_string) > 0) { // URL return $word; } if (isset($dictionary[$word_string])) { return $this->UTF8StringToArray($dictionary[$word_string]); } // suround word with '_' characters $tmpword = array_merge(array(95), $word, array(95)); $tmpnumchars = $numchars + 2; $maxpos = $tmpnumchars - $charmin; for ($pos = 0; $pos < $maxpos; ++$pos) { $imax = min(($tmpnumchars - $pos), $charmax); for ($i = $charmin; $i <= $imax; ++$i) { $subword = strtolower($this->UTF8ArrSubString($tmpword, $pos, $pos + $i)); if (isset($patterns[$subword])) { $pattern = $this->UTF8StringToArray($patterns[$subword]); $pattern_length = count($pattern); $digits = 1; for ($j = 0; $j < $pattern_length; ++$j) { // check if $pattern[$j] is a number if (($pattern[$j] >= 48) AND ($pattern[$j] <= 57)) { if ($j == 0) { $zero = $pos - 1; } else { $zero = $pos + $j - $digits; } if (!isset($hyphenword[$zero]) OR ($hyphenword[$zero] != $pattern[$j])) { $hyphenword[$zero] = $this->unichr($pattern[$j]); } ++$digits; } } } } } $inserted = 0; $maxpos = $numchars - $rightmin; for ($i = $leftmin; $i <= $maxpos; ++$i) { if (isset($hyphenword[$i]) AND (($hyphenword[$i] % 2) != 0)) { // 173 = soft hyphen character array_splice($word, $i + $inserted, 0, 173); ++$inserted; } } return $word; } /** * Returns an array of hyphenation patterns. * @param $file (string) TEX file containing hypenation patterns. TEX pattrns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ * @return array of hyphenation patterns * @author Nicola Asuni * @since 4.9.012 (2010-04-12) * @public */ public function getHyphenPatternsFromTEX($file) { // TEX patterns are available at: // http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ $data = file_get_contents($file); $patterns = array(); // remove comments $data = preg_replace('/\%[^\n]*/', '', $data); // extract the patterns part preg_match('/\\\\patterns\{([^\}]*)\}/i', $data, $matches); $data = trim(substr($matches[0], 10, -1)); // extract each pattern $patterns_array = preg_split('/[\s]+/', $data); // create new language array of patterns $patterns = array(); foreach($patterns_array as $val) { if (!$this->empty_string($val)) { $val = trim($val); $val = str_replace('\'', '\\\'', $val); $key = preg_replace('/[0-9]+/', '', $val); $patterns[$key] = $val; } } return $patterns; } /** * Returns text with soft hyphens. * @param $text (string) text to process * @param $patterns (mixed) Array of hypenation patterns or a TEX file containing hypenation patterns. TEX patterns can be downloaded from http://www.ctan.org/tex-archive/language/hyph-utf8/tex/generic/hyph-utf8/patterns/ * @param $dictionary (array) Array of words to be returned without applying the hyphenation algoritm. * @param $leftmin (int) Minimum number of character to leave on the left of the word without applying the hyphens. * @param $rightmin (int) Minimum number of character to leave on the right of the word without applying the hyphens. * @param $charmin (int) Minimum word length to apply the hyphenation algoritm. * @param $charmax (int) Maximum length of broken piece of word. * @return array text with soft hyphens * @author Nicola Asuni * @since 4.9.012 (2010-04-12) * @public */ public function hyphenateText($text, $patterns, $dictionary=array(), $leftmin=1, $rightmin=2, $charmin=1, $charmax=8) { $text = $this->unhtmlentities($text); $word = array(); // last word $txtarr = array(); // text to be returned $intag = false; // true if we are inside an HTML tag if (!is_array($patterns)) { $patterns = $this->getHyphenPatternsFromTEX($patterns); } // get array of characters $unichars = $this->UTF8StringToArray($text); // for each char foreach ($unichars as $char) { if ((!$intag) AND $this->unicode->uni_type[$char] == 'L') { // letter character $word[] = $char; } else { // other type of character if (!$this->empty_string($word)) { // hypenate the word $txtarr = array_merge($txtarr, $this->hyphenateWord($word, $patterns, $dictionary, $leftmin, $rightmin, $charmin, $charmax)); $word = array(); } $txtarr[] = $char; if (chr($char) == '<') { // we are inside an HTML tag $intag = true; } elseif ($intag AND (chr($char) == '>')) { // end of HTML tag $intag = false; } } } if (!$this->empty_string($word)) { // hypenate the word $txtarr = array_merge($txtarr, $this->hyphenateWord($word, $patterns, $dictionary, $leftmin, $rightmin, $charmin, $charmax)); } // convert char array to string and return return $this->UTF8ArrSubString($txtarr); } /** * Enable/disable rasterization of vector images using ImageMagick library. * @param $mode (boolean) if true enable rasterization, false otherwise. * @public * @since 5.0.000 (2010-04-27) */ public function setRasterizeVectorImages($mode) { $this->rasterize_vector_images = $mode; } /** * Get the Path-Painting Operators. * @param $style (string) Style of rendering. Possible values are: *
        *
      • S or D: Stroke the path.
      • *
      • s or d: Close and stroke the path.
      • *
      • f or F: Fill the path, using the nonzero winding number rule to determine the region to fill.
      • *
      • f* or F*: Fill the path, using the even-odd rule to determine the region to fill.
      • *
      • B or FD or DF: Fill and then stroke the path, using the nonzero winding number rule to determine the region to fill.
      • *
      • B* or F*D or DF*: Fill and then stroke the path, using the even-odd rule to determine the region to fill.
      • *
      • b or fd or df: Close, fill, and then stroke the path, using the nonzero winding number rule to determine the region to fill.
      • *
      • b or f*d or df*: Close, fill, and then stroke the path, using the even-odd rule to determine the region to fill.
      • *
      • CNZ: Clipping mode using the even-odd rule to determine which regions lie inside the clipping path.
      • *
      • CEO: Clipping mode using the nonzero winding number rule to determine which regions lie inside the clipping path
      • *
      • n: End the path object without filling or stroking it.
      • *
      * @param $default (string) default style * @author Nicola Asuni * @since 5.0.000 (2010-04-30) * @protected */ protected function getPathPaintOperator($style, $default='S') { $op = ''; switch($style) { case 'S': case 'D': { $op = 'S'; break; } case 's': case 'd': { $op = 's'; break; } case 'f': case 'F': { $op = 'f'; break; } case 'f*': case 'F*': { $op = 'f*'; break; } case 'B': case 'FD': case 'DF': { $op = 'B'; break; } case 'B*': case 'F*D': case 'DF*': { $op = 'B*'; break; } case 'b': case 'fd': case 'df': { $op = 'b'; break; } case 'b*': case 'f*d': case 'df*': { $op = 'b*'; break; } case 'CNZ': { $op = 'W n'; break; } case 'CEO': { $op = 'W* n'; break; } case 'n': { $op = 'n'; break; } default: { if (!empty($default)) { $op = $this->getPathPaintOperator($default, ''); } else { $op = ''; } } } return $op; } /** * Enable or disable default option for font subsetting. * @param $enable (boolean) if true enable font subsetting by default. * @author Nicola Asuni * @public * @since 5.3.002 (2010-06-07) */ public function setFontSubsetting($enable=true) { if ($this->pdfa_mode) { $this->font_subsetting = false; } else { $this->font_subsetting = $enable ? true : false; } } /** * Return the default option for font subsetting. * @return boolean default font subsetting state. * @author Nicola Asuni * @public * @since 5.3.002 (2010-06-07) */ public function getFontSubsetting() { return $this->font_subsetting; } /** * Left trim the input string * @param $str (string) string to trim * @param $replace (string) string that replace spaces. * @return left trimmed string * @author Nicola Asuni * @public * @since 5.8.000 (2010-08-11) */ public function stringLeftTrim($str, $replace='') { return preg_replace('/^'.$this->re_space['p'].'+/'.$this->re_space['m'], $replace, $str); } /** * Right trim the input string * @param $str (string) string to trim * @param $replace (string) string that replace spaces. * @return right trimmed string * @author Nicola Asuni * @public * @since 5.8.000 (2010-08-11) */ public function stringRightTrim($str, $replace='') { return preg_replace('/'.$this->re_space['p'].'+$/'.$this->re_space['m'], $replace, $str); } /** * Trim the input string * @param $str (string) string to trim * @param $replace (string) string that replace spaces. * @return trimmed string * @author Nicola Asuni * @public * @since 5.8.000 (2010-08-11) */ public function stringTrim($str, $replace='') { $str = $this->stringLeftTrim($str, $replace); $str = $this->stringRightTrim($str, $replace); return $str; } /** * Return true if the current font is unicode type. * @return true for unicode font, false otherwise. * @author Nicola Asuni * @public * @since 5.8.002 (2010-08-14) */ public function isUnicodeFont() { return (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0')); } /** * Return normalized font name * @param $fontfamily (string) property string containing font family names * @return string normalized font name * @author Nicola Asuni * @public * @since 5.8.004 (2010-08-17) */ public function getFontFamilyName($fontfamily) { // remove spaces and symbols $fontfamily = preg_replace('/[^a-z0-9\,]/', '', strtolower($fontfamily)); // extract all font names $fontslist = preg_split('/[,]/', $fontfamily); // find first valid font name foreach ($fontslist as $font) { // replace font variations $font = preg_replace('/italic$/', 'I', $font); $font = preg_replace('/oblique$/', 'I', $font); $font = preg_replace('/bold([I]?)$/', 'B\\1', $font); // replace common family names and core fonts $pattern = array(); $replacement = array(); $pattern[] = '/^serif|^cursive|^fantasy|^timesnewroman/'; $replacement[] = 'times'; $pattern[] = '/^sansserif/'; $replacement[] = 'helvetica'; $pattern[] = '/^monospace/'; $replacement[] = 'courier'; $font = preg_replace($pattern, $replacement, $font); if (in_array(strtolower($font), $this->fontlist) OR in_array($font, $this->fontkeys)) { return $font; } } // return current font as default return $this->CurrentFont['fontkey']; } /** * Start a new XObject Template. * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. * Note: X,Y coordinates will be reset to 0,0. * @param $w (int) Template width in user units (empty string or zero = page width less margins). * @param $h (int) Template height in user units (empty string or zero = page height less margins). * @param $group (mixed) Set transparency group. Can be a boolean value or an array specifying optional parameters: 'CS' (solour space name), 'I' (boolean flag to indicate isolated group) and 'K' (boolean flag to indicate knockout group). * @return int the XObject Template ID in case of success or false in case of error. * @author Nicola Asuni * @public * @since 5.8.017 (2010-08-24) * @see endTemplate(), printTemplate() */ public function startTemplate($w=0, $h=0, $group=false) { if ($this->inxobj) { // we are already inside an XObject template return false; } $this->inxobj = true; ++$this->n; // XObject ID $this->xobjid = 'XT'.$this->n; // object ID $this->xobjects[$this->xobjid] = array('n' => $this->n); // store current graphic state $this->xobjects[$this->xobjid]['gvars'] = $this->getGraphicVars(); // initialize data $this->xobjects[$this->xobjid]['intmrk'] = 0; $this->xobjects[$this->xobjid]['transfmrk'] = array(); $this->xobjects[$this->xobjid]['outdata'] = ''; $this->xobjects[$this->xobjid]['xobjects'] = array(); $this->xobjects[$this->xobjid]['images'] = array(); $this->xobjects[$this->xobjid]['fonts'] = array(); $this->xobjects[$this->xobjid]['annotations'] = array(); $this->xobjects[$this->xobjid]['extgstates'] = array(); $this->xobjects[$this->xobjid]['gradients'] = array(); $this->xobjects[$this->xobjid]['spot_colors'] = array(); // set new environment $this->num_columns = 1; $this->current_column = 0; $this->SetAutoPageBreak(false); if (($w === '') OR ($w <= 0)) { $w = $this->w - $this->lMargin - $this->rMargin; } if (($h === '') OR ($h <= 0)) { $h = $this->h - $this->tMargin - $this->bMargin; } $this->xobjects[$this->xobjid]['x'] = 0; $this->xobjects[$this->xobjid]['y'] = 0; $this->xobjects[$this->xobjid]['w'] = $w; $this->xobjects[$this->xobjid]['h'] = $h; $this->w = $w; $this->h = $h; $this->wPt = $this->w * $this->k; $this->hPt = $this->h * $this->k; $this->fwPt = $this->wPt; $this->fhPt = $this->hPt; $this->x = 0; $this->y = 0; $this->lMargin = 0; $this->rMargin = 0; $this->tMargin = 0; $this->bMargin = 0; // set group mode $this->xobjects[$this->xobjid]['group'] = $group; return $this->xobjid; } /** * End the current XObject Template started with startTemplate() and restore the previous graphic state. * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. * @return int the XObject Template ID in case of success or false in case of error. * @author Nicola Asuni * @public * @since 5.8.017 (2010-08-24) * @see startTemplate(), printTemplate() */ public function endTemplate() { if (!$this->inxobj) { // we are not inside a template return false; } $this->inxobj = false; // restore previous graphic state $this->setGraphicVars($this->xobjects[$this->xobjid]['gvars'], true); return $this->xobjid; } /** * Print an XObject Template. * You can print an XObject Template inside the currently opened Template. * An XObject Template is a PDF block that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). * An XObject Template may be painted multiple times, either on several pages or at several locations on the same page and produces the same results each time, subject only to the graphics state at the time it is invoked. * @param $id (string) The ID of XObject Template to print. * @param $x (int) X position in user units (empty string = current x position) * @param $y (int) Y position in user units (empty string = current y position) * @param $w (int) Width in user units (zero = remaining page width) * @param $h (int) Height in user units (zero = remaining page height) * @param $align (string) Indicates the alignment of the pointer next to template insertion relative to template height. The value can be:
      • T: top-right for LTR or top-left for RTL
      • M: middle-right for LTR or middle-left for RTL
      • B: bottom-right for LTR or bottom-left for RTL
      • N: next line
      * @param $palign (string) Allows to center or align the template on the current line. Possible values are:
      • L : left align
      • C : center
      • R : right align
      • '' : empty string : left for LTR or right for RTL
      * @param $fitonpage (boolean) If true the template is resized to not exceed page dimensions. * @author Nicola Asuni * @public * @since 5.8.017 (2010-08-24) * @see startTemplate(), endTemplate() */ public function printTemplate($id, $x='', $y='', $w=0, $h=0, $align='', $palign='', $fitonpage=false) { if (!isset($this->xobjects[$id])) { $this->Error('The XObject Template \''.$id.'\' doesn\'t exist!'); } if ($this->inxobj) { if ($id == $this->xobjid) { // close current template $this->endTemplate(); } else { // use the template as resource for the template currently opened $this->xobjects[$this->xobjid]['xobjects'][$id] = $this->xobjects[$id]; } } // set default values if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); $ow = $this->xobjects[$id]['w']; $oh = $this->xobjects[$id]['h']; // calculate template width and height on document if (($w <= 0) AND ($h <= 0)) { $w = $ow; $h = $oh; } elseif ($w <= 0) { $w = $h * $ow / $oh; } elseif ($h <= 0) { $h = $w * $oh / $ow; } // fit the template on available space list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage); // set page alignment $rb_y = $y + $h; // set alignment if ($this->rtl) { if ($palign == 'L') { $xt = $this->lMargin; } elseif ($palign == 'C') { $xt = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($palign == 'R') { $xt = $this->w - $this->rMargin - $w; } else { $xt = $x - $w; } $rb_x = $xt; } else { if ($palign == 'L') { $xt = $this->lMargin; } elseif ($palign == 'C') { $xt = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($palign == 'R') { $xt = $this->w - $this->rMargin - $w; } else { $xt = $x; } $rb_x = $xt + $w; } // print XObject Template + Transformation matrix $this->StartTransform(); // translate and scale $sx = ($w / $this->xobjects[$id]['w']); $sy = ($h / $this->xobjects[$id]['h']); $tm = array(); $tm[0] = $sx; $tm[1] = 0; $tm[2] = 0; $tm[3] = $sy; $tm[4] = $xt * $this->k; $tm[5] = ($this->h - $h - $y) * $this->k; $this->Transform($tm); // set object $this->_out('/'.$id.' Do'); $this->StopTransform(); // add annotations if (!empty($this->xobjects[$id]['annotations'])) { foreach ($this->xobjects[$id]['annotations'] as $annot) { // transform original coordinates $coordlt = $this->getTransformationMatrixProduct($tm, array(1, 0, 0, 1, ($annot['x'] * $this->k), (-$annot['y'] * $this->k))); $ax = ($coordlt[4] / $this->k); $ay = ($this->h - $h - ($coordlt[5] / $this->k)); $coordrb = $this->getTransformationMatrixProduct($tm, array(1, 0, 0, 1, (($annot['x'] + $annot['w']) * $this->k), ((-$annot['y'] - $annot['h']) * $this->k))); $aw = ($coordrb[4] / $this->k) - $ax; $ah = ($this->h - $h - ($coordrb[5] / $this->k)) - $ay; $this->Annotation($ax, $ay, $aw, $ah, $annot['text'], $annot['opt'], $annot['spaces']); } } // set pointer to align the next text/objects switch($align) { case 'T': { $this->y = $y; $this->x = $rb_x; break; } case 'M': { $this->y = $y + round($h/2); $this->x = $rb_x; break; } case 'B': { $this->y = $rb_y; $this->x = $rb_x; break; } case 'N': { $this->SetY($rb_y); break; } default:{ break; } } } /** * Set the percentage of character stretching. * @param $perc (int) percentage of stretching (100 = no stretching) * @author Nicola Asuni * @public * @since 5.9.000 (2010-09-29) */ public function setFontStretching($perc=100) { $this->font_stretching = $perc; } /** * Get the percentage of character stretching. * @return float stretching value * @author Nicola Asuni * @public * @since 5.9.000 (2010-09-29) */ public function getFontStretching() { return $this->font_stretching; } /** * Set the amount to increase or decrease the space between characters in a text. * @param $spacing (float) amount to increase or decrease the space between characters in a text (0 = default spacing) * @author Nicola Asuni * @public * @since 5.9.000 (2010-09-29) */ public function setFontSpacing($spacing=0) { $this->font_spacing = $spacing; } /** * Get the amount to increase or decrease the space between characters in a text. * @return int font spacing (tracking/kerning) value * @author Nicola Asuni * @public * @since 5.9.000 (2010-09-29) */ public function getFontSpacing() { return $this->font_spacing; } /** * Return an array of no-write page regions * @return array of no-write page regions * @author Nicola Asuni * @public * @since 5.9.003 (2010-10-13) * @see setPageRegions(), addPageRegion() */ public function getPageRegions() { return $this->page_regions; } /** * Set no-write regions on page. * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. * You can set multiple regions for the same page. * @param $regions (array) array of no-write regions. For each region you can define an array as follow: ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right). Omit this parameter to remove all regions. * @author Nicola Asuni * @public * @since 5.9.003 (2010-10-13) * @see addPageRegion(), getPageRegions() */ public function setPageRegions($regions=array()) { // empty current regions array $this->page_regions = array(); // add regions foreach ($regions as $data) { $this->addPageRegion($data); } } /** * Add a single no-write region on selected page. * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. * You can set multiple regions for the same page. * @param $region (array) array of a single no-write region array: ('page' => page number or empy for current page, 'xt' => X top, 'yt' => Y top, 'xb' => X bottom, 'yb' => Y bottom, 'side' => page side 'L' = left or 'R' = right). * @author Nicola Asuni * @public * @since 5.9.003 (2010-10-13) * @see setPageRegions(), getPageRegions() */ public function addPageRegion($region) { if (!isset($region['page']) OR empty($region['page'])) { $region['page'] = $this->page; } if (isset($region['xt']) AND isset($region['xb']) AND ($region['xt'] > 0) AND ($region['xb'] > 0) AND isset($region['yt']) AND isset($region['yb']) AND ($region['yt'] >= 0) AND ($region['yt'] < $region['yb']) AND isset($region['side']) AND (($region['side'] == 'L') OR ($region['side'] == 'R'))) { $this->page_regions[] = $region; } } /** * Remove a single no-write region. * @param $key (int) region key * @author Nicola Asuni * @public * @since 5.9.003 (2010-10-13) * @see setPageRegions(), getPageRegions() */ public function removePageRegion($key) { if (isset($this->page_regions[$key])) { unset($this->page_regions[$key]); } } /** * Check page for no-write regions and adapt current coordinates and page margins if necessary. * A no-write region is a portion of the page with a rectangular or trapezium shape that will not be covered when writing text or html code. * A region is always aligned on the left or right side of the page ad is defined using a vertical segment. * @param $h (float) height of the text/image/object to print in user units * @param $x (float) current X coordinate in user units * @param $y (float) current Y coordinate in user units * @return array($x, $y) * @author Nicola Asuni * @protected * @since 5.9.003 (2010-10-13) */ protected function checkPageRegions($h, $x, $y) { // set default values if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } if (empty($this->page_regions)) { // no page regions defined return array($x, $y); } if (empty($h)) { $h = ($this->FontSize * $this->cell_height_ratio) + $this->cell_padding['T'] + $this->cell_padding['B']; } // check for page break if ($this->checkPageBreak($h, $y)) { // the content will be printed on a new page $x = $this->x; $y = $this->y; } if ($this->num_columns > 1) { if ($this->rtl) { $this->lMargin = $this->columns[$this->current_column]['x'] - $this->columns[$this->current_column]['w']; } else { $this->rMargin = $this->w - $this->columns[$this->current_column]['x'] - $this->columns[$this->current_column]['w']; } } else { if ($this->rtl) { $this->lMargin = $this->original_lMargin; } else { $this->rMargin = $this->original_rMargin; } } // adjust coordinates and page margins foreach ($this->page_regions as $regid => $regdata) { if ($regdata['page'] == $this->page) { // check region boundaries if (($y > ($regdata['yt'] - $h)) AND ($y <= $regdata['yb'])) { // Y is inside the region $minv = ($regdata['xb'] - $regdata['xt']) / ($regdata['yb'] - $regdata['yt']); // inverse of angular coefficient $yt = max($y, $regdata['yt']); $yb = min(($yt + $h), $regdata['yb']); $xt = (($yt - $regdata['yt']) * $minv) + $regdata['xt']; $xb = (($yb - $regdata['yt']) * $minv) + $regdata['xt']; if ($regdata['side'] == 'L') { // left side $new_margin = max($xt, $xb); if ($this->lMargin < $new_margin) { if ($this->rtl) { // adjust left page margin $this->lMargin = $new_margin; } if ($x < $new_margin) { // adjust x position $x = $new_margin; if ($new_margin > ($this->w - $this->rMargin)) { // adjust y position $y = $regdata['yb'] - $h; } } } } elseif ($regdata['side'] == 'R') { // right side $new_margin = min($xt, $xb); if (($this->w - $this->rMargin) > $new_margin) { if (!$this->rtl) { // adjust right page margin $this->rMargin = ($this->w - $new_margin); } if ($x > $new_margin) { // adjust x position $x = $new_margin; if ($new_margin > $this->lMargin) { // adjust y position $y = $regdata['yb'] - $h; } } } } } } } return array($x, $y); } // --- SVG METHODS --------------------------------------------------------- /** * Embedd a Scalable Vector Graphics (SVG) image. * NOTE: SVG standard is not yet fully implemented, use the setRasterizeVectorImages() method to enable/disable rasterization of vector images using ImageMagick library. * @param $file (string) Name of the SVG file or a '@' character followed by the SVG data string. * @param $x (float) Abscissa of the upper-left corner. * @param $y (float) Ordinate of the upper-left corner. * @param $w (float) Width of the image in the page. If not specified or equal to zero, it is automatically calculated. * @param $h (float) Height of the image in the page. If not specified or equal to zero, it is automatically calculated. * @param $link (mixed) URL or identifier returned by AddLink(). * @param $align (string) Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:
      • T: top-right for LTR or top-left for RTL
      • M: middle-right for LTR or middle-left for RTL
      • B: bottom-right for LTR or bottom-left for RTL
      • N: next line
      If the alignment is an empty string, then the pointer will be restored on the starting SVG position. * @param $palign (string) Allows to center or align the image on the current line. Possible values are:
      • L : left align
      • C : center
      • R : right align
      • '' : empty string : left for LTR or right for RTL
      * @param $border (mixed) Indicates if borders must be drawn around the cell. The value can be a number:
      • 0: no border (default)
      • 1: frame
      or a string containing some or all of the following characters (in any order):
      • L: left
      • T: top
      • R: right
      • B: bottom
      or an array of line styles for each border group - for example: array('LTRB' => array('width' => 2, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(0, 0, 0))) * @param $fitonpage (boolean) if true the image is resized to not exceed page dimensions. * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @public */ public function ImageSVG($file, $x='', $y='', $w=0, $h=0, $link='', $align='', $palign='', $border=0, $fitonpage=false) { if ($this->rasterize_vector_images AND ($w > 0) AND ($h > 0)) { // convert SVG to raster image using GD or ImageMagick libraries return $this->Image($file, $x, $y, $w, $h, 'SVG', $link, $align, true, 300, $palign, false, false, $border, false, false, false); } if ($file{0} === '@') { // image from string $this->svgdir = ''; $svgdata = substr($file, 1); } else { // SVG file $this->svgdir = dirname($file); $svgdata = file_get_contents($file); } if ($svgdata === false) { $this->Error('SVG file not found: '.$file); } if ($x === '') { $x = $this->x; } if ($y === '') { $y = $this->y; } // check page for no-write regions and adapt page margins if necessary list($x, $y) = $this->checkPageRegions($h, $x, $y); $k = $this->k; $ox = 0; $oy = 0; $ow = $w; $oh = $h; $aspect_ratio_align = 'xMidYMid'; $aspect_ratio_ms = 'meet'; $regs = array(); // get original image width and height preg_match('/]*)>/si', $svgdata, $regs); if (isset($regs[1]) AND !empty($regs[1])) { $tmp = array(); if (preg_match('/[\s]+x[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { $ox = $this->getHTMLUnitToUnits($tmp[1], 0, $this->svgunit, false); } $tmp = array(); if (preg_match('/[\s]+y[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { $oy = $this->getHTMLUnitToUnits($tmp[1], 0, $this->svgunit, false); } $tmp = array(); if (preg_match('/[\s]+width[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { $ow = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false); } $tmp = array(); if (preg_match('/[\s]+height[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { $oh = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false); } $tmp = array(); $view_box = array(); if (preg_match('/[\s]+viewBox[\s]*=[\s]*"[\s]*([0-9\.\-]+)[\s]+([0-9\.\-]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]*"/si', $regs[1], $tmp)) { if (count($tmp) == 5) { array_shift($tmp); foreach ($tmp as $key => $val) { $view_box[$key] = $this->getHTMLUnitToUnits($val, 0, $this->svgunit, false); } $ox = $view_box[0]; $oy = $view_box[1]; } // get aspect ratio $tmp = array(); if (preg_match('/[\s]+preserveAspectRatio[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) { $aspect_ratio = preg_split('/[\s]+/si', $tmp[1]); switch (count($aspect_ratio)) { case 3: { $aspect_ratio_align = $aspect_ratio[1]; $aspect_ratio_ms = $aspect_ratio[2]; break; } case 2: { $aspect_ratio_align = $aspect_ratio[0]; $aspect_ratio_ms = $aspect_ratio[1]; break; } case 1: { $aspect_ratio_align = $aspect_ratio[0]; $aspect_ratio_ms = 'meet'; break; } } } } } // calculate image width and height on document if (($w <= 0) AND ($h <= 0)) { // convert image size to document unit $w = $ow; $h = $oh; } elseif ($w <= 0) { $w = $h * $ow / $oh; } elseif ($h <= 0) { $h = $w * $oh / $ow; } // fit the image on available space list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage); if ($this->rasterize_vector_images) { // convert SVG to raster image using GD or ImageMagick libraries return $this->Image($file, $x, $y, $w, $h, 'SVG', $link, $align, true, 300, $palign, false, false, $border, false, false, false); } // set alignment $this->img_rb_y = $y + $h; // set alignment if ($this->rtl) { if ($palign == 'L') { $ximg = $this->lMargin; } elseif ($palign == 'C') { $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($palign == 'R') { $ximg = $this->w - $this->rMargin - $w; } else { $ximg = $x - $w; } $this->img_rb_x = $ximg; } else { if ($palign == 'L') { $ximg = $this->lMargin; } elseif ($palign == 'C') { $ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2; } elseif ($palign == 'R') { $ximg = $this->w - $this->rMargin - $w; } else { $ximg = $x; } $this->img_rb_x = $ximg + $w; } // store current graphic vars $gvars = $this->getGraphicVars(); // store SVG position and scale factors $svgoffset_x = ($ximg - $ox) * $this->k; $svgoffset_y = -($y - $oy) * $this->k; if (isset($view_box[2]) AND ($view_box[2] > 0) AND ($view_box[3] > 0)) { $ow = $view_box[2]; $oh = $view_box[3]; } else { if ($ow <= 0) { $ow = $w; } if ($oh <= 0) { $oh = $h; } } $svgscale_x = $w / $ow; $svgscale_y = $h / $oh; // scaling and alignment if ($aspect_ratio_align != 'none') { // store current scaling values $svgscale_old_x = $svgscale_x; $svgscale_old_y = $svgscale_y; // force uniform scaling if ($aspect_ratio_ms == 'slice') { // the entire viewport is covered by the viewBox if ($svgscale_x > $svgscale_y) { $svgscale_y = $svgscale_x; } elseif ($svgscale_x < $svgscale_y) { $svgscale_x = $svgscale_y; } } else { // meet // the entire viewBox is visible within the viewport if ($svgscale_x < $svgscale_y) { $svgscale_y = $svgscale_x; } elseif ($svgscale_x > $svgscale_y) { $svgscale_x = $svgscale_y; } } // correct X alignment switch (substr($aspect_ratio_align, 1, 3)) { case 'Min': { // do nothing break; } case 'Max': { $svgoffset_x += (($w * $this->k) - ($ow * $this->k * $svgscale_x)); break; } default: case 'Mid': { $svgoffset_x += ((($w * $this->k) - ($ow * $this->k * $svgscale_x)) / 2); break; } } // correct Y alignment switch (substr($aspect_ratio_align, 5)) { case 'Min': { // do nothing break; } case 'Max': { $svgoffset_y -= (($h * $this->k) - ($oh * $this->k * $svgscale_y)); break; } default: case 'Mid': { $svgoffset_y -= ((($h * $this->k) - ($oh * $this->k * $svgscale_y)) / 2); break; } } } // store current page break mode $page_break_mode = $this->AutoPageBreak; $page_break_margin = $this->getBreakMargin(); $cell_padding = $this->cell_padding; $this->SetCellPadding(0); $this->SetAutoPageBreak(false); // save the current graphic state $this->_out('q'.$this->epsmarker); // set initial clipping mask $this->Rect($x, $y, $w, $h, 'CNZ', array(), array()); // scale and translate $e = $ox * $this->k * (1 - $svgscale_x); $f = ($this->h - $oy) * $this->k * (1 - $svgscale_y); $this->_out(sprintf('%.3F %.3F %.3F %.3F %.3F %.3F cm', $svgscale_x, 0, 0, $svgscale_y, $e + $svgoffset_x, $f + $svgoffset_y)); // creates a new XML parser to be used by the other XML functions $this->parser = xml_parser_create('UTF-8'); // the following function allows to use parser inside object xml_set_object($this->parser, $this); // disable case-folding for this XML parser xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0); // sets the element handler functions for the XML parser xml_set_element_handler($this->parser, 'startSVGElementHandler', 'endSVGElementHandler'); // sets the character data handler function for the XML parser xml_set_character_data_handler($this->parser, 'segSVGContentHandler'); // start parsing an XML document if (!xml_parse($this->parser, $svgdata)) { $error_message = sprintf('SVG Error: %s at line %d', xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser)); $this->Error($error_message); } // free this XML parser xml_parser_free($this->parser); // restore previous graphic state $this->_out($this->epsmarker.'Q'); // restore graphic vars $this->setGraphicVars($gvars); $this->lasth = $gvars['lasth']; if (!empty($border)) { $bx = $this->x; $by = $this->y; $this->x = $ximg; if ($this->rtl) { $this->x += $w; } $this->y = $y; $this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true); $this->x = $bx; $this->y = $by; } if ($link) { $this->Link($ximg, $y, $w, $h, $link, 0); } // set pointer to align the next text/objects switch($align) { case 'T':{ $this->y = $y; $this->x = $this->img_rb_x; break; } case 'M':{ $this->y = $y + round($h/2); $this->x = $this->img_rb_x; break; } case 'B':{ $this->y = $this->img_rb_y; $this->x = $this->img_rb_x; break; } case 'N':{ $this->SetY($this->img_rb_y); break; } default:{ // restore pointer to starting position $this->x = $gvars['x']; $this->y = $gvars['y']; $this->page = $gvars['page']; $this->current_column = $gvars['current_column']; $this->tMargin = $gvars['tMargin']; $this->bMargin = $gvars['bMargin']; $this->w = $gvars['w']; $this->h = $gvars['h']; $this->wPt = $gvars['wPt']; $this->hPt = $gvars['hPt']; $this->fwPt = $gvars['fwPt']; $this->fhPt = $gvars['fhPt']; break; } } $this->endlinex = $this->img_rb_x; // restore page break $this->SetAutoPageBreak($page_break_mode, $page_break_margin); $this->cell_padding = $cell_padding; } /** * Get the tranformation matrix from SVG transform attribute * @param $attribute (string) transformation * @return array of transformations * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected */ protected function getSVGTransformMatrix($attribute) { // identity matrix $tm = array(1, 0, 0, 1, 0, 0); $transform = array(); if (preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)[\s]*\(([^\)]+)\)/si', $attribute, $transform, PREG_SET_ORDER) > 0) { foreach ($transform as $key => $data) { if (!empty($data[2])) { $a = 1; $b = 0; $c = 0; $d = 1; $e = 0; $f = 0; $regs = array(); switch ($data[1]) { case 'matrix': { if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) { $a = $regs[1]; $b = $regs[2]; $c = $regs[3]; $d = $regs[4]; $e = $regs[5]; $f = $regs[6]; } break; } case 'translate': { if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) { $e = $regs[1]; $f = $regs[2]; } elseif (preg_match('/([a-z0-9\-\.]+)/si', $data[2], $regs)) { $e = $regs[1]; } break; } case 'scale': { if (preg_match('/([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) { $a = $regs[1]; $d = $regs[2]; } elseif (preg_match('/([a-z0-9\-\.]+)/si', $data[2], $regs)) { $a = $regs[1]; $d = $a; } break; } case 'rotate': { if (preg_match('/([0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)[\,\s]+([a-z0-9\-\.]+)/si', $data[2], $regs)) { $ang = deg2rad($regs[1]); $x = $regs[2]; $y = $regs[3]; $a = cos($ang); $b = sin($ang); $c = -$b; $d = $a; $e = ($x * (1 - $a)) - ($y * $c); $f = ($y * (1 - $d)) - ($x * $b); } elseif (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) { $ang = deg2rad($regs[1]); $a = cos($ang); $b = sin($ang); $c = -$b; $d = $a; $e = 0; $f = 0; } break; } case 'skewX': { if (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) { $c = tan(deg2rad($regs[1])); } break; } case 'skewY': { if (preg_match('/([0-9\-\.]+)/si', $data[2], $regs)) { $b = tan(deg2rad($regs[1])); } break; } } $tm = $this->getTransformationMatrixProduct($tm, array($a, $b, $c, $d, $e, $f)); } } } return $tm; } /** * Get the product of two SVG tranformation matrices * @param $ta (array) first SVG tranformation matrix * @param $tb (array) second SVG tranformation matrix * @return transformation array * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected */ protected function getTransformationMatrixProduct($ta, $tb) { $tm = array(); $tm[0] = ($ta[0] * $tb[0]) + ($ta[2] * $tb[1]); $tm[1] = ($ta[1] * $tb[0]) + ($ta[3] * $tb[1]); $tm[2] = ($ta[0] * $tb[2]) + ($ta[2] * $tb[3]); $tm[3] = ($ta[1] * $tb[2]) + ($ta[3] * $tb[3]); $tm[4] = ($ta[0] * $tb[4]) + ($ta[2] * $tb[5]) + $ta[4]; $tm[5] = ($ta[1] * $tb[4]) + ($ta[3] * $tb[5]) + $ta[5]; return $tm; } /** * Convert SVG transformation matrix to PDF. * @param $tm (array) original SVG transformation matrix * @return array transformation matrix * @protected * @since 5.0.000 (2010-05-02) */ protected function convertSVGtMatrix($tm) { $a = $tm[0]; $b = -$tm[1]; $c = -$tm[2]; $d = $tm[3]; $e = $this->getHTMLUnitToUnits($tm[4], 1, $this->svgunit, false) * $this->k; $f = -$this->getHTMLUnitToUnits($tm[5], 1, $this->svgunit, false) * $this->k; $x = 0; $y = $this->h * $this->k; $e = ($x * (1 - $a)) - ($y * $c) + $e; $f = ($y * (1 - $d)) - ($x * $b) + $f; return array($a, $b, $c, $d, $e, $f); } /** * Apply SVG graphic transformation matrix. * @param $tm (array) original SVG transformation matrix * @protected * @since 5.0.000 (2010-05-02) */ protected function SVGTransform($tm) { $this->Transform($this->convertSVGtMatrix($tm)); } /** * Apply the requested SVG styles (*** TO BE COMPLETED ***) * @param $svgstyle (array) array of SVG styles to apply * @param $prevsvgstyle (array) array of previous SVG style * @param $x (int) X origin of the bounding box * @param $y (int) Y origin of the bounding box * @param $w (int) width of the bounding box * @param $h (int) height of the bounding box * @param $clip_function (string) clip function * @param $clip_params (array) array of parameters for clipping function * @return object style * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected */ protected function setSVGStyles($svgstyle, $prevsvgstyle, $x=0, $y=0, $w=1, $h=1, $clip_function='', $clip_params=array()) { $objstyle = ''; $minlen = (0.01 / $this->k); // minimum acceptable length (3 point) if (!isset($svgstyle['opacity'])) { return $objstyle; } // clip-path $regs = array(); if (preg_match('/url\([\s]*\#([^\)]*)\)/si', $svgstyle['clip-path'], $regs)) { $clip_path = $this->svgclippaths[$regs[1]]; foreach ($clip_path as $cp) { $this->startSVGElementHandler('clip-path', $cp['name'], $cp['attribs'], $cp['tm']); } } // opacity if ($svgstyle['opacity'] != 1) { $this->SetAlpha($svgstyle['opacity']); } // color $fill_color = $this->convertHTMLColorToDec($svgstyle['color']); $this->SetFillColorArray($fill_color); // text color $text_color = $this->convertHTMLColorToDec($svgstyle['text-color']); $this->SetTextColorArray($text_color); // clip if (preg_match('/rect\(([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)\)/si', $svgstyle['clip'], $regs)) { $top = (isset($regs[1])?$this->getHTMLUnitToUnits($regs[1], 0, $this->svgunit, false):0); $right = (isset($regs[2])?$this->getHTMLUnitToUnits($regs[2], 0, $this->svgunit, false):0); $bottom = (isset($regs[3])?$this->getHTMLUnitToUnits($regs[3], 0, $this->svgunit, false):0); $left = (isset($regs[4])?$this->getHTMLUnitToUnits($regs[4], 0, $this->svgunit, false):0); $cx = $x + $left; $cy = $y + $top; $cw = $w - $left - $right; $ch = $h - $top - $bottom; if ($svgstyle['clip-rule'] == 'evenodd') { $clip_rule = 'CNZ'; } else { $clip_rule = 'CEO'; } $this->Rect($cx, $cy, $cw, $ch, $clip_rule, array(), array()); } // fill $regs = array(); if (preg_match('/url\([\s]*\#([^\)]*)\)/si', $svgstyle['fill'], $regs)) { // gradient $gradient = $this->svggradients[$regs[1]]; if (isset($gradient['xref'])) { // reference to another gradient definition $newgradient = $this->svggradients[$gradient['xref']]; $newgradient['coords'] = $gradient['coords']; $newgradient['mode'] = $gradient['mode']; $newgradient['gradientUnits'] = $gradient['gradientUnits']; if (isset($gradient['gradientTransform'])) { $newgradient['gradientTransform'] = $gradient['gradientTransform']; } $gradient = $newgradient; } //save current Graphic State $this->_out('q'); //set clipping area if (!empty($clip_function) AND method_exists($this, $clip_function)) { $bbox = call_user_func_array(array($this, $clip_function), $clip_params); if (is_array($bbox) AND (count($bbox) == 4)) { list($x, $y, $w, $h) = $bbox; } } if ($gradient['mode'] == 'measure') { if (isset($gradient['gradientTransform']) AND !empty($gradient['gradientTransform'])) { $gtm = $gradient['gradientTransform']; // apply transformation matrix $xa = ($gtm[0] * $gradient['coords'][0]) + ($gtm[2] * $gradient['coords'][1]) + $gtm[4]; $ya = ($gtm[1] * $gradient['coords'][0]) + ($gtm[3] * $gradient['coords'][1]) + $gtm[5]; $xb = ($gtm[0] * $gradient['coords'][2]) + ($gtm[2] * $gradient['coords'][3]) + $gtm[4]; $yb = ($gtm[1] * $gradient['coords'][2]) + ($gtm[3] * $gradient['coords'][3]) + $gtm[5]; if (isset($gradient['coords'][4])) { $gradient['coords'][4] = sqrt(pow(($gtm[0] * $gradient['coords'][4]), 2) + pow(($gtm[1] * $gradient['coords'][4]), 2)); } $gradient['coords'][0] = $xa; $gradient['coords'][1] = $ya; $gradient['coords'][2] = $xb; $gradient['coords'][3] = $yb; } // convert SVG coordinates to user units $gradient['coords'][0] = $this->getHTMLUnitToUnits($gradient['coords'][0], 0, $this->svgunit, false); $gradient['coords'][1] = $this->getHTMLUnitToUnits($gradient['coords'][1], 0, $this->svgunit, false); $gradient['coords'][2] = $this->getHTMLUnitToUnits($gradient['coords'][2], 0, $this->svgunit, false); $gradient['coords'][3] = $this->getHTMLUnitToUnits($gradient['coords'][3], 0, $this->svgunit, false); if (isset($gradient['coords'][4])) { $gradient['coords'][4] = $this->getHTMLUnitToUnits($gradient['coords'][4], 0, $this->svgunit, false); } if ($w <= $minlen) { $w = $minlen; } if ($h <= $minlen) { $h = $minlen; } // shift units if ($gradient['gradientUnits'] == 'objectBoundingBox') { // convert to SVG coordinate system $gradient['coords'][0] += $x; $gradient['coords'][1] += $y; $gradient['coords'][2] += $x; $gradient['coords'][3] += $y; } // calculate percentages $gradient['coords'][0] = ($gradient['coords'][0] - $x) / $w; $gradient['coords'][1] = ($gradient['coords'][1] - $y) / $h; $gradient['coords'][2] = ($gradient['coords'][2] - $x) / $w; $gradient['coords'][3] = ($gradient['coords'][3] - $y) / $h; if (isset($gradient['coords'][4])) { $gradient['coords'][4] /= $w; } } elseif ($gradient['mode'] == 'percentage') { foreach($gradient['coords'] as $key => $val) { $gradient['coords'][$key] = (intval($val) / 100); if ($val < 0) { $gradient['coords'][$key] = 0; } elseif ($val > 1) { $gradient['coords'][$key] = 1; } } } if (($gradient['type'] == 2) AND ($gradient['coords'][0] == $gradient['coords'][2]) AND ($gradient['coords'][1] == $gradient['coords'][3])) { // single color (no shading) $gradient['coords'][0] = 1; $gradient['coords'][1] = 0; $gradient['coords'][2] = 0.999; $gradient['coords'][3] = 0; } // swap Y coordinates $tmp = $gradient['coords'][1]; $gradient['coords'][1] = $gradient['coords'][3]; $gradient['coords'][3] = $tmp; // set transformation map for gradient if ($gradient['type'] == 3) { // circular gradient $cy = $this->h - $y - ($gradient['coords'][1] * ($w + $h)); $this->_out(sprintf('%.3F 0 0 %.3F %.3F %.3F cm', $w*$this->k, $w*$this->k, $x*$this->k, $cy*$this->k)); } else { $this->_out(sprintf('%.3F 0 0 %.3F %.3F %.3F cm', $w*$this->k, $h*$this->k, $x*$this->k, ($this->h-($y+$h))*$this->k)); } if (count($gradient['stops']) > 1) { $this->Gradient($gradient['type'], $gradient['coords'], $gradient['stops'], array(), false); } } elseif ($svgstyle['fill'] != 'none') { $fill_color = $this->convertHTMLColorToDec($svgstyle['fill']); if ($svgstyle['fill-opacity'] != 1) { $this->SetAlpha($svgstyle['fill-opacity']); } $this->SetFillColorArray($fill_color); if ($svgstyle['fill-rule'] == 'evenodd') { $objstyle .= 'F*'; } else { $objstyle .= 'F'; } } // stroke if ($svgstyle['stroke'] != 'none') { $stroke_style = array( 'color' => $this->convertHTMLColorToDec($svgstyle['stroke']), 'width' => $this->getHTMLUnitToUnits($svgstyle['stroke-width'], 0, $this->svgunit, false), 'cap' => $svgstyle['stroke-linecap'], 'join' => $svgstyle['stroke-linejoin'] ); if (isset($svgstyle['stroke-dasharray']) AND !empty($svgstyle['stroke-dasharray']) AND ($svgstyle['stroke-dasharray'] != 'none')) { $stroke_style['dash'] = $svgstyle['stroke-dasharray']; } $this->SetLineStyle($stroke_style); $objstyle .= 'D'; } // font $regs = array(); if (!empty($svgstyle['font'])) { if (preg_match('/font-family[\s]*:[\s]*([^\;\"]*)/si', $svgstyle['font'], $regs)) { $font_family = $this->getFontFamilyName($regs[1]); } else { $font_family = $svgstyle['font-family']; } if (preg_match('/font-size[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { $font_size = trim($regs[1]); } else { $font_size = $svgstyle['font-size']; } if (preg_match('/font-style[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { $font_style = trim($regs[1]); } else { $font_style = $svgstyle['font-style']; } if (preg_match('/font-weight[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { $font_weight = trim($regs[1]); } else { $font_weight = $svgstyle['font-weight']; } if (preg_match('/font-stretch[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { $font_stretch = trim($regs[1]); } else { $font_stretch = $svgstyle['font-stretch']; } if (preg_match('/letter-spacing[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) { $font_spacing = trim($regs[1]); } else { $font_spacing = $svgstyle['letter-spacing']; } } else { $font_family = $this->getFontFamilyName($svgstyle['font-family']); $font_size = $svgstyle['font-size']; $font_style = $svgstyle['font-style']; $font_weight = $svgstyle['font-weight']; $font_stretch = $svgstyle['font-stretch']; $font_spacing = $svgstyle['letter-spacing']; } $font_size = $this->getHTMLUnitToUnits($font_size, $prevsvgstyle['font-size'], $this->svgunit, false) * $this->k; $font_stretch = $this->getCSSFontStretching($font_stretch, $svgstyle['font-stretch']); $font_spacing = $this->getCSSFontSpacing($font_spacing, $svgstyle['letter-spacing']); switch ($font_style) { case 'italic': { $font_style = 'I'; break; } case 'oblique': { $font_style = 'I'; break; } default: case 'normal': { $font_style = ''; break; } } switch ($font_weight) { case 'bold': case 'bolder': { $font_style .= 'B'; break; } } switch ($svgstyle['text-decoration']) { case 'underline': { $font_style .= 'U'; break; } case 'overline': { $font_style .= 'O'; break; } case 'line-through': { $font_style .= 'D'; break; } default: case 'none': { break; } } $this->SetFont($font_family, $font_style, $font_size); $this->setFontStretching($font_stretch); $this->setFontSpacing($font_spacing); return $objstyle; } /** * Draws an SVG path * @param $d (string) attribute d of the path SVG element * @param $style (string) Style of rendering. Possible values are: *
        *
      • D or empty string: Draw (default).
      • *
      • F: Fill.
      • *
      • F*: Fill using the even-odd rule to determine which regions lie inside the clipping path.
      • *
      • DF or FD: Draw and fill.
      • *
      • DF* or FD*: Draw and fill using the even-odd rule to determine which regions lie inside the clipping path.
      • *
      • CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).
      • *
      • CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).
      • *
      * @return array of container box measures (x, y, w, h) * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected */ protected function SVGPath($d, $style='') { // set fill/stroke style $op = $this->getPathPaintOperator($style, ''); if (empty($op)) { return; } $paths = array(); $d = preg_replace('/([0-9ACHLMQSTVZ])([\-\+])/si', '\\1 \\2', $d); preg_match_all('/([ACHLMQSTVZ])[\s]*([^ACHLMQSTVZ\"]*)/si', $d, $paths, PREG_SET_ORDER); $x = 0; $y = 0; $x1 = 0; $y1 = 0; $x2 = 0; $y2 = 0; $xmin = 2147483647; $xmax = 0; $ymin = 2147483647; $ymax = 0; $relcoord = false; $minlen = (0.01 / $this->k); // minimum acceptable length (3 point) $firstcmd = true; // used to print first point // draw curve pieces foreach ($paths as $key => $val) { // get curve type $cmd = trim($val[1]); if (strtolower($cmd) == $cmd) { // use relative coordinated instead of absolute $relcoord = true; $xoffset = $x; $yoffset = $y; } else { $relcoord = false; $xoffset = 0; $yoffset = 0; } $params = array(); if (isset($val[2])) { // get curve parameters $rawparams = preg_split('/([\,\s]+)/si', trim($val[2])); $params = array(); foreach ($rawparams as $ck => $cp) { $params[$ck] = $this->getHTMLUnitToUnits($cp, 0, $this->svgunit, false); if (abs($params[$ck]) < $minlen) { // aproximate little values to zero $params[$ck] = 0; } } } // store current origin point $x0 = $x; $y0 = $y; switch (strtoupper($cmd)) { case 'M': { // moveto foreach ($params as $ck => $cp) { if (($ck % 2) == 0) { $x = $cp + $xoffset; } else { $y = $cp + $yoffset; if ($firstcmd OR (abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) { if ($ck == 1) { $this->_outPoint($x, $y); $firstcmd = false; } else { $this->_outLine($x, $y); } } $xmin = min($xmin, $x); $ymin = min($ymin, $y); $xmax = max($xmax, $x); $ymax = max($ymax, $y); if ($relcoord) { $xoffset = $x; $yoffset = $y; } } } break; } case 'L': { // lineto foreach ($params as $ck => $cp) { if (($ck % 2) == 0) { $x = $cp + $xoffset; } else { $y = $cp + $yoffset; if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) { $this->_outLine($x, $y); } $xmin = min($xmin, $x); $ymin = min($ymin, $y); $xmax = max($xmax, $x); $ymax = max($ymax, $y); if ($relcoord) { $xoffset = $x; $yoffset = $y; } } } break; } case 'H': { // horizontal lineto foreach ($params as $ck => $cp) { $x = $cp + $xoffset; if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) { $this->_outLine($x, $y); } $xmin = min($xmin, $x); $xmax = max($xmax, $x); if ($relcoord) { $xoffset = $x; } } break; } case 'V': { // vertical lineto foreach ($params as $ck => $cp) { $y = $cp + $yoffset; if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) { $this->_outLine($x, $y); } $ymin = min($ymin, $y); $ymax = max($ymax, $y); if ($relcoord) { $yoffset = $y; } } break; } case 'C': { // curveto foreach ($params as $ck => $cp) { $params[$ck] = $cp; if ((($ck + 1) % 6) == 0) { $x1 = $params[($ck - 5)] + $xoffset; $y1 = $params[($ck - 4)] + $yoffset; $x2 = $params[($ck - 3)] + $xoffset; $y2 = $params[($ck - 2)] + $yoffset; $x = $params[($ck - 1)] + $xoffset; $y = $params[($ck)] + $yoffset; $this->_outCurve($x1, $y1, $x2, $y2, $x, $y); $xmin = min($xmin, $x, $x1, $x2); $ymin = min($ymin, $y, $y1, $y2); $xmax = max($xmax, $x, $x1, $x2); $ymax = max($ymax, $y, $y1, $y2); if ($relcoord) { $xoffset = $x; $yoffset = $y; } } } break; } case 'S': { // shorthand/smooth curveto foreach ($params as $ck => $cp) { $params[$ck] = $cp; if ((($ck + 1) % 4) == 0) { if (($key > 0) AND ((strtoupper($paths[($key - 1)][1]) == 'C') OR (strtoupper($paths[($key - 1)][1]) == 'S'))) { $x1 = (2 * $x) - $x2; $y1 = (2 * $y) - $y2; } else { $x1 = $x; $y1 = $y; } $x2 = $params[($ck - 3)] + $xoffset; $y2 = $params[($ck - 2)] + $yoffset; $x = $params[($ck - 1)] + $xoffset; $y = $params[($ck)] + $yoffset; $this->_outCurve($x1, $y1, $x2, $y2, $x, $y); $xmin = min($xmin, $x, $x1, $x2); $ymin = min($ymin, $y, $y1, $y2); $xmax = max($xmax, $x, $x1, $x2); $ymax = max($ymax, $y, $y1, $y2); if ($relcoord) { $xoffset = $x; $yoffset = $y; } } } break; } case 'Q': { // quadratic B騷ier curveto foreach ($params as $ck => $cp) { $params[$ck] = $cp; if ((($ck + 1) % 4) == 0) { // convert quadratic points to cubic points $x1 = $params[($ck - 3)] + $xoffset; $y1 = $params[($ck - 2)] + $yoffset; $xa = ($x + (2 * $x1)) / 3; $ya = ($y + (2 * $y1)) / 3; $x = $params[($ck - 1)] + $xoffset; $y = $params[($ck)] + $yoffset; $xb = ($x + (2 * $x1)) / 3; $yb = ($y + (2 * $y1)) / 3; $this->_outCurve($xa, $ya, $xb, $yb, $x, $y); $xmin = min($xmin, $x, $xa, $xb); $ymin = min($ymin, $y, $ya, $yb); $xmax = max($xmax, $x, $xa, $xb); $ymax = max($ymax, $y, $ya, $yb); if ($relcoord) { $xoffset = $x; $yoffset = $y; } } } break; } case 'T': { // shorthand/smooth quadratic B騷ier curveto foreach ($params as $ck => $cp) { $params[$ck] = $cp; if (($ck % 2) != 0) { if (($key > 0) AND ((strtoupper($paths[($key - 1)][1]) == 'Q') OR (strtoupper($paths[($key - 1)][1]) == 'T'))) { $x1 = (2 * $x) - $x1; $y1 = (2 * $y) - $y1; } else { $x1 = $x; $y1 = $y; } // convert quadratic points to cubic points $xa = ($x + (2 * $x1)) / 3; $ya = ($y + (2 * $y1)) / 3; $x = $params[($ck - 1)] + $xoffset; $y = $params[($ck)] + $yoffset; $xb = ($x + (2 * $x1)) / 3; $yb = ($y + (2 * $y1)) / 3; $this->_outCurve($xa, $ya, $xb, $yb, $x, $y); $xmin = min($xmin, $x, $xa, $xb); $ymin = min($ymin, $y, $ya, $yb); $xmax = max($xmax, $x, $xa, $xb); $ymax = max($ymax, $y, $ya, $yb); if ($relcoord) { $xoffset = $x; $yoffset = $y; } } } break; } case 'A': { // elliptical arc foreach ($params as $ck => $cp) { $params[$ck] = $cp; if ((($ck + 1) % 7) == 0) { $x0 = $x; $y0 = $y; $rx = abs($params[($ck - 6)]); $ry = abs($params[($ck - 5)]); $ang = -$rawparams[($ck - 4)]; $angle = deg2rad($ang); $fa = $rawparams[($ck - 3)]; // large-arc-flag $fs = $rawparams[($ck - 2)]; // sweep-flag $x = $params[($ck - 1)] + $xoffset; $y = $params[$ck] + $yoffset; if ((abs($x0 - $x) < $minlen) AND (abs($y0 - $y) < $minlen)) { // endpoints are almost identical $xmin = min($xmin, $x); $ymin = min($ymin, $y); $xmax = max($xmax, $x); $ymax = max($ymax, $y); } else { $cos_ang = cos($angle); $sin_ang = sin($angle); $a = (($x0 - $x) / 2); $b = (($y0 - $y) / 2); $xa = ($a * $cos_ang) - ($b * $sin_ang); $ya = ($a * $sin_ang) + ($b * $cos_ang); $rx2 = $rx * $rx; $ry2 = $ry * $ry; $xa2 = $xa * $xa; $ya2 = $ya * $ya; $delta = ($xa2 / $rx2) + ($ya2 / $ry2); if ($delta > 1) { $rx *= sqrt($delta); $ry *= sqrt($delta); $rx2 = $rx * $rx; $ry2 = $ry * $ry; } $numerator = (($rx2 * $ry2) - ($rx2 * $ya2) - ($ry2 * $xa2)); if ($numerator < 0) { $root = 0; } else { $root = sqrt($numerator / (($rx2 * $ya2) + ($ry2 * $xa2))); } if ($fa == $fs){ $root *= -1; } $cax = $root * (($rx * $ya) / $ry); $cay = -$root * (($ry * $xa) / $rx); // coordinates of ellipse center $cx = ($cax * $cos_ang) - ($cay * $sin_ang) + (($x0 + $x) / 2); $cy = ($cax * $sin_ang) + ($cay * $cos_ang) + (($y0 + $y) / 2); // get angles $angs = $this->getVectorsAngle(1, 0, (($xa - $cax) / $rx), (($cay - $ya) / $ry)); $dang = $this->getVectorsAngle((($xa - $cax) / $rx), (($ya - $cay) / $ry), ((-$xa - $cax) / $rx), ((-$ya - $cay) / $ry)); if (($fs == 0) AND ($dang > 0)) { $dang -= (2 * M_PI); } elseif (($fs == 1) AND ($dang < 0)) { $dang += (2 * M_PI); } $angf = $angs - $dang; if ((($fs == 0) AND ($angs > $angf)) OR (($fs == 1) AND ($angs < $angf))) { // reverse angles $tmp = $angs; $angs = $angf; $angf = $tmp; } $angs = round(rad2deg($angs), 6); $angf = round(rad2deg($angf), 6); // covent angles to positive values if (($angs < 0) AND ($angf < 0)) { $angs += 360; $angf += 360; } $pie = false; if (($key == 0) AND (isset($paths[($key + 1)][1])) AND (trim($paths[($key + 1)][1]) == 'z')) { $pie = true; } list($axmin, $aymin, $axmax, $aymax) = $this->_outellipticalarc($cx, $cy, $rx, $ry, $ang, $angs, $angf, $pie, 2, false, ($fs == 0), true); $xmin = min($xmin, $x, $axmin); $ymin = min($ymin, $y, $aymin); $xmax = max($xmax, $x, $axmax); $ymax = max($ymax, $y, $aymax); } if ($relcoord) { $xoffset = $x; $yoffset = $y; } } } break; } case 'Z': { $this->_out('h'); break; } } $firstcmd = false; } // end foreach if (!empty($op)) { $this->_out($op); } return array($xmin, $ymin, ($xmax - $xmin), ($ymax - $ymin)); } /** * Returns the angle in radiants between two vectors * @param $x1 (int) X coordinate of first vector point * @param $y1 (int) Y coordinate of first vector point * @param $x2 (int) X coordinate of second vector point * @param $y2 (int) Y coordinate of second vector point * @author Nicola Asuni * @since 5.0.000 (2010-05-04) * @protected */ protected function getVectorsAngle($x1, $y1, $x2, $y2) { $dprod = ($x1 * $x2) + ($y1 * $y2); $dist1 = sqrt(($x1 * $x1) + ($y1 * $y1)); $dist2 = sqrt(($x2 * $x2) + ($y2 * $y2)); $angle = acos($dprod / ($dist1 * $dist2)); if (is_nan($angle)) { $angle = M_PI; } if ((($x1 * $y2) - ($x2 * $y1)) < 0) { $angle *= -1; } return $angle; } /** * Sets the opening SVG element handler function for the XML parser. (*** TO BE COMPLETED ***) * @param $parser (resource) The first parameter, parser, is a reference to the XML parser calling the handler. * @param $name (string) The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. * @param $attribs (array) The third parameter, attribs, contains an associative array with the element's attributes (if any). The keys of this array are the attribute names, the values are the attribute values. Attribute names are case-folded on the same criteria as element names. Attribute values are not case-folded. The original order of the attributes can be retrieved by walking through attribs the normal way, using each(). The first key in the array was the first attribute, and so on. * @param $ctm (array) tranformation matrix for clipping mode (starting transformation matrix). * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected */ protected function startSVGElementHandler($parser, $name, $attribs, $ctm=array()) { // check if we are in clip mode if ($this->svgclipmode) { $this->svgclippaths[$this->svgclipid][] = array('name' => $name, 'attribs' => $attribs, 'tm' => $this->svgcliptm[$this->svgclipid]); return; } if ($this->svgdefsmode AND !in_array($name, array('clipPath', 'linearGradient', 'radialGradient', 'stop'))) { if (!isset($attribs['id'])) { $attribs['id'] = 'DF_'.(count($this->svgdefs) + 1); } $this->svgdefs[$attribs['id']] = array('name' => $name, 'attribs' => $attribs); return; } $clipping = false; if ($parser == 'clip-path') { // set clipping mode $clipping = true; } // get styling properties $prev_svgstyle = $this->svgstyles[(count($this->svgstyles) - 1)]; // previous style $svgstyle = $this->svgstyles[0]; // set default style if (isset($attribs['style']) AND !$this->empty_string($attribs['style'])) { // fix style for regular expression $attribs['style'] = ';'.$attribs['style']; } foreach ($prev_svgstyle as $key => $val) { if (in_array($key, $this->svginheritprop)) { // inherit previous value $svgstyle[$key] = $val; } if (isset($attribs[$key]) AND !$this->empty_string($attribs[$key])) { // specific attribute settings if ($attribs[$key] == 'inherit') { $svgstyle[$key] = $val; } else { $svgstyle[$key] = $attribs[$key]; } } elseif (isset($attribs['style']) AND !$this->empty_string($attribs['style'])) { // CSS style syntax $attrval = array(); if (preg_match('/[;\"\s]{1}'.$key.'[\s]*:[\s]*([^;\"]*)/si', $attribs['style'], $attrval) AND isset($attrval[1])) { if ($attrval[1] == 'inherit') { $svgstyle[$key] = $val; } else { $svgstyle[$key] = $attrval[1]; } } } } // transformation matrix if (!empty($ctm)) { $tm = $ctm; } else { $tm = $this->svgstyles[(count($this->svgstyles) - 1)]['transfmatrix']; } if (isset($attribs['transform']) AND !empty($attribs['transform'])) { $tm = $this->getTransformationMatrixProduct($tm, $this->getSVGTransformMatrix($attribs['transform'])); } $svgstyle['transfmatrix'] = $tm; $invisible = false; if (($svgstyle['visibility'] == 'hidden') OR ($svgstyle['visibility'] == 'collapse') OR ($svgstyle['display'] == 'none')) { // the current graphics element is invisible (nothing is painted) $invisible = true; } // process tag switch($name) { case 'defs': { $this->svgdefsmode = true; break; } // clipPath case 'clipPath': { if ($invisible) { break; } $this->svgclipmode = true; if (!isset($attribs['id'])) { $attribs['id'] = 'CP_'.(count($this->svgcliptm) + 1); } $this->svgclipid = $attribs['id']; $this->svgclippaths[$this->svgclipid] = array(); $this->svgcliptm[$this->svgclipid] = $tm; break; } case 'svg': { // start of SVG object break; } case 'g': { // group together related graphics elements array_push($this->svgstyles, $svgstyle); $this->StartTransform(); $this->setSVGStyles($svgstyle, $prev_svgstyle); break; } case 'linearGradient': { if ($this->pdfa_mode) { break; } if (!isset($attribs['id'])) { $attribs['id'] = 'GR_'.(count($this->svggradients) + 1); } $this->svggradientid = $attribs['id']; $this->svggradients[$this->svggradientid] = array(); $this->svggradients[$this->svggradientid]['type'] = 2; $this->svggradients[$this->svggradientid]['stops'] = array(); if (isset($attribs['gradientUnits'])) { $this->svggradients[$this->svggradientid]['gradientUnits'] = $attribs['gradientUnits']; } else { $this->svggradients[$this->svggradientid]['gradientUnits'] = 'objectBoundingBox'; } //$attribs['spreadMethod'] $x1 = (isset($attribs['x1'])?$attribs['x1']:'0%'); $y1 = (isset($attribs['y1'])?$attribs['y1']:'0%'); $x2 = (isset($attribs['x2'])?$attribs['x2']:'100%'); $y2 = (isset($attribs['y2'])?$attribs['y2']:'0%'); if (substr($x1, -1) != '%') { $this->svggradients[$this->svggradientid]['mode'] = 'measure'; } else { $this->svggradients[$this->svggradientid]['mode'] = 'percentage'; } if (isset($attribs['gradientTransform'])) { $this->svggradients[$this->svggradientid]['gradientTransform'] = $this->getSVGTransformMatrix($attribs['gradientTransform']); } $this->svggradients[$this->svggradientid]['coords'] = array($x1, $y1, $x2, $y2); if (isset($attribs['xlink:href']) AND !empty($attribs['xlink:href'])) { // gradient is defined on another place $this->svggradients[$this->svggradientid]['xref'] = substr($attribs['xlink:href'], 1); } break; } case 'radialGradient': { if ($this->pdfa_mode) { break; } if (!isset($attribs['id'])) { $attribs['id'] = 'GR_'.(count($this->svggradients) + 1); } $this->svggradientid = $attribs['id']; $this->svggradients[$this->svggradientid] = array(); $this->svggradients[$this->svggradientid]['type'] = 3; $this->svggradients[$this->svggradientid]['stops'] = array(); if (isset($attribs['gradientUnits'])) { $this->svggradients[$this->svggradientid]['gradientUnits'] = $attribs['gradientUnits']; } else { $this->svggradients[$this->svggradientid]['gradientUnits'] = 'objectBoundingBox'; } //$attribs['spreadMethod'] $cx = (isset($attribs['cx'])?$attribs['cx']:0.5); $cy = (isset($attribs['cy'])?$attribs['cy']:0.5); $fx = (isset($attribs['fx'])?$attribs['fx']:$cx); $fy = (isset($attribs['fy'])?$attribs['fy']:$cy); $r = (isset($attribs['r'])?$attribs['r']:0.5); if (isset($attribs['cx']) AND (substr($attribs['cx'], -1) != '%')) { $this->svggradients[$this->svggradientid]['mode'] = 'measure'; } else { $this->svggradients[$this->svggradientid]['mode'] = 'percentage'; } if (isset($attribs['gradientTransform'])) { $this->svggradients[$this->svggradientid]['gradientTransform'] = $this->getSVGTransformMatrix($attribs['gradientTransform']); } $this->svggradients[$this->svggradientid]['coords'] = array($cx, $cy, $fx, $fy, $r); if (isset($attribs['xlink:href']) AND !empty($attribs['xlink:href'])) { // gradient is defined on another place $this->svggradients[$this->svggradientid]['xref'] = substr($attribs['xlink:href'], 1); } break; } case 'stop': { // gradient stops if (substr($attribs['offset'], -1) == '%') { $offset = floatval(substr($attribs['offset'], -1)) / 100; } else { $offset = floatval($attribs['offset']); if ($offset > 1) { $offset /= 100; } } $stop_color = isset($svgstyle['stop-color'])?$this->convertHTMLColorToDec($svgstyle['stop-color']):'black'; $opacity = isset($svgstyle['stop-opacity'])?$svgstyle['stop-opacity']:1; $this->svggradients[$this->svggradientid]['stops'][] = array('offset' => $offset, 'color' => $stop_color, 'opacity' => $opacity); break; } // paths case 'path': { if ($invisible) { break; } if (isset($attribs['d'])) { $d = trim($attribs['d']); if (!empty($d)) { if ($clipping) { $this->SVGTransform($tm); $this->SVGPath($d, 'CNZ'); } else { $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, 0, 0, 1, 1, 'SVGPath', array($d, 'CNZ')); if (!empty($obstyle)) { $this->SVGPath($d, $obstyle); } $this->StopTransform(); } } } break; } // shapes case 'rect': { if ($invisible) { break; } $x = (isset($attribs['x'])?$this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false):0); $y = (isset($attribs['y'])?$this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false):0); $w = (isset($attribs['width'])?$this->getHTMLUnitToUnits($attribs['width'], 0, $this->svgunit, false):0); $h = (isset($attribs['height'])?$this->getHTMLUnitToUnits($attribs['height'], 0, $this->svgunit, false):0); $rx = (isset($attribs['rx'])?$this->getHTMLUnitToUnits($attribs['rx'], 0, $this->svgunit, false):0); $ry = (isset($attribs['ry'])?$this->getHTMLUnitToUnits($attribs['ry'], 0, $this->svgunit, false):$rx); if ($clipping) { $this->SVGTransform($tm); $this->RoundedRectXY($x, $y, $w, $h, $rx, $ry, '1111', 'CNZ', array(), array()); } else { $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'RoundedRectXY', array($x, $y, $w, $h, $rx, $ry, '1111', 'CNZ')); if (!empty($obstyle)) { $this->RoundedRectXY($x, $y, $w, $h, $rx, $ry, '1111', $obstyle, array(), array()); } $this->StopTransform(); } break; } case 'circle': { if ($invisible) { break; } $cx = (isset($attribs['cx'])?$this->getHTMLUnitToUnits($attribs['cx'], 0, $this->svgunit, false):0); $cy = (isset($attribs['cy'])?$this->getHTMLUnitToUnits($attribs['cy'], 0, $this->svgunit, false):0); $r = (isset($attribs['r'])?$this->getHTMLUnitToUnits($attribs['r'], 0, $this->svgunit, false):0); $x = $cx - $r; $y = $cy - $r; $w = 2 * $r; $h = $w; if ($clipping) { $this->SVGTransform($tm); $this->Circle($cx, $cy, $r, 0, 360, 'CNZ', array(), array(), 8); } else { $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Circle', array($cx, $cy, $r, 0, 360, 'CNZ')); if (!empty($obstyle)) { $this->Circle($cx, $cy, $r, 0, 360, $obstyle, array(), array(), 8); } $this->StopTransform(); } break; } case 'ellipse': { if ($invisible) { break; } $cx = (isset($attribs['cx'])?$this->getHTMLUnitToUnits($attribs['cx'], 0, $this->svgunit, false):0); $cy = (isset($attribs['cy'])?$this->getHTMLUnitToUnits($attribs['cy'], 0, $this->svgunit, false):0); $rx = (isset($attribs['rx'])?$this->getHTMLUnitToUnits($attribs['rx'], 0, $this->svgunit, false):0); $ry = (isset($attribs['ry'])?$this->getHTMLUnitToUnits($attribs['ry'], 0, $this->svgunit, false):0); $x = $cx - $rx; $y = $cy - $ry; $w = 2 * $rx; $h = 2 * $ry; if ($clipping) { $this->SVGTransform($tm); $this->Ellipse($cx, $cy, $rx, $ry, 0, 0, 360, 'CNZ', array(), array(), 8); } else { $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Ellipse', array($cx, $cy, $rx, $ry, 0, 0, 360, 'CNZ')); if (!empty($obstyle)) { $this->Ellipse($cx, $cy, $rx, $ry, 0, 0, 360, $obstyle, array(), array(), 8); } $this->StopTransform(); } break; } case 'line': { if ($invisible) { break; } $x1 = (isset($attribs['x1'])?$this->getHTMLUnitToUnits($attribs['x1'], 0, $this->svgunit, false):0); $y1 = (isset($attribs['y1'])?$this->getHTMLUnitToUnits($attribs['y1'], 0, $this->svgunit, false):0); $x2 = (isset($attribs['x2'])?$this->getHTMLUnitToUnits($attribs['x2'], 0, $this->svgunit, false):0); $y2 = (isset($attribs['y2'])?$this->getHTMLUnitToUnits($attribs['y2'], 0, $this->svgunit, false):0); $x = $x1; $y = $y1; $w = abs($x2 - $x1); $h = abs($y2 - $y1); if (!$clipping) { $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Line', array($x1, $y1, $x2, $y2)); $this->Line($x1, $y1, $x2, $y2); $this->StopTransform(); } break; } case 'polyline': case 'polygon': { if ($invisible) { break; } $points = (isset($attribs['points'])?$attribs['points']:'0 0'); $points = trim($points); // note that point may use a complex syntax not covered here $points = preg_split('/[\,\s]+/si', $points); if (count($points) < 4) { break; } $p = array(); $xmin = 2147483647; $xmax = 0; $ymin = 2147483647; $ymax = 0; foreach ($points as $key => $val) { $p[$key] = $this->getHTMLUnitToUnits($val, 0, $this->svgunit, false); if (($key % 2) == 0) { // X coordinate $xmin = min($xmin, $p[$key]); $xmax = max($xmax, $p[$key]); } else { // Y coordinate $ymin = min($ymin, $p[$key]); $ymax = max($ymax, $p[$key]); } } $x = $xmin; $y = $ymin; $w = ($xmax - $xmin); $h = ($ymax - $ymin); if ($name == 'polyline') { $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'PolyLine', array($p, 'CNZ')); $this->PolyLine($p, 'D', array(), array()); $this->StopTransform(); } else { // polygon if ($clipping) { $this->SVGTransform($tm); $this->Polygon($p, 'CNZ', array(), array(), true); } else { $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Polygon', array($p, 'CNZ')); if (!empty($obstyle)) { $this->Polygon($p, $obstyle, array(), array(), true); } $this->StopTransform(); } } break; } // image case 'image': { if ($invisible) { break; } if (!isset($attribs['xlink:href']) OR empty($attribs['xlink:href'])) { break; } $x = (isset($attribs['x'])?$this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false):0); $y = (isset($attribs['y'])?$this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false):0); $w = (isset($attribs['width'])?$this->getHTMLUnitToUnits($attribs['width'], 0, $this->svgunit, false):0); $h = (isset($attribs['height'])?$this->getHTMLUnitToUnits($attribs['height'], 0, $this->svgunit, false):0); $img = $attribs['xlink:href']; if (!$clipping) { $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h); if (preg_match('/^data:image\/[^;]+;base64,/', $img, $m) > 0) { // embedded image encoded as base64 $img = '@'.base64_decode(substr($img, strlen($m[0]))); } else { // fix image path if (!$this->empty_string($this->svgdir) AND (($img{0} == '.') OR (basename($img) == $img))) { // replace relative path with full server path $img = $this->svgdir.'/'.$img; } if (($img[0] == '/') AND !empty($_SERVER['DOCUMENT_ROOT']) AND ($_SERVER['DOCUMENT_ROOT'] != '/')) { $findroot = strpos($img, $_SERVER['DOCUMENT_ROOT']); if (($findroot === false) OR ($findroot > 1)) { if (substr($_SERVER['DOCUMENT_ROOT'], -1) == '/') { $img = substr($_SERVER['DOCUMENT_ROOT'], 0, -1).$img; } else { $img = $_SERVER['DOCUMENT_ROOT'].$img; } } } $img = urldecode($img); $testscrtype = @parse_url($img); if (!isset($testscrtype['query']) OR empty($testscrtype['query'])) { // convert URL to server path $img = str_replace(K_PATH_URL, K_PATH_MAIN, $img); } } $this->Image($img, $x, $y, $w, $h); $this->StopTransform(); } break; } // text case 'text': case 'tspan': { $this->svgtextmode['invisible'] = $invisible; if ($invisible) { break; } array_push($this->svgstyles, $svgstyle); // only basic support - advanced features must be implemented $x = (isset($attribs['x'])?$this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false):$this->x); $y = (isset($attribs['y'])?$this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false):$this->y); $svgstyle['text-color'] = $svgstyle['fill']; $this->svgtext = ''; if (isset($svgstyle['text-anchor'])) { $this->svgtextmode['text-anchor'] = $svgstyle['text-anchor']; } else { $this->svgtextmode['text-anchor'] = 'start'; } if (isset($svgstyle['direction'])) { if ($svgstyle['direction'] == 'rtl') { $this->svgtextmode['rtl'] = true; } else { $this->svgtextmode['rtl'] = false; } } else { $this->svgtextmode['rtl'] = false; } if (isset($svgstyle['stroke']) AND ($svgstyle['stroke'] != 'none') AND isset($svgstyle['stroke-width']) AND ($svgstyle['stroke-width'] > 0)) { $this->svgtextmode['stroke'] = $this->getHTMLUnitToUnits($svgstyle['stroke-width'], 0, $this->svgunit, false); } else { $this->svgtextmode['stroke'] = false; } $this->StartTransform(); $this->SVGTransform($tm); $obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, 1, 1); $this->x = $x; $this->y = $y; break; } // use case 'use': { if (isset($attribs['xlink:href'])) { $use = $this->svgdefs[substr($attribs['xlink:href'], 1)]; if (isset($attribs['xlink:href'])) { unset($attribs['xlink:href']); } if (isset($attribs['id'])) { unset($attribs['id']); } $attribs = array_merge($use['attribs'], $attribs); $this->startSVGElementHandler($parser, $use['name'], $use['attribs']); } break; } default: { break; } } // end of switch } /** * Sets the closing SVG element handler function for the XML parser. * @param $parser (resource) The first parameter, parser, is a reference to the XML parser calling the handler. * @param $name (string) The second parameter, name, contains the name of the element for which this handler is called. If case-folding is in effect for this parser, the element name will be in uppercase letters. * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected */ protected function endSVGElementHandler($parser, $name) { switch($name) { case 'defs': { $this->svgdefsmode = false; break; } // clipPath case 'clipPath': { $this->svgclipmode = false; break; } case 'g': { // ungroup: remove last style from array array_pop($this->svgstyles); $this->StopTransform(); break; } case 'text': case 'tspan': { if ($this->svgtextmode['invisible']) { // This implementation must be fixed to following the rule: // If the 'visibility' property is set to hidden on a 'tspan', 'tref' or 'altGlyph' element, then the text is invisible but still takes up space in text layout calculations. break; } // print text $text = $this->svgtext; //$text = $this->stringTrim($text); $textlen = $this->GetStringWidth($text); if ($this->svgtextmode['text-anchor'] != 'start') { // check if string is RTL text if ($this->svgtextmode['text-anchor'] == 'end') { if ($this->svgtextmode['rtl']) { $this->x += $textlen; } else { $this->x -= $textlen; } } elseif ($this->svgtextmode['text-anchor'] == 'middle') { if ($this->svgtextmode['rtl']) { $this->x += ($textlen / 2); } else { $this->x -= ($textlen / 2); } } } $textrendermode = $this->textrendermode; $textstrokewidth = $this->textstrokewidth; $this->setTextRenderingMode($this->svgtextmode['stroke'], true, false); $this->Cell($textlen, 0, $text, 0, 0, '', false, '', 0, false, 'L', 'T'); // restore previous rendering mode $this->textrendermode = $textrendermode; $this->textstrokewidth = $textstrokewidth; $this->svgtext = ''; $this->StopTransform(); array_pop($this->svgstyles); break; } default: { break; } } } /** * Sets the character data handler function for the XML parser. * @param $parser (resource) The first parameter, parser, is a reference to the XML parser calling the handler. * @param $data (string) The second parameter, data, contains the character data as a string. * @author Nicola Asuni * @since 5.0.000 (2010-05-02) * @protected */ protected function segSVGContentHandler($parser, $data) { $this->svgtext .= $data; } // --- END SVG METHODS ----------------------------------------------------- } // END OF TCPDF CLASS //============================================================+ // END OF FILE //============================================================+ PKa\m"  fonts/helveticabi.phpnuW+A96,'FontBBox'=>'[-174 -228 1114 962]','ItalicAngle'=>-12,'Ascent'=>962,'Descent'=>-228,'Leading'=>0,'CapHeight'=>718,'XHeight'=>532,'StemV'=>140,'StemH'=>118,'AvgWidth'=>535,'MaxWidth'=>1000,'MissingWidth'=>535); $cw=array(0=>278,1=>278,2=>278,3=>278,4=>278,5=>278,6=>278,7=>278,8=>278,9=>278,10=>278,11=>278,12=>278,13=>278,14=>278,15=>278,16=>278,17=>278,18=>278,19=>278,20=>278,21=>278,22=>278,23=>278,24=>278,25=>278,26=>278,27=>278,28=>278,29=>278,30=>278,31=>278,32=>278,33=>333,34=>474,35=>556,36=>556,37=>889,38=>722,39=>238,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>333,59=>333,60=>584,61=>584,62=>584,63=>611,64=>975,65=>722,66=>722,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>556,75=>722,76=>611,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>333,92=>278,93=>333,94=>584,95=>556,96=>333,97=>556,98=>611,99=>556,100=>611,101=>556,102=>333,103=>611,104=>611,105=>278,106=>278,107=>556,108=>278,109=>889,110=>611,111=>611,112=>611,113=>611,114=>389,115=>556,116=>333,117=>611,118=>556,119=>778,120=>556,121=>556,122=>500,123=>389,124=>280,125=>389,126=>584,127=>350,128=>556,129=>350,130=>278,131=>556,132=>500,133=>1000,134=>556,135=>556,136=>333,137=>1000,138=>667,139=>333,140=>1000,141=>350,142=>611,143=>350,144=>350,145=>278,146=>278,147=>500,148=>500,149=>350,150=>556,151=>1000,152=>333,153=>1000,154=>556,155=>333,156=>944,157=>350,158=>500,159=>667,160=>278,161=>333,162=>556,163=>556,164=>556,165=>556,166=>280,167=>556,168=>333,169=>737,170=>370,171=>556,172=>584,173=>333,174=>737,175=>333,176=>400,177=>584,178=>333,179=>333,180=>333,181=>611,182=>556,183=>278,184=>333,185=>333,186=>365,187=>556,188=>834,189=>834,190=>834,191=>611,192=>722,193=>722,194=>722,195=>722,196=>722,197=>722,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>667,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>889,231=>556,232=>556,233=>556,234=>556,235=>556,236=>278,237=>278,238=>278,239=>278,240=>611,241=>611,242=>611,243=>611,244=>611,245=>611,246=>611,247=>584,248=>611,249=>611,250=>611,251=>611,252=>611,253=>556,254=>611,255=>556); // --- EOF --- PKa\w͞͞fonts/pdfatimesbi.znuW+AxuX[.ADF:`hinnTw<sz/k^{uϺ~JY$ecOꅔ* d/nci,QP96l,ThԪ`KGVA3% uPRPqsqP@?Ȃ Z65sOKt0+;ӯ_~/+]BpXШ)A 4,c CW_IrGAg`@zbob rCÕ6Y;أAW59PLh_T]mAl "vaeaee`Anlcmz?\ h3D\ƅs fv6^ 66v6 >+ O6m:ӤiSd6Qw)GK˿@+ W"(Ŀ'SQ_@Aӿ]P|Y.b=P跓fcعs}`KgH:>8X\@c9&6Acڃ c+ JM%hb zq`fؠP1Bl0u[K\צByy>!+=0A× J&vh B/F'('@a%_N^?`iBh fec}`c_{`lA _4՛u@m"7m,@ֿ=  Bb16R7TA +k +W6(n,mLF@Kh񿜼x`^ж~AJ"+oyd`RW A_ˈ?qo hXz`c1׺bV:gF ch^l\s+V{BIO^8 (ՀZzG$n 5%>Oߌ/p7ؗh[XvMgE=pj rM?d^7smL(g/u_ng.?d9s6#X.y &1Wm+׿z/[{PuDpΤT@&CXFԢ֛-چӮ [o,Dw#vrOiaBXg]R;~|ߣ*DgnUxrEDU&\_z~^0d&@,"I{㪧85MM ޣ1!OLFD`JKHٍ]h*&ϦϳV^'!+XЄĬ0\c1Vߡ 7y?%%([e &s X 8Q8ksCh]gnS:C͸y]Q\>T̕A$wÍ2}ՌGɍ)ƛTcIlcl.&FtS{Wwgfc?NJ48ܐGǫ/fC{Y٭bWGPӴ?^; f!9Um닻Ԯ6qWW!z lOPbv&֏@ mB*d=MS٬WMrKvWƏd%~~F/DR\gW (n#Hvȗu ^f]lCȑ![` '@Ij; <(407=X|UeW9 S^^KY"Ql6{okNRݲ* gJ5G3y>xoG|nWEbJh>7aɉﺮiq }9{$+(@`Y}Է{{"q9+/{[aCXg<TW4`EtgfCvjXB oUmo+. dNeʇ~|5lYIfFi׉1 )Va`S 1UW"B|s;hXgslӍD@#\f3s>xBK/F@ .o>5 a*h꛺z:W ayGvdZ':su-CU ظO!XMNJDČv,>I\/ 7MǙJovtZZ1g=1М٣8C'GO8'X`ɰ=q]^='~S$ZtKfy6賗ባM2Y?KW@l>o/ <cD0"kB(k@hD5h[R$}Ћm/(Ԅ;O0a E^Unǻ#]r">%sG~RBi2ل^F} ѦFsS3\Mq*>̉[1{MserSڔ'ESE ʗq.#/LR1kSWύij?X|D aQ `ClS^N6׫_D#\L- ,Ҍ@2L<|Vj׊rRn:z/ji623ib(3%=Vgxvt 9, dN|61]˞iP +qtZfAVDE3#+WT]fRcKW m$)6qKu\l .Ojv?oK|€PvdeN\v]EdÉo|sq;o>{X^%{ $(`I?( IaijB >hUϫ å11|@K-rMe&0 7VK0F7OkM {vI*$ tZl&z~]Ab2фB0^GeS[i*dgMF{EnJS؇?)@Z$ sZ:'7ILmy& MnV^zm|A8aBbj*:C;~"Z2pk{wB2v ʶ0:li4FU* )& L"$ޘ<ZEa<.vIdl3lu.K}=d`S0 Iړ?U:<=Z˓\{$Bl]_];:@{}_x[~20#Y &m9$]Ի? }+\^kK'_= l I}lNc])lg̦C^|IԺI~TCmi,~E*`l'*çgXdrcnlnb *h;D&qtR_gtl&Û,emb%#礗0inQj]uFU{WeH%@4꿸YhA5܆ ̱)m/g^Xqyr]hH]!*UaX cVOtDw_n\9/,ۆ| Dm[gDu;R% ʣ)҅ސ(/ gD^Վ1 rr8Ek[lVTlLrDނu|Օ0WeP gM >0i|,_t{'$"hÒ+eju///x-?|ޘ5>Qc/Nt } (Ǧ(x?2&_g3~{;Qb펥4v. {w|!e&拜g[۫7܆v(9[ǖT@&6J[gWFe K2Pq}Bd@*BMcpw&yؼs<@zIG?ѵ,1+AԼp 'ܫǞ j/cSr:WRD u,}'ZxK1FRjCU)*vXL=@z谓PsƦt9TtM(1%Kɣ oMT#f=4dQx Q/ɍϟcaWb Uԭ; n5\ObR*ٽ?ZRByR\C ہ~;w~Dk6-j<1~˂甚fR88o೾PHԴ-*ޘ# Dž;5~k4}X>)ISꙌǃzhB?0bq:Qih6>9H5}mХ`"P=׭!"LB ,4*W56f9>Kc D'+2rt#],d!2A>X59 )'ح˃C*ޙE ,Q az+mW=P\\6!G*K9a@Gj/GttY R^ O W;$Ch U"_ Gcu=yǣC 6YVS",ƿ7dժGB UR&Rey&XB_;.jvp9*!fΕI o{ FiƯ +j0)/81 ->WƢm?"62(&FAkH L8htų=#y.i: ?׼> }O6jNXv4oX]1~(._N-7ѯfJ*6\#]F4TP qP1A[컑<|Rt%hot=e'=9(Ck8+<|ׁh+2% ?7 o1=$1>W?=ţKw fd+Krj}v.3)_B{9\W#5c=iXa PT-="\ȽԪlH ԯ sJ, )]ɛI% )#cKgL^Ӽp*TיSr&zXƝG'VVa*R~lj>m9GbGX!!Nq'sEޭIJ1YJ"OVԚjb}-s*{r*"KJ0(:T1+#0Եb ok%Ob_髹Hǻ3:xG)Q54Z+Ov*%ٶKܳ@^:܄,sdv /I':5mR T1gV<ˋ X-&E҄T}K"#IvwUXx s Sa̰YU|R)r΄QZ.jOPq)BM]BrM|2F=^ڛV=DAB6'y)qp͹|+GJ5iv7v<eXOiRZHh.0~j]c?|67۞J^sZ%N; ToeGu~{et]~jC B^L_& ώuax횫dv:l(fX{ru3%p⢒|`%)ut 5tkD3ۯc$I|&ϰ.J&y Q}op>)f\'=U~GarryYQjpIO| W:7" }cQ4}qxڳA]ّ7DTt!Wv$}æW (QCڙ$fZ*׵kcZ&qRjm.sDT!t&P3~ylฯʩ8AƼ ܏ݗ]_26ʤeX7^"8{u$aܩ+1  Vli|4x=zSY[QYO ۷-01-3CWFOS"\7qCw ,"2}iDPZuaPe׷Ըѡkt=+XͷG9g~oFl+"J aUQBT\5GSM.t%eGIS:'C:Z?Z|\ϐJhciYh_2₨XHcwζ,bE3nsb- WBtGWO;vnCAVFA¨SѥcbwӾG D},':)"K#h/߅ċei?ovj17$T$\I6"5l[؈ݭ=r)`Yʟп=? =@*C+)7c9 DGA킅-?%ʛq罊b!ߟK `k4d20%8viw,z2,mRkgFL֎fP9zL: ޣ^ge*ׯJǫ7Csus=fe>Cڹ4)J,~÷};_`aVf`v%V~ӠY)= 7ef Oi5!8mgm%uh ˾ڂ-Zt7| 3qcs4#j 匍JԤNo :63SB_Hiߏb+_lod%{4HyzJ}w |/[ M6cFgd\<*쨹xD(MR류N5Qۚl.^nfHeol^ /8^2Ж<6cKFD{M&ّ==x2̢@r~]/CxXSNVjjDlf93;XKʗ? %йIFdUM{dJndfhoﮆxJuD|_? &زVʇ̃y+ˇm`<+5?=[;%G'h|Cd{D)0<|L]=}X` 2D~sED5f αj#RO@PCS`f;u vIv8ne*+}OD.ZPp.sȷіY(t8xw>xz$wozkgEmH[kT0m֧lHGTߨF'KkD;_/k aț]GǽG6.tHq'C*zmnҚ]2= oXO)8.]dˠbKfetC|$}~vJaF.($1Obk6$<Y;.t/uZ*P.P;thլW"e@W^`w Gq-xNK+tgZMn'ƨ?"`-FeGpo)梻$xxJz'yf=KxTK1ƅB{3sS 184#yG!wOYj'o?o_&O4pH9R"NwQڔeZa˖JP"gp22.R* 6ϰec}k X>.LNa?4meքHxW?{|X#'IvzrRu,C2>NѪ894֦UEa ;[ˡ\UP+Բu6ۂ;A !T'Ú,զyg|ϨC2tŽ rfvcਹ>=o|RyP9ԟKiů ,@jHRAk߽D1$s)İebCzvQTt^ٝb'>Q2nx9ER|q. `Yu/CFSNgn/.W5?Tj]Ƒ-&/M_0 ?/EsOUj9I{YI/ $8Uqq3B-.., ʆȄXǞCn$EwVѕmsGOɟ0:7IfZ 7<ODžSz߼dY 5dʯ1'4k1ljP<1ZVzIIm~tyj1Nو1*'}mԳc82/2>2ѵ6qgtvoH_}s13wPO&Hlp\GU־@[SD};RʥB k,K)T| }g5%X7Ue+2 &gy/ <=HY4\;NX`^ ˑi "d.[e1scHPGD>,]\ۨmhU$}.>zgu~s-ʆxB{SQZ<5BPtZWw3`+sς!k!VuTjĮ)ez4[}O;r$z.;<,M`W̳5Ʌ񉱸5n̂_7r(PopCؿMVw%xӭ}NINb&=726,y&9V+ aĖx9fG8;φb.pN ~r#aU1E?6`j{UNMLY"WQVHe{PvΔ3xސnG;=h[l1]u;!lfr*+ڵ<end_8mG=^O։k ЋxOx"E+æ'SG-xY_1v@A]j G_w!O ,m/,aP20|ɜL#Lbf$/N~ɼGh\: 2&rJ> uΧNTwp4#¶~TY:Un.IPG= Kqo6e0ʕK8˧&[6&uuK 뛾H9֛Lho9I =gNE3pA}yXfK a2"?}29[I^8[܆mll~l]M=v{C'ȹ&OM}bhf fSN'N&b=D' AG5rE7kb h&WUC,_ Kqfm3;~V(RYh.uL=~NA`& y5&ɺkd epr;c憚G$4?W)I&a)?G:b>PѺο/ *Ytt tH=٦\0`rzhHMI)z[ \ a}nǣA2C#ݠ,o$qwB)v*z6Ƣ6l3$u;-If=.*jꙹ Iȍ]!㌁OB-#.40"!, GF[B뛓k/_ Q{ b>덊bEl;]֜໏xfc< ȷdn?¯)s|1$UtʀqOp4UgOMG/-lbwM$ny,ՋYR;B6W o54-P2oH9 _cL} iYrNPY.V F0ovu7*wS gP<'Ra {b(g71xmn{\5j9a\G|?K1\65FakXp?ݍX<La:bm[;Tң2ڝK @\ׄl6>KRM<jE5^˷b? ql. ivyjť?pO= ElB6 ps%#ꕌ/(?c@s/,}0ә!GEĂ?B5T5㈶{ TZz",]_bvPybS8b(UXfw!W13vUM' .'Joa,蔕jۦ@4*T=xMRy׻bGIJQkCQd:q}cNPGZ38)9ls&[;.Mk(jlG2X  uJHDHr]n^Z[3PybB,6%ׅ6_GE $}_5$UU)%V"Mk 0VXKQ>@*Lhntzh5fCNj*Čct͢a^VCRu~:P5%% NhS ,kɄd&{}4[ qSd^>vl_ߛu;?C9@Et^ i!0Gff%;y@TWܯ%穿+[J1c fo,sZx/Ѱ*WMɀji:J(̍ U07cVKĪܤzجZ;]N 2v)$:^pIE]6iߞ]*:mcobo7lQaf!GCQ·iI)8٩"!fG`PHt^91IiMo?;<{р')`Hhャ O"Y ,e`4 S4A&jq7 :椽sefѐ > KrYU϶VYe|G?YEWNX&-¬@aEtw{"Rޣ%au5N fuկb ټ|_a^9TNIMiN7~A{ıu?Mᥚx%Ɲ85Tj!Rۊ| D >-g JKJ'7RJTއmK]i_RD|1A /8]`ʾ[IUs.}.'R@p(?Ƴb N4@u=# zeQR]S|<貖N\IjrA0ZjE)9 Qr% !i"4ex}K1P{J񿓐pйV\m>gL{-ּ@vjg'5r;܌VC DUV]kL{eIӽKpvO Lj#r 3@eXGd˪+QDCh Ӧj% v<@0ji.R~/4|MS%Kᚤgv; {y/")rl6xҏYM'#).Jx˵^z{40+*/v8+4&!nFb;fkb)5V4O Z 6]~K[= ߀2$PGO$a<NsoFObfȾxdHΤ) d|Oס?>]==>MÎ0)UT|G@w}L'A:z1&Tb!.Cz% ÒL($ 8lܘ@#޽gG3$82T@↕z5K[T=f * t`2Xm Py\*|$rIF1 K&(GvLUE7uURBtdD6?u,惂iL^d *ȫb`p9$/c(S)-9XgށyI?OVCpfC`7˽C =xH$n 0 (Q蛄Yu+ i>7B 7uw)gAx jD62&nt'A KcsL1Ɇ= E3-tMCTVVE@9(O ˎ&lU#BV۹ֆrdUkRA1ရ,/Am6 @a"N5Ϳ X=f/Y[d5!1v]gby5ętQGLj y? oj1GLx k.^E'etf N6LmUG):S+{r*L!;yI\Fk5R.~^pn7v;Мcj4 <@}և :~d5'<ΣpB,b nv0j$>H"Ƙ3w.V^fW)5i9l#b7 :\h/G7 zpd(.&qz]? _"ecގ. ^Lݎ _V52L)Kш0Tw*z ڈ^-@sп󊳴KycnKtMV'sfCWFM~jr~e5LK5)kŤs ~i s*l)ۣ&XQ!_S EF0ZZufᔾiae |XV8ePNzr$Ez(%3glO$kJZpAwYwԔwTjS* C;4^"QW:ۥ@?߱6>jd"'+8,l&L)QhqڅUE [K7êK;OL&*e 6N35vrˮAa;@¦49V`- . 3.RpLƅ$?/ 8_}OP*:BivkL~*K@글> ݣ+,&*g'wNUއaSk%k^I O;8t{G$vP,AMFi  r$@:_ojA Ioj\&`Ѷ/FT(<,}~ݦ D>?'#}l,r45 F"Z핡% `\]txTU Y/%b݆gm>-rO%Vp7)e!-CeHTb@TDQ҆/aSN t ˷5rxA$HF?HF ``F n*Q^kY!5^;&#.*"d^8;L`y=-Pʨ3tvGAN*YnsL/qL:TlQ~VT-/Y/9c"ve+-g 7cn$a nA\']PTL[׭$.g#^owvy?jGКMn$|Jt ?Z`s tx-#:Iu66lhhDg^?a$!6:KK!MƥJz6!zc{X mI38WIWORF9NNe@j+4Q7e}f&̓SJjQU9^7U 7LB-2U`Ѥ)0UbbV7f`{4,JF\@;nJo( pu ˎ+ j~5 qͰr31.y&&  ~|kYEDxycUE+ 4zmxxuCv?PH%1={z3׋XL%dZeU m3 (h2@n2lѬm P#_ 葡AhZ&W!W7"nLcIoAFݨitJq* lYd4m:۪D,;w4 S?z҉ĮY#ޏ3=䏒1{XjAig% *lf2Xo-i] յWU,ŀ J=U*+FomYF2*7 bOk#H!~P B3txj5!Q-Qy?eJ}fuM{N̥PU0V\i"dXSDfMaY+^ywn;Dee4tS#)G] ̚% +p NseJd.ش0mZp% +s_vqRیLot 9+. ֝_x)y휇NU3N-7Dh]Eh9ZQ [bLU×33k:e/QPlN8S<1*W9A"i?\Q@ $T 4=;h}6]}f+lxx==` FKAF7m%JjS陼zfrIeIGcHezh`\d{$7 }%ڳ؝ irhi5}jW:ƿ}u-:''2X%&̪2ʹ;4k-Yse';kf[M-9Ճͯj}kɇK"AIZlWj*} SX1qK˂:OEB;ň6Zx8u纫>Azi@B% ^*'C{rƎ~xnXÙchTAc͚.eў*q@tՠ}6}"/1ectW0НA?C(5HD\k&LMZeB*l FZWttONfM&H; qF3 9 'Lئ%~lz 22R "G!ϑg{NJBoAּmrALn} 6*ɴLETD$-"PR:,G0*NC r%Z(Db u0z+Vpn:q&dɨJvw%}ed3'Y:z/ tmT{Q’kpox ;:x4%gdvG' ==BoΤy˟X A¼w0XܘaG4BecAr)]fWrϲ/t+xQɠޘVLi,pYI|xTiFo'2 S:ߊ_~i l ~}kwtM:g^|΅am;ܛP{̗iZ+É ʃ` UWW><@~@J-0OW7}0#Ch*JO#6O0R,KG#$F=,1r2qY{ӱ@1쨶{{w.MQ) mlyC9,DBa~~rYrrq'Y<ɁR*v!%o̤ocڠCvrUp̆r!tR:&:!gH#UPc njrgJ5WѧDOAT>ru {&6@k aҤے[b'\,/_ҝ:\N+` k :=#xYck=?SB܉D#YpmigO> ³G:O5gm˞^/^>MF b3YcfՋQŴ' #K_}R< ;"x|6'*UKzMAUv\q(:N'D)%Ʌ <^=?6_ }Eldq:MÄd)3r5ZU3,qf2qwAe8t?'`vjbloϿh'~e6G1R0x]]# zAc (H`~C2or摭6t ^'G[Z)(9 ^r :^)7J=]hg<Ԛy}ֳc-V2B |R:F,jiaaG;UԑZrOtt%mZt ;%i욖NNykm du.Mƞ)nN܀t Z=ҞŒslϮg`y^/ջxǓ):?=hvcW/p)9 sZ͢ 0`Y> Ky|\sfHXO.WGu¢ᆏn'X/$Zh=*Uw;0H \F{aGm MLW%`k#= M?RT*~DAXϠ9*Ъ6YOO-˂xJ廢8pTBT̵p8Ս.q.ϲסdJ*:@^`Sƀrhkչ~]d f{Fgah.:7 ٔs֍ZvMg`5*:mƐBJ w]Ǥ&Xy1;DG:ULS|,i9Eȅ0 >GC8Ș#?X_mzLQ*dјEKOyP-)pg)Țj NwaX>N:Yxq+- ,\\%`vƶNLuI,d4 PsY&5&GnӑCw[q^,' 79ImhJ2CT y^/>XDݾB x/ w}`J)rP֦.~0Ypz}[p/dezP ;=Is;5yބM]&Zfc: LYؽ,5npb)yj4 tŗ׻LJo75eZ5%`t=v۰_ Ve,2))Ct7deWhmm 1GG:dAphS Nk[rBf-p?đCQλt6bi;Xg-{`.cUC>SY0fʔࣞXdȥjǵ1B| y疁*JCؚ*oj>K5<-WFW~2W *|*I;jawmc-gP/Xɠ\ >Z:qu]a MmPC<&n4#%N~%dAo< UNd4lIŁХ|iś~!ݧeW>-IC58O,z`v@d%x=#?ZvTu.rȈcHqeԪ9ѤNP % ӞRZ3W'}ĸѸ<$Aʵ5,Qg0qO y5D\=Û('=_YՈʆ6 \fj4 P.ȍ?*<lbs;?Luզ6hZc/\%iex<m{$LMK7\cxW/ܔUR-.`)ɉBSo.|& ]^3Dj%iD}[©;]xuzP X_'8$KsU#oV@rxK'.WGP^vtxVf܏O=Vٴȑ*%lo!%&#\PhΝ]<]ɫ  K/+u~Mj%K|f N^K1, Vi"rMvNnup0~6)GiMnnd5M[/UY!t*'ҋ ^rpɆ>6pRrL@dJ[5\-)tN Kثxh{~71^'5F:.Mwj1E}U|:e;j??n7s-GSr#%F$m)̱ts1u(H> 0dlP`W񥩀4*Vv~&K$oa|2! \{U> @Ʀrf) 4?PHk f1iFɋQMSd?!pV{OJBp )pY`dv^CB9@~A#3fN#bוJIZ/g&[jv%VןWg#χA;NK1OK 0sJw=="TL l%$?A>;B[G!AIOEqjHG9P8A%u@0/ZhDxh7i=A|;zLy!wdUifdKմuIYZyzl's١`:64^ÞyVa щ7Q1|7> w渑y,)/ҴC/YX-mYBꖺ9V v̲W4a9K$[wVXib3e }pɪ(=$˩$f" v<8<"0uۧ}؆7gހjY]01: "_!P\l?L~AޒniǛ|k"cS+}5~,@LvYu^zгF6pP -[ ~D'ؑ mC}h_Fh[Xfd&E2h7I,F#m`UD\ ?JW bXii+ 0dQP#+ sԽjA֓~cƘ }#8ՠV$zI^SƁر6\_0(gCFD}k.Jx[khX۞AÕ ݱãG\+t]uzo'@YV2pXxW#zU$|C`1`',ᖔ=^.NaG][h]Ce@$W{v =e!41Ea{ۦzRaE[H4kq!nEqRZ%VҋcЁs_a?5u'\XXnaӏ$%v,7p97l&뿵B9ԕNTu" u`p#ꂣGbOF"?-l*'w>`ٚWl]̡ HLquTTM;bNgZ8i(G^vis]0h]}mG'_Hi#f>ߕo7(obe!vb}-fK4wa p/9ҧQm$IvZk!3"#Ȟ _85M7~怴#:<,UD1YC Ta9b9ݒAZ3u36ef%fSTe+=o:{h)0ɋNY>u@qKG2] \G Mv +,C44%N+i<6J\B_AKs7лg:a,P()k_!'E{60rNz=~+yKZPh[*F~ZAO;K1ձ2I)"kVҪ8q +fŏRUPL!LEAqgv]/8)M2*{fiW>sO>cwxC=*53R (|dWA~ۘ ]od7eDq^0ϫ}TE1YZVhצ46Sc: (YdmDkcɟ{zz`C&D!1#<gVZ|'߾:B\n)4y=} -?1sO(:%zؖz}ʑՋ\v6Uxi='?|Z>:pC|Hwh{ ,%6GmB:a$tk` ? U柝/y.Cه S7"-_pQYۡl:w؂( #IF7kE3vATp#נuw'k;n|m|E{)y#$ةtKGf9^*ݴ\Ag%׮8=yAB2*Ö: ώPe揪7loUԏOcnNW2 7vz= OJ^"9䲯Qb..?sM }w1lj餷f7#ߣ0ex@б2gvËj & _ϙku,so^_j}C!U(,^/*ٓ@K!PvFV"}sBTb;?ވu1v2KczKdƳ\-IRj\l+b? wI ]~6S2k\.yBD /QxaSU7͡܎Êi\"1U}"mmVg@bkr p+P  2 ɦx|WD[Tl%f !;8F A~^$-bxq_x=̘=BN8/%9-(E 븸5:-ḧ́(pz:7,+D1Pr Sр>/6G^76yi蘞+tQXUlm{ ݾ%ps1>ò1(b ;~eRc9ۮ: WV73Gskh}nd9#k9@ nM\ ]AG?!Up~p36 {H @K¯ftc1jEF̸̈6 JԜkG@)Ʉˑh*aP΁.]Jhֲ A%::4Y1ȥJX7=)tp&8kXXoH2^w1TE:/@ݚZ;oye"m7bIpzo|8Mno6Vc~3 [t|펌JPO|0lKCl'NydOSl1*TئjfZVNN0ŭkBXDw6p,:ϝeb"sǙ7}зnԄE ,= Pa|1WKw44D޲A"3)|v[9Oȩ]kS@7P{%yX.OsO2@Tv Sh52 E>~ߨ}!iI >W͔_u5ؽ: , wsx];3쎯(KAQVE dm9%eKmKb;&0{ EC362>Db T-BS~fyW i/3bfҍgCXA"gǭ&`zH zMc ̏n?e!'(;<7UN(m1k:EImVZY>@ݽD $F>F;t FKhrop_b;~2vE~R+4W8}Ќ$-a#zq6 [/7wJ{HSAZn[}>jF(TSgO, ʯqi7yo+koh @ (r Djm^ՇCEe@imYf; DgE\\uĂDb,%l5{[>Sq]yXk. MiC,6Xȣ&˦v#NOI Qck,8cݳ`3KeI75n?T6r7O)tzZs -k"^ԥsF:S_:M+R'm7r+j G S8KBa3l@j 2[ʼns"B9K*gX^s&gB$s ۠L ^͜^HXl3vkBseA,4d0B)LӖYʧ={4AB R!4?qJz_}vtqNP1Y~V;H֖`>?mbhΘktIknx<F8aL&-3V*v:9cwDb+ f=rY6>@=B( kt6wfcHx{$pcG}(ZCUw\]Y GE"KJ.e6*i7Q>osh| ;϶Z ">Q9M׌Ls!ojCf=8 Lѣ"^&: !'T1H׺CK̴p&sKmY*kv(,kZg^{n㖒'E -Ip&jSҽK*I>vQ֟>BY&lb]P;-]JX,@l 29lfX*#1uT:b,ŵ sk?y"QbMۦ.GSNSx:۔Qosi7:QNY5 soTՖTNf>^o%2--m>_\Α1>pU^ՑbX0l(#CX잂b Q*pB?.Guhd:7{WFQ G-=O%#^"}2ʳtx27baL,;l)+(sڞi~y ֏BAs ȝX74fqida`Mm>r ݙߋ5X:}!Uض=_KI=;!S[UhW}eڄ8oŸܿ$D=y9dޗk*9躂ݐ$?HDcyM euARb4ESc5Y +hqǛG HK@ lc+uyY\gA;FTniT /[O+$򫕉3{g|!o9Ƥڿ (눷ИMtLP#kݗpJ޹[%JGfD3Dl刢 ,ڣ(JfZZ~QJzpdqbƟ9\fBK<\5Y7*6N@ȱ"M%63\% Ȭ-cDY F6"z!m=?cѣ` < iÍŀy|4$J,u 0h#|cvE  N2˷G
      ?k/Nm9!KUZ9fj-dzPu4g09yl~4]ta3WTvvD]\Ti*97O,zDOBT2쬥st3~0mрd FFrKҵ=0Lr|Qi~k뙻 %i?ŒaRc|<1i#ǔ3g2ovdˁQ*Y5q{O/<h3ĖO` =JAc]KZbzqOV?-S/F1}ӯ( hIG4m|8c5Њci yTRq6;  |~O1s{l&%^:Am4huڝR{c+hBY]}$+# ӯтu]*i؄=9HN"19\$tp$V?oR?g ݪS--g *S lW}d\kd~yT`9 8|Tט/VkM|݉gʀQn&Q}*,o$0jX" Q?ͷ6.\ʹ؊)AgSA3N,65TT}S4MƄpMvеWn=H}P_J^5+MţE* RQ͗Z>9s0)i̗`c/nvf--4*;tَa%hq>(D~KѬC󻧇1 ]D:;f~ e=;sp;$K@&k5p%p.d޿ZX@YJClsyo؛@vy\%BScWɂG-OGqʾxo>%0-"eO?V;!<̽Ggɐ0p UPhފ2,:!,rܻ%=f7j=X,4ve28B7IC|'‰?y|ӰlJNB #4T|BsaN3dfH|Ugg/!CMkoXWՉ \sz@%}iklF?yx.*]2U+d+j@׈7f_&G $bSIqז{.Zt=QeVFҨc!?F3#}rVq-%JY/E"or!5p뷴aa#p&v"kT#Bbq[^=X kI ,JY01!,ZwO+ʑQ-m9us;gL&BI(QiZ zO3~&X7F?_h7`kǦu~yxȻҩ#\]ή[lEыgC8c!u+G3HEDw):*OӖaqAث%"yϹ\ѕ4Eh<h7j r#\."UMw0cڴϹNm|sD`oFbΞ fNSId~m=`|p'%}B3t A gNX'rAFtz﵌j Ҝ!r`t Y:mV\όrE$5K`(GN*H@])`]THACp,p^Nfr`v7F?>B_<$2dbY"}ծ"0ҥR [p~9ƂFiEQ8E/W;sy{[ |L4z=$|ˢ˨H&K cU^K5RNդ),j& g6f})d!\1֜}Mu0SH^طҠ*ƿ7m4"^vf] DKp+l:C#X+7_tΠz,xھ7Zr|6bV\Ltw絫<8>XOJ#Fnkn_{/1SdUL=껪vzcx 5&, =`k% 7dugr7;) &xj4.0#+kdxߙw/Qe/-I2ə[{v1F3<5lB5T.NkD_cMLJj=t_;߃0@ߗeetTI4yK~0~4_q-Ϸ(BS 'q)rE<{p?LCJE'nԈ&2HvpAL_e3f^UeOf7 7OClS͔kbUOjf(wUY1ɪ.ps*t쾖WqIQ2>kȦv:M#(r]r%|!D-dD~Z[XżC ~}-lcK^n^wyjjO2/nT{7c> tطp6j@6(©a⋼ {:r_E)z'>au mߠ~ ,'oMtJe9CD=Rtz 5uV l8>\<^E1[mk2{!~}\}Bb{q_ަcw}{PI{%h)-vsU6πzQUMݲw{YvB t͋@tZPI0b@ ·@iK}o27 JZ S3o瓦-)!Poޖc@ nFT@gN>>řUfv E#cd`fV|67`,zi|fҨH`M{Gθ:cǝ`I<4ErįҗCap 6˜K1Ԡ5jgN4&G?'^Fnxi=n[?i@{k 'X,oFrF'&/ª P0YK)Z3 ZD-Y.5]bIKh,mX@Y[ BYicnl[ڊmƚ_a!:Dvt*#@< ]ZMM6n$?鰠[^ !G5V77b ZJޫKe?|b/A߂H;k+Q,+rri)r1[IuC]2»I >`YysҌl4լBF? :QJY$׾rjpdQ!߃3ٔXJO}iT&s6´/$ї;'F93RhH f%1v‡' ,lf Ew-.2R h)W6Z5FT7E|އQGl1X3P+ qta|X-WЬաPv~I aA/=[JdosNhB66fSȨS7VLPcf͌bx,[MѬ6z?)ȂScq-ˈ7sGY\@8oƺ*UtPɆ(v90!*>ƕ,ҝ +Ҙ^@W!xz9LԈĮHn*J&F;< I)lZr8ShJsl_u2&,Mn:B/xzsFÛ t3yQuM5"Full:B7> |~ݕ5R üŭ=մ,Pr {sM&?e(YlƂhiB8 ~40,y9\뽸Tvc*gW_L4=bty|;*s"sx1ۂ$sePKa\  fonts/timesb.phpnuW+A32,'FontBBox'=>'[-168 -218 1000 935]','ItalicAngle'=>0,'Ascent'=>935,'Descent'=>-218,'Leading'=>0,'CapHeight'=>676,'XHeight'=>461,'StemV'=>139,'StemH'=>44,'AvgWidth'=>516,'MaxWidth'=>1000,'MissingWidth'=>516); $cw=array(0=>250,1=>250,2=>250,3=>250,4=>250,5=>250,6=>250,7=>250,8=>250,9=>250,10=>250,11=>250,12=>250,13=>250,14=>250,15=>250,16=>250,17=>250,18=>250,19=>250,20=>250,21=>250,22=>250,23=>250,24=>250,25=>250,26=>250,27=>250,28=>250,29=>250,30=>250,31=>250,32=>250,33=>333,34=>555,35=>500,36=>500,37=>1000,38=>833,39=>278,40=>333,41=>333,42=>500,43=>570,44=>250,45=>333,46=>250,47=>278,48=>500,49=>500,50=>500,51=>500,52=>500,53=>500,54=>500,55=>500,56=>500,57=>500,58=>333,59=>333,60=>570,61=>570,62=>570,63=>500,64=>930,65=>722,66=>667,67=>722,68=>722,69=>667,70=>611,71=>778,72=>778,73=>389,74=>500,75=>778,76=>667,77=>944,78=>722,79=>778,80=>611,81=>778,82=>722,83=>556,84=>667,85=>722,86=>722,87=>1000,88=>722,89=>722,90=>667,91=>333,92=>278,93=>333,94=>581,95=>500,96=>333,97=>500,98=>556,99=>444,100=>556,101=>444,102=>333,103=>500,104=>556,105=>278,106=>333,107=>556,108=>278,109=>833,110=>556,111=>500,112=>556,113=>556,114=>444,115=>389,116=>333,117=>556,118=>500,119=>722,120=>500,121=>500,122=>444,123=>394,124=>220,125=>394,126=>520,127=>350,128=>500,129=>350,130=>333,131=>500,132=>500,133=>1000,134=>500,135=>500,136=>333,137=>1000,138=>556,139=>333,140=>1000,141=>350,142=>667,143=>350,144=>350,145=>333,146=>333,147=>500,148=>500,149=>350,150=>500,151=>1000,152=>333,153=>1000,154=>389,155=>333,156=>722,157=>350,158=>444,159=>722,160=>250,161=>333,162=>500,163=>500,164=>500,165=>500,166=>220,167=>500,168=>333,169=>747,170=>300,171=>500,172=>570,173=>333,174=>747,175=>333,176=>400,177=>570,178=>300,179=>300,180=>333,181=>556,182=>540,183=>250,184=>333,185=>300,186=>330,187=>500,188=>750,189=>750,190=>750,191=>500,192=>722,193=>722,194=>722,195=>722,196=>722,197=>722,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>389,205=>389,206=>389,207=>389,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>570,216=>778,217=>722,218=>722,219=>722,220=>722,221=>722,222=>611,223=>556,224=>500,225=>500,226=>500,227=>500,228=>500,229=>500,230=>722,231=>444,232=>444,233=>444,234=>444,235=>444,236=>278,237=>278,238=>278,239=>278,240=>500,241=>556,242=>500,243=>500,244=>500,245=>500,246=>500,247=>570,248=>500,249=>556,250=>556,251=>556,252=>556,253=>500,254=>556,255=>500); // --- EOF --- PKa\O^))fonts/freesansi.znuW+Axܽg`UU=kTJHHHA@:! XhbwDDzEDoy&kY3\3po~8Iyg)<ѴIvΦaP74oݮDMuL!.#KEm.:戯EFw=hؗSJ)|Q6@$)}\im"E~E#Iːyoؾo,R<[gK܋<;eK(󝊮܏>d1^L|["Riq&jK.p7}EcUf6hpq{"Փ 9j6x:4lDuc$N՛qwRk<[JqpKS}Զ^Sn?)]/>{.aGoosqÀRj.:U"2li4wv4]s< )6sVltd"Q=E(m " (_KƩ޲J$[+yNv'*OG#G"Txy+f+O+G.Nkr񤘹 gOt/?/hIq8,*>\<)f.̜Y-[skjz111֪gj?f[ 5>׮Ҿ(1'f*{7f͖lز{5jsyf۵ 2u)֗9ce-3.ͱ616ǮB}EoՋckwƜYc{[N;RIlKV⥳^,Zs4O{,Op?;s݆s-rL/7:iǍIARuKpOB^擹<7JPw&Ik|Z|P".BPZYukAت}s~qC͹9H:;mDl1|i9{s"%̜g̱-{Y1՗zf;ǃwu>l|c(5DB>QVq ,wl"ۏgDZدImF2IGy eK=-Nb,j$.9"6M~5杗W,m}99IK"sB+sr.K k_k=4$-8e~Ā58p'ՐA3/wdj5c\Ru3[E,l?TĮmeg^ ~Z",#hswy}!{`X >3Nw90#IcMVId,D]`,^O<\ f'6|,rSF#ʇGMܓ{_: وUy\uyYsuy)EBv#mOM5h!gO_Mqȇ=d?tE:]IDؗgSH.qf!yH=5LM7jJeq~qAy Y yC}אl$i'bC˾`9ޏEK8׵z|8zGCMdOՒ`OBe6Li3At0E5LFFpG==b|aSG[}]Q[DN^Ak!2G+q:\L74`=oQ^D(oiǚg1;7DaA|^GIfj<ҝ̗:͡5z--{oJ%5ֹ}t>t3Ǹ~G+M} gY}dn Tӟ|dtʥ=sM f.9iֻ>sv-:q=?GuR Y7 )_2s.Y{% GM})Φ/K|+Blb䡷A?y޵ l:>[9^<-%khWJbNc Hic'R[ `>|\}t Oj(f\~'~琋d)Gګ[Gh7PC҂|MyIK[%a^O᥹yEhC)5F8[*RN{oX;4uj-#/țԠ>Ӭ1yì?3fy-r53[Uխsqk֭ڵ׬a^?^|9Z60k[jڪIJ;fM_}" ~c3Fk+ vvvtgo mqW-lU>46ǸcJN8)SDZM'M7ٯcO͋ x;଩ ý)/$My8g`EϞ1>=@ĘaaWH@hU_0cg&I'VV?Ы&7 WRZ/O(UO|~4,^{0kEOgra=Va7xǚJle! W0[{Q۵7[qbHt9ɞ<ZO)a2}[# e=,MVϰ?!\IgI] ۈqMt7OدOn5@̵dF-*W)8TԀqG H}+1FZTӒ=> xW$DHjSU-L5^2jXJg3Z{RSڴJmΚOe>KvO'g慟w)m*%@|/X.l3~pF2Ķ\%?ruҋC`g O Ǝĸ>'w1o VyeVwʘ `9?&Vz@}kF?ѯ^Lm2 b {AJ;Ƒ Y~[_u3c4zc>W%'eZV0#e}F )zq?^{Y} kx)TkǞkq8|s6qsռF5MU,$g=2_obnN.w҅hcEO7-MTxY,1yלu]>xxt5釤|XmO^%j;u;^| 6⩿x>yAe%ZS&)~-澒$7P8^&A7ލa=.y7C-\/%Ǻq2ύ@ Wmd\7!\"͝qI-L/{g^9<'s?s ߊf,׫ZR[*m`|IpOu×52Ĺ3n 1mhS-fihϙ:5[Y֒2P='TW9AOra^ c7Fgy&vӃU99S7ϼEg7eSyN_"ͳROQX΁׏uxu%G.TY"gJ9= N1ϭZejfEe?SI2S7hZVF~bnYU#iZ01qA^"Lюd|=kO|i"ii}07}uY֜q{-B=$]{'Υjogy?MU,1p<:N-}kˏlXR$An~M0u4-!>ߐZjT/솴?vK:Mq"߷<}ҜY9ZRI0y0V ?o2&~1痚1?ߪCEzZCK@jѵQ偼C&.U|?sK.djweK+gTM2Ar䮱h;;uƸ7ZqNYcVθ4M*iA̷A}k7n_;xGո>̛d^m36se|Y-m6$h͢CA?HCqRlٜG߻"oR_3D Oqr_ pvc膄jM%B!! zel6~=8xH}m8T0ӥc|~4NkC8OKecBnWe^{Wi=R53,%XoAj+?n~s=\\Oܫ8wa7.#&'CVj`U=.m4N]&/j:%syGblgE"!-%͌UǪ#TyOʴG\Q*_u]{0=gڋ1soDbox|e$ѝbS%:9y71gaq6%ׁzcsL`9#C9a6{$I"1֓ʀW RUsf /o3^6R & }e1[﹔K_IK:s&:RY tv!!Hq"mg~g3azq@\:Rc9'b%U-g0c;7v~D٣=eNYNګ2Q\=Z%Cg4}~T?;9t9ȹsS79uܧ/q/u_}Ag/N<8/AP젼NAu6hoЉ Am}lmfV6ھ v N Nn*xB[!ZKH*!CBCCz~fC&h頋A?j0(t"[)q] 5ӂ n<݊8aYVSC3a3N;cal16 l-c1n3:mFC#1lFh`~~a]v~aLJ}Ö00a^7w/_;sĵϯ}vе]{mϵv]qmm׶\|m _[~m%_wmεM6ڰkC 6ڠkZ۫W~w3WO\ӯvwus/E={Vtttttwt5safo/Wei+멋83]Mܥsb,QI<9Vf+~RUIug@ bKLKM%R[wz%R_-%V$^$Q$K#ITN4!%SdK4f\ZpNm)yJZ ji+tI tMKRI2Y^We̖d/G|,Ke, 禕R*d^6v[dlw=-#K׳2F0nwdHn?K?yf~N7s],!n8 ,]^,(Ua'\~!.[3ۮwzFƺs=zU^i"缩L%oW=]'h}q2\e_6^{,Ewni;JhzRg;N*飯JU|iJܶ١J3 K3:+u4?Sp4ӟFf|FۂՌޙMєzV+WR ?Qr)RUJyURO ͧ-;Z)m٥z&Duf, qܻ-qk]Ǎ37.ގ'J˕\SIvYBckъ 7鉌AbE_oΖf 7@:{"N}#E㐽LN }k;n(d`ÝUrL|d6µk?^B"ઈUDM"zDx{+"^6^u\@xWM>n}W@ڗ|?@я~􃟪` 'TC:WG:ٛ#p.@F^ W Dqg0B!BJ|U(\bP00'pN5S$³ZA-B|gm؏nm8`M|Omվ)R\u|[PօU>􏄓H"'"Z"]Q]xŻ(EQ;Q `[4آVlV5 րSbjpŀ+\1W qĒXr X<Ƒ8@kY8rxk/B~㱟',g [@'\lG.XZy#yjEͶ[kboM|j oCۀ-m툯=g.@`HN;W'0Pp\i3 cWuE+nt}ww!5S=z&{ԁ`nOzuO0I<=ד:/B"sWDE+^^ ^ЛM ٛ }11bb)&'Zc.ULbK~b/6b/x/1#~؏c?0S?b,{ KKKKYB=??gccO? C0 0f`jy022o0 &73PJ? Éq81 |ܨ#܏BgOS=EL0̣4?xcc /c˱5L=K^gdw>b0-b/b/b/bp@|w ݇p!8>LJ>C8>19zZB%t R+K]R\J/Ri)@R-RbXFlp˨e-Coy^[{˩Ĺ r l~'<[ĶWJ.>֧p)5[RҿXW*[MnVj8\ ޵]uj=rF7&D6l ~-}{e+6l;l;6c;qo'Apvy\"vo7{hx^˽ ν}o#aݏ~`:@  $'w߇Q!a&`: ׇ};oSKs(yx/qcqC8$/K0>pu<:ɻ?S)>ק4r~4uszZٟ `,%蝥aq#s{_<}j>S }߇}jWEW6ӯWbX_+o <:;>?t'''Gpm'f(ߴY&AJE1^QZ$2NnCF!rj|%%\劮IQn'![E-w #<ӧ<>BW2)b }u%ys"P}f#ƦO 9& x~KՖ1TYȟ.M |؈`: ?xb N<N := D'p^ +^1<6gÞg` }K}C* ]1'F8|S5"ԂZجZQj6[حGߨy_cE ?v8x< ĔwI`I!: ~8ӫlJ%48KOjq>WDe B1z%?g,pdQoMӄ5Y[eC5F5NsY b%\0ߊ:ᜬOLmiKvp׎u_bH`L:U'{ ˙Xu.B yV/=͹V$/G/"71bb/Fo>7gDU>?3vA``  08;hj8~FoF(lr6SOGKD=M1K}>CϠ,Ϟ%F]jf<9X@&<5El^g)YJMOjљL ;>SjکT oi5~ 377 tN ̀7&vL̤f,rQocMM9\8˼3yĒ8Cv>.< x=j!}."N}|b|@^>χ#j#8v w)>2YF匛Yp{˩XN|_W+iV bZA+OO+y%Vbo%Vbo%Vާ{է{2F>%OSRRUzXE>W*bYEmUUpWjd5<&wV^VS_kk5} |aܭaYX]Cku-6bs-zk[^[u[u[:aoaoao=֓zYO<z֣ m@oz@{uFT{#7q#qoF|oDo#zۄ&6 MmMބMBm"ijx6fL<g387s38-- ڊߊͭ܊V{+boaoq9m݆mڎێvo%!T;| ܁Ļ{;NN/g! ].b] { {nnnn&=Ļx`s6qۃ=f;^K^^^>>>>sS>~~?g2M?7MAAAA?g9uYN!!!aaa?=u3sS3?g GGGGG㟳s99O9(:???/_ /9c?c?c?c?c?/%_K/%qqqqq IIIII)Bk)֋S:S::⌬N^f8 ; ;Úv5 k֠3;tgXΰa :ϳCp?<Ob|ĻGpB=l'C0|6 0rpb'5gMp"rA ԡ_!.ս'Z$1D.DЩz() hk8["Dl@< 0R3quqŃ!G/%KHD0'&< !7"G} S'IW*6R. 4|-NtHs::3>~31jLlgrų,7֚` qf39<ˁǦՔn}39c N.%GZa9mNkO>Ϙj6kQ;l=:Ӂ\tCqvN䫀ЙxPK]]ۍ[J,Co9\J?w)>Wa5:Zo |n`H ı2n18i;;`n{)m?a?svy-{ry\?`)}^U;M n/ju;s9Ol+X/kr us o2}كhj >ëuھN\7q?G7k_q_oCOGvۘ%DDܐ;E$rRtDw)1ݗ^ESD%:#-k]_tl\$ߟW=(z1WG5N@m=wљP$l੹BZD!zw]0E6HlǠ3R=~-EOGb rV$+h)8S/{:2!wDoLd=&pKXv4+y-˻đG h[sϻ?yx .!z7{ =QdzO{ыya4$r3[D !x(ppHB.ó<q菇~L@&颿'/aeL^x GD> :}tO'o32{33-jmCp?>?sl..{pP B,"y{w8?~D|D8[Ky> ˈaS+?[IOy_UܯVa Rwkaw=׃e6`c#~6u#6o݂Vb ?۰فy{;|'q.]n&{8 ==ڃ=ڃEo/z{_{2^>򰏱1}p}Ŀ'O̹ &-C;*{*̳wT}jj57d:&z?Y~-?qB>z_?1 Y>ZRNxH9'VqS{E$b]kk%$ZBWѿ@Z{ k>ؼ-biwƌG{n~$xA+5xIKKUkWuRI&c]y{4AJOYMةk`mZkP;͌g|uk8nZ@q5ZwlD7k圐ԺoUoZ1ڃo9$^GhO Rx]Ϟ.EN2n}DP ~jI,cUw/HCCj%8ccx|7{qԤ==mMl3>aѡѹgEK` h\IĄ( ߱WHt ,C-X<2YɥZڦ6+ޫWk.jf7 Ey}}F1F{8ka~͇g&5[gqLvJF ͨY%Ծ@vP']8YjJIH ܿzŬhr=]~XC%1ڣJ*tBxȻS%qSԳތ^#~O杭{8Di~1ihLri\ԡG 6LN 6V!AjzUh1ot0_zԖ_5tᤨFML懛?ύ641M%j肊F$SWQxCTˡUrq v NS`0W*iJHlQyW!_(IΈ߬* NL xO&}qcFi: Oj 'xeFٸ qM)#110Vw ǷVg- LUss*pqɍl'9N؃ulSfwTBqՃb{WLᛟ=Jsi:?RSN*(8QesR|^7_^MǶZ3Ì'x0LUE eCS2# v(*Q~2''CqDQ~!-}<=9?BiVC ?-?L%CK-eӱUy,RDJ4**Pщ-Gpˁq-J~;6mЯSԳN,̳lۜ4wŶ lR\ M=Ʒ}`U%4X;'6Isk2$T?Ҋ1I3*6Ə, CYw~.O ̢Z1iCڕ|R[ռk尶oU?8 c}+m8򅹧bKȧ۲lz5{|o.6n7~x+&/~j`PZ^*ؿ{Z0oxĎ ]kRkTgdinΊ֨\p(y*"EM#h=nmf\NPZ99zճJԨu]a ]Z\qF)s:.#]KPjh a5ltk3qgVR|ze Ml1~b icTCCR>_6uoWQ֢XWiYETkqJ[y+r֪5v.unx/occӻRUg3.ؼ9,*Fy/{5jG[\m7}M?kW /S1ji_d0|Ն(I>e `l@E5z8}^++#pוUv2Ǵ nڢ[FO6 S-kdIg$2ks}RGXEM d;VFBW]ʢ)mߧ=Uk~twU覺+g̉T 1Wi8PsB*V4pTҵC:>>zt@u+ɾ 쐼CkstȒz~‘ONjY&pTͧ/{v,C'۳ Z~78A({Uu~^h1^Ffw__:dހuW֏V.:k 9O!RQ&ҜVa}?nL{{Ya=f ݠZyJi2GױK=uˮNY+sOTnne㢅˚ Zƿ]|}ؕL 6jn~1snYE#}j?s.:tE8̉=yV-KBvR:%KNxהIC{%4NKn1Iz6K;{rI%ϙ8!wVa^ :D$%0ga^=ZD{5K57tbo޴k<2[S Rɏj۶EogCY}&LaBٸTѷpsfFz.ƯOL]ĥwh]Mb4jJET~oJ?:DR-]_l=k+-Q)J6دJgŪ3kFN>RxGzۿSe֧[evn6EUdk}*k߷?<̑%Y.˒%˲Vk-Keٲ-[w[݉8NaICl}o([K{[KP( 䶅ۋ̜#Yv{;Üo;Qk~\9 X9UV|'Z*) ٥_fלoz |YMo I~;Fdו0~ƪö)Dcض"ֶ=t"}Kx]o$e  ۋ/f#{%ZCZL)8?P ^?&|[N=zLO|)JF(9ֱB<{enX"P˄JNe4X허u`R/Uקӣ9/@jHʗhv1RV ?d!oyEN^ U8,Y 3)4ou+zg"vCuw*cqsxtgT؏x_\r}Z#֮ǖdo{8nFv| L$vóQW Mu;}"F'\~ahiۊ%U5&M"ܭW:bM S*U`]tX_ N趇8l+f$]Fas/*-nƾsw Я8BցfmKmQ ^a kKe$9]C;EEډ;6~ط}Vq ]p=9] `[;myiL z{祮;z]ڱ0OwsmGDV nNwLUӍcꉝa*aLYigcI`緷oT4eSoT+` R蝐859/Pvfv^}╿Ck-^ꈎ w{z:swD )vs1'<OuB!*dY^J|Oե k,WeJD 0J9@8D@ Ϭб2d͒7yd$2}\v\TKF!Z"7\ūt 4K >@[t','Y^In#ݼZ[# ޏ -9 )jxtIiݕ,ɫZwUKCMfK1nؒ/gh?ja&;Vn4{}b9  0E3w)5g2vEޓt-`Iw Gی'D__7vc:<tfX%*I;ARrJ̊E[Ν;3m,n 6_Q,2#+fxou[ \m,@<Ɣ}a.=َ{XXDNjx`#"~ =ƵUBk=S5]u\k՞޶F7a}(<@Zw5muJ@Zf ;<_n"(K>@R?7{ w 2U٩1!j*;]@Ӝ1c~ve.&=c1)(gb Hb.j$3@UZL`$keb{~`sDðd잪$Z0%Za_R6l*ืTX $z&#xa\({w˅b¾})HbbpA{BGhC)=ƩVFv&Uλ:XbiJHoE6,KέM-`;tjuHq&?|qhMx~Ƹ p".T SΐŠ`p8 v7ǂ2]V+#N0!-0Y57,%;8!Avs$PؔŬSײ6/>|G.QRm^_}SyCbU%ܞY Ձ[ G ez]u@ MHM7zkl55%q bUM fP<. ㏣?ah$sgNH W;q\ɍ>/=/p(lm ,*_f/'AgI[`饙kwC@Uy"Ctl׸hXPco]v|Ҡ[tB`tۨuȅeZ;PՋ@ZTJeJ_sX6،&r0(_U],@wv*C9'8QRX/!)`. dPx+b6?Q!).,oƎ?@G{k<}m 8uK}p| ͏8M]ev_D>ya< O(7߈ڊڲPeu=p!E4JG0T-E@JmUɬf-*UUnʬSH|)MHZVnsV1q<Ġ ̟Ӫ'G̏ߏ_ΤSoeĎ-5l)~Wd_EI7wF Nk'mZr2 \BLFZ‘y|EHE:rlC%Cbw-VPU%J^QB,}9y,+FBy|=?t!rH4lߎ4<*o,O7Mjk<-h/j #.[VanO<ޟ~RT#8_cB$#W3^@<̑H\5׈铚TfvJbʑ0Mz_7P3dyќ]'|f2L0 w `KͳmZ\EeKѩQ0t2}ij3ZE)ӛZЖR9yw x &v=D|3 ȓ.'{Cޏx,oӢ ZJ?27NP=_<{bpq688 ԫѩtsM^B %PR2IFG*lFrPzh+eb >oscEv3}z{y{u o2ߢ-Xpi6dm&n|+UG0:"G;/Y M#"RSi-C 쟩G{TZ6`YAR}GVg%ohjb;ro ^q싂bwM4΋8/u2E({w9qf 2KfZPgAZtl"}x3!ܡJ LAbO +`=$C yy>q21'.Uov؁n*2UJ#8zRxNAmCW,S.$Kd?~|Jֽُ_άɺ386YFi~Y_J{|EBVHY^MKcQxr҂0V 2w60Ip=s3WCIyG!s]׾μg/l' yZw{U%x *O۴IǓD~Tkُ sQc̀SFAS }Qa31rIڵ}Qm+୆߁\]:R3{[}fz*r n>!u;-Azd=L Cgod={og3wvN?,ߑ|UO%k &x~m߃LytggA "&=2LeO}l؎m繪dݝLRVlsV'4m}>OIKл1#fyw1Qjz!g]{=jt.X3?'ssz};E/ؗjnN֢DPB\.>8\b@.$dΔ\3yn>mݦNARQEMQj_j.޻)JF Dlp;S{fa)qӦFsށO QKRAS+wZ7v8bDW]ٖ^LM@*/ , ]vƆJ.WTbㇺ>n2A oq|gW@ ph Oݷ }@a_ɹogQ1?%q?oak\{GNFw⣳c>hY qָUMvqZ'sgwH=][_]㣿$6RԺL*y*늯v6أbGz=b߃/Yx=R0?Y`]{g't:׎x&!>DdYơ-X5C6<$j3}E%4UCE2J:t#KҴF^ղctHFuP[3.UnX-^><0uLV:zK|ʤ [i]1rϜ,_u`]T9ε3ir^0)Na\32yNWկ@6r:7Vgڄq3Ή.;Мv|PqǩP}Hɚרsr1Kqs`Px@ 6د&;1 òpD:m` 6<+ & gxw e"To&33e[(t:.PSYOm$V`༌VOL^Fdb]M,?VE.D)W.>?o6#q-:r7/f g32iBt} cpDO?|`ݘ ,a[(VR~fyF$j>4$'!9`oop!0Dm澽M@A d?,'rXC^7̾S`#e,ܿPNdk1?dqcֆ%"<J6U"kYeNS^qleYbtw|᫪.U—[3OE|{q#Xc;nW`#2Il{+ZM@yCi"x5s>7!ZEq!}$"?DG*OOr.f9T ݤ}Co&qVbN8vu *pn,.?Zd- r sb"y'A0+SBt͌Vd ƛE7}$IQu (&Ok7U;"  > r=w吵ѱ.Zσ֜+5Wbկ?( qP/{Ug)*쿲E Q{ (n-/([,;3; :GDrHb̼ڲviO{I;=S'o{ɼ0 +>ׯ< ;ts#$v}a^H-$/__|m.w_,'wv;vؤOb,i7v?_GEBcd v"[VH6Z3K9 >Fciea>(t4Vg:_PS) y g3 I-&%ēҮ ;O &>FC^5712C Y?Zfh 5:QC;Ķ_[#XbV̖ؕu-G5 ʨ)_۶K4}|ZuB%\o2 ۩N`roJ$.gcƀSbx ?(ޑD w1c_r,7Y̞fH?'0'n qVѡ (~E[ Щz۶DtBYoǟ>0֛8uX߱xѢwehNB&9s\~-lILj}y6<'#VGݭsCs` N6_:JVm4bgm)75}~ۿЈY~Od];"Jȹz݇ito {o4{o>3Yܛ_}1F_H`Y!"g7 ^_$cX'!I.KgMYBwy-67@UF㭢u e"W٘P%qk6"OC8KtMF<<^VT؞ 䉋<U PݭAi9nēVM*KArrI,IRgWP JRdR->j]lvI|?&B gK .-" v2#䰆D kCfĚuac.$] 3 ^.VQ^w3qqA&Y ?_F_; R& fOh WMoz)fوi@>`\2@{)4MP~,yX&&|cǎ"@7?]r11?A?؄'6aa"1AuZ}WV?ʫ8'@r.g&;_&G֟{+Mb7>- 29@E.s>wFHCv*ƵbIIgNK\Wa,6ق-W+&D6 X$ψzؓjG+ݘDA| >dx41 cL7ʘw4v_32o ˤiӟC'tV{332u](8 ȷ(ȴ`=\ͭl9&͹qssqsq<#W Kd~lW<&±9*HrT$?,>Veo('UA|9gP#O<]Y;JYy\4GoMUxBt[Uk+?2x{z{̞ U&;( lHw &%9<#F 98WW$) EUnC+Ӈ3^-|4XUR1 m+` Zm:A[*oH03&3O/IvI Fhqn!𫺾w=,E\w ]Zyxlq}낿8.)8J,EccQıS㳽-H4nN&a 昇hq7[S:nph*aX6 f:srqr Yx.D{hS]֩iӦsvlf4H[ux ,TY{`NuDA dM [=3m{TVLf!z|uvosQ@KdoFw*RCi6[%(_ 0X|k[c>ؽ_lNq]r= _K-LMwxV? –_d3|i;W N]L3[)-kW>9:ZqX!dK@6'>g$_pj<+ABw6x;zAS2 ?#{GJ|_yZz@ȫ]+ĮE<׋aX*QpUo [w [`>W7*|_SR \BKbTu|9,LouT; ͱ&\Ols+_?:< Ij {LSe`JY_dL-v>cPYT\4N=x}18oqH]\uE/HoJ[)k LW|ljQpJISJiLXPP CY;[f[Yv}oϒC 5h w猚 lhmUAZ;y;tӖR58ˆއu|PѱSW{zH OI {{Rn7u|mL2z+8j`Io OK -}= ?;/'Cv1TUZjm4d˜uqmdxjBV>nc?17Zl؀۷cC[H2J6.c~5͠y !>Hxja^wU6B]Y9EBx''>;*gϟ/=}}t_r N7N GאB1nXÕ_Uɕ&RǟxXh~py(P_RIDeQg"K eVGdSH)Dr t@w GсyhYԬYC5a]wso |B=|C}凘|0Q.5RPF`M*q1L`->m rmCsܲ捍bG o =5ԉ#[.JA. 8v|?<}5+YHk|H8f1L@NQ,+UA&q'TV+bCX<+$ .㭍1+_ rCc>TdzP`6ITr~]nb/a:k-Q6Z/jpMNQRxxrnf9>>]|Gh7U,-Z2SM譡O|/jޯsIu ]eUk:Cc+O#~g,0|x4Jx#9ZUDx[[ӳT~k&Suy H4:[t^Q-up_C[T΅]i;xRxl(qůgv6)Ǥ{&fSS:wSݱ+\*}le:GtvBs7G@T"ɹɠDJoz> !]yS La*jv3#"dA‘Tk e~_Zkjuԗ(Rj1xYcp4h[\ZRR ד\;Xw`_{WYUIwH Tj2 Dح|-/kڏkoSr1^&oUU*X~c'WM_U2VzjrRHdm,Кa^%@M:hbWy9QLgRhuJރXVޅtBsGM.u.FB*$ÿR+^a Q* wEoRBÖ%w oG$<|hO(kLC'|owD?|5mץxzfaQ6T6F[>M2gB1GMj& ]~>w9 [~oY^cfzMM?hOy]Xp"U> ֊\$𳒘!l]괬,T;,x{f2麖q6uT˟ߓ#2VPQZRjȥF{uϣ]lE|Tx&/La7E?ijd@~+*iirƪX[PiO>_e_yM[>V*j%̽X S r1@.xEЍN x U#(s:XiNG#EtȸfdfD5 ѩ{ Xk7,efw<4"}UPFaE=_t}[2wf][mՉ--U%E` /j6x$mhԈ)PBl/,s%kҝC2-Iюړ7?\$]OnLmɍLlC#ܜN1yiڹ˷rU8id=9,ƨݏ9|+hc*IuO[TLkX:/v.q\f/8Eﻊn#xF9\7ƫ}דx'?]c00?[ia/.01Hiҿ0fIo?}FU:G﷛Pc\=s\ϝ>w u=w盜{='Yz;g<8c83,<@VhC:ADs-Sɾݷ!}'@GHlw?5έs|hTĖoQs$'Jaz8#zGs烺 %,-?bNQ>dT1LJFר5V&G57ݘ8|Y ɚ⠳^rÁ;o\V[[CDUNޛ5^rֽK<^b}Qēlm6AڭB$嫃5,s#>oI~WUR'D)%<_gR .}*m(Xq~tU=<2i|NQZ:*[ -՛z|td.T"b&g=6xl0=ޕ7HkQ_"rN~SJ:qVW^[ Ș̺>\)ګjZnI3*~)U-6րl&>9,gXٚg 1K2;UNL6Ww59U.)ކNM~pڤ*ᖴ6QKjfցjB>u4̝ "{(OD pGwk?i" |%ֲXaɽ,c4/}AONd Xe ڧvFAݳ!ng<9㜷?ظ/ (\\ ;o{g*6';ƷVn=0UieHwDFǟMxd^f2xWy_'60Yt;igwgs G|/˗{ߐlKOgsy [Bklm>|'LsǘK lzHc[iO3z_Ё>`)>|'gg0~Bfۻ } \'?/)s˄>w` >`c,oLBRh0q$p *|#vA}08Ul<'1vg#xJ51>ˑ9yO~c<Xݑ"ߔ@qFg;s{MlKw|J |ՙQk>v3SVGpDooKծXՀ @Gz,"S(TSb Ճ᪌XWJen(sTʵRtbVә33)?3ԗIu'L Nn5 F& R)H1R ;3^׾'޺ 2͈&gM3j!08~DdSz?pP#Od9?|G n>svV:>^@ 8J$gC|vRo|Z9 (0[dr:$,u6y!*?4}2 fa$|)zyRycι oZjGu_\͹II2mysP>"8s,x(G]Z["ǵtO"]ӿiXM"R>PC zSk+e?xړ&f)!:_7PLnA8PmBz;iTx6,{SZiz؊J]՛EgcSa]l9Fr&+6Ye\2pZ"7x+[-z cJ\S"41% i0xM %G۷z=~okit62m7Fx0G'm#[Ѽjdp]/i-XՑ!i H,fU#H.f^*OD_׵iWgOU`P1*j\D F]m!F%.7TCVVFCzƅ>@R} Sy O2yEf-:[o~}ȾXXTF,yrj;^gH`~Edp=ٷn\ݶnxя3rO] [:lWF,a%[R*d}:%\5;$1 Mt4TWۅ> T)it jA[Z D$<=+j\O&KaL1b~Pl.QjF#'6n(Je|X*>s[uѮL*Xk6^=-| n4ځsE!ˀ8Ó|"-<`1RNmZjL10jE?$Wk$zW]~ S)khHydmyebrH}T~DUu!yo#9O8Y~0>./ǹcd7Inys(nҌ)Ny;bDU U\,q!=S5;.Wm2I6"ӗ0\FNU" 6 MR܉kfO&/\H;n]v6Ddцw¬s[F'[۝/YB4dhטF!䃚`]Hp zٴOפ]k9R]~I?LlDLm; ^őbFa#|5i5&hr@`e`)&00s3Rr=92ag +VZFgCēցMjCgzW& Kw:&Cvyv6V39ӰYq H<~};JoamK5{ߺ|MD&9w^M]a Hw.Y̞gv*7Gfsye6WyJ"%ݠ#u~!M(wɗ9GV? +Dbx=:MSԫ=X$zu"ީ9>M݉jз|̅XϩV>2;~e~`e71o=p7[:ЏxIK&TM:;3X3S(|l_R.* o{v7=kCaY0I<$Ȱ{5ok?fs/ֻVgN*ǹD bTfR:jMR 1:S&eOL! " pXzM8A Io@x fȥRb7xj-]ۙp{.Y"4Gb`gӭ P39ʹ1_\0Ά#vFY#UWƆ‘-";#۳\CS)Nuhj=NDtNƵܮ%v櫅eKU쌚!؉Cyd#||>߀1pe]yJg(GdLUA`Ƭ32=R,W)a)exD"ԁA"ZJBUpX*jH1G_F2"҈|;& DW [F~M/+MBV˭zD_.+ZDSVqad5S߀70>v։ 6[uF &?Ϊp宾*X&&B؎ƁDw_Kj L'{ۢ_ogd*By[JQa4^aUWTǤf 38d'X,`7Y++Q, {R0N!Yu@AI`1-^Iosy>)adf줺3[ H7|)f}v0AP%61'T.;)t"G#*HFКc)ca;X.Zx_D+:Q 0Tm;zZZ kyOW||Vٝ +E[D zǝ%wvgvG:(cp ArZp6;~lX< R-l"=:o,Gi$]пY)4%}ɓ@3$)x,:-ą9m=3l`mYpNQ۴G9۱CvR޵Q\T\l2l"_O&_WCZpwYd PjfqJ- G{ҔޠA":8$G$1i6jsnw!jۈ# 80񣱪tg_yxB)ٓXG$G@G)e(H.l4FVCLڜ(t=HlD 0_-cOXs_-l%' T\d DssefGFR&-Ց;$->2qUy22E齇+\u۶tcD<>6'% md7Z|0|:ٯ6]Ҋ&R}ķݏnw@LO m& % ^P)Je)z%4!|| 5qe=jcwFgdDfxB+--U~ah oc1#ˈVAɧcv$ÙDعmpD ]+1E\Wݥ*[D>/EHMYe4m[C"R}Nb6r [z3=zM̺.3EfWF-)-irΆpJ V9{YSw c֤ZηGJ])m.O- umv3yb4/|œf囘l cxΐlPg\_EQV ?T {z*?C|Jtv,3װyafxDMk X\LKY9_BKVJ1SYEV1 (yغؕ-LB{[q0k$= G)L bS25UgܥΥѹ7_ne}(u. R x{dWA @0 vFXFf6ʹelI++5 ܧՔ1xH* e D27HZ- ew䂘袁Wy٪LTh(4 kW|SIum[J._So܆NA!5xx lg am PGmUōčt3.혫_=n ^ҽcnu7ꨩZ2׺$#O\JYnwǺ-|ډSBrubu)Lr+{'w ^Ei9cEcXѭ_Y.L,ݪ;?; XH@X (/[` ~@0̆Ԧ_[SJzRq~ɔWvwTt:ݽ9?syL2K)B .X*omr474֐][&RɃU֎F[Xf()HٙB|* 1Z 6z<91?(UNY[E# q nOnZwj2w","".-7 0F+$lZ ;q5Um+_`sajtdM ]cS.NTđ0?w 4X#8#~)L0W [ sS%KX u[kR42{RMx 6Q{E㙃_NDSg?Ɔkjk;+ڃܖy@s$WX.;zA%8`=}$7-3Mr)⹛|pBcy7x,!'MTdd x}/ks>& fS j_t?SY^Lq730xl#L`Kr'{n8>v?\y`$mε?C83@C6b] lڄ1ǹ.]Wg  I4P q/4bOR1bev djF ` 5&v 8jξOn6iay,?"a]GAy)kE;ǟ %qI`Q}ځNI? ~F ggZBWZDT/%\:>Y0R|^ [fNia 0OˆsDObU#+6;01kdj.z&0mwixZְ$I%[ޖo{I $$4lJ4P(eRv2.)R{ߍ'٦~Ǐݽ?gT;  aМqi3zpnQIG" bu2eUujmfĥ3.BU/M 7`&;b#|# 4{Iq316jӦ]LjK5DpVQwfeXuMPRw鄘[557.Lyx_E YMNO / " UY2̠Q)X'R2cB/6HSҽ֠>>ax~>wDmMZd`73E]B+.$k`;XϪRx/Hl u%f=<|f3{o3L~]};?_3o3:`VJ!N,|ɿ#mq#@ڤp_-i9Ki7l to}xw q6wx(ߙ-3OzpWX;z*>H4Xg=Jyր3 LQVmۢ۶uV2Cڝž6^'!(Eo*{\ #>1CopOEAL_u"!,,YZ##R*!EAg+4ƲݡΩUhZVT vftU۵JC=QMTB"=\` ';ȱ>!#]n8/$(\1rF^,w2ҴE`WV˅ NRjuv{H5Ϋ7\ @K\&pP7*)&=z6 2ptPBns3dǿ`g;w?j3[Z3[[eEי~xH*𐍈q;Ql{Aw9Sh,Z8Y;>)8R3c8sGC{mEt njpNҷkb`6o$En}o7gvu gۡX C7<cSC;/t)9!J`\`T吾P;?V@.N 82_F}) w Yُ)ޙI!$ =Am/1-5PSss">)(>BS9<'o[}ۀC'_#*'A+>BE_?C[侀㘓k]g^&k j󢶏yPn Z{UV;%g8 SAԡ !)kݮ `~jy \ 7sa`nCx{=Xo#49y]F#*3)+|.wt.EB/b/l1{:֋(rߪlfI0T˲2]be^Պ].K`7cD*RRԶmN5.f\"Ki"Զ#72epHO$yCb|"`^4q47DnKu͸Y2y,4.AD܂ }FSf:voUZ nj`Ê\ۓsa's߳pgmd7i[^Y~/DBil } !xqm{I +8k_ТXF~v%| }xy^!.mN :%^Һr8+tSx#Kx Yo\!.`~ST}ʷc}ha3,$>uLݧ$]88}hPo_=G[?Oa|D⤢.Fy=Hc_9ohN>ǬzqQr_?S/L7Hm&o#8qS1Ar>ug`(.9 r{?u*)Vv#_Qi_ZZ"ryI4i"ȅ_sqv|*ګWyw;_˿?O [9_ FYpwMCTL8P_?3)nBO 4 MhِtE m&%˙ /B(23Hۭ|#zgC+>ܵ 鷃S=@<fRqe?R?<Bm=Em/2myQr32n%i; zrɸ-ѧf>*& PיpLe6kA p! }s-ח|;yV !$j{qAn'£㔎,s#RWM;M^Ɲ;9} W9U'̐y)^-Z&$+JwlBjxΑ{k=kk;csl537(SbJ# 4#vsBd[,JAcSҥҌvU'U+2Z~d#^u- y5܂6 i s)a.&8[G9 .`?(YV '/Wceɳ% RIaȿǿk݀F|팖A>ڟ {:_ƯE;pU"H(&C^=OU$A:oyh(ː Uˤepѵ-,ּɚ>L9qM3Qd U *Bm tvSyjWB8ZIFla$\rӫK}.E8{/_T(!A{@Ii*9a%~gL,WȽ֥GvTJ{7!.>  /iax ?rD3a7ߐXFisHA5,lW uz:'a %;D6׶qnGh#s T~@٫Ɩ@7Qsއ}h_|LZp+ p Bz?g@$Hm)3(2E\,LQϕjyTlϰj,,2K,͐)STb byBx-+` U(]"KMϸ>JdX:E&X ,UdLUHtj"Id4h_iR$(C&n|:?YuWT\'>t&"-DHc m;3aU-D$*rVByEY!u|x7GfزaV +J2$&k# Kkt93E[WA+Jtf@1B`һJ"iN6U4ӬR`b؃>5|5ۏڹ` i"zBߢ-l:j+^`ܝ=BmBG\; IjDaSQ[7+IǨm5i,}cP j=6-݈6܆x62!Nwn0 __J9fPv̈́/e>E0tVf*YMV4!(W&`R[cEx/E9"s`S^zqSR"pS a4(!EuG9p; Qlה-]G-B4u1fiw3$sڽS_$95=ȼl~DϠ07?7Ju4»¾z2iP qoYiX֬y7fݝ?.euAHf7 HB)RDq<dCK%ّ钚 b?_qG֚XT]gs˯ra[QR^5h ضdp7:}1}řqx xxs=E qoC_]0p?;l: f67踳{SgO<rNsC2k<>^rOsZN5:4!X8.og^>? a<'.DMj>\(,bO| 24+7/}R<۶Pvtw%bX774fVYJqa@8Z-D;%هueըU`ņ; $,𞥑n!$EYQ'3xg Ahruzzѫ׎9+`phNpMI e&\ohT<&œ__2zdW+I^ $~$hPoܸmG\]pk8ii D lVnr׷,Ƹ/^th (PJ#(ㇿR7CKq05 ˝>~!WA!XuxoW'eŽ;4XR1z]{5hkX:9гm*d]'ڮ vn;T;dҼnwg%@"n59^$]{ >B7Ur7Uge)ԥsP^Γ}r 27ZDXĕa^Ai :Q]|d(ݓedzuUYiC ):'8CCBfP+LU8`rg3_Gȭf5i8s;"!bv*ogIz->ū^~ |_ze]sq{wU^Xݮ 67]w8>/2+p^.k?h;Jqk PMu/$|h$n|+ո=ӂ9Mܞg濅eHOw_^ DYpCٌ&b"D"B*LٝJ_.6*dBMʩȺh`fU-ߚ~c`Ղ*8ɍHSM:KԪ;kFL{Նh^ˡzK¡D2+2!5&{a3.Ko^EkHCr4;-^I",+aD0oJ})h#4Gx&u[_zbè,k F_SAwECn WC-`%$E2Ta R5=!Z𐿤MRTchۊop/caFJ+9Ґ4N+epNA{ap]~%]ws,vQ^R3,{1ˎAҪͩy\- l,Lom g2+-+L lͅ=KsId,2c@ ܿ̕jEGh輡b =H|J^@N_[(S=%$~xiEjR %Dl5G&A ,іgTI%A%F}*G*NAKiM"n]— ZkP%M-ׇ'FA"KT#i05E6[놎 uH~嫈0w0G#:q?WFL&HH`smuIldGD^)IwJz.ug`7 BQFHz䓩fmAMEWy"kJPHRݑWu*׌omZ,UZf5įL.czp>靡U%nM)%|1Io¿,tV;7tzUR5T;YYSū ;bVγ;J`sS *ug+3&8SH0KXdu=LɊMGU0G]'ju3 9rd#/ v0Z+h9U+C5EuCw) YQ?zue9:N2[u]Ն2RwV8k<2X $DPxvi~玖QIMrFzC#wՇ'j_vVYʏc^sE-Dm=e4El*L!$F 0 vp9hWjW~2и)y;+aDE}ehC[~hK>RrF`j VaSoS?kM)]i9A}666ro944W$k+B I"_-SS-7˻U{ ,R)5Yͪ'8E"BLc\$a?+ Ҩqt_玘pP]ۘÆ{j2&ڵFf0L3FB |R-o7l,pU}͙5=Df\ ?zM8aLgƸTcPiͶZMIFRf='ĝːuJ*O wO*-.84"w12~Q7Ҧ+uMR0ey@!u;G{u͊g&?e('X,|cqBx 2[3Vl(H-"9;Tpwʖr[fxRPdq) 6Ry ֎u?KqAf a?W%/ɏݬ>O^&}̜]?SX-΂s>)l!XTP:wSuE_J#YwhTd-MeEi`VIȧ"{Tۑ_+/n+ml14i"XDL ]oIƾ\wN#zRMPP3c+QWڜM-H'4ǜIa/slG jd^7+=D*Gs茻p&"Hpɩ N5eۥɿ@^a"ֱzm3kcXS6p rQ]ҁh=>J/cݔ:` `=5.TZMjCզ-Jq]Z%y:nZFvůmUi] @$4B QƕmD*-牏Nw67cZ^UxMkxd1!KA?}~2Ӯ$LD!d.IarQaiQ"́|ӲT4u\I(U8rٻ eGu:-(݃"> 'v,AQ!SD*FߐQ\RX"56O{T07EPe*(o9F (ug,̌43{%RsW?LMqŚ_SqRǟ{Uxw':aoE݅/g;(\4h^Ju?gV40ek %WCvǜ墳[yW ern??)z؂pSn{_m ]K9ܳK)ZG2['tj:h(wqtz~!U|[ ڹqO{7?ؿ|1`NJHZT3"At#6zEqͧ8 8p^7]n)=|$'272ms$ }iqy>ƺc6/דgDkpwHQ!pBŝ|tႪOßƆOj1/;=e?$sd7 {4ct$^#O%{旋b9H9rm[E+6[oQd#ṇn/,Q]x~xNFhQť֙'k!wP ӴX*1њ wp[[xh[B%PL.mx8=WFh] D\ sZ2jjvW[]66M=zmӢ!eH!'8X]\/;kWټ*|gMȐ_|5t8..u9…Dx՗J 7a|Rߒ 0Ц!Do+ p/ !T¾.\J̬s9ENm_Ĵ9%s9ZWXud ʼn3b!gDkDHlaRZSD],:AwWN ^{2G|ѱC.Z,_~H]{ |g{5 ΀n"ddJ;-BQ@bzp(3غzܢZ5lnL;m޳EB4UKCzu4&͹ݱqT]3847lL 䙔)א83p /xgEC%gpCȎCi'lkV) P!ܯv? sgohfx./%X]Hh%Yqf> tnY.ќ-y,8rID.Bly{qtXGIURt|fw?%hX5A/1&샄jR:|U\<> +=4<.<r{$ )DKosU`O,˚?Y0J7bgGNsŮ^mby_Iwig;zvיh>=˓2l 4ͽ#<^\U{w-m.$-0+\u>.}y`͎{Eɜ֜N, w!`&^~ЂfZݹIl ʹgAEʝIE%jhV۩HZ' yNƩQci,"/+ [ӫj*'|;WQk]k-Lx,ѹ{1uFSި xB E_OGsм+xAϜPgg}:<~3tvpt.6[g^ 2UҕRs]hK aj+(Az`uՏG;ZjSVb)G|"<; +Z۷= Lv@8ц֙hub{уHx@Oj6RĠ/~j)'CkȢ:kn}M Ճ:bG"L$Dɉdjy?cs<'0RVQoDy$g\/ ~(mC+.w\1- d"{^` ƌ_&e~qUfDq^}`y_JsK8Q8ޖ)PS8 sÈi-z+QP-~/J@xIs l( ]EơS%{N|{>ir_Mrk?|k|Ak ߸8$S/3*A}~k5:KwӪ]Xᄍ[h΍? IbS̃@jVD'UƼy%]R2Y~<@l|-\" Qt# Sˈ`8Wb?O5&cmڲ#HfR0r'+uz .ra7TWN)X>| A$hjooj)O܃`[& Ppko ⓕ #O{V4G?;#w:gdmf+"%#e xBY cR*FFÅBu#MqBDM .lQ/U,W)[@vp/s$;BryĘky7wť>C?;L&x@lxnb1܉dU4w|M(KZFpML%oS7H)nB:Xqכe?ZiZM{1kokHk]q.Z딎i\CXύ9n=vl1ܳ=KEnp(, `UȊ!XvrҴmKgԭk+[->+:c7jkzK*0e& Rd2WN?͈X֘LDRr ke F׭,!b߬invU}p^%P =Kf *6j, {z>Ƀ+`==xs<¦&yra$l D6D;jwy>nLb+%S[m6[UV%T:ekGİő.'Ϭd)ڌ+Wr_+\;1^Qv~ԗ"AJ:hC1{4mT1%.˚FXhMhM8@ԓ:Wn$W*ʵFxqL*i^GЍeonA)̩mH!k,|1Dt& 7`5aPY,y3u {hlq·#b#^]>t{FF?)7Ins.vK߉$~Wzby`h9^`ڳg иa" 9wh_n#++G!|t}`ΜzuBН%d9kl.(OU轫n8"x ;_+7+Wq qe, R;Bv9e_rܭP DAVj _̗h8xݬKF88֞h'2r j[iTXuw ;#zF#\ gkO,=jk%zW4Ԛ=v'(4uhw H*nԖ*6ɖL.9@umh+M(46;a>w!6O??%|.g:⎹ G;+>38,HvJ: `Y}anMƋ ݉.U\9̬) f͸Ǧ:[pn0|>yplVt.1-YI>>B1/ ϔy"EANr^a^AߋkN_/Mro㝲9*!weG91 "L*`=ο O!H pdzG":0p*V3vqyR0X:k"- .LjgiKm5ߐoI[D;$: BFTg-H_rkuZ?RB{^[Se$CqB釾C9\jsid;7vM3'w%5t/q ].+g}31+a43ݫП'of@DhH$spWx7%%/~/E#GJ_^WB5!?Yh hΝ3G/]Sxt۟+wy^aV)oYA2e t8>&I ?M?I"'VKiɧb?+AD:Ysb%QO& x ߐu#|[D;рQ &ډ , (km;4V%ut eCU cY,qhĕpFز;uшkAɪQ-z_{oN[RLW_o_:8U\뷖NTMe1on.tFU&k<[D X- 1 =뵏/ĺ#"u+/@&cKuhnC'޺H"Oи <| f7}jՏOT_;=>C'H&b-b–_okg^FuF1P_RnsAQZf+$-ϱx ɄEX;CP$Ax%8"њl$o" ?8b񅳀'O-RUag>cꎇ䒝/X_S}~!wVWV-,7k/`zd6'-V 5R "+u*jج:ќidDy-]64>շ=3=oj?}Jp9|͂$ɱR99Xu"֗HU7, (v{snh g\}{ 3PEsIQ];wZA0FjbCO,+'Ɲjr)wvTf~"П[mIF& 奝!HqAQ]lLfg;ϮqI<ϰeG&۽4hA4 H{zICVxIT2p4a.7Ў%@6kW8^pQ m<\68_Y= ͱ$ٟ.V M e/Y9gF9-/s7V nS7_O"N!yaWuDzkG2&@]ː +-ғ:ܻϫH7̅Uݢ1ʲӗJpog)[...Dgڤ-*`>$:|zBniO{0@ށ߹AB[륩H&!߽Xx&L 嶅占qSlL!V}%Wݎ\J0^r SjVISk@ ~ڐb۫ZIk 5cR!2VʌgS}f(5 {6)+q97@ti5N "j"x)MM'ZSd必^|F uG J֤:i\p 5\ќݰ&ZbQCǦWIDijGv[گll*.wK||Umi䔷 ۄqI ^VO,:Tt<-VCJ0!]oΑWUKjIZ9[9VMAæٜٝîڻ^c{3`&G8 w9qG>0U43k?zV~UL,& oYyuY+xفoj40vD|Hڷa|V;!4gIFٽ|WY6$Ȇ_cjXb_q?ឈʊcI͡џ)Fqaȟ]ٍG9ź+Aބú_D7B?@x<:"4ܺY?rǶsj*˅٬ͅÍzTW vj v`Ҍf'Im7[19WE ک+vt=i8\f ~o:cyɀ_f#dV Z8ӎD/ 8=XVm]]E\/d u*8\ d+'ԻOiyt :gl e0|^5ur}. (uC͟suTeTPKc#l 5`[ɱb]]HƟ | : P"cȆCrm *EfLX&S5Zzd6}ӠƛGRQj$}GoYZXI0i=2>{y\m,FPi3g P)D<7?pu74t@E+pt#?C7uoo qljO">7T;3F3/m &:^W8$|^xn64{#WWY)BsMNGr'= UF "brRҾ€> x0H5zJZ X.K^ia0ɑop LdD *p] mS"`Ej_ݕrk@@ѽ4$Ȁ҉)gWzz]Gj" z2K#7}` HB74UX`ǧ#$#Xo[ ϭCiZZJ-nJ?yؑL_ (Q?"3hf60 Dhi1F& D6l빲PIvE-]h2^L>u^@L4˦Hꌧ"i; !3w\{q=<_׮'nv-+ f W]1`Bo֯K̈́-iM3M8mIv-#tG'V`zoF`, W潭ߞb! v~/A9[gLm͍nzeRK\*&#S?;ڽ-`׎)e{,Fl==kxv`HGD=62Јx%Rf^a\ks!+PI,6q4ccIagM;!ĒF Z}Ƞm׍PۙNdgDSڞI YuF1]Ll12=v?K:S.w޷ /4Sx;&&rdpOl%vMjR/ 0;_ů42YÅ">$l&Eu=Ba$pO54([2|Jsh3K4=|o0I$gm~ڭ1Eޞ;NA0m#vJ?3ubXtrJ?Q Lys+vȪs4p!SMV-dlWs,MyB]}!yȢ{`Œj+ HR}aɥeSjKO.Ud#Qe[*k!BntV&[4ugCAr+1*j\ "CT;`FEuBk,E>,5)وTJ) JC~֡##7CqO]Bm:9E r-Qi:zꛪ o(H"K?K(G{y#7J{Dk fRihW |CY42$w$ZlB!Re:툃hw,to\JR;p\dsgve>;g],eX;lzbU{ke%t$89biNJiր gF= $`64Dǭ+‡5&Cu$ѵdN^&kjpF2GodA?xFJ#tG aN ~֨.3Lľ8F:_._ !fvh.2UDwߤgh8jԻ=s JJḒU@?Zl/--*LSOu-Dh Cy1O!WDBGPu=ȗ&&@‘ +ܱ{=@a LTWx$ҮB8"] +&:Er5@njrmɴ_k2{*FJHE&n}a?lgu)Z]yaB%msN"@*+/}VB, }ڣ.T'CT~F{T|I5hI.u NV 5Kqbr;/ǁg$݆P>Au/ ˆ8ɩkO/^K>4(9- d &%mftv߇v]x4Nx}`2ʬ|T6orGR_ {I+V A Y}[g9- nqTu7rd_ +7M/mX$Z2hw/|(Zu(;xW-N};0;l%4ԇ[BwnE[m_.oO.50z%U@oc2[(ӎdʥX@z)>weLp$닜 1QIz72ڗvlW doDV؅ Z WCN::Lr ^X_ubl[o Fkol|IIqC=Z ٰ آAֹ,`Hb;6!ʀ{h۞hٰ9l ڑb'@""UtӔH P~ Z,hבޝqgt@Le=0P|u8mqjf=~sM5KVwU?lLЧKPy}c@`37rD aIxX: { Mr^k\^\m0[qs϶/d = %)sycژ7d_, ӓO1qt'=@if+GW1AAq^0>΍RaG~f2?_7*6~ ߱o8%mq3vlUGw?5#7N?6`2ՅW}%\#`\tt -L#CfjtX<2[$KRܾ=#}DKKB^A^?&KzR]<0}3Yo3xl܆ߋ6x^2tC!{?FI{h wO {_'θd>t C3/@OBӦAwh%[Y#B`Zp yx2Oݲqε,2}c߽i\g%Z*T3kOrG$OJ??dbof8^ /;4N /}=#>>sBO3YL\^t?ýXr&)O</(<^ݱ^[쿋*P8R}jFJסZ$ |'s_/ݣTv&C{ܝmW4@?^@ϲ y(<ÓLܞ_ZS Hvһ+ ݑZӺ["7bV 'O5 bC2P\܏>ۖ)cA)z4/.6pIJQ+L6kƯԺWXD^]oG?ޱEPՏhZ4Ey}θB6a#&zrr"ia|li]:~FXUj=` 'kh6̞sr=V.HтGW*lFi?ґI \h]N܈ =bm7\j4(F =<Vwݲx-'k5'."Dg`;7ᓫ~?-8ՖǏOOĸcyo%` ǤBo2?n/*#TTh5x:PhJڑY􂷂OƇ:ѷ<:gwǷx BȼW7Z #H-EPkwK$qluwr!n5'ɞg4}_׿nh6[g(uxFcz;Ж78Ŵl~~Y_5}#pimJјzVD3!u\PsN: _] OhNX,Ҕdu)ghӉ7 zYj"|T \[w[ ewr} ivtq+7Z3AKK"mK7*e:p50fP!sHX1YƋ[e ;q7>Ѿ39I@ Y7nOA?Yfg8@x&D, OI Jcܦ;:DF #zq?$|7'`֎CyHbll@gk_U'YX txT{[Lу[?na9~Tqn]j[B||߆ch"] ?O;wѥ1hVedu~xEql~FA) sL>/ InlYrxvќ_z#y.tgnđG B V}bRwypw-F/RË#LiW+Y ?83́3ѥqA8k6;@/nɳ8hM # gen?Xw 8pIJ6o}톣 =>tC:-qR7wZ߅7oc &2 lMyt?IRgf)z]CA0uӦvV<6I{_+tS;{L4@/ zZ۞N,/o{<*ccyw<=~Kk zSxH~:nZɞ 9;Qg¿S79|.'}J"$- VY[ <s >H E:0 &QW2:ถl#}Ul,\ϋC6{")nۋXnM I*֏I[MA-Qn*Ĕ "LQ6[@Y2%EwO  u dB|+PGXѽf #|;AVe ܽED+ML-o8AX2exI ,l9>PE#@l7-pJAf`P04)T vg`0qA<Rkm!"LNnpDј uNIwQ$RR&2ᙠY[3K K }rn2(5v5ʵ@P8΀I)eQV=@I`l[Ih/ωk#;~sBadLǒZ2Nq#JBg RUs u ;˕&:iи+5MLW:dc5SjըhΐU8 %{Zj9M6פFKNulwDB*R_@Y?ILi۳S@{etyln.)z$?}vl Aun)" ]2%9{']F'~)ɢn2y{TNŦ߾f"nxcb\ߚKxIBnNO GA.T t'I.YO:ZNZs KN纳&gS㬊J^m;#0(~wa¦!+ hrR^ Z_eN$!m|s :ZӜI"Bn$n c$FpN"rzXxn[fx:U8XYi4U;V2,kM ۽-FmӀk/%p0nf'kc2 L_߶aV)f vp; tѦmڣ}fo9Y&(c@IVֆs08 h$05Z;́сC!m]t<syE,j |J,K:4&s  Hyp|v9#oX^n8>}[<_fSV[/ ⵮אzBkwҎC=*]>J#2N3djL8,j)*{my5hȸE'{=ʀˁ"(T6F&#{|^Gs9hb3HoY);6 pvP"Y!_WO]&Qzv]nMʙѳ@Ll҃S^FP!)@#ܻpaw Jf"Pc GSvO`{J#ƜROL $Kn6;6:ؾ;~zz}t TGVabeJLk XA8) #:&11T 7{م\GI$T?1b3wePЛP&JS 0l j=SGɄ1rI:ǥSԦìTkbFH\qrK|@`G5ۉvn!t`稹AhIi l-gAAL Ƞ_dLyY\B#:.ݯ|Ol{6yۇp:=R8}w+(R9p.xuިjq' ßGJV_ B:,tķNeN}DgeҎ|I2$ˋ˃o ju\v- &SCK{~U-Τ\Dϳ/p;@Rω\ 3?#Gl ^1CG\Ъ][?R/i}|A#+:f5>L\Yc_z*brgE7>wpt / SD+'>Hx-Aa9Lxjhjguol3.$H0dvMuB!IrT_X7,Ob."XG|bwȑ@*%} AfxV]:uI_.ݔ7@T;w_cpՎZ#&x^A6Hg l;¦@dG1.ue8fpjaS PAΤ>ߐK ` zз/Z_15.qæx"w +iϰ"vku]0ju7m-退o4z=Ą.Α Cpx_%OeZ(G4Z>ꐺ7F`)/Ȥ_I>M.0>2pa߯C.`V2N!{]aOƐhvVr H9Bd|` i-r*a`I!.@R9YZzq^i"bx]v4 ;-\9 ysOk=nY0/'IEZThk@;5+<6JR29:I)EF x Tά#1%b1}i 4UdRW لs.xņB/U,d8iY!g?&:O"׺7R l4L??dcrU!o ^fB2*3 iRt/ړ]JVp3MS8WKqA GM!%(BpyL|Dt7edw%)A\Т|M,(ghFe6ANvjKFpҫ{K:s<丟] $N\e'.lC<P@W"fHH:kc1b4$DX/rhdx4>iapa6UGi&Wnxz;9꿭L ǹ87pYOb!Sf> ΢ :hSkg+prkU4aeX;c>Zݡ]Ls"7ەl0 W9%ӐSߐ9g0$| Qհ=KGgсYiRY +,B.d S/s:jfk9-OR HXiHOUIeH2cb7DZU=/"F˜[aR-g 1 ѧSoܢw*nT/^X?%YzR'70zAlgZt[Wvg%hsO5[]V'OGݽNslD% &jp=o=㷬Dբ'\br$nBso3a%&fdfw,KP\S~i0}[9./ӟ40~ ̙JYR4}qp|!1yc0&OOMHIPS_QN3YU|7:eШwͨRS6lDr~g7Xp )91ڝE>!8vRX/]jOmA"߻ʝ쯂okta,BS"^j3D@v\:O?<!h]0[Sِ;J]Yt|QF;J$e3 SXD&#tbTW"ֳx7t50cEk{H77}Ȫ۔xXM# AŜf"=hQm1{G[dQ4Dd {Ra_ĴFJ>޶/u EAEa@@!t&@SG9Mr8_:؃{hW= z~XPUԢDbll_MpY}t-7QʊHя Xᙜ)D+ -l1Stzeh(ʰBFɵRXt -aV٢>Thʩc<ф-s`X8Szt7?iU![%"etOlHj$9II%4% 8#ls cg) }Yq\ÛX<ac "W`[F{{CGOnX=>ӹؐ6n&*4z= f0n&dӁhmf ZO$l ^oJųw6r.`M8cr9_ eJ:Qgф)ݐԘtL6ŝQ(J @{*"F!d^ra?a9^"d/l?ܾYu nV:fY%H56hzmH؍BkLcv&{%Ay{j6ov eU4FiBnH08T叝WWzC!s+R/XB)Ev|ވXB{bJy:.ȦָÁǹyǁwiue);)P\/q!Bn5ɧ8%`kB.,%շE؏{fe+[V'&6l C6J(o a#|+THD֘jBu4vaGƛb4tmUz Y/󩡈Cr%j(`i##@/:+@N厞V' ~#Dd RoO$`Cpm=Xw*Lvl%Zl\s6MaS"pI֏BYYvR޻^(*sÜ@M?WÂʼt~^lpےtaZ %r)AdWmf+TZJeCGhY&%R$ E}ZAOlZBY0(=rڴLϫU22OռN5иv尡q*]{<b s+h[cf  G=6!7p!^/L(~l۹="BD-xoq,i=/pG淅ƝEohvx޴LjWd~e+_΅ WpomGY23 p-ʔ`Z.ے`+ʾ1$ә 6#FOM r q$`w%{7N$ #|ϯSAuBR6m]$4bϙZH 7(j:bi1dG2do=1=mzg1-ECNVU(&ܙ(t=wqSwmn.S(펽n۷L'm+[rrK&X#J%˭F^ci!室A]X&Ob P&UH6SЎfvWIhPF_>m JJ RRFVBJC\dJ޴\$29!h4N.~lTtj2B;w!8y3?2]OɁQtm'TI$sXv&sxjN]0=pk?fm X2ڨdPP丠7lOٜ_ux@F  \t:saOp [\{@=˛=r$.θp,Z-$;<ц\Uq] RRAL;wKbY8ehI d*T&q\Z@6PbT!YB&Q|ja'μPj2vã[}W/K&]}-[p]3Q'D~>-fMѷ|VL y>Bsj[ۗ/K@c yÃHT;͕ ;zLD}X mPE\ 7.0qݻޖcpDFB힖"XpϗCwy7^CX2cFN_mdW[ c[qtzS˰k|3"ó 7;`C  -e{첏sxJrQ`ӹ;vxS1eBČdGC1w=-yBXHwڐ[6lF.W4:)m|Tc,: 9۽6n.\,BdgM:V{eE4%@CʡԸݍP~)#RMcQ>&ZN6 Y<bWJnjQXڻ.sR]nhI] YgoZ6اׇEF п1=R0eScU-5BAYrnŸޝ9%MLaa/d^.Oliua8 ̹}{Bu@7S 8K4N6Zzw/CU֘\pht.ޒz{K/?7kZZVq vX'O~@ls.x36u^t4ތ4jV5Slp.)LO 4G K;jsD}'n zW7S”ks8.R;Խ/[)[ӻoq d0567{J֡jsm'4>v?;P02d񭃳R֎P͔{Ũ6#x7tM~tB:(AuT5@s#{7ܥ(;~khtjա}:_{[Ww NpCWwL">qee咗i}bֿN|%fjD+,7Y?bW 3˻}'H5+iqh]7ЉM=7ђ;6U"wz {DjVD!51+p5spfjn[xhe9zܚ]?J evCsj ׇbK.fɺ"'rXhڧ5gw*MHŸVLJZܻ3;'ɛn2{tmW췄uoal>a%jp-sVѶ,{,n9ikjfuavQeW?"3~u%eu}~Y汾4'7uiT8?䴴B^DnX@޻"^*d_#֖--3ڀ!͵o M|mٕIQˎt5}ঞzp>:DGe3R*o*n#Gw?5 O%I)Q:m#@c⷗w޼ ~H Hr|K] ;1D>nMc_:ܦ'TXaӋGM{_ybOFS R})eHt~uX%ϥ񱌫>+ FN폙,{4,\D4|р=". _vxfaELBWqHgjl5^hمjeJTHʚfe9'[+J^Z p97p򈞃\lx[ƁGprRKMiFGgq]ɛP)Ȋ0뺦ySRwG?5?:%FAgիNGƯ,*9^fuX.MM: I%83 ClCͮ86Afd7` m#06-s %\B|c"m{Ihv8:{|tH[vh >8vBu}ϔ o̸S*dypny_'>㹈)Qf0㱽OĒqgrݤ;h\2:fBlu-2>w;l_&mpѾKUk2ȿ3K#o-~RInjʕ6^40 ŐQZoZjN1˧)>)*h32(ﺋqʹeNT׎37ymT ӁVn}]/Z~rXgaC6Y,6GXgN&>=884Cݥښ:Ow߁MnG1N4k?oǟ<$[[$۲eem[%[{;Nف0 e]h^FiJˆB ab#YNĶ:w{眻{\ڭ, а $xqyo,bǝRG0kJ*j4!@XRnJlකBkWjյֈHFދ$Ε*TupxrqQ1kco˗ݼ:WxbS{-V-k0\fSg+Z]_JKf?HzRgm\5Yx%f?'#Ww~qMTmYWX3 X"EvdㄺC~p",hԺ\[OnѢ-/)2X[TUOPW1".U ,Z/Gvn_2Sv@Q3\n8UQ[5 gwY2{f:avU5Ͱ7Uh E Z= ѬWN]ɶd)a5Ե~-kUvPRnJ(rd"eS1ђ [=6V૨`]8r]yW_*qs4% Hy;#~)'ቁfz3vU"FJW1?R2OkG4z7l:68K~O(a%F^eU1Z =㜅,n{hccXdyeVght51%Y?*4GB][']: _ U;cc*{W^"O65Z[3n㫰I"cϹ„MPॸE~Nr֑T:9ǔ-M*YJN %JeϮK'=QѨܢr_}k+#NAkW.4-=OG|*V tF%R`l|,I L59j̧ qerki 7\A8}ban|amZ|ı0'Eqw e#Pw2[B&iMW@:>Kz˖K]CNwyzUlvcz{f4ܛPE򱚜YP TWn"EDMH5F?=cE xR-]MAl4X.o ʭWg}zܟ-T)xC}TgϷS}"UUAP~n=?o>ʫ0`lGϲ itCuңUT< VaW{<5"V]Wۓ6w6tuu]ȍjGZ31sY4Hb_w8ySuI qh;8F4K8kSUQܪVK-7آꔒ%*CC2^kWİi :o[5H&67 .ueHWym!92t<)8:NRWNOi.݆޲g?ëLO%[YEۦEK̤.ݠu54ܣ,=*iPf2b4j|1.FX#xW|sd)cpYIW/+ŕʹr{[Q;@Ii]OKu.ЛP(ŕμi'\R_ {~-wy>{~|_aqK1 $cs0NZVA+78B٢Mѻmy] ۃ|~SL?J.AS<}IG=8ժÒk5󭑈[1RjSC6UU(jB66JѱYʜ9Nk`3(\r1vTQb,6:sudGfxMvNe_j"Yas3ɡ^p3pDm8|iX"`#" u+sKs_[E(~9Hh[S5^maԘ`:cϠyӼh}#F džޘ7DTSU/qe974&:{9/l^+v SUs#[9EVWR?{{_vUۏUoSl ֮ f_fWڝ4ȭAiS)6TYyo?mwvv*͉m u!mLd 8Zk_8,ڪ]FzJ(_{?c>u}CokJ譨!E}ᤪ/ֿIbb&/OzW}uHn4V%v: ;:}A!C#GR3rn4v:?%h-Y}.X3 xx.Y1k4o6߰J2>e(=eP +umY[B+>Aim_)=1[wQ4vwE6DHa,ksY;XUM8`qănPe[;Rv 7T%IO('ھ#_ݜQ-ƠMg3_/B^׊,ć/K%ϯn/Fl2{eX\T bt1(w7WJ^"P_9UMv ɺD+[frRfylCe&Q L".p7T [w-^v3 Oq2Cc2mjP;bkVMtA7ݔlWz~ҕړWj>QcMтu¥kqW_ƺs'm!R]* Ɇ$2O#sצ^7VQ5Kze̯){Clr១j}'Vg>ӓ0d8VS}^l?U?K hW42wh2}h>[HD`_[׏[+[kߠ|! KwlB G5 r/l9n<{fN[.j'=>j/SU;ZU`w`C}ag+%̡[ꮃDf?% @bdd9DС+?6]3xٖȷCXd駖2RYBl+́KشX3!W:uoU4%n|߷ʆrQ ӊ'RCEgƺ3_|LO<=}IQNK3߽mp!?'P O(V$SYXу8>)v]!6Fe皚DM '+*ferGyx~o.տ(+5zc:{Y4ɔ1TVT m]K^Q1#W(˟P)ZׄUif))Pk -Y%!5hquJcM 5jOa(Sm5kLu]FKÎR+XjR; ]U|Jh|d/~Β hփAYO[g͜^AN5uZ5%6ޣ v6uRѠR)6X7}U^U4y2cvH;_6pTR4I{lI/1z VBP!Q%J^^X,~džewg/0;e? v{)>Tc_ ҡ!{E%h,sN鶩~|fx pMf>I=#CVuzi+W׬~i(3 eG;mrBB$ `=uwO ]Ddƻ * F& o @ o<$vQ @EdU}2↝)0n{'5Ҩ࿳v*56F|]O6iue,D|hlDO ep)19QsMdl(ċd <׶׹g.G]wR\=ۥr o_k4?ԺvscGtRdE{V9:{ +7@G@?ӓ*4w+׵kXOB^F1Yl`'2@r Mx ,V{ܠjpU]TZ0dkOKF-|.seV BL'8 b6v#]V*Ea;g6}i֑X!*'e$@8.sM>qᐟk{RQiSZ!}ap|'>cG]Μ.ֻ*\".qxlzz(˙o:k/t+/-XteAqeX"FcZEG8wWڣ sf&9>k3SG)wy3(zMǏ/|z|)ɬKĠwtQiЍKȧrWxЉ2>bk[I8st]9%jkazs3 f{iZijUq}ơXs5? 8w!WZNi^pD߄j_̙q^]eװN^G2I*;DɂuR#Dr^o- _B΂= s>w Ĕ o$F f˪G+ zG&|N-`Sweuޗlu-%(gCN.u$CCE5Ia),O![!)‘Zad\b3LXZ TTEЬ+az&E"^ID)$ei wCib\V$fsTIy%*ܫ2NpX]Ph5 JS}`]Dudg}Lmbf4y?dU+ve.f{)A7z<qd8O𜘮Kg:4ӌsa'0~׌Y/Cx߹{UA+~I#m:2sS(Uf3IDeBjhv56k@:s2緍c-~:bazC PbWTZTUh;Y6^Њg+cx7:?we2bduID0Sjn&or]x;"_m3=bP*zڈ°U:Z93i.OU2A ݡ5G,n_(3Dꁭ;Z螊3] M\.9.2F:y?^-ed$O!v9֛ a1&C ]a1ūqcԷk1T'RB .SX^Q_Fo\ӷ{zzN) }QMS.1V.X U"G*./#]PYvC+ЫJGRx85+a>:X6Q VYYYIP ÐI<3uыOmb%`B2 Pv]'QqW~ٳWhq|= EsN;)7*Vsfͪ99PKN~qMܬU"JٵAX7x[W:{Irgr v3hV԰ԦsiOeaIyⶲhjٰ BFmc9?[t}C77qBRa?l,띛l:'[nΡgK'64lhKߖ14 WD #W)jQrgړyt9{2 d>Χ?W=o[Gsnޖiݕ(=TPn2mD8J) 9HY[f̥ea*,2 (Z] 6eb?h2GF<ǡ?O7$݇VB<1Kp?E":j NZlFcd7 fiWPek r户]n"k}5*UXUHk8fb%*CvUQ \bq޲.ԠBmA.Te9[6GY쓢s'*HLm,waYl6yɺǶ2XX^懕3je{B 'ę[^Z#fIUHZ68Y1=ɵGZum\Ț5?k+ Ku64:%`zy~nvbA͜*]k$o2B@Ƭؾ!vZWЮ;&:;V8[pcI>Ն6+aBӱTcIBrQ~L`'-"S7%2ǣ?wA).wy{&UtԌx ^en_iOQ_⎄:^flku'WrS=!6-/3 "PgC}1|D qr6knK{E'TE%_nw5NJFG63U:P^̵nimQ,?74f{́K[*Mf9Hpފ7:'޶;5cA=]Jہ_-*Kѝ(E nA >zCOzI$eHO)9ʪ%WZ[&^' g M_gTє[嬪2H"pmu%pY8h].k+;ִTVx+`7YF-ڿCV1n- kę9'L1㢯L e,f8C؊Ciaf1Υ5ķ"Z ohMl1-|^Pܺ(e4t?w,*٫>)},2]$-'>_+^m dy%^jii Ds`4s}-*ᢏ^YףD?]^::f|AA@un.4f!/m94v *gjRodyd`d7v#|ķST:] ߁ȚNÚϿ!K翜M +7}R醫OYrI{ :=boA#aoC3IFDL07\qtlN`Z6Wo\ih:0({ {OŠEe: ygPjzw/_x>oCC9݄[$6$kT pl&_tΨbL$.μXvpY vefK9È4rt͔k~wK+,:zg"T5}p tWol䗁͙2}`j{ބYŞ@uaہAs)ZjWs4q}g:u`֖p.U_)]g̪6zd3WrӁowů,<Ln`ȷf$\m4IL-c7cS5'hC}exhgFK]j=xX;j8sY3ܽU l :|+QP>[65}eʕ $+>g3 \ѰWumcwT?W MMéj)jmJ *׈M}ߟ>)9MY"&ǩ1S{ fo77`d\C=d9ۖn I2Af]vIWkJ7)0#q$7mqɢ1:5ypzCDc ɠLg]k_¾eKcR>sn0IfI+zh@`y ZMֽ1^umUk7[_z1^x[p]#!ÑƷO ~v ]گY\ N7uHVQTtt 8ܙ}ZWnu84Gl C{Lkz OSAP.weN6sڭwJn&C/ݯD}GSHguUд,4MY«bd{n櫬ԭ3)쒮5'-Ik+ |CdņIފ'9uP#g0 Pɽ)oaXljhZ*[yrNd9kŔA[K*u|qml >Q~Ӫ G樍Ȓޞٕ+H"ZRaCEU^~$r~{'u;:Z9obw>(+㪼Kj˯n;n\ԦhvIac{9daASk?[mo0acrV/מ>`J EӜA^,Ve^?mؠ67ٺ%ENǼ[]P cvLc\b.0,.E.PA^\1"~N\q7u0v {X|) feFeL;{X RHǬ: N~}0+=l>|ʲS ^7a1D'3q1M~Oa euOawq/|}C?Ϻg>ź"s={9Fq !<'ωYc֋@>wB_|hQ},>q(% }:o@ڽcw|8@'hXzgH !=o)z4b+^(@a+pn>sksp<P(t]h.'A۩0]3v}D]ĦK2PKf;b$||:4ΣCm$y K兗 X^={qp of?4azhɁ{00JӰi?!6V83Exx!Wk翶 6=Cz/ Cyٌqȷ'?!![ic@<3l!1fD/\:שcl94*w>^zO tF6\_,|`{uKs߅;`%m#pa6Xlo`ގ'>Gvia7>|6^|6m}QvNχ)zB|0/\HǹZc+ߗU/1hAzy~>$[w)f +(#8.nW5]lp|qb5 !P'! Ƒq~a8y>Yl/ۻg F(??Y8s#˷27H UM)q+qb_.aClQF+'*Bό0|1|9xoDu=og=um]sN>]3(w8^: <*HwM}=ʃ-}X Mٚ+R]NvV^`y&bA=b;Xymr\\:X?%|X^)ꡂtΧ{Q`{R|y vw.0zB+p,[K,u[ߨ.&3\?跂N0z@c_A! Bxw~kL ۃ~q?$qasԫyT?ޥ,GvXv3SLS|9DD*$`Ē3̥8UF.g˃39?B J ݇t8t۟PWf ܟHBs'?h]MrXI]6&bu,%OK_ӯ<1z'LHYz?Q<<=|oyTEll.?wSc,=#ѽԟs#u^=^~|?>?/ӯ֩k yzT3%G<<>I76+~0 s>wƉu3[gn_9נqO,=½ |sh?<1P<|>;E>7&!1N"5SOQR)$ p8~~;ExPמOvT^f-/ɜw2a>ב-\D~ jeA)ү'0Cp*7OPy{AL}W}5|j}1_f?KX?Ttf%SJLdT\Bo*7B?eH9|<0>G53 e#bZ5!8l?"x0o'>A[Y')g?q;+W|͜ZV>ْ~W8^o&&菊?O">#O]O3y# ;f~Q<̰Șz.~]3]Cmg|Fą^+1?zMx//_ܚ)"E # k,9xY,›|^aQcق|C|/ ~&ȳL㴏s7+hw%8aBtir Ȍ?>¡߇~a\ֲG,]8c`%S4+眒O3X!TF?_xpԄx@9@\IDa>wȳ7Gq qs#ø8-?m,֧to|bD?gNg~ oϣvѷ%!8Hb/"|xsc&$"tpD鯡.F#|J@ySe3@qva)/ПavuAI2]_ SD޲?F [9 o#Q>#hw#Lq]ďuN~'86czy!NAL2T!?;E7@Ȼ'b LOpB Lo6^0}i!N{;r ~K!%'#4OoB-c|-?O~1XƉk1;.D2rh"M_Z-o7 eG<[ U-/Y>i;rF(Og3Ͽf{0Yz C}p =y} wc[.5лNh=qs%xyx%Q߶gyH~L<<>/5'w8>Wc,k?OcXԢbBQos=ϟRwQL0ɟ-eʋ;c* #8d<<9zDWKŌP,+o97u D?W][`gf?' Xoy/T"'+G̷ ?X!ssE;e E+Yl,d7S'4HV'i>#j˦9"`a~;s? ~O`B:Af=B]5dLk ~?Ec"#x+eϨFfw@y<n@{;ߌdw`A f .WKp gcٷ:n~XVǃW _¾dX7GY~FgIO/;x擼]y(:^¼su%]5F P%{ p=3~я ʽʗ37a^ pgü& Jvwa|ϰKo~ĖH1av?*Bwbݠ6ZiȫgcA9X_<<Cy}B t_(s[\TUOد XHxA?:^Dr?oxW BϺS ?W5h߃59=0D?0d_˰Oo)L c+`D!?6ϰ_(Gm?H@Npq";ϓ8G`?}GVMmڞ%6K$ OJa“ҿ_KAu8 >e|/L)jp/xU}+c .U}Ɨ9RMl!m$O;]'(9g Es*/o+R/؋,enհ._Zy.pF#4{6hV#D:+Kou7k xTs >_ = v`(HtLj.[L_~S>"{ #yd9`>]ԫ`x_|]3qG2|~^?MC퐞}. D.G`۹hu~Fw#g %S %;I_zcuSUmkuW3;N"!Tݢ5mJM)UORK҆o|-;C-mv]M 7!`k);!VGOMnvlh n5:5նiX8 J-P,kW)|wZ`?CD?e۱Kv)HC=eGSs8%8@Src]phf<Z-^T^HCW<ޣ^i'8Evvt@مyP:n;'&.:`;C۩eGo$wu@)Ѐ/U-;&<,a;B />F=%By[BYT(^uo ZHZ7?AT$BirL#4_A}Dp=IHRB|8~߆i=1F5^%q; HdO.wk2}*Cx Rp;6dvx eϣEԿoqv- P--"f 0go]>&BѠ=*}{H:Nbɲlɽlc\6$CH8$8! AB5$wI2?Ito}333eIYxOfQKA(֫8) %ҟކsꭲ@M16Md>x~8/V@ N/XC7VP[Ŀ#.YDzS2׵HZtE[`wn:yϟ9Y-`([CZnw-OE3oH~$jcp.(;@y[;ѳOg[ RqpcX)~4al7M>Od=ծN5giN~%bT)M!м7MD=[h,.jW!O|!HCoHX <}u_ߜAyPYb"ž͢xr]jgxu}]p@(aؠ'/cfՉ61 nlټ&MbV`cB7QÆ_ ZUWSKݡv+tz6jNkK-uXmQp\WY;5n;,/V>yH NMgP ␒/i7S;!Q3x]Z5[7̹kkXQfʥTPIp3A0Is&.JJh)Xr #WM+PkH7+I;|CG\y|}%A喑4{J] 4GJZCҜ4\\qD(mUTCHDR ]!9ɣ4oە4{auCeX64~ JCwi"nBk-\GGi]$J 3lZen#+QVCQ\;.>*!XU'O[6v=ɳ.L3 Q) k0G0nsrt~xW*8M@ -M&|{vctަ34KoC WY?Y'WُDW{aAϝ I5aD}ӕT{\ɀ$7Z  ũe`9!&&TKuGM859uTS[m}.P;r~^jKxk| ܊^~匔ѧN)Jsyy`>gi9m;z^sTxWL6kaşvNLܯKPa{H[ۺ#{KH-ES45&x++JjoL׫\z27}Ŝo1; ]t-\^5#Iٙ nb ͇ 1?}HSD{Rh?,$.*KG 5Aiw"p|rTc`US|oT+饃?"ECkh_uȷ/m[./E?'6s1|׹k1|~v}Q -$U'􅝟\UUSi--/TzL̝b۝KIX0o.U|Tg]rWhc_ߚ%Ӽcۓyk,I&THɩ7X>4>XN,j2zLB]Qf#RNഋ%qh .a8䌴!{:ϒQ #j`2xyG:@K) < ;6 vELpn]79h Nץ; pa8u4 1p0x!]zbݺu`ﵨ;#Eղ$SP%X*R$W38{a xtT%&c7q٫2/E8O9|! :`υ?qH|,rq4X(M+IzZ"kWݺ8m^&gO&I::Wn+(ʳv[ yrY;lžg_p.F`% LzD"[6Œň-*{\oMػIt'P@SE3/XT<,7ZӅPY'rX{f^gBϧsK9F!.^+TgI{ыҷlYRp=‰VN#࿷4IW5SjA;cr487ӖiڞiݵN'5mZM[+J5vQe)qA۬ 3wmmڂ-Z͛7 6kkؼxgt|߮6o nU[sM(tYE*UB_:6ZFxKP *ɍu5sQ~a͍|^pg{yޣ<0.i97' _^EL郿-~G?PzļO?Ԍo3~>7U.Z+.RT@z!G>.))7ϗ'E8р[{8{h9\ ƺʁo 0ؽLZc߾v̧ƒ9!#09N]H⸹A0!>w)FZio`3P? iF(fSH\'EOl>+O(l< (sşݰ< :;TYU+"L}6j̙{+ar8 0q&9q+8+s;W3Jy|'ƧOܻ9!.>o/̛}yS[~l~;1d2/^~ !܇k8kR9Ǒ#k] iz=n5gm6LMX qQMJ7e'EZ9c`}>pؽ=Ťܢz]aͭ)d +'xHH6|׶۳sCŻ3:֎.x}Ӯ_>mġnp{&s/dX|~E~IkaPGHlŢ]\yRdmIU JS]j-k?#gle2kn/>858(P5ix&_X!ijLfљ%̹`@h4jq7!88+plMr-HvN?/OϹ(uR3wtȇò-eoEi|d˗L\A?mgc_zEXd+c* |s@X@ G@ՠl@*-rsՌO7Nd|C<֣GVSp,` z\&|-Heٵ3<~>nڞj$Rfۦ( WC>9R7ׯx~0 uy]GQ(橫l̵wkl{j(5ݸܱHltM Sqf#Uڐ"FMFbdUpm$ F._YAS [,KpWvW@E"Z$1=I k o6 *z]N>T!q$j[0l|nR!7 ZD>4D]Uf1ޭP[G4 bΒX)  *VYU59R}8A"-y}[A 1MP(`%-~GTpx][:/^y1>nX*ǔ@d~N5#jŘ#1ZSvUѽQ YڨU1GUO 3%{};uw(9}f hH<T?"-A@d +){t/L= ApWղYR;;BAa9PW /Lεnó˝i^˜P[d7:Q=!=KB4<~:u(VDGHC H]Y$I6\  @I!8Iڬ" ^HWl+ D-NTh$5\[L9aHKJ2Xȋ*js8ee` L>(j24tڍH\285g~P*+E> έFC q!#u 0O# JA఺hYgr`}i4[ajmaC֑x'f0RGQ.O]H :UX; 0aچXET}>!xы;$Qy$Kx`kB{~epK)Fnz%d^,89f3oM_هn0 fHʼ>%PO7%䗕5xt #YƸr^ݔC"I!>g>ʫ 9{+Q\y{Iv[x"PH"ނ$Z =74*Z08/2&WDW"6LHG֐OuHW>mQgWh]QpSg#n3zߡJ#p^]kQ6}fz(#&?]vO|*"YJ"NUpWMf+m"r0` ո;R@k/y/ ;{`EK{n9:tlcn¶_^s PZawV2 >t#D~ l\7šV%?Ves>#P%U~uR@pL0hŐOf v!]/U&mm N#ZǢ4ٖ&(Dms@1q$*E"]awU6ژfcOP @0SOv]ҝp\.W~dfyOc2i_["(̑E#hKN`V2vA'kMdTVSsy\5 wEGvEP"D,*JLGt?#v(z m9;=2ypEr~2}i)<EzuImƐΠ2x#M]8>nnm8B_RI<$Y 4mHFT[?R\Rd,%}fY g# B553>Y"fvyM:,CD=ֻ(߈?S<$ֿ;,l,{L}D8_{skRO> elfq/^'7ձd79`w-|i9O QI'7!zd 'OsH o՜_sG3(7sNoD.pq"(mlT48+d֭^{U u|W[}jp#wEϏsQyE5٧T* 'f+s2HO*}6wQѣX#uӊz+)撂aš2a%8P%6ݎ+@ٔDifikޥQ (ȣw\<7^'`ۗserݦ6؃rQī|>K9[y؏@^[xKdU@&GhCp-b>p< 70dN^\CJ72W JRlnSXռ;!Wb&:TN;6lԥ%͍-᠏ O@#ǝ*05WgFmk"Bw(\XnZ׮pn_Y˵qyVO=L[vү* P?f}80~O&סiSp D'O4b+,: C.ۼQMՆѯ,N^?M7,{fm`p󍋮=Y;/Yvm]D]X߶Kԗ/ZUC- Ɏ¾;cϝB֮[:u^+'*A9sJ?gk:}ۙm>C(ߩ?\d^xbtv*5X Uݹa\wr~^41 ó{ó߃CC|h_'~0u kNV]"9 j~\yYz):`ׄԫ 0Gwh]wKyG@^P9F\x7iꩮ ukGӞikmfjUmnomX )xMq$+{D^xe>߿"yx(=ڜ 3&9(Gqsv~Ϳ䟃oIz7JRo3[6w$?^o#?Ec|-}_`ۅ8QyT%כ!,߈{*KQJI?oOQ?>m6s]_m<(J(tZ3QoRJ~=/%25{1ŧ)t겹t\=nnAJ='aq>uo5\帿GrA? ~x!{G 2@چ"zIs~{Vö)r[y=l:TfAŕzlBS>Rnq\j.æ|l\=l>.G}XRcIRnYPc?aΐ]%Ej6?A-ւ_ӑuh+քow]@#5U32R;k^m)Krg 7Au"ٶJ9R1",M=VK-XTRIitT{jl[g,Afs7vEwִ?e>--RL2Qy;߹~h`[U2B>ل'i_.>-K|隦Ϥ0g8$6 >*+Dcp 4Rq5ZGyvCx~yPi 2]#5s^Y5yhh9_C`/43{z"+Dn# bȪf_w$s3c `[ ,pLigUSVnp%gs.9@d/e*t7>S~:F$>Gm6o_E~:Lt1PY3Hn449gY'O Ȏ}7E,UL]H(dO#3xNL˙F[;Wu^XX$2K'jW=IJ')V@Uov}F:X^>uT )fPo3Z`OŜ1<|xo 8|ů8AmR/%}%Y|)2 c/Byz##z*{KTܿXld ]?߾Cst5 -2F.}{]-SVh'u{Tv;HT0nўi|>HIH!q^*a2EcT"W2L3p,fynD UK@=ˌdS#t&TᝇP6YȆ*)-*<uvl~5:֟CGbBX V,_sػd - q9rtZ87ns*-<<.g'rd k/FHVf5tAxǒ?bqЪcG#_Y(F ]6lS d}M6T:䄗Y%s5%֗3lRUA $cz5!5DpթX"m}#0ў ղ-[ּp2T#,$Épi+.dvc52ta XY}p|axg70g:I 60Ւ Opb >-\zkTȣ`r)NCDq2hRtxإr/̯ %;Z ^WBz_^' 7GiSA? J$dd ^k}6CЭCK+[9>ՄY3gRO.3Ƥ!Bv^pv/-{dsךTÚdEkƟ⚆?.u)'#ͫ>^U!y=qCw{G6Kh|։۞lR!⫋M QV`d`T 9|2 e2eBy3!+ 6#!2ld~zb4h/{>c/<O>!@#i ӠqODu6^Wp]j.o 7K~ho1`g{IWbYe,m߂ֹnaXvAxėu|f!^d/xgy)^76|c +gop_XTl9 yuϯǖ1f|[9t] Wɫ*FVg~_PF"{Tw3rI%! <翎|I:@~d&; ,-1|6(#CClkY'xuI=7^kl@2 heN šATj rQ-_3'Ew~f0?DX~͌c)'|C3 ksY\~;PE"0UAxN h"M r@QQٓ &>e>733?@=!ݍO͋ Lmgqpۦ'oZuY\|*|!ne1BG[P;7v ET @}DM'm^:Q 0xU 6Pn[el lqX&ٱxD'cq%-9̒>ظ'gh2wV)Rte ǏJƏd9#k")[OdV=r]1ö 13cfh= )smz0k@O,5C`;"N#쁜y8-`wp_*|b8hl &!]%rBDQB axeA{7"z |wڵ?e?B'ʀ"|lQ3w(D Ɛ`ސ3c/}nﹸ  !ԇfO>|T2C A"oTY֪TJ= %Ssx Q/Oaao11t%ىnQ[86.'"k<B*fU $=HzG>YwI;389de-bz)>݈@L?f6BU"9o"s[# $xN~WKΗU)w j݁Vk Nh~3,9ϰnobNVp MK8#Ux$,?ߗe嘹g$e%?ۡ.~A_e D@|)  qAK9)?IܳT=~ů_z{982v1AIP.eݥkNN5gCQN Qc_WpPq./<=' _.yI wOOruKXkܵZL昹B܇0&/>hXېhɁUmOת0݋.]]m ZYsz ]i ̜͙Cgi8suY3 ٗ?7 0rӠ .pG*̪xض]wHV_w2_-=Ūy9Qa\0y8v[p!sg:{ͻ0w_>x=x#AVxd~3-@| QvNΡ~tLBӿX4e(1,O&w;HmY nE>{kpRrJ_μ|Er0k%}&ezrtv>=pzkv-I[aJ>/rnRq8NOp  ≯6Vk` ̗kL[Pʜ9}%@9ˍbbߔ!Re^0'MVy"oV}7t*4Mfs{,✪"3-K.i6y?<Ϸ kF*=p{叔nݕ/!~'p 8&uTry0Գ5k{|V-6[ƶdYސѨ$%1Y~]Ұuy5Tx<lXe{up>X{IΝ&5]o&lՅIcVO 1'/3&)OwtRBвFg"$w#JaBm///ςSj ۘ$@^)|Y/ȫuyR~_Nˋy(h2Y3N6zTB9@$UWЩ:x~pnmglD)Xap2 h0&4UCp:/@R>c*r N/)J9B+z 7d(F$JE: C0N rChm]="Ĭ昺qv/j`ĩ'6_>!A~ ,Ƌ&-]KBkpZ4QS*rsч a>h䪘$tOi%Hi$VG}_yv uq|A/^ǎ23D!&@;^uWCm !y`l LrK2 }5qrKc/=RRHs6т]s+ז8H\V D?wz5g'$d%:'WX"i nݐ|+B p(%j-c5T=҄`nɌ. &&V;h4)0x2 .\oi=soPZBBbhJʋQ F>94I3<[UĻɴG[D9$-4[7+JhTJ`4[`G:]PڧQCЩM4mjUsB2_F pͳkU`ǖA[>E%ݴH"y&f eZk TӜ [IĞMlsm Z4 Mj=3U`M̻x#]@;aQ)1] IeA!U07?٫qM@#M< R"½Ԁ"㝯?@v+m8PJ5Ր+ -@/ZNiK>lig퀔?̙Ϡ6& x@'Ac0'X P4"YzoqR6y,xqR/{qGQ0,AHMqO \;sn ēV:2Ls[}-*WiڠFSp @1lH܃GO(TXY|JPe{\.YIn*¬4 D%G4MGuޡmX?6fFBQyc!ʬ3̳9H03 ڥK5vt247єP72nq) 0Xj^yn=Fe";9:N+"aOI **#Za&|^ +_z .6 1׆SFm=9H'њJH"o **hQ|nHvZb>Y]ny԰Q2O"T)CJk:Y5f6XWs?X_$Vj|-0x#cE_nq%ʭ喼*T#Zc:/L#붍MN Nxr-9QJB:xE pn$`X\Ԅ<*Fր yRD{R(A|e(FԨ]IUܴ^:s+j!K/gEt{mϞ'Y^X=K'۽@ThNRd-hۭIxFCIH0e=$x9S`2#UܼeP @֬Yˏݨ?BcQzK`^Aܙ uSIrf%Y)#S&2s/f9u:@,LfQ_Y=sΫ C3ѣ C3|'ZZ/Qf$؇&@4 Ϭ s5?Ԫv jɹ,FU@LB=zM@0s0OAZt%}_r+gŁ8\ k~W+g VO%|*EZOZ&HsگLJ_KQ:{cf41m!(QUB pLhᵂ|3ȍ#'XX79EKnA02 ~G*.ₑqMś\ِ˃՜q}'eA|x.w{4[DqyG1\:k#j@5/gsl◥_̡w;*J~lx=0`WwoaJuAx*ni"zwvɯ(7x;// cTr.|/SJxD' EJ>KXqvfgash'D0̗#KHc3 x9ph='%_}B.iWwTX) e2sEOK4I&N6O( :FJ7Nŧ&^pHQmRL1]vf[iGSsܧ'-<˒*$z\ /o "OVC?oɞg!Ӽ[IdS%Y24i3ws?Z*XD8daIr q+C2Pٴ? dp@q/~E~^{gsۖ<ݱU:o؊7L0P6pdgrѱTvy%AD ]YHt-Wwu)jTV8"ƤxjƯ(KCϰYn]P"D(VLR0̤cic1H0@@q8zOFi>Z388M`xf9NnCPD%VNy=krьGd')^v +RLf7/_(%ʓ z%B`3UXA90_}˖URovЧ]|ء[O|x0 LlmF0ncEǂgԅ5|C68~BRfwz(( ԯءٴ!{pԋS;u]8OUY{\ LT '̃x$Te[lILw? ^,yTxIzD Sv51tJgV[7wy!E5L.չ敉4`܇at^< [_c]xK6g{B"_2zLRkk'}>MPHvg'ꏄ=ykfp1l4 XO(xQ|*L߭aDKcRGGLvIN$2nCx}E졻!+dݱC5A|o<~rlͦL=׭䛱$E ׉/g0Ww^ ܞjf;t^-﬷ѹ5[әa:r7Y%Iu $.N~%^Xs ] wu&_۳4טfI~k)n:OzmhTppIVBA;)MDjsBJRDLHO[Sf±ٵ\L$eA R4n9wGU'? ߏxsf3i[{ʡE{L,Ѭj }ɢ)qGV8Jn9nf@? O<7DNgB,c YgrZE˵Kip8uۦ+1H+i$ȰqOS\bD$*IJ.tqs1sŐ7u/_ӄ9oAE/m"kXMݧ'_@!5HA#:WV ۨMT}39N=e\\rUחWwBY %L55#2{-_3X*jy|Bu &CccqV C[=z]N.'2o$bYys./.JT;=K'܏k1FR$Ársw89xRC@vJ _W׺J:ܗ֮wxS]~ C{.0,;H',9E ?"7N^<*T-C/yz!  d)5b,r[AM_/0S ջ0R՚'R v[k,^q/ ܍hF5 ᆅX|Nfkbj"HL+PZQ7κ|nvIE\PJ&ʱAdgM2!Ӷy~O< /vͺ=AAP8pV`"'2-]D5O&{+ϝ+ Y<(JBV7f?&rm>5po^Ll1șV._ {#7>X[l~q }ҋmv~TE}0\)t7؍߸`7CMR􏣫_]1j0 16EU/.d*+w?źr#g#s UP>pg1U6fKq'W|?hg2Q 8փnMusC{|pv%>r ɸ7JiyE&$Ԯjk9 1օ6,wGwbƎ(Grh"U0,~3Gl_asZ孌 G]ЉZ0wz\;۵:YCjX@nXV^[H%u_!˜ .|{s < {aqw wBi!.URPѝ_ Wo} N%B btsm8xin-]2I]V@1^Ur?~?E.5HQ4]L𝔣R,dj~mx mf~"4{b5mC31J[kmHn?PO""I5҈IaŦclcq$w;mqc=a3fxu@g(oSK@"B2h<etc7x܀bB-=߲Ч.xXh l`6U^s!.\ƖըG%K<y bBwqd7?(6JS -A y0f4_Dܩھ0 Ɓ(eC?+җו|$=!Y-Fwphlf`<ӯ!oJфZ}ObSJ^3|m,|+;af{n|Ľ'99h<\uڼc'Rk郱ִe[v&} XS4Ws;q?"Y[gJ nP6;_R~Eb菓v.Q{)a[-5jyitb<bf9?ϖ.nhSX  NyP3=*%s5w˿#8Ư_7zcq,5:FډxCΤU?vpN?H'H'\I*!#ݹ2УD~u83Qg,<ʂw$B}+O׭ 缵]ӳ_"d wK]OwO3z>h[*lc@`HXnz4ٶ)@g;uki97ȝY#6' ٶkTVnWJ@xe/HZ>5] &Λ*ȷ?^11z1ZQW6 }MmsvTŚq ~e8K˚l dr6 %w.^@o}wxNi^iŻ픯3*CaStn ͼEmWZʂW˞Xo.'݄M^ [W 9cFSekTlz:?œGv][Â}6aTWvzKZxXQGN4 ѽo`>N wi@[<Ɓr3OZL1j-ㅒ(k OW3iPǕٕ6u,?M@DUcwس۪|ő I8,lw"0[v)6 7Tf7b/¢.?y-Ɠ#_vW>o;!*<3Ē!; aJ4Pnf~f&IЫGAуD. \Z@M0 n876IJ(TMi>]%)"Is#3A1ݒ$PawX}aȹ #*|%c#+Ԙ0UHЮ 9 e%"X|F̓$g=Sc]LxΒ*Lh6Cv{<+? $`3 '?&s~Yps~I//3D{\55JUf_;) 8@^l+mJe⬍4oxu^@;ﴦ9ӆh* .T̓'ϻkJ0acj!&zN"zW]ǀ^!#\AH,s9pVfEޢ/ BV5UOEm*n>GN|t]k¾)g ,pRo_o#8Qr'&/IpX_缼IdzrW'kL0z_s8An xR&<]iEv|sѠ}hFNTR i_wj#E.s?YQA,esq)7h@u7_n#fĬu u֢c j0e8gluǼASon0?7iS͜?:LvL/JEFԱSjʚIȞ峝物\S{Z׎d|L.d,|3!A!GsLj>f8 i)wqx-s1.%Mi)U\G[ĺEJџPZ>V9dvI7XR ,0nI GE?Y\5fRBai˫/%mbL_ǻoq#?0L?E1M2xQ 50wUPsVaV/7~gFb.Yt@L_zuX5¡RA sq cg//雿SW`m8Q8uC8(&;$(2;T$J㘄ދXXtaR\Zp\wƑM=3oc)I4ac"pS2yrs4zxj VcHGHlL{~0C2xr'ԼhLqC4?Φ3l*2"]^ҷbVlX@NxMFq"7LI9DEKo{y)!.<5L|͑pWǧ8)]äKIDOL4甖)̇ZJ7(ѫV7ؘ3D:B-3qoГH#5 |*;~ >Uf gR" J=Y QrJ Ιs nE[{6G(}l6?z+Eu~:PuHLS$^>vQU:T f7ie힧 /}s*yrZTy N6{CD)AtƵURv+ ibmMA0b bS?&clbI$bcU:28f>b#rqGnk&@R kZ_br'Vyϥl j %\ȴK ̅͒GsѱuGNçmpޜ"~1X×ڰw$:s(Ć!*4$^TB-ԫ**JQ 1YF"4֞j,$]RhvG[aKS^.bW\ א_"Sjw9:vWh'P-"(Z;mz0 ' 6#b &($r )Hsf8TYRq"W]Eb6]漪HrIj`œox=4Ywb܈ 1eB8,; vF/Ź!6 +tdȳd^5>T;Lʋqڡ57Yڽ΂Ww;'l@E 3FAD]P\^~۞uɎ9{34ytp{/ݮW-|Q6Vۚtz j_ & =4Ӑ&\,痓Hn_zz}ܽo֢@Z/xOo}&w ѐ+FBsY70n^p@W qcS%럁x#:a[ 61žŌ5Pү%"WTԛg9w^K*"N ߋWa)2}aNkNjL sOՊ1#xXfZzm;n3W?>ؘd%ۂn*V1uW>ޘ}rqS <6~fqWJ|;p PUƮx44#9/ /UF WR/;7\*F˾~"XiVR2^E]XxT=hav>}i]Pdm3wegR+ ~W{h o= nkve%دON %hePoʦ;.E/E0=Ǘ ;vN 5_߮C/u ªhgco%Dtnz\E-oim:3zαsxȟ5/Tį;{ӛx>/!mBm%`@"//<ӿʁ~PDaI^,e7FTLd[hxElՍ Xf̖nLYū+%HdyMW"]+S(H/Qi68v(ޠA4F<*+wc r,W=ό}t쓗v& nkD#nyg-rڬ֙E6`^9` ,kbQ]gYֶ;zh>#`\.sAJ/F[QE>o1GSdBO37 ,^ʯ4s0s2KN|& ܵJ8?iXC imM'gK ;T|l6]:?TXo31iO]eFHmK3rZk 35%4!Gd`,Y@PEe&pG(ux嗀KD}ݍs F ŌRK~hu% -(f :סk ňb%Mp:-^iGq¦e MCP[AތO7|780 {نߺy*e*f3;ZB:g[`v9|yp/b[{n6w <-;<3Rs`˳Nmj>ƖcZ%'-mwwtҩFobV  ![B-!  ?iݺʜ!($&o4w-d@ $$Arg)0;pB; |Zte:hS KDlbRԽ/g;[$q=%EGehR/n6SS2q|/rFyxr`<IX]푉ۨ!/& eRg>ɂoX 3z84I( }&Sj(jQo+?s|52 YG KLolm ضbq+_9jC \߷'h-B[K0 FV/@stX}}ߩ/xb%2$ ,-5ǂ5G|"Y5HZfYOv0=UMΎY[)pd!ّ"gLɀ)/vCt:m|-YJ^QSܓS5L1 .<4n&m'Z F݃?=f+(osPonnñXX9{8W{Wm!^m=cGǮyRp<;)_K#1$UOKݢls&g_Cy%_yPɩN GXN~!)/ H|!9O sHW窽<)(&hv+&^xvEy76ƫUˌ[_yxEiij^Me'8-NL(yy1 H:  l%;;j[20yw:mNYDH}7 K^Aަ9&l\=v߰[ |r+ i U<=33%twcdJ7]Xz:6t1l^4[`n~P޾ǻX24%.(W)&&;lA z"x8j&iEdW%=ݥ&m+V#h6.<;˳J>Jg~MH54\5b`}@T\En:3LNJ,({Zx}oq(!97ǰ4̵1=ifP1eL/@U)JZJrOC"%Lioo@&6RA&ː[/Ŋv N ~^cZ]q19 "pgv1Lң}1^@`ՂvΑ=35>C}1RkTm.ɦ(WC܅o$SճZ4Od'8haoF$/F>C1\!ȋT|JM V,J7̀\4$o(K !_~Ok+|BRE~~s| &e{{]gKfѽ)"s'7V{pO %W;8eLa.Vx5%)ȊĂG#6r1&x|^* 4Kaz:i@}. `Dex403JX)@{Fu8p).0ý #I=Mғɠ"pBv9P|<6KKv/v$F[#0q2١g/0N6vYCX\`<*grMoo4>Mp\eN\ uɭ]Śڬ q5X/tRN9O(aW]XWqR5C|zw|ȗlнgrxHO9$j9!~yX2fnŔ}nH~LQh`}SIJ|19Ip3IV kzJK{)z-LFAk٠_א{B>%9Ftf8k\qSv֐+kax:Q5=e5"]ʱ@E^MM9W%W"br0xip\Jݠ֏ o|W'Ʀ߼a L#|i/d0ؓ*˄Ҟ*TB*y uvԎ_a#jo}igLf`Hh!oF0=F݊t`+ ܽp\u]‰{YJ /̪[*r`+cv;x*Һ?Qt|bo4b,򠾲{6ͷ1闙GIɳ@:W`7Oh~5b35'񉢔M]ISGGuYeiwfJ$oEVn{o-{>#I =um'é:4BLGT lKT +y)ZdeZ9zPu@],)v\`p75O.y&hJVP3믗j>Q=~8#(C˱Fq>!>xDvEzEIDv&Y7yJx\B7i q7׈,1f1#1HK:-\]n'tIqA@ Og$ $W!_ȥz P )-Wիe_7c':QnKP:r@aQYݫ/`)xC䪯t>ǫ鹞?W|ISDLovs,@~e Ú3ձ x0̋c){ î ~8?"F 3[JHq9qzv_*!qp3N0G+6 nasV=\1H\o]-g=嗼X4O2d-\8ƛ5r~"Ze R r GݾA/Hׂ lql3Fwf\|hy";ݔWx=́g˝P$%Ws"58j̉fGv_jOd>gJFTPNǷFb\1mqMy[>į5!vk f۞euvtYl(n#.$2s/7ZHƒhKrŎJ{\%?FV\|i#W.y{3_3KX:09$"m(I&Zq}Cm@'h!VЇ@.jm|ҁ ( .pNp;@;^՘ΰnSaYhWwY.(VHN_X.(?K0pܞx_e㭚" #ZꩉF+ @B)8BfgmϵqX3o%qm%7lxymx)ye0ߏB2>7?Ƴ0G<h:e5{7T;l;)'1Dd)Q;W R$ɿDz>Lp螷/_Y]zͼ'4gVoՋ>ʻ6.qHZ yL@$Qԣb$։SnMe_DJxX"=3VA?xgFr~cԍ^ixv)B66nʼn|dH!"mӵq+dI}.Xax݀7e;G/U"5P"ޫBٸxPg*XgIBXk4)/^wk8$ӽ7]( 0N7wbm;X_uv6s책;cD}m{֌JH4Kւm|g/w{O >`{ZUENpi7]%㶰xއ9XFuV[8 @CÀ#Ӌءس^͇L 1<#hBwOwKS2.}eE |Z{z>vC~Фy-rJ|+}N5"=8X[7&Lzlr> La$8;M9p2.Dzi,Ry@hTiFdџts+cDd>Jd4q7V8 ^ y(q2a3wJc"H`2yl?WTd9}q~\K}{,v .vfnK|bnn<}ȸBdk\fk>>|:D5f18qKoq*/9R]&h'Ŧr =q"(^7!yܼE۸mE{ y}͑.bP9}c'*>!Q/ a)$:AO $]1a=l0pd(em[xG1$a$U=P~o/7 ~kNxmI%O휆l(Q,X$*xIdQM ]' *쬵9L/j7Gcluz Ǧ~KHl ;JB+ͅ5{QX}*a gM6V#1.nc2)w:>8qVtmT;x+g=b=5KYk8Ԟ1J0_iUAVwL'_<&lGf_[ hcVճ߈{D9gh,iVjW95|HM{gzD. ~Xqj*dvXTҥkY#3sXX+myz<=\:'rpss $"4MDM,ĺ7z(DM+6c|k:>vLՇHrk:wg{d79&9aȔ{Nz5czMWOޚ?*I+%2oN&vkϴXxpܫhuk^Sڼ¸/jH-7 _e,ˊp9Fn87d(e5tBjf 咷及Z2Pټ?ZCT"wj<':r+z%xk: G6G!H77J:~YQ|{n4I7m$思V;;(@zzD[r<-Q篏cih2t5%hq-R(YGLNVrcyztYբk~7&s@a)򥢓Oί8qQ Ð#u [(USvsQGk-Z~@`ZJ%gg$P0걓rQi хhV;f]"Sͅ>jOhyKfZ֙fxb)cAi '̙[:߫yw qg F#pawP=y -*f=[F[&h n| gSa`·j[ ZppE~1lQo6\ kj-7ѩ7{ hvg?uu D  VH*Г6^p7GڇXx潅/0d ,O+>!I\KZ@O"_JOmz]:8'i̡w gq=.+svl=GdZzX/FL-: r{h ޿Ѷ{ܮAf;$t8-mc\Lš. ap%$_ɰ 6&rmЁ\Fj$ -4q:x[KyM"vYk]`yv6NA a8GF된M#Ys:Ҟ\Joϸ,qW(ۀ(: $~w}.Ie}LT}dJ|_ wkϲ>` dҲnz 0ѱ<%Ξ5V~H ! 7 cKOb;wcu$xCbZSCL(%15U}qHIy6ƍ*dc fēP_&!ťpq0ٯ ҫm`Ϧo%q&*Zd'R{9ebϽ%亩HzO> m \xDҒGJ8F:;g+y*FrߛsAdrx`K^/BNSo:_[Q7 66\ d_EUI@w3:hƧH"wȯ/}%!7Hw;,d !vn -l0~жߏ-» sîm[8جN\@(EF>[ Ǩ٫gq&1CN`6=0I+vdz^ Xv)qMi|$Kb Ǯ+Ng77":nƀ[rї: J#+u H&EC7=>՟&grd* 9tz91nE9tgO"hkŝ3!Gxe'GM>ڽ4ր$qnl oG+VFX٬`8/r30m Ԭ81~oPWo3{zGVuUuWuWWWuuuι:LyvwfljJ" @!AX6 ۤg 6`aLxclUffW¿GfV{N{=b1D{A07BťBd1ĭTAH%lq,;]f.L\ÅRl$$taͯ)*V5}F/m#}ԝn˴] v'QJ,}:(ۓŊ@ _,X^8-]wvvb\Ot3VZ|99{--Q½M]xKKVq< 9$uIR}SX@I*ގ$B _,51ہicZUh|Bι6'hMhTIƸ֎['%bG^Bb\j}c'Zx9mo=e&+Tb ]y%kWCovk\6D͜9@L: \QM#8{x[ dtc h婦'7u|4[kf'arIAis-Z\t,OVd`%(R e>41:= = อs.2 8W \s'p̰ι|I_-b& !բFַɽH?Uƈh|B-Ug*ɐ}Qt=ɱrJ<1$ hn}o'5hLz+?܎4-YtQGQD"7=+yX, _KLSvr^g#}lp,Epotxo;u 6c4qAUe(?^+g~UYZtd}}eUX-hlF0(xrBf`hBM?^d>6? obz,kyQ/M55g@Ew:y`&6X[޾ᨒzwUSipuKa3Bpв Jg"ƥǵtz<|pReRy'm(CRFǭ q|gxǐVqp}x81sSr(; uq,hd%wöpyM?~uԏ 9x։~z[]꭫jNyQP$F|J|9FXPcD˄2Lz}Pe[x .oT5:/{&Ά0_ k1[,0+Me\ V<9'wxZ+vzg+_u a:d?܅-w*ykfһP?~*G{wuEFwڇR_wy3_aפHj1ʘ@D* * F F_8&11߯s()ǜn1Q AGHi^A9mz(26;G#-I[풏~1sP IQ(he^FؽZ T(+0(A.vIvׅ2@$Gu)jhuhsŬ@DZ3k9"\ٓN^_k|3g_qF4ѾBLOBhyr)[c7| q~?UQ=39.ow;ܫ"m^Jg2 Zcfup# "2c]š1G$9̶J7.HlՇVa/ɻ/$l?̗+9L^d{ k' !l9,= ce2ށ\}[ 8Jv>Yd9 0IQ ^3UoޒMEAqxPVy]}1鍢6ȉPWNm1F)E 9CO?|((S kt x-({脓h^*Ԅՠ"lgw0 %cwjAVnj#eWqE\^&.}tָ!3qOv˷yC.f+/U"v+jK౸FmY|l>vk4Տq= Mخ^$Xy&q;k';_&EqPk:}{ AԔE/7twؙQ/!js0c L,5-P,gXr O8jW| dEnSZ;?u>'ŲˣD ƠJ^1߹7Vǖw <¬n\Z)~MDe2ݻ3RAjKO ]*cZM;d!-"ku Wt ʠ-E%$_Pt~qsȗ3iF`KD֧~vd!\Jip?rL0sŴo^٪t/Y嶂eXplv:m dE0!>`]7 ~yt)LSnC"2y)1KXOchZPg4 3+.(6BNt>tGƵfжaxp o JcFНuɼ\_e(K7dsRV"S!]5; wGn腂 v'sK 8rŏ9X]Hf`#aOM8hH')x ˘hLX}d5#MzV P X)COsD?{kJpf&=kRȄd<**VT4 0ft]KGvbtx)Dr/0k2⅂N<b:Ս Ɋ#$ƀpDfPʋ舧3#Ut|]XR b&D܎ҲDV#)j%WB@Ӱ؏5TB8ǁӕ7dGӳYrfe\+ YIq03w\DP1J6ѐZl,P08,!"{NYώˀj%%M\IE3$ďfvQd #Mcy"d^t`]4sfR L6]`4C::$\ vQR!.)ͭNy77ĨX` hA z2?ﰋ$xPA9P5vW竡ɤ`DIZ4xMӷxy7z}(±x8_ {NjcLs_ ?Kmy}\ An3sc)3~&xK!voEZs6SE1}=}ˀz3}uTw#>$ aޯ_ ~0).n)JG ΀OdpEkѭHf2`˕p6W7"ʻr͞H/[+;Q:7Y#zqr .zW+w7ČcDvó^ ::cruSQqW~PhP }M3\QH-tc^4m܆A\%4j|U~ФYCE}u*HVNj_ u*:ΪFWOXc{qWiV]jJn݂E/#Zh dzǤ})PA*dպj=_/,6ʾٲyvDe8x{5A>.paN: @y+u 51֚`7XWl1P}jAx^SxO$v;Y/@:ҕx9,tRp/W7MQW"Hu;s͔UX(~%M8}WПHf[Wqfu˦u2&{BCx8ٝ+. R1w%d#G)6ZLnw"GQF7J}N`qpNy[Pdkm%F Ti4^%3ޑ󛄌Nw6' !%3'A0ƓUKK!xv$_!ZX/ψxC\'c9K4Lrڶ%xI0+Vz)/o%P,wa>A:CdmPzw?=s|3Đkäq4eVQr$4(6w6!D$,=VF FJ49Ĝℝ Ȉb rձ0TWF-˨Iװ}k޿MT ^7'$ % [񠷿`\o"a;]繄RID~weZH$#)Jsm3n'.,Vy).Æս+`{ tw͙ 6%"]'O`iaJsxPRqL~&fW0ت?em@e>alÍVu C*=ۣKNǡ7Y*N|q̢2Q`H4ծpHRbPKFaMH1gôv}Pynh'ٛ67/29I:j\<Ua52hSFofS!:}n0,(Ќy #Ew8-" ile3xs+xn^U=1wJo/|˙,2Rvu6ꉇBGe'5!],wIp.#gΔkw~#Qb~Lc_ 5MWw.̴ fZY?%D#G?tÉjqфkݰV>Ú>k|F{%-{dg־a z,N[&}F-C|I wZDX,U_?J-$VI$/W)E P{`fM'*w_, =0C|l|By(Nn׋69W)8dWRBg¤Qn8F+{WԷ7J4ٌyimZ1`MP-ŕB`AݘM)Uگ∏rE*޽kí ec|ǢrB0q_~M?2Vvdla/$%~_hN O&;l!~j/&R(RD<:R(Io\1]xSr\܇ |G/TT>HQ(/i3=6ʺmĨ^8#"/h#`G "Հ76;Hpͤw#A(魴@/zI/u3xn_^[]zQ9<$ɥD2{5z"^S mrLvϢeɡ[`97:8/&z To 4ba]QOEWNM`R[IZ5;EoU:f@L9GG6G`LH%D_y䰗7G$-n;졚LgE`xg9z3jIsݮht#hfwUrS1WZɤ;)eoq@_hySFt;XwS\^ BZ;vwѯtB%SwiD3X J>Bq&(Oq@m=b`^nC[hGA_HVl.@y^|G]_US ~u݀6;M> ,r1cPנpuK)6Ŷ'IYS_,b~,)ɨ]"jZhMغ 4Oߎ8eifN~Vk + ۵-Nj?RilV)Xu8' {b8ǙN 嗸WE*yRP<)^O|%Vo1'=s5w}TQ9\H1${xKu-lU>)54yT4Aԧ淈(kyП_ Yz4M7-/OS="L3K.9Q*Dk<$ѼAxkW Պ=`>4]׹ k.5HE)ʔ(5Mi-ւjLJzr~wQ1єW7ijx7lV:m-hoNv,_<{XZ(kt2h0 [1yX3UH|%n`mAS%=S\R#ďb~-@;Zr$SG:9SQ#6܃BibgUD1OcYXa}#L9Ŀ[ɄeҲ ]pB1,jd:"V׊: $ C`A[>(J[<ش]G_^N=:Y+?YSj#(y=r*'R^%W]\Xw$|Xw^=ZH`Tb1H5ŘO |l jY ^Cl]崱R vXJHk^n<1_})@ A'.GS2g 3C'C'bATxirv^Ie1$ۛ7r Zg^`;?~}RbژBAt q9z1O"so=~}?G]]'ğXIj@sPoɧ#SaIzƕXh5 aa7)Е_H:>j('1 U6bЩحb}|̩`%H׎)y?-y)! zwaHzWN!hA/]{i ]_#&҂3aT͒iT=x3`xPZD<`,h>{DM2P] !х_$L1l4B>r&91px Fl&s,Gn]6 !}EJ5ؾ<,OWGWum Ip|FFxYgr{WFomÓ1x I۷NL&?ӡEk5~$c6s/.Й|Pw., $i">W!K4]yOob@»%z 0:-Xʔd3*T#p؍"͸Q@9M+Z:c&ZgIm k]uz˻Oق G` /<^&7pr[{:=1P.<$=I{EJ7G|o>nʣT565~OZ&`QgGOÖ3I<0+Zr/C,O؉u0qǯ; Xrt.[O 5Hnj:ҮL0l(D|cv19ѡ>ɞ>.iQM ܆yK+w7-#HrΐS*i"` {Gb SEc*i)qv % n4>[ɦO?fۡp6mGHx71Ž u,ɺHZcz.g/f02J"{ks9ؽcݪ^i_$F3ىBy+6SxOSxH!.Yqh46r~JuP@#'*Ἒqy7Y}Y54DbDT#OYCUƨcbL)C`&y[,#>$@[u]7UdjGe@YA§wU#D9e7)I0'` WPcaI Y&J_7 _9D9`e7`8479rj픂.##P<0ܫ}3+i0amte)6QuX^h Ɛ01(}9dC6X-zmWù~0e-[e9Ly(2hFH&Fg +GG,N<b4i=Js'v }6p!^6֑W33P (i;G[iܣVm!H6RQn?m5Dwl5 n-ǃɂ&Oq¨ITL &Oin?Tdm^^N0bD a92fo+ݡ13JFa={l3~1`}P߫4R\m7!$j4XZT)3TUrU)$.8⽎}OULg l:j1G8RoOa0G ?pTQ*N'}kKّ#9!qi7?,-5| x*&]=&5nJ+aA"J:D'j|BCUv7U ŋGsoIieO|a )0]EgN NFWWflzΫL\%Y3zIΟຕ?>O0MB(cC>ChZapAFL09C79m6Zžf _kb Lir Uۯ_XJpLCc\ # +\D:ޥʈV0gZ'NJcБEHRz98@ *c١AOjѲƇ[,4O- Nkߘ}*fSVoO2G֑~0.{7ژaO ˁ礖.7=1;F;MHqc욊F;k>#2Y2 X`t:˲.*1[d+;T-6Vchz?yՐ6\Os'CZ[*\xB>׼H9~19 `f+x _P{_Fr9BbP@gDg<>]2@\z`GFAX_x\{P_D2%z-vKL\BJ#ZZpLOU8S3/Z}p ʝTe5&k䛌3ZmTR'%(#ӄ86]<ܗ#l~؅OY*De>LMBh{ B``u&OPr,|M~B`slj0yᠡu?/1]\|4 ';2.C-< c@YT 5w8vjeVS>>S#ig3t>{ћ\Us}YC:%m?Z)p2vմNdb8GEvu 7j!VY= 2Kd:);Cp{-b4sff˻\h.H8B@D4 nnnTՈIh(K=?.-LEkuj+UQy ߚYeɐ|X# F [֯;X> 20~ڽ0|kH(P8ZGϏG*RW`M2_-W<&5v#jmSd,V\~d-͵VZЖT/ٱ/,̸x6Fu<'Ҕj?k*޾]RhY:=ui&>~[XΔt֟ m>E~~r hh ]K%$O^]o.;ZFSd}c1>6M)}U/xՕu ЌJ4E}mxEu),m;6kor7I7{u0';lo+<R+E"tmԉ_h|G/6Z?2@0Cn̅Z3.s}m# 0|tϞY 2,fCLjdcD &@S;_*ss7ۣ-|6|Qtm9f%7 v$U4 s$&(uHfW dUGh2S@Ύ}z,3ihgȓJbHdvۍZ3؝\rudP.6)uYਢG-^qs;C}4)L@[2Y< z^' sK7 rh3ifj%{n B؅ ‡2ZCCe"wu.f%׼it7͆*"HJ8^;9K,K}ze:|7΄ݢ GՈei18SVebRTrJfxc2Kܟ10v=st牗f I({ZH,]dJ ay9/){P[M(G0a!r\rhʉ-٣OGoUaXRNUZat@N] kΞzwKoq^U DWE'{ *".T^9Ρ Iakl x#^~!Sv3Q0B: 051V"D" ҠWJ"ZPd#<񠁟n0W<SN$&?UǪѩHfpDnC mJX~ͱ֞`ێ>J%5]|x;7g5^?՘HY]XQ^ºό(be6:t~q^wJrKa[e#O8zp ʼ]r;(-6tټ,;Xm71D |( y΢Mϱ]Xsݺ24,7{4 K ul [X25l=Fv/~U*jiiVx_UĚYL|=3h)"7cƲw>T3Rmp7ht э ˻̨ZѤIٜt$kSSG(:G/VfttS(yѼT{v38k[Z=.V Oe4%.2SxbAa%|mWIZӯ=|L e x( ]OelupCs׭N{ +aEE$"7öA]-L9+ ZkuwVեS$P'e ey5rEkqQ}7)cL{( FТ୤ɫvhc% L^O]\3Zr zVTCВNDC!βS) UQ IQ1w6`DVn@.ly-U0a~E#FUZ[:εOHPj#x2)@?9bkChQ5:RKos+Fn.}VH4E]#+,OЇ)V>=|n1_(uě1|#jlq0$axdH9|;ya2/Ę  lepka9#K_:gXt&ZH;C,uB -x jP["zXs|k> eq^nFZ@ƞN2UQRC2ڟwS-m.o/x7:z Zؾ0m#;ۊ>8'͓vSD ;KvG)ur}6vzxٶȂCS3#A[:Ah's7Bt-/BL$(/~љKP[%x(猧4N"\Tp{?K=ɣMn,ӉC+m?"+{6LL$։G,S뱱<9֛o5א~wݲMmE0;{nj<']}fs(XP}CSMs80>׻ |Ϣd3Y xONbF8TGIL}'1ϖFY]k؄ǾG{~m%aFq֜sJJحvƑ5!7uU3L!i \}lx4܋tӫ#&] _`nރztq]Km5ƪh+jOyd<یmksik"SZW{ț%[_7Rf9?w>>ᒘVӫڏ;lV/[goVU.tNQ+m>E|x#xfC/愂ve ƒn <]SQ|agjzזsM^w45!=ft05̯?~Zi%tAh ++w찹3{]%ȁX0W$ 5RkpX߭E DV-pSG:Bg[}j}֔8Znw5uj}.0,U*y g"x#"͕H!a vbz[NœL!9nhq>,VZi*IQFEEv;9%t^IK!8*@?n~kx:3=|n-kw<]ͩ%s :GfUUfUS^߭øSaƒ5MO?ɲ>l`90mjr-׹ Ha^S/z݁s~)KnMJw[_㾦ε! .˟~+ƶ|+(}6qeēK66ߛM]fB ]: ytׄ't0=oYIH:>Kd*`bvA1^ C)X zS5%9A~rԧt-vם5~ϫ-}pZXsM1Ow>E;;6WcMy:)TzvuE8=BCPy#ctoc/aNFw: h{8*ޫ^k׾׫z]U^-]{[:ҝ( *@.̏](#0 *ʰ8S㗓ۯ޻9s".iHpg|cdYkqUBWz0cM[2ybkt% /-C[EW~˘y4Což`hkM&Z1k yFWGj%c}Uggx$Sseպ2ߐo|}g!5hVZ$\񊜹SülLꉉ`K'gIVq6~Uɑ6tS VǶtvß.D|Xmb5r=S6>YjNowUy0AqNWNɦ iaY#rڌ󦔍pNs0DJmq듵qG"C{ۊɶR sjf]L.%onk&Ƴ%aFst~\&xL'"!ˠwbjVO.- ۽Ԝ%93[<*!.Isl8bC)R63AoGh{6zm][gsuAuSaMg̞+}_rGSIJscC1& 27Zݦ2ޜQ>u5k# r3/_mwya N k6H{.7a<42x/i=\=Y@3fksNinzK,3jms<l46 Ep1>o9]1JÆW9S.̕ƜW-Orjj2Vc,Ř'N}0*~9ScXvyCAMXɒ$i(2kҼ]^VO~^d&BNG%.monyÚec˪?{kʵc4u݀iRm~C7h7~q jOCThjR&ޅ5Y #/8YI^̮n24R嬻iDX#8&c[':H1T ]$e`g0ΰ;,:Rգ|$4\G;k`ل˦bXLFImPh@ssQm+o-5I0YtYկdZds ~6"x|Gn3Yjr^R7Zݲ,\XnXO#lwB&u6)Xs55륅5+iz2sU{C Bo,XDf>p>;NtwF6xg {˺Ɖ2Xi\`s^z|nx CjV}9ۀb)N|X je2QP6 _4|^F=]/))C(mcFW8S'6h(6Nr %]hey~ӣL8Y#G^^kO F?Wu1r$2mg4s'Z%Pu)nhhoZ \{ nݪK|o884¨3&eӄUv21dsqV7F̅Iڥ`^OɵKf3}>:-XJ8QP6zXf2Qgk܋W6~V}ˬ O9)?7:f{\^xd%0X'Dv9P}GWc4)o{%FJA`u4wY\WΠ wt\KKս G6P,F)*ovv[>hn,9@\X2%O>n䕍QeXƎ5zq:mܑXrFVg&f*t(w@Xm/lu&۬RP(*Tӳq\m\n_\zflXcCBt{{p{Prɪ*j ᜊt~ğЇun_G~tYHok4gV}cNV^EvRʸBzlA5Rul3[QjX.F1v z^mVnuXĂv]' +b15&s3"UggULJ)#=G, *U>VmgkcoǪ+.]/vtΝ֭S5L9weNViFsSh@aRk zc*Kѹ;pCZO ]hi=-[7ƭʏxR>wϑ;xVFDsޞs磣Y/ٲXDnR`!,5Wٹ sn۹7pGE浫DO6;s+p,{ p~r`]XR;C{t#d1o\ؕ5qU`_=7CbruJ܃1˔ l8bfĚGRd,e76.g!e RVZsq٬1B -NUDܺNgsRMzUr4avSֹk*igd5q/oUFsI-fYbw6 8-,3N^,a;bgaVۖb w!`:EuPA36"\$S.uBG~MR1Qs.k3nMFRPaҦ(ʹByl9ltܸ.7vyCoܩ nXT:g~6ͼΏ賣wwHmNlդ2F*_Rpњh.sk֥ 7i AXf NXr qZ^K*gC钭1%2f*PNJ9 9&/l#;Ճ6o8jyT_xfRMڿqkTx[o4\E2C=`ps*M:z=,/-A}6s&6-8(ٚT6tP#0Rҕ2w 6xc[zѡ"9& MO3;Qשol~Vurκt=mmoraՅdn:])2g|MKݖݟzɤ6S`5%Wщ 1'2Frtc`vafgڳKt`3\҇+.Q\H2gYafRrXG lzgU} 6,8:Zu>k[f#?¶l}N!3&{K$tV5׵nZ +4-F:}Tp5BlDhhSMF%cq*_l?3Kʼnݮ|[3sqI#~Wq~':qNiؾ^Ӷum+6=vk/h}MCo[z7hKsܴ!'^2"p"hOx¾ g=݈D6MP}\an٬m3y%<,o7O=vrlT_7A.xoŴF uZ? _;="硜HWI#K3zB?T^1&}JXϩ;Đ5FlWl\vfٞ[-BAGzQJH,y)v.& c'+6'/h[<;_HЬ>i%>Jͥ+:s ?7l['3SVtldYUur*nKèԓoVG2Qf4EΓ;LZ gbCnγԵCQldZnY9:DV31\ޙ@hBj3}:c%7.,1NsiXى5cX~]C/AVԖ~n-GZ~,xu^zyir/,VQc +WҠC%omW[zV戚ݔr"\n^ݕN\~Oj-7WRH;.sl^w/;SoY_Cf#s`X4[39ľ?q.lLRgX;IW7;úñ jo4F屢# yEܾP96"@"'I{ːpi7"'tfʏث#ѮeUmgsկ;Ncm ^HdI ʻxy|?Gdz)ɡx@VP9ᘏ΢7 /0i{%sS}ԭMѨ´LQK afa$nْpu޳LzQ>p~1*vLuN{ G=."[h6zU/zz13.P>stʺj3YҊѵ:F@۷pP.SY+E< cR7j\)[S/&]f!XނL#r%SJ5TiSqgppiՙ,D!;^ X z4,yv?"eqWsdl?pְuhJ۽*V=˹L'j_/jbu9cM$#jnː/8H$Zphՠk][mXtQj?C.aM4}+񱝵𙂖`cL:oq|-QSoL ˢKl2 d^ g:Z3!$JcBlQrvéCn=d K-r|\؃_^dJR6bY%OWc']7Ey+CyӝbTlM۠|(_*5wqɣ q69J ]D6SyfPe+R9sÑNM=ܡAe_xAu@(PY Z5ν{Xԗ:{b_Z }!.享Ų%%c*bDo:=%i2DcqEfQO*XTp ƒ)aipVØr6[|CoԊ]9:ҏ3crV $8s}RѼę{HEHَ6<[}C8w4SŹd<̋W&ׯ g4sn-9[W2;R`Xsm՛FWi11LECZ,>d+'dޢ.!zQp{+rkΖ2-[PʙʧZ -lb#TɗplZjC81Deg:˗˹ϖi8 fqz}&o=1DF!G6u 9jO#'5wtl܍>蜳.˷yp5|#jj%7%ViOqd+{OsuudyTcڊ n=ש{ҝ-# $ ]YL?;ͩ6paI/=!Ҵ$ _VdFk9e85zC~gov ʙNIqEdh:i$>Ή]k rZw̄8*+2 ?̖QΓ6j+Ckz*.^Tmה;S.9s\6x8Mǂzx3 ʮd@R;`ޤ]28tim䘟sgKV% ۪[edRk7I +0} 36F?Q"0rS3UY'ól7zvc_R7;:<5^W-؆؂,2ô$=.-)\iɐڨ@"±j56HDh slVԶۼ45i3 gHnR#zeH3X8>Yu__9,p@Z\M8ĵܛ_-ƪHڳ ~LQ;YI<;f|7S|k_ȷ))oO87 R/]{'Ȳd?ml-QHesS#HY"\w/֥6|gk6K/ 9ú1l:OLj޼K-@Pm_^ W g,~:~>jZ؆Ҽ t;CjLG.4^zeJ5X|m0xYW0Wc~BD傞p(Mܜxb$ݣ)*7|޹!jol_xUw:;.n <mJEۚrLVKxpgul8Ȩ6mGSJOim|Ngjsї7z=Yk~b؏}22'#2ft-:εdX:釔cF#Ǽʍ]j۱=2wJמu>f4q=1_@UjnC2wlKPcnnZ¢4m*Iu. ӅLœ/0@f.GtzcfI6V*>2L6g;gRԣO1DgF|#ټL &%w8 q,[XY}YS'ZcVǻ^BǜAmܽK͸}$mBOޱft^A2\05ڕvqTO"0N7h+bsWw$7L"/(,:?ǻyO%ͻbk2΢-6(K~cj;Rc{(Ue:j3slyơ4e!utcs r$[+#qz l40e>*l?!e$ 3Fyk J@YҬ5ʬҊ=t7 m\ czUXI=)pA *x,ҩC?58;M-㤉78-HĜ3hсM$5S7E=]4eӂGάS2WHV_QcKPWCo]FEO3095 @j#HׄMIC\QgD{Ԃ7)[r$\z龨{VD|"Z?0{=Rϛg ͔t3f.~]ا-Шq$Ukq5Lh8OŦZi8RH.8gaUsW^e3MAWƒ:f~:ŧlY 3O_#j8^i>mO%gӊ6fcA&B,5hv%Oy>څ8Ӯvf`BPМ,-+jD^ſ)`cto#G"6Yt֪NXJLf"i4FFop1\Ҧ6)Q)uZnH{ٙgFmhK~ׄ>=[3V[,y`4utfRAie|S&P:l6D%s.Zb0/杤i*95 b`ҭbs!NkL4mtؒ]&,;:zK>^YQVҰ^d$Ɣ¼Ot&[F!3y:99Qs~8ש>.ȸ5s=_ h,SXיؿ(3ьl[0{c hfďhȏZIM!ՋVvj&KK~q=4|GH>0.Iw~Kc ]E1n`e*-~y;8Y5wШ9&G7#oq~@#م#LT/&~0F YV'742mPkGƘ]HFm-oYrرO:+]H|NGhOS7Gq+]1G=ғ_ҙEWNO7GRUf[7L&LifDa'c5LB{p #74"q4NDzX)ުpmh=RcI]hDŽ6wr9өq5 ;4hb ?y :K`}iǬ&GFVڝL5#~yBH +L+j7(_p4?M5F` YV'#hӋ:l$<`/l:bhodz3|FvEiVʍZ Q"5OĴSu=bڮ2}25 &jd. U}fOzcבXfqccNIS D1 _`/-rƫ+ p̓3V|N-y.>DzB4!Q>EDqf@c[Š9zE-t{;9! ܱҮ{NKAb=s*Ym$Ј$׾R=! . 7ڪmy:|٘-@非l1ůժ]>c| t.3GڄL@cЪUJaF c6ѫ9'I&6d劾?0eVjtF3N &IU7HdN sƔ{'ڹ};泺=)E4^E-7MJ ?_4.c7]Q&wg>=}4ٟN,P [Xea0OXc߈ya\]x,Cikw1/ oW/gJm~7F!nR H!s?˙Q3}?^}E_I3Ei/-Fc7j+I[bzo1;6O#ً?Vw%nG!/^.0b؟~"Fl~S63R9UeF:3vڳ]?#w̿zx 5榍PD bZvyӤZ̙Un5ׇ7/eL: FB?ѮiHe[?$Dq@ͰKݨmlin`M7ȓsANJv`*Ykbo;4yѐ71PTV M,5?rU? J1U~"r0 ̟[Uˇ]?QuzoRuV_Q|?R/mYat 0cr?*KRޒ"G4FAŹ+یHVj5)h?תS#-gW;; &4Ae; ӫmY]B";Ol8f^ 5, S[|KF8l'1b2`,X)(UkFGN7}|?^;J־\ U3*!Qnh(0#3aE?iX~ S w,nUJZޡQ'+txڗiM*S=߳?.[[&ٝqnm/L&mjGJ3?߶6aY)l5e-2>t3ml'2.&)6k}9ѯK7\7Buxh9&;9Ώl 5 Ć67;mUΔUz-0g(sd.!zEh`]E"Sr%6f$5R}<5COq-3Baժ7m̱7ib)},nVVJYLfj ;[V)3+uQ$8@Ag8nSMb 'pQ7B׾fpvcd*b)߼T,Y[>WJ]+c$wkمz4Lsa++uYl>O5gIHµ؎%i;{>bʯ]Y7YLN Pzm}qо' ҚD3T3FڃQ{K/f[MhWZBH&;Ƞ̨X[|NG& ;:dqߤ6ާb4+I2_wLv+ݎ莎{SĸfNg4iS=uC{koX/V졎"!mVEjQeֻJ՚/޹{;;6ӟ\?fLYy%zSkږmݤN{%3l9_ly=Ǿ]TVLb a{L}̾1XH$oZ.]Dd&QvZ g7^xRX^Ύdnd "I$>Od,iTOQіSy"(~g// |O =% P4h:~5@i2Q1q `9]F3}3}AP-PTYFiMXhPwjjCeax9p~`6r! @Ba%O&6)m`X& \M*gDt/ag8  ׀^ \ (z ? z p+pp~x Zu7o¯nWn x; x/>>|QA1C''Og_@_à_F+ׁogwA}п4u"; @3+n!Dip #J;@;A@0(8~D x"SE`'PRJɢσp ,Z$E~&D1OH]"M_'DKM)Aڗ)}牬g8H$gR͓$RFS@XeoxNA1C''OƯ,@?/ |O =%!)IHJ$B @?!A6: ::2I"Nn_s@ ]xO $"ɀO I"D$D !A*h:$DPzhJ'!IHD$A@$ <h5?)RD"%hR MM55"@* )B- zϏ'+5(N㯛-P6KK/^<x#&fзoxNAcǁOOBMƯ,@?#o |>)HA R`k`k`k`k )"nRD ( R@v9@ H E€C ))H)4 y!EBJ`^Ha^H)24HAHyH)'R@5 h5σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<σy?<|ox| Ys//0#Q u7oᙷ]~/) O? O? O? o%XW+hh;hh'hh?ziHeH%c$On=CJ.o{p/i܋8@H%i ? LkT5HeH%EꭤTRRLk~KIII(m(r,jf5`7{@Gcq<3z%5"ס|=pp# 8$22D_ކo/} z)p72}5k 5-[o]]}> <'><|=$)i< gA?y/_< <| u7o|} JR7" @3-@2/)W@*3eTR #(0,!HN3t^0^Hb_D)zD)i`"Ό̉ͳ@:'fD~EÃ̃̃̃@v` ؁@v;Pl(`6` ؁@'0 ؁f=vN H)0 2v;P| /%@ȗ _@v;P(` z@v;P(` ؁@v;P(@.ȅ` v` ؁@v;P(` ؁@v;P(` ؁@vG(`` q؁8\(` ؁@3>0؁@v;P(08@3;P G ؁@v_`0000s΁s"`9p{f9Ds600``m΁s6` 9!&#O6Зw/^ x-:7+7x+6;wx^}Q@?|0x1C''O>|y /͇AW | ϼ |.=@:```0af!:̒Ct:%t^/tҗCt:a}'wrD(J@*k9Dr"o9Xw9Drr`` k9Ģsb9Z2C-O戟k4y2SPFD^(E`8_QpDZ<"Ozu@*yxCyHGґttпn ݅z^zs Zu7on x;wx~>|xq!֓:| }2J^|&-<6]~4<<>σ_sJS  y~M|_yp{ܞyyWys6RJ?e־ |䱒璇璇璇"bR,XCC==ᭈDWXR)FᧈSD)"dD$BFDȈᧈPD"CtQr!B.Dȅ88888885JHE$"aDXD"<C!qC!q8DH!"CD@D@M%šaGEx" ^_!¿_/D"~^[K/DH!"~_!_E"f_a6I!)"$Ek"~k"FԈR#§!/"| "!5"l-#b-Rw/bEʋ$BDH !A"$뫀$k@:={A Z ]a,()w@__xpr^M-[ox? q!Sxxς~|U |EQ40)W䋄(N3UXo@t?JޠH X+`U( O{{{{["-֙;$xKIAW)ǔ`oK րm^tC!Ɛo5@o7Qrpp|r Rne=ˁ{k^xr3y Vmہw~x^}>|QAcǁOOπ~s"%0#Q u7oᙷm~IiU zU^J:$x CW+ꐠW%XFQ` &)`;~ FQ%hT $A$줒Q%줒W%줒]%hW 6[":bX4IZHD(-F"S(МEh"4gY!/Eh"Y,Bs9МEh"4gY,Bs9МEh"4gYW9МEh"4gY,Bs9МEh"4gY,Bs9МEh"4gY,Bs9МEh"4gY,Bs9МEh"ƽq/Bs9МEh"4gY,Bs9МEh"ƺY,Bs9KddD0`X3 oKKȈӒнp8nn{6z\ q"r%-/^ x9p/poބ ۀ ..{| !G>> | 4_| xx27o |.=@ D8hhځRI)ARJT;)awP +P%=3KЙ%tf :D %\J$KQQT/VJT+c]u2֕ГeXeXeeeĴПeHST,CПep+CjПe2 I)cW[;EDRhIxVۀP/^x-:7><|x$)sP"0-wt.C{нeeeeepZ2beDe:+C3}e,cf02S0je2s \~.C?]eęˈ0iV.cYU&E~E4_+,e bY;iVN xA|0ǀ@< | -zπ~sEK#_|m;wSXXXD!*+BT`-WZ Q\A(DD!*X Q*gk@ t~:_ί0TWW |՟ V*+XZZ WADU "rVSOEC C1 Vy*X`U*d BFcWǮbA*UDcP**8182z ޼%MH7|Jio_w/"hhhhhhh*bUĺuW"]E ߳ ߳ ߳ ߳ ߳ ߳ ߳J$]_> <| 8)iπ~sEK#_|m;wR߳J|HEЌr @ tU4*"UHS* ib@{3PŞ* TC@";=@i";9*UN*d ٩Bv*]* yB^jyA^jyA^jyA^jyA^jyA^jyA^jyA^jyA^jt'nߓ4CH+{BH+fMs \˒Q]v+ܑp]B%^,˲,ڊ n!tɜt&k-u %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x %^x % ^NHH "% F :! Z܂VnA?A'Ak߂oA뷠[-htt~ :! :! :! :! Z~ ( NHNHNHNHNHNHNHcA뱠Xz,h= ZǂcA뱠Xz,h= ZǂcA'A'A'A'A'ATAW+h Z}P iPV_AZ}+V_A Z}PPPO+h Z}NHZAU*h}TA'>A5ttttBtBtBtBBZ+|'|'|'|'w;BzG!D.B"w;BzGH!#w;BzGH!#wBH!#w;BzG5!ԄPBM5!ԄP;BzGH!#w;BzGH!#w;BzGH!#w;BzGH!#wNHa';BzGH!섰;B !;BzG;!#NHa'wvBzG;!#;BzGH!#w;BzGH!#wp;B8 !#w;BzGH!#w;H #%0F a#w;zGXa#w;zGXa#wKX 0 ( 0 zGXa#w;zGXa#w;zGXa#w;zGXa#wX;zGXaVa#zGX;zGXa;?wa;?w;zGXa#w;zGX͇a#w;zG a#w;yySov_93o?kss75?'q^焿W s7 ߜ/|s7 ߜ|YQxg|O<=_=c͎7;='_=7k}ovԿKo~}7;m~[߼[8Sj~6;;ws;ws;wt\gy3\?<˳:NNNNSɟO%=?x߄<)))w'zߝ}w݉w~w~wp34 gh8Cp34 gh8Cp34 gh8Cp34 gh8Cp34 gh8Cp34 gh8Cp34 gh8KYp4, gi8KYp4, gi8KYp4, gi8KYp4, gi8KYp4, gi8KYp4, gi8KYp4u읳n7>9oQxsi6+=9y|{s889oy`{sw+>筃9oy`s|>9o}ϩ9zNӝTœJS s*aN%̩950."#*!"*!"*!=yϫyϣx(Gnw[յWuU]{U^յW9Uή"kYZWU}|U__*W:ShG8Z*Wϧ՟NO~==ǟ߰ kI߰M&{oj`:mD55&cd욌]$rלˬ9Yke֤O?+gocɺJsҟyv7w矞y>OϞ/+ל9 Ys&$^k?>{k{k{kzkfSMf6ŚkN7֜n9X3xƚޚޚ^VΚ[9k&L5xM/^Ӌ58N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$N$&b(&bHLILtcj#f S1+>_ f cLtYb:KLg,1%Bb*$Bb*$Bb1S!1S!1bo1!rY9t}b%Zb%Zb%tYWĬ+b%Zb%Zb1't"c~-2Ș"cV1+FJ#f҈P1*fu[do1EtݛĈKĈKJJKĈKĈKKKĈKĈKĈKĈKĈKĈKĈKzzzKzzzKĈKĈKĈKKĈKĈKĈKĈKĈKĈKĈKĈKĈKĈKĈKĈKĈKĈKĈKĈKĈKuN~>?uuNɺ:YW' Y7k$uu~:Yw?z]u|'QϘgsWurUκYW9*g]嬫urUκZ*g]嬫urVίoxgӿmy>z>y>{z{x*Z7YkduUѺ*ZWEhuUUѺ*ZYE?_!?yo~ͤZwx]-ue˺UUUϊlYWQ*j]Eu0-aV,YX '̄Og0$\Tr o(%aB&a o(%aB&aB&UB&ao I0$aIo N*0a"\Dp &%̂K0+a"VDX &b%L>Ixs)ͥ7\Jxs)ͥ7*9*9*9*9*9*9!20!20aI´9r ,%0*aUBU'̼JyP P 0*aU{J ӮSJvRB'T~B'LJiW $LJ`!aU D$Op?a|o s26!c26!]$3Igp/~ $K&͗KH 7&'$LOHs0$~O}?[n&0M$t4iyIb'I$͵HӗE|I:{RgOz5/$}'/$}'UfT~~~s ,_f6 Yp͂{lܣ/``iP W|}{3* έ fTL(/2Q_0e`Ͽ`͂lܸ/``jsP ,WYpnU@_}WIѻ%EgEWEWEVEVEQz\E ͢,bheQ+:-hEVZѻIE_eEuwNxNxNxNxNxUt[tUtUtUtUtUtUtUZQ+zE]uW:ZYmYmYmYm={EgE=_E_ETTTTTT7jSTԛzSQo*:*:*:*:*zǩhjQ_-)Eu^ԃNfzPlll/EEu^tӡ΋>E=hcQ*AEu^4΋&yQ*:-AEEu^tK蝇wy(%Qtn[tn[tb[tb[}JOI)>%ݧtSR%_}J*tS}JOI)>%,tS}J(>%ݧS}JOI)ᢤtS}JOI)>%ݧtS}JOI)>%ݧS}JOI)>%ݧtS}JOI)>%ݧtS}JOI)>%ݧtS}JOI)>%ݧtS}JOI)>%ݧtS}JOI)>%ݧtS}JOI)>%ݧtS}JOI)>%ݧʒSBeI)tS}JOI)>%ݧʒSBeI)>%ݧtS}J,>%Tt*KOI)>%ݧʒS}JOI)>eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eWF_}eUWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWA_}UWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_}UUWE_^G^G^G^G^G^G^G w5upWQQQQCY^G^G _5{5duuuuԐUQQQQQQQQQQQQQQQQCV.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.G.GMUrTu.GMUrrrrrrrrTu.GMUrrrrrrrTu.GMUrTu.G.G.G.GMUrffffl۰lF؆JU _pScW6PjxÍ 7 7%Pfl-anCoH ɿ!7$ߐ 6T݆PunCm 77L0U`T S6dJې*mCn U~6TΆ;nB6|jW6|jC=l 6L0a`Ä 6|nW6DppM 77DppW6M _7|n^ֆ {Y6M.ory˛\&7M.ory˛\&7M.ory˛\&7M.ory˛\&7M.ory˛\&7M.ory˛\&7M.ory˛\&7M.ory˛\&7M.ory˛\&7M.ory˛\&7-.oqy[\-.oqy[\-.oqy[\-.oqy[\-.oqy[\-.oqy[\-.oqy[\-.oqy[\-.oqy[\-.oqy[\m.osy\6m.osy\6m.osy\6m.osy\6m.osy\6m.osy\6m.osy\6m.osy\6m.osy\6m.osy\6m.py;\w.py;\w.py;\w.py;\w.py;\w.py;\w.py;\w.py;\w.py;\w.py;\w.py˻\.w].ry˻\.w].ry˻\.w].ry˻\.w].ry˻\.w].ry˻\.w].ry˻\.w].ry˻\.w].ry˻\.w].ry˻\.w].ryu VwK u_jIPSoScSMo}Ӥ&uK}Ӥ&u4I}Ϻo}Ӥ&uQ}ӤȺoԽUMu={YM[u_sCP59}͡&u4I7MiRMo}Ӥ&u4I7MiRMo}Ӥ&u4I7MiRMo}Ӥh7MiRMo}ӤutI7PMo}Ӥ&u4C7iRMo}ӡ&u4I7MPMo:}Ӥu4C7MiR'SM=o}Ӥֺo}Ӥ&u4IݮK7Mv]iRRMo*uIݮK7M~3oNZ;iu6444444$dNKNKNKNKNKCB6ѐ ;- ;- ;- ;- iٰENKNKNK# ;- ;- ;- ;- ;- ;- ;- ;- ;- ;- ;- ;- ;- ;- ;- ;- ;- ې ې ې ۰ҰҰҰҰҰҰҰҐ ;- ܰҐ ;- ;- ;- ;- ;- ;- )ݰҐ ;- ݰҰҰҰҰҰҰҐ ;- ;- ;- ;- ;- ;- P ߰ҰҰҰҰҰҰҰҰҰҰҰҰҰҰҰҰҰҰҰҐ ܐ UݰҰP UP U=]`ϻ{f4홯g.Ӟ~{&g Ӟ9*{Ngʞ9*{jgߞL{&2ȴg"ӞL{&2ȴgߞ:ɞ:ɞY({f왪gҞJ{&홛gnҞ}{ڷg:ߞH{#홏gɞ:ɞ:ɞjgߞ ~{&g>ҞH{ggɞK_==L33d<=Lϯ}~k_>ϯ}~k_>ϯ}~k_>ϯ}~k_>ϯ}~k_>ϯ}~k_>ϯ}~k_>ϯ}~k_>ϯ}~k_>u~_:u~_:u~_:u~_:u~_:u~_:u~_:u~_:u~_:uȯC~_:!uȯC~_:!uȯC~_:!uȯC~_:!uȯC~_:!uȯC~_:!uȯC~_:!uȯC~_:!uȯC~_:!uį#~_G:uį#~_G:uį#~_G:uį#~_G:uį#~_G:uį#~_G:uį#~_G:uį#~_G:uį#~_G:u̯c~_:1u̯c~_:1u̯c~_:1u̯c~_:1u̯c~_:1u̯c~_:1u̯c~_:1u̯c~_:1u̯c~_:1Nr‘p#'91Mo%'~+91Io%'9i'v~bNFpBn't; NvbVY'fU~bV NvBn't;ۉ5 eN(sBʜPT%S*RJT:)NtJS*RJT:vJSZV:)NiuJSZV:)NiuJSZV:)NiuJSZV:թ]SLvN2𔆧4<) hxF3g4< hxF3g4< hxF3g4< hxF3g4< hxF3g4< hxF3g4< hxF3g4<9 ixNs4<9 ixNs4<9 ixNs4<9 ixNs4<9 ixNs4<9 ixNs4<9 ixNs4 /hxA ^4 /hxA ^4 /hxA ^4 /hxA ^4 /hxA ^4 /hxA ^4 /hxAK^𒆗4% /ixIK^𒆗4% /ixIK^𒆗4% /ixIK^𒆗4% /ixIK^𒆗4% /ixIK^𒆗4% /ixIK^𒆗4% \Y]9ͅ+\ͅ+S|)ʗ|m ˕o.\9sxeVҕ|)z7|a|a|aʗ|a|a|a+s2 7|s7|s7|)ʗ|)|a|a~ݕ+{tWv̸2ʌ+3̸+_J+_Jrreەuԕuԕuԕuԕuԕ'\kVZ_krVZ_kVZ_kVZ_kVZ_kVZ_k ohxC74 ohxC74 ohxC74 ohxC74 ohxC74 ohxC74 ohxC4- oixK[𖆷4- oixK[𖆷4- oixK[𖆷4- oixK[𖆷4- oixK[𖆷4- oixK[𖆷4- oixK[w4 hxG;w4 hxG;w4 hxG;w4 hxG;w4 hxG;w4 hxG;w4 hxO{4= ixO{4= ixO{4= ixO{4= ixO{4= ixO{4= ixO{4@=nt{@=Pb{(@=Pb{(@=Pb{(@=Pb{(@H릙M+̦fS74/h45qEM\4qR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-uR'-u֝۲Gkvw^L7[fk 6m&X[UZ[UZݽJk{˥-k{ץnXۭ`m3fk{ץ-?F^ۍym7nk6>곭>곭>곭>곭>곭>m&X/mUVmUVmU6m&XL`m3fk۶m۶wmj]znzn継`mߵUx:oVmɴ'LoVm]mf6`m\?v`m3fk 6m&XL`mϴk{m&X3mϴ?6`mL?vwm3fmݹymn{D#QQ>:z{{{{N<ڽyth(xtiףӮG]Nv=Z>:ztiףG{5Nv=:ztiףuuuuuuu<|tiףӮG]g<|KȩGN=rSzRQ*>JGW_~ubG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vCG=tbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbG*vbkuZkؑؑO({BʞT|ORI*>I'$T|ORI*>I'I'$T|ORI*>I'$T|ORI*>I'$T|ORI*>I'$T|ORI*>I'$T|ORI*>I'ĩ'N=qSOzORI*>I'ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ]ؕ{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]ו{]֕l]֕lrY=˱g9,Ǟس{crY=˱g9,Ǟسz]ϲYv=ˮg,e׳z]ϲYv=ˮg,e׳z]ϲYv=ˮg,e׳z]ϲYv=ˮg,e׳z]ϲYv=ˮg,e׳z]ϲY:=Kg,SώG^G;=w4zh蹣ѓW=w4zh蹣sG'zhSɨt9iɥ;="===w4zc{ҩgFM=75znj蹩sSFM=75znj蹩ѓf=i֓f=i֓f=i֓f=Iճҳҳҳҳ3ܳ3sS'znj$RM\깩sSFM=75z2FOɜɜ鹩sSFMߞ=sS'[znjdKOɖݘݘݘݘݘ={=75znjdKMl鹩ѓ-=ғ-=75zFOdKMl鹩sSg߻ggg礠G =78^͋y3/rEμșg/jEMص{Q/rEz8#xqFJxQ /E2H"^$Ëdx /^8#xqF/E2H"^$Ëdx /z /E2HЗ }З }З }З }З }З }З }З }З }З }З }З }З }.З }.%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_=C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2%C_2U{_2%C_2%C_2%C_2%ë߳^*%^īxRUJJW>_ī|UVʊWY*+^eūxUUVʊWY*+^eūxUVʊWY*+^)*+^eūxUVʊWYJWRz{!2UʐW2!2!2!2!2!2!2!2!2!2!2!2!2! x4! dȀG2!2!2!2!2!2!2!2!2!2!2!2!2!2P'u2!2!2!2!2!2!2!2!2!2!2!2!2!2!2!2!2!2!2!2!2P2!2!2!2!2!2!2!2!2! P0@ d@ d@ɍ7&7ƛxorMM7&ƛxoMbI7$ƛxoMbI7&1$ƛxoMbMbI7&1$ƛxoVoM2I7&a(a(a(a(a(a(a(a(a(a(a(a(aȅ!aȅdJdJdJdJdJdJdJdJdJdJdJdJdJdJdzJdJdJdJdJdJdJdJdJdJdJdJdJdJdJdJdJdJdJdJdءdJdJdJdJdJdJdJdJdJjJdJdJdJdxxxR]JKw).%ޥĻ|WR]}Kw.+eŻx]mwY.+eŻx]VˊwY.+eŻx]VˊwY.+eŻx;ީNwːw.CeȻ ɍɍɍɍɍɍɍɍɍɍɍɍ_F|ɍ_Frc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fb*Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fv$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1Fc$1FcGa$Fa$ƪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzǪzbYYĜXs'j{'eMԬ9s'O98s>QoM71|'OMTĹĜ9s'*b{z&M[61ombļsssssssʟs>1|bĜ9s'O9s>1|bĜ9M9s>1|bĜ9s'O9s>1|bĴ9&OL{s>q6q61|dmdmbĜ9s'OMM98Ys>q61|‰ '*8Ys>q61|dmbĜ󉓵ZMԚob}s'N&O9s>1|bĜ &O71qkʼn[o*NLܚx_qb}&蛘5AĜ󉓵9'kM98Y8Y8Y8YjCXm~Xm~Xm~Xm~Xm~Xm~Xm~H aaaaaaaaaaaaa!>6?6?6?6?6?6?6?6?dԇ' ?iIO~𓆟4' ?iIO~𓆟4' ?iIO~𓆟4' ?iIO~𓆟4' ?iIO~𓆟4' ?iIO~𓆟4' ?iIO~_tݾE/}n_tݾE/}Qb_ž(E/}Qb_ž(E/}Qb_ž(E/}Qb_e(E/|Qf?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?Nǩ8TSq?NGӽŶyyRFXZE872E,$v8vobf7@¦]iwucwulԶ#'v=%h}3 g.RB_K}/>Ky}{}{}{}{}{}\^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Ze_-keee*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf2KYRe*T,Uf,unmRY6Kf,unmRY6Kf,unmRY6Kf,unmRY6Kf,unmRY6Kf,unmRY6KU|TiRYYYYYYY*T~Va UUUXb?ggP1 *Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*Z*V*V*V*V*V*V*V*V*V*V*V*V**V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V*V* PVaU TUUUUUUUUc+ PVVVVVVVaU TUbbbb^UŻwWkkkkU_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_U_~`51~`+~`m]jSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjSd&;5٩NMvjk&;5٩NMvjsGvٹ#;wd玣q;vGvN]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]vSe.;u٩N]u{]e.;u٩N]v]ٹ+;weuv]ٹAՠj}+*_=y_ՒVK/{_qSsjuŭo-m6g;~;p'~p#<0x ?xOxu/<~_{Um7.`>U\t{ܷqߺ}~~~[OݯA[b7޷q_[/}x8}9f*fܗV3}`wm]"~RV6[ٸoecIdaI\ %׼.uuK6ڒj%߹j% KVE~k\#%?mIW/m=~<#xq<'qOiOSOp|eq=_So[-znOpOq~^=܋p?x39G(#P9< ~G^{p/xq<9<}TϫR/z``vb _I{ ]1<}y!Oħ¨kCvq:>sF}VY5jgըϪQ_D`|o#8NG+qkCW7tovצ{ kC:Ru ^K8}ڐ gzQ>EZZZZZZ|W|W|W|W|W|W|W|W|W|W|W|W|W|W|WKK"x)2'I+i#`Hq˸zz/K_WU8qzXa,VFaEOn )_v^܇CxQ5A^iwL98hAk0}ӠM7 z4}ӠM7 2`t`A= zdA+=Es<yk=.)۟J:du}H_ !}5d(~?0w]CkHw !5+n5okߐ׾!}C^ y-C)yC 0C{wCywLJJX%*)VIJURbLJURbLJURbaVfaVfaVfaVWjX_ aVfaV]úkXw a5*úkUYeUYeUYeUu0 0 ʰn-ì2*ì2*ì2*aX? a>*ì2*ì2*ì2*ì2*Fya9*FsUYeUYe 0 0 aVfaVfaVIJUҬf4Y%*iVIJUҬf4Y%*iVIJ觍~觍~UҬ6i6i6iVI4Y%*iVIJUҬf4Y%*iVIJUҬ'iVIJUҬ'i}f4Y%*iVIJUҬf4Y%Һ(Ҭf4Y%Ҭf4Y%*iVIJUҬf4Y%ҬfKJZY%ӬևiVIJUҬf4Y%3Ӭf4Y%3Ӭf4YeUFXeUFXeUFXeUFՈW#jUFXeUFt׈]#kDwʈaVaVaVa2*#2*#2[Ftʈ~#aĸʈQ1#thʈaVaV1v#2*#2*#nUFXeUFXeUVJ^W`kKWZ^l>OSke\N=>q_Pe|%<* _soַ/V.!~??]n܋p?xa3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Ç>a3| f0Çp`3Lry*3U^Wi*i*^]e}Wj]wv}W]kwq5}׸]cNc;f4 }5 p=P?OӶ)[g96 6K_|Ƃ bM^m[c~?m??]^܇CxQTԏ~L|R?&cR?R8A6:0d<|C#Y,~Ld|Lb,"txIJ˺)3,>qE"YYYef}v /ԯfne{~[[>܏ x1msx O,x2Wx p`4xGl^qC0r5>k0kqGa>2x;y{y{{{{Cτq?6==t:ݸNGӍt:ݸN7Ӎt:ݘsߜn̹oN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tcN7tㄎЍ:j,b,baaaw'LX23;S=&H'H'LNX>3&|zD7p[Tou[mvwNwnG؃{qx9a0!<{&XtE'XtE'Xt'|y'|9/ yvB]g<5Ϯyݞg<5Ϯyvͳk^5Ϯyvͳk^5Ϯyvͳk]g<5Ϯyvͳk]g<5Ϯyvͳk]g<5Ϯyvͳk]g<5Ϯyvͳk]g<5Ϯyvͳk]g׼뮼ʳk]g<5Ϯyvͳk]g׼<5Ϯyvͳk]g<5Ϯyvͳt= i@ i@ i@ i@>çeӺnu+ӺnZMiOiȦӟ-ilwŧut%w=|?#܁;S܅y{p/xq sx/xgrٽTϫRx +XEci9?o5LVôo5LVôO}aZNnô^ i;{+Môik -L[[=i֞=iy󴮞|wi罹}a7~ji'sO:?9}>s9>Bb֭ >u.1g1g1g1gEbμbμbμbNϙW1\ͶlGy}?ďpoOpOq~Qv{{p/x!#xxOISx3xyq#~W_Q׷kxݖxoVSEG"1g1g1g1'Ssfs5g1'_sfsR6g1`.d-rS8iGWO{̙{̙{̹Vtεsm?Rw|>0'I|ʞk[8pE}q6+o}5ly߲-{>~G 'w⧸ ?OShq10&eQRczz bx()q%p#np[_Xo[ToUQ}?ďpcnOpOq~V<=3xy^KeR=J5~5`ww#cQ:c1vaWSauZ=q10~ԑWj|`Lb\u mzC:t,UEX"k}cUqXP1X/U@ULJC/[_?xE+[OO}Ӷש|EKy:?e_Wqڄ=c ~jdn}}Vw=|?#^܁;S܅y&{p/x!̏3?? w#/!?ˏl#?|GC~4o V |0va7˶Fl:[Moyķ=!G8G(?>sx OG><^x՞[q;{>p5>k0㎜|d.p,.Jd"~0]Z7j߶ǫEb2ܺ* ZI|}b֭ >uֵglylI_WUF߄mق[-m~6ߎ܉.̣<^܇C?G(884~g,xGR=J ^uo-7&اVSQwc? N\ov=^u_=G6~B8)4J''tCئtcnN󱎟>U~f1X=^Eދ?ek, C*לn _ͭF7pފor\}g n N!G⯁q f39G@m){;>_@*~&saƙC`GvWZFZHk{0 U|q>o%݀زQzsZAk埵^_Q|˳zw=|?#܁;S܅ygqe\+؍,wx/%c犹vW#YVɲJUe,dY%*YVɲJUe,dYuvYVw=]{U=kܳ=kܳ=*Ye,dY%*YVɲJUe,dY%*YVɲJU$*YVɲJU$Oe,dY%*YVɲJUe,duQVeuQUe,duWUe,.0VɲJUe,d[U{YV,daU0*YVɲ )uJVgfY%*YVɲJVgRݕzkw^{* $kVIX%WJUVqU]{*JtWݕ讄UݕJ* $J* $%aUVIX%-nIX%aUVIX%aD?$!qOX%aU\/֞J* $Jb#h&̈́UVq]X%J* $b !VY*]*[.]"p>OSk}umWSO3,>{/|_ yPJc&|ͽ6_W[z[x[˻nvwNwg{p/x!!L0qc{;akwX/]foYY`|q1pz `Lz\"0fs^zIN֝&;M_ |AnU܈5oq̭L$ON$ON$ON䤕I+QV&DMZnJԤI+QV&DM$NuIN֝&;MZwdIvdI&oJԤI+QV&+dI֝d?w|Mr$N_ 4Fp,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY',e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY`[ز,e- lY[زb)b)b)b)b)b)b)b))b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)b)c4ŖSl9ŖSl9Ŗ{17~̍ǿsI|*WEvq:>skp}K^Mɏyck~RS_ s$P s8uw:_Λ̛̛tl>^+\e'OSpʖgY|dgas7˶|o5lַu'b>ؼO}"6yǫ'w⧸ w܋p?x~$pq 9:0~N:9cμ9Ƽ̛c̛c̛c̛Wi7777WwqSgY|z]1\s%^#Mw[زսRޭރ{qxa3+񻩁qVsjW|wŚ畸kѢV-W ')|ws/k|Wԯ77f܊x&{>~6ߎ܉.܍{p/x!0x {n''qOi+%N󱎫?WõYu]?0ПOfC'_k8e{x|l 7˶~UQ 7%q!p[ }?m܎܉.߭ރ{qxy·cx>''qOiuz@=CaL>p58q Pw#ҍ<1\c~Ƿ1wqm-p:&-u`gY|w/sl+W՛/y̤hfR43)L:hfR%Yҙ%=Yғ%/qxK^ҥ%/8%/qxK^8%/8%/qxK^ҫ%Zҫ%Zҫ%Zҫ%/qxK^8%/qxK^8%/qxK^8%/qxKoK^ҷ%}[8%}[ҷ%/mK^mK%}[-qxK^ҷ%/mK^8%/qxK^%/vK^8%^;K^8%/qxK^{j')$垤c{8S,mWSOŵy|/}O^˽vUFk=7p []|#f )v^܇Ca܏ x1<''qOi<㙜sx/u«xoMxFO;{:|4>x-Ij|{0?%8L"g ߷e˞meǃmYDze?[|Pd٪Aem/hi_CuDztAɟ>/[#X].[]pؾO=,gaAe_AUxYX-ZV|P/?YFXm?^T}/e=Mm|P^3>Ṽ:gV󰽯zPtP'Q/;zPt`>xPPu_Ss<ù꭫aտ}P7a{g~?$ӅO8"P dtsQtd:6ں\[aaS_-nFMh VDHrABv2 MJ%3!8/hj~6k]wߟ42.hk]f a"F怘eUp_r`q(<p~hjJ`Vf+S3HSydrS͜r<K5!M/*K砝zpلB}.t/ߩc"cJf@;hf 5KY6ֲLoxA=؃ 6jnۭ[Fhˀm'q_cs[W?W-6>x8Cn4_=Ɂ,m0fIl%0vx~;<=r6635^62J%vX'0 o'c*2OXiPvP+̥l( ̧T; (7 jfΖٙkZ\ CvÕWA+z>J؏pk:*y4ba4{K[*bO w%ha` -1=f}{ᓥNߠL;X`1w+[5`^,{YCwݱb {cqQu}˷4˳/5ra?1y|^G(z5:6 Y;C0z8xjo_^RFs<~ZjṘ΃]zЮl0y\Wy~6zT`*osL'cL{{K3j޴>6%e7CVe5ޫ=kŽSgU#{Zg+Ro_[x2rkGA b!&Ed b7l--b:̶ p\Xd8)*"<@K3~_8\8> ɖ2^f钞|'0y% `ҵi W+zc+qՋhM7%30_w~V4!S8m݂Z|}nD)~rt-iX30ykod092&{\oU"zS}l  ,Ӡ7%5ղ%A.K`ca$I}b,UT%Ri@Z&.!)%-#+G.NNNNNNN#.!)%-#+'/] ](]$],]"]*]&].]!])]%]-]#]+]']/ ($,"*&.!)%-#+'/= =(=$=,="=*=&=.=!=)=%=-=#=+='=/ ($,"*&.!)%-#+'/} }(}$},}"}*}&}.}!})}%}-}#}+}'}/ ($,"*&.!)%YeYUYuِMLyA>Q>I>Y>E>U>M||||||||yN oW[E%eU5u M-m]=}C#cS3s K+k[;{G'gW7wO/o_ Q$EVEU4EW TKiQ(Cape2RYAVVR(++(*)+k(k*Z:ʺzʆF&XeSe2^Db+SJBiSfʖV6Jҡt*)Kqbe2YlLUS)ӕLe2[UvT)YN.ʮe7SJF*S%2RPzRRJY(U+KʀL]CSK[GWO_9@9P9($wh##ccNQNVNQN ~?E9]9C9S9K9[9G9W9O9_@PHXDTL\BRJZFVN^AQIYEUM]CSK[GWO_y@yPyHyXyDyTyLy\yByRyJyZyFyVyNy^yAyQyIyYyEyUyMy]yCySyKy[yGyWyOy_@PHXDTL\BRJZFVN^AQIYEUM]CSK%ʪꪡ*Uj-u:LPG+JueWUWSWWPT[յԵuu ՍԍMԱ8u<5ڪG\M'!lVpB SpRrՉ$u:EVnNS3ՙ,u:GAS;; TOM5jNV{ԼP]^>uZV+jUu:.SwWPTRVQUSWPTRVQUSWPTRVQUSWOPOTOROVOQOUOS^^^^^^^^^^^^^^^^ޠިޤެޢުަޮޡީޥޭޣޫާޯ>>>>>>>>>>>>>>>>~~~~~~~~~~~~~~~~MdMTMtLjLm6T Fh#Qڊhm%m֪mmmmm6i ZDjh1-%6-mmmmmmmkZҺ4WM&kSmv4m6C^fksڎR_AW+kkZ:zF&_mcz\OmzRL\BRJZ&ʂ{G]}>IOѷէ }{}>Kw;N.}7zF꾞ӻ=/W/%O_^kzD_==}}CC##ccSSggggWWWW7777wwwwA ɐ P 0 j02Z!Pc1a4V0F+1*ƪjƚF1g7&#j؆cČ0ڌntF2\c1ɘlL15ӌ c{c1˘m1v0;N.Ʈc73F3#o,4(%XlQ5jFXj ˌݍ==}}CCÌÍ##ccSSӌggggWWWW7777wwwwOOOO////ooookuƗFr p=<|ڛK615#??????LbJl*J$wideCPs9a4W0G+͕1*jf9g7'3jڦc̸0̤nvf2]s9ɜlN15ۙ s{9Ӝe6;sy|s'sgssWsi3cfM̙f7̂k͒g.6fŬ5\b.5e^>~A!aQ1q I)i33ͳ̳ssE%eU5u M-m]=}C#cS3s K+k[;{G'gW7wOr*\`fN&'?-_PT*ըN jRJh Bat8AG("MWct*]NנkV]CץtCݘnBM8:N6uhi$݌nN[ҭtN;h'M.҉tLmTFt{:΢Kw|ݙBw nԣiY=4OE@{ih]L˴BFetwݓE}~tz=DCapz=Ecqxz=DOSi?tz=EϦsy|z^D/Kerz^EkuzzDo[mvzE{}~}>DGcq}>Egsy}D_Wku}Eߦw{}~D?Ogs~Eow{D_ow2`&1!l(Ɔl$[b+l%6Val &kek:l][m6d&l,۔caQf3X%XKl %ۊmͶaub.&l ۖMe۱il:g3,6a;lG6g;.lW˱nl![ YŬ*j-aK[vg{=^loۗgA`v;gG#Qhv ;ǎg'Idv ;Ngg3Ylv;g Ebv ].gW+Ujv ]Ǯg7Mfv ngw;]nvgCa{=gO'Si {=Ǟg/Ke {^go7[m{gGc }>g_/Wk }Ǿg?Og ~g?_$KK4K ˴,jXCapk5ZehVX+[XZY[kXkZZ:nr5g&X+jٖcŬڬnuXV\k5ɚlMZYӬ k{k5˚mͱvZ;Z,C@__zrIgAhxe=.Rw/2PZ|9SVNhdbe2^d6)h߫]#`Ws B5J+lšDF[Bm)znJXiꤴWV{O Y_saLƞ'ÞCMFPʓ֔& efV%˾_,xl>O2h\ДЧ*pNޫŰETK0{bv~zCԊ^[j!>3P9lPn03PŬV kV+ ݜB3C9'Z8s75͜75.9|[!s֜2pmbIפ4t}~e\LZiQ+'D&Q:(c(((P&Q@ى2 $'?IM"nqD$&7IM"nq6T.jyg=nGvnGvnGvnG.mǬ50;i@@쎸:݃ @ഇ2G e':::NDNh'v;ډD#w?)O!~ SB?)O!~ SBw!~w!~K!zWҘT_<ѻ ѻEt]DwEt7("n{E=]p^)xP/5tJtQ6Je eee$v(;QPv M ~#AG?Dˬ=Ҕ$L"Y$LE("EQi{~{ŞF(ocOm쩍=m݂_, 3bX0cX0&!!!!!!#~aU #8#8#8#8#xJ-z0$H"$h! O x@'< 4B@|zQzQzQzQzQzQzQzQzQzQzQzQzQzQzQzQzdDQt}Qt}Qt}Qt}Qt}Qt}Qt}Qt}Qt}Qt}Qt}Qt}$#x;v;ߎ툏///////ڎSeS*-⪾0FZ+:(f{P p6.1޲Vg{KYֈ:NN v+m*a#P-A eBP&fաa?8{az(z(zhe|F+\ .UjI.l EBww_________"".⻈".⻈ﺔ4hC3cy#M[gh>"i{~ٯOZ/] 2Ú|H<>JJt!؊!?l qp3(44G57z~2V2X0~ЇbjE +2#eqܴ_(- Rn`1#Aj^wCk}͵gKK-}ZE~+䗁0 &hF/KL>- WH٘WёA, +Nz;H4Rx->`\W`lQanp\ld l\1{pa>|R#g ,'U|V(ti} $ }kZRX6|#`آX .LVXŅj~KAΊ}n?.GsNee$v(;QPv w|#C#C#C#C#C#C#C#C#C#C#C#C#C;Eqď#>F6F6F6F6F6F6F6F6FvG| m Dl cneH}k/E"yyȳͮ*ޟ\Be:zoTMB#P|Ʊij :f@ڶ^_OzYOޮ&O; Dg䕙=%mVSf{5Y(3zJ'7o`':7wׯw7_agx}5tGZ/T=R] nVyƴEKޥpP::bM^7JarOIh\(U+}/Hj-6͖R(՚G$FI"Z'CfN9*Ft^'6H6"6"v'> ag̈́M.3BqӚiWIJF:Ԧ֦5ٕƍm7O6t߉EԲFE. ;D&ۡNl5TB69?m P{jQЛ.2g4*7ԊPg7:5q?0QfWl2F!z2I^9 V0kB i|wDW=pjAj0:m"_Cnنo0nKD̿777/4k77_mָ0&W̟i2AY,o~o7H6 8X٦uݴ٦UX B^lZUi_ŵ84CWRsG!櫢PK)12qjAcdoYlzcJ:Sq𙊃T|38Lg*>Sq𙊃T|38Lg*>Sq𙊃Tv@||t >Vp𵂃@||c;;;487 ipMA 4848%>-qiOK|Z`8P7 NMo|8)w8{/ LwC7񵃃|t!|8,>`qX|888,>`qC)~ )~ "4 ,Je8X1|Fg1۱1q m(ݎe'.]bA|wA|<^ x1<^ x1<^ x1<^ xX|3"Dp@kgx sU^bT7Ob7D&,'b.U"fy2BE^ [ɆDxgYiH^~2J~kg-U=n~r+-rp;([UgՄV7{ˢ_뉬Ȫ+@P^r~Aμv` "GX!T.˥Lsc.)ܦenJ5^,+Jpؠ@1_􃦁fo>S\M{-ZTE"8L\D9a7'aMU6|*0SdBKQ:(c(((P&Q@ى2 @@@@@@@@NO%H!H!H!H!H!H!H!B.B.B.B.B.B.B.B.wE|]wE(yq>8lO6'瓍d|q>8lO6'瓍d|q>8lO6'瓍d|q>8lO6'瓍d|q>ٝ߉߉߉߉߉߉߉ylf8m~a-f nt eee$K5Z.Je2r | (m","",""DLDH XFE4&5J,_ DKDKDKDKDQEma# ma-l6ۈo#6ۈo#6ۈov^.kY8Ap,d Y8ApVbh?`Pg6r}!r!r!XjR*UO+u-GVqJG*$hhyh\)I}h'I 2I 2I Om@$& I߆m߆m߆m߆m߆m߆m߆m߆mD$'?IO"~񓈟D$'?aaaaay?a҈F4?iO#~ӈF4zW0z3A g> |3A g~3A,g?Y"~񳈟E,g?Y"~">#>#>#>#~s}apA by_l@"vAFQ(1q m((QvDBم2 M\t.yݼnE7wѭE/xCF(u]t.n]ۍ"^a?t.n]Evu]t.nF|mķF|wNEvI]sA]<*xTvQţGe.]<*xTvQţGe.]<*xTvQ#Gd.]<"xDv;:_WK'˴SCyC'26ce.]<.x\vvvZvAW{륥yo8gO.]<=xZviӲe7+5|O<*]<3xfv3gf.]<3xfvvu挆dJyaQ<.x\v".B"۩yQ:(c(((P&QMN̟;3|PF8a|w PnP܌Z|%S*¿PS a=T  %$BQD"е(%l9BCKD]|x؛/r7Y\}٪ЦB2^ٯm_)xPsR(PtЌ9qs;͂D:C7171ď!~ cC?1ď!~ G8?w9%D%x1Pl V% D,7"|_oZ\ Ԉ>b 3甛ss!3B\ׇY#oԁ:g"{&*=gDhOF9M}\5Jh%qΐL|wW)זrI-˞WXU+P"ަ,)h-ծZq@ȢYt 8g8GX/X/X/R8S8׳vpgxAE[eJ}G<|G<|G<|M^&SP/-ܔtO@d}sl[^i]5͌ lk,-1 }ՖI邗YT𫰑+WECB|!]p4`NΕEZ٘V jێ2 kN"'n[-{2#j8Pv3Uef: /MJEب+~?/h&L g7q m((9L3J@ alt2qmĵF\qm Dv8ttt`;> ɗ6&T[Gpߏ}?~$N  -+Vw-L`DDDDD؅8#8#8cW8,]h'? O >F '? O ~@'r+KK76Vc\ :jiŲE 0׫F/g_1a ? ;*V+wU<ܣhxc Nߠ_ &ÃXhFÃM24e㋲C/6R-}~#dz|n*VP"D/%Jzz6{ gɁpЏ?IɱDO?LN ə<χ?\@.r*Я?\CnFMv?I~@ п$_5( #RDFJ>N=-e@J}/ʠW]$/EM> [@U AG/AJ aDQ+h"YH[H**DV/"rR1_ eD20 =_!J;6` 3 ẑ9л< E>׃~y{iK]"d4ЧoOΤA߉tw{7}龠GaHЏǂ~=);= )tϠg~&=(ؖM/Bz!ы@^ %/07o7~^ @a(}7I-oӏ@~ 'kп߀-`v3I$tn1 2諰U@_lma1M&ecAߔm 86 l&Ob@&>M}[-SLgYfs@߁\#<3qa;]A_@O3,z@ϳ< B1J1l11e{=@ߓd{A߇}/ۏAe~;#ّŎhv60X|v'w1#ؽ'fL":k(,Xpk8#,X/*ֺgohfZ`k!j|r+)wlHRiMfQ?r@_*c"rZ ^H-$b]6T[~^BaF[CNA ~['DO[DTd^D^x^J\K\K\K\x=xeJKKK\Kyy y+q0/q /?/r%%%%%vI0*PGX=LޔLhe4aÜq4ټb_ɪҫʁM<=&cӣ A,e\!0 srmfu3ֺkj*y'߉`[š| 5o[1Q.ֿwcR|{1NӚ "B```Ov@d)`1b5'|pY}Z/෧:\AWw׻n~_~}_ׇ~}_'~}_Ip} ۿ[׺)IiBhrfMcԠ j:(fw`ۘALa ,V뮃*?E[= ?5 ~k{]Emerޱd( Mt- d3}Γq'SDm6Uh mfԵ üB%˳Wߜ~o:v/Yv$ {)ُaǿ0^_5URimiH],!$#&/])16Wh; m mg"]@h ZZhe?!yкZB[(EB+WhE'B+ "jB- ZV? vV ~uư'heZ mo M4 ;l vdgؑ2؍.Hy؁>&ߒ%NH™Mꐦ+?;ځB;Hh *ÄvЎQB;ZhX/vN)B;Uh ?B;]hg l5#7w9-̈́q[^{ x4jM>6 Va+7ޫ_y~m]Vx#9Fp{\  ga"/9 sl5~g #`;]::h֓) Zޯ&@xnS&Fنz[tGd6AAgpk޴r5knh.8֖k xIޯ6f&Xk3'3۰h0,R#tpm϶3<,gfPk{k5xg]0`̃'mkϢ3gvp)"rр0 *R>(#PG7DH**^7l)IP"BV"ywYԶsι;DZ'S}9o(i$t5tgxw%wG92a<[7=#k}B3噮e_c0JBnxI,?=K\5Kw'F ѿ^;R\Un[趺z \H/ӥz'46R(er*sd,d+[co<:~fnƛfYd4,Wd>O^O6>&P!n I69~9|p۔PjگBmZ z77l=43ۨ~:t~9}hϹs}ν|3?PFu9^(Gw:5WZvb!ʍБwX,9dMڀt>??M14<*Pۥg&5\Hօ\!SW'@gzަ M#HE= a%цX{>Az1Jd=9;KxyH/K@^ӫB6M`";u3L ~l8],&H+ѷ/'ɢZRq-Qn'.H>'wb"Ȣsiy1V_H}#H??!q稟IU};  vR`=}ԥдJy=),>,>o!  `3#4203*]uի[eį6ʤ (]Gާ*p73xq7P&.XMx8-ˈoEqhI=xJENAHf@r `Z%-!m  !7K"@. \ 2rV ݐ9yv! !B^[6"2rp&nWDXqmQy[w/}#U3bϒQ#3MԯVΜȌH&H6=88bUݿ3OO:ĩ#fjU ~}Fr>uoI_"Bt;Q>nuwS ܎> [g3 wF9cdg3ݙv:8;g"|qbDIz9XGգ?^8{5DQGMPQTZsc|sun;Q3 d13bfErK^Vf܏nvduYdlVߗC5]w\>OIT|)+J"ɨFSt(1_\kY yR rH)#Ȝ6؞~=Y":iۧ:G/?:-⎎;jU;4WQ\(O=W%p7ddyd'&hKP@Ѕ ;@/2s d\Xgqij߼+$UjLq,SV) ,W%jh)>N[)~Vp[%Z)TZfŭ/Sev{TWT@[Ͼ*+8ǗVߓ#V,F;CYo[k%z VgRNe03Ur) m~+9s3PXsR;z*櫔Zi0`W&J5,&*_`sQ]Ma{4Rb̕W :-( U=uZ8t6c; . s(%GhFfSX*4p5Qhd-pAm@ϛdf4rv4A0ZL}S6MMX8:O穤nn[[bҭo:_ꮪ.D6gc'abDݍ}۹ݦ{=\^Ž.^y݀^*ǻdf3#h&xPͬo MxEZ~uQ>U?DK`cV?GQhiu Z=\S_'=}.e^6o\4IzQ/X?A3 Z7 >VADs7ќ#"f Fs;hzQ1 n>Bsفz}+ȔN$ƍ:bX:!;$FO'Sn!zlTeImleVXa1}>Qe,Oէ\^vӁp7e)(,ݱJ1{-E&^`ψz]6.BΘ1Fc^tx%KNPRR͕!ٓYmڠʴEv@U)@5*r&FY_ݦj@TwY?~hg_W"7 7{[ 2: 囪ߖ|{ŕOK.^{u8=W&[ce@u Ym?%B#wTJ MjT7 ᝢ\e,1w 7+ eE|!PºbXWX]\崭(qV+JcEqXQb(NPQ,ҨX[-\V aV apX' ^GVQo 끰+J8>[ </b.k2y/xa s=,O0s:lc6{fyg-=fˬk`&I楃̃GD[8$=k$뿦Vފ[)z[.e-^X5[~JO~2OB?f4!BOxGOx'4= MO$=''RDH)z"EOz£'0As0x/=3>2κ͊1`^ ]yz\="|.RϨg1/a>_QKԫեeOٿ`Fc&W"D~ 3C}L%1C130#00;;J CB\K^u)Q5N[NJnmG7?+`K^^rw-f#9"sq`]ڊ#ʃb7R/kRٲe'_''ɓ݀YEX\,λ\\,I. K2S4+g:rX9Y93B#ib.ss!s1Q\\b.6 xx\,b435L͊Tjqt-ΕfZ<+'³r"<+\=z[%cw]2ve3.ptY rɿb ȿЀ˯ ȿ YrXrXrȶ Yd[ $D#$E#$kF#(Xlr74[Vz٬\)5&Mvci@vכdgqVdg~iHv`]&2*$f8췯ע͉Q&.'GIlol/2:jܑ\[OL/Z|ѺoϲmW;O_ЯYDH."DD3DIVɬnYjxlxqsJNx ^8¯)̵D/o/쪘+׬@qP]˸WETGR<(}6,Bi$ FaH4VčU.g,b2!AMEֲZk1ֲӃǷekN]X֬j5oVdU>VT̔_!#kԿfW6U7# !v0bd5L~lyJEf}\V3]4f_!_c}y.D+edX袲h3\]oW`&`4dا)bn6sʘf;g4wrxybbn07ۗ)f|<3=dB6%5i r0đ\sp64+wj?WPKa\'Ofonts/freemono.phpnuW+A33,'FontBBox'=>'[-793 -200 699 800]','ItalicAngle'=>0,'Ascent'=>800,'Descent'=>-200,'Leading'=>90,'CapHeight'=>563,'XHeight'=>417,'StemV'=>70,'StemH'=>30,'AvgWidth'=>600,'MaxWidth'=>600,'MissingWidth'=>600); $cw=array(0=>0,1=>600,2=>600,3=>600,4=>600,5=>600,6=>600,7=>600,8=>0,9=>600,10=>600,11=>600,12=>600,13=>600,14=>600,15=>600,16=>600,17=>600,18=>600,19=>600,20=>600,21=>600,22=>600,23=>600,24=>600,25=>600,26=>600,27=>600,28=>600,29=>0,30=>600,31=>600,32=>600,33=>600,34=>600,35=>600,36=>600,37=>600,38=>600,39=>600,40=>600,41=>600,42=>600,43=>600,44=>600,45=>600,46=>600,47=>600,48=>600,49=>600,50=>600,51=>600,52=>600,53=>600,54=>600,55=>600,56=>600,57=>600,58=>600,59=>600,60=>600,61=>600,62=>600,63=>600,64=>600,65=>600,66=>600,67=>600,68=>600,69=>600,70=>600,71=>600,72=>600,73=>600,74=>600,75=>600,76=>600,77=>600,78=>600,79=>600,80=>600,81=>600,82=>600,83=>600,84=>600,85=>600,86=>600,87=>600,88=>600,89=>600,90=>600,91=>600,92=>600,93=>600,94=>600,95=>600,96=>600,97=>600,98=>600,99=>600,100=>600,101=>600,102=>600,103=>600,104=>600,105=>600,106=>600,107=>600,108=>600,109=>600,110=>600,111=>600,112=>600,113=>600,114=>600,115=>600,116=>600,117=>600,118=>600,119=>600,120=>600,121=>600,122=>600,123=>600,124=>600,125=>600,126=>600,127=>600,128=>600,129=>600,130=>600,131=>600,132=>600,133=>600,134=>600,135=>600,136=>600,137=>600,138=>600,139=>600,140=>600,141=>600,142=>600,143=>600,144=>600,145=>600,146=>600,147=>600,148=>600,149=>600,150=>600,151=>600,152=>600,153=>600,154=>600,155=>600,156=>600,157=>600,158=>600,159=>600,160=>600,161=>600,162=>600,163=>600,164=>600,165=>600,166=>600,167=>600,168=>600,169=>600,170=>600,171=>600,172=>600,173=>600,174=>600,175=>600,176=>600,177=>600,178=>600,179=>600,180=>600,181=>600,182=>600,183=>600,184=>600,185=>600,186=>600,187=>600,188=>600,189=>600,190=>600,191=>600,192=>600,193=>600,194=>600,195=>600,196=>600,197=>600,198=>600,199=>600,200=>600,201=>600,202=>600,203=>600,204=>600,205=>600,206=>600,207=>600,208=>600,209=>600,210=>600,211=>600,212=>600,213=>600,214=>600,215=>600,216=>600,217=>600,218=>600,219=>600,220=>600,221=>600,222=>600,223=>600,224=>600,225=>600,226=>600,227=>600,228=>600,229=>600,230=>600,231=>600,232=>600,233=>600,234=>600,235=>600,236=>600,237=>600,238=>600,239=>600,240=>600,241=>600,242=>600,243=>600,244=>600,245=>600,246=>600,247=>600,248=>600,249=>600,250=>600,251=>600,252=>600,253=>600,254=>600,255=>600,256=>600,257=>600,258=>600,259=>600,260=>600,261=>600,262=>600,263=>600,264=>600,265=>600,266=>600,267=>600,268=>600,269=>600,270=>600,271=>600,272=>600,273=>600,274=>600,275=>600,276=>600,277=>600,278=>600,279=>600,280=>600,281=>600,282=>600,283=>600,284=>600,285=>600,286=>600,287=>600,288=>600,289=>600,290=>600,291=>600,292=>600,293=>600,294=>600,295=>600,296=>600,297=>600,298=>600,299=>600,300=>600,301=>600,302=>600,303=>600,304=>600,305=>600,306=>600,307=>600,308=>600,309=>600,310=>600,311=>600,312=>600,313=>600,314=>600,315=>600,316=>600,317=>600,318=>600,319=>600,320=>600,321=>600,322=>600,323=>600,324=>600,325=>600,326=>600,327=>600,328=>600,329=>600,330=>600,331=>600,332=>600,333=>600,334=>600,335=>600,336=>600,337=>600,338=>600,339=>600,340=>600,341=>600,342=>600,343=>600,344=>600,345=>600,346=>600,347=>600,348=>600,349=>600,350=>600,351=>600,352=>600,353=>600,354=>600,355=>600,356=>600,357=>600,358=>600,359=>600,360=>600,361=>600,362=>600,363=>600,364=>600,365=>600,366=>600,367=>600,368=>600,369=>600,370=>600,371=>600,372=>600,373=>600,374=>600,375=>600,376=>600,377=>600,378=>600,379=>600,380=>600,381=>600,382=>600,383=>600,384=>600,385=>600,386=>600,387=>600,388=>600,389=>600,390=>600,391=>600,392=>600,393=>600,394=>600,395=>600,396=>600,397=>600,398=>600,399=>600,400=>600,401=>600,402=>600,403=>600,404=>600,405=>600,406=>600,407=>600,408=>600,409=>600,410=>600,411=>600,412=>600,413=>600,414=>600,415=>600,416=>600,417=>600,418=>600,419=>600,420=>600,421=>600,422=>600,423=>600,424=>600,425=>600,426=>600,427=>600,428=>600,429=>600,430=>600,431=>600,432=>600,433=>600,434=>600,435=>600,436=>600,437=>600,438=>600,439=>600,440=>600,441=>600,442=>600,443=>600,444=>600,445=>600,446=>600,447=>600,448=>600,449=>600,450=>600,451=>600,452=>600,453=>600,454=>600,455=>600,456=>600,457=>600,458=>600,459=>600,460=>600,461=>600,462=>600,463=>600,464=>600,465=>600,466=>600,467=>600,468=>600,469=>600,470=>600,471=>600,472=>600,473=>600,474=>600,475=>600,476=>600,477=>600,478=>600,479=>600,480=>600,481=>600,482=>600,483=>600,484=>600,485=>600,486=>600,487=>600,488=>600,489=>600,490=>600,491=>600,492=>600,493=>600,494=>600,495=>600,496=>600,497=>600,498=>600,499=>600,500=>600,501=>600,502=>600,503=>600,504=>600,505=>600,506=>600,507=>600,508=>600,509=>600,510=>600,511=>600,512=>600,513=>600,514=>600,515=>600,516=>600,517=>600,518=>600,519=>600,520=>600,521=>600,522=>600,523=>600,524=>600,525=>600,526=>600,527=>600,528=>600,529=>600,530=>600,531=>600,532=>600,533=>600,534=>600,535=>600,536=>600,537=>600,538=>600,539=>600,540=>600,541=>600,542=>600,543=>600,544=>600,548=>600,549=>600,550=>600,551=>600,552=>600,553=>600,554=>600,555=>600,556=>600,557=>600,558=>600,559=>600,560=>600,561=>600,562=>600,563=>600,567=>600,592=>600,593=>600,594=>600,595=>600,596=>600,597=>600,598=>600,599=>600,600=>600,601=>600,602=>600,603=>600,604=>600,605=>600,606=>600,607=>600,608=>600,609=>600,610=>600,611=>600,612=>600,613=>600,614=>600,615=>600,616=>600,617=>600,618=>600,619=>600,620=>600,621=>600,622=>600,623=>600,624=>600,625=>600,626=>600,627=>600,628=>600,629=>600,630=>600,631=>600,632=>600,633=>600,634=>600,635=>600,636=>600,637=>600,638=>600,639=>600,640=>600,641=>600,642=>600,643=>600,644=>600,645=>600,646=>600,647=>600,648=>600,649=>600,650=>600,651=>600,652=>600,653=>600,654=>600,655=>600,656=>600,657=>600,658=>600,659=>600,660=>600,661=>600,662=>600,663=>600,664=>600,665=>600,666=>600,667=>600,668=>600,669=>600,670=>600,671=>600,672=>600,673=>600,674=>600,675=>600,676=>600,677=>600,678=>600,679=>600,680=>600,681=>600,682=>600,683=>600,684=>600,685=>600,686=>600,687=>600,688=>600,689=>600,690=>600,691=>600,692=>600,693=>600,694=>600,695=>600,696=>600,697=>600,698=>600,699=>600,700=>600,701=>600,702=>600,703=>600,704=>600,705=>600,706=>600,707=>600,708=>600,709=>600,710=>600,711=>600,712=>600,713=>600,714=>600,715=>600,716=>600,717=>600,718=>600,719=>600,720=>600,721=>600,722=>600,723=>600,724=>600,725=>600,726=>600,727=>600,728=>600,729=>600,730=>600,731=>600,732=>600,733=>600,734=>600,735=>600,736=>600,737=>600,738=>600,739=>600,740=>600,741=>600,742=>600,743=>600,744=>600,745=>600,746=>600,747=>600,748=>600,749=>600,750=>600,751=>600,752=>600,753=>600,754=>600,755=>600,756=>600,757=>600,758=>600,759=>600,760=>600,761=>600,762=>600,763=>600,764=>600,765=>600,766=>600,767=>600,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,843=>0,844=>0,845=>0,848=>0,849=>0,850=>0,851=>0,852=>0,853=>0,854=>0,855=>0,856=>0,857=>0,858=>0,884=>600,885=>600,890=>600,894=>600,900=>600,901=>600,902=>600,903=>600,904=>600,905=>600,906=>600,908=>600,910=>600,911=>600,912=>600,913=>600,914=>600,915=>600,916=>600,917=>600,918=>600,919=>600,920=>600,921=>600,922=>600,923=>600,924=>600,925=>600,926=>600,927=>600,928=>600,929=>600,931=>600,932=>600,933=>600,934=>600,935=>600,936=>600,937=>600,938=>600,939=>600,940=>600,941=>600,942=>600,943=>600,944=>600,945=>600,946=>600,947=>600,948=>600,949=>600,950=>600,951=>600,952=>600,953=>600,954=>600,955=>600,956=>600,957=>600,958=>600,959=>600,960=>600,961=>600,962=>600,963=>600,964=>600,965=>600,966=>600,967=>600,968=>600,969=>600,970=>600,971=>600,972=>600,973=>600,974=>600,976=>600,977=>600,978=>600,979=>600,980=>600,981=>600,982=>600,986=>600,987=>600,988=>600,1008=>600,1009=>600,1012=>600,1013=>600,1024=>600,1025=>600,1026=>600,1027=>600,1028=>600,1029=>600,1030=>600,1031=>600,1032=>600,1033=>600,1034=>600,1035=>600,1036=>600,1037=>600,1038=>600,1039=>600,1040=>600,1041=>600,1042=>600,1043=>600,1044=>600,1045=>600,1046=>600,1047=>600,1048=>600,1049=>600,1050=>600,1051=>600,1052=>600,1053=>600,1054=>600,1055=>600,1056=>600,1057=>600,1058=>600,1059=>600,1060=>600,1061=>600,1062=>600,1063=>600,1064=>600,1065=>600,1066=>600,1067=>600,1068=>600,1069=>600,1070=>600,1071=>600,1072=>600,1073=>600,1074=>600,1075=>600,1076=>600,1077=>600,1078=>600,1079=>600,1080=>600,1081=>600,1082=>600,1083=>600,1084=>600,1085=>600,1086=>600,1087=>600,1088=>600,1089=>600,1090=>600,1091=>600,1092=>600,1093=>600,1094=>600,1095=>600,1096=>600,1097=>600,1098=>600,1099=>600,1100=>600,1101=>600,1102=>600,1103=>600,1104=>600,1105=>600,1106=>600,1107=>600,1108=>600,1109=>600,1110=>600,1111=>600,1112=>600,1113=>600,1114=>600,1115=>600,1116=>600,1117=>600,1118=>600,1119=>600,1120=>600,1121=>600,1122=>600,1123=>600,1124=>600,1126=>600,1127=>600,1128=>600,1130=>600,1131=>600,1132=>600,1133=>600,1136=>600,1137=>600,1138=>600,1140=>600,1141=>600,1142=>600,1143=>600,1148=>600,1149=>600,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1162=>600,1163=>600,1164=>600,1165=>600,1166=>600,1167=>600,1168=>600,1169=>600,1170=>600,1171=>600,1172=>600,1173=>600,1174=>600,1175=>600,1176=>600,1177=>600,1178=>600,1179=>600,1180=>600,1181=>600,1182=>600,1183=>600,1184=>600,1185=>600,1186=>600,1187=>600,1188=>600,1189=>600,1190=>600,1191=>600,1192=>600,1193=>600,1194=>600,1195=>600,1196=>600,1197=>600,1198=>600,1199=>600,1200=>600,1201=>600,1202=>600,1203=>600,1204=>600,1205=>600,1206=>600,1207=>600,1208=>600,1209=>600,1210=>600,1211=>600,1212=>600,1213=>600,1214=>600,1215=>600,1216=>600,1217=>600,1218=>600,1219=>600,1220=>600,1221=>600,1222=>600,1223=>600,1224=>600,1225=>600,1226=>600,1227=>600,1228=>600,1229=>600,1230=>600,1231=>600,1232=>600,1233=>600,1234=>600,1235=>600,1236=>600,1237=>600,1238=>600,1239=>600,1240=>600,1241=>600,1242=>600,1243=>600,1244=>600,1245=>600,1246=>600,1247=>600,1248=>600,1249=>600,1250=>600,1251=>600,1252=>600,1253=>600,1254=>600,1255=>600,1256=>600,1257=>600,1258=>600,1259=>600,1260=>600,1261=>600,1262=>600,1263=>600,1264=>600,1265=>600,1266=>600,1267=>600,1268=>600,1269=>600,1270=>600,1271=>600,1272=>600,1273=>600,1296=>600,1297=>600,1298=>600,1299=>600,1306=>600,1307=>600,1308=>600,1309=>600,1310=>600,1311=>600,1329=>600,1330=>600,1331=>600,1332=>600,1333=>600,1334=>600,1335=>600,1336=>600,1337=>600,1338=>600,1339=>600,1340=>600,1341=>600,1342=>600,1343=>600,1344=>600,1345=>600,1346=>600,1347=>600,1348=>600,1349=>600,1350=>600,1351=>600,1352=>600,1353=>600,1354=>600,1355=>600,1356=>600,1357=>600,1358=>600,1359=>600,1360=>600,1361=>600,1362=>600,1363=>600,1364=>600,1365=>600,1366=>600,1369=>600,1370=>600,1371=>600,1372=>600,1373=>600,1374=>600,1375=>600,1377=>600,1378=>600,1379=>600,1380=>600,1381=>600,1382=>600,1383=>600,1384=>600,1385=>600,1386=>600,1387=>600,1388=>600,1389=>600,1390=>600,1391=>600,1392=>600,1393=>600,1394=>600,1395=>600,1396=>600,1397=>600,1398=>600,1399=>600,1400=>600,1401=>600,1402=>600,1403=>600,1404=>600,1405=>600,1406=>600,1407=>600,1408=>600,1409=>600,1410=>600,1411=>600,1412=>600,1413=>600,1414=>600,1415=>600,1417=>600,1418=>600,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1467=>0,1468=>0,1469=>0,1470=>600,1471=>0,1472=>600,1473=>0,1474=>0,1475=>600,1476=>0,1488=>600,1489=>600,1490=>600,1491=>600,1492=>600,1493=>600,1494=>600,1495=>600,1496=>600,1497=>600,1498=>600,1499=>600,1500=>600,1501=>600,1502=>600,1503=>600,1504=>600,1505=>600,1506=>600,1507=>600,1508=>600,1509=>600,1510=>600,1511=>600,1512=>600,1513=>600,1514=>600,1520=>600,1521=>600,1522=>600,1523=>600,1524=>600,4304=>600,4305=>600,4306=>600,4307=>600,4308=>600,4309=>600,4310=>600,4311=>600,4312=>600,4313=>600,4314=>600,4315=>600,4316=>600,4317=>600,4318=>600,4319=>600,4320=>600,4321=>600,4322=>600,4323=>600,4324=>600,4325=>600,4326=>600,4327=>600,4328=>600,4329=>600,4330=>600,4331=>600,4332=>600,4333=>600,4334=>600,4335=>600,4336=>600,4337=>600,4338=>600,4339=>600,4340=>600,4341=>600,4345=>600,4347=>600,4348=>600,5024=>600,5025=>600,5026=>600,5027=>600,5028=>600,5029=>600,5030=>600,5031=>600,5032=>600,5033=>600,5034=>600,5035=>600,5036=>600,5037=>600,5038=>600,5039=>600,5040=>600,5041=>600,5042=>600,5043=>600,5044=>600,5045=>600,5046=>600,5047=>600,5048=>600,5049=>600,5050=>600,5051=>600,5052=>600,5053=>600,5054=>600,5055=>600,5056=>600,5057=>600,5058=>600,5059=>600,5060=>600,5061=>600,5062=>600,5063=>600,5064=>600,5065=>600,5066=>600,5067=>600,5068=>600,5069=>600,5070=>600,5071=>600,5072=>600,5073=>600,5074=>600,5075=>600,5076=>600,5077=>600,5078=>600,5079=>600,5080=>600,5081=>600,5082=>600,5083=>600,5084=>600,5085=>600,5086=>600,5087=>600,5088=>600,5089=>600,5090=>600,5091=>600,5092=>600,5093=>600,5094=>600,5095=>600,5096=>600,5097=>600,5098=>600,5099=>600,5100=>600,5101=>600,5102=>600,5103=>600,5104=>600,5105=>600,5106=>600,5107=>600,5108=>600,5792=>600,5793=>600,5794=>600,5795=>600,5796=>600,5797=>600,5798=>600,5799=>600,5800=>600,5801=>600,5802=>600,5803=>600,5804=>600,5805=>600,5806=>600,5807=>600,5808=>600,5809=>600,5810=>600,5811=>600,5812=>600,5813=>600,5814=>600,5815=>600,5816=>600,5817=>600,5818=>600,5819=>600,5820=>600,5821=>600,5822=>600,5823=>600,5824=>600,5825=>600,5826=>600,5827=>600,5828=>600,5829=>600,5830=>600,5831=>600,5832=>600,5833=>600,5834=>600,5835=>600,5836=>600,5837=>600,5838=>600,5839=>600,5840=>600,5841=>600,5842=>600,5843=>600,5844=>600,5845=>600,5846=>600,5847=>600,5848=>600,5849=>600,5850=>600,5851=>600,5852=>600,5853=>600,5854=>600,5855=>600,5856=>600,5857=>600,5858=>600,5859=>600,5860=>600,5861=>600,5862=>600,5863=>600,5864=>600,5865=>600,5866=>600,5867=>600,5868=>600,5869=>600,5870=>600,5871=>600,5872=>600,7680=>600,7681=>600,7682=>600,7683=>600,7684=>600,7685=>600,7686=>600,7687=>600,7688=>600,7689=>600,7690=>600,7691=>600,7692=>600,7693=>600,7694=>600,7695=>600,7696=>600,7697=>600,7698=>600,7699=>600,7700=>600,7701=>600,7702=>600,7703=>600,7704=>600,7705=>600,7706=>600,7707=>600,7708=>600,7709=>600,7710=>600,7711=>600,7712=>600,7713=>600,7714=>600,7715=>600,7716=>600,7717=>600,7718=>600,7719=>600,7720=>600,7721=>600,7722=>600,7723=>600,7724=>600,7725=>600,7726=>600,7727=>600,7728=>600,7729=>600,7730=>600,7731=>600,7732=>600,7733=>600,7734=>600,7735=>600,7736=>600,7737=>600,7738=>600,7739=>600,7740=>600,7741=>600,7742=>600,7743=>600,7744=>600,7745=>600,7746=>600,7747=>600,7748=>600,7749=>600,7750=>600,7751=>600,7752=>600,7753=>600,7754=>600,7755=>600,7756=>600,7757=>600,7758=>600,7759=>600,7760=>600,7761=>600,7762=>600,7763=>600,7764=>600,7765=>600,7766=>600,7767=>600,7768=>600,7769=>600,7770=>600,7771=>600,7772=>600,7773=>600,7774=>600,7775=>600,7776=>600,7777=>600,7778=>600,7779=>600,7780=>600,7781=>600,7782=>600,7783=>600,7784=>600,7785=>600,7786=>600,7787=>600,7788=>600,7789=>600,7790=>600,7791=>600,7792=>600,7793=>600,7794=>600,7795=>600,7796=>600,7797=>600,7798=>600,7799=>600,7800=>600,7801=>600,7802=>600,7803=>600,7804=>600,7805=>600,7806=>600,7807=>600,7808=>600,7809=>600,7810=>600,7811=>600,7812=>600,7813=>600,7814=>600,7815=>600,7816=>600,7817=>600,7818=>600,7819=>600,7820=>600,7821=>600,7822=>600,7823=>600,7824=>600,7825=>600,7826=>600,7827=>600,7828=>600,7829=>600,7830=>600,7831=>600,7832=>600,7833=>600,7834=>600,7835=>600,7840=>600,7841=>600,7842=>600,7843=>600,7844=>600,7845=>600,7846=>600,7847=>600,7848=>600,7849=>600,7850=>600,7851=>600,7852=>600,7853=>600,7854=>600,7855=>600,7856=>600,7857=>600,7858=>600,7859=>600,7860=>600,7861=>600,7862=>600,7863=>600,7864=>600,7865=>600,7866=>600,7867=>600,7868=>600,7869=>600,7870=>600,7871=>600,7872=>600,7873=>600,7874=>600,7875=>600,7876=>600,7877=>600,7878=>600,7879=>600,7880=>600,7881=>600,7882=>600,7883=>600,7884=>600,7885=>600,7886=>600,7887=>600,7888=>600,7889=>600,7890=>600,7891=>600,7892=>600,7893=>600,7894=>600,7895=>600,7896=>600,7897=>600,7898=>600,7899=>600,7900=>600,7901=>600,7902=>600,7903=>600,7904=>600,7905=>600,7906=>600,7907=>600,7908=>600,7909=>600,7910=>600,7911=>600,7912=>600,7913=>600,7914=>600,7915=>600,7916=>600,7917=>600,7918=>600,7919=>600,7920=>600,7921=>600,7922=>600,7923=>600,7924=>600,7925=>600,7926=>600,7927=>600,7928=>600,7929=>600,7936=>600,7937=>600,7938=>600,7939=>600,7940=>600,7941=>600,7942=>600,7943=>600,7944=>600,7945=>600,7946=>600,7947=>600,7948=>600,7949=>600,7950=>600,7951=>600,7952=>600,7953=>600,7954=>600,7955=>600,7956=>600,7957=>600,7960=>600,7961=>600,7962=>600,7963=>600,7964=>600,7965=>600,7968=>600,7969=>600,7970=>600,7971=>600,7972=>600,7973=>600,7974=>600,7975=>600,7976=>600,7977=>600,7978=>600,7979=>600,7980=>600,7981=>600,7982=>600,7983=>600,7984=>600,7985=>600,7986=>600,7987=>600,7988=>600,7989=>600,7990=>600,7991=>600,7992=>600,7993=>600,7994=>600,7995=>600,7996=>600,7997=>600,7998=>600,7999=>600,8000=>600,8001=>600,8002=>600,8003=>600,8004=>600,8005=>600,8008=>600,8009=>600,8010=>600,8011=>600,8012=>600,8013=>600,8016=>600,8017=>600,8018=>600,8019=>600,8020=>600,8021=>600,8022=>600,8023=>600,8025=>600,8027=>600,8029=>600,8031=>600,8032=>600,8033=>600,8034=>600,8035=>600,8036=>600,8037=>600,8038=>600,8039=>600,8040=>600,8041=>600,8042=>600,8043=>600,8044=>600,8045=>600,8046=>600,8047=>600,8048=>600,8049=>600,8050=>600,8051=>600,8052=>600,8053=>600,8054=>600,8055=>600,8056=>600,8057=>600,8058=>600,8059=>600,8060=>600,8061=>600,8064=>600,8065=>600,8066=>600,8067=>600,8068=>600,8069=>600,8070=>600,8071=>600,8072=>600,8073=>600,8074=>600,8075=>600,8076=>600,8077=>600,8078=>600,8079=>600,8080=>600,8081=>600,8082=>600,8083=>600,8084=>600,8085=>600,8086=>600,8087=>600,8088=>600,8089=>600,8090=>600,8091=>600,8092=>600,8093=>600,8094=>600,8095=>600,8096=>600,8097=>600,8098=>600,8099=>600,8100=>600,8101=>600,8102=>600,8103=>600,8104=>600,8105=>600,8106=>600,8107=>600,8108=>600,8109=>600,8110=>600,8111=>600,8112=>600,8113=>600,8114=>600,8115=>600,8116=>600,8118=>600,8119=>600,8120=>600,8121=>600,8122=>600,8123=>600,8124=>600,8125=>600,8126=>600,8127=>600,8128=>600,8129=>600,8130=>600,8131=>600,8132=>600,8134=>600,8135=>600,8136=>600,8137=>600,8138=>600,8139=>600,8140=>600,8141=>600,8142=>600,8143=>600,8144=>600,8145=>600,8146=>600,8147=>600,8150=>600,8151=>600,8152=>600,8153=>600,8154=>600,8155=>600,8157=>600,8158=>600,8159=>600,8160=>600,8161=>600,8162=>600,8163=>600,8164=>600,8165=>600,8166=>600,8167=>600,8168=>600,8169=>600,8170=>600,8171=>600,8172=>600,8173=>600,8174=>600,8175=>600,8178=>600,8179=>600,8180=>600,8182=>600,8183=>600,8184=>600,8185=>600,8186=>600,8187=>600,8188=>600,8189=>600,8190=>600,8192=>600,8193=>600,8194=>600,8195=>600,8196=>600,8197=>600,8198=>600,8199=>600,8200=>600,8201=>600,8202=>600,8203=>600,8204=>0,8205=>0,8206=>0,8207=>0,8208=>600,8209=>600,8210=>600,8211=>600,8212=>600,8213=>600,8214=>600,8215=>600,8216=>600,8217=>600,8218=>600,8219=>600,8220=>600,8221=>600,8222=>600,8223=>600,8224=>600,8225=>600,8226=>600,8227=>600,8228=>600,8229=>600,8230=>600,8231=>600,8232=>600,8233=>600,8234=>600,8235=>600,8236=>600,8237=>600,8238=>600,8239=>600,8240=>600,8241=>600,8242=>600,8243=>600,8244=>600,8245=>600,8246=>600,8247=>600,8248=>600,8249=>600,8250=>600,8251=>600,8252=>600,8253=>600,8254=>600,8255=>600,8256=>600,8257=>600,8258=>600,8259=>600,8260=>600,8261=>600,8262=>600,8263=>600,8264=>600,8265=>600,8266=>600,8267=>600,8268=>600,8269=>600,8270=>600,8271=>600,8272=>600,8273=>600,8274=>600,8275=>600,8276=>600,8277=>600,8278=>600,8279=>600,8280=>600,8281=>600,8282=>600,8283=>600,8284=>600,8285=>600,8286=>600,8287=>600,8288=>600,8289=>600,8290=>600,8291=>600,8292=>600,8304=>600,8305=>600,8308=>600,8309=>600,8310=>600,8311=>600,8312=>600,8313=>600,8314=>600,8315=>600,8316=>600,8317=>600,8318=>600,8319=>600,8320=>600,8321=>600,8322=>600,8323=>600,8324=>600,8325=>600,8326=>600,8327=>600,8328=>600,8329=>600,8330=>600,8331=>600,8332=>600,8333=>600,8334=>600,8336=>600,8337=>600,8338=>600,8339=>600,8340=>600,8353=>600,8354=>600,8355=>600,8356=>600,8357=>600,8358=>600,8359=>600,8360=>600,8361=>600,8362=>600,8363=>600,8364=>600,8365=>600,8366=>600,8368=>600,8369=>600,8370=>600,8371=>600,8372=>600,8373=>600,8400=>0,8401=>0,8402=>0,8406=>0,8407=>0,8411=>0,8412=>0,8413=>0,8414=>0,8415=>0,8416=>0,8417=>0,8418=>0,8419=>0,8421=>0,8422=>0,8424=>0,8426=>0,8427=>0,8428=>0,8429=>0,8430=>0,8431=>0,8448=>600,8449=>600,8450=>600,8451=>600,8452=>600,8453=>600,8454=>600,8455=>600,8456=>600,8457=>600,8461=>600,8462=>600,8463=>600,8464=>600,8465=>600,8466=>600,8467=>600,8468=>600,8469=>600,8470=>600,8471=>600,8472=>600,8473=>600,8474=>600,8476=>600,8477=>600,8478=>600,8480=>600,8481=>600,8482=>600,8484=>600,8486=>600,8487=>600,8489=>600,8490=>600,8491=>600,8494=>600,8498=>600,8501=>600,8502=>600,8503=>600,8504=>600,8505=>600,8506=>600,8507=>600,8513=>600,8514=>600,8515=>600,8516=>600,8523=>600,8525=>600,8526=>600,8531=>600,8532=>600,8533=>600,8534=>600,8535=>600,8536=>600,8537=>600,8538=>600,8539=>600,8540=>600,8541=>600,8542=>600,8543=>600,8544=>600,8545=>600,8546=>600,8547=>600,8548=>600,8549=>600,8550=>600,8551=>600,8552=>600,8553=>600,8554=>600,8555=>600,8556=>600,8557=>600,8558=>600,8559=>600,8560=>600,8561=>600,8562=>600,8563=>600,8564=>600,8565=>600,8566=>600,8567=>600,8568=>600,8569=>600,8570=>600,8571=>600,8572=>600,8573=>600,8574=>600,8575=>600,8592=>600,8593=>600,8594=>600,8595=>600,8596=>600,8597=>600,8598=>600,8599=>600,8600=>600,8601=>600,8602=>600,8603=>600,8604=>600,8605=>600,8606=>600,8607=>600,8608=>600,8609=>600,8610=>600,8611=>600,8612=>600,8613=>600,8614=>600,8615=>600,8616=>600,8617=>600,8618=>600,8619=>600,8620=>600,8621=>600,8622=>600,8623=>600,8624=>600,8625=>600,8626=>600,8627=>600,8628=>600,8629=>600,8630=>600,8631=>600,8632=>600,8633=>600,8634=>600,8635=>600,8636=>600,8637=>600,8638=>600,8639=>600,8640=>600,8641=>600,8642=>600,8643=>600,8644=>600,8645=>600,8646=>600,8647=>600,8648=>600,8649=>600,8650=>600,8651=>600,8652=>600,8653=>600,8654=>600,8655=>600,8656=>600,8657=>600,8658=>600,8659=>600,8660=>600,8661=>600,8669=>600,8678=>600,8679=>600,8680=>600,8681=>600,8691=>600,8704=>600,8705=>600,8706=>600,8707=>600,8708=>600,8709=>600,8710=>600,8711=>600,8712=>600,8713=>600,8714=>600,8715=>600,8716=>600,8717=>600,8718=>600,8719=>600,8720=>600,8721=>600,8722=>600,8723=>600,8724=>600,8725=>600,8726=>600,8727=>600,8728=>600,8729=>600,8730=>600,8731=>600,8732=>600,8733=>600,8734=>600,8735=>600,8736=>600,8737=>600,8738=>600,8739=>600,8740=>600,8741=>600,8742=>600,8743=>600,8744=>600,8745=>600,8746=>600,8747=>600,8748=>600,8749=>600,8750=>600,8751=>600,8752=>600,8753=>600,8754=>600,8755=>600,8756=>600,8757=>600,8758=>600,8759=>600,8760=>600,8761=>600,8762=>600,8763=>600,8764=>600,8765=>600,8766=>600,8767=>600,8768=>600,8769=>600,8770=>600,8771=>600,8772=>600,8773=>600,8774=>600,8775=>600,8776=>600,8777=>600,8778=>600,8779=>600,8780=>600,8781=>600,8782=>600,8783=>600,8784=>600,8785=>600,8786=>600,8787=>600,8788=>600,8789=>600,8790=>600,8791=>600,8792=>600,8793=>600,8794=>600,8795=>600,8796=>600,8797=>600,8798=>600,8799=>600,8800=>600,8801=>600,8802=>600,8803=>600,8804=>600,8805=>600,8806=>600,8807=>600,8808=>600,8809=>600,8810=>600,8811=>600,8812=>600,8813=>600,8814=>600,8815=>600,8816=>600,8817=>600,8818=>600,8819=>600,8820=>600,8821=>600,8822=>600,8823=>600,8824=>600,8825=>600,8826=>600,8827=>600,8828=>600,8829=>600,8830=>600,8831=>600,8832=>600,8833=>600,8834=>600,8835=>600,8836=>600,8837=>600,8838=>600,8839=>600,8840=>600,8841=>600,8842=>600,8843=>600,8844=>600,8845=>600,8846=>600,8847=>600,8848=>600,8849=>600,8850=>600,8851=>600,8852=>600,8853=>600,8854=>600,8855=>600,8856=>600,8857=>600,8858=>600,8859=>600,8860=>600,8861=>600,8862=>600,8863=>600,8864=>600,8865=>600,8866=>600,8867=>600,8868=>600,8869=>600,8870=>600,8871=>600,8872=>600,8873=>600,8874=>600,8875=>600,8876=>600,8877=>600,8878=>600,8879=>600,8880=>600,8881=>600,8882=>600,8883=>600,8884=>600,8885=>600,8886=>600,8887=>600,8888=>600,8889=>600,8890=>600,8891=>600,8892=>600,8893=>600,8894=>600,8895=>600,8896=>600,8897=>600,8898=>600,8899=>600,8900=>600,8901=>600,8902=>600,8903=>600,8904=>600,8905=>600,8906=>600,8907=>600,8908=>600,8909=>600,8910=>600,8911=>600,8912=>600,8913=>600,8914=>600,8915=>600,8916=>600,8917=>600,8918=>600,8919=>600,8920=>600,8921=>600,8922=>600,8923=>600,8924=>600,8925=>600,8926=>600,8927=>600,8928=>600,8929=>600,8930=>600,8931=>600,8932=>600,8933=>600,8934=>600,8935=>600,8936=>600,8937=>600,8938=>600,8939=>600,8940=>600,8941=>600,8942=>600,8943=>600,8944=>600,8945=>600,8960=>600,8962=>600,8963=>600,8964=>600,8965=>600,8966=>600,8968=>600,8969=>600,8970=>600,8971=>600,8972=>600,8973=>600,8974=>600,8975=>600,8976=>600,8978=>600,8980=>600,8981=>600,8984=>600,8985=>600,8988=>600,8989=>600,8990=>600,8991=>600,8992=>600,8993=>600,8994=>600,8995=>600,8996=>600,8997=>600,8998=>600,8999=>600,9001=>600,9002=>600,9003=>600,9004=>600,9014=>600,9015=>600,9016=>600,9017=>600,9018=>600,9019=>600,9020=>600,9021=>600,9022=>600,9023=>600,9024=>600,9025=>600,9026=>600,9027=>600,9028=>600,9029=>600,9030=>600,9031=>600,9032=>600,9033=>600,9034=>600,9035=>600,9036=>600,9037=>600,9038=>600,9039=>600,9040=>600,9041=>600,9042=>600,9043=>600,9044=>600,9045=>600,9046=>600,9047=>600,9048=>600,9049=>600,9050=>600,9051=>600,9052=>600,9053=>600,9054=>600,9055=>600,9056=>600,9057=>600,9058=>600,9059=>600,9060=>600,9061=>600,9062=>600,9063=>600,9064=>600,9065=>600,9066=>600,9067=>600,9068=>600,9069=>600,9070=>600,9071=>600,9072=>600,9073=>600,9074=>600,9075=>600,9076=>600,9077=>600,9078=>600,9079=>600,9080=>600,9081=>600,9082=>600,9084=>600,9085=>600,9086=>600,9087=>600,9088=>600,9089=>600,9090=>600,9091=>600,9092=>600,9093=>600,9094=>600,9095=>600,9096=>600,9097=>600,9098=>600,9099=>600,9100=>600,9101=>600,9102=>600,9103=>600,9104=>600,9105=>600,9106=>600,9107=>600,9108=>600,9109=>600,9110=>600,9111=>600,9112=>600,9113=>600,9114=>600,9115=>600,9116=>600,9117=>600,9118=>600,9119=>600,9120=>600,9121=>600,9122=>600,9123=>600,9124=>600,9125=>600,9126=>600,9127=>600,9128=>600,9129=>600,9130=>600,9131=>600,9132=>600,9133=>600,9134=>600,9135=>600,9136=>600,9137=>600,9138=>600,9139=>600,9140=>600,9141=>600,9142=>600,9143=>600,9146=>600,9147=>600,9148=>600,9149=>600,9150=>600,9151=>600,9152=>600,9153=>600,9154=>600,9155=>600,9156=>600,9157=>600,9158=>600,9159=>600,9160=>600,9161=>600,9162=>600,9163=>600,9164=>600,9165=>600,9166=>600,9167=>600,9178=>600,9179=>600,9182=>600,9183=>600,9186=>600,9187=>600,9188=>600,9189=>600,9190=>600,9216=>600,9217=>600,9218=>600,9219=>600,9220=>600,9221=>600,9222=>600,9223=>600,9224=>600,9225=>600,9226=>600,9227=>600,9228=>600,9229=>600,9230=>600,9231=>600,9232=>600,9233=>600,9234=>600,9235=>600,9236=>600,9237=>600,9238=>600,9239=>600,9240=>600,9241=>600,9242=>600,9243=>600,9244=>600,9245=>600,9246=>600,9247=>600,9248=>600,9249=>600,9251=>600,9252=>600,9280=>600,9281=>600,9282=>600,9283=>600,9284=>600,9285=>600,9286=>600,9287=>600,9288=>600,9289=>600,9290=>600,9312=>600,9313=>600,9314=>600,9315=>600,9316=>600,9317=>600,9318=>600,9319=>600,9320=>600,9321=>600,9472=>600,9473=>600,9474=>600,9475=>600,9476=>600,9477=>600,9478=>600,9479=>600,9480=>600,9481=>600,9482=>600,9483=>600,9484=>600,9485=>600,9486=>600,9487=>600,9488=>600,9489=>600,9490=>600,9491=>600,9492=>600,9493=>600,9494=>600,9495=>600,9496=>600,9497=>600,9498=>600,9499=>600,9500=>600,9501=>600,9502=>600,9503=>600,9504=>600,9505=>600,9506=>600,9507=>600,9508=>600,9509=>600,9510=>600,9511=>600,9512=>600,9513=>600,9514=>600,9515=>600,9516=>600,9517=>600,9518=>600,9519=>600,9520=>600,9521=>600,9522=>600,9523=>600,9524=>600,9525=>600,9526=>600,9527=>600,9528=>600,9529=>600,9530=>600,9531=>600,9532=>600,9533=>600,9534=>600,9535=>600,9536=>600,9537=>600,9538=>600,9539=>600,9540=>600,9541=>600,9542=>600,9543=>600,9544=>600,9545=>600,9546=>600,9547=>600,9548=>600,9549=>600,9550=>600,9551=>600,9552=>600,9553=>600,9554=>600,9555=>600,9556=>600,9557=>600,9558=>600,9559=>600,9560=>600,9561=>600,9562=>600,9563=>600,9564=>600,9565=>600,9566=>600,9567=>600,9568=>600,9569=>600,9570=>600,9571=>600,9572=>600,9573=>600,9574=>600,9575=>600,9576=>600,9577=>600,9578=>600,9579=>600,9580=>600,9581=>600,9582=>600,9583=>600,9584=>600,9585=>600,9586=>600,9587=>600,9588=>600,9589=>600,9590=>600,9591=>600,9592=>600,9593=>600,9594=>600,9595=>600,9596=>600,9597=>600,9598=>600,9599=>600,9600=>600,9601=>600,9602=>600,9603=>600,9604=>600,9605=>600,9606=>600,9607=>600,9608=>600,9609=>600,9610=>600,9611=>600,9612=>600,9613=>600,9614=>600,9615=>600,9616=>600,9617=>600,9618=>600,9619=>600,9620=>600,9621=>600,9622=>600,9623=>600,9624=>600,9625=>600,9626=>600,9627=>600,9628=>600,9629=>600,9630=>600,9631=>600,9632=>600,9633=>600,9634=>600,9635=>600,9636=>600,9637=>600,9638=>600,9639=>600,9640=>600,9641=>600,9642=>600,9643=>600,9644=>600,9645=>600,9646=>600,9647=>600,9648=>600,9649=>600,9650=>600,9651=>600,9652=>600,9653=>600,9654=>600,9655=>600,9656=>600,9657=>600,9658=>600,9659=>600,9660=>600,9661=>600,9662=>600,9663=>600,9664=>600,9665=>600,9666=>600,9667=>600,9668=>600,9669=>600,9670=>600,9671=>600,9672=>600,9673=>600,9674=>600,9675=>600,9676=>600,9677=>600,9678=>600,9679=>600,9680=>600,9681=>600,9682=>600,9683=>600,9684=>600,9685=>600,9686=>600,9687=>600,9688=>600,9689=>600,9690=>600,9691=>600,9692=>600,9693=>600,9694=>600,9695=>600,9696=>600,9697=>600,9698=>600,9699=>600,9700=>600,9701=>600,9702=>600,9703=>600,9704=>600,9705=>600,9706=>600,9707=>600,9708=>600,9709=>600,9710=>600,9711=>600,9712=>600,9713=>600,9714=>600,9715=>600,9716=>600,9717=>600,9718=>600,9719=>600,9720=>600,9721=>600,9722=>600,9723=>600,9724=>600,9725=>600,9726=>600,9727=>600,9728=>600,9729=>600,9730=>600,9731=>600,9733=>600,9734=>600,9735=>600,9736=>600,9737=>600,9744=>600,9745=>600,9746=>600,9754=>600,9755=>600,9756=>600,9757=>600,9758=>600,9759=>600,9766=>600,9768=>600,9769=>600,9774=>600,9775=>600,9776=>600,9777=>600,9778=>600,9779=>600,9780=>600,9781=>600,9782=>600,9783=>600,9785=>600,9786=>600,9787=>600,9788=>600,9789=>600,9790=>600,9791=>600,9792=>600,9793=>600,9794=>600,9795=>600,9796=>600,9797=>600,9798=>600,9799=>600,9800=>600,9801=>600,9802=>600,9803=>600,9804=>600,9805=>600,9806=>600,9807=>600,9808=>600,9809=>600,9810=>600,9811=>600,9824=>600,9825=>600,9826=>600,9827=>600,9828=>600,9829=>600,9830=>600,9831=>600,9833=>600,9834=>600,9835=>600,9836=>600,9837=>600,9838=>600,9839=>600,9856=>600,9857=>600,9858=>600,9859=>600,9860=>600,9861=>600,10176=>600,10177=>600,10178=>600,10179=>600,10180=>600,10181=>600,10182=>600,10183=>600,10184=>600,10185=>600,10186=>600,10188=>600,10192=>600,10193=>600,10194=>600,10195=>600,10196=>600,10197=>600,10198=>600,10199=>600,10212=>600,10213=>600,10214=>600,10215=>600,10216=>600,10217=>600,10218=>600,10219=>600,10226=>600,10227=>600,10229=>600,10230=>600,10231=>600,10232=>600,10233=>600,10234=>600,10235=>600,10236=>600,10240=>600,10241=>600,10242=>600,10243=>600,10244=>600,10245=>600,10246=>600,10247=>600,10248=>600,10249=>600,10250=>600,10251=>600,10252=>600,10253=>600,10254=>600,10255=>600,10256=>600,10257=>600,10258=>600,10259=>600,10260=>600,10261=>600,10262=>600,10263=>600,10264=>600,10265=>600,10266=>600,10267=>600,10268=>600,10269=>600,10270=>600,10271=>600,10272=>600,10273=>600,10274=>600,10275=>600,10276=>600,10277=>600,10278=>600,10279=>600,10280=>600,10281=>600,10282=>600,10283=>600,10284=>600,10285=>600,10286=>600,10287=>600,10288=>600,10289=>600,10290=>600,10291=>600,10292=>600,10293=>600,10294=>600,10295=>600,10296=>600,10297=>600,10298=>600,10299=>600,10300=>600,10301=>600,10302=>600,10303=>600,10304=>600,10305=>600,10306=>600,10307=>600,10308=>600,10309=>600,10310=>600,10311=>600,10312=>600,10313=>600,10314=>600,10315=>600,10316=>600,10317=>600,10318=>600,10319=>600,10320=>600,10321=>600,10322=>600,10323=>600,10324=>600,10325=>600,10326=>600,10327=>600,10328=>600,10329=>600,10330=>600,10331=>600,10332=>600,10333=>600,10334=>600,10335=>600,10336=>600,10337=>600,10338=>600,10339=>600,10340=>600,10341=>600,10342=>600,10343=>600,10344=>600,10345=>600,10346=>600,10347=>600,10348=>600,10349=>600,10350=>600,10351=>600,10352=>600,10353=>600,10354=>600,10355=>600,10356=>600,10357=>600,10358=>600,10359=>600,10360=>600,10361=>600,10362=>600,10363=>600,10364=>600,10365=>600,10366=>600,10367=>600,10368=>600,10369=>600,10370=>600,10371=>600,10372=>600,10373=>600,10374=>600,10375=>600,10376=>600,10377=>600,10378=>600,10379=>600,10380=>600,10381=>600,10382=>600,10383=>600,10384=>600,10385=>600,10386=>600,10387=>600,10388=>600,10389=>600,10390=>600,10391=>600,10392=>600,10393=>600,10394=>600,10395=>600,10396=>600,10397=>600,10398=>600,10399=>600,10400=>600,10401=>600,10402=>600,10403=>600,10404=>600,10405=>600,10406=>600,10407=>600,10408=>600,10409=>600,10410=>600,10411=>600,10412=>600,10413=>600,10414=>600,10415=>600,10416=>600,10417=>600,10418=>600,10419=>600,10420=>600,10421=>600,10422=>600,10423=>600,10424=>600,10425=>600,10426=>600,10427=>600,10428=>600,10429=>600,10430=>600,10431=>600,10432=>600,10433=>600,10434=>600,10435=>600,10436=>600,10437=>600,10438=>600,10439=>600,10440=>600,10441=>600,10442=>600,10443=>600,10444=>600,10445=>600,10446=>600,10447=>600,10448=>600,10449=>600,10450=>600,10451=>600,10452=>600,10453=>600,10454=>600,10455=>600,10456=>600,10457=>600,10458=>600,10459=>600,10460=>600,10461=>600,10462=>600,10463=>600,10464=>600,10465=>600,10466=>600,10467=>600,10468=>600,10469=>600,10470=>600,10471=>600,10472=>600,10473=>600,10474=>600,10475=>600,10476=>600,10477=>600,10478=>600,10479=>600,10480=>600,10481=>600,10482=>600,10483=>600,10484=>600,10485=>600,10486=>600,10487=>600,10488=>600,10489=>600,10490=>600,10491=>600,10492=>600,10493=>600,10494=>600,10495=>600,10752=>600,10753=>600,10754=>600,10755=>600,10756=>600,10757=>600,10758=>600,10781=>600,10815=>600,11008=>600,11009=>600,11010=>600,11011=>600,11012=>600,11013=>600,11014=>600,11015=>600,11016=>600,11017=>600,11018=>600,11019=>600,11020=>600,11021=>600,11026=>600,11027=>600,11028=>600,11029=>600,11030=>600,11031=>600,11032=>600,11033=>600,11035=>600,11036=>600,11037=>600,11038=>600,11039=>600,11040=>600,11041=>600,11042=>600,11043=>600,11044=>600,11045=>600,11046=>600,11047=>600,11048=>600,11049=>600,11050=>600,11051=>600,11091=>600,11092=>600,11799=>600,42888=>600,42889=>600,42890=>600,42891=>600,42892=>600,43264=>600,43265=>600,43266=>600,43267=>600,43268=>600,43269=>600,43270=>600,43271=>600,43272=>600,43273=>600,43274=>600,43275=>600,43276=>600,43277=>600,43278=>600,43279=>600,43280=>600,43281=>600,43282=>600,43283=>600,43284=>600,43285=>600,43286=>600,43287=>600,43288=>600,43289=>600,43290=>600,43291=>600,43292=>600,43293=>600,43294=>600,43295=>600,43296=>600,43297=>600,43298=>600,43299=>600,43300=>600,43301=>600,43302=>0,43303=>0,43304=>0,43305=>0,43306=>0,43307=>0,43308=>0,43309=>0,43310=>600,43311=>600,64256=>600,64257=>600,64258=>600,64259=>600,64260=>600,64261=>600,64285=>600,64286=>600,64287=>600,64288=>600,64289=>600,64290=>600,64291=>600,64292=>600,64293=>600,64294=>600,64295=>600,64296=>600,64297=>600,64298=>600,64299=>600,64300=>600,64301=>600,64302=>600,64303=>600,64304=>600,64305=>600,64306=>600,64307=>600,64308=>600,64309=>600,64310=>600,64312=>600,64313=>600,64314=>600,64315=>600,64316=>600,64318=>600,64320=>600,64321=>600,64323=>600,64324=>600,64326=>600,64327=>600,64328=>600,64329=>600,64330=>600,64331=>600,64332=>600,64333=>600,64334=>600,64335=>600,65533=>600,65535=>600); // --- EOF --- PKa\:!Z!Zfonts/freesansbi.phpnuW+A96,'FontBBox'=>'[-908 -313 1591 1076]','ItalicAngle'=>-12,'Ascent'=>1000,'Descent'=>-300,'Leading'=>90,'CapHeight'=>729,'XHeight'=>540,'StemV'=>123,'StemH'=>53,'AvgWidth'=>478,'MaxWidth'=>1501,'MissingWidth'=>700); $cw=array(0=>0,1=>700,2=>700,3=>700,4=>700,5=>700,6=>700,7=>700,8=>0,9=>600,10=>700,11=>700,12=>700,13=>600,14=>700,15=>700,16=>700,17=>700,18=>700,19=>700,20=>700,21=>700,22=>700,23=>700,24=>700,25=>700,26=>700,27=>700,28=>700,29=>0,30=>700,31=>700,32=>278,33=>333,34=>474,35=>556,36=>556,37=>889,38=>722,39=>238,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>333,59=>333,60=>584,61=>584,62=>584,63=>611,64=>975,65=>722,66=>722,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>556,75=>722,76=>611,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>333,92=>278,93=>333,94=>584,95=>556,96=>333,97=>556,98=>611,99=>556,100=>611,101=>556,102=>333,103=>611,104=>611,105=>278,106=>278,107=>556,108=>278,109=>889,110=>611,111=>611,112=>611,113=>611,114=>389,115=>556,116=>333,117=>611,118=>556,119=>778,120=>556,121=>556,122=>500,123=>389,124=>280,125=>389,126=>584,127=>700,128=>722,129=>722,130=>722,131=>667,132=>722,133=>778,134=>722,135=>556,136=>556,137=>556,138=>556,139=>556,140=>556,141=>556,142=>556,143=>556,144=>556,145=>556,146=>278,147=>278,148=>278,149=>278,150=>611,151=>611,152=>611,153=>611,154=>611,155=>611,156=>611,157=>611,158=>611,159=>611,160=>278,161=>333,162=>556,163=>556,164=>556,165=>556,166=>280,167=>556,168=>333,169=>737,170=>370,171=>556,172=>584,173=>333,174=>737,175=>333,176=>606,177=>584,178=>350,179=>350,180=>333,181=>667,182=>556,183=>278,184=>333,185=>248,186=>365,187=>556,188=>869,189=>869,190=>869,191=>611,192=>722,193=>722,194=>722,195=>722,196=>722,197=>722,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>667,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>892,231=>556,232=>556,233=>556,234=>556,235=>556,236=>278,237=>278,238=>278,239=>278,240=>611,241=>611,242=>611,243=>611,244=>611,245=>611,246=>611,247=>584,248=>611,249=>611,250=>611,251=>611,252=>611,253=>556,254=>611,255=>556,256=>722,257=>556,258=>722,259=>556,260=>722,261=>556,262=>722,263=>556,264=>722,265=>556,266=>722,267=>556,268=>722,269=>556,270=>722,271=>722,272=>722,273=>611,274=>667,275=>556,276=>667,277=>556,278=>667,279=>556,280=>667,281=>556,282=>667,283=>556,284=>778,285=>611,286=>778,287=>611,288=>778,289=>611,290=>778,291=>611,292=>722,293=>611,294=>722,295=>611,296=>278,297=>278,298=>278,299=>278,300=>278,301=>278,302=>278,303=>268,304=>278,305=>278,306=>595,307=>488,308=>556,309=>278,310=>722,311=>556,312=>529,313=>611,314=>278,315=>611,316=>278,317=>611,318=>444,319=>611,320=>556,321=>611,322=>278,323=>722,324=>611,325=>722,326=>611,327=>722,328=>611,329=>656,330=>720,331=>611,332=>778,333=>611,334=>778,335=>611,336=>778,337=>611,338=>1000,339=>962,340=>722,341=>389,342=>722,343=>389,344=>722,345=>389,346=>667,347=>556,348=>667,349=>556,350=>667,351=>556,352=>667,353=>556,354=>611,355=>333,356=>611,357=>444,358=>611,359=>404,360=>722,361=>611,362=>722,363=>611,364=>722,365=>611,366=>722,367=>611,368=>722,369=>611,370=>722,371=>611,372=>944,373=>778,374=>667,375=>556,376=>667,377=>611,378=>500,379=>611,380=>500,381=>611,382=>500,383=>333,384=>611,385=>963,386=>722,387=>611,388=>687,389=>611,390=>722,391=>752,392=>562,393=>722,394=>968,395=>722,396=>611,397=>609,398=>667,399=>778,400=>672,401=>611,402=>333,403=>778,404=>667,405=>940,406=>278,407=>395,408=>778,409=>556,410=>333,411=>620,412=>889,413=>722,414=>611,415=>778,416=>808,417=>673,418=>1111,419=>722,420=>914,421=>611,422=>647,423=>667,424=>556,425=>688,426=>441,427=>333,428=>742,429=>333,430=>611,431=>789,432=>684,433=>780,434=>722,435=>762,436=>706,437=>611,438=>500,439=>556,440=>556,441=>645,442=>569,443=>579,446=>611,447=>608,448=>258,449=>443,450=>584,451=>278,452=>1333,453=>1222,454=>1111,455=>1167,456=>889,457=>556,458=>1278,459=>1000,460=>889,461=>722,462=>556,463=>278,464=>278,465=>778,466=>611,467=>722,468=>611,469=>722,470=>611,471=>722,472=>611,473=>722,474=>611,475=>722,476=>611,477=>556,478=>722,479=>556,480=>722,481=>556,482=>1000,483=>892,484=>811,485=>641,486=>778,487=>611,488=>722,489=>556,490=>778,491=>611,492=>778,493=>611,494=>556,495=>556,496=>278,497=>1333,498=>1222,499=>1111,500=>778,501=>611,503=>630,504=>722,505=>611,506=>722,507=>556,508=>1000,509=>892,510=>778,511=>611,512=>722,513=>556,514=>722,515=>556,516=>667,517=>556,518=>667,519=>556,520=>278,521=>278,522=>278,523=>278,524=>778,525=>611,526=>778,527=>611,528=>722,529=>389,530=>722,531=>389,532=>722,533=>611,534=>722,535=>611,536=>667,537=>556,538=>611,539=>333,540=>569,541=>486,542=>722,543=>611,548=>645,549=>500,550=>722,551=>556,552=>667,553=>556,554=>778,555=>611,556=>778,557=>611,558=>778,559=>611,560=>778,561=>611,562=>667,563=>556,567=>278,592=>556,593=>611,594=>671,595=>611,596=>556,597=>600,598=>595,599=>611,600=>556,601=>556,602=>834,603=>570,604=>546,605=>820,606=>570,607=>278,608=>611,609=>611,610=>556,611=>556,612=>646,613=>619,614=>611,615=>611,616=>278,617=>326,618=>278,619=>473,620=>527,621=>298,622=>778,623=>889,624=>889,625=>889,626=>611,627=>611,628=>615,629=>590,630=>878,631=>822,632=>778,633=>389,634=>389,635=>406,636=>419,637=>389,638=>455,639=>455,640=>620,641=>586,642=>606,643=>333,644=>302,645=>333,646=>556,647=>328,648=>333,649=>623,650=>686,651=>630,652=>556,653=>778,654=>556,655=>556,656=>519,657=>571,658=>556,659=>632,660=>611,661=>611,662=>611,663=>556,664=>579,665=>572,666=>570,667=>616,668=>603,669=>552,670=>556,671=>454,672=>611,673=>611,674=>611,675=>1004,676=>1018,677=>1097,678=>804,679=>593,680=>840,681=>866,682=>752,683=>668,684=>536,685=>486,686=>659,687=>679,688=>377,689=>377,690=>202,691=>272,692=>272,693=>299,694=>395,695=>534,696=>364,697=>278,698=>454,699=>278,700=>333,701=>278,702=>333,703=>333,704=>333,705=>333,706=>333,707=>333,708=>333,709=>333,710=>333,711=>333,712=>333,713=>333,714=>333,715=>333,716=>272,717=>333,718=>333,719=>333,720=>333,721=>333,722=>333,723=>333,724=>333,725=>333,726=>333,727=>333,728=>333,729=>333,730=>333,731=>333,732=>333,733=>333,734=>333,735=>510,736=>372,737=>210,738=>363,739=>373,740=>334,741=>526,742=>526,743=>526,744=>526,745=>526,746=>519,747=>519,748=>333,749=>333,750=>333,751=>333,752=>333,753=>333,754=>333,755=>333,756=>333,757=>437,758=>437,759=>400,760=>333,761=>200,762=>200,763=>200,764=>200,765=>332,766=>333,767=>333,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,842=>0,843=>0,844=>0,845=>0,846=>0,847=>0,848=>0,849=>0,850=>0,851=>0,852=>0,853=>0,854=>0,855=>0,856=>0,857=>0,858=>0,859=>0,860=>0,861=>0,862=>0,863=>0,864=>0,865=>0,866=>0,867=>0,868=>0,869=>0,870=>0,871=>0,872=>0,873=>0,874=>0,875=>0,876=>0,877=>0,878=>0,879=>0,884=>208,885=>247,890=>364,894=>333,900=>239,901=>446,902=>688,903=>333,904=>903,905=>962,906=>448,908=>904,910=>991,911=>932,912=>346,913=>764,914=>688,915=>642,916=>744,917=>710,918=>688,919=>743,920=>810,921=>296,922=>744,923=>744,924=>860,925=>714,926=>690,927=>822,928=>781,929=>698,931=>688,932=>688,933=>744,934=>777,935=>783,936=>805,937=>780,938=>296,939=>744,940=>640,941=>530,942=>597,943=>339,944=>575,945=>656,946=>576,947=>591,948=>620,949=>570,950=>522,951=>586,952=>586,953=>346,954=>576,955=>620,956=>667,957=>564,958=>530,959=>610,960=>721,961=>626,962=>595,963=>676,964=>592,965=>575,966=>801,967=>632,968=>722,969=>800,970=>346,971=>575,972=>609,973=>604,974=>769,977=>580,978=>742,979=>857,980=>620,981=>778,982=>740,983=>601,1008=>556,1009=>566,1012=>778,1013=>328,1024=>667,1025=>667,1026=>790,1027=>617,1028=>731,1029=>667,1030=>278,1031=>278,1032=>556,1033=>1110,1034=>1088,1035=>790,1036=>722,1037=>757,1038=>698,1039=>722,1040=>722,1041=>722,1042=>722,1043=>617,1044=>876,1045=>667,1046=>1100,1047=>670,1048=>757,1049=>757,1050=>722,1051=>715,1052=>874,1053=>753,1054=>778,1055=>753,1056=>680,1057=>722,1058=>611,1059=>698,1060=>909,1061=>657,1062=>845,1063=>688,1064=>1132,1065=>1217,1066=>835,1067=>980,1068=>678,1069=>735,1070=>1142,1071=>708,1072=>553,1073=>591,1074=>574,1075=>429,1076=>745,1077=>572,1078=>792,1079=>554,1080=>603,1081=>603,1082=>559,1083=>583,1084=>664,1085=>603,1086=>588,1087=>603,1088=>605,1089=>549,1090=>440,1091=>541,1092=>948,1093=>539,1094=>690,1095=>564,1096=>901,1097=>987,1098=>692,1099=>806,1100=>572,1101=>546,1102=>893,1103=>586,1104=>572,1105=>572,1106=>616,1107=>429,1108=>549,1109=>562,1110=>281,1111=>281,1112=>282,1113=>888,1114=>897,1115=>606,1116=>559,1117=>603,1118=>541,1119=>603,1120=>986,1121=>736,1136=>830,1137=>761,1138=>778,1139=>590,1148=>942,1149=>736,1150=>986,1151=>736,1154=>456,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1160=>0,1161=>0,1162=>791,1163=>662,1164=>639,1165=>581,1166=>670,1167=>649,1168=>623,1169=>450,1170=>623,1171=>472,1172=>674,1173=>528,1174=>1091,1175=>803,1176=>659,1177=>548,1178=>739,1179=>569,1180=>742,1181=>560,1182=>737,1183=>559,1184=>900,1185=>679,1186=>808,1187=>673,1188=>1004,1189=>761,1190=>1114,1191=>876,1192=>963,1193=>766,1194=>724,1195=>554,1196=>611,1197=>454,1198=>667,1199=>584,1200=>652,1201=>632,1202=>667,1203=>550,1204=>951,1205=>748,1206=>759,1207=>630,1208=>669,1209=>580,1210=>672,1211=>576,1212=>977,1213=>752,1214=>993,1215=>761,1216=>318,1217=>1087,1218=>792,1219=>726,1220=>530,1221=>782,1222=>674,1223=>749,1224=>603,1225=>823,1226=>682,1227=>675,1228=>573,1229=>941,1230=>754,1231=>310,1232=>704,1233=>553,1234=>711,1235=>553,1236=>1000,1237=>892,1238=>667,1239=>569,1240=>738,1241=>561,1242=>738,1243=>561,1244=>1086,1245=>792,1246=>670,1247=>554,1248=>558,1249=>546,1250=>753,1251=>603,1252=>753,1253=>603,1254=>778,1255=>588,1256=>778,1257=>590,1258=>778,1259=>590,1260=>735,1261=>546,1262=>698,1263=>541,1264=>698,1265=>541,1266=>698,1267=>541,1268=>686,1269=>564,1270=>617,1271=>475,1272=>976,1273=>806,1296=>672,1297=>546,1298=>729,1299=>577,1306=>778,1307=>611,1308=>944,1309=>776,1310=>750,1311=>573,1329=>730,1330=>713,1331=>765,1332=>752,1333=>708,1334=>801,1335=>496,1336=>713,1337=>855,1338=>686,1339=>727,1340=>420,1341=>897,1342=>841,1343=>708,1344=>660,1345=>666,1346=>747,1347=>698,1348=>757,1349=>630,1350=>747,1351=>651,1352=>743,1353=>657,1354=>728,1355=>799,1356=>752,1357=>743,1358=>768,1359=>691,1360=>713,1361=>640,1362=>425,1363=>818,1364=>672,1365=>805,1366=>754,1369=>333,1370=>222,1371=>250,1372=>333,1373=>333,1374=>352,1375=>362,1377=>873,1378=>613,1379=>634,1380=>636,1381=>593,1382=>639,1383=>417,1384=>613,1385=>658,1386=>711,1387=>609,1388=>318,1389=>836,1390=>670,1391=>613,1392=>607,1393=>611,1394=>626,1395=>619,1396=>618,1397=>324,1398=>613,1399=>540,1400=>591,1401=>392,1402=>873,1403=>577,1404=>603,1405=>600,1406=>626,1407=>951,1408=>613,1409=>612,1410=>348,1411=>951,1412=>616,1413=>606,1414=>763,1415=>626,1417=>333,1418=>398,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1467=>0,1468=>0,1469=>0,1470=>516,1471=>0,1472=>297,1473=>0,1474=>0,1475=>333,1476=>0,1488=>714,1489=>651,1490=>557,1491=>638,1492=>682,1493=>297,1494=>443,1495=>682,1496=>670,1497=>284,1498=>590,1499=>595,1500=>667,1501=>683,1502=>704,1503=>297,1504=>429,1505=>670,1506=>653,1507=>661,1508=>660,1509=>616,1510=>671,1511=>672,1512=>600,1513=>840,1514=>756,1520=>554,1521=>550,1522=>542,1523=>238,1524=>474,4256=>616,4257=>645,4258=>664,4259=>839,4260=>627,4261=>630,4262=>827,4263=>928,4264=>639,4265=>630,4266=>951,4267=>606,4268=>608,4269=>835,4270=>630,4271=>610,4272=>804,4273=>615,4274=>823,4275=>747,4276=>870,4277=>627,4278=>840,4279=>627,4280=>665,4281=>610,4282=>799,4283=>598,4284=>665,4285=>664,4286=>608,4287=>886,4288=>629,4304=>463,4305=>516,4306=>564,4307=>706,4308=>459,4309=>476,4310=>623,4311=>711,4312=>494,4313=>476,4314=>894,4315=>500,4316=>500,4317=>712,4318=>493,4319=>503,4320=>712,4321=>503,4322=>710,4323=>670,4324=>707,4325=>459,4326=>691,4327=>465,4328=>492,4329=>480,4330=>656,4331=>500,4332=>492,4333=>524,4334=>500,4335=>688,4336=>510,4337=>739,4338=>450,4339=>479,4340=>502,4341=>501,4345=>564,4347=>515,4348=>449,5024=>714,5025=>731,5026=>624,5027=>908,5028=>1040,5029=>271,5030=>654,5031=>863,5032=>604,5033=>791,5034=>714,5035=>522,5036=>661,5037=>926,5038=>615,5039=>811,5040=>538,5041=>633,5042=>979,5043=>964,5044=>635,5045=>607,5046=>753,5047=>831,5048=>566,5049=>977,5050=>958,5051=>710,5052=>616,5053=>834,5054=>790,5055=>612,5056=>766,5057=>857,5058=>627,5059=>649,5060=>607,5061=>1127,5062=>680,5063=>920,5064=>928,5065=>1333,5066=>920,5067=>705,5068=>695,5069=>1074,5070=>672,5071=>672,5072=>667,5073=>819,5074=>679,5075=>575,5076=>903,5077=>652,5078=>776,5079=>643,5080=>670,5081=>660,5082=>648,5083=>934,5084=>909,5085=>613,5086=>615,5087=>735,5088=>900,5089=>1024,5090=>647,5091=>760,5092=>829,5093=>824,5094=>756,5095=>625,5096=>981,5097=>1014,5098=>1040,5099=>790,5100=>926,5101=>686,5102=>656,5103=>920,5104=>741,5105=>890,5106=>626,5107=>974,5108=>699,7680=>722,7681=>556,7682=>722,7683=>611,7684=>722,7685=>611,7686=>722,7687=>611,7688=>722,7689=>556,7690=>722,7691=>611,7692=>722,7693=>611,7694=>722,7695=>611,7696=>722,7697=>611,7698=>722,7699=>611,7700=>667,7701=>556,7702=>667,7703=>556,7704=>667,7705=>556,7706=>667,7707=>556,7708=>667,7709=>556,7710=>611,7711=>333,7712=>778,7713=>611,7714=>722,7715=>611,7716=>722,7717=>611,7718=>722,7719=>611,7720=>722,7721=>611,7722=>722,7723=>611,7724=>278,7725=>278,7726=>278,7727=>278,7728=>722,7729=>556,7730=>722,7731=>556,7732=>722,7733=>556,7734=>611,7735=>278,7736=>611,7737=>278,7738=>611,7739=>278,7740=>611,7741=>278,7742=>833,7743=>889,7744=>833,7745=>889,7746=>833,7747=>889,7748=>722,7749=>611,7750=>722,7751=>611,7752=>722,7753=>611,7754=>722,7755=>611,7756=>778,7757=>611,7758=>778,7759=>611,7760=>778,7761=>611,7762=>778,7763=>611,7764=>667,7765=>611,7766=>667,7767=>611,7768=>722,7769=>389,7770=>722,7771=>389,7772=>722,7773=>389,7774=>722,7775=>389,7776=>667,7777=>556,7778=>667,7779=>556,7780=>667,7781=>556,7782=>667,7783=>556,7784=>667,7785=>556,7786=>611,7787=>333,7788=>611,7789=>333,7790=>611,7791=>333,7792=>611,7793=>333,7794=>722,7795=>611,7796=>722,7797=>611,7798=>722,7799=>611,7800=>722,7801=>611,7802=>722,7803=>611,7804=>667,7805=>556,7806=>667,7807=>556,7808=>944,7809=>778,7810=>944,7811=>778,7812=>944,7813=>778,7814=>944,7815=>778,7816=>944,7817=>778,7818=>667,7819=>556,7820=>667,7821=>556,7822=>667,7823=>556,7824=>611,7825=>500,7826=>611,7827=>500,7828=>611,7829=>500,7830=>611,7831=>333,7832=>778,7833=>556,7834=>555,7835=>333,7840=>722,7841=>556,7842=>722,7843=>556,7844=>722,7845=>556,7846=>722,7847=>556,7848=>722,7849=>556,7850=>722,7851=>556,7852=>722,7853=>556,7854=>722,7855=>556,7856=>722,7857=>556,7858=>722,7859=>556,7860=>722,7861=>556,7862=>722,7863=>556,7864=>667,7865=>556,7866=>667,7867=>556,7868=>667,7869=>556,7870=>667,7871=>556,7872=>667,7873=>556,7874=>667,7875=>556,7876=>667,7877=>556,7878=>667,7879=>556,7880=>278,7881=>278,7882=>278,7883=>278,7884=>778,7885=>611,7886=>778,7887=>611,7888=>778,7889=>611,7890=>778,7891=>611,7892=>778,7893=>611,7894=>778,7895=>611,7896=>778,7897=>611,7898=>808,7899=>673,7900=>808,7901=>673,7902=>808,7903=>673,7904=>808,7905=>673,7906=>808,7907=>673,7908=>722,7909=>611,7910=>722,7911=>611,7912=>789,7913=>684,7914=>789,7915=>684,7916=>789,7917=>684,7918=>789,7919=>684,7920=>789,7921=>684,7922=>667,7923=>556,7924=>667,7925=>556,7926=>667,7927=>556,7928=>667,7929=>556,7936=>656,7937=>656,7938=>656,7939=>656,7940=>656,7941=>656,7942=>656,7943=>656,7944=>764,7945=>764,7946=>916,7947=>940,7948=>908,7949=>891,7950=>844,7951=>869,7952=>570,7953=>570,7954=>570,7955=>570,7956=>570,7957=>570,7960=>842,7961=>836,7962=>1025,7963=>1051,7964=>1035,7965=>1049,7968=>586,7969=>586,7970=>586,7971=>586,7972=>586,7973=>586,7974=>586,7975=>586,7976=>891,7977=>886,7978=>1081,7979=>1108,7980=>1085,7981=>1096,7982=>1009,7983=>1023,7984=>346,7985=>346,7986=>346,7987=>346,7988=>346,7989=>346,7990=>346,7991=>346,7992=>467,7993=>476,7994=>631,7995=>661,7996=>631,7997=>633,7998=>568,7999=>571,8000=>610,8001=>610,8002=>610,8003=>610,8004=>610,8005=>610,8008=>945,8009=>905,8010=>1118,8011=>1121,8012=>1064,8013=>1062,8016=>575,8017=>575,8018=>575,8019=>575,8020=>575,8021=>575,8022=>575,8023=>575,8025=>964,8027=>1148,8029=>1162,8031=>1081,8032=>800,8033=>800,8034=>800,8035=>800,8036=>800,8037=>800,8038=>800,8039=>800,8040=>904,8041=>875,8042=>1092,8043=>1087,8044=>1003,8045=>1002,8046=>1001,8047=>1025,8048=>656,8049=>656,8050=>570,8051=>570,8052=>586,8053=>586,8054=>346,8055=>346,8056=>610,8057=>610,8058=>575,8059=>575,8060=>800,8061=>800,8064=>656,8065=>656,8066=>656,8067=>656,8068=>656,8069=>656,8070=>656,8071=>656,8072=>854,8073=>855,8074=>1006,8075=>1030,8076=>996,8077=>977,8078=>938,8079=>959,8080=>586,8081=>586,8082=>586,8083=>586,8084=>586,8085=>586,8086=>586,8087=>586,8088=>960,8089=>960,8090=>1155,8091=>1186,8092=>1161,8093=>1171,8094=>1087,8095=>1102,8096=>800,8097=>800,8098=>800,8099=>800,8100=>800,8101=>800,8102=>800,8103=>800,8104=>1005,8105=>980,8106=>1201,8107=>1192,8108=>1109,8109=>1108,8110=>1106,8111=>1130,8112=>656,8113=>656,8114=>656,8115=>656,8116=>640,8118=>656,8119=>656,8120=>764,8121=>764,8122=>764,8123=>764,8124=>854,8125=>278,8126=>201,8127=>147,8128=>278,8129=>333,8130=>586,8131=>586,8132=>597,8134=>586,8135=>586,8136=>911,8137=>925,8138=>941,8139=>948,8140=>826,8141=>402,8142=>403,8143=>147,8144=>346,8145=>346,8146=>346,8147=>346,8150=>346,8151=>346,8152=>296,8153=>296,8154=>511,8155=>521,8157=>434,8158=>433,8159=>333,8160=>575,8161=>575,8162=>575,8163=>575,8164=>626,8165=>626,8166=>575,8167=>575,8168=>744,8169=>744,8170=>901,8171=>975,8172=>837,8173=>353,8174=>351,8175=>303,8178=>800,8179=>800,8180=>800,8182=>800,8183=>800,8184=>979,8185=>918,8186=>936,8187=>877,8188=>895,8189=>333,8190=>159,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>333,8197=>250,8198=>167,8199=>556,8200=>278,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>333,8209=>333,8210=>556,8211=>556,8212=>1000,8213=>1000,8214=>437,8215=>556,8216=>278,8217=>278,8218=>278,8219=>278,8220=>500,8221=>500,8222=>500,8223=>503,8224=>556,8225=>556,8226=>350,8227=>350,8228=>278,8229=>666,8230=>1000,8231=>278,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>500,8240=>1000,8241=>1372,8242=>238,8243=>426,8244=>614,8245=>238,8246=>379,8247=>571,8248=>450,8249=>333,8250=>333,8251=>622,8252=>666,8253=>617,8254=>556,8255=>658,8256=>658,8257=>438,8258=>840,8259=>400,8260=>167,8261=>334,8262=>334,8263=>1222,8264=>944,8265=>944,8266=>556,8267=>556,8268=>537,8269=>537,8270=>389,8271=>333,8272=>658,8273=>389,8274=>634,8275=>568,8276=>658,8277=>793,8278=>515,8279=>855,8280=>722,8281=>725,8282=>224,8283=>722,8284=>604,8285=>224,8286=>224,8287=>0,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8304=>351,8305=>200,8308=>351,8309=>351,8310=>351,8311=>351,8312=>351,8313=>351,8314=>351,8315=>351,8316=>351,8317=>270,8318=>270,8319=>391,8320=>351,8321=>251,8322=>351,8323=>351,8324=>351,8325=>351,8326=>351,8327=>351,8328=>351,8329=>351,8330=>350,8331=>350,8332=>350,8333=>270,8334=>270,8336=>363,8337=>366,8338=>394,8339=>360,8340=>355,8355=>611,8356=>576,8357=>833,8358=>724,8360=>1286,8362=>1049,8363=>571,8364=>640,8368=>594,8373=>591,8376=>612,8400=>0,8401=>0,8402=>0,8403=>0,8406=>0,8407=>0,8411=>0,8412=>0,8413=>0,8414=>0,8415=>0,8416=>0,8417=>0,8421=>0,8422=>0,8423=>0,8424=>0,8425=>0,8426=>0,8427=>0,8428=>0,8429=>0,8430=>0,8431=>0,8432=>0,8448=>945,8449=>1007,8451=>1020,8453=>981,8454=>1002,8455=>667,8456=>722,8457=>930,8462=>611,8465=>606,8467=>608,8468=>883,8470=>1006,8471=>860,8476=>699,8480=>1000,8481=>1330,8482=>1000,8486=>780,8487=>780,8489=>286,8490=>722,8491=>722,8494=>556,8498=>626,8501=>714,8502=>651,8503=>557,8504=>638,8506=>906,8507=>1425,8513=>778,8514=>611,8515=>611,8516=>667,8523=>710,8525=>1242,8526=>460,8531=>869,8532=>869,8533=>869,8534=>869,8535=>869,8536=>869,8537=>869,8538=>869,8539=>869,8540=>869,8541=>869,8542=>869,8543=>869,8544=>278,8545=>556,8546=>834,8547=>945,8548=>667,8549=>945,8550=>1223,8551=>1501,8552=>945,8553=>667,8554=>945,8555=>1223,8556=>611,8557=>722,8558=>722,8559=>833,8560=>278,8561=>556,8562=>834,8563=>834,8564=>556,8565=>834,8566=>1112,8567=>1390,8568=>834,8569=>556,8570=>834,8571=>1112,8572=>278,8573=>556,8574=>611,8575=>889,8592=>964,8593=>964,8594=>964,8595=>964,8596=>964,8597=>964,8598=>964,8599=>964,8600=>964,8601=>964,8602=>964,8603=>964,8606=>964,8607=>964,8608=>964,8609=>964,8610=>964,8611=>964,8612=>964,8613=>964,8614=>964,8615=>964,8616=>964,8644=>964,8645=>964,8646=>964,8647=>964,8648=>964,8649=>964,8650=>964,8706=>608,8710=>729,8721=>856,8722=>584,8723=>584,8725=>1107,8730=>597,8800=>584,8804=>584,8805=>584,9251=>500,9674=>541,9675=>860,9711=>1020,9824=>626,9825=>694,9826=>595,9827=>776,9828=>626,9829=>694,9830=>595,9831=>776,9833=>333,9834=>556,9835=>778,9836=>778,9837=>556,9838=>556,9839=>556,11568=>352,11569=>872,11570=>872,11571=>720,11572=>720,11573=>720,11574=>664,11575=>752,11576=>752,11577=>720,11578=>720,11579=>596,11580=>698,11581=>742,11582=>574,11583=>742,11584=>872,11585=>872,11586=>312,11587=>720,11588=>696,11589=>720,11590=>584,11591=>742,11592=>796,11593=>613,11594=>672,11595=>888,11596=>836,11597=>524,11598=>720,11599=>300,11600=>836,11601=>300,11602=>718,11603=>388,11604=>872,11605=>872,11606=>696,11607=>308,11608=>640,11609=>872,11610=>872,11611=>762,11612=>424,11613=>720,11614=>762,11615=>720,11616=>709,11617=>720,11618=>541,11619=>828,11620=>454,11621=>828,11631=>482,11799=>333,42888=>333,42889=>276,42890=>342,42891=>258,42892=>258,64256=>607,64257=>576,64258=>603,64259=>849,64260=>849,64261=>627,64275=>1243,64276=>1226,64277=>1233,64278=>1238,64279=>1448,64285=>284,64286=>305,64287=>542,64288=>653,64289=>964,64290=>888,64291=>932,64292=>845,64293=>917,64294=>933,64295=>850,64296=>1006,64297=>584,64298=>840,64299=>840,64300=>840,64301=>840,64302=>714,64303=>714,64304=>714,64305=>651,64306=>557,64307=>638,64308=>682,64309=>348,64310=>443,64312=>670,64313=>354,64314=>590,64315=>595,64316=>667,64318=>704,64320=>429,64321=>670,64323=>661,64324=>660,64326=>671,64327=>672,64328=>600,64329=>840,64330=>756,64331=>212,64332=>591,64333=>550,64334=>568,64335=>714,65533=>900,65535=>700); // --- EOF --- PKa\ ]fonts/pdfatimesi.znuW+AxuTU[)n8ԡSSp$-)%% %ݝ- {]{zclν\s5 jL"f$։,.)98[MTA.`G0Ė xLMvk,2&9Kd;A';j ;7 !|E###2la5 :ו+_W,Itkco^g[aFHlAа&n_ɐ8Xr tr͡bv4g9CÕ5؀lM& -2/u7;`2[+;9]/YYXX,> nm@mQQ+ M& ';+ecBa,ck_fv t{'t')@37_%Jݯ${ ~_5J tտ]=B" +'3`GI+Ldj 07vl R8=t ˟7-m rtp}dk{$@ [S0vp0vCF `/W>sv@V팡m`B[[8hٛX86&4X[;[v Shߛx6P1i1#$hzۿ #ƿ^{+ v58nvG0r7t9@5/b{3' ]NV:= S4<tHN#A\@oO ? ֐3x.lXֿJ ;o1 K ǿ >.NȽ nؽ ^?(y/XR (}/؁2({/8r (/ x/xJ` 6` j .j #xYh`ljr%e@W&/)l v0uy9οGS}rAAAr^ɽ#쁂-h@q-(N zV?++ bB(6@A߽ @q( |}X+b?P距fen8qN`kgJ8?8XY&ƎƲͭ!?B9am s?Hf V()6=+5Arƅ%7:Bfjy/lS/(4$H6s_<z_ύ?M J(P2l0>(@6J#x&('@yʯ?'C30nBl faay`c_{`yA_4՛uv+E+.hyC@= mf4L JP %̯Yl PXC,ж遙9`Ў-D6Ʀ#3nJ_= 4 +O-#? +cSg{ۯz=(6(nu~Cyf 2yظ~z8[W([][ V(KcJD~/D(E~+"$ D:DPUeo ȃSF?SJ3({plPVJGplPjJ+6(=e 'P?}re'N4/PADzP*,J,J:*;(mvn\@'-Ppx pPRkuK 9@iebp.#(tEH"/2d4(MUPr:ߑ@'7O ?} 9aB?lH ?~AXe}O?"ᆒ@1GBG0P;  ^?p@Oߊ~ߦKoo=is0Cr"; nj]q{\DB9%SG\K3Vk޻(P-4u]y)М5fNN"ѻgcZ1MaMQQ,nһ _7+HPxMn6Bcs4Q.'=d2ORW$7m|URS=]%kWn!Ya-/]婴mh.0'z=%R-uS:O8im9G П2W~sȯ́58 'fꨮ~å1ܬ׊4f)uɜ 3BQXŊ+M,:F>L/H]t>wmQL|,\;}s,j<[AzpsyymHE@44`zV^G&M(I'Ԗ";riY' xVC[Գ;W͖ګTG%W_jٖUanJL7q-ֶզ}<¶܃vV4@FoVl/&!]tzKܷVoX)i2AUDF9>٧y DKSQ2\ݘHwmǟ(M3CM-8T)wkw. @o5|k̸tc}<Qxmhƨ¿̩%!厭\[?ho;.<@!}oβSgAA׏ہ>=C|Vdމlxu;7RsS0}_$Rf%W:w)'Ð/Q;ܖ$u{)~y^PÜ&a`=pI_2}qPUʟٞX'gDvڄ/bKV֪9GZþi|8tԎW!MUw~RCZwוJ@]`L:Xܷѭᝏ{D>QbD/^}Lm|بwwݐeec J:XC؞-xNgc=Fv>=7ӈu6{[Ga4+j VrC\b|tq m4pĐṄpk)KǑS C'D+064\2)yKL!W{aO~OGcK7D!^:x(p WvCz%T<~ΊMk;͓&zqɓF*?Jg*%aҝ|W]-5@Ts,-a>շ8oɳ"p7Iɯ9p?v']rbꞷ55%{ⴒ:uc|[!-0&we8*"}iK+B#˔ ]O`V:1<갲؟|gwҔYxLtU{!KQvifQI$t,ɖg5, DDlȥЫ2tۯ@4\)iBCI5(ڭvbbfSy>0)P-/pƫj(\ޖ_#3 d/|.:{ߩ, maKB#.b' #ͪˍ".h?z%p]" 1jHy^4Jܡ|0:cvQy]f,d <)V1qHIK)!wq.G:6_U7~'/ [śIUiڞ8t^H U]~Fǽb.,8 nf)3p9VW+]eQ |VG@- 28Jl0^O T]vudÓ+J g$҆YjBL)or23Â0hJ;$FRFNYx>`Üy{CsՆvyQW2ۅolevϸ#nryȨXjJsGblcCtq D'l \\_ Cx<vo 9"_+bcqn~*VJ[[~gk4ZDEFZI*xf[bӛYQ>M6 :Fdn:{IX$bx"B[+?I<*-H=q'M~W_$cɉH5jO)mk{5<s F;Am/pFWy#S$`k=#JB Dl\"q)6OV&K3I3t].?;[JFn^.̗pr3þ"V&:|ɰܮ=t?^=7(u A$BМ<,fkȈ+EX"a hE^s3IVCqrl…Z2jZpH{Ix%yJ( 8!v?3U[eJ{0ɺ$8]_􉗎, P&DULca_-jDvShx\f+;ȗsk]G7tik?RʊjaTtD*ICWTR;3G BuTy@Ӓy{G+'̻{q!v+")U5{j=M95R= bAQZԄ= }Xa |EXadGaOwBD|(t)v4iyd~8ϻjHV=׼5;#L|XP1T(a1onmE||t2[$%cfI6##$+O/ ^zRkmt4dFgmy dD9eg4'/Ky'S[Q% X) 'e.[,D v^95}f*~\2912s(m#%ineXjd}oQ1`چ.c]xb\<51)yN\"7md_.P`!UT"嗖c%$uِ2@UG):᪾ͻy WW@|s\-4dy_e[6g[<+jZ@|/BXvV,dt[ gy/gԈz 6!OW9ZЭFao)YD A6mC#GGOԕzl9(s*j0r6{K_>yM3ZSg<ܾmb101- e@#WT4P5gOѳ[ }o&-8VKv?sRi0NV1NF|%Qc/[D^B?Tf Mx3^ W801ʟ&z"gh_ cZe68Nz up2w3y$D sOy> ^K}گQei55*HV5&ܖ84(9Ö %R~MF8ײx'[)]UڊP}B6\SV$ؐAg)a@F(mn"),V Ԣ[AH!ݵ9ow支j7Ϟ(f;DQY:Q٤}w$EA0: 7{L%Z?n^}vk"4pѓEG4U/wxu*D7莕JK[e٥z~r "Ȋ'ߠ~[0AlٻILrH%KFGr/ꚻ/,m3H\pM"mc7a?a mU@=8;"k¯ }eΌȷ<5iϟ++/}% $X"~JR]v0Qz%AɃ>~-ܻL-N'@~cYytMX ,{w6l0U /\1xfҧ{4j$I?aجJ]e uEj!̥\ZAm򘨎kE~MΝedX uc2ZA@S~#_H~)_.U0'=#AGFt9lVʟmgiYpkYɏ7.14 )k~}-j').Lq Oۂ<畹N3w6u{" (3s*螡UڢnFAx_1/@GӚiĭ6mŌnrңټ6ܮ{ d%D/>yɴf7 B )7tF,b..v0ۚS/ɣ^#mJr?UE28Ki3CݼTce._jZke#\aP_, Z??T_;o'>0j #,D@*%|Lu[ohanxM(3G,f5 ^0i(^ %݈jMǐ*h]r׶VA1e 9wQ lhʞXs̈׽o†T]܎n+OOķ%J/KD!N^ڣ:[MƝSz0_GTCs(ىj^i/y l"A2D]Yk fgK-i$GJLτ5 4 ^_CvqZihxRnLz)hUZC!o1b $3^qSW1n?eaf dGt2$K߉qVWi{ YQt(jGiy]c <_Sd%,hq}kYf}3Z+$_}qyՆ׭O;ոD2'(\_磚4="2 *+CuQoXT #^̢?m^ʒ4e %[apnLOK~]uF +|;#P38APj yFZSGmT>wi>5;몼hOƽncpZl@0hѥS3WqF3 Vl#sVd}st%)|U4eakTU(M ֲeRŠrSڧh}ų|r~ԨPDKvx[z,K?o^yo'Pc0푚Z}sLDHNW!= Ge+ ܗi-T0bQМiuԳb i3XAW&\n"z;uY78lS@1,Y髽P8 FFjFH',I[S#;IZavM7dM[p5X/G3O&vJSigG<&(ڂy,w^Ioz h8Y?p{Ҫl:.wǐC@$ظJRF]6hn)VڠizA2fvZUǼj-`";&ٵ 6&rط}#1xešqá/k&>!c*~`΍PyUϞ/("p%Ld6ҦOuz0Jr&bE"25A$T:]\ޱjBz G{{a~,cw^CM 0k4ɘI1ox:UOGwe U z̨<CVK]@53H4a26\7f AGJn)+,d-+&ZR33wiϼ&έfO4f 4Čy& uRU<ˏ:){/lWqW^[yZQs. -7t+7^SP"~> kJiNQnB6#@ѦuNƤ~^$]&X2.4)2Gʡ(eeIⲘԵFF*SΜ5E}a92+Xdж4;țnUaՐM"}3~лvJ&mP܋^5SXqo2 Z8Ɖ2|!eyʹƏ@Y;tb՚ k[&*]uUc uR td/q3ƎewM8*m-y¸hS!\z:D̅J.Ljwd4jk(Կ &׵5:9Xr(Y~GO15bNuS*i&r[X C;5 i^^4@9{7g߷>|1@2C{brKiSeKUo)g5?ik+M<,̆^G|k'>e]Ϛ# dd9K2#yI"P euI}F5'9AiÂH› ac ųSd"NnQjlDXaȶ)eٯ#.RK<8}^t'ÈF,>"؜ԭ>NƄDg2Yz}Dv׀Cy"8Χ\{)U%[ĸ{ϯTE>dTh³ϨZ }N^v?4=&rT$[g{::R) Qr|WHt#>jUkFU^L Et/~MC֬]&6S\:twmN1HG)/NJgA&.WUPi /뎤o]CFq鳑-I.k\0ƝiN-K_ۇ WrR6*>3x;Xb3נR'rcy$ZPqGo,xCES͡/sYA+8YvZYizw}K%OX=?p:+LJ>Qx">Ch+^Qװ³ GQE€1y=lnf$"!iDW$:qٙO  ]樓vSgG}*_=~8GE(g v*[ikDRz5?jA|LZ=.TZϖS}SN kcRxXNE{DV˹4$CUEfRK3^w~N|bX1Tٕ&ĚSMR;e3tDL-~[Vr˨oR&hUs'&_[OmQpI6zTM-D_YlDaݰoLFn_ģr0xQVê7Vf\7.J4kDl*u<)\ "GΪ܈C A:1w4T$iVh<(DEi&J̟wRc&CvioZ?4YOF_>Sܕob @ijQԵ2͈Kɋ@B$CLj5壡P³ŏgECg'#x +ū H9[|a\oЂ`P>E; FqZ1(: T(]"kr3vۥPpNc }|=DVS&.7g\z0|}F=^~XM./׬_wkoPc ^'Pكǥ*J 'J9hkpƥ g?.ѽVbvl.=ѱ =H &^F;Dwo(ժ3~ fnZ)&;H\ <{'&X0`&'Q^#B B4_OZEgR9Ђo!0j(fg*  (]EW1s~ݐZeF܁^O)vssY8faTNq&q#6UD. QxQyC@_Ru=AkB&ts {#Sd>1`[.(e3:'#Ǿ_U޼^kQƝ +6*V*҇iBS |/5E|ż;?3߄:K 9% BE%K" znɚyDǕց̔Ѭ}tvb}G[!'s=oŦ5ZzDJ=< Le2ԪakR3 !JPC߳pa$+6Α \IuB'҉'^=-٬M/#7R(CNe#"E^rO1P~"1`e{KЦÁb9ߛOHp.O CvS>es o1[X+qEEH P{xxu>j;jJ4Ɋ{zy BҴg?2bک@x%d>x cɃ Cn6H?tbD0NZ'č_*\×K;|}:M}'?c^៶b(uWe@S1tyaxjC%(K T(ȧ %!CP;4HY4␥F-~9/yGbKP_B—@d RV:gn}# $\_j|"ʰ!zB#dD!N-Ieq܋5:XE$r*7>rUf?Iij2FYBX!0!{O?sr=Sqܧ}J;m TE5BKrDA#|l<ђL=;W̖gǑvU>*zBxBG PrᄁjحqD?ՔO(L~])._rb ژ  JM!q1Khu]y^:([9G=qף?ěra)41,44ObC;JNˏ:qʽcՆ[סEan̅p3B*t, 1ipHECN2+: /1=F$$\~dEZCbq՛ x?yBjq7QrOF%|1 SDF2tapDZUPyIKbNa7Z7Brq XUmoG,7N`|jL!ةc`1}r94<3a|Ƿq6#{%Ms)Ŕ5<*{˦n wĆ 2i"s&;}|@ h,?۶LxF~r5B]%*+4&-ym hq@[4l)R-mszr$R <6t٥M@B@]:B<4=e*ȥ9NnsV#ԒHgWC_[R>VAF"X)SN^XJ(/ j{)X' Bv귈?1E!%;lS%kmJH~ ݦnfMMC KXnwX)[R׺6}{0eI ydSn(3 L~҃rHno6d֬+ ȂEvZ SFʾrۆ9 nI xWT`óy#ƣqI ,RX+/_;VlP cV#cda:hƘdS@MbڱKE18c |\j[$WuB}R x֔Sǭn6(,8þf߇`JǶ 7pcB[⁶ð>`P9謶\UHԬtzncd>aƮF^gBA]#)wU8v3oD\n|V:oL~Zt Mu=wҰX6-06vؕqSQQ]YŹ7 덄K(D"ؽwJ\/)25.?=$0e&❗x,@vM^xTH@`GaԬMA֝=[B[Pt1,j$Ɨ(*|O5m3Z@ѫwNpT]r0XꒋGCi/mo7N)mlaZb&x5TwaA oq5 ٜKx gY̕DCЉVqb$?cdQ5wUzBMUL*h'6Ol\SS`+FT]6+F7 ;Xlf4a*8؜)Gu[FirdHt5x#f U:NΖ7AI~Ŀ2&=ebh/" ^G+by}ztN}C۠ʉcSu!`#vf >WN0"ߩd mf*AK#zƿ'~(XTSUW5զ(D4w;?kqbA Q0D 7G8U Ly}+Dp(FNG. `9 xEYZD!k#MӅE>l>eUn2pcsnm;&3Ie`v78' Bw׀2kQxĐUAmyy DNiRGaꊋ5'\mD7[^&0qh::9%NWY(`^&,/g]Aݷ%.ʗ؊зLi?nIʙrWv1C;(Ua-|:f?c9.m836Ż&X"7y:BJQE\<寶!XWmr~q y61|EH\rIm"\Xfg LyjCnG! %f}qY\ 9j_urGY vN] viOZHdh'RXr5#~(i1U*r,hÙMl#\_#UWa_8 Etj5^֢mJyKw ͂/VlTsӏ-ou -\]~pq^bJ5IKHt~F*MaY9qޑxY>IVj:9)/E1us?(DԼ[5G+@Yg(JPGֻr>7dCK@^ɸKͻawr\!޽8 E|?Pց C˝R. AଆjħCRր)!ןrŐdO>X:%OJ?qE:.s%fkSD<7v}Q Qv+#))N9~7Ec< ؂x~_GZ}UsOj|Dﴎ?hk^r y&iަaQ.JJO{DXt˿.5.J{觽;M2"⧮ƽ$qgQ"!dsVg *7bbߎDϞZG1@0U? tAe^h,7 EoM? 1OT AoO4+rjؓtJax@|?%asAЋ@K/6!zͻ.P\e'F>jX,zTielj|lg {E@ ,-,6;bZ}4DNA`_..ETjr~S p=D}b).֞1քbI@\aZfwaj,/zWTRCH)\z|5O<ڌf&HHVV Kp2Hf!J>Gp+65~9g ʫz/$Ѝf9yD W;0 mZ8T:9Rm"TݙPO;Vi͉!oT*xv7dͿA#ؖ_ :d@4=Ϣ$Uw{SE[@$Ѥzx%XZOk 'J`lc;n[gD -n6s\~ta aL@5]-m3)pwcu TP^b[9~bEV2#+L)xgzΦ+` 0{UҎ dc ɤ֤*z{|MQj0IR7^r͏8/*;@!/b~4۸\|< B@VV-, |( F K *Q~) NN #ZnjXm J`Bk'dhx5)7o\7@=p㖃^݌*dhGϵSiSU4sȨ &zobE2[ I]0H<1t{R+b5Z뛻%]ɉ]aGge3 5#0> 3%Wq1]MԹ%k8,c,!ʓC)hb$i[h#j- 8z[p/ ($#dnCƂ6*1HSܣ;hj '"!(xE9fn9tڝrPeA7=7(/8\SK30[G*ju9:f.{:P;TZq2H@M!n%8+!q8+#;ѤۈtSI@f$.aI;vEߓ/pKN`#,v,{NlbirːZڏtٚ[[s٢P;vE,1Vi\=GR[nf9o{X0V!!khQ=gCiJÖN 0,G yF ;b^?!1+ua%4ޏFsl6Oe {7nQ]GD-M'A?ʹ'cY^﹨_>Go7e$&L~GrhE /KS|KlJ՟2Y߾$x}kued"Xm ԅsZTW<`FN~湛LX*/]͊QHYs+k.#>k[!< d$ &CX ,dh0[.9?[Y./l[cS 'X:@RZuH+l}P` bRp?z6Qӣc?[1LΆaP1AF kjEp/8f: `;˅Ë4;"wUwJQ,/d'H콣. g+FWz1a_+i_cW}!aag&wh1fQ + 2`+9y\ACW q݁Fvb1h %ݢT&x_39k$f }~GI ߡ%X"r/X/XZlmpi˒vlΤTֻ ^v2)r-C q*FV%g:XQRN ɱ;o%NtZ-9S,iX!ĹY&h&1x,Ҋw$nZX~YÅ$<:֚ZN@J[p6lE*G};E-_m|Z(5V&& ykuaoDV$.Sw1kޟ!ѽȭ`!,CrUZ'Qsݧ};Dzd®B cbuaZP=۶-ts 1v4FbY $VoBqpl\?&`DTnfImR8r]" gE_Rm*'pRWLF7bz@ CO*'RTINV*l.u5(aiY|t`i, #WGoj!)~Y(Ffk5tTJ >==X>aEwM#܄C1+WWl }Z(T3qJƋ!!*ح+XFZ~&%!^O{7߳m<לg.(_7!7V3%Y#iNaolAA ےT@ЬH@=jiHl0~]DʏC%tmJ*Y!_4&Rf2Fje͏j=OMLv܏_qCv }Y׽A/'l͎_GV>rH!м>?M]kO,wCM{cڰ`0_7faeFAQw{^@Hnj =5qe Va_])4صIVrY-w4 ZBܦEL.x1? i/A(;G>8['TC\!z+BXEOԋhkNGK8&JQ6GDaW24:mӗ\ix VA1ojMѩ@ _P0۱ `!xZW3̓9G1W,Cnq ѠɕÔj,ma*y[ك ;kSd*=ۣ2c$:ӗih!Oܻ/O`DK#n2F筤~Gן# Tn n-|l}lޢSրvF\CVtT'Jj00ci?PIVVvBO x-؜% kidK2}Sl^ĤF13g@NZn,V`64Z *o*=!pXJA%cNh ~[eńg+Q$Y۩'w3Q(/ޒp̟mrf0 18;?ָo7`#y9sjoPx_q\y7WC++3 0?ea-Ua#$o:15..sM^˾MDGB{q,|8/h> 61c l4d1j-XȳqniOm]iI gJTob'I?M2uTԾ4`b[)z*)e6٣A>9X0F͐]c% ˷͞;޽= [:>QpOɻ{ތeNt7NѪ XFMV~KT'F%1?)R2Q}ΞPEN~CVPO5&J CoN{Wl=S SBj28NBBΈsSr7UU5la-V~T)uun>7<3'oNRhfԥ#e+듖Q$Q>9yN!P&]*VW6/6^*)$To _aT\[4C ENcF>=/VS1+RL#yx˝5)elZKb0܉eX:g)Du5\;Db`Y^],4-?˰cf!66{[)^Ԉ!ZQ jaR#rˏ{ ztK˃*:x1$ɰMKBO!.6tXCe? ;!=/'];3#tˡAdN _r6)@QAahdРHnրpm2 8(P?239oN ((3FU3yfV%>YFxZckHtOgu>U{*Ń={p͋$"vnўxG"@'8{}oSߝ=B1@a3Xd+"^' m/lU}tΩgN?HnZcńo"ם)۰$w=. ,C,,\wEg8g9Y  .DL0|Ċ-Ǿj\ .}g BOA ٫-iBQSby,o4`mWП*֜3)k@e/koXq;P#t ag_22Bbn0TX#-Nk6a {g:WPyK\?yojt'*w4ą$:ƂH)cR5ReAy5b ݽR-؇ZȢcXGQH]PV:5n_`ɠ\ /ՀyȪX#\Y BjhU_`~вJŔ Ig Uf{\7eэ wFn@Z GVWrYuJtS#Q{fRU.}b}2…ք,1Y-EjTzU{s) I_g_ x *X?Ix1+QaŜ0:fer \$ BD}[ԟvH0(67n +{:ED%p$Av['X`9) CavX)])@vstR%RmΦnHlGoD30'OU*)3rPuJ*adrrL@ATADp&%v[ь(Ɛ 4IK3c_UuKm/"i|)ř5D_7ب $w"ʱi쵩\t 4r+Q}#'Zfz@PHӷڽhIQ`.s:VZWAr\~XYƫDy̡؆9ء ಐ7l+\]"Gph6\Tc4|;R XP'WhC2H垸I~}˔" fBȆn8AHa>m^})*DB2MzBU-eNG[vKSqdWNç\冚ŧ%{h1Fz$tpcQgc%Eo0RU%#CT _*6׾ ]G.2Mss62B B:rJ]3r(9M`\Co]"SL}D,  ˡ_9-Ep^p2&O~#oAwԠB>p+#˸W_ה),:b$ Y(AJ.%%-"^%8IL]:!øŕFE6.X@,)ra?S~DLaOKu>=?Q4lx `&پʔn{qnʎ;bQBS&;.h:xnCKH:9E/[D75Ҟ6>2mkig0#.b>Y87s-o, Ƴ^-HnE.EDOAG?S4ZQN=[!ܴw5Gͪ7U^3W9ſ],"7O{0r|7Ę4'/2Et1XTP+{lL@V?S{O60;$}ʩ 3~֦o=$8T*!icpl7\!$_skAnj x|>(recv"B7'l\,.D>&2J!ؾy?X t}tT6jQ9;LoFrGk DZES彘,Չnhoc::붳g0#nPRbn>5fN2>Ƌ++l\#&t' d\|P(NưU]$IQa@ H^። 1 J0#cQS(Ԓ) lY+-sٍ{m%NLϘPp!qna1.wip5A/͡Ȏ5I$9X8i<&G̏{Lcegϼ]6ެpA\g[7.2Mr5r,nsctNh8lAb _i):x}Dv 'i&/"cr} \M9!oI5sorذZ?`L8{J@p#۔E3*K뫍HT7'.;:@y&`1[4FӺƏ pHBX`,]y:"Lqɋn:l$ˤmLJM|[CnV% Ȇ[rh{) 0;,|,K΁yC 7Q3aWs"*bHUyW!:9.Z?̑/~ nPWRͧ58Szތjxo(cBvK 2a=@:{Yq*:yNI+ v%y:Qa(`{fZnbQ^pPS;yg;~kxͻCxPgܾei³ ekXD~Å|BPո!nו"g<|mc8<%KKUuaZ+_̞'Y(ׂXv ڄ6;R쎻Twcj`TN(QlR.wW>Y9'L2׾ F- wf br븬LxnY$fF1K~M>UýE TXV(;xX'^ù"f98igîtC0D3#.Ma]a'2 Ggg~GP* 3oq7{~oK{^(TOpr6G6>\—UxDDT)"GsZtÏ s ṕ@Gr\g_dv!$ȋ9fwu 8CF$@-9X?RS@՚?.L^1}4p,Τ1$ o"Nvl9BmWF=ThQĪ=7IHɝ.\|ظ\SD?iZl/lx/n'r5_㗓ؚ'~C8G5 !4NI>I'X~*@;%"&JwvdtY1&M DҐ#ž%6L| mCoVDXʎ%(C_P{VgcXӲdg60p 86bX cNZͻݶzۭ,I#Hk+bkt`(0pFfيV/?qV*n^aH4D.}zҀ SpZe$Clϱ*>VGc}gv)L\ f^luc<fRQP-,EǘHH;Kl6f5G~2zR@QT_-BIqzшȍ[l&SIuwS=\"*=1 SgV%8Z%څA˩Mu za+.ƧЫ.-\ÒU%.s^Y\,1?ro P"PiRz},Y0HӐ)( !4}B<bx!tڌ^LQHmO6#vfjtxwfx0u62li7xGPNu8cT͂~R0OFJBCj bK yP7){ww%_z_NT`@^90}al㩡[;zJLmn{9WB WS|t5 <8RVFxjx&4Y7S>{| ll{lKJ4O`=JWnedž6-_5Zo[ll"uWj6 ?cf/e) t,T 'abNC^l5`)K<!uSj;c b(׉fVty3~ٰO25o-*#cl4FG aP=2:'<ӿ= Hˇ}#qOzf@=\].N9cb.H#:4HT,'LWεX:OX`",tÓ^ݪicpBQ̀$Uwl֎| XcG4"Fk܊׶EZyT$>'(<Hu7Ɔ'CH+-BSsoXHZǟb'vLlv`pp PJ ½6H{jCsꩡC.?N8QL"ƚ8 s/Ի*XM!hAh}g!+P5{ E#t\oՏ;]IswSnN&Y.h ^RSga剷6־PЯV?ZQF9$?/-Ô$@JML֑|m6- t\@ Lfo5n#'9e`bLd/&^_C< dr_zj Iꎷ,>iH^ ̷G%"^2.|4/4"LEŎ:lp# >AΓyNWv@mFX&L`H }$ˬDDrWmyNN ΰF7l,v: 3Ѻ(A(Z E^r,;7mϭ}U -M,j*?UJqNYv%ꇾ:;1D\Bn_‹mya2 rQ^5{WEK8\gC_>#yWHAixת\ b잺hPKa\fonts/freesans.phpnuW+A32,'FontBBox'=>'[-1166 -469 1518 1050]','ItalicAngle'=>0,'Ascent'=>1000,'Descent'=>-300,'Leading'=>90,'CapHeight'=>729,'XHeight'=>524,'StemV'=>70,'StemH'=>30,'AvgWidth'=>441,'MaxWidth'=>1501,'MissingWidth'=>700); $cw=array(0=>0,1=>700,2=>700,3=>700,4=>700,5=>700,6=>700,7=>700,8=>0,9=>600,10=>700,11=>700,12=>700,13=>600,14=>700,15=>700,16=>700,17=>700,18=>700,19=>700,20=>700,21=>700,22=>700,23=>700,24=>700,25=>700,26=>700,27=>700,28=>700,29=>0,30=>700,31=>700,32=>278,33=>278,34=>355,35=>556,36=>556,37=>889,38=>667,39=>191,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>278,59=>278,60=>584,61=>584,62=>584,63=>556,64=>1015,65=>667,66=>667,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>500,75=>667,76=>556,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>278,92=>278,93=>277,94=>469,95=>556,96=>333,97=>556,98=>556,99=>500,100=>556,101=>556,102=>278,103=>556,104=>556,105=>222,106=>222,107=>500,108=>222,109=>833,110=>556,111=>556,112=>556,113=>556,114=>333,115=>500,116=>278,117=>556,118=>500,119=>722,120=>500,121=>500,122=>500,123=>334,124=>260,125=>334,126=>584,127=>700,128=>667,129=>667,130=>722,131=>667,132=>722,133=>778,134=>722,135=>556,136=>556,137=>556,138=>556,139=>556,140=>556,141=>500,142=>556,143=>556,144=>556,145=>556,146=>251,147=>251,148=>251,149=>251,150=>556,151=>556,152=>556,153=>556,154=>556,155=>556,156=>556,157=>556,158=>556,159=>556,160=>278,161=>278,162=>556,163=>556,164=>556,165=>556,166=>260,167=>556,168=>333,169=>737,170=>370,171=>448,172=>584,173=>333,174=>737,175=>333,176=>606,177=>584,178=>350,179=>350,180=>333,181=>556,182=>537,183=>278,184=>333,185=>350,186=>365,187=>448,188=>869,189=>869,190=>879,191=>556,192=>667,193=>667,194=>667,195=>667,196=>667,197=>667,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>666,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>896,231=>500,232=>556,233=>556,234=>556,235=>556,236=>251,237=>251,238=>251,239=>251,240=>556,241=>556,242=>556,243=>556,244=>556,245=>556,246=>556,247=>584,248=>611,249=>556,250=>556,251=>556,252=>556,253=>500,254=>555,255=>500,256=>667,257=>556,258=>667,259=>556,260=>667,261=>556,262=>722,263=>500,264=>722,265=>500,266=>722,267=>500,268=>722,269=>500,270=>722,271=>722,272=>722,273=>556,274=>667,275=>556,276=>667,277=>556,278=>667,279=>556,280=>667,281=>556,282=>667,283=>556,284=>778,285=>556,286=>778,287=>556,288=>778,289=>556,290=>778,291=>556,292=>722,293=>556,294=>722,295=>556,296=>278,297=>251,298=>278,299=>251,300=>278,301=>251,302=>278,303=>222,304=>278,305=>251,306=>740,307=>384,308=>500,309=>222,310=>667,311=>500,312=>500,313=>556,314=>222,315=>556,316=>222,317=>556,318=>367,319=>556,320=>500,321=>556,322=>222,323=>722,324=>556,325=>722,326=>556,327=>722,328=>556,329=>702,330=>710,331=>556,332=>778,333=>556,334=>778,335=>556,336=>778,337=>556,338=>1000,339=>938,340=>722,341=>333,342=>722,343=>333,344=>722,345=>333,346=>667,347=>500,348=>667,349=>500,350=>667,351=>500,352=>667,353=>500,354=>611,355=>278,356=>611,357=>443,358=>611,359=>278,360=>722,361=>556,362=>722,363=>556,364=>722,365=>556,366=>722,367=>556,368=>722,369=>556,370=>722,371=>556,372=>944,373=>722,374=>667,375=>500,376=>667,377=>611,378=>500,379=>611,380=>500,381=>611,382=>500,383=>278,384=>556,385=>854,386=>668,387=>556,388=>717,389=>596,390=>722,391=>767,392=>575,393=>722,394=>899,395=>667,396=>556,397=>564,398=>667,399=>722,400=>667,401=>611,402=>278,403=>802,404=>667,405=>889,406=>278,407=>345,408=>667,409=>500,410=>345,411=>560,412=>833,413=>722,414=>556,415=>778,416=>788,417=>565,418=>944,419=>722,420=>842,421=>556,422=>666,423=>667,424=>500,425=>611,426=>333,427=>278,428=>611,429=>278,430=>611,431=>776,432=>624,433=>778,434=>722,435=>722,436=>556,437=>611,438=>500,439=>611,440=>611,441=>500,442=>500,443=>556,446=>556,447=>556,448=>260,449=>370,450=>584,451=>278,452=>1311,453=>1208,454=>1056,455=>1056,456=>778,457=>444,458=>1158,459=>944,460=>778,461=>667,462=>556,463=>278,464=>251,465=>778,466=>556,467=>722,468=>556,469=>722,470=>556,471=>722,472=>556,473=>722,474=>556,475=>722,476=>556,477=>556,478=>667,479=>556,480=>667,481=>556,482=>1000,483=>896,484=>778,485=>556,486=>778,487=>556,488=>667,489=>500,490=>778,491=>556,492=>778,493=>556,494=>611,495=>526,496=>222,497=>1333,498=>1222,499=>1056,500=>778,501=>556,503=>630,504=>722,505=>556,506=>667,507=>556,508=>1000,509=>896,510=>778,511=>611,512=>667,513=>556,514=>667,515=>556,516=>667,517=>556,518=>667,519=>556,520=>278,521=>251,522=>278,523=>251,524=>778,525=>556,526=>778,527=>556,528=>722,529=>333,530=>722,531=>333,532=>722,533=>556,534=>722,535=>556,536=>667,537=>500,538=>611,539=>278,540=>521,541=>393,542=>722,543=>556,548=>611,549=>500,550=>667,551=>556,552=>667,553=>556,554=>778,555=>556,556=>778,557=>556,558=>778,559=>556,560=>778,561=>556,562=>667,563=>500,567=>222,592=>556,593=>562,594=>571,595=>556,596=>500,597=>500,598=>608,599=>602,600=>556,601=>556,602=>804,603=>500,604=>499,605=>742,606=>510,607=>283,608=>596,609=>556,610=>556,611=>500,612=>556,613=>556,614=>556,615=>556,616=>268,617=>255,618=>278,619=>473,620=>427,621=>260,622=>618,623=>833,624=>833,625=>833,626=>594,627=>596,628=>567,629=>556,630=>778,631=>722,632=>730,633=>333,634=>333,635=>372,636=>333,637=>333,638=>386,639=>371,640=>546,641=>546,642=>500,643=>299,644=>298,645=>309,646=>463,647=>278,648=>278,649=>596,650=>626,651=>539,652=>500,653=>722,654=>500,655=>556,656=>565,657=>508,658=>526,659=>552,660=>556,661=>556,662=>556,663=>722,664=>778,665=>506,666=>520,667=>623,668=>558,669=>469,670=>550,671=>430,672=>602,673=>556,674=>556,675=>940,676=>956,677=>944,678=>689,679=>515,680=>764,681=>786,682=>660,683=>597,684=>530,685=>486,686=>570,687=>631,688=>333,689=>333,690=>167,691=>236,692=>236,693=>276,694=>359,695=>500,696=>330,697=>278,698=>454,699=>278,700=>278,701=>278,702=>333,703=>333,704=>333,705=>333,706=>333,707=>333,708=>333,709=>333,710=>333,711=>333,712=>333,713=>333,714=>333,715=>333,716=>272,717=>333,718=>333,719=>333,720=>333,721=>333,722=>333,723=>333,724=>333,725=>333,726=>333,727=>333,728=>333,729=>333,730=>333,731=>333,732=>333,733=>333,734=>333,735=>510,736=>333,737=>186,738=>333,739=>333,740=>334,741=>526,742=>526,743=>526,744=>526,745=>526,746=>519,747=>519,748=>333,749=>333,750=>333,751=>333,752=>333,753=>333,754=>333,755=>327,756=>261,757=>437,758=>437,759=>333,760=>278,761=>200,762=>200,763=>200,764=>200,765=>333,766=>333,767=>333,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,842=>0,843=>0,844=>0,845=>0,846=>0,847=>0,848=>0,849=>0,850=>0,851=>0,852=>0,853=>0,854=>0,855=>0,856=>0,857=>0,858=>0,859=>0,860=>0,861=>0,862=>0,863=>0,864=>0,865=>0,866=>0,867=>0,868=>0,869=>0,870=>0,871=>0,872=>0,873=>0,874=>0,875=>0,876=>0,877=>0,878=>0,879=>0,884=>278,885=>199,890=>332,894=>278,900=>333,901=>333,902=>667,903=>275,904=>786,905=>828,906=>369,908=>833,910=>845,911=>778,912=>286,913=>667,914=>667,915=>582,916=>778,917=>667,918=>628,919=>722,920=>778,921=>278,922=>667,923=>667,924=>833,925=>722,926=>630,927=>778,928=>722,929=>667,931=>628,932=>611,933=>667,934=>717,935=>667,936=>745,937=>778,938=>278,939=>667,940=>596,941=>528,942=>548,943=>307,944=>538,945=>596,946=>542,947=>531,948=>564,949=>512,950=>455,951=>548,952=>525,953=>286,954=>510,955=>551,956=>540,957=>500,958=>470,959=>546,960=>619,961=>569,962=>547,963=>620,964=>492,965=>538,966=>741,967=>571,968=>662,969=>740,970=>286,971=>538,972=>546,973=>538,974=>740,977=>580,978=>742,979=>845,980=>620,981=>741,982=>740,983=>556,1008=>556,1009=>566,1012=>778,1013=>328,1024=>667,1025=>657,1026=>766,1027=>582,1028=>722,1029=>667,1030=>278,1031=>278,1032=>500,1033=>1080,1034=>1014,1035=>766,1036=>628,1037=>730,1038=>613,1039=>722,1040=>666,1041=>668,1042=>668,1043=>582,1044=>812,1045=>657,1046=>905,1047=>667,1048=>730,1049=>730,1050=>632,1051=>674,1052=>846,1053=>721,1054=>796,1055=>721,1056=>654,1057=>722,1058=>611,1059=>613,1060=>861,1061=>657,1062=>742,1063=>626,1064=>830,1065=>851,1066=>841,1067=>874,1068=>670,1069=>717,1070=>1001,1071=>686,1072=>552,1073=>550,1074=>506,1075=>404,1076=>602,1077=>547,1078=>755,1079=>499,1080=>567,1081=>567,1082=>489,1083=>517,1084=>618,1085=>558,1086=>550,1087=>557,1088=>577,1089=>520,1090=>444,1091=>468,1092=>865,1093=>466,1094=>578,1095=>498,1096=>692,1097=>712,1098=>664,1099=>690,1100=>521,1101=>520,1102=>759,1103=>543,1104=>549,1105=>549,1106=>577,1107=>404,1108=>519,1109=>502,1110=>224,1111=>251,1112=>223,1113=>813,1114=>853,1115=>577,1116=>489,1117=>567,1118=>468,1119=>558,1120=>942,1121=>693,1136=>762,1137=>662,1138=>800,1139=>550,1148=>942,1149=>693,1150=>942,1151=>693,1154=>468,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1160=>0,1161=>0,1162=>763,1163=>583,1164=>689,1165=>526,1166=>652,1167=>572,1168=>601,1169=>397,1170=>589,1171=>392,1172=>591,1173=>475,1174=>927,1175=>830,1176=>661,1177=>493,1178=>658,1179=>510,1180=>675,1181=>519,1182=>684,1183=>514,1184=>839,1185=>653,1186=>740,1187=>570,1188=>987,1189=>714,1190=>1058,1191=>808,1192=>810,1193=>645,1194=>722,1195=>516,1196=>611,1197=>402,1198=>668,1199=>578,1200=>668,1201=>588,1202=>664,1203=>488,1204=>936,1205=>679,1206=>638,1207=>521,1208=>630,1209=>498,1210=>630,1211=>498,1212=>927,1213=>699,1214=>927,1215=>699,1216=>254,1217=>905,1218=>755,1219=>668,1220=>512,1221=>696,1222=>524,1223=>721,1224=>558,1225=>744,1226=>571,1227=>630,1228=>498,1229=>869,1230=>631,1231=>254,1232=>666,1233=>552,1234=>666,1235=>552,1236=>1000,1237=>879,1238=>657,1239=>547,1240=>722,1241=>543,1242=>722,1243=>543,1244=>905,1245=>755,1246=>667,1247=>499,1248=>611,1249=>540,1250=>730,1251=>567,1252=>730,1253=>567,1254=>796,1255=>550,1256=>800,1257=>550,1258=>800,1259=>550,1260=>717,1261=>520,1262=>613,1263=>468,1264=>613,1265=>468,1266=>613,1267=>468,1268=>626,1269=>498,1270=>582,1271=>395,1272=>874,1273=>690,1296=>667,1297=>491,1298=>665,1299=>509,1306=>778,1307=>575,1308=>934,1309=>712,1310=>627,1311=>489,1329=>720,1330=>696,1331=>750,1332=>725,1333=>699,1334=>751,1335=>446,1336=>703,1337=>790,1338=>656,1339=>697,1340=>390,1341=>852,1342=>791,1343=>698,1344=>585,1345=>656,1346=>651,1347=>658,1348=>759,1349=>595,1350=>772,1351=>603,1352=>703,1353=>648,1354=>698,1355=>744,1356=>738,1357=>703,1358=>739,1359=>660,1360=>693,1361=>623,1362=>385,1363=>788,1364=>632,1365=>775,1366=>714,1369=>333,1370=>222,1371=>200,1372=>333,1373=>333,1374=>333,1375=>333,1377=>833,1378=>551,1379=>572,1380=>569,1381=>546,1382=>581,1383=>353,1384=>551,1385=>568,1386=>569,1387=>552,1388=>276,1389=>795,1390=>535,1391=>553,1392=>537,1393=>512,1394=>568,1395=>552,1396=>531,1397=>249,1398=>527,1399=>405,1400=>551,1401=>390,1402=>833,1403=>509,1404=>523,1405=>545,1406=>584,1407=>879,1408=>552,1409=>552,1410=>301,1411=>884,1412=>578,1413=>556,1414=>668,1415=>544,1417=>278,1418=>333,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1467=>0,1468=>0,1469=>0,1470=>488,1471=>0,1472=>212,1473=>0,1474=>0,1475=>278,1476=>0,1488=>640,1489=>591,1490=>466,1491=>598,1492=>622,1493=>212,1494=>351,1495=>623,1496=>608,1497=>200,1498=>526,1499=>550,1500=>600,1501=>623,1502=>621,1503=>212,1504=>378,1505=>607,1506=>587,1507=>575,1508=>568,1509=>540,1510=>590,1511=>606,1512=>547,1513=>776,1514=>687,1520=>424,1521=>412,1522=>400,1523=>184,1524=>344,1792=>600,1793=>201,1794=>201,1795=>201,1796=>201,1797=>500,1798=>500,1799=>500,1800=>370,1801=>370,1802=>574,1803=>574,1804=>645,1805=>574,1807=>0,1808=>452,1809=>452,1810=>574,1811=>645,1812=>645,1813=>509,1814=>509,1815=>682,1816=>585,1817=>404,1818=>627,1819=>718,1820=>718,1821=>484,1822=>682,1823=>600,1824=>660,1825=>682,1826=>538,1827=>718,1828=>718,1829=>718,1830=>574,1831=>574,1832=>638,1833=>585,1834=>509,1835=>682,1836=>682,1840=>0,1841=>0,1842=>0,1843=>0,1844=>0,1845=>0,1846=>0,1847=>0,1848=>0,1849=>0,1850=>0,1851=>0,1852=>0,1853=>0,1854=>0,1855=>0,1856=>0,1857=>0,1858=>0,1859=>0,1860=>0,1861=>0,1862=>0,1863=>0,1864=>0,1865=>0,1866=>0,2304=>0,2305=>0,2306=>0,2307=>305,2308=>702,2309=>717,2310=>828,2311=>464,2312=>464,2313=>582,2314=>804,2315=>921,2316=>641,2317=>433,2318=>433,2319=>433,2320=>433,2321=>856,2322=>827,2323=>837,2324=>856,2325=>749,2326=>780,2327=>522,2328=>590,2329=>650,2330=>620,2331=>644,2332=>703,2333=>692,2334=>680,2335=>568,2336=>531,2337=>611,2338=>538,2339=>608,2340=>564,2341=>660,2342=>500,2343=>593,2344=>568,2345=>568,2346=>479,2347=>733,2348=>492,2349=>578,2350=>518,2351=>556,2352=>435,2353=>435,2354=>656,2355=>661,2356=>661,2357=>492,2358=>646,2359=>479,2360=>667,2361=>486,2364=>6,2365=>442,2366=>211,2367=>226,2368=>225,2369=>0,2370=>0,2371=>0,2372=>0,2373=>0,2374=>84,2375=>0,2376=>0,2377=>226,2378=>225,2379=>226,2380=>226,2381=>0,2382=>0,2384=>839,2385=>0,2386=>0,2387=>0,2388=>0,2389=>0,2392=>749,2393=>780,2394=>522,2395=>703,2396=>611,2397=>538,2398=>733,2399=>556,2400=>900,2401=>626,2402=>625,2403=>625,2404=>674,2405=>674,2406=>575,2407=>575,2408=>575,2409=>575,2410=>575,2411=>575,2412=>575,2413=>575,2414=>575,2415=>575,2416=>365,2417=>387,2418=>717,2425=>814,2426=>556,2427=>568,2428=>703,2429=>575,2430=>611,2431=>492,2433=>0,2434=>300,2435=>264,2437=>656,2438=>829,2439=>507,2440=>564,2441=>539,2442=>559,2443=>600,2444=>481,2447=>580,2448=>627,2451=>540,2452=>613,2453=>570,2454=>467,2455=>481,2456=>438,2457=>483,2458=>408,2459=>509,2460=>601,2461=>563,2462=>771,2463=>401,2464=>404,2465=>540,2466=>408,2467=>460,2468=>543,2469=>477,2470=>418,2471=>433,2472=>445,2474=>499,2475=>594,2476=>397,2477=>565,2478=>458,2479=>433,2480=>410,2482=>508,2486=>518,2487=>445,2488=>508,2489=>460,2492=>0,2493=>440,2494=>193,2495=>189,2496=>180,2497=>0,2498=>0,2499=>0,2500=>0,2503=>295,2504=>303,2507=>0,2508=>0,2509=>0,2510=>356,2519=>219,2524=>553,2525=>408,2527=>439,2528=>594,2529=>481,2530=>0,2531=>0,2534=>500,2535=>437,2536=>479,2537=>530,2538=>497,2539=>500,2540=>482,2541=>503,2542=>517,2543=>481,2544=>377,2545=>377,2546=>429,2547=>383,2548=>429,2549=>478,2550=>545,2551=>158,2552=>365,2553=>280,2554=>357,2561=>0,2562=>0,2563=>351,2565=>860,2566=>1088,2567=>869,2568=>928,2569=>723,2570=>723,2575=>665,2576=>857,2579=>716,2580=>858,2581=>682,2582=>634,2583=>696,2584=>744,2585=>649,2586=>674,2587=>656,2588=>653,2589=>629,2590=>639,2591=>641,2592=>657,2593=>650,2594=>653,2595=>651,2596=>640,2597=>634,2598=>662,2599=>630,2600=>625,2602=>645,2603=>653,2604=>624,2605=>613,2606=>658,2607=>734,2608=>620,2610=>676,2611=>719,2613=>626,2614=>666,2616=>666,2617=>614,2620=>0,2622=>286,2623=>322,2624=>301,2625=>0,2626=>0,2631=>0,2632=>0,2635=>0,2636=>0,2637=>0,2641=>0,2649=>636,2650=>762,2651=>652,2652=>653,2654=>656,2662=>672,2663=>543,2664=>622,2665=>622,2666=>576,2667=>589,2668=>509,2669=>645,2670=>661,2671=>655,2672=>0,2673=>0,2674=>666,2675=>726,2676=>1217,2677=>0,2689=>22,2690=>23,2691=>0,2693=>775,2694=>979,2695=>594,2696=>568,2697=>525,2698=>724,2699=>942,2700=>558,2701=>775,2703=>775,2704=>775,2705=>979,2707=>979,2708=>979,2709=>610,2710=>706,2711=>623,2712=>610,2713=>601,2714=>614,2715=>642,2716=>684,2717=>634,2718=>644,2719=>509,2720=>541,2721=>539,2722=>524,2723=>657,2724=>547,2725=>616,2726=>494,2727=>601,2728=>627,2730=>524,2731=>620,2732=>691,2733=>687,2734=>468,2735=>590,2736=>509,2738=>571,2739=>687,2741=>526,2742=>620,2743=>575,2744=>620,2745=>549,2748=>53,2749=>415,2750=>241,2751=>186,2752=>217,2753=>32,2754=>21,2755=>38,2756=>27,2757=>45,2759=>41,2760=>46,2761=>207,2763=>190,2764=>182,2765=>16,2768=>962,2784=>949,2785=>609,2786=>0,2787=>0,2790=>479,2791=>502,2792=>484,2793=>471,2794=>501,2795=>527,2796=>462,2797=>524,2798=>454,2799=>495,2801=>752,4256=>587,4257=>620,4258=>642,4259=>815,4260=>600,4261=>595,4262=>799,4263=>893,4264=>622,4265=>597,4266=>939,4267=>602,4268=>603,4269=>790,4270=>587,4271=>623,4272=>799,4273=>601,4274=>792,4275=>724,4276=>847,4277=>599,4278=>812,4279=>603,4280=>653,4281=>590,4282=>754,4283=>596,4284=>653,4285=>651,4286=>596,4287=>888,4288=>593,4304=>436,4305=>491,4306=>528,4307=>692,4308=>447,4309=>447,4310=>628,4311=>734,4312=>449,4313=>445,4314=>843,4315=>449,4316=>449,4317=>682,4318=>449,4319=>480,4320=>682,4321=>468,4322=>710,4323=>623,4324=>697,4325=>447,4326=>702,4327=>447,4328=>470,4329=>440,4330=>632,4331=>449,4332=>470,4333=>536,4334=>449,4335=>656,4336=>474,4337=>630,4338=>394,4339=>419,4340=>422,4341=>436,4345=>528,4347=>515,4348=>449,5024=>678,5025=>756,5026=>604,5027=>770,5028=>969,5029=>207,5030=>633,5031=>800,5032=>474,5033=>689,5034=>672,5035=>446,5036=>637,5037=>776,5038=>511,5039=>723,5040=>528,5041=>591,5042=>839,5043=>963,5044=>615,5045=>563,5046=>705,5047=>800,5048=>558,5049=>880,5050=>966,5051=>675,5052=>527,5053=>733,5054=>779,5055=>547,5056=>756,5057=>834,5058=>604,5059=>632,5060=>605,5061=>1051,5062=>657,5063=>842,5064=>748,5065=>1192,5066=>842,5067=>632,5068=>668,5069=>928,5070=>626,5071=>655,5072=>502,5073=>696,5074=>642,5075=>518,5076=>952,5077=>622,5078=>710,5079=>521,5080=>556,5081=>656,5082=>622,5083=>881,5084=>760,5085=>564,5086=>567,5087=>712,5088=>717,5089=>838,5090=>617,5091=>689,5092=>767,5093=>728,5094=>690,5095=>551,5096=>859,5097=>957,5098=>900,5099=>779,5100=>805,5101=>621,5102=>604,5103=>842,5104=>653,5105=>737,5106=>601,5107=>901,5108=>655,5121=>941,5122=>941,5123=>941,5124=>941,5125=>726,5126=>726,5127=>726,5128=>726,5129=>726,5130=>726,5131=>726,5132=>941,5133=>941,5134=>941,5135=>941,5136=>941,5137=>941,5138=>882,5139=>882,5140=>882,5141=>882,5142=>726,5143=>882,5144=>882,5145=>882,5146=>882,5147=>726,5148=>494,5149=>347,5150=>447,5151=>329,5152=>329,5153=>452,5154=>452,5155=>276,5156=>451,5157=>463,5158=>289,5159=>216,5160=>400,5161=>400,5162=>400,5163=>1169,5164=>941,5165=>810,5166=>1012,5167=>941,5168=>941,5169=>941,5170=>941,5171=>726,5172=>726,5173=>726,5174=>726,5175=>726,5176=>726,5177=>726,5178=>941,5179=>941,5180=>941,5181=>941,5182=>941,5183=>941,5184=>726,5185=>882,5186=>726,5187=>882,5188=>882,5189=>726,5190=>882,5191=>726,5192=>726,5193=>390,5194=>159,5195=>332,5196=>742,5197=>742,5198=>742,5199=>742,5200=>744,5201=>744,5202=>744,5203=>744,5204=>744,5205=>744,5206=>744,5207=>914,5208=>912,5209=>912,5210=>914,5211=>912,5212=>914,5213=>744,5214=>916,5215=>744,5216=>916,5217=>916,5218=>744,5219=>916,5220=>744,5221=>915,5222=>477,5223=>855,5224=>855,5225=>855,5226=>855,5227=>592,5228=>592,5229=>592,5230=>592,5231=>592,5232=>610,5233=>713,5234=>592,5235=>608,5236=>718,5237=>764,5238=>764,5239=>718,5240=>764,5241=>718,5242=>718,5243=>763,5244=>735,5245=>763,5246=>764,5247=>718,5248=>764,5249=>734,5250=>763,5251=>361,5252=>361,5253=>708,5254=>708,5255=>708,5256=>651,5257=>592,5258=>592,5259=>592,5260=>592,5261=>592,5262=>610,5263=>713,5264=>592,5265=>608,5266=>608,5267=>763,5268=>763,5269=>608,5270=>763,5271=>608,5272=>609,5273=>763,5274=>627,5275=>763,5276=>763,5277=>609,5278=>763,5279=>625,5280=>763,5281=>361,5282=>361,5283=>592,5284=>592,5285=>592,5286=>592,5287=>592,5288=>610,5289=>713,5290=>592,5291=>608,5292=>592,5293=>763,5294=>763,5295=>592,5296=>763,5297=>592,5298=>592,5299=>763,5300=>610,5301=>763,5302=>763,5303=>592,5304=>763,5305=>608,5306=>763,5307=>346,5308=>276,5309=>346,5310=>331,5311=>562,5312=>712,5313=>712,5314=>712,5315=>712,5316=>712,5317=>712,5318=>712,5319=>712,5320=>712,5321=>868,5322=>828,5323=>828,5324=>712,5325=>828,5326=>712,5327=>712,5328=>466,5329=>452,5330=>466,5331=>712,5332=>712,5333=>712,5334=>712,5335=>712,5336=>712,5337=>712,5338=>712,5339=>712,5340=>868,5341=>828,5342=>828,5343=>868,5344=>828,5345=>868,5346=>712,5347=>828,5348=>712,5349=>828,5350=>828,5351=>712,5352=>828,5353=>712,5354=>466,5355=>262,5356=>624,5357=>504,5358=>524,5359=>504,5360=>521,5361=>504,5362=>520,5363=>624,5364=>504,5365=>520,5366=>620,5367=>660,5368=>659,5369=>620,5370=>676,5371=>620,5372=>620,5373=>660,5374=>637,5375=>676,5376=>659,5377=>620,5378=>659,5379=>636,5380=>659,5381=>309,5382=>365,5383=>309,5384=>458,5385=>315,5386=>315,5387=>347,5388=>1010,5389=>1020,5390=>872,5391=>872,5392=>830,5393=>830,5394=>830,5395=>854,5396=>854,5397=>854,5398=>854,5399=>1001,5400=>1002,5401=>1001,5402=>1002,5403=>1001,5404=>1002,5405=>998,5406=>998,5407=>998,5408=>998,5409=>998,5410=>998,5411=>998,5412=>998,5413=>594,5414=>516,5415=>516,5416=>516,5417=>516,5418=>516,5419=>532,5420=>636,5421=>516,5422=>532,5423=>671,5424=>672,5425=>671,5426=>672,5427=>671,5428=>672,5429=>671,5430=>672,5431=>687,5432=>672,5433=>671,5434=>672,5435=>671,5436=>688,5437=>671,5438=>372,5439=>505,5440=>464,5441=>460,5442=>830,5443=>830,5444=>830,5445=>830,5446=>830,5447=>830,5448=>556,5449=>556,5450=>556,5451=>556,5452=>556,5453=>556,5454=>691,5455=>712,5456=>343,5457=>362,5458=>624,5459=>817,5460=>817,5461=>817,5462=>817,5463=>824,5464=>824,5465=>824,5466=>824,5467=>980,5468=>972,5469=>465,5470=>742,5471=>742,5472=>742,5473=>742,5474=>742,5475=>742,5476=>742,5477=>742,5478=>742,5479=>742,5480=>898,5481=>848,5482=>410,5483=>742,5484=>742,5485=>744,5486=>744,5487=>825,5488=>742,5489=>742,5490=>744,5491=>744,5492=>800,5493=>800,5494=>800,5495=>800,5496=>800,5497=>800,5498=>800,5499=>493,5500=>592,5501=>460,5502=>875,5503=>875,5504=>875,5505=>777,5506=>795,5507=>875,5508=>875,5509=>644,5510=>592,5511=>592,5512=>592,5513=>592,5514=>782,5515=>782,5516=>782,5517=>782,5518=>1056,5519=>1056,5520=>1056,5521=>687,5522=>705,5523=>1056,5524=>1056,5525=>524,5526=>782,5527=>646,5528=>646,5529=>646,5530=>646,5531=>712,5532=>712,5533=>712,5534=>712,5535=>466,5536=>772,5537=>772,5538=>772,5539=>772,5540=>772,5541=>772,5542=>466,5543=>638,5544=>638,5545=>638,5546=>638,5547=>638,5548=>638,5549=>638,5550=>388,5551=>488,5552=>515,5553=>515,5554=>515,5555=>515,5556=>592,5557=>592,5558=>592,5559=>592,5560=>542,5561=>542,5562=>542,5563=>542,5564=>561,5565=>561,5566=>561,5567=>561,5568=>630,5569=>630,5570=>630,5571=>630,5572=>941,5573=>941,5574=>726,5575=>726,5576=>726,5577=>726,5578=>941,5579=>941,5580=>726,5581=>726,5582=>726,5583=>726,5584=>941,5585=>941,5586=>726,5587=>726,5588=>730,5589=>726,5590=>941,5591=>941,5592=>726,5593=>726,5594=>730,5595=>726,5596=>830,5597=>830,5598=>830,5599=>830,5600=>830,5601=>830,5602=>830,5603=>830,5604=>830,5605=>830,5606=>830,5607=>830,5608=>830,5609=>830,5610=>830,5611=>830,5612=>830,5613=>830,5614=>400,5615=>722,5616=>722,5617=>722,5618=>722,5619=>722,5620=>722,5621=>722,5622=>722,5623=>722,5624=>722,5625=>722,5626=>722,5627=>722,5628=>722,5629=>722,5630=>722,5631=>722,5632=>722,5633=>522,5634=>592,5635=>592,5636=>712,5637=>712,5638=>712,5639=>712,5640=>722,5641=>722,5642=>722,5643=>722,5644=>722,5645=>722,5646=>830,5647=>830,5648=>704,5649=>704,5650=>704,5651=>704,5652=>647,5653=>647,5654=>647,5655=>830,5656=>830,5657=>830,5658=>830,5659=>830,5660=>647,5661=>647,5662=>830,5663=>830,5664=>830,5665=>830,5666=>830,5667=>830,5668=>465,5669=>465,5670=>465,5671=>465,5672=>830,5673=>830,5674=>574,5675=>574,5676=>574,5677=>574,5678=>609,5679=>609,5680=>647,5681=>647,5682=>647,5683=>647,5684=>739,5685=>739,5686=>754,5687=>754,5688=>754,5689=>754,5690=>830,5691=>830,5692=>755,5693=>755,5694=>755,5695=>755,5696=>830,5697=>830,5698=>830,5699=>830,5700=>830,5701=>830,5702=>427,5703=>427,5704=>830,5705=>830,5706=>830,5707=>830,5708=>830,5709=>830,5710=>830,5711=>830,5712=>718,5713=>718,5714=>718,5715=>718,5716=>830,5717=>830,5718=>718,5719=>718,5720=>718,5721=>718,5722=>525,5723=>830,5724=>830,5725=>718,5726=>718,5727=>718,5728=>718,5729=>830,5730=>830,5731=>718,5732=>718,5733=>718,5734=>718,5735=>722,5736=>722,5737=>722,5738=>722,5739=>722,5740=>722,5741=>822,5742=>370,5743=>875,5744=>1056,5745=>1316,5746=>1314,5747=>963,5748=>981,5749=>1314,5750=>1330,5751=>668,5752=>778,5753=>778,5754=>698,5755=>698,5756=>778,5757=>778,5758=>400,5759=>400,6320=>726,6321=>726,6322=>726,6323=>882,6324=>726,6325=>726,6326=>786,6327=>744,6328=>592,6329=>764,6330=>592,6331=>712,6332=>712,6333=>712,6334=>504,6335=>504,6336=>830,6337=>830,6338=>1001,6339=>516,6340=>516,6341=>556,6342=>824,6343=>892,6344=>824,6345=>892,6346=>712,6347=>824,6348=>712,6349=>824,6350=>996,6351=>964,6352=>964,6353=>726,6354=>726,6355=>686,6356=>525,6357=>452,6358=>361,6359=>361,6360=>346,6361=>466,6362=>310,6363=>486,6364=>575,6365=>575,6366=>223,6367=>216,6368=>984,6369=>556,6370=>556,6371=>906,6372=>858,6373=>906,6374=>744,6375=>744,6376=>758,6377=>592,6378=>808,6379=>646,6380=>630,6381=>906,6382=>722,6383=>722,6384=>906,6385=>647,6386=>984,6387=>280,6388=>319,6389=>355,7680=>667,7681=>556,7682=>667,7683=>556,7684=>667,7685=>556,7686=>667,7687=>556,7688=>722,7689=>500,7690=>722,7691=>556,7692=>722,7693=>556,7694=>722,7695=>556,7696=>722,7697=>556,7698=>722,7699=>556,7700=>667,7701=>556,7702=>667,7703=>556,7704=>667,7705=>556,7706=>667,7707=>556,7708=>667,7709=>556,7710=>611,7711=>278,7712=>778,7713=>556,7714=>722,7715=>556,7716=>722,7717=>556,7718=>722,7719=>556,7720=>722,7721=>556,7722=>722,7723=>556,7724=>278,7725=>222,7726=>278,7727=>251,7728=>667,7729=>500,7730=>667,7731=>500,7732=>667,7733=>500,7734=>556,7735=>222,7736=>556,7737=>222,7738=>556,7739=>222,7740=>556,7741=>222,7742=>833,7743=>833,7744=>833,7745=>833,7746=>833,7747=>833,7748=>722,7749=>556,7750=>722,7751=>556,7752=>722,7753=>556,7754=>722,7755=>556,7756=>778,7757=>556,7758=>778,7759=>556,7760=>778,7761=>556,7762=>778,7763=>556,7764=>667,7765=>556,7766=>667,7767=>556,7768=>722,7769=>333,7770=>722,7771=>333,7772=>722,7773=>333,7774=>722,7775=>333,7776=>667,7777=>500,7778=>667,7779=>500,7780=>667,7781=>500,7782=>667,7783=>500,7784=>667,7785=>500,7786=>611,7787=>278,7788=>611,7789=>278,7790=>611,7791=>278,7792=>611,7793=>278,7794=>722,7795=>556,7796=>722,7797=>556,7798=>722,7799=>556,7800=>722,7801=>556,7802=>722,7803=>556,7804=>667,7805=>500,7806=>667,7807=>500,7808=>944,7809=>722,7810=>944,7811=>722,7812=>944,7813=>722,7814=>944,7815=>722,7816=>944,7817=>722,7818=>667,7819=>500,7820=>667,7821=>500,7822=>667,7823=>500,7824=>611,7825=>500,7826=>611,7827=>500,7828=>611,7829=>500,7830=>556,7831=>278,7832=>722,7833=>500,7834=>555,7835=>278,7840=>667,7841=>556,7842=>667,7843=>556,7844=>667,7845=>556,7846=>667,7847=>556,7848=>667,7849=>556,7850=>667,7851=>556,7852=>667,7853=>556,7854=>667,7855=>556,7856=>667,7857=>556,7858=>667,7859=>556,7860=>667,7861=>556,7862=>667,7863=>556,7864=>667,7865=>556,7866=>667,7867=>556,7868=>667,7869=>556,7870=>667,7871=>556,7872=>667,7873=>556,7874=>667,7875=>556,7876=>667,7877=>556,7878=>667,7879=>556,7880=>278,7881=>251,7882=>278,7883=>222,7884=>778,7885=>556,7886=>778,7887=>556,7888=>778,7889=>556,7890=>778,7891=>556,7892=>778,7893=>556,7894=>778,7895=>556,7896=>778,7897=>556,7898=>788,7899=>565,7900=>788,7901=>565,7902=>788,7903=>565,7904=>788,7905=>565,7906=>788,7907=>565,7908=>722,7909=>556,7910=>722,7911=>556,7912=>776,7913=>624,7914=>776,7915=>624,7916=>776,7917=>624,7918=>776,7919=>624,7920=>776,7921=>624,7922=>667,7923=>500,7924=>667,7925=>500,7926=>667,7927=>500,7928=>667,7929=>500,7936=>596,7937=>596,7938=>596,7939=>596,7940=>596,7941=>596,7942=>596,7943=>596,7944=>667,7945=>667,7946=>742,7947=>756,7948=>692,7949=>699,7950=>673,7951=>667,7952=>512,7953=>512,7954=>512,7955=>512,7956=>512,7957=>512,7960=>730,7961=>714,7962=>900,7963=>882,7964=>867,7965=>879,7968=>548,7969=>548,7970=>548,7971=>548,7972=>548,7973=>548,7974=>548,7975=>548,7976=>772,7977=>778,7978=>945,7979=>947,7980=>943,7981=>946,7982=>853,7983=>853,7984=>286,7985=>286,7986=>286,7987=>286,7988=>286,7989=>286,7990=>286,7991=>286,7992=>322,7993=>321,7994=>482,7995=>485,7996=>477,7997=>484,7998=>394,7999=>390,8000=>546,8001=>546,8002=>546,8003=>546,8004=>546,8005=>546,8008=>775,8009=>784,8010=>990,8011=>987,8012=>887,8013=>897,8016=>538,8017=>538,8018=>538,8019=>538,8020=>538,8021=>538,8022=>538,8023=>538,8025=>747,8027=>915,8029=>971,8031=>863,8032=>740,8033=>740,8034=>740,8035=>740,8036=>740,8037=>740,8038=>740,8039=>740,8040=>769,8041=>774,8042=>972,8043=>970,8044=>879,8045=>918,8046=>901,8047=>901,8048=>596,8049=>596,8050=>512,8051=>512,8052=>548,8053=>548,8054=>286,8055=>286,8056=>546,8057=>546,8058=>538,8059=>538,8060=>740,8061=>740,8064=>596,8065=>596,8066=>596,8067=>596,8068=>596,8069=>596,8070=>596,8071=>596,8072=>830,8073=>828,8074=>916,8075=>916,8076=>853,8077=>860,8078=>835,8079=>827,8080=>548,8081=>548,8082=>548,8083=>548,8084=>548,8085=>548,8086=>548,8087=>548,8088=>928,8089=>931,8090=>1104,8091=>1109,8092=>1099,8093=>1102,8094=>1009,8095=>1012,8096=>740,8097=>740,8098=>740,8099=>740,8100=>740,8101=>740,8102=>740,8103=>740,8104=>934,8105=>934,8106=>1130,8107=>1128,8108=>1045,8109=>1077,8110=>1062,8111=>1065,8112=>596,8113=>596,8114=>596,8115=>596,8116=>596,8118=>596,8119=>596,8120=>667,8121=>667,8122=>667,8123=>667,8124=>832,8125=>333,8126=>200,8127=>333,8128=>333,8129=>333,8130=>548,8131=>548,8132=>548,8134=>548,8135=>548,8136=>833,8137=>776,8138=>944,8139=>896,8140=>875,8141=>400,8142=>400,8143=>333,8144=>286,8145=>286,8146=>286,8147=>286,8150=>286,8151=>286,8152=>278,8153=>278,8154=>385,8155=>376,8157=>400,8158=>400,8159=>333,8160=>538,8161=>538,8162=>538,8163=>538,8164=>569,8165=>569,8166=>538,8167=>514,8168=>667,8169=>667,8170=>817,8171=>827,8172=>741,8173=>393,8174=>393,8175=>333,8178=>740,8179=>740,8180=>740,8182=>740,8183=>740,8184=>833,8185=>833,8186=>848,8187=>814,8188=>939,8189=>333,8190=>333,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>333,8197=>250,8198=>167,8199=>556,8200=>278,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>333,8209=>333,8210=>556,8211=>556,8212=>1000,8213=>1000,8214=>312,8215=>566,8216=>222,8217=>221,8218=>222,8219=>221,8220=>333,8221=>333,8222=>333,8223=>333,8224=>556,8225=>556,8226=>350,8227=>350,8228=>278,8229=>666,8230=>1000,8231=>278,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>500,8240=>1000,8241=>1360,8242=>278,8243=>469,8244=>680,8245=>278,8246=>469,8247=>680,8248=>376,8249=>250,8250=>250,8251=>622,8252=>556,8253=>556,8254=>556,8255=>658,8256=>658,8257=>438,8258=>840,8259=>400,8260=>167,8261=>334,8262=>334,8263=>1112,8264=>834,8265=>834,8266=>556,8267=>537,8268=>537,8269=>537,8270=>389,8271=>278,8272=>658,8273=>389,8274=>634,8275=>500,8276=>658,8277=>787,8278=>515,8279=>855,8280=>722,8281=>725,8282=>224,8283=>722,8284=>604,8285=>224,8286=>224,8287=>0,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8304=>350,8305=>140,8308=>350,8309=>350,8310=>350,8311=>350,8312=>350,8313=>350,8314=>350,8315=>350,8316=>350,8317=>350,8318=>350,8319=>360,8320=>350,8321=>350,8322=>350,8323=>350,8324=>350,8325=>350,8326=>350,8327=>350,8328=>350,8329=>350,8330=>350,8331=>350,8332=>350,8333=>350,8334=>350,8336=>363,8337=>366,8338=>360,8339=>325,8340=>350,8353=>615,8354=>601,8355=>611,8356=>556,8357=>833,8358=>682,8359=>1317,8360=>1202,8361=>879,8362=>869,8363=>538,8364=>655,8365=>667,8366=>611,8368=>570,8369=>684,8370=>717,8371=>667,8372=>667,8373=>640,8376=>516,8400=>0,8401=>0,8402=>0,8403=>0,8404=>0,8405=>0,8406=>0,8407=>0,8408=>0,8409=>0,8410=>0,8411=>0,8412=>0,8413=>0,8414=>0,8415=>0,8416=>0,8417=>0,8420=>0,8421=>0,8422=>0,8423=>0,8424=>0,8425=>0,8426=>0,8427=>0,8428=>0,8429=>0,8430=>0,8431=>0,8432=>0,8448=>870,8449=>859,8450=>722,8451=>1017,8452=>556,8453=>796,8454=>832,8455=>667,8456=>722,8457=>919,8459=>969,8460=>615,8461=>647,8462=>556,8463=>572,8464=>809,8465=>606,8466=>900,8467=>481,8468=>747,8469=>722,8470=>934,8471=>882,8472=>600,8473=>667,8474=>778,8475=>850,8476=>699,8477=>722,8478=>834,8479=>722,8480=>1043,8481=>1261,8482=>1000,8483=>667,8484=>611,8486=>778,8487=>778,8488=>512,8489=>286,8490=>667,8491=>667,8492=>908,8493=>623,8494=>556,8495=>469,8496=>562,8497=>895,8498=>588,8499=>1080,8501=>640,8502=>592,8503=>466,8504=>598,8505=>278,8506=>868,8507=>1338,8508=>619,8510=>582,8511=>722,8513=>778,8514=>556,8515=>556,8516=>667,8522=>516,8523=>655,8525=>1200,8526=>435,8531=>869,8532=>869,8533=>869,8534=>869,8535=>869,8536=>869,8537=>869,8538=>869,8539=>869,8540=>869,8541=>869,8542=>869,8543=>869,8544=>278,8545=>556,8546=>834,8547=>945,8548=>667,8549=>945,8550=>1223,8551=>1501,8552=>945,8553=>667,8554=>945,8555=>1223,8556=>556,8557=>722,8558=>722,8559=>833,8560=>222,8561=>444,8562=>666,8563=>722,8564=>500,8565=>722,8566=>944,8567=>1166,8568=>722,8569=>500,8570=>722,8571=>944,8572=>222,8573=>500,8574=>556,8575=>833,8592=>987,8593=>603,8594=>987,8595=>603,8596=>1042,8597=>1042,8598=>800,8599=>800,8600=>800,8601=>800,8614=>987,8617=>987,8618=>987,8629=>658,8636=>987,8637=>987,8638=>380,8639=>393,8640=>987,8641=>987,8642=>380,8643=>379,8652=>987,8656=>987,8657=>603,8658=>987,8659=>603,8660=>1042,8661=>603,8669=>1092,8704=>667,8706=>556,8707=>667,8709=>823,8710=>711,8711=>711,8712=>584,8713=>584,8714=>584,8715=>584,8716=>584,8717=>713,8719=>823,8720=>823,8721=>804,8722=>584,8723=>584,8724=>584,8725=>510,8726=>392,8727=>584,8729=>584,8730=>542,8733=>713,8734=>713,8736=>768,8739=>200,8740=>288,8741=>312,8742=>340,8743=>603,8744=>603,8745=>768,8746=>768,8747=>556,8748=>796,8749=>956,8750=>556,8756=>863,8764=>584,8765=>584,8766=>573,8768=>244,8769=>584,8770=>584,8771=>584,8772=>584,8773=>584,8774=>584,8775=>584,8776=>584,8777=>584,8781=>554,8784=>584,8800=>584,8801=>584,8802=>584,8804=>584,8805=>584,8810=>955,8811=>955,8813=>554,8814=>584,8815=>584,8816=>584,8817=>584,8818=>584,8819=>584,8826=>584,8827=>584,8828=>584,8829=>584,8832=>584,8833=>584,8834=>584,8835=>584,8836=>584,8837=>584,8838=>584,8839=>584,8840=>584,8841=>584,8844=>768,8847=>636,8848=>636,8849=>636,8850=>636,8851=>636,8852=>636,8853=>768,8854=>768,8855=>768,8856=>768,8857=>768,8866=>658,8867=>658,8868=>658,8869=>658,8870=>600,8871=>608,8882=>636,8883=>636,8884=>636,8885=>636,8896=>744,8897=>744,8898=>764,8899=>764,8901=>278,8902=>471,8904=>710,8928=>584,8929=>584,8930=>636,8931=>636,8960=>823,8968=>456,8969=>455,8970=>455,8971=>456,8992=>556,8993=>556,8994=>658,8995=>658,9001=>329,9002=>329,9115=>384,9116=>384,9117=>384,9118=>384,9119=>384,9120=>384,9121=>388,9122=>388,9123=>388,9124=>388,9125=>388,9126=>388,9134=>556,9216=>800,9217=>800,9218=>800,9219=>800,9220=>800,9221=>800,9222=>800,9223=>800,9224=>800,9225=>800,9226=>800,9227=>800,9228=>800,9229=>800,9230=>800,9231=>800,9232=>800,9233=>800,9234=>800,9235=>800,9236=>800,9237=>800,9238=>800,9239=>800,9240=>800,9241=>800,9242=>800,9243=>800,9244=>800,9245=>800,9246=>800,9247=>800,9248=>800,9249=>800,9250=>556,9251=>500,9252=>800,9312=>788,9313=>788,9314=>788,9315=>788,9316=>788,9317=>788,9318=>788,9319=>788,9320=>788,9321=>788,9472=>1000,9473=>1000,9474=>1000,9475=>1000,9476=>1000,9477=>1000,9478=>1000,9479=>1000,9480=>1000,9481=>1000,9482=>1000,9483=>1000,9484=>1000,9485=>1000,9486=>1000,9487=>1000,9488=>1000,9489=>1000,9490=>1000,9491=>1000,9492=>1000,9493=>1000,9494=>1000,9495=>1000,9496=>1000,9497=>1000,9498=>1000,9499=>1000,9500=>1000,9501=>1000,9502=>1000,9503=>1000,9504=>1000,9505=>1000,9506=>1000,9507=>1000,9508=>1000,9509=>1000,9510=>1000,9511=>1000,9512=>1000,9513=>1000,9514=>1000,9515=>1000,9516=>1000,9517=>1000,9518=>1000,9519=>1000,9520=>1000,9521=>1000,9522=>1000,9523=>1000,9524=>1000,9525=>1000,9526=>1000,9527=>1000,9528=>1000,9529=>1000,9530=>1000,9531=>1000,9532=>1000,9533=>1000,9534=>1000,9535=>1000,9536=>1000,9537=>1000,9538=>1000,9539=>1000,9540=>1000,9541=>1000,9542=>1000,9543=>1000,9544=>1000,9545=>1000,9546=>1000,9547=>1000,9552=>1000,9553=>1000,9554=>1000,9555=>1000,9556=>1000,9557=>1000,9558=>1000,9559=>1000,9560=>1000,9561=>1000,9562=>1000,9563=>1000,9564=>1000,9565=>1000,9566=>1000,9567=>1000,9568=>1000,9569=>1000,9570=>1000,9571=>1000,9572=>1000,9573=>1000,9574=>1000,9575=>1000,9576=>1000,9577=>1000,9578=>1000,9579=>1000,9580=>1000,9600=>1000,9601=>1000,9602=>1000,9603=>1000,9604=>1000,9605=>1000,9606=>1000,9607=>1000,9608=>1000,9609=>1000,9610=>1000,9611=>1000,9612=>1000,9613=>1000,9614=>1000,9615=>1000,9616=>1000,9617=>1000,9618=>1000,9619=>1000,9620=>1000,9621=>1000,9622=>1000,9623=>1000,9624=>1000,9625=>1000,9626=>1000,9627=>1000,9628=>1000,9629=>1000,9630=>1000,9631=>1000,9632=>800,9633=>800,9634=>800,9635=>800,9636=>800,9637=>800,9638=>800,9639=>800,9640=>800,9641=>800,9642=>625,9643=>625,9644=>800,9645=>800,9646=>800,9647=>800,9648=>1000,9649=>1000,9650=>892,9651=>892,9652=>669,9653=>669,9654=>892,9655=>892,9656=>669,9657=>669,9658=>891,9659=>891,9660=>892,9661=>892,9662=>669,9663=>669,9664=>892,9665=>892,9666=>669,9667=>669,9668=>891,9669=>891,9670=>788,9671=>788,9672=>788,9673=>800,9674=>489,9675=>800,9676=>800,9677=>800,9678=>800,9679=>800,9680=>800,9681=>800,9682=>800,9683=>800,9684=>800,9685=>800,9686=>800,9687=>800,9688=>350,9689=>800,9690=>800,9691=>800,9692=>800,9693=>800,9694=>800,9695=>799,9696=>800,9697=>800,9698=>1000,9699=>1000,9700=>1000,9701=>1000,9702=>350,9703=>800,9704=>800,9705=>800,9706=>800,9707=>800,9708=>892,9709=>892,9710=>892,9711=>882,9712=>800,9713=>800,9714=>800,9715=>800,9716=>800,9717=>800,9718=>800,9719=>800,9720=>800,9721=>800,9722=>800,9723=>800,9724=>800,9725=>800,9726=>800,9727=>800,9772=>929,9824=>626,9825=>694,9826=>595,9827=>776,9828=>626,9829=>694,9830=>595,9831=>776,9833=>333,9834=>555,9835=>722,9836=>722,9837=>415,9838=>377,9839=>402,10048=>1161,10752=>791,10753=>791,10754=>791,10755=>764,10756=>764,10761=>584,11568=>352,11569=>872,11570=>872,11571=>720,11572=>720,11573=>720,11574=>544,11575=>709,11576=>709,11577=>720,11578=>720,11579=>596,11580=>698,11581=>742,11582=>574,11583=>742,11584=>872,11585=>872,11586=>292,11587=>696,11588=>696,11589=>720,11590=>544,11591=>724,11592=>756,11593=>600,11594=>672,11595=>888,11596=>836,11597=>524,11598=>720,11599=>260,11600=>836,11601=>224,11602=>678,11603=>380,11604=>872,11605=>872,11606=>720,11607=>268,11608=>640,11609=>872,11610=>872,11611=>770,11612=>424,11613=>720,11614=>770,11615=>720,11616=>709,11617=>720,11618=>541,11619=>828,11620=>454,11621=>828,11631=>442,11799=>333,42240=>698,42241=>698,42242=>676,42243=>800,42244=>800,42245=>850,42246=>930,42247=>720,42248=>756,42249=>750,42250=>750,42251=>750,42252=>540,42253=>540,42254=>780,42255=>780,42256=>1082,42257=>1082,42258=>780,42259=>780,42260=>720,42261=>774,42262=>600,42263=>600,42264=>600,42265=>600,42266=>983,42267=>983,42268=>749,42269=>749,42270=>1080,42271=>890,42272=>869,42273=>720,42274=>739,42275=>983,42276=>780,42277=>840,42278=>780,42279=>424,42280=>840,42281=>967,42282=>462,42283=>952,42284=>735,42285=>735,42286=>780,42287=>750,42288=>869,42289=>772,42290=>772,42291=>676,42292=>762,42293=>674,42294=>674,42295=>488,42296=>604,42297=>822,42298=>1059,42299=>851,42300=>851,42301=>689,42302=>844,42303=>708,42304=>907,42305=>907,42306=>907,42307=>612,42308=>612,42309=>840,42310=>775,42311=>544,42312=>774,42313=>540,42314=>704,42315=>723,42316=>887,42317=>887,42318=>676,42319=>817,42320=>762,42321=>887,42322=>824,42323=>890,42324=>705,42325=>780,42326=>705,42327=>533,42328=>523,42329=>694,42330=>772,42331=>772,42332=>772,42333=>892,42334=>711,42335=>711,42336=>832,42337=>832,42338=>944,42339=>944,42340=>832,42341=>928,42342=>743,42343=>735,42344=>731,42345=>782,42346=>595,42347=>890,42348=>680,42349=>887,42350=>815,42351=>510,42352=>848,42353=>700,42354=>700,42355=>700,42356=>724,42357=>724,42358=>633,42359=>633,42360=>813,42361=>834,42362=>625,42363=>887,42364=>592,42365=>772,42366=>772,42367=>639,42368=>639,42369=>887,42370=>887,42371=>717,42372=>717,42373=>786,42374=>891,42375=>780,42376=>841,42377=>500,42378=>792,42379=>522,42380=>522,42381=>647,42382=>361,42383=>815,42384=>850,42385=>683,42386=>834,42387=>898,42388=>522,42389=>820,42390=>820,42391=>808,42392=>864,42393=>772,42394=>808,42395=>869,42396=>900,42397=>844,42398=>844,42399=>812,42400=>812,42401=>812,42402=>930,42403=>990,42404=>540,42405=>608,42406=>630,42407=>910,42408=>687,42409=>687,42410=>744,42411=>687,42412=>724,42413=>742,42414=>724,42415=>742,42416=>744,42417=>744,42418=>744,42419=>744,42420=>780,42421=>540,42422=>540,42423=>595,42424=>740,42425=>620,42426=>772,42427=>914,42428=>914,42429=>857,42430=>800,42431=>772,42432=>887,42433=>990,42434=>1005,42435=>799,42436=>799,42437=>948,42438=>948,42439=>906,42440=>1044,42441=>600,42442=>600,42443=>574,42444=>742,42445=>574,42446=>742,42447=>500,42448=>604,42449=>704,42450=>704,42451=>746,42452=>820,42453=>731,42454=>805,42455=>606,42456=>726,42457=>726,42458=>500,42459=>813,42460=>939,42461=>898,42462=>660,42463=>633,42464=>914,42465=>689,42466=>1231,42467=>784,42468=>710,42469=>982,42470=>704,42471=>782,42472=>591,42473=>770,42474=>620,42475=>620,42476=>930,42477=>930,42478=>930,42479=>785,42480=>785,42481=>813,42482=>813,42483=>971,42484=>971,42485=>721,42486=>801,42487=>582,42488=>604,42489=>618,42490=>582,42491=>1059,42492=>1059,42493=>1059,42494=>1059,42495=>720,42496=>789,42497=>723,42498=>721,42499=>772,42500=>772,42501=>772,42502=>772,42503=>772,42504=>620,42505=>634,42506=>806,42507=>825,42508=>670,42509=>521,42510=>512,42511=>1134,42512=>1324,42513=>772,42514=>1091,42515=>445,42516=>811,42517=>776,42518=>614,42519=>720,42520=>902,42521=>765,42522=>920,42523=>1024,42524=>735,42525=>742,42526=>816,42527=>715,42528=>692,42529=>200,42530=>677,42531=>770,42532=>640,42533=>595,42534=>526,42535=>677,42536=>500,42537=>715,42538=>1143,42539=>560,42888=>333,42889=>276,42890=>342,42891=>194,42892=>194,64256=>495,64257=>460,64258=>465,64259=>652,64260=>645,64261=>520,64275=>1004,64276=>1044,64277=>1042,64278=>1037,64279=>1256,64285=>200,64286=>305,64287=>400,64288=>587,64289=>890,64290=>848,64291=>872,64292=>800,64293=>850,64294=>873,64295=>797,64296=>937,64297=>584,64298=>776,64299=>776,64300=>776,64301=>776,64302=>640,64303=>640,64304=>640,64305=>591,64306=>466,64307=>598,64308=>622,64309=>262,64310=>351,64312=>608,64313=>270,64314=>526,64315=>550,64316=>600,64318=>621,64320=>378,64321=>607,64323=>575,64324=>568,64326=>590,64327=>606,64328=>547,64329=>776,64330=>687,64331=>212,64332=>591,64333=>550,64334=>568,64335=>640,65533=>900,65535=>700); // --- EOF --- PKa\S ?fonts/pdfahelveticabi.znuW+AxuX[.ifnBAAP@BNA:9^\w{ޟ5<$ljg uf1$_@]!Ζ&F"v֦ ֖.2ΖbP?WtߓPCE!FP3ԋ*t= qr`y&V(E=--y9C}'_ܿ>A, Gt;3g7#Go^v.Ì 8B2{~G607ٞ4>2Ɍ +nk*jgcuvBAjji 0[ڢR@SZ/=諛Z{7N3ND`Y  'KE#r?WM]>hwG9A;pSǻ_ ?J?YF6?#5 *@Qy1PD`ctt*Z:X̌ yfk q(9Yz;$χj898z5=90rt4@Jv'%ԗ;]lk wq@k׶NFMZ6íl-l@;Q0m]lՂhjgmmxoCM'4o5,Jl,@{hU<A:V0hduoc[8k6 \؁W`}hl@'k#'{^slcfg:?e-~?0pO;+s62G "dB~{svNoim`7ԅFG-]P9Xq`c` Ƚ .ؽ#8Y`{ l@{@{ \@{ TGpt/@{ Tl@{T@{ Ը\@{ GphhdbqpP߱ n9XZX:lnv˯|9n 9' h|/&((h?P@ h@-(h@q(nAQ}@@ 5@({8'>P@{f?P z?o; AAT`G 0ߛlim `.˃ 56rz04s|:({1 kkK{')oC|ͬ!7.-\~ #Gq],z j1zRG^3x9h mN LP*@𰂠da>(L!6FJ#x'('@a%_N^?Go E% 0?큩PXyhl77BEɃ#E+hyYAl+z(> &ȿ [Xs45R7T5k+k;sh_h mY6/ABIdcd[<2?@P*Q=hT@P<?6{VF&.A(6z?(6(nu~Cyf1聍?8~zXW([][ _]N@AW; ERQ$A(o@(ʠLv`~p@(g r=80JM ԟ>فRJONԿ20 , BQoBC6F%#P ڟp o@ kCI(U-mX J+cs@m;(5hGz7F!JwӠD722GphGpPC-8(! Z h> r2~#-P,KB۲>O_"ᄒk"b`w#(]-(]we(=t+B(=~? F_Ɂ f/;Y0:_;J nS-0> P怽c٩cf!Wk6\lsV+>$%Y;'C0\>C&xۃPVv#cUz9l}6lgZ3Z}L٭Ob2NZr qXa"K662J|$ajT}ԌNF9.(F̓gYZj}H̶IޣQz+%D E؍^LB:&ZhsK/T5x^/ZvEߦ_E%꜊ pW{ fԼK0E> <Tӣ"1c fRq *F} JSRjV&X~R!h'ڡ%OQ$5_uzxue=Lk6ⴛSuR;]sc˶-OH԰%h=uIdl#%/ 6YHYb,Xƻ%: cRC=K:ܡgd ZRmOWEh1ъic>jx7Pz1t ^9=n9pTROcG Sp] Eal_LT4ʹ^bPuĺrh>\k gX_S'y߁ѻј_?≿[!2aНLKȈW2"yTƠ9ZܸE63zdӼ;kWF^Vg#)Bұn0$@򩘈;C]szV_ V0@pX2a?0i9潨yx(^m7QJrpv\֏eCn%,mgiXۄբE<7G5ҵ}睴2{YX4Ieֳ3L8 :cԟr*)<!J.=z 5(gCy l&8s^|Uy|wx.TX*31baꕤl!/Q2+pq#2&2aX.>[ݓk6a-~fh*$<nY&5jNe"z/pס|\/2Kb賑ˏ6|!_yT/3"NnTx&ST[˝%ۄ *Q)͋n mI#b0t~wfwFnr~S];8=Z^,K}]xfD :/.‹oIdIs.dN>odW .WŠLpl 7oe0~^,=)-/"ٲ<>NS!ڗv/H_}&>)F{ ۺ"9eT Z:J_/ JpNv)3~-v,{<,1I|y)ۖw:]< pz;W([O(qK57UFHv~23%Uڥ Il$~jف&dEv$t\_NJ7)K~tK7Ih)b#N5u?k{Yxm761e7xSXo*B ?49.DY$* faITj˹KĎz cj(N0+Ky-Z'gL r17s   u :#^iRjjAYJ*O $Fq gR,,^wӞů[*F cJO#L^J$O/@EXRV0,+zaF'Rl7}~#.KM~RPtk֡hLH.#U;f&]:m H#jX~Yz\d>v{j!=~!r ~U+њVA89G͗ obe߻mKܖi,-kѵJܭuWFte7۞ deя^y4/0ސmv҅c>uK(ضL}&B!pߡI2a[ԬツrO4J-'f]V]/LtҨ~t{J^<_֌[;v'hx :?XIz 7)68iץк X'xc̗"-Y&[P9*dlxeK:ԮtlXH4!TOidc΍:K<>-!-Ijpr/˘7HȫiQG~ۯj?%}U!g9)#)գ%oeՋo/=yfc$S`g-WG Zɏi#_mid}= [SD' )Ţ cV{:XlQyD\CUlg6CS $[aIr,@S?n{Jd[r W-šv~a^,rڰQn1#R8J3y5tKYy-iQO!F%>XpgC$yƂyΉ%,Zehx|-h܋dI8)NLKyB4+OYII uUoOo L~a5zQ}':lݞ~&F}uG6jRV$yLvV9w"vdnD^ O:l>Wol:2(^jPh^)5?f1[t"gr<$O9\QOoDI۫[ŔI\eӢK+I{yZLMFF ~FQ*?"Dx (GHp̤W1#x1  mM|KjptmڹΛ[4i~GQ3I%)iok[jE9?2c/SSza -@_Ӈmf32Lq!ـkFdBǪ4ϜR+(x}zxL dC|1xuao0!,e})aak]?PEV?$nl -^48Lf.%OSX ir\iJ#_ı59[0hޤ a ׵rZTmI/h|:f Jn"}$^ ~'t_쵱 ֺv_@~jh%uhԘe7t_]jf*gs h# i R.fbeﹰ>J{Ո?E_{27>K(\<@~~֕EV=tUNNRKQEtmx|dѮJliًy-z;&^`v[xPcy ߶yraԦ4:wTqz̚f8et$u+'ܜ@8EmY榆q) L'3w*;K#/E^T*FeYߔGxK=ı3t)c߬Qfӛ ,v̘o۬DDzݝ| Ű Ŭ:a/ q8 ;[&}|yètC"cFD;,Ǟ#=MOb?|2rYfC쟺кr"3NFqKm'*NAO^ǝ +9;9/.RLs&$hǩ+߰P3-Q~6⋧WvEDvdщW&糺m q48nxwԧVn$./fέy-iu*ع nl۞Aus"5փ6pmvb|У4滠)r$|3q~dgl&GBRx5ҞnaK[QgxL[T:yw[he.8Cs<bՅ"IXh7y]8D (+_Q免Y Ig&z#2nm,Tc2#%6^Kzc@*(ʺ3(6XW:8dQfMuI<~5~Luc +1׽VҀ@icC@3)cZ:My|;& qp$8k῅7 rHґ;erv'WFo5NWgx:G,$NsivJuZ_ߟ] V@X^E bPܝl+cmGv2uڷ { l9rRhU)-Wcw|@5rԻȊawnv!w7cWS vw[Wj4.6k29{R1b8ugUWvBۜ^_h'*;7u'ϛ9iC^j&F 7=3t)\"bt"e"|>d}Iԗ<j^4ݘx(7FhXk|oy&ƞB4F(͒ yW#_,OiQlDS+[ Lv-tֆh\=by2q0HD%rtdͯ+FI"gsđ-K%63 lc;V]s{) GkT'sPج[e<"}Go|I1#iߵ7 2S$:)s,O|^U˙Vfy|: 2ɖg5ڏB׶ |B]}8a( sC`*pkuVFp1elц]EGPeJq듄v*:Z@R<߼4h!XrxpQ T5{ tQƯ>X1RSU>DJi%$Kf_TޛF\8(}^~zAQK`R8OGbɦkY3yy3CI?((Ds/9ԭPjNIGEc%By4wM:/9+IMv'KfmG9\#{0<޼>^q2%LȂ\8Jfx!b؄$߂LTazB\j3JhmaRY!#M]=ϒ2_(Q=JOvǵ #!U@ٕNSlq.C!F؆!\P5O(M0Ē WS363 1MX=qAmi&4Irciԡ{s*X k$LiW!f@>6Ж Āل'0Y@)Sهo9Ȝ`є3b⏹:{xq|a:_!_^-(/XPzyXg}{K}'dЂvZ#^p6l78K)e}f4-c-'/ގQL) H(Eq-Vq|:9 d/'PI;g]oۻe&÷ldeco8"l1c;2>YLu1Uʓk0ɩ׼zɔopQJXْB"ȀbVr㕱tq6>`b񣥠ok d"uc: 9H! 6S5< /K\#la {nJ6&Eh|6ΎmGu$rfYnHq5\.|k aò5]tetd*ӧBK;+' đn'ʞC< aא*8*ex\OhɃ'9UOyƏZdt >&7,Lww"f QqWaM\r$jD jss2#!6EޘГW0D]UFH1?k5|mلLc{|]W+cw (1,KQu(Jkz?7>zF#ASޙٹ]`|`r) 4uk?kP:`M2ŧ 69\%5<\͉\hb_\\GZt~gHm5/)ٜ|y[X['BδH> $Kzش gu7#x|%F93ӹc|ԣo^w>o|/Wa\|z'ŝm)б\RG|9)Ǜy5UsnUNҐˀ6 ;JjLџU>KF깮"k%To-z7Zr=378];Ҿ,/U9&] o۟ 2ɦ` e|JW!~a3s[WqQ>6;pڬcd#He;O3Ui8 RwfŇf/ 6nୗaۊ`]}%ܺ1̳ SN ̒["'T鮏z=aDꗴy#r#w翴1>ImXxher#u8F 8Gc$R(HGa ]jPH;4!4\-UW/TFͬZ|M"8kt}1̫/5 lJ#B ݎ&&N6 ~K(,YTn+mGT#ZD3F+z42JͷT!b$ayItӡ 7iLO}3Zح=h=&)Se悒VvWNCˤ5ʩvQ*Fv" ˓4QKM7l|P2$e,PetɌsXq>^EDl<}to|댌Xĵ eZ0Nq"+ piC$5<UE,^@Wi` oqg}m<R/C_אrEIUdThQ7}Nn?}3>%qȎs9e_ŕRԳN~V'O|"kLdecť/ I=1-6Ή qZ)T)Ec s&|5MJDzTگv%!mk_N!}ع`ۊ=iۙ_ݘN ؽZU~ۗvR|Ac@ol]sjڏ~0؎v>Eq7 ÑSW!wׄ%>{/(j֓ezthX\$XNQ/X&PVbS҅4s4E ޡf] ZI EM QU[ʘ^.Ԣ: W%Nu0|<|e@E)=/6VL;Y%]xzJdj҃eVeaE |[:8n PUtvYJDXk&e|5[Ao4_>"n^6ָ3'BIܭdfl$^kuSeW+r<_347"n6uDSfŀ//g `Z} qK3d/{[6vCnhXj$,&(bVZlA=g_mξ jPō%p~fHxS'[uV]6ieX.wD ,p21&aS ֋Qk0]f/j٦J|Gx9.\kCE<;T)޻[*`|'G#s|ok9Oe,ߌR׿̀1n'̛[YkkbGK$FYabi!a~'g8߇H']ak\V@/DuGs&sٞVTdg: ı0B܋D؎$g˟peO]}NHh옑 m#ňާjFG)-g~Tani㤂W 7;%*Z.q 睞ZBuDM EP9Ͻ8I̙{+p.f8_?ޥI7V@mdʶݗƗ4e+9A)#|Mgr|W))alyu3m 5\iI{Sd"lT;Z攚v<̰Dͪ6RY}ūB'2VCim yJ?Bǘyw惗 {B#1QkyUKI"✈WU#ݨr6QMspmpFdEöVP r㨧J,:VÉ^ J֜Tx+w软=_z_[Wʜ65|xQt+% 8tvܩI*&ƿfUϬT4_(sk]_^6lvWz;Ok~in U[3x"*3=La|~bTN)O2]AxZK$7%-1d}i|w{vv\4q\>?Vs[>·.q3E )"dye-u2T!Eol>~˷ATmlDeF|Yn$ğqp)w.؏AY"W.I-W“Ip,ǵ6]/CP.+ ^b߾µBqRIMY`{ λ <$j[^uK\(4>;^-޵fr5z)O2B=e"̕2]mޱz܄[;6**vfrp=̮U&6dzMS+HGVh vHsu0Yw/,*$y7T-]S:?!ͳ7ۑzHޛo_S"g*r|H|B7,v` xb3M>=}. Wy,.ƞ7K\!" :Rbrg;|{}6Sˍ*4 gS2r]PqOlhKudٻNϴT̓N{")2yKqfS 6,-mҌ/F')Մu#+7Bi_/p@aY6TBtNeիTG{a4eVhʷ$iǩ:s=e_F%VS>3/!b`W{s8ڻK ơn:0OIQ#w4GϨNkO[Rdu7}[}4ER15jQ"gHU\\}j H 8z~{AyjTVN7 b2D% )C8ıA]HnHt.{~3\<3M|,lgk36uF{kʓ~+`F[Ȃ|oo/ sln,D Tbg[b\-6zHl$Uh~̗эmuS) J7aH:ؕ$yѡ`癱HJ?R`Lhg,H]Q0OLp R=]w*-.4ۢV&abָ8%oŀ_L\ySROɨ nh\w/⇢Q{΋uZ&+H֦pޓlE 1?_1_OulREQ7ejʯh'uېZ9DDk4F諦 g-3_N1?Dtvo D?#Yk1#mSbaݙ |m=6Ɔ{(- ["xMYi7ZຸѬ;Zx['8͑^f̏bۊ0҂J 9ҙHFO(^A2rEj.8ȗJ4jD4)h ʶU 6&}x jQ TLs@`sE3 c缪 -sb=6ξ\#Sr҇ct\!֐guIz#گFXp݊m2lޞ)Ro;瘰Ú;BP5njj5wHyW%uc|G\K(Ȁ$f"R{%Px^K܃Xuzmi]V ]qZr ff 0OK"#'pLfω0\M"<ħrp饅X>tY5yg/ܾ?|G1BgŠo&)Ω (8JXejpo=@' o@cʔzyN"1/ּKb_Ʊe^ ϐ{:HE6>IV }K?i{*8ܦU`QК^{˟kr'{'p/d\|fD™N|mh^ v:MccDײnC>Q%pEe䃣Ws,J L;@cC+V3܏ ?K`"L]aai#斤"\W 5lP 1i/r8Ɏǿ,R`:%*4 vJ 5g!yk4 P3t_L59HN0{j̓aˬ|ݦ0"0A514H[('-AoZ1k˂Z B3'[Kd0[54󊅏iS)W0'T?cGBy2 v113i 1S,}eo^GW ̃;Oe"^ղA>ì 1=;(%k޳k%GL2 tHS K/b4QzL4vIQ\>rf7qioi,zL|Uu:@c[:2TVe<1 ';v[+ q[ -rϘg3dd\h!ttU@M]O%XOj|~wF_oPw8{4 9ݑ 埤?dø'8kؕ3|ʠ5'h_<۴sV~C倩!}8.#g,i@l)_TWHRo2JbC>NL x*n_!]jMjs9@>DVc0r|[KhWshBqTBڄ9p*gCrkD6啳)݌3z뾱틁Q8>,1ӏзR=%8BVrr3g x7#v}=ʚ%ςeաqa1kTaEp6𾋌OV#bQ,/'`&৚1 pSzB'G&Y M;8a-qP zkwpE t}‚O=FЊnEF羁K}O2Uy7݃H7qޜJ7#E`tvsQG;4ȭz7-=Hyk̅rL}ߴ Uȕ0i֌Qy@/2%b'6]4eTmvɃƏ>Z?ouj38k5C D`Ak[>!DkF5H\|\jsxJ`_`| ׃.d =X,ؤАǻDi >Gur‰)G~)t Ob(g^VYh(LѮxD 6[;Mw%(RO$ܱ.U.|1[m6 lz 䍍%}}_F+9\X~+Oˍb9ٷˬ1[VoVp'w-7Mo:W΂ɍBxkzCθ-4;HTVeďB M1)R/ \ԃv]i}mVWu(xw28[~G[3e5ϊ7mLW:u E*dPӊ $Scڽ@}E ;8p{xx,p2 |dӎ,9>Xˋ m*~&148{W2"UPԁ G;2+ %Kca<-~W`L.E=Cb%r ىW~q#rX"O\hEnWbK\5M YzȟR'Pљ*]7\b.}쉬ًA@d1- 0L9\iCmEYb}?ۚcf\ ujdko ٨Π3tiN,~!vóR)u Ց̪Ec瘠S_7Pnh*<$o ;h~`EƵ-t+4 w -]'r4أ7!V[L7Ԫt:<.aRV{s-"=ɢX8MOK> U)mbyZ}u_`U"3)+4&dӣ=4i'6-eb=li^6X~H*7IZLLFƬ{͎x h"O0roC`gcbP놩j+f; s٘e-ŢՋ}q*іyh۴7 4; [^wخmH![?x`yQFXZ]ؐB^.kF5`.Ժ{o  *OIS3ivX KM)At,cr65m}jY F4oJ:C.M1Ip_&$_vxYh7 ˴iKIv|m;jD^ë0xE4!6 7Mq*f5,/xK%Id= ̗Fr}Tj?pj`մʧ~q"E;@&3%t/T*<xȞr! 2yUc*QȄĿ 3#izs E.t2C-A #>&-HqSk6A^lDDL%1 ܉`(J?$XRmy5o(qmTi0J6 ;k )wv)SiDbo8{MYdgB.G ]c,J H jP2\}ONF(f-Ɯ03rJ>E(e)>^joLk>KO`^`Bqaz5|  Z:ދ2(ABMЄ tULsNz*]8saT!M]*FzX N@7.P@0 +p;֘k@1mDɺ=Ķm{ ߿S݇.4 CLn &}s?)o|<'\vp_:U9-:?H ™ (䏍LvbXԫ95 49&&S@1;Phv$/;pܶJOHw7PЃ||"A08)3z]nOhOEl¼[U@ZLF~b Jd]3~tdy[4!es1Hh)%ș=K|K(Y[>YopQX )K6S&ׄHHuI*Uvj)uz՞VHx"6>Q;ʜf kw,sOTփ'j`&G^2 { Ij\ޜ)\3(<Ɠ_@be%|ݲJ&_KEzfH;3-.2lи}|@(~Mi 0!.Ec810Vn%TZi?{[*pѽ / P?up+[d~K~%bT |'|::&PW,[}]1.̼M'9o o1J!$$R)6ȊY!N%KYҾI->#a(WtH%;RzȞTϭloD1دjQbNTT5П@&*Jo̷/I.hq}]NAw`;gכ)r@=J\QŶ YuzsRXsC1<46ڸV;m@mdl90k2Ps:},x+ $ l\k~5Z+*OR.x5I^<KxۉYBIj]Jɡyۂ)\|;@,IJ%BbHJҹ&U߮(犳r\G}>"[ᶢHzxrrWdxo7R|yWTEaEYb dZ&CZg;_q0C0˨T7E؁ k %`Y~r6v@\ly@Cx + 54rZv9ku?0~mUSaxߓSe6ր}2.<4I/.MݩQWے:$?UBuqyR/:ś)>SS {'ps~ncGxgt.mL&#s?G|)xcmʴQ >I2LhxtP5"vbA$Yى2*Bà:La*=>3k% -k"ZcWհ瑥}r >X{(*W}TА;BBDZ?uDl"g;oD(_'SXƜՑ5 z`I0)QT ḫu;78(:S^+"'da= m؉#F*-;E;u),Z˾JXX2KmwB$"`QGoeL9ȳJoN pg@m^ ;ɛos<ы6u2 ̥ p!N Y@Dw{V[lM:?R(BjT9< H[|kGvW LX ZRD j}7)\ )}D3b9ҫ 2#Y0[iK_v! N%()FV,?wn'G ڹtH%AŖbr!զ"Aq>>/8<eU]c*ԇJKgY]nl/\Ќ']bY.KXHĭn EcWi).U1g*f;|CqDۼ u[l[Ñ a|c8FQjpwrc iu&RUOt_-=ٿ5 q '䡹YjX.!$$>};c/Fqh-~k~[YO^ufwAJFe5VGbcZNJMt,_MDShdQ]׊QFMg-г#bQ[%;a)vwG5IG^nc2yO ui$dW Mh_g0 .$b7rao^{X0)u4H!4s_9G0m:ߐ֟{LxV_AD1O7υ3Ci-JDxɕ̸NZJM` ط}nOf=̈́"+h_Xsqu`=g.3Ѭdc|Yp]R<+$0QQ*lv~;Ӱd^k#șϲAu&}?Au_=G`ᖂ0uQ8H#\svsjNO Vʥ?cE)f @T%`h tcRu6ҭ%R-ީ 5! ^vE{zWf# ҅=ɪڠuftӁl1ÿEeiF^J9x amV0q2JKir6 G#ƔbW5.hQDuW1e\|_𨖥 ZQZW"bf!I A?|[,k[ jy2oS}%-qnᓒI*=$|E mJe9\ߏ'4 d93vj ˑ7.@vOgYz$f2bQ4`>7^VW!(Ka7&-P ؋8ӉB_vG0nGVkC pIPwĆCTz-'%ECVst0G9=Qӱ I$rX0K!F~tYJܽ&ߎнQTV! %OH8ڷYk xӵ&y 8$Ol&S^pP`2V#JpI t sq$ͺ7 #.$0k02:ߘ 濳}$UjNM-y][H<㠖aؓ9 ϔ1X(**d It}y=o+h)-attb<؎]ydb"Mww)DP9٤7/%ubTG^۲ *i= o}rl^̚ \)䮞W|FfŐB L"wؼm)LdZ5Bj:b8~--0E=q]NjB2th{ppaozA6Ԏ0hB~c<.uwLL>](.1ˍ)MҖMNvD|TU&at꒯Z̚5cgvPpLNA,IݙMhOE.2 Z)dLns|`u3]|s2`#]!B,J%^e 5b[5^o.C U 6ޙ{OVe5,ށ\fMgD\njX-ބCnQC^Q<녿d ?i > f5QB,BJ\:Y~uLs59Ύ] aHGQ+Uw@AN*Ёn2E0=DCX@Κ:dnGy+T?Ki]/0ѫgGt,&$J<|#ϝ&i)>ey O\x"n$5&)vѡvdm9FdHE6ػѮ%tn^j65lc\;>_r=yWDّ x{0q?j܉" E?;3Oĩn-8Btv &oCY*  Xaܔ/yO-˯C7Rꯜ&B$m@;܌Ň FЧ8H= ^g"zk޽^w]]3V+o6b'9sCRO>J.a/>6 [mƿEy.c RjkxʫCc:9Jܜa6׍zFC ƀ?R \ OMJyZ8wf2%ğGnoy̻|N3 -°raRuޒ/lM,gaWSQ]&J3 WK[l\I@Ȅr2ˋP`tʸ!Z1TL>]WlHA= 1ٰ@ & <|Su$qwW{9mǀW^-]|[sGTFSkZyCY?Jӄ(7|$ΕuUKnk}[w+i:g2| 'D@ ӎ1VLæR̀t>Ve͟mLh+A,e_| _\D IٱٗMkMV, #j2 M}Bܹz`sZמL,^61|VupfɹQoTx;l#-<2z:XjLBIݩݍŅqE"FU6H;F%MM Jz pDxrJI86'K{<@1JN rEva _S?XQ(8Ϧ7Hu.ݹ>BwK܉}XJqƺk`P>z/x}'(G2(cR%Fnvh gb'%DuK>X)KPdXNVԈ9} ;j1w|QB3'+"b%?O.sq)]4r[qxOɨH sA,ŏ^1_$">%{l5>=  - X&T\|yC6qhEu~I9^9&fh-yBHC{ rnOkV1D{3lg#TZb[ӶseL"/C$'Ty#YDiڿp/HMTI!CU%ﻶڎ;90:{qˡeP Ixu.@t23ic&?>RhDP}6*r͠@c:urhu>k^< LOq)- t–e(#)BoWgX0F kiPA;-GS<ޡؓ#BwG .y (YV$怚/#~}Os>"c]ɱKUpG P:.szQC-'|d869bP '^D\%U`nyMTr4Qvoa=vDfCnJ{ux'`Kn˪-Ri7Y@Mk'R/uÊ&ߛo!5O0pnJxl쫪+ &Hq:e8  Sˆeݜmv}%)&Lv{ 1toʕcgc?ibo2 Q?9mA .w5 +ogZ.}g͔/Z@ljЁoמ$}8^p"!ahi:e@JZ#!쟳-q#:-2&dRL]R{>Dv&F̴4'QTUl-Y! e+|D{u/%! \Sb2KcrGi lTP4Y܌'@~%Is8c`[#IXfa"gϸspZ r_*ZjFJHTiIȩAޖ a5[2^D^a7uةYf9tT%TCegʂ<4ӬZg]Iޡ$Yc'LTNOY]MY%=13{4LK @5$ҝjri,&̽;XփwV$"=łJ6oo6z{`d_[;(cb>vQ,U ,a,`D[_r?"GX}Ы*Y25e|1n%aѻB%zTI##@-R~ șYeJʼ_mu;D[}idiƅ1xzoQ ȇ01ujWvw']JюFͩ>_QAFy|ɏ _^FF w `1AXp$,1< L:pQW X!>A:?rNMKX0q 1W6j^֝J2(o@1v[)[/#Uwrqbތ +_T.,ۤU>'ep8+ifS2ZPHqĭL7F+L.] 'l e~G.RNo:h#V|FLJA {a{=p8~^Vq`{Ty֖e,{14v'gW$,D̆k̓*І\0/$IU)OMq] mD])D-֪vHJv7He?wK(6[)wꅌ6+: |(ai+Z6"ul oDMmmV' '`Eg*/) h;W&b[~*hԮ^p_މĸ>{qwO>L])>)FV1_oh;8&F <[Js"p - mH V2P/"ii-HN3&rB+7E<~q l(~:t^PCwxwCb WU;S-Z(%qYU75R0|rO_х7#m'h ~m[BVKኬ?4*oST"t/xSu4>"?%a{81$h?t@+`\!,r5".qO!M2@??yElO:# a?(hT=Q6jM UJSW^Jr(׋?DQ ٯĨ 99ѯw} ^}S5^Bpj`ic`,ʃؙ'm0h_к"g/;Fʣ4NH; O7Q-u( y ln47hzZ * „>5[˫n{:g)Կfs9=\GIoNJej_R v[~Bpñ)AHX@ 6c.(Z½FrYnn0>*.\FjсvϽg"pMLfrG_$<U:IZ2Y Pie&aFC$Mi<ph|lAt:xPlz̟#\'qLCH|?ÕcMfJPKa\Mȭȭfonts/freesans.znuW+Axw|ށ$H%{ZBHz77blHb ; 9s9fw}Ỳh"\Rq/O;/[-ޤa}*׋O$MRڴyHӁMuhp13HQmU\zg"&w;W(R`m߱cF5}ȣ?2b+y@#$JWCx$dtl?Jwrff@:ܯE<c3.YVd}upQöZ+yz!Nj"=ǍHaOP'PGypI88AxX_o+*vZj}ygW #پ9͓C3Geuu2VFzo}0sԭN?ᯫ׉c?y:׺D8-MX[$n|CD+ )TZI3MRzS o'[4¼Y/(b ?L ʸƼUR3.z_bx$v]vx$Ũ/-ox<}]-t]yhweIT!IV6k$Bۍ4D hhQP ނrpj;{m=o,q˩ꈲ?_.[,FYcO/5m~v9?m?@r0ssR\[9zVޚW}u[ HE_eɌuOliŨ}M!ں&HZЂ%p}Mbdrd5֫{0s>hE)h# S6Ը߲ۯEv(QϒVڃQıK~eDkYĐZKY U1nbS^<>F^<cdoQ?[@}c,gVsPPi'{[[S $Xxs`Ż֜{~gouNrJm@8P:hVR1`'S APكPq}8DR@iOaǞJ*EM,/PdDe1CճuCٌ~xg_/P}SFwڋyQdԅhƹh}/n_mFxCv flYA[vZf1ֆ}Xņg8c!gKφ偾Nґu``,uѢ)PeW}3vJSK,Y)&AU?*ZPGϜ)7V}qu>nרU'\<֥% XjXՒCUyɗCUmZA-[9RӖm.rTMg+jصDXO=Ⱆk;Fïjgc,l}sgϑ]ĹcjlלB?k\Ɨ5淓r r|}l0YO[~e\@{81ps6<%rr DQqUF+zWvcF1ͥEN0/7̿>C?3F nz|>Д=|5G!Fcch7`S?/ZMֳSunȍG&9ہ#I$ [A߄>vc,"}m8ʾI=ŧ1\qvUS%*-'S-z'1V}5=.3Ym|[jH6AKK* A1(0]f)j(q2InVߐQ?wьa2Ն(eE: fL(^4eHM /rJc7-wh;w:oN{sf]qq_7jsLgXA{2} #F# *= *֐p ȣPâP@X_gP?:LЃPNm`ծh`- g3g$d>²<,䨉 tWgEi<#W?SSyNj~segySjפgXkOYx{ -}"/<6ħ|ͼJ6o#˼aay .7%}t0ۼl?y7\ϱsDY26Ҽ̞thC 󳙡oG̫ܝ%3禍l+'[=/.Hm >KϮSXR.{#fOgͼjz/ZEjy \5߄v]9KFЯ g?OH(k  omνQz^HuISqЇn伓_(Pm]-6~gIo}s33G7QeC;ґ퇎U'^kF`_]seЍgcuNJpIԟ7bsC<}ƺyZ9[j&]1d%rI4Cp'Rōf|x:}1g50O:.][,FsΞKkyj㼳Z*kߍ %zI;a˿@&.Lʜ9;{{1DZ~F&iJJ^+Mcf#ZZ6 ~LV*әM۴sA`{{>je+4sA8 |~.bGWp6߱;l-/B[r}?;[vn[t)B; =>sڽ`G. ;4!O{Ԇ-z{9r3sGyFOJ.9)hN}{.N)ڂ`j۰kȮ_wY{?]ufN_CT=-uگ:4i/g\6P~j9`5c tP7:ރS} u}ؘfMry0}>i6ƀ`'?rx Rdިto]/}0?}v^s2ݹ9w7\;E`gqZP5mk=Mx04lԔ=wػ{ݿ_Pg+P%xr=sn`w=1˯_yw㶜KwvipA<sj6^jckNnV6u?sssyb)&,Z⮵{Xާnj˒P8f 8YSL`ݫսOz6}>4~,s@>]}0Jusb9ǩGu֌wݕ{i3/sRk^=pε!g%ga=P]&' w|ɡ;]uu=ZwSWt?߾cg,>ԿQSj?w\Y8ӕާt y?/z=hIޛ;d6=p<罭x?-睭_/UOǞO?i^/c-Cgtv3aG-oyY+5Wyja^v y_^ε 0<*d^r%BY:AU6{nK4]d}O\؟BIS5/ yE#[m6<3!xso pںu ߬d''JO}s[<ޔcԗz/wFo3}8XgT0҉ В^U_Jr~VkzXRFcվVGms;zywI TRЇIt;@Pbc$:ZѮTie4W遲hU5_}s0nHm:.Gn[x_=^CAA "@ᠵ6Pʩy{9`@YrMg\u>*jMސ&8zO9ǧ1ZH}bzuĹ%^[7l@ w9{sPw@eP Tud_ؼEпd9>rf<"RzDS8d%I);l3B뵥Qs\oLQj C7k(ɫJ՜oK#0뺠CCv{K~xz. VꋀFavQ[nEЗά:z\ }}w,9߻XgcWquHWAmxۋ9y=k2>n_@2KZsJkWCt|sͨ_bBSwW]Kޚ$YgY,;XGq1z\Q6D1VJ}qCOѱP^8U@GmY(;}9|ʇrfO{PA]ss#EAj02O hX{AZhC \]H'V YRGzy$0cԶK[i znF,ݾ'4" 65x $-$5#*9_=PAPǡN{ ))k:߃zvt`8p)H{0g 9H~Esڹ?xLJ6g 3v\? }QM 9rSo@^&)@{#xx맸|߬­gZ^)C >1#:o< {X8[p{xvsj%1 Vyuu,Ն"'8..qgZm>3P6{_;kϾ $kӜZ,כО_U z9_pIsl\[lzܛ9[ȚdW}gL-=9@vm}ØX߇gUxA[e;(ni#Z1wkC?cs[cIsQr_w@mX 僮zنX5@߅nν Kzw| vq +^l}VcT/wl0ompֶ@0z<#eCSے 9x†m@{cwJxMqۧlSN.0"8Iߣ V7m{ܨ@W4;r|XAol, ݡʷhݰbԨ! Ktv^d/&3XV<3ӵ`/myYkb^13Oh>Λ?,<i<#ť$\) C|W-E?[gcO g^>, ;z{uPA1}/nrKA/`wuA;c@Nh'w. ^6TMEe+OGbFP0@3BCSw} `^n0!E*R.@`AM3t.UOp׼bQ<ĿQviݻg@oܫ(~%Faڢ> 0wCGmc^bNGj~vЯPvS@s/vhE|Fci5V pY"s1φ=+6z:WbZOZk\'U#jݒ_+[5E_dZ ^g#7Xs#r)k"')J,kecfۨ99rGi$Pti$7_x~ ;AK@w$)\3_Ӿq]v4۟[Ek Ӈ~m}u@sRs9UZ>dS34†=n}.ze7vq`9e{miZ1\qvtpIGz&wkV՟d=.3Qvew=fs-{]hk;Nc?Uy"uȟW(FOǜye FPLPmP|ԐS;,+^7Z~η>ίҝب[|仄C-7zYǚrcf\"FPD]k_8߇o6Ն#S]E۲>P<9zWM]#KjrҵmTyKH^| ׹s|7\cjd52!Ow} ΅,xm ?:Cσהc-دkY$ܳ盇u#{e=C )9g}yTtw9ke_f nm:57EE\#Y5.K.(GyNb^Aj[uguQgۺګW$Aɱx@>)y]%%­0(a󻸯${ tU!az,4:}8}Z4)1!.0]'L8`q+V9Vq".ַYkY_^fZTσ讀{R*WhLw%Egr/3aeGh " r<#$[-b ׋d=e>~)]mcZq]e{6kо:;#YV߶ _5ow:m֮z1xxҘ`1/;㊫kk;ؽ}}9OH<k8*pbyq; <xcx}9:;һ̻w/kkk[[{+ߏݾ~aQ/ooO?__v )6fCllq-ę ⇗L.*X -n^;pfڙu3g6lc2Mr5g5=VcL# W_eFƻCEݕܝݽݳiy$O<%v`J`j. \90pKශ??h''SSٓI"u=M<-Agrgggg {<[7A9I9;n婗"=$lu41סϽ6yNpPlvcwuK!B (~T$G*O<ɺw`mӲ8vNuVG~}^ ^{5t!XDURZ@ WPOCP71 #.^nE@j%PoҦÎ1x8x851܂On2VauIhGAq =muA1&)mzZrd?l#S{6GnqNO18{n%J=9` {֌@ȩ8{=J=o!7}6f@b@]z0zF3"Э2/ h9 @v89HldnFB-Q\FYBCGs.!%эhEhbDz0|A4P_w5O>Dz_Cgߠ^>/ f ~::g֛!>h#٧ͺBX_~P^O~ Ӯ-sCȻSP!5^!WX!uUmWo?~!ԓ?F{jOn+BXA`0mֶ(~x_#~j^gUck>5 P<2٫,R2F>j S 7|emc/>]8CW6SK }5-Kb,@lCS7aLd":dc eR7A6pj.2MpL|SF8q5o/(1 Wڇt))C .iZ] t!|o| .<8`pXA7剠KAׂe̓2_BY$e<#LY&yY%G2R??)OOO鬖4IHieRRӚ&1"ʦl=[V>\ݟ\\ТmjξriF£޴T_Zrri5{2`:/V3eSl tFevN /kmR>Vywg)uڋ~:o?rӹeHr8YŽ ǝ9{t,繈{R,K"3r8yA<9([sY0's_ͷƾWq,ȏ'?gPtržPBS Vy {p gn8s*ļB+9J}2#SVYUH O$EWa~l,}EE9k.RsX1-F#8.J(|"Q\Ѵ%yeK<3)|c3?~x sb '}M6Ī>dRK/8|#qȍ|ܫϼx3/y+I K[ޒLwJKP&ΥIiRJ2^2.C\ː2Ķ,Qx%gesY)_ _ 0$ /y +r+rTY<ˣ<_Wீo]]]U$1_%bP {+>TfNeTfNeTfNeT晾2B_*W!gUYUV%U{U^UrJ}"5Id}&R<$R+ؐ P 9rj_T#'հAz:9N,.ZKb$QI*X%:j:j:j&:jgM?5sk!6j#6ա]vSOdşSOu.ꢯ.zX|#_W=U|%d򕌟,_5Wi7m@6@CC=XCR7 }C6Bf#F&hMMߛ)5ŦfĠf5欫Ĺ6Z2%>$Vj{Pmha>aF Fa0vľ|ӞصǶĤ;`Cb:P_k#:#t#1Hu}O' :o'NIJR?LEV*6b[*~"'9L :ۙL]t.ׅ|vŇJ,R?]+vޮ{boWnnnucc_Kw| ݱ;6tǗ_zPk=փAl{Ĵ݃A~{b[Olm='Ķ= Ӌ97<}߇!N}/vξ;bg_K%F}O?lG !6H&}!g~ (E "Vk0F` Ar7PC E0|ƼaÉpG c@H==a$1IݏĦQ3B(08{ 1c{ 9?LjXlK %c},v%F8#{6#vO '$9|ObS| OaS?&0g"'IMNFde29)ȘBl7Se qJJMO֧Tl> 1u7iMgtMgtr>XNGtr6g:񘎟ӱi t ja@ 2虉̝ɼYc9EgY,pyEf1o6qlg#s6ﳩPsw oC?xρ:粖׹:\Msg.!9x;c}?GOl{_ /׼55=/12z/ W׫zg\Qϯk_K%:u\'z'N:׉qx9o2M7ћ:‡-ly ޷mb6z&No ص8n нjdwMICOyHc~?wݻ]K {:߃}xFm#1H>@@CjC2ClG#|a&6gc߄̏c|xL]~̺|}p oFfY㛑eާJ,>>?Cg3t}F>Y~cVm^ڊ/_` _ľWWسhokb5_5}7}vl؎Ovr9ڏ'| ?aOe5v3?cNxvNwb/ kWtJb.⿋~Co{!c[>r{s?ݏߏ??'6 xzw@  =OY[B!rzه0rPsG('$&:189d Q)OQh&6Eu &Oc9C{gYsp؞#]y|@_ gH.""]&Fet] WUj*25\^Ǿvޠ}tI]gї>o1L݂Eln15ڮao©'ؐ=w^M82a3y$/H&hZ2X~M@*x4"mb5Yh-OU0 ?o$E Tr_v7hhScB !| %?Gf~xCVVtlca" [¶Nlۃq_wV8`n!dZW!|@O0q)L [̍HW"*^E(Z1'l*A<# ]̋./rCcK O.%iIbPݥC)l.M`Cd!eG@<c9aOyG~ygN+0^TĮ[)_Vf~e+*DH"~%b{5rW ?SuU;% $D$a{ bZ5Ik"&y\Zĥ}U ;jaW-ꦖXk_zW;zG̒O]'7  6?̆5d!iHnaK#rCWRMq349z[%kVЊiML0mEKa<(qhKQ3{|lՑyO*JĢ3Xj Rc] 9vo A`~Oۓ-@B|XEص[S1g1m \L4X=-`3gYsP4Y+Li%~$+_I^Wҿ򼢭5y Ey/"w 1^/u2>LB_aoz^%5x֢o-a:jf=czb::^ o7M&}1Em8mޡFy&ޥ%>xGFjbx~H?"A9kv k3:7-5qSF?ω[_˗}I޿bi6~_S'ߐoVQ|w;S?@ _?0GďO ;{'`/++1܅]7(g^m79M<0{سxC~~jy|dϜ5!B!t&qGw1OI|QCLj1|>N85sDI/| ޿C:i"i23g` ?~9~=<ERu]¯u\+r~RW5N7&Ķ, gF3ƙQ̨[y E 8/jlFo6dnyQ&W&5cR&LxLl2ӭ>t)~` ]zi` ]8 Z1`~E7Ahd<|Iu78nxo[bAm0,i;'GȃyOxG\=o( y7y7^Rb_ vy߃ls< Ӄ d!3A fܠ 5;3;zC7 z>oX]s37?s??>z~|Ϗn:%z(<2 ` 0V/)n}^ b{IĖ CV '80rN8! Oz!\h[V#5XEP'Pad=DR[ĮHb"gtAWAgt",B!E^/ _QrPW1c~1cn1|.Fl1VgNqƋ3^ř[cC l(}%>TJ9bn§h|&Ȉ&vԿxz_ݏ~t :~|Ï~b/bXK~cXj8[bXŇ8|8|8#Fqq_<|_<|#+z.Id$~$%S9M)bSܕ4T\K2 e+}e}YI V Il,GLk9bWW屽T'auTGgs)9INU95cMlILjas-dbƷTu_!u:Pu.sW\M?ЯGg=#%ӗ][MA}wrk@<B~Ct\7N[߈FjFj36almM[W39kfIJ9uS'Qs|ZYOo̖ԒiI_+¦VmE[ sBmP[)0:-cmiǼvY:Qb:ǎ:R=9agl].Ġ+n ϊz@vO|ꉮİv"ݽכ>ޗ%&}ų7ϋzџxrcA#@ z q@?xA b5Y5\Ɩ`x~lq-CJla o}}8rFP#3Q§Cy÷l,v=N\'8r2@'S4x? 4q&`와=us& { H&2>Lb$Ld2Sr64`NAgYRgΦ`x"o.:c6ͣo>yO|lZ g6.g!>/DBlX"bu/FbSK^BܗץذX. 0Yb,5>=G]-Grd` bWRk+VJ$+k#Ϋ*[U c>Bƪ†-R7mCzށ$@t$^X)"EEB"Xcd>trw99g̜;sv~Xc_Z 5tZ X V5[ 5[5@5ȷ6X=fe6/Apo-|u-d_ ;k!Zȱrk:Э:Э:ЭCCY_\{ΘSaa=<azeeeee|<_ˠ{ؘ@4@to#me6n6n6n6n6C 07666>[@t[@t[@t[@t[`-쭰Vq+ }Bg+ }V }Ams9Ams9Ams;;;;xnvw@ܝvBo' ^;k' vA]]]m0wA w7ݠ vn==@=m^ ~{At{o/>ȷ탾><>ȸ2]~~ۏ~AAAAA!!!!!aaaaaaQQQQQ+W _+888888OOOOOO$O$O$O$O$OU W*_U W      5׀_k 5iiiiiYYY`XpYg1nøq90nøqc9@{91nǸqyE1ǘyy1.G,pq\8~0n]u__E_E_.Na"t/AKt/AKt/h/^먓aס먓!{:^oy/e2x\.ӛ[z|8oCaQ'oC+_߁ ߁@wP].:}={yv  *tx<P`}PoBׇ+O?G`Po:\u~GQd?oon7w7`~7 ܄~7!MMMtm& ? x| 3|;|]?G_@/!`u o5d|5 گao@ l mn66[-~ 7;.p6wq..l|ww=h?Bo?=' ??~B_Q_o;0~G?`}xß ;?x^'N C`.v!k!';t BIHN"@=6$=N"/Aj$Vˑ" VIz9#%"E½^([T'>!! nB5paxlR l@g:ۜte :J$-hmk l!-vhF#D䳻@kZ{oHs=ly 訸Ix$4$NI' <,'q E <\aC'tSBV% -$}a(6 9/h^${s/w[x'MWH <* 7tLސ:g A_N|~] !/|`k50(42kor@C lAC>A 1 `? ! Nȯ$u P{) :A^H{p{#khCz e"DHS$' >r D?>:с6AO=|M}(rQN ig2@g@11.ukq"q?~ caX܋E~W3<3<`8܋^\>|-+@R/@+W[ Q < <1{1+F!S1.%r.%K t.KehUн W> UB[Wtըj`VgpAAk0C2ւzfk<>  CPvu[Pxu_A:خx iF׈FO#u;u;2 petF5 4A&YPOM(ӄ2ME3l Yqط@`[ V Vj+ 8mi\miNh]ڡHFh<c`1𙱐wx83N@LIk2xMF[ LFLO-Sg*l*o*d =4MCOt62MMg 3̈́~3!L,9 gAY٨}issqop7nh|ZN/G;}AEqr,F.%h K!R u |Ao9|`9x4OoOA<Ӑi>v[+!3Y{}sy=^a [NQ'pfG ty^ qd= 9N$ʾ YN6)l}8 ?3ճ|򝅽 7ڒ|.Ea,Xr x q}WA%2{M[mېGƻ%憒PW~"}~!t?N.C`|r@}܄ǨO'<>,>AQs}/h_B/q-WW-|7~ې6t}.x`a|G#vtOOg+0~He|@U(ZiP>>!2!f!j袁Bsjv x¶O#A $ ]0!K>g/P?a8i8&|#P.6Al-(zF耏8ZC]衇C,5@@B}AoD]#Ε~_gxțYpMD!v&B$ȓId%Cd /-WiBN;!"֔f3 !{6șIsK8i$Q>Sψɤ_CSRNR䗁 v(VTTN:tqS ߨոZ:\!Pjd7t8idh/4Cؽk6|n(36^5(x=z&B_ NB?e, }:|ȱ^椏f7w1Yz_ >O2uQ$lV@˧y%ʬY99< >YVAeW^hk!:z䭇/6@΍MtMNmv;l} }7x^ OBG Q ,+藎199;NUShOg!y"|^oe}w| )ҫh_6Q7`&x| y? >gt_@/pKX6- \?P?!g/~\}'d z  ?e't6p2"E$6HJ'[M'5.d}|9u"lg놴d9)NE9.dNsɜϥ\@/>Gs2xldD9/yLJ_9eN|=LkkMdHW8KYMNda,\"@'ʢ/ 4q2Xȏ9,?X/%)9yiICt",'˄Nʲ3nNV s"|.d%_{eL6*;8Yp 3!kMd.PazaHՀJ Gc^$k-afжڂzkAV|oNʵCvЏu$iF-dha d  Ƣ.ơxЎuh'@p1?e&BWNkY&F3o |n*9lpCy&͂La٨9(?zͭ@Byyy|||Cu8pEEbȲ>yKPs '>d}< '8S[Vi4ʯ<+ ,0=v`Kx= yo82d  ˨7+ono[-[dW ` ߃W! Gd{]tqc~OS: APnKl|u\L_k8ߠmu-t[߁~w!]| ˻;{a!yCPGG|d?Ca_ /_+ ;>î+xr?!/ @ {'wlӅ9d '"mOH94 2$ܓ'"}ɭs^(9N'>'1אۀ-ۡBNPt+Z^H咊z[r\'w;2G%#RH8T$`ܐVW WC5>k'.7&'!cd]B {( B!Clք;? xr|r ~Qk9y4t(-J$lX=|p? 'G蚀P$\? Sp/:^*t7 0:2oeN 3Q> zgVYΆ]'A`~ sa\":A&y/A W r8y1>4%([ З@.n v)-K!C)Ks)XW$ؠ6+mh@[,>W5@߁𙁰@إTB*F@^ л7z ~5(_ZOBZ6Cfu:|z`CzCzGz BơP b P1 ]6C05 >`a0< <6 0`6@Q! m;5{#6BpG MlƵ[rBV@{c$d ڑQQFl#^cw,8tP'o<&M>AP1D]'As:dq hBu*OoOk: 1~=gBYu6gϚrPn>>-@}-q}r,E.F}/,w)k)  22xˁ$𞄼OA @#? ڧQ+!3 x=ς׳ѳss?ϣ Hp^Dod]=Vjȼe^K yk-CXus=z˰ E84oq IOSU6B6._C%qW@'wRX 'ካֵ&SRֹ ~szrD@k Z 쯾C뱖ύ?=e<+ЉEŒȒAǒJgPhйxU8Ѻx;L zjNhl/=/.aЈb-{|cwg5bzZBF/wqvE@*zօa KȨ4aB313;ِи1+~ IԒ 94!+!(8!!0$w}OL\0V,aBX)c`Ng+JŒb8i!y77!c̚'')KBhFwڌ˜ܢ(GA1 A1/Uϒj:2B"llȇ8E+LY(JT>>DR4>;++kyӡ\wh5DZ 꼉D{RJ7%AkGZVJ+֨5*צZڲt)љmN-њ婢* -;J+¿}YoE߷Ν⚨LhC*C2V5Y7ch.Gn.ӽp u $؆uE/M%] u+{bG\I a^emegZ Blຒy}ۿ<,F6pŒ\Vgx˭T"_+t af8Rvqܰ9*e99E+C[Mڴ g|>_l?j3O>3BW!!$_ss'jIA_O#B"(GJ҅˴:SVQٝMgB [2N glNyEvPO?7|ȜO8 pTL,(&d}tU,:]vն:97<%'ee:ugOִ.O40=\G-~Wb3Yv>&]G:,8I&02`+̬B:aT U~,/#IXZAG66  Yp_?l"6MM`s'\X?AbK\ȷcd̷m(|Qe*x곲vde}ȋ a{J(Bol MneUnuuڠWgV?~5ϋ 0"#Tq:R+P]c%i1U&70*iaL&b-44颕 rjoԦwKc=G}UP0. fUcdA1)ComYozp'3o>70}@M슨L&7ݥST5O #55qFV$V(GbhouV}q9E. Q I`RuscVʴJvHJXZ@Bo Cqml#leLhZD*"'2ġv`˔u:? =XCQ%kl>51/v`qd\5u%]EwݶvZqlYW(KE ?0Sh KI_eo˺A"Q>? &5NAs7tF2)T&G Ml LP6=+3Jsb?|Ң)H >ԹLR?QY/X Nc55d"M8G:DŽ;mA~:S^ KdP[F֌R>$XQȓΏlJH堾ٞT `qh>$#. ,#c+Wr.,Ƈ<v&!BMq!'>pJBRC߮YՠO"Ϲ/O ?YXPH1;⺃Շs فv%j_Zk_^IJ˞ ?x x7]ICh9G+3e|AjHXtz~~i^R3Fx6ˌ Nǎ2+m@hZ% H<Y}fĚb*<?PG{wێ1rHLe 2zq44`C+]Tj*(1rCr7IN8'߫!%bB ?T-Ѕr?M^DpIh@~04GKϚf~ n J SY_kD,1 |:t9u0fڌMURYZ{\8镤Gm+K!%Ԟ@a ښ&MiO}5ŵ/̝l#٢x_OU)z-ܫ$d͵:q-JRSaB'8;sFvH€@kr!m$/No ci-DALnJcP' tMHQMCCId.1\WR5aU0'܁!*'LT~ѯ캾~[U>EU0aG_{W>;6=YV!dIrq292}EsG "_]_0ѯڈq8l{ :RZFHRς摸 xHKcs[h%/ (Ds IR9ItJ3oCOEӥKĚ9g'\rtzLޜ;wBL:A ּP5$&̱ -덦P_J;BERy9=<xxUۡ~61 !C̷T}s K#1cYKǽ8sRۜWߵx:&O%ЀZ͇9VZ7N\9LV!IFXnb笫D' #GPYj%zWQQl4XZϥ[MZ:Gi WUI%'ۢB+ ]_ߧ"۽%nzmQrsi}2 hl/.nh{1RR͋ͩmJ=,վ|4*AObsaI/]w1ڨ܏I5}o(ʭFh:E3ͿÉ(퉷*YYITGc,LW%GɉtG7$?!ʏQ$\?Aag rPLqWHDrUUjRUX&0UZY=*.V5jZto+? m'`NlM={[$ka‹ pNlھ'xHh{Š$KWե%\r厾^eŖE*TL>צ%ω4Z>l WHe)NCÂ#}uA'Rc r2CB4Z)sWP`:+1+1LMl0V.Ih (/B+*wyms#brbǕ`b)T\WٵťlNmI9Dܗܫ$AOJdvtٔl)ՠCf=qbo?'&XE-:XݝԽ*ߐhOksR-clCp"/2Xpoq????]VJQeTclj1.U/ 0S/v)ett5_28%&yɗBb<8~9<==yVdk#߶B?̝zCOG' 멮%=]q1z;@1q̦P?u]Zށ^| ǞHV9Vn wđ[/#?s;WʟnnE>A6|M{ZGDr1'3/K$),%uZ2OnX9_e$ ֙3tg4F>˞X4.e 'Zڠ|C&Wq[^dk>~xWN&|'@}/+J3{(v{ /y|^سG=qG_l-;OkFa7ݞ|Zx?MOB=nr6=攬U9a؍q`k.U}њ5kvݺs;)O')e?3|C2yD|Cg!G'Ef[2;}{(,%E|~_0E3d;ZlJ!Z);D'ymx/LS"{#|J]Zpf5*ά^^_Lf#Lk̩m oY˩7`aPc!?[7 b^=-{1xۈ|n^fgBMl͙=Gej^ZS#55W:V:/7'kc P&>ӻ~h@ =+^lzoZ !h^,-ItsOaO]4u6}.)'Ky֡e1v}GϘl/yf O\o+`"|%еK5`Ƽ,c;ĕAL\Gc&#(FucU cƄYݧB1]:gU{ȎA)IM)W;4oI"[f˵f[&4/8H{Oh6l:掹2\S/~n(ҸHŢl`[;;u0 q*ĎƥOlRIr5ƄQjZfԶ}_Pw,_=C-s--Y*Cb/]~F"򭩿q-ژY|X$#F5[ʂ4uXO76>>TWX?ߛb ژ *B"AJUa+VZ"=7VjQNg_|,?GQۚF#`mm#a;n4t}Vf\F /α ^ֻYL{^zc+h@iF$&EN/~!)Y%·?ef+3=]ٯ!i}H_\GeiVo~|"_\d|J)\zzzzylK6tz%2֌OVC摟Y{"Rw~Cu?9E?d҅JkC7mko-Ѕwo{o P>a} +l .Ǣ(Q1F׽xt4]{:ZqQKkTC\ +}w9y:I/+{ˈkуJa'^cqO|LWqm6N[67|ا$:wAzk>BOX1 y>&Fetv8{3?Ǔs\> \<}|2X<b$%RRJ3ϔʨH+):$=٢ņ}#۪[bDqw,q&r;60VG{X>L?i?_=[y  I0aejDb 2ͦLM=ֳg\ ";&"yEhbڻnEk5A)2>^zzaz=DFmTmKAi^n}zGڸ:9VVy1CYLޯj`D?;d1/GL͢>6ah'HTfoӶ2r(>)FG0ضneI֒psy}>F%ql8@~HYC~>k tp[WA:,~l2QBCkE~uu%i'JbZL=,Ջtg))f 1i_ȭgXM9p#]ѧKu=hȏ~/>>__Y~p/zMذ#.FR-n?DGGǼd;[]?>!4Y~ q1cpE4*$O17ѳב?;ȹ:F?[IvD8fb>]#, Dcdtb[q p۷)B`II yfR?ʈ[\a, ᮚ x*-6"Q^$qѩѤgD.~/" `&%3[QguVj#O) F(R[=y6d-hCV=ێ'/IGJ[PjgF{MMe2<ēE< ^+ΙU6~H ۻӳƴ|^!x/Djdo-9,n|wcg\Fg} i_cI6b ΄@$gX<`Lj`LlQ$!IeIdGH(}B`aY=(N5-!a!NN*W8WP[Y^taumiӦds,&{jԃk=!y"硖Ҵ`,)sL:fAOc :?ZfKFX`S-ѱtUںz]v@؊5uakZfC!.7ټma-0ۚB9/3b[8Hb-9 lo0[t2{ _eZW?  `7mӽyǼ=eoJNnmn +gO+v k|hՈU903#D'~ s "j~>0hbLgg`<]̸wK2Ӗ20^tS[y#˷]^yw7,ۣ7cO(;R՗.!9ʮ`lezyo,왑c):y\qy\Any2F9ˡE7?7Xk*?Gг#ҋcE6&XҳDŽlLgk!m?{>v{AZr Ul X=!0gtl?{(h™0Em\g^ 7ۙU?0.R` ^FDF+L.m;L+9εg!m<^!QmFÒX3a}_ϱ]~\{9yK|)ҳs8l-$q]%qRK5|H? c|,ܰz=z?g*-cmw޳gk%N|𑙇q s)SK!tQ_yg^]YUm#r؃ {ә<SS9鹰c{Ay<ԁ)Id=W;XH~/DՎg+IϏyIgy.Z,  Cy}@l>}$Ar0T5WztOS4OZS񙅳3ʒRKHpcd rfPhIz=g)j$6=)obkNÿϿu3qqF`wiv%#r|Jy{ bU HvCG>".Rٖ^g.MTIb+C5ӢhpנwoGlP2. ;HK'WaCi!fHF6JJ8@V/|,у6Yq7I&s | gkmz~ ρ?ۖ͏9ۮ[stt\AաE\ 3E^Nc ;œ$Ul'yxNo0yktRFG `г|1Joq'7,Kː3<*NР $z?B>^'LKpJ,IvĻuNH4΅h_͙+r: } 6f)T&NeONt>xNh:L+ 9a~Iz>>[8.MItd{)zcF&?25E쳧N6Aٽ~C/h?Fhtrb=25Q9i ј;1s:Y.qg{Su[d}c7 C '^,772Tr_8˱W 1' 'Y07>rD,^%\S^Ő0]AHa,~@x޺fz_Ѿ۷%WӾ ɴfaAayӳtxƳbߞ鼔ܵZ_"&1=k{-ݾԊt 6.>|gfMXDW,Dz!nnt/َC2O<}WInKHU&+ǻD9&$ơ^ģO~"{ 0ZgtO7i`5; 62CA20;9sx.Letkz]/ee<ؘu幵>jMg壚&|/687zŢl,ucݚ WJ/jWڭ]MP;UT0((-9`g%3*ThГP9PXcN #c.;\o .k>[wz?rSg!U$ǹ9L|r̝$%RlWƬ ɤgԽꈸm29!Cal||QG@cRmXy$ $[ԱEAF$ڗNXaG࣏%6lÓ뜣#٭ T+<˧֙"n(>3(T,VW)c؄]xn =42(Dnԯ_]d (Kf~toKbq߸N2kV[XIo_qi۶R.'#[RN h5!eQ1}|feeY<-t nO2$9-{@t&2\y" Rt9eea T+_AKR"q ~łB:gKW-Ը)ʐὅrW.`g-& YAMszyMʛ_*rZ-~0wk8{"ަ8°\kuI0-0Uu=_iZ|7̵6>֜kO΋gn$6K_rkj ;vlA78{W:R%޲>=z)O>XiPw hvb.YT*E,ihE_yp6/ \|?twHϓv`3ؔEҹ5++濔L5>S4ԋ.3=\ hޡQ>.ũ*{o+mۖ{ⶕoHVaҭg ɷMCݺz:0ji7D|ml]o)ֻOT+wmm+|֤‡f:Xݮ# Sz~Y \(3'GVp}N=qޕ=fz~^᭎a/!_W1M{LO4G!+ =гRh̯уF79.!=oӛRPB_7jjaz]w=*=UiR^GMӸ├MLuaSGf|½i0'?t]O,gJ\b%/RkS|ݍMIC}HOi/&?(KԵEQiW9k:tرCFrb.gtW(jzǃxE $"M?Lf Nt\Tp$tMsw9_Y|wͿCY~\$LoUsnf&=3I&Lf&uR&ILzI @(I PUbϾ*vU;"ذwڽ3ܷn̹{ʷb& R^xJ?!rkMB^ o򙼋z^POĶgK[H}=K?<7C-3M񺛦 aRނ_t{ wK0>/lطtKmy ٯȳ] |gggoo[z~<9M"{qAz?wQpN }{Uvg=~,+_HbCY+?'B~V F>WώFߑ8*~;r><ԿO?HΔOGQ# S7X}>6z*, ︶ Hg xv`'m6 / F9))29<^gZohap4ɶȅM3Tu lfמ Ϛ_jѽ #pR@a;rWs .f^ J0)3{el*OߏА>GeX!-ݖ,~KEUNsQdI1gqmӂqkWlڹs}Y)|'g'.53:ǂ#6D]88M~L(̟$K~iGB4zͤJ9 ܛ/нp*_p9A UOʩV ceԅgKgl=Lج.-Km>Wf c1Us1ycxꖟ,J?g10@52 yn0z^,&}y}Ľ@UTX :_7Ϝ܋2 f|_(߀ ~%|0)xZO}i^i}i/I}q ⳴}PFڧ|)I?{I}#ig/>M_Jڧ|Z4nië>if:m~?m_G'L=%{?LW{^B/Ey)m?'r3pO{k d~pۉ:j{#v&)>)~?3(o#$oJ8DĦ`^T҅ѿuNܬm=߈HDU16I95Y֢8?M]5#915/@ט]ᯉmA0XmݳZZG-wFQ&[[oǐodI) 4'e$&6~Iz[lbbXtD9<)ʟԯCySv9in%T =HHQ |SIAݔlH/!eaa]It> #AL%rȝ, //ܤ?x'~ 6^R],"G"q1$" =eh K{0gDACF]X|^-U7 . 68iWw l%TVwJy L1K֣ҧ!t>^=i~N `B)>٘Αu AuDA>$8eSP " o Pk _5̏& i#L_e`:ʝ]5w7nZ<[Iq7߳b޶*m' FA:sh/ha7Lj(|wwsc=rIl[a'=)Ku$"^@etdf}-ّ5^"R3cc"4Aai%#,,xVK3Pcgxғa@V/8ceFdXWSiv~๟a0bðKu=])d5W˙nlM^їм@~/ yzI2˗o<CcJd&bR 2vSί(No(aE}Z_VjD#B(SUvxM6AnR|dt)xXh4u3|H?!X`JRT3杣Bz =zD}FڒUN֕׵RsASlařMn/M_:: /R>Ȍt673j:v+JT+Y={@>LJVaZf()02<=`{d ,b2P4&qvYkp{; ш1GəP0)" ?CTz<{Sv𬔸` r^nѺFA?!B!YyAXk} k$liLnt= n@:`ej7FQI $ N$?^ tu6 G:)G7@K%}޵@m~tG t NV gpD1MPxDфS4јX"WХ'! W< qp#F릛\7$pep DvwDkRPd(vѠƕ@Gyǹ8?ݜQcD6;IZc̍;m!Z{jm1\)`gİ%*:zl|@('^k%{XW4;^, e``p#__ ux 05. OhA4v">WGvHRT%{~9uŞB!qIG <4o:G Va!p+}`h ުE[aK ||/mQTo}펖jӏRYn3)h8R/&0 دG`@hv< /S4u &Fvrq L #C񙵕i&E W5%/tr_pF;e$-܃rƗN؜ԆsigSc^^Toz,h? "l9P٠eӎޅ2\w=lM Z7}FSoH6O8B\X?b +`xmIvnn7\^Ɓe+:2I1V->Hr1Q1D#- 5 $}\=svʺ+h|\0FUl PҩCկ Z-Bܗoܶt6)?z}eoFRO~z1ل/x/}ϟd9\TQ=I"LD<[Kxٓ~JyeOIs+Uh' ".5mRVԀL>5'I3ݼawJnZEyxL23({]mhlCߜUda#wƄ4NJRG4Ax2?ѩ^\Op|ih^n[?O[)~=$r=tQ?:[ZǰpE9a$yW7f# [aQ8F*sƎ:mƖZsy'gU37[YKꭆҌ2ks=G1zX7|?u^!M".hF?8\ 2,K} fعLBh<CgGfvà_nuo=)[v&zvn'Q;Z3!+m:EpU {RKҝˢHOdgµA*$z"M'݇&:ML1~>$1踐$_3 ̺Z2Se2Џ~dHBsd&:942~0޽1^,1.Oj¹*I&ږw3]GYT:J)^:|Ђ΀b [7KDR<4wA5z8'f{q+ *7# TmAun(: MS&!Ğ'J|m ɱCK+X>i-N֕-I極Yui`ttYttz9GP*Nh!OU\;VwD>E,ϓ5 =4u~CXA%Us/^8iEuϠљղ!}Z+=AlBWޥKaf^u/뙽g2>/ 97;;Xa)mk[>?^^͟,CD1\FlI,ݚ1b 7Iؾc.N<^}=E}aO#56ŅlFy1}kX r-};Gg'9A")]0JxO8AK=:/^1. eL'3#R-ٟ"Y(GsW瑐_s~W~ɶ?QM%OD_ F5>OC0J[8r/L~v&&vY~~p%vgv;U+KĉZe%zz35EȀoY^'~mEAӛ}0H )1_T_^F-GD-T,y@83oE1C< ^HD{b?@blTZ)DG~OaH̚AJ'U> LȪ 6Y+č0.0HH) D:d"|_ri`snu0כƥFm&p+A8S;NKApCAy۪O@j #1X9zLcffPRBeP!Xn`[0Dmp]'Ȕ0Ҷwo36vn'q G5?roDeq,έz\%e&kPY;4Kp1.㾇vop1ѻ01v{~X*pzFN?hVG T}!S'\ux0}lPIT4]mp|ؘrgZ@11ٌ>\9 "q[䲲'y<9Cˤ'4#x1ZK B_0m~;a5 (Q؈|ҊEcvr-%AZ/ M˃?ehBc2 y~lp-zA@5BX_[՘ YLZp >͘v^[""ρ,SIhp8ۊw. *cIucIC{47j3< iZW! İ笑8.ݐO?};=Ӵ٠YI dzs[+) CurYko:j{l >$F_{, |fQ8g0=(DE~&_!>@Z&QWw2hΠ2\ zuMPgEQƪ חCj60_:#ѽנZpEmp/ \G2^mrL>x)hQ;@34ό`jl$U ZX7)&B: ];#GX@H+%/؞\?'m @Wy}hg7<hާ,#,= M E+C#SHVey 08s@9|d̕%}_tOxt`QHCH"L8d'2lAt )`D?;K@0I1k.2W5E8\cc94Ԫ OfZf\5vsKHI$.+S|Úll!f4vD7!&E [E f4usJ@i.e4SzQ6S=xq8IX"mSO: <^%}jnR꼇 i1'Xpz֩)- 0 t;8މdЍکNtV&O9I8Wk U4ppGXy|ΝbX$ с!~9VJ 1)LgEIHbdDk~DeC8Is" BesQ킨 )bTnDefT0P0#-$-q;?qT@Ɛ|} 6m' QF4Ҩڜ;H^@=ƾ#$1g{x_Oqrw؃d\DP=l7wC* u ~^+hk$WoKzм5sG2ʌD[{~9D,4 ?EGh}V#:z^b|O"=Gš `Dׅ)CP'lT&Vģ #sğkl\\)~xύ2p9Sz-< 'yP`t+Ƅܿ 홫UrGPٿq@n '`+%#3S> J3dAGhE&RN5%[i?eZ ؊x7~u{dEz/IٰԿU߂d·ěM&zP4-s {dg)RPiN, y((rSax=.;7bGݝ_mvećPZצRKL{p_?}brn.9&׋na97ϝ%e@(%{~9",OQ&5) ϳ,no.4=CLȻ|/s$~pW' V|˨s'!/y,: ;Jڊ]OhnRgY`Z^c2kNf`و yz}hLtMsh3Ly\`~rPܝ.#u"o'ln;q&.܀L+|M̸LPƽ)N̟Ba!)}[/~XQx&q>V8$+0Lo Λ|'};w (h،^K4p(lGK+^w:gevw JyԹ_ UkoIًb7:y>T/mG}a*1K܋:Z|AʋE]<9}Pg}ȼ$ĻAӎwNxԃC !D#Ee9~DM[H=pA<2yIry77εT|U*8O8* <*%w{nx@gIAyJ̜Bc- ԉ#ɕ^&Wf:x=$fAבK*AGd1b '2B;kdD {@TxtN\|UhU6f 0y@#5,n+*hXz-օYdõch dR08Tx]Uv#!i n-YW\FDu[`~'-es,|n*LIzN޶AjRR$`*Wk5m@)/798.*B N 3AAA`EJ&XIi1 M@*E U U@e"P_B/P4lb u T+|B@2P15&*P@OG^zLB󆶽AwqWa{hB"~UH/㑎ͫRc-<(Xt!ސX5O45CU!ڐ̄P@&?4!3)>*Bx9·'³p» B J\YqԊH_' ~=yɦ&'7YZ֔T:cO*m%I A$==q8Z8qvayLxGaQak8xE8 5N^hRg(UPX(H߮nUQl',HSVa]I8 Iu6z&>vhXt#;sjH]^7߃=>4 ۏq9M%STVIʺCˎRJT6 Ge;u`d/5n !wJlqV^w&ge߄'Pb)FMc6Z£&s:Y ƾ6:.h1`(h{^BCn#!n~zDɐ:Bޙ ~+/y潋FTwL6i֓9d&RY3})t4͒^rler<IV .d88ۅe, >>5]m~yP͜}Cq 9O_Q{yA|i~L E+!tG$bIH :)Myv`RNg"SM7&@`q(u FPwjI~ D?+Vm*Nrn& J&BCsCڋۻhء;s=+ {V&$_YScj6h$(q`<1KXWLVZ;``3؅7z:oPM729N46 SGBގD Ms.yŀ;jG@_|Pt`jf$\$qt$cOKD(CY. N.}_o{p//]rv2C0`tܹ hRt_VQaW:(U]7?^[Ʈ┬#0e`|Xuĉ5x+SIko*M6 =~C5&}_ŕUΒ6]Tg fLp3E6${d"`3c)'B A̎>Jjk{3 2E!G"_.D3Xn75<)LGp+CNVe  Wփy[纝5'En)첬 \03T9z#VNJdTlI i:k:%4J?R##/yZ?D<`e {(#\~780&)*1Heyל V)oe<6$_}XNVƆWwI' G*5mQŁ s' p'ϖ^Ð~Q!ԛi)uv)bށ(ԛ 98UίH %caۑV]Džgj|m,LwjWvzmEɷiB?;h,Q^@zC;L TgX2u;`J , vP8Ѷf(Y-WI ~nM]h&fWl(IP6#!''/';>.+Y92jC:дit_=3<6`$nj6Z6*&;'>.Y HLqZ AT84|ہ^x7=^O1~ ?uENg!"gXmE,glHM HY[];+4j'+M$iA1;Yi}Վ^Gz~KxϪ/KQQzH.n^iخ^yιd XcN*jUo!G[iA $X\:s߼wj6Furp@4|">-ʒ3 NG4N#"ex9G#-^ȁ @1}:`~ѯHdbpRNosŒ:Җo䵍zosfݰe@^O+ 9=IκbwŊ],|#hs`X1V@^2]`ζƲ)\kT[Lp󠵷~689T8ɉ^u-Hϣt߈s7jgX[_嵀Ľ槟BrVra(a  dᣨ+$}V{́Ynp|`>\'n\UnN':Z; 3Y Oӽwγnjد-(y-½dCYuel]:gΥtudʗa&+W+$t~ bX*2T  bK0膅3aku?C/Zv=x| w#m| BԼ^қS܊4de甶> tLJ~Jd{.^@sX(:h$ٽSyM̚¨:#־KU8 űAz L eT;\tTPU4u7U5tsu>~įeHǹkj`H &CO6%: N_ 2@cpy wlw(ҬVw#kI1Ur@E(Bc3]#uKcQX OKˆ믗2^xmFD\A4~R/Nt47xCd8"m2RyF4  % _,S\7eM  eٜ˦C\'yƣ>qÊ~VX>tn+i/w (,3)4`qZW]=ʯv)ޗd|r+>WaƖ#3Z\})HfκRKB>DIJ UΤnNe>Z{`ߤvOY+H +υ~t kg x fN2'H5^+lg2M9/ЎȚfvgu7iK -罻|N~kij{WR{ •nIܮcEc$dDQIl}۵(̷4EH65ԆsdY؂#'1#ؾ[c@^$'za57Z-Xc?6gvp*Ѿ? %<00<`Zs=Q?"0.j/Sa Ӣm;ġ  zB8*z/Q RW 24t]N>X/'g_")-ؘS5к ~:=#^9Gބe)4K@QԐ4ѤpKKSHuD2pl7,3hR;Y.qC6l4 "~3/zۼx6)I:o=tMG<#7$Wh{/Q ׂ 駛Vek4Yu+_tw,z:uܜ-VcOϢ>B 5Fn?Գ^+l떌_ f}wRyo]rwl~!wA ߊ)6lLP߿Hf h挷}ys/4"(ZcV\Fl)58 r ɳr e>U t(pIH#7<5+A 1v&]/NzA@L65m+SDžŧ$վ*R ;6 AQ?f3o&,D1!& Vmڔn)5R͵~qszGW>ږ׮/ɪЯSbMH rĭH0 avt$Ӳ!9 ML ˊ? D2N gFBr-25ڿ'OПNgvC;e7aɱMŒk9UfQgCm8C#|.^qq8O_6HG 1 zAv+x6&s<t=}tq@u2DE9~a ylڐ pNx89\g]0&Ϝ:Ei?9gUIcǻ.:NBb3JS@pڢ_7ImЌ`%V&ޭbx'tHySjܨ9yϜ=wdtvN36gxwNƊjC]]UUwt%; "Ӵc_;ȌQtnkd}gܠsLՋhvJ8:8TC$2$+0yz]Gqn,DGg̡BihSx]]& 퇓s?8{3.W40:8JЯ%d_iOԲٖYO \[]PozjFG)+Ֆh1~- {_]qyލ<~'2.>gm^Z;)|Frx"eCuBbjo% +P_W fe%;wۊTpsj7 S, .mųI9옃ا.h-49Yw 2D:A4ڲq]Ae[=AUk}}۶倕QY g#eS)fFmBx&/XEsEPM!8@PhZ֖c[fسgAWEmmmp]hCm Hkgp] _ MAxHUV0𙢹ғ Efqs[KOnٷ:`{{0,e\D+pzDJxBh g:~}\U׮-*i˸UǪ{jWݚČN: H DV,{,, uksO=ޱi_MuE*=忭"yu|_'h;`%Qy딼fs Mȫ߰Bgl>Gf][Ӹoл+xJ3z~ڬv¿sOynW"Oޒ~!f@$bۭ⭷o |i{&* nGoDa69;uEUq4vqCy[/8n?W1z犏w!4,i_ey $xק`Ϡ~ Ͱ) 2Hϊ o V?JߌO @& ,mMsC4;xh5RS޿b3f<9%XĄc-/LGP[.H/l1lܾ.{Y\xӒ;zhl$۰ *ivA[|*qbcK/EE6%g2GGu%5?>^' 2=#tJnv8I\S5ubt*]\Eꬲfx˽xѾEs[Z{6]"۝BjMlyVp9p^;wz4oDf2ݓP=`Ac#etpZg:@zȉWp4Aђ}\K2%S5x3m s;293q;.)GAhl+KߦV'Z]lzS#۾=uOgoTQ{еXklL|yE[Y?:qi[[)s:9[4ʓiOv+48t) [aǝ/~7q|?Y0E&)K24b×o*ˎ1:u7QkΘ3cZKlԇJCs7] J:Ѥhc4iClcԶYKL%4ַe2?^fq/tn"?kp$ytBrrY~a7ͩFNW ߟeBX&*޶κ:EA0ڶ%cűP7_orpk/ap-۫WK餗Fm]4>_~]sI42o*{G]B)uHUohOj 4&,ddw2ᡝhS.WʠOD59Leėf%s^v`hÆ+׌4 VEa`"2e)oZnL-^0:Pl >oEelzj%~ j ycnJ*%BhQE7NɄPU5Ҥpn0?&3;).x#6 C\o(څZjFuhitwF)1Ymm8;:&P?D7RUgt,we;ЩD4#\G Nbno. r! `)viRǥ߷|zUc["a  ~H;Na څPxCh>CڣqmcltfqEbZ-p+5<=R ܙݸyG֯w?! /LrlWh߀p)t gM_ЌɫY'ًd^ ^!Z WffW~/ 9S+XQDlo ‰,=WUQ˜3I箘]^[4id`̛2-xVoD!My sOayd>pEM$'q=D|KH >^{+x>C|w[%y@ PlV*r=x# Eg+CC }|2_|FK *CN$ Yst$VOgGB7>AslWMLf;W?_/Tu1!D\)@4 ֊lYh2%+tws{NsN}S+}Bd+yz;Jg1FOc*?>XTd=1ש U <8*5 ᘰ B+cXA =S͈Y"kIƄ*ن݃~%0GN"l6Lj`NqӌZW,w)_;#xZNGop]A>Lm뚹ԏ֕' JI}`"{›VHPjɏzZuIo6 7'YBs=h~s=ݭh~Dy'~O.YoI^%J\V}SPoooky<_'<d>$qII?_P):S)ߑk8?>;HWy 1i0'U'uO  n-ұv? @s)V$z1ljHI G|]׌H: =$(Rou]a=XҘ Xi {FC-ʼnyvCP0~]Nҕ k얾%25-XO] V%ͅDCs $OQd<('t$_3'9`0oקD8prKA$"X$:s1{a] [c^M=-n/hόQMx񄌜KcS7;s=U7(sREhlrT%Zu;oðxqttr҆øFltCkpWe-GbȽ~"ۤ3 芪L`c}Að=UkiY\e8M"}-ljx WϞgõZR O˵TF`2zFԼjs,M&S'a|4f ( o6|KFXT,.MRfi`Y&|7d8Z}ޕ?}`dEμnn6m&r\.\wE@@lAD<EEAE@("; (y6ߟ#[޾77_c&w* z =P YܟNZ{?: (gHY]8ly}Cq9s;`䳳x$C Gl޶vǖ Y1p7} 囍bukg4;jqhB-82&~kc'n?+4_,[3~7&%*0pO Z+)p&<0wʋyyHa*"1H_^`|1)uO5䎚 ݎhs@]T'7+;Qk+86xظ56F)a 뛇ec !i\#/SӀ+ʓ2 RFe8߮7CyƉ&DO晪ޚy4_}y7Í燿a%Stmؚ { ߨW-"0t:ib˸8Qlv\LuucG8 $Tz=Gp5 n8B%l_a?`?Z;PhG0*H%&̾ οܔXB¶o{lפCMmr'(d1$#uq^?\b<9 -SFTX̂;~D#.aWdI< 趻H3qǤ2c}X'_Ͻ=ʜh~G=do ׀S/W:6s|ordOs6"[b{S4TNX _||7{-Q<#Cak,37}I6@guyl^|DYYC K,f+bRtB26>SCȯ5klOk[޼3mVv_/ZG< 6CSmفV /X? ΀h7Ŕ wh_gS 1X݋dq|փdS5 V'maa\\KnBm}kR/i>H;rN On+ Bil״+N sI콡lO;})x61u- 'V0ZGt9 [&6G'({t $KMr[\@ʃK9L 7WQNڷ}H+m۽0 o?v2tt ܓɳ64T"(XE UOU hStAH~DeV!5Y]FZFPz6 {hZŚ:~TqR&}j|C@ѫiwIv?ݛ[x& KfU{ػ7H#«GƩk*g IF *(q>9Ez"4NT@'EDקO==/`'l߰[|VpbWçBb%X]N<fʎ+ ~ l_V~$Ce,wmRj7x>=TݿyX pzјsZUuA$pEvf YwE<5pv%??Sv2TP|os#mKqw_ˈᗉ+VJh+{^>u :k:z33{oCo<בo %REJ/X`^n9= @gF'Һ}g8ڝA(cLSi=&W7Pz˿9p:Л1Q/!As=J:H(3Rؾ3B_%& Zc7HgDcLܷ~C7CLw=_dvlZ;8装a8a$jS1w,O憹xB Lzlћ9=KS> ;5D&C/Lp; b҃*lUzsۆΞNU87g:#R.e f ˉ- 36Ed6OģhlR:77|O0R*IhwF*FZ.%ALb_Id.dB _6K@"ZɄ?@+3tPj44‘ c,{3;Ƹڵ)(Hy{?v紆CV76gB :SbY tfiua{Tk 8|xߣo;)×2c1~K8z sb6~bNi@zuy &99n[H^uӃ.b*O DP߬T-.1/;|!d]Ur-u势1BVsH%~J#CSeX4 D~WdC K'wlc~yjF<3vR4[@ͷLHICĺul]|9=6wC$L-.nh9KW@l~]ݕJ7ŵ=O.S'ɺ/\v`=( [3VTZTJ)X^l,H6ѐj3 [s.Ugwf%o2g"0Ipޏt[\l4>"Vmq;1m@XˡB)o6eLDL:igxoXmxW~!ˍ)\s}7Z9^6u4kԈ|c_FS7/? a^stxpoB!WɼhE%f~Ol \@s&gEKF$úI 1bRb]4x`p/:vt:pomQrQ}ϐ6_{G'%"g񮀏#8>H2x{O"$C01Bc 붿*uGöip8,mCW\U,VKD"$$'-?| lz*l 7:Ош&%_n0Ө=ia3CSEOeHwA3jc<9͜`5M~3:/|bVB7#ТM :"t;3 -{ކl[e.ps)"׳k#w8_e 4w+W ܆n48ܾ=Q={ s1~mF pi6C _Vkל͕U3|-/pe.Oؔ,0f!Ii4vv.o}ɝ˅ $^u/E3߄ 7k`׮k6)c룷[s h&b% /V:觝x8 '|6b>WL~u9&5)U p9s8s8\ 뜬$0#9m+[]OgtM=3s)T@z~beO5sj6d̟晋+]e򚱤dl%KIt]/^ MOO6=ZxFp  3lߎ Hu*&OXQB~3gvKD nzO@T26ͥ*D6C*#-?;(o:ﴹsF+Gbmݞq!wJn! )Y' "0(Y(fu@q|KvY#aW|f?=W;ek+_7Nxzd X=m&\.,'S w'ڃ$[[Ŷ3 Oylۧas*`z'E> Y=} +|] :rǘOS)P^Lgw=%3ʪULY u%X辅}\Ӡ$K_s{h{Y~r7iw).W[h~w,|)C'HOܼ\1kgoe|kām]:+mk$Q[+qv!vXu@L C`Rሚ 5xt'`/d%u"le1u U|nk{Vٹ9vxofĎܣO%ρNQ)o|fpNŒ"S;~E|IjMt 489#s5HU#-戇lۖ !{ nCL䣵O߷Qp!oo"d\`OcX%~jjтoa,\, ͹qR_2pj1Rī3$.km~v ޵Y9:!8gzg6CV2)b9υb;iZi%&8o!~hn.kxdZG PSj88w(÷#Ɂ~;s~ ݎ`~ОmE= &g[` ~o@F΢O!T3Y>gql٫X6GZYk>bjMjKAԢ o<}?`*#gagF͡+¹̵8V)fƓ@jw1pdӟ9akgSgeo/KvadLlgTVE} .B}k]4R=)h~\ٷ4t-~fr% %m="\ϝر}k8}i=bM16B!i;Bu ^THalN.7/4?jo=O liSc#t}dfp؍o״YUPOK^qp#^_Fqp\N<8 ejy`ִNnƭ;tnƨ-҈&ɪWRʀ<Qm3؋;H[>;n]ޔZDi3~_`_nqMP m4|S菌)]`E7q\o#Dtݬ,9?8gj֭c  q \-i'fMK3uX[, X3g>53|xNoo[#wN4AnnXƏ$ϣR2KކNK}>`!7>r6N}ܷv G^%F/g; CWN7.§r^'&4Xs 5Ķ+R?SfU8>e^pO oi|a; Ng(ń} niG;9Mw̓Zx&k@ȜgԾP_ANJ,WVt_|⊜Ǔ/_| HxZ4I`k{~\k{Mjˣ"Zf|ӟVrnT? LwJ_8_(_Jo)j5*pl5oR's^ˏe#Sh;z2=*BxsųԍG\r#\kg'P*^GdOps.w"x Ftd[<Ǯ4B4ψMqs`\EF/kVD&@ =@ U&Ҹ\@2Y>׌Mh6QBP!PϬb\ԥH(ՑBk؉pܫ̮1oK}#e3]BÝ{іa[`N_7Q{bћQ\\MUF$Kyˑ/#*{;՗v*nh.SbxT{rO˭ҹr'rI/Z1WR6O9Pu@7Zp i%,Ix,??k6z{qO?(MDR_ߌ" 5`K)t`Hf|__,OҰW m>gл2F}&u#5Tܚ5|ډ ɪ[xWO!HU0yM zE;$Q}j):Bv,ivO>N}忖˿qI0/6.v>/# h+ٽԈLH"u=r:Qϙ~83:ڹd73t*E{ݒ PҩxqK*ְ\6 ohhj 9xBIˇ'7vn^Dq8Wqe?>>N|wR~W 5A%NL_`mktsPn֥s2/PπF SMCJicۿ@ 9!| m(?gQw?mTv*lh~`;9 Rp} ĸϓ_ϽHo/%+QU*[{Z@Z|ʡ)8 ~"L%7VUxvmөzWXcPno .!t;ڣ2á\r.Mf !ϭa1/ɢs-AܒE5ꥮ'cH9 K~,GrǿRPih5w Jt]jG^D+$ bv9%2/ ,7j 7nk=y8f=i {,gJACRBd礫wF~q$Z NշS7ŔN+3I<~CjW{) e"+ؓAP`#A@%s3L9Hy 5),+:*&ShP q= -R.qtczYX7bh )sl.#Y(F6 ="XVdtʾ3MD.D4mٮez36MS^Ra4vhRW܎l8$5:ըL=hLy:G+E'tm+@2#z@ИROI>ufݱ`kܸC*F`JiǔMt简;AL!ej2@}@G}p& i6/G]XZ"[R Ӓh6w4:*`^P;ux(3.F ڭUH~Cl|ኸ`4(04]a=6ڱY.$rXpINo=pxpyxC2#m$Q,KlH=cxpZ@,|D&ٜwqSFy'3KNo4+oQ?a3~E=딴.ZQiR9%6(?,pʄEŲwS*Jk\:Ϫ|Y]_K]MX ݼ2Gw!lSP[ bR@* 2m 6EA8npܦ'FuTLM@7L> 8gBuѯkĠaɗtKbũcUܞ.Z8=2Q.&iC89vDE}ݙdh5m.]| O!k3gW7F2):59XKgˏi&6/;f]?p $~FU^% YDl} q{Bj;"}*St mڼuGEVx ܌`s ;[%lZ?pPOnf6B񭎙ce.O䁯NbYrBlW+ tPDh c`x3*e H㾝d+|JliY^_8u\ކסc$~Qcr. 5@-;))ȪwyՉpGnKsm1xpC%kQ Wҵ$`-Kw,ߋ iAj;)Hy{3ofu)]~eHա*ۀczq#F Lyn`qڃb+'`&M9SRf?J :0Hǂ=ewdqc_HgԂ24io6 lkW0rO5.+AQxY-ndGVV~K"R?K.Ўm__Kr>Rj/p?Ro p8s3kX+qtʊKv*9bwXm]:fg;A\nV=7vbCRL;VKjkzCHg?pU{i]h\~J[vN"Z쾄L4h{ƇJC}%1iå@c)^$a_QӤ0b+S9߹L?#X{ťa5}hA+,ͅaAISi4Q-DYpvo"Ӓlw-~{rF]`V]〿yS%;̛x)?vǹ|2 QOP[նBPЯ+3$zPÈ ,K[ОC{ץeJào3D2=#Db9c&~{'ƸǮL]#;|M~Gt,ccsCFD+\ơEbsQM?' o+}&n11kY*NѹP4 D}fgQN]ؽgo,Hs M,oz =cY6H6slmRZ"Bעi "8xp"כk%4Cpgh ,:m*|3Ța$owCF~~@% NiJ$c@j1.Ԑ%~_.Fn?5TR'̅$_MtѠp#nU)r=5oi9Vʃ+WB6YjzI^n [dJA2.)刨_3!h/^w Rw4a_:"'h"WCrR~9"ofĶJLt=] zgl`vzWuך_{k_!׉A7%srB¶ G>r0SuM` LGU%%v./Q_Yb`vαtP25F+WW=:)jAXlBbU4y͙OiJ5o TUB7 XXf3ձǠ(}vNUNxv[8lGޒ\mDJPho-gm137٢@~\R=;7J?@P}Y-Y1hdƈ%F(|Iv0N֏d7՟pYB]vI!W3kv.Eb\1:FܳYlʯRF.ۍ#4+h#Zd)24`c4Am얅t )5sOXr[ZB\d{9d^3UL-4a-{{7.{3EFaՑnKrrtsd4QY[v|W4<̷4}AlT{v&r;ssceS]#;E77_wh^76.IⴘݹTx`ZZ&BƢNh Sf6ַRF+I l-cxldzEnX.yܩϳ_и09t+mMMV6m |ϱ8oH$֓HcqLP~9&Of3]}g[xlr$t0}}$oX »1x'eQq?f̺p9ݧيa=v;z~ B.9G֯*٣QĮ*vћZ|f6\:=f5(=KΔ_\ZZ&U4JH_f34㵳1(85^ \5 Li4oz#]qC/bl~%t <ѕ3Y4S9Y{`^7nxس&AwEYubVU-W/?>fhe Vk^YGvٿ|Iz$YEV:ڪ TWXٻf.ݿ>ֵJC1 MV=h>3|os~_NFC}gQ ۳^'?!99ͅXռ(X΁ˬOs$? Ϭ=F%ŖFELl&1 f:!A j&j@!J+?5,Kr&Tek7H0>+x>`n^Zndd锚Zï\䯽8rHOƙ(\IKtƣ.Gѽ05`yR>FD#Y/jhd1瞸e3Zw~04Z>-ф ZE T6uN7sU0Hs b9Ɵ$ك;/Q?=-]֘X;C<66XϝSnݕ\=o^ëIc⮋o)9 \u* |!% ʛc1p"+90P(-P!hALQ(]2+qu+X^Pؗ &!jc:>T[Lcr@nGʱMW޴'h]@.5DN4T,Q >Sbk5"{۲ ϛ12w܅TKɱÆ)B)s4+@!q]Vl2~O0צϔPbڞT7j MO{/F|&tI՞Sm} gw.Jas[P {&c>pY;jFO!X݄յԬyɂB~T"`40ƙ7Z&2|#mQXН׷lQs[c_T@Y!5 ND2m;d/.5EKϘ<" bɬi. K#f;Nt؛ɴsF\A~9wqKeq˾^S"08tf9 C{bޛ*ȜpJ?)ՕKcC-7j!%D džbV^A-&%ٓgą+Bd 0_Uf׌u,cML,t,d-&qmyv$ʵ ୴MÛӥ8jAu4pI PL!t4p üT#L0J $)#h"W QdrJMP('BE"sKX#~ImZ: (v=1X|JsHF\[v|a'is!IlUf?%7aA#IZU$ؘ/. >Al8O!hUv 030tFʣ) )2s0 5C" Bͬ} HX"{MLǚ؀v'ŠpIVSZ :58 ]eδX ] j(" 6'dj^) g]wQ0x4*Wo+^ u$f {:bSDV YG.NNk2&oc5I|4 xxۍ:}7=amqUvY~M ΅C3/4(>&>0𯃱Qτ}) cGx}%ãsz[1rg:FZ\k6WV;AWN[Cv-54jFc yڂOls Lm5D God韪pq[ c2{ZRϥ*г!SۻVnL1۫!xO.PX}^HbE|^t󱎭2Դc I,ngDnQ.3L [ϧYH"] KxԪFY( kQ$6"YHے]@eww3CA ԼiwhlinYa$Qz `)D6E?Ҥ1; bKԟXUX< Ez>tiG ]aY/ [\%pq.h*vآјt_]]1&}6> xi^7mhvau 5ظpBn76fZg"J3 ngv%5c|nO nf9uLLBCc($2t$T uAws=]NkM "bi|x|W#Bd|ҳi)c }kC%J̫J2+oZbfVEj|,tuRMѺo`AIFGSH\a|uo#,FM|> 4}J3R8QEQd|3A\vefb,ի!b% TNqy86uAկbH2 4+РN \ 8Zȇ#XO z0#k#ư= +w5] d˜wImѠtK$K ={KÛ-V* i5p噾<$wkuUDz}1iixcu&ii#pT 8_GO0d4m$Dz䭓0upNLq'sHI(% Nʇ_oTzv?NꞜSOOؓcOܝ9gmjUΫ$$aI`6`d's 9lp6h_=r5իu9n̛ml IP'-Rړ[䍬ϢVx҉7 b!y fbRVuʼkKvS9w+]]hE$~t_x^g1WͨfW]gy[7^۷Qj ŸѶ鈿 E<2o(vOgojTҟ=6QVIaJ)'*>OrA\nsp09O8Dgxm<zǎ :KL,lK5pydV@2\؅b={!}>\5s5/:hir-vM1Cؤ8PlGYp=oBmblѺ]%*irҀL,x02_ՔJ͞zj;˥W3.McQmd!r"2 xu hhb6a P 낅Yr, dm nL\ߝBم-fPuwS`?+pc 5F+!aد<'ŊCչpp|2D:@mSAcjXD;wUT:L#xrY0bh;\ y}=3IF+laYKJcx"l5+q?(M3C1vM \OmI2А:XSlU^@^3[դEl[;%]Vk:`8QT,IE 2ӈMԑxaW#9ku/_odIf"q:_"ml}[Wzמ|;lukJ8>'Y8Ңf$5e %L#ՌvS/z{Vf"6N"BT/| >%nATҫH8;z[MZzv2}ߴƴUC^[F'}< ~5v05Boexޢۧ'CT!_AMP7dzOclHՁ\Aõ2[A\cR)Wuܺs](5m6\?ͯqxw?8 W d w_>gV;wD5WQHRw7q??1U[z3 JH[0(0#iGY2-)MrJ%=Pa[ H P\4E&JXD"5mMPFs~S~_{Taʾ*ZS!k*:uɨ:7NViVM>x s] i 7ӴNx<t @OoEg!Sa?UJf=8ּ1vKMSLPxS*Q\Yi?a'~spp/5@Bq4 7#92$[GNNrkv-X,4=I#9x0Z,.5JQGkbOHGee8k(n-K+#"Oo<'k@^B*A:|P74X=34-5X2=6>n؀m5Þ!f6Re]՜kNnƂ<Κ%Ǵ\JMepN,x]%&LҖ_X-cGfSQږ\rofO$c>{`Ϋ}ۛR$$JTrrtn3+CuzCks Iw@kTa;e4P@h.j͔4ËcW~Onz'uQCŧ* UmTLHȗOlR{)an -1W◹lX tnۑEzyW>g=%Ӻ3; ZxLk :،AށMʄ=ք3Dlvfp^(i-qDV̈a浘;N1"(,7dz҇'jF˝6VIJbCwoa(zzRj¡w DS!p*a[D~5tf صR(UG__) %5¨)$;/x|Pvc.臯+iLK*&BAV<m~MgaCZWK @T3=|$Pk뎰=kY-1Αf@Uѷ9!ROơ/oWy&@x[~hL">Z-_'k8LG&P.piρ!kd^Ba1a;2-2=_<(9Z8gJ l0[ !1jDl]TR|#!}[wC`<$ƔZ]ZY& 9mB*hT`B$PJ[{bV\:XM`*eNCG@s\g-4wYmP"f,, gg1,29̇;ݖ+jZ"n,ј" tY?eMm4j Ӄ5D(#9Vک3mduMD[Dp7[iдM,E u]Omq#G S1Jj yHJV˦iUFKu#`4ثngk4VF8} x{pHPЀK5_c˴pWvL$ "/Cn/PBڹ[aisw7.:9 z2YTOOj,WDU L4Z(d!  s~Xk 2mn"ًGz~ a1y_Nn pK @g |ۂZ9䁇 :0/Wli˹sW_}`F)Єe3!B8ZNŻbgaCnv.`㡘/فaOG-X C nGΞR? ` O $IZ7k UV}D_F>3';M1eZKPǦGۤ~*"f;k[cWDKwW+]9Mgc[+9qDwz yn>6t=v[=ք?P)凅\C\p.t#ꘜdSnŃ $ar6X:A^($?67hAr>' a&SnbMrQ'i ʆ#+C դ$3P~_BYkIrl}%lANAxVSgWG֬ ^͚3 bPmc(ľ5p%( Xq # *戌JZdfVK%C{ KL<ՙ¢d98)._ž  `>5G- A4$Eq!`Ǝ)9 i7Si)H7Z9߉ V 7s.a$^'nhƘHp 5o9Ǭuq'<㩞|[ƶ+w\'Lu䳝rsvo̬AG:2"N2nP8S3LGG/w;ùav5ܑ&&a ZFp:|u~8IMf_6մ{^#]o4cqZhKO~ Q^Fnv7/.|v a 3G.)mw?QQ񙼶s # G!uh*UoP^Ou H|K?wA}?? ~|mυ\x?B ڑl(*{wլoPnn|nqU+ػՖf'^l[:S{Fǡ l97e _ƪkwIBt zV:=AœnP Wy7Cms [|OT9ȦpWBrpHO #X7WV _O̵"'Zr<(#$p8z҅Qo,XYBT{1jϜ#S{)ugWQaM!m*2dyevN,ꇴ0 mR\ (%QBA&Ƀ.T)7WoࠏTx[u*Z'`, hо>2!]n=5\\蹤eO'cVO]5-wgm۾ =LwP7V&hJ=p@DQjHjG!G՞K[R3lFOJej L9Yt/ǃ Ctte܀jxGW h_!DWxy]!ryt\,SR\EnlKܿ%!]>־wTvE`wZ]S邬k:ڹBvA KZmfNaP2|i3YM@j:!.Qh>=ywv_5cp8_B5o%@яm}X)-K:KFhQmPASZj?q"{K:"[AsH2PPMv.^[-?A2)zPƽ9=3Ȁ'HSv+/ZLn A+eT_8"xYq$+am|8wHR=cv#dl͖ BJ\-˒8k~o\/WHyxE*?hI'.3 z,M lю> #`ZZmWS J^o%D:$j!iRN{rj]NN^<ڱ \F>tZ@qfEr9>HCg|][z[v6\1;f=J. 䴚گ]əA6v(HɅc"3$PV#Zz/x3wU]gbIZy/O1]=)w~nI~ =$N@k5ϴ4~#4)٨=hxWc@B_K@z26;PE¬lٛ[|ھ.4(8 (ĪCb큲"e̕R9_WgpVrp\-חX\-%ѽ*@Χ܌|6}I'w5^*BR@Ս%)xct18Gēs2Lm-. xVck7;pJ* ee^(gM /,!V¡m]ZhcوX]jn:$ٮ] *ﳱ̎"@`WE%@ `S"1hMgϊ5*RBy</&K4+%wjwJVZ+V]@㢻8.ԒrbMj<^ ~!>62me:}R}WmWipfOtQB_Fn]'+;jޏۓs p}{Ҡ6xo=|b=%K}&y+[\9XzEGkϔťNʵ:Ƥɷ]SOX#B\Kt. wBJ;5ecl^pi=a]8}4_cv6x\LVLDk'oNq Z iVWx )>F g>t)0G Zݦl)5ށށFvy4]+싔8:J5Gԯ'kZjsM# WeOf}KxйЊnA܍sP ffڋںbaت&W I^eskm]vLt r(]i#Q[QN'~Yݬ?ppӄ}̕-4Sg&-Mn5 VyB*G +VM&^+$H_A1fMYRiP EgY k<__s4wi5Fq}hWDgk-!4RwV4u]:J!j9ƍ-wOpˇ9u<"CJuec&VPKV =rwEfYc6Z[f6%äaX0 6>.u igw~ǯV) 9ve\OʉsAsT#Wµ Sr̉ aL\v+ZIӈJ&rb o=]%_&/p-$S!qmrcBHά4EՒ"E"x6N<+VBV>"NN)ޠQ(Sd^ c?3 2D=i4q}!s@ 4!d5mk|UbImsR-ŷ.FcjuK aZă9l4@Va)1)aWx*p^+n߽/=Τ#!V>)9S좏CL"x~4QOs3R#Z䲆`}Ս_HCC7E{~zl>.vs=M63Z2]m~#~2Xvf0SwW06q&W [J- ;XJ\sz\l,΄ID8Ot,yS‰ VrcgqL˔i"܍Z򎉺I$e'g#]Z>t4{4-NL[ po-~ &d-Q[vi3]kžZaC=xT`ynjrӪѪnUeLޝ=&mODPw{'8w-x096(Uŷߙɥ;'g"RIhHAo1k{s}CQ];+5M-ϰ5_>sf♟^Ϗӛ>Ӹ+/KO>o+bpm3kH#mӉ]:9q,?vO{A>Ugپq1.}jRHxQ0E|앀mpFQ%W&Ko M]4Y(~SR(93 U"tv֭z<iZ!V ja=]R:R GL S @?~ sI^ֽ뎁to#U L)\y٢= fQhl覞ᨽc:V([m=]gB}a8Io$bCj M Mo?ƫ$x/5IT=I1>I4߿'x9~ƿZ–.NPUlꀣGU<7=92:ԴJ|AgR6ө̖O!UM;%왕_)c O ѼYೇv ipH}0c%dNz0\_}LC?Ƒ DBZq޾Y;sv_={߸ƛt:Ӵn}YUDžBEBjB s;joٝ۹AM~7aBz5Nx8W]dUD 6ˍ)YUɔvO˛.шMn4U{ԞvcW92kdSνlkվ5vuc)77SY7ÂÂkM?3GKQB ZQ5ivU]~>!cȃ-؄( /zLSL= \f fpY+n:y *gPިٶki׵UIsc-%{I=RD6%aI"mAfa.[2P&koBm6v9^߿t%'Ծ' ](w9[w_ @FP,P#i R]2J^gV)01\ָ |Kp5iod"9 h;n|+ @Wx3LʫjN6aɥuj$ܺ-܌"ʷsȦ]{s:{;v2!\'|~wޅD0xd$)l}[**lN,HE=&!KA:n.L10.2:9 *crͰWM̉&wȑK~Ü;o[ +JkΉ/ [8S_iׯ2(@8IYAǂ?|a^;]4=3*`y% 8յࢭV AO}?l j+uwX39!A'Jbڬjck6331s+= Hx:C,=@Jrk+1mzHz1 G-̸25hp n,Yu=!1'r}IcURZd)i$%ڏҐ4f"PفJj iTOo{ @/KUb%t[RM`Tt=x^ÆB 51KP0g`y Z"a鬓ndxWr]C: ƧAGX H?oސ}W=xSG&J@oΦ$O˳V`o{V~ vO"?)&~G }~"Ffwtͤ HG4'4R & ڑ$=9RWG&L#w~mGirZvq6g.#t|\ . WOpi4wtYnaιh6{* ;5ћgFz@ڬѩ+)TRLWf*rl^_yYAB+w\} * q/b'A>Q߁?{ϗ\?q\K\ySYŽ>R›Wu`n]hwme+;SW9pt)16~/%pr%D~&JA(x= Sd/ׇ؍\9ZRDL;J;ݹsw?2Skv>pᧀ.[7TLrPyy*ָ"VtT5w1xUae=Ġ8Z>v@錏"1ڣ)0+3}GB̩ VcJSmYV:9̶̭8Z;]+`ٝQ0x \1p)/X@¯b!q_LsձfX7/M+y~ w>U1s6T۰{n,mmX O@Ymph,Dfد/ :Rk+<_d`]`}}e8t:I R)#/FB2vV ~esvuX(!6鷗'~ oB~nC~Ĺ@;T/ȭVyY2\sa= %iN~W;YwڪH{31Fpv`LlA(:&w+/bC`p8Tu9yЀ%ԜU;*֏ ~EM \(m"Tm5%V^FHKWO( L4~>&-l% @Hwjbf- oBq$eSkKH*Dpg.KM&t!SD>Fi_"@9bQ 9S RA(欳[R\W:fBƶ@Z=<@S>p)R˟c Þ؆L*(=tA ; kh&`kx<ϕz4Ќ nKv`_G)nPW' 3hyv v8Ij?VYSGoG8&epVC <xQ/ΖCRޣ+ឝDN=KvL:HPoڸ7¥/iogro6V h-'wE '(X%'n];l#f\M=kU8O/NKPnuo\(̖:]R5*OL\ܩ]=ZT_y~念u 2WfU:n\v`ў&1G=$ OVĮ0fcKt6E[r\붃32| 8[| ޝڡC.tM™̎ Nt3<ʟyM (+SR\dӢkK/G.hF/76t۳!"U>Lm K93'^ijnR%s^WXn@3š]G>[6R;+aj ̀om<}᱑H+^nouPMDa>D)6}MxZ9_t0a)/ 遟 ?|DVĕ8]  -c2:l`l0IAc G]$>Utr*඀j 3Ln(gPS31OO"쬫Qx3*7pآ />?/SGC /1SOo~V&կ.y۴;FHϒA^0 yzDą*^+/[ rK( VKrB&L?CI(&2Ed 䂟6ꌹaHH*t,ZZHC3Ťov^~&jGF`P[4 _ޮwtv>f}ɕa)svTno7㟼ona\> ^ʇ==]CR5a_̀ǭ` :,v}K:7W^| C"EWZw:. zHPP(QkH"\P,VFV.<|lDV|{EqBG*L\=ٻ,[T@+mt4 M]al~G]<{V)V//oa~gW1~_.o+go=_kLpRҤgZk&,Y'mIUm7לqPyeYˆ=w P׋8/sRXǖVoĩ| 6FB>$~{pa?;o <=mۦ;J!`BIM3@o*Mq_{a2Ԗjq42TJ9z"iĶ|! W'>67v0rFC+?c<'.uB?0><+_<E ׍C{M0dJ%riЩ͕Ob÷#ٚEdFc"?jů-)gZ5YAG > 9}TPdсTD$mCcoU}ptb6YZԣ_օݴwt׼0wk4f<&ݭ.;u&ֱXx5 bRʅࠁ4 vD{}lH_:29b q|Im#lDKÃ6!y7UE[ jDy~FN5'1CN4(pթI<#2,|.8V=SںP/Sf([ 3M  ʩwGn-^Urޛٵa6"֠y_ς;=>jJU\M./x7y|(PΐnHw5l{ݚi|86yl AA_)_SYl{;3ؾKڦTu5Xluб\G,j$V~6Rx}`Sd5vG:";UH>Ux.42GN$%4.z%G{J%(|dB%Ľ'l271'1TV 9rc&\jp.f&\|uK%>wͥLz^9*?#X߻qww."@ ̪aƟ~Lʱ.|tܥ5kx o U5}*p Ի(>Ie9'ՖɄޛҝbGۍGOmh"ҷޱbhNm|K,bˎOYS˒-ɺ%eeY#G9 IEHH @4Жr(WPQ-wC$N۝ٝŸ>Ʀȉ@r @ViobrNJD!x&WV֌ 7UjWU> "3%Ak @PXE_]3BfvPƔ"S55Hil vz՝7mu]'a[ozV <]~o5 Bao Om_ _1nw҅ D<_!6&c=F7} rs ɗǶe/670|mD# {|ięf!v 6)QFl6"X :˞X;&H[Z|ezQ32_]*¼<8+1]>ӱ(8 T&Fc:˪ Uj=Q΃k*U)l .ȵlB mERRLgC;Cg|CcQ9޶syh1:&[eAXkjw,$/.L Lh|\WWw9:KI%IʔdݤY{I$eTH rY,5O`E4|#YK(ȭ_tdM-ݼpTGtFJ;-qU5Ιif .g_Fu3S^qN{g^V꜊҂cӭcz%71h@o[S),Fgpm|fϞ2ihu7\bd+Hs:CS#iЮ"1,<2C|enZ:II˔vWsMPr0yvڴѷ~1>ET9C2yϐ1Y?jN7UZ oơk'鱦*lԖ4J'Q9D{3ahZ'AiAY*$_~mJ]/nlW4,inA:υ&zQzy$z Bڷ0y# ꥾KCB3j 5¾ug]7 J3&ڂ dAh}{fNFC-kD+ V;-F+ءTW\S5 _}MDB()+:2O@W ='*Zi8@JDB ^~K&QrziovYjEJ\bŶ2#EaV@5sZK1 uC } `=4n!=$9ovKM@N>ú9VKA?6}kBƺDndnuu!-Zs~Y'ik~嶙rJxq^UяLb1kmQV#\)#%rM 6trhwSz~7i3yף[ܹcmҶc3j)I4Lzb`ea hR93TU-mkI+/JR.qVtG+tLBiVv{Kh=i%Zk(_TX(:##=/[*1< mwt2 !ģm,="m0 Z,)tzKq!8\-d\>Y'r *|'_QX׮%54Eo˺-VsPv8+Dbb*}mV%&^,WJ3EBE5sU8~!2&wS)ѻWw>kC@r@ZOwvwf]_BJJ?6rRM.  ;CV\KMn8yC(* 8*^ʁꀓ 4N<9YWk9 7i+YtɦT}MCkZ{n\vO;4_%eN=^J0 ^L0gu}-I pfb}]E޺DiUѠe6|輾*I18 G XC1s2@Q^U֦5{II]Vxr R,3Ԩ4Y, vYFkq5(qeD{7/(ɡ }UCP9Hޮj({=~~yda}eaw}_guvC.Np]>DAPO 鹍Y03d޼@Bu^ްo`|AZahx0HG"WDƐ6GiE}kUp}X8pmQOUwuq}chs~hkj g_=坐Jicp^bӴ158=fKX+Rs ,fahX5S"~e"v9b:E1ݓ_[cr9sje2";o^3?:̵#&^P\,Ju9+ 6}u'+4ݝN55eiHl߼XT~zQ~isEVժ&kymdDs O[{6)+VGX&RrOF5AbNk7:dּRYd(Q o}#]~ʴF839Qa 7qS]6o 6*e Z2heշ<7n?efwO]%vtZiPmnU[ !8iu8Έ}cЛ3^$93Ң*ޥ(Ҽu~QY$lKg+wUTޚ2)hMJB.iNO`cAJ*VO]Kjsk]3\m6[f'nrO$eu5qTj l%|k=v^ ^Bd_8?*fׁ32<:۾&z[A̼)*ju#/^HKJhsz'{Qu)`2YܕLiY',խ4v}jU _[[8ޞʷz(U9-&8*6f-% hgC"tavW7FN^i]1X_VyIhص*ZDy((ɉ5}&YiEDQUԸʠ ݷk`oJ5f`rTOKzU Re6=l'KAmx?@ϮpN}vڠb~ꪶ@88Ҹ SvMXZk7I9:%HTfd^~ZSYHԺBٵs{=mݾT;ejnbn$pVe34p񾞟4?;:ڜN$pSEԴ" GcC^eٵvg^wxZ25RaM!2D7> jʣ+bm޷ffoi/k*CClvY UH?exTzhw>97%>GX'#M;~{ wz=έ[>j͍7QRohEMA5vZ -NK8֟fB뜧Z}m Ml=spO@>jcFJݡ`H^/q^U,uoT+ UL" HJHZ@w*\*dFgjo@Җ >$e9~jon>x|,9(KY%!mƢ;naD/ݞ jZ,%P#,*47[ކ*eLSi 5㷶hMr)|}YJ"3]++(ON:"ɡblEv-烢3[-Vگfs%hcӁ_,(ی^"Bt ZC E]ܗhKZRS z~P3=ͱul/kn擿zy%0GUd֚6)RPm+߁upA7kf"P{4 Xl{{NL>ˈeԒT3Yկ?7>m_`bQ }dcöHJ6e%J5+˓PMO=`ڠs6+-bӗvߒ'~ qu%!Zm%6!iRK>;vj4ss5lIF\Odyj7'Ў݉D(Ų0JzwcY? 8h2:WZ;Nl2yoii(LR;k߹vt;'|q H9ׄ?3#UGp.klr`96Ο+eN2%Di$;z=Gu? ޹HЉ#GO`2_'$l[8&?t"?+Eܠ*(sTSf Ь\f8i+ċ5MM5 4U*M2d*ah7f6?u3\|*a*~E8ׅBo W>%^u*P pbD*{19P+,5h)b>J[[F0{ ={z~tcjMgO͝{njWѕOqV[̥4#DvA"Mvn:~æ'Ԫ/( 2SrE;\us /ugčȿT%z~=ST<>.Χo7)[E }39ɹ؉,~ X^f^!;Tj|Y+ +:Z3' .yF[F✌"CXvϩWT2Ioa@r*!?a_pvO3z:\aĩJkU[UXTS_%Y𹥗N:jMEOk](T~h ,?XiZu(Ö*O5v/R05?6`Ƒ( %H%z:Аg B<=-n_O~KC9AYυaŌ^H7}Ϟ#Qtz;'4YiEzNA #ر8VckƼ^4i+Ԫm΢@3y)BF>$ᡙa5B?Nzu^?K ۦ@ǟQr|xt74" }jpǰ>A?VQYJY]|s|~PlrBnCsj_IERy0T@*X*5dR~  3$dFaw >34*j--#s=㯾 vd]5[ L !?v rBCu?*o(%D"hl[XN1!5_R9pA:#5H;Tu<P((/%jORl YeFctޝ?phAW7S`2/Cy<TIB;G ,WNJrz݄ULcir礃@mr;/˒ NMY%<庭Mnթ ^.yTe8# ' 5XTYi HNXƫ]==yM >~sa,-Mfv!];HR,J߷g'88Et/>%1"~#= ǙY1TReHyr}Yvucjq*'!B[fͯ/56)Tܐ[ͳMCxp:$j #ץH̃ x^ 8&+. 7G7 Wԗm&B:^vmj{]u}u:8&5κϥ!l2,!6ʗ&ʺ_guٱwfh#ؽطIdlִhm={*+pYOՇpNg^yM1xbǢwc9oW8})].8t ,,oVsW@t;+,HH,>_ 2(bE4?3AiQIA8/d3K -%=l; UnzbmqjbM%L%7IZZ!*jJ'nPVzdMUׯ&k )tj>{_ь4f*?3 mIǟ-v^a.0P7eY}Քu.N$V) =^;7bbʙ]f)~VjS'kk[[-.ߺykGvsVQ9WGm؅oD/eN ¶UԈhKĶg=ҞK{ҽJ::?s=.G<FϾ7OǨ~Sjc\2>&߿x;ٶzྀ>SlǠ7ػUTI+c,%;e!5JhM?24 :#X߱Xh {TDzCMo~rtMм0hZ?D|0\ڞUD% N \>̖jqjfkSVf'?.H䤗sU1W)Vy9`[%˫d8RRn%)bD1MN͐mru-X1 „= ʋk3a'OËB9ġ Q zi(B傇*-y߻hHn3Ar5xQ;sf>^~36?0IclQe݃xfh+27=b;6c!D4R/BDx/$_~FZ|] '{d |qt NDVw*l:t4iPլ ׹~\,edW7Up%-{j]ޭ[ݞ5iaƐoȳ& ˄r^촞`WD峋PVLc?sh߽,3R:mw1IqoRj&/5 y^?7ۤ|Y_Sg=/GGoq ٤iiRې4zj?=^Ϣ;2)&pOB_ӗK0IL1z ɉYI) T']Z-ۦZ VScQ>/])J/1QÚ{FA]k4]ʱ̴{ӪWʂ)(ٰ 3[Z᚝þ}By~lQf fLn?. 9TAz4CflݟV&e.鈺dEChuHk,)(Oj_5B^*Sf}ö zޱP60x}7-U=P qf]3Gp^ -$yXA4d_G/+jFC1O 7=VmM)i`hs3 ޹#;oPu^W5}3sgܢJ+5'n8B>¸Pp;P>oCPk|`<"ᆪ}ď`Y>Dd 2B^ >i 39hDO/a{Kj#@&bcG|IdHOKt˗Кq*})O{pf}u"/[KSe1$:A [ gN*tX"$`,o8l5 da`犷LFn!BDP~S d!XJ/n8`bV#!K8n7`"zj hu3~bɁ;vDhVqK8^ָE`_#'Zƺ@7 h3Wxi1 #˚Q<+_'&;〈vQ\E\~rp1m |^T7.] IFp;g y2Hs3?0-J^?X^LD( p A⏉t{~.s@?loėOίan2pT&eeEK->Ec-ypwƕqy?q{ۊi7=|ߗibt9כǢi*!q/htGj>kDc= 8D}G<%"1٨}BOWkFm& JesKKs?1NX]Mxg6r~H> ⺞/%/*`sW':}lDH@( @j=@oRxЛJ&OM=nrdC]/j:r(Թ 7nE$vTmP)s>C-Nɏ! .+W:9rz.My|5dDVNg)U0{8 ]C4-:!mۈOGT=ΡJ`~$.;7++~s9eNCk}F'/̺/dn;@_",1{Ui6Pɟ?-/-k^ŮS b kim> 8= џ oV( 93K ddwoYt^~|A(=fKKIaR *; fWJ~y6rrF2|c7CL[}t xlص<CRBɲ`4Rf9NQ\y$x$ '(x*Vb`e*1߁g9@> |cG"/>ɹHI ,GsrWwZN`)>EKУp$! E>YI{ hqy^yl$'r~-Ob{q-0}4>)#d ˆEc7!FDR"cq[~ w.x{[eNx2F|MPd1r0RwF=#}c%3ᜡ0އ"ch0g՟R_GhH}a\e@\T}Dlbxft?)9Eb,spdSHt}GB6cMZ"DZ2P*62\l@rԶDj7BGfl)-ooe* khyolGKE-?[fZ3"%'ElAa[ҟ#wzݕ.;Ƨw{!<Ew;mKE%rcBoVVaϏo'0 8x7pN %P13r5> ;Nq9x9z' %|d6="]EV%BC-Ĺ<ʃ8\^_މ1/pwb9>=m^{}{Uel˵{W{r(9e4H5rV9~' 3~X(boe|fŕS(qN9BrE^/N&6f| ]5/?gGVPi3 @xQ[!}އv[{[`1^ٛ+ sӀiuS! F`+';&|CH[dl`7eRXi?iy ~$EcBi{q7yXI!78ⰲH[ őx 1^;&8/)G}xr6M$e._Cx*4:"p1M`Y1D#gc'qY"OT(Nz|).X|?T+sɜ}EՠOhy2+g#>bQk^"= V\NsIȚ-a 7]? 5\a&*FWGT7_| u =F?>7EΩk!2pwqJ!)-uE:!=6l{ﻡvYDyNH==x-sHgrFD\&2>E?Kso/2cq EZ)}>Cps.L*l+D6db$8#>GӃ#nQ3t-!ҭWXM挦k4\vLoퟒY 횢|E-/5i?9P/RQ Ė7ۜK? yY(-2QP5UY_M]\~ KmTUi"1C,s N]˖ 5nsOE|arFzynJ32r}ͱXO];ʫ~%G׽>3f;-=,| aLtcAo #qY >kd*i*Ok^ګԬXz BJy9tJ&S_rABKU^sԋmެԔ(vPqԆ3`)KM1?9ƘlgbPҼ˷օcA"wA5Ok˞ݡ:˷`EB빓wv|pb\Q|?3Ĵ"(Ecl(ʾ1Eh6t~ mČ?zU1/%vw63>#A5[R¸P߃ϭ5e <@dH]^i<<3S/9nq+40nvyw;7DDҪV?5 RmT|vܙ;qdm n13TB0|0U ^5)t ynq]!a_! [ ȉ8nm(> (Fq")s% +kqi0j>p' .|{so8*q#uHE"Goi^NVοϯD0ms{d&8m>FtkT61q8BJN\C )@G|=J2s -[#gȞ; /DCǎIs1ʯ esM2eUxpHS4zh9k@%; wea9(2JIVЗˉ+_c>X0q xͨ L/P>%N<.0Kv` ?@ *8<[<XD'w@/0I<*U|Ko h͇ ?ŻF)*.516C"UK:J{$8 -hxX^0wʇJMc;l/dWĔ$sC1M0w.ERlXA#ʦ/)!-[/ym쿉ˇP?+W18Fbh *0UJ/.K&6 KliO0𱥄I3e&)"l1m쟲aqaqQKcD/sG,8|/> Ǩ8ѱ(D;c&ަAI샴c,G U.JY\Q$/-q8\Q<)pXZ(G 2mg)\P %ijOׁͬγcED~*?]u$.Fbߎjwgltld ֭'| %#BQ~ʣ [ ,k?"?xlO?ܓ,O|x@zS=cO#|gcaCyoKG󂨻L߀\dP?:eKãt6S>;zch'dT)L{aOcLФб/tTc,It{ (cb%YpL :3N&v-n@8Hg\,$ t,Dc =}gmaˑ|o^O\,ཀϱﴍs8#.[]-)nΰ[S!YTt= ÙX1DeyF C!%R33Џ_{a[wXtd!̀)g5iK秇7wo?΅g*n쨐]kW\{w 5 έbdt/Xs0|f~ݛ0Ě7gv ΁WHxekgV]+we7* ZN\j6j#J LG(0v|B*eטM'LQpߐ3jib50tZf*l; rrI@"]%@L,a C?2[&JĚu4>j %, [.*hKb(q`uý^]E[]ذ.⬍0.K(̀ IKdֳL6aMKX׽IXOc,lHذ(|<&e!pdP u[}3>6 Tk3_ "%|n ?am?mKe3NPLgETς jf/th6Df ia!mu2[xkld jb:8ãˠs3eߥ4< dHcn"kXs̙{,}xЬ(fLQ,'֏cE55{`D|AҨ1|Ecֻ6]p;@ZnGol]gbQ +WG\X1uxSc/-& n"5[BԷŽ_&'/\hoY %eDiJө- PC(GJ, c[ V#DCw "Xqp8{ċjv q( ML ~>q#rw8?ĭ`8cJ`-<\2q0o~LhH\]?@~fP@tf6!^wZ- 戃[+,E< @_F>Z L;aɨ[ab|?pIРłxriGaN fq &_'ϢD`LFE#?;S=\ڴ \pvJ gpz&  Λ۠LV2AhฉNpd~V'3yu2нocʙo9_!egEr3𗿐 h8L~NX:~4z'pۉJ2G*xfI#RbpOPc/~\ ~%c7r<`{+?#l` M9'/3v^O Ã$`y5GMQEԠI>!"-H0D~gK>˟Sьˡ [oz? }S?qcR%rD142៙ |FQр˶O+/=$f:**F V*pja,mVP^nPcƁ*./4aa#0~`:י#_\P)4е 5z/>{ sX fQI> k0DhBàSV$4h|衇BǏgpՁ}8GG3 7LѬ -@Cu0gp\ q}Gy<prhPSj5%ƯRRA` -,,ObK5SA׫<i ot$qJ( D@|*k K>½o o<ɹ0r ر^&r,-?$n|{/-?J03=ac&iy ,Nly?ZBx\>CI3%C#2]ĴO3 r:@S 3op lI\~ Y; ;a)j)g;(wfeU-reٖ{,˶\^b;{OH\ Z-B:8zPC BW̛ժ{o޼yfvvOC_6<(/zf$ɚ|d`YTǷ-ޝHzϹ ډ¤yAHQċ~GOUȫ(1~9.@,YC$OXԭώ vw7)4DEe!I}}0ZzqfZZ,9s4]V-hq:{YN3+龿cAm3.ͨ/om"/ q=.ΡB_A-+lhRvTMACvT@(ɅP={|4V8:g}|t,]'$~rn(>e=u\yLX%MVɟ /ByԨA%//\Qx>l׭[WZjE.=sct6[iwNkYk׭ מa錊i .o?v񍽼. ;EW7IKK ]$mC2fVOw1;n5&~_+Ź7=gBy { }'^1.m<6*ݸ|CC9}NY+ QiQΜrcH] Ų\ W荲ֱkrTᡱ6‘1t]ގ@H^v0J=hp&wEW6?YHuMQxMOԌtwCͼkWyIa 9´dI%yٶ gOdפ\+ effSmEDcUN_- }0*m&Q4J͂s)fQ}:FS]1j*7"䠽Y!_xslu0GsPr&.kHv .=FL,ELGYG2:EA^ymzòCVH-4;Ţío^[6NVvL/f9$*5Qqj@TuNU%VC59|܉10'G17-ZZ 0fP4;p"oLӚ:hzZDS.kk]f~K)?s`И(3=Mqܻq͛z&9ow?Q1QeLms*7o^iޮ<])!j<7X|Ua&mZYzOFOgxV$oY+?HBȷTfMn&0O7%"t[hO_ϕ`wzn"v%L dVp,ވQ 15T8H#२3hKEͧ@&-8itwA(F7ȷO|m9l ֪߸7ms/ۆv_6lVd/U4͘T17Hڹ|/4 *(!;qQyR{sQZ;+Ȝ{G dj"$E^Eއw{%c Jr^l2mX: &22,#< 1>;et1Dx Go+7:;r"2H-nU >m(@'o9OCARw J3׋Q.9^/w c_@3[wIfv$W-eVÊ/s-qn L:>(I7QR (>/[ 4[?a-Š_v'戻3`r']GGPey!z&Z때arfVa"7ȃ!36$#%5 .׭$YNJoLg[F0 ,xٔqiwpw~ڸ)ڈ2P\twap|]wGBF '̐IoIk}fm:fQVf(3Z;CUa{7p޼yT860;~1mTʥw*5˾Tx]kA>]*[4\:O\OƔM,^؛q8/n>ŞRE>YҞHXϥ^ bDXD_|}VV*[@_O4Ξm )3P@Aץ.^eTN.(ZS)>/ޫKаaE#/^Y_(,?ۼm&pUglja"gՀRWC\E—,% jr>i;ˬNIKⲲybΨb/{;EFCQQ=o5ǂh|05ыZ(bJW;_|\f8S}28:Jf&GJ\"X 5<[2(uz(Z*̜7jFKM+7 E@$$_/ 7swY34N\)W+/ye*d5U~帤r~ӱkάdXP㤠njYL峍0.hs9xq͙',΢u(f5kKRR-Pܯ ʷn_7_=މ֌*(GtAͣ$ JJ69\}XǼe4e˽Itd<jqP9Vxoix/H {ngBx˵EZE+I?4?8ȿOB Nz!As>$lw… 6>QOOF7233;)};m̕o|yǎ:a8U@ޗ?NO5KjЧ{n!1XPAfQoz|xt,/Uc._ }o QYy~GUuweRz|ڷ뉁vM 暨},e$:4VWNHQ LC]1_FatnSjO5? B*ְe'ԗi)LRE|׏rS~ v~]qS[/{dňqͯ>B]l{7DHHQ\V۠+e\%_ 'ByOCكLk{exy{{fN)4>FaW5DJo9up@C\Z([P %- /o1.{WG.]!7yT%o6>UGuXص?]c$8y8lI~ )%*x;S¼K/S&4wri"j;G) [[TF@@`.KUÊ%srRƧL1WPJfYRo#baȕy`G KB{][V ra')+l!>Ffri4NMl9d!CJp΢/^%%eIcrЅ߫MhC'HvX8EKa&C}p簘y,(Ge-=,i`=LyUSUvж[xTxQ|Vh!"\UI6%/m\>Ě żM0.5"!h)"m&. #s~ku.]*gRAY0W=%! YO-G)5ATıe'-gEougrῢݙ3 '7(G.3O"IK5rib?* áC)li~G*6$~Gm&tWU#% EYEz8ު*b~w{38I_%r>{ 6~SnQOR3ifAg2~z|9'|oc5o12:%to:~ w4a@o z"}N|? }*ބ{l`'!4Qh3V}Į촣3$Oa8Y ,~e!ɹ8mHD,3m]L퇘V_x;\ڋzI\ t:8NûEm[z ~c!ٵ߭ 44B7l( Z8kY8,hӗ&pV$[+rpq%J"傥xxGt ed #B4%//ȰiX3.k(WhӇ/Gu:LWR GpN| M>_N {=q]Eݙ㙂S7[O~>'?%<|+k=F O7vrϝίor x8Q@OŠD [E-y-/g[ {J)=ۑt$nXF8VwcLiEѺHC(7^TcWYܝqϒ˗ܳ]ӨY~|p3ؒo<.xUD9C߼F^NF,L1  hR7[⸲nۋX Ԣ9v=[ξfN-}?"9؇Y_ϱR8J{JLM*\*OwC+: |)z+*;u` ĕ abVgEDY2W(wPe)'ֈ6]=+MkD6Bl]|#\%x x4/,|m#>P # SR*/z '[Oy|܃o_>@ny|BDz/"p~ '>{D|7|.>&{^K/+h/{}N'S"Ɵ"W{^\_$3 ba8idzҊw:r^" Po z("P"QB3z%|q?Gd&}3EO/|H{> v0z\/##} pFMbk&~Lwx8}&\"FkVJ,wTD(Y.71j5wI`9܅rFc[Xn LS1QJQ~-rI{-d clO?lgx.Joz$;C )uS?.yڝѻ?40x^쏏Att 3>^[B! |Ae8^J&Wg@z)Oo&̟P w'ir 7 m]AFrx>inSsC^ W?~X{(>U?_ szJd5A%z|D zPA~ D?5Rz!D]o%zj8ȩ}oN#8;ӂH>$73zҏ_\Kof_Doq/\$f~1Kokܥ*XD_Ht-w9AQaf"e{*RPlT~e ?~CN$i' :,ѓ.߽~"=d> xW̨{Uaȥ1IA3KܓAi?𧇜U@Χ_ XWI'38CDzbgp?PwA`ߏKO)=пG˭UG}Wn 9>HO߹75l~Kܧ*dRVADzҾ/T~ '~w O~ 'xSq ~,w&h}\.  -D}E}H?0ᓄ~&f+=@z@3b}zIn)ģ&]K[bD.KqGDb^ʽ.k9 s y \k52x_.+9|':.)V}%)@IrfCX@MddحwԿyA= 19u=DsڃKQnē4VS%zQ\*GkrM {~10;z>=g}I]_ŵ [ (9=?rgAo_X)Y?布*|oN+cWD=fB7Q{;ܿx~@az,oY`o!%?_i <q^-'$8xKϛb>3{o!S=fszi |c}Y$Gh9 15Ɵ۩Y}3_'ߛn?W7p +g@ X/=Ϟ?*JĞ"rWH,bO] D=RZAr ϳ\s6 fB?$GAL/#ӳFgqi(UDxshϏ26X_G<үz?USk_2"#_FwWq)k   /&+\_Q0.xI?4"}='ὰtzu2Dk)OP|fs`?'-.^x $.2&5yN~ᬞ_@ 8NJ nceJ>`[sGkf _ /d vؿxW~2}%>z{:I#J2DNw.(+'8~`spPg'3skhSa+5D>r?[&2~v1W'RJITOP|9X|OwW`*j@qJ>ɸ) 칉SɅ#ݏoz d}L@P'?yI=i<,\Se{|9b :~qJO)  , E}gqrRCWm,Ny6=v7دs~mC%D?Ɨcb;|>y Kw?E?pw!DK{.;ƣ@O2^W V~ZGN*br<\ cw3)?_ \y'Cj%y7_|"]e |'G )a˗W(@5G)ę>V+e?BE;#pAW'%}D)>-gaY,γ8c%|T~>d2|}Ng2ΞE38>oΣCdȿ8ctո;L╚t)=C_iN8jS!p^̥]Y<ƺ(toP+:-rF9CrL">sJqľcK> cm$Ćo0^3g{F%^뱵jwl/kn@qch(> ` H3Jv$v[vo#zr'b>O~?%x!_~'=~+9_>ÇN*(~.;ORd"yԇI|2~M,:0^H$Y-~ftcd,f&bUݶ}m*+D ۀݦAn>n?RW86Big 67MՋAfvI yg>{#s|fiy^"9YDZoqr~u6/n/e>"8NoXMF8DC؉y"woD$Լ1꘎{I[a1;N}wf(/LIsҏIkP'4FVz-G_ ON-G?Cg+#{?稗}Yk%qU gKbpJFpJ>*_;Rn'.eYY,F$~?eA,@N'ɤ÷QubkgNߤ' $ 練9j}ԩ%%Mz#w> 4vA(wX) >JiB(Vn/8%J@$Q y5膒xMv覹l|E'Q>=,GR5?~OR#*"q?Rسp NҟOѥ#.Ӄ~Άưk1:4C藾q3Z1oC+'],k>@ZX鵙M ;e}kH㌚/@lFg-'It4'"jubZ'.j⫫$SIILh0'F.$>Y5&gGYvY7uC5CC5Y֌Cۼ܁>`:C_1 Rw M꼴?3Y>f'4A(BYdTeh;c@63_=ӐwvƬ_DOD0aݢ,#  e)~ ½HdOH_ XX5=ZV~}w2ʤ{I]Qc2Y)~Oѳf'} g$p9t|L&)]n"K}3J';rV| k֚L&(>JvT|NgL(<9>^ q([xd"1?x'{H6g4r*%3C4BFAKdw\1͠5FėF'I(*̑5),,֒,Y`wQGiaezlB -D56Uk.屯` >*87^Opo$7#EüTcE IZf Cw̿j{6vZ Iz`8pY}LۆO;7D;N?w_LbMׁHtw3GK;1nFaq(򕾎5 Zꅻn.4UG`lo*k^/\Y"նz4P߸vaev0DC|(C4lJϻV:ȟ0QrͩKQ OXaJ#UAi*Q^uB U&i^y.;2faAd+dOb=܇܇h>1>cP#-[XL:о#cn>I'z;\)6.rl3'"3]!6IlGhR@VH\3F(59F#}Y:xRl@cj"j&|p`ɔJf_tt_"Jν2‹Kghz; k.jlB9u},ҢR&,޷x]~_cq'b 5gU&ǩ c{R+[S_ZVTƤx» & \\,q*^-39B+ue(pyek}X1X*]媝eiNnyYN~)G;F롆!dWg$L?W --$Fh$EBjk=}|}#kSb&{*P `eLC[#cB7X, 2OVX)˰Fk1̯Ybxl}[42Yu$%c#aɶٱUO~R'ʩͷ ʩPgh%ҩgp4F'^^:gagQ;ys?Q骧6wevũF^Nh* [.~9+|#W2,'PL2CfQħGk/I *g6DLWf-)࢛.wyc|ۻΠr E$g]1yU&fxފD眬%/G[YzC*,DmN s|8*lWFgТ7 s*;Ϸ8*JnoX6!CGmARW?G$F9smi* ֖RMaWˆH)ZF'I+eՐBfI$1n|FgKSIQZp_h]KzykX8H}\>Wĕ:'ji1.DLYOLgNc$CbȾ!04>vUE*MYVhD[ q*Zdt9`&$8U,wv2z4X8cbd)jQp`RS]$C UZ'# Q)ag<yB9id|yxaI{;Zz:vFvvպZ_,oLk)lٔN^Es&Ι?źwk [ܑ:69YYv8iU1-YcVLfiT[jU㜈KgOKw4G&%PZ'n}SnseaBMK Iq+'47g'Ι2F,6d Owb7z`!C[x=SΩ-(kp}~M ͆淡<&\/xs<# c79 Nz%~.tm_2}L lGxJOOzJC S=ϫڨHIS5ufI|:;g5# p}*6ճֹ#j-YPz0h͈!6G 'l 5Vu{ O$/L+qZ:vPa2۩[J—gwWk.~ʅ¿J#yvOuOFj)So"7`;hF].㰗ב}N$c&&1C=i%Gzqkh8g")W;ʴzۖ_]m.ζFۓ*+[fOՙ暸DzgcRL8836Dj5H4$C\!ZSNywkƮ6{,Cs2j\UyjƪJS;qm؎ġ`0BtP}䟐>osK1yX!|4SO:9~iV:8y7;4}Xg'hg)#4$RG8x$?mxf:G*GM#{Ct asW  c _N8H[]Ua^}\Ճ,LI+(LMIy<! ]Y0 9MvI N1V[͕ s.OvCxXJUw*Iw̫#" v=RCr[p:~؞!'<1…䓮nCpȽw= #"G|b~͝xSG&;B1f>-Eyo2L SAtGߡ6;ɯ aga#E SS/޷o+4)6E9=1o>eeN??o<3$f8Ib.q0)Z4iT^9ޒVcԤY͙yB$ Km*EEsgûfbbFۅZZ*ځ=#y0dA#9]#NQy&Nʞw$ oz4v x6+t-^`~%lf~E>o|/-3ې*<ن^k?9=_ 9\3DzXڵrM)#1FjE!Զz'a >'%ҿ׎Gyo0֌|!|kE$W7Zi|@^cvz{خq*(ol)4 ["*&JoMyH[ʸn{za=[MtaІ3;Liȝ,lQKEFYLJoFvV6VOhV$:,1e0G80*HחS2RK&hf\gA]k K4fW$GnӍյQbŚ   |iAIn '] YM 6s_mAl:,-RZ+7RR mRKlRl'}g{S8)I<٣ٺ]F dƚEW_|,S<ɧTO=T ¼LZXɫ 1Iw5+5Ḱe5Au);2gVDCj{k618H-fϷsH% l ^pZKMXXV3JQA:Oo#5!us:Y8X!;V1{w3TbKJQKTaT0[ GԖwp>| ԃ[赏,ٳz@:lsitOtmh-)n])l&:i9j2XZj[wEl3vۑy+OϮ%>z9\G͞Up 34Ľx1yGnvz}6!ZvvXXE`~aD_k*¢_=vyS~!ir܃_=Z4ш}C5j:+N|f+0MUI"VJ  Qk0e[JB"1ySaIrj,qLszvRZEbPGFOљcˌJiRJ }0ʷ%E& TTh]<\ 0&X3LƄ̨ȐXӓbJ秄OL4M6kQMIx"hg5t+'zֆ ^S||JGKϜ2uҕQ[9ɯ+um^w8iNLNd6 14]5BbI&ݑtB:^X}:i9  me қi[dLILԦ ݉y]hY^Z_[ו;~NrnxM4kSAS-z>&ˑ80#}Q[PΣĴ2svdhҸҴl]ڊ$}=+fJU:>HLC1Kh{y~FwȘRHLC lP$Iym(w4"Ź52 2DťXHbnC̍ם|Dk̭JX`)4:+kM`kz!dl{TlEl01OY|So*.XybW琻=4q'};:g +2[%YufzRQ)dB!|ȣ{g¹+GH{?d,p<ȠGOlA.o~$; eE8=O_NtXR F|g;lK-lH,^WPSPRcӭ/4StBѤ>uEqMYC3S%E ~(\Q;T1jfO% baILavOW>+&_*\Fk>}泷SW'2gxM#q9z<0 #DgG1rbtۙElcfx½ŔeAt[L U Doq=+ -)iDSz{5נ Jݛ^u$q>#S!5҄)ΛH>MDbÒFm4AZ' FŘRCC2ćxNiY(/6љKHZ̫"nHPQ{KŠ vLք\zӢ/H3.%KSSRfWUv{-BRB<E*8- OPoM詬&:1daN>nV%i mfTghC’RoUE<1`ݤ2Uz*Dߔז[\=85MDl:"<*Rb=76@zMz`= r5֪lȄ&8Ux67̖Si1hY=P9kPUY8܏2V-󓊚{%rk3sz _MQu-+guuQy>hvW.NVT]vk)Â=ճo!HWB[&X!b$vp+=㩤skVٰ"5hwLꮎ**.!M'V?nhrB"=ş8]Ct47׆T(b~\9y.{ |n^>t+ۉ tP{DNUc$D*w9z5{%ȉ~.C{`LsR :.ZGdv+n@FFWZa@O_v}-|(9"{7ud Ud*"ےeIn-6`P)$!@ZBH %uI#$6ewHM6ɒFf]}3sm}}ߖt93gΜ9sL;E_q 8gaZUJz|~LI*)lvb=5 A :-^pvʦrArSE_eV`{k.rٔfFQf8sWf6'emڼBUY)PWnim@RYZ`8zGm]Z4̚.34ǘSd956kYBLZwϾ(kұRunjJk5S_f@:u {:5o~ +մ @/1 k/>H@XEvcەwz 6(0(II@:l=yeyԪoVom~Wz۫.JB)V7RQR3-Ia$dqɓ Կ1zz;kzX+E()P[Cl";{ Gwx-Z-Kdڤ=Q=̠&.ͶWΓͅ9rCz漏TdMvYyMbv&Oԋts]~ NDrrGRڛn0C9BxPD]\Dx$W!#0+͜j̔˜yT#Nc;zO[dRi$$"z[Gю*%t+2V,z$ ZG D!cc5kR B Mev^FB&ъA"VT6BSl{vqin}kSN)vll>5/Js-vL0a۬]~VCAazIJb6˗:X$wYKꋧ4ýT9;+wg,>ʖS2Y¿*̿UKD0^Ymy~ax.}-:+>֭[12>~=#]mBflR%i NxFjE_I R Ci% eN=$2/iK鏕nsK -\~w -!4w2 lʼn5?ly970!p>p>)}. %&|V bp^dEp]Ǣa~[6T:sB@4<`jN-/m07 M:r^CpRa)g?HTq@WKτG%zBt 6-~YBF?Bbx7 hH3]MfGm ]CuyMM1|-Tvxy#kz:Zoy]s8.o_-cؚGRߣ>t Cl!ݧ7#p0,BY)4-HsZv͍|KZڈHK!|I쑐Ss51XIxO~.Ϫ #9 Ke*fb>f /}g?Oؿ?o~Dp@KxY l ML`0^51cL=|}ӛlF@ڀ/>z4:jY?aBcH zGO;vh4 c:Y;"u@K4&IFZѣC 0öώ?H=]%(PBϛE5쥼_ܦ*!FGB %Jz"RJbc:1zs5Be Khޮ`AGDjtCOOhq7eR{)y߸ǎKWQЕA ?_e'k B$u"2P ц*PUV’hVnik*uiM);}ve}iֺl9]>h1F[*?HiO#]E 3G2ᳫ+}QQ~>Cd[RG ۙ@H4p|U0QUΟB/]]'q3M]qG 7#%aU䟎~~nI`?tt}مZ u;6Aϭ[_$əP~Ok+6>thQ`n{5mn@/^[߸ޜ7{'Z>뚽!63t%a56 ]t9':3X|:=½?67D]p}t~df~oqռޜpY~#{wN;֠{9km@B<g_\otvtYIVl|w֭}KnrcIaO#1'rN{㴻_|Xy7x|xH>=B2Vj4VhV]u$aK+o]ږo\IUd7yóXaLlBYZ -K8!zF˔GOTg.H]2Ke[ڤ&,{gLue- v1zhŨgFAMMHk/!]HaZ ޡZmO6۞+-+g/21w%^"{p8N!swfZ]@J?ZYa$w73t FLn㮜+UL2q2PxJC f9jA3P~,ES9Ͼx8g7|#0y<a[#MS ; ,oۿEȍa =w|M`ـ_cMm7JmpS#ſ/!yIçvARO'{Ϯy);O뇵q[h;d֢ 5z*׸>A0ULDv(.l1;,eF(7SjdyGXrfjF+iZ2#(1 2oUb~)ZsHqĂ Dt2+3-K('ŜgkU*QYIXʮvVS)zE4A|1[QzzLgIv>Z&NjhoX[7jk}n_eJAT;pleg%7@pەh"m4qzĕ.{>Nk4X|}oso8\XLZ:-Ϛq9W6}vڞSqa9߱D|=J%jkMY)GI3ZtlPL+u-v'5ct=Ozℏ WUL}~Ԩdzc^!J.S4 뫪eb ?kŖ[9{_gpu2wFi(_;Ǜh'Nl+bU6d(]a ʧԕܤK[I=81mi(]mxT-Uh- :kbE13W,$_Wó>Zy B%QvM3|Y ʚ#LW1ԗo"!|13颼DPO=0*ƒ) ^Eې  Igyp(Vf /p1w::jeJ/KQer2&e2 ge=7&Q@1&mr"3ؓJhUteCm,&L\BnipaV}ywAQy۽{}oW붧 lތ+nժ,}yھvO+N؁Ȅ+k x!; v?bz{큅 d!;urգXJcb %:*>ŞR p-X-ј 8gr6 -AhZ7Obiߜ D4*/*&< PTi1xWʲ9Q*hRW*lhdh]@>63  )ԟNJΧO둴l s}jcفWݼ9˷ [28e{D'z{Դ̿/Vǭk)=MX4aLø$~i1GdҔS^dO c>X7fZYgݽ;9}8a5Q Ts J Dq6m_e_6/x|>`-(\gԏ-2xIsS(+ 7G?>^~<ڏmCrqdޖ_=Kg_: ξKx}#m`6Nڀ`p`sIq4E0%qۡЩ 2EVz힑^OE嚲yY4?q';ZŒ T<?5pȤDMLp6OX:sۋ]>99ly39ݩ5nDL&as6{Bܜx36evɅ[sVu~L >=kVK8(X37xDfn{o+ٺn[CzE =dN b1z1xb{7> w&_ra*_V^ܽ1)1;50ާH [qOýᯱ>N^Ed2V?}zp2uHݞٞ1҇v 9u'n 碧\݇KFOf)v:W<'SO0B`l<0ZuQv(O[#/M. |fVouf'$h -L  mD| '9I #{6 [~VF!Vw5PP97t`N=(hqyYW kaԄpoD;86xmE x_=m> p: *z2Ҡ͐?tH!k [QhQ>ʧs?4N$ލ"%[ׅuy~^VV#FupJ~H[kӈRC 8.Ce[|c̨m'#܏{~#m#un #{ȼIt+nd=fzagdCIdo |:n6|=q6t AϡoOH:k =7rw#z}َmSl@/FI|6G,k]Lv " 2C60 a7OkaNX,2}z*~~ss$-6GgW7<E'.>GE3?@Z33kljQr'0`m`, FXNFp:3?ӘX]ߞ_X~XS^#--0S# >*[\3D\۔?MNzmS87:_bw~z@h! )ߤQaf}bwS'c:N 'SY<B}na7^NFIVeaM4͌YA?I?3B$&EU3^h%m:o_b属f'3'2UP`uVU~Z++Sp/W WӹtE#U&Uѵ[ "ӛj_gڮ*Vu%ɳӮE̥֒,]Kҹ4.t>=kLw>D4l7iQUֵ1UӞ?>mU [ו5cx8̌S>x#Q|zeҡsBÈuJ#CD,çKL){=`Om?8{ &o4t7EӰ]|≃Ce,ps20xH%4^5'hZo9uo$EJ$Ρ/i<7| X&%Z|NP6< 7 l9ha.gex͜+{%/p 3BJOfffb /fn<5p)03|Cd^5^E 'fPx%$_bT /[x!h0&9(Y3 {%8̋^ !} G&C AbZ˸$?1&{SxvZ $ޫ G_0^R0".πīߙ34 869;Azqj@0x17yt o+*у~/|o! fZP|b -(}rĊ ¿a{S+ȵ*!$cf*6\1irq37*WS0|!M} EDe& =kqg 7ܭG˅(<k_1|ZDGXJ.,x\ޓBL%|cPHA,1'Dgk/Y,ĩFxC qU祣\ S :_].=,y%^f'z=ElFO28?яlɦ{mANFanfj/?ewƭmWPW3 ͷ{㮷޳i79ܖ럌'*j'R#g} RHu K[@ǰ|Dj{f*E=x=nivGW$Qw4Tki(#Jut:OX_,jAg\\f'waVl3&^UwDIȵKmopY5vd;Y(Iͯ; :4ˠХ"gj""wd,b؋[~=!v\7 }9VyK8Y.R܆a}[ 6GzR&-<4꼲dVa4.fcW\w2T+SGuGwu֜Y&%Et]t -񹝻]\=(HCZVz%b_/ $Iud'1ȹuM~ ?B"`j & OئaЃi9ǮpudMsc;,ĥpG)41n$ ŕRp A`E!k(gɕ&.A hXƗ@-h a|="ߑH8,$:(^x0F߆qҮ0E`,t _]bâm&ڦ}BCEEq/ 6@e 5t%)%⟸ɼ>0K@"EҜ%nRɌx08c*sa/XneQO HQuU@(9t:LCaC` !G~bۣy_&4xG͟A8Q>~0u$,$j% `뀬`Yx>գR#)-yAh4:n)`Z]AΗ48."^u^}D sWP *´ 7/ :FU|IW:&|/kU`X4]m(q~x +뇏 aaETH?{xORz%Nu8"g'5di"$OIҔnZ/ݗV9!p_]FUEaiX.y _O- N"C$(MK" Uqij݀z3{h2!{wpK%7h-M\rG H!3ē=Gy\pJ|=1Ð-ݙK(6?6XV,04CKCaS mت8*xí)_ _cG.b?'1t.:ȭe1L=33L73Lf3bf9Yl`63W31ۙ=>vN.>\03O31/2b=.e[0~egB1goW"3G.ȼżͼ;k;/̿0  `;CPaC't8a:̆*X `3\ eoP>nCh3ٲ]PL!ST0̴2#f<3d2 %f=g2yyyyyyyjb[v3a~ߎÞBWOĽBM?$}!POѝ10v~ΏȘ#6oE(y;&FC!ζDCl_rR>}ȩp VU|&'_pPMЄ4`>"cɃ N CIo(4kȎ7ƺ6t7u4.и)V~DɞVu&)9SR/-nxjݭB_)iuQz6K^-Qͦe'SJZ&sVlkwZ S3&Aije fZ^/<-Bn9S?qPD˸V,oCwkq n[n!$ժy8z$L̨Tz&,1Qq'e: 41-Ldz=3u-`>]Jb]nO!*i.H R!/|eೣslWLǥOY]39w{ ?>$7,y C6t3eL %ߙÖcX8qYu>o [wIQ͚uV=<>^97vSqYC/lV kn+$ >q!~?̃X;h0WQŃ&e#.u|? e~5.jf};\(;\ 7rp܄TakЃ802>?@ E>0f_) pK|wV0{xCˮG/O [ @E!R-+'p=$g pCϟ[ M1) 4 }r8>GQ1-%2xt9Ond=>  ,Im'~c@t7#= /-]|s]?c ?=}p_ٵPp)7z'ywwݳϤ>ȽD6LYHzxVn+;>x;<f|OO?8+]֯v~''`6pEnSmd;Ch<'ln1HVKďQOҸOt-@ ~eRH*=SqeBh Q2gf22GZ}R%vԐ)2eR\/kg233HNTQɪ&%ELb)T2OR 4T2_)[M+2U*egddZ)ь$?YD/M^3΢Q>3ٸ} 4&M46b'IY^7jrUNNN_nvN9+{3lRfCD<dQn 3½FNdF׸MǹZÈd]O%/OSEPH[c٢%UhǟD+ Tp+|l 7ʑ@X:aWvLkq0ƃGQMc]Oa{S cn9zڇ%pz8!ܰI(9\hˣ%rݔ7X ls 0VF~+_v߷$:?䭺 $imuНdF+P=]ydzN׹<ޣm7긪ߙzǤ&M:0q~n56wmrtmmW_ۤ)H z4k,~_ ۋve}noW8a*.\cD3bX0y5ݼiϾ')n1BߑX?588_e #I|,K$p~| [hk8Z!W;7y\'qٍ+ f+2$nf7ە`D`)wlWx^dy|<6nbT7QSR[|ٜ6昊LmgkAcZƴ:.8 Q,=MS>pBQ 4DlnEt'Zpn7gwQ#v ޅ} xLIrf>>B`ĴĨ+ @w><뫿Ѭ9=r4 ,wLh3<DŽ{wI 9l"ur߂֛/Q?4y|&`yy JЕ:xx]d?YeDJ:8E9GܓtS)33lA[x.esea2sFԉq)m:IPr =11L.ܯA."Hc C_A~g}__&K$l~ HMFCqQ]B!D|nf;c]68r Z_iE쳕uWk6*[A5 xo8螑jAV@OwɜW5FDhz\]0#^%L3';V0xȁurs*WlH;~=G h(/ ʪ,#PV\^sm9pM]:}p'ǪGcFswNh>X"h?;%5,Awub4:q>rT Tl3lrJ>K5jwkAu]Fj2wҤ$xlgMgu>wRu/)CM ުK=Rj oΌC~wZհNOTSGؤBGcڧR=~J݋M)ߩ}Z >8%} ?z&˼|?t*xsT tra;^C.'QpW/2!].q/Kb4HuRՙ#syXѫz:"WȍRA PîBRz ' )G5%ELoէAz*Vln_^h'  8LYiw >zHtvI?7%>iٱ,Pʉ~1 8n9X-d!8Z+.Δsb%N8@ي?#TI;rY1. IJwLMk,suFA 'jp6C+erWk[+HDE``26MRCzmZ^xZDy&Fu hMBqIYu>SؑLͲLIԺfQ4žYZ;F$(Z WiLRI3NeL$dfgJI`Aaա+O)JuߞFydc4w$W̬dVj4hJVKYyHaJ^dBb ϊԭ[Jf欜yc˛R+3j{yhXXnPHE,"5 țT*ʐ#yBf6$%鲓QdbFddqӇr-RK$o&s#D:SNnQv3Svݲeq&Hȵu)i@,-K 0 q(yKQڜ20yTB%Ic:YbuѣKfBIFQlzj@ɊYlo#C&VԌ5bk%jǟlU'D*q~~"I_Ysي@qƘB*WiD*C$Ej-˒Z+ZtaZ"Zܓ&QD֭o(x d {bI:A.o2Ei\Q6IatjOi! wj&aɲ4E$QlHƍ̿?%Ɔ6Fp): %+S6DۘܡO7p>ÇQqy$a^"~gw:qfW_uzɊZ?Vd_Q_DWp&zs9KyK -rtSK+8Rcȓ9?>^u^:BoŻv= C×hxDQk A+p"U@3w(;fB0avqt .ڎ܂+c :{ҙYEk𵠆￟󓿟pu iXƷ̄@Ew:m %Ig8)M'4+c#)qǶn!N0Nɕ%SZGO/+.3 ZC8g x.RSP_j|tf Ơ~-c|4u :L)$A[85|OޡT'#%wy̑M S3(E|Γvd⿗pp-`i:SoG(]pٽ{\Љ 4qǂEe6;<0cuc&h\;{4;ڻ=ea(jƑm dBb +H LhIBf &46BD^PfwlpB{h5Cȹp֩A:ܶH[x;wF:rgБ{>' RGi_3! mW+2=k݃up5c݃ඏ`ܫn A׳0_Qb8)p%/x~ef`^36A)2i^jpuB;ã丼ykWMDfT$.4{7~s?8QgȂf=PIVo\aK'^`\G).J+oWs L7do^s!G/pU5;p QB{IgYpLik^VZ0Ɔ֒&^̯~oq?:W^AW-'"O1˃,(f"YA+WW9^ψ#lEoa&X~dtgt;\} #w]#0O]=|'lXH_*}#xpͥ148jcI:@?1-y ֯Cb]3jvx̅p4./>9>3! u?_WaG+h+>!=}ÑG`Otv'Gl8ӎŴۙ22e0)"ulK-2:b-xzEu׾zʕ%]:T #Lpg8kĘNzqHcwY7)JtH,/e*)Ԕc46H`% @aByGGM6O2' YhȊF!SM|k/IX@5>[k`dp8  Ɨ_~k|9R'ވ=x¦#.CFo[:GEyaGW ν*xwuQH>80a1҆)'ҰTq|YB>Jg Na M;Gn0 ] $GzDh}6x=.П@[8Fe W"A J~?$u`6D`LJ`n>XB«ew-o55kjiblJf.M/4W02 Ih@)A0- OwX*?n{ 5<24|/In'֋kP3Yv:EPqɇ&ya*u627mV3B!Ҽ-PT|_Hcve~qnjFsX;{Eܔ56U2J?ᇔfz^`CI$Rww|7Aæ޴\Kj<[?q-55G9Y^,VJ5r7[WWݙ%%!9dnXEE6j6m%8jli555u+f[fjc?sR+zr>EC<*> tU9;*:U]kyy]׊rVXV>P.7c)Y^Cx~YfăHR+IC*o _Bb=b'#0nV;&S Ϭ Mmp͈-鸟<"諢y^,xvpCh{q\ɖa]~\ 40C=^slfv3|>kNOx_v>C>5Bp4~S9OlR6E?h[X 8k%za,C"8>b/FGQYUP"Y x%x@x ѣ^!$03LϞn\];' hoy2u,9aϞ Ǘ8rW&Eш3~K\ًaV|vߊ}gsg<&Z;Hx_)Mp9G;|v7p48>݄S]hL^>L0S{"$o5 @2ğ<bƵ4w nNa}@wxkpY0kAdEHJoNVp/p=\?ޞ΃#J?k]dtߡ{y!-qֽk*kHK GZDԇ:Pُ7F>YWJwIҺdfØ6aM>MWggƧ o ~<G8$1gXljϯIs؝1d[1̙.7̫/>> {?>(V#M*(}nǵKuCF6F[U^Jߡ.j{8o nm jTu(/B*`i6KG/6zqC|Ձ--.`wҝ=IpR D`s]_[tً"K@Yā`run.xYOt?՟GXG$JI4tv.zv'7j礑=]ƑtPAIh-3G.wzviR?[9?_p_t`@#f gn)86}%L-sz,+Z+ {oUtѫm RZ7O3V1O?/*9(?pA_;(N`qkfE ,RГ}wX3V1yȒXlBwͮχؽCbϱi F4tUX.-5B'84ܤI"vR;Aԙn:2M~[Pz=BO]Rn,so&슎== ܎2/ $fqO) ꃭC1o-5"v8S2Ĝ3F!JQъ\68 ']gvk,Nһg4ZlsfGL#-"=)/g۶ˉe9FW<\^ZA(}2ܰMg$G&EsʐɽqdU5[6T%WvM:دz]gyЗg|D<5c  *lYO}f)Y{8~jA2[S9|azz'6rF*JZ'֕{%g},ecaM n*-<*_ &z$MHA𓧀LuT }ڇyg(^H(@e )>$5ѶCkw4cw='ZmϬ^p+=[p'c0;wV_̥S$;rv9Callhnh@F!l][.$sŚA4肾e,Jr)Q&%$|˝S@_ /'"௓JO H@gޅ;"Pqa\P08ke|uw{y WƠ5XNг:980́g=Dұ\v n𰂧㩡"L㔰Äk}O$F+g YH=0M0s6"Y5?ϙ[oeE!v; wrgyԿ<̓ N6F~ S iq.-7 xirAݸqӏ?='ccmf}GH`R BF`ɚTE fMd#U2Ӡ^瘑t(H b6 u_͙9OM "h^^ f33'(|yݶm6d5 1=zkf;7rz&sYގkP*A(PC<[_d=+Ǟ+91@j׾;v#"q7$ LQ~'-0x!z!.{8lZ+f}da0)` kp^_a\vƞ'~@e5ΐ 2$J%j-+i8E0^p7ߒYfRF3^Gɸ 1g{V_Bn-WC+xۤ@4rz`sאַήYAkV_u$Rw&I=e8.2ݕ[!v|{ ,SAZ~(HgmZTYS"LA*0".}vǡ<~bpPɔ3DqNYpܷ:[ 7HjiC̃ŞԨxpL;r#sAݚqMvm.\&ԕ"KP%jͅ| MHazcD%eC[aE} E "F'0~5X?#y(*B܂5PuwqM&h+P$gek~-,IZ2ʇh+[oenc"oMDF1)-͖GN1/AWG|[@>d|G~.^lȇ|x 5!Μ 7烣GG;j=wazټ*ܽ k}\/>7MG"sb =GgqBDԀRrOqQ6-ݑ<Z=QUI WG*Ǡǹ9CT+S8J )sae`}BK1^*x׍7mbF.垎n3mwtSWcΛnL$q!;~dUzOj@^SZéبכر3lϖsHtl dQO [}oNs*>{:ӲՊlI4iCGΠCm3GFe ;mՕ/]tQ]Ub =!<473pwVxgѯ!򺊥hK|*X9Xr)i/XJ{%k25eMwY啜/{+~_89„V߻lqthk_ NXK:nؼɟa-X'%߇%L\~ĜLuT^zxW/NO&53:8pYv赥αxIWS=4p>ic6񁭼ZT>}7a$H3AkQV8ۙ]!H~zP+nJY:cv9;b}r)la g/@xW)y:|TWׂexN392:E( I@Ϫo?#|p5Xc}Lg NlwiX)t\)c)~n-mƨe,ReC eyx᪠YZ޺nEs q1g)MG-eVrX(R "1mq/*8~P{?x s}!+'Ʊ+xI}lտO;74] y\>FnOw ^vr9LD5G;+ }K^ۗ};AnJ8 mt>?ChOOq)gfub;[{\ױ T+Yh/Bp0*v ϳ >qpX *G lED/̫N%0Dډ:!SŐ0g>ї5f}jgTF0xPq}~Oԙ4r0nUSA y|*\r0 UpZ ó"\ 5y$؇#`HC^ a)T5}蜥)q\O g;D>"nb x i "gY.gGJmL9CY^}1 n*Iq`;FYL VEBFNg'Qũs$fף3VҬ9 ^Dlǘx$N)WXZ}>#9a_cެl[,/f_Hvnϳ!0%]07\y$e?g"Χk jճD C2sR@gF)'g^BX2@{X\ -B%x˄?J9yKlG,yd?:/ddOrI99)܃1M+!vJg-d #s(C=y.BP^sÕzxzEn, ?~Ǽ2 Jf.p j J߽7T׫HޱIxbMЩE9ߐN2@}XBctoȽvz~JiwZJE@ha zk ^ VO7 N&;GoD֙8#.!8{M`F¼8c_!7;,˓.ȶ35RڂZP;S`W/C$.iR$Â="9<1IsClFZm"ŞR8q/wKir:aKyzٽb.P73Iy%\9w kUJ63̂xrAٟ]F*W]|񪝽}yۤ@Fs#)c5E;M9D¾~q4qsʡb0\jvc`~eOt1Oɓ.Zܒ!؂y9 Kf75> \˦;Z)~SSΏ9:G%yC9rCgyJ̖  >Tj<'U"Uh}jV=ѵ|@ i rOaX *K'#^$%yG܌T-L<Д0h8" >?콐?P#9NcSDgU<.MH{mQ7D4e[8wwmES0 P)ƐhjJZmي="WRϸ^#75D*ӱx:3x:['k$1:Uޤ پ sKjYUd FQq\h//FAB\Ҵ_ᨵ{ =j'_UO݇o6}I47xɒpA1@țH|jᓊ8>Ry̕!K0F7cb98|kӷs$λJqL vF~iT V!hiC>v kƼV${7d@oN?11\aGDYǧD2Tt zC9ÀY|;CEHD|I0Ž K|uj|y0jz WɼЀ\Ѕ0xF^"P7G{҇^8*<#q(s;p)͐]諜 U^&.(!K=`{#920OY?ުļCrQ9Q0d7+[i^hCǟ1?c3qa9ߠ/;)Z+(zT@V|S:\DXJ8l6F"  .jk]#ns9?W^7Ǚ fNFhQ:-&Η(=i[LR,ˀ3`'JUL I;}8mD">Dbp7$y*]a/_e~[Pf 0v#PS3hW?IyrM'ݪfUx7<̺1>! lס }."oFLcz0 5ZyќC~2go)@; 6qͻ[#[;qpP "s >Y釗#&:<.yy}M<~. (JZ#@:2n`CӾl^74 N?7ͺhTgƵ4],d~7m]9ǀ1xdc8W R2%yzH BRIqp0>^͛Kv9y?SWܧӯEzSHک::+O&SB*ΗD2 P:Ǹ'7N[*'8[QL,|j^@y(+bAy:c"5@WNag7I[eY_6_3:ݭG:nW2gB#l$+p"T~NlpӤqEhYvv'I9ׅ&%h՗ 7F6s)KÑ2Q|rJ"$%R]FJޔ]'tk ؼ7OIvs~*}}ʺt4[րQC$~!E"wRʫqJ,ĭ 7zvs=B!X!9ܕ S*NAfeݳ*J<|;dZ2- W!}6;dT- %$ J;Q5a18"@}aG)i?[};|Zr40(QNKV<-v.5wxT)~”ge?a[ G(#r*J>qxAl^P1ߑ;" kHs)wS]sӹˇtC^CVgکHcxQ/Fq8Q_<\ ҿDLAOB>ل jx;MڲӘk@]cxk ^q}B~WD kYx-z5Oq~J31;fQyX撜}ºjٖꬌ[p#WxY|^IJS 72 7".ړQճީ]ԨuTW(JB*d mѯV)5ۺ;ffM5zȐ1N[ñ*\.HҙbkFc]@i^=i?xk܍-Í mPqndJSpcD>{ī#q zug:]y fԷug86с;Rif*k~< w:g2g$OSr!8)#YS\3~[ g.r%lj5jj d9d;t笛-[n_N.[jSC<7%?Ō%g E+ 7wt{S*XAcKx+KkF!>hhaOZ6Ǣ5a=GǼxY"žиGwtB7NاԤK ^rO;`s,cY-SU1Hz_/>T0pl2n V6jl1! '!Ӗɒ LCzChL ['mv&'-BLV笫s8 %|_'µgj~?%_pur mZH )o7 q.~ܐfssd8 >͟$.'mey%5@Q %=u"7 ʻG傲'r$H;+! i!&uK&bL97h%<0ls#k.> 女 {~*41G!iyvt#t1,֓aWRp`+@> A/`S=?cegytRa q-,d >v" ~ӌ~0._5SREJŧğ'ഽ;SrUcoQU'{EKO./x9 GgAW|>A;D?PVm3 ,a8? :9Kx_4 W%gi _&iNxkχc8" V6B*-/X_+Il/%0 bvabg%)"k :# |@1{ C#͢Nȫ_6^_BP?M~A֏hGYzv ,eQT[tÓ+bTsUݡz &PD6E>K }ڙ!Kz!{'Xw]IDfd(fP Jh8oo8Q1 iR`"m| %Rĥ0PJǔ7Qv:87/V/,hGOZN2uӊj)D4{+K[8 y+k=|k"i"&;F=5f j<-}(M)SoS#T=֋Xj\|D4|+Uhu#x00y#uʝ8(7cשk̳pVv!eL׺[Lc}JDAZdUu^]O& 5] `)ѵA-\/ Us{lE›S2j|`*r܄ä!P`<_IbuЪGt*JxqF$;j!;$0|T`£c&A2Ou8話A~RB8\eDS0f~0ýa:;&{)ٲUsq>O"O!<>?s#9,7tF,"L7ev}v_nݥߗH@xjfd=+FU{.94r̙Wfwp"/8´x*$K:\FlY=,Z&Ǭ.3k{ =jٲe!s|3R${}ס8MnܥU Ѝ6oRriK=hsjqkwp}~8{SRR>gB(g$;T9+O}u!%Gr;Jޔ.!zTHgΗ3;,;w"2%>Ёn: t:DKWd¶,u>&/ko^bF8^V)+C@bxVjxCKjE No`_.Clo C( 2vԋ]YH޻՗(`IX =8Aڮ~궘Xn((Q5u%5={w>!xw/exݥ}d ICT~Yȗc.}uШZ4eډz{F ~xtl [%wMM99dZ]Z5:׭+q:'Xo&a^]{0ْ}},r +\c)pVkI ܵT*>M\9_m;KD+痓2Jcеo{jҥ/~hH.-.Hm݀Xvyx8&nt5g?a^۲XQ62G1@, MPؕ`Ds>] eN(TG".эMP3x/2sǼ1~|QbVuOt] OvHz]O*_iK_?0yzY{|ߓ-\'xKٝ8:qZR7( ʡrD;2?\|'a?;0_Q؆h;RŧmܳWsmnzv|h{5w ؁ LCˇbОW: a˲^\)ε3m𙭳Tb/P^;#_P'& MA6kyE\l ͂NO0/tX(@W vZ|<k)'LMc*nS:W]; ;8#9gP3ﲾ+ZsB*B5`lS X:5g -~|`lL_<^jdju7S-J_կZqA<~f.C_,?ۑfu)w4?Fݰ0 %_]P[= p-p lAa 퉗 >DJkvlphO,?9K|03h"g9`|mwG0̭i؎j$h}Z 8&7wǼ=g buq8ϫKzMZvm__%[\Lr>w:5=W%? f~o52?l(v~>2="eMfl=i[ :Q< )'iL*:μ}ΡF* J2هU^zn}5snCf o&>ٰӜ5,V5Gs&Vr^`Q[dD$Тm =!p #WwټlBt 9@@x}m.YX#P,$ 6Y %$B~uo[K9! rA~@V؛ ˼,)ws k ךٽ7C{kw>Gk6GD AZ y'(\"2c-V3"Adt.]TFǖ|&1?/^>[bxx!da2F bjE.e7RJsa '͂ߠ }DuBiW0+M-{s/uk*ՉT~"L{D_|-;E_H$wP/JvWN\L5^7X s ήe0,*ʨ\θeV;,k5B`Qx }&x~.z iPpΦ>kJv7*M x @KDP#|{I? j;(m a;c5ٍ^ UJ){"eW \cS:zV[ %U5Vk;=qV6"9ӝi@JX:8 ]o+˫Z%>y_)i߻k:J*LPxg$  !].Ϩp7ht~>4zf"J4ȜU`2oD8n_h+Wi\IRyu}̞^U1 0=|""-*Q$zS:)=U:U̦LHJK@ӆI^YUTToKa:S* Am${๔7@oV7)DcS'0tYaKJ8M^yZku෮xmۃ%e2UNkReUe$]! 8^^5M{6yVJ}݀ש5 vOZU^/{Ruz<߮BJ`й<{BnڽŸЬUA*Ht ' x\i8iak~P)ǫLP-YLg: U../+.SHk,*B}̜ #VEc@XO^ߐ;x}qC MIhB4;J\IJ7_kk^_afPѪq,xd;L 5  B9D 95)EV)2^^TkU66; D"T懢.[&xQqLWݾ=S4Zˎ](&mڡ1'EQd H+EΉp%'u Q jCQ/r!M^a Zt>%%5ӥHٟUTkMJ8,)Hĥb UQHST-(lUAF)rV(J".:z uU;3U%R+g+A}qpt`MF2{.T+h'P̤2Vh1a}7bCq0 (]P%$("/t3>Z5e:#-Oj eo`fhg:欢BU(GDRn* WY$'=Eb'!>r~jp6T 9015KbsruYT2Zn鞈ݥ1k]nkTY)5TE cv;&\,IT&-+{_ɜ] SUCSЅJE_DAW!RB[C=(u52Fo46  on)ƅu͡S Xׄ\]+*[WUWt@fﱣr@AN %A*]։|{d ,TסU3لsbչ:+rNfja .Uׄ"V ί:RsS4 ,6ML냴Ni&shE*KJJ{s] <h([-`6l)gZQRf**a׹" OA)gW0/b罐ztpL@Δm6`Ck 8lվ'S"eYEeY$6 KR4UNlA}Cp69G/ǹ$[NZr|K4,yVX,t8VjTJTOF̢Tu`_A ĚqI Z6/44Xp4{F'w#?ne9q'8x=P64:fΠM>eZjy{tRVL, * q;1sPwӒ\`7i>iu;W%A/Ђuyϓ478št^ 7I 6 S0ON/>BxG=Prqκ$0~Ek ?4\.,F"[b(ͭWtWa?~ E:fp-)/V85 v| jԉRV+jZI juCrZ}ict\VQYKMAĬWQiCGky|s-ط+aݶQ8~wUUW.Ht*UtE{ .Q5 M>\P:65-ІH߾ j g5|d@'$!DY6eUC&wQQ)W% > U޶] U>^ Fq"/b5mdB'UWξV9bڊIgQjo}X8=Bj&MgҢ9oBc`/[[Xw5w .}L]EWZ;\#r@פB"\պ@0eG{̥%ZUЖ7\i864 rJ-]!>8gp/\9/f[]X.ҮMeFuŤTl [ӂ h;ܭ2j*|UhuH JUy#4Fs*ڨi`=`8bҶ|BE 6 @49lmukzgS[ i d} EAWt. !5gWo06G*z$}JgOQ#93XFƍ4=$(/im53e;':T~kLG"d+ Wd7CZ3X3i9M鐒Lpn0=jrn/^> eFܠЂgM)}99dǝ-f"iC&þβ҈uŤ]Zn{>->4H ,銙f"%3EtH][젬pVζ[M25bwҋ-jN1C~ !wò`{1\)9jܙ56HSZg}I/ V) շi8 [T}χh(ŌuAt\|"ʝ13v#mj7w.ҚR35˶oVދq XV ҉'HI&U8:N&/ʈ3$hԌ@ݩ?L7dfCW=æTۺY!VK9+sScP3{6OUhƠDe3C7(' "v}>~=]w+B|TWU~iFYo? 3 4ئq5LU5~PƨWhHL{aP~iDNf!cX1M)z+r$iR'f`KqNǯa1(0ɖj4y:?pZ:,\ WwgH\kl$Mq+Ujj!\ǔ>ٌ6{\V/gUhI[dH)mLlVy9xk=v»d^j͵~nRe2*d&ɌpSLV-g*g9B7@yj`+YelQOwvҵ*TWwE&,RNP&nRZR]] zABN_OYɪIÇ&D1fT8QVU hv!pkUӡLӫ\'<6~Velt SYJKe7jY \j֢+ %Va89]]c)3K,%a9fT{RW^:`TIXSV}Ӵ75+Mz<c5:M7w=*nmPm&-Sq͟|4@V7AQa TiKjCɫ!x{IwH fVE"]EV:DfSlsMZBSiVzl:Dh(LQ o}WȂ WGjcT,n[R}5z<%ؤruwjHY ?JuW9jF aq[ET$VeP7ϭdU6\u,;`\75Fm58j}Qof/쓺F%cd:^!d+em:5|ȼmץDÊQNyKkayb/:r*)Agt9վ@P~!87NǺ0T ־6p=ߨ{rZema`MT̮:-Ϋ,5҆y,:䔵~P_jCc.sEdXQ7`,N\c=$y={{z'Ozln/uNY: I("! D&&L0-  oK"#dٽ+jwﶪ^zto( $)Tp49`Y'Dmhj-{.{W/n%vGNvt)'^liٱ?3)y,aox,kfsaji{}u/y{9̝>WSUqk|g:L ;HEE!E%t$+Q"J9ǤZ!V e_{{֝?]7AZ#ɻ%؈ W\/'þmIthonВHOT3נi6k%&XWf;<') CaNkw1 EJôpy2-+ ϗZKqXd(|;.C0e]衅ƴ󑁬2EkVctU;2n? EHt#zoyO*kW|oxoQlQ]oajTnDt"Lˏۼ&TJv\=bsxn`EL-sF ㇲרD>jv4Zun hy%8 eiHB,ߙB*d3[B)E/]xхitxznAA/5h$c'!kkZ{Ne#.j 7+EڨR6qlpW,Qm%_k>i|S=|>>cAё[=/6]lf_K2PEYqgyC @!sQxh{wkPT ixK9„1L|'zdqPYiow94{Yl,Β2n}dbAhى-" h;%<j_)z܂c25Ұj 9<21aǶe"-ڦT20|\Sx&γu@̖:8 >#ZxO}$Z UdcQ6!Oh\JZcrW{fuLuEv)?clqt5󯇯<} T3KlP@<8Ew]sm|V O!%-mѥ$GܪKemX*ԣ\sjÕ?1xh>\͡w/M08hNgG#y6'W.>⥬U"eŅC{d(۫d9V^ DC>6T%>626HmfmsCj-𫡔* ABK8ہ?~;o1ojHSn4 ޳"8kP@Ǧҡ;6/6axێ2N-T?C ķDto{GɑL].4Ť>;긮߯HocvBukidFcYof#l[?Zs`s1r`cer]k. U>L&0)b=5bC{4j_l4oB $ >à mqg.plsbu!/_AzSǽht)ޤVq!NCC ~ݢKMYYӂmDƕCNJlf0iOs#C24:|<`#we!m/-_ Ŵ,񺹈۽ y 'RQA(!}1mtp W>&&w F4P9:gWȼSͶuCl&gEj7?w)uppR :Q$vԺD]-hwT)QsZnws[ jM vX GXrii#%.w[5YwŎa(iݘKn3Voj-s< 3XO~2݁J4p)ue6옖mDu|RaQ|z$$$ |fK:M0pDEĔ^JdS||23|ȦiSO~ϖ ,6y=Yo ]Fmw+ELFˋq+Ҷw51h1Q;<#0(EaM~gfQMIMWd0(p^eP"le/oF>)uO3w–)c dPɓO*賹Q/wt#7x$*?DHxi@Kl;ogKvۍyL.{Ŏ?ڃs654~kFdK N])l_ԭntXeatAr8[*3JzőRE#j-F)w7 7NDRI9}ecL=(ߨpoKZ":q4WxͅM\_8,!xz*@_$PFx>^Ic2l%22b . Uȹ…I[XjD\C{*kbU79ךxN?A/{W7)Y96DT0r)螆DZOrvcGQ t7 !MmM z8S;њq#KF[h9"OO=Wۤh 0Y_ʯ,S׿jm\#֨`b\¡ ˬaa~# *݁apvq; QJ6s槢ڦ ?s*/5߷b6~3cDDuNGQ2Zh]::)'.tbUi3= Lg 4cD_LnN΍݆hDeMfqUXbe?=lU -`cR^mwRt"9h[@s3lWe-v0Ŕ򄈌V?XW_cJ?ƯO )%m#8n"SJ,!s~6̌;H ?Z`N̼F_u<[[LI68tH|=eL ᕺ<Ҿs{6\[l"i!LL6.~l00=y['}U2'Ʃ∱Vgnҙ) #;s st;iH;z~H脄c"+'F)$ ?pFUNNKЮR?go7{Rʥest/07o?LJv[3cWζ&9s%:CA[lWml}uG:+v'GF樥 .f=;[UsGퟖ~ewP¬Msfr{卉7(GU\ӏ~$i0|i b7s/DN:GU|:# +B/#cG(`?3l%6iȘ{l*Ab3 oG,;m=DnNv!хJu?5?x,㨵\擄YY"LtF闊Jnq,{-dP4'!Yj9(UnяsF~௖ {  $ݻ5I32' 2LA Hð:/&qY~0剻jPVZvDJRD3ͳ#^_[!UE 99!0]E cQM6n8Pvhe-JF@saHR_wa34v`66b91)A[&%.0@W늟FdW=uOx ƃKz*FKS?iO}LbsdGdɚ'F j|u1VVQĥBoH,N$M|C拝12"hQg5̄dv]hwslЮ7t"5lD!QZ k X:e_վKJŵpL۶M?d/X\2 MFܒ.'>_5E(4W~~D  'Ѧ^ɺ۵ ]ӨR2OWPqIzrD~*UmD` YIN8CFݣIqhqLb#2ꄑ6YM#b!_ 4Q۽13 U/-xVMFKZt 8<liaʋYAΖcV juJ*s2Le>"YzrQWj+R,TD@W $.$RՓv_6;y>4Dtctu<@E{auY% =>RZ)[}:pj1ʡ+I&-ݴZEWtk=bLceٮ!!PY(tE+x|`嫉%7+﹃0KI"DվN?3f.Ù c6vqBnH3V|AɴL >`V,l69mj=M {~b qL1}qԝHpP t R~KڳsKo*jӓ qGI=`ۇi"BHʪ4}y6a|OCY}6k4=)cv}7 tޘ;doJ;HNRK 颺 qȍW P}v)7@@zzѧ3Po׈/dM~d4(& mA ';T,E[ͭIT? Dހe7?j:8}z" 4v5U.fm֔$e"&E?PL}ߊ1@ ؛@zBOhCl2R_^[f*.d6T8^C}YlQQ'9^R' d)/χk; F| w$sƧCONI6TG<^a45xB/R8( .0kw!77$D8=;:dEfB&a(R֤?[?hMbCAWPvyRJ=Bf5Rp􍛪A= A(Z3>[Pߞ?6z]O zK.ٟbnjŁTWPi-^=2lQla8- .3 K|'Sb6_tʟ PiمX0#t7ÙCl=l!@851n yU^7|",0NQE).>p}~ <~j& FUqQ0n< @7B5n L2vfzx m!:3qU@j+'^[4wҳ;~gsnerSKByqC[~Z.zls~5hT{"H_iivozWo=P{ {[J1xg 8tA[W77^'shc(QX8]M4oBλ[j`z|w^b++Tufp;@Tw[+~@ T_&V ;SuHDG Ɣ ˛G8(G& SV%j!Q|Kج@Ynj'6W;kGCԞ?7=ʖcS" m7k<'!g,hAO:;R}3,m R]qܙ!lm%ʆNTǵaZ]xYwQi413jb >7|t'D`s4tYǛJA'&;OdOF!FMV)O 4YngA1λ]cñ'l! `*.ۃN'YktxO 1uXK{n;|,dk[Y\f78hhSZrl؝],ӭ2 OaY!\kAp;6 {1rIکJ-N,od-̶?ߝr< 8dgw(g% ӕ:崞Dd*Q![o:siL$4_WغXjDڅRyN` :*W3^(tf#lqahh(T$F&ֱx2vO\ʾ=?RN2i'889|c|4T;_dGCSZ0OrmWYGx9|F&hb+eҫᯐljF4!-ڴ56 bJ3Xn<6i@/ $ݪv槕Gxf4 qNY6Hʊ^k|ƯxoBa8CGw6[(c.@Du!숁'0t߲P@7$rg v.]tP^5ܭ!1/oܘ6ƚB}U4bkcPwenޑ -R Ȯ2\IchC u ѺzLR$[]I4~KV 'o:pi%(P</\g J/r WkJUs3)ݘ \%8<ŧwKOXL{LLjU“qVrQfԠ@I~ykj 'I+U`!_ӫ3LEżr`Mܵ{ Y.7}[mmPḱ(=l@=F)X 'G <8eoHawW.pH~s)&Rdcv7[=liB퉲t`6K^%G/C(%?ri0VS,&d"dV kҼs2lt߉|x~kHӓZ˚Pg&zR?m크 W>L ֗9/KCh3P}֟7Όo1\k kϕ?ifݹ2e\lDpHc 4Gq|m@#TC_]+j9m|\vH6-GrөtCeoc/eQO XUp윱,=$4ۄ^/;P 5ٚ~x[ԧLµ5}N Yr=Ы|Cbt*AqQr6qJRl/d^n猾Kd?caux%QM?T5! ES#)*Q1UaLjmĞv6x& ޺Q1a{Y.ZKh1 M{@ЯC4.+rдҀbaZ[%x <ޓ=fx@{IHH*cYC%IDh;E\-LqP(eg)涆3&tGq]n+O/~3gP?܃qu f_Ucyw>:hB{zۻFBڭS:1ۅHNGTr&{z-vRa͒Q+hƳAԣ'Qt{ ͤ*x/c]ԛ=5JHχ0&OϘ?%(i?͏A4}zm~OH ˥`i NԢ#>.ٱ1}f@,DѳCKR@ maY您V28OfnLQRE1"lG$nG>2Y#5'q~\jM9O27o?s-|j;[&j [Ga^ncgCqZo%Ve$(pV]OWݱ bkz*PDixTS@̵_kӉȹm26f}H`d֯C`Fx%,FSQrD'd(("ƀ˜\$Œob^/_ ui\vo%}V "}}?ScZXvÈ2.GZ78230 ̻s?nڜ<0F9۟zV Fm_ ۙԗ-\׮Ūjއߎ s/7G鄫[ED{Bef\cE~ Ϝ ުZ-)mI(xQ4ZvsNE'աt*]QK^ܢiGŁ~}6@xBNo2Y彡5k~2iMPMj7d9}{kG3Bn融Y?Dӈ tkFǦW#hPgmMCEe.ŸF+ ӱ2:6x ƞX+vOF,8Kk[#=Chl:x)Lh2cT%,O t N˕Ƕ*y=MgRy8˄VC*?HD\kE"^MRJzjTݚYg**B0/d*cΰIM E1]eg)pD;V}KhqGRp«_,;_M$5 hvG;i_9{`ko`.+#E26/Oaj/v \Tm-H;Mﷺm^2`.7k՗Eg>R 0 KHx3d'\~Cg/8OEwm Ki%IR~P"VYa,H.>EN3ÚN:d1,ۣ7=u~T0#Kemښmп, c/e/|]&&8̅ as˭웬9oo|õ`l60ǽؒcp٠fva_DЦJ_.o RӐ,zwlo|;#i۰TRfn*]Q7%PIܑuSI/N/ReWpYƲF/|x UQ[^^MVm=<*,餝Py.gGz5Q~ǽa,FHO}`nbMw ;ؼnI(_mޯnb(UKwnߍyUT偷^=-#Ho'91Xre29 G 0xIO ͲVi! fޥz&^@_rE'TgHl)tbXB(s7Jh%dk QQ%ۮ@GtCѽ.VеLH~+L-D+s 6(Zu'*!"UHO 64vx0R>.byL_BWL%LT'1⦌22ͼ 62zY>wGHyI h&\tl(wN&.lȫu_ l2`Qzp?v9;m")L8LSc0(= PڑQ5˭7b.b-{׀T.1d՛Td,?WBB97dc]HFe 9Vo*LGԴ7r3o3(y}q&"ȸA]]L٨ǗȐŽhwNhDfj) =@ɒ/3Ae&7CJH?:V^F3GBˌ$\Q@%PyT3~qG7OhP83GT=lv)a:ĈL4 ^=ujGeH|N#x#?պ,*5hFw129SDߚK6}l*L'lXe4cqKZV_;ۻ.ǚ'Pi\a4Ք'yS;<(x͢,#Xi/蝭=]9znd %s?~Nwp$ADNխa,̋l!W6(Eܻ1MJJa6 mY c ŷ#ȢޔR̔BNS織@%X+tMK/%諚ʠʳq9MS ˾:9;z}Rcnx^=Ԝ1<ڟ7ҝmO6}\Κs%yv.[+Vpp ĆΖqt=QFε $d~#=0g7;|&3Ith#5otz|=~-&c~C{&:7!eO" Cg1纾ϵբ kM ^;a\B5 9W[T`?'A$A\˼9Ah0{iոO:^ ZS9hL (RxaP{Wua+2U5Y|q̝t.YDzqxj3G@jǻv_v%nK11Ԇn٧J:BlU} fqSij(Q(䡕}PbgwI־ -z6-2i\l9@?g,))=㶳n1J_]+V»>k')Gm(kBI딣?VU6(o<о[=RRl@5hi+(fF &)X|Cx]vV VFp'ĊW E9W[`CKDŽ}7›`F1?8ƭi|GH\ֆMs]CtA--!۝sE]p;vٸn$JY0/qƔY&{Buo;PWx䩪[*;Èӽo Y:+}ԶI%xF(5IQNrټů\Ysu)bK/2˥Z nw\%Cih7xQ+m}Þ/)'#BYX\nwY\UQRjJTõuushчxȉdNwL6Geg5H7)sK|_\( zU9yӬ-O74==n-7 V ?aYzHs[_OT3tm|x@\<Єqٱ,_E^c ^|ujN !C!$2L{&ዄfgހ ԠIKt(Igmx3\?* B&Ƴt%FޠJf4s(py+ ;q ?['PR1Vm[AC? O62.6b"3g6An'++@wi3iK|sKxiw^}ZXzt.TÕ"x|M2Ͼd- p?7ٚ=Q.~µ`Uu:O6'Ak}:fXnUbaZ-K3WW`.du蜥 =[eWǭ!2S@c¿{}eloO~~ܜ"yuh{j23&/VLAuMv- |@@M]}?6x jCVF1@VVlV/t.b6[ \~Hͥcbm6K\/|Q $ b&U\2۔U+Z#<4kw-)^?'Be%=@0nT[o76ỹټi^YY"NAՃ=lCů؀FBىDjuo5MhlNFgNCitB#c50DvMmrC\zTB-@ȹTI PɲQ_#:>P_fxZYajpROzminv/s~c+v{" n 9>"7V( _wUtGEG0xC"5ndr.m"$x|o1P~dqR`n2a&>0|. dA '+~xj eE²|ҋ7{:jWb5]E%Sj!qB O\3K5?>H(x#pՒAFY_iĺ~1vM^ "έ'WS@yXO_)ϡF?d17P^Ѕ:j>l$*-#V4W;[(1DM%*&+>}}J|a![usFҴ^k{AQHx=58 Ƚ)hQH`7-} K:1G{KR}Cu]]SuwuN;Nb % VTDA1}v].]P5iuUwΩx޹<獿wJSSjفNP2Z e6k7#`V-S Rev}Q6R'_4NJZ_Zo!u!#)憙6JbƑRf~7Fe,w/~̭,T1_,JB&CAŇs5%3HT =SDzSàVDSz r]SY3RsjӪ³X76; 5"E纝dw-e-aQR^o3dB c=j0Sgx%-|u#ak1W⡌aa&b|;U bud"5e}f/`c"x,7b3X>3k][*(oj0MJ:55$1aV wWonoR)nTM/ xm{L>7[Fښ!4>FS2%3Z >W%b2"lefvQ.t+x7?ObWddmMϗB}-ė`sD"1Ϗ"ְE)K_\ ~Ux9b/1qbm%JI;^ ?"^%^3A}lA^OTe֧-:z>> ܚoL$]M[1^?64^X{`笭nC?P5wиAK@n&"tg482 %h"#j4ftdQ=lhMH Oyޓח sRo2ӑp"FX!tÇ@f@YxB /e'VFj" zǻƄPq%͋A|zLky&VemW8 zJ?)^h~4*WٕZ9t぀#iL:S('u Q1o@N׷PqΟ92$dݖ1Jʗ|mQ/JkT5Mp>Qvᓸ~}Yjjisbmxjz#ņT68cm{@ dj#e_ib ř㍮uHu&ś-U?0^Xlޚ8&cJsdP'E{E5gKj*k5XI9y:ϻc9Oޑ{a:gPӰÃ6E}~KmAG֤V[i+ZKG|`>p9cImswn,VG cFw8-|zI.i4! ʲf\*bǐ#y43V"o|CBXGЍ))Duu9:g4*i06kY)4v+M5iA> 7[9)6|aXF&76lW)sO;.a]UT<7pɍKַ^# '[=i)Qv2.٤3'iڍޑ2?m)re:JzEf6VaD5Dї֓ƾ-a}ZgM"bڠ`7/qvFf>>"Jbgk ᳡p`}f@fU&Vq[Z`) x`\"|ݑ 9tZ9,ݗOos0)!JwUy#2 Q>ذZCU&?y? FObgSxF8ʧ"ؓ/%eF\:$Z$. IxY/D`FD{. rhj6sPҌE1F1Ҫ5*RSEj+3txDy9T{RR:ƶ7yx?HRFVb"^C'{ޚˣ\ EX #iS.tVPŲsk Ju[b3'ϯ$nVkR}SirK]rH*Q -%]~6 }IUٲףKZn*!nUJ\|!M.WEX!sjI7Ms[`}}ykf;n7}سg8(&y[Q'}(nĭogݒڀ(]톖ʖl!QDۣXN_ ݷks?QwyP\ _[g PYڵq=ԮU &TQJ=62ꓫceU1l2h y0+_ ^6[^q\nl sal/cuũJ.L&28O>CȪJ+Dva;ݘ)# HhyZ_:#|תqn.̱!K[smK1Zvm.NuC ]3>e֞2w޴5Keouo{":rwMxׯWFwsY{H ҆wɟP#1< 0显,3EE *ljacdC=~5vXmcKPxݎj, ZJFsa;I@/2wp9H3.- I>XyZ6/<ߚnHmJeb'u̔ER҉-B5zlt@ ;EYctk8N y&0XW=li1'}*uaw툕3JS{|>WX\~JJ(ے[,ODN$Ca9]^O+1%Ɛ-j< >k 4{b}X,'X҂XՇV p9 obIg6Ü#n6X 2%蘂pÐAOGphel8 PVF&#){>R&*-WR 8;25WG͕h G' /J2Q6i?}5$n%G:v{c'8z^e&uH >] kZQ_ * i|rtNA`Xk]w?hF;eYA< ދ*@ |4F:ܶ;!7“b )#j4mvMby"yFewsDCzѫGZ  2agL6 V154֫Nu=ŽISq ѿ_9I?p;\4osrV0ؽ9s@RyƊ`h 'eі-e#e/tHotBvs4!G\_#r䬭jbOLgM-Ք>)A~`|6KUa6?fYuɿw!KZҎ܊4wmFoZ WQQJ)jsu/dmxNk/^P^nߣV+M%ŜiDhz[r 7Ti,ٲ|{jQxEM. ݰ_,Ŷ<[jfuelH40~z2d<}hf8\Q=F-do95T9>;|F543URERJѪ5! 'ԡ$<]5;TP-ڑ[ũj.\17VEktVpx0z; ᕊQ+8JjﶱwVȪ!kdγF*7CqmUOT\:[% V*x==fCFVtOX8b1>C+G f$j,ϭ0:+Lm(u+s[=rf3S\?8T۳|֩ |l"I=ڦB%'P[kc<ޡ9?՟ۈ[eFnBfm>%}B |mGh:U QiDu;TuJ=e^_rI>|"5}40N:#Av,,;3`U3\ \ZD~,fƈ]f!.nrQ*br_OgD,r%LV0JrjAkt`JWO@MQB>3t $lP9tE-,8éۚQF/(@.~|Lx ?9owNQ{&x&=T*^X*(En00׮˽Οf1e+( i\ĥ8D6;h1hķKe১jj3/LBWI,?m\3@/vc"vy4;Ō^#hf@ )u#4 czu، #܉y |)0/KK^RK!^I'A!)m GCr%mx+7ySCu2iֆ>;~rhMS~pߴ!5o罁0TA#CJ壛Q'~_*ш3b Oc~NV#qJ' QJKj&e 詬8e['Q`#ןRxUjdA*a*US鈶bނ/7RXږvUQ[o_BuO+ٱB+E0b$'Ph$?W27?-P_ʕdbNI| 1-gÕU ВAUyZ-iiMDEQqÚę.Rŝ1iyV`,)zyZcLN1֍ybk;;zn.;b=3G Oo(FDy·a=Xۆ]:gX8J?Ti:#Qͯ>9VuQVhEQͼ/c}Ad :]ˡϒR(DZ1Ɋ0J5ZfpRdF߸g1Th6e!Uh{l!1lT=AA96wx:YnɲUBBhZNif3S. [G;JvN|X$sF@)4V!{T&m&QkSTP1szD%p" F⧐Cf't7 M>eqJwN>^ȇwjjx@"EO &q2aLb2G]l#{w!{='z Hsy"kpGntC+`t@ ⾤ΙXĠRun3\m(/*5id,w4 bȤ7S[Tƛiŭ55Ox;A3B~y-WBaN8^GԄ䩍ILw ?h$bfI]252$%fqf#R;цNlX;DB Ũ6avlzYiVFPp/%saPBϠ,˝}-$Q# i\%hZPj׿~A=ZQ?w4[]F>YԶՂKٰIjɹ= {&\J|ME3i3}7KT6Mx/j s|R-iKG\ >ڗו cb+W~Eڢa"d" 7D| ++7LۛriWAA$1 F9)p`Lxd7éq޹UaU=[2 9:2$o6yk>Zy~?I_,ѷ^6t oIDWl/dw|f"Hds_ :pɨUT u̱7oxسwX*AK)ixH+?MwQgo.N \x6SʊKz؎Z n>ph-m =)$#;bTJu/k^kl( x<徂>5yTq(Ldx>Cbyv492I'fYEq|RC|M{;tuh:͒:H$Iy@wv2$r[aMx(8 6?(M}?7""rƷf!3O)%` fb[Ԁq3:mY?o&F=J6fFxtnT6mVS>'|hEo>2)D;_wkZ +@= Kl k-nkے mM @!0P</{x|}LVLF F=J(N xB 9^^$8:&x561gR%¸IPWy;':E + O`|mfBҬkш 0ׄZ(;fBuB?$>̿Y.7Q[ *|x,CoߪF{\fA8$l0 Ժ7-^\*nG-7l]u[w(+΍&'%`qf \8SzK\6 g2߭5hВéַ] ##ϚyAp9fVжhݴ瞰RFymG]S Zw))s{aA6{}̂It-*Hx5X)cn44wJS[$TT/xic459Y-'bRVt9s| $(Ctl[ &QmjTp {-H=R ^zDˮuo.oy"X8\Twm-ّ޻jy&eEYuMiNd\=KZh82 G.t 'YBf\ ~E_ZȦŀжkGD``2yra;n}<{N Sȏ@a|V8x} OBFl W[`C6G4Kk2#[};s^e Q #J2,#%#uEMC ޙ;QQ~O#<꺥⋄DrQPΞ/8@Ry ˒h{e}V3m-PR:8}Fe"4/:[^Z@o>۔nS}>,ge:lWhM[oUҖ&nO _zVtums4ψ%Af/8O]K;QރUsހxY՞蚵'wu3XwKc^oX@;oMhyްTG{"-&{? ~X9< 4,70 sJWeNtijG xxv8߀5/ ^2\^jAJw{8^j^44yqts0)[;h1 r k~#KTlC /+_x+8o1NBfna{ "37WAVN'mJ /b*uIKGBR9#~DBS>5aS'?#m1H;1vJ h 7)Xϳ32Z& dM}^!'^"tOӧR6~']?a(xRYS=E%M_'[!~FBl)5LIq XET,s[!Xckqk1e[28{B(6pO.9"[B2gY~ʜ|Y~/g7$. 4-5z{[*ngF3wGsU4l/O{bٚG \xXrɜ2Oo/\jy5HS{=YmnTZږƝ{B>ȗ㱔]x&{g=';K㷐gfNѤ4ysǨ-| &Y$탘(΁+[h؊ȡKC3|>a$. KfpKP5<`8_Ŗ=N+-@U窣ȵu "tOfNW'@xțt5QWYLLHyoߧJҋzF rӡ=ӈ SͧʐQ7˥yR}p8?HB) ́ [=u7m&Advwj\/Igi4\m8='"_װAg7+8lo4%|^Dq\h8oY%C*b7U|.y{Lg3RXoc>XC96:G!FwY@PX0FJ xz'a23p/ߠ4 X5\a5/87ETڡ[L BUm `?r'D[؁FϤ..l i8&Z 5'MGZms3BiDW4o3;CZr&J%KܺRfܨSkSKn!7$T}ټ7rϘ,P-Z^n4uI(3_R/Pk l6ven{ċ}>BSI_xAoZj[bYSeԤUp>ڤ MaJ-}E/@o%ˀ觞Uj/hmGFR^c?e|QKea^#ia4w`*%cYVBY@8 J_&P_ctj+g+DS3ĺQ/ m{«ZۢWY[ ԣa9owu%u.l0m2- )4xjH v=&m#&Ԧ&4w~)jMI5[ʰPU!bSw66ils;8!+:$k>m7GGRWp p|YƒJ ^tё 6,#UHHB?OlVUיE,b{PN5EݗE<9 ywӾUxE|X xEԷ=PAvd/&TLԂJ pjI6n/QN=iT,P독GΫ޾tf o#nEs> ̏wM^EfHfwC:s Υ{U.m`YPĸ%<Ƌ$FUpj>3R-lXIooa,*= yy: \W Z~g;BIZjrych|*Ci'\bփ4_ho $Bd庀߬ƙWBaC Yb$oB$}J@dUTlN2&'vHo+1n@I7%D;U(bۋI|N=Q1Aܿ)ƨߣR*m8Wt轱WF .9tզXnԸI\t 46Bs+m"8qgRz绫nA18<7JL|!kf+tA6i4ӶOTq謲>koj?6W u0ytpt9j[e kϛRSTlT$2>W%z^'`[j57Zp?sQhmУ95"jlu-dl)FFSkɁC4!ˆqje҂.GWĤo}k`Tvɦ )$' ޥ64@o>- ja6wB߬;*t{~kvH17ig38f›M!3(L'yN eRˡpi2 j%7ia>h/=|"#y:MS>}+%%I f"1ԲLfizLUq@{Sڀč'[ޱ\#!=\R &ĥ~yO ̵ JÛ'vw fn%Ai޽vޙFt6HhNq N ut((Y \llt,nv೪ |Kr%v}!mìlXu/-iEY4ff:Xs/qIMfm WF4RK+в!Ty!$uM- Ds=ZHLMb|\R~*xPJBv !ɵ3?{+M۬7Ϭf{ozϣ; .[7Q܊|rnjVh }c+enݾgU""*p+|N,}Cs _BRwT٦dg|.} 3.pO@EMۺs";uپMs>7#+cw?*,ۅ+_ oPKY  /.j앀^G@ZMg.+Ybdc خ( Jݒ}ngX4뵕ckcYW.4XϽvy݁҉`*-דxؗu(YL̍ ?B.}\Z`+f')CUO'WZ8!^BGMvqf^V8x5|2E{eP5%I6q*OGG ^Stt+V/!4 梆j䠅+ùu{irngwW#4 PN jGOl @4.(,r\}Ch{>MX+_͔[ IbKY;>g6)huwWY]x@r sT[=ghčDIku:i^v6h"ۛޝoxFS.ƣѤۏ76:5汤ͯ;η">Xa4H6żeru,]e3QhMlmL}\+:uVt/qBdP~8n^^W'I:該Ԇg妼|x]$rȺkݮn55Kw*DӺ/HL1w;FWWĦ m$]ܕ9 dyدJ=h{N4RCRA8)*zE 6?0>{o=5wX$(Ÿ~t4MOS[]")s]CϕNՍ} Ğ _?o[n3]EDlw [KY[SoQ.Jq"8EmɎgٙ$>=,8VR1w8o M"X\y`{_ŕ%Zyv;)ory g9e3@wZc[˧j_~!~`+Co<1re#/ YSNK%yw-]—">˗ԎلS>Wh倯]'ƲhH,#]biF1! م!Ѕ{RZ !,(5E#8r״PlH-eA0FnT"/U`'6h}7h_{eFL?W޾bC<?h |}hOx`|mMt`A9 NUl`Jc8%X; _̌8|xB{S}G\cr{+"^n%[ƫ큖Kx;Z`=|1 ;"0}txr ȡo;fP+"[k fQ yVNWasmVϵsȞW:wmM<َ!H8Buպf[yiNHIA;Ccl[=ENit~@{8>H\)r9ִʪyL懄=#h# lyh>.k7J'Ƹmr(i&- ƶ`+20v-OxI6JNZa 6Ī=8W;ֱvKPԹ\ +)J=E15B ~ > IԸ<і(*17(K$!t#g:m#VfeP3L,5Ōv-\N?V3gxS -'vWV.9aw崹3%6B7WD`#3i,P'OdҚ/=of٬PlǥulVNCKsW5| V hG3ZՔEx}~C93տ]Jl&.ۇQ9ve5U^5{T4I ?"Vm)!C%  oX$78#N뼦\e |j˘:ʐ,I1&W/^}Vk5Zۣ' ƷH[z-51]:ZUܬ5@wQTE@$W(: g\}jBVd}aH\wx9P /3T&'}LĢW9O*iܞ lye>pxj|tC559zYPmD %5YMVvW$)WN` ]#$ymIoSI33zxR ;\u|O}۬Q]Z3-3tZ-Y3hgo#Pdx Ut:LE4-=e~CM 㩽 S<[}+p>#KPAƍ-_BG<xܵn=r}"|.dw@_GU#J44z ԗ9kxkӥ)A3[sWH ޞ1,7w)qWe{ du.`p 6Pwl`T'H0 G096k94s^=1 ʛo A="R}o\j"Jխ˚|c)tL39 ?ׇyqr_ a]'=$UUN^圫Cݓaf0 A@AW@I5 ˬ."*("L+(愬S{f?{~{{n\v[dcFd9W#74k rQm,ȤWoMo,?k$5Dc[MYxl?x@]s'Ts LgTO`?go4.=?ݞ-plx;#1@= N p&vh2M0eo ҊA| 1j6hJHQteKbD^*<{bKi,F4[-$H5J(Blw7zY&0Y?`lhS>6-aPY?m-҇f1^V8av:܁ktV+]^B[榶Mt6Ӯ uRsuxZΤ(w-*E8T5NeLJ3+sBc]>TEZ(an/s@Vf8л*LkW|hy c<簪_ka⃜X~L:_,2 ! * P/.ưKt\ӓQfh%Ľ9=< d=b4e:G&S5/ I$OFA㵄͡_(Pht\EGvxcUf[lZB(n.eژA4mbX- vRJ+}f1kFRk=A78r;o*iH bWCA]Tj0 p_ Kc߮'׷%E Vfuer;:0cH0F$eW =<(:)9A5>h@2D΅CӎS/?>q{BO'5<204N NjV_`PJG 7τ )#Jg,H]C=]X,Ό6rAVw8f^hv04qΐcto1;NZosQis_눠S-5^mZ9_Z/(֏r։;fǺmu c'da}@TJT t!04b ثw,o]gٯުZ~r0V;Jk0<'HȃC-8W:vCr}ԛK 7hz8Rݻo_Άmc|<#]䶞>RvHMKscƼQhP2 4 '|N>-hwcgR{&v_DY{y V[ň4@v"&}D"Z 4S=Lb,|_UIQB3=4u[oO(6d0}O~[,3˺;NG߮ S~J[?.wOwj@4M!hEPxOZ\_[S.пlAe|aiv2ݗS[뜞89:2џt O䯍,NFPn&IU[B3s? ;svZ ]։8w;N'gϙ` v VF1b9iZOp(VY1G7R\Yx"G?A ^gIx8}A)T{ʀ%i lԍ rc20vo&dW_$ R STŠlk@h9XC6o835dŽVavJ6dʒ3PN8rVj]{9T vKz/`iF((V̚[<*؝ .2GcKK<ϞGo}냼]Wo>e>^JOp.rGR"?%yqu{^=Wl6-N;7cݕuλ9n0+}8,c fT)Fs`G3ő|X1ld +"uPlA2s9w\*$ HvY8m+418FKoԈ;f[ 5xǐΓ2$iT<,r:ȯ e4g][\B' \k;kTjxT(c>p4tnFIP&JG-%Y#md\Х4gvkN|'1ׂw%z\<,͵-ZS xvLn!fvZ(ˇi@=@_6<@۽3$*ueHt"=|Z*A$grEWAE MLH(a88pbBpc?%ufRJgn)7RLyai'.w]wbHjCfulU ZbhdYS$tRQ=0 Y7NUe0f5Lvꌧ>%,(".Q ;ÍABk`d$|@"38P_a1e:~slZ z(љj갸,+ ߫bUS0rBoNoS&Fa5djLޡRCXvn(c߈6%&N@:(?I^B7͊$qbHPwv h-HE]c! |0$}r^wtvn"YCLPI x?iUcl`S SNO6ǔn1;-: w(ɗx9\Ξ]0|4l''y`qX~~SZL:A5+OagRr82p}jp_8 ؓOqM-gڽ'5oty=mYXsSr-> ^쩄ü`LhvZ(oeO#G%Y+`'CU5au͉:nGGaVX!/t߻$a4 ׃`k w>$l)fp+JaC/\YC&sL<\vgR0ww"w5,#q"턅+#i0;lwq,¼r}E褍"ʇX{ҽ11< rhFFK[(N'=M2A@d*#z)!$ŠjL P&ZJ1+"":y i964$)/yw?l6x!>K3dM駶ZGydtP(Cde1#Wk`cCNP}`אAH)Vmlf$6H #}HY勥֖S/ɭH~?lT$Jh*<%QS6&Թs-xқ|&e$$H<C#'6 }8N[hG{qPXuM}%I꒶RMaق46sƭM^~t? I:y"\ࠎFa2Lb- j&mSk:U^Wf :ͪ&$и~e:J5Fm&ꓨMcD $MX7 Vq gB#{gGO%?"{o>|oA_>Lwj~K_Jp7b:S!n~i;t6Ȕ3K&Sv*JK, S=caQw.{c*~qBi|R6λ3&"Mh 4Z.̌oj?d6Z/URUτ0dnKw GQ,8|M~p,s_R0*:,&ńoS=%f=/bs?Cn|{ ZȌC)El=^+h'}oN|/xWߗ^;Zcyp/r<|l#' ^[3/!KγﻓQ@9pt!i /&Rݗ~ϳ{,s_?%}R%p)8< D7h.ݚ+з+yܖIE$j1 < F3I9W>S_-W4 tB>VF["4n.kN@[SG`"}㏻L;`$Ijj Y(5mVq߁{# >eǭT6ypp]\$ϴZ4g\2w މ+b< vy 3߮B:+\ F0 -Wt DԛZ>O/p+_=Ŧ &i j]Ԧah _%EīFB֬ 4Z/aT; `:2~lTGպÛ$=Dr( yˋ+F|{Yqb{by? PT8Bruj~^z|{"G$.:@؃ײ.DeZ [%'/T=`v/,o)MnIIHIQS .,X)$ku=杖}K,L3c_`Y"ө(14|"G=OHCKc\{zϞ?rI7u&+xɓ9 $tSEkJ$#+[J4h*YO Yp<#͑˦?2gkD`l*N GqI&p6tOwY1 )- 'ZSS[*9}ot0`.<D%:{៴Zϟ C%"# A^lbQ0BIt^e̩Mmxc0A$)B@[1>59~b a\ȈR淯JvYD{y49>h h5URA``wIIqD[."hr{cgNp.Yȣdtz5، qfKI~{Ȣ)GoKdkV!p |Fu Y(V)j0aPcmI<锌uOWC6oԣ@y`~@\x_o4oVㅄ.q|ip 7{.EL5uH:)_߫@;'#B*tk(4b-p  o0x&Jl]}*br5uhVϢFS@"+Ymɏ>mAI!I*d5uPzMYEZE-< ބ.1ϋA&kv؋( ?VFi vOgnzzHEelDa`&Qi.h< M\"lph)6F]ޕQxPaXzi9:ZAB8@eBأHF];XxԃJ؂hMghJcQ@)@TSIG}ʔ=n Ҍ( B,u9*͎dlR)#F=ԁ;Gp80|/^36\֕7BWK8=+c{\,-岗zgcx3i(d1d ඤף̍F5ݏÿM6g|Zc\q4T^>m:;\*kzy+!%I-?xu>m1B(ZI|% +p͝%hu 1} \zOD331^&̠fX3ٲ3%h3Lx Htdrl֔3Y9^΋P}`R )L= ƈһ'Q}H Tzq \@h=zP#bV ?|PECM3 n-qt7Nu=WwƦfs3x?$X;]zd^r:pV oWnvCm:IffP[im6w߬'Q_YLF6hոwwU{Bg$az$) TRu/,~gJo&lfcFKbs88]䡏: ')&qnבWoR33'珸b?WXdlihES|bЌYΧGf=8=˒Md3vn2墲m]UgO7%p=p ]ǨAr TDtuW0}tkI) 'c6yť1Dkp yLΟ[HpP~Q4fbz;FvKw%3}1kr>W紸IQp/sYeY]oxٖd-n˵Lڔu_jHoȸ|`"cLW{1wG]{}AAbPaLMz!'G3`Bo2J-cAR#NAmY@xeG\|e愈Ky&IwJrsp|NYhl TdzZL Gs5zp3v,ݼќ_Vrx+أQ%yQ i* m 9S/h+ ]MW~W5%{X5"P"̾ CleA=7U/VH5gԦz)ʯ(KG 7qs!9.5r˟ ٞE?6_RdzWv'ѽ~0X)gJf:8̕ O-V0u@i -_YԃfbbJ)ݭr[Xcw/S8;QDkɒ`VoNsED"YLR8s $bH 4FVuw4Tcߞ4EPBt%'l%(c/->ѕxvJe[,"9l )Q_Kiy6BEJCJWc_R6zI$/!=PnF:G7$S`ȳ@(zaPUE߼Ĺf em'YCMaG>s='v@lȜN@?]@15 c}qzDoouU7D![Ĝ5֮iJǟ;"znW$) 2 hGo6S>0r<`96HtT a_nJB- nROɬp|IϏ1 wit@!ÞS> 8?Dy,8_{@B W= :J.RE.vM:ĦXWa@Bנ۱V&1?K jȹ^/w4zY+L0QȿbյHl:NW`/5x.7<x5JVq'}ŅP81UWӑ`~E T;%+~{5Eu <0 ٱ4bY m!FV(CJQUޓUvW)ʆIBwO}+ItK]I.'rJJeEy^Ov;beMTeQn8svU^HShG^D} "03T$e VY=P>=0~,zP%JkTQ!*!/m""HGcrqܶ+JVkӅMQmSZ rnrm)R8rHMmۗ*A^hU{}zPB !)wTS."TSLh hkj<[ޖԲ5֌Q[zVLd}^ụblץO#f-[yB)$I/qF{oڅw" } Q#sձT*Qg_E]sX,}(R'*O+G.nxy9P","DUo9~dMD6SOy(ks*aa \A qY{=L5@^0qRW"#-Q)2M:ۮm|lkwSNHwaT˄{(q:E hIbGcV܇|;Oަ}kpr\ } #\fD/['7z@0T4ж#3%ܡjX :VgF7OIg1Ѱ8/R $rnkc4, ME_/*>1NBx;/h}cL^:jrBaS^"`!]唉:c ltOD c<iB3+6=)KfBk}2lgKJ1mP DžPcí fh!-w][E.+"qo[[eB_P-<Ȑ[u:<*ansymPε8E}9v5vK1^kdqgMvz}oꍧT-$\$W*Vy=]OK33kD|"<`H ȈkZtteI`=1 i D]zPsLPX IMI ¸D \`Mx $$ABГ0 pIb#l jBb)s0hODo)lƔЧkk=Jĝt}as!Gg`W d+eb(b&)O '$nL/}y箋ptuLT[׹m~J-Swby ;|#ꃌQ0cd ?ƒƀYnjL7j{*pAk u]LQ /+쌋$*R( θ- P Nҵbܔ_dfn]nv=]J\ee,: Xq=1v}Ί:2{\ro"` j[!]\5~^@tw[v{#)'Q*&YVp[!^OȸF\ Stu0Tl=j[LӚθ2Zw gN5̩6sS%圲 'ALk}_ O09aeT^h}<E[̘O}kGs¥hW|,n4' v]3W B;0|k"n{Ph9'eaq?r wDBp33gDv`Mk6/n65\|06aS&l\k=nflYRtoֿE MIA[ّ\ŭc9sOp?tޕE|e~(d|Dm^b}%gwlߑ +Ǔ OٺZx  >Ȟ_]={ + eUA]A Sޯ0=n:d'rug̯ zSSUɤxyohT24oKݯgc뷞W@C}|,-!D<7Xр#9j#P)^ nw179ł&=xIN]xc}=lz[nQ䈏1.'Xa>n6F~L}w? >.؝0[}Bh=Txt> "8pь61 bm=Oʭ@;,  O[C&)mtSD(;m/9A ܼ4|)/f' Hiך y*9 }ߑͤ0N+z-A!V% H ;z7z#dgpW1^Sdf}re#E[kuJ:@\Vl z5DL5Ls(;P+ 9VŸ:˗.6%jA}u[g6޲'b 82:P?BSLw1BqF2_xQ6S948C,q< t;Z)ˠ:}Uo >G]giij ~l/c^wXေ*GMVfzlH4;P*R "0Kpzvh.@>jL!b0@grؼP.UH$ XWzN|ƺ{h= 2kw#-l_~9l# ;>ojoZPjsw ˴r[ :e@>#a3VmԂS¨0S#?@R6*ekf1p^XvU;TB#OâfA Ei'Xx8C$f$y=MZ:"Thx=Ҙ!VZH05:<|<&\cSq  ""J*+`|ܝϔ8K Gfd kSѯ9IՉ⃚\ss[\M:W6a# wXWI\l{2C^WR ݛި /G;ztoxc;wMkKȗ"vDS\T_[mk9(2<ųj%ZTmmE,\#zFZ+}1Ab$s1vz)n^M\2wh,dd7=u+"X-'-0Vҹ/:8u,8'g7_ȣո߽\b7h#zeEWF"X0귧랅Q\^  ~F&d\;jU XAw(=<|CYGp/ݹy'\TŠ)n.YU>+wJ4Op9t1wۊ:~򘟭 {^3hSW |` sJuFW]&LO)R'+u*R&|.Q:A6Ow_,>RRJ%yg>K/8x[oO>4A?Fg.]~ݬ7ʿoL46jt1HjmIpu͍ei]}, )LWx.〿[-k&\p .<d dua0߁2`|LpWffQ>00m^mJx\o& h]qPS 5ht? AjIj0"pЛU+jĆ2FxQZFPO>y4!2Z[x{$(7[P`g\^ @?,QUAB|O8 Lzc);46 q%HH('Fc|&7p kvn"Jm^~S"֨]IGIƽޑ-/rbө1ڄX^kᲅ6i1Mdf!p0v⮦+.o 8'7lF6zgab[M-1ieQ-&2$5g0w9JTA`$ Ŭ&7H#?IlFhg L6:w6O H!J풰2W9!;>^z3<|9;'sj\+,#&g r*(p2=FVedH2b'w1D5ǟx\(o9ɥ[> "42 Ps%)lͶF (.qnxA-B6Ah ̼w#l{2;޿>TU} u[*pT户ܫ -s̯L%R٩N{y;?d㟿r_(Op?wMT#8[]B/,.,ѫ4FQQtW{5c'j0d_ opJ Άl7TI֪1Bw][:Ud$*ᆒ0ѫj2bZ2s'S~/oӥj_q&=sgUW9<石qYCQ3:i2("K5N⇗I@A;TPfY waּf$,O CZ_W<>xƄ\Td:rկS8>bΩP4zgRBK.Q87xWwTG;mC^L-3hݣ36GFG귈Ud}QxQ˜T9Jܟ M7q@h VvqKfJ$J_-Ƌű\9Aeuf=VfBUZIJHAS` g%N~vyy~;enFrBTztbHL*gƨ4)<v1 lq0c)fÑxXޚtnf~NǒhП<مuC$?%Nn4$\n%Sؘ-V7]y$3+7e9.vulc_Pol"7"03$d 6/(l$;'В֮6jP::rn;AEJ"ѡ$Z>xM- NBo DD9>>T!W6㟍V 8V-B:} ):/P sxrh菇nw\ЖMmH3' sn@%2V3o ;@ v 9"Gu'T97B{FBW\F^!v]q <-:K]/.4-FIl>L:Nԡ=vhM8w@M}pt@rǡ ?wIZ2ILՁ獖xnT%#@ p_cK ZT_N8`_S~-T9g nLD |4ie!VO㸚ѧ(Hro~%E3'ð=?hA'%LC>҅cTLPUEY(44rā#'; caD(W[`"ψi Uxȅ ~ғ;"1C)x`a5fze[.VcaF 7#kي7i3HYפ7ۨ{/9t0?5AWHiŮ"[Fk+զ5IruhQ_{: i~ArW+\l=ͲiGw1\C6Q|^f݈ TEsB LI,.Mmq$tlK+\!vVT)TXߒ\}| NssaO"U@,>7%gRNg&eӘ no65f*?Se`Q1xgȷk&/A IfɥҮΊ9= %NJAh0 ;?ӡg!pC!ED68y[pI jݪER{lOEjwǴOa_^! i*w8$ [MWd7 x**u b"2f| P x˧c.W`A-3GMFkn7,J@@R& Հ+/.Ľ/m6ײo*Oui۠3uv{}:mS;ױo]?H64A |`hDD4!g_[gW`guk-\y33eԼTԭٌ5@I-cɪާ5.W7 ac4kPvv&g>whT? {b;iIrLS/Fj;e_>H})7z^elzͪ(x5RK)xj:8OqѰ?w7@`7.r![ۀo\ /Ϗٺ2Ù=>0W&MiXq-̏uƎߘ#p%|P"U$>$Pn{}ik_9|hpVm><1 ~cު,Gn^m Y{~q(Aez '4yBu"w\*obh`*%4x5!϶7ʣHy+€ ArEZFY^c><#<+B'jh6X٘L\?wV'lIqbZv4|xC3c"Lظ[kmovYϤӕPlmrf&$u?j#UG/!VJz}ǾVezO]xޕ su'Zke> - ϺlWi)LH(| I HKUL .Κԛװ60OdcLo%N7{15-}+kA]o!pDvSZ͢Fx"t1~ٺ $.jE皥_Fth}c쏸{ (9q\pa+hZ&EfLwBHHr궅y")oޫ߄k`٠MbM=}`/o`]™ayf6e7Mͽ8$07:z! le6'f& hkih1#1:f[:D .64bŨzHQ_:\0G> H7wtۮcHd-ue1f"zǐW /!,J AELt["{w!|gk*!g >`$a) 1~z2x`ג&(=jp yTBXTp@ F9>ɣ#'w %XX_ʹq ".{3%9KaY ѩ"\D4= XFvf#&ҽ呂xx}x;ɗ'5)J4*镣aU9>q_%+S4moAt}P 11f>2R̝* 0QTS<$;le(B̿}ogG$<50Qv\-va^NVLcޤO:=.;mAlZ?őຫ`M4 #q0lF#P=rfMy8f _Dc.Ilp KUNy>-p7ߞhhnw9r Vϊ݁`tvmk繥A^s'i9֟aJK3CQ 5*? | GSv\ +c L smYYTGd5eӖO WPp-otiS*!9_= CJ;۠FhUzPg Ծypn.jhGZ88AbÚML~4.ΡLi`dۥ.|RcUrgU Zg*1/Q9z FMw:< on6@"KbK˟Mm>Y[! S'ɱЦ5 OR Qd&>d%'X|I|S GcwQ{@U(M*1keK_͖hTwF/b+nQۺ>nK-WLx:j8w FF9h(^MgŏPަ]⯇vo^.Cޛ3NxEA=H Kuؓp71Fif}$Tdr&RE0 :!ҍc\Ds{[t>޿y_X=%qL`SL2)fM}rNHjN7b$".dgͬiI|֟h*DѱWZK"uWݎN%5Kw}DDm !c4d&W;Pj{^sN#DV@9^-A5$A3mu}&9VrC;yX>2vvi~!G}]6CKLՎiR,3r 8#YHiVؤ fZW ;\${)ppN]B9?'*1-:pv.d1gh<<+e=;{;& ImĮe 6jVp{@Ϫ&=ET&$xv-3jK[]!WxH}V$~tax&p̸RX^\FT]QI`sr|UGmo2[8 Zx'#bK><%q/P\N5&ON, "DRMm3OYa&e I?59lP".GY|+^ů5(P* :VڥG1Of& n+1F݆ )~hJh*|AGIQ''!LCȏoKcіee?K;zJ6|@{[]$?? ._֟ ɠo.,tm @N-4n1ty:f:|ds-RbWTBs8 WץYTHi<z '\\R={Wd92bCљ3ۢAj;8 mK|)V eTeoGB/l SڥEw6C:a 5+bVbLX!!1 X|g=AڠYqA&ZNP |T-׊)Ԇ;;#)j7TaJ佮,RɥR+oGF7hPsw:_x C&?]͆?I=JеŖOiMlr+33]n8JJ;;*ɩ5jUPNOhXMR8Ph %Ptq7 |#hw=~27إ<{Yй,{f>شT`߶MJ`dK5W?_t[l+@LW :\MeY<"k<_`5A],= M> w=v6 \7-rͷ#91.X,-qLq؃B5('i4V?e^YMv͠Ҫ_l}~_>P>tԐDMɦT4Sw){6þQ2@h8ְ΂pa,eODbVqx` M{MizPWZ][" 9ҏݦEv{{*j]Wq,M4&4yUM f1*->~<\°+[p5L AžNp!ߘF;CK^6pRcʧ+ߏOhg~}ОnL̴ٳYdyȚAuYrWr 8+p_S$#|3Lط\:pp<'5z7!6{z8C}N]"iz8!KqdVDޯne=X."B/(\\_ٵ8e{((kK+/ WJ`s?>@^l&وf{Hpmocթ5r N9zKxa>Dl>ӿ6<"}c+ﭻu>O7_?pષ~=L`JڢΉ:`޽ӹ#?XV Uͭ$.>(' xNz.vew"0,Eӑ cHWޭn^BIdCz묾ui5{Rk} 0ufR'”=P*}ҳ"Tk` v"e'8~vsBtCySwJZv'+/R"񖛉H\ʇm Uq*vւI90ktvy*z:<SqDU;}.ETofO!l&^ML˕x2h x“kh,"lKn+`z@gLm.Zc}莿F| *&e KrF(7-2}@749{PU޽ڌ8| tY0,V(ُ9|ѣF mJIQ(D@ʻTރ݈1Ϊo79*ll|!)cūlVoK9:[Zmt q=&mH)qv>}u/z-*~ϴh"c*ؚF6pa&&kUh ry}y|'0Dlou8i}bchLR(yTjr(tp)aD]l݃<D \%:;|!QhTL7d~z[kBt%hH1@&eEIcC{ ZEٹt RTȘK]V2f9.cұ]NM`KѠ zc`e1Lq`}sE[9g/iqdXHM-lhUA DkҐ2b#$>U|Aqy"+(v_<m1X֠Ty mRK4ϭ|Ly?NhoD6 ]C&1 -8,=҅&\uie0,q*d}[$Bpt>ǖ `/$le.jfK8295 x]HQ6q`  Oh~ڎo0| q'Hl.|W]Va m 7Sɗ&O'uYԇ !Y8*ny,&wnAyvUBQkղC9Nf1gvnTmOM/$n`T n(\s z1|lb4pZؒizjI Wi^>2;+Yd]9R?هp'9(  X@Kc%wteZ5oVÎ^/&es/י xv=ۉ|"T6qKhH)v{ho)}fQ)AR.kbzpps4;0gxΰt #~_GAGuX{SNij$Nz-GY~#F\k 7 j۷TZ_YnZ N^-}w+v!̼iI.xR3650.alE|Dz~ '^efZ!sď_nUiUAO1gRݢA!b쬷5?w +['Z:2ԡ*]Ȕk64<WÈv[XFS W\궸9;`z$IZ 6ԡ{D7]gG'sс`G:=N{LЁgOߪ ASPݙH@mڸF3_QH:.D \ޠ;s6>ƒDGqJh}àw]BUxRNa0g)XrfFOނk!}^ :qG!}f'tv.9%ĖQ]{67tCT }u8 UZ!;9}P˧6: aDKm ~\˶2ڌQNdcm$[Dk0} caӅ+n3Jq~wn6.K1HDY)w[a  6,P~t LeE+IOKÇcĺFLɔ.ݔ-Ng}~Πj=oӸKks`tZ{y@g*r9\=qյM47qDB g<v]*o_pauuJf$/-ޥONnWQ`%sh)ʱ> ;aw58偙JQR m.ty~0,j.Bo 9u)VrS\Jl E=A)tR_eUA"M|pt7c&MߝDn̥yƚn:-*!Wp{4]V^#k8#wT&:[d|:l%˪y;mtUjw忇&eGy?XEn30ЈqILF[dr(tNj X8 ;Lj=~9W*mनR8U:XLLƚڬ_ ۹.=1+160Ⱦ4V]?qD b_HLr*_lnW6sTئo Jrkܗ*ߎkR`\?vWP˧A59IЁtv1yb&۵MtNh},LVO⫷Xںjl:f e2խcE %m)Ty_,U\y$gt.xC/Dꗴ\Lhu T`zvFrh0xw!OSqI/偭|OPS=BYT3fiRi*$0o Gv:Asn3,1o큠 ɣC ^/1=r0e7kD& 8ԉS0A{Vs 1%lvB"oڻdbq 7>&SDy=:ZIbw9HuM d Mz>{^%f}gŮb}Gxe{gn4% A=9SVofu⊷ N4ih.Oy@=*EԚ|mY1\X{)ϭ c~H^S! q'%? J/Uzexts}IJj8 gޚyiSoÐfz&rխm(+6[AQ`):AJS 5Im*p  z)atZDF_v}aB{ .ۈFu.TT;{S'3usH)濐|#̰o֫1ds3bJ};z.vsŊ Ke#sM7<; Fa/2Ki`d毀P 2+RJ Sy$Qst*E^,H?ysS3ޥ X?EN ڻZPN bsvh >5 %BT2ݿV?`ϭ ؁#8MK";M>pm:([5$o|a+PPkNig:vz6$b߯#4:&Z%tW.}`8 T`V3?:`PMFdh]uERI jG"9ȹI1ilM[`7 +-mDLJIl.JVW,0_W3QA!c&?oJR%|-{'=lEgԏH y1h?TmeXTD'c}ۙX1"k͎FAbN;=>Q :^K" 1Z.R8h3 ZGck8$< ٔ+@9+[XhL&l7 %E6p?dq^R}ʥ?V?q ;ȟ)jIgP%gH$g)DҪU|ƙd+\'4|PɞD&L$ ҟ o1ؾ>@,7eMxkEFx x\wl6 x.:)JYx"=B|r CΓ,8Oz$t'Z>sP3hi!x-toL}9\}gXT4n ؏q2zo;~lg8edrqP\Dt6Ȥ\?Pc\\PX=w=yvù֤ȧ"CC{BYpR&+2ytNqPsʔE?ۙx6jU][]HKOP-M/hMgt>>WsawƣBȪuaiZ\m܍?67Ei._Ҳ!{Zn&6+,iшMB )g}$/"^p_]O겒 DVeKXض{paq|D.߽PPxhӮ~7#+'A;u = >=gve"w@-@@w|53Wudm~s5q>^mm>[VԦ-Fkst8f\B-~I\X~w΍25~"?_4bs;/5GN}3V1څi9WEav16 >Ħ|v46%x:{e>SNPA4cu^ ${m]VI !~EtB=ԛf{:w۲i'pWVj0v^[|^n=MJ>Pѹ.jR npg ST_lQ<_m9sO7oQō8;Q 9vS7>' nn^:nigeu]>ϹW߿ h|[Yj~Ѡ#{k|<K8Nvwd} ?a5୺l-}/tם%?vyX2Iso\Ziגcқ'[yՊl׆F3wbxf0s44N]``7FpGYCc`ª yJ/TpEϢ0>4=O@=#| T,PQ:;ETP] , eiG*2dmxB/M[6L46\L01i3.ݴ̕éH,;Z=YVDb&&i!™SWq유Q,XOQKz'=ːzUa᪪Hb) (<]#Nl0ΎΌƦ'A)RԵYo(RHYB{Rl/ (c4̺ (e@4d<@d7Ѱ9rRJ6A O#R5ūwtVKw'h.!T0RaK@C~09?Ov~`8t>+GgFY&emmufc95-ocr_HHV=xŠ;3rbR73WjC$Wi8$5֑tg!=;61*{S?R 8i1Q;#)쐁Dnc + A[ rbǬbeCϧgE-nFJbn\{ +_q:b_gGJHtRo)3̐4Qk/ᶣ#=NnWwS-\W+ ":&X/3@ IE$s)61e7Kzm#*_E 97}~+0*ܟ= 0Gr .*饙H`Q󧻏s'Lhj%R"!m<@:̣SS'996f!pM4O]w!>sU~9o@=9Y+KPX $?!wH2~a>E'?>i=?nG'|X?v3+օQ\52g?oGs}?Ŷ?ƶ} ih]a?ö'v6i6EfPv-@ڿά$~a;gf?Os0=<9iP?\rQw^޲:)D'7s{P{sʮܓ7s<}If_23$3&<f 0 ↊V[*HmA[]l"e**V\okmU[{kokKN2^/Oy={ybsp]= EV9eڊYnț՜gsE:U_j̯,,kyHve7[^>!Rr8[b1)!Ɓڼ|Q}u_h\Z~K[uRuV0o 2vSޠo)=5k?ηN.sHi6 ŽW8T*kCQ4ۑފďn!#XYeHCW"!v&N7?ѯn  {2RYh@PxTmoGSnD:kt{mj]ԳWڒ %ӹ<,mNU'י\lJv,usGtoEŸ㫰ۅ/&|'D莌oؿl7kZ\k{&U&kU&t$-y;Ž9-f1?w]wFK2{v-ni/ns~D-g5A.USȼT ?fԿvJ(\[)oUщ5D ^XHžu\{EsCqFZNFslrkQO˱.OJqNeӸݢN=Risi .|ȮT+,.VjJxSSM'SV+e{&]tXKz|zQrkJ_V "/hT1J_sPʹU{ϭ✼Jv3Ug ]"*#C13MW|D{ngT[qms&Ldz+o͙9 +!JZ̉=_.**YUe+wRISEaxvL?}͢ws _:Ҟq[k'oJ^’cq;+AgKM^s%*([*okn.0p|kayUTO4o3g暷.[sVQ0?cUp*:-Lү2'U  9Ὣ"k KT0Zll;u.-65^m̺/yխ:Oqni6'UTޕ]8 TNA4BѴ<3GkWً*M:1ĔQh̺^l-U4ig^[/6ˏ9g$.'7hfU's'~s7&u# 2*sWur9uļZ-W 3dQ>xASSS2,7笲ݿFɈtvaOK4rxY nU,Z+V:u_2\0F}mٹ:n-{:cG<*͛[a}}@=֤j116\ M4clM=3S˧Qݨ9#Lڻ~"5Wǐ4='u\EhUk,^GcŚIWV}:ZiԘssٔ{CU2<87GmUe;>^Ji9,+گD~b~wEѨ>W}tx<2_lȾq&ޕəD*KTW6E5Wޚ]O*;8#LI[|x|.UvVc͂/nvyxU$UWVwfH®i&f Uzͫh  .PtQ(3MV_TY_fWdꫫj)5ѿLm2~'7:g ?6Plq?țQhrt:O֐ʑd{M_x=זsӕV;I[T4?xw-يK7kxo2䠉tbWtLpP圑+?!|*IDzcLO(NEsF2N!qKҝw&La7o_<{l,q:1]XYZFh29$PU}מ:M7V[ScmDΰjZX=^e!ht%KE3R|^mi7TyBVaR[g o/ +Ks`k,2h3#*<248?O&5YU4rg֣}1FUqU M.@úyއCFܛŋ?Lʿ-^oߕ)dP"*?Wtih_>ۮ-q- 34^9+c^J] 1QS}H|)y>vNMg/0<.3U U|*['yH 7.W1/$R +>(^mW=%2A|Bu dN\>XM&4~OvԠ'贍gbJ1[ƙV74Omfۿ0*'̣c|lj` M^t~˧3V9~ScVƿ*O3J_# ?|q wnx; T)-~]-/9bMpq0̶O׼q#yYemo~j-J?/JFZo~M%3̋%scxT$h&3%bw'dK+?J)UO[A]eԘ>xJ+ǗUٲOO/h.<ݚWS`οa|pW~\X{3Y|2w䑨O tv,qS#z9kEIzBZdWtxk3kJKUM厛ҦFLBUYa|]d|T6F͝ӸGj@5CڪFOʍ*H[p$wJ)2eΟ[.V/wt3~fh t*^Wk׻/mZrR][' lds`QXʡlAyivk '~VuY}d63J[Q-= Y6ʪm䔭ge̘[oKOyt+i%DeDŚ==$OUۮd[5efyTZTv%h(aKTMXlIvTE ֲ춲V-ˌoEv^S}Jf?6ȼIZr*҅b)])R^QQn{]k~cE8Y:^V`E֍ZݑP.ܲ+Z ;|j&ǩ^͘`3?Oj{wC}kC%&oqU[j/ x5kyw`E?6lr.mbj6󛾞: Fz%=M;j,=o@d{%Ags盆*;O'uw&ϕy:0jqRϥ7/EyiH{_;՝'sgs?s+!'yiyNbG_]uڬ;{Jlz{.idyWR7tcor.\|E=5x:WkV E^ʂݬ6&&Cy&QTZ5rIWZo-O/t֒ҜWg5^ΪFfZfc+oloM(n/5ʔyX'ṔMZ*_Fun^?\_r1>vlgk-*~X720&@jg3qpӓ8;on`N+0vg::{c^31|AȨ* TI:6K[Q>"2*cT}n$"hVٷ'Wv"OMdbׯZ}ɍ*^\Hyk稥fZk_\%V#k߉\YWoi./F#h ߷XD^Vc~VVF5he'"ɟ8gd<&8퍟gLZ/_O}-?(f͟$RaB^WH^ץtd*T^(-g ?T^75Qnu-?uw0`RMY{i#WRBV03PU޺gKv^UE_zO'w)j__-֨/fBτY#ۻZWtN[l_8mnl)fb7mI=\rU6 ȷ5-3ݴcq^l3=! m>Om5gGM&Tʨ' –FLUguK hII6J?j Ȭήyzҷd;F^TE&⼈!D?͙9FM/=CB:3آO3isBuY9y9iiIXwS˜,SG337}.Pjoin뒊T.QN뭩_ͽ*&9}4R_YmuVڦtg.[?nZ|&PyޝbDd(lI'1y|C"}|ؚz@iS@ޅXmhsbdHGi";{8BBqrFǜg%UjهϘSjJĜ Wϊ[>Չl.yO.GMSj?7fXoe\}iy-ME<*!1}毨3vii1/MYzyglIfb7 f;G0x:~C:d38FE#|x~LC{T Oza~Oxw21dIy?_UG#?3;mi-oF[[eE*,?[K [(*6;ٌe ~4rM}Cՠ?Vߢ21$۵@ޟW@boU_LAu '&x}ީz#] #Z:0k{3ퟲenՄK.zҩպ/e$kҗ>6sJ?x354ξX8J#Zw%G"꾯9V]){ MRݬ[V sx5^9y%\² \=sōs] 3GrnY_Q]]^Q|h6zMM볿G*\J;L~&eyTe7Y S gO0=q G؅KlfK=yrV9އyɹZ!+ruNǐ>zT"H u$cGyo w?}:&w+{|'-VK rB#.1qUFȰiÍ\T DXZZnY- 溙?m*vD\ٺnhguYw<ѽ0jZ5`5wl XUeO^ͨK@J$©=9{煮zu 汊kZdjMl}.ԙ/x\]3ٚO41rC~ȱ@6x}[K3'FV,L_ΒzW[9bk A9ޚ ~I5Yl8xepҜQP,+9]-!G*R,;YeN{cSu_@aTh*ogw{GЍⲑ{#_*`S`Ċޫjsk鲽*{-b;}34X60o f<ڰt"c5MN%v|Cվ!R.8HO9?'4L I&+mUks3gry3BCWe2MhN+kR2h̑ .OOc(ʜVkJy.^jr>$2{/&rV]^1Äb9ыS*ZrKw^T0s "ڌRVoWoveݛTE7SЕ Z.Y?qL,kqWU۞fafbSی Wuz3r3o8(: 6Wf⶯; M .X578E6]*"/*Ib%uN~XL_/o[:'';{]5Z͊h~~VQ\j)m-sWΉ,ԝP∶G=a(R=)`#)ebSw5}!cw{6)9G/ٙԄďiOiICG!S$U/hnJͪzݼ+fAIyD润9&?hT1ߓ=X#BN`V :LN M ~]>4{Lјc} Za>s s~"T1=Kl`rs*Vd_wL~WݕȚISYqgu"Q~l_^L)O[WZ'$)3ɀbed<{lz{dK5gg*k+Z}Z肶/vZ|\TioQtڶ-YZfU8,fKnZ}2Ur҉-Ho@{Wwչ)Vg\YFq_ 81`oNSsrE_K:~ˑFoInMxSuwmؗ*KS3+ %ꁺp5j2MmeEӟ7iP5']p(#O}yYe*>4h;y՟򕦲;yGU³Tx*~ơX׺wҙI u#+zmtDfG=3'E{uEu k;=͑7>sI5<{m&绪XƢ/Ō7%H՟:ur@:[`WvO$[V7`UA~q:\%NjKx*PқuIMU P6ijy9ޜ`S2Jh]s@ykA}gX`vOb,ĕZjVm$Wk*8cSGIe^qEz1"O֊|jxO{t ̟IGp 3` q Sv(I}oQgE!M[Cna[ssk*,9Mo*ɭbj-¢̬y5@A2]*kigwvPsY'+H>ڜ?cFM`WJGĢYk: *ˬGA~^ҖBy2v/5k BKYSEGaVy^kNqi&Gs&[JjSx]SjH%4Wm*mkoi`nho1_^+bh2k&P]Vw[?uo?>"{FA"^18yK#ǟux-S3~(U0K=z.h;o ~fdu](kֳ/I:NR. }0pC {v CF`ٟJ!8iv΁s(\p1Oa/lYk:x'5o-p+`my;w]AaxOrO91? /K &<Ş~W0b(^yM4+M-6l/腓Kݝ Oƞ=UZb~ C@|{12x),Ǿ w?S[?/$[3Jd f[3ʰla>Umek}[1,UmeG{8ZvٿKe# aǰp$}}[c1.Ws p#^n6ξ;. pa? ^sw8Ax;= I<1\ "K$[^m_aWk ybi췰٥aT+Rvv9ۂ]]_ل݌݂mnlgJvSI '+Iݩ陂)u3={+5eӻ֔L]jMmY};,Rk.*C_*Q#:]j%IRnevB `#Gީ]Nqoc'g^aSy([\jYWe zx'7Mnx [Vx>=n:p'^j8Ax{9 I|`?q_/—Mx=Oc6(ΎRq%:]]mƶ`W`ש+SlM-6lRqv`OSI 'O(N8;Ύ(.'"'#E؋UvK){9e`+QQPevTT_*Nu ITi2"AE 9Tt*:Yρh͑faA8grC5΁8Ԛq5u1Z{{kp-\;߈ ^n6p wnǝ>'x~#(|} >u`?q E| O-6Tý́TTnt2գ9!́TJA^sPI:kCLl5yA^s!U@=T=T*SR9kjHyA 9k2e/Ǿ [!U&*ۥ?TD_/ş/$ˉˉR_?t#;Q9-d4'*s2T`6qR[:-T әj$d$唺S[58|>= cp!.^زYk: 7F|7p 86|;w]AjG1{ه8Ax69 I>} >`?q繗 EI_^~`7)v-췱l}N}N}NT*ANbec-uNIuDNS'*v+J')U,[FX'A/>]OmFNAfT*V: :Q:QԉJ'It+؉؉؉dI'YIt%ۨB1l#31ƨQaTKAwa`#I*{0Ƒpl62fT3-GHrl_fx\ N7Mnx [Vx>]ohp|> ^xO 1g9x>Ϟ/ly%x-/W_7Mx-~WFmh Ͷ1lˆMjVfl vvǩWmfۤf݌݂mnvw`OP-#5聓No8ZЫlW6Ye+Ͷ62oԬ+4&5ˠQI*2w]uƌm31flR2lUQ3flg؎ZۥZ }0.yvtdvAvSW31yRJRj.5gQT .u>]OWx\ Nڈ ^n\6p wn>Gcp/wyO <Ğx>I<83b?}y<_/e *| oS4| fۥfI*b+Ͷ3&mGIl;cv4NmUlM@Turԩ: z$腓GvAFSzԩ`OUv~qY{Ep1Tq;UqԦʧܗ̡TTTT:N%PJXQN S4uF:T'4u2HSgGNi4uF:ySg1u3Qu2uF:u4A hPG:ԩuu4A hPթuuj]ZWթuuHSg3i4uF:#MHSg3i4uF:#MHSg/}Kg/tF:uNST:5N3ԩQuF:5HSg3iԨ:#MUgS4ujTHSgtF:NgtF: i4uF:#MHS'H'4uF:#MHSg3w:#M|3w:#M54u4t4SԨ:5N/}KG_hCj7:`K'd鐚POC0 *u%[!3{{.<8 t .E؋Wx\ N;ڈ ^n칍n;N >w=\CG1c~<C0<')4[qg~8 "K$[^5 O4[ocׁN;i:: j!u2rl3W=PTM-6V[KvH*;X[:UɰПi:@vtA:gϧ7J*(u*XCT2:ԩ<#cƌ;33B]T.tQq\d7k.5 3<.J@r{3c9g}G.gǖQY1,^̧;Zw p# ^n}׼;. p#Qp?|!< I)4<`?q_'_'2xU|}ބ8i췰V9.Ɔ.Ɔ.Ɔ.LԠ یmî*Wq+]ȕ.Bq.Bq."3Xp]t Xp1tb$b$"3q]޸Ȍ.2 *VݲnT[lo_jxͼfFԍjܨ-U#9|:_eRy7q7q3#F;nfʻ[C7=p3 >x?Ƒp'|>pw8Ax=#(|s=gq</>]V}*nf97s n@<n[}~{np'> ^xO <Ğx>`?q EIL˿*| >oS4[ocJd/1KL2楞2楞2楞2楞T^F^z/#k/UWBDc/K4// z)+dԗUd^j{/i/ѴWjMq9TZRxvT;^e/{&Gu}D]QGu}ɇ|D]ju}D]QGu}D]QGu}D]QGu}D]QGu}D]QGu}yQGu}D]QGu}D]QGu}D]QGu}D]QGu}D]QGu}D]QGu}D]QGu}D]QGu} Gu}D]QGu}D]QGu}D]QGOu}D]QGg PX{K3`lT~,/bOoS3~cY5^X W5p6=p3 >x?|{܆;. a? ^xO g9x>_'_'2^x-Mx oz/u a1T5_[eac-JG~t R?jMy u?Oo[?ό?3*~AR[R_ʞ=UaH_E_~2?ώY[gvBuLz&T2*rboZ@kbo {+q4@MVX:z : >X (wp\ۍm7p ~<CaxOr\39<_/—Mx!@DCCCC=9YUe2By!JY+eVf!@vd!@v+edrDY7{| _֠2kH2'`N>|9 }>Ȍb> %AfKAj s&AL̙{$C0;ރTA֦|-H Ru Ru H Y&."ȪY]:? 4f1<i Ocy3ӘAfZ0Aj 5L&LK 3-AfZ̴i J]{߆;. (| h~<CyGᓴSi۟~9 "| /W_7< ߂oC- u~:?Hd%Hd%Hd%Hd%Hd2KD̽yJ$KDq8A2N$8AY;4gV͂AV͂AV͂A Aa<%d&S"Aֵhfl 3-AVbY݅BPh b3]d.b.xgMwI=H` Žq8͖99}|j}`kb}Vakp-\;j#|z/pwp|{hGcp/Wq>< I)4G;g~8x+|%x-/U| O-6T#.DyFD|XHeV:[). BJB]cp![a/ƾز;. pm{q~<CyG|<Ɩgqx/G| ՙVgzXau'{x{xGil6h z$]j=GS=Yά0#\t񳇧zxz ]Yf{̯סeu^"a/Kャ0؋{Yg^ҋ_zYe m{i^ڰꥭzi^ڪeMꥭzi^ڪ^f{e6->}]r!bbaxU>+W>uA`nkj>܏6~_棿KŞ3\y?ZGkh~֏Yog~[YoygygT?GSڏQ?:i~ZG/ϊ?+Oӆa?m/#lя:2J˰{TV`5phv7{xDoԞvp7_x> YxoA 6-<@ iw 4xwiVX#h| D"i@I~XVEĢbhX4j[ "Rb{qV7[D k(e|yfgcy6fgcy6fgcy6fgcyǠԎ:(| e}\p?|!0<cYx'# g|bϷzf At7Ȼy oA*AjAAb 1m6HL$ A8YSjAAk)!9³CĽ! 3Ck5D"v xwN)C;ew !s=h!ql7 N!F2{H!q{==;L>ɪ|gjL {TɖpFΆ* maIBDa0QhXjWsUq8G1<q< O$|_U}RMI|XˠV@<0}r>9L&v ]Įab0kXLun8UQS<@?WTPTPTPtFQ|F)Q<ųQ %D,Q2KFlFl,ųQ<ųQ|%DiY(%J~_(%J~_x?wӢ|7-wӢ|7-wӢ(ޏ(ޏ(ޏ(ޏ(ޏ(ޏ(y*J(!J|,΢(,J.ˢ(,JC(=$J(9.JC(=$JCd(-Jvݢ(=$Jvݢ(=$JC(1TP}oP} P} 1FoP}o1TP}C1C1TC1TC1T11111111C1TC1TC1|ç1|ç1|C1TC1|ç1|ç1|ç1TC1TC1|ç1TC1|ç1|ç1|Cq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧq|ǧH=xH;J ݀L0ndᅳ0`Zu<ܐ4ApfX,6Eۆ ‘> $u]OH}@~ y@nP<5d>@zH} $(u@JPRR@Hz Q$D=ށ<.t9]r@y ?<0:8ˁ<FF4:0:80:80:80:80:80:80:80:80:H`?P烙f*>`tL0SL3T|0SLoE3T|0SL3T|o!0S;C>4949| ;ơϡg?>ޙШгzCsч;;;;;;;޷Ez8q-[ġCCCCCCCCCCCCCCz??pxxxR:ԡΡΡΡ!r!񐎇t<㡱!# sdHI7߷}]Hə#:H5yd]lϑ96Gv&I#*}=wɜ#s$sdΑ99G2M7[^ɿQ}־S?9.-?iߓꈂG刎Gt<㑕#HG摎#G:2t$hzD#-޾+({D#+VGV$ޚq=Y:uq~䍏\+>#?J\_a_yuHtHtHtHo^j~3N{}N\~o+h뻿Ӿ;#'|䄏Q䄏>9kUHP#?|o͜|_k߼''~2 џh{'l~?l'f|2l'$~B'$~B'$~B'ß?'f|'}'}IOIOIO'N>+ XtW:&|MXt Xt,َ[Q=V|lE[߿r'?|7+a*s=m_;#\{^iw^7how{'GY;{ڥמ?oNs[ ə ə ə əox#!F7Br&$gBr&$gBr&$gBox#$gBr&$gBr&$gBr&$gBr&$gBr&$gBr&$gBr&!93!93!93!93!93!93!93!93a9vFX΄(Ea. sQ\6#ve]a. #Ea7c(Ea ’',y?awQݘ0_*Wa U|0_*Wa %2Wa U|櫰a*U˟ X<0y,ca X<汰;x 1ca XnX<汰n?R(nư[c {Ü洰$œ09-,ޢޢޢn{[0EܘqCc w3FqgKD '#N:Gt81¥wF4b!bcK#\҈_YqcjK#"R.⾬""n͊g]wFܕqWj]FqcM71FqcMg#:Fu1bc^Lj>y#|Gp~#n\q1bcč#n\ADDDܸ'-ňi7.FOq1bZ)wDqKDzg#Ŋ8[q:E)yN#r;n[Y"*eḎDTʈi8gq_VČJČJČJČJČJn uc@ԍQ7DqQGQEqQQgzCzCځ+8hT Ш]Q5@jFkU4=!dt訓Q'NFG+ N; N;x:u9s稳Qg>GKD7jOoT ШQg,GV fn fQD>% qCCC]QDu3@Ծܨ;jF U4~Q=Q{tF΍pT (Gy8}#QoQzz7j{]Q5@n Q~Q5@jFU4fbZ@Řbns'@̝1}Dm1(ܣS46Ř1o21T1T1}D~7!w{yŊbabvܘ>f'|!f!8=1{cǜ9s?I1w*Ƽżżżżżż̳1CL;1C g g g g g g}1iܧsFN1oA1oA1oA1cŜ93w3w;1Ɯ9s?})\[SLG1cNc̠Ɯ동G93G1T1=E̛UL~s/G~{9b刹#^{9b刹S1fo|̝15@c1}GL И#y/bbz7;:bv>Ř]1 c*T$Y 좏E>f}q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q 1`q &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0` &0`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I &1`I 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0` ) 0`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i 1`i f ]wegЗA_wqgggܽ1۟qOƪY]wqgTɠ/c,c?c?c?F 3n`0 3_geeÓvq{pgq{pgpifpifpi++k+k+k+k+k+k+ksgԣɨGQ&MF=Մ۹3nθ;v۹3nΨQ:uF댕3V2n$X_˸8^ r3͸; r3nθ;BMF 5fAnƊ[+nfΝAnfΝAnf+Anƽ"f+AnfѝQ:uF3V12V2V12nXȸ'c#fU r3n 7 r3 7 r3V.2V2`3 6NgdZZZ4k=.k=.k=."4Ьیͺ8Z xĬۼxٕEb*vVou*$THYBĬYkYkYkYkYkYu?VVx1,VVVVVVx7ͬ~37ͬ~3O̺;{κ;>1OĬ-Yg[VzƬYcVMϬ^2k/k/k/k/k/k/Zz0Z˺|Ή9'sNx|Kڲ=ݚmhږ'ޞhڑLٿ J+jOGYcW~ >m?w6{?>S~>S~>S~>uѩ$O$y&S7I99uc#OyS7FJSzN?uѩn1:UME9}w)?S;@N9x5@j-}nsK[>-}nsK[>-}nsK[>-}nsK[>-}nsK[>-}nsK[>-}nsK[>-}nsK[>-}nsK[>-}nsK[>-}nsK[>-}nsˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-npˀ[2 e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2! e-Cnrː[2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#nqˈ[F2e-#n93~83ugǞ=3{gpg?rglxxxx,뙊Bg* (te({F3ʞQg<3gW(uF3JQRgj t6Й@gjQly33gj<(uF3JQg8-h1QgS?#3>0g5L?gß|VWguE?sgn̍f?>W\shy霗y霗y霗y9/9/9/9/Y|QuQuQuQuQuQuQuQuQuQuQuQ?9ꜣ9ꜣ9ꜣ9ꜣ9ꜣ9ꜣ9ꜣ9ꜣ9ꜣ9ꜣ9\s5,>W99.hwA ]v.hwA ]v.hwA ]v.hwA ]v.hwA ]v.hwA ]v.hwA ]v.hwA ]v.hwA ]v.hwAK]v%.iwIK]v%.iwIK]v%.iwIK]v%.iwIK]v%.iwIK]v%.iwIK]v%.iwIK]v%.iwIK]v%.iwIK]vWhwE+]vWhwE+]vWhwE+]vWhwE+]vWhwE+]vWhwE+]vWhwE+]vWhwE+]vWhwE+]vWb:_zk_~ϴWoh? g̑X!m؟Ͼ~\h/W_iSN{}=jXMCk?k޾T~oO_h_?Ծ8|* ____t ۿ~⋚h_z+_hŻ_Q hx5xk<^x5xkj^SԼ5xk<^x5xMkJ]SRה5xk<^x5xk<^t5]rMk\x5rk<^45xk<^x nhwCv7 nhwCv7 nhwCv7 nhwCv7 nhwCv7 nhwCv7 nhwCv7 nhwCv7 nhwCv7 nhwK[v-niwK[v-niwK[v-niwK[v-niwK[v-niwK[v-niwK[v-niwK[v-niwK[v-niwK[vwhwG;vwhwG;vwhwG;vwhwG;vwhwG;vwhwG;vwhwG;vwhwG;vwhwG;v=iwO{v=iwO{v=iwO{v=iwO{v=iwO{v=iwO{v=iwO{v=iwO{v=iwO{vh@=v{h@=v{h@=v{h@=v{h@=v{h@=v{h@=v{h@=v{h@=v{h~2vv?W'6vx| _wK;{{^ihow{+yo۷w췟49]'ҏ3>zG=g|􌏞3>zG=g|􌏞3>zG=g|􌏞3>zG=g|􌏞3>zG=g|O3>y'y'y'y'y'=g|Ϟ3>{g=g|Ϟ3>{g=g|Ϟ3>{g=g|Ϟ3>{g=g|Ϟ3ط=r/-bDbDŋt}+El/F/׿ݿ%WG}%OE|kڡv=~֞k/+_kN{}_}>k~\~3g_iw'f/n6{1'bNŜ9To?G?־/>hosc/⾘x/Βx13"_˛O޾ook^T/REhEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hEc.sј\41hbo ͓7ON랸srɉ >'*LT3Qgτ'{"'8q'xO3{"'n m;'*LT3{$ń''n={b.$'nIr&ɉ$'n3 oOx{ޞ'z oOx{ޞN >|&*LT3QgbN;'*LT'|>qoĽĽFNh=ڄ'?Qgȉ{#'X7r{#'={bĽ|&3qoD{#'*L1Qg >LT hbĽ{'~O={bD >|&*L3{{'*L6QgFN7rD >|&*L qVɉ[%'nUr=3S NL홙qԞ=3S㬩qTnO홙gMVYSS{fmMF[Shkj5gfjԞ=3S{fL홙33gfjԞ=3S㲩qԸlj\65.33gfjԞxmj6`j~=3S{fL홙MqS㸩33gfjԞ=3S㸩] Sv)LR33S㸩qTVOe8nj]`j]`j]`j̔O{*{*{-3=㖙ĞIĞIĞIĞIĞIĞIĞIĞIĞIĞIĞIĞIĞIĞIĞIĞI$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$Lb$ 3=3=ؿ/戜9"{.{.{.{.{.{.{.{.{.{9\~\~BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/BZ/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$BB/$B/dB/dR.eR.eR.eR.eR.eR.eR.eR.eR.eR.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.Rr.%Rr.%RrZr} ,]9r} JA_9r} ,]9+gWs%?WΠ.\9+gWΠA_9+7D_9r}$I+'WNJޮJޮD_9r}$I+'Wv%oWv%oWv%oWv%KWND_9r}$I,]ҕ,]ҕ+'WN$I\]9+'WND_9r}$JrD_IΕ+ɹ+ɹ+'WND_9r}$I+VN$I\9+ɹr}%9Ws%9Ws%9Ws$I+'Ws$JrD_IΕ\IΕ+ɹr}%9Ws$JrD_9r}ebebebޔ+'WNP*3̯r]_WIU}]_jWiU|6_Wծv*7ʍrc5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_}5x_q7#ooooooooooooogY6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6`# 6 h$ 6`# 6`# K.K.K.K.K.K.x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-޷x}-````````````xgy}K[-3rUA}}ˁS?c?g>jfP_͠_j-޿} R{+|/C_?O߼>A 16MjSڴ6'%mY[ўnM[6MmK{=m_;#B{JS\|iڟoTO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'U㓪Ij|R5>TO'+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“+<“5d'kK*c9CfV5}F|gk/b3YfMs_y^ǣ75}yM{'=[.{u Chxسx?ãx̞ <4yx /;+W^6=k|hoG޹]^ۦk^ni?|l8ǡvvv~^5?sc9䱙q!ƽ8.`|lV_{lV13<6|l&o?[qVc<p>6 c3iso nM>is禙M/is nbn4is禙M3z{1xOi>;?Gp͖g\7͸nq47_􋃛Sfb7n4iv9Ms`7n4iv/n4ivӼ<'~dK7-&C|`ZՖfOg8U9+S[V8v˨lc8vcLmYڲ&Ů[Ů[֤ImY-=mW7mW}xسx?ã׏ <4|xɞ/;+W^6x߽koG޹]^ۦk^ninnY]ڲeuiҖե-K[V.mY] v gR;hm{iviviɖե-sź[ź[v+햑nmq3ٲ%G[r%G[r[ [ mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_mjW[Ֆ|-_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|u#_WG:Ց|ucC{6?~şWp *+ڿ=`Wm-_o_k8%,ڇ?g?O~Gs{;xOi<08+>?_zdCymm^W5I,ak_z xW]+W^vomw!>KCva~<<<?S01{(`12mOԁ=OjZ?'uivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivivi&4 5MiBMjPӄ&4 5MiBMjPӄ&4 5MiBMjPӄ&4 5MiBMjPӄ&4 5MiBMjPӄ&4 5MiBMjPӄ&4 5MiBMjPӄ&4 5MiBMjPӄ&4 5MiBMjPӄ&4 5MiBMj>O }?;i?-_xcşT'Cw`Y |_y w]|C?ϽcvOI< ^M g/k@{ 1^s]8ILc^?Jdu֑øGpmmv tgv1U;2VĄv IW'5:0(Ѷ=g3k__r?_ye|z5I,a_1<'$x/y 6x:nDS= fp7^Qƺ<祷= +++++++zBЫ'ooooooo۫o~+zHooooooooooooo}'}'}'}'}j'}'}'}'}'}'}ۧj}֧j}'}'}'}'}'}ۧF}ӧ.}'}'}'}'}'}'}'}'}]fn>p{&0f Gs1紟0n7C xN/q=8C=kz6x7گnpyv[6{>!~a?#1{;'$x9<"%{l\:p6n-w.~aK_ږC|>*+XM<^nioĶf]nvqf]nvqf]nvq{'0~ Li3ڻp{♉m ƽ8vҫoӫ4nm 7nNW=X֞8=~1pZYWn^qy~g~g~g~g~g~g~g~g~~~~~~~~~~~~~~~~~~~~~~~~~Y1FOg0yv0;,1紟}4 |F7Pܸøhz#8%,{?g?O~GsxL8x O< >"% \:>o-w.~K_#| Ycװ˜W[0Obm=ڽ}۵XqaĸCv7| wXgaeuYvXg;ҁz67Zl36p\1Ya$Cv0~;vr`D3V="|)xwƻ_ȫړe|ݞyq<'3x֫i xm.Wp57x o=}>m\:O;zNhgU=؇8fpO}a܋#8f*mg;Vٝ.m8 ޥ{@nH`t@nH3lÀω9>'pω8 8 8+h: 8 8zE+%2o[6{>C?Þ?#%\x romcw K 7-~ul`[Oأݫݧ]_{@<i^\|a܋#-4>B>$;Z?+O,4XIvpvgmB*ÀQQOO!==K%Wg<AwP{m0{]s]s]s]s]s]s]s{}^kxox'7;]g+p#}5Z5K؃}؏G r w r`O` 42h&dLȠAgylyl0 óz `.O4ƾ1q20-*` Wd$+&Y1ɊIVLbd$+&Y1ɊIVLbd$+&Y1ɊI+w%Y1ɊI*_%~d$+&$+&Y1ɊIVLbd$+&Y1ɊIVLbd$+&Y1ɊIVLbd$+&Y1ɊIVLbzfRLbd$+&Y1ɊIVLbd$+&Y1ɊIVLbd$+&Y1'Y1ɊIVLbd$+&Y1ɊIVLbRNbd$+&Y1ɊIVLIVLbd$+&Y1'Y1ɊIVLbRObd+X1Ŋ)VLbSb+X1Ŋ)6ߦX1Ŋ)VL)7+X1X1Ŋ)VLbSb+X1Ŋ)VLbSb+X1Ŋ)VL{)}/Ŋ)VLbSb+X1Ŋ)VLbSb++X1Ŋ)VLbSb++X1Ŋ)VLbJoIbSbŔb+X1Ŋ)}#Ŋ)VLbSf4+Y1͊iVLbӬf4+Y1͊iVLbӬf4+Y1͊iVL]i+͊iVLWi*_4+Y1_Y1͊iVLbӬf4+Y1͊iVLbӬf4+Y1͊iVLbӬf4+Y1͊iVLbӬ3zfӬf4+Y1͊iVLbӬf4+Y1͊iVLbӬf4+Y1͊i}8͊iVLbӬf4+Y1͊iVLbzuӬf4+Y1͊iVLbZ?ObӬf4+Y1͊i=?͊iVLbz~Ӭf4+fX1ÊV̰b3a +fX1ÊV6ÊV̰bF7fX1Ê7ÊV̰b3a +fX1ÊV̰b3a +fX1ÊV̰bF{V̰b3a +fX1ÊV̰b3a +fX1GeX1ÊV̰b3a +fX1dX1ÊV̰b3zK3a +f +fX1ÊVV̰b3a]L.VG`L.3!3,y]yi?!~a~ q<'3xyq/eg .U-o-w#/k@k>UgQ{ W \&c 7":.37{{kkALb Ә]!wery]!wIm6ي̮m].+2''z]aϒ,.wz]rKBwInmfr!A޻y{7o6?nk4y{wN||>̻y73f̼w3nC_{>"%\^kx>>?".g1z7W\lnF6ۊnջzw1Fwmxx75LGP\fy5˫Y^jW,fy5˫Y^jW,fy5˫Y^jW,fy5˫Y^jW,fy5˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f4˥Y.riK\,f3˟YÜ{x1Ð{8m=VX c5p=F{B1 c(tw=ܵXcn1c=Ɛ{!0̐o yCw>yC2rCbQ 9!G1(ŐrCbQ 9!G1(ŐrCbQ 9!G1((|N9e!w;a8cvÎq1;a8cvÎq1;a8cvÎq1;a8cvÎq1;a8cv{^GuD{^GQu{^GQu{^GQu{^GQu{^GQu{^GQu#j1#j1❏x#w>❏ňZ8G1(Fňq#bQ8G1(Fňq#bQ8G1(Fňq#~j1#j1#jϧ}>f_ Gf=cs>U8n܎ӫw{s>W}•7>2øGp61{{6ǵq|Ͻd\ml>W}\g̲/ ж}\ss?~^}uŨYQwY5j5j=QQ߃ bxH٫^~Cq<'3xyq/e .Uwuomg?>Gc.zd p={{{=7s=7swEzU 3g;GC_ j^1{.`9eԷF6j6.Q59,ԋӨyQ5{9j2;;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;9αwsc{;oda^3j^}%zkkhG111U0̝c?1c_Nb ˶;yCǏ <4xx>/{Wp57ϛx o>>wY5\x]؅ ׅ1ׅ1ׅ1ׅ1w....}8øGpԖcPbd:::S}aaaaL333 =*T~5b5b5b5b599}99}9}9}9}9}9}9}}}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZW jA_-}ՂZWq}u\777777ͦq3fzfӸo6FF{Ǎ'}i|x lI׽7i!~a~ 1{>'$x9<"%H^kxo&xߺ>>oy{vQ{ Wn[S{]4n$?n$?n$?n2nvdȸq#q3fnǍ@edd\Rƍ@eܷ܎7s;nvx1ƑqqqI7q9mxxxܷ} iܷ} ()Ef.JJ\d"3E)(2s\d"3(Ef.2s\"3Ef.2s\d"3Ef.2s\d"3Ef.2s\d"3Ef.2s\d"3Ef.2s\d"3Ef.2s\d"3Vd"3Ef.2s\d"3Ef.2sQ+iEf.2s\d"3Ef.2s\d%`3aw͸lƝ`3q'،;f͸l܌:s匞9㛧3z挞9㮰=s53ϕ3 ߮rwfə$·|}~!~a~ q<'3x;^kxo8қx oGz>~5~wXaױ3>?w͸le3.qwٌf]6^wHČ{fbƝf31~go6~͸lf37qٌoH͸ljڌXMi3r4D`Όf$h]g3r4޳g{6{f|[jg|N9q!Xw ұghAh4-HBHS38aL98o````fgggAy~!$+ULb_Wķm|}_k ſx <4xy .U[x]x /L6k8W%~ǿ);;{q<'3xy/82^_:x o7_=c쟳>+鳒>+鳒>+鳒>O:39L:39L:39L:39L:39L:39L:39L:39L:39L:39L:39L:3WRWo%[I6JoGo(-?cxOI< sx/E'g= %Wp5W7&x x3^8 }pnc|xīsG<SxY<^<^x*^xo-w.~KמּbC!8bCg#<ÿÿxOiF̹*͹*͹*͹*͹*͹*͹*͹*9s39L9s39L9s39L9s39L9s39L9s39L9s39L9s39L9s39L9s39L9s39L9s3_okߴaڟh}4gߏ/ ,೶G1yΟ//v:[˞}E7G^Nb m7=?0~ yOI< ^ˎ .Uc6ޱ޳/k@ko[5[6׵[gu0OS}ϒݣݫݧ]_{g|o3Nkgwg>{<;øGpmF-=pgu88]8x 7%T>ΑVqbhOwE*p50__H?oE;fqvW/;oPO?3lSۏb~N|~ /ER{p_ȯPE=>,Ź_ER{B"_ Gq?^W|QLgKeϾnohٷm|}'=T{? $0W a܋#6u?ڦWoӫyVɊqblEy{^e<W'F)aqe*5\ |ZNm =GOE<?_~6fx6fx:_v9SxY=篟 xm.{'Wp57x o=>>p_\5[F$>ͱOs۵=؇ӳ^ %_0F>ͽOo:ۮ}Oi"Z317b,_u~,$⯟EZmm^W5I,ak_z xW]+W^vomw!>K$⯜E&)>ǝq?5^,rq/(C$= oTAffi~,WӼ4y5ͫi^MjWӼ4y5ͫi^MjWӼ4y5ͫi^MjWӼ4y5ͫi^MjWӼ4y5ͫi^MjWӼ4y5ͫi^MjWӼ4y5ͫi^MjWӼ4y5ͫi^MjWӼ4y5ͫi^MjWӼ4y5ͫx@`wz`~xiC 'ygs1紟ׂk~e jI,ʛ{?g?O~Gs[ <4?^y+W^6~_jJ7Ыy{g~Q{ Wn[S{]>oO}ޮݯ3Vܧ$0܅Yo8P/ݦķ^x@`ķ'oC e wWž<`V䀱c3B?| 'pKXKxo-w0!0B8`pH@8WC8{qGq \K84a\7ׄqD > >` &wqi\D %RLLLA WJe|;|ķm|}<ۇ~= ~G3<;Kڗ+W^&xۗ~o[&Np >O q>6WO{vNxui'L{ ƽ8qfµo,6![-p\7c&=u%D.pZ;LVNĿge&\+'L0o3af2؍=_gcIIyI~;ingҜIwR{'I{YI@f&M4 4ih2[%x*^x;6N=[_ykY8;4K4K' N48GM54k4ihIsG&M;4w4L$M$Mp T H&}vRߘGSd 7&}Ν9w2[` +XĊ%V,bKXb+XĊ%V,bKXb+XĊ%V,bI*]%V,bI*W%_XĊ%Ċ%V,bKXb+XĊ%V,bKXb+XĊ%V,bKXb+XĊ%V,bKXbŒY3KXb+XĊ%V,bKXb+XĊ%V,bKXb+XĊ%V,%V,bKXb+XĊ%V,bKXҫKXb+XĊ%V,bKyKXb+XĊ%V,%V,bKXKXb+X̊eV,bˬXf2+Y̊eV,bY-eV,bzoY-e̊eV,eV,bˬXf2+Y̊eV,bˬXf2+Y̊eV,b^Y+bˬXf2+Y̊eV,bˬXf2+Y̊e=̊eV,bˬXf2+Y̊e̊eV,bˬX[ʬXf2+YoY̊eV,bY(bˬXf2+NT]`.혂 l3TgYcԩ lyi?{N2K?M:M{Snvٳ;7~ w]|C>ďc'$x9<"%\:ްM3sp<}hCG,j/ ֱkulFϧS>N|:-0~>أݫݧ]_{bS Nd:-pԖ6өmϧS#ϧSfO2K?e~Jfdv*[`LT_`_FNtJB$ c4'М˖9y o43Ad˖YHLAf> 3d|?2<^8lsߺ xug#k]\}rAsͽ4~ArA>/[i0z 4~0eG˖ӑ*x0e`W0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[aڊTa V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[a V´0mi+L[ V´fififififififififififififififififififififififififififififififififififiVififi~Wyus >z|9Øs 997"[Iwɼyn%_ 97p'=^.y w]|C?ďcfoSxY<^ydϗ+W^M=/~+|_|oG^EpiG-x<y^wɼqEr>*E`J;ޅmLϹøGp׎[z{N9v=';yy-+'Ke)<_kdq7+X~0 (k?x 1ƴް/>by!8K-/{xիyM{'v 7-|w=|yև~= ~G3"vvO" ! `D$dT4p>pp!pp1p9pp%pp5p p-pX ,vN.nhx? OOµ@> <5gu M-m߭ r@@jc1lll\ pU * W 1@PsCAlr[[x7)3;!@ !FDyb]`4 0D%0 S==>`@ "<N '''AyEe`rWWWW777wwwwxCQq I)iYy5u M-m{P*@u4<" ll6췾[$3? ` L@~D"Ó-%ȭ@NB=x vvD; 5AN}~pUg<8 88 ]VWWW777B@  -CˣPsxjN|xj/Ps[ -DPpVYA J?(>ivflf MD4oh"DllkE _@<gre/e/6/" { A=%Kd/!^B { A%Kd/!^B { A%Kd/!^B { A%Kd/!^B { A%Kd/!^B { A%Kd/!^B`_`_ { A%Kd/!!^B/B { A%"KEd/!!^B`_`_`_`_`_`_ { A%K|>K|>K|>Kd/!^B!x{= ^/ ?aaaa00mb{b{b{b{b{b{b{b{b{b{b{b{7 = = = = = = = ~ ߆oa0mb{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{b{|8 >!!!!aa00pb{b{b{b{|8 = >Cl!!a0p|8 >?Cl!a0x{8vl h,u&8`'́--I2]Np듇=@ g{ r`@ `8;I)irp>pp!pp1pe9++kk M-rہ;;{^>~A!a? <<< 4 Ԝ^^ׁ77wl  @ QAt۳m? D r=ol6q@a~ ǎ%Εkn,b`4 0v ʄ]e®2aWLĎNj~r'G f"pp2p p*p<8 /WWWWPx4^^ހ7Amز @>kh-`y8[^5, * WȰ&@nl6Mh~No?Dlr[[YJ}@lߊEߍErm2A"[}@ DQ'wQ~cOC='ד{Ц6fC>z5ˁ++kk}p#pp p+lcYhsx4^ހwlo r@zM`)`y8[gkZڴ0/o lYy%iG/_c"EtG1`jx|#Xy#3?rd# ޑEqdLj V]OF=timiAdyAy`-㘆}Ȩ #X'pd 3ki, :21"֗YY:hAl]E)9 dL5$ FM$f-hSRH?4=eAr9$+)z W63@ xm Wz?ա \ ɖQ亶?@n`7b`9Ă ?XrL 9ܬTB̏z 7`< sC}·`yX b^t5İD_Ofݸqt}1X`3`ͨƮ r=_A^;n5FaTv!+@ \tb`M.XXG#BcnKS|,+acWsJQ ضc#%Eg.2/.: ՌDu Ѻ4A.t@3kKHeØ&M\]휴Ǻa}P !MCChPpIb6RTFjG0u:2j2Uδ6B#yyYy 45y҃FȜL4yq*ING=" {J\Ot9-c\X-Y6Du.c+3.AiOpP7,jGecݛݧ̊ ֙w"F>{")G{th4$ye. XPX6-ե%ŽnM{c{`FEcc> ϰj̥mm7} 1y'̂Y}^p6٠Ը9 90ipFOOU*V,' hTT3:#z`d%۫62~ Kd~/;8'`]Og;;ʶ%۾T"Y>FWEMo[߼3Z{Ϊpv^lCg'7tfDrϲJXbCA3g-HD3;vf$t| mzg̞10>Tk=N,#KQ8K8lݹ/2e}#ǑpǾWbEi}J]d5)^KyMN|/pVX+EDFߣ>,:2ʉ(~gF.=%D4xHz0濙s{{Ѽd;o:͗~_w| BȚ>3.RRkX{ݴxm|(ux-h7rQ?qA+ 1-?ʬSW/7 |ͅ*˗B$$v'p1W;Gw \ޠ˝w2c #l <ߝQMwu{Yb=1P~H'i)VV߅]|:1wu Y~w=gpyl_>F6 l7'Ǖq<9]_ pK+[e0ۇzFz"xss[4;/8ƶkr}B]:N-woWJ^W^tIѧWx̄@ 94hȤ W{-b;FN?gr|yY00ټޒȲqaԨQO?)Dz4j I |ONG՛q0-jK/ /M϶<kn}\44s|&޼Z}'3|H`) @ANЋe+ 龑qzߞl((~dHw7&MHǨ1ܕZ12^-1P zI}f))l-xKR{ؗr{]C^td6ӓx Q0L/obYqnY3p}.tYF\jdPŨ6T[;ՒKc1C}C"3 t־bT%*LZ!O}wGB*i@41pm?8*BO$2p}ؖ:R1qs0S0030RXi V+=*`JXe4UX5:VB`uzR#x Otb8) G}h> GD, },KA% (if;JznQ>|Gbyl(Fl6 `l[%l"6=Il*Naװ{Rl=~b˱Mا1}4,4'N`gSgi4י9s,Z_Wؗy?`?bzxew:RHF"%+c^vaa`/cWOn9O/\%\ *:n^ /x" W]x*^ kx.^7~. Fxc< c&x,7śxs[OxxGی}wx' }mA`|<>wix:{L< ƽ0|8s<܇}}#p?x>cq+xU|O'S4u |:&>gs<|>_/oKw2]=|9_Wk:|=߈o?7[6|;߉?w{>|?~?G'18)~??Og9K<~_/W5:~owoB__#p H"h!X#xB DB"dB!TB#t L"J2DYQ@T$* QJT#5D-6QK# D#1ED1D"#͈x9тhI"ZmDюH$d"hOt :D+эN zD*чK# b01xJ@4" XH,""oKw2]=b9]bױ7JbXC% Fb>Bl%ۉNbC%Aq8B%>!ljOIq8C|N% _牯 EqB\%׉MqC|K|GE]G'gqx@JDxDFN<& $"II ɒɓ)) iY,M!˒d"YL*dUYA$k:d]Yl@6$(2!dٔlFƓdKٚlC%vd"D&)d{ّDv&]ndwٓE&S>d_ٟ@$ayr(&t2dMz!sr?y5S*HP#Qhj 5zzGLB^&PIdj 5FNAMޤfP3Ylj5GͧP E[bmj ZFKG-VP+Ujj ZG6PMfCj FmvP;]GnjGPSCau:F>NP'Sgi 9u:G}I.P_SKe uF}C]nP7[m-UHQS?Pw_{}+Ra;zBc4N4IS4M34Ks4O HKL+JkNI[t)4].Kt%2Ujtu]Eצuzt}ݐnD7h:nBqtSO7[-Vtk ݖNщtLtGݙBwtOݛN}~tz=DCh7FΤlK9t.G|zt.Gңz,"=~~OJO'ғ5z*=~~NIϠgҳz.=O/ҋz)~~^NWҫz-^Oo7қz+Nwһz/O?҇( }>NJOҧs,}>OE_/җ*}Nߠoҷ[;.???ӿW:D?#7w1'!aQ1RLi S)<ǔg*0JLeTa2՘L &Sa2L!ӈiD1L ӄe☦L3&iδ`Z2L-c$&Ia3L'3Ӆtc3=L/7a2f 3 ag2/0n&Ig2d1ٌ gr\&1 SdF11XE%f2 3yLd&1)kTf:3ydf19\f3Y,d1o1%;Rf.YdV15Zfld6130-Vfdv11=^f9|d1#Qs9dN113Y %s|\d.1+U sdn1;̷wL!S|e~d~b~f~a1̯LyȄGocO/ 8K$K4˰,˱<+"+2*:k&kl,[}-V`+ʬVelM[elCۘb ƱMfl<ۜmd[6l[6m&Il2¶g;Nlg ەvg{=^lo6e@v;>e_`lf6bY/;氹lc AɎbGcرK8ev<*;Nb'Sة4u v:&;bgsع].bboKwإ2]=v9]ɮbWkص:v=nbg?`7[ح6v;b?bw{ؽ>v?{=bGأ'18){=ɞb?cOgٳ9K<{^b/Wث5:{bowoBc_ _pHhXxNDNdNTNtLJq2\YWU*q9WUs5\-6Ws \#1Es1\.r͸x9ׂkɵZsm\׎K䒸d.ku:r\+׍zr\*ׇs n07{ʽ4.<\&es^n7rp[mvn}p{}~1w;pGOcqSw;}Ɲpsg/sܗy+5w]pWk7uwprq\=wpr!!qqs??'<<<<ó<˼«ŗKe|99<_W+. _Wk5Z|m_ F|c>c&|,7|sߒoŷm'| ߞw;.|Wߝ{TߗA`~0~8yG~>~$?͏//W~"?O_7 ~&?~!_̿/w ~%_ͯ~#o~'c ? $?͟?_/Wk"_o & "{.#3 ?CC>?OLB JF`NAIEPMC0K(%ersByPQ$T\BPM.j BPO/4 B-MX!Nh*4B Jh- B;!QHA(t: ]B7;B/* a0H,  /n!MHQ/![ ÄB+ >!_! (a0F+($^^ $a0ExM*L^ o 3,a0G+ "-aDxGX*, +*aFX+ &}aE*l ;.#aG+ !pD8*|" ')3pF\8+|! _ %pE*\ 7-pGV{pO/<~BC!,<~~   ODLEB$EJEFdENEAEIEETEMEC4EK,%ˈersbyXQ$V]bXM.kbXO/6b-ƈMX1Nl*6b Jl-ۊ b;1QLA(v;]Įb7C){bO/yqt1Cb-zap1GD/b@ Hq8Z#__lj/W Dq8Y"&No7Lq8[#BqX|[\"#.JqZ\#׉ FqYP"nNq[#AxX<"?OIxZ<#~.ω_ů ExY"^߈Mx[#~+~'E]G'gx_| *ćbX|$&.>HKDJDKJK$J$Kb[&w{mvdaCkR)T II RETYraHUR5TC)ՒjcRTO/5JRWb&R'5IRsRj%Hm(%IR^ u:I.RW]!zITW'HA`i4TzArKiR!yL)Kʖ0i#JyOʗFH~) ,,FI1XE%i4^zU M&I)kTi4]zS!͔fI9\i4_Z -IoI%;Ri\Z!VI5Zi^ m6IKH-Vi]!vII=^i_: },I#Q6]:.}*NJϤstNR:/}%].JtMF.ݐnJ[;P*~J?J?I?KHW)$=#7wDd\&dRdZfdVd^dQdYVdUd]6dSRri\V.'?'+Jre%Wr \K-בrHn,GrDqrS/7[-Vrk Xn,'D9INSUr{lA(w;]r7["{ɽTW'A`y<[# 4l.g`GΔl+9r'|yrP.Gʣy.*Oʧs|NR>/%_/ʗ|MF.ߐoʷ[;P.???˿W9$?#7wD\!RZaV^QYQU]1SRJiRV)U_Pjf5SRU:L樹jS_ A@RGcԱK8eu:ANR'Sԩ4u u:CRgsԹuz@X=RGԣ'1zB=R?SOgճ9KzAZ^R/Wԫ5zCRowoBH^AS_ՐP _ pHhXxMDMdMTMtLJi2ZYV^U*i5VEUӪk5Z-VGk Z#Ek1Z-VӚjʹxBkZkmZNKԒd-Eku:jZMzjZGk m6D{^4-]Զh[mvmSۥ}h{}~vP;֎hGOcqSvR;}hkg/sڗy+vQ]֮hWk7uvShjiZvWQIYEhj!iik??':::::󺠋˺뺡Kez99^AW+.^UWk5Zzm^W Fzc=Jc&z7՛zsRom'z^w;.zW]{TWA`}>TAwiz{L=Kֽ0}yOG~=}>J//W}>IO_ӧ7 }>K}HK_/їw }J_}I_@߬oѷ}KH߭c~H?я ~JL??_/Wk~I_ѯo ~Kѿտ "{~O?CC=?O ʠ `  ɐ P 0 (e6ersFyQѨdT6\FQͨn0jFQϨo40FmMX#hj43F hm1 F;#H2ht2:]F7i2zFo 0yc6Ҍt#Fmxap#5 o0FHc1c5^4^2/W Dc1٘bfL5oӍ7Lc1ۘc5BcxXbc,5ˍJcXc5 Fcbl5ۍNcc5Aq8b5>1ǍOIq8c|n50_獯 Eqٸb\5׍Mq۸c|k|gE]G'gqx`jFxdfn<6042IIɚɛ))iY,m1˚fYɬl*fUYݬa4k:f]Yl`64(3ڌ1flfƛfKlc5vfd&)f{dv6]nfwe6S>f_`4!Pmf13,3fk>3à4 ̑(s9khd3_6_1Ǜ̉$s9|͜jN3_70o3̙,s9ǜk3 ̅"-s|\j.353+̕*s\k3כ̍&}sjn3;̝.#sk3̏̓!yMyۼc~k~gE]G'gy|`j̇f|dfn>6042X[EZE[Z[%Z%[Z[eZU*mZVUɪl*VUUݪaմjY:V]Uj`5Y(+ڊXVjf[ͭVKjcvVd%[)V{duX]nVweR>V_` Y!PmYV2,+ZìVkY>+a (k5khd^^[Z$k5z͚jM^ް[oZ3,k5ǚkͳ[ "-kzZj-޵޳[+*kZk[1ٞ<:כ1ތ _Mu<)4gqC&|y;R^zAnfgLQWtO^PH*2InˌHwdGQQBH~֑&;fx"%ؾQY%j>ݗvJJL:T610^(؎HH:FFL]Gfo$:v"N%t {&KKZ5oY~'/ǝMg & Kv9%. ʁFO 0"EVw\(yYnAn (J1"6#6*i "6#EU(%1LR=ޜ7t&5ry02RYʂRqFSOd4P}޼,o#+(yq-JX9<< q,g;HyQ;eSF;eS6qXsʦN)2)9eS&9eSH/$E*#xGyQOr'9I$G}>QOr'9R"e3dG?џOeG6xV lwgK&;ړɎdG{=ўhOq8Sb~OW,Q/$ؑ"OE6!9R==dGd3zn)2)cS:eS6uf7#-'Yc*RIN씑r r r r r r r j*.% N)KKKKMѱbЧQt?͜2)=юhGO'qF8qL 4xa;Xb;#"]Ge|t 9t>:îOzF*)p]-j{zɰlTPbahX+z$(bȵX?Ҟ@-Y9 @ЗzdRrPO0=[NCuxӇȎDSxP1 =x*&ߥ=nZR'Cd1֝D1@`2`LD0@|>#xosvn ξLHaK"3,R#'3@@k\Qb \ߛe(N҈_c;):3Uz;'oS*>/+9O_<-f3ѽ a&͝>~`s|쯅vFwomIJ+^_#GFKQw"WG8h(H$>AםUF.Q6*9J(Td6? `!ν?:)%")b43h&X3:wg#8X[%:Jv|/='#v2h'#v2h'#v2h'#v2h'#Nq)]0Ź;At)G?џOIa3%%gtTZDՉm@2w{$HOo@R/4_Dk)jtc9n,7 GV/<_ _IGd(JesV ҄H75<#Pmgx~#HxJ`k6sǺ`ʠDQSia>9g?yIPYPĮ}Sz;[ zkx~pR A54Cx^gF5{5Zѩ©IOM, ڧ}"hJp~\ `-@еL\4s]/A׃}: _40H9PWC5-_@fPmА]\ w8Bwqp0TC+ۡxCwqs]<k+?L:Xvn57:qj!II;t#:D?էiD "HR D]$N9& \#L|7C(]AEh#t&6xjb㩉&6_xxbቍ'6xxbቍ'6plXñcc ]Pl<@Ş 3PlJZiwgz:YWϨfv=Ya;M!=bko.٤Ff۩`]Qff1-WzT u2Br \sf! U<0F t!GXB!e89ρs?9ρs? G zG zG zG zG zG zG z~={~={~/|< c @6Yda @6Yda @6Yda @6Yda @6Yda @6Yda @6Yda @6Yda @6Yda @6Yda @6Yda @6Yda @6Yda @6YD!a ,lcaϏ=?XcaϏ=?XcaϏ=?XcaϏ=?XcaϏ=?3L~>}/|B aaA"!#, ,"C8C~QG% ;;;;;;;?VY[eaoUVY[eaoUVY[eaoUVY[eaoUVY[eaoUVY[eaoUVY[eaoUVY[eaoUVY[eaoUVY[E!a^+ {,쵲^+ {,{,칲BcV[YoE!a,쳲>+ (?cUWY_eaU{,쭢Vea[mU߁Ƕ* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Caaa a!Y ,BECGX@XFXAXEXCXG*ூ *ூ *ூ *ூ kுkுkுkு:௃:௃:௃:௃/ _`/Y+1_e'(FJs RPKm}-K=`;<Ã`;<Ã`;<Ã`;<-i eA\vă`G<vă`G<vx3M¶4˃9`N<ă9`N<ă9`N<ă9`N</'ʺQ`T<FŃQ`T<FŃQ`T<FŃQ`T<FŃQ`T<qZwxn{ƃ``<syA-} 'S?q2WH`j<ƃBAPx0:x0:xtztztztztz9?tޫ? 7QWPR(Q,?/Í` B99X;CW0\XK.C9F٤Ydcr rƻ\k<G9H)D'<,ZMo}# ^_f^߬ս^_&^(K έ> M֨Kڝ;go8{lgo8{l÷GE;d=3,JtF 2 Yئ; >5#O /T*^0pT 8 vkZዃׂby߁|X#F|x{>=k>||y><~?χ|y>:~·_ï&Ãc ͇w|n>|7(>|8m>6N͇ip|8m>6N͇iXc ]p|g>3̇{=p|c>1999wTsxsxsxsxʇcñXp|S>)wʇ;ÝNp|S>)wʇ;ÝNXfcǚ5{k>'ɇ}>pbއq8p|8N>'ɇqfcǚ5{k>}Xfcǚ5{k>}Xfcǚ5{k>}Xfcǚzk>}XVZv?uϱX&^Zܢz:~cu{>}Xn'vkNv6˦YXc*U{>V}XKs AʐYԬgڽ{k>}Xvcڽ{k>}o~F74k4BdV,Xlcrz>},8W'kvnZQ_poFA|Fl 6 ^36vu0o Ġj=Yؗ}Y48vi=~Q@yfVm YδDmrB@֘h&#rozخ{j'~ uߓ*ngaÜ*)ݪx2B!L׻bw!e݆QcV}[[ !ܑgw1זb~i&9BJu[uCʤBPr>-4~m~*Pɦ^BST# I.N4Yĝ2%OS--6.<"9Kqqml2.-:Y6B;w~;?3+->wߵQf'9PB~s@Eě 7tЅě:"~Y_ J-R$.t=)UOhJֽ^Q֘3 "ՠ .gc|f83g"s48'% hVWU* +tromg7u[^y|jɌE7ޥwPF4?vV?uk7-{scvO_>u;\:JWsC"Jj[[[[*(($J8n'd>|n9|%/ђD +d('ffQzNq;7 [ 2 VU`,X VrNxLCd`%,X V‚\ }\BG )C8Csρ?sρ?sρ?sρ?O{8a4&8[A&oHT3l$(<ft1N)cAɌz"WYtI"' V^hVn- Q'' BQ%8uIȰ;ԅztDN#)6gW.>ʭf_84Y_%JW]-Fզ044'wW! ? 44rHer1|r!-#UDΰ%2->cSp* 44v˭;jfޏ-5NFS 'ZEޓ<H>+vp_ RϖwFVͽ֦dTv Dhbšߺ9`c ib''`&ȉ}01>'_V3R90e,.e8gD#7KCNNcHw|A"> W\M}iМ偈NV2,V BQZAl'M5ᩨjDdPR8C(m+ޫ ޫ ޫ ޫ،-idc=fc=fc=fc=f#eU5uҭ{{{{{H!-[o+Ng{BÁqqqqGaay5+c3k d.<"9p6\a A4<^80+2dBZޱr",`P`A4wN2x$wN(d A Bha P  2 ,4B,k *B,4B,4lP8 AdtL/IdIdIdId B3 X dGI2*OQgl9Wy4)<$[QXT՜Q:VJ[l>A]zhT;2x##^h<9Sy4q~nGk!K%;z!,CU..pa bG/vdbBZs0.]^G,&`keZ+RR8 RST1iuZ6="8% G*Tqr##A#$6K=R /ݶj #6T=rqStWhM"j[8"iZ=.}SA4%8쒁ܕv>e L0-1T.jI頳Bq΢ae] $H#L~= +3@K\]jȭ= s{Չv]~TjyX8>N3dSm&c0I* JSAG |~i&i#LF 0 10b.`\s#Baaa .ůN4eyM{ <^m +3?lbsrM:Mhc{̄pBy%B)3YZ3mKqJqJqJrW 6B00PWD8pa P]%x8%x8%x8%x8%x8%x8%x8%x8%x8%x8%<+] JxFWJxFW3ѕ[jl %Ɩ[3ѕgt%<+aC &%LJ<0y(zcw~ofzo1U(bPTBS" EL*fzo1S(bPěE^DBofz" EGo~ -[ggggYgYgYgYgo ~6mo ~6m~;w~;w ~.]w ~.]w9999yyyy_____E_E_E_E?9ρs?9ρs?yσ}~>}ofzofzofzofzofzofzofzofzofzofzofzofzofzofzofzofzofzofzofzofzofzof:s F|0{iy֠juvfbsCWu4O˽U{bX-oO0MF"h:5|4S`9X>yVy^C.ED8_ɟFW6ŁEIq B4T[:;O7W$e@Me,a#/FۋAj J$ղdY ײ`jө2jAt;T:\ D\ `; s7+!J `+(YB0 |mKa|`4.5]nWt,BWB5E/\Sىb $RUJ`@`AZ "f=P@T!%hC BKtU xpdYCҩGJ_ TcJ"J/f-6 @ TZٚ.HB#-iaO^ 36j[ABԩ&6vǕ[DXWP2pE]lE:~UFXC[T"%D X_UeRhm2 5QHwJLFO4hIZN*tՙљxNq#$n &D?Syt6.Exo /ɛhdR к\hq;e؀&O*NT=:FM 5yMВVV`3А!Jv FrHжИVٵL[][ji#Tj)guxR!paa aUk0PY BoEkYُS+ᥠ?Y u+kHh4+<*B&9JYE^lWoE Te-%G -Xd({dKuVpTgh T]pPpIZЋh(@+ 퐣h@ $$&]Ȼ\Ⱥ!CB &fVmBTk2Og׷[?U˩GG h}uuHenIh(iUPl 6ve*0!T`K*j̯ FVd Ċ0~ 2$TT%+(]!Zd[Q@4 `}~׌Or-ʔ)6"V8JZ Z)5' tҴlNQjNp*j#UF&% a2.bDݰuIpRi*RRp.5-;D*r+*WtLyp +!=yH–S#j#m/FÑDu%P\1.N?tqH#'=0Jn&/P?|:h %j@G2Te C2ԈD+>1y+X{1NԱNZc-A1M#Yi` %]vp0R.*GFuGUIpd-#p 8F4 v9#_lu[*`)QsVE"PUyUa^eW yּwvWH÷ymXOkEYZSgSJC459#n%)7?BOwvvgQ|]TNPߺ܍XCF{Qس XqfSLto?u|pt?čpBBX\Rk)Gsi{`KnH;XRi~|(xoy>niC2G B_K{yY"{k:!;ˉDw<rB A pY'(mQ"UmUy~cŒ`Cn]:*\r gWYuz[Hse}E6ѩPf\$f#2I-KM9£[`=e1@C{l` NZWf-ެPMxR$ce+ֵzPݨZFAڄvuͺ )Ko&klҖY!(;?jeu7o 7&Yr9_ۤIuG淼[mn$wI[seJ['y['[&a|?za[ef1th w lvVJ6K 69B+;,'#"ǕdΖ;7bh dg-yKNF&I}@&hV(UVQU @^1Y#c PtI7 QwaYUZRQj9J-G.V'pzԭ6Df˳WwJ A*\srna7jP^|69L9SS9ES1|bgjo9ۋ(`l 0AZmcZmc|]yr[%lɄV [9V~'JkK:Uսcfd6x=y}5J"djV-gߪ[\61W , X-Flm3D+Gm%J앷= σDc³12("!*QzfQ=6,ls+^(qlZI7ˣN;.v3o~Q}/m_oޞ~}!k8Cw{+۷q[ۧ}!fVk{/ΗzSDRE[#2昛UE|0 !rqXTʔ^8TzC>}z9D!+B!+J!ҽկ[%)apn<Х,rzfD5KbU,6L(mL8\TX+Aސ Gʄ*T5"osnT0. 뤨}:ic̫aƹ"^Q15*W՚@ ~0ؾvj\{VWm5;n{Ŏ^UwmWMR6Zm]ݶpNmRV-'1'1RjyuFr F+E ^ \l]<*GZur#,Jw5r:ݑIZs+:#4 :&&jtdtW^@w bSzy_I5*`)Q @N T*PS@ASP>OASP>OASP>OASPeFYQVjeFYQVjeFYQVjeFYQVRVT>OESQT>OESQT>OESQT>OESQT>UOUSUTWUqUWUqUWUqUWUqWMqWMqԹpضضضضv^r)W@YUj Yتc۪c۪c۪c۪c۪c۪c۪c۪c۪c۪c۪c۪c۪cY,2 dpp((PV@Uup^Kc)},>RXJKc)}, o̘0#d0$GOQjE_LQ%?~E"j1@57JFo3I]5m/j/jnIc5>n|o~w¿0~IW[¿2"3$SyHp%R%\t _G/3"X;wh.ŸMS_e53ǾjD{fDoɈ}f·j(#;1v1;)vc'~d쑄{G/&Xp'%|E ½*sc#w1jb/'+bZk$z*v~3FM$]#?6~? ''O1⏍SgIn-™xp6O?u||D؋_IY~^_Mu7[7&I]5Qw&>Cė;50"SéWcSN}wgD?}?$éd#bnn}F<<$O#|y͋_l^L/5/%LNx7{_c~¯5_Ku|#M:#-[|;M--a;M4[[ ȼ]?i~ {{ 2ᯘ_#u넿a31͟~|𿚿&&]e7'3Ῐ1vHNTrtd*"NFxO <9y &'$&mN!&]¹dp>'\H6O}7B -Muߞ>%iŸI]'UiJ-Mt ៦JgdQv'wS?ܝM'0R17!ÿ±zwl"l1Hyq%Mk *qm1nZjغ_wzz^}9rpfȀ5bU#6#`r/zn=jFQH`aLÍG1"G8VIŌT0j32tC#Fx,#Geu8_D)[HF}N{Z33IؾzL>uf=yO9(qϙ"">^&Vb"5>.U0 juZ&{ nV>ǻĆ=|bC伏_ˊ|`9>>_w|SSmEb*3|-E ||Xɍ˒'q⊞% F%|\%GY]s9>q|I>&8ǣx$||,O_1|L1%|N K>cx4>|>8q>ac;N>>IO&$8>fG&wq'q@7zƕGظ|O_4n|o)291rJĎbF~o"GDO;2hå$g9x 3d{Hd! މ6DBxd'oPK܍}H܃d" pjFϖ0/&J]+廿"?-wdxԥ2<W# @#Wވ2|?d8tge$f]}R5.{}Zˎײ{E>N^`|&~WNyub)l?oůgL1ќ Nx+N3"lx}#&Hf͢S7c#:xMA:>?:uPto (FEBo)3kq1GS7FP4vw͑O3|y>{>~_ >o\\F4FMHCm%V0͈Fg++JD83i&pQLdqv6LDY>u~OH1o͒Dk'~FMwFxsHϹw}3kJYGUWtKjt.X=] ͱb>#c^)o#gЬ O%FhS}{07{qsKkzi59"p_XߣS4Fџ4Y(DSX"E5h\FqvhS Mj4ѴF3((j접4n^ghW5cg|!bL;54nE3)_JDg/9[gjok#f(#s40Ed|%m"h۱~845zFjtFghCݦ}XitFi.B.b.]35z/?V5*kTѨQMF -jtFVitFRk `O2 4ⱳb4ҩL6rSyѩ>HX8FΈ,҈"WE^yYȍD>̣z(kTѨQMF54jjѲF-V4jkQIYWFWhhPUhtP5Y]hlVh\i|FQ7>Kطb?=dCN9Z$9z]6#EH#Qc+yNum84WdezFGůɒDƣCVZz>`Iաgo:YOhFghJS4LFkTtNmOK(S5:K5itFO\ypH^5GhtFitF'h0a蘭I</2?uvR[d{`qx Ǥ <<=E}*7.v0F'+}yd)2B;Fݥ'5[Oii>=}N#G/hO}Q/iN^W4Oi4zF'Ѭ;&o@#;cO5blO;#ؙd=ώ{Z c.]ԹR oz!O]Ymn^91_K5G^5zFZ^ѫ5zF:^4^7itFoݨ4IktF]ssd{/>DM>MnO!rGw_86N3.[y0𪦼c9d 9,ӳ^9,Mi%W6tzX`1[/9T':M+K3 97?1UTԴ[Nix9^O>m陴kl34A*F>ދٞQO.THQ=H6cN ?O K ?L"zqJG"wA:^/L8UK \.ϫRxȅH+j4?O-=Q:Tn_?WG9GAFRR}].Hkj+ɨ2kvqb۬xyjr$p|;5o&v|'=Hۥ)c /5\ juRO>:mvtzrLj]@muQT5UKj,n}ը=hퟥ{]_{)$+ػ`~b7gPBj~~{샬EN1^zC>xt|3Hij?usoMFEddvJ\EfGn"u﹵ǭ[T [/>DɪqUpqŞCb-XibGb쎤)MΈzӢ]kW$wJgJY%Y%XG0M؝##Bq<%#}.HN9Y'I>}8k0璏]8fV1F$o4ߞΒB䎐c,3$ K>|%$cwUn7TKA^nFBiC,5$K>|%=Pg9힐,\H%֨㫜+<_c}!7XuJwIK[yGyݝ.~f=ϊ5c%KW:+^o^o@[ͷooRw_57acr"94i~dq'&N^\Lv]ŎR*>2Dt,X>ח,{DNdF>q>ݤx)M-(\}3O磿!OXO&{ht{@x 'cO61u1zS%7=trJC'qnMKꍩ[8͜ќ7" 5S(ψ~J{9'zQykx>W4WEkY=J?5FFd:سbWNLzXIL}?ԃ~Yx.3~“FjC~я5F?gF5zH4w~/5Fѯ5O~o5FF5F_y_fEYu[5 "."*(- .: "2. :1ꠂ3OQQQ}[/ZGPd_է wK~wUUYg{ڑZ*er=۩O:$G_ />g|̷vs33f><=7tύ=7oF&=7 ܴ瞛s3Dܘ1L=7rscf%讙=2?MxgL}{\S{>&]0A| ީETvF4^N'52x. ǍU!SƏ0V$ &%5~ЄtHľlbC%h㿵{,gSu;09kkr{: x։2O3twȬx/CxBhF}ކGΈ6ojqmӱtRޡ:6{Xosܰ(mF-7RV C뽇P㐖JM+ r~ȃ qwO`>qvjH%^^)IlͲ~;mJ0jUM_3ŔËWEfdس;NˁYQb[gy #9%䜫!9P,(r9WU$g!9ռsU+r&YH` `]M⺽FΫ,9#w"D r'%qճ L\9fW2rA wEyL\W;յܑꋔʱe\Kanr~ūzդ".v__K;p7GkODF*c(8[tab{Fr8 uZkd&1O=ib#i07af D3\Fs܃8hy,1̋UҼc֘3Sm6flږ=ȶd]lO{kr;VEv:_l+ӈ}6>?sq;%/'J"q 7"v'NN"bD݈G|l3%j^jcASZ g8oI7 ~cίOH x:/{3%$]NLx!1?qǨD\6'\kFi߳/5qcx1"+$wU^)qwK{- K{]N1η CC~rowܻ%}8:~N={#taQ.ڣICHO=Iw-.3L9tx68߶2^{‘r)O~ڭh2RG W';δ;[`]nW*ڮU nqR.k욹V躹^!,7ƍsܥrwnvs]>{-^voB܇ոm"k{^oDw7]MxWz3[;{ޣo{[>󪽍foio7[G]~__+0+ȟO3?_?/c_/-)IRT78,*.QbIGxq,ĵ?l]f02#z?{nD O&Q%'=~gL/T˧)''.-M !Wm$ED3Gy|%ut,ލ3>$Hn]*$.(>SXz{Xna$u؝Y` :e F]JR vVI5,*sN%^IsE4>J,s0zu^+d"b(Deie:5 ;l[`{-32hݜcΑ;E9N{-fki~VM1ʣ-EĖmnsm+1!c*/_%.Ϡ ٗ+R`_oK}߮Sid?+h5`!v&-mhCi嬳:{CiMV9_@P[|YW*?DKou>M;r>2L{ rsdDKAb(1| F~m߂h/Qk77";14 cngE^ sٚYȟ!9Im$!|1^?DUA 6!{a "{mȞA<88qߗvV&I9ՉkOp;F[c17&p=o?l{ѭwg*uYZ/kp[tIdM`5M3vfz3`g1f`.5k,sk2̟fyl4oJ|i15fzvƶl۞h0;ʞk/{ao;=> _f_ o}ǮATfy.J\fYqA ^RYAz$ǎ!g.$ͯ~h~j(.gȻ}wǸ&{¨c{?ݗq)DSKiϥcu+Idy50_Z 6\hP'tC1lREʗHRld0N]>TqjSAAǩVs:T7Sp:/9NqLpqj$9[b_}k{7u>w' p]\Owr7U1Þ䦺nyn[qnv)\]@FJ,O`3VQfh?;D=DO&&XxkS@l([XNDžsҊc8f>o@,A(֐SJ gs]=ڊe<3 ݐWJ9DjY3CJ`*JLru꟤;UKw;J9h:!U#I < q~GcGG=':7Ĥ.%4^K Ieo~inDԻnv*-vCZ:qFZ;I%;9;Ue^%=33WvVv1{ޖMp f4Zf !3Yb"#iaG wAؾ#_< <:F^bd}#>pS~y48`K9/q) W##Nx*j!gU3шt/Hn7jjxNҿ*kҞ-֘wIj;į[xm;H ;7qFkZhxqvk?ɩxذ'o|F\>w ,Eg4녲z_xޢi3N&R3X>щSM[f2p]r888N2-*-s21mI?@~mtNF]yIsG]m߳=W${ivZ٫d^>{Sv6O*H5/HG>^H]'v%lJt~l|@n6+pi:f0yt7ܾLq\--fԟ*M+չ:5q'5(~op}Դk>V:,QNg vL8\Gct.էVdaЮϩ橡kov wL؛& ~~ MBJ^5VϴdK8_Oo>jssT#OB7|u H=#^1sWoCvMzyvˎLE;WR^ ^-iѱP5b{7B3ZVw}|7h@ˑ6؊w#% ~w蝾#7?KiAGpt3  F`bpq0)$4L . ӂ˃++5 nwpO0?X72Ͻ|[˾_˵DE1[ Fተ=R\hoPϣ,ʘ3.>aJÞsh^֭U>klKiRvburvl^ 䦶3;ړ 1ToUZO^%|[sྑ9!,m;9[(Yl&$ay簞#jێVwU/w _`kpLQ`QǍU{;.eiwSJ"u[MDyؖTYمS{'kC;w\^]l!99lJ[=fKsˤ倮`iܱuS`=[1mkJkFD2eg)oH}ƱR??Ma,;C`4.M1]"ir?ݟ.-9iU2h)m6r(ƽ^o9 #I )# Q ߳覣txX!GcLNzb̻SwiCz37a].5Ze)[^JapCDnw߹)Rq,v1t9r-0•^sp7B%{H)K?/\VL"UeHsP­tÕd,xf ՔykJuT*L-;>[d5JY͚Մi_GVDQM*#ǵU ۧuW#ne|Mz5DvV✺{VɄrm%EUHwĭl4ȚTtSIYW--]$Cu$Z5Va$Xk5D=$YB&U.s&ncT .kXںrUz-#k+b$箌$']k'U9~Lq]`$ }>fu-WZq>̓C iT途<HYT(G!y@tE*bTgFf"r=\&гV$g{e>t>O}Y'u$ǛHNVb[/k|Yc!YJ+~ 9ٌT"[ d;RH,2E1%X3%kbF\yA `3LLs̥L'IMRb&0_"mĦ4}%/)LKV+(=&=8X/vF#]iAYQCP5d"jRCE|c;^|/ D$Vt2u2|]ONE*Lq? DNG`B> =Np WLl j hh3M_F*Gg1'#eTfKry)KH~l=Aczɒ@*ɞT&G/"y' y;GH~lU#m}䛔InM>0m@*gMԣm9SjJA9Sf@9S}9֣VlFRmIu &%c1虺tF -r86P;d(]qLc ;77ƽѭn4E>6">r?;չ>ƭuݮ$ږUEqTGj5ZXbu-Uu}W4rbѣoSrR>/2zSǧ|c}c^77WOO{{y{yxא"Hgsi>}/#lC 4Y>Y>Y>OwZ>V&W|T/////# E'GMЗzsj4KQͧF-G;LQe]5Z@QhuԨO:j4őRYp$3h-F 5QGZjRRYOE6R5jQCYRKQs)j.ERs\!5WHPsy\5+\Psj.Ce9Gͥ5m{LWDE:KSgyY4ZSgԙθ~/gBc /I&~`H_e?o'Y~dP#E?y/sK+'o R| OrKC^S}ȧh 9E;ޞh~̮hPj4Zem}F\W3?7bzB P\he<ˈsx__[U;/!wMj[7[ע2Ԋ+vh>ʴ] uѫ5ҜkqsT"c 1l1lc4{u:˾]^]^]^OO~JٷطثW7Hİ%e%(5z-ϰ%DܚIĭbbB" 4 (M^yyyyPÖww&bآD [aG1nͣ7ϸ5)F>|;ŪuQj4&0J-`هQjfFiz}8ϊ>l`{v :ۊƐb!CJ9J+e7gTyj0UFY%gtVHP+}9I423eԈ@l,[/. ;GG90+_K\?S|8 Fґ(#XǰOaQ?wVJ`#lD#c+<z\bCwۡȫ~@/à a Ea\%][L7_6+ktz3zڵu+u8޵*^=[Ug9vfenX;fUccQqِ[|V|llVhE~d[~4CԛˊxhO>nE32,'FontBBox'=>'[-968 -460 1556 1072]','ItalicAngle'=>0,'Ascent'=>1000,'Descent'=>-300,'Leading'=>90,'CapHeight'=>729,'XHeight'=>540,'StemV'=>123,'StemH'=>53,'AvgWidth'=>478,'MaxWidth'=>1501,'MissingWidth'=>700); $cw=array(0=>0,1=>700,2=>700,3=>700,4=>700,5=>700,6=>700,7=>700,8=>0,9=>600,10=>700,11=>700,12=>700,13=>600,14=>700,15=>700,16=>700,17=>700,18=>700,19=>700,20=>700,21=>700,22=>700,23=>700,24=>700,25=>700,26=>700,27=>700,28=>700,29=>0,30=>700,31=>700,32=>278,33=>333,34=>474,35=>556,36=>556,37=>889,38=>722,39=>238,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>333,59=>333,60=>584,61=>584,62=>584,63=>611,64=>975,65=>722,66=>722,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>556,75=>722,76=>611,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>333,92=>278,93=>333,94=>584,95=>556,96=>333,97=>556,98=>611,99=>556,100=>611,101=>556,102=>333,103=>611,104=>611,105=>278,106=>278,107=>556,108=>278,109=>889,110=>611,111=>611,112=>611,113=>611,114=>389,115=>556,116=>333,117=>611,118=>556,119=>778,120=>556,121=>556,122=>500,123=>389,124=>280,125=>389,126=>584,127=>700,128=>722,129=>722,130=>722,131=>667,132=>722,133=>778,134=>722,135=>556,136=>556,137=>556,138=>556,139=>556,140=>556,141=>556,142=>556,143=>556,144=>556,145=>556,146=>278,147=>278,148=>278,149=>278,150=>611,151=>611,152=>611,153=>611,154=>611,155=>611,156=>611,157=>611,158=>611,159=>611,160=>278,161=>333,162=>556,163=>556,164=>556,165=>556,166=>280,167=>556,168=>333,169=>737,170=>370,171=>556,172=>584,173=>333,174=>737,175=>333,176=>606,177=>584,178=>351,179=>351,180=>333,181=>611,182=>556,183=>278,184=>333,185=>300,186=>365,187=>556,188=>869,189=>869,190=>869,191=>611,192=>722,193=>722,194=>722,195=>722,196=>722,197=>722,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>667,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>889,231=>556,232=>556,233=>556,234=>556,235=>556,236=>278,237=>278,238=>278,239=>278,240=>611,241=>611,242=>611,243=>611,244=>611,245=>611,246=>611,247=>584,248=>611,249=>611,250=>611,251=>611,252=>611,253=>556,254=>611,255=>556,256=>722,257=>556,258=>722,259=>556,260=>722,261=>556,262=>722,263=>556,264=>722,265=>556,266=>722,267=>556,268=>722,269=>556,270=>722,271=>723,272=>722,273=>611,274=>667,275=>556,276=>667,277=>556,278=>667,279=>556,280=>667,281=>556,282=>667,283=>556,284=>778,285=>611,286=>778,287=>611,288=>778,289=>611,290=>778,291=>611,292=>722,293=>611,294=>722,295=>611,296=>278,297=>278,298=>278,299=>278,300=>278,301=>278,302=>278,303=>278,304=>278,305=>278,306=>593,307=>486,308=>556,309=>278,310=>722,311=>556,312=>559,313=>611,314=>278,315=>611,316=>278,317=>611,318=>422,319=>611,320=>556,321=>611,322=>278,323=>722,324=>611,325=>722,326=>611,327=>722,328=>611,329=>701,330=>720,331=>611,332=>778,333=>611,334=>778,335=>611,336=>778,337=>611,338=>1000,339=>953,340=>722,341=>389,342=>722,343=>389,344=>722,345=>389,346=>667,347=>556,348=>667,349=>556,350=>667,351=>556,352=>667,353=>556,354=>611,355=>333,356=>611,357=>414,358=>611,359=>333,360=>722,361=>611,362=>722,363=>611,364=>722,365=>611,366=>722,367=>611,368=>722,369=>611,370=>722,371=>611,372=>944,373=>778,374=>667,375=>556,376=>667,377=>611,378=>500,379=>611,380=>500,381=>611,382=>500,383=>333,384=>611,385=>963,386=>704,387=>611,388=>687,389=>611,390=>722,391=>752,392=>562,393=>722,394=>968,395=>722,396=>611,397=>609,398=>667,399=>778,400=>672,401=>611,402=>333,403=>778,404=>667,405=>940,406=>278,407=>395,408=>778,409=>556,410=>333,411=>620,412=>944,413=>722,414=>611,415=>778,416=>811,417=>673,418=>1111,419=>722,420=>914,421=>611,422=>647,423=>667,424=>556,425=>673,426=>441,427=>333,428=>742,429=>333,430=>611,431=>789,432=>676,433=>766,434=>722,435=>839,436=>620,437=>611,438=>500,439=>556,440=>556,441=>645,442=>569,443=>579,446=>611,447=>608,448=>260,449=>370,450=>584,451=>278,452=>1333,453=>1222,454=>1111,455=>1167,456=>889,457=>556,458=>1278,459=>1000,460=>889,461=>722,462=>556,463=>278,464=>278,465=>778,466=>611,467=>722,468=>611,469=>722,470=>611,471=>722,472=>611,473=>722,474=>611,475=>722,476=>611,477=>556,478=>722,479=>556,480=>722,481=>556,482=>1000,483=>889,484=>778,485=>611,486=>778,487=>611,488=>722,489=>556,490=>778,491=>611,492=>778,493=>611,494=>556,495=>556,496=>278,497=>1333,498=>1222,499=>1111,500=>778,501=>611,503=>630,504=>722,505=>611,506=>722,507=>556,508=>1000,509=>889,510=>778,511=>611,512=>722,513=>556,514=>722,515=>556,516=>667,517=>556,518=>667,519=>556,520=>278,521=>278,522=>278,523=>278,524=>778,525=>611,526=>778,527=>611,528=>722,529=>389,530=>722,531=>389,532=>722,533=>611,534=>722,535=>611,536=>667,537=>556,538=>611,539=>333,540=>569,541=>486,542=>722,543=>611,548=>645,549=>500,550=>722,551=>556,552=>667,553=>556,554=>778,555=>611,556=>778,557=>611,558=>778,559=>611,560=>778,561=>611,562=>667,563=>556,567=>278,592=>556,593=>677,594=>678,595=>611,596=>556,597=>600,598=>625,599=>625,600=>556,601=>556,602=>834,603=>571,604=>557,605=>820,606=>570,607=>316,608=>619,609=>611,610=>566,611=>556,612=>656,613=>619,614=>611,615=>611,616=>300,617=>344,618=>300,619=>473,620=>527,621=>298,622=>778,623=>893,624=>889,625=>889,626=>628,627=>626,628=>615,629=>606,630=>878,631=>839,632=>738,633=>411,634=>406,635=>426,636=>396,637=>396,638=>455,639=>475,640=>620,641=>620,642=>610,643=>333,644=>331,645=>333,646=>553,647=>328,648=>333,649=>643,650=>726,651=>639,652=>556,653=>778,654=>556,655=>556,656=>551,657=>591,658=>556,659=>642,660=>611,661=>611,662=>611,663=>556,664=>611,665=>554,666=>590,667=>616,668=>603,669=>552,670=>588,671=>454,672=>626,673=>611,674=>611,675=>1004,676=>1018,677=>1097,678=>804,679=>593,680=>840,681=>866,682=>752,683=>668,684=>525,685=>486,686=>659,687=>679,688=>377,689=>377,690=>202,691=>272,692=>272,693=>299,694=>395,695=>534,696=>364,697=>278,698=>454,699=>278,700=>278,701=>278,702=>333,703=>333,704=>333,705=>333,706=>333,707=>333,708=>333,709=>333,710=>333,711=>333,712=>333,713=>333,714=>333,715=>333,716=>272,717=>333,718=>333,719=>333,720=>333,721=>333,722=>333,723=>333,724=>333,725=>333,726=>333,727=>333,728=>333,729=>333,730=>333,731=>333,732=>333,733=>333,734=>333,735=>510,736=>372,737=>210,738=>363,739=>373,740=>334,741=>526,742=>526,743=>526,744=>526,745=>526,746=>519,747=>519,748=>333,749=>333,750=>333,751=>333,752=>333,753=>333,754=>333,755=>333,756=>333,757=>437,758=>437,759=>400,760=>333,761=>200,762=>200,763=>200,764=>200,765=>333,766=>333,767=>333,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,842=>0,843=>0,844=>0,845=>0,846=>0,847=>0,848=>0,849=>0,850=>0,851=>0,852=>0,853=>0,854=>0,855=>0,856=>0,857=>0,858=>0,859=>0,860=>0,861=>0,862=>0,863=>0,864=>0,865=>0,866=>0,867=>0,868=>0,869=>0,870=>0,871=>0,872=>0,873=>0,874=>0,875=>0,876=>0,877=>0,878=>0,879=>0,884=>379,885=>379,890=>333,894=>333,900=>363,901=>333,902=>761,903=>333,904=>864,905=>903,906=>454,908=>796,910=>991,911=>867,912=>315,913=>696,914=>640,915=>585,916=>726,917=>589,918=>581,919=>654,920=>783,921=>215,922=>648,923=>710,924=>829,925=>683,926=>645,927=>738,928=>726,929=>645,931=>673,932=>674,933=>771,934=>773,935=>780,936=>778,937=>766,938=>263,939=>771,940=>660,941=>541,942=>560,943=>356,944=>568,945=>632,946=>560,947=>591,948=>609,949=>541,950=>488,951=>608,952=>562,953=>315,954=>533,955=>603,956=>582,957=>586,958=>513,959=>611,960=>658,961=>595,962=>590,963=>657,964=>557,965=>568,966=>768,967=>632,968=>708,969=>778,970=>315,971=>568,972=>599,973=>568,974=>778,977=>580,978=>742,979=>857,980=>620,981=>706,982=>740,983=>556,1008=>556,1009=>566,1012=>778,1013=>328,1024=>670,1025=>670,1026=>800,1027=>611,1028=>714,1029=>667,1030=>314,1031=>300,1032=>576,1033=>1100,1034=>1114,1035=>806,1036=>740,1037=>757,1038=>711,1039=>754,1040=>707,1041=>704,1042=>704,1043=>611,1044=>900,1045=>670,1046=>1076,1047=>667,1048=>757,1049=>757,1050=>740,1051=>729,1052=>874,1053=>753,1054=>774,1055=>753,1056=>675,1057=>711,1058=>611,1059=>711,1060=>904,1061=>666,1062=>816,1063=>698,1064=>1057,1065=>1157,1066=>837,1067=>980,1068=>675,1069=>711,1070=>1093,1071=>708,1072=>552,1073=>593,1074=>554,1075=>423,1076=>685,1077=>573,1078=>782,1079=>557,1080=>615,1081=>615,1082=>559,1083=>568,1084=>666,1085=>603,1086=>606,1087=>603,1088=>612,1089=>556,1090=>440,1091=>549,1092=>964,1093=>539,1094=>652,1095=>554,1096=>886,1097=>968,1098=>699,1099=>778,1100=>568,1101=>556,1102=>848,1103=>586,1104=>573,1105=>573,1106=>606,1107=>423,1108=>556,1109=>555,1110=>260,1111=>278,1112=>270,1113=>898,1114=>898,1115=>626,1116=>559,1117=>615,1118=>549,1119=>604,1120=>986,1121=>736,1136=>832,1137=>748,1138=>774,1139=>606,1148=>942,1149=>736,1150=>986,1151=>736,1154=>449,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1160=>0,1161=>0,1162=>832,1163=>675,1164=>678,1165=>611,1166=>675,1167=>612,1168=>636,1169=>440,1170=>622,1171=>449,1172=>647,1173=>574,1174=>1096,1175=>803,1176=>683,1177=>555,1178=>759,1179=>573,1180=>730,1181=>554,1182=>737,1183=>555,1184=>892,1185=>680,1186=>825,1187=>653,1188=>999,1189=>763,1190=>1105,1191=>925,1192=>963,1193=>766,1194=>722,1195=>558,1196=>614,1197=>438,1198=>643,1199=>573,1200=>643,1201=>603,1202=>670,1203=>548,1204=>952,1205=>738,1206=>781,1207=>615,1208=>698,1209=>588,1210=>687,1211=>588,1212=>993,1213=>761,1214=>993,1215=>761,1216=>314,1217=>1076,1218=>809,1219=>700,1220=>543,1221=>793,1222=>634,1223=>753,1224=>603,1225=>819,1226=>663,1227=>706,1228=>588,1229=>935,1230=>720,1231=>314,1232=>707,1233=>564,1234=>707,1235=>566,1236=>1004,1237=>898,1238=>670,1239=>573,1240=>722,1241=>573,1242=>722,1243=>573,1244=>1076,1245=>782,1246=>667,1247=>557,1248=>556,1249=>552,1250=>757,1251=>615,1252=>757,1253=>615,1254=>778,1255=>611,1256=>774,1257=>606,1258=>774,1259=>606,1260=>711,1261=>556,1262=>700,1263=>544,1264=>701,1265=>539,1266=>700,1267=>537,1268=>698,1269=>554,1270=>611,1271=>432,1272=>980,1273=>778,1296=>672,1297=>546,1298=>729,1299=>577,1306=>778,1307=>612,1308=>944,1309=>776,1310=>730,1311=>554,1329=>730,1330=>713,1331=>765,1332=>752,1333=>708,1334=>801,1335=>496,1336=>713,1337=>855,1338=>686,1339=>727,1340=>420,1341=>897,1342=>841,1343=>708,1344=>660,1345=>666,1346=>747,1347=>698,1348=>757,1349=>630,1350=>747,1351=>651,1352=>743,1353=>657,1354=>728,1355=>799,1356=>752,1357=>743,1358=>768,1359=>691,1360=>713,1361=>640,1362=>425,1363=>818,1364=>672,1365=>805,1366=>754,1369=>333,1370=>222,1371=>250,1372=>333,1373=>333,1374=>352,1375=>362,1377=>873,1378=>613,1379=>634,1380=>636,1381=>593,1382=>639,1383=>417,1384=>613,1385=>658,1386=>711,1387=>609,1388=>318,1389=>836,1390=>670,1391=>613,1392=>607,1393=>611,1394=>626,1395=>619,1396=>618,1397=>324,1398=>613,1399=>540,1400=>591,1401=>392,1402=>873,1403=>577,1404=>603,1405=>600,1406=>626,1407=>951,1408=>613,1409=>612,1410=>348,1411=>951,1412=>616,1413=>606,1414=>763,1415=>626,1417=>333,1418=>398,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1467=>0,1468=>0,1469=>0,1470=>516,1471=>0,1472=>297,1473=>0,1474=>0,1475=>333,1476=>0,1488=>714,1489=>651,1490=>557,1491=>638,1492=>682,1493=>297,1494=>443,1495=>682,1496=>670,1497=>284,1498=>590,1499=>595,1500=>667,1501=>683,1502=>704,1503=>297,1504=>429,1505=>670,1506=>653,1507=>661,1508=>660,1509=>616,1510=>671,1511=>672,1512=>600,1513=>840,1514=>756,1520=>554,1521=>550,1522=>542,1523=>238,1524=>474,2561=>0,2562=>122,2563=>313,2565=>897,2566=>1157,2567=>930,2568=>966,2569=>762,2570=>762,2575=>729,2576=>904,2579=>773,2580=>903,2581=>726,2582=>672,2583=>741,2584=>790,2585=>702,2586=>723,2587=>693,2588=>688,2589=>673,2590=>683,2591=>686,2592=>711,2593=>680,2594=>693,2595=>729,2596=>691,2597=>694,2598=>699,2599=>666,2600=>669,2602=>683,2603=>690,2604=>660,2605=>659,2606=>692,2607=>772,2608=>673,2610=>731,2611=>814,2613=>663,2614=>704,2616=>702,2617=>650,2620=>0,2622=>307,2623=>304,2624=>306,2625=>7,2626=>7,2631=>7,2632=>8,2635=>6,2636=>5,2637=>0,2641=>0,2649=>684,2650=>813,2651=>715,2652=>695,2654=>709,2662=>697,2663=>630,2664=>696,2665=>690,2666=>646,2667=>636,2668=>571,2669=>682,2670=>718,2671=>730,2672=>9,2673=>162,2674=>722,2675=>760,2676=>1110,2677=>0,4256=>616,4257=>645,4258=>664,4259=>839,4260=>627,4261=>630,4262=>827,4263=>928,4264=>639,4265=>630,4266=>951,4267=>606,4268=>608,4269=>835,4270=>630,4271=>610,4272=>804,4273=>615,4274=>823,4275=>747,4276=>870,4277=>627,4278=>840,4279=>627,4280=>665,4281=>610,4282=>799,4283=>598,4284=>665,4285=>664,4286=>608,4287=>886,4288=>629,4304=>463,4305=>516,4306=>564,4307=>706,4308=>459,4309=>476,4310=>623,4311=>711,4312=>494,4313=>476,4314=>894,4315=>500,4316=>500,4317=>712,4318=>493,4319=>503,4320=>712,4321=>503,4322=>710,4323=>670,4324=>707,4325=>459,4326=>691,4327=>465,4328=>492,4329=>480,4330=>656,4331=>500,4332=>492,4333=>524,4334=>500,4335=>688,4336=>510,4337=>739,4338=>450,4339=>479,4340=>502,4341=>501,4345=>564,4347=>515,4348=>449,5024=>714,5025=>731,5026=>624,5027=>908,5028=>1040,5029=>271,5030=>654,5031=>863,5032=>604,5033=>791,5034=>714,5035=>522,5036=>661,5037=>926,5038=>615,5039=>811,5040=>538,5041=>633,5042=>979,5043=>964,5044=>635,5045=>607,5046=>753,5047=>831,5048=>566,5049=>977,5050=>958,5051=>710,5052=>616,5053=>834,5054=>790,5055=>612,5056=>766,5057=>857,5058=>627,5059=>649,5060=>607,5061=>1127,5062=>680,5063=>920,5064=>928,5065=>1333,5066=>920,5067=>705,5068=>695,5069=>1074,5070=>672,5071=>672,5072=>667,5073=>819,5074=>679,5075=>575,5076=>903,5077=>652,5078=>776,5079=>643,5080=>670,5081=>660,5082=>648,5083=>934,5084=>909,5085=>613,5086=>615,5087=>735,5088=>900,5089=>1024,5090=>647,5091=>760,5092=>829,5093=>824,5094=>756,5095=>625,5096=>981,5097=>1014,5098=>1040,5099=>790,5100=>926,5101=>686,5102=>656,5103=>920,5104=>741,5105=>890,5106=>626,5107=>974,5108=>699,7680=>722,7681=>556,7682=>722,7683=>611,7684=>722,7685=>611,7686=>722,7687=>611,7688=>722,7689=>556,7690=>722,7691=>611,7692=>722,7693=>611,7694=>722,7695=>611,7696=>722,7697=>611,7698=>722,7699=>611,7700=>667,7701=>556,7702=>667,7703=>556,7704=>667,7705=>556,7706=>667,7707=>556,7708=>667,7709=>556,7710=>611,7711=>333,7712=>778,7713=>611,7714=>722,7715=>611,7716=>722,7717=>611,7718=>722,7719=>611,7720=>722,7721=>611,7722=>722,7723=>611,7724=>278,7725=>278,7726=>278,7727=>278,7728=>722,7729=>556,7730=>722,7731=>556,7732=>722,7733=>556,7734=>611,7735=>278,7736=>611,7737=>278,7738=>611,7739=>278,7740=>611,7741=>278,7742=>833,7743=>889,7744=>833,7745=>889,7746=>833,7747=>889,7748=>722,7749=>611,7750=>722,7751=>611,7752=>722,7753=>611,7754=>722,7755=>611,7756=>778,7757=>611,7758=>778,7759=>611,7760=>778,7761=>611,7762=>778,7763=>611,7764=>667,7765=>611,7766=>667,7767=>611,7768=>722,7769=>389,7770=>722,7771=>389,7772=>722,7773=>389,7774=>722,7775=>389,7776=>667,7777=>556,7778=>667,7779=>556,7780=>667,7781=>556,7782=>667,7783=>556,7784=>667,7785=>556,7786=>611,7787=>333,7788=>611,7789=>333,7790=>611,7791=>333,7792=>611,7793=>333,7794=>722,7795=>611,7796=>722,7797=>611,7798=>722,7799=>611,7800=>722,7801=>611,7802=>722,7803=>611,7804=>667,7805=>556,7806=>667,7807=>556,7808=>944,7809=>778,7810=>944,7811=>778,7812=>944,7813=>778,7814=>944,7815=>778,7816=>944,7817=>778,7818=>667,7819=>556,7820=>667,7821=>556,7822=>667,7823=>556,7824=>611,7825=>500,7826=>611,7827=>500,7828=>611,7829=>500,7830=>611,7831=>333,7832=>778,7833=>556,7834=>555,7835=>333,7840=>722,7841=>556,7842=>722,7843=>556,7844=>722,7845=>556,7846=>722,7847=>556,7848=>667,7849=>556,7850=>722,7851=>556,7852=>722,7853=>556,7854=>722,7855=>556,7856=>722,7857=>556,7858=>722,7859=>556,7860=>722,7861=>556,7862=>722,7863=>556,7864=>667,7865=>556,7866=>667,7867=>556,7868=>667,7869=>556,7870=>667,7871=>556,7872=>667,7873=>556,7874=>667,7875=>556,7876=>667,7877=>556,7878=>667,7879=>556,7880=>278,7881=>278,7882=>278,7883=>278,7884=>778,7885=>611,7886=>778,7887=>611,7888=>778,7889=>611,7890=>778,7891=>611,7892=>778,7893=>611,7894=>778,7895=>611,7896=>778,7897=>611,7898=>811,7899=>673,7900=>811,7901=>673,7902=>811,7903=>673,7904=>811,7905=>673,7906=>811,7907=>673,7908=>722,7909=>611,7910=>722,7911=>611,7912=>789,7913=>676,7914=>789,7915=>676,7916=>789,7917=>676,7918=>789,7919=>676,7920=>789,7921=>676,7922=>667,7923=>556,7924=>667,7925=>556,7926=>667,7927=>556,7928=>667,7929=>556,7936=>632,7937=>632,7938=>632,7939=>632,7940=>632,7941=>632,7942=>632,7943=>632,7944=>696,7945=>696,7946=>865,7947=>849,7948=>796,7949=>807,7950=>730,7951=>750,7952=>541,7953=>541,7954=>541,7955=>541,7956=>541,7957=>541,7960=>758,7961=>760,7962=>957,7963=>943,7964=>939,7965=>945,7968=>608,7969=>608,7970=>608,7971=>608,7972=>608,7973=>608,7974=>608,7975=>608,7976=>823,7977=>831,7978=>1026,7979=>1017,7980=>1002,7981=>1024,7982=>908,7983=>909,7984=>315,7985=>315,7986=>373,7987=>375,7988=>378,7989=>374,7990=>370,7991=>384,7992=>378,7993=>383,7994=>596,7995=>579,7996=>572,7997=>576,7998=>474,7999=>459,8000=>610,8001=>610,8002=>610,8003=>610,8004=>610,8005=>610,8008=>800,8009=>871,8010=>1084,8011=>1079,8012=>975,8013=>973,8016=>568,8017=>568,8018=>568,8019=>568,8020=>568,8021=>568,8022=>568,8023=>568,8025=>906,8027=>1080,8029=>1115,8031=>977,8032=>778,8033=>778,8034=>778,8035=>778,8036=>778,8037=>778,8038=>778,8039=>778,8040=>837,8041=>860,8042=>1062,8043=>1072,8044=>962,8045=>985,8046=>922,8047=>959,8048=>632,8049=>632,8050=>541,8051=>541,8052=>608,8053=>608,8054=>315,8055=>315,8056=>610,8057=>610,8058=>568,8059=>568,8060=>778,8061=>778,8064=>632,8065=>632,8066=>632,8067=>632,8068=>632,8069=>632,8070=>632,8071=>632,8072=>909,8073=>906,8074=>1061,8075=>1035,8076=>984,8077=>994,8078=>910,8079=>916,8080=>608,8081=>608,8082=>608,8083=>608,8084=>608,8085=>608,8086=>608,8087=>608,8088=>1006,8089=>1015,8090=>1204,8091=>1207,8092=>1188,8093=>1209,8094=>1096,8095=>1105,8096=>778,8097=>778,8098=>778,8099=>778,8100=>778,8101=>778,8102=>778,8103=>778,8104=>1026,8105=>1048,8106=>1251,8107=>1260,8108=>1150,8109=>1177,8110=>1106,8111=>1142,8112=>632,8113=>632,8114=>632,8115=>632,8116=>660,8118=>632,8119=>632,8120=>696,8121=>696,8122=>696,8123=>696,8124=>907,8125=>278,8126=>346,8127=>278,8128=>278,8129=>333,8130=>608,8131=>608,8132=>560,8134=>608,8135=>608,8136=>776,8137=>793,8138=>847,8139=>854,8140=>848,8141=>492,8142=>489,8143=>394,8144=>335,8145=>354,8146=>367,8147=>368,8150=>353,8151=>366,8152=>240,8153=>259,8154=>418,8155=>416,8157=>481,8158=>589,8159=>333,8160=>568,8161=>568,8162=>568,8163=>568,8164=>595,8165=>595,8166=>568,8167=>568,8168=>771,8169=>771,8170=>951,8171=>982,8172=>806,8173=>333,8174=>333,8175=>333,8178=>778,8179=>778,8180=>778,8182=>778,8183=>778,8184=>909,8185=>809,8186=>897,8187=>825,8188=>978,8189=>333,8190=>278,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>333,8197=>250,8198=>167,8199=>556,8200=>278,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>333,8209=>333,8210=>556,8211=>556,8212=>1000,8213=>1000,8214=>437,8215=>556,8216=>278,8217=>278,8218=>278,8219=>278,8220=>500,8221=>500,8222=>500,8223=>500,8224=>556,8225=>556,8226=>350,8227=>350,8228=>278,8229=>666,8230=>1000,8231=>278,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>500,8240=>1000,8241=>1367,8242=>238,8243=>426,8244=>614,8245=>238,8246=>379,8247=>571,8248=>450,8249=>333,8250=>333,8251=>622,8252=>666,8253=>614,8254=>556,8255=>658,8256=>658,8257=>438,8258=>840,8259=>400,8260=>167,8261=>334,8262=>334,8263=>1222,8264=>944,8265=>944,8266=>556,8267=>537,8268=>537,8269=>537,8270=>389,8271=>333,8272=>658,8273=>389,8274=>634,8275=>568,8276=>658,8277=>793,8278=>515,8279=>855,8280=>722,8281=>725,8282=>224,8283=>722,8284=>604,8285=>224,8286=>224,8287=>0,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8304=>351,8305=>200,8308=>351,8309=>351,8310=>351,8311=>351,8312=>351,8313=>351,8314=>351,8315=>351,8316=>351,8317=>216,8318=>218,8319=>391,8320=>351,8321=>301,8322=>351,8323=>351,8324=>351,8325=>351,8326=>351,8327=>351,8328=>351,8329=>351,8330=>350,8331=>350,8332=>350,8333=>216,8334=>216,8336=>363,8337=>366,8338=>394,8339=>360,8340=>355,8355=>611,8356=>591,8357=>889,8358=>727,8360=>1265,8362=>1049,8363=>580,8364=>640,8368=>605,8373=>591,8376=>612,8400=>0,8401=>0,8402=>0,8403=>0,8406=>0,8407=>0,8411=>0,8412=>0,8413=>0,8414=>0,8415=>0,8416=>0,8417=>0,8421=>0,8422=>0,8423=>0,8424=>0,8425=>0,8426=>0,8427=>0,8428=>0,8429=>0,8430=>0,8431=>0,8432=>0,8448=>945,8449=>968,8451=>1034,8453=>981,8454=>1002,8455=>667,8456=>722,8457=>919,8462=>611,8465=>606,8467=>608,8468=>881,8470=>999,8471=>860,8476=>699,8480=>1000,8481=>1370,8482=>1000,8486=>766,8487=>778,8489=>315,8490=>741,8491=>729,8494=>556,8498=>588,8501=>714,8502=>651,8503=>557,8504=>638,8506=>871,8507=>1431,8513=>778,8514=>611,8515=>611,8516=>667,8523=>669,8525=>1242,8526=>482,8531=>869,8532=>869,8533=>869,8534=>869,8535=>869,8536=>869,8537=>869,8538=>869,8539=>869,8540=>869,8541=>869,8542=>869,8543=>869,8544=>278,8545=>556,8546=>834,8547=>945,8548=>667,8549=>945,8550=>1223,8551=>1501,8552=>945,8553=>667,8554=>945,8555=>1223,8556=>611,8557=>722,8558=>722,8559=>833,8560=>278,8561=>556,8562=>834,8563=>834,8564=>556,8565=>834,8566=>1112,8567=>1390,8568=>834,8569=>556,8570=>834,8571=>1112,8572=>278,8573=>556,8574=>611,8575=>889,8592=>964,8593=>964,8594=>964,8595=>964,8596=>964,8597=>964,8598=>964,8599=>964,8600=>964,8601=>964,8602=>964,8603=>964,8606=>964,8607=>964,8608=>964,8609=>964,8610=>964,8611=>964,8612=>964,8613=>964,8614=>964,8615=>964,8616=>964,8644=>964,8645=>964,8646=>964,8647=>964,8648=>964,8649=>964,8650=>964,8704=>722,8706=>556,8707=>667,8710=>729,8711=>729,8721=>856,8722=>584,8725=>869,8730=>594,8747=>608,8800=>548,8804=>584,8805=>584,9251=>500,9674=>541,9675=>860,9711=>1020,9772=>923,9824=>626,9825=>694,9826=>595,9827=>776,9828=>626,9829=>694,9830=>595,9831=>776,9833=>333,9834=>556,9835=>778,9836=>778,9837=>556,9838=>556,9839=>556,10048=>1453,11568=>352,11569=>872,11570=>872,11571=>720,11572=>720,11573=>720,11574=>664,11575=>752,11576=>752,11577=>720,11578=>720,11579=>596,11580=>698,11581=>742,11582=>574,11583=>742,11584=>872,11585=>872,11586=>312,11587=>720,11588=>696,11589=>720,11590=>584,11591=>742,11592=>796,11593=>613,11594=>672,11595=>888,11596=>836,11597=>524,11598=>720,11599=>300,11600=>836,11601=>300,11602=>718,11603=>388,11604=>872,11605=>872,11606=>696,11607=>308,11608=>640,11609=>872,11610=>872,11611=>762,11612=>424,11613=>720,11614=>762,11615=>720,11616=>709,11617=>720,11618=>541,11619=>828,11620=>454,11621=>828,11631=>482,11799=>333,42888=>333,42889=>276,42890=>342,42891=>258,42892=>258,64256=>607,64257=>576,64258=>603,64259=>849,64260=>849,64261=>627,64275=>1243,64276=>1226,64277=>1233,64278=>1238,64279=>1448,64285=>284,64286=>305,64287=>542,64288=>653,64289=>964,64290=>888,64291=>932,64292=>845,64293=>917,64294=>933,64295=>850,64296=>1006,64297=>584,64298=>840,64299=>840,64300=>840,64301=>840,64302=>714,64303=>714,64304=>714,64305=>651,64306=>557,64307=>638,64308=>682,64309=>348,64310=>443,64312=>670,64313=>354,64314=>590,64315=>595,64316=>667,64318=>704,64320=>429,64321=>670,64323=>661,64324=>660,64326=>671,64327=>672,64328=>600,64329=>840,64330=>756,64331=>212,64332=>591,64333=>550,64334=>568,64335=>714,65533=>900,65535=>700); // --- EOF --- PKa\Pilddfonts/freeserifi.phpnuW+A96,'FontBBox'=>'[-879 -434 1558 900]','ItalicAngle'=>-16.32768,'Ascent'=>900,'Descent'=>-300,'Leading'=>90,'CapHeight'=>653,'XHeight'=>452,'StemV'=>70,'StemH'=>30,'AvgWidth'=>402,'MaxWidth'=>1601,'MissingWidth'=>700); $cw=array(0=>0,1=>700,2=>700,3=>700,4=>700,5=>700,6=>700,7=>700,8=>0,9=>600,10=>700,11=>700,12=>700,13=>600,14=>700,15=>700,16=>700,17=>700,18=>700,19=>700,20=>700,21=>700,22=>700,23=>700,24=>700,25=>700,26=>700,27=>700,28=>700,29=>0,30=>700,31=>700,32=>250,33=>333,34=>420,35=>500,36=>500,37=>833,38=>778,39=>214,40=>333,41=>333,42=>500,43=>675,44=>250,45=>333,46=>250,47=>278,48=>500,49=>500,50=>500,51=>500,52=>500,53=>500,54=>500,55=>500,56=>500,57=>500,58=>333,59=>333,60=>675,61=>675,62=>675,63=>500,64=>920,65=>611,66=>611,67=>667,68=>722,69=>604,70=>611,71=>722,72=>722,73=>339,74=>444,75=>652,76=>556,77=>828,78=>657,79=>722,80=>603,81=>722,82=>616,83=>500,84=>556,85=>722,86=>611,87=>833,88=>611,89=>556,90=>556,91=>389,92=>278,93=>389,94=>422,95=>500,96=>333,97=>500,98=>500,99=>444,100=>500,101=>444,102=>278,103=>500,104=>500,105=>278,106=>278,107=>444,108=>278,109=>722,110=>500,111=>500,112=>500,113=>500,114=>389,115=>389,116=>278,117=>500,118=>444,119=>667,120=>444,121=>444,122=>389,123=>400,124=>275,125=>400,126=>541,127=>700,128=>611,129=>611,130=>667,131=>611,132=>667,133=>722,134=>722,135=>500,136=>500,137=>500,138=>500,139=>500,140=>500,141=>444,142=>444,143=>444,144=>444,145=>444,146=>278,147=>278,148=>278,149=>278,150=>500,151=>500,152=>500,153=>500,154=>500,155=>500,156=>500,157=>500,158=>500,159=>500,160=>250,161=>389,162=>500,163=>500,164=>500,165=>500,166=>275,167=>500,168=>333,169=>760,170=>276,171=>444,172=>675,173=>333,174=>760,175=>333,176=>400,177=>675,178=>300,179=>300,180=>333,181=>500,182=>523,183=>250,184=>333,185=>250,186=>310,187=>444,188=>750,189=>750,190=>750,191=>500,192=>611,193=>611,194=>611,195=>611,196=>611,197=>611,198=>889,199=>667,200=>611,201=>611,202=>611,203=>611,204=>333,205=>333,206=>333,207=>333,208=>722,209=>667,210=>722,211=>722,212=>722,213=>722,214=>722,215=>675,216=>722,217=>722,218=>722,219=>722,220=>722,221=>556,222=>611,223=>500,224=>500,225=>500,226=>500,227=>500,228=>500,229=>500,230=>673,231=>444,232=>444,233=>444,234=>444,235=>444,236=>278,237=>278,238=>278,239=>278,240=>500,241=>500,242=>500,243=>500,244=>500,245=>500,246=>500,247=>675,248=>500,249=>500,250=>500,251=>500,252=>500,253=>444,254=>500,255=>444,256=>611,257=>500,258=>611,259=>500,260=>611,261=>500,262=>667,263=>444,264=>667,265=>444,266=>667,267=>444,268=>667,269=>444,270=>722,271=>611,272=>722,273=>500,274=>611,275=>444,276=>611,277=>444,278=>611,279=>444,280=>611,281=>444,282=>611,283=>444,284=>722,285=>500,286=>722,287=>500,288=>722,289=>500,290=>722,291=>500,292=>722,293=>500,294=>722,295=>500,296=>333,297=>278,298=>333,299=>278,300=>333,301=>278,302=>333,303=>278,304=>333,305=>278,306=>707,307=>506,308=>444,309=>278,310=>667,311=>444,312=>444,313=>556,314=>278,315=>556,316=>278,317=>556,318=>361,319=>556,320=>278,321=>556,322=>278,323=>667,324=>500,325=>667,326=>500,327=>667,328=>500,329=>550,330=>721,331=>500,332=>722,333=>500,334=>722,335=>500,336=>722,337=>500,338=>944,339=>694,340=>611,341=>389,342=>611,343=>389,344=>611,345=>389,346=>500,347=>389,348=>500,349=>389,350=>500,351=>389,352=>500,353=>389,354=>556,355=>278,356=>556,357=>447,358=>556,359=>278,360=>722,361=>500,362=>722,363=>500,364=>722,365=>500,366=>722,367=>500,368=>722,369=>500,370=>722,371=>500,372=>833,373=>667,374=>556,375=>444,376=>556,377=>556,378=>389,379=>556,380=>389,381=>556,382=>389,383=>278,384=>500,385=>781,386=>610,387=>551,388=>611,389=>549,390=>667,391=>866,392=>703,393=>722,394=>892,395=>682,396=>500,397=>520,398=>611,399=>722,400=>518,401=>611,402=>278,403=>863,404=>611,405=>728,406=>278,407=>333,408=>792,409=>444,410=>278,411=>480,412=>900,413=>779,414=>500,415=>722,416=>759,417=>546,418=>908,419=>722,420=>772,421=>500,422=>611,423=>500,424=>389,425=>657,426=>461,427=>313,428=>556,429=>335,430=>556,431=>778,432=>584,433=>747,434=>755,435=>636,436=>549,437=>556,438=>389,439=>525,440=>558,441=>424,442=>416,443=>500,444=>615,445=>439,446=>389,447=>500,448=>275,449=>500,450=>600,451=>333,452=>1268,453=>1091,454=>869,455=>1000,456=>824,457=>506,458=>1101,459=>895,460=>748,461=>611,462=>500,463=>339,464=>278,465=>722,466=>500,467=>722,468=>500,469=>722,470=>500,471=>722,472=>500,473=>722,474=>500,475=>722,476=>500,477=>444,478=>611,479=>500,480=>611,481=>500,482=>889,483=>673,484=>722,485=>500,486=>722,487=>500,488=>652,489=>444,490=>730,491=>500,492=>730,493=>500,494=>525,495=>446,496=>278,497=>1258,498=>1091,499=>859,500=>817,501=>595,502=>1024,503=>607,504=>657,505=>500,506=>611,507=>500,508=>889,509=>673,510=>722,511=>500,512=>611,513=>500,514=>611,515=>500,516=>604,517=>444,518=>604,519=>444,520=>339,521=>278,522=>339,523=>278,524=>722,525=>500,526=>722,527=>500,528=>616,529=>389,530=>616,531=>389,532=>722,533=>500,534=>722,535=>500,536=>500,537=>389,538=>556,539=>278,540=>424,541=>465,542=>722,543=>500,544=>781,545=>588,546=>568,547=>468,548=>611,549=>444,550=>611,551=>500,552=>604,553=>444,554=>722,555=>500,556=>722,557=>500,558=>722,559=>500,560=>722,561=>500,562=>556,563=>444,564=>405,565=>597,566=>377,567=>278,568=>775,569=>767,570=>722,571=>667,572=>444,573=>611,574=>611,575=>389,576=>444,577=>444,578=>444,579=>667,580=>750,581=>697,582=>611,583=>444,584=>389,585=>278,586=>796,587=>590,588=>667,589=>333,590=>722,591=>500,592=>500,593=>564,594=>564,595=>500,596=>444,597=>444,598=>524,599=>559,600=>444,601=>444,602=>722,603=>416,604=>426,605=>674,606=>454,607=>353,608=>624,609=>500,610=>452,611=>500,612=>582,613=>500,614=>500,615=>500,616=>278,617=>306,618=>278,619=>278,620=>278,621=>364,622=>556,623=>722,624=>778,625=>778,626=>614,627=>599,628=>500,629=>500,630=>668,631=>693,632=>640,633=>389,634=>389,635=>444,636=>389,637=>333,638=>333,639=>333,640=>434,641=>456,642=>389,643=>278,644=>500,645=>466,646=>500,647=>278,648=>278,649=>500,650=>517,651=>500,652=>444,653=>667,654=>444,655=>510,656=>510,657=>432,658=>446,659=>439,660=>444,661=>444,662=>444,663=>444,664=>722,665=>402,666=>454,667=>665,668=>476,669=>347,670=>444,671=>363,672=>590,673=>444,674=>444,675=>798,676=>795,677=>805,678=>554,679=>561,680=>678,681=>614,682=>554,683=>554,684=>500,685=>500,686=>611,687=>716,688=>300,689=>300,690=>258,691=>278,692=>278,693=>309,694=>306,695=>432,696=>310,697=>250,698=>408,699=>333,700=>333,701=>333,702=>333,703=>333,704=>258,705=>258,706=>374,707=>374,708=>383,709=>383,710=>333,711=>333,712=>250,713=>333,714=>333,715=>333,716=>250,717=>333,718=>333,719=>333,720=>278,721=>278,722=>333,723=>333,724=>333,725=>333,726=>333,727=>333,728=>333,729=>333,730=>333,731=>333,732=>333,733=>333,734=>336,735=>352,736=>311,737=>200,738=>243,739=>328,740=>300,741=>460,742=>460,743=>460,744=>460,745=>460,746=>477,747=>475,748=>339,749=>330,750=>444,751=>383,752=>383,753=>294,754=>294,755=>327,756=>261,757=>437,758=>437,759=>333,760=>278,761=>175,762=>175,763=>175,764=>175,765=>337,766=>337,767=>326,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,842=>0,843=>0,844=>0,845=>0,846=>0,847=>0,848=>0,849=>0,850=>0,851=>0,852=>0,853=>0,854=>0,855=>0,856=>0,857=>0,858=>0,859=>0,860=>0,861=>0,862=>0,863=>0,864=>0,865=>0,866=>0,867=>0,868=>0,869=>0,870=>0,871=>0,872=>0,873=>0,874=>0,875=>0,876=>0,877=>0,878=>0,879=>0,884=>199,885=>199,890=>332,894=>333,900=>257,901=>333,902=>661,903=>250,904=>841,905=>950,906=>559,908=>815,910=>877,911=>899,912=>270,913=>661,914=>581,915=>611,916=>660,917=>611,918=>606,919=>742,920=>672,921=>333,922=>667,923=>641,924=>833,925=>657,926=>678,927=>682,928=>749,929=>611,931=>657,932=>596,933=>676,934=>722,935=>611,936=>812,937=>743,938=>333,939=>696,940=>564,941=>416,942=>506,943=>270,944=>504,945=>564,946=>509,947=>496,948=>520,949=>416,950=>398,951=>506,952=>533,953=>270,954=>491,955=>488,956=>501,957=>486,958=>430,959=>510,960=>608,961=>506,962=>423,963=>524,964=>425,965=>504,966=>618,967=>459,968=>693,969=>693,970=>270,971=>504,972=>510,973=>504,974=>693,976=>534,977=>587,978=>620,979=>820,980=>620,981=>640,982=>684,983=>504,984=>555,985=>534,986=>548,987=>496,988=>610,989=>470,990=>633,991=>410,992=>687,993=>544,1008=>534,1009=>534,1010=>485,1011=>278,1012=>722,1013=>280,1014=>280,1015=>610,1016=>500,1017=>704,1018=>832,1019=>703,1020=>533,1021=>704,1022=>704,1023=>704,1024=>604,1025=>604,1026=>668,1027=>611,1028=>666,1029=>500,1030=>339,1031=>339,1032=>444,1033=>972,1034=>977,1035=>703,1036=>664,1037=>720,1038=>728,1039=>728,1040=>611,1041=>610,1042=>611,1043=>611,1044=>682,1045=>604,1046=>976,1047=>592,1048=>720,1049=>720,1050=>664,1051=>719,1052=>828,1053=>722,1054=>722,1055=>749,1056=>603,1057=>667,1058=>556,1059=>728,1060=>722,1061=>611,1062=>728,1063=>666,1064=>997,1065=>1005,1066=>710,1067=>891,1068=>594,1069=>632,1070=>1024,1071=>696,1072=>500,1073=>500,1074=>442,1075=>344,1076=>503,1077=>440,1078=>932,1079=>402,1080=>500,1081=>500,1082=>491,1083=>487,1084=>624,1085=>500,1086=>500,1087=>500,1088=>500,1089=>441,1090=>722,1091=>500,1092=>741,1093=>444,1094=>500,1095=>500,1096=>750,1097=>750,1098=>545,1099=>683,1100=>433,1101=>432,1102=>700,1103=>503,1104=>440,1105=>440,1106=>500,1107=>344,1108=>442,1109=>389,1110=>278,1111=>278,1112=>278,1113=>686,1114=>696,1115=>500,1116=>491,1117=>500,1118=>500,1119=>500,1120=>964,1121=>684,1122=>708,1123=>690,1124=>975,1125=>646,1126=>800,1127=>628,1128=>1096,1129=>795,1130=>952,1131=>730,1132=>1260,1133=>892,1134=>574,1135=>400,1136=>812,1137=>694,1138=>721,1139=>500,1140=>745,1141=>533,1142=>745,1143=>533,1144=>1193,1145=>967,1146=>868,1147=>602,1148=>964,1149=>684,1150=>964,1151=>684,1152=>548,1153=>443,1154=>320,1155=>0,1156=>0,1157=>0,1158=>0,1159=>0,1160=>0,1161=>0,1162=>720,1163=>500,1164=>602,1165=>433,1166=>611,1167=>500,1168=>552,1169=>424,1170=>593,1171=>424,1172=>611,1173=>432,1174=>992,1175=>932,1176=>592,1177=>396,1178=>681,1179=>491,1180=>700,1181=>532,1182=>664,1183=>491,1184=>776,1185=>690,1186=>729,1187=>500,1188=>908,1189=>660,1190=>1034,1191=>694,1192=>730,1193=>543,1194=>666,1195=>443,1196=>556,1197=>775,1198=>556,1199=>574,1200=>555,1201=>574,1202=>660,1203=>443,1204=>798,1205=>581,1206=>674,1207=>500,1208=>690,1209=>516,1210=>640,1211=>500,1212=>785,1213=>558,1214=>785,1215=>558,1216=>339,1217=>976,1218=>932,1219=>664,1220=>491,1221=>719,1222=>487,1223=>722,1224=>500,1225=>722,1226=>500,1227=>666,1228=>500,1229=>828,1230=>624,1231=>339,1232=>611,1233=>500,1234=>611,1235=>500,1236=>889,1237=>673,1238=>604,1239=>444,1240=>722,1241=>444,1242=>722,1243=>444,1244=>976,1245=>932,1246=>592,1247=>402,1248=>525,1249=>446,1250=>720,1251=>500,1252=>720,1253=>500,1254=>722,1255=>500,1256=>722,1257=>500,1258=>722,1259=>500,1260=>632,1261=>432,1262=>728,1263=>500,1264=>728,1265=>500,1266=>728,1267=>500,1268=>666,1269=>500,1270=>611,1271=>424,1272=>891,1273=>683,1296=>532,1297=>409,1298=>719,1299=>487,1306=>722,1307=>500,1308=>833,1309=>656,1310=>664,1311=>491,1329=>794,1330=>712,1331=>782,1332=>854,1333=>711,1334=>702,1335=>707,1336=>655,1337=>777,1338=>782,1339=>710,1340=>663,1341=>830,1342=>917,1343=>672,1344=>469,1345=>666,1346=>858,1347=>685,1348=>856,1349=>618,1350=>858,1351=>709,1352=>719,1353=>714,1354=>731,1355=>702,1356=>874,1357=>719,1358=>844,1359=>519,1360=>703,1361=>608,1362=>586,1363=>750,1364=>780,1365=>714,1366=>684,1369=>120,1370=>120,1371=>269,1372=>307,1373=>241,1374=>312,1375=>300,1377=>786,1378=>506,1379=>542,1380=>541,1381=>506,1382=>503,1383=>478,1384=>499,1385=>541,1386=>539,1387=>508,1388=>289,1389=>750,1390=>540,1391=>513,1392=>508,1393=>503,1394=>531,1395=>518,1396=>500,1397=>243,1398=>473,1399=>406,1400=>499,1401=>407,1402=>793,1403=>414,1404=>463,1405=>500,1406=>516,1407=>758,1408=>504,1409=>466,1410=>288,1411=>758,1412=>510,1413=>501,1414=>562,1415=>543,1417=>278,1418=>280,1425=>0,1426=>0,1427=>0,1428=>0,1429=>0,1430=>0,1431=>418,1432=>0,1433=>0,1434=>0,1435=>0,1436=>0,1437=>0,1438=>0,1439=>0,1440=>0,1441=>0,1442=>0,1443=>0,1444=>0,1445=>0,1446=>0,1447=>0,1448=>0,1449=>0,1450=>0,1451=>0,1452=>0,1453=>0,1454=>0,1455=>0,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1466=>0,1467=>0,1468=>0,1469=>0,1470=>440,1471=>0,1472=>126,1473=>0,1474=>0,1475=>418,1476=>0,1477=>0,1478=>350,1479=>0,1488=>537,1489=>537,1490=>350,1491=>537,1492=>537,1493=>350,1494=>350,1495=>537,1496=>537,1497=>350,1498=>537,1499=>537,1500=>537,1501=>537,1502=>537,1503=>350,1504=>350,1505=>537,1506=>537,1507=>537,1508=>537,1509=>537,1510=>537,1511=>537,1512=>537,1513=>537,1514=>537,1520=>537,1521=>537,1522=>537,1523=>396,1524=>396,2404=>318,2405=>446,2433=>0,2434=>300,2435=>312,2437=>594,2438=>776,2439=>469,2440=>513,2441=>535,2442=>561,2443=>604,2444=>481,2447=>580,2448=>604,2451=>540,2452=>620,2453=>570,2454=>485,2455=>484,2456=>471,2457=>457,2458=>408,2459=>452,2460=>591,2461=>551,2462=>771,2463=>414,2464=>404,2465=>522,2466=>415,2467=>450,2468=>551,2469=>477,2470=>478,2471=>449,2472=>448,2474=>535,2475=>611,2476=>443,2477=>534,2478=>492,2479=>474,2480=>442,2482=>542,2486=>507,2487=>467,2488=>523,2489=>419,2492=>0,2493=>419,2494=>202,2495=>189,2496=>202,2497=>0,2498=>0,2499=>0,2500=>0,2503=>294,2504=>289,2507=>774,2508=>825,2509=>0,2510=>356,2519=>219,2524=>523,2525=>420,2527=>469,2528=>604,2529=>481,2530=>0,2531=>0,2534=>500,2535=>437,2536=>479,2537=>507,2538=>497,2539=>500,2540=>482,2541=>503,2542=>517,2543=>481,2544=>443,2545=>443,2546=>429,2547=>383,2548=>432,2549=>478,2550=>539,2551=>158,2552=>365,2553=>280,2554=>357,3585=>512,3586=>453,3587=>512,3588=>519,3589=>529,3590=>561,3591=>411,3592=>437,3593=>552,3594=>452,3595=>509,3596=>707,3597=>707,3598=>574,3599=>570,3600=>406,3601=>607,3602=>686,3603=>749,3604=>494,3605=>497,3606=>509,3607=>552,3608=>461,3609=>565,3610=>527,3611=>523,3612=>556,3613=>551,3614=>570,3615=>570,3616=>571,3617=>531,3618=>493,3619=>433,3620=>513,3621=>491,3622=>571,3623=>439,3624=>510,3625=>594,3626=>484,3627=>554,3628=>616,3629=>493,3630=>496,3631=>417,3632=>392,3633=>0,3634=>366,3635=>366,3636=>0,3637=>0,3638=>0,3639=>0,3640=>0,3641=>0,3642=>0,3647=>662,3648=>297,3649=>544,3650=>298,3651=>329,3652=>328,3653=>326,3654=>488,3655=>0,3656=>0,3657=>0,3658=>0,3659=>0,3660=>0,3661=>0,3662=>0,3663=>725,3664=>624,3665=>624,3666=>624,3667=>624,3668=>624,3669=>624,3670=>624,3671=>624,3672=>624,3673=>624,3674=>645,3675=>872,4256=>453,4257=>448,4258=>546,4259=>619,4260=>478,4261=>481,4262=>459,4263=>707,4264=>467,4265=>471,4266=>842,4267=>464,4268=>443,4269=>707,4270=>460,4271=>465,4272=>686,4273=>440,4274=>550,4275=>561,4276=>580,4277=>467,4278=>630,4279=>466,4280=>517,4281=>456,4282=>502,4283=>464,4284=>534,4285=>440,4286=>443,4287=>522,4288=>460,4289=>463,4290=>536,4291=>455,4292=>468,4293=>449,4304=>454,4305=>452,4306=>544,4307=>629,4308=>451,4309=>452,4310=>452,4311=>702,4312=>451,4313=>452,4314=>820,4315=>451,4316=>453,4317=>695,4318=>449,4319=>448,4320=>694,4321=>501,4322=>544,4323=>517,4324=>560,4325=>450,4326=>627,4327=>452,4328=>491,4329=>452,4330=>485,4331=>452,4332=>485,4333=>443,4334=>500,4335=>582,4336=>455,4337=>451,4338=>480,4339=>414,4340=>453,4341=>418,4342=>741,4343=>452,4344=>452,4345=>544,4346=>454,4347=>410,4348=>339,5024=>711,5025=>678,5026=>604,5027=>667,5028=>796,5029=>301,5030=>516,5031=>544,5032=>457,5033=>716,5034=>703,5035=>383,5036=>628,5037=>709,5038=>455,5039=>601,5040=>472,5041=>574,5042=>730,5043=>939,5044=>498,5045=>528,5046=>667,5047=>891,5048=>505,5049=>792,5050=>957,5051=>725,5052=>595,5053=>733,5054=>698,5055=>638,5056=>720,5057=>732,5058=>624,5059=>638,5060=>565,5061=>903,5062=>655,5063=>681,5064=>675,5065=>949,5066=>683,5067=>547,5068=>693,5069=>732,5070=>529,5071=>569,5072=>536,5073=>677,5074=>631,5075=>495,5076=>973,5077=>543,5078=>607,5079=>652,5080=>652,5081=>693,5082=>514,5083=>803,5084=>658,5085=>597,5086=>627,5087=>659,5088=>679,5089=>706,5090=>563,5091=>618,5092=>767,5093=>776,5094=>731,5095=>492,5096=>808,5097=>823,5098=>796,5099=>689,5100=>716,5101=>518,5102=>521,5103=>719,5104=>563,5105=>776,5106=>634,5107=>822,5108=>621,7680=>611,7681=>500,7682=>611,7683=>500,7684=>611,7685=>500,7686=>611,7687=>500,7688=>667,7689=>444,7690=>722,7691=>500,7692=>722,7693=>500,7694=>722,7695=>500,7696=>722,7697=>500,7698=>722,7699=>500,7700=>611,7701=>444,7702=>611,7703=>444,7704=>604,7705=>444,7706=>604,7707=>444,7708=>604,7709=>444,7710=>611,7711=>278,7712=>722,7713=>500,7714=>722,7715=>500,7716=>722,7717=>500,7718=>722,7719=>500,7720=>722,7721=>500,7722=>722,7723=>500,7724=>339,7725=>278,7726=>333,7727=>278,7728=>652,7729=>444,7730=>652,7731=>444,7732=>652,7733=>444,7734=>556,7735=>278,7736=>556,7737=>278,7738=>556,7739=>278,7740=>556,7741=>278,7742=>828,7743=>722,7744=>828,7745=>722,7746=>828,7747=>722,7748=>657,7749=>500,7750=>657,7751=>500,7752=>657,7753=>500,7754=>657,7755=>500,7756=>722,7757=>500,7758=>722,7759=>500,7760=>722,7761=>500,7762=>722,7763=>500,7764=>603,7765=>500,7766=>603,7767=>500,7768=>616,7769=>389,7770=>616,7771=>389,7772=>616,7773=>389,7774=>616,7775=>389,7776=>500,7777=>389,7778=>500,7779=>389,7780=>500,7781=>389,7782=>500,7783=>389,7784=>500,7785=>389,7786=>556,7787=>278,7788=>556,7789=>278,7790=>556,7791=>278,7792=>556,7793=>278,7794=>722,7795=>500,7796=>722,7797=>500,7798=>722,7799=>500,7800=>722,7801=>500,7802=>722,7803=>500,7804=>611,7805=>444,7806=>611,7807=>444,7808=>833,7809=>667,7810=>833,7811=>667,7812=>833,7813=>667,7814=>833,7815=>667,7816=>833,7817=>667,7818=>611,7819=>444,7820=>611,7821=>444,7822=>556,7823=>444,7824=>556,7825=>389,7826=>556,7827=>389,7828=>556,7829=>389,7830=>500,7831=>278,7832=>667,7833=>444,7834=>444,7835=>278,7836=>333,7837=>278,7838=>659,7839=>534,7840=>611,7841=>500,7842=>611,7843=>500,7844=>611,7845=>500,7846=>611,7847=>500,7848=>611,7849=>500,7850=>611,7851=>500,7852=>611,7853=>500,7854=>611,7855=>500,7856=>611,7857=>500,7858=>611,7859=>500,7860=>611,7861=>500,7862=>611,7863=>500,7864=>604,7865=>444,7866=>604,7867=>444,7868=>604,7869=>444,7870=>611,7871=>444,7872=>611,7873=>444,7874=>611,7875=>444,7876=>611,7877=>444,7878=>604,7879=>444,7880=>339,7881=>278,7882=>339,7883=>278,7884=>722,7885=>500,7886=>722,7887=>500,7888=>722,7889=>500,7890=>722,7891=>500,7892=>722,7893=>500,7894=>722,7895=>500,7896=>722,7897=>500,7898=>759,7899=>546,7900=>759,7901=>546,7902=>807,7903=>585,7904=>759,7905=>546,7906=>759,7907=>546,7908=>722,7909=>500,7910=>722,7911=>500,7912=>778,7913=>584,7914=>778,7915=>584,7916=>807,7917=>585,7918=>778,7919=>584,7920=>778,7921=>584,7922=>556,7923=>444,7924=>556,7925=>444,7926=>556,7927=>444,7928=>556,7929=>444,7936=>564,7937=>564,7938=>564,7939=>564,7940=>564,7941=>564,7942=>564,7943=>564,7944=>661,7945=>661,7946=>794,7947=>811,7948=>792,7949=>803,7950=>661,7951=>648,7952=>416,7953=>416,7954=>416,7955=>416,7956=>416,7957=>416,7960=>740,7961=>795,7962=>923,7963=>940,7964=>996,7965=>986,7968=>506,7969=>506,7970=>506,7971=>506,7972=>506,7973=>506,7974=>506,7975=>506,7976=>879,7977=>901,7978=>1036,7979=>1035,7980=>1099,7981=>1100,7982=>954,7983=>959,7984=>270,7985=>270,7986=>267,7987=>267,7988=>267,7989=>267,7990=>267,7991=>267,7992=>490,7993=>529,7994=>655,7995=>654,7996=>705,7997=>713,7998=>570,7999=>573,8000=>558,8001=>510,8002=>510,8003=>510,8004=>510,8005=>510,8008=>797,8009=>867,8010=>1026,8011=>1022,8012=>993,8013=>1017,8016=>504,8017=>504,8018=>504,8019=>504,8020=>504,8021=>504,8022=>504,8023=>504,8025=>916,8027=>1062,8029=>1100,8031=>933,8032=>693,8033=>693,8034=>693,8035=>693,8036=>693,8037=>693,8038=>693,8039=>693,8040=>852,8041=>909,8042=>1072,8043=>1072,8044=>1032,8045=>1047,8046=>930,8047=>946,8048=>564,8049=>564,8050=>416,8051=>416,8052=>506,8053=>506,8054=>270,8055=>270,8056=>510,8057=>510,8058=>504,8059=>504,8060=>693,8061=>693,8064=>564,8065=>564,8066=>564,8067=>564,8068=>564,8069=>564,8070=>564,8071=>564,8072=>821,8073=>854,8074=>998,8075=>1011,8076=>992,8077=>1001,8078=>866,8079=>858,8080=>506,8081=>506,8082=>506,8083=>506,8084=>506,8085=>506,8086=>506,8087=>506,8088=>999,8089=>1044,8090=>1179,8091=>1165,8092=>1227,8093=>1229,8094=>1080,8095=>1085,8096=>693,8097=>693,8098=>693,8099=>693,8100=>693,8101=>693,8102=>693,8103=>693,8104=>1037,8105=>1113,8106=>1264,8107=>1264,8108=>1219,8109=>1241,8110=>1120,8111=>1132,8112=>564,8113=>564,8114=>564,8115=>564,8116=>564,8118=>564,8119=>564,8120=>661,8121=>661,8122=>661,8123=>661,8124=>831,8125=>192,8126=>332,8127=>500,8128=>500,8129=>534,8130=>506,8131=>506,8132=>506,8134=>506,8135=>506,8136=>611,8137=>816,8138=>889,8139=>908,8140=>881,8141=>500,8142=>500,8143=>500,8144=>270,8145=>270,8146=>270,8147=>270,8150=>270,8151=>270,8152=>333,8153=>333,8154=>497,8155=>521,8157=>500,8158=>500,8159=>500,8160=>504,8161=>504,8162=>504,8163=>504,8164=>506,8165=>506,8166=>504,8167=>504,8168=>676,8169=>676,8170=>905,8171=>901,8172=>783,8173=>333,8174=>333,8175=>500,8178=>693,8179=>693,8180=>693,8182=>693,8183=>693,8184=>907,8185=>833,8186=>963,8187=>875,8188=>952,8189=>500,8190=>500,8192=>500,8193=>1000,8194=>500,8195=>1000,8196=>333,8197=>250,8198=>167,8199=>500,8200=>250,8201=>200,8202=>100,8203=>0,8204=>0,8205=>0,8206=>0,8207=>0,8208=>333,8209=>333,8210=>500,8211=>500,8212=>1000,8213=>1000,8214=>293,8215=>465,8216=>250,8217=>250,8218=>250,8219=>250,8220=>444,8221=>444,8222=>444,8223=>444,8224=>500,8225=>500,8226=>350,8227=>350,8228=>250,8229=>500,8230=>889,8231=>250,8232=>0,8233=>0,8234=>0,8235=>0,8236=>0,8237=>0,8238=>0,8239=>250,8240=>1000,8241=>1601,8242=>247,8243=>411,8244=>611,8245=>220,8246=>440,8247=>660,8248=>469,8249=>250,8250=>250,8251=>629,8252=>666,8253=>500,8254=>500,8255=>953,8256=>1000,8257=>314,8258=>931,8259=>333,8260=>167,8261=>480,8262=>480,8263=>1000,8264=>833,8265=>833,8266=>500,8267=>453,8268=>453,8269=>450,8270=>500,8271=>278,8272=>882,8273=>500,8274=>497,8275=>500,8276=>953,8277=>512,8278=>410,8279=>855,8280=>620,8281=>620,8282=>179,8283=>621,8284=>564,8285=>179,8286=>179,8287=>111,8288=>0,8289=>0,8290=>0,8291=>0,8292=>0,8304=>300,8305=>235,8308=>300,8309=>300,8310=>300,8311=>300,8312=>300,8313=>300,8314=>300,8315=>300,8316=>300,8317=>216,8318=>216,8319=>318,8320=>300,8321=>250,8322=>300,8323=>300,8324=>300,8325=>300,8326=>300,8327=>300,8328=>300,8329=>300,8330=>300,8331=>300,8332=>300,8333=>216,8334=>216,8336=>350,8337=>304,8338=>340,8339=>317,8340=>278,8352=>698,8353=>667,8354=>667,8355=>611,8356=>500,8357=>722,8358=>667,8359=>988,8360=>953,8361=>833,8362=>869,8363=>512,8364=>741,8365=>722,8366=>611,8367=>1340,8368=>489,8369=>589,8370=>619,8371=>722,8372=>556,8373=>611,8374=>408,8376=>524,8400=>0,8401=>0,8402=>0,8403=>0,8404=>0,8405=>0,8406=>0,8407=>0,8408=>0,8409=>0,8410=>0,8411=>0,8412=>0,8413=>0,8414=>0,8415=>0,8416=>0,8417=>0,8418=>0,8419=>0,8420=>0,8421=>0,8422=>0,8423=>0,8424=>0,8425=>0,8426=>0,8427=>0,8428=>0,8429=>0,8430=>0,8431=>0,8432=>0,8448=>604,8449=>605,8450=>674,8451=>954,8452=>556,8453=>573,8454=>667,8455=>518,8456=>667,8457=>822,8458=>490,8459=>824,8460=>663,8461=>818,8462=>500,8463=>500,8464=>578,8465=>613,8466=>715,8467=>417,8468=>777,8469=>751,8470=>783,8471=>792,8472=>832,8473=>589,8474=>729,8475=>892,8476=>711,8477=>755,8478=>616,8479=>610,8480=>879,8481=>1156,8482=>920,8483=>611,8484=>659,8485=>389,8486=>743,8487=>743,8488=>663,8489=>286,8490=>722,8491=>722,8492=>846,8493=>613,8494=>533,8495=>363,8496=>587,8497=>690,8498=>556,8499=>1021,8500=>387,8501=>537,8502=>537,8503=>350,8504=>537,8505=>417,8506=>906,8507=>1155,8508=>655,8510=>586,8511=>722,8513=>663,8514=>485,8515=>485,8516=>637,8522=>516,8523=>778,8525=>906,8526=>378,8531=>750,8532=>750,8533=>750,8534=>750,8535=>750,8536=>750,8537=>750,8538=>750,8539=>750,8540=>750,8541=>750,8542=>750,8543=>750,8544=>339,8545=>608,8546=>877,8547=>940,8548=>611,8549=>910,8550=>1176,8551=>1439,8552=>940,8553=>611,8554=>936,8555=>1204,8556=>556,8557=>667,8558=>722,8559=>828,8560=>278,8561=>526,8562=>774,8563=>712,8564=>444,8565=>702,8566=>950,8567=>1198,8568=>712,8569=>444,8570=>692,8571=>970,8572=>278,8573=>444,8574=>500,8575=>722,8592=>964,8593=>499,8594=>964,8595=>499,8706=>494,8710=>612,8721=>713,8722=>675,8723=>675,8725=>750,8730=>549,8734=>677,8747=>416,8748=>750,8749=>1083,8750=>722,8751=>750,8800=>564,8804=>675,8805=>675,8992=>686,8993=>686,9251=>500,9674=>494,9675=>791,9676=>791,9824=>626,9825=>694,9826=>595,9827=>776,9828=>626,9829=>694,9830=>595,9831=>776,9833=>333,9834=>555,9835=>722,9836=>722,9837=>415,9838=>377,9839=>402,11799=>333,42790=>722,42791=>491,42792=>770,42793=>586,42794=>532,42795=>409,42796=>437,42797=>389,42798=>578,42799=>580,42888=>333,42889=>278,42890=>282,42891=>286,42892=>278,64256=>526,64257=>500,64258=>500,64259=>747,64260=>748,64261=>518,64262=>665,64275=>971,64276=>969,64277=>978,64278=>971,64279=>1219,64285=>350,64286=>0,64287=>537,64288=>537,64297=>564,64298=>537,64299=>537,64300=>537,64301=>537,64302=>537,64303=>537,64304=>537,64305=>537,64306=>350,64307=>537,64308=>537,64309=>350,64310=>350,64312=>537,64313=>350,64314=>537,64315=>537,64316=>537,64318=>537,64320=>350,64321=>537,64323=>537,64324=>537,64326=>537,64327=>537,64328=>537,64329=>537,64330=>537,64331=>350,64332=>537,64333=>537,64334=>537,64335=>537,65533=>900,65535=>700); // --- EOF --- PKa\۠ՔՔfonts/pdfatimesb.znuW+AxuX[nfF@{ȡATNi=ދ{׽z5 v K's;;S&-+iqtZ!Oml 0 @NOi1^# 1s٤aS5= 3 rA0'N[ {666tz)'goW[kwA?+w`N0ۯO>yS' -di @p8rG+,,K7W"d\!9 lݝ@+#_8ܬ8!@fX2RNGw7ttتs#:/MogXz 8989A_?e{uK'Gp3PR A'/@#53 n[z8_ӿ}dTqrV˻W~%WRfPﻱ (ȯ0 {͠;R`eu-GK+f]M !nnA-(hdih \]ͼa` m xr8:&=D\`lK`ֿ \@pÝ+ws蝍`kלּ@K'(tZ4s`oQ5lJܜ@gئ;U*A:wV0jfg:C=47v <@og+p .4n>:i]<@wϻ< ͯ ] w)Z>;Hyxޜh{?~[Bp *4q0b^0 K 7.^ĝJ >ԝJ ?({'@@; .* ҝ* >;T@?'PNO~'wy'xZw}':w{'zN],!0f27!#7 [[ [W -u׸Y8ޕ/l)XS\@{hsOm)^={Jxf ')0= t`gS|@{z)0')0{ 4 {Qyo-^@{Uknvo,hur:w1 (^`4we`t ).F+(^rƅotaat?0-=_0hܓ`sa_/<޿v/SVr+F&0`z1wq|N]dci q0Dx8rrJp޳=t z;#0t[;0dxC⅕=񷢇 by@0Gа;'WK+C%F_YB~_A0@m-̠鞙r"}4`+Z,~3GF_= ,{ ߳ =0b= c2] F[_;{0Y@,ay1g?lw<FVk`Wec oNBqQw|`T#I0 J#CW6 nL!; P`_p2R?è)H0z*O^*O3miiDz0ʪ, , :;a /C??¾9,{- t#>i6vQ0{ þcǿWOܰ["oX?me xA,B-\U71r@!aTvDEKK|< ^z,ұl0zuiة [džűȮmfnptoX?nXSK7|@!df5 J$h0`!.ƮxC袐e2`x#Pu`gyBE\^=W7+Iݾ.&o).–+d\-^xY~$eb"DWffn$'RhϠ*s'ᔃgވ3ȷ/$JɶAae7 yEIQ$%VH_7Kdye4[خ%Ƿ`F Dhs+쨴4ʟBݣ?е(HRHFJ<zV>bbCa^L񪉥b?XAEuzx0y^jAWnSK'kM9$`k[?6;r.n׍jHuyha)/,mɆV\zܓ^-_4SHb:xULe9 58r:[Ghs4 ^̨ lNh;v4ޞ9=oen AD0yGIG> ޝc=谿$b"+UuR$ڵ{\LK,SSbuJ-ޅe~8gPi!cnSuXjyl׵#Mˀ(hj4ճeə/^Jm 5&#I Tʝ<<^UgE)|tⵓЍtɐTv-â<͡,Fv{cM*'g' oe&^s5 /H0br ֍/&l}{1je#pBnbNEu/1 $iD5WT f_'Ӵ|'*`ߙ:6}. fsiH@G *$q lʎ$>S {Rq b:"̌V*bbcZfude9>sRClz4Ѵ=<3Noco&,vVZ;$h.?|x*䥋z,VϒKWK٧(U  'b|faX*Q_ݠx+Q"E}|jaÒZ{9M)/'FNd!Eƨ(RFU4 Wqj ZuN),{8KmrDԨnrT!}oQ(ޯ$A06\; G~!W!7t8p6AD36Jчѽ9jCT1f1k]?M H$U|74xrԛyB%!67@4+:GʩR+fְ"lKrÅkk-E84c\di&5vFE-wFR5?9>={(w IW_h On[t~zGiPj?=͵8YzȢ\-}- z)P0VDdrFJt$k( ^њ孹/&>Xa\=(.M>a@!p{z|J* 0Ǯo%sSڢFcqfdWl˙Lp*b^76?U'K/E}M3< LO RMMxN>!Eyyg78Yӊ~Y^z|Dm;/,\Qd5O:s(X˭ޔoؕ{[W\-%7i"?+ 2x 퉸Hv$}u8_@+d^`au"Kut'K #VMOCsKNS 㑺 q[J _6s;79i p'vAR>,)0P"G>tj$Jnzn%h٦On;{Fl=&4~$%UڄP M%Q'΃mNzN^!ʸgvu/{sWk!Nf6*tPYyy1y>Ubd{Oz|MH?_㞖rܦ^[ a뚃ÙdJb=gzߞ,,kJ$fuW>D}4;S t.9Jt^;j4I4{eTK`I¸& 'ء0 B kF:!:=Լ l}3rnR"Dw2+DӏYu>GR] ts[4PYOI7cc|>)Yi-C$rMQQb@ʉIb3[e{@⸟12?bӍW_y d/XIhGN'?(yQqJ&m}9\\Z̗Ejࠎ?zodżc~aRZ'N9tt:Y@;VlAHu8R WĘ, pTьߕ0"R(Ē]?cy]7!/5t;E;%p.UψB-f00J7K}l 6XHK"1ο8xR.VOFT$*z/݆q抴Q&V^kYL 3ҔOov}i]26_o2SQ!eѠ24rҸFxVj9_T`F6jHW+X ΋EL=[wg9Ƈ$mSi~ Gi\jS+$W)_"IU1[؟1$pőΤ,.ؘ~ $鉼}+>~R YƻOcCy [d,M;82kHו{|NI% 6vh$1Y1T1_$0`]B<$EDZ$sY;ƆL}ߑ784=Q&Q2':SQDw"v~TBPS+RgO%11]CwϧgP?}J!&3z2&4|G8PX_}|N@:8 6*fm˙otiOGe JO68H9Q+"f\죷| ]ֈz̋fo7Bz+](YMz-7$HI !w競j2rՋdTm=de/8馚~U5#==st^ u#-ͫh Q\9);JiFd-? @:1hzꫦ<uO!K #55ֹ V}#4"L%xT737N@V? g9P E|3|KN ޅ0!s/?).5 ~ީz$'ƾ9L ZMA?LKg]"nۖ>z/uλ9Q#;~OI073폲&?aic,-3Lۤh'fN̿OA:+V-^+H@ 5)$R%Q> TyͽƳΏMYڧ7RtPIYm'Z]/p`w9xhCWLsc8mQ '9^ZΩ*. ';/|f+4/|^hօiX9k_E[d=^@x!(q4LDh5 3HjNIכ@R3v5VIt ;zj,wS'Bsȴ|1%˘|:9Y0R< u#lAoޤ"H^ƙ:S^}4 Xڇ>tn[+F y$Ԣ$~UNc 8ۦPPO ~& ŁDt[FgqL& Η[DoLX+AܨA[I"W6YK2 1n22$l?ֲNIH$38gE1;ie)Ü6_Fh08jabJ~Lc<ݼЩ~Ǝ󟕓zfI+QDd[ W!G0b nDdsJGSi:7sQg'ؔ)M106:*KN (GO$)we:fmjٓ:deXKu"a$VF@t$>Dcp|i( ?;:j,H݄.H-CWh* wdF?FGu;6ަ(TkS;}sڦGkh-IMsRqQu y;w4!YmHӵ 6 z3^CȤŊd>==$'2 {w-ngo5O)&OcNI{%{/j5\ 3U-4ć-pTZA(;-H?|0d󖲁zf8Lm5S֚rLl\ 9g@fD]B*I>7WN  aqonZz]֏%TBÇ[C ɡ.F&/FF2ֱ!{O7%Q * ~LC!<973ǻqQv{}JsMÛhw}(T9O6B%IsF`1!l<#u&3W0dfbr_%I3P4 /jv~EjBow6Uq9u_@'l*1bu_L<zJr:Gu)Qu!zkKI}1y[HC] hH3viE&s@\eqRN b#!#ۼbd?+-¢ayʠͽtA44_K v?nb%Sa[Y`R4SD7 C1Ĺʸ3O v\"Y$ 1u,_ϙug_ʄ bO \ı=-^#M9 cx}~Y%gHDܤ &jiT^$1oQ2 p~3ŸX`M4OAJl4/-I =BDvzj6 $$4nKr AX>TOL{'J~|< ;o{P䈇 UjAJ"]I%'ś{g^Iݵ6޷_J#oXE*GIڿT]˧Wʹvיy qp8*m 8O[~I4;UQGd8{'~}!z<^J|ܵ2`r1WGQ? ?^́Gqj:O /S54抿6/qM lD?TwR4fh7 6I`?/j(cz{8f+qj4ULî3"%Ijw5%)>^UT/i> OG߽!Djo-A_ t"\H2ӧ"ϞYЋ{$ $!?Tu1QHSޟv(BRU샆wrz ef̒.A=D YͻYFTe߬TR;$Ԡ4eBYxK}W+l3eU *G˻fӪv^%j<؉y9nq7Z*f*mZkjݽlLQKSxtD8wU>UcxqS:=#gc23Nv"Os9 [kxeL^rw*_ ?ڒo_y ̷~^o<L_/I \-)s2G珤Bw;4Zj:bHT8Ǖߨ=SQ1MFnĿ1{L.1}ÄLF*xͱ8Vd;_5gOEn:nwH{ ? g C]m/rj֘ϗ]gpfnM֋熮EeW!sm׆C_<0qIJJ/6eA6jtR:'H@zDљ4dpi$| QfΒ0.K#N<\v* UUfZ#Cb|0œD*.U5X'cNg4lle";˶Dj9Y)߶,l s,qbd%$.K, \o!<).؏)?g-?PN-hviҒ!/-N n2 >K`ـRUOG2xV}+&z΢c;߿ht^ql۔lYZ:5cSM'N$VooZ90DT|An/b{nB.bVt~6}wTIIq-9"L!qedHTRaW $3F4sIY4ҊA75ofXJjٴ7cA;Ao+^8K0UEi<}=+khԨ01v%1p}jOwVL.]m 'ڷ #kY#~P'Y/O7(~R]%EG_c*A (kP KJrB=qTaNW ox|+$^>n " #1Ə7˼}_<sD _M8]䀎0?2PV[oRiWU`Rl: yJAylibk [Jj1qؕҶh{Famk4>tg+rgWzmFΟq?XQsle9 C/X(X}Pa—sgRn<.QxočwX-/[ە%돊{Oj\or8A= p__7XU>,Xd&nwҝR/8mE>ӂХi78Uϒ 'C=.kVw &Ũ+}YuDPcPJ;PiBy~NC@B_=c'rġc2QOSS/S=Jyá1ߥ[I嗥 tpd{~NpA\A]K_r/|_o_FB4|^iqx s]h}H,^?Yr4tR ; gWcpꈹCBc;qۦ_půQd'~C5|=ztƒ #ч1r^vs\D9!cth7 źB\YRQZ"gp}BʸRX y:8 <9##nML`x/.toqF7n$^`jLSb 3Dzj 3$VǦR|3p Z蓒% IEp}rW&ˌqx诊L`<~<_d cU@+u̝Ck!E_hAG4sq)%hΏV=ku6hK_tK$닫φss~Am,Hn.B\t2㩴y#WޭЬKXX~n tXUMjX82 GKJZubF1U wr힙lUOiң_<ٞIi)+9xKvi ۭv{|OPC!)"܅+)Ɠ‚E-FYK݃K6ЃJ/:IV,A9ʅ}u@!%c|`1Rfً.9^'`3sV| i=lGJ" Rpؗ4$Q A^K}%mRRDi#>:Cz}mz]S]>INgr5$x 捻FI*0#(O9}:ƴ7yúDvfU#>g8fE̠~CRo~mw2IH^z/^@$Ќ4PnND6GY{ {\>Ίٽl'mp9QA<GirB I.Rka}3w~ LnWBJY+[g^Sˤ(1,ȓ4}ɛ c]IX^-{ }>'v;-F8E2|C?J4Ij5`3gКyjhq-)< ƒ[9,"K4z0;`·~PpOFuy1,zI~-?re}w4ZU+js*p[Vm6EUL8<\`P uY#vkmRW?]}$6iA;WHhQZ; n?Coa k*rG]`Pt ^imaP ~GLҊ\blD#b/>G5hJ3E!|:DXz !6Pof43 > }{=1\+/UZuo#K\Ӵ`ҞXz?i#.s4c-t#_z=ĹB@JJHcQwCw˿fG8}1XJNXi)[&DGqiGDOǭM޷5{QhL/xAo!5s[Ybg$$tqs1fNr1p 6,dSɌ2hWO4V2zCZޣ-K)Ď.AY4TgA[Ԙ|J W3QKS{# X+D;x򪮍)_+vOLP־jҨ dkUq;RGD47scVzmt$jU:<*_ {Bޮm&[~8Ҧ㍱]l?h\N#҃ǜդɩU$DE30QO;yJT kqsTsuzM)nLȀZR>>J$ j qCGÁEqJ.V\(Tɗ5r͌lJ;-J$P@1&oX|2WQnko]˘TNw>T'Bl=1<4qK&|{`I;6 :1[cUl3 ft+uZZ4$D6 Z-<:xR!@L&k&ЮB@!JwmGC m#4,T 1;O\?۪g"%%еXo ylQqu߱3 ?d'}<Cc^1Y;R7q?%)NȢ1Z2֚_MPBYlq/ p|Y7#z|JBEGɭ:k(c>RVO6/a.tnoPyQ :6T(Pbɷ*z-\q CҴ[IWc$oCcHzvxcvȔL+(.7%e"M+Nfڎ]՜7/_}7뾇&#Ӛ,ע:<SfQ)FgČ|g/u{y. /bFE¢!-ίy: LÌ+qglxop,`yM{Vf>#)aAodԫI5- "ࢶK |BPmEo'7"DhVivdzw [Vw֝VF7. H+O5~NWڲ~5[@7h#Zģ=SB_2_Ɨ&7dѕR[IVf*h9>I"?\O.|[H[QZFpU/TjʷfbqJyfbfe=Ult߲s Cx"])ȴZQzJ @/9B:dlK$Aو0~ǴN!D Í(dgsg;oIQ4М4_͸ (RK?H- /T>IOH\cP ^y!2Ĥ`$.F8*|˽+Rf<˔BO&hkd~^˩㳵';Id-"j Ci~-"JTDbOkN!38Ѿ=haRƈ=bZ,w@6} bG֝V@g43ӬK%X{Úo_<6cvS%a8fEk kJ~>xc)KCZ*:|آя/<݊jCg 3i>8 M_O:sAeH&C<%켝}t Fl$\5_q\hFh߆N|Lʬ5׵JIYØ2A i,?(ùɶUƒߎB6rp8J @Ize8>%⨨9vU> +k 1N@R, ++ .*J=;J37AymDŽ7|'u~TOjsCr+G6L2já1f X0ؽ5so^4 u{d\$_JAB]*rJRy(|<@:_5M q,  wN4*&F0܇9؟,ewVIY5[d( jIc՝ зK$?=7ewxvyLb ڤ?o\tw[ ni,pNҡc0CUz](_>L%"F|14fp ;iH K=d$sȓpKbow[9etIapm-d?gy)?i Vsa{ջ w4GgOu/5J#\j_[҈,͈cn\{۾`jԜW>JVMTvQؒ(oD#By :qª0&p4!Q:=7.cI+#B A 'shZf;0pyKb e  af~gQ_g*Q\\'g@ƪ"465[D/gwX~g fOdx֢ WihW>w`ܨ_$Ac@[=ڈ>TE߃ lRofM /Ro=դh9(%vfB9^A2?I;[g-D+e ,n::K(q3Kr2q_uACtTL_+VɕB8'3ע9ٚ0#.~`zzca_;F Dk2=:66&.]P3vü@z=53bWշԋ=Rm4 ʳ0x!a`3Dٚ)15+{,q=yTgsJ/XʉYPQdAt3,:JG80~bHT9"#qWkM7- `u݁P#ƆNwK/p"Qz[8ɞM5]s q K ݠv$VBsk8$J 5J2 AP zp c9D:40{+H./hlNF|u_<,oɦ5oz? BFV@ :VQ| }PX=|SJvV񫓗m-[ifi'ɰ8WAe( $<-Xzn HUcpJ>N%풲E` EN!ý04A񵞼k=MƷ2;*_ϒmÝvo=VuNڒiRjO^}j OifXKDp,]R(!$Z(|[D|2+,>/ٱ)c>.X'mʯ@v=bú~j؂*p'kꅌʛ̜-rzwP8&bKRp+||6ev:{CCXd&"0AX\:q_k~UJ-wD3ⓗ7ܜn؞C!F3emՅW BO2JŚ(s%\J?צ) \XMN%I JSnXajD `kCU:pq>I>A|E2N2ut^H4ʂ 5]MXVCB BTn(EXSeC" W/&?F.RLm\0230Sn_#9;_l@£x]c##2-R0_urO ]OKԛ:a4+ q;.Qdj%ATi=.VNR&]6#}&+ruLIԅgU?< 枏ݵA'@=wUɻoPϘ-{1fM@Na .zLjY'<#6V +%7Jr&t\9lS^B'H4Fܾ$얾Şg+1ޫF{UHCзfO}&G8Xч#ј\mNr&.+䉬x^3BpK+Sir)(? ރ[ W-tEmsj[R{j)̾.-jC DkI\+纐mLw6ϰQvi F$7+f"w7zƙ3T MΒ`'xotS"QD][+`O-,L.{4|^ʁ%ބ(]o"ɼow:O;6ˌdw\6 ӎ N-B..KFyjGv:WDv`7Hc1;j#E;hJ]Fu@Pߊc5>/\Ǜ9{bz$өl[ '$Ъ#TlA)} L#S;ؾ>E1G,rvRФ@o Ŏ[BI|~Au}h=GpiRG-S ۃ<߿+DeD |:27ybv [WS!Pc@(A).5ƌ6S`(|(Rgk4O | CxQDJ!F)!58+5{Y͑mg{֩{{k 0J- L܎z 0 '^DFL0W!?R|@!ӄ(_ME>>I uZ_ܓp1NJنO~X T?N.5Ĭ:ELGc~-n UT p;/,ѐX~m߫sVf M͞_j4SORZt4UjPL51+p.$LLc8.Bo}LUۧ7~F,:t^ۍXm Zj^xY)7s 7ܬ]2S26u`7EBy05"hAe7`׶y\lܱOJG:6Li?O:p[c''븱O͏~wΑpQɤ+Qtі"_;h' !E0{*jLN#4qs|=?yNӉI p_,kA!Z%<愮Ҳ,+2ȦWU 'muU{%=\=oTuz 0X J2@^z)+dihSTڅO:gJ~w_X^&I/ jFcLx:JhĂ8ڷ+T<%+LaI|ǜgȬ;EtD+HQRהul,r$[ G1ywJ@݆!;,%7AWsn58MZdAn"$|9(-+-`o9.Z<|Gwh* 4T2irzHCԩJ/NWI6-]puR;$꬐>r4:/=q-vr- $h:UU B!]VG2W 6eNQF:k!&RUUVO)Pbs2xnG/2x qAlr*35 ۱Tdn:6GZp]*6kzWbQġq"vNUޟl\<U0pG:Y}'>'MW7\d' v$ FD&R ܉G["G+cm {i0$ؙѝQq.L}_,Fh`*Rq*bvC iA0lWvg6/?dW#VQNV`@p ;*޽ ҩ&b?U78.F}(E1 l7,Qyq)E],N KA"IΒyE$AvG&yH$2Z9S(ܤv#aYǔ ծ) (6ݙ<3],) .)Қ\I+a|i!oTU&#YX&)4u$q"БĄnj*9ckֽ*Z}pͷ[?$*`:$VP-gy `KH1~~ WYKM|5Y ʊ٨3Cx=^v/~zNmghhmaЭ :@:AxN<+kp2$ ?$z 0`&u"L-5%mO`vD_סy&6i.6{E\2UFJPl&|0O3ƾv{6e-m \7`wd҉N6VnZ rS)dBQ}R;Bwj('p3)kkdL(lLD3`oNLbF׮NQXPIc4Q%hx/לHV@J&aV|!'RCH$ .DF+pib21J'"RwAH3z%R >?Mzcƌf iswdmrZ)ks+ɧvTϒwzܟEɄQo}:1վ6!p}2`{ F$==&STtWgl;!XEH g}>>'&kυ -,޳Zg#ųWR6LUY3;c4 NQfW3NJSXSP_ߚշ0W00RUmDwu \@g+6LC@?Z۵aH1[ʡRF_{unH4Hj"`|'_.m6 yo3j:);&%51CHGXj~Q2P=*f J g گ:ac72` 6n$u8I'Dրߊx؇zȕV ki[$"eT<ڬJ.ӄ_ a30R$e/=)Ppc*O(:O5\]PvI31\$3g$}R{ ^.ѣ+ +e'f1Yc_,InqDnxE_/Raji0f@N)W*N&b)t]uPrq>-8_BL E,^ ]Z2>SzdE/vEM]"U<1oE 6>OH'e<| p]|} 2׮&2%I#^)'I aGSޔVM@ M9Yt3s;9AIrC cEOk{9*q3~R*BP)rp[`ʆ;>c!-{倆.`m @o:5$b )D_.^yMbj}In6=CJ QO܁MN?"<[Б|~pRlxMyOahG?N$cvRKfab/*ӎ#~SU})AǮ=5BD57`7CM7Nu: >1-؏]3Lj8" tlDxñJ~o-- !/LIj['):eZ<݆øƐIbsTKM>Jl$ڋ.̧G5 c0F逜FpU y|;HR{8*P*!//s}@KѦ{k*|N.CLmS] 8(iYC(X` iͼ#b0W:dop|0HdalU0'+qSՉVƵɾOH?&<\m%yMǝqI'nxTfForv 2߭,Iw2vJ# )1UE0#m>EL}zG` BYU~!jGE Xc T(-JIط&[2>`JWIŤp5ؾ&0I㞰!CR "chOY~^yrӎT~ED& Už<#7Eu+(IBN1~#FCnZ*t"E !` ij&_"yz/\Ro} +]w74ÉMq>"b-&C$,*M»&?S'cTz!rAzjzb.ISV'bo;/l-#2DX{xtm ziESWO>>htT@6lg3Zv\oF%Pa6CPZR)Z| rKYt #Kc*VDr~/هojpaR#VL>Юy QU,AAll`׃2D8|Sm;#θѬYI}RWAYL\-p@u>})'5V"4$0R+anIG/yeA7vmK]BzQOvx܈>y>:/F(~Eq*35x_|ih{`qioJb%~B6l d/%{>"*Qx}o rsc @, $dwuj˒@Q [[pj{p$~$c`,f~%qqe~|(n޾^M4b~u퇶Ĕ~,v2ȼ%'!H4L۶ lnUcY/#$K_3JZ?fIۆvƗLql?G+xN$O\m-Ird{DZ6ؘ+'0p%w Mȫ}Ԍ[*: Õ<#a ָ-`h^% %s1ĺa?J6+ .lۚS˻lSvW@PctpB`2ן^o,7Qi'ٌ?!ӎc۪촳Ll2EjMЁB K^GțB2L-[&MB+4yCitr'qa q*GoI D+5i35 7]ԡTh:0dK~1Z[_w_%Y햔Kmύ[r.r.=W8{髲.TjX~Zv,3\?ʲp7)9bEҽ'5c yJԏeHm Ÿ;n-K0454ZY5kHwA֐IQJe "U[~=DNmPlf ~Gg .}mX~jҔ|3bHPC&ڀ~ݐ 'נ-o7~ t.`s*>"3èwb\;'),3xWR11.5% gKvGC'=(:DLJ8/{-"P<_;dcO"}݀+J48k(]v^j=Xg&n m8r],LpOg.L~X̮w?j 0KNR^ԟBl̈E %}Biz+K1P 8%p.@">nmײXlp޴q&Cn4lVޓH2j= ?|c퉐umR>&fdy\b_IN3E/^H"BGL%,ޱȺCj *i _+#_r͖QӧS\l1Lv26J$Ek6}1Nt2%TltCh(xOJJJ(dtQ͛7m޴*vpPꂵIZdRbV>k9s#u}͹ESXun`VxMBg[#5mwK\"Q pSG 7Nq^f`G|qkohewm,4iw].`9s1C-T\E&=DE]gy%@-bJx"-ykL.ƼF\JM"N@=lD4h8[Ofy'q׸̋k_zN@ÖbJN-ynRc'yc$dÁUk߳3K'E9yҽ9+6`Xу@f2 R+ EۀB]N1{u_$!pd#w S=>X}`b:9x%w;A> rm7߳' 5%QQ4jDI6EF8{!95$lQe&.=,2>,'Tʓ ?~EK>:ylv\ɰ5=I|',qvb'̸U7qKaUr|K!vtr/C;l^vdʏA `GxGX,qC99kEybr_>$E|?1 icJ}d?fH >"o{]z 8FU-bKK6KF/UokpmyzCQOgop%##R SeӃ/q:t@Uoڰy'kKQU [33GHlф:P] 6.Zb<|o-i n͐`c:) *#(Ko ~issQ?4-걽 {a DUþoW͟Ԓ "Iw903;z@+@,uC"^WB[y"W}jP+zqqxP#)jD Em'DogwuXES4kS~Bև ɖKOL8i }ӌU* ӯwJ]Sp~&!D ˆ:CD ^b z%׶=lh♟1.э},}]Sr3S]Ucoew rM8Epx}\}^-tdA4"5JӇ}C9LrF &=J:qsrqfdF|LjěH90bhܴ$]3:XD e]NߍA *HB@)kRJ5#-:;::88h)VdZ}<$%廡FtJ8U18?wZto.+3fdߪ~OS2(&C84H\9Ǽ*VٶY'FuKט'RWq! _v 1ͺ|YKa򈞒?K h \zӍ/ :_eugѥ3[ھXVCN!fjd$ &2|(&N~sK8K.?.lDx:}4$GN>X z)_iZdA/c`ǪUNђd҆rWWk]My@0PqPm kT~*< iI֒)Sw Vv]~ԙKJIπhZ  _TpgvRl:i⁈g8 + 5/#.}g)U{hd-͟:̄b9+.J)6^4u׽a 3%ҙl;U|!㶹Ef⧐)9}YGفѽՈ,umYbΧ\>©j~5b#Nڂ!MoQ})&J3-6r>/'3h׬؉g"`>H{jyǓ监M$S +|~v"UI̴{ ֮* 8u+"4m7rIKڇopsk_AU~ZCRujGuqkaXPn/ng.UK|!#4L383QFw'xX&vI$i%6o8j59+3+qM/N 4ONx/\e:]?8@7[ZYTB ~Bk ̵|űڜ>]<%#q\+.3to#^C d]WVsE<#*פb{WT"FrPip[*:m8AeV@*zϺI ]z빴d2z +iMg-'z!{T:B|ص.ypU$H>|Dئ}*5iCv Hbuoq[~%Pp׵9 F*೴uLR0SmhP_2Pe{x(Lop|MWC. Ь U߉ܚH!nKY-zeJT%JD|S#ńoq[:{ PRkZ2R* )IcJD L;cJvKi7 X"\1ЉAV1 9{cJ,lU(uLj`L᳁9c4E8==ÏӉˬ{L<{R?R0F X3oEj~$Tv#3S?Hɇ"b ^ǪʹfB(^G.vw\QQ$DM &&NW! ZVdw}^.I[{Td);[^)EQ G' u&jj叜h\s)pPG0源|P!_3+m̊=)jNę!alt9L˓n28G%MNI#TʝĿǗs,`zkL]z&8cEnje/s]Q9 N)HO5H#}Xep8|vO3`~YZIZLleIq$Ec PZ<ÉQH;[*d$wޟWb|^S\#a]kM[Vn%.t|st yHe^cSFW!YwᘒX\0B.~~..v~]wWe>X_ }1`D*|m*\I U&h]Ml%i%%^*Շ*7>]˥qR{&JTXBH!R 8ֲE}?I:DLԒMW`S{`[ˊY|&kcxy{7\LXCD!0{l*\7=٧ 5w,Q&1l_ c_g7 MY {Kd5IY;e>@e5;HG]K* LmZy_InHCOr5m|`.^߮N~r]7Ә(ת>k4GƏe}W ]8ˬ:?ăh ڎr$54d__rpǩl/|7^`mZ 3 F.~yRJ' I;/afu?%8d|s* Ǻs;#x[z2O4?-~ `i𞠴dGu{/H+pxgf ĉ®TLaHEлEiDKE"/{w9nơ| +]иDd&:|KM0]hn|x6 LkVI>&&*c}@*K6 aWrR/QfIJYlΨbgh [YcS3N%s`gDZOt`nS VYy2 ף .Rq8FjV8•fX;al# &]b9LD>uNNL7oxIw&>HzH\^])-IJ-Bq\xg"PKa\QQfonts/freesansb.znuW+Axg`TI%THɤ =!zW5kBDEEE RDEDb/TL˽y]{]ms&sBa-۷UkiNWj;m} S!=JKzz>y^89"DƆ={wL#QFJz&%I!$ϰC&-7_!b\9rpxFd%?tQLzD`5d$*DרqFx1!ʍBsa!ï|~siOMFs}f>,/!61e¨aDž6zM7q\'y[9A7M2~S<% yĤS )obǤ)#&rJ(_OS=IUję矺P̴:[몸U4|c}Wsfg_Gn䣢JO{M;-)?ю 'l֞IFSJj6r1j+V(>CMsnMl &[DE;22O$yA$kf m!~ɴ@r:r/ oB?j : 3Y2b& ohbm(]r]ۢ3֢HoW8K6uW u1?D}(Ev)yZ;~PS:Sɵo"#9R_Yl((CD/'J/M^~D@1#A!'CiW9Eo+O^W܁b urP7ˁS'~ #D߈ z,T"|wMłGWxDCJUBnR fʯo {&~v7Ϥrlh"˷uCX{l/Q>8 V |7EoV~C̞A}e.q)w9b8V?jcn>v<21=ܣS嗢2Dgci1n}Qgا-*d m8~J 4!~a1|[42lGٳ5~$d=Z3Ёvm)qbnnCo"C0t :)MOC}Eq-,{noYz,A~}}s5OL3j8{>6(WA co:9m;W+nלRu?DZՀi:= VMn5PDCa2R͜.cu-\KXwm.[Ow]Q.Z+cYܡ*rmi7z0L:"U`QF橋u'ZkCu.* ;f)-fzcZꦮhWEn nbx}ctE\O{sD`uЍ9v/XxC_m#}D,;}^5=*Bgn'܉S*X=:i0AAj}Wڟ ^nZ׋4 Ey~۬;Fm-&5Oo"}CO_A]u~H$u"@gʦP;~zB[ J'B:F>Q/C_q.պ:u"巎 P}gkn~j'[ 4{w,u(93(po|z̡#g"+kK.@mt nua]9| -A!e|\(v@ȾsPq6uZVG)Ah'֍v}93AN9=X,c[zM6 jXn{_c7|j0̱}!Q[uV֎r lLkNbaȣDLbW׬ NGȝ:\$]l^t@DFr8i3qڥ.kHf:SJ}' POxQ2 5vҮ6cu+2o\boPn7^+x;:3?33hg@2_lCnid*+xB0_J24= K gLeWkUwz /9C=ˊQ4z59k4#k)#߽nlGy3GkkEN%kG'w]7J);#,?b?:oqnF"E:K@d|nh.+.Oucbްo!7mWeVg&ms NP||8C_7@ֲ/e/qɢ~5Sޠwݰ{&R0{C*c.#(?! ٟ-UY'sho}R%C ; ff-VC )[2ex7#?SWebu"z9s(u,O}OoG1a7Gy{/GrSq _tݴf쥞+9䴞WjocDk1_~pC\.W[/9z^oK$mB< &=-y*VѧdCJ>u9 R 7Ef2v3&")a%3n`1px#5\ϧSW3ݖ]ܫA\h-̞q Uݰד5Yb4q+Xěi;iTf'd Q^DH'<|ZL%iس>&J|~}]e+ukh-a9Dc[6~G}Qs.~U?jS!@H.y qe_RC܏ ^vYD2|R~_t9썧3 ׍P*נO{Wg3*g:΃0α Ѷ_ Ol_gkY~0`:c2d~6~1j]5eXm{sMOtOr9}/> lsoFe\k23igy|*'2lFꍹ\a/LǙ?v٘i-K_kC}l[%Of-Ëo6ܥsC#k a]36"/(7lbl|{gmWm2vGa7_bl?q.hsP;B,U.D^J_o˻vkhfPb1cAvQ}-'.I 7er`*}*w>Zg k%b{.3;Q muWt7 u: @.~h|E:}_:JwɎn}goPd'}U$̫2![e5 ^8Y 7kml.V3.\vN3B+hO"Y_ so95C gSsޣ<¹Adz8 ;DEx[{1KMmԫ5+%`g9G[]޲/y'l(ge9Y3clL)֢τɹ9Y(88~o4݋7.K̓˫Ze&f 5 ~1\51N57irjgN:}t====׽Ƚ{{w ӽ{]ϕ +V?l@XUa] 9J44ٴƴiittfi6̞fo9l7G̉ds9<߼ü|6:%i_x#",E5*jbtaˆpp#FoQbeSHMb<&" 0M<-e0N25.rrjʩiJ:t.ݝܛǺ'g|]H9M5I&֙#9<}EfGten{$͜mnG=̻'}#Y##-u!nG o^y%qۋmGlmڶ6VV٦&Fmm%,[-fBXhG/^{߽u箟~Ǯp+UWf_տR꟯H3~SOw[~u}MՏU?w}%]wo[ߺ>>>>>>>>>ҍK/.tҞK.K/x_G.>uuVϱ==_@ьlYaY^;JDBĊ8/DH-E+,R81t!2ٛgVxJ<)~q@aqD<# Y1qb_Lc]GJ1MBla[oQb+ Ůoqb!]ωbzNU1^T)Eb"} .\NYw k˗._srDԈbk:^E-Ľb!r&<4[h .ueu+넥 9,\*7['}dBG\BߥGY;K9O\WXPgW]첏U_٭˃,:zCy9WKs.WnZQQT'?B*]۔PoR 'c3DvQDiY!&ud6Uw=w ݮWMoxě\*LCƘLÇE( hSCu!jSE(upb+n#h6ޯ t6u&;T֥gNUcP'KTݩ2DuwQEB CSV1Z!cm˕:TԙJr@¢")*eGe([(({1fX$)Lꚍn򋯣QurRZZ_5۫hyh=XP*DԮ׶icW-Nq3{NϷ ǽ+nn\7ܸx8nT7gYЭ7r:Xczyhq +T|:WUߨ҂ (0+or{v 7PrGAuu_=a.Oƭ0|d8ZĵVΓl 9ЇCz@PGBB`UѯC{C\=;5FVcx<3ЇB4 ̄nB+L8h}^ \odz_)M!|LJzx|ݗs/=:ĵ? !+_ oB̫iF Mx'A|.! ]0䄡S>1a2ׄƌ|3q pYB-aA y`AlA"6_F b=1ّD$r`_Q+hFhb.An -z@X!6§'b-8|CWq)x㩏>x ؐ &&H]ؕ]ؕ]ؕ]I+ %$xhO=%-ioZaK+|ъV5qloZV!?$K2$K2:&SB} I>R!R3TRJ.\L/i%i6 ߦ4|+ 4xMGN:o:O'!g l lͤ_&D^~B,tB,l"Y,-fd 39$\asy#6`s1/@t)@t)@t)@t)@Br~ɫh Fk|Rϊh+OEAf҆-זЎvĴriOw#y֑t$:q : OgvolJtE߮g1uv`o (!>%ԗ"N[wt鎏ӯ2{O{R;D/ߋqӋBF/ЋYol덞ɕMob{}q|}г:!~}У|} V_by}ܾİ/%~c_v#-Gn9rˉU?a?xs?ѿ?ӿ?qϼ t@ H9\*}VkV;}`97/99@AzD`74B!2C18k(Xmðm97 Ca#g8>Nno#?G7QEk46Ʀywco uc3R79g>nOxdO iceMWDtO&addLs2y1)`O~ 1T욊ܩ\OmMG?]*WITJV7_ f33Lrav"of? ΂6&γv\dT*G#ow YH,B|uY]Eb}G[mc1n1/!_Km YR|赔X⯥-{)>XMK2x20e/Cel,#óػ,n>Z l\A {q]++o%:ď+{%+Jt_IޮDjVV5F^5ѵjVa*d®Un>[*| xjЯ쩁jુo5_Mns5a5:ƆF5?k߬a Xkk ւ[NkZk1i%u}i:CuطY}==co=1_ϸ\_7о_m@ ހ6ж?mox7»ލFlHMhS[a&߄7a&co®mFLjU-:bC-:Ղn~ n?[k zmA-`n[ow+[V Vߊ[<6 ݶ6mFmGv1܎赝nw@Alvǽ~{{ Nw"}v].b ໏͜w~?c~r~~x_>c rp]:?D={>#K^>{YGG|(<(>~ >y\ԑ^bvm#VO d>A^< fOדI|$ϒ!9ɋy}{(9u^z1|w ǰyp )O S4:&FqW>3!'_%WU׳rX1_Ck^g\E/sz|>o7r7My~o"-—7F{u;𿃌w] ޻=pțާ}O~=y>]<'7#<~9OΣy0. `_ ._ .`컀_._""E|u#\L?Əcr 8OS| ?~\/Y_ӗK%<_G_Q5_3F%|p _^⺞X#t?}?߂}_#.cty?G'bD\~&N?㇟g.#2/ z_W~ol7btW{?\E5o`w ~}X n uݠ l7&}os7&~~7&ox ٷhod:w6tR mޅ. )茐 Z.)6c[{V7B:VB ׮B B! Z}%d#7B2#~y|bS _H Z_DlLŖێ8Ö=@:uu&O:# ]م._t]+Xwv#%9%ܗW N)1Owӝ!z⧞󤐽" ѳ7u}hup8˾ڗ~}a>*Æ2˩?9U ~a1 D6gh9!%Cm0}J̆=c=u|;~$1<,G1Ght{9g,ql81F#rvG{z}8=d/ b{Y{}އ!2Ÿ7ya,G#y/{ɗKg/?_> ƣy ?=qrq|8#=q#W!cG#!c#>؇'x?> >I$?BS`Ցux??{̧4q~Ӫx@?dDA~ rC{!20~}xYϢρy>J̏xx/ǰǐq ïLj11dɁ݋"}^/_D?;Az@'h?AKDK:K𼄾/aKe^Ɨ{eex_e2Dד$'?'=IO}$xqu S"?Ep 4اir4x x_m0B+bw06΀ygw3_U_%"Utzԝ,zŷgykԽF}׉1ȿs ty>o"MxB[ `;Kw\<>:~r"/rE|܏1y1'>AOSOɭOi}>Cg3?'N x _˗%c+r+55Kzd#ob Eη-~m"[-x1{h>??#~ B`̟u/l 9W* *}"*:_Ů*6]W5t=א}8]Ck̅א}w \zN~ ful7 n0n◛m-lgڊ6Ɔ ,[DtYhr4_: F(pLhTh/tShNm9 (ʅzAӠM>$tEh.|.2^ :lWpp ]\߅~-attC/Iwu{6\;/ Eow\yX+wZc&0g}$#,ŐgIαmZjm}M} B '^:XYɇv~…)~3aBX2,i):gщ 7):lF=ᣠ~Æψ'fϨQׇm$(^m& aQ"2OEgKZjT4~.~4g?ةc4A.h9mQmo^mL5-=i@ WMC{ !IA).|E x$(KxTj8`ɀEHlhH[ ǎuܸ퓓'˜?Uj/-4vla-{oEicQ׵ UȰ}"HyJKcfD%IUj5J DYte5ZDs{]Ԯ;~6BOkݢe!ArW 3taO0w벲CBR:f"sZphO*oQ=oYsv[L݃O`I}^̎EMH}b`ɗD:E}EE2$#%%%zx6mdkvӦE 80Ύl*륟B#@;<Ң>zWF撖'-n!ٰҒ=`o.ސ{ gN˲vY|*Ye~5lJI1XlsvV5'c.\p^jԌB) Rv$l4ܢʅSb--Y5 3k~j[9yȩՏlj|&]|,i)ޖ;bP#0V{(ЃRz\~|/"-*!S5CJ]d5ԩ]iI-Ӗ9&-:uxЩ=JrryNWvO|R )SN!UnGGd;%*,0+lV'_(W8Ỏ{M͈_3z qUT2pl|ǁ|cqCF9m;XjvO[$'R9|b풞0/VbZ/d fʨZӀ6 SUVfꀲ*]r]t_^PAdg|y&*">2Ig8EYsa|"cLʓbox!-C,9m]f/u9+ǞW C嬹X t9MW龺yQ&}ک [=:^Ko L*YKPYMr{VW[eLT2~ᰡ  IJ;2/Wl`S0|}ۦ?ޘ#-ׅi)u۾(\3UiERgtôS:EUіkIӥ[Sf+ ob987GNWaQg{#&jyN;tr\ku$.jJ<<:OYpgn\k[ipVi,"4o"9 /_xY]jr]59A5X~1 aA"{4M[Z 3|7:'C%4}4jc*}\Kr%7!Zy,3KbLUQl7ͺ_7Nc<5gU|g ZqK,^6H7tIyZ+(.Zơ-iպQ~YOeHQ;[ Z]QYV11Xxm}hicL]n1kBҿ9/&0HEXiVۤ ڸQmؤ ~Itzg;}#%C5bf;^htk埘>1c<0qmXc rCZ:HC=zZ?ya xjό Ђҷ}/ .{Wl}/5cYUU\,=NSTߏҝ8[qXY^}t9jŏynt犯/9~nޟ Y}}-WTkb].UUL aRsV k, ھ^ꙁ5>}g[l=#SÍˈ~McGwt%y_//Ł1sb算^}}'Loe=UVUOQr1 \wzv'ESf|iO0qIt?vV=;ǎEI}s>DEvs̮'0@~*knX[u+ 5}::(LMUU%) gVj- jInU7NlaT;_eơyM2#E鹡M}1 aΞJJ$XC ڠmKصfcmK򻌜8pƔV-b}X5wzN~jb|KO_~NwkWf_BLeɅk[{*=[c}v=M&7v)Ɏ%rO֦Ϝn0j2[ *U׶y^iUz׬=u}H?iV"kv#9ݺyj"HI~Ώ7Ҡۮp0AX]YBMoDLRH7'= ?/|R4ɳNz Gu>wLȶB;[{g?P2AwW±?V ,&uPqLwbqSzr[ 44&ұܧL-=۹{j>6m'e|D KZv@yANgލM?l}727r[xXȮ5جa[£qDžhѐa553GNK-"ﯚ[S٭:عpdcZcie|KӔ:sY#\y$ȃK%iYIn ::9e&p׾Y hДԢԢ" 3kC%p+:|eP+:eH Sv|̡h.R.$Y_KVd٧N*:Or'NQr-{EI>k~3S 3ڵӂo=螞 Zu>ꑊf;UTt26:s2Ut9Fȹ W}֘ѾڃeKڵةaL A<&Tog[ëZy>奷e2yqK>Sy'j/mg+X?oxVJf;kxxKTs{wvmطQjxߐc[ mf^.F7&MB{ҧSP[J=a9ٖgϚ= |c\4o4Эip#ըQ~!"0|uF-X兙LiwZȝ($-LC!n+{z?p ߤ[(R~}m]ߧGMeu1}يT?NZ;ރu{^{>" Tkdtio}Ƥu:5mfm$2QKΐ+o-ܚ5kd9UOeȻkO`Icljm-OG[zlR:G.lМwȳ9Ps}P O70Nv*ӹd~^6߽m%2m3-"c'o'h66 tcbsOz:{y4 leH.iÒ[zl̫-ƒ\{872x}wm]j2|nZW6krfԟ~}OZ/@}ƾ{waF+򮍕ϫ8-/'̵8W }O弪OYx|[iM>%[v􋝻^0ȡE φä"O$#GA dsݰW֯dDˈOnhflM=4O ^ݺwo䗘Yj97p#N>1BQ+?g d(1"0e)y-h&9Sfb8-3Y>y ;0k{&lljMc\B#NՓt5IFs iOYz51(OW1*"88bT|0skc~AFo'V~[TX2G{{%%"ړՒ "SS-QړeFZ0#"Ui5D=nM-u3f1CvRuu%99i.)~fuRR*4pcR;;0440{wzcky3Κh)fό27`h4oJoɳGQa?Y Εsw\R=Mb#θ끸??K6=}EDZz{x 2XwN+u戾;?iݬvgS>ƶUC_.ѭEIiE۬쬄$8?0#=࣪{̤NdfғLM4H: BT#Qt-(vem um.֕r̝$"$3vX"R1?t&mn+"JSG6P;Zm.~L ss ՙk7eW3ܐ\bW3f5cքojSrѼ  :Ɣҩ3 m]SiՁU"8+7{+`]?]vx1MH!lhEq-^v%[X$24*$h!=qt:X$ ,ߡFz*F@ %M {mKEфΙ(Pca!>9Z@c ).֑uNEBpB^,//$~Za~i?z9 .33xG \U}T~cc]y}i.I('RN_1<z֎u.荨~kz: d7{nGj~!+v-uŽʪ|-k;`1cw¿rCh̿3cD1w~G"܅GqXr)$Lu-\z%0R}'e;4Zl /!;cȲ<8?))ўV՜qWn߱:)lNYk8fDݘ1]ovl5|[Nwm>9=gVHطe>DdF?A 7pT8jkm+_hB<*$sЋvG'eJGvZO}=,O]נ55/1 cXѺVKu$-U3N%i|#wċ~!"DP:3::A+LTAD Q!3ï9BoQUBߓz'A~̏LQP{]Zzb?)f-Ob t Ux|jG# Wt1@|Yᲈ)$O+!I2MMLVNNR4*3wbJ&oPxeNè sZxm-\0N кJ"UDp/@t]m>ĞC }A}c"$,yTy<߃3~<߃ ܱ\"kKn9a45 7T'm+)♚,>Gޏ#syt{ iOJP}#GZ? uPM`JPy*O"TR'H0 B0h|ߵy CAڠj+5-gl:@  +sec~BL I840[~||ܐ{l4]wx3wDcBp;#cjf?][DԤhP W\lZIı-."`IP #WRH3{ s̅Ɗǚ>2w|/fLtIKlH)1SWD!TnH䶴~*"r[Z^]? 1S97| {I^CN8Ge]?[-O ~D'|A>o$B<"k=4<9sw-O<]`j~$DMImS|{8cDF8.9~n*݋ow|杜6=> Lb.Haѐ63AŃsǖ/?vx"ڪY`F#*'g;z1c&0*amH[UAr<3!v1R\8~3nx#.t>)%iՂ45֭_==5tV'7)=ovzLf3g7s#*s1~/{\ýW`"yܿkԵ#=zu8/ETbC'!ЀnȇZWBC2Q i“=mo[i!g911n8o/~/H9 Jb21-Ǩ6vt>(kἲC<Ѱ 9),0.kfpĞ^SǢ\GM&z~"0䜋<͈3l1;1:.!:垦޺ꦎuZmډ6ַaAG,:n<`RKO)>[B6lc 1`v v݅Cl`u:|˃4 _R;&h, Q|xv/<a?no,-MU7tC&5m!Ѷt&eLʒbv9)#Er3w;@P=8Ok*<>@0U+bs$ {dAe^vY&?2 FCT(hO6Ӥ )5*nCn9*1^OŸ%h$#^K̪X0up5ׇ~ylS쀹#i/7? uM@0koa2,ZB1i>,R!.i5X1dn5%ltaJOl8s–iC3'YB%(- Y/-^4W+r,G/X%I7O*`0a%m .f;Xi[gC_3 1\h;;+)[ۦwk`%WÁ󐑄`mRDq족X-Bct|$ks #B,+$*,Wao]]ayϩ=5I)?Ew+DXx:R3i4UV5cnF氘38x3A6Y# 0GH mkc##"j@zSnObFδؔ0EBFAB4P 3ˀR lX;T2t_VX]?V05/%|]hfÔ1z=-=o% :^@3f!RaVw_pRLu 7.Bw|yř7,LqU)g ;4FhLИLp~-(D- 'dNU2ujIDȪ”PةuzR%S'VlSG2FAvd% hKhӑmH0k%(dVdGSlZ+w/5qp0N5Ěƅ.orKT'HdIf67I!]@,RfߌϿ3&a(BVH._݂uŠ<N hn rL^ 7}9t$jGjE0}¯֋~B } lӥ,Z9\*_[aIf%EVԔ;C^`w/_4H|? #1hqFC@W\ QD~%')-M52ٽ`'^5wÊg#\b)KžI*-I!y ::E2k&Nk̳r 5m)rk{CA*mtBKPefe:ŬS-̥7,N#a"-D?) :BߥY4)] Wҗ_WL+$%AHJ'끤 9Њ]ٷzbhj5 mu=VZQbOktf=!q$үO}r&UBdNtMJ?i2֛{rwpt6d5N2G$[E~96y%Ӳ;kr b]!Rg`BM3.sdFZ3 EMM=Ծۺ۸'rK R]܅mޠUycϧ$b4$8Po=|܂ g,r>,=y`r;]Yz\Ħb^MzVxt_ hߘ1{ũ`~Cx_^# @d|oU6RAٯOdd82{Ƒ.^X\$Ѽ /9D{zo23̕6ͷ'fģ-s~e.5M,΀ܿEuIiEN6wI\y=-^~qgEC4ΐV5ˋr&י'm"0 Z,iK*+~&X":b!yo"t&8ۃ+_~y ٱ03k0<ʄS.uR?骉!KʓeRKO8LP{&ϒ/z(֟KAKRtMbRe" -g ~WX'3L":I[D0+6&6X$FІcF3dɾNAl6"mHFFho63؞CS+d=TT=HA),D:KTBX8~5E2ժU M#h`ףт}v9H5ZG>RԦItf5xZU11b1P(ɨ8 \ظM[?huJ#dMQ+C@.J*RC!JILV;|$:ᔹ^IO"]MYn(cl|ko`#ׄEg%ưԔUa tM_Z556lKPFF@:/-..&BX ب(&VY~)v|mTQ8`|:1$?/ ˹>pTīa󂛹ZN!#3@|ΑO$\o:] @ꥠ|S2fAcv/Hɂ4b$~S3}?2rKͥ8_ a񾿁[2:I~cl\ ʊ7|.7a sBa-ҳWB1֡d2Q^XvhOH 1<-їss{s<ߓSxODD0J^ʛIH;K$~?sHB .\FmBDwQ 9B+˜XW!f<⁳q>:7%kqYٱ[9k$#.RE!Us`]̉Z:|"s,8FtK.hx,F8|sʨ\gf2V-W˰'͔m#USYNTOZou3۪ )5+2To(LLeSa!]bק6oψSa Nڞ >>v[;VO @fJ a! "<4:RftF-iG5eˣ"Ԩce1-n!'fd+Dndo}U5 p>/qHTHx<6 ҠDO4M/}⦕+o7viH4:g7gbIqLnQ ͥ!`sJӬ?a,2jtIrV2S7?=XQ+f֜=UrKԤSrK9$=mF$eeY@Ud61'm}g61Ϩ̬Q}g NʠFq nwb`z^JNh܆Ġ$0~8EӇV{׫ˇb: <}Y/Z{֜B/2SNSFbP1bVUu5]y9LkNDe1M ! ?zKzJz4&z( t%0[lCIoNe)%"` Gm񙌌KY4inp'NXb3d{j"T5OTTwGn@G[[Ž04>*Mwԅ =Obg6jcWmmlTsU04NkI43݈7j7n':(PΟ 6&cȮ%cGckTlӒ46]Br@-&xyߴ$o?0Gf 9{fvi0nIh<! HH3e>[͍| PpK|5VEeefp{㮶M[_u}X Ӫ}g љM86 bmQ.V4mv~ܰi0-!-Μ` ٩_}v618u^QAonK ]v}A6<e$fN,Z 'fL˷(3K}f#]qZ5{<9@s̼§r \}mWSB{z@+wOXwumV{D~#`n3t$f&0J#wlj8EIh@46xco7$Y|b<_4#Vqs~׎;>c#Ď~F¼~*C#?&,VPtRvh攓`Q/#!s`A>HӺś-' &'EEO̙67sggׇho_bu&N|ڬ!`x1,5cli~iSacUJ!{}{~L?IWNdoݹo#ݢUa?;l$xtM:5(GE=MH~ - >KRצn@bA;;è9E@rwz_FϤG4%iQڴ69?ujCLBTFdH,kJϋ9l*C+5 D?r)'dGLRPmhO0ZAhWL4ӫ'ɏ*)#IQ\`0ʆo*t RB0b̽H :}{oLf1 #aNW;j64ΎN77a񶪌kb/wzMeYeEۆy&=1ўkڷ[@߂A?7#RBv$$8љž\0;LoV2 Y:׭+R֨Dw٤ Yx 9ѻmB.O!'?u@ c Z74 YJoϣ!ѣG{ s)CK$$gN`[1wCs58b--z$ZU6Yjwr?wTeT,ș5 ׇwOJ /߰\+肨`?a:{o0 WȪS 3 KJae*%[cNͬN؄^2"::$<,!¼Uˀ*Lڣq7kzZRD`+w6f]S>i[o|l˜WY0^`Ujqf*.Ung:^4W]_γM*^.OE@y2uX-IscO)Nq׊Qk`=<+eǻK:𤭥D-CY?O'mF" v< s)١Ww>%RtNx11It>qgX҉89Ea3CCza#0[1`&;_U0ɜ8Ɲwp#ZS2{Q5FΡב>a^|Qgś_j9h 0~nAw7r*1lD i1*p ¸kʔӦ4=]]=יu:2z8uk#Yw]c;$^'D?Lt}쑗ݳ;Qk?{Oj}jh q=O y˾IpV| \spFUlDf˱4X; pHЍI~- Ձ.}/ԯC$f8JՌtSs4U5a)zhH1+=*#K=67?_+=/,>OtJW-U%\ _>7*C5n^ -̑ ;%BsOV+Ŏu`AI/岔^WU9ʥ:ւ&0,*J6a mECho*ޣH=:6بǟVgGxеm^_G;;HKlj'kfds#g\Ѕ$vۍ$5B8jWPk*"[^PV5О7* c.& lO?HKpQSGb!c~G~#UUϡ$~khN<ݙxn t#`IQy~{4@uZESoL+&mYm]h;i_vH/f&?􃄖LiP%02wrLH"4Hbm2?"L|1 h^ FT_A")]ʡs=7r:tAN4B0En&\AhnB%W|@y܇U ujgW^={:+;wfY׆ZÚYeC&g o5*xd"̉j`N%-#Ơ_C+؆8] KM1FZl 8Ed"MqTΈTFE}&f˦% , fUDLfYSwJ'S+Ni_/u}Ӑb\@-ƔWW4w 6h,Ms"G6_A TT&{h~Apˀ/ZƵ&i eP8%ϭ^2iRqx k)6k=f7ǟ빯y`A1JGȳ-|-$z/Zh I+yA4~N~7};|֥hyݎ\`^Ag "'3F#3 />m=k}#8j!TjЌsg"q{wjkCiwQb]B1PL^ `̰d¯}|RHd6h._G75W ~A2w9Vm;ju{=&.Ne!:UM8SKcUK" EUL( ԕi>Kw6dR0 ~Cl B/Mei)uH&uX1͑r]laeTh thDnT[ @@\Bp I NePFDFiYiqQ`hanh,DI߯Ui9u.s-z]ĚUuA&V0a6]`,T"=Ldz+m,G;DȁHV%ry:QBT;l Jp8ͬeS/_#:^!~/SPwrjI90LgT^h P!8U)q=։}{h+oe$/o%nEE8w(L?Dk Cܠ5lL?86Pg$WDOTAY1@4vb#yT!$k>4WD"9kDWA"b'!vD#'s "f>Hcw~1X629Bg*6p^ |</;Y3챶^xKw ߩy ^~<3147Nj?Av+?y-2B3 0Q }tX3Mc 5O+TX["l1FE&s"yHs3NGomHNn'/ {xGpL46r{*{'L?%< 0z:F~(|ܽʟ=kT:о .C :PGLcrA7?S :L?.geibcRi8)UtDm1?d 7xpO{ɿ obՈp DWkxيuRY"m=((K6\|2ǘAs1@րykM21/.^*!3vHfS9a"|4///"d?#Qݼ9 HG|~;|λ!y٣̯y7_%<L GfIw" S 0mJy*Gy? };o$ܙ{{Wu6ϽD|ke{Mߒݘ߾<]ʤT6UW|O\sZT th)U'Cޣ')_PYɝ񏓵q[v'w'r#$P ៧2<@dZ(P Pa_N8|K鳚jCMwrb2Y?amѵ)Èv"` &k,KdIP9h!>kbYDC=l<`@rm+ PbcV/#Vĩq̻Љ[LhӘ@9#z{̧ 8Q7QDV1, .m.`4&`f gagZ|ƽKw/D9D{{NbSp̨6k2,s5-]J|;? IR8fWVZG~NMH?9qW@+*jv2>w,c|l-Z}H3yxp"-l;p D1J89<{{_1RQɰleu⾄ƿNNù'.ޓ/i_!޳7~$BoC|j/7o2y ^dǧ\3wLEHrU}RR DL!|U:+'B"C!UCw+ q_7NH )"kn5?I.!f>[TՅ75}*cDƲ #,SYGgRR߹tiJ{6+vtGtBVaϦ"ړL;Abqfw٦t g IhN*|k! Y؆F]Ivyyv-;v>? V(]/8s]H: 1D(rr $oJ,,M-*Vch Aoդ*Iz}^SJoХ'ǩTJH{m#4tP4s̶ ̴ȶ'h 0f1 \X&I };Cd͖-͹&0]{h]J}e|Z_Yh9LKz:#Zwtc8:QyIPl"99 srVBde9=՛11Dg-9hL4ƄkT61'Eip#^8AHgjmA1b@bK|omQ;tddA׹t~nX_ۋtBG2#c'#Z ,# Rn](w/Ezj4]/ErVhQXMhwr NDne ۆܭux hm\;,&&s/ WQ}l5ME4Z͆"4nPI0m:z7v>X~7ʧgv?#)Xz7H$@|#D!d/ʳO_&fUd ? CUg8ў a'hf#{ְX*kNF?>i|Y8_9fг :WmQ{0*^q8`˚[x}zV>; "_;n-*v9K qEm/lv!5,7tun;E6 ~ |&꽷/{Q1 @P8_css=l}ڍ'xJF깍}~r pW.g<w܈oGN_MGĶ,sɧf9I% _gMyM,Ez8BH.éh{x՛m{ѷj:-1ȗd1ټyYY[tv< 3LzV691q.%>W\>,{lXI9W-<#פgτ2^8@]޼y6@·OAf)ܻL p).sEޛ.A4!,E`_a~>W N#ݫvmz6s61"{d}ɹQFop299 8}|_xg &EI;"KnEnG,ͷS +rR1erNMNgya~9Y֧YMGns;oYԟoa;pii5"vN"{|ݭǝ}<h i/}cjw)mZG8jE] djYYm*{C0REUwbd]$- ]W BmYq/w qhsx=S, >}?R`3e:u|$ѷO$}{.MǓrZơI*@TWJ޽e`qw"2iTw"C+ű  X܆-O% ٻsns7x5D?{Nb֞+]:͇6K <T /mq@χ* ð^-/h9 x.{X]zĈcKCoIܭ A|uܵΚ swZ((9tˡv%HWīiy(ZGLjי@2?1ք\ojίӁ~ffEqSce :l ;;l4&6r:r}JӬt_c-2t,14ha;jaUjn]Um/W7qʴ(c7.`FKn.^ WVM lLeɻS/Kk SnNt0ʒ]TYQ/?yЎf%ѱbI4GXȳhP:Qe"157 L2d&DWq"-ֶE!* 1= ]QƚiM~2_i1,]bz=PPMDfJkdGP\>ME{ [E bܳ;{Ҫ*{o)KIhzVc.#ޠwkwG.1bUUp¬؉,}rY;o^1| *,yKÇ7xg5<ÚaYbYS`Aj2nastmv运6Rk/q ]ǵ˿ VX@a5~;q4R@%!&MU+w6WkXg=슥Dneohlt ak-q 4ׁi%[Wv箮Z^n˞8ߕoX^{rk({<^?= VzVO9!|STkއ΁ cO(sЁtDPKm7ʅ!LBuL'xn- B FGvoY]CµI4}^Tmq/'/){2!3.!̀ՠ$/Þ3>Lr0>s08QgwcI6qKÜh`>Rۡ88 _BH8t[OܥMOY/rYOl ^}iA9nwn>%8 hHA ܖ!Aרڨh IKqT?h3'ʺ1?2r]~mw$9փ(=[yLg^_zTm/Ì4 Wۄ;ĸAfzX/c/wx Ba^!<Б'Hu̓8O"I"x;5K a`pP+m}ߖ^aΪHx!_tl^5k!n}V_ ^cO?S-%w14ց)H .ԫAEl#pfŬsu r+A`K7ȑ?pz]P >zvSlz؀ G> `Uuj38]:s/wr/'K ;LK` q;0Crn ?'ʶNo_6knV[+z][|p|_k^>z!//IQ_@c64`F3lW0*y9&q|}`[հ}֖%[{Y[ְr3 ' N0kh--ZFeClǓ~o޹玳='O^.?Ͼ@%g!>Z|i馘?, MGZ' 43v&_U>y[ԏ}b^ċ*1TDmt#%b^'(L}GPF3cM37u=o[A?a">͌n\60i"Pf]zbJ ˸ab2,qsԯG>삿G'."i~xƓ֩) =x{R{'Çڌ!RB"p%7e*EH Y)sM6}a~1$xKD4m\2uҥNàp$sHN=7yo9 /4CjwE |%RwƏ&ul3&`d!'M"9I[qs=y.FZ z[P Ԑ%ɃϹNg%w?T BojC+y4}7}~3[5 MZoZ ZJ1)nuـohzŶ'}2N2f,WuR y,c/y&b:xN9u7T7.O\$ fo;Lm} !jSINDzJ6x*Yľs'[}h㶼PĈԛ4.\ʉKr)) N03oSބa9]%RG?Ht <Ɨ{.:\ũҨ',vzғKB(WG4FBsf"𮘚Zݞv4ZVBGo;u10pۼdI(&Y"39 X4؃הՂ;DH K$kVw-os?qѺ)}lڝB!8:AO;P2U_?u CaPP KS0xզ^-m>P .|(ҿ"p8p| fAbvB,iߟέa8;OtoO7^5ܡsmdЮ3p0hI.Œ&2T2+<2u"sbdժj6*ѭC`ޫaLKrYƒKb0wƐq0F! pY{z&O{>.٢B7y.Q,%dZûyoVv~E fghܧ;xI & XѩLSn66~_y#D 2i8(I%A6 m]yN8mG{k;@OPm/ړԎB-`"@rȕ*ӈ`LQpL]9f5M9-SM5S\9Lgi'5bCC|p m#͐+Uyǿ7B&\O'!Y#dK#6+C[ؘs=-ן+WZkoY8|{nu٦K;m,&=gĤ2[O U^tD*Jdr5)ߠoZh2Ʋ&q#H'32bFy9*C?Oo/xw$CFßד,5eߓc ;f&"p衫5}WD^_VS RjO+jrL^zZUbwe/\y/;ǦƦkEDyI@;o—ŇC}Xq#_RFsa6LLHfYȰO| n9T_8#}ތӃAd~&I!3gd>qc'(z&1Kx&p%;'b|O٧A80Ep7W8śWM]: ҿYJMN]n`U{++k#{xx?uPje qWIѠ,(.B==PW˭"Cv#X=cPg[;vro5_soڬ0O8f?f?yp|/7=GBxx#>ѴYGqƄ'{)~DJ\"tOsuFϦ}!rwL ƀ.}yl(_F.$a͐.\[s\&0.H;(~+CM66B]cQ/_}$dzU~YϚ82:QϾE$t>+GK^Bφ[n<**w)Ac<+!pI1Pm7 6_.:늺s!f@Vꗉpҳ -SS_}P5.s)gt2s|]w|(|>N>>=8 t\6-  RI_La!Q % W %0wPP x'Yo2ڝ}fTD3ύ:ą56HP{ %InqAM&ZT4uK$|Pt_cr۸o>ObpֈL :m1!Z&3n=k@u9H (/vpw/Hv7f?rJ4c$UQNoٍ/ߺ}m>:R̺ X?-6Xuҡ@eVo`dgΫneUU<R.ɏ](#ՄO??{Wkflk>{4.xfCﶾCwm@ 2n sWF0Ì# a\@c>GK7MZuBz`­ޫE3w]aE&+'Nm@, h؏?~4n's}HG-KM9-#S=n/fBƳ]g3K@B8pwXux:ߺ c4 Yj\5N;SSe+A7'sl.RJJ!fbڳ}r'm4 |lٯa8/d~? y~)@.\2QN ձ\r$ h-Ϥݶ\`Be5knsvVlF^_ome_1C UV/쾔FaiHױRe]xUtt.'3vE&a>s{ 08l*p/5KM[[-k׏}W]0XX)&\IߗrimHgpp(O YI߬ <Kg~,):Yܟy:mtނsHEC3%9fރb!3N>ߓ|ϯKs?&n߹jӱYd*os5D3Gf.ԷkKgabe$wIpW(d`#fup I_p|j$wBVabb6]@C"~.Ȍ'dNlt Qa|9UI%"y>X18ӏ(izJaDEŋbD[stߓl4h6pP!?;%/$qL|>MǶ<&]lⓝsaLvmU[OhҀ2ia@ bWwFF-S(J/כn5o|xy4f'83$Dž$bGxhH/`alH:z;h0o>#;sו"fe0ckx^C}γq oЧ\ K`+,~.=OGo`?n!I~Noi{q~'=! ə@Fy'li|:D|>O?ya/}>[Nioĉ\H!B7od=#sǓ^Vq 6ߣIc>8uMxw|0?/rv; ,:gy' 7tf|\U{ t$߅ÛouPbNCqTKi/5Np籐EQ\>0JlϹe8 $.uS)'k'[W4TwԶ._!f'w +* 򒭻7n. ݚ/L'\6CCUϩWC,X YZ,q,YHA뺇%f+띙TlTI2uE$8bL EyZi.6hٵDTPXw\UQH@{? ?4Z|LS)L? Ѝ.a =3r"8z M߱t+7s sv.S |QB6O5nUUڕNuFT-? hkpuk*qTݢbsΎy)b5w̒e_'D 0 wŠłTDn4!]t?>)Z7An`2Pޏ|3HA[m nK#6 zg?o 'N[g-nH۷. s{}źcTJ6p ֯GěoU67WaeA"7+ tdi4]n63dxO_.~gh&W†h|z) ;XDфѫ tY6ijj7'@̯,4s?f}5ޗeee SӅ޷#g#aCfrɜwCӬ Wb~{~{g.b^+0xg~>o91wFO$4b.-JULw3c%&{[}6m` OkM昝7,,<z[ŅQ!j=)B`j"r#Sƃt3=O/ r ͸E#`jQac۷]r_+[^y8|7W#k e0l6_e2OoPfmL%/8DH6pfLןx¿}LT؈ w>t"kXk*:q⹲aݔ *\. rΧ>3N4CnX` p:/p/UDpCzawsX*)7Ui)몞`@ʥ)uhǟzt*GN55#Z\ i2(Dck)cONL;Aux?8^f[q^-c*\ʮ0õV8S~ ^ѻEOMzyQZќHKl_t@%م"CtU;\)Ip][ՍMIϧ)XfVk,Ԣ6(C!S(K>5\z_,tLǣT8jFvUzjFv1hF?%p'^ bsļ#QWUE~)]LU՟WS۱eQA`1 řXbdeυ8.!!k)<.M ǪӛOh{KlE]Rsqal91X km=UlG$-I=D]$XR=P6R[0eҤŰsM^m v)NVoZWOUՁ p ߲yIPԻ+t>F{sX֗\܃D_Ve/6ڼ&Lh[ x( O Z9F]Vni\bN9SX#pΡ [y*PZ2*jJժ@Ĕ_OɪCZrm\.6z:/Ёd@t*(`X~H>4/<@@ߌ}EY@d.F@aAyقvxsɽ̼Z&ʔ2exmtk?5U~_ؚ{F3UieY~GCj TI;[5Pc>yLuUSX=Feg\X4l-PK@ݖƆ!0)u[,ֹ`Bi ,|zzIg:ZH:v1K5-Z`8{Ňtm@=/ڷh>Zw$GKBT@t]"0%;1LrӼ r~hių nޥ殸{O4stEK^-Z2u/ul$8* V k $\бNplޖR1ΜjvdM† 6hzj_= %$'-% "r8Ea! nMqg{^>0mvhȐphN/?  Er._k4Tɤ%jIJjuD_\HA0Lz+(*zkVy=jq'p}}MW{+OWLMh?0[nR%*kz¿mBc:0WdSrε_ѴT9?Ixw쾠 T{ 0;٪/#MAQ׌kLg:׭3VN-agC,Qh~[.OnfPbnCE(S?*_;?>gds!h&쐖[iІb$Qo.@IiH 椧0 )5;o\U\1M*9ޠQA-U÷DJÝ2­6_ -HAn>ּhDjI`lVaMӶ'vZa/I-tմԚvjSOipCksfBqD_à$q;MM")xQk碛 ʺ&N_}rKVJ4t-GKQ\id\AKM)fOzx2.Cj89YT2%tb }V-4E=ܜusfp- =iɚJ=Y+ yyZNJMkǏX+,Η'j(I쌔v3/ qAr-6]DOp0T$x T [-oGEVb띰k?F1?\zQ׼3t~x.vhTУ? c˧Ar,MZH1gs^xVVS7F\(M.z:eP,3GjAT$ETxWvLz\uN$]kg_&MK$Q=DPEgv M=1(+y4(`"D+(D$,`?EkD '5Wj;9}(K2uEZr*T֔N,t՘Z>Uf)u9aʁ~r7q'[]NjÑb˾V#VUK}BQozr:MʜUFҽ_bVYyBIg  k4{I="$SvFg*c_ƞfv(!Rʒ)"H A){OGZXhmY_=z>BaxMVrDW8/[1^^KcZ~̧CG{@˙GM%Q)Q6{2K2%H #OO.|r_<_374 yq`yWe65Ǿ\[DkdkHfsx0Hi"9>'~K]s~n_٦.Pf>'+kFgLP/">~Xx@ ;k<&i_f[PuhdK~W7eifYtl?سu涡N^'s} A|kNV_ w KEu?[\j@cTE"< pS˸PĐz@OJpYXs}pcCkCS2Tvgڑ Q=~}K,qU,6:2s΋?ņNB.\ Qq(5DrK畻>mjإHkLѤLSAOx?]Tg zvvN="KG'VKP }4{]Ɓ˧H GtwͥQӖb~!K$UJ&. 0RlʌB}|'|=~H~XĿ;>,GϾLq{/|=N>z?\Mx\lb>\]]]?}= YlL x\Ec18kyȜб82n1$ ߄/%Ƈ󗺸{y?/!XϼwV䬠=>/jL"ċ#Rj"!#6雞)>RWx犎/Ӽ 'zZ Z`a?N¶cz0m'dJY8S3Sd)T:_k;yR*;S(BWԽ0:|,{[eR[{S _![,ٛ -/R^~OFr͠}|5 6zFEygNQYD*:v~ҐɒuNv 7D+: O7s =NpWP#]'#]-P}%$Պ`-AĪP0V4%!]7 C%de-HeEee#dښ5kC{F6Jswi"ѡ12wEG"PKRxo [&aI8yq}D6o.hi'3C3VGytQԚY#Nپ +OZ۝2| a#2`$ y99svN/_i1r  uvV cJBH(x;F0P N${Y{yqg1)LQO G18N5AICqq!pΰ:F j\t26s|"8WOO ^ zB }/k}>֕`\n԰OlIDH!-RV wf}~_OLLUE:-M\X|r֜ݭf]:lczf1Gd"WG.G9eYcowL$2CYsn[]<\s\"r 4d/9ӑLW]Poky3o$5u| Ϟ[J ]Kۋ"|\Wslal I-G~<}쒂9S'?N,bm Cpu FCikI 2?TOpvUvXg:R)*]#ް tn5g;}#Awsr<9*V8"2CS{m,Uju!X47XNR $DqdՄ_CBSH<N8q9xusㄐ%+xGS sFkOC'0&ے |"2 .=^P?,RϹÙjmWhA:=S *zVar=v[Q.W:ݥYb_kي? %s qd" Ut-7Yb<ӂHqWF+ W>[%p.c猫Lߨ4ңm=Kf47L5B&3ؖ<-jjJf!o M AiK6WH+zWCkf R-)rAaJ&UHC Z]V433Y_*-U tnU=Y|_NmXPS*kQI]jV\Rdu~0+4 gc3&o(Tp@8Vq,Ic)#o|Ř98oy% Wv4vb!D8K*(S"R#a_h)3Axld \d*22{O[lyǚ6ظ};'ڽcѝ3\/竸2WM(fhدث/\ h~ |>iyZl|.eſ17y,rgˍJ+K4->NPȹbFK.6-sS 2!>We1Tg.4ޙSOI`H:.S9ʲ2s0 tCsͱBNw^A09s3Ȟ~hGC H RUa*3M΍В'a%UUnG5ZזCڴ ҂*CEU޶I|%æb(kp0W䛩6Ł~\.X>ߞyQ;5ֻs"|p=9Z- ^_RjT&}dy]r.㸝+=Feb3r)&}?t[{U@n=GƾDM<;a p 7hR&.c7)*^b0 )|~N.whXb_>xpce);c :bMZ&8^dHu?Gsx$gL*rM*i{Iw']L1ª|k;^D2OBqR/ VT9NxDZYc+?{t<,MvB' ;Wtus6AiRcHw:>KEvl) jGg+zZC7 êiX ]и"IE/|K\etˬN #Vch5ohxf𹝞F- Q;DE_GӱoG HPJ@2^dw߸eUi Uه+t ,i-ҩ2\QeUڷй}œ"BSOOE+7l$Ӽ򵒥ٛ rkX 2d Ko3+K,_lJj Nyo,ZlٽQI^q*Ȕ-L4e*fAx8Q+أ2i[ؗil^ %7 t.6n2F\/tzs`DWCyΗMuvT*ͮ0suʼnO,󷎨L d7XY2塜ŧ冡LswY^cq4bfH~[Q­zz澎 'pK͒!1F%:୻^3)̲ 6 >\ӾjTKΓeKi!W\QFG֖=jSRe6T#5'ȞU3O< ,#ip6zƷESFovD;3fuߔ-\njRDhno&}CQ];wfJ [i[YlɄڪ3߸h Qj*tChӫ=xy>z܉cKZ]4< Ǻzk|wmeA{GX`, DŽW(O)mjYs c9|]j]EèqdK:Xkxr0TjwT;5blfv^xMv^p6\r60s=KĮ(ni|,v6K"`b8 TTĨ9!:+I$)˔"DwxH(6sg^o4}HXhŞ(V;ϔO3{&"]-\7AGh$ ޱkCCp%ݻIf$"UVpeҺ X/2m^د6U%#x; ,W~ ;ħkk.l+޶<2֏Ȅ:ͭ_X] Ո#30Oس'ܷ؊DTh.'MzE]b_L"7cUNMŊͱ1A!pH=*'&7&&Ƞ QJqL_y(`z㥻txegj/Yj+c>?JW?y'˶"}=۝ZrҒUKo0C@l€5bVu=cfӐ9;so{Z쟛v)aPn\_cvR4pzkBm)1сo"y1%;: ;YVvSkBd-tx7[,k[y'EkWUi c5M3nwȪ7rz/ S},1bWEP:ÖvWB¯[t)L( :F3 kd8Cg›i|'h'*Sx| [RK(Ud ]E>qT$?j96 ͒Z]rF!yHKïs v2r?1\ː#3oq6(C $ =[JYt4iZ65 KsEYIR^*Yӳ A?l3X3n Q!pFȸ#`@y0ɐHD>i>#yra_-Kͫ+[toԖRRS2TAs /t|!s&ri^%'O3K&.|F(L6}>xH1[S_$u9ء&#J>OG[Zn]hY'&Ye$6fӷ /]uz̯lEPILORbkޡJC e7>m`i[riKtRUY ) @JfƐggLC_Bt| P:=l |wOZ jʴ|[r*LMԎڥq#gϦ-lJ|+߭tbʕ+W؊,Yjayip*]Ū=*ZԈ'LQJrun^Siў9| -*Ar[D'˩ة XFxCўw!{P_:ߠvN5aADiTqctVl츼&+tGJ|Zx`8GifW82Ʌ섗x߾=? ި3{ƍr}}?G;=]3p/g8$nB`9%Ɛ5w"FOgW֪ { ҒhH^ >(U^R[CMnȕb ܆4/e)yn7Qޤ"0A|*|iƁ_W4P/V(pq7Wl#غ"Wùv1ӴLAŭ: L:'NkI7_9Xۓ'S%A&T)]3,=r[[NuT(.9\kCZq qiG7`cW6V!jS!?K08s 0}Sƿ||BDFq":gD4k:fdn՟a*wU vdid )z2˭|1Cʕ5\3;|FD 7"Mu7u΃%YpfwWSb52ռEDRNX%KqYȯ.p-TJyPU$,v83 7t]!PFIQvhS3Ȕ2Μ͸b-ŪiҠ¢tTȦ2ʌb}A]+sHno$[(sd_|Zɾs.gF\)R,%uBmGeo<:'XߘW_kVHl>7X h nzF$vBd F#Id9j)Zdcwa-&Ow;U\wZ '.8wqF )g?G\3;ƄۍҐE %Y(ojl-^jYzf\,aKН}6A0+U%Oiebo8M A^}^-ǔ)޴(+M/f=K;+<–A0JV% |"iZj)HZ8" QwmjZHht!aj Jx#]PCb3s:-㸶, Ӥ9f<=My_gk2qͳ墛cwDOVX/  p\(hqAvS5 c#YHK\At1ᄶv\eFH.*l%u,ں`_Қv#7%-'=[Xr3qxeǏXCuTROkaAb  B9;^og L$~hl T[D_*yp8$hV exnL}jbβNDUN_\/[SRe:ə )4 M#v-{ K(e鷵”:n>[(5m}tF}@-Z [FJk%0E-]XX8ؽ̝(_SUTdY=kkF 2'nze-i{.S_?x^)L G\k>[ы?IITRĄK]I].N?l!M'9;VOH|:8|ufjbλ!U|yZ8)ZH }W dDg_4[6X8=rC3u`)V;jwUFA^%e9ް[iь7oV$.FJg{˻75jS*WvLJejQc)q40~HV-+k6Rj َFiRoNlRBV_aCۅBlS{׎]pptڿ2.h$z}{zti'w«\..erX" +e/1eN3TvYj4]=xȒy87dl4ҜqWn*\ ܁"=7'k]]sZS]F/>W .;DP? 9'8&^^U̖2jNsik6utE˽]kzvU6mkߓUj*NU{ʴ q =|cbg$dwœ;X1ݣC'ۻQ8ޮ|]~5}38;|`f0U\Ṷ?A{D߫#u u|P ޾ښUU^ޥ(T ۧvZmy6+&AORtNԫoo]j-))*rh=죁CJx+?r{Vq1{΢nFm[㫁uiGg ?3&Zݷcj@Iw֚~xtVKNQh\@[.ܴqfQKJ]Lm%,GLj4Ҵ4Mz ]yW\nT;ue悒o.n۽9jH}+*@p/t^~'ڐJ=$6 k<s(eYiYm<}NHwk}IMrUb]hH~Eyjcy9Ws[Fum.5NbΒ YH` .#2(`aS͓S$iN,#Qg貲tz@sdVl>X]~:Nٕ2XꜮ!ݚf͟묦⊊:wXT6h?fR+3 \왋Y?fh~rRSܒ$(\"IE<5*EN*HZ5sL۪sř1 ig5u}[JJV/uᘬTr/1FnStԷd涡2Q7ݺvI>մtPWgȝ{1}&{m恥e2o݄֕c_LZxF%u>lѹQU{lt+ÿt՚\vOC6p_]ze̥*T$&N^xro;Kd( gnXQ@[FJs{~"Q6XewJ EiUɓTb'Z|zhsM :87X"-\/R\tW쿰훛+ڐ9=XvՎ<a5l$!j2rV!.|գW]32zvGVM2,u:9V]flxpt0n1e싞WKb;p]u!vCU_Rؾ`n%3-T{_[tT/sܳaELWȩH*)|`Fs&L޺II6γ.ԟhhk;(t(H2s|8ƌvCC߱tP!MZKrzfhe֥K i:͸&o0VO [Se&5JXgЗ; &]dĦtLHeJCIVђ9go#bQCVIM~gr\N;l# :hkZo,ө|eb^C^ƏʈˌU;d9ViqLgTIX) =*! 4l+LeRF(ɰ R ɉI|ft.Ľfs72E*wCGtxSo(]"%볳MZG#P;a XDȗ4Y W.݁vA'>OvoZSK3. r=%/ȻIQIg -s %f [+2~B/#_zXa6). M8jSy_i|_bR[lY95:SkS2 YJMu_-o-t3lSBf91(CU~.YD<ӱ!*1fj<96%vPkk|˧F:yKƻۻ1nmrTlR¦|:n[ N`ܣ́,b51+X:Z̦Yɵg9V`E"T|1XʼnpJ;qUȀFaVdmmiؘ_gd\PqtTMW6dBՒ卵թ5[VwtY"£3E[}Oia#!8 02ֲT r|Yx$3#SQegd۳>>ㄦsIieU[U N{y%w ȓ4ű{ħ`,ܐu?V L.+q7vvdg[˿XfhɞMf+srX;DabK99ac1;Ի啡}C>ZNvfVvW7>a6$fd 雅Z %g$0]|aW?]i $IŜAqd;љ0՟!;??{YX&Xbb)LpixBMoC`(i^߹㍯_ݽnܓ.,p8޼{&u0ydʮ:8dOC溤gg9X EEOuMY^<%6J7un(&%'efܔ9=~˰SW/:EecJBGow9 f^5%+瘫wYGAADzwvom$7Eڧ عsh8}첲q`+-ߣ=+W,irg54ϴnF43 ΊؔzW D2@ ֍>Zݦ|ֶdR36\ԙ>OiBR2{|CaϬM ͈r\F23,WF'=ĥk{guNsgW[{Z{h@ƔX*$mWߨ)2rrYB|_J&o^8fdh EPono]?;e˗eʒƓi] 4$]VUn*dBag87FwFsvQ~`iASthoudx9\l5W8Re1jKVEV{|# .[eݞΣ%RS^7/jU]gl`w<)8z8'A>hr)Ύ\#˚!yPi5Ȭr(-j ,[X%SxuV]FjƬѤ4}vyP(jQꂈ Ij>~Gh7GZqWT*j0=.ik:ln[Zj_2p4G\Cf].5iS42q9cֵUU_+:'YIqҺ/Wv_aNOX^S[{Xv*5E yO_yq"+,pJ\ߋBN+tA-WiY%~W몵i OֻKV|Y\S1z,V;R$'%*,%:]K .[M:gb8AZ6s˛:m6-1^TU\TLWZ[)e/j D$dϟX4A0;rX .[WjV{]Ehz}llR/ZY+( \g%OIgqn^TdVΏa]5yVr]nJgi:eV2ay=lTExwzh|@G3o,[_k2nl2mui5ŨU4h#4Ok[dy&erT(]sKT1'Q7 p@ά(gy*9_IX,zӗ6= r3RclaUP yK=Mqh,˪]lwJ0T_P s5 8wJv =lwSbXjdصN[߆b\[\_3L%K^\ty&ܹL.޹%q`"Mo(2|NB_,,_ٿrqBൾ ρʊxEvnp#ZS6mU+7 p=x# )wh"n2wMXrV((3%"I4Fm#bcނℒTITFjq.ƁwdjԥISRKX[qȾlW?tF_t]Y?s+oAw^vñ"A;}$ ewBȶlWnqmGss`E1dWЧ $뉈,*tA$wq"VT+bҔzzZ^X'1 k\k$`tKsY 9%&f隿7r}.ik0)MNNGbτAm@xg*gѵ뜼Zfn5z)-Ehhҵp,zdPøX=dw+ {_·sd|Pcb^Y+LyMMFѱt`IWYmKrۭw%Ϥ^1Pv\};dx\Wo޸맦.0v=w/Pߥ5gޡ)[.ers6]8_/S= r"wKٲ^`I~RR%%' &Z+q8#2[]+-Gܵn ?y>|\H4I wË W[\;"Z5,3+Xn>>[]b7>ʜ]Emkdʝ sN}oQX>+˪7N4ʣGl&sႺÓ6y*w; C:Є=/{rnW8nd:F#Z" erBM^u(U/קg-zZ3ҁl9j"$887Ɏ3HGE:Z6e\ 'oA GA7lIq*Z'LJզde*l5įJpge:.L[*iRӖ5skVէT. F4-n#Sf'A:^D ڙ-"!: `dmU2V,,dD*6^cGVO鋪e M^Q[z:g.;[6t@ڃo@#S U\TJHs{¾ eb*ʴϝ|TOfβnOi ;Eq{huUsnxN Ms65'3D!kC}TG&[*t'?~=_ֺ6 LŮeпyNhۨnz:p՝ Љ{L%.c,]ez;7_OC;IܧBҤh4DJ{MfV JOOs{nv߆ɋbMq>?)gt&/L4^)%$׾IZƀpB܈s1KI'XSS$[j1'_7 2cĩ@qΥe`)YVm/`M@鈆ӭȫd4ϓD晝ûJ+&=poƆqIG@[̙l t yCt``ݩCCg޸NKoDHS/2t{"#媝p|k5Ϭbcz5w<\> uTw4VFZ>ߕ|CG涻nsUvl2wn!=>!>.*j]&M߂c'i[<< j( vqwܢ" wcR]w"~+ P q"gafCݠJdnx3ֽzuw gZڽo~xNq4_6{sMj |2Pv-hO0|ORKؕ:+t-`uyp95ިT@5:U#Cs-͂L{?=1o0^GayˑPE)ibς)xCV%%kK?:rUܧN%: ]Fv <5g.kZ G7usۊI3ӭ"qW$M;3K%Z(^MI&+u>rzD0tc2Iڼ;'DrBN4B/L`tKE2I pb>9+*(89s3J5͠nư,:oW J'Q@韂`2Mr KuIh`ѽxt?oχ?c{z֟1`eq^GR*xΓUeU|2\%ެ9)kj/PJGv5>>2nv `rd\=u,=0_gTa]p 8,ނ'$jԡB^ȅb or%zEY~cL4721?8KYsJQ\n z“Ie ѹL,Q8D ^~z{L[Qʋ/ʫ2߽e`[؟WXg6~ޞKñCVmY07rF_f^ѷ˖{t7?reٞͽy}}ynԧt'Js:ka"ҏlyokú62hAK_ U эhhZMY4BAv΃o!HaHǭ',d BrPCJbZoL ߊW?Gʻca# aSݗ43}`WT=MM]|wQOҲEY#Z ~0_'#LL[(N|[d F浆$O-%dL=8!+HK*CIsIgS`M7?1񲮢Di*+jֶ5i#zg4O-/xeW3@|"/v>XW֏O9 ;sHMQO~35b~ޥ@< {uѽ|'oĸ_MS7-Hp;9z'x'ƫYDзcz jl|y4=dMeLVyX9@Gh;WI2Xk./RJ]Z!MKws EKu2ߠ$rUi)a z2(Bm7M9cVcy00u7"x!!^&y4^|z$(Dfy9u5u ,ZD9[P 9TBXnK].1}&K  »0^ҷ[OAobГ1QS#^ۣ 7D& :Voºlxfsm.gL~@,vh%}ј8%ƺ>%l!^Oᘸ1C\1^Q^Q)꺳'gsPsK$pdg9D4"MnYbgY/x^nymg 'çg G^~ ?уGX_0쟎1꧕g-P=Gz| "lb;wf;S C<,mֱfsÄ?NAO!!fXO9[ϭ;ԋ0}~F̏.A0N~H鏸?9UDLӠ |ㄾ N1̃oXGp)x?>jG!J}B-@vv; kʕS*wQWC˚Qǖ0;۹"Tksa<"h/Io'3 u'Bfݜ4]<])4~I,g7'HƟ>qȇ))B^χoK'3!߸ކ ^1wDc;[&l&cL%n'GDWc=\?ψEم*+#31~#ȃ&~g mݨѶ|}@t67,u^O/gq0G6FaFlw=7B|h*=A؞}c _Ӈ#|'9zKS0џ/2 :<ku; (7Kge ,5!c5 o?.T0YBl$A_4䚆N'yf<ۃ,uy=ui؏;=n.zvug`=us7C>_8B'z{~Am%毕/שO߳(Hya9Y1.{Nk!{?[~:T#~ Rox%$ ),Nπx?x0}}\?ߋB",?'+{V2Ѱ]7XS7r 72߃a~'e P3r}yۏ#0쿆@SPN/)pVc >*9D#oS;=?B"w1R~]=a`C+|>5߈/||l;8>& q䏁?y1#^ ,? a̷ϢB- m}oP>is>Gwg9g[,j 'DOa|Ƨ#S.P~*n7䰞,|0=I= =}.=qY?N1L@ßږ-p-'!<o^?.Os߱,x\? uT=( c]խI~0 B?SOkOzF}#lGs!c ~\ _PF??s~9?O< j?5?@>h7(,~?|g`g`%Ls{9ه]KvhAOl?qfcŕ=n9'Eɷ:j*Mx>KO3C_%e+kO.@ֿvQC+}dOVxzAWJq14%$%bNؽͨ%EŋU¸( -/p=lh_Ѕz=nm.gkC_kODhQ_{#Hb`9~;Կ!ޙ#ms*1lMp_gY*;׻NXF ~-?xliqh [fSFȨQ#xϹǩXز~ġ)b\yM\ѻ }- P%|oX2r&' sP$B/qL&/ :O:_e@K/þ"Spy. 4|bLH, 2ٵRc7Z)c;v{sbOqO0/Z /xwyq"wާs`[>\B]!»~]Ow+.AMK=, Lgx// ukD+ k_>浓mfΗOp^ɀ~z4~r˻/O?ةk)tzL>' jdOuZR LD3blKZr Ol붺*-᱌м:Qw 1?wPg7p_?m)gn'gc(6{!I( 14k&b{l#1mWFm@>C3߽>.;דbЅ+I@ ' >V v.j,n)ED:l*U L h*jwxO/HOZ.[;g4>;VFg^cTd^4A==*-[7/U>%24b7fPNzIAeђ Ƨx5..J/n棲Z?,wP6|/D*eɰO|8 3UkMiIjH,In'o}p#1ڶ[|/*a W{pLЍYs% MrBOd":+]ϾYX!Z| yY^cc-";'\ ? 7W1k0[C}e6}2KsșgIЍxx*p=3~ky % )\5ԍ-[)3=` x05SZH ?2z _Ũ$t=kInc).` tuk]u~4MTV4` (4Zs@8B#oow+cT u>B ڷ#=Eۡ D5? {){H%@b}oۃ]_ò_S_S$f@u~Pѐ3:!zdKsj!ߛ *-,4M[NT X` {).l|M&~p! I +}?r1z t=w 1&'giUD˥IlQFa#"i#t:M/{ERm]kӦDl1FCѐDiΪZgM]?Om8K.$B  | )<ҫ| bݿGz/cȿ\6} }F/ЏQ3[jocp,F-1X1[I&}V>ї1J=~?ۊ"JZG : R"w"8ԇl_P7]eNM]|i%ϨYRyTt avH+;%cŚmfV^3-kp)ipVtt~ jb||OP%0f癱Y>XwoF+V:fI 2r\"rۣ+ƳGڲ6kLF%L?S)k-lz5+ r|.<>&BE<"{gnwFƮjK1fjbhvYy{FCʤT d v`3 +OXM~uXEun5TLYϭC[*zE?IlX֌xdFȏK 꺪k Jf#O*32e  |gY~34,?!@!>',Dz\bP?8;HWH'/Ctchu7y$M/Z=c[߆m1SAmYNXe#YZ *Gz"WVjGhɘ&l蟘+ǞI chF6eRiR.6ji۪Ƿ֥ʎ̪r-pߎ+,VЈǮn5qJ8KUMo֮IL8uݺS:jhnIT545>8m%wWsyuZ8Kg4]{)KcD/&t"L3WI؃]zrSɣӖ1U-$7b兣g;)@_+m*՗u{r G[vRj+[tjgvr;tEE}(['ϙY16r#FӬ5sL7Z T/g=n/+Z;vQkג?' Zh_i5d˺JOkCwƲ1KqV鈍l|2zR~PE˷3^:W Rgͬ~i8mug^tVlCJjwJ.}}w'ZO]g71:mO\|v>e[hq|e2Ncdm dmnzrǨY]Y/vmx'ݱQ}_';ǻfcY9If-/X+?<$|YDC~3̆{줹bHQM^7U[ZW~ѡH ^vEt{U_sݮ#M}2pd>fH s:(g)g 5>ޫ!#l?LrGkC|塃_ %_~m{(/+Գx}0:+ؽv#|gO(ù+>@a &- e&Y1g8Sx L]Ԕp+́)'柾8 ݰXi>U^d-)6o}e}tw< p>uk<G6Εr26qt,Vou1LMMmL$Z.VbocUM˔PgF221γc"~2x)]6mr/ \ (535]Q ߄(QFwc';MV0?Ա5*sV@[ LI?v++kIKGݖݻEAG \Bfa9Swt`'}}~SSyO׼]~|)5 ~D5mM78DBy[WsiǗhMK5!aӑGBulTCAy~Y ;r4p!ѷ@)7#ԴF-ēfFz~-Bˠn {T 6 mmn;*#0ʠiazSQuXL?","@cY貐}gigt7O65:h/-ɳ:1lvd2F̥!_ 7,²_uF(P]5.e,TֶMzJbE%+bG7ájGf;8 wyl_LiS'S_yidܜUb>NE\5mӕo]ţMwW y5>i5AR]S+ÇGKEJjỻg7shC^"o5'O{yOs#ɲ?..rމu sF+'Ej0] Kʆi#tv)Hd}'ʟnO1u$tu95~"y5T"ө\ui}~)/QٓJ ɷP# 4L_,H>kVqDN,_2V<+rڌqRCx.2]=EEKJ&dkaт-ɲdWF}&'{^նf',oAu9{3qE?Q|ЉW’=&VjCKumt֭+rJhCu8Z;:5(ڹ ]؟rٚ]C3d2ܥGg.ܸqᢚkjȝ͛0oן}}w..`?c{5:|U\34粞Fggjlj&hd臅Nh _e5Ihifj3>O/4!/ ?1ҐϏJNMC醷YUeC bLRg4J.-չ SH9;mV{4?Ju:(CzLJ{5~Z.;Giˤ3WO!ZU]);wޅZNWf:KSž|i8CG>L ~9OdonN lk8yEڹBJmMsDkdμ9[fL2N,/*,4Y-M'2R_;fQV$ur-ԑ~^O̲fDvX͆1Xi&.#v7`+G-diN6Brvw7c]w};ko3,ԲĖ'tO3ܰKb xW$n~z%L7G3/Gxg,_k@vB;v&)X&mZ0V7 kʳ\-Fa|Lߥ37Iȡ/"]xߊ5N2]uÙq$/YG~o^͟1z}c/udDdfݘlW)É <F>^x yFAN-%5DC 5Om*9$Ltn=?gcK,ڲ uhiqh@QqN%d#tOVG^x![3_YC-6GxrNNl?״QB'ޘO\_^ j[< ypf}|Nuz׻!p}?myBvz wzd |}w2qvN]p"w쿄뇾 \p Uw.5uVϪ' q5Ct4}?.?՟6 f0=8n$wu_@K>i;M;^uϖgkU2?xFk;7D:Q' E9ǤCߩD)t D:W^mcC{{rOc@o~Ck ^ }??rٺ47oٮv-iD&z|>w̶e=FP!x![mf>Y2}̈ 1sRi{)Zjq:n;6^2;*{f>%cQQumKG/1ܚr?-MZ]i#y|_Gik~ /ȳ9!mV kfkI/#3\H8źׄ?a6J'BFʃJABG)S=3dub64t8Io{&xӚCkSO?LRcɟl|R-Ƨ݊?mRI߀F16OG3-D=:~DS_=Gn z'Z7"J<9^Dz3l(M,-UuZegGcκFs$MAe ٦?ml~zfKYWp83^HOSLamyeidϣfl2IaŤxt(JqrYs:6g4F+x}_b$kmqH]-Vz81d嘏A>z嫅w>(!Jw*Yə2H3|L8IE)ǠIN+j/v{uNZ[%ٵlH`XK5+uvV;0uSo@pY]ڻAU6_(9shl~Ɩ_Lk=~/% & Y(G~gl n:%f(}СC-OXh/8b"ڗ^K*rr.9lW> %|U:4zב֎|Ax??;G遽?ק%W=O㱜LRPb3)b [R͹+]ȄOz#CtMG. 8NI2'Ӊi,J pj`XW%:|O5ƨhrWv ]rCYqAQ/,)5mUu.ipa8[Vhɷ؍ %z\h ;mvDFEa6o0蒒mKjjVp煭.h\h O?rIo$29L抜8Jr"qTSB rӫCN5Zh/ǦƄf*ߢ9:}TgZO%b\#WXЗ8Z?! fA\p3#WH1sNe}<燕XKBs㍗?&t.núBgIu&_{ڙ׎+.?i^i6W[飽gZb@~QeksrY})g1[GRWW&_j(v.^YQnX:~iSbD>o-ӨzC"(X~ʒ Z*u-&[ʸ=H79\udl)_4>䆫d"vFr$YHvi@":"d٧OǨ;yŏ3pEq\e}83TRv 03P NWfB9zG0u*>`/_Iѩ q(?IrVD~d'QJx3k(—dxfP"nfY馢JiXs-ArC8oϷg8] ȴ O6svQ/ЇjG !r;%Z0+Ǫ#FR0}ɒ㪤F=TyVq\TY!Dc"mJdid'he.*{:9+*h}ەcJU-_?t y&{U\3K){.q۔cҮpܢPص%aZjћ,L]譹r̫6}:*) ˗ FŧK -κX4}U}kL.іM|kRb$ VB Le$B˒\3VdЛt9ZT`z2i"V47^u5ɠgNznbʿŹy2 Ul<r M_!xcħyHMm;ww HUw38%h|͟`N]{C_F>i2Oؗg1'Ld 65F<^A}=.'Ӷ_߱sR1aYN+]_|A>X^f #w>x@Ny_/PJֱrN7J/L`wTm G/eZ6^K<sl- }ʟ44f`iT8% 4<}}0t\_Bp7*_o 1?n(Ox;k:rX`c'Rޡ_{Xmfe,b:qk'JC#l|dn>+7lj~9A~8OZl˗R0@'m*v=܄^1Wt7Mf]ͧ+w+Mss}CG2M >dP=`/3O^;O32$$<]yNc.k+`n%NBA:QsN̲vbv/uĝG 1{6ٿ|oPUXo^<:aޥ{OhU~b΋Ͼ)AFzj>gc<\}^Ss?W|F1mULLeܵ/`̔Fu6u~wWmH#U#bTFC-9:wP'<'52uR<gqOٚږˑ_F+=oW ^;Yw鏇xWS-ҏsǷu 5|<7By e!@*F%5+ 3E"(PX3yθy]jِ^[YPt^t5NkMbQ잍C!‹MWU].h$ lwpgx|l-XʹNp%Ա[l y/ʾ4{gOjѯC-~J#Uk)ᶁ5 3V\APmJ,lNJCaL*/FLI@6Y2/z1ilvEَϏQ?+K='t\R;nicăλKXF;%Th֧a][c[dOu$# :X{yGsbYׇOcøs!N ]->߻;{/g=➕ˮܳr|]'w|u{w1Iyٕj22JS-ZPSwnWo~\}v&W}T":"C{eTk7ͭ3ӽ=X=陭-3L/ܸ4× q+̖oV3[Jrw.^\P2Xgj6T[N:ev[Ý}{e/Cs4Y:"QU Y(2Պmcaձ rE$$FWe;T3x,{L<00 F4O~" cX,K+Ŀ3ʟ_AϮljf]:Ӧ2.-\ 2- "yk6/lh?>1PwkZس5prCݨޚBkA"P߷O_)$ni+Kt`ύ3FkhL&UENiqm)7oy,~witpicY{e3Qy&"ka͌:m6¼oOu)mhyz$+ztFztpԋ\7^;áZe;W5ymf R?SQ9,?V3zi!iSVzVScýy޴+wldrU4njJ59̅"ڪOYٔy{VY'0r VtǺo cbVc+*ӫm)zO~P&Z}h>(41da[/|-o_n9G Tɳ:י TLR$mhH[r;i4YRb>@*VwTIf@R֩%ݰQ-.//Ȁ ,rQ4t\sNJ5UXB㼕8Gs5l+kB/&zs\fiUx!}huRuW$:"csrzo(%4%Ia TZ2W'ګGWk(42:teˋ/LcO36Kjb22kZ{*:4ёl y\ŋgtO^<{I N\?u Յ17=}{Us]u<6W_k) cN۩yy契(.C!Ql_/s>IY ZAJ;2XM:j9Y5[fϪUwrc2d*[VN f-KrD"]' h!+Ū(Fẗ́@;O#uE=s%^ ﬡzb(.IY-&},QU[(+28GOfA I]/vqB? d̅cÓuPjZu뭗Fk@I|tR>&ڶyӖS^u]kmw`YKX.Ԉy|Y›>Y}¹ܿ%sUYkb "V,P,fB]Չ\s-5sOʘhr`Ɗptj+P@F9N+*o$ҒWѬ =fpd̷%~g5QB"]kOX[u$-|0٢Mx;ũ^hcMYre"9eRVRȮ5ȍ |u+{x'.iYs}zRIIrIhipl%싏)eT9?v*k!`-aU8=&̚4Kmzzv?3O agEg&ЬY /hˆ~uVss;ܿ>=x9ܿe_a_g{`84˙7K/dfgߘs.|Eoͺ^s-s!3lz]=3̋amz&~6~P35wmNy^(.]czgEe]M7t j9yul}|nIR\OpGޕIr+VZ익ܤ\"E,rs-`XGM,XcUEDe!M:rg."{+!fƏ٨.fq Mޑj>:VG6}mΥ4נnj5U( YL]iU%vے^z'*M{&Hw7ԷC6lm3H;82n֞+F7ViVbo(6:ǜR[}\ɠ28m'M jW&E2AJe?qڷXZ9}ȷ۷oh8rw8N' RLۯZұʦKAǥߖy adO\dn/N|;\fxGS: $A>Jw(Ge>Ӫ>+ 3[/|Sp=^6WL[r{N߯+*= 3qI̓fݵkaCՇ[ZZ.q$r!S?Y3ν,t{iH..sRS4exk5"yJ-OyTnN ݸ倚%Lt=گ0xN-l괗t}< ߔ2O&O 'Wԧ+ψ7o'|9.v=dM/vR"MNcx7T2?1:$5N%sI:~s(O;?m̴G*{ȤaΟ--r2ҝS R~^ys8u۟;6Ńg jQ1^l}6Q{{&EV9z]FbouoiT6Ud}cBS !h!-&Q?!C,ǼMG-ǟ"7l#w=8~ңKbE*2z喺ԯU}OЩC1mpjX7݅y, \I(n[/&a,4UB$m#+K=y)T@ʷu}-Xi(RO5o-4@k2XN]+0on׬hkDE A]Υdi7To$*wm8W1-y3v.7ejKC W"msnˢ.-K]TGӞ=Y|1[ڽv;x^:eQ]?&Z[X7'm"%2>y#Jw JDE{47xQª3b?]SU2#Sny0E9;P0Y3GӐT* z\mdeWb6f4TPfugՔ?\cF] W=ȥ޷{M H`=:{gگ913?~=A_sqx]NAe}~_j~߫Qw9f~FCdս@@o3'={)ܟB5w:_7L(^Դq[2uԨvDUo-8owYwYj1jzd9|{♩(|ad{˶%]jⵡҚ7G,t>|1?g_|.=r$zm|X ,)!Id/dd?J`h$LxH=  j4OZ Bn2E+}]\< (d7=ڛ !.N.ΰE99ya8;\"@JM q{5"d2gA%XPX&͐q8`g # p8.ӀӁpy& gA @"/ۀہ/AK;pn+W#"Uxpf-ۀ=~|a#GG OBg! _WQ>"m߄[߆z:}@7hQA`#zZe9@+^xed'db\U,Kd/dd?J\ 8ʍqcX L9+yxpΘ]ӹ ˺Oy~Ǚ W2sY9^Jq.KLdLg.l8|>o@93=0=q%tfȵbi.W=z =`zp=@7 Ei6Mf`;+c= .\;3 eW zFx!"fVpp;b% x9p/ ՈZ:7oރF> | 8|> | W= !? /_F |õG B{\5,8c1G09ʱe/dd?JoV:] ! h`k˜5[ٽ c+q/V.U\Fglr[n[UWOgdl=*[4xGavi< ASG*Wk2 Ei#|.M!#x`2^ L`|g^s2r?: xBE-x  W^ x5r}-o xb~QcǑ'O"Oᪧ!? g!>|"0&m;p} GA`#c(G C`h1i1^>~h\B (0&APZ , C`h1CO,AP. 4y AP1P#QWOg(")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")")"M6>ƶ!1>0+C`e !pC+y4Cn6"&͐ہqN\5`p bN48.3!!~6pBnM /nnAsp;b%x)p'p xjƵz 7oނ x;nރCx~#>|1<|!> |x,B>|./@~\^F"߄[߆z:}@7(q k4Cii9@+G!C9 r1#4}+B Q 4^`;.`\nehL1]dQ1) `"F!h4F`!C0 a7ACZ1o0ƿaa芰& 7U7 K=Kai po xtA{}p:}{0z0w.~!oM /nnU[q6vKx)p'pp7pr^k!_xFM}[o {!QcQbOD |<#W׀o-oC~!<|C7hA 13x#x#Qy#y#4#Lcpz>ȭ0.Q ´a]&`D4`Z˭۸Qyi & ^a%8F1 (°%f2%;000 ^~`K%$l{ A~`EH"$h Am/`K%X +Bm/ $l ^ `'Hl{ @`'Hl{ KKKK%X  ւkA%p_%p_m/`K%l{ ւ^m/`K%l{ ^m/`KJ^g%8+`K%l{ }~\B.`K%l{ ^B.ЃK%l{ ^m/`K%l{ =^BO-SK%Om/`K%l{ =J%l{ ^m/SK%l{ =^BO-D >J%(`K%))~ '>F#9#>Sm+#`eJf0qUYJ.ZkGkGkG0a<]p" Cgw&CJfw6pxiGkG[y7/^mnn^ w {^EN^x#&>H-Vmہwn?{>|0QcI4g ,C9/_+py׾|.oA~;w!#߇!~A hzzz ܝGl +18" ^>~ȕ1acD llz##@!`z\v#^;4kLc40]P1X0уK@cDЃG0ly̖G0[.C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24 C3 24CQ QGnD1B'D QG% = =QXQ<ݎbt*(VD%q}z ٿ(fX=*(fL028w !x!"fVqp;b%]j7pr^k!_xFM}-([o {!Qcq'O> |x,9/_+(W׀o-oC~W |x>oU@QE1ż_(VD1bUL(VD1bUL~Qb4Ū(FQb4%`@#;D(Q | 8b{CHs/_+pyW|.oA~;w!Cߠ|A Ia&-8cym!; ;! K9{ a=0c`b L101bZ \a,Ìz \a.=Yb* A jbX]z 1̮0ҸCKxOis7q4>7>7oq<}cF=y8֗Ʊ4q̕3? \d2Wd`gϞH4I.n)DI<;Q$]EB<@7|>b}50 g0==bs`0>bHoU{{Xjoy5~WWW]Q+*w\ۊl+jv%۞hЖ ^wFtBϼkFtA>{ʷz>C EG~2}J &}޴-zޡow]{ާ#[>|}F?_hƻ~K8j^Kk&rWT]Q+fVW̚?5[^1k"=Wc+*w]1~WŭUWT*^tŬي5+*zEEW{+jyŘۊ^1涢W+fVF[mj}T^Q+{Eu _5Wt8W>CHj\ɫ+\j'M7lԾh Mzڗ`+qz-Ze1Ktϖvzב1Қϭk7h˖6.>=2рu4zFgtNtI铎4}>K}B_?7uiNߠoҷM{ޢ6}i~_/+!~L?O?k/[P_jō_{7Dc>$ɯ_5&jL~UzUUz׫w꺒UUו]dլUWկ_5Vj~UUUc۫WcbU}UUוodլUίW&zU)dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2! )dH!C RȐB2a͙s5pk1kȰfL~eŖU⚞9 X_sMk*\Ef|-?>-Ҧڥ=ڧtHG4czC }w{ʧLUjhyuit]Z?#=WmI5iVK v^lB-wm)=Zv}{V-5ڠMG8)-ڦڥ=ڧtC݈tL{53:sKzN򭞦gsy}/^WϼzF_o7[&Eo;]]=k%~!Ȗ'Kmڿ;K~]dxsua%ѺѧuIni]}ZDF%Ѻ$ZDh]KuI*뺳ug^U^7uݼϺsu>d;]7.}֥ϺY>q' ?Kg2IKIKIKIKIKIKIKZNIIKIKIKIKIKIKIKIKIKIKIKIKIIKIKIKIKIKIKIKIKIKIKIKIKIKIKIKIKIKIKIKIKIKId''-q'-q'-q'-q'-q'-q'-q|8i8is!yeH F>/lIx/<^ q$cnd9 -9%Et-}z#XJA[M;K{OOmD:׽҈N9]%=O~>C E3zF_o7[yަw^}K=>OAI?ҏ~Aco;~I⥯\ps!x//N.k=TUyUW^P\{Y/dqAv\d3B`&£\h5i%mcj۪j js/8s f/Xy'Ň&ENbCp#5I = g!;6MY=E׼>eӞ?C4G=t{Klˁvr6-UZsv6Ӣmڡ]ڣ}zJ5h@WC =3: I 훾-zޡo{}__' KGO_>o#$6dІ гЧЛЏPVnXalp!6Gb}$6Gb}$6Gb7h\!6ԆڐSrjCNmȩ 9nXy!6oH g㿑7KFl6o0j?KV#l8p.\~ùz4 ^6{$^6mMLjSlMUj6m4ӷEY[ryK@dojMk6Im:t&ioәԦMWlZ3)6U֦ڴf~Sem:4Sio3ooS:_=҈Nw.蒞'O~>C E*Wo &}ޤmzCk{׾ K~D?}~F?_hƞC{%~]Є lk֦M3ζ6n:4clkӌᦳMsf 7]5ipU3f 7]5iܔrSVnGZDGՅζ6tiMtioᦫf6njfZM7c3&F)iকVoZieE]4rѵu\Vḃ?C|!yuŞ^M54kbˡw^sW|bmҦڥ=ڧt]CшtLĐFtBϼkFtA>Egsy}oyB_? 5M9Io}j}O}ڿ_Gcϧgs[~o[>_ү|mq'Xj\~&z.>KWxTEz.V\TUE]t}E]t}E]t5Gsq]'uq]'>E+|.u-rd|Q-_TrF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grF-grֈhV=k\4VeMeUqVgUqT֪ͪ߬ͪ߬Z=gl껬ճYY}>yVvV;cgY}>vV;Κ[Ϛ[Z=z6klVmffV:6j3GգZUY/6efVmfͪͬճYz6k *k ^5xYkzY=uVmfj3GUY=Qgj3k ^Vmf˪ͬ5xYzY=uV:G5o9gƗY}zZqUY+eZe5z6kl٬sV9k}]uYr27'ss27'ss5'ss27Zs5Zs27'ss27fsj6fsj6fs27'ss27'ss27~s27'ss27'ss27'ss27'ss27'ss27'ss27'ss27'ss27'ss27'ss27'ss*:'ss27'ss27s*:s*:s*:s*:s*:'ss27'ss27'ss27'ss27s*:s*:'ss27'ss27'ss27'ss27'ss27'ss27'ss27'ss27'ss27s:'ss:s27'ss27s:'ss:'ss:s27s27s27'ss27'ss27'ss27'ss27s27s27s27s27'ss:'ss:'ss:'ss27'ss27'ss27'ss27'ss27'ss27'ss27'ss27s27s27'ss27'ss27'ss27'ss27's27/s2727/s88/s27~7~7~27/s27f27/s27/s27/s27/s27/s27/s27/s27/s27/s27B27/s27/s*4B*4B*4B*4B*4B27/s27/s27/s27/s*4B*4B27/s27/s27/s27/s27/s27/s27/s27/s276j3/sj3627/s276j3/sj3/sj3627627627/s27/s27/s27/s27627627627627/sj3/sj3/sj3/s27/s27/s27/s27/s27/s27/s272727/s27/s27/s27/s27/s27/s27/s/b:䊕KfQ/E$/Eȵot^{VikWi{M{B,}>O_/ҟ: &}ޤmz;CrާЏ~I_2xɬ%'^2x%b%4G#BSt&c&hٽK| /d^yK5.%՗ҟ7OhB˜p._z5!&Nlf.Nwh˱w}WDWhӋ4G&3—$Y/qC.?%IgALVn\r㲕ܸ;$'vHM8!)pHC R8!)pHC R8!)pHC R8!)pHC R8!)pHC R8!)pHC R8!)pHC R8!)pHC R8!)pHC R8!)pHC R8!)pHC R8!WbW!J+Db~ \lyor%I.=G(߫C#zlKh6}>C EL_ҟk|Aߤoћvަwێk=z~я)>C%c=vT}bG%bG%]=8+z,W_+up"}pQW8JUsWU\1 tŬWb$̭?-c㱋@-z͞O3Vz}DS U}^=Oi?M"O8:}Iߢ7-zޡo{;-}>ɧ{ Є*8<{ ѿGt:9hXc3y\׏ǿ~?Oދ'x8<"'vEM^5"tU7krUkƄIܲ}]wkxWŖ#vgh?Og9<}he }>7|k|AߤoћEo;#ܣ~ȟ3>4ɠWW^uU\uU\喫q1"U>'W*\哫*\ŁW[$\[~ͭG&V;&x}%[bKRlɈ-=L^=tdזnomv[~WK2}JO?3Ky uTܖRq[r| 9dR;[xKo-Uj?Sڒ[xKo-Y|5kF`o_S;ϯ_kb}KKt{ׁ-:ڑ->JkԵՉS4}>K苎}B_?7k|AߤoћMз}w]xާ#-[/oW\M*⮩kV]ݒ}\krs^y5 bGk?ӄk9O<_]k| a5LO.C'E-z'ݳvOoDh$IB#֢wQ߻].{ZDԢwWE}wQuH[E}wQ߻]TE}wQ߻].{E}wQ߻].{q].{E}wQ߻].{E}wQ߻].{E}wۋE}wQ߻].{@Q%iQE}wQ߻].{E})-ܢwQ߻].{E}m-)mٶt%v C3mg\E0-#6mˈm.mٖۮۖa[:lKm-6m[۹mm綵vn.J ͖Mi[6Cߦл>O?ޏO?~I|c ls6ms6mKm Ɛm m-ötؖ\%Dnƙmmnm-ötv}6/m6/m6/H#vÎtؑ;aG:H#v8dG:H#vÎtؑ;aG:H#vÎtؑ;aG:H#vÎtؑ;aG:H#vÎtؑ;aG:H#vÎtؑ;a/H#vj;~#vÎtؑ;aG:H]]57+/ve:u&wŮؕq^1]Z{Uu` =H8vnk&ZN|4}>K>%2}Jݠ:}Iߢ7}[6Cޡw}=z~яmT3KƮzU}]gwz1]cwv]]Wo7Lî]c}vzߍwzUz}W]K|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_W%*UJ|U_jx==3{[_{)Ѣ}vwi^p9G*yo]AO,}>O_/ğ: -7-zӻn}C{>{?~I|{칗˞{왯3_gr|=>=>={q5hk5O!{z{z{f3f33gcǞq={1c3Y2由Ee#Ke)끔@z e)#OySvSƜQsYYYs219e)cNsʘSƜ2IRƖ2-el););););)**cK[RƖ2$e$)럔$e$)#IIHRF2$e[e5e5e5e5e5eTe5e5e5e5e2”0e#ce#ceTe)sHCR62V62V62V62V62'zz'i_6K}N;}}}~G}4G}4G}4G}}}}}}}}}׫׫׫Wz_]b_r_r_rocccccqw~8++y5a#WXlߵD쳯9-5[$7{Á7{Á7{Á7U㼦:}Iߢ7sަw]ǹG>lH98?p xF.M~ȁ_HvFE?0~7:<؏d˟;mҟ⌾8 aEV^Z WxbԷTbEVdhůYqF_VdhEVWW\]q^_+Wl`c+X 6V"C+jZZZZZq^q^ 6V"C+2w d!+YQk d!+2"C+2"C++

      >C8C)yh<ڡyC6m9DC8C8DCIw=b!&:C|>C|>#~wZюZaKS,}>O_/zK*}n8k|Aߤoћ-zޡwO?Gc[>Y<_d c+x=6vl ڱ1};I;I䱾豾豾豾9c+r;[9v{lݏMX;=v{I՝OΎTZKS]o>V巪9ܪ9ܪ*UuUr]nnnnnM^EM^EM&5jf|jf|jf|j5Úkr]53>5ÚaMϰ&_jf|j&_j&_j&_jWP3S3S3S3S3Sc jz5^A͌O͌O͌O͌OMXV5iUV5=C͌O͌O͌OMr$WMrkz5ǚCMϡPs=d\Md\ jf|jf|jf|jf|jf|jz53>5ǚvհX3RW3RW3RW53>5!X jVC:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:`u#XVG:5Z5@58i NkpZ] wmlj5P:w5] jpWz_ .jpQC/je5\5Q jpQ\jq5x3 iLgZӓttW4ݕ&G5qiEMI5MjRԇoVFHzMOizNIӳutG;7QMwo~3욞ILg5=tMϤkzNӵM6]Kt-aӵM6]K̦8MqV4ijW&6y錠錠錠錠9Mi~UMW6=usMmz\Sv!߸P16:ԛ45555ĽOSbOOܛOΉ9qsu'h|WJ.]Zez@{z5d˱v־ֵ^m6.S:9]%=O)3Y}@oЛMз}w軎|{WC[> O!O!O!OܭOܭO!O܁O܁O܁Oܿ$pH.-wYl֖,Tk][[Oo>TjITjbK*e%ZؒJ-wYlITjIYK6ZR-WxKgk鳵Z*emyKpizåU+U˕-9R-9kI^_K\R-W\R-[O[O[O[O[ZmokF6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6mh#@F6t @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At @:At"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@E.t]"@C=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC=!@zC}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#@G>}#皝SO=SUOU9SO=SO?uS%]Wh:rRr}ۿJk׵eKvhhҁ9 iD'̻ftNtIOi }>G/Kҗ+U3p״_o7[ަwێ}מw{}ާ/JC-OS3-B7[~P_jw}Cz*ǞZ{&WWki Mp{p{p{lxoxs#?%F{g>uS>uS>u/SO=u/S8u/S8u/S8|S8S8SO|;5Wx p 0pFf(1@J Pb|~8700W>7XU2@`?0 'XO2p5Ոq'0p5U%JV *H?׍h@c4z]3: ISOg9<}pMзw}=k~H?w}N}HO_ohR9>33333U+3jp V dj&MV9+.jp`~ {`~ jp jpI58Ł'=djpj́5]kt \9.e`])C=C8TC=TC8CU9TCU9TC=C=CU9TC=TC=C=C=C=TC=C=TC=C5;C=C=TC=C=C=C=C=C:TC:TC:TC:TC=C=C=C:C=C=C=C=C=C=C=C=C=C=C=C=C=C=C=C=C=C=C=CJbPja(R{(R{(R{(0D!2 a C=C=C=C=C=C=C=D"Pjc(R{(R{(R{(R{C=DJJJ!b 1R{C=DJJ!b c(R{(R{(G0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!F0B2a #d!C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 2 C 20F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#0F12a cd#?Ec2XOzL#ב:2\GpdHƷw] ~^9%-&W^[^-ڲsKtϞoOx{|cVik]aϖ#ivi)8ڐh@O iD'̫3: I_4}>K苾K2}J״_o7[pަw^}w}{׾ %~!Ȗ'|꽟mڿwWүm&d c2įdH;؞zL]$ɐ:i@_ՠc2$CU/p?^7xQx4h#&CWKp=&C?&Cb2$[~Bc2S0 c2ğhVI+I4DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!DBd!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B"d!B&0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d &0A 2La d ESd")2L@N1a SLbES닦M=N=N/{Z_4hj}ƩES닦M.N/Z_4hj}ES+VM,ZY4hjeʢESU?USU?USSSSS+VM,ZY4hjeʢES+VM,ZY4hjeʢES+VM,ZY4hjeʢES+VM,ZY4hjeTmNT%N,ZY4hjeʢES+*q*q*qjeʢES+VM,ZY4hjeʢES#{S+VM,ZY4hjeʢES#{S+FVM,ZY4hjeʢZY457hjdojeʢES+VMUʢDS+VM :3gq%Ovgq%[VlY)8^H34o#9%{n]Ze?N}6gV?32fd3#gFItD:?'}|,}>O_7MMw}]}O}ڟhNlH_V_{mMls6glsƽg{h3.=s'3w>s'3w>s'Gl-S͙-S͙-SYxO9sij~#z_-aܶڶ3kάmqg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg88pƁ3qg899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p΁ss899p \p.8p \p.8p \p.8p \p.8p \p.8p \p.8p \p.8p \p.8p \p.8p \p.8p \p.8p \p.8p \p.8p \p%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\r%.9pɁK\rsbOzM2w??e.2wwߐM^{8[]ZxZ]H6qwkk\+j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9D$G$G$G$G$GU̍/Q#Q#Q#Q#QU&j$9*gFFF7j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9j$9ZEUjUUTVQ#Q#Q#Q#Q#Q#Q#Q#Q+j$9rE$GU䨑䨑䨑䨑䨑䨑䨑䨑5UF*]HrHrHrHrHrHrHrHrHrHrHrHrTIIIIIIQUFFFFFFFFFFFFFFFFFFFFFjeTEŲIIIʸʸYC&f 5dbˋ$&#bȋ#/f=bȋ#/fObvƉɎ]ecc"f=&brY%f׼]bv͋5/f׼]bv͋$fwbv*٩$fJbv*U6fW٘]ecvc"fbvЋA/fJbˋ//fbˋ//f}Ib%ٗ$f_bv&fכbvU6fW٘]ecvc"fOnbc%bVYE$fUDbVa ucH!!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8H#!8Hxoy^K".H".H".H".H".H".H".H".H".H".H".H".H".H".H".H".H".H".H".H".H".H".HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!$HH"!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!RHH!!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4HH#!4Hxޟv/{g}B<}yG~7oy̷ls{bBL)1->_zcpLA,%,gx!V=&6ibO(jo|7A_w>'g_A?$~X|[1^?%w2|f'g;vgHxfg0|fgv)|fgv)|fgv)#=#=F˱k_w<7omvwT?bbRLix3bV̉y>۱xLA,%,$gx!V}-RyP|TwA|{kcc;gЃ=փ=փ=vӱJ]Wr캒cוx3[XOXOXOKU:{_~z{%{K>vӱ{NmNvDj?v{bd^d>/_Wůyw<^7m;]1q1!&ŔG^X~~Nr7~}}#aw<7>O}㧾So7~/ccZ\xTwA|yOŜ-95Zrj\̩_~85qj>|ʩ;wSOOͧO95rj>|ʙ>gZLki3}ϴ>gZLki3}ϴ>gZLki3}ϴ>gZLki3}ϴ>gZLki3}ϴ>gZLki3}ϴ>gZLki3}ϴ>gZLkis}ϵ>Z\kks}ϵ>Z\kks}ϵ>Z\kks}ϵ>Z\kks}ϵ>Z\kks}ϵ>Z\kks}ϵ>Z\kks}ϵ>ZBk_h }/־ZBk_h }/־ZBk_h }/־ZBk_h }/־ZBk_h }/־ZBk_h }/־ZBk_h }/־ZBk_h }/ Zg+{Um^5^u?DUWyjUW^U߫bׯ;ů;W3o+~czW_~W_~Z_U}kUZշVUU}>@UPfޛU{oVYTPuC U}>@U$TPuC U.TPTU@UcfU].vj˪].UcUcUcUcUUw?PT~O[_꠪qqqqqjjjjjjjjjjjjjjjjjjjjjjjjjj~U߼u$\Cr> u[VCru[VCB u;$[VCru;$\Cru;$q^Cr u\suw\7Bu{#\faݚumVWHnvH!~'n߃}=n߃}vH˔L˔L˔L˔vH!nvH˔vH!nvH˗|˗|[n=º|˗|nv9nmCOЧmhRJņ+TlR+z =ކh`hhhhhh"&jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4Ղ&lM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jAS-hM4ՂZT jA<&4y4ՂZT Z bԂZR ZjAK-h-ԂZR ZjAK-h-ԂZВ-R ZjAK-h-ԂZR ZjAK-h-ԂZR ZjAK-h-ԂZR ZjAK-h-ԂZR ZjAK-h-ԂZR ZjAK-h-ԂZR ZjAK-h-0@ - 0R ZjAK-h-mo3f6󷙿mo3f6󷙿mo3f6󷙿mo3f6󷙿mo3f6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}lf6۷پmo}l6}ޗ}ޗ}ޗ}ޗ}ޗ}ޗ}ޗ}ޗ}ޗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ}ؗ|ɗ|ɗqeo5uԱP:@uXuaKwԱP:@Xcu:X,u8c3wuظu:Ygc㞵'w\бPj@uԱPj@uԱPj@uw8uԱPj@uԱP;w8sj@uԱP=quaՀ:<ܱP;VX c5Հ:VX c5Հ:V0mj@X ôuԱPj@uôX c5Հ:VX c5vaԎՀ:aԎ0jj@uԱPj@uܗױPj@FX èuc5vc5vav]Q;c5Հ:???#C;2#7;ri\ce&iiWrE+r-Y+/W]W=W{źW{źW{źW{*+ֽr\-j+W_ZuXuX WHb+ֽb+W_ZuXuXʵWrmk\+_k\+W{źW{źW{+ww^ݝWb+sWr9+sWH2Wxe\ᕹ+s]Nrr.'w9]Nrr.'w9]Nrr.'w9]Nrr.'w9]Nb.'w1.'w9]Nrr.'w9]Nrr.'w9]Nrr.'w9]Nrr.'w9]N".'w9]Nrr.'w9]Nrr.'w9]Nrr.'w9]Nrr.'w9]Nrr.'w9]Nrrlrr.'w9]Nrr.'w9]NrrLrr.'w9]Ns{?=~s{?=ӓ;=~ɝ?N{,cKX=t{,cKX=t{,c{t{,cKX=t{,cKX=t{,cKX=t{t{,cKX=t{a6zw{c{ٻ}wg>{ٻ}wg>{ٻ}wg>{ٻ}wg>{ٻ>G`wg>{ٻ}wg>{ٻ}wg>{ٻ}wg>{ٻ}wGx}wg>{ٻ}wg>{ٻ}wg>{ٻ}wg>{ٻ}wg>{ٻ}wg>{ٻ}Yg>{ٻ}wg>{ٻ}wg>{ٻ}ڗ}ڗ}g>{ٻ׌}׌}׌}׌}׌}׌}׌}׌}-_5c_˗kƾkkkkkkkkkk$_#E\}\}\}\}\}HkNkN'8yNp<'8yNp<'8yNp<'8yNp<'06؀p<'8yNp<'8yNp<'8yNp<'8yNp<'<@<'8yNp<'8yNp<'8yNp<'8yNp<'8yNp<'8yNp@6 8yNp<'8yNp<'8yNp@&8yNp<'zC~󐟇+ß}ڿx W;99[9?ßss399?ܕݟQϱz/ϭ|s+q\bI,? jb#bSlmRxdW9w<<_xO;g:;^xRkǏ_j'ڈ{`;3>7x Wjx=89~ݺ^0 u`vz /vfzs!â|ٙa?&~{{yxȎcfx3^3 fx3>zLt fx /vfؽ+^R+^Rk/뉵'~YO7Zk9N8Z'rjkξ'웸o7ĝ}wMXqb-lj'rXqb-lj'~SO8o'~SOXqb-lj'rwo޽'rXq7oꉵ'rXqb-lj'rXq7o'rk +&ԛXqb-lj'rXqN;&ԛSoN'울k{&ћ5=kzį鉻&Λ;o󦨘b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*b)*A np$  7HA np$  7HA np `7 n0p `7 n0p `7 n0p `7 n0p `7 n0p `7 n0p `7 n0p o|7z8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙLq8c1gz3=ƙ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p ܪ*p U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sU` U*0W\sUNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNST;UNSZ2jafaf",TPjB-X `afafafaf,ԂZ0w0w0w0w`/,~afafafaf s7 s7 c 38 38 38 38 38 38 38 38 _p/8 38 38 38 38 38 38 _YYYYYYYYYYYYYYYYYYYYYYYY0<0000000/xx ^YYYYYYYYY ΂ofp|00000000ۅ.,,,,,,vag 38 ]Y ΂o|0020202020000KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKyo{[=VO+ﭞzj{WܻNVOwU̽^ӽ[ro{[=VOzSﭞzoE{+"[ފ{zSﭞzo{[VOzkT]yrsss{Wܻ^o^oZ^ [9w+]x pń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbpń+&\1 WLbp%OWt%OWLbpńLLLLLLLLLLLLLLLLLLLLLLLLLL~`&|`&|`&|`5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p̈́k&\3 Lf5p-Ot-OLf5p̈́LȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄLȄL~dG&|dG&|dG&|d—LRk×;vr/w&Ho;G_Yyg ~Q K3/_UwĽ_xs̷[~y~(H3/U7C1bBL)1->fqV̉y?X< bQ,e"gx!VZMl-R]}qs3Ϛ3gn/ĥxG/1Fܯ&jr/54\˝3rrvq|_wfҗ^rKs /Y?,-~T Oֈ{i^Axɐ/ dȗ^5xi]V{{ڢoDK /&4l+V|%O_+V|W^2k7ڹnW{徒W+ye+|徒W,۟m}l^q1!&ŔG1#fŜ{g bQ,ecsB5[ܡ;q<=A|< |W |徒W+y徒W+ybWL_Վ_?,-~Twt+?#? PjG%]%]%O]|zmSO`|2OdII8II망O}'>!I-x~R Ԃ'l>S?O*d<'Q?pOc'OğٳEWww1*.&Ĥ3+gY1'c| ŒX+GXkbK|Wy8tBL|8s³_9~pv%pk};wg.o:Ѿ]|[D>w>wO}v_ٽ^mݻ5ٽLg.;ٽ}vb[yg.W>؏⾭؏gv9];/loǷwϷſp%W<< g[ۻ]g>|ńSbZ|&ynjsb^v,8SbI,>əx.^U&6cK{;;3q<y_?~amO?~7;5vW؏beHD7~뀻뀻뀻뀻뀻뀻뀻u]u]u:::wpwpwpwpwpwpwpwE(:@wpwpwpwpw{UҢ,23SUi¾dfu*^Jhġ.Ɍ#J@zAH6{ĆBC#և*9}Z{4Ю@hWj] v5Ю@hWj] A4 rDNj] v5Ю BhWj] v5 6.j] v5ЮFzh51aF!VC4lmGZ˓.dO`߀7Mx&oq')Sƞ3dn%$>O3߯g9|_E| _ez_ycp5I7f܂o:UqwN܍{^܇!9O3bҞy|%|+*.pWWj\kq &nmpݸ}}8za܏sqO;>W/S^Wc 8cV1٩h;ꎦh3Z6>V"3ڊ,|w2VB}:mShvS|+6s`%ho::&5ZGø~dޠ6Q&MɼA&dޠɼAEmMBY٬l4f6ff3f4h6l6Y5[n?T6h6k,NC1,N]4h6wlE&k&k&k&k&k&k&k&k&k&k&k&k&^B%D]B%k&DZB%DZB%k&[&k&k&k&k&k&k&k&k&k&k&k&p&k&kB&Di&k&k&k&k&k&k&k&k&k&vBl'v&k&kBl'k&k&k&k&k&k&D{&k&k&k&k&uMPuMPuMPuMPׄV ꚠ j5A]5A]5I]5I]5I]5I]5I]5I]"<)“5)Γ5)ړ5I]5)b>)b>I]=I]5I]5I]5I]5I]"3I]5I]5I]5I]5I]6)n5I]5I]5I]5I]5I]"0)"0I]5I]5)5I]5I]5I]5I]5)ޒ5)~5I]5I]$I]5I]5)N5I]5I]5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]Sb/%R.%R5E]S"-%R"-%R5E]S-E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]Sb8E]S5E]S5%JS4E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]S5E]Sb;%Sb;E]S5E]S5%S5E]S5E]S5E]S5E]S5E]S5E]S=E]S5E]S5E]S5E]S5E]SZGkkkkJIQuMQuMi5)ꚢ)ꚢiꚦiꚦiꚦiꚦiꚦiꚦiiiiꚦii1i1iўiꚦiꚦiꚦiꚦiiꚦiꚦiꚦiꚦiqiꚦiꚦiꚦiꚦiꚦiiiꚦiiꚦiꚦiꚦiꚦioi?iꚦiꚦiqiꚦi'iꚦiꚦiB][DK um յXk-Ե.+%mr^h;^+:q%kR:7xwZjK՘2 'Zqt֝w,a||I| gp .S?_ėe\WU\ |OVWj\kq 6f܂o:vw܋p?p~}]ec-a|,f0ˇY>a|ջeg?,f3˟Yg?,f3˟Yg?,f3˟Yg?,f3˟YgN~Y;zYv6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6n6nvmvmvmvmvmvmvlvlvlvlvlvlvlvlvlvlvlvlvlvlvlvlvlvkvk!>;gvavavavavavavC|v!>;x;x;x`?IwQ ¨52#CHJ+ƾFgsyx-^z' RněfqZ5S&)y2N2uK!e>K9::_~$>O3:=+/˸Y૸_Wj\kq ѳl͸ttގwn܃{qCJ8>>ʮkǷw]9!#9?x,Og/Dhx4E#īYG\?G`6H&v--E ">m(X4Rlw*Sg=#0c݂#ς#ςgȳFy}Ztd#ςgȳ`Y4X^S4X7hZYofݼE;ĊH?*PER4 ] /h}ޢE{*PhoK}hEsEs1}<-eaT7G)zshhhh0܃Eʋ .Z%)Z%)Z%)Z%)Z%)\+hWpѮ]E}G1DZcxE{C驭wr.9\shp)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz)AJz{{_m덖VJ*iI:;>FN=NSiMSөtSt)33}MN;Fvj +ո:\ qwN>܏=(xO wt;:K 8G;Nb:{Sѩwt;:͛u#:IԩGtZ%>iӯN2:Q;w.MN+q5A\MWq5A\MWq%UW]K\u.q%UW]K\u.q%UW]K\u.q%UW]K\u.q%UW]K\u.q%UW]K\u.q%UW]K\u.q%UW]K\u.q%UW]K\u.q%UW]K\u.q%UW]K\u.q%UWۨW=mmm n_66666vjn+)NvjH붞m=zJn)SEZStc%n={Rӏs< ϋ}_ W\p=nPF&܌[MG6܎wn܃{qJ;(Ú{~ 6+唳!#OK?dec*f>9oxvgn+#VF%tKt[62m,meHDvm,ѭuKtk02meHn+#X dwa\RnkZhCvnovJgw7Viu7ݴVw{ۛ$&i =4C{hx Ѳzhx =4-C{C{hx =4C{hx =4C{hx =4C{hx =4C{hx =4#zDQ=4C{hx ="GlC{hx =4C{hx J``S?kOi@/@/@=SkOi=Z%ﵧ*ykW@Hib׎^1wboWrq{p$>O3*s=^ėe\WU\ |dո:\[>܏Ʈ[6w=!~$c^T{OWKgW{s/^;W{6l;W{kjUv{kjvkjkkwv^X{+W^_y~w뫫/uu߻l^@_Fm83EhZ9Eط2`ʀv9]hv9]d Ȣ%޵:7(F)7κE$)q NU4t9gRf8_ ħi|R{g9|_pE| _e 5\j5z FO 7|ѭ ^܇>GGU1vǝ6K_?d䬏ϰg؟gc0`6@ Q؀>s Bd3&0)Lc fP0000]߅el (Am  PaQo,pjSZoD 0;`6w@o<{o]bgg?ƞ^/ǿ K+k|W*\kp-7&܌[ % ĭ w܋p?ǃx>>>>>>>>>>>>>>>>>>>>>>>syZϵk?.ϵk?ʿW//u[\p5܈p3n7+|6܎w.܍{p/x!܏ xbT~R^_ԯW+Jz~~~~~~~~~~~~~~~~~~~~~~~~|V|>+^f^^~ {ElnޏF~al\8 !GRh?p,;'Mk㵎^㕜%;qp'-xs')g2N>] LS]܍8>!e1>O .y|%|+*.p5z=/xуx;(>Ʈ·>#iaϲϱ?9sW Ŝqv*J ؈6ǒw;nQvh۰; OUa8S0Nv{ qv*05U@׊Rų qāٻpw,'cXc8ˉ߬?9yXJ#DXcK83\? W?g[T lxa|Sq^9( ɞAx *p2N>gLѻ\n%'\e1>O .\s<%|9|k_+٫p5V%Ow:>ʮk']~IOċqr?D9sgc=rOřq6hl$;NgW̰[6l-TW{bO=U/Sq^90Sq6ۧSq6)5{\<++88z@=畿}*+2VU I8Q-x ĞS0UiNg`d߉wIg=x+q5z 7|mrn܁;q>܏pK9sO;w;7xDEI5Hpk)]n={O8ħi|Rg;Y|}_—qr| W|%{5z܀ 7|ѭj{;܉q{q/;J͸#509=y}yOvS-____JS8=ǁ>/,0$ oot&ẟ7!orkPOByw'd"}s9kTڝRrݻq{JXq u7(an͸pM8;p'sQ<9H9i)x$Dxx%'qJ`,O8&/O/O/O$D!{XB|!0'~w|w'~w|"r>o}CIdS?=]xYx/W.')|%TY|}_—qr| WjZq u7ȿm͸tt+n8;p'=~<Qv}]soqg>')w>~ 9c<3AY9> pŸcX fUܸ#jpv==:U܃1,~#32ILa[0ZD` _͌z^/E{܃v<,` _ ` ڌbǡ6)g=w7#!O}5˰M؃ ; Eʭ$d"T. yfR»qօ{qdո:\\ ou6)qwN㬽<(= 9M:5aF?ES?E(Y?ES?~2,a;v`; {"/aa)BJ/įKFpw'oIFؚW$C^~|,c%5Kk|70F{5~M*V=BkTXvNzI| gp .uV'zG_ėe\૸_g>܏=bM[6w!~$c'sb>G]s=G]s5G]s5G]s5G]s5G]s"3G]s5G]s5G]s5G]s5G]s6'ns5G]s5G]s5G]s5G]s5G]s"0's"0G]s5G]s5's5G]s5G]s5G]s5G]s5'r5'~r5G]s5G]s$G]s5G]s5'Nr5G]s5G]suu'ZQqK)Q]QqKQ]Qqf3q4vGc/^1/^/=}ވ7͡ P'dS]k{:κ}n%={}1>O .{g9|_P˜ 5\J*\kp-7&܌[MG6܎wn܃{q ҏcm<'|N)fHΏ4A81N2ΌǸ*q'еibucޣ80> nF7s>xxs ́72>~:p2Nq4ӥRf|zW: W\p=nPF 7|C[&vsq'RxZA!e1>O .+Y|y_—q^Wq9+uX)*\kp-7zMnU6vw~:dec{9skQ.bz/;fg`7#٣)^% L;n1gح!K,8ZZGAk}q܅}Ŵ}>cYv=NôvLaO_8X waƽ .HC)?ҊjmGZO܈7Ho >')S]w{Rf:N鳔s<~ᗁOHYOS4>Kp=ѳ>/˜ 5\+q5z܀=&܌[MGm8;p'=~<#*oq|OI|S}@ʯ?cG`6H&vww2U/~6qe؎ {h}G]l]lv~]{v2Ne8mq;nw|{%0{ofO }[6vp S5iNqdRn̗?vMWj\kq 7f܂oȳ}np=p/xJ;sO;RNRy+J6n>_씳 {"6?;~1:p,;Ѹ2pw==={ wħi\K _Wq9+p%ո:\F܄q nuoqwN#^܇{>*Goq>'}я4A<"Ex%^%=p8{&);NVbv8+h%v{"<05q(cpϵ!>#p</s` ;a|xތHqix'NYKSཎ>>Kp|k_w+٫p57f܂[ގwy>܏܏ (֤ǥ>'}я3AYhQDx%^wjpv==ksIvf9Fof ;%((jvcOD)` LaGe`=Q+^?TWoaxo~+ކw$y&gMcOw )wgJXq u7ȿQ9p3n7܎w>܏pqO;J>%xZA<+ 8Gr#0il6lǎȸo?\dܫ"BcByq8Q-x"4 gyލJ\q u7(s6f܂o6yx@90cx\N)}<- X;p|Lm-rwdhep>XV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRV/eRQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/RQ/X/uuu\uuu uWԝUwy5d_V)CuWbv3C}_ W]/Zt&Wյ J[Z#kȾ.GSWш!G=,ɐ}yݨNHbdא}y]țWjȾ.1p.uWCv(/V١LJo׍8dWϐ}EݰoE݌o+}Ⱦ}eU#ٗץF'#_OFd3>0dg|}UH!}u,qƐi3v5dG^|x? +p? oGƆ߲ٗHܐ_0lp5匨١GǺbu=b-9Cv& ! ~xR1 !a6d+Cv,G9!;?;!;Kᯫ->r9C)"$<^xŸ<2u3C\MPc.?xO )5/;Ǔ}~X{b,ErϷԔ 7м'OtK޾N ſΊc)ߴOo1uzsR75uL|Kb(pVjy tQCsZ}!Rv4O=X%m-Ec:ԋ~_G}v yǮ9[{CO1:᯴Թ =6{Hfz%>|ΐ> ]{Iu~t6{D1o_cgK5w?Ό.>:sRs==0 +,p#zP.Ee藞j%cLV~b{ylHQ Qך;s/YE}x>mxnCC~_W>>w\wH:^L}U[|K}_M/Me)}{إ2̱CZ:>BHTд{Cs&Es$x-`Q@" 9HLt0 Do}ˉspт? %%.J.VY_1!%=4'.5a,?%^99 fKLzޗm}s $f;) s⧽/9sG.0TD^oxAp<.{f/y+0}p\'斕Pƒ=6w޼O$Y8GM|iOLsCptΣs.3wb,]^?'7?㉷MvW'NɟN)'&xʴ2OIL>eS49sk|@u?gG+TpKC*9s 74;ý-u4R~Ѓ[ʢ:s¼%,l 7 sp99_Թ\ sB%,W{d=4^n ݱ1s4<g u,Eߥ,sˋ*RctJFxs-3NX0g# .BQ!͞e/ l)X{HvKv{^#M7;@FC:$2F#MM:Ɏ`k(v ;`p{r^A3^ūy |̇| |#17|39߂oɷ[mH-ߎoG|>u7l9wX䍼x|>O|O>d§i'3}ħ|_>A`~?gx3o<,s|6{|.dOxx?|!_G#Qh~ ?ȏ|1?O ~&?~!_/ ~%_ͯ~#=o'~'3 ?| ?ɟOg9<//*-w6!? o9W-_ſ'3k\!ZWxL Q)D`1D pX_l 6&bS;1Bl&6[-Vbk)ۉ(-vcDDDELEBԊ:Q/NbgU&vcER4&i=81^L{b/$&}1UL )ā q8D*2YVmbh91[b][&zDb/b8\!G1Xq8^ NIdq8U&Ng3Ylq8-cqH\,. qJ\-ײ;=&N\/n7ߋqM. (w?_qO/xL<.'ē)xF<+ϋRxIM,^ L)owĻ=X.>LK/ėbJ|-ߊU;A(~?_jF2ɥR*t'dJV9HCP9LrCXn"7#frsRn%ȑr[^;rG9FFdTd\&dA$w]nrw9V&el)>I!rSN{ɽ$9Y#ȩr.g}LJ/ʃyf"[eVY]l9GvȹSvd& |J>-T(_/W5|C.oʷ|O/#D~*)?+ \)_orN~/?ʟZQLq%TJie\2U*TRժF R5T Szj}Pm6VM)6S-Ԗj+FT۪jAV;1**yԪ`NvxdwdJFNR*|QƩj &jQST5MMW3ԾjOPuʨfբZUVY]l5GuSunuQOyjZEpu:RVǨcqxu:Q-V')Tu:]Tg9\u:_].T%Ru\]TW5Zu^ݠnTW7-Vu]AQݡTVw=^u_=T_#Qz\-QO'SizV=W/EzY^UjzSVw?{}\}>T'SOZ>W_/JZ}Uw{Q~VjfkVZkjOr]+u5zz z#DoGz Jo#z;wУz討NZ]uIwѻzNFݤS:} zO=Q֓diz3~z}>PևCuF7ݪM:g9C՝Kwt}_P/҇#(}>Fz>IOѧ }>K}H_/ї }J_}I߬oѷ'}KE߭~H?яz~B?Og9~A//~M-w~GH?џ oBW^'Ek 3#2x̔ SiL1`3 5pYl`64&fS;3"li2[mHloFhc"&jb&obv5X4ɤLf3Ό7̞fm&f3L5t3kfs9l1i6-dMeM6sLk:M6kLgfYd7G#Qhs9g7'bs9ٜbN5Ls9ۜc5Bs\b.5Js\c5י F{sbn5ONgsc5Ay54sҬ4_7[|g7?OgYm8pq\sʜr©tj v8Capg=g}ggCg#gcggSwg3gsg gKg+gkgg3q"Nԉ9q':uNuN䤜;{8gOg3əLq:Ӝ g_gssssssq:m,99N3tn0u~g3Y,t9;G8G:G9G;8:9;'8':SSӜӝ33ss KK˜˝++kk;797;8:9;pɹsn^>~A!a#Σc I)iY9yg7eU5u gwm]v'=}v7-q_oc$C#cvO3_ IKg=|vָ=rWUv븮en[VUn[rCܡ0w;w;vwtǸ7ܸpk:mpwrwvwqwuwswwǺI}6)78w;ӝNr'Sܩ4w;םffmun;mwslwu;.=q{>ߝNw ܅"pH(hX8xDw{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{&fV6v;?wvr>>>>}}}}]>>>>>>>>.u_t_r.vpoK[v9;.psvqu.w?p?t?r?v?q?u~]]~~~~rswptrvqWkkA1qwZK5ёqi}$]t+î5[:g >eWtty?F˾%\/+qE_TETNgnL~ `0 &kM)4ommmmn6nCZM.ӓڻzh$$'A8 INp3 $'A8-"F4AAV5 l a $b- bM bMhhzMׄmBC&4 =ۄM~ S@?)O~ S@?)O~Ӡ4fp|ϲnp&aDvG4A= >> NAo(K"Ù$!dC6#]E30u IF&`0A4Џ~#G*ޒ 'pil'p((EA)F(ZEQEKhiGQ -14svd{{g L`I&h&h&h&h&h&h-ׂ~mlVۑu" ,&t{{W\Z0P j@-` Ԃ:0P : :@=}==}E^Cxu7JMwEuӽ2>8]A2'dS6#/ӡN_HUc͑_|=/(taz:g>]:2}]݃Jp"OVХBfZ+s\#2k)vug;[:ze{܀7 cK.RϾ\sVG'o=l@5L"9ss5p*r:-AGᠣpQ8h:^TvA_OXqq$@juE]Yإ4R:\ணpQ(u ]G}%vɇ]Po}mYg;\\g}wUy{/,*EUˠ #_Q)5N2殰&.{еkC BjVh+¶nvvvۆ"cj,Wdl+bxhaOVWU~s˄94jns7@{KMJ́fHE#@Ὦ͸'*, R9dMaH=^ jɵ+Ĝii._i;'5$Va:P*S V&YFJUILSV2 Cic1whL/{:rk쁅%{2X(#cЎFvwv+tQimDca_nNIWoxšnq[ X Z ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `kA`kA` ` ` ` ` ` ` ` ` ^.QkV6x?䦵bWeɎLֹLE:l]*&e~efgZRپ#QS$:zZ;a* twg֌ث_/fPsrJ{57#ep!'d{sK8FuYlis?Ѱ1y4Ɔ5їqPZ4)gT&u&$:łKwޠQm죶vtAWʸz-6+J{ Tc]8rȩǰK11a8bp1XTOԌ϶,!k9z]=.XT &Զw^gF@֪[Zx0,l,d({T-|bee(0Q=>7~ٞ(shgIź=EN+6jz~[QDz h*bʩ-ūqVRg( ~UzwP:Rdj|A^Q+hk9.˲E%%ϭ%9E٢Eg/tYwlQ٢//NJR"_X*޵şsErj(GqkɸU2%8tђ:JΒQW:甌ڣ(n-J W]Wbűx\.2&c u?WYeJU@kf:[QxAwp-,=8 3c =x}0\` 0 qıgo〠8;c ސl}@}l!ē-8Bc !-8IBk!ql!ēF6B6BFo}$AAAA @ @; q,ıB; q,ıB; q,ıo 8vYcg!B; q,Y>vYcg!8.)(L3Y\s@*FqbıO4Il4`+q\ıE q\ırFC+q\@ rE 'j}"lllxku ӿD 0 /8A?%0K`v.]fw %0KAfw %0K`v.\fs %0K`6,.Y\Dmi)~L)`\O%g,QMβ=_qXfn&.d`mEkfViӏf˴xYO-;xB\gkmK䢊"LolO.M2أ"vowe\'rr9fx$Phn6/ϓ*`|k TGjlv_/IA*eh70 ŠŊ邢94*[[Il&Um[Il&Em[Il&a̓0Il& j+I&FkH` 0 zQri2vDAIl&FlIl&lIl&lN& 'sI¹$Tp*I8$G# 瑄Hy$pI8$A 1O˜'a̓0I$ r9 ANbi-$֒XZK0I$ q۬I,emȘ0%u IF&`a#7~#7~#7~#7~#7~#7~#7~#7~|HHHHHHH~Ӡ4A? iO~Ӡ4A? iA}}A6ik`$}AbЧ)}AbЧ)}AbЧ)}AbЧ)}AbЧ)}AbЧ)}AbЧ)}AbЧ)}5~7~7~7~7~7~7~7>8=@zǠ11G >8=Ac8=Ac8=Ac8=Ac8=Ac8=A.AЇǠ)⛒ŗû Z:zTֵkiLCNFc"."".""IE.2 .qRk/Q/Q/Q/Q/Q" YD!A1"Y@?1Џ~ c@?1Џe{[=wVE\E\E\E\E\E\ERH@ H! O~"Q6uZ\'E\$E\$E\$E/ZzS;^o ?G-Q yԂچiŚ5O+ܷVd :H'ouԁ:Ȥ2L :Ȥ|]5Co| }{Y<>W____h߀7 h߀7~7~ɆoO5ῳ( NL= NGi4w; ͠Nil4f_ogYp>gYp~4O탳}8kڇ}8kڇ}8kڇ}8kڏ~7Mp>ܴ-p>ܲ-p>ܰ7 p~'о|עZ_V}UnՇ[VZЩE{jA]8Sԇ3L}8Sԇ3L}8Sԇ3L}8Sԇ3LzЫzЫzЫ=8OӇ<}8OӇ^8OӇ<}8OӇ<}8OӇ@ooЇs\}L}L}8WՇs\}L}L}8WՇs\}8WՇs\}L}L}8WNՇST}8UbbIwd;sU=]׹tNݻJ2:0Q1Qi}xXهa2Kv^',ڵ د>ÿ>ÿƲ`k0jQKb />/$$>/馪-Gˀ+m¢p>Hµyꃤ~UY1% Z:z|̀-YF@?)kovdL'Ntޖ=JK&( `< ƣ`< 3 `8 `8z`8cT ^,^i0ǚ삖\j rZ;8$8A8A*Rqq448Xnt&@7'@? O~'@? ЯZЯZЯW,ʒ) ~/ 3"m]=ܼ̊l7 Wqp ^i.uX#5;ӓ a 9=U{\g[YWg/Wd wlˊygegl We./B7m۔)iG[ Vz!:r=57OB_ժ֮Y*kDбAz:ex$+, )4nEŪQGdDMK4K4>  ~QG~QG#c0L9-=Y\7Lgw|[O&n8!X[ޓ%;jNAf )fF3(Fb`/| öE`"m8˵f]2}VƋEz[0GQ(sI$gIVw*8 `d x.S)yԂZS ~jO-?ᴀ`#`` 0 u_u_u_u_u_u_u_u_{8t,]fUfKkP34VJXi4='$DӓhzM$* 4BeP P 5&0ה>>Q]#C[Y*xaL_Kuk.oh<3o:YjM;Ӛڳ7 l p\e ږtP2(QYP> |K#!FU 9jcбZX-tG*(` 0lL66Ӏ!<0)D f"P(P(P(P(P(8A?qЏ>BBBBBlO 'ۓI'@?5)ؚlM &[I֤H]e*/JN-/6A;5GRғm9sW_ʾj\0w:NO&x7sh!;!3̆udFBfwo_;caw{$#<#3Hl]X9}Ȭ_Wfú2l\Wfj]ueȌYWft]ueוGkוYuI).D֕.D%[@b[m\.!YƬKc%1$.ɌYW"jZd]YW0 @spp&~$~k8ߪ*;gfD[lk?tH_C:ɿKҋ\bb )}o 73Zd⋌~c Z:zA^d9%-dWo`KõoV7gJWabKsڳ7}+&^Ϳ*;Z׃kJp?UҬ!YKk@s4g}Av@u &xu@F7 (Е$[͕UEwxaua9H>5koY3*._ i<Nd~:"l:;]@tv+Jv! VoC Btv{a8K?^#uؿ }Ak¿aW3k &`›y ᭼x ƃ0)?\N*¯wA}/ AᏊ\|N ¿LuFu#mQ25hÄvC]=]ExƤzzPoHFz#7[ކʌ47s diN DCb0~ܝ*^%|; t>ݥ'1mø7ń%< Oxy7x;7}} oy|x _]Kuu_]O5)VٖtrLY#`m҄gKz2,Ep2+ՓgDY@ٕN;p ;e3FN-+Ьm{`'toNs*#FPkҊ$*J68p3g/pflQKnvMRΤoKmzuY7vMo6צwtt%fQ={)JidJشڄ@UM6{6 {ǵc2=ڦU6i%l ~Y3z"v;.eײ[؝~p)R {s!CND\OAe\=oei {"? 8pRBޜHN$‰\}ADo[ ϒn7I["IO# c<Ƣ$)lQېލM&bDK.E6m^cs.,ms(y s}I6綒/l% 9whs96mI2ʶ/Ʊa+$ᔷ?;|#l9W$2lcEOl]gՆ/))q-q-q-qZ%.%%.%.ZD-cKtk8Ֆ8ݖ8ٖXVm+mKm*Ж8ܖoKUb-q-gKv+٦$2@k!|t/kFi[sSIWipek6u7泽 v{`B(FXujր|6acqt0k%(:d瓭Nv/EdKس%oSuuM'~ESJzHE6M6}̦ >iӧlMs6}Km7bWmM_NK[={-f;Ż$q %CHQ b=6HĶ+` 2 S3ء$>vI\}v?Ij)E S/C|$]') qt~!mKi?Tn vP;R-`\1^[p7Y XSKؠ.`~ۣ+` ؄gX*`{Ilr y)ljV5<7bF{[ (~߷ C6tdvp̢Z5.IPU5^v{'k3ީwi_YG4StЧ83ih W/7OwZnlw`~Sw~I};l'xLo_ZcZ1%wo6"u>z|='Ft빙9lM6ݥ$&XUڸֱ{9وl>lF؞ qpnugG~S?[dͲ5+Xfr۫Ut'kV,]󌽷trݥWRXjkYf-/ܪ~[z-,(<2yBlyHWB^Q>xl ae%5,wBН/YW 'r+a-EK|V]0d|AnCP^ZŅZޖNP&;(]a|DoMW2_VЇLx'NXOPh;R[bJ-C߇m +OҠ-AY[~ wŖE˖+h(?,?O[!Wf%y4CӨ ,]YCQ4GQc?=/z44QtҼ*ej35d9v!|W:j(B:Lb!izgstH.:/]EG5ESWSctk[K(}NӔ,=Oa)/!tH*EmJߥCk,C:$.咓gUǕ|0CP?n7|cVGМo7tK%[,zVw$;ߝ|!n~7+/w_#OOff3Vf7۳Jف҄I*SgHxssIF$ݚ/۾\ЗSl=G]ۣn{tQiR^^l/ ۋU4L&N@&ۋ$p9)Tf*4XtP74f_:*)I#aQð(15/ѕVWZ-VKe7P4[>t(Wc!PT>@CCÞCCϞCжPtE:pCh gc}:4t:44#:^z9pùtѥ9e9Ee*y5& UA|J>!<]ɇao7" 4o7!mo7#ev g*L+7 ;(3UPmFф17#d!og& iDi~c؋ɂLx*;Nx&;Mynu)v!RǫI_~4%FMԫ?Qo~~L}!$zd'&'ل j]6D"{!Op'Ad}' ?Sèĕ!+Z읕% ko]>:~B͟c9_a^R?$(󟄥awie!JXҶr]z:Y^vy;"xP~%We)@d''+AОO, G+uW@ls`չv ˞vmma{ᰉtx+7elw/6_Xoͯ6*k OGM寱?7!U֪Kk]k˭=/X{^cy 7gϰ `/!؁VK&jޡ#Zfcma?QfmkmkmknҖ[+ֵJkQ+-VX+j5֊kE5fruy?'XKZKad6VYXe-a Y9L{d=k}qO }{Hzonwoc۵]n}=mOKӕs q#in},m qػ+ZmkEa{Q^l%Ec{^En{^l/:ۋGtm/^,Xn{bEi{bJQVi{_?_\?IeNڨ6G}4^4'^B1zaI$Hױ F[7oaH_ y/؃K$IOy̋$HoxIȮd6d5d f $I1j.汤uԪ-*\X!F\[Ύ_θyf8 :%-φ0[bK߁X8,XQRs:;goK@=?]fݏ9Yn8S_Bzp fWكFy02%c#t'l̎rv$WD5֊W[=jK՗ ;nq;ĎۡvXvUvl.׎=kInH#Ž;H*K_E+#W1uMIL]SSؘZA6666.T[PmBuId]QYWDF Ѵc-MbC1FӮCըVڋ;{jTٳs l\f0;Yk2()0\ S+ zj;4T(۱gC4FٮDCmڣ6U^t٣^[k$[l. pC9;3|··v?BLDA,-[kKWVl^jmK-c_?gc I> B<Z*ҔҐFlBi[Y^nݙzuWݩQ偵 +x y/&jp][6 +OK`]W``u0\[ K6֘_A WHëX=-/ٽPoVc;K%Li0xCOG/''ӳғe< ߓ;rMKe0#e_s( vN%k5UAdžlY 2L 01C+_,("_allDNWb;l% O)Do(s[ȭdTdLI_NS gqK,ھݐtnM(:tRkRڲӦ3xJ-7ΔN#Ɇi^g %|'e?/*UbP[Q4:n"%&b8P4v)"qX,N犋ŕzqC-RxK'>+W{Z*Y&kp\e\$Ǣ3[ΓGΤ~T^-o;aD>+_˷r\~#TLUզjKj.QS{ijujSG-PGԩlu\]nRPw#IzY-SgKJvu7#zzN zͺ]w>Hb}^ߢwci{cB׫2e 7mIv$nv2co&)f9ش٦3GLs\mn4;ͽaC1oϳ"o{b;3fnwmomzMgT64tM6D.>6=;XZ-n `{׾qX|tMc6mwO*FX󰒖S%7n(_o=PNCY: tH*IV_6ݼ$|+j`i-N*&nW"J4}p&m^ҏB^J}t@6ߕZX}C6fSOH{EO?dceQtkh'A\=RLl{ɺ>c_+2GR;ͷְ%YeK\߲ȃn.]%&gzإכc6s9k.0W5&nfϓ$xUR0+ %0O)fO?٦sZb[ďlm+ֈ5l;)`ۻ݉l;ٝJI:e:$ޥC:?K:W/h//IEՌfFtHg3tvGb:O\:/J:a:ivȟ%:)9# _ FT9ܔ-܎1tҹ 6Si,~srKim̺(O%7jc#t'MW1ƬJR<~Z[P\)ߢr?IGHǞ'ZF!՗S?s7)4ţ4rv)>O34y'1|1?/W-~7?ƟK-_jDbs1Rq+|1QL3Ub8B'NgťS(nw{"rt>ٜ-f6=æ$;tlIzM$k%%m:Wm:Ӧ3JJ&7b>˰SmzgY>[f/FlMl=XQ3TlD6Ȧm-*| άi6= ҈bfbWmzh__d+ȯ((r`&NzKYiJ@k3SY0$_&[YfW!""Ɖ7L؞hs h1簽y|6lnc{̽ly< VP/ >+ė+N|϶?+"VIN^Ajoܱnc{{^^,NsFDΡ# &9?xEt y wy7OӹW|NC+:Eb8ӹ9#M'Y}A610H:gypL:gM<:ɊG3N?oQ!ŦbK#j.Q{iM,#IxY,i~)V)>se!2%gvH.ϕ+1X~jV5O.UKjF6Bv(^||/skxqX'pip:< .yUK5?96,'FontBBox'=>'[-170 -225 1116 931]','ItalicAngle'=>-12,'Ascent'=>931,'Descent'=>-225,'Leading'=>0,'CapHeight'=>718,'XHeight'=>523,'StemV'=>88,'StemH'=>76,'AvgWidth'=>513,'MaxWidth'=>1015,'MissingWidth'=>513); $cw=array(0=>278,1=>278,2=>278,3=>278,4=>278,5=>278,6=>278,7=>278,8=>278,9=>278,10=>278,11=>278,12=>278,13=>278,14=>278,15=>278,16=>278,17=>278,18=>278,19=>278,20=>278,21=>278,22=>278,23=>278,24=>278,25=>278,26=>278,27=>278,28=>278,29=>278,30=>278,31=>278,32=>278,33=>278,34=>355,35=>556,36=>556,37=>889,38=>667,39=>191,40=>333,41=>333,42=>389,43=>584,44=>278,45=>333,46=>278,47=>278,48=>556,49=>556,50=>556,51=>556,52=>556,53=>556,54=>556,55=>556,56=>556,57=>556,58=>278,59=>278,60=>584,61=>584,62=>584,63=>556,64=>1015,65=>667,66=>667,67=>722,68=>722,69=>667,70=>611,71=>778,72=>722,73=>278,74=>500,75=>667,76=>556,77=>833,78=>722,79=>778,80=>667,81=>778,82=>722,83=>667,84=>611,85=>722,86=>667,87=>944,88=>667,89=>667,90=>611,91=>278,92=>278,93=>278,94=>469,95=>556,96=>333,97=>556,98=>556,99=>500,100=>556,101=>556,102=>278,103=>556,104=>556,105=>222,106=>222,107=>500,108=>222,109=>833,110=>556,111=>556,112=>556,113=>556,114=>333,115=>500,116=>278,117=>556,118=>500,119=>722,120=>500,121=>500,122=>500,123=>334,124=>260,125=>334,126=>584,127=>350,128=>556,129=>350,130=>222,131=>556,132=>333,133=>1000,134=>556,135=>556,136=>333,137=>1000,138=>667,139=>333,140=>1000,141=>350,142=>611,143=>350,144=>350,145=>222,146=>222,147=>333,148=>333,149=>350,150=>556,151=>1000,152=>333,153=>1000,154=>500,155=>333,156=>944,157=>350,158=>500,159=>667,160=>278,161=>333,162=>556,163=>556,164=>556,165=>556,166=>260,167=>556,168=>333,169=>737,170=>370,171=>556,172=>584,173=>333,174=>737,175=>333,176=>400,177=>584,178=>333,179=>333,180=>333,181=>556,182=>537,183=>278,184=>333,185=>333,186=>365,187=>556,188=>834,189=>834,190=>834,191=>611,192=>667,193=>667,194=>667,195=>667,196=>667,197=>667,198=>1000,199=>722,200=>667,201=>667,202=>667,203=>667,204=>278,205=>278,206=>278,207=>278,208=>722,209=>722,210=>778,211=>778,212=>778,213=>778,214=>778,215=>584,216=>778,217=>722,218=>722,219=>722,220=>722,221=>667,222=>667,223=>611,224=>556,225=>556,226=>556,227=>556,228=>556,229=>556,230=>889,231=>500,232=>556,233=>556,234=>556,235=>556,236=>278,237=>278,238=>278,239=>278,240=>556,241=>556,242=>556,243=>556,244=>556,245=>556,246=>556,247=>584,248=>611,249=>556,250=>556,251=>556,252=>556,253=>500,254=>556,255=>500); // --- EOF --- PKa\2fonts/freeserifbi.ctg.znuW+AxsԥI'{H۶m۶3+m۶m۶m۶Sykjutwݞsk~ ws)P ?;BEUNyDUTpBTThFUTxAETTdEEUTtCTTlGUT|@%TTbD%UTrBTTjFUTzAeTTfEeUTvCTTnGUT~U@TTaUDUTqUBTTiUFUTyUAUTTeUEUUTuUCT/5H QcD5]Q\5_S "D-VK2B-W+*FSkzQmP[MmWUUWSUP5RUT5SU RRUVSUQuRUUuSUSRUWc` @jFjH6VSՄ@Iji3L5+wN @ja @_3/5@굁7Mjs ֟wjڭjگ::N:Ψ:.꒺ꚺnꖺꞺzz^zިz>~ ,8B0! $B8 "DB41 &ĂB< !$ĐB2H) %ԐB:H #d̐B69 'ܐB> PB1(%$PB9("TPB55&Ԃ_6ԁPCh14 C h 5C3t C 7`0 0  `40`2L0 `6́0X`1, X `5`3l  `7쁽80p 8 4p2\p 6܁px1< x 53| 4hFMN{DtpBԡthFtx!@#:JUG u Sұ8::Nf:NS:N:N3:ά:ήs:έt~]@ԅta]D.KҺ.u]QWҕ*j][uu=]_7 u#X7Mu3\-u+Zmu;^wu'Yw]u7]=u/[}u?_ =XC0=\#(=Zc8=^O$=YOS4=]3,=[s<=_/ "X/K2\+*Zk:^o&Yo[6];.[{>_!}XG1}\')}Zg9}^_%}Y_W5}]7-}[w=}_?#X?O3\/+Zo;^'Y_7]0ʀ4dX7ALP7!LHʄ6aLX΄ߩ`"ޏ[/֣&nb&V`N8&g&Id$&If&IeR4&Ig`2L&bl&ar\&c|&)` B)bb)aJR)cʚr`*JbjajZ&2MS3M42M43M Ҵ2Mۚv`:Nbnaz^c~`AfbafaFQfcƚqf`&IfbifafYfcyfY`EfYbefYaVUfYc֚uf`6Mfbmfav]fc}f9`C9bc9aNS9cΚs漹`.K油bk溹an[涹c{y`Gybgya^Wycޚw`>Obo 5D$dc 08 Cc 0&cL09 ScL0=f 3c̊0; sc̋0?X c,Ű8X Kc,.\~WJ\q z܀qn-v܁;q=~<#xq<'3xy^+⵿oM{xC| >g_K| w?G ~o" M,9R0 N!($RQx@)E(QtA1)Ŧ8Q|J@ )%$QrJA)b*JMi(-g>u!B!B{2R&LY(+e씃rR.My(/T R!*LE(TJR)*Me,T*R%LU*UTjR-jSK>5ԈSjJ݂ͨZR+jMm-ԁ:R'L]+uԃzR/M}/4 LC;&4Ih44Hh2M4 Ih6͡4ZHh1- ZIi u6FDi mmvNEi}A:DctNI:E st.ED ]ktN !ĿA7ݦ;t}z@='szA/7{@}/w5F&fs88Cs8'sN89SsNg)!B!B!5N9gLpV9\p^B\pQ.ŹR\pY.WJ\pUչZ :\q}n 7&ܔqsn-6ܖq{w.ܕqw=>ܗqy!#|q>'3|y_+|u7;|}~?'s~/7{/wahɲYoؠ6 nCؐ6 mذ6 o#؈6lب6ncؘ6mظ6o؄6Mlؤ6MMaST6Mct6`3L6bl6as\6c>o ؂-s\lq[–li[Ɩly[Vle[Vlu[ִ/czm`Fmbfm󼖶mmضq{vlgv3G ^c~`AvbavaGQvcqv`'Ivbivvmعvo؅v]lإv]nWؕv]mصv]o7؍vlحvnw؝vmؽvo؃=lأ=nOؓ=mس:g d/+feo;o؇}lا}n_ؗϬ־d?/fN9p;.ȯ\P!\Hʅva\X΅ws]$EqQ]4p1],qq]<%p ]"%qI]2ܥp)]*ڥqi]:ep]&eqY]6p9].qy]>p]!WqE]1Wܕp%])Wڕqe]9WUp]%WUqU]5Wp5]-긺k울kZkڸk:~zn솸nFnƸn&}d7Mu 7r7s-r-s ҭrݚׯn[{[o춸nv63Pv݁z;r@9ꎹ;N?θ;.R`|]qW\s wrw=w?P?p#8{g{h_W{u @>>>/澻^y<{>>C>>#>>c>t|'}'} ҧi}:g}&gY}?8/s>/ ¾/o[—wom鿹ZƗٖ}omWk+n!UBU}5__rR)/5}-iFofv>!B!?_#B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!Bo[6o㟝;ξIB!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B#~G1~ݫ&~T?O3kgY~y~_E~_e~_WՁ@Y~C7~~wyB!ݿӟuPKa\bMrAAfonts/freemonobi.phpnuW+A97,'FontBBox'=>'[-642 -200 834 800]','ItalicAngle'=>-12,'Ascent'=>800,'Descent'=>-200,'Leading'=>90,'CapHeight'=>583,'XHeight'=>437,'StemV'=>123,'StemH'=>53,'AvgWidth'=>600,'MaxWidth'=>600,'MissingWidth'=>600); $cw=array(0=>0,1=>600,2=>600,3=>600,4=>600,5=>600,6=>600,7=>600,8=>0,9=>600,10=>600,11=>600,12=>600,13=>600,14=>600,15=>600,16=>600,17=>600,18=>600,19=>600,20=>600,21=>600,22=>600,23=>600,24=>600,25=>600,26=>600,27=>600,28=>600,29=>0,30=>600,31=>600,32=>600,33=>600,34=>600,35=>600,36=>600,37=>600,38=>600,39=>600,40=>600,41=>600,42=>600,43=>600,44=>600,45=>600,46=>600,47=>600,48=>600,49=>600,50=>600,51=>600,52=>600,53=>600,54=>600,55=>600,56=>600,57=>600,58=>600,59=>600,60=>600,61=>600,62=>600,63=>600,64=>600,65=>600,66=>600,67=>600,68=>600,69=>600,70=>600,71=>600,72=>600,73=>600,74=>600,75=>600,76=>600,77=>600,78=>600,79=>600,80=>600,81=>600,82=>600,83=>600,84=>600,85=>600,86=>600,87=>600,88=>600,89=>600,90=>600,91=>600,92=>600,93=>600,94=>600,95=>600,96=>600,97=>600,98=>600,99=>600,100=>600,101=>600,102=>600,103=>600,104=>600,105=>600,106=>600,107=>600,108=>600,109=>600,110=>600,111=>600,112=>600,113=>600,114=>600,115=>600,116=>600,117=>600,118=>600,119=>600,120=>600,121=>600,122=>600,123=>600,124=>600,125=>600,126=>600,127=>600,128=>600,129=>600,130=>600,131=>600,132=>600,133=>600,134=>600,135=>600,136=>600,137=>600,138=>600,139=>600,140=>600,141=>600,142=>600,143=>600,144=>600,145=>600,146=>600,147=>600,148=>600,149=>600,150=>600,151=>600,152=>600,153=>600,154=>600,155=>600,156=>600,157=>600,158=>600,159=>600,160=>600,161=>600,162=>600,163=>600,164=>600,165=>600,166=>600,167=>600,168=>600,169=>600,170=>600,171=>600,172=>600,173=>600,174=>600,175=>600,176=>600,177=>600,178=>600,179=>600,180=>600,181=>600,182=>600,183=>600,184=>600,185=>600,186=>600,187=>600,188=>600,189=>600,190=>600,191=>600,192=>600,193=>600,194=>600,195=>600,196=>600,197=>600,198=>600,199=>600,200=>600,201=>600,202=>600,203=>600,204=>600,205=>600,206=>600,207=>600,208=>600,209=>600,210=>600,211=>600,212=>600,213=>600,214=>600,215=>600,216=>600,217=>600,218=>600,219=>600,220=>600,221=>600,222=>600,223=>600,224=>600,225=>600,226=>600,227=>600,228=>600,229=>600,230=>600,231=>600,232=>600,233=>600,234=>600,235=>600,236=>600,237=>600,238=>600,239=>600,240=>600,241=>600,242=>600,243=>600,244=>600,245=>600,246=>600,247=>600,248=>600,249=>600,250=>600,251=>600,252=>600,253=>600,254=>600,255=>600,256=>600,257=>600,258=>600,259=>600,260=>600,261=>600,262=>600,263=>600,264=>600,265=>600,266=>600,267=>600,268=>600,269=>600,270=>600,271=>600,272=>600,273=>600,274=>600,275=>600,276=>600,277=>600,278=>600,279=>600,280=>600,281=>600,282=>600,283=>600,284=>600,285=>600,286=>600,287=>600,288=>600,289=>600,290=>600,291=>600,292=>600,293=>600,294=>600,295=>600,296=>600,297=>600,298=>600,299=>600,300=>600,301=>600,302=>600,303=>600,304=>600,305=>600,306=>600,307=>600,308=>600,309=>600,310=>600,311=>600,312=>600,313=>600,314=>600,315=>600,316=>600,317=>600,318=>600,319=>600,320=>600,321=>600,322=>600,323=>600,324=>600,325=>600,326=>600,327=>600,328=>600,329=>600,330=>600,331=>600,332=>600,333=>600,334=>600,335=>600,336=>600,337=>600,338=>600,339=>600,340=>600,341=>600,342=>600,343=>600,344=>600,345=>600,346=>600,347=>600,348=>600,349=>600,350=>600,351=>600,352=>600,353=>600,354=>600,355=>600,356=>600,357=>600,358=>600,359=>600,360=>600,361=>600,362=>600,363=>600,364=>600,365=>600,366=>600,367=>600,368=>600,369=>600,370=>600,371=>600,372=>600,373=>600,374=>600,375=>600,376=>600,377=>600,378=>600,379=>600,380=>600,381=>600,382=>600,383=>600,384=>600,385=>600,386=>600,387=>600,388=>600,389=>600,390=>600,391=>600,392=>600,393=>600,394=>600,395=>600,396=>600,397=>600,398=>600,399=>600,400=>600,401=>600,402=>600,403=>600,404=>600,405=>600,406=>600,407=>600,408=>600,409=>600,410=>600,411=>600,412=>600,413=>600,414=>600,415=>600,416=>600,417=>600,418=>600,419=>600,420=>600,421=>600,422=>600,423=>600,424=>600,425=>600,426=>600,427=>600,428=>600,429=>600,430=>600,431=>600,432=>600,433=>600,434=>600,435=>600,436=>600,437=>600,438=>600,439=>600,440=>600,441=>600,442=>600,443=>600,444=>600,445=>600,446=>600,447=>600,448=>600,449=>600,450=>600,451=>600,452=>600,453=>600,454=>600,455=>600,456=>600,457=>600,458=>600,459=>600,460=>600,461=>600,462=>600,463=>600,464=>600,465=>600,466=>600,467=>600,468=>600,469=>600,470=>600,471=>600,472=>600,473=>600,474=>600,475=>600,476=>600,477=>600,478=>600,479=>600,480=>600,481=>600,482=>600,483=>600,484=>600,485=>600,486=>600,487=>600,488=>600,489=>600,490=>600,491=>600,492=>600,493=>600,494=>600,495=>600,496=>600,497=>600,498=>600,499=>600,500=>600,501=>600,502=>600,503=>600,504=>600,505=>600,506=>600,507=>600,508=>600,509=>600,510=>600,511=>600,512=>600,513=>600,514=>600,515=>600,516=>600,517=>600,518=>600,519=>600,520=>600,521=>600,522=>600,523=>600,524=>600,525=>600,526=>600,527=>600,528=>600,529=>600,530=>600,531=>600,532=>600,533=>600,534=>600,535=>600,536=>600,537=>600,538=>600,539=>600,540=>600,541=>600,542=>600,543=>600,544=>600,548=>600,549=>600,550=>600,551=>600,552=>600,553=>600,554=>600,555=>600,556=>600,557=>600,558=>600,559=>600,560=>600,561=>600,562=>600,563=>600,567=>600,592=>600,593=>600,594=>600,595=>600,596=>600,598=>600,599=>600,600=>600,601=>600,603=>600,604=>600,607=>600,608=>600,609=>600,613=>600,614=>600,615=>600,616=>600,617=>600,618=>600,619=>600,621=>600,623=>600,624=>600,625=>600,626=>600,627=>600,628=>600,629=>600,633=>600,634=>600,635=>600,636=>600,637=>600,638=>600,639=>600,640=>600,641=>600,642=>600,643=>600,644=>600,645=>600,647=>600,648=>600,649=>600,652=>600,653=>600,654=>600,656=>600,657=>600,658=>600,659=>600,660=>600,661=>600,662=>600,663=>600,664=>600,665=>600,666=>600,667=>600,668=>600,669=>600,670=>600,671=>600,672=>600,673=>600,674=>600,688=>600,689=>600,690=>600,691=>600,692=>600,693=>600,694=>600,695=>600,696=>600,697=>600,698=>600,699=>600,700=>600,701=>600,702=>600,703=>600,704=>600,705=>600,706=>600,707=>600,708=>600,709=>600,710=>600,711=>600,712=>600,713=>600,714=>600,715=>600,716=>600,717=>600,718=>600,719=>600,720=>600,721=>600,722=>600,723=>600,724=>600,725=>600,726=>600,727=>600,728=>600,729=>600,730=>600,731=>600,732=>600,733=>600,734=>600,735=>600,736=>600,737=>600,738=>600,739=>600,740=>600,741=>600,742=>600,743=>600,744=>600,745=>600,746=>600,747=>600,748=>600,749=>600,750=>600,751=>600,752=>600,753=>600,754=>600,755=>600,756=>600,757=>600,758=>600,759=>600,760=>600,761=>600,762=>600,763=>600,764=>600,765=>600,766=>600,767=>600,768=>0,769=>0,770=>0,771=>0,772=>0,773=>0,774=>0,775=>0,776=>0,777=>0,778=>0,779=>0,780=>0,781=>0,782=>0,783=>0,784=>0,785=>0,786=>0,787=>0,788=>0,789=>0,790=>0,791=>0,792=>0,793=>0,794=>0,795=>0,796=>0,797=>0,798=>0,799=>0,800=>0,801=>0,802=>0,803=>0,804=>0,805=>0,806=>0,807=>0,808=>0,809=>0,810=>0,811=>0,812=>0,813=>0,814=>0,815=>0,816=>0,817=>0,818=>0,819=>0,820=>0,821=>0,822=>0,823=>0,824=>0,825=>0,826=>0,827=>0,828=>0,829=>0,830=>0,831=>0,832=>0,833=>0,834=>0,835=>0,836=>0,837=>0,838=>0,839=>0,840=>0,841=>0,843=>0,844=>0,845=>0,848=>0,849=>0,850=>0,851=>0,852=>0,853=>0,854=>0,855=>0,856=>0,857=>0,858=>0,884=>600,885=>600,890=>600,894=>600,900=>600,901=>600,902=>600,903=>600,904=>600,905=>600,906=>600,908=>600,910=>600,911=>600,912=>600,913=>600,914=>600,915=>600,916=>600,917=>600,918=>600,919=>600,920=>600,921=>600,922=>600,923=>600,924=>600,925=>600,926=>600,927=>600,928=>600,929=>600,931=>600,932=>600,933=>600,934=>600,935=>600,936=>600,937=>600,938=>600,939=>600,940=>600,941=>600,942=>600,943=>600,944=>600,945=>600,946=>600,947=>600,948=>600,949=>600,950=>600,951=>600,952=>600,953=>600,954=>600,955=>600,956=>600,957=>600,958=>600,959=>600,960=>600,961=>600,962=>600,963=>600,964=>600,965=>600,966=>600,967=>600,968=>600,969=>600,970=>600,971=>600,972=>600,973=>600,974=>600,976=>600,977=>600,978=>600,979=>600,980=>600,981=>600,982=>600,986=>600,987=>600,988=>600,1008=>600,1009=>600,1012=>600,1013=>600,1024=>600,1025=>600,1026=>600,1027=>600,1028=>600,1029=>600,1030=>600,1031=>600,1032=>600,1033=>600,1034=>600,1035=>600,1036=>600,1037=>600,1038=>600,1039=>600,1040=>600,1041=>600,1042=>600,1043=>600,1044=>600,1045=>600,1046=>600,1047=>600,1048=>600,1049=>600,1050=>600,1051=>600,1052=>600,1053=>600,1054=>600,1055=>600,1056=>600,1057=>600,1058=>600,1059=>600,1060=>600,1061=>600,1062=>600,1063=>600,1064=>600,1065=>600,1066=>600,1067=>600,1068=>600,1069=>600,1070=>600,1071=>600,1072=>600,1073=>600,1074=>600,1075=>600,1076=>600,1077=>600,1078=>600,1079=>600,1080=>600,1081=>600,1082=>600,1083=>600,1084=>600,1085=>600,1086=>600,1087=>600,1088=>600,1089=>600,1090=>600,1091=>600,1092=>600,1093=>600,1094=>600,1095=>600,1096=>600,1097=>600,1098=>600,1099=>600,1100=>600,1101=>600,1102=>600,1103=>600,1104=>600,1105=>600,1106=>600,1107=>600,1108=>600,1109=>600,1110=>600,1111=>600,1112=>600,1113=>600,1114=>600,1115=>600,1116=>600,1117=>600,1118=>600,1119=>600,1136=>600,1137=>600,1138=>600,1156=>0,1157=>0,1158=>0,1162=>600,1163=>600,1164=>600,1165=>600,1166=>600,1167=>600,1168=>600,1169=>600,1170=>600,1171=>600,1172=>600,1173=>600,1174=>600,1175=>600,1176=>600,1177=>600,1178=>600,1179=>600,1180=>600,1181=>600,1182=>600,1183=>600,1184=>600,1185=>600,1186=>600,1187=>600,1188=>600,1189=>600,1190=>600,1191=>600,1192=>600,1193=>600,1194=>600,1195=>600,1196=>600,1197=>600,1198=>600,1199=>600,1200=>600,1201=>600,1202=>600,1203=>600,1204=>600,1205=>600,1206=>600,1207=>600,1208=>600,1209=>600,1210=>600,1211=>600,1212=>600,1213=>600,1214=>600,1215=>600,1216=>600,1217=>600,1218=>600,1219=>600,1220=>600,1221=>600,1222=>600,1223=>600,1224=>600,1225=>600,1226=>600,1227=>600,1228=>600,1229=>600,1230=>600,1231=>600,1232=>600,1233=>600,1234=>600,1235=>600,1236=>600,1237=>600,1238=>600,1239=>600,1240=>600,1241=>600,1242=>600,1243=>600,1244=>600,1245=>600,1246=>600,1247=>600,1248=>600,1249=>600,1250=>600,1251=>600,1252=>600,1253=>600,1254=>600,1255=>600,1256=>600,1257=>600,1258=>600,1259=>600,1260=>600,1261=>600,1262=>600,1263=>600,1264=>600,1265=>600,1266=>600,1267=>600,1268=>600,1269=>600,1270=>600,1271=>600,1272=>600,1273=>600,1296=>600,1297=>600,1298=>600,1299=>600,1306=>600,1307=>600,1308=>600,1309=>600,1310=>600,1311=>600,1456=>0,1457=>0,1458=>0,1459=>0,1460=>0,1461=>0,1462=>0,1463=>0,1464=>0,1465=>0,1467=>0,1468=>0,1469=>0,1470=>0,1471=>0,1472=>600,1473=>0,1474=>0,1475=>600,1476=>0,1488=>600,1489=>600,1490=>600,1491=>600,1492=>600,1493=>600,1494=>600,1495=>600,1496=>600,1497=>600,1498=>600,1499=>600,1500=>600,1501=>600,1502=>600,1503=>600,1504=>600,1505=>600,1506=>600,1507=>600,1508=>600,1509=>600,1510=>600,1511=>600,1512=>600,1513=>600,1514=>600,1520=>600,1521=>600,1522=>600,1523=>600,1524=>600,4304=>600,4305=>600,4306=>600,4307=>600,4308=>600,4309=>600,4310=>600,4311=>600,4312=>600,4313=>600,4314=>600,4315=>600,4316=>600,4317=>600,4318=>600,4319=>600,4320=>600,4321=>600,4322=>600,4323=>600,4324=>600,4325=>600,4326=>600,4327=>600,4328=>600,4329=>600,4330=>600,4331=>600,4332=>600,4333=>600,4334=>600,4335=>600,4336=>600,4337=>600,4338=>600,4339=>600,4340=>600,4341=>600,4345=>600,4347=>600,4348=>600,7680=>600,7681=>600,7682=>600,7683=>600,7684=>600,7685=>600,7686=>600,7687=>600,7688=>600,7689=>600,7690=>600,7691=>600,7692=>600,7693=>600,7694=>600,7695=>600,7696=>600,7697=>600,7698=>600,7699=>600,7700=>600,7701=>600,7702=>600,7703=>600,7704=>600,7705=>600,7706=>600,7707=>600,7708=>600,7709=>600,7710=>600,7711=>600,7712=>600,7713=>600,7714=>600,7715=>600,7716=>600,7717=>600,7718=>600,7719=>600,7720=>600,7721=>600,7722=>600,7723=>600,7724=>600,7725=>600,7726=>600,7727=>600,7728=>600,7729=>600,7730=>600,7731=>600,7732=>600,7733=>600,7734=>600,7735=>600,7736=>600,7737=>600,7738=>600,7739=>600,7740=>600,7741=>600,7742=>600,7743=>600,7744=>600,7745=>600,7746=>600,7747=>600,7748=>600,7749=>600,7750=>600,7751=>600,7752=>600,7753=>600,7754=>600,7755=>600,7756=>600,7757=>600,7758=>600,7759=>600,7760=>600,7761=>600,7762=>600,7763=>600,7764=>600,7765=>600,7766=>600,7767=>600,7768=>600,7769=>600,7770=>600,7771=>600,7772=>600,7773=>600,7774=>600,7775=>600,7776=>600,7777=>600,7778=>600,7779=>600,7780=>600,7781=>600,7782=>600,7783=>600,7784=>600,7785=>600,7786=>600,7787=>600,7788=>600,7789=>600,7790=>600,7791=>600,7792=>600,7793=>600,7794=>600,7795=>600,7796=>600,7797=>600,7798=>600,7799=>600,7800=>600,7801=>600,7802=>600,7803=>600,7804=>600,7805=>600,7806=>600,7807=>600,7808=>600,7809=>600,7810=>600,7811=>600,7812=>600,7813=>600,7814=>600,7815=>600,7816=>600,7817=>600,7818=>600,7819=>600,7820=>600,7821=>600,7822=>600,7823=>600,7824=>600,7825=>600,7826=>600,7827=>600,7828=>600,7829=>600,7830=>600,7831=>600,7832=>600,7833=>600,7834=>600,7835=>600,7840=>600,7841=>600,7842=>600,7843=>600,7844=>600,7845=>600,7846=>600,7847=>600,7848=>600,7849=>600,7850=>600,7851=>600,7852=>600,7853=>600,7854=>600,7855=>600,7856=>600,7857=>600,7858=>600,7859=>600,7860=>600,7861=>600,7862=>600,7863=>600,7864=>600,7865=>600,7866=>600,7867=>600,7868=>600,7869=>600,7870=>600,7871=>600,7872=>600,7873=>600,7874=>600,7875=>600,7876=>600,7877=>600,7878=>600,7879=>600,7880=>600,7881=>600,7882=>600,7883=>600,7884=>600,7885=>600,7886=>600,7887=>600,7888=>600,7889=>600,7890=>600,7891=>600,7892=>600,7893=>600,7894=>600,7895=>600,7896=>600,7897=>600,7898=>600,7899=>600,7900=>600,7901=>600,7902=>600,7903=>600,7904=>600,7905=>600,7906=>600,7907=>600,7908=>600,7909=>600,7910=>600,7911=>600,7912=>600,7913=>600,7914=>600,7915=>600,7916=>600,7917=>600,7918=>600,7919=>600,7920=>600,7921=>600,7922=>600,7923=>600,7924=>600,7925=>600,7926=>600,7927=>600,7928=>600,7929=>600,8192=>600,8193=>600,8194=>600,8195=>600,8196=>600,8197=>600,8198=>600,8199=>600,8200=>600,8201=>600,8202=>600,8203=>600,8204=>0,8205=>0,8206=>0,8207=>0,8208=>600,8209=>600,8210=>600,8211=>600,8212=>600,8213=>600,8214=>600,8215=>600,8216=>600,8217=>600,8218=>600,8219=>600,8220=>600,8221=>600,8222=>600,8223=>600,8224=>600,8225=>600,8226=>600,8227=>600,8228=>600,8229=>600,8230=>600,8231=>600,8232=>600,8233=>600,8234=>600,8235=>600,8236=>600,8237=>600,8238=>600,8239=>600,8240=>600,8241=>600,8242=>600,8243=>600,8244=>600,8245=>600,8246=>600,8247=>600,8248=>600,8249=>600,8250=>600,8251=>600,8252=>600,8253=>600,8254=>600,8255=>600,8256=>600,8257=>600,8258=>600,8259=>600,8260=>600,8261=>600,8262=>600,8263=>600,8264=>600,8265=>600,8266=>600,8267=>600,8268=>600,8269=>600,8270=>600,8271=>600,8272=>600,8273=>600,8274=>600,8275=>600,8276=>600,8277=>600,8278=>600,8279=>600,8280=>600,8281=>600,8282=>600,8283=>600,8284=>600,8285=>600,8286=>600,8287=>600,8288=>600,8289=>600,8290=>600,8291=>600,8292=>600,8304=>600,8305=>600,8308=>600,8309=>600,8310=>600,8311=>600,8312=>600,8313=>600,8314=>600,8315=>600,8316=>600,8317=>600,8318=>600,8319=>600,8320=>600,8321=>600,8322=>600,8323=>600,8324=>600,8325=>600,8326=>600,8327=>600,8328=>600,8329=>600,8330=>600,8331=>600,8332=>600,8333=>600,8334=>600,8336=>600,8337=>600,8338=>600,8339=>600,8340=>600,8362=>600,8364=>600,8373=>600,8448=>600,8449=>600,8451=>600,8453=>600,8454=>600,8455=>600,8457=>600,8462=>600,8465=>600,8466=>600,8467=>600,8470=>600,8472=>600,8476=>600,8480=>600,8481=>600,8482=>600,8486=>600,8487=>600,8489=>600,8490=>600,8491=>600,8494=>600,8498=>600,8501=>600,8502=>600,8503=>600,8504=>600,8506=>600,8507=>600,8513=>600,8514=>600,8515=>600,8516=>600,8523=>600,8525=>600,8526=>600,8531=>600,8532=>600,8533=>600,8534=>600,8535=>600,8536=>600,8537=>600,8538=>600,8539=>600,8540=>600,8541=>600,8542=>600,8543=>600,8544=>600,8545=>600,8546=>600,8547=>600,8548=>600,8549=>600,8550=>600,8553=>600,8556=>600,8557=>600,8558=>600,8559=>600,8560=>600,8564=>600,8569=>600,8572=>600,8573=>600,8574=>600,8575=>600,8592=>600,8593=>600,8594=>600,8595=>600,8596=>600,8704=>600,8706=>600,8707=>600,8709=>600,8710=>600,8711=>600,8712=>600,8713=>600,8714=>600,8715=>600,8716=>600,8717=>600,8719=>600,8720=>600,8721=>600,8722=>600,8723=>600,8725=>600,8727=>600,8729=>600,8730=>600,8731=>600,8732=>600,8733=>600,8734=>600,8756=>600,8800=>600,8801=>600,8804=>600,8805=>600,9251=>600,9674=>600,9824=>600,9825=>600,9826=>600,9827=>600,9828=>600,9829=>600,9830=>600,9831=>600,9833=>600,9834=>600,9835=>600,9836=>600,9837=>600,9838=>600,9839=>600,11799=>600,42888=>600,42889=>600,42890=>600,42891=>600,42892=>600,64256=>600,64257=>600,64258=>600,64285=>600,64287=>600,64288=>600,64298=>600,64299=>600,64300=>600,64301=>600,64302=>600,64303=>600,64304=>600,64305=>600,64306=>600,64307=>600,64308=>600,64309=>600,64310=>600,64312=>600,64313=>600,64314=>600,64315=>600,64316=>600,64318=>600,64320=>600,64321=>600,64323=>600,64324=>600,64326=>600,64327=>600,64328=>600,64329=>600,64330=>600,64331=>600,64332=>600,64333=>600,64334=>600,64335=>600,65533=>600,65535=>600); // --- EOF --- PKa\"bttfonts/freemonobi.znuW+Axܽy`E8^s2\$!$LBIH8B!rKEDDDĈʺ""*"" ,EUdYI&Qw?T^ JօAoV?`H O4#rŻkBD= \:rTq+!rU/12sγ GooFHoY3M rBIp=bBv dFl8EP?/6gB?SLjilp:S'[y3&Ϝզ}:mF*a gw .9`hlo9lmx1U@CF3??&"AhszK4/EXVQ-b8'2s 0 @`?1! A?xcZ;9y)Qo (\|Eţ%.D%!$ r0.j9-eBfd?iJ>`F&Q3:-j!8^Ŷ!R&.t~Q@ a&*y*F;*"9c`0,`_~dp<d)f}[Ōa͎]܆v[ge` |RX-NV6 Xc/YZz;R 7o'y \"9+T(#W[\9۟4cK o|?X_d*?XwUvB3ۺVr`kfZ-5=gov;?6?ޱ-bm.`~tKHF,1$X,/@ݿH'1qX$mGMc!dM9`$k Hoհr`%=|sdNfi!/%3KX^a f>/FЁLa۶m_do?v2y4ّ*٫ý~Iv?^@:@}ߣ 9 '{W4m@q>=1g$+7KC/=KK+Ji,c3:o$ G2z49''H&/`e4`I4bha<4 9K$wxwuyʧOCl -hSGJt7-W{&wXy-p0NQAvW2c#lg~%COBO8NOyM/Ўe?BĎO~yPІЃ`2`pl'V8d6?|P#" An`!x,KVOhp԰}`i-~=@"oP|,0f{ýgh^f +$$V@26 <81q)+ۂd1#б%7`>NǓ@lem[#0#`f$s1Ѻac߮du,pcm?չf hHƇmcUlqOcvL,dgb>ٗq€/g &i5V&c}Yy9x.Bczn 5<< Y0}\!Xʻd| 6+L8n\>~$)˹ ll=?!dc)I2l dǾ<?Y>}@-;& r`+]G^`CAF[էa9%:5\@^]Ƕ|`?jX- h \ZAoַW^N2uZ#+U-֕6` @%~V6U fh_?ﵿWvX5j+~E/0@/BSh $~Dnt/It Z aU]DQ=Aѳ RT&墷< %h5rF 9㿀COVԁы(؆rP){%;He4=A1CFpC炯M/Btpmh*G%ߣs*B+PĔZhiL_F(:.* R_OP9"P?"QJ)>B3@) w` R׋9]_AQ.Aj#|%Й$(_L A{`&O>Z2$[ԍA (nA;>:]G 2*8_Qɤ?40@2%-qPvlҟ@#㰠g^Rp[ )$PŇ&2Ud YG6Svar)$)r,tqVp^|9ù7'8t2/<93:'/ MLLL;ML 3,0EfYeVfivsy<\f`l441?j^gAEh[b$[--6ccjʊ{{{2e|}?^e irM%O+5d7g83h p$&6q;K]< OwwSr8g@-&d44a9BHrd2;4G) `<8j9o^ELs,4G {82sKr+ϿM?__oc!|?گ+}~/ɾI89Wg]4c?1ES{~_={{型={s˞O{NPχ=絞ܞ재̞A==o~A.V_ ^>&2"<|DxYx) a!Яx#WDyV)@!P8@B|bi)RwWOToԂӃG1?-mP4x87A(KxGd} (| 0Y(m.x< aՆTeU BC!kCO7գqzboF/A+Uډv!~FPMށXCAh:j6 ċhjעh#o~,K8z bx"`R -EMh1xg =[[{?}Hd?-u6'^{%ĀF Ad#J?x!Ƒ d#*dYn$*.UӍ9n:-1&qn"t;M b1vsb&Mݹܚnn ~l5ϭW@}j湫 gjj?^6Xt#yFr{Q!12)=>;4ƴr1usìnWwt5Alug0N)S|]Wm2 6MML>!6uv6ZL]Vz8+;0;3"z3jYg:b5Xm ;T=|MTwCì]VSװ.k#~y7< 2[ t ~TLt=Vltʫ3u"-KߕJQ[t<|ney{Mi|EK X |łKv+7 bU͛x6%hJ8XT R:cqtsMCpn|BtlM8wȩ`{c*SgD CFd=J6RtDz"##GG6E5 rCaaaa39U-fTˌ;{ϙL',20m0m3u3̋ͫ{gW,BKjeYly׊VfMfZXX7YwX߶immlmm{lmlglWl7lw mn{ӎ4b*Fv~1 }gS< q)\&W+U*wչ&uqn[v=lw{}}?&$Fc^ј1c9+F&niqs]_>~k}ǟ=N= %Ip#n"?QhHt%&%Ny{nx~NKZ>t($ytrC)-kRzx?KSmOOMߚ~?6ccwRt93"k9;!dmB܄ 'c‰ W&LL8abăNL;ɮՓO9䫭V}kYֆ֙ [mҺ[}SBȦN)2})˦qʶ)rbʙ6YVV6mQ[WۺMmۺδ]n֮h7G{3/o_۾}_v::<;wqTͩܩySKN:격knmN=8 SNtj;mIs;tqggɦM+V>nڤi3-bںimvbiLO;hK~w9`FɌu3g͘9LL̸3 gVά:sf}ߞoumO7?wvmڹk6<#{f3g/_ٲg7<{sCN>c6x={ȘMٛm:Gxpbs/D腮ֽ-'^}Ū^ܷ|_J{iKg%l[ڗ-/ǽr˕/׾rs_/_x˷Mۣ'o^z{훷~v{+1RJ+u{WνruGɎ;nZjɫUֽg;;v.Ο_Zk}mkg_K+yWѮ]vm޵w=w mݺ{~#7ֿqݮ$߬|sٛ޼ǵuOkoV[]o|[}w^?-өw}wϟ^/l_K_6{;~?|g>Hul`op烛?r@qt @ځL:Cɇ>\փ=8 v\p੃?hG?:w(PCZ:ЪCm?C9tЍCw;\v/^ُ{d):RuHۑGYsdӑG>rȉ#gyѐn$OJ>Ould'~r蓓\'cӏ-;>~> ;:䎓ouԳggyٞйv{'~~m?x3/qp!BՅ /9zlڿ/^lڋ{.wqIutu)RK.Myi%V]pe]]}Jӕ+'&ߜ?6^-~|ճW/_vջߒ߆}+o}{Z5ϵkeתg?\~_u:]wg7} ~(a{?|Ù.p?wStSu欛nv<{ſ/-[o]~<۩n߮]w{ݾ秹?r'N睍wܹ4g?'\oK/k9ͻQwݝywmwkޭ{a3ޯp{s޿u A܃*?h}0l|k=PC"Af=InmOʣdуwE̺uȅHPqVKJWQ)ő:'|z$&#퇤jCD*}MJ. ([Pمʢ"*M@K (2s'_ v<kز 8H)>!,}[R.&SC&72{ ovdejLB˥B CB ̌{̨GEmCH3ط?^-u_M!TAj}RLV_"hHnUR bZ%Rd'`- ~ѡ Gvq)UF"&{bMXizKrF}``~d0N;;I3D$)%yg˘zV,w=?~FK:OlQN72RYS-L:q?!Yr6I-g4"M,k(NEbpc8v !kJ)z^!%3ycG(S jRUO>Ti1E-/Tkd04F^3Z SA$ Rh0COuyz5#f*ZV5ɮ IF6)ñP ,$~x,N\mi6ipN|K5ҁi7{Alv-Bprnʈ+-ΐd{Qt'Q1xڷ(Jt[͏G18}%1\)C6\ԙ1%ubWnv:B!Os{KlN>(iIKϐ-1.vLJp$$7gA& $YHAd$gsXc ,K!#a# AE^t%W{&, >RWXg?(IAC9zFBK#w~rA'ր6s%F7:D#!M'Rby7xi^bl39Aqt'4nȬj\ӓZN)I625."xɪ& +ʶKg'̊1:2]ř29 x^#4wV&-gʽHtÔ Gwz@C2D1@_} Yǖfj%ユNa=8iKĥa'Tr1H&H%RPw"}r'$_\,Cz:k"LP2AAl%x 'D+$ʶ-ֿBN"ncڼLd!o5 rb.O){RPZhHtֻѐ%(%"{]25! Bᄵ4 xYD VNO8V>X^;-$ `lQEiQ]-J *%V׃&$lw09tl3982(j 8*WDAaBc9 sXG cHHYREfӿTP˔[҆;¹rcAZ,[]԰)ƹAQyĸWQ/ ˌ'!(FdǢqZq+E{bE߰Q|ksӐPȸ2h Dmt6Q("0C:dq"v&Ves+FuẗAy *w-xcz~j[UL´9|Yx (:2='nrZbxbZu1$a,7vL]i,,VSLE.ϐQP:J-uLPcWZm E"nST92 euT$Yb:*:^q.'(p<3D}r#{<|1L${soRifFddn!8҈ 2 #Us>WՍ@k%IRJ|@B! ULSLd*>_eYҵ¿fKòEu@7@G$! W X!` b?BBP3i@TZ+=yJ:>xt#b:I`Ld I0}d~xS1Xu6]z"h=l%ɖl8JKA.Em΅v'^MxF06Wzh䤪Ya2h2'^Iz\)%s .o0 ScH,W0n6Aօ3"UoX].zL@5gjK&Q@ŕK)3υ09LMZ'րlפ߃*V`F0Aa|cu߁X^V'g@\aF1N 'Y ΢EʼnUmv}dQSDcK1߻组6k"Z~N5k%=nXÉ߉r:"HAcbSwvtFըӂP:}D\tMذ~DH4I%b T{"5zi96aסN A-/fY)5aYV-- -Wl=SW;BGlT #523HWz\&0J{ XTg9-#>`}Ijۃ9zGFmѓPmOLLIEA B!}J F1Y>8j_U^ >̝Ws&\582kVƨ'`{庽JQh^4)1zvlz"oorqұ0a+VQ2xc[_Dsg5߯AoBG-.~m~kc_3"ۚM+XQCH[ií _lFҶ+6 wd?Y<.Il5%gud.oDy ztJȰV&q2l!m4&-xQmߞ6.%Ò%0kJ߷$>DQ-e3ϓ`~BXTlN)UYa|635c5hXr ZaM_02Mds(=@\,R̴,U$W" ڢ*W.Q\Z+S\$UJ!AF )!2B) Qcz-",)`Vyكq#_b(ܱalszF$FHU9cJ5\/'Ί}Ua0ܬT2 &E_cSjf hC~>&2Fl'D3q3@ 1GmTl0;P7F' Ћ`\ +*h5h+1l nq&65ξ}on _% ƱZ GRFfܒӷku ^Q|^%YT5a<0P~Cٓ`{n$qv=׆A JàpMCJ-"KH*!0Ĭ5Ma2LҘ92 4pґRDmQ&z25 ~b=V.NX Aų /G\ͥ-Qt54lAZ}'e| .Iufҥ(hW9(u` {!!x}/̓7mBBpPixNݫQPYwWQRO$s!dǾbM1fO<&K}cdWJ&SyZBO))N(0& I҈)tAIu$b'TJvjiVJU@ ۽7YG9M<$.ɘ t&^!F 0^U`^`tHc<yB_6@#h*k\XT-&M O+nt,C8)=`R(HKy<^%SFٔ FL:EѻR=},t}C3F!U[2 DžGT^CH裢(֖`MJ*$VD>}40qX"F\ b<iȟA} ?Ph@A8W#~GperBB:\ڈP ke2 4 :Z2y*qB2*kʈ83&/*QJX>= )58zS{aoE}tÉ)'rdT Fmv!5$RoίIrRBEA-";N)MȔBÖ0OQBIdF:Hz{Ib+S=+W%iqݤQb#,I#V˕S)JbUTءnS07$UJZAK ~TkhMP[lڬ!CcL1E1fO;d*]$I퀢j2 dID|>R9x hNV)m4qt!,Q5$\dH. 5mxEJ,(%r+W&m+^ w/ ;h8.E7vMnvۅ[/U1魋DZgYHf!?|~o<<^e ;Gp,[S&W`|2B%%T*zr]AR*]\BےtJ}^ xOEK`qh:DZ%+ZoʴpQ{~5L!|Nh$\aS[57[+P$IyCrQ8!EJԢ0J(&Gs&krI^o/%ɑZ_ s(?+K7CjI7-)2Po[*w}dZO H]H$UjUqVqT¥$:AL>/>ThN#xًu4vVFb p8\aTGU Oϭ ~W( JVEѾxA&]zGwX`!Zh>E`?6 vo/$W_ T`I׹IM!кXo0k$5IE"c=1v$H\'hʦ+03 w@\ImV/WLx-lAeֈr cר,ތj98c"oΑa3F.:/n 1!HX0& ]@bӿ48(H؏"-(x]vl:F z供9+ .{^)K<\I4j\c$5¦ܗ?6ZN)ėG+W ${B+H>3Gu*\L(8͉~}XNp;uqAYR+0G*-]I.޽ s}d.; OA<{ԖSIp!`PLsE|lҷw>c3*|7g BF:8f1$O2WzF/'KS~/4ċ?u`?%3B6} pֆS^ۤ:p,Y݂C"=k%I(hA.yrZ8QFm6MhXi(_޻ee#WzUb }Hj*O)ES 0>ӈ]Oٗ7%30ߜEx{1g[5*K:)vaRyuc]ϲ8(0{G{Ct6Ï4&5ZseG-!dViz޷znhoK֑`|(<K=AEKJrg QWgC^a6WUa(~.J~1NNXH{ddeE>Y_Ne;_ <5c ͅ,'.c~.$eQH,EQ eBF3⋉ZJ*d'$*v">՘&NZ_^HC~Na<楗")efnV]a*C~%MD=vJbmC@ ҇wOI0$T`w^xnn2Cyc҂VNp)-Z ~gf 7HW쿵/OJczAh%M!Mޭ6!McS|;E=N 6ddX vf if޲2[$ɩ2"NM%YƉE[0"cJ-رrጒryȴ^Tk] 4JbV}j'jrnnŰ!ii㴅 .kL$YjAȲ  -_C)b{y,< 2YwP-s|f%Y aes>dWRT)oaA`,>8sp]2ҨIqJO\uI<Ҧf&QyϮ tj/ѮKiiT5I%N ig:nPHVXA:[xS5n:~ىKӋdT)>ӨF,+F7?UHtR'&i$COU̶&ʬS|]PZ;%5yʬN sD7"7Һ1 Y* 3OF0~+֍Buֵ <c321?Wx B?}-;OL̃@ą }k'^![;Z=F3Y)^(V$o;VXQ CL9~\CrbuA{$uu+$[LIhLȘΤ&$^'ro5|'zR&̀J'۞/ύֿC Rh^eo8ozV~GcxHCMJqR>Er7#c0[H IԜ?ef]E=-Wb VY0G26bD;]x3& g>&i&N6 .oQ[8{jJN'MH{WڊXϱ,kfV)=Ɣw&C[=֓r;ΨFr<>>!?4J96TrL&@b )fO ǯd=uV.EOu=ML2[x.~m-0>JpwNZlFU Nj7~) _j<~#c5PęLgtV;+5Cu3nB-]\gq+d\lV2n3f>xpv2]6ᣕA%5Q80D]y^w㗛x.a#'\:d=z͂1AM8gb;00wTr{dh HYħuTp%zW~܋٩8/kQgCB;؊V$dݟ'*/Xzϑ.T &Iy|4Jcl'Gdp}4WC>*G?R~ڟQ׀&#qYj~~S1fY*whb8QtǹNWo^xo|$1 p0?(v74yD=ZqU&;M'l {RJ-`S xz9=9>G'.c Cp&6NHȄ' otio4w؝q)hfd{1MlK뉽_9bJ=i'a512\Q2{\{}n Qɀfw=MqEPL#K{wwzL筧6ym݂ -͖puW+4HUVn1 ˻D3oؘ]phYŨ-eʙ;wL&l /Xg9%>ﰱ&<;7q"5^ĥ[:4.bk~Sd-㖔x>Zs+k V)/h"18jO".eo3I#Ӥ#f[;X'kUI[JVgkgh2$ԣd7^X\=-=h  GMցHes!8U!ددs$S{Bm%*WhoB v{6C EEXcVyײ1>߇iI3W>x26ΑstLqLANbeBJJP#س M8gzU$k=WrbB,9E__@}oyd\t2O_7Y'?xLdE@ ,q:G3|O£KQC1ecQqGu,e{.MY_yS3 o/-~铩)nOfC(ϣq渁qWZGYbz̊B=]w{SHhqfjE/G#ukW4gd4g9v/)b{7,;W.>;'4yr:Yc[=Mt|;H\iz9z*glӋ[{oJ#1Og`2 꾿dޕG^3 UA8>s0@\R\(%pV)I N9sndƃ}H9ʶ¶rS[GX)y3*RZ[gTJ}#;dQlbWT56US__\JrLz=I_0Uc@ i97 k2 x~SׂTz 4/ڸRkD!@ /ˬ/hj=n31~ݾG.0օBm1UrZN쮂FO̹{nG@7Idpx I47-TD3n lEsu~--uw6n5+Tb)Q;)3zс5kfW]\ NlzjÅux\}Tkmj#_?Nj!·nF x;ל|K(BAVRΥt|pc͍X "yØzR1v`d/37S!nK^(WDQ66>=B4"z)Y4f3J#5g JT`7mh "/KIfіT9A[YYut25?y3P,pF}D`#ŠkJxg^.UoyI3$h.QA, sGBJhtrT=;}\ݫ#Quy˶zcW<x@vذ?vDp\.P 6$&_N[gDb"R%@5m6p|1;~t ~6&yCOnʼnCbm9Y2^QUz'iDX |DŰg CEk/~8Ѹ^&W~Y;"_Ӹ|hmp8edлu.FɴD@VaԌR=x񝙍DpIg{:0xO>iƵ Orem:$cD#X'hUGmbMFb0_ cú/PZ?ZT[9Gb={<7NGyٺ#[ fJb5Ch<̺95=ҵ=9齑H0`M"_ '0cVP%eR0-g4) )f!),PFuaț r2䭗ls^wG>0̡@VyW).Ž^;`\VURE\bNN::|}uPy \?LXe{}2% X2 ֟v&Y\!=Mr1M {7|?þPcdh/fq;yVʶ=K/ vNGF-}? `Kdrr~),<ǰx{زY;qDP&G@>g@AFoƋy=}Kx|B5X e  )jP&hv0 f=2a , 1n}361=2 Ym(ZE{NgwsNfKxhBP3р`KQ>tkhǚ#GAJS&d 6e{*ufC1* IS?2` ]Hraoo{+{՜_6UqUjrD]\҈ot_Dɋ֣WSivx~qH 3ZApcq.џALc2nuUw&@Vc7O'>'6zS̗L $G}47>(R9i ALkE iMv&T:>ƻRk<1?ȠOzE3¡B`Xj`kYG68D \-s4^{:11.= 4RX,uU7G@bQGq$M7ڢwNt"_JcGoZ7':}5Fz+ƶ]8x]WZMb fLj49ݻzoʘiEXzm <FZ9ջNhf[)̞/XXf'sx^+"RP}k܍>}G:C@!hG& D5fBYЩm 'i6T9k yåG_hm{Rrd=3 kophɷUoWAf;x|AcC_^;=J=I(2)9]1jZǼ拄cCZ5p9V`[2ў.>5[bFjg]SC]Gp{v#%[HF#=UMaKYVʩǩ(|$rcx4sZmٓYҙZ<\3[ ®HnwCVdK>2QT9&mZٟ>Y%D+K%Y鯯û76۳j4Eڅ6] 8w]I׼v/op$71) \s,;53Mθ/<@dFe"k_NQ>^d۰sPv]ѕYkIYڰs@_"Ss'ec^HQ ]L`YOⰈ8u*u RDc \l?Ȧ(Lz|+tO=S y% }nuWȖ Cp.3(dHE"E 'b9 c' F[GSd#H򋟆)x"Ӷ(0!AZalZ>]'PJ>E3w%$,Biy1؀Sll1}Jjؿ:y. ? |G41S_(GƔBh,Qrtq-.D 0Jޙ.wbpcbqDCbWA[Qo3дRd-V1 <`N+ÚYx).4锊?.AVkĵ`us)jL`2,15KgْT*z%{ K..9g[ӛ/@{}m\ALzpx m0XЖֽ 3'۶b3ӌ )'WhLMxbNFu+~($D9ĥyATT c'B[bh6hRʀ'яb_f[gx͇ہvp3\o@Qg\ۂ__&?EfwFh&q\-5\ߨVZN'|.dsʑ^Õmtu"k'i?F8s$M.^™qx0:p\ỤZAJIFbm f8wzl9,/9KSο afG:lF##y'@45ZA.0M۽MI;V{}Ow,ba uJЙf'Esf/ɜ_gĖo{S%d\h -k鞻Vr@Ǥ.an_<)@GmhWGHXwZsyC)ApO5Z}NmUA0&ڌz#)蒀&]2Ew>"2 Ddb3ʾ(N`ex?9] 瑌F hu&qN 0#.x؏%c0sFoIzowDF>P{155fԣ}~8 3( [\!Ŝ&O)5~O4pIVX[i|TFϹp`G dhϖ;cYo\#Q PnX+"GбAGMw p#(i޹ [x}8<V.QrudxD*{}&qYΪ'V>p;'B#$d12/k|2e܉GNJoiL2Ҭq{'o Gx57:|2I Y]ATI )O}o nՍѾ*6qVgTo>75Ɛ{~xߵTM{fvWI'69a9T_P1xi~.鋁SɡH s1DIm.)]ۿ|hUJUH[̈O5wT2 ?=%,ײz_2ARX` Y"~hvC@ǕxЦ?8!W!X8p@ 4נUP+X}63/ӺT`&Q/OnHҌ[('j;n}NPxNFNY9%.`M~iJ|藔oaoG_"V~bKzj_F6׋ g0Z~QSi|j9?r?R_jq+W#ߒ{[J|_֛ScHOco^ .x%i<xYǹnELY;nrWZ ֊[ 껗σ!b1m{McmSֈլLcqo.}JURys,=jCtW*{Ԋ7 )켣pI|^0VÇSt:iD-oW;"O&yTYYKL_@plZqʎSWVKO->ooAn:+!亹vTn=sA-<F$FJ5&Z#J9>N!O6=AxNä97k|oɘ=spJg"y!(gN7aCP}䰬)hКt;Vi-YQ綤13&`r;Pjy[y'bNݡ- axVPR N0Ө ݢuͶk#*DA6KJp҆Yq-NeGWY5):Ge~A]@zrA‘ؕm<P 5:*nrlkǶ& d { tpgae*/l_h:mְmÇ_{jЋͩ@WZ> w·^cFw!8Y˜+wsو\q6'Xb=LtF3+V'gx 9ކ#r9E) o\mKwx+ʄCCgZ%g٢x?,PcK_[[4~xFRTN1/r ?ۓ3r}>Һ@~&PT~/o ulS~xS_ ?A$oLnXVR/Y=TAS_Goկ)tl~+~xH7/s_K.oVU:Y_dI{7k95p}GC@[_~؃oH>{:]Ŧ\v(I)仂KZ<F"-hv}h̴v)^5*_rδr1-GK+Wͭ`ZַvjedѹvHAEn9dݶ2a~Y(p32޼!1(?% yB%kܞs)fȩy{=p(Ӈ'N-9og~<D4<͛OX#nJ{F:gk=(_X 6gkMIa]( fwRf:[F|33Ҟ}pgvԞg4QY7'P"Y7kIW_MBI匈Q*KPnv 4A*Cs-ܼvw|uȷZ5bmMw.,\7;0WUP idMW ޱ&lQ_5PJ\g#z˘1]9FsIEVdзbӝ\J?jڼy`o`I]f/\9-w_EkثiWeC)b> ~,r_x"gGxѸoxm<gCd&X7Տkgwd_؋GbGNW弘! c W =ea2G;gFB{Z0Mr6aXRY3:!=rъeLcLHd-8ƝϞѵ9B.O͡QhU7q|[F[bP]3)HӬ`l۟ ^ ;ggfj0, _u4K8*ZlsgIcQK'G2a}]c9`)t蚼m;ss@ jNY-==wXpyWbO=J(ZY0;LMឍ5Er l"=b)t:TK4`X_dhG-|&8ca9.ያ{^Hɘ Ok1B[Ta?9Χ\rVT5Qd\n<gƿT!ƌ}onZ`)%d:ª]Ïtdlm*c d#ްpu_2W wZÓFc4:g$Iğȵڽ |ɕna7J,ˤ8bq )jc!H-!˅kվ8|ͩ)SghUE\TiqܗbhF̬>X'X_)E߂j 8cvc۫Yw'rm6*̬3&W `Zt]lt=# 'mv|D+gpǜVb:T (s3C}ugb}qOh AfmOUTl5plm u>w "󜃦-.A92;Yƻެ5p+0 (Sygd2H6PS]8sZCd?2s<+9lM}iuwG_pute9,h@$û>`vtY#\g6m^y_ x9x/xD}Wj*@E,][2x1c'Sx)'10KN5鿆1#gGW^~<k @R< E-`?ӫ@Ue įxRk ʊHH,Yz%U;(_Nn,ܐLjShfc-M`>Yw"lѰ7 D"͍撾w~MF(ݤK]9CsN:ZZi·9B< ՜>p/[XT+[FH-\'!9WP} hov9Y H 4J0C;xcHn%'l:A6Hצ481HM=bRpBk n< eo6tߡKwplŖ.7x:b국1nVI:!)'O/VOmu nPޣ[:h^qrdUh&IoGs`O{&o{h'PAxm?it #d+n&^{H7^͝dc͞9lf} - gv ͏l-@5yʼUQ,<ZMg/ۈƘUJa&[)k4wZDZK_E}s?zv[{l+Y,w,"'|yCj$7 hbdtǖn o 8iZoΒb[c~iM] BhC}#l18Z&Kin!6.qS4UHYcσaO/A}Pӷ +Np N0㲄щ̸ܸAEc`%y}a B:&1.-R&e/Wp)ۿ ϶pB.WE[;甥t.J(=: z >.N<wwњe7gqT'eeGe{Mm0R~vF?cIEʉ7Q|JA;lE]%X>m%ǭk=¦<" bb.z GiGc$GZBWxMNiڞ0aIx0Kr':Ƽ6[4Yhal,yM8h!i~¹K+w\[@40sXʍ0I@G@< z-Ng"0{™1?JZY=c0H>H\x-S;DOӒ=.iӠd(*iyM}q+TRT`Am6>Dc'lEҵYJYF',  ^{DDT>^w[y 8 zgbrl2Έ-'Z~?̠198Oշ )|}dVRNOf-t^D- N &摜SA5hGt GDktͫBbElPR|DߖZ>*b)L%絀|XV*%ܱ1d}8;pzϘ;v` 2/}}^%\H@v\\|#kVRrs\4s\k"Q p߾!ic3ϾwfrN#mEw].Mwys~ʰƧ BKU {+:A~mJ$,MF(়0ռYtxr.nn%4rX 嗢y<'#P?muPa"N1] w/r-&WV,X5*c;_DH@_p+u>/^zM&Gmp eȂCv(pQe Mn%6fl'όLdU5Mx8d6Yڤ,E%2t٘_οTo<2o[ꦰv` ')(^l?P1o1@-.oj)OTLqid{α/)r;<\Տgvd+12,M ١zH1rGcJ5vhPpe2NŏT^rہSiIDKzG|9(|}/#yΚ3Lhʔ)/֗u$NY+qJcB3&DQ Y;z| p!\ y? $p U9[_ (0q[f{1%؊zE㟄ȅc#A-\|Lj7_$SbN>c>Ǜ;'IGlףvC:WD~` Lun<#yv y7Qd(XvU\pC..5޷!B!76(JR]B+ HXAb&|4A̓)ݧ&ۉu]ۭhIEE*A~iQz  D)8/HkT^߂ f6^} ,tZ!XGu?QQxwşEģA'+IZ櫁O2HVw03%}%IuWjJȱe qbzQ<<ހU`Qy|\=8&yR*{yw5"sCKCQg{ \[Wmh!EA3PJ~QA4?ķnKTLVH1ml{3ކ^zJ>0o{ ^nyX'<`xƦf}wlɵkK='(h6R AҴl-wYtŇN"@cЫSojWL% :R%2X1D[С/{PnS$H>łtcߓIMyU:|eA=q c5n ͽñKu\t+F :q`B[AjjVr)(Hw`GlMvoaXjMHJ1R<tؾqC*bg8tL#5^#TV~^`t~xM_,St |~fxĚjx# z82JA/x '@x G?bڱ;VOWp~K7_!2>Np~qSu:+ƹ85ҵ PG8;BdA,+aZlE \ť Iڎ7ȀA1;vHEF`>끍JXM\vr"{i5?L9pdf)Zn ?\DyE7q~cH@ul $ Or"7YCPB!o!\dt;CG+}u')ȿX? lCbIm:6 i2.>`!t/b $pWn=í~ՃN6H+s <``m oEm]["pJb'a,4T8*J<@YQouE3I-V'j}K[E+k&/2.C=̡ }:5MwJ6юdF^3FVwTNi{lCkhiyR<:;3.\|edw.$e?X7/ջީ[F[-=-$7*s4K!C)>pBʥG?&eUT8)X-.CK7` ʩY1.Gf%O9$58s'3l4:}=5m(guA(Nl΀6 $Ú B}ג<Kz%_N(W'ⵢר%`h5[VIF%œ]7ΐqXr@ҝNm.B`w}:Z's^ș O! |gܱW.rw6J*w`XM6n7m(-t3K #Of;ffk,/ߡP.u NR٥ FA H9}`BV V5"dg!zԟ1h0ōv9BVj!&mc[6I.`Hfx^E9 `ո*|a8?d(Z*~ikbY#g=Zw< MmH<"zvq7~7 }K{cdOmF볒qE0,f1(vIhbRFh$΂8 |V 't7ɞ:7:GrgAD1Rp`ʄvp-VW)6s;lz;E; g{Zϖ'6+}ƬN]v\g!`=9ϑSY}*bF.#>0AהM@χ- P,%XÝr.ܒN `J"-6_t>Ny-/'b ^ZLD9DK"?h}Y>IzQޱxNFh.Pt#/:ѣq_aiۏde >GƺhZcR.GgUYVIJY=oęfw܂ ު \UVtHnhm+*"}AGmAOx-j^m>8)/Fm9xȈ111?ׇGUwn *n!}<yu~MyzY\HKmjxI#QQ=v/&oq6px\N֍jH5D ' |~ux u Kgf} I\>WY a1=k´h i{\Mß+{LB -+ * ߦcp{`Ӥ1.v g_),oU$J2CVLnҥ}mQyS+jduG#h~{zJ_XKf8+ʫηo"[3Ugma uneI\FcTy桬f& Ӆpp!70ZLw:Ό(7'xy{=`J\Py)#,"%Ju ezyMxCfmŤ֐Mm  :TF+ςw+y9;2uZ_]K@l%"'o>,~Yt)\L,ܥ>UyhO 6u/hEmocNZ kz^}'vGe⁘jԶ!^}Jm%'ka-ίsg$iw_/֩<҈xYFtC^/xO,^%?J4n&QT~FkF^j+;oDt ^>x gxӕ[/!q`*xA2͋Oix xU'Vy"_9iCmIE?T)ԖDm~:_WEmd9j_ XٿmyԶ2-4 YC]`fG)*}\[w|GjfNg 7#>[5H].=,HeO!+s90NG,Es"A@h$8rp+ϋ]?n9z۝Js _3?M埠 ) [*Z_KR ͅOUU`~X.ݓɓתT.wޱv}l嶣L`wqӭ8RQ!YtGavr}6_c3Y֯\65qK^1d\S`C>^AK9IArDd׷Z0q5^sݟRw|{<# zn37t$81ZJsSsAB }+'~I^sUh$\$Zc5[ x2=H(WX왨y&Q=Fwc3C95% B1hУ<!}#4f]%zf7@c ShĢuhg,ij3yf;q\j%?DFwj:CHʛn]_"HMZ)+;G(ȗ=%poo;>sgΫU[uХ Rq< y:ӻke}Sɛ?|aǾM$`HxX6UKZMe;yl}˷nY݈tk]:;?(R .vTJgW0/=[Se=Ctcv#3q5K\r,oL51Yq8Ƶl&\Cyhdpk)MMMȰcª֨a d%8?9ܹje1>[F{.vwf|E} rn&7$2vϹxf}0 G>՞l -a{\|/oƨ|ޘR}m?"#|L })vaWrG@'9[m'="Į*ޣ}CQ'A-r"ǻ拗ݼvBfZjo[_\>jaa8M[A0k>j7sɚ}ӝ{a#B'IFF_1OP=D"Obs9O89 <\@&WmZFSV3LD_l3N{q'Z s, P6ҵq/yZoDJqM',"v-bDq}n0h1/kKcxǷU&_{ ?$LIR|ƘϬTw *1´aּeR`78i0(Un7nJLstmdM tG0CAkZ)qc4. 5fh{1O8LnJ04@+0v [VsLA/a 8 y>_IQ`VgOH/2F7\kxƾ47D=0t‰K[A \dd|7Bk=~[ru%g w3A[7 &D*nM*~x%nj'DXcҳ2>:`q9 lZX|v%yAGyn|ťrG-$\x5/'}P1zF7藚` kZZl Fh?uєG|E>gE+K7 nw5>H?8|3T6΢OaQeRE""tY)BX R4Ĥ=ágL8]ARny"r0-&Q^IQfFwoce7og.=eLP덝gڰ?Sdbya׻>d)硭[ɑV xfCQ<[,x*wH{|Ov׵vU~wc:.AbS*J,?!܎oruVgfIa_jl>Z9Q]~bhsﲻn02ENMu-)Ll̊~9BkVFuz n $#=ډ58)px,Z9} ZbXb nsf9% 791p85 .Ys}?tb2X@Z=esBf,>1%볐)ٖG)d.mڹwR> 9v~>$99=/7^nm {=Bkʘ~iAk7ۥ^!9U:[nb)C\@"v]8H.hz&Rn.D lTmҡ9&zr~O i9kG?\hs:rqAjz Bى BՎ /1x'eҳI<8_/ D͑ghaCGO$ӻ|ڲ'ی06eLUxSe|=$<Ŏ(]tDw,JnY}*fnqY9q*;<%Ri Pr(~AL6ake.n ֵqzh?Cph4-=sՁN/,?p,a;r[V`FZv,iU|\EVК5T`vV  ;|BԻe=Ol׌x)!xiY?FrŎa~Pr"V)#8p) qHUTϐI̎MTV܇r)}in;B,YڭKR!> M$xu0es6;ngos4E3'I Va;N!O'Уqu"{U)*=\4VtJ0g~׎,D]p6oK猬C³A?h%EN3 ?F^$L"ce,vo 3 Wi%wϑވgbc zm.- q3څͅ&HN<{}K RSc+Dk6,%M,6,ώ#7po0[P<MbX>YXF́h[쁮6n4F8cfg'\!~R#@y*ުBMȤW.lLwN}m(z .,Ӗ@`~,Db ;r4 h \kl{O pcH?-nJ #0^۳ p#1|Qk&յ֣WV 1և+I)R"` Ŧz~3EYF0z&ք!Ka1CTh BnDke6&:+=IY>I|/n^\z!0ߣ=/tC1:2A}w`NUTePG3iꈆi|vEӓBj u'!p, Zh*G=hZǍ(enI%zF{x`B_Z9-M 5I x.tD`d'tQekCD#7"}A`a +0L`#s s8dctq *OVT'?_իj< 6ΑkGh N^6e]S/&*8+ N+x3+Y"'+2MjZz)nxF=ul1xk\2%#V)ՓFq%2pߴ '|(n֜_D۳>N-uX 'z,QφגbWmQ,lc޳oZ"i :نNϰFj\ѩ-R+DwJrp.vw@Bg Hb".vvE'6pu'I58dX b'V6vsO~= N(WZ P-VI}YI_Qe}BO&Ðh;m?ihĄKT2^# ;_uP &E.^­ $T#Q6'2{3HC"Ng)f { E"TETQ3M>I(W\( KIhiu4G{kΪM*F6fNbӞGpdK1ew3_bXtXƧjlV䝣oF"aZABN-y- A%8;~0%Z,Cp&<ۭ ɧI=Ӆ ^K@ɨ˺ ~o[2& -À+NнH,Žoʢ4Ϭ6mpK驎)]/-%Q~2δ.8&N25>"Z#{z`GT֩ oWi*6z jP`a3RM.:^9H-\\~`9=Sh*+fVsRg;89ԴimP^{ksZˇ&$[t @HI寙3o'ߣ8$`l-oPI`cE}BP X~4B@R>/ZE^*[dݑ=vr3p8-A‚v.㭉gEtG < [ZÜחSRٞoyi[y=@)~!6 JH2D&$`+H:{8 sbRcl.1GR ?\591G6ZA"{w0#%Ϗއi"\B {!JQXQy=Gm6SзuE;k&L%Cx -zghmVUsV8{\gƌ2̣} 5hQ#p1O P%o- D'b4?|{Z+J#s3L^id*ш942|QG(LpL%-3WAi6XU%tb:]XGqHz؊fl6i/]9 i[g2{ݴY8vl7BI<!۹ ^JJLj1؊D_B-.NϫLf^*ۻkA /`65?unCѶ;{c~ +}gf^ћK5%bY#6VE7 ?NưAm*uL܍6 Ոbt"wʗvĒB<5~'WHdu1`B4.!# QVbp5ʚ"HڤH<%YbcKEm mz6O&A^LHBH#tpB4{ﻮrFSX\s$/EUfR8rNhE|8KÁQ|y8wi^;5P 4?y()P,,: QO W[5aT3tl+WZ~}iX`ޥ9wY›*[|`4{ :&eK|'׼LyPѐf!e2;u[`7ͷn*^`/{@nDGKc$JULXy9|˖[ўqNJFrLhsC-EDl{ 5=7]]>Mtv-/ndr4M7EY L\Ѷ;E| /E'k+DO@,YQ1d}i\9pcāVZw/Z1qFk>_q\ =;HjEnWb8GjiL!~ʥb{!: {Z }1+sڐ GzEYx+}R0VZL0Gse^ŗ4ֵﭶ\.,~%UWUzcϩ̫W'u}f.,W';FkN Mif]y#0`b)szstԗM{"ٓ`-o"~|I[R1j&ok0W+yl&m\зi"hKK7Z Q ڳ MrDi#aЪ-lGI Rr$lsFtӝWP;<7JhJ~ ( &G F̳t,Qߎ*OL28-@b &|KbF4XT9H%j* k%:U(XR,2Le?d^j`vD%v`$W:tG] bWHyI!wDDQi&~N߁zW|ZGaVeUZ궬\+J<`y4j=o:h wzv,-W;q1Ev%#n"r,PK/8M{~]]cV{>t{W S~LG8]U>٭k(`@W+_cgFgDE1TvlGixKʂ o zzu(;cm6 [ѻ Z>&y뱏7ڣDriYZLa5yK c⽴!ԴyafPa>"m/ES6N>](**<,ؑLֆ7KiRhV*a4*6(H'‹RpJ|5GVB N`4tagTK1JSY (.d4v`>.qQ3vwsn>58) :_PpU\U5ozVծb~߈'mFWDЛq$}>&;KAiz&ƐjY"y^J ;q*nK/)y=y[tmo/aN2&UejS=E|p:D[.SvT N@䊉_(ӛ$5h^fg,[+@;cܢ]Rsv }rܼvf7/u{@jF5>sMJcWψ u`~8݅޽20Pɺ[u~N@o,_賠בdey/>T{LZb՝VLuc 2|6B^ѹw쿔q%K`< "ݕW]uv&ʿYIXAF*(IƼ$C0&1{"כ p c>'>9E$7Y^]H̥9 !0RɀɔL1Б)41A?7!&M+D;ZʎX4x( _6Rv*لLI}ΊZ qףy:؊Ud4e@w!2<#l, \Pp.ٖhnMYɆćc^c&PGDG9 `o!w %\_FV-pN8g#-Z.ZA *|I,3ϳcr<,/EӌO'A  WJp\;AOIJe-nLQ52/\%dN~& NgG'C$^8km /f]Fi&=;??ItY4K$rBLI aZx\s Ҷ$y%sڷVic^pRF\SgPĀxæfs0+-i̠Ʋ+Ro!Rp&E=Pt}3*#8v<4xCҟVNwtv {s 6+R1Rhbp*1#UW"܄&A!c~ꣷIT8-'qJeJ&*MD~֙DqU+O?(Y9"#Vr6ފGr<^zƴJ=1 3#iRc Ɋ=#p!>ncc"N[g 0 {zCq@d=dA<*{ɮI.a}&b@;RzѸdw wqQLV7RgMüebzLbkjz64~6LY3hLO7)tSb/@8o0<K{THXt>,)ElDvƒs1 >y+ 2&7@)=^.FȔ|R>ḳ |{ﭾ[MSy) B]~-$c9wV6 B#ZKz@7Tb5z.Ԕ**C,Xi)3B`Dɗ&JC4`11*cTp:db< 􆻑@!eO#F]ÓgMyOq9|!XӓR,D(;YMEC%Ysxw;x(R-uRP9<}[aN]hɒȈ@sv2<'zvrȶy1e` TAr^ĸ xZ`ឞ|ʭ|gc,D)Zlv6qD2p;JE '(ysvW!Ĝ3 a5{Bѵ̮6tB4h\x.\^M 285!C'#^88o$Dлl"ްX{o>Kz]wBv NCC\L]n7.%{Mh?f$>6Uw=E:YY9;wX dmaZTțj g>~/j+?U3rڣVbwf:gu%l칙Xm_LJ}RЦh஽뉇@u"c5HyO06P1Д 6wo ބ6#`6#`0&s=,)aMNZ|iyjuvZNTi"}i:[F,K+?:*7te&q! mM 6փywgbgRP%[W@QBDfC%"yiQr3&Έ}Psj%)Ʉ55+=W'=9>_DxRmu)S,,<.V_~ _"{Lr?opLmSoLyK0lY˄M>| cXx>KgȟQMxZROPXؖ}p묗Ae-e!87O{X+v*1_"oQ#9_HG{1J/ڸs+B7Vla'Qyh["t ZD9eQ-=(E?ϟ~-O`=`D a *+V5kjG%qY/[DG*2})dAK4<`` |>#jr}:d3aƽO@ʫ N8d3HGk }3K ϲ@߹PVSa8"®6&%[ndᘷ<*/U%ascRƸGc¸tb59qi;Ya!*buW8 ,-FSOc3K9c{e5<Ӓ2QZ~4ڧ(.%5Upp^E/kO3>?':Ys$GIh&+j$s 66Joui{$t5.NV [>jX2ji4mɝ+74 H0wF?eƻb&{0597pɦpczn\{'d$&b&vrm޹@mp$:ϞͽYLvME \.oܼ~R۶xU- sGKk2+x x^ێP%zfϚ+{D wAGޣ ^Ɇ|YW7NdZSNX'/b3&hXVe:yZ( y<{ꔪɲ:yD,^/3վ4:dZgmFeON((-&Cμq;.jߧsQW=ծd/ܸ/ם1w+uN7,k{1>ͮi$཭ M2&A*~,p=KlN+o5}\"u=p0#$U'% ەڲt78C^`qyv sDW!ܛٛzH|\{+ຝΩsJg՝5@l 1μn{N4 3ԛD(l`:-Y&]99f3τϙ\GlsljdO̙g/\4œ >gxk!{f7š<9 qlƒ4dwhaS w %!U_ ?6'] U=sAQL=sxAs|JSv5V9#WgFDFk4r:ǎb s4MRa!&"c9o~$sHI5p,]t$Bz2NA("&K9VN a[1(;k"%o2/As<͕_9k>{?78swƒSYIbFKp[Jr/嗔*`2(?glO(t9#u c|~\?lL)*s)Jtc拉6]q'qdbdLյl} o=ۤ ٲ~S΅9|~y g]Χi{[uUp-y΅Ď./E7[.7k)/C2fd-F5a^;]Zk Jzzɨ _i m͋66n?ad]=cMAx|/]|WT߰8h4[LC^JoDc>[WwΗ>bX WuBP$%WS+sTކ,i߇'ߦ< ~~TF\D0+rҲ3[r)k 83g}őL ɼd?fAr0V*9--nsñ(Jعᄅr {{,$<nXµ_q9(~KfJMAJ̦`q Y9 =,3ނN X_|igC7s3B!ig#8ؖX&ǒ&iө:>CxbM*VϽG) 9NM"D*0\CUՄ)JG${j Z E.VK#w VՠKoۧe^{>_ p:*̖`+Rz^SGηt_A{ QA?eӋ<ÁOΜk2i}N rj?뢸{GY.q8ūƁXj /ֹ\TBъ .L]S{?U-Z܎vx'ZP4{hd:/'>pJ]^}rXƉɆ!*`yYgl3`0ao"3'8xuEui|2Wߒ;+6X[/z0y1Ý8螙Q5L@09$j X+3[}qXWtDfg:^/aN`7YN wu=_l\tUSo{5ۜ +8m.CrӕUo8_}mMf>O^ҊF-oR&SyW"A^p=z]+e ;a 0nӍp5θ00sш Nõz`y(9hImuM*{K "y,x,ߒ& :hklGaL%F1{QO0)_ I,ssNXXrqpk+Glp܋"ʸcm Cn^:8t+1ma)U%p|zu?RʙC+? Hn*B 1MeM'~6 ˁlO2Kdb3 ra>_΅IS6ן;S[BN=nC͌{G7=m3]Vp~ |`M)&_A^iY_+,A, -'#.#kD’YFOdU*OO-xWcO uWNW%6de}W?4xV~4ǢM YDCg.gqS!s w,%.q@;} r)l@zMl”qRcQt/^~D)@9}3aoׂ9wd5ϕP'h `?B`mfó> 4؜*Bcz537cxp/!s:XzܐoD(#}e4GdjOmWh*bqs3)5E({9Cn}AONB&°\_8]íސ#?qAKR`۽ ,Ԏ+)c՛|0C'1w#N ΁~Ih]nQ*? {<]77sjƼ}. 5LouO:/㽃Г61s |QE[=C2r:A߮mw*JO*U^G;wySgx.&4cO+_b'R+EDci,@#m2ZBYz1p(JjgXh*X¬[uL[5fngvOqx ߯70홳RJ,Ȁ1x~ H]>&z:|&M= r)N_κгԱ[Tx†B)-(R<Ⱥ7zt[zJ眤^PmN!bPq+膀 M6p|荅oVkU%z(7rof @];O]=x @V9do .gP3A/ ˀD9} @MVb-H\40.g+&Dܲ'h篘_*-ШV9T`|nzo5 vH>3I`acgtry`83lm{7ch(WSo|-̨+R}Bpp͒院nח ;;2 ~>;SV.Y=5KeiKR%+4䢞D*rwuBʐx`83Q!8N/vrM?ȵ0$wf˾1Zeg9KdچV*]pXC&ry؍yϗ3=տk֡mL+c1epQFMJey?u?Z.^Z3"N.nєCKW =3DGsw2.6Oz 9b\EFPtY ks͂?9`E:?u Z}kl:dܷƹЦJq"B59NuKm1EͲ{g6\5E_@c` >%$eMM2Iw:ph"Y8]hmC1̹)+_u9m>gaQ6ςN!HqZbMuyƝ_'o---+8Gjvo%$.ʇI>7j S>} ȦL\R? >ޖqҽwH2s_[oXzFsMzcD]e`pmxWpRzmaz?Q_I 'أg.tlFZ5W,Y5ߝ)G[ϐ|JȆ5q`Yf0^D1YLh 0/rf;V _0:2XYMڱ-l&^cBj8R.Dy&Zo1L{Rm;[4Q&\T؎8.lXk\t<9lY+h<8=btFw0ϙ\݉5ʞ8X:ҕ,w~IC?Lyŷv)zIKHW y*Uf jxu5$bs4epy򁀟ɤ}l:Yewݣ6Ɖؑq)XK̙<#舴9 qK:({ rg Y[$%b|*3v#2Jة]k'&ˣWx3In+^n_~ q_׆eYE_a? h6U.|͵υW<2;3WB &A{e~zqHM)RT;hԆVQѬ[(A l߫Jg]R,1('|ԃ,pa:FӾlJ$ 񕅼%赻|ĨFdkvAi Ye5Y.v\R[-IaM='b=+RK˹LJVk-9J@{wܠ=7sˋc;-/jZ3iIzS.7.n iYCkZ)duw`Y-xeŖ@_&3J , 2.ClOd!B]Sq02:Vk6^+^Z2r|-_y>9>?ݙLMuӊ#nDu.؍lq(֥'GDP!rxLycgk n:ubQo.hfOX~EGNr|LoyWӶM%NmZ{E$]{:&ck|9ⲧW~.򒦤Fq)栗hb/ Ӆ4'K\8uk,L&0,I{}P4O9?e^zx˪1q &[XKN+9X+0YV "6^,ɂ[b5ȫNDtJM&oHZ*!@ѧ Yx87_vZB4s߭[lyI7`Zߑ+s{33[@_#ػ9ɰls¦z:kr̴3`388;@Ad˿uG^ptx<3+'A~AwMG*wXFtoY̘!4Es9͜eNb'.ۥ9);ؐ]mYl`oUW lÛ&m]7BoXw*茴w!A,HX5OX4\"rr |@(ocNշ>[=䧯'' <o!76SVA/oGkO"yto"!EvqwvO>Q/i>E?i!QQ#K|ɥ8=Q9+{?mܵO^¶XǼi%L]M̮J-dtezHۆs[k5lh6_h2RsxDgAOY"wC]TW=@a{Nӓ9OU|𝺞T|f|O) m=g ~ׂ'OWo?9H]x0<{`-: J1n Fx ;Xa]`lfOn}`-?\m9Գۇ0Y",˛ؠW}fɹTe󭗆[z\gX9 |~qwOrbÈ^9؉VsNpPhuInڏY+3`#؀W.X!:FT+l~~"O+=d_A1gZN=},ugErbSH>0A4(27)sJh8u]UPp;keK]sӼS&Q)8f\ߥ#t)*>.A~38//)6vv|QWG:3s!rgTy1O؆*|s?7d^:KoO\f. VP;hСz}-^qEșByAM|9Kм[:lg 燐%YXBzq{纮 R]MTn^Ûni֨5?tx N?7%hG .ftFȁxXrl,T#g)A2Uy]٥*_3bO ^[W}`Zvv[kħYaݕ67u" w! \}u#]y5{U:B-=dn@R6c|4/| 0\G㢌TkG1_UЌ8ڌLso˚˯'~2n"l.kJ>Kt3>v4#'J~pCu=N//ޏ|څgH`My֒\EZY~jټҠq f^T.z7pB 6+SX\(?~v.] g`Os1.\.42[[Y5N:|img@{ wZڊd/C&vF;{UgzOl_rY589B5*_DZ%p4C?%%f ? w"jS+-s!'Z|b˪_'s:=!kh?H + JFbݿ{ =oAt}[^0כGkqIj9Ix() "/G+_Q=u[? S# Wh<߂{+ ?דqm*]/#JBkV#dЌO=q!PO#zԏ#LiK}B'쨜5!T ulZ/Swف}MA_՘v:qW{E>CFeV}zDǐQ޻7\]D]o74Z}4Uo:OP ~T{}S{gܶv oHƛ\ \Vkn S"(˅D9(`:vVOyeS!_ϭuZ"-xs}|ި>>:7Bu7Cṯ=`j:q%:>\'VBCbvTO?a<ڎLjPޛ{/_1v!YW*rU;JӮֻGY;}n$춫~nk轧T*R}xCv_VnZ}puJ}o|dl)cv" ?x_K?V>:>>[Cg^&!"{)k1Y٫^ :q8@{" #'~(SnO:0{ie3M1":Zp[R˟_oz9+On:p鬧{|wGtm9{*~}CYS󚱱}cc J.i)Chjh2߅ }?ߘ  v5Us@&[8M`1聑yHVT]F^t${}MuSk}ʗ\@0ȥC"o]9{ԇm~d? Zq!.)!NnM-ƫV@*6 5n?>V. (U>XՕXm[3Н 8tPÙܦK4BsWN.L!ٹ||-Vχ;нt9vY@>j%r01X"z5IDgoK&Dݕumt'/oh*/L7`j^opGWg{c=VO0(Y?A:HGḦyZexH Wya1aWg^0ΖNgןQQu(,YvL"Ar2HQ͸PऎZ\SB~@5McMsیK7 Nܜ3K.VRv ~Ǵ&(?9drr&;o79GY g,+4 Rޏkj^S xsRM80ZM>'{9a/E jM鷶鷭w]6BhXPoѝ@1NGÏ:%9frI6˶%Ev<yˎ#}d?r5A5KGx#/W#}KUY?8e [戼ɆU&Mܞp2T^b ,^i?c0J~SqZ0o!wx XJq7hiwѶ8k|z.,? 5D=C#r3l_o2B}du!Zެ W\5^"hM 4L9u%- #RErܤ#$a2vVnƕzChZ7V6 zFsmC[UIpC:aMV3[e`ڙnΡ >F+͙,3DH-u|nWB|PX *1"(\ V%8]ʛ| F˛Z [DG\΋n78 [&o=4GC_,ۼ:yN0٬n 7rnn@t́y 8jwbtZ',zo/ ,8x܉ɹ`8XpGLǨ1$Kk<?tð&iC^rܢM\\s9mU\+%z2#8#3 tFMT̩Wꗷʫrg ZhMB-1m(}Vm>hJU__k4wA7Q{5(0jIFmNn ̺"§`Ak wٺ,eЀ7哵ߠXW +1pJ]y'} GANfeͼחygA )ܙ9s+K]rlk7;P9R[HFf3 xկ)Usϯjd׀Tī+ψqiK:%$ZyMy_lCs8җmxBeg3T2Wjj=]U/z7YYίin{p(<*hdڽ$Ze 0>tF+m~h8K\V X,ʯnS{Exɏlv=\Ml!j r֣Lm"#3"\+1ۖh#wd[ 77xxu͹o(w~L?E .#w"wn[գ|ĀWi[#u@HcP0[-&^#{z,8X䷢vS4hI*E=挏ڏusKUf>6\}ގP-qZ_Gz@ +\ =V䭧?GH|yTk \ B=Rk`1=Dos0ì*{8^'| &-quH%VxpYR rN4DoT~GKju5V-Ç)EC'Dob6xmV}Pt# ce=@w[}YڮrO>LWm,[*恁߃/o<=h5&# G-^!+jZ}Y#W \ӋafȒOŏ{P2fl &9 `.ʍ[,h`+B|f4؁˾x^wlE#?໲F?l~nY_+YiDZ$s>'_|WPb+l:zTsR_Jx7&xnM .Ĭm CN1nq1"p؝9_tx\Nq£xݫ5{/,.FjK$:1P^ѕЃ΢puR@6'֠p!NP YqF&MV~t: j8~L9'mM`Do߉,jTHHPaW{v2=||l@V+E^6 v? <'[iO4?f/8Vw!ȄwGQ;B6=ZE5kp}Y<^N )I㚮IMI<_s%Ȼ vGf,1q~}f@LFY펫,\Aur&b4n:Dߡ6o_~ vu-ta<'!O`aw~^viu 2\}"u؉ yu؝Y:(=E`a^ >K݁,۫*PI*`?~XS}3~\`H`CsVQ t"R$mxJ+BOV.T.SdC3w嚎|玕?5X]\=Fƻy[+'{ūmW/PǑ bOFB̓d9xo.m05y=;o~z  [7!ֺ<'bcs-rfvve$ף#"l^cT']&[HX(թ"M͂8]iA_~D oaՒLY\Xxi#`@=vG/BQݧ!cِn|:`.QobSY0ܢ:Ӥ1 5ђ蠀WreZWf :5؜аtL6yt+pFzVpk4Zo |,O"b'qs`51&JmabՍ]PhR@i˅S@sj jmy6:ߓ`4NI"]fN-vF붲ӕzO.?QRTYpZ|Zj6nq5 v2O"X6['cޛ_ b.c/W `L˦hlC|d'ݖe5CaXx7^ҙ\)ruĿOqu_c~S vƩUJii%k}"o+rxc}1Og+T$uuD>ڽsk_NQ5: S.A;(^D2pf"tڝ T>hx7ǻĈۤjШ3}৔Jzq$2. YjhoFL}dQ[b456\RlXѦDvMYcЂp.JWNWpVitŎ~?]lr8M9ۼk;&]0s7jw؃2XȢ'ѨSQR\n\i;qAl|Մ\o9^( 3Ke2@I1 &rrtݸG a&D[B ;m,a}+vGM]#^3H >%%o1up zy _ R8[=jA.U6UbF#SVdq.xyR$1q$5K`6Dx#i2>h0D<4]j ._\+ 97Z2r>?9'nF_LlNdw{uL*g9^c2 >r[zH\ţGݜpq Z\9 o@a$Aapz r 'F:3FSs"m3Pc&# 4G+E"~m}[OK~KVJ&^`4cš43Y@T^ڜ>j[_M_x7GZ]>z;ȸ=p=h- 뛫*xD0xz^5K[u ʽssOXa "{1$|N2ԼNQ])=2k9sfXE}>D \{inS!9qnۑpT> `N8KQy.αoT n%8m|x? 9Kih-&I9ĆvR>*|Wr ~fC|v_ T_ȯ?*w8,O|jۏXϧ->X殇v4oԃoSLmhk-[E>_sxuStxJĦo-Eeϓ18$TmfDI뷇3o dZr*lSbb齼7*_rnP+. .?hCs$x"Nc&N~Qf+oOH]~;Š[s2r/6I[(Hrƀ[cJȺ2ި6g QvPdj pqC trHM{. [NאNgl݅R{C25ZF5[FJQ(IJ`5X&,Uv46eűdKh7,MFC(8y(YlbPLW_FEPq.SOh/CJ@.hB 2.NW83f;b! ;v$N5%CrՁe^Gsf6?C8 BXFmŒv9p&?'o-Hb"Ú 1Wwd {=#K}9I(ogZc$ǻr3.#<`un}Ӹ[5J'εe= Lt/['JdCt26;Z j(X}ށƂYQ|˽i6kM,Fl1>S]y#8Ek;8};W F}'{_'˧so>:!Nk4O8+qO7IF:՗i?=W{-\{>z 3KyhcQZ+{V7STEXk _E[})O7sq?M/ϸVxp wijjjYu<[uSpH{-ݸufo=)\ $R׮>ej3cs-XjʋsNn,dZA 8GM|g'㡜q93x5#t w\yTl  zgVu_ʠzf9à;Y AˇyDBʱ[%Lv 0߽S :UV_P@BCr[#3:pgdB0 4r<,l!Z>138?+f#?oQ%@ W5S*yTʼ6%Hma62k)E[}rI/2?;?`l9q lBsQ\OY˯zVԂ3וfaJ3% TuՈO40Η7%{4{ElG㝙xmVgG,xQ*}ӁGpܔZ Aހn$H:I5`siGu4|ceV[_ Ja@X>8/yV]foû>koۊ[x><ՈDϫ&yr"SV7B6A0e@ ֣&Kki0s)PFG) rj)I֛5Z-s.0w,j fT<'::Ǚ-~UF<놫`;YXEA@1љTO; ע,Ӫc|4f^%LQry͂BȚHgM~y15B?Ar : Ia^S 8 d%7o)htHn`Aer@10rTʺH& UEcT?֒%ӛ|>pwLu:N4OuʹA# { 7~vĮ{-٢_%(>GFXT'ڮ:7 Alm0X<@9s{ ;c0'(#p\+IIp34m.̉Q̋{=Rx1 Ɍ֧TEě%-&~ղu-W!nw./n;@O9G,׻sw5,rd^Nnka = o,ѝ0S9wtQ?qog\QTm ́_Y8~ » }g "ur壋g1RQce9>zEmBr<֔1CH'{A%zPkBDmom]P5Q\G6yT&<E<>M)mP9#9 k^5Gツ:H$ptnO=U<ol7mypc;"pR!ݘMNzB-es],Pm 'z$(5CX,$* sO5b^jm%8n;5`TIb܋LSmRe "XcczPc~i4+-ms N*Wm:.|XVנ}C,vP=bb\aF#\Rsg/ b@(w9/M:m&uMB?Dz.͉5&[]pKgo Y ~WݛUg4[ti3ݳNhKUnf$C'tfRdd}UpaQeqs|u]/dbWv D8L=d5?`O>',(uƾ)W>{ 3V'kۚWE ZǨWg-Gx-]^N`oU]%kY͛`QZ_Y|+d~_\}b nY.-)U+-tDÌ⊪[U-"d7ssF 05mVNYxv͊[hYqMyC}&վw]z*S=ؕ[Y4AaG,h u1zVYmE'd|z:7 vUjkU*(,h[|PPֺwCS>U\3; NIw|H=mؒg WwzyMmAqO*'._Y=㵷w0BUU9W\u 5[_cS*0Q=Ln-b* J9a9[V_8/+q[r##S [$;JjJ̒BLzƇԷ 3v\ʍ\9j?;%`)ޜ^ӛO:x,z ɋhi{j'5g9樟%KXSP}$ST39C/m{[}Ap-ۖQY 36`gV[7ox,j/iYLX٬^6y7.h+2/\Zmh=;=;Jj[+f4ޘֶ|KCuMkʶ;M (Q3z̿LC1^-O-,ۖm[ \N=˧_p^`TWNG]I=:VQVҼ%u%)/QOJJ7w6|{t(6wW}3:?#Z=&jYK(l΍#72w1 dMi{+\4T6'{ߧ;74m(+,⚖9]5*P[5=^LWBN\)%A*礋 ߐd&[A*%} 2 _$)Ťw Xu#/HW[q]y f[y䕵A^|3j" 2x*=55ȃs׊y5<' y>$VAZ0`7"_@`w _w"_LV]|{o+ T^ծ@pk/Ծ܂b%~yW^ o.E^@{:!j|%gxyA:3=3.BaǯRX# JTn=lO:*L莰)(W&kOLq`kq5.(LQM+dxz8@ɤذS8߄PbcKo!M hCHhKKf #xj…)s96ft Mt@,O&(X[G 4&( Lg.G cJªЗZmD}"g0+e) H>݄..r2 | rնIiS:M\q ; z21i{-MUxTc۟c%t,E6DZҩL̓L֦*萶$y~{ރ&^Vnh+:n.)@^|)V!fHeX[jg4uuM4URݎ-/dw#%um܃9dbO1;(pV:U2}U}oZ׎O{Խ~4>Տ.֘99VRcڒL嘉s= ¾t,@l3n)Q."z܈c;ck}ji*o*]&>0G) lb>AHtւ̶Tۓ:5տ\·Oأ$1hVVrCՇ} _F0_`pZ]>~N5u,wiszM=Te:528M[Q3cA=3f&^c9D>?_ZF^Nَ}i\3{ݴnÙ>mcXNOK\ 7iW"]w5/++E} Ws%H,NƆ@+vck4E)8"=bj4XiYI38Sذkm,l, (IjCtZǴ\Oڛ@m.fV']q0r+nueM ~w-ە[oذؽi`ֵݛ\nڸas?fof,WC$X͌{,(İP)}2'Ɔcs*TmvW ,[ \ػwRR !)L[@XdžqPcQ%-($I'F-{Gb)WUvU\8UMq(c'J1־LX:ͨoϺIxj`,Q$D<,p,UP‰=G`K7)^(InEt@uMjR~7rhlx$?`elY>.maNY ƔirX[줪䪙*o9l6" A\{;ۡƭu f* :dbt~32jޡӏEqexc$='" !2b>n뿤XQV]:]bvZƶFw)=>C\aJ foU#4497Zv@U(D8@3&#Õ]:qAb6ԀŢשkt 2GԣOnXORYGXx9 fx5 rPi7tnĥx4Y2,*ݲ@WI[ǧ c- {+ SC:.OMt^p%N98ӮD̔.^~T~t#:&pnA)ًQ;O 'z^&~ToY[qm8E\:ÿ C/<=q3k3{cPԥOB,WCkd)67կA?*ntk:f{?|gz? ǫ`4zޡF_,c@ 8P'K&8EQ~T\89ğq]b)$!$RHH1)! RIf*RMjH-#3,ROlCIi&-02dpCԻ$@`j,!K2ЛmJjkd/Md3B];l#rI>E>M>COo#7[R{r9|\MJnC^!/_y $&א[_@N~@On.L.!)#4y< u*J#?&?!w@x\H^$ϓ%09,v>?9Je,9O דϑId'yJjKh>LZHh1O -RZN+h%Ah5Τh='mΡ6J\zGvDsԝM=K}O4Hh.5U,+h7t5]C$wѵt]O7Ѝpn[Vo=nzI?E?M?C&aa:BcDߢoGwwcq=>}>EHgOOsy}D_?ПW//ku5 -}EHDߦw{}+;'7N0L0 rYgbVJY+g`UհZVfY5FĚY keml.;cY;[:Bü,"-aK2`ݬ>J l [ֱlgfmeG#6`GS3hf!ff(f#,ƎaX1`l7KK eDz}82y}N`'ϱv*;`gs*y}c3"Ev1].c/+ؕ*v5]ˮc׳؍&ev3 }ʾnc_g;؝.v7}c7ك!0{}=ʾþc'ٓ)C4{=~~~~ʞcϳ؋%2{~~~^c7دooٛw-G'6{cfﳿ_??ٿؿ؇lS8Knx>/Poż2^+x%-Z^gY7Fěy om|.?\/|!n^~AC|_̗|_N+x7ὼ|5_u|=7&o[Ho;Q|'4 ?|y[<ʇc.|'8͓<|{|?O'~*?gll~ṡa: { }$?͟"_?___ k[&=/W7wO/o!T0R"GDP9,YZ%I_I%\ )B&d,HY*drղF:9SΒAΖ.9G6&,[dlsar/!N>]2$r\*r=W~9 WUrPkZNFy$7-r$ߒoGwwca|B~_>) ?OgG'9|A(_/˟WW5|CZFV)'/ ߒow=g@UM]CSK[G~('~`7! 1r<#(0 "(1J2ܨ0*FQmԐsZΘi2c2FlF18̘g7ڍF4܆>oeEbcXf,7VFkƀXe 5Zc`l476ˍcqqn02v2>MD5>cm6"E.2 0\bo1c7F1#a2Ƅkk33>ko`h|gb,xz-vⴝ[TAUAn r.ȭeB5\u_١XV̲qo=7;l$T=a5e{Չԍ"!# "BBڍi/>H6 !~CB7! !nqCB74 7$0ڪ-F41݈ݍrƜB{{{{H#H-a0?a#~{{?ߋx6C>C>C>C>C>rC>C>C| -G~ķ+V? B~DG~DG~DGt sѣE( zEUOb7rasmjZv!7S#6Og'R7RR/RR? .!H{"Cڏ. ݈F|7ߍnw 7g@Kh;4-q%ăD =؃8؃8"=^o.q+:1#1Ə@?Gh a~4$?P_P_ DADhw"^Qo bF-[<8lypʃÕ+O<8OӊX~fČGnLH%'i3bDL[c 4c)+Rj&# ˆcINErBIs*ȤIM ɀqcaɷTl2Zdð%JPx8Lv,R6"3H){GccO$ұH"ۈ{p㱰,,#b<edaYXw,; 뎅u2( Aƃ'QAƃ'?m3Qď"~h4OCyW457 \Ou @Vn9S% |,SV!PPS֨JH9 NI,Zi60f\AFJ^rۉѡ0Pl,2RmZlL%" Nz"9fE2C3tH%KO5Q%ӘCVCɓ4|Ul*l/q*3vZz-?lEbqXlBۋK%x( ;AUHf2~Ao!(* 3 ٥4]J l3: m;s +'.J}>nC\z O/.<`<muvX w;᦮p :\Å2\AÙϑd>Gvm)=Nq4{Gu4{^'/:^`x s0|9Ss0|M巓"8)N"Xtl :[栣9h:.Gso`t9]F`t9]F9!#`r0pOŔ i9pN:pu9\3mvpÕϱ̍Cך>\kpe"BFAڏtiSis>\w2VӇN;}tҡG-mQ_mu/d!>^·NnL7;P9n߀▚3%aC'h L'>3^zИ4Rpԇ{>+ !>z03zz*{a:kḺѕC!fJBf_ UE/z qᎫw\} a"^/F0i4E;>qᎫ7pՇ;>qE2ͤ |>}8pឫ\}}}"#)p7և~mG 6܏~c}Xpk >27.}T~~㎦w4wHFZH: v`vzt8OH,=~[NqXލ&XS}$s #0eQsI3:)J:-3@@q* Y<1+*D-TIm86jő@ d{qJG2/AhľʸpִHV&cξ06r51H'Gs3LS0quv'LvJ!_emƭۅ{M)E%H蒪lNFAECG@Dڅ4i^}Hش?8~P݈ݖs P7RR/RR? .!&!R iԦnw#݈F|7ߍnw#݈F|7ߍ =A|{߃ =A|{߃^"E|/{ߋ^"E|/{ߋ>!}C|߇>!}C|߇~#G|?ߏ~#G|?ߏ ~@? ~@?A"~D ?A"~D ?]߅]߅]߅]߅]߅]߅]߅]߅!!~CB?!!~Co~D&7QMo~GLDLo?a#~ÈF0?a#~ÈF0?ď ~#AG?ď ~#AGB| -ķB| -ķB| -ķB| -ķ?Qď"~E(G?kn^>~A]H3LCHH#H-QΏƆ'P =[E~(ҿf~R*![u|A=h^A=h4ڃF{1Y^PYEt/{͋hHn'  ԇyCXևȇ@>>tӇ^hq}qG\?1{G|?ߏn=H߇)@?_qV2P$0.&&aa4~ر(^%,h h{mIkLޘY%lMy656 IYȋ#I˹ LG4'q)G2.t r$3ˑCX"!,HKw8["ޔǍ;7v2 Ґ17»rIsWz6x,4X{ Z1hr餙Jn)+'F.;=;7vnOOJFKWl#a>>!LMڍMشbbb,h&\X2B3)62762762762762;TZ0Rͧ TBP `:ѹѹ@@{hO *Ptɞ;wQO1]1]07hnb<_S]?;:@5ֱTK̸ ]K~JvD*嬸~/N(ADX." )P; ^ " !B.O&JfW͈7btb+XD"*RޑXڒ:f*R1kZg *HY<i~vU5sU޹(OݻT_x*wODn 9SzaWfdmו$HimZ%֗޴UY,q} ]B-,2U7M7%#4{=-i1@d+3[y".zbZc`lQŸ3>͝27M4KJ4Tid%jooj2}j׵ (tyfmg50Чߗސ?ջ; =ߚ$?#.o)\\H._pU_ \Cn&gD}[6gF"3r?yo?#ǀ|' H^e6w @- &C4 |&O3eg g_b`']od؝AbQ=`O}CfO %𿒐wJ&%ۀ+)wn{ }f|ָڸ*t9d2 S%Gfz4xDmYD n^"ky>o^Y\ţJpxt5 :5'q}%!;2ԗjkzYz mXta@ ȔFҮ!T pE6m? Rd [( 0vl%fIђ $TK.͒thY%7eI^Ғ۲$jɝYzʴ,B-Pr]GV* C[zAB>),9 R#| ge>ãctc1c=Ĩ1f:F1:_b +u~:FѨcѦcM:C}4(KTnq%OBm|B^#o??@ۀ8LA˾Tp^,|uܩn}W.}b}^y>ws>>D͍Mkk2no@oc\D!o~H}}2q!pm ))Jg.5|dzi!ǐqj),r>~WPw`dx$̠m&Ag5Da }=#9z"=\A0Mgq.zMp ǝpp|'xxx?>c JáX; F8¡,Mt8e]f}^{h}> m|9~#Y{й+=(j^2 j?P?Xa%eFry3R+?z䓟bV~80K:/s շD#ߟW>*dPKa\bQccfonts/pdfahelveticab.znuW+Axu\UI:Ct7H HtK( HK4f͞5{gCC"b1KBlXl|"`k(ڄZbh#yyɩQhh^X8Yc4 9Ol:ApA@.>vn>9 @333 ܉ׯ`S'`6+_Wο<]y]l`"S'WCo^%!ζ&ÊBC.;@2!7r'I/'l ^rzs'';>z-VGSV[l䈂]؉lfa녻Hn6[+:9X벱~7=裛@l+ڀޛB=Y@ r6rh^R6XؚBMp{+ 9&(BAn˻_9@+ mhca~? U FA2N"f6 GI 79#nۚ-lG_D shqۂɹx5= 1֌En`]ПP_n`7V[t9DQ~m&;hgo;:w@+ u1UfV. ;C 0 O5-Jl;U2zO vvckhxoۙW8ֆry9Nw9'_=#S0pyp}G˃9ߞ`k0SZCUZh llx\ ٯS|*;t?6},\{{7@^R{{{P@^*P{xq/8 q/u/x^6ν N {eo/t-,-_l^Np_>\}7|P܀7`t/x(T&(h?P`@q,(. zx/ɀ@6@(pxpz+({4Q8A\oɃ̃xN+ ;ۃXv ` uP>c,vREك#%ߦBIw1Z$o\8C 5cCxf=BCIt =z?qm#c( M6J#x&('@yʯ?'C ݄"ւM  (,~<_4՛uv+E;+.hyC=`R?IkP@LL @(a~el|Bqc 1vж遙r"=4=?(Z(l 3G&`J_= 4 =Pb= c2v J[_;{PMy1|`?Ǽl\j=w+tr.A[ .' w: ERQ$A(_"PʠLq`yp@(g 6߃~$~eRS_''@O\ Pf8?мVeUcY(jkY(ttPw$P8[;YY?0r~o|@P@px^Jj?@q`me6PZY? m?A@;?Ÿ 0 AP>%tAY@;(- '?}, r2~(!, ,_Bȟ'D %oEž@G0P;W0P;{e(t=+B( F_ Ӧm0 l$}ll]JQ_E Mn%ϰJb^p1]JaG#0oʅW)˩Ub˱+;]$ެ{)Zel,Nⷮkyô%!]ITպ)@ޕ*N[(+TWL*`GS\*qmG1r\܊j0:eR5beZ> |,Ni?½󵵾G6"L9mae< sҋ~^Y$\'G~& N}FlgUWzkB:Xnrہ[=vwCrKsgOSTp-{?JnyP X,J<պa. $}<6zJT\aT׈^w 7ky4C9&'?9h!iq @ݖ}CX|]e8"V﹛L[ʹv~ #k1p{_͆5G!Qw/fYb.__=;1m՛|kl[||h|z4-f [l>jd2,UF(RG#,O>joճ/$bzFf>SI+*ג9bsL,ME!䬾F9jtY~xzSU-\#fbnf\=$^1Ȏ̪Uy ?'gTPA~%ө#r(S&k7N#Bs`l.(5;8&YwShc7)Sϖs" t6"r@_BHՄ [ S]ȉu:›W}[5`<-0 ͉0/ʳ]&4ROv* 771=:NC`3D勝@:0N3sbqWw yJ0}V^RB[c=yaBr}ϖzae`}smcz:)R+0_6y8,BW=fOۗṞ!0SYLD͏b%qAWԢ6{H49>CՋM$=&!):i Zt[ڒazBb~Uvn z^uXLu+CKwƥ@gh>3_R]~%r6-OM]De(XV̮RHFz-j!'J)\ē?LwR@PڀFVI)0VtI-`!k<Q|$ZR,WQ̱#Mvc'4C8NC$LuSYޭ5BrTjW}zNtK6x\㔠Ϯ!>Q}X6O 9eb} >M9uy5k˓n ?agZ@Io%B2vΐQ Λ8PiX`+S3%O`äK>/xywMaA{ӷ1J{mS%AThtOlh\sȊs+Y2~qt'rCO ӟ0i0>=%Z* e1V4j? ɱRz@,djMi3tzq9=WO BP=×9mpGo(84]}OU"2;P/MsHIB5 ;Ju01f:>%KP@D .ׯFo7KR+a}Q|;r^NL i]nFϾj$ܳ'6M(En%bOʗBgK04zNm<@*Wxīj 5n; }̂O,J< i\`ź̼hS* -y׾Q'IEd*o;"[kU=8UQ 5/ڻxQ*N1!5MY"mo)ސDx eC׻1^c@WAADϋO?<-Ґ [evd!e푀utn8SO[Aq#9-YYd[|sNyv(+R9dއo%"|+:z|vxO.Ky +]LsbG4GXUOw7WDcuIler,X@R?`͝J`! #xN؍EmyҔ!"(Xf!2Gɂ^+<})('G 2qmK(cW͘1n.w \1$Ɲ;,kݲ%%dS=B Z&ŞL+^Xa1ݍKozsbTi+."x\Yʤd!9_{8tzJ 6km=\^蚛 0&VY^`}.hORc YMW?U M Xde (/hU^x}%i 7Ew ^2k7ײ< ?z>%Hv,ןJVEcg30\?m2=ɑ|wD|sBia9c}~z3Ib>jGV?ͳTCVCtcq[4{\iY ّ *!p 'tw,F$Y{XI&bܳ٣0qpi3XӪF:VX.{+ |/c5'CA0d8'Ň?w{ڽG(.沃\rISh#^MZ.N;Bs~|p>?D[k@SR(HV:5W+u=%73E+1ǝu:{+؜یW!m>ي6 6_b*h4t(Hf}Qȃ{)XyF,Xp7)Y}/V)&S*'VR 4N1]&;rg9N1zu/a9+ f6+&N1*|Ht-F3*D`R3@ [z cyZ\ d~)cS'g*wg4g?m03ݫͮk?wSqt;+t} ec'_=`KÓE"_7  ddoO*W~;8@ kwT$! m_uw,sp2@w7f^\>'-&Ӆq&808!3{ɚ n{2!2{Wa$%p eSn lj:JƋ5kTC"RYEඟ##y Uh(e$Ӹ_?$f~TH\?Lrա5bvg9Zvudd1v5g,MƜG AߙɴֲU7eہ/]&bPX9T[wk]O՝?eΊނRO]*<0R&aEd}=P+DyCh b=#NkJt #me6oiwp#1? 3+F@Lc)Fe 뵺2I2n`H??'[L8C3bJY_DtCύc ({ӔO# acqfo^bB2t&fԕ2%E߻[Ҝ]v|nVҖo!3*)h k)56lwNͽ=2^ʖbT93L= b/sS FQ81bo#X$⳧r!ā˓;dpKnaNGuzwsu@sBWr0nNY?XwW?vڢY*S,a+Vrhz ;=!x,bBS*{햎}TWlA-Tͤ95rΤ;U# 8pw]iAF/.Tӱ[LljZS!jꉼWeX#t yے8F$AjGT}lYovtRbg0#+#&mMCaBo,y Te3ncvs8;Xʗ^ICJw`+y/hT6;jdRq<BXZte &$(ND*RާRq ߘ7{ CnBku4S=hpo!2~no[awȭOnl$]&4pIВzd y1b@g?LdS-~2ggto-۲!fQP"vKJvn|GջbN,SƖFxo\kPs-&8qFv~䮷~љ'exHwd[xVEk̈3ǯP{8&*;+{W7e&!у~XhY!Dat޸_A҆+:<@iwSB1n%FtN33>r*\XXKsܗKl X1-~8gEӐvym,`Ӆt(UuLnXWkD(E^Vy*tkL}1Ue\3Wb1{џv矾s`/x>'桧Ɛ TiC(u-OBFI;AU$(U7v.+Z'\z^nWo-li'Y5> Hph5<4"'QpÚ[XrȪ;lHk8j ѷIC0^"- f.ych ܌y~Ggx$y <Ηf~S=` z䵃KMAYAlDY#1Ez=vGYv%AN<r@^N$x|y,SW|D묐֢BV?G٬kbƝ8gٚNۅh&Q[x&t\pg3QgD X#}o5A]"4V?_dꛑKIohUv%m<$ WLqa3w"aҍ<]9g]C063/xFkGl hVô}Y/@~5Nr. /ɟV@-cXd RJMv84;y##y̖=X[Z "]&#`Glc ip?d(nV2N\Y)tZ9*fXLGesy֌'Dۿo2qX.p zcdFӛghO=9U(O5&odUeb:{'oMF=w39 -P"̕"Qs7Q2gu ۿP{#y췦V|q#pdQ&Y}[}93&4ݣ6 CSf<dcn@dĺd6~T̛%pE 1vm#/[ip;ylQ˛wYw]J|łliSI)T>MR3".#q׍ޱ`tO<7/Vpj*Z2s!`{#s+Y6#\ >fcFf#nE-KwoeހjcۺFH냅I넝ю\b11tbW(jND -Xe1Xힵy\ς0+$*6NJ{A1ЈD+iRcb[xCf EǒwXiUFd q#.1VyNpS4ci\Kh^_@ƙ&]>[Qտ,KPd3/!^;1 ꅟ'E+E`VVV,〘3^x^Nwf7ȅ Gtr|*vXgw\kršgzo nb*Ol!;78 hGGYK/&1W/p IQai|P|xh4:%U]OrVVkNtn?Ec'34[BⓚG$E UѤ > 6V 0J'.!ç"وjdPb &F: |Fo`W lFyM9w,c U `42.nQI&MUc~}q|*[K-z)C3&i "2A^獥W>3J?ǭ'XFaN&}cxT-G$['qr5y2".C'BF7KcXM0˱zXf*))7$(?>!P@1eͭr܋+[R1򒈵gw2q۟x8&/֚{6"5FY[zJfښQIE>ZDcqPs~U=54/PybVNT6+\z:E'كrG~rDY#!(JtHIܞ5Ǚ|hkC($vF*#gY>1,QvWqe4cɉlInYbWaD`Kٻ 7hZ]Ҝk0FQZG$E^Vtû؄.@gT߼̩j٫qr 4mm%"R[ZG*I@!xG*xH-] QX ,15iKXsY!BӖwU~T(?4=v>yՋɎGYF*]3tEu53F/Op_I5yNǕ2`"p?%:P{p` aJ!F՛-bj.Qs"7[r di-KniHm Y6D9st=Xe`JZօCG{ҕ},lA"" Oεo)`Ko3G!w^<ΤD+}*F})LMҥir¹jdrt;gMGCle'VEccuY86 7p.7oq;063c$aO]|Zǰa h.,o&GdMo5]Xt#10(&#̧GA9gjE.T1$zQ1t--٧".׋*엣3e{6R;0Hh}R+ֻ0Z-}.$uquS\zFYFS^T4XX4Y7P/M,Q}.{͍-hrtX3VsZнy+? =PKqnSi1@wL %t2A3$Vp ZS ؟`Pw@C]*Gt!K4߆(:;˒&3?[J'"nFxaAN]H@wmB+q>bR _3DA\ +ٟ`MԊO|&ߪt0u }JEʎ5)껁$*L.BUÑ8#^x=5)uOOBZt,Lwיv"\K;;UӲkqu(;'ƪ vQ66+՝^kpW¯Ê5 XRfV2T:pw%Tj\۽~qYyހ!'M6A[/2& \Z7*ֆ*G>\^YBAeg5lIC=P̱hFSȦW >mF-vB͙/NQhjOW:7:(xYO3I J)weUP.jRm"g8;Lj<ȣܼ}ˇo㿝-FL9ςY1p ۺ\yƓijC~ɏ]D%hNFپv!uڮs.~.!LW bIx e˪0!D35!N6UUdۭ>,SK^{I]u1cu UnWH'N{ߕ|"<&q kH7@gY8{eIYҩ1 ^GU|.@ :=OD5O)W4=KhlQzWn#A[&\oiwLŎ =4˴k~syL-u3琞O$o2< c_"tIx|flj={l2A-O,j2]j~^rSBh$50._3AER3a"9PHJdYVkCs[& mdz%83CyՂ׮7g ܺ!z0]`:_ug!\F-_lPyupZ<{k\3ܠTMRQ/ҧ wˤh>ԬĩQ'킥lBŖe RyW(R&i=ifۼpteOF BJK^GD uqg~n "E5vHD$S(/ifs}0|r`CdI[[7v,&g-6٫l,cnZX 'lzw~f%N"U8֬"YREF,"&e&hwZ;PlB^7i1=FeR-Oҥ鸜|T#r@J1eW*8gYahu.DZ]@%M^ 1 Ki8#* FdڸbIљLm%\9㵳$o ZOlQ<^(o&z`H4 5gFΖ}5@A/Nhy&,f㎛ l5Lnn.ɮVnxSSȄ5s YXIPz<ɂ.m|!8#O#3 #n0U|*9e9"?ܓ22KW{0CnOAY)2)e ܸWƣ1MFmK̞vĪSJ7QTB[?$3RI!hE!6a%5cPCQ ,|bT>{k>I[cdpB1rITC7uAԡI{ /^Z$-ٛb";.Ryd@"Tbg9#A[,龕Ǐ[ظG"Zcm%oMp s6І4@8I!nw# 2C֞nJySyCXH*nONX;F쑊Kcv'khrl[1XaXTp%eN]vH0ǴtMa=uZw,7x0|i~&_N^%U·d:Qʋ8NC+Ƴ>=ͤE]B,9?ĻG 3ۄ,栢%<즰ߦ*ǻ0ȹ~6(j}/]2`2Pɋrjx&33WGR7kZhQ k>"`H` 7hX-= WN3J36p'Y-Fq=:%گ!x!3ւ:jSKiAk.ҫ<'үVN9y0޼o`V/1Rj<@b](j,*e-O)<96_3 V._^eK4+]zxWޫl&O;jHg7 fE+\['TNhh8 Da ?${AX-)5I_bE#AV^(xosjMcFƤ:\,5P~+EG,oimGzr㑲 M&(}19K^*'-p7$9ӌpwU)>J_9aR<  3ѧ]%]aK:dRgTZc7G)8LoT ؂5qz$~\0t<&& h%N_uN~vN ({_(ZWv$,HT9wB{kh605zCS/kۖrz BDqkL,06uo,YQC!beM pswA!>^~֚d<=Ĉm"ul|xvb1*ʛUmbd-d+5BTtڍ,L b\$k✳@ƥ,?lȚ̈́tg{(^bZ>E<{dy2gkkRƣفCx#ָ:\ )s^U9&a|BF"%xLj~v INWa#6k[T@/`##΄m!v|"Joe$/P`ȿ_ K^Dd/>אViǶs6u CYy >Y:>Ҫ+khGGHe$u'4&;[GN}Ķ5.'T>7p a$mkse` Z-6Z7t4Yi 8w,lY\G3H~6P2=+lC 'y'vNMH>tlȇ\lG ^ͅIr C;{o! o&]'ҡB7/`=FX7`pLĤkЌl[8۾YjeS{.c'VgĪT!mwۤd?SM cN3 )l5ɪj8U"šr ZwRRSv2Ou VVX8sXr7v9F/gWm%! V<-2}Y}Bb_6o){Z4kཧ~ٷ$2D,#׌}VX0 ic֥VaiQ$}RՉ@=g#o/~ .Jj7q%|kEO j49BA]|]?]ͫ:w wvvt;3\"rstèWkņ)_ lP̍~xZNU뱻Ud+Kh&q AY$cڐl&7h Fvu3r[ d]A&Z:aVAx$ʝF)5~8pEvL ,|E /񺘞5T(2pOti{{:&I{{XCF $*\($:J&__ zQ Gm?}Զ]ڷWOBXx?\ =aIYw"'Ҕ(a͔ -xj f·&C& G>'^\M15`~ňDjK r[(/?m)G߷o,\}E3w/N;+,q0T,4Ԗ VF_*7%|F>|Kja?EkIxZُ'N2;. ,u9WU %?l5 dJ*VP\ۋ uv N F|p4]E{ bY+1?`3F`tMsƤUѯ6OuЅM/ǽqQ= bZom=, ol#=;9xY{5,.DLPM3JAQ',~떚FJl3pc|͡! o W͟bb!Jl1>C#@([ Yg6. Vf!E aW;OnѢԓ>")ʾ1V([J֛A[PfnRI}eD}A]'͸`2F兄"PIB>?)Xޭ3۠erCzH;XЌŋb;㕺_s*izaL#ƫ*B>66<Z}i -Q'B=7N<4SB;v96 (7=y#ؗ8؏D7d ]x\RBzW 8!ɺ H~c΍X}'LJ:Fr:w\n+it/ - $M90~P/{ ۵S`Xy> M19DQ8dַ&#J~+m2r j.ف`|DI667xq8M#xᆲZye]CM>t(~{޴z*`W_L=&~Ջ:t^JrU^ (b;]v- 毃fDZ*n=}(oN*%?̑~vc,0H_7[0vsmִ̕ mY{)v2KN݉IW21 B;cPOWn8[d$[n$G}u&O^oibm~HǛJvow4oo,Ҩ"d'J% cFH*\ gbi^gy$&jua)+iEƠE Hd;X)gK{[q}56u'*UN1j~ar7T yJKib^LCkkJ e럷 /r\޹oxD~, ՎDzfD?f˙=^(Lw[-#Zz;U"GdP GE0;K͛x>RϠ|/fKʓ[zʵr&<`YyNf$PQ B}!ѰPݦ2 )~ Bsos\`mGf|0sReL'dd =@[_8Yh{4Fzg9k pa 7㏈y }LtuYUx h.kC#bģ/.!߃z16 2s'HR) 1tƝ[e˫~X1 ͵!M]%甓8#:9oM+$10:T!jTuy_DF|⌴`DJ7},td$&fgcћU3㨄7cl'Q}%QCXx?$b# aU~'wyaF]$J`la_.rO2 8ĝ|Gͳӿjzn7saZFCi6"xO8:L>ghͻNL2tXBk~25A-ppZSR&bW*M{\:5PzXtzfXC܀!Vi.Ā>[c .> }&`PBS KBXM.՗fVz%aQ2@4ľdS!_T^UVPvud 1>{I,Ce@]+^R|"w +v@sm'yDLãTcrGB`Ɂ._QK\-D=@5ZBL0Ggqu~{DpI Pn${8ўr@LW =LQ߮xvvoZN%*4Wq%'i"^-@†l2(yJ%cW2)8wSIu-kEF*R@D,&6xV/HHDtӺ]U4%/O>9a]s*t}h]8OG!Tg?`|BF$?2v. k_B}!žbM`cFwVWEHlt,ozjشf2# +Ԃ؎Wx<"ǡ\֚,#k Z,ޓEk/Mg*GZ?Ӕ& Rdn T0K_7ᣑylxfٙ6,z* wEqmI9 ZͷBTzZH1Թ+p@WC(hE1oC%͝b' 3TƬp3o#`ct _%:R3#U I4‡1$Ra)|b's,mK/1y!ozڦ/jxpes,)ug/`tl"L~]6)h/CXa8=gLnq@ #v7~.!D4!oPȜˊiYӓnx⪔ׅ=}qA*3y (Er0T)ё%}5JS4[m#]Pg1-:y(I<$O,t#*fŚoܻ=U6qP?]Y?eK>AO][mΏ|I!hnLc޶7b|kOf'0~y)^Ř)J\df`4f28|r Gi$ǏfFXe_`|\zbo,$kfYfYM:<(^[BjېvW8-ZU]h?K.\bkAHuTm訸z PATf C@0DZ`RX@4m:zfWI_6n  .SjrzRF~hd=b&Iͺ0u*UoFiSĒj.gBa+he>}K970@Bf5?jРA| XڀISD<8_6$*f0՚Nf/1 oä"hI=ŵ[lXey=G:ДnpK-D)Mh Sjjͥ3iJeBH^.ᥳ2i03\!z3 j4&)#]H~җ%x7Jc5 @BFaጃ͋n3[?VZqIWT 텅ٔ0 ,MdW*@I T4EyLH;D41څA#C[ݬUt0T_X&S+*R#qvj2e12w(.*Ico@zRwo$tf>H.D_uH++V`)JlzsKBIu_(2QJN^Lt:$Oˎ NLGS-G(YGoFVk3y`xEO'xO;taPk'"$d?ЏTQRs|YǔEjoߒJ Z0pka§6JY xMX(LN9uKSbkv  ҭ02H@cr4jVR{(5HmPpʰ㣵)%܀7N<`j:iP{ #0]GL;OٖcM ŕ̀QkWf=ChIxBԌ֏;'2^Ct[W3]g4 ц9 (%K' !~1X>'!N`DOgUrkYERdux@j>u׌<ʭ<*4&RUέ C-ۜRDbL`єӕN렸TKKJQHB>HMO^Ni߻I1-*|\<5$l{Pn)-e0^[F"#f^7$$l"ƪH2{cҼ+|yG]5lpHiTp7a؍'Ţ+)^VN0RžŽh^6^Ŭy=77Q±gYI #qx*e "d^N6*:H+ھfX.D! "7'%UVJq#Is3,@AVUM}٨+%&ɉgnxr̔lκ qjm*dJzmt]c[ '7z rboHq 1 D"|HTwjS%ckl˭h5i 6wHb բ^-čB粷b[M$"Zr@ච5vL6M_'PKQ^>z]B&'//}xHB/3̢l,w)sB1Q0g7--{:\k l`,sRu7)}-a>omPK-/ ϙH#nƍߟƎ࣌@|<󂄽'_0OYB` UP]fK?XUaSD+%:[]SR,]o5l50@7ti睒Uwd6Kz (hhi4MfśZL }7`/R"dG&6ܰN\'*o--ZXY)[Ex(xnroD\a5:iQsgK?TK֓OBmLwc<^pʐi#%Scxoj_ro[3yYaudh=Pmg?@4FP,X^"H<Ka Ya HʉW=~5};09 Y CLRZ,ks}H#D]P>Ht!]|xˊu4\+SI}"$U$uht2S΋␸զ \dUm0n8qQHhGH҄WVqrs$B;]*zStN;4;OSF,J"uLtl@A+6#\-e9`|v|t|1\! [^ˍam1:xNtAV_29Ⴇ v@}i'dT_ҎFf3䥠#aG94S]/% /dlTFy7(T>u GNweWE *0oDMrKg:qTU! 6T2f 1E|#l+;ǹꥪNP<Kց4qf[`1twxF\<{|h7`w%۴oW~<"@}=)e?UZé' `МQͱ9&# ûpmV 񫜣H!:kՌoɻe,$ PC *Y3B(v*qh iƔq|6lN^NF:02z`NzLR85#'Ra>!&V/e =QN&{vc170OA$D~Y1Gsxegc|f!T +qܕ7 qړdTQ#N-ݵ1IPD[QiЇ&~ ՔJX:fw?cWg"A?*4XHfyԫ y-XC"_ dl(%Ñ?x#Cgp&"o0Cj۵O%hGmzU 8 6Fv Rǘ9٧159#=Ȁy'80+/q]X_ګzXmO`)WUV @2LGוMmU}& Z]hq m5UD6Sq.愠P_D}B " IW ƈ|1VP{rc_ǫuq!4 rlsGW\s4x#?>(cдXXRmi`Y?ٳםIb!z2%{_BQmtnJGz N쟐h^o "d4'4\*v#gQgpsFi5zFkEMD Vd)M<*&~帱ǣig$TNhZte,i.2ߞe":X|f5d t`k /i5K"@{R2,*hDՃˤe%cD&ы$hiD*.:?.Uh\lhiT+08$E4%PծHJQg Fx!qz\|<_77\}Or*ŔPKa\*exfonts/freesansi.ctg.znuW+Axu8r઒T <0 v2drv3ɦsdٲ$޽=#h0`BB( a ,"B$ Q *DbB, q .ăB"H I )$RB*H i -2B& Y +drB. y /P B!( E(PJB)( e,P*B% U*TPjB- u `L0|X `,e~V*X ka= 66 aԅzP@Ch 4fZ@Kh v:@G tnz@O~H24e80 FH6&DH843Ygl;/xA "Xȼ4WR!@u7fȽ-(Na}A8pNi8g p.eW\pnmw܇cxO<W[x|OWPFz } !0$b8 0"Fb410&b< 0!&Ęb2L)0%Ԙb:L0#f̘b6̎90'ܘb>̏ Xb1,%$Xb9,"VXb55&Xb= !6b3l-%b;l#vb7=>@=>aq!8p#q18xqN)8t3q98|\ q.%WJ\q u>p 7f܂[qnwn܃{qxa>|Ͻ~w_d^K| w?G ~oi2dɑGȧBR( Ma(,"R$LQ(*EbR,Mq(.ţR"JLI()%䔂RR*JMi(-2R&LY(+e씃rR.My(/T R!*LE(TJR)*Me,T*R%LU*UTjR-Mu.գԀR#jLM)5ԂZR+jMm-ԁ:R'L]+uԃzR/M}/4 LCh( 4F(Mch,4&$LSh*M4f,Msh.ͣ"ZLKh)-h9VZKh=m6Jh;vKh?t:J?1:N'$t9:O"]t5N7&ݢt=O!=3zN? zI5H3}+PH)QrS* ϑ :C>1}\')}Zg9}^_%}Y_Wq$BߧFoAйQPX?O3\_~~?`!6pJ3~~p„4LhƄ5L&bPD6QLDe/4Ll jg&Id$&If&IeR4&Igқ &]Q!B!Wd2,&f&er<&g)d ")f)eJ2)gʛ d*ULUST75LMS6uL]S7 LC46MLS47-LKʴ6mL[δ7LGt6]LWt7=Lϟg(M!Ŀ233 23 33Ҍ23֌33L23L3 3233,2,3?fYiVfYk֙fh6fjfivfk9h9j~4qsœ4isƜ5{B!B!s\2s\3 s2s3<2<3Oyi^ykޙh>j LXafˎ=>Cqha9#qdQ9Gcqlq9qbNI9'SqjNi9 3qfY9gsqny9\ qa.E\Kqi.e \+qeUW\kqmuܐqcnM7ܒ[qknm}ܑ;qg]wܓ{qo}<`Cy'$|9>"_|57&A]? :~ď ?g_k~o?g_`ђUV[cZgY!l?gC6 k٠o6d#(6fZbJ@(mƳm&m&m Ҧm֦mfmfm3h\6c|6-` B-bb-aKR-cr`+JbjakZczm`Fmbfma[VmcvklGv]lWv=lO}l~`AvbavaGQvtP1vg vbhlةvngؙvmعvo؅v]l[jr®jƮ@nn{{h=iO=kh/jiok}h}j'¾kƾ{~g~w93uy.]p…t\hƅu\xEt\dwEsу.b8..K$.K撻.KR4.Kһ .eqY]6oA]r]s]Wr]W4p+J+Իo{?+*쪸j긺^PkƮkꚹ殅kZֿ2ֵs]ur]5uw=\Ov}\_w@7 vCP7 w#H7ʍvcX7΍&In⦺infYns-r4вJܭp+ݪ?ɴڭ l׺uwFmv[Vmw;Nv{^wAwvGQ;掻;N3;λ .+殻qw=w=m;ßGc$~K˳!_B]Cqж̘Ss6BBB+3*yD)B.qA9\>"g/E\4f/*pxjd{^4{B }q9m W)M/+y'7DLEhM98R!99A6ɯoeHy_>ҙ߽,EIP2BoLУgpzP&1A0"ZG@.{ d1@0"E Y Q#H›Z e#|Z93JS|q_GG|Eh1#tKqjDSԅ  8B1S~P3 cBb:@^FQ09 0G@ ]4ACaz 22S}:2 Sj 8\ƪ 4}c{jq@B}:<B@5D& CC9W*l(26MjxoSs6@ọ-P6BNDN3Q"`6FP BE0&9ڈ I-m2Xh8eA Prx&j\5-7AB)r erxJ9# 9,hY -3мMB*PkgЩ/i (~s?P֢m.I(ߧK)e'^T)˴2Jȝz ~e(2%oj@WiHBZfGJ;msQ{R}+gQ{E?tIm %?#PyWBj(^2Cb~G%sKDTK-0 Mki2lV(h7a8'FCh*Eq1 xO97b5r&& 6; H k-ez8F`*J`lH 9}"Zmܸ2W; e# yh)DAk~ݯBy.sPبj}S?tz#*xok^|2*VCy%&v(UNE6(S{g3@NKn5^3Oط3yAk(ЅsMH@ =՞ v {M6<[0y !`;Y dx#iی "qSA0& (j _Ja:r@& ?G0 ^ 3])>XJ>D1aDAydGFr?<#ZF|E(zOz!6Zh3.j7̵c}@XXhPZ1|s*>n<$:) Bj+t$c9 4*l8qjlxLϓ#z)j2u(;` }@nT؊OqbS !E. | FHN=*v[. h2(p\E@= @By'У9&e[{U{x(Є+LQ󄼱Gc&:]eR9D,eOj=w0  e /+y$o3Z >r.!n]o>WE"g~d~sQ1=mǧP#Us3Z@G#VB/Pqkh c KdA)N")^2)0&ɇsR9r1r=37|0EA_ #q4E> PX4vߢLysùHQb¾|ʧp>MG.H'̄B1tۧEdL/9SHQ]6Gȭ6#]|3>m$n?{Ũ<bIH!|11) `Ӡ 궩ʱNG:--pY"[< Yoh!P[~- 1EMEc3Y)+ ]&E5?EQ:ZJ܄J (>aUq7ʖPvRA,` 0`os,(_uz= @?߂톁Jր\>CB?5\rw2:P>?DJKH{-$ 7%Z`1y Q>"#bYJW̩g^OPx(z>O^@ۑ6#畺2z, ֭ )ҡtgN]wB)~A0yW`+HA!Dϡ|:P?J 0+l`XC=9; z W|hhYo3G]Zd jb=#`ߛaW PZC| ~S {؃Ѽ h Us5Gdոv1T̵Ɯ@O'`<~ 0olRdA΂6Tƀ9cAO8C,@3e8?G` _Dmw~2 YC ?A.z d~,1@H ?D&0B {_gG xr/ q)ʿd=gNBy#^*&2FM@g&܅r7HG͡" d1id<{,iQ)I*(Dސ'Y zY 3 i&ḡmmgg)L3s4!?|9@, |nBb5B]-퇶@6gfB{UgE<GHoxCzp6ša_! (C>#M9NךAkh]~7,CzR坖)؞ڿRC.K!? HBw*J`< Lzײ}J?{Erz\u_wh`{n[{W[qjGu/y+U/{AtOg\ @6";u="C<̇d4ʀ3?<ZD 38<cO&1 e$% TƈD_@hW|X~m_FU/GaqP2#-`U {W |a,AՌ:\Eoȉ׏|xUTe|<>j%G2d81@wA_OGD+~l`jΏ6>s~8$Qm!Ȁ12w03 0fw*7[@`ʩTN||M nW jn  z1z)j !/sR68ȉPfC̘$@`K_Sb*wȂ70 4Y #߂.\Arv=pA1Dv*nޜ}o8 6(PHq>mKF$>5rCנ432 B}+~~yC!U(X GH e~JXK. edYOGߐO9ߙL+f 3Y|k{KQVFVVaVqVSҬYMZju̪+o~xxyCfgWoxxO'u|6߄[|gckZ::F`{gL\|&ֿ`0yEЋ W 1)aCHYNv||L24g1Ә9uf f?~ =\cLxVV2N[uY]3y aU;]}˻GS&SC1';`q$~ީjyip+ ް!/©*(:ӊN6ۊ&Fz|t/??~0 _>?|hxppa[n}ͷyN~,'TNg۵OO0Pj/~ `=S!Q$1YHMHIi!mt҇h2F&!sdqV EBdD9!g\!#w) \Y<^ SzA,&|0fތf|\Ffa VnPL,ӎShEc'Cu%p-#53xaͤch^Qp 꼰V4a,R*A*0j%nPvWRp$D+w+ˌUcQy7aiCdcppQe0Ùemc^555k5ZZJ]j-jYV2k ::[]^Q}zzz 'O5Wа(آq@WcX㙦X3UZugZZZZ۵kk=Ӗigki7hoޫ@[Bgq].OTCwHs=^^>^}u}c}~~~~Q@j`aV.!E+ 7n7ox#1ۀe;2v{/0`ˍ|2*V=645N53.5^b\khc&&l$dA&&}&MM٦N3<<4[J--S,s-K,,X[B5p]~e>u0 WnaelemlcnucxD6> .m|?~$?/W[/խ!`{@Gh8 4*&p[`g CAw{>BhpBrC]:V6~4=|(8";(=}= I))٘Ӕs45?j͜9/seE5{sro`HQ?c`ŝ?+}VYkfz77tnvν[JޥťKW6ؼyw,3(J65=o>?x~3[/./.([gAׂ qEbEIEcEkō  r/X0tla O-Yxe텏UUTWZW:WTW&VfVTTVUR`ʎʾÕO*؋y- ^TJTQWZ[UVTS|xqW?Zbxɞ%=K/XtKe,]6L{ySW?_[QfEJ+ܾΕWrX巪|ծUjljkJjjV^r7֠5kYs{-Z뺶rZ)յkis]Wnͺu\_7X|z/Yd}{7o]߱wzn}h}j}u]7n(ݰoC'Fo"6Yo Tq@^!!aIñ'mReo-{QQxmnkk*k:4u뚭]5l;\ٮ=|{;lv8N; ~Swej|wݏHTyO={+߻W7so7߽/{߱}ud~wC]?\)O:>rG܏?9?n>l|c~I'͜wG8Gi?shCOS>]iۧWi?~lϱ>E>}^8xķ,kkijree>_}_/n|qVԪjjٚܚZZZкjǭ/O`9zD'OT9pb'h?{ꉻ'x٦n㵉ڼBdmmmmm m;u m{IIII'e'3N,?Y}䶓N6l;}r͓O>?8wsǩSRO*=TS{N5j;{ꩻzyZ44Ӳ O>]z}O>=x釧39yKk۷k?~a33zgxgDgDI=wL3;|L37<<ѡuuDv$wdwwTvt4t8qjݎgYg==z6l%gk6sٖg8{h'4tL,lyXg{goλ;_S?>;':}.\ƹs՟vn߹sm y]..N}GW`WlWjW^WiגڮƮ=]Z:nt=k7=os<_s;~w?>[u{wv˺3 ˻뻷unn <.^z!B%j/4^sЅ /ܸph1qI)isXO{Oo՞={^^TȾȻ(}1b‹/_vqm/^y罌^^N}Go`olojo^oi=z[z;{{o}|ץK/\*Rݥm]:zԥKW.ݾXZAϡϫ///o[߾澶}_f\6̽s9r˹K.W]^sy]^>~r;Ok }so?nKޗ_F~)2/{{t`Ɓ]mCb|UUW]_ ~䫗zփ_K뺯>u_߾wJӕWZ]7XM~f7W^-j}W[v^z>i\c_^&w-Zk%*Vڞk]]_?to=q{C|#Fʍ+ou؍7}]w߭mw׿{!!!ߐl(olhCW}}W͂7"nibru+V-٭[ٷJnUց[Gouփ[c5nvs;vUnoۭ{n_=t;:wXq#~'Nʝ;wNӝw3p;չk|WtnĻwݭ^=={r-W޾{]ݾ|Xkx7\<\=k/GLG###u##W_s>?׃t?hc[~lG9]>~Xß )㧍? >2(QÏ,m?灟?6~x__8$rOl,{W_~Me^hhhhѝGGG2r?~zgg &mo<}^ן?{cDc~cccyccKjk1vlz ~/"_$~QE͋;_xI߉SoX5D"B|ҖoOAhcĵWv6ն!q1xbC!K 91u2j" /bρWm[ :!5=;"4yD#@V$; w nVRQtqEDQLT" ɳ gJ xy> U$ʉ y"_/T,KuH],8cOD"؝Za—>dV> 8dt8 GT34'2P:zt8-? f>6\XfMe7ԉa 5Qktsps!8~!wX;ajkX5,] ;'F^].5(e]j8ʎ2Q&I:eMԞ#_z'B|H3:Ku0D`.6,z$$$<7K4P,c6gykC5[,L-m6!N:L<%{rYecK@;5:H m 3< OK9ĵ+VTIVxhCs5f"eHpϊefUk->y+٧P(~>9HFSl[Ub2aٱF-`Lu#x6a66LLGT3"_ ~,"sv͎'<~ϨDm,%^AVNFVaʖuiZze<P1/--qZ-q; u m.. o !z^كN:КäE.eXh.RҦE?Hf %M-Bg /eHTzH1($QT0+ErQXJJG>d0˥s]qQj)*S43H98צ(q7B Itֳ`k&5Y*#)V.#E֙Vvj:FF*#t&Xsz[DO,z3ByBW~WB>Ҷ/*~n Ε qܰ4] ә "j7LqW8 y I-=s|&{Nu#|J9~ɞىo'ZykS̃\'SIAB'PX Xr%W,ZXEв]%cuxD98O;8xHh,&XVՋfiir'ϵȜDX{(G1uNSPsZpNQD^tݐK-:X(^kc6__1o`Oȃ(;啘Lnaҟ;++WVRs a||S<9{ p Q~P e9BӝzvnjF\*gH{vȻЂO 'q|'Im3?-*R4u XP'~@A(hiO*/%I$&b~ %zЌy)&1w E鵆z~Ʈ::Zd]jd/i,}Q*֖>1gRxT_;%<[_}[}=CSqp{SSJ'&8BRev?zng@t@[q,Yn($w֏s a=l!rs @T">m| L#fR@ $B}@yep/G}iGk\7wNQW:+ߑ& q?wE4#Q~]1``wftV706xxٱߊ,0?_[>]vи$_1a uw"Ft:tq;ebu۠k2\׭%-\e2q01 *>|'?,lo[~g!_#ͱɥĵ,UhwQ3)%iA yZ`y ;Ӛ5VPRBb"9=;fC3:lo[(V^}Md19R3$Rt'$>iGlфc䟁~{ R:Kw@s2 RiIT iӃ+l6RLUIs7hjC@SRiE W?>$Rҟ0|;절G)1S%FR{[JW,*j삢I'ǏF]'J%,|SDv8b5:61A{D w } jo* ^RvawH 3s_ OJvΌDσv8vDaȱBCQf)vEn6zKx+Jf?5ѺAW"fj21AOz>[ΥW)!52C/ <3;[V'jBsdKz11=Bsd&0]9V:ƺ>62?{[@_,aDP 崽AT"M+,H ">"c)e A&B;#T.Db8~zyIfYF3i3'4^lz̩6) S5Fnװc'O؝s)¢EA:/;&Ըtd~LF 9M,t 6)m^  qo>6P,Uuʔ %jUP rdZixELITpuaki55Qګרk <[;|R#S}]SݸH_];/0I0, } G뉹icBKSU J t.mNTR7+༄xZ830>0U¼̍Kg2ݥIhS0E_bVp&!~W@};N"/jqu{8xqۤn2ho0lےI֖IJ&;VpV9Q%Te؉DZcuttml4lDb8zLhuٔɟ2D-5J;iQydO'5.# u?fQoAp^%8'R>P|9tOvl'V'm Gߔ61aV eeMt0TWDR Ν+% !YzcX2+Q8|&d Kg oPH'En! !1qL ͰhRgD01ؖlb%oz<y*>YR~~|޿Ly>;D)hqH駔_/&B P"Ę,ᵻJLNqfE3*[y9zqm]W搒fT&F5KX+4Ce(Ŏ vfx;̪ފ7\M&8v1Sa_ /TIЖNX낂djnڡJ•/:1XJ;xCEoE7r; |^O;ms>2k3sf7%WQIk8PX|wp_|OT[-йV8'B°W fYh{kK&lYb(a!ĎB%01@BʏaSy)ݔ̓w͛}qg~# Hb`/Nq] 8⬉%Ӂi'0sb81l@'o-ǘ5Q k3ԭrfx;M⌀Bf zOi ]2H_fQugd߿OW7U|6aq/.XyS:J8~.\WǒoWb`^D)vG9Gjl1c])DUˠo-v5 AMщl5cN5FƢ`k6sa[  B yښ<' ,gyBZ?EL9`g3wf@/cK=k[qr<I3ۮ٘7=>KQQCdPK>ڱH; u*#4i~I~!6^i$@*q%b 1\8UBhBhUnDeJߩN/!-j7h6h7[hnѪ^?D);v >p\.ߣ I$Nxԧ26VHd+MԶw$M3ΙelglU$W:9k*2H/lD ɦc)14,Thi|[..Ȝo.qbOJp+`iژsEQ2=q\3XK+Z7su➞XԈE*F@,}qɿ*`Uv(֒d2)4q*'èjJl'j~V+}&ڊ}]SҧV\\~dKQl2_ӳeQT:D^U"Pvqv Q>di C"t XK45DVZO25Դ4#NB44l\B5'虱MK֚ǘZLF\{(ŷF(&,ZfqJriie[y&J!*q%ue'~5~FδJz' N@LNM|L]Jn_(_d{N|4#S-fi;ь[`k[Tͳ>2Qcܚ-2bik=9V-f%YIVOA5+Ww_H /'H@//zx@AN/I xzx(sf ٬7T]a`@vL1Ý{V~Ӆ i9G5\mlnO7,.#x4p"-P49->IB7΍d+yn_<vj.flKI!04›( v|7Q9:]H]őkfa߈,^Sʷ MM]ƠB 犕Eq"8O=|epƋl |X1ܜTs^O#d#N x|:Ƴy^uCL}34≦\Ph-XҝknkMݗlʔ Uig1ݢ"7v{Ų-7rn 66Q `J(M5$P`BB @X~3sɐFܙ3sΜ9wΠ"9g"'8]lɧ%uyMvaPicWj|}UW[b+yZ[o4hBhx?;7^MA'b:{ wk[⳱yE9EWG˂f573s荏| kZVo "PP5Cayoڇ4ݳF1W 0A9X:!7(h_g;ՐrQ J'ޤC?ԧԩY裈|: Czё/!r %"6tjp1 x/}7I3s {|̙҆G!>'42r(?}q `u֕Z+]aunޥu=O]|dF2;ɝ{xq~/_Q͡s6duJ'ٷ}?:8 _O_뗓屟K1}9פv8 vU[ R^y=6*}h[{3(xq_tvjz'!>(X^I;{%:~q %OE므@Fӯѩ %)5lO/>86>v(w3oϞlrh3h;#D~lNL,X>5'\%SO\:X@=~9tkŲK*d-{ 1'+_Zܵ䴃"ğBȏq4ETέd|z2O,~&> gH=eq磗t6Nxl~@k|zasWKe\^(ْ= OoeE/o Ջv)7Ң1F{88ThKTS]rܐ_6^i6.-.tt|s:kJi x=ǷkKВ4No(pb̡}|=;wzU: zh*}c~rl4R?nmMוB;/e"#?qsC_ZAf+  .o|b:=͜p/k[Lšp8Ad_qUsdt-- (7 *})HqTdq89ìP"?tbW7|YRYfي6(u)AS™Dr6UM9J_مdN8?Gb-4sѿkaCs˓9_$ѱM \$S=\q:^6xI A`׆X2b /nr ^de?]?o(^+WlG*2N\i\`zۊyeʬ,\`6M.U_y k5=Fe%,nB_J"zOਲ਼cu9 5s! mLLM}znC_V]z.pmzu9'[ʾٔ#M1 `{bVU :uGG'  g \Ց|PYR\?ڹY_uc"6;YiaBl/n ~2,fnt:~߁:rDgT54nv..wq$X9^WzH W97Z{TZ4=d@=29<7 \_?ǸFhp_2K::_܆quǃ73GOۇYU~gg7ɱ*Qk< B4JM!6EC̴kUC^Gh A7T%o /jtbnj+7-4Vj$/ߒbciզOFx_^x~ sOKRQr. =xp9L0^\%Տ > $g^PVTWPoBS;l'?_bz LNR!z+1|Dži f6fCk_b;| :~ڧ E\psm^kLϞ7ǞGQmAmNU*/E_?K3àŒj2Oyt!HWS(cp ~  6 uW\䇉{ /'fV`^$#V?zg1k X5&p=-h)F{]fހ-ZW3oGD7i~}QeiCƇf Nih%@ ¿ż|P5x q+Fp!9N&=Dbz׷nE7ZWǡ]|\ Vμ%?' J'NJm;̯ۃdf\gX|e V\2k9\=OuBb8RrnPp5/ Loy7'd͍9wvK1V;  | Փ8S?;mBKqt;j=W?zyU@W=k"Qhapl/LQr<[m1IQ|Q_u}o{'7,MȞ<~Lۡ8\gH^us\y4yq/r3t1{л їSRΩk~ꄾoH/| גi&ȋ%eCF9E|Wzzᣇ*Wg[~JSS:Vtk.֋u2 WB9u)&cqc碤,jC}^GbMq *!'ɶwq@N=]>.-)PE:_3^Տ$"D(";3G5 4Z0qA{k-cN0`!kk[pEiжg8H%YE]ӻV'qcOh'P{Gq41.-o*o$|S_47>"j/$ǕW Y!7?d<уpz7}s<} Z+[_Rw:+CTj>}@ryNxI3f56EpMg }ki3x'݋=kYYy*ZW^t:ٹή?~wv:%qgD/|ߧ{4Iq $K/1ǜ,EﺏuXL ;cܾsY[I(2l: T{?%3iGLS2!{&FWy:ch|ОE;[Ub5j<N1ԫK ^ƺO۩oѳ[U"vANfo¥cvAuh'7|qI w]FrB0d{0_WU9џQP?+斿/wqgX%E8?$Ys )mng+H\`].Vv#2:^(R3ڵxQh^"Ug{疎(wչK턾)Vl5$ Ɯv _BbW`SŢSjKgYOZ1쨉d|S-9O*o1 YyjyIwx2qh >E$LIP0 3p$ +d$xP,_(a,f4(bG22$C4wjX|9{8]u8Κd9 _tka@Ul:x^o}9;Czv/s4𓓹 ȣ?> E}ekъdVD]BnaF70x|q#qBqŃSewug0 1^V4:uҩ^ u{GiXluj";,mv5eRA Yu`OԴ?_{jBc.̮ՇᥓcZtx-cX*Ҷxk흻v2S/80; 5̼X]2vp\ۗX|ΌȼbD(jiע풌6u9lQ?-k5|aJ~qlj{\b~2I9GߝdaM751 W/m,e|f;NU}+#;u8kdIGimHOW0mO_bv}vH3a' Gg1K@RHl&pΡ KgqƂnhmhUfE`srW]禪MfWz* ~b|~fkWXc7p]#eV[|/Gboh9j=3pY}QUև.ٹ_bx}^86m=Y6\:hȯ*ոJ]cvtIya},}Ύ! N@ *-3\O{)fEMp=@cD NwK>ciI N1;JDMqߣW=)7/\9pz%(˂n$ fnA@+G=;;65\ Ue94uYCzNoV|#6 }t/5*MTXLzRY҇.\*CZS JQ7w |vӎ5[[+2O1A@~DNLƉiuZ?>urA-Ѝmh,E )f) g0n`~p*n<ȯD(`\7z 2A/-_a~q3hl;M;M͠yr3s[b]Nguq%0hp#.˞i,?b.-ݨ+̛{As?xebN++4zg0[O~K_۝gy}}"ؒSP־Gh'ϒʴõ~gU[4ҙ"cv}6H|@$?yhDM|>=klvA7*HKU+ZE[7ZBx*uE7TJ fgAiL8C[es?c]l?bO ڱ»% Ce`d=rg!N6#0d !H&!NR/QP\-i<ܝw!vZˆvӶ 8\Қ3= , 9+|qinwErbۜ65N췸Y\L#1 .i^ʮ/]̠%Y]v/_PwO$S/Ryp8Z~mڽ5{V׮ZRk]} |P0K&1۳9F@w:ߕJ j$[޼nO!Sͤ0>D [u@D: ֖SsT)t *iӬm 5VԖ/seFJ{=u3qC* D.mh0tm.Wq!DF{'Ors4:2RG83qfoHüB/sw=Ϻ}YNC!Wa']2$H.+veU02ݾdV6}˴a$jŃҪR>8,ՋR:\Apq=ДӫD ="q̘JSƲhzh]23]Tݸudm[7fܶ\ P]|h^VWV6ԵlԸ~Y(E 1_\ CՇ,glx dMlY#y5Bʕ**C.]P\%Vh٤ZBɤ*ڵ::5-B:\PA { ynq'&qbV5ڎ Jjp9ϲeSR!~GSW(c;{6]&y=c?9g5MβDM4gd :3JZK2dfr u^p6  z4.Msn4kU2}J^Ce6m)Ζ恏sy+ <' Jc0|ljjfL$  ?EvV!g~)n"є䤝~Ԏ>Ovl#_p*/̘hluM)X!\sUD?[cFIUIFB69wwU]e 9~sP(< !Cl( _~zXhFrdvNa\|Soslg 5UW:~{LQoLJ$U”Xgޢ*]üT:;C&7VV 9'HE"9ώC%^X%E zq﹬A/־<5r\ l?V3 +[C8xib6u k7pqwHn^C,\hU\ylӮYVlha-JJMo^..*񢧧^BNbn-MӍ/:y1'd|e#F2r9ь 7YMMM=H,mrgZȍe; O@)_J|֏i1$>|bf\gў kUd[/zHX Url^?ܭ7_ڑ.B{L_xAm')$Q v;U3nѼ@HȳU W0k}|NvR7ȥ5lRq2\kX}u!Z k^'H 'xF$rToF{>u X>7K6YBF":(J׌FzLMƽ Ԡ5XUmP6J\SN0`7d|s$~ yR^(;\\4;ؙCh~ (w_e貆tn$+2m;<h*i Pa/#m㮴8P -n~U}v櫮]K+!%aP ƠҠqzOd?J<}$o{h|9Me$z;OXсñ { =Uyv^{V{*c<}3|Er Ƃ|Sbnu2y{ɱ6R9X}/c8ޭ'Hd>> ?C7 R>/{ORQŞ'=9u}ş{4sY]r =z{~ER?j5PTlN{gyg!yCtT+ JF‘3*+ʤJy\t8u`^{#^@Bb1)|MdFb0y"?DG7P z M!yC#`@t$U+wPH~d FՖlu%,IK[_L˨hpNjѻ Zm+еok5 >JQ#IF&al;#卅GnPG=v]vu9XϪLpϛj<9&#gnUȤoC$]L}{] In~UJ6S~j, aoDHSLBd0+Y{H> ıx/Y}b[j7{G}q,J!9/1&ȩxy=k;ɳL:F_#%t+9$6W>$:ƒ8TD},o"3I1LqR]RyyO',/;Zc[(>1^vR?՚.ޖ 6\4~ w`n}&Hxek<%6X VDS^F.0ln7fuz);h\opj2B1ŗwX kDz@Y?1wÝ n~:4ÂYBCV[HҘJhT t*1A9 Ooa/YfZID s+wg}Hm~nKQ0.m\.}pGNZ^>7#N|s#,#Ϲmw~?w3u='/'O9rLOMtvo8֎qHt$l,'' RI,œ,2>M|:;~$J9HQ`r8)9yyK饴Np$E [Y/rGjBpY.sKg%REth>m}w'i d4-aѮ,Ifg+0W ,b_;X9~I\G'=9{nBߢm8e(V '\{yx!h<"fЪj]ak ]Ʀğ6TaxdlI q wOϘire Ɉ\Y0ф]N@=#8ܴ]SR @gLUbI,M̐<BCedC#]!MVoqEG=kq^}J)b,MɟZ>WB5]wE雾3[QIJH7!-R<155{;^̊"v^B"C.U^fA~τDBD)biZe6Ϩ{u6e]֨ZY<4{cu_Kdʟ4Y"@լ7hrRZ" 4s6 b :Pg&^XP9;Q JuQ4ɂ1U1{2͚}rWgwЦ2 ^.k]&ƎPkj[_WE)Uā,]d݉b)!!`3cX< $$;Y'(=M*D^`fEApU{yZ+ZDG'M6(\- 6|$'.MRO0aʨ N2N1S^~&ws:C$w Ne~t?t)|!Lg)p&,rcj4DyEtTL엏t:zޏ979J@ȡ&+ju>{r湡>X^W ;Ciˀݡ&Z]ONUJkrK4#ӥ gt{j.7DK2 ۏ#_Lu-žvhfWUҷ@A%Vh,`sA]7n,H7ZRz<"Ѯc}"m̹6 <)κ@V2 U{[ok?Ǐ7Lx+Ϝ@|s^Cz賘wZ(#-H(3 Qx tm!133 -AynG] 5d/Z֖NeXZ5h|KA+j7/Yצ9œep}8+: k&*njdR3u o̴Wojn,bhXˋ2:Ntwm[n:l*(=%RS%ھACP ±$!>)]sp:׮L{kAɁyye"<鶱• M:N,0Vu6;(xf g|cɊěi,cylzU_ۼ.9GD5n||>ZϤa3b MkW7Ww~;y1ô"g}@s 0& QۭObmի&;`[iT5#a]q`"#K3 wz9ǓuPUfzeWL su̙Υ9tn#- %6 #Wu82N9C_95 Noy{U*[o2L**$3+#dV>'";.>hE#,8t=\ptgm:&Â)=Q f)WxF;=KG$Zm{:Y8E&טfQZݒ&K 9gKw~It%>^W ,S moKVtЮkӶc5KA0s p6~qa& \)E l&dAt-7vz؊Y@/a6+l%a%{jGyVX4t27feEn ̗A1ZӸxUv $S) 2 x+ɌG=v F;w`}i1!D{Ƚh d CE.O@MʌJ}f2'hAs^f!% Hŏ=C-a!(/}, KoV 3V-vr[,"mfѨW|GYk^Oߖ_U^!cЧR:zlAx=k;Gf#q#,.,ٖ W^؍C"`4Xh|j WFM4]@Ht66 -ƛ [4m!'Pܽ?)~Qxk7^}qwQ9 Ze/+uȕ:-r-BvS"`YVP̙KG1gDZR4 - Z\eYء[׊ w{ zSr&Ǿtl u#JJ,+H#w*64/_Dbx‹&'&x9#C)&1 p9jCmQcYsF;7sW$j**ɪmD#SI\L" VxI Mn!~5pun"Eܾx]JVYԬYwV~ЩρZEiK Y1]+mn LO>j3AWeG |B$11U%FM "q.0To f8ު6ثL{37]srS+ SN'f8Kdh'| iVvX؆MѮ,E s#]/>YblEѸ t@{?l; AE=d}$EJqI,f&r7/*pkB,+Yaժ@y\< vnY3~9giX<|xa&G݅V?QC1ɷ*FbAOۃm6rHCMT(xxO/ήIzSɮW8z˴Eb"=dXԓtƻ6C\pfU34?ۃlj# ^A>޿K9o`>}m_ߋ ;r4FFlٛǬEpXXC}cWl*`z=Dmg=78[+:k1; > kkvjpQvua-fwØЉSRά->$R(JcOts?A<HtX0@k"gniH/zM>?w0lXE '׸Mu\Q{pS%qGp'P@&JLРΥ]7nY9ޜ@N7lD<.s^Rlql}BXh%󮱹k<i-rC s8WU:_JND&i]LlIM)teuѲT'U Ls%CƱal/y51p}tO|mIc?[`wd-nxm!x"rA+ߌGqU0,e[JTF5̟B..Xr0ļ]R "G}F ذLؔ|O : Qʹ$DPH~tʿbjkE_xv!z٣yk?'m.CsPʉ]8 qǪZyP{뤽x9f%qQ<78ӛԍkDwY2YNARN,AQC]HvdjZ `4p zcjg*@:)׏Kܕ Ob}A~RU|7R$֠=o}NB iKaN<2TRS[z'&< xo9`.e8՞'o-)z <ᯱ-/MC0__F^ z:SeOβ?),h+o0^C&_h dҚĈL5,IDgϊJ?c֚R1zERX(-^i.8WWiVYM9uu>X$Rdr:ₒ.iT׋. w]T!ċRmLO*ThYQ3 Uf$DD61mwkn|!)hQ<}B/4r^hoh=-keD߾悓p? B474Ù*dspBM;ϩW7v/o_Z띨|X62bem`3"~ISmϑv;ѩnBK%>R Woڵn:2t?p6)?!nE41`zP|Nw0)n HM{0gG@FJ/ -&v>{̽tj? nv"&n;=Mz%XKT& qϦF>LM7)|Y+t)(E=Goc/t< g7斊^g;$GOXy^Zw'n35n\F Q Tn9c6dˡkZ2jWAFjdjԎ5PߡU|(ehioib17ڲL ׂLG|AUj(R7-l*6oNj3i&y^QJ|=hAsoIak*P󨿀a3)M*& b9ĆNۀ יZT58|+S5 6o׀N=kgx| fr_'IeQ()-WXd[GHGُ|L348g7I'c+E⭼ /гc삳_OX_!(}Kh2,cGewU{gFi>a?F o` \5eSF4/Zg=`"M&1` o`3d?ːT5}-3j4nrLl'u9cd\ErD3R4ƹ3)v,7ٯ{Cvڗl)ps$s^ d!"x`i))S{=!2Tg.֮_e5 Sr75A )>},S&EQ7g\L~ u]Fh[ڊipFiՈR y(#dqI.tx~A:0+d ĝ;U\3OJC\qfh?jZo)D|T6hGmyvQNZh^6hyx]Vv4&wieWyٕ;0 퐱=5B%Y ">)O,܈ |▰_CM*)[BK*W :a;?V!c]nO/a_"kf#dz'2m мǼ>ξT"L:9W"={y}#&8/?N}ȫπV oc 3:{>t tؤd; RRS3<0zVCy;kF?^`nU{{Q2orevLW=e"淤D\[#e{9[+s?}أyz}8Y"'Ȩ2xCbHbZt W 'ZS {v5W/bgG%4_`0$Nn0Lm6OJs;X4֌k`O5#SMe A{/IZ4$wgYGI} [{( %Hq;tv-a1zRb?Wj[%)H`v߹>֠"2rv`_go90O2/žJd/w[}.5 IKyT*$Gg? Nkи?I'l7b@rtD5j̵?g~*IW@KA/bfK*Ԓrz*E+D\ۛhKGsm6b(}}>=T/'OKn}}^`1 sL5{B;󺈙a5F/Cۚ5a{и=G %#bH).0P*Z_f;d@ SP Uhdb$z) RSGa-0 :Sp]tڱTL5H)vez bae?9j\Ȧ7 2|&C׬ Pd|{^sa5M1vImOLjdSxX6H*U~,ZR*+탆 ![tƒ:;an)3nEab=yzͭ9W6Pvm<@Ϧ7fzbc?(.Nb!HgT$F: 2\\sKC('P~\鈖: p;vhXgenf"D{2^B{o!9 aާ]܌I9oPٜ)g>c&zL90O*f !fc۔Hr o.񂦦rʄ߸Ξe,O l!C)}ΐ޵`4[žYhIWL3vj;R:Ņe ڼvs<*\bFS?+c15S.G7 a% ~O?>G=XHμBCV#7=_/OYM:Fm+>mT+3Ҕ ^;:N/XPɵA_Z˕$WVz=q^΍JZRv^?Y?cH!9c7q "g%mڊﮝY66lٱZl1T*.ϯrUZZMƼVohYV x{0vixvfZzv!d2캙RކN\4m1>1AHlqOf$%LeUU^nYdp}zmp:͖J&] ?\>FkT6 Ȝk7 v /2:Fx1)i+ B@n>gbvEg:1v#M]AhM~XKhJv1mUgιZe-Ydɶ;NL I P({JZFBiJ)(ZF(?JĶ==yyjkaINv?cx} \۳02jVhZ i;Cmih.ǘls my|>%mԶ>A-ajP[/j=1b6;K沧pzXh:}3{<ϻJomz,җF!b!ub>ƸNJ #dl,aRnc)_cHfSB'-NÊeGu0\Ext+KN$lFJxn sxݜ>5X~0ҧ^xr]C _F[v02_Mx̄le'Nb2wF(}/v'0bnw' in?sxDG>8'?f/A Ǝ?SH'ֆ oh4n1_; >88r=7ހ Oq?D\yMinREP&)M2B録]ʹي9޽ 6٥5=D?\5 %qd3jqӉPO,^p=K ‘mÃ#@]a`i3'x;)X*Z  l_& yz3{;ϡwP9y;nwm{x`$8f)0k=~q T5A'd7>o0~S|$0$g3 ,I9)ewsks#.{;?6C`_$ר4Gmnт\}*8^c{iEe>Y<&Vwl:RX`ִwUz᫑ڌh hz }|XkdhvpSDvcO#z00/Z3}fE^%bo9pp-=46ځKh%TG@,o8-k˱O@ӽzeנi4e.ƎxxFe&߰b411j&Gdx&^?KvXx[fdNl6xؚ>l^HKQǦH{GͶ'/[C!cْ 6YekG3%@O'5oZ4ƞk=R8IFx-)o6X<~{pn!^Eϝ'ץPI$2:1>/PZ Tk&W+۠`/hKM,SZ\cd߂,It 9YzO DcM7Wc$='ÐO<e*S%P#{5O Zw:o$E Z"1'./Wn}hbb=V_'Dz55mtM>>ZP9J!pyPEN hnAׁ~uu`Whe&~LbN=3R6 s-#=rۡmmkIjRkڔyGŠWXmv H:g'h#|Ab+UBrS3.[VnOEmřIڌRWQ3e[c %KlM6+mM ]S7;6T=*L[N⺻q-(S J}DwBfU "J}Ǩ$U1ȡ/$eZ3t۳26wo_UF/'nszXrH,!S\:vl8+3£uYr[YKmf1ŗk$Gɚ<6! Z] ^`Yg(Kfl:d^a7mIX@b+ɲEI"Qulehf҆S1Ak~'ի( Ǔ4f Äe_ ^rN:*MZdD$JMnk.7%ٲ{~I|?fiK[2Y0;*K|q 5O ;Ó(9$aq#rozCpXWS 4j 5:G̹ wyw/*eY&l]wp>RX2 qdaݽ?/˗׮RmijmmOۂ]NJ6/۵u!+%/R859E!EHh1#oRzؗ0ᯚ)Gp)Dx9`])OֻJ[V/V:-HٷZME|Yߴ=W,mξgu[Uc4}mvVpA^_nxK{ܰ :=v9*Ӹip@^s;|8z8_K6stw r|*p3@+@Ԁ_mYz7PȂʼBcTͪ5TB-y_ݔ(Re}šYF4O#c.$ /Ѳ sUJiGR*KBa#]|WvN¤MI-0BFW irs$C??5f7nq솦^h| ,ގelW/%u %9/5,]"TXSJBn+1;34oq)S[|Jש>#KNaCjMg"Z:AtuY`i.qUS[uUu.X0hs)2**f9oq]|N*"pJ/ Sѓscڟ#u&oh#bv0[n>NbDk \ɧLe)b4/f+GG;/.yĕgiF{lv]?2)=˄0f?Vr5G=tSJ6;*J2RMr޲+3S΄ޠE;{222 r/$,*ޚi` *9ޢk~}Me8Zލha XնRi(ͻڝO Zi9*!VUq(#Խ\٩([[ԇUEYtWm ){5&uLjbk*M]2B̀!|'V´Ҝng%9Gf[,mVѠot' ߹}^AЁ[Ts-_LecYʢL֣]R.Zzq=Qߘ@.\qt,r-󮌄o2k]c.\PeQΘC ![nLoגtHk}v0C$N-6m}*}]5|` ,,MTh}#!Q,)(rWrg99;c塕Jc39ڙU.u57hd챸|p/E\Þnmf~mm0^sh1Z:i#݃Kxq:)$.;PKtX\0{\ _tY|,sjEqYs5ߺ5i{WqYc e蛖iuht}T}Ⱦ%[Hv) \&D*CMUFe+BQ6ԤeF,yo˭d9e1^L2!;eRmll+]_0VfBΜEΜꞢ,歼\iXcH3,:gn-]XtkҽJk@Os" WI2kvMVάPQw׎v>(fw?i'szD$\:`m4$wݴҍ6|(8ER0x>]TRZOouUZkH6V,o迹yKмpMͲID_@vv;h V>pM({J GLr:Kf@F";=Z푦JmHI u\wG|Fx䚤k ygؐJ*_fr?Xa->3CeOYX5Ӧ&բyX܊g.36$[>wossIިwܙ]?KU7֭VX,0g݂#+|YO4K˽26KM.k&⠉*_*& !,zd4"]WIׇה 2svƼ:Ya5>G3 N ObsH.C(">4#7nmEƛg-ejaP"՘%-Yj{p֩O`MOy}JH5iB|XJ$wjbI+xoyn#YhInrW6#T]2nmn8Bƫf ,)幸RձuPV3ݲq~]4qEG@j?}[3*5LdJ'F!I32Q`4|zHx=0)a3^8=sji9XoG:K6u68`a_gqs@:`3>g<31up7\,z^>;Q. q}!8l=f2y;&NB^@He!Ro^A2砾ə}\~z~]5{'C$*SL|okb_4:y]s@};oi(\*1?F0Q: P%YclO/x$VY|h ?HdsOwf'7={;9z;yyB}$+H'Br08|( M8asm,ΰnے&`Tjg/ljV|Ǝ)b54bǃF 83md;C(d\ q/zO2o*@.<6t)'x $~ G璳fBD9nW?E~*-oJ(*~5gcwup7})$&@8DhŞ=蕂 䓓 ^fǃF44悻{] Hku~V~ȃFѹIp/i\/0[U4q{6,:@SMJe"bI,b^/Uji6xe.s#"RM!KIvc^ر4o`[?PzK+w`9ʬ.( ϪJAW!RL!X %+Nm+O7U. c? F ;N:Լ-8hC1V qa"L׭Ÿ"p|/N.$5~%a jVd^̫|g GGE 2O FT@(NGj o@8{_=uVTzVNY+[O2U86.G?N_sq >:0e.@㋔*yO VXu[xçF$4XGp Ɵ_  ov!ܬ%gޜߕ 9-u¯0U"AJqѬ1`F O-[ e#=m\eN]Np܉V.'!b֪ٛ]2V*'{8 ML aY4H$>8Xx7{/jO|-BMCĦx;X% g?z+N 8S=-XTRKޣG׺Q4׏{Ō46~V> ˊJ&]'@frE%ƅZ47464T wFŵ׻M:4j0Ϗ!y/wWc.< c0J'{96 H"̮$6A ^i1{1/!'(3j2td+8{{2LP^A,269hl+Ƚo'2S7>x R/hc|vt${9N[~ u-H3 ? $Wאנ*Dk`rGj9P)z=ۇv1&p}pcr4š 6AGǐTOl~HwN8k/%p`#WwBϸ}1cxnޱϣ^`3π0Ю}µ^-K/ڋ4aJasĕ⽟ 1޺ʣ M^MQ펾6M(2QZ_/Zz` ]}{S~MЛl+&b2!S,Zq-R/tH_NIM`r7& ଦνf0Ʈg:h K_[Q]|pOspdAV9)yM)3?xn@<|_^o9g\bV.k,H 7=d>W&Z`1أ{x7ρD^rCu}gJ,'Enq 5)=hd_EWVjsjOiį|na b~o"n!?BB<1} HnДHs%l)Zz1zv&_ȳx"HPJ`4qKW.3nNIDvI[#s *[Q^ Y=ϣX4:2cY"s_F2[2mſo _JOd";xc15b#MuKxn|ѵ  "QX-2;Eh÷0K4 "A|و|]fP=2kt9lr/{7e }<5Ӥ#(Lk3_%?lLČ.Eh}MlgBr X(PjTu_[޷7zj%3>5-* ڴ#/T#3ǠZ&$߀5?pez>bad՟7;,QVwabVlhMˢfyf/lD'@ߛ*s`֮cL6)\5VWfWZt%zӚ%w{j)/QyxJpN3bw6cV9ETAek`D(j"tՆKOU޼7Eܝyea;=|u=^}T"S)2!RA50R&\g%3S[=X[?d-4*Yb. CT-ʬF2mwlmcvaҨ:͋w0bfR[|V&~ ' ?a `k[g^r ~n6w%*{$ojɅ xw>֧{AN"7Tmhav}W w}9~_C\>-8>.5Lم~|}; u+MKLf{ !K5_|mhDЯg)&BP䉎I{w5Fҍ qaTgILsS]ӛJD>\8է"%V:33KKi%ۧ@{-5- 1@ަ)eJofCɟl{KOyr+?j)]r&TVM x զE]lsLeˌΆks,Dsu #G2lbdxjz[266g:_vPu9fAua#>1RniTר4laji͖5xc-ET9fh1sm}6ڼb`S5hF2+X0Y ;ؚX'kRݩ'[$)k(-M#Μ145XL/ǶaܠSm=G:c̏az#d םEJ_g?SJ 3?$T=54D#!t/y٤&p^RSy;H6:h "rYjx[]}j[:SlQӴѵp uk%g5XY Ιj{:aa\?={^_G1VpKբڞkEÞaOS zҡayxbqN\nzZ.H#Jß " >eRov,]nHK W.j.I/[zaGǫ9V%) ec>Q"59O^w`x_C +O6-ќuX$=a*OsWRt~Jzkt+ fs8[Ad&D9ۻ_,,AYKLMKGu'gSz-T0@rs $n >r q}^uh)'2i"!<[H$ L ]&24h.)qu_h6ߊ2.3XM{Ju: sBD#w )ņ۞rabkv(,E8Wa0bidgB8+b)[ \/sӡdV-nkrحLwX,+7&X^IJ*nq<ȗH|ɐ2v(v' ^s0'C`I,(?~}6e'f)7O.@ E]fY,fv8F-} n-NbՒQ--MkB9ҟ?/rJed\G È7&"?G9m 2!3_N ~x&N$2Lb( {Yl&Zɸf(AN ' :w?EA8mZӠ*%ho5 Roc![pU~{`n?x_{mT/M9/Z30p#yl{ EՉ3SH!9g`C -FT|__\-?tG [Pn؄C},}1ga' ;?~uO8:CwL㜜4a?lst"}I49ػ aN[h, _N;}H+'o ^| ~IE AxPr-yq%ˏϲLO#яyo ˄6P) e~Ab{ ?|g<<@` sMݕ-d ??? ( ]zix6a^򃕛K:5}%CC,XwSZWWhEc!:hR0:AK!Iy#޳s ?`5X2ΎWΒy2k:/KV$u( 0Sc:.!$0f~CKMp{G5\|#Osx}#ßzU0S\[zs';ui?ceF6<+2|#=7'ͭON?_>?Ni.?9js=oOܴr3d\&N_xȴ{|ׯи/}M~UyW8%i37P;aS?>16HbOBemdj'4PB}$U63؎"0tMq!lj'+ǟy#2E;U;ƒ3Wp<} .((bX,k5- e',EOzܪ <+.%9_nۢ2,gfYdڼQT!:+26hNaJr6A.ohϳ [o^ԙMGhᙬ<݀LyٙgKz6Xk xܙk Ti dXcG{d0._y;+Ieq"9`MF L>#/o7 2{sǯ&ݞ"1'WxXB"#a OyN nM۹g0̣#&eݢ",(夐L׫cgICDC'33rSL>oAd4?St8s ; Z%Pz#b~cs%wKiRm\_5k僜;gMZzBCJZVd]8=3{7xhȠH,X>\u~vGS}lo%2޶Ʌ?esDt:9|ZB8M8r((WVbZKg7,.] ?OIϬ6P{{|ڸ24CgEY GڳUII{Ύhǵ9$<ػIyk,;7nyUL٥aKm2.cvc֣Kt䖄A8|Tl_mXtԘ;Y?787')^[oml0ڈQ\9;d 0Z>08m" Èt; yBlUrUSVo|ËI.#c@t )f޵kimBf?\Hr4/4{S" %~- #hٴÿu:|^*eD<.Ц{M\^B+y|X?t)"~X:O7WvNN#HwN"m 6Ef[oa׍MP]2s?/ؿ9;:MS#XM&8RYZ㳦ߥ(K7=#=ȵW_+Ͼx09d ̮4zYg~^fB`R|fQ^D>}ĤeXĺF5lV&2]U7ul.6,ܷ$ Ʊt|鱷U?& SzM[OzZmLS%Uz`߇_>e]7h]QO\D$_Y |oq"yLl\h2VO;U);}֒i]a_jv.72oAԄ{].Q TePN-QǸXmkmxͼbFpS9 4HA6kmnYCO 5-9j?&ɾ|Ԁ_+^R{2q M+$315$l$w¸ .{r E\jaYHm͛,jC+*ȏ+On_=&JVLț;j~*94ZC$Y>Je֥J^?f ,z\ 3˥)s}  "e|0IXWtv2N%umsʸ]92X!%0p _TC0a'w,V OMFځUMΓNPlJRuwW=yQ*[M -/tkN}_a.Y %SFQrn#s{cuqChB'w" mc!.I Z:m̎ H4H}"?}j$kR[ 2l29S!iV)cV.|۔j%z'gt6nVz1WrX5!?1$zg1vMS.W)^P6~mq`\ t>S8R=qMxv-zk"F9_t+-HHVQ7IIUEF޿F{`᜔-+{ō% zr9hq^d,GZ}j"MW^6^(ɓɲP:.g߿.)JeW@OIR*ͶlCuMyky?G$.?%mn7I(I݉Uco Ysd0 &e K) 9)`u}ƦCY zk=f8db؏6)JN23 ʼfk%k0-@=cV!$:MCuiIH}|8c`j݇=s*/`96u \<0bii/wB8ھ|FSN~77uҢ:W$Ӥ |ꪞwh#xK~auLk99{pFhOϕ4&{~}e_e@yEWs%^86R.f- K;֏tw6qWF^+zK2] )>geWckeIk^unڛLHEDNLlD |1;e*Rͤԁ-r`vBwK3+G|v|C4ֻ1T&"- /sh%y{ͩ)vU<Ð#w?q[=Un%)f%c M87H1a$/.A:LgNܻ Nk8ǽNi舘RS EMsamEz3[q`Ed:*DPUFvh]P#(<=ί$ ҲzF#>+:4DP- g⏯(rմRݣNk-ܿqdP˯1E>Дo)5.5s% &eI!_fIMB0`&BՃћ3ZWsVtIy*4W(HK;=r{ϲ n,cqk !ث8O4*i['.3ѣFD(<޲v-IpIP'?5#ŷ{PQ3 W0RuԠߠQRAD Ci%G`_.h_sY*Bz\]$ffnf׈2i"Kh (jq + _UÖ␭('k2sIDO YROT yAKTںY%!`ͩ ),xj+8*/ ws M 7h=ЫdM MV AFM&V`AYg:gO+ST{r paY>_8O-3)YEmsz\IYj*3uY=|EU]%ťW%its'‘0Dפi[BnvxZt-͊f11ڗ~W]+Z\-ذҥ5% ӜUnm9P (KSEIh7(x_ۘ.\u(҅ ʊW̭{KV|ˍ IZcX6׿b)>SlBϤOjL3gCKڎ=o4q)ɭ̭O?#X 8N!ڝt<qSFT6. 4Mo ¬י"+١]rX,6en2v^ 4,qb7 (vxE[?zF\bM~4*ǭ!q{<9%- #u}0z~*%X3yqɊdv);%pfpsk>(Ԯ큃r&>c5!K}- p{Rwa19,o$LlWYn,Y(1g#Ib!_21Oi"CJ,rC'U˭(r<ˠв;7B *9q#e&GqN#>EX! CO u. 9IyE9nwo5\,w͔7AU\#.f<:uw7^-E2qmH(4H0b`T%l`Ƀ@){ %ȋ}HWz WgK80+޽P6{Vw=22 -#zRRdIHkQ^lݮy)L-䪎,ۛػ iDjDꍋ>{**$Z # E qΰ'ߔٴKTy{j=b0}9Zk"ą(< bU4̯|4l2$ 9m4S*jZypWMuHL_QH{+?t#-Eߒ`t):K:;'Q6:Ji_h<$Ѽ;{zRI'j?\xjS_[?/Gл:]N:f= /ţnG?zd"8هјR:<&z<%O{Ge-&zDуˣI L,k$~^s!Ɗ $ĕ&/ދ'2ō1w2Ws~]b`6 ϰOQ,nDR' w@I [pnw6rVjǴ