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:
parent
492d6b5b06
commit
a76a10b730
@ -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 {
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user