Home | History | Annotate | Download | only in fpdf_page
      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