| OLD | NEW |
| (Empty) |
| 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 "core/fpdfapi/fpdf_page/pageint.h" | |
| 8 | |
| 9 #include <algorithm> | |
| 10 | |
| 11 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" | |
| 12 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" | |
| 13 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" | |
| 14 #include "core/fpdfapi/fpdf_render/render_int.h" | |
| 15 #include "core/include/fpdfapi/fpdf_pageobj.h" | |
| 16 #include "third_party/base/stl_util.h" | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 FX_FLOAT ClipFloat(FX_FLOAT f) { | |
| 21 return std::max(0.0f, std::min(1.0f, f)); | |
| 22 } | |
| 23 | |
| 24 } // namespace | |
| 25 | |
| 26 void CPDF_GraphicStates::DefaultStates() { | |
| 27 m_ColorState.New()->Default(); | |
| 28 } | |
| 29 void CPDF_GraphicStates::CopyStates(const CPDF_GraphicStates& src) { | |
| 30 m_ClipPath = src.m_ClipPath; | |
| 31 m_GraphState = src.m_GraphState; | |
| 32 m_ColorState = src.m_ColorState; | |
| 33 m_TextState = src.m_TextState; | |
| 34 m_GeneralState = src.m_GeneralState; | |
| 35 } | |
| 36 CPDF_ClipPathData::CPDF_ClipPathData() { | |
| 37 m_PathCount = 0; | |
| 38 m_pPathList = NULL; | |
| 39 m_pTypeList = NULL; | |
| 40 m_TextCount = 0; | |
| 41 m_pTextList = NULL; | |
| 42 } | |
| 43 CPDF_ClipPathData::~CPDF_ClipPathData() { | |
| 44 int i; | |
| 45 delete[] m_pPathList; | |
| 46 FX_Free(m_pTypeList); | |
| 47 for (i = m_TextCount - 1; i > -1; i--) | |
| 48 delete m_pTextList[i]; | |
| 49 FX_Free(m_pTextList); | |
| 50 } | |
| 51 CPDF_ClipPathData::CPDF_ClipPathData(const CPDF_ClipPathData& src) { | |
| 52 m_pPathList = NULL; | |
| 53 m_pPathList = NULL; | |
| 54 m_pTextList = NULL; | |
| 55 m_PathCount = src.m_PathCount; | |
| 56 if (m_PathCount) { | |
| 57 int alloc_size = m_PathCount; | |
| 58 if (alloc_size % 8) { | |
| 59 alloc_size += 8 - (alloc_size % 8); | |
| 60 } | |
| 61 m_pPathList = new CPDF_Path[alloc_size]; | |
| 62 for (int i = 0; i < m_PathCount; i++) { | |
| 63 m_pPathList[i] = src.m_pPathList[i]; | |
| 64 } | |
| 65 m_pTypeList = FX_Alloc(uint8_t, alloc_size); | |
| 66 FXSYS_memcpy(m_pTypeList, src.m_pTypeList, m_PathCount); | |
| 67 } else { | |
| 68 m_pPathList = NULL; | |
| 69 m_pTypeList = NULL; | |
| 70 } | |
| 71 m_TextCount = src.m_TextCount; | |
| 72 if (m_TextCount) { | |
| 73 m_pTextList = FX_Alloc(CPDF_TextObject*, m_TextCount); | |
| 74 for (int i = 0; i < m_TextCount; i++) { | |
| 75 if (src.m_pTextList[i]) { | |
| 76 m_pTextList[i] = src.m_pTextList[i]->Clone(); | |
| 77 } else { | |
| 78 m_pTextList[i] = NULL; | |
| 79 } | |
| 80 } | |
| 81 } else { | |
| 82 m_pTextList = NULL; | |
| 83 } | |
| 84 } | |
| 85 void CPDF_ClipPathData::SetCount(int path_count, int text_count) { | |
| 86 ASSERT(m_TextCount == 0 && m_PathCount == 0); | |
| 87 if (path_count) { | |
| 88 m_PathCount = path_count; | |
| 89 int alloc_size = (path_count + 7) / 8 * 8; | |
| 90 m_pPathList = new CPDF_Path[alloc_size]; | |
| 91 m_pTypeList = FX_Alloc(uint8_t, alloc_size); | |
| 92 } | |
| 93 if (text_count) { | |
| 94 m_TextCount = text_count; | |
| 95 m_pTextList = FX_Alloc(CPDF_TextObject*, text_count); | |
| 96 } | |
| 97 } | |
| 98 CFX_FloatRect CPDF_ClipPath::GetClipBox() const { | |
| 99 CFX_FloatRect rect; | |
| 100 FX_BOOL bStarted = FALSE; | |
| 101 int count = GetPathCount(); | |
| 102 if (count) { | |
| 103 rect = GetPath(0).GetBoundingBox(); | |
| 104 for (int i = 1; i < count; i++) { | |
| 105 CFX_FloatRect path_rect = GetPath(i).GetBoundingBox(); | |
| 106 rect.Intersect(path_rect); | |
| 107 } | |
| 108 bStarted = TRUE; | |
| 109 } | |
| 110 count = GetTextCount(); | |
| 111 if (count) { | |
| 112 CFX_FloatRect layer_rect; | |
| 113 FX_BOOL bLayerStarted = FALSE; | |
| 114 for (int i = 0; i < count; i++) { | |
| 115 CPDF_TextObject* pTextObj = GetText(i); | |
| 116 if (!pTextObj) { | |
| 117 if (!bStarted) { | |
| 118 rect = layer_rect; | |
| 119 bStarted = TRUE; | |
| 120 } else { | |
| 121 rect.Intersect(layer_rect); | |
| 122 } | |
| 123 bLayerStarted = FALSE; | |
| 124 } else { | |
| 125 if (!bLayerStarted) { | |
| 126 layer_rect = CFX_FloatRect(pTextObj->GetBBox(nullptr)); | |
| 127 bLayerStarted = TRUE; | |
| 128 } else { | |
| 129 layer_rect.Union(CFX_FloatRect(pTextObj->GetBBox(nullptr))); | |
| 130 } | |
| 131 } | |
| 132 } | |
| 133 } | |
| 134 return rect; | |
| 135 } | |
| 136 void CPDF_ClipPath::AppendPath(CPDF_Path path, int type, FX_BOOL bAutoMerge) { | |
| 137 CPDF_ClipPathData* pData = GetModify(); | |
| 138 if (pData->m_PathCount && bAutoMerge) { | |
| 139 CPDF_Path old_path = pData->m_pPathList[pData->m_PathCount - 1]; | |
| 140 if (old_path.IsRect()) { | |
| 141 CFX_FloatRect old_rect(old_path.GetPointX(0), old_path.GetPointY(0), | |
| 142 old_path.GetPointX(2), old_path.GetPointY(2)); | |
| 143 CFX_FloatRect new_rect = path.GetBoundingBox(); | |
| 144 if (old_rect.Contains(new_rect)) { | |
| 145 pData->m_PathCount--; | |
| 146 pData->m_pPathList[pData->m_PathCount].SetNull(); | |
| 147 } | |
| 148 } | |
| 149 } | |
| 150 if (pData->m_PathCount % 8 == 0) { | |
| 151 CPDF_Path* pNewPath = new CPDF_Path[pData->m_PathCount + 8]; | |
| 152 for (int i = 0; i < pData->m_PathCount; i++) { | |
| 153 pNewPath[i] = pData->m_pPathList[i]; | |
| 154 } | |
| 155 delete[] pData->m_pPathList; | |
| 156 uint8_t* pNewType = FX_Alloc(uint8_t, pData->m_PathCount + 8); | |
| 157 FXSYS_memcpy(pNewType, pData->m_pTypeList, pData->m_PathCount); | |
| 158 FX_Free(pData->m_pTypeList); | |
| 159 pData->m_pPathList = pNewPath; | |
| 160 pData->m_pTypeList = pNewType; | |
| 161 } | |
| 162 pData->m_pPathList[pData->m_PathCount] = path; | |
| 163 pData->m_pTypeList[pData->m_PathCount] = (uint8_t)type; | |
| 164 pData->m_PathCount++; | |
| 165 } | |
| 166 void CPDF_ClipPath::DeletePath(int index) { | |
| 167 CPDF_ClipPathData* pData = GetModify(); | |
| 168 if (index >= pData->m_PathCount) { | |
| 169 return; | |
| 170 } | |
| 171 pData->m_pPathList[index].SetNull(); | |
| 172 for (int i = index; i < pData->m_PathCount - 1; i++) { | |
| 173 pData->m_pPathList[i] = pData->m_pPathList[i + 1]; | |
| 174 } | |
| 175 pData->m_pPathList[pData->m_PathCount - 1].SetNull(); | |
| 176 FXSYS_memmove(pData->m_pTypeList + index, pData->m_pTypeList + index + 1, | |
| 177 pData->m_PathCount - index - 1); | |
| 178 pData->m_PathCount--; | |
| 179 } | |
| 180 #define FPDF_CLIPPATH_MAX_TEXTS 1024 | |
| 181 void CPDF_ClipPath::AppendTexts(CPDF_TextObject** pTexts, int count) { | |
| 182 CPDF_ClipPathData* pData = GetModify(); | |
| 183 if (pData->m_TextCount + count > FPDF_CLIPPATH_MAX_TEXTS) { | |
| 184 for (int i = 0; i < count; i++) { | |
| 185 delete pTexts[i]; | |
| 186 } | |
| 187 return; | |
| 188 } | |
| 189 CPDF_TextObject** pNewList = | |
| 190 FX_Alloc(CPDF_TextObject*, pData->m_TextCount + count + 1); | |
| 191 if (pData->m_pTextList) { | |
| 192 FXSYS_memcpy(pNewList, pData->m_pTextList, | |
| 193 pData->m_TextCount * sizeof(CPDF_TextObject*)); | |
| 194 FX_Free(pData->m_pTextList); | |
| 195 } | |
| 196 pData->m_pTextList = pNewList; | |
| 197 for (int i = 0; i < count; i++) { | |
| 198 pData->m_pTextList[pData->m_TextCount + i] = pTexts[i]; | |
| 199 } | |
| 200 pData->m_pTextList[pData->m_TextCount + count] = NULL; | |
| 201 pData->m_TextCount += count + 1; | |
| 202 } | |
| 203 void CPDF_ClipPath::Transform(const CFX_Matrix& matrix) { | |
| 204 CPDF_ClipPathData* pData = GetModify(); | |
| 205 int i; | |
| 206 for (i = 0; i < pData->m_PathCount; i++) { | |
| 207 pData->m_pPathList[i].Transform(&matrix); | |
| 208 } | |
| 209 for (i = 0; i < pData->m_TextCount; i++) | |
| 210 if (pData->m_pTextList[i]) { | |
| 211 pData->m_pTextList[i]->Transform(matrix); | |
| 212 } | |
| 213 } | |
| 214 CPDF_ColorStateData::CPDF_ColorStateData(const CPDF_ColorStateData& src) { | |
| 215 m_FillColor.Copy(&src.m_FillColor); | |
| 216 m_FillRGB = src.m_FillRGB; | |
| 217 m_StrokeColor.Copy(&src.m_StrokeColor); | |
| 218 m_StrokeRGB = src.m_StrokeRGB; | |
| 219 } | |
| 220 void CPDF_ColorStateData::Default() { | |
| 221 m_FillRGB = m_StrokeRGB = 0; | |
| 222 m_FillColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY)); | |
| 223 m_StrokeColor.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY)); | |
| 224 } | |
| 225 void CPDF_ColorState::SetFillColor(CPDF_ColorSpace* pCS, | |
| 226 FX_FLOAT* pValue, | |
| 227 int nValues) { | |
| 228 CPDF_ColorStateData* pData = GetModify(); | |
| 229 SetColor(pData->m_FillColor, pData->m_FillRGB, pCS, pValue, nValues); | |
| 230 } | |
| 231 void CPDF_ColorState::SetStrokeColor(CPDF_ColorSpace* pCS, | |
| 232 FX_FLOAT* pValue, | |
| 233 int nValues) { | |
| 234 CPDF_ColorStateData* pData = GetModify(); | |
| 235 SetColor(pData->m_StrokeColor, pData->m_StrokeRGB, pCS, pValue, nValues); | |
| 236 } | |
| 237 void CPDF_ColorState::SetColor(CPDF_Color& color, | |
| 238 FX_DWORD& rgb, | |
| 239 CPDF_ColorSpace* pCS, | |
| 240 FX_FLOAT* pValue, | |
| 241 int nValues) { | |
| 242 if (pCS) { | |
| 243 color.SetColorSpace(pCS); | |
| 244 } else if (color.IsNull()) { | |
| 245 color.SetColorSpace(CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY)); | |
| 246 } | |
| 247 if (color.m_pCS->CountComponents() > nValues) { | |
| 248 return; | |
| 249 } | |
| 250 color.SetValue(pValue); | |
| 251 int R, G, B; | |
| 252 rgb = color.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (FX_DWORD)-1; | |
| 253 } | |
| 254 void CPDF_ColorState::SetFillPattern(CPDF_Pattern* pPattern, | |
| 255 FX_FLOAT* pValue, | |
| 256 int nValues) { | |
| 257 CPDF_ColorStateData* pData = GetModify(); | |
| 258 pData->m_FillColor.SetValue(pPattern, pValue, nValues); | |
| 259 int R, G, B; | |
| 260 FX_BOOL ret = pData->m_FillColor.GetRGB(R, G, B); | |
| 261 if (pPattern->m_PatternType == 1 && | |
| 262 ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) { | |
| 263 pData->m_FillRGB = 0x00BFBFBF; | |
| 264 return; | |
| 265 } | |
| 266 pData->m_FillRGB = ret ? FXSYS_RGB(R, G, B) : (FX_DWORD)-1; | |
| 267 } | |
| 268 void CPDF_ColorState::SetStrokePattern(CPDF_Pattern* pPattern, | |
| 269 FX_FLOAT* pValue, | |
| 270 int nValues) { | |
| 271 CPDF_ColorStateData* pData = GetModify(); | |
| 272 pData->m_StrokeColor.SetValue(pPattern, pValue, nValues); | |
| 273 int R, G, B; | |
| 274 FX_BOOL ret = pData->m_StrokeColor.GetRGB(R, G, B); | |
| 275 if (pPattern->m_PatternType == 1 && | |
| 276 ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) { | |
| 277 pData->m_StrokeRGB = 0x00BFBFBF; | |
| 278 return; | |
| 279 } | |
| 280 pData->m_StrokeRGB = | |
| 281 pData->m_StrokeColor.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (FX_DWORD)-1; | |
| 282 } | |
| 283 CPDF_TextStateData::CPDF_TextStateData() { | |
| 284 m_pFont = NULL; | |
| 285 m_pDocument = NULL; | |
| 286 m_FontSize = 1.0f; | |
| 287 m_WordSpace = 0; | |
| 288 m_CharSpace = 0; | |
| 289 m_TextMode = 0; | |
| 290 m_Matrix[0] = m_Matrix[3] = 1.0f; | |
| 291 m_Matrix[1] = m_Matrix[2] = 0; | |
| 292 m_CTM[0] = m_CTM[3] = 1.0f; | |
| 293 m_CTM[1] = m_CTM[2] = 0; | |
| 294 } | |
| 295 CPDF_TextStateData::CPDF_TextStateData(const CPDF_TextStateData& src) { | |
| 296 if (this == &src) { | |
| 297 return; | |
| 298 } | |
| 299 FXSYS_memcpy(this, &src, sizeof(CPDF_TextStateData)); | |
| 300 if (m_pDocument && m_pFont) { | |
| 301 m_pFont = | |
| 302 m_pDocument->GetPageData()->GetFont(m_pFont->GetFontDict(), FALSE); | |
| 303 } | |
| 304 } | |
| 305 CPDF_TextStateData::~CPDF_TextStateData() { | |
| 306 if (m_pDocument && m_pFont) { | |
| 307 CPDF_DocPageData* pPageData = m_pDocument->GetPageData(); | |
| 308 if (pPageData && !pPageData->IsForceClear()) { | |
| 309 pPageData->ReleaseFont(m_pFont->GetFontDict()); | |
| 310 } | |
| 311 } | |
| 312 } | |
| 313 void CPDF_TextState::SetFont(CPDF_Font* pFont) { | |
| 314 CPDF_TextStateData* pStateData = GetModify(); | |
| 315 if (pStateData) { | |
| 316 CPDF_Document* pDoc = pStateData->m_pDocument; | |
| 317 CPDF_DocPageData* pPageData = pDoc ? pDoc->GetPageData() : NULL; | |
| 318 if (pPageData && pStateData->m_pFont && !pPageData->IsForceClear()) { | |
| 319 pPageData->ReleaseFont(pStateData->m_pFont->GetFontDict()); | |
| 320 } | |
| 321 pStateData->m_pDocument = pFont ? pFont->m_pDocument : NULL; | |
| 322 pStateData->m_pFont = pFont; | |
| 323 } | |
| 324 } | |
| 325 FX_FLOAT CPDF_TextState::GetFontSizeV() const { | |
| 326 FX_FLOAT* pMatrix = GetMatrix(); | |
| 327 FX_FLOAT unit = FXSYS_sqrt2(pMatrix[1], pMatrix[3]); | |
| 328 FX_FLOAT size = unit * GetFontSize(); | |
| 329 return (FX_FLOAT)FXSYS_fabs(size); | |
| 330 } | |
| 331 FX_FLOAT CPDF_TextState::GetFontSizeH() const { | |
| 332 FX_FLOAT* pMatrix = GetMatrix(); | |
| 333 FX_FLOAT unit = FXSYS_sqrt2(pMatrix[0], pMatrix[2]); | |
| 334 FX_FLOAT size = unit * GetFontSize(); | |
| 335 return (FX_FLOAT)FXSYS_fabs(size); | |
| 336 } | |
| 337 FX_FLOAT CPDF_TextState::GetBaselineAngle() const { | |
| 338 FX_FLOAT* m_Matrix = GetMatrix(); | |
| 339 return FXSYS_atan2(m_Matrix[2], m_Matrix[0]); | |
| 340 } | |
| 341 FX_FLOAT CPDF_TextState::GetShearAngle() const { | |
| 342 FX_FLOAT* m_Matrix = GetMatrix(); | |
| 343 FX_FLOAT shear_angle = FXSYS_atan2(m_Matrix[1], m_Matrix[3]); | |
| 344 return GetBaselineAngle() + shear_angle; | |
| 345 } | |
| 346 CPDF_GeneralStateData::CPDF_GeneralStateData() { | |
| 347 FXSYS_memset(this, 0, sizeof(CPDF_GeneralStateData)); | |
| 348 FXSYS_strcpy((FX_CHAR*)m_BlendMode, "Normal"); | |
| 349 m_StrokeAlpha = 1.0f; | |
| 350 m_FillAlpha = 1.0f; | |
| 351 m_Flatness = 1.0f; | |
| 352 m_Matrix.SetIdentity(); | |
| 353 } | |
| 354 CPDF_GeneralStateData::CPDF_GeneralStateData(const CPDF_GeneralStateData& src) { | |
| 355 FXSYS_memcpy(this, &src, sizeof(CPDF_GeneralStateData)); | |
| 356 if (src.m_pTransferFunc && src.m_pTransferFunc->m_pPDFDoc) { | |
| 357 CPDF_DocRenderData* pDocCache = | |
| 358 src.m_pTransferFunc->m_pPDFDoc->GetRenderData(); | |
| 359 if (!pDocCache) { | |
| 360 return; | |
| 361 } | |
| 362 m_pTransferFunc = pDocCache->GetTransferFunc(m_pTR); | |
| 363 } | |
| 364 } | |
| 365 CPDF_GeneralStateData::~CPDF_GeneralStateData() { | |
| 366 if (m_pTransferFunc && m_pTransferFunc->m_pPDFDoc) { | |
| 367 CPDF_DocRenderData* pDocCache = m_pTransferFunc->m_pPDFDoc->GetRenderData(); | |
| 368 if (!pDocCache) { | |
| 369 return; | |
| 370 } | |
| 371 pDocCache->ReleaseTransferFunc(m_pTR); | |
| 372 } | |
| 373 } | |
| 374 static int GetBlendType(const CFX_ByteStringC& mode) { | |
| 375 switch (mode.GetID()) { | |
| 376 case FXBSTR_ID('N', 'o', 'r', 'm'): | |
| 377 case FXBSTR_ID('C', 'o', 'm', 'p'): | |
| 378 return FXDIB_BLEND_NORMAL; | |
| 379 case FXBSTR_ID('M', 'u', 'l', 't'): | |
| 380 return FXDIB_BLEND_MULTIPLY; | |
| 381 case FXBSTR_ID('S', 'c', 'r', 'e'): | |
| 382 return FXDIB_BLEND_SCREEN; | |
| 383 case FXBSTR_ID('O', 'v', 'e', 'r'): | |
| 384 return FXDIB_BLEND_OVERLAY; | |
| 385 case FXBSTR_ID('D', 'a', 'r', 'k'): | |
| 386 return FXDIB_BLEND_DARKEN; | |
| 387 case FXBSTR_ID('L', 'i', 'g', 'h'): | |
| 388 return FXDIB_BLEND_LIGHTEN; | |
| 389 case FXBSTR_ID('C', 'o', 'l', 'o'): | |
| 390 if (mode.GetLength() == 10) { | |
| 391 return FXDIB_BLEND_COLORDODGE; | |
| 392 } | |
| 393 if (mode.GetLength() == 9) { | |
| 394 return FXDIB_BLEND_COLORBURN; | |
| 395 } | |
| 396 return FXDIB_BLEND_COLOR; | |
| 397 case FXBSTR_ID('H', 'a', 'r', 'd'): | |
| 398 return FXDIB_BLEND_HARDLIGHT; | |
| 399 case FXBSTR_ID('S', 'o', 'f', 't'): | |
| 400 return FXDIB_BLEND_SOFTLIGHT; | |
| 401 case FXBSTR_ID('D', 'i', 'f', 'f'): | |
| 402 return FXDIB_BLEND_DIFFERENCE; | |
| 403 case FXBSTR_ID('E', 'x', 'c', 'l'): | |
| 404 return FXDIB_BLEND_EXCLUSION; | |
| 405 case FXBSTR_ID('H', 'u', 'e', 0): | |
| 406 return FXDIB_BLEND_HUE; | |
| 407 case FXBSTR_ID('S', 'a', 't', 'u'): | |
| 408 return FXDIB_BLEND_SATURATION; | |
| 409 case FXBSTR_ID('L', 'u', 'm', 'i'): | |
| 410 return FXDIB_BLEND_LUMINOSITY; | |
| 411 } | |
| 412 return FXDIB_BLEND_NORMAL; | |
| 413 } | |
| 414 void CPDF_GeneralStateData::SetBlendMode(const CFX_ByteStringC& blend_mode) { | |
| 415 if (blend_mode.GetLength() > 15) { | |
| 416 return; | |
| 417 } | |
| 418 FXSYS_memcpy(m_BlendMode, blend_mode.GetPtr(), blend_mode.GetLength()); | |
| 419 m_BlendMode[blend_mode.GetLength()] = 0; | |
| 420 m_BlendType = ::GetBlendType(blend_mode); | |
| 421 } | |
| 422 int RI_StringToId(const CFX_ByteString& ri) { | |
| 423 FX_DWORD id = ri.GetID(); | |
| 424 if (id == FXBSTR_ID('A', 'b', 's', 'o')) { | |
| 425 return 1; | |
| 426 } | |
| 427 if (id == FXBSTR_ID('S', 'a', 't', 'u')) { | |
| 428 return 2; | |
| 429 } | |
| 430 if (id == FXBSTR_ID('P', 'e', 'r', 'c')) { | |
| 431 return 3; | |
| 432 } | |
| 433 return 0; | |
| 434 } | |
| 435 void CPDF_GeneralState::SetRenderIntent(const CFX_ByteString& ri) { | |
| 436 GetModify()->m_RenderIntent = RI_StringToId(ri); | |
| 437 } | |
| 438 CPDF_AllStates::CPDF_AllStates() { | |
| 439 m_TextX = m_TextY = m_TextLineX = m_TextLineY = 0; | |
| 440 m_TextLeading = 0; | |
| 441 m_TextRise = 0; | |
| 442 m_TextHorzScale = 1.0f; | |
| 443 } | |
| 444 CPDF_AllStates::~CPDF_AllStates() {} | |
| 445 void CPDF_AllStates::Copy(const CPDF_AllStates& src) { | |
| 446 CopyStates(src); | |
| 447 m_TextMatrix.Copy(src.m_TextMatrix); | |
| 448 m_ParentMatrix.Copy(src.m_ParentMatrix); | |
| 449 m_CTM.Copy(src.m_CTM); | |
| 450 m_TextX = src.m_TextX; | |
| 451 m_TextY = src.m_TextY; | |
| 452 m_TextLineX = src.m_TextLineX; | |
| 453 m_TextLineY = src.m_TextLineY; | |
| 454 m_TextLeading = src.m_TextLeading; | |
| 455 m_TextRise = src.m_TextRise; | |
| 456 m_TextHorzScale = src.m_TextHorzScale; | |
| 457 } | |
| 458 void CPDF_AllStates::SetLineDash(CPDF_Array* pArray, | |
| 459 FX_FLOAT phase, | |
| 460 FX_FLOAT scale) { | |
| 461 CFX_GraphStateData* pData = m_GraphState.GetModify(); | |
| 462 pData->m_DashPhase = phase * scale; | |
| 463 pData->SetDashCount(pArray->GetCount()); | |
| 464 for (FX_DWORD i = 0; i < pArray->GetCount(); i++) { | |
| 465 pData->m_DashArray[i] = pArray->GetNumberAt(i) * scale; | |
| 466 } | |
| 467 } | |
| 468 void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS, | |
| 469 CPDF_StreamContentParser* pParser) { | |
| 470 CPDF_GeneralStateData* pGeneralState = m_GeneralState.GetModify(); | |
| 471 for (const auto& it : *pGS) { | |
| 472 const CFX_ByteString& key_str = it.first; | |
| 473 CPDF_Object* pElement = it.second; | |
| 474 CPDF_Object* pObject = pElement ? pElement->GetDirect() : nullptr; | |
| 475 if (!pObject) | |
| 476 continue; | |
| 477 | |
| 478 FX_DWORD key = key_str.GetID(); | |
| 479 switch (key) { | |
| 480 case FXBSTR_ID('L', 'W', 0, 0): | |
| 481 m_GraphState.GetModify()->m_LineWidth = pObject->GetNumber(); | |
| 482 break; | |
| 483 case FXBSTR_ID('L', 'C', 0, 0): | |
| 484 m_GraphState.GetModify()->m_LineCap = | |
| 485 (CFX_GraphStateData::LineCap)pObject->GetInteger(); | |
| 486 break; | |
| 487 case FXBSTR_ID('L', 'J', 0, 0): | |
| 488 m_GraphState.GetModify()->m_LineJoin = | |
| 489 (CFX_GraphStateData::LineJoin)pObject->GetInteger(); | |
| 490 break; | |
| 491 case FXBSTR_ID('M', 'L', 0, 0): | |
| 492 m_GraphState.GetModify()->m_MiterLimit = pObject->GetNumber(); | |
| 493 break; | |
| 494 case FXBSTR_ID('D', 0, 0, 0): { | |
| 495 CPDF_Array* pDash = pObject->AsArray(); | |
| 496 if (!pDash) | |
| 497 break; | |
| 498 | |
| 499 CPDF_Array* pArray = pDash->GetArrayAt(0); | |
| 500 if (!pArray) | |
| 501 break; | |
| 502 | |
| 503 SetLineDash(pArray, pDash->GetNumberAt(1), 1.0f); | |
| 504 break; | |
| 505 } | |
| 506 case FXBSTR_ID('R', 'I', 0, 0): | |
| 507 m_GeneralState.SetRenderIntent(pObject->GetString()); | |
| 508 break; | |
| 509 case FXBSTR_ID('F', 'o', 'n', 't'): { | |
| 510 CPDF_Array* pFont = pObject->AsArray(); | |
| 511 if (!pFont) | |
| 512 break; | |
| 513 | |
| 514 m_TextState.GetModify()->m_FontSize = pFont->GetNumberAt(1); | |
| 515 m_TextState.SetFont(pParser->FindFont(pFont->GetStringAt(0))); | |
| 516 break; | |
| 517 } | |
| 518 case FXBSTR_ID('T', 'R', 0, 0): | |
| 519 if (pGS->KeyExist("TR2")) { | |
| 520 continue; | |
| 521 } | |
| 522 case FXBSTR_ID('T', 'R', '2', 0): | |
| 523 pGeneralState->m_pTR = | |
| 524 (pObject && !pObject->IsName()) ? pObject : nullptr; | |
| 525 break; | |
| 526 case FXBSTR_ID('B', 'M', 0, 0): { | |
| 527 CPDF_Array* pArray = pObject->AsArray(); | |
| 528 CFX_ByteString mode = | |
| 529 pArray ? pArray->GetStringAt(0) : pObject->GetString(); | |
| 530 | |
| 531 pGeneralState->SetBlendMode(mode); | |
| 532 if (pGeneralState->m_BlendType > FXDIB_BLEND_MULTIPLY) { | |
| 533 pParser->GetPageObjectHolder()->SetBackgroundAlphaNeeded(TRUE); | |
| 534 } | |
| 535 break; | |
| 536 } | |
| 537 case FXBSTR_ID('S', 'M', 'a', 's'): | |
| 538 if (ToDictionary(pObject)) { | |
| 539 pGeneralState->m_pSoftMask = pObject; | |
| 540 FXSYS_memcpy(pGeneralState->m_SMaskMatrix, | |
| 541 &pParser->GetCurStates()->m_CTM, sizeof(CFX_Matrix)); | |
| 542 } else { | |
| 543 pGeneralState->m_pSoftMask = NULL; | |
| 544 } | |
| 545 break; | |
| 546 case FXBSTR_ID('C', 'A', 0, 0): | |
| 547 pGeneralState->m_StrokeAlpha = ClipFloat(pObject->GetNumber()); | |
| 548 break; | |
| 549 case FXBSTR_ID('c', 'a', 0, 0): | |
| 550 pGeneralState->m_FillAlpha = ClipFloat(pObject->GetNumber()); | |
| 551 break; | |
| 552 case FXBSTR_ID('O', 'P', 0, 0): | |
| 553 pGeneralState->m_StrokeOP = pObject->GetInteger(); | |
| 554 if (!pGS->KeyExist("op")) { | |
| 555 pGeneralState->m_FillOP = pObject->GetInteger(); | |
| 556 } | |
| 557 break; | |
| 558 case FXBSTR_ID('o', 'p', 0, 0): | |
| 559 pGeneralState->m_FillOP = pObject->GetInteger(); | |
| 560 break; | |
| 561 case FXBSTR_ID('O', 'P', 'M', 0): | |
| 562 pGeneralState->m_OPMode = pObject->GetInteger(); | |
| 563 break; | |
| 564 case FXBSTR_ID('B', 'G', 0, 0): | |
| 565 if (pGS->KeyExist("BG2")) { | |
| 566 continue; | |
| 567 } | |
| 568 case FXBSTR_ID('B', 'G', '2', 0): | |
| 569 pGeneralState->m_pBG = pObject; | |
| 570 break; | |
| 571 case FXBSTR_ID('U', 'C', 'R', 0): | |
| 572 if (pGS->KeyExist("UCR2")) { | |
| 573 continue; | |
| 574 } | |
| 575 case FXBSTR_ID('U', 'C', 'R', '2'): | |
| 576 pGeneralState->m_pUCR = pObject; | |
| 577 break; | |
| 578 case FXBSTR_ID('H', 'T', 0, 0): | |
| 579 pGeneralState->m_pHT = pObject; | |
| 580 break; | |
| 581 case FXBSTR_ID('F', 'L', 0, 0): | |
| 582 pGeneralState->m_Flatness = pObject->GetNumber(); | |
| 583 break; | |
| 584 case FXBSTR_ID('S', 'M', 0, 0): | |
| 585 pGeneralState->m_Smoothness = pObject->GetNumber(); | |
| 586 break; | |
| 587 case FXBSTR_ID('S', 'A', 0, 0): | |
| 588 pGeneralState->m_StrokeAdjust = pObject->GetInteger(); | |
| 589 break; | |
| 590 case FXBSTR_ID('A', 'I', 'S', 0): | |
| 591 pGeneralState->m_AlphaSource = pObject->GetInteger(); | |
| 592 break; | |
| 593 case FXBSTR_ID('T', 'K', 0, 0): | |
| 594 pGeneralState->m_TextKnockout = pObject->GetInteger(); | |
| 595 break; | |
| 596 } | |
| 597 } | |
| 598 pGeneralState->m_Matrix = m_CTM; | |
| 599 } | |
| 600 CPDF_ContentMarkItem::CPDF_ContentMarkItem() { | |
| 601 m_ParamType = None; | |
| 602 } | |
| 603 CPDF_ContentMarkItem::CPDF_ContentMarkItem(const CPDF_ContentMarkItem& src) { | |
| 604 m_MarkName = src.m_MarkName; | |
| 605 m_ParamType = src.m_ParamType; | |
| 606 if (m_ParamType == DirectDict) { | |
| 607 m_pParam = ToDictionary(src.m_pParam->Clone()); | |
| 608 } else { | |
| 609 m_pParam = src.m_pParam; | |
| 610 } | |
| 611 } | |
| 612 CPDF_ContentMarkItem::~CPDF_ContentMarkItem() { | |
| 613 if (m_ParamType == DirectDict && m_pParam) | |
| 614 m_pParam->Release(); | |
| 615 } | |
| 616 FX_BOOL CPDF_ContentMarkItem::HasMCID() const { | |
| 617 if (m_pParam && | |
| 618 (m_ParamType == DirectDict || m_ParamType == PropertiesDict)) { | |
| 619 return m_pParam->KeyExist("MCID"); | |
| 620 } | |
| 621 return FALSE; | |
| 622 } | |
| 623 | |
| 624 CPDF_ContentMarkData::CPDF_ContentMarkData(const CPDF_ContentMarkData& src) | |
| 625 : m_Marks(src.m_Marks) {} | |
| 626 | |
| 627 int CPDF_ContentMarkData::CountItems() const { | |
| 628 return pdfium::CollectionSize<int>(m_Marks); | |
| 629 } | |
| 630 | |
| 631 int CPDF_ContentMarkData::GetMCID() const { | |
| 632 for (const auto& mark : m_Marks) { | |
| 633 CPDF_ContentMarkItem::ParamType type = mark.GetParamType(); | |
| 634 if (type == CPDF_ContentMarkItem::PropertiesDict || | |
| 635 type == CPDF_ContentMarkItem::DirectDict) { | |
| 636 CPDF_Dictionary* pDict = mark.GetParam(); | |
| 637 if (pDict->KeyExist("MCID")) | |
| 638 return pDict->GetIntegerBy("MCID"); | |
| 639 } | |
| 640 } | |
| 641 return -1; | |
| 642 } | |
| 643 | |
| 644 void CPDF_ContentMarkData::AddMark(const CFX_ByteString& name, | |
| 645 CPDF_Dictionary* pDict, | |
| 646 FX_BOOL bDirect) { | |
| 647 CPDF_ContentMarkItem item; | |
| 648 item.SetName(name); | |
| 649 if (pDict) { | |
| 650 if (bDirect) { | |
| 651 item.SetParam(CPDF_ContentMarkItem::DirectDict, | |
| 652 ToDictionary(pDict->Clone())); | |
| 653 } else { | |
| 654 item.SetParam(CPDF_ContentMarkItem::PropertiesDict, pDict); | |
| 655 } | |
| 656 } | |
| 657 m_Marks.push_back(item); | |
| 658 } | |
| 659 | |
| 660 void CPDF_ContentMarkData::DeleteLastMark() { | |
| 661 if (!m_Marks.empty()) | |
| 662 m_Marks.pop_back(); | |
| 663 } | |
| 664 | |
| 665 FX_BOOL CPDF_ContentMark::HasMark(const CFX_ByteStringC& mark) const { | |
| 666 if (!m_pObject) { | |
| 667 return FALSE; | |
| 668 } | |
| 669 for (int i = 0; i < m_pObject->CountItems(); i++) { | |
| 670 CPDF_ContentMarkItem& item = m_pObject->GetItem(i); | |
| 671 if (item.GetName() == mark) { | |
| 672 return TRUE; | |
| 673 } | |
| 674 } | |
| 675 return FALSE; | |
| 676 } | |
| 677 FX_BOOL CPDF_ContentMark::LookupMark(const CFX_ByteStringC& mark, | |
| 678 CPDF_Dictionary*& pDict) const { | |
| 679 if (!m_pObject) { | |
| 680 return FALSE; | |
| 681 } | |
| 682 for (int i = 0; i < m_pObject->CountItems(); i++) { | |
| 683 CPDF_ContentMarkItem& item = m_pObject->GetItem(i); | |
| 684 if (item.GetName() == mark) { | |
| 685 pDict = NULL; | |
| 686 if (item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict || | |
| 687 item.GetParamType() == CPDF_ContentMarkItem::DirectDict) { | |
| 688 pDict = item.GetParam(); | |
| 689 } | |
| 690 return TRUE; | |
| 691 } | |
| 692 } | |
| 693 return FALSE; | |
| 694 } | |
| OLD | NEW |