t in unicode } $unicode = $this->UTF8StringToArray($str); // array containing UTF-8 unicode values return $this->arrUTF8ToUTF16BE($unicode, $setbom); } /** * 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 array $unicode array containing UTF-8 unicode values * @param boolean $setbom if true set the Byte Order Mark (BOM = 0xFEFF) * @return string * @access protected * @author Nicola Asuni * @since 2.1.000 (2008-01-08) * @see UTF8ToUTF16BE() */ function arrUTF8ToUTF16BE($unicode, $setbom=true) { $outstr = ""; // string to be returned if ($setbom) { $outstr .= "\xFE\xFF"; // Byte Order Mark (BOM) } foreach($unicode as $char) { if($char == 0xFFFD) { $outstr .= "\xFF\xFD"; // replacement character } elseif ($char < 0x10000) { $outstr .= chr($char >> 0x08); $outstr .= chr($char & 0xFF); } else { $char -= 0x10000; $w1 = 0xD800 | ($char >> 0x10); $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 array $font font * @since 1.1 */ function setHeaderFont($font) { $this->header_font = $font; } /** * Set footer font. * @param array $font font * @since 1.1 */ function setFooterFont($font) { $this->footer_font = $font; } /** * Set language array. * @param array $language * @since 1.1 */ function setLanguageArray($language) { $this->l = $language; $this->rtl = $this->l['a_meta_dir']=='rtl' ? true : false; } /** * Set document barcode. * @param string $bc barcode */ function setBarcode($bc="") { $this->barcode = $bc; } /** * Print Barcode. * @param int $x x position in user units * @param int $y y position in user units * @param int $w width in user units * @param int $h height position in user units * @param string $type type of barcode (I25, C128A, C128B, C128C, C39) * @param string $style barcode style * @param string $font font for text * @param int $xres x resolution * @param string $code code to print */ function writeBarcode($x, $y, $w, $h, $type, $style, $font, $xres, $code) { require_once(dirname(__FILE__)."/barcode/barcode.php"); require_once(dirname(__FILE__)."/barcode/i25object.php"); require_once(dirname(__FILE__)."/barcode/c39object.php"); require_once(dirname(__FILE__)."/barcode/c128aobject.php"); require_once(dirname(__FILE__)."/barcode/c128bobject.php"); require_once(dirname(__FILE__)."/barcode/c128cobject.php"); if (empty($code)) { return; } if (empty($style)) { $style = BCS_ALIGN_LEFT; $style |= BCS_IMAGE_PNG; $style |= BCS_TRANSPARENT; //$style |= BCS_BORDER; //$style |= BCS_DRAW_TEXT; //$style |= BCS_STRETCH_TEXT; //$style |= BCS_REVERSE_COLOR; } if (empty($font)) {$font = BCD_DEFAULT_FONT;} if (empty($xres)) {$xres = BCD_DEFAULT_XRES;} $scale_factor = 1.5 * $xres * $this->k; $bc_w = round($w * $scale_factor); //width in points $bc_h = round($h * $scale_factor); //height in points switch (strtoupper($type)) { case "I25": { $obj = new I25Object($bc_w, $bc_h, $style, $code); break; } case "C128A": { $obj = new C128AObject($bc_w, $bc_h, $style, $code); break; } default: case "C128B": { $obj = new C128BObject($bc_w, $bc_h, $style, $code); break; } case "C128C": { $obj = new C128CObject($bc_w, $bc_h, $style, $code); break; } case "C39": { $obj = new C39Object($bc_w, $bc_h, $style, $code); break; } } $obj->SetFont($font); $obj->DrawObject($xres); //use a temporary file.... $tmpName = tempnam(K_PATH_CACHE,'img'); imagepng($obj->getImage(), $tmpName); $this->Image($tmpName, $x, $y, $w, $h, 'png'); $obj->DestroyObject(); unset($obj); unlink($tmpName); } /** * Returns the PDF data. */ function getPDFData() { if($this->state < 3) { $this->Close(); } return $this->buffer; } // --- HTML PARSER FUNCTIONS --- /** * Allows to preserve some HTML formatting.
* Supports: h1, h2, h3, h4, h5, h6, b, u, i, a, img, p, br, strong, em, font, blockquote, li, ul, ol, hr, td, th, tr, table, sup, sub, small * @param string $html text to display * @param boolean $ln if true add a new line after text (default = true) * @param int $fill Indicates if the background must be painted (1) or transparent (0). Default value: 0. * @param boolean $reseth if true reset the last cell height (default false). * @param boolean $cell if true add the default cMargin space to each Write (default false). */ function writeHTML($html, $ln=true, $fill=0, $reseth=false, $cell=false) { // store some variables $html=strip_tags($html,"




      1. "); //remove all unsupported tags //replace carriage returns, newlines and tabs $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " "); $html = strtr($html, $repTable); $pattern = '/(<[^>]+>)/Uu'; $a = preg_split($pattern, $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); //explodes the string if ((empty($this->lasth))OR ($reseth)) { //set row height $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; } foreach($a as $key=>$element) { if (!preg_match($pattern, $element)) { //Text if($this->HREF) { $this->addHtmlLink($this->HREF, $element, $fill); } elseif($this->tdbegin) { if((strlen(trim($element)) > 0) AND ($element != " ")) { $this->Cell($this->tdwidth, $this->tdheight, $this->unhtmlentities($element), $this->tableborder, '', $this->tdalign, $this->tdbgcolor); } elseif($element == " ") { $this->Cell($this->tdwidth, $this->tdheight, '', $this->tableborder, '', $this->tdalign, $this->tdbgcolor); } } else { $ctmpmargin = $this->cMargin; if(!$cell) { $this->cMargin = 0; } $this->Write($this->lasth, stripslashes($this->unhtmlentities($element)), '', $fill, '', false, 0); $this->cMargin = $ctmpmargin; } } else { $element = substr($element, 1, -1); //Tag if($element{0}=='/') { $this->closedHTMLTagHandler(strtolower(substr($element, 1))); } else { //Extract attributes // get tag name preg_match('/([a-zA-Z0-9]*)/', $element, $tag); $tag = strtolower($tag[0]); // get attributes preg_match_all('/([^=\s]*)=["\']?([^"\']*)["\']?/', $element, $attr_array, PREG_PATTERN_ORDER); $attr = array(); // reset attribute array while(list($id,$name)=each($attr_array[1])) { $attr[strtolower($name)] = $attr_array[2][$id]; } $this->openHTMLTagHandler($tag, $attr, $fill); } } } if ($ln) { $this->Ln($this->lasth); } } /** * 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 float $w Cell width. If 0, the cell extends up to the right margin. * @param float $h Cell minimum height. The cell extends automatically if needed. * @param float $x upper-left corner X coordinate * @param float $y upper-left corner Y coordinate * @param string $html html text to print. Default value: empty string. * @param mixed $border Indicates if borders must be drawn around the cell. The value can be either 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
        * @param int $ln 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 int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0. * @param boolean $reseth if true reset the last cell height (default true). * @see Cell() */ function writeHTMLCell($w, $h, $x, $y, $html='', $border=0, $ln=0, $fill=0, $reseth=true) { if ((empty($this->lasth))OR ($reseth)) { //set row height $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; } // get current page number $startpage = $this->page; if (!empty($y)) { $this->SetY($y); } else { $y = $this->GetY(); } if (!empty($x)) { $this->SetX($x); } else { $x = $this->GetX(); } if(empty($w)) { if ($this->rtl) { $w = $this->x - $this->lMargin; } else { $w = $this->w - $this->rMargin - $this->x; } } // store original margin values $lMargin = $this->lMargin; $rMargin = $this->rMargin; // set new margin values if ($this->rtl) { $this->SetLeftMargin($this->x - $w); $this->SetRightMargin($this->w - $this->x); } else { $this->SetLeftMargin($this->x); $this->SetRightMargin($this->w - $this->x - $w); } // calculate remaining vertical space on first page ($startpage) $restspace = $this->getPageHeight() - $this->GetY() - $this->getBreakMargin(); // Write HTML text $this->writeHTML($html, true, $fill, $reseth, true); // Get end-of-text Y position $currentY = $this->GetY(); // get latest page number $endpage = $this->page; if (!empty($border)) { // check if a new page has been created if ($endpage > $startpage) { // design borders around HTML cells. for ($page=$startpage; $page<=$endpage; $page++) { $this->page = $page; if ($page==$startpage) { $this->SetY($this->getPageHeight() - $restspace - $this->getBreakMargin()); $h = $restspace - 1; } elseif ($page==$endpage) { $this->SetY($this->tMargin); // put cursor at the beginning of text $h = $currentY - $this->tMargin; } else { $this->SetY($this->tMargin); // put cursor at the beginning of text $h = $this->getPageHeight() - $this->tMargin - $this->getBreakMargin(); } $this->SetX($x); $this->Cell($w, $h, "", $border, 1, '', 0); } } else { $h = max($h, ($currentY - $y)); $this->SetY($y); // put cursor at the beginning of text $this->SetX($x); // design a cell around the text $this->Cell($w, $h, "", $border, 1, '', 0); } } // restore original margin values $this->SetLeftMargin($lMargin); $this->SetRightMargin($rMargin); if($ln>0) { //Go to the beginning of the next line $this->SetY($currentY); if($ln == 2) { $this->SetX($x + $w); } } else { // go left or right by case $this->page = $startpage; $this->y = $y; $this->SetX($x + $w); } } /** * Process opening tags. * @param string $tag tag name (in uppercase) * @param string $attr tag attribute (in uppercase) * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0. * @access private */ function openHTMLTagHandler($tag, $attr, $fill=0) { // check for text direction attribute if (isset($attr['dir'])) { $this->tmprtl = $attr['dir']=='rtl' ? 'R' : 'L'; } else { $this->tmprtl = false; } //Opening tag switch($tag) { case 'table': { if ((isset($attr['border'])) AND ($attr['border'] != '')) { $this->tableborder = $attr['border']; } else { $this->tableborder = 0; } break; } case 'tr': { break; } case 'td': case 'th': { if ((isset($attr['width'])) AND ($attr['width'] != '')) { $this->tdwidth = ($attr['width']/4); } else { $this->tdwidth = (($this->w - $this->lMargin - $this->rMargin) / $this->default_table_columns); } if ((isset($attr['height'])) AND ($attr['height'] != '')) { $this->tdheight=($attr['height'] / $this->k); } else { $this->tdheight = $this->lasth; } if ((isset($attr['align'])) AND ($attr['align'] != '')) { switch ($attr['align']) { case 'center': { $this->tdalign = "C"; break; } case 'right': { $this->tdalign = "R"; break; } default: case 'left': { $this->tdalign = "L"; break; } } } else { if($this->rtl) { $this->tdalign = "R"; } else { $this->tdalign = "L"; } } if ((isset($attr['bgcolor'])) AND ($attr['bgcolor'] != '')) { $coul = $this->convertColorHexToDec($attr['bgcolor']); $this->SetFillColor($coul['R'], $coul['G'], $coul['B']); $this->tdbgcolor=true; } $this->tdbegin=true; break; } case 'hr': { $this->Ln(); if ((isset($attr['width'])) AND ($attr['width'] != '')) { $hrWidth = $attr['width']; } else { $hrWidth = $this->w - $this->lMargin - $this->rMargin; } $x = $this->GetX(); $y = $this->GetY(); $this->GetLineWidth(); $prevlinewidth = $this->SetLineWidth(0.2); $this->Line($x, $y, $x + $hrWidth, $y); $this->SetLineWidth($prevlinewidth); $this->Ln(); break; } case 'strong': { $this->setStyle('b', true); break; } case 'em': { $this->setStyle('i', true); break; } case 'b': case 'i': case 'u': { $this->setStyle($tag, true); break; } case 'a': { $this->HREF = $attr['href']; break; } case 'img': { if(isset($attr['src'])) { // replace relative path with real server path if ($attr['src'][0] == '/') { $attr['src'] = $_SERVER['DOCUMENT_ROOT'].$attr['src']; } $attr['src'] = str_replace(K_PATH_URL, K_PATH_MAIN, $attr['src']); if(!isset($attr['width'])) { $attr['width'] = 0; } if(!isset($attr['height'])) { $attr['height'] = 0; } if(!isset($attr['align'])) { $align = 'N'; } else { switch($attr['align']) { case 'top':{ $align = 'T'; break; } case 'middle':{ $align = 'M'; break; } case 'bottom':{ $align = 'B'; break; } default:{ $align = 'N'; break; } } } $this->Image($attr['src'], $this->GetX(),$this->GetY(), $this->pixelsToMillimeters($attr['width']), $this->pixelsToMillimeters($attr['height']), '', '', $align); } break; } case 'ul': { $this->listordered = false; $this->listcount = 0; break; } case 'ol': { $this->listordered = true; $this->listcount = 0; break; } case 'li': { $this->Ln(); if ($this->listordered) { if (isset($attr['value'])) { $this->listcount = intval($attr['value']); } $this->lispacer = " ".(++$this->listcount).". "; } else { //unordered list simbol $this->lispacer = " - "; } $rtldir = $this->tmprtl; $this->tmprtl = false; $this->Write($this->lasth, $this->lispacer, '', $fill, '', false, 0); $this->tmprtl = $rtldir; break; } case 'blockquote': case 'br': { $this->Ln(); if(strlen($this->lispacer) > 0) { if ($this->rtl) { $this->x -= $this->GetStringWidth($this->lispacer); } else { $this->x += $this->GetStringWidth($this->lispacer); } } break; } case 'p': { $this->Ln(); $this->Ln(); break; } case 'sup': { $currentFontSize = $this->FontSize; $this->tempfontsize = $this->FontSizePt; $this->SetFontSize($this->FontSizePt * K_SMALL_RATIO); $this->SetXY($this->GetX(), $this->GetY() - (($currentFontSize - $this->FontSize)*(K_SMALL_RATIO))); break; } case 'sub': { $currentFontSize = $this->FontSize; $this->tempfontsize = $this->FontSizePt; $this->SetFontSize($this->FontSizePt * K_SMALL_RATIO); $this->SetXY($this->GetX(), $this->GetY() + (($currentFontSize - $this->FontSize)*(K_SMALL_RATIO))); break; } case 'small': { $currentFontSize = $this->FontSize; $this->tempfontsize = $this->FontSizePt; $this->SetFontSize($this->FontSizePt * K_SMALL_RATIO); $this->SetXY($this->GetX(), $this->GetY() + (($currentFontSize - $this->FontSize)/3)); break; } case 'font': { if (isset($attr['color']) AND $attr['color']!='') { $coul = $this->convertColorHexToDec($attr['color']); $this->SetTextColor($coul['R'],$coul['G'],$coul['B']); $this->issetcolor=true; } if (isset($attr['face']) and in_array(strtolower($attr['face']), $this->fontlist)) { $this->SetFont(strtolower($attr['face'])); $this->issetfont=true; } if (isset($attr['size'])) { $headsize = intval($attr['size']); } else { $headsize = 0; } $currentFontSize = $this->FontSize; $this->tempfontsize = $this->FontSizePt; $this->SetFontSize($this->FontSizePt + $headsize); $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; break; } case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': { $headsize = (4 - substr($tag, 1)) * 2; $currentFontSize = $this->FontSize; $this->tempfontsize = $this->FontSizePt; $this->SetFontSize($this->FontSizePt + $headsize); $this->setStyle('b', true); $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; break; } } } /** * Process closing tags. * @param string $tag tag name (in uppercase) * @access private */ function closedHTMLTagHandler($tag) { //Closing tag switch($tag) { case 'td': case 'th': { $this->tdbegin = false; $this->tdwidth = 0; $this->tdheight = 0; if($this->rtl) { $this->tdalign = "R"; } else { $this->tdalign = "L"; } $this->tdbgcolor = false; $this->SetFillColor($this->prevFillColor[0], $this->prevFillColor[1], $this->prevFillColor[2]); break; } case 'tr': { $this->Ln(); break; } case 'table': { $this->tableborder=0; break; } case 'strong': { $this->setStyle('b', false); break; } case 'em': { $this->setStyle('i', false); break; } case 'b': case 'i': case 'u': { $this->setStyle($tag, false); break; } case 'a': { $this->HREF = ''; break; } case 'sup': { $currentFontSize = $this->FontSize; $this->SetFontSize($this->tempfontsize); $this->tempfontsize = $this->FontSizePt; $this->SetXY($this->GetX(), $this->GetY() - (($currentFontSize - $this->FontSize)*(K_SMALL_RATIO))); break; } case 'sub': { $currentFontSize = $this->FontSize; $this->SetFontSize($this->tempfontsize); $this->tempfontsize = $this->FontSizePt; $this->SetXY($this->GetX(), $this->GetY() + (($currentFontSize - $this->FontSize)*(K_SMALL_RATIO))); break; } case 'small': { $currentFontSize = $this->FontSize; $this->SetFontSize($this->tempfontsize); $this->tempfontsize = $this->FontSizePt; $this->SetXY($this->GetX(), $this->GetY() - (($this->FontSize - $currentFontSize)/3)); break; } case 'font': { if ($this->issetcolor == true) { $this->SetTextColor($this->prevTextColor[0], $this->prevTextColor[1], $this->prevTextColor[2]); } if ($this->issetfont) { $this->FontFamily = $this->prevFontFamily; $this->FontStyle = $this->prevFontStyle; $this->SetFont($this->FontFamily); $this->issetfont = false; } $currentFontSize = $this->FontSize; $this->SetFontSize($this->tempfontsize); $this->tempfontsize = $this->FontSizePt; //$this->TextColor = $this->prevTextColor; $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; break; } case 'p': { $this->Ln(); $this->Ln(); break; } case 'ul': case 'ol': { $this->Ln(); $this->Ln(); break; } case 'li': { $this->lispacer = ""; break; } case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': { $currentFontSize = $this->FontSize; $this->SetFontSize($this->tempfontsize); $this->tempfontsize = $this->FontSizePt; $this->setStyle('b', false); $this->Ln(); $this->lasth = $this->FontSize * K_CELL_HEIGHT_RATIO; break; } default : { break; } } $this->tmprtl = false; } /** * Sets font style. * @param string $tag tag name (in lowercase) * @param boolean $enable * @access private */ function setStyle($tag, $enable) { //Modify style and select corresponding font $this->$tag += ($enable ? 1 : -1); $style=''; foreach(array('b', 'i', 'u') as $s) { if($this->$s > 0) { $style .= $s; } } $this->SetFont('', $style); } /** * Output anchor link. * @param string $url link URL * @param string $name link name * @param int $fill Indicates if the cell background must be painted (1) or transparent (0). Default value: 0. * @access public */ function addHtmlLink($url, $name, $fill=0) { //Put a hyperlink $this->SetTextColor(0, 0, 255); $this->setStyle('u', true); $this->Write($this->lasth, $name, $url, $fill, '', false, 0); $this->setStyle('u', false); $this->SetTextColor(0); } /** * Returns an associative array (keys: R,G,B) from * a hex html code (e.g. #3FE5AA). * @param string $color hexadecimal html color [#rrggbb] * @return array * @access private */ function convertColorHexToDec($color = "#000000"){ $tbl_color = array(); $tbl_color['R'] = hexdec(substr($color, 1, 2)); $tbl_color['G'] = hexdec(substr($color, 3, 2)); $tbl_color['B'] = hexdec(substr($color, 5, 2)); return $tbl_color; } /** * Converts pixels to millimeters in 72 dpi. * @param int $px pixels * @return float millimeters * @access private */ function pixelsToMillimeters($px){ return $px * 25.4 / 72; } /** * Reverse function for htmlentities. * Convert entities in UTF-8. * * @param $text_to_convert Text to convert. * @return string converted */ function unhtmlentities($text_to_convert) { if (!$this->isunicode) { return html_entity_decode($text_to_convert); } require_once(dirname(__FILE__).'/html_entity_decode_php4.php'); return html_entity_decode_php4($text_to_convert); } // ENCRYPTION METHODS ---------------------------------- // SINCE 2.0.000 (2008-01-02) /** * Compute encryption key depending on object number where the encrypted data is stored * @param int $n object number * @since 2.0.000 (2008-01-02) */ function _objectkey($n) { return substr($this->_md5_16($this->encryption_key.pack('VXxx',$n)),0,10); } /** * Put encryption on PDF document * @since 2.0.000 (2008-01-02) */ function _putencryption() { $this->_out('/Filter /Standard'); $this->_out('/V 1'); $this->_out('/R 2'); $this->_out('/O ('.$this->_escape($this->Ovalue).')'); $this->_out('/U ('.$this->_escape($this->Uvalue).')'); $this->_out('/P '.$this->Pvalue); } /** * Returns the input text exrypted using RC4 algorithm and the specified key. * RC4 is the standard encryption algorithm used in PDF format * @param string $key encryption key * @param String $text input text to be encrypted * @return String encrypted text * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec */ function _RC4($key, $text) { if ($this->last_rc4_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_rc4_key = $key; $this->last_rc4_key_c = $rc4; } else { $rc4 = $this->last_rc4_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; } /** * Encrypts a string using MD5 and returns it's value as a binary string. * @param string $str input string * @return String MD5 encrypted binary string * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec */ function _md5_16($str) { return pack('H*',md5($str)); } /** * Compute O value (used for RC4 encryption) * @param String $user_pass user password * @param String $owner_pass user password * @return String O value * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec */ function _Ovalue($user_pass, $owner_pass) { $tmp = $this->_md5_16($owner_pass); $owner_RC4_key = substr($tmp,0,5); return $this->_RC4($owner_RC4_key, $user_pass); } /** * Compute U value (used for RC4 encryption) * @return String U value * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec */ function _Uvalue() { return $this->_RC4($this->encryption_key, $this->padding); } /** * Compute encryption key * @param String $user_pass user password * @param String $owner_pass user password * @param String $protection protection type * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec */ function _generateencryptionkey($user_pass, $owner_pass, $protection) { // Pad passwords $user_pass = substr($user_pass.$this->padding,0,32); $owner_pass = substr($owner_pass.$this->padding,0,32); // Compute O value $this->Ovalue = $this->_Ovalue($user_pass,$owner_pass); // Compute encyption key $tmp = $this->_md5_16($user_pass.$this->Ovalue.chr($protection)."\xFF\xFF\xFF"); $this->encryption_key = substr($tmp,0,5); // Compute U value $this->Uvalue = $this->_Uvalue(); // Compute P value $this->Pvalue = -(($protection^255)+1); } /** * Set document protection * The permission array is composed of values taken from the following ones: * - copy: copy text and images to the clipboard * - print: print the document * - modify: modify it (except for annotations and forms) * - annot-forms: add annotations and forms * 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 Array $permissions the set of permissions. Empty by default (only viewing is allowed). (print, modify, copy, annot-forms) * @param String $user_pass user password. Empty by default. * @param String $owner_pass owner password. If not specified, a random value is used. * @since 2.0.000 (2008-01-02) * @author Klemen Vodopivec */ function SetProtection($permissions=array(),$user_pass='',$owner_pass=null) { $options = array('print' => 4, 'modify' => 8, 'copy' => 16, 'annot-forms' => 32); $protection = 192; foreach($permissions as $permission) { if (!isset($options[$permission])) { $this->Error('Incorrect permission: '.$permission); } $protection += $options[$permission]; } if ($owner_pass === null) { $owner_pass = uniqid(rand()); } $this->encrypted = true; $this->_generateencryptionkey($user_pass, $owner_pass, $protection); } // END OF ENCRYPTION FUNCTIONS ------------------------- // START TRANSFORMATIONS SECTION ----------------------- // authors: Moritz Wagner, Andreas Wurmser, Nicola Asuni /** * 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. * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function StartTransform() { $this->_out('q'); } /** * 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. * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function StopTransform() { $this->_out('Q'); } /** * Horizontal Scaling. * @param float $s_x scaling factor for width as percent. 0 is not allowed. * @param int $x abscissa of the scaling center. Default is current x position * @param int $y ordinate of the scaling center. Default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function ScaleX($s_x, $x='', $y=''){ $this->Scale($s_x, 100, $x, $y); } /** * Vertical Scaling. * @param float $s_y scaling factor for height as percent. 0 is not allowed. * @param int $x abscissa of the scaling center. Default is current x position * @param int $y ordinate of the scaling center. Default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function ScaleY($s_y, $x='', $y=''){ $this->Scale(100, $s_y, $x, $y); } /** * Vertical and horizontal proportional Scaling. * @param float $s scaling factor for width and height as percent. 0 is not allowed. * @param int $x abscissa of the scaling center. Default is current x position * @param int $y ordinate of the scaling center. Default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function ScaleXY($s, $x='', $y=''){ $this->Scale($s, $s, $x, $y); } /** * Vertical and horizontal non-proportional Scaling. * @param float $s_x scaling factor for width as percent. 0 is not allowed. * @param float $s_y scaling factor for height as percent. 0 is not allowed. * @param int $x abscissa of the scaling center. Default is current x position * @param int $y ordinate of the scaling center. Default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function Scale($s_x, $s_y, $x='', $y=''){ if($x === '') { $x=$this->x; } if($y === '') { $y=$this->y; } if($this->rtl) { $x = $this->w - $x; } if($s_x == 0 OR $s_y == 0) $this->Error('Please use values unequal 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[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 int $x abscissa of the point. Default is current x position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function MirrorH($x=''){ $this->Scale(-100, 100, $x); } /** * Verical Mirroring. * @param int $y ordinate of the point. Default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function MirrorV($y=''){ $this->Scale(100, -100, '', $y); } /** * Point reflection mirroring. * @param int $x abscissa of the point. Default is current x position * @param int $y ordinate of the point. Default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ 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 float $angle gradient angle of the straight line. Default is 0 (horizontal line). * @param int $x abscissa of the point. Default is current x position * @param int $y ordinate of the point. Default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function MirrorL($angle=0, $x='',$y=''){ $this->Scale(-100, 100, $x, $y); $this->Rotate(-2*($angle-90),$x,$y); } /** * Translate graphic object horizontally. * @param int $t_x movement to the right * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function TranslateX($t_x){ $this->Translate($t_x, 0); } /** * Translate graphic object vertically. * @param int $t_y movement to the bottom * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function TranslateY($t_y){ $this->Translate(0, $t_y, $x, $y); } /** * Translate graphic object horizontally and vertically. * @param int $t_x movement to the right * @param int $t_y movement to the bottom * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function Translate($t_x, $t_y){ if($this->rtl) { $t_x = -$t_x; } //calculate elements of transformation matrix $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 float $angle angle in degrees for counter-clockwise rotation * @param int $x abscissa of the rotation center. Default is current x position * @param int $y ordinate of the rotation center. Default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function Rotate($angle, $x='', $y=''){ if($x === '') { $x=$this->x; } if($y === '') { $y=$this->y; } if($this->rtl) { $x = $this->w - $x; $angle = -$angle; } $y=($this->h-$y)*$this->k; $x*=$this->k; //calculate elements of transformation matrix $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 float $angle_x angle in degrees between -90 (skew to the left) and 90 (skew to the right) * @param int $x abscissa of the skewing center. default is current x position * @param int $y ordinate of the skewing center. default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function SkewX($angle_x, $x='', $y=''){ $this->Skew($angle_x, 0, $x, $y); } /** * Skew vertically. * @param float $angle_y angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) * @param int $x abscissa of the skewing center. default is current x position * @param int $y ordinate of the skewing center. default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function SkewY($angle_y, $x='', $y=''){ $this->Skew(0, $angle_y, $x, $y); } /** * Skew. * @param float $angle_x angle in degrees between -90 (skew to the left) and 90 (skew to the right) * @param float $angle_y angle in degrees between -90 (skew to the bottom) and 90 (skew to the top) * @param int $x abscissa of the skewing center. default is current x position * @param int $y ordinate of the skewing center. default is current y position * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ function Skew($angle_x, $angle_y, $x='', $y=''){ if($x === '') { $x=$this->x; } if($y === '') { $y=$this->y; } if($this->rtl) { $x = $this->w - $x; $angle_x = -$angle_x; } 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� for skewing'); $x*=$this->k; $y=($this->h-$y)*$this->k; //calculate elements of transformation matrix $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. * @since 2.1.000 (2008-01-07) * @see StartTransform(), StopTransform() */ 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])); } // 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 float $width The width. * @since 1.0 * @see Line(), Rect(), Cell(), MultiCell() */ function SetLineWidth($width) { //Set line width $this->LineWidth=$width; if($this->page>0) { $this->_out(sprintf('%.2f w',$width*$this->k)); } } /** * Returns the current the line width. * @return int Line width * @since 2.1.000 (2008-01-07) * @see Line(), SetLineWidth() */ function GetLineWidth() { return $this->LineWidth; } /** * Set line style. * * @param array $style 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(red, green, blue).
        • *
        * @access public * @since 2.1.000 (2008-01-08) */ function SetLineStyle($style) { extract($style); if (isset($width)) { $width_prev = $this->LineWidth; $this->SetLineWidth($width); $this->LineWidth = $width_prev; } if (isset($cap)) { $ca = array("butt" => 0, "round"=> 1, "square" => 2); if (isset($ca[$cap])) { $this->_out($ca[$cap] . " J"); } } if (isset($join)) { $ja = array("miter" => 0, "round" => 1, "bevel" => 2); if (isset($ja[$join])) { $this->_out($ja[$join] . " j"); } } if (isset($dash)) { $dash_string = ""; if ($dash) { if (ereg("^.+,", $dash)) { $tab = explode(",", $dash); } else { $tab = array($dash); } $dash_string = ""; foreach ($tab as $i => $v) { if ($i) { $dash_string .= " "; } $dash_string .= sprintf("%.2f", $v); } } if (!isset($phase) OR !$dash) { $phase = 0; } $this->_out(sprintf("[%s] %.2f d", $dash_string, $phase)); } if (isset($color)) { list($r, $g, $b) = $color; $this->SetDrawColor($r, $g, $b); } } /* * Set a draw point. * @param float $x Abscissa of point. * @param float $y Ordinate of point. * @access private * @since 2.1.000 (2008-01-08) */ function _outPoint($x, $y) { if($this->rtl) { $x = $this->w - $x; } $this->_out(sprintf("%.2f %.2f m", $x * $this->k, ($this->h - $y) * $this->k)); } /* * Draws a line from last draw point. * @param float $x Abscissa of end point. * @param float $y Ordinate of end point. * @access private * @since 2.1.000 (2008-01-08) */ function _outLine($x, $y) { if($this->rtl) { $x = $this->w - $x; } $this->_out(sprintf("%.2f %.2f l", $x * $this->k, ($this->h - $y) * $this->k)); } /** * Draws a rectangle. * @param float $x Abscissa of upper-left corner (or upper-right corner for RTL language). * @param float $y Ordinate of upper-left corner (or upper-right corner for RTL language). * @param float $w Width. * @param float $h Height. * @param string $op options * @access protected * @since 2.1.000 (2008-01-08) */ function _outRect($x, $y, $w, $h, $op) { if($this->rtl) { $x = $this->w - $x - $w; } $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op)); } /* * Draws a Bezier curve from last draw point. * The Bezier curve is a tangent to the line between the control points at either end of the curve. * @param float $x1 Abscissa of control point 1. * @param float $y1 Ordinate of control point 1. * @param float $x2 Abscissa of control point 2. * @param float $y2 Ordinate of control point 2. * @param float $x3 Abscissa of end point. * @param float $y3 Ordinate of end point. * @access private * @since 2.1.000 (2008-01-08) */ function _outCurve($x1, $y1, $x2, $y2, $x3, $y3) { if($this->rtl) { $x1 = $this->w - $x1; $x2 = $this->w - $x2; $x3 = $this->w - $x3; } $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)); } /** * Draws a line between two points. * @param float $x1 Abscissa of first point. * @param float $y1 Ordinate of first point. * @param float $x2 Abscissa of second point. * @param float $y2 Ordinate of second point. * @param array $style Line style. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array). * @access public * @since 1.0 * @see SetLineWidth(), SetDrawColor(), SetLineStyle() */ function Line($x1, $y1, $x2, $y2, $style = array()) { if ($style) { $this->SetLineStyle($style); } $this->_outPoint($x1, $y1); $this->_outLine($x2, $y2); $this->_out(" S"); } /** * Draws a rectangle. * @param float $x Abscissa of upper-left corner (or upper-right corner for RTL language). * @param float $y Ordinate of upper-left corner (or upper-right corner for RTL language). * @param float $w Width. * @param float $h Height. * @param string $style Style of rendering. Possible values are: *
          *
        • D or empty string: Draw (default).
        • *
        • F: Fill.
        • *
        • DF or FD: Draw and fill.
        • *
        * @param array $border_style Border style of rectangle. Array with keys among the following: *
          *
        • all: Line style of all borders. Array like for {@link SetLineStyle SetLineStyle}.
        • *
        • L, T, R, B or combinations: Line style of left, top, right or bottom border. Array like for {@link SetLineStyle SetLineStyle}.
        • *
        * If a key is not present or is null, not draws the border. Default value: default line style (empty array). * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @access public * @since 1.0 * @see SetLineStyle() */ function Rect($x, $y, $w, $h, $style='', $border_style = array(), $fill_color = array()) { if (!(false === strpos($style, "F")) AND $fill_color) { list($r, $g, $b) = $fill_color; $this->SetFillColor($r, $g, $b); } switch ($style) { case "F": { $op='f'; $border_style = array(); $this->_outRect($x, $y, $w, $h, $op); break; } case "DF": case "FD": { if (!$border_style OR isset($border_style["all"])) { $op='B'; if (isset($border_style["all"])) { $this->SetLineStyle($border_style["all"]); $border_style = array(); } } else { $op='f'; } $this->_outRect($x, $y, $w, $h, $op); break; } default: { $op='S'; if (!$border_style OR isset($border_style["all"])) { if (isset($border_style["all"]) && $border_style["all"]) { $this->SetLineStyle($border_style["all"]); $border_style = array(); } $this->_outRect($x, $y, $w, $h, $op); } break; } } if ($border_style) { $border_style2 = array(); foreach ($border_style as $line => $value) { $lenght = strlen($line); for ($i = 0; $i < $lenght; $i++) { $border_style2[$line[$i]] = $value; } } $border_style = $border_style2; if (isset($border_style["L"]) && $border_style["L"]) { $this->Line($x, $y, $x, $y + $h, $border_style["L"]); } if (isset($border_style["T"]) && $border_style["T"]) { $this->Line($x, $y, $x + $w, $y, $border_style["T"]); } if (isset($border_style["R"]) && $border_style["R"]) { $this->Line($x + $w, $y, $x + $w, $y + $h, $border_style["R"]); } if (isset($border_style["B"]) && $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 float $x0 Abscissa of start point. * @param float $y0 Ordinate of start point. * @param float $x1 Abscissa of control point 1. * @param float $y1 Ordinate of control point 1. * @param float $x2 Abscissa of control point 2. * @param float $y2 Ordinate of control point 2. * @param float $x3 Abscissa of end point. * @param float $y3 Ordinate of end point. * @param string $style Style of rendering. Possible values are: *
          *
        • D or empty string: Draw (default).
        • *
        • F: Fill.
        • *
        • DF or FD: Draw and fill.
        • *
        * @param array $line_style Line style of curve. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array). * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @access public * @see SetLineStyle() * @since 2.1.000 (2008-01-08) */ function Curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3, $style = "", $line_style = array(), $fill_color = array()) { if (!(false === strpos($style, "F")) AND $fill_color) { list($r, $g, $b) = $fill_color; $this->SetFillColor($r, $g, $b); } switch ($style) { case "F": { $op = "f"; $line_style = array(); break; } case "FD": case "DF": { $op = "B"; break; } default: { $op = "S"; break; } } if ($line_style) { $this->SetLineStyle($line_style); } $this->_outPoint($x0, $y0); $this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3); $this->_out($op); } /** * Draws an ellipse. * An ellipse is formed from n Bezier curves. * @param float $x0 Abscissa of center point. * @param float $y0 Ordinate of center point. * @param float $rx Horizontal radius. * @param float $ry Vertical radius (if ry = 0 then is a circle, see {@link Circle Circle}). Default value: 0. * @param float $angle: Angle oriented (anti-clockwise). Default value: 0. * @param float $astart: Angle start of draw line. Default value: 0. * @param float $afinish: Angle finish of draw line. Default value: 360. * @param string $style Style of rendering. Possible values are: *
          *
        • D or empty string: Draw (default).
        • *
        • F: Fill.
        • *
        • DF or FD: Draw and fill.
        • *
        • C: Draw close.
        • *
        * @param array $line_style Line style of ellipse. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array). * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @param integer $nc Number of curves used in ellipse. Default value: 8. * @access public * @since 2.1.000 (2008-01-08) */ function Ellipse($x0, $y0, $rx, $ry = 0, $angle = 0, $astart = 0, $afinish = 360, $style = "", $line_style = array(), $fill_color = array(), $nc = 8) { if ($angle) { $this->StartTransform(); $this->Rotate($angle, $x0, $y0); $this->Ellipse($x0, $y0, $rx, $ry, 0, $astart, $afinish, $style, $line_style, $fill_color, $nc); $this->StopTransform(); return; } if ($rx) { if (!(false === strpos($style, "F")) AND $fill_color) { list($r, $g, $b) = $fill_color; $this->SetFillColor($r, $g, $b); } switch ($style) { case "F": { $op = "f"; $line_style = array(); break; } case "FD": case "DF": { $op = "B"; break; } case "C": { $op = "s"; // Small "s" signifies closing the path as well break; } default: { $op = "S"; break; } } if ($line_style) { $this->SetLineStyle($line_style); } if (!$ry) { $ry = $rx; } $rx *= $this->k; $ry *= $this->k; if ($nc < 2){ $nc = 2; } $astart = deg2rad((float) $astart); $afinish = deg2rad((float) $afinish); $total_angle = $afinish - $astart; $dt = $total_angle / $nc; $dtm = $dt/3; $x0 *= $this->k; $y0 = ($this->h - $y0) * $this->k; $t1 = $astart; $a0 = $x0 + ($rx * cos($t1)); $b0 = $y0 + ($ry * sin($t1)); $c0 = -$rx * sin($t1); $d0 = $ry * cos($t1); $this->_outPoint($a0 / $this->k, $this->h - ($b0 / $this->k)); for ($i = 1; $i <= $nc; $i++) { // Draw this bit of the total curve $t1 = ($i * $dt) + $astart; $a1 = $x0 + ($rx * cos($t1)); $b1 = $y0 + ($ry * sin($t1)); $c1 = -$rx * sin($t1); $d1 = $ry * cos($t1); $this->_outCurve(($a0 + ($c0 * $dtm)) / $this->k, $this->h - (($b0 + ($d0 * $dtm)) / $this->k), ($a1 - ($c1 * $dtm)) / $this->k, $this->h - (($b1 - ($d1 * $dtm)) / $this->k), $a1 / $this->k, $this->h - ($b1 / $this->k)); $a0 = $a1; $b0 = $b1; $c0 = $c1; $d0 = $d1; } $this->_out($op); } } /** * Draws a circle. * A circle is formed from n Bezier curves. * @param float $x0 Abscissa of center point. * @param float $y0 Ordinate of center point. * @param float $r Radius. * @param float $astart: Angle start of draw line. Default value: 0. * @param float $afinish: Angle finish of draw line. Default value: 360. * @param string $style Style of rendering. Possible values are: *
          *
        • D or empty string: Draw (default).
        • *
        • F: Fill.
        • *
        • DF or FD: Draw and fill.
        • *
        • C: Draw close.
        • *
        * @param array $line_style Line style of circle. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array). * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @param integer $nc Number of curves used in circle. Default value: 8. * @access public * @since 2.1.000 (2008-01-08) */ function Circle($x0, $y0, $r, $astart = 0, $afinish = 360, $style = "", $line_style = array(), $fill_color = array(), $nc = 8) { $this->Ellipse($x0, $y0, $r, 0, 0, $astart, $afinish, $style, $line_style, $fill_color, $nc); } /** * Draws a polygon. * @param array $p Points 0 to ($np - 1). Array with values (x0, y0, x1, y1,..., x(np-1), y(np - 1)) * @param string $style Style of rendering. Possible values are: *
          *
        • D or empty string: Draw (default).
        • *
        • F: Fill.
        • *
        • DF or FD: Draw and fill.
        • *
        * @param array $line_style Line style of polygon. Array with keys among the following: *
          *
        • all: Line style of all lines. Array like for {@link SetLineStyle SetLineStyle}.
        • *
        • 0 to ($np - 1): Line style of each line. Array like for {@link SetLineStyle SetLineStyle}.
        • *
        * If a key is not present or is null, not draws the line. Default value is default line style (empty array). * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @access public * @since 2.1.000 (2008-01-08) */ function Polygon($p, $style = "", $line_style = array(), $fill_color = array()) { $np = count($p) / 2; if (!(false === strpos($style, "F")) AND $fill_color) { list($r, $g, $b) = $fill_color; $this->SetFillColor($r, $g, $b); } switch ($style) { case "F": { $line_style = array(); $op = "f"; break; } case "FD": case "DF": { $op = "B"; break; } default: { $op = "S"; break; } } $draw = true; if ($line_style) { if (isset($line_style["all"])) { $this->SetLineStyle($line_style["all"]); } else { // 0 .. (np - 1), op = {B, S} $draw = false; if ("B" == $op) { $op = "f"; $this->_outPoint($p[0], $p[1]); for ($i = 2; $i < ($np * 2); $i = $i + 2) { $this->_outLine($p[$i], $p[$i + 1]); } $this->_outLine($p[0], $p[1]); $this->_out($op); } $p[$np * 2] = $p[0]; $p[($np * 2) + 1] = $p[1]; for ($i = 0; $i < $np; $i++) { if (isset($line_style[$i])) { $this->Line($p[$i * 2], $p[($i * 2) + 1], $p[($i * 2) + 2], $p[($i * 2) + 3], $line_style[$i]); } } } } if ($draw) { $this->_outPoint($p[0], $p[1]); for ($i = 2; $i < ($np * 2); $i = $i + 2) { $this->_outLine($p[$i], $p[$i + 1]); } $this->_outLine($p[0], $p[1]); $this->_out($op); } } /** * Draws a regular polygon. * @param float $x0 Abscissa of center point. * @param float $y0 Ordinate of center point. * @param float $r: Radius of inscribed circle. * @param integer $ns Number of sides. * @param float $angle Angle oriented (anti-clockwise). Default value: 0. * @param boolean $draw_circle Draw inscribed circle or not. Default value: false. * @param string $style Style of rendering. Possible values are: *
          *
        • D or empty string: Draw (default).
        • *
        • F: Fill.
        • *
        • DF or FD: Draw and fill.
        • *
        * @param array $line_style Line style of polygon sides. Array with keys among the following: *
          *
        • all: Line style of all sides. Array like for {@link SetLineStyle SetLineStyle}.
        • *
        • 0 to ($ns - 1): Line style of each side. Array like for {@link SetLineStyle SetLineStyle}.
        • *
        * If a key is not present or is null, not draws the side. Default value is default line style (empty array). * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @param string $circle_style 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.
        • *
        * @param array $circle_outLine_style Line style of inscribed circle (if draws). Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array). * @param array $circle_fill_color Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). * @access public * @since 2.1.000 (2008-01-08) */ 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 float $x0 Abscissa of center point. * @param float $y0 Ordinate of center point. * @param float $r Radius of inscribed circle. * @param integer $nv Number of vertices. * @param integer $ng Number of gap (if ($ng % $nv = 1) then is a regular polygon). * @param float $angle: Angle oriented (anti-clockwise). Default value: 0. * @param boolean $draw_circle: Draw inscribed circle or not. Default value is false. * @param string $style Style of rendering. Possible values are: *
          *
        • D or empty string: Draw (default).
        • *
        • F: Fill.
        • *
        • DF or FD: Draw and fill.
        • *
        * @param array $line_style Line style of polygon sides. Array with keys among the following: *
          *
        • all: Line style of all sides. Array like for * {@link SetLineStyle SetLineStyle}.
        • *
        • 0 to (n - 1): Line style of each side. Array like for {@link SetLineStyle SetLineStyle}.
        • *
        * If a key is not present or is null, not draws the side. Default value is default line style (empty array). * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @param string $circle_style 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.
        • *
        * @param array $circle_outLine_style Line style of inscribed circle (if draws). Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array). * @param array $circle_fill_color Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array). * @access public * @since 2.1.000 (2008-01-08) */ 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 (2 > $nv) { $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 float $x Abscissa of upper-left corner. * @param float $y Ordinate of upper-left corner. * @param float $w Width. * @param float $h Height. * @param float $r Radius of the rounded corners. * @param string $round_corner 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 string $style Style of rendering. Possible values are: *
          *
        • D or empty string: Draw (default).
        • *
        • F: Fill.
        • *
        • DF or FD: Draw and fill.
        • *
        * @param array $border_style Border style of rectangle. Array like for {@link SetLineStyle SetLineStyle}. Default value: default line style (empty array). * @param array $fill_color Fill color. Format: array(red, green, blue). Default value: default color (empty array). * @access public * @since 2.1.000 (2008-01-08) */ function RoundedRect($x, $y, $w, $h, $r, $round_corner = "1111", $style = "", $border_style = array(), $fill_color = array()) { if ("0000" == $round_corner) { // Not rounded $this->Rect($x, $y, $w, $h, $style, $border_style, $fill_color); } else { // Rounded if (!(false === strpos($style, "F")) AND $fill_color) { list($red, $g, $b) = $fill_color; $this->SetFillColor($red, $g, $b); } switch ($style) { case "F": { $border_style = array(); $op = "f"; break; } case "FD": case "DF": { $op = "B"; break; } default: { $op = "S"; break; } } if ($border_style) { $this->SetLineStyle($border_style); } $MyArc = 4 / 3 * (sqrt(2) - 1); $this->_outPoint($x + $r, $y); $xc = $x + $w - $r; $yc = $y + $r; $this->_outLine($xc, $y); if ($round_corner[0]) { $this->_outCurve($xc + ($r * $MyArc), $yc - $r, $xc + $r, $yc - ($r * $MyArc), $xc + $r, $yc); } else { $this->_outLine($x + $w, $y); } $xc = $x + $w - $r; $yc = $y + $h - $r; $this->_outLine($x + $w, $yc); if ($round_corner[1]) { $this->_outCurve($xc + $r, $yc + ($r * $MyArc), $xc + ($r * $MyArc), $yc + $r, $xc, $yc + $r); } else { $this->_outLine($x + $w, $y + $h); } $xc = $x + $r; $yc = $y + $h - $r; $this->_outLine($xc, $y + $h); if ($round_corner[2]) { $this->_outCurve($xc - ($r * $MyArc), $yc + $r, $xc - $r, $yc + ($r * $MyArc), $xc - $r, $yc); } else { $this->_outLine($x, $y + $h); } $xc = $x + $r; $yc = $y + $r; $this->_outLine($x, $yc); if ($round_corner[3]) { $this->_outCurve($xc - $r, $yc - ($r * $MyArc), $xc - ($r * $MyArc), $yc - $r, $xc, $yc - $r); } else { $this->_outLine($x, $y); $this->_outLine($x + $r, $y); }