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 "layoutprovider_taggedpdf.h"
8CPDF_LayoutElement::CPDF_LayoutElement()
9{
10    m_pTaggedElement = NULL;
11    m_pParentElement = NULL;
12}
13CPDF_LayoutElement::~CPDF_LayoutElement()
14{
15    m_ObjArray.RemoveAll();
16    int size = m_ChildArray.GetSize();
17    for(int i = 0; i < size; i++) {
18        CPDF_LayoutElement* pChild = (CPDF_LayoutElement*)m_ChildArray.GetAt(i);
19        delete pChild;
20        pChild = NULL;
21    }
22    m_ChildArray.RemoveAll();
23}
24LayoutType CPDF_LayoutElement::ConvertLayoutType(FX_BSTR name)
25{
26    if(name == (const char*)("Document")) {
27        return LayoutDocument;
28    } else if(name == (const char*)("Part")) {
29        return LayoutPart;
30    } else if(name == (const char*)("Art")) {
31        return LayoutArt;
32    } else if(name == (const char*)("Sect")) {
33        return LayoutSect;
34    } else if(name == (const char*)("Div")) {
35        return LayoutDiv;
36    } else if(name == (const char*)("BlockQuote")) {
37        return LayoutBlockQuote;
38    } else if(name == (const char*)("Caption")) {
39        return LayoutCaption;
40    } else if(name == (const char*)("TOC")) {
41        return LayoutTOC;
42    } else if(name == (const char*)("TOCI")) {
43        return LayoutTOCI;
44    } else if(name == (const char*)("Index")) {
45        return LayoutIndex;
46    } else if(name == (const char*)("NonStruct")) {
47        return LayoutNonStruct;
48    } else if(name == (const char*)("Private")) {
49        return LayoutPrivate;
50    } else if(name == (const char*)("P")) {
51        return LayoutParagraph;
52    } else if(name == (const char*)("H")) {
53        return LayoutHeading;
54    } else if(name == (const char*)("H1")) {
55        return LayoutHeading1;
56    } else if(name == (const char*)("H2")) {
57        return LayoutHeading2;
58    } else if(name == (const char*)("H3")) {
59        return LayoutHeading3;
60    } else if(name == (const char*)("H4")) {
61        return LayoutHeading4;
62    } else if(name == (const char*)("H5")) {
63        return LayoutHeading5;
64    } else if(name == (const char*)("H6")) {
65        return LayoutHeading6;
66    } else if(name == (const char*)("L")) {
67        return LayoutList;
68    } else if(name == (const char*)("LI")) {
69        return LayoutListItem;
70    } else if(name == (const char*)("Lbl")) {
71        return LayoutListLabel;
72    } else if(name == (const char*)("LBody")) {
73        return LayoutListBody;
74    } else if(name == (const char*)("Table")) {
75        return LayoutTable;
76    } else if(name == (const char*)("TR")) {
77        return LayoutTableRow;
78    } else if(name == (const char*)("TH")) {
79        return LayoutTableHeaderCell;
80    } else if(name == (const char*)("TD")) {
81        return LayoutTableDataCell;
82    } else if(name == (const char*)("THead")) {
83        return LayoutTableHeaderGroup;
84    } else if(name == (const char*)("TBody")) {
85        return LayoutTableBodyGroup;
86    } else if(name == (const char*)("TFoot")) {
87        return LayoutTableFootGroup;
88    } else if(name == (const char*)("Span")) {
89        return LayoutSpan;
90    } else if(name == (const char*)("Quote")) {
91        return LayoutQuote;
92    } else if(name == (const char*)("Note")) {
93        return LayoutNote;
94    } else if(name == (const char*)("Reference")) {
95        return LayoutReference;
96    } else if(name == (const char*)("BibEntry")) {
97        return LayoutBibEntry;
98    } else if(name == (const char*)("Code")) {
99        return LayoutCode;
100    } else if(name == (const char*)("Link")) {
101        return LayoutLink;
102    } else if(name == (const char*)("Annot")) {
103        return LayoutAnnot;
104    } else if(name == (const char*)("Ruby")) {
105        return LayoutRuby;
106    } else if(name == (const char*)("RB")) {
107        return LayoutRubyBase;
108    } else if(name == (const char*)("RT")) {
109        return LayoutRubyAnnot;
110    } else if(name == (const char*)("RP")) {
111        return LayoutRubyPunc;
112    } else if(name == (const char*)("Warichu")) {
113        return LayoutWarichu;
114    } else if(name == (const char*)("WT")) {
115        return LayoutWarichuText;
116    } else if(name == (const char*)("WP")) {
117        return LayoutWarichuPunc;
118    } else if(name == (const char*)("Figure")) {
119        return LayoutFigure;
120    } else if(name == (const char*)("Formula")) {
121        return LayoutFormula;
122    } else if(name == (const char*)("Form")) {
123        return LayoutForm;
124    } else {
125        return LayoutUnknown;
126    }
127}
128CFX_ByteStringC CPDF_LayoutElement::ConvertLayoutType(LayoutType type)
129{
130    FX_BSTR name = "";
131    if(type == LayoutArifact) {
132        return "Arifact";
133    } else if( type == LayoutDocument) {
134        return "Document";
135    } else if( type == LayoutPart) {
136        return "Part";
137    } else if( type == LayoutArt) {
138        return "Art";
139    } else if( type == LayoutSect) {
140        return "Sect";
141    } else if( type == LayoutDiv) {
142        return "Div";
143    } else if( type == LayoutBlockQuote) {
144        return "BlockQuote";
145    } else if( type == LayoutCaption) {
146        return "Caption";
147    } else if( type == LayoutTOC) {
148        return "TOC";
149    } else if( type == LayoutTOCI) {
150        return "TOCI";
151    } else if( type == LayoutIndex) {
152        return "Index";
153    } else if( type == LayoutNonStruct) {
154        return "NonStruct";
155    } else if( type == LayoutPrivate) {
156        return "Private";
157    } else if( type == LayoutParagraph) {
158        return "P";
159    } else if( type == LayoutHeading) {
160        return "H";
161    } else if( type == LayoutHeading1) {
162        return "H1";
163    } else if( type == LayoutHeading2) {
164        return "H2";
165    } else if( type == LayoutHeading3) {
166        return "H3";
167    } else if( type == LayoutHeading4) {
168        return "H4";
169    } else if( type == LayoutHeading5) {
170        return "H5";
171    } else if( type == LayoutHeading6) {
172        return "H6";
173    } else if( type == LayoutList) {
174        return "L";
175    } else if( type == LayoutListItem) {
176        return "LI";
177    } else if( type == LayoutListLabel) {
178        return "Lbl";
179    } else if( type == LayoutListBody) {
180        return "LBody";
181    } else if( type == LayoutTable) {
182        return "Table";
183    } else if( type == LayoutTableRow) {
184        return "TR";
185    } else if( type == LayoutTableHeaderCell) {
186        return "TH";
187    } else if( type == LayoutTableDataCell) {
188        return "TD";
189    } else if( type == LayoutTableHeaderGroup) {
190        return "THead";
191    } else if( type == LayoutTableBodyGroup) {
192        return "TBody";
193    } else if( type == LayoutTableFootGroup) {
194        return "TFoot";
195    } else if( type == LayoutSpan) {
196        return "Span";
197    } else if( type == LayoutQuote) {
198        return "Quote";
199    } else if( type == LayoutNote) {
200        return "Note";
201    } else if( type == LayoutReference) {
202        return "Reference";
203    } else if( type == LayoutBibEntry) {
204        return "BibEntry";
205    } else if( type == LayoutCode) {
206        return "Code";
207    } else if( type == LayoutLink) {
208        return "Link";
209    } else if( type == LayoutAnnot) {
210        return "Annot";
211    } else if( type == LayoutRuby) {
212        return "Ruby";
213    } else if( type == LayoutRubyBase) {
214        return "RB";
215    } else if( type == LayoutRubyAnnot) {
216        return "RT";
217    } else if( type == LayoutRubyPunc) {
218        return "RP";
219    } else if( type == LayoutWarichu) {
220        return "Warichu";
221    } else if( type == LayoutWarichuText) {
222        return "WT";
223    } else if( type == LayoutWarichuPunc) {
224        return "WP";
225    } else if( type == LayoutFigure) {
226        return "Figure";
227    } else if( type == LayoutFormula) {
228        return "Formula";
229    } else if( type == LayoutForm) {
230        return "Form";
231    }
232    return name;
233}
234CFX_ByteStringC CPDF_LayoutElement::ConvertLayoutAttr(LayoutAttr attr)
235{
236    switch(attr) {
237        case LayoutArtifactType:
238            return "Type";
239        case LayoutArtifactAttached:
240            return "Attached";
241        case LayoutArtifactSubType:
242            return "Subtype";
243        case LayoutPlacement:
244            return "Placement";
245        case LayoutWritingMode:
246            return "WritingMode";
247        case LayoutBackgroundColor:
248            return "BackgroundColor";
249        case LayoutBorderColor:
250            return "BorderColor";
251        case LayoutBorderStyle:
252            return "BorderStyle";
253        case LayoutBorderThickness:
254            return "BorderThickness";
255        case LayoutPadding:
256            return "Padding";
257        case LayoutColor:
258            return "Color";
259        case LayoutSpaceBefore:
260            return "SpaceBefore";
261        case LayoutSpaceAfter:
262            return "SpaceAfter";
263        case LayoutStartIndent:
264            return "StartIndent";
265        case LayoutEndIndent:
266            return "EndIndent";
267        case LayoutTextIndent:
268            return "TextIndent";
269        case LayoutTextAlign:
270            return "TextAlign";
271        case LayoutBBox:
272            return "BBox";
273        case LayoutWidth:
274            return "Width";
275        case LayoutHeight:
276            return "Height";
277        case LayoutBlockAlign:
278            return "BlockAlign";
279        case LayoutInlineAlign:
280            return "InlineAlign";
281        case LayoutTBorderStyle:
282            return "TBorderStyle";
283        case LayoutTPadding:
284            return "TPadding";
285        case LayoutBaselineShift:
286            return "BaselineShift";
287        case LayoutLineHeight:
288            return "LineHeight";
289        case LayoutTextDecorationColor:
290            return "TextDecorationColor";
291        case LayoutTextDecorationThickness:
292            return "TextDecorationThickness";
293        case LayoutTextDecorationType:
294            return "TextDecorationType";
295        case LayoutRubyAlign:
296            return "RubyAlign";
297        case LayoutRubyPosition:
298            return "RubyPosition";
299        case LayoutGlyphOrientationVertical:
300            return "GlyphOrientationVertical";
301        case LayoutColumnCount:
302            return "ColumnCount";
303        case LayoutColumnGap:
304            return "ColumnGap";
305        case LayoutColumnWidths:
306            return "ColumnWidths";
307        case LayoutListNumbering:
308            return "ListNumbering";
309        case LayoutFieldRole:
310            return "Role";
311        case LayoutFieldChecked:
312            return "checked";
313        case LayoutFieldDesc:
314            return "Desc";
315        case LayoutRowSpan:
316            return "RowSpan";
317        case LayoutColSpan:
318            return "ColSpan";
319        case LayoutTableHeaders:
320            return "Headers";
321        case LayoutTableHeaderScope:
322            return "Scope";
323        case LayoutTableSummary:
324            return "Summary";
325        default:
326            return "";
327    }
328}
329LayoutEnum CPDF_LayoutElement::ConvertLayoutEnum(CFX_ByteStringC Enum)
330{
331    if(Enum == "Block") {
332        return LayoutBlock;
333    } else if (Enum == "Inline") {
334        return LayoutInline;
335    } else if (Enum == "Before") {
336        return LayoutBefore;
337    } else if (Enum == "Start") {
338        return LayoutStart;
339    } else if (Enum == "End") {
340        return LayoutEnd;
341    } else if (Enum == "LrTb") {
342        return LayoutLrTb;
343    } else if (Enum == "RlTb") {
344        return LayoutRlTb;
345    } else if (Enum == "TbRl") {
346        return LayoutTbRl;
347    } else if (Enum == "None") {
348        return LayoutNone;
349    } else if (Enum == "Hidden") {
350        return LayoutHidden;
351    } else if (Enum == "Dotted") {
352        return LayoutDotted;
353    } else if (Enum == "Dashed") {
354        return LayoutDashed;
355    } else if (Enum == "Solid") {
356        return LayoutSolid;
357    } else if (Enum == "Double") {
358        return LayoutDouble;
359    } else if (Enum == "Groove") {
360        return LayoutGroove;
361    } else if (Enum == "Ridge") {
362        return LayoutRidge;
363    } else if (Enum == "Inset") {
364        return LayoutInset;
365    } else if (Enum == "Outset") {
366        return LayoutOutset;
367    } else if (Enum == "Normal") {
368        return LayoutNormal;
369    } else if (Enum == "Auto") {
370        return LayoutAuto;
371    } else if (Enum == "Center") {
372        return LayoutCenter;
373    } else if (Enum == "Justify") {
374        return LayoutJustify;
375    } else if (Enum == "Middle") {
376        return LayoutMiddle;
377    } else if (Enum == "Underline") {
378        return LayoutUnderline;
379    } else if (Enum == "Overline") {
380        return LayoutOverline;
381    } else if (Enum == "LineThrough") {
382        return LayoutLineThrough;
383    } else if (Enum == "Distribute") {
384        return LayoutDistribute;
385    } else if (Enum == "Disc") {
386        return LayoutDisc;
387    } else if (Enum == "Circle") {
388        return LayoutCircle;
389    } else if (Enum == "Square") {
390        return LayoutSquare;
391    } else if (Enum == "Decimal") {
392        return LayoutDecimal;
393    } else if (Enum == "UpperRoman") {
394        return LayoutUpperRoman;
395    } else if (Enum == "LowerRoman") {
396        return LayoutLowerRoman;
397    } else if (Enum == "UpperAlpha") {
398        return LayoutUpperAlpha;
399    } else if (Enum == "LowerAlpha") {
400        return LayoutLowerAlpha;
401    } else if (Enum == "rb") {
402        return LayoutRB;
403    } else if (Enum == "cb") {
404        return LayoutCB;
405    } else if (Enum == "pb") {
406        return LayoutPB;
407    } else if (Enum == "tv") {
408        return LayoutTV;
409    } else if (Enum == "on") {
410        return LayoutOn;
411    } else if (Enum == "off") {
412        return LayoutOff;
413    } else if (Enum == "neutral") {
414        return LayoutNeutral;
415    } else if (Enum == "Row") {
416        return LayoutRow;
417    } else if (Enum == "Column") {
418        return LayoutColumn;
419    } else if (Enum == "Both") {
420        return LayoutBoth;
421    } else if (Enum == "Left") {
422        return LayoutLeft;
423    } else if (Enum == "Top") {
424        return LayoutTop;
425    } else if (Enum == "Bottom") {
426        return LayoutBottom;
427    } else if (Enum == "Right") {
428        return LayoutRight;
429    } else if (Enum == "Pagination") {
430        return LayoutPagination;
431    } else if (Enum == "Layout") {
432        return LayoutLayout;
433    } else if (Enum == "Page") {
434        return LayoutPage;
435    } else if (Enum == "Background") {
436        return LayoutBackground;
437    } else if (Enum == "Header") {
438        return LayoutHeader;
439    } else if (Enum == "Footer") {
440        return LayoutFooter;
441    } else if (Enum == "Watermark") {
442        return LayoutWatermark;
443    } else {
444        return LayoutInvalid;
445    }
446}
447LayoutType CPDF_LayoutElement::GetType()
448{
449    if(!m_pTaggedElement) {
450        return LayoutUnknown;
451    }
452    CFX_ByteString name = m_pTaggedElement->GetType();
453    return this->ConvertLayoutType(name);
454}
455int	CPDF_LayoutElement::CountAttrValues(LayoutAttr attr_type)
456{
457    if(!m_pTaggedElement) {
458        return 0;
459    }
460    CPDF_Object* pObj = m_pTaggedElement->GetAttr(GetAttrOwner(attr_type), ConvertLayoutAttr(attr_type), IsInheritable(attr_type));
461    if(pObj) {
462        return 1;
463    } else {
464        return 0;
465    }
466}
467LayoutEnum CPDF_LayoutElement::GetEnumAttr(LayoutAttr attr_type, int index)
468{
469    if(!m_pTaggedElement) {
470        return LayoutInvalid;
471    }
472    CFX_ByteStringC owner = GetAttrOwner(attr_type);
473    CFX_ByteStringC default_value = GetDefaultNameValue(attr_type);
474    CFX_ByteStringC AttrName = ConvertLayoutAttr(attr_type);
475    CFX_ByteString	AttrValue = m_pTaggedElement->GetName(owner, AttrName, default_value, IsInheritable(attr_type), index);
476    return ConvertLayoutEnum(AttrValue);
477}
478CFX_ByteStringC CPDF_LayoutElement::GetAttrOwner(LayoutAttr attr_type)
479{
480    switch(attr_type) {
481        case LayoutListNumbering:
482            return "List";
483        case LayoutFieldRole:
484        case LayoutFieldChecked :
485        case LayoutFieldDesc:
486            return "PrintField";
487        case LayoutRowSpan:
488        case LayoutColSpan:
489        case LayoutTableHeaders:
490        case LayoutTableHeaderScope:
491        case LayoutTableSummary:
492            return "Table";
493        default:
494            return "Layout";
495    }
496}
497FX_FLOAT	CPDF_LayoutElement::GetNumberAttr(LayoutAttr attr_type, int index)
498{
499    if(!m_pTaggedElement) {
500        return 0;
501    }
502    CFX_ByteStringC owner = GetAttrOwner(attr_type);
503    FX_FLOAT default_value = GetDefaultFloatValue(attr_type);
504    CFX_ByteStringC AttrName = ConvertLayoutAttr(attr_type);
505    FX_FLOAT f = m_pTaggedElement->GetNumber(owner, AttrName, default_value, IsInheritable(attr_type), index);
506    if(attr_type == LayoutWidth && !f) {
507        f = m_pTaggedElement->GetNumber("Table", AttrName, default_value, IsInheritable(attr_type), index);
508    }
509    return f;
510}
511FX_COLORREF	CPDF_LayoutElement::GetColorAttr(LayoutAttr attr_type, int index)
512{
513    if(!m_pTaggedElement) {
514        return 0;
515    }
516    CFX_ByteStringC owner = GetAttrOwner(attr_type);
517    FX_COLORREF default_value = GetDefaultColorValue(attr_type);
518    CFX_ByteStringC AttrName = ConvertLayoutAttr(attr_type);
519    FX_ARGB f = m_pTaggedElement->GetColor(owner, AttrName, default_value, IsInheritable(attr_type), index);
520    return f;
521}
522FX_FLOAT CPDF_LayoutElement::GetDefaultFloatValue(LayoutAttr attr_type)
523{
524    switch(attr_type) {
525        case LayoutColumnCount:
526            return 1;
527        case LayoutRowSpan:
528            return 1;
529        case LayoutColSpan:
530            return 1;
531        default:
532            return 0;
533    }
534}
535FX_COLORREF CPDF_LayoutElement::GetDefaultColorValue(LayoutAttr attr_type)
536{
537    return -1;
538}
539CFX_ByteStringC CPDF_LayoutElement::GetDefaultNameValue(LayoutAttr attr_type)
540{
541    switch(attr_type) {
542        case LayoutPlacement:
543            return "Inline";
544        case LayoutWritingMode:
545            return "LrTb";
546        case LayoutBorderStyle:
547            return "None";
548        case LayoutTextAlign:
549            return "Start";
550        case LayoutBlockAlign:
551            return "Before";
552        case LayoutInlineAlign:
553            return "Start";
554        case LayoutTBorderStyle:
555            return "None";
556        case LayoutTextDecorationType:
557            return "None";
558        case LayoutRubyAlign:
559            return "Distribute";
560        case LayoutRubyPosition:
561            return "Before";
562        case LayoutGlyphOrientationVertical:
563            return "Auto";
564        case LayoutListNumbering:
565            return "None";
566        case LayoutFieldRole:
567            return "None";
568        default:
569            return "";
570    }
571}
572FX_BOOL	CPDF_LayoutElement::IsInheritable(LayoutAttr type)
573{
574    switch(type) {
575        case LayoutWritingMode:
576        case LayoutTextAlign:
577        case LayoutBlockAlign:
578        case LayoutInlineAlign:
579        case LayoutLineHeight:
580        case LayoutGlyphOrientationVertical:
581        case LayoutRubyAlign:
582        case LayoutRubyPosition:
583        case LayoutBorderThickness:
584        case LayoutStartIndent:
585        case LayoutEndIndent:
586        case LayoutTextIndent:
587        case LayoutTPadding:
588        case LayoutTextDecorationThickness:
589        case LayoutBorderColor:
590        case LayoutColor:
591        case LayoutTextDecorationColor:
592            return TRUE;
593        default:
594            return FALSE;
595    }
596}
597int	CPDF_LayoutElement::CountChildren()
598{
599    return m_ChildArray.GetSize();
600}
601IPDF_LayoutElement* CPDF_LayoutElement::GetChild(int index)
602{
603    return (IPDF_LayoutElement*)m_ChildArray.GetAt(index);
604}
605IPDF_LayoutElement* CPDF_LayoutElement::GetParent()
606{
607    return m_pParentElement;
608}
609int	CPDF_LayoutElement::CountObjects()
610{
611    if(m_pTaggedElement == NULL) {
612        return 0;
613    }
614    CFX_PtrArray* pObj = &m_ObjArray;
615    int size = pObj->GetSize();
616    return size;
617}
618CPDF_PageObject* CPDF_LayoutElement::GetObject(int index)
619{
620    if(m_pTaggedElement == NULL) {
621        return NULL;
622    }
623    CFX_PtrArray *pObj = &m_ObjArray;
624    int size = pObj->GetSize();
625    if(index < size) {
626        return (CPDF_PageObject*)pObj->GetAt(index);
627    }
628    return NULL;
629}
630FX_BOOL CPDF_LayoutElement::AddObject(CPDF_PageObject* pObj)
631{
632    return m_ObjArray.Add(pObj);
633}
634IPDF_LayoutProvider* IPDF_LayoutProvider::Create_LayoutProvider_TaggedPDF(CPDF_PageObjects* pPage)
635{
636    if(pPage == NULL) {
637        return NULL;
638    }
639    CPDF_LayoutProvider_TaggedPDF* pProvider = FX_NEW CPDF_LayoutProvider_TaggedPDF;
640    if (!pProvider) {
641        return NULL;
642    }
643    pProvider->Init(pPage);
644    return pProvider;
645}
646CPDF_LayoutProvider_TaggedPDF::CPDF_LayoutProvider_TaggedPDF()
647{
648    m_pPause = NULL;
649    m_pRoot = NULL;
650    m_pPageTree = NULL;
651    m_pCurTaggedElement = NULL;
652}
653CPDF_LayoutProvider_TaggedPDF::~CPDF_LayoutProvider_TaggedPDF()
654{
655    m_pCurTaggedElement = NULL;
656    m_pPause = NULL;
657    if(m_pRoot) {
658        delete m_pRoot;
659    }
660    m_pRoot = NULL;
661    if(m_pPageTree) {
662        delete m_pPageTree;
663    }
664    m_pPageTree = NULL;
665}
666void CPDF_LayoutProvider_TaggedPDF::ProcessElement(CPDF_LayoutElement*pParent, CPDF_StructElement* pTaggedElement)
667{
668    if(!pTaggedElement) {
669        return;
670    }
671    if(!pParent) {
672        m_Status = LayoutError;
673        return;
674    }
675    CPDF_LayoutElement* pElement = FX_NEW CPDF_LayoutElement;
676    if (!pElement) {
677        m_Status = LayoutError;
678        return;
679    }
680    pElement->m_pParentElement = pParent;
681    pElement->m_pTaggedElement = pTaggedElement;
682    pParent->m_ChildArray.Add(pElement);
683    int count = pTaggedElement->CountKids();
684    for(int i = 0; i < count; i++) {
685        CPDF_StructKid Kid = pTaggedElement->GetKid(i);
686        switch(Kid.m_Type) {
687            case CPDF_StructKid::Element: {
688                    ProcessElement(pElement, Kid.m_Element.m_pElement);
689                    if(m_Status != LayoutReady) {
690                        return ;
691                    }
692                }
693                break;
694            case CPDF_StructKid::PageContent: {
695                    int count = m_pPage->CountObjects();
696                    FX_POSITION pos = m_pPage->GetFirstObjectPosition();
697                    if(!pos) {
698                        m_Status = LayoutError;
699                        return ;
700                    }
701                    while (pos) {
702                        CPDF_PageObject* pObj = m_pPage->GetNextObject(pos);
703                        int pbjMCID = pObj->m_ContentMark.GetMCID();
704                        if((FX_DWORD)(pObj->m_ContentMark.GetMCID()) == Kid.m_PageContent.m_ContentId) {
705                            pElement->AddObject(pObj);
706                        }
707                    }
708                }
709                break;
710            case CPDF_StructKid::StreamContent:
711            case CPDF_StructKid::Object:
712            default:
713                break;
714        }
715    }
716}
717LayoutStatus CPDF_LayoutProvider_TaggedPDF::StartLoad(IFX_Pause* pPause)
718{
719    m_pPause = pPause;
720    if(m_pPage->m_pDocument && m_pPage->m_pFormDict) {
721        m_pPageTree = CPDF_StructTree::LoadPage(m_pPage->m_pDocument, m_pPage->m_pFormDict);
722    }
723    if(!m_pPageTree) {
724        m_Status = LayoutError;
725        return LayoutError;
726    }
727    int count = m_pPageTree->CountTopElements();
728    if(count == 0) {
729        m_Status = LayoutError;
730        return LayoutError;
731    }
732    m_pRoot = FX_NEW CPDF_LayoutElement;
733    if (!m_pRoot) {
734        m_Status = LayoutError;
735        return LayoutError;
736    }
737    for(int i = 0; i < count; i++) {
738        CPDF_StructElement* pElement = m_pPageTree->GetTopElement(i);
739        if(pElement) {
740            ProcessElement(m_pRoot, pElement);
741            if(m_Status != LayoutReady) {
742                return m_Status;
743            }
744        }
745    }
746    m_pCurTaggedElement = NULL;
747    m_Status = LayoutFinished;
748    return LayoutFinished;
749}
750LayoutStatus CPDF_LayoutProvider_TaggedPDF::Continue()
751{
752    if(!m_pCurTaggedElement) {
753        return LayoutError;
754    }
755    if(m_Status != LayoutToBeContinued) {
756        return LayoutError;
757    }
758    m_Status = LayoutReady;
759    int count = m_pPageTree->CountTopElements();
760    for(int i = 0; i < count; i++) {
761        CPDF_StructElement* pElement = m_pPageTree->GetTopElement(i);
762        if(pElement) {
763            ProcessElement(m_pRoot, pElement);
764            if(m_Status != LayoutReady) {
765                return m_Status;
766            }
767        }
768    }
769    m_pCurTaggedElement = NULL;
770    m_Status = LayoutFinished;
771    return LayoutFinished;
772}
773int CPDF_LayoutProvider_TaggedPDF::GetPosition()
774{
775    if(m_TopElementIndex == 0) {
776        return 0;
777    }
778    int count = m_pPageTree->CountTopElements();
779    return m_TopElementIndex / count * 100;
780}
781