[med-svn] [r-cran-tikzdevice] 04/09: New upstream version 0.10-1
Andreas Tille
tille at debian.org
Wed Nov 29 20:36:17 UTC 2017
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository r-cran-tikzdevice.
commit 639e7512a5117aaa9613c3ad47f1b940123f5782
Author: Andreas Tille <tille at debian.org>
Date: Wed Nov 29 21:31:08 2017 +0100
New upstream version 0.10-1
---
DESCRIPTION | 39 +
MD5 | 90 +
NAMESPACE | 53 +
NEWS.md | 502 +++++
R/cacheMetrics.R | 111 +
R/deviceUtils.R | 384 ++++
R/latexStrWidth.R | 486 ++++
R/sanitizeTexString.R | 85 +
R/tikz.R | 303 +++
R/tikzAnnotate.R | 415 ++++
R/tikzDevice-package.R | 132 ++
R/tikzInternal.R | 29 +
R/zzz.R | 96 +
build/vignette.rds | Bin 0 -> 214 bytes
debian/README.test | 10 -
debian/changelog | 16 -
debian/compat | 1 -
debian/control | 31 -
debian/copyright | 30 -
debian/docs | 3 -
debian/rules | 18 -
debian/source/format | 1 -
debian/tests/control | 3 -
debian/tests/run-unit-test | 12 -
debian/watch | 2 -
inst/doc/tikzDevice.R | 279 +++
inst/doc/tikzDevice.Rnw | 2129 ++++++++++++++++++
inst/doc/tikzDevice.pdf | Bin 0 -> 495284 bytes
man/anyMultibyteUTF8Characters.Rd | 48 +
man/getLatexStrWidth.Rd | 87 +
man/gridToDevice.Rd | 42 +
man/sanitizeTexString.Rd | 82 +
man/setTikzDefaults.Rd | 50 +
man/tikz.Rd | 258 +++
man/tikzAnnotate.Rd | 186 ++
man/tikzCompilerInfo.Rd | 28 +
man/tikzDevice-package.Rd | 137 ++
src/tikzDevice.c | 2363 ++++++++++++++++++++
src/tikzDevice.h | 224 ++
tests/testthat/Rplots.tex | 0
tests/testthat/Rplots_colors.tex | 2 +
tests/testthat/helper_bootstrap.R | 77 +
tests/testthat/helper_expectations.R | 18 +
tests/testthat/helper_graphics.R | 155 ++
tests/testthat/helper_reporters.R | 246 ++
.../standard_graphs/annotation_noflush.pdf | Bin 0 -> 1123 bytes
tests/testthat/standard_graphs/base_annotation.pdf | Bin 0 -> 17393 bytes
tests/testthat/standard_graphs/base_raster.pdf | Bin 0 -> 13759 bytes
.../standard_graphs/base_raster_noresample.pdf | Bin 0 -> 1566 bytes
.../standard_graphs/base_symbolic_simple.pdf | Bin 0 -> 1556 bytes
.../standard_graphs/character_expansion.pdf | Bin 0 -> 1340 bytes
tests/testthat/standard_graphs/contour_lines.pdf | Bin 0 -> 32839 bytes
tests/testthat/standard_graphs/draw_circles.pdf | Bin 0 -> 3037 bytes
.../standard_graphs/draw_filled_circles.pdf | Bin 0 -> 2096 bytes
.../testthat/standard_graphs/filled_rectangle.pdf | Bin 0 -> 1518 bytes
.../standard_graphs/ggplot2_superscripts.pdf | Bin 0 -> 17097 bytes
tests/testthat/standard_graphs/ggplot2_test.pdf | Bin 0 -> 29901 bytes
tests/testthat/standard_graphs/graph_box.pdf | Bin 0 -> 11849 bytes
tests/testthat/standard_graphs/grid_annotation.pdf | Bin 0 -> 12126 bytes
tests/testthat/standard_graphs/grid_raster.pdf | Bin 0 -> 17672 bytes
tests/testthat/standard_graphs/hello_TeX.pdf | Bin 0 -> 11202 bytes
tests/testthat/standard_graphs/line_color.pdf | Bin 0 -> 1187 bytes
.../testthat/standard_graphs/line_color_width.pdf | Bin 0 -> 1191 bytes
tests/testthat/standard_graphs/line_types.pdf | Bin 0 -> 1299 bytes
tests/testthat/standard_graphs/line_weights.pdf | Bin 0 -> 1262 bytes
.../testthat/standard_graphs/lots_of_elements.pdf | Bin 0 -> 49083 bytes
.../standard_graphs/luatex_utf8_characters.pdf | Bin 0 -> 12315 bytes
tests/testthat/standard_graphs/pch_caracters.pdf | Bin 0 -> 17740 bytes
tests/testthat/standard_graphs/persp_3D.pdf | Bin 0 -> 35828 bytes
tests/testthat/standard_graphs/plot_legend.pdf | Bin 0 -> 16174 bytes
tests/testthat/standard_graphs/polypath.pdf | Bin 0 -> 17108 bytes
.../testthat/standard_graphs/raster_reflection.pdf | Bin 0 -> 19107 bytes
.../testthat/standard_graphs/string_placement.pdf | Bin 0 -> 29082 bytes
tests/testthat/standard_graphs/text_alignment.pdf | Bin 0 -> 12838 bytes
tests/testthat/standard_graphs/text_color.pdf | Bin 0 -> 14081 bytes
tests/testthat/standard_graphs/transparency.pdf | Bin 0 -> 6113 bytes
tests/testthat/standard_graphs/utf8_characters.pdf | Bin 0 -> 10735 bytes
tests/testthat/standard_graphs/xetex_variants.pdf | Bin 0 -> 26992 bytes
tests/testthat/test_error_handling.R | 130 ++
tests/testthat/test_graphics.R | 717 ++++++
tests/testthat/test_metrics_dict.R | 87 +
tests/testthat/test_pointsize.R | 18 +
tests/unit_tests.R | 25 +
vignettes/agufull04.bst | 1815 +++++++++++++++
vignettes/consoleExample.tex | 19 +
vignettes/figs/annotation.tex | 97 +
vignettes/figs/latexEx.tex | 118 +
vignettes/figs/pdf-example.pdf | Bin 0 -> 4607 bytes
vignettes/figs/simpleEx.tex | 76 +
vignettes/figs/tikz-example.tex | 76 +
vignettes/figs/titlePlot.tex | 312 +++
vignettes/figs/westCoast.tex | 385 ++++
vignettes/img/Rlogo.png | Bin 0 -> 79779 bytes
vignettes/img/plotmathDefault.pdf | Bin 0 -> 276186 bytes
vignettes/img/plotmathTikz.pdf | Bin 0 -> 19987 bytes
vignettes/img/xelatexEx.pdf | Bin 0 -> 26959 bytes
vignettes/refs.bib | 54 +
vignettes/sweavetolst.sty | 132 ++
vignettes/tikzCodeBlock.sty | 395 ++++
vignettes/tikzDevice-concordance.tex | 4 +
vignettes/tikzDevice.Rnw | 2129 ++++++++++++++++++
vignettes/tikzDeviceVignette.sty | 305 +++
102 files changed, 16030 insertions(+), 127 deletions(-)
diff --git a/DESCRIPTION b/DESCRIPTION
new file mode 100644
index 0000000..6671310
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,39 @@
+Encoding: UTF-8
+Package: tikzDevice
+Type: Package
+Title: R Graphics Output in LaTeX Format
+Version: 0.10-1
+Date: 2016-02-09
+Authors at R: c( person("Charlie", "Sharpsteen", role = "aut"),
+ person("Cameron", "Bracken", role = "aut"), person("Kirill",
+ "Müller", role = c("ctb", "cre"), email =
+ "krlmlr+r at mailbox.org"), person("Yihui", "Xie", role = "ctb") )
+URL: https://github.com/yihui/tikzDevice
+BugReports: https://github.com/yihui/tikzDevice/issues
+Description: Provides a graphics output device for R that records plots
+ in a LaTeX-friendly format. The device transforms plotting
+ commands issued by R functions into LaTeX code blocks. When
+ included in a LaTeX document, these blocks are interpreted with
+ the help of 'TikZ'---a graphics package for TeX and friends
+ written by Till Tantau. Using the 'tikzDevice', the text of R
+ plots can contain LaTeX commands such as mathematical formula.
+ The device also allows arbitrary LaTeX code to be inserted into
+ the output stream.
+License: GPL (>= 2)
+Depends: R (>= 2.14.0)
+Imports: filehash (>= 2.3), png
+Suggests: testthat (>= 0.8.1), evaluate, stringr, ggplot2, maps, knitr,
+ crayon
+SystemRequirements: pgf (>= 2.00)
+LazyLoad: yes
+VignetteBuilder: knitr
+RoxygenNote: 5.0.1
+NeedsCompilation: yes
+Packaged: 2016-02-09 20:31:26 UTC; muelleki
+Author: Charlie Sharpsteen [aut],
+ Cameron Bracken [aut],
+ Kirill Müller [ctb, cre],
+ Yihui Xie [ctb]
+Maintainer: Kirill Müller <krlmlr+r at mailbox.org>
+Repository: CRAN
+Date/Publication: 2016-02-10 09:11:31
diff --git a/MD5 b/MD5
new file mode 100644
index 0000000..9d29003
--- /dev/null
+++ b/MD5
@@ -0,0 +1,90 @@
+4bf6a24b03889eb42e869625ac594ca0 *DESCRIPTION
+a9005515973c6a56380b0a10f4ba579f *NAMESPACE
+d1716cc59050e96ce58bb7b16282be1b *NEWS.md
+f1da36f1631da1ce3f21e4389ac1cde5 *R/cacheMetrics.R
+98a1a55a550d923056ac0bcef353ba14 *R/deviceUtils.R
+03257455b23a17c1f020e50863da715c *R/latexStrWidth.R
+9939dab5452ff368caf466e9561a7858 *R/sanitizeTexString.R
+0a169b7d47ed200a1ab0fd80c48c4ad6 *R/tikz.R
+3c6c4dce69934806035e4eeafebf5293 *R/tikzAnnotate.R
+04745ee959f00af2a25e4fd18b586489 *R/tikzDevice-package.R
+550d970e822d4479106798f02a27c33a *R/tikzInternal.R
+485f7c93e38768a98ae94e09c481067a *R/zzz.R
+f53cdeb868fa4559eb457681e65db549 *build/vignette.rds
+85af3ae9f36af9053bdf17edde20ad68 *inst/doc/tikzDevice.R
+f4fa3184e3a7b39ae7ee766a06029ca1 *inst/doc/tikzDevice.Rnw
+69af2f57d24308cd26bb471e3a033b77 *inst/doc/tikzDevice.pdf
+a1b0cf9a5a6741378e76f7b6868a9eb4 *man/anyMultibyteUTF8Characters.Rd
+2c1fe2e35461be861086b5f4b044e775 *man/getLatexStrWidth.Rd
+87313446821b6fccd0687464692b952d *man/gridToDevice.Rd
+71ff6a44795743f78f3477306a344489 *man/sanitizeTexString.Rd
+2d3d0d929a13bfa91e9c1e4c38b97e4d *man/setTikzDefaults.Rd
+310ab7b3e41d5e55274f7ca5f18d5ee8 *man/tikz.Rd
+3d759e71baa1ffe17e458f66ea03b0dd *man/tikzAnnotate.Rd
+ccb9123d1562d5f72f818d8568c2c947 *man/tikzCompilerInfo.Rd
+b6727c540f8389f1c71d8c548de26c1b *man/tikzDevice-package.Rd
+9a9c7bd372e4a73773b979fce8742248 *src/tikzDevice.c
+e24c44e35b90aa058354bb52e219bd19 *src/tikzDevice.h
+d41d8cd98f00b204e9800998ecf8427e *tests/testthat/Rplots.tex
+7781ce122de246891adbc5ea9d220666 *tests/testthat/Rplots_colors.tex
+8c20a7ca08d980205438bebd35b79eb9 *tests/testthat/helper_bootstrap.R
+136dde4c8eb780c6ebbe24aa4cd97c93 *tests/testthat/helper_expectations.R
+67295f7cb798486f0b170714694b9b9a *tests/testthat/helper_graphics.R
+0d3c15c0935cdcc4e8520d91fcc92cf5 *tests/testthat/helper_reporters.R
+275938a5fceb495ae329ee9ce1accee9 *tests/testthat/standard_graphs/annotation_noflush.pdf
+c43da51a80fd4c4ddfc29c057b965b0c *tests/testthat/standard_graphs/base_annotation.pdf
+7c3b8b29d0d158066045f105f2b240b7 *tests/testthat/standard_graphs/base_raster.pdf
+e7c89cbd143b1c92ead5abf400fcabae *tests/testthat/standard_graphs/base_raster_noresample.pdf
+a3e0d9b8ae94928ff0f66c8f2b4fb3f9 *tests/testthat/standard_graphs/base_symbolic_simple.pdf
+22d37f4ba14ca367bd0c9aa0edee95e3 *tests/testthat/standard_graphs/character_expansion.pdf
+67a1345a4ad34d3ef4344136216ca8a7 *tests/testthat/standard_graphs/contour_lines.pdf
+c11b1bc1ae3e0bbfa22619a8d214436a *tests/testthat/standard_graphs/draw_circles.pdf
+f863f0b34f5d6e4ab254fa03c5a154da *tests/testthat/standard_graphs/draw_filled_circles.pdf
+8614f6e41ba0e7da6f4033d51ce9e251 *tests/testthat/standard_graphs/filled_rectangle.pdf
+11d71098549f8ae9d867646349cdee4f *tests/testthat/standard_graphs/ggplot2_superscripts.pdf
+a6a7ad1ebcd4c637a006f8972df244c9 *tests/testthat/standard_graphs/ggplot2_test.pdf
+7da8d38f9af4ab708e62c85d2eded8ee *tests/testthat/standard_graphs/graph_box.pdf
+4dff6d86d4b9ef121152ac1f42d76166 *tests/testthat/standard_graphs/grid_annotation.pdf
+8357fb6dae8aeabc398bcadc34bcac54 *tests/testthat/standard_graphs/grid_raster.pdf
+bedcf9f95ffc4d35a9afadd0f484d50a *tests/testthat/standard_graphs/hello_TeX.pdf
+4528f9ae65644d4ae0e8f7798bd76679 *tests/testthat/standard_graphs/line_color.pdf
+3a7ac18aed35c611be6c3a7faa24e30c *tests/testthat/standard_graphs/line_color_width.pdf
+ff3cc288a490a6090c6a631db38f399e *tests/testthat/standard_graphs/line_types.pdf
+21c0f882d246e028366b4fedce19ec8b *tests/testthat/standard_graphs/line_weights.pdf
+90c99d54c9131e2880d6206a26a0a9e5 *tests/testthat/standard_graphs/lots_of_elements.pdf
+62f59c743ec071c274b498944d1be415 *tests/testthat/standard_graphs/luatex_utf8_characters.pdf
+54d9f9072e5b5453526dc53084446566 *tests/testthat/standard_graphs/pch_caracters.pdf
+a071cec01357ac14f4c283c91bc61bb4 *tests/testthat/standard_graphs/persp_3D.pdf
+a0e5c745ff2a0d71cd3dce5b942c9b29 *tests/testthat/standard_graphs/plot_legend.pdf
+f31e7b65cf1055bb22df1b9a8919a73c *tests/testthat/standard_graphs/polypath.pdf
+bdce1f468d665eeb8eb71d1c81ec58d4 *tests/testthat/standard_graphs/raster_reflection.pdf
+88b0472ebdf87b365dc994aef25444ea *tests/testthat/standard_graphs/string_placement.pdf
+586ee1b81437af9da31a24b883bb8aab *tests/testthat/standard_graphs/text_alignment.pdf
+bed326a4880addb9d61a2f09017b7b7b *tests/testthat/standard_graphs/text_color.pdf
+6ffc2996185810dec2fa221f3d72edcb *tests/testthat/standard_graphs/transparency.pdf
+13b3c5296acaf151978f1af947a0fcaf *tests/testthat/standard_graphs/utf8_characters.pdf
+262cb48fa2b7121bfafc1bddbe80d58e *tests/testthat/standard_graphs/xetex_variants.pdf
+69925ccbf6767435c89c570a598f6382 *tests/testthat/test_error_handling.R
+198360595474040e839c234fe5751860 *tests/testthat/test_graphics.R
+7d38be4c46c27e4cf73b64dc85bf0237 *tests/testthat/test_metrics_dict.R
+2795aff8133b1e41da9624d076e8bef8 *tests/testthat/test_pointsize.R
+f44c49b9d96b8d11b8de10686c7f8daf *tests/unit_tests.R
+6141124f420ca67b5b282ea4e18d23b2 *vignettes/agufull04.bst
+8de32046540ba433cdc539742072bfbf *vignettes/consoleExample.tex
+6b2554232e8c79f812e81b6bf7ad96ef *vignettes/figs/annotation.tex
+f6790980753f3295a8ee95e8523c721e *vignettes/figs/latexEx.tex
+adce6b736be0f998be04643c2e5ce69e *vignettes/figs/pdf-example.pdf
+9633410e537b6ca0b1365bc084b0799e *vignettes/figs/simpleEx.tex
+5a7ccae3400bf9df4de689741f22f9db *vignettes/figs/tikz-example.tex
+a1fb04d372395eeae231c5726a3afa27 *vignettes/figs/titlePlot.tex
+ed4789db739f3c298f7351923835d903 *vignettes/figs/westCoast.tex
+7012cde5b60209165cdc281d888b33ac *vignettes/img/Rlogo.png
+deea1d45830a3efd285ff6dd630cb2dd *vignettes/img/plotmathDefault.pdf
+91b12c045d1f42636f64062d2b59d869 *vignettes/img/plotmathTikz.pdf
+b46bd1ca663f3c0de3c47862f58d61e8 *vignettes/img/xelatexEx.pdf
+ee79774a53dce8a923c4242b65d63d85 *vignettes/refs.bib
+61d7f0a2d41b911054ceb62cea2380de *vignettes/sweavetolst.sty
+5555e1ac11de90b19f2dc66a639ee7c3 *vignettes/tikzCodeBlock.sty
+199f7d375ae849dfad05ae9e1e08d584 *vignettes/tikzDevice-concordance.tex
+f4fa3184e3a7b39ae7ee766a06029ca1 *vignettes/tikzDevice.Rnw
+e75a59491624989154600cfe33b36579 *vignettes/tikzDeviceVignette.sty
diff --git a/NAMESPACE b/NAMESPACE
new file mode 100644
index 0000000..a9e244c
--- /dev/null
+++ b/NAMESPACE
@@ -0,0 +1,53 @@
+# Generated by roxygen2: do not edit by hand
+
+S3method(drawDetails,tikz_annotation)
+S3method(drawDetails,tikz_coord)
+S3method(drawDetails,tikz_node)
+S3method(format,ENV_VAR)
+S3method(format,OPTION)
+S3method(format,PATH)
+export(anyMultibyteUTF8Characters)
+export(getLatexCharMetrics)
+export(getLatexStrWidth)
+export(grid.tikzAnnotate)
+export(grid.tikzCoord)
+export(grid.tikzNode)
+export(gridToDevice)
+export(sanitizeTexString)
+export(setTikzDefaults)
+export(tikz)
+export(tikzAnnotate)
+export(tikzAnnotateGrob)
+export(tikzCompilerInfo)
+export(tikzCoord)
+export(tikzCoordGrob)
+export(tikzNode)
+export(tikzNodeGrob)
+importFrom(filehash,dbCreate)
+importFrom(filehash,dbExists)
+importFrom(filehash,dbFetch)
+importFrom(filehash,dbInit)
+importFrom(filehash,dbInsert)
+importFrom(grDevices,as.raster)
+importFrom(grDevices,dev.cur)
+importFrom(grDevices,dev.list)
+importFrom(grDevices,dev.off)
+importFrom(grDevices,png)
+importFrom(graphics,grconvertX)
+importFrom(graphics,grconvertY)
+importFrom(graphics,par)
+importFrom(graphics,plot.new)
+importFrom(graphics,rasterImage)
+importFrom(grid,convertX)
+importFrom(grid,convertY)
+importFrom(grid,current.transform)
+importFrom(grid,drawDetails)
+importFrom(grid,grid.draw)
+importFrom(grid,grob)
+importFrom(grid,unit)
+importFrom(stats,complete.cases)
+importFrom(utils,packageVersion)
+useDynLib(tikzDevice,TikZ_Annotate)
+useDynLib(tikzDevice,TikZ_DeviceInfo)
+useDynLib(tikzDevice,TikZ_EvalWithoutInterrupts)
+useDynLib(tikzDevice,TikZ_StartDevice)
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..aabe1d2
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,502 @@
+Version 0.10-1 (2016-02-09)
+===
+
+- Use `CDR(CDDR())` instead of `CDDDR()`, the latter is available only in R 3.2.0 (#136).
+
+
+Changes in version 0.10 (2016-02-04)
+===
+
+Features
+---
+
+- Use `png::writePNG()` to output raster images to avoid reentrancy issues with capturing and playback and to reduce size of raster images. The `tikzRasterResolution` option is now obsolete (#132).
+
+Bug Fixes
+---
+
+- The setting `sanitize = TRUE` works even if the `tikzDevice` package is not attached to the search path (#129).
+
+Internal
+---
+
+- Update `ggplot2` results to account for minor differences due to the package's update (#131).
+- Add test for combined rotation and reflection of raster images.
+- Add tracing code to the beginning of almost every C function.
+
+
+Changes in version 0.9 (2015-11-16)
+===
+
+Features
+---
+
+- PNG images now use `png(type = "cairo")` on all platforms (#121)
+- New argument `verbose` to `tikz()` function (#117, #124)
+
+Bug Fixes
+---
+
+- Fix segfault when no file extension is provided (#101)
+- Fix quoting issue with spaces in the tempdir name (#99, #105, #106)
+- Fix the error from getMetricsFromLatex() when options(OutDec) is set to "," (#57)
+- Allow loading package even if LaTeX is not available, with a warning instead of a fatal error (#112, 125)
+- Bump dependency for `filehash` (#109)
+
+Internal
+---
+
+- R compatibility update: Explicit imports from recommended pacakges (#116)
+- Use `crayon` for coloring test output (#112)
+
+
+Changes in version 0.8.1 (2015-01-07)
+===
+
+Bug Fixes
+---
+
+- Renamed `strlcpy` to `strlcpy_` to avoid name clashes on OS X and Solaris (#97).
+- Reduced size of archive on CRAN.
+
+Changes in version 0.8 (2015-01-07)
+===
+
+Compatibility
+---
+
+- This release doesn't work on OS X and Solaris. This will be resolved soon.
+
+Contributors
+---
+
+- Thanks to Greg Jefferis, Bill Venables, Sam Mason, Gvozden Neskovic,
+ Martin Bergner and Casper Ti. Vector for contributing to this release.
+
+Features
+---
+
+- Add parameter `timestamp` to `tikz` to make the output of the timestamp optional (#28,
+ #73, thanks Martin Bergner).
+- Add parameter `lwdUnit` to `tikz` to specify the physical width of a line
+ (in points) that is 1 unit wide in R. By default, the value of option
+ `tikzLwdUnit` is used; this option has a value of 0.4 at startup (#68,
+ thanks Casper Ti. Vector).
+- Optionally use symbolic colors defined in a single external file instead of
+ hard-coded colors defined in-place. New parameters `symbolicColors`,
+ `colorFileName` and `maxSymbolicColors`; new options `tikzSymbolicColors`
+ and `tikzMaxSymbolicColors`. The external file is only created if requested;
+ in this case, symbolic color names are used instead of `fillColor` and
+ `drawColor` (#70, thanks Martin Bergner).
+
+Bug Fixes
+---
+
+- Ignore fill color for lines to remove thin line (1 pixel wide) that was shown
+ with dashed or dotted lines on some viewers (#63, thanks Martin Bergner).
+- More robust handling of metrics dictionary. Changes to the
+ `tikzMetricsDictionary` option are recognized even if a metrics dictionary
+ already has been initialized, a message is printed the first time a dictionary
+ is used (in addition to the message that is printed when the dictionary is
+ created). A missing dictionary file is recreated (#21).
+- Performance improvements with zero-width strings (#66, thanks Gvozden Neskovic)
+- Add parameter `checkstate` to allow adding annotations to a new plot (#52,
+ thanks Sam Mason)
+- Allow raster images to be output without resampling by setting
+ `options(tikzRasterResolution = NA)` (#54, thanks Sam Mason)
+- In console mode, print a `\relax` statement after the comment to allow using
+ `tikzDevice` in a Sweave code chunk with `results=tex`, as advertised in the
+ vignette. (The default is `strip.white=TRUE` which makes the following
+ `\begin{tikzpicture}` appear on the same line as the encoding comment in the
+ resulting `.tex` file.) (#47, thanks Bill Venables)
+
+Vignette
+---
+
+- Use `knitr` as vignette builder (#37).
+- Fixed typos (#45, thanks Greg Jefferis).
+- Vignette now also compiles if the `zi4` TeX package is installed instead of
+ `inconsolata`. This should fix the CRAN notes and warnings on Windows.
+- Loading `babel` TeX package to avoid printing tilde in references (#49).
+
+Internal
+---
+
+- Tests perform strict image comparison (#18).
+- Testing now also works in RStudio.
+
+
+Changes in version 0.7.0 (2013-12-10, CRAN release)
+===
+
+Contributors
+---
+
+- New package maintainers: Kirill Müller and Yihui Xie.
+
+- Zack Weinberg for suggestions and comments that led to optimizations in the
+ quality and quantity of TikZ output.
+
+- Romain Franconville for bugreports that led to the discovery of two bugs in
+ the raster routines.
+
+- corecode for fixing the getDocumentPointsize routines for corner cases
+
+- Sietse Brouwer for enumerating the exact list of LaTeX packages
+ `tikzDevice` requires and for vignette spelling/style corrections.
+
+- Stéphane Laurent for reporting a bug in the detection of the document font size.
+
+New Features
+---
+
+- The `tikz` function now has a `onefile` argument that behaves similar to
+ the `onefile` argument of the `pdf` device (#40).
+
+- LuaLaTeX is now supported directly and can be selected by passing
+ `engine = 'luatex'` to `tikz` (#28).
+
+- New function `tikzCompilerInfo`, reports information concerning the compilers
+ used by the tikzDevice
+
+- Updated vignette (yihui/tikzDevice#36).
+
+Bug Fixes
+---
+
+- Colorized text now obeys transparency settings.
+
+- The tikzDevice no longer produces output for plots that are completely
+ empty.
+
+- The `tikz` option `footer` now works as described by the documentation.
+ Previously, it had no effect (#52).
+
+- The `tikz` device can now handle raster images with negative widths or
+ heights that arise from calling a raster plotting function using reversed
+ axes (#53).
+
+- Creating raster output with the tikzDevice could mess with the behavior of
+ some graphical paramaters such as par('mfrow'). This has been fixed (#54).
+
+- Calls to the `filehash` package have been protected from user interruptions.
+ This should prevent rogue lockfiles and corrupted metrics dictionaries.
+
+- The `documentDeclaration` and `packages` arguments to the `tikz` function
+ are now used in metric calculations. Previously, only global options were
+ consulted.
+
+- Properly copy strings containing LaTeX info, avoiding use of freed memory.
+
+- Point size of main font in document is now inferred correctly (even if the option
+ tikzDocumentDeclaration contains newlines), again fixed
+ regexp in getDocumentPointsize (yihui/tikzDevice#34).
+
+- Package can be installed in R 3.0.2.
+
+- No C warnings when installing (#68).
+
+- Function `grid.tikzNode` works again, had no effect due to a missing S3
+ export.
+
+- Fixed formatting of documentation.
+
+Behind the scenes
+---
+
+- The tikzDevice now requires R 2.14.0 or later.
+
+- Semantic versioning will be used from now on
+
+- Package is uploaded to RForge (http://rforge.net)
+
+- Enable continuous integration via craigcitro/r-travis. All supported R
+ versions are tested.
+
+- Upgrade documentation generation from Roxygen to Roxygen2.
+
+- Testing framework updated to use testthat 0.6. Earlier versions of testthat
+ are no longer supported due to a switch from Mutatr classes to standard R
+ Reference Classes (#56).
+
+- Some magic numbers that control the leading used in the margin text of base
+ graphics were adjusted to values used by the PDF device. Hopefully this
+ will make the spacing used by x axis labels and y axis labels a bit more
+ symmetric (#49).
+
+- The tikzDevice now delays the creation of clipping scopes until a drawing
+ operation occurs that can be clipped. This prevents empty clipping scopes
+ from appearing in the output and can reduce the size of the output by ~3/4
+ in some cases (#45).
+
+- The code that handles line color and fill color has been completely
+ refactored to avoid useless operations such as 0 transparency fills and
+ draws (#46).
+
+- Defer starting new tikzpicture environments (#12).
+
+- Replace library.dynam with useDynLib (#50).
+
+- Reduce verbosity of start-up message.
+
+- Support ggplot 0.9.0.
+
+Changes in version 0.6.2 (2011-11-13)
+===
+
+New Features
+---
+
+- The annotation system has been improved. A new function `tikzNode` has been
+ added that makes it easy to insert TikZ nodes with custom options and
+ content. `tikzCoord` is now a wrapper for `tikzNode` that simplifies the
+ function call required to get a plain coordinate.
+
+- Annotation of Grid graphics is now supported. New functions
+ `tikzAnnotateGrob`, `tikzNodeGrob` and `tikzCoordGrob` allow the creation of
+ Grid grobs that execute annotiation commands when drawn to a `tikz` device.
+ Wrapper functions `grid.tikzAnnotate`, `grid.tikzNode` and `grid.tikzCoord`
+ are also provided. The necessary transformations between Grid coordinates,
+ which are viewport-centric, to absolute device coordinates are handled by a
+ new function `gridToDevice`.
+
+- Support has been added for the `dev.capabilities` function in R 2.14.0.
+
+Bug Fixes
+---
+
+- Fixed a bug where the outline of the background bounding box was being drawn
+ with the forground color instead of the background color. This was
+ unnoticible except when a non-white background was used. Thanks to Matthieu
+ Stigler for reporting.
+
+Behind the Scenes
+---
+
+- The tikzDevice is now checked with "visual regression testing" which compares
+ the results of graphics tests against a set of standard images using a visual
+ diff. If a change occurs that significantly affects font metrics or graphics
+ primitives the effects will show up in the diff. Currently, ImageMagick's
+ `compare` utility is used to calculate differences. This process was inspired
+ by the work of Paul Murrell and Stephen Gardiner on the graphicsQC package.
+ Future versions of the tikzDevice may use graphicsQC to perform this task.
+
+- The tikzDevice Vignette used to employ a rather ugly hack that re-wrote the
+ internals of the Sweave driver during processing in order to gain more
+ control over syntax highlighting. This hack has been replaced by TeX macros
+ that achieve the same result without messing with R.
+
+
+Changes in version 0.6.1 (2011-4-14)
+===
+
+Bug Fixes
+---
+
+- Fixed a bug where `tikz` was not applying background color to the plot
+ canvas.
+
+- Fixed a Vignette bug caused by an incorrect merge that was breaking the CRAN
+ build.
+
+
+Changes in version 0.6.0 (2011-4-13)
+===
+
+New Features
+---
+
+- Unicode Support!!!! XeLaTeX may now be used calculate metrics and widths for
+ Unicode characters. PdfLaTeX remains the default LaTeX compiler, but this may
+ be changed by setting the global option `tikzDefaultEngine` to `xetex`.
+
+- New global option `tikzXelatexPackages` which contains packages necessary to
+ use unicode characters with xelatex. Specifically, the fontspec and the
+ xunicode packages as well as the xetex option to the preview package.
+
+- New global option `tikzUnicodeMetricPackages` which contains the packages
+ necessary to calculate metrics for multibyte unicode characters with xelatex.
+
+- New function anyMultibyteUTF8Characters() which will check if the given
+ string contains any multibyte unicode characters. Exposed in the package
+ namespace since it is general and may be useful in other applications.
+
+- The TikZ device now fully supports the `Raster` graphics primitive that was
+ added in R 2.11.0 and no longer throws "not implemented" warnings when this
+ functionality is used. This is accompilshed by writing raster images to PNG
+ files, `Rplots_ras#.png`, which are then included in the main TeX file
+ `Rplots.tex`.
+
+- The TikZ device now fully supports the `polypath` graphics primitive that was
+ added in R 2.12.0 and no longer throws "not implemented" warnings when this
+ functionality is used.
+
+
+Bug Fixes
+---
+
+- Fixed a bug where the `lwd` parameter used to control line widths was
+ declared by tikzDevice to be of type `int` when it is actually a `double`.
+ This was causing line widths to be ignored or miscalculated. Many thanks to
+ Baptiste Auguie for reporting this issue.
+
+
+Depreciation Notices
+---
+
+- Versions of R < 2.11.0 are no longer supported due to lack of required
+ functions for handling Unicode strings.
+
+
+Behind the Scenes
+---
+
+- New Makefile for executing common development tasks.
+
+- Package documentation now handled by `roxygen`. Many thanks to Hadley
+ Wickham and Yihui Xie for the `Rd2roxygen` package which facilitated this
+ switch.
+
+- Package test suite completely overhauled and now based on Hadley Wickham's
+ `test_that` unit testing framework.
+
+
+Changes in version 0.5.3
+===
+
+Bug Fixes
+---
+
+- R 2.12.x now throws a warning message when shell commands run via `system()`
+ have non-zero exit conditions. The metric calculation runs LaTeX on a file
+ containing an \@@end command. This causes a non zero exit condition. The end
+ result was that users were getting spammed by warning messages. These
+ messages have been gagged for now and a better way to run LaTeX such that a
+ non-zero condition can meaningfully indicate an error is being investigated.
+
+- The range of characters the default sanitizer looks for has been extended. It
+ should now process all characters that are special to TeX with the exception
+ of backslashes. Documentation has been improved.
+
+- Detection of failed string metric calculations has been strengthened and the
+ resulting error message has been improved.
+
+
+Changes in version 0.5.2
+===
+
+Contributors
+---
+
+- mlt for reporting problems with the Sanitize function that led to the
+ discovery of two situations where buffer overflows were occurring.
+
+
+Bug Fixes
+---
+
+- Fixed buffer overflows and memory leaks related to string pointers in
+ tikzDevice.c.
+
+- Fixed compilation of the tikzDevice vignette under R 2.12.0.
+
+- Reduced the verbosity of the package startup message.
+
+
+Changes in version 0.5.1
+===
+
+Bug Fixes
+---
+
+- A stub function has been added so that the `polypath()` function
+ introduced in R 2.12.0 won't crash the device.
+
+- Fixed bug where no string output was shown when the sanitize=TRUE option was
+ used.
+
+- The path to a LaTeX compiler returned by `Sys.which()` is now checked by
+ `file.access()` to check that it is actually an executable and not an error
+ message. This fixes issues arising from `Sys.which()` on Solaris.
+
+- On UNIX platforms, `/usr/texbin/pdflatex` is added to the end of the list of
+ places to search for a LaTeX compiler. This should help people using R.app on
+ OS X find a LaTeX compiler without having to manually specify it.
+
+- `tikz()` produces a better error message when it cannot open a file for output.
+
+- In the event that LaTeX crashes during a metric calculation, the LaTeX log
+ output is echoed using `message()` instead of `cat()`. This makes it show up
+ during operations that supperss `cat()` output such as `R CMD build` and
+ `R CMD Sweave`.
+
+
+Changes in version 0.5.0
+===
+
+Contributors
+---
+
+- Lorenzo Isella contributed bug reports and examples that led to the
+ discovery of a bug in fontsize calculations that appeared when
+ certain LaTeX commands were used to change the active font.
+
+- Vivianne Vilar for spotting spelling and grammar errors in the
+ vignette.
+
+- Gabor Grothendieck for the idea for sending output to the screen
+ for use with sink() (i.e. the "console" option)
+
+New Features
+---
+
+- "console" option for directing tikz() output back into the R console
+ instead of to a file.
+
+- Preliminary support for a "sanitize" option which allows automatic
+ escaping of characters that have special meaning to TeX like "$" and
+ "%".
+
+- tikzAnnotate() and tikzCoord() functions. tikzAnnotate() allows
+ arbitrary LaTeX code to be injected into the output stream of an
+ active tikz() graphics device. tikzCoord() is a wrapper for
+ tikzAnnotate() that inserts named locations into the graphics code.
+ These locations may be referenced by other TikZ drawing commands.
+
+
+Bug Fixes
+---
+
+- Removed bad colon in the DESCRIPTION file.
+
+- Proper fontsize calculations now include ps from par() and fontsize
+ from gpar(). This fixes issues with lattice-based graphics such as
+ ggplot2.
+
+- Metrics are now calculated properly when commands like
+ \renewcommand\rmdefault are used to adjust the active font.
+
+- Sanitization of % signs in labels.
+
+- The package no longer overwrites user customizations set in places like
+ .Rprofile with default values when loaded.
+
+- Attempting to use new graphics functions such as rasterImage() now
+ produces error messages instead of fatal crashes in R 2.11.0 and
+ above.
+
+Changes in version 0.4.0
+===
+
+- Initial Beta Release
+
+- Support for all essential graphical parameters: colors, line types,
+ line weights, semi-transparency, line endings and line joining.
+
+- String width and character metrics are calculated by direct calls to a LaTeX
+ compiler. This is an inefficient but robust method. Some of the inefficiency
+ of this method is compensated for by storing calculated string widths in a
+ database managed by the filehash package. This way if we pay a computational
+ price to compute the width of a string, we
+ hopefully only pay it once.
+
diff --git a/R/cacheMetrics.R b/R/cacheMetrics.R
new file mode 100644
index 0000000..8dc6cf4
--- /dev/null
+++ b/R/cacheMetrics.R
@@ -0,0 +1,111 @@
+# Filehash contains a function for generating a SHA1 hash from an R object, but
+# doesn't export it. The digest package also contains the exact same code made
+# publicly available but it seems redundant to add it to the dependency list.
+# This function simplifies access to filehash's unexported SHA1 function.
+sha1 <- filehash:::sha1
+
+
+# Since calling LaTeX to obtain string metrics is inefficient and expensive,
+# this function will search a string metrics dictionary to see if we have
+# already calculated metrics for this particular object. If so we return the
+# cached value.
+#
+#' @importFrom filehash dbExists dbFetch
+queryMetricsDictionary <-
+function( key, verbose )
+{
+ # Ensure the dictionary is available.
+ checkDictionaryStatus(verbose = verbose)
+
+ # Check for the string.
+ haveMetrics <- evalWithoutInterrupts(dbExists(.tikzInternal[['dictionary']], sha1(key)))
+ if ( haveMetrics ) {
+
+ # Yay! The width exists! Recover and return it.
+ metrics <- evalWithoutInterrupts(dbFetch(.tikzInternal[['dictionary']], sha1(key)))
+
+ } else {
+
+ # No dice. Return -1 to indicate that metrics for this string
+ # are not present in the dictionary.
+ return( -1 )
+
+ }
+}
+
+
+# This function enters values into the metrics dictionary. The metrics are
+# stored under a key which is a SHA1 hash created from the object they are
+# associated with.
+#
+#' @importFrom filehash dbInsert
+storeMetricsInDictionary <-
+function( key, metrics )
+{
+ evalWithoutInterrupts(dbInsert(.tikzInternal[['dictionary']], sha1(key), metrics))
+
+ # Return nothing.
+ invisible()
+}
+
+
+# This function checks to see if our dictionary has been created as a variable
+# in our private .tikzInternal environment. If not, it either opens a user
+# specified dictionary or creates a new one in tempdir().
+#
+#' @importFrom filehash dbCreate dbInit
+checkDictionaryStatus <- function(verbose)
+{
+ if (!verbose) {
+ message <- function(...) invisible()
+ }
+
+ dict_path <- getOption('tikzMetricsDictionary')
+ old_dict_path <- .tikzInternal[['dict_path']]
+ old_dictionary <- .tikzInternal[['dictionary']]
+ old_db_file <- .tikzInternal[['db_file']]
+ need_create <- FALSE
+
+ # Check for a user specified dictionary.
+ if( !is.null( dict_path ) ){
+ db_file <- path.expand(dict_path)
+
+ # Create the database file if it does not exist.
+ if( !file.exists( db_file ) ){
+ message("Creating new TikZ metrics dictionary at:\n\t", db_file)
+ need_create <- TRUE
+ }
+ } else {
+ # Create a temporary dictionary- it will disappear after
+ # the R session finishes.
+ db_file <- old_db_file
+ if ( is.null(db_file) || !file.exists(db_file) || !is.null(old_dict_path) ) {
+ db_file <- file.path( tempdir(), 'tikzMetricsDictionary' )
+ message("Creating temporary TikZ metrics dictionary at:\n\t", db_file)
+ need_create <- TRUE
+ }
+ }
+
+ # Create the database file if it does not exist.
+ if ( need_create ) {
+ unlink( db_file, recursive = TRUE )
+ dbCreate( db_file, type='DB1' )
+
+ # Need to initialize new database
+ old_dictionary <- NULL
+ }
+
+ if ( !is.null(old_dictionary) && identical(dict_path, old_dict_path) )
+ return(invisible())
+
+ # Add the dictionary as an object in the .tikzOptions
+ # environment.
+ message("Using TikZ metrics dictionary at:\n\t", db_file)
+ .tikzInternal[['dictionary']] <- dbInit(db_file)
+ .tikzInternal[['dict_path']] <- dict_path
+ .tikzInternal[['db_file']] <- db_file
+
+ # Return nothing.
+ invisible()
+
+}
diff --git a/R/deviceUtils.R b/R/deviceUtils.R
new file mode 100644
index 0000000..7fc979b
--- /dev/null
+++ b/R/deviceUtils.R
@@ -0,0 +1,384 @@
+# Utility functions that have nowhere else to live at the moment.
+# These functions are used by the device subroutines.
+
+getDocumentPointsize <- function( docString ){
+
+ # This function scans a LaTeX document declaration
+ # for base pointsize used in the document. For example,
+ # the declaration:
+ #
+ # \documentclass[draft,12pt]{article}
+ #
+ # Should cause this function to return 12 as the pointsize.
+ # The pointsize is used by the tikzDevice to determine
+ # scaling factors and is stored at the C level in the
+ # startps component of the pDevDesc structure.
+
+ # Search the document declaration for the pointsize, and extract it if it is
+ # there. (Split the input by newlines before.)
+ pointsize <- gsub( '^(?:.*[[, \t](\\d+)pt[], \t])?.*$', '\\1',
+ strsplit(docString, "\n", fixed = TRUE),
+ ignore.case = F, perl = T )
+
+ # Return first matching line (if any), or NA otherwise
+ as.numeric(pointsize[pointsize != ""][1])
+}
+
+
+#' Reset tikzDevice options to default values.
+#'
+#' This function resets the following options:
+#'
+#' \itemize{
+#' \item \code{tikzDefaultEngine}
+#' \item \code{tikzLatex}
+#' \item \code{tikzDocumentDeclaration}
+#' \item \code{tikzFooter}
+#' \item \code{tikzLatexPackages}
+#' \item \code{tikzXelatexPackages}
+#' \item \code{tikzLualatexPackages}
+#' \item \code{tikzMetricPackages}
+#' \item \code{tikzUnicodeMetricPackages}
+#' \item \code{tikzSanitizeCharacters}
+#' \item \code{tikzReplacementCharacters}
+#' \item \code{tikzPdftexWarnUTF}
+#' }
+#'
+#' @param overwrite Should values that are allready set in \code{options()} be
+#' overwritten?
+#' @return Nothing returned.
+#'
+#' @author Cameron Bracken \email{cameron.bracken@@gmail.com} and Charlie
+#' Sharpsteen \email{source@@sharpsteen.net}
+#'
+#' @seealso \code{\link{tikz}}
+#'
+#' @examples
+#'
+#' print( options( 'tikzDocumentDeclaration' ) )
+#' options( tikzDocumentDeclaration = 'foo' )
+#' setTikzDefaults()
+#' print( options( 'tikzDocumentDeclaration' ) )
+#'
+#' @export
+setTikzDefaults <- function( overwrite = TRUE ){
+
+ tikzDefaults <- list(
+
+ tikzDefaultEngine = 'pdftex',
+
+ tikzLatex = getOption( 'tikzLatexDefault' ),
+
+ tikzDocumentDeclaration = "\\documentclass[10pt]{article}\n",
+
+ tikzLatexPackages = c(
+ "\\usepackage{tikz}\n",
+ "\\usepackage[active,tightpage,psfixbb]{preview}\n",
+ "\\PreviewEnvironment{pgfpicture}\n",
+ "\\setlength\\PreviewBorder{0pt}\n"
+ ),
+
+ tikzXelatexPackages = c(
+ "\\usepackage{tikz}\n",
+ "\\usepackage[active,tightpage,xetex]{preview}\n",
+ "\\usepackage{fontspec,xunicode}\n",
+ "\\PreviewEnvironment{pgfpicture}\n",
+ "\\setlength\\PreviewBorder{0pt}\n"
+ ),
+
+ tikzLualatexPackages = c(
+ "\\usepackage{tikz}\n",
+ "\\usepackage[active,tightpage,psfixbb]{preview}\n",
+ "\\usepackage{fontspec,xunicode}\n",
+ "\\PreviewEnvironment{pgfpicture}\n",
+ "\\setlength\\PreviewBorder{0pt}\n"
+ ),
+
+ tikzFooter = "",
+
+ tikzMetricPackages = c(
+ # The fontenc package is very important here!
+ # R assumes the output device is uing T1 encoding.
+ # LaTeX defaults to OT1. This package makes the
+ # symbol codes consistant for both systems.
+ "\\usepackage[T1]{fontenc}\n",
+ "\\usetikzlibrary{calc}\n"
+ ),
+
+ tikzUnicodeMetricPackages = c(
+ # The fontenc package is very important here!
+ # R assumes the output device is uing T1 encoding.
+ # LaTeX defaults to OT1. This package makes the
+ # symbol codes consistant for both systems.
+ "\\usepackage[T1]{fontenc}\n",
+ "\\usetikzlibrary{calc}\n",
+ "\\usepackage{fontspec,xunicode}\n"
+ ),
+
+
+ tikzSanitizeCharacters = c('%','$','}','{','^','_','#','&','~'),
+
+ tikzReplacementCharacters = c('\\%','\\$','\\}','\\{','\\^{}','\\_{}',
+ '\\#','\\&','\\char`\\~'),
+
+ tikzLwdUnit = 0.4,
+
+ tikzPdftexWarnUTF = TRUE,
+
+ tikzSymbolicColors = FALSE,
+ tikzMaxSymbolicColors = 100
+ )
+
+ if( !overwrite ){
+
+ # We don't want to overwrite options that have allready been set.
+ # Figure out which those are.
+ tikzSetOptions <- sapply( do.call( options, as.list(names(tikzDefaults)) ),
+ is.null )
+
+ tikzSetOptions <- names( tikzDefaults )[ tikzSetOptions ]
+
+ }else{
+
+ tikzSetOptions <- names( tikzDefaults )
+
+ }
+
+ # Set defaults
+ do.call( options, tikzDefaults[ tikzSetOptions ] )
+
+ # Return a list of the options that were modified.
+ invisible( tikzSetOptions )
+
+}
+
+isTikzDevice <- function(which = dev.cur()){
+ if (which == 1){ return(FALSE) }
+
+ dev_name <- names(dev.list()[which - 1])
+ return(dev_name == 'tikz output')
+}
+
+
+#' @useDynLib tikzDevice TikZ_DeviceInfo
+getDeviceInfo <- function(dev_num = dev.cur()) {
+ # This function recovers some information about a tikz() graphics device that
+ # is stored at the C level in the tikzDevDesc struct.
+ #
+ # Currently returns:
+ #
+ # * The path to the TeX file that is being created.
+ if (!isTikzDevice(dev_num)){
+ stop("The specified device is not a tikz device!")
+ }
+
+ device_info <- .Call(TikZ_DeviceInfo, dev_num)
+
+ return(device_info)
+}
+
+# This function allows an R expression to be evaluated in a context where it
+# will be protected from user interrupts (use of CTRL-C for example).
+#
+#' @useDynLib tikzDevice TikZ_EvalWithoutInterrupts
+evalWithoutInterrupts <- function(expr, envir = parent.frame())
+{
+ # Wrap the expression in a call to `substitute` so that it gets passed
+ # directly to the C code instead of being evaluated before being passed to
+ # the C code.
+ .Call(TikZ_EvalWithoutInterrupts, substitute(expr), envir)
+}
+
+
+#' Check If a String Contains Multibyte UTF-8 characters
+#'
+#' This function is used by tikzDevice to check if an incoming string contains
+#' multibyte UTF-8 characters
+#'
+#' This function searches through the characters in the given string, if any of
+#' the characters in the string are more than one byte then the function
+#' returns \code{TRUE} otherwise it returns \code{FALSE}.
+#'
+#' The function will assume an input encoding of UTF-8 but will take any
+#' specified encoding into account and will convert from the specified encoding
+#' to UTF-8 before doing any checks
+#'
+#' @param string A character vector of length 1 (a string).
+#' @param encoding The input encoding of \code{string}, if not specified
+#' previously via \code{\link{Encoding}} or by this argument then a value of
+#' "UTF-8" is assumed
+#' @return A boolean value
+#' @author Cameron Bracken \email{cameron.bracken@@gmail.com}
+#' @seealso \code{\link{tikz}}
+#' @keywords character
+#' @encoding UTF8
+#' @examples
+#'
+#' # TRUE
+#' anyMultibyteUTF8Characters('R is GNU ©, but not ®')
+#' # FALSE
+#' anyMultibyteUTF8Characters('R is GNU copyright but not restricted')
+#'
+#' @export
+anyMultibyteUTF8Characters <- function(string, encoding = "UTF-8"){
+
+ # This function checks if any of the characters in the given string
+ # are multibyte unicode charcters (not ASCII)
+ #
+ # The function will assume an input encoding of UTF-8 but will take any
+ # specified encoding into account and will convert from the specified
+ # encoding to UTF-8 before doing any checks
+
+ mb <- FALSE
+
+ # Set the encoding of the string if it is not explicitly set
+ if(Encoding(string) == "unknown")
+ Encoding(string) <- encoding
+
+ # convert the string to UTF-8
+ string <- enc2utf8(string)
+
+ # Check if any of the characters are Multibyte
+ explode <- strsplit(string,'')[[1]]
+ for(i in 1:length(explode)){
+
+ if(length(charToRaw(explode[i])) > 1){
+ mb <- TRUE
+ break
+ }
+ }
+
+ return(mb)
+
+}
+
+
+# -----------------------------------------------------------------------------
+# Methods for locating TeX Compilers
+# -----------------------------------------------------------------------------
+
+# S3 classes to represent the various sources for the path to an exectuable.
+PATH <-
+function(origin)
+{
+ structure(Sys.which(origin), origin = origin, class = 'PATH')
+}
+
+OPTION <-
+function(origin)
+{
+ structure(ifelse(is.null(getOption(origin)), '', Sys.which(getOption(origin))),
+ origin = origin, class = 'OPTION')
+}
+
+ENV_VAR <-
+function(origin)
+{
+ structure(ifelse(is.null(Sys.getenv(origin)), '', Sys.which(Sys.getenv(origin))),
+ origin = origin, class = 'ENV_VAR')
+}
+
+
+isExecutable <-
+function(executable)
+{
+ path <- as.character(executable)
+
+ # file.access doesn't like non-zero lengths.
+ if ( nchar(path) == 0 ) { return(FALSE) }
+
+ if ( file.access(path, 1) == 0 ) {
+ return(TRUE)
+ } else {
+ return(FALSE)
+ }
+}
+
+formatExecutable <-
+function(executable)
+{
+ desc <- 'path:\n\t'
+ desc <- paste(desc, as.character(executable), sep = '')
+ desc <- paste(desc, "\nObtained from ", sep = '')
+ desc <- paste(desc, format(executable), '\n', sep = '')
+
+ return(desc)
+}
+
+# S3 methods have to be exported to the NAMESPACE in order to be effective
+# during .onLoad...
+
+#' @export
+format.PATH <- function(x, ...) { sprintf('the PATH using the command: %s', attr(x, 'origin')) }
+#' @export
+format.OPTION <- function(x, ...) { sprintf('the global option: %s', attr(x, 'origin')) }
+#' @export
+format.ENV_VAR <- function(x, ...) { sprintf('the environment variable: %s', attr(x, 'origin')) }
+
+
+#' Print paths to TeX compilers.
+#'
+#' This function reports information concerning compilers that the \code{tikz}
+#' device will use to calculate character metrics. Information on LaTeX will
+#' always be available but information on XeLaTeX and LuaLaTeX will only be
+#' reported if the compilers were found.
+#'
+#' @param verbose
+#' If set to \code{FALSE}, calling this function will not cause any output to
+#' be printed to the screen. Defaults to \code{TRUE}.
+#'
+#' @return
+#' Invisibly returns a list containing paths to TeX compilers.
+#'
+#' @author
+#' Charlie Sharpsteen \email{source@@sharpsteen.net}
+#'
+#' @seealso
+#' \code{\link{tikz}}
+#'
+#' @export
+tikzCompilerInfo <-
+function(verbose = TRUE)
+{
+ latexCompiler <- getOption('tikzLatex')
+ xelatexCompiler <- getOption('tikzXelatex')
+ lualatexCompiler <- getOption('tikzLualatex')
+
+ if ( verbose ) {
+ cat('\nLaTeX Compiler:\n\t')
+ cat(latexCompiler)
+ cat('\n\t')
+ p <- pipe(paste(latexCompiler, '--version'))
+ cat(utils::head(readLines(p), 2), sep = '\n\t')
+ close(p)
+ cat('\n')
+
+ cat('\nXeLaTeX Compiler:\n\t')
+ if ( is.null(xelatexCompiler) ) {
+ cat('Not available.\n')
+ } else {
+ cat(xelatexCompiler)
+ cat('\n\t')
+ p <- pipe(paste(xelatexCompiler, '--version'))
+ cat(utils::head(readLines(p), 2), sep = '\n\t')
+ close(p)
+ cat('\n')
+ }
+
+ cat('\nLuaLaTeX Compiler:\n\t')
+ if ( is.null(lualatexCompiler) ) {
+ cat('Not available.\n')
+ } else {
+ cat(lualatexCompiler)
+ cat('\n\t')
+ p <- pipe(paste(lualatexCompiler, '--version'))
+ cat(utils::head(readLines(p), 2), sep = '\n\t')
+ close(p)
+ cat('\n')
+ }
+ } # End if(verbose)
+
+ invisible(list(
+ latex = latexCompiler, xelatex = xelatexCompiler, lualatex = lualatexCompiler
+ ))
+}
diff --git a/R/latexStrWidth.R b/R/latexStrWidth.R
new file mode 100644
index 0000000..e17bb2d
--- /dev/null
+++ b/R/latexStrWidth.R
@@ -0,0 +1,486 @@
+#' Obtain Font Metrics from LaTeX
+#'
+#' These functions calculate the width of a character or string as it would
+#' appear after being compiled by LaTeX.
+#'
+#' These functions are used internally by the \code{tikz} device for proper
+#' string placement in graphics. Both functions check to see if metrics exist
+#' in a global or temporary dictionary (as defined in
+#' \code{options('tikzMetricsDictionary')}) and if so will pull the metrics
+#' from there. If the dictionary does not exist, then a temporary one is
+#' created for the current R session. Metrics are calculated via \code{system}
+#' calls to LaTeX compilers. Querying compilers to calculate metrics is
+#' expensive and so we strongly recommend setting
+#' \code{options('tikzMetricsDictionary') <- '/path/to/dictionary'} to create a
+#' global dictionary.
+#'
+#' @param texString An arbitrary string for which the width is to be
+#' calculated. May contain LaTeX markup.
+#' @param cex a real number that specifies a scaling factor that is to be
+#' applied to device output.
+#' @param face an integer in the range [1-5] that specifies the font face to
+#' use. See \link{par} for details.
+#' @param engine a string specifying which TeX engine to use. Possible values
+#' are 'pdftex', 'xetex' and 'luatex'. See the Unicode section of \link{tikzDevice} for
+#' details.
+#' @param documentDeclaration See the sections ``Options That Affect Package
+#' Behavior'' and ``Font Size Calculations'' of \link{tikzDevice-package}
+#' for more details.
+#' @param packages See the section ``Options That Affect Package Behavior'' of
+#' \link{tikzDevice-package}.
+#' @param verbose A logical value indicating whether diagnostic messages are
+#' printed when measuring dimensions of strings. Defaults to \code{TRUE} in
+#' interactive mode only, to \code{FALSE} otherwise.
+#'
+#'
+#' @return
+#' \item{getLatexStrWidth}{The width of \code{texString} in points.}
+#' \item{getLatexCharMetrics}{A numeric vector holding ascent, descent
+#' and width. Values should all be nonnegative.}
+#'
+#' @author Charlie Sharpsteen \email{source@@sharpsteen.net} and Cameron
+#' Bracken \email{cameron.bracken@@gmail.com}
+#'
+#' @keywords string character metrics
+#'
+#' @examples
+#'
+#' getLatexStrWidth('{\\\\tiny Hello \\\\LaTeX!}')
+#'
+#' @references PGF Manual
+#' @export
+getLatexStrWidth <-
+function(texString, cex = 1, face = 1, engine = getOption('tikzDefaultEngine'),
+ documentDeclaration = getOption("tikzDocumentDeclaration"), packages,
+ verbose = interactive())
+{
+
+ switch(engine,
+ pdftex = {
+ if ( anyMultibyteUTF8Characters(texString) && getOption('tikzPdftexWarnUTF') ) {
+ warning("Attempting to calculate the width of a Unicode string",
+ "using the pdftex engine. This may fail! See the Unicode",
+ "section of ?tikzDevice for more information.")
+ }
+ if (missing(packages)) {packages <- getOption('tikzLatexPackages')}
+ },
+
+ xetex = {
+ if (is.null(getOption('tikzXelatex'))) {
+ stop("Cannot find XeLaTeX! Please check your system ",
+ "configuration or manually provide a value for ",
+ "options(tikzXelatex)")
+ }
+ if (missing(packages)) {packages <- getOption('tikzXelatexPackages')}
+ },
+
+ luatex = {
+ if (is.null(getOption('tikzLualatex'))) {
+ stop("Cannot find LuaLaTeX! Please check your system ",
+ "configuration or manually provide a value for ",
+ "options(tikzLualatex)")
+ }
+ if (missing(packages)) {packages <- getOption('tikzLualatexPackages')}
+ },
+
+ {#ELSE
+ stop('Unsupported TeX engine: ', engine,
+ '\nAvailable choices are:\n',
+ '\tpdftex\n',
+ '\txetex\n',
+ '\tluatex\n')
+ }
+ )
+
+ # Create an object that contains the string and it's
+ # properties.
+ TeXMetrics <- list( type='string', scale=cex, face=face, value=texString,
+ documentDeclaration = documentDeclaration,
+ packages = packages, engine = engine)
+
+
+ # Check to see if we have a width stored in
+ # our dictionary for this string.
+ width <- queryMetricsDictionary( TeXMetrics, verbose = verbose )
+
+ if( width >= 0 ){
+
+ # Positive (and zero) string width means there was a
+ # cached value available. Yay! We're done.
+ return( width )
+
+ }else{
+
+ # Bummer. No width on record for this string.
+ # Call LaTeX and get one.
+ width <- getMetricsFromLatex( TeXMetrics, verbose = verbose )
+
+ if (is.null(width)) {
+ # Something went wrong. Return 0
+ return(0)
+ } else {
+ # Store the width in the dictionary so we don't
+ # have to do this again.
+ storeMetricsInDictionary( TeXMetrics, width )
+
+ # Return the width.
+ return( width )
+ }
+
+ }
+}
+
+
+#' @rdname getLatexStrWidth
+#'
+#' @param charCode an integer that corresponds to a symbol in the ASCII
+#' character table under the Type 1 font encoding. All numeric values are
+#' coerced using \code{as.integer}. Non-numeric values will not be accepted.
+#'
+#' @examples
+#'
+#' # Calculate ascent, descent and width for "A"
+#' getLatexCharMetrics(65)
+#'
+#' @export
+getLatexCharMetrics <-
+function(charCode, cex = 1, face = 1, engine = getOption('tikzDefaultEngine'),
+ documentDeclaration = getOption("tikzDocumentDeclaration"), packages,
+ verbose = interactive())
+{
+
+ # This function is pretty much an exact duplicate of getLatexStrWidth, these
+ # two functions should be generalized and combined.
+ switch(engine,
+ pdftex = {
+ if (missing(packages)) {packages <- getOption('tikzLatexPackages')}
+ },
+
+ xetex = {
+ if (is.null(getOption('tikzXelatex'))) {
+ stop("Cannot find XeLaTeX! Please check your system ",
+ "configuration or manually provide a value for ",
+ "options(tikzXelatex)")
+ }
+ if (missing(packages)) {packages <- getOption('tikzXelatexPackages')}
+ },
+
+ luatex = {
+ if (is.null(getOption('tikzLualatex'))) {
+ stop("Cannot find LuaLaTeX! Please check your system ",
+ "configuration or manually provide a value for ",
+ "options(tikzLualatex)")
+ }
+ if (missing(packages)) {packages <- getOption('tikzLualatexPackages')}
+ },
+
+ {#ELSE
+ stop('Unsupported TeX engine: ', engine,
+ '\nAvailable choices are:\n',
+ '\tpdftex\n',
+ '\txetex\n',
+ '\tluatex\n')
+ }
+ )
+
+ # We must be given an integer character code.
+ if ( !is.numeric(charCode) ) {
+ warning("getLatexCharMetrics only accepts integers!")
+ return(NULL)
+ }
+
+ if ( engine == 'pdftex' && !(charCode > 31 && charCode < 127 ) ) {
+ if (getOption('tikzPdftexWarnUTF')) {
+ warning("pdftex can only generate metrics for character codes ",
+ "between 32 and 126! See the Unicode section of ?tikzDevice ",
+ "for more information.")
+ }
+ return(NULL)
+ }
+
+ # Coerce the charCode to integer in case someone was being funny
+ # and passed a float.
+ #
+ # IMPORTANT: The charCode must be in UTF-8 encoding or else funny business
+ # will likely occur.
+ charCode <- as.integer( charCode )
+
+ # Create an object that contains the character and it's
+ # properties.
+ TeXMetrics <- list( type='char', scale=cex, face=face, value=charCode,
+ documentDeclaration = documentDeclaration,
+ packages = packages, engine = engine)
+
+ # Check to see if we have metrics stored in
+ # our dictionary for this character.
+ metrics <- queryMetricsDictionary( TeXMetrics, verbose = verbose )
+
+ if( all(metrics >= 0) ){
+
+ # The metrics should be a vector of three non negative
+ # numbers.
+ return( metrics )
+
+ }else{
+
+ # Bummer. No metrics on record for this character.
+ # Call LaTeX to obtain them.
+ metrics <- getMetricsFromLatex( TeXMetrics, verbose = verbose )
+
+ if (is.null(metrics)) {
+ # Couldn't get metrics for some reason, return 0
+ return(c(0, 0, 0))
+ } else {
+ # Store the metrics in the dictionary so we don't
+ # have to do this again.
+ storeMetricsInDictionary( TeXMetrics, metrics )
+
+ return( metrics )
+ }
+
+ }
+}
+
+getMetricsFromLatex <-
+function( TeXMetrics, verbose = verbose ){
+
+ if (!verbose) {
+ message <- function(...) invisible()
+ }
+
+ # Reimplementation of the original C function since
+ # the C function causes all kinds of gibberish to
+ # hit the screen when called under Windows and
+ # Linux.
+ #
+ # On both platforms this causes the whole process
+ # of calling LaTeX in order to obtain string width
+ # to take even longer.
+ #
+ # Oh. And Windows couldn't nut up and make it through
+ # the C process so it shit it's self and died.
+
+
+ # Create the TeX file in a temporary directory so
+ # it doesn't clutter anything.
+ texDir <- tempdir()
+ texLog <- file.path(texDir, 'tikzStringWidthCalc.log')
+ texFile <- file.path(texDir, 'tikzStringWidthCalc.tex')
+ if (!file.exists(texFile)) file.create(texFile)
+ texFile <- normalizePath(texFile, '/')
+
+ # Open the TeX file for writing.
+ texIn <- file(texFile, 'w')
+
+ writeLines(getOption("tikzDocumentDeclaration"), texIn)
+
+ # Add extra packages, it wont really matter if the user puts
+ # in duplicate packages or many irrelevant packages since they
+ # mostly wont be used. The packages we do care about are the
+ # font ones. I suppose it is possible that the user could add
+ # some wacky macros that could screw stuff up but lets pretend
+ # that cant happen for now.
+ #
+ # Also, we load the user packages last so the user can override
+ # things if they need to.
+ #
+ # The user MUST load the tikz package here.
+ #
+ # Load important packages for calculating metrics, must use different
+ # packages for (multibyte) unicode characters.
+ writeLines(TeXMetrics$packages, texIn)
+ switch(TeXMetrics$engine,
+ pdftex = {
+ writeLines(getOption('tikzMetricPackages'), texIn)
+ },
+ xetex = {
+ writeLines(getOption('tikzUnicodeMetricPackages'), texIn)
+ },
+ luatex = {
+ writeLines(getOption('tikzUnicodeMetricPackages'), texIn)
+ }
+ )
+
+ writeLines("\\batchmode", texIn)
+
+ # Begin a tikz picture.
+ writeLines("\\begin{document}\n\\begin{tikzpicture}", texIn)
+
+ # Insert the value of cex into the node options.
+ nodeOpts <- paste('\\node[inner sep=0pt, outer sep=0pt, scale=',
+ formatC(TeXMetrics$scale, decimal.mark = '.'), ']', sep = '')
+
+ # Create the node contents depending on the type of metrics
+ # we are after.
+
+ # First, which font face are we using?
+ #
+ # From ?par:
+ #
+ # font
+ #
+ # An integer which specifies which font to use for text. If possible,
+ # device drivers arrange so that 1 corresponds to plain text (the default),
+ # 2 to bold face, 3 to italic and 4 to bold italic. Also, font 5 is expected
+ # to be the symbol font, in Adobe symbol encoding. On some devices font families
+ # can be selected by family to choose different sets of 5 fonts.
+
+ nodeContent <- ''
+ switch( TeXMetrics$face,
+
+ normal = {
+ # We do nothing for font face 1, normal font.
+ },
+
+ bold = {
+ # Using bold, we set in bold *series*
+ nodeContent <- '\\bfseries'
+ },
+
+ italic = {
+ # Using italic, we set in the italic *shape*
+ nodeContent <- '\\itshape'
+ },
+
+ bolditalic = {
+ # With bold italic we set in bold *series* with italic *shape*
+ nodeContent <- '\\bfseries\\itshape'
+ },
+
+ symbol = {
+ # We are currently ignoring R's symbol fonts.
+ }
+
+ ) # End output font face switch.
+
+
+ # Now for the content. For string width we set the whole string in
+ # the node. For character metrics we have an integer corresponding
+ # to a posistion in the ASCII character table- so we use the LaTeX
+ # \char command to translate it to an actual character.
+ switch( TeXMetrics$type,
+
+ string = {
+
+ nodeContent <- paste( nodeContent,TeXMetrics$value )
+
+ },
+
+ char = {
+
+ nodeContent <- paste( nodeContent,'\\char',TeXMetrics$value, sep='' )
+
+ }
+
+ )# End switch for metric type.
+
+ message("Measuring dimensions of: ", nodeContent);
+
+ writeLines( paste( nodeOpts, ' (TeX) {', nodeContent, "};", sep=''), texIn)
+
+ # We calculate width for both characters and strings.
+ writeLines("\\path let \\p1 = ($(TeX.east) - (TeX.west)$),
+ \\n1 = {veclen(\\x1,\\y1)} in (TeX.east) -- (TeX.west)
+ node{ \\typeout{tikzTeXWidth=\\n1} };", texIn)
+
+ # We only want ascent and descent for characters.
+ if( TeXMetrics$type == 'char' ){
+
+ # Calculate the ascent and print it to the log.
+ writeLines("\\path let \\p1 = ($(TeX.north) - (TeX.base)$),
+ \\n1 = {veclen(\\x1,\\y1)} in (TeX.north) -- (TeX.base)
+ node{ \\typeout{tikzTeXAscent=\\n1} };", texIn)
+
+ # Calculate the descent and print it to the log.
+ writeLines("\\path let \\p1 = ($(TeX.base) - (TeX.south)$),
+ \\n1 = {veclen(\\x1,\\y1)} in (TeX.base) -- (TeX.south)
+ node{ \\typeout{tikzTeXDescent=\\n1} };", texIn)
+
+ }
+
+ # Stop before creating output
+ writeLines("\\makeatletter", texIn)
+ writeLines("\\@@end", texIn)
+
+ # Close the LaTeX file, ready to compile
+ close( texIn )
+
+ # Recover the latex command. Use XeLaTeX if the character is not ASCII
+ latexCmd <- switch(TeXMetrics$engine,
+ pdftex = getOption('tikzLatex'),
+ xetex = getOption('tikzXelatex'),
+ luatex = getOption('tikzLualatex'),
+ )
+
+ # Append the batchmode flag to increase LaTeX
+ # efficiency.
+ latexCmd <- paste(shQuote(latexCmd), '-interaction=batchmode', '-halt-on-error',
+ '-output-directory', shQuote(texDir), shQuote(texFile))
+
+ # avoid warnings about non-zero exit status, we know tex exited abnormally
+ # it was designed that way for speed
+ suppressWarnings(silence <- system( latexCmd, intern=T, ignore.stderr=T))
+
+ # Read the contents of the log file.
+ logContents <- readLines( texLog )
+
+ if (TeXMetrics$engine == 'xetex') {
+ # Check to see if XeLaTeX was unable to typeset any Unicode characters.
+ missing_glyphs <- logContents[grep('^\\s*Missing character: There is no',
+ logContents )]
+
+ if (length(missing_glyphs)) {
+ warning('XeLaTeX was unable to calculate metrics for some characters:\n',
+ paste('\t', missing_glyphs, collapse = '\n') )
+
+ # Bail out of the calculation
+ return(NULL)
+ }
+ }
+
+ # Recover width by finding the line containing
+ # tikzTeXWidth in the logfile.
+ match <- logContents[ grep('tikzTeXWidth=', logContents) ]
+
+ # Remove all parts of the string besides the
+ # number.
+ width <- gsub('[=A-Za-z]','',match)
+
+ # complete.cases() checks for NULLs, NAs and NaNs
+ if( length(width) == 0 | any(!complete.cases(width)) ){
+
+ message(paste(readLines(texFile),collapse='\n'))
+ message(paste(readLines(texLog),collapse='\n'))
+ stop('\nTeX was unable to calculate metrics for the following string\n',
+ 'or character:\n\n\t',
+ TeXMetrics$value, '\n\n',
+ 'Common reasons for failure include:\n',
+ ' * The string contains a character which is special to LaTeX unless\n',
+ ' escaped properly, such as % or $.\n',
+ ' * The string makes use of LaTeX commands provided by a package and\n',
+ ' the tikzDevice was not told to load the package.\n\n',
+ 'The contents of the LaTeX log of the aborted run have been printed above,\n',
+ 'it may contain additional details as to why the metric calculation failed.\n'
+ )
+
+ }
+
+ # If we're dealing with a string, we're done.
+ if( TeXMetrics$type == 'string' ){
+
+ return( as.double( width ) )
+
+ }else{
+
+ # For a character, we want ascent and descent too.
+ match <- logContents[ grep('tikzTeXAscent=', logContents) ]
+ ascent <- gsub('[=A-Za-z]','',match)
+
+ match <- logContents[ grep('tikzTeXDescent=', logContents) ]
+ descent <- gsub('[=A-Za-z]','',match)
+
+ return( as.double( c(ascent,descent,width) ) )
+
+ }
+
+}
diff --git a/R/sanitizeTexString.R b/R/sanitizeTexString.R
new file mode 100644
index 0000000..63785f7
--- /dev/null
+++ b/R/sanitizeTexString.R
@@ -0,0 +1,85 @@
+#' Replace LaTeX Special Characters in a String
+#'
+#' This function is used by tikzDevice when \code{sanitize=TRUE} to replace
+#' special LaTeX characters (such as the comment character %) in plotting text
+#' where the user does not have direct control over the generated text.
+#'
+#' \code{sanitizeTexString} searches character by character through a string
+#' replacing each occurrence of a special character contained in
+#' \code{strip[i]} with the corresponding replacement value in
+#' \code{replacement[i]}. tikzDevice calls back this function for every piece
+#' of text when the sanitize option is TRUE. See \code{\link{tikz}} for more
+#' information on the default special characters and replacement values.
+#'
+#' By default, `tikzSanitizeCharacters` replaces the following characters:
+#'
+#' \itemize{
+#' \item \verb{\%}
+#' \item \verb{$}
+#' \item \verb{\}}
+#' \item \verb{\{}
+#' \item \verb{^}
+#' \item \verb{_}
+#' \item \verb{#}
+#' \item \verb{&}
+#' \item \verb{~}
+#' }
+#'
+#' With the contents of `tikzReplacementCharacters`:
+#'
+#' \itemize{
+#' \item \verb{\\\%}
+#' \item \verb{\\$}
+#' \item \verb{\\\}}
+#' \item \verb{\\\{}
+#' \item \verb{\\^{}}
+#' \item \verb{\\_{}}
+#' \item \verb{\\#}
+#' \item \verb{\\&}
+#' \item \verb{\char`\~}
+#' }
+#'
+#' These defaults may be adjusted using the \code{\link{options}} function.
+#'
+#' @param string A character vector of length 1 (a string).
+#' @param strip A character vector of single characters to search for.
+#' @param replacement A character vector of replacement values.
+#'
+#' @return \item{sanitizedString}{A character vector of length 1 with all
+#' special characters replaced.}
+#'
+#' @author Cameron Bracken \email{cameron.bracken@@gmail.com}
+#'
+#' @seealso \code{\link{tikz}}
+#' @keywords character
+#'
+#' @examples
+#'
+#' # Be careful with sanitizing, it may lead to unexpected behavior.
+#' # For example, we may want -1 to be a superscript it gets
+#' # sanitized away with the other default special characters.
+#' # The string appears in LaTeX exactly as shown.
+#' \dontrun{
+#' sanitizeTexString('10\% of 10$ is 10^\{-1\}$')
+#' }
+#'
+#' @export
+sanitizeTexString <- function(string,
+ strip = getOption('tikzSanitizeCharacters'),
+ replacement = getOption('tikzReplacementCharacters')){
+
+ #separate the string into a vector of charaters
+ explode <- strsplit(string,'')[[1]]
+ if(any(is.na(explode))) stop("Unable to sanitize string, you may be trying to pass in an unsupported symbol")
+
+ # Replace each matching character with its replacement characters
+ for(i in 1:length(explode)){
+
+ matches <- (explode[i] == strip)
+ if(any(matches))
+ explode[i] <- paste('{',replacement[which(matches)],'}',sep='')
+
+ }
+ # stick the string back together
+ return(paste(explode,collapse=''))
+}
diff --git a/R/tikz.R b/R/tikz.R
new file mode 100644
index 0000000..3d35124
--- /dev/null
+++ b/R/tikz.R
@@ -0,0 +1,303 @@
+#' TikZ Graphics Device
+#'
+#' \code{tikz} is used to open a R graphics device which supports output in the
+#' TikZ graphics language. TikZ code may be included inside a LaTeX document by
+#' specifying \code{\\usepackage{tikz}} in the document header.
+#'
+#' The TikZ device enables LaTeX-ready output from graphics functions. This is
+#' done by encoding graphics commands using TikZ markup. All text in a graphic
+#' output with \code{tikz} will be typeset by LaTeX and therefore will match
+#' whatever fonts are currently used in the document. This also means that
+#' \strong{LaTeX mathematics can be typeset directly into labels and
+#' annotations}.
+#'
+#' The TikZ device currently supports three modes of output depending on the
+#' value of the parameter \code{standAlone} and \code{bareBones}. If
+#' \code{standAlone} and \code{bareBones} are set to the default value of
+#' \code{FALSE}, the resulting file will only contain graphics output wrapped
+#' in a LaTeX \code{tikzpicture} environment. Since this file is not a
+#' complete LaTeX document, it will need to be included in another LaTeX
+#' document using the \code{\\input} command. For example:
+#' \preformatted{
+#' \\documentclass{article}
+#' \\usepackage{tikz}
+#' \\begin{document}
+#' \\begin{figure}
+#' \\centering
+#' \\input{Rplots.tex}
+#' \\caption{}
+#' \\end{figure}
+#' \\end{document}
+#' }
+#'
+#' When \code{standAlone} is set to \code{TRUE}, the device wraps the
+#' \code{tikzpicture} environment in a complete LaTeX document suitable for
+#' direct compilation. In this mode the \code{preview} package is used to crop
+#' the resulting output to the bounding box of the graphic.
+#'
+#' When \code{bareBones} is set to \code{TRUE}, the output is not wrapped in a
+#' document or a \code{tikzpicture} environment. This is useful for embedding
+#' an generated graphic within an existing TikZ picture.
+#'
+#' In cases where both \code{standAlone} and \code{bareBones} have been set to
+#' \code{TRUE}, the \code{standAlone} option will take precedence.
+#'
+#' When the option \code{symbolicColors} is set to \code{TRUE}, the colors will
+#' be written as symbolic names, e.g. \code{red, gray90} and similar. If the
+#' color is not mapped to a symbolic name in R, the color will be named
+#' \code{XXXXX} when \code{#XXXXXX} is its hexadecimal color. All the color
+#' names will have to be defined in the enclosing document, which is
+#' automatically written if the path of a color file \code{colorFileName} is
+#' set.
+#'
+#' @param file A character string indicating the desired path to the output
+#' file.
+#' @param width The width of the output figure, in \bold{inches}.
+#' @param height The height of the output figure, in \bold{inches}.
+#' @param onefile Should output be directed to separate environments in a
+#' single file (default \code{TRUE}). If \code{FALSE} this option works
+#' exactly like the argument of the same name to \code{\link{pdf}}
+#' (see there for more details).
+#' @param bg The starting background color for the plot.
+#' @param fg The starting foreground color for the plot.
+#' @param pointsize Base pointsize used in the LaTeX document. This option is
+#' only used if a valid pointsize cannot be extracted from the value of
+#' \code{getOption("tikzDocumentDeclaration")}. See the section ``Font Size
+#' Calculations'' in \link{tikzDevice-package} for more details.
+#' @param lwdUnit The number of \code{pt}s in LaTeX that \code{lwd=1} in R is
+#' translated to. Defaults to 0.4 (LaTeX and TikZ default); for compatibility
+#' with R default, please use 72.27/96 (96 pixels in R is 1 inch, which is 72.27
+#' points in TeX).
+#' @param standAlone A logical value indicating whether the output file should
+#' be suitable for direct processing by LaTeX. A value of \code{FALSE}
+#' indicates that the file is intended for inclusion in a larger document.
+#' See \sQuote{Details}.
+#' @param bareBones A logical value. When \code{TRUE} the figure will not be
+#' wrapped in a \code{tikzpicture} environment. This option is useful for
+#' embedding one TikZ picture within another. When \code{TRUE} multipage
+#' output will be drawn on a single page.
+#' @param console Should the output of tikzDevice be directed to the R console
+#' (default \code{FALSE}). This is useful for dumping tikz output directly into a
+#' LaTeX document via \code{\link{sink}}. If TRUE, the \code{file} argument
+#' is ignored. Setting \code{file=''} is equivalent to setting
+#' \code{console=TRUE}.
+#' @param sanitize Should special latex characters be replaced (Default FALSE).
+#' See the section ``Options That Affect Package Behavior'' for which
+#' characters are replaced.
+#' @param engine a string specifying which TeX engine to use. Possible values
+#' are 'pdftex', 'xetex' and 'luatex'. See the Unicode section of
+#' \link{tikzDevice-package} for details.
+#' @param documentDeclaration See the sections ``Options That Affect Package
+#' Behavior'' and ``Font Size Calculations'' of \link{tikzDevice-package}
+#' for more details.
+#' @param packages See the section ``Options That Affect Package Behavior'' of
+#' \link{tikzDevice-package}.
+#' @param footer See the section ``Options That Affect Package Behavior'' of
+#' \link{tikzDevice-package}.
+#' @param symbolicColors A logical value indicating whether colors are written
+#' as RGB values or as symbolic names in which case the need to be defined in
+#' the LaTeX document. These definitions can be generated with the following
+#' \code{colorFileName} parameter. See also the section ``Options That Affect
+#' Package Behavior'' of \link{tikzDevice-package}.
+#' @param colorFileName a character string indicating where the color map for
+#' symbolic colors is to be stored. It can contain a placeholder \code{\%s}
+#' where the tikz filename is inserted. If the string is empty, no file is
+#' written.
+#' @param maxSymbolicColors an integer number indicating the maximal number
+#' of distinct colors to write symbolically. Any excess color will be defined
+#' as if \code{symbolicColors} was set to \code{FALSE}. See also the section
+#' ``Options That Affect' Package Behavior'' of \link{tikzDevice-package}.
+#' @param timestamp A logical value indicating whether a timestamp is written
+#' to the TeX file.
+#' @param verbose A logical value indicating whether diagnostic messages are
+#' printed when measuring dimensions of strings. Defaults to \code{TRUE} in
+#' interactive mode only, to \code{FALSE} otherwise.
+#'
+#' @return \code{tikz()} returns no values.
+#'
+#' @note To compile the output of \code{tikz} a working installation of LaTeX
+#' and PGF is needed. Current releases of the TikZ package are available
+#' from \url{http://www.ctan.org}. The package may also be installed through
+#' the MikTeX package manager on Windows or using the TeX Live package
+#' manager, \code{tlmgr}, on Unix/Linux/OS X. The TeX Live package manager
+#' will only be installed by default for TeX Live distributions dated 2008
+#' and later. Both bleeding-edge and release versions of TikZ may be obtained
+#' from the project website hosted at
+#' \url{http://sourceforge.net/projects/pgf/}.
+#'
+#' Multiple plots will be placed as separate environments in the output file.
+#'
+#' @author Charlie Sharpsteen \email{source@@sharpsteen.net} and Cameron
+#' Bracken \email{cameron.bracken@@gmail.com}
+#'
+#' @seealso \code{\link{pictex}}, \code{\link{getLatexCharMetrics}},
+#' \code{\link{getLatexStrWidth}}, \code{\link{setTikzDefaults}},
+#' \code{\link{tikzAnnotate}}, \code{\link{sanitizeTexString}}
+#' @references The TikZ and PGF Packages: Manual for version 2.00\cr
+#' \url{http://sourceforge.net/projects/pgf}\cr Till Tantau, February 20,
+#' 2008
+#' @keywords device
+#'
+#' @examples
+#'
+#' \dontrun{
+#'
+#' ## Example 1 ###################################
+#' #Set up temporary work directory
+#' td <- tempdir()
+#' tf <- file.path(td,'example1.tex')
+#' oldwd <- getwd()
+#' setwd(td)
+#'
+#' # Minimal plot
+#' tikz(tf,standAlone=TRUE)
+#' plot(1)
+#' dev.off()
+#'
+#' # View the output
+#' tools::texi2dvi(tf,pdf=T)
+#' system(paste(getOption('pdfviewer'),file.path(td,'example1.pdf')))
+#' setwd(oldwd)
+#' ################################################
+#'
+#' ## Example 2 ###################################
+#' #Set up temporary work directory
+#' td <- tempdir()
+#' tf <- file.path(td,'example2.tex')
+#' oldwd <- getwd()
+#' setwd(td)
+#'
+#' #LaTeX math symbol names
+#' syms <-c('alpha','theta','tau','beta','vartheta','pi','upsilon',
+#' 'gamma','gamma','varpi','phi','delta','kappa','rho',
+#' 'varphi','epsilon','lambda','varrho','chi','varepsilon',
+#' 'mu','sigma','psi','zeta','nu','varsigma','omega','eta',
+#' 'xi','Gamma','Lambda','Sigma','Psi','Delta','Xi','Upsilon',
+#' 'Omega','Theta','Pi','Phi')
+#' x <- rnorm(length(syms))
+#' y <- rnorm(length(syms))
+#'
+#' tikz(tf,standAlone=TRUE)
+#' plot(-2:2, -2:2, type = "n", axes=F,
+#' xlab='', ylab='', main='TikZ Device Math Example')
+#' text(x,y,paste('\\\\Large$\\\\',syms,'$',sep=''))
+#' dev.off()
+#'
+#' #View the output
+#' tools::texi2dvi(tf,pdf=TRUE)
+#' system(paste(getOption('pdfviewer'),file.path(td,'example2.pdf')))
+#' setwd(oldwd)
+#' ################################################
+#'
+#' ## Example 3 ###################################
+#' #Set up temporary work directory
+#' td <- tempdir()
+#' tf <- file.path(td,'example3.tex')
+#' oldwd <- getwd()
+#' setwd(td)
+#'
+#' tikz(tf,standAlone=TRUE)
+#' plot(-2:2, -2:2, type = "n", axes=F, xlab='', ylab='', main='Random Circles')
+#' points(rnorm(50), rnorm(50), pch=21,
+#' bg=rainbow(50,alpha=.5), cex=10)
+#' dev.off()
+#'
+#' #View the output
+#' tools::texi2dvi(tf,pdf=TRUE)
+#' system(paste(getOption('pdfviewer'),file.path(td,'example3.pdf')))
+#' setwd(oldwd)
+#' ################################################
+#' }
+#'
+#' @export
+#' @useDynLib tikzDevice TikZ_StartDevice
+tikz <-
+function (file = ifelse(onefile, "./Rplots.tex", "./Rplot%03d.tex"),
+ width = 7, height = 7, onefile = TRUE,
+ bg="transparent", fg="black", pointsize = 10, lwdUnit = getOption("tikzLwdUnit"),
+ standAlone = FALSE, bareBones = FALSE, console = FALSE, sanitize = FALSE,
+ engine = getOption("tikzDefaultEngine"),
+ documentDeclaration = getOption("tikzDocumentDeclaration"),
+ packages,
+ footer = getOption("tikzFooter"),
+ symbolicColors = getOption("tikzSymbolicColors"), colorFileName = "%s_colors.tex",
+ maxSymbolicColors = getOption("tikzMaxSymbolicColors"),
+ timestamp = TRUE,
+ verbose = interactive()
+){
+
+ tryCatch({
+ # Ok, this sucks. We copied the function signature of pdf() and got `file`
+ # as an argument to our function. We should have copied png() and used
+ # `filename`.
+
+ # file_path_as_absolute can give us the absolute path to the output
+ # file---but it has to exist first. So, we use file() to "touch" the
+ # path.
+ touch_file <- suppressWarnings(file(file, 'w'))
+ close(touch_file)
+
+ file <- tools::file_path_as_absolute(file)
+ },
+ error = function(e) {
+ stop(simpleError(paste(
+ "Cannot create:\n\t", file,
+ "\nBecause the directory does not exist or is not writable."
+ )))
+ })
+
+ # remove the file if we are outputting to multiple files since the file
+ # name will get changed in the C code
+ if( !onefile ) file.remove(file)
+
+ # Determine which TeX engine is being used.
+ switch(engine,
+ pdftex = {
+ engine <- 1L # In the C routines, a integer value of 1 means pdftex
+ if (missing(packages)) {packages <- getOption('tikzLatexPackages')}
+ },
+ xetex = {
+ engine <- 2L
+ if (missing(packages)) {packages <- getOption('tikzXelatexPackages')}
+ },
+ luatex = {
+ engine <- 3L
+ if (missing(packages)) {packages <- getOption('tikzLualatexPackages')}
+ },
+ {#ELSE
+ stop('Unsupported TeX engine: ', engine,
+ '\nAvailable choices are:\n',
+ '\tpdftex\n',
+ '\txetex\n',
+ '\tluatex\n')
+ })
+
+ # Ensure the standAlone option will trump the bareBones option.
+ if( standAlone ) { bareBones = FALSE }
+ if( footer != getOption("tikzFooter") && !standAlone)
+ warning( "Footers are ignored when standAlone is set to FALSE" )
+
+ # Extract the document pointsize from the documentDeclaration
+ baseSize <- getDocumentPointsize( documentDeclaration )
+
+ # If a pointsize was not found, we use the value of the pointsize
+ # argument.
+ if( is.na( baseSize ) ){ baseSize <- pointsize }
+
+ # Collapse the character vectors into a single string
+ # which is easier to work with in C
+ documentDeclaration <-
+ paste( paste(documentDeclaration, collapse='\n'), collapse='\n')
+ packages <- paste( paste( packages, collapse='\n'), collapse='\n')
+ footer <- paste( paste( footer,collapse='\n'), collapse='\n')
+ if(maxSymbolicColors < 0)
+ stop("maxSymbolicColors needs to be nonnegative")
+
+ .External(TikZ_StartDevice, file, width, height, onefile, bg, fg, baseSize, lwdUnit,
+ standAlone, bareBones, documentDeclaration, packages, footer, console,
+ sanitize, engine, symbolicColors, colorFileName, maxSymbolicColors,
+ timestamp, verbose)
+
+ invisible()
+
+}
diff --git a/R/tikzAnnotate.R b/R/tikzAnnotate.R
new file mode 100644
index 0000000..0e175b9
--- /dev/null
+++ b/R/tikzAnnotate.R
@@ -0,0 +1,415 @@
+#' Convert grid coordinates to device coordinates
+#'
+#' This function converts a coordinate pair specifying a location in a
+#' grid \code{\link{viewport}} in grid units to a coordinate pair specifying a
+#' location in device units relative to the lower left corner of the plotting
+#' canvas.
+#'
+#' @param x x coordinate.
+#' @param y y coordinate. If no values are given for \code{x} and \code{y}, the
+#' location of the lower-left corner of the current viewport will be
+#' calculated.
+#' @param units Character string indicating the units of \code{x} and \code{y}.
+#' See the \code{\link{unit}} function for acceptable unit types.
+#'
+#' @return A tuple of coordinates in device units.
+#'
+#' @author Charlie Sharpsteen \email{source@@sharpsteen.net}
+#'
+#' @keywords graphics grid conversion units
+#' @seealso
+#' \code{\link{unit}}
+#' \code{\link{viewport}}
+#' \code{\link{convertX}}
+#' \code{\link{convertY}}
+#' \code{\link{current.transform}}
+#'
+#'
+#' @export
+#' @importFrom grid convertX convertY current.transform unit
+gridToDevice <- function(x = 0, y = 0, units = 'native') {
+ # Converts a coordinate pair from the current viewport to an "absolute
+ # location" measured in device units from the lower left corner. This is done
+ # by first casting to inches in the current viewport and then using the
+ # current.transform() matric to obtain inches in the device canvas.
+ x <- convertX(unit(x, units), unitTo = 'inches', valueOnly = TRUE)
+ y <- convertY(unit(y, units), unitTo = 'inches', valueOnly = TRUE)
+
+ transCoords <- c(x,y,1) %*% current.transform()
+ transCoords <- (transCoords / transCoords[3])
+
+ return(
+ # Finally, cast from inches to device coordinates (which are TeX points for
+ # the tikzDevice)
+ c(
+ grconvertX(transCoords[1], from = 'inches', to = 'device'),
+ grconvertY(transCoords[2], from = 'inches', to = 'device')
+ )
+ )
+
+}
+
+
+#-------------------------------------------------------------------------------
+# Annotation of Base Graphics
+#-------------------------------------------------------------------------------
+
+#' Add Custom TikZ Code to an Active Device
+#'
+#' These functions allow custom (LaTeX) commands to be added to the output of an
+#' active tikzDevice.
+#'
+#' \code{tikzAnnotate} is intended to allow the insertion of arbitrary TikZ
+#' commands into the output stream of a graphic. For LaTeX commands that
+#' reference specific locations in an R plot, coordinates must be specified in
+#' "device units" which for \code{tikz} output are TeX points relative to the
+#' lower left corner of the device canvas. Functions such as
+#' \code{\link{grconvertX}} and \code{\link{gridToDevice}} can help make the
+#' necessary conversions for base and grid graphics. The \code{tikzNode} and
+#' \code{tikzCoord} functions automatically perform unit conversions acording
+#' the the value of their \code{units} parameters.
+#'
+#' \code{tikzNode} is a wrapper for \code{tikzAnnotate} that inserts TikZ
+#' \code{\\node} or \code{\\coordinates} commands into the output. The
+#' difference between a node and a coordinate is the presence of a
+#' \code{content} section that can contain arbitrary LaTeX text. This is
+#' useful for adding textual annotations at specific locations in a TikZ
+#' graphic. The \code{tikzCoord} function is a wrapper for \code{tikzNode}
+#' that simplifies the task of inserting named coordinates.
+#'
+#' Additionally, the \code{tikzAnnotateGrob}, \code{tikzNodeGrob} and
+#' \code{tikzCoordGrob} functions are supplied for creating grid objects
+#' or "\code{\link{grob}}s" that can be used in Grid graphics. High level
+#' wrapper functions \code{grid.tikzAnnotate}, \code{grid.tikzNode} and
+#' \code{grid.tikzCoord} are also supplied which creat and render a \code{grob}
+#' in one step.
+#'
+#' See the TikZ Device vignette for more information and examples and the
+#' TikZ manual for the definitive reference on what is possible with nodes.
+#'
+#' @param annotation A character vector, one element per line to be added to
+#' the open tikz device.
+#'
+#' @param checkstate A logical, whether to "flush" the device state prior to
+#' writing the \code{annotation}.
+#'
+#' @return Nothing returned.
+#'
+#' @author Cameron Bracken <cameron.bracken@@gmail.com> and Charlie Sharpsteen
+#' \email{source@@sharpsteen.net}
+#'
+#'
+#' @examples
+#'
+#' \dontrun{
+#'
+#' ### Example 1: Annotations in Base Graphics
+#' # Load some additional TikZ libraries
+#' tikz("annotation.tex",width=4,height=4,
+#' packages = c(getOption('tikzLatexPackages'),
+#' "\\usetikzlibrary{decorations.pathreplacing}",
+#' "\\usetikzlibrary{positioning}",
+#' "\\usetikzlibrary{shapes.arrows,shapes.symbols}")
+#' )
+#'
+#' p <- rgamma (300 ,1)
+#' outliers <- which( p > quantile(p,.75)+1.5*IQR(p) )
+#' boxplot(p)
+#'
+#' # Add named coordinates that other TikZ commands can hook onto
+#' tikzCoord(1, min(p[outliers]), 'min outlier')
+#' tikzCoord(1, max(p[outliers]), 'max outlier')
+#'
+#' # Use tikzAnnotate to insert arbitrary code, such as drawing a
+#' # fancy path between min outlier and max outlier.
+#' tikzAnnotate(c("\\draw[very thick,red,",
+#' # Turn the path into a brace.
+#' 'decorate,decoration={brace,amplitude=12pt},',
+#' # Shift it 1em to the left of the coordinates
+#' 'transform canvas={xshift=-1em}]',
+#' '(min outlier) --',
+#' # Add a node with some text in the middle of the path
+#' 'node[single arrow,anchor=tip,fill=white,draw=green,',
+#' 'left=14pt,text width=0.70in,align=center]',
+#' '{Holy Outliers Batman!}', '(max outlier);'))
+#'
+#' # tikzNode can be used to place nodes with customized options and content
+#' tikzNode(
+#' opts='starburst,fill=green,draw=blue,very thick,right=of max outlier',
+#' content='Wow!'
+#' )
+#'
+#' dev.off()
+#'
+#'
+#' ### Example 2: Annotations in Grid Graphics
+#' library(grid)
+#'
+#' tikz("grid_annotation.tex",width=4,height=4,
+#' packages = c(getOption('tikzLatexPackages'),
+#' "\\usetikzlibrary{shapes.callouts}")
+#' )
+#'
+#' pushViewport(plotViewport())
+#' pushViewport(dataViewport(1:10, 1:10))
+#'
+#' grid.rect()
+#' grid.xaxis()
+#' grid.yaxis()
+#' grid.points(1:10, 1:10)
+#'
+#' for ( i in seq(2,8,2) ){
+#' grid.tikzNode(i,i,opts='ellipse callout,draw,anchor=pointer',content=i)
+#' }
+#'
+#' dev.off()
+#'
+#' }
+#'
+#'
+#' @keywords tikz device annotation
+#' @seealso
+#' \code{\link{grconvertX}}
+#' \code{\link{grconvertY}}
+#' \code{\link{gridToDevice}}
+#' \code{\link{unit}}
+#' \code{\link{tikz}}
+#'
+#' @useDynLib tikzDevice TikZ_Annotate
+#' @export
+tikzAnnotate <-
+function (annotation, checkstate = TRUE)
+{
+
+ if (!isTikzDevice()){
+ stop("The active device is not a tikz device, please start a tikz device to use this function. See ?tikz.")
+ }
+
+ .C(TikZ_Annotate, as.character(annotation),
+ as.integer(length(annotation)), as.logical(checkstate))
+
+ invisible()
+}
+
+#' @rdname tikzAnnotate
+#'
+#' @param x numeric, x location for a named coordinate in user coordinates
+#' @param y numeric, y location for a named coordinate in user coordinates
+#' @param opts A character string that will be used as options for a \code{node}.
+#' See the "Nodes and Edges" section of the TikZ manual for complete details.
+#' @param name Optional character string that will be used as a name for a
+#' \code{coordinate} or \code{node}. Other TikZ commands can use this
+#' name to refer to a location in a graphic.
+#' @param content A character string that will be used as the content to be displayed
+#' inside of a \code{node}. If left as \code{NULL} a \code{coordinate} will be
+#' created instead of a \code{node}. If a \code{node} with empty content is truely
+#' desired, pass an empty string \code{""}.
+#' @param units Character string specifying the unit system associated with
+#' \code{x} and \code{y}. See \code{\link{grconvertX}} for acceptable
+#' units in base graphics and \code{\link{unit}} for acceptable
+#' units in grid graphics.
+#'
+#' @export
+tikzNode <- function(
+ x = NULL, y = NULL,
+ opts = NULL,
+ name = NULL, content = NULL,
+ units = 'user'
+) {
+ # If there is no node content, we create a coordinate.
+ node_string <- ifelse(is.null(content), '\\coordinate', '\\node')
+
+ # Process the other components.
+ if ( !is.null(opts) ) {
+ node_string <- paste(node_string, '[', opts, ']', sep = '')
+ }
+ if ( !is.null(name) ) {
+ # Ensure we got a character.
+ if ( !is.character(name) ) {
+ stop( "The coordinate name must be a character!" )
+ }
+
+ node_string <- paste(node_string, ' (', name, ')', sep = '')
+ }
+ if ( !is.null(x) && !is.null(y) ) {
+ # For now, we demand that x and y be scalar values.
+ # TODO: Vectorize this function
+ if ( length(x) > 1 ) {
+ warning("More than one X coordinate specified. Only the first will be used!")
+ x <- x[1]
+ }
+
+ if ( length(y) > 1 ) {
+ warning("More than one Y coordinate specified. Only the first will be used!")
+ y <- y[1]
+ }
+
+ # Convert coordinates to device coordinates.
+ if ( units != 'device' ) {
+ x <- grconvertX(x, from = units, to = 'device')
+ y <- grconvertY(y, from = units, to = 'device')
+ }
+
+ node_string <- paste(node_string,
+ ' at (', round(x,2), ',', round(y,2), ')', sep = '')
+ }
+ if ( !is.null(content) ) {
+ node_string <- paste(node_string, ' {', content, '}', sep = '')
+ }
+
+ # Use tikzAnnotate() to add a coordinate.
+ tikzAnnotate(paste(node_string, ';', sep = ''))
+
+}
+
+
+#' @rdname tikzAnnotate
+#' @export
+tikzCoord <- function( x, y, name, units = 'user') {
+
+ tikzNode(x = x, y = y, name = name, units = units)
+
+}
+
+
+#-------------------------------------------------------------------------------
+# Annotation of Grid Graphics
+#
+# These functions are merely wrappers that call the base graphics functions in
+# the end.
+#-------------------------------------------------------------------------------
+
+# Constructors for grid objects (grobs)
+#--------------------------------------
+
+#' @rdname tikzAnnotate
+#' @importFrom grid grob
+#' @export
+tikzAnnotateGrob <- function(annotation) {
+
+ grob(annotation = annotation, cl = 'tikz_annotation')
+
+}
+
+
+#' @rdname tikzAnnotate
+#' @importFrom grid grob
+#' @export
+tikzNodeGrob <- function(
+ x = NULL, y = NULL,
+ opts = NULL, name = NULL,
+ content = NULL,
+ units = 'native'
+) {
+
+ grob(x = x, y = y, opts = opts, coord_name = name, content = content,
+ units = units, cl = 'tikz_node')
+
+}
+
+
+#' @rdname tikzAnnotate
+#' @importFrom grid grob
+#' @export
+tikzCoordGrob <- function(x, y, name, units = 'native') {
+
+ grob(x = x, y = y, coord_name = name, units = units, cl = 'tikz_coord')
+
+}
+
+# Grid wrapper functions
+#-----------------------
+
+#' @rdname tikzAnnotate
+#'
+#' @param draw A logical value indicating whether graphics output should be
+#' produced.
+#'
+#' @importFrom grid grid.draw
+#' @export
+grid.tikzAnnotate <- function(annotation, draw = TRUE) {
+
+ annotate_grob <- tikzAnnotateGrob(annotation)
+ if ( draw ) { grid.draw(annotate_grob) }
+
+ invisible( annotate_grob )
+
+}
+
+
+#' @rdname tikzAnnotate
+#' @importFrom grid grid.draw
+#' @export
+grid.tikzNode <- function(
+ x = NULL, y = NULL,
+ opts = NULL, name = NULL,
+ content = NULL,
+ units = 'native',
+ draw = TRUE
+) {
+
+ node_grob <- tikzNodeGrob(
+ x = x, y = y,
+ opts = opts, name = name, content = content,
+ units = units
+ )
+ if (draw) { grid.draw(node_grob) }
+
+ invisible(node_grob)
+
+}
+
+
+#' @rdname tikzAnnotate
+#' @importFrom grid grid.draw
+#' @export
+grid.tikzCoord <- function(x, y, name, units = 'native', draw = TRUE) {
+
+ coord_grob <- tikzCoordGrob(x = x, y = y, name = name, units = units)
+ if (draw) { grid.draw(coord_grob) }
+
+ invisible(coord_grob)
+
+}
+
+# Grid execution
+#---------------
+# These S3 methods get executed when TikZ annotation grobs get drawn to a
+# device. They handle the actual "drawing" of the annotations by calling to the
+# base graphics functions.
+
+if ('roxygen2' %in% loadedNamespaces()) do.call(library, list('grid'))
+
+#' @importFrom grid drawDetails
+#' @export
+drawDetails.tikz_annotation <- function(x, recording) {
+
+ tikzAnnotate(x$annotation)
+
+}
+
+
+#' @importFrom grid drawDetails
+#' @export
+drawDetails.tikz_node <- function(x, recording) {
+
+ if ( is.null(x$x) && is.null(x$y) ) {
+ coords <- c(NULL, NULL)
+ } else {
+ coords <- gridToDevice(x$x, x$y, x$units)
+ }
+
+ tikzNode(coords[1], coords[2], x$opts,
+ x$coord_name, x$content, units = 'device')
+
+}
+
+
+#' @importFrom grid drawDetails
+#' @export
+drawDetails.tikz_coord <- function(x, recording) {
+
+ coords <- gridToDevice(x$x, x$y, x$units)
+ tikzCoord(coords[1], coords[2], x$coord_name, units = 'device')
+
+}
diff --git a/R/tikzDevice-package.R b/R/tikzDevice-package.R
new file mode 100644
index 0000000..bbd865b
--- /dev/null
+++ b/R/tikzDevice-package.R
@@ -0,0 +1,132 @@
+#' Support for native LaTeX output of R graphics
+#'
+#' The tikzDevice package implements the \code{\link{tikz}} ouput device which
+#' generates R graphics in a LaTeX friendly format. LaTeX handles the
+#' typesetting of all text in graphics generated by \code{tikz}. This allows for
+#' seamless integration between these graphics and documents that are also being
+#' typeset by LaTeX. Using LaTeX to generate graph text also means that
+#' \strong{LaTeX mathematics can be typeset directly into labels and
+#' annotations}.
+#'
+#' @name tikzDevice-package
+#' @aliases tikzDevice-package tikzDevice
+#' @docType package
+#' @section Options That Affect Package Behavior: The \pkg{tikzDevice} package
+#' is currently influenced by a number of global options that may be set in
+#' scripts, from the console or in a \code{.Rprofile} file. All of the options
+#' can be set by using \code{options(<option> = <value>)}. These options
+#' allow for the use of custom \code{documentclass} declarations, LaTeX
+#' packages, and typesetting engines (e.g. XeLaTeX or LuaLaTeX). The defaults,
+#' if are any for a given option, are shown below the description. The global
+#' options are:
+#'
+#' \describe{
+#'
+#' \item{\code{tikzDefaultEngine}}{ Specifies which typesetting engine
+#' functions in the tikzDevice package will prefer. Current possible values
+#' are \code{pdftex}, \code{xetex} or \code{luatex}. Respectively, these
+#' values trigger the use of the \code{pdflatex}, \code{xelatex} and
+#' \code{lualatex} compilers. }
+#'
+#' \item{\code{tikzLatex}}{ Specifies the location of the LaTeX compiler to be
+#' used by \pkg{tikzDevice}. Setting this option may help the package locate a
+#' missing compiler. The default is searched for when the package is loaded,
+#' otherwise it can be set manually. This option may be set as follows:
+#' \code{options( tikzLatex = '/path/to/latex/compiler' )}. }
+#'
+#' \item{\code{tikzXelatex}}{ Functions similar to \code{tikzLatex}, except
+#' this option specifies the location of the XeLaTeX compiler. }
+#'
+#' \item{\code{tikzLualatex}}{ Functions similar to \code{tikzLatex}, except
+#' this option specifies the location of the LuaLaTeX compiler. }
+#'
+#' \item{\code{tikzMetricsDictionary}}{ When using the graphics device
+#' provided by \pkg{tikzDevice}, you may notice that appears to ``lag" or
+#' ``hang" when commands such as \code{plot()} are executed. This is because
+#' the device must query the LaTeX compiler for string widths and font
+#' metrics. For a normal plot, this may happen dozens or hundreds of times-
+#' hence becomes unresponsive for a while. The good news is that the
+#' \code{\link{tikz}} code is designed to cache the results of these
+#' computations so they need only be performed once for each string or
+#' character. By default, these values are stored in a temporary cache file
+#' which is deleted when is shut down. A location for a permanent cache file
+#' may be specified by setting the value of \code{tikzMetricsDictionary} in
+#' \code{.Rprofile} with \code{options(tikzMetricsDictionary =
+#' '/path/to/dictionary/location')}. }
+#'
+#' \item{\code{tikzDocumentDeclaration}}{ A string. The LaTeX documentclass
+#' declaration used in output files when \code{standAlone == TRUE}.
+#' \code{tikzDocumentDeclaration} also influences the calculation of font
+#' metrics. The default value is: \code{options(tikzDocumentDeclaration =
+#' "\\documentclass[10pt]{article}")} }
+#'
+#' \item{\code{tikzLatexPackages}}{ A character vector. These are the packages
+#' which are included when using the \code{pdftex} engine and
+#' \code{\link{tikz}} is used with the the \code{standAlone} option as well as
+#' when font metrics are calculated. }
+#'
+#' \item{\code{tikzXelatexPackages}}{ This option works like
+#' \code{tikzLatexPackages}, except is is used when the \code{xetex} engine is
+#' in use. }
+#'
+#' \item{\code{tikzLualatexPackages}}{ This option works like
+#' \code{tikzXelatexPackages}, except is is used when the \code{luatex} engine
+#' is in use. }
+#'
+#' \item{\code{tikzFooter}}{ A character vector. The footer to be used only
+#' when \code{standAlone==TRUE}. }
+#'
+#' \item{\code{tikzMetricPackages}}{ A character vector. These are the
+#' packages which are additionally loaded when doing font metric calculations.
+#' As you see below, the font encoding is set to Type 1. This is very
+#' important so that character codes of LaTeX and match up. The default value
+#' is: \code{options(tikzMetricPackages = c( "\\usepackage[utf8]{inputenc}",
+#' "\\usepackage[T1]{fontenc}", "\\usetikzlibrary{calc}" ))} }
+#'
+#' \item{\code{tikzUnicodeMetricPackages}}{ This vector is used when font
+#' metric calculations are performed using the \code{xetex} or \code{luatex}
+#' engines. It should have the same contents as \code{tikzMetricPackages} with
+#' the addition of the \code{fontspec} and \code{xunicode} packages. }
+#'
+#' \item{\code{tikzSanitizeCharacters}}{ A character vector of special latex
+#' characters to replace. These values should correspond to the replacement
+#' values from the \code{tikzReplacementCharacters} option. See
+#' \code{\link{sanitizeTexString}} for more details. }
+#'
+#' \item{\code{tikzReplacementCharacters}}{ A character vector of replacements
+#' for special latex characters. These values should correspond to the values
+#' from the \code{tikzSanitizeCharacters} option. }
+#'
+#' \item{\code{tikzLwdUnit}}{ A numeric that denotes the number of \code{pt}s in LaTeX that \code{lwd=1} in R is
+#' translated to. Defaults to 0.4 (LaTeX and TikZ default); for compatibility
+#' with R default, please use 72.27/96 (96 pixels in R is 1 inch, which is 72.27
+#' points in TeX).}
+#'
+#' \item{\code{tikzPdftexWarnUTF}}{ A \code{TRUE/FALSE} value that controls
+#' whether warnings are printed if Unicode characters are sent to a device
+#' using the \code{pdftex} engine. }
+#'
+#' \item{\code{tikzSymbolicColors}}{ A logical value indicating whether colors
+#' are written as RGB values or as symbolic names in which case the need to be
+#' defined in the LaTeX document. }
+#'
+#' \item{\code{tikzMaxSymbolicColors}}{ an integer number indicating the
+#' maximal number of distinct colors to write symbolically. Any excess color
+#' will be defined as if \code{symbolicColors} was set to \code{FALSE}.} }
+#'
+#' Default values for all options may be viewed or restored using the
+#' \code{\link{setTikzDefaults}} function.
+#' @author See \code{packageDescription("tikzDevice")}.
+#'
+#' Submit bug reports to: \url{https://github.com/yihui/tikzDevice/issues}
+#' @seealso \code{\link{tikz}}
+#' @references The TikZ and PGF Packages: Manual for version 2.00\cr
+#' \url{http://sourceforge.net/projects/pgf}\cr Till Tanatu, February 20, 2008
+#' @keywords package
+NULL
+
+#' @importFrom grDevices as.raster dev.cur dev.list dev.off png
+#' @importFrom graphics grconvertX grconvertY par plot.new rasterImage
+#' @importFrom stats complete.cases
+#' @importFrom utils packageVersion
+NULL
diff --git a/R/tikzInternal.R b/R/tikzInternal.R
new file mode 100644
index 0000000..02ad35f
--- /dev/null
+++ b/R/tikzInternal.R
@@ -0,0 +1,29 @@
+# These are unexported functions that are called by the C routines of the tikz
+# device to execute tasks that are difficult to do at the C level.
+
+getDateStampForTikz <- function(){
+
+ # This function retrieves the current date stamp using
+ # sys.time() and formats it to a string. This function
+ # is used by the C routine Print_TikZ_Header to add
+ # date stamps to output files.
+
+ return( strftime( Sys.time() ) )
+
+}
+
+getTikzDeviceVersion <- function() {
+ as.character(packageVersion('tikzDevice'))
+}
+
+tikz_writeRaster <- function(fileName, rasterCount, nativeRaster) {
+ raster_file <- paste0(
+ tools::file_path_sans_ext(fileName),
+ '_ras', rasterCount, '.png')
+
+ png::writePNG(nativeRaster, raster_file)
+
+ return(
+ basename(tools::file_path_sans_ext(raster_file))
+ )
+}
diff --git a/R/zzz.R b/R/zzz.R
new file mode 100644
index 0000000..68d6143
--- /dev/null
+++ b/R/zzz.R
@@ -0,0 +1,96 @@
+.onLoad <-
+function(libname, pkgname) {
+
+ # Ensure options are set.
+ setTikzDefaults( overwrite = FALSE )
+
+ # Perform a search for executable TeX compilers. R options, environment
+ # variables and common paths will be checked. If PdfLaTeX can not be found,
+ # loading of this package will be aborted as a LaTeX compiler is required in
+ # order to determine string metrics. Other compilers, such as XeLaTeX, are
+ # optional.
+ foundLatex <- FALSE
+ foundXelatex <- FALSE
+ foundLualatex <- FALSE
+
+ latexLocs <- list(
+ OPTION('tikzLatex'),
+ ENV_VAR('R_LATEXCMD'),
+ ENV_VAR('R_PDFLATEXCMD'),
+ OPTION('latexcmd'),
+ PATH('pdflatex'),
+ PATH('latex')
+ )
+
+ # Only check for xelatex and lualatex in the options and the PATH variable
+ # since there are no R environment variables for these compilers.
+ xelatexLocs <- list(
+ OPTION('tikzXelatex'),
+ PATH('xelatex')
+ )
+
+ lualatexLocs <- list(
+ OPTION('tikzLualatex'),
+ PATH('lualatex')
+ )
+
+ # Non-Windows users are likely to use some derivative of TeX Live. This next
+ # test primarily covers the fact that R.app does not include `/usr/texbin` on
+ # the search path on OS X.
+ if( .Platform[['OS.type']] == 'unix' ){
+ # Using explicit list insertion because the `c` function drops attributes
+ # and thus destroys S3 objects. Writing 3 new class methods for PATH,
+ # OBJECT and ENV_VAR is just overkill.
+ latexLocs[[length(latexLocs) + 1]] <- PATH('/usr/texbin/pdflatex')
+ xelatexLocs[[length(xelatexLocs) + 1]] <- PATH('/usr/texbin/xelatex')
+ lualatexLocs[[length(lualatexLocs) + 1]] <- PATH('/usr/texbin/lualatex')
+ }
+
+ for ( latexPath in latexLocs ) {
+ if ( isExecutable(latexPath) ) {
+ foundLatex <- TRUE
+ options(tikzLatex = as.character(latexPath), tikzLatexDefault = as.character(latexPath))
+ break
+ }
+ }
+
+ for( xelatexPath in xelatexLocs ) {
+ if( isExecutable(xelatexPath) ) {
+ foundXelatex <- TRUE
+ options(tikzXelatex = as.character(xelatexPath), tikzXelatexDefault = as.character(xelatexPath))
+ break
+ }
+ }
+
+ for( lualatexPath in lualatexLocs ) {
+ if( isExecutable(lualatexPath) ) {
+ foundLualatex <- TRUE
+ options(tikzLualatex = as.character(lualatexPath), tikzLualatexDefault = as.character(lualatexPath))
+ break
+ }
+ }
+
+ if (!foundLatex ) {
+ warning("\n\ntikzDevice: No appropriate LaTeX compiler could be found.\n",
+ "Access to LaTeX is required in order for the TikZ device\n",
+ "to produce output.\n\n",
+ "The following places were tested for a valid LaTeX compiler:\n\n\t",
+ paste( sapply(latexLocs, format),collapse='\n\t'),
+ "\n\nIf you have a working LaTeX compiler, try one of the\n",
+ "following solutions:",
+
+ "\n\n\tSet the path to your compiler as the value of either latexcmd or",
+ "\n\ttikzLatex in .Rprofile using options().",
+
+ "\n\n\tSet the path to your compiler as the value of either R_LATEXCMD or",
+ "\n\tR_PDFLATEXCMD in .Renviron.",
+
+ "\n\n\tEnsure the folder containing your compiler is included in PATH.\n"
+ )
+ }
+
+}
+
+# Any variables defined in here will be hidden
+# from normal users.
+.tikzInternal <- new.env()
diff --git a/build/vignette.rds b/build/vignette.rds
new file mode 100644
index 0000000..f905671
Binary files /dev/null and b/build/vignette.rds differ
diff --git a/debian/README.test b/debian/README.test
deleted file mode 100644
index 3d2b347..0000000
--- a/debian/README.test
+++ /dev/null
@@ -1,10 +0,0 @@
-Notes on how this package can be tested.
-────────────────────────────────────────
-
-To run the unit tests provided by the package you can do
-
- sh run-unit-test
-
-in this directory.
-
-
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 4182ef8..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,16 +0,0 @@
-r-cran-tikzdevice (0.10-1-2) unstable; urgency=medium
-
- * Rebuild against new R version
- Closes: #863369
- * debhelper 10
- * Use dh-r instead of cdbs
- * Standards-Version: 4.1.0 (no changes needed)
- * d/watch: version=4
-
- -- Andreas Tille <tille at debian.org> Sun, 27 Aug 2017 14:29:31 +0200
-
-r-cran-tikzdevice (0.10-1-1) unstable; urgency=low
-
- * Initial release (closes: #837347)
-
- -- Andreas Tille <tille at debian.org> Sat, 10 Sep 2016 22:03:58 +0200
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index f599e28..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-10
diff --git a/debian/control b/debian/control
deleted file mode 100644
index 383c82f..0000000
--- a/debian/control
+++ /dev/null
@@ -1,31 +0,0 @@
-Source: r-cran-tikzdevice
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Andreas Tille <tille at debian.org>
-Section: gnu-r
-Priority: optional
-Build-Depends: debhelper (>= 10),
- dh-r,
- r-base-dev,
- r-cran-filehash,
- r-cran-png
-Standards-Version: 4.1.0
-Vcs-Browser: https://anonscm.debian.org/viewvc/debian-med/trunk/packages/R/r-cran-tikzdevice/trunk/
-Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/R/r-cran-tikzdevice/trunk/
-Homepage: https://cran.r-project.org/package=tikzDevice
-
-Package: r-cran-tikzdevice
-Architecture: any
-Depends: ${misc:Depends},
- ${shlibs:Depends},
- ${R:Depends}
-Recommends: ${R:Recommends}
-Suggests: ${R:Suggests}
-Description: GNU R graphics output in LaTeX format
- This GNU R package provides a graphics output device for R that records
- plots in a LaTeX-friendly format. The device transforms plotting
- commands issued by R functions into LaTeX code blocks. When included in
- a LaTeX document, these blocks are interpreted with the help of 'TikZ'—a
- graphics package for TeX and friends written by Till Tantau. Using the
- 'tikzDevice', the text of R plots can contain LaTeX commands such as
- mathematical formula. The device also allows arbitrary LaTeX code to be
- inserted into the output stream.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index a9386b1..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,30 +0,0 @@
-Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: tikzDevice
-Upstream-Contact: Kirill Müller <krlmlr+r at mailbox.org>
-Source: https://cran.r-project.org/package=tikzDevice
-
-Files: *
-Copyright: 2014-2016 Charlie Sharpsteen, Cameron Bracken, Kirill Müller, Yihui Xie
-License: GPL-2+
-
-Files: debian/*
-Copyright: 2016 Andreas Tille <tille at debian.org>
-License: GPL-2+
-
-License: GPL-2+
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- .
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- .
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- .
- On Debian systems, the complete text of the GNU General Public
- License can be found in `/usr/share/common-licenses/GPL-2'.
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index 960011c..0000000
--- a/debian/docs
+++ /dev/null
@@ -1,3 +0,0 @@
-tests
-debian/README.test
-debian/tests/run-unit-test
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index b0e20cd..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/make -f
-
-include /usr/share/dpkg/default.mk
-
-%:
- dh $@ --buildsystem R
-
-override_dh_install:
- dh_install
- find debian -name LICENSE -delete
-
-override_dh_installdocs:
- dh_installdocs
- # Delete tests depending from devtools since this is not (yet) packaged
- cd debian/$(DEB_SOURCE)/usr/share/doc/$(DEB_SOURCE)/tests/ ; \
- if grep -qR devtools * ; then \
- rm -f `grep -lR devtools *` ; \
- fi
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/tests/control b/debian/tests/control
deleted file mode 100644
index b044b0c..0000000
--- a/debian/tests/control
+++ /dev/null
@@ -1,3 +0,0 @@
-Tests: run-unit-test
-Depends: @, r-cran-testthat
-Restrictions: allow-stderr
diff --git a/debian/tests/run-unit-test b/debian/tests/run-unit-test
deleted file mode 100644
index 7a52816..0000000
--- a/debian/tests/run-unit-test
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh -e
-
-oname=tikzDevice
-pkg=r-cran-`echo $oname | tr '[A-Z]' '[a-z]'`
-if [ "$ADTTMP" = "" ] ; then
- ADTTMP=`mktemp -d /tmp/${pkg}-test.XXXXXX`
- trap "rm -rf $ADTTMP" 0 INT QUIT ABRT PIPE TERM
-fi
-cd $ADTTMP
-cp -a /usr/share/doc/${pkg}/tests/* .
-
-LC_ALL=C R --no-save < unit_tests.R
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index 5d7b1d2..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=4
-http://cran.r-project.org/src/contrib/tikzDevice_([-\d.]*)\.tar\.gz
diff --git a/inst/doc/tikzDevice.R b/inst/doc/tikzDevice.R
new file mode 100644
index 0000000..4857e8e
--- /dev/null
+++ b/inst/doc/tikzDevice.R
@@ -0,0 +1,279 @@
+## ----setup,echo=FALSE,results='hide'-------------------------------------
+ library(tikzDevice)
+ if( !file.exists('figs') ){dir.create( 'figs' )}
+
+ options(tikzMetricsDictionary='.tikzMetrics')
+
+ knitr::opts_chunk$set(
+ echo=FALSE,
+ fig.path='figs/fig',
+ message=FALSE,
+ width = 100,
+ comment = NA
+ )
+ knitr::knit_hooks$set(
+ source = function(x, options) {
+ paste("\\vspace{-1ex}",
+ "\\begin{tikzCodeBlock}[listing style=sweavechunk]",
+ paste(x, collapse = '\n'),
+ "\\end{tikzCodeBlock}\n\n", sep = '\n')
+ },
+ output = function(x, options) {
+ paste("\\vspace{-2ex}",
+ "\\begin{Verbatim}[frame=single]",
+ sub("\n+$", "", paste(x, collapse = '\n')),
+ "\\end{Verbatim}",
+ "",
+ sep = '\n')
+ },
+ warning = function(x, options) {
+ paste("\\vspace{-2ex}",
+ "\\begin{Verbatim}[frame=single,formatcom=\\color{warningcolor}]",
+ sub("\n+$", "", paste(strwrap(x, width = options$width),
+ collapse = '\n')),
+ "\\end{Verbatim}",
+ "",
+ sep = '\n')
+ },
+ chunk = function(x, options) x
+ )
+
+## ----tikzTitlePlot,results='hide'----------------------------------------
+ tikz('figs/titlePlot.tex',width=4,height=4)
+
+ x <- seq(-4.5,4.5,length.out=100)
+ y <- dnorm(x)
+
+ xi <- seq(-2,2,length.out=30)
+ yi <- dnorm(xi)
+
+ plot(x,y,type='l',col='blue',ylab='$p(x)$',xlab='$x$')
+ lines(xi,yi,type='s')
+ lines(range(xi),c(0,0))
+ lines(xi,yi,type='h')
+ title(main="$p(x)=\\frac{1}{\\sqrt{2\\pi}}e^{-\\frac{x^2}{2}}$")
+ int <- integrate(dnorm,min(xi),max(xi),subdivisions=length(xi))
+ text(2.8,0.3,paste(
+ "\\small$\\displaystyle\\int_{",min(xi),"}^{",max(xi),"}p(x)dx",
+ "\\approx",round(int[['value']],3),'$',sep=''))
+
+ dev.off()
+
+## ----pdf-example,echo=FALSE,results='hide'-------------------------------
+ pdf('figs/pdf-example.pdf', width = 3.25, height = 3.25)
+ plot(1, 1, main = 'Hello!', ps = 10)
+ dev.off()
+
+## ----tikz-example,echo=FALSE,results='hide'------------------------------
+ tikz('figs/tikz-example.tex', width = 3.25, height = 3.25)
+ plot(1, 1, main = 'Hello \\TeX !')
+ dev.off()
+
+## ----tikzArgs, code=formatR::usage(tikz), eval=FALSE---------------------
+# tikz(file = ifelse(onefile, "./Rplots.tex", "./Rplot%03d.tex"), width = 7, height = 7,
+# onefile = TRUE, bg = "transparent", fg = "black", pointsize = 10, lwdUnit = getOption("tikzLwdUnit"),
+# standAlone = FALSE, bareBones = FALSE, console = FALSE, sanitize = FALSE,
+# engine = getOption("tikzDefaultEngine"), documentDeclaration = getOption("tikzDocumentDeclaration"),
+# packages, footer = getOption("tikzFooter"), symbolicColors = getOption("tikzSymbolicColors"),
+# colorFileName = "%s_colors.tex", maxSymbolicColors = getOption("tikzMaxSymbolicColors"),
+# timestamp = TRUE, verbose = interactive())
+
+## ----simpleEx,echo=TRUE,results='hide'-----------------------------------
+library(tikzDevice)
+tikz('figs/simpleEx.tex',width=3.5,height=3.5)
+plot(1,main='Hello World!')
+dev.off()
+
+## ----latexEx,echo=TRUE,results='hide',tidy=FALSE-------------------------
+library(tikzDevice)
+tikz('figs/latexEx.tex',
+ width=3.5,height=3.5)
+
+x <- rnorm(10)
+y <- x + rnorm(5,sd=0.25)
+
+model <- lm(y ~ x)
+rsq <- summary( model )$r.squared
+rsq <- signif(rsq,4)
+
+plot(x, y, main='Hello \\LaTeX!')
+abline(model, col='red')
+
+mtext(paste("Linear model: $R^{2}=",
+ rsq, "$"), line=0.5)
+
+legend('bottomright', legend =
+ paste("$y = ",
+ round(coef(model)[2],3), 'x +',
+ round(coef(model)[1],3), '$',
+ sep = ''), bty = 'n')
+
+dev.off()
+
+## ----bareBonesExample,echo=TRUE,results='hide',tidy=FALSE----------------
+library(tikzDevice)
+library(maps)
+
+tikz('figs/westCoast.tex', bareBones=TRUE)
+
+map('state', regions=c('california', 'oregon', 'washington'),
+ lwd=4, col='grey40')
+
+# Insert some named coordinates into the picture that will
+# be available once the picture is included into the
+# TeX document.
+tikzCoord(-124.161, 40.786, 'humBay')
+tikzCoord(-122.962, 46.148, 'longView')
+tikzCoord(-124.237, 43.378, 'coosBay')
+tikzCoord(-122.419, 37.775, 'sfBay')
+
+dev.off()
+
+## ----standAloneExample,echo=TRUE,results='hide',tidy=FALSE---------------
+library(tikzDevice)
+tikz('standAloneExample.tex',standAlone=TRUE)
+plot(sin,-pi,2*pi,main="A Stand Alone TikZ Plot")
+dev.off()
+
+## ----standAloneCompileExample, results='hide', eval=FALSE----------------
+#
+# library(tools)
+#
+# catch <- system(paste(Sys.which('pdflatex'),
+# '-interaction=batchmode -output-directory figs/ figs/standAloneExample.tex'),
+# ignore.stderr=T)
+#
+# # If compiling the example failed, we don't want to include a broken link.
+# if( catch == 0 ){
+# pdfLink <- "The file \\\\code{standAloneExample.tex} may then be compiled to produce
+# \\\\href{./figs/standAloneExample.pdf}{standAloneExample.pdf}. "
+# }else{
+# pdfLink <- ""
+# }
+# #%\Sexpr{print(pdfLink)}
+
+## ----xelatexFontVariantExample,tidy=FALSE,echo=TRUE,eval=FALSE,results='hide'----
+# # Set options for using XeLaTeX font variants.
+# options(tikzXelatexPackages = c(
+# getOption('tikzXelatexPackages'),
+# "\\usepackage[colorlinks, breaklinks]{hyperref}",
+# "\\usepackage{color}",
+# "\\definecolor{Gray}{rgb}{.7,.7,.7}",
+# "\\definecolor{lightblue}{rgb}{.2,.5,1}",
+# "\\definecolor{myred}{rgb}{1,0,0}",
+# "\\newcommand{\\red}[1]{\\color{myred} #1}",
+# "\\newcommand{\\reda}[1]{\\color{myred}\\fontspec[Variant=2]{Zapfino}#1}",
+# "\\newcommand{\\redb}[1]{\\color{myred}\\fontspec[Variant=3]{Zapfino}#1}",
+# "\\newcommand{\\redc}[1]{\\color{myred}\\fontspec[Variant=4]{Zapfino}#1}",
+# "\\newcommand{\\redd}[1]{\\color{myred}\\fontspec[Variant=5]{Zapfino}#1}",
+# "\\newcommand{\\rede}[1]{\\color{myred}\\fontspec[Variant=6]{Zapfino}#1}",
+# "\\newcommand{\\redf}[1]{\\color{myred}\\fontspec[Variant=7]{Zapfino}#1}",
+# "\\newcommand{\\redg}[1]{\\color{myred}\\fontspec[Variant=8]{Zapfino}#1}",
+# "\\newcommand{\\lbl}[1]{\\color{lightblue} #1}",
+# "\\newcommand{\\lbla}[1]{\\color{lightblue}\\fontspec[Variant=2]{Zapfino}#1}",
+# "\\newcommand{\\lblb}[1]{\\color{lightblue}\\fontspec[Variant=3]{Zapfino}#1}",
+# "\\newcommand{\\lblc}[1]{\\color{lightblue}\\fontspec[Variant=4]{Zapfino}#1}",
+# "\\newcommand{\\lbld}[1]{\\color{lightblue}\\fontspec[Variant=5]{Zapfino}#1}",
+# "\\newcommand{\\lble}[1]{\\color{lightblue}\\fontspec[Variant=6]{Zapfino}#1}",
+# "\\newcommand{\\lblf}[1]{\\color{lightblue}\\fontspec[Variant=7]{Zapfino}#1}",
+# "\\newcommand{\\lblg}[1]{\\color{lightblue}\\fontspec[Variant=8]{Zapfino}#1}",
+# "\\newcommand{\\old}[1]{",
+# "\\fontspec[Ligatures={Common, Rare},Variant=1,Swashes={LineInitial, LineFinal}]{Zapfino}",
+# "\\fontsize{25pt}{30pt}\\selectfont #1}%",
+# "\\newcommand{\\smallprint}[1]{\\fontspec{Hoefler Text}
+# \\fontsize{10pt}{13pt}\\color{Gray}\\selectfont #1}"
+# ))
+#
+# # Set the content using custom defined commands
+# label <- c(
+# "\\noindent{\\red d}roo{\\lbl g}",
+# "\\noindent{\\reda d}roo{\\lbla g}",
+# "\\noindent{\\redb d}roo{\\lblb g}",
+# "\\noindent{\\redf d}roo{\\lblf g}\\\\[.3cm]",
+# "\\noindent{\\redc d}roo{\\lblc g}",
+# "\\noindent{\\redd d}roo{\\lbld g}",
+# "\\noindent{\\rede d}roo{\\lble g}",
+# "\\noindent{\\redg d}roo{\\lblg g}\\\\[.2cm]"
+# )
+#
+# # Set the titles using custom defined commands, and hyperlinks
+# title <- c(
+# paste(
+# "\\smallprint{D. Taraborelli (2008),",
+# "\\href{http://nitens.org/taraborelli/latex}",
+# "{The Beauty of \\LaTeX}}"
+# ), paste(
+# "\\smallprint{\\\\\\emph{Some rights reserved}.",
+# "\\href{http://creativecommons.org/licenses/by-sa/3.0/}",
+# "{\\textsc{cc-by-sa}}}"
+# ))
+#
+# # Draw the graphic
+# tikz('xelatexEx.tex',
+# standAlone=TRUE,width=5,height=5,
+# engine = 'xetex')
+# lim <- 0:(length(label)+1)
+# plot(lim,lim,cex=0,pch='.',xlab = title[2],ylab='', main = title[1])
+# for(i in 1:length(label))
+# text(i,i,label[i])
+# dev.off()
+
+## ----annotation,echo=TRUE,results='hide',tidy=FALSE----------------------
+library(tikzDevice)
+
+# Load some additional TikZ libraries
+tikz("figs/annotation.tex",width=4,height=4,
+ packages = c(getOption('tikzLatexPackages'),
+ "\\usetikzlibrary{decorations.pathreplacing}",
+ "\\usetikzlibrary{positioning}",
+ "\\usetikzlibrary{shapes.arrows,shapes.symbols}")
+)
+
+p <- rgamma (300 ,1)
+outliers <- which( p > quantile(p,.75)+1.5*IQR(p) )
+boxplot(p)
+
+# Add named coordinates that other TikZ commands can hook onto
+tikzCoord(1, min(p[outliers]), 'min outlier')
+tikzCoord(1, max(p[outliers]), 'max outlier')
+
+# Use tikzAnnotate to insert arbitrary code, such as drawing a
+# fancy path between min outlier and max outlier.
+tikzAnnotate(c("\\draw[very thick,red,",
+ # Turn the path into a brace.
+ 'decorate,decoration={brace,amplitude=12pt},',
+ # Shift it 1em to the left of the coordinates
+ 'transform canvas={xshift=-1em}]',
+ '(min outlier) --',
+ # Add a node with some text in the middle of the path
+ 'node[single arrow,anchor=tip,fill=white,draw=green,',
+ 'left=14pt,text width=0.70in,align=center]',
+ '{Holy Outliers Batman!}', '(max outlier);'))
+
+# tikzNode can be used to place nodes with customized options and content
+tikzNode(
+ opts='starburst,fill=green,draw=blue,very thick,right=of max outlier',
+ content='Wow!'
+)
+
+dev.off()
+
+## ----strWidthDemo,echo=T-------------------------------------------------
+getLatexStrWidth( "The symbol: alpha" )
+getLatexStrWidth( "The symbol: $\\alpha$" )
+
+## ----charMetricDemo,echo=T,tidy=FALSE------------------------------------
+# Get metrics for 'y'
+getLatexCharMetrics(121)
+
+# Get metrics for 'x' - the second value is the descent
+# and should be zero or very close to zero.
+getLatexCharMetrics(120)
+
+## ----charMetricErrors,echo=T,tidy=FALSE----------------------------------
+getLatexCharMetrics('y')
+getLatexCharMetrics(20)
+
+# Will return metrics for 'y'
+getLatexCharMetrics(121.99)
+
diff --git a/inst/doc/tikzDevice.Rnw b/inst/doc/tikzDevice.Rnw
new file mode 100644
index 0000000..0770e25
--- /dev/null
+++ b/inst/doc/tikzDevice.Rnw
@@ -0,0 +1,2129 @@
+% !TEX TS-program = knitr
+% \VignetteIndexEntry{The tikzDevice Package}
+% \VignetteDepends{tikzDevice}
+% \VignetteEngine{knitr::knitr}
+
+\documentclass[10pt,oneside,letterpaper,article]{memoir}
+\usepackage[utf8]{inputenc}
+\usepackage{tikzDeviceVignette}
+
+
+<<setup,echo=FALSE,results='hide'>>=
+ library(tikzDevice)
+ if( !file.exists('figs') ){dir.create( 'figs' )}
+
+ options(tikzMetricsDictionary='.tikzMetrics')
+
+ knitr::opts_chunk$set(
+ echo=FALSE,
+ fig.path='figs/fig',
+ message=FALSE,
+ width = 100,
+ comment = NA
+ )
+ knitr::knit_hooks$set(
+ source = function(x, options) {
+ paste("\\vspace{-1ex}",
+ "\\begin{tikzCodeBlock}[listing style=sweavechunk]",
+ paste(x, collapse = '\n'),
+ "\\end{tikzCodeBlock}\n\n", sep = '\n')
+ },
+ output = function(x, options) {
+ paste("\\vspace{-2ex}",
+ "\\begin{Verbatim}[frame=single]",
+ sub("\n+$", "", paste(x, collapse = '\n')),
+ "\\end{Verbatim}",
+ "",
+ sep = '\n')
+ },
+ warning = function(x, options) {
+ paste("\\vspace{-2ex}",
+ "\\begin{Verbatim}[frame=single,formatcom=\\color{warningcolor}]",
+ sub("\n+$", "", paste(strwrap(x, width = options$width),
+ collapse = '\n')),
+ "\\end{Verbatim}",
+ "",
+ sep = '\n')
+ },
+ chunk = function(x, options) x
+ )
+@
+
+
+
+\title{TikZDevice: LaTeX Graphics for R}
+\author{Charlie Sharpsteen and Cameron Bracken}
+\date{\Sexpr{strftime(read.dcf(system.file('DESCRIPTION', package = 'tikzDevice'), fields = 'Date'), format = '%B %d, %Y')}}
+\gdef\packageURL{\url{https://github.com/yihui/tikzDevice}}
+\gdef\packageVersion{\Sexpr{tikzDevice:::getTikzDeviceVersion()}}
+
+% Use the hyperref package to fill in PDF metadata.
+\hypersetup{
+ pdftitle=\thetitle,
+ pdfauthor=\theauthor,
+ pdfsubject={Manual for Version: \packageVersion, \thedate}
+}
+
+
+\begin{document}
+% -----------------------------------------------------------------------------
+% Cover Page
+% -----------------------------------------------------------------------------
+<<tikzTitlePlot,results='hide'>>=
+ tikz('figs/titlePlot.tex',width=4,height=4)
+
+ x <- seq(-4.5,4.5,length.out=100)
+ y <- dnorm(x)
+
+ xi <- seq(-2,2,length.out=30)
+ yi <- dnorm(xi)
+
+ plot(x,y,type='l',col='blue',ylab='$p(x)$',xlab='$x$')
+ lines(xi,yi,type='s')
+ lines(range(xi),c(0,0))
+ lines(xi,yi,type='h')
+ title(main="$p(x)=\\frac{1}{\\sqrt{2\\pi}}e^{-\\frac{x^2}{2}}$")
+ int <- integrate(dnorm,min(xi),max(xi),subdivisions=length(xi))
+ text(2.8,0.3,paste(
+ "\\small$\\displaystyle\\int_{",min(xi),"}^{",max(xi),"}p(x)dx",
+ "\\approx",round(int[['value']],3),'$',sep=''))
+
+ dev.off()
+@
+
+\begin{titlingpage}
+ % NOTE:
+ % Most dimensions and positions in this cover page were optimized for US
+ % Letter stock size and so are given in inches. It may be useful to revise
+ % this one day so that the layout is a bit more scalable.
+ %
+ % Use remember picture and overlay so that `current page` coordinates can be
+ % accessed.
+ \begin{tikzpicture}[remember picture, overlay]
+ % Title and Info
+ % --------------
+ {\fontsize{60}{36}
+ \node[below right = 0.5em of current page.north west,
+ anchor = north east,
+ rotate = 90,
+ outer sep = 0pt,
+ inner sep = 0pt
+ ]
+ (title)
+ {\bfseries{\fontsize{36}{36}\selectfont\color{red}\TikZ}Device};
+ }
+
+ \draw[line width = 5pt] ([xshift = 7.5pt]title.base west) -- ([xshift = 7.5pt]title.base east);
+
+ % Have to split subtitle, authors, etc. into several nodes because
+ % apparently TikZ can't deal with font change commands and line breaks
+ % existing in the same node. A bit of a pain because the value of
+ % \baselineskip has to be twaddled by wrapping some \nodes in font
+ % size descriptors.
+ \node[right = 12.5pt of title.base east,
+ anchor = north west,
+ align = left,
+ font = {\Huge\bfseries}
+ ]
+ (subtitle)
+ {\LaTeX\ Graphics for \lang{R}};
+
+ {\huge
+ \node[below = \baselineskip of subtitle.base west,
+ anchor = north west,
+ align = left,
+ font = {\LARGE}
+ ]
+ (authors)
+ {%
+ Charlie Sharpsteen\\
+ Cameron Bracken%
+ };
+ }
+
+ \node[right = 12.5pt of title.base west,
+ anchor = base west,
+ align = left
+ ]
+ (packageInfo)
+ {%
+ \thedate\\
+ \packageURL%
+ };
+
+ {\LARGE
+ \node[above = \baselineskip of packageInfo.north west,
+ anchor = base west,
+ align = left,
+ font = {\LARGE\bfseries}
+ ]
+ (version)
+ {Version: \packageVersion};
+ }
+
+
+ % Logo and Plot
+ % -------------
+
+ % Scaling the R logo to a width of 4.75 in was determed through trial and
+ % error. The center of the image is shifted relative to the bottom right
+ % corner of the page such that the point where the right leg of the "R"
+ % glyph intersects the inside of the halo is sitting over the corner of the
+ % page.
+ \node[inner sep = 0pt,
+ above left = 0.78in and 1.48in of current page.south east,
+ anchor = center
+ ]
+ (Rlogo)
+ {\includegraphics[width=4.75in]{img/Rlogo}};
+
+ % This node contains an embedded `tikzpicture` environment produced by the
+ % tikzTitlePlot code block.
+ \node[anchor = north east,
+ inner sep = 0pt
+ ]
+ (titlePlot) at (current page.north east)
+ {\input{figs/titlePlot.tex}};
+
+
+ % Connect Logo and Plot
+ % ---------------------
+ \node[below left = 0.325\stockheight and 0.325\stockwidth of current page.center]
+ (midPointA) {};
+
+ \node[below right = 0.125\stockheight and 0.125\stockwidth of current page.center]
+ (midPointB) {};
+
+ \tikzset{
+ grow bigger/.style={decoration = {
+ shape backgrounds,
+ shape = dart,
+ shape scaled,
+ shape start size = 0.125cm,
+ shape end size = 0.5cm,
+ shape sep = {.25cm, between borders}
+ }}
+ }
+
+ \path[decorate, grow bigger, fill = black!25]
+ plot[smooth, tension = 1]
+ coordinates{(Rlogo.190) (midPointA) (midPointB) (titlePlot.south)};
+
+ \end{tikzpicture}
+\end{titlingpage}
+
+
+% -----------------------------------------------------------------------------
+% Table of Contents
+% -----------------------------------------------------------------------------
+\frontmatter
+ \tableofcontents*
+
+
+\mainmatter
+
+
+% -----------------------------------------------------------------------------
+% Chapter 1: Introduction
+% -----------------------------------------------------------------------------
+\chapter{Introduction}
+
+The \pkg{tikzDevice} package provides a graphics output device for \lang{R} that
+records plots in a \LaTeX -friendly format. The device transforms plotting
+commands issued by \lang{R} functions into \LaTeX\ code blocks. When included in a
+paper typeset by \LaTeX , these blocks are interpreted with the help of
+TikZ---a graphics package for \TeX\ and friends written by Till Tantau. By
+allowing \LaTeX\ to handle typesetting of text in \lang{R} plots along with the
+rest of the text in the paper the full power of \TeX\ is available to the
+\lang{R} user. There are also no discontinuities in font selection and
+typesetting as demonstrated by a comparison between \autoref{fig:pdf-example}
+and \autoref{fig:tikz-example}.
+
+
+% FIXME:
+% This example is biased. It would be best to choose a TeX font for which AFM
+% metrics are available and show how much of a pain in the ass it is to use the
+% R `Type1Font` function vs. how easy it is to set tikzDevice options and let
+% TeX do the heavy lifting.
+\begin{figure}[!hb]
+ \centering
+
+ \begin{minipage}[t]{0.4\linewidth}
+ \begin{tikzCodeBlock}[listing style=sweavechunk,
+ code body/.append style={codebody color=white}]
+pdf('pdf-example.pdf',
+ width = 3.25, height = 3.25)
+plot(1, 1, main = 'Hello!')
+dev.off()
+ \end{tikzCodeBlock}
+
+<<pdf-example,echo=FALSE,results='hide'>>=
+ pdf('figs/pdf-example.pdf', width = 3.25, height = 3.25)
+ plot(1, 1, main = 'Hello!', ps = 10)
+ dev.off()
+@
+ \includegraphics{figs/pdf-example}
+ \caption{Output from \code{pdf()}}
+ \label{fig:pdf-example}
+ \end{minipage}
+ \hspace{0.1\linewidth}
+ \begin{minipage}[t]{0.4\linewidth}
+ \begin{tikzCodeBlock}[listing style=sweavechunk,
+ code body/.append style={codebody color=white}]
+tikz('tikz-example.tex',
+ width = 3.25, height = 3.25)
+plot(1, 1, main = 'Hello \\TeX !')
+dev.off()
+ \end{tikzCodeBlock}
+
+<<tikz-example,echo=FALSE,results='hide'>>=
+ tikz('figs/tikz-example.tex', width = 3.25, height = 3.25)
+ plot(1, 1, main = 'Hello \\TeX !')
+ dev.off()
+@
+ \input{figs/tikz-example.tex}
+ \caption{Output from \code{tikz()}}
+ \label{fig:tikz-example}
+ \end{minipage}
+\end{figure}
+
+
+This document is divided into three parts. \autoref{part:usage} describes the
+package functionality and provides example usage. Besides the \lang{R}
+environment, use of the \TikZ\ device requires the user to have a
+working \LaTeX{} compiler along with an installed version of the \TikZ{}
+package---version 2.00 or greater. \autoref{part:installation} of this
+documentation offers suggestions on how to get these dependencies installed and
+working properly.
+
+\autoref{part:implementation} is intended for those who are curious as to the
+details of how this package is implemented. This part attempts to explain how
+the \pkg{tikzDevice} package does the things that it does and why it chooses to
+do them that way. The authors have attempted to write this part of the
+documentation in a way that is accessible to users as well as developers. This
+information is provided in the hope that the \pkg{tikzDevice} may serve as a
+case study for creating new \lang{R} graphics devices. This part of the
+documentation may also help those considering undertaking the transition from
+casual package-building to full-on hacking of the \lang{R} internals.
+
+\section{Acknowledgements}
+
+This package would not have been possible without the hard work and ingenuity
+of many individuals. This package straddles the divide between two great open
+source communities---the \lang{R} programming language and the \TeX{}
+typesetting system. It is our hope that this work will make it easier for users
+to leverage the strengths of both systems.
+
+First off, we would like to thank the \lang{R} Core Team for creating such a
+wonderful, open and flexible programming environment. Compared to other
+languages we have used, creating packages and extensions for \lang{R} has
+always been a liberating experience.
+
+This package started as a fork of the Pic\TeX\ device created by Valerio Aimale
+which is part of the \lang{R} core graphics system. Without access to this
+simple, compact example of implementing a graphics device we likely would have
+abandoned the project in its infancy. We would also like to thank Paul Murrell
+for all of his work on the \lang{R} graphics system and especially for his
+research and documentation concerning the differences between the font systems
+used by \TeX{} and \lang{R}.
+
+This package also owes its existence to Friedrich Leisch's work on the
+\pkg{Sweave} system and Roger D. Peng's \pkg{cacheSweave} extension. These
+two tools got us interested in the concept of Literate Programming and
+development of this package was driven by our desire to achieve a more seamless
+union between our reports and our code.
+
+The performance of this package is also enhanced by the database capabilities
+provided by Roger D. Peng's \pkg{filehash} package. Without this package, the
+approach to calculating font metrics taken by the \pkg{tikzDevice} would be
+infeasible.
+
+Last, but certainly not least, we would like to thank Till Tantau, Mark Wibrow
+and the rest of the PGF/\TikZ\ team for creating the \LaTeX\ graphics package
+that makes the output of this device meaningful. We would also like to express
+deep appreciation for the beautiful documentation that has been created for the
+\TikZ\ system.
+
+As always, there are many more who have contributed in ways too numerous to
+list.\\[\baselineskip]
+
+\noindent Thank you!\\
+\quad{\itshape ---The tikzDevice Team}
+
+\nocite{murrellTex}
+\nocite{rintern2009}
+\nocite{tantau2008}
+\nocite{peng2006}
+
+
+\partimage{
+ \node[above left = 1in of current page.south east,
+ anchor = south east,
+ scale = 1.25
+ ]
+ % This image is generated by an example in chapter 3.
+ {\input{figs/latexEx}};
+}
+\part{Usage and Examples}
+ \label{part:usage}
+
+
+% -----------------------------------------------------------------------------
+% Chapter 2: Package Loading
+% -----------------------------------------------------------------------------
+\chapter{Loading the Package}
+
+The functions in the \pkg{tikzDevice} package are made accessible in the
+\lang{R} environment by using \code{library()}:
+
+\begin{Verbatim}[frame=single]
+library(tikzDevice)
+\end{Verbatim}
+
+\noindent Upon loading, the package will search for the following \LaTeX\ compilers:
+
+\begin{itemize}
+ \item{\hologo{pdfLaTeX}}
+ \item{\hologo{XeLaTeX}}
+ \item{\hologo{LuaLaTeX}}
+\end{itemize}
+
+Access to \LaTeX\ is essential for the device to produce output as the compiler
+is queried for font metrics when constructing plots that contain text. For more
+information on why communication between the device and \LaTeX\ is necessary,
+see \autoref{part:implementation}. The package will fail to load if
+\hologo{pdfLaTeX} cannot be located. The presence of the \hologo{XeLaTeX} and
+\hologo{LuaLaTeX} compilers is optional. When the package loads successfully,
+a startup message will be printed that looks similar to the following:
+
+\begin{Verbatim}[frame=single]
+Loading required package: filehash
+filehash: Simple key-value database (2.2 2011-07-21)
+tikzDevice: R Graphics Output in LaTeX Format (v0.7)
+ LaTeX found in the PATH using the command: pdflatex
+ XeLaTeX found in the PATH using the command: xelatex
+ LuaLaTeX found in the PATH using the command: lualatex
+\end{Verbatim}
+
+If a working \hologo{pdfLaTeX} compiler cannot be found, the \pkg{tikzDevice} package
+will fail to load and a warning message will be displayed:
+
+\begin{Verbatim}[frame=single]
+Error : .onLoad failed in loadNamespace() for 'tikzDevice', details:
+ call: fun(libname, pkgname)
+ error:
+
+An appropriate LaTeX compiler could not be found.
+Access to LaTeX is required in order for the TikZ device
+to produce output.
+
+The following places were tested for a valid LaTeX compiler:
+
+ the global option: tikzLatex
+ the environment variable: R_LATEXCMD
+ the environment variable: R_PDFLATEXCMD
+ the global option: latexcmd
+ the PATH using the command: pdflatex
+ the PATH using the command: latex
+ the PATH using the command: /usr/texbin/pdflatex
+
+...
+
+Error: loading failed
+\end{Verbatim}
+
+In this case, \pkg{tikzDevice} has done its very best to locate a working
+compiler and came up empty. If you have a working \LaTeX\ compiler, the next
+section describes how to inform the \pkg{tikzDevice} package of its location.
+For suggestions on how to obtain a \LaTeX\ compiler, see
+\autoref{part:installation}.
+
+
+\section{Options That Affect Package Behavior}
+ \label{sec:options}
+
+The \pkg{tikzDevice} package is influenced by a number of options that may be
+set locally in your \lang{R} scripts or in the \lang{R} console or globally in
+a \code{.Rprofile} file. All of the options can be set by using
+\code{options(<option> = <value>)}. These options allow for the use of custom
+\code{documentclass} declarations, \LaTeX\ packages, and typesetting engines
+(e.g. \hologo{XeLaTeX} or \hologo{LuaLaTeX}).
+
+For convenience the function \code{setTikzDefaults()} is provided which sets
+all the global options back to their original values.
+
+The proper placement of a \code{.Rprofile} file is explained in the \lang{R}
+manual page \code{?Startup}. For the details of why calling the \LaTeX\ compiler is
+necessary, see \autoref{part:implementation}.
+
+A lot of power is given to you through these global options, and with great
+power comes great responsibility. For example, if you do not include the
+\TikZ\ package in the \code{tikzLatexPackages} option then all of the string
+metric calculations will fail. Or if you use a different font when compiling
+than you used for calculating metrics, strings may be placed incorrectly.
+There are innumerable ways for packages to clash in \LaTeX\ so be aware.
+
+
+\subsection{The \pkgopt{tikzDefaultEngine} Option}
+
+This option specifies which typesetting engine the \pkg{tikzDevice} package
+will prefer. Current possible values are \code{pdftex}, \code{xetex} or
+\code{luatex} which will respectively trigger the use of the \hologo{pdfLaTeX},
+\hologo{XeLaTeX} or \hologo{LuaLaTeX} compilers.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzDefaultEngine = 'pdftex')
+\end{tikzCodeBlock}
+
+\begin{tikzCodeBlock}[title={Choosing the \TeX\ engine},listing style=sweavechunk]
+options(tikzDefaultEngine = 'xetex')
+options(tikzDefaultEngine = 'luatex')
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzLatex}, \pkgopt{tikzXelatex} and \pkgopt{tikzLualatex} Options}
+
+Specifies the location of the \LaTeX{}, \hologo{XeLaTeX} and \hologo{LuaLaTeX}
+compilers to be used by \pkg{tikzDevice}. Setting a default for this option may
+help the package locate a missing compiler:
+
+\begin{tikzCodeBlock}[title={Setting default compilers in \code{.Rprofile}},listing style=sweavechunk]
+options(tikzLatex = '/path/to/pdflatex')
+options(tikzXelatex = '/path/to/xelatex')
+options(tikzLualatex = '/path/to/lualatex')
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzMetricsDictionary} Option}
+
+When using the graphics device provided by \pkg{tikzDevice}, you may notice
+that \lang{R} appears to ``lag" or ``hang'' when commands such as \code{plot()}
+are executed. This is because the device must query the \LaTeX\ compiler for
+string widths and font metrics. For a normal plot, this may happen dozens or
+hundreds of times---hence \lang{R} becomes unresponsive for a while. The good
+news is that the \code{tikz()} code is designed to cache the results of these
+computations so they need only be performed once for each string or character.
+By default, these values are stored in a temporary cache file which is deleted
+when \lang{R} is shut down. Using the option \code{tikzMetricsDictionary}, a
+permanent cache file may be specified:
+
+\begin{tikzCodeBlock}[title={Setting a location in \code{.Rprofile} for a permanent metrics dictionary},listing style=sweavechunk]
+options(tikzMetricsDictionary = '/path/to/dictionary/location')
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzDocumentDeclaration} Option}
+
+For \code{standAlone == TRUE}, \code{tikzDocumentDeclaration} also influences the
+calculation of font metrics. If a base font size is specified as an option to
+the document class, the \pkg{tikzDevice} will use this value as the base font
+size for graphics.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzDocumentDeclaration = "\\documentclass[10pt]{article}")
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzLatexPackages}, \pkgopt{tikzXelatexPackages} and \pkgopt{tikzLualatexPackages} Options}
+
+Character vectors. These are the packages which are included when using the
+\code{standAlone} option as well as when font metrics are calculated. If you
+use additional packages that affect fonts, such as \code{mathpazo}, or
+additional \LaTeX\ macros, such as \code{amsmath}, these packages should be
+added to this list.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(
+ tikzLatexPackages = c(
+ "\\usepackage{tikz}",
+ "\\usepackage[active,tightpage]{preview}",
+ "\\PreviewEnvironment{pgfpicture}",
+ "\\setlength\\PreviewBorder{0pt}")
+ ),
+
+ tikzXelatexPackages = c(
+ "\\usepackage{tikz}\n",
+ "\\usepackage[active,tightpage,xetex]{preview}\n",
+ "\\usepackage{fontspec,xunicode}\n",
+ "\\PreviewEnvironment{pgfpicture}\n",
+ "\\setlength\\PreviewBorder{0pt}\n"
+ ),
+
+ tikzLualatexPackages = c(
+ "\\usepackage{tikz}\n",
+ "\\usepackage[active,tightpage,psfixbb]{preview}\n",
+ "\\usepackage{fontspec,xunicode}\n",
+ "\\PreviewEnvironment{pgfpicture}\n",
+ "\\setlength\\PreviewBorder{0pt}\n"
+ )
+)
+\end{tikzCodeBlock}
+
+\begin{tikzCodeBlock}[title={Adding a package that affects fonts},listing style=sweavechunk]
+options( tikzLatexPackages = c(
+ getOption( "tikzLatexPackages" ),
+ "\\usepackage{mathpazo}"
+))
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzMetricPackages} and \pkgopt{tikzUnicodeMetricPackages} Options}
+
+Character vectors. These are the extra packages which are additionally loaded
+when doing font metric calculations. As you see below, the font encoding is
+set to Type 1. This is very important so that character codes of \LaTeX\ and
+\lang{R} match up. The Unicode metric packages are used when the \hologo{XeTeX}
+or \hologo{LuaTeX} engines are in use.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(
+ tikzMetricPackages = c(
+ "\\usepackage[T1]{fontenc}\n",
+ "\\usetikzlibrary{calc}\n"
+ ),
+
+ tikzUnicodeMetricPackages = c(
+ "\\usepackage[T1]{fontenc}\n",
+ "\\usetikzlibrary{calc}\n",
+ "\\usepackage{fontspec,xunicode}\n"
+ )
+)
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzFooter} Option}
+
+A character vector. This footer is appended to the end of the figure when
+\code{standAlone==TRUE} before the \verb|\end{document}| statement.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzFooter = "")
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzSanitizeCharacters} and \pkgopt{tikzReplacementCharacters} Options}
+
+\code{tikzSanitizeCharacters} is a character vector of special \LaTeX
+characters to replace while \code{tikzReplacementCharacters} is a character
+vector containing the corresponding replacements.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(
+ tikzSanitizeCharacters = c('%','$','}','{','^','_','#','&','~'),
+ tikzReplacementCharacters = c('\\%','\\$','\\}','\\{','\\^{}','\\_{}',
+ '\\#','\\&','\\char`\\~')
+)
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzLwdUnit} Option}
+
+Originally, 1 unit of line width in \lang{R} was translated to 0.4~pt.
+This results in lines that are thinner than with default graphics
+or with the PDF device.
+This option controls the translation factor~-- use \code{72.27 / 96}
+for compatibility with the \lang{R} default
+(96 pixels in \lang{R} is 1 inch, which is 72.27 points in \TeX{}).
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzLwdUnit = 72.27 / 96)
+\end{tikzCodeBlock}
+
+
+\subsection{The deprecated \pkgopt{tikzRasterResolution} Option}
+
+When \code{tikz} is requested to add a raster to a graphic, the raster is
+written to a PNG file which is then included by the \LaTeX\ code.
+In the current version, the raster is always written ``as is''
+(after mirroring has been applied) using \code{png::writePNG()}
+\citep{urbanek2013}.
+No resampling or transformation of any kind are applied in this process,
+rotation and interpolation are carried out by \LaTeX.
+
+
+\subsection{The \pkgopt{tikzPdftexWarnUTF} Option}
+
+A \code{TRUE/FALSE} value that controls whether warnings are printed if
+Unicode characters are sent to a device using the \hologo{pdfTeX} engine.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzPdftexWarnUTF = TRUE)
+\end{tikzCodeBlock}
+
+
+% -----------------------------------------------------------------------------
+% Chapter 3: The tikz Function
+% -----------------------------------------------------------------------------
+\chapter{The \code{tikz} Function}
+
+\section{Description}
+
+The \code{tikz} function provides most of the functionality of the
+\pkg{tikzDevice} package. This function opens an \lang{R} graphics device that
+records plots as a series of \TikZ\ commands. The device supports many levels
+of output that range from stand-alone \LaTeX\ documents that may be compiled
+into figures to code chunks that must be incorporated into existing \LaTeX\
+documents using the \verb`\include{}` macro.
+
+
+\section{Usage}
+
+The \code{tikz} function opens a new graphics device and may be called with
+the following arguments:
+
+<<tikzArgs, code=formatR::usage(tikz), eval=FALSE>>=
+@
+
+\begin{flexlabelled}{code}{*}{0.5em}{0.5em}{*}{\leftmargin}
+ \item[file]
+ A character string indicating the desired path to the output file. It is
+ recommended, but not required, that the filename end in \code{.tex}.
+
+ \item[width]
+ The width of the output figure, in \emph{inches}.
+
+ \item[height]
+ The height of the output figure, in \emph{inches}.
+
+ \item[onefile]
+ Controls whether output should be directed to a single file containing one
+ \code{tikzpicture} environment per plot or split into multiple files each
+ containing a single \code{tikzpicture} environment.
+
+ \item[bg]
+ The starting background color for the plot.
+
+ \item[fg]
+ The starting foreground color for the plot.
+
+ \item[pointsize]
+ Base pointsize used in the LaTeX document. This option is only referenced
+ if a valid pointsize cannot be extracted from the value of
+ \code{getOption("tikzDocumentDeclaration")}. See \autoref{subsec:fontCalc}
+ for more details.
+
+ \item[lwdUnit]
+ The number of \code{pt}s in LaTeX that \code{lwd=1} in R is translated to.
+ Defaults to 0.4 (LaTeX and TikZ default); for compatibility with R default,
+ please use 72.27/96 (96 pixels in R is 1 inch, which is 72.27 points in TeX).
+ See also \autoref{sec:options}, ``Options That Affect Package Behavior.''
+
+ \item[standAlone]
+ A logical value indicating whether the resulting file should be suitable
+ for direct processing by \LaTeX.
+
+ \item[bareBones]
+ A logical value indicating whether \TikZ\ code is produced without being
+ placed within a \code{tikzpicture} environment.
+
+ \item[console]
+ Controls whether output is directed to the \lang{R} console. This is useful
+ for dumping \TikZ\ output directly into a \LaTeX\ document via sink. If
+ \code{TRUE}, the \code{file} argument is ignored. Setting \code{file=\'{}\'{}} is
+ equivalent to setting \code{console=TRUE}.
+
+ \item[sanitize]
+ Should special latex characters be replaced (Default \code{FALSE}). See
+ \autoref{sec:options}, ``Options That Affect Package Behavior''
+ for which characters are replaced.
+
+ \item[engine]
+ A string specifying which \TeX{} engine to use. Possible values are
+ \code{'pdftex'}, \code{'xetex'} and \code{'luatex'}.
+
+ \item[documentDeclaration]
+ See \autoref{sec:options}, ``Options That Affect Package Behavior.''
+
+ \item[packages]
+ See \autoref{sec:options}, ``Options That Affect Package Behavior.''
+
+ \item[footer]
+ See \autoref{sec:options}, ``Options That Affect Package Behavior.''
+\end{flexlabelled}
+
+The first six options should be familiar to anyone who has used the default
+graphics devices shipped with \lang{R}. The options \code{standAlone}
+and \code{bareBones} are specific to the \code{tikz()} graphics device and
+affect the structure the output file. Using these options \code{tikz}
+supports three modes of output:
+
+\begin{itemize}
+ \item
+ Graphics production as complete \LaTeX\ files suitable for compilation.
+
+ \item
+ Graphics production as complete figures suitable for inclusion in \LaTeX\
+ files.
+
+ \item
+ Graphics production as raw figure code suitable for inclusion in an
+ enclosing \code{tikzpicture} environment in a \LaTeX\ file.
+\end{itemize}
+
+
+\section{Font Size Calculations}
+ \label{subsec:fontCalc}
+
+The overarching goal of the \pkg{tikzDevice} is to provide seamless integration
+between text in \lang{R} graphics and the text of \LaTeX\ documents that contain those
+graphics. In order to achieve this integration the device must translate font
+sizes specified in \lang{R} to corresponding font sizes in \LaTeX. The issue is
+that font sizes in \LaTeX\ are controlled by a ``base font size'' that is
+specified at the beginning of the document---typically 10pt. There is no easy
+way in \LaTeX\ to change the font size to a new numerical value, such as 16pt
+for a plot title. Fortunately, the \TikZ\ graphics system allows text to be
+resized using a scaling factor. The \pkg{tikzDevice} calculates a scaling
+factor used to approximate other font sizes using the following three inputs:
+
+\begin{itemize}
+ \item
+ The ``base font size'' specified when the graphics device is created.
+
+ \item
+ The ``character expansion factor'' parameter, specified using the `cex'
+ argument to functions such as described in the documentation of the \lang{R}
+ function \code{par}.
+
+ \item
+ The ``font size'' parameter, specified using the `ps' argument to functions
+ such as \code{par} or the `fontsize' argument to functions such as
+ \code{gpar}.
+\end{itemize}
+
+The calculation used is:
+
+\[
+ \mbox{Scaling Factor} = \mbox{cex} \cdot \frac{\mbox{ps}}{\mbox{base font size}}
+\]
+
+The tricky bit is the specification of the ``base font size''. By default the
+\pkg{tikzDevice} will attempt to determine this parameter by scanning the value of
+\code{options( "tikzDocumentDeclaration" )} using the regular expression
+\code{\textbackslash d+pt}. With the default header:
+\[
+ \mbox{\code{\textbackslash documentclass[10pt]\{article\}}}
+\]
+this regular expression will return 10 as the base pointsize to be used by the
+device. If the regular expression fails to produce a match, the value of the
+\code{pointsize} argument to the \code{tikz} function will be used.
+
+
+\subsection{UTF-8 Output}
+
+Version 0.6.0 of the \pkg{tikzDevice} introduced support for (multibyte)
+Unicode characters in the text of graphics through support for \hologo{XeTeX}.
+Version 0.7.0 extended multilingual typesetting further by adding support for
+the \hologo{LuaTeX} compiler. Unicode support in \pkg{tikzDevice} is subject to
+a few important caveats:
+
+\begin{description}
+ \item[System Requirements:]
+ A working version of \hologo{XeLaTeX} or \hologo{LuaLaTeX} along with the
+ packages \code{fontspec} and \code{xunicode} are required for direct
+ processing of Unicode input. If \pkg{tikzDevice} cannot find a Unicode-aware
+ compiler, then Unicode support cannot be guaranteed.
+
+ \item[Encoding:]
+ \pkg{tikzDevice} will try its best to convert characters from other
+ encodings but do not count on it converting things correctly, best to do
+ the conversion yourself beforehand to avoid unexpected output.
+
+ \item[Fonts:]
+ Having a Unicode character actually show up in your \LaTeX\ document relies
+ on the font you use having the glyph available. We leave it up to the user
+ to know for themselves what is available. Otherwise you will likely just
+ get no output in place of where the character should be.
+
+ \item[Plotmath:]
+ There is specifically no support for input of plotmath characters as
+ unicode since the user can simply input \LaTeX\ math directly. We strongly
+ encourage the use of \LaTeX\ math over plotmath for style and consistency's
+ sake. A consequence of this is that most of the \lang{R} examples and demos
+ of plotmath won't work without significant manipulation (your mileage may
+ vary but you may get anything from errors to warnings to documents that
+ mysteriously won't compile). That is not to say that the output could not
+ be duplicated with \pkg{tikzDevice} but the examples will not work out of
+ the box.
+
+ \item[Compiling:]
+ A graphic that contains UTF-8 characters should be compiled with
+ \hologo{XeLaTeX} or \hologo{LuaLaTeX} with the \code{xunicode} and
+ \code{fontspec} packages enabled.
+
+ \item[ASCII only:]
+ Everything should be exactly the same as previous versions if only ASCII
+ (single byte) characters are used (i.e. character codes less than 132).
+\end{description}
+
+
+
+\section{Examples}
+
+\subsection{Default Mode}
+
+The most common use of the \code{tikz} function is to produce a plot that
+will be included in another \LaTeX\ document, such as a report. Running the
+following example in \lang{R} will produce a very simple graphic using the
+\code{plot} function:
+
+<<simpleEx,echo=TRUE,results='hide'>>=
+library(tikzDevice)
+tikz('figs/simpleEx.tex',width=3.5,height=3.5)
+plot(1,main='Hello World!')
+dev.off()
+@
+
+A \LaTeX\ document is then required to display the figure. This document must
+include \TikZ\ as one of the packages that it loads. \TikZ\ provides several
+libraries that enable additional functionality, however none of these libraries
+are currently required to use the output of \code{tikz}. Inside the \LaTeX\
+document, the contents of the file \code{simpleEx.tex} are imported using the
+\verb|\include| command.
+
+\begin{figure}[H]
+ \centering
+
+ \begin{minipage}{0.5\textwidth}
+ \begin{tikzCodeBlock}[title={Example \LaTeX{} Document},listing style=latexsource,code body/.append style={codebody color=white}]
+\documentclass{article}
+
+% All LaTeX documents including
+% tikz() output must use this
+% package!
+\usepackage{tikz}
+
+\begin{document}
+ \begin{figure}[!h]
+ \centering
+
+ % The output from tikz()
+ % is imported here.
+ \input{simpleEx.tex}
+
+ \caption{Simple Example}
+ \end{figure}
+\end{document}
+ \end{tikzCodeBlock}
+ \end{minipage}
+ \hfill
+ \begin{minipage}{0.45\textwidth}
+ \input{figs/simpleEx.tex}
+ \end{minipage}
+ \caption{Example of simple \code{tikz} usage.}
+\end{figure}
+
+One of the most exciting aspects of the \code{tikz} function is that the
+inclusion of arbitrary \LaTeX\ code is allowed in strings passed to plotting
+commands. An important issue to note is that many \LaTeX\ commands are prefixed
+by the backaslash character: \textbackslash. Unfortunately, in many programming
+languages, the backslash character is also given a special status when it
+appears in strings. Therefore, it is necessary to place two backslashes,
+\textbackslash\textbackslash, in \lang{R} strings in order to cause backslash to
+appear in the output for \LaTeX. The next example demonstrates how to use
+\LaTeX\ commands in plot annotation.
+
+
+\begin{figure}[H]
+ \centering
+ \begin{minipage}{0.5\textwidth}
+<<latexEx,echo=TRUE,results='hide',tidy=FALSE>>=
+library(tikzDevice)
+tikz('figs/latexEx.tex',
+ width=3.5,height=3.5)
+
+x <- rnorm(10)
+y <- x + rnorm(5,sd=0.25)
+
+model <- lm(y ~ x)
+rsq <- summary( model )$r.squared
+rsq <- signif(rsq,4)
+
+plot(x, y, main='Hello \\LaTeX!')
+abline(model, col='red')
+
+mtext(paste("Linear model: $R^{2}=",
+ rsq, "$"), line=0.5)
+
+legend('bottomright', legend =
+ paste("$y = ",
+ round(coef(model)[2],3), 'x +',
+ round(coef(model)[1],3), '$',
+ sep = ''), bty = 'n')
+
+dev.off()
+@
+ \end{minipage}
+ \hfill
+ \begin{minipage}{0.45\textwidth}
+ \input{figs/latexEx.tex}
+ \end{minipage}
+ \caption{A more complicated example of \code{tikz} usage incorporating
+ natively rendered \LaTeX\ commands.}
+\end{figure}
+
+
+\subsection{\pkgopt{bareBones} Mode}
+
+\code{bareBones} output is designed to facilitate inclusion of code generated
+by \code{tikz} into a larger \TikZ\ graphic. Normally \code{tikz} wraps output
+as a self-contained \code{tikzpicture} environment. When \code{bareBones} is
+invoked, the wrapping environment is omitted. This option allows output to be
+embedded inside another \code{tikzpicture} of the user's own construction.
+
+<<bareBonesExample,echo=TRUE,results='hide',tidy=FALSE>>=
+library(tikzDevice)
+library(maps)
+
+tikz('figs/westCoast.tex', bareBones=TRUE)
+
+map('state', regions=c('california', 'oregon', 'washington'),
+ lwd=4, col='grey40')
+
+# Insert some named coordinates into the picture that will
+# be available once the picture is included into the
+# TeX document.
+tikzCoord(-124.161, 40.786, 'humBay')
+tikzCoord(-122.962, 46.148, 'longView')
+tikzCoord(-124.237, 43.378, 'coosBay')
+tikzCoord(-122.419, 37.775, 'sfBay')
+
+dev.off()
+@
+
+The \verb|\include| command may now be used to import the device output into
+another \code{tikzpicture}. The included code must be wrapped in a \code{scope}
+environment that contains the options \code{x=1pt} and \code{y=1pt}. This
+informs \TikZ\ of the units being used in the coordinates of the plot output.
+The options \code{xshift} and \code{yshift} may also be applied to the
+\code{scope} in order to position the plot. The following code demonstrates how
+to embed \code{bareBones} output in a \code{tikzpicture}:
+
+\begin{tikzCodeBlock}[title={Example of a \TikZ{} environment including \code{bareBones} output},
+ code body/.append style={codebody color=white},
+ listing style=latexsource]
+\begin{tikzpicture}
+
+ % Include bareBones output inside a scope with x and y units set to 1pt
+ \begin{scope}[x=1pt,y=1pt]
+ \input{figs/westCoast}
+ \end{scope}
+
+ % Label ports using coordinates placed into the barBones output by the
+ % tikzAnnotate function.
+ \foreach \name/\port in {
+ Longview/longView,
+ Coos Bay/coosBay,
+ Humboldt Bay/humBay,
+ Oakland/sfBay%
+ } {
+ \node[circle, draw, ultra thick, fill=green!60!brown!40,
+ outer sep=6pt,minimum size=12pt,
+ pin={[draw, ultra thick,
+ rounded corners,
+ pin edge={black, ultra thick, <-, >=stealth}
+ ] 180 : \name}] at (\port) {};
+ }
+
+\end{tikzpicture}
+\end{tikzCodeBlock}
+
+
+\begin{figure}[H]
+
+ \centering
+
+ \begin{tikzpicture}
+
+ \begin{scope}[x=1pt,y=1pt]
+ \input{figs/westCoast}
+ \end{scope}
+
+ \foreach \name/\port in {
+ Longview/longView,
+ Coos Bay/coosBay,
+ Humboldt Bay/humBay,
+ Oakland/sfBay%
+ } {
+ \node[circle, draw, ultra thick, fill=green!60!brown!40,
+ outer sep=6pt,minimum size=12pt,
+ pin={[draw, ultra thick,
+ rounded corners,
+ pin edge={black, ultra thick, <-, >=stealth}
+ ] 180 : \name}] at (\port) {};
+ }
+
+ \end{tikzpicture}
+
+ \caption{A \TikZ\ drawing with embedded output from \code{tikz(bareBones=TRUE)}.}
+\end{figure}
+
+\subsection{\pkgopt{standAlone} Mode}
+
+When the \code{standAlone} option is passed to \code{tikz}, the resulting
+\code{.tex} file will be a complete \LaTeX\ document that can be compiled into
+a stand-alone figure. This means that in addition to \verb|\begin{tikzpicture}|
+and \verb|\end{tikzpicture}| the file will also contain \verb|\begin{document}|,
+\verb|\end{document}| and a \LaTeX\ preamble. The \code{preview} package is also
+used in files produced by \code{standAlone} to crop the pages in the resulting
+document to the bounding boxes of the plots. Stand-alone output may be
+produced in the following manner:
+
+<<standAloneExample,echo=TRUE,results='hide',tidy=FALSE>>=
+library(tikzDevice)
+tikz('standAloneExample.tex',standAlone=TRUE)
+plot(sin,-pi,2*pi,main="A Stand Alone TikZ Plot")
+dev.off()
+@
+
+
+<<standAloneCompileExample, results='hide', eval=FALSE>>=
+
+ library(tools)
+
+ catch <- system(paste(Sys.which('pdflatex'),
+ '-interaction=batchmode -output-directory figs/ figs/standAloneExample.tex'),
+ ignore.stderr=T)
+
+ # If compiling the example failed, we don't want to include a broken link.
+ if( catch == 0 ){
+ pdfLink <- "The file \\\\code{standAloneExample.tex} may then be compiled to produce
+ \\\\href{./figs/standAloneExample.pdf}{standAloneExample.pdf}. "
+ }else{
+ pdfLink <- ""
+ }
+ #%\Sexpr{print(pdfLink)}
+@
+
+Note that files produced using the \code{standAlone} option should not be
+included in \LaTeX\ documents using the \verb|\input| command! Use
+\verb|\includegraphics| or load the \code{pdfpages} package and use
+\verb|\includepdf|.
+
+
+\subsection{\pkgopt{console} output Mode}
+
+Version 0.5.0 of \pkg{tikzDevice} introduced the \code{console} option. With
+this option, \code{tikz} will send output to \code{stdout} instead of a file.
+This kind of output can be redirected to a file with \code{sink} or spit out
+directly into a \TeX\ document from a \pkg{Sweave} file so that the \TeX\ file
+is self contained and does not include other files via \verb|\input|.
+(Including the chunk option \code{strip.white=FALSE} was necessary for some
+versions of \pkg{tikzDevice} prior to 0.7.2.)
+
+\tikzCodeInput[title={Catching \code{tikz} output inside Sweave},listing style=sweavechunk]{consoleExample}
+
+
+\subsection{Using \hologo{XeLaTeX}}
+
+It is also possible to use other typesetting engines like \hologo{XeLaTeX} by
+using the global options provided by \pkg{tikzDevice}. The following example
+was inspired by Dario Taraborelli and his article
+\href{http://nitens.org/taraborelli/latex}{The Beauty of LaTeX}.
+
+% `eval` normally set to `FALSE` as this example takes a long time to run and the
+% required fonts are only availble by default on OS X.
+<<xelatexFontVariantExample,tidy=FALSE,echo=TRUE,eval=FALSE,results='hide'>>=
+# Set options for using XeLaTeX font variants.
+options(tikzXelatexPackages = c(
+ getOption('tikzXelatexPackages'),
+ "\\usepackage[colorlinks, breaklinks]{hyperref}",
+ "\\usepackage{color}",
+ "\\definecolor{Gray}{rgb}{.7,.7,.7}",
+ "\\definecolor{lightblue}{rgb}{.2,.5,1}",
+ "\\definecolor{myred}{rgb}{1,0,0}",
+ "\\newcommand{\\red}[1]{\\color{myred} #1}",
+ "\\newcommand{\\reda}[1]{\\color{myred}\\fontspec[Variant=2]{Zapfino}#1}",
+ "\\newcommand{\\redb}[1]{\\color{myred}\\fontspec[Variant=3]{Zapfino}#1}",
+ "\\newcommand{\\redc}[1]{\\color{myred}\\fontspec[Variant=4]{Zapfino}#1}",
+ "\\newcommand{\\redd}[1]{\\color{myred}\\fontspec[Variant=5]{Zapfino}#1}",
+ "\\newcommand{\\rede}[1]{\\color{myred}\\fontspec[Variant=6]{Zapfino}#1}",
+ "\\newcommand{\\redf}[1]{\\color{myred}\\fontspec[Variant=7]{Zapfino}#1}",
+ "\\newcommand{\\redg}[1]{\\color{myred}\\fontspec[Variant=8]{Zapfino}#1}",
+ "\\newcommand{\\lbl}[1]{\\color{lightblue} #1}",
+ "\\newcommand{\\lbla}[1]{\\color{lightblue}\\fontspec[Variant=2]{Zapfino}#1}",
+ "\\newcommand{\\lblb}[1]{\\color{lightblue}\\fontspec[Variant=3]{Zapfino}#1}",
+ "\\newcommand{\\lblc}[1]{\\color{lightblue}\\fontspec[Variant=4]{Zapfino}#1}",
+ "\\newcommand{\\lbld}[1]{\\color{lightblue}\\fontspec[Variant=5]{Zapfino}#1}",
+ "\\newcommand{\\lble}[1]{\\color{lightblue}\\fontspec[Variant=6]{Zapfino}#1}",
+ "\\newcommand{\\lblf}[1]{\\color{lightblue}\\fontspec[Variant=7]{Zapfino}#1}",
+ "\\newcommand{\\lblg}[1]{\\color{lightblue}\\fontspec[Variant=8]{Zapfino}#1}",
+ "\\newcommand{\\old}[1]{",
+ "\\fontspec[Ligatures={Common, Rare},Variant=1,Swashes={LineInitial, LineFinal}]{Zapfino}",
+ "\\fontsize{25pt}{30pt}\\selectfont #1}%",
+ "\\newcommand{\\smallprint}[1]{\\fontspec{Hoefler Text}
+ \\fontsize{10pt}{13pt}\\color{Gray}\\selectfont #1}"
+))
+
+# Set the content using custom defined commands
+label <- c(
+ "\\noindent{\\red d}roo{\\lbl g}",
+ "\\noindent{\\reda d}roo{\\lbla g}",
+ "\\noindent{\\redb d}roo{\\lblb g}",
+ "\\noindent{\\redf d}roo{\\lblf g}\\\\[.3cm]",
+ "\\noindent{\\redc d}roo{\\lblc g}",
+ "\\noindent{\\redd d}roo{\\lbld g}",
+ "\\noindent{\\rede d}roo{\\lble g}",
+ "\\noindent{\\redg d}roo{\\lblg g}\\\\[.2cm]"
+)
+
+# Set the titles using custom defined commands, and hyperlinks
+title <- c(
+paste(
+ "\\smallprint{D. Taraborelli (2008),",
+ "\\href{http://nitens.org/taraborelli/latex}",
+ "{The Beauty of \\LaTeX}}"
+), paste(
+ "\\smallprint{\\\\\\emph{Some rights reserved}.",
+ "\\href{http://creativecommons.org/licenses/by-sa/3.0/}",
+ "{\\textsc{cc-by-sa}}}"
+))
+
+# Draw the graphic
+tikz('xelatexEx.tex',
+ standAlone=TRUE,width=5,height=5,
+ engine = 'xetex')
+lim <- 0:(length(label)+1)
+plot(lim,lim,cex=0,pch='.',xlab = title[2],ylab='', main = title[1])
+for(i in 1:length(label))
+ text(i,i,label[i])
+dev.off()
+@
+
+Compiling the resulting file with \hologo{XeLaTeX} will produce the output in
+\autoref{fig:xelatex}. Please note some of the fonts used in the example may
+not be available on every system.
+
+\begin{figure}[!h]
+\centering
+\includegraphics{img/xelatexEx.pdf}
+\caption{Result of \hologo{XeLaTeX} example}\label{fig:xelatex}
+\end{figure}
+
+
+\subsection{Annotating Graphics with \TikZ\ Commands}
+
+The function \code{tikzAnnotate} provides the ability to annotate you graphics
+with \TikZ\ commands. There are a lot of exciting possibilities with this
+feature---it basically opens up the door for you to draw anything on your plot
+that can be drawn with \TikZ. Check out the results in
+\autoref{fig:annotation}.
+
+<<annotation,echo=TRUE,results='hide',tidy=FALSE>>=
+library(tikzDevice)
+
+# Load some additional TikZ libraries
+tikz("figs/annotation.tex",width=4,height=4,
+ packages = c(getOption('tikzLatexPackages'),
+ "\\usetikzlibrary{decorations.pathreplacing}",
+ "\\usetikzlibrary{positioning}",
+ "\\usetikzlibrary{shapes.arrows,shapes.symbols}")
+)
+
+p <- rgamma (300 ,1)
+outliers <- which( p > quantile(p,.75)+1.5*IQR(p) )
+boxplot(p)
+
+# Add named coordinates that other TikZ commands can hook onto
+tikzCoord(1, min(p[outliers]), 'min outlier')
+tikzCoord(1, max(p[outliers]), 'max outlier')
+
+# Use tikzAnnotate to insert arbitrary code, such as drawing a
+# fancy path between min outlier and max outlier.
+tikzAnnotate(c("\\draw[very thick,red,",
+ # Turn the path into a brace.
+ 'decorate,decoration={brace,amplitude=12pt},',
+ # Shift it 1em to the left of the coordinates
+ 'transform canvas={xshift=-1em}]',
+ '(min outlier) --',
+ # Add a node with some text in the middle of the path
+ 'node[single arrow,anchor=tip,fill=white,draw=green,',
+ 'left=14pt,text width=0.70in,align=center]',
+ '{Holy Outliers Batman!}', '(max outlier);'))
+
+# tikzNode can be used to place nodes with customized options and content
+tikzNode(
+ opts='starburst,fill=green,draw=blue,very thick,right=of max outlier',
+ content='Wow!'
+)
+
+dev.off()
+@
+
+\begin{figure}[!h]
+\centering
+\input{figs/annotation.tex}
+\caption{An example using \TikZ\ annotation.}\label{fig:annotation}
+\end{figure}
+
+\begin{landscape}
+
+\subsection{\pkgopt{tikz} vs. \pkgopt{pdf} for \pkgopt{plotmath} symbols and Unicode characters}
+
+This is a side-by-side example showing how \code{tikz(..., engine = 'xetex')} handles UTF-8
+characters and plotmath symbols compared to the standard \lang{R} \code{pdf} device.
+
+\begin{figure}[!h]
+\centering
+ \begin{minipage}{4.25in}
+ \includegraphics[width=4.25in]{img/plotmathDefault.pdf}
+ \caption{\code{example(text)} using the standard \code{pdf()} device.}\label{fig:plotmathDefault}
+ \end{minipage}
+ \vspace{1em}
+ \begin{minipage}{4.25in}
+ \includegraphics[width=4.25in]{img/plotmathTikz.pdf}
+ \caption{\code{example(text)} using \code{tikz(..., engine = 'xetex')}.}\label{fig:plotmathTikz}
+ \end{minipage}
+\end{figure}
+
+\end{landscape}
+
+
+% -----------------------------------------------------------------------------
+% Chapter 4: The Metrics Functions
+% -----------------------------------------------------------------------------
+\chapter{The \code{getLatexCharMetrics} and \code{getLatexStrWidth} Functions}
+
+\section{Description}
+
+These two functions may be used to retrieve font metrics through the interface
+provided by the \pkg{tikzDevice} package. Cached values of the metrics are
+returned if they have been calculated by the \pkg{tikzDevice} before. If no
+cached values exist, a \LaTeX\ compiler will be invoked to generate them.
+
+\section{Usage}
+
+The font metric functions are called as follows:
+
+\begin{Verbatim}[frame=single]
+getLatexStrWidth( texString, cex = 1, face= 1)
+
+getLatexCharMetrics( charCode, cex = 1, face = 1 )
+\end{Verbatim}
+
+\begin{flexlabelled}{code}{*}{0.5em}{0.5em}{*}{\leftmargin}
+ \item[texString]
+ A string for which to compute the width. \LaTeX\ commands may be used in
+ the string, however all backslashes will need to be doubled.
+
+ \item[charCode]
+ An integer between 32 and 126 which indicates a printable character in the
+ ASCII symbol table using the T1 font encoding.
+
+ \item[cex]
+ The character expansion factor to be used when determining metrics.
+
+ \item[face]
+ An integer specifying the \lang{R} font face to use during metric
+ calculations. The accepted values are as follows:
+
+ \begin{description}
+ \item[1:]
+ Text should be set in normal font face.
+ \item[2:]
+ Text should be set in {\bfseries bold font face}.
+ \item[3:]
+ Text should be set in {\itshape italic font face}.
+ \item[4:]
+ Text should be set in {\bfseries\itshape bold italic font face}.
+ \item[5:]
+ Text should be interpreted as \code{plotmath} symbol characters.
+ Requests for font face 5 are currently ignored.
+ \end{description}
+\end{flexlabelled}
+
+\section{Examples}
+
+The \code{getLatexStrWidth} function may be used to calculate the width of
+strings containing fairly arbitrary \LaTeX\ commands. For example, consider
+the following calculations:
+
+
+<<strWidthDemo,echo=T>>=
+getLatexStrWidth( "The symbol: alpha" )
+getLatexStrWidth( "The symbol: $\\alpha$" )
+@
+
+For the first calculation, the word ``alpha'' was interpreted as just a word and
+the widths of the characters `a', `l', `p', `h' and `a' were included in the
+string width. For the second string, \verb|\alpha| was interpreted as a
+mathematical symbol and only the width of the symbol `$\alpha$' was included in
+the string width.
+
+The \code{getLatexCharWidth} function must be passed an integer corresponding
+to an ASCII character code and returns three values:
+
+\begin{itemize}
+ \item
+ The \code{ascent} of the character. This is the distance between the
+ baseline and the highest point of the character's glyph.
+
+ \item
+ The \code{descent} of the character. This is the distance between the baseline and
+ the lowest point of the character's glyph.
+
+ \item
+ The width of the character.
+\end{itemize}
+
+The character `y' has an \code{ASCII} symbol code of 121 and possesses a tail
+that descends below the text line. Therefore a non-zero value will be returned
+for the descent of `y'. The character `x', \code{ASCII} code 120, has no
+descenders, so its descent will be returned as zero.
+
+<<charMetricDemo,echo=T,tidy=FALSE>>=
+# Get metrics for 'y'
+getLatexCharMetrics(121)
+
+# Get metrics for 'x' - the second value is the descent
+# and should be zero or very close to zero.
+getLatexCharMetrics(120)
+@
+
+Note that characters, along with numbers outside the range of [32--126], may not
+be passed to the \nolinebreak\code{getLatexCharMetrics} function. If for
+some reason a floating point number is passed, it will be floored through
+conversion by \code{as.integer}.
+
+<<charMetricErrors,echo=T,tidy=FALSE>>=
+getLatexCharMetrics('y')
+getLatexCharMetrics(20)
+
+# Will return metrics for 'y'
+getLatexCharMetrics(121.99)
+@
+
+
+
+\part{Installation Guide}
+ \label{part:installation}
+
+\chapter{Obtaining a \LaTeX\ Distribution}
+
+This section offers pointers on how to obtain a \LaTeX\ distribution if there
+is not one already installed on your system. The distributions detailed in this
+section are favorites of the \pkg{tikzDevice} developers as they provide integrated
+package managers which greatly simplify the process of installing additional
+\LaTeX\ packages. Currently this section is not, and may never be, a
+troubleshooting guide for \LaTeX\ installation. For those unfortunate
+situations we refer the user to the documentation of each distribution.
+
+A \LaTeX\ distribution provides the packages and support programs required by
+the \pkg{tikzDevice} and the documents that use its output. In addition to a
+\LaTeX\ compiler, a few extension packages are required.
+\autoref{tikz:required} describes how to obtain and install these packages.
+
+\section{Windows}
+
+Windows users will probably prefer the MiKTeX distribution available at
+\url{http://www.miktex.org}. An amazing feature of the MiKTeX distribution is
+that it contains a package manager that will attempt to install missing
+packages on-the-fly. Normally when \LaTeX\ is compiling a document that tries
+to load a missing package it will wipe out with a warning message. When the
+MiKTeX compilers are used compilation will be suspended while the new package
+is downloaded.
+
+% Perhaps a mention of the new portable MiKTeX distribution that can be run off
+% of a thumbdrive? I haven't used it yet so I don't feel qualified to discuss it at this
+% time.
+
+
+\section{UNIX/Linux}
+
+For users running a Linux or UNIX operating system, we recommend the TeX Live
+distribution which is available at
+\url{http://www.tug.org/texlive/acquire.html}. TeX Live is maintained by the
+TeX Users Group and a new version is released every year.
+We recommend using TeX Live 2008 or higher as the \code{tlmgr} package
+manager was introduced in the 2008 distribution. Using \code{tlmgr} greatly
+simplifies the adding and removing packages from the distribution. The website
+offers an installation package, called \code{install-tl.tar.gz} or something
+similar, that contains a shell script that can be used to install an up-to-date
+version of the TeX Live distribution.
+Note that the version
+of TeX Live provided by many Linux package management systems sometimes
+lags behind the version provided directly by the TeX Users Group.
+
+\section{Mac OS X}
+
+For users running Apple's OS X, we recommend the Mac TeX package available at
+\url{http://www.tug.org/mactex/}. Mac TeX is basically TeX Live packaged inside
+a convenient OS X installer along with a few add-on packages. One striking
+difference between the Mac TeX and TeX Live installers is that the installer
+for Mac TeX includes the whole TeX Live distribution in the initial download-
+for TeX Live 2013 this amounts to approximately 2.3 GB. This is quite a large
+download that contains several packages that the average or even advanced user
+will never ever use. To conserve time and space we recommend installing from
+the basic installer at \url{http://www.tug.org/mactex/morepackages.html} and
+using the \code{tlmgr} utility to add desired add-on packages.
+
+Adam R. Maxwell has created a very nice graphical interface to \code{tlmgr} for
+OS X called the TeX Live Utility. It may be obtained from
+\url{http://code.google.com/p/mactlmgr/} and we highly recommend it.
+
+
+\section{Installing \TikZ\ and Other Packages}
+ \label{tikz:required}
+
+Unsurprisingly, \pkg{tikzDevice} requires the \TikZ\ package to be installed
+and available in order to function properly. \TikZ\ is an abstraction of a
+lower-level graphics language called \lang{PGF} and both are distributed as the
+the \code{pgf} package. Users who do no have a full \TeX\ installation will
+also need to install a few more required packages:
+
+\begin{flexlabelled}{pkg}{0pt}{0.5em}{0.5em}{*}{\leftmargin}
+
+ \item[pgf]{As mentioned, provides \TikZ.}
+ \item[preview]{Used to crop documents in order to produce standalone figures.}
+ \item[ms]{Martin Schröder's LaTeX packages. \code{everyshi.sty} lets us run commands at every shipped page.}
+ \item[graphics]{\hologo{LaTeX}'s general-purpose graphics inclusion functionality.}
+ \item[pdftex-def]{Device-specific colour and graphics definitions when running \hologo{pdfTeX}/\hologo{pdfLaTeX}.}
+ \item[oberdiek]{\code{infwarerr.sty} provides info/error/warning messages}
+ \item[ec]{(Font metrics for) the default font, European Computer Modern.}
+ \item[xcolor]{Used by \TikZ\ to specify colors.}
+ \item[fontspec]{Used by \hologo{LuaTeX} and \hologo{XeTeX} to select fonts.}
+ \item[xunicode]{Assists \hologo{LuaTeX} and \hologo{XeTeX} with UTF-8 characters.}
+
+\end{flexlabelled}
+
+
+\subsection{Using a \LaTeX\ Package Manager}
+
+The easiest way to install \LaTeX\ packages is by using a distribution that
+includes a package manager such as MiKTeX or TeX Live/Mac TeX. For Windows
+users, the MiKTeX package manager usually handles package installation
+automagically during compilation of a document that is requesting a missing
+package. The MiKTeX package manager, \code{mpm}, can also be run manually from
+the command prompt:
+
+\begin{tikzCodeNode}[title={Using \code{mpm} to install packages},listing style=bashsource,code body/.append style={codebody color=white}]
+mpm --install packagename
+\end{tikzCodeNode}
+
+For versions of TeX Live and Mac TeX dated 2008 or newer, the \code{tlmgr}
+package manager is used in an almost identical manner:
+
+\begin{tikzCodeNode}[title={Using \code{tlmgr} to install packages},listing style=bashsource,code body/.append style={codebody color=white}]
+tlmgr install packagename
+\end{tikzCodeNode}
+
+\subsection{Manual Installation}
+
+Sometimes an automated package manager cannot be used. Common reasons may be
+that one is not available, as is the case with the TeX Live 2007 distribution,
+or that when running the package manager you do not have write access to the
+location where \LaTeX\ packages are stored, as is the case with accounts on
+shared computers. If this is the case, a manual install may be the best option
+for making a \LaTeX\ package available.
+
+Generally, the best place to find \LaTeX\ packages is the Comprehensive TeX
+Archive Network, or \lang{CTAN} located at \url{http://www.ctan.org}. In the
+case of the PGF/\TikZ\ package, the project homepage at
+\url{http://www.sourceforge.net/projects/pgf} is also a good place to obtain
+the package---especially if you would like to play with the bleeding-edge
+development version.
+
+Generally speaking, all \LaTeX\ packages are stored in a specially directory
+called a \code{texmf} folder. Most \TeX\ distributions allow for each user to
+have their own personal \code{texmf} folder somewhere in their home path. The
+most usual locations, and here {\bfseries\itshape usual} is an unfortunately
+loose term, are as follows:
+
+\begin{tikzCodeNode}[title={For UNIX/Linux},listing style=bashsource,code body/.append style={codebody color=white}]
+~/texmf
+\end{tikzCodeNode}
+
+\begin{tikzCodeNode}[title={For Mac OS X},listing style=bashsource,code body/.append style={codebody color=white}]
+~/Library/texmf
+\end{tikzCodeNode}
+
+\begin{tikzCodeNode}[title={For Windows, using MiKTeX},listing style=bashsource,code body/.append style={codebody color=white}]
+# None predefined. However the following command will open
+# the MiKTeX options panel and a new texmf folder may be assigned
+# under the "Roots" tab.
+mo
+\end{tikzCodeNode}
+
+
+The location of files and subfolders in the \code{texmf} directory should
+follow a standard pattern called the \TeX\ Directory Structure or TDS which is
+documented here: \url{http://tug.org/tds/tds.pdf}. Fortunately, most packages
+available on \pkg{CTAN} are archived in such a way that they will unpack into
+a TDS-compliant configuration. TDS-compliant archives usually have the phrase
+\code{tds} somewhere in their filename and may be installed from a UNIX
+shell\footnote{Sorry Windows users, we enjoy using command prompt about as much
+as a poke in the eye with a sharp stick. Hence we don't use it enough to offer
+advice. May we suggest \href{http://www.cygwin.com}{Cygwin}?} like so:
+
+\begin{tikzCodeNode}[title={Installing \LaTeX{} package archives},listing style=bashsource,code body/.append style={codebody color=white}]
+# For zip files.
+unzip package.tds.zip -d /path/to/texmf
+
+# For tarballs.
+tar -xzf -C /path/to/texmf package.tar.gz
+\end{tikzCodeNode}
+
+For packages that aren't provided in TDS-compliant form look for installation
+notes---usually provided in the form of an \code{INSTALL} file. If all else
+fails \LaTeX\ packages can usually be installed by copying the files ending in
+\code{.sty} to \code{texmf/tex/latex/}.
+
+After package files have been unpacked to a \code{texmf} folder, the database
+of installed packages needs to be updated for the \LaTeX\ compiler to take
+notice of the additions. This is done with the \code{mktexlsr} command:
+
+\begin{tikzCodeNode}[title={Registering new \LaTeX{} packages},listing style=bashsource,code body/.append style={codebody color=white}]
+mktexlsr
+
+# Successful package installation can be checked by running the
+# kpsewhich command. For a package accessed in a document
+# by \usepackage{package}, kpsewhich should return a path to
+# package.sty
+kpsewhich tikz.sty
+!out/Users/Smithe/Library/texmf/tex/latex/pgf/frontendlayer/tikz.sty!/out
+\end{tikzCodeNode}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Listing commands cannot be saved in macros, so we execute them here and stash
+% the output in a box.
+\newsavebox{\programflow}
+\begin{lrbox}{\programflow}
+\begin{tikzpicture}
+
+ \node[text width = 4.3in] (r code) {
+ \begin{tikzCodeNode}[title={\lang{R} User Types}, listing style=sweavechunk]
+tikz('Rplot.tex')
+plot(1)
+dev.off()
+ \end{tikzCodeNode}
+ };
+
+ \node[below = \baselineskip of r code, text width = 4.3in] (c code) {
+ \begin{tikzCodeNode}[title={TikZ Device Translates}, listing style = csource]
+static void TikZ_Circle( double x, double y, double r,
+ const pGEcontext plotParams, pDevDesc deviceInfo){
+
+...
+
+ printOutput(tikzInfo,"\n\\path[");
+ TikZ_WriteDrawOptions(plotParams, deviceInfo, ops);
+
+ /* End options, print coordinates. */
+ printOutput(tikzInfo, "] (%6.2f,%6.2f) circle (%6.2f);\n",
+ x,y,r);
+}
+ \end{tikzCodeNode}
+ };
+
+ \node[below = \baselineskip of c code, text width = 4.3in] (latex code) {
+ \begin{tikzCodeNode}[title={\LaTeX\ Output is Produced}, listing style = latexexample]
+% Created by tikzDevice
+% !TEX encoding = UTF-8 Unicode
+\begin{tikzpicture}[x=1pt,y=1pt]
+
+...
+
+\path[draw=drawColor,line width= 0.4pt,
+ line join=round,line cap=round]
+ (264.94,258.95) circle ( 2.25);
+
+...
+
+\end{tikzpicture}
+ \end{tikzCodeNode}
+ };
+
+\end{tikzpicture}
+\end{lrbox}
+
+
+\partimage{
+ \node[above left = 1in of current page.south east,
+ anchor = south east,
+ scale = 1.25
+ ]
+ % Here we use the box containing the output.
+ {\usebox{\programflow}};
+}
+
+\part{Package Internals}
+ \label{part:implementation}
+
+\epigraph{We will encourage you to develop the three great virtues of a programmer: {\itshape laziness}, {\itshape impatience}, and {\itshape hubris}.}{{\itshape Programming Perl}\\ --{\scshape Larry Wall}}
+
+\chapter{Introduction and Background}
+
+
+We learn best through working with examples. When it comes to programming languages this involves taking working code that someone else has written, breaking it in as many places at it can possibly be broken, and then trying to build something out of the wreckage. Open source software facilitates this process wonderfully by ensuring the source code of a project is always available for inspection and experimentation. The \pkg{tikzDevice} its self was created by disassembling and then rebu [...]
+
+This section is our attempt to help anyone who may be experimenting with our code, and by extension the internals of the \lang{R} graphics system. There may also be useful, or useless, tidbits concerning building \lang{R} packages and interacting with the core \lang{R} language. The \lang{R} language can be extended in so many interesting and useful ways and it is our hope that the following documentation may provide a case study for anyone attempting such an extension.
+
+We will make an attempt to assume no special expertise with any of the systems or programming languages leveraged by this package and described by this documentation. Therefore, if you are an experienced developer and find yourself thinking ``My god, are they {\bfseries really} about to launch into a description of how \lang{C} header files work?'', please feel free to skip ahead a few paragraphs. We received our formal introduction to computer programming in a college engineering progra [...]
+
+Therefore, this section is for all the budding developers like ourselves out there---people who have done some programming and who are starting to take a close look at the nuts and bolts of the \lang{R} programming environment. If you feel like you are wandering through a vast forest getting smacked in the face by every branch then maybe this section will help pull some of those branches out of the way...
+
+...then again we have a lot of material to cover: \lang{R}, \lang{C}, \LaTeX , \TikZ{} , typography and the details of computerized font systems. Our grip may fail and send those branches flying back with increased velocity.
+
+We wish you luck!\\
+\vbox{}\quad{\itshape -The tikzDevice Team}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\chapter{Anatomy of an \lang{R} Graphics Device}
+
+The core of an \lang{R} graphics device is a collection of functions, written in \lang{C}, that perform various specialized tasks. A description of some of these functions can be found in the {\itshape R Internals} manual while the main documentation is in the \lang{C} header file \code{GraphicsDevice.h}. For most \lang{R} installations this header file can be found in the directory \code{R\_HOME/include/R\_ext}. For copies of \lang{R} distributed in source code form, \code{GraphicsDevic [...]
+
+
+\setlength\columnsep{5em}
+
+\begin{multicols}{2}
+
+
+\section{Drawing Routines}
+
+\begin{itemize}
+
+\item[\code{circle}]{This function is required to draw a circle centered at a given location with a given radius.}
+
+\item[\code{clip}]{This function specifies a rectangular area to be used a a clipping boundary for any device output that follows.}
+
+\item[\code{line}]{This function draws a line between two points.}
+
+\item[\code{polygon}]{This function draws lines between a list of points and then connects the first point to the last point.}
+
+\item[\code{polyline}]{This function draws lines between a list of points.}
+
+\item[\code{rect}]{This function is given a lower left corner and an upper right corner and draws a rectangle between the two.}
+
+\item[\code{text}]{This function inserts text at a given location.}
+
+\end{itemize}
+
+\section{Font Metric Routines}
+
+\begin{itemize}
+
+\item[\code{metricInfo}]{This function is given the name of a single character and reports the ascent, descent and width of that character.}
+
+\item[\code{strWidth}]{This function is given a text string and reports the width of that string.}
+
+\end{itemize}
+
+\section{Utility Routines}
+
+\begin{itemize}
+
+\item[\code{activate}]{This function is called when the device is designated as the active output device---i.e. by using \code{dev.set()} in \lang{R}}
+
+\item[\code{close}]{This function is called when the device is shut down---i.e. by using \code{dev.off()} in \lang{R}}
+
+\item[\code{deactivate}]{This function is called when another device is designated as the active output device.}
+
+\item[\code{locator}]{This function is mainly used by devices with a GUI window and reports the location of a mouseclick.}
+
+\item[\code{mode}]{This function is called when a device begins drawing output and again when the device finishes drawing output.}
+
+\item[\code{newPage}]{This function initiates the creation of a new page of output.}
+
+\item[\code{size}]{This function reports the size of the canvas the device is drawing on.}
+
+\end{itemize}
+
+\end{multicols}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\chapter{Calculating Font Metrics}
+
+Font metrics are measurements associated with the glyphs, or printed characters, of a particular font. \lang{R} requires three of these metrics in order to produce correctly aligned output. The three metrics graphics devices are required to supply are:
+
+\begin{tikzpicture}
+
+\coordinate (centerpoint) at (0,0);
+
+\node[anchor=north,outer sep=0pt] (title) at ($(centerpoint) + (4em,0)$) {\bfseries Ascent};
+
+\node[scale=4,text=black!40,inner sep=0pt,outer sep=0pt,below=0.25em of title] (char) {g};
+\draw[color=black,very thick] (char.base west) -- (char.base east);
+\draw[color=black,very thick] (char.north west) -- (char.north east);
+\draw[color=red,very thick,<->,>=stealth] ([xshift=10pt]char.base west) -- ([xshift=10pt]char.north west);
+
+
+\newdimen\yone
+\newdimen\ytwo
+
+\pgfextracty{\yone}{\pgfpointanchor{char}{north}}
+\pgfextracty{\ytwo}{\pgfpointanchor{char}{south}}
+\pgfmathparse{ \yone - \ytwo }
+
+\yone = \pgfmathresult pt
+
+\node[anchor = north west,outer sep=0pt,text width=0.6\textwidth] at ($(centerpoint) + (8em, 0)$){
+Ascent is the distance between the baseline and the tallest point on a
+character's glyph. For the ``g'' printed to the left, the ascent has been
+calculated as: \the\yone
+};
+\end{tikzpicture}
+
+
+
+\begin{tikzpicture}
+
+\coordinate (centerpoint) at (0,0) {};
+
+\node[anchor=north,outer sep=0pt] (title) at ($(centerpoint) + (4em,0)$) {\bfseries Descent};
+
+\node[scale=4,text=black!40,inner sep=0pt,outer sep=0pt,below= 0.25em of title.south] (char) {g};
+\draw[color=black,very thick] (char.base west) -- (char.base east);
+\draw[color=black,very thick] (char.south west) -- (char.south east);
+\draw[color=red,very thick,<-,>=stealth] ([xshift=10pt]char.south west) -- +(0,-6pt);
+\draw[color=red,very thick,<-,>=stealth] ([xshift=10pt]char.base west) -- +(0,+6pt);
+
+
+\newdimen\yone
+\newdimen\ytwo
+
+\pgfextracty{\yone}{\pgfpointanchor{char}{base}}
+\pgfextracty{\ytwo}{\pgfpointanchor{char}{south}}
+\pgfmathparse{ \yone - \ytwo }
+
+\yone = \pgfmathresult pt
+
+\node[anchor = north west,outer sep=0pt,text width=0.6\textwidth] at ($(centerpoint) + (8em, 0)$){
+Descent is the distance between the baseline and the lowest point on a
+character's glyph. For the ``g'' printed to the left, the descent has been
+calculated as: \the\yone
+};
+\end{tikzpicture}
+
+
+
+\begin{tikzpicture}
+
+\coordinate (centerpoint) at (0,0);
+
+\node[outer sep=0pt,anchor=north] (title) at ($(centerpoint) + (4em,0)$) {\bfseries Width};
+
+\node[scale=4,text=black!40,inner sep=0pt,outer sep=0pt,below= 0.25em of title.south] (char) {g};
+\draw[color=black,very thick] (char.south west) -- (char.north west);
+\draw[color=black,very thick] (char.south east) -- (char.north east);
+\draw[color=red,very thick,<->,>=stealth] (char.base west) -- (char.base east);
+
+\newdimen\xone
+\newdimen\xtwo
+
+\pgfextractx{\xone}{\pgfpointanchor{char}{east}}
+\pgfextractx{\xtwo}{\pgfpointanchor{char}{west}}
+\pgfmathparse{ \xone - \xtwo }
+
+\xone = \pgfmathresult pt
+
+\node[anchor = north west,outer sep=0pt,text width=0.6\textwidth] at ($(centerpoint) + (8em, 0)$){
+Width is the distance between the left and right sides of a character's glyph.
+For the ``g'' printed to the left, the width has been calculated as: \the\xone};
+\end{tikzpicture}
+
+Providing font metrics and string widths is without a doubt the most difficult task a \lang{R} graphics device must undertake. The calculation of string widths is made even more difficult for the \pkg{tikzDevice} as we attempt to process arbitrary \LaTeX{} strings. Inside \lang{R} the string ``\verb`$\alpha$`'' literally has 8 characters, but when it is typeset it only has one: $\alpha$.
+
+Calculating font metrics is a tricky business to begin with and the fact that the typeset representation of a \LaTeX{} string is different from its representation in source code compounds the difficulty of the task immensely. Therefore, we took the path of laziness and started looking for an easy way out (remember the three great virtues of a programmer?). The solution we came up with seemed easy enough---make \LaTeX{} calculate these metrics for us, after all that is what a \LaTeX{} com [...]
+
+Now, how to do that?
+
+\subsection{Character Metrics}
+
+As a starting point, let's examine the interface of the \lang{C} function that \lang{R} calls in order to determine character metrics:
+
+\begin{tikzCodeBlock}[title={Function declaration for \code{metricInfo}}]
+void (metricInfo)(int c, const pGEcontext gc,
+ double* ascent, double* descent, double* width,
+ pDevDesc dd);
+\end{tikzCodeBlock}
+
+The most important variables involved in the function are \code{c}, \code{ascent}, \code{descent} and \code{width}. The incoming variable is \code{c}, which contains the character for which \lang{R} is requesting font metrics. Interestingly, \code{c} is passed as an integer, not a character as one might expect. What's up with that? Well, the short answer is that \lang{R} passes the \code{ASCII} or \code{UTF8} {\itshape symbol code} of a character and not the character itself. How to use [...]
+
+The outgoing variables are \code{ascent}, \code{descent} and \code{width}. The asterisks, `*', in their definitions mean these variables are passed as {\itshape pointers} as opposed to {\itshape values}. A complete discussion of the differences between pointers and values could, and has, filled up several chapters of several programming books. The important distinction in context of the \code{metricInfo} function is that when a number is assigned to a pointer variable, that number is ava [...]
+
+The other two variables present in the function are the \code{pGEcontext} variable \code{gc} and the \code{pDevDesc} variable \code{dd}. \code{gc} contains information such as the font face, foreground color, background color, character expansion factor, ect. currently in use by the graphics system. \code{dd} is the object which contains \lang{R}'s representation of the graphics device. For the sake of simplifying the following discussion, we will ignore these variables.
+
+So, to recap---we have an integer \code{c} coming in that represents a code for a character in the \code{ASCII} or \code{UTF8} symbol tables (for the sake of the following discussion, we will assume \code{ASCII} characters only). Our overall task is to somehow turn that integer into three numbers which can be assigned to the pointer variables \code{ascent}, \code{descent} and \code{width}. And, since we're being lazy, we've decided that the best way to do that is to ask the \LaTeX{} comp [...]
+
+Recovering these numbers from the \LaTeX{} compiler involves the execution of three additional tasks:
+
+\begin{enumerate}
+
+ \item{We must write a \LaTeX{} input file that contains instructions for calculating the metrics.}
+
+ \item{We call the \LaTeX{} compiler to process that input file.}
+
+ \item{We must read the compiler's output in order to recover the metrics.}
+
+\end{enumerate}
+
+Each of these tasks could be executed from inside our \lang{C} function, \code{metricInfo}. However, we will run into some difficulties---namely with step 2, which involves calling out to the operating system with orders to run \LaTeX . Each operating system handles these calls a little differently and our package must attempt to get this job done whether it is running on Windows, UNIX, Linux or Mac OS X.
+
+Portable \lang{C} code could be written to handle each of these situations, but that is starting to sound like work and we're trying to be lazy here. What we need is to be able to work at a higher {\itshape level of abstraction}. That is---instead of using \lang{C}, we need to be working inside a language that shields us from such details as what operating system is being used. \lang{R} may have called this \lang{C} function to calculate font metrics, but we really want to do the actual [...]
+
+\subsection{Calling \lang{R} Functions from \lang{C} Functions}
+
+The ``Ritual of the Calling of the \lang{R} Function'' is easy enough to perform as long as you don't have burning need to know all the details of the objects you are handling. The \lang{C} level representation of a \lang{R} object such as a variable or function is an object known as a \code{SEXP}. For the exact details on what a \code{SEXP} is and how it works, we refer the interested user to chapter one of the {\itshape \lang{R} Internals} manual.
+
+The \lang{R} function we will be calling is declared in the \lang{R} environment as follows:
+
+\begin{tikzCodeBlock}[title={Definition of target \lang{R} function},listing style=sweavechunk]
+getLatexCharMetrics <- function( charCode ){
+
+ # System call to LaTeX
+
+}
+\end{tikzCodeBlock}
+
+In order to call this function for \lang{C}, we need a vector composed of two \lang{C}-level \lang{R} objects---one containing the name of the function we are calling and another one containing the value we are passing for \code{charCode}. This is set up in \lang{C} as follows:
+
+\begin{tikzCodeBlock}[title={Preparing a \lang{R} function call inside \lang{C}}]
+void (metricInfo)(int c, const pGEcontext gc, double* ascent, double* descent,
+ double* width, pDevDesc dd){
+
+ SEXP RCallBack;
+ PROTECT( RCallBack = allocVector(LANGSXP, 2) );
+
+ SEXP metricFun = findFun( install("getLatexCharMetrics"), R_Global_Env );
+
+ SETCAR( RCallBack, metricFun );
+
+ SETCADR( RCallBack, ScalarInteger( c ) );
+ SET_TAG( CDR( RCallBack ), install("charCode") );
+
+ \\ To be continued...
+
+}
+\end{tikzCodeBlock}
+
+The first thing that happens in the code chunk above is that a new \code{SEXP} variable named \code{RCallBack} is created. This variable will be the agent through which we will communicate with the \lang{R} environment. The next action is to allocate our callback variable as a vector of length 2-- we need one slot for the \lang{R} function name and one slot for the value that is being passed into the function. This allocation happens inside the \lang{R} environment, so it is executed ins [...]
+
+The next portion of the \lang{C} function retrieves the \lang{R} function object for \code{getLatexCharMetrics}. The function is searched for in \lang{R} global namespace, so it must be one that is available to the user from the \lang{R} command prompt when the package is loaded. The function is stored in the \code{SEXP} variable \code{metricFun}. We do not have to involve \code{PROTECT} in the assignment since \code{getLatexCharMetrics} exists as a variable name in the \lang{R} environment.
+
+The last portion of the code chunk is responsible for loading the function name and call value into \code{RCallBack}. The \code{CAR} statement is used to retrieve the value of a \code{SEXP} variable and the \code{SETCAR} statement is used to set the value of a \code{SEXP}. In this case we use \code{SETCAR} to designate the \lang{R} function stored in \code{metricFun} as the first value of \code{RCallBack}.
+
+When dealing with a vector \code{SEXP} such as \code{RCallBack}, which has 2 slots, we need to use a different function to access the second slot. The \code{CDR} function will allow us to move to the second slot in \code{RCallBack} where we may perform a \code{SETCAR} to specify a value. In the example code, these operations were combined by using the \code{SETCADR} function which has the same effect as:
+
+\begin{tikzCodeBlock}[listing style=sweavechunk]
+SETCAR( CDR(RCallBack), ScalarInteger( c ) );
+\end{tikzCodeBlock}
+
+After assigning the value of the \lang{C} variable \code{c} as the second value of \code{RCallBack}, we need to ``tag'' it as the value that corresponds to the \code{charCode} argument of \code{getLatexCharMetrics}. This is done by using the \code{SET\_TAG} function. Once again, we use \code{CDR} to shift our area of operation to the second slot of \code{RCallBack}. Now that the \code{RCallBack} object is set up, we are ready to actually call the \code{getLatexCharMetrics} function.
+
+\begin{tikzCodeBlock}[title={Executing a \lang{R} function call inside \lang{C}}]
+SEXP LatexMetrics;
+PROTECT( LatexMetrics = eval( RCallBack, R_GlobalEnv) );
+\end{tikzCodeBlock}
+
+And that's it! We create a new \code{SEXP} to hold the return values of \code{getLatexCharMetrics} and execute the \code{eval} function to cause \code{getLatexCharMetrics} to be executed inside the \lang{R} environment. The details of the \lang{R} function will be explained in the next section, for now let's assume that it returns the three values we're interested in as a vector of three numbers. How do we extract these values and assign then to \code{ascent}, \code{descent} and \code{width}?
+
+\begin{tikzCodeBlock}[title={Recovering return values from a \lang{R} function call}]
+ *ascent = REAL(RMetrics)[0];
+ *descent = REAL(RMetrics)[1];
+ *width = REAL(RMetrics)[2];
+
+ UNPROTECT(2);
+
+ return;
+\end{tikzCodeBlock}
+
+Here the \code{REAL} function is used to coerce the \code{SEXP} variable \code{RMetrics} to a vector of real numbers. These numbers are then extracted and assigned to the return values of \code{metricInfo}. In \lang{C} we must specify the `first' value in a vector using the index 0 rather than the index 1. \footnote{There are good logical reasons for this from the point of view of a computer scientist---but if your background in arrays is rooted in linear algebra it will be a bit disorie [...]
+
+\subsection{Implementing a System Call to \LaTeX}
+
+Now we may turn to the actual guts of the \lang{R} function \code{getLatexCharMetrics}. The first thing we need to do is set up a file for \LaTeX{} input:
+
+\begin{tikzCodeBlock}[title={Creating a \LaTeX{} input file},listing style=sweavechunk]
+getLatexCharMetrics <- function( charCode ){
+
+ texDir <- tempdir()
+
+ texLog <- file.path( texDir,'tikzStringWidthCalc.log' )
+ texFile <- file.path( texDir,'tikzStringWidthCalc.tex' )
+
+ texIn <- file( texFile, 'w')
+
+ # To be continued...
+\end{tikzCodeBlock}
+
+The first thing we do is choose a place to create this input file. Now, when the \LaTeX{} compiler is run on a \code{.tex} file, a lot of additional files get created---the whole process is a bit messy. Since the user probably wouldn't appreciate having to clean up our mess, we use the \code{tempdir()} function to retrieve a path to a {\itshape temporary directory} on the system. Here is the first place we benefit from the added level of abstraction granted by \lang{R}. Each operating sy [...]
+
+Now that we have a place to work, we set up a couple of filenames---one for the input file, which ends in \code{.tex} and one for the \LaTeX{} log file, which ends in \code{.log}. We then open the \code{.tex} file for writing. The next step is to setup the preamble of the \LaTeX{} file.
+
+\begin{tikzCodeBlock}[title={Setting up the preamble of a \LaTeX{} input file},listing style=sweavechunk]
+ writeLines("\\documentclass{article}", texIn)
+
+ writeLines("\\usepackage[T1]{fontenc}", texIn)
+
+ writeLines("\\usepackage{tikz}", texIn)
+ writeLines("\\usetikzlibrary{calc}", texIn)
+
+ writeLines("\\batchmode", texIn)
+\end{tikzCodeBlock}
+
+Here we have started a standard \LaTeX{} input file by specifying
+\code{article} as the document class. We also add the \code{fontenc} package
+and specify \code{T1} as its option. This ensures we are using the Type 1 font
+encoding---by default \TeX{} and \LaTeX{} use an encoding called \code{OT1}. Why
+do we need to worry about font encodings? Well, a font encoding specifies which
+\code{ASCII} symbol codes map to which characters and by default, \lang{R}
+expects us to be using the Type 1 encoding (\lang{R} does support other
+encodings---but we're ignoring that for now). For example, in the Type 1
+encoding, the character that corresponds to the \code{ASCII} code 60 is the
+less-than sign: `{\char60}'. If we were to allow \TeX{}
+to retain its default \code{OT1} encoding, that same character code would
+instead map to an upside-down exclamation point: `{\usefont{OT1}{lmr}{m}{n}\char60}'.
+
+The other two packages we load are the \code{tikz} package and its \code{calc}
+library. Essentially we will have \TikZ{} drop the character into a box and
+report some measurements concerning the size of that box. The last command,
+\code{batchmode} tells \LaTeX{} that there isn't any user available to interact
+with---so it should not bother to stop and ask any questions while processing this
+file.
+
+The next step is to set up the part of the \LaTeX{} file that will actually
+calculate and report the widths we are looking for. As mentioned before, this
+is done by setting the character inside a \TikZ{} node and extracting the
+dimensions of the box that surrounds it. In an attempt to improve clarity, the
+following code will be presented as straight \LaTeX{} --
+\code{getLatexCharMetrics} inserts it into the \code{texIn} file by means of
+\code{writeLines} as we have been doing all along. The string highlighted in
+{\color{red} red} should be replaced with the value of the variable charCode
+that was passed in to the function \code{getLatexCharMetrics}.
+
+\begin{tikzCodeBlock}[title={Extracting character dimensions using \TikZ},listing style=latexexample]
+\begin{tikzpicture}
+
+\node[inner sep=0pt,outer sep=0pt] (char) {\charXXcharCodeXX};
+
+\path let \p1 = ($(char.east) - (char.west)$),
+ \n1 = {veclen(\x1,\y1)} in (char.east) -- (char.west)
+ node{ \typeout{tikzTeXWidth=\n1} };
+
+\path let \p1 = ($(char.north) - (char.base)$),
+ \n1 = {veclen(\x1,\y1)} in (char.north) -- (char.base)
+ node{ \typeout{tikzTeXAscent=\n1} };
+
+\path let \p1 = ($(char.base) - (char.south)$),
+ \n1 = {veclen(\x1,\y1)} in (char.base) -- (char.south)
+ node{ \typeout{tikzTeXDescent=\n1} };
+\end{tikzCodeBlock}
+
+What the heck just happened? Well, first we instructed \LaTeX{} to enter the \TikZ{} picture environment using \verb`\begin{tikzpicture}`. Then we ordered \TikZ{} to create a node named ``char'' containing the command \verb`\char` followed by the value of charCode. For example, if we were passed `103' as the character code, which corresponds to the character `g', the node line should be:
+
+\begin{tikzCodeBlock}[listing style=latexexample]
+\node[inner sep=0pt,outer sep=0pt] (char) {\char103};
+\end{tikzCodeBlock}
+
+The \code{inner sep} and \code{outer sep} options are set to \code{0pt} in order to ensure the boundaries of the node `hug' the contents tightly. Now the whole point of setting the character inside a node is that \TikZ{} defines `anchors' along the bounding box of the node. All anchors are referred using a \code{node name.posistion} notation. Since we named the node \code{char}, all the anchors start with \code{char}. The anchor posistions relevant to our problem are shown below:
+
+\begin{center}
+\begin{tikzpicture}
+
+ \node[draw=black, very thick,inner sep=0, outer sep=0, text=black!40,scale=14]
+ (char) {\char103};
+
+ \foreach \anchor/\placement in
+ {north/above, south/below, base/below, east/right, west/left} {
+
+ \draw[shift=(char.\anchor),color=red] plot[mark=*] coordinates{(0,0)}
+ node[\placement,text=red] {\small\texttt{(char.\anchor)}};
+ }
+
+ \node[above= 1em of char.north] {Node Bounding Box}
+ edge[ultra thick,->,>=stealth,out=0,in=0] ($(char.10) + (6pt,12pt)$);
+
+
+\end{tikzpicture}
+\end{center}
+
+The `base' anchor sits on the baseline of the text---therefore to calculate the ascent of the character `g', all we have to do is figure out the difference in height between the positions \code{char.north} and \code{char.base}. Similarly, for the descent we would calculate the difference in height between \code{char.base} and \code{char.south} and width can be obtained using \code{char.west} and \code{char.east}. This is the purpose of the admittedly cryptic \verb`\path` commands that ar [...]
+
+\begin{tikzCodeBlock}[]
+\path let \p1 = ($(char.north) - (char.base)$),
+ \n1 = {veclen(\x1,\y1)} in node{ \typeout{tikzTeXAscent=\n1} };
+\end{tikzCodeBlock}
+
+So, what exactly is going on here? Normally, the \verb`\path` command is used to draw lines between points and add additional coordinates or nodes along those lines. For example, the command:
+
+\begin{tikzCodeBlock}[]
+\path[draw] (0,0) -- (1,1) node {Hi!};
+\end{tikzCodeBlock}
+
+Draws a line from \code{(0,0)} to \code{(1,1)} and places a node at \code{(1,1)} containing the word `Hi!'. In the \TikZ{} code produced by \code{getLatexCharMetrics}, the \code{let} operation is specified. Basically, \code{let} postpones the actual drawing of a path and performs calculations until the \code{in} keyword is encountered. The result of these calculations are stored in a set of special variables which must start with \verb`\n`, \verb`\p`, \verb`\x` or \verb`\y`. The first \c [...]
+
+\begin{tikzCodeBlock}[]
+\p1 = ( $(char.north) - (char.base)$ )
+\end{tikzCodeBlock}
+
+This performs a vector subtraction between the coordinates of \code{char.north} and \code{char.base}. The resulting x and y components are stored in the `point' variable \verb`\p1`. The second operation executed is:
+
+\begin{tikzCodeBlock}[]
+\n1 = {veclen(\x1,\y1)}
+\end{tikzCodeBlock}
+
+This \code{let} operation treats the coordinates stored in \verb`\p1` as a vector and calculates its magnitude. The `1' appended to the \verb`\x` and \verb`\y` variables specifies that we are accessing the x and y components of \verb`\p1`. This result is stored in the `number' variable \verb`\n1`. Now, that our metric is stored in \verb`\n1`, our final task is to ensure it makes it into the \LaTeX{} \code{.log} file---this is done by adding a \code{node} containing the \verb`\typeout` co [...]
+\begin{tikzCodeBlock}[]
+\typeout{tikzTexAscent=\n1}
+\end{tikzCodeBlock}
+cause the phrase `tikzTexAscent=' to appear in the \code{.log} file---followed by the ascent calculated using the node anchors. After the ascent, descent and width have been calculated the \LaTeX{} compiler may be shut down, this is done by adding the final two lines to the input file:
+
+\begin{tikzCodeBlock}[title={Terminating a \LaTeX{} compilation},listing style=sweavechunk]
+ writeLines("\\makeatother", texIn)
+
+ writeLines("\\@@end", texIn)
+
+ close(texIn)
+\end{tikzCodeBlock}
+
+Now that the input file has been prepped, we must process it using the \LaTeX{} compiler and load the contents of the resulting \code{.log} so that we may search for the metrics we dumped using \verb`\typeout`.
+
+\begin{tikzCodeBlock}[title={Terminating a \LaTeX{} compilation},listing style=sweavechunk]
+ latexCmd <- getOption('tikzLatex')
+ latexCmd <- paste( latexCmd, '-interaction=batchmode',
+ '-output-directory', texDir, texFile)
+
+ silence <- system( latexCmd, intern=T, ignore.stderr=T)
+
+ texOut <- file( texLog, 'r' )
+
+ logContents <- readLines( texOut )
+ close( texOut )
+\end{tikzCodeBlock}
+
+The \LaTeX{} compiler is executed through the \code{system} function which handles the details of implementing a system call on whatever operating system we happen to be using. We assign the return value of the \code{system} function to a dummy variable called \code{silence} so that no output floods the user's screen. The last task is to extract our metrics from the text of the \code{.log} we loaded.
+
+\begin{tikzCodeBlock}[title={Parsing the \code{.log} file text},listing style=sweavechunk]
+ match <- logContents[ grep('tikzTeXWidth=', logContents) ]
+ width <- gsub('[=A-Za-z]','',match)
+
+ match <- logContents[ grep('tikzTeXAscent=', logContents) ]
+ ascent <- gsub('[=A-Za-z]','',match)
+
+ match <- logContents[ grep('tikzTeXDescent=', logContents) ]
+ descent <- gsub('[=A-Za-z]','',match)
+
+ return( as.double( c(ascent,descent,width) ) )
+\end{tikzCodeBlock}
+
+Here we use the \code{grep} function to search through the log output for the tags `tikzTeXWidth=', `tikzTeXAscent=' and `tikzTeXDescent=' that we specified when we used \verb`\typeout`. After we recover a line containing one of these tags, we use the \code{gsub} command to remove the letters and the equals sign from the text line---leaving just the number we're interested in. These values are then coerced using \code{as.double} and set as the return value of \code{getLatexCharMetrics}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\chapter{On the Importance of Font and Style Consistency in Reports}
+If you haven't figured it out by now, we are quite picky about the way our graphics and reports look. We are especially picky about the consistency in fonts (both sizes and shapes). Without launching into a diatribe about this, we just want to say with tools like \pkg{tikzDevice} you no longer have to settle for what is ``just okay.'' So go nuts, be picky about how your text and graphics look. Don't be afraid to snub your nose at reports which pay no attention to detail. Be that pers [...]
+
+\section{The \pkg{pgfSweave} Package and Automatic Report Generation}
+Now for a little shameless self promotion. The authors of \pkg{tikzDevice} have another package called \pkg{pgfSweave} which provides a driver for Sweave. \pkg{pgfSweave} started as an interface to \href{http://sourceforge.net/projects/eps2pgf/}{eps2pgf} and its ability to interpret strings in eps files as \LaTeX{}. This was used to much the same effect as \pkg{tikzDevice}. The problem was the conversion from eps to pgf was SLOW. Long story short, by combining this functionality with [...]
+
+\newpage
+
+\bibliography{refs}
+
+\end{document}\n
diff --git a/inst/doc/tikzDevice.pdf b/inst/doc/tikzDevice.pdf
new file mode 100644
index 0000000..0ed669f
Binary files /dev/null and b/inst/doc/tikzDevice.pdf differ
diff --git a/man/anyMultibyteUTF8Characters.Rd b/man/anyMultibyteUTF8Characters.Rd
new file mode 100644
index 0000000..f05edd0
--- /dev/null
+++ b/man/anyMultibyteUTF8Characters.Rd
@@ -0,0 +1,48 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/deviceUtils.R
+\encoding{UTF8}
+\name{anyMultibyteUTF8Characters}
+\alias{anyMultibyteUTF8Characters}
+\title{Check If a String Contains Multibyte UTF-8 characters}
+\usage{
+anyMultibyteUTF8Characters(string, encoding = "UTF-8")
+}
+\arguments{
+\item{string}{A character vector of length 1 (a string).}
+
+\item{encoding}{The input encoding of \code{string}, if not specified
+previously via \code{\link{Encoding}} or by this argument then a value of
+"UTF-8" is assumed}
+}
+\value{
+A boolean value
+}
+\description{
+This function is used by tikzDevice to check if an incoming string contains
+multibyte UTF-8 characters
+}
+\details{
+This function searches through the characters in the given string, if any of
+the characters in the string are more than one byte then the function
+returns \code{TRUE} otherwise it returns \code{FALSE}.
+
+The function will assume an input encoding of UTF-8 but will take any
+specified encoding into account and will convert from the specified encoding
+to UTF-8 before doing any checks
+}
+\examples{
+
+# TRUE
+anyMultibyteUTF8Characters('R is GNU ©, but not ®')
+# FALSE
+anyMultibyteUTF8Characters('R is GNU copyright but not restricted')
+
+}
+\author{
+Cameron Bracken \email{cameron.bracken at gmail.com}
+}
+\seealso{
+\code{\link{tikz}}
+}
+\keyword{character}
+
diff --git a/man/getLatexStrWidth.Rd b/man/getLatexStrWidth.Rd
new file mode 100644
index 0000000..c76d90c
--- /dev/null
+++ b/man/getLatexStrWidth.Rd
@@ -0,0 +1,87 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/latexStrWidth.R
+\name{getLatexStrWidth}
+\alias{getLatexCharMetrics}
+\alias{getLatexStrWidth}
+\title{Obtain Font Metrics from LaTeX}
+\usage{
+getLatexStrWidth(texString, cex = 1, face = 1,
+ engine = getOption("tikzDefaultEngine"),
+ documentDeclaration = getOption("tikzDocumentDeclaration"), packages,
+ verbose = interactive())
+
+getLatexCharMetrics(charCode, cex = 1, face = 1,
+ engine = getOption("tikzDefaultEngine"),
+ documentDeclaration = getOption("tikzDocumentDeclaration"), packages,
+ verbose = interactive())
+}
+\arguments{
+\item{texString}{An arbitrary string for which the width is to be
+calculated. May contain LaTeX markup.}
+
+\item{cex}{a real number that specifies a scaling factor that is to be
+applied to device output.}
+
+\item{face}{an integer in the range [1-5] that specifies the font face to
+use. See \link{par} for details.}
+
+\item{engine}{a string specifying which TeX engine to use. Possible values
+are 'pdftex', 'xetex' and 'luatex'. See the Unicode section of \link{tikzDevice} for
+details.}
+
+\item{documentDeclaration}{See the sections ``Options That Affect Package
+Behavior'' and ``Font Size Calculations'' of \link{tikzDevice-package}
+for more details.}
+
+\item{packages}{See the section ``Options That Affect Package Behavior'' of
+\link{tikzDevice-package}.}
+
+\item{verbose}{A logical value indicating whether diagnostic messages are
+printed when measuring dimensions of strings. Defaults to \code{TRUE} in
+interactive mode only, to \code{FALSE} otherwise.}
+
+\item{charCode}{an integer that corresponds to a symbol in the ASCII
+character table under the Type 1 font encoding. All numeric values are
+coerced using \code{as.integer}. Non-numeric values will not be accepted.}
+}
+\value{
+\item{getLatexStrWidth}{The width of \code{texString} in points.}
+ \item{getLatexCharMetrics}{A numeric vector holding ascent, descent
+ and width. Values should all be nonnegative.}
+}
+\description{
+These functions calculate the width of a character or string as it would
+appear after being compiled by LaTeX.
+}
+\details{
+These functions are used internally by the \code{tikz} device for proper
+string placement in graphics. Both functions check to see if metrics exist
+in a global or temporary dictionary (as defined in
+\code{options('tikzMetricsDictionary')}) and if so will pull the metrics
+from there. If the dictionary does not exist, then a temporary one is
+created for the current R session. Metrics are calculated via \code{system}
+calls to LaTeX compilers. Querying compilers to calculate metrics is
+expensive and so we strongly recommend setting
+\code{options('tikzMetricsDictionary') <- '/path/to/dictionary'} to create a
+global dictionary.
+}
+\examples{
+
+ getLatexStrWidth('{\\\\\\\\tiny Hello \\\\\\\\LaTeX!}')
+
+
+ # Calculate ascent, descent and width for "A"
+ getLatexCharMetrics(65)
+
+}
+\author{
+Charlie Sharpsteen \email{source at sharpsteen.net} and Cameron
+ Bracken \email{cameron.bracken at gmail.com}
+}
+\references{
+PGF Manual
+}
+\keyword{character}
+\keyword{metrics}
+\keyword{string}
+
diff --git a/man/gridToDevice.Rd b/man/gridToDevice.Rd
new file mode 100644
index 0000000..4f982af
--- /dev/null
+++ b/man/gridToDevice.Rd
@@ -0,0 +1,42 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tikzAnnotate.R
+\name{gridToDevice}
+\alias{gridToDevice}
+\title{Convert grid coordinates to device coordinates}
+\usage{
+gridToDevice(x = 0, y = 0, units = "native")
+}
+\arguments{
+\item{x}{x coordinate.}
+
+\item{y}{y coordinate. If no values are given for \code{x} and \code{y}, the
+location of the lower-left corner of the current viewport will be
+calculated.}
+
+\item{units}{Character string indicating the units of \code{x} and \code{y}.
+See the \code{\link{unit}} function for acceptable unit types.}
+}
+\value{
+A tuple of coordinates in device units.
+}
+\description{
+This function converts a coordinate pair specifying a location in a
+grid \code{\link{viewport}} in grid units to a coordinate pair specifying a
+location in device units relative to the lower left corner of the plotting
+canvas.
+}
+\author{
+Charlie Sharpsteen \email{source at sharpsteen.net}
+}
+\seealso{
+\code{\link{unit}}
+ \code{\link{viewport}}
+ \code{\link{convertX}}
+ \code{\link{convertY}}
+ \code{\link{current.transform}}
+}
+\keyword{conversion}
+\keyword{graphics}
+\keyword{grid}
+\keyword{units}
+
diff --git a/man/sanitizeTexString.Rd b/man/sanitizeTexString.Rd
new file mode 100644
index 0000000..1782bfa
--- /dev/null
+++ b/man/sanitizeTexString.Rd
@@ -0,0 +1,82 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/sanitizeTexString.R
+\name{sanitizeTexString}
+\alias{sanitizeTexString}
+\title{Replace LaTeX Special Characters in a String}
+\usage{
+sanitizeTexString(string, strip = getOption("tikzSanitizeCharacters"),
+ replacement = getOption("tikzReplacementCharacters"))
+}
+\arguments{
+\item{string}{A character vector of length 1 (a string).}
+
+\item{strip}{A character vector of single characters to search for.}
+
+\item{replacement}{A character vector of replacement values.}
+}
+\value{
+\item{sanitizedString}{A character vector of length 1 with all
+ special characters replaced.}
+}
+\description{
+This function is used by tikzDevice when \code{sanitize=TRUE} to replace
+special LaTeX characters (such as the comment character %) in plotting text
+where the user does not have direct control over the generated text.
+}
+\details{
+\code{sanitizeTexString} searches character by character through a string
+replacing each occurrence of a special character contained in
+\code{strip[i]} with the corresponding replacement value in
+\code{replacement[i]}. tikzDevice calls back this function for every piece
+of text when the sanitize option is TRUE. See \code{\link{tikz}} for more
+information on the default special characters and replacement values.
+
+By default, `tikzSanitizeCharacters` replaces the following characters:
+
+\itemize{
+ \item \verb{\%}
+ \item \verb{$}
+ \item \verb{\}}
+ \item \verb{\{}
+ \item \verb{^}
+ \item \verb{_}
+ \item \verb{#}
+ \item \verb{&}
+ \item \verb{~}
+}
+
+With the contents of `tikzReplacementCharacters`:
+
+\itemize{
+ \item \verb{\\\%}
+ \item \verb{\\$}
+ \item \verb{\\\}}
+ \item \verb{\\\{}
+ \item \verb{\\^{}}
+ \item \verb{\\_{}}
+ \item \verb{\\#}
+ \item \verb{\\&}
+ \item \verb{\char`\~}
+ }
+
+These defaults may be adjusted using the \code{\link{options}} function.
+}
+\examples{
+
+# Be careful with sanitizing, it may lead to unexpected behavior.
+# For example, we may want -1 to be a superscript it gets
+# sanitized away with the other default special characters.
+# The string appears in LaTeX exactly as shown.
+\dontrun{
+ sanitizeTexString('10\\\% of 10$ is 10^\\{-1\\}$')
+}
+
+}
+\author{
+Cameron Bracken \email{cameron.bracken at gmail.com}
+}
+\seealso{
+\code{\link{tikz}}
+}
+\keyword{character}
+
diff --git a/man/setTikzDefaults.Rd b/man/setTikzDefaults.Rd
new file mode 100644
index 0000000..335dee4
--- /dev/null
+++ b/man/setTikzDefaults.Rd
@@ -0,0 +1,50 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/deviceUtils.R
+\name{setTikzDefaults}
+\alias{setTikzDefaults}
+\title{Reset tikzDevice options to default values.}
+\usage{
+setTikzDefaults(overwrite = TRUE)
+}
+\arguments{
+\item{overwrite}{Should values that are allready set in \code{options()} be
+overwritten?}
+}
+\value{
+Nothing returned.
+}
+\description{
+This function resets the following options:
+}
+\details{
+\itemize{
+ \item \code{tikzDefaultEngine}
+ \item \code{tikzLatex}
+ \item \code{tikzDocumentDeclaration}
+ \item \code{tikzFooter}
+ \item \code{tikzLatexPackages}
+ \item \code{tikzXelatexPackages}
+ \item \code{tikzLualatexPackages}
+ \item \code{tikzMetricPackages}
+ \item \code{tikzUnicodeMetricPackages}
+ \item \code{tikzSanitizeCharacters}
+ \item \code{tikzReplacementCharacters}
+ \item \code{tikzPdftexWarnUTF}
+}
+}
+\examples{
+
+ print( options( 'tikzDocumentDeclaration' ) )
+ options( tikzDocumentDeclaration = 'foo' )
+ setTikzDefaults()
+ print( options( 'tikzDocumentDeclaration' ) )
+
+}
+\author{
+Cameron Bracken \email{cameron.bracken at gmail.com} and Charlie
+ Sharpsteen \email{source at sharpsteen.net}
+}
+\seealso{
+\code{\link{tikz}}
+}
+
diff --git a/man/tikz.Rd b/man/tikz.Rd
new file mode 100644
index 0000000..b964073
--- /dev/null
+++ b/man/tikz.Rd
@@ -0,0 +1,258 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tikz.R
+\name{tikz}
+\alias{tikz}
+\title{TikZ Graphics Device}
+\usage{
+tikz(file = ifelse(onefile, "./Rplots.tex", "./Rplot\%03d.tex"), width = 7,
+ height = 7, onefile = TRUE, bg = "transparent", fg = "black",
+ pointsize = 10, lwdUnit = getOption("tikzLwdUnit"), standAlone = FALSE,
+ bareBones = FALSE, console = FALSE, sanitize = FALSE,
+ engine = getOption("tikzDefaultEngine"),
+ documentDeclaration = getOption("tikzDocumentDeclaration"), packages,
+ footer = getOption("tikzFooter"),
+ symbolicColors = getOption("tikzSymbolicColors"),
+ colorFileName = "\%s_colors.tex",
+ maxSymbolicColors = getOption("tikzMaxSymbolicColors"), timestamp = TRUE,
+ verbose = interactive())
+}
+\arguments{
+\item{file}{A character string indicating the desired path to the output
+file.}
+
+\item{width}{The width of the output figure, in \bold{inches}.}
+
+\item{height}{The height of the output figure, in \bold{inches}.}
+
+\item{onefile}{Should output be directed to separate environments in a
+single file (default \code{TRUE}). If \code{FALSE} this option works
+exactly like the argument of the same name to \code{\link{pdf}}
+(see there for more details).}
+
+\item{bg}{The starting background color for the plot.}
+
+\item{fg}{The starting foreground color for the plot.}
+
+\item{pointsize}{Base pointsize used in the LaTeX document. This option is
+only used if a valid pointsize cannot be extracted from the value of
+\code{getOption("tikzDocumentDeclaration")}. See the section ``Font Size
+Calculations'' in \link{tikzDevice-package} for more details.}
+
+\item{lwdUnit}{The number of \code{pt}s in LaTeX that \code{lwd=1} in R is
+translated to. Defaults to 0.4 (LaTeX and TikZ default); for compatibility
+with R default, please use 72.27/96 (96 pixels in R is 1 inch, which is 72.27
+points in TeX).}
+
+\item{standAlone}{A logical value indicating whether the output file should
+be suitable for direct processing by LaTeX. A value of \code{FALSE}
+indicates that the file is intended for inclusion in a larger document.
+See \sQuote{Details}.}
+
+\item{bareBones}{A logical value. When \code{TRUE} the figure will not be
+wrapped in a \code{tikzpicture} environment. This option is useful for
+embedding one TikZ picture within another. When \code{TRUE} multipage
+output will be drawn on a single page.}
+
+\item{console}{Should the output of tikzDevice be directed to the R console
+(default \code{FALSE}). This is useful for dumping tikz output directly into a
+LaTeX document via \code{\link{sink}}. If TRUE, the \code{file} argument
+is ignored. Setting \code{file=''} is equivalent to setting
+\code{console=TRUE}.}
+
+\item{sanitize}{Should special latex characters be replaced (Default FALSE).
+See the section ``Options That Affect Package Behavior'' for which
+characters are replaced.}
+
+\item{engine}{a string specifying which TeX engine to use. Possible values
+are 'pdftex', 'xetex' and 'luatex'. See the Unicode section of
+\link{tikzDevice-package} for details.}
+
+\item{documentDeclaration}{See the sections ``Options That Affect Package
+Behavior'' and ``Font Size Calculations'' of \link{tikzDevice-package}
+for more details.}
+
+\item{packages}{See the section ``Options That Affect Package Behavior'' of
+\link{tikzDevice-package}.}
+
+\item{footer}{See the section ``Options That Affect Package Behavior'' of
+\link{tikzDevice-package}.}
+
+\item{symbolicColors}{A logical value indicating whether colors are written
+as RGB values or as symbolic names in which case the need to be defined in
+the LaTeX document. These definitions can be generated with the following
+\code{colorFileName} parameter. See also the section ``Options That Affect
+Package Behavior'' of \link{tikzDevice-package}.}
+
+\item{colorFileName}{a character string indicating where the color map for
+symbolic colors is to be stored. It can contain a placeholder \code{\%s}
+where the tikz filename is inserted. If the string is empty, no file is
+written.}
+
+\item{maxSymbolicColors}{an integer number indicating the maximal number
+of distinct colors to write symbolically. Any excess color will be defined
+as if \code{symbolicColors} was set to \code{FALSE}. See also the section
+``Options That Affect' Package Behavior'' of \link{tikzDevice-package}.}
+
+\item{timestamp}{A logical value indicating whether a timestamp is written
+to the TeX file.}
+
+\item{verbose}{A logical value indicating whether diagnostic messages are
+printed when measuring dimensions of strings. Defaults to \code{TRUE} in
+interactive mode only, to \code{FALSE} otherwise.}
+}
+\value{
+\code{tikz()} returns no values.
+}
+\description{
+\code{tikz} is used to open a R graphics device which supports output in the
+TikZ graphics language. TikZ code may be included inside a LaTeX document by
+specifying \code{\\usepackage{tikz}} in the document header.
+}
+\details{
+The TikZ device enables LaTeX-ready output from graphics functions. This is
+done by encoding graphics commands using TikZ markup. All text in a graphic
+output with \code{tikz} will be typeset by LaTeX and therefore will match
+whatever fonts are currently used in the document. This also means that
+\strong{LaTeX mathematics can be typeset directly into labels and
+annotations}.
+
+The TikZ device currently supports three modes of output depending on the
+value of the parameter \code{standAlone} and \code{bareBones}. If
+\code{standAlone} and \code{bareBones} are set to the default value of
+\code{FALSE}, the resulting file will only contain graphics output wrapped
+in a LaTeX \code{tikzpicture} environment. Since this file is not a
+complete LaTeX document, it will need to be included in another LaTeX
+document using the \code{\\input} command. For example:
+\preformatted{
+ \\documentclass{article}
+ \\usepackage{tikz}
+ \\begin{document}
+ \\begin{figure}
+ \\centering
+ \\input{Rplots.tex}
+ \\caption{}
+ \\end{figure}
+ \\end{document}
+}
+
+When \code{standAlone} is set to \code{TRUE}, the device wraps the
+\code{tikzpicture} environment in a complete LaTeX document suitable for
+direct compilation. In this mode the \code{preview} package is used to crop
+the resulting output to the bounding box of the graphic.
+
+When \code{bareBones} is set to \code{TRUE}, the output is not wrapped in a
+document or a \code{tikzpicture} environment. This is useful for embedding
+an generated graphic within an existing TikZ picture.
+
+In cases where both \code{standAlone} and \code{bareBones} have been set to
+\code{TRUE}, the \code{standAlone} option will take precedence.
+
+When the option \code{symbolicColors} is set to \code{TRUE}, the colors will
+be written as symbolic names, e.g. \code{red, gray90} and similar. If the
+color is not mapped to a symbolic name in R, the color will be named
+\code{XXXXX} when \code{#XXXXXX} is its hexadecimal color. All the color
+names will have to be defined in the enclosing document, which is
+automatically written if the path of a color file \code{colorFileName} is
+set.
+}
+\note{
+To compile the output of \code{tikz} a working installation of LaTeX
+ and PGF is needed. Current releases of the TikZ package are available
+ from \url{http://www.ctan.org}. The package may also be installed through
+ the MikTeX package manager on Windows or using the TeX Live package
+ manager, \code{tlmgr}, on Unix/Linux/OS X. The TeX Live package manager
+ will only be installed by default for TeX Live distributions dated 2008
+ and later. Both bleeding-edge and release versions of TikZ may be obtained
+ from the project website hosted at
+ \url{http://sourceforge.net/projects/pgf/}.
+
+Multiple plots will be placed as separate environments in the output file.
+}
+\examples{
+
+\dontrun{
+
+## Example 1 ###################################
+#Set up temporary work directory
+td <- tempdir()
+tf <- file.path(td,'example1.tex')
+oldwd <- getwd()
+setwd(td)
+
+# Minimal plot
+tikz(tf,standAlone=TRUE)
+ plot(1)
+dev.off()
+
+# View the output
+tools::texi2dvi(tf,pdf=T)
+system(paste(getOption('pdfviewer'),file.path(td,'example1.pdf')))
+setwd(oldwd)
+################################################
+
+## Example 2 ###################################
+#Set up temporary work directory
+td <- tempdir()
+tf <- file.path(td,'example2.tex')
+oldwd <- getwd()
+setwd(td)
+
+#LaTeX math symbol names
+syms <-c('alpha','theta','tau','beta','vartheta','pi','upsilon',
+ 'gamma','gamma','varpi','phi','delta','kappa','rho',
+ 'varphi','epsilon','lambda','varrho','chi','varepsilon',
+ 'mu','sigma','psi','zeta','nu','varsigma','omega','eta',
+ 'xi','Gamma','Lambda','Sigma','Psi','Delta','Xi','Upsilon',
+ 'Omega','Theta','Pi','Phi')
+x <- rnorm(length(syms))
+y <- rnorm(length(syms))
+
+tikz(tf,standAlone=TRUE)
+ plot(-2:2, -2:2, type = "n", axes=F,
+ xlab='', ylab='', main='TikZ Device Math Example')
+ text(x,y,paste('\\\\\\\\Large$\\\\\\\\',syms,'$',sep=''))
+dev.off()
+
+#View the output
+tools::texi2dvi(tf,pdf=TRUE)
+system(paste(getOption('pdfviewer'),file.path(td,'example2.pdf')))
+setwd(oldwd)
+################################################
+
+## Example 3 ###################################
+#Set up temporary work directory
+td <- tempdir()
+tf <- file.path(td,'example3.tex')
+oldwd <- getwd()
+setwd(td)
+
+tikz(tf,standAlone=TRUE)
+ plot(-2:2, -2:2, type = "n", axes=F, xlab='', ylab='', main='Random Circles')
+ points(rnorm(50), rnorm(50), pch=21,
+ bg=rainbow(50,alpha=.5), cex=10)
+dev.off()
+
+#View the output
+tools::texi2dvi(tf,pdf=TRUE)
+system(paste(getOption('pdfviewer'),file.path(td,'example3.pdf')))
+setwd(oldwd)
+################################################
+}
+
+}
+\author{
+Charlie Sharpsteen \email{source at sharpsteen.net} and Cameron
+ Bracken \email{cameron.bracken at gmail.com}
+}
+\references{
+The TikZ and PGF Packages: Manual for version 2.00\cr
+ \url{http://sourceforge.net/projects/pgf}\cr Till Tantau, February 20,
+ 2008
+}
+\seealso{
+\code{\link{pictex}}, \code{\link{getLatexCharMetrics}},
+ \code{\link{getLatexStrWidth}}, \code{\link{setTikzDefaults}},
+ \code{\link{tikzAnnotate}}, \code{\link{sanitizeTexString}}
+}
+\keyword{device}
+
diff --git a/man/tikzAnnotate.Rd b/man/tikzAnnotate.Rd
new file mode 100644
index 0000000..eb44e80
--- /dev/null
+++ b/man/tikzAnnotate.Rd
@@ -0,0 +1,186 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tikzAnnotate.R
+\name{tikzAnnotate}
+\alias{grid.tikzAnnotate}
+\alias{grid.tikzCoord}
+\alias{grid.tikzNode}
+\alias{tikzAnnotate}
+\alias{tikzAnnotateGrob}
+\alias{tikzCoord}
+\alias{tikzCoordGrob}
+\alias{tikzNode}
+\alias{tikzNodeGrob}
+\title{Add Custom TikZ Code to an Active Device}
+\usage{
+tikzAnnotate(annotation, checkstate = TRUE)
+
+tikzNode(x = NULL, y = NULL, opts = NULL, name = NULL, content = NULL,
+ units = "user")
+
+tikzCoord(x, y, name, units = "user")
+
+tikzAnnotateGrob(annotation)
+
+tikzNodeGrob(x = NULL, y = NULL, opts = NULL, name = NULL,
+ content = NULL, units = "native")
+
+tikzCoordGrob(x, y, name, units = "native")
+
+grid.tikzAnnotate(annotation, draw = TRUE)
+
+grid.tikzNode(x = NULL, y = NULL, opts = NULL, name = NULL,
+ content = NULL, units = "native", draw = TRUE)
+
+grid.tikzCoord(x, y, name, units = "native", draw = TRUE)
+}
+\arguments{
+\item{annotation}{A character vector, one element per line to be added to
+the open tikz device.}
+
+\item{checkstate}{A logical, whether to "flush" the device state prior to
+writing the \code{annotation}.}
+
+\item{x}{numeric, x location for a named coordinate in user coordinates}
+
+\item{y}{numeric, y location for a named coordinate in user coordinates}
+
+\item{opts}{A character string that will be used as options for a \code{node}.
+See the "Nodes and Edges" section of the TikZ manual for complete details.}
+
+\item{name}{Optional character string that will be used as a name for a
+\code{coordinate} or \code{node}. Other TikZ commands can use this
+name to refer to a location in a graphic.}
+
+\item{content}{A character string that will be used as the content to be displayed
+inside of a \code{node}. If left as \code{NULL} a \code{coordinate} will be
+created instead of a \code{node}. If a \code{node} with empty content is truely
+desired, pass an empty string \code{""}.}
+
+\item{units}{Character string specifying the unit system associated with
+\code{x} and \code{y}. See \code{\link{grconvertX}} for acceptable
+units in base graphics and \code{\link{unit}} for acceptable
+units in grid graphics.}
+
+\item{draw}{A logical value indicating whether graphics output should be
+produced.}
+}
+\value{
+Nothing returned.
+}
+\description{
+These functions allow custom (LaTeX) commands to be added to the output of an
+active tikzDevice.
+}
+\details{
+\code{tikzAnnotate} is intended to allow the insertion of arbitrary TikZ
+commands into the output stream of a graphic. For LaTeX commands that
+reference specific locations in an R plot, coordinates must be specified in
+"device units" which for \code{tikz} output are TeX points relative to the
+lower left corner of the device canvas. Functions such as
+\code{\link{grconvertX}} and \code{\link{gridToDevice}} can help make the
+necessary conversions for base and grid graphics. The \code{tikzNode} and
+\code{tikzCoord} functions automatically perform unit conversions acording
+the the value of their \code{units} parameters.
+
+\code{tikzNode} is a wrapper for \code{tikzAnnotate} that inserts TikZ
+\code{\\node} or \code{\\coordinates} commands into the output. The
+difference between a node and a coordinate is the presence of a
+\code{content} section that can contain arbitrary LaTeX text. This is
+useful for adding textual annotations at specific locations in a TikZ
+graphic. The \code{tikzCoord} function is a wrapper for \code{tikzNode}
+that simplifies the task of inserting named coordinates.
+
+Additionally, the \code{tikzAnnotateGrob}, \code{tikzNodeGrob} and
+\code{tikzCoordGrob} functions are supplied for creating grid objects
+or "\code{\link{grob}}s" that can be used in Grid graphics. High level
+wrapper functions \code{grid.tikzAnnotate}, \code{grid.tikzNode} and
+\code{grid.tikzCoord} are also supplied which creat and render a \code{grob}
+in one step.
+
+See the TikZ Device vignette for more information and examples and the
+TikZ manual for the definitive reference on what is possible with nodes.
+}
+\examples{
+
+\dontrun{
+
+### Example 1: Annotations in Base Graphics
+# Load some additional TikZ libraries
+tikz("annotation.tex",width=4,height=4,
+ packages = c(getOption('tikzLatexPackages'),
+ "\\\\usetikzlibrary{decorations.pathreplacing}",
+ "\\\\usetikzlibrary{positioning}",
+ "\\\\usetikzlibrary{shapes.arrows,shapes.symbols}")
+)
+
+p <- rgamma (300 ,1)
+outliers <- which( p > quantile(p,.75)+1.5*IQR(p) )
+boxplot(p)
+
+# Add named coordinates that other TikZ commands can hook onto
+tikzCoord(1, min(p[outliers]), 'min outlier')
+tikzCoord(1, max(p[outliers]), 'max outlier')
+
+# Use tikzAnnotate to insert arbitrary code, such as drawing a
+# fancy path between min outlier and max outlier.
+tikzAnnotate(c("\\\\draw[very thick,red,",
+ # Turn the path into a brace.
+ 'decorate,decoration={brace,amplitude=12pt},',
+ # Shift it 1em to the left of the coordinates
+ 'transform canvas={xshift=-1em}]',
+ '(min outlier) --',
+ # Add a node with some text in the middle of the path
+ 'node[single arrow,anchor=tip,fill=white,draw=green,',
+ 'left=14pt,text width=0.70in,align=center]',
+ '{Holy Outliers Batman!}', '(max outlier);'))
+
+# tikzNode can be used to place nodes with customized options and content
+tikzNode(
+ opts='starburst,fill=green,draw=blue,very thick,right=of max outlier',
+ content='Wow!'
+)
+
+dev.off()
+
+
+### Example 2: Annotations in Grid Graphics
+library(grid)
+
+tikz("grid_annotation.tex",width=4,height=4,
+ packages = c(getOption('tikzLatexPackages'),
+ "\\\\usetikzlibrary{shapes.callouts}")
+)
+
+pushViewport(plotViewport())
+pushViewport(dataViewport(1:10, 1:10))
+
+grid.rect()
+grid.xaxis()
+grid.yaxis()
+grid.points(1:10, 1:10)
+
+for ( i in seq(2,8,2) ){
+ grid.tikzNode(i,i,opts='ellipse callout,draw,anchor=pointer',content=i)
+}
+
+dev.off()
+
+}
+
+
+}
+\author{
+Cameron Bracken <cameron.bracken at gmail.com> and Charlie Sharpsteen
+ \email{source at sharpsteen.net}
+}
+\seealso{
+\code{\link{grconvertX}}
+ \code{\link{grconvertY}}
+ \code{\link{gridToDevice}}
+ \code{\link{unit}}
+ \code{\link{tikz}}
+}
+\keyword{annotation}
+\keyword{device}
+\keyword{tikz}
+
diff --git a/man/tikzCompilerInfo.Rd b/man/tikzCompilerInfo.Rd
new file mode 100644
index 0000000..9fe3f87
--- /dev/null
+++ b/man/tikzCompilerInfo.Rd
@@ -0,0 +1,28 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/deviceUtils.R
+\name{tikzCompilerInfo}
+\alias{tikzCompilerInfo}
+\title{Print paths to TeX compilers.}
+\usage{
+tikzCompilerInfo(verbose = TRUE)
+}
+\arguments{
+\item{verbose}{If set to \code{FALSE}, calling this function will not cause any output to
+be printed to the screen. Defaults to \code{TRUE}.}
+}
+\value{
+Invisibly returns a list containing paths to TeX compilers.
+}
+\description{
+This function reports information concerning compilers that the \code{tikz}
+device will use to calculate character metrics. Information on LaTeX will
+always be available but information on XeLaTeX and LuaLaTeX will only be
+reported if the compilers were found.
+}
+\author{
+Charlie Sharpsteen \email{source at sharpsteen.net}
+}
+\seealso{
+\code{\link{tikz}}
+}
+
diff --git a/man/tikzDevice-package.Rd b/man/tikzDevice-package.Rd
new file mode 100644
index 0000000..b041da3
--- /dev/null
+++ b/man/tikzDevice-package.Rd
@@ -0,0 +1,137 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tikzDevice-package.R
+\docType{package}
+\name{tikzDevice-package}
+\alias{tikzDevice}
+\alias{tikzDevice-package}
+\title{Support for native LaTeX output of R graphics}
+\description{
+The tikzDevice package implements the \code{\link{tikz}} ouput device which
+generates R graphics in a LaTeX friendly format. LaTeX handles the
+typesetting of all text in graphics generated by \code{tikz}. This allows for
+seamless integration between these graphics and documents that are also being
+typeset by LaTeX. Using LaTeX to generate graph text also means that
+\strong{LaTeX mathematics can be typeset directly into labels and
+annotations}.
+}
+\section{Options That Affect Package Behavior}{
+ The \pkg{tikzDevice} package
+ is currently influenced by a number of global options that may be set in
+ scripts, from the console or in a \code{.Rprofile} file. All of the options
+ can be set by using \code{options(<option> = <value>)}. These options
+ allow for the use of custom \code{documentclass} declarations, LaTeX
+ packages, and typesetting engines (e.g. XeLaTeX or LuaLaTeX). The defaults,
+ if are any for a given option, are shown below the description. The global
+ options are:
+
+ \describe{
+
+ \item{\code{tikzDefaultEngine}}{ Specifies which typesetting engine
+ functions in the tikzDevice package will prefer. Current possible values
+ are \code{pdftex}, \code{xetex} or \code{luatex}. Respectively, these
+ values trigger the use of the \code{pdflatex}, \code{xelatex} and
+ \code{lualatex} compilers. }
+
+ \item{\code{tikzLatex}}{ Specifies the location of the LaTeX compiler to be
+ used by \pkg{tikzDevice}. Setting this option may help the package locate a
+ missing compiler. The default is searched for when the package is loaded,
+ otherwise it can be set manually. This option may be set as follows:
+ \code{options( tikzLatex = '/path/to/latex/compiler' )}. }
+
+ \item{\code{tikzXelatex}}{ Functions similar to \code{tikzLatex}, except
+ this option specifies the location of the XeLaTeX compiler. }
+
+ \item{\code{tikzLualatex}}{ Functions similar to \code{tikzLatex}, except
+ this option specifies the location of the LuaLaTeX compiler. }
+
+ \item{\code{tikzMetricsDictionary}}{ When using the graphics device
+ provided by \pkg{tikzDevice}, you may notice that appears to ``lag" or
+ ``hang" when commands such as \code{plot()} are executed. This is because
+ the device must query the LaTeX compiler for string widths and font
+ metrics. For a normal plot, this may happen dozens or hundreds of times-
+ hence becomes unresponsive for a while. The good news is that the
+ \code{\link{tikz}} code is designed to cache the results of these
+ computations so they need only be performed once for each string or
+ character. By default, these values are stored in a temporary cache file
+ which is deleted when is shut down. A location for a permanent cache file
+ may be specified by setting the value of \code{tikzMetricsDictionary} in
+ \code{.Rprofile} with \code{options(tikzMetricsDictionary =
+ '/path/to/dictionary/location')}. }
+
+ \item{\code{tikzDocumentDeclaration}}{ A string. The LaTeX documentclass
+ declaration used in output files when \code{standAlone == TRUE}.
+ \code{tikzDocumentDeclaration} also influences the calculation of font
+ metrics. The default value is: \code{options(tikzDocumentDeclaration =
+ "\\documentclass[10pt]{article}")} }
+
+ \item{\code{tikzLatexPackages}}{ A character vector. These are the packages
+ which are included when using the \code{pdftex} engine and
+ \code{\link{tikz}} is used with the the \code{standAlone} option as well as
+ when font metrics are calculated. }
+
+ \item{\code{tikzXelatexPackages}}{ This option works like
+ \code{tikzLatexPackages}, except is is used when the \code{xetex} engine is
+ in use. }
+
+ \item{\code{tikzLualatexPackages}}{ This option works like
+ \code{tikzXelatexPackages}, except is is used when the \code{luatex} engine
+ is in use. }
+
+ \item{\code{tikzFooter}}{ A character vector. The footer to be used only
+ when \code{standAlone==TRUE}. }
+
+ \item{\code{tikzMetricPackages}}{ A character vector. These are the
+ packages which are additionally loaded when doing font metric calculations.
+ As you see below, the font encoding is set to Type 1. This is very
+ important so that character codes of LaTeX and match up. The default value
+ is: \code{options(tikzMetricPackages = c( "\\usepackage[utf8]{inputenc}",
+ "\\usepackage[T1]{fontenc}", "\\usetikzlibrary{calc}" ))} }
+
+ \item{\code{tikzUnicodeMetricPackages}}{ This vector is used when font
+ metric calculations are performed using the \code{xetex} or \code{luatex}
+ engines. It should have the same contents as \code{tikzMetricPackages} with
+ the addition of the \code{fontspec} and \code{xunicode} packages. }
+
+ \item{\code{tikzSanitizeCharacters}}{ A character vector of special latex
+ characters to replace. These values should correspond to the replacement
+ values from the \code{tikzReplacementCharacters} option. See
+ \code{\link{sanitizeTexString}} for more details. }
+
+ \item{\code{tikzReplacementCharacters}}{ A character vector of replacements
+ for special latex characters. These values should correspond to the values
+ from the \code{tikzSanitizeCharacters} option. }
+
+ \item{\code{tikzLwdUnit}}{ A numeric that denotes the number of \code{pt}s in LaTeX that \code{lwd=1} in R is
+ translated to. Defaults to 0.4 (LaTeX and TikZ default); for compatibility
+ with R default, please use 72.27/96 (96 pixels in R is 1 inch, which is 72.27
+ points in TeX).}
+
+ \item{\code{tikzPdftexWarnUTF}}{ A \code{TRUE/FALSE} value that controls
+ whether warnings are printed if Unicode characters are sent to a device
+ using the \code{pdftex} engine. }
+
+ \item{\code{tikzSymbolicColors}}{ A logical value indicating whether colors
+ are written as RGB values or as symbolic names in which case the need to be
+ defined in the LaTeX document. }
+
+ \item{\code{tikzMaxSymbolicColors}}{ an integer number indicating the
+ maximal number of distinct colors to write symbolically. Any excess color
+ will be defined as if \code{symbolicColors} was set to \code{FALSE}.} }
+
+ Default values for all options may be viewed or restored using the
+ \code{\link{setTikzDefaults}} function.
+}
+\author{
+See \code{packageDescription("tikzDevice")}.
+
+ Submit bug reports to: \url{https://github.com/yihui/tikzDevice/issues}
+}
+\references{
+The TikZ and PGF Packages: Manual for version 2.00\cr
+ \url{http://sourceforge.net/projects/pgf}\cr Till Tanatu, February 20, 2008
+}
+\seealso{
+\code{\link{tikz}}
+}
+\keyword{package}
+
diff --git a/src/tikzDevice.c b/src/tikzDevice.c
new file mode 100644
index 0000000..753ce3e
--- /dev/null
+++ b/src/tikzDevice.c
@@ -0,0 +1,2363 @@
+/*
+ * tikzDevice, (C) 2009-2011 Charlie Sharpsteen and Cameron Bracken
+ *
+ * A graphics device for R :
+ * A Computer Language for Statistical Data Analysis
+ *
+ * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka
+ * Copyright (C) 2001-8 The R Development Core Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, a copy is available at
+ * http://www.r-project.org/Licenses/
+ *
+ * The C code in this project started as a fork of:
+ * A PicTeX Device, (C) 1996 Valerio Aimale
+ *
+ *
+ * "If I have seen further, it is only by standing on
+ * the shoulders of giants."
+ *
+ * -I. Newton
+ *
+*/
+
+/********************************************************************/
+
+/*
+ * NOTE:
+ * This is the first effort of dyed-in-the-wool Fortran programmers
+ * to write C code. Hence the comments in this file will make many
+ * observations that may seem obvious or inane. There also may be a
+ * generous amount of snide comments concerning the syntax of the
+ * C language.
+*/
+
+/*
+ * Function prototypes are defined in here. Apparently in C
+ * it is absolutely necessary for function definitions to appear
+ * BEFORE they are called by other functions. Hence many source code
+ * files do not present code in the order in which that code
+ * is used. Using a header file with function declarations allows
+ * the programmer to order the code in any sequence they choose.
+*/
+
+/*
+ * This header also includes other header files describing functions
+ * provided by the R language.
+*/
+#include "tikzDevice.h"
+
+// We are writing to files so we need stdio.h
+#include <stdio.h>
+
+/*
+ * Main entry point from the R environment, called by the R function
+ * tikz() to open a new TikZ graphics device.
+*/
+SEXP TikZ_StartDevice ( SEXP args ){
+
+ /*
+ * Make sure the version number of the R running this
+ * routine is compatible with the version number of
+ * the R that compiled this routine.
+ */
+ R_GE_checkVersionOrDie(R_GE_version);
+
+ /* Declare local variabls for holding the components of the args SEXP */
+ const char *fileName, *colorFileName;
+ const char *bg, *fg;
+ double width, height;
+ Rboolean standAlone, bareBones;
+ const char *documentDeclaration, *packages, *footer;
+ double baseSize, lwdUnit;
+ Rboolean console, sanitize, onefile, symbolicColors;
+
+ /*
+ * pGEDevDesc is a variable provided by the R Graphics Engine
+ * that represents a graphics device to the rest of the R system.
+ * It contains one important componant of type pDevDesc
+ * which contains information specific to the implementation of
+ * the TikZ Device. The creation and initialization of this component
+ * is the main task of this routine.
+ */
+ pGEDevDesc tikzDev;
+
+
+ /* Retrieve function arguments from input SEXP. */
+
+
+ /*
+ * Skip first argument. It holds the name of the R function
+ * that called this C routine.
+ */
+ args = CDR(args);
+
+ /* Recover file name. */
+ fileName = translateChar(asChar(CAR(args)));
+ /* Advance to next argument stored in the args SEXP. */
+ args = CDR(args);
+
+ /* Recover figure dimensions. */
+ /* For now these are assumed to be in inches. */
+ width = asReal(CAR(args)); args = CDR(args);
+ height = asReal(CAR(args)); args = CDR(args);
+
+ onefile = asLogical(CAR(args)); args = CDR(args);
+
+ /* Recover initial background and foreground colors. */
+ bg = CHAR(asChar(CAR(args))); args = CDR(args);
+ fg = CHAR(asChar(CAR(args))); args = CDR(args);
+
+ /* Recover the base fontsize */
+ baseSize = asReal(CAR(args)); args = CDR(args);
+
+ /* Recover the lwd-to-pt ratio */
+ lwdUnit = asReal(CAR(args)); args = CDR(args);
+
+ /*
+ * Set the standAlone parameter which specifies if the TikZ
+ * pictures generated by this device should be wrapped in their
+ * own LaTeX Document
+ */
+ standAlone = asLogical(CAR(args)); args = CDR(args);
+
+ /*
+ * Set the bareBones parameter which specifies if TikZ code
+ * should be output directly without wrapping it a LaTeX document
+ * or the tikzpicture environment.
+ */
+ bareBones = asLogical(CAR(args)); args = CDR(args);
+
+ /* Grab the latex header and footers*/
+ documentDeclaration = CHAR(asChar(CAR(args))); args = CDR(args);
+ packages = CHAR(asChar(CAR(args))); args = CDR(args);
+ footer = CHAR(asChar(CAR(args))); args = CDR(args);
+
+ /*
+ * Should the output be sent to the R console? An null file name also
+ * indicates console output.
+ */
+ console = asLogical(CAR(args)); args = CDR(args);
+ if ( fileName[0] == '\0' )
+ console = TRUE;
+
+ /*
+ * Should text strings passed to the plotting device be sent
+ * to a sanitization function- i.e. to provide automatic
+ * escaping of TeX special characters such as %,_,\, etc?
+ */
+ sanitize = asLogical(CAR(args)); args = CDR(args);
+
+ /*
+ * See the definition of tikz_engine in tikzDevice.h
+ */
+ int engine = asInteger(CAR(args)); args = CDR(args);
+
+ /*
+ * Should symbolic names be used (red instead of 1.0, 1.0, 1.0)
+ */
+ symbolicColors = asLogical(CAR(args)); args = CDR(args);
+ colorFileName = translateChar(asChar(CAR(args))); args = CDR(args);
+ int maxSymbolicColors = asInteger(CAR(args)); args = CDR(args);
+ Rboolean timestamp = asLogical(CAR(args)); args = CDR(args);
+ Rboolean verbose = asLogical(CAR(args)); args = CDR(args);
+
+ /* Ensure there is an empty slot avaliable for a new device. */
+ R_CheckDeviceAvailable();
+
+ BEGIN_SUSPEND_INTERRUPTS{
+
+ /*
+ * The pDevDesc variable specifies the funtions and components
+ * that describe the specifics of this graphics device. After
+ * setup, this information will be incorporated into the pGEDevDesc
+ * variable tikzDev.
+ */
+ pDevDesc deviceInfo;
+
+ /*
+ * Create the deviceInfo variable. If this operation fails,
+ * a 0 is returned in order to cause R to shut down due to the
+ * possibility of corrupted memory.
+ */
+ if( !( deviceInfo = (pDevDesc) calloc(1, sizeof(DevDesc))) ) {
+ return 0;
+ }
+
+ /*
+ * Call setup routine to initialize deviceInfo and associate
+ * R graphics function hooks with the appropriate C routines
+ * in this file.
+ */
+ if( !TikZ_Setup( deviceInfo, fileName, width, height, onefile, bg, fg, baseSize, lwdUnit,
+ standAlone, bareBones, documentDeclaration, packages,
+ footer, console, sanitize, engine, symbolicColors, colorFileName,
+ maxSymbolicColors, timestamp, verbose ) ){
+ /*
+ * If setup was unsuccessful, destroy the device and return
+ * an error message.
+ */
+ free( deviceInfo );
+ error("TikZ device setup was unsuccessful!");
+ }
+
+ /* Create tikzDev as a Graphics Engine device using deviceInfo. */
+ tikzDev = GEcreateDevDesc( deviceInfo );
+
+ /*
+ * Register the device as an avaiable graphics device in the R
+ * Session. The user will now see a device labeled "tikz output"
+ * when running functions such as dev.list().
+ */
+ GEaddDevice2( tikzDev, "tikz output" );
+
+ } END_SUSPEND_INTERRUPTS;
+
+
+ return R_NilValue;
+
+}
+
+
+/*
+ * This function is responsible for initializing device parameters
+ * contained in the variable deviceInfo. It returns a true or false
+ * value depending on the success of initialization operations. The
+ * static keyword means this function can only be seen by other functions
+ * in this file. A better choice for the keyword might have been something
+ * like "private"...
+*/
+
+static Rboolean TikZ_Setup(
+ pDevDesc deviceInfo,
+ const char *fileName,
+ double width, double height, Rboolean onefile,
+ const char *bg, const char *fg, double baseSize, double lwdUnit,
+ Rboolean standAlone, Rboolean bareBones,
+ const char *documentDeclaration,
+ const char *packages, const char *footer,
+ Rboolean console, Rboolean sanitize, int engine,
+ Rboolean symbolicColors, const char* colorFileName,
+ int maxSymbolicColors, Rboolean timestamp, Rboolean verbose){
+
+ /*
+ * Create tikzInfo, this variable contains information which is
+ * unique to the implementation of the TikZ Device. The deviceInfo
+ * variable contains a slot into which tikzInfo can be placed so that
+ * this information persists and is retrievable during the lifespan
+ * of this device.
+ *
+ * More information on the components of the deviceInfo structure,
+ * which is a pointer to a DevDesc variable, can be found under
+ * struct _DevDesc in the R header file GraphicsDevice.h
+ *
+ * tikzInfo is a structure which is defined in the file tikzDevice.h
+ */
+ tikzDevDesc *tikzInfo;
+
+ /*
+ * Initialize tikzInfo, return false if this fails. A false return
+ * value will cause the whole device initialization routine to fail.
+ */
+ if( !( tikzInfo = (tikzDevDesc *) malloc(sizeof(tikzDevDesc)) ) ){
+ return FALSE;
+ }
+
+ /* Copy TikZ-specific information to the tikzInfo variable. */
+ if ( onefile == FALSE ) {
+ /*
+ * Hopefully 10 extra digits will be enough for storing incrementing file
+ * numbers.
+ */
+ tikzInfo->outFileName = calloc_x_strlen(fileName, 10);
+ tikzInfo->originalFileName = calloc_strcpy(fileName);
+ } else {
+ tikzInfo->outFileName = calloc_strcpy(fileName);
+ }
+ tikzInfo->outputFile= NULL;
+
+ tikzInfo->originalColorFileName = calloc_strcpy(colorFileName);
+ tikzInfo->ncolors = 0;
+ tikzInfo->colorFile = NULL;
+ tikzInfo->maxSymbolicColors = maxSymbolicColors;
+ tikzInfo->colors = calloc(maxSymbolicColors, sizeof(int));
+ tikzInfo->excessWarningPrinted = FALSE;
+ tikzInfo->engine = engine;
+ tikzInfo->rasterFileCount = 1;
+ tikzInfo->pageNum = 1;
+ tikzInfo->lwdUnit = lwdUnit;
+ tikzInfo->debug = DEBUG;
+ tikzInfo->standAlone = standAlone;
+ tikzInfo->bareBones = bareBones;
+ tikzInfo->oldFillColor = 0;
+ tikzInfo->oldDrawColor = 0;
+ tikzInfo->stringWidthCalls = 0;
+
+ tikzInfo->documentDeclaration = calloc_strcpy(documentDeclaration);
+ tikzInfo->packages = calloc_strcpy(packages);
+ tikzInfo->footer = calloc_strcpy(footer);
+ tikzInfo->symbolicColors = symbolicColors;
+ tikzInfo->console = console;
+ tikzInfo->sanitize = sanitize;
+ tikzInfo->clipState = TIKZ_NO_CLIP;
+ tikzInfo->pageState = TIKZ_NO_PAGE;
+ tikzInfo->onefile = onefile;
+ tikzInfo->timestamp = timestamp;
+ tikzInfo->verbose = verbose;
+
+ /* initialize strings, just to be on the safe side */
+ strscpy(tikzInfo->drawColor, "drawColor");
+ strscpy(tikzInfo->fillColor, "fillColor");
+
+ /* Incorporate tikzInfo into deviceInfo. */
+ deviceInfo->deviceSpecific = (void *) tikzInfo;
+
+ /*
+ * These next statements define the capabilities of the device.
+ * These capabilities include:
+ * -Device/user interaction
+ * -Gamma correction
+ * -Clipping abilities
+ * -UTF8 support
+ * -Text justification/alignment abilities
+ */
+
+ /*
+ * Define the gamma factor- used to adjust the luminosity of an image.
+ * Set to 1 since there is no gamma correction in the TikZ device. Also,
+ * canChangeGamma is set to FALSE to disallow user adjustment of this
+ * default.
+ */
+ deviceInfo->startgamma = 1;
+ deviceInfo->canChangeGamma = FALSE;
+
+ /*
+ * canHAdj is an integer specifying the level of horizontal adjustment
+ * or justification provided by this device. Currently set to 1 as this
+ * is implemented by having the device insert /raggedleft, /raggedright
+ * and /centering directives.
+ *
+ * Level 2 represents support for continuous variation between left aligned
+ * and right aligned- this is certainly possible in TeX but would take some
+ * thought to implement.
+ */
+ deviceInfo->canHAdj = 1;
+
+ /*
+ * useRotatedTextInContour specifies if the text function along with
+ * rotation parameters should be used over Hershey fonts when printing
+ * contour plot labels. As one of the primary goals of this device
+ * is to unify font choices, this value is set to true.
+ */
+ deviceInfo->useRotatedTextInContour = TRUE;
+
+ /*
+ * canClip specifies whether the device implements routines for trimming
+ * plotting output such that it falls within a rectangular clipping area.
+ */
+ deviceInfo->canClip = TRUE;
+
+ /*
+ * These next parameters speficy if the device reacts to keyboard and
+ * mouse events. Since this device outputs to a file, not a screen window,
+ * these actions are disabled.
+ */
+ deviceInfo->canGenMouseDown = FALSE;
+ deviceInfo->canGenMouseMove = FALSE;
+ deviceInfo->canGenMouseUp = FALSE;
+ deviceInfo->canGenKeybd = FALSE;
+
+ /*
+ * This parameter specifies whether the device is set up to handle UTF8
+ * characters. This makes a difference in the complexity of the text
+ * handling functions that must be built into the device. If set to true
+ * both hook functions textUTF8 and strWidthUTF8 must be implemented.
+ * Compared to ASCII, which only has 128 character values, UTF8 has
+ * thousands.
+ *
+ * Version 0.6.0 of tikzDevice gained the ability to calculate metrics for
+ * UTF8 encoded strings and characters. Those calculations are not done here
+ * in the C code but implemented through the magical callback to R. On the R
+ * level, we determine automatically is a string contains multibyte UTF8
+ * characters and then use XeLaTeX. Bottom line is, even though hasTextUTF8
+ * is FALSE we can still print UTF8 characters and we dont need a separate
+ * text handling function for UTF8 characters (thank god).
+ *
+ * wantSymbolUTF8 indicates if mathematical symbols should be sent to
+ * the device as UTF8 characters. These can be handled in the same way as
+ * normal UTF8 text and so wantSymbolUTF8 is TRUE.
+ */
+ deviceInfo->hasTextUTF8 = FALSE;
+ switch (tikzInfo->engine) {
+ case pdftex:
+ deviceInfo->wantSymbolUTF8 = FALSE;
+ break;
+ case xetex:
+ case luatex:
+ deviceInfo->wantSymbolUTF8 = TRUE;
+ break;
+ }
+
+#if R_GE_version >= 9
+ /* Added in 2.14.0 for `dev.capabilities`. In all cases 0 means NA (unset). */
+ deviceInfo->haveTransparency = 2; /* 1 = no, 2 = yes */
+ deviceInfo->haveTransparentBg = 2; /* 1 = no, 2 = fully, 3 = semi */
+ deviceInfo->haveRaster = 2; /* 1 = no, 2 = yes, 3 = except for missing values */
+ deviceInfo->haveCapture = 1; /* 1 = no, 2 = yes */
+ deviceInfo->haveLocator = 1; /* 1 = no, 2 = yes */
+#endif
+
+ /*
+ * Initialize device parameters. These concern properties such as the
+ * plotting canvas size, the initial foreground and background colors and
+ * the initial clipping area. Other parameters related to fonts and text
+ * output are also included.
+ */
+
+ /*
+ * Set canvas size. The bottom left corner is considered the origin and
+ * assigned the value of 0pt, 0pt. The upper right corner is assigned by
+ * converting the specified height and width of the device to points.
+ */
+ deviceInfo->bottom = 0;
+ deviceInfo->left = 0;
+ deviceInfo->top = dim2dev( height );
+ deviceInfo->right = dim2dev( width );
+
+ /* Set default character size in pixels. */
+ deviceInfo->cra[0] = 0.9 * baseSize;
+ deviceInfo->cra[1] = 1.2 * baseSize;
+
+ /* Set initial font. */
+ deviceInfo->startfont = 1;
+
+ /* Set base font size. */
+ deviceInfo->startps = baseSize;
+
+ /*
+ * Apparently these are supposed to center text strings over the points at
+ * which they are plotted.
+ *
+ * Values cribbed from devPS.c in the R source. In paticular, setting
+ * `yLineBias` to 0 causes text in the margins of an x axis to recieve more
+ * leading that text in the margins of a y axis.
+ */
+ deviceInfo->xCharOffset = 0.4900;
+ deviceInfo->yCharOffset = 0.3333;
+ deviceInfo->yLineBias = 0.2;
+
+ /* Specify the number of inches per pixel in the x and y directions. */
+ deviceInfo->ipr[0] = 1/dim2dev(1);
+ deviceInfo->ipr[1] = 1/dim2dev(1);
+
+ /* Set initial foreground and background colors. */
+ deviceInfo->startfill = R_GE_str2col( bg );
+ deviceInfo->startcol = R_GE_str2col( fg );
+
+ /* Set initial line type. */
+ deviceInfo->startlty = 0;
+
+
+ /*
+ * Connect R graphic function hooks to TikZ Routines implemented in this
+ * file. Each routine performs a specific function such as adding text,
+ * drawing a line or reporting/adjusting the status of the device.
+ */
+
+ /* Utility routines. */
+ deviceInfo->close = TikZ_Close;
+ deviceInfo->newPage = TikZ_NewPage;
+ deviceInfo->clip = TikZ_Clip;
+ deviceInfo->size = TikZ_Size;
+
+ /* Text routines. */
+ deviceInfo->metricInfo = TikZ_MetricInfo;
+ deviceInfo->strWidth = TikZ_StrWidth;
+ deviceInfo->text = TikZ_Text;
+
+ /* Drawing routines. */
+ deviceInfo->line = TikZ_Line;
+ deviceInfo->circle = TikZ_Circle;
+ deviceInfo->rect = TikZ_Rectangle;
+ deviceInfo->polyline = TikZ_Polyline;
+ deviceInfo->polygon = TikZ_Polygon;
+ deviceInfo->path = TikZ_Path;
+
+ /*
+ * Raster Routines. Currently implemented as stub functions to
+ * avoid nasty crashes.
+ */
+ deviceInfo->raster = TikZ_Raster;
+ deviceInfo->cap = TikZ_Cap;
+
+ /* Dummy routines. These are mainly used by GUI graphics devices. */
+ deviceInfo->activate = TikZ_Activate;
+ deviceInfo->deactivate = TikZ_Deactivate;
+ deviceInfo->locator = TikZ_Locator;
+ deviceInfo->mode = TikZ_Mode;
+
+ /*
+ * If outputting to a single file, call TikZ_Open to create and initialize
+ * the output. For multiple files, each call to TikZ_NewPage will set up a
+ * new file.
+ */
+ if( tikzInfo->onefile )
+ if( !TikZ_Open(deviceInfo) )
+ return FALSE;
+
+ return TRUE;
+}
+
+static void TikZ_WriteColorDefinition( tikzDevDesc *tikzInfo, void (*printOut)(tikzDevDesc *tikzInfo, const char *format, ...), int color, const char* colorname, const char* colorstr )
+{
+
+ debug_print_empty();
+
+ if ( strncmp(colorstr, "gray", 4) == 0 && strlen(colorstr) > 4)
+ {
+ int perc = atoi(colorstr+4);
+ printOut(tikzInfo,
+ "\\definecolor{%s}{gray}{%4.2f}\n",
+ colorname,
+ perc/100.0);
+ }
+ /* define aliased colors with RGB values */
+ else
+ printOut(tikzInfo,
+ "\\definecolor{%s}{RGB}{%d,%d,%d}\n",
+ colorname,
+ R_RED(color),
+ R_GREEN(color),
+ R_BLUE(color));
+}
+
+static void TikZ_WriteColorDefinitions( tikzDevDesc *tikzInfo )
+{
+
+ debug_print_empty();
+
+ int i;
+
+ for( i = 0; i < tikzInfo->ncolors; ++i)
+ {
+ const char* colorstr = col2name(tikzInfo->colors[i]);
+
+ if(colorstr[0] == '#')
+ colorstr = colorstr+1;
+
+ TikZ_WriteColorDefinition(tikzInfo, printColorOutput, tikzInfo->colors[i], colorstr, colorstr);
+ }
+}
+
+static void TikZ_WriteColorFile(tikzDevDesc *tikzInfo)
+{
+
+ debug_print_empty();
+
+ if ( tikzInfo->outColorFileName && tikzInfo->symbolicColors )
+ {
+ tikzInfo->colorFile = fopen(R_ExpandFileName(tikzInfo->outColorFileName), "w");
+ if( tikzInfo->colorFile)
+ {
+ TikZ_WriteColorDefinitions(tikzInfo);
+ fclose(tikzInfo->colorFile);
+ }
+ else
+ {
+ warning( "Color definition file could not be opened and is missing.\n" );
+ }
+
+ /* delete all colors used up till now */
+ tikzInfo->ncolors = 0;
+ tikzInfo->excessWarningPrinted = FALSE;
+ }
+}
+
+/*==============================================================================
+ Core Graphics Routines
+ Implementaion of an R Graphics Device as Defined by:
+ GraphicsDevice.h
+==============================================================================*/
+
+/*
+ * Routines for handling device state:
+ *
+ * - Open
+ * - Close
+ * - Newpage
+ * - Clip
+ * - Size
+ */
+static Rboolean TikZ_Open( pDevDesc deviceInfo )
+{
+
+ debug_print_empty();
+
+ /*
+ * Shortcut pointers to variables of interest. It seems like there HAS to be
+ * a more elegent way of accesing these...
+ */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ /* If creating multiple files, add the page number to the filename. */
+ if ( !tikzInfo->onefile )
+ sprintf(tikzInfo->outFileName, tikzInfo->originalFileName, tikzInfo->pageNum);
+
+ if( strlen(tikzInfo->originalColorFileName) > 0 )
+ {
+ tikzInfo->outColorFileName = calloc_x_strlen(tikzInfo->originalColorFileName, strlen(tikzInfo->outFileName));
+
+ /* deal with the extension */
+ const char *ext = strrchr(tikzInfo->outFileName, '.');
+
+ if( ext != NULL && strcmp(ext, ".tex") == 0)
+ {
+ char *fname = calloc_strcpy(tikzInfo->outFileName);
+ size_t extposition = ext - tikzInfo->outFileName;
+ fname[extposition] = '\0';
+ snprintf(tikzInfo->outColorFileName, strlen(tikzInfo->originalColorFileName)+strlen(tikzInfo->outFileName), tikzInfo->originalColorFileName, fname);
+ free(fname);
+ }
+ else
+ snprintf(tikzInfo->outColorFileName, strlen(tikzInfo->originalColorFileName)+strlen(tikzInfo->outFileName), tikzInfo->originalColorFileName, tikzInfo->outFileName);
+ }
+ else
+ tikzInfo->outColorFileName = NULL;
+
+ if ( !tikzInfo->console )
+ if ( !(tikzInfo->outputFile = fopen(R_ExpandFileName(tikzInfo->outFileName), "w")) )
+ return FALSE;
+
+ /* Print header comment */
+ Print_TikZ_Header( tikzInfo );
+
+ /* Header for a standalone LaTeX document*/
+ if ( tikzInfo->standAlone == TRUE ){
+ printOutput(tikzInfo,"%s",tikzInfo->documentDeclaration);
+ printOutput(tikzInfo,"%s",tikzInfo->packages);
+ printOutput(tikzInfo,"\\begin{document}\n\n");
+ }
+
+ return TRUE;
+}
+
+static void TikZ_Close( pDevDesc deviceInfo)
+{
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ if ( tikzInfo->clipState == TIKZ_FINISH_CLIP ) {
+ printOutput(tikzInfo, "\\end{scope}\n");
+ tikzInfo->clipState = TIKZ_NO_CLIP;
+ }
+
+ /* End the tikz environment if we're not doing a bare bones plot. */
+ if( tikzInfo->bareBones != TRUE && tikzInfo->pageState == TIKZ_FINISH_PAGE ) {
+ printOutput(tikzInfo, "\\end{tikzpicture}\n");
+ tikzInfo->pageState = TIKZ_NO_PAGE;
+ }
+
+ /* Close off the standalone document*/
+ if ( tikzInfo->standAlone == TRUE ) {
+ printOutput(tikzInfo, tikzInfo->footer);
+ printOutput(tikzInfo,"\n\\end{document}\n");
+ }
+
+ if ( tikzInfo->debug == TRUE )
+ printOutput(tikzInfo,
+ "%% Calculated string width %d times\n",
+ tikzInfo->stringWidthCalls);
+
+ /* Close the file and destroy the tikzInfo structure. */
+ if(tikzInfo->console == FALSE)
+ {
+ fclose(tikzInfo->outputFile);
+ tikzInfo->outputFile = NULL;
+ }
+
+ /* write symbolic color names to the corresponding file */
+ TikZ_WriteColorFile(tikzInfo);
+
+ /* Deallocate pointers */
+ free(tikzInfo->outFileName);
+ if ( !tikzInfo->onefile )
+ free(tikzInfo->originalFileName);
+
+ free(tikzInfo->colors);
+ free(tikzInfo->outColorFileName);
+ free(tikzInfo->originalColorFileName);
+
+ const_free(tikzInfo->documentDeclaration);
+ const_free(tikzInfo->packages);
+ const_free(tikzInfo->footer);
+
+ free(tikzInfo);
+
+}
+
+static void TikZ_NewPage( const pGEcontext plotParams, pDevDesc deviceInfo )
+{
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ if ( tikzInfo->clipState == TIKZ_FINISH_CLIP ) {
+ printOutput(tikzInfo, "\\end{scope}\n");
+ tikzInfo->clipState = TIKZ_NO_CLIP;
+ }
+
+ if ( tikzInfo->pageState == TIKZ_FINISH_PAGE ) {
+ if ( !tikzInfo->bareBones )
+ printOutput(tikzInfo, "\\end{tikzpicture}\n");
+
+ if ( !tikzInfo->onefile ) {
+ if( tikzInfo->standAlone )
+ printOutput(tikzInfo,"\n\\end{document}\n");
+
+ if( !tikzInfo->console )
+ fclose(tikzInfo->outputFile);
+ }
+
+ /* write symbolic color names to the corresponding file */
+ TikZ_WriteColorFile(tikzInfo);
+ }
+
+ /*
+ * Color definitions do not persist accross tikzpicture environments. Set the
+ * cached colors to "impossible" values so that the first drawing operation
+ * inside the next environment will trigger a re-definition of colors.
+ */
+ tikzInfo->oldFillColor = -999;
+ tikzInfo->oldDrawColor = -999;
+
+ /*
+ * Setting this flag will cause the `TikZ_CheckState` function to emit the
+ * code required to begin a new `tikzpicture` enviornment. `TikZ_CheckState`
+ * is called by every graphics function that generates visible output.
+ */
+ tikzInfo->pageState = TIKZ_START_PAGE;
+}
+
+static void TikZ_Clip( double x0, double x1,
+ double y0, double y1, pDevDesc deviceInfo )
+{
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ deviceInfo->clipBottom = y0;
+ deviceInfo->clipLeft = x0;
+ deviceInfo->clipTop = y1;
+ deviceInfo->clipRight = x1;
+
+ if ( tikzInfo->clipState == TIKZ_FINISH_CLIP )
+ printOutput(tikzInfo, "\\end{scope}\n");
+
+ /*
+ * Color definitions do not persist accross scopes. Set the cached colors to
+ * "impossible" values so that the first drawing operation inside the scope
+ * will trigger a re-definition of colors.
+ */
+ tikzInfo->oldFillColor = -999;
+ tikzInfo->oldDrawColor = -999;
+
+ /*
+ * Setting this flag will cause the `TikZ_CheckState` function to emit the
+ * code required to begin a new clipping scope. `TikZ_CheckState` is called
+ * by every graphics function that generates visible output.
+ */
+ tikzInfo->clipState = TIKZ_START_CLIP;
+}
+
+static void TikZ_Size( double *left, double *right,
+ double *bottom, double *top, pDevDesc deviceInfo){
+
+ debug_print_empty();
+
+ /* Return canvas size. */
+ *bottom = deviceInfo->bottom;
+ *left = deviceInfo->left;
+ *top = deviceInfo->top;
+ *right = deviceInfo->right;
+
+}
+
+
+/*
+ * Routines for calculating text metrics:
+ *
+ * - MetricInfo
+ * - StrWidth
+ */
+
+/*
+ * This function is supposed to calculate character metrics (such as raised
+ * letters, stretched letters, ect). Currently the TikZ device does not
+ * perform such functions, so this function returns the default metrics
+ * the Quartz device uses when it can't think of anything else.
+ *
+ * The fact that this function is not implemented is the most likely cause
+ * for the *vertical* alignment of text strings being off. This shortcoming
+ * is most obvious when plot legends are created.
+ *
+*/
+static void TikZ_MetricInfo(int c, const pGEcontext plotParams,
+ double *ascent, double *descent, double *width, pDevDesc deviceInfo ){
+
+ debug_print_empty();
+
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ if (tikzInfo->engine == pdftex) {
+ /*
+ * PdfTeX can only deal with ASCII characters, check the character code c
+ * to see if it falls outside the range of printable characters which are:
+ * 32-126
+ */
+ if( c < 32 || c > 126 ){
+ /* Non-printable character. Set metrics to zero and return. */
+ *ascent = 0.0;
+ *descent = 0.0;
+ *width = 0.0;
+ return;
+ }
+ }
+
+ // Calculate font scaling factor.
+ double fontScale = ScaleFont( plotParams, deviceInfo );
+
+ // Prepare to call back to R in order to retrieve character metrics.
+ SEXP namespace;
+ PROTECT( namespace = TIKZ_NAMESPACE );
+
+ // Call out to R to retrieve the latexParseCharForMetrics function.
+ // Note: this code will eventually call a different function that provides
+ // caching of the results. Right now we're directly calling the function
+ // that activates LaTeX.
+ SEXP metricFun = findFun(install("getLatexCharMetrics"), namespace);
+
+ SEXP RCallBack;
+ PROTECT( RCallBack = allocVector(LANGSXP, 8) );
+
+ // Place the function into the first slot of the SEXP.
+ SETCAR( RCallBack, metricFun );
+
+ // Place the character code into the second slot of the SEXP.
+ SETCADR( RCallBack, ScalarInteger( c ) );
+ SET_TAG( CDR( RCallBack ), install("charCode") );
+
+ // Pass graphics parameters cex and fontface.
+ SETCADDR( RCallBack, ScalarReal( fontScale ) );
+ SET_TAG( CDDR( RCallBack ), install("cex") );
+ SETCADDDR( RCallBack, ScalarInteger( plotParams->fontface ) );
+ SET_TAG( CDR(CDDR( RCallBack )), install("face") );
+
+ /*
+ * Set the TeX engine based on tikzInfo
+ */
+ switch (tikzInfo->engine) {
+ case pdftex:
+ SETCAD4R(RCallBack, mkString("pdftex"));
+ break;
+ case xetex:
+ SETCAD4R(RCallBack, mkString("xetex"));
+ break;
+ case luatex:
+ SETCAD4R(RCallBack, mkString("luatex"));
+ break;
+ }
+ SET_TAG(CDDR(CDDR(RCallBack)), install("engine"));
+
+ SETCAD4R(CDR(RCallBack), mkString(tikzInfo->documentDeclaration));
+ SET_TAG(CDR(CDDR(CDDR(RCallBack))), install("documentDeclaration"));
+
+ SETCAD4R(CDDR(RCallBack), mkString(tikzInfo->packages));
+ SET_TAG(CDDR(CDDR(CDDR(RCallBack))), install("packages"));
+
+ SETCAD4R(CDR(CDDR(RCallBack)), ScalarLogical(tikzInfo->verbose));
+ SET_TAG(CDR(CDDR(CDDR(CDDR(RCallBack)))), install("verbose"));
+
+ SEXP RMetrics;
+ PROTECT( RMetrics = eval(RCallBack, namespace) );
+
+ // Recover the metrics.
+ *ascent = REAL(RMetrics)[0];
+ *descent = REAL(RMetrics)[1];
+ *width = REAL(RMetrics)[2];
+
+ if( tikzInfo->debug == TRUE )
+ printOutput( tikzInfo, "%% Calculated character metrics. ascent: %f, descent: %f, width: %f\n",
+ *ascent, *descent, *width);
+
+ UNPROTECT(3);
+
+ return;
+
+}
+
+/*
+ * This function is supposed to calculate the plotted with, in device raster
+ * units of an arbitrary string. This is perhaps the most difficult function
+ * that a device needs to implement. Calculating the exact with of a string
+ * is especially tricky because this device is designed to print characters
+ * in whatever font is being used in the the TeX document. The end font that
+ * the user decides to typeset their document in may also be unknown to the
+ * device. The problem is further complicated by the fact that TeX strings
+ * can be used directly in annotations. For example the string \textit{x}
+ * literaly has 10 characters but when it is actually typeset it only has
+ * one. Given this difficulty the function currently writes the string
+ * to a temporary file and calls LaTeX in order to obtain an authoratative
+ * measure of the string width.
+ *
+ * There is a rediculous amount of overhead involved with this process and
+ * the number of calls required to obtion widths for common things such as
+ * all the number s on a plot axes can easily add up to several seconds.
+ *
+ * However, if we do not perform string width calculation R is unable to
+ * properly align text in the plots R. This is something that LaTeX and
+ * TikZ should actually be taking care of by themselves but the current
+ * graphics system does not allow for this.
+ *
+ * Given that we need text strings to be aligned for good output, we are
+ * stuck using this inefficient hybrid system untill we think of something
+ * better.
+ *
+*/
+static double TikZ_StrWidth( const char *str,
+ const pGEcontext plotParams, pDevDesc deviceInfo ){
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ // Calculate font scaling factor.
+ double fontScale = ScaleFont( plotParams, deviceInfo );
+
+ /*
+ * New string width calculation method: call back to R
+ * and run the R function getLatexStrWidth.
+ *
+ * This used to be implemented as a C function, but
+ * the nuts and bolts were re-implemented back
+ * on the R side of this package. There seems to
+ * have been no major performance penalty associated
+ * with doing this.
+ *
+ * Why was it done?
+ *
+ * - Windows and Linux did not suppress the output
+ * of the C system call to LaTeX which resulted
+ * in spam and lag. In the case of Windows, a
+ * whole mess of CMD windows were spawned which
+ * eventually crashed the system.
+ *
+ * - Using R's system() call we gain a level of
+ * abstraction that works accross all platforms.
+ * We can also use functions like tempdir() to
+ * do the dirty work somewhere where the user
+ * won't have to clean it up.
+ *
+ * - If a LaTeX parser ever gets implemented, it
+ * will probably be easiest to implement it in
+ * R. If a LaTeX parser ever gets stolen from
+ * something like python's matplotlib, R will
+ * probably provide the interface. Therefore
+ * a callback to R may be necessary anyway.
+ *
+ * - Having C code called by R call R code is
+ * fucking wicked.
+ *
+ */
+
+ /*
+ * Find the namespace of the TikZ package.
+ */
+ SEXP namespace;
+ PROTECT( namespace = TIKZ_NAMESPACE );
+
+ // Call out to R to retrieve the getLatexStrWidth function.
+ SEXP widthFun = findFun(install("getLatexStrWidth"), namespace);
+
+ /*
+ * Create a SEXP that will be the R function call. The SEXP will have five
+ * components- the R function being called, the string being passed, the
+ * current value of the graphics parameters cex and fontface and the TeX
+ * engine to be used. Therefore it is allocated as a LANGSXP vector of
+ * length 5. This is done inside a PROTECT() function to keep the R garbage
+ * collector from saying "Hmmm... what's this? Looks like noone is using it
+ * so I guess I will nuke it."
+ */
+ SEXP RCallBack;
+ PROTECT( RCallBack = allocVector(LANGSXP, 8) );
+
+ // Place the function into the first slot of the SEXP.
+ SETCAR( RCallBack, widthFun );
+
+ //If using the sanitize option call back to R for the sanitized string
+ char *cleanString = NULL;
+ if(tikzInfo->sanitize == TRUE){
+ cleanString = Sanitize( str );
+ // Place the sanitized string into the second slot of the SEXP.
+ SETCADR( RCallBack, mkString( cleanString ) );
+
+ }else{
+
+ // Place the string into the second slot of the SEXP.
+ SETCADR( RCallBack, mkString( str ) );
+
+ }
+ // Tag the string with a name, this name coressponds to the
+ // dummy argument of the R function getLatexStringWidth.
+ SET_TAG( CDR( RCallBack ), install("texString") );
+
+ // Pass graphics parameters cex and fontface.
+ SETCADDR( RCallBack, ScalarReal( fontScale ) );
+ SET_TAG( CDDR( RCallBack ), install("cex") );
+ SETCADDDR( RCallBack, ScalarInteger( plotParams->fontface ) );
+ SET_TAG( CDR(CDDR( RCallBack )), install("face") );
+
+ /*
+ * Set the TeX engine based on tikzInfo
+ */
+ switch (tikzInfo->engine) {
+ case pdftex:
+ SETCAD4R(RCallBack, mkString("pdftex"));
+ break;
+ case xetex:
+ SETCAD4R(RCallBack, mkString("xetex"));
+ break;
+ case luatex:
+ SETCAD4R(RCallBack, mkString("luatex"));
+ break;
+ }
+ SET_TAG(CDDR(CDDR(RCallBack)), install("engine"));
+
+ SETCAD4R(CDR(RCallBack), mkString(tikzInfo->documentDeclaration));
+ SET_TAG(CDR(CDDR(CDDR(RCallBack))), install("documentDeclaration"));
+
+ SETCAD4R(CDDR(RCallBack), mkString(tikzInfo->packages));
+ SET_TAG(CDDR(CDDR(CDDR(RCallBack))), install("packages"));
+
+ SETCAD4R(CDR(CDDR(RCallBack)), ScalarLogical(tikzInfo->verbose));
+ SET_TAG(CDR(CDDR(CDDR(CDDR(RCallBack)))), install("verbose"));
+
+ /*
+ * Call the R function, capture the result.
+ * PROTECT may not be necessary here, but I'm doing
+ * it just in case the SEXP holds a pointer to an
+ * R function return value that the garbage collector
+ * decides to nuke.
+ */
+ SEXP RStrWidth;
+ PROTECT( RStrWidth = eval(RCallBack, namespace) );
+
+ /*
+ * Why REAL()[0] instead of asReal(CAR())? I have no fucking
+ * clue...
+ *
+ * After browsing Rinternals.h, the location where SEXPs and
+ * their access functions are defined, I have an explanation
+ * that seems plausible.
+ *
+ * Since getLatexStrWidth returns a single variable of a single
+ * type, it is returned as a vector SEXP. The value can be
+ * extracted to a C variable by coercing the SEXP to real and
+ * then accessing the first element of the resulting array.
+ *
+ * When a R function returns, or passes in the case of the
+ * .External call that leads into all of this code, a collection
+ * of *different* objects they are passed as a list instead of
+ * a vector. Therefore CAR is needed to access the list followed
+ * by coercion using asReal().
+ *
+ * Seems like this explains what is going on here, although it
+ * is just a wild guess on my part. Maybe I should post to
+ * r-devel and ask for clarification...
+ *
+ */
+ double width = REAL(RStrWidth)[0];
+
+ /*
+ * Since we called PROTECT thrice, we must call UNPROTECT
+ * and pass the number 3.
+ */
+ UNPROTECT(3);
+ if(tikzInfo->sanitize == TRUE){ free(cleanString); }
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% Calculated string width of %s as %f\n",str,width);
+
+ /*
+ * Increment the number of times this function has been called
+ * Used for debugging purposes.
+ *
+ */
+ tikzInfo->stringWidthCalls++;
+
+ return(width);
+
+}
+
+
+/*
+ * Output routines
+ *
+ * - Text
+ * - Circle
+ * - Rectangle
+ * - Line
+ * - Polyline
+ * - Polygon
+ * - Path
+ * - Raster
+ */
+
+/*
+ * This function should plot a string of text at coordinates x and y with
+ * a rotation value specified by rot and horizontal alignment specified by
+ * hadj. Additional parameters such as color, font type, font style, line
+ * height and font size are specified in the pGEcontext variable plotParams.
+ *
+ * The rotation value is given in degrees.
+*/
+static void TikZ_Text( double x, double y, const char *str,
+ double rot, double hadj, const pGEcontext plotParams,
+ pDevDesc deviceInfo){
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ double tol = 0.01;
+
+ // Append font face commands depending on which font R is using.
+ char *tikzString = calloc_x_strlen(str, 20);
+
+ switch( plotParams->fontface ){
+
+ case 2:
+ // R is requesting bold font.
+ strcat( tikzString, "\\bfseries " );
+ break;
+
+ case 3:
+ // R is requesting italic font.
+ strcat( tikzString, "\\itshape " );
+ break;
+
+ case 4:
+ // R is requesting bold italic font.
+ strcat( tikzString, "\\bfseries\\itshape " );
+ break;
+
+ } // End font face switch.
+
+ // Form final output string.
+ strcat( tikzString, str );
+
+ // Calculate font scaling factor.
+ double fontScale = ScaleFont( plotParams, deviceInfo );
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% Drawing node at x = %f, y = %f\n",
+ x,y);
+
+ TikZ_CheckState(deviceInfo);
+ TikZ_DefineColors(plotParams, deviceInfo, DRAWOP_DRAW);
+
+ /* Start a node for the text, open an options bracket. */
+ printOutput(tikzInfo,"\n\\node[text=%s", tikzInfo->drawColor);
+ /* FIXME: Should bail out of this function early if text is fully transparent */
+ if( !R_OPAQUE(plotParams->col) )
+ printOutput(tikzInfo, ",text opacity=%4.2f", R_ALPHA(plotParams->col)/255.0);
+
+ /* Rotate the text if desired. */
+ if( rot != 0 )
+ printOutput(tikzInfo, ",rotate=%6.2f", rot );
+
+ /* End options, print coordinates and string. */
+ printOutput(tikzInfo, ",anchor=");
+
+ //Justify the text
+ if(fabs(hadj - 0.0) < tol){
+ //Left Justified
+ printOutput(tikzInfo, "base west");
+ }
+ if(fabs(hadj - 0.5) < tol){
+ //Center Justified
+ printOutput(tikzInfo, "base");
+ }
+ if(fabs(hadj - 1) < tol){
+ //Right Justified
+ printOutput(tikzInfo, "base east");
+ }
+
+ printOutput(tikzInfo,
+ ",inner sep=0pt, outer sep=0pt, scale=%6.2f] at (%6.2f,%6.2f) {",
+ fontScale, x, y);
+
+ char *cleanString = NULL;
+ if(tikzInfo->sanitize == TRUE){
+ //If using the sanitize option call back to R for the sanitized string
+ cleanString = Sanitize( tikzString );
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,"\n%% Sanatized %s to %s\n",tikzString,cleanString);
+ printOutput(tikzInfo, "%s};\n", cleanString);
+ }else{
+ printOutput(tikzInfo, "%s};\n", tikzString);
+ }
+
+ /*
+ * Since we no longer need tikzString,
+ * we should free the memory that it is being stored in.
+ */
+ free( tikzString );
+ if(tikzInfo->sanitize == TRUE){ free( cleanString ); }
+
+ /*
+ * Add a small red marker to indicate the
+ * point the text string is being aligned to.
+ */
+ if( DEBUG == TRUE )
+ printOutput(tikzInfo,
+ "\n\\draw[color=red, fill=red] (%6.2f,%6.2f) circle (0.5pt);\n",
+ x, y);
+
+}
+
+
+static void TikZ_Circle( double x, double y, double r,
+ const pGEcontext plotParams, pDevDesc deviceInfo){
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+ TikZ_DrawOps ops = TikZ_GetDrawOps(plotParams);
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% Drawing Circle at x = %f, y = %f, r = %f\n",
+ x,y,r);
+
+ TikZ_CheckState(deviceInfo);
+ TikZ_DefineColors(plotParams, deviceInfo, ops);
+
+ /* Start drawing, open an options bracket. */
+ printOutput(tikzInfo,"\n\\path[");
+ TikZ_WriteDrawOptions(plotParams, deviceInfo, ops);
+
+ /* End options, print coordinates. */
+ printOutput(tikzInfo, "] (%6.2f,%6.2f) circle (%6.2f);\n",
+ x,y,r);
+}
+
+static void TikZ_Rectangle( double x0, double y0,
+ double x1, double y1, const pGEcontext plotParams, pDevDesc deviceInfo){
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+ TikZ_DrawOps ops = TikZ_GetDrawOps(plotParams);
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% Drawing Rectangle from x0 = %f, y0 = %f to x1 = %f, y1 = %f\n",
+ x0,y0,x1,y1);
+
+ TikZ_CheckState(deviceInfo);
+ TikZ_DefineColors(plotParams, deviceInfo, ops);
+
+ /* Start drawing, open an options bracket. */
+ printOutput(tikzInfo,"\n\\path[");
+ TikZ_WriteDrawOptions(plotParams, deviceInfo, ops);
+
+ /* End options, print coordinates. */
+ printOutput(tikzInfo,
+ "] (%6.2f,%6.2f) rectangle (%6.2f,%6.2f);\n",
+ x0,y0,x1,y1);
+
+}
+
+
+static void TikZ_Line( double x1, double y1,
+ double x2, double y2, const pGEcontext plotParams, pDevDesc deviceInfo){
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+ TikZ_DrawOps ops = TikZ_GetDrawOps(plotParams) & DRAWOP_DRAW;
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% Drawing line from x1 = %10.4f, y1 = %10.4f to x2 = %10.4f, y2 = %10.4f\n",
+ x1,y1,x2,y2);
+
+ TikZ_CheckState(deviceInfo);
+ TikZ_DefineColors(plotParams, deviceInfo, ops);
+
+ /* Start drawing a line, open an options bracket. */
+ printOutput(tikzInfo,"\n\\path[");
+ TikZ_WriteDrawOptions(plotParams, deviceInfo, ops);
+
+ /* End options, print coordinates. */
+ printOutput(tikzInfo, "] (%6.2f,%6.2f) -- (%6.2f,%6.2f);\n",
+ x1,y1,x2,y2);
+
+}
+
+
+static void TikZ_Polyline( int n, double *x, double *y,
+ pGEcontext plotParams, pDevDesc deviceInfo ){
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+ /*
+ * FIXME:
+ * Any fill operations returned by TikZ_GetDrawOps are removed by
+ * applying a bitwise and with `DRAWOP_DRAW`. This is because the old
+ * StyleDef-based code had an ugly hack in it that explicitly disabled
+ * filling for polypaths.
+ *
+ * This fixme is here because we have no tests that detect this supposed bug.
+ */
+ TikZ_DrawOps ops = TikZ_GetDrawOps(plotParams) & DRAWOP_DRAW;
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% Starting Polyline\n");
+
+ TikZ_CheckState(deviceInfo);
+ TikZ_DefineColors(plotParams, deviceInfo, ops);
+
+ /* Start drawing, open an options bracket. */
+ printOutput(tikzInfo,"\n\\path[");
+ TikZ_WriteDrawOptions(plotParams, deviceInfo, ops);
+
+ /* End options, print first set of coordinates. */
+ printOutput(tikzInfo, "] (%6.2f,%6.2f) --\n",
+ x[0],y[0]);
+
+ /* Print coordinates for the middle segments of the line. */
+ int i;
+ for ( i = 1; i < n-1; i++ ){
+
+ printOutput(tikzInfo, "\t(%6.2f,%6.2f) --\n",
+ x[i],y[i]);
+
+ }
+
+ /* Print last set of coordinates. End path. */
+ printOutput(tikzInfo, "\t(%6.2f,%6.2f);\n",
+ x[n-1],y[n-1]);
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% End Polyline\n");
+
+}
+
+static void TikZ_Polygon( int n, double *x, double *y,
+ pGEcontext plotParams, pDevDesc deviceInfo ){
+
+ debug_print_empty();
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+ TikZ_DrawOps ops = TikZ_GetDrawOps(plotParams);
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% Starting Polygon\n");
+
+ TikZ_CheckState(deviceInfo);
+ TikZ_DefineColors(plotParams, deviceInfo, ops);
+
+ /* Start drawing, open an options bracket. */
+ printOutput(tikzInfo,"\n\\path[");
+ TikZ_WriteDrawOptions(plotParams, deviceInfo, ops);
+
+ /* End options, print first set of coordinates. */
+ printOutput(tikzInfo, "] (%6.2f,%6.2f) --\n",
+ x[0],y[0]);
+
+ /* Print coordinates for the middle segments of the line. */
+ int i;
+ for ( i = 1; i < n; i++ ){
+
+ printOutput(tikzInfo, "\t(%6.2f,%6.2f) --\n",
+ x[i],y[i]);
+
+ }
+
+ /* End path by cycling to first set of coordinates. */
+ printOutput(tikzInfo, "\tcycle;\n" );
+
+ /*Show only for debugging*/
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,
+ "%% End Polyline\n");
+
+}
+
+
+static void
+TikZ_Path( double *x, double *y,
+ int npoly, int *nper,
+ Rboolean winding,
+ const pGEcontext plotParams, pDevDesc deviceInfo
+){
+
+ debug_print_empty();
+
+ int i, j, index;
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+ TikZ_DrawOps ops = TikZ_GetDrawOps(plotParams);
+
+ if(tikzInfo->debug) { printOutput(tikzInfo, "%% Drawing polypath with %i subpaths\n", npoly); }
+
+ TikZ_CheckState(deviceInfo);
+ TikZ_DefineColors(plotParams, deviceInfo, ops);
+
+ /*
+ * Start drawing, open an options bracket.
+ *
+ * TikZ has built-in support for handling rule-based filling of operlaping
+ * polygons as R expects.
+ *
+ * Thank you TikZ!
+ */
+ printOutput(tikzInfo,"\n\\path[");
+ TikZ_WriteDrawOptions(plotParams, deviceInfo, ops);
+
+ /*
+ * Select rule to be used for overlapping fills as specified by the 'winding'
+ * parameter. See the "Graphic Parameters: Interior Rules" section of the PGF
+ * manual for details.
+ */
+ if (winding) {
+ printOutput(tikzInfo, ",nonzero rule");
+ } else {
+ printOutput(tikzInfo, ",even odd rule");
+ }
+
+ printOutput(tikzInfo, "]");
+
+
+ /* Draw polygons */
+ index = 0;
+ for (i = 0; i < npoly; i++) {
+
+ if(tikzInfo->debug) { printOutput(tikzInfo, "\n%% Drawing subpath: %i\n", i); }
+
+ printOutput(tikzInfo, "\n\t(%6.2f,%6.2f) --\n", x[index],y[index]);
+ index++;
+
+ for (j = 1; j < nper[i]; j++) {
+ printOutput(tikzInfo, "\t(%6.2f,%6.2f) --\n", x[index],y[index]);
+ index++;
+ }
+
+ printOutput(tikzInfo, "\tcycle" );
+
+ }
+
+ /* Close the \filldraw command */
+ printOutput(tikzInfo, ";\n");
+
+}
+
+
+/*
+ * Creates a raster image whose lower left corner is centered at the
+ * coordinates given by x and y.
+ *
+ * This is currently a stub function which displayes a message stating
+ * that raster creation is not yet implemented. Without this function,
+ * R would crash if the user attempts to print a raster.
+ *
+ * This could probably be implemented by writing the raster to an image file,
+ * say PNG, and then dropping a node in the TikZ output that contains
+ * an \includegraphics directive.
+*/
+static void TikZ_Raster(
+ unsigned int *raster,
+ int w, int h,
+ double x, double y,
+ double width, double height,
+ double rot,
+ Rboolean interpolate,
+ const pGEcontext plotParams, pDevDesc deviceInfo
+){
+
+ debug_print_empty();
+
+ /* Shortcut pointer to device information. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ /*
+ * Recover package namespace as the raster output function is not exported
+ * into the global environment.
+ */
+ SEXP namespace;
+ PROTECT( namespace = TIKZ_NAMESPACE );
+
+ /*
+ * Prepare callback to R for creation of a PNG from raster data. Three
+ * parameters will be passed:
+ *
+ * - The name of the current output file.
+ *
+ * - The number of rasters that have been output so far.
+ *
+ * - The raster data (as "nativeRaster" object).
+ */
+ SEXP RCallBack;
+ PROTECT( RCallBack = allocVector(LANGSXP, 4) );
+ SETCAR( RCallBack, install("tikz_writeRaster") );
+
+ SETCADR( RCallBack, mkString( tikzInfo->outFileName ) );
+ SET_TAG( CDR(RCallBack), install("fileName") );
+
+ SETCADDR( RCallBack, ScalarInteger( tikzInfo->rasterFileCount ) );
+ SET_TAG( CDDR(RCallBack), install("rasterCount") );
+
+ /*
+ * The raster values are stored as a 32 bit unsigned integer, effectively the
+ * data part of a "nativeRaster" object. From these, a proper "nativeRaster"
+ * object is created. Mirroring will be done as necessary.
+ */
+ SEXP nativeRaster;
+ PROTECT( nativeRaster = allocVector(INTSXP, w * h) );
+
+ int i, j, index, target, row_offset = 0, col_offset = 0, row_trans = 1, col_trans = 1;
+ if ( height < 0 ) {
+ /* Using these parameters, one can cause a loop to "count backwards" */
+ row_trans = -1;
+ row_offset = h - 1;
+ /*
+ * If a dimension is negative, the (x,y) coordinate no longer references
+ * the lower left corner of the image. We correct for this and then make
+ * sure the dimension is positive.
+ */
+ y += height;
+ height = fabs(height);
+ }
+
+ if ( width < 0 ) {
+ col_trans = -1;
+ col_offset = w - 1;
+ x += width;
+ width = fabs(width);
+ }
+
+ for ( i = 0; i < h; ++i ) {
+ for ( j = 0; j < w; ++j ) {
+ target = i*w + j;
+ index = (row_trans*i + row_offset)*w + (col_trans*j + col_offset);
+
+ INTEGER(nativeRaster)[target] = raster[index];
+ }
+ }
+
+ /* Turning the integer vector into a full-fledged nativeRaster object. */
+ SEXP dim = allocVector(INTSXP, 2);
+ INTEGER(dim)[0] = h;
+ INTEGER(dim)[1] = w;
+ setAttrib(nativeRaster, R_DimSymbol, dim);
+ setAttrib(nativeRaster, R_ClassSymbol, mkString("nativeRaster"));
+ setAttrib(nativeRaster, install("channels"), ScalarInteger(4));
+
+ SETCADDDR( RCallBack, nativeRaster );
+ SET_TAG(CDR(CDDR(RCallBack)), install("nativeRaster"));
+
+ SEXP rasterFile;
+ PROTECT( rasterFile = eval(RCallBack, namespace) );
+
+ TikZ_CheckState(deviceInfo);
+
+ /* Position the image using a node */
+ printOutput(tikzInfo, "\\node[inner sep=0pt,outer sep=0pt,anchor=south west,rotate=%6.2f] at (%6.2f, %6.2f) {\n",
+ rot, x, y);
+ /* Include the image using PGF's native image handling */
+ printOutput(tikzInfo, "\t\\pgfimage[width=%6.2fpt,height=%6.2fpt,",
+ width, height);
+ /* Set PDF interpolation (not all viewers respect this, but they should) */
+ if (interpolate) {
+ printOutput(tikzInfo, "interpolate=true]");
+ } else {
+ printOutput(tikzInfo, "interpolate=false]");
+ }
+ /* Slap in the file name */
+ printOutput(tikzInfo, "{%s}", translateChar(asChar(rasterFile)));
+ printOutput(tikzInfo, "};\n");
+
+ if (tikzInfo->debug) { printOutput(tikzInfo, "\\draw[fill=red] (%6.2f, %6.2f) circle (1pt);", x, y); }
+
+ /*
+ * Increment the number of raster files we have created with this device.
+ * This is used to provide unique file names for each raster.
+ */
+ tikzInfo->rasterFileCount++;
+
+ UNPROTECT(4);
+ return;
+
+}
+
+
+/*
+ * From what little documentation exists in GraphicsDevice.h, it is
+ * assumed that this function is intended to support capturing a
+ * "screen shot" of the current device output and returning it
+ * as a raster image.
+ *
+ * Implementing this functionality would require some careful thought
+ * and probably won't happen unless a serious need arises.
+ *
+ * Argument for implementation: could be useful for "previewing" the
+ * current* state of the tikzDevice output.
+*/
+static SEXP TikZ_Cap( pDevDesc deviceInfo ){
+
+ debug_print_empty();
+
+ warning( "The tikzDevice does not currently support capturing device output to a raster image." );
+ return R_NilValue;
+
+}
+
+
+/*
+ * Activate and deactivate execute commands when the active R device is
+ * changed. For devices using plotting windows, these routines usually change
+ * the window title to something like "Active" or "Inactive". Locator is a
+ * routine that is determines coordinates on the plotting canvas corresponding
+ * to a mouse click. For devices plotting to files these functions can be left
+ * as dummy routines.
+*/
+static void TikZ_Activate( pDevDesc deviceInfo ){
+ debug_print_empty();
+}
+
+static void TikZ_Deactivate( pDevDesc deviceInfo ){
+ debug_print_empty();
+}
+
+static Rboolean TikZ_Locator( double *x, double *y, pDevDesc deviceInfo ){
+
+ debug_print_empty();
+
+ return FALSE;
+}
+
+/*
+ * The mode function is called when R begins drawing and ends drawing using
+ * a device. Currently there are no actions necessary under these conditions
+ * so this function is a dummy routine. Conciveably this function could be
+ * used to wrap TikZ graphics in \begin{scope} and \end{scope} directives.
+*/
+static void TikZ_Mode( int mode, pDevDesc deviceInfo ){
+
+ debug_print_empty();
+}
+
+/*==============================================================================
+
+ End Core Graphics Routines
+
+==============================================================================*/
+
+
+/*==============================================================================
+
+ Style Definition Routines
+
+==============================================================================*/
+
+/*
+ * This function constructs a value that can be tested using a bitwise and to
+ * determine if a given plotting opertion will result in a visible fill or
+ * stroke.
+ */
+static TikZ_DrawOps TikZ_GetDrawOps(pGEcontext plotParams)
+{
+
+ debug_print_empty();
+
+ TikZ_DrawOps ops = DRAWOP_NOOP;
+
+ /*
+ * NOTE:
+ *
+ * Should also check that `plotParams.lty > 0` as a line type of 0 means
+ * "blank". However, R does not seem to set this parameter consistently.
+ */
+ if( !R_TRANSPARENT(plotParams->col) && (plotParams->lwd > 0) )
+ ops |= DRAWOP_DRAW;
+
+ if( !R_TRANSPARENT(plotParams->fill) )
+ ops |= DRAWOP_FILL;
+
+ return ops;
+}
+
+static Rboolean TikZ_CheckColor(tikzDevDesc *tikzInfo, int color)
+{
+
+ debug_print_empty();
+
+ int i;
+
+ for (i = 0; i < tikzInfo->ncolors; ++i)
+ {
+ if( tikzInfo->colors[i] == color )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static Rboolean TikZ_CheckAndAddColor(tikzDevDesc *tikzInfo, int color)
+{
+
+ debug_print_empty();
+
+ Rboolean colorfound = FALSE;
+
+ if( !tikzInfo->symbolicColors )
+ return FALSE;
+
+ colorfound = TikZ_CheckColor(tikzInfo, color);
+
+ if( !colorfound && !tikzInfo->excessWarningPrinted && tikzInfo->ncolors == tikzInfo->maxSymbolicColors )
+ {
+ warning("Too many colors used, reverting to non-symbolic storage");
+ tikzInfo->excessWarningPrinted = TRUE;
+ return FALSE;
+ }
+
+ if( tikzInfo->ncolors < tikzInfo->maxSymbolicColors && !colorfound )
+ {
+ tikzInfo->colors[tikzInfo->ncolors] = color;
+ tikzInfo->ncolors++;
+ colorfound = TRUE;
+ }
+
+ return colorfound;
+}
+
+static void TikZ_DefineDrawColor(tikzDevDesc *tikzInfo, int color, TikZ_DrawOps ops)
+{
+
+ debug_print_empty();
+
+ const char *colorstr = col2name(color);
+ const char* colors[] = {"", "drawColor", "fillColor"};
+ char (*pdest)[sizeof tikzInfo->drawColor / sizeof* tikzInfo->drawColor];
+
+ if( colorstr[0] == '#' )
+ colorstr = colorstr+1;
+
+ if( ops == DRAWOP_DRAW)
+ {
+ pdest = &tikzInfo->drawColor;
+ }
+ else if( ops == DRAWOP_FILL )
+ {
+ pdest = &tikzInfo->fillColor;
+ }
+ else
+ return; // shouldn't happen, just to satisfy the compiler
+
+ if( TikZ_CheckAndAddColor(tikzInfo, color) )
+ {
+ strscpy(*pdest, colorstr);
+ }
+ else
+ {
+ strscpy(*pdest, colors[ops]);
+
+ TikZ_WriteColorDefinition(tikzInfo, printOutput, color, *pdest, colorstr);
+ }
+
+
+}
+
+static void TikZ_DefineColors(pGEcontext plotParams, pDevDesc deviceInfo, TikZ_DrawOps ops)
+{
+
+ debug_print_empty();
+
+ int color;
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ if ( ops & DRAWOP_DRAW ) {
+ color = plotParams->col;
+ if ( color != tikzInfo->oldDrawColor ) {
+ tikzInfo->oldDrawColor = color;
+ TikZ_DefineDrawColor(tikzInfo, color, DRAWOP_DRAW);
+ }
+ }
+
+ if ( ops & DRAWOP_FILL ) {
+ color = plotParams->fill;
+ if( color != tikzInfo->oldFillColor ) {
+ tikzInfo->oldFillColor = color;
+ TikZ_DefineDrawColor(tikzInfo, color, DRAWOP_FILL);
+ }
+ }
+
+}
+
+/*
+ * NOTE: This function operates under the assumption that no other functions
+ * have written into the options bracket for a path. Custom path options should
+ * be added after the call to `TikZ_WriteDrawOptions` and should remember to
+ * bring their own commas.
+ */
+static void TikZ_WriteDrawOptions(const pGEcontext plotParams, pDevDesc deviceInfo,
+ TikZ_DrawOps ops)
+{
+
+ debug_print_empty();
+
+ /* Bail out if there is nothing to do */
+ if ( ops == DRAWOP_NOOP )
+ return;
+
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ if ( ops & DRAWOP_DRAW ) {
+ printOutput(tikzInfo, "draw=%s", tikzInfo->drawColor);
+ if( !R_OPAQUE(plotParams->col) )
+ printOutput(tikzInfo, ",draw opacity=%4.2f", R_ALPHA(plotParams->col)/255.0);
+
+ TikZ_WriteLineStyle(plotParams, tikzInfo);
+ }
+
+ if ( ops & DRAWOP_FILL ) {
+ /* Toss in a comma if we printed draw options */
+ if ( ops & DRAWOP_DRAW )
+ printOutput(tikzInfo, ",");
+
+ printOutput(tikzInfo, "fill=%s", tikzInfo->fillColor);
+ if( !R_OPAQUE(plotParams->fill) )
+ printOutput(tikzInfo, ",fill opacity=%4.2f", R_ALPHA(plotParams->fill)/255.0);
+ }
+
+}
+
+static void TikZ_WriteLineStyle(pGEcontext plotParams, tikzDevDesc *tikzInfo)
+{
+
+ debug_print_empty();
+
+ /* Set the line width */
+ printOutput(tikzInfo,",line width=%4.1fpt", tikzInfo->lwdUnit * plotParams->lwd);
+
+ if ( plotParams->lty > 1 ) {
+ char dashlist[8];
+ int i, nlty, lty = plotParams->lty;
+
+ /*
+ * From ?par :
+ *
+ * Line types can either be specified by giving an index into a small
+ * built-in table of line types (1 = solid, 2 = dashed, etc, see lty above)
+ * or directly as the lengths of on/off stretches of line. This is done
+ * with a string of an even number (up to eight) of characters, namely
+ * non-zero (hexadecimal) digits which give the lengths in consecutive
+ * positions in the string. For example, the string "33" specifies three
+ * units on followed by three off and "3313" specifies three units on
+ * followed by three off followed by one on and finally three off. The
+ * ‘units’ here are (on most devices) proportional to lwd, and with lwd = 1
+ * are in pixels or points or 1/96 inch.
+ *
+ * The five standard dash-dot line types (lty = 2:6) correspond to:
+ * c("44", "13", "1343", "73", "2262")
+ *
+ * (0=blank, 1=solid (default), 2=dashed, 3=dotted, 4=dotdash, 5=longdash,
+ * 6=twodash)
+ */
+
+ /*Retrieve the line type pattern*/
+ for ( i = 0; i < 8 && lty & 15 ; i++ ) {
+ dashlist[i] = lty & 15;
+ lty = lty >> 4;
+ }
+ nlty = i; i = 0;
+
+ printOutput(tikzInfo, ",dash pattern=");
+
+ /*Set the dash pattern*/
+ while( i < nlty ){
+ if( (i % 2) == 0 ){
+ printOutput(tikzInfo, "on %dpt ", dashlist[i]);
+ }else{
+ printOutput(tikzInfo, "off %dpt ", dashlist[i]);
+ }
+ i++;
+ }
+ }
+
+ switch ( plotParams->ljoin ) {
+ case GE_ROUND_JOIN:
+ printOutput(tikzInfo, ",line join=round");
+ break;
+ case GE_MITRE_JOIN:
+ /* Default if nothing is specified */
+ if(plotParams->lmitre != 10)
+ printOutput(tikzInfo, ",mitre limit=%4.2f",plotParams->lmitre);
+ break;
+ case GE_BEVEL_JOIN:
+ printOutput(tikzInfo, ",line join=bevel");
+ }
+
+ switch ( plotParams->lend ) {
+ case GE_ROUND_CAP:
+ printOutput(tikzInfo, ",line cap=round");
+ break;
+ case GE_BUTT_CAP:
+ /* Default if nothing is specified */
+ break;
+ case GE_SQUARE_CAP:
+ printOutput(tikzInfo, ",line cap=rect");
+ }
+
+}
+
+/*
+ * This function calculates an appropriate scaling factor for text by
+ * first calculating the ratio of the requested font size to the LaTeX
+ * base font size. The ratio is then further scaled by the value of
+ * the character expansion factor cex.
+*/
+static double
+ScaleFont( const pGEcontext plotParams, pDevDesc deviceInfo ){
+
+ debug_print_empty();
+
+ // These parameters all affect the font size.
+ double baseSize = deviceInfo->startps;
+ double fontSize = plotParams->ps;
+ double cex = plotParams->cex;
+
+ double fontScale = ( fontSize / baseSize ) * cex;
+
+ return( fontScale );
+
+}
+
+
+/*==============================================================================
+
+ Other User Callable Routines
+
+==============================================================================*/
+
+void TikZ_Annotate(const char **annotation, int *size, int *checkstate){
+
+ debug_print_empty();
+
+ //1. Get values of tikzInfo and deviceInfo
+ //2. Print out annotation
+ pDevDesc deviceInfo = GEcurrentDevice()->dev;
+
+ /* Shortcut pointers to variables of interest. */
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ int i = 0;
+
+ if(tikzInfo->debug == TRUE)
+ printOutput(tikzInfo,"\n%% Annotating Graphic\n");
+
+ if (*checkstate)
+ TikZ_CheckState(deviceInfo);
+
+ for(i = 0; i < size[0]; ++i)
+ printOutput(tikzInfo, "%s\n", annotation[i] );
+}
+
+
+/*
+ * Returns information stored in the tikzDevDesc structure of a given device.
+ */
+SEXP TikZ_DeviceInfo(SEXP device_num){
+
+ debug_print_empty();
+
+ int dev_index = asInteger(device_num);
+ pDevDesc deviceInfo = GEgetDevice(dev_index - 1)->dev;
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ SEXP info, names;
+ PROTECT( info = allocVector(VECSXP, 2) );
+ PROTECT( names = allocVector(STRSXP, 2) );
+
+ SET_VECTOR_ELT(info, 0, mkString(tikzInfo->outFileName));
+ SET_STRING_ELT(names, 0, mkChar("output_file"));
+
+ switch( tikzInfo->engine ){
+ case pdftex:
+ SET_VECTOR_ELT(info, 1, mkString("pdftex"));
+ break;
+ case xetex:
+ SET_VECTOR_ELT(info, 1, mkString("xetex"));
+ break;
+ case luatex:
+ SET_VECTOR_ELT(info, 1, mkString("luatex"));
+ break;
+ }
+ SET_STRING_ELT(names, 1, mkChar("engine"));
+
+
+ setAttrib(info, R_NamesSymbol, names);
+
+ UNPROTECT(2);
+ return(info);
+
+}
+
+
+/* Run R evaluations inside a context protected from things like CTRL-C */
+SEXP TikZ_EvalWithoutInterrupts(SEXP expr, SEXP envir){
+
+ debug_print_empty();
+
+ SEXP result;
+
+ BEGIN_SUSPEND_INTERRUPTS{
+ result = eval(expr, envir);
+ }END_SUSPEND_INTERRUPTS;
+
+ return result;
+}
+
+
+/*==============================================================================
+
+ Utility Routines
+
+==============================================================================*/
+
+static void printOutput(tikzDevDesc *tikzInfo, const char *format, ...){
+
+ va_list(ap);
+ va_start(ap, format);
+
+ if(tikzInfo->console == TRUE)
+ Rvprintf(format, ap);
+ else
+ vfprintf(tikzInfo->outputFile, format, ap);
+
+ va_end(ap);
+
+}
+
+static void printColorOutput(tikzDevDesc *tikzInfo, const char *format, ...){
+
+ va_list(ap);
+ va_start(ap, format);
+
+ if(tikzInfo->colorFile == NULL)
+ Rvprintf(format, ap);
+ else
+ vfprintf(tikzInfo->colorFile, format, ap);
+
+ va_end(ap);
+
+}
+
+
+/*
+ * This function is responsible for writing header information
+ * to the output file. Currently this header information includes:
+ *
+ * - The current version number of TikZ device.
+ * - The date on which the graphic was created.
+ *
+*/
+static void Print_TikZ_Header( tikzDevDesc *tikzInfo ){
+
+ debug_print_empty();
+
+ /* Call back to R to retrieve current date and version num*/
+
+ /*
+ * Recover package namespace as the date formatting function
+ * is not exported
+ */
+ SEXP namespace;
+ PROTECT( namespace = TIKZ_NAMESPACE );
+
+
+ SEXP currentDate;
+ PROTECT(
+ currentDate = eval(lang1( install("getDateStampForTikz") ),
+ namespace )
+ );
+
+ SEXP currentVersion;
+ PROTECT(
+ currentVersion = eval(lang1( install("getTikzDeviceVersion") ),
+ namespace )
+ );
+
+ if( tikzInfo->timestamp )
+ printOutput( tikzInfo, "%% Created by tikzDevice version %s on %s\n",
+ CHAR(STRING_ELT(currentVersion,0)), CHAR(STRING_ELT(currentDate,0)) );
+
+ //Specifically for TeXShop, force it to open the file with UTF-8 encoding
+ printOutput(tikzInfo, "%% !TEX encoding = UTF-8 Unicode\n");
+
+ if ( tikzInfo->console )
+ printOutput(tikzInfo, "\\relax\n");
+
+ UNPROTECT(3);
+
+}
+
+static char *Sanitize(const char *str){
+
+ debug_print_empty();
+
+ SEXP namespace;
+ PROTECT( namespace = TIKZ_NAMESPACE );
+
+ //Splice in escaped charaters via a callback to R
+
+ //Call out to R to retrieve the sanitizeTexString function.
+ SEXP sanitizeFun = findFun( install("sanitizeTexString"), namespace );
+
+ /*
+ * Create a SEXP that will be the R function call. The SEXP will
+ * have four components- the R function being calledand the string
+ * being passed. Therefore it is allocated as a LANGSXP
+ * vector of length 2. This is done inside a PROTECT() function
+ * to keep the R garbage collector from saying "Hmmm... what's
+ * this? Looks like noone is using it so I guess I will nuke it."
+ */
+ SEXP RCallBack;
+ PROTECT( RCallBack = allocVector(LANGSXP,2) );
+
+ // Place the function into the first slot of the SEXP.
+ SETCAR( RCallBack, sanitizeFun );
+
+ // Place the string into the second slot of the SEXP.
+ SETCADR( RCallBack, mkString( str ) );
+ // Tag the string with a name, this name coressponds to the
+ // dummy argument of the R function sanitizeTexString.
+ SET_TAG( CDR( RCallBack ), install("string") );
+
+ /*
+ * Call the R function, capture the result.
+ */
+ SEXP RSanitizedString;
+ PROTECT( RSanitizedString = eval( RCallBack, R_GlobalEnv ) );
+
+ const char *cleanString = CHAR(asChar(RSanitizedString));
+
+ //if(DEBUG)
+ // printf("Clean String: %s\n",cleanString);
+
+ /*
+ * cleanString is a pointer to data derived from an R object. Once UNPROTECT
+ * is called, this object may be eaten by the R garbage collector. Therefore,
+ * we need to copy the data we care about into a new string.
+ */
+ char *cleanStringCP = calloc_strcpy(cleanString);
+
+ // Since we called PROTECT three times, we must call UNPROTECT
+ // and pass the number 3.
+ UNPROTECT(3);
+
+ return cleanStringCP;
+}
+
+#if 0
+static Rboolean contains_multibyte_chars(const char *str){
+ /*
+ * Recover package namespace as the multibyte check function
+ * is not exported
+ */
+ SEXP namespace;
+ PROTECT( namespace = TIKZ_NAMESPACE );
+
+ SEXP multibyte_check_fun = findFun(
+ install("anyMultibyteUTF8Characters"), namespace);
+
+ SEXP RCallBack;
+ PROTECT( RCallBack = allocVector(LANGSXP,2) );
+
+ // Place the function into the first slot of the SEXP.
+ SETCAR( RCallBack, multibyte_check_fun );
+
+ // Place the string into the second slot of the SEXP.
+ SETCADR( RCallBack, mkString( str ) );
+ SET_TAG( CDR( RCallBack ), install("string") );
+
+ /*
+ * Call the R function, capture the result.
+ */
+ SEXP result;
+ PROTECT( result = eval(RCallBack, namespace) );
+
+ UNPROTECT(3);
+
+ return(asLogical(result));
+}
+#endif
+
+
+/*
+ * This function is responsible for converting lengths given in page
+ * dimensions (ie. inches, cm, etc.) to device dimensions (currenty
+ * points- 1/72.27 of an inch). However, due to the flexability of TeX
+ * and TikZ, any combination of device and user dimensions could
+ * theoretically be supported.
+*/
+static double dim2dev( double length ){
+ return length*72.27;
+}
+
+
+/*
+ * This function checks to see if a new page or clipping scope needs to be
+ * started and is called by every function that produces visible output. Having
+ * this function allows the creation of new pages or clipping scopes to be
+ * deferred until there is actually output to place in the environment.
+ */
+static void TikZ_CheckState(pDevDesc deviceInfo)
+{
+ tikzDevDesc *tikzInfo = (tikzDevDesc *) deviceInfo->deviceSpecific;
+
+ if( tikzInfo->pageState == TIKZ_START_PAGE ) {
+ /*
+ * Start a new file if we are outputting to multiple files.
+ *
+ * FIXME:
+ * Need better error handling. If we can't open a file, we are basically
+ * fucked and the whole device should implode. Instead, calling `error` will
+ * jump control to R without allowing for any sort of teardown and the
+ * program will be left in an indeterminate state.
+ */
+ if( !tikzInfo->onefile )
+ if( !TikZ_Open(deviceInfo) )
+ error("Unable to open output file: %s", tikzInfo->outputFile);
+
+ if ( tikzInfo->debug == TRUE )
+ printOutput(tikzInfo,
+ "%% Beginning new tikzpicture 'page'\n");
+
+ if ( tikzInfo->bareBones != TRUE )
+ {
+ printOutput(tikzInfo, "\\begin{tikzpicture}[x=1pt,y=1pt]\n");
+
+ if( tikzInfo->symbolicColors && tikzInfo->outColorFileName)
+ printOutput(tikzInfo, "\\InputIfFileExists{%s}{}{}\n", tikzInfo->outColorFileName);
+ }
+ /*
+ * Emit a path that encloses the entire canvas area in order to ensure that
+ * the final typeset plot is the size the user specified. Adding the `use as
+ * bounding box` key to the path options should save TikZ some work when it
+ * comes to calculating the bounding of the graphic from its contents.
+ */
+ int color = deviceInfo->startfill;
+ tikzInfo->oldFillColor = color;
+ TikZ_DefineDrawColor(tikzInfo, color, DRAWOP_FILL);
+
+ printOutput(tikzInfo, "\\path[use as bounding box");
+
+ /* TODO: Consider only filling when the color is not transparent. */
+ printOutput(tikzInfo, ",fill=%s", tikzInfo->fillColor);
+ if( !R_OPAQUE(color) )
+ printOutput(tikzInfo, ",fill opacity=%4.2f", R_ALPHA(color)/255.0);
+
+ printOutput(tikzInfo, "] (0,0) rectangle (%6.2f,%6.2f);\n",
+ deviceInfo->right,deviceInfo->top);
+
+ tikzInfo->pageState = TIKZ_FINISH_PAGE;
+ tikzInfo->pageNum++;
+ } /* End if pageState == TIKZ_START_PAGE */
+
+
+ if ( tikzInfo->clipState == TIKZ_START_CLIP ) {
+ printOutput(tikzInfo, "\\begin{scope}\n");
+ printOutput(tikzInfo,
+ "\\path[clip] (%6.2f,%6.2f) rectangle (%6.2f,%6.2f);\n",
+ deviceInfo->clipLeft, deviceInfo->clipBottom,
+ deviceInfo->clipRight, deviceInfo->clipTop);
+
+ if ( tikzInfo->debug == TRUE )
+ printOutput(tikzInfo,
+ "\\path[draw=red,very thick,dashed] (%6.2f,%6.2f) rectangle (%6.2f,%6.2f);\n",
+ deviceInfo->clipLeft, deviceInfo->clipBottom,
+ deviceInfo->clipRight, deviceInfo->clipTop);
+
+ tikzInfo->clipState = TIKZ_FINISH_CLIP;
+ } /* End if clipState == TIKZ_START_CLIP */
+
+}
+
+static char *calloc_strcpy(const char *str){
+ return calloc_x_strcpy(str, 0);
+}
+
+static char *calloc_x_strcpy(const char *str, size_t extra){
+ char *ret;
+
+ ret = calloc_x_strlen(str, extra);
+ strcpy(ret, str);
+ return ret;
+}
+
+static char *calloc_x_strlen(const char *str, size_t extra){
+ return (char*) calloc(strlen(str) + 1 + extra, sizeof(char));
+}
+
+static void const_free(const void *ptr){
+ free((void*)ptr);
+}
+
+static void strlcpy_(char *dst, const char* src, size_t n){
+ if (n <= 0) return;
+ strncpy(dst, src, n - 1);
+ dst[n - 1] = '\0';
+}
diff --git a/src/tikzDevice.h b/src/tikzDevice.h
new file mode 100644
index 0000000..d889992
--- /dev/null
+++ b/src/tikzDevice.h
@@ -0,0 +1,224 @@
+/*
+ * There probably won't be more than one C source file using
+ * this header, but it's still a good idea to make sure the
+ * compiler will only include it once. Errors could result
+ * otherwise.
+*/
+
+#ifndef HAVE_TIKZDEV_H // Begin once-only header
+#define HAVE_TIKZDEV_H
+
+#ifndef DEBUG
+#define DEBUG FALSE
+#endif
+
+/* Use default graphics engine function declarations. */
+#define R_USE_PROTOTYPES 1
+
+/* Declarations for functions provided by the R language */
+#include <R.h>
+#include <Rinternals.h>
+#include <R_ext/GraphicsEngine.h>
+
+/* Check R Graphics Engine for minimum supported version */
+#if R_GE_version < 8
+#error "This version of the tikzDevice must be compiled against R 2.12.0 or newer!"
+#endif
+
+/* Macro definitions */
+#define TIKZ_NAMESPACE R_FindNamespace(mkString("tikzDevice"))
+
+
+/*
+ * tikz_engine can take on possible values from a list of all the TeX engines
+ * we support.
+ */
+typedef enum {
+ pdftex = 1,
+ xetex = 2,
+ luatex = 3
+} tikz_engine;
+
+typedef enum {
+ TIKZ_START_PAGE = 1,
+ TIKZ_NO_PAGE = 0,
+ TIKZ_FINISH_PAGE = -1
+} TikZ_PageState;
+
+typedef enum {
+ TIKZ_START_CLIP = 1,
+ TIKZ_NO_CLIP = 0,
+ TIKZ_FINISH_CLIP = -1
+} TikZ_ClipState;
+
+
+/*
+ * tikzDevDesc is a structure that is used to hold information
+ * that is unique to the implementation of the TikZ Device. A
+ * new component may be created for any information that it is
+ * deemed desirable to have available during execution of TikZ
+ * Device routines.
+*/
+typedef struct {
+ FILE *outputFile;
+ FILE *colorFile;
+ char *outFileName;
+ char *originalFileName;
+ char *outColorFileName;
+ char *originalColorFileName;
+ tikz_engine engine;
+ int rasterFileCount;
+ int pageNum;
+ double lwdUnit;
+ Rboolean debug;
+ Rboolean standAlone;
+ Rboolean bareBones;
+ Rboolean onefile;
+ int oldFillColor;
+ int oldDrawColor;
+ int stringWidthCalls;
+ const char *documentDeclaration;
+ const char *packages;
+ const char *footer;
+ Rboolean console;
+ Rboolean sanitize;
+ TikZ_ClipState clipState;
+ TikZ_PageState pageState;
+ Rboolean symbolicColors;
+ int* colors;
+ int ncolors;
+ int maxSymbolicColors;
+ Rboolean excessWarningPrinted;
+ char drawColor[32];
+ char fillColor[32];
+ Rboolean timestamp;
+ Rboolean verbose;
+} tikzDevDesc;
+
+
+/* Function Prototypes */
+
+/* Public Functions */
+SEXP TikZ_StartDevice(SEXP args);
+void TikZ_Annotate(const char **annotation, int *size, int *checkstate);
+SEXP TikZ_DeviceInfo(SEXP device_num);
+
+
+static Rboolean TikZ_Setup(
+ pDevDesc deviceInfo,
+ const char *fileName,
+ double width, double height, Rboolean onefile,
+ const char *bg, const char *fg, double baseSize, double lwdUnit,
+ Rboolean standAlone, Rboolean bareBones,
+ const char *documentDeclaration,
+ const char *packages, const char *footer,
+ Rboolean console, Rboolean sanitize, int engine,
+ Rboolean symbolicColors, const char *colorFileName,
+ int maxSymbolicColors, Rboolean timestamp, Rboolean verbose );
+
+
+/* Graphics Engine function hooks. Defined in GraphicsDevice.h . */
+
+/* Device State */
+static Rboolean TikZ_Open( pDevDesc deviceInfo );
+static void TikZ_Close( pDevDesc deviceInfo );
+static void TikZ_NewPage( const pGEcontext plotParams, pDevDesc deviceInfo );
+static void TikZ_Clip( double x0, double x1,
+ double y0, double y1, pDevDesc deviceInfo );
+static void TikZ_Size( double *left, double *right,
+ double *bottom, double *top, pDevDesc deviceInfo);
+
+/* Font Metrics*/
+static void TikZ_MetricInfo( int c, const pGEcontext plotParams,
+ double *ascent, double *descent, double *width, pDevDesc deviceInfo );
+static double TikZ_StrWidth( const char *str,
+ const pGEcontext plotParams, pDevDesc deviceInfo );
+
+/* Drawing routines. */
+static void TikZ_Text( double x, double y, const char *str,
+ double rot, double hadj, const pGEcontext plotParams, pDevDesc deviceInfo);
+static void TikZ_Circle( double x, double y, double r,
+ const pGEcontext plotParams, pDevDesc deviceInfo );
+static void TikZ_Rectangle( double x0, double y0,
+ double x1, double y1, const pGEcontext plotParams, pDevDesc deviceInfo );
+static void TikZ_Line( double x1, double y1,
+ double x2, double y2, const pGEcontext plotParams, pDevDesc deviceInfo );
+static void TikZ_Polyline( int n, double *x, double *y,
+ pGEcontext plotParams, pDevDesc deviceInfo );
+static void TikZ_Polygon( int n, double *x, double *y,
+ pGEcontext plotParams, pDevDesc deviceInfo );
+static void
+TikZ_Path( double *x, double *y,
+ int npoly, int *nper,
+ Rboolean winding,
+ const pGEcontext plotParams, pDevDesc deviceInfo );
+
+static void TikZ_Raster(
+ unsigned int *raster,
+ int w, int h,
+ double x, double y,
+ double width, double height,
+ double rot,
+ Rboolean interpolate,
+ const pGEcontext plotParams, pDevDesc deviceInfo
+);
+
+/* Dummy/Unimplemented routines. */
+static SEXP TikZ_Cap( pDevDesc deviceInfo );
+static void TikZ_Activate( pDevDesc deviceInfo );
+static void TikZ_Deactivate( pDevDesc deviceInfo );
+static Rboolean TikZ_Locator( double *x, double *y, pDevDesc deviceInfo );
+static void TikZ_Mode( int mode, pDevDesc deviceInfo );
+
+/* End R Graphics engine function hooks. */
+
+
+
+/*Internal style definition routines*/
+
+/*
+ * This enumeration specifies the kinds of drawing operations that need to be
+ * performed, such as filling or drawing a path.
+ *
+ * When adding new members, use the next power of 2 as so that the presence or
+ * absance of an operation can be determined using bitwise operators.
+ */
+typedef enum {
+ DRAWOP_NOOP = 0,
+ DRAWOP_DRAW = 1,
+ DRAWOP_FILL = 2
+} TikZ_DrawOps;
+static TikZ_DrawOps TikZ_GetDrawOps(pGEcontext plotParams);
+
+static void TikZ_DefineColors(const pGEcontext plotParams, pDevDesc deviceInfo, TikZ_DrawOps ops);
+static void TikZ_WriteDrawOptions(const pGEcontext plotParams, pDevDesc deviceInfo, TikZ_DrawOps ops);
+static void TikZ_WriteLineStyle(pGEcontext plotParams, tikzDevDesc *tikzInfo);
+
+static double ScaleFont( const pGEcontext plotParams, pDevDesc deviceInfo );
+
+/* Utility Routines*/
+static void printOutput(tikzDevDesc *tikzInfo, const char *format, ...);
+static void printColorOutput(tikzDevDesc *tikzInfo, const char *format, ...);
+static void Print_TikZ_Header( tikzDevDesc *tikzInfo );
+static char *Sanitize(const char *str);
+#if 0
+static Rboolean contains_multibyte_chars(const char *str);
+#endif
+static double dim2dev( double length );
+static void TikZ_CheckState(pDevDesc deviceInfo);
+static char *calloc_strcpy(const char *str);
+static char *calloc_x_strcpy(const char *str, size_t extra);
+static char *calloc_x_strlen(const char *str, size_t extra);
+static void const_free(const void *ptr);
+static void strlcpy_(char *dst, const char* src, size_t n);
+#define strscpy(dst, src) strlcpy_(dst, src, sizeof(dst) / sizeof(*(dst)))
+
+
+// From http://stackoverflow.com/a/1644898/946850:
+#define debug_print(fmt, ...) \
+ do { if (DEBUG) fprintf(stderr, "%s:%d:%s(): " fmt "\n", __FILE__, __LINE__, __func__, __VA_ARGS__); } while (0)
+
+#define debug_print_empty() \
+ do { if (DEBUG) fprintf(stderr, "%s:%d:%s()\n", __FILE__, __LINE__, __func__); } while (0)
+
+#endif // End of Once Only header
diff --git a/tests/testthat/Rplots.tex b/tests/testthat/Rplots.tex
new file mode 100644
index 0000000..e69de29
diff --git a/tests/testthat/Rplots_colors.tex b/tests/testthat/Rplots_colors.tex
new file mode 100644
index 0000000..21145ca
--- /dev/null
+++ b/tests/testthat/Rplots_colors.tex
@@ -0,0 +1,2 @@
+\definecolor{transparent}{RGB}{255,255,255}
+\definecolor{black}{RGB}{0,0,0}
diff --git a/tests/testthat/helper_bootstrap.R b/tests/testthat/helper_bootstrap.R
new file mode 100644
index 0000000..4e69819
--- /dev/null
+++ b/tests/testthat/helper_bootstrap.R
@@ -0,0 +1,77 @@
+library(methods)
+library(tikzDevice)
+library(testthat)
+library(stringr)
+
+library(tools)
+library(evaluate)
+
+# Process command arguments
+test_args <- commandArgs(TRUE)
+torture_mem <- any(str_detect(test_args, '^--use-gctorture'))
+
+if ( length(tags_to_run <- test_args[str_detect(test_args, '^--run-tests')]) ) {
+ tags_to_run <- unlist(str_split(
+ str_split(tags_to_run, '=')[[1]][2],
+ ',' ))
+}
+
+if (torture_mem) { gctorture(TRUE) }
+using_windows <- Sys.info()['sysname'] == 'Windows'
+
+# Ensure tikzDevice options have been set to their default values.
+setTikzDefaults(overwrite = TRUE)
+options(tikzMetricsDictionary = NULL)
+
+expand_test_path <- function(path) {
+ normalizePath(path, mustWork = FALSE)
+}
+
+# Set up directories for test output.
+test_output_dir <- expand_test_path(file.path(getwd(), 'test_output'))
+if( !file.exists(test_output_dir) ) dir.create(test_output_dir)
+test_work_dir <- expand_test_path(file.path(getwd(), 'test_work'))
+if( !file.exists(test_work_dir) ) dir.create(test_work_dir)
+
+test_standard_dir <- normalizePath('standard_graphs')
+
+oldwarn = options(warn = 1)
+
+# Locate required external programs
+gs_cmd <- Sys.which(ifelse(using_windows, 'gswin32c', 'gs'))
+if ( nchar(gs_cmd) == 0 ) {
+ warning("Ghostscript not found.")
+ gs_cmd <- NULL
+} else {
+ gs_cmd <- normalizePath(gs_cmd)
+}
+
+compare_cmd <- Sys.which("compare")
+if ( nchar(compare_cmd) == 0 || is.null(gs_cmd) ) {
+ warning("compare not found.")
+ compare_cmd <- NULL
+} else {
+ compare_cmd <- normalizePath(compare_cmd)
+}
+
+convert_cmd <- normalizePath(
+ ifelse(using_windows,
+ system("bash -c 'which convert'", intern = TRUE, ignore.stderr = TRUE),
+ Sys.which('convert')
+ ))
+
+if ( nchar(convert_cmd) == 0 ) {
+ convert_cmd <- NULL
+ warning("convert not found.")
+} else if ( is.null(gs_cmd) ) {
+ convert_cmd <- NULL
+ warning("Cannot use convert because Ghostscript is missing.")
+} else {
+ convert_cmd <- normalizePath(convert_cmd)
+}
+
+cat("Ghostscript: ", gs_cmd, "\n")
+cat("compare: ", compare_cmd, "\n")
+cat("convert: ", convert_cmd, "\n")
+
+options(oldwarn)
diff --git a/tests/testthat/helper_expectations.R b/tests/testthat/helper_expectations.R
new file mode 100644
index 0000000..7766362
--- /dev/null
+++ b/tests/testthat/helper_expectations.R
@@ -0,0 +1,18 @@
+# Custom expectations for tests.
+
+runs_cleanly <- function ()
+# This expecatation is an inversion and combination of the throws_error and
+# gives_warning expectations. That is, the code run under this expectation
+# should not throw any errors or generate any warnings.
+{
+ function(expr) {
+ oldwarn = options(warn = 2)
+ res = try(eval(substitute(expr), parent.frame()), silent = TRUE)
+ options(oldwarn)
+
+ is_try_error = inherits(res, 'try-error')
+ expectation(!is_try_error,
+ sprintf("warnings or errors occurred:\n%s",
+ as.character(res)))
+ }
+}
diff --git a/tests/testthat/helper_graphics.R b/tests/testthat/helper_graphics.R
new file mode 100644
index 0000000..19304e9
--- /dev/null
+++ b/tests/testthat/helper_graphics.R
@@ -0,0 +1,155 @@
+# This file contains functions that help set up and run the tikzDevice through
+# test graphs.
+
+get_graphics_reporter <- function() {
+ get_reporter()$reporters[[2]]
+}
+
+do_graphics_test <- function(short_name, description, graph_code, fuzz = 0,
+ engine = 'pdftex', graph_options = NULL, skip_if = NULL, tags = NULL, ...) {
+
+ context(description)
+
+ if (str_length(Sys.getenv('R_TESTS')) != 0){
+ # `R CMD check` is running. Skip test and return so our graphics testsuite
+ # does not slow down the CRAN daily checks.
+ cat("SKIP")
+ return(FALSE)
+ }
+
+ if (!is.null(skip_if)) {
+ if (skip_if()) {
+ cat("SKIP")
+ return(FALSE)
+ }
+ }
+
+ graph_created <- FALSE
+
+ if (!is.null(graph_options)) {
+ # If this test uses custom options, make sure the current options are
+ # restored after it finishes.
+ orig_opts <- options()
+ options(graph_options)
+ on.exit(options(orig_opts))
+ }
+
+ graph_file <- file.path(test_work_dir, str_c(short_name,'.tex'))
+
+ test_that('Graph is created cleanly',{
+ # Set random number generator to a known state so results will be
+ # reproducible
+ set.seed(4) # As specified by RFC 1149.5 ;)
+
+ expect_that(
+ create_graph(graph_code, graph_file, engine),
+ runs_cleanly()
+ )
+
+ })
+
+ test_that('Graph compiles cleanly',{
+
+ expect_that(graph_created <<- compile_graph(graph_file, engine), runs_cleanly())
+
+ })
+
+ test_that('Output regression check',{
+
+ # Uses the `compare` utility in imagemagick/graphicsmagick to diff the
+ # generated graph against a "standard". If there are any differences, we
+ # changed the code in a way that broke the behavior of the TikzDevice.
+ # This test always "passes" as the real result is the number of pixels that
+ # were found to be different between the test graph and the standard graph.
+ # Such a result must be interpreted by a human.
+ expect_less_than(compare_graph(short_name, tags), fuzz + 0.1, is_true(),
+ info = short_name,
+ label = "Pixel representation of graph unchanged")
+
+ })
+
+
+ return( graph_created )
+
+}
+
+create_graph <- function(graph_code, graph_file, engine){
+
+ tikz(file = graph_file, standAlone = TRUE, engine = engine)
+ on.exit(dev.off())
+
+ eval(graph_code)
+
+ invisible()
+
+}
+
+compile_graph <- function(graph_file, engine){
+ # Have to compile in the same directory as the .tex file so that things like
+ # raster images can be found.
+ oldwd <- getwd()
+ setwd(test_work_dir); on.exit(setwd(oldwd))
+
+ tex_cmd <- switch(engine,
+ pdftex = getOption('tikzLatex'),
+ xetex = getOption('tikzXelatex'),
+ luatex = getOption('tikzLualatex')
+ )
+
+ silence <- system(paste(shQuote(tex_cmd), '-interaction=batchmode',
+ '-output-directory', test_work_dir,
+ graph_file ), intern = TRUE)
+
+ output_pdf = sub('tex$', 'pdf', graph_file)
+ if ( file.exists(output_pdf) ) {
+ file.rename(output_pdf, file.path(test_output_dir, basename(output_pdf)))
+ graph_created <- TRUE
+ } else {
+ graph_created <- FALSE
+ }
+
+ return( graph_created )
+
+}
+
+compare_graph <- function(graph_name, tags){
+ if ( is.null(compare_cmd) ) {
+ get_graphics_reporter()$vis_result('SKIP')
+ return(TRUE)
+ }
+
+ test_output <- file.path(test_output_dir, str_c(graph_name, '.pdf'))
+ if( 'ggplot2' %in% tags && exists('scale_y_probit') ) {
+ # We are using a version of ggplot2 that predates 0.9.
+ #
+ # FIXME: Remove this once we drop support for 2.13.x.
+ standard_graph <- file.path(test_standard_dir, 'ggplot_old', str_c(graph_name, '.pdf'))
+ } else {
+ standard_graph <- file.path(test_standard_dir, str_c(graph_name, '.pdf'))
+ }
+
+ if ( !file.exists(test_output) || !file.exists(standard_graph) ) {
+ get_graphics_reporter()$vis_result('SKIP')
+ return(TRUE)
+ }
+
+
+ # Normalize and quote some paths in case we are running on Windows
+ compare_output <- file.path(test_work_dir, str_c(graph_name, '_diff.png'))
+ command_line <- paste(
+ shQuote(compare_cmd), '-density 300', '-metric AE',
+ shQuote(test_output), shQuote(standard_graph), shQuote(compare_output),
+ "2>&1 | awk '{metric=$NF};END{print metric}'"
+ )
+
+ get_graphics_reporter()$set_cmp_command(command_line)
+ result <- as.double(system(paste(
+ # Force the command to be executed through bash
+ 'bash -c ', shQuote(command_line)),
+ intern = TRUE, ignore.stderr = TRUE))
+
+ get_graphics_reporter()$vis_result(result)
+
+ return(as.numeric(result))
+
+}
diff --git a/tests/testthat/helper_reporters.R b/tests/testthat/helper_reporters.R
new file mode 100644
index 0000000..0d11de6
--- /dev/null
+++ b/tests/testthat/helper_reporters.R
@@ -0,0 +1,246 @@
+# This file contains custom test reporters.
+
+library(stringr)
+
+DetailedReporter <- setRefClass('DetailedReporter', where = .GlobalEnv, contains = 'Reporter',
+ fields = list(
+ 'width' = 'integer',
+ 'n_tests' = 'integer',
+ 'n_failed' = 'integer',
+ 'failures' = 'list',
+ 'start_time' = 'ANY'
+ ),
+ methods = list(
+
+ start_reporter = function() {
+ failed <<- FALSE
+
+ width <<- getOption('width')
+ n_tests <<- 0L
+ n_failed <<- 0L
+ failures <<- list()
+ start_time <<- NULL
+
+ cat(str_c(rep('=', width), collapse=''), '\n')
+ },
+
+ start_context = function(desc) {
+ cat(str_c('\n', desc, '\n'))
+ cat(str_c(rep('-', nchar(desc)), collapse=''), '\n')
+
+ context <<- desc
+ n_tests <<- 0L
+ n_failed <<- 0L
+ failures <<- list()
+ },
+
+ start_test = function(desc){
+ cat(desc)
+ test <<- desc
+ start_time <<- Sys.time()
+ },
+
+ add_result = function(result) {
+ spacer <- paste(rep(' ',width - nchar(test) - 5),
+ collapse = '')
+ if (result$passed) {
+ cat(spacer, crayon::green("PASS\n"))
+ } else {
+ failed <<- TRUE
+ n_failed <<- n_failed + 1L
+ result$test <- test
+ failures[[n_failed]] <<- result
+
+ cat(spacer, crayon::red("FAIL\n"))
+ }
+ },
+
+ end_test = function(){
+ elapsed_time <- as.numeric(difftime(Sys.time(), start_time,
+ units='secs'))
+ cat(' Elapsed Time: ', sprintf("%6.2f", elapsed_time), ' seconds\n')
+ test <<- NULL
+ start_time <<- NULL
+ n_tests <<- n_tests + 1L
+ },
+
+ end_context = function() {
+ cat(paste(rep('-', width), collapse=''), '\n')
+ n_success <- n_tests - n_failed
+ success_per <- round( n_success / n_tests * 100, 2 )
+
+ test_status <- paste(n_success, '/', n_tests,
+ ' (', success_per, '%)', sep = '')
+ test_status <- ifelse(n_failed == 0L,
+ crayon::green(test_status),
+ crayon::red(test_status))
+
+ cat(test_status, 'tests successfully executed in this context.\n' )
+
+ if( n_failed > 0L ){
+ cat('\nOutput from failed tests:\n\n')
+
+ charrep <- function(char, times) {
+ sapply(times, function(i) str_c(rep.int(char, i), collapse = ""))
+ }
+
+ type <- ifelse(sapply(failures, "[[", "error"), "Error", "Failure")
+ tests <- sapply(failures, "[[", "test")
+ header <- str_c(type, ": ", tests, " ")
+ linewidth <- ifelse(nchar(header) > getOption("width"),
+ 0, getOption("width") - nchar(header))
+ line <- charrep("-", linewidth )
+
+ message <- sapply(failures, "[[", "failure_msg")
+
+ cat(str_c(
+ crayon::red(header), line, "\n",
+ message, "\n", collapse = "\n"))
+
+ }
+ },
+
+ end_reporter = function() {
+ cat(str_c(rep('=', width), collapse=''), '\n\n')
+ }
+ ) # End methods list
+) # End DetailedReporter class
+
+# This reporter is used by the graphics tests. It is very similar to the
+# DetailedReporter, but contains specialized functionality for displaying the
+# results of graphics tests.
+GraphicsReporter <- setRefClass('GraphicsReporter', where = .GlobalEnv, contains = 'DetailedReporter',
+ fields = list(
+ 'cmp_command' = 'character',
+ 'ran_vis_diff' = 'logical',
+ 'pixel_error' = 'ANY',
+ 'n_ctx_failed' = 'integer'
+ ),
+ methods = list(
+
+ start_reporter = function() {
+ width <<- getOption('width')
+
+ ran_vis_diff <<- FALSE
+ pixel_error <<- 'SKIP'
+ n_tests <<- 0L
+ n_failed <<- 0L
+ n_ctx_failed <<- 0L
+
+ cat(str_c(rep('=', width), collapse=''), '\n')
+ cat('Graphics Tests', '\n')
+ cat(str_c(rep('~', width), collapse=''), '\n')
+ },
+
+ start_context = function(desc) {
+ cat(str_c('\n', desc, '\n'))
+ failed <<- FALSE
+ },
+
+ start_test = function(desc){
+ cat(' ', desc)
+ test <<- desc
+ start_time <<- Sys.time()
+ },
+
+ set_cmp_command = function(the_cmp_command) {
+ cmp_command <<- the_cmp_command
+ },
+
+ vis_result = function(the_error) {
+ ran_vis_diff <<- TRUE
+ pixel_error <<- the_error
+ },
+
+ add_result = function(result) {
+ if ( ran_vis_diff ) {
+ if ( is.na(pixel_error) ) {
+ spacer <- paste(rep(' ', width - nchar(test) - 19),
+ collapse = '')
+ cat(spacer, crayon::yellow("UNKNOWN"), "\n")
+ } else if ( pixel_error == 'SKIP' ) {
+ spacer <- paste(rep(' ', width - nchar(test) - 19),
+ collapse = '')
+ cat(spacer, crayon::yellow("SKIP"), "\n")
+ } else {
+ spacer <- paste(rep(' ', width - nchar(test) - 29),
+ collapse = '')
+ cat(spacer, 'Error of:',
+ crayon::yellow(sprintf("%8.2g pixels", pixel_error)),
+ "\n"
+ )
+ if (pixel_error > 0)
+ cat(' Command for comparison:', "\n", cmp_command, "\n")
+ }
+ }
+
+ spacer <- paste(rep(' ', width - nchar(test) - 19),
+ collapse = '')
+ if (result$passed) {
+ cat(spacer, crayon::green("PASS"))
+ } else {
+ failed <<- TRUE
+ n_failed <<- n_failed + 1L
+ result$test <- test
+ failures[[n_failed]] <<- result
+
+ cat(spacer, crayon::red("FAIL"))
+ }
+ },
+
+ end_test = function(){
+ if( ran_vis_diff ) {
+ ran_vis_diff <<- FALSE
+ } else {
+ elapsed_time <- as.numeric(difftime(Sys.time(), start_time,
+ units='secs'))
+ cat(sprintf(" %6.2f sec\n", elapsed_time))
+ }
+ },
+
+ end_context = function() {
+ if ( failed ) {
+ n_ctx_failed <<- n_ctx_failed + 1L
+ }
+ n_tests <<- n_tests + 1L
+ },
+
+ end_reporter = function() {
+ cat(paste(rep('-', width), collapse=''), '\n')
+ n_success <- n_tests - n_ctx_failed
+ success_per <- round( n_success / n_tests * 100, 2 )
+
+ test_status <- paste(n_success, '/', n_tests,
+ ' (', success_per, '%)', sep = '')
+ test_status <- ifelse(n_ctx_failed == 0L,
+ crayon::green(test_status),
+ crayon::red(test_status))
+
+ cat(test_status, 'tests successfully executed.\n' )
+
+ if( n_failed > 0L ){
+ cat('\nOutput from failed tests:\n\n')
+
+ charrep <- function(char, times) {
+ sapply(times, function(i) str_c(rep.int(char, i), collapse = ""))
+ }
+
+ type <- ifelse(sapply(failures, "[[", "error"), "Error", "Failure")
+ tests <- sapply(failures, "[[", "test")
+ header <- str_c(type, ": ", tests, " ")
+ linewidth <- ifelse(nchar(header) > getOption("width"),
+ 0, getOption("width") - nchar(header))
+ line <- charrep("-", linewidth )
+
+ message <- sapply(failures, "[[", "failure_msg")
+
+ cat(str_c(
+ crayon::red(header), line, "\n",
+ message, "\n", collapse = "\n"))
+
+ }
+ cat(str_c(rep('=', width), collapse=''), '\n\n')
+ }
+
+ ) # End methods list
+) # End GraphicsReporter
diff --git a/tests/testthat/standard_graphs/annotation_noflush.pdf b/tests/testthat/standard_graphs/annotation_noflush.pdf
new file mode 100644
index 0000000..9c71da0
Binary files /dev/null and b/tests/testthat/standard_graphs/annotation_noflush.pdf differ
diff --git a/tests/testthat/standard_graphs/base_annotation.pdf b/tests/testthat/standard_graphs/base_annotation.pdf
new file mode 100644
index 0000000..a27c803
Binary files /dev/null and b/tests/testthat/standard_graphs/base_annotation.pdf differ
diff --git a/tests/testthat/standard_graphs/base_raster.pdf b/tests/testthat/standard_graphs/base_raster.pdf
new file mode 100644
index 0000000..32408ca
Binary files /dev/null and b/tests/testthat/standard_graphs/base_raster.pdf differ
diff --git a/tests/testthat/standard_graphs/base_raster_noresample.pdf b/tests/testthat/standard_graphs/base_raster_noresample.pdf
new file mode 100644
index 0000000..79ca5d3
Binary files /dev/null and b/tests/testthat/standard_graphs/base_raster_noresample.pdf differ
diff --git a/tests/testthat/standard_graphs/base_symbolic_simple.pdf b/tests/testthat/standard_graphs/base_symbolic_simple.pdf
new file mode 100644
index 0000000..f164464
Binary files /dev/null and b/tests/testthat/standard_graphs/base_symbolic_simple.pdf differ
diff --git a/tests/testthat/standard_graphs/character_expansion.pdf b/tests/testthat/standard_graphs/character_expansion.pdf
new file mode 100644
index 0000000..1604a0c
Binary files /dev/null and b/tests/testthat/standard_graphs/character_expansion.pdf differ
diff --git a/tests/testthat/standard_graphs/contour_lines.pdf b/tests/testthat/standard_graphs/contour_lines.pdf
new file mode 100644
index 0000000..316c3a0
Binary files /dev/null and b/tests/testthat/standard_graphs/contour_lines.pdf differ
diff --git a/tests/testthat/standard_graphs/draw_circles.pdf b/tests/testthat/standard_graphs/draw_circles.pdf
new file mode 100644
index 0000000..3db8a78
Binary files /dev/null and b/tests/testthat/standard_graphs/draw_circles.pdf differ
diff --git a/tests/testthat/standard_graphs/draw_filled_circles.pdf b/tests/testthat/standard_graphs/draw_filled_circles.pdf
new file mode 100644
index 0000000..dbc7b5d
Binary files /dev/null and b/tests/testthat/standard_graphs/draw_filled_circles.pdf differ
diff --git a/tests/testthat/standard_graphs/filled_rectangle.pdf b/tests/testthat/standard_graphs/filled_rectangle.pdf
new file mode 100644
index 0000000..03c91a3
Binary files /dev/null and b/tests/testthat/standard_graphs/filled_rectangle.pdf differ
diff --git a/tests/testthat/standard_graphs/ggplot2_superscripts.pdf b/tests/testthat/standard_graphs/ggplot2_superscripts.pdf
new file mode 100644
index 0000000..af9918a
Binary files /dev/null and b/tests/testthat/standard_graphs/ggplot2_superscripts.pdf differ
diff --git a/tests/testthat/standard_graphs/ggplot2_test.pdf b/tests/testthat/standard_graphs/ggplot2_test.pdf
new file mode 100644
index 0000000..1d2e7fb
Binary files /dev/null and b/tests/testthat/standard_graphs/ggplot2_test.pdf differ
diff --git a/tests/testthat/standard_graphs/graph_box.pdf b/tests/testthat/standard_graphs/graph_box.pdf
new file mode 100644
index 0000000..2c0ae85
Binary files /dev/null and b/tests/testthat/standard_graphs/graph_box.pdf differ
diff --git a/tests/testthat/standard_graphs/grid_annotation.pdf b/tests/testthat/standard_graphs/grid_annotation.pdf
new file mode 100644
index 0000000..ff30efd
Binary files /dev/null and b/tests/testthat/standard_graphs/grid_annotation.pdf differ
diff --git a/tests/testthat/standard_graphs/grid_raster.pdf b/tests/testthat/standard_graphs/grid_raster.pdf
new file mode 100644
index 0000000..caa19bc
Binary files /dev/null and b/tests/testthat/standard_graphs/grid_raster.pdf differ
diff --git a/tests/testthat/standard_graphs/hello_TeX.pdf b/tests/testthat/standard_graphs/hello_TeX.pdf
new file mode 100644
index 0000000..3029b8c
Binary files /dev/null and b/tests/testthat/standard_graphs/hello_TeX.pdf differ
diff --git a/tests/testthat/standard_graphs/line_color.pdf b/tests/testthat/standard_graphs/line_color.pdf
new file mode 100644
index 0000000..5e9b323
Binary files /dev/null and b/tests/testthat/standard_graphs/line_color.pdf differ
diff --git a/tests/testthat/standard_graphs/line_color_width.pdf b/tests/testthat/standard_graphs/line_color_width.pdf
new file mode 100644
index 0000000..09345af
Binary files /dev/null and b/tests/testthat/standard_graphs/line_color_width.pdf differ
diff --git a/tests/testthat/standard_graphs/line_types.pdf b/tests/testthat/standard_graphs/line_types.pdf
new file mode 100644
index 0000000..810fa8a
Binary files /dev/null and b/tests/testthat/standard_graphs/line_types.pdf differ
diff --git a/tests/testthat/standard_graphs/line_weights.pdf b/tests/testthat/standard_graphs/line_weights.pdf
new file mode 100644
index 0000000..bad597c
Binary files /dev/null and b/tests/testthat/standard_graphs/line_weights.pdf differ
diff --git a/tests/testthat/standard_graphs/lots_of_elements.pdf b/tests/testthat/standard_graphs/lots_of_elements.pdf
new file mode 100644
index 0000000..b121892
Binary files /dev/null and b/tests/testthat/standard_graphs/lots_of_elements.pdf differ
diff --git a/tests/testthat/standard_graphs/luatex_utf8_characters.pdf b/tests/testthat/standard_graphs/luatex_utf8_characters.pdf
new file mode 100644
index 0000000..24bcfdb
Binary files /dev/null and b/tests/testthat/standard_graphs/luatex_utf8_characters.pdf differ
diff --git a/tests/testthat/standard_graphs/pch_caracters.pdf b/tests/testthat/standard_graphs/pch_caracters.pdf
new file mode 100644
index 0000000..e4a63a8
Binary files /dev/null and b/tests/testthat/standard_graphs/pch_caracters.pdf differ
diff --git a/tests/testthat/standard_graphs/persp_3D.pdf b/tests/testthat/standard_graphs/persp_3D.pdf
new file mode 100644
index 0000000..11ea73a
Binary files /dev/null and b/tests/testthat/standard_graphs/persp_3D.pdf differ
diff --git a/tests/testthat/standard_graphs/plot_legend.pdf b/tests/testthat/standard_graphs/plot_legend.pdf
new file mode 100644
index 0000000..62e6b02
Binary files /dev/null and b/tests/testthat/standard_graphs/plot_legend.pdf differ
diff --git a/tests/testthat/standard_graphs/polypath.pdf b/tests/testthat/standard_graphs/polypath.pdf
new file mode 100644
index 0000000..cc8b8a4
Binary files /dev/null and b/tests/testthat/standard_graphs/polypath.pdf differ
diff --git a/tests/testthat/standard_graphs/raster_reflection.pdf b/tests/testthat/standard_graphs/raster_reflection.pdf
new file mode 100644
index 0000000..e24c1ce
Binary files /dev/null and b/tests/testthat/standard_graphs/raster_reflection.pdf differ
diff --git a/tests/testthat/standard_graphs/string_placement.pdf b/tests/testthat/standard_graphs/string_placement.pdf
new file mode 100644
index 0000000..086a212
Binary files /dev/null and b/tests/testthat/standard_graphs/string_placement.pdf differ
diff --git a/tests/testthat/standard_graphs/text_alignment.pdf b/tests/testthat/standard_graphs/text_alignment.pdf
new file mode 100644
index 0000000..731a05d
Binary files /dev/null and b/tests/testthat/standard_graphs/text_alignment.pdf differ
diff --git a/tests/testthat/standard_graphs/text_color.pdf b/tests/testthat/standard_graphs/text_color.pdf
new file mode 100644
index 0000000..01d828f
Binary files /dev/null and b/tests/testthat/standard_graphs/text_color.pdf differ
diff --git a/tests/testthat/standard_graphs/transparency.pdf b/tests/testthat/standard_graphs/transparency.pdf
new file mode 100644
index 0000000..7214ba1
Binary files /dev/null and b/tests/testthat/standard_graphs/transparency.pdf differ
diff --git a/tests/testthat/standard_graphs/utf8_characters.pdf b/tests/testthat/standard_graphs/utf8_characters.pdf
new file mode 100644
index 0000000..50578dc
Binary files /dev/null and b/tests/testthat/standard_graphs/utf8_characters.pdf differ
diff --git a/tests/testthat/standard_graphs/xetex_variants.pdf b/tests/testthat/standard_graphs/xetex_variants.pdf
new file mode 100644
index 0000000..9af8be6
Binary files /dev/null and b/tests/testthat/standard_graphs/xetex_variants.pdf differ
diff --git a/tests/testthat/test_error_handling.R b/tests/testthat/test_error_handling.R
new file mode 100644
index 0000000..865fa99
--- /dev/null
+++ b/tests/testthat/test_error_handling.R
@@ -0,0 +1,130 @@
+# Switch to the detailed reporter implemented in helper_reporters.R
+with_reporter(MultiReporter$new(reporters = list(get_reporter(), DetailedReporter$new())), {
+
+context('Test tikzDevice error and warning messages')
+
+test_that('Null device is not a tikzDevice',{
+
+ expect_that(
+ suppressMessages(isTikzDevice()),
+ is_false()
+ )
+
+})
+
+test_that('Device produces an error for unescaped characters',{
+
+ expect_that(
+ suppressMessages(getLatexStrWidth('_')),
+ throws_error('TeX was unable to calculate metrics')
+ )
+
+})
+
+test_that('Device warns about the lower bound of the ASCII table when using pdftex',{
+
+ expect_that(
+ getLatexCharMetrics(31, engine = 'pdftex'),
+ gives_warning('pdftex can only generate metrics for character codes between 32 and 126!')
+ )
+
+})
+
+test_that('Device warns about the upper bound of the ASCII table when using pdftex',{
+
+ expect_that(
+ getLatexCharMetrics(127),
+ gives_warning('pdftex can only generate metrics for character codes between 32 and 126!')
+ )
+
+})
+
+test_that("Device won't accept non-numeric ASCII codes",{
+
+ expect_that(
+ suppressMessages(getLatexCharMetrics('a')),
+ gives_warning('getLatexCharMetrics only accepts integers!')
+ )
+
+})
+
+test_that('Device throws error when a path cannot be opened',{
+
+ expect_that(
+ tikz('/why/would/you/have/a/path/like/this.tex'),
+ throws_error('directory does not exist or is not writable')
+ )
+
+})
+
+test_that('tikzAnnotate refuses to work with a non-tikzDevice',{
+
+ expect_that(
+ tikzAnnotate('test'),
+ throws_error('The active device is not a tikz device')
+ )
+
+})
+
+test_that('XeTeX warns about unrecognized UTF8 characters',{
+
+ expect_that(
+ suppressMessages(getLatexStrWidth('α', engine = 'xetex')),
+ gives_warning('XeLaTeX was unable to calculate metrics')
+ )
+
+})
+
+test_that('tikzNode warns about more than one X coordinate value',{
+ tikz()
+ plot.new()
+ on.exit(dev.off())
+
+ expect_that(
+ tikzCoord(c(1,2), 2, 'test'),
+ gives_warning('More than one X coordinate specified')
+ )
+
+})
+
+test_that('tikzNode warns about more than one Y coordinate value',{
+ tikz()
+ plot.new()
+ on.exit(dev.off())
+
+ expect_that(
+ tikzCoord(1, c(1,2), 'test'),
+ gives_warning('More than one Y coordinate specified')
+ )
+
+})
+
+test_that('symbolicColors warns about wrong filename',{
+ tikz(symbolicColors = T, colorFileName = '/')
+ plot(1,2,axes=F, xlab='', ylab='')
+
+ expect_that(
+ dev.off(),
+ gives_warning('Color definition file could not be opened and is missing')
+ )
+})
+
+test_that('symbolicColors warns about too many colors',{
+ tikz(symbolicColors = T, maxSymbolicColors = 2)
+ plot.new()
+ points(0,0)
+ on.exit(dev.off())
+ expect_that(
+ points(0,1, col ="red"),
+ gives_warning('Too many colors used, reverting to non-symbolic storage')
+ )
+})
+
+test_that('check that maxSymbolicColors is nonnegative',{
+ expect_that(
+ tikz(symbolicColors = T, maxSymbolicColors = -1),
+ throws_error("maxSymbolicColors needs to be nonnegative")
+ )
+})
+
+}) # End reporter swap
diff --git a/tests/testthat/test_graphics.R b/tests/testthat/test_graphics.R
new file mode 100644
index 0000000..6893bd1
--- /dev/null
+++ b/tests/testthat/test_graphics.R
@@ -0,0 +1,717 @@
+# Switch to the detailed reporter implemented in helper_reporters.R
+with_reporter(MultiReporter$new(reporters = list(get_reporter(), GraphicsReporter$new())), {
+
+test_graphs <- list(
+ list(
+ short_name = 'hello_TeX',
+ description = 'Draw a circle and some simple text',
+ tags = c('base', 'text'),
+ graph_code = quote({
+ plot(1, axes=F, xlab='', ylab='')
+ text(1, 1.1, 'Hello TeX')
+ })
+ ),
+
+ list(
+ short_name = 'graph_box',
+ description = 'Draw a box around a graph',
+ tags = c('base'),
+ graph_code = quote({
+ plot(1, type='n', axes=F)
+ box()
+ })
+ ),
+
+ list(
+ short_name = 'text_color',
+ description = 'Draw colorized text',
+ tags = c('base', 'text'),
+ graph_code = quote({
+ plot(1, type='n')
+ text(0.8,0.8,'red',col='red')
+ text(1.2,1.2,'blue',col=rgb(0,0,1,0.5),cex=2)
+ })
+ ),
+
+ list(
+ short_name = 'plot_legend',
+ description = 'Draw a legend box',
+ tags = c('base'),
+ graph_code = quote({
+ plot(1,1, xlim=c(0,10), ylim=c(0,10))
+
+ legend( x='top', title='Legend Test', legend=c('Hello, world!'), inset=0.05 )
+
+ legend( 6, 4, title='Another Legend Test', legend=c('Test 1','Test 2'), pch=c(1,16))
+ })
+ ),
+
+ list(
+ short_name = 'pch_caracters',
+ description = 'Draw common plotting characters',
+ tags = c('base'),
+ graph_code = quote({
+ # Magic stuff taken from example(points)
+ n <- floor(sqrt(26))
+ npchIndex <- 0:(25)
+
+ ix <- npchIndex %/% n
+ iy <- 3 + (n-1) - npchIndex %% n
+
+ rx <- c(-1,1)/2 + range(ix)
+ ry <- c(-1,1)/2 + range(iy)
+
+ # Set up plot area
+ plot(rx, ry, type="n", axes=F, xlab='', ylab='', sub="Standard R plotting characters")
+
+ # Plot characters.
+ for( i in 1:26 ){
+
+ points(ix[i], iy[i], pch=i-1)
+ # Place text label so we know which character is being plotted.
+ text(ix[i]-0.3, iy[i], i-1 )
+
+ }
+ })
+ ),
+
+ list(
+ short_name = 'draw_circles',
+ description = 'Draw circles',
+ tags = c('base'),
+ graph_code = quote({
+ plot(-2:2, -2:2, type = "n", axes=F, xlab='', ylab='')
+ points(rnorm(10), rnorm(10), col = "red")
+ points(rnorm(10)/2, rnorm(10)/2, col = "blue")
+ })
+ ),
+
+ list(
+ short_name = 'draw_filled_circles',
+ description = 'Draw filled circles',
+ tags = c('base'),
+ graph_code = quote({
+ plot(-2:2, -2:2, type = "n", axes=F, xlab='', ylab='')
+ points(rnorm(10), rnorm(10), pch=21, col='blue', bg='forestgreen')
+ })
+ ),
+
+ list(
+ short_name = 'line_color',
+ description = 'Draw colored lines',
+ tags = c('base'),
+ graph_code = quote({
+ plot(c(0,1), c(0,1), type = "l", axes=F,
+ xlab='', ylab='', col='red3')
+ })
+ ),
+
+ list(
+ short_name = 'line_color_width',
+ description = 'Draw colored lines with changed line width',
+ tags = c('base'),
+ graph_options = list(
+ tikzLwdUnit = 72.27/96
+ ),
+ graph_code = quote({
+ plot(c(0,1), c(0,1), type = "l", axes=F,
+ xlab='', ylab='', col='red3')
+ })
+ ),
+
+ list(
+ short_name = "character_expansion",
+ description = "Test character expansion",
+ tags = c('base'),
+ graph_code = quote({
+ plot(1, axes=F, xlab='', ylab='', cex=10)
+ points(1, cex=.5)
+ })
+ ),
+
+ list(
+ short_name = 'filled_rectangle',
+ description = 'Test filled rectangles',
+ tags = c('base'),
+ graph_code = quote({
+ plot(-2:2, -2:2, type = "n", axes=F, xlab='', ylab='')
+ points(rnorm(10), rnorm(10), pch=22, col='red', bg='gold')
+ })
+ ),
+
+ list(
+ short_name = 'line_types',
+ description = 'Test line types',
+ tags = c('base'),
+ graph_code = quote({
+ plot(0, type='n', xlim=c(0,1), ylim=c(0,6),
+ axes=F, xlab='', ylab='')
+ for(i in 0:6)
+ lines(c(0, 1), c(i, i), lty=i)
+ })
+ ),
+
+ list(
+ short_name = 'line_weights',
+ description = 'Test line weights',
+ tags = c('base'),
+ graph_code = quote({
+ plot(0, type='n', xlim=c(0,1), ylim=c(0,6),
+ axes=F, xlab='', ylab='')
+ for(i in 0:6)
+ lines(c(0,1), c(i,i), lwd=i)
+ })
+ ),
+
+ list(
+ short_name = 'transparency',
+ description = 'Test transparency',
+ tags = c('base'),
+ graph_code = quote({
+ plot(-2:2, -2:2, type = "n", axes=F, xlab='', ylab='')
+ points(rnorm(50), rnorm(50), pch=21, bg=rainbow(50,alpha=.5), cex=10)
+ })
+ ),
+
+ list(
+ short_name = 'lots_of_elements',
+ description = 'Test of many points for file size',
+ tags = c('base'),
+ graph_code = quote({
+ plot(-2:2, -2:2, type = "n", axes=F, xlab='', ylab='')
+ points(rnorm(500), rnorm(500), pch=21, bg=rainbow(50,alpha=.5), cex=10)
+ })
+ ),
+
+ list(
+ short_name = 'contour_lines',
+ description = 'Test contour lines and associated text',
+ tags = c('base', 'text'),
+ graph_code = quote({
+ x <- -6:16
+ op <- par(mfrow = c(2, 2))
+ contour(outer(x, x), method = "edge")
+ z <- outer(x, sqrt(abs(x)), FUN = "/")
+ image(x, x, z)
+ contour(x, x, z, col = "pink", add = TRUE, method = "edge")
+ contour(x, x, z, ylim = c(1, 6), method = "simple", labcex = 1)
+ contour(x, x, z, ylim = c(-6, 6), nlev = 20, lty = 2, method = "simple")
+ par(op)
+ })
+ ),
+
+ list(
+ short_name = 'string_placement',
+ description = 'Test string placement and TeX symbol generation',
+ tags = c('base', 'text'),
+ graph_code = quote({
+ syms <-c('alpha','theta','tau','beta','vartheta','pi','upsilon',
+ 'gamma','gamma','varpi','phi','delta','kappa','rho','varphi',
+ 'epsilon','lambda','varrho','chi','varepsilon','mu','sigma',
+ 'psi','zeta','nu','varsigma','omega','eta','xi','Gamma',
+ 'Lambda','Sigma','Psi','Delta','Xi','Upsilon','Omega',
+ 'Theta','Pi','Phi')
+ x <- rnorm(length(syms))
+ y <- rnorm(length(syms))
+ plot(-2:2, -2:2, type = "n", axes=F, xlab='', ylab='')
+ points(x, y, pch=21, bg='black', cex=.5)
+ text(x,y,paste('\\Large$\\',syms,'$',sep=''))
+ })
+ ),
+
+ list(
+ short_name = 'text_alignment',
+ description = 'Test text alignment',
+ tags = c('base', 'text'),
+ graph_code = quote({
+ plot(1,1,type='n',xlab='',ylab='',axes=F)
+ abline(v=1)
+
+ #left justified
+ par(adj = 0)
+ text(1,1.1,'Left')
+
+ #Center Justified
+ par(adj = 0.5)
+ text(1,1,'Center')
+
+ #Right Justified
+ par(adj = 1)
+ text(1,0.9,'Right')
+ })
+ ),
+
+ list(
+ short_name = 'persp_3D',
+ description = 'Test of 3D graphs with persp',
+ tags = c('base', '3D'),
+ graph_code = quote({
+ x <- seq( -1.95, 1.95, length=30 )
+ y <- seq( -1.95, 1.95, length=35 )
+
+ z <- outer( x, y, function(a,b){ a*b^2 } )
+
+ nrz <- nrow(z)
+ ncz <- ncol(z)
+
+ jet.colors <- colorRampPalette( c("blue", "green") )
+
+ nbcol <- 100
+
+ color <- jet.colors(nbcol)
+
+ zfacet <- z[-1,-1] + z[-1,-ncz] + z[-nrz, -1] + z[-nrz, -ncz]
+ facetcol <- cut(zfacet, nbcol)
+
+ persp(x, y, z, col=color[facetcol], phi=30, theta=-30, ticktype='detailed')
+ })
+ ),
+
+ list(
+ short_name = 'base_annotation',
+ description = 'Annotation of base graphics',
+ tags = c('base', 'annotation'),
+ graph_options = list(
+ tikzLatexPackages = c(getOption('tikzLatexPackages'),
+ "\\usetikzlibrary{decorations.pathreplacing}",
+ "\\usetikzlibrary{positioning}",
+ "\\usetikzlibrary{shapes.arrows,shapes.symbols}"
+ )
+ ),
+ fuzz = 130,
+ graph_code = quote({
+
+ p <- rgamma (300 ,1)
+ outliers <- which( p > quantile(p,.75)+1.5*IQR(p) )
+ boxplot(p)
+
+ # Add named coordinates that other TikZ commands can hook onto
+ tikzCoord(1, min(p[outliers]), 'min outlier')
+ tikzCoord(1, max(p[outliers]), 'max outlier')
+
+ # Use tikzAnnotate to insert arbitrary code, such as drawing a fancy path
+ # between min outlier and max outlier.
+ tikzAnnotate(c("\\draw[very thick,red,",
+ # Turn the path into a brace.
+ 'decorate,decoration={brace,amplitude=12pt},',
+ # Shift it 1em to the left of the coordinates
+ 'transform canvas={xshift=-1em}]',
+ '(min outlier) --',
+ # Add a node with some text in the middle of the path
+ 'node[single arrow,anchor=tip,fill=white,draw=green,',
+ 'left=14pt,text width=0.70in,align=center]',
+ '{Holy Outliers Batman!}', '(max outlier);'))
+
+ # tikzNode can be used to place nodes with customized options and content
+ tikzNode(
+ opts='starburst,fill=green,draw=blue,very thick,right=of max outlier',
+ content='Wow!'
+ )
+
+ })
+ ),
+
+ list(
+ short_name = 'grid_annotation',
+ description = 'Annotation of grid graphics',
+ tags = c('grid', 'annotation'),
+ graph_options = list(
+ tikzLatexPackages = c(getOption('tikzLatexPackages'),
+ "\\usetikzlibrary{shapes.callouts}"
+ )
+ ),
+ fuzz = 745,
+ graph_code = quote({
+
+ library(grid)
+
+ pushViewport(plotViewport())
+ pushViewport(dataViewport(1:10, 1:10))
+
+ grid.rect()
+ grid.xaxis()
+ grid.yaxis()
+ grid.points(1:10, 1:10)
+
+ for ( i in seq(2,8,2) ){
+ grid.tikzNode(i,i,opts='ellipse callout,draw,anchor=pointer',content=i)
+ }
+
+ })
+ ),
+
+ list(
+ short_name = 'annotation_noflush',
+ description = 'Annotation prior to any graphics output',
+ tags = c('base', 'annotation'),
+ graph_code = quote({
+ plot.new()
+ plot.window(0:1, 0:1)
+ tikzCoord(0, 0, name="ll")
+ tikzCoord(1, 1, name="ur")
+ tikzAnnotate('\\draw (ll) rectangle (ur);');
+ })
+ ),
+
+ list(
+ short_name = 'ggplot2_test',
+ description = 'Test of ggplot2 graphics',
+ tags = c('ggplot2'),
+ graph_code = quote({
+ sink(tempfile())
+ suppressPackageStartupMessages(library(mgcv))
+ suppressPackageStartupMessages(library(ggplot2))
+ sink()
+ print(qplot(carat, price, data = diamonds, geom = "smooth",
+ colour = color))
+ })
+ ),
+
+ list(
+ short_name = 'ggplot2_superscripts',
+ description = 'Test of grid text alignment with ggplot2',
+ tags = c('ggplot2', 'text'),
+ graph_code = quote({
+ sink(tempfile())
+ suppressPackageStartupMessages(library(ggplot2))
+ sink()
+
+ soilSample <- structure(list(`Grain Diameter` = c(8, 5.6, 4, 2.8, 2, 1, 0.5, 0.355, 0.25),
+ `Percent Finer` = c(0.951603145795523, 0.945553539019964,
+ 0.907239362774753, 0.86771526517443, 0.812865497076023, 0.642064932446058,
+ 0.460375075620085, 0.227465214761041, 0.0389191369227667)),
+ .Names = c("Grain Diameter", "Percent Finer"), row.names = c(NA, 9L),
+ class = "data.frame")
+
+ # R 2.12.x and 2.13.x have to test with ggplot2 v0.8.9 which is very
+ # different from 0.9.0.
+ #
+ # FIXME: Remove this once we drop support for 2.13.x
+ if( exists('scale_y_probit') ){
+ # We are using a ggplot2 version that is earlier than 0.9.0
+ testPlot <- qplot( `Grain Diameter`, `Percent Finer`, data = soilSample) +
+ scale_x_log10() + scale_y_probit() + theme_bw()
+ } else {
+ sink(tempfile())
+ suppressPackageStartupMessages(library(scales))
+ sink()
+ testPlot <- qplot(log10(`Grain Diameter`), `Percent Finer`, data = soilSample) +
+ scale_x_continuous(labels = math_format(10^.x)) +
+ scale_y_continuous(trans = 'probit', breaks = seq(0.2, 0.8, 0.2)) +
+ theme_bw()
+ }
+
+ print( testPlot )
+ })
+ ),
+
+ list(
+ short_name = 'polypath',
+ description = 'Test polypath support',
+ tags = c('base', 'polypath'),
+ graph_code = quote({
+ # From example(polypath)
+ plotPath <- function(x, y, col="grey", rule="winding") {
+ plot.new()
+ plot.window(range(x, na.rm=TRUE), range(y, na.rm=TRUE))
+ polypath(x, y, col=col, rule=rule)
+ if (!is.na(col))
+ mtext(paste("Rule:", rule), side=1, line=0)
+ }
+
+ plotRules <- function(x, y, title) {
+ plotPath(x, y)
+ plotPath(x, y, rule="evenodd")
+ mtext(title, side=3, line=0)
+ plotPath(x, y, col=NA)
+ }
+
+ op <- par(mfrow=c(5, 3), mar=c(2, 1, 1, 1))
+
+ plotRules(c(.1, .1, .9, .9, NA, .2, .2, .8, .8),
+ c(.1, .9, .9, .1, NA, .2, .8, .8, .2),
+ title="Nested rectangles, both clockwise")
+ plotRules(x=c(.1, .1, .9, .9, NA, .2, .8, .8, .2),
+ y=c(.1, .9, .9, .1, NA, .2, .2, .8, .8),
+ title="Nested rectangles, outer clockwise, inner anti-clockwise")
+ plotRules(x=c(.1, .1, .4, .4, NA, .6, .9, .9, .6),
+ y=c(.1, .4, .4, .1, NA, .6, .6, .9, .9),
+ title="Disjoint rectangles")
+ plotRules(x=c(.1, .1, .6, .6, NA, .4, .4, .9, .9),
+ y=c(.1, .6, .6, .1, NA, .4, .9, .9, .4),
+ title="Overlapping rectangles, both clockwise")
+ plotRules(x=c(.1, .1, .6, .6, NA, .4, .9, .9, .4),
+ y=c(.1, .6, .6, .1, NA, .4, .4, .9, .9),
+ title="Overlapping rectangles, one clockwise, other anti-clockwise")
+
+ par(op)
+
+ })
+ ),
+
+ list(
+ short_name = 'base_raster',
+ description = 'Test raster support in base graphics',
+ tags = c('base', 'raster', 'reflection'),
+ fuzz = 642,
+ graph_code = quote({
+
+ plot(c(100, 250), c(300, 450), type = "n", xlab="", ylab="")
+ image <- as.raster(matrix(rep(c(rep(0:1, 4), rep(1:0, 4)), each = 3), ncol=6, nrow=4))
+ rasterImage(image, 100, 300, 150, 350, interpolate=FALSE)
+ rasterImage(image, 100, 400, 150, 450)
+ rasterImage(image, 200, 300, 200 + xinch(.5), 300 + yinch(.3),
+ interpolate=FALSE)
+ rasterImage(image, 200, 400, 250, 450, angle=15,
+ interpolate=FALSE)
+ rasterImage(image, 175 + xinch(.5), 350, 175, 350 + yinch(.3), angle=-30,
+ interpolate=FALSE)
+ rasterImage(image, 200 + xinch(.5), 350 + yinch(.3), 200, 350, angle=-45,
+ interpolate=FALSE)
+ rasterImage(image, 225, 350 + yinch(.3), 225 + xinch(.5), 350, angle=-60,
+ interpolate=FALSE)
+
+ })
+ ),
+
+ list(
+ short_name = 'raster_reflection',
+ description = 'Test raster handling in graphics with reflected axes',
+ tags = c('base', 'raster', 'reflection'),
+ graph_code = quote({
+
+ par(mfrow = c(2,2))
+ image(volcano, useRaster = TRUE)
+ image(volcano, xlim = c(1,0), useRaster = TRUE)
+ image(volcano, ylim = c(1,0), useRaster = TRUE)
+ image(volcano, xlim = c(1,0), ylim = c(1,0), useRaster = TRUE)
+
+ })
+ ),
+
+ list(
+ short_name = 'grid_raster',
+ description = 'Test raster support in grid graphics',
+ tags = c('grid', 'raster'),
+ graph_code = quote({
+
+ suppressPackageStartupMessages(library(grid))
+ suppressPackageStartupMessages(library(lattice))
+
+ plt <- levelplot(volcano, panel = panel.levelplot.raster,
+ col.regions = topo.colors, cuts = 30, interpolate = TRUE)
+
+ print(plt)
+
+ })
+ ),
+
+ list(
+ short_name = 'base_raster_noresample',
+ description = 'Test noresampling raster support in base graphics',
+ tags = c('base', 'raster'),
+ fuzz = 1400,
+ graph_code = quote({
+ plot.new()
+ suppressWarnings(rasterImage(as.raster(matrix(seq(0,1,len=9),3)),0,0,1,1,interpolate=TRUE))
+ })
+ ),
+
+ list(
+ short_name = 'base_symbolic_simple',
+ description = 'Test symbolic colors for a simple image',
+ tags = c('base', 'symbolic'),
+ graph_options = list(
+ tikzSymbolicColors=TRUE, tikzMaxSymbolicColors=3),
+ graph_code = quote({
+ plot.new()
+ points(0,0)
+ points(0,1, col="red")
+ suppressWarnings(points(1,1, col="green"))
+ points(1,0, col="gray50")
+ points(0.5,0.5, col="#F3346A")
+ })
+ ),
+ # New pdfLaTeX tests go here
+ #list(
+ # short_name = 'something_suitable_as_a_filename',
+ # description = 'Longer description of what the test does',
+ # tags = c('plot', 'tags'),
+ # graph_options = list(optional stuff to pass to options() during this test)
+ # graph_code = quote({
+ #
+ # })
+ #)
+
+ ### XeLaTeX Tests
+ list(
+ short_name = 'utf8_characters',
+ description = 'Test of UTF8 characters',
+ tags = c('base', 'xetex', 'utf8'),
+ engine = 'xetex',
+ graph_code = quote({
+ n <- 8
+ chars <- intToUtf8(seq(187,,1,n*n),multiple=T)
+
+ plot(1:n,type='n',xlab='',ylab='',axes=FALSE, main="UTF-8 Characters")
+ text(rep(1:n, n), rep(1:n, rep(n, n)), chars)
+ })
+ ),
+
+
+ list(
+ short_name = 'xetex_variants',
+ description = 'Test of XeLaTeX font variants',
+ tags = c('xetex', 'utf8'),
+ engine = 'xetex',
+ # Only OS X is likely to have the required fonts installed
+ skip_if = function(){Sys.info()['sysname'] != 'Darwin'},
+ graph_options = list(
+ tikzXelatexPackages = c(
+ "\\usepackage{fontspec}",
+ "\\usepackage[colorlinks, breaklinks, pdftitle={The Beauty of LaTeX},pdfauthor={Taraborelli, Dario}]{hyperref}",
+ "\\usepackage{tikz}",
+ "\\usepackage{color}",
+ "\\definecolor{Gray}{rgb}{.7,.7,.7}",
+ "\\definecolor{lightblue}{rgb}{.2,.5,1}",
+ "\\definecolor{myred}{rgb}{1,0,0}",
+ "\\newcommand{\\red}[1]{\\color{myred} #1}",
+ "\\newcommand{\\reda}[1]{\\color{myred}\\fontspec[Variant=2]{Zapfino}#1}",
+ "\\newcommand{\\redb}[1]{\\color{myred}\\fontspec[Variant=3]{Zapfino}#1}",
+ "\\newcommand{\\redc}[1]{\\color{myred}\\fontspec[Variant=4]{Zapfino}#1}",
+ "\\newcommand{\\redd}[1]{\\color{myred}\\fontspec[Variant=5]{Zapfino}#1}",
+ "\\newcommand{\\rede}[1]{\\color{myred}\\fontspec[Variant=6]{Zapfino}#1}",
+ "\\newcommand{\\redf}[1]{\\color{myred}\\fontspec[Variant=7]{Zapfino}#1}",
+ "\\newcommand{\\redg}[1]{\\color{myred}\\fontspec[Variant=8]{Zapfino}#1}",
+ "\\newcommand{\\lbl}[1]{\\color{lightblue} #1}",
+ "\\newcommand{\\lbla}[1]{\\color{lightblue}\\fontspec[Variant=2]{Zapfino}#1}",
+ "\\newcommand{\\lblb}[1]{\\color{lightblue}\\fontspec[Variant=3]{Zapfino}#1}",
+ "\\newcommand{\\lblc}[1]{\\color{lightblue}\\fontspec[Variant=4]{Zapfino}#1}",
+ "\\newcommand{\\lbld}[1]{\\color{lightblue}\\fontspec[Variant=5]{Zapfino}#1}",
+ "\\newcommand{\\lble}[1]{\\color{lightblue}\\fontspec[Variant=6]{Zapfino}#1}",
+ "\\newcommand{\\lblf}[1]{\\color{lightblue}\\fontspec[Variant=7]{Zapfino}#1}",
+ "\\newcommand{\\lblg}[1]{\\color{lightblue}\\fontspec[Variant=8]{Zapfino}#1}",
+ "\\newcommand{\\old}[1]{",
+ "\\fontspec[Ligatures={Common, Rare},Variant=1,Swashes={LineInitial, LineFinal}]{Zapfino}",
+ "\\fontsize{25pt}{30pt}\\selectfont #1}%",
+ "\\newcommand{\\smallprint}[1]{\\fontspec{Hoefler Text}\\fontsize{10pt}{13pt}\\color{Gray}\\selectfont #1}%\n",
+ "\\usepackage[active,tightpage,xetex]{preview}",
+ "\\PreviewEnvironment{pgfpicture}",
+ "\\setlength\\PreviewBorder{0pt}"
+ )),
+ graph_code = quote({
+
+ label <- c(
+ "\\noindent{\\red d}roo{\\lbl g}",
+ "\\noindent{\\reda d}roo{\\lbla g}",
+ "\\noindent{\\redb d}roo{\\lblb g}",
+ "\\noindent{\\redf d}roo{\\lblf g}\\\\[.3cm]",
+ "\\noindent{\\redc d}roo{\\lblc g}",
+ "\\noindent{\\redd d}roo{\\lbld g}",
+ "\\noindent{\\rede d}roo{\\lble g}",
+ "\\noindent{\\redg d}roo{\\lblg g}\\\\[.2cm]"
+ )
+ title <- c(
+ "\\smallprint{D. Taraborelli (2008), \\href{http://nitens.org/taraborelli/latex}{The Beauty of \\LaTeX}}",
+ "\\smallprint{\\\\\\emph{Some rights reserved}. \\href{http://creativecommons.org/licenses/by-sa/3.0/}{\\textsc{cc-by-sa}}}"
+ )
+
+ lim <- 0:(length(label)+1)
+ plot(lim,lim,cex=0,pch='.',xlab = title[2],ylab='', main = title[1])
+ for(i in 1:length(label))
+ text(i,i,label[i])
+ })
+ ),
+
+ ### LuaLaTeX Tests
+ list(
+ short_name = 'luatex_utf8_characters',
+ description = 'Test of UTF8 characters w/ LuaTeX',
+ tags = c('base', 'luatex', 'utf8'),
+ engine = 'luatex',
+ # Travis CI runs Ubuntu Precise with a fontspec package that doesn't accept
+ # LuaLaTeX yet
+ skip_if = function(){ Sys.getenv("TRAVIS") != "" },
+ graph_code = quote({
+ n <- 8
+ chars <- intToUtf8(seq(187,,1,n*n),multiple=T)
+
+ plot(1:n,type='n',xlab='',ylab='',axes=FALSE, main="UTF-8 Characters")
+ text(rep(1:n, n), rep(1:n, rep(n, n)), chars)
+ })
+ ),
+
+ # New UTF8/XeLaTeX/LuaLatex tests go here
+ #list(
+ # short_name = 'something_suitable_as_a_filename',
+ # description = 'Longer description of what the test does',
+ # tags = c('plot', 'tags'),
+ # uses_xetex = TRUE,
+ # graph_options = list(optional stuff to pass to options() during this test)
+ # graph_code = quote({
+ #
+ # })
+ #)
+
+ NULL
+
+)
+
+test_graphs <- test_graphs[!vapply(test_graphs, is.null, logical(1L))]
+
+if ( length(tags_to_run) ) {
+ test_graphs <- Filter(
+ function(graph){ any(graph$tags %in% tags_to_run) },
+ test_graphs )
+}
+
+
+run_test <- function(graph){ do.call(do_graphics_test, graph) }
+graphs_produced <- Filter(run_test, test_graphs)
+
+context('Graph test cleanup')
+
+test_that('All graphics devices closed',{
+
+ expect_that(length(dev.list()), equals(0))
+
+})
+
+}) # End reporter swap
+
+
+message('\nFinished generating TikZ test graphs.')
+message('PDF files are in:\n\t', test_output_dir)
+message('\nTeX sources and log files are in:\n\t', test_work_dir)
+
+if ( !is.null(gs_cmd) ) {
+ # Combine all test PDFs into one big file for easy viewing
+ graph_files <- Map(function(graph) {
+ file.path(test_output_dir, str_c(graph$short_name, '.pdf'))
+ }, graphs_produced)
+ test_output <- file.path(test_output_dir, 'test_results.pdf')
+
+ silence <- system(paste(shQuote(gs_cmd), '-dNOPAUSE', '-sDEVICE=pdfwrite',
+ str_c('-sOUTPUTFILE=', test_output),
+ '-dBATCH', paste(shQuote(graph_files), collapse = ' ')),
+ intern = TRUE, ignore.stderr = TRUE)
+
+ message('\nAll test outputs combined into:\n\t', test_output)
+}
+
+
+if ( !is.null(compare_cmd) && !is.null(convert_cmd) ) {
+ # Combine all visual diffs into one big PDF file for easy viewing
+ graph_files <- Map(function(graph) {
+ file.path(test_work_dir, str_c(graph$short_name, '_diff.png'))
+ }, graphs_produced)
+ diff_output <- file.path(test_output_dir, 'test_diffs.pdf')
+
+ silence <- system(paste(shQuote(convert_cmd),
+ paste(shQuote(graph_files), collapse = ' '),
+ diff_output),
+ intern = TRUE, ignore.stderr = TRUE)
+
+ message('\nResults of all visual diffs combined into:\n\t', diff_output)
+
+}
diff --git a/tests/testthat/test_metrics_dict.R b/tests/testthat/test_metrics_dict.R
new file mode 100644
index 0000000..72e5462
--- /dev/null
+++ b/tests/testthat/test_metrics_dict.R
@@ -0,0 +1,87 @@
+# Switch to the detailed reporter implemented in helper_reporters.R
+with_reporter(MultiReporter$new(reporters = list(get_reporter(), DetailedReporter$new())), {
+
+context('Metrics dictionary')
+
+test_that('Temporary metrics dictionary is created, but only once', {
+ expect_equal(getOption('tikzMetricsDictionary'), NULL)
+
+ rm(list = ls(envir = .tikzInternal), envir = .tikzInternal)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Creating"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ expect_true(file.exists(.tikzInternal[["db_file"]]))
+})
+
+test_that('Silent creation of temporary metrics dictionary', {
+ expect_equal(getOption('tikzMetricsDictionary'), NULL)
+
+ rm(list = ls(envir = .tikzInternal), envir = .tikzInternal)
+ expect_that(checkDictionaryStatus(verbose = FALSE), not(shows_message()))
+ expect_that(checkDictionaryStatus(verbose = FALSE), not(shows_message()))
+ expect_true(file.exists(.tikzInternal[["db_file"]]))
+})
+
+test_that('Switching metrics dictionary', {
+ expect_equal(getOption('tikzMetricsDictionary'), NULL)
+
+ tempA <- file.path(getwd(), ".tikzTempA")
+ tempB <- file.path(getwd(), ".tikzTempB")
+
+ tryCatch(
+ {
+ options(tikzMetricsDictionary=tempA)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Creating"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ options(tikzMetricsDictionary=tempB)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Creating"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ options(tikzMetricsDictionary=tempA)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Using"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ options(tikzMetricsDictionary=tempB)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Using"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ options(tikzMetricsDictionary=tempA)
+ expect_that(checkDictionaryStatus(verbose = FALSE), not(shows_message()))
+ expect_that(checkDictionaryStatus(verbose = FALSE), not(shows_message()))
+ options(tikzMetricsDictionary=tempB)
+ expect_that(checkDictionaryStatus(verbose = FALSE), not(shows_message()))
+ expect_that(checkDictionaryStatus(verbose = FALSE), not(shows_message()))
+ },
+ finally = {
+ options(tikzMetricsDictionary=NULL)
+ unlink(tempA, recursive = TRUE)
+ unlink(tempB, recursive = TRUE)
+ }
+ )
+})
+
+test_that('Turning custom metrics dictionary on and off', {
+ expect_equal(getOption('tikzMetricsDictionary'), NULL)
+
+ temp <- file.path(getwd(), ".tikzTemp")
+
+ tryCatch(
+ {
+ options(tikzMetricsDictionary=temp)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Creating"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ options(tikzMetricsDictionary=NULL)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Creating"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ options(tikzMetricsDictionary=temp)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Using"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ options(tikzMetricsDictionary=NULL)
+ expect_that(checkDictionaryStatus(verbose = TRUE), shows_message("Creating"))
+ expect_that(checkDictionaryStatus(verbose = TRUE), not(shows_message()))
+ },
+ finally = {
+ options(tikzMetricsDictionary=NULL)
+ unlink(temp, recursive = TRUE)
+ }
+ )
+})
+
+}) # End reporter swap
+
diff --git a/tests/testthat/test_pointsize.R b/tests/testthat/test_pointsize.R
new file mode 100644
index 0000000..784d888
--- /dev/null
+++ b/tests/testthat/test_pointsize.R
@@ -0,0 +1,18 @@
+# Switch to the detailed reporter implemented in helper_reporters.R
+with_reporter(MultiReporter$new(reporters = list(get_reporter(), DetailedReporter$new())), {
+
+context('Querying of pointsize')
+
+test_that('Pointsize is extracted correctly',{
+ expect_equal(getDocumentPointsize('\\documentclass[draft,12pt]{article}'), 12)
+ expect_equal(getDocumentPointsize('\\documentclass[11pt,draft]{article}'), 11)
+ expect_equal(getDocumentPointsize('\\documentclass[ 10pt ,draft]{article}'), 10)
+ expect_equal(getDocumentPointsize('\\documentclass[10pt]{article}'), 10)
+ expect_true(is.na(getDocumentPointsize('\\documentclass{article}')))
+ expect_true(is.na(getDocumentPointsize('\\documentclass{report}')))
+ expect_equal(getDocumentPointsize('\\documentclass[12pt]{report}\n'), 12)
+ expect_true(is.na(getDocumentPointsize('\\documentclass{report}\n')))
+ expect_equal(getDocumentPointsize('\\PassOptionToPackage{x}{y}\n\\documentclass[11pt]{report}\n'), 11)
+})
+
+}) # End reporter swap
diff --git a/tests/unit_tests.R b/tests/unit_tests.R
new file mode 100755
index 0000000..1705b4a
--- /dev/null
+++ b/tests/unit_tests.R
@@ -0,0 +1,25 @@
+#!/usr/bin/env Rscript
+if (nchar(Sys.getenv('R_TESTS')) == 0) {
+ # Protects against R CMD check
+ library(testthat)
+ library(methods)
+ FailureReporter <- setRefClass(
+ "FailureReporter", contains = "Reporter",
+ methods = list(
+ start_reporter = function() {},
+
+ add_result = function(result) {
+ if (result$skipped) {
+ return()
+ }
+ if (result$passed) {
+ return()
+ }
+
+ failed <<- TRUE
+ }
+ )
+ )
+
+ test_check('tikzDevice', reporter = FailureReporter$new())
+} # if (nchar(Sys.getenv('R_TESTS')) == 0) {
diff --git a/vignettes/agufull04.bst b/vignettes/agufull04.bst
new file mode 100644
index 0000000..d56c8cc
--- /dev/null
+++ b/vignettes/agufull04.bst
@@ -0,0 +1,1815 @@
+%%
+%% This is file `agufull04.bst',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% merlin.mbs (with options: `head,ay,nat,seq-key,nm-rev1,jnrlst,lab,lab-it,keyxyr,blkyear,dt-beg,yr-par,xmth,note-yr,thtit-a,trnum-it,vol-it,volp-com,pgsep-c,num-xser,ser-vol,ser-ed,pg-bk,pg-pre,pre-edn,agu-doi,doi,edpar,bkedcap,edby,blk-com,pp,ed,abr,ednx,xedn,jabr,and-com,em-it,nfss,{}')
+%% physjour.mbs (with options: `ay,nat,seq-key,nm-rev1,jnrlst,lab,lab-it,keyxyr,blkyear,dt-beg,yr-par,xmth,note-yr,thtit-a,trnum-it,vol-it,volp-com,pgsep-c,num-xser,ser-vol,ser-ed,pg-bk,pg-pre,pre-edn,agu-doi,doi,edpar,bkedcap,edby,blk-com,pp,ed,abr,ednx,xedn,jabr,and-com,em-it,nfss,{}')
+%% geojour.mbs (with options: `ay,nat,seq-key,nm-rev1,jnrlst,lab,lab-it,keyxyr,blkyear,dt-beg,yr-par,xmth,note-yr,thtit-a,trnum-it,vol-it,volp-com,pgsep-c,num-xser,ser-vol,ser-ed,pg-bk,pg-pre,pre-edn,agu-doi,doi,edpar,bkedcap,edby,blk-com,pp,ed,abr,ednx,xedn,jabr,and-com,em-it,nfss,{}')
+%% photjour.mbs (with options: `ay,nat,seq-key,nm-rev1,jnrlst,lab,lab-it,keyxyr,blkyear,dt-beg,yr-par,xmth,note-yr,thtit-a,trnum-it,vol-it,volp-com,pgsep-c,num-xser,ser-vol,ser-ed,pg-bk,pg-pre,pre-edn,agu-doi,doi,edpar,bkedcap,edby,blk-com,pp,ed,abr,ednx,xedn,jabr,and-com,em-it,nfss,{}')
+%% merlin.mbs (with options: `tail,ay,nat,seq-key,nm-rev1,jnrlst,lab,lab-it,keyxyr,blkyear,dt-beg,yr-par,xmth,note-yr,thtit-a,trnum-it,vol-it,volp-com,pgsep-c,num-xser,ser-vol,ser-ed,pg-bk,pg-pre,pre-edn,agu-doi,doi,edpar,bkedcap,edby,blk-com,pp,ed,abr,ednx,xedn,jabr,and-com,em-it,nfss,{}')
+%% ----------------------------------------
+%% *** For journals of the American Geophysical Union ***
+%% *** NOTE: this version does not limit the number of authors in ref list.
+%% *** Use agu.bst to limit authors to maximum 9.
+%% ***
+%% ----------------------------------------
+%% *** Version 3.0 from 2004/02/06
+%% *** Changed date format for AGU journals
+%% *** The date now appears in parentheses after authors
+%% ***
+%% *** Version 2.2 from 2003/06/26
+%% *** (with bug fix from 2003/08/19)
+%% *** Includes new fields eid and doi
+%% *** The eid is what the AGU calls "citation number"
+%% *** and doi is the DOI number; both of these are
+%% *** used as substitution for page number
+%% *** The issue number is now also included as
+%% *** 84(3) for vol. 84, nr. 3
+%% ***
+%% *** Version 2.1d from 1999/05/20
+%% *** Book editors done right as P. James (Ed.),
+%% *** Missing italics with some authors fixed
+%% ***
+%% *** Version 2.1c from 1999/02/11
+%% *** This version does not crash older BibTeX installations with
+%% *** more than 3000 wiz-functions
+%% ***
+%% *** Version 2.1b from 1997/11/18
+%% *** (page numbers over 9999 are broken with commas, as 12,345)
+%% ***
+%% *** Version 2.1a from 1997/05/26
+%% *** (contains improvements from copy editor comments,
+%% *** notes added with first word lowercase (bug in 2.1 fixed)
+%% *** and journal `number' never output
+%% *** abbreviation for grl corrected)
+%% ***
+%%
+%% Copyright 1994-2004 Patrick W Daly
+ % ===============================================================
+ % IMPORTANT NOTICE:
+ % This bibliographic style (bst) file has been generated from one or
+ % more master bibliographic style (mbs) files, listed above.
+ %
+ % This generated file can be redistributed and/or modified under the terms
+ % of the LaTeX Project Public License Distributed from CTAN
+ % archives in directory macros/latex/base/lppl.txt; either
+ % version 1 of the License, or any later version.
+ % ===============================================================
+ % Name and version information of the main mbs file:
+ % \ProvidesFile{merlin.mbs}[2004/02/09 4.13 (PWD, AO, DPC)]
+ % For use with BibTeX version 0.99a or later
+ %-------------------------------------------------------------------
+ % This bibliography style file is intended for texts in ENGLISH
+ % This is an author-year citation style bibliography. As such, it is
+ % non-standard LaTeX, and requires a special package file to function properly.
+ % Such a package is natbib.sty by Patrick W. Daly
+ % The form of the \bibitem entries is
+ % \bibitem[Jones et al.(1990)]{key}...
+ % \bibitem[Jones et al.(1990)Jones, Baker, and Smith]{key}...
+ % The essential feature is that the label (the part in brackets) consists
+ % of the author names, as they should appear in the citation, with the year
+ % in parentheses following. There must be no space before the opening
+ % parenthesis!
+ % With natbib v5.3, a full list of authors may also follow the year.
+ % In natbib.sty, it is possible to define the type of enclosures that is
+ % really wanted (brackets or parentheses), but in either case, there must
+ % be parentheses in the label.
+ % The \cite command functions as follows:
+ % \citet{key} ==>> Jones et al. (1990)
+ % \citet*{key} ==>> Jones, Baker, and Smith (1990)
+ % \citep{key} ==>> (Jones et al., 1990)
+ % \citep*{key} ==>> (Jones, Baker, and Smith, 1990)
+ % \citep[chap. 2]{key} ==>> (Jones et al., 1990, chap. 2)
+ % \citep[e.g.][]{key} ==>> (e.g. Jones et al., 1990)
+ % \citep[e.g.][p. 32]{key} ==>> (e.g. Jones et al., p. 32)
+ % \citeauthor{key} ==>> Jones et al.
+ % \citeauthor*{key} ==>> Jones, Baker, and Smith
+ % \citeyear{key} ==>> 1990
+ %---------------------------------------------------------------------
+
+ENTRY
+ { address
+ author
+ booktitle
+ chapter
+ doi
+ edition
+ editor
+ eid
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ volume
+ year
+ }
+ {}
+ { label extra.label sort.label short.list }
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+STRINGS { s t}
+FUNCTION {output.nonnull}
+{ 's :=
+ output.state mid.sentence =
+ { ", " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull
+ if$
+}
+FUNCTION {fin.entry}
+{ add.period$
+ write$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+ 'skip$
+ { after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+FUNCTION {add.blank}
+{ " " * before.all 'output.state :=
+}
+
+FUNCTION {date.block}
+{
+ skip$
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+FUNCTION {emphasize}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "\textit{" swap$ * "}" * }
+ if$
+}
+FUNCTION {cite.name.font}
+{ emphasize }
+FUNCTION {tie.or.space.prefix}
+{ duplicate$ text.length$ #3 <
+ { "~" }
+ { " " }
+ if$
+ swap$
+}
+
+FUNCTION {capitalize}
+{ "u" change.case$ "t" change.case$ }
+
+FUNCTION {space.word}
+{ " " swap$ * " " * }
+ % Here are the language-specific definitions for explicit words.
+ % Each function has a name bbl.xxx where xxx is the English word.
+ % The language selected here is ENGLISH
+FUNCTION {bbl.and}
+{ "and"}
+
+FUNCTION {bbl.etal}
+{ "et~al." }
+
+FUNCTION {bbl.editors}
+{ "eds." }
+
+FUNCTION {bbl.editor}
+{ "ed." }
+
+FUNCTION {bbl.edby}
+{ "edited by" }
+
+FUNCTION {bbl.edition}
+{ "ed." }
+
+FUNCTION {bbl.volume}
+{ "vol." }
+
+FUNCTION {bbl.of}
+{ "of" }
+
+FUNCTION {bbl.number}
+{ "no." }
+
+FUNCTION {bbl.nr}
+{ "no." }
+
+FUNCTION {bbl.in}
+{ "in" }
+
+FUNCTION {bbl.pages}
+{ "pp." }
+
+FUNCTION {bbl.page}
+{ "p." }
+
+FUNCTION {bbl.chapter}
+{ "chap." }
+
+FUNCTION {bbl.techrep}
+{ "Tech. Rep." }
+
+FUNCTION {bbl.mthesis}
+{ "Master's thesis" }
+
+FUNCTION {bbl.phdthesis}
+{ "Ph.D. thesis" }
+
+MACRO {jan} {"Jan."}
+
+MACRO {feb} {"Feb."}
+
+MACRO {mar} {"Mar."}
+
+MACRO {apr} {"Apr."}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"Jun."}
+
+MACRO {jul} {"Jul."}
+
+MACRO {aug} {"Aug."}
+
+MACRO {sep} {"Sep."}
+
+MACRO {oct} {"Oct."}
+
+MACRO {nov} {"Nov."}
+
+MACRO {dec} {"Dec."}
+
+ %-------------------------------------------------------------------
+ % Begin module:
+ % \ProvidesFile{physjour.mbs}[2002/01/14 2.2 (PWD)]
+MACRO {aa}{"Astron. \& Astrophys."}
+MACRO {aasup}{"Astron. \& Astrophys. Suppl. Ser."}
+MACRO {aj} {"Astron. J."}
+MACRO {aph} {"Acta Phys."}
+MACRO {advp} {"Adv. Phys."}
+MACRO {ajp} {"Amer. J. Phys."}
+MACRO {ajm} {"Amer. J. Math."}
+MACRO {amsci} {"Amer. Sci."}
+MACRO {anofd} {"Ann. Fluid Dyn."}
+MACRO {am} {"Ann. Math."}
+MACRO {ap} {"Ann. Phys. (NY)"}
+MACRO {adp} {"Ann. Phys. (Leipzig)"}
+MACRO {ao} {"Appl. Opt."}
+MACRO {apl} {"Appl. Phys. Lett."}
+MACRO {app} {"Astroparticle Phys."}
+MACRO {apj} {"Astrophys. J."}
+MACRO {apjsup} {"Astrophys. J. Suppl."}
+MACRO {apss} {"Astrophys. Space Sci."}
+MACRO {araa} {"Ann. Rev. Astron. Astrophys."}
+MACRO {baas} {"Bull. Amer. Astron. Soc."}
+MACRO {baps} {"Bull. Amer. Phys. Soc."}
+MACRO {cmp} {"Comm. Math. Phys."}
+MACRO {cpam} {"Commun. Pure Appl. Math."}
+MACRO {cppcf} {"Comm. Plasma Phys. \& Controlled Fusion"}
+MACRO {cpc} {"Comp. Phys. Comm."}
+MACRO {cqg} {"Class. Quant. Grav."}
+MACRO {cra} {"C. R. Acad. Sci. A"}
+MACRO {fed} {"Fusion Eng. \& Design"}
+MACRO {ft} {"Fusion Tech."}
+MACRO {grg} {"Gen. Relativ. Gravit."}
+MACRO {ieeens} {"IEEE Trans. Nucl. Sci."}
+MACRO {ieeeps} {"IEEE Trans. Plasma Sci."}
+MACRO {ijimw} {"Interntl. J. Infrared \& Millimeter Waves"}
+MACRO {ip} {"Infrared Phys."}
+MACRO {irp} {"Infrared Phys."}
+MACRO {jap} {"J. Appl. Phys."}
+MACRO {jasa} {"J. Acoust. Soc. America"}
+MACRO {jcp} {"J. Comp. Phys."}
+MACRO {jetp} {"Sov. Phys.--JETP"}
+MACRO {jfe} {"J. Fusion Energy"}
+MACRO {jfm} {"J. Fluid Mech."}
+MACRO {jmp} {"J. Math. Phys."}
+MACRO {jne} {"J. Nucl. Energy"}
+MACRO {jnec} {"J. Nucl. Energy, C: Plasma Phys., Accelerators, Thermonucl. Res."}
+MACRO {jnm} {"J. Nucl. Mat."}
+MACRO {jpc} {"J. Phys. Chem."}
+MACRO {jpp} {"J. Plasma Phys."}
+MACRO {jpsj} {"J. Phys. Soc. Japan"}
+MACRO {jsi} {"J. Sci. Instrum."}
+MACRO {jvst} {"J. Vac. Sci. \& Tech."}
+MACRO {nat} {"Nature"}
+MACRO {nature} {"Nature"}
+MACRO {nedf} {"Nucl. Eng. \& Design/Fusion"}
+MACRO {nf} {"Nucl. Fusion"}
+MACRO {nim} {"Nucl. Inst. \& Meth."}
+MACRO {nimpr} {"Nucl. Inst. \& Meth. in Phys. Res."}
+MACRO {np} {"Nucl. Phys."}
+MACRO {npb} {"Nucl. Phys. B"}
+MACRO {nt/f} {"Nucl. Tech./Fusion"}
+MACRO {npbpc} {"Nucl. Phys. B (Proc. Suppl.)"}
+MACRO {inc} {"Nuovo Cimento"}
+MACRO {nc} {"Nuovo Cimento"}
+MACRO {pf} {"Phys. Fluids"}
+MACRO {pfa} {"Phys. Fluids A: Fluid Dyn."}
+MACRO {pfb} {"Phys. Fluids B: Plasma Phys."}
+MACRO {pl} {"Phys. Lett."}
+MACRO {pla} {"Phys. Lett. A"}
+MACRO {plb} {"Phys. Lett. B"}
+MACRO {prep} {"Phys. Rep."}
+MACRO {pnas} {"Proc. Nat. Acad. Sci. USA"}
+MACRO {pp} {"Phys. Plasmas"}
+MACRO {ppcf} {"Plasma Phys. \& Controlled Fusion"}
+MACRO {phitrsl} {"Philos. Trans. Roy. Soc. London"}
+MACRO {prl} {"Phys. Rev. Lett."}
+MACRO {pr} {"Phys. Rev."}
+MACRO {physrev} {"Phys. Rev."}
+MACRO {pra} {"Phys. Rev. A"}
+MACRO {prb} {"Phys. Rev. B"}
+MACRO {prc} {"Phys. Rev. C"}
+MACRO {prd} {"Phys. Rev. D"}
+MACRO {pre} {"Phys. Rev. E"}
+MACRO {ps} {"Phys. Scripta"}
+MACRO {procrsl} {"Proc. Roy. Soc. London"}
+MACRO {rmp} {"Rev. Mod. Phys."}
+MACRO {rsi} {"Rev. Sci. Inst."}
+MACRO {science} {"Science"}
+MACRO {sciam} {"Sci. Am."}
+MACRO {sam} {"Stud. Appl. Math."}
+MACRO {sjpp} {"Sov. J. Plasma Phys."}
+MACRO {spd} {"Sov. Phys.--Doklady"}
+MACRO {sptp} {"Sov. Phys.--Tech. Phys."}
+MACRO {spu} {"Sov. Phys.--Uspeki"}
+MACRO {st} {"Sky and Telesc."}
+ % End module: physjour.mbs
+ %-------------------------------------------------------------------
+ % Begin module:
+ % \ProvidesFile{geojour.mbs}[2002/07/10 2.0h (PWD)]
+MACRO {aisr} {"Adv. Space Res."}
+MACRO {ag} {"Ann. Geophys."}
+MACRO {anigeo} {"Ann. Geofis."}
+MACRO {angl} {"Ann. Glaciol."}
+MACRO {andmet} {"Ann. d. Meteor."}
+MACRO {andgeo} {"Ann. d. Geophys."}
+MACRO {andphy} {"Ann. Phys.-Paris"}
+MACRO {afmgb} {"Arch. Meteor. Geophys. Bioklimatol."}
+MACRO {atph} {"Atm\'osphera"}
+MACRO {aao} {"Atmos. Ocean"}
+MACRO {ass}{"Astrophys. Space Sci."}
+MACRO {atenv} {"Atmos. Environ."}
+MACRO {aujag} {"Aust. J. Agr. Res."}
+MACRO {aumet} {"Aust. Meteorol. Mag."}
+MACRO {blmet} {"Bound.-Lay. Meteorol."}
+MACRO {bams} {"Bull. Amer. Meteorol. Soc."}
+MACRO {cch} {"Clim. Change"}
+MACRO {cdyn} {"Clim. Dynam."}
+MACRO {cbul} {"Climatol. Bull."}
+MACRO {cap} {"Contrib. Atmos. Phys."}
+MACRO {dsr} {"Deep-Sea Res."}
+MACRO {dhz} {"Dtsch. Hydrogr. Z."}
+MACRO {dao} {"Dynam. Atmos. Oceans"}
+MACRO {eco} {"Ecology"}
+MACRO {empl}{"Earth, Moon and Planets"}
+MACRO {envres} {"Environ. Res."}
+MACRO {envst} {"Environ. Sci. Technol."}
+MACRO {ecms} {"Estuarine Coastal Mar. Sci."}
+MACRO {expa}{"Exper. Astron."}
+MACRO {geoint} {"Geofis. Int."}
+MACRO {geopub} {"Geofys. Publ."}
+MACRO {geogeo} {"Geol. Geofiz."}
+MACRO {gafd} {"Geophys. Astrophys. Fluid Dyn."}
+MACRO {gfd} {"Geophys. Fluid Dyn."}
+MACRO {geomag} {"Geophys. Mag."}
+MACRO {georl} {"Geophys. Res. Lett."}
+MACRO {grl} {"Geophys. Res. Lett."}
+MACRO {ga} {"Geophysica"}
+MACRO {gs} {"Geophysics"}
+MACRO {ieeetap} {"IEEE Trans. Antenn. Propag."}
+MACRO {ijawp} {"Int. J. Air Water Pollut."}
+MACRO {ijc} {"Int. J. Climatol."}
+MACRO {ijrs} {"Int. J. Remote Sens."}
+MACRO {jam} {"J. Appl. Meteorol."}
+MACRO {jaot} {"J. Atmos. Ocean. Technol."}
+MACRO {jatp} {"J. Atmos. Terr. Phys."}
+MACRO {jastp} {"J. Atmos. Solar-Terr. Phys."}
+MACRO {jce} {"J. Climate"}
+MACRO {jcam} {"J. Climate Appl. Meteor."}
+MACRO {jcm} {"J. Climate Meteor."}
+MACRO {jcy} {"J. Climatol."}
+MACRO {jgr} {"J. Geophys. Res."}
+MACRO {jga} {"J. Glaciol."}
+MACRO {jh} {"J. Hydrol."}
+MACRO {jmr} {"J. Mar. Res."}
+MACRO {jmrj} {"J. Meteor. Res. Japan"}
+MACRO {jm} {"J. Meteor."}
+MACRO {jpo} {"J. Phys. Oceanogr."}
+MACRO {jra} {"J. Rech. Atmos."}
+MACRO {jaes} {"J. Aeronaut. Sci."}
+MACRO {japca} {"J. Air Pollut. Control Assoc."}
+MACRO {jas} {"J. Atmos. Sci."}
+MACRO {jmts} {"J. Mar. Technol. Soc."}
+MACRO {jmsj} {"J. Meteorol. Soc. Japan"}
+MACRO {josj} {"J. Oceanogr. Soc. Japan"}
+MACRO {jwm} {"J. Wea. Mod."}
+MACRO {lao} {"Limnol. Oceanogr."}
+MACRO {mwl} {"Mar. Wea. Log"}
+MACRO {mau} {"Mausam"}
+MACRO {meteor} {"``Meteor'' Forschungsergeb."}
+MACRO {map} {"Meteorol. Atmos. Phys."}
+MACRO {metmag} {"Meteor. Mag."}
+MACRO {metmon} {"Meteor. Monogr."}
+MACRO {metrun} {"Meteor. Rundsch."}
+MACRO {metzeit} {"Meteor. Z."}
+MACRO {metgid} {"Meteor. Gidrol."}
+MACRO {mwr} {"Mon. Weather Rev."}
+MACRO {nwd} {"Natl. Weather Dig."}
+MACRO {nzjmfr} {"New Zeal. J. Mar. Freshwater Res."}
+MACRO {npg} {"Nonlin. Proc. Geophys."}
+MACRO {om} {"Oceanogr. Meteorol."}
+MACRO {ocac} {"Oceanol. Acta"}
+MACRO {oceanus} {"Oceanus"}
+MACRO {paleoc} {"Paleoceanography"}
+MACRO {pce} {"Phys. Chem. Earth"}
+MACRO {pmg} {"Pap. Meteor. Geophys."}
+MACRO {ppom} {"Pap. Phys. Oceanogr. Meteor."}
+MACRO {physzeit} {"Phys. Z."}
+MACRO {pps} {"Planet. Space Sci."}
+MACRO {pss} {"Planet. Space Sci."}
+MACRO {pag} {"Pure Appl. Geophys."}
+MACRO {qjrms} {"Quart. J. Roy. Meteorol. Soc."}
+MACRO {quatres} {"Quat. Res."}
+MACRO {rsci} {"Radio Sci."}
+MACRO {rse} {"Remote Sens. Environ."}
+MACRO {rgeo} {"Rev. Geophys."}
+MACRO {rgsp} {"Rev. Geophys. Space Phys."}
+MACRO {rdgeo} {"Rev. Geofis."}
+MACRO {revmeta} {"Rev. Meteorol."}
+MACRO {sgp}{"Surveys in Geophys."}
+MACRO {sp} {"Solar Phys."}
+MACRO {ssr} {"Space Sci. Rev."}
+MACRO {tellus} {"Tellus"}
+MACRO {tac} {"Theor. Appl. Climatol."}
+MACRO {tagu} {"Trans. Am. Geophys. Union (EOS)"}
+MACRO {wrr} {"Water Resour. Res."}
+MACRO {weather} {"Weather"}
+MACRO {wafc} {"Weather Forecast."}
+MACRO {ww} {"Weatherwise"}
+MACRO {wmob} {"WMO Bull."}
+MACRO {zeitmet} {"Z. Meteorol."}
+ % End module: geojour.mbs
+ %-------------------------------------------------------------------
+ % Begin module:
+ % \ProvidesFile{photjour.mbs}[1999/02/24 2.0b (PWD)]
+
+MACRO {appopt} {"Appl. Opt."}
+MACRO {bell} {"Bell Syst. Tech. J."}
+MACRO {ell} {"Electron. Lett."}
+MACRO {jasp} {"J. Appl. Spectr."}
+MACRO {jqe} {"IEEE J. Quantum Electron."}
+MACRO {jlwt} {"J. Lightwave Technol."}
+MACRO {jmo} {"J. Mod. Opt."}
+MACRO {josa} {"J. Opt. Soc. America"}
+MACRO {josaa} {"J. Opt. Soc. Amer.~A"}
+MACRO {josab} {"J. Opt. Soc. Amer.~B"}
+MACRO {jdp} {"J. Phys. (Paris)"}
+MACRO {oc} {"Opt. Commun."}
+MACRO {ol} {"Opt. Lett."}
+MACRO {phtl} {"IEEE Photon. Technol. Lett."}
+MACRO {pspie} {"Proc. Soc. Photo-Opt. Instrum. Eng."}
+MACRO {sse} {"Solid-State Electron."}
+MACRO {sjot} {"Sov. J. Opt. Technol."}
+MACRO {sjqe} {"Sov. J. Quantum Electron."}
+MACRO {sleb} {"Sov. Phys.--Leb. Inst. Rep."}
+MACRO {stph} {"Sov. Phys.--Techn. Phys."}
+MACRO {stphl} {"Sov. Techn. Phys. Lett."}
+MACRO {vr} {"Vision Res."}
+MACRO {zph} {"Z. f. Physik"}
+MACRO {zphb} {"Z. f. Physik~B"}
+MACRO {zphd} {"Z. f. Physik~D"}
+
+MACRO {CLEO} {"CLEO"}
+MACRO {ASSL} {"Adv. Sol.-State Lasers"}
+MACRO {OSA} {"OSA"}
+ % End module: photjour.mbs
+%% Copyright 1994-2004 Patrick W Daly
+MACRO {acmcs} {"ACM Comput. Surv."}
+
+MACRO {acta} {"Acta Inf."}
+
+MACRO {cacm} {"Commun. ACM"}
+
+MACRO {ibmjrd} {"IBM J. Res. Dev."}
+
+MACRO {ibmsj} {"IBM Syst.~J."}
+
+MACRO {ieeese} {"IEEE Trans. Software Eng."}
+
+MACRO {ieeetc} {"IEEE Trans. Comput."}
+
+MACRO {ieeetcad}
+ {"IEEE Trans. Comput. Aid. Des."}
+
+MACRO {ipl} {"Inf. Process. Lett."}
+
+MACRO {jacm} {"J.~ACM"}
+
+MACRO {jcss} {"J.~Comput. Syst. Sci."}
+
+MACRO {scp} {"Sci. Comput. Program."}
+
+MACRO {sicomp} {"SIAM J. Comput."}
+
+MACRO {tocs} {"ACM Trans. Comput. Syst."}
+
+MACRO {tods} {"ACM Trans. Database Syst."}
+
+MACRO {tog} {"ACM Trans. Graphic."}
+
+MACRO {toms} {"ACM Trans. Math. Software"}
+
+MACRO {toois} {"ACM Trans. Office Inf. Syst."}
+
+MACRO {toplas} {"ACM Trans. Progr. Lang. Syst."}
+
+MACRO {tcs} {"Theor. Comput. Sci."}
+
+FUNCTION {bibinfo.check}
+{ swap$
+ duplicate$ missing$
+ {
+ pop$ pop$
+ ""
+ }
+ { duplicate$ empty$
+ {
+ swap$ pop$
+ }
+ { swap$
+ pop$
+ }
+ if$
+ }
+ if$
+}
+FUNCTION {bibinfo.warn}
+{ swap$
+ duplicate$ missing$
+ {
+ swap$ "missing " swap$ * " in " * cite$ * warning$ pop$
+ ""
+ }
+ { duplicate$ empty$
+ {
+ swap$ "empty " swap$ * " in " * cite$ * warning$
+ }
+ { swap$
+ pop$
+ }
+ if$
+ }
+ if$
+}
+STRINGS { bibinfo}
+INTEGERS { nameptr namesleft numnames }
+
+FUNCTION {format.names}
+{ 'bibinfo :=
+ duplicate$ empty$ 'skip$ {
+ 's :=
+ "" 't :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr
+ duplicate$ #1 >
+ { "{f.~}{vv~}{ll}{, jj}" }
+ { "{vv~}{ll}{, f.}{, jj}" }
+ if$
+ format.name$
+ bibinfo bibinfo.check
+ 't :=
+ nameptr #1 >
+ {
+ namesleft #1 >
+ { ", " * t * }
+ {
+ "," *
+ s nameptr "{ll}" format.name$ duplicate$ "others" =
+ { 't := }
+ { pop$ }
+ if$
+ t "others" =
+ {
+ " " * bbl.etal *
+ }
+ {
+ bbl.and
+ space.word * t *
+ }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ } if$
+}
+FUNCTION {format.names.ed}
+{
+ 'bibinfo :=
+ duplicate$ empty$ 'skip$ {
+ 's :=
+ "" 't :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr
+ "{f.~}{vv~}{ll}{, jj}"
+ format.name$
+ bibinfo bibinfo.check
+ 't :=
+ nameptr #1 >
+ {
+ namesleft #1 >
+ { ", " * t * }
+ {
+ numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ s nameptr "{ll}" format.name$ duplicate$ "others" =
+ { 't := }
+ { pop$ }
+ if$
+ t "others" =
+ {
+
+ " " * bbl.etal *
+ }
+ {
+ bbl.and
+ space.word * t *
+ }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ } if$
+}
+FUNCTION {format.key}
+{ empty$
+ { key field.or.null }
+ { "" }
+ if$
+}
+
+FUNCTION {format.authors}
+{ author "author" format.names
+}
+FUNCTION {get.bbl.editor}
+{ editor num.names$ #1 > 'bbl.editors 'bbl.editor if$ }
+
+FUNCTION {format.editors}
+{ editor "editor" format.names duplicate$ empty$ 'skip$
+ {
+ " " *
+ get.bbl.editor
+ capitalize
+ "(" swap$ * ")" *
+ *
+ }
+ if$
+}
+FUNCTION {format.book.pages}
+{ pages "pages" bibinfo.check
+ duplicate$ empty$ 'skip$
+ { " " * bbl.pages * }
+ if$
+}
+FUNCTION {format.doi}
+{ doi "doi" bibinfo.check
+ duplicate$ empty$ 'skip$
+ {
+ "\doi{" swap$ * "}" *
+ }
+ if$
+}
+FUNCTION {format.note}
+{
+ note empty$
+ { "" }
+ { note #1 #1 substring$
+ duplicate$ "{" =
+ 'skip$
+ { output.state mid.sentence =
+ { "l" }
+ { "u" }
+ if$
+ change.case$
+ }
+ if$
+ note #2 global.max$ substring$ * "note" bibinfo.check
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title
+ duplicate$ empty$ 'skip$
+ { "t" change.case$ }
+ if$
+ "title" bibinfo.check
+}
+FUNCTION {format.full.names}
+{'s :=
+ "" 't :=
+ #1 'nameptr :=
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr
+ "{vv~}{ll}" format.name$
+ 't :=
+ nameptr #1 >
+ {
+ namesleft #1 >
+ { ", " * t * }
+ {
+ s nameptr "{ll}" format.name$ duplicate$ "others" =
+ { 't := }
+ { pop$ }
+ if$
+ t "others" =
+ {
+ " " * bbl.etal *
+ cite.name.font
+ }
+ {
+ numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ bbl.and
+ space.word * t *
+ }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ t "others" =
+ 'skip$
+ { cite.name.font }
+ if$
+}
+
+FUNCTION {author.editor.key.full}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.full.names }
+ if$
+ }
+ { author format.full.names }
+ if$
+}
+
+FUNCTION {author.key.full}
+{ author empty$
+ { key empty$
+ { cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { author format.full.names }
+ if$
+}
+
+FUNCTION {editor.key.full}
+{ editor empty$
+ { key empty$
+ { cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.full.names }
+ if$
+}
+
+FUNCTION {make.full.names}
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.key.full
+ { type$ "proceedings" =
+ 'editor.key.full
+ 'author.key.full
+ if$
+ }
+ if$
+}
+
+FUNCTION {output.bibitem}
+{ newline$
+ "\bibitem[{" write$
+ label write$
+ ")" make.full.names duplicate$ short.list =
+ { pop$ }
+ { * }
+ if$
+ "}]{" * write$
+ cite$ write$
+ "}" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {if.digit}
+{ duplicate$ "0" =
+ swap$ duplicate$ "1" =
+ swap$ duplicate$ "2" =
+ swap$ duplicate$ "3" =
+ swap$ duplicate$ "4" =
+ swap$ duplicate$ "5" =
+ swap$ duplicate$ "6" =
+ swap$ duplicate$ "7" =
+ swap$ duplicate$ "8" =
+ swap$ "9" = or or or or or or or or or
+}
+FUNCTION {n.separate}
+{ 't :=
+ ""
+ #0 'numnames :=
+ { t empty$ not }
+ { t #-1 #1 substring$ if.digit
+ { numnames #1 + 'numnames := }
+ { #0 'numnames := }
+ if$
+ t #-1 #1 substring$ swap$ *
+ t #-2 global.max$ substring$ 't :=
+ numnames #5 =
+ { duplicate$ #1 #2 substring$ swap$
+ #3 global.max$ substring$
+ "," swap$ * *
+ }
+ 'skip$
+ if$
+ }
+ while$
+}
+FUNCTION {n.dashify}
+{
+ n.separate
+ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+ { t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+ { "-" *
+ t #2 global.max$ substring$ 't :=
+ }
+ while$
+ }
+ if$
+ }
+ { t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+ }
+ if$
+ }
+ while$
+}
+
+FUNCTION {word.in}
+{ bbl.in
+ " " * }
+
+FUNCTION {format.date}
+{ year "year" bibinfo.check duplicate$ empty$
+ {
+ }
+ 'skip$
+ if$
+ extra.label *
+ before.all 'output.state :=
+ " (" swap$ * ")" *
+}
+FUNCTION {format.btitle}
+{ title "title" bibinfo.check
+ duplicate$ empty$ 'skip$
+ {
+ emphasize
+ }
+ if$
+}
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ { bbl.volume volume tie.or.space.prefix
+ "volume" bibinfo.check * *
+ series "series" bibinfo.check
+ duplicate$ empty$ 'pop$
+ { emphasize ", " * swap$ * }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+ { series field.or.null }
+ { series empty$
+ { number "number" bibinfo.check }
+ { output.state mid.sentence =
+ { bbl.number }
+ { bbl.number capitalize }
+ if$
+ number tie.or.space.prefix "number" bibinfo.check * *
+ bbl.in space.word *
+ series "series" bibinfo.check *
+ }
+ if$
+ }
+ if$
+ }
+ { "" }
+ if$
+}
+
+FUNCTION {format.edition}
+{ edition duplicate$ empty$ 'skip$
+ {
+ output.state mid.sentence =
+ { "l" }
+ { "t" }
+ if$ change.case$
+ "edition" bibinfo.check
+ " " * bbl.edition *
+ }
+ if$
+}
+INTEGERS { multiresult }
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+ { #1 'multiresult := }
+ { t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+FUNCTION {format.pages}
+{ pages duplicate$ empty$ 'skip$
+ { duplicate$ multi.page.check
+ {
+ bbl.pages swap$
+ n.dashify
+ }
+ {
+ bbl.page swap$
+ }
+ if$
+ tie.or.space.prefix
+ "pages" bibinfo.check
+ * *
+ }
+ if$
+}
+FUNCTION {format.journal.pages}
+{ pages duplicate$ empty$ 'pop$
+ { swap$ duplicate$ empty$
+ { pop$ pop$ format.pages }
+ {
+ ", " *
+ swap$
+ n.dashify
+ "pages" bibinfo.check
+ *
+ }
+ if$
+ }
+ if$
+}
+FUNCTION {format.journal.eid}
+{ eid "eid" bibinfo.check
+ duplicate$ empty$ 'pop$
+ { swap$ duplicate$ empty$ 'skip$
+ {
+ ", " *
+ }
+ if$
+ swap$ *
+ }
+ if$
+}
+FUNCTION {format.vol.num.pages}
+{ volume field.or.null
+ duplicate$ empty$ 'skip$
+ {
+ "volume" bibinfo.check
+ }
+ if$
+ emphasize
+ number "number" bibinfo.check duplicate$ empty$ 'skip$
+ {
+ swap$ duplicate$ empty$
+ { "there's a number but no volume in " cite$ * warning$ }
+ 'skip$
+ if$
+ swap$
+ "(" swap$ * ")" *
+ }
+ if$ *
+ eid empty$
+ { format.journal.pages }
+ { format.journal.eid }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+ { bbl.chapter }
+ { type "l" change.case$
+ "type" bibinfo.check
+ }
+ if$
+ chapter tie.or.space.prefix
+ "chapter" bibinfo.check
+ * *
+ pages empty$
+ 'skip$
+ { ", " * format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.booktitle}
+{
+ booktitle "booktitle" bibinfo.check
+ emphasize
+}
+FUNCTION {format.in.ed.booktitle}
+{ format.booktitle duplicate$ empty$ 'skip$
+ {
+ format.bvolume duplicate$ empty$ 'pop$
+ { ", " swap$ * * }
+ if$
+ editor "editor" format.names.ed duplicate$ empty$ 'pop$
+ {
+ bbl.edby
+ " " * swap$ *
+ swap$
+ "," *
+ " " * swap$
+ * }
+ if$
+ word.in swap$ *
+ }
+ if$
+}
+FUNCTION {format.thesis.type}
+{ type duplicate$ empty$
+ 'pop$
+ { swap$ pop$
+ "t" change.case$ "type" bibinfo.check
+ }
+ if$
+}
+FUNCTION {format.tr.number}
+{ number "number" bibinfo.check
+ type duplicate$ empty$
+ { pop$ bbl.techrep }
+ 'skip$
+ if$
+ "type" bibinfo.check
+ swap$ duplicate$ empty$
+ { pop$ "t" change.case$ }
+ { tie.or.space.prefix * * }
+ if$
+}
+FUNCTION {format.article.crossref}
+{
+ word.in
+ " \cite{" * crossref * "}" *
+}
+FUNCTION {format.book.crossref}
+{ volume duplicate$ empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ pop$ word.in
+ }
+ { bbl.volume
+ swap$ tie.or.space.prefix "volume" bibinfo.check * * bbl.of space.word *
+ }
+ if$
+ " \cite{" * crossref * "}" *
+}
+FUNCTION {format.incoll.inproc.crossref}
+{
+ word.in
+ " \cite{" * crossref * "}" *
+}
+FUNCTION {format.org.or.pub}
+{ 't :=
+ ""
+ address empty$ t empty$ and
+ 'skip$
+ {
+ t empty$
+ { address "address" bibinfo.check *
+ }
+ { t *
+ address empty$
+ 'skip$
+ { ", " * address "address" bibinfo.check * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+FUNCTION {format.publisher.address}
+{ publisher "publisher" bibinfo.warn format.org.or.pub
+}
+
+FUNCTION {format.organization.address}
+{ organization "organization" bibinfo.check format.org.or.pub
+}
+
+FUNCTION {article}
+{ output.bibitem
+ format.authors "author" output.check
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title "title" output.check
+ crossref missing$
+ {
+ journal
+ "journal" bibinfo.check
+ emphasize
+ "journal" output.check
+ format.vol.num.pages output
+ format.doi output
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ format.note output
+ fin.entry
+}
+FUNCTION {book}
+{ output.bibitem
+ author empty$
+ { format.editors "author and editor" output.check
+ editor format.key output
+ }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ format.date "year" output.check
+ date.block
+ format.btitle "title" output.check
+ crossref missing$
+ { format.bvolume output
+ format.number.series output
+ format.edition output
+ format.book.pages output
+ format.publisher.address output
+ }
+ {
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.doi output
+ format.note output
+ fin.entry
+}
+FUNCTION {booklet}
+{ output.bibitem
+ format.authors output
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title "title" output.check
+ howpublished "howpublished" bibinfo.check output
+ address "address" bibinfo.check output
+ format.book.pages output
+ format.doi output
+ format.note output
+ fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ author empty$
+ { format.editors "author and editor" output.check
+ editor format.key output
+ }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ format.date "year" output.check
+ date.block
+ format.btitle "title" output.check
+ crossref missing$
+ {
+ format.bvolume output
+ format.chapter.pages "chapter and pages" output.check
+ format.number.series output
+ format.edition output
+ format.publisher.address output
+ }
+ {
+ format.chapter.pages "chapter and pages" output.check
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.doi output
+ format.note output
+ fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ format.authors "author" output.check
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title "title" output.check
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.number.series output
+ format.edition output
+ format.chapter.pages output
+ format.publisher.address output
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.chapter.pages output
+ }
+ if$
+ format.doi output
+ format.note output
+ fin.entry
+}
+FUNCTION {inproceedings}
+{ output.bibitem
+ format.authors "author" output.check
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title "title" output.check
+ crossref missing$
+ { format.in.ed.booktitle "booktitle" output.check
+ format.number.series output
+ format.pages output
+ publisher empty$
+ { format.organization.address output }
+ { organization "organization" bibinfo.check output
+ format.publisher.address output
+ }
+ if$
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ format.doi output
+ format.note output
+ fin.entry
+}
+FUNCTION {conference} { inproceedings }
+FUNCTION {manual}
+{ output.bibitem
+ format.authors output
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.btitle "title" output.check
+ organization "organization" bibinfo.check output
+ address "address" bibinfo.check output
+ format.edition output
+ format.doi output
+ format.note output
+ fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ format.authors "author" output.check
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title
+ "title" output.check
+ bbl.mthesis format.thesis.type output.nonnull
+ school "school" bibinfo.warn output
+ address "address" bibinfo.check output
+ format.doi output
+ format.note output
+ fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ format.authors output
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title output
+ howpublished "howpublished" bibinfo.check output
+ format.doi output
+ format.note output
+ fin.entry
+}
+FUNCTION {phdthesis}
+{ output.bibitem
+ format.authors "author" output.check
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title
+ "title" output.check
+ bbl.phdthesis format.thesis.type output.nonnull
+ school "school" bibinfo.warn output
+ address "address" bibinfo.check output
+ format.doi output
+ format.note output
+ fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ format.editors output
+ editor format.key output
+ format.date "year" output.check
+ date.block
+ format.btitle "title" output.check
+ format.bvolume output
+ format.number.series output
+ publisher empty$
+ { format.organization.address output }
+ { organization "organization" bibinfo.check output
+ format.publisher.address output
+ }
+ if$
+ format.doi output
+ format.note output
+ fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ format.authors "author" output.check
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title
+ "title" output.check
+ format.tr.number emphasize output.nonnull
+ institution "institution" bibinfo.warn output
+ address "address" bibinfo.check output
+ format.doi output
+ format.note output
+ fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ format.authors "author" output.check
+ author format.key output
+ format.date "year" output.check
+ date.block
+ format.title "title" output.check
+ format.doi output
+ format.note "note" output.check
+ fin.entry
+}
+
+FUNCTION {default.type} { misc }
+READ
+FUNCTION {sortify}
+{ purify$
+ "l" change.case$
+}
+INTEGERS { len }
+FUNCTION {chop.word}
+{ 's :=
+ 'len :=
+ s #1 len substring$ =
+ { s len #1 + global.max$ substring$ }
+ 's
+ if$
+}
+FUNCTION {format.lab.names}
+{ 's :=
+ "" 't :=
+ s #1 "{vv~}{ll}" format.name$
+ s num.names$ duplicate$
+ #2 >
+ { pop$
+ " " * bbl.etal *
+ cite.name.font
+ "others" 't :=
+ }
+ { #2 <
+ 'skip$
+ { s #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ {
+ " " * bbl.etal *
+ cite.name.font
+ "others" 't :=
+ }
+ { bbl.and space.word * s #2 "{vv~}{ll}" format.name$
+ * }
+ if$
+ }
+ if$
+ }
+ if$
+ t "others" =
+ 'skip$
+ { cite.name.font }
+ if$
+}
+
+FUNCTION {author.key.label}
+{ author empty$
+ { key empty$
+ { cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {author.editor.key.label}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.lab.names }
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {editor.key.label}
+{ editor empty$
+ { key empty$
+ { cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.lab.names }
+ if$
+}
+
+FUNCTION {calc.short.authors}
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.key.label
+ { type$ "proceedings" =
+ 'editor.key.label
+ 'author.key.label
+ if$
+ }
+ if$
+ 'short.list :=
+}
+
+FUNCTION {calc.label}
+{ calc.short.authors
+ short.list
+ "("
+ *
+ year duplicate$ empty$
+ short.list key field.or.null = or
+ { pop$ "" }
+ 'skip$
+ if$
+ *
+ 'label :=
+}
+
+FUNCTION {sort.format.names}
+{ 's :=
+ #1 'nameptr :=
+ ""
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { s nameptr
+ "{vv{ } }{ll{ }}{ f{ }}{ jj{ }}"
+ format.name$ 't :=
+ nameptr #1 >
+ {
+ " " *
+ namesleft #1 = t "others" = and
+ { "zzzzz" * }
+ { numnames #2 > nameptr #2 = and
+ { "zz" * year field.or.null * " " * }
+ 'skip$
+ if$
+ t sortify *
+ }
+ if$
+ }
+ { t sortify * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+ "A " #2
+ "An " #3
+ "The " #4 t chop.word
+ chop.word
+ chop.word
+ sortify
+ #1 global.max$ substring$
+}
+FUNCTION {author.sort}
+{ author empty$
+ { key empty$
+ { "to sort, need author or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+FUNCTION {author.editor.sort}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { "to sort, need author, editor, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+FUNCTION {editor.sort}
+{ editor empty$
+ { key empty$
+ { "to sort, need editor or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+FUNCTION {presort}
+{ calc.label
+ label sortify
+ " "
+ *
+ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.sort
+ { type$ "proceedings" =
+ 'editor.sort
+ 'author.sort
+ if$
+ }
+ if$
+ #1 entry.max$ substring$
+ 'sort.label :=
+ sort.label
+ *
+ " "
+ *
+ cite$
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {presort}
+SORT
+STRINGS { last.label next.extra }
+INTEGERS { last.extra.num number.label }
+FUNCTION {initialize.extra.label.stuff}
+{ #0 int.to.chr$ 'last.label :=
+ "" 'next.extra :=
+ #0 'last.extra.num :=
+ #0 'number.label :=
+}
+FUNCTION {forward.pass}
+{ last.label label =
+ { last.extra.num #1 + 'last.extra.num :=
+ last.extra.num int.to.chr$ 'extra.label :=
+ }
+ { "a" chr.to.int$ 'last.extra.num :=
+ "" 'extra.label :=
+ label 'last.label :=
+ }
+ if$
+ number.label #1 + 'number.label :=
+}
+FUNCTION {reverse.pass}
+{ next.extra "b" =
+ { "a" 'extra.label := }
+ 'skip$
+ if$
+ extra.label 'next.extra :=
+ extra.label
+ duplicate$ empty$
+ 'skip$
+ { "{\natexlab{" swap$ * "}}" * }
+ if$
+ 'extra.label :=
+ label extra.label * 'label :=
+}
+EXECUTE {initialize.extra.label.stuff}
+ITERATE {forward.pass}
+REVERSE {reverse.pass}
+FUNCTION {bib.sort.order}
+{ sort.label
+ " "
+ *
+ year field.or.null sortify
+ *
+ " "
+ *
+ cite$
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+ITERATE {bib.sort.order}
+SORT
+FUNCTION {begin.bib}
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+ "\begin{thebibliography}{" number.label int.to.str$ * "}" *
+ write$ newline$
+ "\providecommand{\natexlab}[1]{#1}"
+ write$ newline$
+ "\expandafter\ifx\csname urlstyle\endcsname\relax"
+ write$ newline$
+ " \providecommand{\doi}[1]{doi:\discretionary{}{}{}#1}\else"
+ write$ newline$
+ " \providecommand{\doi}{doi:\discretionary{}{}{}\begingroup \urlstyle{rm}\Url}\fi"
+ write$ newline$
+}
+EXECUTE {begin.bib}
+EXECUTE {init.state.consts}
+ITERATE {call.type$}
+FUNCTION {end.bib}
+{ newline$
+ "\end{thebibliography}" write$ newline$
+}
+EXECUTE {end.bib}
+%% End of customized bst file
+%%
+%% End of file `agufull04.bst'.
diff --git a/vignettes/consoleExample.tex b/vignettes/consoleExample.tex
new file mode 100644
index 0000000..2e14f44
--- /dev/null
+++ b/vignettes/consoleExample.tex
@@ -0,0 +1,19 @@
+ \documentclass{article}
+ \usepackage{tikz}
+
+
+ \begin{document}
+ \begin{figure}[ht]
+ \centering
+ <<inline,echo=FALSE,results='tex'>>=
+
+ require(tikzDevice)
+ tikz(console=TRUE,width=5,height=5)
+ x <- rnorm(100)
+ plot(x)
+ dummy <- dev.off()
+ @
+ \caption{caption}
+ \label{fig:inline}
+ \end{figure}
+ \end{document}
diff --git a/vignettes/figs/annotation.tex b/vignettes/figs/annotation.tex
new file mode 100644
index 0000000..9af7e8a
--- /dev/null
+++ b/vignettes/figs/annotation.tex
@@ -0,0 +1,97 @@
+% Created by tikzDevice version 0.10.1 on 2016-02-09 21:31:05
+% !TEX encoding = UTF-8 Unicode
+\begin{tikzpicture}[x=1pt,y=1pt]
+\definecolor{fillColor}{RGB}{255,255,255}
+\path[use as bounding box,fill=fillColor,fill opacity=0.00] (0,0) rectangle (289.08,289.08);
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (263.88,239.88);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 1.2pt,line join=round] (116.78, 87.72) -- (196.30, 87.72);
+
+\path[draw=drawColor,line width= 0.4pt,dash pattern=on 4pt off 4pt ,line join=round,line cap=round] (156.54, 67.82) -- (156.54, 75.60);
+
+\path[draw=drawColor,line width= 0.4pt,dash pattern=on 4pt off 4pt ,line join=round,line cap=round] (156.54,149.25) -- (156.54,105.60);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (136.66, 67.82) -- (176.42, 67.82);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (136.66,149.25) -- (176.42,149.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (116.78, 75.60) --
+ (196.30, 75.60) --
+ (196.30,105.60) --
+ (116.78,105.60) --
+ (116.78, 75.60);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,168.85) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,233.26) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,222.21) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,156.34) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,219.21) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,203.73) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,167.20) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,195.10) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,178.84) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54,206.66) circle ( 2.25);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (289.08,289.08);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 67.80) -- ( 49.20,236.87);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 67.80) -- ( 43.20, 67.80);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 95.98) -- ( 43.20, 95.98);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,124.16) -- ( 43.20,124.16);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,152.33) -- ( 43.20,152.33);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,180.51) -- ( 43.20,180.51);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,208.69) -- ( 43.20,208.69);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,236.87) -- ( 43.20,236.87);
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 67.80) {0};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 95.98) {1};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,124.16) {2};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,152.33) {3};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,180.51) {4};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,208.69) {5};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,236.87) {6};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 61.20) --
+ (263.88, 61.20) --
+ (263.88,239.88) --
+ ( 49.20,239.88) --
+ ( 49.20, 61.20);
+\coordinate (min outlier) at (156.54,156.34);
+\coordinate (max outlier) at (156.54,233.26);
+\draw[very thick,red,
+decorate,decoration={brace,amplitude=12pt},
+transform canvas={xshift=-1em}]
+(min outlier) --
+node[single arrow,anchor=tip,fill=white,draw=green,
+left=14pt,text width=0.70in,align=center]
+{Holy Outliers Batman!}
+(max outlier);
+\node[starburst,fill=green,draw=blue,very thick,right=of max outlier] {Wow!};
+\end{scope}
+\end{tikzpicture}
diff --git a/vignettes/figs/latexEx.tex b/vignettes/figs/latexEx.tex
new file mode 100644
index 0000000..72f90e7
--- /dev/null
+++ b/vignettes/figs/latexEx.tex
@@ -0,0 +1,118 @@
+% Created by tikzDevice version 0.10.1 on 2016-02-09 21:31:03
+% !TEX encoding = UTF-8 Unicode
+\begin{tikzpicture}[x=1pt,y=1pt]
+\definecolor{fillColor}{RGB}{255,255,255}
+\path[use as bounding box,fill=fillColor,fill opacity=0.00] (0,0) rectangle (252.94,252.94);
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (227.75,203.75);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 76.67, 91.58) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (164.70,138.67) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (210.84,158.50) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (217.23,198.47) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (221.13,187.78) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 96.75,106.31) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (134.22,116.30) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (107.72, 82.85) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (152.13,150.70) circle ( 2.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 55.81, 66.48) circle ( 2.25);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (252.94,252.94);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 57.13, 61.20) -- (222.73, 61.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 57.13, 61.20) -- ( 57.13, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 90.25, 61.20) -- ( 90.25, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (123.37, 61.20) -- (123.37, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.49, 61.20) -- (156.49, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (189.61, 61.20) -- (189.61, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (222.73, 61.20) -- (222.73, 55.20);
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 57.13, 39.60) {-1.5};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 90.25, 39.60) {-1.0};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (123.37, 39.60) {-0.5};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (156.49, 39.60) {0.0};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (189.61, 39.60) {0.5};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (222.73, 39.60) {1.0};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 69.21) -- ( 49.20,190.71);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 69.21) -- ( 43.20, 69.21);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 93.51) -- ( 43.20, 93.51);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,117.81) -- ( 43.20,117.81);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,142.11) -- ( 43.20,142.11);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,166.41) -- ( 43.20,166.41);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,190.71) -- ( 43.20,190.71);
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 69.21) {-1.5};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,117.81) {-0.5};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,142.11) {0.0};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,166.41) {0.5};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,190.71) {1.0};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 61.20) --
+ (227.75, 61.20) --
+ (227.75,203.75) --
+ ( 49.20,203.75) --
+ ( 49.20, 61.20);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (252.94,252.94);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.20] at (138.47,224.20) {\bfseries Hello \LaTeX!};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (138.47, 15.60) {x};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 10.80,132.47) {y};
+\end{scope}
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (227.75,203.75);
+\definecolor{drawColor}{RGB}{255,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 62.67) -- (227.74,189.40);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (252.94,252.94);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (138.47,212.14) {Linear model: $R^{2}= 0.9109 $};
+\end{scope}
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (227.75,203.75);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\node[text=drawColor,anchor=base west,inner sep=0pt, outer sep=0pt, scale= 1.00] at (133.38, 69.76) {$y = 0.967x +-0.068$};
+\end{scope}
+\end{tikzpicture}
diff --git a/vignettes/figs/pdf-example.pdf b/vignettes/figs/pdf-example.pdf
new file mode 100644
index 0000000..28895e4
Binary files /dev/null and b/vignettes/figs/pdf-example.pdf differ
diff --git a/vignettes/figs/simpleEx.tex b/vignettes/figs/simpleEx.tex
new file mode 100644
index 0000000..230a32f
--- /dev/null
+++ b/vignettes/figs/simpleEx.tex
@@ -0,0 +1,76 @@
+% Created by tikzDevice version 0.10.1 on 2016-02-09 21:31:03
+% !TEX encoding = UTF-8 Unicode
+\begin{tikzpicture}[x=1pt,y=1pt]
+\definecolor{fillColor}{RGB}{255,255,255}
+\path[use as bounding box,fill=fillColor,fill opacity=0.00] (0,0) rectangle (252.94,252.94);
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (227.75,203.75);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (138.47,132.47) circle ( 2.25);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (252.94,252.94);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 55.81, 61.20) -- (221.13, 61.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 55.81, 61.20) -- ( 55.81, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 97.14, 61.20) -- ( 97.14, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (138.47, 61.20) -- (138.47, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (179.80, 61.20) -- (179.80, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (221.13, 61.20) -- (221.13, 55.20);
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 55.81, 39.60) {0.6};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 97.14, 39.60) {0.8};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (138.47, 39.60) {1.0};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (179.80, 39.60) {1.2};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (221.13, 39.60) {1.4};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 66.48) -- ( 49.20,198.47);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 66.48) -- ( 43.20, 66.48);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 99.48) -- ( 43.20, 99.48);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,132.47) -- ( 43.20,132.47);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,165.47) -- ( 43.20,165.47);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,198.47) -- ( 43.20,198.47);
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 66.48) {0.6};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 99.48) {0.8};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,132.47) {1.0};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,165.47) {1.2};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,198.47) {1.4};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 61.20) --
+ (227.75, 61.20) --
+ (227.75,203.75) --
+ ( 49.20,203.75) --
+ ( 49.20, 61.20);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (252.94,252.94);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.20] at (138.47,224.20) {\bfseries Hello World!};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (138.47, 15.60) {Index};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 10.80,132.47) {1};
+\end{scope}
+\end{tikzpicture}
diff --git a/vignettes/figs/tikz-example.tex b/vignettes/figs/tikz-example.tex
new file mode 100644
index 0000000..a5887d4
--- /dev/null
+++ b/vignettes/figs/tikz-example.tex
@@ -0,0 +1,76 @@
+% Created by tikzDevice version 0.10.1 on 2016-02-09 21:31:03
+% !TEX encoding = UTF-8 Unicode
+\begin{tikzpicture}[x=1pt,y=1pt]
+\definecolor{fillColor}{RGB}{255,255,255}
+\path[use as bounding box,fill=fillColor,fill opacity=0.00] (0,0) rectangle (234.88,234.88);
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (209.68,185.68);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (129.44,123.44) circle ( 2.25);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (234.88,234.88);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 55.14, 61.20) -- (203.73, 61.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 55.14, 61.20) -- ( 55.14, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 92.29, 61.20) -- ( 92.29, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (129.44, 61.20) -- (129.44, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (166.59, 61.20) -- (166.59, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (203.73, 61.20) -- (203.73, 55.20);
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 55.14, 39.60) {0.6};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 92.29, 39.60) {0.8};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (129.44, 39.60) {1.0};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (166.59, 39.60) {1.2};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (203.73, 39.60) {1.4};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 65.81) -- ( 49.20,181.07);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 65.81) -- ( 43.20, 65.81);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 94.62) -- ( 43.20, 94.62);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,123.44) -- ( 43.20,123.44);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,152.25) -- ( 43.20,152.25);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,181.07) -- ( 43.20,181.07);
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 65.81) {0.6};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 94.62) {0.8};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,123.44) {1.0};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,152.25) {1.2};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,181.07) {1.4};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 61.20) --
+ (209.68, 61.20) --
+ (209.68,185.68) --
+ ( 49.20,185.68) --
+ ( 49.20, 61.20);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (234.88,234.88);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.20] at (129.44,206.14) {\bfseries Hello \TeX !};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (129.44, 15.60) {1};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 10.80,123.44) {1};
+\end{scope}
+\end{tikzpicture}
diff --git a/vignettes/figs/titlePlot.tex b/vignettes/figs/titlePlot.tex
new file mode 100644
index 0000000..aa8de51
--- /dev/null
+++ b/vignettes/figs/titlePlot.tex
@@ -0,0 +1,312 @@
+% Created by tikzDevice version 0.10.1 on 2016-02-09 21:31:03
+% !TEX encoding = UTF-8 Unicode
+\begin{tikzpicture}[x=1pt,y=1pt]
+\definecolor{fillColor}{RGB}{255,255,255}
+\path[use as bounding box,fill=fillColor,fill opacity=0.00] (0,0) rectangle (289.08,289.08);
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (263.88,239.88);
+\definecolor{drawColor}{RGB}{0,0,255}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 57.15, 67.82) --
+ ( 59.16, 67.82) --
+ ( 61.17, 67.83) --
+ ( 63.17, 67.83) --
+ ( 65.18, 67.84) --
+ ( 67.19, 67.86) --
+ ( 69.20, 67.88) --
+ ( 71.21, 67.91) --
+ ( 73.21, 67.95) --
+ ( 75.22, 68.00) --
+ ( 77.23, 68.07) --
+ ( 79.24, 68.17) --
+ ( 81.25, 68.31) --
+ ( 83.25, 68.48) --
+ ( 85.26, 68.72) --
+ ( 87.27, 69.02) --
+ ( 89.28, 69.41) --
+ ( 91.28, 69.92) --
+ ( 93.29, 70.56) --
+ ( 95.30, 71.36) --
+ ( 97.31, 72.35) --
+ ( 99.32, 73.58) --
+ (101.32, 75.09) --
+ (103.33, 76.91) --
+ (105.34, 79.09) --
+ (107.35, 81.68) --
+ (109.36, 84.72) --
+ (111.36, 88.26) --
+ (113.37, 92.33) --
+ (115.38, 96.98) --
+ (117.39,102.22) --
+ (119.39,108.07) --
+ (121.40,114.53) --
+ (123.41,121.58) --
+ (125.42,129.18) --
+ (127.43,137.28) --
+ (129.43,145.80) --
+ (131.44,154.65) --
+ (133.45,163.70) --
+ (135.46,172.83) --
+ (137.47,181.88) --
+ (139.47,190.68) --
+ (141.48,199.08) --
+ (143.49,206.90) --
+ (145.50,213.97) --
+ (147.50,220.14) --
+ (149.51,225.26) --
+ (151.52,229.21) --
+ (153.53,231.90) --
+ (155.54,233.26) --
+ (157.54,233.26) --
+ (159.55,231.90) --
+ (161.56,229.21) --
+ (163.57,225.26) --
+ (165.58,220.14) --
+ (167.58,213.97) --
+ (169.59,206.90) --
+ (171.60,199.08) --
+ (173.61,190.68) --
+ (175.61,181.88) --
+ (177.62,172.83) --
+ (179.63,163.70) --
+ (181.64,154.65) --
+ (183.65,145.80) --
+ (185.65,137.28) --
+ (187.66,129.18) --
+ (189.67,121.58) --
+ (191.68,114.53) --
+ (193.69,108.07) --
+ (195.69,102.22) --
+ (197.70, 96.98) --
+ (199.71, 92.33) --
+ (201.72, 88.26) --
+ (203.72, 84.72) --
+ (205.73, 81.68) --
+ (207.74, 79.09) --
+ (209.75, 76.91) --
+ (211.76, 75.09) --
+ (213.76, 73.58) --
+ (215.77, 72.35) --
+ (217.78, 71.36) --
+ (219.79, 70.56) --
+ (221.80, 69.92) --
+ (223.80, 69.41) --
+ (225.81, 69.02) --
+ (227.82, 68.72) --
+ (229.83, 68.48) --
+ (231.83, 68.31) --
+ (233.84, 68.17) --
+ (235.85, 68.07) --
+ (237.86, 68.00) --
+ (239.87, 67.95) --
+ (241.87, 67.91) --
+ (243.88, 67.88) --
+ (245.89, 67.86) --
+ (247.90, 67.84) --
+ (249.91, 67.83) --
+ (251.91, 67.83) --
+ (253.92, 67.82) --
+ (255.93, 67.82);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (289.08,289.08);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 68.19, 61.20) -- (244.89, 61.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 68.19, 61.20) -- ( 68.19, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (112.37, 61.20) -- (112.37, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (156.54, 61.20) -- (156.54, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (200.71, 61.20) -- (200.71, 55.20);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (244.89, 61.20) -- (244.89, 55.20);
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 68.19, 39.60) {-4};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (112.37, 39.60) {-2};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (156.54, 39.60) {0};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (200.71, 39.60) {2};
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (244.89, 39.60) {4};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 67.81) -- ( 49.20,233.87);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 67.81) -- ( 43.20, 67.81);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,109.33) -- ( 43.20,109.33);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,150.84) -- ( 43.20,150.84);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,192.36) -- ( 43.20,192.36);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20,233.87) -- ( 43.20,233.87);
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80, 67.81) {0.0};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,109.33) {0.1};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,150.84) {0.2};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,192.36) {0.3};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 34.80,233.87) {0.4};
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] ( 49.20, 61.20) --
+ (263.88, 61.20) --
+ (263.88,239.88) --
+ ( 49.20,239.88) --
+ ( 49.20, 61.20);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (289.08,289.08);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (156.54, 15.60) {$x$};
+
+\node[text=drawColor,rotate= 90.00,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at ( 10.80,150.54) {$p(x)$};
+\end{scope}
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (263.88,239.88);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (112.37, 90.23) --
+ (115.41, 90.23) --
+ (115.41, 97.07) --
+ (118.46, 97.07) --
+ (118.46,105.28) --
+ (121.51,105.28) --
+ (121.51,114.88) --
+ (124.55,114.88) --
+ (124.55,125.84) --
+ (127.60,125.84) --
+ (127.60,138.00) --
+ (130.65,138.00) --
+ (130.65,151.11) --
+ (133.69,151.11) --
+ (133.69,164.80) --
+ (136.74,164.80) --
+ (136.74,178.62) --
+ (139.78,178.62) --
+ (139.78,192.02) --
+ (142.83,192.02) --
+ (142.83,204.41) --
+ (145.88,204.41) --
+ (145.88,215.22) --
+ (148.92,215.22) --
+ (148.92,223.87) --
+ (151.97,223.87) --
+ (151.97,229.93) --
+ (155.02,229.93) --
+ (155.02,233.04) --
+ (158.06,233.04) --
+ (158.06,233.04) --
+ (161.11,233.04) --
+ (161.11,229.93) --
+ (164.16,229.93) --
+ (164.16,223.87) --
+ (167.20,223.87) --
+ (167.20,215.22) --
+ (170.25,215.22) --
+ (170.25,204.41) --
+ (173.30,204.41) --
+ (173.30,192.02) --
+ (176.34,192.02) --
+ (176.34,178.62) --
+ (179.39,178.62) --
+ (179.39,164.80) --
+ (182.43,164.80) --
+ (182.43,151.11) --
+ (185.48,151.11) --
+ (185.48,138.00) --
+ (188.53,138.00) --
+ (188.53,125.84) --
+ (191.57,125.84) --
+ (191.57,114.88) --
+ (194.62,114.88) --
+ (194.62,105.28) --
+ (197.67,105.28) --
+ (197.67, 97.07) --
+ (200.71, 97.07) --
+ (200.71, 90.23);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (112.37, 67.81) --
+ (200.71, 67.81);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (112.37, 67.81) -- (112.37, 90.23);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (115.41, 67.81) -- (115.41, 97.07);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (118.46, 67.81) -- (118.46,105.28);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (121.51, 67.81) -- (121.51,114.88);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (124.55, 67.81) -- (124.55,125.84);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (127.60, 67.81) -- (127.60,138.00);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (130.65, 67.81) -- (130.65,151.11);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (133.69, 67.81) -- (133.69,164.80);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (136.74, 67.81) -- (136.74,178.62);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (139.78, 67.81) -- (139.78,192.02);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (142.83, 67.81) -- (142.83,204.41);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (145.88, 67.81) -- (145.88,215.22);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (148.92, 67.81) -- (148.92,223.87);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (151.97, 67.81) -- (151.97,229.93);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (155.02, 67.81) -- (155.02,233.04);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (158.06, 67.81) -- (158.06,233.04);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (161.11, 67.81) -- (161.11,229.93);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (164.16, 67.81) -- (164.16,223.87);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (167.20, 67.81) -- (167.20,215.22);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (170.25, 67.81) -- (170.25,204.41);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (173.30, 67.81) -- (173.30,192.02);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (176.34, 67.81) -- (176.34,178.62);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (179.39, 67.81) -- (179.39,164.80);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (182.43, 67.81) -- (182.43,151.11);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (185.48, 67.81) -- (185.48,138.00);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (188.53, 67.81) -- (188.53,125.84);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (191.57, 67.81) -- (191.57,114.88);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (194.62, 67.81) -- (194.62,105.28);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (197.67, 67.81) -- (197.67, 97.07);
+
+\path[draw=drawColor,line width= 0.4pt,line join=round,line cap=round] (200.71, 67.81) -- (200.71, 90.23);
+\end{scope}
+\begin{scope}
+\path[clip] ( 0.00, 0.00) rectangle (289.08,289.08);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.20] at (156.54,260.34) {\bfseries $p(x)=\frac{1}{\sqrt{2\pi}}e^{-\frac{x^2}{2}}$};
+\end{scope}
+\begin{scope}
+\path[clip] ( 49.20, 61.20) rectangle (263.88,239.88);
+\definecolor{drawColor}{RGB}{0,0,0}
+
+\node[text=drawColor,anchor=base,inner sep=0pt, outer sep=0pt, scale= 1.00] at (218.38,189.86) {\small$\displaystyle\int_{-2}^{2}p(x)dx\approx0.954$};
+\end{scope}
+\end{tikzpicture}
diff --git a/vignettes/figs/westCoast.tex b/vignettes/figs/westCoast.tex
new file mode 100644
index 0000000..b7ab2d5
--- /dev/null
+++ b/vignettes/figs/westCoast.tex
@@ -0,0 +1,385 @@
+% Created by tikzDevice version 0.10.1 on 2016-02-09 21:31:05
+% !TEX encoding = UTF-8 Unicode
+\definecolor{fillColor}{RGB}{255,255,255}
+\path[use as bounding box,fill=fillColor,fill opacity=0.00] (0,0) rectangle (505.89,505.89);
+\begin{scope}
+\path[clip] (154.11, 49.20) rectangle (351.78,456.69);
+\definecolor{drawColor}{gray}{0.40}
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (340.98,113.44) --
+ (281.76,173.05) --
+ (244.43,207.79) --
+ (242.11,209.73) --
+ (241.89,282.96);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (340.98,113.44) --
+ (342.24,109.69) --
+ (342.14,108.30) --
+ (344.47,105.94) --
+ (345.84,100.10) --
+ (350.18, 95.93) --
+ (347.21, 92.46) --
+ (344.04, 89.12) --
+ (342.77, 86.90) --
+ (343.09, 82.18) --
+ (342.98, 79.81) --
+ (340.02, 74.95) --
+ (339.07, 72.03) --
+ (340.02, 70.92) --
+ (339.81, 66.47) --
+ (342.77, 65.50) --
+ (343.94, 62.86) --
+ (342.56, 58.69) --
+ (339.18, 58.00);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (339.18, 58.00) --
+ (295.29, 53.27) --
+ (294.55, 56.89) --
+ (295.82, 56.05) --
+ (294.03, 58.00) --
+ (293.18, 57.44) --
+ (293.18, 59.80) --
+ (292.12, 67.03) --
+ (287.68, 73.56) --
+ (277.21, 83.29) --
+ (274.57, 83.29) --
+ (273.72, 82.31) --
+ (271.71, 83.98) --
+ (271.71, 86.62) --
+ (270.02, 89.40) --
+ (261.46, 90.65) --
+ (257.54, 92.46) --
+ (256.06, 95.79) --
+ (249.72, 99.40) --
+ (244.96, 99.13) --
+ (236.92,100.10) --
+ (234.60, 99.96) --
+ (231.53,102.60) --
+ (230.58,103.99) --
+ (231.21,106.77) --
+ (230.79,108.71) --
+ (231.43,109.69) --
+ (230.58,112.05) --
+ (230.58,117.05) --
+ (226.99,118.58) --
+ (226.25,120.53) --
+ (227.51,121.22) --
+ (226.35,124.28) --
+ (223.50,125.25) --
+ (218.53,131.09) --
+ (210.70,142.62) --
+ (207.63,145.68) --
+ (206.37,151.37) --
+ (207.85,152.62) --
+ (209.33,154.71) --
+ (208.80,159.29) --
+ (206.47,160.68) --
+ (202.14,161.93) --
+ (197.91,167.77) --
+ (197.69,171.66) --
+ (196.11,176.38) --
+ (196.21,180.55) --
+ (197.48,181.25) --
+ (198.75,180.97) --
+ (198.75,179.16) --
+ (198.86,176.94) --
+ (204.25,172.91) --
+ (206.05,173.05) --
+ (204.25,174.30) --
+ (202.98,177.22) --
+ (200.66,180.00) --
+ (200.02,182.64) --
+ (198.43,184.16) --
+ (198.65,185.55) --
+ (201.08,187.22) --
+ (202.24,187.08) --
+ (198.22,190.00) --
+ (196.21,188.75) --
+ (196.21,187.08) --
+ (196.95,185.97) --
+ (196.64,185.28) --
+ (197.59,183.33) --
+ (196.95,183.19) --
+ (196.74,182.08) --
+ (188.81,186.94) --
+ (187.23,185.83) --
+ (187.54,188.47) --
+ (187.33,191.11) --
+ (188.92,190.56) --
+ (186.70,193.75) --
+ (185.01,196.53) --
+ (180.67,200.14) --
+ (173.37,209.04) --
+ (174.01,210.98) --
+ (171.79,218.35) --
+ (172.63,223.63) --
+ (171.79,229.60) --
+ (166.82,236.41) --
+ (161.74,241.41) --
+ (161.21,246.83) --
+ (166.08,258.09) --
+ (165.87,260.87) --
+ (165.76,263.64) --
+ (166.50,263.09) --
+ (167.13,266.84) --
+ (166.82,271.84) --
+ (167.45,271.84) --
+ (166.18,275.04) --
+ (164.07,278.10) --
+ (164.81,282.82);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (241.89,282.96) --
+ (199.49,282.96) --
+ (182.26,282.96) --
+ (164.81,282.82);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (298.68,379.67) --
+ (302.06,375.08) --
+ (302.91,375.78) --
+ (305.76,373.97) --
+ (307.24,370.36) --
+ (301.22,357.16) --
+ (300.16,355.35) --
+ (299.52,351.60) --
+ (298.89,351.04) --
+ (297.52,349.93) --
+ (293.60,343.26) --
+ (293.60,338.68) --
+ (296.46,336.87) --
+ (297.30,337.43) --
+ (298.89,336.04) --
+ (298.15,333.40) --
+ (298.57,331.45) --
+ (296.88,326.17) --
+ (296.88,282.96);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (296.88,282.96) --
+ (254.80,282.96) --
+ (241.89,282.96);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (164.81,282.82) --
+ (162.06,286.71) --
+ (160.90,293.52) --
+ (161.85,296.44) --
+ (158.36,303.25) --
+ (160.90,309.64) --
+ (161.85,315.19) --
+ (165.13,322.42) --
+ (167.88,347.01) --
+ (167.56,347.99) --
+ (169.57,359.94) --
+ (169.36,364.24) --
+ (170.10,365.63) --
+ (169.36,367.30) --
+ (171.05,367.02) --
+ (169.99,369.80) --
+ (169.04,378.83) --
+ (170.31,380.64) --
+ (168.72,384.95) --
+ (172.42,383.28) --
+ (171.89,384.53) --
+ (172.63,384.67) --
+ (174.22,383.84) --
+ (177.18,385.23) --
+ (178.66,385.23);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (298.68,379.67) --
+ (261.25,379.67) --
+ (255.85,378.00) --
+ (254.58,378.14) --
+ (248.45,376.75) --
+ (233.75,372.16) --
+ (229.95,373.14) --
+ (224.24,371.05) --
+ (222.54,371.19) --
+ (220.53,370.08) --
+ (216.73,372.30) --
+ (209.22,372.30) --
+ (200.34,368.69) --
+ (191.03,371.05) --
+ (190.50,375.92) --
+ (188.28,381.47) --
+ (184.48,383.84) --
+ (180.56,383.00) --
+ (178.66,385.23);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (186.27,442.06) --
+ (187.75,440.81) --
+ (187.33,438.86) --
+ (185.85,439.83) --
+ (185.01,440.39) --
+ (184.90,443.03) --
+ (186.27,442.06);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (189.87,438.03) --
+ (191.14,438.86) --
+ (189.66,441.36) --
+ (188.71,440.25) --
+ (189.87,438.03);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (190.93,443.03) --
+ (189.13,444.56) --
+ (189.87,442.61) --
+ (187.65,442.75) --
+ (187.54,443.86) --
+ (188.81,445.67) --
+ (191.67,444.70) --
+ (190.93,443.03);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (192.72,432.47) --
+ (191.77,434.00) --
+ (193.68,437.33) --
+ (196.00,436.22) --
+ (196.53,435.25) --
+ (192.94,433.86) --
+ (195.16,432.61) --
+ (196.00,429.00) --
+ (196.43,429.00) --
+ (196.43,430.25) --
+ (199.39,427.88) --
+ (198.65,425.80) --
+ (196.74,427.74) --
+ (195.16,428.58) --
+ (194.52,431.91) --
+ (192.72,432.47);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (296.99,452.34) --
+ (203.40,452.34) --
+ (191.03,451.51) --
+ (192.09,450.39) --
+ (191.35,449.56) --
+ (192.72,448.59) --
+ (192.72,447.20) --
+ (193.78,446.78) --
+ (194.20,445.67) --
+ (195.79,446.92) --
+ (196.95,445.81) --
+ (196.21,445.39) --
+ (197.59,441.92) --
+ (196.95,440.53) --
+ (196.64,439.00) --
+ (193.99,440.39) --
+ (193.25,439.83) --
+ (194.63,438.03) --
+ (195.58,438.44) --
+ (197.38,436.22) --
+ (198.86,434.55) --
+ (199.39,430.38) --
+ (202.03,429.00) --
+ (198.54,423.44) --
+ (198.75,420.38) --
+ (198.12,419.96) --
+ (199.39,418.16) --
+ (198.33,418.02) --
+ (199.92,412.74) --
+ (198.12,410.79) --
+ (198.33,409.96) --
+ (196.11,411.35) --
+ (193.36,406.21) --
+ (190.72,407.60) --
+ (190.72,406.49) --
+ (189.45,407.04) --
+ (189.55,404.68) --
+ (188.49,406.35) --
+ (187.44,405.79) --
+ (188.71,407.60) --
+ (188.07,407.74) --
+ (186.49,406.35) --
+ (187.75,408.43) --
+ (185.85,408.43) --
+ (187.01,409.68) --
+ (186.70,408.99) --
+ (188.49,409.54) --
+ (191.14,413.02) --
+ (191.24,408.29) --
+ (192.41,409.68) --
+ (191.98,411.35) --
+ (194.20,412.74) --
+ (193.46,410.93) --
+ (195.26,410.93) --
+ (196.21,416.77) --
+ (194.95,417.18) --
+ (193.15,416.77) --
+ (193.04,418.99) --
+ (194.73,418.16) --
+ (194.10,421.91) --
+ (195.37,421.35) --
+ (195.79,422.33) --
+ (197.17,422.19) --
+ (195.37,426.08) --
+ (194.52,426.77) --
+ (195.26,424.83) --
+ (195.26,423.85) --
+ (194.31,424.27) --
+ (191.77,419.96) --
+ (189.02,418.43) --
+ (185.75,413.15) --
+ (189.34,414.41) --
+ (190.19,414.27) --
+ (189.13,413.43) --
+ (184.48,412.46) --
+ (186.27,417.60) --
+ (190.08,421.77) --
+ (189.87,423.71) --
+ (190.93,423.44) --
+ (191.24,422.33) --
+ (193.99,425.10) --
+ (193.15,426.91) --
+ (193.78,428.44) --
+ (192.72,430.66) --
+ (192.72,428.72) --
+ (191.46,428.72) --
+ (191.56,431.36) --
+ (189.98,430.11) --
+ (190.93,428.86) --
+ (189.87,427.88) --
+ (189.87,428.86) --
+ (188.92,430.11) --
+ (187.65,429.69) --
+ (185.75,431.36) --
+ (183.95,431.08) --
+ (172.42,432.05) --
+ (160.47,436.22) --
+ (155.61,437.47) --
+ (156.67,436.50) --
+ (156.03,433.86) --
+ (156.45,427.88) --
+ (161.11,422.33) --
+ (162.38,416.49) --
+ (164.60,411.21) --
+ (166.50,403.15) --
+ (167.35,405.10) --
+ (168.83,404.54) --
+ (172.42,403.43) --
+ (168.93,402.04) --
+ (168.40,400.65) --
+ (166.71,401.76) --
+ (167.66,397.04) --
+ (169.57,397.59) --
+ (170.41,397.45) --
+ (171.89,396.90) --
+ (169.57,394.95) --
+ (170.94,392.45) --
+ (170.10,388.98) --
+ (168.93,388.70) --
+ (168.72,393.56) --
+ (167.88,395.09) --
+ (167.66,387.31) --
+ (170.20,386.34) --
+ (172.63,386.62) --
+ (173.59,386.62) --
+ (179.51,385.92) --
+ (180.04,384.39) --
+ (178.66,385.23);
+
+\path[draw=drawColor,line width= 1.6pt,line join=round,line cap=round] (298.68,379.67) --
+ (298.04,386.48) --
+ (296.78,389.12) --
+ (296.88,390.09) --
+ (296.88,392.73) --
+ (296.99,452.34);
+\coordinate (humBay) at (165.21,253.29);
+\coordinate (longView) at (187.34,383.33);
+\coordinate (coosBay) at (163.81,316.15);
+\coordinate (sfBay) at (197.36,180.27);
+\end{scope}
diff --git a/vignettes/img/Rlogo.png b/vignettes/img/Rlogo.png
new file mode 100644
index 0000000..bb31b84
Binary files /dev/null and b/vignettes/img/Rlogo.png differ
diff --git a/vignettes/img/plotmathDefault.pdf b/vignettes/img/plotmathDefault.pdf
new file mode 100644
index 0000000..5fe6a55
Binary files /dev/null and b/vignettes/img/plotmathDefault.pdf differ
diff --git a/vignettes/img/plotmathTikz.pdf b/vignettes/img/plotmathTikz.pdf
new file mode 100644
index 0000000..a9c94e4
Binary files /dev/null and b/vignettes/img/plotmathTikz.pdf differ
diff --git a/vignettes/img/xelatexEx.pdf b/vignettes/img/xelatexEx.pdf
new file mode 100644
index 0000000..e67f108
Binary files /dev/null and b/vignettes/img/xelatexEx.pdf differ
diff --git a/vignettes/refs.bib b/vignettes/refs.bib
new file mode 100644
index 0000000..d5bf938
--- /dev/null
+++ b/vignettes/refs.bib
@@ -0,0 +1,54 @@
+%% This BibTeX bibliography file was created using BibDesk.
+%% http://bibdesk.sourceforge.net/
+
+
+%% Created for Charles Sharpsteen at 2009-07-25 14:25:30 -0700
+
+
+%% Saved with string encoding Unicode (UTF-8)
+
+
+
+ at article{peng2006,
+ Author = {Roger D. Peng},
+ Date-Added = {2009-07-24 17:12:20 -0700},
+ Date-Modified = {2009-07-25 14:25:30 -0700},
+ Journal = {R News},
+ Number = {4},
+ Pages = {19--24},
+ Title = {Interacting with data using the filehash package},
+ Url = {\url{http://CRAN.R-project.org/doc/Rnews/}},
+ Volume = {6},
+ Year = {2006},
+ Bdsk-Url-1 = {http://CRAN.R-project.org/doc/Rnews/}}
+
+ at misc{murrellTex,
+ Author = {Paul Murrell},
+ Date-Added = {2009-07-24 16:54:42 -0700},
+ Date-Modified = {2009-07-24 17:11:06 -0700},
+ Howpublished = {\url{http://www.stat.auckland.ac.nz/~paul/R/CM/CMR.html}},
+ Title = {{Using Computer Modern Fonts in R Graphics}},
+ Year = {2005}}
+
+ at manual{rintern2009,
+ Author = {{R Development Core Team}},
+ Date-Added = {2009-07-24 16:50:20 -0700},
+ Date-Modified = {2009-07-24 16:53:11 -0700},
+ Title = {R Internals: Version 2.9.1},
+ Year = {2009}}
+
+ at manual{tantau2008,
+ Author = {Till Tantau},
+ Date-Added = {2009-07-24 16:46:57 -0700},
+ Date-Modified = {2009-07-24 16:50:08 -0700},
+ Month = {Febuary},
+ Title = {The TikZ and PGF Packages: Manual for version 2.00},
+ Year = {2008}}
+
+ at manual{urbanek2013,
+ title = {png: Read and write PNG images},
+ author = {Simon Urbanek},
+ note = {R package version 0.1-7},
+ url = {http://www.rforge.net/png/},
+ year = {2013},
+}
diff --git a/vignettes/sweavetolst.sty b/vignettes/sweavetolst.sty
new file mode 100644
index 0000000..fc95adc
--- /dev/null
+++ b/vignettes/sweavetolst.sty
@@ -0,0 +1,132 @@
+\RequirePackage{verbatim}
+\RequirePackage{xstring}
+\RequirePackage{listings}
+% Source code formatting macros
+\lstloadlanguages{R}
+\lstset{columns=fullflexible}
+
+\lstdefinestyle{sweavechunk}{
+ language = R,
+ basicstyle=\ttfamily,
+ % The hacked version of the Sweave output function inserts these tags
+ % around each output portion- we can grab them and apply formatting
+ % to everything inside.
+ moredelim=[is][\color{gray}]
+ {Swe at veBeginOutput}
+ {Swe at veEndOutput},
+ moredelim=[is][]
+ {Swe at veBeginInput}
+ {Swe at veEndInput},
+ showstringspaces = false,
+ upquote = false,
+ commentstyle = {\color{blue!70}\itshape}
+}
+
+
+% Re-define and customize the Schunk environment. Tasks to perform:
+%
+% * Capture all output using a verbatim environment and pipe it to a
+% temporary file.
+%
+% * Re-define Schunk to execute the above to steps and then read in the
+% final result using lstinputlisting.
+
+% We need to allocate some TeX variables
+\newwrite\sweave at tmpout % For writing output
+\newif\ifsweave at skipline % For skipping line processing after reading a delimiter
+\newif\ifsweave at outputready % For determining when a line is ready to be written
+\newtoks\sweave at linebuffer % For holding output lines before they are written
+
+% These macros help fill and manage the output buffer.
+\def\sweave at addtobuffer#1{% For appending to the contents of a token list.
+ % Taken from TeX by Topic
+ \toks0={#1} % Store the string to be added in a temporary buffer
+ % Construct a command that sets the line buffer equal to the contents of it's
+ % self plus the temporary buffer.
+ \edef\act{\noexpand\sweave at linebuffer={\the\sweave at linebuffer \the\toks0}}%
+ % Execute that command.
+ \act%
+}
+
+% This macro will add a line of code read from a temp file to the buffer.
+\def\sweave at addoutput#1{%
+ % expandafter is necessary to ensure #1 gets expanded before being appended to
+ % the buffer. Otherwise we get the name of the macros storing the line of
+ % code instead of the line of code.
+ \expandafter\sweave at addtobuffer\expandafter{#1}%
+ \sweave at outputreadytrue % The buffer now has code inside it for writing.
+}
+
+% This macro will write out the contents of the buffer and reset it. The
+% parameter #1 contains the file that should be written to.
+\def\sweave at flushbuffer#1{%
+ \immediate\write#1{\the\sweave at linebuffer}%
+ \sweave at linebuffer={}%
+ \sweave at outputreadyfalse%
+}
+
+% Verbatim redefines the catcodes of common LaTeX special characters so that it
+% can capture them. However, this means we can't match against patterns like
+% \begin{Sinput} that are defined outside of a environment where Verbatim has
+% altered catcodes. For some reason use of indentation will throw a wrench into
+% the definitions below.
+\begingroup
+\let\do\@makeother
+\catcode`\|=0 \catcode`[=1 \catcode`]=2
+|dospecials
+|gdef|sweave at beginsinput[\begin{Sinput}]
+|gdef|sweave at endsinput[\end{Sinput}]
+|gdef|sweave at beginsoutput[\begin{Soutput}]
+|gdef|sweave at endsoutput[\end{Soutput}]
+|endgroup
+
+% This macro initiates a verbatim environment that writes it's contents
+% to a temporary file.
+\def\sweave at startcapture{%
+ \immediate\openout\sweave at tmpout=\jobname.lstin\relax%
+ \begingroup%
+ \def\verbatim at nolig@list{}%
+ \def\verbatim at processline{%
+ \edef\sweave at codeline{\the\verbatim at line}%
+ \IfBeginWith{\sweave at codeline}{\sweave at beginsinput}%
+ {\sweave at addtobuffer{Swe at veBeginInput}\sweave at skiplinetrue}%
+ {}%
+ \IfBeginWith{\sweave at codeline}{\sweave at endsinput}%
+ {\sweave at addtobuffer{Swe at veEndInput}\sweave at skiplinetrue}%
+ {}%
+ \IfBeginWith{\sweave at codeline}{\sweave at beginsoutput}%
+ {\sweave at addtobuffer{Swe at veBeginOutput}\sweave at skiplinetrue}%
+ {}%
+ \IfBeginWith{\sweave at codeline}{\sweave at endsoutput}%
+ {\sweave at addtobuffer{Swe at veEndOutput}\sweave at skiplinetrue}%
+ {}%
+ % Now process the line
+ \ifsweave at skipline%
+ \sweave at skiplinefalse%
+ \else%
+ \ifsweave at outputready%
+ \sweave at flushbuffer{\sweave at tmpout}%
+ \fi%
+ \sweave at addoutput{\sweave at codeline}%
+ \fi%
+ }%
+ \let\do\@makeother\dospecials\catcode`\^^M\active
+ \verbatim at start%
+}
+
+% This macro stops the verbatim environment closes the temporary file.
+\def\sweave at stopcapture{%
+ \sweave at flushbuffer{\sweave at tmpout}% Write out last line
+ \endgroup%
+ \immediate\closeout\sweave at tmpout%
+}
+
+% Here we re-define the Schunk environment declared by Sweave.sty
+\def\Schunk{\sweave at startcapture}
+\def\endSchunk{%
+ \sweave at stopcapture%
+ \tikzCodeInput[listing style=sweavechunk]{\jobname.lstin}%
+}
+
+\endinput
+
diff --git a/vignettes/tikzCodeBlock.sty b/vignettes/tikzCodeBlock.sty
new file mode 100644
index 0000000..76e9cde
--- /dev/null
+++ b/vignettes/tikzCodeBlock.sty
@@ -0,0 +1,395 @@
+% Copyright (c) 2009-2012 by Charlie Sharpsteen
+% Some rights reserved.
+%
+% Redistribution and use in source and binary forms of the software as well
+% as documentation, with or without modification, are permitted provided
+% that the following conditions are met:
+%
+% * Redistributions of source code must retain the above copyright
+% notice, this list of conditions and the following disclaimer.
+%
+% * Redistributions in binary form must reproduce the above
+% copyright notice, this list of conditions and the following
+% disclaimer in the documentation and/or other materials provided
+% with the distribution.
+%
+% * The names of the contributors may not be used to endorse or
+% promote products derived from this software without specific
+% prior written permission.
+%
+% THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+% CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
+% NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+% OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+% PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+% LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+% SOFTWARE AND DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+% DAMAGE.
+
+
+% =============================================================================
+%
+% tikzCodeBlock.sty
+%
+% =============================================================================
+% A nicely styled container for multipage code listings. Look and feel inspired
+% by SyntaxHighlighter (although this is just a pale imitation):
+%
+% http://alexgorbatchev.com/SyntaxHighlighter
+%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{tikzCodeBlock}[2012/02/09 v0.3 Multipage listings set inside TikZ nodes]
+
+\RequirePackage{tikz}
+\usetikzlibrary{positioning}
+
+\RequirePackage{framed}
+\RequirePackage{listings}
+
+
+% We start off defining a new node shape to hold our code chunks.
+% It has a couple of extra options when it comes to background color
+% and such.
+
+% Shape 'code node'
+%
+% Inherits everything from rectangle except the behind background path.
+%
+% Adapted from Texample:
+% http://www.texample.net/tikz/examples/rectangle-node-with-diagonal-fill/
+%
+% Contributed by Mark Wibrow- the guy who designed the PGF math engine
+% and made most of the stock node shapes.
+%
+\pgfdeclareshape{code node}
+{
+ % This bit from \pgflibarayshapes.code.tex
+ \inheritsavedanchors[from=rectangle]
+ \inheritanchorborder[from=rectangle]
+ \inheritanchor[from=rectangle]{north}
+ \inheritanchor[from=rectangle]{north west}
+ \inheritanchor[from=rectangle]{north east}
+ \inheritanchor[from=rectangle]{center}
+ \inheritanchor[from=rectangle]{west}
+ \inheritanchor[from=rectangle]{east}
+ \inheritanchor[from=rectangle]{mid}
+ \inheritanchor[from=rectangle]{mid west}
+ \inheritanchor[from=rectangle]{mid east}
+ \inheritanchor[from=rectangle]{base}
+ \inheritanchor[from=rectangle]{base west}
+ \inheritanchor[from=rectangle]{base east}
+ \inheritanchor[from=rectangle]{south}
+ \inheritanchor[from=rectangle]{south west}
+ \inheritanchor[from=rectangle]{south east}
+
+ \inheritbackgroundpath[from=rectangle]
+ \inheritbeforebackgroundpath[from=rectangle]
+ \inheritbehindforegroundpath[from=rectangle]
+ \inheritforegroundpath[from=rectangle]
+ \inheritbeforeforegroundpath[from=rectangle]
+
+ % Now do the background filling.
+ \behindbackgroundpath{%
+ % \southwest and \northeast defined by rectangle, but
+ % (somewhat annoyingly) not \southeast and \northwest
+ % so use this workaround.
+ \pgfextractx{\pgf at xa}{\southwest}%
+ \pgfextracty{\pgf at ya}{\southwest}%
+ \pgfextractx{\pgf at xb}{\northeast}%
+ \pgfextracty{\pgf at yb}{\northeast}%
+
+ % New code here. We want to draw a bar 4 ex wide to lie
+ % under the line numbers. So we define two points that
+ % are 7 ex to the left of the southwest and northwest corners.
+ \def\pgf at numberstripe@southwest{%
+ \pgfpointadd{\southwest}%
+ {\pgfpoint{\pgf at codestripe@width}{0}}%
+ }
+ \def\pgf at numberstripe@northwest{%
+ \pgfpointadd{\pgfpoint{\pgf at xa}{\pgf at yb}}%
+ {\pgfpoint{\pgf at codestripe@width}{0}}%
+ }
+ % Now we draw the code bar.
+ \pgfpathmoveto{\southwest}%
+ \pgfpathlineto{\pgf at numberstripe@southwest}%
+ \pgfpathlineto{\pgf at numberstripe@northwest}%
+ \pgfpathlineto{\pgfpoint{\pgf at xa}{\pgf at yb}}%
+ \pgfpathclose
+ % Now fill it with a nice light grey.
+ \color{\pgf at codestripe@color}%
+ \pgfusepath{fill}%
+ % Now for the rest of the node.
+ \pgfpathmoveto{\pgf at numberstripe@southwest}%
+ \pgfpathlineto{\pgfpoint{\pgf at xb}{\pgf at ya}}%
+ \pgfpathlineto{\northeast}%
+ \pgfpathlineto{\pgf at numberstripe@northwest}%
+ \pgfpathclose
+ %
+ \color{\pgf at codebody@color}%
+ \pgfusepath{fill}
+ }
+}
+
+%--------------------- Begin User Level Shape Options -----------------
+
+% Default widths.
+\def\pgf at codestripe@width{0pt}
+
+% Default color values
+\def\pgf at codebody@color{white}
+\def\pgf at codestripe@color{gray!30}
+
+% Use these with PGF
+\def\pgfsetcodestripecolor#1{\def\pgf at codestripe@color{#1}}%
+\def\pgfsetcodestripewidth#1{\def\pgf at codestripe@width{#1}}%
+\def\pgfsetcodebodycolor#1{\def\pgf at codebody@color{#1}}%
+
+% Use these with TikZ
+\tikzoption{codestripe color}{\pgfsetcodestripecolor{#1}}
+\tikzoption{codestripe width}{\pgfsetcodestripewidth{#1}}
+\tikzoption{codebody color}{\pgfsetcodebodycolor{#1}}
+
+%--------------------- End User Level Shape Options -------------------
+
+%===============================================
+
+%--------------------- Begin Internal Package Macros ------------------
+
+\newcommand\tikzCode at setupKeys{%
+ % This command leverages the pgfkeys package,
+ % included by tikz, to set up handling for options
+ % of the form [key=value]
+ \pgfkeys{/tikzCode/title/.store in=\tikzCode at codeNodeTitle,
+ /tikzCode/footer/.store in=\tikzCode at codeNodeFooter,
+ /tikzCode/listing style/.store in=\tikzCode at listingStyle,
+ /tikzCode/code body/.style={/tikzCode/defaults/code body},
+ /tikzCode/code title body/.style={/tikzCode/defaults/code title body},
+ /tikzCode/code title outline/.style={/tikzCode/defaults/code title outline},
+ /tikzCode/code footer/.style={/tikzCode/defaults/code footer},
+ }
+}
+
+
+% This macro sets a chunk of text inside a specialized node.
+\newcommand{\tikzCode at place@codenodebody}[1]{%
+ \node[/tikzCode/code body] (code node body) {#1};
+}
+
+% This macro adds a header.
+\newcommand{\tikzCode at place@codenodetitle}{%
+ \node[/tikzCode/code title body] (code node title) {\tikzCode at codeNodeTitle};
+ \draw[/tikzCode/code title outline] (code node title.south west) --
+ (code node title.south east) --
+ (code node title.north east) --
+ (code node title.north west) --
+ cycle;
+}
+
+% And this one adds a footer.
+\newcommand{\tikzCode at place@codenodefooter}{%
+ \node[/tikzCode/code footer] {\tikzCode at codeNodeFooter};
+}
+
+
+% This macro outputs a singleton frame.
+\newcommand{\tikzCode at place@singleframe}[1]{%
+ \begin{tikzpicture}%
+
+ \tikzCode at place@codenodebody{#1}
+
+ \ifx \tikzCode at codeNodeTitle \undefined
+ % Nothin' to do.
+ \relax
+ \else
+ \tikzCode at place@codenodetitle
+ \fi
+
+ \ifx \tikzCode at codeNodeFooter \undefined
+ \relax
+ \else
+ \tikzCode at place@codenodefooter
+ \fi
+
+ \end{tikzpicture}%
+}
+
+
+% This macro outputs the first of a series of frames.
+\newcommand{\tikzCode at place@firstframe}[1]{%
+ \begin{tikzpicture}%
+
+ \tikzCode at place@codenodebody{#1}
+
+ \ifx \tikzCode at codeNodeTitle \undefined
+ % Nothin' to do.
+ \relax
+ \else
+ \tikzCode at place@codenodetitle
+ \fi
+
+ \end{tikzpicture}%
+}
+
+% This macro outputs the middle portions of a series of frames.
+\newcommand{\tikzCode at place@middleframe}[1]{%
+ \begin{tikzpicture}%
+
+ \tikzCode at place@codenodebody{#1}
+
+ \end{tikzpicture}%
+}
+
+% This macro outputs the last of a series of frames.
+\newcommand{\tikzCode at place@lastframe}[1]{%
+ \begin{tikzpicture}%
+
+ \tikzCode at place@codenodebody{#1}
+
+ \ifx \tikzCode at codeNodeFooter \undefined
+ \relax
+ \else
+ \tikzCode at place@codenodefooter
+ \fi
+
+ \end{tikzpicture}%
+}
+
+% This macro patches our code into the framed package.
+\newcommand{\tikzCode at set@framedcommands}{%
+ \def\FrameCommand{\tikzCode at place@singleframe}%
+ \def\FirstFrameCommand{\tikzCode at place@firstframe}%
+ \def\MidFrameCommand{\tikzCode at place@middleframe}%
+ \def\LastFrameCommand{\tikzCode at place@lastframe}%
+}
+
+
+%--------------------- End Internal Package Macros -----------------------
+
+% Default Code Node Style definitions.
+\tikzset{
+ /tikzCode/defaults/code body/.style={
+ % The code node is a homebrewed shape- several things can
+ % possibly go pear shaped with it- for example, adding rounded
+ % corners causes things to go whacky. Also- don't use the fill
+ % command :P
+ shape = code node,
+ draw = blue!50,
+ thick,
+ codebody color = blue!10,
+ outer sep = 0pt,
+ inner sep = 1ex,
+ % Subtract off 2 * inner sep and line width
+ text width = {\linewidth - 2ex - 1.6pt}
+ },
+ /tikzCode/defaults/code title body/.style={
+ fill = white,
+ inner sep = 1ex,
+ outer sep = 0pt,
+ % Explicitly unset the text width for the title node so that it always fits
+ % its self to the width of the title.
+ text width = ,
+ right = 0pt of code node body.north west,
+ anchor = base west
+ },
+ /tikzCode/defaults/code title outline/.style={
+ draw = blue!50,
+ thick
+ },
+ /tikzCode/defaults/code footer/.style={
+ draw = blue!50,
+ thick,
+ fill = white,
+ inner sep = 1ex,
+ outer sep = 0pt,
+ % Explicitly unset the text width for the footer node so that it always fits
+ % its self to the width of the title.
+ text width = ,
+ above = 0pt of code node body.south,
+ anchor = base
+ }
+}
+
+
+% -----------------------------------------------------------------------------
+% User-Level Commands
+% -----------------------------------------------------------------------------
+
+% tikzCodeBlock
+% =============
+% This environment captures contents verbatim, processes the text with the
+% listings package, pagebreaks the results into chunks using the framed
+% package, then sets each chunk in a TikZ node.
+%
+% Defined using `\lstnewenvironment` so that the listings package knows when to
+% stop capturing input verbatim.
+\lstnewenvironment{tikzCodeBlock}[1][]{%
+ % Process environment options.
+ \tikzCode at setupKeys
+ % Shift the key directory to our namespace.
+ \pgfkeys{ /tikzCode/.cd, #1 }%
+ \ifx \tikzCode at listingStyle \undefined
+ \lstset{resetmargins = true}%
+ \else
+ \lstset{style = \tikzCode at listingStyle, resetmargins = true}%
+ \fi
+ % Start the framed environment.
+ \tikzCode at set@framedcommands
+ \MakeFramed{\FrameRestore}%
+}%
+{\endMakeFramed}
+
+
+% tikzCodeNode
+% ============
+% This is like the tikzCodeBlock environment except that it does use any
+% functionality from the framed package to produce multiple chunks that break
+% accross pages. Useful for creating listings that do not break and that can be
+% embedded inside another tikzPicture.
+%
+% If this environment is embedded inside another TikZ node, the text width
+% __MUST BE SET__ for that node. This is due to the use of `\vskip\topsep`.
+\lstnewenvironment{tikzCodeNode}[1][]{%
+ % Process environment options.
+ \tikzCode at setupKeys
+ % Shift the key directory to our namespace.
+ \pgfkeys{ /tikzCode/.cd, #1 }%
+ \ifx \tikzCode at listingStyle \undefined
+ \lstset{resetmargins = true}%
+ \else
+ \lstset{style = \tikzCode at listingStyle, resetmargins = true}%
+ \fi
+ % Collect listings output into a box for insertion into a TikZ picture
+ \setbox\@tempboxa=\vbox\bgroup\color at setgroup
+}%
+{\color at endgroup\egroup\vskip\topsep\noindent\tikzCode at place@singleframe{\box\@tempboxa}}
+
+
+% tikzCodeInput
+% =============
+% This is like the tikzCodeBlock environment except that it reads input from a
+% file.
+\newcommand{\tikzCodeInput}[2][]{%
+ {% use a separate namespace
+ % Process environment options.
+ \tikzCode at setupKeys
+ % Shift the key directory to our namespace.
+ \pgfkeys{ /tikzCode/.cd, #1 }%
+ \tikzCode at set@framedcommands
+ % Start the framed environment.
+ \MakeFramed{\FrameRestore}%
+ \ifx \tikzCode at listingStyle \undefined
+ \lstinputlisting[resetmargins = true]{#2}%
+ \else
+ \lstinputlisting[style = \tikzCode at listingStyle, resetmargins = true]{#2}%
+ \fi
+ \endMakeFramed
+ }
+}
+
+
+% Make sure LaTeX knows we're done here.
+\endinput
diff --git a/vignettes/tikzDevice-concordance.tex b/vignettes/tikzDevice-concordance.tex
new file mode 100644
index 0000000..4cd727e
--- /dev/null
+++ b/vignettes/tikzDevice-concordance.tex
@@ -0,0 +1,4 @@
+\Sconcordance{concordance:tikzDevice.tex:tikzDevice.Rnw:%
+1 10 1 49 0 1 40 19 1 1 2 1 21 167 1 1 5 14 1 1 5 390 1 1 2 199 1 %
+3 0 80 1 3 0 37 1 3 0 85 1 3 0 2 1 1 17 95 1 3 0 60 1 3 0 94 1 15 %
+0 36 1 14 0 13 1 31 0 736 1}
diff --git a/vignettes/tikzDevice.Rnw b/vignettes/tikzDevice.Rnw
new file mode 100644
index 0000000..0770e25
--- /dev/null
+++ b/vignettes/tikzDevice.Rnw
@@ -0,0 +1,2129 @@
+% !TEX TS-program = knitr
+% \VignetteIndexEntry{The tikzDevice Package}
+% \VignetteDepends{tikzDevice}
+% \VignetteEngine{knitr::knitr}
+
+\documentclass[10pt,oneside,letterpaper,article]{memoir}
+\usepackage[utf8]{inputenc}
+\usepackage{tikzDeviceVignette}
+
+
+<<setup,echo=FALSE,results='hide'>>=
+ library(tikzDevice)
+ if( !file.exists('figs') ){dir.create( 'figs' )}
+
+ options(tikzMetricsDictionary='.tikzMetrics')
+
+ knitr::opts_chunk$set(
+ echo=FALSE,
+ fig.path='figs/fig',
+ message=FALSE,
+ width = 100,
+ comment = NA
+ )
+ knitr::knit_hooks$set(
+ source = function(x, options) {
+ paste("\\vspace{-1ex}",
+ "\\begin{tikzCodeBlock}[listing style=sweavechunk]",
+ paste(x, collapse = '\n'),
+ "\\end{tikzCodeBlock}\n\n", sep = '\n')
+ },
+ output = function(x, options) {
+ paste("\\vspace{-2ex}",
+ "\\begin{Verbatim}[frame=single]",
+ sub("\n+$", "", paste(x, collapse = '\n')),
+ "\\end{Verbatim}",
+ "",
+ sep = '\n')
+ },
+ warning = function(x, options) {
+ paste("\\vspace{-2ex}",
+ "\\begin{Verbatim}[frame=single,formatcom=\\color{warningcolor}]",
+ sub("\n+$", "", paste(strwrap(x, width = options$width),
+ collapse = '\n')),
+ "\\end{Verbatim}",
+ "",
+ sep = '\n')
+ },
+ chunk = function(x, options) x
+ )
+@
+
+
+
+\title{TikZDevice: LaTeX Graphics for R}
+\author{Charlie Sharpsteen and Cameron Bracken}
+\date{\Sexpr{strftime(read.dcf(system.file('DESCRIPTION', package = 'tikzDevice'), fields = 'Date'), format = '%B %d, %Y')}}
+\gdef\packageURL{\url{https://github.com/yihui/tikzDevice}}
+\gdef\packageVersion{\Sexpr{tikzDevice:::getTikzDeviceVersion()}}
+
+% Use the hyperref package to fill in PDF metadata.
+\hypersetup{
+ pdftitle=\thetitle,
+ pdfauthor=\theauthor,
+ pdfsubject={Manual for Version: \packageVersion, \thedate}
+}
+
+
+\begin{document}
+% -----------------------------------------------------------------------------
+% Cover Page
+% -----------------------------------------------------------------------------
+<<tikzTitlePlot,results='hide'>>=
+ tikz('figs/titlePlot.tex',width=4,height=4)
+
+ x <- seq(-4.5,4.5,length.out=100)
+ y <- dnorm(x)
+
+ xi <- seq(-2,2,length.out=30)
+ yi <- dnorm(xi)
+
+ plot(x,y,type='l',col='blue',ylab='$p(x)$',xlab='$x$')
+ lines(xi,yi,type='s')
+ lines(range(xi),c(0,0))
+ lines(xi,yi,type='h')
+ title(main="$p(x)=\\frac{1}{\\sqrt{2\\pi}}e^{-\\frac{x^2}{2}}$")
+ int <- integrate(dnorm,min(xi),max(xi),subdivisions=length(xi))
+ text(2.8,0.3,paste(
+ "\\small$\\displaystyle\\int_{",min(xi),"}^{",max(xi),"}p(x)dx",
+ "\\approx",round(int[['value']],3),'$',sep=''))
+
+ dev.off()
+@
+
+\begin{titlingpage}
+ % NOTE:
+ % Most dimensions and positions in this cover page were optimized for US
+ % Letter stock size and so are given in inches. It may be useful to revise
+ % this one day so that the layout is a bit more scalable.
+ %
+ % Use remember picture and overlay so that `current page` coordinates can be
+ % accessed.
+ \begin{tikzpicture}[remember picture, overlay]
+ % Title and Info
+ % --------------
+ {\fontsize{60}{36}
+ \node[below right = 0.5em of current page.north west,
+ anchor = north east,
+ rotate = 90,
+ outer sep = 0pt,
+ inner sep = 0pt
+ ]
+ (title)
+ {\bfseries{\fontsize{36}{36}\selectfont\color{red}\TikZ}Device};
+ }
+
+ \draw[line width = 5pt] ([xshift = 7.5pt]title.base west) -- ([xshift = 7.5pt]title.base east);
+
+ % Have to split subtitle, authors, etc. into several nodes because
+ % apparently TikZ can't deal with font change commands and line breaks
+ % existing in the same node. A bit of a pain because the value of
+ % \baselineskip has to be twaddled by wrapping some \nodes in font
+ % size descriptors.
+ \node[right = 12.5pt of title.base east,
+ anchor = north west,
+ align = left,
+ font = {\Huge\bfseries}
+ ]
+ (subtitle)
+ {\LaTeX\ Graphics for \lang{R}};
+
+ {\huge
+ \node[below = \baselineskip of subtitle.base west,
+ anchor = north west,
+ align = left,
+ font = {\LARGE}
+ ]
+ (authors)
+ {%
+ Charlie Sharpsteen\\
+ Cameron Bracken%
+ };
+ }
+
+ \node[right = 12.5pt of title.base west,
+ anchor = base west,
+ align = left
+ ]
+ (packageInfo)
+ {%
+ \thedate\\
+ \packageURL%
+ };
+
+ {\LARGE
+ \node[above = \baselineskip of packageInfo.north west,
+ anchor = base west,
+ align = left,
+ font = {\LARGE\bfseries}
+ ]
+ (version)
+ {Version: \packageVersion};
+ }
+
+
+ % Logo and Plot
+ % -------------
+
+ % Scaling the R logo to a width of 4.75 in was determed through trial and
+ % error. The center of the image is shifted relative to the bottom right
+ % corner of the page such that the point where the right leg of the "R"
+ % glyph intersects the inside of the halo is sitting over the corner of the
+ % page.
+ \node[inner sep = 0pt,
+ above left = 0.78in and 1.48in of current page.south east,
+ anchor = center
+ ]
+ (Rlogo)
+ {\includegraphics[width=4.75in]{img/Rlogo}};
+
+ % This node contains an embedded `tikzpicture` environment produced by the
+ % tikzTitlePlot code block.
+ \node[anchor = north east,
+ inner sep = 0pt
+ ]
+ (titlePlot) at (current page.north east)
+ {\input{figs/titlePlot.tex}};
+
+
+ % Connect Logo and Plot
+ % ---------------------
+ \node[below left = 0.325\stockheight and 0.325\stockwidth of current page.center]
+ (midPointA) {};
+
+ \node[below right = 0.125\stockheight and 0.125\stockwidth of current page.center]
+ (midPointB) {};
+
+ \tikzset{
+ grow bigger/.style={decoration = {
+ shape backgrounds,
+ shape = dart,
+ shape scaled,
+ shape start size = 0.125cm,
+ shape end size = 0.5cm,
+ shape sep = {.25cm, between borders}
+ }}
+ }
+
+ \path[decorate, grow bigger, fill = black!25]
+ plot[smooth, tension = 1]
+ coordinates{(Rlogo.190) (midPointA) (midPointB) (titlePlot.south)};
+
+ \end{tikzpicture}
+\end{titlingpage}
+
+
+% -----------------------------------------------------------------------------
+% Table of Contents
+% -----------------------------------------------------------------------------
+\frontmatter
+ \tableofcontents*
+
+
+\mainmatter
+
+
+% -----------------------------------------------------------------------------
+% Chapter 1: Introduction
+% -----------------------------------------------------------------------------
+\chapter{Introduction}
+
+The \pkg{tikzDevice} package provides a graphics output device for \lang{R} that
+records plots in a \LaTeX -friendly format. The device transforms plotting
+commands issued by \lang{R} functions into \LaTeX\ code blocks. When included in a
+paper typeset by \LaTeX , these blocks are interpreted with the help of
+TikZ---a graphics package for \TeX\ and friends written by Till Tantau. By
+allowing \LaTeX\ to handle typesetting of text in \lang{R} plots along with the
+rest of the text in the paper the full power of \TeX\ is available to the
+\lang{R} user. There are also no discontinuities in font selection and
+typesetting as demonstrated by a comparison between \autoref{fig:pdf-example}
+and \autoref{fig:tikz-example}.
+
+
+% FIXME:
+% This example is biased. It would be best to choose a TeX font for which AFM
+% metrics are available and show how much of a pain in the ass it is to use the
+% R `Type1Font` function vs. how easy it is to set tikzDevice options and let
+% TeX do the heavy lifting.
+\begin{figure}[!hb]
+ \centering
+
+ \begin{minipage}[t]{0.4\linewidth}
+ \begin{tikzCodeBlock}[listing style=sweavechunk,
+ code body/.append style={codebody color=white}]
+pdf('pdf-example.pdf',
+ width = 3.25, height = 3.25)
+plot(1, 1, main = 'Hello!')
+dev.off()
+ \end{tikzCodeBlock}
+
+<<pdf-example,echo=FALSE,results='hide'>>=
+ pdf('figs/pdf-example.pdf', width = 3.25, height = 3.25)
+ plot(1, 1, main = 'Hello!', ps = 10)
+ dev.off()
+@
+ \includegraphics{figs/pdf-example}
+ \caption{Output from \code{pdf()}}
+ \label{fig:pdf-example}
+ \end{minipage}
+ \hspace{0.1\linewidth}
+ \begin{minipage}[t]{0.4\linewidth}
+ \begin{tikzCodeBlock}[listing style=sweavechunk,
+ code body/.append style={codebody color=white}]
+tikz('tikz-example.tex',
+ width = 3.25, height = 3.25)
+plot(1, 1, main = 'Hello \\TeX !')
+dev.off()
+ \end{tikzCodeBlock}
+
+<<tikz-example,echo=FALSE,results='hide'>>=
+ tikz('figs/tikz-example.tex', width = 3.25, height = 3.25)
+ plot(1, 1, main = 'Hello \\TeX !')
+ dev.off()
+@
+ \input{figs/tikz-example.tex}
+ \caption{Output from \code{tikz()}}
+ \label{fig:tikz-example}
+ \end{minipage}
+\end{figure}
+
+
+This document is divided into three parts. \autoref{part:usage} describes the
+package functionality and provides example usage. Besides the \lang{R}
+environment, use of the \TikZ\ device requires the user to have a
+working \LaTeX{} compiler along with an installed version of the \TikZ{}
+package---version 2.00 or greater. \autoref{part:installation} of this
+documentation offers suggestions on how to get these dependencies installed and
+working properly.
+
+\autoref{part:implementation} is intended for those who are curious as to the
+details of how this package is implemented. This part attempts to explain how
+the \pkg{tikzDevice} package does the things that it does and why it chooses to
+do them that way. The authors have attempted to write this part of the
+documentation in a way that is accessible to users as well as developers. This
+information is provided in the hope that the \pkg{tikzDevice} may serve as a
+case study for creating new \lang{R} graphics devices. This part of the
+documentation may also help those considering undertaking the transition from
+casual package-building to full-on hacking of the \lang{R} internals.
+
+\section{Acknowledgements}
+
+This package would not have been possible without the hard work and ingenuity
+of many individuals. This package straddles the divide between two great open
+source communities---the \lang{R} programming language and the \TeX{}
+typesetting system. It is our hope that this work will make it easier for users
+to leverage the strengths of both systems.
+
+First off, we would like to thank the \lang{R} Core Team for creating such a
+wonderful, open and flexible programming environment. Compared to other
+languages we have used, creating packages and extensions for \lang{R} has
+always been a liberating experience.
+
+This package started as a fork of the Pic\TeX\ device created by Valerio Aimale
+which is part of the \lang{R} core graphics system. Without access to this
+simple, compact example of implementing a graphics device we likely would have
+abandoned the project in its infancy. We would also like to thank Paul Murrell
+for all of his work on the \lang{R} graphics system and especially for his
+research and documentation concerning the differences between the font systems
+used by \TeX{} and \lang{R}.
+
+This package also owes its existence to Friedrich Leisch's work on the
+\pkg{Sweave} system and Roger D. Peng's \pkg{cacheSweave} extension. These
+two tools got us interested in the concept of Literate Programming and
+development of this package was driven by our desire to achieve a more seamless
+union between our reports and our code.
+
+The performance of this package is also enhanced by the database capabilities
+provided by Roger D. Peng's \pkg{filehash} package. Without this package, the
+approach to calculating font metrics taken by the \pkg{tikzDevice} would be
+infeasible.
+
+Last, but certainly not least, we would like to thank Till Tantau, Mark Wibrow
+and the rest of the PGF/\TikZ\ team for creating the \LaTeX\ graphics package
+that makes the output of this device meaningful. We would also like to express
+deep appreciation for the beautiful documentation that has been created for the
+\TikZ\ system.
+
+As always, there are many more who have contributed in ways too numerous to
+list.\\[\baselineskip]
+
+\noindent Thank you!\\
+\quad{\itshape ---The tikzDevice Team}
+
+\nocite{murrellTex}
+\nocite{rintern2009}
+\nocite{tantau2008}
+\nocite{peng2006}
+
+
+\partimage{
+ \node[above left = 1in of current page.south east,
+ anchor = south east,
+ scale = 1.25
+ ]
+ % This image is generated by an example in chapter 3.
+ {\input{figs/latexEx}};
+}
+\part{Usage and Examples}
+ \label{part:usage}
+
+
+% -----------------------------------------------------------------------------
+% Chapter 2: Package Loading
+% -----------------------------------------------------------------------------
+\chapter{Loading the Package}
+
+The functions in the \pkg{tikzDevice} package are made accessible in the
+\lang{R} environment by using \code{library()}:
+
+\begin{Verbatim}[frame=single]
+library(tikzDevice)
+\end{Verbatim}
+
+\noindent Upon loading, the package will search for the following \LaTeX\ compilers:
+
+\begin{itemize}
+ \item{\hologo{pdfLaTeX}}
+ \item{\hologo{XeLaTeX}}
+ \item{\hologo{LuaLaTeX}}
+\end{itemize}
+
+Access to \LaTeX\ is essential for the device to produce output as the compiler
+is queried for font metrics when constructing plots that contain text. For more
+information on why communication between the device and \LaTeX\ is necessary,
+see \autoref{part:implementation}. The package will fail to load if
+\hologo{pdfLaTeX} cannot be located. The presence of the \hologo{XeLaTeX} and
+\hologo{LuaLaTeX} compilers is optional. When the package loads successfully,
+a startup message will be printed that looks similar to the following:
+
+\begin{Verbatim}[frame=single]
+Loading required package: filehash
+filehash: Simple key-value database (2.2 2011-07-21)
+tikzDevice: R Graphics Output in LaTeX Format (v0.7)
+ LaTeX found in the PATH using the command: pdflatex
+ XeLaTeX found in the PATH using the command: xelatex
+ LuaLaTeX found in the PATH using the command: lualatex
+\end{Verbatim}
+
+If a working \hologo{pdfLaTeX} compiler cannot be found, the \pkg{tikzDevice} package
+will fail to load and a warning message will be displayed:
+
+\begin{Verbatim}[frame=single]
+Error : .onLoad failed in loadNamespace() for 'tikzDevice', details:
+ call: fun(libname, pkgname)
+ error:
+
+An appropriate LaTeX compiler could not be found.
+Access to LaTeX is required in order for the TikZ device
+to produce output.
+
+The following places were tested for a valid LaTeX compiler:
+
+ the global option: tikzLatex
+ the environment variable: R_LATEXCMD
+ the environment variable: R_PDFLATEXCMD
+ the global option: latexcmd
+ the PATH using the command: pdflatex
+ the PATH using the command: latex
+ the PATH using the command: /usr/texbin/pdflatex
+
+...
+
+Error: loading failed
+\end{Verbatim}
+
+In this case, \pkg{tikzDevice} has done its very best to locate a working
+compiler and came up empty. If you have a working \LaTeX\ compiler, the next
+section describes how to inform the \pkg{tikzDevice} package of its location.
+For suggestions on how to obtain a \LaTeX\ compiler, see
+\autoref{part:installation}.
+
+
+\section{Options That Affect Package Behavior}
+ \label{sec:options}
+
+The \pkg{tikzDevice} package is influenced by a number of options that may be
+set locally in your \lang{R} scripts or in the \lang{R} console or globally in
+a \code{.Rprofile} file. All of the options can be set by using
+\code{options(<option> = <value>)}. These options allow for the use of custom
+\code{documentclass} declarations, \LaTeX\ packages, and typesetting engines
+(e.g. \hologo{XeLaTeX} or \hologo{LuaLaTeX}).
+
+For convenience the function \code{setTikzDefaults()} is provided which sets
+all the global options back to their original values.
+
+The proper placement of a \code{.Rprofile} file is explained in the \lang{R}
+manual page \code{?Startup}. For the details of why calling the \LaTeX\ compiler is
+necessary, see \autoref{part:implementation}.
+
+A lot of power is given to you through these global options, and with great
+power comes great responsibility. For example, if you do not include the
+\TikZ\ package in the \code{tikzLatexPackages} option then all of the string
+metric calculations will fail. Or if you use a different font when compiling
+than you used for calculating metrics, strings may be placed incorrectly.
+There are innumerable ways for packages to clash in \LaTeX\ so be aware.
+
+
+\subsection{The \pkgopt{tikzDefaultEngine} Option}
+
+This option specifies which typesetting engine the \pkg{tikzDevice} package
+will prefer. Current possible values are \code{pdftex}, \code{xetex} or
+\code{luatex} which will respectively trigger the use of the \hologo{pdfLaTeX},
+\hologo{XeLaTeX} or \hologo{LuaLaTeX} compilers.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzDefaultEngine = 'pdftex')
+\end{tikzCodeBlock}
+
+\begin{tikzCodeBlock}[title={Choosing the \TeX\ engine},listing style=sweavechunk]
+options(tikzDefaultEngine = 'xetex')
+options(tikzDefaultEngine = 'luatex')
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzLatex}, \pkgopt{tikzXelatex} and \pkgopt{tikzLualatex} Options}
+
+Specifies the location of the \LaTeX{}, \hologo{XeLaTeX} and \hologo{LuaLaTeX}
+compilers to be used by \pkg{tikzDevice}. Setting a default for this option may
+help the package locate a missing compiler:
+
+\begin{tikzCodeBlock}[title={Setting default compilers in \code{.Rprofile}},listing style=sweavechunk]
+options(tikzLatex = '/path/to/pdflatex')
+options(tikzXelatex = '/path/to/xelatex')
+options(tikzLualatex = '/path/to/lualatex')
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzMetricsDictionary} Option}
+
+When using the graphics device provided by \pkg{tikzDevice}, you may notice
+that \lang{R} appears to ``lag" or ``hang'' when commands such as \code{plot()}
+are executed. This is because the device must query the \LaTeX\ compiler for
+string widths and font metrics. For a normal plot, this may happen dozens or
+hundreds of times---hence \lang{R} becomes unresponsive for a while. The good
+news is that the \code{tikz()} code is designed to cache the results of these
+computations so they need only be performed once for each string or character.
+By default, these values are stored in a temporary cache file which is deleted
+when \lang{R} is shut down. Using the option \code{tikzMetricsDictionary}, a
+permanent cache file may be specified:
+
+\begin{tikzCodeBlock}[title={Setting a location in \code{.Rprofile} for a permanent metrics dictionary},listing style=sweavechunk]
+options(tikzMetricsDictionary = '/path/to/dictionary/location')
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzDocumentDeclaration} Option}
+
+For \code{standAlone == TRUE}, \code{tikzDocumentDeclaration} also influences the
+calculation of font metrics. If a base font size is specified as an option to
+the document class, the \pkg{tikzDevice} will use this value as the base font
+size for graphics.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzDocumentDeclaration = "\\documentclass[10pt]{article}")
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzLatexPackages}, \pkgopt{tikzXelatexPackages} and \pkgopt{tikzLualatexPackages} Options}
+
+Character vectors. These are the packages which are included when using the
+\code{standAlone} option as well as when font metrics are calculated. If you
+use additional packages that affect fonts, such as \code{mathpazo}, or
+additional \LaTeX\ macros, such as \code{amsmath}, these packages should be
+added to this list.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(
+ tikzLatexPackages = c(
+ "\\usepackage{tikz}",
+ "\\usepackage[active,tightpage]{preview}",
+ "\\PreviewEnvironment{pgfpicture}",
+ "\\setlength\\PreviewBorder{0pt}")
+ ),
+
+ tikzXelatexPackages = c(
+ "\\usepackage{tikz}\n",
+ "\\usepackage[active,tightpage,xetex]{preview}\n",
+ "\\usepackage{fontspec,xunicode}\n",
+ "\\PreviewEnvironment{pgfpicture}\n",
+ "\\setlength\\PreviewBorder{0pt}\n"
+ ),
+
+ tikzLualatexPackages = c(
+ "\\usepackage{tikz}\n",
+ "\\usepackage[active,tightpage,psfixbb]{preview}\n",
+ "\\usepackage{fontspec,xunicode}\n",
+ "\\PreviewEnvironment{pgfpicture}\n",
+ "\\setlength\\PreviewBorder{0pt}\n"
+ )
+)
+\end{tikzCodeBlock}
+
+\begin{tikzCodeBlock}[title={Adding a package that affects fonts},listing style=sweavechunk]
+options( tikzLatexPackages = c(
+ getOption( "tikzLatexPackages" ),
+ "\\usepackage{mathpazo}"
+))
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzMetricPackages} and \pkgopt{tikzUnicodeMetricPackages} Options}
+
+Character vectors. These are the extra packages which are additionally loaded
+when doing font metric calculations. As you see below, the font encoding is
+set to Type 1. This is very important so that character codes of \LaTeX\ and
+\lang{R} match up. The Unicode metric packages are used when the \hologo{XeTeX}
+or \hologo{LuaTeX} engines are in use.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(
+ tikzMetricPackages = c(
+ "\\usepackage[T1]{fontenc}\n",
+ "\\usetikzlibrary{calc}\n"
+ ),
+
+ tikzUnicodeMetricPackages = c(
+ "\\usepackage[T1]{fontenc}\n",
+ "\\usetikzlibrary{calc}\n",
+ "\\usepackage{fontspec,xunicode}\n"
+ )
+)
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzFooter} Option}
+
+A character vector. This footer is appended to the end of the figure when
+\code{standAlone==TRUE} before the \verb|\end{document}| statement.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzFooter = "")
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzSanitizeCharacters} and \pkgopt{tikzReplacementCharacters} Options}
+
+\code{tikzSanitizeCharacters} is a character vector of special \LaTeX
+characters to replace while \code{tikzReplacementCharacters} is a character
+vector containing the corresponding replacements.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(
+ tikzSanitizeCharacters = c('%','$','}','{','^','_','#','&','~'),
+ tikzReplacementCharacters = c('\\%','\\$','\\}','\\{','\\^{}','\\_{}',
+ '\\#','\\&','\\char`\\~')
+)
+\end{tikzCodeBlock}
+
+
+\subsection{The \pkgopt{tikzLwdUnit} Option}
+
+Originally, 1 unit of line width in \lang{R} was translated to 0.4~pt.
+This results in lines that are thinner than with default graphics
+or with the PDF device.
+This option controls the translation factor~-- use \code{72.27 / 96}
+for compatibility with the \lang{R} default
+(96 pixels in \lang{R} is 1 inch, which is 72.27 points in \TeX{}).
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzLwdUnit = 72.27 / 96)
+\end{tikzCodeBlock}
+
+
+\subsection{The deprecated \pkgopt{tikzRasterResolution} Option}
+
+When \code{tikz} is requested to add a raster to a graphic, the raster is
+written to a PNG file which is then included by the \LaTeX\ code.
+In the current version, the raster is always written ``as is''
+(after mirroring has been applied) using \code{png::writePNG()}
+\citep{urbanek2013}.
+No resampling or transformation of any kind are applied in this process,
+rotation and interpolation are carried out by \LaTeX.
+
+
+\subsection{The \pkgopt{tikzPdftexWarnUTF} Option}
+
+A \code{TRUE/FALSE} value that controls whether warnings are printed if
+Unicode characters are sent to a device using the \hologo{pdfTeX} engine.
+
+\begin{tikzCodeBlock}[title={Default},listing style=sweavechunk]
+options(tikzPdftexWarnUTF = TRUE)
+\end{tikzCodeBlock}
+
+
+% -----------------------------------------------------------------------------
+% Chapter 3: The tikz Function
+% -----------------------------------------------------------------------------
+\chapter{The \code{tikz} Function}
+
+\section{Description}
+
+The \code{tikz} function provides most of the functionality of the
+\pkg{tikzDevice} package. This function opens an \lang{R} graphics device that
+records plots as a series of \TikZ\ commands. The device supports many levels
+of output that range from stand-alone \LaTeX\ documents that may be compiled
+into figures to code chunks that must be incorporated into existing \LaTeX\
+documents using the \verb`\include{}` macro.
+
+
+\section{Usage}
+
+The \code{tikz} function opens a new graphics device and may be called with
+the following arguments:
+
+<<tikzArgs, code=formatR::usage(tikz), eval=FALSE>>=
+@
+
+\begin{flexlabelled}{code}{*}{0.5em}{0.5em}{*}{\leftmargin}
+ \item[file]
+ A character string indicating the desired path to the output file. It is
+ recommended, but not required, that the filename end in \code{.tex}.
+
+ \item[width]
+ The width of the output figure, in \emph{inches}.
+
+ \item[height]
+ The height of the output figure, in \emph{inches}.
+
+ \item[onefile]
+ Controls whether output should be directed to a single file containing one
+ \code{tikzpicture} environment per plot or split into multiple files each
+ containing a single \code{tikzpicture} environment.
+
+ \item[bg]
+ The starting background color for the plot.
+
+ \item[fg]
+ The starting foreground color for the plot.
+
+ \item[pointsize]
+ Base pointsize used in the LaTeX document. This option is only referenced
+ if a valid pointsize cannot be extracted from the value of
+ \code{getOption("tikzDocumentDeclaration")}. See \autoref{subsec:fontCalc}
+ for more details.
+
+ \item[lwdUnit]
+ The number of \code{pt}s in LaTeX that \code{lwd=1} in R is translated to.
+ Defaults to 0.4 (LaTeX and TikZ default); for compatibility with R default,
+ please use 72.27/96 (96 pixels in R is 1 inch, which is 72.27 points in TeX).
+ See also \autoref{sec:options}, ``Options That Affect Package Behavior.''
+
+ \item[standAlone]
+ A logical value indicating whether the resulting file should be suitable
+ for direct processing by \LaTeX.
+
+ \item[bareBones]
+ A logical value indicating whether \TikZ\ code is produced without being
+ placed within a \code{tikzpicture} environment.
+
+ \item[console]
+ Controls whether output is directed to the \lang{R} console. This is useful
+ for dumping \TikZ\ output directly into a \LaTeX\ document via sink. If
+ \code{TRUE}, the \code{file} argument is ignored. Setting \code{file=\'{}\'{}} is
+ equivalent to setting \code{console=TRUE}.
+
+ \item[sanitize]
+ Should special latex characters be replaced (Default \code{FALSE}). See
+ \autoref{sec:options}, ``Options That Affect Package Behavior''
+ for which characters are replaced.
+
+ \item[engine]
+ A string specifying which \TeX{} engine to use. Possible values are
+ \code{'pdftex'}, \code{'xetex'} and \code{'luatex'}.
+
+ \item[documentDeclaration]
+ See \autoref{sec:options}, ``Options That Affect Package Behavior.''
+
+ \item[packages]
+ See \autoref{sec:options}, ``Options That Affect Package Behavior.''
+
+ \item[footer]
+ See \autoref{sec:options}, ``Options That Affect Package Behavior.''
+\end{flexlabelled}
+
+The first six options should be familiar to anyone who has used the default
+graphics devices shipped with \lang{R}. The options \code{standAlone}
+and \code{bareBones} are specific to the \code{tikz()} graphics device and
+affect the structure the output file. Using these options \code{tikz}
+supports three modes of output:
+
+\begin{itemize}
+ \item
+ Graphics production as complete \LaTeX\ files suitable for compilation.
+
+ \item
+ Graphics production as complete figures suitable for inclusion in \LaTeX\
+ files.
+
+ \item
+ Graphics production as raw figure code suitable for inclusion in an
+ enclosing \code{tikzpicture} environment in a \LaTeX\ file.
+\end{itemize}
+
+
+\section{Font Size Calculations}
+ \label{subsec:fontCalc}
+
+The overarching goal of the \pkg{tikzDevice} is to provide seamless integration
+between text in \lang{R} graphics and the text of \LaTeX\ documents that contain those
+graphics. In order to achieve this integration the device must translate font
+sizes specified in \lang{R} to corresponding font sizes in \LaTeX. The issue is
+that font sizes in \LaTeX\ are controlled by a ``base font size'' that is
+specified at the beginning of the document---typically 10pt. There is no easy
+way in \LaTeX\ to change the font size to a new numerical value, such as 16pt
+for a plot title. Fortunately, the \TikZ\ graphics system allows text to be
+resized using a scaling factor. The \pkg{tikzDevice} calculates a scaling
+factor used to approximate other font sizes using the following three inputs:
+
+\begin{itemize}
+ \item
+ The ``base font size'' specified when the graphics device is created.
+
+ \item
+ The ``character expansion factor'' parameter, specified using the `cex'
+ argument to functions such as described in the documentation of the \lang{R}
+ function \code{par}.
+
+ \item
+ The ``font size'' parameter, specified using the `ps' argument to functions
+ such as \code{par} or the `fontsize' argument to functions such as
+ \code{gpar}.
+\end{itemize}
+
+The calculation used is:
+
+\[
+ \mbox{Scaling Factor} = \mbox{cex} \cdot \frac{\mbox{ps}}{\mbox{base font size}}
+\]
+
+The tricky bit is the specification of the ``base font size''. By default the
+\pkg{tikzDevice} will attempt to determine this parameter by scanning the value of
+\code{options( "tikzDocumentDeclaration" )} using the regular expression
+\code{\textbackslash d+pt}. With the default header:
+\[
+ \mbox{\code{\textbackslash documentclass[10pt]\{article\}}}
+\]
+this regular expression will return 10 as the base pointsize to be used by the
+device. If the regular expression fails to produce a match, the value of the
+\code{pointsize} argument to the \code{tikz} function will be used.
+
+
+\subsection{UTF-8 Output}
+
+Version 0.6.0 of the \pkg{tikzDevice} introduced support for (multibyte)
+Unicode characters in the text of graphics through support for \hologo{XeTeX}.
+Version 0.7.0 extended multilingual typesetting further by adding support for
+the \hologo{LuaTeX} compiler. Unicode support in \pkg{tikzDevice} is subject to
+a few important caveats:
+
+\begin{description}
+ \item[System Requirements:]
+ A working version of \hologo{XeLaTeX} or \hologo{LuaLaTeX} along with the
+ packages \code{fontspec} and \code{xunicode} are required for direct
+ processing of Unicode input. If \pkg{tikzDevice} cannot find a Unicode-aware
+ compiler, then Unicode support cannot be guaranteed.
+
+ \item[Encoding:]
+ \pkg{tikzDevice} will try its best to convert characters from other
+ encodings but do not count on it converting things correctly, best to do
+ the conversion yourself beforehand to avoid unexpected output.
+
+ \item[Fonts:]
+ Having a Unicode character actually show up in your \LaTeX\ document relies
+ on the font you use having the glyph available. We leave it up to the user
+ to know for themselves what is available. Otherwise you will likely just
+ get no output in place of where the character should be.
+
+ \item[Plotmath:]
+ There is specifically no support for input of plotmath characters as
+ unicode since the user can simply input \LaTeX\ math directly. We strongly
+ encourage the use of \LaTeX\ math over plotmath for style and consistency's
+ sake. A consequence of this is that most of the \lang{R} examples and demos
+ of plotmath won't work without significant manipulation (your mileage may
+ vary but you may get anything from errors to warnings to documents that
+ mysteriously won't compile). That is not to say that the output could not
+ be duplicated with \pkg{tikzDevice} but the examples will not work out of
+ the box.
+
+ \item[Compiling:]
+ A graphic that contains UTF-8 characters should be compiled with
+ \hologo{XeLaTeX} or \hologo{LuaLaTeX} with the \code{xunicode} and
+ \code{fontspec} packages enabled.
+
+ \item[ASCII only:]
+ Everything should be exactly the same as previous versions if only ASCII
+ (single byte) characters are used (i.e. character codes less than 132).
+\end{description}
+
+
+
+\section{Examples}
+
+\subsection{Default Mode}
+
+The most common use of the \code{tikz} function is to produce a plot that
+will be included in another \LaTeX\ document, such as a report. Running the
+following example in \lang{R} will produce a very simple graphic using the
+\code{plot} function:
+
+<<simpleEx,echo=TRUE,results='hide'>>=
+library(tikzDevice)
+tikz('figs/simpleEx.tex',width=3.5,height=3.5)
+plot(1,main='Hello World!')
+dev.off()
+@
+
+A \LaTeX\ document is then required to display the figure. This document must
+include \TikZ\ as one of the packages that it loads. \TikZ\ provides several
+libraries that enable additional functionality, however none of these libraries
+are currently required to use the output of \code{tikz}. Inside the \LaTeX\
+document, the contents of the file \code{simpleEx.tex} are imported using the
+\verb|\include| command.
+
+\begin{figure}[H]
+ \centering
+
+ \begin{minipage}{0.5\textwidth}
+ \begin{tikzCodeBlock}[title={Example \LaTeX{} Document},listing style=latexsource,code body/.append style={codebody color=white}]
+\documentclass{article}
+
+% All LaTeX documents including
+% tikz() output must use this
+% package!
+\usepackage{tikz}
+
+\begin{document}
+ \begin{figure}[!h]
+ \centering
+
+ % The output from tikz()
+ % is imported here.
+ \input{simpleEx.tex}
+
+ \caption{Simple Example}
+ \end{figure}
+\end{document}
+ \end{tikzCodeBlock}
+ \end{minipage}
+ \hfill
+ \begin{minipage}{0.45\textwidth}
+ \input{figs/simpleEx.tex}
+ \end{minipage}
+ \caption{Example of simple \code{tikz} usage.}
+\end{figure}
+
+One of the most exciting aspects of the \code{tikz} function is that the
+inclusion of arbitrary \LaTeX\ code is allowed in strings passed to plotting
+commands. An important issue to note is that many \LaTeX\ commands are prefixed
+by the backaslash character: \textbackslash. Unfortunately, in many programming
+languages, the backslash character is also given a special status when it
+appears in strings. Therefore, it is necessary to place two backslashes,
+\textbackslash\textbackslash, in \lang{R} strings in order to cause backslash to
+appear in the output for \LaTeX. The next example demonstrates how to use
+\LaTeX\ commands in plot annotation.
+
+
+\begin{figure}[H]
+ \centering
+ \begin{minipage}{0.5\textwidth}
+<<latexEx,echo=TRUE,results='hide',tidy=FALSE>>=
+library(tikzDevice)
+tikz('figs/latexEx.tex',
+ width=3.5,height=3.5)
+
+x <- rnorm(10)
+y <- x + rnorm(5,sd=0.25)
+
+model <- lm(y ~ x)
+rsq <- summary( model )$r.squared
+rsq <- signif(rsq,4)
+
+plot(x, y, main='Hello \\LaTeX!')
+abline(model, col='red')
+
+mtext(paste("Linear model: $R^{2}=",
+ rsq, "$"), line=0.5)
+
+legend('bottomright', legend =
+ paste("$y = ",
+ round(coef(model)[2],3), 'x +',
+ round(coef(model)[1],3), '$',
+ sep = ''), bty = 'n')
+
+dev.off()
+@
+ \end{minipage}
+ \hfill
+ \begin{minipage}{0.45\textwidth}
+ \input{figs/latexEx.tex}
+ \end{minipage}
+ \caption{A more complicated example of \code{tikz} usage incorporating
+ natively rendered \LaTeX\ commands.}
+\end{figure}
+
+
+\subsection{\pkgopt{bareBones} Mode}
+
+\code{bareBones} output is designed to facilitate inclusion of code generated
+by \code{tikz} into a larger \TikZ\ graphic. Normally \code{tikz} wraps output
+as a self-contained \code{tikzpicture} environment. When \code{bareBones} is
+invoked, the wrapping environment is omitted. This option allows output to be
+embedded inside another \code{tikzpicture} of the user's own construction.
+
+<<bareBonesExample,echo=TRUE,results='hide',tidy=FALSE>>=
+library(tikzDevice)
+library(maps)
+
+tikz('figs/westCoast.tex', bareBones=TRUE)
+
+map('state', regions=c('california', 'oregon', 'washington'),
+ lwd=4, col='grey40')
+
+# Insert some named coordinates into the picture that will
+# be available once the picture is included into the
+# TeX document.
+tikzCoord(-124.161, 40.786, 'humBay')
+tikzCoord(-122.962, 46.148, 'longView')
+tikzCoord(-124.237, 43.378, 'coosBay')
+tikzCoord(-122.419, 37.775, 'sfBay')
+
+dev.off()
+@
+
+The \verb|\include| command may now be used to import the device output into
+another \code{tikzpicture}. The included code must be wrapped in a \code{scope}
+environment that contains the options \code{x=1pt} and \code{y=1pt}. This
+informs \TikZ\ of the units being used in the coordinates of the plot output.
+The options \code{xshift} and \code{yshift} may also be applied to the
+\code{scope} in order to position the plot. The following code demonstrates how
+to embed \code{bareBones} output in a \code{tikzpicture}:
+
+\begin{tikzCodeBlock}[title={Example of a \TikZ{} environment including \code{bareBones} output},
+ code body/.append style={codebody color=white},
+ listing style=latexsource]
+\begin{tikzpicture}
+
+ % Include bareBones output inside a scope with x and y units set to 1pt
+ \begin{scope}[x=1pt,y=1pt]
+ \input{figs/westCoast}
+ \end{scope}
+
+ % Label ports using coordinates placed into the barBones output by the
+ % tikzAnnotate function.
+ \foreach \name/\port in {
+ Longview/longView,
+ Coos Bay/coosBay,
+ Humboldt Bay/humBay,
+ Oakland/sfBay%
+ } {
+ \node[circle, draw, ultra thick, fill=green!60!brown!40,
+ outer sep=6pt,minimum size=12pt,
+ pin={[draw, ultra thick,
+ rounded corners,
+ pin edge={black, ultra thick, <-, >=stealth}
+ ] 180 : \name}] at (\port) {};
+ }
+
+\end{tikzpicture}
+\end{tikzCodeBlock}
+
+
+\begin{figure}[H]
+
+ \centering
+
+ \begin{tikzpicture}
+
+ \begin{scope}[x=1pt,y=1pt]
+ \input{figs/westCoast}
+ \end{scope}
+
+ \foreach \name/\port in {
+ Longview/longView,
+ Coos Bay/coosBay,
+ Humboldt Bay/humBay,
+ Oakland/sfBay%
+ } {
+ \node[circle, draw, ultra thick, fill=green!60!brown!40,
+ outer sep=6pt,minimum size=12pt,
+ pin={[draw, ultra thick,
+ rounded corners,
+ pin edge={black, ultra thick, <-, >=stealth}
+ ] 180 : \name}] at (\port) {};
+ }
+
+ \end{tikzpicture}
+
+ \caption{A \TikZ\ drawing with embedded output from \code{tikz(bareBones=TRUE)}.}
+\end{figure}
+
+\subsection{\pkgopt{standAlone} Mode}
+
+When the \code{standAlone} option is passed to \code{tikz}, the resulting
+\code{.tex} file will be a complete \LaTeX\ document that can be compiled into
+a stand-alone figure. This means that in addition to \verb|\begin{tikzpicture}|
+and \verb|\end{tikzpicture}| the file will also contain \verb|\begin{document}|,
+\verb|\end{document}| and a \LaTeX\ preamble. The \code{preview} package is also
+used in files produced by \code{standAlone} to crop the pages in the resulting
+document to the bounding boxes of the plots. Stand-alone output may be
+produced in the following manner:
+
+<<standAloneExample,echo=TRUE,results='hide',tidy=FALSE>>=
+library(tikzDevice)
+tikz('standAloneExample.tex',standAlone=TRUE)
+plot(sin,-pi,2*pi,main="A Stand Alone TikZ Plot")
+dev.off()
+@
+
+
+<<standAloneCompileExample, results='hide', eval=FALSE>>=
+
+ library(tools)
+
+ catch <- system(paste(Sys.which('pdflatex'),
+ '-interaction=batchmode -output-directory figs/ figs/standAloneExample.tex'),
+ ignore.stderr=T)
+
+ # If compiling the example failed, we don't want to include a broken link.
+ if( catch == 0 ){
+ pdfLink <- "The file \\\\code{standAloneExample.tex} may then be compiled to produce
+ \\\\href{./figs/standAloneExample.pdf}{standAloneExample.pdf}. "
+ }else{
+ pdfLink <- ""
+ }
+ #%\Sexpr{print(pdfLink)}
+@
+
+Note that files produced using the \code{standAlone} option should not be
+included in \LaTeX\ documents using the \verb|\input| command! Use
+\verb|\includegraphics| or load the \code{pdfpages} package and use
+\verb|\includepdf|.
+
+
+\subsection{\pkgopt{console} output Mode}
+
+Version 0.5.0 of \pkg{tikzDevice} introduced the \code{console} option. With
+this option, \code{tikz} will send output to \code{stdout} instead of a file.
+This kind of output can be redirected to a file with \code{sink} or spit out
+directly into a \TeX\ document from a \pkg{Sweave} file so that the \TeX\ file
+is self contained and does not include other files via \verb|\input|.
+(Including the chunk option \code{strip.white=FALSE} was necessary for some
+versions of \pkg{tikzDevice} prior to 0.7.2.)
+
+\tikzCodeInput[title={Catching \code{tikz} output inside Sweave},listing style=sweavechunk]{consoleExample}
+
+
+\subsection{Using \hologo{XeLaTeX}}
+
+It is also possible to use other typesetting engines like \hologo{XeLaTeX} by
+using the global options provided by \pkg{tikzDevice}. The following example
+was inspired by Dario Taraborelli and his article
+\href{http://nitens.org/taraborelli/latex}{The Beauty of LaTeX}.
+
+% `eval` normally set to `FALSE` as this example takes a long time to run and the
+% required fonts are only availble by default on OS X.
+<<xelatexFontVariantExample,tidy=FALSE,echo=TRUE,eval=FALSE,results='hide'>>=
+# Set options for using XeLaTeX font variants.
+options(tikzXelatexPackages = c(
+ getOption('tikzXelatexPackages'),
+ "\\usepackage[colorlinks, breaklinks]{hyperref}",
+ "\\usepackage{color}",
+ "\\definecolor{Gray}{rgb}{.7,.7,.7}",
+ "\\definecolor{lightblue}{rgb}{.2,.5,1}",
+ "\\definecolor{myred}{rgb}{1,0,0}",
+ "\\newcommand{\\red}[1]{\\color{myred} #1}",
+ "\\newcommand{\\reda}[1]{\\color{myred}\\fontspec[Variant=2]{Zapfino}#1}",
+ "\\newcommand{\\redb}[1]{\\color{myred}\\fontspec[Variant=3]{Zapfino}#1}",
+ "\\newcommand{\\redc}[1]{\\color{myred}\\fontspec[Variant=4]{Zapfino}#1}",
+ "\\newcommand{\\redd}[1]{\\color{myred}\\fontspec[Variant=5]{Zapfino}#1}",
+ "\\newcommand{\\rede}[1]{\\color{myred}\\fontspec[Variant=6]{Zapfino}#1}",
+ "\\newcommand{\\redf}[1]{\\color{myred}\\fontspec[Variant=7]{Zapfino}#1}",
+ "\\newcommand{\\redg}[1]{\\color{myred}\\fontspec[Variant=8]{Zapfino}#1}",
+ "\\newcommand{\\lbl}[1]{\\color{lightblue} #1}",
+ "\\newcommand{\\lbla}[1]{\\color{lightblue}\\fontspec[Variant=2]{Zapfino}#1}",
+ "\\newcommand{\\lblb}[1]{\\color{lightblue}\\fontspec[Variant=3]{Zapfino}#1}",
+ "\\newcommand{\\lblc}[1]{\\color{lightblue}\\fontspec[Variant=4]{Zapfino}#1}",
+ "\\newcommand{\\lbld}[1]{\\color{lightblue}\\fontspec[Variant=5]{Zapfino}#1}",
+ "\\newcommand{\\lble}[1]{\\color{lightblue}\\fontspec[Variant=6]{Zapfino}#1}",
+ "\\newcommand{\\lblf}[1]{\\color{lightblue}\\fontspec[Variant=7]{Zapfino}#1}",
+ "\\newcommand{\\lblg}[1]{\\color{lightblue}\\fontspec[Variant=8]{Zapfino}#1}",
+ "\\newcommand{\\old}[1]{",
+ "\\fontspec[Ligatures={Common, Rare},Variant=1,Swashes={LineInitial, LineFinal}]{Zapfino}",
+ "\\fontsize{25pt}{30pt}\\selectfont #1}%",
+ "\\newcommand{\\smallprint}[1]{\\fontspec{Hoefler Text}
+ \\fontsize{10pt}{13pt}\\color{Gray}\\selectfont #1}"
+))
+
+# Set the content using custom defined commands
+label <- c(
+ "\\noindent{\\red d}roo{\\lbl g}",
+ "\\noindent{\\reda d}roo{\\lbla g}",
+ "\\noindent{\\redb d}roo{\\lblb g}",
+ "\\noindent{\\redf d}roo{\\lblf g}\\\\[.3cm]",
+ "\\noindent{\\redc d}roo{\\lblc g}",
+ "\\noindent{\\redd d}roo{\\lbld g}",
+ "\\noindent{\\rede d}roo{\\lble g}",
+ "\\noindent{\\redg d}roo{\\lblg g}\\\\[.2cm]"
+)
+
+# Set the titles using custom defined commands, and hyperlinks
+title <- c(
+paste(
+ "\\smallprint{D. Taraborelli (2008),",
+ "\\href{http://nitens.org/taraborelli/latex}",
+ "{The Beauty of \\LaTeX}}"
+), paste(
+ "\\smallprint{\\\\\\emph{Some rights reserved}.",
+ "\\href{http://creativecommons.org/licenses/by-sa/3.0/}",
+ "{\\textsc{cc-by-sa}}}"
+))
+
+# Draw the graphic
+tikz('xelatexEx.tex',
+ standAlone=TRUE,width=5,height=5,
+ engine = 'xetex')
+lim <- 0:(length(label)+1)
+plot(lim,lim,cex=0,pch='.',xlab = title[2],ylab='', main = title[1])
+for(i in 1:length(label))
+ text(i,i,label[i])
+dev.off()
+@
+
+Compiling the resulting file with \hologo{XeLaTeX} will produce the output in
+\autoref{fig:xelatex}. Please note some of the fonts used in the example may
+not be available on every system.
+
+\begin{figure}[!h]
+\centering
+\includegraphics{img/xelatexEx.pdf}
+\caption{Result of \hologo{XeLaTeX} example}\label{fig:xelatex}
+\end{figure}
+
+
+\subsection{Annotating Graphics with \TikZ\ Commands}
+
+The function \code{tikzAnnotate} provides the ability to annotate you graphics
+with \TikZ\ commands. There are a lot of exciting possibilities with this
+feature---it basically opens up the door for you to draw anything on your plot
+that can be drawn with \TikZ. Check out the results in
+\autoref{fig:annotation}.
+
+<<annotation,echo=TRUE,results='hide',tidy=FALSE>>=
+library(tikzDevice)
+
+# Load some additional TikZ libraries
+tikz("figs/annotation.tex",width=4,height=4,
+ packages = c(getOption('tikzLatexPackages'),
+ "\\usetikzlibrary{decorations.pathreplacing}",
+ "\\usetikzlibrary{positioning}",
+ "\\usetikzlibrary{shapes.arrows,shapes.symbols}")
+)
+
+p <- rgamma (300 ,1)
+outliers <- which( p > quantile(p,.75)+1.5*IQR(p) )
+boxplot(p)
+
+# Add named coordinates that other TikZ commands can hook onto
+tikzCoord(1, min(p[outliers]), 'min outlier')
+tikzCoord(1, max(p[outliers]), 'max outlier')
+
+# Use tikzAnnotate to insert arbitrary code, such as drawing a
+# fancy path between min outlier and max outlier.
+tikzAnnotate(c("\\draw[very thick,red,",
+ # Turn the path into a brace.
+ 'decorate,decoration={brace,amplitude=12pt},',
+ # Shift it 1em to the left of the coordinates
+ 'transform canvas={xshift=-1em}]',
+ '(min outlier) --',
+ # Add a node with some text in the middle of the path
+ 'node[single arrow,anchor=tip,fill=white,draw=green,',
+ 'left=14pt,text width=0.70in,align=center]',
+ '{Holy Outliers Batman!}', '(max outlier);'))
+
+# tikzNode can be used to place nodes with customized options and content
+tikzNode(
+ opts='starburst,fill=green,draw=blue,very thick,right=of max outlier',
+ content='Wow!'
+)
+
+dev.off()
+@
+
+\begin{figure}[!h]
+\centering
+\input{figs/annotation.tex}
+\caption{An example using \TikZ\ annotation.}\label{fig:annotation}
+\end{figure}
+
+\begin{landscape}
+
+\subsection{\pkgopt{tikz} vs. \pkgopt{pdf} for \pkgopt{plotmath} symbols and Unicode characters}
+
+This is a side-by-side example showing how \code{tikz(..., engine = 'xetex')} handles UTF-8
+characters and plotmath symbols compared to the standard \lang{R} \code{pdf} device.
+
+\begin{figure}[!h]
+\centering
+ \begin{minipage}{4.25in}
+ \includegraphics[width=4.25in]{img/plotmathDefault.pdf}
+ \caption{\code{example(text)} using the standard \code{pdf()} device.}\label{fig:plotmathDefault}
+ \end{minipage}
+ \vspace{1em}
+ \begin{minipage}{4.25in}
+ \includegraphics[width=4.25in]{img/plotmathTikz.pdf}
+ \caption{\code{example(text)} using \code{tikz(..., engine = 'xetex')}.}\label{fig:plotmathTikz}
+ \end{minipage}
+\end{figure}
+
+\end{landscape}
+
+
+% -----------------------------------------------------------------------------
+% Chapter 4: The Metrics Functions
+% -----------------------------------------------------------------------------
+\chapter{The \code{getLatexCharMetrics} and \code{getLatexStrWidth} Functions}
+
+\section{Description}
+
+These two functions may be used to retrieve font metrics through the interface
+provided by the \pkg{tikzDevice} package. Cached values of the metrics are
+returned if they have been calculated by the \pkg{tikzDevice} before. If no
+cached values exist, a \LaTeX\ compiler will be invoked to generate them.
+
+\section{Usage}
+
+The font metric functions are called as follows:
+
+\begin{Verbatim}[frame=single]
+getLatexStrWidth( texString, cex = 1, face= 1)
+
+getLatexCharMetrics( charCode, cex = 1, face = 1 )
+\end{Verbatim}
+
+\begin{flexlabelled}{code}{*}{0.5em}{0.5em}{*}{\leftmargin}
+ \item[texString]
+ A string for which to compute the width. \LaTeX\ commands may be used in
+ the string, however all backslashes will need to be doubled.
+
+ \item[charCode]
+ An integer between 32 and 126 which indicates a printable character in the
+ ASCII symbol table using the T1 font encoding.
+
+ \item[cex]
+ The character expansion factor to be used when determining metrics.
+
+ \item[face]
+ An integer specifying the \lang{R} font face to use during metric
+ calculations. The accepted values are as follows:
+
+ \begin{description}
+ \item[1:]
+ Text should be set in normal font face.
+ \item[2:]
+ Text should be set in {\bfseries bold font face}.
+ \item[3:]
+ Text should be set in {\itshape italic font face}.
+ \item[4:]
+ Text should be set in {\bfseries\itshape bold italic font face}.
+ \item[5:]
+ Text should be interpreted as \code{plotmath} symbol characters.
+ Requests for font face 5 are currently ignored.
+ \end{description}
+\end{flexlabelled}
+
+\section{Examples}
+
+The \code{getLatexStrWidth} function may be used to calculate the width of
+strings containing fairly arbitrary \LaTeX\ commands. For example, consider
+the following calculations:
+
+
+<<strWidthDemo,echo=T>>=
+getLatexStrWidth( "The symbol: alpha" )
+getLatexStrWidth( "The symbol: $\\alpha$" )
+@
+
+For the first calculation, the word ``alpha'' was interpreted as just a word and
+the widths of the characters `a', `l', `p', `h' and `a' were included in the
+string width. For the second string, \verb|\alpha| was interpreted as a
+mathematical symbol and only the width of the symbol `$\alpha$' was included in
+the string width.
+
+The \code{getLatexCharWidth} function must be passed an integer corresponding
+to an ASCII character code and returns three values:
+
+\begin{itemize}
+ \item
+ The \code{ascent} of the character. This is the distance between the
+ baseline and the highest point of the character's glyph.
+
+ \item
+ The \code{descent} of the character. This is the distance between the baseline and
+ the lowest point of the character's glyph.
+
+ \item
+ The width of the character.
+\end{itemize}
+
+The character `y' has an \code{ASCII} symbol code of 121 and possesses a tail
+that descends below the text line. Therefore a non-zero value will be returned
+for the descent of `y'. The character `x', \code{ASCII} code 120, has no
+descenders, so its descent will be returned as zero.
+
+<<charMetricDemo,echo=T,tidy=FALSE>>=
+# Get metrics for 'y'
+getLatexCharMetrics(121)
+
+# Get metrics for 'x' - the second value is the descent
+# and should be zero or very close to zero.
+getLatexCharMetrics(120)
+@
+
+Note that characters, along with numbers outside the range of [32--126], may not
+be passed to the \nolinebreak\code{getLatexCharMetrics} function. If for
+some reason a floating point number is passed, it will be floored through
+conversion by \code{as.integer}.
+
+<<charMetricErrors,echo=T,tidy=FALSE>>=
+getLatexCharMetrics('y')
+getLatexCharMetrics(20)
+
+# Will return metrics for 'y'
+getLatexCharMetrics(121.99)
+@
+
+
+
+\part{Installation Guide}
+ \label{part:installation}
+
+\chapter{Obtaining a \LaTeX\ Distribution}
+
+This section offers pointers on how to obtain a \LaTeX\ distribution if there
+is not one already installed on your system. The distributions detailed in this
+section are favorites of the \pkg{tikzDevice} developers as they provide integrated
+package managers which greatly simplify the process of installing additional
+\LaTeX\ packages. Currently this section is not, and may never be, a
+troubleshooting guide for \LaTeX\ installation. For those unfortunate
+situations we refer the user to the documentation of each distribution.
+
+A \LaTeX\ distribution provides the packages and support programs required by
+the \pkg{tikzDevice} and the documents that use its output. In addition to a
+\LaTeX\ compiler, a few extension packages are required.
+\autoref{tikz:required} describes how to obtain and install these packages.
+
+\section{Windows}
+
+Windows users will probably prefer the MiKTeX distribution available at
+\url{http://www.miktex.org}. An amazing feature of the MiKTeX distribution is
+that it contains a package manager that will attempt to install missing
+packages on-the-fly. Normally when \LaTeX\ is compiling a document that tries
+to load a missing package it will wipe out with a warning message. When the
+MiKTeX compilers are used compilation will be suspended while the new package
+is downloaded.
+
+% Perhaps a mention of the new portable MiKTeX distribution that can be run off
+% of a thumbdrive? I haven't used it yet so I don't feel qualified to discuss it at this
+% time.
+
+
+\section{UNIX/Linux}
+
+For users running a Linux or UNIX operating system, we recommend the TeX Live
+distribution which is available at
+\url{http://www.tug.org/texlive/acquire.html}. TeX Live is maintained by the
+TeX Users Group and a new version is released every year.
+We recommend using TeX Live 2008 or higher as the \code{tlmgr} package
+manager was introduced in the 2008 distribution. Using \code{tlmgr} greatly
+simplifies the adding and removing packages from the distribution. The website
+offers an installation package, called \code{install-tl.tar.gz} or something
+similar, that contains a shell script that can be used to install an up-to-date
+version of the TeX Live distribution.
+Note that the version
+of TeX Live provided by many Linux package management systems sometimes
+lags behind the version provided directly by the TeX Users Group.
+
+\section{Mac OS X}
+
+For users running Apple's OS X, we recommend the Mac TeX package available at
+\url{http://www.tug.org/mactex/}. Mac TeX is basically TeX Live packaged inside
+a convenient OS X installer along with a few add-on packages. One striking
+difference between the Mac TeX and TeX Live installers is that the installer
+for Mac TeX includes the whole TeX Live distribution in the initial download-
+for TeX Live 2013 this amounts to approximately 2.3 GB. This is quite a large
+download that contains several packages that the average or even advanced user
+will never ever use. To conserve time and space we recommend installing from
+the basic installer at \url{http://www.tug.org/mactex/morepackages.html} and
+using the \code{tlmgr} utility to add desired add-on packages.
+
+Adam R. Maxwell has created a very nice graphical interface to \code{tlmgr} for
+OS X called the TeX Live Utility. It may be obtained from
+\url{http://code.google.com/p/mactlmgr/} and we highly recommend it.
+
+
+\section{Installing \TikZ\ and Other Packages}
+ \label{tikz:required}
+
+Unsurprisingly, \pkg{tikzDevice} requires the \TikZ\ package to be installed
+and available in order to function properly. \TikZ\ is an abstraction of a
+lower-level graphics language called \lang{PGF} and both are distributed as the
+the \code{pgf} package. Users who do no have a full \TeX\ installation will
+also need to install a few more required packages:
+
+\begin{flexlabelled}{pkg}{0pt}{0.5em}{0.5em}{*}{\leftmargin}
+
+ \item[pgf]{As mentioned, provides \TikZ.}
+ \item[preview]{Used to crop documents in order to produce standalone figures.}
+ \item[ms]{Martin Schröder's LaTeX packages. \code{everyshi.sty} lets us run commands at every shipped page.}
+ \item[graphics]{\hologo{LaTeX}'s general-purpose graphics inclusion functionality.}
+ \item[pdftex-def]{Device-specific colour and graphics definitions when running \hologo{pdfTeX}/\hologo{pdfLaTeX}.}
+ \item[oberdiek]{\code{infwarerr.sty} provides info/error/warning messages}
+ \item[ec]{(Font metrics for) the default font, European Computer Modern.}
+ \item[xcolor]{Used by \TikZ\ to specify colors.}
+ \item[fontspec]{Used by \hologo{LuaTeX} and \hologo{XeTeX} to select fonts.}
+ \item[xunicode]{Assists \hologo{LuaTeX} and \hologo{XeTeX} with UTF-8 characters.}
+
+\end{flexlabelled}
+
+
+\subsection{Using a \LaTeX\ Package Manager}
+
+The easiest way to install \LaTeX\ packages is by using a distribution that
+includes a package manager such as MiKTeX or TeX Live/Mac TeX. For Windows
+users, the MiKTeX package manager usually handles package installation
+automagically during compilation of a document that is requesting a missing
+package. The MiKTeX package manager, \code{mpm}, can also be run manually from
+the command prompt:
+
+\begin{tikzCodeNode}[title={Using \code{mpm} to install packages},listing style=bashsource,code body/.append style={codebody color=white}]
+mpm --install packagename
+\end{tikzCodeNode}
+
+For versions of TeX Live and Mac TeX dated 2008 or newer, the \code{tlmgr}
+package manager is used in an almost identical manner:
+
+\begin{tikzCodeNode}[title={Using \code{tlmgr} to install packages},listing style=bashsource,code body/.append style={codebody color=white}]
+tlmgr install packagename
+\end{tikzCodeNode}
+
+\subsection{Manual Installation}
+
+Sometimes an automated package manager cannot be used. Common reasons may be
+that one is not available, as is the case with the TeX Live 2007 distribution,
+or that when running the package manager you do not have write access to the
+location where \LaTeX\ packages are stored, as is the case with accounts on
+shared computers. If this is the case, a manual install may be the best option
+for making a \LaTeX\ package available.
+
+Generally, the best place to find \LaTeX\ packages is the Comprehensive TeX
+Archive Network, or \lang{CTAN} located at \url{http://www.ctan.org}. In the
+case of the PGF/\TikZ\ package, the project homepage at
+\url{http://www.sourceforge.net/projects/pgf} is also a good place to obtain
+the package---especially if you would like to play with the bleeding-edge
+development version.
+
+Generally speaking, all \LaTeX\ packages are stored in a specially directory
+called a \code{texmf} folder. Most \TeX\ distributions allow for each user to
+have their own personal \code{texmf} folder somewhere in their home path. The
+most usual locations, and here {\bfseries\itshape usual} is an unfortunately
+loose term, are as follows:
+
+\begin{tikzCodeNode}[title={For UNIX/Linux},listing style=bashsource,code body/.append style={codebody color=white}]
+~/texmf
+\end{tikzCodeNode}
+
+\begin{tikzCodeNode}[title={For Mac OS X},listing style=bashsource,code body/.append style={codebody color=white}]
+~/Library/texmf
+\end{tikzCodeNode}
+
+\begin{tikzCodeNode}[title={For Windows, using MiKTeX},listing style=bashsource,code body/.append style={codebody color=white}]
+# None predefined. However the following command will open
+# the MiKTeX options panel and a new texmf folder may be assigned
+# under the "Roots" tab.
+mo
+\end{tikzCodeNode}
+
+
+The location of files and subfolders in the \code{texmf} directory should
+follow a standard pattern called the \TeX\ Directory Structure or TDS which is
+documented here: \url{http://tug.org/tds/tds.pdf}. Fortunately, most packages
+available on \pkg{CTAN} are archived in such a way that they will unpack into
+a TDS-compliant configuration. TDS-compliant archives usually have the phrase
+\code{tds} somewhere in their filename and may be installed from a UNIX
+shell\footnote{Sorry Windows users, we enjoy using command prompt about as much
+as a poke in the eye with a sharp stick. Hence we don't use it enough to offer
+advice. May we suggest \href{http://www.cygwin.com}{Cygwin}?} like so:
+
+\begin{tikzCodeNode}[title={Installing \LaTeX{} package archives},listing style=bashsource,code body/.append style={codebody color=white}]
+# For zip files.
+unzip package.tds.zip -d /path/to/texmf
+
+# For tarballs.
+tar -xzf -C /path/to/texmf package.tar.gz
+\end{tikzCodeNode}
+
+For packages that aren't provided in TDS-compliant form look for installation
+notes---usually provided in the form of an \code{INSTALL} file. If all else
+fails \LaTeX\ packages can usually be installed by copying the files ending in
+\code{.sty} to \code{texmf/tex/latex/}.
+
+After package files have been unpacked to a \code{texmf} folder, the database
+of installed packages needs to be updated for the \LaTeX\ compiler to take
+notice of the additions. This is done with the \code{mktexlsr} command:
+
+\begin{tikzCodeNode}[title={Registering new \LaTeX{} packages},listing style=bashsource,code body/.append style={codebody color=white}]
+mktexlsr
+
+# Successful package installation can be checked by running the
+# kpsewhich command. For a package accessed in a document
+# by \usepackage{package}, kpsewhich should return a path to
+# package.sty
+kpsewhich tikz.sty
+!out/Users/Smithe/Library/texmf/tex/latex/pgf/frontendlayer/tikz.sty!/out
+\end{tikzCodeNode}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% Listing commands cannot be saved in macros, so we execute them here and stash
+% the output in a box.
+\newsavebox{\programflow}
+\begin{lrbox}{\programflow}
+\begin{tikzpicture}
+
+ \node[text width = 4.3in] (r code) {
+ \begin{tikzCodeNode}[title={\lang{R} User Types}, listing style=sweavechunk]
+tikz('Rplot.tex')
+plot(1)
+dev.off()
+ \end{tikzCodeNode}
+ };
+
+ \node[below = \baselineskip of r code, text width = 4.3in] (c code) {
+ \begin{tikzCodeNode}[title={TikZ Device Translates}, listing style = csource]
+static void TikZ_Circle( double x, double y, double r,
+ const pGEcontext plotParams, pDevDesc deviceInfo){
+
+...
+
+ printOutput(tikzInfo,"\n\\path[");
+ TikZ_WriteDrawOptions(plotParams, deviceInfo, ops);
+
+ /* End options, print coordinates. */
+ printOutput(tikzInfo, "] (%6.2f,%6.2f) circle (%6.2f);\n",
+ x,y,r);
+}
+ \end{tikzCodeNode}
+ };
+
+ \node[below = \baselineskip of c code, text width = 4.3in] (latex code) {
+ \begin{tikzCodeNode}[title={\LaTeX\ Output is Produced}, listing style = latexexample]
+% Created by tikzDevice
+% !TEX encoding = UTF-8 Unicode
+\begin{tikzpicture}[x=1pt,y=1pt]
+
+...
+
+\path[draw=drawColor,line width= 0.4pt,
+ line join=round,line cap=round]
+ (264.94,258.95) circle ( 2.25);
+
+...
+
+\end{tikzpicture}
+ \end{tikzCodeNode}
+ };
+
+\end{tikzpicture}
+\end{lrbox}
+
+
+\partimage{
+ \node[above left = 1in of current page.south east,
+ anchor = south east,
+ scale = 1.25
+ ]
+ % Here we use the box containing the output.
+ {\usebox{\programflow}};
+}
+
+\part{Package Internals}
+ \label{part:implementation}
+
+\epigraph{We will encourage you to develop the three great virtues of a programmer: {\itshape laziness}, {\itshape impatience}, and {\itshape hubris}.}{{\itshape Programming Perl}\\ --{\scshape Larry Wall}}
+
+\chapter{Introduction and Background}
+
+
+We learn best through working with examples. When it comes to programming languages this involves taking working code that someone else has written, breaking it in as many places at it can possibly be broken, and then trying to build something out of the wreckage. Open source software facilitates this process wonderfully by ensuring the source code of a project is always available for inspection and experimentation. The \pkg{tikzDevice} its self was created by disassembling and then rebu [...]
+
+This section is our attempt to help anyone who may be experimenting with our code, and by extension the internals of the \lang{R} graphics system. There may also be useful, or useless, tidbits concerning building \lang{R} packages and interacting with the core \lang{R} language. The \lang{R} language can be extended in so many interesting and useful ways and it is our hope that the following documentation may provide a case study for anyone attempting such an extension.
+
+We will make an attempt to assume no special expertise with any of the systems or programming languages leveraged by this package and described by this documentation. Therefore, if you are an experienced developer and find yourself thinking ``My god, are they {\bfseries really} about to launch into a description of how \lang{C} header files work?'', please feel free to skip ahead a few paragraphs. We received our formal introduction to computer programming in a college engineering progra [...]
+
+Therefore, this section is for all the budding developers like ourselves out there---people who have done some programming and who are starting to take a close look at the nuts and bolts of the \lang{R} programming environment. If you feel like you are wandering through a vast forest getting smacked in the face by every branch then maybe this section will help pull some of those branches out of the way...
+
+...then again we have a lot of material to cover: \lang{R}, \lang{C}, \LaTeX , \TikZ{} , typography and the details of computerized font systems. Our grip may fail and send those branches flying back with increased velocity.
+
+We wish you luck!\\
+\vbox{}\quad{\itshape -The tikzDevice Team}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\chapter{Anatomy of an \lang{R} Graphics Device}
+
+The core of an \lang{R} graphics device is a collection of functions, written in \lang{C}, that perform various specialized tasks. A description of some of these functions can be found in the {\itshape R Internals} manual while the main documentation is in the \lang{C} header file \code{GraphicsDevice.h}. For most \lang{R} installations this header file can be found in the directory \code{R\_HOME/include/R\_ext}. For copies of \lang{R} distributed in source code form, \code{GraphicsDevic [...]
+
+
+\setlength\columnsep{5em}
+
+\begin{multicols}{2}
+
+
+\section{Drawing Routines}
+
+\begin{itemize}
+
+\item[\code{circle}]{This function is required to draw a circle centered at a given location with a given radius.}
+
+\item[\code{clip}]{This function specifies a rectangular area to be used a a clipping boundary for any device output that follows.}
+
+\item[\code{line}]{This function draws a line between two points.}
+
+\item[\code{polygon}]{This function draws lines between a list of points and then connects the first point to the last point.}
+
+\item[\code{polyline}]{This function draws lines between a list of points.}
+
+\item[\code{rect}]{This function is given a lower left corner and an upper right corner and draws a rectangle between the two.}
+
+\item[\code{text}]{This function inserts text at a given location.}
+
+\end{itemize}
+
+\section{Font Metric Routines}
+
+\begin{itemize}
+
+\item[\code{metricInfo}]{This function is given the name of a single character and reports the ascent, descent and width of that character.}
+
+\item[\code{strWidth}]{This function is given a text string and reports the width of that string.}
+
+\end{itemize}
+
+\section{Utility Routines}
+
+\begin{itemize}
+
+\item[\code{activate}]{This function is called when the device is designated as the active output device---i.e. by using \code{dev.set()} in \lang{R}}
+
+\item[\code{close}]{This function is called when the device is shut down---i.e. by using \code{dev.off()} in \lang{R}}
+
+\item[\code{deactivate}]{This function is called when another device is designated as the active output device.}
+
+\item[\code{locator}]{This function is mainly used by devices with a GUI window and reports the location of a mouseclick.}
+
+\item[\code{mode}]{This function is called when a device begins drawing output and again when the device finishes drawing output.}
+
+\item[\code{newPage}]{This function initiates the creation of a new page of output.}
+
+\item[\code{size}]{This function reports the size of the canvas the device is drawing on.}
+
+\end{itemize}
+
+\end{multicols}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\chapter{Calculating Font Metrics}
+
+Font metrics are measurements associated with the glyphs, or printed characters, of a particular font. \lang{R} requires three of these metrics in order to produce correctly aligned output. The three metrics graphics devices are required to supply are:
+
+\begin{tikzpicture}
+
+\coordinate (centerpoint) at (0,0);
+
+\node[anchor=north,outer sep=0pt] (title) at ($(centerpoint) + (4em,0)$) {\bfseries Ascent};
+
+\node[scale=4,text=black!40,inner sep=0pt,outer sep=0pt,below=0.25em of title] (char) {g};
+\draw[color=black,very thick] (char.base west) -- (char.base east);
+\draw[color=black,very thick] (char.north west) -- (char.north east);
+\draw[color=red,very thick,<->,>=stealth] ([xshift=10pt]char.base west) -- ([xshift=10pt]char.north west);
+
+
+\newdimen\yone
+\newdimen\ytwo
+
+\pgfextracty{\yone}{\pgfpointanchor{char}{north}}
+\pgfextracty{\ytwo}{\pgfpointanchor{char}{south}}
+\pgfmathparse{ \yone - \ytwo }
+
+\yone = \pgfmathresult pt
+
+\node[anchor = north west,outer sep=0pt,text width=0.6\textwidth] at ($(centerpoint) + (8em, 0)$){
+Ascent is the distance between the baseline and the tallest point on a
+character's glyph. For the ``g'' printed to the left, the ascent has been
+calculated as: \the\yone
+};
+\end{tikzpicture}
+
+
+
+\begin{tikzpicture}
+
+\coordinate (centerpoint) at (0,0) {};
+
+\node[anchor=north,outer sep=0pt] (title) at ($(centerpoint) + (4em,0)$) {\bfseries Descent};
+
+\node[scale=4,text=black!40,inner sep=0pt,outer sep=0pt,below= 0.25em of title.south] (char) {g};
+\draw[color=black,very thick] (char.base west) -- (char.base east);
+\draw[color=black,very thick] (char.south west) -- (char.south east);
+\draw[color=red,very thick,<-,>=stealth] ([xshift=10pt]char.south west) -- +(0,-6pt);
+\draw[color=red,very thick,<-,>=stealth] ([xshift=10pt]char.base west) -- +(0,+6pt);
+
+
+\newdimen\yone
+\newdimen\ytwo
+
+\pgfextracty{\yone}{\pgfpointanchor{char}{base}}
+\pgfextracty{\ytwo}{\pgfpointanchor{char}{south}}
+\pgfmathparse{ \yone - \ytwo }
+
+\yone = \pgfmathresult pt
+
+\node[anchor = north west,outer sep=0pt,text width=0.6\textwidth] at ($(centerpoint) + (8em, 0)$){
+Descent is the distance between the baseline and the lowest point on a
+character's glyph. For the ``g'' printed to the left, the descent has been
+calculated as: \the\yone
+};
+\end{tikzpicture}
+
+
+
+\begin{tikzpicture}
+
+\coordinate (centerpoint) at (0,0);
+
+\node[outer sep=0pt,anchor=north] (title) at ($(centerpoint) + (4em,0)$) {\bfseries Width};
+
+\node[scale=4,text=black!40,inner sep=0pt,outer sep=0pt,below= 0.25em of title.south] (char) {g};
+\draw[color=black,very thick] (char.south west) -- (char.north west);
+\draw[color=black,very thick] (char.south east) -- (char.north east);
+\draw[color=red,very thick,<->,>=stealth] (char.base west) -- (char.base east);
+
+\newdimen\xone
+\newdimen\xtwo
+
+\pgfextractx{\xone}{\pgfpointanchor{char}{east}}
+\pgfextractx{\xtwo}{\pgfpointanchor{char}{west}}
+\pgfmathparse{ \xone - \xtwo }
+
+\xone = \pgfmathresult pt
+
+\node[anchor = north west,outer sep=0pt,text width=0.6\textwidth] at ($(centerpoint) + (8em, 0)$){
+Width is the distance between the left and right sides of a character's glyph.
+For the ``g'' printed to the left, the width has been calculated as: \the\xone};
+\end{tikzpicture}
+
+Providing font metrics and string widths is without a doubt the most difficult task a \lang{R} graphics device must undertake. The calculation of string widths is made even more difficult for the \pkg{tikzDevice} as we attempt to process arbitrary \LaTeX{} strings. Inside \lang{R} the string ``\verb`$\alpha$`'' literally has 8 characters, but when it is typeset it only has one: $\alpha$.
+
+Calculating font metrics is a tricky business to begin with and the fact that the typeset representation of a \LaTeX{} string is different from its representation in source code compounds the difficulty of the task immensely. Therefore, we took the path of laziness and started looking for an easy way out (remember the three great virtues of a programmer?). The solution we came up with seemed easy enough---make \LaTeX{} calculate these metrics for us, after all that is what a \LaTeX{} com [...]
+
+Now, how to do that?
+
+\subsection{Character Metrics}
+
+As a starting point, let's examine the interface of the \lang{C} function that \lang{R} calls in order to determine character metrics:
+
+\begin{tikzCodeBlock}[title={Function declaration for \code{metricInfo}}]
+void (metricInfo)(int c, const pGEcontext gc,
+ double* ascent, double* descent, double* width,
+ pDevDesc dd);
+\end{tikzCodeBlock}
+
+The most important variables involved in the function are \code{c}, \code{ascent}, \code{descent} and \code{width}. The incoming variable is \code{c}, which contains the character for which \lang{R} is requesting font metrics. Interestingly, \code{c} is passed as an integer, not a character as one might expect. What's up with that? Well, the short answer is that \lang{R} passes the \code{ASCII} or \code{UTF8} {\itshape symbol code} of a character and not the character itself. How to use [...]
+
+The outgoing variables are \code{ascent}, \code{descent} and \code{width}. The asterisks, `*', in their definitions mean these variables are passed as {\itshape pointers} as opposed to {\itshape values}. A complete discussion of the differences between pointers and values could, and has, filled up several chapters of several programming books. The important distinction in context of the \code{metricInfo} function is that when a number is assigned to a pointer variable, that number is ava [...]
+
+The other two variables present in the function are the \code{pGEcontext} variable \code{gc} and the \code{pDevDesc} variable \code{dd}. \code{gc} contains information such as the font face, foreground color, background color, character expansion factor, ect. currently in use by the graphics system. \code{dd} is the object which contains \lang{R}'s representation of the graphics device. For the sake of simplifying the following discussion, we will ignore these variables.
+
+So, to recap---we have an integer \code{c} coming in that represents a code for a character in the \code{ASCII} or \code{UTF8} symbol tables (for the sake of the following discussion, we will assume \code{ASCII} characters only). Our overall task is to somehow turn that integer into three numbers which can be assigned to the pointer variables \code{ascent}, \code{descent} and \code{width}. And, since we're being lazy, we've decided that the best way to do that is to ask the \LaTeX{} comp [...]
+
+Recovering these numbers from the \LaTeX{} compiler involves the execution of three additional tasks:
+
+\begin{enumerate}
+
+ \item{We must write a \LaTeX{} input file that contains instructions for calculating the metrics.}
+
+ \item{We call the \LaTeX{} compiler to process that input file.}
+
+ \item{We must read the compiler's output in order to recover the metrics.}
+
+\end{enumerate}
+
+Each of these tasks could be executed from inside our \lang{C} function, \code{metricInfo}. However, we will run into some difficulties---namely with step 2, which involves calling out to the operating system with orders to run \LaTeX . Each operating system handles these calls a little differently and our package must attempt to get this job done whether it is running on Windows, UNIX, Linux or Mac OS X.
+
+Portable \lang{C} code could be written to handle each of these situations, but that is starting to sound like work and we're trying to be lazy here. What we need is to be able to work at a higher {\itshape level of abstraction}. That is---instead of using \lang{C}, we need to be working inside a language that shields us from such details as what operating system is being used. \lang{R} may have called this \lang{C} function to calculate font metrics, but we really want to do the actual [...]
+
+\subsection{Calling \lang{R} Functions from \lang{C} Functions}
+
+The ``Ritual of the Calling of the \lang{R} Function'' is easy enough to perform as long as you don't have burning need to know all the details of the objects you are handling. The \lang{C} level representation of a \lang{R} object such as a variable or function is an object known as a \code{SEXP}. For the exact details on what a \code{SEXP} is and how it works, we refer the interested user to chapter one of the {\itshape \lang{R} Internals} manual.
+
+The \lang{R} function we will be calling is declared in the \lang{R} environment as follows:
+
+\begin{tikzCodeBlock}[title={Definition of target \lang{R} function},listing style=sweavechunk]
+getLatexCharMetrics <- function( charCode ){
+
+ # System call to LaTeX
+
+}
+\end{tikzCodeBlock}
+
+In order to call this function for \lang{C}, we need a vector composed of two \lang{C}-level \lang{R} objects---one containing the name of the function we are calling and another one containing the value we are passing for \code{charCode}. This is set up in \lang{C} as follows:
+
+\begin{tikzCodeBlock}[title={Preparing a \lang{R} function call inside \lang{C}}]
+void (metricInfo)(int c, const pGEcontext gc, double* ascent, double* descent,
+ double* width, pDevDesc dd){
+
+ SEXP RCallBack;
+ PROTECT( RCallBack = allocVector(LANGSXP, 2) );
+
+ SEXP metricFun = findFun( install("getLatexCharMetrics"), R_Global_Env );
+
+ SETCAR( RCallBack, metricFun );
+
+ SETCADR( RCallBack, ScalarInteger( c ) );
+ SET_TAG( CDR( RCallBack ), install("charCode") );
+
+ \\ To be continued...
+
+}
+\end{tikzCodeBlock}
+
+The first thing that happens in the code chunk above is that a new \code{SEXP} variable named \code{RCallBack} is created. This variable will be the agent through which we will communicate with the \lang{R} environment. The next action is to allocate our callback variable as a vector of length 2-- we need one slot for the \lang{R} function name and one slot for the value that is being passed into the function. This allocation happens inside the \lang{R} environment, so it is executed ins [...]
+
+The next portion of the \lang{C} function retrieves the \lang{R} function object for \code{getLatexCharMetrics}. The function is searched for in \lang{R} global namespace, so it must be one that is available to the user from the \lang{R} command prompt when the package is loaded. The function is stored in the \code{SEXP} variable \code{metricFun}. We do not have to involve \code{PROTECT} in the assignment since \code{getLatexCharMetrics} exists as a variable name in the \lang{R} environment.
+
+The last portion of the code chunk is responsible for loading the function name and call value into \code{RCallBack}. The \code{CAR} statement is used to retrieve the value of a \code{SEXP} variable and the \code{SETCAR} statement is used to set the value of a \code{SEXP}. In this case we use \code{SETCAR} to designate the \lang{R} function stored in \code{metricFun} as the first value of \code{RCallBack}.
+
+When dealing with a vector \code{SEXP} such as \code{RCallBack}, which has 2 slots, we need to use a different function to access the second slot. The \code{CDR} function will allow us to move to the second slot in \code{RCallBack} where we may perform a \code{SETCAR} to specify a value. In the example code, these operations were combined by using the \code{SETCADR} function which has the same effect as:
+
+\begin{tikzCodeBlock}[listing style=sweavechunk]
+SETCAR( CDR(RCallBack), ScalarInteger( c ) );
+\end{tikzCodeBlock}
+
+After assigning the value of the \lang{C} variable \code{c} as the second value of \code{RCallBack}, we need to ``tag'' it as the value that corresponds to the \code{charCode} argument of \code{getLatexCharMetrics}. This is done by using the \code{SET\_TAG} function. Once again, we use \code{CDR} to shift our area of operation to the second slot of \code{RCallBack}. Now that the \code{RCallBack} object is set up, we are ready to actually call the \code{getLatexCharMetrics} function.
+
+\begin{tikzCodeBlock}[title={Executing a \lang{R} function call inside \lang{C}}]
+SEXP LatexMetrics;
+PROTECT( LatexMetrics = eval( RCallBack, R_GlobalEnv) );
+\end{tikzCodeBlock}
+
+And that's it! We create a new \code{SEXP} to hold the return values of \code{getLatexCharMetrics} and execute the \code{eval} function to cause \code{getLatexCharMetrics} to be executed inside the \lang{R} environment. The details of the \lang{R} function will be explained in the next section, for now let's assume that it returns the three values we're interested in as a vector of three numbers. How do we extract these values and assign then to \code{ascent}, \code{descent} and \code{width}?
+
+\begin{tikzCodeBlock}[title={Recovering return values from a \lang{R} function call}]
+ *ascent = REAL(RMetrics)[0];
+ *descent = REAL(RMetrics)[1];
+ *width = REAL(RMetrics)[2];
+
+ UNPROTECT(2);
+
+ return;
+\end{tikzCodeBlock}
+
+Here the \code{REAL} function is used to coerce the \code{SEXP} variable \code{RMetrics} to a vector of real numbers. These numbers are then extracted and assigned to the return values of \code{metricInfo}. In \lang{C} we must specify the `first' value in a vector using the index 0 rather than the index 1. \footnote{There are good logical reasons for this from the point of view of a computer scientist---but if your background in arrays is rooted in linear algebra it will be a bit disorie [...]
+
+\subsection{Implementing a System Call to \LaTeX}
+
+Now we may turn to the actual guts of the \lang{R} function \code{getLatexCharMetrics}. The first thing we need to do is set up a file for \LaTeX{} input:
+
+\begin{tikzCodeBlock}[title={Creating a \LaTeX{} input file},listing style=sweavechunk]
+getLatexCharMetrics <- function( charCode ){
+
+ texDir <- tempdir()
+
+ texLog <- file.path( texDir,'tikzStringWidthCalc.log' )
+ texFile <- file.path( texDir,'tikzStringWidthCalc.tex' )
+
+ texIn <- file( texFile, 'w')
+
+ # To be continued...
+\end{tikzCodeBlock}
+
+The first thing we do is choose a place to create this input file. Now, when the \LaTeX{} compiler is run on a \code{.tex} file, a lot of additional files get created---the whole process is a bit messy. Since the user probably wouldn't appreciate having to clean up our mess, we use the \code{tempdir()} function to retrieve a path to a {\itshape temporary directory} on the system. Here is the first place we benefit from the added level of abstraction granted by \lang{R}. Each operating sy [...]
+
+Now that we have a place to work, we set up a couple of filenames---one for the input file, which ends in \code{.tex} and one for the \LaTeX{} log file, which ends in \code{.log}. We then open the \code{.tex} file for writing. The next step is to setup the preamble of the \LaTeX{} file.
+
+\begin{tikzCodeBlock}[title={Setting up the preamble of a \LaTeX{} input file},listing style=sweavechunk]
+ writeLines("\\documentclass{article}", texIn)
+
+ writeLines("\\usepackage[T1]{fontenc}", texIn)
+
+ writeLines("\\usepackage{tikz}", texIn)
+ writeLines("\\usetikzlibrary{calc}", texIn)
+
+ writeLines("\\batchmode", texIn)
+\end{tikzCodeBlock}
+
+Here we have started a standard \LaTeX{} input file by specifying
+\code{article} as the document class. We also add the \code{fontenc} package
+and specify \code{T1} as its option. This ensures we are using the Type 1 font
+encoding---by default \TeX{} and \LaTeX{} use an encoding called \code{OT1}. Why
+do we need to worry about font encodings? Well, a font encoding specifies which
+\code{ASCII} symbol codes map to which characters and by default, \lang{R}
+expects us to be using the Type 1 encoding (\lang{R} does support other
+encodings---but we're ignoring that for now). For example, in the Type 1
+encoding, the character that corresponds to the \code{ASCII} code 60 is the
+less-than sign: `{\char60}'. If we were to allow \TeX{}
+to retain its default \code{OT1} encoding, that same character code would
+instead map to an upside-down exclamation point: `{\usefont{OT1}{lmr}{m}{n}\char60}'.
+
+The other two packages we load are the \code{tikz} package and its \code{calc}
+library. Essentially we will have \TikZ{} drop the character into a box and
+report some measurements concerning the size of that box. The last command,
+\code{batchmode} tells \LaTeX{} that there isn't any user available to interact
+with---so it should not bother to stop and ask any questions while processing this
+file.
+
+The next step is to set up the part of the \LaTeX{} file that will actually
+calculate and report the widths we are looking for. As mentioned before, this
+is done by setting the character inside a \TikZ{} node and extracting the
+dimensions of the box that surrounds it. In an attempt to improve clarity, the
+following code will be presented as straight \LaTeX{} --
+\code{getLatexCharMetrics} inserts it into the \code{texIn} file by means of
+\code{writeLines} as we have been doing all along. The string highlighted in
+{\color{red} red} should be replaced with the value of the variable charCode
+that was passed in to the function \code{getLatexCharMetrics}.
+
+\begin{tikzCodeBlock}[title={Extracting character dimensions using \TikZ},listing style=latexexample]
+\begin{tikzpicture}
+
+\node[inner sep=0pt,outer sep=0pt] (char) {\charXXcharCodeXX};
+
+\path let \p1 = ($(char.east) - (char.west)$),
+ \n1 = {veclen(\x1,\y1)} in (char.east) -- (char.west)
+ node{ \typeout{tikzTeXWidth=\n1} };
+
+\path let \p1 = ($(char.north) - (char.base)$),
+ \n1 = {veclen(\x1,\y1)} in (char.north) -- (char.base)
+ node{ \typeout{tikzTeXAscent=\n1} };
+
+\path let \p1 = ($(char.base) - (char.south)$),
+ \n1 = {veclen(\x1,\y1)} in (char.base) -- (char.south)
+ node{ \typeout{tikzTeXDescent=\n1} };
+\end{tikzCodeBlock}
+
+What the heck just happened? Well, first we instructed \LaTeX{} to enter the \TikZ{} picture environment using \verb`\begin{tikzpicture}`. Then we ordered \TikZ{} to create a node named ``char'' containing the command \verb`\char` followed by the value of charCode. For example, if we were passed `103' as the character code, which corresponds to the character `g', the node line should be:
+
+\begin{tikzCodeBlock}[listing style=latexexample]
+\node[inner sep=0pt,outer sep=0pt] (char) {\char103};
+\end{tikzCodeBlock}
+
+The \code{inner sep} and \code{outer sep} options are set to \code{0pt} in order to ensure the boundaries of the node `hug' the contents tightly. Now the whole point of setting the character inside a node is that \TikZ{} defines `anchors' along the bounding box of the node. All anchors are referred using a \code{node name.posistion} notation. Since we named the node \code{char}, all the anchors start with \code{char}. The anchor posistions relevant to our problem are shown below:
+
+\begin{center}
+\begin{tikzpicture}
+
+ \node[draw=black, very thick,inner sep=0, outer sep=0, text=black!40,scale=14]
+ (char) {\char103};
+
+ \foreach \anchor/\placement in
+ {north/above, south/below, base/below, east/right, west/left} {
+
+ \draw[shift=(char.\anchor),color=red] plot[mark=*] coordinates{(0,0)}
+ node[\placement,text=red] {\small\texttt{(char.\anchor)}};
+ }
+
+ \node[above= 1em of char.north] {Node Bounding Box}
+ edge[ultra thick,->,>=stealth,out=0,in=0] ($(char.10) + (6pt,12pt)$);
+
+
+\end{tikzpicture}
+\end{center}
+
+The `base' anchor sits on the baseline of the text---therefore to calculate the ascent of the character `g', all we have to do is figure out the difference in height between the positions \code{char.north} and \code{char.base}. Similarly, for the descent we would calculate the difference in height between \code{char.base} and \code{char.south} and width can be obtained using \code{char.west} and \code{char.east}. This is the purpose of the admittedly cryptic \verb`\path` commands that ar [...]
+
+\begin{tikzCodeBlock}[]
+\path let \p1 = ($(char.north) - (char.base)$),
+ \n1 = {veclen(\x1,\y1)} in node{ \typeout{tikzTeXAscent=\n1} };
+\end{tikzCodeBlock}
+
+So, what exactly is going on here? Normally, the \verb`\path` command is used to draw lines between points and add additional coordinates or nodes along those lines. For example, the command:
+
+\begin{tikzCodeBlock}[]
+\path[draw] (0,0) -- (1,1) node {Hi!};
+\end{tikzCodeBlock}
+
+Draws a line from \code{(0,0)} to \code{(1,1)} and places a node at \code{(1,1)} containing the word `Hi!'. In the \TikZ{} code produced by \code{getLatexCharMetrics}, the \code{let} operation is specified. Basically, \code{let} postpones the actual drawing of a path and performs calculations until the \code{in} keyword is encountered. The result of these calculations are stored in a set of special variables which must start with \verb`\n`, \verb`\p`, \verb`\x` or \verb`\y`. The first \c [...]
+
+\begin{tikzCodeBlock}[]
+\p1 = ( $(char.north) - (char.base)$ )
+\end{tikzCodeBlock}
+
+This performs a vector subtraction between the coordinates of \code{char.north} and \code{char.base}. The resulting x and y components are stored in the `point' variable \verb`\p1`. The second operation executed is:
+
+\begin{tikzCodeBlock}[]
+\n1 = {veclen(\x1,\y1)}
+\end{tikzCodeBlock}
+
+This \code{let} operation treats the coordinates stored in \verb`\p1` as a vector and calculates its magnitude. The `1' appended to the \verb`\x` and \verb`\y` variables specifies that we are accessing the x and y components of \verb`\p1`. This result is stored in the `number' variable \verb`\n1`. Now, that our metric is stored in \verb`\n1`, our final task is to ensure it makes it into the \LaTeX{} \code{.log} file---this is done by adding a \code{node} containing the \verb`\typeout` co [...]
+\begin{tikzCodeBlock}[]
+\typeout{tikzTexAscent=\n1}
+\end{tikzCodeBlock}
+cause the phrase `tikzTexAscent=' to appear in the \code{.log} file---followed by the ascent calculated using the node anchors. After the ascent, descent and width have been calculated the \LaTeX{} compiler may be shut down, this is done by adding the final two lines to the input file:
+
+\begin{tikzCodeBlock}[title={Terminating a \LaTeX{} compilation},listing style=sweavechunk]
+ writeLines("\\makeatother", texIn)
+
+ writeLines("\\@@end", texIn)
+
+ close(texIn)
+\end{tikzCodeBlock}
+
+Now that the input file has been prepped, we must process it using the \LaTeX{} compiler and load the contents of the resulting \code{.log} so that we may search for the metrics we dumped using \verb`\typeout`.
+
+\begin{tikzCodeBlock}[title={Terminating a \LaTeX{} compilation},listing style=sweavechunk]
+ latexCmd <- getOption('tikzLatex')
+ latexCmd <- paste( latexCmd, '-interaction=batchmode',
+ '-output-directory', texDir, texFile)
+
+ silence <- system( latexCmd, intern=T, ignore.stderr=T)
+
+ texOut <- file( texLog, 'r' )
+
+ logContents <- readLines( texOut )
+ close( texOut )
+\end{tikzCodeBlock}
+
+The \LaTeX{} compiler is executed through the \code{system} function which handles the details of implementing a system call on whatever operating system we happen to be using. We assign the return value of the \code{system} function to a dummy variable called \code{silence} so that no output floods the user's screen. The last task is to extract our metrics from the text of the \code{.log} we loaded.
+
+\begin{tikzCodeBlock}[title={Parsing the \code{.log} file text},listing style=sweavechunk]
+ match <- logContents[ grep('tikzTeXWidth=', logContents) ]
+ width <- gsub('[=A-Za-z]','',match)
+
+ match <- logContents[ grep('tikzTeXAscent=', logContents) ]
+ ascent <- gsub('[=A-Za-z]','',match)
+
+ match <- logContents[ grep('tikzTeXDescent=', logContents) ]
+ descent <- gsub('[=A-Za-z]','',match)
+
+ return( as.double( c(ascent,descent,width) ) )
+\end{tikzCodeBlock}
+
+Here we use the \code{grep} function to search through the log output for the tags `tikzTeXWidth=', `tikzTeXAscent=' and `tikzTeXDescent=' that we specified when we used \verb`\typeout`. After we recover a line containing one of these tags, we use the \code{gsub} command to remove the letters and the equals sign from the text line---leaving just the number we're interested in. These values are then coerced using \code{as.double} and set as the return value of \code{getLatexCharMetrics}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\chapter{On the Importance of Font and Style Consistency in Reports}
+If you haven't figured it out by now, we are quite picky about the way our graphics and reports look. We are especially picky about the consistency in fonts (both sizes and shapes). Without launching into a diatribe about this, we just want to say with tools like \pkg{tikzDevice} you no longer have to settle for what is ``just okay.'' So go nuts, be picky about how your text and graphics look. Don't be afraid to snub your nose at reports which pay no attention to detail. Be that pers [...]
+
+\section{The \pkg{pgfSweave} Package and Automatic Report Generation}
+Now for a little shameless self promotion. The authors of \pkg{tikzDevice} have another package called \pkg{pgfSweave} which provides a driver for Sweave. \pkg{pgfSweave} started as an interface to \href{http://sourceforge.net/projects/eps2pgf/}{eps2pgf} and its ability to interpret strings in eps files as \LaTeX{}. This was used to much the same effect as \pkg{tikzDevice}. The problem was the conversion from eps to pgf was SLOW. Long story short, by combining this functionality with [...]
+
+\newpage
+
+\bibliography{refs}
+
+\end{document}\n
diff --git a/vignettes/tikzDeviceVignette.sty b/vignettes/tikzDeviceVignette.sty
new file mode 100644
index 0000000..9758bde
--- /dev/null
+++ b/vignettes/tikzDeviceVignette.sty
@@ -0,0 +1,305 @@
+% !TEX root = tikzDevice.Rnw
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{tikzDeviceVignette}
+
+\RequirePackage{xspace}
+\RequirePackage[T1]{fontenc}
+\RequirePackage{microtype}
+\RequirePackage{lmodern}
+\IfFileExists{zi4.sty}{%
+ \RequirePackage[scaled=.85]{zi4}}{%
+ \RequirePackage[scaled=.85]{inconsolata}}
+\RequirePackage[colorlinks]{hyperref}
+
+% Various TeX logos---included in the Oberdiek bundle which contains hyperref,
+% so there is a good chance it will be installed.
+\IfFileExists{hologo.sty}{\RequirePackage{hologo}}{}
+\providecommand\hologo[1]{#1\xspace}
+
+% Sexyness
+\RequirePackage{tikz}
+\usetikzlibrary{calc,positioning}
+\usetikzlibrary{shapes.multipart,shapes.geometric,shapes.symbols,shapes.arrows}
+\usetikzlibrary{decorations.shapes,decorations.text,decorations.pathreplacing}
+
+% Page layout
+\RequirePackage{epigraph}
+\RequirePackage{multicol}
+\RequirePackage{pdflscape}
+
+% Graphics control.
+\RequirePackage{graphicx}
+\RequirePackage{float}
+
+% Bibliography
+\RequirePackage{natbib}
+\bibliographystyle{agufull04}
+\RequirePackage[english]{babel}
+
+\RequirePackage{fancyvrb}
+% Extra pretty pretty printing.
+\RequirePackage{tikzCodeBlock}
+\RequirePackage{sweavetolst}
+
+% Text macros
+\newcommand{\TikZ}{Ti\textit{k}Z}
+
+
+% -----------------------------------------------------------------------------
+% Page Setup
+% -----------------------------------------------------------------------------
+
+% Text Block and Margins
+% ======================
+% See page p. 72 of the memoir manual
+% Define text width by setting right and left margins
+\setlrmarginsandblock{0.75in}{0.75in}{*}
+% Define text height by setting upper and lower margins
+\setulmarginsandblock{0.75in}{1.25in}{*}
+% These define the distance from the type block of the header and footer
+\setheadfoot{\baselineskip}{0.25in}
+\setheaderspaces{*}{0.25in}{*}
+\checkandfixthelayout
+
+% Header and Footer
+% =================
+\makepagestyle{tikzDevice}
+ \makeevenhead{tikzDevice}{\leftmark}{}{\thepage}
+ \makeoddhead{tikzDevice}{\rightmark}{}{\thepage}
+ \makeheadrule{tikzDevice}{\textwidth}{\normalrulethickness}
+ \makepsmarks{tikzDevice}{%
+ \nouppercaseheads
+ \createmark{chapter}{both}{nonumber}{}{}
+ \createplainmark{toc}{both}{\contentsname}
+ \createplainmark{lof}{both}{\listfigurename}
+ \createplainmark{lot}{both}{\listtablename}
+ \createplainmark{bib}{both}{\bibname}
+ \createplainmark{index}{both}{\indexname}
+ \createplainmark{glossary}{both}{\glossaryname}
+ }
+ \makeevenfoot{tikzDevice}{{\footnotesize\TikZ}Device}{}{\LaTeX\ Graphics for \lang{R}}
+ \makeoddfoot{tikzDevice}{{\footnotesize\TikZ}Device}{}{\LaTeX\ Graphics for \lang{R}}
+ \makefootrule{tikzDevice}{\textwidth}{\normalrulethickness}{\footruleskip}
+
+\pagestyle{tikzDevice}
+
+% Styles for Document Divisions
+% =============================
+
+
+% Part Divisions
+% --------------
+% Inspired by the cover page of the tikzDevice manual.
+
+% Kill the commands memoir normally uses to set the part name and
+% number---everything will be taken care of by the command that sets the title.
+\renewcommand{\printpartname}{}
+\renewcommand{\printpartnum}{}
+
+% Define a command that can be used to add custom graphics to each part page.
+\newcommand{\partimage}[1]{\gdef\@partimage{#1}}
+\partimage{\null}
+
+% This is where all the magic happens.
+\renewcommand{\printparttitle}[1]{
+ \begin{tikzpicture}[remember picture, overlay]
+ % Title and Info
+ % --------------
+ {\fontsize{60}{36}
+ \node[below right = 0.5em of current page.north west,
+ anchor = north east,
+ rotate = 90,
+ outer sep = 0pt,
+ inner sep = 0pt,
+ font = {\bfseries}
+ ]
+ (title)
+ {\partname\ \thepart};
+ }
+
+ \draw[line width = 5pt] ([xshift = 7.5pt]title.base west) -- ([xshift = 7.5pt]title.base east);
+
+ \node[right = 12.5pt of title.base east,
+ anchor = north west,
+ align = left,
+ font = {\Huge\bfseries}
+ ]
+ (subtitle)
+ {#1};
+
+ \@partimage
+
+ \end{tikzpicture}%
+ \partimage{\null} % Make sure a part image is not recycled
+}
+
+\aliaspagestyle{part}{empty}
+
+
+% Chapter Divisions
+% -----------------
+% Inspired by Alain Matthes' tkz-doc class which uses `\titleformat[frame]`
+% from the `titlesec` package. A similar result is produced here using TikZ
+% nodes. Helpful tips for handling numberd/non-numbered chapters taken from the
+% documentation of the `memoirchapterstyles` package by Lars Madsen.
+\makechapterstyle{tkzframed}{%
+ % Inherit most attributes, such as spacing, from Memoir's article chapter
+ % style.
+ \chapterstyle{article}
+
+ % The chapter number has to be set after the title since it is positioned
+ % relative to a node containing the title. A boolean is used to control the
+ % appearance of the node containing the chapter numbers.
+ \newif\ifnumberedchap
+ \numberedchaptrue
+ \renewcommand{\printchapternum}{\global\numberedchaptrue}
+ \renewcommand{\printchapternonum}{\global\numberedchapfalse}
+ \renewcommand{\chapnumfont}{\footnotesize\scshape}
+
+ \renewcommand{\printchaptertitle}[1]{%
+ \begin{tikzpicture}
+ % Print text inside a block containing the font commands so that
+ % parameters such as `\baselineskip` and sizes such as `em` and `ex` are
+ % sized relative to the font size.
+ {\chapnamefont
+ \node[draw,
+ line width = \fboxrule,
+ outer sep = 0pt,
+ inner xsep = 0pt,
+ inner ysep = \baselineskip,
+ text width = \linewidth,
+ align = center
+ ]
+ (title)
+ % Double the hash symbol, #, because this macro definition is inside
+ % another macro definition.
+ {##1};
+ }
+ \ifnumberedchap
+ {\chapnumfont
+ \node[
+ fill = white,
+ anchor = west,
+ right = 1ex of title.north west,
+ outer sep = 0pt,
+ inner xsep = 0.5em,
+ inner ysep = 0pt
+ ]
+ % Set the chapter number using old-style lower case numerals, if
+ % available.
+ {Chapter \oldstylenums{\thechapter}};
+ }
+ \fi
+ \end{tikzpicture}%
+ }
+}
+
+\chapterstyle{tkzframed}
+% Don't mess with the header/footer when starting a new chapter.
+\aliaspagestyle{chapter}{tikzDevice}
+
+
+% Section Divisions
+% -----------------
+% The style of sectional divisions is also cribbed from tkz-doc. Here we define
+% a hook function that gets called before setting section titles. The hook
+% function causes the section number to be placed within a `\fbox` and tosses
+% in a following quad (1em) space. During typesetting, the macro
+% `\setsecnumformat` is passed a single parameter, represented by `##1`, that
+% contains the division level---in this case: section. This is transformed into
+% `\thesection` by `\csname` and `\endcsname` which is the name of the counter
+% storing the section number.
+\setsecheadstyle{\large\bfseries}
+\setsechook{\setsecnumformat{\fbox{\csname the##1\endcsname}\quad}}
+
+% TODO:
+% Style subsections and below (if used).
+
+% Don't number any division below section level.
+\maxtocdepth{subsection}
+\setsecnumdepth{section}
+
+
+% Font macros
+\newcommand{\lang}{\textsf}
+% Mbox it to prevent hyphenation of code
+\newcommand{\code}[1]{\mbox{\ttfamily #1}}
+\newcommand{\pkg}{\textbf}
+\newcommand{\pkgopt}[1]{{\color{red}#1}}
+
+% Other LaTeX macros
+\renewcommand{\sectionautorefname}{Section}
+\renewcommand{\subsectionautorefname}{Subsection}
+
+
+% Source code formatting macros
+\lstset{basicstyle = \ttfamily}
+
+\lstdefinestyle{latexsource}{
+ language = [LaTeX]TeX,
+ showstringspaces = false,
+ upquote = false,
+ commentstyle = {\color{red!80}\itshape}
+}
+
+\lstdefinestyle{latexexample}{
+ language = [LaTeX]TeX,
+ showstringspaces = false,
+ upquote = false,
+ commentstyle = {\color{red!80}\itshape},
+ moredelim=[is][\color{red}]{XX}{XX}
+}
+
+\lstdefinestyle{bashsource}{
+ language = bash,
+ % literate={~}{{$\sim$}}1,
+ moredelim=[is][\color{gray}]
+ {!out}
+ {!/out},
+ showstringspaces = false,
+ upquote = false,
+ commentstyle = {\color{blue!80}\itshape}
+}
+
+\lstdefinestyle{csource}{
+ language = c,
+ upquote = false,
+ commentstyle = {\color{blue!80}\itshape}
+}
+
+
+% TikZ Style definitions.
+\tikzset{
+ % Taken from one of the first examples in the PGF manuel.
+ package warning/.style={
+ rectangle split,
+ rectangle split parts = 2,
+ rounded corners,
+ draw = red!50,
+ thick,
+ fill = red!10,
+ inner sep = 1ex,
+ text width = \textwidth
+ }
+}
+
+
+% TikZ Macros.
+
+\newcommand{\tikzDocDisclaim}[2]{
+ \noindent\begin{tikzpicture}
+
+ \node[package warning]{
+ \begin{center}
+ \large\bfseries
+ #1
+ \end{center}
+ \nodepart{second}
+ #2
+ };
+
+ \end{tikzpicture}%
+}
+
+\endinput
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-tikzdevice.git
More information about the debian-med-commit
mailing list