< Windows samples

PDFDCTest - C++

This sample shows how to create and use PDFDC (i.e. a PDF Device Context). Windows developers can use standard GDI or GDI+ API-s to write on PDFDC and to generate PDF documents based on their existing drawing functions. PDFDC can also be used to implement file conversion from any printable file format to PDF.

//---------------------------------------------------------------------------------------
// Copyright (c) 2001-2018 by PDFTron Systems Inc. All Rights Reserved.
// Consult legal.txt regarding legal and license information.
//---------------------------------------------------------------------------------------

#include <iostream>
#include <sstream>
#include <PDF/PDFNet.h>
#include <PDF/PDFDC.h>
#include <PDF/PDFDCEX.h>

//-----------------------------------------------------------------------------------
// This sample shows how to create and use PDFDC (i.e. a PDF Device Context).
// Windows developers can use standard GDI or GDI+ API-s to write on PDFDC 
// and to generate PDF documents based on their existing drawing functions.
// PDFDC can also be used to implement file conversion from any printable 
// file format to PDF (i.e. a virtual PDF printer driver).
//
// The second part of this sample demonstrates the PDFDCEX which allows 
// printer-like multipage translations with GDI resources used across pages.
// While PDFDC is good for adding GDI drawings to an existing PDF Page, PDFDCEX 
// allows you to create page after page of GDI to PDF conversion using existing 
// printing functions.
//-----------------------------------------------------------------------------------

using namespace pdftron;
using namespace PDF;

// Relative path to the folder containing test files.
std::string inputPath =  "../../TestFiles/";
std::string outputPath = "../../TestFiles/Output/";

// Define a font
static const LOGFONTW ArialFont =
{ 
	12,							// height (points)
	0,							// width (use default)
	0,							// rotation of baseline for text strings
	0,							// rotation of each character
	FW_NORMAL,					// weight
	FALSE,						// italic
	FALSE,						// underline
	FALSE,						// strike out
	ANSI_CHARSET,				// character set
	OUT_DEFAULT_PRECIS,			// output precision
	CLIP_DEFAULT_PRECIS,		// clip precision
	DEFAULT_QUALITY,			// quality
	VARIABLE_PITCH | FF_SWISS,	// pitch and family
	L"Arial"					// font name
};


int main()
{
	int ret = 0;
#if defined(_WIN32)  && !defined(WINCE)

	PDFNet::Initialize();

	try  
	{	
		// Start with a PDFDoc to put the picture into, and a PDFDC to translate GDI to PDF
		PDFDoc pdfdoc;
		PDFDC pdfDc;

		// Set the dpi between GDI logical units and the PDF page at 50/inch.
		pdfDc.SetDPI(50);

		// Create a page to put the GDI content onto
		Page page = pdfdoc.PageCreate();

		//////////////////////////////////////////////////////////////////////////
		// Begin the translation from GDI to PDF.
		// Provide the PDF page to place the picture onto, and the bounding box for the content.
		// We're going to dpi the GDI content to fill the page while preserving the aspect
		// ratio.
		// Get back a GDI Device Context
		HDC hDC = pdfDc.Begin( page, page.GetCropBox() );

		// Create GDI resources and draw GDI content
		HFONT hArialFont = CreateFontIndirectW(  &ArialFont );
		HGDIOBJ hOldFont = SelectObject(hDC, hArialFont );

		Ellipse(hDC, -30, -30, 30, 30);
		SetTextAlign(hDC, TA_CENTER | TA_BOTTOM);
		TextOutW(hDC, 0, ArialFont.lfHeight / 2, L"Hello World", 11);
		SelectObject(hDC, hOldFont);
		DeleteObject(hArialFont);

		// Complete the translation
		pdfDc.End();

		// Add the page to the document
		pdfdoc.PagePushBack(page);


		//////////////////////////////////////////////////////////////////////////
		// Page two
		page = pdfdoc.PageCreate();
		hDC = pdfDc.Begin( page, page.GetCropBox(), true );

		// Create GDI resources and draw GDI content
		hArialFont = CreateFontIndirectW(  &ArialFont );
		hOldFont = SelectObject(hDC, hArialFont );

		Ellipse(hDC, -20, -20, 20, 20);
		SetTextAlign(hDC, TA_CENTER | TA_BOTTOM);
		TextOutW(hDC, 0, ArialFont.lfHeight / 2, L"Page 2", 6);
		SelectObject(hDC, hOldFont);
		DeleteObject(hArialFont);

		// Complete the translation
		pdfDc.End();

		// Add the page to the document
		pdfdoc.PagePushBack(page);

		// Save the PDF document
		pdfdoc.Save(outputPath + "PDFDCTest.pdf", SDF::SDFDoc::e_remove_unused, NULL);
		std::cout << "Saved PDFDCTest.pdf\n";

		////////////////////////////////////////////////////////////////////////////////
		// PDFDCEX example: 
		// Add two pages to a new PDFDoc.
		// Fonts and resources are shared across pages.  No need to work with each PDFPage.
		// We work in page coordinates which are page dimensions (inches) times
		// DPI. Origin is at upper left corner of the page, positive down and to right.

		// Start with a PDFDoc to put the translation into, and a PDFDCEX to translate GDI to PDF
		PDFDoc pdfdoc2;
		PDFDCEX pdfDcEx;
		HDC hDC2;
		HFONT hArialFont2;
		HGDIOBJ hOldFont2;
		HGDIOBJ hPen2, hOldPen2;

		// Begin the translation from GDI to PDF -- provide the PDFDoc to append to.
		// Get back a GDI Device Context, we've added "::" the start of all of the
		// GDI calls to emphasize that we only use the PDFDCEX at the beginning and end.
		PDF::Point paperDimensions(8.5, 11);
		hDC2 = pdfDcEx.Begin( pdfdoc2, paperDimensions );

		UInt32 dpi = pdfDcEx.GetDPI(); 
		PDF::Point paperSize( paperDimensions.x * dpi, paperDimensions.y * dpi);

		::StartPage(hDC2);

		// We like to think of font height in "points" -- convert this to page pixels
		LOGFONTW tmpFont = ArialFont;
		tmpFont.lfHeight *= dpi / 72;
		hArialFont2 = ::CreateFontIndirectW(  &tmpFont );
		hOldFont2 = ::SelectObject(hDC2, hArialFont2 );

		hPen2 = ::CreatePen(PS_SOLID, 1, RGB(0,0,0));
		hOldPen2 = ::SelectObject(hDC2, hPen2);
		::SetBkMode(hDC2, TRANSPARENT);
		::Ellipse(hDC2, (int)(paperSize.x/2 - dpi), (int)(paperSize.y/2 - dpi), (int)(paperSize.x/2 + dpi), (int)(paperSize.y/2 + dpi));
		::SetTextAlign(hDC2, TA_CENTER | TA_BOTTOM);
		::TextOutW(hDC2, (int)(paperSize.x/2), (int)(paperSize.y/2 + tmpFont.lfHeight / 2), L"Hello World", 11);
		::SelectObject(hDC2, hOldPen2);
		::DeleteObject(hPen2);
		::EndPage(hDC2);

		////////////////////////////////////////////////////////////////////////////
		// Page two
		// Reuse existing font and DC.
		::StartPage(hDC2);
		::Ellipse(hDC2, -20, -20, 20, 20);
		::SetTextAlign(hDC2, TA_CENTER | TA_BOTTOM);
		::TextOutW(hDC2, (int)(paperSize.x/2), (int)(paperSize.y/2 + ArialFont.lfHeight / 2), L"Page 2", 6);
		::SelectObject(hDC2, hOldFont2);
		::DeleteObject(hArialFont2);
		::EndPage(hDC2);

		// Complete the translation
		pdfDcEx.End();

		// Save the PDF document
		pdfdoc2.Save(outputPath + "PDFDCEXTest.pdf", SDF::SDFDoc::e_remove_unused, NULL);
		std::cout << "Saved PDFDCEXTest.pdf\nDone.\n";
	}
	catch(Common::Exceptionn& e)
	{
		std::cout << e << std::endl;
		ret = 1;
	}
	catch(...)
	{
		std::cout << "Unknown Exception" << std::endl;
		ret = 1;
	}

	PDFNet::Terminate();
#endif // defined(_WIN32)  && !defined(WINCE)
	return ret;
}