##// END OF EJS Templates
PDF: prepare switching TCPDF UTF-8 in non CJK or FPDF ANSI in CJK (#61)....
Toshi MARUYAMA -
r5138:988841d69a0d
parent child
Show More
@@ -29,6 +29,58 module Redmine
29 29 include ActionView::Helpers::TextHelper
30 30 include ActionView::Helpers::NumberHelper
31 31
32 class ITCPDF < TCPDF
33 include Redmine::I18n
34 attr_accessor :footer_date
35
36 def initialize(lang)
37 super()
38 set_language_if_valid lang
39 @font_for_content = 'FreeSans'
40 @font_for_footer = 'FreeSans'
41 SetCreator(Redmine::Info.app_name)
42 SetFont(@font_for_content)
43 end
44
45 def SetFontStyle(style, size)
46 SetFont(@font_for_content, style, size)
47 end
48
49 def SetTitle(txt)
50 txt = begin
51 utf16txt = Iconv.conv('UTF-16BE', 'UTF-8', txt)
52 hextxt = "<FEFF" # FEFF is BOM
53 hextxt << utf16txt.unpack("C*").map {|x| sprintf("%02X",x) }.join
54 hextxt << ">"
55 rescue
56 txt
57 end || ''
58 super(txt)
59 end
60
61 def textstring(s)
62 # Format a text string
63 if s =~ /^</ # This means the string is hex-dumped.
64 return s
65 else
66 return '('+escape(s)+')'
67 end
68 end
69
70 alias RDMCell Cell
71 alias RDMMultiCell MultiCell
72
73 def Footer
74 SetFont(@font_for_footer, 'I', 8)
75 SetY(-15)
76 SetX(15)
77 RDMCell(0, 5, @footer_date, 0, 0, 'L')
78 SetY(-15)
79 SetX(-30)
80 RDMCell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
81 end
82 end
83
32 84 class IFPDF < FPDF
33 85 include Redmine::I18n
34 86 attr_accessor :footer_date
@@ -90,7 +142,7 module Redmine
90 142 end
91 143 end
92 144
93 def Cell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
145 def fix_text_encoding(txt)
94 146 @ic ||= Iconv.new(l(:general_pdf_encoding), 'UTF-8')
95 147 # these quotation marks are not correctly rendered in the pdf
96 148 txt = txt.gsub(/[Ò€œÒ€�]/, '"') if txt
@@ -102,27 +154,37 module Redmine
102 154 rescue
103 155 txt
104 156 end || ''
105 super w,h,txt,border,ln,align,fill,link
157 return txt
158 end
159
160 def RDMCell(w,h=0,txt='',border=0,ln=0,align='',fill=0,link='')
161 Cell(w,h,fix_text_encoding(txt),border,ln,align,fill,link)
162 end
163
164 def RDMMultiCell(w,h=0,txt='',border=0,align='',fill=0)
165 MultiCell(w,h,fix_text_encoding(txt),border,align,fill)
106 166 end
107 167
108 168 def Footer
109 169 SetFont(@font_for_footer, 'I', 8)
110 170 SetY(-15)
111 171 SetX(15)
112 Cell(0, 5, @footer_date, 0, 0, 'L')
172 RDMCell(0, 5, @footer_date, 0, 0, 'L')
113 173 SetY(-15)
114 174 SetX(-30)
115 Cell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
175 RDMCell(0, 5, PageNo().to_s + '/{nb}', 0, 0, 'C')
116 176 end
177 alias alias_nb_pages AliasNbPages
117 178 end
118
179
119 180 # Returns a PDF string of a list of issues
120 181 def issues_to_pdf(issues, project, query)
121 182 pdf = IFPDF.new(current_language)
183
122 184 title = query.new_record? ? l(:label_issue_plural) : query.name
123 185 title = "#{project} - #{title}" if project
124 186 pdf.SetTitle(title)
125 pdf.AliasNbPages
187 pdf.alias_nb_pages
126 188 pdf.footer_date = format_date(Date.today)
127 189 pdf.AddPage("L")
128 190
@@ -136,15 +198,15 module Redmine
136 198
137 199 # title
138 200 pdf.SetFontStyle('B',11)
139 pdf.Cell(190,10, title)
201 pdf.RDMCell(190,10, title)
140 202 pdf.Ln
141 203
142 204 # headers
143 205 pdf.SetFontStyle('B',8)
144 206 pdf.SetFillColor(230, 230, 230)
145 pdf.Cell(15, row_height, "#", 1, 0, 'L', 1)
207 pdf.RDMCell(15, row_height, "#", 1, 0, 'L', 1)
146 208 query.columns.each_with_index do |column, i|
147 pdf.Cell(col_width[i], row_height, column.caption, 1, 0, 'L', 1)
209 pdf.RDMCell(col_width[i], row_height, column.caption, 1, 0, 'L', 1)
148 210 end
149 211 pdf.Ln
150 212
@@ -155,13 +217,13 module Redmine
155 217 issues.each do |issue|
156 218 if query.grouped? && (group = query.group_by_column.value(issue)) != previous_group
157 219 pdf.SetFontStyle('B',9)
158 pdf.Cell(277, row_height,
220 pdf.RDMCell(277, row_height,
159 221 (group.blank? ? 'None' : group.to_s) + " (#{query.issue_count_by_group[group]})",
160 222 1, 1, 'L')
161 223 pdf.SetFontStyle('',8)
162 224 previous_group = group
163 225 end
164 pdf.Cell(15, row_height, issue.id.to_s, 1, 0, 'L', 1)
226 pdf.RDMCell(15, row_height, issue.id.to_s, 1, 0, 'L', 1)
165 227 query.columns.each_with_index do |column, i|
166 228 s = if column.is_a?(QueryCustomFieldColumn)
167 229 cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
@@ -176,13 +238,13 module Redmine
176 238 value
177 239 end
178 240 end
179 pdf.Cell(col_width[i], row_height, s.to_s, 1, 0, 'L', 1)
241 pdf.RDMCell(col_width[i], row_height, s.to_s, 1, 0, 'L', 1)
180 242 end
181 243 pdf.Ln
182 244 end
183 245 if issues.size == Setting.issues_export_limit.to_i
184 246 pdf.SetFontStyle('B',10)
185 pdf.Cell(0, row_height, '...')
247 pdf.RDMCell(0, row_height, '...')
186 248 end
187 249 pdf.Output
188 250 end
@@ -191,73 +253,73 module Redmine
191 253 def issue_to_pdf(issue)
192 254 pdf = IFPDF.new(current_language)
193 255 pdf.SetTitle("#{issue.project} - ##{issue.tracker} #{issue.id}")
194 pdf.AliasNbPages
256 pdf.alias_nb_pages
195 257 pdf.footer_date = format_date(Date.today)
196 258 pdf.AddPage
197 259
198 260 pdf.SetFontStyle('B',11)
199 pdf.Cell(190,10, "#{issue.project} - #{issue.tracker} # #{issue.id}: #{issue.subject}")
261 pdf.RDMCell(190,10, "#{issue.project} - #{issue.tracker} # #{issue.id}: #{issue.subject}")
200 262 pdf.Ln
201 263
202 264 y0 = pdf.GetY
203 265
204 266 pdf.SetFontStyle('B',9)
205 pdf.Cell(35,5, l(:field_status) + ":","LT")
267 pdf.RDMCell(35,5, l(:field_status) + ":","LT")
206 268 pdf.SetFontStyle('',9)
207 pdf.Cell(60,5, issue.status.to_s,"RT")
269 pdf.RDMCell(60,5, issue.status.to_s,"RT")
208 270 pdf.SetFontStyle('B',9)
209 pdf.Cell(35,5, l(:field_priority) + ":","LT")
271 pdf.RDMCell(35,5, l(:field_priority) + ":","LT")
210 272 pdf.SetFontStyle('',9)
211 pdf.Cell(60,5, issue.priority.to_s,"RT")
273 pdf.RDMCell(60,5, issue.priority.to_s,"RT")
212 274 pdf.Ln
213 275
214 276 pdf.SetFontStyle('B',9)
215 pdf.Cell(35,5, l(:field_author) + ":","L")
277 pdf.RDMCell(35,5, l(:field_author) + ":","L")
216 278 pdf.SetFontStyle('',9)
217 pdf.Cell(60,5, issue.author.to_s,"R")
279 pdf.RDMCell(60,5, issue.author.to_s,"R")
218 280 pdf.SetFontStyle('B',9)
219 pdf.Cell(35,5, l(:field_category) + ":","L")
281 pdf.RDMCell(35,5, l(:field_category) + ":","L")
220 282 pdf.SetFontStyle('',9)
221 pdf.Cell(60,5, issue.category.to_s,"R")
283 pdf.RDMCell(60,5, issue.category.to_s,"R")
222 284 pdf.Ln
223 285
224 286 pdf.SetFontStyle('B',9)
225 pdf.Cell(35,5, l(:field_created_on) + ":","L")
287 pdf.RDMCell(35,5, l(:field_created_on) + ":","L")
226 288 pdf.SetFontStyle('',9)
227 pdf.Cell(60,5, format_date(issue.created_on),"R")
289 pdf.RDMCell(60,5, format_date(issue.created_on),"R")
228 290 pdf.SetFontStyle('B',9)
229 pdf.Cell(35,5, l(:field_assigned_to) + ":","L")
291 pdf.RDMCell(35,5, l(:field_assigned_to) + ":","L")
230 292 pdf.SetFontStyle('',9)
231 pdf.Cell(60,5, issue.assigned_to.to_s,"R")
293 pdf.RDMCell(60,5, issue.assigned_to.to_s,"R")
232 294 pdf.Ln
233 295
234 296 pdf.SetFontStyle('B',9)
235 pdf.Cell(35,5, l(:field_updated_on) + ":","LB")
297 pdf.RDMCell(35,5, l(:field_updated_on) + ":","LB")
236 298 pdf.SetFontStyle('',9)
237 pdf.Cell(60,5, format_date(issue.updated_on),"RB")
299 pdf.RDMCell(60,5, format_date(issue.updated_on),"RB")
238 300 pdf.SetFontStyle('B',9)
239 pdf.Cell(35,5, l(:field_due_date) + ":","LB")
301 pdf.RDMCell(35,5, l(:field_due_date) + ":","LB")
240 302 pdf.SetFontStyle('',9)
241 pdf.Cell(60,5, format_date(issue.due_date),"RB")
303 pdf.RDMCell(60,5, format_date(issue.due_date),"RB")
242 304 pdf.Ln
243 305
244 306 for custom_value in issue.custom_field_values
245 307 pdf.SetFontStyle('B',9)
246 pdf.Cell(35,5, custom_value.custom_field.name + ":","L")
308 pdf.RDMCell(35,5, custom_value.custom_field.name + ":","L")
247 309 pdf.SetFontStyle('',9)
248 pdf.MultiCell(155,5, (show_value custom_value),"R")
310 pdf.RDMMultiCell(155,5, (show_value custom_value),"R")
249 311 end
250 312
251 313 pdf.SetFontStyle('B',9)
252 pdf.Cell(35,5, l(:field_subject) + ":","LTB")
314 pdf.RDMCell(35,5, l(:field_subject) + ":","LTB")
253 315 pdf.SetFontStyle('',9)
254 pdf.Cell(155,5, issue.subject,"RTB")
316 pdf.RDMCell(155,5, issue.subject,"RTB")
255 317 pdf.Ln
256 318
257 319 pdf.SetFontStyle('B',9)
258 pdf.Cell(35,5, l(:field_description) + ":")
320 pdf.RDMCell(35,5, l(:field_description) + ":")
259 321 pdf.SetFontStyle('',9)
260 pdf.MultiCell(155,5, issue.description.to_s,"BR")
322 pdf.RDMMultiCell(155,5, issue.description.to_s,"BR")
261 323
262 324 pdf.Line(pdf.GetX, y0, pdf.GetX, pdf.GetY)
263 325 pdf.Line(pdf.GetX, pdf.GetY, 170, pdf.GetY)
@@ -265,49 +327,49 module Redmine
265 327
266 328 if issue.changesets.any? && User.current.allowed_to?(:view_changesets, issue.project)
267 329 pdf.SetFontStyle('B',9)
268 pdf.Cell(190,5, l(:label_associated_revisions), "B")
330 pdf.RDMCell(190,5, l(:label_associated_revisions), "B")
269 331 pdf.Ln
270 332 for changeset in issue.changesets
271 333 pdf.SetFontStyle('B',8)
272 pdf.Cell(190,5, format_time(changeset.committed_on) + " - " + changeset.author.to_s)
334 pdf.RDMCell(190,5, format_time(changeset.committed_on) + " - " + changeset.author.to_s)
273 335 pdf.Ln
274 336 unless changeset.comments.blank?
275 337 pdf.SetFontStyle('',8)
276 pdf.MultiCell(190,5, changeset.comments.to_s)
338 pdf.RDMMultiCell(190,5, changeset.comments.to_s)
277 339 end
278 340 pdf.Ln
279 341 end
280 342 end
281 343
282 344 pdf.SetFontStyle('B',9)
283 pdf.Cell(190,5, l(:label_history), "B")
345 pdf.RDMCell(190,5, l(:label_history), "B")
284 346 pdf.Ln
285 347 for journal in issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
286 348 pdf.SetFontStyle('B',8)
287 pdf.Cell(190,5, format_time(journal.created_on) + " - " + journal.user.name)
349 pdf.RDMCell(190,5, format_time(journal.created_on) + " - " + journal.user.name)
288 350 pdf.Ln
289 351 pdf.SetFontStyle('I',8)
290 352 for detail in journal.details
291 pdf.Cell(190,5, "- " + show_detail(detail, true))
353 pdf.RDMCell(190,5, "- " + show_detail(detail, true))
292 354 pdf.Ln
293 355 end
294 356 if journal.notes?
295 357 pdf.SetFontStyle('',8)
296 pdf.MultiCell(190,5, journal.notes.to_s)
358 pdf.RDMMultiCell(190,5, journal.notes.to_s)
297 359 end
298 360 pdf.Ln
299 361 end
300 362
301 363 if issue.attachments.any?
302 364 pdf.SetFontStyle('B',9)
303 pdf.Cell(190,5, l(:label_attachment_plural), "B")
365 pdf.RDMCell(190,5, l(:label_attachment_plural), "B")
304 366 pdf.Ln
305 367 for attachment in issue.attachments
306 368 pdf.SetFontStyle('',8)
307 pdf.Cell(80,5, attachment.filename)
308 pdf.Cell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
309 pdf.Cell(25,5, format_date(attachment.created_on),0,0,"R")
310 pdf.Cell(65,5, attachment.author.name,0,0,"R")
369 pdf.RDMCell(80,5, attachment.filename)
370 pdf.RDMCell(20,5, number_to_human_size(attachment.filesize),0,0,"R")
371 pdf.RDMCell(25,5, format_date(attachment.created_on),0,0,"R")
372 pdf.RDMCell(65,5, attachment.author.name,0,0,"R")
311 373 pdf.Ln
312 374 end
313 375 end
@@ -509,12 +509,12 module Redmine
509 509 def to_pdf
510 510 pdf = ::Redmine::Export::PDF::IFPDF.new(current_language)
511 511 pdf.SetTitle("#{l(:label_gantt)} #{project}")
512 pdf.AliasNbPages
512 pdf.alias_nb_pages
513 513 pdf.footer_date = format_date(Date.today)
514 514 pdf.AddPage("L")
515 515 pdf.SetFontStyle('B',12)
516 516 pdf.SetX(15)
517 pdf.Cell(PDF::LeftPaneWidth, 20, project.to_s)
517 pdf.RDMCell(PDF::LeftPaneWidth, 20, project.to_s)
518 518 pdf.Ln
519 519 pdf.SetFontStyle('B',9)
520 520
@@ -549,7 +549,7 module Redmine
549 549 width = ((month_f >> 1) - month_f) * zoom
550 550 pdf.SetY(y_start)
551 551 pdf.SetX(left)
552 pdf.Cell(width, height, "#{month_f.year}-#{month_f.month}", "LTR", 0, "C")
552 pdf.RDMCell(width, height, "#{month_f.year}-#{month_f.month}", "LTR", 0, "C")
553 553 left = left + width
554 554 month_f = month_f >> 1
555 555 end
@@ -567,14 +567,14 module Redmine
567 567 width = (7 - self.date_from.cwday + 1) * zoom-1
568 568 pdf.SetY(y_start + header_heigth)
569 569 pdf.SetX(left)
570 pdf.Cell(width + 1, height, "", "LTR")
570 pdf.RDMCell(width + 1, height, "", "LTR")
571 571 left = left + width+1
572 572 end
573 573 while week_f <= self.date_to
574 574 width = (week_f + 6 <= self.date_to) ? 7 * zoom : (self.date_to - week_f + 1) * zoom
575 575 pdf.SetY(y_start + header_heigth)
576 576 pdf.SetX(left)
577 pdf.Cell(width, height, (width >= 5 ? week_f.cweek.to_s : ""), "LTR", 0, "C")
577 pdf.RDMCell(width, height, (width >= 5 ? week_f.cweek.to_s : ""), "LTR", 0, "C")
578 578 left = left + width
579 579 week_f = week_f+7
580 580 end
@@ -590,7 +590,7 module Redmine
590 590 width = zoom
591 591 pdf.SetY(y_start + 2 * header_heigth)
592 592 pdf.SetX(left)
593 pdf.Cell(width, height, day_name(wday).first, "LTR", 0, "C")
593 pdf.RDMCell(width, height, day_name(wday).first, "LTR", 0, "C")
594 594 left = left + width
595 595 wday = wday + 1
596 596 wday = 1 if wday > 7
@@ -599,7 +599,7 module Redmine
599 599
600 600 pdf.SetY(y_start)
601 601 pdf.SetX(15)
602 pdf.Cell(subject_width+g_width-15, headers_heigth, "", 1)
602 pdf.RDMCell(subject_width+g_width-15, headers_heigth, "", 1)
603 603
604 604 # Tasks
605 605 top = headers_heigth + y_start
@@ -719,11 +719,11 module Redmine
719 719 params[:pdf].SetX(15)
720 720
721 721 char_limit = PDF::MaxCharactorsForSubject - params[:indent]
722 params[:pdf].Cell(params[:subject_width]-15, 5, (" " * params[:indent]) + subject.to_s.sub(/^(.{#{char_limit}}[^\s]*\s).*$/, '\1 (...)'), "LR")
722 params[:pdf].RDMCell(params[:subject_width]-15, 5, (" " * params[:indent]) + subject.to_s.sub(/^(.{#{char_limit}}[^\s]*\s).*$/, '\1 (...)'), "LR")
723 723
724 724 params[:pdf].SetY(params[:top])
725 725 params[:pdf].SetX(params[:subject_width])
726 params[:pdf].Cell(params[:g_width], 5, "", "LR")
726 params[:pdf].RDMCell(params[:g_width], 5, "", "LR")
727 727 end
728 728
729 729 def image_subject(params, subject, options={})
@@ -780,19 +780,19 module Redmine
780 780 params[:pdf].SetY(params[:top]+1.5)
781 781 params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
782 782 params[:pdf].SetFillColor(200,200,200)
783 params[:pdf].Cell(coords[:bar_end] - coords[:bar_start], height, "", 0, 0, "", 1)
783 params[:pdf].RDMCell(coords[:bar_end] - coords[:bar_start], height, "", 0, 0, "", 1)
784 784
785 785 if coords[:bar_late_end]
786 786 params[:pdf].SetY(params[:top]+1.5)
787 787 params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
788 788 params[:pdf].SetFillColor(255,100,100)
789 params[:pdf].Cell(coords[:bar_late_end] - coords[:bar_start], height, "", 0, 0, "", 1)
789 params[:pdf].RDMCell(coords[:bar_late_end] - coords[:bar_start], height, "", 0, 0, "", 1)
790 790 end
791 791 if coords[:bar_progress_end]
792 792 params[:pdf].SetY(params[:top]+1.5)
793 793 params[:pdf].SetX(params[:subject_width] + coords[:bar_start])
794 794 params[:pdf].SetFillColor(90,200,90)
795 params[:pdf].Cell(coords[:bar_progress_end] - coords[:bar_start], height, "", 0, 0, "", 1)
795 params[:pdf].RDMCell(coords[:bar_progress_end] - coords[:bar_start], height, "", 0, 0, "", 1)
796 796 end
797 797 end
798 798 # Renders the markers
@@ -801,19 +801,19 module Redmine
801 801 params[:pdf].SetY(params[:top] + 1)
802 802 params[:pdf].SetX(params[:subject_width] + coords[:start] - 1)
803 803 params[:pdf].SetFillColor(50,50,200)
804 params[:pdf].Cell(2, 2, "", 0, 0, "", 1)
804 params[:pdf].RDMCell(2, 2, "", 0, 0, "", 1)
805 805 end
806 806 if coords[:end]
807 807 params[:pdf].SetY(params[:top] + 1)
808 808 params[:pdf].SetX(params[:subject_width] + coords[:end] - 1)
809 809 params[:pdf].SetFillColor(50,50,200)
810 params[:pdf].Cell(2, 2, "", 0, 0, "", 1)
810 params[:pdf].RDMCell(2, 2, "", 0, 0, "", 1)
811 811 end
812 812 end
813 813 # Renders the label on the right
814 814 if options[:label]
815 815 params[:pdf].SetX(params[:subject_width] + (coords[:bar_end] || 0) + 5)
816 params[:pdf].Cell(30, 2, options[:label])
816 params[:pdf].RDMCell(30, 2, options[:label])
817 817 end
818 818 end
819 819
General Comments 0
You need to be logged in to leave comments. Login now