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     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