This is an automated email from the git hooks/post-receive script.

benjamin-guest pushed a commit to branch master
in repository r-cran-scales.

commit f8386f2d128f3d86609cde4bbff5bf5eed8f0b7a
Author: Benjamin Eikel <benja...@eikel.org>
Date:   Thu Jul 30 13:12:53 2015 +0200

    Imported Upstream version 0.2.5
---
 DESCRIPTION                      |  29 +--
 MD5                              | 172 +++++++++--------
 NAMESPACE                        |  14 +-
 NEWS                             |  44 +++++
 R/RcppExports.R                  |  15 ++
 R/bounds.r                       |  21 +--
 R/colour-manip.r                 |  10 +-
 R/colour-mapping.r               | 386 +++++++++++++++++++++++++++++++++++++++
 R/date-time.r                    |  24 +--
 R/formatter.r                    | 139 ++++++++++++--
 R/pal-brewer.r                   |  33 ++--
 R/pal-hue.r                      |   2 +-
 R/pal-shape.r                    |   2 +-
 R/scales.r                       |   3 +-
 R/trans-date.r                   |   6 +-
 R/trans-numeric.r                |   5 +-
 README.md                        |   2 +
 build/partial.rdb                | Bin 6283 -> 8433 bytes
 man/Range-class.Rd               |   3 +-
 man/abs_area.Rd                  |   3 +-
 man/alpha.Rd                     |   3 +-
 man/area_pal.Rd                  |   3 +-
 man/as.trans.Rd                  |   3 +-
 man/asn_trans.Rd                 |   3 +-
 man/atanh_trans.Rd               |   3 +-
 man/boxcox_trans.Rd              |   3 +-
 man/brewer_pal.Rd                |   9 +-
 man/cbreaks.Rd                   |   3 +-
 man/censor.Rd                    |   3 +-
 man/col2hcl.Rd                   |   7 +-
 man/col_numeric.Rd               | 108 +++++++++++
 man/colour_ramp.Rd               |  40 ++++
 man/comma_format.Rd              |  11 +-
 man/cscale.Rd                    |   3 +-
 man/date_breaks.Rd               |   3 +-
 man/date_format.Rd               |   8 +-
 man/date_trans.Rd                |   3 +-
 man/dichromat_pal.Rd             |   3 +-
 man/discard.Rd                   |   3 +-
 man/div_gradient_pal.Rd          |   3 +-
 man/dollar_format.Rd             |  27 ++-
 man/dscale.Rd                    |   3 +-
 man/exp_trans.Rd                 |   3 +-
 man/expand_range.Rd              |   3 +-
 man/extended_breaks.Rd           |   3 +-
 man/format_format.Rd             |   3 +-
 man/fullseq.Rd                   |   3 +-
 man/gradient_n_pal.Rd            |   3 +-
 man/grey_pal.Rd                  |   3 +-
 man/hue_pal.Rd                   |   8 +-
 man/identity_pal.Rd              |   3 +-
 man/identity_trans.Rd            |   3 +-
 man/linetype_pal.Rd              |   3 +-
 man/log1p_trans.Rd               |   7 +-
 man/log_breaks.Rd                |   3 +-
 man/log_trans.Rd                 |   3 +-
 man/manual_pal.Rd                |   3 +-
 man/math_format.Rd               |   5 +-
 man/muted.Rd                     |   3 +-
 man/ordinal_format.Rd            |  26 +++
 man/package-scales.Rd            |   3 +-
 man/parse_format.Rd              |   5 +-
 man/percent_format.Rd            |   5 +-
 man/pretty_breaks.Rd             |   3 +-
 man/probability_trans.Rd         |   3 +-
 man/reciprocal_trans.Rd          |   3 +-
 man/rescale.Rd                   |   3 +-
 man/rescale_max.Rd               |   3 +-
 man/rescale_mid.Rd               |   3 +-
 man/rescale_none.Rd              |   3 +-
 man/rescale_pal.Rd               |   3 +-
 man/reverse_trans.Rd             |   3 +-
 man/scientific_format.Rd         |   5 +-
 man/seq_gradient_pal.Rd          |   3 +-
 man/shape_pal.Rd                 |   3 +-
 man/show_col.Rd                  |   9 +-
 man/sqrt_trans.Rd                |   3 +-
 man/squish.Rd                    |   3 +-
 man/squish_infinite.Rd           |   3 +-
 man/time_trans.Rd                |   3 +-
 man/trans_breaks.Rd              |   3 +-
 man/trans_format.Rd              |   5 +-
 man/trans_new.Rd                 |   3 +-
 man/trans_range.Rd               |   3 +-
 man/unit_format.Rd               |  33 ++++
 man/wrap_format.Rd               |  25 +++
 man/zero_range.Rd                |  16 +-
 src/RcppExports.cpp              |  43 +++++
 src/colors.cpp                   | 242 ++++++++++++++++++++++++
 tests/testthat/test-colors.r     |  60 ++++++
 tests/testthat/test-formatter.r  | 111 +++++++----
 tests/testthat/test-zero-range.r |  11 +-
 92 files changed, 1600 insertions(+), 283 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
index 7444db0..e8a3080 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,23 +1,26 @@
 Package: scales
-Type: Package
-Title: Scale functions for graphics.
-Version: 0.2.4
-Author: Hadley Wickham <h.wick...@gmail.com>
-Maintainer: Hadley Wickham <h.wick...@gmail.com>
-Description: Scales map data to aesthetics, and provide
+Version: 0.2.5
+Authors@R: c(
+    person("Hadley", "Wickham", , "had...@rstudio.com", c("aut", "cre")),
+    person("RStudio", role = "cph")
+    )
+Title: Scale Functions for Visualization
+Description: Graphical scales map data to aesthetics, and provide
     methods for automatically determining breaks and labels
     for axes and legends.
 URL: https://github.com/hadley/scales
 BugReports: https://github.com/hadley/scales/issues
 Depends: R (>= 2.13)
-Imports: RColorBrewer, dichromat, munsell (>= 0.2), plyr (>= 1.2),
-        labeling, methods
+Imports: RColorBrewer, dichromat, plyr, munsell (>= 0.2), labeling,
+        methods, Rcpp
+LinkingTo: Rcpp
 Suggests: testthat (>= 0.8)
 License: MIT + file LICENSE
 LazyLoad: yes
-Roxygen: list(wrap = FALSE)
-BuildManual: yes
-Packaged: 2014-04-21 22:24:36 UTC; hadley
-NeedsCompilation: no
+NeedsCompilation: yes
+Packaged: 2015-06-12 16:14:42 UTC; hadley
+Author: Hadley Wickham [aut, cre],
+  RStudio [cph]
+Maintainer: Hadley Wickham <had...@rstudio.com>
 Repository: CRAN
-Date/Publication: 2014-04-22 10:50:55
+Date/Publication: 2015-06-12 23:50:17
diff --git a/MD5 b/MD5
index 4aa8f7b..1f4b24e 100644
--- a/MD5
+++ b/MD5
@@ -1,105 +1,115 @@
-1ba8d7157ea2fc2b12d4f4708b26d9f3 *DESCRIPTION
+29d506a30eaf011b43e8df38a4a2612d *DESCRIPTION
 42d91d5ce1f6db25d653397ec9da4f25 *LICENSE
-ad819e13163d287a357c7ff9f1a93edd *NAMESPACE
-675f887506fcc8f842ff3eee50a7d1be *NEWS
-8f5993ce0966e0ddc628de948c294aae *R/bounds.r
+54fdd968f4485c3b22b764e0eb0acc5f *NAMESPACE
+9d77960b242dadc6010ba7eb83fd43ff *NEWS
+ee154387df2488852decb38c14e4c697 *R/RcppExports.R
+8b906c5c20e6f20d971485d94109892c *R/bounds.r
 079b8af0d7acb058149e54824572af5a *R/breaks.r
-d3aec579399aabafd0d4a635dfb1c347 *R/colour-manip.r
-2f8186364bc82ff1aad0b095bebefaca *R/date-time.r
+17252f5fd662f167ae903b92b49d1ddf *R/colour-manip.r
+6d5410196f7ed8aa9334fe7f837e04dd *R/colour-mapping.r
+d2c6598a250614e3ad4a5b47153d6b3e *R/date-time.r
 f967c78e39bbcb23a60709f2a2735dbc *R/documentation.r
-fb428bf4a5535e13eb77bc15fa8f6a21 *R/formatter.r
+6ebbb7185088f95f671ad1941dbdbca1 *R/formatter.r
 4f198007ee8d818bed5a007004f43e65 *R/full-seq.r
 932da2aa512e9fefe925ade14e87e30c *R/pal-area.r
-be07befacefc9095d5209249c48e732b *R/pal-brewer.r
+727241d5eb4b3abd11b9102a293927df *R/pal-brewer.r
 e3e27dccb6da5ed52478799e65843004 *R/pal-dichromat.r
 59192407795030694ff12bc1e31a2993 *R/pal-gradient.r
 71512f007a23dc9d24abcfed6361dad1 *R/pal-grey.r
-e3cd2ce2a082f9cb4136697dccf02d66 *R/pal-hue.r
+c20f4657f1ad2b33afffb0680ae0edcf *R/pal-hue.r
 732494f5f4054ca39a7da7731d023add *R/pal-identity.r
 a4c1f8acacabe7943df7173df7fe0633 *R/pal-linetype.r
 716233051ba6990a7f9df54b51227294 *R/pal-manual.r
 8cf6ec1effbef4498ee7d88ce0cbe9e2 *R/pal-rescale.r
-bff20c9fef8cae96c082ca8e216f662f *R/pal-shape.r
+58a8a345646e7034a6558e481defc8d6 *R/pal-shape.r
 6c4b15dde8f951ed9b35431756af8cb8 *R/range.r
 15e5251a1e5775a3b081728ac24cd207 *R/scale-continuous.r
 56da7559ee91befb22cc28f0c8fa4f55 *R/scale-discrete.r
-c401d1f1b3a958d8c5ad032f3f8f6123 *R/scales.r
-5726ee3b0cb6c6636338c04d2bb96b39 *R/trans-date.r
-031a2b0204cbc710e8ba4fe52eab9efc *R/trans-numeric.r
+fc408b59519e0aa383e069d789484e95 *R/scales.r
+6f1a14588c52e2cfc70a4347c3b6a743 *R/trans-date.r
+3f1ec156f1cb24f09643e4d02b68d393 *R/trans-numeric.r
 7f0e5368736657d377f6b1a77b6e8f84 *R/trans.r
-9d336da792ba088f2d59267c6ff25633 *README.md
-c100cb70c6e4f569e70f3548ee30c784 *build/partial.rdb
-6f0a135e325a8b8465e6abba6c1fdf1c *man/Range-class.Rd
-da4b52b7e5d12d35a54c710981d54063 *man/abs_area.Rd
-bbd79457d65b27004c5a2f36b5ef202b *man/alpha.Rd
-f228408634422228704c3f11a28fbb97 *man/area_pal.Rd
-da56dc3d22721af73e3904bd26534dd4 *man/as.trans.Rd
-a5a01321840e16f941b90144841fdb26 *man/asn_trans.Rd
-f9b876cef286529325ff41f84a3552ae *man/atanh_trans.Rd
-d02bbb63eca869ec46badd66ea51deca *man/boxcox_trans.Rd
-d767f3134e23abc2f99b81244c1afc0e *man/brewer_pal.Rd
-9663fba2431573eea0e21f73842aebc6 *man/cbreaks.Rd
-f87f6992c16f3a32e070425f42d852cd *man/censor.Rd
-cf689a20e79ab92dcbd43e4bf2f87262 *man/col2hcl.Rd
-dcf3bd6ad2118c93a4495f45a59b0857 *man/comma_format.Rd
-b3236d241c358c98a3a686c4aa515ebb *man/cscale.Rd
-56882213b864fc148449433025709a57 *man/date_breaks.Rd
-27aaa204a54c1e0346bdfff3ca27068f *man/date_format.Rd
-51d67856f5c698d66c26805738fc4ed1 *man/date_trans.Rd
-1e8f4420ccddaeee68954e5d82c48906 *man/dichromat_pal.Rd
-9148536a20911b3126a24bf44bbfe99d *man/discard.Rd
-609ea7ae5173cb918752e8a4171f8670 *man/div_gradient_pal.Rd
-f40e4cdf72a4059c7b5257eb1168e6e6 *man/dollar_format.Rd
-0cecccf7eb0f12b15fae10874a3dcf86 *man/dscale.Rd
-f0ab4e4374ffe344142c7b1ff9922705 *man/exp_trans.Rd
-caa3d1db9501b203a44691a6616ca82d *man/expand_range.Rd
-0113fec97bbb9c0451a8d9eae4f509f7 *man/extended_breaks.Rd
-fa164fde9baaeabb19858828ce8c4dcd *man/format_format.Rd
-f0629a989b5e37f3de173429b803bd4b *man/fullseq.Rd
-33c2a19079d757f1c88e2d1ac454975d *man/gradient_n_pal.Rd
-ab0289f49fd83fa5d83def8f191573cd *man/grey_pal.Rd
-ab8360edc93e0f76e07b6ead8b3f2739 *man/hue_pal.Rd
-7ce51b53b33d2079ef08c4607f44e9ae *man/identity_pal.Rd
-ec4be8c7ffae1004aa5ce3a432d9a035 *man/identity_trans.Rd
-c8d3fd514ecb944e6bc708a7d48ea934 *man/linetype_pal.Rd
-e868233a5123034b9e0d3a4178ecb629 *man/log1p_trans.Rd
-a0ed6ad964539ec8e069d28f70d3ab9b *man/log_breaks.Rd
-e78f8fe2edc87c67348575b17a7cfaae *man/log_trans.Rd
-34138dade796d24063794ce55193f796 *man/manual_pal.Rd
-46f262dbd478eada530b9c81188ada0e *man/math_format.Rd
-c14e9f1fa4813fc336796934efa902eb *man/muted.Rd
-d92e19a18d4b01110446e0fb4ece3010 *man/package-scales.Rd
-8f13ed5e537f681885943cfd41f83d31 *man/parse_format.Rd
-8ea452f108fc992f444c41f17011506a *man/percent_format.Rd
-34458dd6bf81990af47a8087629329c2 *man/pretty_breaks.Rd
-01d5717746893307939245fad90dea63 *man/probability_trans.Rd
-fe7909118a7382fdea3b7c6ffae3981a *man/reciprocal_trans.Rd
-390dcae6dacea10dd6028d20084f60ab *man/rescale.Rd
-42adeedc8604aa148feb3df26fac45ed *man/rescale_max.Rd
-2b6b414c8165aa8857969e5b1eff1888 *man/rescale_mid.Rd
-b94f9189ff392dc51b59a68d266e054d *man/rescale_none.Rd
-f35d5b64a5579133d2a8478297910b8d *man/rescale_pal.Rd
-9456aff898ff1647d437f0ad1d510646 *man/reverse_trans.Rd
-4da43ab7c993f521d4e3effac7c35acc *man/scientific_format.Rd
-ff5862ba11ec017e76de787018aef82b *man/seq_gradient_pal.Rd
-64bbfe0e079cccbb3f62f315b2daa86a *man/shape_pal.Rd
-d928592228b6c37eee0ef8e88080e2d9 *man/show_col.Rd
-d83e111d07efd96dfaa92e6d1da2a1dd *man/sqrt_trans.Rd
-1db309a93a9b09d46c1faddf2fcd511c *man/squish.Rd
-444857020e5e04c6cb7b207daa977d40 *man/squish_infinite.Rd
-3b76e826d3205bed7949bc7e7252d889 *man/time_trans.Rd
-7537b357129242a9aa809ce3e174c499 *man/trans_breaks.Rd
-787b3ee0489be64064deeb1bc09122fa *man/trans_format.Rd
-6a8f59cb1a749503142251c58efba26d *man/trans_new.Rd
-f94947db0896a38fddaa6bcc23342e02 *man/trans_range.Rd
-636f4990321ef4c8d6dd72ae37121ed4 *man/zero_range.Rd
+e64f23c90bdbf4d8827a62fc7225d54b *README.md
+228ae254b5cc635c4845872bc6bb6cbc *build/partial.rdb
+fd70092adc19b48aa793fdb0f92dce1b *man/Range-class.Rd
+fce13530360aab377cc560559a4a2f93 *man/abs_area.Rd
+d258d45730e4128f57ee66209b889570 *man/alpha.Rd
+d881492d8245940cfef56ccfb11d465f *man/area_pal.Rd
+c8e4c7d2827b05cb36a1d7d59f9232f4 *man/as.trans.Rd
+bb1bcadebad4c8fdf7f88ce0e2e68f89 *man/asn_trans.Rd
+72fc591d1cba0de07625bc2461e71c76 *man/atanh_trans.Rd
+780eddf013a39e7b8c5fe4f95e2bfeec *man/boxcox_trans.Rd
+c82c29f561c587a0176210fb70b972c5 *man/brewer_pal.Rd
+eaf194b88f726dbc78adcb31e597e67d *man/cbreaks.Rd
+abe08ee28c8b500a428d99a15a6702de *man/censor.Rd
+057c32eec20053bba0ab8f4c3285587a *man/col2hcl.Rd
+fd4909fc3155ba9175d0aad916d2739f *man/col_numeric.Rd
+fa0983e358e9f4c6cf3404ea9e252aa6 *man/colour_ramp.Rd
+9f8f20685d08d3c8899e5edb87c8fb2e *man/comma_format.Rd
+6af58fb0659e35ccd623578022b68229 *man/cscale.Rd
+d1184e9313cea106baeccbfb11972a97 *man/date_breaks.Rd
+e2ce34f86735e443653a822ad00be127 *man/date_format.Rd
+db2d1f498451ba63ae9246530a107dae *man/date_trans.Rd
+a45f6f2fbec9075e23a5949e898384bd *man/dichromat_pal.Rd
+1d693820f56b36a92749acb1ef5c0c51 *man/discard.Rd
+ed3fcd5322e10fb47075dcb59e8a4379 *man/div_gradient_pal.Rd
+dd9f77b9581800966162dfcaf1bce214 *man/dollar_format.Rd
+aca55d1e3cf4a29a7587171c4c91f4f0 *man/dscale.Rd
+aefdfdcc999b84ae8baa165707006774 *man/exp_trans.Rd
+861eaade3c3ca07850123de7369528d5 *man/expand_range.Rd
+fb25e4a8c9dfc63378e7e33e1e2dde13 *man/extended_breaks.Rd
+c4eb666dde93e1837eb23cfaafcdfb60 *man/format_format.Rd
+10107f4aeecf4630093b1f05b4c957c3 *man/fullseq.Rd
+f24fbbbfcb040fee0585509d77936e6c *man/gradient_n_pal.Rd
+51435e80a8cf16fc6f779641404b9301 *man/grey_pal.Rd
+2102643b3fbaf92689fa1e138c3c7911 *man/hue_pal.Rd
+e430a9cd1580ea10b2303dc73a024c56 *man/identity_pal.Rd
+1dabc084871fe0a4ba5b4adda751fe12 *man/identity_trans.Rd
+642b0ab7efd8cb05c86e9eba6767e55e *man/linetype_pal.Rd
+88dc512a6a4d93ba73547dbf21498a6d *man/log1p_trans.Rd
+4f98a6e3e8aaa2be34a7dfca8f9c7d61 *man/log_breaks.Rd
+c5c53152d732efea98815eef3fa7d4db *man/log_trans.Rd
+7283343859583ac9c24910adcea53649 *man/manual_pal.Rd
+f88147e8f0a68082a33be8d0d9a2338a *man/math_format.Rd
+7edc85cada114baef84ac84c97ae7388 *man/muted.Rd
+37e2c97f91ef013cfaa73ca15c477cb3 *man/ordinal_format.Rd
+63bdd34d82fd68a683052aeed5409493 *man/package-scales.Rd
+42536b5030fc3c87497ad313199fccfa *man/parse_format.Rd
+ddbfda0cf145475fcb278fd7cec04d5f *man/percent_format.Rd
+e163f69f11dd3b5ea25a7e43c25a15ba *man/pretty_breaks.Rd
+b6814d4a32eeff376cb0faf8fb85db16 *man/probability_trans.Rd
+76e2d86afd4307c610fcd741bab16ced *man/reciprocal_trans.Rd
+b87f012dbe9dbb60e6d3786716282a29 *man/rescale.Rd
+6b3ea9a1fc3c698b00520734008b0ec1 *man/rescale_max.Rd
+587a98fdf6437581b7794980eff7d80f *man/rescale_mid.Rd
+c9ba91efea5c79cd225cc2f891e98af9 *man/rescale_none.Rd
+f316dffe50d948ce165a3f70f6885b71 *man/rescale_pal.Rd
+580b26f89573ac7fb3dc59f2ca10339a *man/reverse_trans.Rd
+09c7e1d1e5b681b09e35b5389cb40e69 *man/scientific_format.Rd
+6c59838270e62d62548d9844fd0b3071 *man/seq_gradient_pal.Rd
+b0bfb42b822b103e4247e723edd1244a *man/shape_pal.Rd
+e35211937f0d0333d7d8acf00884989d *man/show_col.Rd
+9b8a8077ed07e623fb1426a8be7148e8 *man/sqrt_trans.Rd
+3aae272f7d19655f21bf8ed3109d8a38 *man/squish.Rd
+cba1789efcb00599b2c60c34a9f7f423 *man/squish_infinite.Rd
+419b017f8806e229eabb09fcb33d7b3a *man/time_trans.Rd
+e2f975db54c837882e145854cbd70430 *man/trans_breaks.Rd
+7fef205b9dcd4e613cb4f8c00bf8ec92 *man/trans_format.Rd
+df03a130e2e2a562cf936c6fe36815f6 *man/trans_new.Rd
+7f96b3eecdbf2d1a4501d2af284081f7 *man/trans_range.Rd
+ac433e5b09bdef99c9d15a47f02e3500 *man/unit_format.Rd
+dbf6561109775b98018a4eb99a4b5aff *man/wrap_format.Rd
+6983587d9ba3532024f4b1a0617af6c9 *man/zero_range.Rd
+26153fe9ba8cc9c1db5c380f9b68ddd6 *src/RcppExports.cpp
+a6352bdbb8fc2eec47d3bd78ae92cb8d *src/colors.cpp
 1bc97669868c55fc86b10bffb2010b63 *tests/testthat.R
 41879206aab0f820a4262399a9357faf *tests/testthat/test-alpha.r
 210d4b72f91809cb8c82a36d60eff279 *tests/testthat/test-bounds.r
 b5bb7a6051319394602be12701d8b845 *tests/testthat/test-breaks-log.r
-ebcef8414ebe4ccb27a31661e9430a7c *tests/testthat/test-formatter.r
+361eca6c9ef2ec2361364c81ff4a39cc *tests/testthat/test-colors.r
+654894086b182f8a53ecd56ba01e03cc *tests/testthat/test-formatter.r
 306be4c95033a6b3d1446644165026eb *tests/testthat/test-range.r
 1f4791748d113fc5cf34c84c7325348c *tests/testthat/test-scale.r
 cf896ab44315aa38f0b00484b3e3c624 *tests/testthat/test-trans-date.r
 13c44729a8f80c2a38ed1be41a85b42c *tests/testthat/test-trans.r
-d3d90179f2c34194952dda5dd4d021d7 *tests/testthat/test-zero-range.r
+f898ccce2009062bb08a27f5e68d4eb0 *tests/testthat/test-zero-range.r
diff --git a/NAMESPACE b/NAMESPACE
index 50ed812..9e1c4e4 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -1,4 +1,4 @@
-# Generated by roxygen2 (4.0.0): do not edit by hand
+# Generated by roxygen2 (4.1.1): do not edit by hand
 
 S3method(fullseq,Date)
 S3method(fullseq,POSIXt)
@@ -17,6 +17,11 @@ export(brewer_pal)
 export(cbreaks)
 export(censor)
 export(col2hcl)
+export(col_bin)
+export(col_factor)
+export(col_numeric)
+export(col_quantile)
+export(colour_ramp)
 export(comma)
 export(comma_format)
 export(cscale)
@@ -50,6 +55,8 @@ export(logit_trans)
 export(manual_pal)
 export(math_format)
 export(muted)
+export(ordinal)
+export(ordinal_format)
 export(parse_format)
 export(percent)
 export(percent_format)
@@ -76,6 +83,11 @@ export(trans_breaks)
 export(trans_format)
 export(trans_new)
 export(trans_range)
+export(unit_format)
+export(wrap_format)
 export(zero_range)
+import(Rcpp)
+import(methods)
 import(munsell)
 import(plyr)
+useDynLib(scales)
diff --git a/NEWS b/NEWS
index 417e4fd..4d7aba0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,47 @@
+Version 0.2.5
+------------------------------------------------------------------------------
+
+## Improved formatting functions
+
+* `date_format()` gans an option to specify time zone (#51).
+
+* `dollar_format()` is now more flexible and can add either prefixes or 
suffixes
+  for different currencies (#53). It gains a `negative_parens` argument
+  to show negative values as `($100)` and now passes missing values through
+  unchanged (#40, @dougmitarotonda).
+
+* New `ordinal_format()` generates ordinal numbers (1st, 2nd etc)
+  (@aaronwolen, #55)
+
+* New `unit_format()` makes it easier to add units to labels, optionally
+  scaling (@ThierryO, 46)
+
+* New `wrap_format()` function to wrap character vectors to a desired width.
+  (@jimhester, #37).
+
+## New colour scaling functions
+
+* New color scaling functions `col_numeric()`, `col_bin()`, `col_quantile()`,
+  and `col_factor()`. These functions provide concise ways to map continuous or
+  categorical values to color spectra.
+
+* New `colour_ramp()` function for performing color interpolation in the CIELAB
+  color space (like `grDevices::colorRamp(space = 'Lab')`, but much faster).
+
+## Other bug fixes and minor improvements
+
+* `boxcox_trans()` returns correct value when p is close to zero (#31).
+
+* `dollar()` and `percent()` both correctly return a zero length string
+  for zero length input (@BrianDiggs, #35)
+
+* `brewer_pal()` gains a `direction` argument to easily invert the order
+  of colours (@jiho, #36).
+
+* `show_col()` has additional options to showcase colors better (@jiho, #52)
+
+* Relaxed tolerance in `zero_range()` to `.Machine$double.eps * 1000` (#33).
+
 Version 0.2.4
 ------------------------------------------------------------------------------
 
diff --git a/R/RcppExports.R b/R/RcppExports.R
new file mode 100644
index 0000000..ca72a2f
--- /dev/null
+++ b/R/RcppExports.R
@@ -0,0 +1,15 @@
+# This file was generated by Rcpp::compileAttributes
+# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
+
+doColorRamp <- function(colors, x, alpha, naColor) {
+    .Call('scales_doColorRamp', PACKAGE = 'scales', colors, x, alpha, naColor)
+}
+
+rgbToLab <- function(rgb) {
+    .Call('scales_rgbToLab', PACKAGE = 'scales', rgb)
+}
+
+rgbToXyz <- function(rgb) {
+    .Call('scales_rgbToXyz', PACKAGE = 'scales', rgb)
+}
+
diff --git a/R/bounds.r b/R/bounds.r
index aad2947..f8c22b5 100644
--- a/R/bounds.r
+++ b/R/bounds.r
@@ -12,7 +12,7 @@
 #' rescale(1)
 rescale <- function(x, to = c(0, 1), from = range(x, na.rm = TRUE)) {
   if (zero_range(from) || zero_range(to)) return(rep(mean(to), length(x)))
-  
+
   (x - from[1]) / diff(from) * diff(to) + to[1]
 }
 
@@ -30,7 +30,7 @@ rescale <- function(x, to = c(0, 1), from = range(x, na.rm = 
TRUE)) {
 #' rescale_mid(1)
 rescale_mid <- function(x, to = c(0, 1), from = range(x, na.rm = TRUE), mid = 
0) {
   if (zero_range(from) || zero_range(to)) return(rep(mean(to), length(x)))
-  
+
   extent <- 2 * max(abs(from - mid))
   (x - mid) / extent * diff(to) + mean(to)
 }
@@ -123,7 +123,7 @@ squish_infinite <- function(x, range = c(0, 1)) {
 }
 
 #' Expand a range with a multiplicative or additive constant.
-#' 
+#'
 #' @param range range of data, numeric vector of length 2
 #' @param mul multiplicative constract
 #' @param add additive constant
@@ -134,7 +134,7 @@ expand_range <- function(range, mul = 0, add = 0, 
zero_width = 1) {
 
   if (zero_range(range)) {
     c(range[1] - zero_width / 2, range[1] + zero_width / 2)
-  } else {    
+  } else {
     range + c(-1, 1) * (diff(range) * mul + add)
   }
 }
@@ -143,7 +143,7 @@ expand_range <- function(range, mul = 0, add = 0, 
zero_width = 1) {
 #'
 #' The machine epsilon is the difference between 1.0 and the next number
 #' that can be represented by the machine. By default, this function
-#' uses epsilon * 100 as the tolerance. First it scales the values so that
+#' uses epsilon * 1000 as the tolerance. First it scales the values so that
 #' they have a mean of 1, and then it checks if the difference between
 #' them is larger than the tolerance.
 #'
@@ -151,15 +151,15 @@ expand_range <- function(range, mul = 0, add = 0, 
zero_width = 1) {
 #' eps <- .Machine$double.eps
 #' zero_range(c(1, 1 + eps))       # TRUE
 #' zero_range(c(1, 1 + 99 * eps))  # TRUE
-#' zero_range(c(1, 1 + 101 * eps)) # FALSE - Crossed the tol threshold
+#' zero_range(c(1, 1 + 1001 * eps)) # FALSE - Crossed the tol threshold
 #' zero_range(c(1, 1 + 2 * eps), tol = eps) # FALSE - Changed tol
 #'
 #' # Scaling up or down all the values has no effect since the values
 #' # are rescaled to 1 before checking against tol
 #' zero_range(100000 * c(1, 1 + eps))        # TRUE
-#' zero_range(100000 * c(1, 1 + 200 * eps))  # FALSE
+#' zero_range(100000 * c(1, 1 + 1001 * eps))  # FALSE
 #' zero_range(.00001 * c(1, 1 + eps))        # TRUE
-#' zero_range(.00001 * c(1, 1 + 200 * eps))  # FALSE
+#' zero_range(.00001 * c(1, 1 + 1001 * eps))  # FALSE
 #'
 #' # NA values
 #' zero_range(c(1, NA))   # NA
@@ -172,11 +172,10 @@ expand_range <- function(range, mul = 0, add = 0, 
zero_width = 1) {
 #'
 #' @export
 #' @param x numeric range: vector of length 2
-#' @param tol A value specifying the tolerance. Defaults to
-#'   \code{.Machine$double.eps * 100}.
+#' @param tol A value specifying the tolerance.
 #' @return logical \code{TRUE} if the relative difference of the endpoints of
 #' the range are not distinguishable from 0.
-zero_range <- function(x, tol = .Machine$double.eps * 100) {
+zero_range <- function(x, tol = 1000 * .Machine$double.eps) {
   if (length(x) == 1) return(TRUE)
   if (length(x) != 2) stop("x must be length 1 or 2")
   if (any(is.na(x)))  return(NA)
diff --git a/R/colour-manip.r b/R/colour-manip.r
index f91f101..241f2d2 100644
--- a/R/colour-manip.r
+++ b/R/colour-manip.r
@@ -77,8 +77,10 @@ alpha <- function(colour, alpha = NA) {
 #' A quick and dirty way to show colours in a plot.
 #'
 #' @param colours a character vector of colours
+#' @param labels boolean, whether to show the hexadecimal representation of 
the colours in each tile
+#' @param borders colour of the borders of the tiles; matches the 
\code{border} argument of \code{\link[graphics]{rect}}. The default means 
\code{par("fg")}. Use \code{border = NA} to omit borders.
 #' @export
-show_col <- function(colours) {
+show_col <- function(colours, labels = TRUE, borders = NULL) {
   n <- length(colours)
   ncol <- ceiling(sqrt(n))
   nrow <- ceiling(n / ncol)
@@ -92,6 +94,8 @@ show_col <- function(colours) {
   size <- max(dim(colours))
   plot(c(0, size), c(0, -size), type = "n", xlab="", ylab="", axes = FALSE)
   rect(col(colours) - 1, -row(colours) + 1, col(colours), -row(colours),
-    col = colours)
-  text(col(colours) - 0.5, -row(colours) + 0.5, colours)
+    col = colours, border = borders)
+  if ( labels ) {
+    text(col(colours) - 0.5, -row(colours) + 0.5, colours)    
+  }
 }
diff --git a/R/colour-mapping.r b/R/colour-mapping.r
new file mode 100644
index 0000000..46e3c39
--- /dev/null
+++ b/R/colour-mapping.r
@@ -0,0 +1,386 @@
+#' Color mapping
+#'
+#' Conveniently maps data values (numeric or factor/character) to colors
+#' according to a given palette, which can be provided in a variety of formats.
+#'
+#' \code{col_numeric} is a simple linear mapping from continuous numeric data
+#' to an interpolated palette.
+#'
+#' @param palette The colors or color function that values will be mapped to
+#' @param domain The possible values that can be mapped.
+#'
+#'   For \code{col_numeric} and \code{col_bin}, this can be a simple numeric
+#'   range (e.g. \code{c(0, 100)}); \code{col_quantile} needs representative
+#'   numeric data; and \code{col_factor} needs categorical data.
+#'
+#'   If \code{NULL}, then whenever the resulting color function is called, the
+#'   \code{x} value will represent the domain. This implies that if the 
function
+#'   is invoked multiple times, the encoding between values and colors may not
+#'   be consistent; if consistency is needed, you must provide a 
non-\code{NULL}
+#'   domain.
+#' @param na.color The color to return for \code{NA} values. Note that
+#'   \code{na.color=NA} is valid.
+#'
+#' @return A function that takes a single parameter \code{x}; when called with 
a
+#'   vector of numbers (except for \code{col_factor}, which expects
+#'   factors/characters), #RRGGBB color strings are returned.
+#'
+#' @export
+col_numeric <- function(palette, domain, na.color = "#808080") {
+  rng <- NULL
+  if (length(domain) > 0) {
+    rng <- range(domain, na.rm = TRUE)
+    if (!all(is.finite(rng))) {
+      stop("Wasn't able to determine range of domain")
+    }
+  }
+
+  pf <- safePaletteFunc(palette, na.color)
+
+  withColorAttr('numeric', list(na.color = na.color), function(x) {
+    if (length(x) == 0 || all(is.na(x))) {
+      return(pf(x))
+    }
+
+    if (is.null(rng)) rng <- range(x, na.rm = TRUE)
+
+    rescaled <- scales::rescale(x, from = rng)
+    if (any(rescaled < 0 | rescaled > 1, na.rm = TRUE))
+      warning("Some values were outside the color scale and will be treated as 
NA")
+    pf(rescaled)
+  })
+}
+
+# Attach an attribute colorType to a color function f so we can derive legend
+# items from it
+withColorAttr <- function(type, args = list(), fun) {
+  structure(fun, colorType = type, colorArgs = args)
+}
+
+# domain may or may not be NULL.
+# Iff domain is non-NULL, x may be NULL.
+# bins is non-NULL. It may be a scalar value (# of breaks) or a set of breaks.
+getBins <- function(domain, x, bins, pretty) {
+  if (is.null(domain) && is.null(x)) {
+    stop("Assertion failed: domain and x can't both be NULL")
+  }
+
+  # Hard-coded bins
+  if (length(bins) > 1) {
+    return(bins)
+  }
+
+  if (bins < 2) {
+    stop("Invalid bins value of ", bins, "; bin count must be at least 2")
+  }
+  if (pretty) {
+    base::pretty(domain %||% x, n = bins)
+  } else {
+    rng <- range(domain %||% x, na.rm = TRUE)
+    seq(rng[1], rng[2], length.out = bins + 1)
+  }
+}
+
+#' @details \code{col_bin} also maps continuous numeric data, but performs
+#'   binning based on value (see the \code{\link[base]{cut}} function).
+#' @param bins Either a numeric vector of two or more unique cut points or a
+#'   single number (greater than or equal to 2) giving the number of intervals
+#'   into which the domain values are to be cut.
+#' @param pretty Whether to use the function \code{\link{pretty}()} to generate
+#'   the bins when the argument \code{bins} is a single number. When
+#'   \code{pretty = TRUE}, the actual number of bins may not be the number of
+#'   bins you specified. When \code{pretty = FALSE}, \code{\link{seq}()} is 
used
+#'   to generate the bins and the breaks may not be "pretty".
+#' @rdname col_numeric
+#' @export
+col_bin <- function(palette, domain, bins = 7, pretty = TRUE, na.color = 
"#808080") {
+  # domain usually needs to be explicitly provided (even if NULL) but not if
+  # breaks are specified
+  if (missing(domain) && length(bins) > 1) {
+    domain <- NULL
+  }
+  autobin <- is.null(domain) && length(bins) == 1
+  if (!is.null(domain))
+    bins <- getBins(domain, NULL, bins, pretty)
+  numColors <- if (length(bins) == 1) bins else length(bins) - 1
+  colorFunc <- col_factor(palette, domain = if (!autobin) 1:numColors, 
na.color = na.color)
+  pf = safePaletteFunc(palette, na.color)
+
+  withColorAttr('bin', list(bins = bins, na.color = na.color), function(x) {
+    if (length(x) == 0 || all(is.na(x))) {
+      return(pf(x))
+    }
+    binsToUse <- getBins(domain, x, bins, pretty)
+    ints <- cut(x, binsToUse, labels = FALSE, include.lowest = TRUE, right = 
FALSE)
+    if (any(is.na(x) != is.na(ints)))
+      warning("Some values were outside the color scale and will be treated as 
NA")
+    colorFunc(ints)
+  })
+}
+
+#' @details \code{col_quantile} similarly bins numeric data, but via the
+#'   \code{\link[stats]{quantile}} function.
+#' @param n Number of equal-size quantiles desired. For more precise control,
+#'   use the \code{probs} argument instead.
+#' @param probs See \code{\link[stats]{quantile}}. If provided, the \code{n}
+#'   argument is ignored.
+#' @rdname col_numeric
+#' @export
+col_quantile <- function(palette, domain, n = 4,
+  probs = seq(0, 1, length.out = n + 1), na.color = "#808080") {
+
+  if (!is.null(domain)) {
+    bins <- quantile(domain, probs, na.rm = TRUE, names = FALSE)
+    return(withColorAttr(
+      'quantile', list(probs = probs, na.color = na.color),
+      col_bin(palette, domain = NULL, bins = bins, na.color = na.color)
+    ))
+  }
+
+  # I don't have a precise understanding of how quantiles are meant to map to 
colors.
+  # If you say probs = seq(0, 1, 0.25), which has length 5, does that map to 4 
colors
+  # or 5? 4, right?
+  colorFunc <- col_factor(palette, domain = 1:(length(probs) - 1), na.color = 
na.color)
+  withColorAttr('quantile', list(probs = probs, na.color = na.color), 
function(x) {
+    binsToUse <- quantile(x, probs, na.rm = TRUE, names = FALSE)
+    ints <- cut(x, binsToUse, labels = FALSE, include.lowest = TRUE, right = 
FALSE)
+    if (any(is.na(x) != is.na(ints)))
+      warning("Some values were outside the color scale and will be treated as 
NA")
+    colorFunc(ints)
+  })
+}
+
+# If already a factor, return the levels. Otherwise, convert to factor then
+# return the levels.
+calcLevels <- function(x, ordered) {
+  if (is.null(x)) {
+    NULL
+  } else if (is.factor(x)) {
+    levels(x)
+  } else if (ordered) {
+    unique(x)
+  } else {
+    sort(unique(x))
+  }
+}
+
+getLevels <- function(domain, x, lvls, ordered) {
+  if (!is.null(lvls))
+    return(lvls)
+
+  if (!is.null(domain)) {
+    return(calcLevels(domain, ordered))
+  }
+
+  if (!is.null(x)) {
+    return(calcLevels(x, ordered))
+  }
+}
+
+#' @details \code{col_factor} maps factors to colors. If the palette is
+#'   discrete and has a different number of colors than the number of factors,
+#'   interpolation is used.
+#' @param levels An alternate way of specifying levels; if specified, domain is
+#'   ignored
+#' @param ordered If \code{TRUE} and \code{domain} needs to be coerced to a
+#'   factor, treat it as already in the correct order
+#' @rdname col_numeric
+#' @export
+col_factor <- function(palette, domain, levels = NULL, ordered = FALSE,
+  na.color = "#808080") {
+
+  # domain usually needs to be explicitly provided (even if NULL) but not if
+  # levels are specified
+  if (missing(domain) && !is.null(levels)) {
+    domain <- NULL
+  }
+
+  if (!is.null(levels) && anyDuplicated(levels)) {
+    warning("Duplicate levels detected")
+    levels <- unique(levels)
+  }
+  lvls <- getLevels(domain, NULL, levels, ordered)
+  hasFixedLevels <- is.null(lvls)
+  pf <- safePaletteFunc(palette, na.color)
+
+  withColorAttr('factor', list(na.color = na.color), function(x) {
+    if (length(x) == 0 || all(is.na(x))) {
+      return(pf(x))
+    }
+
+    lvls <- getLevels(domain, x, lvls, ordered)
+
+    if (!is.factor(x) || hasFixedLevels) {
+      origNa <- is.na(x)
+      # Seems like we need to re-factor if hasFixedLevels, in case the x value
+      # has a different set of levels (like if droplevels was called in between
+      # when the domain was given and now)
+      x <- factor(x, lvls)
+      if (any(is.na(x) != origNa)) {
+        warning("Some values were outside the color scale and will be treated 
as NA")
+      }
+    }
+
+    scaled <- scales::rescale(as.integer(x), from = c(1, length(lvls)))
+    if (any(scaled < 0 | scaled > 1, na.rm = TRUE)) {
+      warning("Some values were outside the color scale and will be treated as 
NA")
+    }
+    pf(scaled)
+  })
+}
+
+#' @details The \code{palette} argument can be any of the following:
+#' \enumerate{
+#'   \item{A character vector of RGB or named colors. Examples: 
\code{palette()}, \code{c("#000000", "#0000FF", "#FFFFFF")}, 
\code{topo.colors(10)}}
+#'   \item{The name of an RColorBrewer palette, e.g. \code{"BuPu"} or 
\code{"Greens"}.}
+#'   \item{A function that receives a single value between 0 and 1 and returns 
a color. Examples: \code{colorRamp(c("#000000", "#FFFFFF"), 
interpolate="spline")}.}
+#' }
+#' @examples
+#' pal <- col_bin("Greens", domain = 0:100)
+#' show_col(pal(sort(runif(10, 60, 100))))
+#'
+#' # Exponential distribution, mapped continuously
+#' show_col(col_numeric("Blues", domain = NULL)(sort(rexp(16))))
+#' # Exponential distribution, mapped by interval
+#' show_col(col_bin("Blues", domain = NULL, bins = 4)(sort(rexp(16))))
+#' # Exponential distribution, mapped by quantile
+#' show_col(col_quantile("Blues", domain = NULL)(sort(rexp(16))))
+#'
+#' # Categorical data; by default, the values being colored span the gamut...
+#' show_col(col_factor("RdYlBu", domain = NULL)(LETTERS[1:5]))
+#' # ...unless the data is a factor, without droplevels...
+#' show_col(col_factor("RdYlBu", domain = NULL)(factor(LETTERS[1:5], 
levels=LETTERS)))
+#' # ...or the domain is stated explicitly.
+#' show_col(col_factor("RdYlBu", levels = LETTERS)(LETTERS[1:5]))
+#' @rdname col_numeric
+#' @name col_numeric
+NULL
+
+
+safePaletteFunc <- function(pal, na.color) {
+  filterRange(
+    filterNA(na.color = na.color,
+      filterZeroLength(
+        filterRGB(
+          toPaletteFunc(pal)
+        )
+      )
+    )
+  )
+}
+
+toPaletteFunc <- function(pal) {
+  UseMethod("toPaletteFunc")
+}
+
+# Strings are interpreted as color names, unless length is 1 and it's the name
+# of an RColorBrewer palette
+toPaletteFunc.character <- function(pal) {
+  if (length(pal) == 1 && pal %in% row.names(RColorBrewer::brewer.pal.info)) {
+    return(colour_ramp(
+      RColorBrewer::brewer.pal(RColorBrewer::brewer.pal.info[pal, 
'maxcolors'], pal)
+    ))
+  }
+
+  colour_ramp(pal)
+}
+
+# Accept colorRamp style matrix
+toPaletteFunc.matrix <- function(pal) {
+  toPaletteFunc(rgb(pal, maxColorValue = 255))
+}
+
+# If a function, just assume it's already a function over [0-1]
+toPaletteFunc.function <- function(pal) {
+  pal
+}
+
+# colorRamp(space = 'Lab') throws error when called with
+# zero-length input
+filterZeroLength <- function(f) {
+  force(f)
+  function(x) {
+    if (length(x) == 0) {
+      character(0)
+    } else {
+      f(x)
+    }
+  }
+}
+
+# Wraps an underlying non-NA-safe function (like colorRamp).
+filterNA <- function(f, na.color) {
+  force(f)
+  function(x) {
+    results <- character(length(x))
+    nas <- is.na(x)
+    results[nas] <- na.color
+    results[!nas] <- f(x[!nas])
+    results
+  }
+}
+
+# Wraps a function that may return RGB color matrix instead of rgb string.
+filterRGB <- function(f) {
+  force(f)
+  function(x) {
+    results <- f(x)
+    if (is.character(results)) {
+      results
+    } else if (is.matrix(results)) {
+      rgb(results, maxColorValue = 255)
+    } else {
+      stop("Unexpected result type ", class(x)[[1]])
+    }
+  }
+}
+
+filterRange <- function(f) {
+  force(f)
+  function(x) {
+    x[x < 0 | x > 1] <- NA
+    f(x)
+  }
+}
+
+#' Fast color interpolation
+#'
+#' Returns a function that maps the interval [0,1] to a set of colors.
+#' Interpolation is performed in the CIELAB color space. Similar to
+#' \code{\link[grDevices]{colorRamp}(space = 'Lab')}, but hundreds of
+#' times faster, and provides results in \code{"#RRGGBB"} (or
+#' \code{"#RRGGBBAA"}) character form instead of RGB color matrices.
+#'
+#' @param colors Colors to interpolate; must be a valid argument to
+#'   \code{\link[grDevices]{col2rgb}}. This can be a character vector of
+#'   \code{"#RRGGBB"} or  \code{"#RRGGBBAA"}, color names from
+#'   \code{\link[grDevices]{colors}}, or a positive integer that indexes into
+#'   \code{\link[grDevices]{palette}()}.
+#' @param na.color The color to map to \code{NA} values (for example,
+#'   \code{"#606060"} for dark grey, or \code{"#00000000"} for transparent) and
+#'   values outside of [0,1]. Can itself by \code{NA}, which will simply cause
+#'   an \code{NA} to be inserted into the output.
+#' @param alpha Whether to include alpha channels in interpolation; otherwise,
+#'   any alpha information will be discarded. If \code{TRUE} then the returned
+#'   function will provide colors in \code{"#RRGGBBAA"} format instead of
+#'   \code{"#RRGGBB"}.
+#'
+#' @return A function that takes a numeric vector and returns a character 
vector
+#'   of the same length with RGB or RGBA hex colors.
+#'
+#' @seealso \link[grDevices]{colorRamp}
+#'
+#' @export
+colour_ramp <- function(colors, na.color = NA, alpha = FALSE) {
+  if (length(colors) == 0) {
+    stop("Must provide at least one color to create a color ramp")
+  }
+
+  colorMatrix <- col2rgb(colors, alpha = alpha)
+  structure(
+    function(x) {
+      doColorRamp(colorMatrix, x, alpha, ifelse(is.na(na.color), "", na.color))
+    },
+    safe_palette_func = TRUE
+  )
+}
diff --git a/R/date-time.r b/R/date-time.r
index a73e2dd..027f6d8 100644
--- a/R/date-time.r
+++ b/R/date-time.r
@@ -1,4 +1,4 @@
-# Minimal date time code so no external dependencies needed, and 
+# Minimal date time code so no external dependencies needed, and
 # we can do the date operations we need.  Need to look at this again once we
 # switch to S4 for lubridate.
 
@@ -23,33 +23,33 @@ floor_time <- function(date, time) {
   if (prec$unit == "sec") {
     to_time(round_any(as.numeric(date), prec$mult))
   } else if (prec$unit == "min") {
-    to_time(round_any(as.numeric(date), prec$mult * 60))    
+    to_time(round_any(as.numeric(date), prec$mult * 60))
   } else {
     as.POSIXct(
-      cut(date, time, right = TRUE, include.lowest = TRUE), 
+      cut(date, time, right = TRUE, include.lowest = TRUE),
       tz = attr(date, "tz") %||% ""
-    )  
+    )
   }
 }
 
-ceiling_date <- function(date, time) { 
+ceiling_date <- function(date, time) {
   prec <- parse_unit_spec(time)
-  
+
   up <- c("day" = 1, "week" = 7, "month" = 31, "year" = 365)
   date <- date + prec$mult * up[prec$unit]
-  
+
   floor_date(date, time)
 }
 
-ceiling_time <- function(date, time) { 
+ceiling_time <- function(date, time) {
   prec <- parse_unit_spec(time)
-  
+
   up <- c(
-    "sec" = 1, "min" = 60, "hour" = 3600, 
+    "sec" = 1, "min" = 60, "hour" = 3600,
     c("day" = 1, "week" = 7, "month" = 31, "year" = 365) * 3600 * 24
   )
   date <- date + prec$mult * up[prec$unit]
-  
+
   floor_time(date, time)
 }
 
@@ -63,6 +63,6 @@ parse_unit_spec <- function(unitspec) {
     unit <- parts[[2]]
   }
   unit <- gsub("s$", "", unit)
-  
+
   list(unit = unit, mult = mult)
 }
diff --git a/R/formatter.r b/R/formatter.r
index 010aca1..1ee28ab 100644
--- a/R/formatter.r
+++ b/R/formatter.r
@@ -2,13 +2,19 @@
 #'
 #' @param ... other arguments passed on to \code{\link{format}}
 #' @param x a numeric vector to format
-#' @return a function with single paramater x, a numeric vector, that
+#' @return a function with single parameter x, a numeric vector, that
 #'   returns a character vector
 #' @export
 #' @examples
 #' comma_format()(c(1, 1e3, 2000, 1e6))
 #' comma_format(digits = 9)(c(1, 1e3, 2000, 1e6))
 #' comma(c(1, 1e3, 2000, 1e6))
+#'
+#' # If you're European you can switch . and , with the more general
+#' # format_format
+#' point <- format_format(big.mark = ".", decimal.mark = ",", scientific = 
FALSE)
+#' point(c(1, 1e3, 2000, 1e6))
+#' point(c(1, 1.021, 1000.01))
 comma_format <- function(...) {
   function(x) comma(x, ...)
 }
@@ -26,39 +32,77 @@ comma <- function(x, ...) {
 #' any of the values has a non-zero cents and the largest value is less
 #' than \code{largest_with_cents} which by default is 100000.
 #'
-#' @return a function with single paramater x, a numeric vector, that
+#' @return a function with single parameter x, a numeric vector, that
 #'   returns a character vector
 #' @param largest_with_cents the value that all values of \code{x} must
 #'   be less than in order for the cents to be displayed
+#' @param prefix,suffix Symbols to display before and after amount.
+#' @param big.mark Character used between every 3 digits.
+#' @param negative_parens Should negative values be shown with parentheses?
+#' @param ... Other arguments passed on to \code{\link{format}}.
 #' @param x a numeric vector to format
 #' @export
 #' @examples
-#' dollar_format()(c(100, 0.23, 1.456565, 2e3))
+#' dollar_format()(c(-100, 0.23, 1.456565, 2e3))
 #' dollar_format()(c(1:10 * 10))
 #' dollar(c(100, 0.23, 1.456565, 2e3))
 #' dollar(c(1:10 * 10))
 #' dollar(10^(1:8))
-dollar_format <- function(largest_with_cents = 100000) {
+#'
+#' usd <- dollar_format(prefix = "USD ")
+#' usd(c(100, -100))
+#'
+#' euro <- dollar_format(prefix = "", suffix = "\u20ac")
+#' euro(100)
+#'
+#' finance <- dollar_format(negative_parens = TRUE)
+#' finance(c(-100, 100))
+dollar_format <- function(prefix = "$", suffix = "",
+                          largest_with_cents = 100000, ..., big.mark = ",",
+                          negative_parens = FALSE) {
   function(x) {
+    if (length(x) == 0) return(character())
     x <- round_any(x, 0.01)
-    if (max(x, na.rm = TRUE) < largest_with_cents &
-        !all(x == floor(x), na.rm = TRUE)) {
+    if (needs_cents(x, largest_with_cents)) {
       nsmall <- 2L
     } else {
       x <- round_any(x, 1)
       nsmall <- 0L
     }
-    paste0("$", format(x, nsmall = nsmall, trim = TRUE, big.mark = ",", 
scientific = FALSE, digits=1L))
+
+    negative <- !is.na(x) & x < 0
+    if (negative_parens) {
+      x <- abs(x)
+    }
+
+    amount <- format(abs(x), nsmall = nsmall, trim = TRUE, big.mark = big.mark,
+      scientific = FALSE, digits = 1L)
+
+    if (negative_parens) {
+      paste0(ifelse(negative, "(", ""), prefix, amount, suffix, 
ifelse(negative, ")", ""))
+    } else {
+      paste0(prefix, ifelse(negative, "-", ""), amount, suffix)
+    }
   }
 }
 
+needs_cents <- function(x, threshold) {
+  if (all(is.na(x)))
+    return(FALSE)
+
+  if (max(abs(x), na.rm = TRUE) > threshold)
+    return(FALSE)
+
+  !all(x == floor(x), na.rm = TRUE)
+}
+
 #' @export
 #' @rdname dollar_format
 dollar <- dollar_format()
 
 #' Percent formatter: multiply by one hundred and display percent sign.
 #'
-#' @return a function with single paramater x, a numeric vector, that
+#' @return a function with single parameter x, a numeric vector, that
 #'   returns a character vector
 #' @param x a numeric vector to format
 #' @export
@@ -68,6 +112,7 @@ dollar <- dollar_format()
 #' percent(runif(10, 1, 10))
 percent_format <- function() {
   function(x) {
+    if (length(x) == 0) return(character())
     x <- round_any(x, precision(x) / 100)
     paste0(comma(x * 100), "%")
   }
@@ -78,7 +123,7 @@ percent <- percent_format()
 
 #' Scientific formatter.
 #'
-#' @return a function with single paramater x, a numeric vector, that
+#' @return a function with single parameter x, a numeric vector, that
 #'   returns a character vector
 #' @param digits number of significant digits to show
 #' @param ... other arguments passed on to \code{\link{format}}
@@ -102,10 +147,41 @@ scientific <- function(x, digits = 3, ...) {
   format(x, trim = TRUE, scientific = TRUE, ...)
 }
 
+#' Ordinal formatter: add ordinal suffixes (-st, -nd, -rd, -th) to numbers.
+#'
+#' @return a function with single paramater x, a numeric vector, that
+#'   returns a character vector
+#' @param x a numeric vector to format
+#' @export
+#' @examples
+#' ordinal_format()(1:10)
+#' ordinal(1:10)
+
+ordinal_format <- function(x) {
+  function(x) ordinal(x)
+}
+
+#' @export
+#' @rdname ordinal_format
+ordinal <- function(x) {
+  stopifnot(all(x > 0))
+
+  suffixes <- list(
+    st = "(?<!1)1$",
+    nd = "(?<!1)2$",
+    rd = "(?<!1)3$",
+    th = "(?<=1)[123]$",
+    th = "[0456789]$"
+  )
+
+  out <- stack(llply(suffixes, grep, x = x, perl = TRUE))
+  paste0(comma(x), out$ind[order(out$values)])
+}
+
 #' Parse a text label to produce expressions for plotmath.
 #'
 #' @seealso \code{\link{plotmath}}
-#' @return a function with single paramater x, a character vector, that
+#' @return a function with single parameter x, a character vector, that
 #'    returns a list of expressions
 #' @export
 #' @examples
@@ -123,7 +199,7 @@ parse_format <- function() {
 #' @param format another format function to apply prior to mathematical
 #'   transformation - this makes it easier to use floating point numbers in
 #'   mathematical expressions.
-#' @return a function with single paramater x, a numeric vector, that
+#' @return a function with single parameter x, a numeric vector, that
 #'    returns a list of expressions
 #' @export
 #' @seealso \code{\link{plotmath}}
@@ -145,11 +221,26 @@ math_format <- function(expr = 10 ^ .x, format = force) {
 }
 globalVariables(".x")
 
+#' Wrap text to a specified width, adding newlines for spaces if text exceeds
+#' the width
+#'
+#' @param width value above which to wrap
+#' @return Function with single parameter x, a character vector, that
+#'    returns a wrapped character vector
+#' @export
+#' @examples
+#' wrap_10 <- wrap_format(10)
+#' wrap_10('A long line that needs to be wrapped')
+wrap_format <- function(width) {
+  function(x) {
+    unlist(lapply(strwrap(x, width = width, simplify = FALSE), paste0, 
collapse = "\n"))
+  }
+}
 #' Format labels after transformation.
 #'
 #' @param trans transformation to apply
 #' @param format additional formatter to apply after transformation
-#' @return a function with single paramater x, a numeric vector, that
+#' @return a function with single parameter x, a numeric vector, that
 #'    returns a character vector of list of expressions
 #' @export
 #' @examples
@@ -183,6 +274,28 @@ format_format <- function(...) {
 precision <- function(x) {
   rng <- range(x, na.rm = TRUE)
 
-  span <- if (zero_range(rng)) rng[1] else diff(rng)
+  span <- if (zero_range(rng)) abs(rng[1]) else diff(rng)
   10 ^ floor(log10(span))
 }
+
+#' Add units to the labels
+#'
+#' @param unit The units to append
+#' @param scale A scaling factor. Useful if the underlying data is on another 
scale
+#' @param sep The separator between the number and the label
+#' @param ... Arguments passed on to \code{\link{format}}
+#' @export
+#' @examples
+#' # labels in kilometer when the raw data are in meter
+#' km <- unit_format(unit = "km", scale = 1e-3, digits = 2)
+#' km(runif(10) * 1e3)
+#'
+#' # labels in hectares, raw data in square meters
+#' ha <- unit_format(unit = "ha", scale = 1e-4)
+#' km(runif(10) * 1e5)
+#' @seealso \code{\link{comma}}
+unit_format <- function(unit = "m", scale = 1, sep = " ", ...){
+  function(x){
+    paste(comma(x * scale, ...), unit, sep = sep)
+  }
+}
diff --git a/R/pal-brewer.r b/R/pal-brewer.r
index b840a5b..325a339 100644
--- a/R/pal-brewer.r
+++ b/R/pal-brewer.r
@@ -3,6 +3,9 @@
 #' @param type One of seq (sequential), div (diverging) or qual (qualitative)
 #' @param palette If a string, will use that named palette.  If a number, will
 #'   index into the list of palettes of appropriate \code{type}
+#' @param direction Sets the order of colors in the scale. If 1, the default,
+#'   colors are as output by \code{\link[RColorBrewer]{brewer.pal}}. If -1, the
+#'   order of colors is reversed.
 #' @references \url{http://colorbrewer2.org}
 #' @export
 #' @examples
@@ -13,21 +16,27 @@
 #' # Can use with gradient_n to create a continous gradient
 #' cols <- brewer_pal("div")(5)
 #' show_col(gradient_n_pal(cols)(seq(0, 1, length = 30)))
-brewer_pal <- function(type = "seq", palette = 1) {
+brewer_pal <- function(type = "seq", palette = 1, direction = 1) {
   pal <- pal_name(palette, type)
 
-  # If <3 colors are requested, brewer.pal will return a 3-color palette and
-  # give a warning. This warning isn't useful, so suppress it.
-  # If the palette has k colors and >k colors are requested, brewer.pal will
-  # return a k-color palette and give a warning. This warning is useful, so
-  # don't suppress it. In both cases, the seq_len(n) is there to make sure
-  # that the n items are returned, even if brewer.pal returns a different
-  # number of items.
   function(n) {
-    if (n < 3)
-      suppressWarnings(RColorBrewer::brewer.pal(n, pal))[seq_len(n)]
-    else
-      RColorBrewer::brewer.pal(n, pal)[seq_len(n)]
+    # If <3 colors are requested, brewer.pal will return a 3-color palette and
+    # give a warning. This warning isn't useful, so suppress it.
+    # If the palette has k colors and >k colors are requested, brewer.pal will
+    # return a k-color palette and give a warning. This warning is useful, so
+    # don't suppress it.
+    if (n < 3) {
+      pal <- suppressWarnings(RColorBrewer::brewer.pal(n, pal))
+    } else {
+      pal <- RColorBrewer::brewer.pal(n, pal)
+    }
+    # In both cases ensure we have n items
+    pal <- pal[seq_len(n)]
+
+    if (direction == -1)
+      pal <- rev(pal)
+
+    pal
   }
 }
 
diff --git a/R/pal-hue.r b/R/pal-hue.r
index ba8effc..8afd14a 100644
--- a/R/pal-hue.r
+++ b/R/pal-hue.r
@@ -3,7 +3,7 @@
 #' @param h range of hues to use, in [0, 360]
 #' @param l luminance (lightness), in [0, 100]
 #' @param c chroma (intensity of colour), maximum value varies depending on
-#    combination of hue and luminance.
+#'   combination of hue and luminance.
 #' @param h.start hue to start at
 #' @param direction direction to travel around the colour wheel,
 #'   1 = clockwise, -1 = counter-clockwise
diff --git a/R/pal-shape.r b/R/pal-shape.r
index 450c8e3..9cef4a5 100644
--- a/R/pal-shape.r
+++ b/R/pal-shape.r
@@ -7,7 +7,7 @@ shape_pal <- function(solid = TRUE) {
     if (n > 6) {
       msg <- paste("The shape palette can deal with a maximum of 6 discrete ", 
         "values because more than 6 becomes difficult to discriminate; ",
-        "you have ", n, ". Consider specifying shapes manually. if you ",
+        "you have ", n, ". Consider specifying shapes manually if you ",
         "must have them.", sep = "")
       warning(paste(strwrap(msg), collapse = "\n"), call. = FALSE)
     }
diff --git a/R/scales.r b/R/scales.r
index 74bce73..48a9a93 100644
--- a/R/scales.r
+++ b/R/scales.r
@@ -3,5 +3,6 @@
 #' @docType package
 #' @name package-scales
 #' @aliases scales package-scales
-#' @import munsell plyr
+#' @import munsell plyr Rcpp methods
+#' @useDynLib scales
 NULL
diff --git a/R/trans-date.r b/R/trans-date.r
index d42ac5b..9dd0fe6 100644
--- a/R/trans-date.r
+++ b/R/trans-date.r
@@ -68,7 +68,9 @@ date_breaks <- function(width = "1 month") {
 #' 
 #' @param format Date format using standard POSIX specification.  See
 #'  \code{\link{strptime}} for possible formats.
+#' @param tz a time zone name, see \code{\link{timezones}}. Defaults
+#'  to UTC
 #' @export
-date_format <- function(format = "%Y-%m-%d") {
-  function(x) format(x, format)
+date_format <- function(format = "%Y-%m-%d", tz = 'UTC') {
+  function(x) format(x, format, tz = tz)
 }
diff --git a/R/trans-numeric.r b/R/trans-numeric.r
index 0d06ba4..15a02bc 100644
--- a/R/trans-numeric.r
+++ b/R/trans-numeric.r
@@ -22,7 +22,7 @@ atanh_trans <- function() {
 #   more details on method.
 #' @export
 boxcox_trans <- function(p) {
-  if (abs(p) < 1e-07) return(log_trans)
+  if (abs(p) < 1e-07) return(log_trans())
 
   trans <- function(x) (x ^ p - 1) / p * sign(x - 1)
   inv <- function(x) (abs(x) * p + 1 * sign(x)) ^ (1 / p)
@@ -71,6 +71,9 @@ log2_trans <- function() {
 #' Log plus one transformation.
 #'
 #' @export
+#' @examples
+#' trans_range(log_trans(), 1:10)
+#' trans_range(log1p_trans(), 0:9)
 log1p_trans <- function() {
   trans_new("log1p", "log1p", "expm1")
 }
diff --git a/README.md b/README.md
index d6cae00..89f29e6 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
 # Scales
 
 [![Build 
Status](https://travis-ci.org/hadley/scales.png?branch=master)](https://travis-ci.org/hadley/scales)
+[![Coverage 
Status](https://img.shields.io/codecov/c/github/hadley/scales/master.svg)](https://codecov.io/github/hadley/scales?branch=master)
+[![CRAN_Status_Badge](http://www.r-pkg.org/badges/version/scales)](http://cran.r-project.org/web/packages/scales)
 
 One of the most difficult parts of any graphics package is scaling, converting 
from data values to perceptual properties. The inverse of scaling, making 
guides (legends and axes) that can be used to read the graph, is often even 
harder! The idea of the `scales` package is to implement scales in a way that 
is graphics system agnostic, so that everyone can benefit by pooling knowledge 
and resources about this tricky topic.
 
diff --git a/build/partial.rdb b/build/partial.rdb
index 5ed6d6a..527592f 100644
Binary files a/build/partial.rdb and b/build/partial.rdb differ
diff --git a/man/Range-class.Rd b/man/Range-class.Rd
index 40e6d80..892f5ce 100644
--- a/man/Range-class.Rd
+++ b/man/Range-class.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/range.r
 \docType{class}
 \name{Range-class}
 \alias{ContinuousRange}
diff --git a/man/abs_area.Rd b/man/abs_area.Rd
index 43c4b22..8f9d0b3 100644
--- a/man/abs_area.Rd
+++ b/man/abs_area.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-area.r
 \name{abs_area}
 \alias{abs_area}
 \title{Point area palette (continuous), with area proportional to value.}
diff --git a/man/alpha.Rd b/man/alpha.Rd
index 68c9693..e6cac66 100644
--- a/man/alpha.Rd
+++ b/man/alpha.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/colour-manip.r
 \name{alpha}
 \alias{alpha}
 \title{Modify colour transparency.
diff --git a/man/area_pal.Rd b/man/area_pal.Rd
index 8f827cc..0719554 100644
--- a/man/area_pal.Rd
+++ b/man/area_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-area.r
 \name{area_pal}
 \alias{area_pal}
 \title{Point area palette (continuous).}
diff --git a/man/as.trans.Rd b/man/as.trans.Rd
index 5a58dee..87dbbc2 100644
--- a/man/as.trans.Rd
+++ b/man/as.trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans.r
 \name{as.trans}
 \alias{as.trans}
 \title{Convert character string to transformer.}
diff --git a/man/asn_trans.Rd b/man/asn_trans.Rd
index f6675e4..796742e 100644
--- a/man/asn_trans.Rd
+++ b/man/asn_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{asn_trans}
 \alias{asn_trans}
 \title{Arc-sin square root transformation.}
diff --git a/man/atanh_trans.Rd b/man/atanh_trans.Rd
index 387d600..839e844 100644
--- a/man/atanh_trans.Rd
+++ b/man/atanh_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{atanh_trans}
 \alias{atanh_trans}
 \title{Arc-tangent transformation.}
diff --git a/man/boxcox_trans.Rd b/man/boxcox_trans.Rd
index 88946c7..2b6c02a 100644
--- a/man/boxcox_trans.Rd
+++ b/man/boxcox_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{boxcox_trans}
 \alias{boxcox_trans}
 \title{Box-Cox power transformation.}
diff --git a/man/brewer_pal.Rd b/man/brewer_pal.Rd
index a4a5418..9b28c01 100644
--- a/man/brewer_pal.Rd
+++ b/man/brewer_pal.Rd
@@ -1,15 +1,20 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-brewer.r
 \name{brewer_pal}
 \alias{brewer_pal}
 \title{Color Brewer palette (discrete).}
 \usage{
-brewer_pal(type = "seq", palette = 1)
+brewer_pal(type = "seq", palette = 1, direction = 1)
 }
 \arguments{
 \item{type}{One of seq (sequential), div (diverging) or qual (qualitative)}
 
 \item{palette}{If a string, will use that named palette.  If a number, will
 index into the list of palettes of appropriate \code{type}}
+
+\item{direction}{Sets the order of colors in the scale. If 1, the default,
+colors are as output by \code{\link[RColorBrewer]{brewer.pal}}. If -1, the
+order of colors is reversed.}
 }
 \description{
 Color Brewer palette (discrete).
diff --git a/man/cbreaks.Rd b/man/cbreaks.Rd
index efe31ae..fcc327d 100644
--- a/man/cbreaks.Rd
+++ b/man/cbreaks.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/breaks.r
 \name{cbreaks}
 \alias{cbreaks}
 \title{Compute breaks for continuous scale.}
diff --git a/man/censor.Rd b/man/censor.Rd
index 9af74dd..4d6802e 100644
--- a/man/censor.Rd
+++ b/man/censor.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{censor}
 \alias{censor}
 \title{Censor any values outside of range.}
diff --git a/man/col2hcl.Rd b/man/col2hcl.Rd
index f52a659..c985e5a 100644
--- a/man/col2hcl.Rd
+++ b/man/col2hcl.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/colour-manip.r
 \name{col2hcl}
 \alias{col2hcl}
 \title{Modify standard R colour in hcl colour space.}
@@ -10,10 +11,10 @@ col2hcl(colour, h, c, l, alpha = 1)
 
 \item{h}{new hue}
 
-\item{l}{new luminance}
-
 \item{c}{new chroma}
 
+\item{l}{new luminance}
+
 \item{alpha}{alpha value.  Defaults to 1.}
 }
 \description{
diff --git a/man/col_numeric.Rd b/man/col_numeric.Rd
new file mode 100644
index 0000000..a32a9ee
--- /dev/null
+++ b/man/col_numeric.Rd
@@ -0,0 +1,108 @@
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/colour-mapping.r
+\name{col_numeric}
+\alias{col_bin}
+\alias{col_factor}
+\alias{col_numeric}
+\alias{col_quantile}
+\title{Color mapping}
+\usage{
+col_numeric(palette, domain, na.color = "#808080")
+
+col_bin(palette, domain, bins = 7, pretty = TRUE, na.color = "#808080")
+
+col_quantile(palette, domain, n = 4, probs = seq(0, 1, length.out = n + 1),
+  na.color = "#808080")
+
+col_factor(palette, domain, levels = NULL, ordered = FALSE,
+  na.color = "#808080")
+}
+\arguments{
+\item{palette}{The colors or color function that values will be mapped to}
+
+\item{domain}{The possible values that can be mapped.
+
+  For \code{col_numeric} and \code{col_bin}, this can be a simple numeric
+  range (e.g. \code{c(0, 100)}); \code{col_quantile} needs representative
+  numeric data; and \code{col_factor} needs categorical data.
+
+  If \code{NULL}, then whenever the resulting color function is called, the
+  \code{x} value will represent the domain. This implies that if the function
+  is invoked multiple times, the encoding between values and colors may not
+  be consistent; if consistency is needed, you must provide a non-\code{NULL}
+  domain.}
+
+\item{na.color}{The color to return for \code{NA} values. Note that
+  \code{na.color=NA} is valid.}
+
+\item{bins}{Either a numeric vector of two or more unique cut points or a
+single number (greater than or equal to 2) giving the number of intervals
+into which the domain values are to be cut.}
+
+\item{pretty}{Whether to use the function \code{\link{pretty}()} to generate
+the bins when the argument \code{bins} is a single number. When
+\code{pretty = TRUE}, the actual number of bins may not be the number of
+bins you specified. When \code{pretty = FALSE}, \code{\link{seq}()} is used
+to generate the bins and the breaks may not be "pretty".}
+
+\item{n}{Number of equal-size quantiles desired. For more precise control,
+use the \code{probs} argument instead.}
+
+\item{probs}{See \code{\link[stats]{quantile}}. If provided, the \code{n}
+argument is ignored.}
+
+\item{levels}{An alternate way of specifying levels; if specified, domain is
+ignored}
+
+\item{ordered}{If \code{TRUE} and \code{domain} needs to be coerced to a
+factor, treat it as already in the correct order}
+}
+\value{
+A function that takes a single parameter \code{x}; when called with a
+  vector of numbers (except for \code{col_factor}, which expects
+  factors/characters), #RRGGBB color strings are returned.
+}
+\description{
+Conveniently maps data values (numeric or factor/character) to colors
+according to a given palette, which can be provided in a variety of formats.
+}
+\details{
+\code{col_numeric} is a simple linear mapping from continuous numeric data
+to an interpolated palette.
+
+\code{col_bin} also maps continuous numeric data, but performs
+  binning based on value (see the \code{\link[base]{cut}} function).
+
+\code{col_quantile} similarly bins numeric data, but via the
+  \code{\link[stats]{quantile}} function.
+
+\code{col_factor} maps factors to colors. If the palette is
+  discrete and has a different number of colors than the number of factors,
+  interpolation is used.
+
+The \code{palette} argument can be any of the following:
+\enumerate{
+  \item{A character vector of RGB or named colors. Examples: \code{palette()}, 
\code{c("#000000", "#0000FF", "#FFFFFF")}, \code{topo.colors(10)}}
+  \item{The name of an RColorBrewer palette, e.g. \code{"BuPu"} or 
\code{"Greens"}.}
+  \item{A function that receives a single value between 0 and 1 and returns a 
color. Examples: \code{colorRamp(c("#000000", "#FFFFFF"), 
interpolate="spline")}.}
+}
+}
+\examples{
+pal <- col_bin("Greens", domain = 0:100)
+show_col(pal(sort(runif(10, 60, 100))))
+
+# Exponential distribution, mapped continuously
+show_col(col_numeric("Blues", domain = NULL)(sort(rexp(16))))
+# Exponential distribution, mapped by interval
+show_col(col_bin("Blues", domain = NULL, bins = 4)(sort(rexp(16))))
+# Exponential distribution, mapped by quantile
+show_col(col_quantile("Blues", domain = NULL)(sort(rexp(16))))
+
+# Categorical data; by default, the values being colored span the gamut...
+show_col(col_factor("RdYlBu", domain = NULL)(LETTERS[1:5]))
+# ...unless the data is a factor, without droplevels...
+show_col(col_factor("RdYlBu", domain = NULL)(factor(LETTERS[1:5], 
levels=LETTERS)))
+# ...or the domain is stated explicitly.
+show_col(col_factor("RdYlBu", levels = LETTERS)(LETTERS[1:5]))
+}
+
diff --git a/man/colour_ramp.Rd b/man/colour_ramp.Rd
new file mode 100644
index 0000000..40ba5cb
--- /dev/null
+++ b/man/colour_ramp.Rd
@@ -0,0 +1,40 @@
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/colour-mapping.r
+\name{colour_ramp}
+\alias{colour_ramp}
+\title{Fast color interpolation}
+\usage{
+colour_ramp(colors, na.color = NA, alpha = FALSE)
+}
+\arguments{
+\item{colors}{Colors to interpolate; must be a valid argument to
+\code{\link[grDevices]{col2rgb}}. This can be a character vector of
+\code{"#RRGGBB"} or  \code{"#RRGGBBAA"}, color names from
+\code{\link[grDevices]{colors}}, or a positive integer that indexes into
+\code{\link[grDevices]{palette}()}.}
+
+\item{na.color}{The color to map to \code{NA} values (for example,
+\code{"#606060"} for dark grey, or \code{"#00000000"} for transparent) and
+values outside of [0,1]. Can itself by \code{NA}, which will simply cause
+an \code{NA} to be inserted into the output.}
+
+\item{alpha}{Whether to include alpha channels in interpolation; otherwise,
+  any alpha information will be discarded. If \code{TRUE} then the returned
+  function will provide colors in \code{"#RRGGBBAA"} format instead of
+  \code{"#RRGGBB"}.}
+}
+\value{
+A function that takes a numeric vector and returns a character vector
+  of the same length with RGB or RGBA hex colors.
+}
+\description{
+Returns a function that maps the interval [0,1] to a set of colors.
+Interpolation is performed in the CIELAB color space. Similar to
+\code{\link[grDevices]{colorRamp}(space = 'Lab')}, but hundreds of
+times faster, and provides results in \code{"#RRGGBB"} (or
+\code{"#RRGGBBAA"}) character form instead of RGB color matrices.
+}
+\seealso{
+\link[grDevices]{colorRamp}
+}
+
diff --git a/man/comma_format.Rd b/man/comma_format.Rd
index 3b128d2..4eb1476 100644
--- a/man/comma_format.Rd
+++ b/man/comma_format.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
 \name{comma_format}
 \alias{comma}
 \alias{comma_format}
@@ -14,7 +15,7 @@ comma(x, ...)
 \item{x}{a numeric vector to format}
 }
 \value{
-a function with single paramater x, a numeric vector, that
+a function with single parameter x, a numeric vector, that
   returns a character vector
 }
 \description{
@@ -24,5 +25,11 @@ Comma formatter: format number with commas separating 
thousands.
 comma_format()(c(1, 1e3, 2000, 1e6))
 comma_format(digits = 9)(c(1, 1e3, 2000, 1e6))
 comma(c(1, 1e3, 2000, 1e6))
+
+# If you're European you can switch . and , with the more general
+# format_format
+point <- format_format(big.mark = ".", decimal.mark = ",", scientific = FALSE)
+point(c(1, 1e3, 2000, 1e6))
+point(c(1, 1.021, 1000.01))
 }
 
diff --git a/man/cscale.Rd b/man/cscale.Rd
index 2274397..5b7322b 100644
--- a/man/cscale.Rd
+++ b/man/cscale.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/scale-continuous.r
 \name{cscale}
 \alias{cscale}
 \title{Continuous scale.}
diff --git a/man/date_breaks.Rd b/man/date_breaks.Rd
index 39f6f9e..191388e 100644
--- a/man/date_breaks.Rd
+++ b/man/date_breaks.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-date.r
 \name{date_breaks}
 \alias{date_breaks}
 \title{Regularly spaced dates.}
diff --git a/man/date_format.Rd b/man/date_format.Rd
index 0180c96..5807e60 100644
--- a/man/date_format.Rd
+++ b/man/date_format.Rd
@@ -1,13 +1,17 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-date.r
 \name{date_format}
 \alias{date_format}
 \title{Formatted dates.}
 \usage{
-date_format(format = "\%Y-\%m-\%d")
+date_format(format = "\%Y-\%m-\%d", tz = "UTC")
 }
 \arguments{
 \item{format}{Date format using standard POSIX specification.  See
 \code{\link{strptime}} for possible formats.}
+
+\item{tz}{a time zone name, see \code{\link{timezones}}. Defaults
+to UTC}
 }
 \description{
 Formatted dates.
diff --git a/man/date_trans.Rd b/man/date_trans.Rd
index 0cb78eb..3f8b33f 100644
--- a/man/date_trans.Rd
+++ b/man/date_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-date.r
 \name{date_trans}
 \alias{date_trans}
 \title{Transformation for dates (class Date).}
diff --git a/man/dichromat_pal.Rd b/man/dichromat_pal.Rd
index 5464c49..0a33a85 100644
--- a/man/dichromat_pal.Rd
+++ b/man/dichromat_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-dichromat.r
 \name{dichromat_pal}
 \alias{dichromat_pal}
 \title{Dichromat (colour-blind) palette (discrete).}
diff --git a/man/discard.Rd b/man/discard.Rd
index 70c32c4..4bc1378 100644
--- a/man/discard.Rd
+++ b/man/discard.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{discard}
 \alias{discard}
 \title{Discard any values outside of range.}
diff --git a/man/div_gradient_pal.Rd b/man/div_gradient_pal.Rd
index 13e4160..d925b3f 100644
--- a/man/div_gradient_pal.Rd
+++ b/man/div_gradient_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-gradient.r
 \name{div_gradient_pal}
 \alias{div_gradient_pal}
 \title{Diverging colour gradient (continous).}
diff --git a/man/dollar_format.Rd b/man/dollar_format.Rd
index 6b51856..f0df57a 100644
--- a/man/dollar_format.Rd
+++ b/man/dollar_format.Rd
@@ -1,21 +1,31 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
 \name{dollar_format}
 \alias{dollar}
 \alias{dollar_format}
 \title{Currency formatter: round to nearest cent and display dollar sign.}
 \usage{
-dollar_format(largest_with_cents = 1e+05)
+dollar_format(prefix = "$", suffix = "", largest_with_cents = 1e+05, ...,
+  big.mark = ",", negative_parens = FALSE)
 
 dollar(x)
 }
 \arguments{
+\item{prefix,suffix}{Symbols to display before and after amount.}
+
 \item{largest_with_cents}{the value that all values of \code{x} must
 be less than in order for the cents to be displayed}
 
+\item{...}{Other arguments passed on to \code{\link{format}}.}
+
+\item{big.mark}{Character used between every 3 digits.}
+
+\item{negative_parens}{Should negative values be shown with parentheses?}
+
 \item{x}{a numeric vector to format}
 }
 \value{
-a function with single paramater x, a numeric vector, that
+a function with single parameter x, a numeric vector, that
   returns a character vector
 }
 \description{
@@ -25,10 +35,19 @@ any of the values has a non-zero cents and the largest 
value is less
 than \code{largest_with_cents} which by default is 100000.
 }
 \examples{
-dollar_format()(c(100, 0.23, 1.456565, 2e3))
+dollar_format()(c(-100, 0.23, 1.456565, 2e3))
 dollar_format()(c(1:10 * 10))
 dollar(c(100, 0.23, 1.456565, 2e3))
 dollar(c(1:10 * 10))
 dollar(10^(1:8))
+
+usd <- dollar_format(prefix = "USD ")
+usd(c(100, -100))
+
+euro <- dollar_format(prefix = "", suffix = "\\u20ac")
+euro(100)
+
+finance <- dollar_format(negative_parens = TRUE)
+finance(c(-100, 100))
 }
 
diff --git a/man/dscale.Rd b/man/dscale.Rd
index b4a9146..05d1db7 100644
--- a/man/dscale.Rd
+++ b/man/dscale.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/scale-discrete.r
 \name{dscale}
 \alias{dscale}
 \title{Discrete scale.}
diff --git a/man/exp_trans.Rd b/man/exp_trans.Rd
index a599168..c19a3de 100644
--- a/man/exp_trans.Rd
+++ b/man/exp_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{exp_trans}
 \alias{exp_trans}
 \title{Exponential transformation (inverse of log transformation).}
diff --git a/man/expand_range.Rd b/man/expand_range.Rd
index c35168b..f2d7c28 100644
--- a/man/expand_range.Rd
+++ b/man/expand_range.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{expand_range}
 \alias{expand_range}
 \title{Expand a range with a multiplicative or additive constant.}
diff --git a/man/extended_breaks.Rd b/man/extended_breaks.Rd
index cd4d864..0ffb341 100644
--- a/man/extended_breaks.Rd
+++ b/man/extended_breaks.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/breaks.r
 \name{extended_breaks}
 \alias{extended_breaks}
 \title{Extended breaks.
diff --git a/man/format_format.Rd b/man/format_format.Rd
index d62e8f7..8487b55 100644
--- a/man/format_format.Rd
+++ b/man/format_format.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
 \name{format_format}
 \alias{format_format}
 \title{Format with using any arguments to \code{\link{format}}.}
diff --git a/man/fullseq.Rd b/man/fullseq.Rd
index 51c5426..ab96aeb 100644
--- a/man/fullseq.Rd
+++ b/man/fullseq.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/full-seq.r
 \name{fullseq}
 \alias{fullseq}
 \title{Generate sequence of fixed size intervals covering range.}
diff --git a/man/gradient_n_pal.Rd b/man/gradient_n_pal.Rd
index 28e5d14..f29b3ae 100644
--- a/man/gradient_n_pal.Rd
+++ b/man/gradient_n_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-gradient.r
 \name{gradient_n_pal}
 \alias{gradient_n_pal}
 \title{Arbitrary colour gradient palette (continous).}
diff --git a/man/grey_pal.Rd b/man/grey_pal.Rd
index d67404c..515d9a9 100644
--- a/man/grey_pal.Rd
+++ b/man/grey_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-grey.r
 \name{grey_pal}
 \alias{grey_pal}
 \title{Grey scale palette (discrete).}
diff --git a/man/hue_pal.Rd b/man/hue_pal.Rd
index d068f5e..d7f71ef 100644
--- a/man/hue_pal.Rd
+++ b/man/hue_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-hue.r
 \name{hue_pal}
 \alias{hue_pal}
 \title{Hue palette (discrete).}
@@ -9,9 +10,10 @@ hue_pal(h = c(0, 360) + 15, c = 100, l = 65, h.start = 0,
 \arguments{
 \item{h}{range of hues to use, in [0, 360]}
 
-\item{l}{luminance (lightness), in [0, 100]}
+\item{c}{chroma (intensity of colour), maximum value varies depending on
+combination of hue and luminance.}
 
-\item{c}{chroma (intensity of colour), maximum value varies depending on}
+\item{l}{luminance (lightness), in [0, 100]}
 
 \item{h.start}{hue to start at}
 
diff --git a/man/identity_pal.Rd b/man/identity_pal.Rd
index f182585..4d8d7c0 100644
--- a/man/identity_pal.Rd
+++ b/man/identity_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-identity.r
 \name{identity_pal}
 \alias{identity_pal}
 \title{Identity palette.}
diff --git a/man/identity_trans.Rd b/man/identity_trans.Rd
index 512966d..d1ed748 100644
--- a/man/identity_trans.Rd
+++ b/man/identity_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{identity_trans}
 \alias{identity_trans}
 \title{Identity transformation (do nothing).}
diff --git a/man/linetype_pal.Rd b/man/linetype_pal.Rd
index 3fba6d0..1cc633a 100644
--- a/man/linetype_pal.Rd
+++ b/man/linetype_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-linetype.r
 \name{linetype_pal}
 \alias{linetype_pal}
 \title{Line type palette (discrete).}
diff --git a/man/log1p_trans.Rd b/man/log1p_trans.Rd
index 7079d76..58c0957 100644
--- a/man/log1p_trans.Rd
+++ b/man/log1p_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{log1p_trans}
 \alias{log1p_trans}
 \title{Log plus one transformation.}
@@ -8,4 +9,8 @@ log1p_trans()
 \description{
 Log plus one transformation.
 }
+\examples{
+trans_range(log_trans(), 1:10)
+trans_range(log1p_trans(), 0:9)
+}
 
diff --git a/man/log_breaks.Rd b/man/log_breaks.Rd
index 819a93e..4c80f99 100644
--- a/man/log_breaks.Rd
+++ b/man/log_breaks.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/breaks.r
 \name{log_breaks}
 \alias{log_breaks}
 \title{Log breaks (integer breaks on log-transformed scales).}
diff --git a/man/log_trans.Rd b/man/log_trans.Rd
index 57052d8..50231a0 100644
--- a/man/log_trans.Rd
+++ b/man/log_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{log_trans}
 \alias{log10_trans}
 \alias{log2_trans}
diff --git a/man/manual_pal.Rd b/man/manual_pal.Rd
index 46e1b4c..dc43650 100644
--- a/man/manual_pal.Rd
+++ b/man/manual_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-manual.r
 \name{manual_pal}
 \alias{manual_pal}
 \title{Manual palette (manual).}
diff --git a/man/math_format.Rd b/man/math_format.Rd
index bd1ab58..54a9df9 100644
--- a/man/math_format.Rd
+++ b/man/math_format.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
 \name{math_format}
 \alias{math_format}
 \title{Add arbitrary expression to a label.
@@ -14,7 +15,7 @@ transformation - this makes it easier to use floating point 
numbers in
 mathematical expressions.}
 }
 \value{
-a function with single paramater x, a numeric vector, that
+a function with single parameter x, a numeric vector, that
    returns a list of expressions
 }
 \description{
diff --git a/man/muted.Rd b/man/muted.Rd
index 64e8919..9eb3306 100644
--- a/man/muted.Rd
+++ b/man/muted.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/colour-manip.r
 \name{muted}
 \alias{muted}
 \title{Mute standard colour.}
diff --git a/man/ordinal_format.Rd b/man/ordinal_format.Rd
new file mode 100644
index 0000000..86df7db
--- /dev/null
+++ b/man/ordinal_format.Rd
@@ -0,0 +1,26 @@
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
+\name{ordinal_format}
+\alias{ordinal}
+\alias{ordinal_format}
+\title{Ordinal formatter: add ordinal suffixes (-st, -nd, -rd, -th) to 
numbers.}
+\usage{
+ordinal_format(x)
+
+ordinal(x)
+}
+\arguments{
+\item{x}{a numeric vector to format}
+}
+\value{
+a function with single paramater x, a numeric vector, that
+  returns a character vector
+}
+\description{
+Ordinal formatter: add ordinal suffixes (-st, -nd, -rd, -th) to numbers.
+}
+\examples{
+ordinal_format()(1:10)
+ordinal(1:10)
+}
+
diff --git a/man/package-scales.Rd b/man/package-scales.Rd
index 9d87e67..dee0f49 100644
--- a/man/package-scales.Rd
+++ b/man/package-scales.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/scales.r
 \docType{package}
 \name{package-scales}
 \alias{package-scales}
diff --git a/man/parse_format.Rd b/man/parse_format.Rd
index 37d2d97..86a6653 100644
--- a/man/parse_format.Rd
+++ b/man/parse_format.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
 \name{parse_format}
 \alias{parse_format}
 \title{Parse a text label to produce expressions for plotmath.}
@@ -6,7 +7,7 @@
 parse_format()
 }
 \value{
-a function with single paramater x, a character vector, that
+a function with single parameter x, a character vector, that
    returns a list of expressions
 }
 \description{
diff --git a/man/percent_format.Rd b/man/percent_format.Rd
index 24c2bf3..9ffdd85 100644
--- a/man/percent_format.Rd
+++ b/man/percent_format.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
 \name{percent_format}
 \alias{percent}
 \alias{percent_format}
@@ -12,7 +13,7 @@ percent(x)
 \item{x}{a numeric vector to format}
 }
 \value{
-a function with single paramater x, a numeric vector, that
+a function with single parameter x, a numeric vector, that
   returns a character vector
 }
 \description{
diff --git a/man/pretty_breaks.Rd b/man/pretty_breaks.Rd
index 83e6312..a904c28 100644
--- a/man/pretty_breaks.Rd
+++ b/man/pretty_breaks.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/breaks.r
 \name{pretty_breaks}
 \alias{pretty_breaks}
 \title{Pretty breaks.
diff --git a/man/probability_trans.Rd b/man/probability_trans.Rd
index 7114be8..825083b 100644
--- a/man/probability_trans.Rd
+++ b/man/probability_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{probability_trans}
 \alias{logit_trans}
 \alias{probability_trans}
diff --git a/man/reciprocal_trans.Rd b/man/reciprocal_trans.Rd
index 80a88f8..15d197a 100644
--- a/man/reciprocal_trans.Rd
+++ b/man/reciprocal_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{reciprocal_trans}
 \alias{reciprocal_trans}
 \title{Reciprocal transformation.}
diff --git a/man/rescale.Rd b/man/rescale.Rd
index 14718d2..22861b1 100644
--- a/man/rescale.Rd
+++ b/man/rescale.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{rescale}
 \alias{rescale}
 \title{Rescale numeric vector to have specified minimum and maximum.}
diff --git a/man/rescale_max.Rd b/man/rescale_max.Rd
index 5ec4131..d17f53d 100644
--- a/man/rescale_max.Rd
+++ b/man/rescale_max.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{rescale_max}
 \alias{rescale_max}
 \title{Rescale numeric vector to have specified maximum.}
diff --git a/man/rescale_mid.Rd b/man/rescale_mid.Rd
index 56e6fd9..d0772a9 100644
--- a/man/rescale_mid.Rd
+++ b/man/rescale_mid.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{rescale_mid}
 \alias{rescale_mid}
 \title{Rescale numeric vector to have specified minimum, midpoint, and 
maximum.}
diff --git a/man/rescale_none.Rd b/man/rescale_none.Rd
index 2e3972b..44b482b 100644
--- a/man/rescale_none.Rd
+++ b/man/rescale_none.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{rescale_none}
 \alias{rescale_none}
 \title{Don't peform rescaling}
diff --git a/man/rescale_pal.Rd b/man/rescale_pal.Rd
index f6691b2..16c2a4f 100644
--- a/man/rescale_pal.Rd
+++ b/man/rescale_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-rescale.r
 \name{rescale_pal}
 \alias{rescale_pal}
 \title{Rescale palette (continuous).}
diff --git a/man/reverse_trans.Rd b/man/reverse_trans.Rd
index 6c4dbfa..fb05742 100644
--- a/man/reverse_trans.Rd
+++ b/man/reverse_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{reverse_trans}
 \alias{reverse_trans}
 \title{Reverse transformation.}
diff --git a/man/scientific_format.Rd b/man/scientific_format.Rd
index f20da18..fe96bac 100644
--- a/man/scientific_format.Rd
+++ b/man/scientific_format.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
 \name{scientific_format}
 \alias{scientific}
 \alias{scientific_format}
@@ -16,7 +17,7 @@ scientific(x, digits = 3, ...)
 \item{x}{a numeric vector to format}
 }
 \value{
-a function with single paramater x, a numeric vector, that
+a function with single parameter x, a numeric vector, that
   returns a character vector
 }
 \description{
diff --git a/man/seq_gradient_pal.Rd b/man/seq_gradient_pal.Rd
index 7fd45d9..f105526 100644
--- a/man/seq_gradient_pal.Rd
+++ b/man/seq_gradient_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-gradient.r
 \name{seq_gradient_pal}
 \alias{seq_gradient_pal}
 \title{Sequential colour gradient palette (continous).}
diff --git a/man/shape_pal.Rd b/man/shape_pal.Rd
index c1d275f..965aa39 100644
--- a/man/shape_pal.Rd
+++ b/man/shape_pal.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/pal-shape.r
 \name{shape_pal}
 \alias{shape_pal}
 \title{Shape palette (discrete).}
diff --git a/man/show_col.Rd b/man/show_col.Rd
index 2604bd6..88ee713 100644
--- a/man/show_col.Rd
+++ b/man/show_col.Rd
@@ -1,12 +1,17 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/colour-manip.r
 \name{show_col}
 \alias{show_col}
 \title{Show colours.}
 \usage{
-show_col(colours)
+show_col(colours, labels = TRUE, borders = NULL)
 }
 \arguments{
 \item{colours}{a character vector of colours}
+
+\item{labels}{boolean, whether to show the hexadecimal representation of the 
colours in each tile}
+
+\item{borders}{colour of the borders of the tiles; matches the \code{border} 
argument of \code{\link[graphics]{rect}}. The default means \code{par("fg")}. 
Use \code{border = NA} to omit borders.}
 }
 \description{
 A quick and dirty way to show colours in a plot.
diff --git a/man/sqrt_trans.Rd b/man/sqrt_trans.Rd
index 9e45fa4..6103908 100644
--- a/man/sqrt_trans.Rd
+++ b/man/sqrt_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-numeric.r
 \name{sqrt_trans}
 \alias{sqrt_trans}
 \title{Square-root transformation.}
diff --git a/man/squish.Rd b/man/squish.Rd
index a48266b..7043951 100644
--- a/man/squish.Rd
+++ b/man/squish.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{squish}
 \alias{squish}
 \title{Squish values into range.}
diff --git a/man/squish_infinite.Rd b/man/squish_infinite.Rd
index 811ca63..60a3c20 100644
--- a/man/squish_infinite.Rd
+++ b/man/squish_infinite.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{squish_infinite}
 \alias{squish_infinite}
 \title{Squish infinite values to range.}
diff --git a/man/time_trans.Rd b/man/time_trans.Rd
index b906a83..04ad475 100644
--- a/man/time_trans.Rd
+++ b/man/time_trans.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans-date.r
 \name{time_trans}
 \alias{time_trans}
 \title{Transformation for times (class POSIXt).}
diff --git a/man/trans_breaks.Rd b/man/trans_breaks.Rd
index bd228a5..5afb75d 100644
--- a/man/trans_breaks.Rd
+++ b/man/trans_breaks.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/breaks.r
 \name{trans_breaks}
 \alias{trans_breaks}
 \title{Pretty breaks on transformed scale.}
diff --git a/man/trans_format.Rd b/man/trans_format.Rd
index fc15849..28207c9 100644
--- a/man/trans_format.Rd
+++ b/man/trans_format.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
 \name{trans_format}
 \alias{trans_format}
 \title{Format labels after transformation.}
@@ -11,7 +12,7 @@ trans_format(trans, format = scientific_format())
 \item{format}{additional formatter to apply after transformation}
 }
 \value{
-a function with single paramater x, a numeric vector, that
+a function with single parameter x, a numeric vector, that
    returns a character vector of list of expressions
 }
 \description{
diff --git a/man/trans_new.Rd b/man/trans_new.Rd
index 219cd68..7ea4baf 100644
--- a/man/trans_new.Rd
+++ b/man/trans_new.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans.r
 \name{trans_new}
 \alias{is.trans}
 \alias{trans}
diff --git a/man/trans_range.Rd b/man/trans_range.Rd
index f8c8df0..ab8edba 100644
--- a/man/trans_range.Rd
+++ b/man/trans_range.Rd
@@ -1,4 +1,5 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/trans.r
 \name{trans_range}
 \alias{trans_range}
 \title{Compute range of transformed values.}
diff --git a/man/unit_format.Rd b/man/unit_format.Rd
new file mode 100644
index 0000000..bf927da
--- /dev/null
+++ b/man/unit_format.Rd
@@ -0,0 +1,33 @@
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
+\name{unit_format}
+\alias{unit_format}
+\title{Add units to the labels}
+\usage{
+unit_format(unit = "m", scale = 1, sep = " ", ...)
+}
+\arguments{
+\item{unit}{The units to append}
+
+\item{scale}{A scaling factor. Useful if the underlying data is on another 
scale}
+
+\item{sep}{The separator between the number and the label}
+
+\item{...}{Arguments passed on to \code{\link{format}}}
+}
+\description{
+Add units to the labels
+}
+\examples{
+# labels in kilometer when the raw data are in meter
+km <- unit_format(unit = "km", scale = 1e-3, digits = 2)
+km(runif(10) * 1e3)
+
+# labels in hectares, raw data in square meters
+ha <- unit_format(unit = "ha", scale = 1e-4)
+km(runif(10) * 1e5)
+}
+\seealso{
+\code{\link{comma}}
+}
+
diff --git a/man/wrap_format.Rd b/man/wrap_format.Rd
new file mode 100644
index 0000000..1ced77a
--- /dev/null
+++ b/man/wrap_format.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/formatter.r
+\name{wrap_format}
+\alias{wrap_format}
+\title{Wrap text to a specified width, adding newlines for spaces if text 
exceeds
+the width}
+\usage{
+wrap_format(width)
+}
+\arguments{
+\item{width}{value above which to wrap}
+}
+\value{
+Function with single parameter x, a character vector, that
+   returns a wrapped character vector
+}
+\description{
+Wrap text to a specified width, adding newlines for spaces if text exceeds
+the width
+}
+\examples{
+wrap_10 <- wrap_format(10)
+wrap_10('A long line that needs to be wrapped')
+}
+
diff --git a/man/zero_range.Rd b/man/zero_range.Rd
index 4dafbd2..5b6805e 100644
--- a/man/zero_range.Rd
+++ b/man/zero_range.Rd
@@ -1,15 +1,15 @@
-% Generated by roxygen2 (4.0.0): do not edit by hand
+% Generated by roxygen2 (4.1.1): do not edit by hand
+% Please edit documentation in R/bounds.r
 \name{zero_range}
 \alias{zero_range}
 \title{Determine if range of vector is close to zero, with a specified 
tolerance}
 \usage{
-zero_range(x, tol = .Machine$double.eps * 100)
+zero_range(x, tol = 1000 * .Machine$double.eps)
 }
 \arguments{
 \item{x}{numeric range: vector of length 2}
 
-\item{tol}{A value specifying the tolerance. Defaults to
-\code{.Machine$double.eps * 100}.}
+\item{tol}{A value specifying the tolerance.}
 }
 \value{
 logical \code{TRUE} if the relative difference of the endpoints of
@@ -18,7 +18,7 @@ the range are not distinguishable from 0.
 \description{
 The machine epsilon is the difference between 1.0 and the next number
 that can be represented by the machine. By default, this function
-uses epsilon * 100 as the tolerance. First it scales the values so that
+uses epsilon * 1000 as the tolerance. First it scales the values so that
 they have a mean of 1, and then it checks if the difference between
 them is larger than the tolerance.
 }
@@ -26,15 +26,15 @@ them is larger than the tolerance.
 eps <- .Machine$double.eps
 zero_range(c(1, 1 + eps))       # TRUE
 zero_range(c(1, 1 + 99 * eps))  # TRUE
-zero_range(c(1, 1 + 101 * eps)) # FALSE - Crossed the tol threshold
+zero_range(c(1, 1 + 1001 * eps)) # FALSE - Crossed the tol threshold
 zero_range(c(1, 1 + 2 * eps), tol = eps) # FALSE - Changed tol
 
 # Scaling up or down all the values has no effect since the values
 # are rescaled to 1 before checking against tol
 zero_range(100000 * c(1, 1 + eps))        # TRUE
-zero_range(100000 * c(1, 1 + 200 * eps))  # FALSE
+zero_range(100000 * c(1, 1 + 1001 * eps))  # FALSE
 zero_range(.00001 * c(1, 1 + eps))        # TRUE
-zero_range(.00001 * c(1, 1 + 200 * eps))  # FALSE
+zero_range(.00001 * c(1, 1 + 1001 * eps))  # FALSE
 
 # NA values
 zero_range(c(1, NA))   # NA
diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp
new file mode 100644
index 0000000..232f6c0
--- /dev/null
+++ b/src/RcppExports.cpp
@@ -0,0 +1,43 @@
+// This file was generated by Rcpp::compileAttributes
+// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
+
+#include <Rcpp.h>
+
+using namespace Rcpp;
+
+// doColorRamp
+StringVector doColorRamp(NumericMatrix colors, NumericVector x, bool alpha, 
std::string naColor);
+RcppExport SEXP scales_doColorRamp(SEXP colorsSEXP, SEXP xSEXP, SEXP 
alphaSEXP, SEXP naColorSEXP) {
+BEGIN_RCPP
+    Rcpp::RObject __result;
+    Rcpp::RNGScope __rngScope;
+    Rcpp::traits::input_parameter< NumericMatrix >::type colors(colorsSEXP);
+    Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP);
+    Rcpp::traits::input_parameter< bool >::type alpha(alphaSEXP);
+    Rcpp::traits::input_parameter< std::string >::type naColor(naColorSEXP);
+    __result = Rcpp::wrap(doColorRamp(colors, x, alpha, naColor));
+    return __result;
+END_RCPP
+}
+// rgbToLab
+NumericVector rgbToLab(NumericVector rgb);
+RcppExport SEXP scales_rgbToLab(SEXP rgbSEXP) {
+BEGIN_RCPP
+    Rcpp::RObject __result;
+    Rcpp::RNGScope __rngScope;
+    Rcpp::traits::input_parameter< NumericVector >::type rgb(rgbSEXP);
+    __result = Rcpp::wrap(rgbToLab(rgb));
+    return __result;
+END_RCPP
+}
+// rgbToXyz
+NumericVector rgbToXyz(NumericVector rgb);
+RcppExport SEXP scales_rgbToXyz(SEXP rgbSEXP) {
+BEGIN_RCPP
+    Rcpp::RObject __result;
+    Rcpp::RNGScope __rngScope;
+    Rcpp::traits::input_parameter< NumericVector >::type rgb(rgbSEXP);
+    __result = Rcpp::wrap(rgbToXyz(rgb));
+    return __result;
+END_RCPP
+}
diff --git a/src/colors.cpp b/src/colors.cpp
new file mode 100644
index 0000000..6a7c1df
--- /dev/null
+++ b/src/colors.cpp
@@ -0,0 +1,242 @@
+#include <Rcpp.h>
+
+#include <iomanip>
+#include <sstream>
+#include <iostream>
+
+using namespace Rcpp;
+
+// Convert an integer (0-255) to two ASCII hex digits, starting at buf
+void intToHex(unsigned int x, char* buf) {
+  const char* hexchars = "0123456789ABCDEF";
+  buf[0] = hexchars[(x >> 4) & 0xF];
+  buf[1] = hexchars[x & 0xF];
+}
+
+// Convert the rgb values to #RRGGBB hex string
+std::string rgbcolor(double r, double g, double b) {
+  char color[8];
+  color[0] = '#';
+  intToHex(static_cast<unsigned int>(r), color + 1);
+  intToHex(static_cast<unsigned int>(g), color + 3);
+  intToHex(static_cast<unsigned int>(b), color + 5);
+  color[7] = 0;
+  return std::string(color);
+}
+
+// Convert the rgba values to #RRGGBB hex string
+std::string rgbacolor(double r, double g, double b, double a) {
+  char color[10];
+  color[0] = '#';
+  intToHex(static_cast<unsigned int>(r), color + 1);
+  intToHex(static_cast<unsigned int>(g), color + 3);
+  intToHex(static_cast<unsigned int>(b), color + 5);
+  intToHex(static_cast<unsigned int>(a), color + 7);
+  color[9] = 0;
+  return std::string(color);
+}
+
+
+// === BEGIN SRGB/LAB CONVERSION =======================================
+
+double linear2srgb(double c) {
+  double a = 0.055;
+  if (c <= 0.0031308) {
+    return 12.92 * c;
+  } else {
+    return (1 + a) * ::pow(c, 1.0/2.4) - a;
+  }
+}
+
+double srgb2linear(double c) {
+  double a = 0.055;
+  if (c <= 0.04045) {
+    return c / 12.92;
+  } else {
+    return ::pow((c + a) / (1 + a), 2.4);
+  }
+}
+
+double d65_x = 0.95320571254937703;
+double d65_y = 1.0;
+double d65_z = 1.08538438164691575;
+
+double srgb_xyz[][3] = {
+  {0.416821341885317054, 0.35657671707797467, 0.179807653586085414},
+  {0.214923504409616606, 0.71315343415594934, 0.071923061434434166},
+  {0.019538500400874251, 0.11885890569265833, 0.946986975553383292}
+};
+
+void srgb2xyz(double r, double g, double b, double* x, double *y, double* z) {
+  r = srgb2linear(r);
+  g = srgb2linear(g);
+  b = srgb2linear(b);
+  *x = srgb_xyz[0][0] * r + srgb_xyz[0][1] * g + srgb_xyz[0][2] * b;
+  *y = srgb_xyz[1][0] * r + srgb_xyz[1][1] * g + srgb_xyz[1][2] * b;
+  *z = srgb_xyz[2][0] * r + srgb_xyz[2][1] * g + srgb_xyz[2][2] * b;
+}
+
+double xyz_srgb[][3] = {
+  { 3.206520517144463067, -1.52104178377365540, -0.493310848791455814},
+  {-0.971982546201231923,  1.88126865160848711,  0.041672484599589298},
+  { 0.055838338593097898, -0.20474057484135894,  1.060928433268858884}
+};
+
+void xyz2srgb(double x, double y, double z, double *r, double *g, double *b) {
+  *r = xyz_srgb[0][0] * x + xyz_srgb[0][1] * y + xyz_srgb[0][2] * z;
+  *g = xyz_srgb[1][0] * x + xyz_srgb[1][1] * y + xyz_srgb[1][2] * z;
+  *b = xyz_srgb[2][0] * x + xyz_srgb[2][1] * y + xyz_srgb[2][2] * z;
+  *r = linear2srgb(*r);
+  *g = linear2srgb(*g);
+  *b = linear2srgb(*b);
+}
+
+double labf(double t) {
+  if (t > ::pow(6.0 / 29.0, 3.0)) {
+    return ::pow(t, 1.0 / 3.0);
+  } else {
+    return 1.0/3.0 * ::pow(29.0 / 6.0, 2.0) * t + (4.0 / 29.0);
+  }
+}
+
+void xyz2lab(double x, double y, double z, double *l, double *a, double *b) {
+  x = x / d65_x;
+  y = y / d65_y;
+  z = z / d65_z;
+  *l = 116.0 * labf(y) - 16.0;
+  *a = 500.0 * (labf(x) - labf(y));
+  *b = 200.0 * (labf(y) - labf(z));
+}
+
+double labf_inv(double t) {
+  if (t > 6.0 / 29.0) {
+    return ::pow(t, 3.0);
+  } else {
+    return 3 * ::pow(6.0/29.0, 2) * (t - 4.0 / 29.0);
+  }
+}
+
+void lab2xyz(double l, double a, double b, double *x, double *y, double *z) {
+  *y = d65_y * labf_inv(1.0 / 116.0 * (l + 16.0));
+  *x = d65_x * labf_inv(1.0 / 116.0 * (l + 16.0) + 1.0 / 500.0 * a);
+  *z = d65_z * labf_inv(1.0 / 116.0 * (l + 16.0) - 1.0 / 200.0 * b);
+}
+
+void srgb2lab(double red, double green, double blue, double *l, double *a, 
double *b) {
+  double x, y, z;
+  srgb2xyz(red, green, blue, &x, &y, &z);
+  xyz2lab(x, y, z, l, a, b);
+}
+void lab2srgb(double l, double a, double b, double *red, double *green, double 
*blue) {
+  double x, y, z;
+  lab2xyz(l, a, b, &x, &y, &z);
+  xyz2srgb(x, y, z, red, green, blue);
+}
+
+// === END SRGB/LAB CONVERSION =======================================
+
+
+StringVector doColorRampSerial(NumericMatrix colors, NumericVector x, bool 
alpha, std::string naColor) {
+
+  size_t ncolors = colors.ncol();
+
+  StringVector result(x.length());
+  for (R_len_t i = 0; i < x.length(); i++) {
+    double xval = x[i];
+    if (xval < 0 || xval > 1 || R_IsNA(xval)) {
+      // Illegal or NA value for this x value.
+      result[i] = NA_STRING;
+    } else {
+      // Scale the [0,1] value to [0,n-1]
+      xval *= ncolors - 1;
+      // Find the closest color that's *lower* than xval. This'll be one of the
+      // colors we use to interpolate; the other will be colorOffset+1.
+      size_t colorOffset = static_cast<size_t>(::floor(xval));
+      double l, a, b;
+      double opacity = 0;
+      if (colorOffset == ncolors - 1) {
+        // xvalue is exactly at the top of the range. Just use the top color.
+        l = colors(0, colorOffset);
+        a = colors(1, colorOffset);
+        b = colors(2, colorOffset);
+        if (alpha) {
+          opacity = colors(3, colorOffset);
+        }
+      } else {
+        // Do a linear interp between the two closest colors.
+        double factorB = xval - colorOffset;
+        double factorA = 1 - factorB;
+        l = factorA * colors(0, colorOffset) + factorB * colors(0, colorOffset 
+ 1);
+        a = factorA * colors(1, colorOffset) + factorB * colors(1, colorOffset 
+ 1);
+        b = factorA * colors(2, colorOffset) + factorB * colors(2, colorOffset 
+ 1);
+        if (alpha) {
+          opacity = ::round(factorA * colors(3, colorOffset) + factorB * 
colors(3, colorOffset + 1));
+        }
+      }
+
+      double red, green, blue;
+      lab2srgb(l, a, b, &red, &green, &blue);
+      red   = std::max(0.0, std::min(255.0, ::round(red * 255)));
+      green = std::max(0.0, std::min(255.0, ::round(green * 255)));
+      blue  = std::max(0.0, std::min(255.0, ::round(blue * 255)));
+
+      // Convert the result to hex string
+      if (!alpha)
+        result[i] = rgbcolor(red, green, blue);
+      else
+        result[i] = rgbacolor(red, green, blue, opacity);
+    }
+  }
+  return result;
+}
+
+// [[Rcpp::export]]
+StringVector doColorRamp(NumericMatrix colors, NumericVector x, bool alpha, 
std::string naColor) {
+  for (int col = 0; col < colors.cols(); col++) {
+    double red = colors(0, col) / 255;
+    double green = colors(1, col) / 255;
+    double blue = colors(2, col) / 255;
+    double l, a, b;
+    srgb2lab(red, green, blue, &l, &a, &b);
+    colors(0, col) = l;
+    colors(1, col) = a;
+    colors(2, col) = b;
+  }
+  return doColorRampSerial(colors, x, alpha, naColor);
+}
+
+// For unit testing
+// [[Rcpp::export]]
+NumericVector rgbToLab(NumericVector rgb) {
+  double l, a, b;
+  srgb2lab(rgb[0], rgb[1], rgb[2], &l, &a, &b);
+  NumericVector result(3);
+  result[0] = l;
+  result[1] = a;
+  result[2] = b;
+  return result;
+}
+
+// For unit testing
+// [[Rcpp::export]]
+NumericVector rgbToXyz(NumericVector rgb) {
+  double x, y, z;
+  srgb2xyz(rgb[0], rgb[1], rgb[2], &x, &y, &z);
+  NumericVector result(3);
+  result[0] = x;
+  result[1] = y;
+  result[2] = z;
+  return result;
+}
+
+/*** R
+x <- runif(10000)
+colors <- c('black', 'white')
+c0 <- function(x) {
+  rgb(colorRamp(colors, space = 'Lab')(x) / 255)
+}
+c1 <- colour_ramp(colors)
+
+which(c0(x) != c1(x))
+*/
+
diff --git a/tests/testthat/test-colors.r b/tests/testthat/test-colors.r
new file mode 100644
index 0000000..fba84c5
--- /dev/null
+++ b/tests/testthat/test-colors.r
@@ -0,0 +1,60 @@
+context("Colors")
+
+bw <- c("black", "white")
+
+test_that("Edgy col_bin scenarios", {
+  # Do these cases make sense?
+  expect_equal(col_bin(bw, NULL)(1), "#777777")
+  expect_equal(col_bin(bw, 1)(1), "#FFFFFF")
+})
+
+test_that("Outside of domain returns na.color", {
+  suppressWarnings({
+    expect_identical("#808080", col_factor(bw, letters)("foo"))
+    expect_identical("#808080", col_quantile(bw, 0:1)(-1))
+    expect_identical("#808080", col_quantile(bw, 0:1)(2))
+    expect_identical("#808080", col_numeric(bw, c(0, 1))(-1))
+    expect_identical("#808080", col_numeric(bw, c(0, 1))(2))
+    expect_true(is.na(col_factor(bw, letters, na.color = NA)("foo")))
+    expect_true(is.na(col_quantile(bw, 0:1, na.color = NA)(-1)))
+    expect_true(is.na(col_quantile(bw, 0:1, na.color = NA)(2)))
+    expect_true(is.na(col_numeric(bw, c(0, 1), na.color = NA)(-1)))
+    expect_true(is.na(col_numeric(bw, c(0, 1), na.color = NA)(2)))
+  })
+  expect_warning(col_factor(bw, letters, na.color = NA)("foo"))
+  expect_warning(col_quantile(bw, 0:1, na.color = NA)(-1))
+  expect_warning(col_quantile(bw, 0:1, na.color = NA)(2))
+  expect_warning(col_numeric(bw, c(0, 1), na.color = NA)(-1))
+  expect_warning(col_numeric(bw, c(0, 1), na.color = NA)(2))
+})
+
+test_that("Basic color accuracy", {
+  expect_identical(c("#000000", "#7F7F7F", "#FFFFFF"), 
col_numeric(colorRamp(bw), NULL)(c(0, 0.5, 1)))
+
+  expect_identical(c("#000000", "#FFFFFF"), col_bin(bw, NULL)(c(1,2)))
+  expect_identical(c("#000000", "#FFFFFF"), col_bin(bw, c(1,2))(c(1,2)))
+  expect_identical(c("#000000", "#FFFFFF"), col_bin(bw, c(1,2), 2)(c(1,2)))
+  expect_identical(c("#000000", "#FFFFFF"), col_bin(bw, NULL, 
bins=c(1,1.5,2))(c(1,2)))
+  expect_identical(c("#000000", "#FFFFFF"), col_bin(bw, c(1,2), 
bins=c(1,1.5,2))(c(1,2)))
+
+  expect_identical(c("#000000", "#777777", "#FFFFFF"), col_numeric(bw, 
NULL)(1:3))
+  expect_identical(c("#000000", "#777777", "#FFFFFF"), col_numeric(bw, 
c(1:3))(1:3))
+  expect_identical(rev(c("#000000", "#777777", "#FFFFFF")), 
col_numeric(rev(bw), c(1:3))(1:3))
+
+  # domain != unique(x)
+  expect_identical(c("#000000", "#0E0E0E", "#181818"), col_factor(bw, 
LETTERS)(LETTERS[1:3]))
+
+  # domain == unique(x)
+  expect_identical(c("#000000", "#777777", "#FFFFFF"), col_factor(bw, 
LETTERS[1:3])(LETTERS[1:3]))
+
+  # no domain
+  expect_identical(c("#000000", "#777777", "#FFFFFF"), col_factor(bw, 
NULL)(LETTERS[1:3]))
+
+  # Non-factor domains are sorted unless instructed otherwise
+  expect_identical(c("#000000", "#777777", "#FFFFFF"), col_factor(bw, 
rev(LETTERS[1:3]))(LETTERS[1:3]))
+  expect_identical(rev(c("#000000", "#777777", "#FFFFFF")), col_factor(bw, 
rev(LETTERS[1:3]), ordered = TRUE)(LETTERS[1:3]))
+})
+
+test_that("CIELab overflow", {
+  expect_identical(c("#FFFFFF", "#CFB1FF", "#9165FF", "#0000FF"), 
scales::colour_ramp(c("white", "blue"))(0:3/3))
+})
diff --git a/tests/testthat/test-formatter.r b/tests/testthat/test-formatter.r
index d5b354a..9f3cd85 100644
--- a/tests/testthat/test-formatter.r
+++ b/tests/testthat/test-formatter.r
@@ -16,43 +16,29 @@ test_that("scientific format shows specific sig figs", {
   expect_equal(scientific(0.123456, digits = 3), "1.23e-01")
 })
 
-test_that("dollar format", {
-  expect_equal(dollar(c(100, 0.23, 1.456565, 2e3)),
-               c("$100.00", "$0.23", "$1.46", "$2,000.00"))
-  expect_equal(dollar(c(1:10 * 10)),
-               c("$10", "$20", "$30", "$40", "$50", "$60", "$70",
-                 "$80", "$90", "$100"))
-  expect_equal(dollar((1:10 * 10) + 0.01),
-               c("$10.01", "$20.01", "$30.01", "$40.01", "$50.01", "$60.01",
-                 "$70.01", "$80.01", "$90.01", "$100.01"))
-  expect_equal(dollar((1:10 * 10) + 0.001),
-               c("$10", "$20", "$30", "$40", "$50", "$60", "$70",
-                 "$80", "$90", "$100"))
-  expect_equal(dollar(10^(1:8)),
-               c("$10", "$100", "$1,000", "$10,000", "$100,000",
-                 "$1,000,000", "$10,000,000", "$100,000,000"))
-  expect_equal(dollar(seq(10111.11, 100000, 10111.11)),
-               c("$10,111.11", "$20,222.22", "$30,333.33", "$40,444.44",
-                 "$50,555.55", "$60,666.66", "$70,777.77", "$80,888.88",
-                 "$90,999.99"))
-  expect_equal(dollar(seq(101111.11, 1000000, 101111.11)),
-               c("$101,111", "$202,222", "$303,333", "$404,444", "$505,556",
-                 "$606,667", "$707,778", "$808,889", "$910,000"))
-  expect_equal(dollar(seq(101111, 1000000, 101111)),
-               c("$101,111", "$202,222", "$303,333", "$404,444", "$505,555",
-                 "$606,666", "$707,777", "$808,888", "$909,999"))
-  expect_equal(dollar(seq(10111111.11, 100000000, 10111111.11)),
-               c("$10,111,111", "$20,222,222", "$30,333,333", "$40,444,444",
-                 "$50,555,556", "$60,666,667", "$70,777,778", "$80,888,889",
-                 "$91,000,000"))
-  expect_equal(dollar((1:10) * 100000),
-               c("$100,000", "$200,000", "$300,000", "$400,000", "$500,000",
-                 "$600,000", "$700,000", "$800,000", "$900,000", "$1,000,000"))
-  expect_equal(dollar(((1:10) * 100000) + 0.01),
-               c("$100,000", "$200,000", "$300,000", "$400,000", "$500,000",
-                 "$600,000", "$700,000", "$800,000", "$900,000", "$1,000,000"))
-  expect_equal(dollar(c(9.999)), c("$10"))
-  expect_equal(dollar(c(99.999)), c("$100"))
+test_that("wrap correctly wraps long lines", {
+  expect_equal(wrap_format(10)("this is a long line"),
+               "this is a\nlong line")
+  expect_equal(wrap_format(10)(c("this is a long line", "this is another long 
line")),
+               c("this is a\nlong line", "this is\nanother\nlong line"))
+  expect_equal(wrap_format(10)("a_very_long_word_without_spaces"),
+               "a_very_long_word_without_spaces")
+  expect_equal(wrap_format(10)("short line"), "short\nline")
+  expect_equal(wrap_format(15)("short line"), "short line")
+})
+
+test_that("ordinal format", {
+  expect_equal(ordinal(1),  "1st")
+  expect_equal(ordinal(2),  "2nd")
+  expect_equal(ordinal(3),  "3rd")
+  expect_equal(ordinal(4),  "4th")
+  expect_equal(ordinal(11), "11th")
+  expect_equal(ordinal(12), "12th")
+  expect_equal(ordinal(21), "21st")
+})
+
+test_that("ordinal format maintains order", {
+  expect_equal(ordinal(c(21, 1, 11)), c("21st", "1st", "11th"))
 })
 
 test_that("formatters don't add extra spaces", {
@@ -63,5 +49,54 @@ test_that("formatters don't add extra spaces", {
   expect_false(has_space(dollar(x)))
   expect_false(has_space(percent(x)))
   expect_false(has_space(percent(x)))
-  expect_false(has_space(scientific(x)))  
+  expect_false(has_space(scientific(x)))
+})
+
+test_that("formats work with 0 length input", {
+  x <- numeric()
+  expected <- character()
+  expect_identical(comma(x), expected)
+  expect_identical(dollar(x), expected)
+  expect_identical(percent(x), expected)
+  expect_identical(scientific(x), expected)
+  expect_identical(comma_format()(x), expected)
+  expect_identical(date_format()(as.Date(character(0))), expected)
+  expect_identical(dollar_format()(x), expected)
+  expect_identical(math_format()(x), list())
+  expect_identical(parse_format()(x), list())
+  expect_identical(percent_format()(x), expected)
+  expect_identical(scientific_format()(x), expected)
+  expect_identical(trans_format(identity)(x), expected)
+})
+
+test_that("unit format", {
+  expect_equal(
+    unit_format(unit = "km", scale = 1e-3)(c(1e3, 2e3)),
+    c("1 km", "2 km")
+  )
+  expect_equal(
+    unit_format(unit = "ha", scale = 1e-4)(c(1e3, 2e3)),
+    c("0.1 ha", "0.2 ha")
+  )
+  expect_equal(
+    unit_format()(c(1e3, 2e3)),
+    c("1,000 m", "2,000 m")
+  )
+})
+
+
+# Percent formatter -------------------------------------------------------
+
+test_that("negative percents work", {
+  expect_equal(percent(-0.6), "-60%")
+})
+
+# Dollar formatter --------------------------------------------------------
+
+test_that("negative comes before prefix", {
+  expect_equal(dollar(-1), "$-1")
+})
+
+test_that("missing values preserved", {
+  expect_equal(dollar(NA_real_), "$NA")
 })
diff --git a/tests/testthat/test-zero-range.r b/tests/testthat/test-zero-range.r
index b6fe325..63a3842 100644
--- a/tests/testthat/test-zero-range.r
+++ b/tests/testthat/test-zero-range.r
@@ -2,8 +2,7 @@ context("Zero range")
 
 test_that("large numbers with small differences", {
   expect_false(zero_range(c(1330020857.8787, 1330020866.8787)))
-  expect_true(zero_range(c(1330020857.8787, 1330020857.8787)))
-  expect_true(zero_range(c(1330020857.8787, 1330020857.8787*(1+1e-20))))
+  expect_true( zero_range(c(1330020857.8787, 1330020857.8787)))
 })
 
 test_that("small numbers with differences on order of values", {
@@ -49,14 +48,14 @@ test_that("NA and Inf", {
 })
 
 test_that("Tolerance", {
-  # By default, tolerance is 100 times this
+  # By default, tolerance is 1000 times this
   eps <- .Machine$double.eps
 
   expect_true(zero_range(c(1, 1 + eps)))
   expect_true(zero_range(c(1, 1 + 99 * eps)))
 
   # Cross the threshold
-  expect_false(zero_range(c(1, 1 + 101 * eps)))
+  expect_false(zero_range(c(1, 1 + 1001 * eps)))
   expect_false(zero_range(c(1, 1 + 2   * eps), tol = eps))
 
   # Scaling up or down all the values has no effect since the values
@@ -65,6 +64,6 @@ test_that("Tolerance", {
   expect_true(zero_range(.00001 * c(1, 1 + eps)))
   expect_true(zero_range(100000 * c(1, 1 + 99 * eps)))
   expect_true(zero_range(.00001 * c(1, 1 + 99 * eps)))
-  expect_false(zero_range(100000 * c(1, 1 + 200 * eps)))
-  expect_false(zero_range(.00001 * c(1, 1 + 200 * eps)))
+  expect_false(zero_range(100000 * c(1, 1 + 1001 * eps)))
+  expect_false(zero_range(.00001 * c(1, 1 + 1001 * eps)))
 })

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/debian-med/r-cran-scales.git

_______________________________________________
debian-med-commit mailing list
debian-med-commit@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit

Reply via email to