Various fixes

Unicode:
Replace \0 with \xC0\x80
Limit max codepoint to 0xFFFF (Java chars are wonderful)
Fix wtrunc and math.huge
Fix wtrunc with a pos of 0 returning the entire string

GPU (not screen):
Simplify rdepthTbl
Add depth names table
return the old depth when changing depth
limit the resolution change correctly
allow gpu.get to work with a little over the max dimensions

Screen:
Don't modify characters if it's a wide character at the very edge of the
screen
Have getColor set the palette index instead
Return true in cec.fill
Floor the resolution when changing
This commit is contained in:
gamax92 2015-06-24 17:52:07 -06:00
parent 618504f9cd
commit 95405445d9
3 changed files with 68 additions and 27 deletions

View File

@ -3,12 +3,20 @@ local env = ...
local utf8 = require("utf8") local utf8 = require("utf8")
env.unicode = { env.unicode = {
char = utf8.char,
len = utf8.len, len = utf8.len,
reverse = utf8.reverse, reverse = utf8.reverse,
sub = utf8.sub, sub = utf8.sub,
} }
function env.unicode.char(...)
cprint("unicode.char", ...)
local args = table.pack(...)
for i = 1,args.n do
checkArg(i,args[i],"number")
args[i] = args[i]%0x10000
end
return utf8.char(table.unpack(args)):gsub("%z","\xC0\x80") .. ""
end
function env.unicode.lower(str) function env.unicode.lower(str)
cprint("unicode.lower", str) cprint("unicode.lower", str)
if type(str) == "number" then str = tostring(str) end if type(str) == "number" then str = tostring(str) end
@ -52,6 +60,9 @@ function env.unicode.wtrunc(str, count)
cprint("unicode.wtrunc", str, count) cprint("unicode.wtrunc", str, count)
checkArg(1,str,"string") checkArg(1,str,"string")
checkArg(2,count,"number") checkArg(2,count,"number")
if count == math.huge then
count = 0
end
local width = 0 local width = 0
local pos = 0 local pos = 0
local len = utf8.len(str) local len = utf8.len(str)
@ -62,5 +73,5 @@ function env.unicode.wtrunc(str, count)
end end
width = width + getCharWidth(utf8.byte(str,pos,pos)) width = width + getCharWidth(utf8.byte(str,pos,pos))
end end
return utf8.sub(str, 1, pos-1) return utf8.sub(str, 1, math.max(pos-1,0))
end end

View File

@ -7,7 +7,8 @@ local lua_utf8 = require("utf8")
local bindaddress local bindaddress
local depthTbl = {1,4,8} local depthTbl = {1,4,8}
local rdepthTbl = {1,nil,nil,2,nil,nil,nil,3} local rdepthTbl = {1,[4]=2,[8]=3}
local depthNames = {"OneBit","FourBit","EightBit"}
-- gpu component -- gpu component
local obj = {} local obj = {}
@ -82,7 +83,9 @@ function obj.setDepth(depth) -- Set the color depth. Returns the previous value.
if rdepthTbl[depth] == nil or rdepthTbl[depth] > math.max(scrmax, maxtier) then if rdepthTbl[depth] == nil or rdepthTbl[depth] > math.max(scrmax, maxtier) then
error("unsupported depth",3) error("unsupported depth",3)
end end
return component.cecinvoke(bindaddress, "setDepth", rdepthTbl[depth]) local old = depthNames[component.cecinvoke(bindaddress, "getDepth")]
component.cecinvoke(bindaddress, "setDepth", rdepthTbl[depth])
return old
end end
function obj.maxDepth() -- Get the maximum supported color depth. function obj.maxDepth() -- Get the maximum supported color depth.
cprint("gpu.maxDepth") cprint("gpu.maxDepth")
@ -121,6 +124,11 @@ function obj.setResolution(width, height) -- Set the screen resolution. Returns
if bindaddress == nil then if bindaddress == nil then
return nil, "no screen" return nil, "no screen"
end end
local smw,smh = component.cecinvoke(bindaddress, "maxResolution")
smw,smh = math.min(smw,maxwidth),math.min(smh,maxheight)
if width <= 0 or width >= smw + 1 or height <= 0 or height >= smh + 1 then
error("unsupported resolution",3)
end
return component.cecinvoke(bindaddress, "setResolution", width, height) return component.cecinvoke(bindaddress, "setResolution", width, height)
end end
function obj.maxResolution() -- Get the maximum screen resolution. function obj.maxResolution() -- Get the maximum screen resolution.
@ -170,7 +178,7 @@ function obj.get(x, y) -- Get the value displayed on the screen at the specified
return nil, "no screen" return nil, "no screen"
end end
local w,h = component.cecinvoke(bindaddress, "getResolution") local w,h = component.cecinvoke(bindaddress, "getResolution")
if x < 1 or x > w or y < 1 or y > h then if x < 1 or x >= w+1 or y < 1 or y >= h+1 then
error("index out of bounds",3) error("index out of bounds",3)
end end
return component.cecinvoke(bindaddress, "get", x, y) return component.cecinvoke(bindaddress, "get", x, y)

View File

@ -172,20 +172,22 @@ end
local function setPos(x,y,c,fg,bg) local function setPos(x,y,c,fg,bg)
local renderchange = screen.txt[y][x] ~= utf8.char(c) or screen.bg[y][x] ~= scrbgc or (screen.txt[y][x] ~= " " and screen.fg[y][x] ~= scrfgc) local renderchange = screen.txt[y][x] ~= utf8.char(c) or screen.bg[y][x] ~= scrbgc or (screen.txt[y][x] ~= " " and screen.fg[y][x] ~= scrfgc)
local charWidth = getCharWidth(c) local charWidth = getCharWidth(c)
local renderafter = getCharWidth(utf8.byte(screen.txt[y][x])) > 1 and charWidth == 1 and x < width if charWidth == 1 or x < width then
if x > 1 and getCharWidth(utf8.byte(screen.txt[y][x-1])) > 1 then local renderafter = getCharWidth(utf8.byte(screen.txt[y][x])) > 1 and charWidth == 1 and x < width
renderchange = false if x > 1 and getCharWidth(utf8.byte(screen.txt[y][x-1])) > 1 then
else renderchange = false
screenSet(x,y,c) else
end screenSet(x,y,c)
if renderchange then end
renderChar(c,(x-1)*8,(y-1)*16,fg,bg) if renderchange then
if charWidth > 1 and x < width then renderChar(c,(x-1)*8,(y-1)*16,fg,bg)
screenSet(x+1,y,32) if charWidth > 1 then
screenSet(x+1,y,32)
end
end
if renderafter then
renderChar(32,x*8,(y-1)*16,screen.fg[y][x+1],screen.bg[y][x+1])
end end
end
if renderafter then
renderChar(32,x*8,(y-1)*16,screen.fg[y][x+1],screen.bg[y][x+1])
end end
end end
@ -214,7 +216,12 @@ local function searchPalette(value)
return index, score return index, score
end end
local function getColor(value) local function getColor(value, sel)
if sel then
scrfgp = nil
else
scrbgp = nil
end
if tier == 3 then if tier == 3 then
local pi,ps = searchPalette(value) local pi,ps = searchPalette(value)
local r,g,b = extract(value) local r,g,b = extract(value)
@ -226,10 +233,21 @@ local function getColor(value)
if defs < ps then if defs < ps then
return defc return defc
else else
if sel then
scrfgp = pi
else
scrbgp = pi
end
return palcol[pi] return palcol[pi]
end end
elseif tier == 2 then elseif tier == 2 then
return palcol[searchPalette(value)] local pi = searchPalette(value)
if sel then
scrfgp = pi
else
scrbgp = pi
end
return palcol[pi]
else else
if value > 0 then if value > 0 then
return 0xFFFFFF -- TODO: Configuration color return 0xFFFFFF -- TODO: Configuration color
@ -303,8 +321,8 @@ function cec.setForeground(value, palette) -- Sets the foreground color to the s
cprint("(cec) screen.setForeground", value, palette) cprint("(cec) screen.setForeground", value, palette)
local oldc, oldp = scrrfc, scrfgp local oldc, oldp = scrrfc, scrfgp
scrrfc = palette and palcol[value] or value scrrfc = palette and palcol[value] or value
scrfgc = palette and scrrfc or getColor(scrrfc)
scrfgp = palette and value scrfgp = palette and value
scrfgc = palette and scrrfc or getColor(scrrfc,true)
return oldc, oldp return oldc, oldp
end end
function cec.getBackground() -- Get the current background color and whether it's from the palette or not. function cec.getBackground() -- Get the current background color and whether it's from the palette or not.
@ -315,8 +333,8 @@ function cec.setBackground(value, palette) -- Sets the background color to the s
cprint("(cec) screen.setBackground", value, palette) cprint("(cec) screen.setBackground", value, palette)
local oldc, oldp = scrrbc, scrbgp local oldc, oldp = scrrbc, scrbgp
scrrbc = palette and palcol[value] or value scrrbc = palette and palcol[value] or value
scrbgc = palette and scrrbc or getColor(scrrbc)
scrbgp = palette and value scrbgp = palette and value
scrbgc = palette and scrrbc or getColor(scrrbc,false)
return oldc, oldp return oldc, oldp
end end
function cec.getDepth() -- Returns the currently set color depth. function cec.getDepth() -- Returns the currently set color depth.
@ -329,8 +347,8 @@ function cec.setDepth(depth) -- Set the color depth. Returns the previous value.
if tier > 1 then if tier > 1 then
loadPalette() loadPalette()
end end
scrfgc = getColor(scrrfc) scrfgc = getColor(scrrfc,true)
scrfbc = getColor(scrrbc) scrfbc = getColor(scrrbc,false)
-- TODO: Lowering the depth recolors the entire screen -- TODO: Lowering the depth recolors the entire screen
end end
function cec.maxDepth() -- Get the maximum supported color depth. function cec.maxDepth() -- Get the maximum supported color depth.
@ -355,6 +373,7 @@ function cec.fill(x1, y1, w, h, char) -- Fills a portion of the screen at the sp
setPos(x,y,code,scrfgc,scrbgc) setPos(x,y,code,scrfgc,scrbgc)
end end
end end
return true
end end
function cec.getResolution() -- Get the current screen resolution. function cec.getResolution() -- Get the current screen resolution.
cprint("(cec) screen.getResolution") cprint("(cec) screen.getResolution")
@ -362,8 +381,9 @@ function cec.getResolution() -- Get the current screen resolution.
end end
function cec.setResolution(newwidth, newheight) -- Set the screen resolution. Returns true if the resolution changed. function cec.setResolution(newwidth, newheight) -- Set the screen resolution. Returns true if the resolution changed.
cprint("(cec) screen.setResolution", newwidth, newheight) cprint("(cec) screen.setResolution", newwidth, newheight)
newwidth,newheight = math.floor(newwidth),math.floor(newheight)
local oldwidth, oldheight = width, height local oldwidth, oldheight = width, height
width, height = math.min(newwidth, maxwidth), math.min(newheight, maxheight) width, height = newwidth, newheight
return oldwidth ~= width or oldheight ~= height return oldwidth ~= width or oldheight ~= height
end end
function cec.maxResolution() -- Get the maximum screen resolution. function cec.maxResolution() -- Get the maximum screen resolution.
@ -444,8 +464,10 @@ function cec.copy(x1, y1, w, h, tx, ty) -- Copies a portion of the screen from t
copy.bgp[y-y1][x-x1] = screen.bgp[y][x] copy.bgp[y-y1][x-x1] = screen.bgp[y][x]
end end
end end
for y = math.max(math.min(y1+ty, height), 1), math.max(math.min(y2+ty, height), 1) do local my1,my2 = math.max(math.min(y1+ty, height), 1), math.max(math.min(y2+ty, height), 1)
for x = math.max(math.min(x1+tx, width), 1), math.max(math.min(x2+tx, width), 1) do local mx1,mx2 = math.max(math.min(x1+tx, width), 1), math.max(math.min(x2+tx, width), 1)
for y = my1,my2 do
for x = mx1,mx2 do
screen.txt[y][x] = copy.txt[y-y1-ty][x-x1-tx] screen.txt[y][x] = copy.txt[y-y1-ty][x-x1-tx]
screen.fg[y][x] = copy.fg[y-y1-ty][x-x1-tx] screen.fg[y][x] = copy.fg[y-y1-ty][x-x1-tx]
screen.bg[y][x] = copy.bg[y-y1-ty][x-x1-tx] screen.bg[y][x] = copy.bg[y-y1-ty][x-x1-tx]