Usually, if you need this level of control over plot elements, you will have to do it manually using primitives ( points() , lines() / segments() , text() , etc.) and careful calculations from the graph parameters (for example , par('usr') ). It is not simple. Here is an example of how this can be done:
point.line.point <- function(x1,y1,x2=x1,y2=y1,...) { points(c(x1,x2),c(y1,y2),...); segments(x1,y1,x2,y2,...); }; legend.plp <- function(x,y,labels,col,linewidth=diff(par('usr')[1:2])/10,textgap=diff(par('usr')[1:2])/20,...) { comb <- cbind(labels,col); xc <- x; for (i in seq_len(nrow(comb))) { x2 <- xc+linewidth; point.line.point(xc,y,x2,col=comb[i,'col'],...); text(x2+textgap,y,comb[i,'labels'],...); xc <- x2+textgap*1.5+strwidth(comb[i,'labels']); }; }; plot(1,1,type="n"); legend.plp(par('usr')[1]+diff(par('usr')[1:2])/20,par('usr')[4]-diff(par('usr')[3:4])/20,1:2,c('darkblue','darkred'),font=2,cex=1.5);
