[Rd] par(lty = "1") -- lty storage-etc bug (PR#584)
maechler@stat.math.ethz.ch
maechler@stat.math.ethz.ch
Tue, 27 Jun 2000 09:11:36 +0200 (MET DST)
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] "1ÂS°I@ø}@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
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._