SkPDF: SkPDFString is no longer aware of wide strings.
authorhalcanary <halcanary@google.com>
Tue, 7 Apr 2015 17:40:03 +0000 (10:40 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 7 Apr 2015 17:40:03 +0000 (10:40 -0700)
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
src/pdf/SkPDFTypes.cpp
src/pdf/SkPDFTypes.h

index ced075e..f624cb4 100644 (file)
@@ -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<uint8_t>(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");
     }
index e80d118..89d6a0b 100644 (file)
@@ -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<uint8_t>(cin[i]);
+            static const char gHex[] = "0123456789ABCDEF";
+            *str++ = gHex[(c >> 4) & 0xF];
+            *str++ = gHex[(c     ) & 0xF];
         }
-        result.append(">");
+        *str++ = '>';
     }
-
     return result;
 }
 
index 0a16bf9..dca96e4 100644 (file)
@@ -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;
 };