/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkPDFCatalog.h"
#include "SkPDFTypes.h"
#include "SkStream.h"
#ifdef SK_BUILD_FOR_WIN
#define SNPRINTF _snprintf
#else
#define SNPRINTF snprintf
#endif
///////////////////////////////////////////////////////////////////////////////
void SkPDFObject::emit(SkWStream* stream, SkPDFCatalog* catalog,
bool indirect) {
SkPDFObject* realObject = catalog->getSubstituteObject(this);
return realObject->emitObject(stream, catalog, indirect);
}
size_t SkPDFObject::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
SkDynamicMemoryWStream buffer;
emit(&buffer, catalog, indirect);
return buffer.getOffset();
}
void SkPDFObject::getResources(const SkTSet<SkPDFObject*>& knownResourceObjects,
SkTSet<SkPDFObject*>* newResourceObjects) {}
void SkPDFObject::emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog) {
catalog->emitObjectNumber(stream, this);
stream->writeText(" obj\n");
emit(stream, catalog, false);
stream->writeText("\nendobj\n");
}
size_t SkPDFObject::getIndirectOutputSize(SkPDFCatalog* catalog) {
return catalog->getObjectNumberSize(this) + strlen(" obj\n") +
this->getOutputSize(catalog, false) + strlen("\nendobj\n");
}
void SkPDFObject::AddResourceHelper(SkPDFObject* resource,
SkTDArray<SkPDFObject*>* list) {
list->push(resource);
resource->ref();
}
void SkPDFObject::GetResourcesHelper(
const SkTDArray<SkPDFObject*>* resources,
const SkTSet<SkPDFObject*>& knownResourceObjects,
SkTSet<SkPDFObject*>* newResourceObjects) {
if (resources->count()) {
newResourceObjects->setReserve(
newResourceObjects->count() + resources->count());
for (int i = 0; i < resources->count(); i++) {
if (!knownResourceObjects.contains((*resources)[i]) &&
!newResourceObjects->contains((*resources)[i])) {
newResourceObjects->add((*resources)[i]);
(*resources)[i]->ref();
(*resources)[i]->getResources(knownResourceObjects,
newResourceObjects);
}
}
}
}
SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) {
SkSafeRef(obj);
}
SkPDFObjRef::~SkPDFObjRef() {}
void SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
bool indirect) {
SkASSERT(!indirect);
catalog->emitObjectNumber(stream, fObj.get());
stream->writeText(" R");
}
size_t SkPDFObjRef::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
SkASSERT(!indirect);
return catalog->getObjectNumberSize(fObj.get()) + strlen(" R");
}
SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {}
SkPDFInt::~SkPDFInt() {}
void SkPDFInt::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
bool indirect) {
if (indirect) {
return emitIndirectObject(stream, catalog);
}
stream->writeDecAsText(fValue);
}
SkPDFBool::SkPDFBool(bool value) : fValue(value) {}
SkPDFBool::~SkPDFBool() {}
void SkPDFBool::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
bool indirect) {
SkASSERT(!indirect);
if (fValue) {
stream->writeText("true");
} else {
stream->writeText("false");
}
}
size_t SkPDFBool::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
SkASSERT(!indirect);
if (fValue) {
return strlen("true");
}
return strlen("false");
}
SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {}
SkPDFScalar::~SkPDFScalar() {}
void SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
bool indirect) {
if (indirect) {
return emitIndirectObject(stream, catalog);
}
Append(fValue, stream);
}
// static
void SkPDFScalar::Append(SkScalar value, SkWStream* stream) {
// The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and
// +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31).
// When using floats that are outside the whole value range, we can use
// integers instead.
#if !defined(SK_ALLOW_LARGE_PDF_SCALARS)
if (value > 32767 || value < -32767) {
stream->writeDecAsText(SkScalarRoundToInt(value));
return;
}
char buffer[SkStrAppendScalar_MaxSize];
char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value));
stream->write(buffer, end - buffer);
return;
#endif // !SK_ALLOW_LARGE_PDF_SCALARS
#if defined(SK_ALLOW_LARGE_PDF_SCALARS)
// Floats have 24bits of significance, so anything outside that range is
// no more precise than an int. (Plus PDF doesn't support scientific
// notation, so this clamps to SK_Max/MinS32).
if (value > (1 << 24) || value < -(1 << 24)) {
stream->writeDecAsText(value);
return;
}
// Continue to enforce the PDF limits for small floats.
if (value < 1.0f/65536 && value > -1.0f/65536) {
stream->writeDecAsText(0);
return;
}
// SkStrAppendFloat might still use scientific notation, so use snprintf
// directly..
static const int kFloat_MaxSize = 19;
char buffer[kFloat_MaxSize];
int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value);
// %f always prints trailing 0s, so strip them.
for (; buffer[len - 1] == '0' && len > 0; len--) {
buffer[len - 1] = '\0';
}
if (buffer[len - 1] == '.') {
buffer[len - 1] = '\0';
}
stream->writeText(buffer);
return;
#endif // SK_ALLOW_LARGE_PDF_SCALARS
}
SkPDFString::SkPDFString(const char value[])
: fValue(FormatString(value, strlen(value))) {
}
SkPDFString::SkPDFString(const SkString& value)
: fValue(FormatString(value.c_str(), value.size())) {
}
SkPDFString::SkPDFString(const uint16_t* value, size_t len, bool wideChars)
: fValue(FormatString(value, len, wideChars)) {
}
SkPDFString::~SkPDFString() {}
void SkPDFString::emitObject(SkWStream* stream, SkPDFCatalog* catalog,
bool indirect) {
if (indirect)
return emitIndirectObject(stream, catalog);
stream->write(fValue.c_str(), fValue.size());
}
size_t SkPDFString::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
if (indirect)
return getIndirectOutputSize(catalog);
return fValue.size();
}
// static
SkString SkPDFString::FormatString(const char* input, size_t len) {
return DoFormatString(input, len, false, false);
}
SkString SkPDFString::FormatString(const uint16_t* input, size_t len,
bool wideChars) {
return DoFormatString(input, len, true, wideChars);
}
// static
SkString SkPDFString::DoFormatString(const void* input, size_t len,
bool wideInput, bool wideOutput) {
SkASSERT(len <= kMaxLen);
const uint16_t* win = (const uint16_t*) input;
const char* cin = (const char*) input;
if (wideOutput) {
SkASSERT(wideInput);
SkString result;
result.append("<");
for (size_t i = 0; i < len; i++) {
result.appendHex(win[i], 4);
}
result.append(">");
return result;
}
// 7-bit clean is a heuristic to decide what string format to use;
// a 7-bit clean string should require little escaping.
bool sevenBitClean = true;
for (size_t i = 0; i < len; i++) {
SkASSERT(!wideInput || !(win[i] & ~0xFF));
char val = wideInput ? win[i] : cin[i];
if (val > '~' || val < ' ') {
sevenBitClean = false;
break;
}
}
SkString result;
if (sevenBitClean) {
result.append("(");
for (size_t i = 0; i < len; i++) {
SkASSERT(!wideInput || !(win[i] & ~0xFF));
char
我虽横行却不霸道
- 粉丝: 95
- 资源: 1万+
最新资源
- 使用python爬取数据并采用Django搭建系统的前后台,使用Spark进行数据处理并进行电影推荐项目源码
- 基于C++的简易图书管理系统(含exe可执行文件)
- Python毕业设计基于知识图谱的电影推荐系统源码(完整项目代码)
- 国际象棋棋子检测3-YOLO(v5至v9)、COCO、CreateML、Darknet、Paligemma、TFRecord数据集合集.rar
- Hadoop复习资料题库.zip
- 基于python和协同过滤算法的电影推荐系统
- 基于resnet的动物图像分类系统(python期末大作业)PyQt+Flask+HTML5+PyTorch.zip
- 电动蝶阀远程自动化控制系统的构建与应用
- 使用机器学习算法基于用户的社交媒体使用情况预测用户情绪
- jQuery信息提示插件
- 国际象棋棋子检测8-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rar
- 2023最新仿蓝奏云合集下载页面系统源码 带后台版本
- Cisco Packet Tracer实用技巧及网络配置指南
- 基于SpringBoot+Vue的家具商城系统设计与实现(编号:97913147)(1).zip
- 基于springboot+vue的大学生创业项目的信息管理系统(编号:96166263).zip
- 基于Springboot的本科实践教学管理系统(编号:1407703).zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈