diff --git a/include/class.pdf.php b/include/class.pdf.php
index 34973391ffa8e288ee3d5e20473f2d28313349c4..9a7f0a7004eaf408f3fe08740596d31579699bde 100644
--- a/include/class.pdf.php
+++ b/include/class.pdf.php
@@ -30,17 +30,11 @@ class Ticket2PDF extends mPDF
 	function Ticket2PDF($ticket, $psize='Letter', $notes=false) {
         global $thisstaff;
 
-
         $this->ticket = $ticket;
         $this->includenotes = $notes;
 
         parent::__construct('', $psize);
 
-        $this->SetMargins(10,10,10);
-		$this->AliasNbPages();
-		$this->AddPage();
-		$this->cMargin = 3;
-
         $this->_print();
 	}
 
@@ -48,70 +42,6 @@ class Ticket2PDF extends mPDF
         return $this->ticket;
     }
 
-    function getLogoFile() {
-        global $ost;
-
-        if (!function_exists('imagecreatefromstring')
-                || (!($logo = $ost->getConfig()->getClientLogo()))) {
-            return INCLUDE_DIR.'fpdf/print-logo.png';
-        }
-
-        $tmp = tempnam(sys_get_temp_dir(), 'pdf') . '.jpg';
-        $img = imagecreatefromstring($logo->getData());
-        // Handle transparent images with white background
-        $img2 = imagecreatetruecolor(imagesx($img), imagesy($img));
-        $white = imagecolorallocate($img2, 255, 255, 255);
-        imagefill($img2, 0, 0, $white);
-        imagecopy($img2, $img, 0, 0, 0, 0, imagesx($img), imagesy($img));
-        imagejpeg($img2, $tmp);
-        return $tmp;
-    }
-
-	//report header...most stuff are hard coded for now...
-	function Header() {
-        global $cfg;
-
-		//Common header
-        $logo = $this->getLogoFile();
-		$this->Image($logo, $this->lMargin, $this->tMargin, 0, 20);
-        if (strpos($logo, INCLUDE_DIR) === false)
-            unlink($logo);
-		$this->SetFont('Arial', 'B', 16);
-		$this->SetY($this->tMargin + 20);
-        $this->SetX($this->lMargin);
-        $this->WriteCell(0, 0, '', "B", 2, 'L');
-		$this->Ln(1);
-        $this->SetFont('Arial', 'B',10);
-        $this->WriteCell(0, 5, $cfg->getTitle(), 0, 0, 'L');
-        $this->SetFont('Arial', 'I',10);
-        $this->WriteCell(0, 5, Format::daydatetime(null, false), 0, 1, 'R');
-		$this->Ln(5);
-	}
-
-	//Page footer baby
-	function Footer() {
-        global $thisstaff;
-
-		$this->SetY(-15);
-        $this->WriteCell(0, 2, '', "T", 2, 'L');
-		$this->SetFont('Arial', 'I', 9);
-        $this->WriteCell(0, 7, sprintf(__('Ticket #%1$s printed by %2$s on %3$s'),
-            $this->getTicket()->getNumber(), $thisstaff->getUserName(), date('r')), 0, 0, 'L');
-		//$this->WriteCell(0,10,'Page '.($this->PageNo()-$this->pageOffset).' of {nb} '.$this->pageOffset.' '.$this->PageNo(),0,0,'R');
-		$this->WriteCell(0, 7, sprintf(__('Page %d'), ($this->PageNo() - $this->pageOffset)), 0, 0, 'R');
-	}
-
-    function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='') {
-        parent::Cell($w, $h, $txt, $border, $ln, $align, $fill, $link);
-    }
-
-    function WriteText($w, $text, $border) {
-
-        $this->SetFont('Arial','',11);
-        $this->MultiCell($w, 7, $text, $border, 'L');
-
-    }
-
     function WriteHtml() {
         static $filenumber = 1;
         $args = func_get_args();
@@ -131,187 +61,16 @@ class Ticket2PDF extends mPDF
     }
 
     function _print() {
+        global $thisstaff, $cfg;
 
         if(!($ticket=$this->getTicket()))
             return;
 
-        $w =(($this->w/2)-$this->lMargin);
-        $l = 35;
-        $c = $w-$l;
-
-        // Setup HTML writing and load default thread stylesheet
-        $this->WriteHtml(
-            '<style>'.file_get_contents(ROOT_DIR.'css/thread.css')
-            .'</style>', 1, true, false);
-
-        $this->SetFont('Arial', 'B', 11);
-        $this->cMargin = 0;
-        $this->SetFont('Arial', 'B', 11);
-        $this->SetTextColor(10, 86, 142);
-        $this->WriteCell($w, 7,sprintf(__('Ticket #%s'),$ticket->getNumber()), 0, 0, 'L');
-        $this->Ln(7);
-        $this->cMargin = 3;
-        $this->SetTextColor(0);
-        $this->SetDrawColor(220, 220, 220);
-        $this->SetFillColor(244, 250, 255);
-        $this->SetX($this->lMargin);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Status'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, (string)$ticket->getStatus(), 1, 0, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Name'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, (string)$ticket->getName(), 1, 1, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Priority'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, $ticket->getPriority(), 1, 0, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Email'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, $ticket->getEmail(), 1, 1, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Department'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, $ticket->getDeptName(), 1, 0, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Phone'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, $ticket->getPhoneNumber(), 1, 1, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Create Date'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, Format::datetime($ticket->getCreateDate()), 1, 0, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Source'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $source = ucfirst($ticket->getSource());
-        if($ticket->getIP())
-            $source.='  ('.$ticket->getIP().')';
-        $this->WriteCell($c, 7, $source, 1, 0, 'L', true);
-        $this->Ln(12);
-
-        $this->SetFont('Arial', 'B', 11);
-        if($ticket->isOpen()) {
-            $this->WriteCell($l, 7, __('Assigned To'), 1, 0, 'L', true);
-            $this->SetFont('');
-            $this->WriteCell($c, 7, $ticket->isAssigned()?$ticket->getAssigned():' -- ', 1, 0, 'L', true);
-        } else {
-
-            $closedby = __('unknown');
-            if(($staff = $ticket->getStaff()))
-                $closedby = (string) $staff->getName();
-
-            $this->WriteCell($l, 7, __('Closed By'), 1, 0, 'L', true);
-            $this->SetFont('');
-            $this->WriteCell($c, 7, $closedby, 1, 0, 'L', true);
-        }
-
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Help Topic'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, $ticket->getHelpTopic(), 1, 1, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('SLA Plan'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $sla = $ticket->getSLA();
-        $this->WriteCell($c, 7, $sla?$sla->getName():' -- ', 1, 0, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Last Response'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, Format::datetime($ticket->getLastRespDate()), 1, 1, 'L', true);
-        $this->SetFont('Arial', 'B', 11);
-        if($ticket->isOpen()) {
-            $this->WriteCell($l, 7, __('Due Date'), 1, 0, 'L', true);
-            $this->SetFont('');
-            $this->WriteCell($c, 7, Format::datetime($ticket->getEstDueDate()), 1, 0, 'L', true);
-        } else {
-            $this->WriteCell($l, 7, __('Close Date'), 1, 0, 'L', true);
-            $this->SetFont('');
-            $this->WriteCell($c, 7, Format::datetime($ticket->getCloseDate()), 1, 0, 'L', true);
-        }
-
-        $this->SetFont('Arial', 'B', 11);
-        $this->WriteCell($l, 7, __('Last Message'), 1, 0, 'L', true);
-        $this->SetFont('');
-        $this->WriteCell($c, 7, Format::datetime($ticket->getLastMsgDate()), 1, 1, 'L', true);
-
-        $this->SetFillColor(255, 255, 255);
-        foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) {
-            $idx = 0;
-            foreach ($form->getAnswers() as $a) {
-                if (in_array($a->getField()->get('name'),
-                            array('email','name','subject','phone','priority')))
-                    continue;
-                $this->SetFont('Arial', 'B', 11);
-                if ($idx++ === 0) {
-                    $this->Ln(5);
-                    $this->SetFillColor(244, 250, 255);
-                    $this->WriteCell(($l+$c)*2, 7, $a->getForm()->get('title'),
-                        1, 0, 'L', true);
-                    $this->SetFillColor(255, 255, 255);
-                }
-                if ($val = $a->toString()) {
-                    $this->Ln(7);
-                    $this->WriteCell($l*2, 7, $a->getField()->get('label'), 1, 0, 'L', true);
-                    $this->SetFont('');
-                    $this->WriteCell($c*2, 7, $val, 1, 0, 'L', true);
-                }
-            }
-        }
-        $this->SetFillColor(244, 250, 255);
-        $this->Ln(10);
-
-        $this->SetFont('Arial', 'B', 11);
-        $this->cMargin = 0;
-        $this->SetTextColor(10, 86, 142);
-        $this->WriteCell($w, 7,trim($ticket->getSubject()), 0, 0, 'L');
-        $this->Ln(7);
-        $this->SetTextColor(0);
-        $this->cMargin = 3;
-
-        //Table header colors (RGB)
-        $colors = array('M'=>array(195, 217, 255),
-                        'R'=>array(255, 224, 179),
-                        'N'=>array(250, 250, 210));
-        //Get ticket thread
-        $types = array('M', 'R');
-        if($this->includenotes)
-            $types[] = 'N';
-
-        if(($entries = $ticket->getThreadEntries($types))) {
-            foreach($entries as $entry) {
-
-                $color = $colors[$entry['thread_type']];
-
-                $this->SetFillColor($color[0], $color[1], $color[2]);
-                $this->SetFont('Arial', 'B', 11);
-                $this->WriteCell($w/2, 7, Format::datetime($entry['created']), 'LTB', 0, 'L', true);
-                $this->SetFont('Arial', '', 10);
-                $this->WriteCell($w, 7, Format::truncate($entry['title'], 50), 'TB', 0, 'L', true);
-                $this->WriteCell($w/2, 7, $entry['name'] ?: $entry['poster'], 'TBR', 1, 'L', true);
-                $this->SetFont('');
-                $text = $entry['body']->display('pdf');
-                if($entry['attachments']
-                        && ($tentry=$ticket->getThreadEntry($entry['id']))
-                        && ($attachments = $tentry->getAttachments())) {
-                    $files = array();
-                    foreach($attachments as $attachment)
-                        if (!$attachment['inline'])
-                            $files[]= $attachment['name'];
-
-                    if ($files)
-                        $text.="<div>Files Attached: [".implode(', ',$files)."]</div>";
-                        $text.="<div>".sprintf(__('Files Attached: [%s]'),implode(', ',$files))."</div>";
-                }
-                $this->WriteHtml('<div class="thread-body">'.$text.'</div>', 2, false, false);
-                $this->Ln(5);
-            }
-        }
-
-        $this->WriteHtml('', 2, false, true);
+        ob_start();
+        include STAFFINC_DIR.'templates/ticket-print.tmpl.php';
+        $html = ob_get_clean();
 
+        $this->WriteHtml($html, 0, true, true);
     }
 }
 ?>
diff --git a/include/staff/templates/ticket-print.tmpl.php b/include/staff/templates/ticket-print.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..bd9ed2aa74873535a86a439102c2b77188ac39c9
--- /dev/null
+++ b/include/staff/templates/ticket-print.tmpl.php
@@ -0,0 +1,250 @@
+<html>
+
+<head>
+    <style type="text/css">
+@page {
+    header: html_def;
+    footer: html_def;
+    margin: 15mm;
+    margin-top: 35mm;
+}
+.logo {
+  max-width: 220px;
+  max-height: 71px;
+  width: auto;
+  height: auto;
+  margin: 0;
+}
+#ticket_thread .message,
+#ticket_thread .response,
+#ticket_thread .note {
+    margin-top:10px;
+    border:1px solid #aaa;
+    border-bottom:2px solid #aaa;
+}
+#ticket_thread .header {
+    text-align:left;
+    border-bottom:1px solid #aaa;
+    padding:3px;
+    position: relative;
+}
+#ticket_thread .message .header {
+    background:#C3D9FF;
+}
+#ticket_thread .response .header {
+    background:#FFE0B3;
+}
+#ticket_thread .note .header {
+    background:#FFE;
+}
+#ticket_thread .info {
+    padding:5px;
+    background:#F4FAFF;
+    height:16px;
+    line-height:16px;
+}
+
+table.meta-data {
+    width: 100%;
+}
+table.custom-data {
+    margin-top: 10px;
+}
+table.custom-data th {
+    width: 25%;
+}
+table.custom-data th,
+table.meta-data th {
+    text-align: right;
+    background-color: #ddd;
+    padding: 3px 8px;
+}
+table.meta-data td {
+    padding: 3px 8px;
+}
+.faded {
+    color:#666;
+}
+.pull-left {
+    float: left;
+}
+.pull-right {
+    float: right;
+    position: absolute;
+    right: 0;
+}
+.flush-right {
+    text-align: right;
+}
+.flush-left {
+    text-align: left;
+}
+.ltr {
+    direction: ltr;
+    unicode-bidi: embed;
+}
+.headline {
+    border-bottom: 2px solid black;
+    font-weight: bold;
+}
+div.hr {
+    border-top: 0.2mm solid #bbb;
+    margin: 0.5mm 0;
+    font-size: 0.0001em;
+}
+<?php include ROOT_DIR . 'css/thread.css'; ?>
+    </style>
+</head>
+<body>
+
+<htmlpageheader name="def" style="display:none">
+<?php if ($logo = $cfg->getClientLogo()) { ?>
+    <img src="cid:<?php echo $logo->getKey(); ?>" class="logo"/>
+<?php } else { ?>
+    <img src="<?php echo INCLUDE_DIR . 'fpdf/print-logo.png'; ?>" class="logo"/>
+<?php } ?>
+    <div class="hr">&nbsp;</div>
+    <table><tr>
+        <td class="flush-left"><?php echo (string) $ost->company; ?></td>
+        <td class="flush-right"><?php echo Format::db_daydatetime(Misc::gmtime()); ?></td>
+    </tr></table>
+</htmlpageheader>
+
+<htmlpagefooter name="def" style="display:none">
+    <hr class="tight faded"/>
+    <table width="100%"><tr><td class="flush-left">
+        Ticket #<?php echo $ticket->getNumber(); ?> printed by
+        <?php echo $thisstaff->getUserName(); ?> on
+        <?php echo Format::db_daydatetime(Misc::gmtime()); ?>
+    </td>
+    <td class="flush-right">
+        Page {PAGENO}
+    </td>
+    </tr></table>
+</htmlpagefooter>
+
+<!-- Ticket metadata -->
+<h1>Ticket #<?php echo $ticket->getNumber(); ?></h1>
+<table class="meta-data" cellpadding="0" cellspacing="0">
+<tbody>
+<tr>
+    <th><?php echo __('Status'); ?></th>
+    <td><?php echo $ticket->getStatus(); ?></td>
+    <th><?php echo __('Name'); ?></th>
+    <td><?php echo $ticket->getOwner()->getName(); ?></td>
+</tr>
+<tr>
+    <th><?php echo __('Priority'); ?></th>
+    <td><?php echo $ticket->getPriority(); ?></td>
+    <th><?php echo __('Email'); ?></th>
+    <td><?php echo $ticket->getEmail(); ?></td>
+</tr>
+<tr>
+    <th><?php echo __('Department'); ?></th>
+    <td><?php echo $ticket->getDept(); ?></td>
+    <th><?php echo __('Phone'); ?></th>
+    <td><?php echo $ticket->getPhoneNumber(); ?></td>
+</tr>
+<tr>
+    <th><?php echo __('Create Date'); ?></th>
+    <td><?php echo Format::db_datetime($ticket->getCreateDate()); ?></td>
+    <th><?php echo __('Source'); ?></th>
+    <td><?php echo $ticket->getSource(); ?></td>
+</tr>
+</tbody>
+<tbody>
+    <tr><td colspan="4" class="spacer">&nbsp;</td></tr>
+</tbody>
+<tbody>
+<tr>
+    <th><?php echo __('Assigned To'); ?></th>
+    <td><?php echo $ticket->getAssigned(); ?></td>
+    <th><?php echo __('Help Topic'); ?></th>
+    <td><?php echo $ticket->getHelpTopic(); ?></td>
+</tr>
+<tr>
+    <th><?php echo __('SLA Plan'); ?></th>
+    <td><?php if ($sla = $ticket->getSLA()) echo $sla->getName(); ?></td>
+    <th><?php echo __('Last Response'); ?></th>
+    <td><?php echo Format::db_datetime($ticket->getLastResponseDate()); ?></td>
+</tr>
+<tr>
+    <th><?php echo __('Due Date'); ?></th>
+    <td><?php echo Format::db_datetime($ticket->getEstDueDate()); ?></td>
+    <th><?php echo __('Last Message'); ?></th>
+    <td><?php echo Format::db_datetime($ticket->getLastMessageDate()); ?></td>
+</tr>
+</tbody>
+</table>
+
+<!-- Custom Data -->
+<?php
+foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) {
+    // Skip core fields shown earlier in the ticket view
+    // TODO: Rewrite getAnswers() so that one could write
+    //       ->getAnswers()->filter(not(array('field__name__in'=>
+    //           array('email', ...))));
+    $answers = array_filter($form->getAnswers(), function ($a) {
+        return !in_array($a->getField()->get('name'),
+                array('email','subject','name','priority'));
+        });
+    if (count($answers) == 0)
+        continue;
+    ?>
+        <table class="custom-data" cellspacing="0" cellpadding="4" width="100%" border="0">
+        <tr><td colspan="2" class="headline flush-left"><?php echo $form->getTitle(); ?></th></tr>
+        <?php foreach($answers as $a) {
+            if (!($v = $a->display())) continue; ?>
+            <tr>
+                <th><?php
+    echo $a->getField()->get('label');
+                ?>:</th>
+                <td><?php
+    echo $v;
+                ?></td>
+            </tr>
+            <?php } ?>
+        </table>
+    <?php
+    $idx++;
+} ?>
+
+<!-- Ticket Thread -->
+<h2><?php echo $ticket->getSubject(); ?></h2>
+<div id="ticket_thread">
+<?php
+$types = array('M', 'R');
+if ($this->includenotes)
+    $types[] = 'N';
+
+if ($thread = $ticket->getThreadEntries($types)) {
+    $threadTypes=array('M'=>'message','R'=>'response', 'N'=>'note');
+    foreach ($thread as $entry) { ?>
+        <div class="thread-entry <?php echo $threadTypes[$entry['thread_type']]; ?>">
+            <table class="header" style="width:100%"><tr><td>
+                    <span><?php
+                        echo Format::db_datetime($entry['created']);?></span>
+                    <span style="padding:0 1em" class="faded title"><?php
+                        echo Format::truncate($entry['title'], 100); ?></span>
+                </td>
+                <td class="flush-right faded title" style="white-space:no-wrap">
+                    <?php
+                        echo Format::htmlchars($entry['name'] ?: $entry['poster']); ?></span>
+                </td>
+            </tr></table>
+            <div class="thread-body">
+                <div><?php echo $entry['body']->display('pdf'); ?></div>
+            <?php
+            if($entry['attachments']
+                    && ($tentry = $ticket->getThreadEntry($entry['id']))
+                    && ($links = $tentry->getAttachmentsLinks())) {?>
+            <div class="info"><?php echo $tentry->getAttachmentsLinks(); ?></div>
+            <?php
+            } ?>
+            </div>
+        </div>
+<?php }
+} ?>
+</div>
+</body>
+</html>