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