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/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 password_tries_remaining_(0), | 559 password_tries_remaining_(0), |
560 doc_(NULL), | 560 doc_(NULL), |
561 form_(NULL), | 561 form_(NULL), |
562 defer_page_unload_(false), | 562 defer_page_unload_(false), |
563 selecting_(false), | 563 selecting_(false), |
564 mouse_down_state_(PDFiumPage::NONSELECTABLE_AREA, | 564 mouse_down_state_(PDFiumPage::NONSELECTABLE_AREA, |
565 PDFiumPage::LinkTarget()), | 565 PDFiumPage::LinkTarget()), |
566 next_page_to_search_(-1), | 566 next_page_to_search_(-1), |
567 last_page_to_search_(-1), | 567 last_page_to_search_(-1), |
568 last_character_index_to_search_(-1), | 568 last_character_index_to_search_(-1), |
569 current_find_index_(-1), | |
570 resume_find_index_(-1), | |
571 permissions_(0), | 569 permissions_(0), |
572 fpdf_availability_(NULL), | 570 fpdf_availability_(NULL), |
573 next_timer_id_(0), | 571 next_timer_id_(0), |
574 last_page_mouse_down_(-1), | 572 last_page_mouse_down_(-1), |
575 first_visible_page_(-1), | 573 first_visible_page_(-1), |
576 most_visible_page_(-1), | 574 most_visible_page_(-1), |
577 called_do_document_action_(false), | 575 called_do_document_action_(false), |
578 render_grayscale_(false), | 576 render_grayscale_(false), |
579 progressive_paint_timeout_(0), | 577 progressive_paint_timeout_(0), |
580 getting_password_(false) { | 578 getting_password_(false) { |
(...skipping 1098 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1679 // Started midway, but only 1 page and we already looped around. | 1677 // Started midway, but only 1 page and we already looped around. |
1680 (pages_.size() == 1 && !first_search) || | 1678 (pages_.size() == 1 && !first_search) || |
1681 // Started midway, and we've just looped around. | 1679 // Started midway, and we've just looped around. |
1682 (pages_.size() > 1 && current_page == next_page_to_search_)); | 1680 (pages_.size() > 1 && current_page == next_page_to_search_)); |
1683 | 1681 |
1684 if (end_of_search) { | 1682 if (end_of_search) { |
1685 // Send the final notification. | 1683 // Send the final notification. |
1686 client_->NotifyNumberOfFindResultsChanged(find_results_.size(), true); | 1684 client_->NotifyNumberOfFindResultsChanged(find_results_.size(), true); |
1687 | 1685 |
1688 // When searching is complete, resume finding at a particular index. | 1686 // When searching is complete, resume finding at a particular index. |
1689 if (resume_find_index_ != -1) { | 1687 // Assuming the user has not clicked the find button in the meanwhile. |
1690 current_find_index_ = resume_find_index_; | 1688 if (resume_find_index_.valid() && !current_find_index_.valid()) { |
1691 resume_find_index_ = -1; | 1689 size_t resume_index = resume_find_index_.GetIndex(); |
| 1690 if (resume_index >= find_results_.size()) { |
| 1691 // This might happen if the PDF has some dynamically generated text? |
| 1692 resume_index = 0; |
| 1693 } |
| 1694 current_find_index_.SetIndex(resume_index); |
| 1695 client_->NotifySelectedFindResultChanged(resume_index); |
1692 } | 1696 } |
| 1697 resume_find_index_.Invalidate(); |
1693 } else { | 1698 } else { |
1694 pp::CompletionCallback callback = | 1699 pp::CompletionCallback callback = |
1695 find_factory_.NewCallback(&PDFiumEngine::ContinueFind); | 1700 find_factory_.NewCallback(&PDFiumEngine::ContinueFind); |
1696 pp::Module::Get()->core()->CallOnMainThread( | 1701 pp::Module::Get()->core()->CallOnMainThread( |
1697 0, callback, case_sensitive ? 1 : 0); | 1702 0, callback, case_sensitive ? 1 : 0); |
1698 } | 1703 } |
1699 } | 1704 } |
1700 | 1705 |
1701 void PDFiumEngine::SearchUsingPDFium(const base::string16& term, | 1706 void PDFiumEngine::SearchUsingPDFium(const base::string16& term, |
1702 bool case_sensitive, | 1707 bool case_sensitive, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1765 int end = FPDFText_GetCharIndexFromTextIndex( | 1770 int end = FPDFText_GetCharIndexFromTextIndex( |
1766 pages_[current_page]->GetTextPage(), | 1771 pages_[current_page]->GetTextPage(), |
1767 temp_start + results[i].length); | 1772 temp_start + results[i].length); |
1768 AddFindResult(PDFiumRange(pages_[current_page], start, end - start)); | 1773 AddFindResult(PDFiumRange(pages_[current_page], start, end - start)); |
1769 } | 1774 } |
1770 } | 1775 } |
1771 | 1776 |
1772 void PDFiumEngine::AddFindResult(const PDFiumRange& result) { | 1777 void PDFiumEngine::AddFindResult(const PDFiumRange& result) { |
1773 // Figure out where to insert the new location, since we could have | 1778 // Figure out where to insert the new location, since we could have |
1774 // started searching midway and now we wrapped. | 1779 // started searching midway and now we wrapped. |
1775 size_t i; | 1780 size_t result_index; |
1776 int page_index = result.page_index(); | 1781 int page_index = result.page_index(); |
1777 int char_index = result.char_index(); | 1782 int char_index = result.char_index(); |
1778 for (i = 0; i < find_results_.size(); ++i) { | 1783 for (result_index = 0; result_index < find_results_.size(); ++result_index) { |
1779 if (find_results_[i].page_index() > page_index || | 1784 if (find_results_[result_index].page_index() > page_index || |
1780 (find_results_[i].page_index() == page_index && | 1785 (find_results_[result_index].page_index() == page_index && |
1781 find_results_[i].char_index() > char_index)) { | 1786 find_results_[result_index].char_index() > char_index)) { |
1782 break; | 1787 break; |
1783 } | 1788 } |
1784 } | 1789 } |
1785 find_results_.insert(find_results_.begin() + i, result); | 1790 find_results_.insert(find_results_.begin() + result_index, result); |
1786 UpdateTickMarks(); | 1791 UpdateTickMarks(); |
1787 | 1792 |
1788 if (current_find_index_ == -1 && resume_find_index_ == -1) { | 1793 if (current_find_index_.valid()) { |
1789 // Select the first match. | 1794 if (result_index <= current_find_index_.GetIndex()) { |
| 1795 // Update the current match index |
| 1796 size_t find_index = current_find_index_.IncrementIndex(); |
| 1797 DCHECK_LT(find_index, find_results_.size()); |
| 1798 client_->NotifySelectedFindResultChanged(current_find_index_.GetIndex()); |
| 1799 } |
| 1800 } else if (!resume_find_index_.valid()) { |
| 1801 // Both indices are invalid. Select the first match. |
1790 SelectFindResult(true); | 1802 SelectFindResult(true); |
1791 } else if (static_cast<int>(i) <= current_find_index_) { | |
1792 // Update the current match index | |
1793 current_find_index_++; | |
1794 client_->NotifySelectedFindResultChanged(current_find_index_); | |
1795 } | 1803 } |
1796 client_->NotifyNumberOfFindResultsChanged(find_results_.size(), false); | 1804 client_->NotifyNumberOfFindResultsChanged(find_results_.size(), false); |
1797 } | 1805 } |
1798 | 1806 |
1799 bool PDFiumEngine::SelectFindResult(bool forward) { | 1807 bool PDFiumEngine::SelectFindResult(bool forward) { |
1800 if (find_results_.empty()) { | 1808 if (find_results_.empty()) { |
1801 NOTREACHED(); | 1809 NOTREACHED(); |
1802 return false; | 1810 return false; |
1803 } | 1811 } |
1804 | 1812 |
1805 SelectionChangeInvalidator selection_invalidator(this); | 1813 SelectionChangeInvalidator selection_invalidator(this); |
1806 | 1814 |
1807 // Move back/forward through the search locations we previously found. | 1815 // Move back/forward through the search locations we previously found. |
1808 if (forward) { | 1816 size_t new_index; |
1809 if (++current_find_index_ == static_cast<int>(find_results_.size())) | 1817 const size_t last_index = find_results_.size() - 1; |
1810 current_find_index_ = 0; | 1818 if (current_find_index_.valid()) { |
| 1819 size_t current_index = current_find_index_.GetIndex(); |
| 1820 if (forward) { |
| 1821 new_index = (current_index >= last_index) ? 0 : current_index + 1; |
| 1822 } else { |
| 1823 new_index = (current_find_index_.GetIndex() == 0) ? |
| 1824 last_index : current_index - 1; |
| 1825 } |
1811 } else { | 1826 } else { |
1812 if (--current_find_index_ < 0) { | 1827 new_index = forward ? 0 : last_index; |
1813 current_find_index_ = find_results_.size() - 1; | |
1814 } | |
1815 } | 1828 } |
| 1829 current_find_index_.SetIndex(new_index); |
1816 | 1830 |
1817 // Update the selection before telling the client to scroll, since it could | 1831 // Update the selection before telling the client to scroll, since it could |
1818 // paint then. | 1832 // paint then. |
1819 selection_.clear(); | 1833 selection_.clear(); |
1820 selection_.push_back(find_results_[current_find_index_]); | 1834 selection_.push_back(find_results_[current_find_index_.GetIndex()]); |
1821 | 1835 |
1822 // If the result is not in view, scroll to it. | 1836 // If the result is not in view, scroll to it. |
1823 size_t i; | |
1824 pp::Rect bounding_rect; | 1837 pp::Rect bounding_rect; |
1825 pp::Rect visible_rect = GetVisibleRect(); | 1838 pp::Rect visible_rect = GetVisibleRect(); |
1826 // Use zoom of 1.0 since visible_rect is without zoom. | 1839 // Use zoom of 1.0 since visible_rect is without zoom. |
1827 std::vector<pp::Rect> rects = find_results_[current_find_index_]. | 1840 std::vector<pp::Rect> rects; |
1828 GetScreenRects(pp::Point(), 1.0, current_rotation_); | 1841 rects = find_results_[current_find_index_.GetIndex()].GetScreenRects( |
1829 for (i = 0; i < rects.size(); ++i) | 1842 pp::Point(), 1.0, current_rotation_); |
| 1843 for (size_t i = 0; i < rects.size(); ++i) |
1830 bounding_rect = bounding_rect.Union(rects[i]); | 1844 bounding_rect = bounding_rect.Union(rects[i]); |
1831 if (!visible_rect.Contains(bounding_rect)) { | 1845 if (!visible_rect.Contains(bounding_rect)) { |
1832 pp::Point center = bounding_rect.CenterPoint(); | 1846 pp::Point center = bounding_rect.CenterPoint(); |
1833 // Make the page centered. | 1847 // Make the page centered. |
1834 int new_y = static_cast<int>(center.y() * current_zoom_) - | 1848 int new_y = static_cast<int>(center.y() * current_zoom_) - |
1835 static_cast<int>(visible_rect.height() * current_zoom_ / 2); | 1849 static_cast<int>(visible_rect.height() * current_zoom_ / 2); |
1836 if (new_y < 0) | 1850 if (new_y < 0) |
1837 new_y = 0; | 1851 new_y = 0; |
1838 client_->ScrollToY(new_y); | 1852 client_->ScrollToY(new_y); |
1839 | 1853 |
1840 // Only move horizontally if it's not visible. | 1854 // Only move horizontally if it's not visible. |
1841 if (center.x() < visible_rect.x() || center.x() > visible_rect.right()) { | 1855 if (center.x() < visible_rect.x() || center.x() > visible_rect.right()) { |
1842 int new_x = static_cast<int>(center.x() * current_zoom_) - | 1856 int new_x = static_cast<int>(center.x() * current_zoom_) - |
1843 static_cast<int>(visible_rect.width() * current_zoom_ / 2); | 1857 static_cast<int>(visible_rect.width() * current_zoom_ / 2); |
1844 if (new_x < 0) | 1858 if (new_x < 0) |
1845 new_x = 0; | 1859 new_x = 0; |
1846 client_->ScrollToX(new_x); | 1860 client_->ScrollToX(new_x); |
1847 } | 1861 } |
1848 } | 1862 } |
1849 | 1863 |
1850 client_->NotifySelectedFindResultChanged(current_find_index_); | 1864 client_->NotifySelectedFindResultChanged(current_find_index_.GetIndex()); |
1851 | |
1852 return true; | 1865 return true; |
1853 } | 1866 } |
1854 | 1867 |
1855 void PDFiumEngine::StopFind() { | 1868 void PDFiumEngine::StopFind() { |
1856 SelectionChangeInvalidator selection_invalidator(this); | 1869 SelectionChangeInvalidator selection_invalidator(this); |
1857 | 1870 |
1858 selection_.clear(); | 1871 selection_.clear(); |
1859 selecting_ = false; | 1872 selecting_ = false; |
1860 find_results_.clear(); | 1873 find_results_.clear(); |
1861 next_page_to_search_ = -1; | 1874 next_page_to_search_ = -1; |
1862 last_page_to_search_ = -1; | 1875 last_page_to_search_ = -1; |
1863 last_character_index_to_search_ = -1; | 1876 last_character_index_to_search_ = -1; |
1864 current_find_index_ = -1; | 1877 current_find_index_.Invalidate(); |
1865 current_find_text_.clear(); | 1878 current_find_text_.clear(); |
1866 UpdateTickMarks(); | 1879 UpdateTickMarks(); |
1867 find_factory_.CancelAll(); | 1880 find_factory_.CancelAll(); |
1868 } | 1881 } |
1869 | 1882 |
1870 void PDFiumEngine::UpdateTickMarks() { | 1883 void PDFiumEngine::UpdateTickMarks() { |
1871 std::vector<pp::Rect> tickmarks; | 1884 std::vector<pp::Rect> tickmarks; |
1872 for (size_t i = 0; i < find_results_.size(); ++i) { | 1885 for (size_t i = 0; i < find_results_.size(); ++i) { |
1873 pp::Rect rect; | 1886 pp::Rect rect; |
1874 // Always use an origin of 0,0 since scroll positions don't affect tickmark. | 1887 // Always use an origin of 0,0 since scroll positions don't affect tickmark. |
(...skipping 11 matching lines...) Expand all Loading... |
1886 CancelPaints(); | 1899 CancelPaints(); |
1887 | 1900 |
1888 current_zoom_ = new_zoom_level; | 1901 current_zoom_ = new_zoom_level; |
1889 | 1902 |
1890 CalculateVisiblePages(); | 1903 CalculateVisiblePages(); |
1891 UpdateTickMarks(); | 1904 UpdateTickMarks(); |
1892 } | 1905 } |
1893 | 1906 |
1894 void PDFiumEngine::RotateClockwise() { | 1907 void PDFiumEngine::RotateClockwise() { |
1895 current_rotation_ = (current_rotation_ + 1) % 4; | 1908 current_rotation_ = (current_rotation_ + 1) % 4; |
1896 | 1909 RotateInternal(); |
1897 // Store the current find index so that we can resume finding at that | |
1898 // particular index after we have recomputed the find results. | |
1899 std::string current_find_text = current_find_text_; | |
1900 resume_find_index_ = current_find_index_; | |
1901 | |
1902 InvalidateAllPages(); | |
1903 | |
1904 if (!current_find_text.empty()) | |
1905 StartFind(current_find_text.c_str(), false); | |
1906 } | 1910 } |
1907 | 1911 |
1908 void PDFiumEngine::RotateCounterclockwise() { | 1912 void PDFiumEngine::RotateCounterclockwise() { |
1909 current_rotation_ = (current_rotation_ - 1) % 4; | 1913 current_rotation_ = (current_rotation_ - 1) % 4; |
1910 | 1914 RotateInternal(); |
1911 // Store the current find index so that we can resume finding at that | |
1912 // particular index after we have recomputed the find results. | |
1913 std::string current_find_text = current_find_text_; | |
1914 resume_find_index_ = current_find_index_; | |
1915 | |
1916 InvalidateAllPages(); | |
1917 | |
1918 if (!current_find_text.empty()) | |
1919 StartFind(current_find_text.c_str(), false); | |
1920 } | 1915 } |
1921 | 1916 |
1922 void PDFiumEngine::InvalidateAllPages() { | 1917 void PDFiumEngine::InvalidateAllPages() { |
1923 CancelPaints(); | 1918 CancelPaints(); |
1924 StopFind(); | 1919 StopFind(); |
1925 LoadPageInfo(true); | 1920 LoadPageInfo(true); |
1926 client_->Invalidate(pp::Rect(plugin_size_)); | 1921 client_->Invalidate(pp::Rect(plugin_size_)); |
1927 } | 1922 } |
1928 | 1923 |
1929 std::string PDFiumEngine::GetSelectedText() { | 1924 std::string PDFiumEngine::GetSelectedText() { |
(...skipping 872 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2802 if (area_ == area) { | 2797 if (area_ == area) { |
2803 if (area == PDFiumPage::WEBLINK_AREA) | 2798 if (area == PDFiumPage::WEBLINK_AREA) |
2804 return target_.url == target.url; | 2799 return target_.url == target.url; |
2805 if (area == PDFiumPage::DOCLINK_AREA) | 2800 if (area == PDFiumPage::DOCLINK_AREA) |
2806 return target_.page == target.page; | 2801 return target_.page == target.page; |
2807 return true; | 2802 return true; |
2808 } | 2803 } |
2809 return false; | 2804 return false; |
2810 } | 2805 } |
2811 | 2806 |
| 2807 PDFiumEngine::FindTextIndex::FindTextIndex() |
| 2808 : valid_(false), index_(0) { |
| 2809 } |
| 2810 |
| 2811 PDFiumEngine::FindTextIndex::~FindTextIndex() { |
| 2812 } |
| 2813 |
| 2814 void PDFiumEngine::FindTextIndex::Invalidate() { |
| 2815 valid_ = false; |
| 2816 } |
| 2817 |
| 2818 size_t PDFiumEngine::FindTextIndex::GetIndex() const { |
| 2819 DCHECK(valid_); |
| 2820 return index_; |
| 2821 } |
| 2822 |
| 2823 void PDFiumEngine::FindTextIndex::SetIndex(size_t index) { |
| 2824 valid_ = true; |
| 2825 index_ = index; |
| 2826 } |
| 2827 |
| 2828 size_t PDFiumEngine::FindTextIndex::IncrementIndex() { |
| 2829 DCHECK(valid_); |
| 2830 return ++index_; |
| 2831 } |
| 2832 |
2812 void PDFiumEngine::DeviceToPage(int page_index, | 2833 void PDFiumEngine::DeviceToPage(int page_index, |
2813 float device_x, | 2834 float device_x, |
2814 float device_y, | 2835 float device_y, |
2815 double* page_x, | 2836 double* page_x, |
2816 double* page_y) { | 2837 double* page_y) { |
2817 *page_x = *page_y = 0; | 2838 *page_x = *page_y = 0; |
2818 int temp_x = static_cast<int>((device_x + position_.x())/ current_zoom_ - | 2839 int temp_x = static_cast<int>((device_x + position_.x())/ current_zoom_ - |
2819 pages_[page_index]->rect().x()); | 2840 pages_[page_index]->rect().x()); |
2820 int temp_y = static_cast<int>((device_y + position_.y())/ current_zoom_ - | 2841 int temp_y = static_cast<int>((device_y + position_.y())/ current_zoom_ - |
2821 pages_[page_index]->rect().y()); | 2842 pages_[page_index]->rect().y()); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2981 buffer += location.y() * (*stride); | 3002 buffer += location.y() * (*stride); |
2982 buffer += (location.x() + page_offset_.x()) * 4; | 3003 buffer += (location.x() + page_offset_.x()) * 4; |
2983 *region = buffer; | 3004 *region = buffer; |
2984 } | 3005 } |
2985 | 3006 |
2986 void PDFiumEngine::OnSelectionChanged() { | 3007 void PDFiumEngine::OnSelectionChanged() { |
2987 if (HasPermission(PDFEngine::PERMISSION_COPY)) | 3008 if (HasPermission(PDFEngine::PERMISSION_COPY)) |
2988 pp::PDF::SetSelectedText(GetPluginInstance(), GetSelectedText().c_str()); | 3009 pp::PDF::SetSelectedText(GetPluginInstance(), GetSelectedText().c_str()); |
2989 } | 3010 } |
2990 | 3011 |
| 3012 void PDFiumEngine::RotateInternal() { |
| 3013 // Store the current find index so that we can resume finding at that |
| 3014 // particular index after we have recomputed the find results. |
| 3015 std::string current_find_text = current_find_text_; |
| 3016 if (current_find_index_.valid()) |
| 3017 resume_find_index_.SetIndex(current_find_index_.GetIndex()); |
| 3018 else |
| 3019 resume_find_index_.Invalidate(); |
| 3020 |
| 3021 InvalidateAllPages(); |
| 3022 |
| 3023 if (!current_find_text.empty()) { |
| 3024 // Clear the UI. |
| 3025 client_->NotifyNumberOfFindResultsChanged(0, false); |
| 3026 StartFind(current_find_text.c_str(), false); |
| 3027 } |
| 3028 } |
| 3029 |
2991 void PDFiumEngine::Form_Invalidate(FPDF_FORMFILLINFO* param, | 3030 void PDFiumEngine::Form_Invalidate(FPDF_FORMFILLINFO* param, |
2992 FPDF_PAGE page, | 3031 FPDF_PAGE page, |
2993 double left, | 3032 double left, |
2994 double top, | 3033 double top, |
2995 double right, | 3034 double right, |
2996 double bottom) { | 3035 double bottom) { |
2997 PDFiumEngine* engine = static_cast<PDFiumEngine*>(param); | 3036 PDFiumEngine* engine = static_cast<PDFiumEngine*>(param); |
2998 int page_index = engine->GetVisiblePageIndex(page); | 3037 int page_index = engine->GetVisiblePageIndex(page); |
2999 if (page_index == -1) { | 3038 if (page_index == -1) { |
3000 // This can sometime happen when the page is closed because it went off | 3039 // This can sometime happen when the page is closed because it went off |
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3536 double* height) { | 3575 double* height) { |
3537 FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, NULL); | 3576 FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, NULL); |
3538 if (!doc) | 3577 if (!doc) |
3539 return false; | 3578 return false; |
3540 bool success = FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0; | 3579 bool success = FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0; |
3541 FPDF_CloseDocument(doc); | 3580 FPDF_CloseDocument(doc); |
3542 return success; | 3581 return success; |
3543 } | 3582 } |
3544 | 3583 |
3545 } // namespace chrome_pdf | 3584 } // namespace chrome_pdf |
OLD | NEW |