diff options
-rw-r--r-- | bench/PDFBench.cpp | 20 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 42 | ||||
-rw-r--r-- | src/pdf/SkPDFTypes.cpp | 18 | ||||
-rw-r--r-- | src/pdf/SkPDFUtils.cpp | 50 | ||||
-rw-r--r-- | src/pdf/SkPDFUtils.h | 2 | ||||
-rw-r--r-- | tests/PDFPrimitivesTest.cpp | 8 |
6 files changed, 77 insertions, 63 deletions
diff --git a/bench/PDFBench.cpp b/bench/PDFBench.cpp index 76ee3cad0d..8f5d2db5b4 100644 --- a/bench/PDFBench.cpp +++ b/bench/PDFBench.cpp @@ -208,6 +208,25 @@ struct WStreamWriteTextBenchmark : public Benchmark { } }; +struct WritePDFTextBenchmark : public Benchmark { + std::unique_ptr<SkWStream> fWStream; + WritePDFTextBenchmark() : fWStream(new NullWStream) {} + const char* onGetName() override { return "WritePDFText"; } + bool isSuitableFor(Backend backend) override { + return backend == kNonRendering_Backend; + } + void onDraw(int loops, SkCanvas*) override { + static const char kHello[] = "HELLO SKIA!\n"; + static const char kBinary[] = "\001\002\003\004\005\006"; + while (loops-- > 0) { + for (int i = 1000; i-- > 0;) { + SkPDFUtils::WriteString(fWStream.get(), kHello, strlen(kHello)); + SkPDFUtils::WriteString(fWStream.get(), kBinary, strlen(kBinary)); + } + } + } +}; + } // namespace DEF_BENCH(return new PDFImageBench;) DEF_BENCH(return new PDFJpegImageBench;) @@ -215,3 +234,4 @@ DEF_BENCH(return new PDFCompressionBench;) DEF_BENCH(return new PDFScalarBench;) DEF_BENCH(return new PDFShaderBench;) DEF_BENCH(return new WStreamWriteTextBenchmark;) +DEF_BENCH(return new WritePDFTextBenchmark;) diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 5b4ae93504..b9e310d846 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -1067,30 +1067,32 @@ void SkPDFDevice::drawImageRect(const SkDraw& draw, // discarded. If true, the upper byte is encoded // first. Otherwise, we assert the upper byte is // zero. -static SkString format_wide_string(const uint16_t* input, - size_t len, - bool wideChars) { +static void write_wide_string(SkDynamicMemoryWStream* wStream, + const uint16_t* input, + size_t len, + bool wideChars) { if (wideChars) { SkASSERT(2 * len < 65535); static const char gHex[] = "0123456789ABCDEF"; - SkString result(4 * len + 2); - result[0] = '<'; + wStream->writeText("<"); for (size_t i = 0; i < len; i++) { - result[4 * i + 1] = gHex[(input[i] >> 12) & 0xF]; - result[4 * i + 2] = gHex[(input[i] >> 8) & 0xF]; - result[4 * i + 3] = gHex[(input[i] >> 4) & 0xF]; - result[4 * i + 4] = gHex[(input[i] ) & 0xF]; + 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); } - result[4 * len + 1] = '>'; - return result; + wStream->writeText(">"); } else { SkASSERT(len <= 65535); - SkString tmp(len); + SkAutoMalloc buffer(len); // Remove every other byte. + uint8_t* ptr = (uint8_t*)buffer.get(); for (size_t i = 0; i < len; i++) { SkASSERT(0 == input[i] >> 8); - tmp[i] = static_cast<uint8_t>(input[i]); + ptr[i] = static_cast<uint8_t>(input[i]); } - return SkPDFUtils::FormatString(tmp.c_str(), tmp.size()); + SkPDFUtils::WriteString(wStream, (char*)buffer.get(), len); } } @@ -1184,10 +1186,9 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, fFontGlyphUsage->noteGlyphUsage( font, glyphIDsCopy.begin() + consumedGlyphCount, availableGlyphs); - SkString encodedString = - format_wide_string(glyphIDsCopy.begin() + consumedGlyphCount, - availableGlyphs, font->multiByteGlyphs()); - content.entry()->fContent.writeText(encodedString.c_str()); + write_wide_string(&content.entry()->fContent, + glyphIDsCopy.begin() + consumedGlyphCount, + availableGlyphs, font->multiByteGlyphs()); consumedGlyphCount += availableGlyphs; content.entry()->fContent.writeText(" Tj\n"); } @@ -1264,9 +1265,8 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y); set_text_transform(x, y, textPaint.getTextSkewX(), &content.entry()->fContent); - SkString encodedString = - format_wide_string(&encodedValue, 1, font->multiByteGlyphs()); - content.entry()->fContent.writeText(encodedString.c_str()); + write_wide_string(&content.entry()->fContent, &encodedValue, 1, + font->multiByteGlyphs()); content.entry()->fContent.writeText(" Tj\n"); } content.entry()->fContent.writeText("ET\n"); diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp index 285da38513..19635ab84e 100644 --- a/src/pdf/SkPDFTypes.cpp +++ b/src/pdf/SkPDFTypes.cpp @@ -110,18 +110,6 @@ static void write_name_escaped(SkWStream* o, const char* name) { } } -static void write_string(SkWStream* o, const SkString& s) { - o->write(s.c_str(), s.size()); -} - -static SkString format_string(const SkString& s) { - return SkPDFUtils::FormatString(s.c_str(), s.size()); -} - -static SkString format_string(const char* s) { - return SkPDFUtils::FormatString(s, strlen(s)); -} - void SkPDFUnion::emitObject(SkWStream* stream, const SkPDFObjNumMap& objNumMap, const SkPDFSubstituteMap& substitutes) const { @@ -142,14 +130,16 @@ void SkPDFUnion::emitObject(SkWStream* stream, return; case Type::kString: SkASSERT(fStaticString); - write_string(stream, format_string(fStaticString)); + SkPDFUtils::WriteString(stream, fStaticString, + strlen(fStaticString)); return; case Type::kNameSkS: stream->writeText("/"); write_name_escaped(stream, pun(fSkString)->c_str()); return; case Type::kStringSkS: - write_string(stream, format_string(*pun(fSkString))); + SkPDFUtils::WriteString(stream, pun(fSkString)->c_str(), + pun(fSkString)->size()); return; case Type::kObjRef: stream->writeDecAsText(objNumMap.getObjectNumber( diff --git a/src/pdf/SkPDFUtils.cpp b/src/pdf/SkPDFUtils.cpp index f305765389..4e1a6d792d 100644 --- a/src/pdf/SkPDFUtils.cpp +++ b/src/pdf/SkPDFUtils.cpp @@ -370,46 +370,48 @@ size_t SkPDFUtils::FloatToDecimal(float value, return output - result; } -SkString SkPDFUtils::FormatString(const char* cin, size_t len) { +void SkPDFUtils::WriteString(SkWStream* wStream, const char* cin, size_t len) { SkDEBUGCODE(static const size_t kMaxLen = 65535;) SkASSERT(len <= kMaxLen); - // 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; - size_t characterCount = 2 + len; + size_t extraCharacterCount = 0; for (size_t i = 0; i < len; i++) { if (cin[i] > '~' || cin[i] < ' ') { - sevenBitClean = false; - break; + extraCharacterCount += 3; } if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { - ++characterCount; + ++extraCharacterCount; } } - SkString result; - if (sevenBitClean) { - result.resize(characterCount); - char* str = result.writable_str(); - *str++ = '('; + if (extraCharacterCount <= len) { + wStream->writeText("("); for (size_t i = 0; i < len; i++) { - if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { - *str++ = '\\'; + if (cin[i] > '~' || cin[i] < ' ') { + uint8_t c = static_cast<uint8_t>(cin[i]); + uint8_t octal[4]; + octal[0] = '\\'; + octal[1] = '0' + ( c >> 6 ); + octal[2] = '0' + ((c >> 3) & 0x07); + octal[3] = '0' + ( c & 0x07); + wStream->write(octal, 4); + } else { + if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { + wStream->writeText("\\"); + } + wStream->write(&cin[i], 1); } - *str++ = cin[i]; } - *str++ = ')'; + wStream->writeText(")"); } else { - result.resize(2 * len + 2); - char* str = result.writable_str(); - *str++ = '<'; + wStream->writeText("<"); for (size_t i = 0; i < len; i++) { uint8_t c = static_cast<uint8_t>(cin[i]); static const char gHex[] = "0123456789ABCDEF"; - *str++ = gHex[(c >> 4) & 0xF]; - *str++ = gHex[(c ) & 0xF]; + char hexValue[2]; + hexValue[0] = gHex[(c >> 4) & 0xF]; + hexValue[1] = gHex[ c & 0xF]; + wStream->write(hexValue, 2); } - *str++ = '>'; + wStream->writeText(">"); } - return result; } diff --git a/src/pdf/SkPDFUtils.h b/src/pdf/SkPDFUtils.h index 3340089ef8..693d9cd398 100644 --- a/src/pdf/SkPDFUtils.h +++ b/src/pdf/SkPDFUtils.h @@ -66,7 +66,7 @@ public: static size_t FloatToDecimal(float value, char output[kMaximumFloatDecimalLength]); static void AppendScalar(SkScalar value, SkWStream* stream); - static SkString FormatString(const char* input, size_t len); + static void WriteString(SkWStream* wStream, const char* input, size_t len); }; #endif diff --git a/tests/PDFPrimitivesTest.cpp b/tests/PDFPrimitivesTest.cpp index e438bfef78..9e2a89e609 100644 --- a/tests/PDFPrimitivesTest.cpp +++ b/tests/PDFPrimitivesTest.cpp @@ -217,9 +217,11 @@ static void TestPDFUnion(skiatest::Reporter* reporter) { SkString stringComplexInput("\ttest ) string ( foo"); SkPDFUnion stringComplex = SkPDFUnion::String(stringComplexInput); - ASSERT_EMIT_EQ(reporter, - stringComplex, - "<0974657374202920737472696E67202820666F6F>"); + ASSERT_EMIT_EQ(reporter, stringComplex, "(\\011test \\) string \\( foo)"); + + SkString binaryStringInput("\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\20"); + SkPDFUnion binaryString = SkPDFUnion::String(binaryStringInput); + ASSERT_EMIT_EQ(reporter, binaryString, "<0102030405060708090A0B0C0D0E0F10>"); SkString nameInput("Test name\twith#tab"); SkPDFUnion name = SkPDFUnion::Name(nameInput); |