mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2026-04-20 02:57:21 +02:00
Major plugin refactor and cleanup.
Switched to POCO library for unified platform/library interface. Deprecated the external module API. It was creating more problems than solving. Removed most built-in libraries in favor of system libraries for easier maintenance. Cleaned and secured code with help from static analyzers.
This commit is contained in:
+99
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// AttributedString.cpp
|
||||
//
|
||||
|
||||
#include "Poco/PDF/AttributedString.h"
|
||||
#include "Poco/Format.h"
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
AttributedString::AttributedString():
|
||||
_align(ALIGN_LEFT),
|
||||
_style(STYLE_PLAIN),
|
||||
_fontName("Helvetica"),
|
||||
_fontSize(10)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AttributedString::AttributedString(const char* content):
|
||||
_content(content),
|
||||
_align(ALIGN_LEFT),
|
||||
_style(STYLE_PLAIN),
|
||||
_fontName("Helvetica"),
|
||||
_fontSize(10)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AttributedString::AttributedString(const std::string& content, Alignment align, int style):
|
||||
_content(content),
|
||||
_align(align),
|
||||
_style(static_cast<Style>(style)),
|
||||
_fontName("Helvetica"),
|
||||
_fontSize(10)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AttributedString::~AttributedString()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void AttributedString::setAttribute(int attr, const Poco::Dynamic::Var& value)
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case ATTR_FONT:
|
||||
_fontName = value.toString();
|
||||
return;
|
||||
case ATTR_SIZE:
|
||||
_fontSize = value;
|
||||
return;
|
||||
case ATTR_STYLE:
|
||||
_style = value.convert<int>();
|
||||
return;
|
||||
case ATTR_ALIGN:
|
||||
_align = static_cast<Alignment>(value.convert<int>());
|
||||
return;
|
||||
default:
|
||||
throw InvalidArgumentException(
|
||||
format("AttributeString::setAttribute: %d", attr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Poco::Dynamic::Var AttributedString::getAttribute(int attr)
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case ATTR_FONT: return _fontName;
|
||||
case ATTR_SIZE: return _fontSize;
|
||||
case ATTR_STYLE: return static_cast<int>(_style);
|
||||
case ATTR_ALIGN: return static_cast<int>(_align);
|
||||
default:
|
||||
throw InvalidArgumentException(
|
||||
format("AttributeString::setAttribute: %d", attr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AttributedString::clearAttribute(int attr)
|
||||
{
|
||||
switch (attr)
|
||||
{
|
||||
case ATTR_FONT: _fontName = "Helvetica"; return;
|
||||
case ATTR_SIZE: _fontSize = 10; return;
|
||||
case ATTR_STYLE: _style = STYLE_PLAIN; return;
|
||||
case ATTR_ALIGN: _align = ALIGN_LEFT; return;
|
||||
default:
|
||||
throw InvalidArgumentException(
|
||||
format("AttributeString::setAttribute: %d", attr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+164
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// Cell.cpp
|
||||
//
|
||||
|
||||
#include "Poco/PDF/Cell.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Cell::Cell(const AttributedString& content, const std::string& name, FontMapPtr pFontMap):
|
||||
_content(content),
|
||||
_name(name),
|
||||
_outline(OUTLINE_NONE),
|
||||
_lineWidth(1.0f),
|
||||
_encoding("UTF-8"),
|
||||
_trueType(true),
|
||||
_widthAsPct(-1)
|
||||
{
|
||||
setFonts(pFontMap);
|
||||
}
|
||||
|
||||
|
||||
Cell::Cell(const AttributedString& content, FontMapPtr pFontMap, const std::string& encoding, bool trueType, int widthAsPct):
|
||||
_content(content),
|
||||
_outline(OUTLINE_NONE),
|
||||
_lineWidth(1.0f),
|
||||
_encoding(encoding),
|
||||
_trueType(trueType),
|
||||
_widthAsPct(widthAsPct)
|
||||
{
|
||||
setFonts(pFontMap);
|
||||
}
|
||||
|
||||
|
||||
Cell::~Cell()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Cell::setFonts(FontMapPtr pFontMap)
|
||||
{
|
||||
_pFontMap = pFontMap;
|
||||
if (_pFontMap) poco_assert(_pFontMap->size() == 4);
|
||||
}
|
||||
|
||||
|
||||
void Cell::borderTopBottom(bool show)
|
||||
{
|
||||
borderTop(show);
|
||||
borderBottom(show);
|
||||
}
|
||||
|
||||
|
||||
void Cell::borderLeftRight(bool show)
|
||||
{
|
||||
borderLeft(show);
|
||||
borderRight(show);
|
||||
}
|
||||
|
||||
|
||||
void Cell::borderAll(bool show)
|
||||
{
|
||||
borderTop(show);
|
||||
borderBottom(show);
|
||||
borderLeft(show);
|
||||
borderRight(show);
|
||||
}
|
||||
|
||||
|
||||
void Cell::draw(Page& page, float x, float y, float width, float height)
|
||||
{
|
||||
// uncomment to force showing of the cell outline regardless of settings
|
||||
//_outline = 15;
|
||||
|
||||
if (_outline != OUTLINE_NONE)
|
||||
{
|
||||
page.setLineWidth(_lineWidth);
|
||||
page.moveTo(x, y);
|
||||
if (_outline & OUTLINE_LEFT ) page.lineTo(x, y+height);
|
||||
page.moveTo(x, y+height);
|
||||
if (_outline & OUTLINE_TOP ) page.lineTo(x+width, y+height);
|
||||
page.moveTo(x+width, y+height);
|
||||
if (_outline & OUTLINE_RIGHT ) page.lineTo(x+width, y );
|
||||
page.moveTo(x+width, y);
|
||||
if (_outline & OUTLINE_BOTTOM) page.lineTo(x, y );
|
||||
page.stroke();
|
||||
}
|
||||
|
||||
std::string text = _content;
|
||||
if (!text.empty())
|
||||
{
|
||||
Font originalFont = page.getFont();
|
||||
float originalSize = page.getFontSize();
|
||||
try
|
||||
{
|
||||
// font names hard coded here, needs more work on the library level
|
||||
int fontStyle = _content.getAttribute(AttributedString::ATTR_STYLE);
|
||||
float fontSize = _content.getAttribute(AttributedString::ATTR_SIZE);
|
||||
if (fontStyle == AttributedString::STYLE_PLAIN)
|
||||
{
|
||||
if (!_pFontMap) page.setFont("Helvetica", fontSize);
|
||||
else if (_trueType) page.setTTFont((*_pFontMap)[AttributedString::STYLE_PLAIN], fontSize, _encoding);
|
||||
else page.setFont((*_pFontMap)[AttributedString::STYLE_PLAIN], fontSize, _encoding);
|
||||
}
|
||||
else if (fontStyle | AttributedString::STYLE_BOLD)
|
||||
{
|
||||
if (!_pFontMap) page.setFont("Helvetica-Bold", fontSize);
|
||||
else if (_trueType) page.setTTFont((*_pFontMap)[AttributedString::STYLE_BOLD], fontSize, _encoding);
|
||||
else page.setFont((*_pFontMap)[AttributedString::STYLE_BOLD], fontSize, _encoding);
|
||||
}
|
||||
else if (fontStyle | AttributedString::STYLE_ITALIC)
|
||||
{
|
||||
if (!_pFontMap) page.setFont("Helvetica-Oblique", fontSize);
|
||||
else if (_trueType) page.setTTFont((*_pFontMap)[AttributedString::STYLE_ITALIC], fontSize, _encoding);
|
||||
else page.setFont((*_pFontMap)[AttributedString::STYLE_ITALIC], fontSize, _encoding);
|
||||
}
|
||||
else if ((fontStyle & AttributedString::STYLE_BOLD) && (fontStyle & AttributedString::STYLE_ITALIC))
|
||||
{
|
||||
if (!_pFontMap) page.setFont("Helvetica-BoldOblique", fontSize);
|
||||
else if (_trueType) page.setTTFont((*_pFontMap)[AttributedString::STYLE_BOLD | AttributedString::STYLE_ITALIC], fontSize, _encoding);
|
||||
else page.setFont((*_pFontMap)[AttributedString::STYLE_BOLD | AttributedString::STYLE_ITALIC], fontSize, _encoding);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw NotFoundException(format("Unknown font style: %d", fontStyle));
|
||||
}
|
||||
|
||||
float tw = page.textWidth(text);
|
||||
// trim text that does not fit
|
||||
while (tw > width && text.size())
|
||||
{
|
||||
text = text.substr(0, text.size() - 1);
|
||||
tw = page.textWidth(text);
|
||||
}
|
||||
float th = page.getFontSize();
|
||||
float yPos = (height <= th) ? y : y + (height - th) / 2;
|
||||
int align = _content.getAttribute(AttributedString::ATTR_ALIGN);
|
||||
switch (align)
|
||||
{
|
||||
case AttributedString::ALIGN_LEFT:
|
||||
page.writeOnce(x + 5, yPos, text); break;
|
||||
case AttributedString::ALIGN_CENTER:
|
||||
page.writeOnce(x + (width - tw) / 2, yPos, text); break;
|
||||
break;
|
||||
case AttributedString::ALIGN_RIGHT:
|
||||
page.writeOnce(x + (width - tw), yPos, text); break;
|
||||
break;
|
||||
default:
|
||||
throw NotFoundException(format("Unknown alignment mode: %d", align));
|
||||
}
|
||||
}
|
||||
catch (Poco::Exception&)
|
||||
{
|
||||
page.setFont(originalFont, originalSize);
|
||||
throw;
|
||||
}
|
||||
page.setFont(originalFont, originalSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Destination.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: Destination
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/Destination.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Destination::Destination(HPDF_Doc* pPDF,
|
||||
const HPDF_Destination& destination,
|
||||
const std::string& name):
|
||||
Resource<HPDF_Destination>(pPDF, destination, name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
Destination::~Destination()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+350
@@ -0,0 +1,350 @@
|
||||
//
|
||||
// Document.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: Document
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/Document.h"
|
||||
#include "Poco/PDF/PDFException.h"
|
||||
#include "Poco/File.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/LocalDateTime.h"
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
#include "Poco/StringTokenizer.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include <utility>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Document::Document(const std::string fileName,
|
||||
Poco::UInt32 pageCount,
|
||||
Page::Size pageSize,
|
||||
Page::Orientation orientation):
|
||||
_pdf(HPDF_New(HPDF_Error_Handler, 0)),
|
||||
_fileName(fileName),
|
||||
_pRawData(0),
|
||||
_size(0)
|
||||
{
|
||||
init(pageCount, pageSize, orientation);
|
||||
}
|
||||
|
||||
|
||||
Document::Document(Poco::UInt32 pageCount,
|
||||
Page::Size pageSize,
|
||||
Page::Orientation orientation):
|
||||
_pdf(HPDF_New(HPDF_Error_Handler, 0)),
|
||||
_pRawData(0),
|
||||
_size(0)
|
||||
{
|
||||
init(pageCount, pageSize, orientation);
|
||||
}
|
||||
|
||||
|
||||
Document::~Document()
|
||||
{
|
||||
HPDF_Free(_pdf);
|
||||
delete _pRawData;
|
||||
}
|
||||
|
||||
|
||||
void Document::init(Poco::UInt32 pageCount,
|
||||
Page::Size pageSize, Page::Orientation orientation)
|
||||
{
|
||||
useUTF8Encoding();
|
||||
compression(COMPRESSION_ALL);
|
||||
for (Poco::UInt32 i = 0; i < pageCount; ++i)
|
||||
addPage(pageSize, orientation);
|
||||
}
|
||||
|
||||
|
||||
void Document::createNew(bool resetAll)
|
||||
{
|
||||
reset(resetAll);
|
||||
HPDF_NewDoc(_pdf);
|
||||
}
|
||||
|
||||
|
||||
void Document::save(const std::string fileName)
|
||||
{
|
||||
std::string fn = fileName.empty() ? _fileName : fileName;
|
||||
if (fn.empty())
|
||||
HPDF_SaveToStream (_pdf);
|
||||
else
|
||||
HPDF_SaveToFile(_pdf, fn.c_str());
|
||||
}
|
||||
|
||||
|
||||
const Document::DataPtr Document::data(SizeType& sz)
|
||||
{
|
||||
sz = size();
|
||||
delete _pRawData;
|
||||
_pRawData = new HPDF_BYTE[sz];
|
||||
HPDF_ReadFromStream(_pdf, _pRawData, &sz);
|
||||
return _pRawData;
|
||||
}
|
||||
|
||||
|
||||
Document::SizeType Document::size()
|
||||
{
|
||||
if (HPDF_Stream_Validate(_pdf->stream)) HPDF_ResetStream(_pdf);
|
||||
HPDF_SaveToStream(_pdf);
|
||||
return _size = HPDF_GetStreamSize(_pdf);
|
||||
}
|
||||
|
||||
|
||||
const Page& Document::addPage(Page::Size pageSize, Page::Orientation orientation)
|
||||
{
|
||||
Page page(this, HPDF_AddPage(_pdf), pageSize);
|
||||
page.setSizeAndOrientation(pageSize, orientation);
|
||||
_pages.push_back(page);
|
||||
return _pages.back();
|
||||
}
|
||||
|
||||
|
||||
const Page& Document::insertPage(int index,
|
||||
Page::Size pageSize,
|
||||
Page::Orientation orientation)
|
||||
{
|
||||
poco_assert (index > 0);
|
||||
poco_assert (index < _pages.size());
|
||||
HPDF_Page target = *((HPDF_Page*) HPDF_List_ItemAt(_pdf->page_list, static_cast<HPDF_UINT>(index)));
|
||||
return *_pages.insert(_pages.begin() + index,
|
||||
Page(this,
|
||||
HPDF_InsertPage(_pdf, target),
|
||||
pageSize,
|
||||
orientation));
|
||||
}
|
||||
|
||||
|
||||
const Page& Document::getCurrentPage()
|
||||
{
|
||||
Page p(this, HPDF_GetCurrentPage(_pdf));
|
||||
PageContainer::iterator it = _pages.begin();
|
||||
PageContainer::iterator end = _pages.end();
|
||||
for (;it != end; ++it)
|
||||
if (*it == p) return *it;
|
||||
|
||||
throw NotFoundException("Current page not found.");
|
||||
}
|
||||
|
||||
|
||||
const Font& Document::loadFont(const std::string& name, const std::string& encoding)
|
||||
{
|
||||
Font font(&_pdf, HPDF_GetFont(_pdf, name.c_str(), encoding.empty() ? 0 : encoding.c_str()));
|
||||
std::pair<FontContainer::iterator, bool> ret =
|
||||
_fonts.insert(FontContainer::value_type(name, font));
|
||||
|
||||
if (ret.second) return ret.first->second;
|
||||
|
||||
throw IllegalStateException("Could not create font.");
|
||||
}
|
||||
|
||||
|
||||
const Font& Document::font(const std::string& name, const std::string& encoding)
|
||||
{
|
||||
FontContainer::iterator it = _fonts.find(name);
|
||||
if (_fonts.end() != it) return it->second;
|
||||
|
||||
return loadFont(name, encoding);
|
||||
}
|
||||
|
||||
|
||||
std::string Document::loadType1Font(const std::string& afmFileName, const std::string& pfmFileName)
|
||||
{
|
||||
return HPDF_LoadType1FontFromFile(_pdf, afmFileName.c_str(), pfmFileName.c_str());
|
||||
}
|
||||
|
||||
|
||||
std::string Document::loadTTFont(const std::string& fileName, bool embed, int index)
|
||||
{
|
||||
if (-1 == index)
|
||||
{
|
||||
return HPDF_LoadTTFontFromFile(_pdf,
|
||||
fileName.c_str(),
|
||||
embed ? HPDF_TRUE : HPDF_FALSE);
|
||||
}
|
||||
else if (index >= 0)
|
||||
{
|
||||
return HPDF_LoadTTFontFromFile2(_pdf,
|
||||
fileName.c_str(),
|
||||
static_cast<HPDF_UINT>(index),
|
||||
embed ? HPDF_TRUE : HPDF_FALSE);
|
||||
}
|
||||
else
|
||||
throw InvalidArgumentException("Invalid font index.");
|
||||
}
|
||||
|
||||
|
||||
const Image& Document::loadPNGImageImpl(const std::string& fileName, bool doLoad)
|
||||
{
|
||||
Path path(fileName);
|
||||
|
||||
if (File(path).exists())
|
||||
{
|
||||
std::pair<ImageContainer::iterator, bool> it;
|
||||
if (doLoad)
|
||||
{
|
||||
Image image(&_pdf, HPDF_LoadPngImageFromFile(_pdf, fileName.c_str()));
|
||||
it = _images.insert(ImageContainer::value_type(path.getBaseName(), image));
|
||||
}
|
||||
else
|
||||
{
|
||||
Image image(&_pdf, HPDF_LoadPngImageFromFile2(_pdf, fileName.c_str()));
|
||||
it = _images.insert(ImageContainer::value_type(path.getBaseName(), image));
|
||||
}
|
||||
if (it.second) return it.first->second;
|
||||
else throw IllegalStateException("Could not insert image.");
|
||||
}
|
||||
else
|
||||
throw NotFoundException("File not found: " + fileName);
|
||||
}
|
||||
|
||||
|
||||
const Image& Document::loadJPEGImage(const std::string& fileName)
|
||||
{
|
||||
Path path(fileName);
|
||||
|
||||
if (File(path).exists())
|
||||
{
|
||||
Image image(&_pdf, HPDF_LoadJpegImageFromFile(_pdf, fileName.c_str()));
|
||||
std::pair<ImageContainer::iterator, bool> it =
|
||||
_images.insert(ImageContainer::value_type(path.getBaseName(), image));
|
||||
if (it.second) return it.first->second;
|
||||
else throw IllegalStateException("Could not insert image.");
|
||||
}
|
||||
else
|
||||
throw NotFoundException("File not found: " + fileName);
|
||||
}
|
||||
|
||||
|
||||
void Document::encryption(Encryption mode, Poco::UInt32 keyLength)
|
||||
{
|
||||
if (ENCRYPT_R3 == mode && (keyLength < 5 || keyLength > 128))
|
||||
throw InvalidArgumentException("Invalid key length.");
|
||||
|
||||
HPDF_SetEncryptionMode(_pdf,
|
||||
static_cast<HPDF_EncryptMode>(mode),
|
||||
static_cast<HPDF_UINT>(keyLength));
|
||||
}
|
||||
|
||||
|
||||
const Encoder& Document::loadEncoder(const std::string& name)
|
||||
{
|
||||
EncoderContainer::iterator it = _encoders.find(name);
|
||||
if (_encoders.end() == it) return it->second;
|
||||
|
||||
Encoder enc(&_pdf, HPDF_GetEncoder(_pdf, name.c_str()), name);
|
||||
std::pair<EncoderContainer::iterator, bool> ret =
|
||||
_encoders.insert(EncoderContainer::value_type(name, enc));
|
||||
|
||||
if (ret.second) return ret.first->second;
|
||||
|
||||
throw IllegalStateException("Could not create encoder.");
|
||||
}
|
||||
|
||||
|
||||
const Encoder& Document::getCurrentEncoder()
|
||||
{
|
||||
HPDF_Encoder enc = HPDF_GetCurrentEncoder(_pdf);
|
||||
std::string name = enc->name;
|
||||
EncoderContainer::iterator it = _encoders.find(name);
|
||||
if (_encoders.end() == it)
|
||||
{
|
||||
std::pair<EncoderContainer::iterator, bool> ret =
|
||||
_encoders.insert(EncoderContainer::value_type(name, Encoder(&_pdf, enc)));
|
||||
|
||||
if (ret.second) return ret.first->second;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
const Encoder& Document::setCurrentEncoder(const std::string& name)
|
||||
{
|
||||
loadEncoder(name);
|
||||
HPDF_SetCurrentEncoder(_pdf, name.c_str());
|
||||
return getCurrentEncoder();
|
||||
}
|
||||
|
||||
|
||||
const Outline& Document::createOutline(const std::string& title, const Outline& parent, const Encoder& encoder)
|
||||
{
|
||||
_outlines.push_back(Outline(&_pdf, HPDF_CreateOutline(_pdf, parent, title.c_str(), encoder)));
|
||||
return _outlines.back();
|
||||
}
|
||||
|
||||
|
||||
void Document::setInfo(Info info, const LocalDateTime& dt)
|
||||
{
|
||||
if (INFO_CREATION_DATE == info || INFO_MOD_DATE == info)
|
||||
{
|
||||
HPDF_Date hpdfDate;
|
||||
hpdfDate.year = dt.year();
|
||||
hpdfDate.month = dt.month();
|
||||
hpdfDate.day = dt.day();
|
||||
hpdfDate.hour = dt.hour();
|
||||
hpdfDate.minutes = dt.minute();
|
||||
hpdfDate.seconds = dt.second();
|
||||
std::string tzd = DateTimeFormatter::tzdISO(dt.tzd());
|
||||
StringTokenizer st(tzd, "+-:");
|
||||
if (st.count() >= 2)
|
||||
{
|
||||
hpdfDate.ind = tzd[0];
|
||||
hpdfDate.off_hour = NumberParser::parse(st[0]);
|
||||
hpdfDate.off_minutes = NumberParser::parse(st[1]);
|
||||
}
|
||||
else hpdfDate.ind = ' ';
|
||||
|
||||
HPDF_SetInfoDateAttr(_pdf, static_cast<HPDF_InfoType>(info), hpdfDate);
|
||||
}
|
||||
else
|
||||
throw InvalidArgumentException("Can not set document info.");
|
||||
}
|
||||
|
||||
|
||||
void Document::setInfo(Info info, const std::string& value)
|
||||
{
|
||||
if (INFO_CREATION_DATE == info || INFO_MOD_DATE == info)
|
||||
throw InvalidArgumentException("Can not set document date.");
|
||||
|
||||
HPDF_SetInfoAttr(_pdf, static_cast<HPDF_InfoType>(info), value.c_str());
|
||||
}
|
||||
|
||||
|
||||
void Document::setPassword(const std::string& ownerPassword, const std::string& userPassword)
|
||||
{
|
||||
if (ownerPassword.empty())
|
||||
throw InvalidArgumentException("Owner password empty.");
|
||||
|
||||
HPDF_SetPassword(_pdf, ownerPassword.c_str(), userPassword.c_str());
|
||||
}
|
||||
|
||||
|
||||
void Document::reset(bool all)
|
||||
{
|
||||
if (!all) HPDF_FreeDoc(_pdf);
|
||||
else
|
||||
{
|
||||
_pages.clear();
|
||||
_fonts.clear();
|
||||
_encoders.clear();
|
||||
_outlines.clear();
|
||||
_images.clear();
|
||||
HPDF_FreeDocAll(_pdf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Encoder.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: Encoder
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/Encoder.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Encoder::Encoder(HPDF_Doc* pPDF,
|
||||
const HPDF_Encoder& encoder,
|
||||
const std::string& name):
|
||||
Resource<HPDF_Encoder>(pPDF, encoder, name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
Encoder::~Encoder()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Font.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: Font
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/Font.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Font::Font(HPDF_Doc* pPDF, HPDF_Font font):
|
||||
Resource<HPDF_Font>(pPDF, font, HPDF_Font_GetFontName(font))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// Image.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: Image
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/Image.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Image::Image(HPDF_Doc* pPDF, const HPDF_Image& resource, const std::string& name):
|
||||
Resource<HPDF_Image>(pPDF, resource, name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// LinkAnnotation.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: LinkAnnotation
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/LinkAnnotation.h"
|
||||
#include "Poco/PDF/PDFException.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
LinkAnnotation::LinkAnnotation(HPDF_Doc* pPDF,
|
||||
const HPDF_Annotation& annotation,
|
||||
const std::string& name):
|
||||
Resource<HPDF_Annotation>(pPDF, annotation, name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LinkAnnotation::~LinkAnnotation()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Outline.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: Outline
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/Outline.h"
|
||||
#include "Poco/PDF/PDFException.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Outline::Outline(HPDF_Doc* pPDF, const HPDF_Outline& outline, const std::string& name):
|
||||
Resource<HPDF_Outline>(pPDF, outline, name)
|
||||
{
|
||||
open();
|
||||
}
|
||||
|
||||
|
||||
Outline::~Outline()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Outline::Outline(const Outline& other):
|
||||
Resource<HPDF_Outline>(other)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Outline& Outline::operator = (const Outline& outline)
|
||||
{
|
||||
Outline tmp(outline);
|
||||
swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+271
@@ -0,0 +1,271 @@
|
||||
//
|
||||
// PDFException.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: PDFException
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/PDFException.h"
|
||||
#include "Poco/Format.h"
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
void HPDF_Error_Handler(HPDF_STATUS error_no, HPDF_STATUS detail_no, void* user_data)
|
||||
{
|
||||
switch (error_no)
|
||||
{
|
||||
case HPDF_ARRAY_COUNT_ERR:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_ARRAY_ITEM_NOT_FOUND:
|
||||
throw NotFoundException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_ARRAY_ITEM_UNEXPECTED_TYPE:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_BINARY_LENGTH_ERR:
|
||||
throw InvalidArgumentException("The length of the data exceeds HPDF_LIMIT_MAX_STRING_LEN.");
|
||||
case HPDF_CANNOT_GET_PALLET:
|
||||
throw NotFoundException("Cannot get a pallet data from PNG image.");
|
||||
case HPDF_DICT_COUNT_ERR:
|
||||
throw InvalidArgumentException("The count of elements of a dictionary exceeds HPDF_LIMIT_MAX_DICT_ELEMENT");
|
||||
case HPDF_DICT_ITEM_NOT_FOUND:
|
||||
throw NotFoundException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_DICT_ITEM_UNEXPECTED_TYPE:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_DICT_STREAM_LENGTH_NOT_FOUND:
|
||||
throw NotFoundException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_DOC_ENCRYPTDICT_NOT_FOUND:
|
||||
throw NotFoundException("HPDF_SetPermission() OR HPDF_SetEncryptMode() was called before a password is set.");
|
||||
case HPDF_DOC_INVALID_OBJECT:
|
||||
throw IllegalStateException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_DUPLICATE_REGISTRATION:
|
||||
throw IllegalStateException("Tried to register a font that has been registered.");
|
||||
case HPDF_EXCEED_JWW_CODE_NUM_LIMIT:
|
||||
throw IllegalStateException("Cannot register a character to the japanese word wrap characters list.");
|
||||
case HPDF_ENCRYPT_INVALID_PASSWORD:
|
||||
throw IllegalStateException("Tried to set the owner password to NULL.");
|
||||
case HPDF_ERR_UNKNOWN_CLASS:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_EXCEED_GSTATE_LIMIT:
|
||||
throw IllegalStateException("The depth of the stack exceeded HPDF_LIMIT_MAX_GSTATE.");
|
||||
case HPDF_FAILD_TO_ALLOC_MEM:
|
||||
throw IllegalStateException("Memory allocation failed.");
|
||||
case HPDF_FILE_IO_ERROR:
|
||||
throw IOException("File processing failed. (A detailed code is set.)");
|
||||
case HPDF_FILE_OPEN_ERROR:
|
||||
throw IOException("Cannot open a file. (A detailed code is set.)");
|
||||
case HPDF_FONT_EXISTS:
|
||||
throw IllegalStateException("Tried to load a font that has been registered.");
|
||||
case HPDF_FONT_INVALID_WIDTHS_TABLE:
|
||||
throw IllegalStateException("The format of a font-file is invalid. Internal error. The consistency of the data was lost.");
|
||||
case HPDF_INVALID_AFM_HEADER:
|
||||
throw IllegalStateException("Cannot recognize a header of an afm file.");
|
||||
case HPDF_INVALID_ANNOTATION:
|
||||
throw IllegalStateException("The specified annotation handle is invalid.");
|
||||
case HPDF_INVALID_BIT_PER_COMPONENT:
|
||||
throw IllegalStateException("Bit-per-component of a image which was set as mask-image is invalid.");
|
||||
case HPDF_INVALID_CHAR_MATRICS_DATA:
|
||||
throw IllegalStateException("Cannot recognize char-matrics-data of an afm file.");
|
||||
case HPDF_INVALID_COLOR_SPACE:
|
||||
switch (detail_no)
|
||||
{
|
||||
case 1:
|
||||
throw InvalidArgumentException("The color_space parameter of HPDF_LoadRawImage is invalid.");
|
||||
case 2:
|
||||
throw InvalidArgumentException("Color-space of a image which was set as mask-image is invalid.");
|
||||
case 3:
|
||||
throw InvalidArgumentException("The function which is invalid in the present color-space was invoked.");
|
||||
default:
|
||||
throw PDFException();
|
||||
}
|
||||
case HPDF_INVALID_COMPRESSION_MODE:
|
||||
throw InvalidArgumentException("Invalid value was set when invoking HPDF_SetCommpressionMode().");
|
||||
case HPDF_INVALID_DATE_TIME:
|
||||
throw InvalidArgumentException("An invalid date-time value was set.");
|
||||
case HPDF_INVALID_DESTINATION:
|
||||
throw InvalidArgumentException("An invalid destination handle was set.");
|
||||
case HPDF_INVALID_DOCUMENT:
|
||||
throw InvalidArgumentException("An invalid document handle is set.");
|
||||
case HPDF_INVALID_DOCUMENT_STATE:
|
||||
throw IllegalStateException("The function which is invalid in the present state was invoked.");
|
||||
case HPDF_INVALID_ENCODER:
|
||||
throw InvalidArgumentException("An invalid encoder handle is set.");
|
||||
case HPDF_INVALID_ENCODER_TYPE:
|
||||
throw InvalidArgumentException("A combination between font and encoder is wrong.");
|
||||
case HPDF_INVALID_ENCODING_NAME:
|
||||
throw InvalidArgumentException("An Invalid encoding name is specified.");
|
||||
case HPDF_INVALID_ENCRYPT_KEY_LEN:
|
||||
throw InvalidArgumentException("The lengh of the key of encryption is invalid.");
|
||||
case HPDF_INVALID_FONTDEF_DATA:
|
||||
switch (detail_no)
|
||||
{
|
||||
case 1:
|
||||
throw InvalidArgumentException("An invalid font handle was set.");
|
||||
case 2:
|
||||
throw InvalidArgumentException("Unsupported font format.");
|
||||
default:
|
||||
throw PDFException();
|
||||
}
|
||||
case HPDF_INVALID_FONTDEF_TYPE:
|
||||
throw IllegalStateException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_INVALID_FONT_NAME:
|
||||
throw NotFoundException("A font which has the specified name is not found.");
|
||||
case HPDF_INVALID_IMAGE:
|
||||
throw InvalidArgumentException("Unsupported image format.");
|
||||
case HPDF_INVALID_JPEG_DATA:
|
||||
throw InvalidArgumentException("Unsupported image format.");
|
||||
case HPDF_INVALID_N_DATA:
|
||||
throw IOException("Cannot read a postscript-name from an afm file.");
|
||||
case HPDF_INVALID_OBJECT:
|
||||
switch (detail_no)
|
||||
{
|
||||
case 1:
|
||||
throw IllegalStateException("An invalid object is set.");
|
||||
case 2:
|
||||
throw IllegalStateException("Internal error. The consistency of the data was lost.");
|
||||
default:
|
||||
throw PDFException();
|
||||
}
|
||||
case HPDF_INVALID_OBJ_ID:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_INVALID_OPERATION:
|
||||
switch (detail_no)
|
||||
{
|
||||
case 1:
|
||||
throw IllegalStateException("Invoked HPDF_Image_SetColorMask() against the image-object which was set a mask-image.");
|
||||
default:
|
||||
throw PDFException();
|
||||
}
|
||||
case HPDF_INVALID_OUTLINE:
|
||||
throw InvalidArgumentException("An invalid outline-handle was specified.");
|
||||
case HPDF_INVALID_PAGE:
|
||||
throw InvalidArgumentException("An invalid page-handle was specified.");
|
||||
case HPDF_INVALID_PAGES:
|
||||
throw InvalidArgumentException("An invalid pages-handle was specified. (internel error)");
|
||||
case HPDF_INVALID_PARAMETER:
|
||||
throw InvalidArgumentException("An invalid value is set.");
|
||||
case HPDF_INVALID_PNG_IMAGE:
|
||||
throw InvalidArgumentException("Invalid PNG image format.");
|
||||
case HPDF_INVALID_STREAM:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_MISSING_FILE_NAME_ENTRY:
|
||||
throw InvalidArgumentException("Internal error. The \"_FILE_NAME\" entry for delayed loading is missing.");
|
||||
case HPDF_INVALID_TTC_FILE:
|
||||
throw InvalidArgumentException("Invalid .TTC file format.");
|
||||
case HPDF_INVALID_TTC_INDEX:
|
||||
throw InvalidArgumentException("The index parameter was exceed the number of included fonts");
|
||||
case HPDF_INVALID_WX_DATA:
|
||||
throw IOException("Cannot read a width-data from an afm file.");
|
||||
case HPDF_ITEM_NOT_FOUND:
|
||||
throw NotFoundException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_LIBPNG_ERROR:
|
||||
throw IOException("An error has returned from PNGLIB while loading an image.");
|
||||
case HPDF_NAME_INVALID_VALUE:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_NAME_OUT_OF_RANGE:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_PAGES_MISSING_KIDS_ENTRY:
|
||||
throw IllegalStateException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_PAGE_CANNOT_FIND_OBJECT:
|
||||
throw NotFoundException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_PAGE_CANNOT_GET_ROOT_PAGES:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_PAGE_CANNOT_RESTORE_GSTATE:
|
||||
throw IllegalStateException("There are no graphics-states to be restored.");
|
||||
case HPDF_PAGE_CANNOT_SET_PARENT:
|
||||
throw IllegalStateException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_PAGE_FONT_NOT_FOUND:
|
||||
throw NotFoundException("The current font is not set.");
|
||||
case HPDF_PAGE_INVALID_FONT:
|
||||
throw InvalidArgumentException("An invalid font-handle was spacified.");
|
||||
case HPDF_PAGE_INVALID_FONT_SIZE:
|
||||
throw InvalidArgumentException("An invalid font-size was set.");
|
||||
case HPDF_PAGE_INVALID_GMODE:
|
||||
throw InvalidArgumentException("See Graphics mode.");
|
||||
case HPDF_PAGE_INVALID_INDEX:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_PAGE_INVALID_ROTATE_VALUE:
|
||||
throw InvalidArgumentException("The specified value is not a multiple of 90.");
|
||||
case HPDF_PAGE_INVALID_SIZE:
|
||||
throw InvalidArgumentException("An invalid page-size was set.");
|
||||
case HPDF_PAGE_INVALID_XOBJECT:
|
||||
throw InvalidArgumentException("An invalid image-handle was set.");
|
||||
case HPDF_PAGE_OUT_OF_RANGE:
|
||||
throw RangeException("The specified value is out of range.");
|
||||
case HPDF_REAL_OUT_OF_RANGE:
|
||||
throw RangeException("The specified value is out of range.");
|
||||
case HPDF_STREAM_EOF:
|
||||
throw IllegalStateException("Unexpected EOF marker was detected.");
|
||||
case HPDF_STREAM_READLN_CONTINUE:
|
||||
throw IllegalStateException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_STRING_OUT_OF_RANGE:
|
||||
throw RangeException("The length of the specified text is too long.");
|
||||
case HPDF_THIS_FUNC_WAS_SKIPPED:
|
||||
throw IllegalStateException("The execution of a function was skipped because of other errors.");
|
||||
case HPDF_TTF_CANNOT_EMBEDDING_FONT:
|
||||
throw IllegalStateException("This font cannot be embedded. (restricted by license)");
|
||||
case HPDF_TTF_INVALID_CMAP:
|
||||
throw InvalidArgumentException("Unsupported ttf format. (cannot find unicode cmap.)");
|
||||
case HPDF_TTF_INVALID_FOMAT:
|
||||
throw InvalidArgumentException("Unsupported ttf format.");
|
||||
case HPDF_TTF_MISSING_TABLE:
|
||||
throw InvalidArgumentException("Unsupported ttf format. (cannot find a necessary table)");
|
||||
case HPDF_UNSUPPORTED_FONT_TYPE:
|
||||
throw InvalidArgumentException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_UNSUPPORTED_FUNC:
|
||||
switch (detail_no)
|
||||
{
|
||||
case 1:
|
||||
throw IllegalStateException("The library is not configured to use PNGLIB.");
|
||||
case 2:
|
||||
throw IllegalStateException("Internal error. The consistency of the data was lost.");
|
||||
default:
|
||||
throw PDFException();
|
||||
}
|
||||
case HPDF_UNSUPPORTED_JPEG_FORMAT:
|
||||
throw InvalidArgumentException("Unsupported JPEG format.");
|
||||
case HPDF_UNSUPPORTED_TYPE1_FONT:
|
||||
throw IllegalStateException("Failed to parse .PFB file.");
|
||||
case HPDF_XREF_COUNT_ERR:
|
||||
throw IllegalStateException("Internal error. The consistency of the data was lost.");
|
||||
case HPDF_ZLIB_ERROR:
|
||||
throw IllegalStateException("An error has occurred while executing a function of Zlib.");
|
||||
case HPDF_INVALID_PAGE_INDEX:
|
||||
throw IllegalStateException("An error returned from Zlib.");
|
||||
case HPDF_INVALID_URI:
|
||||
throw InvalidArgumentException("An invalid URI was set.");
|
||||
case HPDF_PAGE_LAYOUT_OUT_OF_RANGE:
|
||||
throw RangeException("An invalid page-layout was set.");
|
||||
case HPDF_PAGE_MODE_OUT_OF_RANGE:
|
||||
throw RangeException("An invalid page-mode was set.");
|
||||
case HPDF_PAGE_NUM_STYLE_OUT_OF_RANGE:
|
||||
throw RangeException("An invalid page-num-style was set.");
|
||||
case HPDF_ANNOT_INVALID_ICON:
|
||||
throw InvalidArgumentException("An invalid icon was set.");
|
||||
case HPDF_ANNOT_INVALID_BORDER_STYLE:
|
||||
throw InvalidArgumentException("An invalid border-style was set.");
|
||||
case HPDF_PAGE_INVALID_DIRECTION:
|
||||
throw InvalidArgumentException("An invalid page-direction was set.");
|
||||
case HPDF_INVALID_FONT:
|
||||
throw InvalidArgumentException("An invalid font-handle was specified. ");
|
||||
default:
|
||||
throw PDFException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
POCO_IMPLEMENT_EXCEPTION(PDFException, Poco::RuntimeException, "PDF Base Exception")
|
||||
POCO_IMPLEMENT_EXCEPTION(PDFCreateException, PDFException, "PDF creation failed")
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+219
@@ -0,0 +1,219 @@
|
||||
//
|
||||
// Page.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: Page
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/Page.h"
|
||||
#include "Poco/PDF/Document.h"
|
||||
#include "Poco/PDF/PDFException.h"
|
||||
#undef min
|
||||
#undef max
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Page::Page(Document* pDocument,
|
||||
const HPDF_Page& page,
|
||||
Size pageSize,
|
||||
Orientation orientation):
|
||||
_pDocument(pDocument),
|
||||
_page(page),
|
||||
_size(pageSize),
|
||||
_orientation(orientation),
|
||||
_pCurrentFont(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Page::Page(const Page& other):
|
||||
_pDocument(other._pDocument),
|
||||
_page(other._page),
|
||||
_size(other._size),
|
||||
_orientation(other._orientation),
|
||||
_pCurrentFont(other._pCurrentFont ? new Font(*other._pCurrentFont) : (Font*)0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Page::~Page()
|
||||
{
|
||||
delete _pCurrentFont;
|
||||
}
|
||||
|
||||
|
||||
Page& Page::operator = (const Page& page)
|
||||
{
|
||||
Page tmp(page);
|
||||
swap(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool Page::operator == (const Page& other) const
|
||||
{
|
||||
return &_pDocument->handle() == &other._pDocument->handle() && _page == other._page;
|
||||
}
|
||||
|
||||
|
||||
void Page::swap(Page& other)
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(_pDocument, other._pDocument);
|
||||
swap(_page, other._page);
|
||||
swap(_size, other._size);
|
||||
swap(_orientation, other._orientation);
|
||||
swap(_pCurrentFont, other._pCurrentFont);
|
||||
}
|
||||
|
||||
|
||||
void Page::writeOnce(float xPos, float yPos, const std::string& text)
|
||||
{
|
||||
beginText();
|
||||
write(xPos, yPos, text);
|
||||
endText();
|
||||
}
|
||||
|
||||
|
||||
int Page::writeOnceInRectangle(float left,
|
||||
float top,
|
||||
float right,
|
||||
float bottom,
|
||||
const std::string& text,
|
||||
TextAlignment align)
|
||||
{
|
||||
beginText();
|
||||
int ret = writeInRectangle(left, top, right, bottom, text, align);
|
||||
endText();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
float Page::textWidth(const std::string& text)
|
||||
{
|
||||
return HPDF_Page_TextWidth(_page, text.c_str());
|
||||
}
|
||||
|
||||
|
||||
void Page::setFont(const std::string& name, float size, const std::string& encoding)
|
||||
{
|
||||
setFont(_pDocument->font(name, encoding), size);
|
||||
}
|
||||
|
||||
|
||||
void Page::setTTFont(const std::string& name, float size, const std::string& encoding, bool embed)
|
||||
{
|
||||
setFont(_pDocument->font(_pDocument->loadTTFont(name, embed), encoding), size);
|
||||
}
|
||||
|
||||
|
||||
const Font& Page::getFont() const
|
||||
{
|
||||
delete _pCurrentFont; _pCurrentFont = 0;
|
||||
HPDF_Font pCurFont = HPDF_Page_GetCurrentFont(_page);
|
||||
if (!pCurFont) throw Poco::NullPointerException("PDF::Page has no font set.");
|
||||
_pCurrentFont = new Font(&_pDocument->handle(), pCurFont);
|
||||
return *_pCurrentFont;
|
||||
}
|
||||
|
||||
|
||||
void Page::setRotation(int angle)
|
||||
{
|
||||
if (0 != angle % 90 || angle > std::numeric_limits<HPDF_UINT16>::max())
|
||||
throw InvalidArgumentException("Invalid angle value.");
|
||||
|
||||
HPDF_Page_SetRotate(_page, static_cast<HPDF_UINT16>(angle));
|
||||
}
|
||||
|
||||
|
||||
const Destination& Page::createDestination(const std::string& name)
|
||||
{
|
||||
DestinationContainer::iterator it = _destinations.find(name);
|
||||
if (_destinations.end() != it)
|
||||
throw InvalidArgumentException("Destination already exists.");
|
||||
|
||||
Destination dest(&_pDocument->handle(), HPDF_Page_CreateDestination(_page), name);
|
||||
std::pair<DestinationContainer::iterator, bool> ret =
|
||||
_destinations.insert(DestinationContainer::value_type(name, dest));
|
||||
|
||||
if (ret.second) return ret.first->second;
|
||||
|
||||
throw IllegalStateException("Could not create destination.");
|
||||
}
|
||||
|
||||
|
||||
const TextAnnotation& Page::createTextAnnotation(const std::string& name,
|
||||
const Rectangle& rect,
|
||||
const std::string& text,
|
||||
const Encoder& encoder)
|
||||
{
|
||||
TextAnnotationContainer::iterator it = _textAnnotations.find(name);
|
||||
if (_textAnnotations.end() != it)
|
||||
throw InvalidArgumentException("Annotation already exists.");
|
||||
|
||||
TextAnnotation ann(&_pDocument->handle(),
|
||||
HPDF_Page_CreateTextAnnot(_page, rect, text.c_str(), encoder),
|
||||
name);
|
||||
|
||||
std::pair<TextAnnotationContainer::iterator, bool> ret =
|
||||
_textAnnotations.insert(TextAnnotationContainer::value_type(name, ann));
|
||||
|
||||
if (ret.second) return ret.first->second;
|
||||
|
||||
throw IllegalStateException("Could not create annotation.");
|
||||
}
|
||||
|
||||
|
||||
const LinkAnnotation& Page::createLinkAnnotation(const std::string& name,
|
||||
const Rectangle& rect,
|
||||
const Destination& dest)
|
||||
{
|
||||
LinkAnnotationContainer::iterator it = _linkAnnotations.find(name);
|
||||
if (_linkAnnotations.end() != it)
|
||||
throw InvalidArgumentException("Annotation already exists.");
|
||||
|
||||
LinkAnnotation ann(&_pDocument->handle(),
|
||||
HPDF_Page_CreateLinkAnnot(_page, rect, dest),
|
||||
name);
|
||||
std::pair<LinkAnnotationContainer::iterator, bool> ret =
|
||||
_linkAnnotations.insert(LinkAnnotationContainer::value_type(name, ann));
|
||||
|
||||
if (ret.second) return ret.first->second;
|
||||
|
||||
throw IllegalStateException("Could not create annotation.");
|
||||
}
|
||||
|
||||
|
||||
const LinkAnnotation& Page::createURILinkAnnotation(const std::string& name,
|
||||
const Rectangle& rect,
|
||||
const std::string& uri)
|
||||
{
|
||||
LinkAnnotationContainer::iterator it = _linkAnnotations.find(name);
|
||||
if (_linkAnnotations.end() != it)
|
||||
throw InvalidArgumentException("Annotation already exists.");
|
||||
|
||||
LinkAnnotation ann(&_pDocument->handle(),
|
||||
HPDF_Page_CreateURILinkAnnot(_page, rect, uri.c_str()),
|
||||
name);
|
||||
std::pair<LinkAnnotationContainer::iterator, bool> ret =
|
||||
_linkAnnotations.insert(LinkAnnotationContainer::value_type(name, ann));
|
||||
|
||||
if (ret.second) return ret.first->second;
|
||||
|
||||
throw IllegalStateException("Could not create annotation.");
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+100
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// Table.cpp
|
||||
//
|
||||
|
||||
#include "Poco/PDF/Table.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
Table::Table(int columnCount, int rowCount, const std::string& name, Cell::FontMapPtr pFontMap):
|
||||
_name(name), _cells(rowCount, TableRow(columnCount))
|
||||
{
|
||||
setFonts(pFontMap);
|
||||
}
|
||||
|
||||
|
||||
Table::~Table()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Table::addRow()
|
||||
{
|
||||
_cells.push_back(TableRow(columns()));
|
||||
}
|
||||
|
||||
|
||||
void Table::addRow(const TableRow& row)
|
||||
{
|
||||
if (_cells.empty())
|
||||
{
|
||||
_cells.push_back(row);
|
||||
}
|
||||
else
|
||||
{
|
||||
_cells.push_back(row);
|
||||
_cells.back().resize(_cells.front().size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Table::setCell(int col, int row, const Cell& cell)
|
||||
{
|
||||
_cells[row][col] = cell;
|
||||
if (_pFontMap && !cell.getFonts()) _cells[row][col].setFonts(_pFontMap);
|
||||
}
|
||||
|
||||
|
||||
void Table::setColumnWidth(int col, double width)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Table::setFonts(Cell::FontMapPtr pFontMap)
|
||||
{
|
||||
_pFontMap = pFontMap;
|
||||
if (_pFontMap) { poco_assert(_pFontMap->size() == 4); }
|
||||
}
|
||||
|
||||
|
||||
void Table::draw(Page& page, float x, float y, float width, float height)
|
||||
{
|
||||
if (_cells.size())
|
||||
{
|
||||
int rows = static_cast<int>(_cells.size());
|
||||
int cols = static_cast<int>(_cells[0].size());
|
||||
int r = 0;
|
||||
for (Cells::iterator it = _cells.begin(); it != _cells.end(); ++it)
|
||||
{
|
||||
TableRow& row(*it);
|
||||
float h = height / rows;
|
||||
int c = 0;
|
||||
float lastX = x;
|
||||
for (TableRow::iterator itr = row.begin(); itr != row.end(); ++itr)
|
||||
{
|
||||
Cell& cell(*itr);
|
||||
float w = width / cols;
|
||||
if (!cell.hasWidth())
|
||||
{
|
||||
cell.draw(page, x + (w * c), y - (h * r), w, h);
|
||||
lastX += (w * c);
|
||||
}
|
||||
else
|
||||
{
|
||||
w = width * cell.getWidthAsPct() / 100.0f;
|
||||
cell.draw(page, lastX, y - (h * r), w, h);
|
||||
lastX += w;
|
||||
}
|
||||
|
||||
++c;
|
||||
}
|
||||
++r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// TextAnnotation.cpp
|
||||
//
|
||||
// Library: PDF
|
||||
// Package: PDFCore
|
||||
// Module: TextAnnotation
|
||||
//
|
||||
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/TextAnnotation.h"
|
||||
#include "Poco/PDF/PDFException.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
TextAnnotation::TextAnnotation(HPDF_Doc* pPDF,
|
||||
const HPDF_Annotation& annotation,
|
||||
const std::string& name):
|
||||
Resource<HPDF_Annotation>(pPDF, annotation, name)
|
||||
{
|
||||
open();
|
||||
}
|
||||
|
||||
|
||||
TextAnnotation::~TextAnnotation()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+886
@@ -0,0 +1,886 @@
|
||||
//
|
||||
// XMLTemplate.cpp
|
||||
//
|
||||
|
||||
|
||||
#include "Poco/PDF/XMLTemplate.h"
|
||||
#include "Poco/PDF/Table.h"
|
||||
#include "Poco/SAX/SAXParser.h"
|
||||
#include "Poco/SAX/DefaultHandler.h"
|
||||
#include "Poco/SAX/Attributes.h"
|
||||
#include "Poco/SAX/InputSource.h"
|
||||
#include "Poco/Util/PropertyFileConfiguration.h"
|
||||
#include "Poco/FileStream.h"
|
||||
#include "Poco/AutoPtr.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Path.h"
|
||||
#include "Poco/TextConverter.h"
|
||||
#include "Poco/UTF8Encoding.h"
|
||||
#include "Poco/UTF8String.h"
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace PDF {
|
||||
|
||||
|
||||
class StackedConfiguration : public Poco::Util::AbstractConfiguration
|
||||
{
|
||||
public:
|
||||
typedef Poco::AutoPtr<Poco::Util::AbstractConfiguration> ConfigPtr;
|
||||
typedef std::vector<ConfigPtr> ConfigStack;
|
||||
|
||||
void push(ConfigPtr pConfig)
|
||||
{
|
||||
_stack.push_back(pConfig);
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
_stack.pop_back();
|
||||
}
|
||||
|
||||
ConfigPtr current() const
|
||||
{
|
||||
poco_assert(_stack.size() > 0);
|
||||
return _stack.back();
|
||||
}
|
||||
|
||||
float getFloat(const std::string& value)
|
||||
{
|
||||
return static_cast<float>(getDouble(value));
|
||||
}
|
||||
|
||||
float getFloat(const std::string& value, float deflt)
|
||||
{
|
||||
return static_cast<float>(getDouble(value, deflt));
|
||||
}
|
||||
|
||||
// AbstractConfiguration
|
||||
bool getRaw(const std::string& key, std::string& value) const
|
||||
{
|
||||
for (ConfigStack::const_reverse_iterator it = _stack.rbegin(); it != _stack.rend(); ++it)
|
||||
{
|
||||
if ((*it)->has(key))
|
||||
{
|
||||
value = (*it)->getRawString(key);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setRaw(const std::string& key, const std::string& value)
|
||||
{
|
||||
throw Poco::InvalidAccessException("not writable");
|
||||
}
|
||||
|
||||
void enumerate(const std::string& key, Poco::Util::AbstractConfiguration::Keys& range) const
|
||||
{
|
||||
std::set<std::string> keys;
|
||||
for (ConfigStack::const_iterator itc = _stack.begin(); itc != _stack.end(); ++itc)
|
||||
{
|
||||
Poco::Util::AbstractConfiguration::Keys partRange;
|
||||
(*itc)->keys(key, partRange);
|
||||
for (Poco::Util::AbstractConfiguration::Keys::const_iterator itr = partRange.begin(); itr != partRange.end(); ++itr)
|
||||
{
|
||||
if (keys.find(*itr) == keys.end())
|
||||
{
|
||||
range.push_back(*itr);
|
||||
keys.insert(*itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void removeRaw(const std::string& key)
|
||||
{
|
||||
throw Poco::InvalidAccessException("not writable");
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<ConfigPtr> _stack;
|
||||
};
|
||||
|
||||
|
||||
class Box
|
||||
{
|
||||
public:
|
||||
Box() :
|
||||
_x(0),
|
||||
_y(0),
|
||||
_width(0),
|
||||
_height(0)
|
||||
{
|
||||
}
|
||||
|
||||
Box(float x, float y, float width, float height) :
|
||||
_x(x),
|
||||
_y(y),
|
||||
_width(width),
|
||||
_height(height)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Box(const Box& box) :
|
||||
_x(box._x),
|
||||
_y(box._y),
|
||||
_width(box._width),
|
||||
_height(box._height)
|
||||
{
|
||||
}
|
||||
|
||||
~Box()
|
||||
{
|
||||
}
|
||||
|
||||
Box& operator = (const Box& box)
|
||||
{
|
||||
Box tmp(box);
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(Box& box)
|
||||
{
|
||||
std::swap(_x, box._x);
|
||||
std::swap(_y, box._y);
|
||||
std::swap(_width, box._width);
|
||||
std::swap(_height, box._height);
|
||||
}
|
||||
|
||||
float left() const
|
||||
{
|
||||
return _x;
|
||||
}
|
||||
|
||||
float right() const
|
||||
{
|
||||
return _x + _width;
|
||||
}
|
||||
|
||||
float bottom() const
|
||||
{
|
||||
return _y;
|
||||
}
|
||||
|
||||
float top() const
|
||||
{
|
||||
return _y + _height;
|
||||
}
|
||||
|
||||
float width() const
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
float height() const
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
void inset(float delta)
|
||||
{
|
||||
_x += delta;
|
||||
_y -= delta;
|
||||
_width -= 2 * delta;
|
||||
_height -= 2 * delta;
|
||||
}
|
||||
|
||||
void extend(float delta)
|
||||
{
|
||||
inset(-delta);
|
||||
}
|
||||
|
||||
void inset(float left, float right, float top, float bottom)
|
||||
{
|
||||
_x += left;
|
||||
_y += bottom;
|
||||
_width -= (left + right);
|
||||
_height -= (top + bottom);
|
||||
}
|
||||
|
||||
private:
|
||||
float _x;
|
||||
float _y;
|
||||
float _width;
|
||||
float _height;
|
||||
};
|
||||
|
||||
|
||||
class TemplateHandler : public Poco::XML::DefaultHandler
|
||||
{
|
||||
public:
|
||||
typedef Poco::AutoPtr<Poco::Util::AbstractConfiguration> StylePtr;
|
||||
|
||||
TemplateHandler(const Poco::Path& base) :
|
||||
_base(base),
|
||||
_pDocument(0),
|
||||
_pPage(0),
|
||||
_y(0)
|
||||
{
|
||||
_styles.push(parseStyle("font-family: Helvetica; font-size: 12; line-height: 1.2"));
|
||||
}
|
||||
|
||||
~TemplateHandler()
|
||||
{
|
||||
_styles.pop();
|
||||
delete _pPage;
|
||||
delete _pDocument;
|
||||
}
|
||||
|
||||
Document* document()
|
||||
{
|
||||
Document* pDocument = _pDocument;
|
||||
_pDocument = 0;
|
||||
return pDocument;
|
||||
}
|
||||
|
||||
void startDoc(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
if (_pDocument) throw Poco::IllegalStateException("only one <document> element is allowed");
|
||||
|
||||
StylePtr pStyle = pushStyle(attributes);
|
||||
|
||||
_size = attributes.getValue("size");
|
||||
if (_size.empty()) _size = "A4";
|
||||
_orientation = attributes.getValue("orientation");
|
||||
if (_orientation.empty()) _orientation = "portrait";
|
||||
|
||||
_encoding = attributes.getValue("encoding");
|
||||
if (_encoding.empty()) _encoding = "WinAnsiEncoding";
|
||||
|
||||
_pDocument = new Document(0, parsePageSize(_size), parseOrientation(_orientation));
|
||||
}
|
||||
|
||||
void endDoc()
|
||||
{
|
||||
popStyle();
|
||||
}
|
||||
|
||||
void startPage(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
if (!_pDocument) throw Poco::IllegalStateException("missing <document> element");
|
||||
if (_pPage) throw Poco::IllegalStateException("nested <page> elements are not allowed");
|
||||
|
||||
StylePtr pStyle = pushStyle(attributes);
|
||||
|
||||
std::string size = attributes.getValue("size");
|
||||
if (size.empty()) size = _size;
|
||||
std::string orientation = attributes.getValue("orientation");
|
||||
if (orientation.empty()) orientation = _orientation;
|
||||
|
||||
_pPage = new Page(_pDocument->addPage(parsePageSize(_size), parseOrientation(orientation)));
|
||||
_pPage->setLineWidth(0.2f);
|
||||
RGBColor black = {0, 0, 0};
|
||||
_pPage->setRGBStroke(black);
|
||||
|
||||
// read or force font, page must have default
|
||||
std::string fontFamily = _styles.getString("font-family", "helvetica");
|
||||
float fontSize = _styles.getFloat("font-size", 10.0);
|
||||
std::string fontStyle = _styles.getString("font-style", "normal");
|
||||
std::string fontWeight = _styles.getString("font-weight", "normal");
|
||||
|
||||
Font font = loadFont(fontFamily, fontStyle, fontWeight);
|
||||
_pPage->setFont(font, fontSize);
|
||||
|
||||
_boxes.push_back(Box(0, 0, _pPage->getWidth(), _pPage->getHeight()));
|
||||
|
||||
float margin = _styles.getFloat("margin", 0);
|
||||
float marginLeft = _styles.getFloat("margin-left", margin);
|
||||
float marginRight = _styles.getFloat("margin-right", margin);
|
||||
float marginTop = _styles.getFloat("margin-top", margin);
|
||||
float marginBottom = _styles.getFloat("margin-bottom", margin);
|
||||
|
||||
_boxes.back().inset(marginLeft, marginRight, marginTop, marginBottom);
|
||||
|
||||
_y = _boxes.back().top();
|
||||
}
|
||||
|
||||
void endPage()
|
||||
{
|
||||
_boxes.pop_back();
|
||||
delete _pPage;
|
||||
_pPage = 0;
|
||||
popStyle();
|
||||
}
|
||||
|
||||
void startSpan(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
if (!_pPage) throw Poco::IllegalStateException("missing <page> element");
|
||||
|
||||
StylePtr pStyle = pushStyle(attributes);
|
||||
|
||||
_text.clear();
|
||||
}
|
||||
|
||||
void endSpan()
|
||||
{
|
||||
std::string fontFamily = _styles.getString("font-family");
|
||||
float fontSize = _styles.getFloat("font-size");
|
||||
float lineHeight = _styles.getFloat("line-height");
|
||||
std::string textAlign = _styles.getString("text-align", "left");
|
||||
std::string fontStyle = _styles.getString("font-style", "normal");
|
||||
std::string fontWeight = _styles.getString("font-weight", "normal");
|
||||
std::string textTransform = _styles.getString("text-transform", "none");
|
||||
|
||||
_text = transform(_text, textTransform);
|
||||
_text = transcode(_text);
|
||||
|
||||
Font font = loadFont(fontFamily, fontStyle, fontWeight);
|
||||
_pPage->setFont(font, fontSize);
|
||||
|
||||
float width = static_cast<float>(font.textWidth(_text).width*fontSize / 1000);
|
||||
float height = static_cast<float>(font.upperHeight()*fontSize / 1000)*lineHeight;
|
||||
|
||||
float x = static_cast<float>(_styles.current()->getDouble("left", _styles.current()->getDouble("right", width) - width));
|
||||
float y = static_cast<float>(_styles.current()->getDouble("bottom", _styles.current()->getDouble("top", _y) - height));
|
||||
|
||||
if (textAlign == "center")
|
||||
x = (box().width() - width) / 2;
|
||||
else if (textAlign == "right")
|
||||
x = box().width() - width;
|
||||
|
||||
translateInBox(x, y);
|
||||
|
||||
_pPage->writeOnce(x, y, _text);
|
||||
|
||||
moveY(y);
|
||||
|
||||
popStyle();
|
||||
}
|
||||
|
||||
void startImg(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
if (!_pPage) throw Poco::IllegalStateException("missing <page> element");
|
||||
|
||||
StylePtr pStyle = pushStyle(attributes);
|
||||
|
||||
std::string path = attributes.getValue("src");
|
||||
Image image = loadImage(path);
|
||||
|
||||
float width = static_cast<float>(pStyle->getDouble("width", image.width()));
|
||||
float height = static_cast<float>(pStyle->getDouble("height", image.height()));
|
||||
|
||||
float scale = static_cast<float>(pStyle->getDouble("scale", 1.0));
|
||||
float scaleX = static_cast<float>(pStyle->getDouble("scale-x", scale));
|
||||
float scaleY = static_cast<float>(pStyle->getDouble("scale-y", scale));
|
||||
|
||||
width *= scaleX;
|
||||
height *= scaleY;
|
||||
|
||||
float x = static_cast<float>(_styles.current()->getDouble("left", _styles.current()->getDouble("right", width) - width));
|
||||
float y = static_cast<float>(_styles.current()->getDouble("bottom", _styles.current()->getDouble("top", _y) - height));
|
||||
|
||||
translateInBox(x, y);
|
||||
|
||||
_pPage->drawImage(image, x, y, width, height);
|
||||
|
||||
moveY(y);
|
||||
}
|
||||
|
||||
void endImg()
|
||||
{
|
||||
popStyle();
|
||||
}
|
||||
|
||||
void startTable(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
if (!_pPage) throw Poco::IllegalStateException("missing <page> element");
|
||||
|
||||
StylePtr pStyle = pushStyle(attributes);
|
||||
|
||||
_pTable = new Table(0, 0, attributes.getValue("name"));
|
||||
}
|
||||
|
||||
void endTable()
|
||||
{
|
||||
if (_pTable->rows() > 0)
|
||||
{
|
||||
std::string fontFamily = _styles.getString("font-family");
|
||||
float fontSize = _styles.getFloat("font-size");
|
||||
std::string fontStyle = _styles.getString("font-style", "normal");
|
||||
std::string fontWeight = _styles.getString("font-weight", "normal");
|
||||
|
||||
Font font = loadFont(fontFamily, fontStyle, fontWeight);
|
||||
|
||||
float lineHeight = static_cast<float>((font.ascent() - font.descent())*fontSize / 1000)*_styles.getFloat("line-height");
|
||||
|
||||
float width = static_cast<float>(_styles.current()->getDouble("width", box().width()));
|
||||
float height = static_cast<float>(_styles.current()->getDouble("height", _pTable->rows()*lineHeight));
|
||||
|
||||
float x = static_cast<float>(_styles.current()->getDouble("left", _styles.current()->getDouble("right", width) - width));
|
||||
float y = static_cast<float>(_styles.current()->getDouble("bottom", _styles.current()->getDouble("top", _y) - height) + height);
|
||||
y -= lineHeight;
|
||||
|
||||
translateInBox(x, y);
|
||||
|
||||
_pTable->draw(*_pPage, x, y, width, height);
|
||||
|
||||
y -= height - lineHeight;
|
||||
|
||||
moveY(y);
|
||||
}
|
||||
_pTable = 0;
|
||||
popStyle();
|
||||
}
|
||||
|
||||
void startTr(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
if (!_pTable) throw Poco::IllegalStateException("missing <table> element");
|
||||
|
||||
StylePtr pStyle = pushStyle(attributes);
|
||||
_row.clear();
|
||||
}
|
||||
|
||||
void endTr()
|
||||
{
|
||||
_pTable->addRow(_row);
|
||||
_row.clear();
|
||||
popStyle();
|
||||
}
|
||||
|
||||
void startTd(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
StylePtr pStyle = pushStyle(attributes);
|
||||
|
||||
_text.clear();
|
||||
}
|
||||
|
||||
void endTd()
|
||||
{
|
||||
AttributedString::Alignment align = AttributedString::ALIGN_LEFT;
|
||||
int style = AttributedString::STYLE_PLAIN;
|
||||
|
||||
|
||||
std::string fontFamily = _styles.getString("font-family");
|
||||
float fontSize = _styles.getFloat("font-size");
|
||||
std::string textAlign = _styles.getString("text-align", "left");
|
||||
std::string fontStyle = _styles.getString("font-style", "normal");
|
||||
std::string fontWeight = _styles.getString("font-weight", "normal");
|
||||
std::string textTransform = _styles.getString("text-transform", "none");
|
||||
std::string widthPct = _styles.getString("width", "");
|
||||
// solid only supported at this time
|
||||
bool borderAll = _styles.getString("border-style", "") == "solid";
|
||||
bool borderLeft = _styles.getString("border-left", "") == "solid";
|
||||
bool borderTop = _styles.getString("border-top", "") == "solid";
|
||||
bool borderRight = _styles.getString("border-right", "") == "solid";
|
||||
bool borderBottom = _styles.getString("border-bottom", "") == "solid";
|
||||
|
||||
_text = transform(_text, textTransform);
|
||||
_text = transcode(_text);
|
||||
|
||||
if (textAlign == "right")
|
||||
align = AttributedString::ALIGN_RIGHT;
|
||||
else if (textAlign == "left")
|
||||
align = AttributedString::ALIGN_LEFT;
|
||||
else if (textAlign == "center")
|
||||
align = AttributedString::ALIGN_CENTER;
|
||||
|
||||
if (fontStyle == "italic" || fontStyle == "oblique")
|
||||
style |= AttributedString::STYLE_ITALIC;
|
||||
|
||||
if (fontWeight == "bold")
|
||||
style |= AttributedString::STYLE_BOLD;
|
||||
|
||||
AttributedString content(_text, align, style);
|
||||
content.setAttribute(AttributedString::ATTR_SIZE, fontSize);
|
||||
|
||||
Cell::FontMapPtr pFontMap = new Cell::FontMap;
|
||||
std::string normalizedFontFamily(normalizeFontName(fontFamily));
|
||||
(*pFontMap)[AttributedString::STYLE_PLAIN] = normalizedFontFamily;
|
||||
(*pFontMap)[AttributedString::STYLE_BOLD] = boldFontName(normalizedFontFamily);
|
||||
(*pFontMap)[AttributedString::STYLE_ITALIC] = italicFontName(normalizedFontFamily);
|
||||
(*pFontMap)[AttributedString::STYLE_BOLD | AttributedString::STYLE_ITALIC] = boldItalicFontName(normalizedFontFamily);
|
||||
|
||||
int width = -1;
|
||||
if (!widthPct.empty())
|
||||
{
|
||||
if (*widthPct.rbegin() != '%')
|
||||
throw Poco::InvalidArgumentException("Only percentage widths supported for table cells.");
|
||||
else
|
||||
{
|
||||
widthPct.erase(widthPct.length() - 1);
|
||||
width = NumberParser::parse(widthPct);
|
||||
}
|
||||
}
|
||||
|
||||
Cell cell(content, pFontMap, _encoding, false, width);
|
||||
if (borderAll) cell.borderAll(true);
|
||||
if (borderLeft) cell.borderLeft(true);
|
||||
if (borderTop) cell.borderTop(true);
|
||||
if (borderRight) cell.borderRight(true);
|
||||
if (borderBottom) cell.borderBottom(true);
|
||||
_row.push_back(cell);
|
||||
|
||||
popStyle();
|
||||
}
|
||||
|
||||
void startHr(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
if (!_pPage) throw Poco::IllegalStateException("missing <page> element");
|
||||
|
||||
StylePtr pStyle = pushStyle(attributes);
|
||||
|
||||
float width = static_cast<float>(_styles.current()->getDouble("width", box().width()));
|
||||
float height = static_cast<float>(_styles.current()->getDouble("height", 0.2));
|
||||
|
||||
float x = static_cast<float>(_styles.current()->getDouble("left", _styles.current()->getDouble("right", width) - width));
|
||||
float y = static_cast<float>(_styles.current()->getDouble("bottom", _styles.current()->getDouble("top", _y) - height));
|
||||
|
||||
translateInBox(x, y);
|
||||
|
||||
_pPage->moveTo(x, y);
|
||||
_pPage->lineTo(x + width, y);
|
||||
_pPage->stroke();
|
||||
|
||||
moveY(y);
|
||||
}
|
||||
|
||||
void endHr()
|
||||
{
|
||||
popStyle();
|
||||
}
|
||||
|
||||
// DocumentHandler
|
||||
void startDocument()
|
||||
{
|
||||
}
|
||||
|
||||
void endDocument()
|
||||
{
|
||||
}
|
||||
|
||||
void startElement(const Poco::XML::XMLString& uri, const Poco::XML::XMLString& localName, const Poco::XML::XMLString& qname, const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
if (localName == "document")
|
||||
startDoc(attributes);
|
||||
else if (localName == "page")
|
||||
startPage(attributes);
|
||||
else if (localName == "span")
|
||||
startSpan(attributes);
|
||||
else if (localName == "img")
|
||||
startImg(attributes);
|
||||
else if (localName == "table")
|
||||
startTable(attributes);
|
||||
else if (localName == "tr")
|
||||
startTr(attributes);
|
||||
else if (localName == "td")
|
||||
startTd(attributes);
|
||||
else if (localName == "hr")
|
||||
startHr(attributes);
|
||||
}
|
||||
|
||||
void endElement(const Poco::XML::XMLString& uri, const Poco::XML::XMLString& localName, const Poco::XML::XMLString& qname)
|
||||
{
|
||||
if (localName == "document")
|
||||
endDoc();
|
||||
else if (localName == "page")
|
||||
endPage();
|
||||
else if (localName == "span")
|
||||
endSpan();
|
||||
else if (localName == "img")
|
||||
endImg();
|
||||
else if (localName == "table")
|
||||
endTable();
|
||||
else if (localName == "tr")
|
||||
endTr();
|
||||
else if (localName == "td")
|
||||
endTd();
|
||||
else if (localName == "hr")
|
||||
endHr();
|
||||
}
|
||||
|
||||
void characters(const Poco::XML::XMLChar ch[], int start, int length)
|
||||
{
|
||||
_text.append(ch + start, length);
|
||||
}
|
||||
|
||||
protected:
|
||||
StylePtr pushStyle(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
StylePtr pStyle = parseStyle(attributes);
|
||||
if (_boxes.size() > 0)
|
||||
{
|
||||
pStyle->setDouble("box.width", box().width());
|
||||
pStyle->setDouble("box.height", box().height());
|
||||
}
|
||||
_styles.push(pStyle);
|
||||
return pStyle;
|
||||
}
|
||||
|
||||
void popStyle()
|
||||
{
|
||||
_styles.pop();
|
||||
}
|
||||
|
||||
StylePtr parseStyle(const Poco::XML::Attributes& attributes)
|
||||
{
|
||||
return parseStyle(attributes.getValue("style"));
|
||||
}
|
||||
|
||||
StylePtr parseStyle(const std::string& style) const
|
||||
{
|
||||
std::string props = Poco::translate(style, ";", "\n");
|
||||
std::istringstream istr(props);
|
||||
return new Poco::Util::PropertyFileConfiguration(istr);
|
||||
}
|
||||
|
||||
static Page::Size parsePageSize(const std::string& size)
|
||||
{
|
||||
using Poco::icompare;
|
||||
if (icompare(size, "letter") == 0)
|
||||
return Page::PAGE_SIZE_LETTER;
|
||||
else if (icompare(size, "legal") == 0)
|
||||
return Page::PAGE_SIZE_LEGAL;
|
||||
else if (icompare(size, "a3") == 0)
|
||||
return Page::PAGE_SIZE_A3;
|
||||
else if (icompare(size, "a4") == 0)
|
||||
return Page::PAGE_SIZE_A4;
|
||||
else if (icompare(size, "a5") == 0)
|
||||
return Page::PAGE_SIZE_A5;
|
||||
else if (icompare(size, "b4") == 0)
|
||||
return Page::PAGE_SIZE_B4;
|
||||
else if (icompare(size, "b5") == 0)
|
||||
return Page::PAGE_SIZE_B5;
|
||||
else if (icompare(size, "executive") == 0)
|
||||
return Page::PAGE_SIZE_EXECUTIVE;
|
||||
else if (icompare(size, "us4x6") == 0)
|
||||
return Page::PAGE_SIZE_US4x6;
|
||||
else if (icompare(size, "us4x8") == 0)
|
||||
return Page::PAGE_SIZE_US4x8;
|
||||
else if (icompare(size, "us5x7") == 0)
|
||||
return Page::PAGE_SIZE_US5x7;
|
||||
else if (icompare(size, "comm10") == 0)
|
||||
return Page::PAGE_SIZE_COMM10;
|
||||
else throw Poco::InvalidArgumentException("size", size);
|
||||
}
|
||||
|
||||
static Page::Orientation parseOrientation(const std::string& orientation)
|
||||
{
|
||||
if (icompare(orientation, "portrait") == 0)
|
||||
return Page::ORIENTATION_PORTRAIT;
|
||||
else if (icompare(orientation, "landscape") == 0)
|
||||
return Page::ORIENTATION_LANDSCAPE;
|
||||
else throw Poco::InvalidArgumentException("orientation", orientation);
|
||||
}
|
||||
|
||||
std::string normalizeFontName(const std::string& fontFamily)
|
||||
{
|
||||
poco_assert(fontFamily.size());
|
||||
|
||||
std::string fontName = toLower(fontFamily);
|
||||
fontName[0] = Poco::Ascii::toUpper(fontName[0]);
|
||||
return fontName;
|
||||
}
|
||||
|
||||
Font loadFont(const std::string& fontFamily, const std::string& fontStyle, const std::string& fontWeight)
|
||||
{
|
||||
poco_assert(_pDocument);
|
||||
|
||||
std::string normalizedFontFamily = normalizeFontName(fontFamily);
|
||||
std::string fontName;
|
||||
if (fontStyle == "italic" || fontStyle == "oblique")
|
||||
{
|
||||
if (fontWeight == "bold")
|
||||
fontName = boldItalicFontName(normalizedFontFamily);
|
||||
else
|
||||
fontName = italicFontName(normalizedFontFamily);
|
||||
} else if (fontWeight == "bold")
|
||||
{
|
||||
fontName = boldFontName(normalizedFontFamily);
|
||||
} else
|
||||
{
|
||||
fontName = normalizedFontFamily;
|
||||
}
|
||||
return _pDocument->font(fontName, _encoding);
|
||||
}
|
||||
|
||||
std::string boldFontName(const std::string& fontFamily)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _pDocument->font(fontFamily + "-Bold", _encoding).name();
|
||||
} catch (...)
|
||||
{
|
||||
}
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
std::string italicFontName(const std::string& fontFamily)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _pDocument->font(fontFamily + "-Oblique", _encoding).name();
|
||||
} catch (...)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
return _pDocument->font(fontFamily + "-Italic", _encoding).name();
|
||||
} catch (...)
|
||||
{
|
||||
}
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
std::string boldItalicFontName(const std::string& fontFamily)
|
||||
{
|
||||
try
|
||||
{
|
||||
return _pDocument->font(fontFamily + "-BoldOblique", _encoding).name();
|
||||
} catch (...)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
Font font = _pDocument->font(fontFamily + "-BoldItalic", _encoding);
|
||||
} catch (...)
|
||||
{
|
||||
}
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
Image loadImage(const std::string& path)
|
||||
{
|
||||
Poco::Path p(_base);
|
||||
p.resolve(path);
|
||||
if (Poco::icompare(p.getExtension(), "jpg") == 0 || icompare(p.getExtension(), "jpeg") == 0)
|
||||
return _pDocument->loadJPEGImage(p.toString());
|
||||
else if (Poco::icompare(p.getExtension(), "png") == 0)
|
||||
return _pDocument->loadPNGImage(p.toString());
|
||||
else
|
||||
throw Poco::InvalidArgumentException("cannot determine image type", path);
|
||||
}
|
||||
|
||||
void translateInBox(float& x, float& y)
|
||||
{
|
||||
if (x < 0)
|
||||
x = box().right() + x;
|
||||
else
|
||||
x += box().left();
|
||||
|
||||
if (y < 0)
|
||||
y = box().top() + y;
|
||||
else
|
||||
y += box().bottom();
|
||||
}
|
||||
|
||||
void moveY(float y)
|
||||
{
|
||||
float padding = _styles.getFloat("padding", 0);
|
||||
float newY = y - padding;
|
||||
newY -= box().bottom();
|
||||
|
||||
_y = std::min(_y, newY);
|
||||
}
|
||||
|
||||
const Box& box() const
|
||||
{
|
||||
poco_assert(_boxes.size() > 0);
|
||||
return _boxes.back();
|
||||
}
|
||||
|
||||
std::string transcode(const std::string& text)
|
||||
{
|
||||
std::string result;
|
||||
Poco::UTF8Encoding inEncoding;
|
||||
Poco::TextEncoding& outEncoding = Poco::TextEncoding::byName(mapEncoding(_encoding));
|
||||
Poco::TextConverter converter(inEncoding, outEncoding);
|
||||
converter.convert(text, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::string mapEncoding(const std::string& encoding)
|
||||
{
|
||||
if (encoding == "WinAnsiEncoding")
|
||||
return "Latin-1";
|
||||
else if (encoding == "ISO8859-2")
|
||||
return "Latin-2";
|
||||
else if (encoding == "ISO8859-15")
|
||||
return "Latin-9";
|
||||
else if (encoding == "CP1250")
|
||||
return "CP1250";
|
||||
else if (encoding == "CP1251")
|
||||
return "CP1251";
|
||||
else if (encoding == "CP1252")
|
||||
return "CP1252";
|
||||
else
|
||||
throw Poco::InvalidArgumentException("PDF Document encoding not supported", encoding);
|
||||
}
|
||||
|
||||
static std::string transform(const std::string& text, const std::string& trans)
|
||||
{
|
||||
if (trans == "uppercase")
|
||||
return UTF8::toUpper(text);
|
||||
else if (trans == "lowercase")
|
||||
return UTF8::toLower(text);
|
||||
else
|
||||
return text;
|
||||
}
|
||||
|
||||
private:
|
||||
Poco::Path _base;
|
||||
std::string _encoding;
|
||||
Document* _pDocument;
|
||||
Page* _pPage;
|
||||
Table::Ptr _pTable;
|
||||
TableRow _row;
|
||||
StackedConfiguration _styles;
|
||||
std::vector<Box> _boxes;
|
||||
std::string _size;
|
||||
std::string _orientation;
|
||||
std::string _text;
|
||||
float _y;
|
||||
};
|
||||
|
||||
|
||||
XMLTemplate::XMLTemplate(std::istream& xmlStream, const std::string& base) :
|
||||
_base(base),
|
||||
_pDocument(0)
|
||||
{
|
||||
load(xmlStream);
|
||||
}
|
||||
|
||||
|
||||
XMLTemplate::XMLTemplate(const std::string& path) :
|
||||
_base(path),
|
||||
_pDocument(0)
|
||||
{
|
||||
Poco::FileInputStream xmlStream(path);
|
||||
load(xmlStream);
|
||||
}
|
||||
|
||||
|
||||
XMLTemplate::~XMLTemplate()
|
||||
{
|
||||
delete _pDocument;
|
||||
}
|
||||
|
||||
|
||||
void XMLTemplate::load(std::istream& xmlStream)
|
||||
{
|
||||
Poco::XML::InputSource xmlSource(xmlStream);
|
||||
Poco::XML::SAXParser parser;
|
||||
TemplateHandler handler(_base);
|
||||
parser.setContentHandler(&handler);
|
||||
parser.setFeature(Poco::XML::XMLReader::FEATURE_NAMESPACES, true);
|
||||
parser.setFeature(Poco::XML::XMLReader::FEATURE_NAMESPACE_PREFIXES, true);
|
||||
parser.parse(&xmlSource);
|
||||
|
||||
_pDocument = handler.document();
|
||||
}
|
||||
|
||||
|
||||
void XMLTemplate::create(const std::string& path)
|
||||
{
|
||||
_pDocument->save(path);
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::PDF
|
||||
Vendored
+149
@@ -0,0 +1,149 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-2004 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id$ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
#define BASE 65521UL /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* use NO_DIVIDE if your processor does not do division in hardware */
|
||||
#ifdef NO_DIVIDE
|
||||
# define MOD(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 16)) a -= (BASE << 16); \
|
||||
if (a >= (BASE << 15)) a -= (BASE << 15); \
|
||||
if (a >= (BASE << 14)) a -= (BASE << 14); \
|
||||
if (a >= (BASE << 13)) a -= (BASE << 13); \
|
||||
if (a >= (BASE << 12)) a -= (BASE << 12); \
|
||||
if (a >= (BASE << 11)) a -= (BASE << 11); \
|
||||
if (a >= (BASE << 10)) a -= (BASE << 10); \
|
||||
if (a >= (BASE << 9)) a -= (BASE << 9); \
|
||||
if (a >= (BASE << 8)) a -= (BASE << 8); \
|
||||
if (a >= (BASE << 7)) a -= (BASE << 7); \
|
||||
if (a >= (BASE << 6)) a -= (BASE << 6); \
|
||||
if (a >= (BASE << 5)) a -= (BASE << 5); \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
# define MOD4(a) \
|
||||
do { \
|
||||
if (a >= (BASE << 4)) a -= (BASE << 4); \
|
||||
if (a >= (BASE << 3)) a -= (BASE << 3); \
|
||||
if (a >= (BASE << 2)) a -= (BASE << 2); \
|
||||
if (a >= (BASE << 1)) a -= (BASE << 1); \
|
||||
if (a >= BASE) a -= BASE; \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOD(a) a %= BASE
|
||||
# define MOD4(a) a %= BASE
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long sum2;
|
||||
unsigned n;
|
||||
|
||||
/* split Adler-32 into component sums */
|
||||
sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
adler += buf[0];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (buf == Z_NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
MOD4(sum2); /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
DO16(buf); /* 16 sums unrolled */
|
||||
buf += 16;
|
||||
} while (--n);
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
}
|
||||
while (len--) {
|
||||
adler += *buf++;
|
||||
sum2 += adler;
|
||||
}
|
||||
MOD(adler);
|
||||
MOD(sum2);
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
|
||||
uLong adler1;
|
||||
uLong adler2;
|
||||
z_off_t len2;
|
||||
{
|
||||
unsigned long sum1;
|
||||
unsigned long sum2;
|
||||
unsigned rem;
|
||||
|
||||
/* the derivation of this formula is left as an exercise for the reader */
|
||||
rem = (unsigned)(len2 % BASE);
|
||||
sum1 = adler1 & 0xffff;
|
||||
sum2 = rem * sum1;
|
||||
MOD(sum2);
|
||||
sum1 += (adler2 & 0xffff) + BASE - 1;
|
||||
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
|
||||
if (sum1 > BASE) sum1 -= BASE;
|
||||
if (sum1 > BASE) sum1 -= BASE;
|
||||
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
|
||||
if (sum2 > BASE) sum2 -= BASE;
|
||||
return sum1 | (sum2 << 16);
|
||||
}
|
||||
Vendored
+79
@@ -0,0 +1,79 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-2003 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* @(#) $Id: //poco/Main/Foundation/src/compress.c#8 $ */
|
||||
|
||||
#define ZLIB_INTERNAL
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. The level
|
||||
parameter has the same meaning as in deflateInit. sourceLen is the byte
|
||||
length of the source buffer. Upon entry, destLen is the total size of the
|
||||
destination buffer, which must be at least 0.1% larger than sourceLen plus
|
||||
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
|
||||
|
||||
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
||||
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
|
||||
Z_STREAM_ERROR if the level parameter is invalid.
|
||||
*/
|
||||
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
int level;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, level);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
*/
|
||||
int ZEXPORT compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
If the default memLevel or windowBits for deflateInit() is changed, then
|
||||
this function needs to be updated.
|
||||
*/
|
||||
uLong ZEXPORT compressBound (sourceLen)
|
||||
uLong sourceLen;
|
||||
{
|
||||
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
|
||||
}
|
||||
Vendored
+423
@@ -0,0 +1,423 @@
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-2005 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*
|
||||
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
|
||||
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
|
||||
* tables for updating the shift register in one step with three exclusive-ors
|
||||
* instead of four steps with four exclusive-ors. This results in about a
|
||||
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
|
||||
*/
|
||||
|
||||
/* @(#) $Id: //poco/Main/Foundation/src/crc32.c#8 $ */
|
||||
|
||||
/*
|
||||
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
|
||||
protection on the static variables used to control the first-use generation
|
||||
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
|
||||
first call get_crc_table() to initialize the tables before allowing more than
|
||||
one thread to use crc32().
|
||||
*/
|
||||
|
||||
#ifdef MAKECRCH
|
||||
# include <stdio.h>
|
||||
# ifndef DYNAMIC_CRC_TABLE
|
||||
# define DYNAMIC_CRC_TABLE
|
||||
# endif /* !DYNAMIC_CRC_TABLE */
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#include "zutil.h" /* for STDC and FAR definitions */
|
||||
|
||||
#define local static
|
||||
|
||||
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
|
||||
#ifndef NOBYFOUR
|
||||
# ifdef STDC /* need ANSI C limits.h to determine sizes */
|
||||
# include <limits.h>
|
||||
# define BYFOUR
|
||||
# if (UINT_MAX == 0xffffffffUL)
|
||||
typedef unsigned int u4;
|
||||
# else
|
||||
# if (ULONG_MAX == 0xffffffffUL)
|
||||
typedef unsigned long u4;
|
||||
# else
|
||||
# if (USHRT_MAX == 0xffffffffUL)
|
||||
typedef unsigned short u4;
|
||||
# else
|
||||
# undef BYFOUR /* can't find a four-byte integer type! */
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif /* STDC */
|
||||
#endif /* !NOBYFOUR */
|
||||
|
||||
/* Definitions for doing the crc four data bytes at a time. */
|
||||
#ifdef BYFOUR
|
||||
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
|
||||
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
|
||||
local unsigned long crc32_little OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
local unsigned long crc32_big OF((unsigned long,
|
||||
const unsigned char FAR *, unsigned));
|
||||
# define TBLS 8
|
||||
#else
|
||||
# define TBLS 1
|
||||
#endif /* BYFOUR */
|
||||
|
||||
/* Local functions for crc concatenation */
|
||||
local unsigned long gf2_matrix_times OF((unsigned long *mat,
|
||||
unsigned long vec));
|
||||
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local volatile int crc_table_empty = 1;
|
||||
local unsigned long FAR crc_table[TBLS][256];
|
||||
local void make_crc_table OF((void));
|
||||
#ifdef MAKECRCH
|
||||
local void write_table OF((FILE *, const unsigned long FAR *));
|
||||
#endif /* MAKECRCH */
|
||||
/*
|
||||
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||
|
||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||
with the lowest powers in the most significant bit. Then adding polynomials
|
||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||
one. If we call the above polynomial p, and represent a byte as the
|
||||
polynomial q, also with the lowest power in the most significant bit (so the
|
||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||
where a mod b means the remainder after dividing a by b.
|
||||
|
||||
This calculation is done using the shift-register method of multiplying and
|
||||
taking the remainder. The register is initialized to zero, and for each
|
||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||
out is a one). We start with the highest power (least significant bit) of
|
||||
q and repeat for all eight bits of q.
|
||||
|
||||
The first table is simply the CRC of all possible eight bit values. This is
|
||||
all the information needed to generate CRCs on data a byte at a time for all
|
||||
combinations of CRC register values and incoming bytes. The remaining tables
|
||||
allow for word-at-a-time CRC calculation for both big-endian and little-
|
||||
endian machines, where a word is four bytes.
|
||||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
unsigned long c;
|
||||
int n, k;
|
||||
unsigned long poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static volatile int first = 1; /* flag to limit concurrent making */
|
||||
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
||||
/* See if another task is already doing this (not thread-safe, but better
|
||||
than nothing -- significantly reduces duration of vulnerability in
|
||||
case the advice about DYNAMIC_CRC_TABLE is ignored) */
|
||||
if (first) {
|
||||
first = 0;
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
|
||||
poly = 0UL;
|
||||
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
|
||||
poly |= 1UL << (31 - p[n]);
|
||||
|
||||
/* generate a crc for every 8-bit value */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = (unsigned long)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[0][n] = c;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
/* generate crc for each value followed by one, two, and three zeros,
|
||||
and then the byte reversal of those as well as the first table */
|
||||
for (n = 0; n < 256; n++) {
|
||||
c = crc_table[0][n];
|
||||
crc_table[4][n] = REV(c);
|
||||
for (k = 1; k < 4; k++) {
|
||||
c = crc_table[0][c & 0xff] ^ (c >> 8);
|
||||
crc_table[k][n] = c;
|
||||
crc_table[k + 4][n] = REV(c);
|
||||
}
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
|
||||
crc_table_empty = 0;
|
||||
}
|
||||
else { /* not first */
|
||||
/* wait for the other guy to finish (not efficient, but rare) */
|
||||
while (crc_table_empty)
|
||||
;
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
/* write out CRC tables to crc32.h */
|
||||
{
|
||||
FILE *out;
|
||||
|
||||
out = fopen("crc32.h", "w");
|
||||
if (out == NULL) return;
|
||||
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
|
||||
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
|
||||
fprintf(out, "local const unsigned long FAR ");
|
||||
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
|
||||
write_table(out, crc_table[0]);
|
||||
# ifdef BYFOUR
|
||||
fprintf(out, "#ifdef BYFOUR\n");
|
||||
for (k = 1; k < 8; k++) {
|
||||
fprintf(out, " },\n {\n");
|
||||
write_table(out, crc_table[k]);
|
||||
}
|
||||
fprintf(out, "#endif\n");
|
||||
# endif /* BYFOUR */
|
||||
fprintf(out, " }\n};\n");
|
||||
fclose(out);
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
}
|
||||
|
||||
#ifdef MAKECRCH
|
||||
local void write_table(out, table)
|
||||
FILE *out;
|
||||
const unsigned long FAR *table;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
|
||||
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
|
||||
}
|
||||
#endif /* MAKECRCH */
|
||||
|
||||
#else /* !DYNAMIC_CRC_TABLE */
|
||||
/* ========================================================================
|
||||
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
|
||||
*/
|
||||
#include "crc32.h"
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
const unsigned long FAR * ZEXPORT get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
return (const unsigned long FAR *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
|
||||
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
|
||||
|
||||
/* ========================================================================= */
|
||||
unsigned long ZEXPORT crc32(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0UL;
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif /* DYNAMIC_CRC_TABLE */
|
||||
|
||||
#ifdef BYFOUR
|
||||
if (sizeof(void *) == sizeof(ptrdiff_t)) {
|
||||
u4 endian;
|
||||
|
||||
endian = 1;
|
||||
if (*((unsigned char *)(&endian)))
|
||||
return crc32_little(crc, buf, len);
|
||||
else
|
||||
return crc32_big(crc, buf, len);
|
||||
}
|
||||
#endif /* BYFOUR */
|
||||
crc = crc ^ 0xffffffffUL;
|
||||
while (len >= 8) {
|
||||
DO8;
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1;
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffUL;
|
||||
}
|
||||
|
||||
#ifdef BYFOUR
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOLIT4 c ^= *buf4++; \
|
||||
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
|
||||
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
|
||||
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_little(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
|
||||
c = (u4)crc;
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
while (len >= 32) {
|
||||
DOLIT32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOLIT4;
|
||||
len -= 4;
|
||||
}
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)c;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DOBIG4 c ^= *++buf4; \
|
||||
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
|
||||
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
|
||||
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long crc32_big(crc, buf, len)
|
||||
unsigned long crc;
|
||||
const unsigned char FAR *buf;
|
||||
unsigned len;
|
||||
{
|
||||
register u4 c;
|
||||
register const u4 FAR *buf4;
|
||||
|
||||
c = REV((u4)crc);
|
||||
c = ~c;
|
||||
while (len && ((ptrdiff_t)buf & 3)) {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
len--;
|
||||
}
|
||||
|
||||
buf4 = (const u4 FAR *)(const void FAR *)buf;
|
||||
buf4--;
|
||||
while (len >= 32) {
|
||||
DOBIG32;
|
||||
len -= 32;
|
||||
}
|
||||
while (len >= 4) {
|
||||
DOBIG4;
|
||||
len -= 4;
|
||||
}
|
||||
buf4++;
|
||||
buf = (const unsigned char FAR *)buf4;
|
||||
|
||||
if (len) do {
|
||||
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
|
||||
} while (--len);
|
||||
c = ~c;
|
||||
return (unsigned long)(REV(c));
|
||||
}
|
||||
|
||||
#endif /* BYFOUR */
|
||||
|
||||
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
|
||||
|
||||
/* ========================================================================= */
|
||||
local unsigned long gf2_matrix_times(mat, vec)
|
||||
unsigned long *mat;
|
||||
unsigned long vec;
|
||||
{
|
||||
unsigned long sum;
|
||||
|
||||
sum = 0;
|
||||
while (vec) {
|
||||
if (vec & 1)
|
||||
sum ^= *mat;
|
||||
vec >>= 1;
|
||||
mat++;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
local void gf2_matrix_square(square, mat)
|
||||
unsigned long *square;
|
||||
unsigned long *mat;
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < GF2_DIM; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
|
||||
uLong crc1;
|
||||
uLong crc2;
|
||||
z_off_t len2;
|
||||
{
|
||||
int n;
|
||||
unsigned long row;
|
||||
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
|
||||
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
|
||||
|
||||
/* degenerate case */
|
||||
if (len2 == 0)
|
||||
return crc1;
|
||||
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = 0xedb88320L; /* CRC-32 polynomial */
|
||||
row = 1;
|
||||
for (n = 1; n < GF2_DIM; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
|
||||
/* put operator for two zero bits in even */
|
||||
gf2_matrix_square(even, odd);
|
||||
|
||||
/* put operator for four zero bits in odd */
|
||||
gf2_matrix_square(odd, even);
|
||||
|
||||
/* apply len2 zeros to crc1 (first square will put the operator for one
|
||||
zero byte, eight zero bits, in even) */
|
||||
do {
|
||||
/* apply zeros operator for this bit of len2 */
|
||||
gf2_matrix_square(even, odd);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(even, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
if (len2 == 0)
|
||||
break;
|
||||
|
||||
/* another iteration of the loop with odd and even swapped */
|
||||
gf2_matrix_square(odd, even);
|
||||
if (len2 & 1)
|
||||
crc1 = gf2_matrix_times(odd, crc1);
|
||||
len2 >>= 1;
|
||||
|
||||
/* if no more bits set, then done */
|
||||
} while (len2 != 0);
|
||||
|
||||
/* return combined crc */
|
||||
crc1 ^= crc2;
|
||||
return crc1;
|
||||
}
|
||||
Vendored
+1736
File diff suppressed because it is too large
Load Diff
Vendored
+1026
File diff suppressed because it is too large
Load Diff
Vendored
+235
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_annotation.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_info.h"
|
||||
#include "hpdf_3dmeasure.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*------ HPDF_3DMeasure -----------------------------------------------------*/
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_AddPoint3D(HPDF_Dict dict, const char* key, HPDF_Point3D point)
|
||||
{
|
||||
HPDF_Array array;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
array = HPDF_Array_New (dict->mmgr);
|
||||
if (!array)
|
||||
return HPDF_Error_GetCode ( dict->error);
|
||||
|
||||
if (HPDF_Dict_Add (dict, key, array) != HPDF_OK)
|
||||
return HPDF_Error_GetCode ( dict->error);
|
||||
|
||||
ret += HPDF_Array_AddReal(array, point.x);
|
||||
ret += HPDF_Array_AddReal(array, point.y);
|
||||
ret += HPDF_Array_AddReal(array, point.z);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
HPDF_3DMeasure
|
||||
HPDF_3DC3DMeasure_New(HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref,
|
||||
HPDF_Point3D firstanchorpoint,
|
||||
HPDF_Point3D textanchorpoint
|
||||
)
|
||||
{
|
||||
HPDF_3DMeasure measure;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
|
||||
HPDF_PTRACE((" HPDF_3DC3DMeasure_New\n"));
|
||||
|
||||
measure = HPDF_Dict_New (mmgr);
|
||||
if (!measure)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Xref_Add (xref, measure) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
ret += HPDF_Dict_AddPoint3D(measure, "A1", firstanchorpoint);
|
||||
ret += HPDF_Dict_AddPoint3D(measure, "TP", textanchorpoint);
|
||||
|
||||
ret += HPDF_Dict_AddName (measure, "Type", "3DMeasure");
|
||||
ret += HPDF_Dict_AddName (measure, "Subtype", "3DC");
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return measure;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_3DMeasure_SetColor(HPDF_3DMeasure measure,
|
||||
HPDF_RGBColor color)
|
||||
{
|
||||
HPDF_Array array;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
array = HPDF_Array_New (measure->mmgr);
|
||||
if (!array)
|
||||
return HPDF_Error_GetCode (measure->error);
|
||||
|
||||
ret = HPDF_Dict_Add (measure, "C", array);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
ret += HPDF_Array_AddName(array, "DeviceRGB");
|
||||
ret += HPDF_Array_AddReal(array, color.r);
|
||||
ret += HPDF_Array_AddReal(array, color.g);
|
||||
ret += HPDF_Array_AddReal(array, color.b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_3DMeasure_SetTextSize(HPDF_3DMeasure measure,
|
||||
HPDF_REAL textsize)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
ret = HPDF_Dict_AddReal(measure, "TS", textsize);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_3DMeasure_SetName(HPDF_3DMeasure measure,
|
||||
const char* name)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_String s;
|
||||
|
||||
s = HPDF_String_New (measure->mmgr, name, 0);
|
||||
if (!s)
|
||||
return HPDF_Error_GetCode ( s->error);
|
||||
|
||||
ret = HPDF_Dict_Add(measure, "TRL", s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_3DC3DMeasure_SetTextBoxSize(HPDF_3DMeasure measure,
|
||||
HPDF_INT32 x,
|
||||
HPDF_INT32 y)
|
||||
{
|
||||
HPDF_Array array;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
array = HPDF_Array_New (measure->mmgr);
|
||||
if (!array)
|
||||
return HPDF_Error_GetCode (measure->error);
|
||||
|
||||
ret = HPDF_Dict_Add (measure, "TB", array);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
ret += HPDF_Array_AddNumber(array, x);
|
||||
ret += HPDF_Array_AddNumber(array, y);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_3DC3DMeasure_SetText(HPDF_3DMeasure measure,
|
||||
const char* text,
|
||||
HPDF_Encoder encoder)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_String s;
|
||||
|
||||
s = HPDF_String_New (measure->mmgr, text, encoder);
|
||||
if (!s)
|
||||
return HPDF_Error_GetCode ( s->error);
|
||||
|
||||
ret = HPDF_Dict_Add(measure, "UT", s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_3DC3DMeasure_SetProjectionAnotation(HPDF_3DMeasure measure,
|
||||
HPDF_Annotation projectionanotation)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
ret = HPDF_Dict_Add(measure, "S", projectionanotation);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_3DMeasure
|
||||
HPDF_PD33DMeasure_New(HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref,
|
||||
HPDF_Point3D annotationPlaneNormal,
|
||||
HPDF_Point3D firstAnchorPoint,
|
||||
HPDF_Point3D secondAnchorPoint,
|
||||
HPDF_Point3D leaderLinesDirection,
|
||||
HPDF_Point3D measurementValuePoint,
|
||||
HPDF_Point3D textYDirection,
|
||||
HPDF_REAL value,
|
||||
const char* unitsString
|
||||
)
|
||||
{
|
||||
HPDF_3DMeasure measure;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_String s;
|
||||
|
||||
HPDF_PTRACE((" HPDF_3DC3DMeasure_New\n"));
|
||||
|
||||
measure = HPDF_Dict_New (mmgr);
|
||||
if (!measure)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Xref_Add (xref, measure) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
ret += HPDF_Dict_AddPoint3D(measure, "AP", annotationPlaneNormal);
|
||||
ret += HPDF_Dict_AddPoint3D(measure, "A1", firstAnchorPoint);
|
||||
ret += HPDF_Dict_AddPoint3D(measure, "A2", secondAnchorPoint);
|
||||
ret += HPDF_Dict_AddPoint3D(measure, "D1", leaderLinesDirection);
|
||||
ret += HPDF_Dict_AddPoint3D(measure, "TP", measurementValuePoint);
|
||||
ret += HPDF_Dict_AddPoint3D(measure, "TY", textYDirection);
|
||||
|
||||
ret += HPDF_Dict_AddReal(measure, "V", value);
|
||||
|
||||
s = HPDF_String_New (measure->mmgr, unitsString, 0);
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
ret = HPDF_Dict_Add(measure, "U", s);
|
||||
|
||||
ret += HPDF_Dict_AddName (measure, "Type", "3DMeasure");
|
||||
ret += HPDF_Dict_AddName (measure, "Subtype", "PD3");
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return measure;
|
||||
}
|
||||
|
||||
+1166
File diff suppressed because it is too large
Load Diff
Vendored
+354
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_array.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
HPDF_Array
|
||||
HPDF_Array_New (HPDF_MMgr mmgr)
|
||||
{
|
||||
HPDF_Array obj;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_New\n"));
|
||||
|
||||
obj = HPDF_GetMem (mmgr, sizeof(HPDF_Array_Rec));
|
||||
if (obj) {
|
||||
HPDF_MemSet (obj, 0, sizeof(HPDF_Array_Rec));
|
||||
obj->header.obj_class = HPDF_OCLASS_ARRAY;
|
||||
obj->mmgr = mmgr;
|
||||
obj->error = mmgr->error;
|
||||
obj->list = HPDF_List_New (mmgr, HPDF_DEF_ITEMS_PER_BLOCK);
|
||||
if (!obj->list) {
|
||||
HPDF_FreeMem (mmgr, obj);
|
||||
obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Array
|
||||
HPDF_Box_Array_New (HPDF_MMgr mmgr,
|
||||
HPDF_Box box)
|
||||
{
|
||||
HPDF_Array obj;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Box_Array_New\n"));
|
||||
|
||||
obj = HPDF_Array_New (mmgr);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
ret += HPDF_Array_Add (obj, HPDF_Real_New (mmgr, box.left));
|
||||
ret += HPDF_Array_Add (obj, HPDF_Real_New (mmgr, box.bottom));
|
||||
ret += HPDF_Array_Add (obj, HPDF_Real_New (mmgr, box.right));
|
||||
ret += HPDF_Array_Add (obj, HPDF_Real_New (mmgr, box.top));
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Array_Free (HPDF_Array array)
|
||||
{
|
||||
if (!array)
|
||||
return;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_Free\n"));
|
||||
|
||||
HPDF_Array_Clear (array);
|
||||
|
||||
HPDF_List_Free (array->list);
|
||||
|
||||
array->header.obj_class = 0;
|
||||
|
||||
HPDF_FreeMem (array->mmgr, array);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Array_Write (HPDF_Array array,
|
||||
HPDF_Stream stream,
|
||||
HPDF_Encrypt e)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_Write\n"));
|
||||
|
||||
ret = HPDF_Stream_WriteStr (stream, "[ ");
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < array->list->count; i++) {
|
||||
void * element = HPDF_List_ItemAt (array->list, i);
|
||||
|
||||
ret = HPDF_Obj_Write (element, stream, e);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
ret = HPDF_Stream_WriteChar (stream, ' ');
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Stream_WriteChar (stream, ']');
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Array_AddNumber (HPDF_Array array,
|
||||
HPDF_INT32 value)
|
||||
{
|
||||
HPDF_Number n = HPDF_Number_New (array->mmgr, value);
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_AddNumber\n"));
|
||||
|
||||
if (!n)
|
||||
return HPDF_Error_GetCode (array->error);
|
||||
else
|
||||
return HPDF_Array_Add (array, n);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Array_AddReal (HPDF_Array array,
|
||||
HPDF_REAL value)
|
||||
{
|
||||
HPDF_Real r = HPDF_Real_New (array->mmgr, value);
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_AddReal\n"));
|
||||
|
||||
if (!r)
|
||||
return HPDF_Error_GetCode (array->error);
|
||||
else
|
||||
return HPDF_Array_Add (array, r);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Array_AddName (HPDF_Array array,
|
||||
const char *value)
|
||||
{
|
||||
HPDF_Name n = HPDF_Name_New (array->mmgr, value);
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_AddName\n"));
|
||||
|
||||
if (!n)
|
||||
return HPDF_Error_GetCode (array->error);
|
||||
else
|
||||
return HPDF_Array_Add (array, n);
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Array_Add (HPDF_Array array,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_Obj_Header *header;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_Add\n"));
|
||||
|
||||
if (!obj) {
|
||||
if (HPDF_Error_GetCode (array->error) == HPDF_OK)
|
||||
return HPDF_SetError (array->error, HPDF_INVALID_OBJECT, 0);
|
||||
else
|
||||
return HPDF_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_DIRECT)
|
||||
return HPDF_SetError (array->error, HPDF_INVALID_OBJECT, 0);
|
||||
|
||||
if (array->list->count >= HPDF_LIMIT_MAX_ARRAY) {
|
||||
HPDF_PTRACE((" HPDF_Array_Add exceed limitatin of array count(%d)\n",
|
||||
HPDF_LIMIT_MAX_ARRAY));
|
||||
|
||||
HPDF_Obj_Free (array->mmgr, obj);
|
||||
return HPDF_SetError (array->error, HPDF_ARRAY_COUNT_ERR, 0);
|
||||
}
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_INDIRECT) {
|
||||
HPDF_Proxy proxy = HPDF_Proxy_New (array->mmgr, obj);
|
||||
|
||||
if (!proxy) {
|
||||
HPDF_Obj_Free (array->mmgr, obj);
|
||||
return HPDF_Error_GetCode (array->error);
|
||||
}
|
||||
|
||||
proxy->header.obj_id |= HPDF_OTYPE_DIRECT;
|
||||
obj = proxy;
|
||||
} else
|
||||
header->obj_id |= HPDF_OTYPE_DIRECT;
|
||||
|
||||
ret = HPDF_List_Add (array->list, obj);
|
||||
if (ret != HPDF_OK)
|
||||
HPDF_Obj_Free (array->mmgr, obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_UINT
|
||||
HPDF_Array_Items (HPDF_Array array)
|
||||
{
|
||||
return array->list->count;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Array_Insert (HPDF_Array array,
|
||||
void *target,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_Obj_Header *header;
|
||||
HPDF_STATUS ret;
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_Insert\n"));
|
||||
|
||||
if (!obj) {
|
||||
if (HPDF_Error_GetCode (array->error) == HPDF_OK)
|
||||
return HPDF_SetError (array->error, HPDF_INVALID_OBJECT, 0);
|
||||
else
|
||||
return HPDF_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_DIRECT) {
|
||||
HPDF_PTRACE((" HPDF_Array_Add this object cannot owned by array "
|
||||
"obj=0x%08X\n", (HPDF_UINT)array));
|
||||
|
||||
return HPDF_SetError (array->error, HPDF_INVALID_OBJECT, 0);
|
||||
}
|
||||
|
||||
if (array->list->count >= HPDF_LIMIT_MAX_ARRAY) {
|
||||
HPDF_PTRACE((" HPDF_Array_Add exceed limitatin of array count(%d)\n",
|
||||
HPDF_LIMIT_MAX_ARRAY));
|
||||
|
||||
HPDF_Obj_Free (array->mmgr, obj);
|
||||
|
||||
return HPDF_SetError (array->error, HPDF_ARRAY_COUNT_ERR, 0);
|
||||
}
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_INDIRECT) {
|
||||
HPDF_Proxy proxy = HPDF_Proxy_New (array->mmgr, obj);
|
||||
|
||||
if (!proxy) {
|
||||
HPDF_Obj_Free (array->mmgr, obj);
|
||||
return HPDF_Error_GetCode (array->error);
|
||||
}
|
||||
|
||||
proxy->header.obj_id |= HPDF_OTYPE_DIRECT;
|
||||
obj = proxy;
|
||||
} else
|
||||
header->obj_id |= HPDF_OTYPE_DIRECT;
|
||||
|
||||
/* get the target-object from object-list
|
||||
* consider that the pointer contained in list may be proxy-object.
|
||||
*/
|
||||
for (i = 0; i < array->list->count; i++) {
|
||||
void *ptr = HPDF_List_ItemAt (array->list, i);
|
||||
void *obj_ptr;
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
if (header->obj_class == HPDF_OCLASS_PROXY)
|
||||
obj_ptr = ((HPDF_Proxy)ptr)->obj;
|
||||
else
|
||||
obj_ptr = ptr;
|
||||
|
||||
if (obj_ptr == target) {
|
||||
ret = HPDF_List_Insert (array->list, ptr, obj);
|
||||
if (ret != HPDF_OK)
|
||||
HPDF_Obj_Free (array->mmgr, obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
HPDF_Obj_Free (array->mmgr, obj);
|
||||
|
||||
return HPDF_ITEM_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
HPDF_Array_GetItem (HPDF_Array array,
|
||||
HPDF_UINT index,
|
||||
HPDF_UINT16 obj_class)
|
||||
{
|
||||
void *obj;
|
||||
HPDF_Obj_Header *header;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_GetItem\n"));
|
||||
|
||||
obj = HPDF_List_ItemAt (array->list, index);
|
||||
|
||||
if (!obj) {
|
||||
HPDF_SetError (array->error, HPDF_ARRAY_ITEM_NOT_FOUND, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
if (header->obj_class == HPDF_OCLASS_PROXY) {
|
||||
obj = ((HPDF_Proxy)obj)->obj;
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
}
|
||||
|
||||
if ((header->obj_class & HPDF_OCLASS_ANY) != obj_class) {
|
||||
HPDF_SetError (array->error, HPDF_ARRAY_ITEM_UNEXPECTED_TYPE, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
HPDF_Array_Clear (HPDF_Array array)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Array_Clear\n"));
|
||||
|
||||
if (!array)
|
||||
return;
|
||||
|
||||
for (i = 0; i < array->list->count; i++) {
|
||||
void * obj = HPDF_List_ItemAt (array->list, i);
|
||||
|
||||
if (obj) {
|
||||
HPDF_Obj_Free (array->mmgr, obj);
|
||||
}
|
||||
}
|
||||
|
||||
HPDF_List_Clear (array->list);
|
||||
}
|
||||
|
||||
Vendored
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_binary.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
|
||||
HPDF_Binary
|
||||
HPDF_Binary_New (HPDF_MMgr mmgr,
|
||||
HPDF_BYTE *value,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
HPDF_Binary obj;
|
||||
|
||||
obj = HPDF_GetMem (mmgr, sizeof(HPDF_Binary_Rec));
|
||||
|
||||
if (obj) {
|
||||
HPDF_MemSet(&obj->header, 0, sizeof(HPDF_Obj_Header));
|
||||
obj->header.obj_class = HPDF_OCLASS_BINARY;
|
||||
|
||||
obj->mmgr = mmgr;
|
||||
obj->error = mmgr->error;
|
||||
obj->value = NULL;
|
||||
obj->len = 0;
|
||||
if (HPDF_Binary_SetValue (obj, value, len) != HPDF_OK) {
|
||||
HPDF_FreeMem (mmgr, obj);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Binary_Write (HPDF_Binary obj,
|
||||
HPDF_Stream stream,
|
||||
HPDF_Encrypt e)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
|
||||
if (obj->len == 0)
|
||||
return HPDF_Stream_WriteStr (stream, "<>");
|
||||
|
||||
if ((ret = HPDF_Stream_WriteChar (stream, '<')) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if (e)
|
||||
HPDF_Encrypt_Reset (e);
|
||||
|
||||
if ((ret = HPDF_Stream_WriteBinary (stream, obj->value, obj->len, e)) !=
|
||||
HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_Stream_WriteChar (stream, '>');
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Binary_SetValue (HPDF_Binary obj,
|
||||
HPDF_BYTE *value,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
if (len > HPDF_LIMIT_MAX_STRING_LEN)
|
||||
return HPDF_SetError (obj->error, HPDF_BINARY_LENGTH_ERR, 0);
|
||||
|
||||
if (obj->value) {
|
||||
HPDF_FreeMem (obj->mmgr, obj->value);
|
||||
obj->len = 0;
|
||||
}
|
||||
|
||||
obj->value = HPDF_GetMem (obj->mmgr, len);
|
||||
if (!obj->value)
|
||||
return HPDF_Error_GetCode (obj->error);
|
||||
|
||||
HPDF_MemCpy (obj->value, value, len);
|
||||
obj->len = len;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Binary_Free (HPDF_Binary obj)
|
||||
{
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
if (obj->value)
|
||||
HPDF_FreeMem (obj->mmgr, obj->value);
|
||||
|
||||
HPDF_FreeMem (obj->mmgr, obj);
|
||||
}
|
||||
|
||||
HPDF_UINT
|
||||
HPDF_Binary_GetLen (HPDF_Binary obj)
|
||||
{
|
||||
return obj->len;
|
||||
}
|
||||
|
||||
HPDF_BYTE*
|
||||
HPDF_Binary_GetValue (HPDF_Binary obj)
|
||||
{
|
||||
return obj->value;
|
||||
}
|
||||
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_boolean.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
HPDF_Boolean
|
||||
HPDF_Boolean_New (HPDF_MMgr mmgr,
|
||||
HPDF_BOOL value)
|
||||
{
|
||||
HPDF_Boolean obj = HPDF_GetMem (mmgr, sizeof(HPDF_Boolean_Rec));
|
||||
|
||||
if (obj) {
|
||||
HPDF_MemSet(&obj->header, 0, sizeof(HPDF_Obj_Header));
|
||||
obj->header.obj_class = HPDF_OCLASS_BOOLEAN;
|
||||
obj->value = value;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Boolean_Write (HPDF_Boolean obj,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
|
||||
if (obj->value)
|
||||
ret = HPDF_Stream_WriteStr (stream, "true");
|
||||
else
|
||||
ret = HPDF_Stream_WriteStr (stream, "false");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Vendored
+385
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_catalog.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_catalog.h"
|
||||
#include "hpdf_pages.h"
|
||||
|
||||
static const char * const HPDF_PAGE_LAYOUT_NAMES[] = {
|
||||
"SinglePage",
|
||||
"OneColumn",
|
||||
"TwoColumnLeft",
|
||||
"TwoColumnRight",
|
||||
"TwoPageLeft",
|
||||
"TwoPageRight",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static const char * const HPDF_PAGE_MODE_NAMES[] = {
|
||||
"UseNone",
|
||||
"UseOutlines",
|
||||
"UseThumbs",
|
||||
"FullScreen",
|
||||
"UseOC",
|
||||
"UseAttachments",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
HPDF_Catalog
|
||||
HPDF_Catalog_New (HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Catalog catalog;
|
||||
HPDF_STATUS ret = 0;
|
||||
|
||||
catalog = HPDF_Dict_New (mmgr);
|
||||
if (!catalog)
|
||||
return NULL;
|
||||
|
||||
catalog->header.obj_class |= HPDF_OSUBCLASS_CATALOG;
|
||||
|
||||
if (HPDF_Xref_Add (xref, catalog) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
/* add requiered elements */
|
||||
ret += HPDF_Dict_AddName (catalog, "Type", "Catalog");
|
||||
ret += HPDF_Dict_Add (catalog, "Pages", HPDF_Pages_New (mmgr, NULL, xref));
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return catalog;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Pages
|
||||
HPDF_Catalog_GetRoot (HPDF_Catalog catalog)
|
||||
{
|
||||
HPDF_Dict pages;
|
||||
|
||||
if (!catalog)
|
||||
return NULL;
|
||||
|
||||
pages = HPDF_Dict_GetItem (catalog, "Pages", HPDF_OCLASS_DICT);
|
||||
if (!pages || pages->header.obj_class != (HPDF_OSUBCLASS_PAGES |
|
||||
HPDF_OCLASS_DICT))
|
||||
HPDF_SetError (catalog->error, HPDF_PAGE_CANNOT_GET_ROOT_PAGES, 0);
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
|
||||
HPDF_NameDict
|
||||
HPDF_Catalog_GetNames (HPDF_Catalog catalog)
|
||||
{
|
||||
if (!catalog)
|
||||
return NULL;
|
||||
return HPDF_Dict_GetItem (catalog, "Names", HPDF_OCLASS_DICT);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Catalog_SetNames (HPDF_Catalog catalog,
|
||||
HPDF_NameDict dict)
|
||||
{
|
||||
return HPDF_Dict_Add (catalog, "Names", dict);
|
||||
}
|
||||
|
||||
|
||||
HPDF_PageLayout
|
||||
HPDF_Catalog_GetPageLayout (HPDF_Catalog catalog)
|
||||
{
|
||||
HPDF_Name layout;
|
||||
HPDF_UINT i = 0;
|
||||
|
||||
layout = (HPDF_Name)HPDF_Dict_GetItem (catalog, "PageLayout",
|
||||
HPDF_OCLASS_NAME);
|
||||
if (!layout)
|
||||
return HPDF_PAGE_LAYOUT_EOF;
|
||||
|
||||
while (HPDF_PAGE_LAYOUT_NAMES[i]) {
|
||||
if (HPDF_StrCmp (layout->value, HPDF_PAGE_LAYOUT_NAMES[i]) == 0)
|
||||
return (HPDF_PageLayout)i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return HPDF_PAGE_LAYOUT_EOF;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Catalog_SetPageLayout (HPDF_Catalog catalog,
|
||||
HPDF_PageLayout layout)
|
||||
{
|
||||
return HPDF_Dict_AddName (catalog, "PageLayout",
|
||||
HPDF_PAGE_LAYOUT_NAMES[(HPDF_INT)layout]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
HPDF_PageMode
|
||||
HPDF_Catalog_GetPageMode (HPDF_Catalog catalog)
|
||||
{
|
||||
HPDF_Name mode;
|
||||
HPDF_UINT i = 0;
|
||||
|
||||
mode = (HPDF_Name)HPDF_Dict_GetItem (catalog, "PageMode", HPDF_OCLASS_NAME);
|
||||
if (!mode)
|
||||
return HPDF_PAGE_MODE_USE_NONE;
|
||||
|
||||
while (HPDF_PAGE_MODE_NAMES[i]) {
|
||||
if (HPDF_StrCmp (mode->value, HPDF_PAGE_MODE_NAMES[i]) == 0)
|
||||
return (HPDF_PageMode)i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return HPDF_PAGE_MODE_USE_NONE;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Catalog_SetPageMode (HPDF_Catalog catalog,
|
||||
HPDF_PageMode mode)
|
||||
{
|
||||
return HPDF_Dict_AddName (catalog, "PageMode",
|
||||
HPDF_PAGE_MODE_NAMES[(HPDF_INT)mode]);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Catalog_SetOpenAction (HPDF_Catalog catalog,
|
||||
HPDF_Destination open_action)
|
||||
{
|
||||
if (!open_action) {
|
||||
HPDF_Dict_RemoveElement (catalog, "OpenAction");
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
return HPDF_Dict_Add (catalog, "OpenAction", open_action);
|
||||
}
|
||||
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_Catalog_Validate (HPDF_Catalog catalog)
|
||||
{
|
||||
if (!catalog)
|
||||
return HPDF_FALSE;
|
||||
|
||||
if (catalog->header.obj_class != (HPDF_OSUBCLASS_CATALOG |
|
||||
HPDF_OCLASS_DICT)) {
|
||||
HPDF_SetError (catalog->error, HPDF_INVALID_OBJECT, 0);
|
||||
return HPDF_FALSE;
|
||||
}
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Catalog_AddPageLabel (HPDF_Catalog catalog,
|
||||
HPDF_UINT page_num,
|
||||
HPDF_Dict page_label)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
HPDF_Array nums;
|
||||
HPDF_Dict labels = HPDF_Dict_GetItem (catalog, "PageLabels",
|
||||
HPDF_OCLASS_DICT);
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Catalog_AddPageLabel\n"));
|
||||
|
||||
if (!labels) {
|
||||
labels = HPDF_Dict_New (catalog->mmgr);
|
||||
|
||||
if (!labels)
|
||||
return catalog->error->error_no;
|
||||
|
||||
if ((ret = HPDF_Dict_Add (catalog, "PageLabels", labels)) != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
nums = HPDF_Dict_GetItem (labels, "Nums", HPDF_OCLASS_ARRAY);
|
||||
|
||||
if (!nums) {
|
||||
nums = HPDF_Array_New (catalog->mmgr);
|
||||
|
||||
if (!nums)
|
||||
return catalog->error->error_no;
|
||||
|
||||
if ((ret = HPDF_Dict_Add (labels, "Nums", nums)) != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = HPDF_Array_AddNumber (nums, page_num)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_Array_Add (nums, page_label);
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Catalog_SetViewerPreference (HPDF_Catalog catalog,
|
||||
HPDF_UINT value)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
HPDF_Dict preferences;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Catalog_SetViewerPreference\n"));
|
||||
|
||||
if (!value) {
|
||||
ret = HPDF_Dict_RemoveElement (catalog, "ViewerPreferences");
|
||||
|
||||
if (ret == HPDF_DICT_ITEM_NOT_FOUND)
|
||||
ret = HPDF_OK;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
preferences = HPDF_Dict_New (catalog->mmgr);
|
||||
if (!preferences)
|
||||
return catalog->error->error_no;
|
||||
|
||||
if ((ret = HPDF_Dict_Add (catalog, "ViewerPreferences", preferences))
|
||||
!= HPDF_OK)
|
||||
return ret;
|
||||
|
||||
/* */
|
||||
|
||||
if (value & HPDF_HIDE_TOOLBAR) {
|
||||
if ((ret = HPDF_Dict_AddBoolean (preferences, "HideToolbar",
|
||||
HPDF_TRUE)) != HPDF_OK)
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = HPDF_Dict_RemoveElement (preferences, "HideToolbar")) !=
|
||||
HPDF_OK)
|
||||
if (ret != HPDF_DICT_ITEM_NOT_FOUND)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value & HPDF_HIDE_MENUBAR) {
|
||||
if ((ret = HPDF_Dict_AddBoolean (preferences, "HideMenubar",
|
||||
HPDF_TRUE)) != HPDF_OK)
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = HPDF_Dict_RemoveElement (preferences, "HideMenubar")) !=
|
||||
HPDF_OK)
|
||||
if (ret != HPDF_DICT_ITEM_NOT_FOUND)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value & HPDF_HIDE_WINDOW_UI) {
|
||||
if ((ret = HPDF_Dict_AddBoolean (preferences, "HideWindowUI",
|
||||
HPDF_TRUE)) != HPDF_OK)
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = HPDF_Dict_RemoveElement (preferences, "HideWindowUI")) !=
|
||||
HPDF_OK)
|
||||
if (ret != HPDF_DICT_ITEM_NOT_FOUND)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value & HPDF_FIT_WINDOW) {
|
||||
if ((ret = HPDF_Dict_AddBoolean (preferences, "FitWindow",
|
||||
HPDF_TRUE)) != HPDF_OK)
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = HPDF_Dict_RemoveElement (preferences, "FitWindow")) !=
|
||||
HPDF_OK)
|
||||
if (ret != HPDF_DICT_ITEM_NOT_FOUND)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value & HPDF_CENTER_WINDOW) {
|
||||
if ((ret = HPDF_Dict_AddBoolean (preferences, "CenterWindow",
|
||||
HPDF_TRUE)) != HPDF_OK)
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = HPDF_Dict_RemoveElement (preferences, "CenterWindow")) !=
|
||||
HPDF_OK)
|
||||
if (ret != HPDF_DICT_ITEM_NOT_FOUND)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value & HPDF_PRINT_SCALING_NONE) {
|
||||
if ((ret = HPDF_Dict_AddName (preferences, "PrintScaling",
|
||||
"None")) != HPDF_OK)
|
||||
return ret;
|
||||
} else {
|
||||
if ((ret = HPDF_Dict_RemoveElement (preferences, "PrintScaling")) !=
|
||||
HPDF_OK)
|
||||
if (ret != HPDF_DICT_ITEM_NOT_FOUND)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
HPDF_UINT
|
||||
HPDF_Catalog_GetViewerPreference (HPDF_Catalog catalog)
|
||||
{
|
||||
HPDF_Dict preferences;
|
||||
HPDF_UINT value = 0;
|
||||
HPDF_Boolean obj;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Catalog_GetViewerPreference\n"));
|
||||
|
||||
preferences = (HPDF_Dict)HPDF_Dict_GetItem (catalog, "ViewerPreferences",
|
||||
HPDF_OCLASS_DICT);
|
||||
|
||||
if (!preferences)
|
||||
return 0;
|
||||
|
||||
obj = (HPDF_Boolean)HPDF_Dict_GetItem (preferences, "HideToolbar",
|
||||
HPDF_OCLASS_BOOLEAN);
|
||||
if (obj) {
|
||||
if (obj->value)
|
||||
value += HPDF_HIDE_TOOLBAR;
|
||||
}
|
||||
|
||||
obj = (HPDF_Boolean)HPDF_Dict_GetItem (preferences, "HideMenubar",
|
||||
HPDF_OCLASS_BOOLEAN);
|
||||
if (obj) {
|
||||
if (obj->value)
|
||||
value += HPDF_HIDE_MENUBAR;
|
||||
}
|
||||
|
||||
obj = (HPDF_Boolean)HPDF_Dict_GetItem (preferences, "HideWindowUI",
|
||||
HPDF_OCLASS_BOOLEAN);
|
||||
if (obj) {
|
||||
if (obj->value)
|
||||
value += HPDF_HIDE_WINDOW_UI;
|
||||
}
|
||||
|
||||
obj = (HPDF_Boolean)HPDF_Dict_GetItem (preferences, "FitWindow",
|
||||
HPDF_OCLASS_BOOLEAN);
|
||||
if (obj) {
|
||||
if (obj->value)
|
||||
value += HPDF_FIT_WINDOW;
|
||||
}
|
||||
|
||||
obj = (HPDF_Boolean)HPDF_Dict_GetItem (preferences, "CenterWindow",
|
||||
HPDF_OCLASS_BOOLEAN);
|
||||
if (obj) {
|
||||
if (obj->value)
|
||||
value += HPDF_CENTER_WINDOW;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_destination.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
const char * const HPDF_DESTINATION_TYPE_NAMES[] = {
|
||||
"XYZ",
|
||||
"Fit",
|
||||
"FitH",
|
||||
"FitV",
|
||||
"FitR",
|
||||
"FitB",
|
||||
"FitBH",
|
||||
"FitBV",
|
||||
NULL
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*----- HPDF_Destination -----------------------------------------------------*/
|
||||
|
||||
HPDF_Destination
|
||||
HPDF_Destination_New (HPDF_MMgr mmgr,
|
||||
HPDF_Page target,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Destination dst;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_New\n"));
|
||||
|
||||
if (!HPDF_Page_Validate (target)) {
|
||||
HPDF_SetError (mmgr->error, HPDF_INVALID_PAGE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dst = HPDF_Array_New (mmgr);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
dst->header.obj_class |= HPDF_OSUBCLASS_DESTINATION;
|
||||
|
||||
if (HPDF_Xref_Add (xref, dst) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
/* first item of array must be target page */
|
||||
if (HPDF_Array_Add (dst, target) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
/* default type is HPDF_FIT */
|
||||
if (HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_FIT]) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_Destination_Validate (HPDF_Destination dst)
|
||||
{
|
||||
HPDF_Obj_Header *header = (HPDF_Obj_Header *)dst;
|
||||
HPDF_Page target;
|
||||
|
||||
if (!dst || header->obj_class !=
|
||||
(HPDF_OCLASS_ARRAY | HPDF_OSUBCLASS_DESTINATION))
|
||||
return HPDF_FALSE;
|
||||
|
||||
/* destination-types not defined. */
|
||||
if (dst->list->count < 2)
|
||||
return HPDF_FALSE;
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
if (!HPDF_Page_Validate (target)) {
|
||||
HPDF_SetError (dst->error, HPDF_INVALID_PAGE, 0);
|
||||
return HPDF_FALSE;
|
||||
}
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Destination_SetXYZ (HPDF_Destination dst,
|
||||
HPDF_REAL left,
|
||||
HPDF_REAL top,
|
||||
HPDF_REAL zoom)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Page target;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_SetXYZ\n"));
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_INVALID_DESTINATION;
|
||||
|
||||
if (left < 0 || top < 0 || zoom < 0.08 || zoom > 32)
|
||||
return HPDF_RaiseError (dst->error, HPDF_INVALID_PARAMETER, 0);
|
||||
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
|
||||
if (dst->list->count > 1) {
|
||||
HPDF_Array_Clear (dst);
|
||||
ret += HPDF_Array_Add (dst, target);
|
||||
}
|
||||
|
||||
ret += HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_XYZ]);
|
||||
ret += HPDF_Array_AddReal (dst, left);
|
||||
ret += HPDF_Array_AddReal (dst, top);
|
||||
ret += HPDF_Array_AddReal (dst, zoom);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (dst->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Destination_SetFit (HPDF_Destination dst)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Page target;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_SetFit\n"));
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_INVALID_DESTINATION;
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
|
||||
if (dst->list->count > 1) {
|
||||
HPDF_Array_Clear (dst);
|
||||
ret += HPDF_Array_Add (dst, target);
|
||||
}
|
||||
|
||||
ret += HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_FIT]);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (dst->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Destination_SetFitH (HPDF_Destination dst,
|
||||
HPDF_REAL top)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Page target;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_SetFitH\n"));
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_INVALID_DESTINATION;
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
|
||||
if (dst->list->count > 1) {
|
||||
HPDF_Array_Clear (dst);
|
||||
ret += HPDF_Array_Add (dst, target);
|
||||
}
|
||||
|
||||
ret += HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_FIT_H]);
|
||||
ret += HPDF_Array_AddReal (dst, top);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (dst->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Destination_SetFitV (HPDF_Destination dst,
|
||||
HPDF_REAL left)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Page target;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_SetFitV\n"));
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_INVALID_DESTINATION;
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
|
||||
if (dst->list->count > 1) {
|
||||
HPDF_Array_Clear (dst);
|
||||
ret += HPDF_Array_Add (dst, target);
|
||||
}
|
||||
|
||||
ret += HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_FIT_V]);
|
||||
ret += HPDF_Array_AddReal (dst, left);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (dst->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Destination_SetFitR (HPDF_Destination dst,
|
||||
HPDF_REAL left,
|
||||
HPDF_REAL bottom,
|
||||
HPDF_REAL right,
|
||||
HPDF_REAL top)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Page target;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_SetFitR\n"));
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_INVALID_DESTINATION;
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
|
||||
if (dst->list->count > 1) {
|
||||
HPDF_Array_Clear (dst);
|
||||
ret += HPDF_Array_Add (dst, target);
|
||||
}
|
||||
|
||||
ret += HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_FIT_R]);
|
||||
ret += HPDF_Array_AddReal (dst, left);
|
||||
ret += HPDF_Array_AddReal (dst, bottom);
|
||||
ret += HPDF_Array_AddReal (dst, right);
|
||||
ret += HPDF_Array_AddReal (dst, top);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (dst->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Destination_SetFitB (HPDF_Destination dst)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Page target;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_SetFitB\n"));
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_INVALID_DESTINATION;
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
|
||||
if (dst->list->count > 1) {
|
||||
HPDF_Array_Clear (dst);
|
||||
ret += HPDF_Array_Add (dst, target);
|
||||
}
|
||||
|
||||
ret += HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_FIT_B]);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (dst->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Destination_SetFitBH (HPDF_Destination dst,
|
||||
HPDF_REAL top)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Page target;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_SetFitBH\n"));
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_INVALID_DESTINATION;
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
|
||||
if (dst->list->count > 1) {
|
||||
HPDF_Array_Clear (dst);
|
||||
ret += HPDF_Array_Add (dst, target);
|
||||
}
|
||||
|
||||
ret += HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_FIT_BH]);
|
||||
ret += HPDF_Array_AddReal (dst, top);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (dst->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Destination_SetFitBV (HPDF_Destination dst,
|
||||
HPDF_REAL left)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Page target;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Destination_SetFitBV\n"));
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_INVALID_DESTINATION;
|
||||
|
||||
target = (HPDF_Page)HPDF_Array_GetItem (dst, 0, HPDF_OCLASS_DICT);
|
||||
|
||||
if (dst->list->count > 1) {
|
||||
HPDF_Array_Clear (dst);
|
||||
ret += HPDF_Array_Add (dst, target);
|
||||
}
|
||||
|
||||
ret += HPDF_Array_AddName (dst,
|
||||
HPDF_DESTINATION_TYPE_NAMES[(HPDF_INT)HPDF_FIT_BV]);
|
||||
ret += HPDF_Array_AddReal (dst, left);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (dst->error);
|
||||
|
||||
return HPDF_OK;
|
||||
|
||||
}
|
||||
|
||||
Vendored
+518
@@ -0,0 +1,518 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_dict.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
HPDF_DictElement
|
||||
GetElement (HPDF_Dict dict,
|
||||
const char *key);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
HPDF_Dict
|
||||
HPDF_Dict_New (HPDF_MMgr mmgr)
|
||||
{
|
||||
HPDF_Dict obj;
|
||||
|
||||
obj = (HPDF_Dict)HPDF_GetMem (mmgr, sizeof(HPDF_Dict_Rec));
|
||||
if (obj) {
|
||||
HPDF_MemSet (obj, 0, sizeof(HPDF_Dict_Rec));
|
||||
obj->header.obj_class = HPDF_OCLASS_DICT;
|
||||
obj->mmgr = mmgr;
|
||||
obj->error = mmgr->error;
|
||||
obj->list = HPDF_List_New (mmgr, HPDF_DEF_ITEMS_PER_BLOCK);
|
||||
obj->filter = HPDF_STREAM_FILTER_NONE;
|
||||
if (!obj->list) {
|
||||
HPDF_FreeMem (mmgr, obj);
|
||||
obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Dict
|
||||
HPDF_DictStream_New (HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Dict obj;
|
||||
HPDF_Number length;
|
||||
HPDF_STATUS ret = 0;
|
||||
|
||||
obj = HPDF_Dict_New (mmgr);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
/* only stream object is added to xref automatically */
|
||||
ret += HPDF_Xref_Add (xref, obj);
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
length = HPDF_Number_New (mmgr, 0);
|
||||
if (!length)
|
||||
return NULL;
|
||||
|
||||
ret = HPDF_Xref_Add (xref, length);
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
ret = HPDF_Dict_Add (obj, "Length", length);
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
obj->stream = HPDF_MemStream_New (mmgr, HPDF_STREAM_BUF_SIZ);
|
||||
if (!obj->stream)
|
||||
return NULL;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Dict_Free (HPDF_Dict dict)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
|
||||
if (!dict)
|
||||
return;
|
||||
|
||||
if (dict->free_fn)
|
||||
dict->free_fn (dict);
|
||||
|
||||
for (i = 0; i < dict->list->count; i++) {
|
||||
HPDF_DictElement element =
|
||||
(HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
|
||||
|
||||
if (element) {
|
||||
HPDF_Obj_Free (dict->mmgr, element->value);
|
||||
HPDF_FreeMem (dict->mmgr, element);
|
||||
}
|
||||
}
|
||||
|
||||
if (dict->stream)
|
||||
HPDF_Stream_Free (dict->stream);
|
||||
|
||||
HPDF_List_Free (dict->list);
|
||||
|
||||
dict->header.obj_class = 0;
|
||||
|
||||
HPDF_FreeMem (dict->mmgr, dict);
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_Add_FilterParams(HPDF_Dict dict, HPDF_Dict filterParam)
|
||||
{
|
||||
HPDF_Array paramArray;
|
||||
/* prepare params object */
|
||||
paramArray = HPDF_Dict_GetItem (dict, "DecodeParms",
|
||||
HPDF_OCLASS_ARRAY);
|
||||
if(paramArray==NULL) {
|
||||
paramArray = HPDF_Array_New (dict->mmgr);
|
||||
if (!paramArray)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
/* add parameters */
|
||||
HPDF_Dict_Add(dict, "DecodeParms", paramArray);
|
||||
}
|
||||
HPDF_Array_Add(paramArray, filterParam);
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_Write (HPDF_Dict dict,
|
||||
HPDF_Stream stream,
|
||||
HPDF_Encrypt e)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
ret = HPDF_Stream_WriteStr (stream, "<<\012");
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if (dict->before_write_fn) {
|
||||
if ((ret = dict->before_write_fn (dict)) != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* encrypt-dict must not be encrypted. */
|
||||
if (dict->header.obj_class == (HPDF_OCLASS_DICT | HPDF_OSUBCLASS_ENCRYPT))
|
||||
e = NULL;
|
||||
|
||||
if (dict->stream) {
|
||||
/* set filter element */
|
||||
if (dict->filter == HPDF_STREAM_FILTER_NONE)
|
||||
HPDF_Dict_RemoveElement (dict, "Filter");
|
||||
else {
|
||||
HPDF_Array array = HPDF_Dict_GetItem (dict, "Filter",
|
||||
HPDF_OCLASS_ARRAY);
|
||||
|
||||
if (!array) {
|
||||
array = HPDF_Array_New (dict->mmgr);
|
||||
if (!array)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
ret = HPDF_Dict_Add (dict, "Filter", array);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_Array_Clear (array);
|
||||
|
||||
#ifndef LIBHPDF_HAVE_NOZLIB
|
||||
if (dict->filter & HPDF_STREAM_FILTER_FLATE_DECODE)
|
||||
HPDF_Array_AddName (array, "FlateDecode");
|
||||
#endif /* LIBHPDF_HAVE_NOZLIB */
|
||||
|
||||
if (dict->filter & HPDF_STREAM_FILTER_DCT_DECODE)
|
||||
HPDF_Array_AddName (array, "DCTDecode");
|
||||
|
||||
if(dict->filter & HPDF_STREAM_FILTER_CCITT_DECODE)
|
||||
HPDF_Array_AddName (array, "CCITTFaxDecode");
|
||||
|
||||
if(dict->filterParams!=NULL)
|
||||
{
|
||||
HPDF_Dict_Add_FilterParams(dict, dict->filterParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dict->list->count; i++) {
|
||||
HPDF_DictElement element =
|
||||
(HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
|
||||
HPDF_Obj_Header *header = (HPDF_Obj_Header *)(element->value);
|
||||
|
||||
if (!element->value)
|
||||
return HPDF_SetError (dict->error, HPDF_INVALID_OBJECT, 0);
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_HIDDEN) {
|
||||
HPDF_PTRACE((" HPDF_Dict_Write obj=%p skipped obj_id=0x%08X\n",
|
||||
element->value, (HPDF_UINT)header->obj_id));
|
||||
} else {
|
||||
ret = HPDF_Stream_WriteEscapeName (stream, element->key);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
ret = HPDF_Stream_WriteChar (stream, ' ');
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
ret = HPDF_Obj_Write (element->value, stream, e);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
ret = HPDF_Stream_WriteStr (stream, "\012");
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (dict->write_fn) {
|
||||
if ((ret = dict->write_fn (dict, stream)) != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, ">>")) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if (dict->stream) {
|
||||
HPDF_UINT32 strptr;
|
||||
HPDF_Number length;
|
||||
|
||||
/* get "length" element */
|
||||
length = (HPDF_Number)HPDF_Dict_GetItem (dict, "Length",
|
||||
HPDF_OCLASS_NUMBER);
|
||||
if (!length)
|
||||
return HPDF_SetError (dict->error,
|
||||
HPDF_DICT_STREAM_LENGTH_NOT_FOUND, 0);
|
||||
|
||||
/* "length" element must be indirect-object */
|
||||
if (!(length->header.obj_id & HPDF_OTYPE_INDIRECT)) {
|
||||
return HPDF_SetError (dict->error, HPDF_DICT_ITEM_UNEXPECTED_TYPE,
|
||||
0);
|
||||
}
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, "\012stream\015\012")) /* Acrobat 8.15 requires both \r and \n here */
|
||||
!= HPDF_OK)
|
||||
return ret;
|
||||
|
||||
strptr = stream->size;
|
||||
|
||||
if (e)
|
||||
HPDF_Encrypt_Reset (e);
|
||||
|
||||
if ((ret = HPDF_Stream_WriteToStream (dict->stream, stream,
|
||||
dict->filter, e)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
HPDF_Number_SetValue (length, stream->size - strptr);
|
||||
|
||||
ret = HPDF_Stream_WriteStr (stream, "\012endstream");
|
||||
}
|
||||
|
||||
/* 2006.08.13 add. */
|
||||
if (dict->after_write_fn) {
|
||||
if ((ret = dict->after_write_fn (dict)) != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_Add (HPDF_Dict dict,
|
||||
const char *key,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_Obj_Header *header;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_DictElement element;
|
||||
|
||||
if (!obj) {
|
||||
if (HPDF_Error_GetCode (dict->error) == HPDF_OK)
|
||||
return HPDF_SetError (dict->error, HPDF_INVALID_OBJECT, 0);
|
||||
else
|
||||
return HPDF_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_DIRECT)
|
||||
return HPDF_SetError (dict->error, HPDF_INVALID_OBJECT, 0);
|
||||
|
||||
if (!key) {
|
||||
HPDF_Obj_Free (dict->mmgr, obj);
|
||||
return HPDF_SetError (dict->error, HPDF_INVALID_OBJECT, 0);
|
||||
}
|
||||
|
||||
if (dict->list->count >= HPDF_LIMIT_MAX_DICT_ELEMENT) {
|
||||
HPDF_PTRACE((" HPDF_Dict_Add exceed limitatin of dict count(%d)\n",
|
||||
HPDF_LIMIT_MAX_DICT_ELEMENT));
|
||||
|
||||
HPDF_Obj_Free (dict->mmgr, obj);
|
||||
return HPDF_SetError (dict->error, HPDF_DICT_COUNT_ERR, 0);
|
||||
}
|
||||
|
||||
/* check whether there is an object which has same name */
|
||||
element = GetElement (dict, key);
|
||||
|
||||
if (element) {
|
||||
HPDF_Obj_Free (dict->mmgr, element->value);
|
||||
element->value = NULL;
|
||||
} else {
|
||||
element = (HPDF_DictElement)HPDF_GetMem (dict->mmgr,
|
||||
sizeof(HPDF_DictElement_Rec));
|
||||
|
||||
if (!element) {
|
||||
/* cannot create element object */
|
||||
if (!(header->obj_id & HPDF_OTYPE_INDIRECT))
|
||||
HPDF_Obj_Free (dict->mmgr, obj);
|
||||
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
}
|
||||
|
||||
HPDF_StrCpy (element->key, key, element->key +
|
||||
HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||||
element->value = NULL;
|
||||
|
||||
ret = HPDF_List_Add (dict->list, element);
|
||||
if (ret != HPDF_OK) {
|
||||
if (!(header->obj_id & HPDF_OTYPE_INDIRECT))
|
||||
HPDF_Obj_Free (dict->mmgr, obj);
|
||||
|
||||
HPDF_FreeMem (dict->mmgr, element);
|
||||
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
}
|
||||
}
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_INDIRECT) {
|
||||
HPDF_Proxy proxy = HPDF_Proxy_New (dict->mmgr, obj);
|
||||
|
||||
if (!proxy)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
element->value = proxy;
|
||||
proxy->header.obj_id |= HPDF_OTYPE_DIRECT;
|
||||
} else {
|
||||
element->value = obj;
|
||||
header->obj_id |= HPDF_OTYPE_DIRECT;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_AddName (HPDF_Dict dict,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
HPDF_Name name = HPDF_Name_New (dict->mmgr, value);
|
||||
if (!name)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
return HPDF_Dict_Add (dict, key, name);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_AddNumber (HPDF_Dict dict,
|
||||
const char *key,
|
||||
HPDF_INT32 value)
|
||||
{
|
||||
HPDF_Number number = HPDF_Number_New (dict->mmgr, value);
|
||||
|
||||
if (!number)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
return HPDF_Dict_Add (dict, key, number);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_AddReal (HPDF_Dict dict,
|
||||
const char *key,
|
||||
HPDF_REAL value)
|
||||
{
|
||||
HPDF_Real real = HPDF_Real_New (dict->mmgr, value);
|
||||
|
||||
if (!real)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
return HPDF_Dict_Add (dict, key, real);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_AddBoolean (HPDF_Dict dict,
|
||||
const char *key,
|
||||
HPDF_BOOL value)
|
||||
{
|
||||
HPDF_Boolean obj = HPDF_Boolean_New (dict->mmgr, value);
|
||||
|
||||
if (!obj)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
return HPDF_Dict_Add (dict, key, obj);
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
HPDF_Dict_GetItem (HPDF_Dict dict,
|
||||
const char *key,
|
||||
HPDF_UINT16 obj_class)
|
||||
{
|
||||
HPDF_DictElement element = GetElement (dict, key);
|
||||
void *obj;
|
||||
|
||||
if (element && HPDF_StrCmp(key, element->key) == 0) {
|
||||
HPDF_Obj_Header *header = (HPDF_Obj_Header *)element->value;
|
||||
|
||||
if (header->obj_class == HPDF_OCLASS_PROXY) {
|
||||
HPDF_Proxy p = element->value;
|
||||
header = (HPDF_Obj_Header *)p->obj;
|
||||
obj = p->obj;
|
||||
} else
|
||||
obj = element->value;
|
||||
|
||||
if ((header->obj_class & HPDF_OCLASS_ANY) != obj_class) {
|
||||
HPDF_PTRACE((" HPDF_Dict_GetItem dict=%p key=%s obj_class=0x%08X\n",
|
||||
dict, key, (HPDF_UINT)header->obj_class));
|
||||
HPDF_SetError (dict->error, HPDF_DICT_ITEM_UNEXPECTED_TYPE, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
HPDF_DictElement
|
||||
GetElement (HPDF_Dict dict,
|
||||
const char *key)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
|
||||
for (i = 0; i < dict->list->count; i++) {
|
||||
HPDF_DictElement element =
|
||||
(HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
|
||||
|
||||
if (HPDF_StrCmp (key, element->key) == 0)
|
||||
return element;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Dict_RemoveElement (HPDF_Dict dict,
|
||||
const char *key)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
|
||||
for (i = 0; i < dict->list->count; i++) {
|
||||
HPDF_DictElement element =
|
||||
(HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
|
||||
|
||||
if (HPDF_StrCmp (key, element->key) == 0) {
|
||||
HPDF_List_Remove (dict->list, element);
|
||||
|
||||
HPDF_Obj_Free (dict->mmgr, element->value);
|
||||
HPDF_FreeMem (dict->mmgr, element);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return HPDF_DICT_ITEM_NOT_FOUND;
|
||||
}
|
||||
|
||||
const char*
|
||||
HPDF_Dict_GetKeyByObj (HPDF_Dict dict,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
|
||||
for (i = 0; i < dict->list->count; i++) {
|
||||
HPDF_Obj_Header *header;
|
||||
HPDF_DictElement element =
|
||||
(HPDF_DictElement)HPDF_List_ItemAt (dict->list, i);
|
||||
|
||||
header = (HPDF_Obj_Header *)(element->value);
|
||||
if (header->obj_class == HPDF_OCLASS_PROXY) {
|
||||
HPDF_Proxy p = element->value;
|
||||
|
||||
if (p->obj == obj)
|
||||
return element->key;
|
||||
} else {
|
||||
if (element->value == obj)
|
||||
return element->key;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Vendored
+2368
File diff suppressed because it is too large
Load Diff
Vendored
+184
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_doc_png.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
#include "hpdf_image.h"
|
||||
|
||||
|
||||
static HPDF_Image
|
||||
LoadPngImageFromStream (HPDF_Doc pdf,
|
||||
HPDF_Stream imagedata,
|
||||
HPDF_BOOL delayed_loading);
|
||||
|
||||
HPDF_EXPORT(HPDF_Image)
|
||||
HPDF_LoadPngImageFromMem (HPDF_Doc pdf,
|
||||
const HPDF_BYTE *buffer,
|
||||
HPDF_UINT size)
|
||||
{
|
||||
HPDF_Stream imagedata;
|
||||
HPDF_Image image;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_LoadPngImageFromFile\n"));
|
||||
|
||||
if (!HPDF_HasDoc (pdf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create file stream */
|
||||
imagedata = HPDF_MemStream_New (pdf->mmgr, size);
|
||||
|
||||
if (!HPDF_Stream_Validate (imagedata)) {
|
||||
HPDF_RaiseError (&pdf->error, HPDF_INVALID_STREAM, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (imagedata, buffer, size) != HPDF_OK) {
|
||||
HPDF_Stream_Free (imagedata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = LoadPngImageFromStream (pdf, imagedata, HPDF_FALSE);
|
||||
|
||||
/* destroy file stream */
|
||||
HPDF_Stream_Free (imagedata);
|
||||
|
||||
if (!image) {
|
||||
HPDF_CheckError (&pdf->error);
|
||||
}
|
||||
|
||||
return image;
|
||||
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_Image)
|
||||
HPDF_LoadPngImageFromFile (HPDF_Doc pdf,
|
||||
const char *filename)
|
||||
{
|
||||
HPDF_Stream imagedata;
|
||||
HPDF_Image image;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_LoadPngImageFromFile\n"));
|
||||
|
||||
if (!HPDF_HasDoc (pdf))
|
||||
return NULL;
|
||||
|
||||
/* create file stream */
|
||||
imagedata = HPDF_FileReader_New (pdf->mmgr, filename);
|
||||
|
||||
if (HPDF_Stream_Validate (imagedata))
|
||||
image = LoadPngImageFromStream (pdf, imagedata, HPDF_FALSE);
|
||||
else
|
||||
image = NULL;
|
||||
|
||||
/* destroy file stream */
|
||||
if (imagedata)
|
||||
HPDF_Stream_Free (imagedata);
|
||||
|
||||
if (!image)
|
||||
HPDF_CheckError (&pdf->error);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/* delaied loading version of HPDF_LoadPngImageFromFile */
|
||||
HPDF_EXPORT(HPDF_Image)
|
||||
HPDF_LoadPngImageFromFile2 (HPDF_Doc pdf,
|
||||
const char *filename)
|
||||
{
|
||||
HPDF_Stream imagedata;
|
||||
HPDF_Image image;
|
||||
HPDF_String fname;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_LoadPngImageFromFile\n"));
|
||||
|
||||
if (!HPDF_HasDoc (pdf))
|
||||
return NULL;
|
||||
|
||||
/* check whether file name is valid or not. */
|
||||
imagedata = HPDF_FileReader_New (pdf->mmgr, filename);
|
||||
|
||||
if (HPDF_Stream_Validate (imagedata))
|
||||
image = LoadPngImageFromStream (pdf, imagedata, HPDF_TRUE);
|
||||
else
|
||||
image = NULL;
|
||||
|
||||
/* destroy file stream */
|
||||
if (imagedata)
|
||||
HPDF_Stream_Free (imagedata);
|
||||
|
||||
if (!image) {
|
||||
HPDF_CheckError (&pdf->error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add file-name to image dictionary as a hidden entry.
|
||||
* it is used when the image data is needed.
|
||||
*/
|
||||
fname = HPDF_String_New (pdf->mmgr, filename, NULL);
|
||||
if (!fname) {
|
||||
HPDF_CheckError (&pdf->error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fname->header.obj_id |= HPDF_OTYPE_HIDDEN;
|
||||
|
||||
if ((HPDF_Dict_Add (image, "_FILE_NAME", fname)) != HPDF_OK) {
|
||||
HPDF_CheckError (&pdf->error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
#ifndef LIBHPDF_HAVE_NOPNGLIB
|
||||
static HPDF_Image
|
||||
LoadPngImageFromStream (HPDF_Doc pdf,
|
||||
HPDF_Stream imagedata,
|
||||
HPDF_BOOL delayed_loading)
|
||||
{
|
||||
HPDF_Image image;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_LoadPngImageFromStream\n"));
|
||||
|
||||
image = HPDF_Image_LoadPngImage (pdf->mmgr, imagedata, pdf->xref,
|
||||
delayed_loading);
|
||||
|
||||
if (image && (pdf->compression_mode & HPDF_COMP_IMAGE))
|
||||
image->filter = HPDF_STREAM_FILTER_FLATE_DECODE;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
#else
|
||||
static HPDF_Image
|
||||
LoadPngImageFromStream (HPDF_Doc pdf,
|
||||
HPDF_Stream imagedata,
|
||||
HPDF_BOOL delayed_loading)
|
||||
{
|
||||
HPDF_SetError (&pdf->error, HPDF_UNSUPPORTED_FUNC, 0);
|
||||
HPDF_UNUSED (delayed_loading);
|
||||
HPDF_UNUSED (imagedata);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* LIBHPDF_HAVE_NOPNGLIB */
|
||||
|
||||
Vendored
+3002
File diff suppressed because it is too large
Load Diff
+36366
File diff suppressed because it is too large
Load Diff
+15312
File diff suppressed because it is too large
Load Diff
+16132
File diff suppressed because it is too large
Load Diff
+27985
File diff suppressed because it is too large
Load Diff
+276
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_encoder_utf.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2008 Antony Dovgal <tony@daylessday.org>
|
||||
* Copyright (c) 2010 Sergey Konovalov <webmaster@crynet.ru>
|
||||
* Copyright (c) 2011 Koen Deforche <koen@emweb.be>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_encoder.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
typedef struct _UTF8_EncoderAttr_Rec *UTF8_EncoderAttr;
|
||||
typedef struct _UTF8_EncoderAttr_Rec {
|
||||
HPDF_BYTE current_byte;
|
||||
HPDF_BYTE end_byte;
|
||||
HPDF_BYTE utf8_bytes[8];
|
||||
} UTF8_EncoderAttr_Rec;
|
||||
|
||||
static const HPDF_CidRange_Rec UTF8_NOTDEF_RANGE = {0x0000, 0x001F, 1};
|
||||
static const HPDF_CidRange_Rec UTF8_SPACE_RANGE = {0x0000, 0xFFFF, 0};
|
||||
static const HPDF_CidRange_Rec UTF8_CID_RANGE[] = {
|
||||
{ 0x0000, 0xFFFF, 0x0 },
|
||||
{ 0xFFFF, 0xFFFF, 0x0 }
|
||||
};
|
||||
|
||||
static HPDF_ByteType
|
||||
UTF8_Encoder_ByteType_Func (HPDF_Encoder encoder,
|
||||
HPDF_ParseText_Rec *state);
|
||||
|
||||
static HPDF_UNICODE
|
||||
UTF8_Encoder_ToUnicode_Func (HPDF_Encoder encoder,
|
||||
HPDF_UINT16 code);
|
||||
|
||||
static char *
|
||||
UTF8_Encoder_EncodeText_Func (HPDF_Encoder encoder,
|
||||
const char *text,
|
||||
HPDF_UINT len,
|
||||
HPDF_UINT *length);
|
||||
|
||||
static HPDF_STATUS
|
||||
UTF8_Init (HPDF_Encoder encoder);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* This function is taken from hpdf_encoder_utf8.c, originally submitted
|
||||
* to libharu by 'Mirco'
|
||||
*/
|
||||
static HPDF_ByteType
|
||||
UTF8_Encoder_ByteType_Func (HPDF_Encoder encoder,
|
||||
HPDF_ParseText_Rec *state)
|
||||
{
|
||||
// This function is supposed to increment state->index
|
||||
// Not logical ! (look at function HPDF_String_Write in hpdf_string.c)
|
||||
|
||||
// When HPDF_BYTE_TYPE_SINGLE is returned, the current byte is the
|
||||
// CODE argument in call ToUnicode_Func
|
||||
// When HPDF_BYTE_TYPE_LEAD is returned, the current byte (msb) and the
|
||||
// next byte (lsb) is the CODE arguement in call ToUnicodeFunc
|
||||
// When HPDF_BYTE_TYPE_TRIAL is returned, the current byte is ignored
|
||||
|
||||
HPDF_CMapEncoderAttr encoder_attr;
|
||||
HPDF_BYTE byte;
|
||||
UTF8_EncoderAttr utf8_attr;
|
||||
|
||||
encoder_attr = (HPDF_CMapEncoderAttr) encoder->attr;
|
||||
utf8_attr = (UTF8_EncoderAttr) ((void *)encoder_attr->cid_map[0]);
|
||||
|
||||
if (state->index == 0) {
|
||||
//First byte, initialize.
|
||||
HPDF_PTRACE ((" UTF8_Encoder_ByteType_Func - Initialize: (%u) %s\n",
|
||||
state->len, state->text));
|
||||
|
||||
utf8_attr->current_byte = 0;
|
||||
}
|
||||
|
||||
byte = state->text[state->index];
|
||||
state->index++;
|
||||
|
||||
HPDF_PTRACE ((" UTF8_Encoder_ByteType_Func - Byte: %hx\n", byte));
|
||||
|
||||
if (utf8_attr->current_byte == 0) {
|
||||
utf8_attr->utf8_bytes[0] = byte;
|
||||
utf8_attr->current_byte = 1;
|
||||
|
||||
if (!(byte & 0x80)) {
|
||||
utf8_attr->current_byte = 0;
|
||||
utf8_attr->end_byte = 0;
|
||||
return HPDF_BYTE_TYPE_SINGLE;
|
||||
}
|
||||
|
||||
if ((byte & 0xf8) == 0xf0)
|
||||
utf8_attr->end_byte = 3;
|
||||
else if ((byte & 0xf0) == 0xe0)
|
||||
utf8_attr->end_byte = 2;
|
||||
else if ((byte & 0xe0) == 0xc0)
|
||||
utf8_attr->end_byte = 1;
|
||||
else
|
||||
utf8_attr->current_byte = 0; //ERROR, skip this byte
|
||||
} else {
|
||||
utf8_attr->utf8_bytes[utf8_attr->current_byte] = byte;
|
||||
if (utf8_attr->current_byte == utf8_attr->end_byte) {
|
||||
utf8_attr->current_byte = 0;
|
||||
return HPDF_BYTE_TYPE_SINGLE;
|
||||
}
|
||||
|
||||
utf8_attr->current_byte++;
|
||||
}
|
||||
|
||||
return HPDF_BYTE_TYPE_TRIAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is taken from hpdf_encoder_utf8.c, originally submitted
|
||||
* to libharu by 'Mirco'
|
||||
*/
|
||||
static HPDF_UNICODE
|
||||
UTF8_Encoder_ToUnicode_Func (HPDF_Encoder encoder,
|
||||
HPDF_UINT16 code)
|
||||
{
|
||||
// Supposed to convert CODE to unicode.
|
||||
// This function is allways called after ByteType_Func.
|
||||
// ByteType_Func recognizes the utf-8 bytes belonging to one character.
|
||||
|
||||
HPDF_CMapEncoderAttr encoder_attr;
|
||||
UTF8_EncoderAttr utf8_attr;
|
||||
unsigned int val;
|
||||
|
||||
encoder_attr = (HPDF_CMapEncoderAttr) encoder->attr;
|
||||
utf8_attr = (UTF8_EncoderAttr) ((void *)encoder_attr->cid_map[0]);
|
||||
|
||||
switch (utf8_attr->end_byte) {
|
||||
case 3:
|
||||
val = (unsigned int) ((utf8_attr->utf8_bytes[0] & 0x7) << 18) +
|
||||
(unsigned int) ((utf8_attr->utf8_bytes[1]) << 12) +
|
||||
(unsigned int) ((utf8_attr->utf8_bytes[2] & 0x3f) << 6) +
|
||||
(unsigned int) ((utf8_attr->utf8_bytes[3] & 0x3f));
|
||||
break;
|
||||
case 2:
|
||||
val = (unsigned int) ((utf8_attr->utf8_bytes[0] & 0xf) << 12) +
|
||||
(unsigned int) ((utf8_attr->utf8_bytes[1] & 0x3f) << 6) +
|
||||
(unsigned int) ((utf8_attr->utf8_bytes[2] & 0x3f));
|
||||
break;
|
||||
case 1:
|
||||
val = (unsigned int) ((utf8_attr->utf8_bytes[0] & 0x1f) << 6) +
|
||||
(unsigned int) ((utf8_attr->utf8_bytes[1] & 0x3f));
|
||||
break;
|
||||
case 0:
|
||||
val = (unsigned int) utf8_attr->utf8_bytes[0];
|
||||
break;
|
||||
default:
|
||||
val = 32; // Unknown character
|
||||
}
|
||||
|
||||
if (val > 65535) //Convert everything outside UCS-2 to space
|
||||
val = 32;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static char *
|
||||
UTF8_Encoder_EncodeText_Func (HPDF_Encoder encoder,
|
||||
const char *text,
|
||||
HPDF_UINT len,
|
||||
HPDF_UINT *length)
|
||||
{
|
||||
char *result = malloc(len * 2);
|
||||
char *c = result;
|
||||
HPDF_ParseText_Rec parse_state;
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_Encoder_SetParseText (encoder, &parse_state,
|
||||
(const HPDF_BYTE *)text, len);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
HPDF_UNICODE tmp_unicode;
|
||||
HPDF_ByteType btype = HPDF_Encoder_ByteType (encoder, &parse_state);
|
||||
|
||||
if (btype != HPDF_BYTE_TYPE_TRIAL) {
|
||||
tmp_unicode = HPDF_Encoder_ToUnicode (encoder, 0);
|
||||
|
||||
HPDF_UInt16Swap (&tmp_unicode);
|
||||
HPDF_MemCpy ((HPDF_BYTE *)c, (const HPDF_BYTE*)&tmp_unicode, 2);
|
||||
c += 2;
|
||||
}
|
||||
}
|
||||
|
||||
*length = c - result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
UTF8_Init (HPDF_Encoder encoder)
|
||||
{
|
||||
HPDF_CMapEncoderAttr attr;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
if ((ret = HPDF_CMapEncoder_InitAttr (encoder)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We override these two
|
||||
*/
|
||||
encoder->byte_type_fn = UTF8_Encoder_ByteType_Func;
|
||||
encoder->to_unicode_fn = UTF8_Encoder_ToUnicode_Func;
|
||||
encoder->encode_text_fn = UTF8_Encoder_EncodeText_Func;
|
||||
|
||||
attr = (HPDF_CMapEncoderAttr)encoder->attr;
|
||||
|
||||
if (HPDF_CMapEncoder_AddCMap (encoder, UTF8_CID_RANGE) != HPDF_OK)
|
||||
return encoder->error->error_no;
|
||||
|
||||
if (HPDF_CMapEncoder_AddCodeSpaceRange (encoder, UTF8_SPACE_RANGE)
|
||||
!= HPDF_OK)
|
||||
return encoder->error->error_no;
|
||||
|
||||
if (HPDF_CMapEncoder_AddNotDefRange (encoder, UTF8_NOTDEF_RANGE)
|
||||
!= HPDF_OK)
|
||||
return encoder->error->error_no;
|
||||
|
||||
attr->is_lead_byte_fn = NULL;
|
||||
attr->is_trial_byte_fn = NULL;
|
||||
|
||||
HPDF_StrCpy (attr->registry, "Adobe", attr->registry +
|
||||
HPDF_LIMIT_MAX_NAME_LEN);
|
||||
HPDF_StrCpy (attr->ordering, "Identity-H", attr->ordering +
|
||||
HPDF_LIMIT_MAX_NAME_LEN);
|
||||
attr->suppliment = 0;
|
||||
attr->writing_mode = HPDF_WMODE_HORIZONTAL;
|
||||
|
||||
/* Not sure about this
|
||||
attr->uid_offset = 0;
|
||||
attr->xuid[0] = 0;
|
||||
attr->xuid[1] = 0;
|
||||
attr->xuid[2] = 0;
|
||||
*/
|
||||
|
||||
encoder->type = HPDF_ENCODER_TYPE_DOUBLE_BYTE;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_UseUTFEncodings (HPDF_Doc pdf)
|
||||
{
|
||||
HPDF_Encoder encoder;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
if (!HPDF_HasDoc (pdf))
|
||||
return HPDF_INVALID_DOCUMENT;
|
||||
|
||||
encoder = HPDF_CMapEncoder_New (pdf->mmgr, "UTF-8",
|
||||
UTF8_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterEncoder (pdf, encoder)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
Vendored
+635
@@ -0,0 +1,635 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_encryor.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*------------------------------------------------------------------------------
|
||||
*
|
||||
* The code implements MD5 message-digest algorithm is based on the code
|
||||
* written by Colin Plumb.
|
||||
* The copyright of it is as follows.
|
||||
*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_consts.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_encrypt.h"
|
||||
|
||||
static const HPDF_BYTE HPDF_PADDING_STRING[] = {
|
||||
0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41,
|
||||
0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
|
||||
0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80,
|
||||
0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*------ MD5 message-digest algorithm ---------------------------------------*/
|
||||
|
||||
static void
|
||||
MD5Transform (HPDF_UINT32 buf[4],
|
||||
const HPDF_UINT32 in[16]);
|
||||
|
||||
|
||||
static void
|
||||
MD5ByteReverse (HPDF_BYTE *buf,
|
||||
HPDF_UINT32 longs);
|
||||
|
||||
|
||||
void
|
||||
HPDF_MD5Init (struct HPDF_MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_MD5Update (struct HPDF_MD5Context *ctx,
|
||||
const HPDF_BYTE *buf,
|
||||
HPDF_UINT32 len)
|
||||
{
|
||||
HPDF_UINT32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((HPDF_UINT32) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
HPDF_BYTE *p = (HPDF_BYTE *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t)
|
||||
{
|
||||
HPDF_MemCpy (p, buf, len);
|
||||
return;
|
||||
}
|
||||
HPDF_MemCpy (p, buf, t);
|
||||
MD5ByteReverse (ctx->in, 16);
|
||||
MD5Transform (ctx->buf, (HPDF_UINT32 *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
HPDF_MemCpy (ctx->in, buf, 64);
|
||||
MD5ByteReverse (ctx->in, 16);
|
||||
MD5Transform (ctx->buf, (HPDF_UINT32 *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
HPDF_MemCpy (ctx->in, buf, len);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void
|
||||
HPDF_MD5Final (HPDF_BYTE digest[16],
|
||||
struct HPDF_MD5Context *ctx)
|
||||
{
|
||||
HPDF_UINT32 count;
|
||||
HPDF_BYTE *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
HPDF_MemSet (p, 0, count);
|
||||
MD5ByteReverse (ctx->in, 16);
|
||||
MD5Transform (ctx->buf, (HPDF_UINT32 *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
HPDF_MemSet (ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
HPDF_MemSet (p, 0, count - 8);
|
||||
}
|
||||
MD5ByteReverse (ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((HPDF_UINT32 *) ctx->in)[14] = ctx->bits[0];
|
||||
((HPDF_UINT32 *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform (ctx->buf, (HPDF_UINT32 *) ctx->in);
|
||||
MD5ByteReverse ((HPDF_BYTE *) ctx->buf, 4);
|
||||
HPDF_MemCpy ((HPDF_BYTE *)digest, (HPDF_BYTE *)ctx->buf, 16);
|
||||
HPDF_MemSet ((HPDF_BYTE *)ctx, 0, sizeof (ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the HPDF_MD5 algorithm. */
|
||||
#define HPDF_MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void
|
||||
MD5Transform (HPDF_UINT32 buf[4],
|
||||
const HPDF_UINT32 in[16])
|
||||
{
|
||||
register HPDF_UINT32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
HPDF_MD5STEP (F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
HPDF_MD5STEP (F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
HPDF_MD5STEP (F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
HPDF_MD5STEP (F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
HPDF_MD5STEP (F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
HPDF_MD5STEP (F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
HPDF_MD5STEP (F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
HPDF_MD5STEP (F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
HPDF_MD5STEP (F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
HPDF_MD5STEP (F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
HPDF_MD5STEP (F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
HPDF_MD5STEP (F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
HPDF_MD5STEP (F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
HPDF_MD5STEP (F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
HPDF_MD5STEP (F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
HPDF_MD5STEP (F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
HPDF_MD5STEP (F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
HPDF_MD5STEP (F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
HPDF_MD5STEP (F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
HPDF_MD5STEP (F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
HPDF_MD5STEP (F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
HPDF_MD5STEP (F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
HPDF_MD5STEP (F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
HPDF_MD5STEP (F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
HPDF_MD5STEP (F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
HPDF_MD5STEP (F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
HPDF_MD5STEP (F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
HPDF_MD5STEP (F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
HPDF_MD5STEP (F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
HPDF_MD5STEP (F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
HPDF_MD5STEP (F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
HPDF_MD5STEP (F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
HPDF_MD5STEP (F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
HPDF_MD5STEP (F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
HPDF_MD5STEP (F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
HPDF_MD5STEP (F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
HPDF_MD5STEP (F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
HPDF_MD5STEP (F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
HPDF_MD5STEP (F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
HPDF_MD5STEP (F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
HPDF_MD5STEP (F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
HPDF_MD5STEP (F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
HPDF_MD5STEP (F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
HPDF_MD5STEP (F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
HPDF_MD5STEP (F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
HPDF_MD5STEP (F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
HPDF_MD5STEP (F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
HPDF_MD5STEP (F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
HPDF_MD5STEP (F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
HPDF_MD5STEP (F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
HPDF_MD5STEP (F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
HPDF_MD5STEP (F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
HPDF_MD5STEP (F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
HPDF_MD5STEP (F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
HPDF_MD5STEP (F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
HPDF_MD5STEP (F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
HPDF_MD5STEP (F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
HPDF_MD5STEP (F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
HPDF_MD5STEP (F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
HPDF_MD5STEP (F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
HPDF_MD5STEP (F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
HPDF_MD5STEP (F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
HPDF_MD5STEP (F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
HPDF_MD5STEP (F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
MD5ByteReverse (HPDF_BYTE *buf,
|
||||
HPDF_UINT32 longs)
|
||||
{
|
||||
HPDF_UINT32 t;
|
||||
do
|
||||
{
|
||||
t = (HPDF_UINT32) ((HPDF_UINT32) buf[3] << 8 | buf[2]) << 16 |
|
||||
((HPDF_UINT32) buf[1] << 8 | buf[0]);
|
||||
*(HPDF_UINT32 *) buf = t;
|
||||
buf += 4;
|
||||
}
|
||||
while (--longs);
|
||||
}
|
||||
|
||||
/*----- encrypt-obj ---------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
ARC4Init (HPDF_ARC4_Ctx_Rec *ctx,
|
||||
const HPDF_BYTE *key,
|
||||
HPDF_UINT key_len);
|
||||
|
||||
|
||||
static void
|
||||
ARC4CryptBuf (HPDF_ARC4_Ctx_Rec *ctx,
|
||||
const HPDF_BYTE *in,
|
||||
HPDF_BYTE *out,
|
||||
HPDF_UINT len);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
HPDF_PadOrTrancatePasswd (const char *pwd,
|
||||
HPDF_BYTE *new_pwd)
|
||||
{
|
||||
HPDF_UINT len = HPDF_StrLen (pwd, HPDF_PASSWD_LEN + 1);
|
||||
|
||||
HPDF_PTRACE((" HPDF_PadOrTrancatePasswd\n"));
|
||||
|
||||
HPDF_MemSet (new_pwd, 0x00, HPDF_PASSWD_LEN);
|
||||
|
||||
if (len >= HPDF_PASSWD_LEN) {
|
||||
HPDF_MemCpy (new_pwd, (HPDF_BYTE *)pwd, HPDF_PASSWD_LEN);
|
||||
} else {
|
||||
if (len > 0) {
|
||||
HPDF_MemCpy (new_pwd, (HPDF_BYTE *)pwd, len);
|
||||
}
|
||||
HPDF_MemCpy (new_pwd + len, HPDF_PADDING_STRING, HPDF_PASSWD_LEN - len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Encrypt_Init (HPDF_Encrypt attr)
|
||||
{
|
||||
HPDF_MemSet (attr, 0, sizeof(HPDF_Encrypt_Rec));
|
||||
attr->mode = HPDF_ENCRYPT_R2;
|
||||
attr->key_len = 5;
|
||||
HPDF_MemCpy (attr->owner_passwd, HPDF_PADDING_STRING, HPDF_PASSWD_LEN);
|
||||
HPDF_MemCpy (attr->user_passwd, HPDF_PADDING_STRING, HPDF_PASSWD_LEN);
|
||||
attr->permission = HPDF_ENABLE_PRINT | HPDF_ENABLE_EDIT_ALL |
|
||||
HPDF_ENABLE_COPY | HPDF_ENABLE_EDIT | HPDF_PERMISSION_PAD;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Encrypt_CreateOwnerKey (HPDF_Encrypt attr)
|
||||
{
|
||||
HPDF_ARC4_Ctx_Rec rc4_ctx;
|
||||
HPDF_MD5_CTX md5_ctx;
|
||||
HPDF_BYTE digest[HPDF_MD5_KEY_LEN];
|
||||
HPDF_BYTE tmppwd[HPDF_PASSWD_LEN];
|
||||
|
||||
HPDF_PTRACE((" HPDF_Encrypt_CreateOwnerKey\n"));
|
||||
|
||||
/* create md5-digest using the value of owner_passwd */
|
||||
|
||||
/* Algorithm 3.3 step 2 */
|
||||
HPDF_MD5Init(&md5_ctx);
|
||||
HPDF_MD5Update(&md5_ctx, attr->owner_passwd, HPDF_PASSWD_LEN);
|
||||
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 2\n"));
|
||||
|
||||
HPDF_MD5Final(digest, &md5_ctx);
|
||||
|
||||
/* Algorithm 3.3 step 3 (Revision 3 only) */
|
||||
if (attr->mode == HPDF_ENCRYPT_R3) {
|
||||
HPDF_UINT i;
|
||||
|
||||
for (i = 0; i < 50; i++) {
|
||||
HPDF_MD5Init(&md5_ctx);
|
||||
|
||||
/* HPDF_MD5Update (&md5_ctx, digest, HPDF_MD5_KEY_LEN); */
|
||||
HPDF_MD5Update (&md5_ctx, digest, attr->key_len);
|
||||
HPDF_MD5Final(digest, &md5_ctx);
|
||||
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 3 loop %u\n", i));
|
||||
}
|
||||
}
|
||||
|
||||
/* Algorithm 3.3 step 4 */
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 7 loop 0\n"));
|
||||
|
||||
ARC4Init (&rc4_ctx, digest, attr->key_len);
|
||||
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 5\n"));
|
||||
|
||||
/* Algorithm 3.3 step 6 */
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 6\n"));
|
||||
ARC4CryptBuf (&rc4_ctx, attr->user_passwd, tmppwd, HPDF_PASSWD_LEN);
|
||||
|
||||
/* Algorithm 3.3 step 7 */
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 7\n"));
|
||||
if (attr->mode == HPDF_ENCRYPT_R3) {
|
||||
HPDF_BYTE tmppwd2[HPDF_PASSWD_LEN];
|
||||
HPDF_UINT i;
|
||||
|
||||
for (i = 1; i <= 19; i++) {
|
||||
HPDF_UINT j;
|
||||
HPDF_BYTE new_key[HPDF_MD5_KEY_LEN];
|
||||
|
||||
for (j = 0; j < attr->key_len; j++)
|
||||
new_key[j] = (HPDF_BYTE)(digest[j] ^ i);
|
||||
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 7 loop %u\n", i));
|
||||
|
||||
HPDF_MemCpy (tmppwd2, tmppwd, HPDF_PASSWD_LEN);
|
||||
ARC4Init(&rc4_ctx, new_key, attr->key_len);
|
||||
ARC4CryptBuf(&rc4_ctx, tmppwd2, tmppwd, HPDF_PASSWD_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
/* Algorithm 3.3 step 8 */
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 8\n"));
|
||||
HPDF_MemCpy (attr->owner_key, tmppwd, HPDF_PASSWD_LEN);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Encrypt_CreateEncryptionKey (HPDF_Encrypt attr)
|
||||
{
|
||||
HPDF_MD5_CTX md5_ctx;
|
||||
HPDF_BYTE tmp_flg[4];
|
||||
|
||||
HPDF_PTRACE((" HPDF_Encrypt_CreateEncryptionKey\n"));
|
||||
|
||||
/* Algorithm3.2 step2 */
|
||||
HPDF_MD5Init(&md5_ctx);
|
||||
HPDF_MD5Update(&md5_ctx, attr->user_passwd, HPDF_PASSWD_LEN);
|
||||
|
||||
/* Algorithm3.2 step3 */
|
||||
HPDF_MD5Update(&md5_ctx, attr->owner_key, HPDF_PASSWD_LEN);
|
||||
|
||||
|
||||
/* Algorithm3.2 step4 */
|
||||
HPDF_PTRACE(("@@@ permission =%d\n", attr->permission));
|
||||
tmp_flg[0] = (HPDF_BYTE)(attr->permission);
|
||||
tmp_flg[1] = (HPDF_BYTE)(attr->permission >> 8);
|
||||
tmp_flg[2] = (HPDF_BYTE)(attr->permission >> 16);
|
||||
tmp_flg[3] = (HPDF_BYTE)(attr->permission >> 24);
|
||||
|
||||
HPDF_MD5Update(&md5_ctx, tmp_flg, 4);
|
||||
|
||||
/* Algorithm3.2 step5 */
|
||||
HPDF_PTRACE(("@ Algorithm 3.2 step 5\n"));
|
||||
|
||||
HPDF_MD5Update(&md5_ctx, attr->encrypt_id, HPDF_ID_LEN);
|
||||
HPDF_MD5Final(attr->encryption_key, &md5_ctx);
|
||||
|
||||
/* Algorithm 3.2 step6 (Revision 3 only) */
|
||||
if (attr->mode == HPDF_ENCRYPT_R3) {
|
||||
HPDF_UINT i;
|
||||
|
||||
for (i = 0; i < 50; i++) {
|
||||
HPDF_PTRACE(("@ Algorithm 3.3 step 6 loop %u\n", i));
|
||||
HPDF_MD5Init(&md5_ctx);
|
||||
HPDF_MD5Update (&md5_ctx, attr->encryption_key, attr->key_len);
|
||||
HPDF_MD5Final(attr->encryption_key, &md5_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Encrypt_CreateUserKey (HPDF_Encrypt attr)
|
||||
{
|
||||
HPDF_ARC4_Ctx_Rec ctx;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Encrypt_CreateUserKey\n"));
|
||||
|
||||
/* Algorithm 3.4/5 step1 */
|
||||
|
||||
/* Algorithm 3.4 step2 */
|
||||
ARC4Init(&ctx, attr->encryption_key, attr->key_len);
|
||||
ARC4CryptBuf(&ctx, HPDF_PADDING_STRING, attr->user_key, HPDF_PASSWD_LEN);
|
||||
|
||||
if (attr->mode == HPDF_ENCRYPT_R3) {
|
||||
HPDF_MD5_CTX md5_ctx;
|
||||
HPDF_BYTE digest[HPDF_MD5_KEY_LEN];
|
||||
HPDF_BYTE digest2[HPDF_MD5_KEY_LEN];
|
||||
HPDF_UINT i;
|
||||
|
||||
/* Algorithm 3.5 step2 (same as Algorithm3.2 step2) */
|
||||
HPDF_MD5Init(&md5_ctx);
|
||||
HPDF_MD5Update(&md5_ctx, HPDF_PADDING_STRING, HPDF_PASSWD_LEN);
|
||||
|
||||
/* Algorithm 3.5 step3 */
|
||||
HPDF_MD5Update(&md5_ctx, attr->encrypt_id, HPDF_ID_LEN);
|
||||
HPDF_MD5Final(digest, &md5_ctx);
|
||||
|
||||
HPDF_PTRACE(("@ Algorithm 3.5 step 3\n"));
|
||||
|
||||
/* Algorithm 3.5 step4 */
|
||||
ARC4Init(&ctx, attr->encryption_key, attr->key_len);
|
||||
ARC4CryptBuf(&ctx, digest, digest2, HPDF_MD5_KEY_LEN);
|
||||
|
||||
HPDF_PTRACE(("@ Algorithm 3.5 step 4\n"));
|
||||
|
||||
/* Algorithm 3.5 step5 */
|
||||
for (i = 1; i <= 19; i++) {
|
||||
HPDF_UINT j;
|
||||
HPDF_BYTE new_key[HPDF_MD5_KEY_LEN];
|
||||
|
||||
HPDF_PTRACE(("@ Algorithm 3.5 step 5 loop %u\n", i));
|
||||
|
||||
for (j = 0; j < attr->key_len; j++)
|
||||
new_key[j] = (HPDF_BYTE)(attr->encryption_key[j] ^ i);
|
||||
|
||||
HPDF_MemCpy (digest, digest2, HPDF_MD5_KEY_LEN);
|
||||
|
||||
ARC4Init(&ctx, new_key, attr->key_len);
|
||||
ARC4CryptBuf(&ctx, digest, digest2, HPDF_MD5_KEY_LEN);
|
||||
}
|
||||
|
||||
/* use the result of Algorithm 3.4 as 'arbitrary padding' */
|
||||
HPDF_MemSet (attr->user_key, 0, HPDF_PASSWD_LEN);
|
||||
HPDF_MemCpy (attr->user_key, digest2, HPDF_MD5_KEY_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ARC4Init (HPDF_ARC4_Ctx_Rec *ctx,
|
||||
const HPDF_BYTE *key,
|
||||
HPDF_UINT key_len)
|
||||
{
|
||||
HPDF_BYTE tmp_array[HPDF_ARC4_BUF_SIZE];
|
||||
HPDF_UINT i;
|
||||
HPDF_UINT j = 0;
|
||||
|
||||
HPDF_PTRACE((" ARC4Init\n"));
|
||||
|
||||
for (i = 0; i < HPDF_ARC4_BUF_SIZE; i++)
|
||||
ctx->state[i] = (HPDF_BYTE)i;
|
||||
|
||||
for (i = 0; i < HPDF_ARC4_BUF_SIZE; i++)
|
||||
tmp_array[i] = key[i % key_len];
|
||||
|
||||
for (i = 0; i < HPDF_ARC4_BUF_SIZE; i++) {
|
||||
HPDF_BYTE tmp;
|
||||
|
||||
j = (j + ctx->state[i] + tmp_array[i]) % HPDF_ARC4_BUF_SIZE;
|
||||
|
||||
tmp = ctx->state[i];
|
||||
ctx->state[i] = ctx->state[j];
|
||||
ctx->state[j] = tmp;
|
||||
}
|
||||
|
||||
ctx->idx1 = 0;
|
||||
ctx->idx2 = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ARC4CryptBuf (HPDF_ARC4_Ctx_Rec *ctx,
|
||||
const HPDF_BYTE *in,
|
||||
HPDF_BYTE *out,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
HPDF_UINT t;
|
||||
HPDF_BYTE K;
|
||||
|
||||
HPDF_PTRACE((" ARC4CryptBuf\n"));
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
HPDF_BYTE tmp;
|
||||
|
||||
ctx->idx1 = (HPDF_BYTE)((ctx->idx1 + 1) % 256);
|
||||
ctx->idx2 = (HPDF_BYTE)((ctx->idx2 + ctx->state[ctx->idx1]) % 256);
|
||||
|
||||
tmp = ctx->state[ctx->idx1];
|
||||
ctx->state[ctx->idx1] = ctx->state[ctx->idx2];
|
||||
ctx->state[ctx->idx2] = tmp;
|
||||
|
||||
t = (ctx->state[ctx->idx1] + ctx->state[ctx->idx2]) % 256;
|
||||
K = ctx->state[t];
|
||||
|
||||
out[i] = (HPDF_BYTE)(in[i] ^ K);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Encrypt_InitKey (HPDF_Encrypt attr,
|
||||
HPDF_UINT32 object_id,
|
||||
HPDF_UINT16 gen_no)
|
||||
{
|
||||
HPDF_MD5_CTX ctx;
|
||||
HPDF_UINT key_len;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Encrypt_Init\n"));
|
||||
|
||||
attr->encryption_key[attr->key_len] = (HPDF_BYTE)object_id;
|
||||
attr->encryption_key[attr->key_len + 1] = (HPDF_BYTE)(object_id >> 8);
|
||||
attr->encryption_key[attr->key_len + 2] = (HPDF_BYTE)(object_id >> 16);
|
||||
attr->encryption_key[attr->key_len + 3] = (HPDF_BYTE)gen_no;
|
||||
attr->encryption_key[attr->key_len + 4] = (HPDF_BYTE)(gen_no >> 8);
|
||||
|
||||
HPDF_PTRACE(("@@@ OID=%u, gen_no=%u\n", (HPDF_INT)object_id, gen_no));
|
||||
|
||||
HPDF_MD5Init(&ctx);
|
||||
HPDF_MD5Update(&ctx, attr->encryption_key, attr->key_len + 5);
|
||||
HPDF_MD5Final(attr->md5_encryption_key, &ctx);
|
||||
|
||||
key_len = (attr->key_len + 5 > HPDF_ENCRYPT_KEY_MAX) ?
|
||||
HPDF_ENCRYPT_KEY_MAX : attr->key_len + 5;
|
||||
|
||||
ARC4Init(&attr->arc4ctx, attr->md5_encryption_key, key_len);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Encrypt_Reset (HPDF_Encrypt attr)
|
||||
{
|
||||
HPDF_UINT key_len = (attr->key_len + 5 > HPDF_ENCRYPT_KEY_MAX) ?
|
||||
HPDF_ENCRYPT_KEY_MAX : attr->key_len + 5;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Encrypt_Reset\n"));
|
||||
|
||||
ARC4Init(&attr->arc4ctx, attr->md5_encryption_key, key_len);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Encrypt_CryptBuf (HPDF_Encrypt attr,
|
||||
const HPDF_BYTE *src,
|
||||
HPDF_BYTE *dst,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
ARC4CryptBuf(&attr->arc4ctx, src, dst, len);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_encryptdict.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
#include "hpdf_encryptdict.h"
|
||||
#include "hpdf_info.h"
|
||||
#ifndef HPDF_UNUSED
|
||||
#define HPDF_UNUSED(a) ((void)(a))
|
||||
#endif
|
||||
|
||||
HPDF_EncryptDict
|
||||
HPDF_EncryptDict_New (HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Encrypt attr;
|
||||
HPDF_EncryptDict dict;
|
||||
|
||||
HPDF_PTRACE((" HPDF_EncryptDict_New\n"));
|
||||
|
||||
dict = HPDF_Dict_New (mmgr);
|
||||
if (!dict)
|
||||
return NULL;
|
||||
|
||||
dict->header.obj_class |= HPDF_OSUBCLASS_ENCRYPT;
|
||||
dict->free_fn = HPDF_EncryptDict_OnFree;
|
||||
|
||||
attr = HPDF_GetMem (dict->mmgr, sizeof(HPDF_Encrypt_Rec));
|
||||
if (!attr) {
|
||||
HPDF_Dict_Free (dict);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dict->attr = attr;
|
||||
HPDF_Encrypt_Init (attr);
|
||||
|
||||
if (HPDF_Xref_Add (xref, dict) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_EncryptDict_CreateID (HPDF_EncryptDict dict,
|
||||
HPDF_Dict info,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_MD5_CTX ctx;
|
||||
HPDF_Encrypt attr = (HPDF_Encrypt)dict->attr;
|
||||
|
||||
/* use the result of 'time' function to get random value.
|
||||
* when debugging, 'time' value is ignored.
|
||||
*/
|
||||
#ifndef LIBHPDF_DEBUG
|
||||
time_t t = HPDF_TIME (NULL);
|
||||
#endif /* LIBHPDF_DEBUG */
|
||||
|
||||
HPDF_MD5Init (&ctx);
|
||||
HPDF_UNUSED (xref);
|
||||
HPDF_UNUSED (info);
|
||||
|
||||
#ifndef LIBHPDF_DEBUG
|
||||
HPDF_MD5Update(&ctx, (HPDF_BYTE *)&t, sizeof(t));
|
||||
|
||||
/* create File Identifier from elements of Into dictionary. */
|
||||
if (info) {
|
||||
const char *s;
|
||||
HPDF_UINT len;
|
||||
|
||||
/* Author */
|
||||
s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_AUTHOR);
|
||||
if ((len = HPDF_StrLen (s, -1)) > 0)
|
||||
HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len);
|
||||
|
||||
/* Creator */
|
||||
s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_CREATOR);
|
||||
if ((len = HPDF_StrLen (s, -1)) > 0)
|
||||
HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len);
|
||||
|
||||
/* Producer */
|
||||
s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_PRODUCER);
|
||||
if ((len = HPDF_StrLen (s, -1)) > 0)
|
||||
HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len);
|
||||
|
||||
/* Title */
|
||||
s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_TITLE);
|
||||
if ((len = HPDF_StrLen (s, -1)) > 0)
|
||||
HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len);
|
||||
|
||||
/* Subject */
|
||||
s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_SUBJECT);
|
||||
if ((len = HPDF_StrLen (s, -1)) > 0)
|
||||
HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len);
|
||||
|
||||
/* Keywords */
|
||||
s = HPDF_Info_GetInfoAttr (info, HPDF_INFO_KEYWORDS);
|
||||
if ((len = HPDF_StrLen (s, -1)) > 0)
|
||||
HPDF_MD5Update(&ctx, (const HPDF_BYTE *)s, len);
|
||||
|
||||
HPDF_MD5Update(&ctx, (const HPDF_BYTE *)&(xref->entries->count),
|
||||
sizeof(HPDF_UINT32));
|
||||
|
||||
}
|
||||
#endif
|
||||
HPDF_MD5Final(attr->encrypt_id, &ctx);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_EncryptDict_Prepare (HPDF_EncryptDict dict,
|
||||
HPDF_Dict info,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
HPDF_Encrypt attr = (HPDF_Encrypt)dict->attr;
|
||||
HPDF_Binary user_key;
|
||||
HPDF_Binary owner_key;
|
||||
|
||||
HPDF_PTRACE((" HPDF_EncryptDict_Prepare\n"));
|
||||
|
||||
HPDF_EncryptDict_CreateID (dict, info, xref);
|
||||
HPDF_Encrypt_CreateOwnerKey (attr);
|
||||
HPDF_Encrypt_CreateEncryptionKey (attr);
|
||||
HPDF_Encrypt_CreateUserKey (attr);
|
||||
|
||||
owner_key = HPDF_Binary_New (dict->mmgr, attr->owner_key, HPDF_PASSWD_LEN);
|
||||
if (!owner_key)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
if ((ret = HPDF_Dict_Add (dict, "O", owner_key)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
user_key = HPDF_Binary_New (dict->mmgr, attr->user_key, HPDF_PASSWD_LEN);
|
||||
if (!user_key)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
if ((ret = HPDF_Dict_Add (dict, "U", user_key)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
ret += HPDF_Dict_AddName (dict, "Filter", "Standard");
|
||||
|
||||
if (attr->mode == HPDF_ENCRYPT_R2) {
|
||||
ret += HPDF_Dict_AddNumber (dict, "V", 1);
|
||||
ret += HPDF_Dict_AddNumber (dict, "R", 2);
|
||||
} else if (attr->mode == HPDF_ENCRYPT_R3) {
|
||||
ret += HPDF_Dict_AddNumber (dict, "V", 2);
|
||||
ret += HPDF_Dict_AddNumber (dict, "R", 3);
|
||||
ret += HPDF_Dict_AddNumber (dict, "Length", attr->key_len * 8);
|
||||
}
|
||||
|
||||
ret += HPDF_Dict_AddNumber (dict, "P", attr->permission);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_Error_GetCode (dict->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_EncryptDict_OnFree (HPDF_Dict obj)
|
||||
{
|
||||
HPDF_Encrypt attr = (HPDF_Encrypt)obj->attr;
|
||||
|
||||
HPDF_PTRACE((" HPDF_EncryptDict_OnFree\n"));
|
||||
|
||||
if (attr)
|
||||
HPDF_FreeMem (obj->mmgr, attr);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_EncryptDict_SetPassword (HPDF_EncryptDict dict,
|
||||
const char *owner_passwd,
|
||||
const char *user_passwd)
|
||||
{
|
||||
HPDF_Encrypt attr = (HPDF_Encrypt)dict->attr;
|
||||
|
||||
HPDF_PTRACE((" HPDF_EncryptDict_SetPassword\n"));
|
||||
|
||||
if (HPDF_StrLen(owner_passwd, 2) == 0)
|
||||
return HPDF_SetError(dict->error, HPDF_ENCRYPT_INVALID_PASSWORD, 0);
|
||||
|
||||
if (owner_passwd && user_passwd &&
|
||||
HPDF_StrCmp (owner_passwd, user_passwd) == 0)
|
||||
return HPDF_SetError(dict->error, HPDF_ENCRYPT_INVALID_PASSWORD, 0);
|
||||
|
||||
HPDF_PadOrTrancatePasswd (owner_passwd, attr->owner_passwd);
|
||||
HPDF_PadOrTrancatePasswd (user_passwd, attr->user_passwd);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_EncryptDict_Validate (HPDF_EncryptDict dict)
|
||||
{
|
||||
HPDF_Obj_Header *header = (HPDF_Obj_Header *)dict;
|
||||
|
||||
HPDF_PTRACE((" HPDF_EncryptDict_Validate\n"));
|
||||
|
||||
if (!dict || !dict->attr)
|
||||
return HPDF_FALSE;
|
||||
|
||||
if (header->obj_class != (HPDF_OCLASS_DICT | HPDF_OSUBCLASS_ENCRYPT))
|
||||
return HPDF_FALSE;
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Encrypt
|
||||
HPDF_EncryptDict_GetAttr (HPDF_EncryptDict dict)
|
||||
{
|
||||
HPDF_Obj_Header *header = (HPDF_Obj_Header *)dict;
|
||||
|
||||
HPDF_PTRACE((" HPDF_EncryptDict_GetAttr\n"));
|
||||
|
||||
if (dict && dict->attr &&
|
||||
(header->obj_class == (HPDF_OCLASS_DICT | HPDF_OSUBCLASS_ENCRYPT)))
|
||||
return (HPDF_Encrypt)dict->attr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_error.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_error.h"
|
||||
#include "hpdf_consts.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
#ifndef HPDF_STDCALL
|
||||
#ifdef HPDF_DLL_MAKE
|
||||
#define HPDF_STDCALL __stdcall
|
||||
#else
|
||||
#ifdef HPDF_DLL
|
||||
#define HPDF_STDCALL __stdcall
|
||||
#else
|
||||
#define HPDF_STDCALL
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void
|
||||
HPDF_CopyError (HPDF_Error dst,
|
||||
HPDF_Error src);
|
||||
|
||||
|
||||
void
|
||||
HPDF_Error_Init (HPDF_Error error,
|
||||
void *user_data)
|
||||
{
|
||||
HPDF_MemSet(error, 0, sizeof(HPDF_Error_Rec));
|
||||
|
||||
error->user_data = user_data;
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Error_GetCode (HPDF_Error error)
|
||||
{
|
||||
return error->error_no;
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Error_GetDetailCode (HPDF_Error error)
|
||||
{
|
||||
return error->detail_no;
|
||||
}
|
||||
|
||||
void
|
||||
HPDF_CopyError (HPDF_Error dst,
|
||||
HPDF_Error src)
|
||||
{
|
||||
dst->error_no = src->error_no;
|
||||
dst->detail_no = src->detail_no;
|
||||
dst->error_fn = src->error_fn;
|
||||
dst->user_data = src->user_data;
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_SetError (HPDF_Error error,
|
||||
HPDF_STATUS error_no,
|
||||
HPDF_STATUS detail_no)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_SetError: error_no=0x%04X "
|
||||
"detail_no=0x%04X\n", (HPDF_UINT)error_no, (HPDF_UINT)detail_no));
|
||||
|
||||
error->error_no = error_no;
|
||||
error->detail_no = detail_no;
|
||||
|
||||
return error_no;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_CheckError (HPDF_Error error)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_CheckError: error_no=0x%04X detail_no=0x%04X\n",
|
||||
(HPDF_UINT)error->error_no, (HPDF_UINT)error->detail_no));
|
||||
|
||||
if (error->error_no != HPDF_OK && error->error_fn)
|
||||
error->error_fn (error->error_no, error->detail_no, error->user_data);
|
||||
|
||||
return error->error_no;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_RaiseError (HPDF_Error error,
|
||||
HPDF_STATUS error_no,
|
||||
HPDF_STATUS detail_no)
|
||||
{
|
||||
HPDF_SetError (error, error_no, detail_no);
|
||||
|
||||
return HPDF_CheckError (error);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Error_Reset (HPDF_Error error)
|
||||
{
|
||||
error->error_no = HPDF_NOERROR;
|
||||
error->detail_no = HPDF_NOERROR;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_annotation.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_info.h"
|
||||
#include "hpdf_exdata.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*------ HPDF_ExData -----------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
HPDF_ExData
|
||||
HPDF_3DAnnotExData_New(HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_ExData exdata;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
|
||||
HPDF_PTRACE((" HPDF_ExData_New\n"));
|
||||
|
||||
exdata = HPDF_Dict_New (mmgr);
|
||||
if (!exdata)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Xref_Add (xref, exdata) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
ret += HPDF_Dict_AddName (exdata, "Type", "ExData");
|
||||
ret += HPDF_Dict_AddName (exdata, "Subtype", "3DM");
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return exdata;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_3DAnnotExData_Set3DMeasurement(HPDF_ExData exdata,
|
||||
HPDF_3DMeasure measure)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
ret = HPDF_Dict_Add (exdata, "M3DREF", measure);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_ext_gstate.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_ext_gstate.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
static const char * const HPDF_BM_NAMES[] = {
|
||||
"Normal",
|
||||
"Multiply",
|
||||
"Screen",
|
||||
"Overlay",
|
||||
"Darken",
|
||||
"Lighten",
|
||||
"ColorDodge",
|
||||
"ColorBurn",
|
||||
"HardLight",
|
||||
"SoftLight",
|
||||
"Difference",
|
||||
"Exclusion"
|
||||
};
|
||||
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_ExtGState_Validate (HPDF_ExtGState ext_gstate)
|
||||
{
|
||||
if (!ext_gstate || (ext_gstate->header.obj_class !=
|
||||
(HPDF_OSUBCLASS_EXT_GSTATE | HPDF_OCLASS_DICT) &&
|
||||
ext_gstate->header.obj_class !=
|
||||
(HPDF_OSUBCLASS_EXT_GSTATE_R | HPDF_OCLASS_DICT)))
|
||||
return HPDF_FALSE;
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
ExtGState_Check (HPDF_ExtGState ext_gstate)
|
||||
{
|
||||
if (!HPDF_ExtGState_Validate (ext_gstate))
|
||||
return HPDF_INVALID_OBJECT;
|
||||
|
||||
if (ext_gstate->header.obj_class ==
|
||||
(HPDF_OSUBCLASS_EXT_GSTATE_R | HPDF_OCLASS_DICT))
|
||||
return HPDF_RaiseError (ext_gstate->error, HPDF_EXT_GSTATE_READ_ONLY,
|
||||
0);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Dict
|
||||
HPDF_ExtGState_New (HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Dict obj = HPDF_Dict_New (mmgr);
|
||||
|
||||
HPDF_PTRACE ((" HPDF_ExtGState_New\n"));
|
||||
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Xref_Add (xref, obj) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddName (obj, "Type", "ExtGState") != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
obj->header.obj_class |= HPDF_OSUBCLASS_EXT_GSTATE;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_ExtGState_SetAlphaStroke (HPDF_ExtGState ext_gstate,
|
||||
HPDF_REAL value)
|
||||
{
|
||||
HPDF_STATUS ret = ExtGState_Check (ext_gstate);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if (value < 0 || value > 1.0f)
|
||||
return HPDF_RaiseError (ext_gstate->error,
|
||||
HPDF_EXT_GSTATE_OUT_OF_RANGE, 0);
|
||||
|
||||
return HPDF_Dict_AddReal (ext_gstate, "CA", value);
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_ExtGState_SetAlphaFill (HPDF_ExtGState ext_gstate,
|
||||
HPDF_REAL value)
|
||||
{
|
||||
HPDF_STATUS ret = ExtGState_Check (ext_gstate);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if (value < 0 || value > 1.0f)
|
||||
return HPDF_RaiseError (ext_gstate->error,
|
||||
HPDF_EXT_GSTATE_OUT_OF_RANGE, 0);
|
||||
|
||||
return HPDF_Dict_AddReal (ext_gstate, "ca", value);
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_ExtGState_SetBlendMode (HPDF_ExtGState ext_gstate,
|
||||
HPDF_BlendMode bmode)
|
||||
{
|
||||
HPDF_STATUS ret = ExtGState_Check (ext_gstate);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((int)bmode < 0 || (int)bmode > (int)HPDF_BM_EOF)
|
||||
return HPDF_RaiseError (ext_gstate->error,
|
||||
HPDF_EXT_GSTATE_OUT_OF_RANGE, 0);
|
||||
|
||||
return HPDF_Dict_AddName (ext_gstate, "BM", HPDF_BM_NAMES[(int)bmode]);
|
||||
}
|
||||
|
||||
/*
|
||||
HPDF_STATUS
|
||||
HPDF_ExtGState_SetStrokeAdjustment (HPDF_ExtGState ext_gstate,
|
||||
HPDF_BOOL value)
|
||||
{
|
||||
HPDF_STATUS ret = ExtGState_Check (ext_gstate);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_Dict_AddBoolean (ext_gstate, "SA", value);
|
||||
}
|
||||
*/
|
||||
|
||||
Vendored
+231
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_font.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_TextWidth)
|
||||
HPDF_Font_TextWidth (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
HPDF_TextWidth tw = {0, 0, 0, 0};
|
||||
HPDF_FontAttr attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Font_TextWidth\n"));
|
||||
|
||||
if (!HPDF_Font_Validate(font))
|
||||
return tw;
|
||||
|
||||
if (len > HPDF_LIMIT_MAX_STRING_LEN) {
|
||||
HPDF_RaiseError (font->error, HPDF_STRING_OUT_OF_RANGE, 0);
|
||||
return tw;
|
||||
}
|
||||
|
||||
attr = (HPDF_FontAttr)font->attr;
|
||||
|
||||
if (!attr->text_width_fn) {
|
||||
HPDF_SetError (font->error, HPDF_INVALID_OBJECT, 0);
|
||||
return tw;
|
||||
}
|
||||
|
||||
tw = attr->text_width_fn (font, text, len);
|
||||
|
||||
return tw;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_UINT)
|
||||
HPDF_Font_MeasureText (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len,
|
||||
HPDF_REAL width,
|
||||
HPDF_REAL font_size,
|
||||
HPDF_REAL char_space,
|
||||
HPDF_REAL word_space,
|
||||
HPDF_BOOL wordwrap,
|
||||
HPDF_REAL *real_width)
|
||||
{
|
||||
HPDF_FontAttr attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Font_MeasureText\n"));
|
||||
|
||||
if (!HPDF_Font_Validate(font))
|
||||
return 0;
|
||||
|
||||
if (len > HPDF_LIMIT_MAX_STRING_LEN) {
|
||||
HPDF_RaiseError (font->error, HPDF_STRING_OUT_OF_RANGE, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
attr = (HPDF_FontAttr)font->attr;
|
||||
|
||||
if (!attr->measure_text_fn) {
|
||||
HPDF_RaiseError (font->error, HPDF_INVALID_OBJECT, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return attr->measure_text_fn (font, text, len, width, font_size,
|
||||
char_space, word_space, wordwrap, real_width);
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(const char*)
|
||||
HPDF_Font_GetFontName (HPDF_Font font)
|
||||
{
|
||||
HPDF_FontAttr attr;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Font_GetFontName\n"));
|
||||
|
||||
if (!HPDF_Font_Validate(font))
|
||||
return NULL;
|
||||
|
||||
attr = (HPDF_FontAttr)font->attr;
|
||||
|
||||
return attr->fontdef->base_font;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(const char*)
|
||||
HPDF_Font_GetEncodingName (HPDF_Font font)
|
||||
{
|
||||
HPDF_FontAttr attr;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Font_GetEncodingName\n"));
|
||||
|
||||
if (!HPDF_Font_Validate(font))
|
||||
return NULL;
|
||||
|
||||
attr = (HPDF_FontAttr)font->attr;
|
||||
|
||||
return attr->encoder->name;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_INT)
|
||||
HPDF_Font_GetUnicodeWidth (HPDF_Font font,
|
||||
HPDF_UNICODE code)
|
||||
{
|
||||
HPDF_FontAttr attr;
|
||||
HPDF_FontDef fontdef;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Font_GetUnicodeWidth\n"));
|
||||
|
||||
if (!HPDF_Font_Validate(font))
|
||||
return 0;
|
||||
|
||||
attr = (HPDF_FontAttr)font->attr;
|
||||
fontdef = attr->fontdef;
|
||||
|
||||
if (fontdef->type == HPDF_FONTDEF_TYPE_TYPE1) {
|
||||
return HPDF_Type1FontDef_GetWidth (fontdef, code);
|
||||
} else if (fontdef->type == HPDF_FONTDEF_TYPE_TRUETYPE) {
|
||||
return HPDF_TTFontDef_GetCharWidth (fontdef, code);
|
||||
} else if (fontdef->type == HPDF_FONTDEF_TYPE_CID) {
|
||||
HPDF_CMapEncoderAttr encoder_attr =
|
||||
(HPDF_CMapEncoderAttr)attr->encoder->attr;
|
||||
HPDF_UINT l, h;
|
||||
|
||||
for (l = 0; l <= 255; l++) {
|
||||
for (h = 0; h < 255; h++) {
|
||||
if (code == encoder_attr->unicode_map[l][h]) {
|
||||
HPDF_UINT16 cid = encoder_attr->cid_map[l][h];
|
||||
|
||||
return HPDF_CIDFontDef_GetCIDWidth (fontdef, cid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HPDF_PTRACE((" HPDF_Font_GetUnicodeWidth not found (0x%04X)\n", code));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_Box)
|
||||
HPDF_Font_GetBBox (HPDF_Font font)
|
||||
{
|
||||
HPDF_Box bbox = {0, 0, 0, 0};
|
||||
|
||||
HPDF_PTRACE((" HPDF_Font_GetBBox\n"));
|
||||
if (HPDF_Font_Validate(font))
|
||||
return ((HPDF_FontAttr)font->attr)->fontdef->font_bbox;
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_INT)
|
||||
HPDF_Font_GetAscent (HPDF_Font font)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Font_GetAscent\n"));
|
||||
|
||||
if (HPDF_Font_Validate(font))
|
||||
return ((HPDF_FontAttr)font->attr)->fontdef->ascent;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_INT)
|
||||
HPDF_Font_GetDescent (HPDF_Font font)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Font_GetDescent\n"));
|
||||
|
||||
if (HPDF_Font_Validate(font))
|
||||
return ((HPDF_FontAttr)font->attr)->fontdef->descent;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_UINT)
|
||||
HPDF_Font_GetXHeight (HPDF_Font font)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Font_GetXHeight\n"));
|
||||
|
||||
if (HPDF_Font_Validate(font))
|
||||
return ((HPDF_FontAttr)font->attr)->fontdef->x_height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_UINT)
|
||||
HPDF_Font_GetCapHeight (HPDF_Font font)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Font_GetCapHeight\n"));
|
||||
|
||||
if (HPDF_Font_Validate(font))
|
||||
return ((HPDF_FontAttr)font->attr)->fontdef->cap_height;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_Font_Validate (HPDF_Font font)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Font_Validate\n"));
|
||||
|
||||
if (!font || !font->attr || font->header.obj_class !=
|
||||
(HPDF_OSUBCLASS_FONT | HPDF_OCLASS_DICT))
|
||||
return HPDF_FALSE;
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1086
File diff suppressed because it is too large
Load Diff
Vendored
+408
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_font_tt.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_font.h"
|
||||
|
||||
static HPDF_STATUS
|
||||
OnWrite (HPDF_Dict obj,
|
||||
HPDF_Stream stream);
|
||||
|
||||
static HPDF_STATUS
|
||||
BeforeWrite (HPDF_Dict obj);
|
||||
|
||||
|
||||
static void
|
||||
OnFree (HPDF_Dict obj);
|
||||
|
||||
|
||||
static HPDF_INT
|
||||
CharWidth (HPDF_Font font,
|
||||
HPDF_BYTE code);
|
||||
|
||||
static HPDF_TextWidth
|
||||
TextWidth (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
CreateDescriptor (HPDF_Font font);
|
||||
|
||||
|
||||
static HPDF_UINT
|
||||
MeasureText (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len,
|
||||
HPDF_REAL width,
|
||||
HPDF_REAL font_size,
|
||||
HPDF_REAL char_space,
|
||||
HPDF_REAL word_space,
|
||||
HPDF_BOOL wordwrap,
|
||||
HPDF_REAL *real_width);
|
||||
|
||||
|
||||
HPDF_Font
|
||||
HPDF_TTFont_New (HPDF_MMgr mmgr,
|
||||
HPDF_FontDef fontdef,
|
||||
HPDF_Encoder encoder,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Dict font;
|
||||
HPDF_FontAttr attr;
|
||||
HPDF_TTFontDefAttr fontdef_attr;
|
||||
HPDF_BasicEncoderAttr encoder_attr;
|
||||
HPDF_STATUS ret = 0;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_TTFont_New\n"));
|
||||
|
||||
font = HPDF_Dict_New (mmgr);
|
||||
if (!font)
|
||||
return NULL;
|
||||
|
||||
font->header.obj_class |= HPDF_OSUBCLASS_FONT;
|
||||
|
||||
/* check whether the fontdef object and the encoder object is valid. */
|
||||
if (encoder->type != HPDF_ENCODER_TYPE_SINGLE_BYTE) {
|
||||
HPDF_SetError(font->error, HPDF_INVALID_ENCODER_TYPE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fontdef->type != HPDF_FONTDEF_TYPE_TRUETYPE) {
|
||||
HPDF_SetError(font->error, HPDF_INVALID_FONTDEF_TYPE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
attr = HPDF_GetMem (mmgr, sizeof(HPDF_FontAttr_Rec));
|
||||
if (!attr) {
|
||||
HPDF_Dict_Free (font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HPDF_MemSet (attr, 0, sizeof(HPDF_FontAttr_Rec));
|
||||
|
||||
font->header.obj_class |= HPDF_OSUBCLASS_FONT;
|
||||
font->write_fn = OnWrite;
|
||||
font->before_write_fn = BeforeWrite;
|
||||
font->free_fn = OnFree;
|
||||
font->attr = attr;
|
||||
|
||||
attr->type = HPDF_FONT_TRUETYPE;
|
||||
attr->writing_mode = HPDF_WMODE_HORIZONTAL;
|
||||
attr->text_width_fn = TextWidth;
|
||||
attr->measure_text_fn = MeasureText;
|
||||
attr->fontdef = fontdef;
|
||||
attr->encoder = encoder;
|
||||
attr->xref = xref;
|
||||
|
||||
/* singlebyte-font has a widths-array which is an array of 256 signed
|
||||
* short integer.
|
||||
* in the case of type1-font, widths-array for all letters is made in
|
||||
* constructer. but in the case of true-type-font, the array is
|
||||
* initialized at 0, and set when the corresponding character was used
|
||||
* for the first time.
|
||||
*/
|
||||
attr->widths = HPDF_GetMem (mmgr, sizeof(HPDF_INT16) * 256);
|
||||
if (!attr->widths) {
|
||||
HPDF_Dict_Free (font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HPDF_MemSet (attr->widths, 0, sizeof(HPDF_INT16) * 256);
|
||||
|
||||
attr->used = HPDF_GetMem (mmgr, sizeof(HPDF_BYTE) * 256);
|
||||
if (!attr->used) {
|
||||
HPDF_Dict_Free (font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HPDF_MemSet (attr->used, 0, sizeof(HPDF_BYTE) * 256);
|
||||
|
||||
fontdef_attr = (HPDF_TTFontDefAttr)fontdef->attr;
|
||||
|
||||
ret += HPDF_Dict_AddName (font, "Type", "Font");
|
||||
ret += HPDF_Dict_AddName (font, "BaseFont", fontdef_attr->base_font);
|
||||
ret += HPDF_Dict_AddName (font, "Subtype", "TrueType");
|
||||
|
||||
encoder_attr = (HPDF_BasicEncoderAttr)encoder->attr;
|
||||
|
||||
ret += HPDF_Dict_AddNumber (font, "FirstChar", encoder_attr->first_char);
|
||||
ret += HPDF_Dict_AddNumber (font, "LastChar", encoder_attr->last_char);
|
||||
if (fontdef->missing_width != 0)
|
||||
ret += HPDF_Dict_AddNumber (font, "MissingWidth",
|
||||
fontdef->missing_width);
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Xref_Add (xref, font) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
CreateDescriptor (HPDF_Font font)
|
||||
{
|
||||
HPDF_FontAttr font_attr = (HPDF_FontAttr)font->attr;
|
||||
HPDF_FontDef def = font_attr->fontdef;
|
||||
HPDF_TTFontDefAttr def_attr = (HPDF_TTFontDefAttr)def->attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_TTFont_CreateDescriptor\n"));
|
||||
|
||||
if (!font_attr->fontdef->descriptor) {
|
||||
HPDF_Dict descriptor = HPDF_Dict_New (font->mmgr);
|
||||
HPDF_STATUS ret = 0;
|
||||
HPDF_Array array;
|
||||
|
||||
if (!descriptor)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
ret += HPDF_Xref_Add (font_attr->xref, descriptor);
|
||||
ret += HPDF_Dict_AddName (descriptor, "Type", "FontDescriptor");
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "Ascent", def->ascent);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "Descent", def->descent);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "CapHeight", def->cap_height);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "Flags", def->flags);
|
||||
|
||||
array = HPDF_Box_Array_New (font->mmgr, def->font_bbox);
|
||||
ret += HPDF_Dict_Add (descriptor, "FontBBox", array);
|
||||
|
||||
ret += HPDF_Dict_AddName (descriptor, "FontName", def_attr->base_font);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "ItalicAngle",
|
||||
def->italic_angle);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "StemV", def->stemv);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "XHeight", def->x_height);
|
||||
|
||||
if (def_attr->char_set)
|
||||
ret += HPDF_Dict_AddName (descriptor, "CharSet",
|
||||
def_attr->char_set);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
if (def_attr->embedding) {
|
||||
HPDF_Dict font_data = HPDF_DictStream_New (font->mmgr,
|
||||
font_attr->xref);
|
||||
|
||||
if (!font_data)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
if (HPDF_TTFontDef_SaveFontData (font_attr->fontdef,
|
||||
font_data->stream) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
ret += HPDF_Dict_Add (descriptor, "FontFile2", font_data);
|
||||
ret += HPDF_Dict_AddNumber (font_data, "Length1",
|
||||
def_attr->length1);
|
||||
ret += HPDF_Dict_AddNumber (font_data, "Length2", 0);
|
||||
ret += HPDF_Dict_AddNumber (font_data, "Length3", 0);
|
||||
|
||||
font_data->filter = font->filter;
|
||||
}
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
font_attr->fontdef->descriptor = descriptor;
|
||||
}
|
||||
|
||||
return HPDF_Dict_Add (font, "FontDescriptor",
|
||||
font_attr->fontdef->descriptor);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_INT
|
||||
CharWidth (HPDF_Font font,
|
||||
HPDF_BYTE code)
|
||||
{
|
||||
HPDF_FontAttr attr = (HPDF_FontAttr)font->attr;
|
||||
|
||||
if (attr->used[code] == 0) {
|
||||
HPDF_UNICODE unicode = HPDF_Encoder_ToUnicode (attr->encoder, code);
|
||||
|
||||
attr->used[code] = 1;
|
||||
attr->widths[code] = HPDF_TTFontDef_GetCharWidth(attr->fontdef,
|
||||
unicode);
|
||||
}
|
||||
|
||||
return attr->widths[code];
|
||||
}
|
||||
|
||||
|
||||
static HPDF_TextWidth
|
||||
TextWidth (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
HPDF_FontAttr attr = (HPDF_FontAttr)font->attr;
|
||||
HPDF_TextWidth ret = {0, 0, 0, 0};
|
||||
HPDF_UINT i;
|
||||
HPDF_BYTE b = 0;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_TTFont_TextWidth\n"));
|
||||
|
||||
if (attr->widths) {
|
||||
for (i = 0; i < len; i++) {
|
||||
b = text[i];
|
||||
ret.numchars++;
|
||||
ret.width += CharWidth (font, b);
|
||||
|
||||
if (HPDF_IS_WHITE_SPACE(b)) {
|
||||
ret.numspace++;
|
||||
ret.numwords++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
HPDF_SetError (font->error, HPDF_FONT_INVALID_WIDTHS_TABLE, 0);
|
||||
|
||||
/* 2006.08.19 add. */
|
||||
if (HPDF_IS_WHITE_SPACE(b))
|
||||
; /* do nothing. */
|
||||
else
|
||||
ret.numwords++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_UINT
|
||||
MeasureText (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len,
|
||||
HPDF_REAL width,
|
||||
HPDF_REAL font_size,
|
||||
HPDF_REAL char_space,
|
||||
HPDF_REAL word_space,
|
||||
HPDF_BOOL wordwrap,
|
||||
HPDF_REAL *real_width)
|
||||
{
|
||||
HPDF_DOUBLE w = 0;
|
||||
HPDF_UINT tmp_len = 0;
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_TTFont_MeasureText\n"));
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
HPDF_BYTE b = text[i];
|
||||
|
||||
if (HPDF_IS_WHITE_SPACE(b)) {
|
||||
tmp_len = i + 1;
|
||||
|
||||
if (real_width)
|
||||
*real_width = (HPDF_REAL)w;
|
||||
|
||||
w += word_space;
|
||||
} else if (!wordwrap) {
|
||||
tmp_len = i;
|
||||
|
||||
if (real_width)
|
||||
*real_width = (HPDF_REAL)w;
|
||||
}
|
||||
|
||||
w += (HPDF_DOUBLE)CharWidth (font, b) * font_size / 1000;
|
||||
|
||||
/* 2006.08.04 break when it encountered line feed */
|
||||
if (w > width || b == 0x0A)
|
||||
return tmp_len;
|
||||
|
||||
if (i > 0)
|
||||
w += char_space;
|
||||
}
|
||||
|
||||
/* all of text can be put in the specified width */
|
||||
if (real_width)
|
||||
*real_width = (HPDF_REAL)w;
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
OnWrite (HPDF_Dict obj,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr;
|
||||
HPDF_BasicEncoderAttr encoder_attr =
|
||||
(HPDF_BasicEncoderAttr)attr->encoder->attr;
|
||||
HPDF_UINT i;
|
||||
HPDF_STATUS ret;
|
||||
char buf[128];
|
||||
char *pbuf = buf;
|
||||
char *eptr = buf + 127;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Font_OnWrite\n"));
|
||||
|
||||
/* Widths entry */
|
||||
if ((ret = HPDF_Stream_WriteEscapeName (stream, "Widths")) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, " [\012")) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
for (i = encoder_attr->first_char; i <= encoder_attr->last_char; i++) {
|
||||
|
||||
pbuf = HPDF_IToA (pbuf, attr->widths[i], eptr);
|
||||
*pbuf++ = ' ';
|
||||
|
||||
if ((i + 1) % 16 == 0) {
|
||||
HPDF_StrCpy(pbuf, "\012", eptr);
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
|
||||
return ret;
|
||||
pbuf = buf;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HPDF_StrCpy (pbuf, "]\012", eptr);
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return attr->encoder->write_fn (attr->encoder, stream);
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
BeforeWrite (HPDF_Dict obj)
|
||||
{
|
||||
HPDF_PTRACE ((" HPDF_TTFont_BeforeWrite\n"));
|
||||
|
||||
return CreateDescriptor (obj);
|
||||
}
|
||||
|
||||
static void
|
||||
OnFree (HPDF_Dict obj)
|
||||
{
|
||||
HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_TTFont_OnFree\n"));
|
||||
|
||||
if (attr) {
|
||||
if (attr->widths) {
|
||||
HPDF_FreeMem (obj->mmgr, attr->widths);
|
||||
}
|
||||
|
||||
if (attr->used) {
|
||||
HPDF_FreeMem (obj->mmgr, attr->used);
|
||||
}
|
||||
|
||||
HPDF_FreeMem (obj->mmgr, attr);
|
||||
}
|
||||
}
|
||||
+394
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_font_type1.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_font.h"
|
||||
|
||||
static HPDF_STATUS
|
||||
Type1Font_OnWrite (HPDF_Dict obj,
|
||||
HPDF_Stream stream);
|
||||
|
||||
|
||||
static void
|
||||
Type1Font_OnFree (HPDF_Dict obj);
|
||||
|
||||
|
||||
static HPDF_TextWidth
|
||||
Type1Font_TextWidth (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len);
|
||||
|
||||
|
||||
static HPDF_UINT
|
||||
Type1Font_MeasureText (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len,
|
||||
HPDF_REAL width,
|
||||
HPDF_REAL font_size,
|
||||
HPDF_REAL char_space,
|
||||
HPDF_REAL word_space,
|
||||
HPDF_BOOL wordwrap,
|
||||
HPDF_REAL *real_width);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
Type1Font_CreateDescriptor (HPDF_MMgr mmgr,
|
||||
HPDF_Font font,
|
||||
HPDF_Xref xref);
|
||||
|
||||
|
||||
HPDF_Font
|
||||
HPDF_Type1Font_New (HPDF_MMgr mmgr,
|
||||
HPDF_FontDef fontdef,
|
||||
HPDF_Encoder encoder,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Dict font;
|
||||
HPDF_FontAttr attr;
|
||||
HPDF_Type1FontDefAttr fontdef_attr;
|
||||
HPDF_BasicEncoderAttr encoder_attr;
|
||||
HPDF_STATUS ret = 0;
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1Font_New\n"));
|
||||
|
||||
/* check whether the fontdef object and the encoder object is valid. */
|
||||
if (encoder->type != HPDF_ENCODER_TYPE_SINGLE_BYTE) {
|
||||
HPDF_SetError(mmgr->error, HPDF_INVALID_ENCODER_TYPE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fontdef->type != HPDF_FONTDEF_TYPE_TYPE1) {
|
||||
HPDF_SetError(mmgr->error, HPDF_INVALID_FONTDEF_TYPE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
font = HPDF_Dict_New (mmgr);
|
||||
if (!font)
|
||||
return NULL;
|
||||
|
||||
font->header.obj_class |= HPDF_OSUBCLASS_FONT;
|
||||
|
||||
attr = HPDF_GetMem (mmgr, sizeof(HPDF_FontAttr_Rec));
|
||||
if (!attr) {
|
||||
HPDF_Dict_Free (font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
font->header.obj_class |= HPDF_OSUBCLASS_FONT;
|
||||
font->write_fn = Type1Font_OnWrite;
|
||||
font->free_fn = Type1Font_OnFree;
|
||||
|
||||
HPDF_MemSet (attr, 0, sizeof(HPDF_FontAttr_Rec));
|
||||
|
||||
font->attr = attr;
|
||||
attr->type = HPDF_FONT_TYPE1;
|
||||
attr->writing_mode = HPDF_WMODE_HORIZONTAL;
|
||||
attr->text_width_fn = Type1Font_TextWidth;
|
||||
attr->measure_text_fn = Type1Font_MeasureText;
|
||||
attr->fontdef = fontdef;
|
||||
attr->encoder = encoder;
|
||||
attr->xref = xref;
|
||||
|
||||
/* singlebyte-font has a widths-array which is an array of 256 signed
|
||||
* short integer.
|
||||
*/
|
||||
attr->widths = HPDF_GetMem (mmgr, sizeof(HPDF_INT16) * 256);
|
||||
if (!attr->widths) {
|
||||
HPDF_Dict_Free (font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
encoder_attr = (HPDF_BasicEncoderAttr)encoder->attr;
|
||||
|
||||
HPDF_MemSet (attr->widths, 0, sizeof(HPDF_INT16) * 256);
|
||||
for (i = encoder_attr->first_char; i <= encoder_attr->last_char; i++) {
|
||||
HPDF_UNICODE u = encoder_attr->unicode_map[i];
|
||||
|
||||
HPDF_UINT16 w = HPDF_Type1FontDef_GetWidth (fontdef, u);
|
||||
attr->widths[i] = w;
|
||||
}
|
||||
|
||||
fontdef_attr = (HPDF_Type1FontDefAttr)fontdef->attr;
|
||||
|
||||
ret += HPDF_Dict_AddName (font, "Type", "Font");
|
||||
ret += HPDF_Dict_AddName (font, "BaseFont", fontdef->base_font);
|
||||
ret += HPDF_Dict_AddName (font, "Subtype", "Type1");
|
||||
|
||||
if (!fontdef_attr->is_base14font) {
|
||||
if (fontdef->missing_width != 0)
|
||||
ret += HPDF_Dict_AddNumber (font, "MissingWidth",
|
||||
fontdef->missing_width);
|
||||
|
||||
ret += Type1Font_CreateDescriptor (mmgr, font, xref);
|
||||
}
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Xref_Add (xref, font) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
Type1Font_CreateDescriptor (HPDF_MMgr mmgr,
|
||||
HPDF_Font font,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_FontAttr font_attr = (HPDF_FontAttr)font->attr;
|
||||
HPDF_FontDef def = font_attr->fontdef;
|
||||
HPDF_Type1FontDefAttr def_attr = (HPDF_Type1FontDefAttr)def->attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1Font_CreateDescriptor\n"));
|
||||
|
||||
if (!font_attr->fontdef->descriptor) {
|
||||
HPDF_Dict descriptor = HPDF_Dict_New (mmgr);
|
||||
HPDF_STATUS ret = 0;
|
||||
HPDF_Array array;
|
||||
|
||||
if (!descriptor)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
ret += HPDF_Xref_Add (xref, descriptor);
|
||||
ret += HPDF_Dict_AddName (descriptor, "Type", "FontDescriptor");
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "Ascent", def->ascent);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "Descent", def->descent);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "Flags", def->flags);
|
||||
|
||||
array = HPDF_Box_Array_New (mmgr, def->font_bbox);
|
||||
ret += HPDF_Dict_Add (descriptor, "FontBBox", array);
|
||||
|
||||
ret += HPDF_Dict_AddName (descriptor, "FontName",
|
||||
font_attr->fontdef->base_font);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "ItalicAngle",
|
||||
def->italic_angle);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "StemV", def->stemv);
|
||||
ret += HPDF_Dict_AddNumber (descriptor, "XHeight", def->x_height);
|
||||
|
||||
if (def_attr->char_set)
|
||||
ret += HPDF_Dict_AddName (descriptor, "CharSet",
|
||||
def_attr->char_set);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
if (def_attr->font_data) {
|
||||
HPDF_Dict font_data = HPDF_DictStream_New (mmgr, xref);
|
||||
|
||||
if (!font_data)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
if (HPDF_Stream_WriteToStream (def_attr->font_data,
|
||||
font_data->stream, HPDF_STREAM_FILTER_NONE, NULL) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
ret += HPDF_Dict_Add (descriptor, "FontFile", font_data);
|
||||
ret += HPDF_Dict_AddNumber (font_data, "Length1",
|
||||
def_attr->length1);
|
||||
ret += HPDF_Dict_AddNumber (font_data, "Length2",
|
||||
def_attr->length2);
|
||||
ret += HPDF_Dict_AddNumber (font_data, "Length3",
|
||||
def_attr->length3);
|
||||
|
||||
font_data->filter = font->filter;
|
||||
}
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_Error_GetCode (font->error);
|
||||
|
||||
font_attr->fontdef->descriptor = descriptor;
|
||||
}
|
||||
|
||||
return HPDF_Dict_Add (font, "FontDescriptor",
|
||||
font_attr->fontdef->descriptor);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_TextWidth
|
||||
Type1Font_TextWidth (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
HPDF_FontAttr attr = (HPDF_FontAttr)font->attr;
|
||||
HPDF_TextWidth ret = {0, 0, 0, 0};
|
||||
HPDF_UINT i;
|
||||
HPDF_BYTE b = 0;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1Font_TextWidth\n"));
|
||||
|
||||
if (attr->widths) {
|
||||
for (i = 0; i < len; i++) {
|
||||
b = text[i];
|
||||
ret.numchars++;
|
||||
ret.width += attr->widths[b];
|
||||
|
||||
if (HPDF_IS_WHITE_SPACE(b)) {
|
||||
ret.numspace++;
|
||||
ret.numwords++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
HPDF_SetError (font->error, HPDF_FONT_INVALID_WIDTHS_TABLE, 0);
|
||||
|
||||
/* 2006.08.19 add. */
|
||||
if (HPDF_IS_WHITE_SPACE(b))
|
||||
; /* do nothing. */
|
||||
else
|
||||
ret.numwords++;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_UINT
|
||||
Type1Font_MeasureText (HPDF_Font font,
|
||||
const HPDF_BYTE *text,
|
||||
HPDF_UINT len,
|
||||
HPDF_REAL width,
|
||||
HPDF_REAL font_size,
|
||||
HPDF_REAL char_space,
|
||||
HPDF_REAL word_space,
|
||||
HPDF_BOOL wordwrap,
|
||||
HPDF_REAL *real_width)
|
||||
{
|
||||
HPDF_REAL w = 0;
|
||||
HPDF_UINT tmp_len = 0;
|
||||
HPDF_UINT i;
|
||||
HPDF_FontAttr attr = (HPDF_FontAttr)font->attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1Font_MeasureText\n"));
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
HPDF_BYTE b = text[i];
|
||||
|
||||
if (HPDF_IS_WHITE_SPACE(b)) {
|
||||
tmp_len = i + 1;
|
||||
|
||||
if (real_width)
|
||||
*real_width = w;
|
||||
|
||||
w += word_space;
|
||||
} else if (!wordwrap) {
|
||||
tmp_len = i;
|
||||
|
||||
if (real_width)
|
||||
*real_width = w;
|
||||
}
|
||||
|
||||
w += attr->widths[b] * font_size / 1000;
|
||||
|
||||
/* 2006.08.04 break when it encountered line feed */
|
||||
if (w > width || b == 0x0A)
|
||||
return tmp_len;
|
||||
|
||||
if (i > 0)
|
||||
w += char_space;
|
||||
}
|
||||
|
||||
/* all of text can be put in the specified width */
|
||||
if (real_width)
|
||||
*real_width = w;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
Type1Font_OnWrite (HPDF_Dict obj,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr;
|
||||
HPDF_Type1FontDefAttr fontdef_attr =
|
||||
(HPDF_Type1FontDefAttr)attr->fontdef->attr;
|
||||
HPDF_BasicEncoderAttr encoder_attr =
|
||||
(HPDF_BasicEncoderAttr)attr->encoder->attr;
|
||||
HPDF_UINT i;
|
||||
HPDF_STATUS ret;
|
||||
char buf[HPDF_TMP_BUF_SIZ];
|
||||
char *eptr = buf + HPDF_TMP_BUF_SIZ - 1;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Font_Type1Font_OnWrite\n"));
|
||||
|
||||
/* if font is base14-font these entries is not required */
|
||||
if (!fontdef_attr->is_base14font || encoder_attr->has_differences) {
|
||||
char *pbuf;
|
||||
|
||||
pbuf = (char *)HPDF_StrCpy (buf, "/FirstChar ", eptr);
|
||||
pbuf = HPDF_IToA (pbuf, encoder_attr->first_char, eptr);
|
||||
HPDF_StrCpy (pbuf, "\012", eptr);
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
pbuf = (char *)HPDF_StrCpy (buf, "/LastChar ", eptr);
|
||||
pbuf = HPDF_IToA (pbuf, encoder_attr->last_char, eptr);
|
||||
HPDF_StrCpy (pbuf, "\012", eptr);
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
/* Widths entry */
|
||||
if ((ret = HPDF_Stream_WriteEscapeName (stream, "Widths")) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, " [\012")) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
pbuf = buf;
|
||||
for (i = encoder_attr->first_char; i <= encoder_attr->last_char; i++) {
|
||||
|
||||
pbuf = HPDF_IToA (pbuf, attr->widths[i], eptr);
|
||||
*pbuf++ = ' ';
|
||||
|
||||
if ((i + 1) % 16 == 0) {
|
||||
HPDF_StrCpy(pbuf, "\012", eptr);
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
|
||||
return ret;
|
||||
pbuf = buf;
|
||||
}
|
||||
}
|
||||
|
||||
HPDF_StrCpy (pbuf, "]\012", eptr);
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return attr->encoder->write_fn (attr->encoder, stream);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Type1Font_OnFree (HPDF_Dict obj)
|
||||
{
|
||||
HPDF_FontAttr attr = (HPDF_FontAttr)obj->attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1Font_OnFree\n"));
|
||||
|
||||
if (attr) {
|
||||
if (attr->widths) {
|
||||
HPDF_FreeMem (obj->mmgr, attr->widths);
|
||||
}
|
||||
HPDF_FreeMem (obj->mmgr, attr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_fontdef.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_fontdef.h"
|
||||
|
||||
void
|
||||
HPDF_FontDef_Cleanup (HPDF_FontDef fontdef)
|
||||
{
|
||||
if (!fontdef)
|
||||
return;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_FontDef_Cleanup\n"));
|
||||
|
||||
if (fontdef->clean_fn)
|
||||
fontdef->clean_fn (fontdef);
|
||||
|
||||
fontdef->descriptor = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
HPDF_FontDef_Free (HPDF_FontDef fontdef)
|
||||
{
|
||||
if (!fontdef)
|
||||
return;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_FontDef_Free\n"));
|
||||
|
||||
if (fontdef->free_fn)
|
||||
fontdef->free_fn (fontdef);
|
||||
HPDF_FreeMem (fontdef->mmgr, fontdef);
|
||||
}
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_FontDef_Validate (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_PTRACE ((" HPDF_FontDef_Validate\n"));
|
||||
|
||||
if (!fontdef || fontdef->sig_bytes != HPDF_FONTDEF_SIG_BYTES)
|
||||
return HPDF_FALSE;
|
||||
else
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
+4508
File diff suppressed because it is too large
Load Diff
+197
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_fontdef_cid.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_fontdef.h"
|
||||
|
||||
void
|
||||
HPDF_CIDFontDef_FreeWidth (HPDF_FontDef fontdef);
|
||||
|
||||
|
||||
void
|
||||
HPDF_CIDFontDef_FreeFunc (HPDF_FontDef fontdef);
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
/*----- HPDF_CIDFontDef ------------------------------------------------*/
|
||||
|
||||
void
|
||||
HPDF_CIDFontDef_FreeWidth (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_CIDFontDefAttr attr = (HPDF_CIDFontDefAttr)fontdef->attr;
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_FontDef_Validate\n"));
|
||||
|
||||
for (i = 0; i < attr->widths->count; i++) {
|
||||
HPDF_CID_Width *w =
|
||||
(HPDF_CID_Width *)HPDF_List_ItemAt (attr->widths, i);
|
||||
|
||||
HPDF_FreeMem (fontdef->mmgr, w);
|
||||
}
|
||||
|
||||
HPDF_List_Free (attr->widths);
|
||||
attr->widths = NULL;
|
||||
|
||||
fontdef->valid = HPDF_FALSE;
|
||||
}
|
||||
|
||||
|
||||
HPDF_FontDef
|
||||
HPDF_CIDFontDef_New (HPDF_MMgr mmgr,
|
||||
char *name,
|
||||
HPDF_FontDef_InitFunc init_fn)
|
||||
{
|
||||
HPDF_FontDef fontdef;
|
||||
HPDF_CIDFontDefAttr fontdef_attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_CIDFontDef_New\n"));
|
||||
|
||||
if (!mmgr)
|
||||
return NULL;
|
||||
|
||||
fontdef = HPDF_GetMem (mmgr, sizeof(HPDF_FontDef_Rec));
|
||||
if (!fontdef)
|
||||
return NULL;
|
||||
|
||||
HPDF_MemSet (fontdef, 0, sizeof(HPDF_FontDef_Rec));
|
||||
fontdef->sig_bytes = HPDF_FONTDEF_SIG_BYTES;
|
||||
HPDF_StrCpy (fontdef->base_font, name, fontdef->base_font +
|
||||
HPDF_LIMIT_MAX_NAME_LEN);
|
||||
fontdef->mmgr = mmgr;
|
||||
fontdef->error = mmgr->error;
|
||||
fontdef->type = HPDF_FONTDEF_TYPE_UNINITIALIZED;
|
||||
fontdef->free_fn = HPDF_CIDFontDef_FreeFunc;
|
||||
fontdef->init_fn = init_fn;
|
||||
fontdef->valid = HPDF_FALSE;
|
||||
fontdef_attr = HPDF_GetMem (mmgr, sizeof(HPDF_CIDFontDefAttr_Rec));
|
||||
if (!fontdef_attr) {
|
||||
HPDF_FreeMem (fontdef->mmgr, fontdef);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fontdef->attr = fontdef_attr;
|
||||
HPDF_MemSet ((HPDF_BYTE *)fontdef_attr, 0,
|
||||
sizeof(HPDF_CIDFontDefAttr_Rec));
|
||||
|
||||
fontdef_attr->widths = HPDF_List_New (mmgr, HPDF_DEF_CHAR_WIDTHS_NUM);
|
||||
if (!fontdef_attr->widths) {
|
||||
HPDF_FreeMem (fontdef->mmgr, fontdef);
|
||||
HPDF_FreeMem (fontdef->mmgr, fontdef_attr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fontdef->missing_width = 500;
|
||||
fontdef_attr->DW = 1000;
|
||||
fontdef_attr->DW2[0] = 880;
|
||||
fontdef_attr->DW2[1] = -1000;
|
||||
|
||||
return fontdef;
|
||||
}
|
||||
|
||||
|
||||
HPDF_INT16
|
||||
HPDF_CIDFontDef_GetCIDWidth (HPDF_FontDef fontdef,
|
||||
HPDF_UINT16 cid)
|
||||
{
|
||||
HPDF_CIDFontDefAttr attr = (HPDF_CIDFontDefAttr)fontdef->attr;
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_CIDFontDef_GetCIDWidth\n"));
|
||||
|
||||
for (i = 0; i < attr->widths->count; i++) {
|
||||
HPDF_CID_Width *w = (HPDF_CID_Width *)HPDF_List_ItemAt (attr->widths,
|
||||
i);
|
||||
|
||||
if (w->cid == cid)
|
||||
return w->width;
|
||||
}
|
||||
|
||||
/* Not found in pdf_cid_width array. */
|
||||
return attr->DW;
|
||||
}
|
||||
|
||||
void
|
||||
HPDF_CIDFontDef_FreeFunc (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_CIDFontDefAttr attr = (HPDF_CIDFontDefAttr)fontdef->attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_CIDFontDef_FreeFunc\n"));
|
||||
|
||||
HPDF_CIDFontDef_FreeWidth (fontdef);
|
||||
HPDF_FreeMem (fontdef->mmgr, attr);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_CIDFontDef_AddWidth (HPDF_FontDef fontdef,
|
||||
const HPDF_CID_Width *widths)
|
||||
{
|
||||
HPDF_CIDFontDefAttr attr = (HPDF_CIDFontDefAttr)fontdef->attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_CIDFontDef_AddWidth\n"));
|
||||
|
||||
while (widths->cid != 0xFFFF) {
|
||||
HPDF_CID_Width *w = HPDF_GetMem (fontdef->mmgr,
|
||||
sizeof (HPDF_CID_Width));
|
||||
HPDF_STATUS ret;
|
||||
|
||||
if (!w)
|
||||
return fontdef->error->error_no;
|
||||
|
||||
w->cid = widths->cid;
|
||||
w->width = widths->width;
|
||||
|
||||
if ((ret = HPDF_List_Add (attr->widths, w)) != HPDF_OK) {
|
||||
HPDF_FreeMem (fontdef->mmgr, w);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
widths++;
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_CIDFontDef_ChangeStyle (HPDF_FontDef fontdef,
|
||||
HPDF_BOOL bold,
|
||||
HPDF_BOOL italic)
|
||||
{
|
||||
HPDF_PTRACE ((" HPDF_CIDFontDef_ChangeStyle\n"));
|
||||
|
||||
if (!fontdef || !fontdef->attr)
|
||||
return HPDF_INVALID_FONTDEF_DATA;
|
||||
|
||||
if (bold) {
|
||||
fontdef->stemv *= 2;
|
||||
fontdef->flags |= HPDF_FONT_FOURCE_BOLD;
|
||||
}
|
||||
|
||||
if (italic) {
|
||||
fontdef->italic_angle -= 11;
|
||||
fontdef->flags |= HPDF_FONT_ITALIC;
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+474
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_fontdef_cns.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
static const HPDF_CID_Width SIMSUN_W_ARRAY[] = {
|
||||
{668, 500},
|
||||
{669, 500},
|
||||
{670, 500},
|
||||
{671, 500},
|
||||
{672, 500},
|
||||
{673, 500},
|
||||
{674, 500},
|
||||
{675, 500},
|
||||
{676, 500},
|
||||
{677, 500},
|
||||
{678, 500},
|
||||
{679, 500},
|
||||
{680, 500},
|
||||
{681, 500},
|
||||
{682, 500},
|
||||
{683, 500},
|
||||
{684, 500},
|
||||
{685, 500},
|
||||
{686, 500},
|
||||
{687, 500},
|
||||
{688, 500},
|
||||
{689, 500},
|
||||
{690, 500},
|
||||
{691, 500},
|
||||
{692, 500},
|
||||
{693, 500},
|
||||
{694, 500},
|
||||
{696, 500},
|
||||
{697, 500},
|
||||
{698, 500},
|
||||
{699, 500},
|
||||
{814, 500},
|
||||
{815, 500},
|
||||
{816, 500},
|
||||
{817, 500},
|
||||
{818, 500},
|
||||
{819, 500},
|
||||
{820, 500},
|
||||
{821, 500},
|
||||
{822, 500},
|
||||
{823, 500},
|
||||
{824, 500},
|
||||
{825, 500},
|
||||
{826, 500},
|
||||
{827, 500},
|
||||
{828, 500},
|
||||
{829, 500},
|
||||
{830, 500},
|
||||
{831, 500},
|
||||
{832, 500},
|
||||
{833, 500},
|
||||
{834, 500},
|
||||
{835, 500},
|
||||
{836, 500},
|
||||
{837, 500},
|
||||
{838, 500},
|
||||
{839, 500},
|
||||
{840, 500},
|
||||
{841, 500},
|
||||
{842, 500},
|
||||
{843, 500},
|
||||
{844, 500},
|
||||
{845, 500},
|
||||
{846, 500},
|
||||
{847, 500},
|
||||
{848, 500},
|
||||
{849, 500},
|
||||
{850, 500},
|
||||
{851, 500},
|
||||
{852, 500},
|
||||
{853, 500},
|
||||
{854, 500},
|
||||
{855, 500},
|
||||
{856, 500},
|
||||
{857, 500},
|
||||
{858, 500},
|
||||
{859, 500},
|
||||
{860, 500},
|
||||
{861, 500},
|
||||
{862, 500},
|
||||
{863, 500},
|
||||
{864, 500},
|
||||
{865, 500},
|
||||
{866, 500},
|
||||
{867, 500},
|
||||
{868, 500},
|
||||
{869, 500},
|
||||
{870, 500},
|
||||
{871, 500},
|
||||
{872, 500},
|
||||
{873, 500},
|
||||
{874, 500},
|
||||
{875, 500},
|
||||
{876, 500},
|
||||
{877, 500},
|
||||
{878, 500},
|
||||
{879, 500},
|
||||
{880, 500},
|
||||
{881, 500},
|
||||
{882, 500},
|
||||
{883, 500},
|
||||
{884, 500},
|
||||
{885, 500},
|
||||
{886, 500},
|
||||
{887, 500},
|
||||
{888, 500},
|
||||
{889, 500},
|
||||
{890, 500},
|
||||
{891, 500},
|
||||
{892, 500},
|
||||
{893, 500},
|
||||
{894, 500},
|
||||
{895, 500},
|
||||
{896, 500},
|
||||
{897, 500},
|
||||
{898, 500},
|
||||
{899, 500},
|
||||
{900, 500},
|
||||
{901, 500},
|
||||
{902, 500},
|
||||
{903, 500},
|
||||
{904, 500},
|
||||
{905, 500},
|
||||
{906, 500},
|
||||
{907, 500},
|
||||
{7716, 500},
|
||||
{0xFFFF, 0}
|
||||
};
|
||||
|
||||
|
||||
static const HPDF_CID_Width SIMHEI_W_ARRAY[] = {
|
||||
{668, 500},
|
||||
{669, 500},
|
||||
{670, 500},
|
||||
{671, 500},
|
||||
{672, 500},
|
||||
{673, 500},
|
||||
{674, 500},
|
||||
{675, 500},
|
||||
{676, 500},
|
||||
{677, 500},
|
||||
{678, 500},
|
||||
{679, 500},
|
||||
{680, 500},
|
||||
{681, 500},
|
||||
{682, 500},
|
||||
{683, 500},
|
||||
{684, 500},
|
||||
{685, 500},
|
||||
{686, 500},
|
||||
{687, 500},
|
||||
{688, 500},
|
||||
{689, 500},
|
||||
{690, 500},
|
||||
{691, 500},
|
||||
{692, 500},
|
||||
{693, 500},
|
||||
{694, 500},
|
||||
{696, 500},
|
||||
{697, 500},
|
||||
{698, 500},
|
||||
{699, 500},
|
||||
{814, 500},
|
||||
{815, 500},
|
||||
{816, 500},
|
||||
{817, 500},
|
||||
{818, 500},
|
||||
{819, 500},
|
||||
{820, 500},
|
||||
{821, 500},
|
||||
{822, 500},
|
||||
{823, 500},
|
||||
{824, 500},
|
||||
{825, 500},
|
||||
{826, 500},
|
||||
{827, 500},
|
||||
{828, 500},
|
||||
{829, 500},
|
||||
{830, 500},
|
||||
{831, 500},
|
||||
{832, 500},
|
||||
{833, 500},
|
||||
{834, 500},
|
||||
{835, 500},
|
||||
{836, 500},
|
||||
{837, 500},
|
||||
{838, 500},
|
||||
{839, 500},
|
||||
{840, 500},
|
||||
{841, 500},
|
||||
{842, 500},
|
||||
{843, 500},
|
||||
{844, 500},
|
||||
{845, 500},
|
||||
{846, 500},
|
||||
{847, 500},
|
||||
{848, 500},
|
||||
{849, 500},
|
||||
{850, 500},
|
||||
{851, 500},
|
||||
{852, 500},
|
||||
{853, 500},
|
||||
{854, 500},
|
||||
{855, 500},
|
||||
{856, 500},
|
||||
{857, 500},
|
||||
{858, 500},
|
||||
{859, 500},
|
||||
{860, 500},
|
||||
{861, 500},
|
||||
{862, 500},
|
||||
{863, 500},
|
||||
{864, 500},
|
||||
{865, 500},
|
||||
{866, 500},
|
||||
{867, 500},
|
||||
{868, 500},
|
||||
{869, 500},
|
||||
{870, 500},
|
||||
{871, 500},
|
||||
{872, 500},
|
||||
{873, 500},
|
||||
{874, 500},
|
||||
{875, 500},
|
||||
{876, 500},
|
||||
{877, 500},
|
||||
{878, 500},
|
||||
{879, 500},
|
||||
{880, 500},
|
||||
{881, 500},
|
||||
{882, 500},
|
||||
{883, 500},
|
||||
{884, 500},
|
||||
{885, 500},
|
||||
{886, 500},
|
||||
{887, 500},
|
||||
{888, 500},
|
||||
{889, 500},
|
||||
{890, 500},
|
||||
{891, 500},
|
||||
{892, 500},
|
||||
{893, 500},
|
||||
{894, 500},
|
||||
{895, 500},
|
||||
{896, 500},
|
||||
{897, 500},
|
||||
{898, 500},
|
||||
{899, 500},
|
||||
{900, 500},
|
||||
{901, 500},
|
||||
{902, 500},
|
||||
{903, 500},
|
||||
{904, 500},
|
||||
{905, 500},
|
||||
{906, 500},
|
||||
{907, 500},
|
||||
{7716, 500},
|
||||
{0xFFFF, 0}
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*----- SimHei Font ---------------------------------------------------------*/
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
SimSun_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_FontDef_SimSun_Init\n"));
|
||||
|
||||
fontdef->ascent = 859;
|
||||
fontdef->descent = -140;
|
||||
fontdef->cap_height = 683;
|
||||
fontdef->font_bbox = HPDF_ToBox(0, -140, 996, 855);
|
||||
fontdef->flags = HPDF_FONT_SYMBOLIC + HPDF_FONT_FIXED_WIDTH +
|
||||
HPDF_FONT_SERIF;
|
||||
fontdef->italic_angle = 0;
|
||||
fontdef->stemv = 78;
|
||||
if ((ret = HPDF_CIDFontDef_AddWidth (fontdef, SIMSUN_W_ARRAY)) !=
|
||||
HPDF_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
fontdef->type = HPDF_FONTDEF_TYPE_CID;
|
||||
fontdef->valid = HPDF_TRUE;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
SimSun_Bold_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = SimSun_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_TRUE, HPDF_FALSE);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
SimSun_Italic_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = SimSun_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_FALSE, HPDF_TRUE);
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
SimSun_BoldItalic_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = SimSun_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_TRUE, HPDF_TRUE);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
SimHei_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_FontDef_SimHei_Init\n"));
|
||||
|
||||
fontdef->ascent = 859;
|
||||
fontdef->descent = -140;
|
||||
fontdef->cap_height = 769;
|
||||
fontdef->font_bbox = HPDF_ToBox(-0, -140, 996, 855);
|
||||
fontdef->flags = HPDF_FONT_SYMBOLIC + HPDF_FONT_FIXED_WIDTH;
|
||||
fontdef->italic_angle = 0;
|
||||
fontdef->stemv = 78;
|
||||
if ((ret = HPDF_CIDFontDef_AddWidth (fontdef, SIMHEI_W_ARRAY)) !=
|
||||
HPDF_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
fontdef->type = HPDF_FONTDEF_TYPE_CID;
|
||||
fontdef->valid = HPDF_TRUE;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
SimHei_Bold_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = SimHei_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_TRUE, HPDF_FALSE);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
SimHei_Italic_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = SimHei_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_FALSE, HPDF_TRUE);
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
SimHei_BoldItalic_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = SimHei_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_TRUE, HPDF_TRUE);
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_UseCNSFonts (HPDF_Doc pdf)
|
||||
{
|
||||
HPDF_FontDef fontdef;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
if (!HPDF_HasDoc (pdf))
|
||||
return HPDF_INVALID_DOCUMENT;
|
||||
|
||||
/* SimSun */
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "SimSun",
|
||||
SimSun_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "SimSun,Bold",
|
||||
SimSun_Bold_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "SimSun,Italic",
|
||||
SimSun_Italic_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "SimSun,BoldItalic",
|
||||
SimSun_BoldItalic_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
/* SimHei */
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "SimHei",
|
||||
SimHei_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "SimHei,Bold",
|
||||
SimHei_Bold_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "SimHei,Italic",
|
||||
SimHei_Italic_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "SimHei,BoldItalic",
|
||||
SimHei_BoldItalic_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_fontdef_cnt.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
static const HPDF_CID_Width MING_LIU_W_ARRAY[] = {
|
||||
{668, 500},
|
||||
{669, 500},
|
||||
{670, 500},
|
||||
{671, 500},
|
||||
{672, 500},
|
||||
{673, 500},
|
||||
{674, 500},
|
||||
{675, 500},
|
||||
{676, 500},
|
||||
{677, 500},
|
||||
{678, 500},
|
||||
{679, 500},
|
||||
{680, 500},
|
||||
{681, 500},
|
||||
{682, 500},
|
||||
{683, 500},
|
||||
{684, 500},
|
||||
{685, 500},
|
||||
{686, 500},
|
||||
{687, 500},
|
||||
{688, 500},
|
||||
{689, 500},
|
||||
{690, 500},
|
||||
{691, 500},
|
||||
{692, 500},
|
||||
{693, 500},
|
||||
{694, 500},
|
||||
{696, 500},
|
||||
{697, 500},
|
||||
{698, 500},
|
||||
{699, 500},
|
||||
{814, 500},
|
||||
{815, 500},
|
||||
{816, 500},
|
||||
{817, 500},
|
||||
{818, 500},
|
||||
{819, 500},
|
||||
{820, 500},
|
||||
{821, 500},
|
||||
{822, 500},
|
||||
{823, 500},
|
||||
{824, 500},
|
||||
{825, 500},
|
||||
{826, 500},
|
||||
{827, 500},
|
||||
{828, 500},
|
||||
{829, 500},
|
||||
{830, 500},
|
||||
{831, 500},
|
||||
{832, 500},
|
||||
{833, 500},
|
||||
{834, 500},
|
||||
{835, 500},
|
||||
{836, 500},
|
||||
{837, 500},
|
||||
{838, 500},
|
||||
{839, 500},
|
||||
{840, 500},
|
||||
{841, 500},
|
||||
{842, 500},
|
||||
{843, 500},
|
||||
{844, 500},
|
||||
{845, 500},
|
||||
{846, 500},
|
||||
{847, 500},
|
||||
{848, 500},
|
||||
{849, 500},
|
||||
{850, 500},
|
||||
{851, 500},
|
||||
{852, 500},
|
||||
{853, 500},
|
||||
{854, 500},
|
||||
{855, 500},
|
||||
{856, 500},
|
||||
{857, 500},
|
||||
{858, 500},
|
||||
{859, 500},
|
||||
{860, 500},
|
||||
{861, 500},
|
||||
{862, 500},
|
||||
{863, 500},
|
||||
{864, 500},
|
||||
{865, 500},
|
||||
{866, 500},
|
||||
{867, 500},
|
||||
{868, 500},
|
||||
{869, 500},
|
||||
{870, 500},
|
||||
{871, 500},
|
||||
{872, 500},
|
||||
{873, 500},
|
||||
{874, 500},
|
||||
{875, 500},
|
||||
{876, 500},
|
||||
{877, 500},
|
||||
{878, 500},
|
||||
{879, 500},
|
||||
{880, 500},
|
||||
{881, 500},
|
||||
{882, 500},
|
||||
{883, 500},
|
||||
{884, 500},
|
||||
{885, 500},
|
||||
{886, 500},
|
||||
{887, 500},
|
||||
{888, 500},
|
||||
{889, 500},
|
||||
{890, 500},
|
||||
{891, 500},
|
||||
{892, 500},
|
||||
{893, 500},
|
||||
{894, 500},
|
||||
{895, 500},
|
||||
{896, 500},
|
||||
{897, 500},
|
||||
{898, 500},
|
||||
{899, 500},
|
||||
{900, 500},
|
||||
{901, 500},
|
||||
{902, 500},
|
||||
{903, 500},
|
||||
{904, 500},
|
||||
{905, 500},
|
||||
{906, 500},
|
||||
{907, 500},
|
||||
{7716, 500},
|
||||
{0xFFFF, 0}
|
||||
};
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
MingLiU_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_FontDef_MingLiU_Init\n"));
|
||||
|
||||
fontdef->ascent = 800;
|
||||
fontdef->descent = -199;
|
||||
fontdef->cap_height = 769;
|
||||
fontdef->font_bbox = HPDF_ToBox(0, -199, 1000, 800);
|
||||
fontdef->flags = HPDF_FONT_SYMBOLIC + HPDF_FONT_FIXED_WIDTH +
|
||||
HPDF_FONT_SERIF;
|
||||
fontdef->italic_angle = 0;
|
||||
fontdef->stemv = 78;
|
||||
if ((ret = HPDF_CIDFontDef_AddWidth (fontdef, MING_LIU_W_ARRAY)) !=
|
||||
HPDF_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
fontdef->type = HPDF_FONTDEF_TYPE_CID;
|
||||
fontdef->valid = HPDF_TRUE;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
MingLiU_Bold_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = MingLiU_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_TRUE, HPDF_FALSE);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
MingLiU_Italic_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = MingLiU_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_FALSE, HPDF_TRUE);
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
MingLiU_BoldItalic_Init (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_STATUS ret = MingLiU_Init (fontdef);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_CIDFontDef_ChangeStyle (fontdef, HPDF_TRUE, HPDF_TRUE);
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_UseCNTFonts (HPDF_Doc pdf)
|
||||
{
|
||||
HPDF_FontDef fontdef;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
if (!HPDF_HasDoc (pdf))
|
||||
return HPDF_INVALID_DOCUMENT;
|
||||
|
||||
/* MingLiU */
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "MingLiU",
|
||||
MingLiU_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "MingLiU,Bold",
|
||||
MingLiU_Bold_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "MingLiU,Italic",
|
||||
MingLiU_Italic_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
fontdef = HPDF_CIDFontDef_New (pdf->mmgr, "MingLiU,BoldItalic",
|
||||
MingLiU_BoldItalic_Init);
|
||||
|
||||
if ((ret = HPDF_Doc_RegisterFontDef (pdf, fontdef)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
+1907
File diff suppressed because it is too large
Load Diff
+1575
File diff suppressed because it is too large
Load Diff
+2275
File diff suppressed because it is too large
Load Diff
+524
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_fontdef_type1.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_fontdef.h"
|
||||
|
||||
static void
|
||||
FreeWidth (HPDF_FontDef fontdef);
|
||||
|
||||
|
||||
static void
|
||||
FreeFunc (HPDF_FontDef fontdef);
|
||||
|
||||
|
||||
static const char*
|
||||
GetKeyword (const char *src,
|
||||
char *keyword,
|
||||
HPDF_UINT len);
|
||||
|
||||
static HPDF_STATUS
|
||||
LoadAfm (HPDF_FontDef fontdef,
|
||||
HPDF_Stream stream);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
LoadFontData (HPDF_FontDef fontdef,
|
||||
HPDF_Stream stream);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
FreeWidth (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
|
||||
|
||||
HPDF_PTRACE ((" FreeWidth\n"));
|
||||
|
||||
HPDF_FreeMem (fontdef->mmgr, attr->widths);
|
||||
attr->widths = NULL;
|
||||
|
||||
fontdef->valid = HPDF_FALSE;
|
||||
}
|
||||
|
||||
HPDF_FontDef
|
||||
HPDF_Type1FontDef_New (HPDF_MMgr mmgr)
|
||||
{
|
||||
HPDF_FontDef fontdef;
|
||||
HPDF_Type1FontDefAttr fontdef_attr;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1FontDef_New\n"));
|
||||
|
||||
if (!mmgr)
|
||||
return NULL;
|
||||
|
||||
fontdef = HPDF_GetMem (mmgr, sizeof(HPDF_FontDef_Rec));
|
||||
if (!fontdef)
|
||||
return NULL;
|
||||
|
||||
HPDF_MemSet (fontdef, 0, sizeof (HPDF_FontDef_Rec));
|
||||
fontdef->sig_bytes = HPDF_FONTDEF_SIG_BYTES;
|
||||
fontdef->mmgr = mmgr;
|
||||
fontdef->error = mmgr->error;
|
||||
fontdef->type = HPDF_FONTDEF_TYPE_TYPE1;
|
||||
fontdef->free_fn = FreeFunc;
|
||||
|
||||
fontdef_attr = HPDF_GetMem (mmgr, sizeof(HPDF_Type1FontDefAttr_Rec));
|
||||
if (!fontdef_attr) {
|
||||
HPDF_FreeMem (fontdef->mmgr, fontdef);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fontdef->attr = fontdef_attr;
|
||||
HPDF_MemSet ((HPDF_BYTE *)fontdef_attr, 0, sizeof(HPDF_Type1FontDefAttr_Rec));
|
||||
fontdef->flags = HPDF_FONT_STD_CHARSET;
|
||||
|
||||
return fontdef;
|
||||
}
|
||||
|
||||
static const char*
|
||||
GetKeyword (const char *src,
|
||||
char *keyword,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
HPDF_UINT src_len = HPDF_StrLen (src, -1);
|
||||
|
||||
HPDF_PTRACE ((" GetKeyword\n"));
|
||||
|
||||
if (!keyword || src_len == 0 || len == 0)
|
||||
return NULL;
|
||||
|
||||
*keyword = 0;
|
||||
|
||||
while (len > 1) {
|
||||
if (HPDF_IS_WHITE_SPACE(*src)) {
|
||||
*keyword = 0;
|
||||
|
||||
while (HPDF_IS_WHITE_SPACE(*src))
|
||||
src++;
|
||||
return src;
|
||||
}
|
||||
|
||||
*keyword++ = *src++;
|
||||
len--;
|
||||
}
|
||||
|
||||
*keyword = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
LoadAfm (HPDF_FontDef fontdef,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
|
||||
char buf[HPDF_TMP_BUF_SIZ];
|
||||
HPDF_CharData* cdata;
|
||||
HPDF_STATUS ret;
|
||||
HPDF_UINT len;
|
||||
char keyword[HPDF_LIMIT_MAX_NAME_LEN + 1];
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE ((" LoadAfm\n"));
|
||||
|
||||
len = HPDF_TMP_BUF_SIZ;
|
||||
|
||||
/* chaeck AFM header */
|
||||
if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
GetKeyword (buf, keyword, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||||
|
||||
if (HPDF_StrCmp (keyword, "StartFontMetrics") != 0)
|
||||
return HPDF_INVALID_AFM_HEADER;
|
||||
|
||||
/* Global Font Information */
|
||||
|
||||
for (;;) {
|
||||
const char *s;
|
||||
|
||||
len = HPDF_TMP_BUF_SIZ;
|
||||
if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
s = GetKeyword (buf, keyword, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||||
|
||||
if (HPDF_StrCmp (keyword, "FontName") == 0) {
|
||||
HPDF_StrCpy (fontdef->base_font, s,
|
||||
fontdef->base_font + HPDF_LIMIT_MAX_NAME_LEN);
|
||||
} else
|
||||
|
||||
if (HPDF_StrCmp (keyword, "Weight") == 0) {
|
||||
if (HPDF_StrCmp (s, "Bold") == 0)
|
||||
fontdef->flags |= HPDF_FONT_FOURCE_BOLD;
|
||||
} else
|
||||
|
||||
if (HPDF_StrCmp (keyword, "IsFixedPitch") == 0) {
|
||||
if (HPDF_StrCmp (s, "true") == 0)
|
||||
fontdef->flags |= HPDF_FONT_FIXED_WIDTH;
|
||||
} else
|
||||
|
||||
if (HPDF_StrCmp (keyword, "ItalicAngle") == 0) {
|
||||
fontdef->italic_angle = (HPDF_INT16)HPDF_AToI (s);
|
||||
if (fontdef->italic_angle != 0)
|
||||
fontdef->flags |= HPDF_FONT_ITALIC;
|
||||
} else
|
||||
|
||||
if (HPDF_StrCmp (keyword, "CharacterSet") == 0) {
|
||||
HPDF_UINT len = HPDF_StrLen (s, HPDF_LIMIT_MAX_STRING_LEN);
|
||||
|
||||
if (len > 0) {
|
||||
attr->char_set = HPDF_GetMem (fontdef->mmgr, len + 1);
|
||||
if (!attr->char_set)
|
||||
return HPDF_Error_GetCode (fontdef->error);
|
||||
|
||||
HPDF_StrCpy (attr->char_set, s, attr->char_set + len);
|
||||
}
|
||||
} else
|
||||
if (HPDF_StrCmp (keyword, "FontBBox") == 0) {
|
||||
char buf[HPDF_INT_LEN + 1];
|
||||
|
||||
s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
|
||||
fontdef->font_bbox.left = (HPDF_REAL)HPDF_AToI (buf);
|
||||
|
||||
s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
|
||||
fontdef->font_bbox.bottom = (HPDF_REAL)HPDF_AToI (buf);
|
||||
|
||||
s = GetKeyword (s, buf, HPDF_INT_LEN + 1);
|
||||
fontdef->font_bbox.right = (HPDF_REAL)HPDF_AToI (buf);
|
||||
|
||||
GetKeyword (s, buf, HPDF_INT_LEN + 1);
|
||||
fontdef->font_bbox.top = (HPDF_REAL)HPDF_AToI (buf);
|
||||
} else
|
||||
if (HPDF_StrCmp (keyword, "EncodingScheme") == 0) {
|
||||
HPDF_StrCpy (attr->encoding_scheme, s,
|
||||
attr->encoding_scheme + HPDF_LIMIT_MAX_NAME_LEN);
|
||||
} else
|
||||
if (HPDF_StrCmp (keyword, "CapHeight") == 0) {
|
||||
fontdef->cap_height = (HPDF_UINT16)HPDF_AToI (s);
|
||||
} else
|
||||
if (HPDF_StrCmp (keyword, "Ascender") == 0) {
|
||||
fontdef->ascent = (HPDF_INT16)HPDF_AToI (s);
|
||||
} else
|
||||
if (HPDF_StrCmp (keyword, "Descender") == 0) {
|
||||
fontdef->descent = (HPDF_INT16)HPDF_AToI (s);
|
||||
} else
|
||||
if (HPDF_StrCmp (keyword, "STDHW") == 0) {
|
||||
fontdef->stemh = (HPDF_UINT16)HPDF_AToI (s);
|
||||
} else
|
||||
if (HPDF_StrCmp (keyword, "STDHV") == 0) {
|
||||
fontdef->stemv = (HPDF_UINT16)HPDF_AToI (s);
|
||||
} else
|
||||
if (HPDF_StrCmp (keyword, "StartCharMetrics") == 0) {
|
||||
attr->widths_count = HPDF_AToI (s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cdata = (HPDF_CharData*)HPDF_GetMem (fontdef->mmgr,
|
||||
sizeof(HPDF_CharData) * attr->widths_count);
|
||||
if (cdata == NULL)
|
||||
return HPDF_Error_GetCode (fontdef->error);
|
||||
|
||||
HPDF_MemSet (cdata, 0, sizeof(HPDF_CharData) * attr->widths_count);
|
||||
attr->widths = cdata;
|
||||
|
||||
/* load CharMetrics */
|
||||
for (i = 0; i < attr->widths_count; i++, cdata++) {
|
||||
const char *s;
|
||||
char buf2[HPDF_LIMIT_MAX_NAME_LEN + 1];
|
||||
|
||||
len = HPDF_TMP_BUF_SIZ;
|
||||
if ((ret = HPDF_Stream_ReadLn (stream, buf, &len)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
/* C default character code. */
|
||||
s = GetKeyword (buf, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||||
if (HPDF_StrCmp (buf2, "CX") == 0) {
|
||||
/* not suppoted yet. */
|
||||
return HPDF_SetError (fontdef->error,
|
||||
HPDF_INVALID_CHAR_MATRICS_DATA, 0);
|
||||
} else
|
||||
if (HPDF_StrCmp (buf2, "C") == 0) {
|
||||
s += 2;
|
||||
|
||||
s = GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||||
HPDF_AToI (buf2);
|
||||
|
||||
cdata->char_cd = (HPDF_INT16)HPDF_AToI (buf2);
|
||||
|
||||
} else
|
||||
return HPDF_SetError (fontdef->error,
|
||||
HPDF_INVALID_CHAR_MATRICS_DATA, 0);
|
||||
|
||||
/* WX Character width */
|
||||
s = HPDF_StrStr (s, "WX ", 0);
|
||||
if (!s)
|
||||
return HPDF_SetError (fontdef->error, HPDF_INVALID_WX_DATA, 0);
|
||||
|
||||
s += 3;
|
||||
|
||||
s = GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||||
if (buf2[0] == 0)
|
||||
return HPDF_SetError (fontdef->error, HPDF_INVALID_WX_DATA, 0);
|
||||
|
||||
cdata->width = (HPDF_INT16)HPDF_AToI (buf2);
|
||||
|
||||
/* N PostScript language character name */
|
||||
s = HPDF_StrStr (s, "N ", 0);
|
||||
if (!s)
|
||||
return HPDF_SetError (fontdef->error, HPDF_INVALID_N_DATA, 0);
|
||||
|
||||
s += 2;
|
||||
|
||||
GetKeyword (s, buf2, HPDF_LIMIT_MAX_NAME_LEN + 1);
|
||||
|
||||
cdata->unicode = HPDF_GryphNameToUnicode (buf2);
|
||||
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
LoadFontData (HPDF_FontDef fontdef,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
|
||||
char buf[HPDF_STREAM_BUF_SIZ];
|
||||
char* pbuf = buf;
|
||||
HPDF_UINT len = 0;
|
||||
HPDF_STATUS ret;
|
||||
HPDF_BOOL end_flg = HPDF_FALSE;
|
||||
|
||||
HPDF_PTRACE ((" LoadFontData\n"));
|
||||
|
||||
attr->font_data = HPDF_MemStream_New (fontdef->mmgr, HPDF_STREAM_BUF_SIZ);
|
||||
|
||||
if (!attr->font_data)
|
||||
return HPDF_Error_GetCode (fontdef->error);
|
||||
|
||||
len = 11;
|
||||
ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)pbuf, &len);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
pbuf += 11;
|
||||
|
||||
for (;;) {
|
||||
len = HPDF_STREAM_BUF_SIZ - 11;
|
||||
ret = HPDF_Stream_Read (stream, (HPDF_BYTE *)pbuf, &len);
|
||||
if (ret == HPDF_STREAM_EOF) {
|
||||
end_flg = HPDF_TRUE;
|
||||
} else if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if (len > 0) {
|
||||
if (attr->length1 == 0) {
|
||||
const char *s1 = HPDF_StrStr (buf, "eexec", len + 11);
|
||||
|
||||
/* length1 indicate the size of ascii-data of font-file. */
|
||||
if (s1)
|
||||
attr->length1 = attr->font_data->size + (s1 - buf) + 6;
|
||||
}
|
||||
|
||||
if (attr->length1 > 0 && attr->length2 == 0) {
|
||||
const char *s2 = HPDF_StrStr (buf, "cleartomark",
|
||||
len + 11);
|
||||
|
||||
if (s2)
|
||||
attr->length2 = attr->font_data->size + - 520 -
|
||||
attr->length1 + (s2 - buf);
|
||||
/* length1 indicate the size of binary-data.
|
||||
* in most fonts, it is all right at 520 bytes . but it need
|
||||
* to modify because it does not fully satisfy the
|
||||
* specification of type-1 font.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if (end_flg) {
|
||||
if ((ret = HPDF_Stream_Write (attr->font_data, (HPDF_BYTE *)buf, len + 11)) !=
|
||||
HPDF_OK)
|
||||
return ret;
|
||||
|
||||
break;
|
||||
} else {
|
||||
if ((ret = HPDF_Stream_Write (attr->font_data, (HPDF_BYTE *)buf, len)) !=
|
||||
HPDF_OK)
|
||||
return ret;
|
||||
HPDF_MemCpy ((HPDF_BYTE *)buf, (HPDF_BYTE *)buf + len, 11);
|
||||
pbuf = buf + 11;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr->length1 == 0 || attr->length2 == 0)
|
||||
return HPDF_SetError (fontdef->error, HPDF_UNSUPPORTED_TYPE1_FONT, 0);
|
||||
|
||||
attr->length3 = attr->font_data->size - attr->length1 - attr->length2;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_FontDef
|
||||
HPDF_Type1FontDef_Load (HPDF_MMgr mmgr,
|
||||
HPDF_Stream afm,
|
||||
HPDF_Stream font_data)
|
||||
{
|
||||
HPDF_FontDef fontdef;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1FontDef_Load\n"));
|
||||
|
||||
if (!afm)
|
||||
return NULL;
|
||||
|
||||
fontdef = HPDF_Type1FontDef_New (mmgr);
|
||||
|
||||
if (!fontdef)
|
||||
return NULL;
|
||||
|
||||
ret = LoadAfm (fontdef, afm);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_FontDef_Free (fontdef);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* if font-data is specified, the font data is embeded */
|
||||
if (font_data) {
|
||||
ret = LoadFontData (fontdef, font_data);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_FontDef_Free (fontdef);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return fontdef;
|
||||
}
|
||||
|
||||
HPDF_FontDef
|
||||
HPDF_Type1FontDef_Duplicate (HPDF_MMgr mmgr,
|
||||
HPDF_FontDef src)
|
||||
{
|
||||
HPDF_FontDef fontdef = HPDF_Type1FontDef_New (mmgr);
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1FontDef_Duplicate\n"));
|
||||
|
||||
fontdef->type = src->type;
|
||||
fontdef->valid = src->valid;
|
||||
|
||||
/* copy data of attr,widths
|
||||
attention to charset */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Type1FontDef_SetWidths (HPDF_FontDef fontdef,
|
||||
const HPDF_CharData* widths)
|
||||
{
|
||||
const HPDF_CharData* src = widths;
|
||||
HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
|
||||
HPDF_CharData* dst;
|
||||
HPDF_UINT i = 0;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1FontDef_SetWidths\n"));
|
||||
|
||||
FreeWidth (fontdef);
|
||||
|
||||
while (src->unicode != 0xFFFF) {
|
||||
src++;
|
||||
i++;
|
||||
}
|
||||
|
||||
attr->widths_count = i;
|
||||
|
||||
dst = (HPDF_CharData*)HPDF_GetMem (fontdef->mmgr, sizeof(HPDF_CharData) *
|
||||
attr->widths_count);
|
||||
if (dst == NULL)
|
||||
return HPDF_Error_GetCode (fontdef->error);
|
||||
|
||||
HPDF_MemSet (dst, 0, sizeof(HPDF_CharData) * attr->widths_count);
|
||||
attr->widths = dst;
|
||||
|
||||
src = widths;
|
||||
for (i = 0; i < attr->widths_count; i++) {
|
||||
dst->char_cd = src->char_cd;
|
||||
dst->unicode = src->unicode;
|
||||
dst->width = src->width;
|
||||
if (dst->unicode == 0x0020) {
|
||||
fontdef->missing_width = src->width;
|
||||
}
|
||||
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_INT16
|
||||
HPDF_Type1FontDef_GetWidthByName (HPDF_FontDef fontdef,
|
||||
const char* gryph_name)
|
||||
{
|
||||
HPDF_UNICODE unicode = HPDF_GryphNameToUnicode (gryph_name);
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1FontDef_GetWidthByName\n"));
|
||||
|
||||
return HPDF_Type1FontDef_GetWidth (fontdef, unicode);
|
||||
}
|
||||
|
||||
|
||||
HPDF_INT16
|
||||
HPDF_Type1FontDef_GetWidth (HPDF_FontDef fontdef,
|
||||
HPDF_UNICODE unicode)
|
||||
{
|
||||
HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
|
||||
HPDF_CharData *cdata = attr->widths;
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Type1FontDef_GetWidth\n"));
|
||||
|
||||
for (i = 0; i < attr->widths_count; i++) {
|
||||
if (cdata->unicode == unicode)
|
||||
return cdata->width;
|
||||
cdata++;
|
||||
}
|
||||
|
||||
return fontdef->missing_width;
|
||||
}
|
||||
|
||||
static void
|
||||
FreeFunc (HPDF_FontDef fontdef)
|
||||
{
|
||||
HPDF_Type1FontDefAttr attr = (HPDF_Type1FontDefAttr)fontdef->attr;
|
||||
|
||||
HPDF_PTRACE ((" FreeFunc\n"));
|
||||
|
||||
if (attr->char_set)
|
||||
HPDF_FreeMem (fontdef->mmgr, attr->char_set);
|
||||
|
||||
if (attr->font_data)
|
||||
HPDF_Stream_Free (attr->font_data);
|
||||
|
||||
HPDF_FreeMem (fontdef->mmgr, attr->widths);
|
||||
HPDF_FreeMem (fontdef->mmgr, attr);
|
||||
}
|
||||
|
||||
Vendored
+123
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_gstate.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_gstate.h"
|
||||
|
||||
HPDF_GState
|
||||
HPDF_GState_New (HPDF_MMgr mmgr,
|
||||
HPDF_GState current)
|
||||
{
|
||||
HPDF_GState gstate;
|
||||
|
||||
if (current && current->depth >= HPDF_LIMIT_MAX_GSTATE) {
|
||||
HPDF_SetError (mmgr->error, HPDF_EXCEED_GSTATE_LIMIT, 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gstate = HPDF_GetMem (mmgr, sizeof(HPDF_GState_Rec));
|
||||
if (!gstate)
|
||||
return NULL;
|
||||
|
||||
if (current) {
|
||||
gstate->trans_matrix = current->trans_matrix;
|
||||
gstate->line_width = current->line_width;
|
||||
gstate->line_cap = current->line_cap;
|
||||
gstate->line_join = current->line_join;
|
||||
gstate->miter_limit = current->miter_limit;
|
||||
gstate->dash_mode = current->dash_mode;
|
||||
gstate->flatness = current->flatness;
|
||||
|
||||
gstate->char_space = current->char_space;
|
||||
gstate->word_space = current->word_space;
|
||||
gstate->h_scalling = current->h_scalling;
|
||||
gstate->text_leading = current->text_leading;
|
||||
gstate->rendering_mode = current->rendering_mode;
|
||||
gstate->text_rise = current->text_rise;
|
||||
|
||||
gstate->cs_stroke = current->cs_stroke;
|
||||
gstate->cs_fill = current->cs_fill;
|
||||
gstate->rgb_fill = current->rgb_fill;
|
||||
gstate->rgb_stroke = current->rgb_stroke;
|
||||
gstate->cmyk_fill = current->cmyk_fill;
|
||||
gstate->cmyk_stroke = current->cmyk_stroke;
|
||||
gstate->gray_fill = current->gray_fill;
|
||||
gstate->gray_stroke = current->gray_stroke;
|
||||
|
||||
gstate->font = current->font;
|
||||
gstate->font_size = current->font_size;
|
||||
gstate->writing_mode = current->writing_mode;
|
||||
|
||||
gstate->prev = current;
|
||||
gstate->depth = current->depth + 1;
|
||||
} else {
|
||||
HPDF_TransMatrix DEF_MATRIX = {1, 0, 0, 1, 0, 0};
|
||||
HPDF_RGBColor DEF_RGB_COLOR = {0, 0, 0};
|
||||
HPDF_CMYKColor DEF_CMYK_COLOR = {0, 0, 0, 0};
|
||||
HPDF_DashMode DEF_DASH_MODE = {{0, 0, 0, 0, 0, 0, 0, 0}, 0, 0};
|
||||
|
||||
gstate->trans_matrix = DEF_MATRIX;
|
||||
gstate->line_width = HPDF_DEF_LINEWIDTH;
|
||||
gstate->line_cap = HPDF_DEF_LINECAP;
|
||||
gstate->line_join = HPDF_DEF_LINEJOIN;
|
||||
gstate->miter_limit = HPDF_DEF_MITERLIMIT;
|
||||
gstate->dash_mode = DEF_DASH_MODE;
|
||||
gstate->flatness = HPDF_DEF_FLATNESS;
|
||||
|
||||
gstate->char_space = HPDF_DEF_CHARSPACE;
|
||||
gstate->word_space = HPDF_DEF_WORDSPACE;
|
||||
gstate->h_scalling = HPDF_DEF_HSCALING;
|
||||
gstate->text_leading = HPDF_DEF_LEADING;
|
||||
gstate->rendering_mode = HPDF_DEF_RENDERING_MODE;
|
||||
gstate->text_rise = HPDF_DEF_RISE;
|
||||
|
||||
gstate->cs_stroke = HPDF_CS_DEVICE_GRAY;
|
||||
gstate->cs_fill = HPDF_CS_DEVICE_GRAY;
|
||||
gstate->rgb_fill = DEF_RGB_COLOR;
|
||||
gstate->rgb_stroke = DEF_RGB_COLOR;
|
||||
gstate->cmyk_fill = DEF_CMYK_COLOR;
|
||||
gstate->cmyk_stroke = DEF_CMYK_COLOR;
|
||||
gstate->gray_fill = 0;
|
||||
gstate->gray_stroke = 0;
|
||||
|
||||
gstate->font = NULL;
|
||||
gstate->font_size = 0;
|
||||
gstate->writing_mode = HPDF_WMODE_HORIZONTAL;
|
||||
|
||||
gstate->prev = NULL;
|
||||
gstate->depth = 1;
|
||||
}
|
||||
|
||||
return gstate;
|
||||
}
|
||||
|
||||
HPDF_GState
|
||||
HPDF_GState_Free (HPDF_MMgr mmgr,
|
||||
HPDF_GState gstate)
|
||||
{
|
||||
HPDF_GState current = NULL;
|
||||
|
||||
if (gstate) {
|
||||
current = gstate->prev;
|
||||
HPDF_FreeMem (mmgr, gstate);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
Vendored
+664
@@ -0,0 +1,664 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_image.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
static const char *COL_CMYK = "DeviceCMYK";
|
||||
static const char *COL_RGB = "DeviceRGB";
|
||||
static const char *COL_GRAY = "DeviceGray";
|
||||
|
||||
static HPDF_STATUS
|
||||
LoadJpegHeader (HPDF_Image image,
|
||||
HPDF_Stream stream);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static HPDF_STATUS
|
||||
LoadJpegHeader (HPDF_Image image,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
HPDF_UINT16 tag;
|
||||
HPDF_UINT16 height;
|
||||
HPDF_UINT16 width;
|
||||
HPDF_BYTE precision;
|
||||
HPDF_BYTE num_components;
|
||||
const char *color_space_name;
|
||||
HPDF_UINT len;
|
||||
HPDF_STATUS ret;
|
||||
HPDF_Array array;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_LoadJpegHeader\n"));
|
||||
|
||||
len = 2;
|
||||
if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&tag, &len) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
HPDF_UInt16Swap (&tag);
|
||||
if (tag != 0xFFD8)
|
||||
return HPDF_INVALID_JPEG_DATA;
|
||||
|
||||
/* find SOF record */
|
||||
for (;;) {
|
||||
HPDF_UINT16 size;
|
||||
|
||||
len = 2;
|
||||
if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&tag, &len) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
HPDF_UInt16Swap (&tag);
|
||||
|
||||
len = 2;
|
||||
if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&size, &len) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
HPDF_UInt16Swap (&size);
|
||||
|
||||
HPDF_PTRACE (("tag=%04X size=%u\n", tag, size));
|
||||
|
||||
if (tag == 0xFFC0 || tag == 0xFFC1 ||
|
||||
tag == 0xFFC2 || tag == 0xFFC9) {
|
||||
|
||||
len = 1;
|
||||
if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&precision, &len) !=
|
||||
HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
len = 2;
|
||||
if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&height, &len) !=
|
||||
HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
HPDF_UInt16Swap (&height);
|
||||
|
||||
len = 2;
|
||||
if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&width, &len) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
HPDF_UInt16Swap (&width);
|
||||
|
||||
len = 1;
|
||||
if (HPDF_Stream_Read (stream, (HPDF_BYTE *)&num_components, &len) !=
|
||||
HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
break;
|
||||
} else if ((tag | 0x00FF) != 0xFFFF)
|
||||
/* lost marker */
|
||||
return HPDF_SetError (image->error, HPDF_UNSUPPORTED_JPEG_FORMAT,
|
||||
0);
|
||||
|
||||
if (HPDF_Stream_Seek (stream, size - 2, HPDF_SEEK_CUR) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
}
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Height", height) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Width", width) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
/* classification of RGB and CMYK is less than perfect
|
||||
* YCbCr and YCCK are classified into RGB or CMYK.
|
||||
*
|
||||
* It is necessary to read APP14 data to distinguish colorspace perfectly.
|
||||
|
||||
*/
|
||||
switch (num_components) {
|
||||
case 1:
|
||||
color_space_name = COL_GRAY;
|
||||
break;
|
||||
case 3:
|
||||
color_space_name = COL_RGB;
|
||||
break;
|
||||
case 4:
|
||||
array = HPDF_Array_New (image->mmgr);
|
||||
if (!array)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
ret = HPDF_Dict_Add (image, "Decode", array);
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1));
|
||||
ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0));
|
||||
ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1));
|
||||
ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0));
|
||||
ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1));
|
||||
ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0));
|
||||
ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 1));
|
||||
ret += HPDF_Array_Add (array, HPDF_Number_New (image->mmgr, 0));
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
color_space_name = COL_CMYK;
|
||||
|
||||
break;
|
||||
default:
|
||||
return HPDF_SetError (image->error, HPDF_UNSUPPORTED_JPEG_FORMAT,
|
||||
0);
|
||||
}
|
||||
|
||||
if (HPDF_Dict_Add (image, "ColorSpace",
|
||||
HPDF_Name_New (image->mmgr, color_space_name)) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
if (HPDF_Dict_Add (image, "BitsPerComponent",
|
||||
HPDF_Number_New (image->mmgr, precision)) != HPDF_OK)
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
HPDF_Image
|
||||
HPDF_Image_LoadJpegImage (HPDF_MMgr mmgr,
|
||||
HPDF_Stream jpeg_data,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Dict image;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_LoadJpegImage\n"));
|
||||
|
||||
image = HPDF_DictStream_New (mmgr, xref);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
|
||||
/* add requiered elements */
|
||||
image->filter = HPDF_STREAM_FILTER_DCT_DECODE;
|
||||
ret += HPDF_Dict_AddName (image, "Type", "XObject");
|
||||
ret += HPDF_Dict_AddName (image, "Subtype", "Image");
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (LoadJpegHeader (image, jpeg_data) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Stream_Seek (jpeg_data, 0, HPDF_SEEK_SET) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
for (;;) {
|
||||
HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
|
||||
HPDF_UINT len = HPDF_STREAM_BUF_SIZ;
|
||||
HPDF_STATUS ret = HPDF_Stream_Read (jpeg_data, buf,
|
||||
&len);
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
if (ret == HPDF_STREAM_EOF) {
|
||||
if (len > 0) {
|
||||
ret = HPDF_Stream_Write (image->stream, buf, len);
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (image->stream, buf, len) != HPDF_OK)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
HPDF_Image
|
||||
HPDF_Image_LoadJpegImageFromMem (HPDF_MMgr mmgr,
|
||||
const HPDF_BYTE *buf,
|
||||
HPDF_UINT size,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Stream jpeg_data;
|
||||
HPDF_Image image;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_LoadJpegImageFromMem\n"));
|
||||
|
||||
jpeg_data = HPDF_MemStream_New(mmgr,size);
|
||||
if (!HPDF_Stream_Validate (jpeg_data)) {
|
||||
HPDF_RaiseError (mmgr->error, HPDF_INVALID_STREAM, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (jpeg_data, buf, size) != HPDF_OK) {
|
||||
HPDF_Stream_Free (jpeg_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = HPDF_Image_LoadJpegImage(mmgr,jpeg_data,xref);
|
||||
|
||||
/* destroy file stream */
|
||||
HPDF_Stream_Free (jpeg_data);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Image
|
||||
HPDF_Image_LoadRawImage (HPDF_MMgr mmgr,
|
||||
HPDF_Stream raw_data,
|
||||
HPDF_Xref xref,
|
||||
HPDF_UINT width,
|
||||
HPDF_UINT height,
|
||||
HPDF_ColorSpace color_space)
|
||||
{
|
||||
HPDF_Dict image;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_UINT size;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_LoadRawImage\n"));
|
||||
|
||||
if (color_space != HPDF_CS_DEVICE_GRAY &&
|
||||
color_space != HPDF_CS_DEVICE_RGB &&
|
||||
color_space != HPDF_CS_DEVICE_CMYK) {
|
||||
HPDF_SetError (mmgr->error, HPDF_INVALID_COLOR_SPACE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = HPDF_DictStream_New (mmgr, xref);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
ret += HPDF_Dict_AddName (image, "Type", "XObject");
|
||||
ret += HPDF_Dict_AddName (image, "Subtype", "Image");
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (color_space == HPDF_CS_DEVICE_GRAY) {
|
||||
size = width * height;
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", COL_GRAY);
|
||||
} else if (color_space == HPDF_CS_DEVICE_CMYK) {
|
||||
size = width * height * 4;
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", COL_CMYK);
|
||||
} else {
|
||||
size = width * height * 3;
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", COL_RGB);
|
||||
}
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Width", width) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Height", height) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "BitsPerComponent", 8) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Stream_WriteToStream (raw_data, image->stream, 0, NULL) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (image->stream->size != size) {
|
||||
HPDF_SetError (image->error, HPDF_INVALID_IMAGE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Image
|
||||
HPDF_Image_LoadRawImageFromMem (HPDF_MMgr mmgr,
|
||||
const HPDF_BYTE *buf,
|
||||
HPDF_Xref xref,
|
||||
HPDF_UINT width,
|
||||
HPDF_UINT height,
|
||||
HPDF_ColorSpace color_space,
|
||||
HPDF_UINT bits_per_component)
|
||||
{
|
||||
HPDF_Dict image;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_UINT size=0;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_LoadRawImageFromMem\n"));
|
||||
|
||||
if (color_space != HPDF_CS_DEVICE_GRAY &&
|
||||
color_space != HPDF_CS_DEVICE_RGB &&
|
||||
color_space != HPDF_CS_DEVICE_CMYK) {
|
||||
HPDF_SetError (mmgr->error, HPDF_INVALID_COLOR_SPACE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bits_per_component != 1 && bits_per_component != 2 &&
|
||||
bits_per_component != 4 && bits_per_component != 8) {
|
||||
HPDF_SetError (mmgr->error, HPDF_INVALID_IMAGE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = HPDF_DictStream_New (mmgr, xref);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
ret += HPDF_Dict_AddName (image, "Type", "XObject");
|
||||
ret += HPDF_Dict_AddName (image, "Subtype", "Image");
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
switch (color_space) {
|
||||
case HPDF_CS_DEVICE_GRAY:
|
||||
size = (HPDF_UINT)((HPDF_DOUBLE)width * height / (8 / bits_per_component) + 0.876);
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", COL_GRAY);
|
||||
break;
|
||||
case HPDF_CS_DEVICE_RGB:
|
||||
size = (HPDF_UINT)((HPDF_DOUBLE)width * height / (8 / bits_per_component) + 0.876);
|
||||
size *= 3;
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", COL_RGB);
|
||||
break;
|
||||
case HPDF_CS_DEVICE_CMYK:
|
||||
size = (HPDF_UINT)((HPDF_DOUBLE)width * height / (8 / bits_per_component) + 0.876);
|
||||
size *= 4;
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", COL_CMYK);
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Width", width) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Height", height) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "BitsPerComponent", bits_per_component)
|
||||
!= HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Stream_Write (image->stream, buf, size) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_Image_Validate (HPDF_Image image)
|
||||
{
|
||||
HPDF_Name subtype;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_Validate\n"));
|
||||
|
||||
if (!image)
|
||||
return HPDF_FALSE;
|
||||
|
||||
if (image->header.obj_class != (HPDF_OSUBCLASS_XOBJECT |
|
||||
HPDF_OCLASS_DICT)) {
|
||||
HPDF_RaiseError (image->error, HPDF_INVALID_IMAGE, 0);
|
||||
return HPDF_FALSE;
|
||||
}
|
||||
|
||||
subtype = HPDF_Dict_GetItem (image, "Subtype", HPDF_OCLASS_NAME);
|
||||
if (!subtype || HPDF_StrCmp (subtype->value, "Image") != 0) {
|
||||
HPDF_RaiseError (image->error, HPDF_INVALID_IMAGE, 0);
|
||||
return HPDF_FALSE;
|
||||
}
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_Point)
|
||||
HPDF_Image_GetSize (HPDF_Image image)
|
||||
{
|
||||
HPDF_Number width;
|
||||
HPDF_Number height;
|
||||
HPDF_Point ret = {0, 0};
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_GetSize\n"));
|
||||
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return ret;
|
||||
|
||||
width = HPDF_Dict_GetItem (image, "Width", HPDF_OCLASS_NUMBER);
|
||||
height = HPDF_Dict_GetItem (image, "Height", HPDF_OCLASS_NUMBER);
|
||||
|
||||
if (width && height) {
|
||||
ret.x = (HPDF_REAL)width->value;
|
||||
ret.y = (HPDF_REAL)height->value;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Image_GetSize2 (HPDF_Image image, HPDF_Point *size)
|
||||
{
|
||||
HPDF_Number width;
|
||||
HPDF_Number height;
|
||||
size->x = 0;
|
||||
size->y = 0;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_GetSize\n"));
|
||||
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
|
||||
width = HPDF_Dict_GetItem (image, "Width", HPDF_OCLASS_NUMBER);
|
||||
height = HPDF_Dict_GetItem (image, "Height", HPDF_OCLASS_NUMBER);
|
||||
|
||||
if (width && height) {
|
||||
size->x = (HPDF_REAL)width->value;
|
||||
size->y = (HPDF_REAL)height->value;
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_UINT)
|
||||
HPDF_Image_GetBitsPerComponent (HPDF_Image image)
|
||||
{
|
||||
HPDF_Number n;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_GetBitsPerComponent\n"));
|
||||
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return 0;
|
||||
|
||||
n = HPDF_Dict_GetItem (image, "BitsPerComponent", HPDF_OCLASS_NUMBER);
|
||||
|
||||
if (!n)
|
||||
return 0;
|
||||
|
||||
return n->value;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(const char*)
|
||||
HPDF_Image_GetColorSpace (HPDF_Image image)
|
||||
{
|
||||
HPDF_Name n;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_GetColorSpace\n"));
|
||||
|
||||
n = HPDF_Dict_GetItem (image, "ColorSpace", HPDF_OCLASS_NAME);
|
||||
|
||||
if (!n) {
|
||||
HPDF_Array a;
|
||||
|
||||
HPDF_Error_Reset(image->error);
|
||||
|
||||
a = HPDF_Dict_GetItem (image, "ColorSpace", HPDF_OCLASS_ARRAY);
|
||||
|
||||
if (a) {
|
||||
n = HPDF_Array_GetItem (a, 0, HPDF_OCLASS_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
HPDF_CheckError (image->error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return n->value;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_UINT)
|
||||
HPDF_Image_GetWidth (HPDF_Image image)
|
||||
{
|
||||
return (HPDF_UINT)HPDF_Image_GetSize (image).x;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_UINT)
|
||||
HPDF_Image_GetHeight (HPDF_Image image)
|
||||
{
|
||||
return (HPDF_UINT)HPDF_Image_GetSize (image).y;
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Image_SetMask (HPDF_Image image,
|
||||
HPDF_BOOL mask)
|
||||
{
|
||||
HPDF_Boolean image_mask;
|
||||
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
|
||||
if (mask && HPDF_Image_GetBitsPerComponent (image) != 1)
|
||||
return HPDF_SetError (image->error, HPDF_INVALID_BIT_PER_COMPONENT,
|
||||
0);
|
||||
|
||||
image_mask = HPDF_Dict_GetItem (image, "ImageMask", HPDF_OCLASS_BOOLEAN);
|
||||
if (!image_mask) {
|
||||
HPDF_STATUS ret;
|
||||
image_mask = HPDF_Boolean_New (image->mmgr, HPDF_FALSE);
|
||||
|
||||
if ((ret = HPDF_Dict_Add (image, "ImageMask", image_mask)) != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
image_mask->value = mask;
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Image_SetMaskImage (HPDF_Image image,
|
||||
HPDF_Image mask_image)
|
||||
{
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
|
||||
if (!HPDF_Image_Validate (mask_image))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
|
||||
if (HPDF_Image_SetMask (mask_image, HPDF_TRUE) != HPDF_OK)
|
||||
return HPDF_CheckError (image->error);
|
||||
|
||||
return HPDF_Dict_Add (image, "Mask", mask_image);
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Image_SetColorMask (HPDF_Image image,
|
||||
HPDF_UINT rmin,
|
||||
HPDF_UINT rmax,
|
||||
HPDF_UINT gmin,
|
||||
HPDF_UINT gmax,
|
||||
HPDF_UINT bmin,
|
||||
HPDF_UINT bmax)
|
||||
{
|
||||
HPDF_Array array;
|
||||
const char *name;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
|
||||
if (HPDF_Dict_GetItem (image, "ImageMask", HPDF_OCLASS_BOOLEAN))
|
||||
return HPDF_RaiseError (image->error, HPDF_INVALID_OPERATION, 0);
|
||||
|
||||
if (HPDF_Image_GetBitsPerComponent (image) != 8)
|
||||
return HPDF_RaiseError (image->error, HPDF_INVALID_BIT_PER_COMPONENT,
|
||||
0);
|
||||
|
||||
name = HPDF_Image_GetColorSpace (image);
|
||||
if (!name || HPDF_StrCmp (COL_RGB, name) != 0)
|
||||
return HPDF_RaiseError (image->error, HPDF_INVALID_COLOR_SPACE, 0);
|
||||
|
||||
/* Each integer must be in the range 0 to 2^BitsPerComponent - 1 */
|
||||
if (rmax > 255 || gmax > 255 || bmax > 255)
|
||||
return HPDF_RaiseError (image->error, HPDF_INVALID_PARAMETER, 0);
|
||||
|
||||
array = HPDF_Array_New (image->mmgr);
|
||||
if (!array)
|
||||
return HPDF_CheckError (image->error);
|
||||
|
||||
ret += HPDF_Dict_Add (image, "Mask", array);
|
||||
ret += HPDF_Array_AddNumber (array, rmin);
|
||||
ret += HPDF_Array_AddNumber (array, rmax);
|
||||
ret += HPDF_Array_AddNumber (array, gmin);
|
||||
ret += HPDF_Array_AddNumber (array, gmax);
|
||||
ret += HPDF_Array_AddNumber (array, bmin);
|
||||
ret += HPDF_Array_AddNumber (array, bmax);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_CheckError (image->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Image_AddSMask (HPDF_Image image,
|
||||
HPDF_Image smask)
|
||||
{
|
||||
|
||||
const char *name;
|
||||
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
if (!HPDF_Image_Validate (smask))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
|
||||
if (HPDF_Dict_GetItem (image, "SMask", HPDF_OCLASS_BOOLEAN))
|
||||
return HPDF_RaiseError (image->error, HPDF_INVALID_OPERATION, 0);
|
||||
|
||||
name = HPDF_Image_GetColorSpace (smask);
|
||||
if (!name || HPDF_StrCmp (COL_GRAY, name) != 0)
|
||||
return HPDF_RaiseError (smask->error, HPDF_INVALID_COLOR_SPACE, 0);
|
||||
|
||||
return HPDF_Dict_Add (image, "SMask", smask);
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Image_SetColorSpace (HPDF_Image image,
|
||||
HPDF_Array colorspace)
|
||||
{
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
|
||||
return HPDF_Dict_Add (image, "ColorSpace", colorspace);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Image_SetRenderingIntent (HPDF_Image image,
|
||||
const char* intent)
|
||||
{
|
||||
if (!HPDF_Image_Validate (image))
|
||||
return HPDF_INVALID_IMAGE;
|
||||
|
||||
return HPDF_Dict_AddName (image, "Intent", intent);
|
||||
}
|
||||
|
||||
+797
@@ -0,0 +1,797 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_image.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
#include <memory.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define G3CODES
|
||||
#include "t4.h"
|
||||
|
||||
typedef unsigned int uint32;
|
||||
typedef int int32;
|
||||
typedef unsigned short uint16;
|
||||
typedef int32 tsize_t; /* i/o size in bytes */
|
||||
/*
|
||||
* Typedefs for ``method pointers'' used internally.
|
||||
*/
|
||||
typedef unsigned char tidataval_t; /* internal image data value type */
|
||||
typedef tidataval_t* tidata_t; /* reference to internal image data */
|
||||
|
||||
/*
|
||||
* Compression+decompression state blocks are
|
||||
* derived from this ``base state'' block.
|
||||
*/
|
||||
typedef struct {
|
||||
/* int rw_mode; */ /* O_RDONLY for decode, else encode */
|
||||
int mode; /* operating mode */
|
||||
uint32 rowbytes; /* bytes in a decoded scanline */
|
||||
uint32 rowpixels; /* pixels in a scanline */
|
||||
|
||||
uint16 cleanfaxdata; /* CleanFaxData tag */
|
||||
uint32 badfaxrun; /* BadFaxRun tag */
|
||||
uint32 badfaxlines; /* BadFaxLines tag */
|
||||
uint32 groupoptions; /* Group 3/4 options tag */
|
||||
uint32 recvparams; /* encoded Class 2 session params */
|
||||
char* subaddress; /* subaddress string */
|
||||
uint32 recvtime; /* time spent receiving (secs) */
|
||||
char* faxdcs; /* Table 2/T.30 encoded session params */
|
||||
} HPDF_Fax3BaseState;
|
||||
|
||||
typedef struct {
|
||||
HPDF_Fax3BaseState b;
|
||||
|
||||
/* Decoder state info */
|
||||
const unsigned char* bitmap; /* bit reversal table */
|
||||
uint32 data; /* current i/o byte/word */
|
||||
int bit; /* current i/o bit in byte */
|
||||
int EOLcnt; /* count of EOL codes recognized */
|
||||
/* TIFFFaxFillFunc fill;*/ /* fill routine */
|
||||
uint32* runs; /* b&w runs for current/previous row */
|
||||
uint32* refruns; /* runs for reference line */
|
||||
uint32* curruns; /* runs for current line */
|
||||
|
||||
/* Encoder state info */
|
||||
/* Ttag tag; */ /* encoding state */
|
||||
unsigned char* refline; /* reference line for 2d decoding */
|
||||
int k; /* #rows left that can be 2d encoded */
|
||||
int maxk; /* max #rows that can be 2d encoded */
|
||||
|
||||
int line;
|
||||
} HPDF_Fax3CodecState;
|
||||
|
||||
#define Fax3State(tif) (&(tif)->tif_data->b)
|
||||
#define EncoderState(tif) ((tif)->tif_data)
|
||||
#define isAligned(p,t) ((((unsigned long)(p)) & (sizeof (t)-1)) == 0)
|
||||
|
||||
/* NB: the uint32 casts are to silence certain ANSI-C compilers */
|
||||
#define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y)))
|
||||
#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
|
||||
#define TIFFroundup(x, y) (TIFFhowmany(x,y)*(y))
|
||||
|
||||
|
||||
/*
|
||||
struct _HPDF_CCITT_Encoder {
|
||||
} HPDF_CCITT_Encoder;
|
||||
*/
|
||||
|
||||
struct _HPDF_CCITT_Data {
|
||||
HPDF_Fax3CodecState *tif_data;
|
||||
|
||||
HPDF_Stream dst;
|
||||
|
||||
tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */
|
||||
tsize_t tif_rawcc; /* bytes unread from raw buffer */
|
||||
tidata_t tif_rawcp; /* current spot in raw buffer */
|
||||
tidata_t tif_rawdata; /* raw data buffer */
|
||||
|
||||
} HPDF_CCITT_Data;
|
||||
|
||||
static HPDF_STATUS HPDF_InitCCITTFax3(struct _HPDF_CCITT_Data *pData)
|
||||
{
|
||||
HPDF_Fax3BaseState* sp;
|
||||
HPDF_Fax3CodecState* esp;
|
||||
|
||||
/*
|
||||
* Allocate state block so tag methods have storage to record values.
|
||||
*/
|
||||
pData->tif_data = (HPDF_Fax3CodecState *)
|
||||
malloc(sizeof (HPDF_Fax3CodecState));
|
||||
|
||||
if (pData->tif_data == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sp = Fax3State(pData);
|
||||
/* sp->rw_mode = pData->tif_mode; */
|
||||
|
||||
/*
|
||||
* Override parent get/set field methods.
|
||||
*/
|
||||
sp->groupoptions = 0;
|
||||
sp->recvparams = 0;
|
||||
sp->subaddress = NULL;
|
||||
sp->faxdcs = NULL;
|
||||
|
||||
esp = EncoderState(pData);
|
||||
esp->refline = NULL;
|
||||
esp->runs = NULL;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
static HPDF_STATUS HPDF_FreeCCITTFax3(struct _HPDF_CCITT_Data *pData)
|
||||
{
|
||||
if(pData->tif_data!=NULL) {
|
||||
HPDF_Fax3CodecState* esp=pData->tif_data;
|
||||
if(esp->refline!=NULL) {
|
||||
free(esp->refline);
|
||||
esp->refline=NULL;
|
||||
}
|
||||
if(esp->runs!=NULL) {
|
||||
free(esp->runs);
|
||||
esp->runs=NULL;
|
||||
}
|
||||
free(pData->tif_data);
|
||||
pData->tif_data=NULL;
|
||||
}
|
||||
if(pData->tif_rawdata!=NULL) {
|
||||
free(pData->tif_rawdata);
|
||||
pData->tif_rawdata=NULL;
|
||||
}
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Setup G3/G4-related compression/decompression state
|
||||
* before data is processed. This routine is called once
|
||||
* per image -- it sets up different state based on whether
|
||||
* or not decoding or encoding is being done and whether
|
||||
* 1D- or 2D-encoded data is involved.
|
||||
*/
|
||||
static int
|
||||
HPDF_Fax3SetupState(struct _HPDF_CCITT_Data *pData, HPDF_UINT width,
|
||||
HPDF_UINT height,
|
||||
HPDF_UINT line_width)
|
||||
{
|
||||
HPDF_Fax3BaseState* sp = Fax3State(pData);
|
||||
HPDF_Fax3CodecState* esp = EncoderState(pData);
|
||||
uint32 rowbytes, rowpixels, nruns;
|
||||
|
||||
HPDF_UNUSED (height);
|
||||
|
||||
rowbytes = line_width;
|
||||
rowpixels = width;
|
||||
|
||||
sp->rowbytes = (uint32) rowbytes;
|
||||
sp->rowpixels = (uint32) rowpixels;
|
||||
|
||||
nruns = 2*TIFFroundup(rowpixels,32);
|
||||
nruns += 3;
|
||||
esp->runs = (uint32*) malloc(2*nruns * sizeof (uint32));
|
||||
if (esp->runs == NULL)
|
||||
return 1;
|
||||
esp->curruns = esp->runs;
|
||||
esp->refruns = esp->runs + nruns;
|
||||
|
||||
/*
|
||||
* 2d encoding requires a scanline
|
||||
* buffer for the ``reference line''; the
|
||||
* scanline against which delta encoding
|
||||
* is referenced. The reference line must
|
||||
* be initialized to be ``white'' (done elsewhere).
|
||||
*/
|
||||
esp->refline = (unsigned char*) malloc(rowbytes);
|
||||
if (esp->refline == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset encoding state at the start of a strip.
|
||||
*/
|
||||
static HPDF_STATUS
|
||||
HPDF_Fax3PreEncode(struct _HPDF_CCITT_Data *pData/*, tsample_t s*/)
|
||||
{
|
||||
HPDF_Fax3CodecState* sp = EncoderState(pData);
|
||||
|
||||
/* assert(sp != NULL); */
|
||||
sp->bit = 8;
|
||||
sp->data = 0;
|
||||
/* sp->tag = G3_1D; */
|
||||
/*
|
||||
* This is necessary for Group 4; otherwise it isn't
|
||||
* needed because the first scanline of each strip ends
|
||||
* up being copied into the refline.
|
||||
*/
|
||||
if (sp->refline)
|
||||
memset(sp->refline, 0x00, sp->b.rowbytes);
|
||||
sp->k = sp->maxk = 0;
|
||||
sp->line = 0;
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
HPDF_CCITT_AppendToStream(HPDF_Stream dst,
|
||||
tidata_t tif_rawdata,
|
||||
tsize_t tif_rawcc)
|
||||
{
|
||||
if(HPDF_Stream_Write(dst, tif_rawdata, tif_rawcc)!=HPDF_OK)
|
||||
return 1;
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal version of TIFFFlushData that can be
|
||||
* called by ``encodestrip routines'' w/o concern
|
||||
* for infinite recursion.
|
||||
*/
|
||||
static HPDF_STATUS
|
||||
HPDF_CCITT_FlushData(struct _HPDF_CCITT_Data *pData)
|
||||
{
|
||||
if (pData->tif_rawcc > 0) {
|
||||
/*if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
|
||||
(tif->tif_flags & TIFF_NOBITREV) == 0)
|
||||
TIFFReverseBits((unsigned char *pData->tif_rawdata,
|
||||
pData->tif_rawcc);*/
|
||||
if (HPDF_CCITT_AppendToStream(pData->dst,
|
||||
pData->tif_rawdata, pData->tif_rawcc)!=HPDF_OK)
|
||||
return 1;
|
||||
pData->tif_rawcc = 0;
|
||||
pData->tif_rawcp = pData->tif_rawdata;
|
||||
}
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
#define HPDF_Fax3FlushBits(tif, sp) { \
|
||||
if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \
|
||||
(void) HPDF_CCITT_FlushData(tif); \
|
||||
*(tif)->tif_rawcp++ = (tidataval_t) (sp)->data; \
|
||||
(tif)->tif_rawcc++; \
|
||||
(sp)->data = 0, (sp)->bit = 8; \
|
||||
}
|
||||
#define _FlushBits(tif) { \
|
||||
if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \
|
||||
(void) HPDF_CCITT_FlushData(tif); \
|
||||
*(tif)->tif_rawcp++ = (tidataval_t) data; \
|
||||
(tif)->tif_rawcc++; \
|
||||
data = 0, bit = 8; \
|
||||
}
|
||||
static const int _msbmask[9] =
|
||||
{ 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
|
||||
#define _PutBits(tif, bits, length) { \
|
||||
while (length > bit) { \
|
||||
data |= bits >> (length - bit); \
|
||||
length -= bit; \
|
||||
_FlushBits(tif); \
|
||||
} \
|
||||
data |= (bits & _msbmask[length]) << (bit - length); \
|
||||
bit -= length; \
|
||||
if (bit == 0) \
|
||||
_FlushBits(tif); \
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a variable-length bit-value to
|
||||
* the output stream. Values are
|
||||
* assumed to be at most 16 bits.
|
||||
*/
|
||||
static void
|
||||
HPDF_Fax3PutBits(struct _HPDF_CCITT_Data *pData, unsigned int bits, unsigned int length)
|
||||
{
|
||||
HPDF_Fax3CodecState* sp = EncoderState(pData);
|
||||
unsigned int bit = sp->bit;
|
||||
int data = sp->data;
|
||||
|
||||
_PutBits(pData, bits, length);
|
||||
|
||||
sp->data = data;
|
||||
sp->bit = bit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a code to the output stream.
|
||||
*/
|
||||
#define putcode(tif, te) HPDF_Fax3PutBits(tif, (te)->code, (te)->length)
|
||||
|
||||
|
||||
/*
|
||||
* Write the sequence of codes that describes
|
||||
* the specified span of zero's or one's. The
|
||||
* appropriate table that holds the make-up and
|
||||
* terminating codes is supplied.
|
||||
*/
|
||||
static void
|
||||
putspan(struct _HPDF_CCITT_Data *pData, int32 span, const tableentry* tab)
|
||||
{
|
||||
HPDF_Fax3CodecState* sp = EncoderState(pData);
|
||||
unsigned int bit = sp->bit;
|
||||
int data = sp->data;
|
||||
unsigned int code, length;
|
||||
|
||||
while (span >= 2624) {
|
||||
const tableentry* te = &tab[63 + (2560>>6)];
|
||||
code = te->code, length = te->length;
|
||||
#ifdef FAX3_DEBUG
|
||||
DEBUG_PRINT("MakeUp", te->runlen);
|
||||
#endif
|
||||
_PutBits(pData, code, length);
|
||||
span -= te->runlen;
|
||||
}
|
||||
if (span >= 64) {
|
||||
const tableentry* te = &tab[63 + (span>>6)];
|
||||
assert(te->runlen == 64*(span>>6));
|
||||
code = te->code, length = te->length;
|
||||
#ifdef FAX3_DEBUG
|
||||
DEBUG_PRINT("MakeUp", te->runlen);
|
||||
#endif
|
||||
_PutBits(pData, code, length);
|
||||
span -= te->runlen;
|
||||
}
|
||||
code = tab[span].code, length = tab[span].length;
|
||||
#ifdef FAX3_DEBUG
|
||||
DEBUG_PRINT(" Term", tab[span].runlen);
|
||||
#endif
|
||||
_PutBits(pData, code, length);
|
||||
|
||||
sp->data = data;
|
||||
sp->bit = bit;
|
||||
}
|
||||
|
||||
static const unsigned char zeroruns[256] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
|
||||
};
|
||||
static const unsigned char oneruns[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
|
||||
};
|
||||
|
||||
/*
|
||||
* Find a span of ones or zeros using the supplied
|
||||
* table. The ``base'' of the bit string is supplied
|
||||
* along with the start+end bit indices.
|
||||
*/
|
||||
static /*inline*/ int32 find0span(unsigned char* bp, int32 bs, int32 be)
|
||||
{
|
||||
int32 bits = be - bs;
|
||||
int32 n, span;
|
||||
|
||||
bp += bs>>3;
|
||||
/*
|
||||
* Check partial byte on lhs.
|
||||
*/
|
||||
if (bits > 0 && (n = (bs & 7))) {
|
||||
span = zeroruns[(*bp << n) & 0xff];
|
||||
if (span > 8-n) /* table value too generous */
|
||||
span = 8-n;
|
||||
if (span > bits) /* constrain span to bit range */
|
||||
span = bits;
|
||||
if (n+span < 8) /* doesn't extend to edge of byte */
|
||||
return (span);
|
||||
bits -= span;
|
||||
bp++;
|
||||
} else
|
||||
span = 0;
|
||||
if (bits >= (int32)(2 * 8 * sizeof(long))) {
|
||||
long* lp;
|
||||
/*
|
||||
* Align to longword boundary and check longwords.
|
||||
*/
|
||||
while (!isAligned(bp, long)) {
|
||||
if (*bp != 0x00)
|
||||
return (span + zeroruns[*bp]);
|
||||
span += 8, bits -= 8;
|
||||
bp++;
|
||||
}
|
||||
lp = (long*) bp;
|
||||
while ((bits >= (int32)(8 * sizeof(long))) && (0 == *lp)) {
|
||||
span += 8*sizeof (long), bits -= 8*sizeof (long);
|
||||
lp++;
|
||||
}
|
||||
bp = (unsigned char*) lp;
|
||||
}
|
||||
/*
|
||||
* Scan full bytes for all 0's.
|
||||
*/
|
||||
while (bits >= 8) {
|
||||
if (*bp != 0x00) /* end of run */
|
||||
return (span + zeroruns[*bp]);
|
||||
span += 8, bits -= 8;
|
||||
bp++;
|
||||
}
|
||||
/*
|
||||
* Check partial byte on rhs.
|
||||
*/
|
||||
if (bits > 0) {
|
||||
n = zeroruns[*bp];
|
||||
span += (n > bits ? bits : n);
|
||||
}
|
||||
return (span);
|
||||
}
|
||||
|
||||
static /*inline*/ int32
|
||||
find1span(unsigned char* bp, int32 bs, int32 be)
|
||||
{
|
||||
int32 bits = be - bs;
|
||||
int32 n, span;
|
||||
|
||||
bp += bs>>3;
|
||||
/*
|
||||
* Check partial byte on lhs.
|
||||
*/
|
||||
if (bits > 0 && (n = (bs & 7))) {
|
||||
span = oneruns[(*bp << n) & 0xff];
|
||||
if (span > 8-n) /* table value too generous */
|
||||
span = 8-n;
|
||||
if (span > bits) /* constrain span to bit range */
|
||||
span = bits;
|
||||
if (n+span < 8) /* doesn't extend to edge of byte */
|
||||
return (span);
|
||||
bits -= span;
|
||||
bp++;
|
||||
} else
|
||||
span = 0;
|
||||
if (bits >= (int32)(2 * 8 * sizeof(long))) {
|
||||
long* lp;
|
||||
/*
|
||||
* Align to longword boundary and check longwords.
|
||||
*/
|
||||
while (!isAligned(bp, long)) {
|
||||
if (*bp != 0xff)
|
||||
return (span + oneruns[*bp]);
|
||||
span += 8, bits -= 8;
|
||||
bp++;
|
||||
}
|
||||
lp = (long*) bp;
|
||||
while ((bits >= (int32)(8 * sizeof(long))) && (~0 == *lp)) {
|
||||
span += 8*sizeof (long), bits -= 8*sizeof (long);
|
||||
lp++;
|
||||
}
|
||||
bp = (unsigned char*) lp;
|
||||
}
|
||||
/*
|
||||
* Scan full bytes for all 1's.
|
||||
*/
|
||||
while (bits >= 8) {
|
||||
if (*bp != 0xff) /* end of run */
|
||||
return (span + oneruns[*bp]);
|
||||
span += 8, bits -= 8;
|
||||
bp++;
|
||||
}
|
||||
/*
|
||||
* Check partial byte on rhs.
|
||||
*/
|
||||
if (bits > 0) {
|
||||
n = oneruns[*bp];
|
||||
span += (n > bits ? bits : n);
|
||||
}
|
||||
return (span);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the offset of the next bit in the range
|
||||
* [bs..be] that is different from the specified
|
||||
* color. The end, be, is returned if no such bit
|
||||
* exists.
|
||||
*/
|
||||
#define finddiff(_cp, _bs, _be, _color) \
|
||||
(_bs + (_color ? find1span(_cp,_bs,_be) : find0span(_cp,_bs,_be)))
|
||||
/*
|
||||
* Like finddiff, but also check the starting bit
|
||||
* against the end in case start > end.
|
||||
*/
|
||||
#define finddiff2(_cp, _bs, _be, _color) \
|
||||
(_bs < _be ? finddiff(_cp,_bs,_be,_color) : _be)
|
||||
|
||||
|
||||
/*
|
||||
void
|
||||
HPDF_Fax3PostEncode(struct _HPDF_CCITT_Data *pData)
|
||||
{
|
||||
HPDF_Fax3CodecState* sp = EncoderState(pData);
|
||||
|
||||
if (sp->bit != 8)
|
||||
HPDF_Fax3FlushBits(pData, sp);
|
||||
}
|
||||
*/
|
||||
|
||||
static const tableentry horizcode =
|
||||
{ 3, 0x1, 0 }; /* 001 */
|
||||
static const tableentry passcode =
|
||||
{ 4, 0x1, 0 }; /* 0001 */
|
||||
static const tableentry vcodes[7] = {
|
||||
{ 7, 0x03, 0 }, /* 0000 011 */
|
||||
{ 6, 0x03, 0 }, /* 0000 11 */
|
||||
{ 3, 0x03, 0 }, /* 011 */
|
||||
{ 1, 0x1, 0 }, /* 1 */
|
||||
{ 3, 0x2, 0 }, /* 010 */
|
||||
{ 6, 0x02, 0 }, /* 0000 10 */
|
||||
{ 7, 0x02, 0 } /* 0000 010 */
|
||||
};
|
||||
|
||||
/*
|
||||
* 2d-encode a row of pixels. Consult the CCITT
|
||||
* documentation for the algorithm.
|
||||
*/
|
||||
static HPDF_STATUS
|
||||
HPDF_Fax3Encode2DRow(struct _HPDF_CCITT_Data *pData, unsigned char* bp, unsigned char* rp, uint32 bits)
|
||||
{
|
||||
#define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1)
|
||||
uint32 a0 = 0;
|
||||
uint32 a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0));
|
||||
uint32 b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0));
|
||||
uint32 a2, b2;
|
||||
|
||||
for (;;) {
|
||||
b2 = finddiff2(rp, b1, bits, PIXEL(rp,b1));
|
||||
if (b2 >= a1) {
|
||||
int32 d = b1 - a1;
|
||||
if (!(-3 <= d && d <= 3)) { /* horizontal mode */
|
||||
a2 = finddiff2(bp, a1, bits, PIXEL(bp,a1));
|
||||
putcode(pData, &horizcode);
|
||||
if (a0+a1 == 0 || PIXEL(bp, a0) == 0) {
|
||||
putspan(pData, a1-a0, TIFFFaxWhiteCodes);
|
||||
putspan(pData, a2-a1, TIFFFaxBlackCodes);
|
||||
} else {
|
||||
putspan(pData, a1-a0, TIFFFaxBlackCodes);
|
||||
putspan(pData, a2-a1, TIFFFaxWhiteCodes);
|
||||
}
|
||||
a0 = a2;
|
||||
} else { /* vertical mode */
|
||||
putcode(pData, &vcodes[d+3]);
|
||||
a0 = a1;
|
||||
}
|
||||
} else { /* pass mode */
|
||||
putcode(pData, &passcode);
|
||||
a0 = b2;
|
||||
}
|
||||
if (a0 >= bits)
|
||||
break;
|
||||
a1 = finddiff(bp, a0, bits, PIXEL(bp,a0));
|
||||
b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0));
|
||||
b1 = finddiff(rp, b1, bits, PIXEL(bp,a0));
|
||||
}
|
||||
return HPDF_OK;
|
||||
#undef PIXEL
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode the requested amount of data.
|
||||
*/
|
||||
static HPDF_STATUS
|
||||
HPDF_Fax4Encode(struct _HPDF_CCITT_Data *pData, tidata_t bp, tsize_t cc/*, tsample_t s*/)
|
||||
{
|
||||
HPDF_Fax3CodecState *sp = EncoderState(pData);
|
||||
|
||||
/* (void) s; */
|
||||
while ((long)cc > 0) {
|
||||
if (HPDF_Fax3Encode2DRow(pData, bp, sp->refline, sp->b.rowpixels)!=HPDF_OK)
|
||||
return 1;
|
||||
memcpy(sp->refline, bp, sp->b.rowbytes);
|
||||
bp += sp->b.rowbytes;
|
||||
cc -= sp->b.rowbytes;
|
||||
}
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
HPDF_Fax4PostEncode(struct _HPDF_CCITT_Data *pData)
|
||||
{
|
||||
/* HPDF_Fax3CodecState *sp = EncoderState(pData); */
|
||||
|
||||
/* terminate strip w/ EOFB */
|
||||
HPDF_Fax3PutBits(pData, EOL, 12);
|
||||
HPDF_Fax3PutBits(pData, EOL, 12);
|
||||
/*if (sp->bit != 8)
|
||||
HPDF_Fax3FlushBits(pData, sp);
|
||||
*/
|
||||
HPDF_CCITT_FlushData(pData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Stream_CcittToStream( const HPDF_BYTE *buf,
|
||||
HPDF_Stream dst,
|
||||
HPDF_Encrypt e,
|
||||
HPDF_UINT width,
|
||||
HPDF_UINT height,
|
||||
HPDF_UINT line_width,
|
||||
HPDF_BOOL top_is_first)
|
||||
{
|
||||
const HPDF_BYTE *pBufPos;
|
||||
const HPDF_BYTE *pBufEnd; /* end marker */
|
||||
int lineIncrement;
|
||||
struct _HPDF_CCITT_Data data;
|
||||
|
||||
HPDF_UNUSED (e);
|
||||
|
||||
if(height==0) return 1;
|
||||
if(top_is_first) {
|
||||
pBufPos = buf;
|
||||
pBufEnd=buf+(line_width*height);
|
||||
lineIncrement = line_width;
|
||||
} else {
|
||||
pBufPos = buf+(line_width*(height-1));
|
||||
pBufEnd= buf-line_width;
|
||||
lineIncrement = -((int)line_width);
|
||||
}
|
||||
|
||||
memset(&data, 0, sizeof(struct _HPDF_CCITT_Data));
|
||||
data.dst = dst;
|
||||
data.tif_rawdata = (tidata_t) malloc( 16384 ); /* 16 kb buffer */
|
||||
data.tif_rawdatasize = 16384;
|
||||
data.tif_rawcc = 0;
|
||||
data.tif_rawcp = data.tif_rawdata;
|
||||
|
||||
if(HPDF_InitCCITTFax3(&data)!=HPDF_OK)
|
||||
return 1;
|
||||
|
||||
if(HPDF_Fax3SetupState(&data, width, height, line_width)!=HPDF_OK)
|
||||
{
|
||||
HPDF_FreeCCITTFax3(&data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(HPDF_Fax3PreEncode(&data)!=HPDF_OK)
|
||||
{
|
||||
HPDF_FreeCCITTFax3(&data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* encode data */
|
||||
while(pBufEnd!=pBufPos)
|
||||
{
|
||||
HPDF_Fax4Encode(&data, (tidata_t)pBufPos, line_width);
|
||||
pBufPos+=lineIncrement;
|
||||
}
|
||||
|
||||
HPDF_Fax4PostEncode(&data);
|
||||
|
||||
HPDF_FreeCCITTFax3(&data);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
HPDF_Image
|
||||
HPDF_Image_Load1BitImageFromMem (HPDF_MMgr mmgr,
|
||||
const HPDF_BYTE *buf,
|
||||
HPDF_Xref xref,
|
||||
HPDF_UINT width,
|
||||
HPDF_UINT height,
|
||||
HPDF_UINT line_width,
|
||||
HPDF_BOOL top_is_first
|
||||
)
|
||||
{
|
||||
HPDF_Dict image;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
/* HPDF_UINT size; */
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_Load1BitImage\n"));
|
||||
|
||||
image = HPDF_DictStream_New (mmgr, xref);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
ret += HPDF_Dict_AddName (image, "Type", "XObject");
|
||||
ret += HPDF_Dict_AddName (image, "Subtype", "Image");
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
/* size = width * height; */
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Width", width) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Height", height) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "BitsPerComponent", 1) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Stream_CcittToStream (buf, image->stream, NULL, width, height, line_width, top_is_first) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load image from buffer
|
||||
* line_width - width of the line in bytes
|
||||
* top_is_first - image orientation:
|
||||
* TRUE if image is oriented TOP-BOTTOM;
|
||||
* FALSE if image is oriented BOTTOM-TOP
|
||||
*/
|
||||
HPDF_EXPORT(HPDF_Image)
|
||||
HPDF_Image_LoadRaw1BitImageFromMem (HPDF_Doc pdf,
|
||||
const HPDF_BYTE *buf,
|
||||
HPDF_UINT width,
|
||||
HPDF_UINT height,
|
||||
HPDF_UINT line_width,
|
||||
HPDF_BOOL black_is1,
|
||||
HPDF_BOOL top_is_first)
|
||||
{
|
||||
HPDF_Image image;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_Load1BitImageFromMem\n"));
|
||||
|
||||
if (!HPDF_HasDoc (pdf))
|
||||
return NULL;
|
||||
|
||||
image = HPDF_Image_Load1BitImageFromMem(pdf->mmgr, buf, pdf->xref, width,
|
||||
height, line_width, top_is_first);
|
||||
|
||||
if (!image)
|
||||
HPDF_CheckError (&pdf->error);
|
||||
|
||||
if (pdf->compression_mode & HPDF_COMP_IMAGE)
|
||||
{
|
||||
image->filter = HPDF_STREAM_FILTER_CCITT_DECODE;
|
||||
image->filterParams = HPDF_Dict_New(pdf->mmgr);
|
||||
if(image->filterParams==NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* pure 2D encoding, default is 0 */
|
||||
HPDF_Dict_AddNumber (image->filterParams, "K", -1);
|
||||
/* default is 1728 */
|
||||
HPDF_Dict_AddNumber (image->filterParams, "Columns", width);
|
||||
/* default is 0 */
|
||||
HPDF_Dict_AddNumber (image->filterParams, "Rows", height);
|
||||
HPDF_Dict_AddBoolean (image->filterParams, "BlackIs1", black_is1);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
Vendored
+709
@@ -0,0 +1,709 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_image.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_image.h"
|
||||
|
||||
#ifndef LIBHPDF_HAVE_NOPNGLIB
|
||||
#include <png.h>
|
||||
#include <string.h>
|
||||
|
||||
static void
|
||||
PngErrorFunc (png_structp png_ptr,
|
||||
const char *msg);
|
||||
|
||||
|
||||
static void
|
||||
PngReadFunc (png_structp png_ptr,
|
||||
png_bytep data,
|
||||
png_uint_32 length)
|
||||
{
|
||||
HPDF_UINT len = length;
|
||||
HPDF_Stream stream = (HPDF_Stream)png_get_io_ptr (png_ptr);
|
||||
|
||||
HPDF_Stream_Read (stream, data, &len);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
LoadPngData (HPDF_Dict image,
|
||||
HPDF_Xref xref,
|
||||
HPDF_Stream png_data,
|
||||
HPDF_BOOL delayed_loading);
|
||||
|
||||
|
||||
static void
|
||||
PngErrorFunc (png_structp png_ptr,
|
||||
const char *msg);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
ReadPngData_Interlaced (HPDF_Dict image,
|
||||
png_structp png_ptr,
|
||||
png_infop info_ptr);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
ReadPngData (HPDF_Dict image,
|
||||
png_structp png_ptr,
|
||||
png_infop info_ptr);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
CreatePallet (HPDF_Dict image,
|
||||
png_structp png_ptr,
|
||||
png_infop info_ptr);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
PngBeforeWrite (HPDF_Dict obj);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
PngAfterWrite (HPDF_Dict obj);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
PngErrorFunc (png_structp png_ptr,
|
||||
const char *msg)
|
||||
{
|
||||
char error_number[16];
|
||||
HPDF_UINT i;
|
||||
HPDF_STATUS detail_no;
|
||||
HPDF_Error error;
|
||||
|
||||
/* pick out error-number from error message */
|
||||
HPDF_MemSet (error_number, 0, 16);
|
||||
|
||||
for (i = 0; i < 15; i++) {
|
||||
error_number[i] = *(msg + i);
|
||||
if (*(msg + i + 1) == ' ')
|
||||
break;
|
||||
}
|
||||
|
||||
error = (HPDF_Error)png_get_error_ptr (png_ptr);
|
||||
detail_no = (HPDF_STATUS)HPDF_AToI (error_number);
|
||||
HPDF_SetError (error, HPDF_LIBPNG_ERROR, detail_no);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
ReadPngData_Interlaced (HPDF_Dict image,
|
||||
png_structp png_ptr,
|
||||
png_infop info_ptr)
|
||||
{
|
||||
png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
|
||||
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
|
||||
png_bytep* row_pointers = HPDF_GetMem (image->mmgr,
|
||||
height * sizeof (png_bytep));
|
||||
|
||||
if (row_pointers) {
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_MemSet (row_pointers, 0, height * sizeof (png_bytep));
|
||||
for (i = 0; i < (HPDF_UINT)height; i++) {
|
||||
row_pointers[i] = HPDF_GetMem (image->mmgr, len);
|
||||
|
||||
if (image->error->error_no != HPDF_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
if (image->error->error_no == HPDF_OK) {
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
if (image->error->error_no == HPDF_OK) { /* add this line */
|
||||
for (i = 0; i < (HPDF_UINT)height; i++) {
|
||||
if (HPDF_Stream_Write (image->stream, row_pointers[i], len) !=
|
||||
HPDF_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
for (i = 0; i < (HPDF_UINT)height; i++) {
|
||||
HPDF_FreeMem (image->mmgr, row_pointers[i]);
|
||||
}
|
||||
|
||||
HPDF_FreeMem (image->mmgr, row_pointers);
|
||||
}
|
||||
|
||||
return image->error->error_no;
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
ReadPngData (HPDF_Dict image,
|
||||
png_structp png_ptr,
|
||||
png_infop info_ptr)
|
||||
{
|
||||
png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
|
||||
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
|
||||
png_bytep buf_ptr = HPDF_GetMem (image->mmgr, len);
|
||||
|
||||
if (buf_ptr) {
|
||||
HPDF_UINT i;
|
||||
|
||||
for (i = 0; i < (HPDF_UINT)height; i++) {
|
||||
png_read_rows(png_ptr, (png_byte**)&buf_ptr, NULL, 1);
|
||||
if (image->error->error_no != HPDF_OK)
|
||||
break;
|
||||
|
||||
if (HPDF_Stream_Write (image->stream, buf_ptr, len) != HPDF_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
HPDF_FreeMem (image->mmgr, buf_ptr);
|
||||
}
|
||||
|
||||
return image->error->error_no;
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
ReadTransparentPaletteData (HPDF_Dict image,
|
||||
png_structp png_ptr,
|
||||
png_infop info_ptr,
|
||||
png_bytep smask_data,
|
||||
png_bytep trans,
|
||||
int num_trans)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_UINT i, j;
|
||||
png_bytep *row_ptr;
|
||||
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
|
||||
png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
|
||||
|
||||
row_ptr = HPDF_GetMem (image->mmgr, height * sizeof(png_bytep));
|
||||
if (!row_ptr) {
|
||||
return HPDF_FAILD_TO_ALLOC_MEM;
|
||||
} else {
|
||||
png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
for (i = 0; i < (HPDF_UINT)height; i++) {
|
||||
row_ptr[i] = HPDF_GetMem(image->mmgr, len);
|
||||
if (!row_ptr[i]) {
|
||||
for (; i > 0; i--) {
|
||||
HPDF_FreeMem (image->mmgr, row_ptr[i]);
|
||||
}
|
||||
HPDF_FreeMem (image->mmgr, row_ptr);
|
||||
return HPDF_FAILD_TO_ALLOC_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
png_read_image(png_ptr, row_ptr);
|
||||
if (image->error->error_no != HPDF_OK) {
|
||||
ret = HPDF_INVALID_PNG_IMAGE;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
for (j = 0; j < height; j++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
smask_data[width * j + i] = (row_ptr[j][i] < num_trans) ? trans[row_ptr[j][i]] : 0xFF;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (image->stream, row_ptr[j], width) != HPDF_OK) {
|
||||
ret = HPDF_FILE_IO_ERROR;
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
Error:
|
||||
for (i = 0; i < (HPDF_UINT)height; i++) {
|
||||
HPDF_FreeMem (image->mmgr, row_ptr[i]);
|
||||
}
|
||||
|
||||
HPDF_FreeMem (image->mmgr, row_ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
ReadTransparentPngData (HPDF_Dict image,
|
||||
png_structp png_ptr,
|
||||
png_infop info_ptr,
|
||||
png_bytep smask_data)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_INT row_len;
|
||||
HPDF_UINT i, j;
|
||||
png_bytep *row_ptr, row;
|
||||
png_byte color_type;
|
||||
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
|
||||
png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
|
||||
|
||||
color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
|
||||
if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
|
||||
return HPDF_INVALID_PNG_IMAGE;
|
||||
}
|
||||
|
||||
row_ptr = HPDF_GetMem (image->mmgr, height * sizeof(png_bytep));
|
||||
if (!row_ptr) {
|
||||
return HPDF_FAILD_TO_ALLOC_MEM;
|
||||
} else {
|
||||
png_uint_32 len = png_get_rowbytes(png_ptr, info_ptr);
|
||||
|
||||
for (i = 0; i < (HPDF_UINT)height; i++) {
|
||||
row_ptr[i] = HPDF_GetMem(image->mmgr, len);
|
||||
if (!row_ptr[i]) {
|
||||
for (; i > 0; i--) {
|
||||
HPDF_FreeMem (image->mmgr, row_ptr[i]);
|
||||
}
|
||||
HPDF_FreeMem (image->mmgr, row_ptr);
|
||||
return HPDF_FAILD_TO_ALLOC_MEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
png_read_image(png_ptr, row_ptr);
|
||||
if (image->error->error_no != HPDF_OK) {
|
||||
ret = HPDF_INVALID_PNG_IMAGE;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
switch (color_type) {
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA:
|
||||
row_len = 3 * width * sizeof(png_byte);
|
||||
for (j = 0; j < height; j++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
row = row_ptr[j];
|
||||
memmove(row + (3 * i), row + (4*i), 3);
|
||||
smask_data[width * j + i] = row[4 * i + 3];
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (image->stream, row, row_len) != HPDF_OK) {
|
||||
ret = HPDF_FILE_IO_ERROR;
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PNG_COLOR_TYPE_GRAY_ALPHA:
|
||||
row_len = width * sizeof(png_byte);
|
||||
for (j = 0; j < height; j++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
row = row_ptr[j];
|
||||
row[i] = row[2 * i];
|
||||
smask_data[width * j + i] = row[2 * i + 1];
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (image->stream, row, row_len) != HPDF_OK) {
|
||||
ret = HPDF_FILE_IO_ERROR;
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = HPDF_INVALID_PNG_IMAGE;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Error:
|
||||
for (i = 0; i < (HPDF_UINT)height; i++) {
|
||||
HPDF_FreeMem (image->mmgr, row_ptr[i]);
|
||||
}
|
||||
|
||||
HPDF_FreeMem (image->mmgr, row_ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
CreatePallet (HPDF_Dict image,
|
||||
png_structp png_ptr,
|
||||
png_infop info_ptr)
|
||||
{
|
||||
HPDF_INT num_pl = 0;
|
||||
png_color *src_pl = NULL;
|
||||
HPDF_BYTE *ppallet;
|
||||
HPDF_BYTE *p;
|
||||
HPDF_UINT i;
|
||||
HPDF_Array array;
|
||||
|
||||
/* png_get_PLTE does not call PngErrorFunc even if it failed.
|
||||
* so we call HPDF_Set_Error to set error-code.
|
||||
*/
|
||||
if (png_get_PLTE(png_ptr, info_ptr, (png_color**)&src_pl, &num_pl) !=
|
||||
PNG_INFO_PLTE)
|
||||
return HPDF_SetError (image->error, HPDF_LIBPNG_ERROR,
|
||||
HPDF_CANNOT_GET_PALLET);
|
||||
|
||||
|
||||
/* make a pallet array for indexed image. */
|
||||
ppallet = HPDF_GetMem (image->mmgr, num_pl * 3);
|
||||
if (!ppallet)
|
||||
return image->error->error_no;
|
||||
|
||||
p = ppallet;
|
||||
for (i = 0; i < num_pl; i++, src_pl++) {
|
||||
*p++ = src_pl->red;
|
||||
*p++ = src_pl->green;
|
||||
*p++ = src_pl->blue;
|
||||
}
|
||||
|
||||
array = HPDF_Array_New (image->mmgr);
|
||||
if (array) {
|
||||
HPDF_Binary b;
|
||||
|
||||
HPDF_Dict_Add (image, "ColorSpace", array);
|
||||
|
||||
HPDF_Array_AddName (array, "Indexed");
|
||||
HPDF_Array_AddName (array, "DeviceRGB");
|
||||
HPDF_Array_AddNumber (array, num_pl - 1);
|
||||
|
||||
b = HPDF_Binary_New (image->mmgr, ppallet, num_pl * 3);
|
||||
if (b)
|
||||
HPDF_Array_Add (array, b);
|
||||
}
|
||||
|
||||
HPDF_FreeMem (image->mmgr, ppallet);
|
||||
|
||||
return image->error->error_no;
|
||||
}
|
||||
|
||||
#define HPDF_PNG_BYTES_TO_CHECK 8
|
||||
|
||||
HPDF_Image
|
||||
HPDF_Image_LoadPngImage (HPDF_MMgr mmgr,
|
||||
HPDF_Stream png_data,
|
||||
HPDF_Xref xref,
|
||||
HPDF_BOOL delayed_loading)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
HPDF_Dict image;
|
||||
png_byte header[HPDF_PNG_BYTES_TO_CHECK];
|
||||
HPDF_UINT len = HPDF_PNG_BYTES_TO_CHECK;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));
|
||||
|
||||
HPDF_MemSet (header, 0x00, HPDF_PNG_BYTES_TO_CHECK);
|
||||
ret = HPDF_Stream_Read (png_data, header, &len);
|
||||
if (ret != HPDF_OK ||
|
||||
png_sig_cmp (header, (png_size_t)0, HPDF_PNG_BYTES_TO_CHECK)) {
|
||||
HPDF_SetError (mmgr->error, HPDF_INVALID_PNG_IMAGE, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image = HPDF_DictStream_New (mmgr, xref);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
ret += HPDF_Dict_AddName (image, "Type", "XObject");
|
||||
ret += HPDF_Dict_AddName (image, "Subtype", "Image");
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
if (LoadPngData (image, xref, png_data, delayed_loading) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
LoadPngData (HPDF_Dict image,
|
||||
HPDF_Xref xref,
|
||||
HPDF_Stream png_data,
|
||||
HPDF_BOOL delayed_loading)
|
||||
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type;
|
||||
png_structp png_ptr = NULL;
|
||||
png_infop info_ptr = NULL;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Image_LoadPngImage\n"));
|
||||
|
||||
/* create read_struct. */
|
||||
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
|
||||
image->error, PngErrorFunc, PngErrorFunc);
|
||||
|
||||
if (png_ptr == NULL) {
|
||||
HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
|
||||
return HPDF_FAILD_TO_ALLOC_MEM;
|
||||
}
|
||||
|
||||
/* create info-struct */
|
||||
info_ptr = png_create_info_struct (png_ptr);
|
||||
|
||||
if (info_ptr == NULL) {
|
||||
HPDF_SetError (image->error, HPDF_FAILD_TO_ALLOC_MEM, 0);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
png_set_sig_bytes (png_ptr, HPDF_PNG_BYTES_TO_CHECK);
|
||||
png_set_read_fn (png_ptr, (void *)png_data, (png_rw_ptr)&PngReadFunc);
|
||||
|
||||
/* reading info structure. */
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
if (image->error->error_no != HPDF_OK) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
|
||||
|
||||
/* 16bit images are not supported. */
|
||||
if (bit_depth == 16) {
|
||||
png_set_strip_16(png_ptr);
|
||||
}
|
||||
|
||||
png_read_update_info(png_ptr, info_ptr);
|
||||
if (image->error->error_no != HPDF_OK) {
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* check palette-based images for transparent areas and load them immediately if found */
|
||||
if (xref && PNG_COLOR_TYPE_PALETTE & color_type) {
|
||||
png_bytep trans;
|
||||
int num_trans;
|
||||
HPDF_Dict smask;
|
||||
png_bytep smask_data;
|
||||
|
||||
if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ||
|
||||
!png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL)) {
|
||||
goto no_transparent_color_in_palette;
|
||||
}
|
||||
|
||||
smask = HPDF_DictStream_New (image->mmgr, xref);
|
||||
if (!smask) {
|
||||
ret = HPDF_FAILD_TO_ALLOC_MEM;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
ret = HPDF_Dict_AddName (smask, "Type", "XObject");
|
||||
ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
|
||||
ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)width);
|
||||
ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)height);
|
||||
ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
|
||||
ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)bit_depth);
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free(smask);
|
||||
ret = HPDF_INVALID_PNG_IMAGE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
smask_data = HPDF_GetMem(image->mmgr, width * height);
|
||||
if (!smask_data) {
|
||||
HPDF_Dict_Free(smask);
|
||||
ret = HPDF_FAILD_TO_ALLOC_MEM;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (ReadTransparentPaletteData(image, png_ptr, info_ptr, smask_data, trans, num_trans) != HPDF_OK) {
|
||||
HPDF_FreeMem(image->mmgr, smask_data);
|
||||
HPDF_Dict_Free(smask);
|
||||
ret = HPDF_INVALID_PNG_IMAGE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write(smask->stream, smask_data, width * height) != HPDF_OK) {
|
||||
HPDF_FreeMem(image->mmgr, smask_data);
|
||||
HPDF_Dict_Free(smask);
|
||||
ret = HPDF_FILE_IO_ERROR;
|
||||
goto Exit;
|
||||
}
|
||||
HPDF_FreeMem(image->mmgr, smask_data);
|
||||
|
||||
|
||||
ret += CreatePallet(image, png_ptr, info_ptr);
|
||||
ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width);
|
||||
ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height);
|
||||
ret += HPDF_Dict_AddNumber (image, "BitsPerComponent", (HPDF_UINT)bit_depth);
|
||||
ret += HPDF_Dict_Add (image, "SMask", smask);
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
no_transparent_color_in_palette:
|
||||
|
||||
/* read images with alpha channel right away
|
||||
we have to do this because image transparent mask must be added to the Xref */
|
||||
if (xref && PNG_COLOR_MASK_ALPHA & color_type) {
|
||||
HPDF_Dict smask;
|
||||
png_bytep smask_data;
|
||||
|
||||
smask = HPDF_DictStream_New (image->mmgr, xref);
|
||||
if (!smask) {
|
||||
ret = HPDF_FAILD_TO_ALLOC_MEM;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
smask->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
ret = HPDF_Dict_AddName (smask, "Type", "XObject");
|
||||
ret += HPDF_Dict_AddName (smask, "Subtype", "Image");
|
||||
ret += HPDF_Dict_AddNumber (smask, "Width", (HPDF_UINT)width);
|
||||
ret += HPDF_Dict_AddNumber (smask, "Height", (HPDF_UINT)height);
|
||||
ret += HPDF_Dict_AddName (smask, "ColorSpace", "DeviceGray");
|
||||
ret += HPDF_Dict_AddNumber (smask, "BitsPerComponent", (HPDF_UINT)bit_depth);
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free(smask);
|
||||
ret = HPDF_INVALID_PNG_IMAGE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
smask_data = HPDF_GetMem(image->mmgr, width * height);
|
||||
if (!smask_data) {
|
||||
HPDF_Dict_Free(smask);
|
||||
ret = HPDF_FAILD_TO_ALLOC_MEM;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (ReadTransparentPngData(image, png_ptr, info_ptr, smask_data) != HPDF_OK) {
|
||||
HPDF_FreeMem(image->mmgr, smask_data);
|
||||
HPDF_Dict_Free(smask);
|
||||
ret = HPDF_INVALID_PNG_IMAGE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write(smask->stream, smask_data, width * height) != HPDF_OK) {
|
||||
HPDF_FreeMem(image->mmgr, smask_data);
|
||||
HPDF_Dict_Free(smask);
|
||||
ret = HPDF_FILE_IO_ERROR;
|
||||
goto Exit;
|
||||
}
|
||||
HPDF_FreeMem(image->mmgr, smask_data);
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
|
||||
} else {
|
||||
ret += HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");
|
||||
}
|
||||
ret += HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width);
|
||||
ret += HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height);
|
||||
ret += HPDF_Dict_AddNumber (image, "BitsPerComponent", (HPDF_UINT)bit_depth);
|
||||
ret += HPDF_Dict_Add (image, "SMask", smask);
|
||||
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
/* if the image has color palette, copy the pallet of the image to
|
||||
* create color map.
|
||||
*/
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
ret = CreatePallet(image, png_ptr, info_ptr);
|
||||
else if (color_type == PNG_COLOR_TYPE_GRAY)
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceGray");
|
||||
else
|
||||
ret = HPDF_Dict_AddName (image, "ColorSpace", "DeviceRGB");
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
goto Exit;
|
||||
|
||||
/* read image-data
|
||||
* if the image is interlaced, read whole image at once.
|
||||
* if delayed_loading is HPDF_TRUE, the data does not load this phase.
|
||||
*/
|
||||
if (delayed_loading) {
|
||||
image->before_write_fn = PngBeforeWrite;
|
||||
image->after_write_fn = PngAfterWrite;
|
||||
} else {
|
||||
if (png_get_interlace_type(png_ptr, info_ptr) != PNG_INTERLACE_NONE)
|
||||
ret = ReadPngData_Interlaced(image, png_ptr, info_ptr);
|
||||
else
|
||||
ret = ReadPngData(image, png_ptr, info_ptr);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* setting the info of the image. */
|
||||
if (HPDF_Dict_AddNumber (image, "Width", (HPDF_UINT)width)
|
||||
!= HPDF_OK)
|
||||
goto Exit;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "Height", (HPDF_UINT)height)
|
||||
!= HPDF_OK)
|
||||
goto Exit;
|
||||
|
||||
if (HPDF_Dict_AddNumber (image, "BitsPerComponent",
|
||||
(HPDF_UINT)bit_depth) != HPDF_OK)
|
||||
goto Exit;
|
||||
|
||||
/* clean up */
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
return HPDF_OK;
|
||||
|
||||
Exit:
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
return ret;
|
||||
}
|
||||
return image->error->error_no;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
PngBeforeWrite (HPDF_Dict obj)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
png_byte header[HPDF_PNG_BYTES_TO_CHECK];
|
||||
HPDF_UINT len = HPDF_PNG_BYTES_TO_CHECK;
|
||||
HPDF_Stream png_data;
|
||||
HPDF_String s;
|
||||
|
||||
HPDF_PTRACE ((" PngBeforeWrite\n"));
|
||||
|
||||
HPDF_MemStream_FreeData(obj->stream);
|
||||
|
||||
s = HPDF_Dict_GetItem (obj, "_FILE_NAME", HPDF_OCLASS_STRING);
|
||||
if (!s)
|
||||
return HPDF_SetError (obj->error, HPDF_MISSING_FILE_NAME_ENTRY, 0);
|
||||
|
||||
png_data = HPDF_FileReader_New (obj->mmgr, (const char *)(s->value));
|
||||
if (!HPDF_Stream_Validate (png_data))
|
||||
return obj->error->error_no;
|
||||
|
||||
HPDF_MemSet (header, 0x00, HPDF_PNG_BYTES_TO_CHECK);
|
||||
ret = HPDF_Stream_Read (png_data, header, &len);
|
||||
if (ret != HPDF_OK ||
|
||||
png_sig_cmp (header, (png_size_t)0, HPDF_PNG_BYTES_TO_CHECK)) {
|
||||
HPDF_Stream_Free(png_data);
|
||||
return HPDF_SetError (obj->error, HPDF_INVALID_PNG_IMAGE, 0);
|
||||
}
|
||||
|
||||
if ((ret = LoadPngData (obj, NULL, png_data, HPDF_FALSE)) != HPDF_OK) {
|
||||
HPDF_Stream_Free(png_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_Stream_Free(png_data);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
PngAfterWrite (HPDF_Dict obj)
|
||||
{
|
||||
HPDF_PTRACE ((" PngAfterWrite\n"));
|
||||
|
||||
HPDF_MemStream_FreeData(obj->stream);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
#endif /* LIBHPDF_HAVE_NOPNGLIB */
|
||||
|
||||
Vendored
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_info.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_info.h"
|
||||
|
||||
static const char * const HPDF_INFO_ATTR_NAMES[] = {
|
||||
"CreationDate",
|
||||
"ModDate",
|
||||
"Author",
|
||||
"Creator",
|
||||
"Producer",
|
||||
"Title",
|
||||
"Subject",
|
||||
"Keywords",
|
||||
"Trapped",
|
||||
"GTS_PDFXVersion",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static const char*
|
||||
InfoTypeToName (HPDF_InfoType type);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static const char*
|
||||
InfoTypeToName (HPDF_InfoType type)
|
||||
{
|
||||
HPDF_UINT idx = (HPDF_UINT)type;
|
||||
|
||||
return HPDF_INFO_ATTR_NAMES[idx];
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Info_SetInfoAttr (HPDF_Dict info,
|
||||
HPDF_InfoType type,
|
||||
const char *value,
|
||||
HPDF_Encoder encoder)
|
||||
{
|
||||
const char* name = InfoTypeToName (type);
|
||||
|
||||
HPDF_PTRACE((" HPDF_Info_SetInfoAttr\n"));
|
||||
|
||||
if (type <= HPDF_INFO_MOD_DATE)
|
||||
return HPDF_SetError (info->error, HPDF_INVALID_PARAMETER, 0);
|
||||
|
||||
if (type == HPDF_INFO_TRAPPED)
|
||||
return HPDF_Dict_AddName(info, name, value);
|
||||
|
||||
return HPDF_Dict_Add (info, name, HPDF_String_New (info->mmgr, value,
|
||||
encoder));
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
HPDF_Info_GetInfoAttr (HPDF_Dict info,
|
||||
HPDF_InfoType type)
|
||||
{
|
||||
const char* name = InfoTypeToName (type);
|
||||
HPDF_String s;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Info_GetInfoAttr\n"));
|
||||
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
s = HPDF_Dict_GetItem (info, name, HPDF_OCLASS_STRING);
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
else
|
||||
return (const char *)(s->value);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Info_SetInfoDateAttr (HPDF_Dict info,
|
||||
HPDF_InfoType type,
|
||||
HPDF_Date value)
|
||||
{
|
||||
char tmp[HPDF_DATE_TIME_STR_LEN + 1];
|
||||
char* ptmp;
|
||||
const char* name = InfoTypeToName (type);
|
||||
|
||||
HPDF_PTRACE((" HPDF_Info_SetInfoDateAttr\n"));
|
||||
|
||||
if (type > HPDF_INFO_MOD_DATE)
|
||||
return HPDF_SetError (info->error, HPDF_INVALID_PARAMETER, 0);
|
||||
|
||||
HPDF_MemSet (tmp, 0, HPDF_DATE_TIME_STR_LEN + 1);
|
||||
if (value.month < 1 || 12 < value.month ||
|
||||
value.day < 1 ||
|
||||
23 < value.hour ||
|
||||
59 < value.minutes ||
|
||||
59 < value.seconds ||
|
||||
(value.ind != '+' && value.ind != '-' && value.ind != 'Z' &&
|
||||
value.ind != ' ') ||
|
||||
23 < value.off_hour ||
|
||||
59 < value.off_minutes) {
|
||||
return HPDF_SetError (info->error, HPDF_INVALID_DATE_TIME, 0);
|
||||
}
|
||||
|
||||
switch (value.month) {
|
||||
case 1:
|
||||
case 3:
|
||||
case 5:
|
||||
case 7:
|
||||
case 8:
|
||||
case 10:
|
||||
case 12:
|
||||
if (value.day > 31)
|
||||
return HPDF_SetError (info->error, HPDF_INVALID_DATE_TIME, 0);
|
||||
|
||||
break;
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
if (value.day > 30)
|
||||
return HPDF_SetError (info->error, HPDF_INVALID_DATE_TIME, 0);
|
||||
|
||||
break;
|
||||
case 2:
|
||||
if (value.day > 29 || (value.day == 29 &&
|
||||
(value.year % 4 != 0 ||
|
||||
(value.year % 100 == 0 && value.year % 400 != 0))))
|
||||
return HPDF_SetError (info->error, HPDF_INVALID_DATE_TIME, 0);
|
||||
|
||||
break;
|
||||
default:
|
||||
return HPDF_SetError (info->error, HPDF_INVALID_DATE_TIME, 0);
|
||||
}
|
||||
|
||||
ptmp = (char *)HPDF_MemCpy ((HPDF_BYTE *)tmp, (HPDF_BYTE *)"D:", 2);
|
||||
ptmp = HPDF_IToA2 (ptmp, value.year, 5);
|
||||
ptmp = HPDF_IToA2 (ptmp, value.month, 3);
|
||||
ptmp = HPDF_IToA2 (ptmp, value.day, 3);
|
||||
ptmp = HPDF_IToA2 (ptmp, value.hour, 3);
|
||||
ptmp = HPDF_IToA2 (ptmp, value.minutes, 3);
|
||||
ptmp = HPDF_IToA2 (ptmp, value.seconds, 3);
|
||||
if (value.ind != ' ') {
|
||||
*ptmp++ = value.ind;
|
||||
ptmp = HPDF_IToA2 (ptmp, value.off_hour, 3);
|
||||
*ptmp++ = '\'';
|
||||
ptmp = HPDF_IToA2 (ptmp, value.off_minutes, 3);
|
||||
*ptmp++ = '\'';
|
||||
}
|
||||
*ptmp = 0;
|
||||
|
||||
return HPDF_Dict_Add (info, name, HPDF_String_New (info->mmgr, tmp,
|
||||
NULL));
|
||||
}
|
||||
|
||||
|
||||
Vendored
+336
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_list.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_consts.h"
|
||||
#include "hpdf_list.h"
|
||||
|
||||
static HPDF_STATUS
|
||||
Resize (HPDF_List list,
|
||||
HPDF_UINT count);
|
||||
|
||||
|
||||
/*
|
||||
* HPDF_List_new
|
||||
*
|
||||
* mmgr : handle to a HPDF_MMgr object.
|
||||
* items_per_block : number of increases of pointers.
|
||||
*
|
||||
* return: If HPDF_List_New success, it returns a handle to new HPDF_List
|
||||
* object, otherwise it returns NULL.
|
||||
*
|
||||
*/
|
||||
|
||||
HPDF_List
|
||||
HPDF_List_New (HPDF_MMgr mmgr,
|
||||
HPDF_UINT items_per_block)
|
||||
{
|
||||
HPDF_List list;
|
||||
|
||||
HPDF_PTRACE((" HPDF_List_New\n"));
|
||||
|
||||
if (mmgr == NULL)
|
||||
return NULL;
|
||||
|
||||
list = (HPDF_List)HPDF_GetMem (mmgr, sizeof(HPDF_List_Rec));
|
||||
if (list) {
|
||||
list->mmgr = mmgr;
|
||||
list->error = mmgr->error;
|
||||
list->block_siz = 0;
|
||||
list->items_per_block =
|
||||
(items_per_block <= 0 ? HPDF_DEF_ITEMS_PER_BLOCK : items_per_block);
|
||||
list->count = 0;
|
||||
list->obj = NULL;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* HPDF_List_add
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
* item : Pointer to a object to be added.
|
||||
*
|
||||
* return: If HPDF_List_Add success, it returns HPDF_OK.
|
||||
* HPDF_FAILD_TO_ALLOC_MEM is returned when the expansion of the
|
||||
* object list is failed.
|
||||
*
|
||||
*/
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_List_Add (HPDF_List list,
|
||||
void *item)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_List_Add\n"));
|
||||
|
||||
if (list->count >= list->block_siz) {
|
||||
HPDF_STATUS ret = Resize (list,
|
||||
list->block_siz + list->items_per_block);
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
list->obj[list->count++] = item;
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* HPDF_List_Insert
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
* target : Pointer to the target object.
|
||||
* item : Pointer to a object to be inserted.
|
||||
*
|
||||
* insert the item before the target.
|
||||
*
|
||||
* return: If HPDF_List_Add success, it returns HPDF_OK.
|
||||
* HPDF_FAILD_TO_ALLOC_MEM is returned when the expansion of the
|
||||
* object list is failed.
|
||||
* HPDF_ITEM_NOT_FOUND is returned where the target object is not
|
||||
* found.
|
||||
*
|
||||
*/
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_List_Insert (HPDF_List list,
|
||||
void *target,
|
||||
void *item)
|
||||
{
|
||||
HPDF_INT target_idx = HPDF_List_Find (list, target);
|
||||
void *last_item = list->obj[list->count - 1];
|
||||
HPDF_INT i;
|
||||
|
||||
HPDF_PTRACE((" HPDF_List_Insert\n"));
|
||||
|
||||
if (target_idx < 0)
|
||||
return HPDF_ITEM_NOT_FOUND;
|
||||
|
||||
/* move the item of the list to behind one by one. */
|
||||
for (i = list->count - 2; i >= target_idx; i--)
|
||||
list->obj[i + 1] = list->obj[i];
|
||||
|
||||
list->obj[target_idx] = item;
|
||||
|
||||
return HPDF_List_Add (list, last_item);
|
||||
}
|
||||
|
||||
/*
|
||||
* HPDF_List_Remove
|
||||
*
|
||||
* Remove the object specified by item parameter from the list object. The
|
||||
* memory area that the object uses is not released.
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
* item : Pointer to a object to be remove.
|
||||
*
|
||||
* return: If HPDF_List_Remove success, it returns HPDF_OK.
|
||||
* HPDF_ITEM_NOT_FOUND is returned when the object specified by item
|
||||
* parameter is not found.
|
||||
*
|
||||
*/
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_List_Remove (HPDF_List list,
|
||||
void *item)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
void **obj = list->obj;
|
||||
|
||||
HPDF_PTRACE((" HPDF_List_Remove\n"));
|
||||
|
||||
for (i = 0; i < list->count; i++) {
|
||||
if (*obj == item) {
|
||||
HPDF_List_RemoveByIndex(list, i);
|
||||
return HPDF_OK;
|
||||
} else
|
||||
obj++;
|
||||
}
|
||||
|
||||
return HPDF_ITEM_NOT_FOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* HPDF_List_RemoveByIndex
|
||||
*
|
||||
* Remove the object by index number.
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
* index : Index of a object to be remove.
|
||||
*
|
||||
* return: If HPDF_List_RemoveByIndex success, it returns HPDF_OK.
|
||||
* HPDF_ITEM_NOT_FOUND is returned when the value which is specified
|
||||
* by index parameter is invalid.
|
||||
*
|
||||
*/
|
||||
|
||||
void*
|
||||
HPDF_List_RemoveByIndex (HPDF_List list,
|
||||
HPDF_UINT index)
|
||||
{
|
||||
void *tmp;
|
||||
|
||||
HPDF_PTRACE((" HPDF_List_RemoveByIndex\n"));
|
||||
|
||||
if (list->count <= index)
|
||||
return NULL;
|
||||
|
||||
tmp = list->obj[index];
|
||||
|
||||
while (index < list->count - 1) {
|
||||
list->obj[index] = list->obj[index + 1];
|
||||
index++;
|
||||
}
|
||||
|
||||
list->count--;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* HPDF_List_ItemAt
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
* index : Index of a object.
|
||||
*
|
||||
* return: If HPDF_List_at success, it returns a pointer to the object.
|
||||
* otherwise it returns NULL.
|
||||
*
|
||||
*/
|
||||
|
||||
void*
|
||||
HPDF_List_ItemAt (HPDF_List list,
|
||||
HPDF_UINT index)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_List_ItemAt\n"));
|
||||
|
||||
return (list->count <= index) ? NULL : list->obj[index];
|
||||
}
|
||||
|
||||
/*
|
||||
* HPDF_List_free
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
HPDF_List_Free (HPDF_List list)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_List_Free\n"));
|
||||
|
||||
if (!list)
|
||||
return ;
|
||||
|
||||
HPDF_List_Clear (list);
|
||||
HPDF_FreeMem (list->mmgr, list);
|
||||
}
|
||||
|
||||
/*
|
||||
* HPDF_List_Clear
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
HPDF_List_Clear (HPDF_List list)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_List_Clear\n"));
|
||||
|
||||
if (list->obj)
|
||||
HPDF_FreeMem (list->mmgr, list->obj);
|
||||
|
||||
list->block_siz = 0;
|
||||
list->count = 0;
|
||||
list->obj = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resize
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
* count : The size of array of pointers.
|
||||
*
|
||||
* return: If Resize success, it returns HPDF_OK.
|
||||
* otherwise it returns error-code which is set by HPDF_MMgr object.
|
||||
*
|
||||
*/
|
||||
|
||||
static HPDF_STATUS
|
||||
Resize (HPDF_List list,
|
||||
HPDF_UINT count)
|
||||
{
|
||||
void **new_obj;
|
||||
|
||||
HPDF_PTRACE((" HPDF_List_Resize\n"));
|
||||
|
||||
if (list->count >= count) {
|
||||
if (list->count == count)
|
||||
return HPDF_OK;
|
||||
else
|
||||
return HPDF_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
new_obj = (void **)HPDF_GetMem (list->mmgr, count * sizeof(void *));
|
||||
|
||||
if (!new_obj)
|
||||
return HPDF_Error_GetCode (list->error);
|
||||
|
||||
if (list->obj)
|
||||
HPDF_MemCpy ((HPDF_BYTE *)new_obj, (HPDF_BYTE *)list->obj,
|
||||
list->block_siz * sizeof(void *));
|
||||
|
||||
list->block_siz = count;
|
||||
if (list->obj)
|
||||
HPDF_FreeMem (list->mmgr, list->obj);
|
||||
list->obj = new_obj;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* HPDF_List_Find
|
||||
*
|
||||
* list : Pointer to a HPDF_List object.
|
||||
* count : the size of array of pointers.
|
||||
*
|
||||
* return: If HPDF_List_Find success, it returns index of the object.
|
||||
* otherwise it returns negative value.
|
||||
*
|
||||
*/
|
||||
|
||||
HPDF_INT32
|
||||
HPDF_List_Find (HPDF_List list,
|
||||
void *item)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
|
||||
HPDF_PTRACE((" HPDF_List_Find\n"));
|
||||
|
||||
for (i = 0; i < list->count; i++) {
|
||||
if (list->obj[i] == item)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Vendored
+250
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_mmgr.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_consts.h"
|
||||
#include "hpdf_mmgr.h"
|
||||
#include "hpdf_utils.h"
|
||||
|
||||
#ifndef HPDF_STDCALL
|
||||
#ifdef HPDF_DLL_MAKE
|
||||
#define HPDF_STDCALL __stdcall
|
||||
#else
|
||||
#ifdef HPDF_DLL
|
||||
#define HPDF_STDCALL __stdcall
|
||||
#else
|
||||
#define HPDF_STDCALL
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void * HPDF_STDCALL
|
||||
InternalGetMem (HPDF_UINT size);
|
||||
|
||||
static void HPDF_STDCALL
|
||||
InternalFreeMem (void* aptr);
|
||||
|
||||
|
||||
HPDF_MMgr
|
||||
HPDF_MMgr_New (HPDF_Error error,
|
||||
HPDF_UINT buf_size,
|
||||
HPDF_Alloc_Func alloc_fn,
|
||||
HPDF_Free_Func free_fn)
|
||||
{
|
||||
HPDF_MMgr mmgr;
|
||||
|
||||
HPDF_PTRACE((" HPDF_MMgr_New\n"));
|
||||
|
||||
if (alloc_fn)
|
||||
mmgr = (HPDF_MMgr)alloc_fn (sizeof(HPDF_MMgr_Rec));
|
||||
else
|
||||
mmgr = (HPDF_MMgr)InternalGetMem (sizeof(HPDF_MMgr_Rec));
|
||||
|
||||
HPDF_PTRACE(("+%p mmgr-new\n", mmgr));
|
||||
|
||||
if (mmgr != NULL) {
|
||||
/* initialize mmgr object */
|
||||
mmgr->error = error;
|
||||
|
||||
|
||||
#ifdef HPDF_MEM_DEBUG
|
||||
mmgr->alloc_cnt = 0;
|
||||
mmgr->free_cnt = 0;
|
||||
#endif
|
||||
/*
|
||||
* if alloc_fn and free_fn are specified, these function is
|
||||
* used. if not, default function (maybe these will be "malloc" and
|
||||
* "free") is used.
|
||||
*/
|
||||
if (alloc_fn && free_fn) {
|
||||
mmgr->alloc_fn = alloc_fn;
|
||||
mmgr->free_fn = free_fn;
|
||||
} else {
|
||||
mmgr->alloc_fn = InternalGetMem;
|
||||
mmgr->free_fn = InternalFreeMem;
|
||||
}
|
||||
|
||||
/*
|
||||
* if buf_size parameter is specified, this object is configured
|
||||
* to be using memory-pool.
|
||||
*
|
||||
*/
|
||||
if (!buf_size)
|
||||
mmgr->mpool = NULL;
|
||||
else {
|
||||
HPDF_MPool_Node node;
|
||||
|
||||
node = (HPDF_MPool_Node)mmgr->alloc_fn (sizeof(HPDF_MPool_Node_Rec) +
|
||||
buf_size);
|
||||
|
||||
HPDF_PTRACE(("+%p mmgr-node-new\n", node));
|
||||
|
||||
if (node == NULL) {
|
||||
HPDF_SetError (error, HPDF_FAILD_TO_ALLOC_MEM, HPDF_NOERROR);
|
||||
|
||||
mmgr->free_fn(mmgr);
|
||||
mmgr = NULL;
|
||||
} else {
|
||||
mmgr->mpool = node;
|
||||
node->buf = (HPDF_BYTE *)node + sizeof(HPDF_MPool_Node_Rec);
|
||||
node->size = buf_size;
|
||||
node->used_size = 0;
|
||||
node->next_node = NULL;
|
||||
}
|
||||
|
||||
#ifdef HPDF_MEM_DEBUG
|
||||
if (mmgr) {
|
||||
mmgr->alloc_cnt += 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mmgr) {
|
||||
mmgr->buf_size = buf_size;
|
||||
}
|
||||
} else
|
||||
HPDF_SetError(error, HPDF_FAILD_TO_ALLOC_MEM, HPDF_NOERROR);
|
||||
|
||||
return mmgr;
|
||||
}
|
||||
|
||||
void
|
||||
HPDF_MMgr_Free (HPDF_MMgr mmgr)
|
||||
{
|
||||
HPDF_MPool_Node node;
|
||||
|
||||
HPDF_PTRACE((" HPDF_MMgr_Free\n"));
|
||||
|
||||
if (mmgr == NULL)
|
||||
return;
|
||||
|
||||
node = mmgr->mpool;
|
||||
|
||||
/* delete all nodes recursively */
|
||||
while (node != NULL) {
|
||||
HPDF_MPool_Node tmp = node;
|
||||
node = tmp->next_node;
|
||||
|
||||
HPDF_PTRACE(("-%p mmgr-node-free\n", tmp));
|
||||
mmgr->free_fn (tmp);
|
||||
|
||||
#ifdef HPDF_MEM_DEBUG
|
||||
mmgr->free_cnt++;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#ifdef HPDF_MEM_DEBUG
|
||||
HPDF_PRINTF ("# HPDF_MMgr alloc-cnt=%u, free-cnt=%u\n",
|
||||
mmgr->alloc_cnt, mmgr->free_cnt);
|
||||
|
||||
if (mmgr->alloc_cnt != mmgr->free_cnt)
|
||||
HPDF_PRINTF ("# ERROR #\n");
|
||||
#endif
|
||||
|
||||
HPDF_PTRACE(("-%p mmgr-free\n", mmgr));
|
||||
mmgr->free_fn (mmgr);
|
||||
}
|
||||
|
||||
void*
|
||||
HPDF_GetMem (HPDF_MMgr mmgr,
|
||||
HPDF_UINT size)
|
||||
{
|
||||
void * ptr;
|
||||
|
||||
if (mmgr->mpool) {
|
||||
HPDF_MPool_Node node = mmgr->mpool;
|
||||
|
||||
#ifdef HPDF_ALINMENT_SIZ
|
||||
size = (size + (HPDF_ALINMENT_SIZ - 1)) / HPDF_ALINMENT_SIZ;
|
||||
size *= HPDF_ALINMENT_SIZ;
|
||||
#endif
|
||||
|
||||
if (node->size - node->used_size >= size) {
|
||||
ptr = (HPDF_BYTE*)node->buf + node->used_size;
|
||||
node->used_size += size;
|
||||
return ptr;
|
||||
} else {
|
||||
HPDF_UINT tmp_buf_siz = (mmgr->buf_size < size) ? size :
|
||||
mmgr->buf_size;
|
||||
|
||||
node = (HPDF_MPool_Node)mmgr->alloc_fn (sizeof(HPDF_MPool_Node_Rec)
|
||||
+ tmp_buf_siz);
|
||||
HPDF_PTRACE(("+%p mmgr-new-node\n", node));
|
||||
|
||||
if (!node) {
|
||||
HPDF_SetError (mmgr->error, HPDF_FAILD_TO_ALLOC_MEM,
|
||||
HPDF_NOERROR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node->size = tmp_buf_siz;
|
||||
}
|
||||
|
||||
node->next_node = mmgr->mpool;
|
||||
mmgr->mpool = node;
|
||||
node->used_size = size;
|
||||
node->buf = (HPDF_BYTE*)node + sizeof(HPDF_MPool_Node_Rec);
|
||||
ptr = node->buf;
|
||||
} else {
|
||||
ptr = mmgr->alloc_fn (size);
|
||||
HPDF_PTRACE(("+%p mmgr-alloc_fn size=%u\n", ptr, size));
|
||||
|
||||
if (ptr == NULL)
|
||||
HPDF_SetError (mmgr->error, HPDF_FAILD_TO_ALLOC_MEM, HPDF_NOERROR);
|
||||
}
|
||||
|
||||
#ifdef HPDF_MEM_DEBUG
|
||||
if (ptr)
|
||||
mmgr->alloc_cnt++;
|
||||
#endif
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
HPDF_FreeMem (HPDF_MMgr mmgr,
|
||||
void *aptr)
|
||||
{
|
||||
if (!aptr)
|
||||
return;
|
||||
|
||||
if (!mmgr->mpool) {
|
||||
HPDF_PTRACE(("-%p mmgr-free-mem\n", aptr));
|
||||
mmgr->free_fn(aptr);
|
||||
|
||||
#ifdef HPDF_MEM_DEBUG
|
||||
mmgr->free_cnt++;
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void * HPDF_STDCALL
|
||||
InternalGetMem (HPDF_UINT size)
|
||||
{
|
||||
return HPDF_MALLOC (size);
|
||||
}
|
||||
|
||||
static void HPDF_STDCALL
|
||||
InternalFreeMem (void* aptr)
|
||||
{
|
||||
HPDF_FREE (aptr);
|
||||
}
|
||||
|
||||
|
||||
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_name.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
|
||||
HPDF_Name
|
||||
HPDF_Name_New (HPDF_MMgr mmgr,
|
||||
const char *value)
|
||||
{
|
||||
HPDF_Name obj;
|
||||
|
||||
obj = HPDF_GetMem (mmgr, sizeof(HPDF_Name_Rec));
|
||||
|
||||
if (obj) {
|
||||
HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
|
||||
obj->header.obj_class = HPDF_OCLASS_NAME;
|
||||
obj->error = mmgr->error;
|
||||
if (HPDF_Name_SetValue (obj, value) == HPDF_NAME_INVALID_VALUE) {
|
||||
HPDF_FreeMem (mmgr, obj);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Name_Write (HPDF_Name obj,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
return HPDF_Stream_WriteEscapeName (stream, obj->value);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Name_SetValue (HPDF_Name obj,
|
||||
const char *value)
|
||||
{
|
||||
if (!value || value[0] == 0)
|
||||
return HPDF_SetError (obj->error, HPDF_NAME_INVALID_VALUE, 0);
|
||||
|
||||
if (HPDF_StrLen (value, HPDF_LIMIT_MAX_NAME_LEN + 1) >
|
||||
HPDF_LIMIT_MAX_NAME_LEN)
|
||||
return HPDF_SetError (obj->error, HPDF_NAME_OUT_OF_RANGE, 0);
|
||||
|
||||
HPDF_StrCpy (obj->value, value, obj->value + HPDF_LIMIT_MAX_NAME_LEN);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
const char*
|
||||
HPDF_Name_GetValue (HPDF_Name obj)
|
||||
{
|
||||
return (const char *)obj->value;
|
||||
}
|
||||
|
||||
Vendored
+237
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_namedict.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_consts.h"
|
||||
#include "hpdf_namedict.h"
|
||||
|
||||
#ifndef HPDF_UNUSED
|
||||
#define HPDF_UNUSED(a) ((void)(a))
|
||||
#endif
|
||||
|
||||
static const char * const HPDF_NAMEDICT_KEYS[] = {
|
||||
"EmbeddedFiles"
|
||||
};
|
||||
|
||||
HPDF_NameDict
|
||||
HPDF_NameDict_New (HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_NameDict ndict;
|
||||
|
||||
HPDF_PTRACE((" HPDF_NameDict_New\n"));
|
||||
|
||||
ndict = HPDF_Dict_New (mmgr);
|
||||
if (!ndict)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Xref_Add (xref, ndict) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
ndict->header.obj_class |= HPDF_OSUBCLASS_NAMEDICT;
|
||||
|
||||
return ndict;
|
||||
}
|
||||
|
||||
HPDF_NameTree
|
||||
HPDF_NameDict_GetNameTree (HPDF_NameDict namedict,
|
||||
HPDF_NameDictKey key)
|
||||
{
|
||||
if (!namedict)
|
||||
return NULL;
|
||||
return HPDF_Dict_GetItem (namedict, HPDF_NAMEDICT_KEYS[key], HPDF_OCLASS_DICT);
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_NameDict_SetNameTree (HPDF_NameDict namedict,
|
||||
HPDF_NameDictKey key,
|
||||
HPDF_NameTree ntree)
|
||||
{
|
||||
return HPDF_Dict_Add (namedict, HPDF_NAMEDICT_KEYS[key], ntree);
|
||||
}
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_NameDict_Validate (HPDF_NameDict namedict)
|
||||
{
|
||||
if (!namedict)
|
||||
return HPDF_FALSE;
|
||||
|
||||
if (namedict->header.obj_class != (HPDF_OSUBCLASS_NAMEDICT |
|
||||
HPDF_OCLASS_DICT)) {
|
||||
HPDF_SetError (namedict->error, HPDF_INVALID_OBJECT, 0);
|
||||
return HPDF_FALSE;
|
||||
}
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*------- NameTree -------*/
|
||||
|
||||
HPDF_NameTree
|
||||
HPDF_NameTree_New (HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_NameTree ntree;
|
||||
HPDF_Array items;
|
||||
|
||||
HPDF_PTRACE((" HPDF_NameTree_New\n"));
|
||||
|
||||
ntree = HPDF_Dict_New (mmgr);
|
||||
if (!ntree)
|
||||
return NULL;
|
||||
|
||||
if (HPDF_Xref_Add (xref, ntree) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
ntree->header.obj_class |= HPDF_OSUBCLASS_NAMETREE;
|
||||
|
||||
items = HPDF_Array_New (mmgr);
|
||||
if (!ntree)
|
||||
return NULL;
|
||||
|
||||
ret += HPDF_Dict_Add (ntree, "Names", items);
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return ntree;
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_NameTree_Add (HPDF_NameTree tree,
|
||||
HPDF_String name,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_Array items;
|
||||
HPDF_INT32 i, icount;
|
||||
|
||||
if (!tree || !name)
|
||||
return HPDF_INVALID_PARAMETER;
|
||||
|
||||
items = HPDF_Dict_GetItem (tree, "Names", HPDF_OCLASS_ARRAY);
|
||||
if (!items)
|
||||
return HPDF_INVALID_OBJECT;
|
||||
|
||||
/* "The keys shall be sorted in lexical order" -- 7.9.6, Name Trees.
|
||||
* Since we store keys sorted, it's best to do a linear insertion sort
|
||||
* Find the first element larger than 'key', and insert 'key' and then
|
||||
* 'obj' into the items. */
|
||||
|
||||
icount = HPDF_Array_Items(items);
|
||||
|
||||
/* If we're larger than the last element, append */
|
||||
if (icount) {
|
||||
HPDF_String last = HPDF_Array_GetItem(items, icount - 2, HPDF_OCLASS_STRING);
|
||||
|
||||
if (HPDF_String_Cmp(name, last) > 0) {
|
||||
HPDF_Array_Add(items, name);
|
||||
HPDF_Array_Add(items, obj);
|
||||
return HPDF_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk backwards through the list until we're smaller than an element=
|
||||
* That's the element to insert in front of. */
|
||||
for (i = icount - 4; i >= 0; i -= 2) {
|
||||
HPDF_String elem = HPDF_Array_GetItem(items, i, HPDF_OCLASS_STRING);
|
||||
|
||||
if (i == 0 || HPDF_String_Cmp(name, elem) < 0) {
|
||||
HPDF_Array_Insert(items, elem, name);
|
||||
HPDF_Array_Insert(items, elem, obj);
|
||||
return HPDF_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Items list is empty */
|
||||
HPDF_Array_Add(items, name);
|
||||
HPDF_Array_Add(items, obj);
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_NameTree_Validate (HPDF_NameTree nametree)
|
||||
{
|
||||
if (!nametree)
|
||||
return HPDF_FALSE;
|
||||
|
||||
if (nametree->header.obj_class != (HPDF_OSUBCLASS_NAMETREE |
|
||||
HPDF_OCLASS_DICT)) {
|
||||
HPDF_SetError (nametree->error, HPDF_INVALID_OBJECT, 0);
|
||||
return HPDF_FALSE;
|
||||
}
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*------- EmbeddedFile -------*/
|
||||
|
||||
HPDF_EmbeddedFile
|
||||
HPDF_EmbeddedFile_New (HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref,
|
||||
const char *file)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Dict ef; /* the dictionary for the embedded file: /Type /EF */
|
||||
HPDF_String name; /* the name of the file: /F (name) */
|
||||
HPDF_Dict eff; /* ef has an /EF <<blah>> key - this is it */
|
||||
HPDF_Dict filestream; /* the stream that /EF <</F _ _ R>> refers to */
|
||||
HPDF_Stream stream;
|
||||
|
||||
ef = HPDF_Dict_New (mmgr);
|
||||
if (!ef)
|
||||
return NULL;
|
||||
if (HPDF_Xref_Add (xref, ef) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
filestream = HPDF_DictStream_New (mmgr, xref);
|
||||
if (!filestream)
|
||||
return NULL;
|
||||
stream = HPDF_FileReader_New (mmgr, file);
|
||||
if (!stream)
|
||||
return NULL;
|
||||
HPDF_Stream_Free(filestream->stream);
|
||||
filestream->stream = stream;
|
||||
filestream->filter = HPDF_STREAM_FILTER_FLATE_DECODE;
|
||||
|
||||
eff = HPDF_Dict_New (mmgr);
|
||||
if (!eff)
|
||||
return NULL;
|
||||
|
||||
name = HPDF_String_New (mmgr, file, NULL);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
ret += HPDF_Dict_AddName (ef, "Type", "F");
|
||||
ret += HPDF_Dict_Add (ef, "F", name);
|
||||
ret += HPDF_Dict_Add (ef, "EF", eff);
|
||||
ret += HPDF_Dict_Add (eff, "F", filestream);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
return ef;
|
||||
}
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_EmbeddedFile_Validate (HPDF_EmbeddedFile emfile)
|
||||
{
|
||||
HPDF_UNUSED (emfile);
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_null.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
|
||||
HPDF_Null
|
||||
HPDF_Null_New (HPDF_MMgr mmgr)
|
||||
{
|
||||
HPDF_Null obj = HPDF_GetMem (mmgr, sizeof(HPDF_Null_Rec));
|
||||
|
||||
if (obj) {
|
||||
HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
|
||||
obj->header.obj_class = HPDF_OCLASS_NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Vendored
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_number.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
|
||||
HPDF_Number
|
||||
HPDF_Number_New (HPDF_MMgr mmgr,
|
||||
HPDF_INT32 value)
|
||||
{
|
||||
HPDF_Number obj = HPDF_GetMem (mmgr, sizeof(HPDF_Number_Rec));
|
||||
|
||||
if (obj) {
|
||||
HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
|
||||
obj->header.obj_class = HPDF_OCLASS_NUMBER;
|
||||
obj->value = value;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Number_Write (HPDF_Number obj,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
return HPDF_Stream_WriteInt (stream, obj->value);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Number_SetValue (HPDF_Number obj,
|
||||
HPDF_INT32 value)
|
||||
{
|
||||
obj->value =value;
|
||||
}
|
||||
|
||||
Vendored
+175
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_objects.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
void
|
||||
HPDF_Obj_Free (HPDF_MMgr mmgr,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_Obj_Header *header;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Obj_Free\n"));
|
||||
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
if (!(header->obj_id & HPDF_OTYPE_INDIRECT))
|
||||
HPDF_Obj_ForceFree (mmgr, obj);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Obj_ForceFree (HPDF_MMgr mmgr,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_Obj_Header *header;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Obj_ForceFree\n"));
|
||||
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Obj_ForceFree obj=0x%08X obj_id=0x%08X "
|
||||
"obj_class=0x%08X\n",
|
||||
(HPDF_UINT)obj, (HPDF_UINT)(header->obj_id),
|
||||
(HPDF_UINT)(header->obj_class)));
|
||||
|
||||
switch (header->obj_class & HPDF_OCLASS_ANY) {
|
||||
case HPDF_OCLASS_STRING:
|
||||
HPDF_String_Free (obj);
|
||||
break;
|
||||
case HPDF_OCLASS_BINARY:
|
||||
HPDF_Binary_Free (obj);
|
||||
break;
|
||||
case HPDF_OCLASS_ARRAY:
|
||||
HPDF_Array_Free (obj);
|
||||
break;
|
||||
case HPDF_OCLASS_DICT:
|
||||
HPDF_Dict_Free (obj);
|
||||
break;
|
||||
default:
|
||||
HPDF_FreeMem (mmgr, obj);
|
||||
}
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Obj_Write (void *obj,
|
||||
HPDF_Stream stream,
|
||||
HPDF_Encrypt e)
|
||||
{
|
||||
HPDF_Obj_Header *header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Obj_Write\n"));
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_HIDDEN) {
|
||||
HPDF_PTRACE(("#HPDF_Obj_Write obj=0x%08X skipped\n", (HPDF_UINT)obj));
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
if (header->obj_class == HPDF_OCLASS_PROXY) {
|
||||
char buf[HPDF_SHORT_BUF_SIZ];
|
||||
char *pbuf = buf;
|
||||
char *eptr = buf + HPDF_SHORT_BUF_SIZ - 1;
|
||||
HPDF_Proxy p = obj;
|
||||
|
||||
header = (HPDF_Obj_Header*)p->obj;
|
||||
|
||||
pbuf = HPDF_IToA (pbuf, header->obj_id & 0x00FFFFFF, eptr);
|
||||
*pbuf++ = ' ';
|
||||
pbuf = HPDF_IToA (pbuf, header->gen_no, eptr);
|
||||
HPDF_StrCpy(pbuf, " R", eptr);
|
||||
|
||||
return HPDF_Stream_WriteStr(stream, buf);
|
||||
}
|
||||
|
||||
return HPDF_Obj_WriteValue(obj, stream, e);
|
||||
}
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Obj_WriteValue (void *obj,
|
||||
HPDF_Stream stream,
|
||||
HPDF_Encrypt e)
|
||||
{
|
||||
HPDF_Obj_Header *header;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Obj_WriteValue\n"));
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Obj_WriteValue obj=0x%08X obj_class=0x%04X\n",
|
||||
(HPDF_UINT)obj, (HPDF_UINT)header->obj_class));
|
||||
|
||||
switch (header->obj_class & HPDF_OCLASS_ANY) {
|
||||
case HPDF_OCLASS_NAME:
|
||||
ret = HPDF_Name_Write (obj, stream);
|
||||
break;
|
||||
case HPDF_OCLASS_NUMBER:
|
||||
ret = HPDF_Number_Write (obj, stream);
|
||||
break;
|
||||
case HPDF_OCLASS_REAL:
|
||||
ret = HPDF_Real_Write (obj, stream);
|
||||
break;
|
||||
case HPDF_OCLASS_STRING:
|
||||
ret = HPDF_String_Write (obj, stream, e);
|
||||
break;
|
||||
case HPDF_OCLASS_BINARY:
|
||||
ret = HPDF_Binary_Write (obj, stream, e);
|
||||
break;
|
||||
case HPDF_OCLASS_ARRAY:
|
||||
ret = HPDF_Array_Write (obj, stream, e);
|
||||
break;
|
||||
case HPDF_OCLASS_DICT:
|
||||
ret = HPDF_Dict_Write (obj, stream, e);
|
||||
break;
|
||||
case HPDF_OCLASS_BOOLEAN:
|
||||
ret = HPDF_Boolean_Write (obj, stream);
|
||||
break;
|
||||
case HPDF_OCLASS_NULL:
|
||||
ret = HPDF_Stream_WriteStr (stream, "null");
|
||||
break;
|
||||
default:
|
||||
ret = HPDF_ERR_UNKNOWN_CLASS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_Proxy
|
||||
HPDF_Proxy_New (HPDF_MMgr mmgr,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_Proxy p = HPDF_GetMem (mmgr, sizeof(HPDF_Proxy_Rec));
|
||||
|
||||
HPDF_PTRACE((" HPDF_Proxy_New\n"));
|
||||
|
||||
if (p) {
|
||||
HPDF_MemSet (&p->header, 0, sizeof(HPDF_Obj_Header));
|
||||
p->header.obj_class = HPDF_OCLASS_PROXY;
|
||||
p->obj = obj;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
Vendored
+330
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_outline.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_destination.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
#define HPDF_OUTLINE_CLOSED 0
|
||||
#define HPDF_OUTLINE_OPENED 1
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
AddChild (HPDF_Outline parent,
|
||||
HPDF_Outline item);
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
BeforeWrite (HPDF_Dict obj);
|
||||
|
||||
|
||||
static HPDF_UINT
|
||||
CountChild (HPDF_Outline outline);
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/*----- HPDF_Outline ---------------------------------------------------------*/
|
||||
|
||||
HPDF_Outline
|
||||
HPDF_OutlineRoot_New (HPDF_MMgr mmgr,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Outline outline;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Number open_flg;
|
||||
|
||||
HPDF_PTRACE((" HPDF_OutlineRoot_New\n"));
|
||||
|
||||
outline = HPDF_Dict_New (mmgr);
|
||||
if (!outline)
|
||||
return NULL;
|
||||
|
||||
outline->before_write_fn = BeforeWrite;
|
||||
|
||||
if (HPDF_Xref_Add (xref, outline) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
open_flg = HPDF_Number_New (mmgr, HPDF_OUTLINE_OPENED);
|
||||
if (!open_flg)
|
||||
return NULL;
|
||||
|
||||
open_flg->header.obj_id |= HPDF_OTYPE_HIDDEN;
|
||||
|
||||
ret += HPDF_Dict_Add (outline, "_OPENED", open_flg);
|
||||
ret += HPDF_Dict_AddName (outline, "Type", "Outlines");
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
outline->header.obj_class |= HPDF_OSUBCLASS_OUTLINE;
|
||||
|
||||
return outline;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Outline
|
||||
HPDF_Outline_New (HPDF_MMgr mmgr,
|
||||
HPDF_Outline parent,
|
||||
const char *title,
|
||||
HPDF_Encoder encoder,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Outline outline;
|
||||
HPDF_String s;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Number open_flg;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Outline_New\n"));
|
||||
|
||||
if (!mmgr || !parent || !xref)
|
||||
return NULL;
|
||||
|
||||
outline = HPDF_Dict_New (mmgr);
|
||||
if (!outline)
|
||||
return NULL;
|
||||
|
||||
outline->before_write_fn = BeforeWrite;
|
||||
|
||||
if (HPDF_Xref_Add (xref, outline) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
s = HPDF_String_New (mmgr, title, encoder);
|
||||
if (!s)
|
||||
return NULL;
|
||||
else
|
||||
ret += HPDF_Dict_Add (outline, "Title", s);
|
||||
|
||||
open_flg = HPDF_Number_New (mmgr, HPDF_OUTLINE_OPENED);
|
||||
if (!open_flg)
|
||||
return NULL;
|
||||
|
||||
open_flg->header.obj_id |= HPDF_OTYPE_HIDDEN;
|
||||
ret += HPDF_Dict_Add (outline, "_OPENED", open_flg);
|
||||
|
||||
ret += HPDF_Dict_AddName (outline, "Type", "Outlines");
|
||||
ret += AddChild (parent, outline);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
outline->header.obj_class |= HPDF_OSUBCLASS_OUTLINE;
|
||||
|
||||
return outline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
AddChild (HPDF_Outline parent,
|
||||
HPDF_Outline item)
|
||||
{
|
||||
HPDF_Outline first = (HPDF_Outline)HPDF_Dict_GetItem (parent, "First",
|
||||
HPDF_OCLASS_DICT);
|
||||
HPDF_Outline last = (HPDF_Outline)HPDF_Dict_GetItem (parent, "Last",
|
||||
HPDF_OCLASS_DICT);
|
||||
HPDF_STATUS ret = 0;
|
||||
|
||||
HPDF_PTRACE((" AddChild\n"));
|
||||
|
||||
if (!first)
|
||||
ret += HPDF_Dict_Add (parent, "First", item);
|
||||
|
||||
if (last) {
|
||||
ret += HPDF_Dict_Add (last, "Next", item);
|
||||
ret += HPDF_Dict_Add (item, "Prev", last);
|
||||
}
|
||||
|
||||
ret += HPDF_Dict_Add (parent, "Last", item);
|
||||
ret += HPDF_Dict_Add (item, "Parent", parent);
|
||||
|
||||
if (ret != HPDF_OK)
|
||||
return HPDF_Error_GetCode (item->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_Outline_GetOpened (HPDF_Outline outline)
|
||||
{
|
||||
HPDF_Number n = (HPDF_Number)HPDF_Dict_GetItem (outline, "_OPENED",
|
||||
HPDF_OCLASS_NUMBER);
|
||||
|
||||
HPDF_PTRACE((" HPDF_Outline_GetOpened\n"));
|
||||
|
||||
if (!n)
|
||||
return HPDF_FALSE;
|
||||
|
||||
return (HPDF_BOOL)n->value;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Outline
|
||||
HPDF_Outline_GetFirst (HPDF_Outline outline)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Outline_GetFirst\n"));
|
||||
|
||||
return (HPDF_Outline)HPDF_Dict_GetItem (outline, "First",
|
||||
HPDF_OCLASS_DICT);
|
||||
}
|
||||
|
||||
|
||||
HPDF_Outline
|
||||
HPDF_Outline_GetLast (HPDF_Outline outline)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Outline_GetLast\n"));
|
||||
|
||||
return (HPDF_Outline)HPDF_Dict_GetItem (outline, "Last", HPDF_OCLASS_DICT);
|
||||
}
|
||||
|
||||
|
||||
HPDF_Outline
|
||||
HPDF_Outline_GetPrev (HPDF_Outline outline)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Outline_GetPrev\n"));
|
||||
|
||||
return (HPDF_Outline)HPDF_Dict_GetItem (outline, "Prev", HPDF_OCLASS_DICT);
|
||||
}
|
||||
|
||||
|
||||
HPDF_Outline
|
||||
HPDF_Outline_GetNext (HPDF_Outline outline)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Outline_GetNext\n"));
|
||||
|
||||
return (HPDF_Outline)HPDF_Dict_GetItem (outline, "Next", HPDF_OCLASS_DICT);
|
||||
}
|
||||
|
||||
|
||||
HPDF_Outline
|
||||
HPDF_Outline_GetParent (HPDF_Outline outline)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Outline_GetParent\n"));
|
||||
|
||||
return (HPDF_Outline)HPDF_Dict_GetItem (outline, "Parent",
|
||||
HPDF_OCLASS_DICT);
|
||||
}
|
||||
|
||||
|
||||
static HPDF_STATUS
|
||||
BeforeWrite (HPDF_Dict obj)
|
||||
{
|
||||
HPDF_Number n = (HPDF_Number)HPDF_Dict_GetItem (obj, "Count",
|
||||
HPDF_OCLASS_NUMBER);
|
||||
HPDF_UINT count = CountChild ((HPDF_Outline)obj);
|
||||
|
||||
HPDF_PTRACE((" BeforeWrite\n"));
|
||||
|
||||
if (count == 0 && n)
|
||||
return HPDF_Dict_RemoveElement (obj, "Count");
|
||||
|
||||
if (!HPDF_Outline_GetOpened ((HPDF_Outline)obj))
|
||||
count = count * -1;
|
||||
|
||||
if (n)
|
||||
n->value = count;
|
||||
else
|
||||
if (count)
|
||||
return HPDF_Dict_AddNumber (obj, "Count", count);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
static HPDF_UINT
|
||||
CountChild (HPDF_Outline outline)
|
||||
{
|
||||
HPDF_Outline child = HPDF_Outline_GetFirst (outline);
|
||||
HPDF_UINT count = 0;
|
||||
|
||||
HPDF_PTRACE((" CountChild\n"));
|
||||
|
||||
while (child) {
|
||||
count++;
|
||||
|
||||
if (HPDF_Outline_GetOpened (child))
|
||||
count += CountChild (child);
|
||||
|
||||
child = HPDF_Outline_GetNext (child);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
HPDF_BOOL
|
||||
HPDF_Outline_Validate (HPDF_Outline outline)
|
||||
{
|
||||
if (!outline)
|
||||
return HPDF_FALSE;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Outline_Validate\n"));
|
||||
|
||||
if (outline->header.obj_class !=
|
||||
(HPDF_OSUBCLASS_OUTLINE | HPDF_OCLASS_DICT))
|
||||
return HPDF_FALSE;
|
||||
|
||||
return HPDF_TRUE;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Outline_SetDestination (HPDF_Outline outline,
|
||||
HPDF_Destination dst)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Outline_SetDestination\n"));
|
||||
|
||||
if (!HPDF_Outline_Validate (outline))
|
||||
return HPDF_INVALID_OUTLINE;
|
||||
|
||||
if (!HPDF_Destination_Validate (dst))
|
||||
return HPDF_RaiseError (outline->error, HPDF_INVALID_DESTINATION, 0);
|
||||
|
||||
if (dst == NULL)
|
||||
return HPDF_Dict_RemoveElement (outline, "Dest");
|
||||
|
||||
if (HPDF_Dict_Add (outline, "Dest", dst) != HPDF_OK)
|
||||
return HPDF_CheckError (outline->error);
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_Outline_SetOpened (HPDF_Outline outline,
|
||||
HPDF_BOOL opened)
|
||||
{
|
||||
HPDF_Number n;
|
||||
|
||||
if (!HPDF_Outline_Validate (outline))
|
||||
return HPDF_INVALID_OUTLINE;
|
||||
|
||||
n = (HPDF_Number)HPDF_Dict_GetItem (outline, "_OPENED",
|
||||
HPDF_OCLASS_NUMBER);
|
||||
|
||||
HPDF_PTRACE((" HPDF_Outline_SetOpened\n"));
|
||||
|
||||
if (!n) {
|
||||
n = HPDF_Number_New (outline->mmgr, (HPDF_INT)opened);
|
||||
if (!n || HPDF_Dict_Add (outline, "_OPENED", n) != HPDF_OK)
|
||||
return HPDF_CheckError (outline->error);
|
||||
} else
|
||||
n->value = (HPDF_INT)opened;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_page_label.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_page_label.h"
|
||||
|
||||
HPDF_Dict
|
||||
HPDF_PageLabel_New (HPDF_Doc pdf,
|
||||
HPDF_PageNumStyle style,
|
||||
HPDF_INT first_page,
|
||||
const char *prefix)
|
||||
{
|
||||
HPDF_Dict obj = HPDF_Dict_New (pdf->mmgr);
|
||||
|
||||
HPDF_PTRACE ((" HPDF_PageLabel_New\n"));
|
||||
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
switch (style) {
|
||||
case HPDF_PAGE_NUM_STYLE_DECIMAL:
|
||||
if (HPDF_Dict_AddName (obj, "S", "D") != HPDF_OK)
|
||||
goto Fail;
|
||||
break;
|
||||
case HPDF_PAGE_NUM_STYLE_UPPER_ROMAN:
|
||||
if (HPDF_Dict_AddName (obj, "S", "R") != HPDF_OK)
|
||||
goto Fail;
|
||||
break;
|
||||
case HPDF_PAGE_NUM_STYLE_LOWER_ROMAN:
|
||||
if (HPDF_Dict_AddName (obj, "S", "r") != HPDF_OK)
|
||||
goto Fail;
|
||||
break;
|
||||
case HPDF_PAGE_NUM_STYLE_UPPER_LETTERS:
|
||||
if (HPDF_Dict_AddName (obj, "S", "A") != HPDF_OK)
|
||||
goto Fail;
|
||||
break;
|
||||
case HPDF_PAGE_NUM_STYLE_LOWER_LETTERS:
|
||||
if (HPDF_Dict_AddName (obj, "S", "a") != HPDF_OK)
|
||||
goto Fail;
|
||||
break;
|
||||
default:
|
||||
HPDF_SetError (&pdf->error, HPDF_PAGE_NUM_STYLE_OUT_OF_RANGE,
|
||||
(HPDF_STATUS)style);
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
if (prefix && prefix[0] != 0)
|
||||
if (HPDF_Dict_Add (obj, "P", HPDF_String_New (pdf->mmgr, prefix,
|
||||
pdf->def_encoder)) != HPDF_OK)
|
||||
goto Fail;
|
||||
|
||||
if (first_page != 0)
|
||||
if (HPDF_Dict_AddNumber (obj, "St", first_page) != HPDF_OK)
|
||||
goto Fail;
|
||||
|
||||
return obj;
|
||||
|
||||
Fail:
|
||||
HPDF_Dict_Free (obj);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+2901
File diff suppressed because it is too large
Load Diff
Vendored
+1975
File diff suppressed because it is too large
Load Diff
Vendored
+386
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_pdfa.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
/* This is used to avoid warnings on 'ctime' when compiling in MSVC 9 */
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define HEADER "<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?><x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 2.9.1-13, framework 1.6'><rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>"
|
||||
#define DC_HEADER "<rdf:Description xmlns:dc='http://purl.org/dc/elements/1.1/' rdf:about=''>"
|
||||
#define DC_TITLE_STARTTAG "<dc:title><rdf:Alt><rdf:li xml:lang=\"x-default\">"
|
||||
#define DC_TITLE_ENDTAG "</rdf:li></rdf:Alt></dc:title>"
|
||||
#define DC_CREATOR_STARTTAG "<dc:creator><rdf:Seq><rdf:li>"
|
||||
#define DC_CREATOR_ENDTAG "</rdf:li></rdf:Seq></dc:creator>"
|
||||
#define DC_DESCRIPTION_STARTTAG "<dc:description><rdf:Alt><rdf:li xml:lang=\"x-default\">"
|
||||
#define DC_DESCRIPTION_ENDTAG "</rdf:li></rdf:Alt></dc:description>"
|
||||
#define DC_FOOTER "</rdf:Description>"
|
||||
#define XMP_HEADER "<rdf:Description xmlns:xmp='http://ns.adobe.com/xap/1.0/' rdf:about=''>"
|
||||
#define XMP_CREATORTOOL_STARTTAG "<xmp:CreatorTool>"
|
||||
#define XMP_CREATORTOOL_ENDTAG "</xmp:CreatorTool>"
|
||||
#define XMP_CREATE_DATE_STARTTAG "<xmp:CreateDate>"
|
||||
#define XMP_CREATE_DATE_ENDTAG "</xmp:CreateDate>"
|
||||
#define XMP_MOD_DATE_STARTTAG "<xmp:ModifyDate>"
|
||||
#define XMP_MOD_DATE_ENDTAG "</xmp:ModifyDate>"
|
||||
#define XMP_FOOTER "</rdf:Description>"
|
||||
#define PDF_HEADER "<rdf:Description xmlns:pdf='http://ns.adobe.com/pdf/1.3/' rdf:about=''>"
|
||||
#define PDF_KEYWORDS_STARTTAG "<pdf:Keywords>"
|
||||
#define PDF_KEYWORDS_ENDTAG "</pdf:Keywords>"
|
||||
#define PDF_PRODUCER_STARTTAG "<pdf:Producer>"
|
||||
#define PDF_PRODUCER_ENDTAG "</pdf:Producer>"
|
||||
#define PDF_FOOTER "</rdf:Description>"
|
||||
#define PDFAID_PDFA1A "<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/' pdfaid:part='1' pdfaid:conformance='A'/>"
|
||||
#define PDFAID_PDFA1B "<rdf:Description rdf:about='' xmlns:pdfaid='http://www.aiim.org/pdfa/ns/id/' pdfaid:part='1' pdfaid:conformance='B'/>"
|
||||
#define FOOTER "</rdf:RDF></x:xmpmeta><?xpacket end='w'?>"
|
||||
|
||||
|
||||
/*
|
||||
* Convert date in PDF specific format: D:YYYYMMDDHHmmSS
|
||||
* to XMP value in format YYYY-MM-DDTHH:mm:SS+offH:offMin
|
||||
*/
|
||||
HPDF_STATUS ConvertDateToXMDate(HPDF_Stream stream, const char *pDate)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
|
||||
if(pDate==NULL) return HPDF_INVALID_PARAMETER;
|
||||
if(strlen(pDate)<16) return HPDF_INVALID_PARAMETER;
|
||||
if(pDate[0]!='D'||
|
||||
pDate[1]!=':') return HPDF_INVALID_PARAMETER;
|
||||
pDate+=2;
|
||||
/* Copy YYYY */
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 4);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
pDate+=4;
|
||||
/* Write -MM */
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)"-", 1);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 2);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
pDate+=2;
|
||||
/* Write -DD */
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)"-", 1);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 2);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
pDate+=2;
|
||||
/* Write THH */
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)"T", 1);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 2);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
pDate+=2;
|
||||
/* Write :mm */
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)":", 1);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 2);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
pDate+=2;
|
||||
/* Write :SS */
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)":", 1);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 2);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
pDate+=2;
|
||||
/* Write +... */
|
||||
if(pDate[0]==0) {
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)"Z", 1);
|
||||
return ret;
|
||||
}
|
||||
if(pDate[0]=='+'||pDate[0]=='-') {
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 3);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
pDate+=4;
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)":", 1);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
ret = HPDF_Stream_Write(stream, (const HPDF_BYTE*)pDate, 2);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
return HPDF_SetError (stream->error, HPDF_INVALID_PARAMETER, 0);
|
||||
}
|
||||
|
||||
/* Write XMP Metadata for PDF/A */
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_PDFA_SetPDFAConformance (HPDF_Doc pdf,HPDF_PDFAType pdfatype)
|
||||
{
|
||||
HPDF_OutputIntent xmp;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
const char *dc_title = NULL;
|
||||
const char *dc_creator = NULL;
|
||||
const char *dc_description = NULL;
|
||||
|
||||
const char *xmp_CreatorTool = NULL;
|
||||
const char *xmp_CreateDate = NULL;
|
||||
const char *xmp_ModifyDate = NULL;
|
||||
|
||||
const char *pdf_Keywords = NULL;
|
||||
const char *pdf_Producer = NULL;
|
||||
|
||||
const char *info = NULL;
|
||||
|
||||
if (!HPDF_HasDoc(pdf)) {
|
||||
return HPDF_INVALID_DOCUMENT;
|
||||
}
|
||||
|
||||
dc_title = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_TITLE);
|
||||
dc_creator = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_AUTHOR);
|
||||
dc_description = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_SUBJECT);
|
||||
|
||||
xmp_CreateDate = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_CREATION_DATE);
|
||||
xmp_ModifyDate = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_MOD_DATE);
|
||||
xmp_CreatorTool = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_CREATOR);
|
||||
|
||||
pdf_Keywords = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_KEYWORDS);
|
||||
pdf_Producer = (const char *)HPDF_GetInfoAttr(pdf, HPDF_INFO_PRODUCER);
|
||||
|
||||
if((dc_title != NULL) || (dc_creator != NULL) || (dc_description != NULL)
|
||||
|| (xmp_CreateDate != NULL) || (xmp_ModifyDate != NULL) || (xmp_CreatorTool != NULL)
|
||||
|| (pdf_Keywords != NULL)) {
|
||||
|
||||
xmp = HPDF_DictStream_New(pdf->mmgr,pdf->xref);
|
||||
if (!xmp) {
|
||||
return HPDF_INVALID_STREAM;
|
||||
}
|
||||
|
||||
/* Update the PDF number version */
|
||||
pdf->pdf_version = HPDF_VER_14;
|
||||
|
||||
HPDF_Dict_AddName(xmp,"Type","Metadata");
|
||||
HPDF_Dict_AddName(xmp,"SubType","XML");
|
||||
|
||||
ret = HPDF_OK;
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, HEADER);
|
||||
|
||||
/* Add the dc block */
|
||||
if((dc_title != NULL) || (dc_creator != NULL) || (dc_description != NULL)) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, DC_HEADER);
|
||||
|
||||
if(dc_title != NULL) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, DC_TITLE_STARTTAG);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, dc_title);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, DC_TITLE_ENDTAG);
|
||||
}
|
||||
|
||||
if(dc_creator != NULL) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, DC_CREATOR_STARTTAG);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, dc_creator);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, DC_CREATOR_ENDTAG);
|
||||
}
|
||||
|
||||
if(dc_description != NULL) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, DC_DESCRIPTION_STARTTAG);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, dc_description);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, DC_DESCRIPTION_ENDTAG);
|
||||
}
|
||||
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, DC_FOOTER);
|
||||
}
|
||||
|
||||
/* Add the xmp block */
|
||||
if((xmp_CreateDate != NULL) || (xmp_ModifyDate != NULL) || (xmp_CreatorTool != NULL)) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_HEADER);
|
||||
|
||||
/* Add CreateDate, ModifyDate, and CreatorTool */
|
||||
if(xmp_CreatorTool != NULL) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATORTOOL_STARTTAG);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, xmp_CreatorTool);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATORTOOL_ENDTAG);
|
||||
}
|
||||
|
||||
if(xmp_CreateDate != NULL) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATE_DATE_STARTTAG);
|
||||
/* Convert date to XMP compatible format */
|
||||
ret += ConvertDateToXMDate(xmp->stream, xmp_CreateDate);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_CREATE_DATE_ENDTAG);
|
||||
}
|
||||
|
||||
if(xmp_ModifyDate != NULL) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_MOD_DATE_STARTTAG);
|
||||
ret += ConvertDateToXMDate(xmp->stream, xmp_ModifyDate);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_MOD_DATE_ENDTAG);
|
||||
}
|
||||
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, XMP_FOOTER);
|
||||
}
|
||||
|
||||
/* Add the pdf block */
|
||||
if((pdf_Keywords != NULL) || (pdf_Producer != NULL)) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_HEADER);
|
||||
|
||||
if(pdf_Keywords != NULL) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_KEYWORDS_STARTTAG);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, pdf_Keywords);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_KEYWORDS_ENDTAG);
|
||||
}
|
||||
|
||||
if(pdf_Producer != NULL) {
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_PRODUCER_STARTTAG);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, pdf_Producer);
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_PRODUCER_ENDTAG);
|
||||
}
|
||||
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, PDF_FOOTER);
|
||||
}
|
||||
|
||||
/* Add the pdfaid block */
|
||||
switch(pdfatype) {
|
||||
case HPDF_PDFA_1A:
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, PDFAID_PDFA1A);
|
||||
break;
|
||||
case HPDF_PDFA_1B:
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, PDFAID_PDFA1B);
|
||||
break;
|
||||
}
|
||||
|
||||
ret += HPDF_Stream_WriteStr(xmp->stream, FOOTER);
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
return HPDF_INVALID_STREAM;
|
||||
}
|
||||
|
||||
if ((ret = HPDF_Dict_Add(pdf->catalog, "Metadata", xmp)) != HPDF_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return HPDF_PDFA_GenerateID(pdf);
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
/* Generate an ID for the trailer dict, PDF/A needs this.
|
||||
TODO: Better algorithm for generate unique ID.
|
||||
*/
|
||||
HPDF_STATUS
|
||||
HPDF_PDFA_GenerateID(HPDF_Doc pdf)
|
||||
{
|
||||
HPDF_Array id;
|
||||
HPDF_BYTE *currentTime;
|
||||
HPDF_BYTE idkey[HPDF_MD5_KEY_LEN];
|
||||
HPDF_MD5_CTX md5_ctx;
|
||||
time_t ltime;
|
||||
|
||||
ltime = time(NULL);
|
||||
currentTime = (HPDF_BYTE *)ctime(<ime);
|
||||
|
||||
id = HPDF_Dict_GetItem(pdf->trailer, "ID", HPDF_OCLASS_ARRAY);
|
||||
if (!id) {
|
||||
id = HPDF_Array_New(pdf->mmgr);
|
||||
|
||||
if (!id || HPDF_Dict_Add(pdf->trailer, "ID", id) != HPDF_OK)
|
||||
return pdf->error.error_no;
|
||||
|
||||
HPDF_MD5Init(&md5_ctx);
|
||||
HPDF_MD5Update(&md5_ctx, (HPDF_BYTE *) "libHaru", sizeof("libHaru") - 1);
|
||||
HPDF_MD5Update(&md5_ctx, currentTime, HPDF_StrLen((const char *)currentTime, -1));
|
||||
HPDF_MD5Final(idkey, &md5_ctx);
|
||||
|
||||
if (HPDF_Array_Add (id, HPDF_Binary_New (pdf->mmgr, idkey, HPDF_MD5_KEY_LEN)) != HPDF_OK)
|
||||
return pdf->error.error_no;
|
||||
|
||||
if (HPDF_Array_Add (id, HPDF_Binary_New (pdf->mmgr,idkey,HPDF_MD5_KEY_LEN)) != HPDF_OK)
|
||||
return pdf->error.error_no;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
/* Function to add one outputintents to the PDF
|
||||
* iccname - name of default ICC profile
|
||||
* iccdict - dictionary containing number of components
|
||||
* and stream with ICC profile
|
||||
*
|
||||
* How to use:
|
||||
* 1. Create dictionary with ICC profile
|
||||
* HPDF_Dict icc = HPDF_DictStream_New (pDoc->mmgr, pDoc->xref);
|
||||
* if(icc==NULL) return false;
|
||||
* HPDF_Dict_AddNumber (icc, "N", 3);
|
||||
* HPDF_STATUS ret = HPDF_Stream_Write (icc->stream, (const HPDF_BYTE *)pICCData, dwICCSize);
|
||||
* if(ret!=HPDF_OK) {
|
||||
* HPDF_Dict_Free(icc);
|
||||
* return false;
|
||||
* }
|
||||
*
|
||||
* 2. Call this function
|
||||
*/
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_PDFA_AppendOutputIntents(HPDF_Doc pdf, const char *iccname, HPDF_Dict iccdict)
|
||||
{
|
||||
HPDF_Array intents;
|
||||
HPDF_Dict intent;
|
||||
HPDF_STATUS ret;
|
||||
if (!HPDF_HasDoc (pdf))
|
||||
return HPDF_INVALID_DOCUMENT;
|
||||
|
||||
/* prepare intent */
|
||||
intent = HPDF_Dict_New (pdf->mmgr);
|
||||
ret = HPDF_Xref_Add (pdf->xref, intent);
|
||||
if ( ret != HPDF_OK) {
|
||||
HPDF_Dict_Free(intent);
|
||||
return ret;
|
||||
}
|
||||
ret += HPDF_Dict_AddName (intent, "Type", "OutputIntent");
|
||||
ret += HPDF_Dict_AddName (intent, "S", "GTS_PDFA1");
|
||||
ret += HPDF_Dict_Add (intent, "OutputConditionIdentifier", HPDF_String_New (pdf->mmgr, iccname, NULL));
|
||||
ret += HPDF_Dict_Add (intent, "OutputCondition", HPDF_String_New (pdf->mmgr, iccname,NULL));
|
||||
ret += HPDF_Dict_Add (intent, "Info", HPDF_String_New (pdf->mmgr, iccname, NULL));
|
||||
ret += HPDF_Dict_Add (intent, "DestOutputProfile ", iccdict);
|
||||
if ( ret != HPDF_OK) {
|
||||
HPDF_Dict_Free(intent);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Copied from HPDF_AddIntent - not public function */
|
||||
intents = HPDF_Dict_GetItem (pdf->catalog, "OutputIntents", HPDF_OCLASS_ARRAY);
|
||||
if (intents == NULL) {
|
||||
intents = HPDF_Array_New (pdf->mmgr);
|
||||
if (intents) {
|
||||
HPDF_STATUS ret = HPDF_Dict_Add (pdf->catalog, "OutputIntents", intents);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_CheckError (&pdf->error);
|
||||
return HPDF_Error_GetDetailCode (&pdf->error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HPDF_Array_Add(intents,intent);
|
||||
return HPDF_Error_GetDetailCode (&pdf->error);
|
||||
}
|
||||
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_real.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
|
||||
HPDF_Real
|
||||
HPDF_Real_New (HPDF_MMgr mmgr,
|
||||
HPDF_REAL value)
|
||||
{
|
||||
HPDF_Real obj = HPDF_GetMem (mmgr, sizeof(HPDF_Real_Rec));
|
||||
|
||||
if (obj) {
|
||||
HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
|
||||
obj->header.obj_class = HPDF_OCLASS_REAL;
|
||||
obj->error = mmgr->error;
|
||||
HPDF_Real_SetValue (obj, value);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Real_Write (HPDF_Real obj,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
return HPDF_Stream_WriteReal (stream, obj->value);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Real_SetValue (HPDF_Real obj,
|
||||
HPDF_REAL value)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
if (value > HPDF_LIMIT_MAX_REAL)
|
||||
return HPDF_SetError (obj->error, HPDF_REAL_OUT_OF_RANGE, 0);
|
||||
|
||||
if (value < HPDF_LIMIT_MIN_REAL)
|
||||
return HPDF_SetError (obj->error, HPDF_REAL_OUT_OF_RANGE, 0);
|
||||
|
||||
obj->value =value;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Vendored
+1470
File diff suppressed because it is too large
Load Diff
Vendored
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_string.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
static const HPDF_BYTE UNICODE_HEADER[] = {
|
||||
0xFE, 0xFF
|
||||
};
|
||||
|
||||
|
||||
HPDF_String
|
||||
HPDF_String_New (HPDF_MMgr mmgr,
|
||||
const char *value,
|
||||
HPDF_Encoder encoder)
|
||||
{
|
||||
HPDF_String obj;
|
||||
|
||||
HPDF_PTRACE((" HPDF_String_New\n"));
|
||||
|
||||
obj = (HPDF_String)HPDF_GetMem (mmgr, sizeof(HPDF_String_Rec));
|
||||
if (obj) {
|
||||
HPDF_MemSet (&obj->header, 0, sizeof(HPDF_Obj_Header));
|
||||
obj->header.obj_class = HPDF_OCLASS_STRING;
|
||||
|
||||
obj->mmgr = mmgr;
|
||||
obj->error = mmgr->error;
|
||||
obj->encoder = encoder;
|
||||
obj->value = NULL;
|
||||
obj->len = 0;
|
||||
|
||||
if (HPDF_String_SetValue (obj, value) != HPDF_OK) {
|
||||
HPDF_FreeMem (obj->mmgr, obj);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_String_SetValue (HPDF_String obj,
|
||||
const char *value)
|
||||
{
|
||||
HPDF_UINT len;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE((" HPDF_String_SetValue\n"));
|
||||
|
||||
if (obj->value) {
|
||||
HPDF_FreeMem (obj->mmgr, obj->value);
|
||||
obj->len = 0;
|
||||
}
|
||||
|
||||
len = HPDF_StrLen(value, HPDF_LIMIT_MAX_STRING_LEN + 1);
|
||||
|
||||
if (len > HPDF_LIMIT_MAX_STRING_LEN)
|
||||
return HPDF_SetError (obj->error, HPDF_STRING_OUT_OF_RANGE, 0);
|
||||
|
||||
obj->value = HPDF_GetMem (obj->mmgr, len + 1);
|
||||
if (!obj->value)
|
||||
return HPDF_Error_GetCode (obj->error);
|
||||
|
||||
HPDF_StrCpy ((char *)obj->value, value, (char *)obj->value + len);
|
||||
obj->len = len;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
HPDF_String_Free (HPDF_String obj)
|
||||
{
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
HPDF_PTRACE((" HPDF_String_Free\n"));
|
||||
|
||||
HPDF_FreeMem (obj->mmgr, obj->value);
|
||||
HPDF_FreeMem (obj->mmgr, obj);
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_String_Write (HPDF_String obj,
|
||||
HPDF_Stream stream,
|
||||
HPDF_Encrypt e)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
|
||||
/*
|
||||
* When encoder is not NULL, text is changed to unicode using encoder,
|
||||
* and it outputs by HPDF_write_binary method.
|
||||
*/
|
||||
|
||||
HPDF_PTRACE((" HPDF_String_Write\n"));
|
||||
|
||||
if (e)
|
||||
HPDF_Encrypt_Reset (e);
|
||||
|
||||
if (obj->encoder == NULL) {
|
||||
if (e) {
|
||||
if ((ret = HPDF_Stream_WriteChar (stream, '<')) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteBinary (stream, obj->value,
|
||||
HPDF_StrLen ((char *)obj->value, -1), e)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_Stream_WriteChar (stream, '>');
|
||||
} else {
|
||||
return HPDF_Stream_WriteEscapeText (stream, (char *)obj->value);
|
||||
}
|
||||
} else {
|
||||
HPDF_BYTE* src = obj->value;
|
||||
HPDF_BYTE buf[HPDF_TEXT_DEFAULT_LEN * 2];
|
||||
HPDF_UINT tmp_len = 0;
|
||||
HPDF_BYTE* pbuf = buf;
|
||||
HPDF_INT32 len = obj->len;
|
||||
HPDF_ParseText_Rec parse_state;
|
||||
HPDF_UINT i;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteChar (stream, '<')) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteBinary (stream, UNICODE_HEADER, 2, e))
|
||||
!= HPDF_OK)
|
||||
return ret;
|
||||
|
||||
HPDF_Encoder_SetParseText (obj->encoder, &parse_state, src, len);
|
||||
|
||||
for (i = 0; (HPDF_INT32)i < len; i++) {
|
||||
HPDF_BYTE b = src[i];
|
||||
HPDF_UNICODE tmp_unicode;
|
||||
HPDF_ByteType btype = HPDF_Encoder_ByteType (obj->encoder,
|
||||
&parse_state);
|
||||
|
||||
if (tmp_len >= HPDF_TEXT_DEFAULT_LEN - 1) {
|
||||
if ((ret = HPDF_Stream_WriteBinary (stream, buf,
|
||||
tmp_len * 2, e)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
tmp_len = 0;
|
||||
pbuf = buf;
|
||||
}
|
||||
|
||||
if (btype != HPDF_BYTE_TYPE_TRIAL) {
|
||||
if (btype == HPDF_BYTE_TYPE_LEAD) {
|
||||
HPDF_BYTE b2 = src[i + 1];
|
||||
HPDF_UINT16 char_code = (HPDF_UINT16)((HPDF_UINT) b * 256 + b2);
|
||||
|
||||
tmp_unicode = HPDF_Encoder_ToUnicode (obj->encoder,
|
||||
char_code);
|
||||
} else {
|
||||
tmp_unicode = HPDF_Encoder_ToUnicode (obj->encoder, b);
|
||||
}
|
||||
|
||||
HPDF_UInt16Swap (&tmp_unicode);
|
||||
HPDF_MemCpy (pbuf, (HPDF_BYTE*)&tmp_unicode, 2);
|
||||
pbuf += 2;
|
||||
tmp_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_len > 0) {
|
||||
if ((ret = HPDF_Stream_WriteBinary (stream, buf, tmp_len * 2, e))
|
||||
!= HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = HPDF_Stream_WriteChar (stream, '>')) != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
|
||||
HPDF_INT32
|
||||
HPDF_String_Cmp (HPDF_String s1,
|
||||
HPDF_String s2)
|
||||
{
|
||||
if (s1->len < s2->len) return -1;
|
||||
if (s1->len > s2->len) return +1;
|
||||
return memcmp(s1->value, s2->value, s1->len);
|
||||
}
|
||||
Vendored
+880
@@ -0,0 +1,880 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_u3d.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifndef M_PI
|
||||
/* Not defined in MSVC6 */
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
HPDF_U3D
|
||||
HPDF_U3D_LoadU3D (HPDF_MMgr mmgr,
|
||||
HPDF_Stream u3d_data,
|
||||
HPDF_Xref xref);
|
||||
|
||||
static const char u3d[] = "U3D";
|
||||
static const char prc[] = "PRC";
|
||||
|
||||
static HPDF_STATUS Get3DStreamType (HPDF_Stream stream, const char **type)
|
||||
{
|
||||
HPDF_BYTE tag[4];
|
||||
HPDF_UINT len;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_U3D_Get3DStreamType\n"));
|
||||
|
||||
len = 4;
|
||||
if (HPDF_Stream_Read (stream, tag, &len) != HPDF_OK) {
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Seek (stream, 0, HPDF_SEEK_SET) != HPDF_OK) {
|
||||
return HPDF_Error_GetCode (stream->error);
|
||||
}
|
||||
|
||||
if (HPDF_MemCmp(tag, (HPDF_BYTE *)u3d, 4/* yes, \0 is required */) == 0) {
|
||||
*type = u3d;
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
if (HPDF_MemCmp(tag, (HPDF_BYTE *)prc, 3) == 0) {
|
||||
*type = prc;
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
|
||||
HPDF_U3D
|
||||
HPDF_U3D_LoadU3DFromMem ( HPDF_MMgr mmgr,
|
||||
const HPDF_BYTE *buf,
|
||||
HPDF_UINT size,
|
||||
HPDF_Xref xref )
|
||||
{
|
||||
HPDF_Dict image;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_U3D_LoadU3DFromMem\n"));
|
||||
|
||||
image = HPDF_DictStream_New (mmgr, xref);
|
||||
if (!image) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
image->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
ret = HPDF_Dict_AddName (image, "Type", "XObject");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free(image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddName (image, "Subtype", "Image");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free(image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (image->stream, buf, size) != HPDF_OK) {
|
||||
HPDF_Dict_Free(image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_Image)
|
||||
HPDF_LoadU3DFromFile (HPDF_Doc pdf,
|
||||
const char *filename)
|
||||
{
|
||||
HPDF_Stream imagedata;
|
||||
HPDF_Image image;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_LoadU3DFromFile\n"));
|
||||
|
||||
if (!HPDF_HasDoc (pdf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create file stream */
|
||||
imagedata = HPDF_FileReader_New (pdf->mmgr, filename);
|
||||
|
||||
if (HPDF_Stream_Validate (imagedata)) {
|
||||
image = HPDF_U3D_LoadU3D (pdf->mmgr, imagedata, pdf->xref);
|
||||
} else {
|
||||
image = NULL;
|
||||
}
|
||||
|
||||
/* destroy file stream */
|
||||
HPDF_Stream_Free (imagedata);
|
||||
|
||||
if (!image) {
|
||||
HPDF_CheckError (&pdf->error);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_Image)
|
||||
HPDF_LoadU3DFromMem (HPDF_Doc pdf,
|
||||
const HPDF_BYTE *buffer,
|
||||
HPDF_UINT size)
|
||||
{
|
||||
HPDF_Stream imagedata;
|
||||
HPDF_Image image;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_LoadU3DFromMem\n"));
|
||||
|
||||
if (!HPDF_HasDoc (pdf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create file stream */
|
||||
imagedata = HPDF_MemStream_New (pdf->mmgr, size);
|
||||
|
||||
if (!HPDF_Stream_Validate (imagedata)) {
|
||||
HPDF_RaiseError (&pdf->error, HPDF_INVALID_STREAM, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (imagedata, buffer, size) != HPDF_OK) {
|
||||
HPDF_Stream_Free (imagedata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Validate (imagedata)) {
|
||||
image = HPDF_U3D_LoadU3D (pdf->mmgr, imagedata, pdf->xref);
|
||||
} else {
|
||||
image = NULL;
|
||||
}
|
||||
|
||||
/* destroy file stream */
|
||||
HPDF_Stream_Free (imagedata);
|
||||
|
||||
if (!image) {
|
||||
HPDF_CheckError (&pdf->error);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
HPDF_U3D
|
||||
HPDF_U3D_LoadU3D (HPDF_MMgr mmgr,
|
||||
HPDF_Stream u3d_data,
|
||||
HPDF_Xref xref)
|
||||
{
|
||||
HPDF_Dict u3d;
|
||||
const char *type;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_U3D_LoadU3D\n"));
|
||||
|
||||
u3d = HPDF_DictStream_New (mmgr, xref);
|
||||
if (!u3d) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u3d->header.obj_class |= HPDF_OSUBCLASS_XOBJECT;
|
||||
|
||||
/* add required elements */
|
||||
u3d->filter = HPDF_STREAM_FILTER_NONE;
|
||||
|
||||
if (HPDF_Dict_AddName (u3d, "Type", "3D") != HPDF_OK) {
|
||||
HPDF_Dict_Free(u3d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Get3DStreamType (u3d_data, &type) != HPDF_OK) {
|
||||
HPDF_Dict_Free(u3d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Dict_AddName (u3d, "Subtype", type) != HPDF_OK) {
|
||||
HPDF_Dict_Free(u3d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
HPDF_BYTE buf[HPDF_STREAM_BUF_SIZ];
|
||||
HPDF_UINT len = HPDF_STREAM_BUF_SIZ;
|
||||
HPDF_STATUS ret = HPDF_Stream_Read (u3d_data, buf, &len);
|
||||
|
||||
if (ret != HPDF_OK) {
|
||||
if (ret == HPDF_STREAM_EOF) {
|
||||
if (len > 0) {
|
||||
ret = HPDF_Stream_Write (u3d->stream, buf, len);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free(u3d);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
HPDF_Dict_Free(u3d);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (HPDF_Stream_Write (u3d->stream, buf, len) != HPDF_OK) {
|
||||
HPDF_Dict_Free(u3d);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return u3d;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_Dict) HPDF_Create3DView(HPDF_MMgr mmgr, const char *name)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Dict view;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Create3DView\n"));
|
||||
|
||||
if (name == NULL || name[0] == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
view = HPDF_Dict_New (mmgr);
|
||||
if (!view) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddName (view, "TYPE", "3DView");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "XN", HPDF_String_New (mmgr, name, NULL));
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "IN", HPDF_String_New (mmgr, name, NULL));
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_U3D_Add3DView(HPDF_U3D u3d, HPDF_Dict view)
|
||||
{
|
||||
HPDF_Array views = NULL;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_Add3DView\n"));
|
||||
|
||||
if (u3d == NULL || view == NULL) {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
views = (HPDF_Array)HPDF_Dict_GetItem (u3d, "VA", HPDF_OCLASS_ARRAY);
|
||||
if (views == NULL) {
|
||||
views = HPDF_Array_New (u3d->mmgr);
|
||||
if (!views) {
|
||||
return HPDF_Error_GetCode (u3d->error);
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (u3d, "VA", views);
|
||||
if (ret == HPDF_OK) {
|
||||
ret = HPDF_Dict_AddNumber (u3d, "DV", 0);
|
||||
} else {
|
||||
HPDF_Array_Free (views);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == HPDF_OK) {
|
||||
ret = HPDF_Array_Add( views, view);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_U3D_AddOnInstanciate(HPDF_U3D u3d, HPDF_JavaScript javascript)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_U3D_AddOnInstanciate\n"));
|
||||
|
||||
if (u3d == NULL || javascript == NULL) {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add(u3d, "OnInstantiate", javascript);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_U3D_SetDefault3DView(HPDF_U3D u3d, const char *name)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_U3D_SetDefault3DView\n"));
|
||||
|
||||
if (u3d == NULL || name == NULL || name[0] == '\0') {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (u3d, "DV", HPDF_String_New (u3d->mmgr, name, NULL));
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_AddNode(HPDF_Dict view, const char *name, HPDF_REAL opacity, HPDF_BOOL visible)
|
||||
{
|
||||
HPDF_Array nodes = NULL;
|
||||
HPDF_Dict node;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_3DView_AddNode\n"));
|
||||
|
||||
if (view == NULL || opacity < 0 || opacity > 1 || name == NULL || name[0] == '\0') {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
nodes = (HPDF_Array)HPDF_Dict_GetItem (view, "NA", HPDF_OCLASS_ARRAY);
|
||||
if (nodes == NULL) {
|
||||
nodes = HPDF_Array_New (view->mmgr);
|
||||
if (!nodes) {
|
||||
return HPDF_Error_GetCode (view->error);
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "NA", nodes);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (nodes);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
node = HPDF_Dict_New (view->mmgr);
|
||||
if (!node) {
|
||||
HPDF_Array_Free (nodes);
|
||||
return HPDF_Error_GetCode (view->error);
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddName (node, "Type", "3DNode");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (nodes);
|
||||
HPDF_Dict_Free (node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (node, "N", HPDF_String_New (view->mmgr, name, NULL));
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (nodes);
|
||||
HPDF_Dict_Free (node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddReal (node, "O", opacity);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (nodes);
|
||||
HPDF_Dict_Free (node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddBoolean (node, "V", visible);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (node);
|
||||
HPDF_Array_Free (nodes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Array_Add(nodes, node);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (node);
|
||||
HPDF_Array_Free (nodes);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetLighting(HPDF_Dict view, const char *scheme)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Dict lighting;
|
||||
int i;
|
||||
static const char * const schemes[] =
|
||||
{ "Artwork", "None", "White", "Day", "Night", "Hard", "Primary", "Blue", "Red", "Cube", "CAD", "Headlamp" };
|
||||
|
||||
HPDF_PTRACE ((" HPDF_3DView_SetLighting\n"));
|
||||
|
||||
if (view == NULL || scheme == NULL || scheme[0] == '\0') {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
if (!strcmp(scheme, schemes[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 12) {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
lighting = HPDF_Dict_New (view->mmgr);
|
||||
if (!lighting) {
|
||||
return HPDF_Error_GetCode (view->error);
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddName (lighting, "Type", "3DLightingScheme");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (lighting);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddName (lighting, "Subtype", scheme);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (lighting);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "LS", lighting);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (lighting);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetBackgroundColor(HPDF_Dict view, HPDF_REAL r, HPDF_REAL g, HPDF_REAL b)
|
||||
{
|
||||
HPDF_Array color;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Dict background;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_3DView_SetBackgroundColor\n"));
|
||||
|
||||
if (view == NULL || r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1) {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
background = HPDF_Dict_New (view->mmgr);
|
||||
if (!background) {
|
||||
return HPDF_Error_GetCode (view->error);
|
||||
}
|
||||
|
||||
color = HPDF_Array_New (view->mmgr);
|
||||
if (!color) {
|
||||
HPDF_Dict_Free (background);
|
||||
return HPDF_Error_GetCode (view->error);
|
||||
}
|
||||
|
||||
ret = HPDF_Array_AddReal (color, r);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (color);
|
||||
HPDF_Dict_Free (background);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Array_AddReal (color, g);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (color);
|
||||
HPDF_Dict_Free (background);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Array_AddReal (color, b);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (color);
|
||||
HPDF_Dict_Free (background);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ret = HPDF_Dict_AddName (background, "Type", "3DBG");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (color);
|
||||
HPDF_Dict_Free (background);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (background, "C", color);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (color);
|
||||
HPDF_Dict_Free (background);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "BG", background);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (color);
|
||||
HPDF_Dict_Free (background);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetPerspectiveProjection(HPDF_Dict view, HPDF_REAL fov)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Dict projection;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_3DView_SetPerspectiveProjection\n"));
|
||||
|
||||
if (view == NULL || fov < 0 || fov > 180) {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
projection = HPDF_Dict_New (view->mmgr);
|
||||
if (!projection) {
|
||||
return HPDF_Error_GetCode (view->error);
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddName (projection, "Subtype", "P");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (projection);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddName (projection, "PS", "Min");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (projection);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddReal (projection, "FOV", fov);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (projection);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "P", projection);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (projection);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetOrthogonalProjection(HPDF_Dict view, HPDF_REAL mag)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Dict projection;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_3DView_SetOrthogonalProjection\n"));
|
||||
|
||||
if (view == NULL || mag <= 0) {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
projection = HPDF_Dict_New (view->mmgr);
|
||||
if (!projection) {
|
||||
return HPDF_Error_GetCode (view->error);
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddName (projection, "Subtype", "O");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (projection);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_AddReal (projection, "OS", mag);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (projection);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "P", projection);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (projection);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define normalize(x, y, z) \
|
||||
{ \
|
||||
HPDF_REAL modulo; \
|
||||
modulo = (float)sqrt((float)(x*x) + (float)(y*y) + (float)(z*z)); \
|
||||
if (modulo != 0.0) \
|
||||
{ \
|
||||
x = x/modulo; \
|
||||
y = y/modulo; \
|
||||
z = z/modulo; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* building the transformation matrix*/
|
||||
/* #1,#2,#3 centre of orbit coordinates (coo)*/
|
||||
/* #4,#5,#6 centre of orbit to camera direction vector (c2c)*/
|
||||
/* #7 orbital radius (roo)*/
|
||||
/* #8 camera roll (roll)*/
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS) HPDF_3DView_SetCamera(HPDF_Dict view, HPDF_REAL coox, HPDF_REAL cooy, HPDF_REAL cooz, HPDF_REAL c2cx, HPDF_REAL c2cy, HPDF_REAL c2cz, HPDF_REAL roo, HPDF_REAL roll)
|
||||
{
|
||||
HPDF_REAL viewx, viewy, viewz;
|
||||
HPDF_REAL leftx, lefty, leftz;
|
||||
HPDF_REAL upx, upy, upz;
|
||||
HPDF_REAL transx, transy, transz;
|
||||
|
||||
HPDF_Array matrix;
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_3DView_SetCamera\n"));
|
||||
|
||||
if (view == NULL) {
|
||||
return HPDF_INVALID_U3D_DATA;
|
||||
}
|
||||
|
||||
/* view vector (opposite to c2c) */
|
||||
viewx = -c2cx;
|
||||
viewy = -c2cy;
|
||||
viewz = -c2cz;
|
||||
|
||||
/* c2c = (0, -1, 0) by default */
|
||||
if (viewx == 0.0 && viewy == 0.0 && viewz == 0.0) {
|
||||
viewy = 1.0;
|
||||
}
|
||||
/* normalize view vector */
|
||||
normalize(viewx, viewy, viewz);
|
||||
|
||||
/* rotation matrix */
|
||||
|
||||
/* top and bottom views */
|
||||
leftx = -1.0f;
|
||||
lefty = 0.0f;
|
||||
leftz = 0.0f;
|
||||
|
||||
/* up-vector */
|
||||
if (viewz < 0.0) /* top view*/
|
||||
{
|
||||
upx = 0.0f;
|
||||
upy = 1.0f;
|
||||
upz = 0.0f;
|
||||
}
|
||||
else /* bottom view*/
|
||||
{
|
||||
upx = 0.0f;
|
||||
upy =-1.0f;
|
||||
upz = 0.0f;
|
||||
}
|
||||
|
||||
if ( fabs(viewx) + fabs(viewy) != 0.0f) /* other views than top and bottom*/
|
||||
{
|
||||
/* up-vector = up_world - (up_world dot view) view*/
|
||||
upx = -viewz*viewx;
|
||||
upy = -viewz*viewy;
|
||||
upz = -viewz*viewz + 1.0f;
|
||||
/* normalize up-vector*/
|
||||
normalize(upx, upy, upz);
|
||||
/* left vector = up x view*/
|
||||
leftx = viewz*upy - viewy*upz;
|
||||
lefty = viewx*upz - viewz*upx;
|
||||
leftz = viewy*upx - viewx*upy;
|
||||
/* normalize left vector*/
|
||||
normalize(leftx, lefty, leftz);
|
||||
}
|
||||
/* apply camera roll*/
|
||||
{
|
||||
HPDF_REAL leftxprime, leftyprime, leftzprime;
|
||||
HPDF_REAL upxprime, upyprime, upzprime;
|
||||
HPDF_REAL sinroll, cosroll;
|
||||
|
||||
sinroll = (HPDF_REAL)sin((roll/180.0f)*M_PI);
|
||||
cosroll = (HPDF_REAL)cos((roll/180.0f)*M_PI);
|
||||
leftxprime = leftx*cosroll + upx*sinroll;
|
||||
leftyprime = lefty*cosroll + upy*sinroll;
|
||||
leftzprime = leftz*cosroll + upz*sinroll;
|
||||
upxprime = upx*cosroll + leftx*sinroll;
|
||||
upyprime = upy*cosroll + lefty*sinroll;
|
||||
upzprime = upz*cosroll + leftz*sinroll;
|
||||
leftx = leftxprime;
|
||||
lefty = leftyprime;
|
||||
leftz = leftzprime;
|
||||
upx = upxprime;
|
||||
upy = upyprime;
|
||||
upz = upzprime;
|
||||
}
|
||||
|
||||
/* translation vector*/
|
||||
roo = (HPDF_REAL)fabs(roo);
|
||||
if (roo == 0.0) {
|
||||
roo = (HPDF_REAL)0.000000000000000001;
|
||||
}
|
||||
transx = coox - roo*viewx;
|
||||
transy = cooy - roo*viewy;
|
||||
transz = cooz - roo*viewz;
|
||||
|
||||
/* transformation matrix*/
|
||||
matrix = HPDF_Array_New (view->mmgr);
|
||||
if (!matrix) {
|
||||
return HPDF_Error_GetCode (view->error);
|
||||
}
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, leftx);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, lefty);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, leftz);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, upx);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, upy);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, upz);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, viewx);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, viewy);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, viewz);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, transx);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, transy);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Array_AddReal (matrix, transz);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Dict_AddName (view, "MS", "M");
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Dict_Add (view, "C2W", matrix);
|
||||
if (ret != HPDF_OK) goto failed;
|
||||
|
||||
ret = HPDF_Dict_AddNumber (view, "CO", (HPDF_INT32)roo);
|
||||
|
||||
failed:
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Array_Free (matrix);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
HPDF_Dict HPDF_3DView_New( HPDF_MMgr mmgr, HPDF_Xref xref, HPDF_U3D u3d, const char *name)
|
||||
{
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Dict view;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_3DView_New\n"));
|
||||
|
||||
if (name == NULL || name[0] == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
view = HPDF_Dict_New (mmgr);
|
||||
if (!view) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (HPDF_Xref_Add (xref, view) != HPDF_OK)
|
||||
return NULL;
|
||||
|
||||
ret = HPDF_Dict_AddName (view, "TYPE", "3DView");
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "XN", HPDF_String_New (mmgr, name, NULL));
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = HPDF_Dict_Add (view, "IN", HPDF_String_New (mmgr, name, NULL));
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = HPDF_U3D_Add3DView( u3d, view);
|
||||
if (ret != HPDF_OK) {
|
||||
HPDF_Dict_Free (view);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_STATUS)
|
||||
HPDF_3DView_Add3DC3DMeasure(HPDF_Dict view,
|
||||
HPDF_3DMeasure measure)
|
||||
{
|
||||
|
||||
HPDF_STATUS ret = HPDF_OK;
|
||||
HPDF_Array array;
|
||||
void* a;
|
||||
|
||||
a = HPDF_Dict_GetItem (view, "MA", HPDF_OCLASS_ARRAY);
|
||||
|
||||
if ( a )
|
||||
{
|
||||
array = (HPDF_Array)a;
|
||||
}
|
||||
else
|
||||
{
|
||||
array = HPDF_Array_New (view->mmgr);
|
||||
if (!array)
|
||||
return 0;
|
||||
|
||||
if (HPDF_Dict_Add (view, "MA", array) != HPDF_OK)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = HPDF_Array_Add(array, measure);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
HPDF_EXPORT(HPDF_JavaScript) HPDF_CreateJavaScript( HPDF_Doc pdf, const char *code )
|
||||
{
|
||||
HPDF_JavaScript javaScript;
|
||||
int len ;
|
||||
|
||||
HPDF_PTRACE ((" HPDF_CreateJavaScript\n"));
|
||||
|
||||
javaScript = (HPDF_JavaScript) HPDF_DictStream_New(pdf->mmgr, pdf->xref);
|
||||
if (!javaScript) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = (HPDF_UINT)strlen(code);
|
||||
if (HPDF_Stream_Write (javaScript->stream, (HPDF_BYTE *)code, len) != HPDF_OK) {
|
||||
HPDF_Dict_Free(javaScript);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return javaScript;
|
||||
}
|
||||
|
||||
|
||||
#undef normalize
|
||||
|
||||
Vendored
+445
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_utils.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_consts.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
HPDF_INT
|
||||
HPDF_AToI (const char *s)
|
||||
{
|
||||
HPDF_BOOL flg = HPDF_FALSE;
|
||||
HPDF_INT v = 0;
|
||||
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* increment pointer until the charactor of 's' is not
|
||||
* white-space-charactor.
|
||||
*/
|
||||
while (*s) {
|
||||
if (HPDF_IS_WHITE_SPACE(*s))
|
||||
s++;
|
||||
else {
|
||||
if (*s == '-') {
|
||||
flg = HPDF_TRUE;
|
||||
s++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (*s >= '0' && *s <= '9') {
|
||||
v *= 10;
|
||||
v += *s - '0';
|
||||
s++;
|
||||
}
|
||||
|
||||
if (flg)
|
||||
v *= -1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
HPDF_DOUBLE
|
||||
HPDF_AToF (const char *s)
|
||||
{
|
||||
HPDF_BOOL flg = HPDF_FALSE;
|
||||
HPDF_INT i = 0;
|
||||
HPDF_DOUBLE v;
|
||||
HPDF_INT tmp = 1;
|
||||
|
||||
/* increment pointer until the charactor of 's' is not
|
||||
* white-space-charactor.
|
||||
*/
|
||||
while (*s) {
|
||||
if (HPDF_IS_WHITE_SPACE(*s))
|
||||
s++;
|
||||
else {
|
||||
if (*s == '-') {
|
||||
flg = HPDF_TRUE;
|
||||
s++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (*s >= '0' && *s <= '9') {
|
||||
if (i > 3276)
|
||||
break;
|
||||
|
||||
i *= 10;
|
||||
i += *s - '0';
|
||||
s++;
|
||||
}
|
||||
|
||||
if (*s == '.') {
|
||||
s++;
|
||||
while (*s >= '0' && *s <= '9') {
|
||||
if (i > 214748364)
|
||||
break;
|
||||
|
||||
i *= 10;
|
||||
i += *s - '0';
|
||||
s++;
|
||||
tmp *= 10;
|
||||
}
|
||||
}
|
||||
|
||||
v = (HPDF_DOUBLE)i / tmp;
|
||||
|
||||
if (flg)
|
||||
v *= -1;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
HPDF_IToA (char *s,
|
||||
HPDF_INT32 val,
|
||||
char *eptr)
|
||||
{
|
||||
char* t;
|
||||
char buf[HPDF_INT_LEN + 1];
|
||||
|
||||
if (val < 0) {
|
||||
if (val < HPDF_LIMIT_MIN_INT)
|
||||
val = HPDF_LIMIT_MIN_INT;
|
||||
*s++ = '-';
|
||||
val = -val;
|
||||
} else if (val > HPDF_LIMIT_MAX_INT) {
|
||||
val = HPDF_LIMIT_MAX_INT;
|
||||
} else if (val == 0) {
|
||||
*s++ = '0';
|
||||
}
|
||||
|
||||
t = buf + HPDF_INT_LEN;
|
||||
*t-- = 0;
|
||||
|
||||
while (val > 0) {
|
||||
*t = (char)((char)(val % 10) + '0');
|
||||
val /= 10;
|
||||
t--;
|
||||
}
|
||||
|
||||
t++;
|
||||
while (s < eptr && *t != 0)
|
||||
*s++ = *t++;
|
||||
*s = 0;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
HPDF_IToA2 (char *s,
|
||||
HPDF_UINT32 val,
|
||||
HPDF_UINT len)
|
||||
{
|
||||
char* t;
|
||||
char* u;
|
||||
|
||||
if (val > HPDF_LIMIT_MAX_INT)
|
||||
val = HPDF_LIMIT_MAX_INT;
|
||||
|
||||
u = s + len - 1;
|
||||
*u = 0;
|
||||
t = u - 1;
|
||||
while (val > 0 && t >= s) {
|
||||
*t = (char)((char)(val % 10) + '0');
|
||||
val /= 10;
|
||||
t--;
|
||||
}
|
||||
|
||||
while (s <= t)
|
||||
*t-- = '0';
|
||||
|
||||
return s + len - 1;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
HPDF_FToA (char *s,
|
||||
HPDF_REAL val,
|
||||
char *eptr)
|
||||
{
|
||||
HPDF_INT32 int_val;
|
||||
HPDF_INT32 fpart_val;
|
||||
char buf[HPDF_REAL_LEN + 1];
|
||||
char* sptr = s;
|
||||
char* t;
|
||||
HPDF_UINT32 i;
|
||||
|
||||
if (val > HPDF_LIMIT_MAX_REAL)
|
||||
val = HPDF_LIMIT_MAX_REAL;
|
||||
else
|
||||
if (val < HPDF_LIMIT_MIN_REAL)
|
||||
val = HPDF_LIMIT_MIN_REAL;
|
||||
|
||||
t = buf + HPDF_REAL_LEN;
|
||||
*t-- = 0;
|
||||
|
||||
if (val < 0) {
|
||||
*s++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
|
||||
/* separate an integer part and a decimal part. */
|
||||
int_val = (HPDF_INT32)(val + 0.000005);
|
||||
fpart_val = (HPDF_INT32)((HPDF_REAL)(val - int_val + 0.000005) * 100000);
|
||||
|
||||
/* process decimal part */
|
||||
for (i = 0; i < 5; i++) {
|
||||
*t = (char)((char)(fpart_val % 10) + '0');
|
||||
fpart_val /= 10;
|
||||
t--;
|
||||
}
|
||||
|
||||
/* process integer part */
|
||||
*t-- = '.';
|
||||
*t = '0';
|
||||
if (int_val == 0)
|
||||
t--;
|
||||
|
||||
while (int_val > 0) {
|
||||
*t = (char)((char)(int_val % 10) + '0');
|
||||
int_val /= 10;
|
||||
t--;
|
||||
}
|
||||
|
||||
t++;
|
||||
while (s <= eptr && *t != 0)
|
||||
*s++ = *t++;
|
||||
s--;
|
||||
|
||||
/* delete an excessive decimal portion. */
|
||||
while (s > sptr) {
|
||||
if (*s == '0')
|
||||
*s = 0;
|
||||
else {
|
||||
if (*s == '.')
|
||||
*s = 0;
|
||||
break;
|
||||
}
|
||||
s--;
|
||||
}
|
||||
|
||||
return (*s == 0) ? s : ++s;
|
||||
}
|
||||
|
||||
|
||||
HPDF_BYTE*
|
||||
HPDF_MemCpy (HPDF_BYTE* out,
|
||||
const HPDF_BYTE *in,
|
||||
HPDF_UINT n)
|
||||
{
|
||||
while (n > 0) {
|
||||
*out++ = *in++;
|
||||
n--;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
HPDF_BYTE*
|
||||
HPDF_StrCpy (char *out,
|
||||
const char *in,
|
||||
char *eptr)
|
||||
{
|
||||
if (in != NULL) {
|
||||
while (eptr > out && *in != 0)
|
||||
*out++ = *in++;
|
||||
}
|
||||
|
||||
*out = 0;
|
||||
|
||||
return (HPDF_BYTE *)out;
|
||||
}
|
||||
|
||||
|
||||
HPDF_INT
|
||||
HPDF_MemCmp (const HPDF_BYTE *s1,
|
||||
const HPDF_BYTE *s2,
|
||||
HPDF_UINT n)
|
||||
{
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
while (*s1 == *s2) {
|
||||
n--;
|
||||
if (n == 0)
|
||||
return 0;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return *s1 - *s2;
|
||||
}
|
||||
|
||||
|
||||
HPDF_INT
|
||||
HPDF_StrCmp (const char *s1,
|
||||
const char *s2)
|
||||
{
|
||||
if (!s1 || !s2) {
|
||||
if (!s1 && s2)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (*s1 == *s2) {
|
||||
s1++;
|
||||
s2++;
|
||||
if (*s1 == 0 || *s2 == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return (HPDF_BYTE)*s1 - (HPDF_BYTE)*s2;
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
HPDF_MemSet (void *s,
|
||||
HPDF_BYTE c,
|
||||
HPDF_UINT n)
|
||||
{
|
||||
HPDF_BYTE* b = (HPDF_BYTE*)s;
|
||||
|
||||
while (n > 0) {
|
||||
*b = c;
|
||||
b++;
|
||||
n--;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
HPDF_UINT
|
||||
HPDF_StrLen (const char *s,
|
||||
HPDF_INT maxlen)
|
||||
{
|
||||
HPDF_INT len = 0;
|
||||
|
||||
if (!s)
|
||||
return 0;
|
||||
|
||||
while (*s != 0 && (maxlen < 0 || len < maxlen)) {
|
||||
s++;
|
||||
len++;
|
||||
}
|
||||
|
||||
return (HPDF_UINT)len;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
HPDF_StrStr (const char *s1,
|
||||
const char *s2,
|
||||
HPDF_UINT maxlen)
|
||||
{
|
||||
HPDF_UINT len = HPDF_StrLen (s2, -1);
|
||||
|
||||
if (!s1)
|
||||
return NULL;
|
||||
|
||||
if (len == 0)
|
||||
return s1;
|
||||
|
||||
if (maxlen == 0)
|
||||
maxlen = HPDF_StrLen (s1, -1);
|
||||
|
||||
if (maxlen < len)
|
||||
return NULL;
|
||||
|
||||
maxlen -= len;
|
||||
maxlen++;
|
||||
|
||||
while (maxlen > 0) {
|
||||
if (HPDF_MemCmp ((HPDF_BYTE *)s1, (HPDF_BYTE *)s2, len) == 0)
|
||||
return s1;
|
||||
|
||||
s1++;
|
||||
maxlen--;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Box
|
||||
HPDF_ToBox (HPDF_INT16 left,
|
||||
HPDF_INT16 bottom,
|
||||
HPDF_INT16 right,
|
||||
HPDF_INT16 top)
|
||||
{
|
||||
HPDF_Box box;
|
||||
|
||||
box.left = left;
|
||||
box.bottom = bottom;
|
||||
box.right = right;
|
||||
box.top = top;
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
|
||||
HPDF_Point
|
||||
HPDF_ToPoint (HPDF_INT16 x,
|
||||
HPDF_INT16 y)
|
||||
{
|
||||
HPDF_Point point;
|
||||
|
||||
point.x = x;
|
||||
point.y = y;
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
HPDF_Rect
|
||||
HPDF_ToRect (HPDF_REAL left,
|
||||
HPDF_REAL bottom,
|
||||
HPDF_REAL right,
|
||||
HPDF_REAL top)
|
||||
{
|
||||
HPDF_Rect rect;
|
||||
|
||||
rect.left = left;
|
||||
rect.bottom = bottom;
|
||||
rect.right = right;
|
||||
rect.top = top;
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_UInt16Swap (HPDF_UINT16 *value)
|
||||
{
|
||||
HPDF_BYTE u[2];
|
||||
|
||||
HPDF_MemCpy (u, (HPDF_BYTE*)value, 2);
|
||||
*value = (HPDF_UINT16)((HPDF_UINT16)u[0] << 8 | (HPDF_UINT16)u[1]);
|
||||
}
|
||||
|
||||
Vendored
+351
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
* << Haru Free PDF Library >> -- hpdf_xref.c
|
||||
*
|
||||
* URL: http://libharu.org
|
||||
*
|
||||
* Copyright (c) 1999-2006 Takeshi Kanno <takeshi_kanno@est.hi-ho.ne.jp>
|
||||
* Copyright (c) 2007-2009 Antony Dovgal <tony@daylessday.org>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies and
|
||||
* that both that copyright notice and this permission notice appear
|
||||
* in supporting documentation.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hpdf_conf.h"
|
||||
#include "hpdf_utils.h"
|
||||
#include "hpdf_objects.h"
|
||||
|
||||
static HPDF_STATUS
|
||||
WriteTrailer (HPDF_Xref xref,
|
||||
HPDF_Stream stream);
|
||||
|
||||
|
||||
HPDF_Xref
|
||||
HPDF_Xref_New (HPDF_MMgr mmgr,
|
||||
HPDF_UINT32 offset)
|
||||
{
|
||||
HPDF_Xref xref;
|
||||
HPDF_XrefEntry new_entry;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Xref_New\n"));
|
||||
|
||||
xref = (HPDF_Xref)HPDF_GetMem (mmgr, sizeof(HPDF_Xref_Rec));
|
||||
if (!xref)
|
||||
return NULL;
|
||||
|
||||
HPDF_MemSet (xref, 0, sizeof(HPDF_Xref_Rec));
|
||||
xref->mmgr = mmgr;
|
||||
xref->error = mmgr->error;
|
||||
xref->start_offset = offset;
|
||||
|
||||
xref->entries = HPDF_List_New (mmgr, HPDF_DEFALUT_XREF_ENTRY_NUM);
|
||||
if (!xref->entries)
|
||||
goto Fail;
|
||||
|
||||
xref->addr = 0;
|
||||
|
||||
if (xref->start_offset == 0) {
|
||||
new_entry = (HPDF_XrefEntry)HPDF_GetMem (mmgr,
|
||||
sizeof(HPDF_XrefEntry_Rec));
|
||||
if (!new_entry)
|
||||
goto Fail;
|
||||
|
||||
if (HPDF_List_Add (xref->entries, new_entry) != HPDF_OK) {
|
||||
HPDF_FreeMem (mmgr, new_entry);
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
/* add first entry which is free entry and whose generation
|
||||
* number is 0
|
||||
*/
|
||||
new_entry->entry_typ = HPDF_FREE_ENTRY;
|
||||
new_entry->byte_offset = 0;
|
||||
new_entry->gen_no = HPDF_MAX_GENERATION_NUM;
|
||||
new_entry->obj = NULL;
|
||||
}
|
||||
|
||||
xref->trailer = HPDF_Dict_New (mmgr);
|
||||
if (!xref->trailer)
|
||||
goto Fail;
|
||||
|
||||
return xref;
|
||||
|
||||
Fail:
|
||||
HPDF_PTRACE((" HPDF_Xref_New failed\n"));
|
||||
HPDF_Xref_Free (xref);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HPDF_Xref_Free (HPDF_Xref xref)
|
||||
{
|
||||
HPDF_UINT i;
|
||||
HPDF_XrefEntry entry;
|
||||
HPDF_Xref tmp_xref;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Xref_Free\n"));
|
||||
|
||||
/* delete xref entries. where prev element is not NULL,
|
||||
* delete all xref entries recursively.
|
||||
*/
|
||||
while (xref) {
|
||||
/* delete all objects belong to the xref. */
|
||||
|
||||
if (xref->entries) {
|
||||
for (i = 0; i < xref->entries->count; i++) {
|
||||
entry = HPDF_Xref_GetEntry (xref, i);
|
||||
if (entry->obj)
|
||||
HPDF_Obj_ForceFree (xref->mmgr, entry->obj);
|
||||
HPDF_FreeMem (xref->mmgr, entry);
|
||||
}
|
||||
|
||||
HPDF_List_Free(xref->entries);
|
||||
}
|
||||
|
||||
if (xref->trailer)
|
||||
HPDF_Dict_Free (xref->trailer);
|
||||
|
||||
tmp_xref = xref->prev;
|
||||
HPDF_FreeMem (xref->mmgr, xref);
|
||||
xref = tmp_xref;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Xref_Add (HPDF_Xref xref,
|
||||
void *obj)
|
||||
{
|
||||
HPDF_XrefEntry entry;
|
||||
HPDF_Obj_Header *header;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Xref_Add\n"));
|
||||
|
||||
if (!obj) {
|
||||
if (HPDF_Error_GetCode (xref->error) == HPDF_OK)
|
||||
return HPDF_SetError (xref->error, HPDF_INVALID_OBJECT, 0);
|
||||
else
|
||||
return HPDF_INVALID_OBJECT;
|
||||
}
|
||||
|
||||
header = (HPDF_Obj_Header *)obj;
|
||||
|
||||
if (header->obj_id & HPDF_OTYPE_DIRECT ||
|
||||
header->obj_id & HPDF_OTYPE_INDIRECT)
|
||||
return HPDF_SetError(xref->error, HPDF_INVALID_OBJECT, 0);
|
||||
|
||||
if (xref->entries->count >= HPDF_LIMIT_MAX_XREF_ELEMENT) {
|
||||
HPDF_SetError(xref->error, HPDF_XREF_COUNT_ERR, 0);
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
/* in the following, we have to dispose the object when an error is
|
||||
* occured.
|
||||
*/
|
||||
|
||||
entry = (HPDF_XrefEntry)HPDF_GetMem (xref->mmgr,
|
||||
sizeof(HPDF_XrefEntry_Rec));
|
||||
if (entry == NULL)
|
||||
goto Fail;
|
||||
|
||||
if (HPDF_List_Add(xref->entries, entry) != HPDF_OK) {
|
||||
HPDF_FreeMem (xref->mmgr, entry);
|
||||
goto Fail;
|
||||
}
|
||||
|
||||
entry->entry_typ = HPDF_IN_USE_ENTRY;
|
||||
entry->byte_offset = 0;
|
||||
entry->gen_no = 0;
|
||||
entry->obj = obj;
|
||||
header->obj_id = xref->start_offset + xref->entries->count - 1 +
|
||||
HPDF_OTYPE_INDIRECT;
|
||||
|
||||
header->gen_no = entry->gen_no;
|
||||
|
||||
return HPDF_OK;
|
||||
|
||||
Fail:
|
||||
HPDF_Obj_ForceFree(xref->mmgr, obj);
|
||||
return HPDF_Error_GetCode (xref->error);
|
||||
}
|
||||
|
||||
HPDF_XrefEntry
|
||||
HPDF_Xref_GetEntry (HPDF_Xref xref,
|
||||
HPDF_UINT index)
|
||||
{
|
||||
HPDF_PTRACE((" HPDF_Xref_GetEntry\n"));
|
||||
|
||||
return (HPDF_XrefEntry)HPDF_List_ItemAt(xref->entries, index);
|
||||
}
|
||||
|
||||
|
||||
HPDF_XrefEntry
|
||||
HPDF_Xref_GetEntryByObjectId (HPDF_Xref xref,
|
||||
HPDF_UINT obj_id)
|
||||
{
|
||||
HPDF_Xref tmp_xref = xref;
|
||||
|
||||
HPDF_PTRACE((" HPDF_Xref_GetEntryByObjectId\n"));
|
||||
|
||||
while (tmp_xref) {
|
||||
HPDF_UINT i;
|
||||
|
||||
if (tmp_xref->entries->count + tmp_xref->start_offset > obj_id) {
|
||||
HPDF_SetError (xref->error, HPDF_INVALID_OBJ_ID, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (tmp_xref->start_offset < obj_id) {
|
||||
for (i = 0; i < tmp_xref->entries->count; i++) {
|
||||
if (tmp_xref->start_offset + i == obj_id) {
|
||||
HPDF_XrefEntry entry = HPDF_Xref_GetEntry(tmp_xref, i);
|
||||
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp_xref = tmp_xref->prev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
HPDF_STATUS
|
||||
HPDF_Xref_WriteToStream (HPDF_Xref xref,
|
||||
HPDF_Stream stream,
|
||||
HPDF_Encrypt e)
|
||||
{
|
||||
HPDF_STATUS ret;
|
||||
HPDF_UINT i;
|
||||
char buf[HPDF_SHORT_BUF_SIZ];
|
||||
char* pbuf;
|
||||
char* eptr = buf + HPDF_SHORT_BUF_SIZ - 1;
|
||||
HPDF_UINT str_idx;
|
||||
HPDF_Xref tmp_xref = xref;
|
||||
|
||||
/* write each objects of xref to the specified stream */
|
||||
|
||||
HPDF_PTRACE((" HPDF_Xref_WriteToStream\n"));
|
||||
|
||||
while (tmp_xref) {
|
||||
if (tmp_xref->start_offset == 0)
|
||||
str_idx = 1;
|
||||
else
|
||||
str_idx = 0;
|
||||
|
||||
for (i = str_idx; i < tmp_xref->entries->count; i++) {
|
||||
HPDF_XrefEntry entry =
|
||||
(HPDF_XrefEntry)HPDF_List_ItemAt (tmp_xref->entries, i);
|
||||
HPDF_UINT obj_id = tmp_xref->start_offset + i;
|
||||
HPDF_UINT16 gen_no = entry->gen_no;
|
||||
|
||||
entry->byte_offset = stream->size;
|
||||
|
||||
pbuf = buf;
|
||||
pbuf = HPDF_IToA (pbuf, obj_id, eptr);
|
||||
*pbuf++ = ' ';
|
||||
pbuf = HPDF_IToA (pbuf, gen_no, eptr);
|
||||
HPDF_StrCpy(pbuf, " obj\012", eptr);
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, buf)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if (e)
|
||||
HPDF_Encrypt_InitKey (e, obj_id, gen_no);
|
||||
|
||||
if ((ret = HPDF_Obj_WriteValue (entry->obj, stream, e)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, "\012endobj\012"))
|
||||
!= HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
tmp_xref = tmp_xref->prev;
|
||||
}
|
||||
|
||||
/* start to write cross-reference table */
|
||||
|
||||
tmp_xref = xref;
|
||||
|
||||
while (tmp_xref) {
|
||||
tmp_xref->addr = stream->size;
|
||||
|
||||
pbuf = buf;
|
||||
pbuf = (char *)HPDF_StrCpy (pbuf, "xref\012", eptr);
|
||||
pbuf = HPDF_IToA (pbuf, tmp_xref->start_offset, eptr);
|
||||
*pbuf++ = ' ';
|
||||
pbuf = HPDF_IToA (pbuf, tmp_xref->entries->count, eptr);
|
||||
HPDF_StrCpy (pbuf, "\012", eptr);
|
||||
ret = HPDF_Stream_WriteStr (stream, buf);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < tmp_xref->entries->count; i++) {
|
||||
HPDF_XrefEntry entry = HPDF_Xref_GetEntry(tmp_xref, i);
|
||||
|
||||
pbuf = buf;
|
||||
pbuf = HPDF_IToA2 (pbuf, entry->byte_offset, HPDF_BYTE_OFFSET_LEN +
|
||||
1);
|
||||
*pbuf++ = ' ';
|
||||
pbuf = HPDF_IToA2 (pbuf, entry->gen_no, HPDF_GEN_NO_LEN + 1);
|
||||
*pbuf++ = ' ';
|
||||
*pbuf++ = entry->entry_typ;
|
||||
HPDF_StrCpy (pbuf, "\015\012", eptr); /* Acrobat 8.15 requires both \r and \n here */
|
||||
ret = HPDF_Stream_WriteStr (stream, buf);
|
||||
if (ret != HPDF_OK)
|
||||
return ret;
|
||||
}
|
||||
|
||||
tmp_xref = tmp_xref->prev;
|
||||
}
|
||||
|
||||
/* write trailer dictionary */
|
||||
ret = WriteTrailer (xref, stream);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static HPDF_STATUS
|
||||
WriteTrailer (HPDF_Xref xref,
|
||||
HPDF_Stream stream)
|
||||
{
|
||||
HPDF_UINT max_obj_id = xref->entries->count + xref->start_offset;
|
||||
HPDF_STATUS ret;
|
||||
|
||||
HPDF_PTRACE ((" WriteTrailer\n"));
|
||||
|
||||
if ((ret = HPDF_Dict_AddNumber (xref->trailer, "Size", max_obj_id))
|
||||
!= HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if (xref->prev)
|
||||
if ((ret = HPDF_Dict_AddNumber (xref->trailer, "Prev",
|
||||
xref->prev->addr)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, "trailer\012")) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Dict_Write (xref->trailer, stream, NULL)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, "\012startxref\012")) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteUInt (stream, xref->addr)) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
if ((ret = HPDF_Stream_WriteStr (stream, "\012%%EOF\012")) != HPDF_OK)
|
||||
return ret;
|
||||
|
||||
return HPDF_OK;
|
||||
}
|
||||
|
||||
Vendored
+623
@@ -0,0 +1,623 @@
|
||||
/* infback.c -- inflate using a call-back interface
|
||||
* Copyright (C) 1995-2005 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/*
|
||||
This code is largely copied from inflate.c. Normally either infback.o or
|
||||
inflate.o would be linked into an application--not both. The interface
|
||||
with inffast.c is retained so that optimized assembler-coded versions of
|
||||
inflate_fast() can be used with either inflate.c or infback.c.
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
/* function prototypes */
|
||||
local void fixedtables OF((struct inflate_state FAR *state));
|
||||
|
||||
/*
|
||||
strm provides memory allocation functions in zalloc and zfree, or
|
||||
Z_NULL to use the library memory allocation functions.
|
||||
|
||||
windowBits is in the range 8..15, and window is a user-supplied
|
||||
window and output buffer that is 2**windowBits bytes.
|
||||
*/
|
||||
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
|
||||
z_streamp strm;
|
||||
int windowBits;
|
||||
unsigned char FAR *window;
|
||||
const char *version;
|
||||
int stream_size;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
|
||||
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
||||
stream_size != (int)(sizeof(z_stream)))
|
||||
return Z_VERSION_ERROR;
|
||||
if (strm == Z_NULL || window == Z_NULL ||
|
||||
windowBits < 8 || windowBits > 15)
|
||||
return Z_STREAM_ERROR;
|
||||
strm->msg = Z_NULL; /* in case we return an error */
|
||||
if (strm->zalloc == (alloc_func)0) {
|
||||
strm->zalloc = zcalloc;
|
||||
strm->opaque = (voidpf)0;
|
||||
}
|
||||
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
|
||||
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
|
||||
sizeof(struct inflate_state));
|
||||
if (state == Z_NULL) return Z_MEM_ERROR;
|
||||
Tracev((stderr, "inflate: allocated\n"));
|
||||
strm->state = (struct internal_state FAR *)state;
|
||||
state->dmax = 32768U;
|
||||
state->wbits = windowBits;
|
||||
state->wsize = 1U << windowBits;
|
||||
state->window = window;
|
||||
state->write = 0;
|
||||
state->whave = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
Return state with length and distance decoding tables and index sizes set to
|
||||
fixed code decoding. Normally this returns fixed tables from inffixed.h.
|
||||
If BUILDFIXED is defined, then instead this routine builds the tables the
|
||||
first time it's called, and returns those tables the first time and
|
||||
thereafter. This reduces the size of the code by about 2K bytes, in
|
||||
exchange for a little execution time. However, BUILDFIXED should not be
|
||||
used for threaded applications, since the rewriting of the tables and virgin
|
||||
may not be thread-safe.
|
||||
*/
|
||||
local void fixedtables(state)
|
||||
struct inflate_state FAR *state;
|
||||
{
|
||||
#ifdef BUILDFIXED
|
||||
static int virgin = 1;
|
||||
static code *lenfix, *distfix;
|
||||
static code fixed[544];
|
||||
|
||||
/* build fixed huffman tables if first call (may not be thread safe) */
|
||||
if (virgin) {
|
||||
unsigned sym, bits;
|
||||
static code *next;
|
||||
|
||||
/* literal/length table */
|
||||
sym = 0;
|
||||
while (sym < 144) state->lens[sym++] = 8;
|
||||
while (sym < 256) state->lens[sym++] = 9;
|
||||
while (sym < 280) state->lens[sym++] = 7;
|
||||
while (sym < 288) state->lens[sym++] = 8;
|
||||
next = fixed;
|
||||
lenfix = next;
|
||||
bits = 9;
|
||||
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
|
||||
|
||||
/* distance table */
|
||||
sym = 0;
|
||||
while (sym < 32) state->lens[sym++] = 5;
|
||||
distfix = next;
|
||||
bits = 5;
|
||||
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
|
||||
|
||||
/* do this just once */
|
||||
virgin = 0;
|
||||
}
|
||||
#else /* !BUILDFIXED */
|
||||
# include "inffixed.h"
|
||||
#endif /* BUILDFIXED */
|
||||
state->lencode = lenfix;
|
||||
state->lenbits = 9;
|
||||
state->distcode = distfix;
|
||||
state->distbits = 5;
|
||||
}
|
||||
|
||||
/* Macros for inflateBack(): */
|
||||
|
||||
/* Load returned state from inflate_fast() */
|
||||
#define LOAD() \
|
||||
do { \
|
||||
put = strm->next_out; \
|
||||
left = strm->avail_out; \
|
||||
next = strm->next_in; \
|
||||
have = strm->avail_in; \
|
||||
hold = state->hold; \
|
||||
bits = state->bits; \
|
||||
} while (0)
|
||||
|
||||
/* Set state from registers for inflate_fast() */
|
||||
#define RESTORE() \
|
||||
do { \
|
||||
strm->next_out = put; \
|
||||
strm->avail_out = left; \
|
||||
strm->next_in = next; \
|
||||
strm->avail_in = have; \
|
||||
state->hold = hold; \
|
||||
state->bits = bits; \
|
||||
} while (0)
|
||||
|
||||
/* Clear the input bit accumulator */
|
||||
#define INITBITS() \
|
||||
do { \
|
||||
hold = 0; \
|
||||
bits = 0; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some input is available. If input is requested, but denied,
|
||||
then return a Z_BUF_ERROR from inflateBack(). */
|
||||
#define PULL() \
|
||||
do { \
|
||||
if (have == 0) { \
|
||||
have = in(in_desc, &next); \
|
||||
if (have == 0) { \
|
||||
next = Z_NULL; \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Get a byte of input into the bit accumulator, or return from inflateBack()
|
||||
with an error if there is no input available. */
|
||||
#define PULLBYTE() \
|
||||
do { \
|
||||
PULL(); \
|
||||
have--; \
|
||||
hold += (unsigned long)(*next++) << bits; \
|
||||
bits += 8; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that there are at least n bits in the bit accumulator. If there is
|
||||
not enough available input to do that, then return from inflateBack() with
|
||||
an error. */
|
||||
#define NEEDBITS(n) \
|
||||
do { \
|
||||
while (bits < (unsigned)(n)) \
|
||||
PULLBYTE(); \
|
||||
} while (0)
|
||||
|
||||
/* Return the low n bits of the bit accumulator (n < 16) */
|
||||
#define BITS(n) \
|
||||
((unsigned)hold & ((1U << (n)) - 1))
|
||||
|
||||
/* Remove n bits from the bit accumulator */
|
||||
#define DROPBITS(n) \
|
||||
do { \
|
||||
hold >>= (n); \
|
||||
bits -= (unsigned)(n); \
|
||||
} while (0)
|
||||
|
||||
/* Remove zero to seven bits as needed to go to a byte boundary */
|
||||
#define BYTEBITS() \
|
||||
do { \
|
||||
hold >>= bits & 7; \
|
||||
bits -= bits & 7; \
|
||||
} while (0)
|
||||
|
||||
/* Assure that some output space is available, by writing out the window
|
||||
if it's full. If the write fails, return from inflateBack() with a
|
||||
Z_BUF_ERROR. */
|
||||
#define ROOM() \
|
||||
do { \
|
||||
if (left == 0) { \
|
||||
put = state->window; \
|
||||
left = state->wsize; \
|
||||
state->whave = left; \
|
||||
if (out(out_desc, put, left)) { \
|
||||
ret = Z_BUF_ERROR; \
|
||||
goto inf_leave; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
strm provides the memory allocation functions and window buffer on input,
|
||||
and provides information on the unused input on return. For Z_DATA_ERROR
|
||||
returns, strm will also provide an error message.
|
||||
|
||||
in() and out() are the call-back input and output functions. When
|
||||
inflateBack() needs more input, it calls in(). When inflateBack() has
|
||||
filled the window with output, or when it completes with data in the
|
||||
window, it calls out() to write out the data. The application must not
|
||||
change the provided input until in() is called again or inflateBack()
|
||||
returns. The application must not change the window/output buffer until
|
||||
inflateBack() returns.
|
||||
|
||||
in() and out() are called with a descriptor parameter provided in the
|
||||
inflateBack() call. This parameter can be a structure that provides the
|
||||
information required to do the read or write, as well as accumulated
|
||||
information on the input and output such as totals and check values.
|
||||
|
||||
in() should return zero on failure. out() should return non-zero on
|
||||
failure. If either in() or out() fails, than inflateBack() returns a
|
||||
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
|
||||
was in() or out() that caused in the error. Otherwise, inflateBack()
|
||||
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
|
||||
error, or Z_MEM_ERROR if it could not allocate memory for the state.
|
||||
inflateBack() can also return Z_STREAM_ERROR if the input parameters
|
||||
are not correct, i.e. strm is Z_NULL or the state was not initialized.
|
||||
*/
|
||||
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
|
||||
z_streamp strm;
|
||||
in_func in;
|
||||
void FAR *in_desc;
|
||||
out_func out;
|
||||
void FAR *out_desc;
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *next; /* next input */
|
||||
unsigned char FAR *put; /* next output */
|
||||
unsigned have, left; /* available input and output */
|
||||
unsigned long hold; /* bit buffer */
|
||||
unsigned bits; /* bits in bit buffer */
|
||||
unsigned copy; /* number of stored or match bytes to copy */
|
||||
unsigned char FAR *from; /* where to copy match bytes from */
|
||||
code this; /* current decoding table entry */
|
||||
code last; /* parent table entry */
|
||||
unsigned len; /* length to copy for repeats, bits to drop */
|
||||
int ret; /* return code */
|
||||
static const unsigned short order[19] = /* permutation of code lengths */
|
||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
/* Check that the strm exists and that the state was initialized */
|
||||
if (strm == Z_NULL || strm->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
|
||||
/* Reset the state */
|
||||
strm->msg = Z_NULL;
|
||||
state->mode = TYPE;
|
||||
state->last = 0;
|
||||
state->whave = 0;
|
||||
next = strm->next_in;
|
||||
have = next != Z_NULL ? strm->avail_in : 0;
|
||||
hold = 0;
|
||||
bits = 0;
|
||||
put = state->window;
|
||||
left = state->wsize;
|
||||
|
||||
/* Inflate until end of block marked as last */
|
||||
for (;;)
|
||||
switch (state->mode) {
|
||||
case TYPE:
|
||||
/* determine and dispatch block type */
|
||||
if (state->last) {
|
||||
BYTEBITS();
|
||||
state->mode = DONE;
|
||||
break;
|
||||
}
|
||||
NEEDBITS(3);
|
||||
state->last = BITS(1);
|
||||
DROPBITS(1);
|
||||
switch (BITS(2)) {
|
||||
case 0: /* stored block */
|
||||
Tracev((stderr, "inflate: stored block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = STORED;
|
||||
break;
|
||||
case 1: /* fixed block */
|
||||
fixedtables(state);
|
||||
Tracev((stderr, "inflate: fixed codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = LEN; /* decode codes */
|
||||
break;
|
||||
case 2: /* dynamic block */
|
||||
Tracev((stderr, "inflate: dynamic codes block%s\n",
|
||||
state->last ? " (last)" : ""));
|
||||
state->mode = TABLE;
|
||||
break;
|
||||
case 3:
|
||||
strm->msg = (char *)"invalid block type";
|
||||
state->mode = BAD;
|
||||
}
|
||||
DROPBITS(2);
|
||||
break;
|
||||
|
||||
case STORED:
|
||||
/* get and verify stored block length */
|
||||
BYTEBITS(); /* go to byte boundary */
|
||||
NEEDBITS(32);
|
||||
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
|
||||
strm->msg = (char *)"invalid stored block lengths";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->length = (unsigned)hold & 0xffff;
|
||||
Tracev((stderr, "inflate: stored length %u\n",
|
||||
state->length));
|
||||
INITBITS();
|
||||
|
||||
/* copy stored block from input to output */
|
||||
while (state->length != 0) {
|
||||
copy = state->length;
|
||||
PULL();
|
||||
ROOM();
|
||||
if (copy > have) copy = have;
|
||||
if (copy > left) copy = left;
|
||||
zmemcpy(put, next, copy);
|
||||
have -= copy;
|
||||
next += copy;
|
||||
left -= copy;
|
||||
put += copy;
|
||||
state->length -= copy;
|
||||
}
|
||||
Tracev((stderr, "inflate: stored end\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
|
||||
case TABLE:
|
||||
/* get dynamic table entries descriptor */
|
||||
NEEDBITS(14);
|
||||
state->nlen = BITS(5) + 257;
|
||||
DROPBITS(5);
|
||||
state->ndist = BITS(5) + 1;
|
||||
DROPBITS(5);
|
||||
state->ncode = BITS(4) + 4;
|
||||
DROPBITS(4);
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if (state->nlen > 286 || state->ndist > 30) {
|
||||
strm->msg = (char *)"too many length or distance symbols";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
|
||||
/* get code length code lengths (not a typo) */
|
||||
state->have = 0;
|
||||
while (state->have < state->ncode) {
|
||||
NEEDBITS(3);
|
||||
state->lens[order[state->have++]] = (unsigned short)BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
while (state->have < 19)
|
||||
state->lens[order[state->have++]] = 0;
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 7;
|
||||
ret = inflate_table(CODES, state->lens, 19, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid code lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: code lengths ok\n"));
|
||||
|
||||
/* get length and distance code code lengths */
|
||||
state->have = 0;
|
||||
while (state->have < state->nlen + state->ndist) {
|
||||
for (;;) {
|
||||
this = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (this.val < 16) {
|
||||
NEEDBITS(this.bits);
|
||||
DROPBITS(this.bits);
|
||||
state->lens[state->have++] = this.val;
|
||||
}
|
||||
else {
|
||||
if (this.val == 16) {
|
||||
NEEDBITS(this.bits + 2);
|
||||
DROPBITS(this.bits);
|
||||
if (state->have == 0) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
len = (unsigned)(state->lens[state->have - 1]);
|
||||
copy = 3 + BITS(2);
|
||||
DROPBITS(2);
|
||||
}
|
||||
else if (this.val == 17) {
|
||||
NEEDBITS(this.bits + 3);
|
||||
DROPBITS(this.bits);
|
||||
len = 0;
|
||||
copy = 3 + BITS(3);
|
||||
DROPBITS(3);
|
||||
}
|
||||
else {
|
||||
NEEDBITS(this.bits + 7);
|
||||
DROPBITS(this.bits);
|
||||
len = 0;
|
||||
copy = 11 + BITS(7);
|
||||
DROPBITS(7);
|
||||
}
|
||||
if (state->have + copy > state->nlen + state->ndist) {
|
||||
strm->msg = (char *)"invalid bit length repeat";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
while (copy--)
|
||||
state->lens[state->have++] = (unsigned short)len;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle error breaks in while */
|
||||
if (state->mode == BAD) break;
|
||||
|
||||
/* build code tables */
|
||||
state->next = state->codes;
|
||||
state->lencode = (code const FAR *)(state->next);
|
||||
state->lenbits = 9;
|
||||
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
|
||||
&(state->lenbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid literal/lengths set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->distcode = (code const FAR *)(state->next);
|
||||
state->distbits = 6;
|
||||
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
|
||||
&(state->next), &(state->distbits), state->work);
|
||||
if (ret) {
|
||||
strm->msg = (char *)"invalid distances set";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracev((stderr, "inflate: codes ok\n"));
|
||||
state->mode = LEN;
|
||||
|
||||
case LEN:
|
||||
/* use inflate_fast() if we have enough input and output */
|
||||
if (have >= 6 && left >= 258) {
|
||||
RESTORE();
|
||||
if (state->whave < state->wsize)
|
||||
state->whave = state->wsize - left;
|
||||
inflate_fast(strm, state->wsize);
|
||||
LOAD();
|
||||
break;
|
||||
}
|
||||
|
||||
/* get a literal, length, or end-of-block code */
|
||||
for (;;) {
|
||||
this = state->lencode[BITS(state->lenbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if (this.op && (this.op & 0xf0) == 0) {
|
||||
last = this;
|
||||
for (;;) {
|
||||
this = state->lencode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(this.bits);
|
||||
state->length = (unsigned)this.val;
|
||||
|
||||
/* process literal */
|
||||
if (this.op == 0) {
|
||||
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", this.val));
|
||||
ROOM();
|
||||
*put++ = (unsigned char)(state->length);
|
||||
left--;
|
||||
state->mode = LEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* process end of block */
|
||||
if (this.op & 32) {
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* invalid code */
|
||||
if (this.op & 64) {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* length code -- get extra bits, if any */
|
||||
state->extra = (unsigned)(this.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->length += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", state->length));
|
||||
|
||||
/* get distance code */
|
||||
for (;;) {
|
||||
this = state->distcode[BITS(state->distbits)];
|
||||
if ((unsigned)(this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
if ((this.op & 0xf0) == 0) {
|
||||
last = this;
|
||||
for (;;) {
|
||||
this = state->distcode[last.val +
|
||||
(BITS(last.bits + last.op) >> last.bits)];
|
||||
if ((unsigned)(last.bits + this.bits) <= bits) break;
|
||||
PULLBYTE();
|
||||
}
|
||||
DROPBITS(last.bits);
|
||||
}
|
||||
DROPBITS(this.bits);
|
||||
if (this.op & 64) {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
state->offset = (unsigned)this.val;
|
||||
|
||||
/* get distance extra bits, if any */
|
||||
state->extra = (unsigned)(this.op) & 15;
|
||||
if (state->extra != 0) {
|
||||
NEEDBITS(state->extra);
|
||||
state->offset += BITS(state->extra);
|
||||
DROPBITS(state->extra);
|
||||
}
|
||||
if (state->offset > state->wsize - (state->whave < state->wsize ?
|
||||
left : 0)) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
Tracevv((stderr, "inflate: distance %u\n", state->offset));
|
||||
|
||||
/* copy match from window to output */
|
||||
do {
|
||||
ROOM();
|
||||
copy = state->wsize - state->offset;
|
||||
if (copy < left) {
|
||||
from = put + copy;
|
||||
copy = left - copy;
|
||||
}
|
||||
else {
|
||||
from = put - state->offset;
|
||||
copy = left;
|
||||
}
|
||||
if (copy > state->length) copy = state->length;
|
||||
state->length -= copy;
|
||||
left -= copy;
|
||||
do {
|
||||
*put++ = *from++;
|
||||
} while (--copy);
|
||||
} while (state->length != 0);
|
||||
break;
|
||||
|
||||
case DONE:
|
||||
/* inflate stream terminated properly -- write leftover output */
|
||||
ret = Z_STREAM_END;
|
||||
if (left < state->wsize) {
|
||||
if (out(out_desc, state->window, state->wsize - left))
|
||||
ret = Z_BUF_ERROR;
|
||||
}
|
||||
goto inf_leave;
|
||||
|
||||
case BAD:
|
||||
ret = Z_DATA_ERROR;
|
||||
goto inf_leave;
|
||||
|
||||
default: /* can't happen, but makes compilers happy */
|
||||
ret = Z_STREAM_ERROR;
|
||||
goto inf_leave;
|
||||
}
|
||||
|
||||
/* Return unused input */
|
||||
inf_leave:
|
||||
strm->next_in = next;
|
||||
strm->avail_in = have;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ZEXPORT inflateBackEnd(strm)
|
||||
z_streamp strm;
|
||||
{
|
||||
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
|
||||
return Z_STREAM_ERROR;
|
||||
ZFREE(strm, strm->state);
|
||||
strm->state = Z_NULL;
|
||||
Tracev((stderr, "inflate: end\n"));
|
||||
return Z_OK;
|
||||
}
|
||||
Vendored
+318
@@ -0,0 +1,318 @@
|
||||
/* inffast.c -- fast decoding
|
||||
* Copyright (C) 1995-2004 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "inflate.h"
|
||||
#include "inffast.h"
|
||||
|
||||
#ifndef ASMINF
|
||||
|
||||
/* Allow machine dependent optimization for post-increment or pre-increment.
|
||||
Based on testing to date,
|
||||
Pre-increment preferred for:
|
||||
- PowerPC G3 (Adler)
|
||||
- MIPS R5000 (Randers-Pehrson)
|
||||
Post-increment preferred for:
|
||||
- none
|
||||
No measurable difference:
|
||||
- Pentium III (Anderson)
|
||||
- M68060 (Nikl)
|
||||
*/
|
||||
#ifdef POSTINC
|
||||
# define OFF 0
|
||||
# define PUP(a) *(a)++
|
||||
#else
|
||||
# define OFF 1
|
||||
# define PUP(a) *++(a)
|
||||
#endif
|
||||
|
||||
/*
|
||||
Decode literal, length, and distance codes and write out the resulting
|
||||
literal and match bytes until either not enough input or output is
|
||||
available, an end-of-block is encountered, or a data error is encountered.
|
||||
When large enough input and output buffers are supplied to inflate(), for
|
||||
example, a 16K input buffer and a 64K output buffer, more than 95% of the
|
||||
inflate execution time is spent in this routine.
|
||||
|
||||
Entry assumptions:
|
||||
|
||||
state->mode == LEN
|
||||
strm->avail_in >= 6
|
||||
strm->avail_out >= 258
|
||||
start >= strm->avail_out
|
||||
state->bits < 8
|
||||
|
||||
On return, state->mode is one of:
|
||||
|
||||
LEN -- ran out of enough output space or enough available input
|
||||
TYPE -- reached end of block code, inflate() to interpret next block
|
||||
BAD -- error in block data
|
||||
|
||||
Notes:
|
||||
|
||||
- The maximum input bits used by a length/distance pair is 15 bits for the
|
||||
length code, 5 bits for the length extra, 15 bits for the distance code,
|
||||
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
|
||||
Therefore if strm->avail_in >= 6, then there is enough input to avoid
|
||||
checking for available input while decoding.
|
||||
|
||||
- The maximum bytes that a single length/distance pair can output is 258
|
||||
bytes, which is the maximum length that can be coded. inflate_fast()
|
||||
requires strm->avail_out >= 258 for each loop to avoid checking for
|
||||
output space.
|
||||
*/
|
||||
void inflate_fast(strm, start)
|
||||
z_streamp strm;
|
||||
unsigned start; /* inflate()'s starting value for strm->avail_out */
|
||||
{
|
||||
struct inflate_state FAR *state;
|
||||
unsigned char FAR *in; /* local strm->next_in */
|
||||
unsigned char FAR *last; /* while in < last, enough input available */
|
||||
unsigned char FAR *out; /* local strm->next_out */
|
||||
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
|
||||
unsigned char FAR *end; /* while out < end, enough space available */
|
||||
#ifdef INFLATE_STRICT
|
||||
unsigned dmax; /* maximum distance from zlib header */
|
||||
#endif
|
||||
unsigned wsize; /* window size or zero if not using window */
|
||||
unsigned whave; /* valid bytes in the window */
|
||||
unsigned write; /* window write index */
|
||||
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
|
||||
unsigned long hold; /* local strm->hold */
|
||||
unsigned bits; /* local strm->bits */
|
||||
code const FAR *lcode; /* local strm->lencode */
|
||||
code const FAR *dcode; /* local strm->distcode */
|
||||
unsigned lmask; /* mask for first level of length codes */
|
||||
unsigned dmask; /* mask for first level of distance codes */
|
||||
code this; /* retrieved table entry */
|
||||
unsigned op; /* code bits, operation, extra bits, or */
|
||||
/* window position, window bytes to copy */
|
||||
unsigned len; /* match length, unused bytes */
|
||||
unsigned dist; /* match distance */
|
||||
unsigned char FAR *from; /* where to copy match from */
|
||||
|
||||
/* copy state to local variables */
|
||||
state = (struct inflate_state FAR *)strm->state;
|
||||
in = strm->next_in - OFF;
|
||||
last = in + (strm->avail_in - 5);
|
||||
out = strm->next_out - OFF;
|
||||
beg = out - (start - strm->avail_out);
|
||||
end = out + (strm->avail_out - 257);
|
||||
#ifdef INFLATE_STRICT
|
||||
dmax = state->dmax;
|
||||
#endif
|
||||
wsize = state->wsize;
|
||||
whave = state->whave;
|
||||
write = state->write;
|
||||
window = state->window;
|
||||
hold = state->hold;
|
||||
bits = state->bits;
|
||||
lcode = state->lencode;
|
||||
dcode = state->distcode;
|
||||
lmask = (1U << state->lenbits) - 1;
|
||||
dmask = (1U << state->distbits) - 1;
|
||||
|
||||
/* decode literals and length/distances until end-of-block or not enough
|
||||
input data or output space */
|
||||
do {
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
this = lcode[hold & lmask];
|
||||
dolen:
|
||||
op = (unsigned)(this.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(this.op);
|
||||
if (op == 0) { /* literal */
|
||||
Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", this.val));
|
||||
PUP(out) = (unsigned char)(this.val);
|
||||
}
|
||||
else if (op & 16) { /* length base */
|
||||
len = (unsigned)(this.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (op) {
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
len += (unsigned)hold & ((1U << op) - 1);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
}
|
||||
Tracevv((stderr, "inflate: length %u\n", len));
|
||||
if (bits < 15) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
this = dcode[hold & dmask];
|
||||
dodist:
|
||||
op = (unsigned)(this.bits);
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
op = (unsigned)(this.op);
|
||||
if (op & 16) { /* distance base */
|
||||
dist = (unsigned)(this.val);
|
||||
op &= 15; /* number of extra bits */
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
if (bits < op) {
|
||||
hold += (unsigned long)(PUP(in)) << bits;
|
||||
bits += 8;
|
||||
}
|
||||
}
|
||||
dist += (unsigned)hold & ((1U << op) - 1);
|
||||
#ifdef INFLATE_STRICT
|
||||
if (dist > dmax) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
hold >>= op;
|
||||
bits -= op;
|
||||
Tracevv((stderr, "inflate: distance %u\n", dist));
|
||||
op = (unsigned)(out - beg); /* max distance in output */
|
||||
if (dist > op) { /* see if copy from window */
|
||||
op = dist - op; /* distance back in window */
|
||||
if (op > whave) {
|
||||
strm->msg = (char *)"invalid distance too far back";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
from = window - OFF;
|
||||
if (write == 0) { /* very common case */
|
||||
from += wsize - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
else if (write < op) { /* wrap around window */
|
||||
from += wsize + write - op;
|
||||
op -= write;
|
||||
if (op < len) { /* some from end of window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = window - OFF;
|
||||
if (write < len) { /* some from start of window */
|
||||
op = write;
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* contiguous in window */
|
||||
from += write - op;
|
||||
if (op < len) { /* some from window */
|
||||
len -= op;
|
||||
do {
|
||||
PUP(out) = PUP(from);
|
||||
} while (--op);
|
||||
from = out - dist; /* rest from output */
|
||||
}
|
||||
}
|
||||
while (len > 2) {
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
len -= 3;
|
||||
}
|
||||
if (len) {
|
||||
PUP(out) = PUP(from);
|
||||
if (len > 1)
|
||||
PUP(out) = PUP(from);
|
||||
}
|
||||
}
|
||||
else {
|
||||
from = out - dist; /* copy direct from output */
|
||||
do { /* minimum length is three */
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
PUP(out) = PUP(from);
|
||||
len -= 3;
|
||||
} while (len > 2);
|
||||
if (len) {
|
||||
PUP(out) = PUP(from);
|
||||
if (len > 1)
|
||||
PUP(out) = PUP(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level distance code */
|
||||
this = dcode[this.val + (hold & ((1U << op) - 1))];
|
||||
goto dodist;
|
||||
}
|
||||
else {
|
||||
strm->msg = (char *)"invalid distance code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((op & 64) == 0) { /* 2nd level length code */
|
||||
this = lcode[this.val + (hold & ((1U << op) - 1))];
|
||||
goto dolen;
|
||||
}
|
||||
else if (op & 32) { /* end-of-block */
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
state->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
strm->msg = (char *)"invalid literal/length code";
|
||||
state->mode = BAD;
|
||||
break;
|
||||
}
|
||||
} while (in < last && out < end);
|
||||
|
||||
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
|
||||
len = bits >> 3;
|
||||
in -= len;
|
||||
bits -= len << 3;
|
||||
hold &= (1U << bits) - 1;
|
||||
|
||||
/* update state and return */
|
||||
strm->next_in = in + OFF;
|
||||
strm->next_out = out + OFF;
|
||||
strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
|
||||
strm->avail_out = (unsigned)(out < end ?
|
||||
257 + (end - out) : 257 - (out - end));
|
||||
state->hold = hold;
|
||||
state->bits = bits;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
|
||||
- Using bit fields for code structure
|
||||
- Different op definition to avoid & for extra bits (do & for table bits)
|
||||
- Three separate decoding do-loops for direct, window, and write == 0
|
||||
- Special case for distance > 1 copies to do overlapped load and store copy
|
||||
- Explicit branch predictions (based on measured branch probabilities)
|
||||
- Deferring match copy and interspersed it with decoding subsequent codes
|
||||
- Swapping literal/length else
|
||||
- Swapping window/direct else
|
||||
- Larger unrolled copy loops (three is about right)
|
||||
- Moving len -= 3 statement into middle of loop
|
||||
*/
|
||||
|
||||
#endif /* !ASMINF */
|
||||
Vendored
+1368
File diff suppressed because it is too large
Load Diff
Vendored
+329
@@ -0,0 +1,329 @@
|
||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-2005 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
|
||||
#define MAXBITS 15
|
||||
|
||||
const char inflate_copyright[] =
|
||||
" inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
include such an acknowledgment, I would appreciate that you keep this
|
||||
copyright string in the executable of your product.
|
||||
*/
|
||||
|
||||
/*
|
||||
Build a set of tables to decode the provided canonical Huffman code.
|
||||
The code lengths are lens[0..codes-1]. The result starts at *table,
|
||||
whose indices are 0..2^bits-1. work is a writable array of at least
|
||||
lens shorts, which is used as a work area. type is the type of code
|
||||
to be generated, CODES, LENS, or DISTS. On return, zero is success,
|
||||
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
|
||||
on return points to the next available entry's address. bits is the
|
||||
requested root table index bits, and on return it is the actual root
|
||||
table index bits. It will differ if the request is greater than the
|
||||
longest code or if it is less than the shortest code.
|
||||
*/
|
||||
int inflate_table(type, lens, codes, table, bits, work)
|
||||
codetype type;
|
||||
unsigned short FAR *lens;
|
||||
unsigned codes;
|
||||
code FAR * FAR *table;
|
||||
unsigned FAR *bits;
|
||||
unsigned short FAR *work;
|
||||
{
|
||||
unsigned len; /* a code's length in bits */
|
||||
unsigned sym; /* index of code symbols */
|
||||
unsigned min, max; /* minimum and maximum code lengths */
|
||||
unsigned root; /* number of index bits for root table */
|
||||
unsigned curr; /* number of index bits for current table */
|
||||
unsigned drop; /* code bits to drop for sub-table */
|
||||
int left; /* number of prefix codes available */
|
||||
unsigned used; /* code entries in table used */
|
||||
unsigned huff; /* Huffman code */
|
||||
unsigned incr; /* for incrementing code, index */
|
||||
unsigned fill; /* index for replicating entries */
|
||||
unsigned low; /* low bits for current root entry */
|
||||
unsigned mask; /* mask for low root bits */
|
||||
code this; /* table entry for duplication */
|
||||
code FAR *next; /* next available space in table */
|
||||
const unsigned short FAR *base; /* base value table to use */
|
||||
const unsigned short FAR *extra; /* extra bits table to use */
|
||||
int end; /* use base and extra for symbol > end */
|
||||
unsigned short count[MAXBITS+1]; /* number of codes of each length */
|
||||
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
|
||||
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
|
||||
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
|
||||
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577, 0, 0};
|
||||
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
|
||||
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
|
||||
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
|
||||
28, 28, 29, 29, 64, 64};
|
||||
|
||||
/*
|
||||
Process a set of code lengths to create a canonical Huffman code. The
|
||||
code lengths are lens[0..codes-1]. Each length corresponds to the
|
||||
symbols 0..codes-1. The Huffman code is generated by first sorting the
|
||||
symbols by length from short to long, and retaining the symbol order
|
||||
for codes with equal lengths. Then the code starts with all zero bits
|
||||
for the first code of the shortest length, and the codes are integer
|
||||
increments for the same length, and zeros are appended as the length
|
||||
increases. For the deflate format, these bits are stored backwards
|
||||
from their more natural integer increment ordering, and so when the
|
||||
decoding tables are built in the large loop below, the integer codes
|
||||
are incremented backwards.
|
||||
|
||||
This routine assumes, but does not check, that all of the entries in
|
||||
lens[] are in the range 0..MAXBITS. The caller must assure this.
|
||||
1..MAXBITS is interpreted as that code length. zero means that that
|
||||
symbol does not occur in this code.
|
||||
|
||||
The codes are sorted by computing a count of codes for each length,
|
||||
creating from that a table of starting indices for each length in the
|
||||
sorted table, and then entering the symbols in order in the sorted
|
||||
table. The sorted table is work[], with that space being provided by
|
||||
the caller.
|
||||
|
||||
The length counts are used for other purposes as well, i.e. finding
|
||||
the minimum and maximum length codes, determining if there are any
|
||||
codes at all, checking for a valid set of lengths, and looking ahead
|
||||
at length counts to determine sub-table sizes when building the
|
||||
decoding tables.
|
||||
*/
|
||||
|
||||
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
|
||||
for (len = 0; len <= MAXBITS; len++)
|
||||
count[len] = 0;
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
count[lens[sym]]++;
|
||||
|
||||
/* bound code lengths, force root to be within code lengths */
|
||||
root = *bits;
|
||||
for (max = MAXBITS; max >= 1; max--)
|
||||
if (count[max] != 0) break;
|
||||
if (root > max) root = max;
|
||||
if (max == 0) { /* no symbols to code at all */
|
||||
this.op = (unsigned char)64; /* invalid code marker */
|
||||
this.bits = (unsigned char)1;
|
||||
this.val = (unsigned short)0;
|
||||
*(*table)++ = this; /* make a table to force an error */
|
||||
*(*table)++ = this;
|
||||
*bits = 1;
|
||||
return 0; /* no symbols, but wait for decoding to report error */
|
||||
}
|
||||
for (min = 1; min <= MAXBITS; min++)
|
||||
if (count[min] != 0) break;
|
||||
if (root < min) root = min;
|
||||
|
||||
/* check for an over-subscribed or incomplete set of lengths */
|
||||
left = 1;
|
||||
for (len = 1; len <= MAXBITS; len++) {
|
||||
left <<= 1;
|
||||
left -= count[len];
|
||||
if (left < 0) return -1; /* over-subscribed */
|
||||
}
|
||||
if (left > 0 && (type == CODES || max != 1))
|
||||
return -1; /* incomplete set */
|
||||
|
||||
/* generate offsets into symbol table for each length for sorting */
|
||||
offs[1] = 0;
|
||||
for (len = 1; len < MAXBITS; len++)
|
||||
offs[len + 1] = offs[len] + count[len];
|
||||
|
||||
/* sort symbols by length, by symbol order within each length */
|
||||
for (sym = 0; sym < codes; sym++)
|
||||
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
|
||||
|
||||
/*
|
||||
Create and fill in decoding tables. In this loop, the table being
|
||||
filled is at next and has curr index bits. The code being used is huff
|
||||
with length len. That code is converted to an index by dropping drop
|
||||
bits off of the bottom. For codes where len is less than drop + curr,
|
||||
those top drop + curr - len bits are incremented through all values to
|
||||
fill the table with replicated entries.
|
||||
|
||||
root is the number of index bits for the root table. When len exceeds
|
||||
root, sub-tables are created pointed to by the root entry with an index
|
||||
of the low root bits of huff. This is saved in low to check for when a
|
||||
new sub-table should be started. drop is zero when the root table is
|
||||
being filled, and drop is root when sub-tables are being filled.
|
||||
|
||||
When a new sub-table is needed, it is necessary to look ahead in the
|
||||
code lengths to determine what size sub-table is needed. The length
|
||||
counts are used for this, and so count[] is decremented as codes are
|
||||
entered in the tables.
|
||||
|
||||
used keeps track of how many table entries have been allocated from the
|
||||
provided *table space. It is checked when a LENS table is being made
|
||||
against the space in *table, ENOUGH, minus the maximum space needed by
|
||||
the worst case distance code, MAXD. This should never happen, but the
|
||||
sufficiency of ENOUGH has not been proven exhaustively, hence the check.
|
||||
This assumes that when type == LENS, bits == 9.
|
||||
|
||||
sym increments through all symbols, and the loop terminates when
|
||||
all codes of length max, i.e. all codes, have been processed. This
|
||||
routine permits incomplete codes, so another loop after this one fills
|
||||
in the rest of the decoding tables with invalid code markers.
|
||||
*/
|
||||
|
||||
/* set up for code type */
|
||||
switch (type) {
|
||||
case CODES:
|
||||
base = extra = work; /* dummy value--not used */
|
||||
end = 19;
|
||||
break;
|
||||
case LENS:
|
||||
base = lbase;
|
||||
base -= 257;
|
||||
extra = lext;
|
||||
extra -= 257;
|
||||
end = 256;
|
||||
break;
|
||||
default: /* DISTS */
|
||||
base = dbase;
|
||||
extra = dext;
|
||||
end = -1;
|
||||
}
|
||||
|
||||
/* initialize state for loop */
|
||||
huff = 0; /* starting code */
|
||||
sym = 0; /* starting code symbol */
|
||||
len = min; /* starting code length */
|
||||
next = *table; /* current table to fill in */
|
||||
curr = root; /* current table index bits */
|
||||
drop = 0; /* current bits to drop from code for index */
|
||||
low = (unsigned)(-1); /* trigger new sub-table when len > root */
|
||||
used = 1U << root; /* use root table entries */
|
||||
mask = used - 1; /* mask for comparing low */
|
||||
|
||||
/* check available table space */
|
||||
if (type == LENS && used >= ENOUGH - MAXD)
|
||||
return 1;
|
||||
|
||||
/* process all codes and make table entries */
|
||||
for (;;) {
|
||||
/* create table entry */
|
||||
this.bits = (unsigned char)(len - drop);
|
||||
if ((int)(work[sym]) < end) {
|
||||
this.op = (unsigned char)0;
|
||||
this.val = work[sym];
|
||||
}
|
||||
else if ((int)(work[sym]) > end) {
|
||||
this.op = (unsigned char)(extra[work[sym]]);
|
||||
this.val = base[work[sym]];
|
||||
}
|
||||
else {
|
||||
this.op = (unsigned char)(32 + 64); /* end of block */
|
||||
this.val = 0;
|
||||
}
|
||||
|
||||
/* replicate for those indices with low len bits equal to huff */
|
||||
incr = 1U << (len - drop);
|
||||
fill = 1U << curr;
|
||||
min = fill; /* save offset to next table */
|
||||
do {
|
||||
fill -= incr;
|
||||
next[(huff >> drop) + fill] = this;
|
||||
} while (fill != 0);
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
|
||||
/* go to next symbol, update count, len */
|
||||
sym++;
|
||||
if (--(count[len]) == 0) {
|
||||
if (len == max) break;
|
||||
len = lens[work[sym]];
|
||||
}
|
||||
|
||||
/* create new sub-table if needed */
|
||||
if (len > root && (huff & mask) != low) {
|
||||
/* if first time, transition to sub-tables */
|
||||
if (drop == 0)
|
||||
drop = root;
|
||||
|
||||
/* increment past last table */
|
||||
next += min; /* here min is 1 << curr */
|
||||
|
||||
/* determine length of next table */
|
||||
curr = len - drop;
|
||||
left = (int)(1 << curr);
|
||||
while (curr + drop < max) {
|
||||
left -= count[curr + drop];
|
||||
if (left <= 0) break;
|
||||
curr++;
|
||||
left <<= 1;
|
||||
}
|
||||
|
||||
/* check for enough space */
|
||||
used += 1U << curr;
|
||||
if (type == LENS && used >= ENOUGH - MAXD)
|
||||
return 1;
|
||||
|
||||
/* point entry in root table to sub-table */
|
||||
low = huff & mask;
|
||||
(*table)[low].op = (unsigned char)curr;
|
||||
(*table)[low].bits = (unsigned char)root;
|
||||
(*table)[low].val = (unsigned short)(next - *table);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fill in rest of table for incomplete codes. This loop is similar to the
|
||||
loop above in incrementing huff for table indices. It is assumed that
|
||||
len is equal to curr + drop, so there is no loop needed to increment
|
||||
through high index bits. When the current sub-table is filled, the loop
|
||||
drops back to the root table to fill in any remaining entries there.
|
||||
*/
|
||||
this.op = (unsigned char)64; /* invalid code marker */
|
||||
this.bits = (unsigned char)(len - drop);
|
||||
this.val = (unsigned short)0;
|
||||
while (huff != 0) {
|
||||
/* when done with sub-table, drop back to root table */
|
||||
if (drop != 0 && (huff & mask) != low) {
|
||||
drop = 0;
|
||||
len = root;
|
||||
next = *table;
|
||||
this.bits = (unsigned char)len;
|
||||
}
|
||||
|
||||
/* put invalid code marker in table */
|
||||
next[huff >> drop] = this;
|
||||
|
||||
/* backwards increment the len-bit code huff */
|
||||
incr = 1U << (len - 1);
|
||||
while (huff & incr)
|
||||
incr >>= 1;
|
||||
if (incr != 0) {
|
||||
huff &= incr - 1;
|
||||
huff += incr;
|
||||
}
|
||||
else
|
||||
huff = 0;
|
||||
}
|
||||
|
||||
/* set return parameters */
|
||||
*table += used;
|
||||
*bits = root;
|
||||
return 0;
|
||||
}
|
||||
Vendored
+798
@@ -0,0 +1,798 @@
|
||||
|
||||
/* png.c - location for general purpose libpng functions
|
||||
*
|
||||
* Last changed in libpng 1.2.21 October 4, 2007
|
||||
* For conditions of distribution and use, see copyright notice in png.h
|
||||
* Copyright (c) 1998-2007 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#define PNG_NO_EXTERN
|
||||
#include "png.h"
|
||||
|
||||
/* Generate a compiler error if there is an old png.h in the search path. */
|
||||
typedef version_1_2_24 Your_png_h_is_not_version_1_2_24;
|
||||
|
||||
/* Version information for C files. This had better match the version
|
||||
* string defined in png.h. */
|
||||
|
||||
#ifdef PNG_USE_GLOBAL_ARRAYS
|
||||
/* png_libpng_ver was changed to a function in version 1.0.5c */
|
||||
PNG_CONST char png_libpng_ver[18] = PNG_LIBPNG_VER_STRING;
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* png_sig was changed to a function in version 1.0.5c */
|
||||
/* Place to hold the signature string for a PNG file. */
|
||||
PNG_CONST png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
|
||||
#endif /* PNG_READ_SUPPORTED */
|
||||
|
||||
/* Invoke global declarations for constant strings for known chunk types */
|
||||
PNG_IHDR;
|
||||
PNG_IDAT;
|
||||
PNG_IEND;
|
||||
PNG_PLTE;
|
||||
PNG_bKGD;
|
||||
PNG_cHRM;
|
||||
PNG_gAMA;
|
||||
PNG_hIST;
|
||||
PNG_iCCP;
|
||||
PNG_iTXt;
|
||||
PNG_oFFs;
|
||||
PNG_pCAL;
|
||||
PNG_sCAL;
|
||||
PNG_pHYs;
|
||||
PNG_sBIT;
|
||||
PNG_sPLT;
|
||||
PNG_sRGB;
|
||||
PNG_tEXt;
|
||||
PNG_tIME;
|
||||
PNG_tRNS;
|
||||
PNG_zTXt;
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
|
||||
|
||||
/* start of interlace block */
|
||||
PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
|
||||
|
||||
/* offset to next interlace block */
|
||||
PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
|
||||
|
||||
/* start of interlace block in the y direction */
|
||||
PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
|
||||
|
||||
/* offset to next interlace block in the y direction */
|
||||
PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
|
||||
|
||||
/* Height of interlace block. This is not currently used - if you need
|
||||
* it, uncomment it here and in png.h
|
||||
PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
|
||||
*/
|
||||
|
||||
/* Mask to determine which pixels are valid in a pass */
|
||||
PNG_CONST int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
|
||||
|
||||
/* Mask to determine which pixels to overwrite while displaying */
|
||||
PNG_CONST int FARDATA png_pass_dsp_mask[]
|
||||
= {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
|
||||
|
||||
#endif /* PNG_READ_SUPPORTED */
|
||||
#endif /* PNG_USE_GLOBAL_ARRAYS */
|
||||
|
||||
/* Tells libpng that we have already handled the first "num_bytes" bytes
|
||||
* of the PNG file signature. If the PNG data is embedded into another
|
||||
* stream we can set num_bytes = 8 so that libpng will not attempt to read
|
||||
* or write any of the magic bytes before it starts on the IHDR.
|
||||
*/
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
void PNGAPI
|
||||
png_set_sig_bytes(png_structp png_ptr, int num_bytes)
|
||||
{
|
||||
if(png_ptr == NULL) return;
|
||||
png_debug(1, "in png_set_sig_bytes\n");
|
||||
if (num_bytes > 8)
|
||||
png_error(png_ptr, "Too many bytes for PNG signature.");
|
||||
|
||||
png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
|
||||
}
|
||||
|
||||
/* Checks whether the supplied bytes match the PNG signature. We allow
|
||||
* checking less than the full 8-byte signature so that those apps that
|
||||
* already read the first few bytes of a file to determine the file type
|
||||
* can simply check the remaining bytes for extra assurance. Returns
|
||||
* an integer less than, equal to, or greater than zero if sig is found,
|
||||
* respectively, to be less than, to match, or be greater than the correct
|
||||
* PNG signature (this is the same behaviour as strcmp, memcmp, etc).
|
||||
*/
|
||||
int PNGAPI
|
||||
png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check)
|
||||
{
|
||||
png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
|
||||
if (num_to_check > 8)
|
||||
num_to_check = 8;
|
||||
else if (num_to_check < 1)
|
||||
return (-1);
|
||||
|
||||
if (start > 7)
|
||||
return (-1);
|
||||
|
||||
if (start + num_to_check > 8)
|
||||
num_to_check = 8 - start;
|
||||
|
||||
return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check)));
|
||||
}
|
||||
|
||||
#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
|
||||
/* (Obsolete) function to check signature bytes. It does not allow one
|
||||
* to check a partial signature. This function might be removed in the
|
||||
* future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG.
|
||||
*/
|
||||
int PNGAPI
|
||||
png_check_sig(png_bytep sig, int num)
|
||||
{
|
||||
return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num));
|
||||
}
|
||||
#endif
|
||||
#endif /* PNG_READ_SUPPORTED */
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
/* Function to allocate memory for zlib and clear it to 0. */
|
||||
#ifdef PNG_1_0_X
|
||||
voidpf PNGAPI
|
||||
#else
|
||||
voidpf /* private */
|
||||
#endif
|
||||
png_zalloc(voidpf png_ptr, uInt items, uInt size)
|
||||
{
|
||||
png_voidp ptr;
|
||||
png_structp p=(png_structp)png_ptr;
|
||||
png_uint_32 save_flags=p->flags;
|
||||
png_uint_32 num_bytes;
|
||||
|
||||
if(png_ptr == NULL) return (NULL);
|
||||
if (items > PNG_UINT_32_MAX/size)
|
||||
{
|
||||
png_warning (p, "Potential overflow in png_zalloc()");
|
||||
return (NULL);
|
||||
}
|
||||
num_bytes = (png_uint_32)items * size;
|
||||
|
||||
p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
|
||||
ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
|
||||
p->flags=save_flags;
|
||||
|
||||
#if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO)
|
||||
if (ptr == NULL)
|
||||
return ((voidpf)ptr);
|
||||
|
||||
if (num_bytes > (png_uint_32)0x8000L)
|
||||
{
|
||||
png_memset(ptr, 0, (png_size_t)0x8000L);
|
||||
png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0,
|
||||
(png_size_t)(num_bytes - (png_uint_32)0x8000L));
|
||||
}
|
||||
else
|
||||
{
|
||||
png_memset(ptr, 0, (png_size_t)num_bytes);
|
||||
}
|
||||
#endif
|
||||
return ((voidpf)ptr);
|
||||
}
|
||||
|
||||
/* function to free memory for zlib */
|
||||
#ifdef PNG_1_0_X
|
||||
void PNGAPI
|
||||
#else
|
||||
void /* private */
|
||||
#endif
|
||||
png_zfree(voidpf png_ptr, voidpf ptr)
|
||||
{
|
||||
png_free((png_structp)png_ptr, (png_voidp)ptr);
|
||||
}
|
||||
|
||||
/* Reset the CRC variable to 32 bits of 1's. Care must be taken
|
||||
* in case CRC is > 32 bits to leave the top bits 0.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_reset_crc(png_structp png_ptr)
|
||||
{
|
||||
png_ptr->crc = crc32(0, Z_NULL, 0);
|
||||
}
|
||||
|
||||
/* Calculate the CRC over a section of data. We can only pass as
|
||||
* much data to this routine as the largest single buffer size. We
|
||||
* also check that this data will actually be used before going to the
|
||||
* trouble of calculating it.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length)
|
||||
{
|
||||
int need_crc = 1;
|
||||
|
||||
if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
|
||||
{
|
||||
if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
|
||||
(PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
|
||||
need_crc = 0;
|
||||
}
|
||||
else /* critical */
|
||||
{
|
||||
if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
|
||||
need_crc = 0;
|
||||
}
|
||||
|
||||
if (need_crc)
|
||||
png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length);
|
||||
}
|
||||
|
||||
/* Allocate the memory for an info_struct for the application. We don't
|
||||
* really need the png_ptr, but it could potentially be useful in the
|
||||
* future. This should be used in favour of malloc(png_sizeof(png_info))
|
||||
* and png_info_init() so that applications that want to use a shared
|
||||
* libpng don't have to be recompiled if png_info changes size.
|
||||
*/
|
||||
png_infop PNGAPI
|
||||
png_create_info_struct(png_structp png_ptr)
|
||||
{
|
||||
png_infop info_ptr;
|
||||
|
||||
png_debug(1, "in png_create_info_struct\n");
|
||||
if(png_ptr == NULL) return (NULL);
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
|
||||
png_ptr->malloc_fn, png_ptr->mem_ptr);
|
||||
#else
|
||||
info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
|
||||
#endif
|
||||
if (info_ptr != NULL)
|
||||
png_info_init_3(&info_ptr, png_sizeof(png_info));
|
||||
|
||||
return (info_ptr);
|
||||
}
|
||||
|
||||
/* This function frees the memory associated with a single info struct.
|
||||
* Normally, one would use either png_destroy_read_struct() or
|
||||
* png_destroy_write_struct() to free an info struct, but this may be
|
||||
* useful for some applications.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
|
||||
{
|
||||
png_infop info_ptr = NULL;
|
||||
if(png_ptr == NULL) return;
|
||||
|
||||
png_debug(1, "in png_destroy_info_struct\n");
|
||||
if (info_ptr_ptr != NULL)
|
||||
info_ptr = *info_ptr_ptr;
|
||||
|
||||
if (info_ptr != NULL)
|
||||
{
|
||||
png_info_destroy(png_ptr, info_ptr);
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn,
|
||||
png_ptr->mem_ptr);
|
||||
#else
|
||||
png_destroy_struct((png_voidp)info_ptr);
|
||||
#endif
|
||||
*info_ptr_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the info structure. This is now an internal function (0.89)
|
||||
* and applications using it are urged to use png_create_info_struct()
|
||||
* instead.
|
||||
*/
|
||||
#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
|
||||
#undef png_info_init
|
||||
void PNGAPI
|
||||
png_info_init(png_infop info_ptr)
|
||||
{
|
||||
/* We only come here via pre-1.0.12-compiled applications */
|
||||
png_info_init_3(&info_ptr, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PNGAPI
|
||||
png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
|
||||
{
|
||||
png_infop info_ptr = *ptr_ptr;
|
||||
|
||||
if(info_ptr == NULL) return;
|
||||
|
||||
png_debug(1, "in png_info_init_3\n");
|
||||
|
||||
if(png_sizeof(png_info) > png_info_struct_size)
|
||||
{
|
||||
png_destroy_struct(info_ptr);
|
||||
info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
|
||||
*ptr_ptr = info_ptr;
|
||||
}
|
||||
|
||||
/* set everything to 0 */
|
||||
png_memset(info_ptr, 0, png_sizeof (png_info));
|
||||
}
|
||||
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
void PNGAPI
|
||||
png_data_freer(png_structp png_ptr, png_infop info_ptr,
|
||||
int freer, png_uint_32 mask)
|
||||
{
|
||||
png_debug(1, "in png_data_freer\n");
|
||||
if (png_ptr == NULL || info_ptr == NULL)
|
||||
return;
|
||||
if(freer == PNG_DESTROY_WILL_FREE_DATA)
|
||||
info_ptr->free_me |= mask;
|
||||
else if(freer == PNG_USER_WILL_FREE_DATA)
|
||||
info_ptr->free_me &= ~mask;
|
||||
else
|
||||
png_warning(png_ptr,
|
||||
"Unknown freer parameter in png_data_freer.");
|
||||
}
|
||||
#endif
|
||||
|
||||
void PNGAPI
|
||||
png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
|
||||
int num)
|
||||
{
|
||||
png_debug(1, "in png_free_data\n");
|
||||
if (png_ptr == NULL || info_ptr == NULL)
|
||||
return;
|
||||
|
||||
#if defined(PNG_TEXT_SUPPORTED)
|
||||
/* free text item num or (if num == -1) all text items */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
|
||||
#else
|
||||
if (mask & PNG_FREE_TEXT)
|
||||
#endif
|
||||
{
|
||||
if (num != -1)
|
||||
{
|
||||
if (info_ptr->text && info_ptr->text[num].key)
|
||||
{
|
||||
png_free(png_ptr, info_ptr->text[num].key);
|
||||
info_ptr->text[num].key = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < info_ptr->num_text; i++)
|
||||
png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
|
||||
png_free(png_ptr, info_ptr->text);
|
||||
info_ptr->text = NULL;
|
||||
info_ptr->num_text=0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_tRNS_SUPPORTED)
|
||||
/* free any tRNS entry */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
|
||||
#else
|
||||
if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS))
|
||||
#endif
|
||||
{
|
||||
png_free(png_ptr, info_ptr->trans);
|
||||
info_ptr->valid &= ~PNG_INFO_tRNS;
|
||||
#ifndef PNG_FREE_ME_SUPPORTED
|
||||
png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
|
||||
#endif
|
||||
info_ptr->trans = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_sCAL_SUPPORTED)
|
||||
/* free any sCAL entry */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
|
||||
#else
|
||||
if (mask & PNG_FREE_SCAL)
|
||||
#endif
|
||||
{
|
||||
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
|
||||
png_free(png_ptr, info_ptr->scal_s_width);
|
||||
png_free(png_ptr, info_ptr->scal_s_height);
|
||||
info_ptr->scal_s_width = NULL;
|
||||
info_ptr->scal_s_height = NULL;
|
||||
#endif
|
||||
info_ptr->valid &= ~PNG_INFO_sCAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_pCAL_SUPPORTED)
|
||||
/* free any pCAL entry */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
|
||||
#else
|
||||
if (mask & PNG_FREE_PCAL)
|
||||
#endif
|
||||
{
|
||||
png_free(png_ptr, info_ptr->pcal_purpose);
|
||||
png_free(png_ptr, info_ptr->pcal_units);
|
||||
info_ptr->pcal_purpose = NULL;
|
||||
info_ptr->pcal_units = NULL;
|
||||
if (info_ptr->pcal_params != NULL)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
|
||||
{
|
||||
png_free(png_ptr, info_ptr->pcal_params[i]);
|
||||
info_ptr->pcal_params[i]=NULL;
|
||||
}
|
||||
png_free(png_ptr, info_ptr->pcal_params);
|
||||
info_ptr->pcal_params = NULL;
|
||||
}
|
||||
info_ptr->valid &= ~PNG_INFO_pCAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_iCCP_SUPPORTED)
|
||||
/* free any iCCP entry */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
|
||||
#else
|
||||
if (mask & PNG_FREE_ICCP)
|
||||
#endif
|
||||
{
|
||||
png_free(png_ptr, info_ptr->iccp_name);
|
||||
png_free(png_ptr, info_ptr->iccp_profile);
|
||||
info_ptr->iccp_name = NULL;
|
||||
info_ptr->iccp_profile = NULL;
|
||||
info_ptr->valid &= ~PNG_INFO_iCCP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_sPLT_SUPPORTED)
|
||||
/* free a given sPLT entry, or (if num == -1) all sPLT entries */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
|
||||
#else
|
||||
if (mask & PNG_FREE_SPLT)
|
||||
#endif
|
||||
{
|
||||
if (num != -1)
|
||||
{
|
||||
if(info_ptr->splt_palettes)
|
||||
{
|
||||
png_free(png_ptr, info_ptr->splt_palettes[num].name);
|
||||
png_free(png_ptr, info_ptr->splt_palettes[num].entries);
|
||||
info_ptr->splt_palettes[num].name = NULL;
|
||||
info_ptr->splt_palettes[num].entries = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(info_ptr->splt_palettes_num)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
|
||||
png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
|
||||
|
||||
png_free(png_ptr, info_ptr->splt_palettes);
|
||||
info_ptr->splt_palettes = NULL;
|
||||
info_ptr->splt_palettes_num = 0;
|
||||
}
|
||||
info_ptr->valid &= ~PNG_INFO_sPLT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
|
||||
if(png_ptr->unknown_chunk.data)
|
||||
{
|
||||
png_free(png_ptr, png_ptr->unknown_chunk.data);
|
||||
png_ptr->unknown_chunk.data = NULL;
|
||||
}
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
|
||||
#else
|
||||
if (mask & PNG_FREE_UNKN)
|
||||
#endif
|
||||
{
|
||||
if (num != -1)
|
||||
{
|
||||
if(info_ptr->unknown_chunks)
|
||||
{
|
||||
png_free(png_ptr, info_ptr->unknown_chunks[num].data);
|
||||
info_ptr->unknown_chunks[num].data = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
if(info_ptr->unknown_chunks_num)
|
||||
{
|
||||
for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++)
|
||||
png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
|
||||
|
||||
png_free(png_ptr, info_ptr->unknown_chunks);
|
||||
info_ptr->unknown_chunks = NULL;
|
||||
info_ptr->unknown_chunks_num = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_hIST_SUPPORTED)
|
||||
/* free any hIST entry */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_HIST) & info_ptr->free_me)
|
||||
#else
|
||||
if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST))
|
||||
#endif
|
||||
{
|
||||
png_free(png_ptr, info_ptr->hist);
|
||||
info_ptr->hist = NULL;
|
||||
info_ptr->valid &= ~PNG_INFO_hIST;
|
||||
#ifndef PNG_FREE_ME_SUPPORTED
|
||||
png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* free any PLTE entry that was internally allocated */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
|
||||
#else
|
||||
if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE))
|
||||
#endif
|
||||
{
|
||||
png_zfree(png_ptr, info_ptr->palette);
|
||||
info_ptr->palette = NULL;
|
||||
info_ptr->valid &= ~PNG_INFO_PLTE;
|
||||
#ifndef PNG_FREE_ME_SUPPORTED
|
||||
png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
|
||||
#endif
|
||||
info_ptr->num_palette = 0;
|
||||
}
|
||||
|
||||
#if defined(PNG_INFO_IMAGE_SUPPORTED)
|
||||
/* free any image bits attached to the info structure */
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
|
||||
#else
|
||||
if (mask & PNG_FREE_ROWS)
|
||||
#endif
|
||||
{
|
||||
if(info_ptr->row_pointers)
|
||||
{
|
||||
int row;
|
||||
for (row = 0; row < (int)info_ptr->height; row++)
|
||||
{
|
||||
png_free(png_ptr, info_ptr->row_pointers[row]);
|
||||
info_ptr->row_pointers[row]=NULL;
|
||||
}
|
||||
png_free(png_ptr, info_ptr->row_pointers);
|
||||
info_ptr->row_pointers=NULL;
|
||||
}
|
||||
info_ptr->valid &= ~PNG_INFO_IDAT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_FREE_ME_SUPPORTED
|
||||
if(num == -1)
|
||||
info_ptr->free_me &= ~mask;
|
||||
else
|
||||
info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This is an internal routine to free any memory that the info struct is
|
||||
* pointing to before re-using it or freeing the struct itself. Recall
|
||||
* that png_free() checks for NULL pointers for us.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_info_destroy(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
png_debug(1, "in png_info_destroy\n");
|
||||
|
||||
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
||||
|
||||
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
|
||||
if (png_ptr->num_chunk_list)
|
||||
{
|
||||
png_free(png_ptr, png_ptr->chunk_list);
|
||||
png_ptr->chunk_list=NULL;
|
||||
png_ptr->num_chunk_list=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
png_info_init_3(&info_ptr, png_sizeof(png_info));
|
||||
}
|
||||
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
|
||||
|
||||
/* This function returns a pointer to the io_ptr associated with the user
|
||||
* functions. The application should free any memory associated with this
|
||||
* pointer before png_write_destroy() or png_read_destroy() are called.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_get_io_ptr(png_structp png_ptr)
|
||||
{
|
||||
if(png_ptr == NULL) return (NULL);
|
||||
return (png_ptr->io_ptr);
|
||||
}
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
#if !defined(PNG_NO_STDIO)
|
||||
/* Initialize the default input/output functions for the PNG file. If you
|
||||
* use your own read or write routines, you can call either png_set_read_fn()
|
||||
* or png_set_write_fn() instead of png_init_io(). If you have defined
|
||||
* PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't
|
||||
* necessarily available.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_init_io(png_structp png_ptr, png_FILE_p fp)
|
||||
{
|
||||
png_debug(1, "in png_init_io\n");
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->io_ptr = (png_voidp)fp;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_TIME_RFC1123_SUPPORTED)
|
||||
/* Convert the supplied time into an RFC 1123 string suitable for use in
|
||||
* a "Creation Time" or other text-based time string.
|
||||
*/
|
||||
png_charp PNGAPI
|
||||
png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
|
||||
{
|
||||
static PNG_CONST char short_months[12][4] =
|
||||
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
|
||||
if(png_ptr == NULL) return (NULL);
|
||||
if (png_ptr->time_buffer == NULL)
|
||||
{
|
||||
png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29*
|
||||
png_sizeof(char)));
|
||||
}
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
{
|
||||
wchar_t time_buf[29];
|
||||
wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"),
|
||||
ptime->day % 32, short_months[(ptime->month - 1) % 12],
|
||||
ptime->year, ptime->hour % 24, ptime->minute % 60,
|
||||
ptime->second % 61);
|
||||
WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer, 29,
|
||||
NULL, NULL);
|
||||
}
|
||||
#else
|
||||
#ifdef USE_FAR_KEYWORD
|
||||
{
|
||||
char near_time_buf[29];
|
||||
png_snprintf6(near_time_buf,29,"%d %s %d %02d:%02d:%02d +0000",
|
||||
ptime->day % 32, short_months[(ptime->month - 1) % 12],
|
||||
ptime->year, ptime->hour % 24, ptime->minute % 60,
|
||||
ptime->second % 61);
|
||||
png_memcpy(png_ptr->time_buffer, near_time_buf,
|
||||
29*png_sizeof(char));
|
||||
}
|
||||
#else
|
||||
png_snprintf6(png_ptr->time_buffer,29,"%d %s %d %02d:%02d:%02d +0000",
|
||||
ptime->day % 32, short_months[(ptime->month - 1) % 12],
|
||||
ptime->year, ptime->hour % 24, ptime->minute % 60,
|
||||
ptime->second % 61);
|
||||
#endif
|
||||
#endif /* _WIN32_WCE */
|
||||
return ((png_charp)png_ptr->time_buffer);
|
||||
}
|
||||
#endif /* PNG_TIME_RFC1123_SUPPORTED */
|
||||
|
||||
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
|
||||
|
||||
png_charp PNGAPI
|
||||
png_get_copyright(png_structp png_ptr)
|
||||
{
|
||||
png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */
|
||||
return ((png_charp) "\n libpng version 1.2.24 - December 14, 2007\n\
|
||||
Copyright (c) 1998-2007 Glenn Randers-Pehrson\n\
|
||||
Copyright (c) 1996-1997 Andreas Dilger\n\
|
||||
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n");
|
||||
}
|
||||
|
||||
/* The following return the library version as a short string in the
|
||||
* format 1.0.0 through 99.99.99zz. To get the version of *.h files
|
||||
* used with your application, print out PNG_LIBPNG_VER_STRING, which
|
||||
* is defined in png.h.
|
||||
* Note: now there is no difference between png_get_libpng_ver() and
|
||||
* png_get_header_ver(). Due to the version_nn_nn_nn typedef guard,
|
||||
* it is guaranteed that png.c uses the correct version of png.h.
|
||||
*/
|
||||
png_charp PNGAPI
|
||||
png_get_libpng_ver(png_structp png_ptr)
|
||||
{
|
||||
/* Version of *.c files used when building libpng */
|
||||
png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */
|
||||
return ((png_charp) PNG_LIBPNG_VER_STRING);
|
||||
}
|
||||
|
||||
png_charp PNGAPI
|
||||
png_get_header_ver(png_structp png_ptr)
|
||||
{
|
||||
/* Version of *.h files used when building libpng */
|
||||
png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */
|
||||
return ((png_charp) PNG_LIBPNG_VER_STRING);
|
||||
}
|
||||
|
||||
png_charp PNGAPI
|
||||
png_get_header_version(png_structp png_ptr)
|
||||
{
|
||||
/* Returns longer string containing both version and date */
|
||||
png_ptr = png_ptr; /* silence compiler warning about unused png_ptr */
|
||||
return ((png_charp) PNG_HEADER_VERSION_STRING
|
||||
#ifndef PNG_READ_SUPPORTED
|
||||
" (NO READ SUPPORT)"
|
||||
#endif
|
||||
"\n");
|
||||
}
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
int PNGAPI
|
||||
png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name)
|
||||
{
|
||||
/* check chunk_name and return "keep" value if it's on the list, else 0 */
|
||||
int i;
|
||||
png_bytep p;
|
||||
if(png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0)
|
||||
return 0;
|
||||
p=png_ptr->chunk_list+png_ptr->num_chunk_list*5-5;
|
||||
for (i = png_ptr->num_chunk_list; i; i--, p-=5)
|
||||
if (!png_memcmp(chunk_name, p, 4))
|
||||
return ((int)*(p+4));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function, added to libpng-1.0.6g, is untested. */
|
||||
int PNGAPI
|
||||
png_reset_zstream(png_structp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL) return Z_STREAM_ERROR;
|
||||
return (inflateReset(&png_ptr->zstream));
|
||||
}
|
||||
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
|
||||
|
||||
/* This function was added to libpng-1.0.7 */
|
||||
png_uint_32 PNGAPI
|
||||
png_access_version_number(void)
|
||||
{
|
||||
/* Version of *.c files used when building libpng */
|
||||
return((png_uint_32) PNG_LIBPNG_VER);
|
||||
}
|
||||
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED)
|
||||
#if !defined(PNG_1_0_X)
|
||||
/* this function was added to libpng 1.2.0 */
|
||||
int PNGAPI
|
||||
png_mmx_support(void)
|
||||
{
|
||||
/* obsolete, to be removed from libpng-1.4.0 */
|
||||
return -1;
|
||||
}
|
||||
#endif /* PNG_1_0_X */
|
||||
#endif /* PNG_READ_SUPPORTED && PNG_ASSEMBLER_CODE_SUPPORTED */
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
#ifdef PNG_SIZE_T
|
||||
/* Added at libpng version 1.2.6 */
|
||||
PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size));
|
||||
png_size_t PNGAPI
|
||||
png_convert_size(size_t size)
|
||||
{
|
||||
if (size > (png_size_t)-1)
|
||||
PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */
|
||||
return ((png_size_t)size);
|
||||
}
|
||||
#endif /* PNG_SIZE_T */
|
||||
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
|
||||
Vendored
+343
@@ -0,0 +1,343 @@
|
||||
|
||||
/* pngerror.c - stub functions for i/o and memory allocation
|
||||
*
|
||||
* Last changed in libpng 1.2.22 [October 13, 2007]
|
||||
* For conditions of distribution and use, see copyright notice in png.h
|
||||
* Copyright (c) 1998-2007 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This file provides a location for all error handling. Users who
|
||||
* need special error handling are expected to write replacement functions
|
||||
* and use png_set_error_fn() to use those functions. See the instructions
|
||||
* at each function.
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
static void /* PRIVATE */
|
||||
png_default_error PNGARG((png_structp png_ptr,
|
||||
png_const_charp error_message));
|
||||
#ifndef PNG_NO_WARNINGS
|
||||
static void /* PRIVATE */
|
||||
png_default_warning PNGARG((png_structp png_ptr,
|
||||
png_const_charp warning_message));
|
||||
#endif /* PNG_NO_WARNINGS */
|
||||
|
||||
/* This function is called whenever there is a fatal error. This function
|
||||
* should not be changed. If there is a need to handle errors differently,
|
||||
* you should supply a replacement error function and use png_set_error_fn()
|
||||
* to replace the error function at run-time.
|
||||
*/
|
||||
#ifndef PNG_NO_ERROR_TEXT
|
||||
void PNGAPI
|
||||
png_error(png_structp png_ptr, png_const_charp error_message)
|
||||
{
|
||||
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
|
||||
char msg[16];
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
if (png_ptr->flags&
|
||||
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
|
||||
{
|
||||
if (*error_message == '#')
|
||||
{
|
||||
int offset;
|
||||
for (offset=1; offset<15; offset++)
|
||||
if (*(error_message+offset) == ' ')
|
||||
break;
|
||||
if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<offset-1; i++)
|
||||
msg[i]=error_message[i+1];
|
||||
msg[i]='\0';
|
||||
error_message=msg;
|
||||
}
|
||||
else
|
||||
error_message+=offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
|
||||
{
|
||||
msg[0]='0';
|
||||
msg[1]='\0';
|
||||
error_message=msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (png_ptr != NULL && png_ptr->error_fn != NULL)
|
||||
(*(png_ptr->error_fn))(png_ptr, error_message);
|
||||
|
||||
/* If the custom handler doesn't exist, or if it returns,
|
||||
use the default handler, which will not return. */
|
||||
png_default_error(png_ptr, error_message);
|
||||
}
|
||||
#else
|
||||
void PNGAPI
|
||||
png_err(png_structp png_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && png_ptr->error_fn != NULL)
|
||||
(*(png_ptr->error_fn))(png_ptr, '\0');
|
||||
|
||||
/* If the custom handler doesn't exist, or if it returns,
|
||||
use the default handler, which will not return. */
|
||||
png_default_error(png_ptr, '\0');
|
||||
}
|
||||
#endif /* PNG_NO_ERROR_TEXT */
|
||||
|
||||
#ifndef PNG_NO_WARNINGS
|
||||
/* This function is called whenever there is a non-fatal error. This function
|
||||
* should not be changed. If there is a need to handle warnings differently,
|
||||
* you should supply a replacement warning function and use
|
||||
* png_set_error_fn() to replace the warning function at run-time.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_warning(png_structp png_ptr, png_const_charp warning_message)
|
||||
{
|
||||
int offset = 0;
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
|
||||
if (png_ptr->flags&
|
||||
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
|
||||
#endif
|
||||
{
|
||||
if (*warning_message == '#')
|
||||
{
|
||||
for (offset=1; offset<15; offset++)
|
||||
if (*(warning_message+offset) == ' ')
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
|
||||
(*(png_ptr->warning_fn))(png_ptr, warning_message+offset);
|
||||
}
|
||||
else
|
||||
png_default_warning(png_ptr, warning_message+offset);
|
||||
}
|
||||
#endif /* PNG_NO_WARNINGS */
|
||||
|
||||
|
||||
/* These utilities are used internally to build an error message that relates
|
||||
* to the current chunk. The chunk name comes from png_ptr->chunk_name,
|
||||
* this is used to prefix the message. The message is limited in length
|
||||
* to 63 bytes, the name characters are output as hex digits wrapped in []
|
||||
* if the character is invalid.
|
||||
*/
|
||||
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
|
||||
static PNG_CONST char png_digit[16] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'A', 'B', 'C', 'D', 'E', 'F'
|
||||
};
|
||||
|
||||
#define PNG_MAX_ERROR_TEXT 64
|
||||
|
||||
#if !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT)
|
||||
static void /* PRIVATE */
|
||||
png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
|
||||
error_message)
|
||||
{
|
||||
int iout = 0, iin = 0;
|
||||
|
||||
while (iin < 4)
|
||||
{
|
||||
int c = png_ptr->chunk_name[iin++];
|
||||
if (isnonalpha(c))
|
||||
{
|
||||
buffer[iout++] = '[';
|
||||
buffer[iout++] = png_digit[(c & 0xf0) >> 4];
|
||||
buffer[iout++] = png_digit[c & 0x0f];
|
||||
buffer[iout++] = ']';
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[iout++] = (png_byte)c;
|
||||
}
|
||||
}
|
||||
|
||||
if (error_message == NULL)
|
||||
buffer[iout] = '\0';
|
||||
else
|
||||
{
|
||||
buffer[iout++] = ':';
|
||||
buffer[iout++] = ' ';
|
||||
png_memcpy(buffer+iout, error_message, PNG_MAX_ERROR_TEXT);
|
||||
buffer[iout+PNG_MAX_ERROR_TEXT-1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
void PNGAPI
|
||||
png_chunk_error(png_structp png_ptr, png_const_charp error_message)
|
||||
{
|
||||
char msg[18+PNG_MAX_ERROR_TEXT];
|
||||
if (png_ptr == NULL)
|
||||
png_error(png_ptr, error_message);
|
||||
else
|
||||
{
|
||||
png_format_buffer(png_ptr, msg, error_message);
|
||||
png_error(png_ptr, msg);
|
||||
}
|
||||
}
|
||||
#endif /* PNG_READ_SUPPORTED */
|
||||
#endif /* !defined(PNG_NO_WARNINGS) || !defined(PNG_NO_ERROR_TEXT) */
|
||||
|
||||
#ifndef PNG_NO_WARNINGS
|
||||
void PNGAPI
|
||||
png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
|
||||
{
|
||||
char msg[18+PNG_MAX_ERROR_TEXT];
|
||||
if (png_ptr == NULL)
|
||||
png_warning(png_ptr, warning_message);
|
||||
else
|
||||
{
|
||||
png_format_buffer(png_ptr, msg, warning_message);
|
||||
png_warning(png_ptr, msg);
|
||||
}
|
||||
}
|
||||
#endif /* PNG_NO_WARNINGS */
|
||||
|
||||
|
||||
/* This is the default error handling function. Note that replacements for
|
||||
* this function MUST NOT RETURN, or the program will likely crash. This
|
||||
* function is used by default, or if the program supplies NULL for the
|
||||
* error function pointer in png_set_error_fn().
|
||||
*/
|
||||
static void /* PRIVATE */
|
||||
png_default_error(png_structp png_ptr, png_const_charp error_message)
|
||||
{
|
||||
#ifndef PNG_NO_CONSOLE_IO
|
||||
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
|
||||
if (*error_message == '#')
|
||||
{
|
||||
int offset;
|
||||
char error_number[16];
|
||||
for (offset=0; offset<15; offset++)
|
||||
{
|
||||
error_number[offset] = *(error_message+offset+1);
|
||||
if (*(error_message+offset) == ' ')
|
||||
break;
|
||||
}
|
||||
if((offset > 1) && (offset < 15))
|
||||
{
|
||||
error_number[offset-1]='\0';
|
||||
fprintf(stderr, "libpng error no. %s: %s\n", error_number,
|
||||
error_message+offset);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "libpng error: %s, offset=%d\n", error_message,offset);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
fprintf(stderr, "libpng error: %s\n", error_message);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_SETJMP_SUPPORTED
|
||||
if (png_ptr)
|
||||
{
|
||||
# ifdef USE_FAR_KEYWORD
|
||||
{
|
||||
jmp_buf jmpbuf;
|
||||
png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf));
|
||||
longjmp(jmpbuf, 1);
|
||||
}
|
||||
# else
|
||||
longjmp(png_ptr->jmpbuf, 1);
|
||||
# endif
|
||||
}
|
||||
#else
|
||||
PNG_ABORT();
|
||||
#endif
|
||||
#ifdef PNG_NO_CONSOLE_IO
|
||||
error_message = error_message; /* make compiler happy */
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef PNG_NO_WARNINGS
|
||||
/* This function is called when there is a warning, but the library thinks
|
||||
* it can continue anyway. Replacement functions don't have to do anything
|
||||
* here if you don't want them to. In the default configuration, png_ptr is
|
||||
* not used, but it is passed in case it may be useful.
|
||||
*/
|
||||
static void /* PRIVATE */
|
||||
png_default_warning(png_structp png_ptr, png_const_charp warning_message)
|
||||
{
|
||||
#ifndef PNG_NO_CONSOLE_IO
|
||||
# ifdef PNG_ERROR_NUMBERS_SUPPORTED
|
||||
if (*warning_message == '#')
|
||||
{
|
||||
int offset;
|
||||
char warning_number[16];
|
||||
for (offset=0; offset<15; offset++)
|
||||
{
|
||||
warning_number[offset]=*(warning_message+offset+1);
|
||||
if (*(warning_message+offset) == ' ')
|
||||
break;
|
||||
}
|
||||
if((offset > 1) && (offset < 15))
|
||||
{
|
||||
warning_number[offset-1]='\0';
|
||||
fprintf(stderr, "libpng warning no. %s: %s\n", warning_number,
|
||||
warning_message+offset);
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "libpng warning: %s\n", warning_message);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
fprintf(stderr, "libpng warning: %s\n", warning_message);
|
||||
#else
|
||||
warning_message = warning_message; /* make compiler happy */
|
||||
#endif
|
||||
png_ptr = png_ptr; /* make compiler happy */
|
||||
}
|
||||
#endif /* PNG_NO_WARNINGS */
|
||||
|
||||
/* This function is called when the application wants to use another method
|
||||
* of handling errors and warnings. Note that the error function MUST NOT
|
||||
* return to the calling routine or serious problems will occur. The return
|
||||
* method used in the default routine calls longjmp(png_ptr->jmpbuf, 1)
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
|
||||
png_error_ptr error_fn, png_error_ptr warning_fn)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
png_ptr->error_ptr = error_ptr;
|
||||
png_ptr->error_fn = error_fn;
|
||||
png_ptr->warning_fn = warning_fn;
|
||||
}
|
||||
|
||||
|
||||
/* This function returns a pointer to the error_ptr associated with the user
|
||||
* functions. The application should free any memory associated with this
|
||||
* pointer before png_write_destroy and png_read_destroy are called.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_get_error_ptr(png_structp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
return ((png_voidp)png_ptr->error_ptr);
|
||||
}
|
||||
|
||||
|
||||
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
|
||||
void PNGAPI
|
||||
png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
|
||||
{
|
||||
if(png_ptr != NULL)
|
||||
{
|
||||
png_ptr->flags &=
|
||||
((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|
||||
Vendored
+101
@@ -0,0 +1,101 @@
|
||||
/* pnggccrd.c was removed from libpng-1.2.20. */
|
||||
|
||||
/* This code snippet is for use by configure's compilation test. */
|
||||
|
||||
#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \
|
||||
defined(PNG_MMX_CODE_SUPPORTED)
|
||||
int PNGAPI png_dummy_mmx_support(void);
|
||||
|
||||
static int _mmx_supported = 2; // 0: no MMX; 1: MMX supported; 2: not tested
|
||||
|
||||
int PNGAPI
|
||||
png_dummy_mmx_support(void) __attribute__((noinline));
|
||||
|
||||
int PNGAPI
|
||||
png_dummy_mmx_support(void)
|
||||
{
|
||||
int result;
|
||||
#if defined(PNG_MMX_CODE_SUPPORTED) // superfluous, but what the heck
|
||||
__asm__ __volatile__ (
|
||||
#if defined(__x86_64__)
|
||||
"pushq %%rbx \n\t" // rbx gets clobbered by CPUID instruction
|
||||
"pushq %%rcx \n\t" // so does rcx...
|
||||
"pushq %%rdx \n\t" // ...and rdx (but rcx & rdx safe on Linux)
|
||||
"pushfq \n\t" // save Eflag to stack
|
||||
"popq %%rax \n\t" // get Eflag from stack into rax
|
||||
"movq %%rax, %%rcx \n\t" // make another copy of Eflag in rcx
|
||||
"xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
|
||||
"pushq %%rax \n\t" // save modified Eflag back to stack
|
||||
"popfq \n\t" // restore modified value to Eflag reg
|
||||
"pushfq \n\t" // save Eflag to stack
|
||||
"popq %%rax \n\t" // get Eflag from stack
|
||||
"pushq %%rcx \n\t" // save original Eflag to stack
|
||||
"popfq \n\t" // restore original Eflag
|
||||
#else
|
||||
"pushl %%ebx \n\t" // ebx gets clobbered by CPUID instruction
|
||||
"pushl %%ecx \n\t" // so does ecx...
|
||||
"pushl %%edx \n\t" // ...and edx (but ecx & edx safe on Linux)
|
||||
"pushfl \n\t" // save Eflag to stack
|
||||
"popl %%eax \n\t" // get Eflag from stack into eax
|
||||
"movl %%eax, %%ecx \n\t" // make another copy of Eflag in ecx
|
||||
"xorl $0x200000, %%eax \n\t" // toggle ID bit in Eflag (i.e., bit 21)
|
||||
"pushl %%eax \n\t" // save modified Eflag back to stack
|
||||
"popfl \n\t" // restore modified value to Eflag reg
|
||||
"pushfl \n\t" // save Eflag to stack
|
||||
"popl %%eax \n\t" // get Eflag from stack
|
||||
"pushl %%ecx \n\t" // save original Eflag to stack
|
||||
"popfl \n\t" // restore original Eflag
|
||||
#endif
|
||||
"xorl %%ecx, %%eax \n\t" // compare new Eflag with original Eflag
|
||||
"jz 0f \n\t" // if same, CPUID instr. is not supported
|
||||
|
||||
"xorl %%eax, %%eax \n\t" // set eax to zero
|
||||
// ".byte 0x0f, 0xa2 \n\t" // CPUID instruction (two-byte opcode)
|
||||
"cpuid \n\t" // get the CPU identification info
|
||||
"cmpl $1, %%eax \n\t" // make sure eax return non-zero value
|
||||
"jl 0f \n\t" // if eax is zero, MMX is not supported
|
||||
|
||||
"xorl %%eax, %%eax \n\t" // set eax to zero and...
|
||||
"incl %%eax \n\t" // ...increment eax to 1. This pair is
|
||||
// faster than the instruction "mov eax, 1"
|
||||
"cpuid \n\t" // get the CPU identification info again
|
||||
"andl $0x800000, %%edx \n\t" // mask out all bits but MMX bit (23)
|
||||
"cmpl $0, %%edx \n\t" // 0 = MMX not supported
|
||||
"jz 0f \n\t" // non-zero = yes, MMX IS supported
|
||||
|
||||
"movl $1, %%eax \n\t" // set return value to 1
|
||||
"jmp 1f \n\t" // DONE: have MMX support
|
||||
|
||||
"0: \n\t" // .NOT_SUPPORTED: target label for jump instructions
|
||||
"movl $0, %%eax \n\t" // set return value to 0
|
||||
"1: \n\t" // .RETURN: target label for jump instructions
|
||||
#if defined(__x86_64__)
|
||||
"popq %%rdx \n\t" // restore rdx
|
||||
"popq %%rcx \n\t" // restore rcx
|
||||
"popq %%rbx \n\t" // restore rbx
|
||||
#else
|
||||
"popl %%edx \n\t" // restore edx
|
||||
"popl %%ecx \n\t" // restore ecx
|
||||
"popl %%ebx \n\t" // restore ebx
|
||||
#endif
|
||||
|
||||
// "ret \n\t" // DONE: no MMX support
|
||||
// (fall through to standard C "ret")
|
||||
|
||||
: "=a" (result) // output list
|
||||
|
||||
: // any variables used on input (none)
|
||||
|
||||
// no clobber list
|
||||
// , "%ebx", "%ecx", "%edx" // GRR: we handle these manually
|
||||
// , "memory" // if write to a variable gcc thought was in a reg
|
||||
// , "cc" // "condition codes" (flag bits)
|
||||
);
|
||||
_mmx_supported = result;
|
||||
#else
|
||||
_mmx_supported = 0;
|
||||
#endif /* PNG_MMX_CODE_SUPPORTED */
|
||||
|
||||
return _mmx_supported;
|
||||
}
|
||||
#endif
|
||||
Vendored
+901
@@ -0,0 +1,901 @@
|
||||
|
||||
/* pngget.c - retrieval of values from info struct
|
||||
*
|
||||
* Last changed in libpng 1.2.15 January 5, 2007
|
||||
* For conditions of distribution and use, see copyright notice in png.h
|
||||
* Copyright (c) 1998-2007 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
return(info_ptr->valid & flag);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_rowbytes(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
return(info_ptr->rowbytes);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
#if defined(PNG_INFO_IMAGE_SUPPORTED)
|
||||
png_bytepp PNGAPI
|
||||
png_get_rows(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
return(info_ptr->row_pointers);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_EASY_ACCESS_SUPPORTED
|
||||
/* easy access to info, added in libpng-0.99 */
|
||||
png_uint_32 PNGAPI
|
||||
png_get_image_width(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
{
|
||||
return info_ptr->width;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_image_height(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
{
|
||||
return info_ptr->height;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_byte PNGAPI
|
||||
png_get_bit_depth(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
{
|
||||
return info_ptr->bit_depth;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_byte PNGAPI
|
||||
png_get_color_type(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
{
|
||||
return info_ptr->color_type;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_byte PNGAPI
|
||||
png_get_filter_type(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
{
|
||||
return info_ptr->filter_type;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_byte PNGAPI
|
||||
png_get_interlace_type(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
{
|
||||
return info_ptr->interlace_type;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_byte PNGAPI
|
||||
png_get_compression_type(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
{
|
||||
return info_ptr->compression_type;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
#if defined(PNG_pHYs_SUPPORTED)
|
||||
if (info_ptr->valid & PNG_INFO_pHYs)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "png_get_x_pixels_per_meter");
|
||||
if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
|
||||
return (0);
|
||||
else return (info_ptr->x_pixels_per_unit);
|
||||
}
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
#if defined(PNG_pHYs_SUPPORTED)
|
||||
if (info_ptr->valid & PNG_INFO_pHYs)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "png_get_y_pixels_per_meter");
|
||||
if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
|
||||
return (0);
|
||||
else return (info_ptr->y_pixels_per_unit);
|
||||
}
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
#if defined(PNG_pHYs_SUPPORTED)
|
||||
if (info_ptr->valid & PNG_INFO_pHYs)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "png_get_pixels_per_meter");
|
||||
if(info_ptr->phys_unit_type != PNG_RESOLUTION_METER ||
|
||||
info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit)
|
||||
return (0);
|
||||
else return (info_ptr->x_pixels_per_unit);
|
||||
}
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
float PNGAPI
|
||||
png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
#if defined(PNG_pHYs_SUPPORTED)
|
||||
if (info_ptr->valid & PNG_INFO_pHYs)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "png_get_aspect_ratio");
|
||||
if (info_ptr->x_pixels_per_unit == 0)
|
||||
return ((float)0.0);
|
||||
else
|
||||
return ((float)((float)info_ptr->y_pixels_per_unit
|
||||
/(float)info_ptr->x_pixels_per_unit));
|
||||
}
|
||||
#else
|
||||
return (0.0);
|
||||
#endif
|
||||
return ((float)0.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
png_int_32 PNGAPI
|
||||
png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
#if defined(PNG_oFFs_SUPPORTED)
|
||||
if (info_ptr->valid & PNG_INFO_oFFs)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns");
|
||||
if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
|
||||
return (0);
|
||||
else return (info_ptr->x_offset);
|
||||
}
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_int_32 PNGAPI
|
||||
png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
#if defined(PNG_oFFs_SUPPORTED)
|
||||
if (info_ptr->valid & PNG_INFO_oFFs)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns");
|
||||
if(info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
|
||||
return (0);
|
||||
else return (info_ptr->y_offset);
|
||||
}
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_int_32 PNGAPI
|
||||
png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
#if defined(PNG_oFFs_SUPPORTED)
|
||||
if (info_ptr->valid & PNG_INFO_oFFs)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "png_get_x_offset_microns");
|
||||
if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
|
||||
return (0);
|
||||
else return (info_ptr->x_offset);
|
||||
}
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_int_32 PNGAPI
|
||||
png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
#if defined(PNG_oFFs_SUPPORTED)
|
||||
if (info_ptr->valid & PNG_INFO_oFFs)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "png_get_y_offset_microns");
|
||||
if(info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
|
||||
return (0);
|
||||
else return (info_ptr->y_offset);
|
||||
}
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr)
|
||||
*.0254 +.5));
|
||||
}
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr)
|
||||
*.0254 +.5));
|
||||
}
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr)
|
||||
*.0254 +.5));
|
||||
}
|
||||
|
||||
float PNGAPI
|
||||
png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
return ((float)png_get_x_offset_microns(png_ptr, info_ptr)
|
||||
*.00003937);
|
||||
}
|
||||
|
||||
float PNGAPI
|
||||
png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
return ((float)png_get_y_offset_microns(png_ptr, info_ptr)
|
||||
*.00003937);
|
||||
}
|
||||
|
||||
#if defined(PNG_pHYs_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr,
|
||||
png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
|
||||
{
|
||||
png_uint_32 retval = 0;
|
||||
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "pHYs");
|
||||
if (res_x != NULL)
|
||||
{
|
||||
*res_x = info_ptr->x_pixels_per_unit;
|
||||
retval |= PNG_INFO_pHYs;
|
||||
}
|
||||
if (res_y != NULL)
|
||||
{
|
||||
*res_y = info_ptr->y_pixels_per_unit;
|
||||
retval |= PNG_INFO_pHYs;
|
||||
}
|
||||
if (unit_type != NULL)
|
||||
{
|
||||
*unit_type = (int)info_ptr->phys_unit_type;
|
||||
retval |= PNG_INFO_pHYs;
|
||||
if(*unit_type == 1)
|
||||
{
|
||||
if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50);
|
||||
if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
#endif /* PNG_pHYs_SUPPORTED */
|
||||
#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */
|
||||
|
||||
/* png_get_channels really belongs in here, too, but it's been around longer */
|
||||
|
||||
#endif /* PNG_EASY_ACCESS_SUPPORTED */
|
||||
|
||||
png_byte PNGAPI
|
||||
png_get_channels(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
return(info_ptr->channels);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
png_bytep PNGAPI
|
||||
png_get_signature(png_structp png_ptr, png_infop info_ptr)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL)
|
||||
return(info_ptr->signature);
|
||||
else
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
#if defined(PNG_bKGD_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_bKGD(png_structp png_ptr, png_infop info_ptr,
|
||||
png_color_16p *background)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)
|
||||
&& background != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "bKGD");
|
||||
*background = &(info_ptr->background);
|
||||
return (PNG_INFO_bKGD);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_cHRM_SUPPORTED)
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_cHRM(png_structp png_ptr, png_infop info_ptr,
|
||||
double *white_x, double *white_y, double *red_x, double *red_y,
|
||||
double *green_x, double *green_y, double *blue_x, double *blue_y)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "cHRM");
|
||||
if (white_x != NULL)
|
||||
*white_x = (double)info_ptr->x_white;
|
||||
if (white_y != NULL)
|
||||
*white_y = (double)info_ptr->y_white;
|
||||
if (red_x != NULL)
|
||||
*red_x = (double)info_ptr->x_red;
|
||||
if (red_y != NULL)
|
||||
*red_y = (double)info_ptr->y_red;
|
||||
if (green_x != NULL)
|
||||
*green_x = (double)info_ptr->x_green;
|
||||
if (green_y != NULL)
|
||||
*green_y = (double)info_ptr->y_green;
|
||||
if (blue_x != NULL)
|
||||
*blue_x = (double)info_ptr->x_blue;
|
||||
if (blue_y != NULL)
|
||||
*blue_y = (double)info_ptr->y_blue;
|
||||
return (PNG_INFO_cHRM);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
|
||||
png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
|
||||
png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
|
||||
png_fixed_point *blue_x, png_fixed_point *blue_y)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "cHRM");
|
||||
if (white_x != NULL)
|
||||
*white_x = info_ptr->int_x_white;
|
||||
if (white_y != NULL)
|
||||
*white_y = info_ptr->int_y_white;
|
||||
if (red_x != NULL)
|
||||
*red_x = info_ptr->int_x_red;
|
||||
if (red_y != NULL)
|
||||
*red_y = info_ptr->int_y_red;
|
||||
if (green_x != NULL)
|
||||
*green_x = info_ptr->int_x_green;
|
||||
if (green_y != NULL)
|
||||
*green_y = info_ptr->int_y_green;
|
||||
if (blue_x != NULL)
|
||||
*blue_x = info_ptr->int_x_blue;
|
||||
if (blue_y != NULL)
|
||||
*blue_y = info_ptr->int_y_blue;
|
||||
return (PNG_INFO_cHRM);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PNG_gAMA_SUPPORTED)
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
|
||||
&& file_gamma != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "gAMA");
|
||||
*file_gamma = (double)info_ptr->gamma;
|
||||
return (PNG_INFO_gAMA);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
|
||||
png_fixed_point *int_file_gamma)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
|
||||
&& int_file_gamma != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "gAMA");
|
||||
*int_file_gamma = info_ptr->int_gamma;
|
||||
return (PNG_INFO_gAMA);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PNG_sRGB_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)
|
||||
&& file_srgb_intent != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "sRGB");
|
||||
*file_srgb_intent = (int)info_ptr->srgb_intent;
|
||||
return (PNG_INFO_sRGB);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_iCCP_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_iCCP(png_structp png_ptr, png_infop info_ptr,
|
||||
png_charpp name, int *compression_type,
|
||||
png_charpp profile, png_uint_32 *proflen)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
|
||||
&& name != NULL && profile != NULL && proflen != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "iCCP");
|
||||
*name = info_ptr->iccp_name;
|
||||
*profile = info_ptr->iccp_profile;
|
||||
/* compression_type is a dummy so the API won't have to change
|
||||
if we introduce multiple compression types later. */
|
||||
*proflen = (int)info_ptr->iccp_proflen;
|
||||
*compression_type = (int)info_ptr->iccp_compression;
|
||||
return (PNG_INFO_iCCP);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_sPLT_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_sPLT(png_structp png_ptr, png_infop info_ptr,
|
||||
png_sPLT_tpp spalettes)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
|
||||
{
|
||||
*spalettes = info_ptr->splt_palettes;
|
||||
return ((png_uint_32)info_ptr->splt_palettes_num);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_hIST_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)
|
||||
&& hist != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "hIST");
|
||||
*hist = info_ptr->hist;
|
||||
return (PNG_INFO_hIST);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
|
||||
png_uint_32 *width, png_uint_32 *height, int *bit_depth,
|
||||
int *color_type, int *interlace_type, int *compression_type,
|
||||
int *filter_type)
|
||||
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && width != NULL && height != NULL &&
|
||||
bit_depth != NULL && color_type != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "IHDR");
|
||||
*width = info_ptr->width;
|
||||
*height = info_ptr->height;
|
||||
*bit_depth = info_ptr->bit_depth;
|
||||
if (info_ptr->bit_depth < 1 || info_ptr->bit_depth > 16)
|
||||
png_error(png_ptr, "Invalid bit depth");
|
||||
*color_type = info_ptr->color_type;
|
||||
if (info_ptr->color_type > 6)
|
||||
png_error(png_ptr, "Invalid color type");
|
||||
if (compression_type != NULL)
|
||||
*compression_type = info_ptr->compression_type;
|
||||
if (filter_type != NULL)
|
||||
*filter_type = info_ptr->filter_type;
|
||||
if (interlace_type != NULL)
|
||||
*interlace_type = info_ptr->interlace_type;
|
||||
|
||||
/* check for potential overflow of rowbytes */
|
||||
if (*width == 0 || *width > PNG_UINT_31_MAX)
|
||||
png_error(png_ptr, "Invalid image width");
|
||||
if (*height == 0 || *height > PNG_UINT_31_MAX)
|
||||
png_error(png_ptr, "Invalid image height");
|
||||
if (info_ptr->width > (PNG_UINT_32_MAX
|
||||
>> 3) /* 8-byte RGBA pixels */
|
||||
- 64 /* bigrowbuf hack */
|
||||
- 1 /* filter byte */
|
||||
- 7*8 /* rounding of width to multiple of 8 pixels */
|
||||
- 8) /* extra max_pixel_depth pad */
|
||||
{
|
||||
png_warning(png_ptr,
|
||||
"Width too large for libpng to process image data.");
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(PNG_oFFs_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_oFFs(png_structp png_ptr, png_infop info_ptr,
|
||||
png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)
|
||||
&& offset_x != NULL && offset_y != NULL && unit_type != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "oFFs");
|
||||
*offset_x = info_ptr->x_offset;
|
||||
*offset_y = info_ptr->y_offset;
|
||||
*unit_type = (int)info_ptr->offset_unit_type;
|
||||
return (PNG_INFO_oFFs);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_pCAL_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_pCAL(png_structp png_ptr, png_infop info_ptr,
|
||||
png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
|
||||
png_charp *units, png_charpp *params)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)
|
||||
&& purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
|
||||
nparams != NULL && units != NULL && params != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "pCAL");
|
||||
*purpose = info_ptr->pcal_purpose;
|
||||
*X0 = info_ptr->pcal_X0;
|
||||
*X1 = info_ptr->pcal_X1;
|
||||
*type = (int)info_ptr->pcal_type;
|
||||
*nparams = (int)info_ptr->pcal_nparams;
|
||||
*units = info_ptr->pcal_units;
|
||||
*params = info_ptr->pcal_params;
|
||||
return (PNG_INFO_pCAL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_sCAL_SUPPORTED)
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_sCAL(png_structp png_ptr, png_infop info_ptr,
|
||||
int *unit, double *width, double *height)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL &&
|
||||
(info_ptr->valid & PNG_INFO_sCAL))
|
||||
{
|
||||
*unit = info_ptr->scal_unit;
|
||||
*width = info_ptr->scal_pixel_width;
|
||||
*height = info_ptr->scal_pixel_height;
|
||||
return (PNG_INFO_sCAL);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
#else
|
||||
#ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr,
|
||||
int *unit, png_charpp width, png_charpp height)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL &&
|
||||
(info_ptr->valid & PNG_INFO_sCAL))
|
||||
{
|
||||
*unit = info_ptr->scal_unit;
|
||||
*width = info_ptr->scal_s_width;
|
||||
*height = info_ptr->scal_s_height;
|
||||
return (PNG_INFO_sCAL);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PNG_pHYs_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_pHYs(png_structp png_ptr, png_infop info_ptr,
|
||||
png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
|
||||
{
|
||||
png_uint_32 retval = 0;
|
||||
|
||||
if (png_ptr != NULL && info_ptr != NULL &&
|
||||
(info_ptr->valid & PNG_INFO_pHYs))
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "pHYs");
|
||||
if (res_x != NULL)
|
||||
{
|
||||
*res_x = info_ptr->x_pixels_per_unit;
|
||||
retval |= PNG_INFO_pHYs;
|
||||
}
|
||||
if (res_y != NULL)
|
||||
{
|
||||
*res_y = info_ptr->y_pixels_per_unit;
|
||||
retval |= PNG_INFO_pHYs;
|
||||
}
|
||||
if (unit_type != NULL)
|
||||
{
|
||||
*unit_type = (int)info_ptr->phys_unit_type;
|
||||
retval |= PNG_INFO_pHYs;
|
||||
}
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
#endif
|
||||
|
||||
png_uint_32 PNGAPI
|
||||
png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette,
|
||||
int *num_palette)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE)
|
||||
&& palette != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "PLTE");
|
||||
*palette = info_ptr->palette;
|
||||
*num_palette = info_ptr->num_palette;
|
||||
png_debug1(3, "num_palette = %d\n", *num_palette);
|
||||
return (PNG_INFO_PLTE);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined(PNG_sBIT_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)
|
||||
&& sig_bit != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "sBIT");
|
||||
*sig_bit = &(info_ptr->sig_bit);
|
||||
return (PNG_INFO_sBIT);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_TEXT_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr,
|
||||
int *num_text)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n",
|
||||
(png_ptr->chunk_name[0] == '\0' ? "text"
|
||||
: (png_const_charp)png_ptr->chunk_name));
|
||||
if (text_ptr != NULL)
|
||||
*text_ptr = info_ptr->text;
|
||||
if (num_text != NULL)
|
||||
*num_text = info_ptr->num_text;
|
||||
return ((png_uint_32)info_ptr->num_text);
|
||||
}
|
||||
if (num_text != NULL)
|
||||
*num_text = 0;
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_tIME_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)
|
||||
&& mod_time != NULL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "tIME");
|
||||
*mod_time = &(info_ptr->mod_time);
|
||||
return (PNG_INFO_tIME);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_tRNS_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
|
||||
png_bytep *trans, int *num_trans, png_color_16p *trans_values)
|
||||
{
|
||||
png_uint_32 retval = 0;
|
||||
if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function\n", "tRNS");
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
{
|
||||
if (trans != NULL)
|
||||
{
|
||||
*trans = info_ptr->trans;
|
||||
retval |= PNG_INFO_tRNS;
|
||||
}
|
||||
if (trans_values != NULL)
|
||||
*trans_values = &(info_ptr->trans_values);
|
||||
}
|
||||
else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */
|
||||
{
|
||||
if (trans_values != NULL)
|
||||
{
|
||||
*trans_values = &(info_ptr->trans_values);
|
||||
retval |= PNG_INFO_tRNS;
|
||||
}
|
||||
if(trans != NULL)
|
||||
*trans = NULL;
|
||||
}
|
||||
if(num_trans != NULL)
|
||||
{
|
||||
*num_trans = info_ptr->num_trans;
|
||||
retval |= PNG_INFO_tRNS;
|
||||
}
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
|
||||
png_uint_32 PNGAPI
|
||||
png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr,
|
||||
png_unknown_chunkpp unknowns)
|
||||
{
|
||||
if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
|
||||
{
|
||||
*unknowns = info_ptr->unknown_chunks;
|
||||
return ((png_uint_32)info_ptr->unknown_chunks_num);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
|
||||
png_byte PNGAPI
|
||||
png_get_rgb_to_gray_status (png_structp png_ptr)
|
||||
{
|
||||
return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_USER_CHUNKS_SUPPORTED)
|
||||
png_voidp PNGAPI
|
||||
png_get_user_chunk_ptr(png_structp png_ptr)
|
||||
{
|
||||
return (png_ptr? png_ptr->user_chunk_ptr : NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_compression_buffer_size(png_structp png_ptr)
|
||||
{
|
||||
return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
|
||||
#ifndef PNG_1_0_X
|
||||
/* this function was added to libpng 1.2.0 and should exist by default */
|
||||
png_uint_32 PNGAPI
|
||||
png_get_asm_flags (png_structp png_ptr)
|
||||
{
|
||||
/* obsolete, to be removed from libpng-1.4.0 */
|
||||
return (png_ptr? 0L: 0L);
|
||||
}
|
||||
|
||||
/* this function was added to libpng 1.2.0 and should exist by default */
|
||||
png_uint_32 PNGAPI
|
||||
png_get_asm_flagmask (int flag_select)
|
||||
{
|
||||
/* obsolete, to be removed from libpng-1.4.0 */
|
||||
flag_select=flag_select;
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */
|
||||
/* this function was added to libpng 1.2.0 */
|
||||
png_uint_32 PNGAPI
|
||||
png_get_mmx_flagmask (int flag_select, int *compilerID)
|
||||
{
|
||||
/* obsolete, to be removed from libpng-1.4.0 */
|
||||
flag_select=flag_select;
|
||||
*compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */
|
||||
return 0L;
|
||||
}
|
||||
|
||||
/* this function was added to libpng 1.2.0 */
|
||||
png_byte PNGAPI
|
||||
png_get_mmx_bitdepth_threshold (png_structp png_ptr)
|
||||
{
|
||||
/* obsolete, to be removed from libpng-1.4.0 */
|
||||
return (png_ptr? 0: 0);
|
||||
}
|
||||
|
||||
/* this function was added to libpng 1.2.0 */
|
||||
png_uint_32 PNGAPI
|
||||
png_get_mmx_rowbytes_threshold (png_structp png_ptr)
|
||||
{
|
||||
/* obsolete, to be removed from libpng-1.4.0 */
|
||||
return (png_ptr? 0L: 0L);
|
||||
}
|
||||
#endif /* ?PNG_1_0_X */
|
||||
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
/* these functions were added to libpng 1.2.6 */
|
||||
png_uint_32 PNGAPI
|
||||
png_get_user_width_max (png_structp png_ptr)
|
||||
{
|
||||
return (png_ptr? png_ptr->user_width_max : 0);
|
||||
}
|
||||
png_uint_32 PNGAPI
|
||||
png_get_user_height_max (png_structp png_ptr)
|
||||
{
|
||||
return (png_ptr? png_ptr->user_height_max : 0);
|
||||
}
|
||||
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
|
||||
|
||||
|
||||
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|
||||
Vendored
+608
@@ -0,0 +1,608 @@
|
||||
|
||||
/* pngmem.c - stub functions for memory allocation
|
||||
*
|
||||
* Last changed in libpng 1.2.13 November 13, 2006
|
||||
* For conditions of distribution and use, see copyright notice in png.h
|
||||
* Copyright (c) 1998-2006 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This file provides a location for all memory allocation. Users who
|
||||
* need special memory handling are expected to supply replacement
|
||||
* functions for png_malloc() and png_free(), and to use
|
||||
* png_create_read_struct_2() and png_create_write_struct_2() to
|
||||
* identify the replacement functions.
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
|
||||
/* Borland DOS special memory handler */
|
||||
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
|
||||
/* if you change this, be sure to change the one in png.h also */
|
||||
|
||||
/* Allocate memory for a png_struct. The malloc and memset can be replaced
|
||||
by a single call to calloc() if this is thought to improve performance. */
|
||||
png_voidp /* PRIVATE */
|
||||
png_create_struct(int type)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
|
||||
}
|
||||
|
||||
/* Alternate version of png_create_struct, for use with user-defined malloc. */
|
||||
png_voidp /* PRIVATE */
|
||||
png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
|
||||
{
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
png_size_t size;
|
||||
png_voidp struct_ptr;
|
||||
|
||||
if (type == PNG_STRUCT_INFO)
|
||||
size = png_sizeof(png_info);
|
||||
else if (type == PNG_STRUCT_PNG)
|
||||
size = png_sizeof(png_struct);
|
||||
else
|
||||
return (png_get_copyright(NULL));
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if(malloc_fn != NULL)
|
||||
{
|
||||
png_struct dummy_struct;
|
||||
png_structp png_ptr = &dummy_struct;
|
||||
png_ptr->mem_ptr=mem_ptr;
|
||||
struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size);
|
||||
}
|
||||
else
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
struct_ptr = (png_voidp)farmalloc(size);
|
||||
if (struct_ptr != NULL)
|
||||
png_memset(struct_ptr, 0, size);
|
||||
return (struct_ptr);
|
||||
}
|
||||
|
||||
/* Free memory allocated by a png_create_struct() call */
|
||||
void /* PRIVATE */
|
||||
png_destroy_struct(png_voidp struct_ptr)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
|
||||
}
|
||||
|
||||
/* Free memory allocated by a png_create_struct() call */
|
||||
void /* PRIVATE */
|
||||
png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
|
||||
png_voidp mem_ptr)
|
||||
{
|
||||
#endif
|
||||
if (struct_ptr != NULL)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if(free_fn != NULL)
|
||||
{
|
||||
png_struct dummy_struct;
|
||||
png_structp png_ptr = &dummy_struct;
|
||||
png_ptr->mem_ptr=mem_ptr;
|
||||
(*(free_fn))(png_ptr, struct_ptr);
|
||||
return;
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
farfree (struct_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate memory. For reasonable files, size should never exceed
|
||||
* 64K. However, zlib may allocate more then 64K if you don't tell
|
||||
* it not to. See zconf.h and png.h for more information. zlib does
|
||||
* need to allocate exactly 64K, so whatever you call here must
|
||||
* have the ability to do that.
|
||||
*
|
||||
* Borland seems to have a problem in DOS mode for exactly 64K.
|
||||
* It gives you a segment with an offset of 8 (perhaps to store its
|
||||
* memory stuff). zlib doesn't like this at all, so we have to
|
||||
* detect and deal with it. This code should not be needed in
|
||||
* Windows or OS/2 modes, and only in 16 bit mode. This code has
|
||||
* been updated by Alexander Lehmann for version 0.89 to waste less
|
||||
* memory.
|
||||
*
|
||||
* Note that we can't use png_size_t for the "size" declaration,
|
||||
* since on some systems a png_size_t is a 16-bit quantity, and as a
|
||||
* result, we would be truncating potentially larger memory requests
|
||||
* (which should cause a fatal error) and introducing major problems.
|
||||
*/
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_malloc(png_structp png_ptr, png_uint_32 size)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
if (png_ptr == NULL || size == 0)
|
||||
return (NULL);
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if(png_ptr->malloc_fn != NULL)
|
||||
ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
|
||||
else
|
||||
ret = (png_malloc_default(png_ptr, size));
|
||||
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of memory!");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_malloc_default(png_structp png_ptr, png_uint_32 size)
|
||||
{
|
||||
png_voidp ret;
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
if (png_ptr == NULL || size == 0)
|
||||
return (NULL);
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
{
|
||||
png_warning(png_ptr, "Cannot Allocate > 64K");
|
||||
ret = NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (size != (size_t)size)
|
||||
ret = NULL;
|
||||
else if (size == (png_uint_32)65536L)
|
||||
{
|
||||
if (png_ptr->offset_table == NULL)
|
||||
{
|
||||
/* try to see if we need to do any of this fancy stuff */
|
||||
ret = farmalloc(size);
|
||||
if (ret == NULL || ((png_size_t)ret & 0xffff))
|
||||
{
|
||||
int num_blocks;
|
||||
png_uint_32 total_size;
|
||||
png_bytep table;
|
||||
int i;
|
||||
png_byte huge * hptr;
|
||||
|
||||
if (ret != NULL)
|
||||
{
|
||||
farfree(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
if(png_ptr->zlib_window_bits > 14)
|
||||
num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
|
||||
else
|
||||
num_blocks = 1;
|
||||
if (png_ptr->zlib_mem_level >= 7)
|
||||
num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
|
||||
else
|
||||
num_blocks++;
|
||||
|
||||
total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
|
||||
|
||||
table = farmalloc(total_size);
|
||||
|
||||
if (table == NULL)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out Of Memory."); /* Note "O" and "M" */
|
||||
else
|
||||
png_warning(png_ptr, "Out Of Memory.");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((png_size_t)table & 0xfff0)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr,
|
||||
"Farmalloc didn't return normalized pointer");
|
||||
else
|
||||
png_warning(png_ptr,
|
||||
"Farmalloc didn't return normalized pointer");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
png_ptr->offset_table = table;
|
||||
png_ptr->offset_table_ptr = farmalloc(num_blocks *
|
||||
png_sizeof (png_bytep));
|
||||
|
||||
if (png_ptr->offset_table_ptr == NULL)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out Of memory."); /* Note "O" and "M" */
|
||||
else
|
||||
png_warning(png_ptr, "Out Of memory.");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
hptr = (png_byte huge *)table;
|
||||
if ((png_size_t)hptr & 0xf)
|
||||
{
|
||||
hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
|
||||
hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */
|
||||
}
|
||||
for (i = 0; i < num_blocks; i++)
|
||||
{
|
||||
png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
|
||||
hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */
|
||||
}
|
||||
|
||||
png_ptr->offset_table_number = num_blocks;
|
||||
png_ptr->offset_table_count = 0;
|
||||
png_ptr->offset_table_count_free = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */
|
||||
else
|
||||
png_warning(png_ptr, "Out of Memory.");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
|
||||
}
|
||||
else
|
||||
ret = farmalloc(size);
|
||||
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if (ret == NULL)
|
||||
{
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
|
||||
else
|
||||
png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */
|
||||
}
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* free a pointer allocated by png_malloc(). In the default
|
||||
configuration, png_ptr is not used, but is passed in case it
|
||||
is needed. If ptr is NULL, return without taking any action. */
|
||||
void PNGAPI
|
||||
png_free(png_structp png_ptr, png_voidp ptr)
|
||||
{
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr->free_fn != NULL)
|
||||
{
|
||||
(*(png_ptr->free_fn))(png_ptr, ptr);
|
||||
return;
|
||||
}
|
||||
else png_free_default(png_ptr, ptr);
|
||||
}
|
||||
|
||||
void PNGAPI
|
||||
png_free_default(png_structp png_ptr, png_voidp ptr)
|
||||
{
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
if(png_ptr == NULL) return;
|
||||
|
||||
if (png_ptr->offset_table != NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < png_ptr->offset_table_count; i++)
|
||||
{
|
||||
if (ptr == png_ptr->offset_table_ptr[i])
|
||||
{
|
||||
ptr = NULL;
|
||||
png_ptr->offset_table_count_free++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
|
||||
{
|
||||
farfree(png_ptr->offset_table);
|
||||
farfree(png_ptr->offset_table_ptr);
|
||||
png_ptr->offset_table = NULL;
|
||||
png_ptr->offset_table_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr != NULL)
|
||||
{
|
||||
farfree(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* Not the Borland DOS special memory handler */
|
||||
|
||||
/* Allocate memory for a png_struct or a png_info. The malloc and
|
||||
memset can be replaced by a single call to calloc() if this is thought
|
||||
to improve performance noticably. */
|
||||
png_voidp /* PRIVATE */
|
||||
png_create_struct(int type)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
|
||||
}
|
||||
|
||||
/* Allocate memory for a png_struct or a png_info. The malloc and
|
||||
memset can be replaced by a single call to calloc() if this is thought
|
||||
to improve performance noticably. */
|
||||
png_voidp /* PRIVATE */
|
||||
png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
|
||||
{
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
png_size_t size;
|
||||
png_voidp struct_ptr;
|
||||
|
||||
if (type == PNG_STRUCT_INFO)
|
||||
size = png_sizeof(png_info);
|
||||
else if (type == PNG_STRUCT_PNG)
|
||||
size = png_sizeof(png_struct);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if(malloc_fn != NULL)
|
||||
{
|
||||
png_struct dummy_struct;
|
||||
png_structp png_ptr = &dummy_struct;
|
||||
png_ptr->mem_ptr=mem_ptr;
|
||||
struct_ptr = (*(malloc_fn))(png_ptr, size);
|
||||
if (struct_ptr != NULL)
|
||||
png_memset(struct_ptr, 0, size);
|
||||
return (struct_ptr);
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
struct_ptr = (png_voidp)farmalloc(size);
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
struct_ptr = (png_voidp)halloc(size,1);
|
||||
# else
|
||||
struct_ptr = (png_voidp)malloc(size);
|
||||
# endif
|
||||
#endif
|
||||
if (struct_ptr != NULL)
|
||||
png_memset(struct_ptr, 0, size);
|
||||
|
||||
return (struct_ptr);
|
||||
}
|
||||
|
||||
|
||||
/* Free memory allocated by a png_create_struct() call */
|
||||
void /* PRIVATE */
|
||||
png_destroy_struct(png_voidp struct_ptr)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
|
||||
}
|
||||
|
||||
/* Free memory allocated by a png_create_struct() call */
|
||||
void /* PRIVATE */
|
||||
png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
|
||||
png_voidp mem_ptr)
|
||||
{
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
if (struct_ptr != NULL)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if(free_fn != NULL)
|
||||
{
|
||||
png_struct dummy_struct;
|
||||
png_structp png_ptr = &dummy_struct;
|
||||
png_ptr->mem_ptr=mem_ptr;
|
||||
(*(free_fn))(png_ptr, struct_ptr);
|
||||
return;
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
farfree(struct_ptr);
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
hfree(struct_ptr);
|
||||
# else
|
||||
free(struct_ptr);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate memory. For reasonable files, size should never exceed
|
||||
64K. However, zlib may allocate more then 64K if you don't tell
|
||||
it not to. See zconf.h and png.h for more information. zlib does
|
||||
need to allocate exactly 64K, so whatever you call here must
|
||||
have the ability to do that. */
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_malloc(png_structp png_ptr, png_uint_32 size)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr == NULL || size == 0)
|
||||
return (NULL);
|
||||
|
||||
if(png_ptr->malloc_fn != NULL)
|
||||
ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
|
||||
else
|
||||
ret = (png_malloc_default(png_ptr, size));
|
||||
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of Memory!");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_malloc_default(png_structp png_ptr, png_uint_32 size)
|
||||
{
|
||||
png_voidp ret;
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
if (png_ptr == NULL || size == 0)
|
||||
return (NULL);
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if(png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Cannot Allocate > 64K");
|
||||
else
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for overflow */
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
if (size != (unsigned long)size)
|
||||
ret = NULL;
|
||||
else
|
||||
ret = farmalloc(size);
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
if (size != (unsigned long)size)
|
||||
ret = NULL;
|
||||
else
|
||||
ret = halloc(size, 1);
|
||||
# else
|
||||
if (size != (size_t)size)
|
||||
ret = NULL;
|
||||
else
|
||||
ret = malloc((size_t)size);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Free a pointer allocated by png_malloc(). If ptr is NULL, return
|
||||
without taking any action. */
|
||||
void PNGAPI
|
||||
png_free(png_structp png_ptr, png_voidp ptr)
|
||||
{
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr->free_fn != NULL)
|
||||
{
|
||||
(*(png_ptr->free_fn))(png_ptr, ptr);
|
||||
return;
|
||||
}
|
||||
else png_free_default(png_ptr, ptr);
|
||||
}
|
||||
void PNGAPI
|
||||
png_free_default(png_structp png_ptr, png_voidp ptr)
|
||||
{
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
farfree(ptr);
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
hfree(ptr);
|
||||
# else
|
||||
free(ptr);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* Not Borland DOS special memory handler */
|
||||
|
||||
#if defined(PNG_1_0_X)
|
||||
# define png_malloc_warn png_malloc
|
||||
#else
|
||||
/* This function was added at libpng version 1.2.3. The png_malloc_warn()
|
||||
* function will set up png_malloc() to issue a png_warning and return NULL
|
||||
* instead of issuing a png_error, if it fails to allocate the requested
|
||||
* memory.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_malloc_warn(png_structp png_ptr, png_uint_32 size)
|
||||
{
|
||||
png_voidp ptr;
|
||||
png_uint_32 save_flags;
|
||||
if(png_ptr == NULL) return (NULL);
|
||||
|
||||
save_flags=png_ptr->flags;
|
||||
png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
|
||||
ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
|
||||
png_ptr->flags=save_flags;
|
||||
return(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
|
||||
png_uint_32 length)
|
||||
{
|
||||
png_size_t size;
|
||||
|
||||
size = (png_size_t)length;
|
||||
if ((png_uint_32)size != length)
|
||||
png_error(png_ptr,"Overflow in png_memcpy_check.");
|
||||
|
||||
return(png_memcpy (s1, s2, size));
|
||||
}
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_memset_check (png_structp png_ptr, png_voidp s1, int value,
|
||||
png_uint_32 length)
|
||||
{
|
||||
png_size_t size;
|
||||
|
||||
size = (png_size_t)length;
|
||||
if ((png_uint_32)size != length)
|
||||
png_error(png_ptr,"Overflow in png_memset_check.");
|
||||
|
||||
return (png_memset (s1, value, size));
|
||||
|
||||
}
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
/* This function is called when the application wants to use another method
|
||||
* of allocating and freeing memory.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
|
||||
malloc_fn, png_free_ptr free_fn)
|
||||
{
|
||||
if(png_ptr != NULL) {
|
||||
png_ptr->mem_ptr = mem_ptr;
|
||||
png_ptr->malloc_fn = malloc_fn;
|
||||
png_ptr->free_fn = free_fn;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function returns a pointer to the mem_ptr associated with the user
|
||||
* functions. The application should free any memory associated with this
|
||||
* pointer before png_write_destroy and png_read_destroy are called.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_get_mem_ptr(png_structp png_ptr)
|
||||
{
|
||||
if(png_ptr == NULL) return (NULL);
|
||||
return ((png_voidp)png_ptr->mem_ptr);
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|
||||
Vendored
+1586
File diff suppressed because it is too large
Load Diff
Vendored
+1473
File diff suppressed because it is too large
Load Diff
Vendored
+167
@@ -0,0 +1,167 @@
|
||||
|
||||
/* pngrio.c - functions for data input
|
||||
*
|
||||
* Last changed in libpng 1.2.13 November 13, 2006
|
||||
* For conditions of distribution and use, see copyright notice in png.h
|
||||
* Copyright (c) 1998-2006 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This file provides a location for all input. Users who need
|
||||
* special handling are expected to write a function that has the same
|
||||
* arguments as this and performs a similar function, but that possibly
|
||||
* has a different input method. Note that you shouldn't change this
|
||||
* function, but rather write a replacement function and then make
|
||||
* libpng use it at run time with png_set_read_fn(...).
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED)
|
||||
|
||||
/* Read the data from whatever input you are using. The default routine
|
||||
reads from a file pointer. Note that this routine sometimes gets called
|
||||
with very small lengths, so you should implement some kind of simple
|
||||
buffering if you are using unbuffered reads. This should never be asked
|
||||
to read more then 64K on a 16 bit machine. */
|
||||
void /* PRIVATE */
|
||||
png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_debug1(4,"reading %d bytes\n", (int)length);
|
||||
if (png_ptr->read_data_fn != NULL)
|
||||
(*(png_ptr->read_data_fn))(png_ptr, data, length);
|
||||
else
|
||||
png_error(png_ptr, "Call to NULL read function");
|
||||
}
|
||||
|
||||
#if !defined(PNG_NO_STDIO)
|
||||
/* This is the function that does the actual reading of data. If you are
|
||||
not reading from a standard C stream, you should create a replacement
|
||||
read_data function and use it at run time with png_set_read_fn(), rather
|
||||
than changing the library. */
|
||||
#ifndef USE_FAR_KEYWORD
|
||||
void PNGAPI
|
||||
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_size_t check;
|
||||
|
||||
if(png_ptr == NULL) return;
|
||||
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
|
||||
* instead of an int, which is what fread() actually returns.
|
||||
*/
|
||||
#if defined(_WIN32_WCE)
|
||||
if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
|
||||
check = 0;
|
||||
#else
|
||||
check = (png_size_t)fread(data, (png_size_t)1, length,
|
||||
(png_FILE_p)png_ptr->io_ptr);
|
||||
#endif
|
||||
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Read Error");
|
||||
}
|
||||
#else
|
||||
/* this is the model-independent version. Since the standard I/O library
|
||||
can't handle far buffers in the medium and small models, we have to copy
|
||||
the data.
|
||||
*/
|
||||
|
||||
#define NEAR_BUF_SIZE 1024
|
||||
#define MIN(a,b) (a <= b ? a : b)
|
||||
|
||||
static void PNGAPI
|
||||
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
int check;
|
||||
png_byte *n_data;
|
||||
png_FILE_p io_ptr;
|
||||
|
||||
if(png_ptr == NULL) return;
|
||||
/* Check if data really is near. If so, use usual code. */
|
||||
n_data = (png_byte *)CVT_PTR_NOCHECK(data);
|
||||
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
|
||||
if ((png_bytep)n_data == data)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
|
||||
check = 0;
|
||||
#else
|
||||
check = fread(n_data, 1, length, io_ptr);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
png_byte buf[NEAR_BUF_SIZE];
|
||||
png_size_t read, remaining, err;
|
||||
check = 0;
|
||||
remaining = length;
|
||||
do
|
||||
{
|
||||
read = MIN(NEAR_BUF_SIZE, remaining);
|
||||
#if defined(_WIN32_WCE)
|
||||
if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) )
|
||||
err = 0;
|
||||
#else
|
||||
err = fread(buf, (png_size_t)1, read, io_ptr);
|
||||
#endif
|
||||
png_memcpy(data, buf, read); /* copy far buffer to near buffer */
|
||||
if(err != read)
|
||||
break;
|
||||
else
|
||||
check += err;
|
||||
data += read;
|
||||
remaining -= read;
|
||||
}
|
||||
while (remaining != 0);
|
||||
}
|
||||
if ((png_uint_32)check != (png_uint_32)length)
|
||||
png_error(png_ptr, "read Error");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This function allows the application to supply a new input function
|
||||
for libpng if standard C streams aren't being used.
|
||||
|
||||
This function takes as its arguments:
|
||||
png_ptr - pointer to a png input data structure
|
||||
io_ptr - pointer to user supplied structure containing info about
|
||||
the input functions. May be NULL.
|
||||
read_data_fn - pointer to a new input function that takes as its
|
||||
arguments a pointer to a png_struct, a pointer to
|
||||
a location where input data can be stored, and a 32-bit
|
||||
unsigned int that is the number of bytes to be read.
|
||||
To exit and output any fatal error messages the new write
|
||||
function should call png_error(png_ptr, "Error msg"). */
|
||||
void PNGAPI
|
||||
png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
|
||||
png_rw_ptr read_data_fn)
|
||||
{
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->io_ptr = io_ptr;
|
||||
|
||||
#if !defined(PNG_NO_STDIO)
|
||||
if (read_data_fn != NULL)
|
||||
png_ptr->read_data_fn = read_data_fn;
|
||||
else
|
||||
png_ptr->read_data_fn = png_default_read_data;
|
||||
#else
|
||||
png_ptr->read_data_fn = read_data_fn;
|
||||
#endif
|
||||
|
||||
/* It is an error to write to a read device */
|
||||
if (png_ptr->write_data_fn != NULL)
|
||||
{
|
||||
png_ptr->write_data_fn = NULL;
|
||||
png_warning(png_ptr,
|
||||
"It's an error to set both read_data_fn and write_data_fn in the ");
|
||||
png_warning(png_ptr,
|
||||
"same structure. Resetting write_data_fn to NULL.");
|
||||
}
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
png_ptr->output_flush_fn = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif /* PNG_READ_SUPPORTED */
|
||||
Vendored
+4284
File diff suppressed because it is too large
Load Diff
Vendored
+3164
File diff suppressed because it is too large
Load Diff
Vendored
+1250
File diff suppressed because it is too large
Load Diff
Vendored
+1556
File diff suppressed because it is too large
Load Diff
Vendored
+662
@@ -0,0 +1,662 @@
|
||||
|
||||
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
|
||||
*
|
||||
* Last changed in libpng 1.2.17 May 15, 2007
|
||||
* For conditions of distribution and use, see copyright notice in png.h
|
||||
* Copyright (c) 1998-2007 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
|
||||
/* turn on BGR-to-RGB mapping */
|
||||
void PNGAPI
|
||||
png_set_bgr(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_bgr\n");
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->transformations |= PNG_BGR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
|
||||
/* turn on 16 bit byte swapping */
|
||||
void PNGAPI
|
||||
png_set_swap(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_swap\n");
|
||||
if(png_ptr == NULL) return;
|
||||
if (png_ptr->bit_depth == 16)
|
||||
png_ptr->transformations |= PNG_SWAP_BYTES;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
|
||||
/* turn on pixel packing */
|
||||
void PNGAPI
|
||||
png_set_packing(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_packing\n");
|
||||
if(png_ptr == NULL) return;
|
||||
if (png_ptr->bit_depth < 8)
|
||||
{
|
||||
png_ptr->transformations |= PNG_PACK;
|
||||
png_ptr->usr_bit_depth = 8;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
|
||||
/* turn on packed pixel swapping */
|
||||
void PNGAPI
|
||||
png_set_packswap(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_packswap\n");
|
||||
if(png_ptr == NULL) return;
|
||||
if (png_ptr->bit_depth < 8)
|
||||
png_ptr->transformations |= PNG_PACKSWAP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_shift(png_structp png_ptr, png_color_8p true_bits)
|
||||
{
|
||||
png_debug(1, "in png_set_shift\n");
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->transformations |= PNG_SHIFT;
|
||||
png_ptr->shift = *true_bits;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
|
||||
defined(PNG_WRITE_INTERLACING_SUPPORTED)
|
||||
int PNGAPI
|
||||
png_set_interlace_handling(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_interlace handling\n");
|
||||
if (png_ptr && png_ptr->interlaced)
|
||||
{
|
||||
png_ptr->transformations |= PNG_INTERLACE;
|
||||
return (7);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
|
||||
/* Add a filler byte on read, or remove a filler or alpha byte on write.
|
||||
* The filler type has changed in v0.95 to allow future 2-byte fillers
|
||||
* for 48-bit input data, as well as to avoid problems with some compilers
|
||||
* that don't like bytes as parameters.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
|
||||
{
|
||||
png_debug(1, "in png_set_filler\n");
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->transformations |= PNG_FILLER;
|
||||
png_ptr->filler = (png_byte)filler;
|
||||
if (filler_loc == PNG_FILLER_AFTER)
|
||||
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
|
||||
else
|
||||
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
|
||||
|
||||
/* This should probably go in the "do_read_filler" routine.
|
||||
* I attempted to do that in libpng-1.0.1a but that caused problems
|
||||
* so I restored it in libpng-1.0.2a
|
||||
*/
|
||||
|
||||
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
|
||||
{
|
||||
png_ptr->usr_channels = 4;
|
||||
}
|
||||
|
||||
/* Also I added this in libpng-1.0.2a (what happens when we expand
|
||||
* a less-than-8-bit grayscale to GA? */
|
||||
|
||||
if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
|
||||
{
|
||||
png_ptr->usr_channels = 2;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(PNG_1_0_X)
|
||||
/* Added to libpng-1.2.7 */
|
||||
void PNGAPI
|
||||
png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
|
||||
{
|
||||
png_debug(1, "in png_set_add_alpha\n");
|
||||
if(png_ptr == NULL) return;
|
||||
png_set_filler(png_ptr, filler, filler_loc);
|
||||
png_ptr->transformations |= PNG_ADD_ALPHA;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
|
||||
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_swap_alpha(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_swap_alpha\n");
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->transformations |= PNG_SWAP_ALPHA;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
|
||||
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_invert_alpha(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_invert_alpha\n");
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->transformations |= PNG_INVERT_ALPHA;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_invert_mono(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_invert_mono\n");
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->transformations |= PNG_INVERT_MONO;
|
||||
}
|
||||
|
||||
/* invert monochrome grayscale data */
|
||||
void /* PRIVATE */
|
||||
png_do_invert(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_invert\n");
|
||||
/* This test removed from libpng version 1.0.13 and 1.2.0:
|
||||
* if (row_info->bit_depth == 1 &&
|
||||
*/
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
if (row == NULL || row_info == NULL)
|
||||
return;
|
||||
#endif
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop = row_info->rowbytes;
|
||||
|
||||
for (i = 0; i < istop; i++)
|
||||
{
|
||||
*rp = (png_byte)(~(*rp));
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
|
||||
row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop = row_info->rowbytes;
|
||||
|
||||
for (i = 0; i < istop; i+=2)
|
||||
{
|
||||
*rp = (png_byte)(~(*rp));
|
||||
rp+=2;
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
|
||||
row_info->bit_depth == 16)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop = row_info->rowbytes;
|
||||
|
||||
for (i = 0; i < istop; i+=4)
|
||||
{
|
||||
*rp = (png_byte)(~(*rp));
|
||||
*(rp+1) = (png_byte)(~(*(rp+1)));
|
||||
rp+=4;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
|
||||
/* swaps byte order on 16 bit depth images */
|
||||
void /* PRIVATE */
|
||||
png_do_swap(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_swap\n");
|
||||
if (
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
row != NULL && row_info != NULL &&
|
||||
#endif
|
||||
row_info->bit_depth == 16)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop= row_info->width * row_info->channels;
|
||||
|
||||
for (i = 0; i < istop; i++, rp += 2)
|
||||
{
|
||||
png_byte t = *rp;
|
||||
*rp = *(rp + 1);
|
||||
*(rp + 1) = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
|
||||
static PNG_CONST png_byte onebppswaptable[256] = {
|
||||
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
|
||||
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
|
||||
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
|
||||
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
|
||||
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
|
||||
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
|
||||
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
|
||||
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
|
||||
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
|
||||
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
|
||||
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
|
||||
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
|
||||
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
|
||||
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
|
||||
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
|
||||
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
|
||||
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
|
||||
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
|
||||
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
|
||||
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
|
||||
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
|
||||
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
|
||||
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
|
||||
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
|
||||
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
|
||||
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
|
||||
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
|
||||
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
|
||||
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
|
||||
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
|
||||
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
|
||||
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
|
||||
};
|
||||
|
||||
static PNG_CONST png_byte twobppswaptable[256] = {
|
||||
0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
|
||||
0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
|
||||
0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
|
||||
0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
|
||||
0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
|
||||
0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
|
||||
0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
|
||||
0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
|
||||
0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
|
||||
0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
|
||||
0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
|
||||
0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
|
||||
0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
|
||||
0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
|
||||
0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
|
||||
0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
|
||||
0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
|
||||
0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
|
||||
0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
|
||||
0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
|
||||
0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
|
||||
0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
|
||||
0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
|
||||
0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
|
||||
0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
|
||||
0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
|
||||
0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
|
||||
0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
|
||||
0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
|
||||
0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
|
||||
0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
|
||||
0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
|
||||
};
|
||||
|
||||
static PNG_CONST png_byte fourbppswaptable[256] = {
|
||||
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
|
||||
0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
|
||||
0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
|
||||
0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
|
||||
0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
|
||||
0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
|
||||
0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
|
||||
0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
|
||||
0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
|
||||
0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
|
||||
0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
|
||||
0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
|
||||
0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
|
||||
0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
|
||||
0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
|
||||
0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
|
||||
0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
|
||||
0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
|
||||
0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
|
||||
0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
|
||||
0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
|
||||
0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
|
||||
0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
|
||||
0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
|
||||
0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
|
||||
0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
|
||||
0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
|
||||
0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
|
||||
0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
|
||||
0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
|
||||
0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
|
||||
0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
|
||||
};
|
||||
|
||||
/* swaps pixel packing order within bytes */
|
||||
void /* PRIVATE */
|
||||
png_do_packswap(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_packswap\n");
|
||||
if (
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
row != NULL && row_info != NULL &&
|
||||
#endif
|
||||
row_info->bit_depth < 8)
|
||||
{
|
||||
png_bytep rp, end, table;
|
||||
|
||||
end = row + row_info->rowbytes;
|
||||
|
||||
if (row_info->bit_depth == 1)
|
||||
table = (png_bytep)onebppswaptable;
|
||||
else if (row_info->bit_depth == 2)
|
||||
table = (png_bytep)twobppswaptable;
|
||||
else if (row_info->bit_depth == 4)
|
||||
table = (png_bytep)fourbppswaptable;
|
||||
else
|
||||
return;
|
||||
|
||||
for (rp = row; rp < end; rp++)
|
||||
*rp = table[*rp];
|
||||
}
|
||||
}
|
||||
#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
|
||||
|
||||
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
|
||||
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
|
||||
/* remove filler or alpha byte(s) */
|
||||
void /* PRIVATE */
|
||||
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
|
||||
{
|
||||
png_debug(1, "in png_do_strip_filler\n");
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
if (row != NULL && row_info != NULL)
|
||||
#endif
|
||||
{
|
||||
png_bytep sp=row;
|
||||
png_bytep dp=row;
|
||||
png_uint_32 row_width=row_info->width;
|
||||
png_uint_32 i;
|
||||
|
||||
if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
|
||||
(row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
|
||||
(flags & PNG_FLAG_STRIP_ALPHA))) &&
|
||||
row_info->channels == 4)
|
||||
{
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
/* This converts from RGBX or RGBA to RGB */
|
||||
if (flags & PNG_FLAG_FILLER_AFTER)
|
||||
{
|
||||
dp+=3; sp+=4;
|
||||
for (i = 1; i < row_width; i++)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
sp++;
|
||||
}
|
||||
}
|
||||
/* This converts from XRGB or ARGB to RGB */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
}
|
||||
row_info->pixel_depth = 24;
|
||||
row_info->rowbytes = row_width * 3;
|
||||
}
|
||||
else /* if (row_info->bit_depth == 16) */
|
||||
{
|
||||
if (flags & PNG_FLAG_FILLER_AFTER)
|
||||
{
|
||||
/* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
|
||||
sp += 8; dp += 6;
|
||||
for (i = 1; i < row_width; i++)
|
||||
{
|
||||
/* This could be (although png_memcpy is probably slower):
|
||||
png_memcpy(dp, sp, 6);
|
||||
sp += 8;
|
||||
dp += 6;
|
||||
*/
|
||||
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
sp += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
/* This could be (although png_memcpy is probably slower):
|
||||
png_memcpy(dp, sp, 6);
|
||||
sp += 8;
|
||||
dp += 6;
|
||||
*/
|
||||
|
||||
sp+=2;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
}
|
||||
row_info->pixel_depth = 48;
|
||||
row_info->rowbytes = row_width * 6;
|
||||
}
|
||||
row_info->channels = 3;
|
||||
}
|
||||
else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
(row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
|
||||
(flags & PNG_FLAG_STRIP_ALPHA))) &&
|
||||
row_info->channels == 2)
|
||||
{
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
/* This converts from GX or GA to G */
|
||||
if (flags & PNG_FLAG_FILLER_AFTER)
|
||||
{
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
sp++;
|
||||
}
|
||||
}
|
||||
/* This converts from XG or AG to G */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
}
|
||||
row_info->pixel_depth = 8;
|
||||
row_info->rowbytes = row_width;
|
||||
}
|
||||
else /* if (row_info->bit_depth == 16) */
|
||||
{
|
||||
if (flags & PNG_FLAG_FILLER_AFTER)
|
||||
{
|
||||
/* This converts from GGXX or GGAA to GG */
|
||||
sp += 4; dp += 2;
|
||||
for (i = 1; i < row_width; i++)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
sp += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This converts from XXGG or AAGG to GG */
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
sp += 2;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
}
|
||||
row_info->pixel_depth = 16;
|
||||
row_info->rowbytes = row_width * 2;
|
||||
}
|
||||
row_info->channels = 1;
|
||||
}
|
||||
if (flags & PNG_FLAG_STRIP_ALPHA)
|
||||
row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
|
||||
/* swaps red and blue bytes within a pixel */
|
||||
void /* PRIVATE */
|
||||
png_do_bgr(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_bgr\n");
|
||||
if (
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
row != NULL && row_info != NULL &&
|
||||
#endif
|
||||
(row_info->color_type & PNG_COLOR_MASK_COLOR))
|
||||
{
|
||||
png_uint_32 row_width = row_info->width;
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
|
||||
{
|
||||
png_bytep rp;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row; i < row_width; i++, rp += 3)
|
||||
{
|
||||
png_byte save = *rp;
|
||||
*rp = *(rp + 2);
|
||||
*(rp + 2) = save;
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
png_bytep rp;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row; i < row_width; i++, rp += 4)
|
||||
{
|
||||
png_byte save = *rp;
|
||||
*rp = *(rp + 2);
|
||||
*(rp + 2) = save;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (row_info->bit_depth == 16)
|
||||
{
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
|
||||
{
|
||||
png_bytep rp;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row; i < row_width; i++, rp += 6)
|
||||
{
|
||||
png_byte save = *rp;
|
||||
*rp = *(rp + 4);
|
||||
*(rp + 4) = save;
|
||||
save = *(rp + 1);
|
||||
*(rp + 1) = *(rp + 5);
|
||||
*(rp + 5) = save;
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
png_bytep rp;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row; i < row_width; i++, rp += 8)
|
||||
{
|
||||
png_byte save = *rp;
|
||||
*rp = *(rp + 4);
|
||||
*(rp + 4) = save;
|
||||
save = *(rp + 1);
|
||||
*(rp + 1) = *(rp + 5);
|
||||
*(rp + 5) = save;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
|
||||
|
||||
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
|
||||
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
|
||||
defined(PNG_LEGACY_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_user_transform_info(png_structp png_ptr, png_voidp
|
||||
user_transform_ptr, int user_transform_depth, int user_transform_channels)
|
||||
{
|
||||
png_debug(1, "in png_set_user_transform_info\n");
|
||||
if(png_ptr == NULL) return;
|
||||
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
|
||||
png_ptr->user_transform_ptr = user_transform_ptr;
|
||||
png_ptr->user_transform_depth = (png_byte)user_transform_depth;
|
||||
png_ptr->user_transform_channels = (png_byte)user_transform_channels;
|
||||
#else
|
||||
if(user_transform_ptr || user_transform_depth || user_transform_channels)
|
||||
png_warning(png_ptr,
|
||||
"This version of libpng does not support user transform info");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function returns a pointer to the user_transform_ptr associated with
|
||||
* the user transform functions. The application should free any memory
|
||||
* associated with this pointer before png_write_destroy and png_read_destroy
|
||||
* are called.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_get_user_transform_ptr(png_structp png_ptr)
|
||||
{
|
||||
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
|
||||
if (png_ptr == NULL) return (NULL);
|
||||
return ((png_voidp)png_ptr->user_transform_ptr);
|
||||
#else
|
||||
return (NULL);
|
||||
#endif
|
||||
}
|
||||
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
/* pnggvrd.c was removed from libpng-1.2.20. */
|
||||
Vendored
+234
@@ -0,0 +1,234 @@
|
||||
|
||||
/* pngwio.c - functions for data output
|
||||
*
|
||||
* Last changed in libpng 1.2.13 November 13, 2006
|
||||
* For conditions of distribution and use, see copyright notice in png.h
|
||||
* Copyright (c) 1998-2006 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
* This file provides a location for all output. Users who need
|
||||
* special handling are expected to write functions that have the same
|
||||
* arguments as these and perform similar functions, but that possibly
|
||||
* use different output methods. Note that you shouldn't change these
|
||||
* functions, but rather write replacement functions and then change
|
||||
* them at run time with png_set_write_fn(...).
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
|
||||
/* Write the data to whatever output you are using. The default routine
|
||||
writes to a file pointer. Note that this routine sometimes gets called
|
||||
with very small lengths, so you should implement some kind of simple
|
||||
buffering if you are using unbuffered writes. This should never be asked
|
||||
to write more than 64K on a 16 bit machine. */
|
||||
|
||||
void /* PRIVATE */
|
||||
png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
if (png_ptr->write_data_fn != NULL )
|
||||
(*(png_ptr->write_data_fn))(png_ptr, data, length);
|
||||
else
|
||||
png_error(png_ptr, "Call to NULL write function");
|
||||
}
|
||||
|
||||
#if !defined(PNG_NO_STDIO)
|
||||
/* This is the function that does the actual writing of data. If you are
|
||||
not writing to a standard C stream, you should create a replacement
|
||||
write_data function and use it at run time with png_set_write_fn(), rather
|
||||
than changing the library. */
|
||||
#ifndef USE_FAR_KEYWORD
|
||||
void PNGAPI
|
||||
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_uint_32 check;
|
||||
|
||||
if(png_ptr == NULL) return;
|
||||
#if defined(_WIN32_WCE)
|
||||
if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
|
||||
check = 0;
|
||||
#else
|
||||
check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
|
||||
#endif
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
#else
|
||||
/* this is the model-independent version. Since the standard I/O library
|
||||
can't handle far buffers in the medium and small models, we have to copy
|
||||
the data.
|
||||
*/
|
||||
|
||||
#define NEAR_BUF_SIZE 1024
|
||||
#define MIN(a,b) (a <= b ? a : b)
|
||||
|
||||
void PNGAPI
|
||||
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_uint_32 check;
|
||||
png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
|
||||
png_FILE_p io_ptr;
|
||||
|
||||
if(png_ptr == NULL) return;
|
||||
/* Check if data really is near. If so, use usual code. */
|
||||
near_data = (png_byte *)CVT_PTR_NOCHECK(data);
|
||||
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
|
||||
if ((png_bytep)near_data == data)
|
||||
{
|
||||
#if defined(_WIN32_WCE)
|
||||
if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
|
||||
check = 0;
|
||||
#else
|
||||
check = fwrite(near_data, 1, length, io_ptr);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
png_byte buf[NEAR_BUF_SIZE];
|
||||
png_size_t written, remaining, err;
|
||||
check = 0;
|
||||
remaining = length;
|
||||
do
|
||||
{
|
||||
written = MIN(NEAR_BUF_SIZE, remaining);
|
||||
png_memcpy(buf, data, written); /* copy far buffer to near buffer */
|
||||
#if defined(_WIN32_WCE)
|
||||
if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
|
||||
err = 0;
|
||||
#else
|
||||
err = fwrite(buf, 1, written, io_ptr);
|
||||
#endif
|
||||
if (err != written)
|
||||
break;
|
||||
else
|
||||
check += err;
|
||||
data += written;
|
||||
remaining -= written;
|
||||
}
|
||||
while (remaining != 0);
|
||||
}
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This function is called to output any data pending writing (normally
|
||||
to disk). After png_flush is called, there should be no data pending
|
||||
writing in any buffers. */
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
void /* PRIVATE */
|
||||
png_flush(png_structp png_ptr)
|
||||
{
|
||||
if (png_ptr->output_flush_fn != NULL)
|
||||
(*(png_ptr->output_flush_fn))(png_ptr);
|
||||
}
|
||||
|
||||
#if !defined(PNG_NO_STDIO)
|
||||
void PNGAPI
|
||||
png_default_flush(png_structp png_ptr)
|
||||
{
|
||||
#if !defined(_WIN32_WCE)
|
||||
png_FILE_p io_ptr;
|
||||
#endif
|
||||
if(png_ptr == NULL) return;
|
||||
#if !defined(_WIN32_WCE)
|
||||
io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
|
||||
if (io_ptr != NULL)
|
||||
fflush(io_ptr);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This function allows the application to supply new output functions for
|
||||
libpng if standard C streams aren't being used.
|
||||
|
||||
This function takes as its arguments:
|
||||
png_ptr - pointer to a png output data structure
|
||||
io_ptr - pointer to user supplied structure containing info about
|
||||
the output functions. May be NULL.
|
||||
write_data_fn - pointer to a new output function that takes as its
|
||||
arguments a pointer to a png_struct, a pointer to
|
||||
data to be written, and a 32-bit unsigned int that is
|
||||
the number of bytes to be written. The new write
|
||||
function should call png_error(png_ptr, "Error msg")
|
||||
to exit and output any fatal error messages.
|
||||
flush_data_fn - pointer to a new flush function that takes as its
|
||||
arguments a pointer to a png_struct. After a call to
|
||||
the flush function, there should be no data in any buffers
|
||||
or pending transmission. If the output method doesn't do
|
||||
any buffering of ouput, a function prototype must still be
|
||||
supplied although it doesn't have to do anything. If
|
||||
PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
|
||||
time, output_flush_fn will be ignored, although it must be
|
||||
supplied for compatibility. */
|
||||
void PNGAPI
|
||||
png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
|
||||
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
|
||||
{
|
||||
if(png_ptr == NULL) return;
|
||||
png_ptr->io_ptr = io_ptr;
|
||||
|
||||
#if !defined(PNG_NO_STDIO)
|
||||
if (write_data_fn != NULL)
|
||||
png_ptr->write_data_fn = write_data_fn;
|
||||
else
|
||||
png_ptr->write_data_fn = png_default_write_data;
|
||||
#else
|
||||
png_ptr->write_data_fn = write_data_fn;
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
#if !defined(PNG_NO_STDIO)
|
||||
if (output_flush_fn != NULL)
|
||||
png_ptr->output_flush_fn = output_flush_fn;
|
||||
else
|
||||
png_ptr->output_flush_fn = png_default_flush;
|
||||
#else
|
||||
png_ptr->output_flush_fn = output_flush_fn;
|
||||
#endif
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
|
||||
/* It is an error to read while writing a png file */
|
||||
if (png_ptr->read_data_fn != NULL)
|
||||
{
|
||||
png_ptr->read_data_fn = NULL;
|
||||
png_warning(png_ptr,
|
||||
"Attempted to set both read_data_fn and write_data_fn in");
|
||||
png_warning(png_ptr,
|
||||
"the same structure. Resetting read_data_fn to NULL.");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_FAR_KEYWORD)
|
||||
#if defined(_MSC_VER)
|
||||
void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
|
||||
{
|
||||
void *near_ptr;
|
||||
void FAR *far_ptr;
|
||||
FP_OFF(near_ptr) = FP_OFF(ptr);
|
||||
far_ptr = (void FAR *)near_ptr;
|
||||
if(check != 0)
|
||||
if(FP_SEG(ptr) != FP_SEG(far_ptr))
|
||||
png_error(png_ptr,"segment lost in conversion");
|
||||
return(near_ptr);
|
||||
}
|
||||
# else
|
||||
void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
|
||||
{
|
||||
void *near_ptr;
|
||||
void FAR *far_ptr;
|
||||
near_ptr = (void FAR *)ptr;
|
||||
far_ptr = (void FAR *)near_ptr;
|
||||
if(check != 0)
|
||||
if(far_ptr != ptr)
|
||||
png_error(png_ptr,"segment lost in conversion");
|
||||
return(near_ptr);
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
#endif /* PNG_WRITE_SUPPORTED */
|
||||
Vendored
+1516
File diff suppressed because it is too large
Load Diff
Vendored
+572
@@ -0,0 +1,572 @@
|
||||
|
||||
/* pngwtran.c - transforms the data in a row for PNG writers
|
||||
*
|
||||
* Last changed in libpng 1.2.9 April 14, 2006
|
||||
* For conditions of distribution and use, see copyright notice in png.h
|
||||
* Copyright (c) 1998-2006 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
|
||||
/* Transform the data according to the user's wishes. The order of
|
||||
* transformations is significant.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_do_write_transformations(png_structp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_do_write_transformations\n");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_USER_TRANSFORM)
|
||||
if(png_ptr->write_user_transform_fn != NULL)
|
||||
(*(png_ptr->write_user_transform_fn)) /* user write transform function */
|
||||
(png_ptr, /* png_ptr */
|
||||
&(png_ptr->row_info), /* row_info: */
|
||||
/* png_uint_32 width; width of row */
|
||||
/* png_uint_32 rowbytes; number of bytes in row */
|
||||
/* png_byte color_type; color type of pixels */
|
||||
/* png_byte bit_depth; bit depth of samples */
|
||||
/* png_byte channels; number of channels (1-4) */
|
||||
/* png_byte pixel_depth; bits per pixel (depth*channels) */
|
||||
png_ptr->row_buf + 1); /* start of pixel data for row */
|
||||
#endif
|
||||
#if defined(PNG_WRITE_FILLER_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_FILLER)
|
||||
png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
|
||||
png_ptr->flags);
|
||||
#endif
|
||||
#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_PACKSWAP)
|
||||
png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
#endif
|
||||
#if defined(PNG_WRITE_PACK_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_PACK)
|
||||
png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
|
||||
(png_uint_32)png_ptr->bit_depth);
|
||||
#endif
|
||||
#if defined(PNG_WRITE_SWAP_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_SWAP_BYTES)
|
||||
png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
#endif
|
||||
#if defined(PNG_WRITE_SHIFT_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_SHIFT)
|
||||
png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
|
||||
&(png_ptr->shift));
|
||||
#endif
|
||||
#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_SWAP_ALPHA)
|
||||
png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
#endif
|
||||
#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_INVERT_ALPHA)
|
||||
png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
#endif
|
||||
#if defined(PNG_WRITE_BGR_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_BGR)
|
||||
png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
#endif
|
||||
#if defined(PNG_WRITE_INVERT_SUPPORTED)
|
||||
if (png_ptr->transformations & PNG_INVERT_MONO)
|
||||
png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PNG_WRITE_PACK_SUPPORTED)
|
||||
/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
|
||||
* row_info bit depth should be 8 (one pixel per byte). The channels
|
||||
* should be 1 (this only happens on grayscale and paletted images).
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
|
||||
{
|
||||
png_debug(1, "in png_do_pack\n");
|
||||
if (row_info->bit_depth == 8 &&
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
row != NULL && row_info != NULL &&
|
||||
#endif
|
||||
row_info->channels == 1)
|
||||
{
|
||||
switch ((int)bit_depth)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
int mask, v;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
sp = row;
|
||||
dp = row;
|
||||
mask = 0x80;
|
||||
v = 0;
|
||||
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
if (*sp != 0)
|
||||
v |= mask;
|
||||
sp++;
|
||||
if (mask > 1)
|
||||
mask >>= 1;
|
||||
else
|
||||
{
|
||||
mask = 0x80;
|
||||
*dp = (png_byte)v;
|
||||
dp++;
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
if (mask != 0x80)
|
||||
*dp = (png_byte)v;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
int shift, v;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
sp = row;
|
||||
dp = row;
|
||||
shift = 6;
|
||||
v = 0;
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
png_byte value;
|
||||
|
||||
value = (png_byte)(*sp & 0x03);
|
||||
v |= (value << shift);
|
||||
if (shift == 0)
|
||||
{
|
||||
shift = 6;
|
||||
*dp = (png_byte)v;
|
||||
dp++;
|
||||
v = 0;
|
||||
}
|
||||
else
|
||||
shift -= 2;
|
||||
sp++;
|
||||
}
|
||||
if (shift != 6)
|
||||
*dp = (png_byte)v;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
int shift, v;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
sp = row;
|
||||
dp = row;
|
||||
shift = 4;
|
||||
v = 0;
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
png_byte value;
|
||||
|
||||
value = (png_byte)(*sp & 0x0f);
|
||||
v |= (value << shift);
|
||||
|
||||
if (shift == 0)
|
||||
{
|
||||
shift = 4;
|
||||
*dp = (png_byte)v;
|
||||
dp++;
|
||||
v = 0;
|
||||
}
|
||||
else
|
||||
shift -= 4;
|
||||
|
||||
sp++;
|
||||
}
|
||||
if (shift != 4)
|
||||
*dp = (png_byte)v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
row_info->bit_depth = (png_byte)bit_depth;
|
||||
row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
|
||||
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
|
||||
row_info->width);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_SHIFT_SUPPORTED)
|
||||
/* Shift pixel values to take advantage of whole range. Pass the
|
||||
* true number of bits in bit_depth. The row should be packed
|
||||
* according to row_info->bit_depth. Thus, if you had a row of
|
||||
* bit depth 4, but the pixels only had values from 0 to 7, you
|
||||
* would pass 3 as bit_depth, and this routine would translate the
|
||||
* data to 0 to 15.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
|
||||
{
|
||||
png_debug(1, "in png_do_shift\n");
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
if (row != NULL && row_info != NULL &&
|
||||
#else
|
||||
if (
|
||||
#endif
|
||||
row_info->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
{
|
||||
int shift_start[4], shift_dec[4];
|
||||
int channels = 0;
|
||||
|
||||
if (row_info->color_type & PNG_COLOR_MASK_COLOR)
|
||||
{
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->red;
|
||||
shift_dec[channels] = bit_depth->red;
|
||||
channels++;
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->green;
|
||||
shift_dec[channels] = bit_depth->green;
|
||||
channels++;
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->blue;
|
||||
shift_dec[channels] = bit_depth->blue;
|
||||
channels++;
|
||||
}
|
||||
else
|
||||
{
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->gray;
|
||||
shift_dec[channels] = bit_depth->gray;
|
||||
channels++;
|
||||
}
|
||||
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
|
||||
{
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
|
||||
shift_dec[channels] = bit_depth->alpha;
|
||||
channels++;
|
||||
}
|
||||
|
||||
/* with low row depths, could only be grayscale, so one channel */
|
||||
if (row_info->bit_depth < 8)
|
||||
{
|
||||
png_bytep bp = row;
|
||||
png_uint_32 i;
|
||||
png_byte mask;
|
||||
png_uint_32 row_bytes = row_info->rowbytes;
|
||||
|
||||
if (bit_depth->gray == 1 && row_info->bit_depth == 2)
|
||||
mask = 0x55;
|
||||
else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
|
||||
mask = 0x11;
|
||||
else
|
||||
mask = 0xff;
|
||||
|
||||
for (i = 0; i < row_bytes; i++, bp++)
|
||||
{
|
||||
png_uint_16 v;
|
||||
int j;
|
||||
|
||||
v = *bp;
|
||||
*bp = 0;
|
||||
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
|
||||
{
|
||||
if (j > 0)
|
||||
*bp |= (png_byte)((v << j) & 0xff);
|
||||
else
|
||||
*bp |= (png_byte)((v >> (-j)) & mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep bp = row;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop = channels * row_info->width;
|
||||
|
||||
for (i = 0; i < istop; i++, bp++)
|
||||
{
|
||||
|
||||
png_uint_16 v;
|
||||
int j;
|
||||
int c = (int)(i%channels);
|
||||
|
||||
v = *bp;
|
||||
*bp = 0;
|
||||
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
|
||||
{
|
||||
if (j > 0)
|
||||
*bp |= (png_byte)((v << j) & 0xff);
|
||||
else
|
||||
*bp |= (png_byte)((v >> (-j)) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
png_bytep bp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop = channels * row_info->width;
|
||||
|
||||
for (bp = row, i = 0; i < istop; i++)
|
||||
{
|
||||
int c = (int)(i%channels);
|
||||
png_uint_16 value, v;
|
||||
int j;
|
||||
|
||||
v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
|
||||
value = 0;
|
||||
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
|
||||
{
|
||||
if (j > 0)
|
||||
value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
|
||||
else
|
||||
value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
|
||||
}
|
||||
*bp++ = (png_byte)(value >> 8);
|
||||
*bp++ = (png_byte)(value & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
|
||||
void /* PRIVATE */
|
||||
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_write_swap_alpha\n");
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
if (row != NULL && row_info != NULL)
|
||||
#endif
|
||||
{
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
/* This converts from ARGB to RGBA */
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
png_byte save = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = save;
|
||||
}
|
||||
}
|
||||
/* This converts from AARRGGBB to RRGGBBAA */
|
||||
else
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
png_byte save[2];
|
||||
save[0] = *(sp++);
|
||||
save[1] = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = save[0];
|
||||
*(dp++) = save[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
{
|
||||
/* This converts from AG to GA */
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
png_byte save = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = save;
|
||||
}
|
||||
}
|
||||
/* This converts from AAGG to GGAA */
|
||||
else
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
png_byte save[2];
|
||||
save[0] = *(sp++);
|
||||
save[1] = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = save[0];
|
||||
*(dp++) = save[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
|
||||
void /* PRIVATE */
|
||||
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_write_invert_alpha\n");
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
if (row != NULL && row_info != NULL)
|
||||
#endif
|
||||
{
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
/* This inverts the alpha channel in RGBA */
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
/* does nothing
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*/
|
||||
sp+=3; dp = sp;
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
}
|
||||
}
|
||||
/* This inverts the alpha channel in RRGGBBAA */
|
||||
else
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
/* does nothing
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*/
|
||||
sp+=6; dp = sp;
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
{
|
||||
/* This inverts the alpha channel in GA */
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
}
|
||||
}
|
||||
/* This inverts the alpha channel in GGAA */
|
||||
else
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
/* does nothing
|
||||
*(dp++) = *(sp++);
|
||||
*(dp++) = *(sp++);
|
||||
*/
|
||||
sp+=2; dp = sp;
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_MNG_FEATURES_SUPPORTED)
|
||||
/* undoes intrapixel differencing */
|
||||
void /* PRIVATE */
|
||||
png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_write_intrapixel\n");
|
||||
if (
|
||||
#if defined(PNG_USELESS_TESTS_SUPPORTED)
|
||||
row != NULL && row_info != NULL &&
|
||||
#endif
|
||||
(row_info->color_type & PNG_COLOR_MASK_COLOR))
|
||||
{
|
||||
int bytes_per_pixel;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep rp;
|
||||
png_uint_32 i;
|
||||
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
|
||||
bytes_per_pixel = 3;
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
bytes_per_pixel = 4;
|
||||
else
|
||||
return;
|
||||
|
||||
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
|
||||
{
|
||||
*(rp) = (png_byte)((*rp - *(rp+1))&0xff);
|
||||
*(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
|
||||
}
|
||||
}
|
||||
else if (row_info->bit_depth == 16)
|
||||
{
|
||||
png_bytep rp;
|
||||
png_uint_32 i;
|
||||
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
|
||||
bytes_per_pixel = 6;
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
bytes_per_pixel = 8;
|
||||
else
|
||||
return;
|
||||
|
||||
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
|
||||
{
|
||||
png_uint_32 s0 = (*(rp ) << 8) | *(rp+1);
|
||||
png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3);
|
||||
png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5);
|
||||
png_uint_32 red = (png_uint_32)((s0-s1) & 0xffffL);
|
||||
png_uint_32 blue = (png_uint_32)((s2-s1) & 0xffffL);
|
||||
*(rp ) = (png_byte)((red >> 8) & 0xff);
|
||||
*(rp+1) = (png_byte)(red & 0xff);
|
||||
*(rp+4) = (png_byte)((blue >> 8) & 0xff);
|
||||
*(rp+5) = (png_byte)(blue & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* PNG_MNG_FEATURES_SUPPORTED */
|
||||
#endif /* PNG_WRITE_SUPPORTED */
|
||||
Vendored
+2792
File diff suppressed because it is too large
Load Diff
Vendored
+285
@@ -0,0 +1,285 @@
|
||||
/* $Id: t4.h,v 1.20 2007/11/10 18:40:44 drolon Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _T4_
|
||||
#define _T4_
|
||||
/*
|
||||
* CCITT T.4 1D Huffman runlength codes and
|
||||
* related definitions. Given the small sizes
|
||||
* of these tables it does not seem
|
||||
* worthwhile to make code & length 8 bits.
|
||||
*/
|
||||
typedef struct tableentry {
|
||||
unsigned short length; /* bit length of g3 code */
|
||||
unsigned short code; /* g3 code */
|
||||
short runlen; /* run length in bits */
|
||||
} tableentry;
|
||||
|
||||
#define EOL 0x001 /* EOL code value - 0000 0000 0000 1 */
|
||||
|
||||
/* status values returned instead of a run length */
|
||||
#define G3CODE_EOL -1 /* NB: ACT_EOL - ACT_WRUNT */
|
||||
#define G3CODE_INVALID -2 /* NB: ACT_INVALID - ACT_WRUNT */
|
||||
#define G3CODE_EOF -3 /* end of input data */
|
||||
#define G3CODE_INCOMP -4 /* incomplete run code */
|
||||
|
||||
/*
|
||||
* Note that these tables are ordered such that the
|
||||
* index into the table is known to be either the
|
||||
* run length, or (run length / 64) + a fixed offset.
|
||||
*
|
||||
* NB: The G3CODE_INVALID entries are only used
|
||||
* during state generation (see mkg3states.c).
|
||||
*/
|
||||
#ifdef G3CODES
|
||||
const tableentry TIFFFaxWhiteCodes[] = {
|
||||
{ 8, 0x35, 0 }, /* 0011 0101 */
|
||||
{ 6, 0x7, 1 }, /* 0001 11 */
|
||||
{ 4, 0x7, 2 }, /* 0111 */
|
||||
{ 4, 0x8, 3 }, /* 1000 */
|
||||
{ 4, 0xB, 4 }, /* 1011 */
|
||||
{ 4, 0xC, 5 }, /* 1100 */
|
||||
{ 4, 0xE, 6 }, /* 1110 */
|
||||
{ 4, 0xF, 7 }, /* 1111 */
|
||||
{ 5, 0x13, 8 }, /* 1001 1 */
|
||||
{ 5, 0x14, 9 }, /* 1010 0 */
|
||||
{ 5, 0x7, 10 }, /* 0011 1 */
|
||||
{ 5, 0x8, 11 }, /* 0100 0 */
|
||||
{ 6, 0x8, 12 }, /* 0010 00 */
|
||||
{ 6, 0x3, 13 }, /* 0000 11 */
|
||||
{ 6, 0x34, 14 }, /* 1101 00 */
|
||||
{ 6, 0x35, 15 }, /* 1101 01 */
|
||||
{ 6, 0x2A, 16 }, /* 1010 10 */
|
||||
{ 6, 0x2B, 17 }, /* 1010 11 */
|
||||
{ 7, 0x27, 18 }, /* 0100 111 */
|
||||
{ 7, 0xC, 19 }, /* 0001 100 */
|
||||
{ 7, 0x8, 20 }, /* 0001 000 */
|
||||
{ 7, 0x17, 21 }, /* 0010 111 */
|
||||
{ 7, 0x3, 22 }, /* 0000 011 */
|
||||
{ 7, 0x4, 23 }, /* 0000 100 */
|
||||
{ 7, 0x28, 24 }, /* 0101 000 */
|
||||
{ 7, 0x2B, 25 }, /* 0101 011 */
|
||||
{ 7, 0x13, 26 }, /* 0010 011 */
|
||||
{ 7, 0x24, 27 }, /* 0100 100 */
|
||||
{ 7, 0x18, 28 }, /* 0011 000 */
|
||||
{ 8, 0x2, 29 }, /* 0000 0010 */
|
||||
{ 8, 0x3, 30 }, /* 0000 0011 */
|
||||
{ 8, 0x1A, 31 }, /* 0001 1010 */
|
||||
{ 8, 0x1B, 32 }, /* 0001 1011 */
|
||||
{ 8, 0x12, 33 }, /* 0001 0010 */
|
||||
{ 8, 0x13, 34 }, /* 0001 0011 */
|
||||
{ 8, 0x14, 35 }, /* 0001 0100 */
|
||||
{ 8, 0x15, 36 }, /* 0001 0101 */
|
||||
{ 8, 0x16, 37 }, /* 0001 0110 */
|
||||
{ 8, 0x17, 38 }, /* 0001 0111 */
|
||||
{ 8, 0x28, 39 }, /* 0010 1000 */
|
||||
{ 8, 0x29, 40 }, /* 0010 1001 */
|
||||
{ 8, 0x2A, 41 }, /* 0010 1010 */
|
||||
{ 8, 0x2B, 42 }, /* 0010 1011 */
|
||||
{ 8, 0x2C, 43 }, /* 0010 1100 */
|
||||
{ 8, 0x2D, 44 }, /* 0010 1101 */
|
||||
{ 8, 0x4, 45 }, /* 0000 0100 */
|
||||
{ 8, 0x5, 46 }, /* 0000 0101 */
|
||||
{ 8, 0xA, 47 }, /* 0000 1010 */
|
||||
{ 8, 0xB, 48 }, /* 0000 1011 */
|
||||
{ 8, 0x52, 49 }, /* 0101 0010 */
|
||||
{ 8, 0x53, 50 }, /* 0101 0011 */
|
||||
{ 8, 0x54, 51 }, /* 0101 0100 */
|
||||
{ 8, 0x55, 52 }, /* 0101 0101 */
|
||||
{ 8, 0x24, 53 }, /* 0010 0100 */
|
||||
{ 8, 0x25, 54 }, /* 0010 0101 */
|
||||
{ 8, 0x58, 55 }, /* 0101 1000 */
|
||||
{ 8, 0x59, 56 }, /* 0101 1001 */
|
||||
{ 8, 0x5A, 57 }, /* 0101 1010 */
|
||||
{ 8, 0x5B, 58 }, /* 0101 1011 */
|
||||
{ 8, 0x4A, 59 }, /* 0100 1010 */
|
||||
{ 8, 0x4B, 60 }, /* 0100 1011 */
|
||||
{ 8, 0x32, 61 }, /* 0011 0010 */
|
||||
{ 8, 0x33, 62 }, /* 0011 0011 */
|
||||
{ 8, 0x34, 63 }, /* 0011 0100 */
|
||||
{ 5, 0x1B, 64 }, /* 1101 1 */
|
||||
{ 5, 0x12, 128 }, /* 1001 0 */
|
||||
{ 6, 0x17, 192 }, /* 0101 11 */
|
||||
{ 7, 0x37, 256 }, /* 0110 111 */
|
||||
{ 8, 0x36, 320 }, /* 0011 0110 */
|
||||
{ 8, 0x37, 384 }, /* 0011 0111 */
|
||||
{ 8, 0x64, 448 }, /* 0110 0100 */
|
||||
{ 8, 0x65, 512 }, /* 0110 0101 */
|
||||
{ 8, 0x68, 576 }, /* 0110 1000 */
|
||||
{ 8, 0x67, 640 }, /* 0110 0111 */
|
||||
{ 9, 0xCC, 704 }, /* 0110 0110 0 */
|
||||
{ 9, 0xCD, 768 }, /* 0110 0110 1 */
|
||||
{ 9, 0xD2, 832 }, /* 0110 1001 0 */
|
||||
{ 9, 0xD3, 896 }, /* 0110 1001 1 */
|
||||
{ 9, 0xD4, 960 }, /* 0110 1010 0 */
|
||||
{ 9, 0xD5, 1024 }, /* 0110 1010 1 */
|
||||
{ 9, 0xD6, 1088 }, /* 0110 1011 0 */
|
||||
{ 9, 0xD7, 1152 }, /* 0110 1011 1 */
|
||||
{ 9, 0xD8, 1216 }, /* 0110 1100 0 */
|
||||
{ 9, 0xD9, 1280 }, /* 0110 1100 1 */
|
||||
{ 9, 0xDA, 1344 }, /* 0110 1101 0 */
|
||||
{ 9, 0xDB, 1408 }, /* 0110 1101 1 */
|
||||
{ 9, 0x98, 1472 }, /* 0100 1100 0 */
|
||||
{ 9, 0x99, 1536 }, /* 0100 1100 1 */
|
||||
{ 9, 0x9A, 1600 }, /* 0100 1101 0 */
|
||||
{ 6, 0x18, 1664 }, /* 0110 00 */
|
||||
{ 9, 0x9B, 1728 }, /* 0100 1101 1 */
|
||||
{ 11, 0x8, 1792 }, /* 0000 0001 000 */
|
||||
{ 11, 0xC, 1856 }, /* 0000 0001 100 */
|
||||
{ 11, 0xD, 1920 }, /* 0000 0001 101 */
|
||||
{ 12, 0x12, 1984 }, /* 0000 0001 0010 */
|
||||
{ 12, 0x13, 2048 }, /* 0000 0001 0011 */
|
||||
{ 12, 0x14, 2112 }, /* 0000 0001 0100 */
|
||||
{ 12, 0x15, 2176 }, /* 0000 0001 0101 */
|
||||
{ 12, 0x16, 2240 }, /* 0000 0001 0110 */
|
||||
{ 12, 0x17, 2304 }, /* 0000 0001 0111 */
|
||||
{ 12, 0x1C, 2368 }, /* 0000 0001 1100 */
|
||||
{ 12, 0x1D, 2432 }, /* 0000 0001 1101 */
|
||||
{ 12, 0x1E, 2496 }, /* 0000 0001 1110 */
|
||||
{ 12, 0x1F, 2560 }, /* 0000 0001 1111 */
|
||||
{ 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */
|
||||
{ 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */
|
||||
{ 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */
|
||||
{ 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */
|
||||
{ 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */
|
||||
};
|
||||
|
||||
const tableentry TIFFFaxBlackCodes[] = {
|
||||
{ 10, 0x37, 0 }, /* 0000 1101 11 */
|
||||
{ 3, 0x2, 1 }, /* 010 */
|
||||
{ 2, 0x3, 2 }, /* 11 */
|
||||
{ 2, 0x2, 3 }, /* 10 */
|
||||
{ 3, 0x3, 4 }, /* 011 */
|
||||
{ 4, 0x3, 5 }, /* 0011 */
|
||||
{ 4, 0x2, 6 }, /* 0010 */
|
||||
{ 5, 0x3, 7 }, /* 0001 1 */
|
||||
{ 6, 0x5, 8 }, /* 0001 01 */
|
||||
{ 6, 0x4, 9 }, /* 0001 00 */
|
||||
{ 7, 0x4, 10 }, /* 0000 100 */
|
||||
{ 7, 0x5, 11 }, /* 0000 101 */
|
||||
{ 7, 0x7, 12 }, /* 0000 111 */
|
||||
{ 8, 0x4, 13 }, /* 0000 0100 */
|
||||
{ 8, 0x7, 14 }, /* 0000 0111 */
|
||||
{ 9, 0x18, 15 }, /* 0000 1100 0 */
|
||||
{ 10, 0x17, 16 }, /* 0000 0101 11 */
|
||||
{ 10, 0x18, 17 }, /* 0000 0110 00 */
|
||||
{ 10, 0x8, 18 }, /* 0000 0010 00 */
|
||||
{ 11, 0x67, 19 }, /* 0000 1100 111 */
|
||||
{ 11, 0x68, 20 }, /* 0000 1101 000 */
|
||||
{ 11, 0x6C, 21 }, /* 0000 1101 100 */
|
||||
{ 11, 0x37, 22 }, /* 0000 0110 111 */
|
||||
{ 11, 0x28, 23 }, /* 0000 0101 000 */
|
||||
{ 11, 0x17, 24 }, /* 0000 0010 111 */
|
||||
{ 11, 0x18, 25 }, /* 0000 0011 000 */
|
||||
{ 12, 0xCA, 26 }, /* 0000 1100 1010 */
|
||||
{ 12, 0xCB, 27 }, /* 0000 1100 1011 */
|
||||
{ 12, 0xCC, 28 }, /* 0000 1100 1100 */
|
||||
{ 12, 0xCD, 29 }, /* 0000 1100 1101 */
|
||||
{ 12, 0x68, 30 }, /* 0000 0110 1000 */
|
||||
{ 12, 0x69, 31 }, /* 0000 0110 1001 */
|
||||
{ 12, 0x6A, 32 }, /* 0000 0110 1010 */
|
||||
{ 12, 0x6B, 33 }, /* 0000 0110 1011 */
|
||||
{ 12, 0xD2, 34 }, /* 0000 1101 0010 */
|
||||
{ 12, 0xD3, 35 }, /* 0000 1101 0011 */
|
||||
{ 12, 0xD4, 36 }, /* 0000 1101 0100 */
|
||||
{ 12, 0xD5, 37 }, /* 0000 1101 0101 */
|
||||
{ 12, 0xD6, 38 }, /* 0000 1101 0110 */
|
||||
{ 12, 0xD7, 39 }, /* 0000 1101 0111 */
|
||||
{ 12, 0x6C, 40 }, /* 0000 0110 1100 */
|
||||
{ 12, 0x6D, 41 }, /* 0000 0110 1101 */
|
||||
{ 12, 0xDA, 42 }, /* 0000 1101 1010 */
|
||||
{ 12, 0xDB, 43 }, /* 0000 1101 1011 */
|
||||
{ 12, 0x54, 44 }, /* 0000 0101 0100 */
|
||||
{ 12, 0x55, 45 }, /* 0000 0101 0101 */
|
||||
{ 12, 0x56, 46 }, /* 0000 0101 0110 */
|
||||
{ 12, 0x57, 47 }, /* 0000 0101 0111 */
|
||||
{ 12, 0x64, 48 }, /* 0000 0110 0100 */
|
||||
{ 12, 0x65, 49 }, /* 0000 0110 0101 */
|
||||
{ 12, 0x52, 50 }, /* 0000 0101 0010 */
|
||||
{ 12, 0x53, 51 }, /* 0000 0101 0011 */
|
||||
{ 12, 0x24, 52 }, /* 0000 0010 0100 */
|
||||
{ 12, 0x37, 53 }, /* 0000 0011 0111 */
|
||||
{ 12, 0x38, 54 }, /* 0000 0011 1000 */
|
||||
{ 12, 0x27, 55 }, /* 0000 0010 0111 */
|
||||
{ 12, 0x28, 56 }, /* 0000 0010 1000 */
|
||||
{ 12, 0x58, 57 }, /* 0000 0101 1000 */
|
||||
{ 12, 0x59, 58 }, /* 0000 0101 1001 */
|
||||
{ 12, 0x2B, 59 }, /* 0000 0010 1011 */
|
||||
{ 12, 0x2C, 60 }, /* 0000 0010 1100 */
|
||||
{ 12, 0x5A, 61 }, /* 0000 0101 1010 */
|
||||
{ 12, 0x66, 62 }, /* 0000 0110 0110 */
|
||||
{ 12, 0x67, 63 }, /* 0000 0110 0111 */
|
||||
{ 10, 0xF, 64 }, /* 0000 0011 11 */
|
||||
{ 12, 0xC8, 128 }, /* 0000 1100 1000 */
|
||||
{ 12, 0xC9, 192 }, /* 0000 1100 1001 */
|
||||
{ 12, 0x5B, 256 }, /* 0000 0101 1011 */
|
||||
{ 12, 0x33, 320 }, /* 0000 0011 0011 */
|
||||
{ 12, 0x34, 384 }, /* 0000 0011 0100 */
|
||||
{ 12, 0x35, 448 }, /* 0000 0011 0101 */
|
||||
{ 13, 0x6C, 512 }, /* 0000 0011 0110 0 */
|
||||
{ 13, 0x6D, 576 }, /* 0000 0011 0110 1 */
|
||||
{ 13, 0x4A, 640 }, /* 0000 0010 0101 0 */
|
||||
{ 13, 0x4B, 704 }, /* 0000 0010 0101 1 */
|
||||
{ 13, 0x4C, 768 }, /* 0000 0010 0110 0 */
|
||||
{ 13, 0x4D, 832 }, /* 0000 0010 0110 1 */
|
||||
{ 13, 0x72, 896 }, /* 0000 0011 1001 0 */
|
||||
{ 13, 0x73, 960 }, /* 0000 0011 1001 1 */
|
||||
{ 13, 0x74, 1024 }, /* 0000 0011 1010 0 */
|
||||
{ 13, 0x75, 1088 }, /* 0000 0011 1010 1 */
|
||||
{ 13, 0x76, 1152 }, /* 0000 0011 1011 0 */
|
||||
{ 13, 0x77, 1216 }, /* 0000 0011 1011 1 */
|
||||
{ 13, 0x52, 1280 }, /* 0000 0010 1001 0 */
|
||||
{ 13, 0x53, 1344 }, /* 0000 0010 1001 1 */
|
||||
{ 13, 0x54, 1408 }, /* 0000 0010 1010 0 */
|
||||
{ 13, 0x55, 1472 }, /* 0000 0010 1010 1 */
|
||||
{ 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */
|
||||
{ 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */
|
||||
{ 13, 0x64, 1664 }, /* 0000 0011 0010 0 */
|
||||
{ 13, 0x65, 1728 }, /* 0000 0011 0010 1 */
|
||||
{ 11, 0x8, 1792 }, /* 0000 0001 000 */
|
||||
{ 11, 0xC, 1856 }, /* 0000 0001 100 */
|
||||
{ 11, 0xD, 1920 }, /* 0000 0001 101 */
|
||||
{ 12, 0x12, 1984 }, /* 0000 0001 0010 */
|
||||
{ 12, 0x13, 2048 }, /* 0000 0001 0011 */
|
||||
{ 12, 0x14, 2112 }, /* 0000 0001 0100 */
|
||||
{ 12, 0x15, 2176 }, /* 0000 0001 0101 */
|
||||
{ 12, 0x16, 2240 }, /* 0000 0001 0110 */
|
||||
{ 12, 0x17, 2304 }, /* 0000 0001 0111 */
|
||||
{ 12, 0x1C, 2368 }, /* 0000 0001 1100 */
|
||||
{ 12, 0x1D, 2432 }, /* 0000 0001 1101 */
|
||||
{ 12, 0x1E, 2496 }, /* 0000 0001 1110 */
|
||||
{ 12, 0x1F, 2560 }, /* 0000 0001 1111 */
|
||||
{ 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */
|
||||
{ 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */
|
||||
{ 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */
|
||||
{ 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */
|
||||
{ 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */
|
||||
};
|
||||
#else
|
||||
extern const tableentry TIFFFaxWhiteCodes[];
|
||||
extern const tableentry TIFFFaxBlackCodes[];
|
||||
#endif
|
||||
#endif /* _T4_ */
|
||||
Vendored
+1223
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user