title: using fpdf to output a bullet list from an array
body: <p>I have been looking for a way to add bullets, or numbering of lists to my pdf output file.</p>
  
  <p>Let's say I have three lines of text coming from the database:</p>
  
  <pre><code>Line 1
  Line 2
  Line 3
  </code></pre>
  
  <p>What I want is fpdf to read each line and place a bullet in front of each. Thus the output will look like this:</p>
  
  <pre><code>• Line 1
  • Line 2
  • Line 3
  </code></pre>
  
  <p>The best solution I have found is the code below. It is fully functional (if you have fpdf uploaded to your server). The problem is I cannot figure out how to generate a list from lines of text:</p>
  
  <pre><code>&lt;? 
        define('FPDF_FONTPATH', 'font/');
  
   include('fpdf/fpdf.php');
  
   class PDF extends FPDF
  
   {
  
  
  
  
       var $wLine;
       var $hLine;
       var $Text; 
       var $border;
       var $align;
       var $fill;
       var $Padding;
       var $lPadding;
       var $tPadding;
       var $bPadding;
       var $rPadding;
       var $TagStyle;
       var $Indent;
       var $Space;
       var $PileStyle; 
            var $Line2Print;
       var $NextLineBegin; 
       var $TagName;
       var $Delta;
       var $StringLength; 
            var $LineLength;
       var $wTextLine;
       var $nbSpace;
       var $Xini;
       var $href;
       var $TagHref; 
  
       function WriteTag($w, $h, $txt, $border=0, $align="J", $fill=false, $padding=0)
       {
           $this-&gt;wLine=$w;
           $this-&gt;hLine=$h;
           $this-&gt;Text=trim($txt);
           $this-&gt;Text=preg_replace("/\n|\r|\t/","",$this-&gt;Text);
           $this-&gt;border=$border;
           $this-&gt;align=$align;
           $this-&gt;fill=$fill;
           $this-&gt;Padding=$padding;
  
           $this-&gt;Xini=$this-&gt;GetX();
           $this-&gt;href="";
           $this-&gt;PileStyle=array();        
                $this-&gt;TagHref=array();
           $this-&gt;LastLine=false;
  
           $this-&gt;SetSpace();
           $this-&gt;Padding();
           $this-&gt;LineLength();
           $this-&gt;BorderTop();
  
           while($this-&gt;Text!="")
           {
               $this-&gt;MakeLine();
               $this-&gt;PrintLine();
           }
  
           $this-&gt;BorderBottom();
       }
  
  
       function SetStyle($tag, $family, $style, $size, $color, $indent=-1)
       {
            $tag=trim($tag);
            $this-&gt;TagStyle[$tag]['family']=trim($family);
            $this-&gt;TagStyle[$tag]['style']=trim($style);
            $this-&gt;TagStyle[$tag]['size']=trim($size);
            $this-&gt;TagStyle[$tag]['color']=trim($color);
            $this-&gt;TagStyle[$tag]['indent']=$indent;
       }
  
  
  
       function SetSpace() 
       {
           $tag=$this-&gt;Parser($this-&gt;Text);
           $this-&gt;FindStyle($tag[2],0);
           $this-&gt;DoStyle(0);
           $this-&gt;Space=$this-&gt;GetStringWidth(" ");
       }
  
  
       function Padding()
       {
           if(preg_match("/^.+,/",$this-&gt;Padding)) {
               $tab=explode(",",$this-&gt;Padding);
               $this-&gt;lPadding=$tab[0];
               $this-&gt;tPadding=$tab[1];
               if(isset($tab[2]))
                   $this-&gt;bPadding=$tab[2];
               else
                   $this-&gt;bPadding=$this-&gt;tPadding;
               if(isset($tab[3]))
                   $this-&gt;rPadding=$tab[3];
               else
                   $this-&gt;rPadding=$this-&gt;lPadding;
           }
           else
           {
               $this-&gt;lPadding=$this-&gt;Padding;
               $this-&gt;tPadding=$this-&gt;Padding;
               $this-&gt;bPadding=$this-&gt;Padding;
               $this-&gt;rPadding=$this-&gt;Padding;
           }
           if($this-&gt;tPadding&lt;$this-&gt;LineWidth)
               $this-&gt;tPadding=$this-&gt;LineWidth;
       }
  
  
       function LineLength()
       {
           if($this-&gt;wLine==0)
               $this-&gt;wLine=$this-&gt;w - $this-&gt;Xini - $this-&gt;rMargin;
  
           $this-&gt;wTextLine = $this-&gt;wLine - $this-&gt;lPadding - $this-&gt;rPadding;
       }
  
  
       function BorderTop()
       {
           $border=0;
           if($this-&gt;border==1)
               $border="TLR";
           $this-&gt;Cell($this-&gt;wLine,$this-&gt;tPadding,"",$border,0,'C',$this-&gt;fill);
           $y=$this-&gt;GetY()+$this-&gt;tPadding;
           $this-&gt;SetXY($this-&gt;Xini,$y);
       }
  
  
       function BorderBottom()
       {
           $border=0;
           if($this-&gt;border==1)
               $border="BLR";
           $this-&gt;Cell($this-&gt;wLine,$this-&gt;bPadding,"",$border,0,'C',$this-&gt;fill);
       }
  
  
       function DoStyle($tag)
       {
           $tag=trim($tag);
           $this-&gt;SetFont($this-&gt;TagStyle[$tag]['family'],
               $this-&gt;TagStyle[$tag]['style'],
               $this-&gt;TagStyle[$tag]['size']);
  
           $tab=explode(",",$this-&gt;TagStyle[$tag]['color']);
           if(count($tab)==1)
               $this-&gt;SetTextColor($tab[0]);
           else
               $this-&gt;SetTextColor($tab[0],$tab[1],$tab[2]);
       }
  
  
       function FindStyle($tag, $ind) 
       {
           $tag=trim($tag);
  
           if($this-&gt;TagStyle[$tag]['family']!="")
               $family=$this-&gt;TagStyle[$tag]['family'];
           else
           {
               reset($this-&gt;PileStyle);
               while(list($k,$val)=each($this-&gt;PileStyle))
               {
                   $val=trim($val);
                   if($this-&gt;TagStyle[$val]['family']!="") {
                       $family=$this-&gt;TagStyle[$val]['family'];
                       break;
                   }
               }
           }
  
           $style="";
           $style1=strtoupper($this-&gt;TagStyle[$tag]['style']);
           if($style1!="N")
           {
               $bold=false;
               $italic=false;
               $underline=false;
               reset($this-&gt;PileStyle);
               while(list($k,$val)=each($this-&gt;PileStyle))
               {
                   $val=trim($val);
                   $style1=strtoupper($this-&gt;TagStyle[$val]['style']);
                   if($style1=="N")
                       break;
                   else
                   {
                       if(strpos($style1,"B")!==false)
                           $bold=true;
                       if(strpos($style1,"I")!==false)
                           $italic=true;
                       if(strpos($style1,"U")!==false)
                           $underline=true;
                   } 
                    }
               if($bold)
                   $style.="B";
               if($italic)
                   $style.="I";
               if($underline)
                   $style.="U";
           }
  
           if($this-&gt;TagStyle[$tag]['size']!=0)
               $size=$this-&gt;TagStyle[$tag]['size'];
           else
           {
               reset($this-&gt;PileStyle);
               while(list($k,$val)=each($this-&gt;PileStyle))
               {
                   $val=trim($val);
                   if($this-&gt;TagStyle[$val]['size']!=0) {
                       $size=$this-&gt;TagStyle[$val]['size'];
                       break;
                   }
               }
           }
  
           if($this-&gt;TagStyle[$tag]['color']!="")
               $color=$this-&gt;TagStyle[$tag]['color'];
           else
           {
               reset($this-&gt;PileStyle);
               while(list($k,$val)=each($this-&gt;PileStyle))
               {
                   $val=trim($val);
                   if($this-&gt;TagStyle[$val]['color']!="") {
                       $color=$this-&gt;TagStyle[$val]['color'];
                       break;
                   }
               }
           }
  
            $this-&gt;TagStyle[$ind]['family']=$family;
           $this-&gt;TagStyle[$ind]['style']=$style;
           $this-&gt;TagStyle[$ind]['size']=$size;
           $this-&gt;TagStyle[$ind]['color']=$color;
           $this-&gt;TagStyle[$ind]['indent']=$this-&gt;TagStyle[$tag]['indent'];
       }
  
  
       function Parser($text)
       {
           $tab=array();
           if(preg_match("|^(&lt;/([^&gt;]+)&gt;)|",$text,$regs)) {
               $tab[1]="c";
               $tab[2]=trim($regs[2]);
           }
           else if(preg_match("|^(&lt;([^&gt;]+)&gt;)|",$text,$regs)) {
               $regs[2]=preg_replace("/^a/","a ",$regs[2]); 
               $tab[1]="o";
               $tab[2]=trim($regs[2]);
  
                if(preg_match("/(.+) (.+)='(.+)'/",$regs[2])) {
                   $tab1=preg_split("/ +/",$regs[2]);
                   $tab[2]=trim($tab1[0]);
                   while(list($i,$couple)=each($tab1))
                   {
                       if($i&gt;0) {
                           $tab2=explode("=",$couple);
                           $tab2[0]=trim($tab2[0]);
                           $tab2[1]=trim($tab2[1]);
                           $end=strlen($tab2[1])-2;
                           $tab[$tab2[0]]=substr($tab2[1],1,$end);
                       }
                   }
               }
           }
            // Espace
            else if(preg_match("/^( )/",$text,$regs)) {
               $tab[1]="s";
               $tab[2]=' ';
           }
           // Texte
           else if(preg_match("/^([^&lt; ]+)/",$text,$regs)) {
               $tab[1]="t";
               $tab[2]=trim($regs[1]);
           }
           // Elagage
           $begin=strlen($regs[1]);
            $end=strlen($text);
            $text=substr($text, $begin, $end);
           $tab[0]=$text;
  
           return $tab; // 0 : $text; 1 : type de balise (tag); 2 : élément
       }
  
  
       function MakeLine()
       {
           $this-&gt;Text.=" ";
           $this-&gt;LineLength=array();
           $this-&gt;TagHref=array();
           $Length=0;
           $this-&gt;nbSpace=0;
  
           $i=$this-&gt;BeginLine();
           $this-&gt;TagName=array();
  
           if($i==0) {
               $Length=$this-&gt;StringLength[0];
               $this-&gt;TagName[0]=1;
               $this-&gt;TagHref[0]=$this-&gt;href;
           }
  
           while($Length&lt;$this-&gt;wTextLine)
           {
               $tab=$this-&gt;Parser($this-&gt;Text);
               $this-&gt;Text=$tab[0];
               if($this-&gt;Text=="") {
                   $this-&gt;LastLine=true;
                   break;
               }
  
               if($tab[1]=="o") {
                   array_unshift($this-&gt;PileStyle,$tab[2]);
                   $this-&gt;FindStyle($this-&gt;PileStyle[0],$i+1);
  
                   $this-&gt;DoStyle($i+1);
                   $this-&gt;TagName[$i+1]=1;
                   if($this-&gt;TagStyle[$tab[2]]['indent']!=-1) {
                       $Length+=$this-&gt;TagStyle[$tab[2]]['indent'];
                       $this-&gt;Indent=$this-&gt;TagStyle[$tab[2]]['indent'];
                   }
                   if($tab[2]=="a")
                       $this-&gt;href=$tab['href'];
               }
  
               if($tab[1]=="c") {
                   array_shift($this-&gt;PileStyle);
                   if(isset($this-&gt;PileStyle[0]))
                   {
                       $this-&gt;FindStyle($this-&gt;PileStyle[0],$i+1);
                       $this-&gt;DoStyle($i+1);
                   }
                   $this-&gt;TagName[$i+1]=1;
                   if($this-&gt;TagStyle[$tab[2]]['indent']!=-1) {
                       $this-&gt;LastLine=true;
                       $this-&gt;Text=trim($this-&gt;Text);
                       break;
                   }
                   if($tab[2]=="a")
                       $this-&gt;href="";
               }
  
               if($tab[1]=="s") {
                   $i++;
                   $Length+=$this-&gt;Space;
                   $this-&gt;Line2Print[$i]="";
                   if($this-&gt;href!="")
                       $this-&gt;TagHref[$i]=$this-&gt;href;
               }
  
               if($tab[1]=="t") {
                   $i++;
                   $this-&gt;StringLength[$i]=$this-&gt;GetStringWidth($tab[2]);
                   $Length+=$this-&gt;StringLength[$i];
                   $this-&gt;LineLength[$i]=$Length;
                   $this-&gt;Line2Print[$i]=$tab[2];
                   if($this-&gt;href!="")
                       $this-&gt;TagHref[$i]=$this-&gt;href;
                }
  
           }
  
           trim($this-&gt;Text);
           if($Length&gt;$this-&gt;wTextLine || $this-&gt;LastLine==true)
               $this-&gt;EndLine();
       }
  
  
       function BeginLine()
       {
           $this-&gt;Line2Print=array();
           $this-&gt;StringLength=array();
  
           if(isset($this-&gt;PileStyle[0]))
           {
               $this-&gt;FindStyle($this-&gt;PileStyle[0],0);
               $this-&gt;DoStyle(0);
           }
  
           if(count($this-&gt;NextLineBegin)&gt;0) {
               $this-&gt;Line2Print[0]=$this-&gt;NextLineBegin['text'];
               $this-&gt;StringLength[0]=$this-&gt;NextLineBegin['length'];
               $this-&gt;NextLineBegin=array();
               $i=0;
           }
           else {
               preg_match("/^(( *(&lt;([^&gt;]+)&gt;)* *)*)(.*)/",$this-&gt;Text,$regs);
               $regs[1]=str_replace(" ", "", $regs[1]);
               $this-&gt;Text=$regs[1].$regs[5];
               $i=-1;
           }
  
           return $i;
       }
  
  
       function EndLine()
       {
           if(end($this-&gt;Line2Print)!="" &amp;&amp; $this-&gt;LastLine==false) {
               $this-&gt;NextLineBegin['text']=array_pop($this-&gt;Line2Print);
               $this-&gt;NextLineBegin['length']=end($this-&gt;StringLength);
               array_pop($this-&gt;LineLength);
           }
  
           while(end($this-&gt;Line2Print)==="")
               array_pop($this-&gt;Line2Print);
  
           $this-&gt;Delta=$this-&gt;wTextLine-end($this-&gt;LineLength);
  
           $this-&gt;nbSpace=0;
           for($i=0; $i&lt;count($this-&gt;Line2Print); $i++) {
               if($this-&gt;Line2Print[$i]=="")
                   $this-&gt;nbSpace++;
           }
       }
  
  
       function PrintLine()
       {
           $border=0;
           if($this-&gt;border==1)
               $border="LR";
           $this-&gt;Cell($this-&gt;wLine,$this-&gt;hLine,"",$border,0,'C',$this-&gt;fill);
           $y=$this-&gt;GetY();
           $this-&gt;SetXY($this-&gt;Xini+$this-&gt;lPadding,$y);
  
           if($this-&gt;Indent!=-1) {
               if($this-&gt;Indent!=0)
                   $this-&gt;Cell($this-&gt;Indent,$this-&gt;hLine);
               $this-&gt;Indent=-1;
           }
  
           $space=$this-&gt;LineAlign();
           $this-&gt;DoStyle(0);
           for($i=0; $i&lt;count($this-&gt;Line2Print); $i++)
           {
               if(isset($this-&gt;TagName[$i]))
                   $this-&gt;DoStyle($i);
               if(isset($this-&gt;TagHref[$i]))
                   $href=$this-&gt;TagHref[$i];
               else
                   $href='';
               if($this-&gt;Line2Print[$i]=="")
                   $this-&gt;Cell($space,$this-&gt;hLine,"         ",0,0,'C',false,$href);
               else
                   $this-&gt;Cell($this-&gt;StringLength[$i],$this-&gt;hLine,$this-&gt;Line2Print[$i],0,0,'C',false,$href);
           }
  
           $this-&gt;LineBreak();
           if($this-&gt;LastLine &amp;&amp; $this-&gt;Text!="")
               $this-&gt;EndParagraph();
           $this-&gt;LastLine=false;
       }
  
  
       function LineAlign()
       {
           $space=$this-&gt;Space;
           if($this-&gt;align=="J") {
               if($this-&gt;nbSpace!=0)
                   $space=$this-&gt;Space + ($this-&gt;Delta/$this-&gt;nbSpace);
               if($this-&gt;LastLine)
                   $space=$this-&gt;Space;
           }
  
           if($this-&gt;align=="R")
               $this-&gt;Cell($this-&gt;Delta,$this-&gt;hLine);
  
           if($this-&gt;align=="C")
               $this-&gt;Cell($this-&gt;Delta/2,$this-&gt;hLine);
  
           return $space;
       }
  
  
       function LineBreak()
       {
           $x=$this-&gt;Xini;
           $y=$this-&gt;GetY()+$this-&gt;hLine;
           $this-&gt;SetXY($x,$y);
       }
  
  
       function EndParagraph()
       {
           $border=0;
           if($this-&gt;border==1)
               $border="LR";
           $this-&gt;Cell($this-&gt;wLine,$this-&gt;hLine/2,"",$border,0,'C',$this-&gt;fill);
           $x=$this-&gt;Xini;
           $y=$this-&gt;GetY()+$this-&gt;hLine/2;
           $this-&gt;SetXY($x,$y);
       }
   // end add
  
   //bullet
       function MultiCellBltArray($w, $h, $blt_array, $border=0, $align='J', $fill=0)
       {
           if (!is_array($blt_array))
           {
               die('MultiCellBltArray requires an array with the following keys: bullet, margin, text, indent, spacer');
               exit;
           }
  
                //Save x
           $bak_x = $this-&gt;x;
  
                for ($i=0; $i&lt;sizeof($blt_array['text']); $i++)
           {
               //Get bullet width including margin
               $blt_width = $this-&gt;GetStringWidth($blt_array['bullet'] . $blt_array['margin'])+$this-&gt;cMargin*2;
  
                    // SetX
               $this-&gt;SetX($bak_x);
  
                    //Output indent
               if ($blt_array['indent'] &gt; 0)
                   $this-&gt;Cell($blt_array['indent']);
  
                    //Output bullet
               $this-&gt;Cell($blt_width, $h, $blt_array['bullet'] . $blt_array['margin'], 0, '', $fill);
  
                    //Output text
               $this-&gt;MultiCell($w-$blt_width, $h, $blt_array['text'][$i], $border, $align, $fill);
  
                    //Insert a spacer between items if not the last item
               if ($i != sizeof($blt_array['text'])-1)
                   $this-&gt;Ln($blt_array['spacer']);
  
                    //Increment bullet if it's a number
               if (is_numeric($blt_array['bullet']))
                   $blt_array['bullet']++;
           }
  
                //Restore x
           $this-&gt;x = $bak_x;
       }
  
   }
  
  
   $pdf=new PDF();
   $pdf-&gt;AliasNbPages();
   $pdf-&gt;AddPage();
   $pdf-&gt;SetFont('Times', '', 12);
  
   $column_width = $pdf-&gt;w-30;
   $sample_text = 'This is sample text.\n This is a new line of text';
  
   $test1 = array();
   $test1['bullet'] = chr(149);
   $test1['margin'] = ' ';
   $test1['indent'] = 0;
   $test1['spacer'] = 0;
   $test1['text'] = array();
   for ($i=0; $i&lt;2; $i++)
   {
       $test1['text'][$i] = $sample_text;
  
   }
   $pdf-&gt;SetX(10);
   $pdf-&gt;MultiCellBltArray($column_width-$pdf-&gt;x, 6, $test1);
   $pdf-&gt;Ln(10);
  
  
   $pdf-&gt;Output();
   ?&gt;
  </code></pre>
  
  <p>The problem is the output looks like this:</p>
  
  <pre><code>• This is bulleted text.\n This is a new line of text
  • This is bulleted text.\n This is a new line of text
  </code></pre>
  
  <p>When I want it to look like:</p>
  
  <pre><code>• This is bulleted text.
  • This is a new line of text
  </code></pre>
  
  <p>This line of code seems to act in such a way as to duplicate the $sample_text above:</p>
  
  <pre><code>for ($i=0; $i&lt;2; $i++)
   {
       $test1['text'][$i] = $sample_text;
  
   }
  </code></pre>
  
  <p>Where is you change '$i&lt;2' to lets say '$i&lt;4', the result would be:</p>
  
  <pre><code>• This is bulleted text.\n This is a new line of text
  • This is bulleted text.\n This is a new line of text
  • This is bulleted text.\n This is a new line of text
  • This is bulleted text.\n This is a new line of text
  </code></pre>
  
  <p>But if I have a set of four different variables, I will want to place them in the sample text file, and then have the code iterate through it, leaving me with a bullet in front of each item:</p>
  
  <pre><code>$sample_text = "item 1 \n item 2 \n item 3 \n item 4";
  </code></pre>
  
  <p>And the result would then be:</p>
  
  <pre><code>• item 1
  • item 2
  • item 3
  • item 4
  </code></pre>