Bring in font-rs again

Change-Id: Id9d98d2378be521f92a1cb086888945cdba3bd63
diff --git a/rustc_deps/Cargo.lock b/rustc_deps/Cargo.lock
index 1963ccb..f458337 100644
--- a/rustc_deps/Cargo.lock
+++ b/rustc_deps/Cargo.lock
@@ -366,6 +366,14 @@
 ]
 
 [[package]]
+name = "font-rs"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "fuchsia-third-party"
 version = "0.1.0"
 dependencies = [
@@ -380,6 +388,7 @@
  "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "encode_unicode 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "font-rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "futures 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1497,6 +1506,7 @@
 "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
 "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
+"checksum font-rs 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4cb8573fe62dde0496216a0996914b7df6e86e996437089bd3cbb9961b2a10e9"
 "checksum futures 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d81ccac876e9e5efad47774552d1ecc05828886ad64468bc716595659bd078cb"
 "checksum futures-async-runtime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bab8d196f9bcbc3b33148960602889bf44c74afe5bea20ee970aaa08df2db2f5"
 "checksum futures-channel 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bbb37ec6418c577b25f5b129c0f4456ad7ce8714ec43c59712aa7e4cd2cb6b85"
diff --git a/rustc_deps/Cargo.toml b/rustc_deps/Cargo.toml
index a10d774..1812bde 100644
--- a/rustc_deps/Cargo.toml
+++ b/rustc_deps/Cargo.toml
@@ -19,6 +19,7 @@
 crossbeam = "0.3.2"
 encode_unicode = "0.1.3"
 failure = "0.1.1"
+font-rs = "0.1.2"
 futures = "0.2.1"
 getopts = "0.2"
 hex = "0.3.2"
diff --git a/rustc_deps/vendor/font-rs/.cargo-checksum.json b/rustc_deps/vendor/font-rs/.cargo-checksum.json
new file mode 100644
index 0000000..0e8eb50
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{".travis.yml":"3dd668ecd6aff316698f4e462e0a81d8d6788b0068f1c3a02cfe6848f86c16b0","CONTRIBUTING.md":"8f3a78ee312b1d3010d7061cf08a92a54235452e9834d2b541b292ad8fe56611","Cargo.toml":"eed33e13b25ba70f05e847792b9fe621e87c02a439d9b6de43bcd44549100651","LICENSE":"cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30","README.md":"6bd80ec4463ceb274f3ca347098fbc5e58866f734412f2dd6a145deae0ba1cbc","benches/glyph.rs":"7dfc29a437b7f06717cd6483c670ac00343ba3cddb9a68502da1e227d0991ded","benches/raster.rs":"01cc1879a103ca6508eeb2f4268b559badd16a96dd68c4f6c8f77e5e05ff6eda","build.rs":"32d3e6a0235ec2f28e6c055e22ebd3bc658e966c529d3daf2113ea89e6aa043a","examples/draw_shape.rs":"10c03b77650cf393f1fa9fafadc30fa6febfb44652d23937be2166528fb7f0a6","examples/render.rs":"dc4069ac340212fbb65db3d0fd47668fabba2da8d34fbbaf1bb72657df468e2a","fonts/notomono-hinted/LICENSE_OFL.txt":"6a73f9541c2de74158c0e7cf6b0a58ef774f5a780bf191f2d7ec9cc53efe2bf2","fonts/notomono-hinted/NotoMono-Regular.ttf":"41fd7ccc82375e2a1e47f0cc2c941c14d7c99ba2f57cf69c9f738d07fb257686","fonts/notomono-hinted/README":"549bf0ba6b9cd63236f4f02fb217a53384984df7bced8f268ed9bb2e7839e317","rustfmt.toml":"f44b130f9ce2d1ecccffbe0c81ea4dd447c13d5e6368165894f6a51f3c5bae2c","src/accumulate.c":"8cabb5ab5c310a9cb162607f21741990d797fc7936153a140a59c48bb3ba0c19","src/accumulate.rs":"7080ab0b700f22affd5878c196fa1a0fd9132de275fba120f2494668d029fac8","src/font.rs":"e47a3ddb23b5566d9481fa54c7b75187198554bc0835d216ffc0322df2cee5e3","src/geom.rs":"38c7d2e24f64f286bfa92ffbd035462084a9fb3d046f46964175de643548102c","src/lib.rs":"f06fd1c6b52ab3a7555fe1bf3551c655003e6363de4025dcc45978eb0414311e","src/macros.rs":"1487e7d99cc29064b58fddb144434fab84b599aaae2f928d6a3ad9c52d6e05a2","src/raster.rs":"1ddf13684700e71bdcea44b90bef447374457c8b26f334fa53586b95238e252f"},"package":"4cb8573fe62dde0496216a0996914b7df6e86e996437089bd3cbb9961b2a10e9"}
\ No newline at end of file
diff --git a/rustc_deps/vendor/font-rs/.travis.yml b/rustc_deps/vendor/font-rs/.travis.yml
new file mode 100644
index 0000000..8cd873b
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/.travis.yml
@@ -0,0 +1,22 @@
+language: rust
+rust:
+  - stable
+  - beta
+  - nightly
+cache:
+  - apt
+  - cargo
+
+os:
+  - linux
+
+script:
+  - cargo build --verbose --features ""
+  - cargo test --verbose --features ""
+  - cargo build --verbose --features sse
+  - cargo test --verbose --features sse
+  - |
+    if [[ "$TRAVIS_RUST_VERSION" == "nightly" ]]; then
+      cargo bench --features ""
+      cargo bench --features "sse"
+    fi
diff --git a/rustc_deps/vendor/font-rs/CONTRIBUTING.md b/rustc_deps/vendor/font-rs/CONTRIBUTING.md
new file mode 100644
index 0000000..1ba8539
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/CONTRIBUTING.md
@@ -0,0 +1,24 @@
+Want to contribute? Great! First, read this page (including the small print at the end).
+
+### Before you contribute
+Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1)
+(CLA), which you can do online. The CLA is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things—for instance that you'll tell us if you
+know that your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first through the issue tracker with your idea so that we can help out and
+possibly guide you. Coordinating up front makes it much easier to avoid
+frustration later on.
+
+### Code reviews
+All submissions, including submissions by project members, require review. We
+use Github pull requests for this purpose.
+
+### The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the Software Grant and Corporate Contributor License Agreement.
diff --git a/rustc_deps/vendor/font-rs/Cargo.toml b/rustc_deps/vendor/font-rs/Cargo.toml
new file mode 100644
index 0000000..776b4fa
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/Cargo.toml
@@ -0,0 +1,26 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "font-rs"
+version = "0.1.2"
+authors = ["Raph Levien <raph@google.com>"]
+build = "build.rs"
+description = "A font renderer written (mostly) in pure, safe Rust"
+keywords = ["font", "truetype", "ttf"]
+license = "Apache-2.0"
+repository = "https://github.com/google/font-rs"
+[build-dependencies.gcc]
+version = "0.3"
+
+[features]
+sse = []
diff --git a/rustc_deps/vendor/font-rs/LICENSE b/rustc_deps/vendor/font-rs/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/rustc_deps/vendor/font-rs/README.md b/rustc_deps/vendor/font-rs/README.md
new file mode 100644
index 0000000..76e3275
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/README.md
@@ -0,0 +1,44 @@
+# font-rs
+
+This is a font renderer written (mostly) in pure, safe Rust. There is an optional
+SIMD module for cumulative sum, currently written in C SSE3 intrinsics.
+
+The current state of the code is quite rough. The code isn't well organized,
+and it's basically not ready for prime time. However, it runs well enough to
+run benchmarks, and those benchmarks suggest extremely promising performance
+compared with Freetype and freetype-go (the loose port of Freetype to Go).
+
+The rasterizer is basically very similar in design to
+[libart](https://people.gnome.org/~mathieu/libart/internals.html), except that
+vectors are drawn immediately into the buffer, rather than sorted and stored
+in intermediate form, and that the buffer for rasterization is a dense array
+rather than a sparse data structure. The main motivation for the latter is to
+avoid branch misprediction and to better exploit data parallelism, both valid
+trends in optimization since libart was originally written.
+
+It's worth comparing the algorithm with that in
+[Anti-Grain Geometry](http://projects.tuxee.net/cl-vectors/section-the-cl-aa-algorithm).
+The original libart algorithm was also inspiration for the current antialiased
+renderer in Freetype. All these renderers share many common features,
+particularly computation of exact subpixel areas and an integration step
+to determine winding number (and convert to pixel value), but differ in details
+such as data structures to represent the vectors and the buffer.
+
+The parsing of TrueType glyph data is done in pull-parser style, as iterators
+over the lower-level data. This technique basically avoids allocating any
+memory for representation of points and quadratic Beziers.
+
+## Authors
+
+The main author is Raph Levien.
+
+## Contributions
+
+We gladly accept contributions via GitHub pull requests, as long as the author
+has signed the Google Contributor License. Please see CONTRIBUTIONS.md for
+more details.
+
+### Disclaimer
+
+This is not an official Google product (experimental or otherwise), it
+is just code that happens to be owned by Google.
diff --git a/rustc_deps/vendor/font-rs/benches/glyph.rs b/rustc_deps/vendor/font-rs/benches/glyph.rs
new file mode 100644
index 0000000..612d2af
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/benches/glyph.rs
@@ -0,0 +1,53 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#![feature(test)]
+extern crate font_rs;
+extern crate test;
+
+use font_rs::font;
+use test::Bencher;
+
+static FONT_DATA: &'static [u8] =
+    include_bytes!("../fonts/notomono-hinted/NotoMono-Regular.ttf");
+
+fn glyphbench(b: &mut Bencher, size: u32) {
+    let font = font::parse(&FONT_DATA).unwrap();
+    b.iter(|| font.render_glyph(200, size));
+}
+
+#[bench]
+fn glyph400(b: &mut Bencher) {
+    glyphbench(b, 400)
+}
+
+#[bench]
+fn glyph100(b: &mut Bencher) {
+    glyphbench(b, 100)
+}
+
+#[bench]
+fn glyph040(b: &mut Bencher) {
+    glyphbench(b, 40)
+}
+
+#[bench]
+fn glyph020(b: &mut Bencher) {
+    glyphbench(b, 20)
+}
+
+#[bench]
+fn glyph010(b: &mut Bencher) {
+    glyphbench(b, 10)
+}
diff --git a/rustc_deps/vendor/font-rs/benches/raster.rs b/rustc_deps/vendor/font-rs/benches/raster.rs
new file mode 100644
index 0000000..759649b
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/benches/raster.rs
@@ -0,0 +1,109 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#![feature(test)]
+extern crate font_rs;
+extern crate test;
+
+use font_rs::geom::Point;
+use font_rs::raster::*;
+use test::Bencher;
+
+fn draw_shape(r: &mut Raster, s: f32) {
+    r.draw_line(
+        &Point::new(s * 10.0, s * 10.5),
+        &Point::new(s * 20.0, s * 150.0),
+    );
+    r.draw_line(
+        &Point::new(s * 20.0, s * 150.0),
+        &Point::new(s * 50.0, s * 139.0),
+    );
+    r.draw_quad(
+        &Point::new(s * 50.0, s * 139.0),
+        &Point::new(s * 100.0, s * 60.0),
+        &Point::new(s * 10.0, s * 10.5),
+    );
+}
+
+#[bench]
+fn empty200(b: &mut Bencher) {
+    b.iter(|| {
+        let w = 200;
+        let h = 200;
+        let r = Raster::new(w, h);
+        r.get_bitmap()
+    })
+}
+
+#[bench]
+fn render200(b: &mut Bencher) {
+    b.iter(|| {
+        let w = 200;
+        let h = 200;
+        let mut r = Raster::new(w, h);
+        draw_shape(&mut r, 1.0);
+        r.get_bitmap()
+    })
+}
+
+#[bench]
+fn prep200(b: &mut Bencher) {
+    b.iter(|| {
+        let w = 200;
+        let h = 200;
+        let mut r = Raster::new(w, h);
+        draw_shape(&mut r, 1.0);
+    })
+}
+
+#[bench]
+fn prep400(b: &mut Bencher) {
+    b.iter(|| {
+        let w = 400;
+        let h = 400;
+        let mut r = Raster::new(w, h);
+        draw_shape(&mut r, 2.0);
+    })
+}
+
+#[bench]
+fn render400(b: &mut Bencher) {
+    b.iter(|| {
+        let w = 400;
+        let h = 400;
+        let mut r = Raster::new(w, h);
+        draw_shape(&mut r, 2.0);
+        r.get_bitmap()
+    })
+}
+
+#[bench]
+fn empty400(b: &mut Bencher) {
+    b.iter(|| {
+        let w = 400;
+        let h = 400;
+        let r = Raster::new(w, h);
+        r.get_bitmap()
+    })
+}
+
+#[bench]
+fn alloc400(b: &mut Bencher) {
+    b.iter(|| vec![0.0; 400 * 400 + 1])
+}
+
+#[bench]
+fn alloc200(b: &mut Bencher) {
+    b.iter(|| vec![0.0; 200 * 200 + 1])
+}
diff --git a/rustc_deps/vendor/font-rs/build.rs b/rustc_deps/vendor/font-rs/build.rs
new file mode 100644
index 0000000..dead2fc
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/build.rs
@@ -0,0 +1,9 @@
+extern crate gcc;
+
+fn main() {
+    gcc::Build::new()
+        .file("src/accumulate.c")
+        .flag("-march=native")
+        .flag("-std=c99")
+        .compile("libaccumulate.a");
+}
diff --git a/rustc_deps/vendor/font-rs/examples/draw_shape.rs b/rustc_deps/vendor/font-rs/examples/draw_shape.rs
new file mode 100644
index 0000000..4a213c0
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/examples/draw_shape.rs
@@ -0,0 +1,69 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! A simple test program for exercising the rasterizer.
+
+extern crate font_rs;
+
+use std::io::{stdout, Write};
+
+use font_rs::geom::Point;
+use font_rs::raster::Raster;
+
+fn draw_shape(r: &mut Raster, s: f32) {
+    r.draw_line(
+        &Point {
+            x: s * 10.0,
+            y: s * 10.5,
+        },
+        &Point {
+            x: s * 20.0,
+            y: s * 150.0,
+        },
+    );
+    r.draw_line(
+        &Point {
+            x: s * 20.0,
+            y: s * 150.0,
+        },
+        &Point {
+            x: s * 50.0,
+            y: s * 139.0,
+        },
+    );
+    r.draw_quad(
+        &Point {
+            x: s * 50.0,
+            y: s * 139.0,
+        },
+        &Point {
+            x: s * 100.0,
+            y: s * 60.0,
+        },
+        &Point {
+            x: s * 10.0,
+            y: s * 10.5,
+        },
+    );
+}
+
+fn main() {
+    let w = 400;
+    let h = 400;
+    let mut r = Raster::new(w, h);
+    draw_shape(&mut r, 4.0);
+    let mut o = stdout();
+    let _ = o.write(format!("P5\n{} {}\n255\n", w, h).as_bytes());
+    let _ = o.write(&r.get_bitmap());
+}
diff --git a/rustc_deps/vendor/font-rs/examples/render.rs b/rustc_deps/vendor/font-rs/examples/render.rs
new file mode 100644
index 0000000..efc437b
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/examples/render.rs
@@ -0,0 +1,67 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+extern crate font_rs;
+
+use std::fs::File;
+use std::io::{Read, Write};
+use std::time::SystemTime;
+
+use font_rs::font::{parse, GlyphBitmap};
+
+fn dump_pgm(glyph: &GlyphBitmap, out_filename: &str) {
+    let mut o = File::create(&out_filename).unwrap();
+    let _ = o.write(format!("P5\n{} {}\n255\n", glyph.width, glyph.height).as_bytes());
+    println!("data len = {}", glyph.data.len());
+    let _ = o.write(&glyph.data);
+}
+
+fn main() {
+    let mut args = std::env::args();
+    let _ = args.next();
+    let filename = args.next().unwrap();
+    let glyph_id: u16 = args.next().unwrap().parse().unwrap();
+    let out_filename = args.next().unwrap();
+    let mut f = File::open(&filename).unwrap();
+    let mut data = Vec::new();
+    match f.read_to_end(&mut data) {
+        Err(e) => println!("failed to read {}, {}", filename, e),
+        Ok(_) => match parse(&data) {
+            Ok(font) => {
+                if out_filename == "__bench__" {
+                    for size in 1..201 {
+                        let start = SystemTime::now();
+                        let n_iter = 1000;
+                        for _ in 0..n_iter {
+                            match font.render_glyph(glyph_id, size) {
+                                Some(_glyph) => (),
+                                None => (),
+                            }
+                        }
+                        let elapsed = start.elapsed().unwrap();
+                        let elapsed =
+                            elapsed.as_secs() as f64 + 1e-9 * (elapsed.subsec_nanos() as f64);
+                        println!("{} {}", size, elapsed * (1e6 / n_iter as f64));
+                    }
+                } else {
+                    match font.render_glyph(glyph_id, 400) {
+                        Some(glyph) => dump_pgm(&glyph, &out_filename),
+                        None => println!("failed to render {} {}", filename, glyph_id),
+                    }
+                }
+            }
+            Err(_) => println!("failed to parse {}", filename),
+        },
+    }
+}
diff --git a/rustc_deps/vendor/font-rs/fonts/notomono-hinted/LICENSE_OFL.txt b/rustc_deps/vendor/font-rs/fonts/notomono-hinted/LICENSE_OFL.txt
new file mode 100644
index 0000000..d952d62
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/fonts/notomono-hinted/LICENSE_OFL.txt
@@ -0,0 +1,92 @@
+This Font Software is licensed under the SIL Open Font License,
+Version 1.1.
+
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font
+creation efforts of academic and linguistic communities, and to
+provide a free and open framework in which fonts may be shared and
+improved in partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply to
+any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software
+components as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to,
+deleting, or substituting -- in part or in whole -- any of the
+components of the Original Version, by changing formats or by porting
+the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed,
+modify, redistribute, and sell modified and unmodified copies of the
+Font Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components, in
+Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the
+corresponding Copyright Holder. This restriction only applies to the
+primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created using
+the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/rustc_deps/vendor/font-rs/fonts/notomono-hinted/NotoMono-Regular.ttf b/rustc_deps/vendor/font-rs/fonts/notomono-hinted/NotoMono-Regular.ttf
new file mode 100644
index 0000000..3560a3a
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/fonts/notomono-hinted/NotoMono-Regular.ttf
Binary files differ
diff --git a/rustc_deps/vendor/font-rs/fonts/notomono-hinted/README b/rustc_deps/vendor/font-rs/fonts/notomono-hinted/README
new file mode 100644
index 0000000..d228764
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/fonts/notomono-hinted/README
@@ -0,0 +1,11 @@
+This package is part of the noto project.  Visit
+google.com/get/noto for more information.
+
+Built on 2017-10-24 from the following noto repository:
+-----
+Repo: noto-fonts
+Tag: v2017-10-24-phase3-second-cleanup
+Date: 2017-10-24 12:10:34 GMT
+Commit: 8ef14e6c606a7a0ef3943b9ca01fd49445620d79
+
+Remove some files that aren't for release.
diff --git a/rustc_deps/vendor/font-rs/rustfmt.toml b/rustc_deps/vendor/font-rs/rustfmt.toml
new file mode 100644
index 0000000..14f806b
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/rustfmt.toml
@@ -0,0 +1,56 @@
+# This file was originally created by running the command
+# rustfmt --dump-default-config rustfmt.toml && sort -u rustfmt.toml -o rustfmt.toml.
+# Changes from the defaults are marked with comments.
+binop_separator = "Front"
+blank_lines_lower_bound = 0
+blank_lines_upper_bound = 1
+brace_style = "SameLineWhere"
+color = "Auto"
+combine_control_expr = true
+comment_width = 100 # Fuchsia uses 100
+condense_wildcard_suffixes = false
+control_brace_style = "AlwaysSameLine"
+disable_all_formatting = false
+empty_item_single_line = true
+error_on_line_overflow = false
+error_on_unformatted = false
+fn_args_density = "Compressed" # Fuchsia prefers compressed
+fn_single_line = false
+force_explicit_abi = true
+force_multiline_blocks = false
+format_strings = true # otherwise strings will violate max_width
+hard_tabs = false
+hide_parse_errors = false
+imports_indent = "Visual"
+imports_layout = "Mixed"
+indent_style = "Block"
+match_arm_blocks = true
+match_block_trailing_comma = false
+max_width = 100
+merge_derives = true
+merge_imports = false
+newline_style = "Unix"
+normalize_comments = false
+remove_blank_lines_at_start_or_end_of_block = true
+reorder_impl_items = false
+reorder_imports = true
+reorder_modules = true
+report_fixme = "Never"
+report_todo = "Never"
+skip_children = false
+space_after_colon = true
+space_before_colon = false
+spaces_around_ranges = false
+spaces_within_parens_and_brackets = false
+struct_field_align_threshold = 0
+struct_lit_single_line = true
+tab_spaces = 4
+trailing_comma = "Vertical"
+trailing_semicolon = true
+type_punctuation_density = "Wide"
+unstable_features = false
+use_field_init_shorthand = false
+use_small_heuristics = true
+use_try_shorthand = true # Fuchsia prefers the shortcut
+where_single_line = false
+wrap_comments = true # otherwise comments will violate max_width
diff --git a/rustc_deps/vendor/font-rs/src/accumulate.c b/rustc_deps/vendor/font-rs/src/accumulate.c
new file mode 100644
index 0000000..2551e36
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/src/accumulate.c
@@ -0,0 +1,37 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// SSE3 instrinsics for cumulative sum and conversion to pixels
+
+#include <stdint.h>
+#include <tmmintrin.h>
+
+void accumulate_sse(const float *in, uint8_t *out, uint32_t n) {
+  __m128 offset = _mm_setzero_ps();
+  __m128i mask = _mm_set1_epi32(0x0c080400);
+  __m128 sign_mask = _mm_set1_ps(-0.f);
+  for (uint32_t i = 0; i < n; i += 4) {
+    __m128 x = _mm_load_ps(&in[i]);
+    x = _mm_add_ps(x, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(x), 4)));
+    x = _mm_add_ps(x, _mm_shuffle_ps(_mm_setzero_ps(), x, 0x40));
+    x = _mm_add_ps(x, offset);
+    __m128 y = _mm_andnot_ps(sign_mask, x);  // fabs(x)
+    y = _mm_min_ps(y, _mm_set1_ps(1.0f));
+    y = _mm_mul_ps(y, _mm_set1_ps(255.0f));
+    __m128i z = _mm_cvttps_epi32(y);
+    z = _mm_shuffle_epi8(z, mask);
+    _mm_store_ss((float *)&out[i], _mm_castsi128_ps(z));
+    offset = _mm_shuffle_ps(x, x, _MM_SHUFFLE(3, 3, 3, 3));
+  }
+}
diff --git a/rustc_deps/vendor/font-rs/src/accumulate.rs b/rustc_deps/vendor/font-rs/src/accumulate.rs
new file mode 100644
index 0000000..8766aa2
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/src/accumulate.rs
@@ -0,0 +1,154 @@
+// Copyright 2018 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#[cfg(feature = "sse")]
+#[link(name = "accumulate")]
+extern "C" {
+    fn accumulate_sse(src: *const f32, dst: *mut u8, n: u32);
+}
+
+#[cfg(feature = "sse")]
+pub fn accumulate(src: &[f32]) -> Vec<u8> {
+    // SIMD instructions force us to align data since we iterate each 4 elements
+    // So:
+    // n (0) => 0
+    // n (1 or 2 or 3 or 4) => 4,
+    // n (5) => 8
+    // and so on
+    let len = src.len();
+    let n = (len + 3) & !3; // align data
+    let mut dst: Vec<u8> = Vec::with_capacity(n);
+    unsafe {
+        accumulate_sse(src.as_ptr(), dst.as_mut_ptr(), n as u32);
+        dst.set_len(len); // we must return vec of the same length as src.len()
+    }
+    dst
+}
+
+#[cfg(not(feature = "sse"))]
+pub fn accumulate(src: &[f32]) -> Vec<u8> {
+    let mut acc = 0.0;
+    src.iter()
+        .map(|c| {
+            // This would translate really well to SIMD
+            acc += c;
+            let y = acc.abs();
+            let y = if y < 1.0 { y } else { 1.0 };
+            (255.0 * y) as u8
+        })
+        .collect()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    // The most simple and straightforward implementation of
+    //  accumulate fn
+    fn accumulate_simple_impl(src: &[f32]) -> Vec<u8> {
+        let mut acc = 0.0;
+        src.iter()
+            .map(|c| {
+                acc += c;
+                let y = acc.abs();
+                let y = if y < 1.0 { y } else { 1.0 };
+                (255.0 * y) as u8
+            })
+            .collect()
+    }
+    fn test_accumulate(src: Vec<f32>) {
+        assert_eq!(accumulate_simple_impl(&src), accumulate(&src));
+    }
+
+    #[test]
+    fn max_255_from_1_0() {
+        // 1.0 * 255.0 = 255.0 (max value)
+        test_accumulate(vec![1.0]);
+    }
+    #[test]
+    fn max_255_from_0_5() {
+        // 0.5 * 2 = 1.0
+        // 1.0 * 255.0 = 255.0 (max value)
+        test_accumulate(vec![0.5; 2]);
+    }
+    #[test]
+    fn max_255_from_0_25() {
+        // 0.25 * 4 = 1.0
+        // 1.0 * 255.0 = 255.0 (max value)
+        test_accumulate(vec![0.25; 4]);
+    }
+    #[test]
+    fn max_255_from_0_125() {
+        // 0.125 * 8 = 1.0
+        // 1.0 * 255.0 = 255.0 (max value)
+        test_accumulate(vec![0.125; 8]);
+    }
+    #[test]
+    fn max_255_from_0_0625() {
+        // 0.0625 * 16 = 1.0
+        // 1.0 * 255.0 = 255.0 (max value)
+        test_accumulate(vec![0.0625; 16]);
+    }
+    #[test]
+    fn max_255_from_0_03125() {
+        // 0.03125 * 32 = 1.0
+        // 1.0 * 255.0 = 255.0 (max value)
+        test_accumulate(vec![0.03125; 32]);
+    }
+    #[test]
+    fn max_255_from_0_015625() {
+        // 0.015625 * 64 = 1.0
+        // 1.0 * 255.0 = 255.0 (max value)
+        test_accumulate(vec![0.015625; 64]);
+    }
+    #[test]
+    fn max_255_from_0_0078125() {
+        // 0.0078125 * 128 = 1.0
+        // 1.0 * 255.0 = 255.0 (max value)
+        test_accumulate(vec![0.0078125; 128]);
+    }
+
+    #[test]
+    fn simple_0() {
+        test_accumulate(vec![]);
+    }
+    #[test]
+    fn simple_1() {
+        test_accumulate(vec![0.1]);
+    }
+    #[test]
+    fn simple_2() {
+        test_accumulate(vec![0.1, 0.2]);
+    }
+    #[test]
+    fn simple_3() {
+        test_accumulate(vec![0.1, 0.2, 0.3]);
+    }
+    #[test]
+    fn simple_4() {
+        test_accumulate(vec![0.1, 0.2, 0.3, 0.4]);
+    }
+    #[test]
+    fn simple_5() {
+        test_accumulate(vec![0.1, 0.2, 0.3, 0.4, 0.5]);
+    }
+    #[test]
+    fn simple_6() {
+        test_accumulate(vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6]);
+    }
+    #[test]
+    fn simple_7() {
+        test_accumulate(vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7]);
+    }
+}
diff --git a/rustc_deps/vendor/font-rs/src/font.rs b/rustc_deps/vendor/font-rs/src/font.rs
new file mode 100644
index 0000000..8f741fc
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/src/font.rs
@@ -0,0 +1,1083 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! A simple renderer for TrueType fonts
+
+use std::collections::HashMap;
+use std::fmt;
+use std::fmt::{Debug, Display, Formatter};
+use std::result::Result;
+
+use geom::{affine_pt, Affine, Point};
+use raster::Raster;
+
+#[derive(PartialEq, Eq, Hash)]
+struct Tag(u32);
+
+impl Tag {
+    fn from_str(s: &str) -> Tag {
+        Tag(get_u32(s.as_bytes(), 0).unwrap())
+    }
+}
+
+impl Display for Tag {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        let &Tag(tag) = self;
+        let buf = vec![
+            ((tag >> 24) & 0xff) as u8,
+            ((tag >> 16) & 0xff) as u8,
+            ((tag >> 8) & 0xff) as u8,
+            (tag & 0xff) as u8,
+        ];
+        f.write_str(&String::from_utf8(buf).unwrap())
+    }
+}
+
+fn get_u16(data: &[u8], off: usize) -> Option<u16> {
+    if off + 1 > data.len() {
+        None
+    } else {
+        Some(((data[off] as u16) << 8) | data[off + 1] as u16)
+    }
+}
+
+fn get_i16(data: &[u8], off: usize) -> Option<i16> {
+    get_u16(data, off).map(|x| x as i16)
+}
+
+fn get_f2_14(data: &[u8], off: usize) -> Option<f32> {
+    get_i16(data, off).map(|x| x as f32 * (1.0 / (1 << 14) as f32))
+}
+
+fn get_u32(data: &[u8], off: usize) -> Option<u32> {
+    if off + 3 > data.len() {
+        None
+    } else {
+        Some(
+            ((data[off] as u32) << 24)
+                | ((data[off + 1] as u32) << 16)
+                | ((data[off + 2] as u32) << 8)
+                | data[off + 3] as u32,
+        )
+    }
+}
+
+// TODO: be consistent, use newtype or one-field struct everywhere
+struct Head<'a>(&'a [u8]);
+
+impl<'a> Head<'a> {
+    fn index_to_loc_format(&self) -> i16 {
+        get_i16(self.0, 50).unwrap()
+    }
+
+    fn units_per_em(&self) -> u16 {
+        get_u16(self.0, 18).unwrap()
+    }
+}
+
+struct Maxp<'a> {
+    data: &'a [u8],
+}
+
+impl<'a> Maxp<'a> {
+    fn num_glyphs(&self) -> u16 {
+        get_u16(self.data, 4).unwrap()
+    }
+}
+
+struct Loca<'a>(&'a [u8]);
+
+impl<'a> Loca<'a> {
+    fn get_off(&self, glyph_ix: u16, fmt: i16) -> Option<u32> {
+        if fmt != 0 {
+            get_u32(self.0, glyph_ix as usize * 4)
+        } else {
+            get_u16(self.0, glyph_ix as usize * 2).map(|raw| raw as u32 * 2)
+        }
+    }
+}
+
+struct EncodingRecord<'a>(&'a [u8]);
+
+impl<'a> EncodingRecord<'a> {
+    fn get_platform_id(&self) -> u16 {
+        get_u16(self.0, 0).unwrap()
+    }
+
+    fn get_encoding_id(&self) -> u16 {
+        get_u16(self.0, 2).unwrap()
+    }
+
+    fn get_offset(&self) -> u32 {
+        get_u32(self.0, 4).unwrap()
+    }
+}
+
+impl<'a> Debug for EncodingRecord<'a> {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        f.debug_struct("EncodingRecord")
+            .field("platformID", &self.get_platform_id())
+            .field("encodingID", &self.get_encoding_id())
+            .field("offset", &self.get_offset())
+            .finish()
+    }
+}
+
+struct Encoding<'a>(&'a [u8]);
+
+impl<'a> Encoding<'a> {
+    fn get_format(&self) -> u16 {
+        get_u16(self.0, 0).unwrap()
+    }
+
+    fn get_length(&self) -> u16 {
+        get_u16(self.0, 2).unwrap()
+    }
+
+    fn get_language(&self) -> u16 {
+        get_u16(self.0, 4).unwrap()
+    }
+}
+
+impl<'a> Debug for Encoding<'a> {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        f.debug_struct("Encoding")
+            .field("format", &self.get_format())
+            .field("length", &self.get_length())
+            .field("language", &self.get_language())
+            .finish()
+    }
+}
+
+struct EncodingFormat4<'a>(&'a [u8]);
+
+impl<'a> EncodingFormat4<'a> {
+    fn get_format(&self) -> u16 {
+        get_u16(self.0, 0).unwrap()
+    }
+
+    fn get_length(&self) -> u16 {
+        get_u16(self.0, 2).unwrap()
+    }
+
+    fn get_language(&self) -> u16 {
+        get_u16(self.0, 4).unwrap()
+    }
+
+    fn get_seg_count_x_2(&self) -> u16 {
+        get_u16(self.0, 6).unwrap()
+    }
+
+    fn get_seg_count(&self) -> u16 {
+        self.get_seg_count_x_2() / 2
+    }
+
+    fn get_search_range(&self) -> u16 {
+        get_u16(self.0, 8).unwrap()
+    }
+
+    fn get_entry_selector(&self) -> u16 {
+        get_u16(self.0, 10).unwrap()
+    }
+
+    fn get_range_shift(&self) -> u16 {
+        get_u16(self.0, 12).unwrap()
+    }
+
+    fn get_u16_vec(&self, start_position: u16, count: u16) -> Vec<u16> {
+        let mut result = vec![];
+        let mut vec_position = start_position;
+        let limit = vec_position + 2 * count;
+        while vec_position < limit {
+            result.push(get_u16(self.0, vec_position as usize).unwrap());
+            vec_position += 2;
+        }
+        result
+    }
+
+    fn get_i16_vec(&self, start_position: u16, count: u16) -> Vec<i16> {
+        let mut result = vec![];
+        let mut vec_position = start_position;
+        let limit = vec_position + 2 * count;
+        while vec_position < limit {
+            result.push(get_i16(self.0, vec_position as usize).unwrap());
+            vec_position += 2;
+        }
+        result
+    }
+
+    fn get_end_counts_position() -> u16 {
+        14
+    }
+
+    fn get_end_counts(&self) -> Vec<u16> {
+        let seg_count = self.get_seg_count();
+        self.get_u16_vec(Self::get_end_counts_position(), seg_count)
+    }
+
+    fn get_start_counts_position(seg_count: u16) -> u16 {
+        Self::get_end_counts_position() + 2 + 2 * seg_count
+    }
+
+    fn get_start_counts(&self) -> Vec<u16> {
+        let seg_count = self.get_seg_count();
+        self.get_u16_vec(Self::get_start_counts_position(seg_count), seg_count)
+    }
+
+    fn get_id_deltas_position(seg_count: u16) -> u16 {
+        Self::get_start_counts_position(seg_count) + 2 * seg_count
+    }
+
+    fn get_id_deltas(&self) -> Vec<i16> {
+        let seg_count = self.get_seg_count();
+        self.get_i16_vec(Self::get_id_deltas_position(seg_count), seg_count)
+    }
+
+    fn get_id_range_offset_position(seg_count: u16) -> u16 {
+        Self::get_id_deltas_position(seg_count) + 2 * seg_count
+    }
+
+    fn get_id_range_offsets(&self) -> Vec<u16> {
+        let seg_count = self.get_seg_count();
+        self.get_u16_vec(Self::get_id_range_offset_position(seg_count), seg_count)
+    }
+
+    fn extract_glyph_id(
+        &self, code_point: u16, start_value: u16, seg_count: u16, seg_index: u16,
+    ) -> Option<u16> {
+        let data = self.0;
+        let seg_index_pos = 2 * seg_index;
+        let id_range_offset_pos = Self::get_id_range_offset_position(seg_count) + seg_index_pos;
+        let id_range_offset_value = get_u16(data, id_range_offset_pos as usize).unwrap();
+        let id_delta_pos = Self::get_id_deltas_position(seg_count) + seg_index_pos;
+        let id_delta = get_i16(data, id_delta_pos as usize).unwrap();
+        if id_range_offset_value == 0 {
+            Some((code_point as i16 + id_delta) as u16)
+        } else {
+            let delta = (code_point - start_value) * 2;
+            let pos = id_range_offset_pos.wrapping_add(delta) + id_range_offset_value;
+            let glyph_array_value = get_u16(data, pos as usize).unwrap();
+            if glyph_array_value == 0 {
+                return None;
+            }
+            let glyph_index = (glyph_array_value as i16).wrapping_add(id_delta);
+            Some(glyph_index as u16)
+        }
+    }
+
+    pub fn lookup_glyph_id(&self, code_point: u16) -> Option<u16> {
+        let end_counts_position = Self::get_end_counts_position();
+        let seg_count = self.get_seg_count();
+        let mut size = seg_count - 1;
+        let mut index = size / 2;
+        while size > 0 {
+            let search = end_counts_position + index * 2;
+            let end_value = get_u16(self.0, search as usize).unwrap();
+            if end_value >= code_point {
+                let start_pos = Self::get_start_counts_position(seg_count) + 2 * index;
+                let start_value = get_u16(self.0, start_pos as usize).unwrap();
+                if start_value > code_point {
+                    size /= 2;
+                    index -= size;
+                } else {
+                    return self.extract_glyph_id(code_point, start_value, seg_count, index);
+                }
+            } else {
+                size /= 2;
+                index += size;
+            }
+        }
+        None
+    }
+}
+
+impl<'a> Debug for EncodingFormat4<'a> {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        f.debug_struct("EncodingFormat4")
+            .field("format", &self.get_format())
+            .field("length", &self.get_length())
+            .field("language", &self.get_language())
+            .field("segCountX2", &self.get_seg_count_x_2())
+            .field("searchRange", &self.get_search_range())
+            .field("entrySelector", &self.get_entry_selector())
+            .field("rangeShift", &self.get_range_shift())
+            .field("endCounts", &self.get_end_counts())
+            .field("startCounts", &self.get_start_counts())
+            .field("idDeltas", &self.get_id_deltas())
+            .field("idRangeOffsets", &self.get_id_range_offsets())
+            .finish()
+    }
+}
+
+struct Cmap<'a>(&'a [u8]);
+
+impl<'a> Cmap<'a> {
+    fn get_version(&self) -> u16 {
+        get_u16(self.0, 0).unwrap()
+    }
+
+    fn get_num_tables(&self) -> u16 {
+        get_u16(self.0, 2).unwrap()
+    }
+
+    fn get_encoding_record(&self, index: u16) -> Option<EncodingRecord<'a>> {
+        if index >= self.get_num_tables() {
+            return None;
+        }
+        let enc_offset = (index * 8 + 4) as usize;
+        let encoding_data = &self.0[enc_offset as usize..(enc_offset + 12) as usize];
+        Some(EncodingRecord(encoding_data))
+    }
+
+    fn get_encoding_records(&self) -> Vec<EncodingRecord> {
+        let mut encodings = vec![];
+        for i in 0..self.get_num_tables() {
+            encodings.push(self.get_encoding_record(i).unwrap());
+        }
+        encodings
+    }
+
+    fn get_encoding(&self, index: u16) -> Option<Encoding<'a>> {
+        if index >= self.get_num_tables() {
+            return None;
+        }
+        let record = self.get_encoding_record(index).unwrap();
+        let subtable_len = get_u16(self.0, (record.get_offset() + 2) as usize).unwrap() as u32;
+        let encoding_data =
+            &self.0[record.get_offset() as usize..(record.get_offset() + subtable_len) as usize];
+        Some(Encoding(encoding_data))
+    }
+
+    fn get_encoding_format_4_at(&self, index: u16) -> Option<EncodingFormat4<'a>> {
+        let encoding = self.get_encoding(index);
+        if encoding.is_none() || encoding.unwrap().get_format() != 4 {
+            return None;
+        }
+        let record = self.get_encoding_record(index).unwrap();
+        let subtable_len = get_u16(self.0, (record.get_offset() + 2) as usize).unwrap() as u32;
+        let encoding_data =
+            &self.0[record.get_offset() as usize..(record.get_offset() + subtable_len) as usize];
+        Some(EncodingFormat4(encoding_data))
+    }
+
+    fn get_encodings(&self) -> Vec<Encoding> {
+        let mut encodings = vec![];
+        for i in 0..self.get_num_tables() {
+            encodings.push(self.get_encoding(i).unwrap());
+        }
+        encodings
+    }
+
+    pub fn find_format_4_encoding(&self) -> Option<u16> {
+        for index in 0..self.get_num_tables() {
+            let encoding = self.get_encoding(index);
+            if let Some(encoding) = encoding {
+                if encoding.get_format() == 4 {
+                    return Some(index);
+                }
+            }
+        }
+        None
+    }
+}
+
+impl<'a> Debug for Cmap<'a> {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        f.debug_struct("Cmap")
+            .field("version", &self.get_version())
+            .field("numTables", &self.get_num_tables())
+            .field("encodingRecords", &self.get_encoding_records())
+            .field("encodings", &self.get_encodings())
+            .finish()
+    }
+}
+
+fn get_bbox_raw(data: &[u8]) -> (i16, i16, i16, i16) {
+    (
+        get_i16(data, 2).unwrap(),
+        get_i16(data, 4).unwrap(),
+        get_i16(data, 6).unwrap(),
+        get_i16(data, 8).unwrap(),
+    )
+}
+
+enum Glyph<'a> {
+    Empty,
+    Simple(SimpleGlyph<'a>),
+    Compound(CompoundGlyph<'a>),
+}
+
+struct SimpleGlyph<'a> {
+    data: &'a [u8],
+}
+
+impl<'a> SimpleGlyph<'a> {
+    fn number_of_contours(&self) -> i16 {
+        get_i16(self.data, 0).unwrap()
+    }
+
+    fn bbox(&self) -> (i16, i16, i16, i16) {
+        get_bbox_raw(self.data)
+    }
+
+    fn points(&self) -> GlyphPoints<'a> {
+        let data = self.data;
+        let n_contours = self.number_of_contours();
+        let insn_len_off = 10 + 2 * n_contours as usize;
+        let n_points = get_u16(data, insn_len_off - 2).unwrap() as usize + 1;
+        let insn_len = get_u16(data, insn_len_off).unwrap(); // insn_len
+        let flags_ix = insn_len_off + insn_len as usize + 2;
+        let mut flags_size = 0;
+        let mut x_size = 0;
+        let mut points_remaining = n_points;
+        while points_remaining > 0 {
+            let flag = data[flags_ix as usize + flags_size];
+            let repeat_count = if (flag & 8) == 0 {
+                1
+            } else {
+                flags_size += 1;
+                data[flags_ix as usize + flags_size] as usize + 1
+            };
+            flags_size += 1;
+            match flag & 0x12 {
+                0x02 | 0x12 => x_size += repeat_count,
+                0x00 => x_size += 2 * repeat_count,
+                _ => (),
+            }
+            points_remaining -= repeat_count;
+        }
+        let x_ix = flags_ix + flags_size;
+        let y_ix = x_ix + x_size;
+        GlyphPoints {
+            data: data,
+            x: 0,
+            y: 0,
+            points_remaining: n_points,
+            last_flag: 0,
+            flag_repeats_remaining: 0,
+            flags_ix: flags_ix,
+            x_ix: x_ix,
+            y_ix: y_ix,
+        }
+    }
+
+    fn contour_sizes(&self) -> ContourSizes {
+        let n_contours = self.number_of_contours();
+        ContourSizes {
+            data: self.data,
+            contours_remaining: n_contours as usize,
+            ix: 10,
+            offset: -1,
+        }
+    }
+}
+
+struct GlyphPoints<'a> {
+    data: &'a [u8],
+    x: i16,
+    y: i16,
+    points_remaining: usize,
+    last_flag: u8,
+    flag_repeats_remaining: u8,
+    flags_ix: usize,
+    x_ix: usize,
+    y_ix: usize,
+}
+
+impl<'a> Iterator for GlyphPoints<'a> {
+    type Item = (bool, i16, i16);
+    fn next(&mut self) -> Option<(bool, i16, i16)> {
+        if self.points_remaining == 0 {
+            None
+        } else {
+            if self.flag_repeats_remaining == 0 {
+                self.last_flag = self.data[self.flags_ix];
+                if (self.last_flag & 8) == 0 {
+                    self.flags_ix += 1;
+                } else {
+                    self.flag_repeats_remaining = self.data[self.flags_ix + 1];
+                    self.flags_ix += 2;
+                }
+            } else {
+                self.flag_repeats_remaining -= 1;
+            }
+            let flag = self.last_flag;
+            //println!("flag={:02x}, flags_ix={}, x_ix={}, ({}) y_ix={} ({})",
+            // flag, self.flags_ix, self.x_ix, self.data.get(self.x_ix), self.y_ix,
+            // self.data.get(self.y_ix));
+            match flag & 0x12 {
+                0x02 => {
+                    self.x -= self.data[self.x_ix] as i16;
+                    self.x_ix += 1;
+                }
+                0x00 => {
+                    self.x += get_i16(self.data, self.x_ix).unwrap();
+                    self.x_ix += 2;
+                }
+                0x12 => {
+                    self.x += self.data[self.x_ix] as i16;
+                    self.x_ix += 1;
+                }
+                _ => (),
+            }
+            match flag & 0x24 {
+                0x04 => {
+                    self.y -= self.data[self.y_ix] as i16;
+                    self.y_ix += 1;
+                }
+                0x00 => {
+                    self.y += get_i16(self.data, self.y_ix).unwrap();
+                    self.y_ix += 2;
+                }
+                0x24 => {
+                    self.y += self.data[self.y_ix] as i16;
+                    self.y_ix += 1;
+                }
+                _ => (),
+            }
+            self.points_remaining -= 1;
+            Some(((self.last_flag & 1) != 0, self.x, self.y))
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (
+            self.points_remaining as usize,
+            Some(self.points_remaining as usize),
+        )
+    }
+}
+
+struct ContourSizes<'a> {
+    data: &'a [u8],
+    contours_remaining: usize,
+    ix: usize,
+    offset: i32,
+}
+
+impl<'a> Iterator for ContourSizes<'a> {
+    type Item = usize;
+    fn next(&mut self) -> Option<(usize)> {
+        if self.contours_remaining == 0 {
+            None
+        } else {
+            let ret = get_u16(self.data, self.ix).unwrap() as i32 - self.offset;
+            self.offset += ret;
+            self.ix += 2;
+            self.contours_remaining -= 1;
+            Some(ret as usize)
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.contours_remaining, Some(self.contours_remaining))
+    }
+}
+
+struct CompoundGlyph<'a> {
+    data: &'a [u8],
+}
+
+struct Components<'a> {
+    data: &'a [u8],
+    more: bool,
+    ix: usize,
+}
+
+const ARG_1_AND_2_ARE_WORDS: u16 = 1;
+const WE_HAVE_A_SCALE: u16 = 1 << 3;
+const MORE_COMPONENTS: u16 = 1 << 5;
+const WE_HAVE_AN_X_AND_Y_SCALE: u16 = 1 << 6;
+const WE_HAVE_A_TWO_BY_TWO: u16 = 1 << 7;
+
+impl<'a> Iterator for Components<'a> {
+    type Item = (u16, Affine);
+    fn next(&mut self) -> Option<(u16, Affine)> {
+        if !self.more {
+            return None;
+        }
+        let flags = get_u16(self.data, self.ix).unwrap();
+        self.ix += 2;
+        let glyph_index = get_u16(self.data, self.ix).unwrap();
+        self.ix += 2;
+        let arg1;
+        let arg2;
+        if (flags & ARG_1_AND_2_ARE_WORDS) != 0 {
+            arg1 = get_i16(self.data, self.ix).unwrap();
+            self.ix += 2;
+            arg2 = get_i16(self.data, self.ix).unwrap();
+            self.ix += 2;
+        } else {
+            arg1 = self.data[self.ix] as i16;
+            self.ix += 1;
+            arg2 = self.data[self.ix] as i16;
+            self.ix += 1;
+        }
+        let mut a = 1.0;
+        let mut b = 0.0;
+        let mut c = 0.0;
+        let mut d = 1.0;
+        if (flags & WE_HAVE_A_TWO_BY_TWO) != 0 {
+            a = get_f2_14(self.data, self.ix).unwrap();
+            self.ix += 2;
+            b = get_f2_14(self.data, self.ix).unwrap();
+            self.ix += 2;
+            c = get_f2_14(self.data, self.ix).unwrap();
+            self.ix += 2;
+            d = get_f2_14(self.data, self.ix).unwrap();
+            self.ix += 2;
+        } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0 {
+            a = get_f2_14(self.data, self.ix).unwrap();
+            self.ix += 2;
+            d = get_f2_14(self.data, self.ix).unwrap();
+            self.ix += 2;
+        } else if (flags & WE_HAVE_A_SCALE) != 0 {
+            a = get_f2_14(self.data, self.ix).unwrap();
+            self.ix += 2;
+            d = a;
+        }
+        // TODO: handle non-ARGS_ARE_XY_VALUES case
+        let x = arg1 as f32;
+        let y = arg2 as f32;
+        let z = Affine::new(a, b, c, d, x, y);
+        self.more = (flags & MORE_COMPONENTS) != 0;
+        Some((glyph_index, z))
+    }
+}
+
+impl<'a> CompoundGlyph<'a> {
+    fn bbox(&self) -> (i16, i16, i16, i16) {
+        get_bbox_raw(self.data)
+    }
+
+    fn components(&self) -> Components {
+        Components {
+            data: self.data,
+            ix: 10,
+            more: true,
+        }
+    }
+}
+
+pub struct Font<'a> {
+    _version: u32,
+    _tables: HashMap<Tag, &'a [u8]>,
+    head: Head<'a>,
+    maxp: Maxp<'a>,
+    cmap: Option<Cmap<'a>>,
+    loca: Option<Loca<'a>>,
+    glyf: Option<&'a [u8]>,
+    encoding_index: Option<u16>,
+}
+
+struct Metrics {
+    l: i32,
+    t: i32,
+    r: i32,
+    b: i32,
+}
+
+impl Metrics {
+    fn width(&self) -> usize {
+        (self.r - self.l) as usize
+    }
+
+    fn height(&self) -> usize {
+        (self.b - self.t) as usize
+    }
+}
+
+impl<'a> Font<'a> {
+    fn metrics_and_affine(
+        &self, xmin: i16, ymin: i16, xmax: i16, ymax: i16, size: u32,
+    ) -> (Metrics, Affine) {
+        let ppem = self.head.units_per_em();
+        let scale = (size as f32) / (ppem as f32);
+        let l = (xmin as f32 * scale).floor() as i32;
+        let t = (ymax as f32 * -scale).floor() as i32;
+        let r = (xmax as f32 * scale).ceil() as i32;
+        let b = (ymin as f32 * -scale).ceil() as i32;
+        let metrics = Metrics {
+            l: l,
+            t: t,
+            r: r,
+            b: b,
+        };
+        let z = Affine::new(scale, 0.0, 0.0, -scale, -l as f32, -t as f32);
+        (metrics, z)
+    }
+
+    fn render_glyph_inner(&self, raster: &mut Raster, z: &Affine, glyph: &Glyph) {
+        match *glyph {
+            Glyph::Simple(ref s) => {
+                let mut p = s.points();
+                for n in s.contour_sizes() {
+                    //println!("n = {}", n);
+                    //let v = path_from_pts(p.by_ref().take(n)).collect::<Vec<_>>();
+                    //println!("size = {}", v.len());
+                    draw_path(raster, z, &mut path_from_pts(p.by_ref().take(n)));
+                }
+            }
+            Glyph::Compound(ref c) => {
+                for (glyph_index, affine) in c.components() {
+                    //println!("component {} {:?}", glyph_index, affine);
+                    let concat = Affine::concat(z, &affine);
+                    if let Some(component_glyph) = self.get_glyph(glyph_index) {
+                        self.render_glyph_inner(raster, &concat, &component_glyph);
+                    }
+                }
+            }
+            _ => {
+                println!("unhandled glyph case");
+            }
+        }
+    }
+
+    pub fn render_glyph(&self, glyph_id: u16, size: u32) -> Option<GlyphBitmap> {
+        let glyph = self.get_glyph(glyph_id);
+        match glyph {
+            Some(Glyph::Simple(ref s)) => {
+                let (xmin, ymin, xmax, ymax) = s.bbox();
+                let (metrics, z) = self.metrics_and_affine(xmin, ymin, xmax, ymax, size);
+                let mut raster = Raster::new(metrics.width(), metrics.height());
+                //dump_glyph(SimpleGlyph(s));
+                self.render_glyph_inner(&mut raster, &z, glyph.as_ref().unwrap());
+                //None
+                Some(GlyphBitmap {
+                    width: metrics.width(),
+                    height: metrics.height(),
+                    left: metrics.l,
+                    top: metrics.t,
+                    data: raster.get_bitmap(),
+                })
+            }
+            Some(Glyph::Compound(ref c)) => {
+                let (xmin, ymin, xmax, ymax) = c.bbox();
+                let (metrics, z) = self.metrics_and_affine(xmin, ymin, xmax, ymax, size);
+                let mut raster = Raster::new(metrics.width(), metrics.height());
+                self.render_glyph_inner(&mut raster, &z, glyph.as_ref().unwrap());
+                Some(GlyphBitmap {
+                    width: metrics.width(),
+                    height: metrics.height(),
+                    left: metrics.l,
+                    top: metrics.t,
+                    data: raster.get_bitmap(),
+                })
+            }
+            _ => {
+                println!("glyph {} error", glyph_id);
+                None
+            }
+        }
+    }
+
+    fn get_glyph(&self, glyph_ix: u16) -> Option<Glyph> {
+        if glyph_ix >= self.maxp.num_glyphs() {
+            return None;
+        }
+        let fmt = self.head.index_to_loc_format();
+        match self.loca {
+            Some(ref loca) => match (
+                loca.get_off(glyph_ix, fmt),
+                loca.get_off(glyph_ix + 1, fmt),
+                self.glyf,
+            ) {
+                (Some(off0), Some(off1), Some(glyf)) => if off0 == off1 {
+                    Some(Glyph::Empty)
+                } else {
+                    let glyph_data = &glyf[off0 as usize..off1 as usize];
+                    if get_i16(glyph_data, 0) == Some(-1) {
+                        Some(Glyph::Compound(CompoundGlyph { data: glyph_data }))
+                    } else {
+                        Some(Glyph::Simple(SimpleGlyph { data: glyph_data }))
+                    }
+                },
+                (_, _, _) => None,
+            },
+            None => None,
+        }
+    }
+
+    pub fn lookup_glyph_id(&self, code_point: u32) -> Option<u16> {
+        match self.encoding_index {
+            Some(encoding_index) => {
+                if code_point > u16::max_value() as u32 {
+                    return None;
+                }
+
+                self.cmap
+                    .as_ref()
+                    .unwrap()
+                    .get_encoding_format_4_at(encoding_index)
+                    .unwrap()
+                    .lookup_glyph_id(code_point as u16)
+            }
+            None => None,
+        }
+    }
+}
+
+#[derive(Debug)]
+enum PathOp {
+    MoveTo(Point),
+    LineTo(Point),
+    QuadTo(Point, Point),
+}
+
+use self::PathOp::{LineTo, MoveTo, QuadTo};
+
+struct BezPathOps<T> {
+    inner: T,
+    first_oncurve: Option<Point>,
+    first_offcurve: Option<Point>,
+    last_offcurve: Option<Point>,
+    alldone: bool,
+    closing: bool,
+}
+
+fn path_from_pts<T: Iterator>(inner: T) -> BezPathOps<T> {
+    BezPathOps {
+        inner: inner,
+        first_oncurve: None,
+        first_offcurve: None,
+        last_offcurve: None,
+        alldone: false,
+        closing: false,
+    }
+}
+
+impl<I> Iterator for BezPathOps<I>
+where
+    I: Iterator<Item = (bool, i16, i16)>,
+{
+    type Item = PathOp;
+    fn next(&mut self) -> Option<PathOp> {
+        loop {
+            if self.closing {
+                if self.alldone {
+                    return None;
+                } else {
+                    match (self.first_offcurve, self.last_offcurve) {
+                        (None, None) => {
+                            self.alldone = true;
+                            return Some(LineTo(self.first_oncurve.unwrap()));
+                        }
+                        (None, Some(last_offcurve)) => {
+                            self.alldone = true;
+                            return Some(QuadTo(last_offcurve, self.first_oncurve.unwrap()));
+                        }
+                        (Some(first_offcurve), None) => {
+                            self.alldone = true;
+                            return Some(QuadTo(first_offcurve, self.first_oncurve.unwrap()));
+                        }
+                        (Some(first_offcurve), Some(last_offcurve)) => {
+                            self.last_offcurve = None;
+                            return Some(QuadTo(
+                                last_offcurve,
+                                Point::lerp(0.5, &last_offcurve, &first_offcurve),
+                            ));
+                        }
+                    }
+                }
+            } else {
+                match self.inner.next() {
+                    None => {
+                        self.closing = true;
+                    }
+                    Some((oncurve, x, y)) => {
+                        let p = Point::new(x, y);
+                        if self.first_oncurve.is_none() {
+                            if oncurve {
+                                self.first_oncurve = Some(p);
+                                return Some(MoveTo(p));
+                            } else {
+                                match self.first_offcurve {
+                                    None => self.first_offcurve = Some(p),
+                                    Some(first_offcurve) => {
+                                        let midp = Point::lerp(0.5, &first_offcurve, &p);
+                                        self.first_oncurve = Some(midp);
+                                        self.last_offcurve = Some(p);
+                                        return Some(MoveTo(midp));
+                                    }
+                                }
+                            }
+                        } else {
+                            match (self.last_offcurve, oncurve) {
+                                (None, false) => self.last_offcurve = Some(p),
+                                (None, true) => return Some(LineTo(p)),
+                                (Some(last_offcurve), false) => {
+                                    self.last_offcurve = Some(p);
+                                    return Some(QuadTo(
+                                        last_offcurve,
+                                        Point::lerp(0.5, &last_offcurve, &p),
+                                    ));
+                                }
+                                (Some(last_offcurve), true) => {
+                                    self.last_offcurve = None;
+                                    return Some(QuadTo(last_offcurve, p));
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+#[derive(Debug)]
+pub enum FontError {
+    Invalid,
+}
+
+pub fn parse(data: &[u8]) -> Result<Font, FontError> {
+    if data.len() < 12 {
+        return Err(FontError::Invalid);
+    }
+    let version = get_u32(data, 0).unwrap();
+    let num_tables = get_u16(data, 4).unwrap() as usize;
+    let _search_range = get_u16(data, 6).unwrap();
+    let _entry_selector = get_u16(data, 8).unwrap();
+    let _range_shift = get_u16(data, 10).unwrap();
+    let mut tables = HashMap::new();
+    for i in 0..num_tables {
+        let header = &data[12 + i * 16..12 + (i + 1) * 16];
+        let tag = get_u32(header, 0).unwrap();
+        let _check_sum = get_u32(header, 4).unwrap();
+        let offset = get_u32(header, 8).unwrap();
+        let length = get_u32(header, 12).unwrap();
+        let table_data = &data[offset as usize..(offset + length) as usize];
+        //println!("{}: {}", Tag(tag), table_data.len());
+        tables.insert(Tag(tag), table_data);
+    }
+    let head = Head(*tables.get(&Tag::from_str("head")).unwrap()); // todo: don't fail
+    let maxp = Maxp {
+        data: *tables.get(&Tag::from_str("maxp")).unwrap(),
+    };
+    let loca = tables.get(&Tag::from_str("loca")).map(|&data| Loca(data));
+    let glyf = tables.get(&Tag::from_str("glyf")).map(|&data| data);
+    let cmap = tables.get(&Tag::from_str("cmap")).map(|&data| Cmap(data));
+    let encoding_index = cmap.as_ref().and_then(|cmap| cmap.find_format_4_encoding());
+    let f = Font {
+        _version: version,
+        _tables: tables,
+        head: head,
+        maxp: maxp,
+        loca: loca,
+        cmap: cmap,
+        glyf: glyf,
+        encoding_index: encoding_index,
+    };
+    //println!("version = {:x}", version);
+    Ok(f)
+}
+
+/*
+fn dump_glyph(g: Glyph) {
+    match g {
+        Glyph::Empty => println!("empty"),
+        Glyph::Simple(s) => {
+            //println!("{} contours", s.number_of_contours())
+            let mut p = s.points();
+            for n in s.contour_sizes() {
+                for _ in 0..n {
+                    println!("{:?}", p.next().unwrap());
+                }
+                println!("z");
+            }
+            let mut p = s.points();
+            for n in s.contour_sizes() {
+                for pathop in path_from_pts(p.by_ref().take(n)) {
+                    println!("{:?}", pathop);
+                }
+            }
+        },
+        _ => println!("other")
+    }
+}
+*/
+
+/*
+fn dump(data: Vec<u8>) {
+    println!("length is {}", data.len());
+    match parse(&data) {
+        Ok(font) => {
+            println!("numGlyphs = {}", font.maxp.num_glyphs());
+            for i in 0.. font.maxp.num_glyphs() {
+                println!("glyph {}", i);
+                match font.get_glyph(i) {
+                    Some(g) => dump_glyph(g),
+                    None => println!("glyph {} error", i)
+                }
+            }
+        },
+        _ => ()
+    }
+}
+*/
+
+fn draw_path<I: Iterator<Item = PathOp>>(r: &mut Raster, z: &Affine, path: &mut I) {
+    let mut lastp = Point::new(0i16, 0i16);
+    for op in path {
+        match op {
+            MoveTo(p) => lastp = p,
+            LineTo(p) => {
+                r.draw_line(&affine_pt(z, &lastp), &affine_pt(z, &p));
+                lastp = p
+            }
+            QuadTo(p1, p2) => {
+                r.draw_quad(
+                    &affine_pt(z, &lastp),
+                    &affine_pt(z, &p1),
+                    &affine_pt(z, &p2),
+                );
+                lastp = p2;
+            }
+        }
+    }
+}
+
+pub struct GlyphBitmap {
+    pub width: usize,
+    pub height: usize,
+    pub left: i32,
+    pub top: i32,
+    pub data: Vec<u8>,
+}
+
+#[cfg(test)]
+mod tests {
+
+    use font::parse;
+
+    static FONT_DATA: &'static [u8] =
+        include_bytes!("../fonts/notomono-hinted/NotoMono-Regular.ttf");
+
+    #[test]
+    fn test_cmap_format_4() {
+        let font = parse(&FONT_DATA).unwrap();
+        let cmap = font.cmap.as_ref().unwrap();
+        assert!(cmap.get_encoding_record(cmap.get_num_tables()).is_none());
+        assert!(cmap.get_encoding(cmap.get_num_tables()).is_none());
+        assert_eq!(font.lookup_glyph_id('A' as u32).unwrap(), 36);
+        assert_eq!(font.lookup_glyph_id(0x3c8).unwrap(), 405);
+        assert_eq!(font.lookup_glyph_id(0xfffd).unwrap(), 589);
+        assert_eq!(font.lookup_glyph_id(0x232B).is_none(), true);
+        assert_eq!(font.lookup_glyph_id(0x1000232B).is_none(), true);
+        // test for panics
+        for i in 0..0x1ffff {
+            font.lookup_glyph_id(i);
+        }
+    }
+}
diff --git a/rustc_deps/vendor/font-rs/src/geom.rs b/rustc_deps/vendor/font-rs/src/geom.rs
new file mode 100644
index 0000000..c292cad
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/src/geom.rs
@@ -0,0 +1,81 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Geometry primitive data structures and manipulations
+
+use std::fmt::{Debug, Formatter, Result};
+
+#[derive(Copy, Clone)]
+pub struct Point {
+    pub x: f32,
+    pub y: f32,
+}
+
+impl Point {
+    pub fn new<T>(x: T, y: T) -> Point
+    where
+        T: Into<f32>,
+    {
+        Point {
+            x: x.into(),
+            y: y.into(),
+        }
+    }
+
+    pub fn lerp(t: f32, p0: &Self, p1: &Self) -> Self {
+        Point {
+            x: p0.x + t * (p1.x - p0.x),
+            y: p0.y + t * (p1.y - p0.y),
+        }
+    }
+}
+
+impl Debug for Point {
+    fn fmt(&self, f: &mut Formatter) -> Result {
+        write!(f, "({}, {})", self.x, self.y)
+    }
+}
+
+#[derive(Debug)]
+pub struct Affine {
+    a: f32,
+    b: f32,
+    c: f32,
+    d: f32,
+    e: f32,
+    f: f32,
+}
+
+impl Affine {
+    /// Concatenate two affine transforms.
+    pub fn concat(t1: &Affine, t2: &Affine) -> Affine {
+        Affine {
+            a: t1.a * t2.a + t1.c * t2.b,
+            b: t1.b * t2.a + t1.d * t2.b,
+            c: t1.a * t2.c + t1.c * t2.d,
+            d: t1.b * t2.c + t1.d * t2.d,
+            e: t1.a * t2.e + t1.c * t2.f + t1.e,
+            f: t1.b * t2.e + t1.d * t2.f + t1.f,
+        }
+    }
+}
+
+pub fn affine_pt(z: &Affine, p: &Point) -> Point {
+    Point {
+        x: z.a * p.x + z.c * p.y + z.e,
+        y: z.b * p.x + z.d * p.y + z.f,
+    }
+}
+
+gen_new!(Affine, a: f32, b: f32, c: f32, d: f32, e: f32, f: f32);
diff --git a/rustc_deps/vendor/font-rs/src/lib.rs b/rustc_deps/vendor/font-rs/src/lib.rs
new file mode 100644
index 0000000..b7b189f
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/src/lib.rs
@@ -0,0 +1,22 @@
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! A very high performance font renderer.
+
+#[macro_use]
+pub mod macros;
+pub mod accumulate;
+pub mod font;
+pub mod geom;
+pub mod raster;
diff --git a/rustc_deps/vendor/font-rs/src/macros.rs b/rustc_deps/vendor/font-rs/src/macros.rs
new file mode 100644
index 0000000..deccd9d
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/src/macros.rs
@@ -0,0 +1,12 @@
+#[macro_export]
+macro_rules! gen_new {
+  ($r:ident, $($field:ident : $field_type:ty),*) => {
+    impl $r {
+      pub fn new($($field: $field_type),*) -> Self {
+        $r {
+          $($field: $field),*
+        }
+      }
+    }
+  }
+}
diff --git a/rustc_deps/vendor/font-rs/src/raster.rs b/rustc_deps/vendor/font-rs/src/raster.rs
new file mode 100644
index 0000000..7caaa9d
--- /dev/null
+++ b/rustc_deps/vendor/font-rs/src/raster.rs
@@ -0,0 +1,139 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! An antialiased rasterizer for quadratic Beziers
+
+use std::cmp::min;
+
+use accumulate::accumulate;
+use geom::Point;
+
+// TODO: sort out crate structure. Right now we want this when compiling raster as a binary,
+// but need it commented out when compiling showttf
+//mod geom;
+
+pub struct Raster {
+    w: usize,
+    h: usize,
+    a: Vec<f32>,
+}
+
+// TODO: is there a faster way? (investigate whether approx recip is good enough)
+fn recip(x: f32) -> f32 {
+    x.recip()
+}
+
+impl Raster {
+    pub fn new(w: usize, h: usize) -> Raster {
+        Raster {
+            w: w,
+            h: h,
+            a: vec![0.0; w * h + 4],
+        }
+    }
+
+    pub fn draw_line(&mut self, p0: &Point, p1: &Point) {
+        //println!("draw_line {} {}", p0, p1);
+        if p0.y == p1.y {
+            return;
+        }
+        let (dir, p0, p1) = if p0.y < p1.y {
+            (1.0, p0, p1)
+        } else {
+            (-1.0, p1, p0)
+        };
+        let dxdy = (p1.x - p0.x) / (p1.y - p0.y);
+        let mut x = p0.x;
+        let y0 = p0.y as usize; // note: implicit max of 0 because usize (TODO: really true?)
+        if p0.y < 0.0 {
+            x -= p0.y * dxdy;
+        }
+        for y in y0..min(self.h, p1.y.ceil() as usize) {
+            let linestart = y * self.w;
+            let dy = ((y + 1) as f32).min(p1.y) - (y as f32).max(p0.y);
+            let xnext = x + dxdy * dy;
+            let d = dy * dir;
+            let (x0, x1) = if x < xnext { (x, xnext) } else { (xnext, x) };
+            let x0floor = x0.floor();
+            let x0i = x0floor as i32;
+            let x1ceil = x1.ceil();
+            let x1i = x1ceil as i32;
+            if x1i <= x0i + 1 {
+                let xmf = 0.5 * (x + xnext) - x0floor;
+                self.a[linestart + x0i as usize] += d - d * xmf;
+                self.a[linestart + (x0i + 1) as usize] += d * xmf;
+            } else {
+                let s = recip(x1 - x0);
+                let x0f = x0 - x0floor;
+                let a0 = 0.5 * s * (1.0 - x0f) * (1.0 - x0f);
+                let x1f = x1 - x1ceil + 1.0;
+                let am = 0.5 * s * x1f * x1f;
+                self.a[linestart + x0i as usize] += d * a0;
+                if x1i == x0i + 2 {
+                    self.a[linestart + (x0i + 1) as usize] += d * (1.0 - a0 - am);
+                } else {
+                    let a1 = s * (1.5 - x0f);
+                    self.a[linestart + (x0i + 1) as usize] += d * (a1 - a0);
+                    for xi in x0i + 2..x1i - 1 {
+                        self.a[linestart + xi as usize] += d * s;
+                    }
+                    let a2 = a1 + (x1i - x0i - 3) as f32 * s;
+                    self.a[linestart + (x1i - 1) as usize] += d * (1.0 - a2 - am);
+                }
+                self.a[linestart + x1i as usize] += d * am;
+            }
+            x = xnext;
+        }
+    }
+
+    pub fn draw_quad(&mut self, p0: &Point, p1: &Point, p2: &Point) {
+        //println!("draw_quad {} {} {}", p0, p1, p2);
+        let devx = p0.x - 2.0 * p1.x + p2.x;
+        let devy = p0.y - 2.0 * p1.y + p2.y;
+        let devsq = devx * devx + devy * devy;
+        if devsq < 0.333 {
+            self.draw_line(p0, p2);
+            return;
+        }
+        let tol = 3.0;
+        let n = 1 + (tol * (devx * devx + devy * devy)).sqrt().sqrt().floor() as usize;
+        //println!("n = {}", n);
+        let mut p = *p0;
+        let nrecip = recip(n as f32);
+        let mut t = 0.0;
+        for _i in 0..n - 1 {
+            t += nrecip;
+            let pn = Point::lerp(t, &Point::lerp(t, p0, p1), &Point::lerp(t, p1, p2));
+            self.draw_line(&p, &pn);
+            p = pn;
+        }
+        self.draw_line(&p, p2);
+    }
+
+    /*
+    fn get_bitmap_fancy(&self) -> Vec<u8> {
+        let mut acc = 0.0;
+        // This would translate really well to SIMD
+        self.a[0..self.w * self.h].iter().map(|&a| {
+            acc += a;
+            (255.0 * acc.abs().min(1.0)) as u8
+            //(255.5 * (0.5 + 0.4 * acc)) as u8
+        }).collect()
+    }
+*/
+
+    pub fn get_bitmap(&self) -> Vec<u8> {
+        accumulate(&self.a[0..self.w * self.h])
+    }
+}