OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "pdf/pdfium/pdfium_engine.h" | 5 #include "pdf/pdfium/pdfium_engine.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "base/i18n/icu_encoding_detection.h" | 9 #include "base/i18n/icu_encoding_detection.h" |
10 #include "base/i18n/icu_string_conversions.h" | 10 #include "base/i18n/icu_string_conversions.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 #include "ppapi/c/private/ppb_pdf.h" | 29 #include "ppapi/c/private/ppb_pdf.h" |
30 #include "ppapi/cpp/dev/memory_dev.h" | 30 #include "ppapi/cpp/dev/memory_dev.h" |
31 #include "ppapi/cpp/input_event.h" | 31 #include "ppapi/cpp/input_event.h" |
32 #include "ppapi/cpp/instance.h" | 32 #include "ppapi/cpp/instance.h" |
33 #include "ppapi/cpp/module.h" | 33 #include "ppapi/cpp/module.h" |
34 #include "ppapi/cpp/private/pdf.h" | 34 #include "ppapi/cpp/private/pdf.h" |
35 #include "ppapi/cpp/trusted/browser_font_trusted.h" | 35 #include "ppapi/cpp/trusted/browser_font_trusted.h" |
36 #include "ppapi/cpp/url_response_info.h" | 36 #include "ppapi/cpp/url_response_info.h" |
37 #include "ppapi/cpp/var.h" | 37 #include "ppapi/cpp/var.h" |
38 #include "ppapi/cpp/var_dictionary.h" | 38 #include "ppapi/cpp/var_dictionary.h" |
| 39 #include "printing/pdf_transform.h" |
39 #include "printing/units.h" | 40 #include "printing/units.h" |
40 #include "third_party/pdfium/public/fpdf_edit.h" | 41 #include "third_party/pdfium/public/fpdf_edit.h" |
41 #include "third_party/pdfium/public/fpdf_ext.h" | 42 #include "third_party/pdfium/public/fpdf_ext.h" |
42 #include "third_party/pdfium/public/fpdf_flatten.h" | 43 #include "third_party/pdfium/public/fpdf_flatten.h" |
43 #include "third_party/pdfium/public/fpdf_ppo.h" | 44 #include "third_party/pdfium/public/fpdf_ppo.h" |
44 #include "third_party/pdfium/public/fpdf_save.h" | 45 #include "third_party/pdfium/public/fpdf_save.h" |
45 #include "third_party/pdfium/public/fpdf_searchex.h" | 46 #include "third_party/pdfium/public/fpdf_searchex.h" |
46 #include "third_party/pdfium/public/fpdf_sysfontinfo.h" | 47 #include "third_party/pdfium/public/fpdf_sysfontinfo.h" |
47 #include "third_party/pdfium/public/fpdf_transformpage.h" | 48 #include "third_party/pdfium/public/fpdf_transformpage.h" |
48 #include "ui/events/keycodes/keyboard_codes.h" | 49 #include "ui/events/keycodes/keyboard_codes.h" |
| 50 #include "ui/gfx/geometry/rect.h" |
49 #include "v8/include/v8.h" | 51 #include "v8/include/v8.h" |
50 | 52 |
51 using printing::ConvertUnit; | 53 using printing::ConvertUnit; |
52 using printing::ConvertUnitDouble; | 54 using printing::ConvertUnitDouble; |
53 using printing::kPointsPerInch; | 55 using printing::kPointsPerInch; |
54 using printing::kPixelsPerInch; | 56 using printing::kPixelsPerInch; |
55 | 57 |
56 namespace chrome_pdf { | 58 namespace chrome_pdf { |
57 | 59 |
58 namespace { | 60 namespace { |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 bool page_orientation_mismatched = is_src_page_landscape != | 318 bool page_orientation_mismatched = is_src_page_landscape != |
317 is_dst_page_landscape; | 319 is_dst_page_landscape; |
318 bool rotate_dst_page = rotated ^ page_orientation_mismatched; | 320 bool rotate_dst_page = rotated ^ page_orientation_mismatched; |
319 if (rotate_dst_page) { | 321 if (rotate_dst_page) { |
320 page_size->SetSize(page_size->height(), page_size->width()); | 322 page_size->SetSize(page_size->height(), page_size->width()); |
321 content_rect->SetRect(content_rect->y(), content_rect->x(), | 323 content_rect->SetRect(content_rect->y(), content_rect->x(), |
322 content_rect->height(), content_rect->width()); | 324 content_rect->height(), content_rect->width()); |
323 } | 325 } |
324 } | 326 } |
325 | 327 |
326 // Calculate the scale factor between |content_rect| and a page of size | |
327 // |src_width| x |src_height|. | |
328 // | |
329 // |content_rect| specifies the printable area of the destination page, with | |
330 // origin at left-bottom. Values are in points. | |
331 // |src_width| specifies the source page width in points. | |
332 // |src_height| specifies the source page height in points. | |
333 // |rotated| True if source page is rotated 90 degree or 270 degree. | |
334 double CalculateScaleFactor(const pp::Rect& content_rect, | |
335 double src_width, | |
336 double src_height, | |
337 bool rotated) { | |
338 if (src_width == 0 || src_height == 0) | |
339 return 1.0; | |
340 | |
341 double actual_source_page_width = rotated ? src_height : src_width; | |
342 double actual_source_page_height = rotated ? src_width : src_height; | |
343 double ratio_x = static_cast<double>(content_rect.width()) / | |
344 actual_source_page_width; | |
345 double ratio_y = static_cast<double>(content_rect.height()) / | |
346 actual_source_page_height; | |
347 return std::min(ratio_x, ratio_y); | |
348 } | |
349 | |
350 // A rect struct for use with FPDF bounding box functions. | |
351 // Remember with PDFs, origin is bottom-left. | |
352 struct ClipBox { | |
353 float left; | |
354 float right; | |
355 float top; | |
356 float bottom; | |
357 }; | |
358 | |
359 // Make the default size to be letter size (8.5" X 11"). We are just following | |
360 // the PDFium way of handling these corner cases. PDFium always consider | |
361 // US-Letter as the default page size. | |
362 void SetDefaultClipBox(bool rotated, ClipBox* clip_box) { | |
363 const int kDpi = 72; | |
364 const float kPaperWidth = 8.5 * kDpi; | |
365 const float kPaperHeight = 11 * kDpi; | |
366 clip_box->left = 0; | |
367 clip_box->bottom = 0; | |
368 clip_box->right = rotated ? kPaperHeight : kPaperWidth; | |
369 clip_box->top = rotated ? kPaperWidth : kPaperHeight; | |
370 } | |
371 | |
372 // Set the media box and/or crop box as needed. If both boxes are there, then | |
373 // nothing needs to be done. If one box is missing, then fill it with the value | |
374 // from the other box. If both boxes are missing, then they both get the default | |
375 // value from SetDefaultClipBox(), based on |rotated|. | |
376 void CalculateMediaBoxAndCropBox(bool rotated, | |
377 bool has_media_box, | |
378 bool has_crop_box, | |
379 ClipBox* media_box, | |
380 ClipBox* crop_box) { | |
381 if (!has_media_box && !has_crop_box) { | |
382 SetDefaultClipBox(rotated, crop_box); | |
383 SetDefaultClipBox(rotated, media_box); | |
384 } else if (has_crop_box && !has_media_box) { | |
385 *media_box = *crop_box; | |
386 } else if (has_media_box && !has_crop_box) { | |
387 *crop_box = *media_box; | |
388 } | |
389 } | |
390 | |
391 // Compute source clip box boundaries based on the crop box / media box of | |
392 // source page. | |
393 // | |
394 // |media_box| The PDF's media box. | |
395 // |crop_box| The PDF's crop box. | |
396 ClipBox CalculateClipBoxBoundary(const ClipBox& media_box, | |
397 const ClipBox& crop_box) { | |
398 ClipBox clip_box; | |
399 | |
400 // Clip |media_box| to the size of |crop_box|, but ignore |crop_box| if it is | |
401 // bigger than |media_box|. | |
402 clip_box.left = | |
403 (crop_box.left < media_box.left) ? media_box.left : crop_box.left; | |
404 clip_box.right = | |
405 (crop_box.right > media_box.right) ? media_box.right : crop_box.right; | |
406 clip_box.top = (crop_box.top > media_box.top) ? media_box.top : crop_box.top; | |
407 clip_box.bottom = | |
408 (crop_box.bottom < media_box.bottom) ? media_box.bottom : crop_box.bottom; | |
409 return clip_box; | |
410 } | |
411 | |
412 // Scale |box| by |scale_factor|. | |
413 void ScaleClipBox(double scale_factor, ClipBox* box) { | |
414 box->left *= scale_factor; | |
415 box->right *= scale_factor; | |
416 box->bottom *= scale_factor; | |
417 box->top *= scale_factor; | |
418 } | |
419 | |
420 // Calculate the clip box translation offset for a page that does need to be | |
421 // scaled. All parameters are in points. | |
422 // | |
423 // |content_rect| specifies the printable area of the destination page, with | |
424 // origin at left-bottom. | |
425 // |source_clip_box| specifies the source clip box positions, relative to | |
426 // origin at left-bottom. | |
427 // |offset_x| and |offset_y| will contain the final translation offsets for the | |
428 // source clip box, relative to origin at left-bottom. | |
429 void CalculateScaledClipBoxOffset(const pp::Rect& content_rect, | |
430 const ClipBox& source_clip_box, | |
431 double* offset_x, double* offset_y) { | |
432 const float clip_box_width = source_clip_box.right - source_clip_box.left; | |
433 const float clip_box_height = source_clip_box.top - source_clip_box.bottom; | |
434 | |
435 // Center the intended clip region to real clip region. | |
436 *offset_x = (content_rect.width() - clip_box_width) / 2 + content_rect.x() - | |
437 source_clip_box.left; | |
438 *offset_y = (content_rect.height() - clip_box_height) / 2 + content_rect.y() - | |
439 source_clip_box.bottom; | |
440 } | |
441 | |
442 // Calculate the clip box offset for a page that does not need to be scaled. | |
443 // All parameters are in points. | |
444 // | |
445 // |content_rect| specifies the printable area of the destination page, with | |
446 // origin at left-bottom. | |
447 // |rotation| specifies the source page rotation values which are N / 90 | |
448 // degrees. | |
449 // |page_width| specifies the screen destination page width. | |
450 // |page_height| specifies the screen destination page height. | |
451 // |source_clip_box| specifies the source clip box positions, relative to origin | |
452 // at left-bottom. | |
453 // |offset_x| and |offset_y| will contain the final translation offsets for the | |
454 // source clip box, relative to origin at left-bottom. | |
455 void CalculateNonScaledClipBoxOffset(const pp::Rect& content_rect, int rotation, | |
456 int page_width, int page_height, | |
457 const ClipBox& source_clip_box, | |
458 double* offset_x, double* offset_y) { | |
459 // Align the intended clip region to left-top corner of real clip region. | |
460 switch (rotation) { | |
461 case 0: | |
462 *offset_x = -1 * source_clip_box.left; | |
463 *offset_y = page_height - source_clip_box.top; | |
464 break; | |
465 case 1: | |
466 *offset_x = 0; | |
467 *offset_y = -1 * source_clip_box.bottom; | |
468 break; | |
469 case 2: | |
470 *offset_x = page_width - source_clip_box.right; | |
471 *offset_y = 0; | |
472 break; | |
473 case 3: | |
474 *offset_x = page_height - source_clip_box.right; | |
475 *offset_y = page_width - source_clip_box.top; | |
476 break; | |
477 default: | |
478 NOTREACHED(); | |
479 break; | |
480 } | |
481 } | |
482 | |
483 // This formats a string with special 0xfffe end-of-line hyphens the same way | 328 // This formats a string with special 0xfffe end-of-line hyphens the same way |
484 // as Adobe Reader. When a hyphen is encountered, the next non-CR/LF whitespace | 329 // as Adobe Reader. When a hyphen is encountered, the next non-CR/LF whitespace |
485 // becomes CR+LF and the hyphen is erased. If there is no whitespace between | 330 // becomes CR+LF and the hyphen is erased. If there is no whitespace between |
486 // two hyphens, the latter hyphen is erased and ignored. | 331 // two hyphens, the latter hyphen is erased and ignored. |
487 void FormatStringWithHyphens(base::string16* text) { | 332 void FormatStringWithHyphens(base::string16* text) { |
488 // First pass marks all the hyphen positions. | 333 // First pass marks all the hyphen positions. |
489 struct HyphenPosition { | 334 struct HyphenPosition { |
490 HyphenPosition() : position(0), next_whitespace_position(0) {} | 335 HyphenPosition() : position(0), next_whitespace_position(0) {} |
491 size_t position; | 336 size_t position; |
492 size_t next_whitespace_position; // 0 for none | 337 size_t next_whitespace_position; // 0 for none |
(...skipping 2919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3412 src_page_width > src_page_height, | 3257 src_page_width > src_page_height, |
3413 &page_size, | 3258 &page_size, |
3414 &content_rect); | 3259 &content_rect); |
3415 | 3260 |
3416 // Compute the screen page width and height in points. | 3261 // Compute the screen page width and height in points. |
3417 const int actual_page_width = | 3262 const int actual_page_width = |
3418 rotated ? page_size.height() : page_size.width(); | 3263 rotated ? page_size.height() : page_size.width(); |
3419 const int actual_page_height = | 3264 const int actual_page_height = |
3420 rotated ? page_size.width() : page_size.height(); | 3265 rotated ? page_size.width() : page_size.height(); |
3421 | 3266 |
| 3267 const gfx::Rect gfx_content_rect(content_rect.x(), |
| 3268 content_rect.y(), |
| 3269 content_rect.width(), |
| 3270 content_rect.height()); |
3422 const double scale_factor = fit_to_page ? | 3271 const double scale_factor = fit_to_page ? |
3423 CalculateScaleFactor( | 3272 printing::CalculateScaleFactor( |
3424 content_rect, src_page_width, src_page_height, rotated) : 1.0; | 3273 gfx_content_rect, src_page_width, src_page_height, rotated) : 1.0; |
3425 | 3274 |
3426 // Calculate positions for the clip box. | 3275 // Calculate positions for the clip box. |
3427 ClipBox media_box; | 3276 printing::ClipBox media_box; |
3428 ClipBox crop_box; | 3277 printing::ClipBox crop_box; |
3429 bool has_media_box = !!FPDFPage_GetMediaBox(page, | 3278 bool has_media_box = !!FPDFPage_GetMediaBox(page, |
3430 &media_box.left, | 3279 &media_box.left, |
3431 &media_box.bottom, | 3280 &media_box.bottom, |
3432 &media_box.right, | 3281 &media_box.right, |
3433 &media_box.top); | 3282 &media_box.top); |
3434 bool has_crop_box = !!FPDFPage_GetCropBox(page, | 3283 bool has_crop_box = !!FPDFPage_GetCropBox(page, |
3435 &crop_box.left, | 3284 &crop_box.left, |
3436 &crop_box.bottom, | 3285 &crop_box.bottom, |
3437 &crop_box.right, | 3286 &crop_box.right, |
3438 &crop_box.top); | 3287 &crop_box.top); |
3439 CalculateMediaBoxAndCropBox( | 3288 printing::CalculateMediaBoxAndCropBox( |
3440 rotated, has_media_box, has_crop_box, &media_box, &crop_box); | 3289 rotated, has_media_box, has_crop_box, &media_box, &crop_box); |
3441 ClipBox source_clip_box = CalculateClipBoxBoundary(media_box, crop_box); | 3290 printing::ClipBox source_clip_box = |
3442 ScaleClipBox(scale_factor, &source_clip_box); | 3291 printing::CalculateClipBoxBoundary(media_box, crop_box); |
| 3292 printing::ScaleClipBox(scale_factor, &source_clip_box); |
3443 | 3293 |
3444 // Calculate the translation offset values. | 3294 // Calculate the translation offset values. |
3445 double offset_x = 0; | 3295 double offset_x = 0; |
3446 double offset_y = 0; | 3296 double offset_y = 0; |
3447 if (fit_to_page) { | 3297 if (fit_to_page) { |
3448 CalculateScaledClipBoxOffset(content_rect, source_clip_box, &offset_x, | 3298 printing::CalculateScaledClipBoxOffset( |
3449 &offset_y); | 3299 gfx_content_rect, source_clip_box, &offset_x, &offset_y); |
3450 } else { | 3300 } else { |
3451 CalculateNonScaledClipBoxOffset(content_rect, src_page_rotation, | 3301 printing::CalculateNonScaledClipBoxOffset( |
3452 actual_page_width, actual_page_height, | 3302 gfx_content_rect, src_page_rotation, |
3453 source_clip_box, &offset_x, &offset_y); | 3303 actual_page_width, actual_page_height, |
| 3304 source_clip_box, &offset_x, &offset_y); |
3454 } | 3305 } |
3455 | 3306 |
3456 // Reset the media box and crop box. When the page has crop box and media box, | 3307 // Reset the media box and crop box. When the page has crop box and media box, |
3457 // the plugin will display the crop box contents and not the entire media box. | 3308 // the plugin will display the crop box contents and not the entire media box. |
3458 // If the pages have different crop box values, the plugin will display a | 3309 // If the pages have different crop box values, the plugin will display a |
3459 // document of multiple page sizes. To give better user experience, we | 3310 // document of multiple page sizes. To give better user experience, we |
3460 // decided to have same crop box and media box values. Hence, the user will | 3311 // decided to have same crop box and media box values. Hence, the user will |
3461 // see a list of uniform pages. | 3312 // see a list of uniform pages. |
3462 FPDFPage_SetMediaBox(page, 0, 0, page_size.width(), page_size.height()); | 3313 FPDFPage_SetMediaBox(page, 0, 0, page_size.width(), page_size.height()); |
3463 FPDFPage_SetCropBox(page, 0, 0, page_size.width(), page_size.height()); | 3314 FPDFPage_SetCropBox(page, 0, 0, page_size.width(), page_size.height()); |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4118 double* height) { | 3969 double* height) { |
4119 FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, NULL); | 3970 FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, NULL); |
4120 if (!doc) | 3971 if (!doc) |
4121 return false; | 3972 return false; |
4122 bool success = FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0; | 3973 bool success = FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0; |
4123 FPDF_CloseDocument(doc); | 3974 FPDF_CloseDocument(doc); |
4124 return success; | 3975 return success; |
4125 } | 3976 } |
4126 | 3977 |
4127 } // namespace chrome_pdf | 3978 } // namespace chrome_pdf |
OLD | NEW |