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