SkPDF: Fix encoding of unichr outside of basic plane

In ToUnicode table, write unicode codepoints as one or two UTF16BE
values, rather than a single hex, as the standard requires.

Factor out uint16 -> big-endian hex code.

SkUtils is now a namespace.

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2120533002

Review-Url: https://codereview.chromium.org/2120533002
This commit is contained in:
halcanary 2016-07-07 12:31:55 -07:00 committed by Commit bot
parent 492d6b5b06
commit a76a10b730
3 changed files with 62 additions and 47 deletions

View File

@ -1063,15 +1063,9 @@ static void write_wide_string(SkDynamicMemoryWStream* wStream,
bool wideChars) {
if (wideChars) {
SkASSERT(2 * len < 65535);
static const char gHex[] = "0123456789ABCDEF";
wStream->writeText("<");
for (size_t i = 0; i < len; i++) {
char result[4]; // Big-endian
result[0] = gHex[(input[i] >> 12) & 0xF];
result[1] = gHex[(input[i] >> 8) & 0xF];
result[2] = gHex[(input[i] >> 4) & 0xF];
result[3] = gHex[(input[i]) & 0xF];
wStream->write(result, 4);
SkPDFUtils::WriteUInt16BE(wStream, input[i]);
}
wStream->writeText(">");
} else {

View File

@ -421,6 +421,16 @@ struct BFRange {
SkUnichar fUnicode;
};
static void write_utf16be(SkDynamicMemoryWStream* wStream, SkUnichar utf32) {
uint16_t utf16[2] = {0, 0};
size_t len = SkUTF16_FromUnichar(utf32, utf16);
SkASSERT(len == 1 || len == 2);
SkPDFUtils::WriteUInt16BE(wStream, utf16[0]);
if (len == 2) {
SkPDFUtils::WriteUInt16BE(wStream, utf16[1]);
}
}
static void append_bfchar_section(const SkTDArray<BFChar>& bfchar,
SkDynamicMemoryWStream* cmap) {
// PDF spec defines that every bf* list can have at most 100 entries.
@ -431,9 +441,9 @@ static void append_bfchar_section(const SkTDArray<BFChar>& bfchar,
cmap->writeText(" beginbfchar\n");
for (int j = 0; j < count; ++j) {
cmap->writeText("<");
cmap->writeHexAsText(bfchar[i + j].fGlyphId, 4);
SkPDFUtils::WriteUInt16BE(cmap, bfchar[i + j].fGlyphId);
cmap->writeText("> <");
cmap->writeHexAsText(bfchar[i + j].fUnicode, 4);
write_utf16be(cmap, bfchar[i + j].fUnicode);
cmap->writeText(">\n");
}
cmap->writeText("endbfchar\n");
@ -450,11 +460,11 @@ static void append_bfrange_section(const SkTDArray<BFRange>& bfrange,
cmap->writeText(" beginbfrange\n");
for (int j = 0; j < count; ++j) {
cmap->writeText("<");
cmap->writeHexAsText(bfrange[i + j].fStart, 4);
SkPDFUtils::WriteUInt16BE(cmap, bfrange[i + j].fStart);
cmap->writeText("> <");
cmap->writeHexAsText(bfrange[i + j].fEnd, 4);
SkPDFUtils::WriteUInt16BE(cmap, bfrange[i + j].fEnd);
cmap->writeText("> <");
cmap->writeHexAsText(bfrange[i + j].fUnicode, 4);
write_utf16be(cmap, bfrange[i + j].fUnicode);
cmap->writeText(">\n");
}
cmap->writeText("endbfrange\n");

View File

@ -11,11 +11,11 @@
#include "SkPaint.h"
#include "SkPath.h"
#include "SkStream.h"
class SkMatrix;
class SkPDFArray;
struct SkRect;
class SkWStream;
#if 0
#define PRINT_NOT_IMPL(str) fprintf(stderr, str)
@ -31,41 +31,52 @@ class SkWStream;
} \
} while (0)
class SkPDFUtils {
public:
static sk_sp<SkPDFArray> RectToArray(const SkRect& rect);
static sk_sp<SkPDFArray> MatrixToArray(const SkMatrix& matrix);
static void AppendTransform(const SkMatrix& matrix, SkWStream* content);
namespace SkPDFUtils {
static void MoveTo(SkScalar x, SkScalar y, SkWStream* content);
static void AppendLine(SkScalar x, SkScalar y, SkWStream* content);
static void AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
SkScalar ctl2X, SkScalar ctl2Y,
SkScalar dstX, SkScalar dstY, SkWStream* content);
static void AppendRectangle(const SkRect& rect, SkWStream* content);
static void EmitPath(const SkPath& path, SkPaint::Style paintStyle,
bool doConsumeDegerates, SkWStream* content);
static void EmitPath(const SkPath& path, SkPaint::Style paintStyle,
SkWStream* content) {
SkPDFUtils::EmitPath(path, paintStyle, true, content);
}
static void ClosePath(SkWStream* content);
static void PaintPath(SkPaint::Style style, SkPath::FillType fill,
SkWStream* content);
static void StrokePath(SkWStream* content);
static void DrawFormXObject(int objectIndex, SkWStream* content);
static void ApplyGraphicState(int objectIndex, SkWStream* content);
static void ApplyPattern(int objectIndex, SkWStream* content);
sk_sp<SkPDFArray> RectToArray(const SkRect& rect);
sk_sp<SkPDFArray> MatrixToArray(const SkMatrix& matrix);
void AppendTransform(const SkMatrix& matrix, SkWStream* content);
// 3 = '-', '.', and '\0' characters.
// 9 = number of significant digits
// abs(FLT_MIN_10_EXP) = number of zeros in FLT_MIN
static const size_t kMaximumFloatDecimalLength = 3 + 9 - FLT_MIN_10_EXP;
// FloatToDecimal is exposed for unit tests.
static size_t FloatToDecimal(float value,
char output[kMaximumFloatDecimalLength]);
static void AppendScalar(SkScalar value, SkWStream* stream);
static void WriteString(SkWStream* wStream, const char* input, size_t len);
};
void MoveTo(SkScalar x, SkScalar y, SkWStream* content);
void AppendLine(SkScalar x, SkScalar y, SkWStream* content);
void AppendCubic(SkScalar ctl1X, SkScalar ctl1Y,
SkScalar ctl2X, SkScalar ctl2Y,
SkScalar dstX, SkScalar dstY, SkWStream* content);
void AppendRectangle(const SkRect& rect, SkWStream* content);
void EmitPath(const SkPath& path, SkPaint::Style paintStyle,
bool doConsumeDegerates, SkWStream* content);
inline void EmitPath(const SkPath& path, SkPaint::Style paintStyle,
SkWStream* content) {
SkPDFUtils::EmitPath(path, paintStyle, true, content);
}
void ClosePath(SkWStream* content);
void PaintPath(SkPaint::Style style, SkPath::FillType fill,
SkWStream* content);
void StrokePath(SkWStream* content);
void DrawFormXObject(int objectIndex, SkWStream* content);
void ApplyGraphicState(int objectIndex, SkWStream* content);
void ApplyPattern(int objectIndex, SkWStream* content);
// 3 = '-', '.', and '\0' characters.
// 9 = number of significant digits
// abs(FLT_MIN_10_EXP) = number of zeros in FLT_MIN
const size_t kMaximumFloatDecimalLength = 3 + 9 - FLT_MIN_10_EXP;
// FloatToDecimal is exposed for unit tests.
size_t FloatToDecimal(float value,
char output[kMaximumFloatDecimalLength]);
void AppendScalar(SkScalar value, SkWStream* stream);
void WriteString(SkWStream* wStream, const char* input, size_t len);
inline void WriteUInt16BE(SkDynamicMemoryWStream* wStream, uint16_t value) {
static const char gHex[] = "0123456789ABCDEF";
char result[4];
result[0] = gHex[ value >> 12 ];
result[1] = gHex[0xF & (value >> 8 )];
result[2] = gHex[0xF & (value >> 4 )];
result[3] = gHex[0xF & (value )];
wStream->write(result, 4);
}
} // namespace SkPDFUtils
#endif