[indic-table] Speed up lookup
diff --git a/src/gen-indic-table.py b/src/gen-indic-table.py
index b568d1e..e94c3e5 100755
--- a/src/gen-indic-table.py
+++ b/src/gen-indic-table.py
@@ -194,11 +194,23 @@
 print "INDIC_TABLE_ELEMENT_TYPE"
 print "hb_indic_get_categories (hb_codepoint_t u)"
 print "{"
-for (start,end) in zip (starts, ends):
-	offset = "indic_offset_0x%04x" % start
-	print "  if (0x%04X <= u && u <= 0x%04X) return indic_table[u - 0x%04X + %s];" % (start, end, start, offset)
-for u,d in singles.items ():
-	print "  if (unlikely (u == 0x%04X)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])
+print "  switch (u >> 12)"
+print "  {"
+pages = set([u>>12 for u in starts+ends+singles.keys()])
+for p in pages:
+	print "    case 0x%0X:" % p
+	for (start,end) in zip (starts, ends):
+		if p not in [start>>12, end>>12]: continue
+		offset = "indic_offset_0x%04x" % start
+		print "      if (0x%04X <= u && u <= 0x%04X) return indic_table[u - 0x%04X + %s];" % (start, end, start, offset)
+	for u,d in singles.items ():
+		if p != u>>12: continue
+		print "      if (unlikely (u == 0x%04X)) return _(%s,%s);" % (u, short[0][d[0]], short[1][d[1]])
+	print "      break;"
+	print ""
+print "    default:"
+print "      break;"
+print "  }"
 print "  return _(x,x);"
 print "}"
 print
diff --git a/src/hb-ot-shape-complex-indic-table.cc b/src/hb-ot-shape-complex-indic-table.cc
index e37509f..642c4e3 100644
--- a/src/hb-ot-shape-complex-indic-table.cc
+++ b/src/hb-ot-shape-complex-indic-table.cc
@@ -732,25 +732,48 @@
 INDIC_TABLE_ELEMENT_TYPE
 hb_indic_get_categories (hb_codepoint_t u)
 {
-  if (0x0900 <= u && u <= 0x0EE0) return indic_table[u - 0x0900 + indic_offset_0x0900];
-  if (0x0F40 <= u && u <= 0x0FC0) return indic_table[u - 0x0F40 + indic_offset_0x0f40];
-  if (0x1000 <= u && u <= 0x10A0) return indic_table[u - 0x1000 + indic_offset_0x1000];
-  if (0x1700 <= u && u <= 0x17E0) return indic_table[u - 0x1700 + indic_offset_0x1700];
-  if (0x1900 <= u && u <= 0x1A80) return indic_table[u - 0x1900 + indic_offset_0x1900];
-  if (0x1B00 <= u && u <= 0x1C50) return indic_table[u - 0x1B00 + indic_offset_0x1b00];
-  if (0x1CF0 <= u && u <= 0x1CF8) return indic_table[u - 0x1CF0 + indic_offset_0x1cf0];
-  if (0xA800 <= u && u <= 0xA8C8) return indic_table[u - 0xA800 + indic_offset_0xa800];
-  if (0xA908 <= u && u <= 0xA9C8) return indic_table[u - 0xA908 + indic_offset_0xa908];
-  if (0xAA00 <= u && u <= 0xAAF8) return indic_table[u - 0xAA00 + indic_offset_0xaa00];
-  if (0xABC0 <= u && u <= 0xABF0) return indic_table[u - 0xABC0 + indic_offset_0xabc0];
-  if (0x10A00 <= u && u <= 0x10A40) return indic_table[u - 0x10A00 + indic_offset_0x10a00];
-  if (0x11000 <= u && u <= 0x11048) return indic_table[u - 0x11000 + indic_offset_0x11000];
-  if (0x11080 <= u && u <= 0x110C0) return indic_table[u - 0x11080 + indic_offset_0x11080];
-  if (0x11100 <= u && u <= 0x11138) return indic_table[u - 0x11100 + indic_offset_0x11100];
-  if (0x11180 <= u && u <= 0x111C8) return indic_table[u - 0x11180 + indic_offset_0x11180];
-  if (0x11680 <= u && u <= 0x116B8) return indic_table[u - 0x11680 + indic_offset_0x11680];
-  if (unlikely (u == 0x00A0)) return _(CP,x);
-  if (unlikely (u == 0x25CC)) return _(CP,x);
+  switch (u >> 12)
+  {
+    case 0x0:
+      if (0x0900 <= u && u <= 0x0EE0) return indic_table[u - 0x0900 + indic_offset_0x0900];
+      if (0x0F40 <= u && u <= 0x0FC0) return indic_table[u - 0x0F40 + indic_offset_0x0f40];
+      if (unlikely (u == 0x00A0)) return _(CP,x);
+      break;
+
+    case 0x1:
+      if (0x1000 <= u && u <= 0x10A0) return indic_table[u - 0x1000 + indic_offset_0x1000];
+      if (0x1700 <= u && u <= 0x17E0) return indic_table[u - 0x1700 + indic_offset_0x1700];
+      if (0x1900 <= u && u <= 0x1A80) return indic_table[u - 0x1900 + indic_offset_0x1900];
+      if (0x1B00 <= u && u <= 0x1C50) return indic_table[u - 0x1B00 + indic_offset_0x1b00];
+      if (0x1CF0 <= u && u <= 0x1CF8) return indic_table[u - 0x1CF0 + indic_offset_0x1cf0];
+      break;
+
+    case 0x2:
+      if (unlikely (u == 0x25CC)) return _(CP,x);
+      break;
+
+    case 0xA:
+      if (0xA800 <= u && u <= 0xA8C8) return indic_table[u - 0xA800 + indic_offset_0xa800];
+      if (0xA908 <= u && u <= 0xA9C8) return indic_table[u - 0xA908 + indic_offset_0xa908];
+      if (0xAA00 <= u && u <= 0xAAF8) return indic_table[u - 0xAA00 + indic_offset_0xaa00];
+      if (0xABC0 <= u && u <= 0xABF0) return indic_table[u - 0xABC0 + indic_offset_0xabc0];
+      break;
+
+    case 0x10:
+      if (0x10A00 <= u && u <= 0x10A40) return indic_table[u - 0x10A00 + indic_offset_0x10a00];
+      break;
+
+    case 0x11:
+      if (0x11000 <= u && u <= 0x11048) return indic_table[u - 0x11000 + indic_offset_0x11000];
+      if (0x11080 <= u && u <= 0x110C0) return indic_table[u - 0x11080 + indic_offset_0x11080];
+      if (0x11100 <= u && u <= 0x11138) return indic_table[u - 0x11100 + indic_offset_0x11100];
+      if (0x11180 <= u && u <= 0x111C8) return indic_table[u - 0x11180 + indic_offset_0x11180];
+      if (0x11680 <= u && u <= 0x116B8) return indic_table[u - 0x11680 + indic_offset_0x11680];
+      break;
+
+    default:
+      break;
+  }
   return _(x,x);
 }