#include <locale.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <functional>
#include <iterator>
#include <map>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <vector>
#if defined(PDF_ENABLE_SKIA) && !defined(PDF_USE_SKIA)
#define PDF_USE_SKIA
#endif
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/span.h"
#include "public/cpp/fpdf_scopers.h"
#include "public/fpdf_annot.h"
#include "public/fpdf_attachment.h"
#include "public/fpdf_dataavail.h"
#include "public/fpdf_edit.h"
#include "public/fpdf_ext.h"
#include "public/fpdf_formfill.h"
#include "public/fpdf_progressive.h"
#include "public/fpdf_structtree.h"
#include "public/fpdf_text.h"
#include "public/fpdfview.h"
#include "testing/command_line_helpers.h"
#include "testing/font_renamer.h"
#include "testing/fx_string_testhelpers.h"
#include "testing/helpers/dump.h"
#include "testing/helpers/event.h"
#include "testing/helpers/page_renderer.h"
#include "testing/helpers/write.h"
#include "testing/test_loader.h"
#include "testing/utils/file_util.h"
#include "testing/utils/hash.h"
#include "testing/utils/path_service.h"
#ifdef _WIN32
#include <crtdbg.h>
#include <errhandlingapi.h>
#include <io.h>
#include <wingdi.h>
#include "testing/helpers/win32/com_factory.h"
#else
#include <unistd.h>
#endif
#ifdef ENABLE_CALLGRIND
#include <valgrind/callgrind.h>
#endif
#if defined(PDF_USE_PARTITION_ALLOC)
#include "testing/allocator_shim_config.h"
#endif
#ifdef PDF_ENABLE_SKIA
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkDocument.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkPixmap.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkSurface.h"
#ifdef _WIN32
#include "third_party/skia/include/docs/SkXPSDocument.h"
#endif
#ifdef BUILD_WITH_CHROMIUM
#include "testing/chromium_support/discardable_memory_allocator.h"
#endif
#endif
#ifdef PDF_ENABLE_V8
#include "testing/v8_initializer.h"
#include "v8/include/libplatform/libplatform.h"
#include "v8/include/v8-array-buffer.h"
#include "v8/include/v8-isolate.h"
#include "v8/include/v8-platform.h"
#include "v8/include/v8-snapshot.h"
#endif
#ifdef _WIN32
#define access …
#define snprintf …
#define R_OK …
#endif
#if defined(__APPLE__) || (defined(__linux__) && !defined(__ANDROID__))
#define WORDEXP_AVAILABLE
#endif
#ifdef WORDEXP_AVAILABLE
#include <wordexp.h>
#endif
namespace {
enum class RendererType { … };
enum class OutputFormat { … };
struct Options { … };
int PageRenderFlagsFromOptions(const Options& options) { … }
std::optional<std::string> ExpandDirectoryPath(const std::string& path) { … }
std::optional<const char*> GetCustomFontPath(const Options& options) { … }
struct FPDF_FORMFILLINFO_PDFiumTest final : public FPDF_FORMFILLINFO { … };
FPDF_FORMFILLINFO_PDFiumTest* ToPDFiumTestFormFillInfo(
FPDF_FORMFILLINFO* form_fill_info) { … }
void OutputMD5Hash(const char* file_name, pdfium::span<const uint8_t> output) { … }
#ifdef PDF_ENABLE_V8
struct V8IsolateDeleter { … };
int ExampleAppAlert(IPDF_JSPLATFORM*,
FPDF_WIDESTRING msg,
FPDF_WIDESTRING title,
int type,
int icon) { … }
void ExampleAppBeep(IPDF_JSPLATFORM*, int type) { … }
int ExampleAppResponse(IPDF_JSPLATFORM*,
FPDF_WIDESTRING question,
FPDF_WIDESTRING title,
FPDF_WIDESTRING default_value,
FPDF_WIDESTRING label,
FPDF_BOOL is_password,
void* response,
int length) { … }
int ExampleDocGetFilePath(IPDF_JSPLATFORM*, void* file_path, int length) { … }
void ExampleDocMail(IPDF_JSPLATFORM*,
void* mailData,
int length,
FPDF_BOOL UI,
FPDF_WIDESTRING To,
FPDF_WIDESTRING Subject,
FPDF_WIDESTRING CC,
FPDF_WIDESTRING BCC,
FPDF_WIDESTRING Msg) { … }
void ExampleDocPrint(IPDF_JSPLATFORM*,
FPDF_BOOL bUI,
int nStart,
int nEnd,
FPDF_BOOL bSilent,
FPDF_BOOL bShrinkToFit,
FPDF_BOOL bPrintAsImage,
FPDF_BOOL bReverse,
FPDF_BOOL bAnnotations) { … }
void ExampleDocSubmitForm(IPDF_JSPLATFORM*,
void* formData,
int length,
FPDF_WIDESTRING url) { … }
void ExampleDocGotoPage(IPDF_JSPLATFORM*, int page_number) { … }
int ExampleFieldBrowse(IPDF_JSPLATFORM*, void* file_path, int length) { … }
#endif
#ifdef PDF_ENABLE_XFA
FPDF_BOOL ExamplePopupMenu(FPDF_FORMFILLINFO* pInfo,
FPDF_PAGE page,
FPDF_WIDGET always_null,
int flags,
float x,
float y) { … }
#endif
void ExampleNamedAction(FPDF_FORMFILLINFO* pInfo, FPDF_BYTESTRING name) { … }
void ExampleUnsupportedHandler(UNSUPPORT_INFO*, int type) { … }
bool ParseCommandLine(const std::vector<std::string>& args,
Options* options,
std::vector<std::string>* files) { … }
void PrintLastError() { … }
FPDF_BOOL Is_Data_Avail(FX_FILEAVAIL* avail, size_t offset, size_t size) { … }
void Add_Segment(FX_DOWNLOADHINTS* hints, size_t offset, size_t size) { … }
FPDF_PAGE GetPageForIndex(FPDF_FORMFILLINFO* param,
FPDF_DOCUMENT doc,
int index) { … }
FPDF_BOOL NeedToPauseNow(IFSDK_PAUSE* p) { … }
class Processor final { … };
class PdfProcessor final { … };
class BitmapPageRenderer : public PageRenderer { … };
class OneShotBitmapPageRenderer : public BitmapPageRenderer { … };
class ProgressiveBitmapPageRenderer : public BitmapPageRenderer { … };
#ifdef _WIN32
class ScopedGdiDc final {
public:
~ScopedGdiDc() { Reset(nullptr); }
void Reset(HDC dc) {
if (dc_) {
[[maybe_unused]] BOOL success = DeleteDC(dc_);
DCHECK(success);
}
dc_ = dc;
}
HDC Get() const { return dc_; }
private:
HDC dc_ = nullptr;
};
class ScopedGdiObject final {
public:
~ScopedGdiObject() { Reset(nullptr); }
void Reset(HGDIOBJ object) {
if (object_) {
[[maybe_unused]] BOOL success = DeleteObject(object_);
DCHECK(success);
}
object_ = object;
}
HGDIOBJ Get() const { return object_; }
private:
HGDIOBJ object_ = nullptr;
};
class GdiDisplayPageRenderer : public BitmapPageRenderer {
public:
GdiDisplayPageRenderer(FPDF_PAGE page,
int width,
int height,
int flags,
const std::function<void()>& idler,
PageWriter writer)
: BitmapPageRenderer(page,
width,
height,
flags,
idler,
std::move(writer)) {}
~GdiDisplayPageRenderer() override {
ResetBitmap();
}
bool Start() override {
dc_.Reset(CreateCompatibleDC(nullptr));
if (!dc_.Get()) {
return false;
}
BITMAPINFO dib_info;
memset(&dib_info, 0, sizeof(BITMAPINFO));
dib_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
dib_info.bmiHeader.biWidth = width();
dib_info.bmiHeader.biHeight = -height();
dib_info.bmiHeader.biPlanes = 1;
dib_info.bmiHeader.biBitCount = 32;
dib_info.bmiHeader.biCompression = BI_RGB;
VOID* dib_pixels;
dib_.Reset(CreateDIBSection(dc_.Get(), &dib_info, DIB_RGB_COLORS,
&dib_pixels, nullptr,
0));
if (!dib_.Get() || !InitializeBitmap(dib_pixels)) {
return false;
}
HGDIOBJ old_obj = SelectObject(dc_.Get(), dib_.Get());
CHECK(old_obj);
CHECK_NE(old_obj, HGDI_ERROR);
FPDF_RenderPage(dc_.Get(), page(), 0, 0,
width(), height(), 0,
flags());
bool result = !!GdiFlush();
HGDIOBJ dib_obj = SelectObject(dc_.Get(), old_obj);
CHECK((GetObjectType(old_obj) != OBJ_REGION && dib_obj) ||
(GetObjectType(old_obj) == OBJ_REGION && dib_obj != HGDI_ERROR));
return result;
}
void Finish(FPDF_FORMHANDLE ) override {
const int stride = FPDFBitmap_GetStride(bitmap());
DCHECK_EQ(width() * sizeof(uint32_t), static_cast<size_t>(stride));
const int pixel_stride = stride / sizeof(uint32_t);
uint32_t* scanline =
reinterpret_cast<uint32_t*>(FPDFBitmap_GetBuffer(bitmap()));
for (int row = 0; row < height(); ++row) {
for (int column = 0; column < width(); ++column) {
scanline[column] |= 0xFF000000;
}
scanline += pixel_stride;
}
}
private:
ScopedGdiDc dc_;
ScopedGdiObject dib_;
};
#endif
#ifdef PDF_ENABLE_SKIA
class SkCanvasPageRenderer : public PageRenderer { … };
class SkPicturePageRenderer final : public SkCanvasPageRenderer { … };
class SkDocumentPageRenderer final : public SkCanvasPageRenderer { … };
#endif
bool PdfProcessor::ProcessPage(const int page_index) { … }
void Processor::ProcessPdf(const std::string& name,
pdfium::span<const uint8_t> data,
const std::string& events) { … }
void ShowConfig() { … }
constexpr char kUsageString[] = …;
void SetUpErrorHandling() { … }
}
int main(int argc, const char* argv[]) { … }