From bb264b775004be3df72f0bb5ee613761a328a6c3 Mon Sep 17 00:00:00 2001 From: halcanary Date: Tue, 7 Apr 2015 10:40:03 -0700 Subject: [PATCH] SkPDF: SkPDFString is no longer aware of wide strings. Since wide strings are only used in SkPDFDevice, I have moved the function that manages them to that directory. Motivation: The SkPDFString will be refactored later along with the other SkPFObject heirarchy. BUG=skia:3585 Review URL: https://codereview.chromium.org/1064013003 --- src/pdf/SkPDFDevice.cpp | 41 +++++++++++++++++++++++++++--- src/pdf/SkPDFTypes.cpp | 67 ++++++++++++++++--------------------------------- src/pdf/SkPDFTypes.h | 12 --------- 3 files changed, 59 insertions(+), 61 deletions(-) diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index ced075e..f624cb4 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -1051,6 +1051,41 @@ void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap, paint); } +// Create a PDF string. Maximum length (in bytes) is 65,535. +// @param input A string value. +// @param len The length of the input array. +// @param wideChars True iff the upper byte in each uint16_t is +// significant and should be encoded and not +// 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) { + if (wideChars) { + SkASSERT(2 * len < 65535); + static const char gHex[] = "0123456789ABCDEF"; + SkString result(4 * len + 2); + result[0] = '<'; + 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]; + } + result[4 * len + 1] = '>'; + return result; + } else { + SkASSERT(len <= 65535); + SkString tmp(len); + for (size_t i = 0; i < len; i++) { + SkASSERT(0 == input[i] >> 8); + tmp[i] = static_cast(input[i]); + } + return SkPDFString::FormatString(tmp.c_str(), tmp.size()); + } +} + void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); @@ -1090,8 +1125,8 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, font, glyphIDsCopy.begin() + consumedGlyphCount, availableGlyphs); SkString encodedString = - SkPDFString::FormatString(glyphIDsCopy.begin() + consumedGlyphCount, - availableGlyphs, font->multiByteGlyphs()); + format_wide_string(glyphIDsCopy.begin() + consumedGlyphCount, + availableGlyphs, font->multiByteGlyphs()); content.entry()->fContent.writeText(encodedString.c_str()); consumedGlyphCount += availableGlyphs; content.entry()->fContent.writeText(" Tj\n"); @@ -1144,7 +1179,7 @@ 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 = - SkPDFString::FormatString(&encodedValue, 1, font->multiByteGlyphs()); + format_wide_string(&encodedValue, 1, font->multiByteGlyphs()); content.entry()->fContent.writeText(encodedString.c_str()); content.entry()->fContent.writeText(" Tj\n"); } diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp index e80d118..89d6a0b 100644 --- a/src/pdf/SkPDFTypes.cpp +++ b/src/pdf/SkPDFTypes.cpp @@ -133,10 +133,6 @@ 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, @@ -146,67 +142,46 @@ void SkPDFString::emitObject(SkWStream* stream, } // 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) { +SkString SkPDFString::FormatString(const char* cin, size_t len) { 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; + size_t characterCount = 2 + len; for (size_t i = 0; i < len; i++) { - SkASSERT(!wideInput || !(win[i] & ~0xFF)); - char val = wideInput ? win[i] : cin[i]; - if (val > '~' || val < ' ') { + if (cin[i] > '~' || cin[i] < ' ') { sevenBitClean = false; break; } + if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { + ++characterCount; + } } - SkString result; if (sevenBitClean) { - result.append("("); + result.resize(characterCount); + char* str = result.writable_str(); + *str++ = '('; for (size_t i = 0; i < len; i++) { - SkASSERT(!wideInput || !(win[i] & ~0xFF)); - char val = wideInput ? win[i] : cin[i]; - if (val == '\\' || val == '(' || val == ')') { - result.append("\\"); + if (cin[i] == '\\' || cin[i] == '(' || cin[i] == ')') { + *str++ = '\\'; } - result.append(&val, 1); + *str++ = cin[i]; } - result.append(")"); + *str++ = ')'; } else { - result.append("<"); + result.resize(2 * len + 2); + char* str = result.writable_str(); + *str++ = '<'; for (size_t i = 0; i < len; i++) { - SkASSERT(!wideInput || !(win[i] & ~0xFF)); - unsigned char val = wideInput ? win[i] : cin[i]; - result.appendHex(val, 2); + uint8_t c = static_cast(cin[i]); + static const char gHex[] = "0123456789ABCDEF"; + *str++ = gHex[(c >> 4) & 0xF]; + *str++ = gHex[(c ) & 0xF]; } - result.append(">"); + *str++ = '>'; } - return result; } diff --git a/src/pdf/SkPDFTypes.h b/src/pdf/SkPDFTypes.h index 0a16bf9..dca96e4 100644 --- a/src/pdf/SkPDFTypes.h +++ b/src/pdf/SkPDFTypes.h @@ -173,13 +173,6 @@ public: explicit SkPDFString(const char value[]); explicit SkPDFString(const SkString& value); - /** Create a PDF string. Maximum length (in bytes) is 65,535. - * @param value A string value. - * @param len The length of value. - * @param wideChars Indicates if the top byte in value is significant and - * should be encoded (true) or not (false). - */ - SkPDFString(const uint16_t* value, size_t len, bool wideChars); virtual ~SkPDFString(); // The SkPDFObject interface. @@ -188,16 +181,11 @@ public: const SkPDFSubstituteMap& substitutes) override; static SkString FormatString(const char* input, size_t len); - static SkString FormatString(const uint16_t* input, size_t len, - bool wideChars); private: static const size_t kMaxLen = 65535; const SkString fValue; - static SkString DoFormatString(const void* input, size_t len, - bool wideInput, bool wideOutput); - typedef SkPDFObject INHERITED; }; -- 2.7.4