SkPDF: Fix encoding of unichr outside of basic plane
authorhalcanary <halcanary@google.com>
Thu, 7 Jul 2016 19:31:55 +0000 (12:31 -0700)
committerCommit bot <commit-bot@chromium.org>
Thu, 7 Jul 2016 19:31:55 +0000 (12:31 -0700)
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

src/pdf/SkPDFDevice.cpp
src/pdf/SkPDFFont.cpp
src/pdf/SkPDFUtils.h

index 12698dc00b012117466c1b4eb1cd00866f4516b0..7c366cdae7a6159d3605e127720b0bc263f4e295 100644 (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 {
index 99b633508ffa6b61966be80699d211aebbac2d8a..0fce0b98d6d757e195c2a9648464ebcfd9a5f104 100644 (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");
index cb6e29fe4151ad35ed7a1c99132aa1a5e7a68cd2..124e19961481a6d48da583f8a00c923fe1ef0b03 100644 (file)
 
 #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