blob: cbe92fd1420e644cfbac59066c0e3b6c86f3c1c1 [file] [log] [blame]
// Copyright 2016 The PDFium Authors
// 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
#include "core/fpdfapi/page/cpdf_form.h"
#include <algorithm>
#include <memory>
#include "core/fpdfapi/page/cpdf_contentparser.h"
#include "core/fpdfapi/page/cpdf_imageobject.h"
#include "core/fpdfapi/page/cpdf_pageobject.h"
#include "core/fpdfapi/page/cpdf_pageobjectholder.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fxcrt/check_op.h"
#include "core/fxge/dib/cfx_dibitmap.h"
CPDF_Form::RecursionState::RecursionState() = default;
CPDF_Form::RecursionState::~RecursionState() = default;
// static
CPDF_Dictionary* CPDF_Form::ChooseResourcesDict(
CPDF_Dictionary* pResources,
CPDF_Dictionary* pParentResources,
CPDF_Dictionary* pPageResources) {
if (pResources)
return pResources;
return pParentResources ? pParentResources : pPageResources;
}
CPDF_Form::CPDF_Form(CPDF_Document* pDoc,
RetainPtr<CPDF_Dictionary> pPageResources,
RetainPtr<CPDF_Stream> pFormStream)
: CPDF_Form(pDoc,
std::move(pPageResources),
std::move(pFormStream),
nullptr) {}
CPDF_Form::CPDF_Form(CPDF_Document* pDoc,
RetainPtr<CPDF_Dictionary> pPageResources,
RetainPtr<CPDF_Stream> pFormStream,
CPDF_Dictionary* pParentResources)
: CPDF_PageObjectHolder(pDoc,
pFormStream->GetMutableDict(),
pPageResources,
pdfium::WrapRetain(ChooseResourcesDict(
pFormStream->GetMutableDict()
->GetMutableDictFor("Resources")
.Get(),
pParentResources,
pPageResources.Get()))),
m_pFormStream(std::move(pFormStream)) {
LoadTransparencyInfo();
}
CPDF_Form::~CPDF_Form() = default;
void CPDF_Form::ParseContent() {
ParseContentInternal(nullptr, nullptr, nullptr, nullptr);
}
void CPDF_Form::ParseContent(const CPDF_AllStates* pGraphicStates,
const CFX_Matrix* pParentMatrix,
RecursionState* recursion_state) {
ParseContentInternal(pGraphicStates, pParentMatrix, nullptr, recursion_state);
}
void CPDF_Form::ParseContentForType3Char(CPDF_Type3Char* pType3Char) {
ParseContentInternal(nullptr, nullptr, pType3Char, nullptr);
}
void CPDF_Form::ParseContentInternal(const CPDF_AllStates* pGraphicStates,
const CFX_Matrix* pParentMatrix,
CPDF_Type3Char* pType3Char,
RecursionState* recursion_state) {
if (GetParseState() == ParseState::kParsed)
return;
if (GetParseState() == ParseState::kNotParsed) {
StartParse(std::make_unique<CPDF_ContentParser>(
GetStream(), this, pGraphicStates, pParentMatrix, pType3Char,
recursion_state ? recursion_state : &m_RecursionState));
}
DCHECK_EQ(GetParseState(), ParseState::kParsing);
ContinueParse(nullptr);
}
bool CPDF_Form::HasPageObjects() const {
return GetPageObjectCount() != 0;
}
CFX_FloatRect CPDF_Form::CalcBoundingBox() const {
if (GetPageObjectCount() == 0)
return CFX_FloatRect();
float left = 1000000.0f;
float right = -1000000.0f;
float bottom = 1000000.0f;
float top = -1000000.0f;
for (const auto& pObj : *this) {
const auto& rect = pObj->GetRect();
left = std::min(left, rect.left);
right = std::max(right, rect.right);
bottom = std::min(bottom, rect.bottom);
top = std::max(top, rect.top);
}
return CFX_FloatRect(left, bottom, right, top);
}
RetainPtr<const CPDF_Stream> CPDF_Form::GetStream() const {
return m_pFormStream;
}
std::optional<std::pair<RetainPtr<CFX_DIBitmap>, CFX_Matrix>>
CPDF_Form::GetBitmapAndMatrixFromSoleImageOfForm() const {
if (GetPageObjectCount() != 1)
return std::nullopt;
CPDF_ImageObject* pImageObject = (*begin())->AsImage();
if (!pImageObject)
return std::nullopt;
return {{pImageObject->GetIndependentBitmap(), pImageObject->matrix()}};
}