Add DoNotDropColorBitmapTables() API.

Adding a API not to drop CBDT/CBLC tables. OTS doesn't recognize the tables
for now, but trusts users of this API, assuming users exactly know the risks.

BUG=324187
R=ksakamoto@chromium.org

Review URL: https://codereview.chromium.org/341983012

git-svn-id: http://ots.googlecode.com/svn/trunk@114 a4e77c2c-9104-11de-800e-5b313e0d2bf3
diff --git a/include/opentype-sanitiser.h b/include/opentype-sanitiser.h
index 6a3492f..4952426 100644
--- a/include/opentype-sanitiser.h
+++ b/include/opentype-sanitiser.h
@@ -192,8 +192,12 @@
 void DisableDebugOutput();
 
 // Enable WOFF2 support(experimental).
+// TODO(bashi): Remove WOFF2 from OTS.
 void EnableWOFF2();
 
+// Force to disable dropping CBDT/CBLC tables.
+void DoNotDropColorBitmapTables();
+
 }  // namespace ots
 
 #endif  // OPENTYPE_SANITISER_H_
diff --git a/ots-common.gypi b/ots-common.gypi
index 9cb539c..51f7cec 100644
--- a/ots-common.gypi
+++ b/ots-common.gypi
@@ -7,6 +7,10 @@
     'ots_sources': [
       'include/ots-memory-stream.h',
       'include/opentype-sanitiser.h',
+      'src/cbdt.cc',
+      'src/cbdt.h',
+      'src/cblc.cc',
+      'src/cblc.h',
       'src/cff.cc',
       'src/cff.h',
       'src/cff_type2_charstring.cc',
diff --git a/ots-standalone.gyp b/ots-standalone.gyp
index c1e2530..90ab4ec 100644
--- a/ots-standalone.gyp
+++ b/ots-standalone.gyp
@@ -83,6 +83,9 @@
       'sources': [
         '<@(ots_sources)',
       ],
+      'defines': [
+        'OTS_DEBUG',
+      ],
       'dependencies': [
         'third_party/lzma_sdk/lzma_sdk.gyp:ots_lzma_sdk',
       ],
diff --git a/src/cbdt.cc b/src/cbdt.cc
new file mode 100644
index 0000000..aff74f1
--- /dev/null
+++ b/src/cbdt.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cbdt.h"
+
+// CBDT
+// https://color-emoji.googlecode.com/git/specification/v1.html
+// We don't support the table, but provide a way not to drop the table.
+
+namespace ots {
+
+extern bool g_drop_color_bitmap_tables;
+
+bool ots_cbdt_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  if (g_drop_color_bitmap_tables) {
+    return OTS_FAILURE();
+  }
+
+  file->cbdt = new OpenTypeCBDT;
+  file->cbdt->data = data;
+  file->cbdt->length = length;
+  return true;
+}
+
+bool ots_cbdt_should_serialise(OpenTypeFile *file) {
+  return file->cbdt != NULL && file->cblc != NULL;
+}
+
+bool ots_cbdt_serialise(OTSStream *out, OpenTypeFile *file) {
+  if (!out->Write(file->cbdt->data, file->cbdt->length)) {
+    return OTS_FAILURE();
+  }
+  return true;
+}
+
+void ots_cbdt_free(OpenTypeFile *file) {
+  delete file->cbdt;
+}
+
+}  // namespace ots
diff --git a/src/cbdt.h b/src/cbdt.h
new file mode 100644
index 0000000..bda075f
--- /dev/null
+++ b/src/cbdt.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef OTS_CBDT_H_
+#define OTS_CBDT_H_
+
+#include "ots.h"
+
+namespace ots {
+
+struct OpenTypeCBDT {
+  OpenTypeCBDT()
+      : data(NULL),
+        length(0) {
+  }
+
+  const uint8_t *data;
+  size_t length;
+};
+
+}  // namespace ots
+
+#endif  // OTS_CBDT_H_
diff --git a/src/cblc.cc b/src/cblc.cc
new file mode 100644
index 0000000..19cfd7d
--- /dev/null
+++ b/src/cblc.cc
@@ -0,0 +1,41 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cblc.h"
+
+// CBLC
+// https://color-emoji.googlecode.com/git/specification/v1.html
+// We don't support the table, but provide a way not to drop the table.
+
+namespace ots {
+
+extern bool g_drop_color_bitmap_tables;
+
+bool ots_cblc_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  if (g_drop_color_bitmap_tables) {
+    return OTS_FAILURE();
+  }
+
+  file->cblc = new OpenTypeCBLC;
+  file->cblc->data = data;
+  file->cblc->length = length;
+  return true;
+}
+
+bool ots_cblc_should_serialise(OpenTypeFile *file) {
+  return file->cblc != NULL && file->cbdt != NULL;
+}
+
+bool ots_cblc_serialise(OTSStream *out, OpenTypeFile *file) {
+  if (!out->Write(file->cblc->data, file->cblc->length)) {
+    return OTS_FAILURE();
+  }
+  return true;
+}
+
+void ots_cblc_free(OpenTypeFile *file) {
+  delete file->cblc;
+}
+
+}  // namespace ots
diff --git a/src/cblc.h b/src/cblc.h
new file mode 100644
index 0000000..373e442
--- /dev/null
+++ b/src/cblc.h
@@ -0,0 +1,24 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef OTS_CBLC_H_
+#define OTS_CBLC_H_
+
+#include "ots.h"
+
+namespace ots {
+
+struct OpenTypeCBLC {
+  OpenTypeCBLC()
+      : data(NULL),
+        length(0) {
+  }
+
+  const uint8_t *data;
+  size_t length;
+};
+
+}  // namespace ots
+
+#endif  // OTS_CBLC_H_
diff --git a/src/cmap.cc b/src/cmap.cc
index 5d52c1e..5f83839 100644
--- a/src/cmap.cc
+++ b/src/cmap.cc
@@ -848,9 +848,12 @@
   const off_t table_start = out->Tell();
 
   // Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables
-  // (e.g., old fonts for Mac). We don't support them.
+  // (e.g., old fonts for Mac). We don't support them except for color bitmap
+  // fonts.
   if (!have_304 && !have_314 && !have_034) {
-    return OTS_FAILURE();
+    if (!(file->cbdt && file->cblc)) {
+      return OTS_FAILURE();
+    }
   }
 
   if (!out->WriteU16(0) ||
diff --git a/src/ots.cc b/src/ots.cc
index 9205a26..f364191 100644
--- a/src/ots.cc
+++ b/src/ots.cc
@@ -143,6 +143,10 @@
     ots::ots_vmtx_should_serialise, ots::ots_vmtx_free, false },
   { "MATH", ots::ots_math_parse, ots::ots_math_serialise,
     ots::ots_math_should_serialise, ots::ots_math_free, false },
+  { "CBDT", ots::ots_cbdt_parse, ots::ots_cbdt_serialise,
+    ots::ots_cbdt_should_serialise, ots::ots_cbdt_free, false },
+  { "CBLC", ots::ots_cblc_parse, ots::ots_cblc_serialise,
+    ots::ots_cblc_should_serialise, ots::ots_cblc_free, false },
   // TODO(bashi): Support mort, base, and jstf tables.
   { 0, NULL, NULL, NULL, NULL, false },
 };
@@ -557,9 +561,8 @@
       return OTS_FAILURE();
     }
   } else {
-    if (!header->glyf || !header->loca) {
-      // No TrueType glyph found.
-      // Note: bitmap-only fonts are not supported.
+    if ((!header->glyf || !header->loca) && (!header->cbdt || !header->cblc)) {
+      // No TrueType glyph or color bitmap found.
       return OTS_FAILURE();
     }
   }
@@ -685,6 +688,8 @@
 
 namespace ots {
 
+bool g_drop_color_bitmap_tables = true;
+
 bool IsValidVersionTag(uint32_t tag) {
   return tag == Tag("\x00\x01\x00\x00") ||
          // OpenType fonts with CFF data have 'OTTO' tag.
@@ -702,6 +707,10 @@
   g_enable_woff2 = true;
 }
 
+void DoNotDropColorBitmapTables() {
+  g_drop_color_bitmap_tables = false;
+}
+
 bool Process(OTSStream *output, const uint8_t *data, size_t length) {
   OpenTypeFile header;
   if (length < 4) {
diff --git a/src/ots.h b/src/ots.h
index 4ee9584..1db48d5 100644
--- a/src/ots.h
+++ b/src/ots.h
@@ -183,6 +183,8 @@
 bool IsValidVersionTag(uint32_t tag);
 
 #define FOR_EACH_TABLE_TYPE \
+  F(cbdt, CBDT) \
+  F(cblc, CBLC) \
   F(cff, CFF) \
   F(cmap, CMAP) \
   F(cvt, CVT) \