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