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 "core/src/fpdfapi/fpdf_page/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_serial.h"
     12 
     13 namespace {
     14 
     15 struct _FX_BSTR {
     16   const FX_CHAR* m_Ptr;
     17   int m_Size;
     18 };
     19 #define _FX_BSTRC(str) \
     20   { str, sizeof(str) - 1 }
     21 
     22 struct PDF_AbbrPairs {
     23   _FX_BSTR full_name;
     24   _FX_BSTR abbr;
     25 };
     26 
     27 const PDF_AbbrPairs PDF_InlineKeyAbbr[] = {
     28     {_FX_BSTRC("BitsPerComponent"), _FX_BSTRC("BPC")},
     29     {_FX_BSTRC("ColorSpace"), _FX_BSTRC("CS")},
     30     {_FX_BSTRC("Decode"), _FX_BSTRC("D")},
     31     {_FX_BSTRC("DecodeParms"), _FX_BSTRC("DP")},
     32     {_FX_BSTRC("Filter"), _FX_BSTRC("F")},
     33     {_FX_BSTRC("Height"), _FX_BSTRC("H")},
     34     {_FX_BSTRC("ImageMask"), _FX_BSTRC("IM")},
     35     {_FX_BSTRC("Interpolate"), _FX_BSTRC("I")},
     36     {_FX_BSTRC("Width"), _FX_BSTRC("W")},
     37 };
     38 
     39 const PDF_AbbrPairs PDF_InlineValueAbbr[] = {
     40     {_FX_BSTRC("DeviceGray"), _FX_BSTRC("G")},
     41     {_FX_BSTRC("DeviceRGB"), _FX_BSTRC("RGB")},
     42     {_FX_BSTRC("DeviceCMYK"), _FX_BSTRC("CMYK")},
     43     {_FX_BSTRC("Indexed"), _FX_BSTRC("I")},
     44     {_FX_BSTRC("ASCIIHexDecode"), _FX_BSTRC("AHx")},
     45     {_FX_BSTRC("ASCII85Decode"), _FX_BSTRC("A85")},
     46     {_FX_BSTRC("LZWDecode"), _FX_BSTRC("LZW")},
     47     {_FX_BSTRC("FlateDecode"), _FX_BSTRC("Fl")},
     48     {_FX_BSTRC("RunLengthDecode"), _FX_BSTRC("RL")},
     49     {_FX_BSTRC("CCITTFaxDecode"), _FX_BSTRC("CCF")},
     50     {_FX_BSTRC("DCTDecode"), _FX_BSTRC("DCT")},
     51 };
     52 
     53 struct AbbrReplacementOp {
     54   bool is_replace_key;
     55   CFX_ByteString key;
     56   CFX_ByteStringC replacement;
     57 };
     58 
     59 CFX_ByteStringC PDF_FindFullName(const PDF_AbbrPairs* table,
     60                                  size_t count,
     61                                  const CFX_ByteStringC& abbr) {
     62   for (size_t i = 0; i < count; ++i) {
     63     if (abbr.GetLength() != table[i].abbr.m_Size)
     64       continue;
     65     if (memcmp(abbr.GetPtr(), table[i].abbr.m_Ptr, abbr.GetLength()))
     66       continue;
     67     return CFX_ByteStringC(table[i].full_name.m_Ptr, table[i].full_name.m_Size);
     68   }
     69   return CFX_ByteStringC();
     70 }
     71 
     72 }  // namespace
     73 
     74 CPDF_StreamContentParser::CPDF_StreamContentParser(
     75     CPDF_Document* pDocument,
     76     CPDF_Dictionary* pPageResources,
     77     CPDF_Dictionary* pParentResources,
     78     CFX_Matrix* pmtContentToUser,
     79     CPDF_PageObjects* pObjList,
     80     CPDF_Dictionary* pResources,
     81     CPDF_Rect* pBBox,
     82     CPDF_ParseOptions* pOptions,
     83     CPDF_AllStates* pStates,
     84     int level)
     85     : m_pDocument(pDocument),
     86       m_pPageResources(pPageResources),
     87       m_pParentResources(pParentResources),
     88       m_pResources(pResources),
     89       m_pObjectList(pObjList),
     90       m_Level(level),
     91       m_ParamStartPos(0),
     92       m_ParamCount(0),
     93       m_pCurStates(new CPDF_AllStates),
     94       m_pLastTextObject(nullptr),
     95       m_DefFontSize(0),
     96       m_pPathPoints(nullptr),
     97       m_PathPointCount(0),
     98       m_PathAllocSize(0),
     99       m_PathCurrentX(0.0f),
    100       m_PathCurrentY(0.0f),
    101       m_PathClipType(0),
    102       m_pLastImage(nullptr),
    103       m_pLastImageDict(nullptr),
    104       m_pLastCloneImageDict(nullptr),
    105       m_bReleaseLastDict(TRUE),
    106       m_bColored(FALSE),
    107       m_bResourceMissing(FALSE) {
    108   if (pmtContentToUser) {
    109     m_mtContentToUser = *pmtContentToUser;
    110   }
    111   if (pOptions) {
    112     m_Options = *pOptions;
    113   }
    114   if (!m_pResources) {
    115     m_pResources = m_pParentResources;
    116   }
    117   if (!m_pResources) {
    118     m_pResources = m_pPageResources;
    119   }
    120   if (pBBox) {
    121     m_BBox = *pBBox;
    122   }
    123   if (pStates) {
    124     m_pCurStates->Copy(*pStates);
    125   } else {
    126     m_pCurStates->m_GeneralState.New();
    127     m_pCurStates->m_GraphState.New();
    128     m_pCurStates->m_TextState.New();
    129     m_pCurStates->m_ColorState.New();
    130   }
    131   for (size_t i = 0; i < FX_ArraySize(m_Type3Data); ++i) {
    132     m_Type3Data[i] = 0.0;
    133   }
    134 }
    135 
    136 CPDF_StreamContentParser::~CPDF_StreamContentParser() {
    137   ClearAllParams();
    138   FX_Free(m_pPathPoints);
    139   if (m_pLastImageDict) {
    140     m_pLastImageDict->Release();
    141   }
    142   if (m_pLastCloneImageDict) {
    143     m_pLastCloneImageDict->Release();
    144   }
    145 }
    146 int CPDF_StreamContentParser::GetNextParamPos() {
    147   if (m_ParamCount == PARAM_BUF_SIZE) {
    148     m_ParamStartPos++;
    149     if (m_ParamStartPos == PARAM_BUF_SIZE) {
    150       m_ParamStartPos = 0;
    151     }
    152     if (m_ParamBuf1[m_ParamStartPos].m_Type == 0) {
    153       if (CPDF_Object* pObject = m_ParamBuf1[m_ParamStartPos].m_pObject)
    154         pObject->Release();
    155     }
    156     return m_ParamStartPos;
    157   }
    158   int index = m_ParamStartPos + m_ParamCount;
    159   if (index >= PARAM_BUF_SIZE) {
    160     index -= PARAM_BUF_SIZE;
    161   }
    162   m_ParamCount++;
    163   return index;
    164 }
    165 void CPDF_StreamContentParser::AddNameParam(const FX_CHAR* name, int len) {
    166   int index = GetNextParamPos();
    167   if (len > 32) {
    168     m_ParamBuf1[index].m_Type = 0;
    169     m_ParamBuf1[index].m_pObject =
    170         new CPDF_Name(PDF_NameDecode(CFX_ByteStringC(name, len)));
    171   } else {
    172     m_ParamBuf1[index].m_Type = PDFOBJ_NAME;
    173     if (!FXSYS_memchr(name, '#', len)) {
    174       FXSYS_memcpy(m_ParamBuf1[index].m_Name.m_Buffer, name, len);
    175       m_ParamBuf1[index].m_Name.m_Len = len;
    176     } else {
    177       CFX_ByteString str = PDF_NameDecode(CFX_ByteStringC(name, len));
    178       FXSYS_memcpy(m_ParamBuf1[index].m_Name.m_Buffer, str.c_str(),
    179                    str.GetLength());
    180       m_ParamBuf1[index].m_Name.m_Len = str.GetLength();
    181     }
    182   }
    183 }
    184 void CPDF_StreamContentParser::AddNumberParam(const FX_CHAR* str, int len) {
    185   int index = GetNextParamPos();
    186   m_ParamBuf1[index].m_Type = PDFOBJ_NUMBER;
    187   FX_atonum(CFX_ByteStringC(str, len), m_ParamBuf1[index].m_Number.m_bInteger,
    188             &m_ParamBuf1[index].m_Number.m_Integer);
    189 }
    190 void CPDF_StreamContentParser::AddObjectParam(CPDF_Object* pObj) {
    191   int index = GetNextParamPos();
    192   m_ParamBuf1[index].m_Type = 0;
    193   m_ParamBuf1[index].m_pObject = pObj;
    194 }
    195 void CPDF_StreamContentParser::ClearAllParams() {
    196   FX_DWORD index = m_ParamStartPos;
    197   for (FX_DWORD i = 0; i < m_ParamCount; i++) {
    198     if (m_ParamBuf1[index].m_Type == 0) {
    199       if (CPDF_Object* pObject = m_ParamBuf1[index].m_pObject)
    200         pObject->Release();
    201     }
    202     index++;
    203     if (index == PARAM_BUF_SIZE) {
    204       index = 0;
    205     }
    206   }
    207   m_ParamStartPos = 0;
    208   m_ParamCount = 0;
    209 }
    210 CPDF_Object* CPDF_StreamContentParser::GetObject(FX_DWORD index) {
    211   if (index >= m_ParamCount) {
    212     return NULL;
    213   }
    214   int real_index = m_ParamStartPos + m_ParamCount - index - 1;
    215   if (real_index >= PARAM_BUF_SIZE) {
    216     real_index -= PARAM_BUF_SIZE;
    217   }
    218   ContentParam& param = m_ParamBuf1[real_index];
    219   if (param.m_Type == PDFOBJ_NUMBER) {
    220     CPDF_Number* pNumber = param.m_Number.m_bInteger
    221                                ? new CPDF_Number(param.m_Number.m_Integer)
    222                                : new CPDF_Number(param.m_Number.m_Float);
    223 
    224     param.m_Type = 0;
    225     param.m_pObject = pNumber;
    226     return pNumber;
    227   }
    228   if (param.m_Type == PDFOBJ_NAME) {
    229     CPDF_Name* pName = new CPDF_Name(
    230         CFX_ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len));
    231     param.m_Type = 0;
    232     param.m_pObject = pName;
    233     return pName;
    234   }
    235   if (param.m_Type == 0) {
    236     return param.m_pObject;
    237   }
    238   ASSERT(FALSE);
    239   return NULL;
    240 }
    241 CFX_ByteString CPDF_StreamContentParser::GetString(FX_DWORD index) {
    242   if (index >= m_ParamCount) {
    243     return CFX_ByteString();
    244   }
    245   int real_index = m_ParamStartPos + m_ParamCount - index - 1;
    246   if (real_index >= PARAM_BUF_SIZE) {
    247     real_index -= PARAM_BUF_SIZE;
    248   }
    249   ContentParam& param = m_ParamBuf1[real_index];
    250   if (param.m_Type == PDFOBJ_NAME) {
    251     return CFX_ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len);
    252   }
    253   if (param.m_Type == 0 && param.m_pObject) {
    254     return param.m_pObject->GetString();
    255   }
    256   return CFX_ByteString();
    257 }
    258 FX_FLOAT CPDF_StreamContentParser::GetNumber(FX_DWORD index) {
    259   if (index >= m_ParamCount) {
    260     return 0;
    261   }
    262   int real_index = m_ParamStartPos + m_ParamCount - index - 1;
    263   if (real_index >= PARAM_BUF_SIZE) {
    264     real_index -= PARAM_BUF_SIZE;
    265   }
    266   ContentParam& param = m_ParamBuf1[real_index];
    267   if (param.m_Type == PDFOBJ_NUMBER) {
    268     return param.m_Number.m_bInteger ? (FX_FLOAT)param.m_Number.m_Integer
    269                                      : param.m_Number.m_Float;
    270   }
    271   if (param.m_Type == 0 && param.m_pObject) {
    272     return param.m_pObject->GetNumber();
    273   }
    274   return 0;
    275 }
    276 FX_FLOAT CPDF_StreamContentParser::GetNumber16(FX_DWORD index) {
    277   return GetNumber(index);
    278 }
    279 void CPDF_StreamContentParser::SetGraphicStates(CPDF_PageObject* pObj,
    280                                                 FX_BOOL bColor,
    281                                                 FX_BOOL bText,
    282                                                 FX_BOOL bGraph) {
    283   pObj->m_GeneralState = m_pCurStates->m_GeneralState;
    284   pObj->m_ClipPath = m_pCurStates->m_ClipPath;
    285   pObj->m_ContentMark = m_CurContentMark;
    286   if (bColor) {
    287     pObj->m_ColorState = m_pCurStates->m_ColorState;
    288   }
    289   if (bGraph) {
    290     pObj->m_GraphState = m_pCurStates->m_GraphState;
    291   }
    292   if (bText) {
    293     pObj->m_TextState = m_pCurStates->m_TextState;
    294   }
    295 }
    296 
    297 const CPDF_StreamContentParser::OpCode CPDF_StreamContentParser::g_OpCodes[] = {
    298     {FXBSTR_ID('"', 0, 0, 0),
    299      &CPDF_StreamContentParser::Handle_NextLineShowText_Space},
    300     {FXBSTR_ID('\'', 0, 0, 0),
    301      &CPDF_StreamContentParser::Handle_NextLineShowText},
    302     {FXBSTR_ID('B', 0, 0, 0), &CPDF_StreamContentParser::Handle_FillStrokePath},
    303     {FXBSTR_ID('B', '*', 0, 0),
    304      &CPDF_StreamContentParser::Handle_EOFillStrokePath},
    305     {FXBSTR_ID('B', 'D', 'C', 0),
    306      &CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary},
    307     {FXBSTR_ID('B', 'I', 0, 0), &CPDF_StreamContentParser::Handle_BeginImage},
    308     {FXBSTR_ID('B', 'M', 'C', 0),
    309      &CPDF_StreamContentParser::Handle_BeginMarkedContent},
    310     {FXBSTR_ID('B', 'T', 0, 0), &CPDF_StreamContentParser::Handle_BeginText},
    311     {FXBSTR_ID('B', 'X', 0, 0),
    312      &CPDF_StreamContentParser::Handle_BeginSectionUndefined},
    313     {FXBSTR_ID('C', 'S', 0, 0),
    314      &CPDF_StreamContentParser::Handle_SetColorSpace_Stroke},
    315     {FXBSTR_ID('D', 'P', 0, 0),
    316      &CPDF_StreamContentParser::Handle_MarkPlace_Dictionary},
    317     {FXBSTR_ID('D', 'o', 0, 0),
    318      &CPDF_StreamContentParser::Handle_ExecuteXObject},
    319     {FXBSTR_ID('E', 'I', 0, 0), &CPDF_StreamContentParser::Handle_EndImage},
    320     {FXBSTR_ID('E', 'M', 'C', 0),
    321      &CPDF_StreamContentParser::Handle_EndMarkedContent},
    322     {FXBSTR_ID('E', 'T', 0, 0), &CPDF_StreamContentParser::Handle_EndText},
    323     {FXBSTR_ID('E', 'X', 0, 0),
    324      &CPDF_StreamContentParser::Handle_EndSectionUndefined},
    325     {FXBSTR_ID('F', 0, 0, 0), &CPDF_StreamContentParser::Handle_FillPathOld},
    326     {FXBSTR_ID('G', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetGray_Stroke},
    327     {FXBSTR_ID('I', 'D', 0, 0),
    328      &CPDF_StreamContentParser::Handle_BeginImageData},
    329     {FXBSTR_ID('J', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineCap},
    330     {FXBSTR_ID('K', 0, 0, 0),
    331      &CPDF_StreamContentParser::Handle_SetCMYKColor_Stroke},
    332     {FXBSTR_ID('M', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetMiterLimit},
    333     {FXBSTR_ID('M', 'P', 0, 0), &CPDF_StreamContentParser::Handle_MarkPlace},
    334     {FXBSTR_ID('Q', 0, 0, 0),
    335      &CPDF_StreamContentParser::Handle_RestoreGraphState},
    336     {FXBSTR_ID('R', 'G', 0, 0),
    337      &CPDF_StreamContentParser::Handle_SetRGBColor_Stroke},
    338     {FXBSTR_ID('S', 0, 0, 0), &CPDF_StreamContentParser::Handle_StrokePath},
    339     {FXBSTR_ID('S', 'C', 0, 0),
    340      &CPDF_StreamContentParser::Handle_SetColor_Stroke},
    341     {FXBSTR_ID('S', 'C', 'N', 0),
    342      &CPDF_StreamContentParser::Handle_SetColorPS_Stroke},
    343     {FXBSTR_ID('T', '*', 0, 0),
    344      &CPDF_StreamContentParser::Handle_MoveToNextLine},
    345     {FXBSTR_ID('T', 'D', 0, 0),
    346      &CPDF_StreamContentParser::Handle_MoveTextPoint_SetLeading},
    347     {FXBSTR_ID('T', 'J', 0, 0),
    348      &CPDF_StreamContentParser::Handle_ShowText_Positioning},
    349     {FXBSTR_ID('T', 'L', 0, 0),
    350      &CPDF_StreamContentParser::Handle_SetTextLeading},
    351     {FXBSTR_ID('T', 'c', 0, 0), &CPDF_StreamContentParser::Handle_SetCharSpace},
    352     {FXBSTR_ID('T', 'd', 0, 0),
    353      &CPDF_StreamContentParser::Handle_MoveTextPoint},
    354     {FXBSTR_ID('T', 'f', 0, 0), &CPDF_StreamContentParser::Handle_SetFont},
    355     {FXBSTR_ID('T', 'j', 0, 0), &CPDF_StreamContentParser::Handle_ShowText},
    356     {FXBSTR_ID('T', 'm', 0, 0),
    357      &CPDF_StreamContentParser::Handle_SetTextMatrix},
    358     {FXBSTR_ID('T', 'r', 0, 0),
    359      &CPDF_StreamContentParser::Handle_SetTextRenderMode},
    360     {FXBSTR_ID('T', 's', 0, 0), &CPDF_StreamContentParser::Handle_SetTextRise},
    361     {FXBSTR_ID('T', 'w', 0, 0), &CPDF_StreamContentParser::Handle_SetWordSpace},
    362     {FXBSTR_ID('T', 'z', 0, 0), &CPDF_StreamContentParser::Handle_SetHorzScale},
    363     {FXBSTR_ID('W', 0, 0, 0), &CPDF_StreamContentParser::Handle_Clip},
    364     {FXBSTR_ID('W', '*', 0, 0), &CPDF_StreamContentParser::Handle_EOClip},
    365     {FXBSTR_ID('b', 0, 0, 0),
    366      &CPDF_StreamContentParser::Handle_CloseFillStrokePath},
    367     {FXBSTR_ID('b', '*', 0, 0),
    368      &CPDF_StreamContentParser::Handle_CloseEOFillStrokePath},
    369     {FXBSTR_ID('c', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_123},
    370     {FXBSTR_ID('c', 'm', 0, 0), &CPDF_StreamContentParser::Handle_ConcatMatrix},
    371     {FXBSTR_ID('c', 's', 0, 0),
    372      &CPDF_StreamContentParser::Handle_SetColorSpace_Fill},
    373     {FXBSTR_ID('d', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetDash},
    374     {FXBSTR_ID('d', '0', 0, 0), &CPDF_StreamContentParser::Handle_SetCharWidth},
    375     {FXBSTR_ID('d', '1', 0, 0),
    376      &CPDF_StreamContentParser::Handle_SetCachedDevice},
    377     {FXBSTR_ID('f', 0, 0, 0), &CPDF_StreamContentParser::Handle_FillPath},
    378     {FXBSTR_ID('f', '*', 0, 0), &CPDF_StreamContentParser::Handle_EOFillPath},
    379     {FXBSTR_ID('g', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetGray_Fill},
    380     {FXBSTR_ID('g', 's', 0, 0),
    381      &CPDF_StreamContentParser::Handle_SetExtendGraphState},
    382     {FXBSTR_ID('h', 0, 0, 0), &CPDF_StreamContentParser::Handle_ClosePath},
    383     {FXBSTR_ID('i', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetFlat},
    384     {FXBSTR_ID('j', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineJoin},
    385     {FXBSTR_ID('k', 0, 0, 0),
    386      &CPDF_StreamContentParser::Handle_SetCMYKColor_Fill},
    387     {FXBSTR_ID('l', 0, 0, 0), &CPDF_StreamContentParser::Handle_LineTo},
    388     {FXBSTR_ID('m', 0, 0, 0), &CPDF_StreamContentParser::Handle_MoveTo},
    389     {FXBSTR_ID('n', 0, 0, 0), &CPDF_StreamContentParser::Handle_EndPath},
    390     {FXBSTR_ID('q', 0, 0, 0), &CPDF_StreamContentParser::Handle_SaveGraphState},
    391     {FXBSTR_ID('r', 'e', 0, 0), &CPDF_StreamContentParser::Handle_Rectangle},
    392     {FXBSTR_ID('r', 'g', 0, 0),
    393      &CPDF_StreamContentParser::Handle_SetRGBColor_Fill},
    394     {FXBSTR_ID('r', 'i', 0, 0),
    395      &CPDF_StreamContentParser::Handle_SetRenderIntent},
    396     {FXBSTR_ID('s', 0, 0, 0),
    397      &CPDF_StreamContentParser::Handle_CloseStrokePath},
    398     {FXBSTR_ID('s', 'c', 0, 0),
    399      &CPDF_StreamContentParser::Handle_SetColor_Fill},
    400     {FXBSTR_ID('s', 'c', 'n', 0),
    401      &CPDF_StreamContentParser::Handle_SetColorPS_Fill},
    402     {FXBSTR_ID('s', 'h', 0, 0), &CPDF_StreamContentParser::Handle_ShadeFill},
    403     {FXBSTR_ID('v', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_23},
    404     {FXBSTR_ID('w', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineWidth},
    405     {FXBSTR_ID('y', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_13},
    406 };
    407 FX_BOOL CPDF_StreamContentParser::OnOperator(const FX_CHAR* op) {
    408   int i = 0;
    409   FX_DWORD opid = 0;
    410   while (i < 4 && op[i]) {
    411     opid = (opid << 8) + op[i];
    412     i++;
    413   }
    414   while (i < 4) {
    415     opid <<= 8;
    416     i++;
    417   }
    418   int low = 0, high = sizeof g_OpCodes / sizeof(OpCode) - 1;
    419   while (low <= high) {
    420     int middle = (low + high) / 2;
    421     int compare = opid - g_OpCodes[middle].m_OpId;
    422     if (compare == 0) {
    423       (this->*g_OpCodes[middle].m_OpHandler)();
    424       return TRUE;
    425     }
    426     if (compare < 0) {
    427       high = middle - 1;
    428     } else {
    429       low = middle + 1;
    430     }
    431   }
    432   return m_CompatCount != 0;
    433 }
    434 void CPDF_StreamContentParser::Handle_CloseFillStrokePath() {
    435   if (m_Options.m_bTextOnly) {
    436     return;
    437   }
    438   Handle_ClosePath();
    439   AddPathObject(FXFILL_WINDING, TRUE);
    440 }
    441 void CPDF_StreamContentParser::Handle_FillStrokePath() {
    442   if (m_Options.m_bTextOnly) {
    443     return;
    444   }
    445   AddPathObject(FXFILL_WINDING, TRUE);
    446 }
    447 void CPDF_StreamContentParser::Handle_CloseEOFillStrokePath() {
    448   if (m_Options.m_bTextOnly) {
    449     return;
    450   }
    451   AddPathPoint(m_PathStartX, m_PathStartY, FXPT_LINETO | FXPT_CLOSEFIGURE);
    452   AddPathObject(FXFILL_ALTERNATE, TRUE);
    453 }
    454 void CPDF_StreamContentParser::Handle_EOFillStrokePath() {
    455   if (m_Options.m_bTextOnly) {
    456     return;
    457   }
    458   AddPathObject(FXFILL_ALTERNATE, TRUE);
    459 }
    460 void CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary() {
    461   if (!m_Options.m_bMarkedContent) {
    462     return;
    463   }
    464   CFX_ByteString tag = GetString(1);
    465   CPDF_Object* pProperty = GetObject(0);
    466   if (!pProperty) {
    467     return;
    468   }
    469   FX_BOOL bDirect = TRUE;
    470   if (pProperty->IsName()) {
    471     pProperty = FindResourceObj("Properties", pProperty->GetString());
    472     if (!pProperty)
    473       return;
    474     bDirect = FALSE;
    475   }
    476   if (CPDF_Dictionary* pDict = pProperty->AsDictionary()) {
    477     m_CurContentMark.GetModify()->AddMark(tag, pDict, bDirect);
    478   }
    479 }
    480 void CPDF_StreamContentParser::Handle_BeginMarkedContent() {
    481   if (!m_Options.m_bMarkedContent) {
    482     return;
    483   }
    484   CFX_ByteString tag = GetString(0);
    485   m_CurContentMark.GetModify()->AddMark(tag, NULL, FALSE);
    486 }
    487 
    488 void PDF_ReplaceAbbr(CPDF_Object* pObj) {
    489   switch (pObj->GetType()) {
    490     case PDFOBJ_DICTIONARY: {
    491       CPDF_Dictionary* pDict = pObj->AsDictionary();
    492       std::vector<AbbrReplacementOp> replacements;
    493       for (const auto& it : *pDict) {
    494         CFX_ByteString key = it.first;
    495         CPDF_Object* value = it.second;
    496         CFX_ByteStringC fullname = PDF_FindFullName(
    497             PDF_InlineKeyAbbr, FX_ArraySize(PDF_InlineKeyAbbr), key);
    498         if (!fullname.IsEmpty()) {
    499           AbbrReplacementOp op;
    500           op.is_replace_key = true;
    501           op.key = key;
    502           op.replacement = fullname;
    503           replacements.push_back(op);
    504           key = fullname;
    505         }
    506 
    507         if (value->IsName()) {
    508           CFX_ByteString name = value->GetString();
    509           fullname = PDF_FindFullName(PDF_InlineValueAbbr,
    510                                       FX_ArraySize(PDF_InlineValueAbbr), name);
    511           if (!fullname.IsEmpty()) {
    512             AbbrReplacementOp op;
    513             op.is_replace_key = false;
    514             op.key = key;
    515             op.replacement = fullname;
    516             replacements.push_back(op);
    517           }
    518         } else {
    519           PDF_ReplaceAbbr(value);
    520         }
    521       }
    522       for (const auto& op : replacements) {
    523         if (op.is_replace_key)
    524           pDict->ReplaceKey(op.key, op.replacement);
    525         else
    526           pDict->SetAtName(op.key, op.replacement);
    527       }
    528       break;
    529     }
    530     case PDFOBJ_ARRAY: {
    531       CPDF_Array* pArray = pObj->AsArray();
    532       for (FX_DWORD i = 0; i < pArray->GetCount(); i++) {
    533         CPDF_Object* pElement = pArray->GetElement(i);
    534         if (pElement->IsName()) {
    535           CFX_ByteString name = pElement->GetString();
    536           CFX_ByteStringC fullname = PDF_FindFullName(
    537               PDF_InlineValueAbbr, FX_ArraySize(PDF_InlineValueAbbr), name);
    538           if (!fullname.IsEmpty()) {
    539             pArray->SetAt(i, new CPDF_Name(fullname));
    540           }
    541         } else {
    542           PDF_ReplaceAbbr(pElement);
    543         }
    544       }
    545       break;
    546     }
    547   }
    548 }
    549 
    550 void CPDF_StreamContentParser::Handle_BeginText() {
    551   m_pCurStates->m_TextMatrix.Set(1.0f, 0, 0, 1.0f, 0, 0);
    552   OnChangeTextMatrix();
    553   m_pCurStates->m_TextX = 0;
    554   m_pCurStates->m_TextY = 0;
    555   m_pCurStates->m_TextLineX = 0;
    556   m_pCurStates->m_TextLineY = 0;
    557 }
    558 void CPDF_StreamContentParser::Handle_BeginSectionUndefined() {
    559   m_CompatCount++;
    560 }
    561 void CPDF_StreamContentParser::Handle_CurveTo_123() {
    562   if (m_Options.m_bTextOnly) {
    563     return;
    564   }
    565   AddPathPoint(GetNumber(5), GetNumber(4), FXPT_BEZIERTO);
    566   AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO);
    567   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO);
    568 }
    569 void CPDF_StreamContentParser::Handle_ConcatMatrix() {
    570   FX_FLOAT a2 = GetNumber16(5), b2 = GetNumber16(4), c2 = GetNumber16(3),
    571            d2 = GetNumber16(2);
    572   FX_FLOAT e2 = GetNumber(1), f2 = GetNumber(0);
    573   CFX_Matrix new_matrix(a2, b2, c2, d2, e2, f2);
    574   new_matrix.Concat(m_pCurStates->m_CTM);
    575   m_pCurStates->m_CTM = new_matrix;
    576   OnChangeTextMatrix();
    577 }
    578 void CPDF_StreamContentParser::Handle_SetColorSpace_Fill() {
    579   if (m_Options.m_bTextOnly) {
    580     return;
    581   }
    582   CFX_ByteString csname = GetString(0);
    583   CPDF_ColorSpace* pCS = FindColorSpace(csname);
    584   if (!pCS) {
    585     return;
    586   }
    587   m_pCurStates->m_ColorState.GetModify()->m_FillColor.SetColorSpace(pCS);
    588 }
    589 void CPDF_StreamContentParser::Handle_SetColorSpace_Stroke() {
    590   if (m_Options.m_bTextOnly) {
    591     return;
    592   }
    593   CFX_ByteString csname = GetString(0);
    594   CPDF_ColorSpace* pCS = FindColorSpace(csname);
    595   if (!pCS) {
    596     return;
    597   }
    598   m_pCurStates->m_ColorState.GetModify()->m_StrokeColor.SetColorSpace(pCS);
    599 }
    600 void CPDF_StreamContentParser::Handle_SetDash() {
    601   if (m_Options.m_bTextOnly) {
    602     return;
    603   }
    604   CPDF_Array* pArray = GetObject(1) ? GetObject(1)->GetArray() : NULL;
    605   if (!pArray) {
    606     return;
    607   }
    608   m_pCurStates->SetLineDash(pArray, GetNumber(0), 1.0f);
    609 }
    610 void CPDF_StreamContentParser::Handle_SetCharWidth() {
    611   m_Type3Data[0] = GetNumber(1);
    612   m_Type3Data[1] = GetNumber(0);
    613   m_bColored = TRUE;
    614 }
    615 void CPDF_StreamContentParser::Handle_SetCachedDevice() {
    616   for (int i = 0; i < 6; i++) {
    617     m_Type3Data[i] = GetNumber(5 - i);
    618   }
    619   m_bColored = FALSE;
    620 }
    621 void CPDF_StreamContentParser::Handle_ExecuteXObject() {
    622   CFX_ByteString name = GetString(0);
    623   if (name == m_LastImageName && m_pLastImage && m_pLastImage->GetStream() &&
    624       m_pLastImage->GetStream()->GetObjNum()) {
    625     AddImage(nullptr, m_pLastImage, FALSE);
    626     return;
    627   }
    628 
    629   if (m_Options.m_bTextOnly) {
    630     if (!m_pResources)
    631       return;
    632 
    633     CPDF_Dictionary* pList = m_pResources->GetDict("XObject");
    634     if (!pList && m_pPageResources && m_pResources != m_pPageResources)
    635       pList = m_pPageResources->GetDict("XObject");
    636     if (!pList)
    637       return;
    638     CPDF_Reference* pRes = ToReference(pList->GetElement(name));
    639     if (!pRes)
    640       return;
    641 
    642     FX_BOOL bForm;
    643     if (m_pDocument->IsFormStream(pRes->GetRefObjNum(), bForm) && !bForm)
    644       return;
    645   }
    646 
    647   CPDF_Stream* pXObject = ToStream(FindResourceObj("XObject", name));
    648   if (!pXObject) {
    649     m_bResourceMissing = TRUE;
    650     return;
    651   }
    652 
    653   CFX_ByteStringC type = pXObject->GetDict()
    654                              ? pXObject->GetDict()->GetConstString("Subtype")
    655                              : CFX_ByteStringC();
    656   if (type == "Image") {
    657     if (m_Options.m_bTextOnly) {
    658       return;
    659     }
    660     CPDF_ImageObject* pObj = AddImage(pXObject, NULL, FALSE);
    661     m_LastImageName = name;
    662     m_pLastImage = pObj->m_pImage;
    663     if (!m_pObjectList->m_bHasImageMask)
    664       m_pObjectList->m_bHasImageMask = m_pLastImage->IsMask();
    665   } else if (type == "Form") {
    666     AddForm(pXObject);
    667   } else {
    668     return;
    669   }
    670 }
    671 void CPDF_StreamContentParser::AddForm(CPDF_Stream* pStream) {
    672   if (!m_Options.m_bSeparateForm) {
    673     CPDF_Dictionary* pResources = pStream->GetDict()->GetDict("Resources");
    674     CFX_Matrix form_matrix = pStream->GetDict()->GetMatrix("Matrix");
    675     form_matrix.Concat(m_pCurStates->m_CTM);
    676     CPDF_Array* pBBox = pStream->GetDict()->GetArray("BBox");
    677     CFX_FloatRect form_bbox;
    678     CPDF_Path ClipPath;
    679     if (pBBox) {
    680       form_bbox = pStream->GetDict()->GetRect("BBox");
    681       ClipPath.New();
    682       ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right,
    683                           form_bbox.top);
    684       ClipPath.Transform(&form_matrix);
    685       form_bbox.Transform(&form_matrix);
    686     }
    687     CPDF_StreamContentParser parser(m_pDocument, m_pPageResources, m_pResources,
    688                                     &m_mtContentToUser, m_pObjectList,
    689                                     pResources, &form_bbox, &m_Options,
    690                                     m_pCurStates.get(), m_Level + 1);
    691     parser.m_pCurStates->m_CTM = form_matrix;
    692     if (ClipPath.NotNull()) {
    693       parser.m_pCurStates->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING,
    694                                                  TRUE);
    695     }
    696     CPDF_StreamAcc stream;
    697     stream.LoadAllData(pStream, FALSE);
    698     if (stream.GetSize() == 0) {
    699       return;
    700     }
    701     parser.Parse(stream.GetData(), stream.GetSize(), 0);
    702     return;
    703   }
    704   CPDF_FormObject* pFormObj = new CPDF_FormObject;
    705   pFormObj->m_pForm =
    706       new CPDF_Form(m_pDocument, m_pPageResources, pStream, m_pResources);
    707   pFormObj->m_FormMatrix = m_pCurStates->m_CTM;
    708   pFormObj->m_FormMatrix.Concat(m_mtContentToUser);
    709   CPDF_AllStates status;
    710   status.m_GeneralState = m_pCurStates->m_GeneralState;
    711   status.m_GraphState = m_pCurStates->m_GraphState;
    712   status.m_ColorState = m_pCurStates->m_ColorState;
    713   status.m_TextState = m_pCurStates->m_TextState;
    714   pFormObj->m_pForm->ParseContent(&status, NULL, NULL, &m_Options, m_Level + 1);
    715   if (!m_pObjectList->m_bBackgroundAlphaNeeded &&
    716       pFormObj->m_pForm->m_bBackgroundAlphaNeeded) {
    717     m_pObjectList->m_bBackgroundAlphaNeeded = TRUE;
    718   }
    719   pFormObj->CalcBoundingBox();
    720   SetGraphicStates(pFormObj, TRUE, TRUE, TRUE);
    721   m_pObjectList->m_ObjectList.AddTail(pFormObj);
    722 }
    723 CPDF_ImageObject* CPDF_StreamContentParser::AddImage(CPDF_Stream* pStream,
    724                                                      CPDF_Image* pImage,
    725                                                      FX_BOOL bInline) {
    726   if (!pStream && !pImage) {
    727     return NULL;
    728   }
    729   CFX_Matrix ImageMatrix;
    730   ImageMatrix.Copy(m_pCurStates->m_CTM);
    731   ImageMatrix.Concat(m_mtContentToUser);
    732   CPDF_ImageObject* pImageObj = new CPDF_ImageObject;
    733   if (pImage) {
    734     pImageObj->m_pImage =
    735         m_pDocument->GetPageData()->GetImage(pImage->GetStream());
    736   } else if (pStream->GetObjNum()) {
    737     pImageObj->m_pImage = m_pDocument->LoadImageF(pStream);
    738   } else {
    739     pImageObj->m_pImage = new CPDF_Image(m_pDocument);
    740     pImageObj->m_pImage->LoadImageF(pStream, bInline);
    741   }
    742   SetGraphicStates(pImageObj, pImageObj->m_pImage->IsMask(), FALSE, FALSE);
    743   pImageObj->m_Matrix = ImageMatrix;
    744   pImageObj->CalcBoundingBox();
    745   m_pObjectList->m_ObjectList.AddTail(pImageObj);
    746   return pImageObj;
    747 }
    748 void CPDF_StreamContentParser::Handle_MarkPlace_Dictionary() {}
    749 void CPDF_StreamContentParser::Handle_EndImage() {}
    750 void CPDF_StreamContentParser::Handle_EndMarkedContent() {
    751   if (!m_Options.m_bMarkedContent) {
    752     return;
    753   }
    754   if (m_CurContentMark.IsNull()) {
    755     return;
    756   }
    757   int count = m_CurContentMark.GetObject()->CountItems();
    758   if (count == 1) {
    759     m_CurContentMark.SetNull();
    760     return;
    761   }
    762   m_CurContentMark.GetModify()->DeleteLastMark();
    763 }
    764 void CPDF_StreamContentParser::Handle_EndText() {
    765   int count = m_ClipTextList.GetSize();
    766   if (count == 0) {
    767     return;
    768   }
    769   if (m_pCurStates->m_TextState.GetObject()->m_TextMode < 4) {
    770     for (int i = 0; i < count; i++) {
    771       delete m_ClipTextList.GetAt(i);
    772     }
    773   } else {
    774     m_pCurStates->m_ClipPath.AppendTexts(m_ClipTextList.GetData(), count);
    775   }
    776   m_ClipTextList.RemoveAll();
    777 }
    778 void CPDF_StreamContentParser::Handle_EndSectionUndefined() {
    779   if (m_CompatCount) {
    780     m_CompatCount--;
    781   }
    782 }
    783 void CPDF_StreamContentParser::Handle_FillPath() {
    784   if (m_Options.m_bTextOnly) {
    785     return;
    786   }
    787   AddPathObject(FXFILL_WINDING, FALSE);
    788 }
    789 void CPDF_StreamContentParser::Handle_FillPathOld() {
    790   if (m_Options.m_bTextOnly) {
    791     return;
    792   }
    793   AddPathObject(FXFILL_WINDING, FALSE);
    794 }
    795 void CPDF_StreamContentParser::Handle_EOFillPath() {
    796   if (m_Options.m_bTextOnly) {
    797     return;
    798   }
    799   AddPathObject(FXFILL_ALTERNATE, FALSE);
    800 }
    801 void CPDF_StreamContentParser::Handle_SetGray_Fill() {
    802   FX_FLOAT value = GetNumber(0);
    803   CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
    804   m_pCurStates->m_ColorState.SetFillColor(pCS, &value, 1);
    805 }
    806 void CPDF_StreamContentParser::Handle_SetGray_Stroke() {
    807   FX_FLOAT value = GetNumber(0);
    808   CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
    809   m_pCurStates->m_ColorState.SetStrokeColor(pCS, &value, 1);
    810 }
    811 void CPDF_StreamContentParser::Handle_SetExtendGraphState() {
    812   CFX_ByteString name = GetString(0);
    813   CPDF_Dictionary* pGS = ToDictionary(FindResourceObj("ExtGState", name));
    814   if (!pGS) {
    815     m_bResourceMissing = TRUE;
    816     return;
    817   }
    818   m_pCurStates->ProcessExtGS(pGS, this);
    819 }
    820 void CPDF_StreamContentParser::Handle_ClosePath() {
    821   if (m_Options.m_bTextOnly) {
    822     return;
    823   }
    824   if (m_PathPointCount == 0) {
    825     return;
    826   }
    827   if (m_PathStartX != m_PathCurrentX || m_PathStartY != m_PathCurrentY) {
    828     AddPathPoint(m_PathStartX, m_PathStartY, FXPT_LINETO | FXPT_CLOSEFIGURE);
    829   } else if (m_pPathPoints[m_PathPointCount - 1].m_Flag != FXPT_MOVETO) {
    830     m_pPathPoints[m_PathPointCount - 1].m_Flag |= FXPT_CLOSEFIGURE;
    831   }
    832 }
    833 void CPDF_StreamContentParser::Handle_SetFlat() {
    834   m_pCurStates->m_GeneralState.GetModify()->m_Flatness = GetNumber(0);
    835 }
    836 void CPDF_StreamContentParser::Handle_BeginImageData() {}
    837 void CPDF_StreamContentParser::Handle_SetLineJoin() {
    838   m_pCurStates->m_GraphState.GetModify()->m_LineJoin =
    839       (CFX_GraphStateData::LineJoin)GetInteger(0);
    840 }
    841 void CPDF_StreamContentParser::Handle_SetLineCap() {
    842   m_pCurStates->m_GraphState.GetModify()->m_LineCap =
    843       (CFX_GraphStateData::LineCap)GetInteger(0);
    844 }
    845 void CPDF_StreamContentParser::Handle_SetCMYKColor_Fill() {
    846   if (m_ParamCount != 4)
    847     return;
    848 
    849   FX_FLOAT values[4];
    850   for (int i = 0; i < 4; i++) {
    851     values[i] = GetNumber(3 - i);
    852   }
    853   CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
    854   m_pCurStates->m_ColorState.SetFillColor(pCS, values, 4);
    855 }
    856 void CPDF_StreamContentParser::Handle_SetCMYKColor_Stroke() {
    857   if (m_ParamCount != 4)
    858     return;
    859 
    860   FX_FLOAT values[4];
    861   for (int i = 0; i < 4; i++) {
    862     values[i] = GetNumber(3 - i);
    863   }
    864   CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
    865   m_pCurStates->m_ColorState.SetStrokeColor(pCS, values, 4);
    866 }
    867 void CPDF_StreamContentParser::Handle_LineTo() {
    868   if (m_ParamCount != 2)
    869     return;
    870 
    871   if (m_Options.m_bTextOnly) {
    872     return;
    873   }
    874   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_LINETO);
    875 }
    876 void CPDF_StreamContentParser::Handle_MoveTo() {
    877   if (m_ParamCount != 2)
    878     return;
    879 
    880   if (m_Options.m_bTextOnly) {
    881     m_pSyntax->SkipPathObject();
    882     return;
    883   }
    884   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_MOVETO);
    885   ParsePathObject();
    886 }
    887 void CPDF_StreamContentParser::Handle_SetMiterLimit() {
    888   m_pCurStates->m_GraphState.GetModify()->m_MiterLimit = GetNumber(0);
    889 }
    890 void CPDF_StreamContentParser::Handle_MarkPlace() {}
    891 void CPDF_StreamContentParser::Handle_EndPath() {
    892   if (m_Options.m_bTextOnly) {
    893     return;
    894   }
    895   AddPathObject(0, FALSE);
    896 }
    897 void CPDF_StreamContentParser::Handle_SaveGraphState() {
    898   std::unique_ptr<CPDF_AllStates> pStates(new CPDF_AllStates);
    899   pStates->Copy(*m_pCurStates);
    900   m_StateStack.push_back(std::move(pStates));
    901 }
    902 void CPDF_StreamContentParser::Handle_RestoreGraphState() {
    903   if (m_StateStack.empty())
    904     return;
    905   std::unique_ptr<CPDF_AllStates> pStates = std::move(m_StateStack.back());
    906   m_StateStack.pop_back();
    907   m_pCurStates->Copy(*pStates);
    908 }
    909 void CPDF_StreamContentParser::Handle_Rectangle() {
    910   if (m_Options.m_bTextOnly) {
    911     return;
    912   }
    913   FX_FLOAT x = GetNumber(3), y = GetNumber(2);
    914   FX_FLOAT w = GetNumber(1), h = GetNumber(0);
    915   AddPathRect(x, y, w, h);
    916 }
    917 void CPDF_StreamContentParser::AddPathRect(FX_FLOAT x,
    918                                            FX_FLOAT y,
    919                                            FX_FLOAT w,
    920                                            FX_FLOAT h) {
    921   AddPathPoint(x, y, FXPT_MOVETO);
    922   AddPathPoint(x + w, y, FXPT_LINETO);
    923   AddPathPoint(x + w, y + h, FXPT_LINETO);
    924   AddPathPoint(x, y + h, FXPT_LINETO);
    925   AddPathPoint(x, y, FXPT_LINETO | FXPT_CLOSEFIGURE);
    926 }
    927 void CPDF_StreamContentParser::Handle_SetRGBColor_Fill() {
    928   if (m_ParamCount != 3)
    929     return;
    930 
    931   FX_FLOAT values[3];
    932   for (int i = 0; i < 3; i++) {
    933     values[i] = GetNumber(2 - i);
    934   }
    935   CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
    936   m_pCurStates->m_ColorState.SetFillColor(pCS, values, 3);
    937 }
    938 void CPDF_StreamContentParser::Handle_SetRGBColor_Stroke() {
    939   if (m_ParamCount != 3)
    940     return;
    941 
    942   FX_FLOAT values[3];
    943   for (int i = 0; i < 3; i++) {
    944     values[i] = GetNumber(2 - i);
    945   }
    946   CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
    947   m_pCurStates->m_ColorState.SetStrokeColor(pCS, values, 3);
    948 }
    949 void CPDF_StreamContentParser::Handle_SetRenderIntent() {}
    950 void CPDF_StreamContentParser::Handle_CloseStrokePath() {
    951   if (m_Options.m_bTextOnly) {
    952     return;
    953   }
    954   Handle_ClosePath();
    955   AddPathObject(0, TRUE);
    956 }
    957 void CPDF_StreamContentParser::Handle_StrokePath() {
    958   if (m_Options.m_bTextOnly) {
    959     return;
    960   }
    961   AddPathObject(0, TRUE);
    962 }
    963 void CPDF_StreamContentParser::Handle_SetColor_Fill() {
    964   if (m_Options.m_bTextOnly) {
    965     return;
    966   }
    967   FX_FLOAT values[4];
    968   int nargs = m_ParamCount;
    969   if (nargs > 4) {
    970     nargs = 4;
    971   }
    972   for (int i = 0; i < nargs; i++) {
    973     values[i] = GetNumber(nargs - i - 1);
    974   }
    975   m_pCurStates->m_ColorState.SetFillColor(NULL, values, nargs);
    976 }
    977 void CPDF_StreamContentParser::Handle_SetColor_Stroke() {
    978   if (m_Options.m_bTextOnly) {
    979     return;
    980   }
    981   FX_FLOAT values[4];
    982   int nargs = m_ParamCount;
    983   if (nargs > 4) {
    984     nargs = 4;
    985   }
    986   for (int i = 0; i < nargs; i++) {
    987     values[i] = GetNumber(nargs - i - 1);
    988   }
    989   m_pCurStates->m_ColorState.SetStrokeColor(NULL, values, nargs);
    990 }
    991 void CPDF_StreamContentParser::Handle_SetColorPS_Fill() {
    992   if (m_Options.m_bTextOnly) {
    993     return;
    994   }
    995   CPDF_Object* pLastParam = GetObject(0);
    996   if (!pLastParam) {
    997     return;
    998   }
    999   int nargs = m_ParamCount;
   1000   int nvalues = nargs;
   1001   if (pLastParam->IsName()) {
   1002     nvalues--;
   1003   }
   1004   FX_FLOAT* values = NULL;
   1005   if (nvalues) {
   1006     values = FX_Alloc(FX_FLOAT, nvalues);
   1007     for (int i = 0; i < nvalues; i++) {
   1008       values[i] = GetNumber(nargs - i - 1);
   1009     }
   1010   }
   1011   if (nvalues != nargs) {
   1012     CPDF_Pattern* pPattern = FindPattern(GetString(0), FALSE);
   1013     if (pPattern) {
   1014       m_pCurStates->m_ColorState.SetFillPattern(pPattern, values, nvalues);
   1015     }
   1016   } else {
   1017     m_pCurStates->m_ColorState.SetFillColor(NULL, values, nvalues);
   1018   }
   1019   FX_Free(values);
   1020 }
   1021 void CPDF_StreamContentParser::Handle_SetColorPS_Stroke() {
   1022   if (m_Options.m_bTextOnly) {
   1023     return;
   1024   }
   1025   CPDF_Object* pLastParam = GetObject(0);
   1026   if (!pLastParam) {
   1027     return;
   1028   }
   1029   int nargs = m_ParamCount;
   1030   int nvalues = nargs;
   1031   if (pLastParam->IsName())
   1032     nvalues--;
   1033 
   1034   FX_FLOAT* values = NULL;
   1035   if (nvalues) {
   1036     values = FX_Alloc(FX_FLOAT, nvalues);
   1037     for (int i = 0; i < nvalues; i++) {
   1038       values[i] = GetNumber(nargs - i - 1);
   1039     }
   1040   }
   1041   if (nvalues != nargs) {
   1042     CPDF_Pattern* pPattern = FindPattern(GetString(0), FALSE);
   1043     if (pPattern) {
   1044       m_pCurStates->m_ColorState.SetStrokePattern(pPattern, values, nvalues);
   1045     }
   1046   } else {
   1047     m_pCurStates->m_ColorState.SetStrokeColor(NULL, values, nvalues);
   1048   }
   1049   FX_Free(values);
   1050 }
   1051 CFX_FloatRect GetShadingBBox(CPDF_Stream* pStream,
   1052                              ShadingType type,
   1053                              const CFX_Matrix* pMatrix,
   1054                              CPDF_Function** pFuncs,
   1055                              int nFuncs,
   1056                              CPDF_ColorSpace* pCS);
   1057 
   1058 void CPDF_StreamContentParser::Handle_ShadeFill() {
   1059   if (m_Options.m_bTextOnly) {
   1060     return;
   1061   }
   1062   CPDF_Pattern* pPattern = FindPattern(GetString(0), TRUE);
   1063   if (!pPattern) {
   1064     return;
   1065   }
   1066   if (pPattern->m_PatternType != CPDF_Pattern::SHADING) {
   1067     return;
   1068   }
   1069   CPDF_ShadingPattern* pShading = static_cast<CPDF_ShadingPattern*>(pPattern);
   1070   if (!pShading->m_bShadingObj) {
   1071     return;
   1072   }
   1073   if (!pShading->Load()) {
   1074     return;
   1075   }
   1076   CPDF_ShadingObject* pObj = new CPDF_ShadingObject;
   1077   pObj->m_pShading = pShading;
   1078   SetGraphicStates(pObj, FALSE, FALSE, FALSE);
   1079   pObj->m_Matrix = m_pCurStates->m_CTM;
   1080   pObj->m_Matrix.Concat(m_mtContentToUser);
   1081   CFX_FloatRect bbox;
   1082   if (!pObj->m_ClipPath.IsNull()) {
   1083     bbox = pObj->m_ClipPath.GetClipBox();
   1084   } else {
   1085     bbox = m_BBox;
   1086   }
   1087   if (pShading->IsMeshShading()) {
   1088     bbox.Intersect(GetShadingBBox(ToStream(pShading->m_pShadingObj),
   1089                                   pShading->m_ShadingType, &pObj->m_Matrix,
   1090                                   pShading->m_pFunctions, pShading->m_nFuncs,
   1091                                   pShading->m_pCS));
   1092   }
   1093   pObj->m_Left = bbox.left;
   1094   pObj->m_Right = bbox.right;
   1095   pObj->m_Top = bbox.top;
   1096   pObj->m_Bottom = bbox.bottom;
   1097   m_pObjectList->m_ObjectList.AddTail(pObj);
   1098 }
   1099 void CPDF_StreamContentParser::Handle_SetCharSpace() {
   1100   m_pCurStates->m_TextState.GetModify()->m_CharSpace = GetNumber(0);
   1101 }
   1102 void CPDF_StreamContentParser::Handle_MoveTextPoint() {
   1103   m_pCurStates->m_TextLineX += GetNumber(1);
   1104   m_pCurStates->m_TextLineY += GetNumber(0);
   1105   m_pCurStates->m_TextX = m_pCurStates->m_TextLineX;
   1106   m_pCurStates->m_TextY = m_pCurStates->m_TextLineY;
   1107 }
   1108 void CPDF_StreamContentParser::Handle_MoveTextPoint_SetLeading() {
   1109   Handle_MoveTextPoint();
   1110   m_pCurStates->m_TextLeading = -GetNumber(0);
   1111 }
   1112 void CPDF_StreamContentParser::Handle_SetFont() {
   1113   FX_FLOAT fs = GetNumber(0);
   1114   if (fs == 0) {
   1115     fs = m_DefFontSize;
   1116   }
   1117   m_pCurStates->m_TextState.GetModify()->m_FontSize = fs;
   1118   CPDF_Font* pFont = FindFont(GetString(1));
   1119   if (pFont) {
   1120     m_pCurStates->m_TextState.SetFont(pFont);
   1121   }
   1122 }
   1123 CPDF_Object* CPDF_StreamContentParser::FindResourceObj(
   1124     const CFX_ByteStringC& type,
   1125     const CFX_ByteString& name) {
   1126   if (!m_pResources) {
   1127     return NULL;
   1128   }
   1129   if (m_pResources == m_pPageResources) {
   1130     CPDF_Dictionary* pList = m_pResources->GetDict(type);
   1131     if (!pList) {
   1132       return NULL;
   1133     }
   1134     CPDF_Object* pRes = pList->GetElementValue(name);
   1135     return pRes;
   1136   }
   1137   CPDF_Dictionary* pList = m_pResources->GetDict(type);
   1138   if (!pList) {
   1139     if (!m_pPageResources) {
   1140       return NULL;
   1141     }
   1142     CPDF_Dictionary* pList = m_pPageResources->GetDict(type);
   1143     if (!pList) {
   1144       return NULL;
   1145     }
   1146     CPDF_Object* pRes = pList->GetElementValue(name);
   1147     return pRes;
   1148   }
   1149   CPDF_Object* pRes = pList->GetElementValue(name);
   1150   return pRes;
   1151 }
   1152 CPDF_Font* CPDF_StreamContentParser::FindFont(const CFX_ByteString& name) {
   1153   CPDF_Dictionary* pFontDict = ToDictionary(FindResourceObj("Font", name));
   1154   if (!pFontDict) {
   1155     m_bResourceMissing = TRUE;
   1156     return CPDF_Font::GetStockFont(m_pDocument, "Helvetica");
   1157   }
   1158 
   1159   CPDF_Font* pFont = m_pDocument->LoadFont(pFontDict);
   1160   if (pFont && pFont->GetType3Font()) {
   1161     pFont->GetType3Font()->SetPageResources(m_pResources);
   1162     pFont->GetType3Font()->CheckType3FontMetrics();
   1163   }
   1164   return pFont;
   1165 }
   1166 CPDF_ColorSpace* CPDF_StreamContentParser::FindColorSpace(
   1167     const CFX_ByteString& name) {
   1168   if (name == "Pattern") {
   1169     return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
   1170   }
   1171   if (name == "DeviceGray" || name == "DeviceCMYK" || name == "DeviceRGB") {
   1172     CFX_ByteString defname = "Default";
   1173     defname += name.Mid(7);
   1174     CPDF_Object* pDefObj = FindResourceObj("ColorSpace", defname);
   1175     if (!pDefObj) {
   1176       if (name == "DeviceGray") {
   1177         return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY);
   1178       }
   1179       if (name == "DeviceRGB") {
   1180         return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB);
   1181       }
   1182       return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK);
   1183     }
   1184     return m_pDocument->LoadColorSpace(pDefObj);
   1185   }
   1186   CPDF_Object* pCSObj = FindResourceObj("ColorSpace", name);
   1187   if (!pCSObj) {
   1188     m_bResourceMissing = TRUE;
   1189     return NULL;
   1190   }
   1191   return m_pDocument->LoadColorSpace(pCSObj);
   1192 }
   1193 CPDF_Pattern* CPDF_StreamContentParser::FindPattern(const CFX_ByteString& name,
   1194                                                     FX_BOOL bShading) {
   1195   CPDF_Object* pPattern =
   1196       FindResourceObj(bShading ? "Shading" : "Pattern", name);
   1197   if (!pPattern || (!pPattern->IsDictionary() && !pPattern->IsStream())) {
   1198     m_bResourceMissing = TRUE;
   1199     return NULL;
   1200   }
   1201   return m_pDocument->LoadPattern(pPattern, bShading,
   1202                                   &m_pCurStates->m_ParentMatrix);
   1203 }
   1204 void CPDF_StreamContentParser::ConvertTextSpace(FX_FLOAT& x, FX_FLOAT& y) {
   1205   m_pCurStates->m_TextMatrix.Transform(x, y, x, y);
   1206   ConvertUserSpace(x, y);
   1207 }
   1208 void CPDF_StreamContentParser::ConvertUserSpace(FX_FLOAT& x, FX_FLOAT& y) {
   1209   m_pCurStates->m_CTM.Transform(x, y, x, y);
   1210   m_mtContentToUser.Transform(x, y, x, y);
   1211 }
   1212 void CPDF_StreamContentParser::AddTextObject(CFX_ByteString* pStrs,
   1213                                              FX_FLOAT fInitKerning,
   1214                                              FX_FLOAT* pKerning,
   1215                                              int nsegs) {
   1216   CPDF_Font* pFont = m_pCurStates->m_TextState.GetFont();
   1217   if (!pFont) {
   1218     return;
   1219   }
   1220   if (fInitKerning != 0) {
   1221     if (!pFont->IsVertWriting()) {
   1222       m_pCurStates->m_TextX -=
   1223           FXSYS_Mul(fInitKerning, m_pCurStates->m_TextState.GetFontSize()) /
   1224           1000;
   1225     } else {
   1226       m_pCurStates->m_TextY -=
   1227           FXSYS_Mul(fInitKerning, m_pCurStates->m_TextState.GetFontSize()) /
   1228           1000;
   1229     }
   1230   }
   1231   if (nsegs == 0) {
   1232     return;
   1233   }
   1234   int textmode;
   1235   if (pFont->GetFontType() == PDFFONT_TYPE3) {
   1236     textmode = 0;
   1237   } else {
   1238     textmode = m_pCurStates->m_TextState.GetObject()->m_TextMode;
   1239   }
   1240   CPDF_TextObject* pText = new CPDF_TextObject;
   1241   m_pLastTextObject = pText;
   1242   SetGraphicStates(pText, TRUE, TRUE, TRUE);
   1243   if (textmode && textmode != 3 && textmode != 4 && textmode != 7) {
   1244     FX_FLOAT* pCTM = pText->m_TextState.GetModify()->m_CTM;
   1245     pCTM[0] = m_pCurStates->m_CTM.a;
   1246     pCTM[1] = m_pCurStates->m_CTM.c;
   1247     pCTM[2] = m_pCurStates->m_CTM.b;
   1248     pCTM[3] = m_pCurStates->m_CTM.d;
   1249   }
   1250   pText->SetSegments(pStrs, pKerning, nsegs);
   1251   pText->m_PosX = m_pCurStates->m_TextX;
   1252   pText->m_PosY = m_pCurStates->m_TextY + m_pCurStates->m_TextRise;
   1253   ConvertTextSpace(pText->m_PosX, pText->m_PosY);
   1254   FX_FLOAT x_advance, y_advance;
   1255   pText->CalcPositionData(&x_advance, &y_advance, m_pCurStates->m_TextHorzScale,
   1256                           m_Level);
   1257   m_pCurStates->m_TextX += x_advance;
   1258   m_pCurStates->m_TextY += y_advance;
   1259   if (textmode > 3) {
   1260     CPDF_TextObject* pCopy = new CPDF_TextObject;
   1261     pCopy->Copy(pText);
   1262     m_ClipTextList.Add(pCopy);
   1263   }
   1264   m_pObjectList->m_ObjectList.AddTail(pText);
   1265   if (pKerning && pKerning[nsegs - 1] != 0) {
   1266     if (!pFont->IsVertWriting()) {
   1267       m_pCurStates->m_TextX -=
   1268           FXSYS_Mul(pKerning[nsegs - 1],
   1269                     m_pCurStates->m_TextState.GetFontSize()) /
   1270           1000;
   1271     } else {
   1272       m_pCurStates->m_TextY -=
   1273           FXSYS_Mul(pKerning[nsegs - 1],
   1274                     m_pCurStates->m_TextState.GetFontSize()) /
   1275           1000;
   1276     }
   1277   }
   1278 }
   1279 void CPDF_StreamContentParser::Handle_ShowText() {
   1280   CFX_ByteString str = GetString(0);
   1281   if (str.IsEmpty()) {
   1282     return;
   1283   }
   1284   AddTextObject(&str, 0, NULL, 1);
   1285 }
   1286 void CPDF_StreamContentParser::Handle_ShowText_Positioning() {
   1287   CPDF_Array* pArray = GetObject(0) ? GetObject(0)->GetArray() : NULL;
   1288   if (!pArray) {
   1289     return;
   1290   }
   1291   int n = pArray->GetCount();
   1292   int nsegs = 0;
   1293   for (int i = 0; i < n; i++) {
   1294     if (pArray->GetElementValue(i)->IsString())
   1295       nsegs++;
   1296   }
   1297   if (nsegs == 0) {
   1298     for (int i = 0; i < n; i++) {
   1299       m_pCurStates->m_TextX -=
   1300           FXSYS_Mul(pArray->GetNumber(i),
   1301                     m_pCurStates->m_TextState.GetFontSize()) /
   1302           1000;
   1303     }
   1304     return;
   1305   }
   1306   CFX_ByteString* pStrs = new CFX_ByteString[nsegs];
   1307   FX_FLOAT* pKerning = FX_Alloc(FX_FLOAT, nsegs);
   1308   int iSegment = 0;
   1309   FX_FLOAT fInitKerning = 0;
   1310   for (int i = 0; i < n; i++) {
   1311     CPDF_Object* pObj = pArray->GetElementValue(i);
   1312     if (pObj->IsString()) {
   1313       CFX_ByteString str = pObj->GetString();
   1314       if (str.IsEmpty()) {
   1315         continue;
   1316       }
   1317       pStrs[iSegment] = str;
   1318       pKerning[iSegment++] = 0;
   1319     } else {
   1320       FX_FLOAT num = pObj ? pObj->GetNumber() : 0;
   1321       if (iSegment == 0) {
   1322         fInitKerning += num;
   1323       } else {
   1324         pKerning[iSegment - 1] += num;
   1325       }
   1326     }
   1327   }
   1328   AddTextObject(pStrs, fInitKerning, pKerning, iSegment);
   1329   delete[] pStrs;
   1330   FX_Free(pKerning);
   1331 }
   1332 void CPDF_StreamContentParser::Handle_SetTextLeading() {
   1333   m_pCurStates->m_TextLeading = GetNumber(0);
   1334 }
   1335 void CPDF_StreamContentParser::Handle_SetTextMatrix() {
   1336   m_pCurStates->m_TextMatrix.Set(GetNumber16(5), GetNumber16(4), GetNumber16(3),
   1337                                  GetNumber16(2), GetNumber(1), GetNumber(0));
   1338   OnChangeTextMatrix();
   1339   m_pCurStates->m_TextX = 0;
   1340   m_pCurStates->m_TextY = 0;
   1341   m_pCurStates->m_TextLineX = 0;
   1342   m_pCurStates->m_TextLineY = 0;
   1343 }
   1344 void CPDF_StreamContentParser::OnChangeTextMatrix() {
   1345   CFX_Matrix text_matrix(m_pCurStates->m_TextHorzScale, 0.0f, 0.0f, 1.0f, 0.0f,
   1346                          0.0f);
   1347   text_matrix.Concat(m_pCurStates->m_TextMatrix);
   1348   text_matrix.Concat(m_pCurStates->m_CTM);
   1349   text_matrix.Concat(m_mtContentToUser);
   1350   FX_FLOAT* pTextMatrix = m_pCurStates->m_TextState.GetModify()->m_Matrix;
   1351   pTextMatrix[0] = text_matrix.a;
   1352   pTextMatrix[1] = text_matrix.c;
   1353   pTextMatrix[2] = text_matrix.b;
   1354   pTextMatrix[3] = text_matrix.d;
   1355 }
   1356 void CPDF_StreamContentParser::Handle_SetTextRenderMode() {
   1357   int mode = GetInteger(0);
   1358   if (mode < 0 || mode > 7) {
   1359     return;
   1360   }
   1361   m_pCurStates->m_TextState.GetModify()->m_TextMode = mode;
   1362 }
   1363 void CPDF_StreamContentParser::Handle_SetTextRise() {
   1364   m_pCurStates->m_TextRise = GetNumber(0);
   1365 }
   1366 void CPDF_StreamContentParser::Handle_SetWordSpace() {
   1367   m_pCurStates->m_TextState.GetModify()->m_WordSpace = GetNumber(0);
   1368 }
   1369 void CPDF_StreamContentParser::Handle_SetHorzScale() {
   1370   if (m_ParamCount != 1) {
   1371     return;
   1372   }
   1373   m_pCurStates->m_TextHorzScale = GetNumber(0) / 100;
   1374   OnChangeTextMatrix();
   1375 }
   1376 void CPDF_StreamContentParser::Handle_MoveToNextLine() {
   1377   m_pCurStates->m_TextLineY -= m_pCurStates->m_TextLeading;
   1378   m_pCurStates->m_TextX = m_pCurStates->m_TextLineX;
   1379   m_pCurStates->m_TextY = m_pCurStates->m_TextLineY;
   1380 }
   1381 void CPDF_StreamContentParser::Handle_CurveTo_23() {
   1382   if (m_Options.m_bTextOnly) {
   1383     return;
   1384   }
   1385   AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO);
   1386   AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO);
   1387   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO);
   1388 }
   1389 void CPDF_StreamContentParser::Handle_SetLineWidth() {
   1390   FX_FLOAT width = GetNumber(0);
   1391   m_pCurStates->m_GraphState.GetModify()->m_LineWidth = width;
   1392 }
   1393 void CPDF_StreamContentParser::Handle_Clip() {
   1394   m_PathClipType = FXFILL_WINDING;
   1395 }
   1396 void CPDF_StreamContentParser::Handle_EOClip() {
   1397   m_PathClipType = FXFILL_ALTERNATE;
   1398 }
   1399 void CPDF_StreamContentParser::Handle_CurveTo_13() {
   1400   if (m_Options.m_bTextOnly) {
   1401     return;
   1402   }
   1403   AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO);
   1404   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO);
   1405   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO);
   1406 }
   1407 void CPDF_StreamContentParser::Handle_NextLineShowText() {
   1408   Handle_MoveToNextLine();
   1409   Handle_ShowText();
   1410 }
   1411 void CPDF_StreamContentParser::Handle_NextLineShowText_Space() {
   1412   m_pCurStates->m_TextState.GetModify()->m_WordSpace = GetNumber(2);
   1413   m_pCurStates->m_TextState.GetModify()->m_CharSpace = GetNumber(1);
   1414   Handle_NextLineShowText();
   1415 }
   1416 void CPDF_StreamContentParser::Handle_Invalid() {}
   1417 void CPDF_StreamContentParser::AddPathPoint(FX_FLOAT x, FX_FLOAT y, int flag) {
   1418   m_PathCurrentX = x;
   1419   m_PathCurrentY = y;
   1420   if (flag == FXPT_MOVETO) {
   1421     m_PathStartX = x;
   1422     m_PathStartY = y;
   1423     if (m_PathPointCount &&
   1424         m_pPathPoints[m_PathPointCount - 1].m_Flag == FXPT_MOVETO) {
   1425       m_pPathPoints[m_PathPointCount - 1].m_PointX = x;
   1426       m_pPathPoints[m_PathPointCount - 1].m_PointY = y;
   1427       return;
   1428     }
   1429   } else if (m_PathPointCount == 0) {
   1430     return;
   1431   }
   1432   m_PathPointCount++;
   1433   if (m_PathPointCount > m_PathAllocSize) {
   1434     int newsize = m_PathPointCount + 256;
   1435     FX_PATHPOINT* pNewPoints = FX_Alloc(FX_PATHPOINT, newsize);
   1436     if (m_PathAllocSize) {
   1437       FXSYS_memcpy(pNewPoints, m_pPathPoints,
   1438                    m_PathAllocSize * sizeof(FX_PATHPOINT));
   1439       FX_Free(m_pPathPoints);
   1440     }
   1441     m_pPathPoints = pNewPoints;
   1442     m_PathAllocSize = newsize;
   1443   }
   1444   m_pPathPoints[m_PathPointCount - 1].m_Flag = flag;
   1445   m_pPathPoints[m_PathPointCount - 1].m_PointX = x;
   1446   m_pPathPoints[m_PathPointCount - 1].m_PointY = y;
   1447 }
   1448 void CPDF_StreamContentParser::AddPathObject(int FillType, FX_BOOL bStroke) {
   1449   int PathPointCount = m_PathPointCount, PathClipType = m_PathClipType;
   1450   m_PathPointCount = 0;
   1451   m_PathClipType = 0;
   1452   if (PathPointCount <= 1) {
   1453     if (PathPointCount && PathClipType) {
   1454       CPDF_Path path;
   1455       path.New()->AppendRect(0, 0, 0, 0);
   1456       m_pCurStates->m_ClipPath.AppendPath(path, FXFILL_WINDING, TRUE);
   1457     }
   1458     return;
   1459   }
   1460   if (PathPointCount &&
   1461       m_pPathPoints[PathPointCount - 1].m_Flag == FXPT_MOVETO) {
   1462     PathPointCount--;
   1463   }
   1464   CPDF_Path Path;
   1465   CFX_PathData* pPathData = Path.New();
   1466   pPathData->SetPointCount(PathPointCount);
   1467   FXSYS_memcpy(pPathData->GetPoints(), m_pPathPoints,
   1468                sizeof(FX_PATHPOINT) * PathPointCount);
   1469   CFX_Matrix matrix = m_pCurStates->m_CTM;
   1470   matrix.Concat(m_mtContentToUser);
   1471   if (bStroke || FillType) {
   1472     CPDF_PathObject* pPathObj = new CPDF_PathObject;
   1473     pPathObj->m_bStroke = bStroke;
   1474     pPathObj->m_FillType = FillType;
   1475     pPathObj->m_Path = Path;
   1476     pPathObj->m_Matrix = matrix;
   1477     SetGraphicStates(pPathObj, TRUE, FALSE, TRUE);
   1478     pPathObj->CalcBoundingBox();
   1479     m_pObjectList->m_ObjectList.AddTail(pPathObj);
   1480   }
   1481   if (PathClipType) {
   1482     if (!matrix.IsIdentity()) {
   1483       Path.Transform(&matrix);
   1484       matrix.SetIdentity();
   1485     }
   1486     m_pCurStates->m_ClipPath.AppendPath(Path, PathClipType, TRUE);
   1487   }
   1488 }
   1489