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