Advertisement
CCCoder

Surface 2 Build

Aug 16th, 2020
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 44.01 KB | None | 0 0
  1. local surface = { } do
  2. --[[
  3. Surface 2
  4.  
  5. The MIT License (MIT)
  6. Copyright (c) 2017 CrazedProgrammer
  7.  
  8. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
  9. associated documentation files (the "Software"), to deal in the Software without restriction,
  10. including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
  12. so, subject to the following conditions:
  13.  
  14. The above copyright notice and this permission notice shall be included in all copies or
  15. substantial portions of the Software.
  16.  
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  18. INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  19. PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  20. COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. ]]
  24.  
  25. local surf = { }
  26. surface.surf = surf
  27.  
  28. local table_concat, math_floor, math_atan2 = table.concat, math.floor, math.atan2
  29.  
  30. local _cc_color_to_hex, _cc_hex_to_color = { }, { }
  31. for i = 0, 15 do
  32. _cc_color_to_hex[2 ^ i] = string.format("%01x", i)
  33. _cc_hex_to_color[string.format("%01x", i)] = 2 ^ i
  34. end
  35.  
  36. local _chars = { }
  37. for i = 0, 255 do
  38. _chars[i] = string.char(i)
  39. end
  40. local _numstr = { }
  41. for i = 0, 1023 do
  42. _numstr[i] = tostring(i)
  43. end
  44.  
  45. local _eprc, _esin, _ecos = 20, { }, { }
  46. for i = 0, _eprc - 1 do
  47. _esin[i + 1] = (1 - math.sin(i / _eprc * math.pi * 2)) / 2
  48. _ecos[i + 1] = (1 + math.cos(i / _eprc * math.pi * 2)) / 2
  49. end
  50.  
  51. local _steps, _palette, _rgbpal, _palr, _palg, _palb = 16
  52.  
  53. local function calcStack(stack, width, height)
  54. local ox, oy, cx, cy, cwidth, cheight = 0, 0, 0, 0, width, height
  55. for i = 1, #stack do
  56. ox = ox + stack[i].ox
  57. oy = oy + stack[i].oy
  58. cx = cx + stack[i].x
  59. cy = cy + stack[i].y
  60. cwidth = stack[i].width
  61. cheight = stack[i].height
  62. end
  63. return ox, oy, cx, cy, cwidth, cheight
  64. end
  65.  
  66. local function clipRect(x, y, width, height, cx, cy, cwidth, cheight)
  67. if x < cx then
  68. width = width + x - cx
  69. x = cx
  70. end
  71. if y < cy then
  72. height = height + y - cy
  73. y = cy
  74. end
  75. if x + width > cx + cwidth then
  76. width = cwidth + cx - x
  77. end
  78. if y + height > cy + cheight then
  79. height = cheight + cy - y
  80. end
  81. return x, y, width, height
  82. end
  83.  
  84.  
  85.  
  86. function surface.create(width, height, b, t, c)
  87. local surface = setmetatable({ }, {__index = surface.surf})
  88. surface.width = width
  89. surface.height = height
  90. surface.buffer = { }
  91. surface.overwrite = false
  92. surface.stack = { }
  93. surface.ox, surface.oy, surface.cx, surface.cy, surface.cwidth, surface.cheight = calcStack(surface.stack, width, height)
  94. -- force array indeces instead of hashed indices
  95.  
  96. local buffer = surface.buffer
  97. for i = 1, width * height * 3, 3 do
  98. buffer[i] = b or false
  99. buffer[i + 1] = t or false
  100. buffer[i + 2] = c or false
  101. end
  102. buffer[width * height * 3 + 1] = false
  103. if not b then
  104. for i = 1, width * height * 3, 3 do
  105. buffer[i] = b
  106. end
  107. end
  108. if not t then
  109. for i = 2, width * height * 3, 3 do
  110. buffer[i] = t
  111. end
  112. end
  113. if not c then
  114. for i = 3, width * height * 3, 3 do
  115. buffer[i] = c
  116. end
  117. end
  118.  
  119. return surface
  120. end
  121.  
  122. function surface.getPlatformOutput(output)
  123. output = output or (term or gpu or (love and love.graphics) or io)
  124.  
  125. if output.blit and output.setCursorPos then
  126. return "cc", output, output.getSize()
  127. elseif output.write and output.setCursorPos and output.setTextColor and output.setBackgroundColor then
  128. return "cc-old", output, output.getSize()
  129. elseif output.blitPixels then
  130. return "riko-4", output, 320, 200
  131. elseif output.points and output.setColor then
  132. return "love2d", output, output.getWidth(), output.getHeight()
  133. elseif output.drawPixel then
  134. return "redirection", output, 64, 64
  135. elseif output.setForeground and output.setBackground and output.set then
  136. return "oc", output, output.getResolution()
  137. elseif output.write then
  138. return "ansi", output, (os.getenv and (os.getenv("COLUMNS"))) or 80, (os.getenv and (os.getenv("LINES"))) or 43
  139. else
  140. error("unsupported platform/output object")
  141. end
  142. end
  143.  
  144. function surf:output(output, x, y, sx, sy, swidth, sheight)
  145. local platform, output, owidth, oheight = surface.getPlatformOutput(output)
  146.  
  147. x = x or 0
  148. y = y or 0
  149. sx = sx or 0
  150. sy = sy or 0
  151. swidth = swidth or self.width
  152. sheight = sheight or self.height
  153. sx, sy, swidth, sheight = clipRect(sx, sy, swidth, sheight, 0, 0, self.width, self.height)
  154.  
  155. local buffer = self.buffer
  156. local bwidth = self.width
  157. local xoffset, yoffset, idx
  158.  
  159. if platform == "cc" then
  160. -- CC
  161. local str, text, back = { }, { }, { }
  162. for j = 0, sheight - 1 do
  163. yoffset = (j + sy) * bwidth + sx
  164. for i = 0, swidth - 1 do
  165. xoffset = (yoffset + i) * 3
  166. idx = i + 1
  167. str[idx] = buffer[xoffset + 3] or " "
  168. text[idx] = _cc_color_to_hex[buffer[xoffset + 2] or 1]
  169. back[idx] = _cc_color_to_hex[buffer[xoffset + 1] or 32768]
  170. end
  171. output.setCursorPos(x + 1, y + j + 1)
  172. output.blit(table_concat(str), table_concat(text), table_concat(back))
  173. end
  174.  
  175. elseif platform == "cc-old" then
  176. -- CC pre-1.76
  177. local str, b, t, pb, pt = { }
  178. for j = 0, sheight - 1 do
  179. output.setCursorPos(x + 1, y + j + 1)
  180. yoffset = (j + sy) * bwidth + sx
  181. for i = 0, swidth - 1 do
  182. xoffset = (yoffset + i) * 3
  183. pb = buffer[xoffset + 1] or 32768
  184. pt = buffer[xoffset + 2] or 1
  185. if pb ~= b then
  186. if #str ~= 0 then
  187. output.write(table_concat(str))
  188. str = { }
  189. end
  190. b = pb
  191. output.setBackgroundColor(b)
  192. end
  193. if pt ~= t then
  194. if #str ~= 0 then
  195. output.write(table_concat(str))
  196. str = { }
  197. end
  198. t = pt
  199. output.setTextColor(t)
  200. end
  201. str[#str + 1] = buffer[xoffset + 3] or " "
  202. end
  203. output.write(table_concat(str))
  204. str = { }
  205. end
  206.  
  207. elseif platform == "riko-4" then
  208. -- Riko 4
  209. local pixels = { }
  210. for j = 0, sheight - 1 do
  211. yoffset = (j + sy) * bwidth + sx
  212. for i = 0, swidth - 1 do
  213. pixels[j * swidth + i + 1] = buffer[(yoffset + i) * 3 + 1] or 0
  214. end
  215. end
  216. output.blitPixels(x, y, swidth, sheight, pixels)
  217.  
  218. elseif platform == "love2d" then
  219. -- Love2D
  220. local pos, r, g, b, pr, pg, pb = { }
  221. for j = 0, sheight - 1 do
  222. yoffset = (j + sy) * bwidth + sx
  223. for i = 0, swidth - 1 do
  224. xoffset = (yoffset + i) * 3
  225. pr = buffer[xoffset + 1]
  226. pg = buffer[xoffset + 2]
  227. pb = buffer[xoffset + 3]
  228. if pr ~= r or pg ~= g or pb ~= b then
  229. if #pos ~= 0 then
  230. output.setColor((r or 0) * 255, (g or 0) * 255, (b or 0) * 255, (r or g or b) and 255 or 0)
  231. output.points(pos)
  232. end
  233. r, g, b = pr, pg, pb
  234. pos = { }
  235. end
  236. pos[#pos + 1] = i + x + 1
  237. pos[#pos + 1] = j + y + 1
  238. end
  239. end
  240. output.setColor((r or 0) * 255, (g or 0) * 255, (b or 0) * 255, (r or g or b) and 255 or 0)
  241. output.points(pos)
  242.  
  243. elseif platform == "redirection" then
  244. -- Redirection arcade (gpu)
  245. -- todo: add image:write support for extra performance
  246. local px = output.drawPixel
  247. for j = 0, sheight - 1 do
  248. for i = 0, swidth - 1 do
  249. px(x + i, y + j, buffer[((j + sy) * bwidth + (i + sx)) * 3 + 1] or 0)
  250. end
  251. end
  252.  
  253. elseif platform == "oc" then
  254. -- OpenComputers
  255. local str, lx, b, t, pb, pt = { }
  256. for j = 0, sheight - 1 do
  257. lx = x
  258. yoffset = (j + sy) * bwidth + sx
  259. for i = 0, swidth - 1 do
  260. xoffset = (yoffset + i) * 3
  261. pb = buffer[xoffset + 1] or 0x000000
  262. pt = buffer[xoffset + 2] or 0xFFFFFF
  263. if pb ~= b then
  264. if #str ~= 0 then
  265. output.set(lx + 1, j + y + 1, table_concat(str))
  266. lx = i + x
  267. str = { }
  268. end
  269. b = pb
  270. output.setBackground(b)
  271. end
  272. if pt ~= t then
  273. if #str ~= 0 then
  274. output.set(lx + 1, j + y + 1, table_concat(str))
  275. lx = i + x
  276. str = { }
  277. end
  278. t = pt
  279. output.setForeground(t)
  280. end
  281. str[#str + 1] = buffer[xoffset + 3] or " "
  282. end
  283. output.set(lx + 1, j + y + 1, table_concat(str))
  284. str = { }
  285. end
  286.  
  287. elseif platform == "ansi" then
  288. -- ANSI terminal
  289. local str, b, t, pb, pt = { }
  290. for j = 0, sheight - 1 do
  291. str[#str + 1] = "\x1b[".._numstr[y + j + 1]..";".._numstr[x + 1].."H"
  292. yoffset = (j + sy) * bwidth + sx
  293. for i = 0, swidth - 1 do
  294. xoffset = (yoffset + i) * 3
  295. pb = buffer[xoffset + 1] or 0
  296. pt = buffer[xoffset + 2] or 7
  297. if pb ~= b then
  298. b = pb
  299. if b < 8 then
  300. str[#str + 1] = "\x1b[".._numstr[40 + b].."m"
  301. elseif b < 16 then
  302. str[#str + 1] = "\x1b[".._numstr[92 + b].."m"
  303. elseif b < 232 then
  304. str[#str + 1] = "\x1b[48;2;".._numstr[math_floor((b - 16) / 36 * 85 / 2)]..";".._numstr[math_floor((b - 16) / 6 % 6 * 85 / 2)]..";".._numstr[math_floor((b - 16) % 6 * 85 / 2)].."m"
  305. else
  306. local gr = _numstr[b * 10 - 2312]
  307. str[#str + 1] = "\x1b[48;2;"..gr..";"..gr..";"..gr.."m"
  308. end
  309. end
  310. if pt ~= t then
  311. t = pt
  312. if t < 8 then
  313. str[#str + 1] = "\x1b[".._numstr[30 + t].."m"
  314. elseif t < 16 then
  315. str[#str + 1] = "\x1b[".._numstr[82 + t].."m"
  316. elseif t < 232 then
  317. str[#str + 1] = "\x1b[38;2;".._numstr[math_floor((t - 16) / 36 * 85 / 2)]..";".._numstr[math_floor((t - 16) / 6 % 6 * 85 / 2)]..";".._numstr[math_floor((t - 16) % 6 * 85 / 2)].."m"
  318. else
  319. local gr = _numstr[t * 10 - 2312]
  320. str[#str + 1] = "\x1b[38;2;"..gr..";"..gr..";"..gr.."m"
  321. end
  322. end
  323. str[#str + 1] = buffer[xoffset + 3] or " "
  324. end
  325. end
  326. output.write(table_concat(str))
  327. end
  328. end
  329.  
  330. function surf:push(x, y, width, height, nooffset)
  331. x, y = x + self.ox, y + self.oy
  332.  
  333. local ox, oy = nooffset and self.ox or x, nooffset and self.oy or y
  334. x, y, width, height = clipRect(x, y, width, height, self.cx, self.cy, self.cwidth, self.cheight)
  335. self.stack[#self.stack + 1] = {ox = ox - self.ox, oy = oy - self.oy, x = x - self.cx, y = y - self.cy, width = width, height = height}
  336.  
  337. self.ox, self.oy, self.cx, self.cy, self.cwidth, self.cheight = calcStack(self.stack, self.width, self.height)
  338. end
  339.  
  340. function surf:pop()
  341. if #self.stack == 0 then
  342. error("no stencil to pop")
  343. end
  344. self.stack[#self.stack] = nil
  345. self.ox, self.oy, self.cx, self.cy, self.cwidth, self.cheight = calcStack(self.stack, self.width, self.height)
  346. end
  347.  
  348. function surf:copy()
  349. local surface = setmetatable({ }, {__index = surface.surf})
  350.  
  351. for k, v in pairs(self) do
  352. surface[k] = v
  353. end
  354.  
  355. surface.buffer = { }
  356. for i = 1, self.width * self.height * 3 + 1 do
  357. surface.buffer[i] = false
  358. end
  359. for i = 1, self.width * self.height * 3 do
  360. surface.buffer[i] = self.buffer[i]
  361. end
  362.  
  363. surface.stack = { }
  364. for i = 1, #self.stack do
  365. surface.stack[i] = self.stack[i]
  366. end
  367.  
  368. return surface
  369. end
  370.  
  371. function surf:clear(b, t, c)
  372. local xoffset, yoffset
  373.  
  374. for j = 0, self.cheight - 1 do
  375. yoffset = (j + self.cy) * self.width + self.cx
  376. for i = 0, self.cwidth - 1 do
  377. xoffset = (yoffset + i) * 3
  378. self.buffer[xoffset + 1] = b
  379. self.buffer[xoffset + 2] = t
  380. self.buffer[xoffset + 3] = c
  381. end
  382. end
  383. end
  384.  
  385. function surf:drawPixel(x, y, b, t, c)
  386. x, y = x + self.ox, y + self.oy
  387.  
  388. local idx
  389. if x >= self.cx and x < self.cx + self.cwidth and y >= self.cy and y < self.cy + self.cheight then
  390. idx = (y * self.width + x) * 3
  391. if b or self.overwrite then
  392. self.buffer[idx + 1] = b
  393. end
  394. if t or self.overwrite then
  395. self.buffer[idx + 2] = t
  396. end
  397. if c or self.overwrite then
  398. self.buffer[idx + 3] = c
  399. end
  400. end
  401. end
  402.  
  403. function surf:drawString(str, x, y, b, t)
  404. x, y = x + self.ox, y + self.oy
  405.  
  406. local sx = x
  407. local insidey = y >= self.cy and y < self.cy + self.cheight
  408. local idx
  409. local lowerxlim = self.cx
  410. local upperxlim = self.cx + self.cwidth
  411. local writeb = b or self.overwrite
  412. local writet = t or self.overwrite
  413.  
  414. for i = 1, #str do
  415. local c = str:sub(i, i)
  416. if c == "\n" then
  417. x = sx
  418. y = y + 1
  419. if insidey then
  420. if y >= self.cy + self.cheight then
  421. return
  422. end
  423. else
  424. insidey = y >= self.cy
  425. end
  426. else
  427. idx = (y * self.width + x) * 3
  428. if x >= lowerxlim and x < upperxlim and insidey then
  429. if writeb then
  430. self.buffer[idx + 1] = b
  431. end
  432. if writet then
  433. self.buffer[idx + 2] = t
  434. end
  435. self.buffer[idx + 3] = c
  436. end
  437. x = x + 1
  438. end
  439. end
  440. end
  441.  
  442. -- You can remove any of these components
  443. function surface.load(strpath, isstr)
  444. local data = strpath
  445. if not isstr then
  446. local handle = io.open(strpath, "rb")
  447. if not handle then return end
  448. local chars = { }
  449. local byte = handle:read(1)
  450. if type(byte) == "number" then -- cc doesn't conform to standards
  451. while byte do
  452. chars[#chars + 1] = _chars[byte]
  453. byte = handle:read(1)
  454. end
  455. else
  456. while byte do
  457. chars[#chars + 1] = byte
  458. byte = handle:read(1)
  459. end
  460. end
  461. handle:close()
  462. data = table_concat(chars)
  463. end
  464.  
  465. if data:sub(1, 3) == "RIF" then
  466. -- Riko 4 image format
  467. local width, height = data:byte(4) * 256 + data:byte(5), data:byte(6) * 256 + data:byte(7)
  468. local surf = surface.create(width, height)
  469. local buffer = surf.buffer
  470. local upper, byte = 8, false
  471. local byte = data:byte(index)
  472.  
  473. for j = 0, height - 1 do
  474. for i = 0, height - 1 do
  475. if not upper then
  476. buffer[(j * width + i) * 3 + 1] = math_floor(byte / 16)
  477. else
  478. buffer[(j * width + i) * 3 + 1] = byte % 16
  479. index = index + 1
  480. data = data:byte(index)
  481. end
  482. upper = not upper
  483. end
  484. end
  485. return surf
  486.  
  487. elseif data:sub(1, 2) == "BM" then
  488. -- BMP format
  489. local width = data:byte(0x13) + data:byte(0x14) * 256
  490. local height = data:byte(0x17) + data:byte(0x18) * 256
  491. if data:byte(0xF) ~= 0x28 or data:byte(0x1B) ~= 1 or data:byte(0x1D) ~= 0x18 then
  492. error("unsupported bmp format, only uncompressed 24-bit rgb is supported.")
  493. end
  494. local offset, linesize = 0x36, math.ceil((width * 3) / 4) * 4
  495.  
  496. local surf = surface.create(width, height)
  497. local buffer = surf.buffer
  498. for j = 0, height - 1 do
  499. for i = 0, width - 1 do
  500. buffer[(j * width + i) * 3 + 1] = data:byte((height - j - 1) * linesize + i * 3 + offset + 3) / 255
  501. buffer[(j * width + i) * 3 + 2] = data:byte((height - j - 1) * linesize + i * 3 + offset + 2) / 255
  502. buffer[(j * width + i) * 3 + 3] = data:byte((height - j - 1) * linesize + i * 3 + offset + 1) / 255
  503. end
  504. end
  505. return surf
  506.  
  507. elseif data:find("\30") then
  508. -- NFT format
  509. local width, height, lwidth = 0, 1, 0
  510. for i = 1, #data do
  511. if data:byte(i) == 10 then -- newline
  512. height = height + 1
  513. if lwidth > width then
  514. width = lwidth
  515. end
  516. lwidth = 0
  517. elseif data:byte(i) == 30 or data:byte(i) == 31 then -- color control
  518. lwidth = lwidth - 1
  519. elseif data:byte(i) ~= 13 then -- not carriage return
  520. lwidth = lwidth + 1
  521. end
  522. end
  523. if data:byte(#data) == 10 then
  524. height = height - 1
  525. end
  526.  
  527. local surf = surface.create(width, height)
  528. local buffer = surf.buffer
  529. local index, x, y, b, t = 1, 0, 0
  530.  
  531. while index <= #data do
  532. if data:byte(index) == 10 then
  533. x, y = 0, y + 1
  534. elseif data:byte(index) == 30 then
  535. index = index + 1
  536. b = _cc_hex_to_color[data:sub(index, index)]
  537. elseif data:byte(index) == 31 then
  538. index = index + 1
  539. t = _cc_hex_to_color[data:sub(index, index)]
  540. elseif data:byte(index) ~= 13 then
  541. buffer[(y * width + x) * 3 + 1] = b
  542. buffer[(y * width + x) * 3 + 2] = t
  543. if b or t then
  544. buffer[(y * width + x) * 3 + 3] = data:sub(index, index)
  545. elseif data:sub(index, index) ~= " " then
  546. buffer[(y * width + x) * 3 + 3] = data:sub(index, index)
  547. end
  548. x = x + 1
  549. end
  550. index = index + 1
  551. end
  552.  
  553. return surf
  554. else
  555. -- NFP format
  556. local width, height, lwidth = 0, 1, 0
  557. for i = 1, #data do
  558. if data:byte(i) == 10 then -- newline
  559. height = height + 1
  560. if lwidth > width then
  561. width = lwidth
  562. end
  563. lwidth = 0
  564. elseif data:byte(i) ~= 13 then -- not carriage return
  565. lwidth = lwidth + 1
  566. end
  567. end
  568. if data:byte(#data) == 10 then
  569. height = height - 1
  570. end
  571.  
  572. local surf = surface.create(width, height)
  573. local buffer = surf.buffer
  574. local x, y = 0, 0
  575. for i = 1, #data do
  576. if data:byte(i) == 10 then
  577. x, y = 0, y + 1
  578. elseif data:byte(i) ~= 13 then
  579. buffer[(y * width + x) * 3 + 1] = _cc_hex_to_color[data:sub(i, i)]
  580. x = x + 1
  581. end
  582. end
  583.  
  584. return surf
  585. end
  586. end
  587.  
  588. function surf:save(file, format)
  589. format = format or "nfp"
  590. local data = { }
  591. if format == "nfp" then
  592. for j = 0, self.height - 1 do
  593. for i = 0, self.width - 1 do
  594. data[#data + 1] = _cc_color_to_hex[self.buffer[(j * self.width + i) * 3 + 1]] or " "
  595. end
  596. data[#data + 1] = "\n"
  597. end
  598.  
  599. elseif format == "nft" then
  600. for j = 0, self.height - 1 do
  601. local b, t, pb, pt
  602. for i = 0, self.width - 1 do
  603. pb = self.buffer[(j * self.width + i) * 3 + 1]
  604. pt = self.buffer[(j * self.width + i) * 3 + 2]
  605. if pb ~= b then
  606. data[#data + 1] = "\30"..(_cc_color_to_hex[pb] or " ")
  607. b = pb
  608. end
  609. if pt ~= t then
  610. data[#data + 1] = "\31"..(_cc_color_to_hex[pt] or " ")
  611. t = pt
  612. end
  613. data[#data + 1] = self.buffer[(j * self.width + i) * 3 + 3] or " "
  614. end
  615. data[#data + 1] = "\n"
  616. end
  617.  
  618. elseif format == "rif" then
  619. data[1] = "RIF"
  620. data[2] = string.char(math_floor(self.width / 256), self.width % 256)
  621. data[3] = string.char(math_floor(self.height / 256), self.height % 256)
  622. local byte, upper, c = 0, false
  623. for j = 0, self.width - 1 do
  624. for i = 0, self.height - 1 do
  625. c = self.buffer[(j * self.width + i) * 3 + 1] or 0
  626. if not upper then
  627. byte = c * 16
  628. else
  629. byte = byte + c
  630. data[#data + 1] = string.char(byte)
  631. end
  632. upper = not upper
  633. end
  634. end
  635. if upper then
  636. data[#data + 1] = string.char(byte)
  637. end
  638.  
  639. elseif format == "bmp" then
  640. data[1] = "BM"
  641. data[2] = string.char(0, 0, 0, 0) -- file size, change later
  642. data[3] = string.char(0, 0, 0, 0, 0x36, 0, 0, 0, 0x28, 0, 0, 0)
  643. data[4] = string.char(self.width % 256, math_floor(self.width / 256), 0, 0)
  644. data[5] = string.char(self.height % 256, math_floor(self.height / 256), 0, 0)
  645. data[6] = string.char(1, 0, 0x18, 0, 0, 0, 0, 0)
  646. data[7] = string.char(0, 0, 0, 0) -- pixel data size, change later
  647. data[8] = string.char(0x13, 0x0B, 0, 0, 0x13, 0x0B, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  648.  
  649. local padchars = math.ceil((self.width * 3) / 4) * 4 - self.width * 3
  650. for j = self.height - 1, 0, -1 do
  651. for i = 0, self.width - 1 do
  652. data[#data + 1] = string.char((self.buffer[(j * self.width + i) * 3 + 1] or 0) * 255)
  653. data[#data + 1] = string.char((self.buffer[(j * self.width + i) * 3 + 2] or 0) * 255)
  654. data[#data + 1] = string.char((self.buffer[(j * self.width + i) * 3 + 3] or 0) * 255)
  655. end
  656. data[#data + 1] = ("\0"):rep(padchars)
  657. end
  658. local size = #table_concat(data)
  659. data[2] = string.char(size % 256, math_floor(size / 256) % 256, math_floor(size / 65536), 0)
  660. size = size - 54
  661. data[7] = string.char(size % 256, math_floor(size / 256) % 256, math_floor(size / 65536), 0)
  662.  
  663. else
  664. error("format not supported")
  665. end
  666.  
  667. data = table_concat(data)
  668. if file then
  669. local handle = io.open(file, "wb")
  670. for i = 1, #data do
  671. handle:write(data:byte(i))
  672. end
  673. handle:close()
  674. end
  675. return data
  676. end
  677. function surf:drawLine(x1, y1, x2, y2, b, t, c)
  678. if x1 == x2 then
  679. x1, y1, x2, y2 = x1 + self.ox, y1 + self.oy, x2 + self.ox, y2 + self.oy
  680. if x1 < self.cx or x1 >= self.cx + self.cwidth then return end
  681. if y2 < y1 then
  682. local temp = y1
  683. y1 = y2
  684. y2 = temp
  685. end
  686. if y1 < self.cy then y1 = self.cy end
  687. if y2 >= self.cy + self.cheight then y2 = self.cy + self.cheight - 1 end
  688. if b or self.overwrite then
  689. for j = y1, y2 do
  690. self.buffer[(j * self.width + x1) * 3 + 1] = b
  691. end
  692. end
  693. if t or self.overwrite then
  694. for j = y1, y2 do
  695. self.buffer[(j * self.width + x1) * 3 + 2] = t
  696. end
  697. end
  698. if c or self.overwrite then
  699. for j = y1, y2 do
  700. self.buffer[(j * self.width + x1) * 3 + 3] = c
  701. end
  702. end
  703. elseif y1 == y2 then
  704. x1, y1, x2, y2 = x1 + self.ox, y1 + self.oy, x2 + self.ox, y2 + self.oy
  705. if y1 < self.cy or y1 >= self.cy + self.cheight then return end
  706. if x2 < x1 then
  707. local temp = x1
  708. x1 = x2
  709. x2 = temp
  710. end
  711. if x1 < self.cx then x1 = self.cx end
  712. if x2 >= self.cx + self.cwidth then x2 = self.cx + self.cwidth - 1 end
  713. if b or self.overwrite then
  714. for i = x1, x2 do
  715. self.buffer[(y1 * self.width + i) * 3 + 1] = b
  716. end
  717. end
  718. if t or self.overwrite then
  719. for i = x1, x2 do
  720. self.buffer[(y1 * self.width + i) * 3 + 2] = t
  721. end
  722. end
  723. if c or self.overwrite then
  724. for i = x1, x2 do
  725. self.buffer[(y1 * self.width + i) * 3 + 3] = c
  726. end
  727. end
  728. else
  729. local delta_x = x2 - x1
  730. local ix = delta_x > 0 and 1 or -1
  731. delta_x = 2 * math.abs(delta_x)
  732. local delta_y = y2 - y1
  733. local iy = delta_y > 0 and 1 or -1
  734. delta_y = 2 * math.abs(delta_y)
  735. self:drawPixel(x1, y1, b, t, c)
  736. if delta_x >= delta_y then
  737. local error = delta_y - delta_x / 2
  738. while x1 ~= x2 do
  739. if (error >= 0) and ((error ~= 0) or (ix > 0)) then
  740. error = error - delta_x
  741. y1 = y1 + iy
  742. end
  743. error = error + delta_y
  744. x1 = x1 + ix
  745. self:drawPixel(x1, y1, b, t, c)
  746. end
  747. else
  748. local error = delta_x - delta_y / 2
  749. while y1 ~= y2 do
  750. if (error >= 0) and ((error ~= 0) or (iy > 0)) then
  751. error = error - delta_y
  752. x1 = x1 + ix
  753. end
  754. error = error + delta_x
  755. y1 = y1 + iy
  756. self:drawPixel(x1, y1, b, t, c)
  757. end
  758. end
  759. end
  760. end
  761.  
  762. function surf:drawRect(x, y, width, height, b, t, c)
  763. self:drawLine(x, y, x + width - 1, y, b, t, c)
  764. self:drawLine(x, y, x, y + height - 1, b, t, c)
  765. self:drawLine(x + width - 1, y, x + width - 1, y + height - 1, b, t, c)
  766. self:drawLine(x, y + height - 1, x + width - 1, y + height - 1, b, t, c)
  767. end
  768.  
  769. function surf:fillRect(x, y, width, height, b, t, c)
  770. x, y, width, height = clipRect(x + self.ox, y + self.oy, width, height, self.cx, self.cy, self.cwidth, self.cheight)
  771.  
  772. if b or self.overwrite then
  773. for j = 0, height - 1 do
  774. for i = 0, width - 1 do
  775. self.buffer[((j + y) * self.width + i + x) * 3 + 1] = b
  776. end
  777. end
  778. end
  779. if t or self.overwrite then
  780. for j = 0, height - 1 do
  781. for i = 0, width - 1 do
  782. self.buffer[((j + y) * self.width + i + x) * 3 + 2] = t
  783. end
  784. end
  785. end
  786. if c or self.overwrite then
  787. for j = 0, height - 1 do
  788. for i = 0, width - 1 do
  789. self.buffer[((j + y) * self.width + i + x) * 3 + 3] = c
  790. end
  791. end
  792. end
  793. end
  794.  
  795. function surf:drawTriangle(x1, y1, x2, y2, x3, y3, b, t, c)
  796. self:drawLine(x1, y1, x2, y2, b, t, c)
  797. self:drawLine(x2, y2, x3, y3, b, t, c)
  798. self:drawLine(x3, y3, x1, y1, b, t, c)
  799. end
  800.  
  801. function surf:fillTriangle(x1, y1, x2, y2, x3, y3, b, t, c)
  802. if y1 > y2 then
  803. local tempx, tempy = x1, y1
  804. x1, y1 = x2, y2
  805. x2, y2 = tempx, tempy
  806. end
  807. if y1 > y3 then
  808. local tempx, tempy = x1, y1
  809. x1, y1 = x3, y3
  810. x3, y3 = tempx, tempy
  811. end
  812. if y2 > y3 then
  813. local tempx, tempy = x2, y2
  814. x2, y2 = x3, y3
  815. x3, y3 = tempx, tempy
  816. end
  817. if y1 == y2 and x1 > x2 then
  818. local temp = x1
  819. x1 = x2
  820. x2 = temp
  821. end
  822. if y2 == y3 and x2 > x3 then
  823. local temp = x2
  824. x2 = x3
  825. x3 = temp
  826. end
  827.  
  828. local x4, y4
  829. if x1 <= x2 then
  830. x4 = x1 + (y2 - y1) / (y3 - y1) * (x3 - x1)
  831. y4 = y2
  832. local tempx, tempy = x2, y2
  833. x2, y2 = x4, y4
  834. x4, y4 = tempx, tempy
  835. else
  836. x4 = x1 + (y2 - y1) / (y3 - y1) * (x3 - x1)
  837. y4 = y2
  838. end
  839.  
  840. local finvslope1 = (x2 - x1) / (y2 - y1)
  841. local finvslope2 = (x4 - x1) / (y4 - y1)
  842. local linvslope1 = (x3 - x2) / (y3 - y2)
  843. local linvslope2 = (x3 - x4) / (y3 - y4)
  844.  
  845. local xstart, xend, dxstart, dxend
  846. for y = math.ceil(y1 + 0.5) - 0.5, math.floor(y3 - 0.5) + 0.5, 1 do
  847. if y <= y2 then -- first half
  848. xstart = x1 + finvslope1 * (y - y1)
  849. xend = x1 + finvslope2 * (y - y1)
  850. else -- second half
  851. xstart = x3 - linvslope1 * (y3 - y)
  852. xend = x3 - linvslope2 * (y3 - y)
  853. end
  854.  
  855. dxstart, dxend = math.ceil(xstart - 0.5), math.floor(xend - 0.5)
  856. if dxstart <= dxend then
  857. self:drawLine(dxstart, y - 0.5, dxend, y - 0.5, b, t, c)
  858. end
  859. end
  860. end
  861.  
  862. function surf:drawEllipse(x, y, width, height, b, t, c)
  863. for i = 0, _eprc - 1 do
  864. self:drawLine(math_floor(x + _ecos[i + 1] * (width - 1) + 0.5), math_floor(y + _esin[i + 1] * (height - 1) + 0.5), math_floor(x + _ecos[(i + 1) % _eprc + 1] * (width - 1) + 0.5), math_floor(y + _esin[(i + 1) % _eprc + 1] * (height - 1) + 0.5), b, t, c)
  865. end
  866. end
  867.  
  868. function surf:fillEllipse(x, y, width, height, b, t, c)
  869. x, y = x + self.ox, y + self.oy
  870.  
  871. local sx, sy
  872. for j = 0, height - 1 do
  873. for i = 0, width - 1 do
  874. sx, sy = i + x, j + y
  875. if ((i + 0.5) / width * 2 - 1) ^ 2 + ((j + 0.5) / height * 2 - 1) ^ 2 <= 1 and sx >= self.cx and sx < self.cx + self.cwidth and sy >= self.cy and sy < self.cy + self.cheight then
  876. if b or self.overwrite then
  877. self.buffer[(sy * self.width + sx) * 3 + 1] = b
  878. end
  879. if t or self.overwrite then
  880. self.buffer[(sy * self.width + sx) * 3 + 2] = t
  881. end
  882. if c or self.overwrite then
  883. self.buffer[(sy * self.width + sx) * 3 + 3] = c
  884. end
  885. end
  886. end
  887. end
  888. end
  889.  
  890. function surf:drawArc(x, y, width, height, fromangle, toangle, b, t, c)
  891. if fromangle > toangle then
  892. local temp = fromangle
  893. fromangle = toangle
  894. temp = toangle
  895. end
  896. fromangle = math_floor(fromangle / math.pi / 2 * _eprc + 0.5)
  897. toangle = math_floor(toangle / math.pi / 2 * _eprc + 0.5) - 1
  898.  
  899. for j = fromangle, toangle do
  900. local i = j % _eprc
  901. self:drawLine(math_floor(x + _ecos[i + 1] * (width - 1) + 0.5), math_floor(y + _esin[i + 1] * (height - 1) + 0.5), math_floor(x + _ecos[(i + 1) % _eprc + 1] * (width - 1) + 0.5), math_floor(y + _esin[(i + 1) % _eprc + 1] * (height - 1) + 0.5), b, t, c)
  902. end
  903. end
  904.  
  905. function surf:fillArc(x, y, width, height, fromangle, toangle, b, t, c)
  906. x, y = x + self.ox, y + self.oy
  907.  
  908. if fromangle > toangle then
  909. local temp = fromangle
  910. fromangle = toangle
  911. temp = toangle
  912. end
  913. local diff = toangle - fromangle
  914. fromangle = fromangle % (math.pi * 2)
  915.  
  916. local fx, fy, sx, sy, dir
  917. for j = 0, height - 1 do
  918. for i = 0, width - 1 do
  919. fx, fy = (i + 0.5) / width * 2 - 1, (j + 0.5) / height * 2 - 1
  920. sx, sy = i + x, j + y
  921. dir = math_atan2(-fy, fx) % (math.pi * 2)
  922. if fx ^ 2 + fy ^ 2 <= 1 and ((dir >= fromangle and dir - fromangle <= diff) or (dir <= (fromangle + diff) % (math.pi * 2))) and sx >= self.cx and sx < self.cx + self.cwidth and sy >= self.cy and sy < self.cy + self.cheight then
  923. if b or self.overwrite then
  924. self.buffer[(sy * self.width + sx) * 3 + 1] = b
  925. end
  926. if t or self.overwrite then
  927. self.buffer[(sy * self.width + sx) * 3 + 2] = t
  928. end
  929. if c or self.overwrite then
  930. self.buffer[(sy * self.width + sx) * 3 + 3] = c
  931. end
  932. end
  933. end
  934. end
  935. end
  936. function surf:drawSurface(surf2, x, y, width, height, sx, sy, swidth, sheight)
  937. x, y, width, height, sx, sy, swidth, sheight = x + self.ox, y + self.oy, width or surf2.width, height or surf2.height, sx or 0, sy or 0, swidth or surf2.width, sheight or surf2.height
  938.  
  939. if width == swidth and height == sheight then
  940. local nx, ny
  941. nx, ny, width, height = clipRect(x, y, width, height, self.cx, self.cy, self.cwidth, self.cheight)
  942. swidth, sheight = width, height
  943. if nx > x then
  944. sx = sx + nx - x
  945. x = nx
  946. end
  947. if ny > y then
  948. sy = sy + ny - y
  949. y = ny
  950. end
  951. nx, ny, swidth, sheight = clipRect(sx, sy, swidth, sheight, 0, 0, surf2.width, surf2.height)
  952. width, height = swidth, sheight
  953. if nx > sx then
  954. x = x + nx - sx
  955. sx = nx
  956. end
  957. if ny > sy then
  958. y = y + ny - sy
  959. sy = ny
  960. end
  961.  
  962. local b, t, c
  963. for j = 0, height - 1 do
  964. for i = 0, width - 1 do
  965. b = surf2.buffer[((j + sy) * surf2.width + i + sx) * 3 + 1]
  966. t = surf2.buffer[((j + sy) * surf2.width + i + sx) * 3 + 2]
  967. c = surf2.buffer[((j + sy) * surf2.width + i + sx) * 3 + 3]
  968. if b or self.overwrite then
  969. self.buffer[((j + y) * self.width + i + x) * 3 + 1] = b
  970. end
  971. if t or self.overwrite then
  972. self.buffer[((j + y) * self.width + i + x) * 3 + 2] = t
  973. end
  974. if c or self.overwrite then
  975. self.buffer[((j + y) * self.width + i + x) * 3 + 3] = c
  976. end
  977. end
  978. end
  979. else
  980. local hmirror, vmirror = false, false
  981. if width < 0 then
  982. hmirror = true
  983. x = x + width
  984. end
  985. if height < 0 then
  986. vmirror = true
  987. y = y + height
  988. end
  989. if swidth < 0 then
  990. hmirror = not hmirror
  991. sx = sx + swidth
  992. end
  993. if sheight < 0 then
  994. vmirror = not vmirror
  995. sy = sy + sheight
  996. end
  997. width, height, swidth, sheight = math.abs(width), math.abs(height), math.abs(swidth), math.abs(sheight)
  998.  
  999. local xscale, yscale, px, py, ssx, ssy, b, t, c = swidth / width, sheight / height
  1000. for j = 0, height - 1 do
  1001. for i = 0, width - 1 do
  1002. px, py = math_floor((i + 0.5) * xscale), math_floor((j + 0.5) * yscale)
  1003. if hmirror then
  1004. ssx = x + width - i - 1
  1005. else
  1006. ssx = i + x
  1007. end
  1008. if vmirror then
  1009. ssy = y + height - j - 1
  1010. else
  1011. ssy = j + y
  1012. end
  1013.  
  1014. if ssx >= self.cx and ssx < self.cx + self.cwidth and ssy >= self.cy and ssy < self.cy + self.cheight and px >= 0 and px < surf2.width and py >= 0 and py < surf2.height then
  1015. b = surf2.buffer[(py * surf2.width + px) * 3 + 1]
  1016. t = surf2.buffer[(py * surf2.width + px) * 3 + 2]
  1017. c = surf2.buffer[(py * surf2.width + px) * 3 + 3]
  1018. if b or self.overwrite then
  1019. self.buffer[(ssy * self.width + ssx) * 3 + 1] = b
  1020. end
  1021. if t or self.overwrite then
  1022. self.buffer[(ssy * self.width + ssx) * 3 + 2] = t
  1023. end
  1024. if c or self.overwrite then
  1025. self.buffer[(ssy * self.width + ssx) * 3 + 3] = c
  1026. end
  1027. end
  1028. end
  1029. end
  1030. end
  1031. end
  1032.  
  1033. function surf:drawSurfaceRotated(surf2, x, y, ox, oy, angle)
  1034. local sin, cos, sx, sy, px, py = math.sin(angle), math.cos(angle)
  1035. for j = math.floor(-surf2.height * 0.75), math.ceil(surf2.height * 0.75) do
  1036. for i = math.floor(-surf2.width * 0.75), math.ceil(surf2.width * 0.75) do
  1037. sx, sy, px, py = x + i, y + j, math_floor(cos * (i + 0.5) - sin * (j + 0.5) + ox), math_floor(sin * (i + 0.5) + cos * (j + 0.5) + oy)
  1038. if sx >= self.cx and sx < self.cx + self.cwidth and sy >= self.cy and sy < self.cy + self.cheight and px >= 0 and px < surf2.width and py >= 0 and py < surf2.height then
  1039. b = surf2.buffer[(py * surf2.width + px) * 3 + 1]
  1040. t = surf2.buffer[(py * surf2.width + px) * 3 + 2]
  1041. c = surf2.buffer[(py * surf2.width + px) * 3 + 3]
  1042. if b or self.overwrite then
  1043. self.buffer[(sy * self.width + sx) * 3 + 1] = b
  1044. end
  1045. if t or self.overwrite then
  1046. self.buffer[(sy * self.width + sx) * 3 + 2] = t
  1047. end
  1048. if c or self.overwrite then
  1049. self.buffer[(sy * self.width + sx) * 3 + 3] = c
  1050. end
  1051. end
  1052. end
  1053. end
  1054. end
  1055.  
  1056. function surf:drawSurfacesInterlaced(surfs, x, y, step)
  1057. x, y, step = x + self.ox, y + self.oy, step or 0
  1058. local width, height = surfs[1].width, surfs[1].height
  1059. for i = 2, #surfs do
  1060. if surfs[i].width ~= width or surfs[i].height ~= height then
  1061. error("surfaces should be the same size")
  1062. end
  1063. end
  1064.  
  1065. local sx, sy, swidth, sheight, index, b, t, c = clipRect(x, y, width, height, self.cx, self.cy, self.cwidth, self.cheight)
  1066. for j = sy, sy + sheight - 1 do
  1067. for i = sx, sx + swidth - 1 do
  1068. index = (i + j + step) % #surfs + 1
  1069. b = surfs[index].buffer[((j - sy) * surfs[index].width + i - sx) * 3 + 1]
  1070. t = surfs[index].buffer[((j - sy) * surfs[index].width + i - sx) * 3 + 2]
  1071. c = surfs[index].buffer[((j - sy) * surfs[index].width + i - sx) * 3 + 3]
  1072. if b or self.overwrite then
  1073. self.buffer[(j * self.width + i) * 3 + 1] = b
  1074. end
  1075. if t or self.overwrite then
  1076. self.buffer[(j * self.width + i) * 3 + 2] = t
  1077. end
  1078. if c or self.overwrite then
  1079. self.buffer[(j * self.width + i) * 3 + 3] = c
  1080. end
  1081. end
  1082. end
  1083. end
  1084.  
  1085. function surf:drawSurfaceSmall(surf2, x, y)
  1086. x, y = x + self.ox, y + self.oy
  1087. if surf2.width % 2 ~= 0 or surf2.height % 3 ~= 0 then
  1088. error("surface width must be a multiple of 2 and surface height a multiple of 3")
  1089. end
  1090.  
  1091. local sub, char, c1, c2, c3, c4, c5, c6 = 32768
  1092. for j = 0, surf2.height / 3 - 1 do
  1093. for i = 0, surf2.width / 2 - 1 do
  1094. if i + x >= self.cx and i + x < self.cx + self.cwidth and j + y >= self.cy and j + y < self.cy + self.cheight then
  1095. char, c1, c2, c3, c4, c5, c6 = 0,
  1096. surf2.buffer[((j * 3) * surf2.width + i * 2) * 3 + 1],
  1097. surf2.buffer[((j * 3) * surf2.width + i * 2 + 1) * 3 + 1],
  1098. surf2.buffer[((j * 3 + 1) * surf2.width + i * 2) * 3 + 1],
  1099. surf2.buffer[((j * 3 + 1) * surf2.width + i * 2 + 1) * 3 + 1],
  1100. surf2.buffer[((j * 3 + 2) * surf2.width + i * 2) * 3 + 1],
  1101. surf2.buffer[((j * 3 + 2) * surf2.width + i * 2 + 1) * 3 + 1]
  1102. if c1 ~= c6 then
  1103. sub = c1
  1104. char = 1
  1105. end
  1106. if c2 ~= c6 then
  1107. sub = c2
  1108. char = char + 2
  1109. end
  1110. if c3 ~= c6 then
  1111. sub = c3
  1112. char = char + 4
  1113. end
  1114. if c4 ~= c6 then
  1115. sub = c4
  1116. char = char + 8
  1117. end
  1118. if c5 ~= c6 then
  1119. sub = c5
  1120. char = char + 16
  1121. end
  1122. self.buffer[((j + y) * self.width + i + x) * 3 + 1] = c6
  1123. self.buffer[((j + y) * self.width + i + x) * 3 + 2] = sub
  1124. self.buffer[((j + y) * self.width + i + x) * 3 + 3] = _chars[128 + char]
  1125. end
  1126. end
  1127. end
  1128. end
  1129. function surf:flip(horizontal, vertical)
  1130. local ox, oy, nx, ny, tb, tt, tc
  1131. if horizontal then
  1132. for i = 0, math.ceil(self.cwidth / 2) - 1 do
  1133. for j = 0, self.cheight - 1 do
  1134. ox, oy, nx, ny = i + self.cx, j + self.cy, self.cx + self.cwidth - i - 1, j + self.cy
  1135. tb = self.buffer[(oy * self.width + ox) * 3 + 1]
  1136. tt = self.buffer[(oy * self.width + ox) * 3 + 2]
  1137. tc = self.buffer[(oy * self.width + ox) * 3 + 3]
  1138. self.buffer[(oy * self.width + ox) * 3 + 1] = self.buffer[(ny * self.width + nx) * 3 + 1]
  1139. self.buffer[(oy * self.width + ox) * 3 + 2] = self.buffer[(ny * self.width + nx) * 3 + 2]
  1140. self.buffer[(oy * self.width + ox) * 3 + 3] = self.buffer[(ny * self.width + nx) * 3 + 3]
  1141. self.buffer[(ny * self.width + nx) * 3 + 1] = tb
  1142. self.buffer[(ny * self.width + nx) * 3 + 2] = tt
  1143. self.buffer[(ny * self.width + nx) * 3 + 3] = tc
  1144. end
  1145. end
  1146. end
  1147. if vertical then
  1148. for j = 0, math.ceil(self.cheight / 2) - 1 do
  1149. for i = 0, self.cwidth - 1 do
  1150. ox, oy, nx, ny = i + self.cx, j + self.cy, i + self.cx, self.cy + self.cheight - j - 1
  1151. tb = self.buffer[(oy * self.width + ox) * 3 + 1]
  1152. tt = self.buffer[(oy * self.width + ox) * 3 + 2]
  1153. tc = self.buffer[(oy * self.width + ox) * 3 + 3]
  1154. self.buffer[(oy * self.width + ox) * 3 + 1] = self.buffer[(ny * self.width + nx) * 3 + 1]
  1155. self.buffer[(oy * self.width + ox) * 3 + 2] = self.buffer[(ny * self.width + nx) * 3 + 2]
  1156. self.buffer[(oy * self.width + ox) * 3 + 3] = self.buffer[(ny * self.width + nx) * 3 + 3]
  1157. self.buffer[(ny * self.width + nx) * 3 + 1] = tb
  1158. self.buffer[(ny * self.width + nx) * 3 + 2] = tt
  1159. self.buffer[(ny * self.width + nx) * 3 + 3] = tc
  1160. end
  1161. end
  1162. end
  1163. end
  1164.  
  1165. function surf:shift(x, y, b, t, c)
  1166. local hdir, vdir = x < 0, y < 0
  1167. local xstart, xend = self.cx, self.cx + self.cwidth - 1
  1168. local ystart, yend = self.cy, self.cy + self.cheight - 1
  1169. local nx, ny
  1170. for j = vdir and ystart or yend, vdir and yend or ystart, vdir and 1 or -1 do
  1171. for i = hdir and xstart or xend, hdir and xend or xstart, hdir and 1 or -1 do
  1172. nx, ny = i - x, j - y
  1173. if nx >= 0 and nx < self.width and ny >= 0 and ny < self.height then
  1174. self.buffer[(j * self.width + i) * 3 + 1] = self.buffer[(ny * self.width + nx) * 3 + 1]
  1175. self.buffer[(j * self.width + i) * 3 + 2] = self.buffer[(ny * self.width + nx) * 3 + 2]
  1176. self.buffer[(j * self.width + i) * 3 + 3] = self.buffer[(ny * self.width + nx) * 3 + 3]
  1177. else
  1178. self.buffer[(j * self.width + i) * 3 + 1] = b
  1179. self.buffer[(j * self.width + i) * 3 + 2] = t
  1180. self.buffer[(j * self.width + i) * 3 + 3] = c
  1181. end
  1182. end
  1183. end
  1184. end
  1185.  
  1186. function surf:map(colors)
  1187. local c
  1188. for j = self.cy, self.cy + self.cheight - 1 do
  1189. for i = self.cx, self.cx + self.cwidth - 1 do
  1190. c = colors[self.buffer[(j * self.width + i) * 3 + 1]]
  1191. if c or self.overwrite then
  1192. self.buffer[(j * self.width + i) * 3 + 1] = c
  1193. end
  1194. end
  1195. end
  1196. end
  1197. surface.palette = { }
  1198. surface.palette.cc = {[1]="F0F0F0",[2]="F2B233",[4]="E57FD8",[8]="99B2F2",[16]="DEDE6C",[32]="7FCC19",[64]="F2B2CC",[128]="4C4C4C",[256]="999999",[512]="4C99B2",[1024]="B266E5",[2048]="3366CC",[4096]="7F664C",[8192]="57A64E",[16384]="CC4C4C",[32768]="191919"}
  1199. surface.palette.riko4 = {"181818","1D2B52","7E2553","008651","AB5136","5F564F","7D7F82","FF004C","FFA300","FFF023","00E755","29ADFF","82769C","FF77A9","FECCA9","ECECEC"}
  1200. surface.palette.redirection = {[0]="040404",[1]="FFFFFF"}
  1201.  
  1202. local function setPalette(palette)
  1203. if palette == _palette then return end
  1204. _palette = palette
  1205. _rgbpal, _palr, _palg, _palb = { }, { }, { }, { }
  1206.  
  1207. local indices = { }
  1208. for k, v in pairs(_palette) do
  1209. if type(v) == "string" then
  1210. _palr[k] = tonumber(v:sub(1, 2), 16) / 255
  1211. _palg[k] = tonumber(v:sub(3, 4), 16) / 255
  1212. _palb[k] = tonumber(v:sub(5, 6), 16) / 255
  1213. elseif type(v) == "number" then
  1214. _palr[k] = math.floor(v / 65536) / 255
  1215. _palg[k] = (math.floor(v / 256) % 256) / 255
  1216. _palb[k] = (v % 256) / 255
  1217. end
  1218. indices[#indices + 1] = k
  1219. end
  1220.  
  1221. local pr, pg, pb, dist, d, id
  1222. for i = 0, _steps - 1 do
  1223. for j = 0, _steps - 1 do
  1224. for k = 0, _steps - 1 do
  1225. pr = (i + 0.5) / _steps
  1226. pg = (j + 0.5) / _steps
  1227. pb = (k + 0.5) / _steps
  1228.  
  1229. dist = 1e10
  1230. for l = 1, #indices do
  1231. d = (pr - _palr[indices[l]]) ^ 2 + (pg - _palg[indices[l]]) ^ 2 + (pb - _palb[indices[l]]) ^ 2
  1232. if d < dist then
  1233. dist = d
  1234. id = l
  1235. end
  1236. end
  1237. _rgbpal[i * _steps * _steps + j * _steps + k + 1] = indices[id]
  1238. end
  1239. end
  1240. end
  1241. end
  1242.  
  1243.  
  1244.  
  1245. function surf:toRGB(palette)
  1246. setPalette(palette)
  1247. local c
  1248. for j = 0, self.height - 1 do
  1249. for i = 0, self.width - 1 do
  1250. c = self.buffer[(j * self.width + i) * 3 + 1]
  1251. self.buffer[(j * self.width + i) * 3 + 1] = _palr[c]
  1252. self.buffer[(j * self.width + i) * 3 + 2] = _palg[c]
  1253. self.buffer[(j * self.width + i) * 3 + 3] = _palb[c]
  1254. end
  1255. end
  1256. end
  1257.  
  1258. function surf:toPalette(palette, dither)
  1259. setPalette(palette)
  1260. local scale, r, g, b, nr, ng, nb, c, dr, dg, db = _steps - 1
  1261. for j = 0, self.height - 1 do
  1262. for i = 0, self.width - 1 do
  1263. r = self.buffer[(j * self.width + i) * 3 + 1]
  1264. g = self.buffer[(j * self.width + i) * 3 + 2]
  1265. b = self.buffer[(j * self.width + i) * 3 + 3]
  1266. r = (r > 1) and 1 or r
  1267. r = (r < 0) and 0 or r
  1268. g = (g > 1) and 1 or g
  1269. g = (g < 0) and 0 or g
  1270. b = (b > 1) and 1 or b
  1271. b = (b < 0) and 0 or b
  1272.  
  1273. nr = (r == 1) and scale or math_floor(r * _steps)
  1274. ng = (g == 1) and scale or math_floor(g * _steps)
  1275. nb = (b == 1) and scale or math_floor(b * _steps)
  1276. c = _rgbpal[nr * _steps * _steps + ng * _steps + nb + 1]
  1277. if dither then
  1278. dr = (r - _palr[c]) / 16
  1279. dg = (g - _palg[c]) / 16
  1280. db = (b - _palb[c]) / 16
  1281.  
  1282. if i < self.width - 1 then
  1283. self.buffer[(j * self.width + i + 1) * 3 + 1] = self.buffer[(j * self.width + i + 1) * 3 + 1] + dr * 7
  1284. self.buffer[(j * self.width + i + 1) * 3 + 2] = self.buffer[(j * self.width + i + 1) * 3 + 2] + dg * 7
  1285. self.buffer[(j * self.width + i + 1) * 3 + 3] = self.buffer[(j * self.width + i + 1) * 3 + 3] + db * 7
  1286. end
  1287. if j < self.height - 1 then
  1288. if i > 0 then
  1289. self.buffer[((j + 1) * self.width + i - 1) * 3 + 1] = self.buffer[((j + 1) * self.width + i - 1) * 3 + 1] + dr * 3
  1290. self.buffer[((j + 1) * self.width + i - 1) * 3 + 2] = self.buffer[((j + 1) * self.width + i - 1) * 3 + 2] + dg * 3
  1291. self.buffer[((j + 1) * self.width + i - 1) * 3 + 3] = self.buffer[((j + 1) * self.width + i - 1) * 3 + 3] + db * 3
  1292. end
  1293. self.buffer[((j + 1) * self.width + i) * 3 + 1] = self.buffer[((j + 1) * self.width + i) * 3 + 1] + dr * 5
  1294. self.buffer[((j + 1) * self.width + i) * 3 + 2] = self.buffer[((j + 1) * self.width + i) * 3 + 2] + dg * 5
  1295. self.buffer[((j + 1) * self.width + i) * 3 + 3] = self.buffer[((j + 1) * self.width + i) * 3 + 3] + db * 5
  1296. if i < self.width - 1 then
  1297. self.buffer[((j + 1) * self.width + i + 1) * 3 + 1] = self.buffer[((j + 1) * self.width + i + 1) * 3 + 1] + dr * 1
  1298. self.buffer[((j + 1) * self.width + i + 1) * 3 + 2] = self.buffer[((j + 1) * self.width + i + 1) * 3 + 2] + dg * 1
  1299. self.buffer[((j + 1) * self.width + i + 1) * 3 + 3] = self.buffer[((j + 1) * self.width + i + 1) * 3 + 3] + db * 1
  1300. end
  1301. end
  1302. end
  1303. self.buffer[(j * self.width + i) * 3 + 1] = c
  1304. self.buffer[(j * self.width + i) * 3 + 2] = nil
  1305. self.buffer[(j * self.width + i) * 3 + 3] = nil
  1306. end
  1307. end
  1308. end
  1309. function surface.loadFont(surf)
  1310. local font = {width = surf.width, height = surf.height - 1}
  1311. font.buffer = { }
  1312. font.indices = {0}
  1313. font.widths = { }
  1314.  
  1315. local startc, hitc, curc = surf.buffer[((surf.height - 1) * surf.width) * 3 + 1]
  1316. for i = 0, surf.width - 1 do
  1317. curc = surf.buffer[((surf.height - 1) * surf.width + i) * 3 + 1]
  1318. if curc ~= startc then
  1319. hitc = curc
  1320. break
  1321. end
  1322. end
  1323.  
  1324. for j = 0, surf.height - 2 do
  1325. for i = 0, surf.width - 1 do
  1326. font.buffer[j * font.width + i + 1] = surf.buffer[(j * surf.width + i) * 3 + 1] == hitc
  1327. end
  1328. end
  1329.  
  1330. local curchar = 1
  1331. for i = 0, surf.width - 1 do
  1332. if surf.buffer[((surf.height - 1) * surf.width + i) * 3 + 1] == hitc then
  1333. font.widths[curchar] = i - font.indices[curchar]
  1334. curchar = curchar + 1
  1335. font.indices[curchar] = i + 1
  1336. end
  1337. end
  1338. font.widths[curchar] = font.width - font.indices[curchar]
  1339.  
  1340. return font
  1341. end
  1342.  
  1343. function surface.getTextSize(str, font)
  1344. local cx, cy, maxx = 0, 0, 0
  1345. local ox, char = cx
  1346.  
  1347. for i = 1, #str do
  1348. char = str:byte(i) - 31
  1349.  
  1350. if char + 31 == 10 then -- newline
  1351. cx = ox
  1352. cy = cy + font.height + 1
  1353. elseif font.indices[char] then
  1354. cx = cx + font.widths[char] + 1
  1355. else
  1356. cx = cx + font.widths[1]
  1357. end
  1358. if cx > maxx then
  1359. maxx = cx
  1360. end
  1361. end
  1362.  
  1363. return maxx - 1, cy + font.height
  1364. end
  1365.  
  1366. function surf:drawText(str, font, x, y, b, t, c)
  1367. local cx, cy = x + self.ox, y + self.oy
  1368. local ox, char, idx = cx
  1369.  
  1370. for i = 1, #str do
  1371. char = str:byte(i) - 31
  1372.  
  1373. if char + 31 == 10 then -- newline
  1374. cx = ox
  1375. cy = cy + font.height + 1
  1376. elseif font.indices[char] then
  1377. for i = 0, font.widths[char] - 1 do
  1378. for j = 0, font.height - 1 do
  1379. x, y = cx + i, cy + j
  1380. if font.buffer[j * font.width + i + font.indices[char] + 1] then
  1381. if x >= self.cx and x < self.cx + self.cwidth and y >= self.cy and y < self.cy + self.cheight then
  1382. idx = (y * self.width + x) * 3
  1383. if b or self.overwrite then
  1384. self.buffer[idx + 1] = b
  1385. end
  1386. if t or self.overwrite then
  1387. self.buffer[idx + 2] = t
  1388. end
  1389. if c or self.overwrite then
  1390. self.buffer[idx + 3] = c
  1391. end
  1392. end
  1393. end
  1394. end
  1395. end
  1396. cx = cx + font.widths[char] + 1
  1397. else
  1398. cx = cx + font.widths[1]
  1399. end
  1400. end
  1401. end
  1402. local smap = { }
  1403. surface.smap = smap
  1404.  
  1405. function surface.loadSpriteMap(surf, spwidth, spheight, sprites)
  1406. if surf.width % spwidth ~= 0 or surf.height % spheight ~= 0 then
  1407. error("sprite width/height does not match smap width/height")
  1408. end
  1409.  
  1410. local smap = setmetatable({ }, {__index = surface.smap})
  1411. smap.surf = surf
  1412. smap.spwidth = spwidth
  1413. smap.spheight = spheight
  1414. smap.sprites = sprites or ((surf.width / spwidth) * (surf.height / spheight))
  1415. smap.perline = surf.width / spwidth
  1416.  
  1417. return smap
  1418. end
  1419.  
  1420. function smap:pos(index, scale)
  1421. if index < 0 or index >= self.sprites then
  1422. error("sprite index out of bounds")
  1423. end
  1424.  
  1425. return (index % self.perline) * self.spwidth, math.floor(index / self.perline) * self.spheight
  1426. end
  1427.  
  1428. function smap:sprite(index, x, y, width, height)
  1429. local sx, sy = self:pos(index)
  1430. return self.surf, x, y, width or self.spwidth, height or self.spheight, sx, sy, self.spwidth, self.spheight
  1431. end
  1432. end return surface
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement