maechler@stat.math.ethz.ch
2000-Jun-27 07:11 UTC
[Rd] par(lty = "1") -- lty storage-etc bug (PR#584)
Bug report, rather than R-help; This is at least since 1.0.0; didn't try even older versions .. Jim> Anon wrote: Anon> ...However, if I use Fred <- c(1,"33")... Is this a Anon> bug, or am I missing something? this made use it essentially something like par(lty = "1") Jim> This is an interesting problem. It boils down to the fact that Jim> PostScript expects an array (even if it's empty) and an offset for Jim> "setdash". Normally, a solid line is specified with an empty Jim> array and zero offset. However, if R gets specs that convert to Jim> zero and puts a zero in the array, the PostScript interpreter will Jim> barf. Zero can appear, but there must be at least one non-zero Jim> number in the array. Hexadecimal strings supplied to lty are Jim> converted to array elements, but a single character "1" seems to Jim> produce "0.00". Remember that the c() operater will coerce the Jim> number 1 to the string "1" when combining it with "33". That is, Jim> it's probably a bad idea to mix the two methods of specifying line Jim> types with "lty". I think there's at least another (maybe the only one) bug in main/graphics.c which is not related to postscript at all, see below. Jim> A possible fix is to insert a test for zero in the function Jim> SetLineStyle() - devPS.c: >> static void SetLineStyle(int newlty, double newlwd, DevDesc *dd) >> { >> PostScriptDesc *pd = (PostScriptDesc *) dd->deviceSpecific; >> int i, ltyarray[8]; >> int sum = 0; >> if (pd->lty != newlty || pd->lwd != newlwd) { >> pd->lwd = newlwd; >> pd->lty = newlty; >> PostScriptSetLineWidth(pd->psfp, dd->gp.lwd*0.75); >> for(i = 0; i < 8 && newlty & 15 ; i++) { >> ltyarray[i] = newlty & 15; >> sum += ltyarray[i]; >> newlty = newlty >> 4; >> } >> if(!sum) i = 0; >> PostScriptSetLineTexture(pd->psfp, ltyarray, i, dd->gp.lwd * 0.75); >> } >> } Jim> producing a solid line when all elements of 'ltyarray' are zero. yes, but I think this shouldn't be necessary. The real bug is uglier: If you use something like par(lty="1") or any other one-letter (hex digit) string, this leads to an invalid `code', and further, the storage location (such dd->lty in C) of that string somehow loses it's final string terminator (\0 in C) and gets mangled. I can reproduce this most easily with the following for(i in seq(along=dev.list())) dev.off() par(lty="1") example(barplot) ## (almost!) always ends in an error, see below, ## and then for(i in 1:4) print(par("lty")) -------- Note that in the Error message below, "invalid hex digit in color" has been changed in the very latest R-release sources to "invalid hex digit in color or lty" which is ``more helpful'' here :> example(barplot) ## (almost!) always ends in an error, see below,barplt> tN <- table(Ni <- rpois(100, lambda = 5)) barplt> r <- barplot(tN, col = "gray") barplt> lines(r, tN, type = "h", col = "red", lwd = 2) Error in plot.xy(xy.coords(x, y), type = type, col = col, lty = lty, ...) : invalid hex digit in color> traceback()[1] "plot.xy(xy.coords(x, y), type = type, col = col, lty = lty, ...)" [2] "lines.default(r, tN, type = \"h\", col = \"red\", lwd = 2)" [3] "lines(r, tN, type = \"h\", col = \"red\", lwd = 2)" [4] "eval.with.vis(expr, envir, enclos)" [5] "eval.with.vis(ei, envir)" [6] "source(zfile, echo = echo, prompt.echo = prompt.echo, verbose = verbose, " [7] " max.deparse.length = 250)" [8] "example(barplot)"> for(i in 1:4) print(par("lty"))[1] "1r" [1] "1SI@}@gMG@\\}@\"J@}@U\\F@4}@?D@|@A@|@]G@|@(B@names" [1] "1|@ult" [1] "1">--------- Peter D., I'd like to learn how to use watchpoints to debug this... Martin -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html Send "info", "help", or "[un]subscribe" (in the "body", not the subject !) To: r-devel-request@stat.math.ethz.ch _._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._