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