ASCII Box rendering
APL, 116 bytes
{⎕IO←0⋄K←' '⍴⍨⌽+⌿2 2⍴⌈⌿↑⍵⋄K⊣{x y W H←⍵-⌊.5×⍳4⋄K[Y←y+⍳H;X←x+⍳W]←' '⋄K[Y;A←x+0 W]←'|'⋄K[B←y+0 H;X]←'-'⋄K[B;A]←'+'}¨⌽⍵}
This is a function that takes an array of arrays and returns a character matrix.
Tests:
t1← (0 0 11 4)(8 2 8 4)(3 5 8 3)
t2← (0 3 11 4)(8 5 8 4)(3 8 8 3)(4 0 13 5)
t3← (⊂0 0 2 2)
t4← (2 2 5 3)(1 1 7 5)(0 0 9 7)
{⎕IO←0⋄K←' '⍴⍨⌽+⌿2 2⍴⌈⌿↑⍵⋄K⊣{x y W H←⍵-⌊.5×⍳4⋄K[Y←y+⍳H;X←x+⍳W]←' '⋄K[Y;A←x+0 W]←'|'⋄K[B←y+0 H;X]←'-'⋄K[B;A]←'+'}¨⌽⍵} ¨ t1 t2 t3 t4
┌───────────────────┬─────────────────────┬────┬───────────┐
│+---------+ │ +-----------+ │++ │+-------+ │
│| | │ | | │++ │|+-----+| │
│| |----+ │ | | │ │||+---+|| │
│+---------+ | │+---------+ | │ │||| ||| │
│ | | │| |-----+ │ │||+---+|| │
│ +----+------+ │| |----+ │ │|+-----+| │
│ | | │+---------+ | │ │+-------+ │
│ +------+ │ | | │ │ │
│ │ +----+------+ │ │ │
│ │ | | │ │ │
│ │ +------+ │ │ │
│ │ │ │ │
│ │ │ │ │
└───────────────────┴─────────────────────┴────┴───────────┘
Explanation:
⎕IO←0
: set the index origin to0
.- Create a matrix of the right size:
⌈⌿↑⍵
: find the largest values for x, y, w, and h+⌿2 2⍴
: x+w and y+hK←' '⍴⍨⌽
: make a matrix of x+w*y+h spaces and store it inK
.
- Draw the boxes into it:
{
...}¨⌽⍵
: for each of the boxes, in reverse order,x y W H←⍵-⌊.5×⍳4
: assign the coordinates tox
,y
,W
, andH
, and subtract 1 from bothW
andH
. (coordinates are exclusive, APL array ranges are inclusive.)K[Y←y+⍳H;X←x+⍳W]←' '
: fill the current box with spacesK[Y;A←x+0 W]←'|'
: draw the vertical sidesK[B←y+0 H;X]←'-'
: draw the horizontal sidesK[B;A]←'+'
: set the edges to '+'
K⊣
: afterwards, returnK
.
ES6, 228 223 217 208 201 198 bytes
Accepts an array of arrays of coordinates and returns a string.
a=>a.reverse().map(([x,y,w,h])=>[...Array(y+h)].map((_,i)=>(s=r[i]||'',r[i]=i<y?s:(s+' '.repeat(x)).slice(0,x)+(c=>c[0]+c[1].repeat(w-2)+c[0])(y-i&&y+h-1-i?'| ':'+-')+s.slice(x+w))),r=[])&&r.join`\n`
Where \n
represents a newline character.
Edit: Saved 5 bytes by reversing my conditions. Saved a further 6 bytes by switching from an array of char arrays to an array of strings. Saved a further 9 bytes by introducing a temporary variable. Saved a further 7 bytes by introducing a helper function. Saved a further 3 bytes by undoing a previous saving!
Ruby, 153 143
->n{a=(0..m=3*n.max).map{$b=' '*m}
(*n,x,y,w,h=n
v=w-2
h.times{|i|a[y+i][x,w]=i%~-h<1??++?-*v+?+:?|+' '*v+?|}
)while n[0]
a.delete($b);puts a}
Ungolfed in test program
f=->n{ #worst case width when x=w=large number, is max input*2+1
a=(1..m=3*n.max).map{$b=' '*m} #find m=max value in input, make an a array of 3*m strings of 3*m spaces
(
*n,x,y,w,h=n #extract x,y,w,h from the end of n, save the rest back to n
v=w-2 #internal space in rectangle is w-2
h.times{|i| #for each row
a[y+i][x,w]= #substitute the relevant characters of the relevant lines of a
i%~-h<1? #i%~-h = i%(h-1). This is zero (<1) for first and last lines of the rectangle
?+ + ?-*v + ?+ :?| + ' '*v +?| # +--...--+ or | ... | as required
}
)while n[0] #loop until data exhausted (n[0] becomes falsy as it does not exist)
a.delete($b);puts a} #delete blank rows ($b is a global variable) and display