1 // Copyright 2014 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 "../../../include/fpdfapi/fpdf_page.h" 8 #include "pageint.h" 9 CPDF_TilingPattern::CPDF_TilingPattern(CPDF_Document* pDoc, CPDF_Object* pPatternObj, const CFX_AffineMatrix* parentMatrix) : 10 CPDF_Pattern(parentMatrix) 11 { 12 m_PatternType = PATTERN_TILING; 13 m_pPatternObj = pPatternObj; 14 m_pDocument = pDoc; 15 CPDF_Dictionary* pDict = m_pPatternObj->GetDict(); 16 ASSERT(pDict != NULL); 17 m_Pattern2Form = pDict->GetMatrix(FX_BSTRC("Matrix")); 18 m_bColored = pDict->GetInteger(FX_BSTRC("PaintType")) == 1; 19 if (parentMatrix) { 20 m_Pattern2Form.Concat(*parentMatrix); 21 } 22 m_pForm = NULL; 23 } 24 CPDF_TilingPattern::~CPDF_TilingPattern() 25 { 26 if (m_pForm) { 27 delete m_pForm; 28 } 29 } 30 FX_BOOL CPDF_TilingPattern::Load() 31 { 32 if (m_pForm != NULL) { 33 return TRUE; 34 } 35 CPDF_Dictionary* pDict = m_pPatternObj->GetDict(); 36 if (pDict == NULL) { 37 return FALSE; 38 } 39 m_bColored = pDict->GetInteger(FX_BSTRC("PaintType")) == 1; 40 m_XStep = (FX_FLOAT)FXSYS_fabs(pDict->GetNumber(FX_BSTRC("XStep"))); 41 m_YStep = (FX_FLOAT)FXSYS_fabs(pDict->GetNumber(FX_BSTRC("YStep"))); 42 if (m_pPatternObj->GetType() != PDFOBJ_STREAM) { 43 return FALSE; 44 } 45 CPDF_Stream* pStream = (CPDF_Stream*)m_pPatternObj; 46 m_pForm = FX_NEW CPDF_Form(m_pDocument, NULL, pStream); 47 m_pForm->ParseContent(NULL, &m_ParentMatrix, NULL, NULL); 48 m_BBox = pDict->GetRect(FX_BSTRC("BBox")); 49 return TRUE; 50 } 51 CPDF_ShadingPattern::CPDF_ShadingPattern(CPDF_Document* pDoc, CPDF_Object* pPatternObj, FX_BOOL bShading, const CFX_AffineMatrix* parentMatrix) : CPDF_Pattern(parentMatrix) 52 { 53 m_PatternType = PATTERN_SHADING; 54 m_pPatternObj = bShading ? NULL : pPatternObj; 55 m_pDocument = pDoc; 56 m_bShadingObj = bShading; 57 if (!bShading) { 58 CPDF_Dictionary* pDict = m_pPatternObj->GetDict(); 59 ASSERT(pDict != NULL); 60 m_Pattern2Form = pDict->GetMatrix(FX_BSTRC("Matrix")); 61 m_pShadingObj = pDict->GetElementValue(FX_BSTRC("Shading")); 62 if (parentMatrix) { 63 m_Pattern2Form.Concat(*parentMatrix); 64 } 65 } else { 66 m_pShadingObj = pPatternObj; 67 } 68 m_ShadingType = 0; 69 m_pCS = NULL; 70 m_nFuncs = 0; 71 for (int i = 0; i < 4; i ++) { 72 m_pFunctions[i] = NULL; 73 } 74 } 75 CPDF_ShadingPattern::~CPDF_ShadingPattern() 76 { 77 Clear(); 78 } 79 void CPDF_ShadingPattern::Clear() 80 { 81 for (int i = 0; i < m_nFuncs; i ++) { 82 if (m_pFunctions[i]) { 83 delete m_pFunctions[i]; 84 } 85 m_pFunctions[i] = NULL; 86 } 87 CPDF_ColorSpace* pCS = m_pCS; 88 if (pCS && m_pDocument) { 89 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); 90 } 91 m_ShadingType = 0; 92 m_pCS = NULL; 93 m_nFuncs = 0; 94 } 95 FX_BOOL CPDF_ShadingPattern::Load() 96 { 97 if (m_ShadingType != 0) { 98 return TRUE; 99 } 100 CPDF_Dictionary* pShadingDict = m_pShadingObj->GetDict(); 101 if (pShadingDict == NULL) { 102 return FALSE; 103 } 104 if (m_nFuncs) { 105 for (int i = 0; i < m_nFuncs; i ++) 106 if (m_pFunctions[i]) { 107 delete m_pFunctions[i]; 108 } 109 m_nFuncs = 0; 110 } 111 CPDF_Object* pFunc = pShadingDict->GetElementValue(FX_BSTRC("Function")); 112 if (pFunc) { 113 if (pFunc->GetType() == PDFOBJ_ARRAY) { 114 m_nFuncs = ((CPDF_Array*)pFunc)->GetCount(); 115 if (m_nFuncs > 4) { 116 m_nFuncs = 4; 117 } 118 for (int i = 0; i < m_nFuncs; i ++) { 119 m_pFunctions[i] = CPDF_Function::Load(((CPDF_Array*)pFunc)->GetElementValue(i)); 120 } 121 } else { 122 m_pFunctions[0] = CPDF_Function::Load(pFunc); 123 m_nFuncs = 1; 124 } 125 } 126 CPDF_Object* pCSObj = pShadingDict->GetElementValue(FX_BSTRC("ColorSpace")); 127 if (pCSObj == NULL) { 128 return FALSE; 129 } 130 CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData(); 131 m_pCS = pDocPageData->GetColorSpace(pCSObj, NULL); 132 m_ShadingType = pShadingDict->GetInteger(FX_BSTRC("ShadingType")); 133 return TRUE; 134 } 135 FX_BOOL CPDF_ShadingPattern::Reload() 136 { 137 Clear(); 138 return Load(); 139 } 140 FX_BOOL CPDF_MeshStream::Load(CPDF_Stream* pShadingStream, CPDF_Function** pFuncs, int nFuncs, CPDF_ColorSpace* pCS) 141 { 142 m_Stream.LoadAllData(pShadingStream); 143 m_BitStream.Init(m_Stream.GetData(), m_Stream.GetSize()); 144 m_pFuncs = pFuncs; 145 m_nFuncs = nFuncs; 146 m_pCS = pCS; 147 CPDF_Dictionary* pDict = pShadingStream->GetDict(); 148 m_nCoordBits = pDict->GetInteger(FX_BSTRC("BitsPerCoordinate")); 149 m_nCompBits = pDict->GetInteger(FX_BSTRC("BitsPerComponent")); 150 m_nFlagBits = pDict->GetInteger(FX_BSTRC("BitsPerFlag")); 151 if (!m_nCoordBits || !m_nCompBits) { 152 return FALSE; 153 } 154 int nComps = pCS->CountComponents(); 155 if (nComps > 8) { 156 return FALSE; 157 } 158 m_nComps = nFuncs ? 1 : nComps; 159 if (((int)m_nComps < 0) || m_nComps > 8) { 160 return FALSE; 161 } 162 m_CoordMax = m_nCoordBits == 32 ? -1 : (1 << m_nCoordBits) - 1; 163 m_CompMax = (1 << m_nCompBits) - 1; 164 CPDF_Array* pDecode = pDict->GetArray(FX_BSTRC("Decode")); 165 if (pDecode == NULL || pDecode->GetCount() != 4 + m_nComps * 2) { 166 return FALSE; 167 } 168 m_xmin = pDecode->GetNumber(0); 169 m_xmax = pDecode->GetNumber(1); 170 m_ymin = pDecode->GetNumber(2); 171 m_ymax = pDecode->GetNumber(3); 172 for (FX_DWORD i = 0; i < m_nComps; i ++) { 173 m_ColorMin[i] = pDecode->GetNumber(i * 2 + 4); 174 m_ColorMax[i] = pDecode->GetNumber(i * 2 + 5); 175 } 176 return TRUE; 177 } 178 FX_DWORD CPDF_MeshStream::GetFlag() 179 { 180 return m_BitStream.GetBits(m_nFlagBits) & 0x03; 181 } 182 void CPDF_MeshStream::GetCoords(FX_FLOAT& x, FX_FLOAT& y) 183 { 184 if (m_nCoordBits == 32) { 185 x = m_xmin + (FX_FLOAT)(m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) / (double)m_CoordMax); 186 y = m_ymin + (FX_FLOAT)(m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) / (double)m_CoordMax); 187 } else { 188 x = m_xmin + m_BitStream.GetBits(m_nCoordBits) * (m_xmax - m_xmin) / m_CoordMax; 189 y = m_ymin + m_BitStream.GetBits(m_nCoordBits) * (m_ymax - m_ymin) / m_CoordMax; 190 } 191 } 192 void CPDF_MeshStream::GetColor(FX_FLOAT& r, FX_FLOAT& g, FX_FLOAT& b) 193 { 194 FX_DWORD i; 195 FX_FLOAT color_value[8]; 196 for (i = 0; i < m_nComps; i ++) { 197 color_value[i] = m_ColorMin[i] + m_BitStream.GetBits(m_nCompBits) * (m_ColorMax[i] - m_ColorMin[i]) / m_CompMax; 198 } 199 if (m_nFuncs) { 200 static const int kMaxResults = 8; 201 FX_FLOAT result[kMaxResults]; 202 int nResults; 203 FXSYS_memset32(result, 0, sizeof(result)); 204 for (FX_DWORD i = 0; i < m_nFuncs; i ++) { 205 if (m_pFuncs[i] && m_pFuncs[i]->CountOutputs() <= kMaxResults) { 206 m_pFuncs[i]->Call(color_value, 1, result, nResults); 207 } 208 } 209 m_pCS->GetRGB(result, r, g, b); 210 } else { 211 m_pCS->GetRGB(color_value, r, g, b); 212 } 213 } 214 FX_DWORD CPDF_MeshStream::GetVertex(CPDF_MeshVertex& vertex, CFX_AffineMatrix* pObject2Bitmap) 215 { 216 FX_DWORD flag = GetFlag(); 217 GetCoords(vertex.x, vertex.y); 218 pObject2Bitmap->Transform(vertex.x, vertex.y); 219 GetColor(vertex.r, vertex.g, vertex.b); 220 m_BitStream.ByteAlign(); 221 return flag; 222 } 223 FX_BOOL CPDF_MeshStream::GetVertexRow(CPDF_MeshVertex* vertex, int count, CFX_AffineMatrix* pObject2Bitmap) 224 { 225 for (int i = 0; i < count; i ++) { 226 if (m_BitStream.IsEOF()) { 227 return FALSE; 228 } 229 GetCoords(vertex[i].x, vertex[i].y); 230 pObject2Bitmap->Transform(vertex[i].x, vertex[i].y); 231 GetColor(vertex[i].r, vertex[i].g, vertex[i].b); 232 m_BitStream.ByteAlign(); 233 } 234 return TRUE; 235 } 236 CFX_FloatRect _GetShadingBBox(CPDF_Stream* pStream, int type, const CFX_AffineMatrix* pMatrix, 237 CPDF_Function** pFuncs, int nFuncs, CPDF_ColorSpace* pCS) 238 { 239 if (pStream == NULL || pStream->GetType() != PDFOBJ_STREAM || pFuncs == NULL || pCS == NULL) { 240 return CFX_FloatRect(0, 0, 0, 0); 241 } 242 CPDF_MeshStream stream; 243 if (!stream.Load(pStream, pFuncs, nFuncs, pCS)) { 244 return CFX_FloatRect(0, 0, 0, 0); 245 } 246 CFX_FloatRect rect; 247 FX_BOOL bStarted = FALSE; 248 FX_BOOL bGouraud = type == 4 || type == 5; 249 int full_point_count = type == 7 ? 16 : (type == 6 ? 12 : 1); 250 int full_color_count = (type == 6 || type == 7) ? 4 : 1; 251 while (!stream.m_BitStream.IsEOF()) { 252 FX_DWORD flag; 253 if (type != 5) { 254 flag = stream.GetFlag(); 255 } 256 int point_count = full_point_count, color_count = full_color_count; 257 if (!bGouraud && flag) { 258 point_count -= 4; 259 color_count -= 2; 260 } 261 for (int i = 0; i < point_count; i ++) { 262 FX_FLOAT x, y; 263 stream.GetCoords(x, y); 264 if (bStarted) { 265 rect.UpdateRect(x, y); 266 } else { 267 rect.InitRect(x, y); 268 bStarted = TRUE; 269 } 270 } 271 stream.m_BitStream.SkipBits(stream.m_nComps * stream.m_nCompBits * color_count); 272 if (bGouraud) { 273 stream.m_BitStream.ByteAlign(); 274 } 275 } 276 rect.Transform(pMatrix); 277 return rect; 278 } 279