You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
8.4 KiB

// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#ifndef XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTPROCESSOR_H_
#define XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTPROCESSOR_H_
#include <float.h>
#include <list>
#include <map>
#include <memory>
#include <vector>
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
#include "third_party/base/optional.h"
#include "xfa/fxfa/fxfa_basic.h"
constexpr float kXFALayoutPrecision = 0.0005f;
class CXFA_ContentLayoutItem;
class CXFA_ContentLayoutProcessor;
class CXFA_LayoutProcessor;
class CXFA_Node;
class CXFA_ViewLayoutItem;
class CXFA_ViewLayoutProcessor;
class CXFA_ContentLayoutProcessor {
public:
enum class Result : uint8_t {
kDone,
kPageFullBreak,
kRowFullBreak,
kManualBreak,
};
enum class Stage : uint8_t {
kNone,
kBookendLeader,
kBreakBefore,
kKeep,
kContainer,
kBreakAfter,
kBookendTrailer,
kDone,
};
CXFA_ContentLayoutProcessor(CXFA_Node* pNode,
CXFA_ViewLayoutProcessor* pViewLayoutProcessor);
~CXFA_ContentLayoutProcessor();
Result DoLayout(bool bUseBreakControl, float fHeightLimit, float fRealHeight);
void DoLayoutPageArea(CXFA_ViewLayoutItem* pPageAreaLayoutItem);
CXFA_Node* GetFormNode() { return m_pFormNode; }
RetainPtr<CXFA_ContentLayoutItem> ExtractLayoutItem();
private:
class Context {
public:
Context();
~Context();
Optional<float> m_fCurColumnWidth;
UnownedPtr<std::vector<float>> m_prgSpecifiedColumnWidths;
UnownedPtr<CXFA_ContentLayoutProcessor> m_pOverflowProcessor;
UnownedPtr<CXFA_Node> m_pOverflowNode;
};
Result DoLayoutInternal(bool bUseBreakControl,
float fHeightLimit,
float fRealHeight,
Context* pContext);
CFX_SizeF GetCurrentComponentSize();
bool HasLayoutItem() const { return !!m_pLayoutItem; }
void SplitLayoutItem(float fSplitPos);
float FindSplitPos(float fProposedSplitPos);
bool ProcessKeepForSplit(
CXFA_ContentLayoutProcessor* pChildProcessor,
Result eRetValue,
std::vector<RetainPtr<CXFA_ContentLayoutItem>>* rgCurLineLayoutItem,
float* fContentCurRowAvailWidth,
float* fContentCurRowHeight,
float* fContentCurRowY,
bool* bAddedItemInRow,
bool* bForceEndPage,
Result* result);
void ProcessUnUseOverFlow(
CXFA_Node* pLeaderNode,
CXFA_Node* pTrailerNode,
const RetainPtr<CXFA_ContentLayoutItem>& pTrailerItem,
CXFA_Node* pFormNode);
bool IsAddNewRowForTrailer(CXFA_ContentLayoutItem* pTrailerItem);
bool JudgeLeaderOrTrailerForOccur(CXFA_Node* pFormNode);
RetainPtr<CXFA_ContentLayoutItem> CreateContentLayoutItem(
CXFA_Node* pFormNode);
void SetCurrentComponentPos(const CFX_PointF& pos);
void SetCurrentComponentSize(const CFX_SizeF& size);
void SplitLayoutItem(CXFA_ContentLayoutItem* pLayoutItem,
CXFA_ContentLayoutItem* pSecondParent,
float fSplitPos);
float InsertKeepLayoutItems();
bool CalculateRowChildPosition(
std::vector<RetainPtr<CXFA_ContentLayoutItem>> (&rgCurLineLayoutItems)[3],
XFA_AttributeValue eFlowStrategy,
bool bContainerHeightAutoSize,
bool bContainerWidthAutoSize,
float* fContentCalculatedWidth,
float* fContentCalculatedHeight,
float* fContentCurRowY,
float fContentCurRowHeight,
float fContentWidthLimit,
bool bRootForceTb);
void ProcessUnUseBinds(CXFA_Node* pFormNode);
bool JudgePutNextPage(
CXFA_ContentLayoutItem* pParentLayoutItem,
float fChildHeight,
std::vector<RetainPtr<CXFA_ContentLayoutItem>>* pKeepItems);
void DoLayoutPositionedContainer(Context* pContext);
void DoLayoutTableContainer(CXFA_Node* pLayoutNode);
Result DoLayoutFlowedContainer(bool bUseBreakControl,
XFA_AttributeValue eFlowStrategy,
float fHeightLimit,
float fRealHeight,
Context* pContext,
bool bRootForceTb);
void DoLayoutField();
void GotoNextContainerNodeSimple(bool bUsePageBreak);
Stage GotoNextContainerNode(Stage nCurStage,
bool bUsePageBreak,
CXFA_Node* pParentContainer,
CXFA_Node** pCurActionNode);
Optional<Stage> ProcessKeepNodesForCheckNext(CXFA_Node** pCurActionNode,
CXFA_Node** pNextContainer,
bool* pLastKeepNode);
Optional<Stage> ProcessKeepNodesForBreakBefore(CXFA_Node** pCurActionNode,
CXFA_Node* pContainerNode);
CXFA_Node* GetSubformSetParent(CXFA_Node* pSubformSet);
void UpdatePendingItemLayout(
const RetainPtr<CXFA_ContentLayoutItem>& pLayoutItem);
void AddTrailerBeforeSplit(
float fSplitPos,
const RetainPtr<CXFA_ContentLayoutItem>& pTrailerLayoutItem,
bool bUseInherited);
void AddLeaderAfterSplit(
const RetainPtr<CXFA_ContentLayoutItem>& pLeaderLayoutItem);
void AddPendingNode(CXFA_Node* pPendingNode, bool bBreakPending);
float InsertPendingItems(CXFA_Node* pCurChildNode);
Result InsertFlowedItem(
CXFA_ContentLayoutProcessor* pProcessor,
bool bContainerWidthAutoSize,
bool bContainerHeightAutoSize,
float fContainerHeight,
XFA_AttributeValue eFlowStrategy,
uint8_t* uCurHAlignState,
std::vector<RetainPtr<CXFA_ContentLayoutItem>> (&rgCurLineLayoutItems)[3],
bool bUseBreakControl,
float fAvailHeight,
float fRealHeight,
float fContentWidthLimit,
float* fContentCurRowY,
float* fContentCurRowAvailWidth,
float* fContentCurRowHeight,
bool* bAddedItemInRow,
bool* bForceEndPage,
Context* pLayoutContext,
bool bNewRow);
Optional<Stage> HandleKeep(CXFA_Node* pBreakAfterNode,
CXFA_Node** pCurActionNode);
Optional<Stage> HandleBookendLeader(CXFA_Node* pParentContainer,
CXFA_Node** pCurActionNode);
Optional<Stage> HandleBreakBefore(CXFA_Node* pChildContainer,
CXFA_Node** pCurActionNode);
Optional<Stage> HandleBreakAfter(CXFA_Node* pChildContainer,
CXFA_Node** pCurActionNode);
Optional<Stage> HandleCheckNextChildContainer(CXFA_Node* pParentContainer,
CXFA_Node* pChildContainer,
CXFA_Node** pCurActionNode);
Optional<Stage> HandleBookendTrailer(CXFA_Node* pParentContainer,
CXFA_Node** pCurActionNode);
void ProcessKeepNodesEnd();
void AdjustContainerSpecifiedSize(Context* pContext,
CFX_SizeF* pSize,
bool* pContainerWidthAutoSize,
bool* pContainerHeightAutoSize);
CXFA_ContentLayoutItem* FindLastContentLayoutItem(
XFA_AttributeValue eFlowStrategy);
CFX_SizeF CalculateLayoutItemSize(const CXFA_ContentLayoutItem* pLayoutChild);
Stage m_nCurChildNodeStage = Stage::kNone;
Result m_ePreProcessRs = Result::kDone;
bool m_bBreakPending = true;
bool m_bUseInherited = false;
bool m_bKeepBreakFinish = false;
bool m_bIsProcessKeep = false;
bool m_bHasAvailHeight = true;
float m_fUsedSize = 0;
float m_fLastRowWidth = 0;
float m_fLastRowY = 0;
float m_fWidthLimit = 0;
CXFA_Node* const m_pFormNode;
CXFA_Node* m_pCurChildNode = nullptr;
CXFA_Node* m_pKeepHeadNode = nullptr;
CXFA_Node* m_pKeepTailNode = nullptr;
RetainPtr<CXFA_ContentLayoutItem> m_pLayoutItem;
RetainPtr<CXFA_ContentLayoutItem> m_pOldLayoutItem;
UnownedPtr<CXFA_ViewLayoutProcessor> m_pViewLayoutProcessor;
std::vector<float> m_rgSpecifiedColumnWidths;
std::vector<RetainPtr<CXFA_ContentLayoutItem>> m_ArrayKeepItems;
std::list<CXFA_Node*> m_PendingNodes;
std::map<CXFA_Node*, int32_t> m_PendingNodesCount;
std::unique_ptr<CXFA_ContentLayoutProcessor> m_pCurChildPreprocessor;
};
#endif // XFA_FXFA_LAYOUT_CXFA_CONTENTLAYOUTPROCESSOR_H_