├── inst └── staticdocs │ ├── index.R │ └── README.md ├── .github ├── .gitignore └── workflows │ ├── test-coverage.yaml │ └── R-CMD-check.yaml ├── .gitattributes ├── revdep ├── .gitignore ├── failures.md ├── problems.md └── README.md ├── tests ├── testthat │ ├── .tikzMetrics │ │ └── .gitignore │ ├── standard_graphs │ │ ├── graph_box.pdf │ │ ├── hello_TeX.pdf │ │ ├── line_color.pdf │ │ ├── line_types.pdf │ │ ├── persp_3D.pdf │ │ ├── polypath.pdf │ │ ├── text_color.pdf │ │ ├── base_raster.pdf │ │ ├── draw_circles.pdf │ │ ├── ggplot2_test.pdf │ │ ├── grid_raster.pdf │ │ ├── line_weights.pdf │ │ ├── plot_legend.pdf │ │ ├── transparency.pdf │ │ ├── base_annotation.pdf │ │ ├── contour_lines.pdf │ │ ├── grid_annotation.pdf │ │ ├── pch_caracters.pdf │ │ ├── text_alignment.pdf │ │ ├── utf8_characters.pdf │ │ ├── xetex_variants.pdf │ │ ├── filled_rectangle.pdf │ │ ├── line_color_width.pdf │ │ ├── lots_of_elements.pdf │ │ ├── raster_reflection.pdf │ │ ├── string_placement.pdf │ │ ├── annotation_noflush.pdf │ │ ├── base_symbolic_simple.pdf │ │ ├── character_expansion.pdf │ │ ├── draw_filled_circles.pdf │ │ ├── ggplot2_superscripts.pdf │ │ ├── base_raster_noresample.pdf │ │ ├── luatex_utf8_characters.pdf │ │ └── ggplot_old │ │ │ ├── ggplot2_test.pdf │ │ │ └── ggplot2_superscripts.pdf │ ├── test_misc.R │ ├── test_pointsize.R │ ├── helper_bootstrap.R │ ├── test_error_handling.R │ ├── test_metrics_dict.R │ └── helper_graphics.R └── testthat.R ├── docs ├── pkgdown.yml ├── articles │ └── tikzDevice.pdf ├── link.svg ├── docsearch.js ├── pkgdown.js ├── pkgdown.css ├── authors.html ├── reference │ ├── tikzCompilerInfo.html │ ├── tikzTest.html │ ├── gridToDevice.html │ ├── index.html │ ├── anyMultibyteUTF8Characters.html │ ├── setTikzDefaults.html │ └── sanitizeTexString.html └── news │ └── index.html ├── vignettes ├── img │ ├── Rlogo.png │ ├── xelatexEx.pdf │ ├── plotmathTikz.pdf │ └── plotmathDefault.pdf ├── .gitignore ├── consoleExample.tex ├── refs.bib ├── sweavetolst.sty └── tikzDeviceVignette.sty ├── codecov.yml ├── cran-comments.md ├── _pkgdown.yml ├── .gitignore ├── tikzDevice.Rproj ├── .Rbuildignore ├── src ├── init.c └── tikzDevice.h ├── R ├── tikzInternal.R ├── sanitizeTexString.R ├── zzz.R ├── cacheMetrics.R └── tikzDevice-package.R ├── man ├── tikzCompilerInfo.Rd ├── tikzTest.Rd ├── setTikzDefaults.Rd ├── gridToDevice.Rd ├── anyMultibyteUTF8Characters.Rd ├── sanitizeTexString.Rd ├── getLatexStrWidth.Rd ├── tikzDevice-package.Rd ├── tikzAnnotate.Rd └── tikz.Rd ├── appveyor.yml ├── NAMESPACE ├── DESCRIPTION ├── README.md └── TODO /inst/staticdocs/index.R: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /NEWS.md merge=union 2 | -------------------------------------------------------------------------------- /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | **/ 2 | data.sqlite 3 | -------------------------------------------------------------------------------- /revdep/failures.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /revdep/problems.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /tests/testthat/.tikzMetrics/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.3.1 2 | pkgdown: 1.3.0 3 | pkgdown_sha: ~ 4 | articles: {} 5 | 6 | -------------------------------------------------------------------------------- /vignettes/img/Rlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/vignettes/img/Rlogo.png -------------------------------------------------------------------------------- /vignettes/img/xelatexEx.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/vignettes/img/xelatexEx.pdf -------------------------------------------------------------------------------- /docs/articles/tikzDevice.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/docs/articles/tikzDevice.pdf -------------------------------------------------------------------------------- /vignettes/img/plotmathTikz.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/vignettes/img/plotmathTikz.pdf -------------------------------------------------------------------------------- /vignettes/img/plotmathDefault.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/vignettes/img/plotmathDefault.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/graph_box.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/graph_box.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/hello_TeX.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/hello_TeX.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/line_color.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/line_color.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/line_types.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/line_types.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/persp_3D.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/persp_3D.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/polypath.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/polypath.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/text_color.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/text_color.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/base_raster.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/base_raster.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/draw_circles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/draw_circles.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/ggplot2_test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/ggplot2_test.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/grid_raster.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/grid_raster.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/line_weights.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/line_weights.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/plot_legend.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/plot_legend.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/transparency.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/transparency.pdf -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | if (nchar(Sys.getenv("R_TESTS")) == 0) { 2 | library(testthat) 3 | library(tikzDevice) 4 | 5 | test_check("tikzDevice") 6 | } 7 | -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/base_annotation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/base_annotation.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/contour_lines.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/contour_lines.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/grid_annotation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/grid_annotation.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/pch_caracters.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/pch_caracters.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/text_alignment.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/text_alignment.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/utf8_characters.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/utf8_characters.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/xetex_variants.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/xetex_variants.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/filled_rectangle.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/filled_rectangle.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/line_color_width.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/line_color_width.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/lots_of_elements.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/lots_of_elements.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/raster_reflection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/raster_reflection.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/string_placement.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/string_placement.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/annotation_noflush.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/annotation_noflush.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/base_symbolic_simple.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/base_symbolic_simple.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/character_expansion.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/character_expansion.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/draw_filled_circles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/draw_filled_circles.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/ggplot2_superscripts.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/ggplot2_superscripts.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/base_raster_noresample.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/base_raster_noresample.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/luatex_utf8_characters.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/luatex_utf8_characters.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/ggplot_old/ggplot2_test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/ggplot_old/ggplot2_test.pdf -------------------------------------------------------------------------------- /tests/testthat/standard_graphs/ggplot_old/ggplot2_superscripts.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daqana/tikzDevice/HEAD/tests/testthat/standard_graphs/ggplot_old/ggplot2_superscripts.pdf -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | /figs 2 | /*.tmp 3 | /*.aux 4 | /*.bbl 5 | /*.blg 6 | /*.log 7 | /*.lst 8 | /*.lstin 9 | /*.out 10 | /*.pdf 11 | /*.tex 12 | /*.toc 13 | /.tikzMetrics 14 | /Sweave.sty 15 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | patch: 10 | default: 11 | target: auto 12 | threshold: 1% 13 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | This upload corrects an error message fixing a recent WARNING. 2 | 3 | ## Test environments 4 | 5 | * local: Linux with R 4.3.1 6 | * GitHub: 7 | * Ubuntu, R release, R-devel 8 | * winbuilder: Windows, R-devel 9 | 10 | ## R CMD check results 11 | 12 | 0 errors | 0 warnings | 0 notes 13 | 14 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | navbar: 2 | title: tikzDevice 3 | left: 4 | - text: Home 5 | href: index.html 6 | - text: Get started 7 | href: articles/tikzDevice.pdf 8 | - text: Reference 9 | href: reference/index.html 10 | - text: Changelog 11 | href: news/index.html 12 | right: 13 | - icon: fa-github 14 | href: https://github.com/daqana/tikzDevice 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.Rproj.user 2 | /.Rhistory 3 | /inst/doc/* 4 | /src/*.o 5 | /src/*.so 6 | /src/*.dll 7 | /tests/test_output 8 | /tests/test_work 9 | /tests/testthat/test_output 10 | /tests/testthat/test_work 11 | /tests/testthat/Rplots* 12 | /test_output 13 | /test_work 14 | .Rproj.user 15 | /inst/web 16 | /vignettes/*.synctex.gz 17 | /.idea/ 18 | /CMakeLists.txt 19 | /clion-test.R 20 | /cmake-build-debug/ 21 | debug 22 | -------------------------------------------------------------------------------- /vignettes/consoleExample.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage{tikz} 3 | 4 | 5 | \begin{document} 6 | \begin{figure}[ht] 7 | \centering 8 | <>= 9 | 10 | require(tikzDevice) 11 | tikz(console=TRUE,width=5,height=5) 12 | x <- rnorm(100) 13 | plot(x) 14 | dummy <- dev.off() 15 | @ 16 | \caption{caption} 17 | \label{fig:inline} 18 | \end{figure} 19 | \end{document} 20 | -------------------------------------------------------------------------------- /tikzDevice.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageBuildArgs: --compact-vignettes=gs+qpdf 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /tests/testthat/test_misc.R: -------------------------------------------------------------------------------- 1 | context("Miscellaneous tests") 2 | 3 | test_that("ggsave should save a *.tex file when used with 'device=tikzDevice::tikz", { 4 | ggsave_path = paste0(test_output_dir, "/ggsave.tex") 5 | if(file.exists(ggsave_path)) { 6 | file.remove(ggsave_path) 7 | } 8 | g = ggplot2::ggplot(data.frame()) 9 | expect_error(ggplot2::ggsave(ggsave_path, g, device=tikzDevice::tikz), NA) 10 | expect_true(file.exists(ggsave_path)) 11 | }) 12 | 13 | test_that("closing tikz device with no error", { 14 | tikzDevice::tikz(onefile = FALSE) 15 | expect_error(dev.off(), NA) 16 | }) 17 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^CRAN-RELEASE$ 2 | \.git.*$ 3 | NEWS.pdf 4 | README.md 5 | TODO 6 | updateVersion.sh 7 | md2news.hs 8 | Makefile 9 | tests/test_work 10 | tests/test_output 11 | tests/testthat/test_work 12 | tests/testthat/test_output 13 | ^.*\.Rproj$ 14 | ^\.Rproj\.user$ 15 | GNUmakefile 16 | ^\.travis\.yml$ 17 | ^cran-comments\.md$ 18 | ^appveyor\.yml$ 19 | ^revdep$ 20 | inst/staticdocs 21 | ^tests/testthat/\.tikzMetrics$ 22 | ^vignettes/\.tikzMetrics$ 23 | vignettes/.*\.synctex\.gz$ 24 | .idea$ 25 | CMakeLists\.txt$ 26 | clion-test\.R$ 27 | cmake-build-debug$ 28 | ^codecov\.yml$ 29 | ^_pkgdown\.yml$ 30 | ^docs$ 31 | ^debug$ 32 | ^\.github$ 33 | -------------------------------------------------------------------------------- /revdep/README.md: -------------------------------------------------------------------------------- 1 | # Platform 2 | 3 | |field |value | 4 | |:--------|:-----------------------------| 5 | |version |R version 3.5.2 (2018-12-20) | 6 | |os |Debian GNU/Linux bullseye/sid | 7 | |system |x86_64, linux-gnu | 8 | |ui |RStudio | 9 | |language |en_US:en | 10 | |collate |en_US.UTF-8 | 11 | |ctype |en_US.UTF-8 | 12 | |tz |Europe/Berlin | 13 | |date |2019-08-07 | 14 | 15 | # Dependencies 16 | 17 | |package | old|new |Δ | 18 | |:----------|----:|:------|:--| 19 | |tikzDevice | 0.12|0.12.3 |* | 20 | |filehash | NA|2.4-2 |* | 21 | 22 | # Revdeps 23 | 24 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /tests/testthat/test_pointsize.R: -------------------------------------------------------------------------------- 1 | context("Querying of pointsize") 2 | 3 | test_that("Pointsize is extracted correctly", { 4 | expect_equal(getDocumentPointsize("\\documentclass[draft,12pt]{article}"), 12) 5 | expect_equal(getDocumentPointsize("\\documentclass[11pt,draft]{article}"), 11) 6 | expect_equal(getDocumentPointsize("\\documentclass[ 10pt ,draft]{article}"), 10) 7 | expect_equal(getDocumentPointsize("\\documentclass[10pt]{article}"), 10) 8 | expect_true(is.na(getDocumentPointsize("\\documentclass{article}"))) 9 | expect_true(is.na(getDocumentPointsize("\\documentclass{report}"))) 10 | expect_equal(getDocumentPointsize("\\documentclass[12pt]{report}\n"), 12) 11 | expect_true(is.na(getDocumentPointsize("\\documentclass{report}\n"))) 12 | expect_equal(getDocumentPointsize("\\PassOptionToPackage{x}{y}\n\\documentclass[11pt]{report}\n"), 11) 13 | }) 14 | -------------------------------------------------------------------------------- /src/init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // for NULL 4 | #include 5 | 6 | #include "tikzDevice.h" 7 | 8 | 9 | static const R_CMethodDef CEntries[] = { 10 | {"TikZ_Annotate", (DL_FUNC) &TikZ_Annotate, 3}, 11 | {NULL, NULL, 0} 12 | }; 13 | 14 | static const R_CallMethodDef CallEntries[] = { 15 | {"TikZ_DeviceInfo", (DL_FUNC) &TikZ_DeviceInfo, 1}, 16 | {"TikZ_EvalWithoutInterrupts", (DL_FUNC) &TikZ_EvalWithoutInterrupts, 2}, 17 | {NULL, NULL, 0} 18 | }; 19 | 20 | static const R_ExternalMethodDef ExternalEntries[] = { 21 | {"TikZ_StartDevice", (DL_FUNC) &TikZ_StartDevice, -1}, 22 | {NULL, NULL, 0} 23 | }; 24 | 25 | void R_init_tikzDevice(DllInfo *dll) 26 | { 27 | R_registerRoutines(dll, CEntries, CallEntries, NULL, ExternalEntries); 28 | R_useDynamicSymbols(dll, FALSE); 29 | } 30 | -------------------------------------------------------------------------------- /R/tikzInternal.R: -------------------------------------------------------------------------------- 1 | # These are unexported functions that are called by the C routines of the tikz 2 | # device to execute tasks that are difficult to do at the C level. 3 | 4 | getDateStampForTikz <- function() { 5 | 6 | # This function retrieves the current date stamp using 7 | # sys.time() and formats it to a string. This function 8 | # is used by the C routine Print_TikZ_Header to add 9 | # date stamps to output files. 10 | 11 | return(strftime(Sys.time())) 12 | } 13 | 14 | getTikzDeviceVersion <- function() { 15 | as.character(packageVersion("tikzDevice")) 16 | } 17 | 18 | tikz_writeRaster <- function(fileName, rasterCount, nativeRaster) { 19 | raster_file <- paste0( 20 | tools::file_path_sans_ext(fileName), 21 | "_ras", rasterCount, ".png" 22 | ) 23 | 24 | png::writePNG(nativeRaster, raster_file) 25 | 26 | return( 27 | basename(tools::file_path_sans_ext(raster_file)) 28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /man/tikzCompilerInfo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deviceUtils.R 3 | \name{tikzCompilerInfo} 4 | \alias{tikzCompilerInfo} 5 | \title{Print paths to TeX compilers.} 6 | \usage{ 7 | tikzCompilerInfo(verbose = TRUE) 8 | } 9 | \arguments{ 10 | \item{verbose}{If set to \code{FALSE}, calling this function will not cause any output to 11 | be printed to the screen. Defaults to \code{TRUE}.} 12 | } 13 | \value{ 14 | Invisibly returns a list containing paths to TeX compilers. 15 | } 16 | \description{ 17 | This function reports information concerning compilers that the \code{tikz} 18 | device will use to calculate character metrics. Information on LaTeX will 19 | always be available but information on XeLaTeX and LuaLaTeX will only be 20 | reported if the compilers were found. 21 | } 22 | \seealso{ 23 | \code{\link[=tikz]{tikz()}} 24 | } 25 | \author{ 26 | Charlie Sharpsteen \email{source@sharpsteen.net} 27 | } 28 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | # Adapt as necessary starting from here 14 | 15 | environment: 16 | WARNINGS_ARE_ERRORS: 1 17 | R_CHECK_ARGS: --ignore-vignettes --no-manual --no-examples --as-cran 18 | 19 | build_script: 20 | - travis-tool.sh install_deps 21 | 22 | test_script: 23 | - travis-tool.sh run_tests 24 | 25 | on_failure: 26 | - travis-tool.sh dump_logs 27 | 28 | artifacts: 29 | - path: '*.Rcheck\**\*.log' 30 | name: Logs 31 | 32 | - path: '*.Rcheck\**\*.out' 33 | name: Logs 34 | 35 | - path: '*.Rcheck\**\*.fail' 36 | name: Logs 37 | 38 | - path: '*.Rcheck\**\*.Rout' 39 | name: Logs 40 | 41 | - path: '\*_*.tar.gz' 42 | name: Bits 43 | 44 | - path: '\*_*.zip' 45 | name: Bits 46 | -------------------------------------------------------------------------------- /man/tikzTest.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deviceUtils.R 3 | \name{tikzTest} 4 | \alias{tikzTest} 5 | \title{Test invocation of a LaTeX engine.} 6 | \usage{ 7 | tikzTest( 8 | texString = "A", 9 | engine = getOption("tikzDefaultEngine"), 10 | documentDeclaration = getOption("tikzDocumentDeclaration"), 11 | packages 12 | ) 13 | } 14 | \arguments{ 15 | \item{texString}{An arbitrary string for which the width is to be 16 | calculated. May contain LaTeX markup.} 17 | 18 | \item{engine}{a string specifying which TeX engine to use. Possible values 19 | are 'pdftex', 'xetex' and 'luatex'. See the Unicode section of 20 | \link{tikzDevice-package} for details.} 21 | 22 | \item{documentDeclaration}{See the sections "Options That Affect Package 23 | Behavior" and "Font Size Calculations" of \link{tikzDevice-package} 24 | for more details.} 25 | 26 | \item{packages}{See the section "Options That Affect Package Behavior" of 27 | \link{tikzDevice-package}.} 28 | } 29 | \description{ 30 | This function simulates the measurement of dimensions and prints detailed 31 | information in case of errors. 32 | } 33 | \seealso{ 34 | \code{\link[=tikz]{tikz()}} 35 | } 36 | -------------------------------------------------------------------------------- /inst/staticdocs/README.md: -------------------------------------------------------------------------------- 1 | tikzDevice 2 | ========== 3 | 4 | [![Build Status](https://travis-ci.org/yihui/tikzDevice.svg)](https://travis-ci.org/yihui/tikzDevice) [![Coverage Status](https://coveralls.io/repos/yihui/tikzDevice/badge.svg)](https://coveralls.io/r/yihui/tikzDevice) 5 | 6 | The tikzDevice package provides a graphics output device for R that records 7 | plots in a LaTeX-friendly format. The device transforms plotting commands 8 | issued by R functions into LaTeX code blocks. When included in a paper typeset 9 | by LaTeX, these blocks are interpreted with the help of TikZ---a graphics 10 | package for TeX and friends written by Till Tantau. 11 | 12 | Using the tikzDevice, the text of R plots can contain LaTeX commands such as 13 | mathematical formula. The device also allows arbitrary LaTeX code to be 14 | inserted into the output stream. 15 | 16 | The tikzDevice supports three main modes of output: 17 | 18 | - Figure chunks: placed in .tex files and suitable for inclusion in LaTeX 19 | documents via the \input{} command. 20 | 21 | - Stand alone figures: Complete LaTeX documents containing figure code that 22 | can be compiled into stand-alone images. Pages are cropped to the size of 23 | the figure using the LaTeX preview package. 24 | 25 | - Console output: TikZ code is returned directly to the R console as a 26 | character vector for further manipulation. 27 | -------------------------------------------------------------------------------- /man/setTikzDefaults.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deviceUtils.R 3 | \name{setTikzDefaults} 4 | \alias{setTikzDefaults} 5 | \title{Reset tikzDevice options to default values.} 6 | \usage{ 7 | setTikzDefaults(overwrite = TRUE) 8 | } 9 | \arguments{ 10 | \item{overwrite}{Should values that are allready set in \code{options()} be 11 | overwritten?} 12 | } 13 | \value{ 14 | Nothing returned. 15 | } 16 | \description{ 17 | This function resets the following options: 18 | } 19 | \details{ 20 | \itemize{ 21 | \item \code{tikzDefaultEngine} 22 | \item \code{tikzLatex} 23 | \item \code{tikzDocumentDeclaration} 24 | \item \code{tikzFooter} 25 | \item \code{tikzLatexPackages} 26 | \item \code{tikzXelatexPackages} 27 | \item \code{tikzLualatexPackages} 28 | \item \code{tikzMetricPackages} 29 | \item \code{tikzUnicodeMetricPackages} 30 | \item \code{tikzSanitizeCharacters} 31 | \item \code{tikzReplacementCharacters} 32 | \item \code{tikzPdftexWarnUTF} 33 | } 34 | } 35 | \examples{ 36 | 37 | print( options( 'tikzDocumentDeclaration' ) ) 38 | options( tikzDocumentDeclaration = 'foo' ) 39 | setTikzDefaults() 40 | print( options( 'tikzDocumentDeclaration' ) ) 41 | 42 | } 43 | \seealso{ 44 | \code{\link[=tikz]{tikz()}} 45 | } 46 | \author{ 47 | Cameron Bracken \email{cameron.bracken@gmail.com} and Charlie 48 | Sharpsteen \email{source@sharpsteen.net} 49 | } 50 | -------------------------------------------------------------------------------- /man/gridToDevice.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tikzAnnotate.R 3 | \name{gridToDevice} 4 | \alias{gridToDevice} 5 | \title{Convert grid coordinates to device coordinates} 6 | \usage{ 7 | gridToDevice(x = 0, y = 0, units = "native") 8 | } 9 | \arguments{ 10 | \item{x}{x coordinate.} 11 | 12 | \item{y}{y coordinate. If no values are given for \code{x} and \code{y}, the 13 | location of the lower-left corner of the current viewport will be 14 | calculated.} 15 | 16 | \item{units}{Character string indicating the units of \code{x} and \code{y}. 17 | See the \code{\link[=unit]{unit()}} function for acceptable unit types.} 18 | } 19 | \value{ 20 | A tuple of coordinates in device units. 21 | } 22 | \description{ 23 | This function converts a coordinate pair specifying a location in a 24 | grid \code{\link[=viewport]{viewport()}} in grid units to a coordinate pair specifying a 25 | location in device units relative to the lower left corner of the plotting 26 | canvas. 27 | } 28 | \seealso{ 29 | \code{\link[=unit]{unit()}} 30 | \code{\link[=viewport]{viewport()}} 31 | \code{\link[=convertX]{convertX()}} 32 | \code{\link[=convertY]{convertY()}} 33 | \code{\link[=current.transform]{current.transform()}} 34 | } 35 | \author{ 36 | Charlie Sharpsteen \email{source@sharpsteen.net} 37 | } 38 | \keyword{conversion} 39 | \keyword{graphics} 40 | \keyword{grid} 41 | \keyword{units} 42 | -------------------------------------------------------------------------------- /man/anyMultibyteUTF8Characters.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/deviceUtils.R 3 | \encoding{UTF8} 4 | \name{anyMultibyteUTF8Characters} 5 | \alias{anyMultibyteUTF8Characters} 6 | \title{Check If a String Contains Multibyte UTF-8 characters} 7 | \usage{ 8 | anyMultibyteUTF8Characters(string, encoding = "UTF-8") 9 | } 10 | \arguments{ 11 | \item{string}{A character vector of length 1 (a string).} 12 | 13 | \item{encoding}{Unused.} 14 | } 15 | \value{ 16 | A boolean value 17 | } 18 | \description{ 19 | This function is used by tikzDevice to check if an incoming string contains 20 | multibyte UTF-8 characters 21 | } 22 | \details{ 23 | This function searches through the characters in the given string, if any of 24 | the characters in the string are more than one byte then the function 25 | returns \code{TRUE} otherwise it returns \code{FALSE}. 26 | 27 | The function will assume an input encoding of UTF-8 but will take any 28 | specified encoding into account and will convert from the specified encoding 29 | to UTF-8 before doing any checks 30 | } 31 | \examples{ 32 | 33 | # TRUE 34 | anyMultibyteUTF8Characters('R is GNU ©, but not ®') 35 | # FALSE 36 | anyMultibyteUTF8Characters('R is GNU copyright but not restricted') 37 | 38 | } 39 | \seealso{ 40 | \code{\link[=tikz]{tikz()}} 41 | } 42 | \author{ 43 | Cameron Bracken \email{cameron.bracken@gmail.com} 44 | } 45 | \keyword{character} 46 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(drawDetails,tikz_annotation) 4 | S3method(drawDetails,tikz_coord) 5 | S3method(drawDetails,tikz_node) 6 | S3method(format,ENV_VAR) 7 | S3method(format,OPTION) 8 | S3method(format,PATH) 9 | export(anyMultibyteUTF8Characters) 10 | export(getLatexCharMetrics) 11 | export(getLatexStrWidth) 12 | export(grid.tikzAnnotate) 13 | export(grid.tikzCoord) 14 | export(grid.tikzNode) 15 | export(gridToDevice) 16 | export(sanitizeTexString) 17 | export(setTikzDefaults) 18 | export(tikz) 19 | export(tikzAnnotate) 20 | export(tikzAnnotateGrob) 21 | export(tikzCompilerInfo) 22 | export(tikzCoord) 23 | export(tikzCoordGrob) 24 | export(tikzNode) 25 | export(tikzNodeGrob) 26 | export(tikzTest) 27 | importFrom(filehash,dbCreate) 28 | importFrom(filehash,dbExists) 29 | importFrom(filehash,dbFetch) 30 | importFrom(filehash,dbInit) 31 | importFrom(filehash,dbInsert) 32 | importFrom(grDevices,as.raster) 33 | importFrom(grDevices,dev.cur) 34 | importFrom(grDevices,dev.list) 35 | importFrom(grDevices,dev.off) 36 | importFrom(grDevices,png) 37 | importFrom(graphics,grconvertX) 38 | importFrom(graphics,grconvertY) 39 | importFrom(graphics,par) 40 | importFrom(graphics,plot.new) 41 | importFrom(graphics,rasterImage) 42 | importFrom(grid,convertX) 43 | importFrom(grid,convertY) 44 | importFrom(grid,current.transform) 45 | importFrom(grid,drawDetails) 46 | importFrom(grid,grid.draw) 47 | importFrom(grid,grob) 48 | importFrom(grid,unit) 49 | importFrom(stats,complete.cases) 50 | importFrom(utils,packageVersion) 51 | useDynLib(tikzDevice, .registration = TRUE) 52 | -------------------------------------------------------------------------------- /vignettes/refs.bib: -------------------------------------------------------------------------------- 1 | %% This BibTeX bibliography file was created using BibDesk. 2 | %% http://bibdesk.sourceforge.net/ 3 | 4 | 5 | %% Created for Charles Sharpsteen at 2009-07-25 14:25:30 -0700 6 | 7 | 8 | %% Saved with string encoding Unicode (UTF-8) 9 | 10 | 11 | 12 | @article{peng2006, 13 | Author = {Roger D. Peng}, 14 | Date-Added = {2009-07-24 17:12:20 -0700}, 15 | Date-Modified = {2009-07-25 14:25:30 -0700}, 16 | Journal = {R News}, 17 | Number = {4}, 18 | Pages = {19--24}, 19 | Title = {Interacting with data using the filehash package}, 20 | Url = {\url{http://CRAN.R-project.org/doc/Rnews/}}, 21 | Volume = {6}, 22 | Year = {2006}, 23 | Bdsk-Url-1 = {http://CRAN.R-project.org/doc/Rnews/}} 24 | 25 | @misc{murrellTex, 26 | Author = {Paul Murrell}, 27 | Date-Added = {2009-07-24 16:54:42 -0700}, 28 | Date-Modified = {2009-07-24 17:11:06 -0700}, 29 | Howpublished = {\url{http://www.stat.auckland.ac.nz/~paul/R/CM/CMR.html}}, 30 | Title = {{Using Computer Modern Fonts in R Graphics}}, 31 | Year = {2005}} 32 | 33 | @manual{rintern2009, 34 | Author = {{R Development Core Team}}, 35 | Date-Added = {2009-07-24 16:50:20 -0700}, 36 | Date-Modified = {2009-07-24 16:53:11 -0700}, 37 | Title = {R Internals: Version 2.9.1}, 38 | Year = {2009}} 39 | 40 | @manual{tantau2008, 41 | Author = {Till Tantau}, 42 | Date-Added = {2009-07-24 16:46:57 -0700}, 43 | Date-Modified = {2009-07-24 16:50:08 -0700}, 44 | Month = {Febuary}, 45 | Title = {The TikZ and PGF Packages: Manual for version 2.00}, 46 | Year = {2008}} 47 | 48 | @manual{urbanek2013, 49 | title = {png: Read and write PNG images}, 50 | author = {Simon Urbanek}, 51 | note = {R package version 0.1-7}, 52 | url = {http://www.rforge.net/png/}, 53 | year = {2013}, 54 | } 55 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Encoding: UTF-8 2 | Package: tikzDevice 3 | Type: Package 4 | Title: R Graphics Output in LaTeX Format 5 | Version: 0.12.6 6 | Authors@R: c( person("Charlie", "Sharpsteen", role = "aut"), 7 | person("Cameron", "Bracken", role = "aut"), person("Kirill", 8 | "Müller", role = c("ctb"), email = 9 | "krlmlr+r@mailbox.org"), person("Yihui", "Xie", role = "ctb"), 10 | person("Ralf", "Stubner", email = "ralf.stubner@gmail.com", 11 | role = "cre"), person("Nico", "Bellack", 12 | email = "nico.belack@daqana.com", role = "ctb") ) 13 | URL: https://daqana.github.io/tikzDevice/, https://github.com/daqana/tikzDevice 14 | BugReports: https://github.com/daqana/tikzDevice/issues 15 | Description: Provides a graphics output device for R that records plots 16 | in a LaTeX-friendly format. The device transforms plotting 17 | commands issued by R functions into LaTeX code blocks. When 18 | included in a LaTeX document, these blocks are interpreted with 19 | the help of 'TikZ'---a graphics package for TeX and friends 20 | written by Till Tantau. Using the 'tikzDevice', the text of R 21 | plots can contain LaTeX commands such as mathematical formula. 22 | The device also allows arbitrary LaTeX code to be inserted into 23 | the output stream. 24 | License: GPL (>= 2) 25 | Depends: R (>= 2.14.0) 26 | Imports: 27 | filehash (>= 2.3), 28 | png 29 | Suggests: 30 | evaluate, 31 | formatR, 32 | ggplot2, 33 | knitr, 34 | lattice, 35 | maps, 36 | scales, 37 | stringr, 38 | testthat (>= 0.8.1), 39 | withr, 40 | covr 41 | SystemRequirements: pgf (>= 2.00) 42 | LazyLoad: yes 43 | VignetteBuilder: knitr 44 | RoxygenNote: 7.2.3 45 | Roxygen: list(markdown = TRUE) 46 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | - master 6 | pull_request: 7 | branches: 8 | - main 9 | - master 10 | 11 | name: test-coverage 12 | 13 | jobs: 14 | test-coverage: 15 | runs-on: ubuntu-20.04 16 | env: 17 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - uses: r-lib/actions/setup-r@v1 22 | 23 | - uses: r-lib/actions/setup-pandoc@v1 24 | 25 | - uses: r-lib/actions/setup-tinytex@v1 26 | - run: | 27 | tlmgr --version 28 | tlmgr install pgf preview grfext 29 | 30 | - name: Install ImageMagick 31 | if: runner.os == 'Linux' 32 | run: sudo apt-get install -y imagemagick 33 | 34 | - name: Query dependencies 35 | run: | 36 | install.packages('remotes') 37 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) 38 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") 39 | shell: Rscript {0} 40 | 41 | - name: Restore R package cache 42 | uses: actions/cache@v2 43 | with: 44 | path: ${{ env.R_LIBS_USER }} 45 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 46 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 47 | 48 | - name: Install system dependencies 49 | run: | 50 | while read -r cmd 51 | do 52 | eval sudo $cmd 53 | done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))') 54 | 55 | - name: Install dependencies 56 | run: | 57 | install.packages(c("remotes")) 58 | remotes::install_deps(dependencies = TRUE) 59 | remotes::install_cran("covr") 60 | shell: Rscript {0} 61 | 62 | - name: Test coverage 63 | run: covr::codecov() 64 | shell: Rscript {0} 65 | -------------------------------------------------------------------------------- /tests/testthat/helper_bootstrap.R: -------------------------------------------------------------------------------- 1 | # Process command arguments 2 | test_args <- commandArgs(TRUE) 3 | torture_mem <- any(stringr::str_detect(test_args, "^--use-gctorture")) 4 | 5 | if (length(tags_to_run <- test_args[stringr::str_detect(test_args, "^--run-tests")])) { 6 | tags_to_run <- unlist(str_split( 7 | str_split(tags_to_run, "=")[[1]][2], 8 | "," 9 | )) 10 | } 11 | 12 | if (torture_mem) { 13 | gctorture(TRUE) 14 | } 15 | using_windows <- Sys.info()["sysname"] == "Windows" 16 | 17 | # Ensure tikzDevice options have been set to their default values. 18 | setTikzDefaults(overwrite = TRUE) 19 | options(tikzMetricsDictionary = NULL) 20 | 21 | expand_test_path <- function(path) { 22 | normalizePath(path, mustWork = FALSE) 23 | } 24 | 25 | # Set up directories for test output. 26 | test_output_dir <- expand_test_path(file.path(getwd(), "test_output")) 27 | if (!file.exists(test_output_dir)) dir.create(test_output_dir) 28 | test_work_dir <- expand_test_path(file.path(getwd(), "test_work")) 29 | if (!file.exists(test_work_dir)) dir.create(test_work_dir) 30 | 31 | test_standard_dir <- normalizePath("standard_graphs") 32 | 33 | oldwarn <- options(warn = 1) 34 | 35 | # Locate required external programs 36 | gs_cmd <- Sys.which(ifelse(using_windows, "gswin32c", "gs")) 37 | if (nchar(gs_cmd) == 0) { 38 | warning("Ghostscript not found.") 39 | gs_cmd <- NULL 40 | } else { 41 | gs_cmd <- normalizePath(gs_cmd) 42 | } 43 | 44 | compare_cmd <- Sys.which("compare") 45 | if (nchar(compare_cmd) == 0 || is.null(gs_cmd)) { 46 | warning("compare not found.") 47 | compare_cmd <- NULL 48 | } else { 49 | compare_cmd <- normalizePath(compare_cmd) 50 | } 51 | 52 | convert_cmd <- normalizePath( 53 | ifelse(using_windows, 54 | system("bash -c 'which convert'", intern = TRUE, ignore.stderr = TRUE), 55 | Sys.which("convert") 56 | ) 57 | ) 58 | 59 | if (nchar(convert_cmd) == 0) { 60 | convert_cmd <- NULL 61 | warning("convert not found.") 62 | } else if (is.null(gs_cmd)) { 63 | convert_cmd <- NULL 64 | warning("Cannot use convert because Ghostscript is missing.") 65 | } else { 66 | convert_cmd <- normalizePath(convert_cmd) 67 | } 68 | 69 | cat("Ghostscript: ", gs_cmd, "\n") 70 | cat("compare: ", compare_cmd, "\n") 71 | cat("convert: ", convert_cmd, "\n") 72 | 73 | options(oldwarn) 74 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | # 4 | # NOTE: This workflow is overkill for most R packages and 5 | # check-standard.yaml is likely a better choice. 6 | # usethis::use_github_action("check-standard") will install it. 7 | on: 8 | push: 9 | branches: [main, master] 10 | pull_request: 11 | branches: [main, master] 12 | workflow_dispatch: 13 | 14 | name: R-CMD-check 15 | 16 | jobs: 17 | R-CMD-check: 18 | runs-on: ${{ matrix.config.os }} 19 | 20 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 21 | 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | config: 26 | - {os: macos-latest, r: 'release'} 27 | 28 | - {os: windows-latest, r: 'release'} 29 | 30 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 31 | - {os: ubuntu-latest, r: 'release'} 32 | - {os: ubuntu-latest, r: 'oldrel'} 33 | 34 | env: 35 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 36 | R_KEEP_PKG_SOURCE: yes 37 | 38 | steps: 39 | - uses: actions/checkout@v3 40 | 41 | - uses: r-lib/actions/setup-pandoc@v2 42 | 43 | - uses: r-lib/actions/setup-tinytex@v2 44 | - run: tlmgr --version 45 | 46 | - name: Install additional LaTeX packages 47 | run: | 48 | tlmgr install pgf preview grfext memoir microtype pdflscape babel-english listings xstring upquote 49 | tlmgr list --only-installed 50 | 51 | - uses: r-lib/actions/setup-r@v2 52 | with: 53 | r-version: ${{ matrix.config.r }} 54 | http-user-agent: ${{ matrix.config.http-user-agent }} 55 | use-public-rspm: true 56 | extra-repositories: https://r-forge.r-universe.dev 57 | 58 | - uses: r-lib/actions/setup-r-dependencies@v2 59 | with: 60 | extra-packages: any::rcmdcheck 61 | needs: check 62 | 63 | - uses: r-lib/actions/check-r-package@v2 64 | with: 65 | args: 'c("--no-manual", "--as-cran")' 66 | build_args: 'c("--no-manual", "--no-build-vignettes")' 67 | error-on: '"error"' 68 | check-dir: '"check"' 69 | upload-snapshots: true 70 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /man/sanitizeTexString.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/sanitizeTexString.R 3 | \name{sanitizeTexString} 4 | \alias{sanitizeTexString} 5 | \title{Replace LaTeX Special Characters in a String} 6 | \usage{ 7 | sanitizeTexString( 8 | string, 9 | strip = getOption("tikzSanitizeCharacters"), 10 | replacement = getOption("tikzReplacementCharacters") 11 | ) 12 | } 13 | \arguments{ 14 | \item{string}{A character vector of length 1 (a string).} 15 | 16 | \item{strip}{A character vector of single characters to search for.} 17 | 18 | \item{replacement}{A character vector of replacement values.} 19 | } 20 | \value{ 21 | \item{sanitizedString}{A character vector of length 1 with all 22 | special characters replaced.} 23 | } 24 | \description{ 25 | This function is used by tikzDevice when \code{sanitize = TRUE} to replace 26 | special LaTeX characters (such as the comment character \%) in plotting text 27 | where the user does not have direct control over the generated text. 28 | } 29 | \details{ 30 | \code{sanitizeTexString()} searches character by character through a string 31 | replacing each occurrence of a special character contained in 32 | \code{strip[i]} with the corresponding replacement value in 33 | \code{replacement[i]}. tikzDevice calls back this function for every piece 34 | of text when the sanitize option is TRUE. See \code{\link[=tikz]{tikz()}} for more 35 | information on the default special characters and replacement values. 36 | 37 | By default, \code{tikzSanitizeCharacters} replaces the following characters: 38 | 39 | \itemize{ 40 | \item \verb{\%} 41 | \item \verb{$} 42 | \item \verb{\}} 43 | \item \verb{\{} 44 | \item \verb{^} 45 | \item \verb{_} 46 | \item \verb{#} 47 | \item \verb{&} 48 | \item \verb{~} 49 | } 50 | 51 | With the contents of \code{tikzReplacementCharacters}: 52 | 53 | \itemize{ 54 | \item \verb{\\\%} 55 | \item \verb{\\$} 56 | \item \verb{\\\}} 57 | \item \verb{\\\{} 58 | \item \verb{\\^{}} 59 | \item \verb{\\_{}} 60 | \item \verb{\\#} 61 | \item \verb{\\&} 62 | \item \verb{\char`\~} 63 | } 64 | 65 | These defaults may be adjusted using the \code{\link[=options]{options()}} function. 66 | } 67 | \examples{ 68 | 69 | # Be careful with sanitizing, it may lead to unexpected behavior. 70 | # For example, we may want -1 to be a superscript it gets 71 | # sanitized away with the other default special characters. 72 | # The string appears in LaTeX exactly as shown. 73 | \dontrun{ 74 | sanitizeTexString('10\\% of 10$ is 10^\{-1\}$') 75 | } 76 | 77 | } 78 | \seealso{ 79 | \code{\link[=tikz]{tikz()}} 80 | } 81 | \author{ 82 | Cameron Bracken \email{cameron.bracken@gmail.com} 83 | } 84 | \keyword{character} 85 | -------------------------------------------------------------------------------- /R/sanitizeTexString.R: -------------------------------------------------------------------------------- 1 | #' Replace LaTeX Special Characters in a String 2 | #' 3 | #' This function is used by tikzDevice when `sanitize = TRUE` to replace 4 | #' special LaTeX characters (such as the comment character %) in plotting text 5 | #' where the user does not have direct control over the generated text. 6 | #' 7 | #' `sanitizeTexString()` searches character by character through a string 8 | #' replacing each occurrence of a special character contained in 9 | #' `strip[i]` with the corresponding replacement value in 10 | #' `replacement[i]`. tikzDevice calls back this function for every piece 11 | #' of text when the sanitize option is TRUE. See [tikz()] for more 12 | #' information on the default special characters and replacement values. 13 | #' 14 | #' By default, `tikzSanitizeCharacters` replaces the following characters: 15 | #' 16 | #' \itemize{ 17 | #' \item \verb{\%} 18 | #' \item \verb{$} 19 | #' \item \verb{\}} 20 | #' \item \verb{\{} 21 | #' \item \verb{^} 22 | #' \item \verb{_} 23 | #' \item \verb{#} 24 | #' \item \verb{&} 25 | #' \item \verb{~} 26 | #' } 27 | #' 28 | #' With the contents of `tikzReplacementCharacters`: 29 | #' 30 | #' \itemize{ 31 | #' \item \verb{\\\%} 32 | #' \item \verb{\\$} 33 | #' \item \verb{\\\}} 34 | #' \item \verb{\\\{} 35 | #' \item \verb{\\^{}} 36 | #' \item \verb{\\_{}} 37 | #' \item \verb{\\#} 38 | #' \item \verb{\\&} 39 | #' \item \verb{\char`\~} 40 | #' } 41 | #' 42 | #' These defaults may be adjusted using the [options()] function. 43 | #' 44 | #' @param string A character vector of length 1 (a string). 45 | #' @param strip A character vector of single characters to search for. 46 | #' @param replacement A character vector of replacement values. 47 | #' 48 | #' @return \item{sanitizedString}{A character vector of length 1 with all 49 | #' special characters replaced.} 50 | #' 51 | #' @author Cameron Bracken \email{cameron.bracken@@gmail.com} 52 | #' 53 | #' @seealso [tikz()] 54 | #' @keywords character 55 | #' 56 | #' @examples 57 | #' 58 | #' # Be careful with sanitizing, it may lead to unexpected behavior. 59 | #' # For example, we may want -1 to be a superscript it gets 60 | #' # sanitized away with the other default special characters. 61 | #' # The string appears in LaTeX exactly as shown. 62 | #' \dontrun{ 63 | #' sanitizeTexString('10\% of 10$ is 10^\{-1\}$') 64 | #' } 65 | #' 66 | #' @export 67 | sanitizeTexString <- function(string, 68 | strip = getOption("tikzSanitizeCharacters"), 69 | replacement = getOption("tikzReplacementCharacters")) { 70 | 71 | # separate the string into a vector of charaters 72 | explode <- strsplit(string, "")[[1]] 73 | if (any(is.na(explode))) stop("Unable to sanitize string, you may be trying to pass in an unsupported symbol") 74 | 75 | # Replace each matching character with its replacement characters 76 | for (i in 1:length(explode)) { 77 | matches <- (explode[i] == strip) 78 | if (any(matches)) { 79 | explode[i] <- paste("{", replacement[which(matches)], "}", sep = "") 80 | } 81 | } 82 | # stick the string back together 83 | return(paste(explode, collapse = "")) 84 | } 85 | -------------------------------------------------------------------------------- /tests/testthat/test_error_handling.R: -------------------------------------------------------------------------------- 1 | context("Test tikzDevice error and warning messages") 2 | 3 | test_that("Null device is not a tikzDevice", { 4 | expect_false( 5 | suppressMessages(isTikzDevice()) 6 | ) 7 | }) 8 | 9 | test_that("Device produces an error for unescaped characters", { 10 | expect_that( 11 | suppressMessages(getLatexStrWidth("_")), 12 | throws_error("TeX was unable to calculate metrics") 13 | ) 14 | }) 15 | 16 | test_that("Device warns about the lower bound of the ASCII table when using pdftex", { 17 | expect_that( 18 | getLatexCharMetrics(31, engine = "pdftex"), 19 | gives_warning("pdftex can only generate metrics for character codes between 32 and 126!") 20 | ) 21 | }) 22 | 23 | test_that("Device warns about the upper bound of the ASCII table when using pdftex", { 24 | expect_that( 25 | getLatexCharMetrics(127), 26 | gives_warning("pdftex can only generate metrics for character codes between 32 and 126!") 27 | ) 28 | }) 29 | 30 | test_that("Device won't accept non-numeric ASCII codes", { 31 | expect_that( 32 | suppressMessages(getLatexCharMetrics("a")), 33 | gives_warning("getLatexCharMetrics only accepts integers!") 34 | ) 35 | }) 36 | 37 | test_that("Device throws error when a path cannot be opened", { 38 | expect_that( 39 | tikz("/why/would/you/have/a/path/like/this.tex"), 40 | throws_error("directory does not exist or is not writable") 41 | ) 42 | }) 43 | 44 | test_that("tikzAnnotate refuses to work with a non-tikzDevice", { 45 | expect_that( 46 | tikzAnnotate("test"), 47 | throws_error("The active device is not a tikz device") 48 | ) 49 | }) 50 | 51 | test_that("XeTeX warns about unrecognized UTF8 characters", { 52 | expect_that( 53 | suppressMessages(getLatexStrWidth("α", engine = "xetex")), 54 | gives_warning("XeLaTeX was unable to calculate metrics") 55 | ) 56 | }) 57 | 58 | test_that("tikzNode warns about more than one X coordinate value", { 59 | tikz() 60 | plot.new() 61 | on.exit(dev.off()) 62 | 63 | expect_that( 64 | tikzCoord(c(1, 2), 2, "test"), 65 | gives_warning("More than one X coordinate specified") 66 | ) 67 | }) 68 | 69 | test_that("tikzNode warns about more than one Y coordinate value", { 70 | tikz() 71 | plot.new() 72 | on.exit(dev.off()) 73 | 74 | expect_that( 75 | tikzCoord(1, c(1, 2), "test"), 76 | gives_warning("More than one Y coordinate specified") 77 | ) 78 | }) 79 | 80 | test_that("symbolicColors warns about wrong filename", { 81 | tikz(symbolicColors = T, colorFileName = "/") 82 | plot(1, 2, axes = F, xlab = "", ylab = "") 83 | 84 | expect_that( 85 | dev.off(), 86 | gives_warning("Color definition file could not be opened and is missing") 87 | ) 88 | }) 89 | 90 | test_that("symbolicColors warns about too many colors", { 91 | tikz(symbolicColors = T, maxSymbolicColors = 2) 92 | plot.new() 93 | points(0, 0) 94 | on.exit(dev.off()) 95 | expect_that( 96 | points(0, 1, col = "red"), 97 | gives_warning("Too many colors used, reverting to non-symbolic storage") 98 | ) 99 | }) 100 | 101 | test_that("check that maxSymbolicColors is nonnegative", { 102 | expect_that( 103 | tikz(symbolicColors = T, maxSymbolicColors = -1), 104 | throws_error("maxSymbolicColors needs to be nonnegative") 105 | ) 106 | }) 107 | -------------------------------------------------------------------------------- /tests/testthat/test_metrics_dict.R: -------------------------------------------------------------------------------- 1 | context("Metrics dictionary") 2 | 3 | test_that("Temporary metrics dictionary is created, but only once", { 4 | expect_equal(getOption("tikzMetricsDictionary"), NULL) 5 | 6 | rm(list = ls(envir = .tikzInternal), envir = .tikzInternal) 7 | expect_message(checkDictionaryStatus(verbose = TRUE), "Creating") 8 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 9 | expect_true(file.exists(.tikzInternal[["db_file"]])) 10 | }) 11 | 12 | test_that("Silent creation of temporary metrics dictionary", { 13 | expect_equal(getOption("tikzMetricsDictionary"), NULL) 14 | 15 | rm(list = ls(envir = .tikzInternal), envir = .tikzInternal) 16 | expect_silent(checkDictionaryStatus(verbose = FALSE)) 17 | expect_silent(checkDictionaryStatus(verbose = FALSE)) 18 | expect_true(file.exists(.tikzInternal[["db_file"]])) 19 | }) 20 | 21 | test_that("Switching metrics dictionary", { 22 | expect_equal(getOption("tikzMetricsDictionary"), NULL) 23 | 24 | tempA <- file.path(getwd(), ".tikzTempA") 25 | tempB <- file.path(getwd(), ".tikzTempB") 26 | 27 | tryCatch( 28 | { 29 | options(tikzMetricsDictionary = tempA) 30 | expect_message(checkDictionaryStatus(verbose = TRUE), "Creating") 31 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 32 | options(tikzMetricsDictionary = tempB) 33 | expect_message(checkDictionaryStatus(verbose = TRUE), "Creating") 34 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 35 | options(tikzMetricsDictionary = tempA) 36 | expect_message(checkDictionaryStatus(verbose = TRUE), "Using") 37 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 38 | options(tikzMetricsDictionary = tempB) 39 | expect_message(checkDictionaryStatus(verbose = TRUE), "Using") 40 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 41 | options(tikzMetricsDictionary = tempA) 42 | expect_silent(checkDictionaryStatus(verbose = FALSE)) 43 | expect_silent(checkDictionaryStatus(verbose = FALSE)) 44 | options(tikzMetricsDictionary = tempB) 45 | expect_silent(checkDictionaryStatus(verbose = FALSE)) 46 | expect_silent(checkDictionaryStatus(verbose = FALSE)) 47 | }, 48 | finally = { 49 | options(tikzMetricsDictionary = NULL) 50 | unlink(tempA, recursive = TRUE) 51 | unlink(tempB, recursive = TRUE) 52 | } 53 | ) 54 | }) 55 | 56 | test_that("Turning custom metrics dictionary on and off", { 57 | expect_equal(getOption("tikzMetricsDictionary"), NULL) 58 | 59 | temp <- file.path(getwd(), ".tikzTemp") 60 | 61 | tryCatch( 62 | { 63 | options(tikzMetricsDictionary = temp) 64 | expect_message(checkDictionaryStatus(verbose = TRUE), "Creating") 65 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 66 | options(tikzMetricsDictionary = NULL) 67 | expect_message(checkDictionaryStatus(verbose = TRUE), "Creating") 68 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 69 | options(tikzMetricsDictionary = temp) 70 | expect_message(checkDictionaryStatus(verbose = TRUE), "Using") 71 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 72 | options(tikzMetricsDictionary = NULL) 73 | expect_message(checkDictionaryStatus(verbose = TRUE), "Creating") 74 | expect_silent(checkDictionaryStatus(verbose = TRUE)) 75 | }, 76 | finally = { 77 | options(tikzMetricsDictionary = NULL) 78 | unlink(temp, recursive = TRUE) 79 | } 80 | ) 81 | }) 82 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onLoad <- function(libname, pkgname) { 2 | 3 | # Ensure options are set. 4 | setTikzDefaults(overwrite = FALSE) 5 | 6 | # Perform a search for executable TeX compilers. R options, environment 7 | # variables and common paths will be checked. If PdfLaTeX can not be found, 8 | # loading of this package will be aborted as a LaTeX compiler is required in 9 | # order to determine string metrics. Other compilers, such as XeLaTeX, are 10 | # optional. 11 | foundLatex <- FALSE 12 | foundXelatex <- FALSE 13 | foundLualatex <- FALSE 14 | 15 | latexLocs <- list( 16 | OPTION("tikzLatex"), 17 | ENV_VAR("R_LATEXCMD"), 18 | ENV_VAR("R_PDFLATEXCMD"), 19 | OPTION("latexcmd"), 20 | PATH("pdflatex"), 21 | PATH("latex") 22 | ) 23 | 24 | # Only check for xelatex and lualatex in the options and the PATH variable 25 | # since there are no R environment variables for these compilers. 26 | xelatexLocs <- list( 27 | OPTION("tikzXelatex"), 28 | PATH("xelatex") 29 | ) 30 | 31 | lualatexLocs <- list( 32 | OPTION("tikzLualatex"), 33 | PATH("lualatex") 34 | ) 35 | 36 | # Non-Windows users are likely to use some derivative of TeX Live. This next 37 | # test primarily covers the fact that R.app does not include `/usr/texbin` on 38 | # the search path on OS X. 39 | if (.Platform[["OS.type"]] == "unix") { 40 | # Using explicit list insertion because the `c` function drops attributes 41 | # and thus destroys S3 objects. Writing 3 new class methods for PATH, 42 | # OBJECT and ENV_VAR is just overkill. 43 | latexLocs[[length(latexLocs) + 1]] <- PATH("/usr/texbin/pdflatex") 44 | xelatexLocs[[length(xelatexLocs) + 1]] <- PATH("/usr/texbin/xelatex") 45 | lualatexLocs[[length(lualatexLocs) + 1]] <- PATH("/usr/texbin/lualatex") 46 | } 47 | 48 | for (latexPath in latexLocs) { 49 | if (isExecutable(latexPath)) { 50 | foundLatex <- TRUE 51 | options(tikzLatex = as.character(latexPath), tikzLatexDefault = as.character(latexPath)) 52 | break 53 | } 54 | } 55 | 56 | for (xelatexPath in xelatexLocs) { 57 | if (isExecutable(xelatexPath)) { 58 | foundXelatex <- TRUE 59 | options(tikzXelatex = as.character(xelatexPath), tikzXelatexDefault = as.character(xelatexPath)) 60 | break 61 | } 62 | } 63 | 64 | for (lualatexPath in lualatexLocs) { 65 | if (isExecutable(lualatexPath)) { 66 | foundLualatex <- TRUE 67 | options(tikzLualatex = as.character(lualatexPath), tikzLualatexDefault = as.character(lualatexPath)) 68 | break 69 | } 70 | } 71 | 72 | if (!foundLatex) { 73 | warning( 74 | "\n\ntikzDevice: No appropriate LaTeX compiler could be found.\n", 75 | "Access to LaTeX is required in order for the TikZ device\n", 76 | "to produce output.\n\n", 77 | "The following places were tested for a valid LaTeX compiler:\n\n\t", 78 | paste(sapply(latexLocs, format), collapse = "\n\t"), 79 | "\n\nIf you have a working LaTeX compiler, try one of the\n", 80 | "following solutions:", 81 | 82 | "\n\n\tSet the path to your compiler as the value of either latexcmd or", 83 | "\n\ttikzLatex in .Rprofile using options().", 84 | 85 | "\n\n\tSet the path to your compiler as the value of either R_LATEXCMD or", 86 | "\n\tR_PDFLATEXCMD in .Renviron.", 87 | 88 | "\n\n\tEnsure the folder containing your compiler is included in PATH.\n" 89 | ) 90 | } 91 | } 92 | 93 | # Any variables defined in here will be hidden 94 | # from normal users. 95 | .tikzInternal <- new.env() 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tikzDevice 2 | ========== 3 | 4 | [![R build status](https://github.com/daqana/tikzDevice/workflows/R-CMD-check/badge.svg)](https://github.com/daqana/tikzDevice/actions) 5 | [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/daqana/tikzDevice?branch=master&svg=true)](https://ci.appveyor.com/project/rstub/tikzDevice) 6 | [![Coverage status](https://codecov.io/gh/daqana/tikzDevice/branch/master/graph/badge.svg)](https://codecov.io/github/daqana/tikzDevice?branch=master) [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/tikzDevice)](https://cran.r-project.org/package=tikzDevice) 7 | 8 | The tikzDevice package provides a graphics output device for R that records 9 | plots in a LaTeX-friendly format. The device transforms plotting commands 10 | issued by R functions into LaTeX code blocks. When included in a paper typeset 11 | by LaTeX, these blocks are interpreted with the help of TikZ---a graphics 12 | package for TeX and friends written by Till Tantau. 13 | 14 | Using the tikzDevice, the text of R plots can contain LaTeX commands such as 15 | mathematical formula. The device also allows arbitrary LaTeX code to be 16 | inserted into the output stream. 17 | 18 | The tikzDevice supports three main modes of output: 19 | 20 | - Figure chunks: placed in .tex files and suitable for inclusion in LaTeX 21 | documents via the \input{} command. 22 | 23 | - Stand alone figures: Complete LaTeX documents containing figure code that 24 | can be compiled into stand-alone images. Pages are cropped to the size of 25 | the figure using the LaTeX preview package. 26 | 27 | - Console output: TikZ code is returned directly to the R console as a 28 | character vector for further manipulation. 29 | 30 | 31 | Obtaining the Package 32 | --------------------- 33 | 34 | Stable versions of the tikzDevice may be installed from CRAN: 35 | 36 | ```r 37 | install.packages( 'tikzDevice' ) 38 | ``` 39 | 40 | Development builds may be installed from RForge: 41 | 42 | ```r 43 | install.packages( 'tikzDevice', repos = 'https://rforge.net', type = 'source' ) 44 | ``` 45 | 46 | Alternatively, install directly from GitHub: 47 | 48 | ```r 49 | devtools::install_github( 'daqana/tikzDevice' ) 50 | ``` 51 | 52 | Bleeding-edge source code is available from GitHub, too: 53 | 54 | ```sh 55 | git clone git://github.com/daqana/tikzDevice.git 56 | ``` 57 | 58 | After cloning, install via 59 | 60 | ```r 61 | devtools::install() 62 | ``` 63 | 64 | Reporting Bugs and Getting Help 65 | ------------------------------- 66 | 67 | Primary development takes place on GitHub. The preferred way to communicate 68 | bugs and feature requests is to open an issue at the primary repository: 69 | 70 | https://github.com/daqana/tikzDevice/issues 71 | 72 | (Unfortunately, the original repository by Charlie Sharpsteen, 73 | https://github.com/Sharpie/RTikZDevice, has not been updated for over a year, 74 | and the package was not even installable anymore with current versions of R. 75 | This was the reason to continue development in a fork.) 76 | 77 | The tikzDevice has also a dedicated mailing list courtesy of R-Forge. The 78 | mailing list is the easiest way to get answers for questions related 79 | to usage: 80 | 81 | tikzdevice-bugs @at@ lists.r-forge.r-project.org 82 | 83 | The mailing list may also be accessed through Google Groups: 84 | 85 | https://groups.google.com/forum/#!forum/tikzdevice 86 | 87 | Adventurous users are encouraged to fork the repository and contribute 88 | to the development of the package! 89 | 90 | 91 | Latest Changes 92 | -------------- 93 | 94 | *See the [NEWS][2] file for latest changes* 95 | 96 | [2]:https://github.com/daqana/tikzDevice/blob/master/NEWS.md 97 | -------------------------------------------------------------------------------- /man/getLatexStrWidth.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/latexStrWidth.R 3 | \name{getLatexStrWidth} 4 | \alias{getLatexStrWidth} 5 | \alias{getLatexCharMetrics} 6 | \title{Obtain Font Metrics from LaTeX} 7 | \usage{ 8 | getLatexStrWidth( 9 | texString, 10 | cex = 1, 11 | face = 1, 12 | engine = getOption("tikzDefaultEngine"), 13 | documentDeclaration = getOption("tikzDocumentDeclaration"), 14 | packages, 15 | verbose = interactive(), 16 | diagnose = FALSE 17 | ) 18 | 19 | getLatexCharMetrics( 20 | charCode, 21 | cex = 1, 22 | face = 1, 23 | engine = getOption("tikzDefaultEngine"), 24 | documentDeclaration = getOption("tikzDocumentDeclaration"), 25 | packages, 26 | verbose = interactive() 27 | ) 28 | } 29 | \arguments{ 30 | \item{texString}{An arbitrary string for which the width is to be 31 | calculated. May contain LaTeX markup.} 32 | 33 | \item{cex}{a real number that specifies a scaling factor that is to be 34 | applied to device output.} 35 | 36 | \item{face}{an integer in the range \code{1:5} that specifies the font face to 37 | use. See \link{par} for details.} 38 | 39 | \item{engine}{a string specifying which TeX engine to use. Possible values 40 | are 'pdftex', 'xetex' and 'luatex'. See the Unicode section of 41 | \link{tikzDevice-package} for details.} 42 | 43 | \item{documentDeclaration}{See the sections "Options That Affect Package 44 | Behavior" and "Font Size Calculations" of \link{tikzDevice-package} 45 | for more details.} 46 | 47 | \item{packages}{See the section "Options That Affect Package Behavior" of 48 | \link{tikzDevice-package}.} 49 | 50 | \item{verbose}{A logical value indicating whether diagnostic messages are 51 | printed when measuring dimensions of strings. Defaults to \code{TRUE} in 52 | interactive mode only, to \code{FALSE} otherwise.} 53 | 54 | \item{diagnose}{pass \code{TRUE} to print detailed error information.} 55 | 56 | \item{charCode}{an integer that corresponds to a symbol in the ASCII 57 | character table under the Type 1 font encoding. All numeric values are 58 | coerced using \code{as.integer()}. Non-numeric values will not be accepted.} 59 | } 60 | \value{ 61 | \item{getLatexStrWidth}{The width of \code{texString} in points.} 62 | \item{getLatexCharMetrics}{A numeric vector holding ascent, descent 63 | and width. Values should all be nonnegative.} 64 | } 65 | \description{ 66 | These functions calculate the width of a character or string as it would 67 | appear after being compiled by LaTeX. 68 | } 69 | \details{ 70 | These functions are used internally by the \code{tikz} device for proper 71 | string placement in graphics. Both functions check to see if metrics exist 72 | in a global or temporary dictionary (as defined in 73 | \code{options('tikzMetricsDictionary')}) and if so will pull the metrics 74 | from there. If the dictionary does not exist, then a temporary one is 75 | created for the current R session. Metrics are calculated via \code{system} 76 | calls to LaTeX compilers. Querying compilers to calculate metrics is 77 | expensive and so we strongly recommend setting 78 | \code{options('tikzMetricsDictionary') <- '/path/to/dictionary'} to create a 79 | global dictionary. 80 | } 81 | \examples{ 82 | 83 | getLatexStrWidth('{\\\\\\\\tiny Hello \\\\\\\\LaTeX!}') 84 | 85 | 86 | # Calculate ascent, descent and width for "A" 87 | getLatexCharMetrics(65) 88 | 89 | } 90 | \references{ 91 | PGF Manual 92 | } 93 | \author{ 94 | Charlie Sharpsteen \email{source@sharpsteen.net} and Cameron 95 | Bracken \email{cameron.bracken@gmail.com} 96 | } 97 | \keyword{character} 98 | \keyword{metrics} 99 | \keyword{string} 100 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $("#sidebar") 6 | .stick_in_parent({offset_top: 40}) 7 | .on('sticky_kit:bottom', function(e) { 8 | $(this).parent().css('position', 'static'); 9 | }) 10 | .on('sticky_kit:unbottom', function(e) { 11 | $(this).parent().css('position', 'relative'); 12 | }); 13 | 14 | $('body').scrollspy({ 15 | target: '#sidebar', 16 | offset: 60 17 | }); 18 | 19 | $('[data-toggle="tooltip"]').tooltip(); 20 | 21 | var cur_path = paths(location.pathname); 22 | var links = $("#navbar ul li a"); 23 | var max_length = -1; 24 | var pos = -1; 25 | for (var i = 0; i < links.length; i++) { 26 | if (links[i].getAttribute("href") === "#") 27 | continue; 28 | // Ignore external links 29 | if (links[i].host !== location.host) 30 | continue; 31 | 32 | var nav_path = paths(links[i].pathname); 33 | 34 | var length = prefix_length(nav_path, cur_path); 35 | if (length > max_length) { 36 | max_length = length; 37 | pos = i; 38 | } 39 | } 40 | 41 | // Add class to parent
  • , and enclosing
  • if in dropdown 42 | if (pos >= 0) { 43 | var menu_anchor = $(links[pos]); 44 | menu_anchor.parent().addClass("active"); 45 | menu_anchor.closest("li.dropdown").addClass("active"); 46 | } 47 | }); 48 | 49 | function paths(pathname) { 50 | var pieces = pathname.split("/"); 51 | pieces.shift(); // always starts with / 52 | 53 | var end = pieces[pieces.length - 1]; 54 | if (end === "index.html" || end === "") 55 | pieces.pop(); 56 | return(pieces); 57 | } 58 | 59 | // Returns -1 if not found 60 | function prefix_length(needle, haystack) { 61 | if (needle.length > haystack.length) 62 | return(-1); 63 | 64 | // Special case for length-0 haystack, since for loop won't run 65 | if (haystack.length === 0) { 66 | return(needle.length === 0 ? 0 : -1); 67 | } 68 | 69 | for (var i = 0; i < haystack.length; i++) { 70 | if (needle[i] != haystack[i]) 71 | return(i); 72 | } 73 | 74 | return(haystack.length); 75 | } 76 | 77 | /* Clipboard --------------------------*/ 78 | 79 | function changeTooltipMessage(element, msg) { 80 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 81 | element.setAttribute('data-original-title', msg); 82 | $(element).tooltip('show'); 83 | element.setAttribute('data-original-title', tooltipOriginalTitle); 84 | } 85 | 86 | if(ClipboardJS.isSupported()) { 87 | $(document).ready(function() { 88 | var copyButton = ""; 89 | 90 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 91 | 92 | // Insert copy buttons: 93 | $(copyButton).prependTo(".hasCopyButton"); 94 | 95 | // Initialize tooltips: 96 | $('.btn-copy-ex').tooltip({container: 'body'}); 97 | 98 | // Initialize clipboard: 99 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 100 | text: function(trigger) { 101 | return trigger.parentNode.textContent; 102 | } 103 | }); 104 | 105 | clipboardBtnCopies.on('success', function(e) { 106 | changeTooltipMessage(e.trigger, 'Copied!'); 107 | e.clearSelection(); 108 | }); 109 | 110 | clipboardBtnCopies.on('error', function() { 111 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 112 | }); 113 | }); 114 | } 115 | })(window.jQuery || window.$) 116 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | # tikzDevice TODO # 2 | 3 | - Fill colors are still shown for polylines and lines; This does not 4 | affect the output but is inefficient. 5 | - Line endings are still shown for circles and squares; This does not 6 | affect the output but is inefficient. 7 | - Output to raw R objects. 8 | - Support for raster images. 9 | 10 | ## FIXED ## 11 | - Fontsize and ps parameters are not taken into account when calculating scaling factors. 12 | 13 | [solution] 14 | Scaling factors are now calculated using: 15 | 16 | (font size / base font size ) * cex 17 | 18 | As opposed to the old way which was just the value of cex. 19 | 20 | - Polylines are filled as white 21 | 22 | [Solution] 23 | Added a parameter tikzInfo->polyLine that is set to TRUE when StyleDef 24 | is called, the fill color is only set if tikzInfo->polyLine == FALSE 25 | 26 | - Shapes are plotted with a default color border of black when it should 27 | be transparent 28 | 29 | [Solution] 30 | See the solution below. 31 | 32 | - The CheckAndSetAlpha() function provides inconsistent results for 33 | example test3 is completely transparent but test4 is not though. 34 | 35 | [Solution] 36 | Allowed for the option to set fill and draw transparency separately 37 | with an extra parameter to CheckAndSetAlpha() 38 | 39 | - Fill and draw colors are redefined before every shape is drawn, this 40 | works as a first cut but is VERY inefficient for large numbers of points 41 | which are not changing colors. possibly use \begin{scope}\end{scope} if 42 | possible 43 | 44 | [Solution] 45 | Introduced the parameters oldFillColor and oldDrawColor in the 46 | tikzInfo structure which are checked against the current color and 47 | only redefined if different 48 | 49 | - when using plot(1,1), all calls to text result in proper output with one 50 | exception: the coordinates of the text nodes are nan. 51 | 52 | [Solution] 53 | This error occurred because TikZ_Setup neglected to set the initial 54 | size of the font by assigning a value to startps inside the device 55 | structure. Additionally, plot characters were not produced because the 56 | initial foreground and background colors were not set. 57 | 58 | - when using plot(1,1), the bounding box of the plot is almost drawn 59 | correctly. The line travels through the correct points, then returns to 60 | (0,0) which results in the right hand side of the plot having a funky 61 | edge. 62 | 63 | [Solution] 64 | This bug was a result of incorrect handling of C's #&@!&^ 0 array 65 | indexing by TikZ_Polyline. 66 | 67 | - When using plot(1,1), all text labels are placed incorrectly. This may 68 | be a result of neglecting to provide a serious attempt at calculating 69 | string width. 70 | 71 | [Solution] 72 | This was indeed a result of not making an attempt to calculate 73 | the width of LaTeX strings. This has been fixed by a somewhat 74 | elaborate system call to the LaTeX compiler. This would be an 75 | elegent solution except for the fact that we have to call the 76 | compiler 100s of times... 77 | 78 | - Adding legends to plots results in incorrect sizing and positioning. 79 | See lengend test for an example of this behavoir. 80 | 81 | [Solution] 82 | This was caused be not implementing a full metricInfo function. 83 | Basically labels in legends seemd to hang below the symbols they 84 | were plotted next to. This was caused by returning fixed ascents 85 | and descents that were too large. Now LaTeX is called and the 86 | character in question is set into a named TikZ node, say A. The 87 | ascent is calculated by TikZ as: 88 | 89 | A.north - A.base 90 | 91 | The descent as: 92 | 93 | A.base - A.south 94 | 95 | And the width as: 96 | 97 | A.east - A.west 98 | -------------------------------------------------------------------------------- /R/cacheMetrics.R: -------------------------------------------------------------------------------- 1 | # Filehash contains a function for generating a SHA1 hash from an R object, but 2 | # doesn't export it. The digest package also contains the exact same code made 3 | # publicly available but it seems redundant to add it to the dependency list. 4 | # This function simplifies access to filehash's unexported SHA1 function. 5 | sha1 <- function(object) { 6 | # The get() for every call has very low impact on performance, but simplifies 7 | # matters here 8 | internal_sha1 <- get("sha1", asNamespace("filehash")) 9 | internal_sha1(object) 10 | } 11 | 12 | # Since calling LaTeX to obtain string metrics is inefficient and expensive, 13 | # this function will search a string metrics dictionary to see if we have 14 | # already calculated metrics for this particular object. If so we return the 15 | # cached value. 16 | # 17 | #' @importFrom filehash dbExists dbFetch 18 | queryMetricsDictionary <- function(key, verbose) { 19 | # Ensure the dictionary is available. 20 | checkDictionaryStatus(verbose = verbose) 21 | 22 | # Check for the string. 23 | haveMetrics <- evalWithoutInterrupts(dbExists(.tikzInternal[["dictionary"]], sha1(key))) 24 | if (haveMetrics) { 25 | 26 | # Yay! The width exists! Recover and return it. 27 | metrics <- evalWithoutInterrupts(dbFetch(.tikzInternal[["dictionary"]], sha1(key))) 28 | } else { 29 | 30 | # No dice. Return -1 to indicate that metrics for this string 31 | # are not present in the dictionary. 32 | return(-1) 33 | } 34 | } 35 | 36 | 37 | # This function enters values into the metrics dictionary. The metrics are 38 | # stored under a key which is a SHA1 hash created from the object they are 39 | # associated with. 40 | # 41 | #' @importFrom filehash dbInsert 42 | storeMetricsInDictionary <- function(key, metrics) { 43 | evalWithoutInterrupts(dbInsert(.tikzInternal[["dictionary"]], sha1(key), metrics)) 44 | 45 | # Return nothing. 46 | invisible() 47 | } 48 | 49 | 50 | # This function checks to see if our dictionary has been created as a variable 51 | # in our private .tikzInternal environment. If not, it either opens a user 52 | # specified dictionary or creates a new one in tempdir(). 53 | # 54 | #' @importFrom filehash dbCreate dbInit 55 | checkDictionaryStatus <- function(verbose) { 56 | if (!verbose) { 57 | message <- function(...) invisible() 58 | } 59 | 60 | dict_path <- getOption("tikzMetricsDictionary") 61 | old_dict_path <- .tikzInternal[["dict_path"]] 62 | old_dictionary <- .tikzInternal[["dictionary"]] 63 | old_db_file <- .tikzInternal[["db_file"]] 64 | need_create <- FALSE 65 | 66 | # Check for a user specified dictionary. 67 | if (!is.null(dict_path)) { 68 | db_file <- path.expand(dict_path) 69 | 70 | # Create the database file if it does not exist. 71 | if (!file.exists(db_file)) { 72 | message("Creating new TikZ metrics dictionary at:\n\t", db_file) 73 | need_create <- TRUE 74 | } 75 | } else { 76 | # Create a temporary dictionary- it will disappear after 77 | # the R session finishes. 78 | db_file <- old_db_file 79 | if (is.null(db_file) || !file.exists(db_file) || !is.null(old_dict_path)) { 80 | db_file <- file.path(tempdir(), "tikzMetricsDictionary") 81 | message("Creating temporary TikZ metrics dictionary at:\n\t", db_file) 82 | need_create <- TRUE 83 | } 84 | } 85 | 86 | # Create the database file if it does not exist. 87 | if (need_create) { 88 | unlink(db_file, recursive = TRUE) 89 | dbCreate(db_file, type = "DB1") 90 | 91 | # Need to initialize new database 92 | old_dictionary <- NULL 93 | } 94 | 95 | if (!is.null(old_dictionary) && identical(dict_path, old_dict_path)) { 96 | return(invisible()) 97 | } 98 | 99 | # Add the dictionary as an object in the .tikzOptions 100 | # environment. 101 | message("Using TikZ metrics dictionary at:\n\t", db_file) 102 | .tikzInternal[["dictionary"]] <- dbInit(db_file) 103 | .tikzInternal[["dict_path"]] <- dict_path 104 | .tikzInternal[["db_file"]] <- db_file 105 | 106 | # Return nothing. 107 | invisible() 108 | } 109 | -------------------------------------------------------------------------------- /tests/testthat/helper_graphics.R: -------------------------------------------------------------------------------- 1 | # This file contains functions that help set up and run the tikzDevice through 2 | # test graphs. 3 | 4 | get_graphics_reporter <- function() { 5 | get_reporter()$reporters[[2]] 6 | } 7 | 8 | do_graphics_test <- function(short_name, description, graph_code, fuzz = 0, 9 | engine = "pdftex", graph_options = NULL, skip_if = NULL, tags = NULL, ...) { 10 | context(description) 11 | 12 | if (Sys.getenv("R_TESTS") != "") { 13 | # `R CMD check` is running. Skip test and return so our graphics testsuite 14 | # does not slow down the CRAN daily checks. 15 | return(FALSE) 16 | } 17 | 18 | if (!is.null(skip_if)) { 19 | if (skip_if()) { 20 | return(FALSE) 21 | } 22 | } 23 | 24 | graph_created <- FALSE 25 | 26 | if (!is.null(graph_options)) { 27 | # If this test uses custom options, make sure the current options are 28 | # restored after it finishes. 29 | orig_opts <- options() 30 | options(graph_options) 31 | on.exit(options(orig_opts)) 32 | } 33 | 34 | graph_file <- file.path(test_work_dir, paste0(short_name, ".tex")) 35 | 36 | test_that("Graph is created cleanly", { 37 | # Set random number generator to a known state so results will be 38 | # reproducible 39 | set.seed(4) # As specified by RFC 1149.5 ;) 40 | 41 | # Keep dictionaries for one day only 42 | dict_path <- file.path(".tikzMetrics", short_name) 43 | if (file.exists(dict_path) && (Sys.time() - file.info(dict_path)$mtime) > 86400) { 44 | unlink(dict_path) 45 | } 46 | 47 | withr::with_options( 48 | list(tikzMetricsDictionary = dict_path), 49 | expect_warning(create_graph(graph_code, graph_file, engine), NA) 50 | ) 51 | }) 52 | 53 | test_that("Graph compiles cleanly", { 54 | expect_warning(graph_created <<- compile_graph(graph_file, engine), NA) 55 | }) 56 | 57 | test_that("Output regression check", { 58 | 59 | # Uses the `compare` utility in imagemagick/graphicsmagick to diff the 60 | # generated graph against a "standard". If there are any differences, we 61 | # changed the code in a way that broke the behavior of the TikzDevice. 62 | # This test always "passes" as the real result is the number of pixels that 63 | # were found to be different between the test graph and the standard graph. 64 | # Such a result must be interpreted by a human. 65 | eval(bquote( 66 | expect_lt(compare_graph(.(short_name), tags), .(fuzz) + 0.1) 67 | )) 68 | }) 69 | 70 | 71 | return(graph_created) 72 | } 73 | 74 | create_graph <- function(graph_code, graph_file, engine) { 75 | tikz(file = graph_file, standAlone = TRUE, engine = engine) 76 | on.exit(dev.off()) 77 | 78 | eval(graph_code) 79 | 80 | invisible() 81 | } 82 | 83 | compile_graph <- function(graph_file, engine) { 84 | # Have to compile in the same directory as the .tex file so that things like 85 | # raster images can be found. 86 | oldwd <- getwd() 87 | setwd(test_work_dir) 88 | on.exit(setwd(oldwd)) 89 | 90 | tex_cmd <- get_latex_cmd(engine) 91 | 92 | silence <- system( 93 | paste( 94 | shQuote(tex_cmd), "-interaction=batchmode", 95 | "-output-directory", test_work_dir, 96 | graph_file 97 | ), intern = TRUE 98 | ) 99 | 100 | output_pdf <- sub("tex$", "pdf", graph_file) 101 | if (file.exists(output_pdf)) { 102 | file.rename(output_pdf, file.path(test_output_dir, basename(output_pdf))) 103 | graph_created <- TRUE 104 | } else { 105 | graph_created <- FALSE 106 | } 107 | 108 | return(graph_created) 109 | } 110 | 111 | compare_graph <- function(graph_name, tags) { 112 | if (is.null(compare_cmd)) { 113 | return(TRUE) 114 | } 115 | 116 | test_output <- file.path(test_output_dir, paste0(graph_name, ".pdf")) 117 | if ("ggplot2" %in% tags && exists("scale_y_probit")) { 118 | # We are using a version of ggplot2 that predates 0.9. 119 | # 120 | # FIXME: Remove this once we drop support for 2.13.x. 121 | standard_graph <- file.path(test_standard_dir, "ggplot_old", paste0(graph_name, ".pdf")) 122 | } else { 123 | standard_graph <- file.path(test_standard_dir, paste0(graph_name, ".pdf")) 124 | } 125 | 126 | if (!file.exists(test_output) || !file.exists(standard_graph)) { 127 | return(TRUE) 128 | } 129 | 130 | 131 | # Normalize and quote some paths in case we are running on Windows 132 | compare_output <- file.path(test_work_dir, paste0(graph_name, "_diff.png")) 133 | command_line <- paste( 134 | shQuote(compare_cmd), "-density 300", "-metric AE", "-quiet", 135 | shQuote(test_output), shQuote(standard_graph), shQuote(compare_output), 136 | "2>&1 | awk '{metric=$NF};END{print metric}'" 137 | ) 138 | 139 | result <- as.double(system( 140 | paste( 141 | # Force the command to be executed through bash 142 | "bash -c ", shQuote(command_line) 143 | ), 144 | intern = TRUE, ignore.stderr = TRUE 145 | )) 146 | 147 | return(as.numeric(result)) 148 | } 149 | -------------------------------------------------------------------------------- /vignettes/sweavetolst.sty: -------------------------------------------------------------------------------- 1 | \RequirePackage{verbatim} 2 | \RequirePackage{xstring} 3 | \RequirePackage{listings} 4 | % Source code formatting macros 5 | \lstloadlanguages{R} 6 | \lstset{columns=fullflexible} 7 | 8 | \lstdefinestyle{sweavechunk}{ 9 | language = R, 10 | basicstyle=\ttfamily, 11 | % The hacked version of the Sweave output function inserts these tags 12 | % around each output portion- we can grab them and apply formatting 13 | % to everything inside. 14 | moredelim=[is][\color{gray}] 15 | {Swe@veBeginOutput} 16 | {Swe@veEndOutput}, 17 | moredelim=[is][] 18 | {Swe@veBeginInput} 19 | {Swe@veEndInput}, 20 | showstringspaces = false, 21 | upquote = false, 22 | commentstyle = {\color{blue!70}\itshape} 23 | } 24 | 25 | 26 | % Re-define and customize the Schunk environment. Tasks to perform: 27 | % 28 | % * Capture all output using a verbatim environment and pipe it to a 29 | % temporary file. 30 | % 31 | % * Re-define Schunk to execute the above to steps and then read in the 32 | % final result using lstinputlisting. 33 | 34 | % We need to allocate some TeX variables 35 | \newwrite\sweave@tmpout % For writing output 36 | \newif\ifsweave@skipline % For skipping line processing after reading a delimiter 37 | \newif\ifsweave@outputready % For determining when a line is ready to be written 38 | \newtoks\sweave@linebuffer % For holding output lines before they are written 39 | 40 | % These macros help fill and manage the output buffer. 41 | \def\sweave@addtobuffer#1{% For appending to the contents of a token list. 42 | % Taken from TeX by Topic 43 | \toks0={#1} % Store the string to be added in a temporary buffer 44 | % Construct a command that sets the line buffer equal to the contents of it's 45 | % self plus the temporary buffer. 46 | \edef\act{\noexpand\sweave@linebuffer={\the\sweave@linebuffer \the\toks0}}% 47 | % Execute that command. 48 | \act% 49 | } 50 | 51 | % This macro will add a line of code read from a temp file to the buffer. 52 | \def\sweave@addoutput#1{% 53 | % expandafter is necessary to ensure #1 gets expanded before being appended to 54 | % the buffer. Otherwise we get the name of the macros storing the line of 55 | % code instead of the line of code. 56 | \expandafter\sweave@addtobuffer\expandafter{#1}% 57 | \sweave@outputreadytrue % The buffer now has code inside it for writing. 58 | } 59 | 60 | % This macro will write out the contents of the buffer and reset it. The 61 | % parameter #1 contains the file that should be written to. 62 | \def\sweave@flushbuffer#1{% 63 | \immediate\write#1{\the\sweave@linebuffer}% 64 | \sweave@linebuffer={}% 65 | \sweave@outputreadyfalse% 66 | } 67 | 68 | % Verbatim redefines the catcodes of common LaTeX special characters so that it 69 | % can capture them. However, this means we can't match against patterns like 70 | % \begin{Sinput} that are defined outside of a environment where Verbatim has 71 | % altered catcodes. For some reason use of indentation will throw a wrench into 72 | % the definitions below. 73 | \begingroup 74 | \let\do\@makeother 75 | \catcode`\|=0 \catcode`[=1 \catcode`]=2 76 | |dospecials 77 | |gdef|sweave@beginsinput[\begin{Sinput}] 78 | |gdef|sweave@endsinput[\end{Sinput}] 79 | |gdef|sweave@beginsoutput[\begin{Soutput}] 80 | |gdef|sweave@endsoutput[\end{Soutput}] 81 | |endgroup 82 | 83 | % This macro initiates a verbatim environment that writes it's contents 84 | % to a temporary file. 85 | \def\sweave@startcapture{% 86 | \immediate\openout\sweave@tmpout=\jobname.lstin\relax% 87 | \begingroup% 88 | \def\verbatim@nolig@list{}% 89 | \def\verbatim@processline{% 90 | \edef\sweave@codeline{\the\verbatim@line}% 91 | \IfBeginWith{\sweave@codeline}{\sweave@beginsinput}% 92 | {\sweave@addtobuffer{Swe@veBeginInput}\sweave@skiplinetrue}% 93 | {}% 94 | \IfBeginWith{\sweave@codeline}{\sweave@endsinput}% 95 | {\sweave@addtobuffer{Swe@veEndInput}\sweave@skiplinetrue}% 96 | {}% 97 | \IfBeginWith{\sweave@codeline}{\sweave@beginsoutput}% 98 | {\sweave@addtobuffer{Swe@veBeginOutput}\sweave@skiplinetrue}% 99 | {}% 100 | \IfBeginWith{\sweave@codeline}{\sweave@endsoutput}% 101 | {\sweave@addtobuffer{Swe@veEndOutput}\sweave@skiplinetrue}% 102 | {}% 103 | % Now process the line 104 | \ifsweave@skipline% 105 | \sweave@skiplinefalse% 106 | \else% 107 | \ifsweave@outputready% 108 | \sweave@flushbuffer{\sweave@tmpout}% 109 | \fi% 110 | \sweave@addoutput{\sweave@codeline}% 111 | \fi% 112 | }% 113 | \let\do\@makeother\dospecials\catcode`\^^M\active 114 | \verbatim@start% 115 | } 116 | 117 | % This macro stops the verbatim environment closes the temporary file. 118 | \def\sweave@stopcapture{% 119 | \sweave@flushbuffer{\sweave@tmpout}% Write out last line 120 | \endgroup% 121 | \immediate\closeout\sweave@tmpout% 122 | } 123 | 124 | % Here we re-define the Schunk environment declared by Sweave.sty 125 | \def\Schunk{\sweave@startcapture} 126 | \def\endSchunk{% 127 | \sweave@stopcapture% 128 | \tikzCodeInput[listing style=sweavechunk]{\jobname.lstin}% 129 | } 130 | 131 | \endinput 132 | 133 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body > .container { 21 | display: flex; 22 | height: 100%; 23 | flex-direction: column; 24 | 25 | padding-top: 60px; 26 | } 27 | 28 | body > .container .row { 29 | flex: 1 0 auto; 30 | } 31 | 32 | footer { 33 | margin-top: 45px; 34 | padding: 35px 0 36px; 35 | border-top: 1px solid #e5e5e5; 36 | color: #666; 37 | display: flex; 38 | flex-shrink: 0; 39 | } 40 | footer p { 41 | margin-bottom: 0; 42 | } 43 | footer div { 44 | flex: 1; 45 | } 46 | footer .pkgdown { 47 | text-align: right; 48 | } 49 | footer p { 50 | margin-bottom: 0; 51 | } 52 | 53 | img.icon { 54 | float: right; 55 | } 56 | 57 | img { 58 | max-width: 100%; 59 | } 60 | 61 | /* Fix bug in bootstrap (only seen in firefox) */ 62 | summary { 63 | display: list-item; 64 | } 65 | 66 | /* Typographic tweaking ---------------------------------*/ 67 | 68 | .contents .page-header { 69 | margin-top: calc(-60px + 1em); 70 | } 71 | 72 | /* Section anchors ---------------------------------*/ 73 | 74 | a.anchor { 75 | margin-left: -30px; 76 | display:inline-block; 77 | width: 30px; 78 | height: 30px; 79 | visibility: hidden; 80 | 81 | background-image: url(./link.svg); 82 | background-repeat: no-repeat; 83 | background-size: 20px 20px; 84 | background-position: center center; 85 | } 86 | 87 | .hasAnchor:hover a.anchor { 88 | visibility: visible; 89 | } 90 | 91 | @media (max-width: 767px) { 92 | .hasAnchor:hover a.anchor { 93 | visibility: hidden; 94 | } 95 | } 96 | 97 | 98 | /* Fixes for fixed navbar --------------------------*/ 99 | 100 | .contents h1, .contents h2, .contents h3, .contents h4 { 101 | padding-top: 60px; 102 | margin-top: -40px; 103 | } 104 | 105 | /* Static header placement on mobile devices */ 106 | @media (max-width: 767px) { 107 | .navbar-fixed-top { 108 | position: absolute; 109 | } 110 | .navbar { 111 | padding: 0; 112 | } 113 | } 114 | 115 | 116 | /* Sidebar --------------------------*/ 117 | 118 | #sidebar { 119 | margin-top: 30px; 120 | } 121 | #sidebar h2 { 122 | font-size: 1.5em; 123 | margin-top: 1em; 124 | } 125 | 126 | #sidebar h2:first-child { 127 | margin-top: 0; 128 | } 129 | 130 | #sidebar .list-unstyled li { 131 | margin-bottom: 0.5em; 132 | } 133 | 134 | .orcid { 135 | height: 16px; 136 | vertical-align: middle; 137 | } 138 | 139 | /* Reference index & topics ----------------------------------------------- */ 140 | 141 | .ref-index th {font-weight: normal;} 142 | 143 | .ref-index td {vertical-align: top;} 144 | .ref-index .icon {width: 40px;} 145 | .ref-index .alias {width: 40%;} 146 | .ref-index-icons .alias {width: calc(40% - 40px);} 147 | .ref-index .title {width: 60%;} 148 | 149 | .ref-arguments th {text-align: right; padding-right: 10px;} 150 | .ref-arguments th, .ref-arguments td {vertical-align: top;} 151 | .ref-arguments .name {width: 20%;} 152 | .ref-arguments .desc {width: 80%;} 153 | 154 | /* Nice scrolling for wide elements --------------------------------------- */ 155 | 156 | table { 157 | display: block; 158 | overflow: auto; 159 | } 160 | 161 | /* Syntax highlighting ---------------------------------------------------- */ 162 | 163 | pre { 164 | word-wrap: normal; 165 | word-break: normal; 166 | border: 1px solid #eee; 167 | } 168 | 169 | pre, code { 170 | background-color: #f8f8f8; 171 | color: #333; 172 | } 173 | 174 | pre code { 175 | overflow: auto; 176 | word-wrap: normal; 177 | white-space: pre; 178 | } 179 | 180 | pre .img { 181 | margin: 5px 0; 182 | } 183 | 184 | pre .img img { 185 | background-color: #fff; 186 | display: block; 187 | height: auto; 188 | } 189 | 190 | code a, pre a { 191 | color: #375f84; 192 | } 193 | 194 | a.sourceLine:hover { 195 | text-decoration: none; 196 | } 197 | 198 | .fl {color: #1514b5;} 199 | .fu {color: #000000;} /* function */ 200 | .ch,.st {color: #036a07;} /* string */ 201 | .kw {color: #264D66;} /* keyword */ 202 | .co {color: #888888;} /* comment */ 203 | 204 | .message { color: black; font-weight: bolder;} 205 | .error { color: orange; font-weight: bolder;} 206 | .warning { color: #6A0366; font-weight: bolder;} 207 | 208 | /* Clipboard --------------------------*/ 209 | 210 | .hasCopyButton { 211 | position: relative; 212 | } 213 | 214 | .btn-copy-ex { 215 | position: absolute; 216 | right: 0; 217 | top: 0; 218 | visibility: hidden; 219 | } 220 | 221 | .hasCopyButton:hover button.btn-copy-ex { 222 | visibility: visible; 223 | } 224 | 225 | /* mark.js ----------------------------*/ 226 | 227 | mark { 228 | background-color: rgba(255, 255, 51, 0.5); 229 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 230 | padding: 1px; 231 | } 232 | 233 | /* vertical spacing after htmlwidgets */ 234 | .html-widget { 235 | margin-bottom: 10px; 236 | } 237 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • tikzDevice 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 45 | 46 | 47 | 48 | 49 | 50 |
    51 |
    52 | 95 | 96 | 97 |
    98 | 99 |
    100 |
    101 | 104 | 105 |
      106 |
    • 107 |

      Charlie Sharpsteen. Author. 108 |

      109 |
    • 110 |
    • 111 |

      Cameron Bracken. Author. 112 |

      113 |
    • 114 |
    • 115 |

      Kirill Müller. Contributor. 116 |

      117 |
    • 118 |
    • 119 |

      Yihui Xie. Contributor. 120 |

      121 |
    • 122 |
    • 123 |

      Ralf Stubner. Maintainer. 124 |

      125 |
    • 126 |
    • 127 |

      Nico Bellack. Contributor. 128 |

      129 |
    • 130 |
    131 | 132 |
    133 | 134 |
    135 | 136 | 137 |
    138 | 141 | 142 |
    143 |

    Site built with pkgdown 1.3.0.

    144 |
    145 |
    146 |
    147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /man/tikzDevice-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/tikzDevice-package.R 3 | \docType{package} 4 | \name{tikzDevice-package} 5 | \alias{tikzDevice-package} 6 | \alias{tikzDevice} 7 | \title{Support for native LaTeX output of R graphics} 8 | \description{ 9 | The tikzDevice package implements the \code{\link[=tikz]{tikz()}} ouput device which 10 | generates R graphics in a LaTeX friendly format. LaTeX handles the 11 | typesetting of all text in graphics generated by \code{tikz}. This allows for 12 | seamless integration between these graphics and documents that are also being 13 | typeset by LaTeX. Using LaTeX to generate graph text also means that 14 | \strong{LaTeX mathematics can be typeset directly into labels and 15 | annotations}. 16 | } 17 | \section{Options That Affect Package Behavior}{ 18 | The \pkg{tikzDevice} package 19 | is currently influenced by a number of global options that may be set in 20 | scripts, from the console or in a \code{.Rprofile} file. All of the options 21 | can be set by using \verb{options(