添加strToBimg,并让其他显示基于strToBimg
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
-- UTF-8 Display Library for ComputerCraft
|
-- UTF-8 Display Library for ComputerCraft (完整修正版)
|
||||||
-- 文件名: utf8display.lua
|
-- 文件名: utf8display.lua
|
||||||
|
|
||||||
local utf8display = {}
|
local utf8display = {}
|
||||||
@@ -101,7 +101,9 @@ end
|
|||||||
|
|
||||||
function fontManager.getFontHeight()
|
function fontManager.getFontHeight()
|
||||||
local font = fontManager.getFont()
|
local font = fontManager.getFont()
|
||||||
if font and font[32] then
|
if font and font[72] then -- 'H' (ASCII 72) 表示最大高度
|
||||||
|
return #font[72]
|
||||||
|
elseif font and font[32] then
|
||||||
return #font[32]
|
return #font[32]
|
||||||
end
|
end
|
||||||
return state.fontHeight
|
return state.fontHeight
|
||||||
@@ -110,48 +112,6 @@ end
|
|||||||
-- 渲染引擎模块
|
-- 渲染引擎模块
|
||||||
local renderer = {}
|
local renderer = {}
|
||||||
|
|
||||||
function renderer.displayChar(charMap, x, y, textColor, backgroundColor)
|
|
||||||
if not charMap or #charMap == 0 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 保存当前终端颜色和光标位置
|
|
||||||
local originalTextColor = term.getTextColor()
|
|
||||||
local originalBackgroundColor = term.getBackgroundColor()
|
|
||||||
local originalCursorX, originalCursorY = term.getCursorPos()
|
|
||||||
|
|
||||||
-- 如果没有提供自定义颜色,则使用当前终端颜色
|
|
||||||
local useTextColor = textColor or originalTextColor
|
|
||||||
local useBackgroundColor = backgroundColor or originalBackgroundColor
|
|
||||||
|
|
||||||
-- 渲染字符(仅在可视区域内)
|
|
||||||
local width, height = term.getSize()
|
|
||||||
for row = 1, #charMap do
|
|
||||||
local drawY = y + row - 1
|
|
||||||
if drawY > height then break end -- 超出底部,不再绘制
|
|
||||||
term.setCursorPos(x, drawY)
|
|
||||||
local line = charMap[row]
|
|
||||||
|
|
||||||
for col = 1, #line do
|
|
||||||
local byte = string.byte(line, col)
|
|
||||||
if byte < 128 then
|
|
||||||
term.setTextColor(useBackgroundColor)
|
|
||||||
term.setBackgroundColor(useTextColor)
|
|
||||||
term.write(string.char(byte + 128))
|
|
||||||
else
|
|
||||||
term.setTextColor(useTextColor)
|
|
||||||
term.setBackgroundColor(useBackgroundColor)
|
|
||||||
term.write(string.char(byte))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 恢复原始终端颜色和光标位置
|
|
||||||
term.setTextColor(originalTextColor)
|
|
||||||
term.setBackgroundColor(originalBackgroundColor)
|
|
||||||
term.setCursorPos(originalCursorX, originalCursorY)
|
|
||||||
end
|
|
||||||
|
|
||||||
function renderer.utf8Decode(str)
|
function renderer.utf8Decode(str)
|
||||||
local i = 1
|
local i = 1
|
||||||
return function()
|
return function()
|
||||||
@@ -210,254 +170,381 @@ function utf8display.loadFont()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 主动初始化字体函数
|
-- 将字符串转换为bimg格式(完整修正版,支持逐字颜色)
|
||||||
function utf8display.initFont()
|
function utf8display.strToBimg(str, textColor, backgroundColor, width)
|
||||||
return utf8display.loadFont()
|
str = tostring(str)
|
||||||
|
local font = fontManager.getFont()
|
||||||
|
local fontHeight = fontManager.getFontHeight()
|
||||||
|
|
||||||
|
-- 判断颜色参数类型
|
||||||
|
local textIsString = type(textColor) == "string"
|
||||||
|
local bgIsString = type(backgroundColor) == "string"
|
||||||
|
|
||||||
|
-- 获取默认颜色
|
||||||
|
local defaultTextColor = term.getTextColor()
|
||||||
|
local defaultBgColor = term.getBackgroundColor()
|
||||||
|
|
||||||
|
-- 处理统一颜色(数字)或逐字颜色(字符串)
|
||||||
|
local uniformTextBlit, uniformBgBlit
|
||||||
|
if not textIsString then
|
||||||
|
uniformTextBlit = colors.toBlit(type(textColor) == "number" and textColor or defaultTextColor)
|
||||||
|
end
|
||||||
|
if not bgIsString then
|
||||||
|
uniformBgBlit = colors.toBlit(type(backgroundColor) == "number" and backgroundColor or defaultBgColor)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 初始化bimg结构
|
||||||
|
local bimg = {}
|
||||||
|
|
||||||
|
-- 处理换行符
|
||||||
|
local lines = {}
|
||||||
|
local start = 1
|
||||||
|
while start <= #str do
|
||||||
|
local nl_pos = str:find("\n", start, true)
|
||||||
|
if nl_pos then
|
||||||
|
local line = str:sub(start, nl_pos - 1)
|
||||||
|
table.insert(lines, line)
|
||||||
|
start = nl_pos + 1
|
||||||
|
else
|
||||||
|
-- 到末尾了
|
||||||
|
local line = str:sub(start)
|
||||||
|
table.insert(lines, line)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, lineStr in ipairs(lines) do
|
||||||
|
-- 收集该行所有字符信息
|
||||||
|
local allChars = {}
|
||||||
|
for code in renderer.utf8Decode(lineStr) do
|
||||||
|
local charMap = font[code] or font[32]
|
||||||
|
local charWidth = #charMap[1]
|
||||||
|
table.insert(allChars, {code = code, map = charMap, width = charWidth})
|
||||||
|
end
|
||||||
|
|
||||||
|
if width then
|
||||||
|
-- 有宽度限制,需要处理自动换行
|
||||||
|
local segments = {}
|
||||||
|
local currentSegment = {}
|
||||||
|
local currentLineWidth = 0
|
||||||
|
|
||||||
|
-- 遍历字符
|
||||||
|
for i, charInfo in ipairs(allChars) do
|
||||||
|
-- 检查是否需要换行
|
||||||
|
if currentLineWidth + charInfo.width > width then
|
||||||
|
-- 将当前段添加到segments
|
||||||
|
if #currentSegment > 0 then
|
||||||
|
table.insert(segments, currentSegment)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 开始新段
|
||||||
|
currentSegment = {}
|
||||||
|
currentLineWidth = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 添加字符到当前段
|
||||||
|
table.insert(currentSegment, charInfo)
|
||||||
|
currentLineWidth = currentLineWidth + charInfo.width
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 添加最后一段(如果存在)
|
||||||
|
if #currentSegment > 0 then
|
||||||
|
table.insert(segments, currentSegment)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 渲染每个段(每个段高度 = fontHeight)
|
||||||
|
for _, segment in ipairs(segments) do
|
||||||
|
-- 为该段构建每行的 text/colors/bg
|
||||||
|
for row = 1, fontHeight do
|
||||||
|
local lineText = ""
|
||||||
|
local lineTextColors = ""
|
||||||
|
local lineBgColors = ""
|
||||||
|
|
||||||
|
-- 为每个字符计算颜色(如果使用字符串颜色)
|
||||||
|
local charIndexInLine = 1
|
||||||
|
for _, char in ipairs(segment) do
|
||||||
|
local fgBlit, bgBlit
|
||||||
|
|
||||||
|
if textIsString then
|
||||||
|
local colorChar = string.sub(textColor, charIndexInLine, charIndexInLine)
|
||||||
|
fgBlit = colorChar ~= "" and colorChar or "f" -- 默认白色
|
||||||
|
else
|
||||||
|
fgBlit = uniformTextBlit
|
||||||
|
end
|
||||||
|
|
||||||
|
if bgIsString then
|
||||||
|
local colorChar = string.sub(backgroundColor, charIndexInLine, charIndexInLine)
|
||||||
|
bgBlit = colorChar ~= "" and colorChar or "0" -- 默认黑色
|
||||||
|
else
|
||||||
|
bgBlit = uniformBgBlit
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 处理该字符的当前行
|
||||||
|
if row <= #char.map then
|
||||||
|
local rowStr = char.map[row]
|
||||||
|
for col = 1, #rowStr do
|
||||||
|
local byte = string.byte(rowStr, col)
|
||||||
|
local displayByte
|
||||||
|
if byte < 128 then
|
||||||
|
-- 颜色反转
|
||||||
|
displayByte = byte + 128
|
||||||
|
lineText = lineText .. string.char(displayByte)
|
||||||
|
lineTextColors = lineTextColors .. bgBlit -- 原背景色变前景
|
||||||
|
lineBgColors = lineBgColors .. fgBlit -- 原前景色变背景
|
||||||
|
else
|
||||||
|
-- 正常
|
||||||
|
displayByte = byte
|
||||||
|
lineText = lineText .. string.char(displayByte)
|
||||||
|
lineTextColors = lineTextColors .. fgBlit
|
||||||
|
lineBgColors = lineBgColors .. bgBlit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
charIndexInLine = charIndexInLine + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(bimg, {lineText, lineTextColors, lineBgColors})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- 无宽度限制,整行处理
|
||||||
|
if #allChars > 0 then
|
||||||
|
-- 为该行构建每行的 text/colors/bg
|
||||||
|
for row = 1, fontHeight do
|
||||||
|
local lineText = ""
|
||||||
|
local lineTextColors = ""
|
||||||
|
local lineBgColors = ""
|
||||||
|
|
||||||
|
-- 为每个字符计算颜色(如果使用字符串颜色)
|
||||||
|
local charIndexInLine = 1
|
||||||
|
for _, char in ipairs(allChars) do
|
||||||
|
local fgBlit, bgBlit
|
||||||
|
|
||||||
|
if textIsString then
|
||||||
|
local colorChar = string.sub(textColor, charIndexInLine, charIndexInLine)
|
||||||
|
fgBlit = colorChar ~= "" and colorChar or "f" -- 默认白色
|
||||||
|
else
|
||||||
|
fgBlit = uniformTextBlit
|
||||||
|
end
|
||||||
|
|
||||||
|
if bgIsString then
|
||||||
|
local colorChar = string.sub(backgroundColor, charIndexInLine, charIndexInLine)
|
||||||
|
bgBlit = colorChar ~= "" and colorChar or "0" -- 默认黑色
|
||||||
|
else
|
||||||
|
bgBlit = uniformBgBlit
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 处理该字符的当前行
|
||||||
|
if row <= #char.map then
|
||||||
|
local rowStr = char.map[row]
|
||||||
|
for col = 1, #rowStr do
|
||||||
|
local byte = string.byte(rowStr, col)
|
||||||
|
local displayByte
|
||||||
|
if byte < 128 then
|
||||||
|
-- 颜色反转
|
||||||
|
displayByte = byte + 128
|
||||||
|
lineText = lineText .. string.char(displayByte)
|
||||||
|
lineTextColors = lineTextColors .. bgBlit -- 原背景色变前景
|
||||||
|
lineBgColors = lineBgColors .. fgBlit -- 原前景色变背景
|
||||||
|
else
|
||||||
|
-- 正常
|
||||||
|
displayByte = byte
|
||||||
|
lineText = lineText .. string.char(displayByte)
|
||||||
|
lineTextColors = lineTextColors .. fgBlit
|
||||||
|
lineBgColors = lineBgColors .. bgBlit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
charIndexInLine = charIndexInLine + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(bimg, {lineText, lineTextColors, lineBgColors})
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- 空行也需要保留
|
||||||
|
table.insert(bimg, {"", "", ""})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 如果没有内容,创建一个空行
|
||||||
|
if #bimg == 0 then
|
||||||
|
table.insert(bimg, {"", "", ""})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 将所有行包装在第一帧中
|
||||||
|
return {{unpack(bimg)}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function clampCursorPos(x, y, width, height)
|
local function clampCursorPos(x, y, width, height)
|
||||||
return math.min(math.max(x, 1), width), math.min(math.max(y, 1), height)
|
return math.min(math.max(x, 1), width), math.min(math.max(y, 1), height)
|
||||||
end
|
end
|
||||||
|
|
||||||
function utf8display.write(raw_str)
|
function utf8display.write(raw_str, textColor, backgroundColor)
|
||||||
str = tostring(raw_str)
|
local str = tostring(raw_str)
|
||||||
-- 将换行符替换为空格
|
str = string.gsub(str, "\n", " ") -- 替换换行为空格
|
||||||
str = string.gsub(str, "\n", " ")
|
|
||||||
|
|
||||||
local font = fontManager.getFont()
|
|
||||||
local fontHeight = fontManager.getFontHeight()
|
|
||||||
local textColor = term.getTextColor()
|
|
||||||
local backgroundColor = term.getBackgroundColor()
|
|
||||||
|
|
||||||
local startX, startY = term.getCursorPos()
|
local startX, startY = term.getCursorPos()
|
||||||
local width, height = term.getSize()
|
local termWidth, termHeight = term.getSize()
|
||||||
local cursorX, cursorY = startX, startY
|
|
||||||
local charCount = 0
|
|
||||||
local contentFitsHorizontally = true
|
|
||||||
local contentFitsVertically = true
|
|
||||||
|
|
||||||
for code in renderer.utf8Decode(str) do
|
-- 获取 bimg(无宽度限制,所以不会自动换行)
|
||||||
if code == 10 then -- 换行符 (理论上不会再有,因为我们已经替换了)
|
local bimg = utf8display.strToBimg(str, textColor, backgroundColor)
|
||||||
cursorX = 1
|
local frame = bimg[1]
|
||||||
cursorY = cursorY + fontHeight
|
|
||||||
else
|
|
||||||
local charMap = font[code] or font[32]
|
|
||||||
local charWidth = #charMap[1]
|
|
||||||
|
|
||||||
-- 不自动换行:即使超出横向宽度也继续写(但不渲染超出部分)
|
if #frame == 0 then
|
||||||
if cursorX + charWidth - 1 > width then
|
-- 空内容,直接返回
|
||||||
contentFitsHorizontally = false
|
return true, { charCount = 0, overflowX = false, overflowY = false }
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 判断是否还能在竖直方向绘制(至少第一行能画)
|
local firstLineWidth = #frame[1][1]
|
||||||
if cursorY <= height then
|
local totalHeight = #frame
|
||||||
renderer.displayChar(charMap, cursorX, cursorY, textColor, backgroundColor)
|
|
||||||
charCount = charCount + 1
|
|
||||||
else
|
|
||||||
contentFitsVertically = false
|
|
||||||
-- 不 break,继续推进光标逻辑(用于正确设置最终光标位置)
|
|
||||||
end
|
|
||||||
|
|
||||||
cursorX = cursorX + charWidth
|
-- 渲染每一行
|
||||||
|
for i, row in ipairs(frame) do
|
||||||
|
local drawY = startY + i - 1
|
||||||
|
if drawY > termHeight then
|
||||||
|
-- 超出底部,跳过绘制
|
||||||
|
break
|
||||||
end
|
end
|
||||||
|
term.setCursorPos(startX, drawY)
|
||||||
|
term.blit(row[1], row[2], row[3])
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 确定最终光标位置
|
-- 判断是否纵向溢出
|
||||||
|
local verticalOverflow = (startY + totalHeight - 1) > termHeight
|
||||||
|
local horizontalOverflow = firstLineWidth >= termWidth
|
||||||
|
|
||||||
local finalX, finalY
|
local finalX, finalY
|
||||||
if not contentFitsHorizontally or not contentFitsVertically then
|
|
||||||
-- 若任一方向溢出,光标回到起始位置
|
if verticalOverflow then
|
||||||
|
-- 情况3:纵向溢出 → 回退到起点
|
||||||
finalX, finalY = startX, startY
|
finalX, finalY = startX, startY
|
||||||
|
elseif horizontalOverflow then
|
||||||
|
-- 情况2:宽但不高 → 光标移到块下方
|
||||||
|
finalX, finalY = startX, startY + totalHeight
|
||||||
else
|
else
|
||||||
-- 否则放在正常结束位置
|
-- 情况1:窄且不高 → 横向推进(仅第一行宽度)
|
||||||
finalX, finalY = cursorX, cursorY
|
finalX, finalY = startX + firstLineWidth, startY
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 安全设置光标(避免超出屏幕导致卡住)
|
finalX, finalY = clampCursorPos(finalX, finalY, termWidth, termHeight)
|
||||||
finalX, finalY = clampCursorPos(finalX, finalY, width, height)
|
|
||||||
term.setCursorPos(finalX, finalY)
|
term.setCursorPos(finalX, finalY)
|
||||||
|
|
||||||
return true, {
|
return true, {
|
||||||
textColor = textColor,
|
|
||||||
backgroundColor = backgroundColor,
|
|
||||||
startX = startX,
|
startX = startX,
|
||||||
startY = startY,
|
startY = startY,
|
||||||
endX = finalX,
|
endX = finalX,
|
||||||
endY = finalY,
|
endY = finalY,
|
||||||
charCount = charCount,
|
charCount = utf8.len(str), -- 假设有 utf8.len,或可估算
|
||||||
fontHeight = fontHeight,
|
fontHeight = fontManager.getFontHeight(),
|
||||||
overflowX = not contentFitsHorizontally,
|
overflowX = horizontalOverflow,
|
||||||
overflowY = not contentFitsVertically
|
overflowY = verticalOverflow
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function utf8display.print(raw_str)
|
function utf8display.blit(raw_str, textColorStr, backgroundColorStr)
|
||||||
str = tostring(raw_str)
|
local str = tostring(raw_str)
|
||||||
local font = fontManager.getFont()
|
str = string.gsub(str, "\n", " ")
|
||||||
local fontHeight = fontManager.getFontHeight()
|
|
||||||
local textColor = term.getTextColor()
|
local startX, startY = term.getCursorPos()
|
||||||
local backgroundColor = term.getBackgroundColor()
|
local termWidth, termHeight = term.getSize()
|
||||||
|
|
||||||
|
-- 直接传入颜色字符串
|
||||||
|
local bimg = utf8display.strToBimg(str, textColorStr, backgroundColorStr)
|
||||||
|
local frame = bimg[1]
|
||||||
|
|
||||||
|
if #frame == 0 then
|
||||||
|
return true, { charCount = 0, overflowX = false, overflowY = false }
|
||||||
|
end
|
||||||
|
|
||||||
|
local firstLineWidth = #frame[1][1]
|
||||||
|
local totalHeight = #frame
|
||||||
|
|
||||||
|
-- 渲染
|
||||||
|
for i, row in ipairs(frame) do
|
||||||
|
local drawY = startY + i - 1
|
||||||
|
if drawY > termHeight then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
term.setCursorPos(startX, drawY)
|
||||||
|
term.blit(row[1], row[2], row[3])
|
||||||
|
end
|
||||||
|
|
||||||
|
local verticalOverflow = (startY + totalHeight - 1) > termHeight
|
||||||
|
local horizontalOverflow = firstLineWidth >= termWidth
|
||||||
|
|
||||||
|
local finalX, finalY
|
||||||
|
|
||||||
|
if verticalOverflow then
|
||||||
|
finalX, finalY = startX, startY
|
||||||
|
elseif horizontalOverflow then
|
||||||
|
finalX, finalY = startX, startY + totalHeight
|
||||||
|
else
|
||||||
|
finalX, finalY = startX + firstLineWidth, startY
|
||||||
|
end
|
||||||
|
|
||||||
|
finalX, finalY = clampCursorPos(finalX, finalY, termWidth, termHeight)
|
||||||
|
term.setCursorPos(finalX, finalY)
|
||||||
|
|
||||||
|
return true, {
|
||||||
|
startX = startX,
|
||||||
|
startY = startY,
|
||||||
|
endX = finalX,
|
||||||
|
endY = finalY,
|
||||||
|
charCount = utf8.len(str),
|
||||||
|
fontHeight = fontManager.getFontHeight(),
|
||||||
|
overflowX = horizontalOverflow,
|
||||||
|
overflowY = verticalOverflow
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function utf8display.print(raw_str, textColor, backgroundColor)
|
||||||
|
local str = tostring(raw_str)
|
||||||
|
|
||||||
local startX, startY = term.getCursorPos()
|
local startX, startY = term.getCursorPos()
|
||||||
local width, height = term.getSize()
|
local width, height = term.getSize()
|
||||||
|
|
||||||
-- 预计算所需总高度(用于滚动)
|
-- 获取颜色
|
||||||
local tempCursorX, tempCursorY = startX, startY
|
local useTextColor = textColor
|
||||||
for code in renderer.utf8Decode(str) do
|
local useBackgroundColor = backgroundColor
|
||||||
if code == 10 then
|
if useTextColor == nil then useTextColor = term.getTextColor() end
|
||||||
tempCursorX = 1
|
if useBackgroundColor == nil then useBackgroundColor = term.getBackgroundColor() end
|
||||||
tempCursorY = tempCursorY + fontHeight
|
|
||||||
else
|
-- 生成 bimg(传入宽度以启用自动换行)
|
||||||
local charMap = font[code] or font[32]
|
local bimg = utf8display.strToBimg(str, useTextColor, useBackgroundColor, width)
|
||||||
local charWidth = #charMap[1]
|
local frame = bimg[1]
|
||||||
if tempCursorX + charWidth - 1 > width then
|
|
||||||
tempCursorX = 1
|
local totalLines = #frame
|
||||||
tempCursorY = tempCursorY + fontHeight
|
local availableLines = height - startY + 1
|
||||||
end
|
|
||||||
tempCursorX = tempCursorX + charWidth
|
|
||||||
end
|
-- 渲染
|
||||||
|
for i, rowData in ipairs(frame) do
|
||||||
|
local drawY = startY + i - 1
|
||||||
|
|
||||||
|
if drawY >= height then term.setCursorPos(1, height) else term.setCursorPos(1, drawY) end
|
||||||
|
term.blit(rowData[1], rowData[2], rowData[3])
|
||||||
|
if drawY >= height then term.scroll(1) end
|
||||||
end
|
end
|
||||||
|
|
||||||
local totalContentHeight = tempCursorY + fontHeight - startY
|
-- 光标移到下一行开头
|
||||||
local availableHeight = height - startY + 1
|
local finalY = startY + totalLines
|
||||||
local scrollHeight = math.max(0, totalContentHeight - availableHeight)
|
|
||||||
|
|
||||||
if scrollHeight > 0 and utf8display.config.autoScroll then
|
|
||||||
term.scroll(scrollHeight)
|
|
||||||
startY = startY - scrollHeight
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 实际渲染
|
|
||||||
local cursorX, cursorY = startX, startY
|
|
||||||
local charCount = 0
|
|
||||||
|
|
||||||
for code in renderer.utf8Decode(str) do
|
|
||||||
if code == 10 then
|
|
||||||
cursorX = 1
|
|
||||||
cursorY = cursorY + fontHeight
|
|
||||||
else
|
|
||||||
local charMap = font[code] or font[32]
|
|
||||||
local charWidth = #charMap[1]
|
|
||||||
if cursorX + charWidth - 1 > width then
|
|
||||||
cursorX = 1
|
|
||||||
cursorY = cursorY + fontHeight
|
|
||||||
end
|
|
||||||
if cursorY <= height then
|
|
||||||
renderer.displayChar(charMap, cursorX, cursorY, textColor, backgroundColor)
|
|
||||||
charCount = charCount + 1
|
|
||||||
end
|
|
||||||
cursorX = cursorX + charWidth
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- print 总是把光标放到下一行开头(符合常规行为)
|
|
||||||
local finalY = cursorY + fontHeight
|
|
||||||
local finalX = 1
|
local finalX = 1
|
||||||
finalX, finalY = clampCursorPos(finalX, finalY, width, height)
|
finalX, finalY = clampCursorPos(finalX, finalY, width, height)
|
||||||
term.setCursorPos(finalX, finalY)
|
term.setCursorPos(finalX, finalY)
|
||||||
|
|
||||||
return true, {
|
return true, {
|
||||||
textColor = textColor,
|
|
||||||
backgroundColor = backgroundColor,
|
|
||||||
startX = startX,
|
startX = startX,
|
||||||
startY = startY,
|
startY = startY,
|
||||||
endX = finalX,
|
endX = finalX,
|
||||||
endY = finalY,
|
endY = finalY,
|
||||||
charCount = charCount,
|
lineCount = totalLines
|
||||||
fontHeight = fontHeight
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
function utf8display.blit(raw_str, textColorStr, backgroundColorStr)
|
|
||||||
text = tostring(raw_str)
|
|
||||||
-- 将换行符替换为空格
|
|
||||||
text = string.gsub(text, "\n", " ")
|
|
||||||
|
|
||||||
local font = fontManager.getFont()
|
|
||||||
local fontHeight = fontManager.getFontHeight()
|
|
||||||
|
|
||||||
local startX, startY = term.getCursorPos()
|
|
||||||
local width, height = term.getSize()
|
|
||||||
local cursorX, cursorY = startX, startY
|
|
||||||
local charCount = 0
|
|
||||||
local contentFitsHorizontally = true
|
|
||||||
local contentFitsVertically = true
|
|
||||||
|
|
||||||
-- 解析颜色字符串
|
|
||||||
local textColors = {}
|
|
||||||
local backgroundColors = {}
|
|
||||||
for i = 1, #textColorStr do
|
|
||||||
textColors[i] = colors.fromBlit(string.sub(textColorStr, i, i))
|
|
||||||
end
|
|
||||||
for i = 1, #backgroundColorStr do
|
|
||||||
backgroundColors[i] = colors.fromBlit(string.sub(backgroundColorStr, i, i))
|
|
||||||
end
|
|
||||||
|
|
||||||
local index = 1
|
|
||||||
for code in renderer.utf8Decode(text) do
|
|
||||||
if code == 10 then -- 换行符 (理论上不会再有,因为我们已经替换了)
|
|
||||||
cursorX = 1
|
|
||||||
cursorY = cursorY + fontHeight
|
|
||||||
else
|
|
||||||
local charMap = font[code] or font[32]
|
|
||||||
local charWidth = #charMap[1]
|
|
||||||
|
|
||||||
if cursorX + charWidth - 1 > width then
|
|
||||||
contentFitsHorizontally = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if cursorY <= height then
|
|
||||||
local useTextColor = textColors[index] or term.getTextColor()
|
|
||||||
local useBackgroundColor = backgroundColors[index] or term.getBackgroundColor()
|
|
||||||
renderer.displayChar(charMap, cursorX, cursorY, useTextColor, useBackgroundColor)
|
|
||||||
charCount = charCount + 1
|
|
||||||
else
|
|
||||||
contentFitsVertically = false
|
|
||||||
end
|
|
||||||
|
|
||||||
cursorX = cursorX + charWidth
|
|
||||||
index = index + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local finalX, finalY
|
|
||||||
if not contentFitsHorizontally or not contentFitsVertically then
|
|
||||||
finalX, finalY = startX, startY
|
|
||||||
else
|
|
||||||
finalX, finalY = cursorX, cursorY
|
|
||||||
end
|
|
||||||
|
|
||||||
finalX, finalY = clampCursorPos(finalX, finalY, width, height)
|
|
||||||
term.setCursorPos(finalX, finalY)
|
|
||||||
|
|
||||||
return true, {
|
|
||||||
startX = startX,
|
|
||||||
startY = startY,
|
|
||||||
endX = finalX,
|
|
||||||
endY = finalY,
|
|
||||||
charCount = charCount,
|
|
||||||
fontHeight = fontHeight,
|
|
||||||
overflowX = not contentFitsHorizontally,
|
|
||||||
overflowY = not contentFitsVertically
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 工具函数
|
|
||||||
function utf8display.getFontInfo()
|
|
||||||
local font = fontManager.getFont()
|
|
||||||
local fontHeight = fontManager.getFontHeight()
|
|
||||||
|
|
||||||
return {
|
|
||||||
height = fontHeight,
|
|
||||||
loaded = font ~= nil,
|
|
||||||
source = utf8display.config.fontPath or utf8display.config.fontUrl,
|
|
||||||
cached = state.loadedFonts[utf8display.config.fontPath or utf8display.config.fontUrl] ~= nil
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function utf8display.isInitialized()
|
|
||||||
return state.font ~= nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 自动初始化(第一次使用时)
|
-- 自动初始化(第一次使用时)
|
||||||
setmetatable(utf8display, {
|
setmetatable(utf8display, {
|
||||||
__index = function(self, key)
|
__index = function(self, key)
|
||||||
|
|||||||
Reference in New Issue
Block a user