各種の開発言語(C/C++、.Net、Java、Pythonなど)を使用して新たにPDFファイルを作成できます。
PDFファイルを作成した後、Toolbox Add-onを使用してコンテンツの追加、フォーム フィールドの追加、メタデータの管理などができます。
Toolbox Add-onのAPIリファレンスはこちらです。(すべて英文)
C#のサンプルプロジェクトではPdftools SDK(Toolbox Add-on)ライブラリ(DLL)をNuGetから自動でダウンロードします。
CのサンプルプロジェクトにはPdftools SDK(Toolbox Add-on)ライブラリ(DLL)が含まれています。
License Agreement(利用許諾契約書)が含まれていますので必ず確認してください。
全1ページの新しいPDFドキュメントを作成し、このページの指定された矩形領域内に両端揃えレイアウトのテキストブロックを追加します。
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.CreateNew, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, null, null))
{
Font font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
// Create page
Page outPage = Page.Create(outDoc, PageSize);
// Add text as justified text
LayoutText(outDoc, outPage, textPath, font, 20);
// Add page to document
outDoc.Pages.Add(outPage);
}
private static void LayoutText(Document outputDoc, Page outPage, string textPath, Font font,
double fontSize)
{
// Create content generator
using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
// Create text object
Text text = Text.Create(outputDoc);
// Create text generator
using TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null);
// Calculate position
Point position = new Point
{
X = Border,
Y = outPage.Size.Height - Border
};
// Move to position
textGenerator.MoveTo(position);
// Loop through all lines of the textinput
string[] lines = File.ReadAllLines(textPath, Encoding.Default);
foreach (string line in lines)
{
// Split string in substrings
string[] substrings = line.Split(new char[] { ' ' }, StringSplitOptions.None);
string currentLine = null;
double maxWidth = outPage.Size.Width - Border * 2;
int wordcount = 0;
// Loop through all words of input strings
foreach (string word in substrings)
{
string tempLine;
// Concatenate substrings to line
if (currentLine != null)
tempLine = currentLine + " " + word;
else
tempLine = word;
// Calculate the current width of line
double width = textGenerator.GetWidth(currentLine);
if (textGenerator.GetWidth(tempLine) > maxWidth)
{
// Calculate the word spacing
textGenerator.WordSpacing = (maxWidth - width) / (wordcount - 1);
// Paint on new line
textGenerator.ShowLine(currentLine);
textGenerator.WordSpacing = 0;
currentLine = word;
wordcount = 1;
}
else
{
currentLine = tempLine;
wordcount++;
}
}
textGenerator.WordSpacing = 0;
// Add given stamp string
textGenerator.ShowLine(currentLine);
}
// Paint the positioned text
gen.PaintText(text);
}
def layout_text(output_doc: Document, out_page: Page, text_path: str, font: Font, font_size: float):
"""
Layout and justify text on the PDF page.
"""
# Create content generator
with ContentGenerator(out_page.content, False) as generator:
# Create text object
text = Text.create(output_doc)
# Create text generator
with TextGenerator(text, font, font_size, None) as text_generator:
# Calculate starting position
position = Point(x=BORDER, y=out_page.size.height - BORDER)
# Move to position
text_generator.move_to(position)
with open(text_path, "r", encoding="utf-8") as file:
lines = file.readlines()
# Loop through all lines of the textinput
for line in lines:
# Split string in substrings
substrings = line.split(" ")
current_line = ""
max_width = out_page.size.width - BORDER * 2
word_count = 0
# Loop through all words of input strings
for word in substrings:
# Concatenate substrings to line
temp_line = f"{current_line} {word}".strip()
# Calculate the current width of line
current_width = text_generator.get_width(current_line)
if text_generator.get_width(temp_line) > max_width:
# Calculate the word spacing
text_generator.word_spacing = (max_width - current_width) / (word_count - 1) if word_count > 1 else 0
text_generator.show_line(current_line)
text_generator.word_spacing = 0
current_line = word
word_count = 1
else:
current_line = temp_line
word_count += 1
text_generator.word_spacing = 0
# Add given stamp string
text_generator.show_line(current_line)
# Paint the positioned text
generator.paint_text(text)
# Define global variables
BORDER = 50
PAGE_SIZE = Size(width=595, height=842) # A4 page size in points
# Create output document
with io.FileIO(output_file_path, "wb+") as out_stream:
with Document.create(out_stream, None, None) as out_doc:
font = Font.create_from_system(out_doc, "Arial", "Italic", True)
# Create page
out_page = Page.create(out_doc, PAGE_SIZE)
# Add text as justified text
layout_text(out_doc, out_page, input_text_path, font, font_size=20)
# Add page to document
out_doc.pages.append(out_page)
A3サイズのページに最大で2枚のA4ページを正しい順序で配置したPDFを作成します。
このPDFをA3ページの両面印刷して、折りたたむと小冊子になります。
int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
{
// Objects that need releasing or closing
TPtxPdfContent_IccBasedColorSpace* pInOutputIntent = NULL;
TPtxPdfContent_IccBasedColorSpace* pOutOutputIntent = NULL;
TPtxPdf_Metadata* pInMetadata = NULL;
TPtxPdf_Metadata* pOutMetadata = NULL;
TPtxPdfNav_ViewerSettings* pInViewerSettings = NULL;
TPtxPdfNav_ViewerSettings* pOutViewerSettings = NULL;
TPtxPdf_FileReferenceList* pInFileRefList = NULL;
TPtxPdf_FileReferenceList* pOutFileRefList = NULL;
TPtxPdf_FileReference* pInFileRef = NULL;
TPtxPdf_FileReference* pOutFileRef = NULL;
iReturnValue = 0;
// Output intent
pInOutputIntent = PtxPdf_Document_GetOutputIntent(pInDoc);
if (pInOutputIntent != NULL)
{
pOutOutputIntent = PtxPdfContent_IccBasedColorSpace_Copy(pOutDoc, pInOutputIntent);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutOutputIntent,
_T("Failed to copy ICC-based color space. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetOutputIntent(pOutDoc, pOutOutputIntent),
_T("Failed to set output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Metadata
pInMetadata = PtxPdf_Document_GetMetadata(pInDoc);
if (pInMetadata != NULL)
{
pOutMetadata = PtxPdf_Metadata_Copy(pOutDoc, pInMetadata);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pOutMetadata),
_T("Failed to set metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Viewer settings
pInViewerSettings = PtxPdf_Document_GetViewerSettings(pInDoc);
if (pInViewerSettings != NULL)
{
pOutViewerSettings = PtxPdfNav_ViewerSettings_Copy(pOutDoc, pInViewerSettings);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutViewerSettings,
_T("Failed to copy viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetViewerSettings(pOutDoc, pOutViewerSettings),
_T("Failed to set viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
}
else
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get viewer settings. %s (ErrorCode: 0x%08x)"), szErrorBuff,
Ptx_GetLastError());
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of input document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of output document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
int nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of associated files. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
{
pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
_T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInFileRef);
pInFileRef = NULL;
Ptx_Release(pOutFileRef);
pOutFileRef = NULL;
}
Ptx_Release(pInFileRefList);
pInFileRefList = NULL;
Ptx_Release(pOutFileRefList);
pOutFileRefList = NULL;
// Plain embedded files
pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pInFileRefList, _T("Failed to get plain embedded files of input document %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
pInFileRefList, _T("Failed to get plain embedded files of output document %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of plain embedded files. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
{
pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
_T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
Ptx_Release(pInFileRef);
pInFileRef = NULL;
Ptx_Release(pOutFileRef);
pOutFileRef = NULL;
}
cleanup:
if (pInOutputIntent != NULL)
Ptx_Release(pInOutputIntent);
if (pOutOutputIntent != NULL)
Ptx_Release(pOutOutputIntent);
if (pInMetadata != NULL)
Ptx_Release(pInMetadata);
if (pOutMetadata != NULL)
Ptx_Release(pOutMetadata);
if (pInViewerSettings != NULL)
Ptx_Release(pInViewerSettings);
if (pOutViewerSettings != NULL)
Ptx_Release(pOutViewerSettings);
if (pInFileRefList != NULL)
Ptx_Release(pInFileRefList);
if (pOutFileRefList != NULL)
Ptx_Release(pOutFileRefList);
if (pInFileRef != NULL)
Ptx_Release(pInFileRef);
if (pOutFileRef != NULL)
Ptx_Release(pOutFileRef);
return iReturnValue;
}
int StampPageNumber(TPtxPdf_Document* pDocument, TPtxPdfContent_Font* pFont,
TPtxPdfContent_ContentGenerator* pGenerator, int nPageNo, BOOL bIsLeftPage)
{
// Objects that need releasing or closing
TPtxPdfContent_Text* pText = NULL;
TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
// Create text object
pText = PtxPdfContent_Text_Create(pDocument);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create text object. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Create text generator
pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, 8.0, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create text generator. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
TCHAR szStampText[50];
_stprintf(szStampText, _T("Page %d"), nPageNo);
// Get width of stamp text
double dStampWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampText);
if (dStampWidth == 0.0)
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get text width. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Compute position
TPtxGeomReal_Point point = {
.dX = bIsLeftPage ? dBorder + 0.5 * dCellWidth - dStampWidth / 2
: 2 * dBorder + 1.5 * dCellWidth - dStampWidth / 2,
.dY = dBorder,
};
// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &point),
_T("Failed to move to position. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Add page number
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_Show(pTextGenerator, szStampText),
_T("Failed to show text. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
BOOL bClose = PtxPdfContent_TextGenerator_Close(pTextGenerator);
pTextGenerator = NULL;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(bClose, _T("Failed to close text generator. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
_T("Failed to paint text. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
cleanup:
if (pText != NULL)
Ptx_Release(pText);
if (pTextGenerator != NULL)
PtxPdfContent_TextGenerator_Close(pTextGenerator);
return iReturnValue;
}
void ComputeTargetRect(TPtxGeomReal_Rectangle* pRectangle, const TPtxGeomReal_Size* pBBox, BOOL bIsLeftPage)
{
// Compute factor for fitting page into rectangle
double dScale = MIN(dCellWidth / pBBox->dWidth, dCellHeight / pBBox->dHeight);
double dGroupWidth = pBBox->dWidth * dScale;
double dGroupHeight = pBBox->dHeight * dScale;
// Compute x-value
double dGroupXPos =
bIsLeftPage ? dCellLeft + (dCellWidth - dGroupWidth) / 2 : dCellRight + (dCellWidth - dGroupWidth) / 2;
// Compute y-value
double dGroupYPos = dCellYPos + (dCellHeight - dGroupHeight) / 2;
// Set rectangle
pRectangle->dLeft = dGroupXPos;
pRectangle->dBottom = dGroupYPos;
pRectangle->dRight = dGroupXPos + dGroupWidth;
pRectangle->dTop = dGroupYPos + dGroupHeight;
}
int CreateBooklet(TPtxPdf_PageList* pInDocList, TPtxPdf_Document* pOutDoc, TPtxPdf_PageList* pOutDocList,
int nLeftPageIndex, int nRightPageIndex, TPtxPdfContent_Font* pFont)
{
// Objects that need releasing or closing
TPtxPdf_PageCopyOptions* pCopyOptions = NULL;
TPtxPdf_Page* pOutPage = NULL;
TPtxPdfContent_Content* pContent = NULL;
TPtxPdfContent_ContentGenerator* pGenerator = NULL;
TPtxPdf_Page* pInPage = NULL;
TPtxPdfContent_Group* pGroup = NULL;
// Configure copy options
pCopyOptions = PtxPdf_PageCopyOptions_New();
// Create page object
pOutPage = PtxPdf_Page_Create(pOutDoc, &pageSize);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to create page object. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// Create content generator
pContent = PtxPdf_Page_GetContent(pOutPage);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create content generator. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
int nPageCount = PtxPdf_PageList_GetCount(pInDocList);
GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get page list count. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Left page
if (nLeftPageIndex lt; nPageCount)
{
// Get the input page
pInPage = PtxPdf_PageList_Get(pInDocList, nLeftPageIndex);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Copy page from input to output
pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// Compute group location
TPtxGeomReal_Size groupSize;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Group_GetSize(pGroup, &groupSize),
_T("Failed to get group size. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
TPtxGeomReal_Rectangle targetRect;
ComputeTargetRect(&targetRect, &groupSize, TRUE);
// Paint group at location
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, &targetRect, NULL),
_T("Failed to paint group. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());
// Add page number to page
if (StampPageNumber(pOutDoc, pFont, pGenerator, nLeftPageIndex + 1, TRUE) != 0)
goto cleanup;
Ptx_Release(pInPage);
pInPage = NULL;
Ptx_Release(pGroup);
pGroup = NULL;
}
// Right page
if (nRightPageIndex lt; nPageCount)
{
// Get the input Page
pInPage = PtxPdf_PageList_Get(pInDocList, nRightPageIndex);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
// Copy page from input to output
pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// Compute group location
TPtxGeomReal_Size groupSize;
PtxPdfContent_Group_GetSize(pGroup, &groupSize);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Group_GetSize(pGroup, &groupSize),
_T("Failed to get group size. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
Ptx_GetLastError());
TPtxGeomReal_Rectangle targetRect;
ComputeTargetRect(&targetRect, &groupSize, FALSE);
// Paint group on the Computed rectangle
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, &targetRect, NULL),
_T("Failed to paint group. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());
// Add page number to page
if (StampPageNumber(pOutDoc, pFont, pGenerator, nRightPageIndex + 1, FALSE) != 0)
goto cleanup;
}
BOOL bClose = PtxPdfContent_ContentGenerator_Close(pGenerator);
pGenerator = NULL;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(bClose, _T("Failed to close content generator. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutDocList, pOutPage),
_T("Failed to add page to output document. %s (ErrorCode: 0x%08x)\n"),
szErrorBuff, Ptx_GetLastError());
cleanup:
if (pGenerator != NULL)
PtxPdfContent_ContentGenerator_Close(pGenerator);
if (pCopyOptions != NULL)
Ptx_Release(pCopyOptions);
if (pOutPage != NULL)
Ptx_Release(pOutPage);
if (pContent != NULL)
Ptx_Release(pContent);
if (pInPage != NULL)
Ptx_Release(pInPage);
if (pGroup != NULL)
Ptx_Release(pGroup);
return iReturnValue;
}
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Create a font
Font font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
// Copy pages
PageList inPages = inDoc.Pages;
PageList outPages = outDoc.Pages;
int numberOfSheets = (inPages.Count + 3) / 4;
for (int sheetNumber = 0; sheetNumber lt; numberOfSheets; ++sheetNumber)
{
// Add on front side
CreateBooklet(inPages, outDoc, outPages, 4 * numberOfSheets - 2 * sheetNumber - 1,
2 * sheetNumber, font);
// Add on back side
CreateBooklet(inPages, outDoc, outPages, 2 * sheetNumber + 1,
4 * numberOfSheets - 2 * sheetNumber - 2, font);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
// Metadata
outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
// Plain embedded files
FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
}
private static void CreateBooklet(PageList inPages, Document outDoc, PageList outPages, int leftPageIndex,
int rightPageIndex, Font font)
{
// Define page copy options
PageCopyOptions copyOptions = new PageCopyOptions();
// Create page object
Page outpage = Page.Create(outDoc, PageSize);
// Create content generator
using (ContentGenerator generator = new ContentGenerator(outpage.Content, false))
{
// Left page
if (leftPageIndex lt; inPages.Count)
{
// Copy page from input to output
Page leftPage = inPages[leftPageIndex];
Group leftGroup = Group.CopyFromPage(outDoc, leftPage, copyOptions);
// Paint group on the calculated rectangle
generator.PaintGroup(leftGroup, ComputTargetRect(leftGroup.Size, true), null);
// Add page number to page
StampPageNumber(outDoc, font, generator, leftPageIndex + 1, true);
}
// Right page
if (rightPageIndex lt; inPages.Count)
{
// Copy page from input to output
Page rigthPage = inPages[rightPageIndex];
Group rightGroup = Group.CopyFromPage(outDoc, rigthPage, copyOptions);
// Paint group on the calculated rectangle
generator.PaintGroup(rightGroup, ComputTargetRect(rightGroup.Size, false), null);
// Add page number to page
StampPageNumber(outDoc, font, generator, rightPageIndex + 1, false);
}
}
// Add page to output document
outPages.Add(outpage);
}
private static Rectangle ComputTargetRect(Size bbox, bool isLeftPage)
{
// Calculate factor for fitting page into rectangle
double scale = Math.Min(CellWidth / bbox.Width, CellHeight / bbox.Height);
double groupWidth = bbox.Width * scale;
double groupHeight = bbox.Height * scale;
// Calculate x-value
double groupXPos = isLeftPage ? CellLeft + (CellWidth - groupWidth) / 2 :
CellRight + (CellWidth - groupWidth) / 2;
// Calculate y-value
double groupYPos = CellYPos + (CellHeight - groupHeight) / 2;
// Calculate rectangle
return new Rectangle
{
Left = groupXPos,
Bottom = groupYPos,
Right = groupXPos + groupWidth,
Top = groupYPos + groupHeight
};
}
private static void StampPageNumber(Document document, Font font, ContentGenerator generator,
int PageNo, bool isLeftPage)
{
// Create text object
Text text = Text.Create(document);
// Create text generator
using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
{
string stampText = string.Format("Page {0}", PageNo);
// Get width of stamp text
double width = textgenerator.GetWidth(stampText);
// Calculate position
double x = isLeftPage ? Border + 0.5 * CellWidth - width / 2 :
2 * Border + 1.5 * CellWidth - width / 2;
double y = Border;
// Move to position
textgenerator.MoveTo(new Point { X = x, Y = y});
// Add page number
textgenerator.Show(stampText);
}
// Paint the positioned text
generator.PaintText(text);
}
def copy_document_data(in_doc: Document, out_doc: Document):
# Copy document-wide data
# Output intent
if in_doc.output_intent is not None:
in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
# Metadata
out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
# Viewer settings
out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
# Associated files (for PDF/A-3 and PDF 2.0 only)
outAssociatedFiles = out_doc.associated_files
for in_file_ref in in_doc.associated_files:
outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
# Plain embedded files
out_embedded_files = out_doc.plain_embedded_files
for in_file_ref in in_doc.plain_embedded_files:
out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
def compute_target_rect(bbox: Size, is_left_page: bool) -> Rectangle:
# Calculate factor for fitting page into rectangle
scale = min(cell_width / bbox.width, cell_height / bbox.height)
group_width = bbox.width * scale
group_height = bbox.height * scale
# Calculate x-value
group_x_pos = cell_left + (cell_width - group_width) / 2 if is_left_page else cell_right + (cell_width - group_width) / 2
# Calculate y-value
group_y_pos = cell_y_pos + (cell_height - group_height) / 2
# Calculate rectangle
return Rectangle(
left=group_x_pos,
bottom=group_y_pos,
right=group_x_pos + group_width,
top=group_y_pos + group_height,
)
def stamp_page_number(document: Document, font: Font, generator: ContentGenerator, page_no: int, is_left_page: bool):
# Create text object
text = Text.create(document)
# Create text generator
with TextGenerator(text, font, 8.0, None) as text_generator:
stamp_text = f"Page {page_no}"
# Get width of stamp text
width = text_generator.get_width(stamp_text)
# Calculate position
x = border + 0.5 * cell_width - width / 2 if is_left_page else 2 * border + 1.5 * cell_width - width / 2
y = border
# Move to position
text_generator.move_to(Point(x=x, y=y))
# Add page number
text_generator.show(stamp_text)
# Paint the positioned text
generator.paint_text(text)
def create_booklet(in_pages: PageList, out_doc: Document, out_pages: PageList, left_page_index: int, right_page_index: int, font: Font):
# Define page copy options
copy_options = PageCopyOptions()
# Create page object
out_page = Page.create(out_doc, page_size)
# Create content generator
with ContentGenerator(out_page.content, False) as generator:
# Left page
if left_page_index lt; len(in_pages):
# Copy page from input to output
left_page = in_pages[left_page_index]
left_group = Group.copy_from_page(out_doc, left_page, copy_options)
# Paint group into target rectangle
generator.paint_group(left_group, compute_target_rect(left_group.size, True), None)
# Add page number to page
stamp_page_number(out_doc, font, generator, left_page_index + 1, True)
# Right page
if right_page_index lt; len(in_pages):
# Copy page from input to output
right_page = in_pages[right_page_index]
right_group = Group.copy_from_page(out_doc, right_page, copy_options)
# Paint group on the calculated rectangle
generator.paint_group(right_group, compute_target_rect(right_group.size, False), None)
# Add page number to page
stamp_page_number(out_doc, font, generator, right_page_index + 1, False)
# Add page to output document
out_pages.append(out_page)
# Define global variables
page_size = Size(1190.0, 842.0) # A3 portrait
border = 10.0
cell_width = (page_size.width - 3 * border) / 2
cell_height = page_size.height - 2 * border
cell_left = border
cell_right = 2 * border + cell_width
cell_y_pos = border
# Open input document
with io.FileIO(input_file_path, "rb") as in_stream:
with Document.open(in_stream, None) as in_doc:
# Create output document
with io.FileIO(output_file_path, "wb+") as output_stream:
with Document.create(output_stream, in_doc.conformance, None) as out_doc:
# Copy document-wide data
copy_document_data(in_doc, out_doc)
# Create a font
font = Font.create_from_system(out_doc, "Arial", "Italic", True)
# Copy pages
in_pages = in_doc.pages
out_pages = out_doc.pages
number_of_sheets = (len(in_pages) + 3) // 4
for sheet_number in range(number_of_sheets):
# Add front side
create_booklet(in_pages, out_doc, out_pages, 4 * number_of_sheets - 2 * sheet_number - 1, 2 * sheet_number, font)
# Add back side
create_booklet(in_pages, out_doc, out_pages, 2 * sheet_number + 1, 4 * number_of_sheets - 2 * sheet_number - 2, font)
他の機能サンプルを参照してください。
質問のページからお送りいただくようお願いします。
または、メールでsupport@trustss.co.jpあてにお送りください。
ご購入前の技術的質問も無償で対応します。サポート受付ページからお願いします。