Files
Hoops_Exchange/publish/publishsource/ExportPDFToHtml/ExportPDFToHtml.cpp
2025-12-15 23:22:33 +08:00

281 lines
10 KiB
C++

/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
/*
* This sample demonstrates how to export an interactive 3D PDF to HTML or SCS format. The chosen
* . The package provides a sample HTTP server for that usage. See \samples\publish\publishhtml\htmlforserver\.
*/
#define INITIALIZE_A3D_API
#define HOOPS_PRODUCT_PUBLISH_ADVANCED
#include <A3DSDKIncludes.h>
#include <hoops_license.h>
#include "../common.hpp"
#include <string>
#include <algorithm>
#include <cctype>
#include <iostream>
// Typical commandline parameters which can be used with VisualCpp IDE :
// "..\..\..\..\samples\publish\publishgallery\Coding_Samples\sample_DemoDataModel.pdf" "html" "online" "..\..\..\..\samples\publish\publishhtml\htmlforserver\exportpdftohtml\root\PdfContent" "LayerDataModelDemo.xml"
// Following are default parameters used when the exe is called with no arguments:
// Console exe is supposed to be launched from exe directory
#ifdef _MSC_VER
# define IN_FILE _T(SAMPLES_PUBLISH_GALLERY_DIRECTORY"\\Coding_Samples\\sample_DemoDataModel.pdf")
# define IN_FILE_HTMLTEMPLATE _T(SAMPLES_DATA_HTML_DIRECTORY"\\exportpdftohtml_template.html")
# define IN_VIEWER_TEMPLATE _T(SAMPLES_PUBLISH_HTML_DIRECTORY"\\htmlforserver\\exportpdftohtml\\root\\viewer.html")
# define EXPORT_FORMAT _T("html") // values are "html" or "scs"
# define EXPORT_TYPE _T("online")
# define OUT_ROOT_DIR _T(SAMPLES_PUBLISH_HTML_DIRECTORY"\\htmlforserver\\exportpdftohtml\\root\\PdfContent")
# define OUT_NAME _T("sample_DemoDataModel")
#else
# define IN_FILE SAMPLES_PUBLISH_GALLERY_DIRECTORY"/Coding_Samples/sample_DemoDataModel.pdf"
# define IN_FILE_HTMLTEMPLATE SAMPLES_DATA_HTML_DIRECTORY"/exportpdftohtml_template.html"
# define IN_VIEWER_TEMPLATE SAMPLES_PUBLISH_HTML_DIRECTORY"/htmlforserver/exportpdftohtml/root/viewer.html"
# define EXPORT_FORMAT "html" // values are "html" or "scs"
# define EXPORT_TYPE "online"
# define OUT_ROOT_DIR SAMPLES_PUBLISH_HTML_DIRECTORY"/htmlforserver/exportpdftohtml/root/PdfContent"
# define OUT_NAME "sample_DemoDataModel"
#endif
enum class ExportType {
WRONG_TYPE, // Only when wrong parameters is passed in the command line arguments
ONLINE, // The solution for client/server integration and request for best performances (cf. kA3DWebOnline).
OFFLINE_SINGLE_FILE, // The easy way to give a PDF exported to someone (cf. kA3DWebOfflineSingleFile).
};
//######################################################################################################################
// Tools
A3DBool hasEnding(const A3DUTF8Char* pcStr, const A3DUTF8Char* pcExt)
{
if (pcExt == nullptr || pcStr == nullptr)
return A3D_FALSE;
const std::string strExt(pcExt);
const std::string str(pcStr);
if (str.length() >= strExt.length())
{
const std::string strFileNameExt = str.substr(str.length() - strExt.length());
return std::equal(strFileNameExt.begin(), strFileNameExt.end(), strExt.begin(), [](char const& c1, char const& c2)
{
return c1 == c2 || std::toupper(c1) == std::toupper(c2);
});
}
else
{
return A3D_FALSE;
}
}
//######################################################################################################################
#ifdef _MSC_VER
int wmain(A3DInt32 iArgc, A3DUniChar** ppcArgv)
#else
int main(int iArgc, A3DUTF8Char** ppcArgv)
#endif
{
#ifndef _MSC_VER
setenv("LC_NUMERIC", "en_US.UTF-8", 1); // Locally force locale
#endif
// if no log file specified on command line or redirection failed, fall back to local file
#ifdef _MSC_VER
GetLogFile(_T(SAMPLES_PUBLISH_HTML_DIRECTORY"\\htmlforserver\\exportpdftohtml\\root\\ExportPDFToHtml.log.txt"));
#else
GetLogFile(SAMPLES_PUBLISH_HTML_DIRECTORY"/htmlforserver/exportpdftohtml/root/ExportPDFToHtml.log.txt");
#endif
A3DSDKHOOPSExchangeLoader sHoopsExchangeLoader(_T(HOOPS_BINARY_DIRECTORY), HOOPS_LICENSE);
CHECK_RET(sHoopsExchangeLoader.m_eSDKStatus);
CHECK_RET(A3DDllSetCallbacksMemory(CheckMalloc, CheckFree));
CHECK_RET(A3DDllSetCallbacksReport(PrintLogMessage, PrintLogWarning, PrintLogError));
// First of all we parse optional command line options
A3DUTF8Char* pc3DTemplateFile = nullptr;
A3DUTF8Char* pcFileName = nullptr;
A3DUTF8Char* pcFormat = nullptr;
A3DUTF8Char* pcOutputDirectory = nullptr;
A3DUTF8Char* pcOutputName = nullptr;
A3DUTF8Char* pcExportType = nullptr;
A3DUns8 iOutputFormats = 0;
ExportType eExportType = ExportType::WRONG_TYPE;
#ifdef _MSC_VER
A3DUTF8Char fileName[_MAX_PATH];
pcFileName = fileName;
A3DMiscUTF16ToUTF8(IN_FILE, pcFileName);
A3DUTF8Char format[_MAX_PATH];
pcFormat = format;
A3DMiscUTF16ToUTF8(EXPORT_FORMAT, pcFormat);
A3DUTF8Char outputDirectory[_MAX_PATH];
pcOutputDirectory = outputDirectory;
A3DMiscUTF16ToUTF8(OUT_ROOT_DIR, pcOutputDirectory);
A3DUTF8Char outputName[_MAX_PATH];
pcOutputName = outputName;
A3DMiscUTF16ToUTF8(OUT_NAME, pcOutputName);
A3DUTF8Char templateFile[_MAX_PATH];
pc3DTemplateFile = templateFile;
A3DMiscUTF16ToUTF8(IN_FILE_HTMLTEMPLATE, pc3DTemplateFile);
A3DUTF8Char exportType[_MAX_PATH];
pcExportType = exportType;
A3DMiscUTF16ToUTF8(EXPORT_TYPE, exportType);
#else
pcFileName = (A3DUTF8Char*)IN_FILE;
pcOutputDirectory = (A3DUTF8Char*)OUT_ROOT_DIR;
pcOutputName = (A3DUTF8Char*)OUT_NAME;
pc3DTemplateFile = (A3DUTF8Char*)IN_FILE_HTMLTEMPLATE;
pcFormat = (A3DUTF8Char*)EXPORT_FORMAT;
pcExportType = (A3DUTF8Char*)EXPORT_TYPE;
#endif
if (iArgc >= 2)
{
#ifdef _MSC_VER
A3DMiscUTF16ToUTF8(ppcArgv[1], pcFileName);
#else
pcFileName = ppcArgv[1];
#endif
}
if (iArgc >= 3)
{
#ifdef _MSC_VER
A3DMiscUTF16ToUTF8(ppcArgv[2], pcFormat);
#else
pcFormat = ppcArgv[2];
#endif
}
if (iArgc >= 4)
{
#ifdef _MSC_VER
A3DMiscUTF16ToUTF8(ppcArgv[3], pcExportType);
#else
pcExportType = ppcArgv[3];
#endif
}
if (iArgc >= 5)
{
#ifdef _MSC_VER
A3DMiscUTF16ToUTF8(ppcArgv[4], pcOutputDirectory);
#else
pcOutputDirectory = ppcArgv[4];
#endif
}
if (iArgc >= 6)
{
#ifdef _MSC_VER
A3DMiscUTF16ToUTF8(ppcArgv[5], pcOutputName);
#else
pcOutputName = ppcArgv[5];
#endif
}
// Treat format parameter
if (pcFormat != nullptr)
{
std::string strFormat(pcFormat);
std::transform(strFormat.begin(), strFormat.end(), strFormat.begin(), [](unsigned char c)
{
return static_cast<char>(::tolower(c));
}
);
const size_t flagSize = strFormat.length();
size_t previousCharIndex = 0;
for (size_t charIndex = 0; charIndex <= flagSize; ++charIndex)
{
if (charIndex > previousCharIndex && (charIndex == flagSize || strFormat[charIndex] == '|'))
{
std::string strValue = strFormat.substr(previousCharIndex, charIndex - previousCharIndex);
previousCharIndex = charIndex + 1;
if (strValue == "html")
{
iOutputFormats |= kA3DWebOutFormatHtml;
}
else if (strValue == "scs")
{
iOutputFormats |= kA3DWebOutFormatScs;
}
}
}
}
if (pcExportType != nullptr)
{
const std::string strExportType(pcExportType);
if (strExportType == "offline_single_file")
eExportType = ExportType::OFFLINE_SINGLE_FILE;
else if (strExportType == "online")
eExportType = ExportType::ONLINE;
else
{
MY_PRINTF("Unsupported export type\n");
}
}
// check parameter validity
if (hasEnding(pcFileName, ".pdf") && pcOutputDirectory != nullptr && pc3DTemplateFile != nullptr && iOutputFormats != 0 && eExportType != ExportType::WRONG_TYPE)
{
A3DRWParamsExportHtmlData paramsExportData;
A3D_INITIALIZE_DATA(A3DRWParamsExportHtmlData, paramsExportData);
paramsExportData.m_bIncludeMeasurementInformation = A3D_TRUE;
paramsExportData.m_pcHtmlTemplateName = pc3DTemplateFile;
paramsExportData.m_ePdfOutputFormat = kA3DWebOutPdfFormatXml;
paramsExportData.m_i3dOutputFormat = iOutputFormats;
if (eExportType == ExportType::ONLINE) {
CHECK_RET(A3DConvertPDFToWebFormat(pcFileName, &paramsExportData, pcOutputDirectory, pcOutputName));
}
else if (eExportType == ExportType::OFFLINE_SINGLE_FILE) {
// set the output as monolithic
paramsExportData.m_eHtmlOutputMode = kA3DWebOfflineSingleFile;
// fill and set mandatory parameters
A3DRWHtmlOfflineData offlineData;
A3D_INITIALIZE_DATA(A3DRWHtmlOfflineData, offlineData);
#ifdef _MSC_VER
A3DUTF8Char viewerFilePath[_MAX_PATH];
A3DMiscUTF16ToUTF8(IN_VIEWER_TEMPLATE, viewerFilePath);
offlineData.m_pcPathToHtmlViewerFile = viewerFilePath;
#else
offlineData.m_pcPathToHtmlViewerFile = (A3DUTF8Char*)IN_VIEWER_TEMPLATE;
#endif
paramsExportData.m_pHtmlOfflineData = &offlineData;
CHECK_RET(A3DConvertPDFToWebFormat(pcFileName, &paramsExportData, pcOutputDirectory, pcOutputName));
}
return A3D_SUCCESS;
}
else
{
MY_PRINTF("\nUsage: ExportPDFToHTML [source] [format] [exportType] [outputDirectory] [outputXmlFile]\n");
MY_PRINTF(" source: the pdf file to convert in HTML\n");
MY_PRINTF(" format: output format(s) for cad models amongst html, scs.\n");
MY_PRINTF(" You can have more than one output format. If so, separate each by using '|'.\n");
MY_PRINTF(" Example: \"html|scs\".\n");
MY_PRINTF(" exportType: (optional) type of the export we would like (\"online\" or \"offline_single_file\").\n");
MY_PRINTF(" outputDirectory: (optional) the directory where the files will be put. The directory must exists.\n");
MY_PRINTF(" outputXmlFilename: (optional) name of the output xml file.\n");
return A3D_ERROR;
}
}