Initial commit.
[pdfium.git] / core / src / reflow / layoutprovider_taggedpdf.cpp
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"
8 CPDF_LayoutElement::CPDF_LayoutElement()
9 {
10     m_pTaggedElement = NULL;
11     m_pParentElement = NULL;
12 }
13 CPDF_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 }
24 LayoutType 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 }
128 CFX_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 }
234 CFX_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 }
329 LayoutEnum 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 }
447 LayoutType 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 }
455 int     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 }
467 LayoutEnum 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 }
478 CFX_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 }
497 FX_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 }
511 FX_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 }
522 FX_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 }
535 FX_COLORREF CPDF_LayoutElement::GetDefaultColorValue(LayoutAttr attr_type)
536 {
537     return -1;
538 }
539 CFX_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 }
572 FX_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 }
597 int     CPDF_LayoutElement::CountChildren()
598 {
599     return m_ChildArray.GetSize();
600 }
601 IPDF_LayoutElement* CPDF_LayoutElement::GetChild(int index)
602 {
603     return (IPDF_LayoutElement*)m_ChildArray.GetAt(index);
604 }
605 IPDF_LayoutElement* CPDF_LayoutElement::GetParent()
606 {
607     return m_pParentElement;
608 }
609 int     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 }
618 CPDF_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 }
630 FX_BOOL CPDF_LayoutElement::AddObject(CPDF_PageObject* pObj)
631 {
632     return m_ObjArray.Add(pObj);
633 }
634 IPDF_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 }
646 CPDF_LayoutProvider_TaggedPDF::CPDF_LayoutProvider_TaggedPDF()
647 {
648     m_pPause = NULL;
649     m_pRoot = NULL;
650     m_pPageTree = NULL;
651     m_pCurTaggedElement = NULL;
652 }
653 CPDF_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 }
666 void 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 }
717 LayoutStatus 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 }
750 LayoutStatus 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 }
773 int 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 }