1 // Copyright 2016 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "core/fpdfapi/page/cpdf_page.h" 8 9 #include <set> 10 #include <utility> 11 12 #include "core/fpdfapi/cpdf_pagerendercontext.h" 13 #include "core/fpdfapi/page/cpdf_contentparser.h" 14 #include "core/fpdfapi/page/cpdf_pageobject.h" 15 #include "core/fpdfapi/parser/cpdf_array.h" 16 #include "core/fpdfapi/parser/cpdf_dictionary.h" 17 #include "core/fpdfapi/parser/cpdf_object.h" 18 #include "core/fpdfapi/render/cpdf_pagerendercache.h" 19 #include "third_party/base/ptr_util.h" 20 #include "third_party/base/stl_util.h" 21 22 CPDF_Page::CPDF_Page(CPDF_Document* pDocument, 23 CPDF_Dictionary* pPageDict, 24 bool bPageCache) 25 : CPDF_PageObjectHolder(pDocument, pPageDict), 26 m_PageWidth(100), 27 m_PageHeight(100), 28 m_pView(nullptr) { 29 if (bPageCache) 30 m_pPageRender = pdfium::MakeUnique<CPDF_PageRenderCache>(this); 31 if (!pPageDict) 32 return; 33 34 CPDF_Object* pPageAttr = GetPageAttr("Resources"); 35 m_pResources = pPageAttr ? pPageAttr->GetDict() : nullptr; 36 m_pPageResources = m_pResources; 37 38 CFX_FloatRect mediabox = GetBox("MediaBox"); 39 if (mediabox.IsEmpty()) 40 mediabox = CFX_FloatRect(0, 0, 612, 792); 41 42 m_BBox = GetBox("CropBox"); 43 if (m_BBox.IsEmpty()) 44 m_BBox = mediabox; 45 else 46 m_BBox.Intersect(mediabox); 47 48 m_PageWidth = m_BBox.Width(); 49 m_PageHeight = m_BBox.Height(); 50 51 int rotate = GetPageRotation(); 52 if (rotate % 2) 53 std::swap(m_PageWidth, m_PageHeight); 54 55 switch (rotate) { 56 case 0: 57 m_PageMatrix = CFX_Matrix(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom); 58 break; 59 case 1: 60 m_PageMatrix = 61 CFX_Matrix(0, -1.0f, 1.0f, 0, -m_BBox.bottom, m_BBox.right); 62 break; 63 case 2: 64 m_PageMatrix = CFX_Matrix(-1.0f, 0, 0, -1.0f, m_BBox.right, m_BBox.top); 65 break; 66 case 3: 67 m_PageMatrix = CFX_Matrix(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left); 68 break; 69 } 70 71 m_iTransparency = PDFTRANS_ISOLATED; 72 LoadTransInfo(); 73 } 74 75 CPDF_Page::~CPDF_Page() {} 76 77 bool CPDF_Page::IsPage() const { 78 return true; 79 } 80 81 void CPDF_Page::StartParse() { 82 if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) 83 return; 84 85 m_pParser = pdfium::MakeUnique<CPDF_ContentParser>(this); 86 m_ParseState = CONTENT_PARSING; 87 } 88 89 void CPDF_Page::ParseContent() { 90 StartParse(); 91 ContinueParse(nullptr); 92 } 93 94 void CPDF_Page::SetRenderContext( 95 std::unique_ptr<CPDF_PageRenderContext> pContext) { 96 m_pRenderContext = std::move(pContext); 97 } 98 99 CPDF_Object* CPDF_Page::GetPageAttr(const ByteString& name) const { 100 CPDF_Dictionary* pPageDict = m_pFormDict.Get(); 101 std::set<CPDF_Dictionary*> visited; 102 while (1) { 103 visited.insert(pPageDict); 104 if (CPDF_Object* pObj = pPageDict->GetDirectObjectFor(name)) 105 return pObj; 106 107 pPageDict = pPageDict->GetDictFor("Parent"); 108 if (!pPageDict || pdfium::ContainsKey(visited, pPageDict)) 109 break; 110 } 111 return nullptr; 112 } 113 114 CFX_FloatRect CPDF_Page::GetBox(const ByteString& name) const { 115 CFX_FloatRect box; 116 CPDF_Array* pBox = ToArray(GetPageAttr(name)); 117 if (pBox) { 118 box = pBox->GetRect(); 119 box.Normalize(); 120 } 121 return box; 122 } 123 124 CFX_Matrix CPDF_Page::GetDisplayMatrix(int xPos, 125 int yPos, 126 int xSize, 127 int ySize, 128 int iRotate) const { 129 if (m_PageWidth == 0 || m_PageHeight == 0) 130 return CFX_Matrix(); 131 132 float x0 = 0; 133 float y0 = 0; 134 float x1 = 0; 135 float y1 = 0; 136 float x2 = 0; 137 float y2 = 0; 138 iRotate %= 4; 139 switch (iRotate) { 140 case 0: 141 x0 = xPos; 142 y0 = yPos + ySize; 143 x1 = xPos; 144 y1 = yPos; 145 x2 = xPos + xSize; 146 y2 = yPos + ySize; 147 break; 148 case 1: 149 x0 = xPos; 150 y0 = yPos; 151 x1 = xPos + xSize; 152 y1 = yPos; 153 x2 = xPos; 154 y2 = yPos + ySize; 155 break; 156 case 2: 157 x0 = xPos + xSize; 158 y0 = yPos; 159 x1 = xPos + xSize; 160 y1 = yPos + ySize; 161 x2 = xPos; 162 y2 = yPos; 163 break; 164 case 3: 165 x0 = xPos + xSize; 166 y0 = yPos + ySize; 167 x1 = xPos; 168 y1 = yPos + ySize; 169 x2 = xPos + xSize; 170 y2 = yPos; 171 break; 172 } 173 CFX_Matrix matrix = m_PageMatrix; 174 matrix.Concat(CFX_Matrix((x2 - x0) / m_PageWidth, (y2 - y0) / m_PageWidth, 175 (x1 - x0) / m_PageHeight, (y1 - y0) / m_PageHeight, 176 x0, y0)); 177 return matrix; 178 } 179 180 int CPDF_Page::GetPageRotation() const { 181 CPDF_Object* pRotate = GetPageAttr("Rotate"); 182 int rotate = pRotate ? (pRotate->GetInteger() / 90) % 4 : 0; 183 return (rotate < 0) ? (rotate + 4) : rotate; 184 } 185 186 bool GraphicsData::operator<(const GraphicsData& other) const { 187 if (fillAlpha != other.fillAlpha) 188 return fillAlpha < other.fillAlpha; 189 if (strokeAlpha != other.strokeAlpha) 190 return strokeAlpha < other.strokeAlpha; 191 return blendType < other.blendType; 192 } 193 194 bool FontData::operator<(const FontData& other) const { 195 if (baseFont != other.baseFont) 196 return baseFont < other.baseFont; 197 return type < other.type; 198 } 199